1 diff -ruN linux-2.6.30.10/arch/ubicom32/crypto/aes_ubicom32.c linux-2.6.30.10-ubi/arch/ubicom32/crypto/aes_ubicom32.c
2 --- linux-2.6.30.10/arch/ubicom32/crypto/aes_ubicom32.c 1970-01-01 02:00:00.000000000 +0200
3 +++ linux-2.6.30.10-ubi/arch/ubicom32/crypto/aes_ubicom32.c 2009-12-11 11:45:11.000000000 +0200
6 + * arch/ubicom32/crypto/aes_ubicom32.c
7 + * Ubicom32 implementation of the AES Cipher Algorithm.
9 + * (C) Copyright 2009, Ubicom, Inc.
11 + * This file is part of the Ubicom32 Linux Kernel Port.
13 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
14 + * it and/or modify it under the terms of the GNU General Public License
15 + * as published by the Free Software Foundation, either version 2 of the
16 + * License, or (at your option) any later version.
18 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
19 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
20 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
21 + * the GNU General Public License for more details.
23 + * You should have received a copy of the GNU General Public License
24 + * along with the Ubicom32 Linux Kernel Port. If not,
25 + * see <http://www.gnu.org/licenses/>.
27 + * Ubicom32 implementation derived from (with many thanks):
32 +#include <crypto/aes.h>
33 +#include <crypto/algapi.h>
34 +#include <linux/err.h>
35 +#include <linux/module.h>
36 +#include <linux/init.h>
37 +#include <linux/spinlock.h>
38 +#include "crypto_ubicom32.h"
39 +#include <asm/linkage.h>
41 +struct ubicom32_aes_ctx {
42 + u8 key[AES_MAX_KEY_SIZE];
47 +static inline void aes_hw_set_key(const u8 *key, u8 key_len)
50 + * switch case has more overhead than 4 move.4 instructions, so just copy 256 bits
52 + SEC_SET_KEY_256(key);
55 +static inline void aes_hw_set_iv(const u8 *iv)
60 +static inline void aes_hw_cipher(u8 *out, const u8 *in)
62 + SEC_SET_INPUT_4W(in);
65 + " ; start AES by writing 0x40(SECURITY_BASE) \n\t"
66 + " move.4 0x40(%0), #0x01 \n\t"
67 + " pipe_flush 0 \n\t"
69 + " ; wait for the module to calculate the output \n\t"
70 + " btst 0x04(%0), #0 \n\t"
77 + SEC_GET_OUTPUT_4W(out);
80 +static int __ocm_text aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
81 + unsigned int key_len)
83 + struct ubicom32_aes_ctx *uctx = crypto_tfm_ctx(tfm);
85 + uctx->key_len = key_len;
86 + memcpy(uctx->key, in_key, key_len);
89 + * leave out HASH_ALG (none = 0), CBC (no = 0), DIR (unknown) yet
91 + switch (uctx->key_len) {
93 + uctx->ctrl = SEC_KEY_128_BITS | SEC_ALG_AES;
96 + uctx->ctrl = SEC_KEY_192_BITS | SEC_ALG_AES;
99 + uctx->ctrl = SEC_KEY_256_BITS | SEC_ALG_AES;
106 +static inline void aes_cipher(struct crypto_tfm *tfm, u8 *out, const u8 *in, u32 extra_flags)
108 + const struct ubicom32_aes_ctx *uctx = crypto_tfm_ctx(tfm);
112 + hw_crypto_set_ctrl(uctx->ctrl | extra_flags);
114 + aes_hw_set_key(uctx->key, uctx->key_len);
115 + aes_hw_cipher(out, in);
117 + hw_crypto_unlock();
120 +static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
122 + aes_cipher(tfm, out, in, SEC_DIR_ENCRYPT);
125 +static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
127 + aes_cipher(tfm, out, in, SEC_DIR_DECRYPT);
130 +static struct crypto_alg aes_alg = {
132 + .cra_driver_name = "aes-ubicom32",
133 + .cra_priority = CRYPTO_UBICOM32_PRIORITY,
134 + .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
135 + .cra_blocksize = AES_BLOCK_SIZE,
136 + .cra_ctxsize = sizeof(struct ubicom32_aes_ctx),
137 + .cra_alignmask = CRYPTO_UBICOM32_ALIGNMENT - 1,
138 + .cra_module = THIS_MODULE,
139 + .cra_list = LIST_HEAD_INIT(aes_alg.cra_list),
142 + .cia_min_keysize = AES_MIN_KEY_SIZE,
143 + .cia_max_keysize = AES_MAX_KEY_SIZE,
144 + .cia_setkey = aes_set_key,
145 + .cia_encrypt = aes_encrypt,
146 + .cia_decrypt = aes_decrypt,
151 +static void __ocm_text ecb_aes_crypt_loop(u8 *out, u8 *in, unsigned int n)
153 + while (likely(n)) {
154 + aes_hw_cipher(out, in);
155 + out += AES_BLOCK_SIZE;
156 + in += AES_BLOCK_SIZE;
157 + n -= AES_BLOCK_SIZE;
161 +static int __ocm_text ecb_aes_crypt(struct blkcipher_desc *desc, struct scatterlist *dst,
162 + struct scatterlist *src, unsigned int nbytes, u32 extra_flags)
164 + const struct ubicom32_aes_ctx *uctx = crypto_blkcipher_ctx(desc->tfm);
167 + struct blkcipher_walk walk;
168 + blkcipher_walk_init(&walk, dst, src, nbytes);
169 + ret = blkcipher_walk_virt(desc, &walk);
177 + hw_crypto_set_ctrl(uctx->ctrl | extra_flags);
178 + aes_hw_set_key(uctx->key, uctx->key_len);
180 + while (likely((nbytes = walk.nbytes))) {
181 + /* only use complete blocks */
182 + unsigned int n = nbytes & ~(AES_BLOCK_SIZE - 1);
183 + u8 *out = walk.dst.virt.addr;
184 + u8 *in = walk.src.virt.addr;
186 + /* finish n/16 blocks */
187 + ecb_aes_crypt_loop(out, in, n);
189 + nbytes &= AES_BLOCK_SIZE - 1;
190 + ret = blkcipher_walk_done(desc, &walk, nbytes);
193 + hw_crypto_unlock();
197 +static int ecb_aes_encrypt(struct blkcipher_desc *desc,
198 + struct scatterlist *dst, struct scatterlist *src,
199 + unsigned int nbytes)
201 + return ecb_aes_crypt(desc, dst, src, nbytes, SEC_DIR_ENCRYPT);
204 +static int ecb_aes_decrypt(struct blkcipher_desc *desc,
205 + struct scatterlist *dst, struct scatterlist *src,
206 + unsigned int nbytes)
208 + return ecb_aes_crypt(desc, dst, src, nbytes, SEC_DIR_DECRYPT);
211 +static struct crypto_alg ecb_aes_alg = {
212 + .cra_name = "ecb(aes)",
213 + .cra_driver_name = "ecb-aes-ubicom32",
214 + .cra_priority = CRYPTO_UBICOM32_COMPOSITE_PRIORITY,
215 + .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
216 + .cra_blocksize = AES_BLOCK_SIZE,
217 + .cra_ctxsize = sizeof(struct ubicom32_aes_ctx),
218 + .cra_alignmask = CRYPTO_UBICOM32_ALIGNMENT - 1,
219 + .cra_type = &crypto_blkcipher_type,
220 + .cra_module = THIS_MODULE,
221 + .cra_list = LIST_HEAD_INIT(ecb_aes_alg.cra_list),
224 + .min_keysize = AES_MIN_KEY_SIZE,
225 + .max_keysize = AES_MAX_KEY_SIZE,
226 + .setkey = aes_set_key,
227 + .encrypt = ecb_aes_encrypt,
228 + .decrypt = ecb_aes_decrypt,
233 +#if CRYPTO_UBICOM32_LOOP_ASM
234 +void __ocm_text cbc_aes_encrypt_loop(u8 *out, u8 *in, u8 *iv, unsigned int n)
237 + "; set init. iv 4w \n\t"
238 + " move.4 0x50(%0), 0x0(%3) \n\t"
239 + " move.4 0x54(%0), 0x4(%3) \n\t"
240 + " move.4 0x58(%0), 0x8(%3) \n\t"
241 + " move.4 0x5c(%0), 0xc(%3) \n\t"
243 + "; we know n > 0, so we can always \n\t"
244 + "; load the first block \n\t"
245 + "; set input 4w \n\t"
246 + " move.4 0x30(%0), 0x0(%2) \n\t"
247 + " move.4 0x34(%0), 0x4(%2) \n\t"
248 + " move.4 0x38(%0), 0x8(%2) \n\t"
249 + " move.4 0x3c(%0), 0xc(%2) \n\t"
251 + "; kickoff hw \n\t"
252 + " move.4 0x40(%0), %2 \n\t"
254 + "; update n & flush \n\t"
255 + " add.4 %4, #-16, %4 \n\t"
256 + " pipe_flush 0 \n\t"
258 + "; while (n): work on 2nd block \n\t"
259 + " 1: lsl.4 d15, %4, #0x0 \n\t"
262 + "; set input 4w (2nd) \n\t"
263 + " move.4 0x30(%0), 0x10(%2) \n\t"
264 + " move.4 0x34(%0), 0x14(%2) \n\t"
265 + " move.4 0x38(%0), 0x18(%2) \n\t"
266 + " move.4 0x3c(%0), 0x1c(%2) \n\t"
268 + "; update n/in asap while waiting \n\t"
269 + " add.4 %4, #-16, %4 \n\t"
270 + " move.4 d15, 16(%2)++ \n\t"
272 + "; wait for the previous output \n\t"
273 + " btst 0x04(%0), #0 \n\t"
276 + "; read previous output \n\t"
277 + " move.4 0x0(%1), 0x50(%0) \n\t"
278 + " move.4 0x4(%1), 0x54(%0) \n\t"
279 + " move.4 0x8(%1), 0x58(%0) \n\t"
280 + " move.4 0xc(%1), 0x5c(%0) \n\t"
282 + "; kick off hw for 2nd input \n\t"
283 + " move.4 0x40(%0), %2 \n\t"
285 + "; update out asap \n\t"
286 + " move.4 d15, 16(%1)++ \n\t"
288 + "; go back to loop \n\t"
291 + "; wait for last output \n\t"
292 + " 5: btst 0x04(%0), #0 \n\t"
295 + "; read last output \n\t"
296 + " move.4 0x0(%1), 0x50(%0) \n\t"
297 + " move.4 0x4(%1), 0x54(%0) \n\t"
298 + " move.4 0x8(%1), 0x58(%0) \n\t"
299 + " move.4 0xc(%1), 0x5c(%0) \n\t"
301 + "; copy out iv \n\t"
302 + " move.4 0x0(%3), 0x50(%0) \n\t"
303 + " move.4 0x4(%3), 0x54(%0) \n\t"
304 + " move.4 0x8(%3), 0x58(%0) \n\t"
305 + " move.4 0xc(%3), 0x5c(%0) \n\t"
308 + : "a" (SEC_BASE), "a" (out), "a" (in), "a" (iv), "d" (n)
315 +static void __ocm_text cbc_aes_encrypt_loop(u8 *out, u8 *in, u8 *iv, unsigned int n)
318 + while (likely(n)) {
319 + aes_hw_cipher(out, in);
320 + out += AES_BLOCK_SIZE;
321 + in += AES_BLOCK_SIZE;
322 + n -= AES_BLOCK_SIZE;
324 + SEC_COPY_4W(iv, out - AES_BLOCK_SIZE);
329 +static void __ocm_text cbc_aes_decrypt_loop(u8 *out, u8 *in, u8 *iv, unsigned int n)
331 + while (likely(n)) {
333 + SEC_COPY_4W(iv, in);
334 + aes_hw_cipher(out, in);
335 + out += AES_BLOCK_SIZE;
336 + in += AES_BLOCK_SIZE;
337 + n -= AES_BLOCK_SIZE;
341 +static int __ocm_text cbc_aes_crypt(struct blkcipher_desc *desc,
342 + struct scatterlist *dst, struct scatterlist *src,
343 + unsigned int nbytes, u32 extra_flags)
345 + struct ubicom32_aes_ctx *uctx = crypto_blkcipher_ctx(desc->tfm);
348 + struct blkcipher_walk walk;
349 + blkcipher_walk_init(&walk, dst, src, nbytes);
350 + ret = blkcipher_walk_virt(desc, &walk);
351 + if (unlikely(ret)) {
358 + hw_crypto_set_ctrl(uctx->ctrl | extra_flags);
359 + aes_hw_set_key(uctx->key, uctx->key_len);
361 + while (likely((nbytes = walk.nbytes))) {
362 + /* only use complete blocks */
363 + unsigned int n = nbytes & ~(AES_BLOCK_SIZE - 1);
365 + u8 *out = walk.dst.virt.addr;
366 + u8 *in = walk.src.virt.addr;
368 + if (extra_flags & SEC_DIR_ENCRYPT) {
369 + cbc_aes_encrypt_loop(out, in, walk.iv, n);
371 + cbc_aes_decrypt_loop(out, in, walk.iv, n);
375 + nbytes &= AES_BLOCK_SIZE - 1;
376 + ret = blkcipher_walk_done(desc, &walk, nbytes);
378 + hw_crypto_unlock();
383 +static int __ocm_text cbc_aes_encrypt(struct blkcipher_desc *desc,
384 + struct scatterlist *dst, struct scatterlist *src,
385 + unsigned int nbytes)
387 + return cbc_aes_crypt(desc, dst, src, nbytes, SEC_DIR_ENCRYPT | SEC_CBC_SET);
390 +static int __ocm_text cbc_aes_decrypt(struct blkcipher_desc *desc,
391 + struct scatterlist *dst, struct scatterlist *src,
392 + unsigned int nbytes)
394 + return cbc_aes_crypt(desc, dst, src, nbytes, SEC_DIR_DECRYPT | SEC_CBC_SET);
397 +static struct crypto_alg cbc_aes_alg = {
398 + .cra_name = "cbc(aes)",
399 + .cra_driver_name = "cbc-aes-ubicom32",
400 + .cra_priority = CRYPTO_UBICOM32_COMPOSITE_PRIORITY,
401 + .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
402 + .cra_blocksize = AES_BLOCK_SIZE,
403 + .cra_ctxsize = sizeof(struct ubicom32_aes_ctx),
404 + .cra_alignmask = CRYPTO_UBICOM32_ALIGNMENT - 1,
405 + .cra_type = &crypto_blkcipher_type,
406 + .cra_module = THIS_MODULE,
407 + .cra_list = LIST_HEAD_INIT(cbc_aes_alg.cra_list),
410 + .min_keysize = AES_MIN_KEY_SIZE,
411 + .max_keysize = AES_MAX_KEY_SIZE,
412 + .ivsize = AES_BLOCK_SIZE,
413 + .setkey = aes_set_key,
414 + .encrypt = cbc_aes_encrypt,
415 + .decrypt = cbc_aes_decrypt,
420 +static int __init aes_init(void)
426 + ret = crypto_register_alg(&aes_alg);
430 + ret = crypto_register_alg(&ecb_aes_alg);
434 + ret = crypto_register_alg(&cbc_aes_alg);
442 + crypto_unregister_alg(&ecb_aes_alg);
444 + crypto_unregister_alg(&aes_alg);
449 +static void __exit aes_fini(void)
451 + crypto_unregister_alg(&cbc_aes_alg);
452 + crypto_unregister_alg(&ecb_aes_alg);
453 + crypto_unregister_alg(&aes_alg);
456 +module_init(aes_init);
457 +module_exit(aes_fini);
459 +MODULE_ALIAS("aes");
461 +MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm");
462 +MODULE_LICENSE("GPL");
463 diff -ruN linux-2.6.30.10/arch/ubicom32/crypto/crypto_des.h linux-2.6.30.10-ubi/arch/ubicom32/crypto/crypto_des.h
464 --- linux-2.6.30.10/arch/ubicom32/crypto/crypto_des.h 1970-01-01 02:00:00.000000000 +0200
465 +++ linux-2.6.30.10-ubi/arch/ubicom32/crypto/crypto_des.h 2009-12-11 11:45:11.000000000 +0200
468 + * arch/ubicom32/crypto/crypto_des.h
469 + * Function for checking keys for the DES and Triple DES Encryption
472 + * (C) Copyright 2009, Ubicom, Inc.
474 + * This file is part of the Ubicom32 Linux Kernel Port.
476 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
477 + * it and/or modify it under the terms of the GNU General Public License
478 + * as published by the Free Software Foundation, either version 2 of the
479 + * License, or (at your option) any later version.
481 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
482 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
483 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
484 + * the GNU General Public License for more details.
486 + * You should have received a copy of the GNU General Public License
487 + * along with the Ubicom32 Linux Kernel Port. If not,
488 + * see <http://www.gnu.org/licenses/>.
490 + * Ubicom32 implementation derived from (with many thanks):
495 +#ifndef __CRYPTO_DES_H__
496 +#define __CRYPTO_DES_H__
498 +extern int crypto_des_check_key(const u8*, unsigned int, u32*);
500 +#endif /* __CRYPTO_DES_H__ */
501 diff -ruN linux-2.6.30.10/arch/ubicom32/crypto/crypto_ubicom32.c linux-2.6.30.10-ubi/arch/ubicom32/crypto/crypto_ubicom32.c
502 --- linux-2.6.30.10/arch/ubicom32/crypto/crypto_ubicom32.c 1970-01-01 02:00:00.000000000 +0200
503 +++ linux-2.6.30.10-ubi/arch/ubicom32/crypto/crypto_ubicom32.c 2009-12-11 11:45:11.000000000 +0200
506 + * arch/ubicom32/crypto/crypto_ubicom32.c
507 + * Generic code to support ubicom32 hardware crypto accelerator
509 + * (C) Copyright 2009, Ubicom, Inc.
511 + * This file is part of the Ubicom32 Linux Kernel Port.
513 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
514 + * it and/or modify it under the terms of the GNU General Public License
515 + * as published by the Free Software Foundation, either version 2 of the
516 + * License, or (at your option) any later version.
518 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
519 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
520 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
521 + * the GNU General Public License for more details.
523 + * You should have received a copy of the GNU General Public License
524 + * along with the Ubicom32 Linux Kernel Port. If not,
525 + * see <http://www.gnu.org/licenses/>.
527 + * Ubicom32 implementation derived from (with many thanks):
532 +#include "crypto_ubicom32.h"
534 +spinlock_t crypto_ubicom32_lock;
535 +bool crypto_ubicom32_inited = false;
536 +volatile bool crypto_ubicom32_on = false;
537 +volatile unsigned long crypto_ubicom32_last_use;
539 +struct timer_list crypto_ubicom32_ps_timer;
540 +void crypto_ubicom32_ps_check(unsigned long data)
542 + unsigned long idle_time = msecs_to_jiffies(HW_CRYPTO_PS_MAX_IDLE_MS);
544 + BUG_ON(!crypto_ubicom32_on);
546 + if (((jiffies - crypto_ubicom32_last_use) > idle_time) && spin_trylock_bh(&crypto_ubicom32_lock)) {
547 + hw_crypto_turn_off();
548 + spin_unlock_bh(&crypto_ubicom32_lock);
552 + /* keep monitoring */
553 + hw_crypto_ps_start();
555 diff -ruN linux-2.6.30.10/arch/ubicom32/crypto/crypto_ubicom32.h linux-2.6.30.10-ubi/arch/ubicom32/crypto/crypto_ubicom32.h
556 --- linux-2.6.30.10/arch/ubicom32/crypto/crypto_ubicom32.h 1970-01-01 02:00:00.000000000 +0200
557 +++ linux-2.6.30.10-ubi/arch/ubicom32/crypto/crypto_ubicom32.h 2009-12-11 11:45:11.000000000 +0200
560 + * arch/ubicom32/crypto/crypto_ubicom32.h
561 + * Support for Ubicom32 cryptographic instructions.
563 + * (C) Copyright 2009, Ubicom, Inc.
565 + * This file is part of the Ubicom32 Linux Kernel Port.
567 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
568 + * it and/or modify it under the terms of the GNU General Public License
569 + * as published by the Free Software Foundation, either version 2 of the
570 + * License, or (at your option) any later version.
572 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
573 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
574 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
575 + * the GNU General Public License for more details.
577 + * You should have received a copy of the GNU General Public License
578 + * along with the Ubicom32 Linux Kernel Port. If not,
579 + * see <http://www.gnu.org/licenses/>.
581 + * Ubicom32 implementation derived from (with many thanks):
586 +#ifndef _CRYPTO_ARCH_UBICOM32_CRYPT_H
587 +#define _CRYPTO_ARCH_UBICOM32_CRYPT_H
589 +#include <linux/module.h>
590 +#include <linux/kernel.h>
591 +#include <linux/jiffies.h>
592 +#include <linux/timer.h>
593 +#include <linux/spinlock.h>
594 +#include <asm/errno.h>
596 +#include <asm/ip5000.h>
598 +#define CRYPTO_UBICOM32_LOOP_ASM 1
599 +#define CRYPTO_UBICOM32_ALIGNMENT 4
600 +#define SEC_ALIGNED(p) (((u32)p & 3) == 0)
602 +#define SEC_BASE SECURITY_BASE
603 +#define SEC_KEY_OFFSET SECURITY_KEY_VALUE(0)
604 +#define SEC_INPUT_OFFSET SECURITY_KEY_IN(0)
605 +#define SEC_OUTPUT_OFFSET SECURITY_KEY_OUT(0)
606 +#define SEC_HASH_OFFSET SECURITY_KEY_HASH(0)
608 +#define SEC_KEY_128_BITS SECURITY_CTRL_KEY_SIZE(0)
609 +#define SEC_KEY_192_BITS SECURITY_CTRL_KEY_SIZE(1)
610 +#define SEC_KEY_256_BITS SECURITY_CTRL_KEY_SIZE(2)
612 +#define SEC_HASH_NONE SECURITY_CTRL_HASH_ALG_NONE
613 +#define SEC_HASH_MD5 SECURITY_CTRL_HASH_ALG_MD5
614 +#define SEC_HASH_SHA1 SECURITY_CTRL_HASH_ALG_SHA1
616 +#define SEC_CBC_SET SECURITY_CTRL_CBC
617 +#define SEC_CBC_NONE 0
619 +#define SEC_ALG_AES SECURITY_CTRL_CIPHER_ALG_AES
620 +#define SEC_ALG_NONE SECURITY_CTRL_CIPHER_ALG_NONE
621 +#define SEC_ALG_DES SECURITY_CTRL_CIPHER_ALG_DES
622 +#define SEC_ALG_3DES SECURITY_CTRL_CIPHER_ALG_3DES
624 +#define SEC_DIR_ENCRYPT SECURITY_CTRL_ENCIPHER
625 +#define SEC_DIR_DECRYPT 0
627 +#define CRYPTO_UBICOM32_PRIORITY 300
628 +#define CRYPTO_UBICOM32_COMPOSITE_PRIORITY 400
630 +#define HW_CRYPTO_PS_MAX_IDLE_MS 100 /* idle time (ms) before shuting down sm */
632 +extern spinlock_t crypto_ubicom32_lock;
633 +extern bool crypto_ubicom32_inited;
634 +extern volatile bool crypto_ubicom32_on;
635 +extern volatile unsigned long crypto_ubicom32_last_use;
636 +extern struct timer_list crypto_ubicom32_ps_timer;
637 +extern void crypto_ubicom32_ps_check(unsigned long data);
639 +#define SEC_COPY_2W(t, s) \
641 + " move.4 0(%0), 0(%1) \n\t" \
642 + " move.4 4(%0), 4(%1) \n\t" \
645 + : "a" (t), "a" (s) \
648 +#define SEC_COPY_4W(t, s) \
650 + " move.4 0(%0), 0(%1) \n\t" \
651 + " move.4 4(%0), 4(%1) \n\t" \
652 + " move.4 8(%0), 8(%1) \n\t" \
653 + " move.4 12(%0), 12(%1) \n\t" \
655 + : "a" (t), "a" (s) \
658 +#define SEC_COPY_5W(t, s) \
660 + " move.4 0(%0), 0(%1) \n\t" \
661 + " move.4 4(%0), 4(%1) \n\t" \
662 + " move.4 8(%0), 8(%1) \n\t" \
663 + " move.4 12(%0), 12(%1) \n\t" \
664 + " move.4 16(%0), 16(%1) \n\t" \
666 + : "a" (t), "a" (s) \
669 +#define SEC_SET_KEY_2W(x) \
671 + " ; write key to Security Keyblock \n\t" \
672 + " move.4 0x10(%0), 0(%1) \n\t" \
673 + " move.4 0x14(%0), 4(%1) \n\t" \
675 + : "a" (SECURITY_BASE), "a" (x) \
678 +#define SEC_SET_KEY_4W(x) \
680 + " ; write key to Security Keyblock \n\t" \
681 + " move.4 0x10(%0), 0(%1) \n\t" \
682 + " move.4 0x14(%0), 4(%1) \n\t" \
683 + " move.4 0x18(%0), 8(%1) \n\t" \
684 + " move.4 0x1c(%0), 12(%1) \n\t" \
686 + : "a"(SECURITY_BASE), "a"(x) \
689 +#define SEC_SET_KEY_6W(x) \
691 + " ; write key to Security Keyblock \n\t" \
692 + " move.4 0x10(%0), 0(%1) \n\t" \
693 + " move.4 0x14(%0), 4(%1) \n\t" \
694 + " move.4 0x18(%0), 8(%1) \n\t" \
695 + " move.4 0x1c(%0), 12(%1) \n\t" \
696 + " move.4 0x20(%0), 16(%1) \n\t" \
697 + " move.4 0x24(%0), 20(%1) \n\t" \
699 + : "a" (SECURITY_BASE), "a" (x) \
702 +#define SEC_SET_KEY_8W(x) \
704 + " ; write key to Security Keyblock \n\t" \
705 + " move.4 0x10(%0), 0(%1) \n\t" \
706 + " move.4 0x14(%0), 4(%1) \n\t" \
707 + " move.4 0x18(%0), 8(%1) \n\t" \
708 + " move.4 0x1c(%0), 12(%1) \n\t" \
709 + " move.4 0x20(%0), 16(%1) \n\t" \
710 + " move.4 0x24(%0), 20(%1) \n\t" \
711 + " move.4 0x28(%0), 24(%1) \n\t" \
712 + " move.4 0x2c(%0), 28(%1) \n\t" \
714 + : "a" (SECURITY_BASE), "a" (x) \
717 +#define SEC_SET_KEY_64(k) SEC_SET_KEY_2W(k)
718 +#define SEC_SET_KEY_128(k) SEC_SET_KEY_4W(k)
719 +#define SEC_SET_KEY_192(k) SEC_SET_KEY_6W(k)
720 +#define SEC_SET_KEY_256(k) SEC_SET_KEY_8W(k)
722 +#define DES_SET_KEY(x) SEC_SET_KEY_64(x)
723 +#define DES3_SET_KEY(x) SEC_SET_KEY_192(x)
725 +#define SEC_SET_INPUT_2W(x) \
727 + " ; write key to Security Keyblock \n\t" \
728 + " move.4 0x30(%0), 0(%1) \n\t" \
729 + " move.4 0x34(%0), 4(%1) \n\t" \
731 + : "a" (SECURITY_BASE), "a" (x) \
734 +#define SEC_GET_OUTPUT_2W(x) \
736 + " ; write key to Security Keyblock \n\t" \
737 + " move.4 0(%1), 0x50(%0) \n\t" \
738 + " move.4 4(%1), 0x54(%0) \n\t" \
740 + : "a" (SECURITY_BASE), "a" (x) \
743 +#define SEC_SET_INPUT_4W(x) \
745 + " ; write key to Security Keyblock \n\t" \
746 + " move.4 0x30(%0), 0(%1) \n\t" \
747 + " move.4 0x34(%0), 4(%1) \n\t" \
748 + " move.4 0x38(%0), 8(%1) \n\t" \
749 + " move.4 0x3c(%0), 12(%1) \n\t" \
751 + : "a" (SECURITY_BASE), "a" (x) \
754 +#define SEC_GET_OUTPUT_4W(x) \
756 + " ; read output from Security Keyblock \n\t" \
757 + " move.4 0(%1), 0x50(%0) \n\t" \
758 + " move.4 4(%1), 0x54(%0) \n\t" \
759 + " move.4 8(%1), 0x58(%0) \n\t" \
760 + " move.4 12(%1), 0x5c(%0) \n\t" \
762 + : "a" (SECURITY_BASE), "a" (x) \
765 +#define SEC_SET_IV_4W(x) \
767 + " ; write IV to Security Keyblock \n\t" \
768 + " move.4 0x50(%0), 0(%1) \n\t" \
769 + " move.4 0x54(%0), 4(%1) \n\t" \
770 + " move.4 0x58(%0), 8(%1) \n\t" \
771 + " move.4 0x5c(%0), 12(%1) \n\t" \
773 + : "a" (SECURITY_BASE), "a" (x) \
776 +#define SEC_PIPE_FLUSH() asm volatile ( " pipe_flush 0 \n\t" )
778 +static inline void hw_crypto_set_ctrl(uint32_t c)
781 + " move.4 0(%0), %1 \n\t"
783 + : "a" (SECURITY_BASE + SECURITY_CTRL), "d" (c)
787 +static inline void hw_crypto_ps_start(void)
789 + crypto_ubicom32_ps_timer.expires = jiffies + msecs_to_jiffies(HW_CRYPTO_PS_MAX_IDLE_MS >> 1);
790 + add_timer(&crypto_ubicom32_ps_timer);
793 +static inline void hw_crypto_turn_on(void)
796 + " moveai A4, %0 \n\t"
797 + " bset 0x0(A4), 0x0(A4), %1 \n\t"
800 + : "i" (OCP_BASE >> 7), "i" (GEN_CLK_PLL_SECURITY_BIT_NO)
803 + crypto_ubicom32_on = true;
806 +static inline void hw_crypto_turn_off(void)
809 + " moveai A4, %0 \n\t"
810 + " bclr 0x0(A4), 0x0(A4), %1 \n\t"
812 + : "i" (OCP_BASE >> 7), "i" (GEN_CLK_PLL_SECURITY_BIT_NO)
815 + crypto_ubicom32_on = false;
820 + * Most probably hw crypto is called in clusters and it makes no sense to turn it off
821 + * and on and waster 13 cycles every time.
823 +static inline void hw_crypto_check(void)
825 + if (likely(crypto_ubicom32_on)) {
828 + crypto_ubicom32_last_use = jiffies;
829 + hw_crypto_turn_on();
830 + hw_crypto_ps_start();
834 + * hw_crypto_ps_init
835 + * Init power save timer
837 +static inline void hw_crypto_ps_init(void)
839 + init_timer_deferrable(&crypto_ubicom32_ps_timer);
840 + crypto_ubicom32_ps_timer.function = crypto_ubicom32_ps_check;
841 + crypto_ubicom32_ps_timer.data = 0;
846 + * Initialize OCP security module lock and disables its clock.
848 +static inline void hw_crypto_init(void)
850 + if (!crypto_ubicom32_inited) {
851 + crypto_ubicom32_inited = true;
852 + spin_lock_init(&crypto_ubicom32_lock);
853 + hw_crypto_ps_init();
854 + hw_crypto_turn_off();
860 + * Locks the OCP security module and enables its clock.
862 +static inline void hw_crypto_lock(void)
864 + spin_lock_bh(&crypto_ubicom32_lock);
868 + * hw_crypto_unlock()
869 + * Unlocks the OCP security module and disables its clock.
871 +static inline void hw_crypto_unlock(void)
873 + crypto_ubicom32_last_use = jiffies;
874 + spin_unlock_bh(&crypto_ubicom32_lock);
877 +#define CONFIG_CRYPTO_UBICOM32_DEBUG 1
879 +#ifdef CONFIG_CRYPTO_UBICOM32_DEBUG
880 +static inline void hex_dump(void *buf, int b_size, const char *msg)
885 + printk("%s:\t", msg);
888 + for (i=0; i < b_size; i++) {
889 + printk("%02x ", b[i]);
890 + if ((i & 3) == 3) {
893 + if ((i & 31) == 31) {
899 +#define UBICOM32_SEC_DUMP(a, b, c) hex_dump(a, b, c)
901 +#define UBICOM32_SEC_DUMP(a, b, c)
904 +#endif /* _CRYPTO_ARCH_UBICOM32_CRYPT_H */
905 diff -ruN linux-2.6.30.10/arch/ubicom32/crypto/des_check_key.c linux-2.6.30.10-ubi/arch/ubicom32/crypto/des_check_key.c
906 --- linux-2.6.30.10/arch/ubicom32/crypto/des_check_key.c 1970-01-01 02:00:00.000000000 +0200
907 +++ linux-2.6.30.10-ubi/arch/ubicom32/crypto/des_check_key.c 2009-12-11 11:45:11.000000000 +0200
910 + * arch/ubicom32/crypto/des_check_key.c
911 + * Ubicom32 architecture function for checking keys for the DES and
912 + * Tripple DES Encryption algorithms.
914 + * (C) Copyright 2009, Ubicom, Inc.
916 + * Originally released as descore by Dana L. How <how@isl.stanford.edu>.
917 + * Modified by Raimar Falke <rf13@inf.tu-dresden.de> for the Linux-Kernel.
918 + * Derived from Cryptoapi and Nettle implementations, adapted for in-place
919 + * scatterlist interface. Changed LGPL to GPL per section 3 of the LGPL.
922 + * Copyright IBM Corp. 2003
923 + * Author(s): Thomas Spatzier
924 + * Jan Glauber (jan.glauber@de.ibm.com)
926 + * Derived from "crypto/des.c"
927 + * Copyright (c) 1992 Dana L. How.
928 + * Copyright (c) Raimar Falke <rf13@inf.tu-dresden.de>
929 + * Copyright (c) Gisle Sflensminde <gisle@ii.uib.no>
930 + * Copyright (C) 2001 Niels Mvller.
931 + * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
933 + * This file is part of the Ubicom32 Linux Kernel Port.
935 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
936 + * it and/or modify it under the terms of the GNU General Public License
937 + * as published by the Free Software Foundation, either version 2 of the
938 + * License, or (at your option) any later version.
940 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
941 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
942 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
943 + * the GNU General Public License for more details.
945 + * You should have received a copy of the GNU General Public License
946 + * along with the Ubicom32 Linux Kernel Port. If not,
947 + * see <http://www.gnu.org/licenses/>.
949 + * Ubicom32 implementation derived from (with many thanks):
954 +#include <linux/init.h>
955 +#include <linux/module.h>
956 +#include <linux/errno.h>
957 +#include <linux/crypto.h>
958 +#include "crypto_des.h"
960 +#define ROR(d,c,o) ((d) = (d) >> (c) | (d) << (o))
962 +static const u8 parity[] = {
963 + 8,1,0,8,0,8,8,0,0,8,8,0,8,0,2,8,0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,3,
964 + 0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,
965 + 0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,
966 + 8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,
967 + 0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,
968 + 8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,
969 + 8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,
970 + 4,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,8,5,0,8,0,8,8,0,0,8,8,0,8,0,6,8,
974 + * RFC2451: Weak key checks SHOULD be performed.
977 +crypto_des_check_key(const u8 *key, unsigned int keylen, u32 *flags)
981 + n = parity[key[0]]; n <<= 4;
982 + n |= parity[key[1]]; n <<= 4;
983 + n |= parity[key[2]]; n <<= 4;
984 + n |= parity[key[3]]; n <<= 4;
985 + n |= parity[key[4]]; n <<= 4;
986 + n |= parity[key[5]]; n <<= 4;
987 + n |= parity[key[6]]; n <<= 4;
988 + n |= parity[key[7]];
991 + if ((*flags & CRYPTO_TFM_REQ_WEAK_KEY)
992 + && !((n - (w >> 3)) & w)) { /* 1 in 10^10 keys passes this test */
993 + if (n < 0x41415151) {
994 + if (n < 0x31312121) {
995 + if (n < 0x14141515) {
996 + /* 01 01 01 01 01 01 01 01 */
997 + if (n == 0x11111111) goto weak;
998 + /* 01 1F 01 1F 01 0E 01 0E */
999 + if (n == 0x13131212) goto weak;
1001 + /* 01 E0 01 E0 01 F1 01 F1 */
1002 + if (n == 0x14141515) goto weak;
1003 + /* 01 FE 01 FE 01 FE 01 FE */
1004 + if (n == 0x16161616) goto weak;
1007 + if (n < 0x34342525) {
1008 + /* 1F 01 1F 01 0E 01 0E 01 */
1009 + if (n == 0x31312121) goto weak;
1010 + /* 1F 1F 1F 1F 0E 0E 0E 0E (?) */
1011 + if (n == 0x33332222) goto weak;
1013 + /* 1F E0 1F E0 0E F1 0E F1 */
1014 + if (n == 0x34342525) goto weak;
1015 + /* 1F FE 1F FE 0E FE 0E FE */
1016 + if (n == 0x36362626) goto weak;
1020 + if (n < 0x61616161) {
1021 + if (n < 0x44445555) {
1022 + /* E0 01 E0 01 F1 01 F1 01 */
1023 + if (n == 0x41415151) goto weak;
1024 + /* E0 1F E0 1F F1 0E F1 0E */
1025 + if (n == 0x43435252) goto weak;
1027 + /* E0 E0 E0 E0 F1 F1 F1 F1 (?) */
1028 + if (n == 0x44445555) goto weak;
1029 + /* E0 FE E0 FE F1 FE F1 FE */
1030 + if (n == 0x46465656) goto weak;
1033 + if (n < 0x64646565) {
1034 + /* FE 01 FE 01 FE 01 FE 01 */
1035 + if (n == 0x61616161) goto weak;
1036 + /* FE 1F FE 1F FE 0E FE 0E */
1037 + if (n == 0x63636262) goto weak;
1039 + /* FE E0 FE E0 FE F1 FE F1 */
1040 + if (n == 0x64646565) goto weak;
1041 + /* FE FE FE FE FE FE FE FE */
1042 + if (n == 0x66666666) goto weak;
1049 + *flags |= CRYPTO_TFM_RES_WEAK_KEY;
1053 +EXPORT_SYMBOL(crypto_des_check_key);
1055 +MODULE_LICENSE("GPL");
1056 +MODULE_DESCRIPTION("Key Check function for DES & DES3 Cipher Algorithms");
1057 diff -ruN linux-2.6.30.10/arch/ubicom32/crypto/des_ubicom32.c linux-2.6.30.10-ubi/arch/ubicom32/crypto/des_ubicom32.c
1058 --- linux-2.6.30.10/arch/ubicom32/crypto/des_ubicom32.c 1970-01-01 02:00:00.000000000 +0200
1059 +++ linux-2.6.30.10-ubi/arch/ubicom32/crypto/des_ubicom32.c 2009-12-11 11:45:11.000000000 +0200
1062 + * arch/ubicom32/crypto/des_ubicom32.c
1063 + * Ubicom32 implementation of the DES Cipher Algorithm.
1065 + * (C) Copyright 2009, Ubicom, Inc.
1067 + * This file is part of the Ubicom32 Linux Kernel Port.
1069 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
1070 + * it and/or modify it under the terms of the GNU General Public License
1071 + * as published by the Free Software Foundation, either version 2 of the
1072 + * License, or (at your option) any later version.
1074 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
1075 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
1076 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
1077 + * the GNU General Public License for more details.
1079 + * You should have received a copy of the GNU General Public License
1080 + * along with the Ubicom32 Linux Kernel Port. If not,
1081 + * see <http://www.gnu.org/licenses/>.
1083 + * Ubicom32 implementation derived from (with many thanks):
1088 +#include <crypto/algapi.h>
1089 +#include <linux/init.h>
1090 +#include <linux/module.h>
1092 +#include "crypto_ubicom32.h"
1093 +extern int crypto_des_check_key(const u8 *key, unsigned int keylen, u32 *flags);
1095 +#define DES_BLOCK_SIZE 8
1096 +#define DES_KEY_SIZE 8
1098 +#define DES3_192_KEY_SIZE (3 * DES_KEY_SIZE)
1099 +#define DES3_192_BLOCK_SIZE DES_BLOCK_SIZE
1101 +#define DES3_SUB_KEY(key, i) (((u8 *)key) + (i * DES_KEY_SIZE))
1116 +struct ubicom32_des_ctx {
1117 + u8 key[3 * DES_KEY_SIZE];
1122 +static inline void des_hw_set_key(const u8 *key, u8 key_len)
1125 + * HW 3DES is not tested yet, use DES just as ipOS
1130 +static inline void des_hw_cipher(u8 *out, const u8 *in)
1132 + SEC_SET_INPUT_2W(in);
1135 + " ; start DES by writing 0x38(SECURITY_BASE) \n\t"
1136 + " move.4 0x38(%0), #0x01 \n\t"
1137 + " pipe_flush 0 \n\t"
1139 + " ; wait for the module to calculate the output \n\t"
1140 + " btst 0x04(%0), #0 \n\t"
1141 + " jmpne.f .-4 \n\t"
1147 + SEC_GET_OUTPUT_2W(out);
1151 +static void inline des3_hw_ede_encrypt(u8 *keys, u8 *out, const u8 *in)
1153 + hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_ENCRYPT);
1154 + des_hw_set_key(DES3_SUB_KEY(keys, 0), DES_KEY_SIZE);
1155 + des_hw_cipher(out, in);
1157 + hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_DECRYPT);
1158 + des_hw_set_key(DES3_SUB_KEY(keys, 1), DES_KEY_SIZE);
1159 + des_hw_cipher(out, out);
1161 + hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_ENCRYPT);
1162 + des_hw_set_key(DES3_SUB_KEY(keys, 2), DES_KEY_SIZE);
1163 + des_hw_cipher(out, out);
1166 +static void inline des3_hw_ede_decrypt(u8 *keys, u8 *out, const u8 *in)
1168 + hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_DECRYPT);
1169 + des_hw_set_key(DES3_SUB_KEY(keys, 2), DES_KEY_SIZE);
1170 + des_hw_cipher(out, in);
1172 + hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_ENCRYPT);
1173 + des_hw_set_key(DES3_SUB_KEY(keys, 1), DES_KEY_SIZE);
1174 + des_hw_cipher(out, out);
1176 + hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_DECRYPT);
1177 + des_hw_set_key(DES3_SUB_KEY(keys, 0), DES_KEY_SIZE);
1178 + des_hw_cipher(out, out);
1182 +static void inline des3_hw_eee_encrypt(u8 *keys, u8 *out, const u8 *in)
1184 + hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_ENCRYPT);
1185 + des_hw_set_key(DES3_SUB_KEY(keys, 0), 2);
1186 + des_hw_cipher(out, in);
1188 + hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_ENCRYPT);
1189 + des_hw_set_key(DES3_SUB_KEY(keys, 1), 2);
1190 + des_hw_cipher(out, out);
1192 + hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_ENCRYPT);
1193 + des_hw_set_key(DES3_SUB_KEY(keys, 2), 2);
1194 + des_hw_cipher(out, out);
1197 +static void inline des3_hw_eee_decrypt(u8 *keys, u8 *out, const u8 *in)
1199 + hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_DECRYPT);
1200 + des_hw_set_key(DES3_SUB_KEY(keys, 2), 2);
1201 + des_hw_cipher(out, in);
1203 + hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_DECRYPT);
1204 + des_hw_set_key(DES3_SUB_KEY(keys, 1), 2);
1205 + des_hw_cipher(out, out);
1207 + hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_DECRYPT);
1208 + des_hw_set_key(DES3_SUB_KEY(keys, 0), 2);
1209 + des_hw_cipher(out, out);
1213 +static int des_setkey(struct crypto_tfm *tfm, const u8 *key,
1214 + unsigned int keylen)
1216 + struct ubicom32_des_ctx *dctx = crypto_tfm_ctx(tfm);
1217 + u32 *flags = &tfm->crt_flags;
1220 + /* test if key is valid (not a weak key) */
1221 + ret = crypto_des_check_key(key, keylen, flags);
1223 + memcpy(dctx->key, key, keylen);
1224 + dctx->key_len = keylen;
1225 + //dctx->ctrl = (keylen == DES_KEY_SIZE) ? SEC_ALG_DES : SEC_ALG_3DES
1226 + /* 2DES and 3DES are both implemented with DES hw function */
1227 + dctx->ctrl = SEC_ALG_DES;
1232 +static inline void des_cipher_1b(struct crypto_tfm *tfm, u8 *out, const u8 *in, u32 extra_flags)
1234 + const struct ubicom32_des_ctx *uctx = crypto_tfm_ctx(tfm);
1237 + hw_crypto_check();
1238 + hw_crypto_set_ctrl(uctx->ctrl | extra_flags);
1240 + des_hw_set_key(uctx->key, uctx->key_len);
1241 + des_hw_cipher(out, in);
1243 + hw_crypto_unlock();
1246 +static void des_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
1248 + des_cipher_1b(tfm, out, in, SEC_DIR_ENCRYPT);
1251 +static void des_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
1253 + des_cipher_1b(tfm, out, in, SEC_DIR_DECRYPT);
1256 +static struct crypto_alg des_alg = {
1257 + .cra_name = "des",
1258 + .cra_driver_name = "des-ubicom32",
1259 + .cra_priority = CRYPTO_UBICOM32_PRIORITY,
1260 + .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
1261 + .cra_blocksize = DES_BLOCK_SIZE,
1262 + .cra_ctxsize = sizeof(struct ubicom32_des_ctx),
1263 + .cra_alignmask = CRYPTO_UBICOM32_ALIGNMENT - 1,
1264 + .cra_alignmask = CRYPTO_UBICOM32_ALIGNMENT - 1,
1265 + .cra_module = THIS_MODULE,
1266 + .cra_list = LIST_HEAD_INIT(des_alg.cra_list),
1269 + .cia_min_keysize = DES_KEY_SIZE,
1270 + .cia_max_keysize = DES_KEY_SIZE,
1271 + .cia_setkey = des_setkey,
1272 + .cia_encrypt = des_encrypt,
1273 + .cia_decrypt = des_decrypt,
1278 +static void ecb_des_ciper_loop(u8 *out, u8 *in, unsigned int n)
1280 + while (likely(n)) {
1281 + des_hw_cipher(out, in);
1282 + out += DES_BLOCK_SIZE;
1283 + in += DES_BLOCK_SIZE;
1284 + n -= DES_BLOCK_SIZE;
1288 +static void ecb_des3_ede_encrypt_loop(u8 *keys, u8 *out, u8 *in, unsigned int n)
1290 + while (likely(n)) {
1291 + des3_hw_ede_encrypt(keys, out, in);
1293 + out += DES_BLOCK_SIZE;
1294 + in += DES_BLOCK_SIZE;
1295 + n -= DES_BLOCK_SIZE;
1299 +static void ecb_des3_ede_decrypt_loop(u8 *keys, u8 *out, u8 *in, unsigned int n)
1301 + while (likely(n)) {
1302 + des3_hw_ede_decrypt(keys, out, in);
1304 + out += DES_BLOCK_SIZE;
1305 + in += DES_BLOCK_SIZE;
1306 + n -= DES_BLOCK_SIZE;
1311 +static void ecb_des3_eee_encrypt_loop(u8 *keys, u8 *out, u8 *in, unsigned int n)
1313 + while (likely(n)) {
1314 + des3_hw_eee_encrypt(keys, out, in);
1316 + out += DES_BLOCK_SIZE;
1317 + in += DES_BLOCK_SIZE;
1318 + n -= DES_BLOCK_SIZE;
1322 +static void ecb_des3_eee_decrypt_loop(u8 *keys, u8 *out, u8 *in, unsigned int n)
1324 + while (likely(n)) {
1325 + des3_hw_eee_decrypt(keys, out, in);
1327 + out += DES_BLOCK_SIZE;
1328 + in += DES_BLOCK_SIZE;
1329 + n -= DES_BLOCK_SIZE;
1334 +static inline void ecb_des_cipher_n(struct ubicom32_des_ctx *uctx, enum des_ops op, u8 *out, u8 *in, unsigned int n)
1339 + /* set the right algo, direction and key once */
1340 + hw_crypto_set_ctrl(SEC_ALG_DES | (op == DES_ENCRYPT ? SEC_DIR_ENCRYPT : 0));
1341 + des_hw_set_key(uctx->key, uctx->key_len);
1342 + ecb_des_ciper_loop(out, in, n);
1345 + case DES3_EDE_ENCRYPT:
1346 + ecb_des3_ede_encrypt_loop(uctx->key, out, in, n);
1349 + case DES3_EDE_DECRYPT:
1350 + ecb_des3_ede_decrypt_loop(uctx->key, out, in, n);
1354 + case DES3_EEE_ENCRYPT:
1355 + ecb_des3_eee_encrypt_loop(uctx->key, out, in, n);
1358 + case DES3_EEE_DECRYPT:
1359 + ecb_des3_eee_decrypt_loop(uctx->key, out, in, n);
1365 +static inline void des_xor_2w(u32 *data, u32 *iv)
1371 +static void cbc_des_encrypt_loop(u8 *out, u8 *in, u8 *iv, unsigned int n)
1373 + while (likely(n)) {
1374 + des_xor_2w((u32 *)in, (u32 *)iv);
1375 + des_hw_cipher(out, in);
1376 + SEC_COPY_2W(iv, out);
1377 + out += DES_BLOCK_SIZE;
1378 + in += DES_BLOCK_SIZE;
1379 + n -= DES_BLOCK_SIZE;
1383 +static void cbc_des_decrypt_loop(u8 *out, u8 *in, u8 *iv, unsigned int n)
1385 + u8 next_iv[DES_BLOCK_SIZE];
1386 + while (likely(n)) {
1387 + SEC_COPY_2W(next_iv, in);
1388 + des_hw_cipher(out, in);
1389 + des_xor_2w((u32 *)out, (u32 *)iv);
1390 + SEC_COPY_2W(iv, next_iv);
1392 + out += DES_BLOCK_SIZE;
1393 + in += DES_BLOCK_SIZE;
1394 + n -= DES_BLOCK_SIZE;
1398 +static void cbc_des3_ede_encrypt_loop(u8 *keys, u8 *out, u8 *in, u8 *iv, unsigned int n)
1400 + while (likely(n)) {
1401 + des_xor_2w((u32 *)in, (u32 *)iv);
1402 + des3_hw_ede_encrypt(keys, out, in);
1403 + SEC_COPY_2W(iv, out);
1405 + out += DES_BLOCK_SIZE;
1406 + in += DES_BLOCK_SIZE;
1407 + n -= DES_BLOCK_SIZE;
1411 +static void cbc_des3_ede_decrypt_loop(u8 *keys, u8 *out, u8 *in, u8 *iv, unsigned int n)
1413 + u8 next_iv[DES_BLOCK_SIZE];
1414 + while (likely(n)) {
1415 + SEC_COPY_2W(next_iv, in);
1416 + des3_hw_ede_decrypt(keys, out, in);
1417 + des_xor_2w((u32 *)out, (u32 *)iv);
1418 + SEC_COPY_2W(iv, next_iv);
1420 + out += DES_BLOCK_SIZE;
1421 + in += DES_BLOCK_SIZE;
1422 + n -= DES_BLOCK_SIZE;
1427 +static void cbc_des3_eee_encrypt_loop(u8 *keys, u8 *out, u8 *in, u8 *iv, unsigned int n)
1429 + while (likely(n)) {
1430 + des_xor_2w((u32 *)in, (u32 *)iv);
1431 + des3_hw_eee_encrypt(keys, out, in);
1432 + SEC_COPY_2W(iv, out);
1434 + out += DES_BLOCK_SIZE;
1435 + in += DES_BLOCK_SIZE;
1436 + n -= DES_BLOCK_SIZE;
1440 +static void cbc_des3_eee_decrypt_loop(u8 *keys, u8 *out, u8 *in, u8 *iv, unsigned int n)
1442 + u8 next_iv[DES_BLOCK_SIZE];
1443 + while (likely(n)) {
1444 + SEC_COPY_2W(next_iv, in);
1445 + des3_hw_eee_decrypt(keys, out, in);
1446 + des_xor_2w((u32 *)out, (u32 *)iv);
1447 + SEC_COPY_2W(iv, next_iv);
1449 + out += DES_BLOCK_SIZE;
1450 + in += DES_BLOCK_SIZE;
1451 + n -= DES_BLOCK_SIZE;
1456 +static inline void cbc_des_cipher_n(struct ubicom32_des_ctx *uctx, enum des_ops op, u8 *out, u8 *in, u8 *iv, unsigned int n)
1460 + hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_ENCRYPT);
1461 + des_hw_set_key(uctx->key, uctx->key_len);
1462 + cbc_des_encrypt_loop(out, in, iv, n);
1466 + /* set the right algo, direction and key once */
1467 + hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_DECRYPT);
1468 + des_hw_set_key(uctx->key, uctx->key_len);
1469 + cbc_des_decrypt_loop(out, in, iv, n);
1472 + case DES3_EDE_ENCRYPT:
1473 + cbc_des3_ede_encrypt_loop(uctx->key, out, in, iv, n);
1476 + case DES3_EDE_DECRYPT:
1477 + cbc_des3_ede_decrypt_loop(uctx->key, out, in, iv, n);
1481 + case DES3_EEE_ENCRYPT:
1482 + cbc_des3_eee_encrypt_loop(uctx->key, out, in, iv, n);
1485 + case DES3_EEE_DECRYPT:
1486 + cbc_des3_eee_decrypt_loop(uctx->key, out, in, iv, n);
1492 +static int des_cipher(struct blkcipher_desc *desc, struct scatterlist *dst,
1493 + struct scatterlist *src, unsigned int nbytes, u32 extra_flags, enum des_ops op)
1495 + struct ubicom32_des_ctx *uctx = crypto_blkcipher_ctx(desc->tfm);
1498 + struct blkcipher_walk walk;
1499 + blkcipher_walk_init(&walk, dst, src, nbytes);
1500 + ret = blkcipher_walk_virt(desc, &walk);
1506 + hw_crypto_check();
1508 + while ((nbytes = walk.nbytes)) {
1509 + /* only use complete blocks */
1510 + unsigned int n = nbytes & ~(DES_BLOCK_SIZE - 1);
1511 + u8 *out = walk.dst.virt.addr;
1512 + u8 *in = walk.src.virt.addr;
1514 + /* finish n/16 blocks */
1515 + if (extra_flags & SEC_CBC_SET) {
1516 + cbc_des_cipher_n(uctx, op, out, in, walk.iv, n);
1518 + ecb_des_cipher_n(uctx, op, out, in, n);
1521 + nbytes &= DES_BLOCK_SIZE - 1;
1522 + ret = blkcipher_walk_done(desc, &walk, nbytes);
1525 + hw_crypto_unlock();
1529 +static int ecb_des_encrypt(struct blkcipher_desc *desc,
1530 + struct scatterlist *dst, struct scatterlist *src,
1531 + unsigned int nbytes)
1533 + return des_cipher(desc, dst, src, nbytes, SEC_CBC_NONE, DES_ENCRYPT);
1536 +static int ecb_des_decrypt(struct blkcipher_desc *desc,
1537 + struct scatterlist *dst, struct scatterlist *src,
1538 + unsigned int nbytes)
1540 + return des_cipher(desc, dst, src, nbytes, SEC_CBC_NONE, DES_DECRYPT);
1543 +static struct crypto_alg ecb_des_alg = {
1544 + .cra_name = "ecb(des)",
1545 + .cra_driver_name = "ecb-des-ubicom32",
1546 + .cra_priority = CRYPTO_UBICOM32_COMPOSITE_PRIORITY,
1547 + .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
1548 + .cra_blocksize = DES_BLOCK_SIZE,
1549 + .cra_ctxsize = sizeof(struct ubicom32_des_ctx),
1550 + .cra_alignmask = CRYPTO_UBICOM32_ALIGNMENT - 1,
1551 + .cra_type = &crypto_blkcipher_type,
1552 + .cra_module = THIS_MODULE,
1553 + .cra_list = LIST_HEAD_INIT(ecb_des_alg.cra_list),
1556 + .min_keysize = DES_KEY_SIZE,
1557 + .max_keysize = DES_KEY_SIZE,
1558 + .setkey = des_setkey,
1559 + .encrypt = ecb_des_encrypt,
1560 + .decrypt = ecb_des_decrypt,
1565 +static int cbc_des_encrypt(struct blkcipher_desc *desc,
1566 + struct scatterlist *dst, struct scatterlist *src,
1567 + unsigned int nbytes)
1569 + return des_cipher(desc, dst, src, nbytes, SEC_CBC_SET, DES_ENCRYPT);
1572 +static int cbc_des_decrypt(struct blkcipher_desc *desc,
1573 + struct scatterlist *dst, struct scatterlist *src,
1574 + unsigned int nbytes)
1576 + return des_cipher(desc, dst, src, nbytes, SEC_CBC_SET, DES_DECRYPT);
1579 +static struct crypto_alg cbc_des_alg = {
1580 + .cra_name = "cbc(des)",
1581 + .cra_driver_name = "cbc-des-ubicom32",
1582 + .cra_priority = CRYPTO_UBICOM32_COMPOSITE_PRIORITY,
1583 + .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
1584 + .cra_blocksize = DES_BLOCK_SIZE,
1585 + .cra_ctxsize = sizeof(struct ubicom32_des_ctx),
1586 + .cra_alignmask = CRYPTO_UBICOM32_ALIGNMENT - 1,
1587 + .cra_type = &crypto_blkcipher_type,
1588 + .cra_module = THIS_MODULE,
1589 + .cra_list = LIST_HEAD_INIT(cbc_des_alg.cra_list),
1592 + .min_keysize = DES_KEY_SIZE,
1593 + .max_keysize = DES_KEY_SIZE,
1594 + .ivsize = DES_BLOCK_SIZE,
1595 + .setkey = des_setkey,
1596 + .encrypt = cbc_des_encrypt,
1597 + .decrypt = cbc_des_decrypt,
1605 + * For DES-EDE3, there is no known need to reject weak or
1606 + * complementation keys. Any weakness is obviated by the use of
1609 + * However, if the first two or last two independent 64-bit keys are
1610 + * equal (k1 == k2 or k2 == k3), then the DES3 operation is simply the
1611 + * same as DES. Implementers MUST reject keys that exhibit this
1615 +static int des3_192_setkey(struct crypto_tfm *tfm, const u8 *key,
1616 + unsigned int keylen)
1619 + struct ubicom32_des_ctx *dctx = crypto_tfm_ctx(tfm);
1620 + const u8 *temp_key = key;
1621 + u32 *flags = &tfm->crt_flags;
1623 + if (!(memcmp(key, &key[DES_KEY_SIZE], DES_KEY_SIZE) &&
1624 + memcmp(&key[DES_KEY_SIZE], &key[DES_KEY_SIZE * 2],
1627 + *flags |= CRYPTO_TFM_RES_BAD_KEY_SCHED;
1630 + for (i = 0; i < 3; i++, temp_key += DES_KEY_SIZE) {
1631 + ret = crypto_des_check_key(temp_key, DES_KEY_SIZE, flags);
1635 + memcpy(dctx->key, key, keylen);
1636 + dctx->ctrl = SEC_ALG_DES; //hw 3DES not working yet
1637 + dctx->key_len = keylen;
1641 +static void des3_192_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
1643 + struct ubicom32_des_ctx *uctx = crypto_tfm_ctx(tfm);
1646 + hw_crypto_check();
1648 + des3_hw_ede_encrypt(uctx->key, dst, src);
1650 + hw_crypto_unlock();
1653 +static void des3_192_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
1655 + struct ubicom32_des_ctx *uctx = crypto_tfm_ctx(tfm);
1658 + hw_crypto_check();
1660 + des3_hw_ede_decrypt(uctx->key, dst, src);
1662 + hw_crypto_unlock();
1665 +static struct crypto_alg des3_192_alg = {
1666 + .cra_name = "des3_ede",
1667 + .cra_driver_name = "des3_ede-ubicom32",
1668 + .cra_priority = CRYPTO_UBICOM32_PRIORITY,
1669 + .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
1670 + .cra_blocksize = DES3_192_BLOCK_SIZE,
1671 + .cra_ctxsize = sizeof(struct ubicom32_des_ctx),
1672 + .cra_alignmask = CRYPTO_UBICOM32_ALIGNMENT - 1,
1673 + .cra_module = THIS_MODULE,
1674 + .cra_list = LIST_HEAD_INIT(des3_192_alg.cra_list),
1677 + .cia_min_keysize = DES3_192_KEY_SIZE,
1678 + .cia_max_keysize = DES3_192_KEY_SIZE,
1679 + .cia_setkey = des3_192_setkey,
1680 + .cia_encrypt = des3_192_encrypt,
1681 + .cia_decrypt = des3_192_decrypt,
1686 +static int ecb_des3_192_encrypt(struct blkcipher_desc *desc,
1687 + struct scatterlist *dst,
1688 + struct scatterlist *src, unsigned int nbytes)
1690 + return des_cipher(desc, dst, src, nbytes, SEC_CBC_NONE, DES3_EDE_ENCRYPT);
1693 +static int ecb_des3_192_decrypt(struct blkcipher_desc *desc,
1694 + struct scatterlist *dst,
1695 + struct scatterlist *src, unsigned int nbytes)
1697 + return des_cipher(desc, dst, src, nbytes, SEC_CBC_NONE, DES3_EDE_DECRYPT);
1700 +static struct crypto_alg ecb_des3_192_alg = {
1701 + .cra_name = "ecb(des3_ede)",
1702 + .cra_driver_name = "ecb-des3_ede-ubicom32",
1703 + .cra_priority = CRYPTO_UBICOM32_COMPOSITE_PRIORITY,
1704 + .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
1705 + .cra_blocksize = DES3_192_BLOCK_SIZE,
1706 + .cra_ctxsize = sizeof(struct ubicom32_des_ctx),
1707 + .cra_alignmask = CRYPTO_UBICOM32_ALIGNMENT - 1,
1708 + .cra_type = &crypto_blkcipher_type,
1709 + .cra_module = THIS_MODULE,
1710 + .cra_list = LIST_HEAD_INIT(
1711 + ecb_des3_192_alg.cra_list),
1714 + .min_keysize = DES3_192_KEY_SIZE,
1715 + .max_keysize = DES3_192_KEY_SIZE,
1716 + .setkey = des3_192_setkey,
1717 + .encrypt = ecb_des3_192_encrypt,
1718 + .decrypt = ecb_des3_192_decrypt,
1723 +static int cbc_des3_192_encrypt(struct blkcipher_desc *desc,
1724 + struct scatterlist *dst,
1725 + struct scatterlist *src, unsigned int nbytes)
1727 + return des_cipher(desc, dst, src, nbytes, SEC_CBC_SET, DES3_EDE_ENCRYPT);
1730 +static int cbc_des3_192_decrypt(struct blkcipher_desc *desc,
1731 + struct scatterlist *dst,
1732 + struct scatterlist *src, unsigned int nbytes)
1734 + return des_cipher(desc, dst, src, nbytes, SEC_CBC_SET, DES3_EDE_DECRYPT);
1737 +static struct crypto_alg cbc_des3_192_alg = {
1738 + .cra_name = "cbc(des3_ede)",
1739 + .cra_driver_name = "cbc-des3_ede-ubicom32",
1740 + .cra_priority = CRYPTO_UBICOM32_COMPOSITE_PRIORITY,
1741 + .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
1742 + .cra_blocksize = DES3_192_BLOCK_SIZE,
1743 + .cra_ctxsize = sizeof(struct ubicom32_des_ctx),
1744 + .cra_alignmask = CRYPTO_UBICOM32_ALIGNMENT - 1,
1745 + .cra_type = &crypto_blkcipher_type,
1746 + .cra_module = THIS_MODULE,
1747 + .cra_list = LIST_HEAD_INIT(
1748 + cbc_des3_192_alg.cra_list),
1751 + .min_keysize = DES3_192_KEY_SIZE,
1752 + .max_keysize = DES3_192_KEY_SIZE,
1753 + .ivsize = DES3_192_BLOCK_SIZE,
1754 + .setkey = des3_192_setkey,
1755 + .encrypt = cbc_des3_192_encrypt,
1756 + .decrypt = cbc_des3_192_decrypt,
1761 +static int init(void)
1767 + ret = crypto_register_alg(&des_alg);
1770 + ret = crypto_register_alg(&ecb_des_alg);
1773 + ret = crypto_register_alg(&cbc_des_alg);
1777 + ret = crypto_register_alg(&des3_192_alg);
1779 + goto des3_192_err;
1780 + ret = crypto_register_alg(&ecb_des3_192_alg);
1782 + goto ecb_des3_192_err;
1783 + ret = crypto_register_alg(&cbc_des3_192_alg);
1785 + goto cbc_des3_192_err;
1791 + crypto_unregister_alg(&ecb_des3_192_alg);
1793 + crypto_unregister_alg(&des3_192_alg);
1795 + crypto_unregister_alg(&cbc_des_alg);
1797 + crypto_unregister_alg(&ecb_des_alg);
1799 + crypto_unregister_alg(&des_alg);
1804 +static void __exit fini(void)
1806 + crypto_unregister_alg(&cbc_des3_192_alg);
1807 + crypto_unregister_alg(&ecb_des3_192_alg);
1808 + crypto_unregister_alg(&des3_192_alg);
1809 + crypto_unregister_alg(&cbc_des_alg);
1810 + crypto_unregister_alg(&ecb_des_alg);
1811 + crypto_unregister_alg(&des_alg);
1817 +MODULE_ALIAS("des");
1818 +MODULE_ALIAS("des3_ede");
1820 +MODULE_LICENSE("GPL");
1821 +MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms");
1822 diff -ruN linux-2.6.30.10/arch/ubicom32/crypto/Makefile linux-2.6.30.10-ubi/arch/ubicom32/crypto/Makefile
1823 --- linux-2.6.30.10/arch/ubicom32/crypto/Makefile 1970-01-01 02:00:00.000000000 +0200
1824 +++ linux-2.6.30.10-ubi/arch/ubicom32/crypto/Makefile 2009-12-11 11:45:11.000000000 +0200
1827 +# arch/ubicom32/crypto/Makefile
1828 +# <TODO: Replace with short file description>
1830 +# (C) Copyright 2009, Ubicom, Inc.
1832 +# This file is part of the Ubicom32 Linux Kernel Port.
1834 +# The Ubicom32 Linux Kernel Port is free software: you can redistribute
1835 +# it and/or modify it under the terms of the GNU General Public License
1836 +# as published by the Free Software Foundation, either version 2 of the
1837 +# License, or (at your option) any later version.
1839 +# The Ubicom32 Linux Kernel Port is distributed in the hope that it
1840 +# will be useful, but WITHOUT ANY WARRANTY; without even the implied
1841 +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
1842 +# the GNU General Public License for more details.
1844 +# You should have received a copy of the GNU General Public License
1845 +# along with the Ubicom32 Linux Kernel Port. If not,
1846 +# see <http://www.gnu.org/licenses/>.
1848 +# Ubicom32 implementation derived from (with many thanks):
1853 +obj-$(CONFIG_CRYPTO_UBICOM32) += crypto_ubicom32.o
1854 +obj-$(CONFIG_CRYPTO_AES_UBICOM32) += aes_ubicom32.o
1855 +obj-$(CONFIG_CRYPTO_DES_UBICOM32) += des.o
1856 +obj-$(CONFIG_CRYPTO_MD5_UBICOM32) += md5.o
1857 +obj-$(CONFIG_CRYPTO_SHA1_UBICOM32) += sha1.o
1859 +des-y := des_ubicom32.o des_check_key.o
1860 +md5-y := md5_ubicom32.o md5_ubicom32_asm.o
1861 +sha1-y := sha1_ubicom32.o
1862 diff -ruN linux-2.6.30.10/arch/ubicom32/crypto/md5_ubicom32_asm.S linux-2.6.30.10-ubi/arch/ubicom32/crypto/md5_ubicom32_asm.S
1863 --- linux-2.6.30.10/arch/ubicom32/crypto/md5_ubicom32_asm.S 1970-01-01 02:00:00.000000000 +0200
1864 +++ linux-2.6.30.10-ubi/arch/ubicom32/crypto/md5_ubicom32_asm.S 2009-12-11 11:45:11.000000000 +0200
1867 + * arch/ubicom32/crypto/md5_ubicom32_asm.S
1868 + * MD5 (Message Digest 5) support for Ubicom32 v3 architecture
1870 + * (C) Copyright 2009, Ubicom, Inc.
1872 + * This file is part of the Ubicom32 Linux Kernel Port.
1874 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
1875 + * it and/or modify it under the terms of the GNU General Public License
1876 + * as published by the Free Software Foundation, either version 2 of the
1877 + * License, or (at your option) any later version.
1879 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
1880 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
1881 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
1882 + * the GNU General Public License for more details.
1884 + * You should have received a copy of the GNU General Public License
1885 + * along with the Ubicom32 Linux Kernel Port. If not,
1886 + * see <http://www.gnu.org/licenses/>.
1888 + * Ubicom32 implementation derived from (with many thanks):
1895 +#include <asm/ip5000.h>
1901 +;*****************************************************************************************
1902 +; The function prototypes
1903 +;*****************************************************************************************
1904 +; void md5_ip5k_init(void)
1905 +; void md5_ip5k_transform(u32_t *data_input)
1906 +; void md5_get_digest(u32_t *digest)
1908 +;*****************************************************************************************
1910 +;*****************************************************************************************;
1911 +; data_input is the pointer to the block of data over which the digest will be calculated.
1912 +; It should be word aligned.
1914 +; digest is the pointer to the block of data into which the digest (the output) will be written.
1915 +; It should be word aligned.
1918 +;*****************************************************************************************
1920 +;*****************************************************************************************
1923 +;*****************************************************************************************
1924 +; An: Address Registers
1925 +;*****************************************************************************************
1926 +#define an_digest A3
1927 +#define an_data_input A3
1928 +#define an_security_block A4
1930 +;*****************************************************************************************
1932 +;*****************************************************************************************
1933 +#define HASH_MD5_IN0 0x01234567
1934 +#define HASH_MD5_IN1 0x89abcdef
1935 +#define HASH_MD5_IN2 0xfedcba98
1936 +#define HASH_MD5_IN3 0x76543210
1938 +#define HASH_SECURITY_BLOCK_CONTROL_INIT_NO_ENCYPTION 2
1939 +#define HASH_SECURITY_BLOCK_CONTROL_INIT_MD5 ((1 << 4) | HASH_SECURITY_BLOCK_CONTROL_INIT_NO_ENCYPTION)
1941 +;*****************************************************************************************
1942 +; Hash related defines
1943 +;*****************************************************************************************
1944 +#define hash_control 0x00(an_security_block)
1945 +#define hash_control_low 0x02(an_security_block)
1946 +#define hash_status 0x04(an_security_block)
1948 +#define hash_input_0 0x30(an_security_block)
1949 +#define hash_input_1 0x34(an_security_block)
1950 +#define hash_input_2 0x38(an_security_block)
1951 +#define hash_input_3 0x3c(an_security_block)
1952 +#define hash_input_4 0x40(an_security_block)
1954 +#define hash_output_0 0x70(an_security_block)
1955 +#define hash_output_0_low 0x72(an_security_block)
1956 +#define hash_output_1 0x74(an_security_block)
1957 +#define hash_output_1_low 0x76(an_security_block)
1958 +#define hash_output_2 0x78(an_security_block)
1959 +#define hash_output_2_low 0x7a(an_security_block)
1960 +#define hash_output_3 0x7c(an_security_block)
1961 +#define hash_output_3_low 0x7e(an_security_block)
1963 +;*****************************************************************************************
1965 +;*****************************************************************************************
1966 + ; C compiler reserves RP (A5) for return address during subroutine call.
1967 + ; Use RP to return to caller
1968 +.macro call_return_macro
1973 +;*****************************************************************************************
1974 +; void md5_ip5k_init(void)
1975 +; initialize the output registers of the hash module
1977 + ;.section .text.md5_ip5k_init,"ax",@progbits
1979 + .global _md5_ip5k_init
1980 + .func md5_ip5k_init, _md5_ip5k_init
1983 + moveai an_security_block, #SECURITY_BASE_EFFECTIVE_ADDRESS
1985 + movei hash_control, #%hi(HASH_SECURITY_BLOCK_CONTROL_INIT_MD5)
1986 + movei hash_control_low, #%lo(HASH_SECURITY_BLOCK_CONTROL_INIT_MD5)
1988 + movei hash_output_0, #%hi(HASH_MD5_IN0)
1989 + movei hash_output_0_low, #%lo(HASH_MD5_IN0)
1991 + movei hash_output_1, #%hi(HASH_MD5_IN1)
1992 + movei hash_output_1_low, #%lo(HASH_MD5_IN1)
1994 + movei hash_output_2, #%hi(HASH_MD5_IN2)
1995 + movei hash_output_2_low, #%lo(HASH_MD5_IN2)
1997 + movei hash_output_3, #%hi(HASH_MD5_IN3)
1998 + movei hash_output_3_low, #%lo(HASH_MD5_IN3)
2004 +;*****************************************************************************************
2005 +; void md5_ip5k_init_digest(u32_t *hash_input)
2006 +; initialize the output registers of the hash module
2008 + ;.section .text.md5_ip5k_init_digest,"ax",@progbits
2010 + .global _md5_ip5k_init_digest
2011 + .func md5_ip5k_init_digest, _md5_ip5k_init_digest
2013 +_md5_ip5k_init_digest:
2014 + movea an_data_input, D0
2016 + moveai an_security_block, #SECURITY_BASE_EFFECTIVE_ADDRESS
2018 + movei hash_control, #%hi(HASH_SECURITY_BLOCK_CONTROL_INIT_MD5)
2019 + movei hash_control_low, #%lo(HASH_SECURITY_BLOCK_CONTROL_INIT_MD5)
2021 + move.4 hash_output_0, (an_data_input)4++
2022 + move.4 hash_output_1, (an_data_input)4++
2023 + move.4 hash_output_2, (an_data_input)4++
2024 + move.4 hash_output_3, (an_data_input)4++
2029 +;*****************************************************************************************
2030 +; void md5_ip5k_transform(u32_t *data_input)
2031 +; performs intermediate transformation step for the hash calculation
2033 + ;.sect .text.md5_ip5k_transform,"ax",@progbits
2035 + .global _md5_ip5k_transform
2036 + .func md5_ip5k_transform, _md5_ip5k_transform
2038 +_md5_ip5k_transform:
2039 + movea an_data_input, D0
2041 + moveai an_security_block, #SECURITY_BASE_EFFECTIVE_ADDRESS
2043 + ; Write the first 128bits (16 bytes)
2044 + move.4 hash_input_0, (an_data_input)4++
2045 + move.4 hash_input_1, (an_data_input)4++
2046 + move.4 hash_input_2, (an_data_input)4++
2047 + move.4 hash_input_3, (an_data_input)4++
2048 + move.4 hash_input_4, D0
2050 + move.4 hash_input_0, (an_data_input)4++
2051 + move.4 hash_input_1, (an_data_input)4++
2052 + move.4 hash_input_2, (an_data_input)4++
2053 + move.4 hash_input_3, (an_data_input)4++
2054 + move.4 hash_input_4, D0
2056 + move.4 hash_input_0, (an_data_input)4++
2057 + move.4 hash_input_1, (an_data_input)4++
2058 + move.4 hash_input_2, (an_data_input)4++
2059 + move.4 hash_input_3, (an_data_input)4++
2060 + move.4 hash_input_4, D0
2062 + move.4 hash_input_0, (an_data_input)4++
2063 + move.4 hash_input_1, (an_data_input)4++
2064 + move.4 hash_input_2, (an_data_input)4++
2065 + move.4 hash_input_3, (an_data_input)4++
2066 + move.4 hash_input_4, D0
2070 +md5_ip5k_transform_wait:
2071 + ; wait for the module to calculate the output hash
2072 + btst hash_status, #0
2073 + jmpne.f md5_ip5k_transform_wait
2078 +;*****************************************************************************************
2079 +; void md5_ip5k_get_digest(u32_t *digest)
2080 +; Return the hash of the input data
2082 + ;.sect .text.md5_get_digest,"ax",@progbits
2084 + .global _md5_ip5k_get_digest
2085 + .func md5_ip5k_get_digest, _md5_ip5k_get_digest
2087 +_md5_ip5k_get_digest:
2088 + movea an_digest, D0
2090 + moveai an_security_block, #SECURITY_BASE_EFFECTIVE_ADDRESS
2092 + ; we have finished
2093 + move.4 0(an_digest), hash_output_0
2094 + move.4 4(an_digest), hash_output_1
2095 + move.4 8(an_digest), hash_output_2
2096 + move.4 12(an_digest), hash_output_3
2100 diff -ruN linux-2.6.30.10/arch/ubicom32/crypto/md5_ubicom32.c linux-2.6.30.10-ubi/arch/ubicom32/crypto/md5_ubicom32.c
2101 --- linux-2.6.30.10/arch/ubicom32/crypto/md5_ubicom32.c 1970-01-01 02:00:00.000000000 +0200
2102 +++ linux-2.6.30.10-ubi/arch/ubicom32/crypto/md5_ubicom32.c 2009-12-11 11:45:11.000000000 +0200
2105 + * arch/ubicom32/crypto/md5_ubicom32.c
2106 + * Ubicom32 implementation of the MD5 Secure Hash Algorithm
2108 + * (C) Copyright 2009, Ubicom, Inc.
2110 + * This file is part of the Ubicom32 Linux Kernel Port.
2112 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
2113 + * it and/or modify it under the terms of the GNU General Public License
2114 + * as published by the Free Software Foundation, either version 2 of the
2115 + * License, or (at your option) any later version.
2117 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
2118 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
2119 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
2120 + * the GNU General Public License for more details.
2122 + * You should have received a copy of the GNU General Public License
2123 + * along with the Ubicom32 Linux Kernel Port. If not,
2124 + * see <http://www.gnu.org/licenses/>.
2126 + * Ubicom32 implementation derived from (with many thanks):
2131 +#include <linux/init.h>
2132 +#include <linux/module.h>
2133 +#include <linux/crypto.h>
2135 +#include "crypto_ubicom32.h"
2137 +#define MD5_DIGEST_SIZE 16
2138 +#define MD5_BLOCK_SIZE 64
2139 +#define MD5_HASH_WORDS 4
2141 +extern void _md5_ip5k_init_digest(u32_t *digest);
2142 +extern void _md5_ip5k_transform(u32_t *data_input);
2143 +extern void _md5_ip5k_get_digest(u32_t *digest);
2145 +struct ubicom32_md5_ctx {
2146 + u64 count; /* message length */
2147 + u32 state[MD5_HASH_WORDS];
2148 + u8 buf[2 * MD5_BLOCK_SIZE];
2151 +static void md5_init(struct crypto_tfm *tfm)
2153 + struct ubicom32_md5_ctx *mctx = crypto_tfm_ctx(tfm);
2154 + mctx->state[0] = 0x01234567;
2155 + mctx->state[1] = 0x89abcdef;
2156 + mctx->state[2] = 0xfedcba98;
2157 + mctx->state[3] = 0x76543210;
2162 +static inline void _md5_process(u32 *digest, const u8 *data)
2164 + _md5_ip5k_transform((u32 *)data);
2167 +static void md5_update(struct crypto_tfm *tfm, const u8 *data,
2170 + struct ubicom32_md5_ctx *mctx = crypto_tfm_ctx(tfm);
2173 + /* how much is already in the buffer? */
2174 + index = mctx->count & 0x3f;
2176 + mctx->count += len;
2178 + if (index + len < MD5_BLOCK_SIZE) {
2183 + hw_crypto_check();
2185 + /* init digest set ctrl register too */
2186 + _md5_ip5k_init_digest(mctx->state);
2188 + if (unlikely(index == 0 && SEC_ALIGNED(data))) {
2190 + while (len >= MD5_BLOCK_SIZE) {
2191 + _md5_process(mctx->state, data);
2192 + data += MD5_BLOCK_SIZE;
2193 + len -= MD5_BLOCK_SIZE;
2198 + /* process one stored block */
2200 + clen = MD5_BLOCK_SIZE - index;
2201 + memcpy(mctx->buf + index, data, clen);
2202 + _md5_process(mctx->state, mctx->buf);
2208 + if (likely(SEC_ALIGNED(data))) {
2209 + goto fast_process;
2212 + /* process as many blocks as possible */
2213 + while (len >= MD5_BLOCK_SIZE) {
2214 + memcpy(mctx->buf, data, MD5_BLOCK_SIZE);
2215 + _md5_process(mctx->state, mctx->buf);
2216 + data += MD5_BLOCK_SIZE;
2217 + len -= MD5_BLOCK_SIZE;
2221 + _md5_ip5k_get_digest(mctx->state);
2222 + hw_crypto_unlock();
2225 + /* anything left? */
2227 + memcpy(mctx->buf + index , data, len);
2230 +/* Add padding and return the message digest. */
2231 +static void md5_final(struct crypto_tfm *tfm, u8 *out)
2233 + struct ubicom32_md5_ctx *mctx = crypto_tfm_ctx(tfm);
2235 + unsigned int index, end;
2237 + /* must perform manual padding */
2238 + index = mctx->count & 0x3f;
2239 + end = (index < 56) ? MD5_BLOCK_SIZE : (2 * MD5_BLOCK_SIZE);
2241 + /* start pad with 1 */
2242 + mctx->buf[index] = 0x80;
2244 + /* pad with zeros */
2246 + memset(mctx->buf + index, 0x00, end - index - 8);
2248 + /* append message length */
2249 + bits[0] = mctx->count << 3;
2250 + bits[1] = mctx->count >> 29;
2251 + __cpu_to_le32s(bits);
2252 + __cpu_to_le32s(bits + 1);
2254 + memcpy(mctx->buf + end - 8, &bits, sizeof(bits));
2256 + /* force to use the mctx->buf and ignore the partial buf */
2257 + mctx->count = mctx->count & ~0x3f;
2258 + md5_update(tfm, mctx->buf, end);
2260 + /* copy digest to out */
2261 + memcpy(out, mctx->state, MD5_DIGEST_SIZE);
2263 + /* wipe context */
2264 + memset(mctx, 0, sizeof *mctx);
2267 +static struct crypto_alg alg = {
2268 + .cra_name = "md5",
2269 + .cra_driver_name= "md5-ubicom32",
2270 + .cra_priority = CRYPTO_UBICOM32_PRIORITY,
2271 + .cra_flags = CRYPTO_ALG_TYPE_DIGEST,
2272 + .cra_blocksize = MD5_BLOCK_SIZE,
2273 + .cra_ctxsize = sizeof(struct ubicom32_md5_ctx),
2274 + .cra_module = THIS_MODULE,
2275 + .cra_list = LIST_HEAD_INIT(alg.cra_list),
2278 + .dia_digestsize = MD5_DIGEST_SIZE,
2279 + .dia_init = md5_init,
2280 + .dia_update = md5_update,
2281 + .dia_final = md5_final,
2286 +static int __init init(void)
2289 + return crypto_register_alg(&alg);
2292 +static void __exit fini(void)
2294 + crypto_unregister_alg(&alg);
2300 +MODULE_ALIAS("md5");
2302 +MODULE_LICENSE("GPL");
2303 +MODULE_DESCRIPTION("MD5 Secure Hash Algorithm");
2304 diff -ruN linux-2.6.30.10/arch/ubicom32/crypto/sha1_ubicom32_asm.S linux-2.6.30.10-ubi/arch/ubicom32/crypto/sha1_ubicom32_asm.S
2305 --- linux-2.6.30.10/arch/ubicom32/crypto/sha1_ubicom32_asm.S 1970-01-01 02:00:00.000000000 +0200
2306 +++ linux-2.6.30.10-ubi/arch/ubicom32/crypto/sha1_ubicom32_asm.S 2009-12-11 11:45:11.000000000 +0200
2309 + * arch/ubicom32/crypto/sha1_ubicom32_asm.S
2310 + * SHA1 hash support for Ubicom32 architecture V3.
2312 + * (C) Copyright 2009, Ubicom, Inc.
2314 + * This file is part of the Ubicom32 Linux Kernel Port.
2316 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
2317 + * it and/or modify it under the terms of the GNU General Public License
2318 + * as published by the Free Software Foundation, either version 2 of the
2319 + * License, or (at your option) any later version.
2321 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
2322 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
2323 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
2324 + * the GNU General Public License for more details.
2326 + * You should have received a copy of the GNU General Public License
2327 + * along with the Ubicom32 Linux Kernel Port. If not,
2328 + * see <http://www.gnu.org/licenses/>.
2330 + * Ubicom32 implementation derived from (with many thanks):
2337 +#include <asm/ip5000.h>
2343 +;*****************************************************************************************
2344 +; The function prototype
2345 +;*****************************************************************************************
2346 +; void sha1_ip5k_init(void)
2347 +; void sha1_ip5k_transform(u32_t *data_input)
2348 +; void sha1_ip5k_output(u32_t *digest)
2350 +;*****************************************************************************************
2352 +;*****************************************************************************************
2353 +; data_input is the pointer to the block of data over which the digest will be calculated.
2354 +; It should be word aligned.
2356 +; digest is the pointer to the block of data into which the digest (the output) will be written.
2357 +; It should be word aligned.
2360 +;*****************************************************************************************
2362 +;*****************************************************************************************
2365 +;*****************************************************************************************
2367 +;*****************************************************************************************
2368 +#define HASH_SHA1_IN0 0x67452301
2369 +#define HASH_SHA1_IN1 0xefcdab89
2370 +#define HASH_SHA1_IN2 0x98badcfe
2371 +#define HASH_SHA1_IN3 0x10325476
2372 +#define HASH_SHA1_IN4 0xc3d2e1f0
2374 +#define HASH_SECURITY_BLOCK_CONTROL_INIT_NO_ENCYPTION 2
2375 +#define HASH_SECURITY_BLOCK_CONTROL_INIT_SHA1 ((1 << 5) | HASH_SECURITY_BLOCK_CONTROL_INIT_NO_ENCYPTION)
2377 +;*****************************************************************************************
2378 +; An: Address Registers
2379 +;*****************************************************************************************
2380 +#define an_digest a4
2381 +#define an_data_input a4
2382 +#define an_security_block a3
2384 +;*****************************************************************************************
2385 +; Hash related defines
2386 +;*****************************************************************************************
2387 +#define hash_control 0x00(an_security_block)
2388 +#define hash_control_low 0x02(an_security_block)
2389 +#define hash_status 0x04(an_security_block)
2391 +#define hash_input_0 0x30(an_security_block)
2392 +#define hash_input_1 0x34(an_security_block)
2393 +#define hash_input_2 0x38(an_security_block)
2394 +#define hash_input_3 0x3c(an_security_block)
2395 +#define hash_input_4 0x40(an_security_block)
2397 +#define hash_output_0 0x70(an_security_block)
2398 +#define hash_output_0_low 0x72(an_security_block)
2399 +#define hash_output_1 0x74(an_security_block)
2400 +#define hash_output_1_low 0x76(an_security_block)
2401 +#define hash_output_2 0x78(an_security_block)
2402 +#define hash_output_2_low 0x7a(an_security_block)
2403 +#define hash_output_3 0x7c(an_security_block)
2404 +#define hash_output_3_low 0x7e(an_security_block)
2405 +#define hash_output_4 0x80(an_security_block)
2406 +#define hash_output_4_low 0x82(an_security_block)
2408 +;*****************************************************************************************
2410 +;*****************************************************************************************
2411 + ; C compiler reserves RP (A5) for return address during subroutine call.
2412 + ; Use RP to return to caller
2413 +.macro call_return_macro
2417 +;*****************************************************************************************
2418 +; void sha1_ip5k_init(void)
2419 +; initialize the output registers of the hash module
2421 + ;.section .text.sha1_ip5k_init,"ax",@progbits
2422 + .section .ocm_text,"ax",@progbits
2423 + .global _sha1_ip5k_init
2424 + .func sha1_ip5k_init, _sha1_ip5k_init
2427 + moveai an_security_block, #SECURITY_BASE_EFFECTIVE_ADDRESS
2429 + movei hash_control, #%hi(HASH_SECURITY_BLOCK_CONTROL_INIT_SHA1)
2430 + movei hash_control_low, #%lo(HASH_SECURITY_BLOCK_CONTROL_INIT_SHA1)
2432 + movei hash_output_0, #%hi(HASH_SHA1_IN0)
2433 + movei hash_output_0_low, #%lo(HASH_SHA1_IN0)
2435 + movei hash_output_1, #%hi(HASH_SHA1_IN1)
2436 + movei hash_output_1_low, #%lo(HASH_SHA1_IN1)
2438 + movei hash_output_2, #%hi(HASH_SHA1_IN2)
2439 + movei hash_output_2_low, #%lo(HASH_SHA1_IN2)
2441 + movei hash_output_3, #%hi(HASH_SHA1_IN3)
2442 + movei hash_output_3_low, #%lo(HASH_SHA1_IN3)
2444 + movei hash_output_4, #%hi(HASH_SHA1_IN4)
2445 + movei hash_output_4_low, #%lo(HASH_SHA1_IN4)
2450 +;*****************************************************************************************
2451 +; void sha1_ip5k_init_digest(u32_t *hash_input)
2452 +; initialize the output registers of the hash module
2454 + ;.section .text.sha1_ip5k_init_digest,"ax",@progbits
2455 + .section .ocm_text,"ax",@progbits
2456 + .global _sha1_ip5k_init_digest
2457 + .func sha1_ip5k_init_digest, _sha1_ip5k_init_digest
2459 +_sha1_ip5k_init_digest:
2460 + movea an_data_input, D0
2462 + moveai an_security_block, #SECURITY_BASE_EFFECTIVE_ADDRESS
2464 + movei hash_control, #%hi(HASH_SECURITY_BLOCK_CONTROL_INIT_SHA1)
2465 + movei hash_control_low, #%lo(HASH_SECURITY_BLOCK_CONTROL_INIT_SHA1)
2467 + move.4 hash_output_0, (an_data_input)4++
2468 + move.4 hash_output_1, (an_data_input)4++
2469 + move.4 hash_output_2, (an_data_input)4++
2470 + move.4 hash_output_3, (an_data_input)4++
2471 + move.4 hash_output_4, (an_data_input)4++
2476 +;*****************************************************************************************
2477 +; void sha1_ip5k_transform(u32_t *data_input)
2478 +; performs intermediate transformation step for the hash calculation
2480 + ;.section .text.sha1_ip5k_transform,"ax",@progbits
2481 + .section .ocm_text,"ax",@progbits
2482 + .global _sha1_ip5k_transform
2483 + .func sha1_ip5k_transform, _sha1_ip5k_transform
2485 +_sha1_ip5k_transform:
2486 + movea an_data_input, D0
2488 + moveai an_security_block, #SECURITY_BASE_EFFECTIVE_ADDRESS
2490 + ; Write the first 128bits (16 bytes)
2491 + move.4 hash_input_0, (an_data_input)4++
2492 + move.4 hash_input_1, (an_data_input)4++
2493 + move.4 hash_input_2, (an_data_input)4++
2494 + move.4 hash_input_3, (an_data_input)4++
2495 + move.4 hash_input_4, D0
2497 + move.4 hash_input_0, (an_data_input)4++
2498 + move.4 hash_input_1, (an_data_input)4++
2499 + move.4 hash_input_2, (an_data_input)4++
2500 + move.4 hash_input_3, (an_data_input)4++
2501 + move.4 hash_input_4, D0
2503 + move.4 hash_input_0, (an_data_input)4++
2504 + move.4 hash_input_1, (an_data_input)4++
2505 + move.4 hash_input_2, (an_data_input)4++
2506 + move.4 hash_input_3, (an_data_input)4++
2507 + move.4 hash_input_4, D0
2509 + move.4 hash_input_0, (an_data_input)4++
2510 + move.4 hash_input_1, (an_data_input)4++
2511 + move.4 hash_input_2, (an_data_input)4++
2512 + move.4 hash_input_3, (an_data_input)4++
2513 + move.4 hash_input_4, D0
2517 +sha1_ip5k_transform_wait:
2518 + ; wait for the module to calculate the output hash
2519 + btst hash_status, #0
2520 + jmpne.f sha1_ip5k_transform_wait
2525 +;*****************************************************************************************
2526 +; void sha1_ip5k_output(u32_t *digest)
2527 +; Return the hash of the input data
2529 + ;.section .text.sha1_ip5k_output,"ax",@progbits
2530 + .section .ocm_text,"ax",@progbits
2531 + .global _sha1_ip5k_output
2532 + .func sha1_ip5k_output, _sha1_ip5k_output
2535 + movea an_digest, D0
2537 + moveai an_security_block, #SECURITY_BASE_EFFECTIVE_ADDRESS
2539 + ; we have finished
2540 + move.4 0(an_digest), hash_output_0
2541 + move.4 4(an_digest), hash_output_1
2542 + move.4 8(an_digest), hash_output_2
2543 + move.4 12(an_digest), hash_output_3
2544 + move.4 16(an_digest), hash_output_4
2549 +;*****************************************************************************************
2550 +;END ;End of program code
2551 +;*****************************************************************************************
2552 diff -ruN linux-2.6.30.10/arch/ubicom32/crypto/sha1_ubicom32.c linux-2.6.30.10-ubi/arch/ubicom32/crypto/sha1_ubicom32.c
2553 --- linux-2.6.30.10/arch/ubicom32/crypto/sha1_ubicom32.c 1970-01-01 02:00:00.000000000 +0200
2554 +++ linux-2.6.30.10-ubi/arch/ubicom32/crypto/sha1_ubicom32.c 2009-12-11 11:45:11.000000000 +0200
2557 + * arch/ubicom32/crypto/sha1_ubicom32.c
2558 + * Ubicom32 implementation of the SHA1 Secure Hash Algorithm.
2560 + * (C) Copyright 2009, Ubicom, Inc.
2562 + * This file is part of the Ubicom32 Linux Kernel Port.
2564 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
2565 + * it and/or modify it under the terms of the GNU General Public License
2566 + * as published by the Free Software Foundation, either version 2 of the
2567 + * License, or (at your option) any later version.
2569 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
2570 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
2571 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
2572 + * the GNU General Public License for more details.
2574 + * You should have received a copy of the GNU General Public License
2575 + * along with the Ubicom32 Linux Kernel Port. If not,
2576 + * see <http://www.gnu.org/licenses/>.
2578 + * Ubicom32 implementation derived from (with many thanks):
2583 +#include <linux/init.h>
2584 +#include <linux/module.h>
2585 +#include <linux/crypto.h>
2586 +#include <crypto/sha.h>
2587 +#include <asm/linkage.h>
2589 +#include "crypto_ubicom32.h"
2590 +#define HASH_SECURITY_BLOCK_CONTROL_INIT_NO_ENCYPTION 2
2591 +#define HASH_SECURITY_BLOCK_CONTROL_INIT_SHA1 ((1 << 5) | HASH_SECURITY_BLOCK_CONTROL_INIT_NO_ENCYPTION)
2593 +struct ubicom32_sha1_ctx {
2594 + u64 count; /* message length */
2596 + u8 buf[2 * SHA1_BLOCK_SIZE];
2599 +static inline void sha1_clear_2ws(u8 *buf, int wc)
2602 + "1: move.4 (%0)4++, #0 \n\t"
2603 + " move.4 (%0)4++, #0 \n\t"
2604 + " sub.4 %1, #2, %1 \n\t"
2605 + " jmple.f 1b \n\t"
2607 + : "a" (buf), "d" (wc)
2612 +/* only wipe out count, state, and 1st half of buf - 9 bytes at most */
2613 +#define sha1_wipe_out(sctx) sha1_clear_2ws((u8 *)sctx, 2 + 5 + 16 - 2)
2615 +static inline void sha1_init_digest(u32 *digest)
2617 + hw_crypto_set_ctrl(HASH_SECURITY_BLOCK_CONTROL_INIT_SHA1);
2619 + " ; move digests to hash_output regs \n\t"
2620 + " move.4 0x70(%0), 0x0(%1) \n\t"
2621 + " move.4 0x74(%0), 0x4(%1) \n\t"
2622 + " move.4 0x78(%0), 0x8(%1) \n\t"
2623 + " move.4 0x7c(%0), 0xc(%1) \n\t"
2624 + " move.4 0x80(%0), 0x10(%1) \n\t"
2626 + : "a" (SEC_BASE), "a" (digest)
2630 +static inline void sha1_transform_feed(const u8 *in)
2633 + " ; write the 1st 16 bytes \n\t"
2634 + " move.4 0x30(%0), 0x0(%1) \n\t"
2635 + " move.4 0x34(%0), 0x4(%1) \n\t"
2636 + " move.4 0x38(%0), 0x8(%1) \n\t"
2637 + " move.4 0x3c(%0), 0xc(%1) \n\t"
2638 + " move.4 0x40(%0), %1 \n\t"
2639 + " ; write the 2nd 16 bytes \n\t"
2640 + " move.4 0x30(%0), 0x10(%1) \n\t"
2641 + " move.4 0x34(%0), 0x14(%1) \n\t"
2642 + " move.4 0x38(%0), 0x18(%1) \n\t"
2643 + " move.4 0x3c(%0), 0x1c(%1) \n\t"
2644 + " move.4 0x40(%0), %1 \n\t"
2645 + " ; write the 3rd 16 bytes \n\t"
2646 + " move.4 0x30(%0), 0x20(%1) \n\t"
2647 + " move.4 0x34(%0), 0x24(%1) \n\t"
2648 + " move.4 0x38(%0), 0x28(%1) \n\t"
2649 + " move.4 0x3c(%0), 0x2c(%1) \n\t"
2650 + " move.4 0x40(%0), %1 \n\t"
2651 + " ; write the 4th 16 bytes \n\t"
2652 + " move.4 0x30(%0), 0x30(%1) \n\t"
2653 + " move.4 0x34(%0), 0x34(%1) \n\t"
2654 + " move.4 0x38(%0), 0x38(%1) \n\t"
2655 + " move.4 0x3c(%0), 0x3c(%1) \n\t"
2656 + " move.4 0x40(%0), %1 \n\t"
2657 + " pipe_flush 0 \n\t"
2659 + : "a"(SEC_BASE), "a"(in)
2663 +static inline void sha1_transform_wait(void)
2666 + " btst 0x04(%0), #0 \n\t"
2667 + " jmpne.f -4 \n\t"
2674 +static inline void sha1_output_digest(u32 *digest)
2677 + " move.4 0x0(%1), 0x70(%0) \n\t"
2678 + " move.4 0x4(%1), 0x74(%0) \n\t"
2679 + " move.4 0x8(%1), 0x78(%0) \n\t"
2680 + " move.4 0xc(%1), 0x7c(%0) \n\t"
2681 + " move.4 0x10(%1), 0x80(%0) \n\t"
2683 + : "a" (SEC_BASE), "a" (digest)
2687 +static __ocm_text void sha1_init(struct crypto_tfm *tfm)
2689 + struct ubicom32_sha1_ctx *sctx = crypto_tfm_ctx(tfm);
2691 + sctx->state[0] = SHA1_H0;
2692 + sctx->state[1] = SHA1_H1;
2693 + sctx->state[2] = SHA1_H2;
2694 + sctx->state[3] = SHA1_H3;
2695 + sctx->state[4] = SHA1_H4;
2699 +static void __ocm_text sha1_update(struct crypto_tfm *tfm, const u8 *data,
2702 + struct ubicom32_sha1_ctx *sctx = crypto_tfm_ctx(tfm);
2705 + /* how much is already in the buffer? */
2706 + index = sctx->count & 0x3f;
2708 + sctx->count += len;
2710 + if (index + len < SHA1_BLOCK_SIZE) {
2715 + hw_crypto_check();
2717 + /* init digest set ctrl register too */
2718 + sha1_init_digest(sctx->state);
2720 + if (unlikely(index == 0 && SEC_ALIGNED(data))) {
2722 +#if CRYPTO_UBICOM32_LOOP_ASM
2723 + if (likely(len >= SHA1_BLOCK_SIZE)) {
2724 + register unsigned int cnt = len >> 6; // loop = len / 64;
2725 + sha1_transform_feed(data);
2726 + data += SHA1_BLOCK_SIZE;
2728 + /* cnt is pre-decremented in the loop */
2730 + "; while (--loop): work on 2nd block \n\t"
2731 + "1: add.4 %2, #-1, %2 \n\t"
2732 + " jmpeq.f 5f \n\t"
2734 + " ; write the 1st 16 bytes \n\t"
2735 + " move.4 0x30(%1), (%0)4++ \n\t"
2736 + " move.4 0x34(%1), (%0)4++ \n\t"
2737 + " move.4 0x38(%1), (%0)4++ \n\t"
2738 + " move.4 0x3c(%1), (%0)4++ \n\t"
2739 + " ; can not kick off hw before it \n\t"
2740 + " ; is done with the prev block \n\t"
2742 + " btst 0x04(%1), #0 \n\t"
2743 + " jmpne.f -4 \n\t"
2745 + " ; tell hw to load 1st 16 bytes \n\t"
2746 + " move.4 0x40(%1), %2 \n\t"
2748 + " ; write the 2nd 16 bytes \n\t"
2749 + " move.4 0x30(%1), (%0)4++ \n\t"
2750 + " move.4 0x34(%1), (%0)4++ \n\t"
2751 + " move.4 0x38(%1), (%0)4++ \n\t"
2752 + " move.4 0x3c(%1), (%0)4++ \n\t"
2753 + " move.4 0x40(%1), %2 \n\t"
2755 + " ; write the 3rd 16 bytes \n\t"
2756 + " move.4 0x30(%1), (%0)4++ \n\t"
2757 + " move.4 0x34(%1), (%0)4++ \n\t"
2758 + " move.4 0x38(%1), (%0)4++ \n\t"
2759 + " move.4 0x3c(%1), (%0)4++ \n\t"
2760 + " move.4 0x40(%1), %2 \n\t"
2762 + " ; write the 4th 16 bytes \n\t"
2763 + " move.4 0x30(%1), (%0)4++ \n\t"
2764 + " move.4 0x34(%1), (%0)4++ \n\t"
2765 + " move.4 0x38(%1), (%0)4++ \n\t"
2766 + " move.4 0x3c(%1), (%0)4++ \n\t"
2767 + " move.4 0x40(%1), %2 \n\t"
2769 + "; no need flush, enough insts \n\t"
2770 + "; before next hw wait \n\t"
2772 + "; go back to loop \n\t"
2775 + "; wait hw for last block \n\t"
2776 + "5: btst 0x04(%1), #0 \n\t"
2777 + " jmpne.f -4 \n\t"
2780 + : "a"( SEC_BASE), "d" (cnt)
2784 + len = len & (64 - 1);
2787 + while (likely(len >= SHA1_BLOCK_SIZE)) {
2788 + sha1_transform_feed(data);
2789 + data += SHA1_BLOCK_SIZE;
2790 + len -= SHA1_BLOCK_SIZE;
2791 + sha1_transform_wait();
2797 + /* process one stored block */
2799 + clen = SHA1_BLOCK_SIZE - index;
2800 + memcpy(sctx->buf + index, data, clen);
2801 + sha1_transform_feed(sctx->buf);
2805 + sha1_transform_wait();
2808 + if (likely(SEC_ALIGNED(data))) {
2809 + goto fast_process;
2812 + /* process as many blocks as possible */
2813 + if (likely(len >= SHA1_BLOCK_SIZE)) {
2814 + memcpy(sctx->buf, data, SHA1_BLOCK_SIZE);
2816 + sha1_transform_feed(sctx->buf);
2817 + data += SHA1_BLOCK_SIZE;
2818 + len -= SHA1_BLOCK_SIZE;
2819 + if (likely(len >= SHA1_BLOCK_SIZE)) {
2820 + memcpy(sctx->buf, data, SHA1_BLOCK_SIZE);
2821 + sha1_transform_wait();
2824 + /* it is the last block */
2825 + sha1_transform_wait();
2831 + sha1_output_digest(sctx->state);
2832 + hw_crypto_unlock();
2835 + /* anything left? */
2837 + memcpy(sctx->buf + index , data, len);
2840 +/* Add padding and return the message digest. */
2841 +static void __ocm_text sha1_final(struct crypto_tfm *tfm, u8 *out)
2843 + struct ubicom32_sha1_ctx *sctx = crypto_tfm_ctx(tfm);
2845 + unsigned int index, end;
2847 + /* must perform manual padding */
2848 + index = sctx->count & 0x3f;
2849 + end = (index < 56) ? SHA1_BLOCK_SIZE : (2 * SHA1_BLOCK_SIZE);
2851 + /* start pad with 1 */
2852 + sctx->buf[index] = 0x80;
2854 + /* pad with zeros */
2856 + memset(sctx->buf + index, 0x00, end - index - 8);
2858 + /* append message length */
2859 + bits = sctx->count << 3 ;
2860 + SEC_COPY_2W(sctx->buf + end - 8, &bits);
2862 + /* force to use the sctx->buf and ignore the partial buf */
2863 + sctx->count = sctx->count & ~0x3f;
2864 + sha1_update(tfm, sctx->buf, end);
2866 + /* copy digest to out */
2867 + SEC_COPY_5W(out, sctx->state);
2869 + /* wipe context */
2870 + sha1_wipe_out(sctx);
2873 +static struct crypto_alg alg = {
2874 + .cra_name = "sha1",
2875 + .cra_driver_name= "sha1-ubicom32",
2876 + .cra_priority = CRYPTO_UBICOM32_PRIORITY,
2877 + .cra_flags = CRYPTO_ALG_TYPE_DIGEST,
2878 + .cra_blocksize = SHA1_BLOCK_SIZE,
2879 + .cra_ctxsize = sizeof(struct ubicom32_sha1_ctx),
2880 + .cra_module = THIS_MODULE,
2881 + .cra_list = LIST_HEAD_INIT(alg.cra_list),
2884 + .dia_digestsize = SHA1_DIGEST_SIZE,
2885 + .dia_init = sha1_init,
2886 + .dia_update = sha1_update,
2887 + .dia_final = sha1_final,
2892 +static int __init init(void)
2895 + return crypto_register_alg(&alg);
2898 +static void __exit fini(void)
2900 + crypto_unregister_alg(&alg);
2906 +MODULE_ALIAS("sha1");
2908 +MODULE_LICENSE("GPL");
2909 +MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm");
2910 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/a.out.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/a.out.h
2911 --- linux-2.6.30.10/arch/ubicom32/include/asm/a.out.h 1970-01-01 02:00:00.000000000 +0200
2912 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/a.out.h 2009-12-11 11:45:11.000000000 +0200
2915 + * arch/ubicom32/include/asm/a.out.h
2916 + * Definitions for Ubicom32 a.out executable format.
2918 + * (C) Copyright 2009, Ubicom, Inc.
2920 + * This file is part of the Ubicom32 Linux Kernel Port.
2922 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
2923 + * it and/or modify it under the terms of the GNU General Public License
2924 + * as published by the Free Software Foundation, either version 2 of the
2925 + * License, or (at your option) any later version.
2927 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
2928 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
2929 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
2930 + * the GNU General Public License for more details.
2932 + * You should have received a copy of the GNU General Public License
2933 + * along with the Ubicom32 Linux Kernel Port. If not,
2934 + * see <http://www.gnu.org/licenses/>.
2936 + * Ubicom32 implementation derived from (with many thanks):
2941 +#ifndef _ASM_UBICOM32_A_OUT_H
2942 +#define _ASM_UBICOM32_A_OUT_H
2946 + unsigned long a_info; /* Use macros N_MAGIC, etc for access */
2947 + unsigned a_text; /* length of text, in bytes */
2948 + unsigned a_data; /* length of data, in bytes */
2949 + unsigned a_bss; /* length of uninitialized data area for file, in bytes */
2950 + unsigned a_syms; /* length of symbol table data in file, in bytes */
2951 + unsigned a_entry; /* start address */
2952 + unsigned a_trsize; /* length of relocation info for text, in bytes */
2953 + unsigned a_drsize; /* length of relocation info for data, in bytes */
2956 +#define N_TRSIZE(a) ((a).a_trsize)
2957 +#define N_DRSIZE(a) ((a).a_drsize)
2958 +#define N_SYMSIZE(a) ((a).a_syms)
2960 +#endif /* _ASM_UBICOM32_A_OUT_H */
2961 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/atomic.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/atomic.h
2962 --- linux-2.6.30.10/arch/ubicom32/include/asm/atomic.h 1970-01-01 02:00:00.000000000 +0200
2963 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/atomic.h 2009-12-11 11:45:11.000000000 +0200
2966 + * arch/ubicom32/include/asm/atomic.h
2967 + * Atomic operations definitions for Ubicom32 architecture.
2969 + * (C) Copyright 2009, Ubicom, Inc.
2971 + * This file is part of the Ubicom32 Linux Kernel Port.
2973 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
2974 + * it and/or modify it under the terms of the GNU General Public License
2975 + * as published by the Free Software Foundation, either version 2 of the
2976 + * License, or (at your option) any later version.
2978 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
2979 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
2980 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
2981 + * the GNU General Public License for more details.
2983 + * You should have received a copy of the GNU General Public License
2984 + * along with the Ubicom32 Linux Kernel Port. If not,
2985 + * see <http://www.gnu.org/licenses/>.
2987 + * Ubicom32 implementation derived from (with many thanks):
2992 +#ifndef _ASM_UBICOM32_ATOMIC_H
2993 +#define _ASM_UBICOM32_ATOMIC_H
2995 +#include <asm/system.h>
2996 +#include <asm/ubicom32-common.h>
2997 +#include <asm/types.h>
3000 + * Most instructions on the Ubicom32 processor are atomic in that they
3001 + * execute in one clock cycle. However, Linux has several operations
3002 + * (e.g. compare and swap) which will require more than a single instruction
3003 + * to perform. To achieve this, the Ubicom32 processor uses a single
3004 + * global bit in a scratchpad register as a critical section lock. All
3005 + * atomic operations acquire this lock.
3007 + * NOTE: To AVOID DEADLOCK(s), the atomic lock must only be used for atomic
3008 + * operations or by the ldsr to avoid disabling a thread performing an atomic
3011 + * Do not attempt to disable interrupts while holding the atomic operations
3012 + * lock or you will DEADLOCK the system.
3015 +#define ATOMIC_INIT(i) { (i) }
3019 + * Add i to v and return the result.
3021 +static inline void __atomic_add(int i, atomic_t *v)
3025 + __atomic_lock_acquire();
3027 + __atomic_lock_release();
3032 + * Subtract i from v and return the result.
3034 +static inline void __atomic_sub(int i, atomic_t *v)
3038 + __atomic_lock_acquire();
3040 + __atomic_lock_release();
3044 + * __atomic_add_return()
3045 + * Add i to v and return the result.
3047 + * The implementation here looks rather odd because we appear to be doing
3048 + * the addition twice. In fact that's exactly what we're doing but with
3049 + * the ubicom32 instruction set we can do the inner load and add with two
3050 + * instructions whereas generating both the atomic result and the "ret"
3051 + * result requires three instructions. The second add is generally only as
3052 + * costly as a move instruction and in cases where we compare the result
3053 + * with a constant the compiler can fold two constant values and do a
3054 + * single instruction, thus saving an instruction overall!
3056 + * At the worst we save one instruction inside the atomic lock.
3058 +static inline int __atomic_add_return(int i, atomic_t *v)
3063 + __atomic_lock_acquire();
3064 + ret = vt->counter;
3065 + vt->counter = ret + i;
3066 + __atomic_lock_release();
3072 + * __atomic_sub_return()
3073 + * Subtract i from v and return the result.
3075 + * The implementation here looks rather odd because we appear to be doing
3076 + * the subtraction twice. In fact that's exactly what we're doing but with
3077 + * the ubicom32 instruction set we can do the inner load and sub with two
3078 + * instructions whereas generating both the atomic result and the "ret"
3079 + * result requires three instructions. The second sub is generally only as
3080 + * costly as a move instruction and in cases where we compare the result
3081 + * with a constant the compiler can fold two constant values and do a
3082 + * single instruction, thus saving an instruction overall!
3084 + * At the worst we save one instruction inside the atomic lock.
3086 +static inline int __atomic_sub_return(int i, atomic_t *v)
3091 + __atomic_lock_acquire();
3092 + ret = vt->counter;
3093 + vt->counter = ret - i;
3094 + __atomic_lock_release();
3100 + * PUBLIC API FOR ATOMIC!
3102 +#define atomic_add(i,v) (__atomic_add( ((int)i),(v)))
3103 +#define atomic_sub(i,v) (__atomic_sub( ((int)i),(v)))
3104 +#define atomic_inc(v) (__atomic_add( 1,(v)))
3105 +#define atomic_dec(v) (__atomic_sub( 1,(v)))
3106 +#define atomic_add_return(i,v) (__atomic_add_return( ((int)i),(v)))
3107 +#define atomic_sub_return(i,v) (__atomic_sub_return( ((int)i),(v)))
3108 +#define atomic_inc_return(v) (__atomic_add_return( 1,(v)))
3109 +#define atomic_dec_return(v) (__atomic_sub_return( 1,(v)))
3110 +#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0)
3111 +#define atomic_dec_and_test(v) (atomic_dec_return(v) == 0)
3112 +#define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0)
3113 +#define atomic_sub_and_test(i,v) (atomic_sub_return((i),(v)) == 0)
3117 + * Acquire the atomic lock and read the variable.
3119 +static inline int atomic_read(const atomic_t *v)
3122 + const atomic_t *vt = v;
3124 + __atomic_lock_acquire();
3125 + ret = vt->counter;
3126 + __atomic_lock_release();
3133 + * Acquire the atomic lock and set the variable.
3135 +static inline void atomic_set(atomic_t *v, int i)
3139 + __atomic_lock_acquire();
3141 + __atomic_lock_release();
3146 + * Acquire the atomic lock and exchange if current == old.
3148 +static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
3153 + __atomic_lock_acquire();
3154 + prev = vt->counter;
3155 + if (prev == old) {
3156 + vt->counter = new;
3158 + __atomic_lock_release();
3165 + * Acquire the atomic lock and exchange values.
3167 +static inline int atomic_xchg(atomic_t *v, int new)
3172 + __atomic_lock_acquire();
3173 + prev = vt->counter;
3174 + vt->counter = new;
3175 + __atomic_lock_release();
3181 + * atomic_add_unless()
3182 + * Acquire the atomic lock and add a unless the value is u.
3184 +static inline int atomic_add_unless(atomic_t *v, int a, int u)
3189 + __atomic_lock_acquire();
3190 + prev = vt->counter;
3193 + __atomic_lock_release();
3197 + __atomic_lock_release();
3201 +#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
3203 +#include <asm-generic/atomic.h>
3206 + * The following is not a real function. The compiler should remove the function
3207 + * call as long as the user does not pass in a size that __xchg and __cmpxchg
3208 + * are not prepared for. If the user does pass in an unknown size, the user
3209 + * will get a link time error.
3211 + * The no return is to prevent a compiler error that can occur when dealing with
3212 + * uninitialized variables. Given that the function doesn't exist there is no
3213 + * net effect (and if it did it would not return).
3215 +extern void __xchg_called_with_bad_pointer(void) __attribute__((noreturn));
3219 + * Xchange *ptr for x atomically.
3221 + * Must be both locally atomic and atomic on SMP. Ubicom32 does not have an
3222 + * atomic exchange instruction so we use the global atomic_lock.
3224 +static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
3226 + unsigned long ret;
3228 + __atomic_lock_acquire();
3232 + ret = *(volatile unsigned char *)ptr;
3233 + *(volatile unsigned char *)ptr = x;
3237 + ret = *(volatile unsigned short *)ptr;
3238 + *(volatile unsigned short *)ptr = x;
3242 + ret = *(volatile unsigned int *)ptr;
3243 + *(volatile unsigned int *)ptr = x;
3247 + __xchg_called_with_bad_pointer();
3250 + __atomic_lock_release();
3254 +#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
3258 + * Compare and Xchange *ptr for x atomically.
3260 + * Must be both locally atomic and atomic on SMP. Ubicom32 does not have an
3261 + * atomic exchange instruction so we use the global atomic_lock.
3263 +static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, unsigned long next, int size)
3265 + unsigned long prev;
3267 + __atomic_lock_acquire();
3270 + prev = *(u8 *)ptr;
3271 + if (prev == old) {
3272 + *(u8 *)ptr = (u8)next;
3277 + prev = *(u16 *)ptr;
3278 + if (prev == old) {
3279 + *(u16 *)ptr = (u16)next;
3284 + prev = *(u32 *)ptr;
3285 + if (prev == old) {
3286 + *(u32 *)ptr = (u32)next;
3291 + __xchg_called_with_bad_pointer();
3294 + __atomic_lock_release();
3299 + * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
3302 +#define cmpxchg_local(ptr, o, n) \
3303 + ((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o), (unsigned long)(n), sizeof(*(ptr))))
3305 +#define cmpxchg(ptr, o, n) __cmpxchg((ptr), (o), (n), sizeof(*(ptr)))
3307 +#define smp_mb__before_atomic_inc() asm volatile ("" : : : "memory")
3308 +#define smp_mb__after_atomic_inc() asm volatile ("" : : : "memory")
3309 +#define smp_mb__before_atomic_dec() asm volatile ("" : : : "memory")
3310 +#define smp_mb__after_atomic_dec() asm volatile ("" : : : "memory")
3312 +#endif /* _ASM_UBICOM32_ATOMIC_H */
3313 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/audio.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/audio.h
3314 --- linux-2.6.30.10/arch/ubicom32/include/asm/audio.h 1970-01-01 02:00:00.000000000 +0200
3315 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/audio.h 2009-12-11 11:45:11.000000000 +0200
3318 + * arch/ubicom32/include/asm/audio.h
3319 + * Audio include file
3321 + * (C) Copyright 2009, Ubicom, Inc.
3323 + * This file is part of the Ubicom32 Linux Kernel Port.
3325 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
3326 + * it and/or modify it under the terms of the GNU General Public License
3327 + * as published by the Free Software Foundation, either version 2 of the
3328 + * License, or (at your option) any later version.
3330 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
3331 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
3332 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
3333 + * the GNU General Public License for more details.
3335 + * You should have received a copy of the GNU General Public License
3336 + * along with the Ubicom32 Linux Kernel Port. If not,
3337 + * see <http://www.gnu.org/licenses/>.
3343 +#include <asm/devtree.h>
3344 +#include <asm/audionode.h>
3347 + * Resource indices used to access IRQs via platform_get_resource
3349 +#define AUDIO_MEM_RESOURCE 0
3350 +#define AUDIO_TX_IRQ_RESOURCE 0
3351 +#define AUDIO_RX_IRQ_RESOURCE 1
3353 +extern struct platform_device * __init audio_device_alloc(const char *driver_name, const char *node_name, const char *inst_name, int priv_size);
3355 +#define audio_device_priv(pdev) (((struct ubi32pcm_platform_data *)(((struct platform_device *)(pdev))->dev.platform_data))->priv_data)
3357 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/audionode.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/audionode.h
3358 --- linux-2.6.30.10/arch/ubicom32/include/asm/audionode.h 1970-01-01 02:00:00.000000000 +0200
3359 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/audionode.h 2009-12-11 11:45:11.000000000 +0200
3363 + * audionode and DMA descriptors
3365 + * Copyright
\81© 2009 Ubicom Inc. <www.ubicom.com>. All rights reserved.
3367 + * This file contains confidential information of Ubicom, Inc. and your use of
3368 + * this file is subject to the Ubicom Software License Agreement distributed with
3369 + * this file. If you are uncertain whether you are an authorized user or to report
3370 + * any unauthorized use, please contact Ubicom, Inc. at +1-408-789-2200.
3371 + * Unauthorized reproduction or distribution of this file is subject to civil and
3372 + * criminal penalties.
3375 +#ifndef _AUDIONODE_H_
3376 +#define _AUDIONODE_H_
3378 +#define AUDIO_INT_FLAG_MORE_SAMPLES 0x00000001
3379 +#define AUDIO_INT_FLAG_COMMAND 0x00000002
3382 + * Commands the Primary OS sends to the audio device
3384 +enum audio_command {
3394 + AUDIO_CMD_DISABLE,
3398 + * Flag bits passed in the registers
3400 +#define CMD_START_FLAG_LE (1 << 0) /* Use Little Endian Mode */
3403 + * Status bits that audio device can set to indicate reason
3404 + * for interrupting the Primary OS
3406 +#define AUDIO_STATUS_PLAY_DMA0_REQUEST (1 << 0) /* Audio device needs samples in DMA0 for playback */
3407 +#define AUDIO_STATUS_PLAY_DMA1_REQUEST (1 << 1) /* Audio device needs samples in DMA1 for playback */
3411 + * NOTE: The active flag shall only be SET by the producer and CLEARED
3412 + * by the consumer, NEVER the other way around. For playback, the
3413 + * Primary OS sets this flag and ipAudio clears it.
3415 + * The producer shall not modify the ptr or ctr fields when the transfer
3416 + * is marked as active, as these are used by the consumer to do the
3419 + volatile u32_t active; /* Nonzero if data in ptr/ctr ready to be transferred */
3420 + volatile void *ptr; /* Pointer to data to be transferred */
3421 + volatile u32_t ctr; /* Counter: number of data units to transfer */
3424 +#define AUDIONODE_CAP_BE (1 << 0)
3425 +#define AUDIONODE_CAP_LE (1 << 1)
3427 +#define AUDIONODE_VERSION 7
3428 +struct audio_node {
3429 + struct devtree_node dn;
3432 + * Version of this node
3437 + * Pointer to the registers
3439 + struct audio_regs *regs;
3443 + * [OCM] Audio registers
3444 + * Registers exposed as part of our MMIO area
3446 +#define AUDIO_REGS_VERSION 7
3447 +struct audio_regs {
3449 + * Version of this register set
3454 + * Interrupt status
3456 + volatile u32_t int_status;
3459 + * Interrupt request
3461 + volatile u32_t int_req;
3464 + * Current IRQ being serviced
3469 + * Maximum number of devices supported
3474 + * [DDR] Device registers for each of the devices
3476 + struct audio_dev_regs *adr;
3479 +#define AUDIO_DEV_REGS_VERSION 2
3480 +struct audio_dev_regs {
3481 + u32_t version; /* Version of this register set */
3483 + u8_t name[32]; /* Name of this driver */
3484 + u32_t caps; /* Capabilities of this driver */
3485 + const u32_t *sample_rates; /* Sample Rates supported by this driver */
3486 + u32_t n_sample_rates; /* Number of sample rates supported by this driver */
3487 + u32_t channel_mask; /* A bit set in a particular position means we support this channel configuration */
3488 + volatile u32_t int_flags; /* Reason for interrupting audio device */
3489 + volatile enum audio_command command; /* Command from Primary OS */
3490 + volatile u32_t flags; /* Flag bits for this command */
3491 + volatile u32_t channels; /* Number of channels */
3492 + volatile u32_t sample_rate; /* Sample rate */
3493 + volatile u32_t status; /* Status bits sent from ipAudio to Primary OS */
3494 + void *primary_os_buffer_ptr; /*
3495 + * Playback: Pointer to next sample to be removed from
3496 + * Primary OS sample buffer
3497 + * Capture: Pointer to where next sample will be inserted
3498 + * into Primary OS sample buffer
3502 + * These are the transfer requests. They are used in alternating
3503 + * order so that when ipAudio is processing one request, the
3504 + * Primary OS can fill in the other one.
3506 + * NOTE: The active bit shall always be SET by the producer and
3507 + * CLEARED by the consumer, NEVER the other way around.
3509 + struct audio_dma dma_xfer_requests[2];
3513 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/auxvec.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/auxvec.h
3514 --- linux-2.6.30.10/arch/ubicom32/include/asm/auxvec.h 1970-01-01 02:00:00.000000000 +0200
3515 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/auxvec.h 2009-12-11 11:45:11.000000000 +0200
3518 + * arch/ubicom32/include/asm/auxvec.h
3519 + * Symbolic values for the entries in the auxiliary table
3520 + * put on the initial stack.
3522 + * (C) Copyright 2009, Ubicom, Inc.
3524 + * This file is part of the Ubicom32 Linux Kernel Port.
3526 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
3527 + * it and/or modify it under the terms of the GNU General Public License
3528 + * as published by the Free Software Foundation, either version 2 of the
3529 + * License, or (at your option) any later version.
3531 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
3532 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
3533 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
3534 + * the GNU General Public License for more details.
3536 + * You should have received a copy of the GNU General Public License
3537 + * along with the Ubicom32 Linux Kernel Port. If not,
3538 + * see <http://www.gnu.org/licenses/>.
3540 + * Ubicom32 implementation derived from (with many thanks):
3545 +#ifndef _ASM_UBICOM32_AUXVEC_H
3546 +#define _ASM_UBICOM32_AUXVEC_H
3548 +#endif /* _ASM_UBICOM32_AUXVEC_H */
3549 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/bitops.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/bitops.h
3550 --- linux-2.6.30.10/arch/ubicom32/include/asm/bitops.h 1970-01-01 02:00:00.000000000 +0200
3551 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/bitops.h 2009-12-11 11:45:11.000000000 +0200
3554 + * arch/ubicom32/include/asm/bitops.h
3555 + * Bit manipulation definitions for Ubicom32 architecture.
3557 + * (C) Copyright 2009, Ubicom, Inc.
3559 + * This file is part of the Ubicom32 Linux Kernel Port.
3561 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
3562 + * it and/or modify it under the terms of the GNU General Public License
3563 + * as published by the Free Software Foundation, either version 2 of the
3564 + * License, or (at your option) any later version.
3566 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
3567 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
3568 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
3569 + * the GNU General Public License for more details.
3571 + * You should have received a copy of the GNU General Public License
3572 + * along with the Ubicom32 Linux Kernel Port. If not,
3573 + * see <http://www.gnu.org/licenses/>.
3575 + * Ubicom32 implementation derived from (with many thanks):
3580 +#ifndef _ASM_UBICOM32_BITOPS_H
3581 +#define _ASM_UBICOM32_BITOPS_H
3584 + * Copyright 1992, Linus Torvalds.
3587 +#include <linux/compiler.h>
3588 +#include <asm/byteorder.h> /* swab32 */
3592 +#ifndef _LINUX_BITOPS_H
3593 +#error only <linux/bitops.h> can be included directly
3596 +#include <asm-generic/bitops/ffs.h>
3597 +#include <asm-generic/bitops/__ffs.h>
3599 +#include <asm-generic/bitops/sched.h>
3600 +#include <asm-generic/bitops/ffz.h>
3602 +#include <asm/ubicom32-common.h>
3604 +static inline void set_bit(int bit, volatile unsigned long *p)
3606 + unsigned long mask = 1UL << (bit & 31);
3610 + __atomic_lock_acquire();
3612 + __atomic_lock_release();
3615 +static inline void clear_bit(int bit, volatile unsigned long *p)
3617 + unsigned long mask = 1UL << (bit & 31);
3621 + __atomic_lock_acquire();
3623 + __atomic_lock_release();
3627 + * clear_bit() doesn't provide any barrier for the compiler.
3629 +#define smp_mb__before_clear_bit() barrier()
3630 +#define smp_mb__after_clear_bit() barrier()
3632 +static inline void change_bit(int bit, volatile unsigned long *p)
3634 + unsigned long mask = 1UL << (bit & 31);
3638 + __atomic_lock_acquire();
3640 + __atomic_lock_release();
3643 +static inline int test_and_set_bit(int bit, volatile unsigned long *p)
3646 + unsigned long mask = 1UL << (bit & 31);
3650 + __atomic_lock_acquire();
3653 + __atomic_lock_release();
3655 + return res & mask;
3658 +static inline int test_and_clear_bit(int bit, volatile unsigned long *p)
3661 + unsigned long mask = 1UL << (bit & 31);
3665 + __atomic_lock_acquire();
3668 + __atomic_lock_release();
3670 + return res & mask;
3673 +static inline int test_and_change_bit(int bit, volatile unsigned long *p)
3676 + unsigned long mask = 1UL << (bit & 31);
3680 + __atomic_lock_acquire();
3683 + __atomic_lock_release();
3685 + return res & mask;
3688 +#include <asm-generic/bitops/non-atomic.h>
3691 + * This routine doesn't need to be atomic.
3693 +static inline int __constant_test_bit(int nr, const volatile unsigned long *addr)
3695 + return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0;
3698 +static inline int __test_bit(int nr, const volatile unsigned long *addr)
3700 + int * a = (int *) addr;
3704 + mask = 1 << (nr & 0x1f);
3705 + return ((mask & *a) != 0);
3708 +#define test_bit(nr,addr) (__builtin_constant_p(nr) ? __constant_test_bit((nr),(addr)) : __test_bit((nr),(addr)))
3710 +#include <asm-generic/bitops/find.h>
3711 +#include <asm-generic/bitops/hweight.h>
3712 +#include <asm-generic/bitops/lock.h>
3714 +#include <asm-generic/bitops/ext2-non-atomic.h>
3715 +#include <asm-generic/bitops/ext2-atomic.h>
3716 +#include <asm-generic/bitops/minix.h>
3718 +#endif /* __KERNEL__ */
3720 +#include <asm-generic/bitops/fls.h>
3721 +#include <asm-generic/bitops/__fls.h>
3722 +#include <asm-generic/bitops/fls64.h>
3724 +#endif /* _ASM_UBICOM32_BITOPS_H */
3725 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/board.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/board.h
3726 --- linux-2.6.30.10/arch/ubicom32/include/asm/board.h 1970-01-01 02:00:00.000000000 +0200
3727 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/board.h 2009-12-11 11:45:11.000000000 +0200
3730 + * arch/ubicom32/include/asm/board.h
3731 + * Board init and revision definitions for Ubicom32 architecture.
3733 + * (C) Copyright 2009, Ubicom, Inc.
3735 + * This file is part of the Ubicom32 Linux Kernel Port.
3737 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
3738 + * it and/or modify it under the terms of the GNU General Public License
3739 + * as published by the Free Software Foundation, either version 2 of the
3740 + * License, or (at your option) any later version.
3742 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
3743 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
3744 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
3745 + * the GNU General Public License for more details.
3747 + * You should have received a copy of the GNU General Public License
3748 + * along with the Ubicom32 Linux Kernel Port. If not,
3749 + * see <http://www.gnu.org/licenses/>.
3751 + * Ubicom32 implementation derived from (with many thanks):
3756 +#ifndef _ASM_UBICOM32_BOARD_H
3757 +#define _ASM_UBICOM32_BOARD_H
3759 +extern const char *board_get_revision(void);
3760 +extern void __init board_init(void);
3762 +#endif /* _ASM_UBICOM32_BOARD_H */
3763 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/bootargs.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/bootargs.h
3764 --- linux-2.6.30.10/arch/ubicom32/include/asm/bootargs.h 1970-01-01 02:00:00.000000000 +0200
3765 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/bootargs.h 2009-12-11 11:45:11.000000000 +0200
3768 + * arch/ubicom32/include/asm/bootargs.h
3769 + * Kernel command line via the devtree API.
3771 + * (C) Copyright 2009, Ubicom, Inc.
3773 + * This file is part of the Ubicom32 Linux Kernel Port.
3775 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
3776 + * it and/or modify it under the terms of the GNU General Public License
3777 + * as published by the Free Software Foundation, either version 2 of the
3778 + * License, or (at your option) any later version.
3780 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
3781 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
3782 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
3783 + * the GNU General Public License for more details.
3785 + * You should have received a copy of the GNU General Public License
3786 + * along with the Ubicom32 Linux Kernel Port. If not,
3787 + * see <http://www.gnu.org/licenses/>.
3789 + * Ubicom32 implementation derived from (with many thanks):
3794 +#ifndef _ASM_UBICOM32_BOOTARGS_H
3795 +#define _ASM_UBICOM32_BOOTARGS_H
3797 +extern const char *bootargs_get_cmdline(void);
3798 +extern void __init bootargs_init(void);
3800 +#endif /* _ASM_UBICOM32_BOOTARGS_H */
3801 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/bootinfo.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/bootinfo.h
3802 --- linux-2.6.30.10/arch/ubicom32/include/asm/bootinfo.h 1970-01-01 02:00:00.000000000 +0200
3803 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/bootinfo.h 2009-12-11 11:45:11.000000000 +0200
3806 + * arch/ubicom32/include/asm/bootinfo.h
3807 + * Definitions of firmware boot parameters passed to the kernel.
3809 + * (C) Copyright 2009, Ubicom, Inc.
3811 + * This file is part of the Ubicom32 Linux Kernel Port.
3813 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
3814 + * it and/or modify it under the terms of the GNU General Public License
3815 + * as published by the Free Software Foundation, either version 2 of the
3816 + * License, or (at your option) any later version.
3818 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
3819 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
3820 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
3821 + * the GNU General Public License for more details.
3823 + * You should have received a copy of the GNU General Public License
3824 + * along with the Ubicom32 Linux Kernel Port. If not,
3825 + * see <http://www.gnu.org/licenses/>.
3827 + * Ubicom32 implementation derived from (with many thanks):
3833 +#ifndef _ASM_UBICOM32_BOOTINFO_H
3834 +#define _ASM_UBICOM32_BOOTINFO_H
3836 +/* Nothing for ubicom32 */
3838 +#endif /* _ASM_UBICOM32_BOOTINFO_H */
3839 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/bug.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/bug.h
3840 --- linux-2.6.30.10/arch/ubicom32/include/asm/bug.h 1970-01-01 02:00:00.000000000 +0200
3841 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/bug.h 2009-12-11 11:45:11.000000000 +0200
3844 + * arch/ubicom32/include/asm/bug.h
3845 + * Generic bug.h for Ubicom32 architecture.
3847 + * (C) Copyright 2009, Ubicom, Inc.
3849 + * This file is part of the Ubicom32 Linux Kernel Port.
3851 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
3852 + * it and/or modify it under the terms of the GNU General Public License
3853 + * as published by the Free Software Foundation, either version 2 of the
3854 + * License, or (at your option) any later version.
3856 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
3857 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
3858 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
3859 + * the GNU General Public License for more details.
3861 + * You should have received a copy of the GNU General Public License
3862 + * along with the Ubicom32 Linux Kernel Port. If not,
3863 + * see <http://www.gnu.org/licenses/>.
3865 + * Ubicom32 implementation derived from (with many thanks):
3870 +#ifndef _ASM_UBICOM32_BUG_H
3871 +#define _ASM_UBICOM32_BUG_H
3873 +#include <linux/kernel.h>
3874 +#include <asm/thread.h>
3876 +#if defined(CONFIG_BUG) && defined(CONFIG_STOP_ON_BUG)
3880 + * Ubicom specific version of the BUG() macro.
3882 + * This implementation performs a THREAD_STALL stopping all threads before
3883 + * calling panic. This enables a developer to see the "real" state of the
3884 + * machine (since panic alters the system state). We do the printf first
3885 + * because while it is slow, it does not alter system state (like
3888 + * TODO: Implement the trap sequence used by other architectures.
3890 +#define BUG() do { \
3891 + printk("BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \
3899 + * WARN() using printk() for now.
3901 + * TODO: Implement the trap sequence used by other architectures.
3905 + printk("WARN: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \
3910 + * Ubicom specific version of the WARN_ON macro.
3912 + * This implementation performs a printk for the WARN_ON() instead
3913 + * of faulting into the kernel and using report_bug().
3915 + * TODO: Implement the trap sequence used by other architectures.
3917 +#define WARN_ON(x) ({ \
3918 + int __ret_warn_on = !!(x); \
3919 + if (__builtin_constant_p(__ret_warn_on)) { \
3920 + if (__ret_warn_on) \
3923 + if (unlikely(__ret_warn_on)) \
3926 + unlikely(__ret_warn_on); \
3930 +#define HAVE_ARCH_BUG
3931 +#define HAVE_ARCH_WARN_ON
3935 +#include <asm-generic/bug.h>
3937 +#endif /* _ASM_UBICOM32_BUG_H */
3938 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/bugs.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/bugs.h
3939 --- linux-2.6.30.10/arch/ubicom32/include/asm/bugs.h 1970-01-01 02:00:00.000000000 +0200
3940 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/bugs.h 2009-12-11 11:45:11.000000000 +0200
3943 + * arch/ubicom32/include/asm/bugs.h
3944 + * Definition of check_bugs() for Ubicom32 architecture.
3946 + * (C) Copyright 2009, Ubicom, Inc.
3947 + * Copyright (C) 1994 Linus Torvalds
3949 + * This file is part of the Ubicom32 Linux Kernel Port.
3951 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
3952 + * it and/or modify it under the terms of the GNU General Public License
3953 + * as published by the Free Software Foundation, either version 2 of the
3954 + * License, or (at your option) any later version.
3956 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
3957 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
3958 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
3959 + * the GNU General Public License for more details.
3961 + * You should have received a copy of the GNU General Public License
3962 + * along with the Ubicom32 Linux Kernel Port. If not,
3963 + * see <http://www.gnu.org/licenses/>.
3965 + * Ubicom32 implementation derived from (with many thanks):
3972 + * This is included by init/main.c to check for architecture-dependent bugs.
3975 + * void check_bugs(void);
3978 +#ifndef _ASM_UBICOM32_BUGS_H
3979 +#define _ASM_UBICOM32_BUGS_H
3981 +static void check_bugs(void)
3985 +#endif /* _ASM_UBICOM32_BUGS_H */
3986 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/byteorder.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/byteorder.h
3987 --- linux-2.6.30.10/arch/ubicom32/include/asm/byteorder.h 1970-01-01 02:00:00.000000000 +0200
3988 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/byteorder.h 2009-12-11 11:45:11.000000000 +0200
3991 + * arch/ubicom32/include/asm/byteorder.h
3992 + * Byte order swapping utility routines.
3994 + * (C) Copyright 2009, Ubicom, Inc.
3996 + * This file is part of the Ubicom32 Linux Kernel Port.
3998 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
3999 + * it and/or modify it under the terms of the GNU General Public License
4000 + * as published by the Free Software Foundation, either version 2 of the
4001 + * License, or (at your option) any later version.
4003 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4004 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4005 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
4006 + * the GNU General Public License for more details.
4008 + * You should have received a copy of the GNU General Public License
4009 + * along with the Ubicom32 Linux Kernel Port. If not,
4010 + * see <http://www.gnu.org/licenses/>.
4012 + * Ubicom32 implementation derived from (with many thanks):
4017 +#ifndef _ASM_UBICOM32_BYTEORDER_H
4018 +#define _ASM_UBICOM32_BYTEORDER_H
4020 +#include <linux/byteorder/big_endian.h>
4022 +#endif /* _ASM_UBICOM32_BYTEORDER_H */
4023 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/cachectl.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/cachectl.h
4024 --- linux-2.6.30.10/arch/ubicom32/include/asm/cachectl.h 1970-01-01 02:00:00.000000000 +0200
4025 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/cachectl.h 2009-12-11 11:45:11.000000000 +0200
4028 + * arch/ubicom32/include/asm/cachectl.h
4029 + * Ubicom32 cache control definitions.
4031 + * (C) Copyright 2009, Ubicom, Inc.
4033 + * This file is part of the Ubicom32 Linux Kernel Port.
4035 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4036 + * it and/or modify it under the terms of the GNU General Public License
4037 + * as published by the Free Software Foundation, either version 2 of the
4038 + * License, or (at your option) any later version.
4040 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4041 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4042 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
4043 + * the GNU General Public License for more details.
4045 + * You should have received a copy of the GNU General Public License
4046 + * along with the Ubicom32 Linux Kernel Port. If not,
4047 + * see <http://www.gnu.org/licenses/>.
4049 + * Ubicom32 implementation derived from (with many thanks):
4054 +#ifndef _ASM_UBICOM32_CACHECTL_H
4055 +#define _ASM_UBICOM32_CACHECTL_H
4057 +#include <asm/ip5000.h>
4060 + * mem_cache_control()
4061 + * Special cache control operation
4063 +extern void mem_cache_control(unsigned long cc, unsigned long begin_addr, unsigned long end_addr, unsigned long op);
4065 +#endif /* _ASM_UBICOM32_CACHECTL_H */
4066 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/cacheflush.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/cacheflush.h
4067 --- linux-2.6.30.10/arch/ubicom32/include/asm/cacheflush.h 1970-01-01 02:00:00.000000000 +0200
4068 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/cacheflush.h 2009-12-11 11:45:11.000000000 +0200
4071 + * arch/ubicom32/include/asm/cacheflush.h
4072 + * Cache flushing definitions for Ubicom32 architecture.
4074 + * (C) Copyright 2009, Ubicom, Inc.
4076 + * This file is part of the Ubicom32 Linux Kernel Port.
4078 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4079 + * it and/or modify it under the terms of the GNU General Public License
4080 + * as published by the Free Software Foundation, either version 2 of the
4081 + * License, or (at your option) any later version.
4083 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4084 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4085 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
4086 + * the GNU General Public License for more details.
4088 + * You should have received a copy of the GNU General Public License
4089 + * along with the Ubicom32 Linux Kernel Port. If not,
4090 + * see <http://www.gnu.org/licenses/>.
4092 + * Ubicom32 implementation derived from (with many thanks):
4097 +#ifndef _ASM_UBICOM32_CACHEFLUSH_H
4098 +#define _ASM_UBICOM32_CACHEFLUSH_H
4101 + * (C) Copyright 2000-2004, Greg Ungerer <gerg@snapgear.com>
4103 +#include <linux/mm.h>
4104 +#include <asm/cachectl.h>
4105 +#include <asm/ip5000.h>
4107 +#define flush_cache_all() __flush_cache_all()
4108 +#define flush_cache_mm(mm) do { } while (0)
4109 +#define flush_cache_dup_mm(mm) do { } while (0)
4110 +#define flush_cache_range(vma, start, end) __flush_cache_all()
4111 +#define flush_cache_page(vma, vmaddr) do { } while (0)
4112 +#define flush_dcache_page(page) do { } while (0)
4113 +#define flush_dcache_mmap_lock(mapping) do { } while (0)
4114 +#define flush_dcache_mmap_unlock(mapping) do { } while (0)
4116 +#define flush_dcache_range(start, end) \
4118 + /* Flush the data cache and invalidate the I cache. */ \
4119 + mem_cache_control(DCCR_BASE, start, end, CCR_CTRL_FLUSH_ADDR); \
4120 + mem_cache_control(ICCR_BASE, start, end, CCR_CTRL_INV_ADDR); \
4123 +#define flush_icache_range(start, end) \
4125 + /* Flush the data cache and invalidate the I cache. */ \
4126 + mem_cache_control(DCCR_BASE, start, end, CCR_CTRL_FLUSH_ADDR); \
4127 + mem_cache_control(ICCR_BASE, start, end, CCR_CTRL_INV_ADDR); \
4130 +#define flush_icache_page(vma,pg) do { } while (0)
4131 +#define flush_icache_user_range(vma,pg,adr,len) do { } while (0)
4132 +#define flush_cache_vmap(start, end) do { } while (0)
4133 +#define flush_cache_vunmap(start, end) do { } while (0)
4135 +#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
4136 + memcpy(dst, src, len)
4137 +#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
4138 + memcpy(dst, src, len)
4141 + * Cache handling for IP5000
4143 +extern inline void mem_cache_invalidate_all(unsigned long cc)
4145 + if (cc == DCCR_BASE)
4146 + UBICOM32_LOCK(DCCR_LOCK_BIT);
4148 + UBICOM32_LOCK(ICCR_LOCK_BIT);
4151 + " bset "D(CCR_CTRL)"(%0), "D(CCR_CTRL)"(%0), #"D(CCR_CTRL_RESET)" \n\t"
4153 + " bclr "D(CCR_CTRL)"(%0), "D(CCR_CTRL)"(%0), #"D(CCR_CTRL_RESET)" \n\t"
4154 + " pipe_flush 0 \n\t"
4160 + if (cc == DCCR_BASE)
4161 + UBICOM32_UNLOCK(DCCR_LOCK_BIT);
4163 + UBICOM32_UNLOCK(ICCR_LOCK_BIT);
4167 +static inline void __flush_cache_all(void)
4172 + mem_cache_invalidate_all(ICCR_BASE);
4177 + mem_cache_invalidate_all(DCCR_BASE);
4180 +#endif /* _ASM_UBICOM32_CACHEFLUSH_H */
4181 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/cache.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/cache.h
4182 --- linux-2.6.30.10/arch/ubicom32/include/asm/cache.h 1970-01-01 02:00:00.000000000 +0200
4183 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/cache.h 2009-12-11 11:45:11.000000000 +0200
4186 + * arch/ubicom32/include/asm/cache.h
4187 + * Cache line definitions for Ubicom32 architecture.
4189 + * (C) Copyright 2009, Ubicom, Inc.
4191 + * This file is part of the Ubicom32 Linux Kernel Port.
4193 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4194 + * it and/or modify it under the terms of the GNU General Public License
4195 + * as published by the Free Software Foundation, either version 2 of the
4196 + * License, or (at your option) any later version.
4198 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4199 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4200 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
4201 + * the GNU General Public License for more details.
4203 + * You should have received a copy of the GNU General Public License
4204 + * along with the Ubicom32 Linux Kernel Port. If not,
4205 + * see <http://www.gnu.org/licenses/>.
4207 + * Ubicom32 implementation derived from (with many thanks):
4212 +#ifndef _ASM_UBICOM32_CACHE_H
4213 +#define _ASM_UBICOM32_CACHE_H
4216 + * bytes per L1 cache line
4218 +#define L1_CACHE_SHIFT 5
4219 +#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
4221 +#define __cacheline_aligned
4222 +#define ____cacheline_aligned
4224 +#endif /* _ASM_UBICOM32_CACHE_H */
4225 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/checksum.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/checksum.h
4226 --- linux-2.6.30.10/arch/ubicom32/include/asm/checksum.h 1970-01-01 02:00:00.000000000 +0200
4227 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/checksum.h 2009-12-11 11:45:11.000000000 +0200
4230 + * arch/ubicom32/include/asm/checksum.h
4231 + * Checksum utilities for Ubicom32 architecture.
4233 + * (C) Copyright 2009, Ubicom, Inc.
4235 + * This file is part of the Ubicom32 Linux Kernel Port.
4237 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4238 + * it and/or modify it under the terms of the GNU General Public License
4239 + * as published by the Free Software Foundation, either version 2 of the
4240 + * License, or (at your option) any later version.
4242 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4243 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4244 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
4245 + * the GNU General Public License for more details.
4247 + * You should have received a copy of the GNU General Public License
4248 + * along with the Ubicom32 Linux Kernel Port. If not,
4249 + * see <http://www.gnu.org/licenses/>.
4251 + * Ubicom32 implementation derived from (with many thanks):
4256 +#ifndef _ASM_UBICOM32_CHECKSUM_H
4257 +#define _ASM_UBICOM32_CHECKSUM_H
4259 +#include <linux/in6.h>
4262 + * computes the checksum of a memory block at buff, length len,
4263 + * and adds in "sum" (32-bit)
4265 + * returns a 32-bit number suitable for feeding into itself
4266 + * or csum_tcpudp_magic
4268 + * this function must be called with even lengths, except
4269 + * for the last fragment, which may be odd
4271 + * it's best to have buff aligned on a 32-bit boundary
4273 +__wsum csum_partial(const void *buff, int len, __wsum sum);
4276 + * the same as csum_partial, but copies from src while it
4279 + * here even more important to align src and dst on a 32-bit (or even
4280 + * better 64-bit) boundary
4283 +__wsum csum_partial_copy_nocheck(const void *src, void *dst,
4284 + int len, __wsum sum);
4288 + * the same as csum_partial_copy, but copies from user space.
4290 + * here even more important to align src and dst on a 32-bit (or even
4291 + * better 64-bit) boundary
4294 +extern __wsum csum_partial_copy_from_user(const void __user *src,
4295 + void *dst, int len, __wsum sum, int *csum_err);
4297 +__sum16 ip_fast_csum(const void *iph, unsigned int ihl);
4300 + * Fold a partial checksum
4303 +static inline __sum16 csum_fold(__wsum sum)
4306 + " lsr.4 d15, %0, #16 \n\t"
4307 + " bfextu %0, %0, #16 \n\t"
4308 + " add.4 %0, d15, %0 \n\t"
4309 + " lsr.4 d15, %0, #16 \n\t"
4310 + " bfextu %0, %0, #16 \n\t"
4311 + " add.4 %0, d15, %0 \n\t"
4316 + return (__force __sum16)~sum;
4321 + * computes the checksum of the TCP/UDP pseudo-header
4322 + * returns a 16-bit checksum, already complemented
4325 +static inline __wsum
4326 +csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
4327 + unsigned short proto, __wsum sum)
4330 + " add.4 %0, %2, %0 \n\t"
4331 + " addc %0, %3, %0 \n\t"
4332 + " addc %0, %4, %0 \n\t"
4333 + " addc %0, %5, %0 \n\t"
4334 + " addc %0, #0, %0 \n\t"
4336 + : "0"(sum), "r" (saddr), "r" (daddr), "r" (len), "r"(proto)
4341 +static inline __sum16
4342 +csum_tcpudp_magic(__be32 saddr, __be32 daddr, unsigned short len,
4343 + unsigned short proto, __wsum sum)
4345 + return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
4349 + * this routine is used for miscellaneous IP-like checksums, mainly
4352 +extern __sum16 ip_compute_csum(const void *buff, int len);
4354 +#define _HAVE_ARCH_IPV6_CSUM
4356 +static __inline__ __sum16
4357 +csum_ipv6_magic(const struct in6_addr *saddr, const struct in6_addr *daddr,
4358 + __u32 len, unsigned short proto, __wsum sum)
4361 + " add.4 %0, 0(%2), %0 \n\t"
4362 + " addc %0, 4(%2), %0 \n\t"
4363 + " addc %0, 8(%2), %0 \n\t"
4364 + " addc %0, 12(%2), %0 \n\t"
4365 + " addc %0, 0(%3), %0 \n\t"
4366 + " addc %0, 4(%3), %0 \n\t"
4367 + " addc %0, 8(%3), %0 \n\t"
4368 + " addc %0, 12(%3), %0 \n\t"
4369 + " addc %0, %4, %0 \n\t"
4370 + " addc %0, #0, %0 \n\t"
4372 + : "0" (sum), "a" (saddr), "a" (daddr), "d" (len + proto)
4374 + return csum_fold(sum);
4377 +#endif /* _ASM_UBICOM32_CHECKSUM_H */
4378 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/cpu.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/cpu.h
4379 --- linux-2.6.30.10/arch/ubicom32/include/asm/cpu.h 1970-01-01 02:00:00.000000000 +0200
4380 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/cpu.h 2009-12-11 11:45:11.000000000 +0200
4383 + * arch/ubicom32/include/asm/cpu.h
4384 + * CPU definitions for Ubicom32 architecture.
4386 + * (C) Copyright 2009, Ubicom, Inc.
4387 + * Copyright (C) 2004-2005 ARM Ltd.
4389 + * This file is part of the Ubicom32 Linux Kernel Port.
4391 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4392 + * it and/or modify it under the terms of the GNU General Public License
4393 + * as published by the Free Software Foundation, either version 2 of the
4394 + * License, or (at your option) any later version.
4396 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4397 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4398 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
4399 + * the GNU General Public License for more details.
4401 + * You should have received a copy of the GNU General Public License
4402 + * along with the Ubicom32 Linux Kernel Port. If not,
4403 + * see <http://www.gnu.org/licenses/>.
4405 + * Ubicom32 implementation derived from (with many thanks):
4410 +#ifndef _ASM_UBICOM32_CPU_H
4411 +#define _ASM_UBICOM32_CPU_H
4413 +#include <linux/percpu.h>
4415 +struct cpuinfo_ubicom32 {
4416 + unsigned long tid; /* Hardware thread number */
4419 + volatile unsigned long ipi_pending; /* Bit map of operations to execute */
4420 + unsigned long ipi_count; /* Number of IPI(s) taken on this cpu */
4424 +DECLARE_PER_CPU(struct cpuinfo_ubicom32, cpu_data);
4426 +#endif /* _ASM_UBICOM32_CPU_H */
4427 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/cputime.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/cputime.h
4428 --- linux-2.6.30.10/arch/ubicom32/include/asm/cputime.h 1970-01-01 02:00:00.000000000 +0200
4429 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/cputime.h 2009-12-11 11:45:11.000000000 +0200
4432 + * arch/ubicom32/include/asm/cputime.h
4433 + * Generic cputime.h for Ubicom32 architecture.
4435 + * (C) Copyright 2009, Ubicom, Inc.
4437 + * This file is part of the Ubicom32 Linux Kernel Port.
4439 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4440 + * it and/or modify it under the terms of the GNU General Public License
4441 + * as published by the Free Software Foundation, either version 2 of the
4442 + * License, or (at your option) any later version.
4444 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4445 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4446 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
4447 + * the GNU General Public License for more details.
4449 + * You should have received a copy of the GNU General Public License
4450 + * along with the Ubicom32 Linux Kernel Port. If not,
4451 + * see <http://www.gnu.org/licenses/>.
4453 + * Ubicom32 implementation derived from (with many thanks):
4458 +#ifndef _ASM_UBICOM32_CPUTIME_H
4459 +#define _ASM_UBICOM32_CPUTIME_H
4461 +#include <asm-generic/cputime.h>
4463 +#endif /* _ASM_UBICOM32_CPUTIME_H */
4464 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/current.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/current.h
4465 --- linux-2.6.30.10/arch/ubicom32/include/asm/current.h 1970-01-01 02:00:00.000000000 +0200
4466 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/current.h 2009-12-11 11:45:11.000000000 +0200
4469 + * arch/ubicom32/include/asm/current.h
4470 + * Definition of get_current() for Ubicom32 architecture.
4472 + * (C) Copyright 2009, Ubicom, Inc.
4473 + * (C) Copyright 2000, Lineo, David McCullough <davidm@uclinux.org>
4474 + * (C) Copyright 2002, Greg Ungerer (gerg@snapgear.com)
4476 + * This file is part of the Ubicom32 Linux Kernel Port.
4478 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4479 + * it and/or modify it under the terms of the GNU General Public License
4480 + * as published by the Free Software Foundation, either version 2 of the
4481 + * License, or (at your option) any later version.
4483 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4484 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4485 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
4486 + * the GNU General Public License for more details.
4488 + * You should have received a copy of the GNU General Public License
4489 + * along with the Ubicom32 Linux Kernel Port. If not,
4490 + * see <http://www.gnu.org/licenses/>.
4492 + * Ubicom32 implementation derived from (with many thanks):
4497 +#ifndef _ASM_UBICOM32_CURRENT_H
4498 +#define _ASM_UBICOM32_CURRENT_H
4500 +#include <linux/thread_info.h>
4502 +struct task_struct;
4504 +static inline struct task_struct *get_current(void)
4506 + return(current_thread_info()->task);
4509 +#define current get_current()
4511 +#endif /* _ASM_UBICOM32_CURRENT_H */
4512 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/delay.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/delay.h
4513 --- linux-2.6.30.10/arch/ubicom32/include/asm/delay.h 1970-01-01 02:00:00.000000000 +0200
4514 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/delay.h 2009-12-11 11:45:11.000000000 +0200
4517 + * arch/ubicom32/include/asm/delay.h
4518 + * Definition of delay routines for Ubicom32 architecture.
4520 + * (C) Copyright 2009, Ubicom, Inc.
4522 + * This file is part of the Ubicom32 Linux Kernel Port.
4524 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4525 + * it and/or modify it under the terms of the GNU General Public License
4526 + * as published by the Free Software Foundation, either version 2 of the
4527 + * License, or (at your option) any later version.
4529 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4530 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4531 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
4532 + * the GNU General Public License for more details.
4534 + * You should have received a copy of the GNU General Public License
4535 + * along with the Ubicom32 Linux Kernel Port. If not,
4536 + * see <http://www.gnu.org/licenses/>.
4538 + * Ubicom32 implementation derived from (with many thanks):
4543 +#ifndef _ASM_UBICOM32_DELAY_H
4544 +#define _ASM_UBICOM32_DELAY_H
4546 +#include <asm/param.h>
4547 +#include <asm/ip5000.h>
4549 +static inline void __delay(unsigned long loops)
4556 + "1: add.4 %0, #-1, %0 \n\t"
4557 + " jmpne.t 1b \n\t"
4563 + * Ubicom32 processor uses fixed 12MHz external OSC.
4564 + * So we use that as reference to count 12 cycles/us
4567 +extern unsigned long loops_per_jiffy;
4569 +static inline void _udelay(unsigned long usecs)
4571 +#if defined(CONFIG_UBICOM32_V4) || defined(CONFIG_UBICOM32_V3)
4573 + " add.4 d15, 0(%0), %1 \n\t"
4574 + " sub.4 #0, 0(%0), d15 \n\t"
4575 + " jmpmi.w.f .-4 \n\t"
4577 + : "a"(TIMER_BASE + TIMER_MPTVAL), "d"(usecs * (12000000/1000000))
4586 + * Moved the udelay() function into library code, no longer inlined.
4588 +extern void udelay(unsigned long usecs);
4590 +#endif /* _ASM_UBICOM32_DELAY_H */
4591 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/device.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/device.h
4592 --- linux-2.6.30.10/arch/ubicom32/include/asm/device.h 1970-01-01 02:00:00.000000000 +0200
4593 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/device.h 2009-12-11 11:45:11.000000000 +0200
4596 + * arch/ubicom32/include/asm/device.h
4597 + * Generic device.h for Ubicom32 architecture.
4599 + * Used for arch specific extensions to struct device
4601 + * (C) Copyright 2009, Ubicom, Inc.
4603 + * This file is part of the Ubicom32 Linux Kernel Port.
4605 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4606 + * it and/or modify it under the terms of the GNU General Public License
4607 + * as published by the Free Software Foundation, either version 2 of the
4608 + * License, or (at your option) any later version.
4610 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4611 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4612 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
4613 + * the GNU General Public License for more details.
4615 + * You should have received a copy of the GNU General Public License
4616 + * along with the Ubicom32 Linux Kernel Port. If not,
4617 + * see <http://www.gnu.org/licenses/>.
4619 + * Ubicom32 implementation derived from (with many thanks):
4624 +#ifndef _ASM_UBICOM32_DEVICE_H
4625 +#define _ASM_UBICOM32_DEVICE_H
4627 +#include <asm-generic/device.h>
4629 +#endif /* _ASM_UBICOM32_DEVICE_H */
4630 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/devtree.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/devtree.h
4631 --- linux-2.6.30.10/arch/ubicom32/include/asm/devtree.h 1970-01-01 02:00:00.000000000 +0200
4632 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/devtree.h 2009-12-11 11:45:11.000000000 +0200
4635 + * arch/ubicom32/include/asm/devtree.h
4636 + * Device Tree Header File (Shared between ultra and the Host OS)
4638 + * (C) Copyright 2009, Ubicom, Inc.
4640 + * This file is part of the Ubicom32 Linux Kernel Port.
4642 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4643 + * it and/or modify it under the terms of the GNU General Public License
4644 + * as published by the Free Software Foundation, either version 2 of the
4645 + * License, or (at your option) any later version.
4647 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4648 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4649 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
4650 + * the GNU General Public License for more details.
4652 + * You should have received a copy of the GNU General Public License
4653 + * along with the Ubicom32 Linux Kernel Port. If not,
4654 + * see <http://www.gnu.org/licenses/>.
4656 + * Ubicom32 implementation derived from (with many thanks):
4662 +#ifndef _ASM_UBICOM32_DEVTREE_H
4663 +#define _ASM_UBICOM32_DEVTREE_H
4665 +#define DEVTREE_MAX_NAME 32
4666 +#define DEVTREE_IRQ_NONE 0xff
4667 +#define DEVTREE_IRQ_DONTCARE 0xff
4668 +#define DEVTREE_NODE_MAGIC 0x10203040
4670 +struct devtree_node {
4671 + struct devtree_node *next;
4672 + unsigned char sendirq;
4673 + unsigned char recvirq;
4674 + char name[DEVTREE_MAX_NAME];
4675 + unsigned int magic;
4678 +extern struct devtree_node *devtree;
4679 +extern struct devtree_node *devtree_find_by_irq(uint8_t sendirq, uint8_t recvirq);
4680 +extern struct devtree_node *devtree_find_node(const char *str);
4681 +extern struct devtree_node *devtree_find_next(struct devtree_node **cur);
4682 +extern int devtree_irq(struct devtree_node *dn, unsigned char *sendirq, unsigned char *recvirq);
4683 +extern void devtree_print(void);
4685 +#endif /* _ASM_UBICOM32_DEVTREE_H */
4686 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/div64.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/div64.h
4687 --- linux-2.6.30.10/arch/ubicom32/include/asm/div64.h 1970-01-01 02:00:00.000000000 +0200
4688 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/div64.h 2009-12-11 11:45:11.000000000 +0200
4691 + * arch/ubicom32/include/asm/div64.h
4692 + * Generic div64.h for Ubicom32 architecture.
4694 + * (C) Copyright 2009, Ubicom, Inc.
4696 + * This file is part of the Ubicom32 Linux Kernel Port.
4698 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4699 + * it and/or modify it under the terms of the GNU General Public License
4700 + * as published by the Free Software Foundation, either version 2 of the
4701 + * License, or (at your option) any later version.
4703 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4704 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4705 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
4706 + * the GNU General Public License for more details.
4708 + * You should have received a copy of the GNU General Public License
4709 + * along with the Ubicom32 Linux Kernel Port. If not,
4710 + * see <http://www.gnu.org/licenses/>.
4712 + * Ubicom32 implementation derived from (with many thanks):
4717 +#ifndef _ASM_UBICOM32_DIV64_H
4718 +#define _ASM_UBICOM32_DIV64_H
4720 +#include <asm-generic/div64.h>
4722 +#endif /* _ASM_UBICOM32_DIV64_H */
4723 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/dma.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/dma.h
4724 --- linux-2.6.30.10/arch/ubicom32/include/asm/dma.h 1970-01-01 02:00:00.000000000 +0200
4725 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/dma.h 2009-12-11 11:45:11.000000000 +0200
4728 + * arch/ubicom32/include/asm/dma.h
4729 + * DMA definitions for Ubicom32 architecture.
4731 + * (C) Copyright 2009, Ubicom, Inc.
4733 + * This file is part of the Ubicom32 Linux Kernel Port.
4735 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4736 + * it and/or modify it under the terms of the GNU General Public License
4737 + * as published by the Free Software Foundation, either version 2 of the
4738 + * License, or (at your option) any later version.
4740 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4741 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4742 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
4743 + * the GNU General Public License for more details.
4745 + * You should have received a copy of the GNU General Public License
4746 + * along with the Ubicom32 Linux Kernel Port. If not,
4747 + * see <http://www.gnu.org/licenses/>.
4749 + * Ubicom32 implementation derived from (with many thanks):
4754 +#ifndef _ASM_UBICOM32_DMA_H
4755 +#define _ASM_UBICOM32_DMA_H
4757 +/* Nothing so far */
4758 +#define MAX_DMA_ADDRESS 0x00 /* This is quite suspicious */
4760 +#endif /* _ASM_UBICOM32_DMA_H */
4761 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/dma-mapping.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/dma-mapping.h
4762 --- linux-2.6.30.10/arch/ubicom32/include/asm/dma-mapping.h 1970-01-01 02:00:00.000000000 +0200
4763 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/dma-mapping.h 2009-12-11 11:45:11.000000000 +0200
4766 + * arch/ubicom32/include/asm/dma-mapping.h
4767 + * Generic dma-mapping.h for Ubicom32 architecture.
4769 + * (C) Copyright 2009, Ubicom, Inc.
4771 + * This file is part of the Ubicom32 Linux Kernel Port.
4773 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4774 + * it and/or modify it under the terms of the GNU General Public License
4775 + * as published by the Free Software Foundation, either version 2 of the
4776 + * License, or (at your option) any later version.
4778 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4779 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4780 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
4781 + * the GNU General Public License for more details.
4783 + * You should have received a copy of the GNU General Public License
4784 + * along with the Ubicom32 Linux Kernel Port. If not,
4785 + * see <http://www.gnu.org/licenses/>.
4787 + * Ubicom32 implementation derived from (with many thanks):
4792 +#ifndef _ASM_UBICOM32_DMA_MAPPING_H
4793 +#define _ASM_UBICOM32_DMA_MAPPING_H
4795 +#include <linux/scatterlist.h>
4798 +/* we implement the API below in terms of the existing PCI one,
4799 + * so include it */
4800 +#include <linux/pci.h>
4801 +/* need struct page definitions */
4802 +#include <linux/mm.h>
4805 +dma_supported(struct device *dev, u64 mask)
4807 + BUG_ON(dev->bus != &pci_bus_type);
4809 + return pci_dma_supported(to_pci_dev(dev), mask);
4813 +dma_set_mask(struct device *dev, u64 dma_mask)
4815 + BUG_ON(dev->bus != &pci_bus_type);
4817 + return pci_set_dma_mask(to_pci_dev(dev), dma_mask);
4820 +static inline void *
4821 +dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
4824 + BUG_ON(dev->bus != &pci_bus_type);
4826 + return pci_alloc_consistent(to_pci_dev(dev), size, dma_handle);
4830 +dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
4831 + dma_addr_t dma_handle)
4833 + BUG_ON(dev->bus != &pci_bus_type);
4835 + pci_free_consistent(to_pci_dev(dev), size, cpu_addr, dma_handle);
4838 +static inline dma_addr_t
4839 +dma_map_single(struct device *dev, void *cpu_addr, size_t size,
4840 + enum dma_data_direction direction)
4842 + BUG_ON(dev->bus != &pci_bus_type);
4844 + return pci_map_single(to_pci_dev(dev), cpu_addr, size, (int)direction);
4848 +dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
4849 + enum dma_data_direction direction)
4851 + BUG_ON(dev->bus != &pci_bus_type);
4853 + pci_unmap_single(to_pci_dev(dev), dma_addr, size, (int)direction);
4856 +static inline dma_addr_t
4857 +dma_map_page(struct device *dev, struct page *page,
4858 + unsigned long offset, size_t size,
4859 + enum dma_data_direction direction)
4861 + BUG_ON(dev->bus != &pci_bus_type);
4863 + return pci_map_page(to_pci_dev(dev), page, offset, size, (int)direction);
4867 +dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
4868 + enum dma_data_direction direction)
4870 + BUG_ON(dev->bus != &pci_bus_type);
4872 + pci_unmap_page(to_pci_dev(dev), dma_address, size, (int)direction);
4876 +dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
4877 + enum dma_data_direction direction)
4879 + BUG_ON(dev->bus != &pci_bus_type);
4881 + return pci_map_sg(to_pci_dev(dev), sg, nents, (int)direction);
4885 +dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
4886 + enum dma_data_direction direction)
4888 + BUG_ON(dev->bus != &pci_bus_type);
4890 + pci_unmap_sg(to_pci_dev(dev), sg, nhwentries, (int)direction);
4894 +dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
4895 + enum dma_data_direction direction)
4897 + BUG_ON(dev->bus != &pci_bus_type);
4899 + pci_dma_sync_single_for_cpu(to_pci_dev(dev), dma_handle,
4900 + size, (int)direction);
4904 +dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size,
4905 + enum dma_data_direction direction)
4907 + BUG_ON(dev->bus != &pci_bus_type);
4909 + pci_dma_sync_single_for_device(to_pci_dev(dev), dma_handle,
4910 + size, (int)direction);
4914 +dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
4915 + enum dma_data_direction direction)
4917 + BUG_ON(dev->bus != &pci_bus_type);
4919 + pci_dma_sync_sg_for_cpu(to_pci_dev(dev), sg, nelems, (int)direction);
4923 +dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
4924 + enum dma_data_direction direction)
4926 + BUG_ON(dev->bus != &pci_bus_type);
4928 + pci_dma_sync_sg_for_device(to_pci_dev(dev), sg, nelems, (int)direction);
4932 +dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
4934 + return pci_dma_mapping_error(to_pci_dev(dev), dma_addr);
4941 +dma_supported(struct device *dev, u64 mask)
4947 +dma_set_mask(struct device *dev, u64 dma_mask)
4953 +static inline void *
4954 +dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
4962 +dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
4963 + dma_addr_t dma_handle)
4968 +static inline dma_addr_t
4969 +dma_map_single(struct device *dev, void *cpu_addr, size_t size,
4970 + enum dma_data_direction direction)
4977 +dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
4978 + enum dma_data_direction direction)
4983 +static inline dma_addr_t
4984 +dma_map_page(struct device *dev, struct page *page,
4985 + unsigned long offset, size_t size,
4986 + enum dma_data_direction direction)
4993 +dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
4994 + enum dma_data_direction direction)
5000 +dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
5001 + enum dma_data_direction direction)
5008 +dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
5009 + enum dma_data_direction direction)
5015 +dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
5016 + enum dma_data_direction direction)
5022 +dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size,
5023 + enum dma_data_direction direction)
5029 +dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
5030 + enum dma_data_direction direction)
5036 +dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
5037 + enum dma_data_direction direction)
5043 +dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
5050 +/* Now for the API extensions over the pci_ one */
5052 +#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
5053 +#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
5054 +#define dma_is_consistent(d, h) (1)
5057 +dma_get_cache_alignment(void)
5059 + /* no easy way to get cache size on all processors, so return
5060 + * the maximum possible, to be safe */
5061 + return (1 << INTERNODE_CACHE_SHIFT);
5065 +dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
5066 + unsigned long offset, size_t size,
5067 + enum dma_data_direction direction)
5069 + /* just sync everything, that's all the pci API can do */
5070 + dma_sync_single_for_cpu(dev, dma_handle, offset+size, direction);
5074 +dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
5075 + unsigned long offset, size_t size,
5076 + enum dma_data_direction direction)
5078 + /* just sync everything, that's all the pci API can do */
5079 + dma_sync_single_for_device(dev, dma_handle, offset+size, direction);
5083 +dma_cache_sync(struct device *dev, void *vaddr, size_t size,
5084 + enum dma_data_direction direction)
5086 + /* could define this in terms of the dma_cache ... operations,
5087 + * but if you get this on a platform, you should convert the platform
5088 + * to using the generic device DMA API */
5092 +#endif /* _ASM_UBICOM32_DMA_MAPPING_H */
5093 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/elf.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/elf.h
5094 --- linux-2.6.30.10/arch/ubicom32/include/asm/elf.h 1970-01-01 02:00:00.000000000 +0200
5095 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/elf.h 2009-12-11 11:45:11.000000000 +0200
5098 + * arch/ubicom32/include/asm/elf.h
5099 + * Definitions for elf executable format for Ubicom32 architecture.
5101 + * (C) Copyright 2009, Ubicom, Inc.
5103 + * This file is part of the Ubicom32 Linux Kernel Port.
5105 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
5106 + * it and/or modify it under the terms of the GNU General Public License
5107 + * as published by the Free Software Foundation, either version 2 of the
5108 + * License, or (at your option) any later version.
5110 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
5111 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
5112 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
5113 + * the GNU General Public License for more details.
5115 + * You should have received a copy of the GNU General Public License
5116 + * along with the Ubicom32 Linux Kernel Port. If not,
5117 + * see <http://www.gnu.org/licenses/>.
5119 + * Ubicom32 implementation derived from (with many thanks):
5124 +#ifndef _ASM_UBICOM32_ELF_H
5125 +#define _ASM_UBICOM32_ELF_H
5128 + * ELF register definitions..
5131 +#include <asm/ptrace.h>
5132 +#include <asm/user.h>
5135 + * Processor specific flags for the ELF header e_flags field.
5137 +#define EF_UBICOM32_V3 0x00000001 /* -fmarch=ubicom32v3 */
5138 +#define EF_UBICOM32_V4 0x00000002 /* -fmarch=ubicom32v4 */
5139 +#define EF_UBICOM32_PIC 0x80000000 /* -fpic */
5140 +#define EF_UBICOM32_FDPIC 0x40000000 /* -mfdpic */
5143 + * Ubicom32 ELF relocation types
5145 +#define R_UBICOM32_NONE 0
5146 +#define R_UBICOM32_16 1
5147 +#define R_UBICOM32_32 2
5148 +#define R_UBICOM32_LO16 3
5149 +#define R_UBICOM32_HI16 4
5150 +#define R_UBICOM32_21_PCREL 5
5151 +#define R_UBICOM32_24_PCREL 6
5152 +#define R_UBICOM32_HI24 7
5153 +#define R_UBICOM32_LO7_S 8
5154 +#define R_UBICOM32_LO7_2_S 9
5155 +#define R_UBICOM32_LO7_4_S 10
5156 +#define R_UBICOM32_LO7_D 11
5157 +#define R_UBICOM32_LO7_2_D 12
5158 +#define R_UBICOM32_LO7_4_D 13
5159 +#define R_UBICOM32_32_HARVARD 14
5160 +#define R_UBICOM32_LO7_CALLI 15
5161 +#define R_UBICOM32_LO16_CALLI 16
5162 +#define R_UBICOM32_GOT_HI24 17
5163 +#define R_UBICOM32_GOT_LO7_S 18
5164 +#define R_UBICOM32_GOT_LO7_2_S 19
5165 +#define R_UBICOM32_GOT_LO7_4_S 20
5166 +#define R_UBICOM32_GOT_LO7_D 21
5167 +#define R_UBICOM32_GOT_LO7_2_D 22
5168 +#define R_UBICOM32_GOT_LO7_4_D 23
5169 +#define R_UBICOM32_FUNCDESC_GOT_HI24 24
5170 +#define R_UBICOM32_FUNCDESC_GOT_LO7_S 25
5171 +#define R_UBICOM32_FUNCDESC_GOT_LO7_2_S 26
5172 +#define R_UBICOM32_FUNCDESC_GOT_LO7_4_S 27
5173 +#define R_UBICOM32_FUNCDESC_GOT_LO7_D 28
5174 +#define R_UBICOM32_FUNCDESC_GOT_LO7_2_D 29
5175 +#define R_UBICOM32_FUNCDESC_GOT_LO7_4_D 30
5176 +#define R_UBICOM32_GOT_LO7_CALLI 31
5177 +#define R_UBICOM32_FUNCDESC_GOT_LO7_CALLI 32
5178 +#define R_UBICOM32_FUNCDESC_VALUE 33
5179 +#define R_UBICOM32_FUNCDESC 34
5180 +#define R_UBICOM32_GOTOFFSET_LO 35
5181 +#define R_UBICOM32_GOTOFFSET_HI 36
5182 +#define R_UBICOM32_FUNCDESC_GOTOFFSET_LO 37
5183 +#define R_UBICOM32_FUNCDESC_GOTOFFSET_HI 38
5184 +#define R_UBICOM32_GNU_VTINHERIT 200
5185 +#define R_UBICOM32_GNU_VTENTRY 201
5187 +typedef unsigned long elf_greg_t;
5189 +#define ELF_NGREG (sizeof(struct pt_regs) / sizeof(elf_greg_t))
5190 +typedef elf_greg_t elf_gregset_t[ELF_NGREG];
5192 +typedef struct user_ubicom32fp_struct elf_fpregset_t;
5195 + * This is used to ensure we don't load something for the wrong architecture.
5197 +#define elf_check_arch(x) ((x)->e_machine == EM_UBICOM32)
5199 +#define elf_check_fdpic(x) ((x)->e_flags & EF_UBICOM32_FDPIC)
5201 +#define elf_check_const_displacement(x) ((x)->e_flags & EF_UBICOM32_PIC)
5204 + * These are used to set parameters in the core dumps.
5206 +#define ELF_CLASS ELFCLASS32
5207 +#define ELF_DATA ELFDATA2MSB
5208 +#define ELF_ARCH EM_UBICOM32
5210 +/* For SVR4/m68k the function pointer to be registered with `atexit' is
5211 + passed in %a1. Although my copy of the ABI has no such statement, it
5212 + is actually used on ASV. */
5213 +#define ELF_PLAT_INIT(_r, load_addr) _r->a1 = 0
5215 +#define ELF_FDPIC_PLAT_INIT(_regs, _exec_map_addr, _interp_map_addr, \
5218 + _regs->dn[1] = _exec_map_addr; \
5219 + _regs->dn[2] = _interp_map_addr; \
5220 + _regs->dn[3] = _dynamic_addr; \
5221 + _regs->an[1] = 0; /* dl_fini will be set by ldso */ \
5224 +#define USE_ELF_CORE_DUMP
5225 +#define ELF_EXEC_PAGESIZE 4096
5228 +#ifdef CONFIG_UBICOM32_V4
5229 +#define ELF_FDPIC_CORE_EFLAGS (EF_UBICOM32_FDPIC | EF_UBICOM32_V4)
5230 +#elif defined CONFIG_UBICOM32_V3
5231 +#define ELF_FDPIC_CORE_EFLAGS (EF_UBICOM32_FDPIC | EF_UBICOM32_V3)
5233 +#error Unknown/Unsupported ubicom32 architecture.
5237 +/* This is the location that an ET_DYN program is loaded if exec'ed. Typical
5238 + use of this is to invoke "./ld.so someprog" to test out a new version of
5239 + the loader. We need to make sure that it is out of the way of the program
5240 + that it will "exec", and that there is sufficient room for the brk. */
5242 +#define ELF_ET_DYN_BASE 0xD0000000UL
5245 + * For Ubicom32, the elf_gregset_t and struct pt_regs are the same size
5246 + * data structure so a copy is performed instead of providing the
5247 + * ELF_CORE_COPY_REGS macro.
5251 + * ELF_CORE_COPY_TASK_REGS is needed to dump register state from multi threaded user projects.
5253 +extern int dump_task_regs(struct task_struct *, elf_gregset_t *);
5254 +#define ELF_CORE_COPY_TASK_REGS(tsk, elf_regs) dump_task_regs(tsk, elf_regs)
5256 +/* This yields a mask that user programs can use to figure out what
5257 + instruction set this cpu supports. */
5259 +#define ELF_HWCAP (0)
5261 +/* This yields a string that ld.so will use to load implementation
5262 + specific libraries for optimization. This is more specific in
5263 + intent than poking at uname or /proc/cpuinfo. */
5265 +#define ELF_PLATFORM (NULL)
5267 +#define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX)
5269 +#endif /* _ASM_UBICOM32_ELF_H */
5270 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/emergency-restart.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/emergency-restart.h
5271 --- linux-2.6.30.10/arch/ubicom32/include/asm/emergency-restart.h 1970-01-01 02:00:00.000000000 +0200
5272 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/emergency-restart.h 2009-12-11 11:45:11.000000000 +0200
5275 + * arch/ubicom32/include/asm/emergency-restart.h
5276 + * Generic emergency-restart.h for Ubicom32 architecture.
5278 + * (C) Copyright 2009, Ubicom, Inc.
5280 + * This file is part of the Ubicom32 Linux Kernel Port.
5282 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
5283 + * it and/or modify it under the terms of the GNU General Public License
5284 + * as published by the Free Software Foundation, either version 2 of the
5285 + * License, or (at your option) any later version.
5287 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
5288 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
5289 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
5290 + * the GNU General Public License for more details.
5292 + * You should have received a copy of the GNU General Public License
5293 + * along with the Ubicom32 Linux Kernel Port. If not,
5294 + * see <http://www.gnu.org/licenses/>.
5296 + * Ubicom32 implementation derived from (with many thanks):
5301 +#ifndef _ASM_UBICOM32_EMERGENCY_RESTART_H
5302 +#define _ASM_UBICOM32_EMERGENCY_RESTART_H
5304 +#include <asm-generic/emergency-restart.h>
5306 +#endif /* _ASM_UBICOM32_EMERGENCY_RESTART_H */
5307 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/entry.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/entry.h
5308 --- linux-2.6.30.10/arch/ubicom32/include/asm/entry.h 1970-01-01 02:00:00.000000000 +0200
5309 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/entry.h 2009-12-11 11:45:11.000000000 +0200
5312 + * arch/ubicom32/include/asm/entry.h
5313 + * Entry register/stack definitions for Ubicom32 architecture.
5315 + * (C) Copyright 2009, Ubicom, Inc.
5317 + * This file is part of the Ubicom32 Linux Kernel Port.
5319 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
5320 + * it and/or modify it under the terms of the GNU General Public License
5321 + * as published by the Free Software Foundation, either version 2 of the
5322 + * License, or (at your option) any later version.
5324 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
5325 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
5326 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
5327 + * the GNU General Public License for more details.
5329 + * You should have received a copy of the GNU General Public License
5330 + * along with the Ubicom32 Linux Kernel Port. If not,
5331 + * see <http://www.gnu.org/licenses/>.
5333 + * Ubicom32 implementation derived from (with many thanks):
5338 +#ifndef _ASM_UBICOM32_ENTRY_H
5339 +#define _ASM_UBICOM32_ENTRY_H
5341 +#include <asm/setup.h>
5342 +#include <asm/page.h>
5344 +#endif /* _ASM_UBICOM32_ENTRY_H */
5345 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/errno.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/errno.h
5346 --- linux-2.6.30.10/arch/ubicom32/include/asm/errno.h 1970-01-01 02:00:00.000000000 +0200
5347 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/errno.h 2009-12-11 11:45:11.000000000 +0200
5350 + * arch/ubicom32/include/asm/errno.h
5351 + * Generic errno.h for Ubicom32 architecture.
5353 + * (C) Copyright 2009, Ubicom, Inc.
5355 + * This file is part of the Ubicom32 Linux Kernel Port.
5357 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
5358 + * it and/or modify it under the terms of the GNU General Public License
5359 + * as published by the Free Software Foundation, either version 2 of the
5360 + * License, or (at your option) any later version.
5362 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
5363 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
5364 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
5365 + * the GNU General Public License for more details.
5367 + * You should have received a copy of the GNU General Public License
5368 + * along with the Ubicom32 Linux Kernel Port. If not,
5369 + * see <http://www.gnu.org/licenses/>.
5371 + * Ubicom32 implementation derived from (with many thanks):
5376 +#ifndef _ASM_UBICOM32_ERRNO_H
5377 +#define _ASM_UBICOM32_ERRNO_H
5379 +#include <asm-generic/errno.h>
5381 +#endif /* _ASM_UBICOM32_ERRNO_H */
5382 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/fb.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/fb.h
5383 --- linux-2.6.30.10/arch/ubicom32/include/asm/fb.h 1970-01-01 02:00:00.000000000 +0200
5384 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/fb.h 2009-12-11 11:45:11.000000000 +0200
5387 + * arch/ubicom32/include/asm/fb.h
5388 + * Definition of fb_is_primary_device() for Ubicom32 architecture.
5390 + * (C) Copyright 2009, Ubicom, Inc.
5392 + * This file is part of the Ubicom32 Linux Kernel Port.
5394 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
5395 + * it and/or modify it under the terms of the GNU General Public License
5396 + * as published by the Free Software Foundation, either version 2 of the
5397 + * License, or (at your option) any later version.
5399 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
5400 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
5401 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
5402 + * the GNU General Public License for more details.
5404 + * You should have received a copy of the GNU General Public License
5405 + * along with the Ubicom32 Linux Kernel Port. If not,
5406 + * see <http://www.gnu.org/licenses/>.
5408 + * Ubicom32 implementation derived from (with many thanks):
5413 +#ifndef _ASM_UBICOM32_FB_H
5414 +#define _ASM_UBICOM32_FB_H
5415 +#include <linux/fb.h>
5417 +#define fb_pgprotect(...) do {} while (0)
5419 +static inline int fb_is_primary_device(struct fb_info *info)
5424 +#endif /* _ASM_UBICOM32_FB_H */
5425 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/fcntl.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/fcntl.h
5426 --- linux-2.6.30.10/arch/ubicom32/include/asm/fcntl.h 1970-01-01 02:00:00.000000000 +0200
5427 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/fcntl.h 2009-12-11 11:45:11.000000000 +0200
5430 + * arch/ubicom32/include/asm/fcntl.h
5431 + * File control bit definitions for Ubicom32 architecture.
5433 + * (C) Copyright 2009, Ubicom, Inc.
5435 + * This file is part of the Ubicom32 Linux Kernel Port.
5437 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
5438 + * it and/or modify it under the terms of the GNU General Public License
5439 + * as published by the Free Software Foundation, either version 2 of the
5440 + * License, or (at your option) any later version.
5442 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
5443 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
5444 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
5445 + * the GNU General Public License for more details.
5447 + * You should have received a copy of the GNU General Public License
5448 + * along with the Ubicom32 Linux Kernel Port. If not,
5449 + * see <http://www.gnu.org/licenses/>.
5451 + * Ubicom32 implementation derived from (with many thanks):
5456 +#ifndef _ASM_UBICOM32_FCNTL_H
5457 +#define _ASM_UBICOM32_FCNTL_H
5459 +#define O_DIRECTORY 040000 /* must be a directory */
5460 +#define O_NOFOLLOW 0100000 /* don't follow links */
5461 +#define O_DIRECT 0200000 /* direct disk access hint - currently ignored */
5462 +#define O_LARGEFILE 0400000
5464 +#include <asm-generic/fcntl.h>
5466 +#endif /* _ASM_UBICOM32_FCNTL_H */
5467 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/flat.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/flat.h
5468 --- linux-2.6.30.10/arch/ubicom32/include/asm/flat.h 1970-01-01 02:00:00.000000000 +0200
5469 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/flat.h 2009-12-11 11:45:11.000000000 +0200
5472 + * arch/ubicom32/include/asm/flat.h
5473 + * Definitions to support flat-format executables.
5475 + * (C) Copyright 2009, Ubicom, Inc.
5477 + * This file is part of the Ubicom32 Linux Kernel Port.
5479 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
5480 + * it and/or modify it under the terms of the GNU General Public License
5481 + * as published by the Free Software Foundation, either version 2 of the
5482 + * License, or (at your option) any later version.
5484 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
5485 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
5486 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
5487 + * the GNU General Public License for more details.
5489 + * You should have received a copy of the GNU General Public License
5490 + * along with the Ubicom32 Linux Kernel Port. If not,
5491 + * see <http://www.gnu.org/licenses/>.
5493 + * Ubicom32 implementation derived from (with many thanks):
5499 +#ifndef _ASM_UBICOM32_FLAT_H
5500 +#define _ASM_UBICOM32_FLAT_H
5502 +#define ARCH_FLAT_ALIGN 0x80
5503 +#define ARCH_FLAT_ALIGN_TEXT 1
5505 +#define R_UBICOM32_32 2
5506 +#define R_UBICOM32_HI24 7
5507 +#define R_UBICOM32_LO7_S 8
5508 +#define R_UBICOM32_LO7_2_S 9
5509 +#define R_UBICOM32_LO7_4_S 10
5510 +#define R_UBICOM32_LO7_D 11
5511 +#define R_UBICOM32_LO7_2_D 12
5512 +#define R_UBICOM32_LO7_4_D 13
5513 +#define R_UBICOM32_LO7_CALLI 15
5514 +#define R_UBICOM32_LO16_CALLI 16
5516 +extern void ubicom32_flat_put_addr_at_rp(unsigned long *rp, u32_t val, u32_t rval, unsigned long *p);
5517 +extern unsigned long ubicom32_flat_get_addr_from_rp(unsigned long *rp, u32_t relval, u32_t flags, unsigned long *p);
5519 +#define flat_stack_align(sp) /* nothing needed */
5520 +#define flat_argvp_envp_on_stack() 1
5521 +#define flat_old_ram_flag(flags) (flags)
5522 +#define flat_reloc_valid(reloc, size) ((reloc) <= (size))
5523 +#define flat_get_addr_from_rp(rp, relval, flags, p) (ubicom32_flat_get_addr_from_rp(rp, relval,flags, p))
5524 +#define flat_put_addr_at_rp(rp, val, relval) do {ubicom32_flat_put_addr_at_rp(rp, val, relval, &persistent);} while(0)
5525 +#define flat_get_relocate_addr(rel) ((persistent) ? (persistent & 0x07ffffff) : (rel & 0x07ffffff))
5527 +static inline int flat_set_persistent(unsigned int relval, unsigned long *p)
5532 + if ((relval >> 27) != R_UBICOM32_32) {
5534 + * Something other than UBICOM32_32. The next entry has the relocation.
5543 +#endif /* _ASM_UBICOM32_FLAT_H */
5544 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/fpu.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/fpu.h
5545 --- linux-2.6.30.10/arch/ubicom32/include/asm/fpu.h 1970-01-01 02:00:00.000000000 +0200
5546 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/fpu.h 2009-12-11 11:45:11.000000000 +0200
5549 + * arch/ubicom32/include/asm/fpu.h
5550 + * Floating point state definitions for Ubicom32 architecture.
5552 + * (C) Copyright 2009, Ubicom, Inc.
5554 + * This file is part of the Ubicom32 Linux Kernel Port.
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.
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.
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/>.
5570 + * Ubicom32 implementation derived from (with many thanks):
5575 +#ifndef _ASM_UBICOM32_FPU_H
5576 +#define _ASM_UBICOM32_FPU_H
5579 + * MAX floating point unit state size (FSAVE/FRESTORE)
5581 +/* No FP unit present then... */
5582 +#define FPSTATESIZE (2) /* dummy size */
5584 +#endif /* _ASM_UBICOM32_FPU_H */
5585 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ftrace.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ftrace.h
5586 --- linux-2.6.30.10/arch/ubicom32/include/asm/ftrace.h 1970-01-01 02:00:00.000000000 +0200
5587 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ftrace.h 2009-12-11 11:45:11.000000000 +0200
5590 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/futex.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/futex.h
5591 --- linux-2.6.30.10/arch/ubicom32/include/asm/futex.h 1970-01-01 02:00:00.000000000 +0200
5592 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/futex.h 2009-12-11 11:45:11.000000000 +0200
5595 + * arch/ubicom32/include/asm/futex.h
5596 + * Generic futex.h for Ubicom32 architecture.
5598 + * (C) Copyright 2009, Ubicom, Inc.
5600 + * This file is part of the Ubicom32 Linux Kernel Port.
5602 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
5603 + * it and/or modify it under the terms of the GNU General Public License
5604 + * as published by the Free Software Foundation, either version 2 of the
5605 + * License, or (at your option) any later version.
5607 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
5608 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
5609 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
5610 + * the GNU General Public License for more details.
5612 + * You should have received a copy of the GNU General Public License
5613 + * along with the Ubicom32 Linux Kernel Port. If not,
5614 + * see <http://www.gnu.org/licenses/>.
5616 + * Ubicom32 implementation derived from (with many thanks):
5621 +#ifndef _ASM_UBICOM32_FUTEX_H
5622 +#define _ASM_UBICOM32_FUTEX_H
5624 +#include <asm-generic/futex.h>
5626 +#endif /* _ASM_UBICOM32_FUTEX_H */
5627 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/.gitignore linux-2.6.30.10-ubi/arch/ubicom32/include/asm/.gitignore
5628 --- linux-2.6.30.10/arch/ubicom32/include/asm/.gitignore 1970-01-01 02:00:00.000000000 +0200
5629 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/.gitignore 2009-12-11 11:45:11.000000000 +0200
5632 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/gpio.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/gpio.h
5633 --- linux-2.6.30.10/arch/ubicom32/include/asm/gpio.h 1970-01-01 02:00:00.000000000 +0200
5634 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/gpio.h 2009-12-11 11:45:11.000000000 +0200
5637 + * arch/ubicom32/include/asm/gpio.h
5638 + * Definitions for GPIO operations on Ubicom32 architecture.
5640 + * (C) Copyright 2009, Ubicom, Inc.
5642 + * This file is part of the Ubicom32 Linux Kernel Port.
5644 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
5645 + * it and/or modify it under the terms of the GNU General Public License
5646 + * as published by the Free Software Foundation, either version 2 of the
5647 + * License, or (at your option) any later version.
5649 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
5650 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
5651 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
5652 + * the GNU General Public License for more details.
5654 + * You should have received a copy of the GNU General Public License
5655 + * along with the Ubicom32 Linux Kernel Port. If not,
5656 + * see <http://www.gnu.org/licenses/>.
5658 + * Ubicom32 implementation derived from (with many thanks):
5663 +#ifndef _ASM_UBICOM32_GPIO_H
5664 +#define _ASM_UBICOM32_GPIO_H
5666 +#include <linux/compiler.h>
5667 +#include <asm/irq.h>
5669 +#include <asm/ip5000.h>
5671 +#define ARCH_NR_GPIOS 512
5672 +#define MAX_UBICOM_ONCHIP_GPIO (9 * 32)
5675 + * Macros for manipulating GPIO numbers
5677 +#define gpio_bit(gn) (1 << (gn & 0x1f))
5678 +#define gpio_bank(gn) (gn >> 5)
5680 +#define gpio_pin_index(gn) (gn & 0x1f)
5681 +#define gpio_port_index(gn) (gn >> 5)
5683 +#define GPIO_RA_0 ((32 * 0) + 0)
5684 +#define GPIO_RA_1 ((32 * 0) + 1)
5685 +#define GPIO_RA_2 ((32 * 0) + 2)
5686 +#define GPIO_RA_3 ((32 * 0) + 3)
5687 +#define GPIO_RA_4 ((32 * 0) + 4)
5688 +#define GPIO_RA_5 ((32 * 0) + 5)
5689 +#define GPIO_RA_6 ((32 * 0) + 6)
5690 +#define GPIO_RA_7 ((32 * 0) + 7)
5692 +#define GPIO_RB_0 ((32 * 1) + 0)
5693 +#define GPIO_RB_1 ((32 * 1) + 1)
5694 +#define GPIO_RB_2 ((32 * 1) + 2)
5695 +#define GPIO_RB_3 ((32 * 1) + 3)
5696 +#define GPIO_RB_4 ((32 * 1) + 4)
5697 +#define GPIO_RB_5 ((32 * 1) + 5)
5698 +#define GPIO_RB_6 ((32 * 1) + 6)
5699 +#define GPIO_RB_7 ((32 * 1) + 7)
5700 +#define GPIO_RB_8 ((32 * 1) + 8)
5701 +#define GPIO_RB_9 ((32 * 1) + 9)
5702 +#define GPIO_RB_10 ((32 * 1) + 10)
5703 +#define GPIO_RB_11 ((32 * 1) + 11)
5704 +#define GPIO_RB_12 ((32 * 1) + 12)
5705 +#define GPIO_RB_13 ((32 * 1) + 13)
5706 +#define GPIO_RB_14 ((32 * 1) + 14)
5707 +#define GPIO_RB_15 ((32 * 1) + 15)
5708 +#define GPIO_RB_16 ((32 * 1) + 16)
5709 +#define GPIO_RB_17 ((32 * 1) + 17)
5710 +#define GPIO_RB_18 ((32 * 1) + 18)
5711 +#define GPIO_RB_19 ((32 * 1) + 19)
5713 +#define GPIO_RC_0 ((32 * 2) + 0)
5714 +#define GPIO_RC_1 ((32 * 2) + 1)
5715 +#define GPIO_RC_2 ((32 * 2) + 2)
5716 +#define GPIO_RC_3 ((32 * 2) + 3)
5717 +#define GPIO_RC_4 ((32 * 2) + 4)
5718 +#define GPIO_RC_5 ((32 * 2) + 5)
5719 +#define GPIO_RC_6 ((32 * 2) + 6)
5720 +#define GPIO_RC_7 ((32 * 2) + 7)
5721 +#define GPIO_RC_8 ((32 * 2) + 8)
5722 +#define GPIO_RC_9 ((32 * 2) + 9)
5723 +#define GPIO_RC_10 ((32 * 2) + 10)
5724 +#define GPIO_RC_11 ((32 * 2) + 11)
5725 +#define GPIO_RC_12 ((32 * 2) + 12)
5726 +#define GPIO_RC_13 ((32 * 2) + 13)
5727 +#define GPIO_RC_14 ((32 * 2) + 14)
5728 +#define GPIO_RC_15 ((32 * 2) + 15)
5729 +#define GPIO_RC_16 ((32 * 2) + 16)
5730 +#define GPIO_RC_17 ((32 * 2) + 17)
5731 +#define GPIO_RC_18 ((32 * 2) + 18)
5732 +#define GPIO_RC_19 ((32 * 2) + 19)
5733 +#define GPIO_RC_20 ((32 * 2) + 20)
5734 +#define GPIO_RC_21 ((32 * 2) + 21)
5735 +#define GPIO_RC_22 ((32 * 2) + 22)
5736 +#define GPIO_RC_23 ((32 * 2) + 23)
5737 +#define GPIO_RC_24 ((32 * 2) + 24)
5738 +#define GPIO_RC_25 ((32 * 2) + 25)
5739 +#define GPIO_RC_26 ((32 * 2) + 26)
5740 +#define GPIO_RC_27 ((32 * 2) + 27)
5741 +#define GPIO_RC_28 ((32 * 2) + 28)
5742 +#define GPIO_RC_29 ((32 * 2) + 29)
5743 +#define GPIO_RC_30 ((32 * 2) + 30)
5744 +#define GPIO_RC_31 ((32 * 2) + 31)
5746 +#define GPIO_RD_0 ((32 * 3) + 0)
5747 +#define GPIO_RD_1 ((32 * 3) + 1)
5748 +#define GPIO_RD_2 ((32 * 3) + 2)
5749 +#define GPIO_RD_3 ((32 * 3) + 3)
5750 +#define GPIO_RD_4 ((32 * 3) + 4)
5751 +#define GPIO_RD_5 ((32 * 3) + 5)
5752 +#define GPIO_RD_6 ((32 * 3) + 6)
5753 +#define GPIO_RD_7 ((32 * 3) + 7)
5754 +#define GPIO_RD_8 ((32 * 3) + 8)
5755 +#define GPIO_RD_9 ((32 * 3) + 9)
5756 +#define GPIO_RD_10 ((32 * 3) + 10)
5757 +#define GPIO_RD_11 ((32 * 3) + 11)
5759 +#define GPIO_RE_0 ((32 * 4) + 0)
5760 +#define GPIO_RE_1 ((32 * 4) + 1)
5761 +#define GPIO_RE_2 ((32 * 4) + 2)
5762 +#define GPIO_RE_3 ((32 * 4) + 3)
5763 +#define GPIO_RE_4 ((32 * 4) + 4)
5764 +#define GPIO_RE_5 ((32 * 4) + 5)
5765 +#define GPIO_RE_6 ((32 * 4) + 6)
5766 +#define GPIO_RE_7 ((32 * 4) + 7)
5768 +#define GPIO_RF_0 ((32 * 5) + 0)
5769 +#define GPIO_RF_1 ((32 * 5) + 1)
5770 +#define GPIO_RF_2 ((32 * 5) + 2)
5771 +#define GPIO_RF_3 ((32 * 5) + 3)
5772 +#define GPIO_RF_4 ((32 * 5) + 4)
5773 +#define GPIO_RF_5 ((32 * 5) + 5)
5774 +#define GPIO_RF_6 ((32 * 5) + 6)
5775 +#define GPIO_RF_7 ((32 * 5) + 7)
5776 +#define GPIO_RF_8 ((32 * 5) + 8)
5777 +#define GPIO_RF_9 ((32 * 5) + 9)
5778 +#define GPIO_RF_10 ((32 * 5) + 10)
5779 +#define GPIO_RF_11 ((32 * 5) + 11)
5780 +#define GPIO_RF_12 ((32 * 5) + 12)
5781 +#define GPIO_RF_13 ((32 * 5) + 13)
5782 +#define GPIO_RF_14 ((32 * 5) + 14)
5783 +#define GPIO_RF_15 ((32 * 5) + 15)
5785 +#define GPIO_RG_0 ((32 * 6) + 0)
5786 +#define GPIO_RG_1 ((32 * 6) + 1)
5787 +#define GPIO_RG_2 ((32 * 6) + 2)
5788 +#define GPIO_RG_3 ((32 * 6) + 3)
5789 +#define GPIO_RG_4 ((32 * 6) + 4)
5790 +#define GPIO_RG_5 ((32 * 6) + 5)
5791 +#define GPIO_RG_6 ((32 * 6) + 6)
5792 +#define GPIO_RG_7 ((32 * 6) + 7)
5793 +#define GPIO_RG_8 ((32 * 6) + 8)
5794 +#define GPIO_RG_9 ((32 * 6) + 9)
5795 +#define GPIO_RG_10 ((32 * 6) + 10)
5796 +#define GPIO_RG_11 ((32 * 6) + 11)
5797 +#define GPIO_RG_12 ((32 * 6) + 12)
5798 +#define GPIO_RG_13 ((32 * 6) + 13)
5799 +#define GPIO_RG_14 ((32 * 6) + 14)
5800 +#define GPIO_RG_15 ((32 * 6) + 15)
5801 +#define GPIO_RG_16 ((32 * 6) + 16)
5802 +#define GPIO_RG_17 ((32 * 6) + 17)
5803 +#define GPIO_RG_18 ((32 * 6) + 18)
5804 +#define GPIO_RG_19 ((32 * 6) + 19)
5805 +#define GPIO_RG_20 ((32 * 6) + 20)
5806 +#define GPIO_RG_21 ((32 * 6) + 21)
5807 +#define GPIO_RG_22 ((32 * 6) + 22)
5808 +#define GPIO_RG_23 ((32 * 6) + 23)
5809 +#define GPIO_RG_24 ((32 * 6) + 24)
5810 +#define GPIO_RG_25 ((32 * 6) + 25)
5811 +#define GPIO_RG_26 ((32 * 6) + 26)
5812 +#define GPIO_RG_27 ((32 * 6) + 27)
5813 +#define GPIO_RG_28 ((32 * 6) + 28)
5814 +#define GPIO_RG_29 ((32 * 6) + 29)
5815 +#define GPIO_RG_30 ((32 * 6) + 30)
5816 +#define GPIO_RG_31 ((32 * 6) + 31)
5818 +#define GPIO_RH_0 ((32 * 7) + 0)
5819 +#define GPIO_RH_1 ((32 * 7) + 1)
5820 +#define GPIO_RH_2 ((32 * 7) + 2)
5821 +#define GPIO_RH_3 ((32 * 7) + 3)
5822 +#define GPIO_RH_4 ((32 * 7) + 4)
5823 +#define GPIO_RH_5 ((32 * 7) + 5)
5824 +#define GPIO_RH_6 ((32 * 7) + 6)
5825 +#define GPIO_RH_7 ((32 * 7) + 7)
5826 +#define GPIO_RH_8 ((32 * 7) + 8)
5827 +#define GPIO_RH_9 ((32 * 7) + 9)
5829 +#define GPIO_RI_0 ((32 * 8) + 0)
5830 +#define GPIO_RI_1 ((32 * 8) + 1)
5831 +#define GPIO_RI_2 ((32 * 8) + 2)
5832 +#define GPIO_RI_3 ((32 * 8) + 3)
5833 +#define GPIO_RI_4 ((32 * 8) + 4)
5834 +#define GPIO_RI_5 ((32 * 8) + 5)
5835 +#define GPIO_RI_6 ((32 * 8) + 6)
5836 +#define GPIO_RI_7 ((32 * 8) + 7)
5837 +#define GPIO_RI_8 ((32 * 8) + 8)
5838 +#define GPIO_RI_9 ((32 * 8) + 9)
5839 +#define GPIO_RI_10 ((32 * 8) + 10)
5840 +#define GPIO_RI_11 ((32 * 8) + 11)
5841 +#define GPIO_RI_12 ((32 * 8) + 12)
5842 +#define GPIO_RI_13 ((32 * 8) + 13)
5843 +#define GPIO_RI_14 ((32 * 8) + 14)
5844 +#define GPIO_RI_15 ((32 * 8) + 15)
5847 + * The following section defines extra GPIO available to some boards.
5848 + * These GPIO are generally external to the processor (i.e. SPI/I2C
5849 + * expander chips).
5851 + * Note that these defines show all possible GPIO available, however,
5852 + * depending on the actual board configuration, some GPIO are not
5853 + * available for use.
5855 +#ifdef CONFIG_IP7500MEDIA
5859 +#define IP7500MEDIA_U15_BASE (32 * 10)
5860 +#define IP7500MEDIA_IO0 (IP7500MEDIA_U15_BASE + 0)
5861 +#define IP7500MEDIA_IO1 (IP7500MEDIA_U15_BASE + 1)
5862 +#define IP7500MEDIA_IO2 (IP7500MEDIA_U15_BASE + 2)
5863 +#define IP7500MEDIA_IO3 (IP7500MEDIA_U15_BASE + 3)
5864 +#define IP7500MEDIA_IO4 (IP7500MEDIA_U15_BASE + 4)
5865 +#define IP7500MEDIA_IO5 (IP7500MEDIA_U15_BASE + 5)
5866 +#define IP7500MEDIA_IO6 (IP7500MEDIA_U15_BASE + 6)
5867 +#define IP7500MEDIA_IO7 (IP7500MEDIA_U15_BASE + 7)
5872 +#define IP7500MEDIA_U16_BASE (32 * 11)
5873 +#define IP7500MEDIA_IO8 (IP7500MEDIA_U16_BASE + 0)
5874 +#define IP7500MEDIA_IO9 (IP7500MEDIA_U16_BASE + 1)
5875 +#define IP7500MEDIA_IO10 (IP7500MEDIA_U16_BASE + 2)
5876 +#define IP7500MEDIA_IO11 (IP7500MEDIA_U16_BASE + 3)
5877 +#define IP7500MEDIA_IO12 (IP7500MEDIA_U16_BASE + 4)
5878 +#define IP7500MEDIA_IO13 (IP7500MEDIA_U16_BASE + 5)
5879 +#define IP7500MEDIA_IO14 (IP7500MEDIA_U16_BASE + 6)
5880 +#define IP7500MEDIA_IO15 (IP7500MEDIA_U16_BASE + 7)
5885 +#define IP7500MEDIA_U17_BASE (32 * 12)
5886 +#define IP7500MEDIA_IO16 (IP7500MEDIA_U17_BASE + 0)
5887 +#define IP7500MEDIA_IO17 (IP7500MEDIA_U17_BASE + 1)
5888 +#define IP7500MEDIA_IO18 (IP7500MEDIA_U17_BASE + 2)
5889 +#define IP7500MEDIA_IO19 (IP7500MEDIA_U17_BASE + 3)
5890 +#define IP7500MEDIA_IO20 (IP7500MEDIA_U17_BASE + 4)
5891 +#define IP7500MEDIA_IO21 (IP7500MEDIA_U17_BASE + 5)
5892 +#define IP7500MEDIA_IO22 (IP7500MEDIA_U17_BASE + 6)
5893 +#define IP7500MEDIA_IO23 (IP7500MEDIA_U17_BASE + 7)
5898 +#define IP7500MEDIA_U18_BASE (32 * 13)
5899 +#define IP7500MEDIA_IO24 (IP7500MEDIA_U18_BASE + 0)
5900 +#define IP7500MEDIA_IO25 (IP7500MEDIA_U18_BASE + 1)
5901 +#define IP7500MEDIA_IO26 (IP7500MEDIA_U18_BASE + 2)
5902 +#define IP7500MEDIA_IO27 (IP7500MEDIA_U18_BASE + 3)
5903 +#define IP7500MEDIA_IO28 (IP7500MEDIA_U18_BASE + 4)
5904 +#define IP7500MEDIA_IO29 (IP7500MEDIA_U18_BASE + 5)
5905 +#define IP7500MEDIA_IO30 (IP7500MEDIA_U18_BASE + 6)
5906 +#define IP7500MEDIA_IO31 (IP7500MEDIA_U18_BASE + 7)
5909 +#ifdef CONFIG_IP7145DPF
5913 +#define IP7145DPF_U48_BASE (32 * 10)
5914 +#define IP7145DPF_IO0 (IP7145DPF_U48_BASE + 0)
5915 +#define IP7145DPF_IO1 (IP7145DPF_U48_BASE + 1)
5916 +#define IP7145DPF_IO2 (IP7145DPF_U48_BASE + 2)
5917 +#define IP7145DPF_IO3 (IP7145DPF_U48_BASE + 3)
5918 +#define IP7145DPF_IO4 (IP7145DPF_U48_BASE + 4)
5919 +#define IP7145DPF_IO5 (IP7145DPF_U48_BASE + 5)
5920 +#define IP7145DPF_IO6 (IP7145DPF_U48_BASE + 6)
5921 +#define IP7145DPF_IO7 (IP7145DPF_U48_BASE + 7)
5926 +#define IP7145DPF_U72_BASE (32 * 11)
5927 +#define IP7145DPF_IOB0 (IP7145DPF_U72_BASE + 0)
5928 +#define IP7145DPF_IOB1 (IP7145DPF_U72_BASE + 1)
5929 +#define IP7145DPF_IOB2 (IP7145DPF_U72_BASE + 2)
5930 +#define IP7145DPF_IOB3 (IP7145DPF_U72_BASE + 3)
5931 +#define IP7145DPF_IOB4 (IP7145DPF_U72_BASE + 4)
5932 +#define IP7145DPF_IOB5 (IP7145DPF_U72_BASE + 5)
5933 +#define IP7145DPF_IOB6 (IP7145DPF_U72_BASE + 6)
5934 +#define IP7145DPF_IOB7 (IP7145DPF_U72_BASE + 7)
5937 +#include <asm-generic/gpio.h>
5940 + * The following macros bypass gpiolib to generate direct references
5941 + * to the port registers. These assume, minimally, that either
5942 + * gpio_direction_input() or gpio_direction_output() have already been
5943 + * called to setup the pin direction and to enable the pin function to
5944 + * be gpio. These macros generate the hardware port address based on
5945 + * the assumption that all ports are 32 bits wide (even though we know
5946 + * they are not). This is so we can efficiently turn pin numbers into
5947 + * port addresses without a lookup.
5949 + * These operations must be done in one instruction to prevent clobbering
5950 + * other thread's accesses to the same port.
5952 +#define UBICOM32_GPIO_ENABLE(pin) \
5954 + asm volatile ("or.4 (%[port]), (%[port]), %[mask]\n\t" \
5956 + : [port] "a" (&UBICOM32_IO_PORT(IO_BASE + (gpio_bank(pin) << 12))->gpio_mask), \
5957 + [mask] "d" (gpio_bit(pin)) \
5958 + : "cc", "memory" \
5962 +#define UBICOM32_GPIO_DISABLE(pin) \
5964 + asm volatile ("and.4 (%[port]), (%[port]), %[mask]\n\t" \
5966 + : [port] "a" (&UBICOM32_IO_PORT(IO_BASE + (gpio_bank(pin) << 12))->gpio_mask), \
5967 + [mask] "d" (~gpio_bit(pin)) \
5968 + : "cc", "memory" \
5972 +#define UBICOM32_GPIO_SET_PIN_INPUT(pin) \
5974 + asm volatile ("and.4 (%[port]), (%[port]), %[mask]\n\t" \
5976 + : [port] "a" (&UBICOM32_IO_PORT(IO_BASE + (gpio_bank(pin) << 12))->gpio_ctl), \
5977 + [mask] "d" (~gpio_bit(pin)) \
5978 + : "cc", "memory" \
5982 +#define UBICOM32_GPIO_SET_PIN_OUTPUT(pin) \
5984 + asm volatile ("or.4 (%[port]), (%[port]), %[mask]\n\t" \
5986 + : [port] "a" (&UBICOM32_IO_PORT(IO_BASE + (gpio_bank(pin) << 12))->gpio_ctl), \
5987 + [mask] "d" (gpio_bit(pin)) \
5988 + : "cc", "memory" \
5992 +#define UBICOM32_GPIO_SET_PIN_TOGGLE(pin) \
5994 + asm volatile ("xor.4 (%[port]), (%[port]), %[mask]\n\t" \
5996 + : [port] "a" (&UBICOM32_IO_PORT(IO_BASE + (gpio_bank(pin) << 12))->gpio_out), \
5997 + [mask] "d" (gpio_bit(pin)) \
5998 + : "cc", "memory" \
6002 +#define UBICOM32_GPIO_SET_PIN_HIGH(pin) \
6004 + asm volatile ("or.4 (%[port]), (%[port]), %[mask]\n\t" \
6006 + : [port] "a" (&UBICOM32_IO_PORT(IO_BASE + (gpio_bank(pin) << 12))->gpio_out), \
6007 + [mask] "d" (gpio_bit(pin)) \
6008 + : "cc", "memory" \
6012 +#define UBICOM32_GPIO_SET_PIN_LOW(pin) \
6014 + asm volatile ("and.4 (%[port]), (%[port]), %[mask]\n\t" \
6016 + : [port] "a" (&UBICOM32_IO_PORT(IO_BASE + (gpio_bank(pin) << 12))->gpio_out), \
6017 + [mask] "d" (~gpio_bit(pin)) \
6018 + : "cc", "memory" \
6022 +#define UBICOM32_GPIO_SET_PIN(pin, val) \
6024 + UBICOM32_GPIO_SET_PIN_HIGH(pin); \
6026 + UBICOM32_GPIO_SET_PIN_LOW(pin); \
6029 +#define UBICOM32_GPIO_GET_PIN(pin) \
6030 + (0 != (UBICOM32_IO_PORT(IO_BASE + (gpio_bank(pin) << 12))->gpio_in \
6034 +static inline int gpio_get_value(unsigned gpio)
6036 + if (gpio <= MAX_UBICOM_ONCHIP_GPIO)
6037 + return UBICOM32_GPIO_GET_PIN(gpio);
6039 + return __gpio_get_value(gpio);
6042 +static inline void gpio_set_value(unsigned gpio, int value)
6044 + if (gpio <= MAX_UBICOM_ONCHIP_GPIO)
6046 + UBICOM32_GPIO_SET_PIN(gpio, value);
6050 + __gpio_set_value(gpio, value);
6054 +static inline int gpio_cansleep(unsigned gpio)
6056 + return __gpio_cansleep(gpio);
6059 +static inline int gpio_to_irq(unsigned gpio)
6061 +#if defined(IP5000) || defined(IP5000_REV2)
6062 + if ((gpio >= GPIO_RA_4) && (gpio <= GPIO_RA_6))
6067 +#elif defined(IP7000) || defined(IP7000_REV2)
6068 + if ((gpio >= GPIO_RA_4) && (gpio <= GPIO_RA_6))
6069 + return 44 + (gpio - GPIO_RA_4);
6079 +static inline int irq_to_gpio(unsigned gpio)
6084 +extern struct ubicom32_io_port *ubi_gpio_get_port(unsigned gpio);
6086 +extern int __init ubi_gpio_init(void);
6088 +#endif /* _ASM_UBICOM32_GPIO_H */
6089 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/hardirq.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/hardirq.h
6090 --- linux-2.6.30.10/arch/ubicom32/include/asm/hardirq.h 1970-01-01 02:00:00.000000000 +0200
6091 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/hardirq.h 2009-12-11 11:45:11.000000000 +0200
6094 + * arch/ubicom32/include/asm/hardirq.h
6095 + * Definition of ack_bad_irq() for Ubicom32 architecture.
6097 + * (C) Copyright 2009, Ubicom, Inc.
6098 + * Copyright (C) 1997, 98, 99, 2000, 01, 05 Ralf Baechle (ralf@linux-mips.org)
6099 + * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
6100 + * Copyright (C) 2001 MIPS Technologies, Inc.
6102 + * This file is part of the Ubicom32 Linux Kernel Port.
6104 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
6105 + * it and/or modify it under the terms of the GNU General Public License
6106 + * as published by the Free Software Foundation, either version 2 of the
6107 + * License, or (at your option) any later version.
6109 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
6110 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
6111 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
6112 + * the GNU General Public License for more details.
6114 + * You should have received a copy of the GNU General Public License
6115 + * along with the Ubicom32 Linux Kernel Port. If not,
6116 + * see <http://www.gnu.org/licenses/>.
6118 + * Ubicom32 implementation derived from (with many thanks):
6123 +#ifndef _ASM_UBICOM32_HARDIRQ_H
6124 +#define _ASM_UBICOM32_HARDIRQ_H
6126 +#include <linux/threads.h>
6127 +#include <linux/irq.h>
6130 + * The hardirq mask has to be large enough to have space
6131 + * for potentially all IRQ sources in the system nesting
6132 + * on a single CPU. For Ubicom32, we have 64 IRQ sources.
6134 +#define HARDIRQ_BITS 6
6135 +#if (1 << HARDIRQ_BITS) < NR_IRQS
6136 +# error HARDIRQ_BITS is too low!
6140 + unsigned int __softirq_pending;
6141 +} ____cacheline_aligned irq_cpustat_t;
6143 +#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
6145 +extern void ack_bad_irq(unsigned int irq);
6147 +#endif /* _ASM_UBICOM32_HARDIRQ_H */
6148 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/hw_irq.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/hw_irq.h
6149 --- linux-2.6.30.10/arch/ubicom32/include/asm/hw_irq.h 1970-01-01 02:00:00.000000000 +0200
6150 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/hw_irq.h 2009-12-11 11:45:11.000000000 +0200
6153 + * arch/ubicom32/include/asm/hw_irq.h
6154 + * Ubicom32 architecture APIC support.
6156 + * (C) Copyright 2009, Ubicom, Inc.
6158 + * This file is part of the Ubicom32 Linux Kernel Port.
6160 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
6161 + * it and/or modify it under the terms of the GNU General Public License
6162 + * as published by the Free Software Foundation, either version 2 of the
6163 + * License, or (at your option) any later version.
6165 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
6166 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
6167 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
6168 + * the GNU General Public License for more details.
6170 + * You should have received a copy of the GNU General Public License
6171 + * along with the Ubicom32 Linux Kernel Port. If not,
6172 + * see <http://www.gnu.org/licenses/>.
6174 + * Ubicom32 implementation derived from (with many thanks):
6179 +#ifndef _ASM_UBICOM32_HW_IRQ_H
6180 +#define _ASM_UBICOM32_HW_IRQ_H
6182 +#endif /* _ASM_UBICOM32_HW_IRQ_H */
6183 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ioctl.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ioctl.h
6184 --- linux-2.6.30.10/arch/ubicom32/include/asm/ioctl.h 1970-01-01 02:00:00.000000000 +0200
6185 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ioctl.h 2009-12-11 11:45:11.000000000 +0200
6188 + * arch/ubicom32/include/asm/ioctl.h
6189 + * Generic ioctl.h for Ubicom32 architecture.
6191 + * (C) Copyright 2009, Ubicom, Inc.
6193 + * This file is part of the Ubicom32 Linux Kernel Port.
6195 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
6196 + * it and/or modify it under the terms of the GNU General Public License
6197 + * as published by the Free Software Foundation, either version 2 of the
6198 + * License, or (at your option) any later version.
6200 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
6201 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
6202 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
6203 + * the GNU General Public License for more details.
6205 + * You should have received a copy of the GNU General Public License
6206 + * along with the Ubicom32 Linux Kernel Port. If not,
6207 + * see <http://www.gnu.org/licenses/>.
6209 + * Ubicom32 implementation derived from (with many thanks):
6214 +#ifndef _ASM_UBICOM32_IOCTL_H
6215 +#define _ASM_UBICOM32_IOCTL_H
6217 +#include <asm-generic/ioctl.h>
6219 +#endif /* _ASM_UBICOM32_IOCTL_H */
6220 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ioctls.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ioctls.h
6221 --- linux-2.6.30.10/arch/ubicom32/include/asm/ioctls.h 1970-01-01 02:00:00.000000000 +0200
6222 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ioctls.h 2009-12-11 11:45:11.000000000 +0200
6225 + * arch/ubicom32/include/asm/ioctls.h
6226 + * Definitions of ioctls for Ubicom32 architecture.
6228 + * (C) Copyright 2009, Ubicom, Inc.
6230 + * This file is part of the Ubicom32 Linux Kernel Port.
6232 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
6233 + * it and/or modify it under the terms of the GNU General Public License
6234 + * as published by the Free Software Foundation, either version 2 of the
6235 + * License, or (at your option) any later version.
6237 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
6238 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
6239 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
6240 + * the GNU General Public License for more details.
6242 + * You should have received a copy of the GNU General Public License
6243 + * along with the Ubicom32 Linux Kernel Port. If not,
6244 + * see <http://www.gnu.org/licenses/>.
6246 + * Ubicom32 implementation derived from (with many thanks):
6251 +#ifndef _ASM_UBICOM32_IOCTLS_H
6252 +#define _ASM_UBICOM32_IOCTLS_H
6254 +#include <asm/ioctl.h>
6256 +/* 0x54 is just a magic number to make these relatively unique ('T') */
6258 +#define TCGETS 0x5401
6259 +#define TCSETS 0x5402
6260 +#define TCSETSW 0x5403
6261 +#define TCSETSF 0x5404
6262 +#define TCGETA 0x5405
6263 +#define TCSETA 0x5406
6264 +#define TCSETAW 0x5407
6265 +#define TCSETAF 0x5408
6266 +#define TCSBRK 0x5409
6267 +#define TCXONC 0x540A
6268 +#define TCFLSH 0x540B
6269 +#define TIOCEXCL 0x540C
6270 +#define TIOCNXCL 0x540D
6271 +#define TIOCSCTTY 0x540E
6272 +#define TIOCGPGRP 0x540F
6273 +#define TIOCSPGRP 0x5410
6274 +#define TIOCOUTQ 0x5411
6275 +#define TIOCSTI 0x5412
6276 +#define TIOCGWINSZ 0x5413
6277 +#define TIOCSWINSZ 0x5414
6278 +#define TIOCMGET 0x5415
6279 +#define TIOCMBIS 0x5416
6280 +#define TIOCMBIC 0x5417
6281 +#define TIOCMSET 0x5418
6282 +#define TIOCGSOFTCAR 0x5419
6283 +#define TIOCSSOFTCAR 0x541A
6284 +#define FIONREAD 0x541B
6285 +#define TIOCINQ FIONREAD
6286 +#define TIOCLINUX 0x541C
6287 +#define TIOCCONS 0x541D
6288 +#define TIOCGSERIAL 0x541E
6289 +#define TIOCSSERIAL 0x541F
6290 +#define TIOCPKT 0x5420
6291 +#define FIONBIO 0x5421
6292 +#define TIOCNOTTY 0x5422
6293 +#define TIOCSETD 0x5423
6294 +#define TIOCGETD 0x5424
6295 +#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */
6296 +#define TIOCSBRK 0x5427 /* BSD compatibility */
6297 +#define TIOCCBRK 0x5428 /* BSD compatibility */
6298 +#define TIOCGSID 0x5429 /* Return the session ID of FD */
6299 +#define TCGETS2 _IOR('T',0x2A, struct termios2)
6300 +#define TCSETS2 _IOW('T',0x2B, struct termios2)
6301 +#define TCSETSW2 _IOW('T',0x2C, struct termios2)
6302 +#define TCSETSF2 _IOW('T',0x2D, struct termios2)
6303 +#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
6304 +#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
6306 +#define FIONCLEX 0x5450 /* these numbers need to be adjusted. */
6307 +#define FIOCLEX 0x5451
6308 +#define FIOASYNC 0x5452
6309 +#define TIOCSERCONFIG 0x5453
6310 +#define TIOCSERGWILD 0x5454
6311 +#define TIOCSERSWILD 0x5455
6312 +#define TIOCGLCKTRMIOS 0x5456
6313 +#define TIOCSLCKTRMIOS 0x5457
6314 +#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
6315 +#define TIOCSERGETLSR 0x5459 /* Get line status register */
6316 +#define TIOCSERGETMULTI 0x545A /* Get multiport config */
6317 +#define TIOCSERSETMULTI 0x545B /* Set multiport config */
6319 +#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
6320 +#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
6321 +#define FIOQSIZE 0x545E
6323 +/* Used for packet mode */
6324 +#define TIOCPKT_DATA 0
6325 +#define TIOCPKT_FLUSHREAD 1
6326 +#define TIOCPKT_FLUSHWRITE 2
6327 +#define TIOCPKT_STOP 4
6328 +#define TIOCPKT_START 8
6329 +#define TIOCPKT_NOSTOP 16
6330 +#define TIOCPKT_DOSTOP 32
6332 +#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
6334 +#endif /* _ASM_UBICOM32_IOCTLS_H */
6335 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/io.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/io.h
6336 --- linux-2.6.30.10/arch/ubicom32/include/asm/io.h 1970-01-01 02:00:00.000000000 +0200
6337 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/io.h 2009-12-11 11:45:11.000000000 +0200
6340 + * arch/ubicom32/include/asm/io.h
6341 + * I/O memory accessor functions for Ubicom32 architecture.
6343 + * (C) Copyright 2009, Ubicom, Inc.
6345 + * This file is part of the Ubicom32 Linux Kernel Port.
6347 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
6348 + * it and/or modify it under the terms of the GNU General Public License
6349 + * as published by the Free Software Foundation, either version 2 of the
6350 + * License, or (at your option) any later version.
6352 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
6353 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
6354 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
6355 + * the GNU General Public License for more details.
6357 + * You should have received a copy of the GNU General Public License
6358 + * along with the Ubicom32 Linux Kernel Port. If not,
6359 + * see <http://www.gnu.org/licenses/>.
6361 + * Ubicom32 implementation derived from (with many thanks):
6366 +#ifndef _ASM_UBICOM32_IO_H
6367 +#define _ASM_UBICOM32_IO_H
6370 +#include <linux/string.h>
6371 +#include <linux/compiler.h>
6373 +static inline unsigned short _swapw(volatile unsigned short v)
6375 + return ((v << 8) | (v >> 8));
6378 +static inline unsigned int _swapl(volatile unsigned long v)
6380 + return ((v << 24) | ((v & 0xff00) << 8) | ((v & 0xff0000) >> 8) | (v >> 24));
6384 +#define readb(addr) \
6385 + ({ unsigned char __v = (*(volatile unsigned char *) (addr)); __v; })
6386 +#define readw(addr) \
6387 + ({ unsigned short __v = (*(volatile unsigned short *) (addr)); __v; })
6388 +#define readl(addr) \
6389 + ({ unsigned int __v = (*(volatile unsigned int *) (addr)); __v; })
6391 +#define writeb(b,addr) (void)((*(volatile unsigned char *) (addr)) = (b))
6392 +#define writew(b,addr) (void)((*(volatile unsigned short *) (addr)) = (b))
6393 +#define writel(b,addr) (void)((*(volatile unsigned int *) (addr)) = (b))
6394 +#else /*CONFIG_PCI */
6396 +#define PCI_CPU_REG_BASE (0x00000000UL) /* taking lower 2GB space */
6397 +#define PCI_DEV_REG_BASE (0x80000000UL)
6399 +#if PCI_CPU_REG_BASE > PCI_DEV_REG_BASE
6400 +#define IS_PCI_ADDRESS(x) (((unsigned int)(x)&(PCI_CPU_REG_BASE)) == 0)
6402 +#define IS_PCI_ADDRESS(x) ((unsigned int)(x)&(PCI_DEV_REG_BASE))
6405 +extern unsigned int ubi32_pci_read_u32(const volatile void __iomem *addr);
6406 +extern unsigned short ubi32_pci_read_u16(const volatile void __iomem *addr);
6407 +extern unsigned char ubi32_pci_read_u8(const volatile void __iomem *addr);
6408 +extern void ubi32_pci_write_u32(unsigned int val, const volatile void __iomem *addr);
6409 +extern void ubi32_pci_write_u16(unsigned short val, const volatile void __iomem *addr);
6410 +extern void ubi32_pci_write_u8(unsigned char val, const volatile void __iomem *addr);
6412 +static inline unsigned char readb(const volatile void __iomem *addr)
6414 + if (IS_PCI_ADDRESS(addr))
6415 + return ubi32_pci_read_u8(addr);
6417 + return (unsigned char)(*(volatile unsigned char *)addr);
6419 +static inline unsigned short readw(const volatile void __iomem *addr)
6421 + if (IS_PCI_ADDRESS(addr))
6422 + return ubi32_pci_read_u16(addr);
6424 + return (unsigned short)(*(volatile unsigned short *)addr);
6427 +static inline unsigned int readl(const volatile void __iomem *addr)
6429 + if (IS_PCI_ADDRESS(addr))
6430 + return ubi32_pci_read_u32(addr);
6432 + return (unsigned int)(*(volatile unsigned int *)addr);
6435 +static inline void writel(unsigned int val, volatile void __iomem *addr)
6437 + if (IS_PCI_ADDRESS(addr))
6438 + ubi32_pci_write_u32(val, addr);
6440 + *(volatile unsigned int *)addr = val;
6443 +static inline void writew(unsigned short val, volatile void __iomem *addr)
6445 + if (IS_PCI_ADDRESS(addr))
6446 + ubi32_pci_write_u16(val, addr);
6448 + *(volatile unsigned short *)addr = val;
6451 +static inline void writeb(unsigned char val, volatile void __iomem *addr)
6453 + if (IS_PCI_ADDRESS(addr))
6454 + ubi32_pci_write_u8(val, addr);
6456 + *(volatile unsigned char *)addr = val;
6460 +#define readb_relaxed(addr) readb(addr)
6461 +#define readw_relaxed(addr) readw(addr)
6462 +#define readl_relaxed(addr) readl(addr)
6465 +#define __raw_readb readb
6466 +#define __raw_readw readw
6467 +#define __raw_readl readl
6468 +#define __raw_writeb writeb
6469 +#define __raw_writew writew
6470 +#define __raw_writel writel
6472 +static inline void io_outsb(unsigned int addr, const void *buf, int len)
6474 + volatile unsigned char *ap = (volatile unsigned char *) addr;
6475 + unsigned char *bp = (unsigned char *) buf;
6480 +static inline void io_outsw(unsigned int addr, const void *buf, int len)
6482 + volatile unsigned short *ap = (volatile unsigned short *) addr;
6483 + unsigned short *bp = (unsigned short *) buf;
6485 + *ap = _swapw(*bp++);
6488 +static inline void io_outsl(unsigned int addr, const void *buf, int len)
6490 + volatile unsigned int *ap = (volatile unsigned int *) addr;
6491 + unsigned int *bp = (unsigned int *) buf;
6493 + *ap = _swapl(*bp++);
6496 +static inline void io_insb(unsigned int addr, void *buf, int len)
6498 + volatile unsigned char *ap = (volatile unsigned char *) addr;
6499 + unsigned char *bp = (unsigned char *) buf;
6504 +static inline void io_insw(unsigned int addr, void *buf, int len)
6506 + volatile unsigned short *ap = (volatile unsigned short *) addr;
6507 + unsigned short *bp = (unsigned short *) buf;
6509 + *bp++ = _swapw(*ap);
6512 +static inline void io_insl(unsigned int addr, void *buf, int len)
6514 + volatile unsigned int *ap = (volatile unsigned int *) addr;
6515 + unsigned int *bp = (unsigned int *) buf;
6517 + *bp++ = _swapl(*ap);
6523 + * make the short names macros so specific devices
6524 + * can override them as required
6527 +#define memset_io(a,b,c) memset((void *)(a),(b),(c))
6528 +#define memcpy_fromio(a,b,c) memcpy((a),(void *)(b),(c))
6529 +#define memcpy_toio(a,b,c) memcpy((void *)(a),(b),(c))
6531 +extern void memcpy_fromio(void *to, const volatile void __iomem *from, unsigned len);
6532 +extern void memcpy_toio(volatile void __iomem *to, const void *from, unsigned len);
6533 +extern void memset_io(volatile void __iomem *addr, int val, size_t count);
6536 +#define inb(addr) readb(addr)
6537 +#define inw(addr) readw(addr)
6538 +#define inl(addr) readl(addr)
6539 +#define outb(x,addr) ((void) writeb(x,addr))
6540 +#define outw(x,addr) ((void) writew(x,addr))
6541 +#define outl(x,addr) ((void) writel(x,addr))
6543 +#define inb_p(addr) inb(addr)
6544 +#define inw_p(addr) inw(addr)
6545 +#define inl_p(addr) inl(addr)
6546 +#define outb_p(x,addr) outb(x,addr)
6547 +#define outw_p(x,addr) outw(x,addr)
6548 +#define outl_p(x,addr) outl(x,addr)
6550 +#define outsb(a,b,l) io_outsb(a,b,l)
6551 +#define outsw(a,b,l) io_outsw(a,b,l)
6552 +#define outsl(a,b,l) io_outsl(a,b,l)
6554 +#define insb(a,b,l) io_insb(a,b,l)
6555 +#define insw(a,b,l) io_insw(a,b,l)
6556 +#define insl(a,b,l) io_insl(a,b,l)
6559 +#define ioread8_rep(a,d,c) insb(a,d,c)
6560 +#define ioread16_rep(a,d,c) insw(a,d,c)
6561 +#define ioread32_rep(a,d,c) insl(a,d,c)
6562 +#define iowrite8_rep(a,s,c) outsb(a,s,c)
6563 +#define iowrite16_rep(a,s,c) outsw(a,s,c)
6564 +#define iowrite32_rep(a,s,c) outsl(a,s,c)
6566 +extern void ioread8_rep(void __iomem *port, void *buf, unsigned long count);
6567 +extern void ioread16_rep(void __iomem *port, void *buf, unsigned long count);
6568 +extern void ioread32_rep(void __iomem *port, void *buf, unsigned long count);
6569 +extern void iowrite8_rep(void __iomem *port, const void *buf, unsigned long count);
6570 +extern void iowrite16_rep(void __iomem *port, const void *buf, unsigned long count);
6571 +extern void iowrite32_rep(void __iomem *port, const void *buf, unsigned long count);
6576 +#define ioread8(X) readb(X)
6577 +#define ioread16(X) readw(X)
6578 +#define ioread32(X) readl(X)
6579 +#define iowrite8(val,X) writeb(val,X)
6580 +#define iowrite16(val,X) writew(val,X)
6581 +#define iowrite32(val,X) writel(val,X)
6582 +#else /*CONFIG_PCI */
6583 +extern unsigned char ioread8(void __iomem *addr);
6584 +extern unsigned short ioread16(void __iomem *addr);
6585 +extern unsigned int ioread32(void __iomem *addr);
6586 +extern void iowrite8(unsigned char val, void __iomem *addr);
6587 +extern void iowrite16(unsigned short val, void __iomem *addr);
6588 +extern void iowrite32(unsigned int val, void __iomem *addr);
6589 +#endif /* CONFIG_PCI */
6591 +#define IO_SPACE_LIMIT 0xffff
6593 +/* Values for nocacheflag and cmode */
6594 +#define IOMAP_FULL_CACHING 0
6595 +#define IOMAP_NOCACHE_SER 1
6596 +#define IOMAP_NOCACHE_NONSER 2
6597 +#define IOMAP_WRITETHROUGH 3
6599 +extern void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag);
6600 +extern void __iounmap(void *addr, unsigned long size);
6602 +static inline void *ioremap(unsigned long physaddr, unsigned long size)
6604 + return __ioremap(physaddr, size, IOMAP_NOCACHE_SER);
6606 +static inline void *ioremap_nocache(unsigned long physaddr, unsigned long size)
6608 + return __ioremap(physaddr, size, IOMAP_NOCACHE_SER);
6610 +static inline void *ioremap_writethrough(unsigned long physaddr, unsigned long size)
6612 + return __ioremap(physaddr, size, IOMAP_WRITETHROUGH);
6614 +static inline void *ioremap_fullcache(unsigned long physaddr, unsigned long size)
6616 + return __ioremap(physaddr, size, IOMAP_FULL_CACHING);
6619 +extern void iounmap(void *addr);
6621 +#define ioport_map(port, nr) ((void __iomem*)(port))
6622 +#define ioport_unmap(addr)
6625 +/* Pages to physical address... */
6626 +#define page_to_phys(page) ((page - mem_map) << PAGE_SHIFT)
6627 +#define page_to_bus(page) ((page - mem_map) << PAGE_SHIFT)
6630 + * Macros used for converting between virtual and physical mappings.
6632 +#define phys_to_virt(vaddr) ((void *) (vaddr))
6633 +#define virt_to_phys(vaddr) ((unsigned long) (vaddr))
6635 +#define virt_to_bus virt_to_phys
6636 +#define bus_to_virt phys_to_virt
6639 + * Convert a physical pointer to a virtual kernel pointer for /dev/mem
6642 +#define xlate_dev_mem_ptr(p) __va(p)
6645 + * Convert a virtual cached pointer to an uncached pointer
6647 +#define xlate_dev_kmem_ptr(p) p
6649 +#endif /* __KERNEL__ */
6651 +#endif /* _ASM_UBICOM32_IO_H */
6652 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ip5000-asm.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ip5000-asm.h
6653 --- linux-2.6.30.10/arch/ubicom32/include/asm/ip5000-asm.h 1970-01-01 02:00:00.000000000 +0200
6654 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ip5000-asm.h 2009-12-11 11:45:11.000000000 +0200
6657 + * arch/ubicom32/include/asm/ip5000-asm.h
6658 + * Instruction macros for the IP5000.
6660 + * (C) Copyright 2009, Ubicom, Inc.
6662 + * This file is part of the Ubicom32 Linux Kernel Port.
6664 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
6665 + * it and/or modify it under the terms of the GNU General Public License
6666 + * as published by the Free Software Foundation, either version 2 of the
6667 + * License, or (at your option) any later version.
6669 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
6670 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
6671 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
6672 + * the GNU General Public License for more details.
6674 + * You should have received a copy of the GNU General Public License
6675 + * along with the Ubicom32 Linux Kernel Port. If not,
6676 + * see <http://www.gnu.org/licenses/>.
6678 + * Ubicom32 implementation derived from (with many thanks):
6684 +#ifndef _ASM_UBICOM32_IP5000_ASM_H
6685 +#define _ASM_UBICOM32_IP5000_ASM_H
6687 +#if !defined(__LINKER__)
6689 +#if defined(__ASSEMBLY__)
6690 +.macro cycles quant
6694 +.if (((\quant) + 3) / 8) > 0
6695 +.rept (((\quant) + 3) / 8)
6699 +.if ((((\quant) + 3) % 8) / 4) > 0
6706 + * Same macro as above just in C inline asm
6709 +.macro cycles quant \n\
6710 +.if (\\quant) == 1 \n\
6713 +.if (((\\quant) + 3) / 8) > 0 \n\
6714 +.rept (((\\quant) + 3) / 8) \n\
6718 +.if ((((\\quant) + 3) % 8) / 4) > 0 \n\
6727 +#if defined(__ASSEMBLY__)
6728 +.macro pipe_flush cyc
6729 + cycles 11 - (\cyc)
6733 + * Same macro as above just in C inline asm
6736 +.macro pipe_flush cyc \n\
6737 + cycles 11 - (\\cyc) \n\
6743 +#if defined(__ASSEMBLY__)
6744 +.macro setcsr_flush cyc
6749 + * Same macro as above just in C inline asm
6752 +.macro setcsr_flush cyc \n\
6753 + cycles 5 - (\\cyc) \n\
6759 + * Macros for prefetch (using miss-aligned memory write)
6761 +#if defined(__ASSEMBLY__)
6763 +.macro pre_fetch_macro thread_num, Ascratch, Aaddress length
6764 + bclr MT_TRAP_EN, MT_TRAP_EN, #(\thread_num)
6765 + bset \Ascratch, \Aaddress, #0 ; force a miss-aligned address
6766 + jmpt.t .+4 ; delay for both address setup and trap disable
6767 + move.4 (\Ascratch), #0
6768 + .if (\length > 32)
6769 + move.4 32(\Ascratch), #0
6771 + .if (\length > 64)
6772 + move.4 64(\Ascratch), #0
6774 + .if (\length > 96)
6775 + move.4 96(\Ascratch), #0
6777 + .if (\length > 128)
6778 + invalid_instruction ; maximum pre-fetch size is 4 cache lines
6780 + bset MT_TRAP_EN, MT_TRAP_EN, #(\thread_num)
6785 + * Same macro as above just in C inline asm
6788 +.macro pre_fetch_macro thread_num, Ascratch, Aaddress length \n\
6789 + bclr MT_TRAP_EN, MT_TRAP_EN, #(\thread_num) \n\
6790 + bset \\Ascratch, \\Aaddress, #0 ; force a miss-aligned address \n\
6791 + jmpt.t .+4 ; delay for both address setup and trap disable \n\
6792 + move.4 (\\Ascratch), #0 \n\
6793 + .if (\\length > 32) \n\
6794 + move.4 32(\\Ascratch), #0 \n\
6796 + .if (\\length > 64) \n\
6797 + move.4 64(\\Ascratch), #0 \n\
6799 + .if (\\length > 96) \n\
6800 + move.4 96(\\Ascratch), #0 \n\
6802 + .if (\\length > 128) \n\
6803 + invalid_instruction ; maximum pre-fetch size is 4 cache lines \n\
6805 + bset MT_TRAP_EN, MT_TRAP_EN, #(\\thread_num) \n\
6810 +#endif /* !defined(__LINKER__) */
6811 +#endif /* defined _ASM_UBICOM32_IP5000_ASM_H */
6812 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ip5000.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ip5000.h
6813 --- linux-2.6.30.10/arch/ubicom32/include/asm/ip5000.h 1970-01-01 02:00:00.000000000 +0200
6814 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ip5000.h 2009-12-11 11:45:11.000000000 +0200
6817 + * arch/ubicom32/include/asm/ip5000.h
6818 + * Specific details for the Ubicom IP5000 processor.
6820 + * (C) Copyright 2009, Ubicom, Inc.
6822 + * This file is part of the Ubicom32 Linux Kernel Port.
6824 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
6825 + * it and/or modify it under the terms of the GNU General Public License
6826 + * as published by the Free Software Foundation, either version 2 of the
6827 + * License, or (at your option) any later version.
6829 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
6830 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
6831 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
6832 + * the GNU General Public License for more details.
6834 + * You should have received a copy of the GNU General Public License
6835 + * along with the Ubicom32 Linux Kernel Port. If not,
6836 + * see <http://www.gnu.org/licenses/>.
6838 + * Ubicom32 implementation derived from (with many thanks):
6844 +#ifndef _ASM_UBICOM32_IP5000_H
6845 +#define _ASM_UBICOM32_IP5000_H
6847 +#include <asm/memory_map.h>
6850 + * Inline assembly define
6852 +#define S(arg) #arg
6853 +#define D(arg) S(arg)
6856 + * Assembler include file
6858 +#include <asm/ip5000-asm.h>
6863 +#define JMPT_PENALTY 3
6864 +#define JMPF_PENALTY 7
6865 +#define RET_PENALTY 7
6870 +#if defined(IP5000) || defined(IP5000_REV2)
6871 +#define THREAD_COUNT 10
6872 +#elif defined(IP7000) || defined(IP7000_REV2)
6873 +#define THREAD_COUNT 12
6875 +#error "Unknown IP5K silicon"
6881 +#if defined(IP5000) || defined(IP5000_REV2)
6882 +#define UBICOM32_ARCH_VERSION 3
6883 +#elif defined(IP7000) || defined(IP7000_REV2)
6884 +#define UBICOM32_ARCH_VERSION 4
6886 +#error "Unknown IP5K silicon"
6893 +#define ROSR_INT (1 << 0)
6896 +#define INT_CHIP(reg, bit) (((reg) << 5) | (bit))
6897 +#define INT_REG(interrupt) (((interrupt) >> 5) * 4)
6898 +#define INT_SET(interrupt) 0x0114 + INT_REG(interrupt)
6899 +#define INT_CLR(interrupt) 0x0124 + INT_REG(interrupt)
6900 +#define INT_STAT(interrupt) 0x0104 + INT_REG(interrupt)
6901 +#define INT_MASK(interrupt) 0x00C0 + INT_REG(interrupt)
6902 +#define INT_BIT(interrupt) ((interrupt) & 0x1F)
6903 +#define INT_BIT_MASK(interrupt) (1 << INT_BIT(interrupt))
6906 + * The LOCK_INT and THREAD_INT are used to wake up corresponding thread. They are sharing
6907 + * the same set of SW interrupt resource.
6909 + * LOCK_INT(n): One SW INT per NRT thread that can participate lock operation.
6910 + * The threads that can participate lock are application threads and DSR thread.
6911 + * (Lock locks - numbers are hard-coded in lock.h)
6912 + * THREAD_INT(n): One SW INT per HRT thread for wake up trigger.
6914 +#define LOCK_INT(thread) INT_CHIP(0, (thread))
6915 +#define THREAD_INT(thread) INT_CHIP(0, (thread))
6918 + * The SYSTEM_INT and DSR_INT are sharing the same set of SW interrupt resource.
6920 + * SYSTEM_INT(n): One SW INT per NRT threads (application threads) as system queue interrupt,
6921 + * and for DSR as self-trigger interrupt.
6922 + * (The application threads include at least thread 0)
6923 + * DSR_INT(n): One SW INT per HRT thread to request DSR service.
6925 +#define SYSTEM_INT(thread) INT_CHIP(0, THREAD_COUNT + (thread))
6926 +#define DSR_INT(thread) INT_CHIP(0, THREAD_COUNT + (thread))
6929 +#define GLOBAL_CTRL_TRAP_RST_EN (1 << 9)
6930 +#define GLOBAL_CTRL_AERROR_RST_EN (1 << 8)
6931 +#define GLOBAL_CTRL_MT_MIN_DELAY(x) ((x) << 3)
6932 +#define GLOBAL_CTRL_HRT_BANK_SELECT (1 << 2)
6933 +#define GLOBAL_CTRL_INT_EN (1 << 0)
6938 +#define HRT_TABLE0_BASE 0x0800
6939 +#define HRT_TABLE1_BASE 0x0900
6940 +#define HRT_TABLE_SIZE 64
6943 + * Break Point Trap Register
6945 +#define ASYNCERROR_INT INT_CHIP(0, 31)
6946 +#define BREAKPOINT_INT INT_CHIP(1, 31)
6950 + * The non-existing FIFO INTs are mapped to INT2 for the ports.
6952 +#define IO_PORT_PTR_TO_NUM(port) (((port) & 0x0000ffff) >> 12)
6953 +#define RX_FIFO_INT(port) \
6954 + ((IO_PORT_PTR_TO_NUM(port) == 0) ? INT_CHIP(0, 25) : \
6955 + ((IO_PORT_PTR_TO_NUM(port) == 1) ? INT_CHIP(0, 26) : \
6956 + ((IO_PORT_PTR_TO_NUM(port) == 2) ? INT_CHIP(0, 29) : \
6957 + ((IO_PORT_PTR_TO_NUM(port) == 3) ? INT_CHIP(1, 24) : \
6958 + ((IO_PORT_PTR_TO_NUM(port) == 4) ? INT_CHIP(1, 27) : \
6959 + ((IO_PORT_PTR_TO_NUM(port) == 5) ? INT_CHIP(1, 16) : \
6960 + ((IO_PORT_PTR_TO_NUM(port) == 6) ? INT_CHIP(1, 19) : \
6961 + ((IO_PORT_PTR_TO_NUM(port) == 7) ? INT_CHIP(1, 20) : \
6962 + ((IO_PORT_PTR_TO_NUM(port) == 8) ? INT_CHIP(1, 21) : \
6963 + INT_CHIP(1, 15))))))))))
6964 +#define TX_FIFO_INT(port) \
6965 + ((IO_PORT_PTR_TO_NUM(port) == 0) ? INT_CHIP(0, 24) : \
6966 + ((IO_PORT_PTR_TO_NUM(port) == 1) ? INT_CHIP(0, 27) : \
6967 + ((IO_PORT_PTR_TO_NUM(port) == 2) ? INT_CHIP(0, 29) : \
6968 + ((IO_PORT_PTR_TO_NUM(port) == 3) ? INT_CHIP(1, 25) : \
6969 + ((IO_PORT_PTR_TO_NUM(port) == 4) ? INT_CHIP(1, 28) : \
6970 + ((IO_PORT_PTR_TO_NUM(port) == 5) ? INT_CHIP(1, 17) : \
6971 + ((IO_PORT_PTR_TO_NUM(port) == 6) ? INT_CHIP(1, 19) : \
6972 + ((IO_PORT_PTR_TO_NUM(port) == 7) ? INT_CHIP(1, 20) : \
6973 + ((IO_PORT_PTR_TO_NUM(port) == 8) ? INT_CHIP(1, 22) : \
6974 + INT_CHIP(1, 15))))))))))
6975 +#define PORT_OTHER_INT(port) \
6976 + ((IO_PORT_PTR_TO_NUM(port) == 0) ? INT_CHIP(0, 25) : \
6977 + ((IO_PORT_PTR_TO_NUM(port) == 1) ? INT_CHIP(0, 28) : \
6978 + ((IO_PORT_PTR_TO_NUM(port) == 2) ? INT_CHIP(0, 29) : \
6979 + ((IO_PORT_PTR_TO_NUM(port) == 3) ? INT_CHIP(1, 26) : \
6980 + ((IO_PORT_PTR_TO_NUM(port) == 4) ? INT_CHIP(1, 29) : \
6981 + ((IO_PORT_PTR_TO_NUM(port) == 5) ? INT_CHIP(1, 18) : \
6982 + ((IO_PORT_PTR_TO_NUM(port) == 6) ? INT_CHIP(1, 19) : \
6983 + ((IO_PORT_PTR_TO_NUM(port) == 7) ? INT_CHIP(1, 20) : \
6984 + ((IO_PORT_PTR_TO_NUM(port) == 8) ? INT_CHIP(1, 23) : \
6985 + INT_CHIP(1, 15))))))))))
6988 + * On Chip Peripherals Base.
6990 +#define OCP_BASE 0x01000000
6991 +#define OCP_GENERAL 0x000
6992 +#define OCP_TIMERS 0x100
6993 +#define OCP_TRNG 0x200 /* True Random Number Generator Control Reigsters */
6994 +#define OCP_DEBUG 0x300
6995 +#define OCP_SECURITY 0x400
6996 +#define OCP_ICCR 0x500 /* I-Cache Control Registers */
6997 +#define OCP_DCCR 0x600 /* D-Cache Control Registers */
6998 +#define OCP_OCMC 0x700 /* On Chip Memory Control Registers */
6999 +#define OCP_STATISTICS 0x800 /* Statistics Counters */
7000 +#define OCP_MTEST 0x900 /* Memory Test Registers */
7001 +#define OCP_MCFG 0xa00 /* Memory Configuration Registers -- IP7000 only */
7002 +#define OCP_DEBUG_INST 0x000 /* Up to 16M */
7005 + * General Configuration Registers (PLL)
7007 +#define GENERAL_CFG_BASE (OCP_BASE + OCP_GENERAL)
7008 +#define GEN_CLK_CORE_CFG 0x00
7009 +#define GEN_CLK_IO_CFG 0x04
7010 +#define GEN_CLK_DDR_CFG 0x08
7011 +#define GEN_CLK_DDRDS_CFG 0x0c
7012 +#define GEN_CLK_SLIP_CLR 0x10
7013 +#define GEN_CLK_SLIP_START 0x14
7014 +#define GEN_CLK_SERDES_SEL 0x18 /* IP7000 only */
7015 +#define GEN_CLK_DDR_CFG2 0x1c /* IP7000 only */
7016 +#define GEN_DDR_CAL_CTRL 0x30 /* IP5000 only */
7017 +#define GEN_DDR_CAL_STAT 0x34 /* IP5000 only */
7018 +#define GEN_USB_DFT_CTRL 0x38 /* IP5000 only */
7019 +#define GEN_USB_DFT_STAT 0x3c /* IP5000 only */
7020 +#define GEN_USB_PHY_CFG 0x40 /* IP7000 only */
7021 +#define GEN_USB_PHY_TEST 0x44 /* IP7000 only */
7022 +#define GEN_USB_PHY_STAT 0x48 /* IP7000 only */
7023 +#define GEN_SW_RESET 0x80
7024 +#define GEN_RESET_REASON 0x84
7025 +#define GEN_BOND_CFG 0x88
7026 +#define GEN_IO_PU_CFG 0x8c
7027 +#define GEN_MEM_RM_CFG 0x90
7028 +#define GEN_IO_CONFIG 0x94
7030 +#define GEN_CLK_PLL_SECURITY_BIT_NO 31
7031 +#define GEN_CLK_PLL_SECURITY (1 << GEN_CLK_PLL_SECURITY_BIT_NO)
7032 +#define GEN_CLK_PLL_ENSAT (1 << 30)
7033 +#define GEN_CLK_PLL_FASTEN (1 << 29)
7034 +#define GEN_CLK_PLL_NR(v) (((v) - 1) << 23)
7035 +#define GEN_CLK_PLL_NF(v) (((v) - 1) << 11)
7036 +#define GEN_CLK_PLL_OD(v) (((v) - 1) << 8)
7037 +#define GEN_CLK_PLL_RESET (1 << 7)
7038 +#define GEN_CLK_PLL_BYPASS (1 << 6)
7039 +#define GEN_CLK_PLL_POWERDOWN (1 << 5)
7040 +#define GEN_CLK_PLL_SELECT (1 << 4)
7042 +#define GEN_GET_CLK_PLL_NR(v) ((((v) >> 23) & 0x003f) + 1)
7043 +#define GEN_GET_CLK_PLL_NF(v) ((((v) >> 11) & 0x0fff) + 1)
7044 +#define GEN_GET_CLK_PLL_OD(v) ((((v) >> 8) & 0x7) + 1)
7047 +#define RESET_FLAG_DST_MEM_ERROR (1 << 18)
7048 +#define RESET_FLAG_SRC1_MEM_ERROR (1 << 17)
7049 +#define RESET_FLAG_WRITE_ADDR (1 << 16)
7050 +#define RESET_FLAG_DST_SYNC_ERROR (1 << 15)
7051 +#define RESET_FLAG_SRC1_SYNC_ERROR (1 << 14)
7052 +#define RESET_FLAG_DST_ALGN_ERROR (1 << 13)
7053 +#define RESET_FLAG_SRC1_ALGN_ERROR (1 << 12)
7054 +#define RESET_FLAG_DST_ADDR_ERROR (1 << 11)
7055 +#define RESET_FLAG_SRC1_ADDR_ERROR (1 << 10)
7056 +#define RESET_FLAG_ILLEGAL_INST (1 << 9)
7057 +#define RESET_FLAG_INST_SYNC_ERROR (1 << 8)
7058 +#define RESET_FLAG_INST_ADDR_ERROR (1 << 7)
7059 +#define RESET_FLAG_DATA_PORT_ERROR (1 << 6)
7060 +#define RESET_FLAG_INST_PORT_ERROR (1 << 5)
7061 +#define RESET_FLAG_SW_RESET (1 << 4)
7062 +#define RESET_FLAG_DEBUG (1 << 3)
7063 +#define RESET_FLAG_WATCHDOG (1 << 2)
7064 +#define RESET_FLAG_POWER_ON (1 << 1)
7065 +#define RESET_FLAG_EXTERNAL (1 << 0)
7070 +#define TIMER_BASE (OCP_BASE + OCP_TIMERS)
7071 +#define TIMER_MPTVAL 0x00
7072 +#define TIMER_RTCOM 0x04
7073 +#define TIMER_TKEY 0x08
7074 +#define TIMER_WDCOM 0x0c
7075 +#define TIMER_WDCFG 0x10
7076 +#define TIMER_SYSVAL 0x14
7077 +#define TIMER_SYSCOM(tmr) (0x18 + (tmr) * 4)
7078 +#define TIMER_TRN_CFG 0x100
7079 +#define TIMER_TRN 0x104
7081 +#define TIMER_COUNT 10
7082 +#define TIMER_INT(tmr) INT_CHIP(1, (tmr))
7083 +#define TIMER_TKEYVAL 0xa1b2c3d4
7084 +#define TIMER_WATCHDOG_DISABLE 0x4d3c2b1a
7085 +#define TIMER_TRN_CFG_ENABLE_OSC 0x00000007
7087 +#ifndef __ASSEMBLY__
7089 + * ubicom32_io_timer
7091 +struct ubicom32_io_timer {
7092 + volatile u32_t mptval;
7093 + volatile u32_t rtcom;
7094 + volatile u32_t tkey;
7095 + volatile u32_t wdcom;
7096 + volatile u32_t wdcfg;
7097 + volatile u32_t sysval;
7098 + volatile u32_t syscom[TIMER_COUNT];
7099 + volatile u32_t reserved[64 - 6 - TIMER_COUNT]; // skip all the way to OCP-TRNG section
7100 + volatile u32_t rsgcfg;
7101 + volatile u32_t trn;
7104 +#define UBICOM32_IO_TIMER ((struct ubicom32_io_timer *)TIMER_BASE)
7107 +#define UBICOM32_VECTOR_TO_TIMER_INDEX(vector) (vector - TIMER_INT(0))
7110 + * OCP-Debug Module (Mailbox)
7112 +#define ISD_MAILBOX_BASE (OCP_BASE + OCP_DEBUG)
7113 +#define ISD_MAILBOX_IN 0x00
7114 +#define ISD_MAILBOX_OUT 0x04
7115 +#define ISD_MAILBOX_STATUS 0x08
7117 +#define ISD_MAILBOX_INT INT_CHIP(1, 30)
7119 +#define ISD_MAILBOX_STATUS_IN_FULL (1 << 31)
7120 +#define ISD_MAILBOX_STATUS_IN_EMPTY (1 << 30)
7121 +#define ISD_MAILBOX_STATUS_OUT_FULL (1 << 29)
7122 +#define ISD_MAILBOX_STATUS_OUT_EMPTY (1 << 28)
7127 +#define SECURITY_BASE (OCP_BASE + OCP_SECURITY)
7128 +#define SECURITY_BASE_EFFECTIVE_ADDRESS (SECURITY_BASE >> 7) // To load the base address in a single instruction
7129 +#define SECURITY_CTRL 0x00
7130 +#define SECURITY_CTRL_BYTE_OFFSET(x) ((x) << 16)
7131 +#define SECURITY_CTRL_KEY_SIZE(x) ((x) << 8)
7132 +#define SECURITY_CTRL_HASH_ALG_NONE (0 << 4)
7133 +#define SECURITY_CTRL_HASH_ALG_MD5 (1 << 4)
7134 +#define SECURITY_CTRL_HASH_ALG_SHA1 (2 << 4)
7135 +#define SECURITY_CTRL_CBC (1 << 3)
7136 +#define SECURITY_CTRL_CIPHER_ALG_AES (0 << 1)
7137 +#define SECURITY_CTRL_CIPHER_ALG_NONE (1 << 1)
7138 +#define SECURITY_CTRL_CIPHER_ALG_DES (2 << 1)
7139 +#define SECURITY_CTRL_CIPHER_ALG_3DES (3 << 1)
7140 +#define SECURITY_CTRL_ENCIPHER (1 << 0)
7141 +#define SECURITY_CTRL_DECIPHER (0 << 0)
7142 +#define SECURITY_STAT 0x04
7143 +#define SECURITY_STAT_BUSY (1 << 0)
7144 +#define SECURITY_KEY_VALUE(x) (0x10 + (x) * 4)
7145 +#define SECURITY_KEY_IN(x) (0x30 + (x) * 4)
7146 +#define SECURITY_KEY_OUT(x) (0x50 + (x) * 4)
7147 +#define SECURITY_KEY_HASH(x) (0x70 + (x) * 4)
7152 +#define ICCR_BASE (OCP_BASE + OCP_ICCR)
7153 +#define ICACHE_TOTAL_SIZE 16384 /* in bytes */
7158 +#define DCCR_BASE (OCP_BASE + OCP_DCCR)
7159 +#if defined(IP5000) || defined(IP5000_REV2)
7160 +#define DCACHE_TOTAL_SIZE 8192 /* in bytes */
7161 +#elif defined(IP7000) || defined(IP7000_REV2)
7162 +#define DCACHE_TOTAL_SIZE 16384 /* in bytes */
7165 +#if defined(IP5000) || defined(IP5000_REV2) || defined(IP7000) || defined(IP7000_REV2)
7166 +#define DCACHE_WRITE_QUEUE_LENGTH 6
7168 +#error "Unknown IP5K silicon"
7171 +#define CACHE_LINE_SIZE 32 /* in bytes */
7173 +#define CCR_ADDR 0x00
7174 +#define CCR_RDD 0x04
7175 +#define CCR_WRD 0x08
7176 +#define CCR_STAT 0x0c
7177 +#define CCR_CTRL 0x10
7179 +#define CCR_STAT_MCBE 0
7180 +#define CCR_STAT_WIDEL 1 /* D-cache only */
7182 +#define CCR_CTRL_DONE 0
7183 +#define CCR_CTRL_RESET 2
7184 +#define CCR_CTRL_VALID 3
7185 +#define CCR_CTRL_RD_DATA (1 << 4)
7186 +#define CCR_CTRL_RD_TAG (2 << 4)
7187 +#define CCR_CTRL_WR_DATA (3 << 4)
7188 +#define CCR_CTRL_WR_TAG (4 << 4)
7189 +#define CCR_CTRL_INV_INDEX (5 << 4)
7190 +#define CCR_CTRL_INV_ADDR (6 << 4)
7191 +#define CCR_CTRL_FLUSH_INDEX (7 << 4) /* D-cache only */
7192 +#define CCR_CTRL_FLUSH_INV_INDEX (8 << 4) /* D-cache only */
7193 +#define CCR_CTRL_FLUSH_ADDR (9 << 4) /* D-cache only */
7194 +#define CCR_CTRL_FLUSH_INV_ADDR (10 << 4) /* D-cache only */
7199 +#define OCMC_BASE (OCP_BASE + OCP_OCMC)
7200 +#define OCMC_BANK_MASK 0x00
7201 +#define OCMC_BIST_CNTL 0x04 /* IP5000 only */
7202 +#define OCMC_BIST_STAT 0x08 /* IP5000 only */
7204 +#define OCMC_BANK_PROG(n) ((1<<(n))-1)
7206 +#define OCMC_BIST_WRCK (1 << 7)
7207 +#define OCMC_BIST_RESET (1 << 5)
7208 +#define OCMC_BIST_SMART (1 << 4)
7209 +#define OCMC_BIST_RUN (1 << 3)
7210 +#define OCMC_BIST_REPAIR (1 << 2)
7212 +#define OCMC_BIST_READY (1 << 3)
7213 +#define OCMC_BIST_FAIL (1 << 2)
7218 +#define STATISTICS_BASE (OCP_BASE + OCP_STATISTICS)
7219 +#define STAT_COUNTER_CTRL(n) ((n)*8)
7220 +#define STAT_COUNTER(n) ((n)*8 + 4)
7222 +#define STAT_EVENT_MP_INST 0
7223 +#define STAT_EVENT_OCM_ACCESS 4
7224 +#define STAT_EVENT_OCM_REQ 5
7225 +#define STAT_EVENT_IC_REQ_INVAL 13
7226 +#define STAT_EVENT_IC_MISS_INVAL 14
7227 +#define STAT_EVENT_IC_REQ_INVAL_NACK 15
7228 +#define STAT_EVENT_IC_REQ_VAL 16
7229 +#define STAT_EVENT_IC_MISS_VAL 17
7230 +#define STAT_EVENT_IC_REQ_VAL_NACK 18
7231 +#define STAT_EVENT_IC_MISS_Q 19
7232 +#define STAT_EVENT_DC_RD_REQ 20
7233 +#define STAT_EVENT_DC_RD_MISS 21
7234 +#define STAT_EVENT_DC_WR_REQ 22
7235 +#define STAT_EVENT_DC_WR_MISS 23
7236 +#define STAT_EVENT_DC_MISS_Q 24
7237 +#define STAT_EVENT_DC_WB_FULL 25
7238 +#define STAT_EVENT_DC_REQ_NACK 26
7239 +#define STAT_EVENT_DC_CORE_REQ 27
7240 +#define STAT_EVENT_DC_MISS 28
7241 +#define STAT_EVENT_DC_EVICT 29
7242 +#define STAT_EVENT_TRUE 30
7243 +#define STAT_EVENT_FALSE 31
7248 +#define MTEST_BASE (OCP_BASE + OCP_MTEST)
7249 +#define MTEST_ADDR 0x00
7250 +#define MTEST_WR 0x04
7251 +#define MTEST_RD 0x08
7252 +#define MTEST_CTRL 0x0c
7255 + * OCP_MCFG (IP7000 only)
7257 +#define MCFG_BASE (OCP_BASE + OCP_MCFG)
7258 +#define MCFG_CTRL 0x00
7259 +#define MCFG_WCFG 0x04
7260 +#define MCFG_RCFG 0x08
7265 +#define IO_BASE 0x02000000
7266 +#define RA (IO_BASE + 0x00000000)
7267 +#define RB (IO_BASE + 0x00001000)
7268 +#define RC (IO_BASE + 0x00002000)
7269 +#define RD (IO_BASE + 0x00003000)
7270 +#define RE (IO_BASE + 0x00004000)
7271 +#define RF (IO_BASE + 0x00005000)
7272 +#define RG (IO_BASE + 0x00006000)
7273 +#define RH (IO_BASE + 0x00007000)
7274 +#define RI (IO_BASE + 0x00008000)
7275 +#define RJ (IO_BASE + 0x00009000)
7276 +#define RLATCH (IO_BASE + 0x00ff0000) // For latched output only
7277 +#define IO_PORT_BR_OFFSET 0x00000800
7280 + * General I/O Register Map (per port)
7282 +#define IO_FUNC 0x00
7283 +#define IO_GPIO_CTL 0x04
7284 +#define IO_GPIO_OUT 0x08
7285 +#define IO_GPIO_IN 0x0C
7286 +#define IO_INT_STATUS 0x10
7287 +#define IO_INT_MASK 0x14
7288 +#define IO_INT_SET 0x18
7289 +#define IO_INT_CLR 0x1C
7290 +#define IO_TX_FIFO 0x20
7291 +#define IO_TX_FIFO_HI 0x24
7292 +#define IO_RX_FIFO 0x28
7293 +#define IO_RX_FIFO_HI 0x2c
7294 +#define IO_CTL0 0x30
7295 +#define IO_CTL1 0x34
7296 +#define IO_CTL2 0x38
7297 +#define IO_STATUS0 0x3c
7298 +#define IO_STATUS1 0x40
7299 +#define IO_STATUS2 0x44
7300 +#define IO_FIFO_WATER 0x48
7301 +#define IO_FIFO_LEVEL 0x4c
7302 +#define IO_GPIO_MASK 0x50
7304 +#define IO_FUNC_FUNCTION_RESET(func) ((1 << ((func) - 1)) << 4) /* Function 0 doesn't need reset */
7305 +#define IO_FUNC_RX_FIFO (1 << 3)
7306 +#define IO_FUNC_SELECT(func) ((func) << 0)
7309 + * External interrupt pins.
7311 +#define EXT_INT_IO_BIT(pin) ((pin) + 5) // Interrupt pin number -> I/O INT bit
7312 +#define EXT_INT_RISING_EDGE(pin) (0x2 << (2*(pin) + 7))
7313 +#define EXT_INT_FALLING_EDGE(pin) (0x1 << (2*(pin) + 7))
7318 +#define IO_XFL_BASE RA
7320 +#define IO_XFL_INT_START (1 << 16)
7321 +#define IO_XFL_INT_ERR (1 << 8)
7322 +#define IO_XFL_INT_DONE (1 << 0)
7324 +#define IO_XFL_CTL0_MASK (0xffe07fff)
7325 +#define IO_XFL_CTL0_RD_CMD(cmd) (((cmd) & 0xff) << 24)
7326 +#define IO_XFL_CTL0_RD_DUMMY(n) (((n) & 0x7) << 21)
7327 +#define IO_XFL_CTL0_CLK_WIDTH(core_cycles) ((((core_cycles) + 1) & 0x7e) << 8) /* must be even number */
7328 +#define IO_XFL_CTL0_CE_WAIT(spi_cycles) (((spi_cycles) & 0x3f) << 2)
7329 +#define IO_XFL_CTL0_MCB_LOCK (1 << 1)
7330 +#define IO_XFL_CTL0_ENABLE (1 << 0)
7331 +#define IO_XFL_CTL0_FAST_VALUE(div, wait) (IO_XFL_CTL0_RD_CMD(0xb) | IO_XFL_CTL0_RD_DUMMY(1) | IO_XFL_CTL0_CLK_WIDTH(div) | IO_XFL_CTL0_CE_WAIT(wait) | IO_XFL_CTL0_ENABLE)
7332 +#define IO_XFL_CTL0_VALUE(div, wait) (IO_XFL_CTL0_RD_CMD(3) | IO_XFL_CTL0_CLK_WIDTH(div) | IO_XFL_CTL0_CE_WAIT(wait) | IO_XFL_CTL0_ENABLE)
7334 +#define IO_XFL_CTL1_MASK (0xc0003fff)
7335 +#define IO_XFL_CTL1_FC_INST(inst) (((inst) & 0x3) << 30)
7336 +#define IO_XFL_CTL1_FC_DATA(n) (((n) & 0x3ff) << 4)
7337 +#define IO_XFL_CTL1_FC_DUMMY(n) (((n) & 0x7) << 1)
7338 +#define IO_XFL_CTL1_FC_ADDR (1 << 0)
7340 +#define IO_XFL_CTL2_FC_CMD(cmd) (((cmd) & 0xff) << 24)
7341 +#define IO_XFL_CTL2_FC_ADDR(addr) ((addr) & 0x00ffffff) /* Only up to 24 bits */
7343 +#define IO_XFL_STATUS0_MCB_ACTIVE (1 << 0)
7344 +#define IO_XFL_STATUS0_IOPCS_ACTIVE (1 << 1)
7349 +#define IO_SDRAM_DATA_BASE RG
7350 +#define IO_SDRAM_CNTL_BASE RH
7352 +#define IO_SDRAM_CTRL0_EN_REF (1 << 0)
7355 + * Port function code (common fucntion codes for all I/O ports)
7357 +#define IO_PORTX_FUNC_GPIO 0x00
7358 +#define IO_PORTX_FUNC_XFL 0x01
7359 +#define IO_PORTX_FUNC_PCI 0x01
7360 +#define IO_PORTX_FUNC_SERDES 0x01
7361 +#define IO_PORTX_FUNC_GMII 0x01
7362 +#define IO_PORTX_FUNC_DDR 0x01
7363 +#define IO_PORTX_FUNC_PCIX 0x01
7364 +#define IO_PORTX_FUNC_USB2_0 0x01
7365 +#define IO_PORTX_FUNC_GPIO_INT_CLK 0x02
7366 +#define IO_PORTX_FUNC_PLIO 0x02
7367 +#define IO_PORTX_FUNC_GPIO_INT 0x03
7368 +#define IO_PORTX_FUNC_MII 0x03
7373 +#define IO_PORT0_FUNC_GPIO IO_PORTX_FUNC_GPIO
7374 +#define IO_PORT0_FUNC_XFL_INT_CLK IO_PORTX_FUNC_XFL // Default mode after reset
7375 +#define IO_PORT0_FUNC_GPIO_INT_CLK IO_PORTX_FUNC_GPIO_INT_CLK
7376 +#define IO_PORT0_FUNC_GPIO_INT IO_PORTX_FUNC_GPIO_INT
7381 +#define IO_PORT1_FUNC_GPIO IO_PORTX_FUNC_GPIO
7382 +#define IO_PORT1_FUNC_PCI IO_PORTX_FUNC_PCI // PCI control
7383 +#define IO_PORT1_FUNC_MII IO_PORTX_FUNC_MII // port 4 MII extension
7388 +#define IO_PORT2_FUNC_GPIO IO_PORTX_FUNC_GPIO
7389 +#define IO_PORT2_FUNC_PCI IO_PORTX_FUNC_PCI // PCI data I/O
7390 +#define IO_PORT2_FUNC_PLIO IO_PORTX_FUNC_PLIO // Extended LM
7395 +#define IO_PORT3_FUNC_GPIO IO_PORTX_FUNC_GPIO
7396 +#define IO_PORT3_FUNC_SERDES IO_PORTX_FUNC_SERDES
7397 +#define IO_PORT3_FUNC_PLIO IO_PORTX_FUNC_PLIO
7402 +#define IO_PORT4_FUNC_GPIO IO_PORTX_FUNC_GPIO
7403 +#define IO_PORT4_FUNC_SERDES IO_PORTX_FUNC_SERDES
7404 +#define IO_PORT4_FUNC_PLIO IO_PORTX_FUNC_PLIO // Extended LM
7405 +#define IO_PORT4_FUNC_MII IO_PORTX_FUNC_MII
7410 +#define IO_PORT5_FUNC_GPIO IO_PORTX_FUNC_GPIO
7411 +#define IO_PORT5_FUNC_GMII IO_PORTX_FUNC_GMII
7416 +#define IO_PORT6_FUNC_GPIO IO_PORTX_FUNC_GPIO
7417 +#define IO_PORT6_FUNC_DDR IO_PORTX_FUNC_DDR
7422 +#define IO_PORT7_FUNC_GPIO IO_PORTX_FUNC_GPIO
7423 +#define IO_PORT7_FUNC_DDR IO_PORTX_FUNC_DDR
7428 +#define IO_PORT8_FUNC_GPIO IO_PORTX_FUNC_GPIO
7429 +#define IO_PORT8_FUNC_PCIX IO_PORTX_FUNC_PCIX
7430 +#define IO_PORT8_FUNC_PLIO IO_PORTX_FUNC_PLIO // Extended LM
7431 +#define IO_PORT8_FUNC_MII IO_PORTX_FUNC_MII // port 4 MII extension
7436 +#define IO_PORT9_FUNC_USB2_0 IO_PORTX_FUNC_USB2_0
7441 +#define IO_PORTX_INT_FIFO_TX_RESET (1 << 31)
7442 +#define IO_PORTX_INT_FIFO_RX_RESET (1 << 30)
7443 +#define IO_PORTX_INT_FIFO_TX_UF (1 << 15)
7444 +#define IO_PORTX_INT_FIFO_TX_WM (1 << 14)
7445 +#define IO_PORTX_INT_FIFO_RX_OF (1 << 13)
7446 +#define IO_PORTX_INT_FIFO_RX_WM (1 << 12)
7448 +#define IO_PORTX_FUNC_FIFO_TX_WM(n) ((n) << 16)
7449 +#define IO_PORTX_FUNC_FIFO_RX_WM(n) ((n) << 0)
7454 +#define IO_PORTX_INT_MII_TX_ERR_SEND (1 << 18)
7455 +#define IO_PORTX_INT_MII_TX_HALT (1 << 17)
7456 +#define IO_PORTX_INT_MII_TX_START (1 << 16)
7457 +#define IO_PORTX_INT_MII_THRESHOLD (1 << 8)
7458 +#define IO_PORTX_INT_MII_RX_EOP (1 << 7)
7459 +#define IO_PORTX_INT_MII_RX_SFD (1 << 6)
7460 +#define IO_PORTX_INT_MII_RX_ERR (1 << 5)
7461 +#define IO_PORTX_INT_MII_TX_EOP (1 << 4)
7462 +#define IO_PORTX_INT_MII_COL (1 << 3)
7463 +#define IO_PORTX_INT_MII_CRS (1 << 2)
7464 +#define IO_PORTX_INT_MII_ODD_NIB_ERR (1 << 1)
7465 +#define IO_PORTX_INT_MII_FALSE_CARRIER (1 << 0)
7470 +#define IO_PORTX_INT_SERDES_TXBUF_VALID (1 << 16)
7471 +#define IO_PORTX_INT_SERDES_RXERR (1 << 7)
7472 +#define IO_PORTX_INT_SERDES_RXEOP (1 << 6)
7473 +#define IO_PORTX_INT_SERDES_SYND (1 << 5)
7474 +#define IO_PORTX_INT_SERDES_TXBE (1 << 4)
7475 +#define IO_PORTX_INT_SERDES_TXEOP (1 << 3)
7476 +#define IO_PORTX_INT_SERDES_SXLP (1 << 2)
7477 +#define IO_PORTX_INT_SERDES_RXBF (1 << 1)
7478 +#define IO_PORTX_INT_SERDES_RXCRS (1 << 0)
7480 +#ifndef __ASSEMBLY__
7481 +struct ubicom32_io_port {
7482 + volatile u32_t function;
7483 + volatile u32_t gpio_ctl;
7484 + volatile u32_t gpio_out;
7485 + volatile u32_t gpio_in;
7486 + volatile u32_t int_status;
7487 + volatile u32_t int_mask;
7488 + volatile u32_t int_set;
7489 + volatile u32_t int_clr;
7490 + volatile u32_t tx_fifo;
7491 + volatile u32_t tx_fifo_hi;
7492 + volatile u32_t rx_fifo;
7493 + volatile u32_t rx_fifo_hi;
7494 + volatile u32_t ctl0;
7495 + volatile u32_t ctl1;
7496 + volatile u32_t ctl2;
7497 + volatile u32_t status0;
7498 + volatile u32_t status1;
7499 + volatile u32_t status2;
7500 + volatile u32_t fifo_watermark;
7501 + volatile u32_t fifo_level;
7502 + volatile u32_t gpio_mask;
7505 +#define UBICOM32_IO_PORT(port) ((struct ubicom32_io_port *)((port)))
7508 +#ifndef __ASSEMBLY__
7510 + * ubicom32_set_interrupt()
7512 +extern inline void ubicom32_set_interrupt(u8_t interrupt)
7514 + u32_t ibit = INT_BIT_MASK(interrupt);
7516 + if (INT_REG(interrupt) == INT_REG(INT_CHIP(0, 0))) {
7518 + "move.4 "D(INT_SET(INT_CHIP(0, 0)))", %0\n\t"
7527 + "move.4 "D(INT_SET(INT_CHIP(1, 0)))", %0\n\t"
7534 + * ubicom32_clear_interrupt()
7536 +extern inline void ubicom32_clear_interrupt(u8_t interrupt)
7538 + u32_t ibit = INT_BIT_MASK(interrupt);
7540 + if (INT_REG(interrupt) == INT_REG(INT_CHIP(0, 0))) {
7542 + "move.4 "D(INT_CLR(INT_CHIP(0, 0)))", %0\n\t"
7551 + "move.4 "D(INT_CLR(INT_CHIP(1, 0)))", %0\n\t"
7558 + * ubicom32_enable_interrupt()
7560 +extern inline void ubicom32_enable_interrupt(u8_t interrupt)
7562 + u32_t ibit = INT_BIT_MASK(interrupt);
7564 + if (INT_REG(interrupt) == INT_REG(INT_CHIP(0, 0))) {
7566 + "or.4 "D(INT_MASK(INT_CHIP(0, 0)))", "D(INT_MASK(INT_CHIP(0, 0)))", %0\n\t"
7575 + "or.4 "D(INT_MASK(INT_CHIP(1, 0)))", "D(INT_MASK(INT_CHIP(1, 0)))", %0\n\t"
7582 + * ubicom32_disable_interrupt()
7584 +extern inline void ubicom32_disable_interrupt(u8_t interrupt)
7586 + u32_t ibit = ~INT_BIT_MASK(interrupt);
7588 + if (INT_REG(interrupt) == INT_REG(INT_CHIP(0, 0))) {
7590 + "and.4 "D(INT_MASK(INT_CHIP(0, 0)))", "D(INT_MASK(INT_CHIP(0, 0)))", %0\n\t"
7599 + "and.4 "D(INT_MASK(INT_CHIP(1, 0)))", "D(INT_MASK(INT_CHIP(1, 0)))", %0\n\t"
7606 + * ubicom32_enable_global_interrupts()
7608 +extern inline void ubicom32_enable_global_interrupts(void)
7611 + "bset GLOBAL_CTRL, GLOBAL_CTRL, #%bit("D(GLOBAL_CTRL_INT_EN)")"
7616 + * ubicom32_disable_global_interrupts()
7618 +extern inline void ubicom32_disable_global_interrupts(void)
7621 + "bclr GLOBAL_CTRL, GLOBAL_CTRL, #%bit("D(GLOBAL_CTRL_INT_EN)")"
7626 + * ubicom32_get_reset_reason()
7628 +extern inline u32_t ubicom32_get_reset_reason(void)
7630 + return *(u32_t *)(GENERAL_CFG_BASE + GEN_RESET_REASON);
7634 + * ubicom32_read_reg()
7636 +extern inline u32_t ubicom32_read_reg(volatile void *reg)
7640 + "move.4 %[dest], %[src] \n\t"
7642 + : [src] "m" (*(u32_t *)reg)
7648 + * ubicom32_write_reg()
7650 +extern inline void ubicom32_write_reg(volatile void *reg, u32_t v)
7653 + "move.4 %[dest], %[src] \n\t"
7655 + : [src] "r" (v), [dest] "m" (*(u32_t *)reg)
7659 +#endif /* __ASSEMBLY__ */
7660 +#endif /* _ASM_UBICOM32_IP5000_H */
7661 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ipcbuf.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ipcbuf.h
7662 --- linux-2.6.30.10/arch/ubicom32/include/asm/ipcbuf.h 1970-01-01 02:00:00.000000000 +0200
7663 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ipcbuf.h 2009-12-11 11:45:11.000000000 +0200
7666 + * arch/ubicom32/include/asm/ipcbuf.h
7667 + * Definition of ipc64_perm struct for Ubicom32 architecture.
7669 + * (C) Copyright 2009, Ubicom, Inc.
7671 + * This file is part of the Ubicom32 Linux Kernel Port.
7673 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
7674 + * it and/or modify it under the terms of the GNU General Public License
7675 + * as published by the Free Software Foundation, either version 2 of the
7676 + * License, or (at your option) any later version.
7678 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
7679 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
7680 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
7681 + * the GNU General Public License for more details.
7683 + * You should have received a copy of the GNU General Public License
7684 + * along with the Ubicom32 Linux Kernel Port. If not,
7685 + * see <http://www.gnu.org/licenses/>.
7687 + * Ubicom32 implementation derived from (with many thanks):
7692 +#ifndef _ASM_UBICOM32_IPCBUF_H
7693 +#define _ASM_UBICOM32_IPCBUF_H
7696 + * The user_ipc_perm structure for m68k architecture.
7697 + * Note extra padding because this structure is passed back and forth
7698 + * between kernel and user space.
7700 + * Pad space is left for:
7701 + * - 32-bit mode_t and seq
7702 + * - 2 miscellaneous 32-bit values
7706 + __kernel_key_t key;
7707 + __kernel_uid32_t uid;
7708 + __kernel_gid32_t gid;
7709 + __kernel_uid32_t cuid;
7710 + __kernel_gid32_t cgid;
7711 + __kernel_mode_t mode;
7712 + unsigned short __pad1;
7713 + unsigned short seq;
7714 + unsigned short __pad2;
7715 + unsigned long __unused1;
7716 + unsigned long __unused2;
7719 +#endif /* _ASM_UBICOM32_IPCBUF_H */
7720 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/irqflags.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/irqflags.h
7721 --- linux-2.6.30.10/arch/ubicom32/include/asm/irqflags.h 1970-01-01 02:00:00.000000000 +0200
7722 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/irqflags.h 2009-12-11 11:45:11.000000000 +0200
7725 + * arch/ubicom32/include/asm/irqflags.h
7726 + * Raw implementation of local IRQ functions.
7728 + * (C) Copyright 2009, Ubicom, Inc.
7730 + * This file is part of the Ubicom32 Linux Kernel Port.
7732 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
7733 + * it and/or modify it under the terms of the GNU General Public License
7734 + * as published by the Free Software Foundation, either version 2 of the
7735 + * License, or (at your option) any later version.
7737 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
7738 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
7739 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
7740 + * the GNU General Public License for more details.
7742 + * You should have received a copy of the GNU General Public License
7743 + * along with the Ubicom32 Linux Kernel Port. If not,
7744 + * see <http://www.gnu.org/licenses/>.
7746 + * Ubicom32 implementation derived from (with many thanks):
7751 +#ifndef _ASM_UBICOM32_IRQFLAGS_H
7752 +#define _ASM_UBICOM32_IRQFLAGS_H
7754 +#include <linux/thread_info.h>
7755 +#include <asm/ubicom32-common.h>
7756 +#if defined(CONFIG_SMP)
7757 +#include <asm/smp.h>
7759 +#include <asm/ldsr.h>
7761 +#if defined(CONFIG_PREEMPT)
7762 +#error Not supported by Ubicom32 irq handling, yet!
7766 + * raw_local_irq_enable()
7767 + * Enable interrupts for this thread.
7769 +static inline void raw_local_irq_enable(void)
7771 + ldsr_local_irq_enable();
7775 + * raw_local_irq_disable()
7776 + * Disable interrupts for this thread.
7778 +static inline void raw_local_irq_disable(void)
7780 + ldsr_local_irq_disable();
7784 + * raw_local_save_flags()
7785 + * Get the current IRQ state.
7787 +#define raw_local_save_flags(flags) \
7789 + (flags) = ldsr_local_irq_is_disabled(); \
7793 + * raw_local_irq_save()
7794 + * Save the current interrupt state and disable interrupts.
7796 +#define raw_local_irq_save(flags) \
7798 + (flags) = ldsr_local_irq_save(); \
7802 + * raw_local_irq_restore()
7803 + * Restore the IRQ state back to flags.
7805 +static inline void raw_local_irq_restore(unsigned long flags)
7807 + ldsr_local_irq_restore(flags);
7811 + * raw_irqs_disabled_flags()
7812 + * Return true if the flags indicate that IRQ(s) are disabled.
7814 +static inline int raw_irqs_disabled_flags(unsigned long flags)
7819 +#endif /* _ASM_UBICOM32_IRQFLAGS_H */
7820 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/irq.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/irq.h
7821 --- linux-2.6.30.10/arch/ubicom32/include/asm/irq.h 1970-01-01 02:00:00.000000000 +0200
7822 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/irq.h 2009-12-11 11:45:11.000000000 +0200
7825 + * arch/ubicom32/include/asm/irq.h
7826 + * IRQ definitions for Ubicom32 architecture.
7828 + * (C) Copyright 2009, Ubicom, Inc.
7830 + * This file is part of the Ubicom32 Linux Kernel Port.
7832 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
7833 + * it and/or modify it under the terms of the GNU General Public License
7834 + * as published by the Free Software Foundation, either version 2 of the
7835 + * License, or (at your option) any later version.
7837 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
7838 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
7839 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
7840 + * the GNU General Public License for more details.
7842 + * You should have received a copy of the GNU General Public License
7843 + * along with the Ubicom32 Linux Kernel Port. If not,
7844 + * see <http://www.gnu.org/licenses/>.
7846 + * Ubicom32 implementation derived from (with many thanks):
7851 +#ifndef _ASM_UBICOM32_IRQ_H
7852 +#define _ASM_UBICOM32_IRQ_H
7854 +#include <asm/irqflags.h>
7857 + * We setup the IRQS to cover the full range of interrupt registers in
7862 +#define irq_canonicalize(irq) (irq)
7864 +extern int irq_soft_alloc(unsigned int *soft);
7865 +extern void ack_bad_irq(unsigned int irq);
7866 +extern void do_IRQ(int irq, struct pt_regs *fp);
7868 +#endif /* _ASM_UBICOM32_IRQ_H */
7869 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/irq_regs.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/irq_regs.h
7870 --- linux-2.6.30.10/arch/ubicom32/include/asm/irq_regs.h 1970-01-01 02:00:00.000000000 +0200
7871 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/irq_regs.h 2009-12-11 11:45:11.000000000 +0200
7874 + * arch/ubicom32/include/asm/irq_regs.h
7875 + * Generic irq_regs.h for Ubicom32 architecture.
7877 + * (C) Copyright 2009, Ubicom, Inc.
7879 + * This file is part of the Ubicom32 Linux Kernel Port.
7881 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
7882 + * it and/or modify it under the terms of the GNU General Public License
7883 + * as published by the Free Software Foundation, either version 2 of the
7884 + * License, or (at your option) any later version.
7886 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
7887 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
7888 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
7889 + * the GNU General Public License for more details.
7891 + * You should have received a copy of the GNU General Public License
7892 + * along with the Ubicom32 Linux Kernel Port. If not,
7893 + * see <http://www.gnu.org/licenses/>.
7895 + * Ubicom32 implementation derived from (with many thanks):
7900 +#ifndef _ASM_UBICOM32_IRQ_REGS_H
7901 +#define _ASM_UBICOM32_IRQ_REGS_H
7903 +#include <asm-generic/irq_regs.h>
7905 +#endif /* _ASM_UBICOM32_IRQ_REGS_H */
7906 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/Kbuild linux-2.6.30.10-ubi/arch/ubicom32/include/asm/Kbuild
7907 --- linux-2.6.30.10/arch/ubicom32/include/asm/Kbuild 1970-01-01 02:00:00.000000000 +0200
7908 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/Kbuild 2009-12-11 11:45:11.000000000 +0200
7910 +include include/asm-generic/Kbuild.asm
7911 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/kdebug.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/kdebug.h
7912 --- linux-2.6.30.10/arch/ubicom32/include/asm/kdebug.h 1970-01-01 02:00:00.000000000 +0200
7913 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/kdebug.h 2009-12-11 11:45:11.000000000 +0200
7916 + * arch/ubicom32/include/asm/kdebug.h
7917 + * Generic kdebug.h for Ubicom32 architecture.
7919 + * (C) Copyright 2009, Ubicom, Inc.
7921 + * This file is part of the Ubicom32 Linux Kernel Port.
7923 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
7924 + * it and/or modify it under the terms of the GNU General Public License
7925 + * as published by the Free Software Foundation, either version 2 of the
7926 + * License, or (at your option) any later version.
7928 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
7929 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
7930 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
7931 + * the GNU General Public License for more details.
7933 + * You should have received a copy of the GNU General Public License
7934 + * along with the Ubicom32 Linux Kernel Port. If not,
7935 + * see <http://www.gnu.org/licenses/>.
7937 + * Ubicom32 implementation derived from (with many thanks):
7942 +#ifndef _ASM_UBICOM32_KDEBUG_H
7943 +#define _ASM_UBICOM32_KDEBUG_H
7945 +#include <asm-generic/kdebug.h>
7947 +#endif /* _ASM_UBICOM32_KDEBUG_H */
7948 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/kmap_types.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/kmap_types.h
7949 --- linux-2.6.30.10/arch/ubicom32/include/asm/kmap_types.h 1970-01-01 02:00:00.000000000 +0200
7950 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/kmap_types.h 2009-12-11 11:45:11.000000000 +0200
7953 + * arch/ubicom32/include/asm/kmap_types.h
7954 + * Definition of km_type's for Ubicom32 architecture.
7956 + * (C) Copyright 2009, Ubicom, Inc.
7958 + * This file is part of the Ubicom32 Linux Kernel Port.
7960 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
7961 + * it and/or modify it under the terms of the GNU General Public License
7962 + * as published by the Free Software Foundation, either version 2 of the
7963 + * License, or (at your option) any later version.
7965 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
7966 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
7967 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
7968 + * the GNU General Public License for more details.
7970 + * You should have received a copy of the GNU General Public License
7971 + * along with the Ubicom32 Linux Kernel Port. If not,
7972 + * see <http://www.gnu.org/licenses/>.
7974 + * Ubicom32 implementation derived from (with many thanks):
7979 +#ifndef _ASM_UBICOM32_KMAP_TYPES_H
7980 +#define _ASM_UBICOM32_KMAP_TYPES_H
7984 + KM_SKB_SUNRPC_DATA,
7985 + KM_SKB_DATA_SOFTIRQ,
7999 +#endif /* _ASM_UBICOM32_KMAP_TYPES_H */
8000 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ldsr.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ldsr.h
8001 --- linux-2.6.30.10/arch/ubicom32/include/asm/ldsr.h 1970-01-01 02:00:00.000000000 +0200
8002 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ldsr.h 2009-12-11 11:45:11.000000000 +0200
8005 + * arch/ubicom32/include/asm/ldsr.h
8006 + * Ubicom32 LDSR interface definitions.
8008 + * (C) Copyright 2009, Ubicom, Inc.
8010 + * This file is part of the Ubicom32 Linux Kernel Port.
8012 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8013 + * it and/or modify it under the terms of the GNU General Public License
8014 + * as published by the Free Software Foundation, either version 2 of the
8015 + * License, or (at your option) any later version.
8017 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8018 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8019 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
8020 + * the GNU General Public License for more details.
8022 + * You should have received a copy of the GNU General Public License
8023 + * along with the Ubicom32 Linux Kernel Port. If not,
8024 + * see <http://www.gnu.org/licenses/>.
8026 + * Ubicom32 implementation derived from (with many thanks):
8031 +#ifndef _ASM_UBICOM32_LDSR_H
8032 +#define _ASM_UBICOM32_LDSR_H
8034 +#include <asm/ubicom32-common.h>
8035 +#include <asm/types.h>
8036 +#include <asm/thread.h>
8038 +extern unsigned int ldsr_soft_irq_mask;
8041 + * ldsr_local_irq_is_disabled()
8042 + * Test if interrupts are disabled for this thread?
8044 +static inline int ldsr_local_irq_is_disabled(void)
8047 + thread_t self = thread_get_self();
8048 + unsigned int mask = (1 << self);
8051 + " and.4 %0, scratchpad1, %1 \n\t"
8058 + * We return a simple 1 == disabled, 0 == enabled
8059 + * losing which tid this is for, because Linux
8060 + * can restore interrupts on a different thread.
8062 + return ret >> self;
8066 + * ldsr_local_irq_save()
8067 + * Get the current interrupt state and disable interrupts.
8069 +static inline unsigned int ldsr_local_irq_save(void)
8072 + thread_t self = thread_get_self();
8073 + unsigned int mask = (1 << self);
8076 + * Ensure the compiler can not optimize out the code
8077 + * (volatile) and that it does not "cache" values around
8078 + * the interrupt state change (memory). This ensures
8079 + * that interrupt changes are treated as a critical
8083 + " and.4 %0, scratchpad1, %1 \n\t"
8084 + " or.4 scratchpad1, scratchpad1, %1 \n\t"
8091 + * We return a simple 1 == disabled, 0 == enabled
8092 + * losing which tid this is for, because Linux
8093 + * can restore interrupts on a different thread.
8095 + return ret >> self;
8099 + * ldsr_local_irq_restore()
8100 + * Restore this cpu's interrupt enable/disable state.
8102 + * Note: flags is either 0 or 1.
8104 +static inline void ldsr_local_irq_restore(unsigned int flags)
8106 + unsigned int temp;
8107 + thread_t self = thread_get_self();
8108 + unsigned int mask = (1 << self);
8109 + flags = (flags << self);
8112 + * Ensure the compiler can not optimize out the code
8113 + * (volatile) and that it does not "cache" values around
8114 + * the interrupt state change (memory). This ensures
8115 + * that interrupt changes are treated as a critical
8118 + * Atomic change to our bit in scratchpad1 without
8119 + * causing any temporary glitch in the value and
8120 + * without effecting other values. Also this uses
8121 + * no branches so no penalties.
8124 + " xor.4 %0, scratchpad1, %1 \n\t"
8125 + " and.4 %0, %2, %0 \n\t"
8126 + " xor.4 scratchpad1, scratchpad1, %0 \n\t"
8127 + " move.4 int_set0, %3 \n\t"
8129 + : "d"(flags), "r"(mask), "r"(ldsr_soft_irq_mask)
8135 + * ldsr_local_irq_disable_interrupt()
8136 + * Disable ints for this thread.
8138 +static inline void ldsr_local_irq_disable(void)
8140 + unsigned int mask = (1 << thread_get_self());
8143 + * Ensure the compiler can not optimize out the code
8144 + * (volatile) and that it does not "cache" values around
8145 + * the interrupt state change (memory). This ensures
8146 + * that interrupt changes are treated as a critical
8150 + " or.4 scratchpad1, scratchpad1, %0 \n\t"
8158 + * ldsr_local_irq_enable_interrupt
8159 + * Enable ints for this thread.
8161 +static inline void ldsr_local_irq_enable(void)
8163 + unsigned int mask = (1 << thread_get_self());
8166 + * Ensure the compiler can not optimize out the code
8167 + * (volatile) and that it does not "cache" values around
8168 + * the interrupt state change (memory). This ensures
8169 + * that interrupt changes are treated as a critical
8173 + " and.4 scratchpad1, scratchpad1, %0 \n\t"
8174 + " move.4 int_set0, %1 \n\t"
8176 + : "d" (~mask), "r" (ldsr_soft_irq_mask)
8181 +extern void ldsr_init(void);
8182 +extern void ldsr_set_trap_irq(unsigned int irq);
8183 +extern void ldsr_mask_vector(unsigned int vector);
8184 +extern void ldsr_unmask_vector(unsigned int vector);
8185 +extern void ldsr_enable_vector(unsigned int vector);
8186 +extern void ldsr_disable_vector(unsigned int vector);
8187 +extern thread_t ldsr_get_threadid(void);
8189 +#endif /* _ASM_UBICOM32_LDSR_H */
8190 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/linkage.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/linkage.h
8191 --- linux-2.6.30.10/arch/ubicom32/include/asm/linkage.h 1970-01-01 02:00:00.000000000 +0200
8192 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/linkage.h 2009-12-11 11:45:11.000000000 +0200
8195 + * arch/ubicom32/include/asm/linkage.h
8196 + * Definition of Ubicom32 architecture specific linkage types.
8198 + * (C) Copyright 2009, Ubicom, Inc.
8200 + * This file is part of the Ubicom32 Linux Kernel Port.
8202 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8203 + * it and/or modify it under the terms of the GNU General Public License
8204 + * as published by the Free Software Foundation, either version 2 of the
8205 + * License, or (at your option) any later version.
8207 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8208 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8209 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
8210 + * the GNU General Public License for more details.
8212 + * You should have received a copy of the GNU General Public License
8213 + * along with the Ubicom32 Linux Kernel Port. If not,
8214 + * see <http://www.gnu.org/licenses/>.
8216 + * Ubicom32 implementation derived from (with many thanks):
8221 +#ifndef _ASM_UBICOM32_LINKAGE_H
8222 +#define _ASM_UBICOM32_LINKAGE_H
8224 +#define __ocm_text __section(.ocm_text)
8225 +#define __ocm_data __section(.ocm_data)
8227 +#endif /* _ASM_UBICOM32_LINKAGE_H */
8228 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/local.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/local.h
8229 --- linux-2.6.30.10/arch/ubicom32/include/asm/local.h 1970-01-01 02:00:00.000000000 +0200
8230 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/local.h 2009-12-11 11:45:11.000000000 +0200
8233 + * arch/ubicom32/include/asm/local.h
8234 + * Generic local.h for Ubicom32 architecture.
8236 + * (C) Copyright 2009, Ubicom, Inc.
8238 + * This file is part of the Ubicom32 Linux Kernel Port.
8240 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8241 + * it and/or modify it under the terms of the GNU General Public License
8242 + * as published by the Free Software Foundation, either version 2 of the
8243 + * License, or (at your option) any later version.
8245 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8246 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8247 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
8248 + * the GNU General Public License for more details.
8250 + * You should have received a copy of the GNU General Public License
8251 + * along with the Ubicom32 Linux Kernel Port. If not,
8252 + * see <http://www.gnu.org/licenses/>.
8254 + * Ubicom32 implementation derived from (with many thanks):
8259 +#ifndef _ASM_UBICOM32_LOCAL_H
8260 +#define _ASM_UBICOM32_LOCAL_H
8262 +#include <asm-generic/local.h>
8264 +#endif /* _ASM_UBICOM32_LOCAL_H */
8265 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/machdep.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/machdep.h
8266 --- linux-2.6.30.10/arch/ubicom32/include/asm/machdep.h 1970-01-01 02:00:00.000000000 +0200
8267 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/machdep.h 2009-12-11 11:45:11.000000000 +0200
8270 + * arch/ubicom32/include/asm/machdep.h
8271 + * Machine dependent utility routines.
8273 + * (C) Copyright 2009, Ubicom, Inc.
8275 + * This file is part of the Ubicom32 Linux Kernel Port.
8277 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8278 + * it and/or modify it under the terms of the GNU General Public License
8279 + * as published by the Free Software Foundation, either version 2 of the
8280 + * License, or (at your option) any later version.
8282 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8283 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8284 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
8285 + * the GNU General Public License for more details.
8287 + * You should have received a copy of the GNU General Public License
8288 + * along with the Ubicom32 Linux Kernel Port. If not,
8289 + * see <http://www.gnu.org/licenses/>.
8291 + * Ubicom32 implementation derived from (with many thanks):
8296 +#ifndef _ASM_UBICOM32_MACHDEP_H
8297 +#define _ASM_UBICOM32_MACHDEP_H
8299 +#include <linux/interrupt.h>
8301 +/* Hardware clock functions */
8302 +extern unsigned long hw_timer_offset(void);
8304 +/* machine dependent power off functions */
8305 +extern void (*mach_reset)(void);
8306 +extern void (*mach_halt)(void);
8307 +extern void (*mach_power_off)(void);
8309 +extern void config_BSP(char *command, int len);
8311 +#endif /* _ASM_UBICOM32_MACHDEP_H */
8312 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/mc146818rtc.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/mc146818rtc.h
8313 --- linux-2.6.30.10/arch/ubicom32/include/asm/mc146818rtc.h 1970-01-01 02:00:00.000000000 +0200
8314 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/mc146818rtc.h 2009-12-11 11:45:11.000000000 +0200
8317 + * arch/ubicom32/include/asm/mc146818rtc.h
8318 + * Generic mc146818rtc.h for Ubicom32 architecture.
8320 + * (C) Copyright 2009, Ubicom, Inc.
8322 + * This file is part of the Ubicom32 Linux Kernel Port.
8324 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8325 + * it and/or modify it under the terms of the GNU General Public License
8326 + * as published by the Free Software Foundation, either version 2 of the
8327 + * License, or (at your option) any later version.
8329 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8330 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8331 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
8332 + * the GNU General Public License for more details.
8334 + * You should have received a copy of the GNU General Public License
8335 + * along with the Ubicom32 Linux Kernel Port. If not,
8336 + * see <http://www.gnu.org/licenses/>.
8338 + * Ubicom32 implementation derived from (with many thanks):
8344 + * Machine dependent access functions for RTC registers.
8346 +#ifndef _ASM_UBICOM32_MC146818RTC_H
8347 +#define _ASM_UBICOM32_MC146818RTC_H
8349 +/* empty include file to satisfy the include in genrtc.c/ide-geometry.c */
8351 +#endif /* _ASM_UBICOM32_MC146818RTC_H */
8352 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/memory_map.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/memory_map.h
8353 --- linux-2.6.30.10/arch/ubicom32/include/asm/memory_map.h 1970-01-01 02:00:00.000000000 +0200
8354 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/memory_map.h 2009-12-11 11:45:11.000000000 +0200
8357 + * arch/ubicom32/include/asm/memory_map.h
8358 + * Machine memory maps/
8360 + * (C) Copyright 2009, Ubicom, Inc.
8362 + * This file is part of the Ubicom32 Linux Kernel Port.
8364 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8365 + * it and/or modify it under the terms of the GNU General Public License
8366 + * as published by the Free Software Foundation, either version 2 of the
8367 + * License, or (at your option) any later version.
8369 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8370 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8371 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
8372 + * the GNU General Public License for more details.
8374 + * You should have received a copy of the GNU General Public License
8375 + * along with the Ubicom32 Linux Kernel Port. If not,
8376 + * see <http://www.gnu.org/licenses/>.
8378 + * Ubicom32 implementation derived from (with many thanks):
8383 +#ifndef _ASM_UBICOM32_MEMORY_MAP_H
8384 +#define _ASM_UBICOM32_MEMORY_MAP_H
8389 +#define OCM_SECTOR_SIZE 0x00008000 /* 32K */
8391 +#if defined(CONFIG_UBICOM32_V3)
8392 +#define OCMSIZE 0x00030000 /* 192K on-chip RAM for both program and data */
8393 +#elif defined(CONFIG_UBICOM32_V4)
8394 +#define OCMSIZE 0x0003C000 /* 240K on-chip RAM for both program and data */
8396 +#error "Unknown IP5K silicon"
8399 +#define OCMSTART 0x3ffc0000 /* alias from 0x03000000 for easy
8400 + * jump to/from SDRAM */
8401 +#define OCMEND (OCMSTART + OCMSIZE)
8403 +#define SDRAMSTART 0x40000000
8405 +#define KERNELSTART (SDRAMSTART + 0x00400000)
8407 +#define FLASHSTART 0x60000000
8410 + * CODELOADER / OS_SYSCALL OCM Reservations
8411 + * Don't change these unless you know what you are doing.
8413 +#define CODELOADER_SIZE 0x30
8414 +#define CODELOADER_BEGIN OCMSTART /* Must be OCM start for gdb to work. */
8415 +#define CODELOADER_END (CODELOADER_BEGIN + CODELOADER_SIZE)
8417 +#define OS_SYSCALL_BEGIN CODELOADER_END /* system_call at this address */
8418 +#define OS_SYSCALL_SIZE (512 - CODELOADER_SIZE)
8419 +#define OS_SYSCALL_END (OS_SYSCALL_BEGIN + OS_SYSCALL_SIZE)
8421 +#endif /* _ASM_UBICOM32_MEMORY_MAP_H */
8422 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/mman.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/mman.h
8423 --- linux-2.6.30.10/arch/ubicom32/include/asm/mman.h 1970-01-01 02:00:00.000000000 +0200
8424 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/mman.h 2009-12-11 11:45:11.000000000 +0200
8427 + * arch/ubicom32/include/asm/mman.h
8428 + * Memory mapping definitions for Ubicom32 architecture.
8430 + * (C) Copyright 2009, Ubicom, Inc.
8432 + * This file is part of the Ubicom32 Linux Kernel Port.
8434 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8435 + * it and/or modify it under the terms of the GNU General Public License
8436 + * as published by the Free Software Foundation, either version 2 of the
8437 + * License, or (at your option) any later version.
8439 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8440 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8441 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
8442 + * the GNU General Public License for more details.
8444 + * You should have received a copy of the GNU General Public License
8445 + * along with the Ubicom32 Linux Kernel Port. If not,
8446 + * see <http://www.gnu.org/licenses/>.
8448 + * Ubicom32 implementation derived from (with many thanks):
8453 +#ifndef _ASM_UBICOM32_MMAN_H
8454 +#define _ASM_UBICOM32_MMAN_H
8456 +#include <asm-generic/mman.h>
8458 +#define MAP_GROWSDOWN 0x0100 /* stack-like segment */
8459 +#define MAP_DENYWRITE 0x0800 /* ETXTBSY */
8460 +#define MAP_EXECUTABLE 0x1000 /* mark it as an executable */
8461 +#define MAP_LOCKED 0x2000 /* pages are locked */
8462 +#define MAP_NORESERVE 0x4000 /* don't check for reservations */
8463 +#define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */
8464 +#define MAP_NONBLOCK 0x10000 /* do not block on IO */
8466 +#define MCL_CURRENT 1 /* lock all current mappings */
8467 +#define MCL_FUTURE 2 /* lock all future mappings */
8469 +#endif /* _ASM_UBICOM32_MMAN_H */
8470 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/mmu_context.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/mmu_context.h
8471 --- linux-2.6.30.10/arch/ubicom32/include/asm/mmu_context.h 1970-01-01 02:00:00.000000000 +0200
8472 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/mmu_context.h 2009-12-11 11:45:11.000000000 +0200
8475 + * arch/ubicom32/include/asm/mmu_context.h
8476 + * MMU context definitions for Ubicom32 architecture.
8478 + * (C) Copyright 2009, Ubicom, Inc.
8479 + * Copyright (C) 2004, Microtronix Datacom Ltd., All rights reserved.
8481 + * This file is part of the Ubicom32 Linux Kernel Port.
8483 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8484 + * it and/or modify it under the terms of the GNU General Public License
8485 + * as published by the Free Software Foundation, either version 2 of the
8486 + * License, or (at your option) any later version.
8488 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8489 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8490 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
8491 + * the GNU General Public License for more details.
8493 + * You should have received a copy of the GNU General Public License
8494 + * along with the Ubicom32 Linux Kernel Port. If not,
8495 + * see <http://www.gnu.org/licenses/>.
8497 + * Ubicom32 implementation derived from (with many thanks):
8503 +#ifndef _ASM_UBICOM32_MMU_CONTEXT_H
8504 +#define _ASM_UBICOM32_MMU_CONTEXT_H
8506 +#include <asm/setup.h>
8507 +#include <asm/page.h>
8508 +#include <asm/pgalloc.h>
8510 +static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
8515 +init_new_context(struct task_struct *tsk, struct mm_struct *mm)
8517 + // mm->context = virt_to_phys(mm->pgd);
8521 +#define destroy_context(mm) do { } while(0)
8523 +static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk)
8527 +#define deactivate_mm(tsk,mm) do { } while (0)
8529 +extern inline void activate_mm(struct mm_struct *prev_mm, struct mm_struct *next_mm)
8533 +#endif /* _ASM_UBICOM32_MMU_CONTEXT_H */
8534 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/mmu.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/mmu.h
8535 --- linux-2.6.30.10/arch/ubicom32/include/asm/mmu.h 1970-01-01 02:00:00.000000000 +0200
8536 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/mmu.h 2009-12-11 11:45:11.000000000 +0200
8539 + * arch/ubicom32/include/asm/mmu.h
8540 + * Definition of mm_context_t struct for Ubicom32 architecture.
8542 + * (C) Copyright 2009, Ubicom, Inc.
8543 + * Copyright (C) 2002, David McCullough <davidm@snapgear.com>
8545 + * This file is part of the Ubicom32 Linux Kernel Port.
8547 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8548 + * it and/or modify it under the terms of the GNU General Public License
8549 + * as published by the Free Software Foundation, either version 2 of the
8550 + * License, or (at your option) any later version.
8552 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8553 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8554 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
8555 + * the GNU General Public License for more details.
8557 + * You should have received a copy of the GNU General Public License
8558 + * along with the Ubicom32 Linux Kernel Port. If not,
8559 + * see <http://www.gnu.org/licenses/>.
8561 + * Ubicom32 implementation derived from (with many thanks):
8566 +#ifndef _ASM_UBICOM32_MMU_H
8567 +#define _ASM_UBICOM32_MMU_H
8570 + struct vm_list_struct *vmlist;
8571 + unsigned long end_brk;
8572 +#ifdef CONFIG_BINFMT_ELF_FDPIC
8573 + unsigned long exec_fdpic_loadmap;
8574 + unsigned long interp_fdpic_loadmap;
8578 +#endif /* _ASM_UBICOM32_MMU_H */
8579 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/module.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/module.h
8580 --- linux-2.6.30.10/arch/ubicom32/include/asm/module.h 1970-01-01 02:00:00.000000000 +0200
8581 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/module.h 2009-12-11 11:45:11.000000000 +0200
8584 + * arch/ubicom32/include/asm/module.h
8585 + * Ubicom32 architecture specific module definitions.
8587 + * (C) Copyright 2009, Ubicom, Inc.
8589 + * This file is part of the Ubicom32 Linux Kernel Port.
8591 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8592 + * it and/or modify it under the terms of the GNU General Public License
8593 + * as published by the Free Software Foundation, either version 2 of the
8594 + * License, or (at your option) any later version.
8596 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8597 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8598 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
8599 + * the GNU General Public License for more details.
8601 + * You should have received a copy of the GNU General Public License
8602 + * along with the Ubicom32 Linux Kernel Port. If not,
8603 + * see <http://www.gnu.org/licenses/>.
8605 + * Ubicom32 implementation derived from (with many thanks):
8610 +#ifndef _ASM_UBICOM32_MODULE_H
8611 +#define _ASM_UBICOM32_MODULE_H
8613 +struct mod_arch_specific {
8615 + int ocm_inst_size;
8618 +#define Elf_Shdr Elf32_Shdr
8619 +#define Elf_Sym Elf32_Sym
8620 +#define Elf_Ehdr Elf32_Ehdr
8622 +#define ARCH_PROC_MODULES_EXTRA(m,mod) \
8623 + seq_printf(m, " OCM(%d bytes @ 0x%p)", \
8624 + (mod)->arch.ocm_inst_size, (mod)->arch.ocm_inst)
8626 +#define ARCH_OOPS_MODULE_EXTRA(mod) \
8627 + printk(KERN_INFO "%p %u OCM(%p %u)\n", \
8628 + (mod)->module_core, (mod)->core_size, \
8629 + (mod)->arch.ocm_inst, (mod)->arch.ocm_inst_size)
8630 +#endif /* _ASM_UBICOM32_MODULE_H */
8631 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/msgbuf.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/msgbuf.h
8632 --- linux-2.6.30.10/arch/ubicom32/include/asm/msgbuf.h 1970-01-01 02:00:00.000000000 +0200
8633 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/msgbuf.h 2009-12-11 11:45:11.000000000 +0200
8636 + * arch/ubicom32/include/asm/msgbuf.h
8637 + * Definition of msqid64_ds struct for Ubicom32 architecture.
8639 + * (C) Copyright 2009, Ubicom, Inc.
8641 + * This file is part of the Ubicom32 Linux Kernel Port.
8643 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8644 + * it and/or modify it under the terms of the GNU General Public License
8645 + * as published by the Free Software Foundation, either version 2 of the
8646 + * License, or (at your option) any later version.
8648 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8649 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8650 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
8651 + * the GNU General Public License for more details.
8653 + * You should have received a copy of the GNU General Public License
8654 + * along with the Ubicom32 Linux Kernel Port. If not,
8655 + * see <http://www.gnu.org/licenses/>.
8657 + * Ubicom32 implementation derived from (with many thanks):
8662 +#ifndef _ASM_UBICOM32_MSGBUF_H
8663 +#define _ASM_UBICOM32_MSGBUF_H
8666 + * The msqid64_ds structure for ubicom32 architecture.
8667 + * Note extra padding because this structure is passed back and forth
8668 + * between kernel and user space.
8670 + * Pad space is left for:
8671 + * - 64-bit time_t to solve y2038 problem
8672 + * - 2 miscellaneous 32-bit values
8675 +struct msqid64_ds {
8676 + struct ipc64_perm msg_perm;
8677 + __kernel_time_t msg_stime; /* last msgsnd time */
8678 + unsigned long __unused1;
8679 + __kernel_time_t msg_rtime; /* last msgrcv time */
8680 + unsigned long __unused2;
8681 + __kernel_time_t msg_ctime; /* last change time */
8682 + unsigned long __unused3;
8683 + unsigned long msg_cbytes; /* current number of bytes on queue */
8684 + unsigned long msg_qnum; /* number of messages in queue */
8685 + unsigned long msg_qbytes; /* max number of bytes on queue */
8686 + __kernel_pid_t msg_lspid; /* pid of last msgsnd */
8687 + __kernel_pid_t msg_lrpid; /* last receive pid */
8688 + unsigned long __unused4;
8689 + unsigned long __unused5;
8692 +#endif /* _ASM_UBICOM32_MSGBUF_H */
8693 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/mutex.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/mutex.h
8694 --- linux-2.6.30.10/arch/ubicom32/include/asm/mutex.h 1970-01-01 02:00:00.000000000 +0200
8695 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/mutex.h 2009-12-11 11:45:11.000000000 +0200
8698 + * arch/ubicom32/include/asm/mutex.h
8699 + * Generic mutex.h for Ubicom32 architecture.
8701 + * (C) Copyright 2009, Ubicom, Inc.
8703 + * This file is part of the Ubicom32 Linux Kernel Port.
8705 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8706 + * it and/or modify it under the terms of the GNU General Public License
8707 + * as published by the Free Software Foundation, either version 2 of the
8708 + * License, or (at your option) any later version.
8710 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8711 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8712 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
8713 + * the GNU General Public License for more details.
8715 + * You should have received a copy of the GNU General Public License
8716 + * along with the Ubicom32 Linux Kernel Port. If not,
8717 + * see <http://www.gnu.org/licenses/>.
8719 + * Ubicom32 implementation derived from (with many thanks):
8725 + * Pull in the generic implementation for the mutex fastpath.
8727 + * TODO: implement optimized primitives instead, or leave the generic
8728 + * implementation in place, or pick the atomic_xchg() based generic
8729 + * implementation. (see asm-generic/mutex-xchg.h for details)
8732 +#ifndef _ASM_UBICOM32_MUTEX_H
8733 +#define _ASM_UBICOM32_MUTEX_H
8735 +#include <asm-generic/mutex-dec.h>
8737 +#endif /* _ASM_UBICOM32_MUTEX_H */
8738 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/namei.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/namei.h
8739 --- linux-2.6.30.10/arch/ubicom32/include/asm/namei.h 1970-01-01 02:00:00.000000000 +0200
8740 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/namei.h 2009-12-11 11:45:11.000000000 +0200
8743 + * arch/ubicom32/include/asm/namei.h
8744 + * Definition of __emul_prefix() for Ubicom32 architecture.
8746 + * (C) Copyright 2009, Ubicom, Inc.
8748 + * This file is part of the Ubicom32 Linux Kernel Port.
8750 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8751 + * it and/or modify it under the terms of the GNU General Public License
8752 + * as published by the Free Software Foundation, either version 2 of the
8753 + * License, or (at your option) any later version.
8755 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8756 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8757 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
8758 + * the GNU General Public License for more details.
8760 + * You should have received a copy of the GNU General Public License
8761 + * along with the Ubicom32 Linux Kernel Port. If not,
8762 + * see <http://www.gnu.org/licenses/>.
8764 + * Ubicom32 implementation derived from (with many thanks):
8769 +#ifndef _ASM_UBICOM32_NAMEI_H
8770 +#define _ASM_UBICOM32_NAMEI_H
8772 +/* This dummy routine maybe changed to something useful
8773 + * for /usr/gnemul/ emulation stuff.
8774 + * Look at asm-sparc/namei.h for details.
8777 +#define __emul_prefix() NULL
8779 +#endif /* _ASM_UBICOM32_NAMEI_H */
8780 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ocm-alloc.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ocm-alloc.h
8781 --- linux-2.6.30.10/arch/ubicom32/include/asm/ocm-alloc.h 1970-01-01 02:00:00.000000000 +0200
8782 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ocm-alloc.h 2009-12-11 11:45:11.000000000 +0200
8785 + * arch/ubicom32/include/asm/ocm-alloc.h
8786 + * Ubicom32 architecture specific ocm definitions.
8788 + * (C) Copyright 2009, Ubicom, Inc.
8790 + * This file is part of the Ubicom32 Linux Kernel Port.
8792 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8793 + * it and/or modify it under the terms of the GNU General Public License
8794 + * as published by the Free Software Foundation, either version 2 of the
8795 + * License, or (at your option) any later version.
8797 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8798 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8799 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
8800 + * the GNU General Public License for more details.
8802 + * You should have received a copy of the GNU General Public License
8803 + * along with the Ubicom32 Linux Kernel Port. If not,
8804 + * see <http://www.gnu.org/licenses/>.
8806 + * Ubicom32 implementation derived from (with many thanks):
8811 +#ifndef _ASM_UBICOM32_OCM_ALLOC_H
8812 +#define _ASM_UBICOM32_OCM_ALLOC_H
8815 +extern void *ocm_inst_alloc(size_t size, pid_t pid);
8816 +extern int ocm_free(const void *ptr);
8817 +extern int ocm_inst_free(const void *ptr);
8819 +#endif /* _ASM_UBICOM32_OCM_ALLOC_H */
8820 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ocm_size.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ocm_size.h
8821 --- linux-2.6.30.10/arch/ubicom32/include/asm/ocm_size.h 1970-01-01 02:00:00.000000000 +0200
8822 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ocm_size.h 2009-12-14 14:30:27.000000000 +0200
8824 +#define APP_OCM_CODE_SIZE (0x3ffc2e00-0x3ffc0000)
8825 +#define APP_OCM_DATA_SIZE (0x3ffd3500-0x3ffc8000)
8827 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ocm_text.lds.inc linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ocm_text.lds.inc
8828 --- linux-2.6.30.10/arch/ubicom32/include/asm/ocm_text.lds.inc 1970-01-01 02:00:00.000000000 +0200
8829 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ocm_text.lds.inc 2009-12-11 11:45:11.000000000 +0200
8832 + * arch/ubicom32/include/asm/ocm_text.lds.inc
8833 + * <TODO: Replace with short file description>
8835 + * (C) Copyright 2009, Ubicom, Inc.
8837 + * This file is part of the Ubicom32 Linux Kernel Port.
8839 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8840 + * it and/or modify it under the terms of the GNU General Public License
8841 + * as published by the Free Software Foundation, either version 2 of the
8842 + * License, or (at your option) any later version.
8844 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8845 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8846 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
8847 + * the GNU General Public License for more details.
8849 + * You should have received a copy of the GNU General Public License
8850 + * along with the Ubicom32 Linux Kernel Port. If not,
8851 + * see <http://www.gnu.org/licenses/>.
8853 + * Ubicom32 implementation derived from (with many thanks):
8859 +*(.text.tcp_packet)
8860 +*(.text.ipt_do_table)
8861 +*(.text.nf_conntrack_in)
8862 +*(.text.ip_forward)
8863 +*(.text.dev_queue_xmit)
8864 +*(.text.netif_receive_skb)
8865 +*(.text.ip_route_input)
8866 +*(.text.ip_finish_output)
8867 +*(.text.nf_iterate)
8868 +*(.text.__hash_conntrack)
8872 +*(.text.__nf_conntrack_find)
8873 +*(.text.dev_hard_start_xmit)
8874 +*(.text.vlan_dev_hard_start_xmit)
8875 +*(.text.vlan_dev_hard_header)
8876 +*(.text.__nf_ct_refresh_acct)
8878 +*(.text.pfifo_fast_enqueue)
8879 +*(.text.ipv4_confirm)
8881 +*(.text.neigh_connected_output)
8882 +*(.text.nf_hook_slow)
8883 +*(.text.nf_nat_packet)
8884 +*(.text.local_bh_enable)
8885 +*(.text.pfifo_fast_dequeue)
8886 +*(.text.ubi32_eth_receive)
8888 +*(.text.skb_checksum)
8890 +*(.text.ubi32_eth_tx_done)
8891 +*(.text.eth_header)
8892 +*(.text.skb_release_data)
8893 +*(.text.nf_conntrack_find_get)
8894 +*(.text.process_backlog)
8895 +*(.text.vlan_skb_recv)
8896 +*(.text.ip_rcv_finish)
8897 +*(.text.__qdisc_run)
8899 +*(.text.eth_type_trans)
8900 +*(.text.__alloc_skb)
8902 +*(.text.nf_ip_checksum)
8903 +*(.text.__skb_checksum_complete_head)
8904 +*(.text.ipv4_conntrack_defrag)
8905 +*(.text.tcp_pkt_to_tuple)
8907 +*(.text.tcp_manip_pkt)
8909 +*(.text.nf_ct_get_tuple)
8911 +*(.text.ubi32_eth_start_xmit)
8912 +*(.text.free_block)
8914 +*(.text.kmem_cache_free)
8915 +*(.text.skb_pull_rcsum)
8916 +*(.text.cache_alloc_refill)
8917 +*(.text.skb_release_head_state)
8919 +*(.text.ip_sabotage_in)
8920 +*(.text.ip_forward_finish)
8921 +*(.text.kmem_cache_alloc)
8922 +*(.text.local_bh_disable)
8923 +*(.text.ipv4_pkt_to_tuple)
8924 +*(.text.inet_proto_csum_replace4)
8925 +*(.text.__nf_ct_l4proto_find)
8926 +*(.text.csum_partial)
8927 +*(.text.neigh_resolve_output)
8928 +*(.text.__kfree_skb)
8930 +*(.text.__find_vlan_dev)
8931 +*(.text.ldsr_ctxsw_thread)
8934 +*(.text.ipv4_invert_tuple)
8935 +*(.text.nf_ct_invert_tuplepr)
8936 +*(.text.skb_make_writable)
8937 +*(.text.ipv4_get_l4proto)
8938 +*(.text.handle_IRQ_event)
8939 +*(.text.net_rx_action)
8940 +*(.text.__do_softirq)
8942 +*(.text.note_interrupt)
8943 +*(.text.ipv4_conntrack_in)
8944 +*(.text.dst_release)
8945 +*(.text.tasklet_action)
8946 +*(.text.nf_nat_out)
8947 +*(.text.nf_ct_invert_tuple)
8949 +*(.text.__tasklet_schedule)
8950 +*(.text.__skb_checksum_complete)
8951 +*(.text.ubi32_eth_interrupt)
8952 +*(.text.dev_kfree_skb_any)
8953 +*(.text.ret_from_interrupt_to_kernel)
8954 +*(.text.preemptive_context_save)
8955 +*(.text.irq_ack_vector)
8956 +*(.text.update_wall_time)
8957 +*(.text.ldsr_thread)
8959 +*(.text.ubi32_eth_do_tasklet)
8960 +*(.text.__napi_schedule)
8962 +*(.text.run_timer_softirq)
8963 +*(.text.ldsr_mask_vector)
8965 +*(.text.ldsr_get_lsb)
8966 +*(.text.ldsr_unmask_vector)
8967 +*(.text.ip_fast_csum)
8968 +*(.text.hrtimer_run_queues)
8969 +*(.text.tcp_invert_tuple)
8971 +*(.text.run_posix_cpu_timers)
8972 +*(.text.free_hot_cold_page)
8973 +*(.text.lock_timer_base)
8974 +*(.text.calc_delta_mine)
8975 +*(.text.slab_destroy)
8976 +*(.text.rcu_pending)
8977 +*(.text.scheduler_tick)
8978 +*(.text.hrtimer_run_pending)
8979 +*(.text.do_softirq)
8981 +*(.text.irq_end_vector)
8982 +*(.text.pci_read_u32)
8983 +*(.text.udivmodsi4)
8986 +*(.text.__slab_alloc)
8987 +*(.text.br_handle_frame)
8988 +*(.text.br_fdb_update)
8989 +*(.text.__br_fdb_get)
8990 +*(.text.br_forward)
8991 +*(.text.br_handle_frame_finish)
8992 +*(.text.pci_write_u32)
8993 +*(.text.kmem_freepages)
8994 +*(.text.br_dev_queue_push_xmit)
8996 +*(.text.next_zones_zonelist)
8997 +*(.text.ubi32_pci_read_u32)
8998 +*(.text.zone_watermark_ok)
8999 +*(.text.__rmqueue_smallest)
9000 +*(.text.ubi32_eth_napi_poll)
9001 +*(.text.ubi32_pci_write_u32)
9002 +*(.text.ubi32_pci_read_u32)
9003 +*(.text._local_bh_enable)
9004 +*(.text._local_bh_disable)
9006 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/page.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/page.h
9007 --- linux-2.6.30.10/arch/ubicom32/include/asm/page.h 1970-01-01 02:00:00.000000000 +0200
9008 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/page.h 2009-12-11 11:45:11.000000000 +0200
9011 + * arch/ubicom32/include/asm/page.h
9012 + * Memory page related operations and definitions.
9014 + * (C) Copyright 2009, Ubicom, Inc.
9016 + * This file is part of the Ubicom32 Linux Kernel Port.
9018 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
9019 + * it and/or modify it under the terms of the GNU General Public License
9020 + * as published by the Free Software Foundation, either version 2 of the
9021 + * License, or (at your option) any later version.
9023 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
9024 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
9025 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
9026 + * the GNU General Public License for more details.
9028 + * You should have received a copy of the GNU General Public License
9029 + * along with the Ubicom32 Linux Kernel Port. If not,
9030 + * see <http://www.gnu.org/licenses/>.
9032 + * Ubicom32 implementation derived from (with many thanks):
9037 +#ifndef _ASM_UBICOM32_PAGE_H
9038 +#define _ASM_UBICOM32_PAGE_H
9040 +/* PAGE_SHIFT determines the page size */
9042 +#define PAGE_SHIFT 12
9043 +#define PAGE_SIZE (1 << PAGE_SHIFT)
9044 +#define PAGE_MASK (~(PAGE_SIZE-1))
9046 +#include <asm/setup.h>
9048 +#ifndef __ASSEMBLY__
9050 +#define get_user_page(vaddr) __get_free_page(GFP_KERNEL)
9051 +#define free_user_page(page, addr) free_page(addr)
9053 +#define clear_page(page) memset((page), 0, PAGE_SIZE)
9054 +#define copy_page(to,from) memcpy((to), (from), PAGE_SIZE)
9056 +#define clear_user_page(page, vaddr, pg) clear_page(page)
9057 +#define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
9059 +#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \
9060 + alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr)
9061 +#define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
9064 + * These are used to make use of C type-checking..
9066 +typedef struct { unsigned long pte; } pte_t;
9067 +typedef struct { unsigned long pmd[16]; } pmd_t;
9068 +typedef struct { unsigned long pgd; } pgd_t;
9069 +typedef struct { unsigned long pgprot; } pgprot_t;
9070 +typedef struct page *pgtable_t;
9072 +#define pte_val(x) ((x).pte)
9073 +#define pmd_val(x) ((&x)->pmd[0])
9074 +#define pgd_val(x) ((x).pgd)
9075 +#define pgprot_val(x) ((x).pgprot)
9077 +#define __pte(x) ((pte_t) { (x) } )
9078 +#define __pmd(x) ((pmd_t) { (x) } )
9079 +#define __pgd(x) ((pgd_t) { (x) } )
9080 +#define __pgprot(x) ((pgprot_t) { (x) } )
9082 +extern unsigned long memory_start;
9083 +extern unsigned long memory_end;
9085 +#endif /* !__ASSEMBLY__ */
9087 +#include <asm/page_offset.h>
9089 +#define PAGE_OFFSET (PAGE_OFFSET_RAW)
9091 +#ifndef __ASSEMBLY__
9093 +#define __pa(vaddr) virt_to_phys((void *)(vaddr))
9094 +#define __va(paddr) phys_to_virt((unsigned long)(paddr))
9096 +#define virt_to_pfn(kaddr) (__pa(kaddr) >> PAGE_SHIFT)
9097 +#define pfn_to_virt(pfn) __va((pfn) << PAGE_SHIFT)
9099 +#define virt_to_page(addr) (mem_map + (((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT))
9100 +#define page_to_virt(page) ((((page) - mem_map) << PAGE_SHIFT) + PAGE_OFFSET)
9102 +#define pfn_to_page(pfn) virt_to_page(pfn_to_virt(pfn))
9103 +#define page_to_pfn(page) virt_to_pfn(page_to_virt(page))
9104 +#define pfn_valid(pfn) ((pfn) < max_mapnr)
9106 +#define virt_addr_valid(kaddr) (((void *)(kaddr) >= (void *)PAGE_OFFSET) && \
9107 + ((void *)(kaddr) < (void *)memory_end))
9109 +#endif /* __ASSEMBLY__ */
9112 +#include <asm-generic/page.h>
9115 +#endif /* _ASM_UBICOM32_PAGE_H */
9116 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/page_offset.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/page_offset.h
9117 --- linux-2.6.30.10/arch/ubicom32/include/asm/page_offset.h 1970-01-01 02:00:00.000000000 +0200
9118 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/page_offset.h 2009-12-11 11:45:11.000000000 +0200
9121 + * arch/ubicom32/include/asm/page_offset.h
9122 + * Definition of PAGE_OFFSET_RAW for Ubicom32 architecture.
9124 + * (C) Copyright 2009, Ubicom, Inc.
9126 + * This file is part of the Ubicom32 Linux Kernel Port.
9128 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
9129 + * it and/or modify it under the terms of the GNU General Public License
9130 + * as published by the Free Software Foundation, either version 2 of the
9131 + * License, or (at your option) any later version.
9133 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
9134 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
9135 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
9136 + * the GNU General Public License for more details.
9138 + * You should have received a copy of the GNU General Public License
9139 + * along with the Ubicom32 Linux Kernel Port. If not,
9140 + * see <http://www.gnu.org/licenses/>.
9142 + * Ubicom32 implementation derived from (with many thanks):
9148 +#ifndef _ASM_UBICOM32_PAGE_OFFSET_H
9149 +#define _ASM_UBICOM32_PAGE_OFFSET_H
9151 +/* This handles the memory map.. */
9152 +#define PAGE_OFFSET_RAW 0x3ffc0000
9154 +#endif /* _ASM_UBICOM32_PAGE_OFFSET_H */
9155 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/param.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/param.h
9156 --- linux-2.6.30.10/arch/ubicom32/include/asm/param.h 1970-01-01 02:00:00.000000000 +0200
9157 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/param.h 2009-12-11 11:45:11.000000000 +0200
9160 + * arch/ubicom32/include/asm/param.h
9161 + * Definition of miscellaneous constants, including HZ.
9163 + * (C) Copyright 2009, Ubicom, Inc.
9165 + * This file is part of the Ubicom32 Linux Kernel Port.
9167 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
9168 + * it and/or modify it under the terms of the GNU General Public License
9169 + * as published by the Free Software Foundation, either version 2 of the
9170 + * License, or (at your option) any later version.
9172 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
9173 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
9174 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
9175 + * the GNU General Public License for more details.
9177 + * You should have received a copy of the GNU General Public License
9178 + * along with the Ubicom32 Linux Kernel Port. If not,
9179 + * see <http://www.gnu.org/licenses/>.
9181 + * Ubicom32 implementation derived from (with many thanks):
9186 +#ifndef _ASM_UBICOM32_PARAM_H
9187 +#define _ASM_UBICOM32_PARAM_H
9190 +#define HZ CONFIG_HZ
9192 +#define CLOCKS_PER_SEC (USER_HZ)
9199 +#define EXEC_PAGESIZE 4096
9202 +#define NOGROUP (-1)
9205 +#define MAXHOSTNAMELEN 64 /* max length of hostname */
9207 +#endif /* _ASM_UBICOM32_PARAM_H */
9208 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/pci.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/pci.h
9209 --- linux-2.6.30.10/arch/ubicom32/include/asm/pci.h 1970-01-01 02:00:00.000000000 +0200
9210 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/pci.h 2009-12-11 11:45:11.000000000 +0200
9213 + * arch/ubicom32/include/asm/pci.h
9214 + * Definitions of PCI operations for Ubicom32 architecture.
9216 + * (C) Copyright 2009, Ubicom, Inc.
9218 + * This file is part of the Ubicom32 Linux Kernel Port.
9220 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
9221 + * it and/or modify it under the terms of the GNU General Public License
9222 + * as published by the Free Software Foundation, either version 2 of the
9223 + * License, or (at your option) any later version.
9225 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
9226 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
9227 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
9228 + * the GNU General Public License for more details.
9230 + * You should have received a copy of the GNU General Public License
9231 + * along with the Ubicom32 Linux Kernel Port. If not,
9232 + * see <http://www.gnu.org/licenses/>.
9234 + * Ubicom32 implementation derived from (with many thanks):
9239 +#ifndef _ASM_UBICOM32_PCI_H
9240 +#define _ASM_UBICOM32_PCI_H
9242 +#include <asm/io.h>
9244 +/* The PCI address space does equal the physical memory
9245 + * address space. The networking and block device layers use
9246 + * this boolean for bounce buffer decisions.
9248 +#define PCI_DMA_BUS_IS_PHYS (1)
9253 + * Perform a master read/write to the PCI bus.
9254 + * These functions return a PCI_RESP_xxx code.
9256 +extern u8 pci_read_u32(u8 pci_cmd, u32 address, u32 *data);
9257 +extern u8 pci_write_u32(u8 pci_cmd, u32 address, u32 data);
9258 +extern u8 pci_read_u16(u8 pci_cmd, u32 address, u16 *data);
9259 +extern u8 pci_write_u16(u8 pci_cmd, u32 address, u16 data);
9260 +extern u8 pci_read_u8(u8 pci_cmd, u32 address, u8 *data);
9261 +extern u8 pci_write_u8(u8 pci_cmd, u32 address, u8 data);
9264 +#define PCIBIOS_MIN_IO 0x100
9265 +#define PCIBIOS_MIN_MEM 0x10000000
9267 +#define pcibios_assign_all_busses() 0
9268 +#define pcibios_scan_all_fns(a, b) 0
9269 +extern void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
9270 + struct resource *res);
9272 +extern void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
9273 + struct pci_bus_region *region);
9275 +struct pci_sys_data;
9279 + struct list_head buses;
9280 + int nr_controllers;
9281 + int (*setup)(int nr, struct pci_sys_data *);
9282 + struct pci_bus *(*scan)(int nr, struct pci_sys_data *);
9283 + void (*preinit)(void);
9284 + void (*postinit)(void);
9285 + u8 (*swizzle)(struct pci_dev *dev, u8 *pin);
9286 + int (*map_irq)(struct pci_dev *dev, u8 slot, u8 pin);
9290 + * Per-controller structure
9292 +struct pci_sys_data {
9293 + struct list_head node;
9294 + int busnr; /* primary bus number */
9295 + u64 mem_offset; /* bus->cpu memory mapping offset */
9296 + unsigned long io_offset; /* bus->cpu IO mapping offset */
9297 + struct pci_bus *bus; /* PCI bus */
9298 + struct resource *resource[3]; /* Primary PCI bus resources */
9299 + /* Bridge swizzling */
9300 + u8 (*swizzle)(struct pci_dev *, u8 *);
9302 + int (*map_irq)(struct pci_dev *, u8, u8);
9303 + struct hw_pci *hw;
9306 +static inline struct resource *
9307 +pcibios_select_root(struct pci_dev *pdev, struct resource *res)
9309 + struct resource *root = NULL;
9311 + if (res->flags & IORESOURCE_IO)
9312 + root = &ioport_resource;
9313 + if (res->flags & IORESOURCE_MEM)
9314 + root = &iomem_resource;
9319 +static inline void pcibios_set_master(struct pci_dev *dev)
9321 + /* No special bus mastering setup handling */
9323 +#define HAVE_ARCH_PCI_SET_DMA_MAX_SEGMENT_SIZE 1
9324 +#define HAVE_ARCH_PCI_SET_DMA_SEGMENT_BOUNDARY 1
9327 +static inline void * pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
9328 + dma_addr_t *dma_handle)
9330 + void *vaddr = kmalloc(size, GFP_KERNEL);
9331 + if(vaddr != NULL) {
9332 + *dma_handle = virt_to_phys(vaddr);
9337 +static inline int pci_dma_supported(struct pci_dev *hwdev, dma_addr_t mask)
9342 +static inline void pci_free_consistent(struct pci_dev *hwdev, size_t size,
9343 + void *cpu_addr, dma_addr_t dma_handle)
9349 +static inline dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr,
9350 + size_t size, int direction)
9352 + return virt_to_phys(ptr);
9355 +static inline void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr,
9356 + size_t size, int direction)
9361 +static inline dma_addr_t
9362 +pci_map_page(struct pci_dev *hwdev, struct page *page,
9363 + unsigned long offset, size_t size, int direction)
9365 + return pci_map_single(hwdev, page_address(page) + offset, size, (int)direction);
9369 +pci_unmap_page(struct pci_dev *hwdev, dma_addr_t dma_address,
9370 + size_t size, int direction)
9372 + pci_unmap_single(hwdev, dma_address, size, direction);
9376 +pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
9377 + int nents, int direction)
9383 +pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg,
9384 + int nents, int direction)
9389 +pci_dma_sync_sg_for_cpu(struct pci_dev *hwdev, struct scatterlist *sg,
9390 + int nelems, int direction)
9395 +pci_dma_sync_sg_for_device(struct pci_dev *hwdev, struct scatterlist *sg,
9396 + int nelems, int direction)
9401 +pci_dma_sync_single_for_cpu(struct pci_dev *hwdev, dma_addr_t dma_handle,
9402 + size_t size, int direction)
9407 +pci_dma_sync_single_for_device(struct pci_dev *hwdev, dma_addr_t dma_handle,
9408 + size_t size, int direction)
9413 +pci_dma_mapping_error(struct pci_dev *hwdev, dma_addr_t dma_addr)
9415 + return dma_addr == 0;
9417 +extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max);
9418 +extern void pci_iounmap(struct pci_dev *dev, void __iomem *);
9421 +#endif /* _ASM_UBICOM32_PCI_H */
9422 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/pcm_tio.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/pcm_tio.h
9423 --- linux-2.6.30.10/arch/ubicom32/include/asm/pcm_tio.h 1970-01-01 02:00:00.000000000 +0200
9424 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/pcm_tio.h 2009-12-11 11:45:11.000000000 +0200
9427 + * arch/ubicom32/include/asm/pcm_tio.h
9428 + * Ubicom32 architecture PCM TIO definitions.
9430 + * (C) Copyright 2009, Ubicom, Inc.
9432 + * This file is part of the Ubicom32 Linux Kernel Port.
9434 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
9435 + * it and/or modify it under the terms of the GNU General Public License
9436 + * as published by the Free Software Foundation, either version 2 of the
9437 + * License, or (at your option) any later version.
9439 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
9440 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
9441 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
9442 + * the GNU General Public License for more details.
9444 + * You should have received a copy of the GNU General Public License
9445 + * along with the Ubicom32 Linux Kernel Port. If not,
9446 + * see <http://www.gnu.org/licenses/>.
9448 +#ifndef _ASM_UBICOM32_PCM_TIO_H
9449 +#define _ASM_UBICOM32_PCM_TIO_H
9451 +#include <asm/devtree.h>
9453 +#define PCM_TIO_REGS_VERSION 2
9454 +struct pcm_tio_regs {
9456 + * set this value to 1 to reload the parameters and restart the HRT
9461 + * Pointers to the input and output buffers
9467 + * Buffer size (see pcm_hrt.S for constraints)
9469 + u32_t buffer_size;
9472 + * Current cycle. This variable increases every time half the buffer
9478 + * Fields below this line are not accessed by the HRT. They are purely
9479 + * informational for the user of this TIO.
9483 + * Version of this structure
9488 + * Number of channels supported
9493 + * Maximum buffer size
9495 + u32_t max_buffer_size;
9501 +#define PCM_TIO_NODE_VERSION 1
9502 +struct pcm_tio_node {
9503 + struct devtree_node dn;
9505 + struct pcm_tio_regs *regs;
9510 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/percpu.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/percpu.h
9511 --- linux-2.6.30.10/arch/ubicom32/include/asm/percpu.h 1970-01-01 02:00:00.000000000 +0200
9512 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/percpu.h 2009-12-11 11:45:11.000000000 +0200
9515 + * arch/ubicom32/include/asm/percpu.h
9516 + * Generic percpu.h for the Ubicom32 architecture.
9518 + * (C) Copyright 2009, Ubicom, Inc.
9520 + * This file is part of the Ubicom32 Linux Kernel Port.
9522 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
9523 + * it and/or modify it under the terms of the GNU General Public License
9524 + * as published by the Free Software Foundation, either version 2 of the
9525 + * License, or (at your option) any later version.
9527 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
9528 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
9529 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
9530 + * the GNU General Public License for more details.
9532 + * You should have received a copy of the GNU General Public License
9533 + * along with the Ubicom32 Linux Kernel Port. If not,
9534 + * see <http://www.gnu.org/licenses/>.
9536 + * Ubicom32 implementation derived from (with many thanks):
9541 +#ifndef _ASM_UBICOM32_PERCPU_H
9542 +#define _ASM_UBICOM32_PERCPU_H
9544 +#include <asm-generic/percpu.h>
9546 +#endif /* _ASM_UBICOM32_PERCPU_H */
9547 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/pgalloc.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/pgalloc.h
9548 --- linux-2.6.30.10/arch/ubicom32/include/asm/pgalloc.h 1970-01-01 02:00:00.000000000 +0200
9549 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/pgalloc.h 2009-12-11 11:45:11.000000000 +0200
9552 + * arch/ubicom32/include/asm/pgalloc.h
9553 + * Page table allocation definitions.
9555 + * (C) Copyright 2009, Ubicom, Inc.
9557 + * This file is part of the Ubicom32 Linux Kernel Port.
9559 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
9560 + * it and/or modify it under the terms of the GNU General Public License
9561 + * as published by the Free Software Foundation, either version 2 of the
9562 + * License, or (at your option) any later version.
9564 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
9565 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
9566 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
9567 + * the GNU General Public License for more details.
9569 + * You should have received a copy of the GNU General Public License
9570 + * along with the Ubicom32 Linux Kernel Port. If not,
9571 + * see <http://www.gnu.org/licenses/>.
9573 + * Ubicom32 implementation derived from (with many thanks):
9578 +#ifndef _ASM_UBICOM32_PGALLOC_H
9579 +#define _ASM_UBICOM32_PGALLOC_H
9581 +#include <linux/mm.h>
9582 +#include <asm/setup.h>
9584 +#define check_pgt_cache() do { } while (0)
9586 +#endif /* _ASM_UBICOM32_PGALLOC_H */
9587 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/pgtable.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/pgtable.h
9588 --- linux-2.6.30.10/arch/ubicom32/include/asm/pgtable.h 1970-01-01 02:00:00.000000000 +0200
9589 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/pgtable.h 2009-12-11 11:45:11.000000000 +0200
9592 + * arch/ubicom32/include/asm/pgtable.h
9593 + * Ubicom32 pseudo page table definitions and operations.
9595 + * (C) Copyright 2009, Ubicom, Inc.
9596 + * Copyright (C) 2004 Microtronix Datacom Ltd
9598 + * This file is part of the Ubicom32 Linux Kernel Port.
9600 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
9601 + * it and/or modify it under the terms of the GNU General Public License
9602 + * as published by the Free Software Foundation, either version 2 of the
9603 + * License, or (at your option) any later version.
9605 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
9606 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
9607 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
9608 + * the GNU General Public License for more details.
9610 + * You should have received a copy of the GNU General Public License
9611 + * along with the Ubicom32 Linux Kernel Port. If not,
9612 + * see <http://www.gnu.org/licenses/>.
9614 + * Ubicom32 implementation derived from (with many thanks):
9618 + * and various works, Alpha, ix86, M68K, Sparc, ...et al
9620 +#ifndef _ASM_UBICOM32_PGTABLE_H
9621 +#define _ASM_UBICOM32_PGTABLE_H
9623 +#include <asm-generic/4level-fixup.h>
9625 +//vic - this bit copied from m68knommu version
9626 +#include <asm/setup.h>
9627 +#include <asm/io.h>
9628 +#include <linux/sched.h>
9630 +typedef pte_t *pte_addr_t;
9632 +#define pgd_present(pgd) (1) /* pages are always present on NO_MM */
9633 +#define pgd_none(pgd) (0)
9634 +#define pgd_bad(pgd) (0)
9635 +#define pgd_clear(pgdp)
9636 +#define kern_addr_valid(addr) (1)
9637 +#define pmd_offset(a, b) ((void *)0)
9639 +#define PAGE_NONE __pgprot(0) /* these mean nothing to NO_MM */
9640 +#define PAGE_SHARED __pgprot(0) /* these mean nothing to NO_MM */
9641 +#define PAGE_COPY __pgprot(0) /* these mean nothing to NO_MM */
9642 +#define PAGE_READONLY __pgprot(0) /* these mean nothing to NO_MM */
9643 +#define PAGE_KERNEL __pgprot(0) /* these mean nothing to NO_MM */
9644 +//vic - this bit copied from m68knommu version
9646 +extern void paging_init(void);
9647 +#define swapper_pg_dir ((pgd_t *) 0)
9649 +#define __swp_type(x) (0)
9650 +#define __swp_offset(x) (0)
9651 +#define __swp_entry(typ,off) ((swp_entry_t) { ((typ) | ((off) << 7)) })
9652 +#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
9653 +#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
9656 + * pgprot_noncached() is only for infiniband pci support, and a real
9657 + * implementation for RAM would be more complicated.
9659 +#define pgprot_noncached(prot) (prot)
9661 +static inline int pte_file(pte_t pte) { return 0; }
9664 + * ZERO_PAGE is a global shared page that is always zero: used
9665 + * for zero-mapped memory areas etc..
9667 +#define ZERO_PAGE(vaddr) (virt_to_page(0))
9669 +extern unsigned int kobjsize(const void *objp);
9670 +extern int is_in_rom(unsigned long);
9673 + * No page table caches to initialise
9675 +#define pgtable_cache_init() do { } while (0)
9677 +#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
9678 + remap_pfn_range(vma, vaddr, pfn, size, prot)
9680 +extern inline void flush_cache_mm(struct mm_struct *mm)
9684 +extern inline void flush_cache_range(struct mm_struct *mm,
9685 + unsigned long start,
9686 + unsigned long end)
9690 +/* Push the page at kernel virtual address and clear the icache */
9691 +extern inline void flush_page_to_ram (unsigned long address)
9695 +/* Push n pages at kernel virtual address and clear the icache */
9696 +extern inline void flush_pages_to_ram (unsigned long address, int n)
9701 + * All 32bit addresses are effectively valid for vmalloc...
9702 + * Sort of meaningless for non-VM targets.
9704 +#define VMALLOC_START 0
9705 +#define VMALLOC_END 0xffffffff
9707 +#define arch_enter_lazy_mmu_mode() do {} while (0)
9708 +#define arch_leave_lazy_mmu_mode() do {} while (0)
9709 +#define arch_flush_lazy_mmu_mode() do {} while (0)
9710 +#define arch_enter_lazy_cpu_mode() do {} while (0)
9711 +#define arch_leave_lazy_cpu_mode() do {} while (0)
9712 +#define arch_flush_lazy_cpu_mode() do {} while (0)
9714 +#endif /* _ASM_UBICOM32_PGTABLE_H */
9715 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/plio.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/plio.h
9716 --- linux-2.6.30.10/arch/ubicom32/include/asm/plio.h 1970-01-01 02:00:00.000000000 +0200
9717 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/plio.h 2009-12-11 11:45:11.000000000 +0200
9723 + * Copyright © 2009 Ubicom Inc. <www.ubicom.com>. All Rights Reserved.
9725 + * This file is part of the Ubicom32 Linux Kernel Port.
9727 + * The Ubicom32 Linux Kernel Port is free software: you can
9728 + * redistribute it and/or modify it under the terms of the GNU General
9729 + * Public License as published by the Free Software Foundation, either
9730 + * version 2 of the License, or (at your option) any later version.
9732 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
9733 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
9734 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9735 + * See the GNU General Public License for more details.
9737 + * You should have received a copy of the GNU General Public License
9738 + * along with the Ubicom32 Linux Kernel Port. If not,
9739 + * see <http://www.gnu.org/licenses/>.
9740 + * This file contains confidential information of Ubicom, Inc. and your use of
9741 + * this file is subject to the Ubicom Software License Agreement distributed with
9742 + * this file. If you are uncertain whether you are an authorized user or to report
9743 + * any unauthorized use, please contact Ubicom, Inc. at +1-408-789-2200.
9744 + * Unauthorized reproduction or distribution of this file is subject to civil and
9745 + * criminal penalties.
9748 +#ifndef __PLIO__H__
9749 +#define __PLIO__H__
9751 +#include <asm/ip5000.h>
9752 +#include <asm/thread.h>
9754 +#define PLIO_PORT RD
9755 +#define PLIO_EXT_PORT RI
9757 +#define TRANSMIT_FIFO_WATERMARK 8
9760 + * PLIO non-blocking register definitions
9766 + unsigned rxfifo_thread_enable: 1; /* allowed rxfifo thread enable */
9768 + unsigned rxfifo_thread: 4; /* allowed rxfifo thread access */
9770 + unsigned br_thread: 4; /* allowed blocking region thread access */
9771 + unsigned fn_reset: 4; /* function reset bit vector */
9772 + unsigned rxfifo_sel: 1; /* select between RXFIFO 0 and 1 */
9773 + unsigned fn_sel: 3; /* select port function */
9774 +} plio_io_function_t;
9783 + unsigned txfifo_uf: 1; /* TXFIFO underflow */
9784 + unsigned txfifo_wm: 1; /* TXFIFO watermark */
9785 + unsigned rxfifo_of: 1; /* RXFIFO overflow */
9786 + unsigned rxfifo_wm: 1; /* RXFIFO watermark */
9788 + unsigned lreg_int_addr_rd: 1; /* read from specified LREG address */
9789 + unsigned lreg_int_addr_wr: 1; /* write to specified LREG address */
9790 + unsigned extctl_int: 4; /* synchronized external interrupts */
9791 + unsigned pfsm_int: 1; /* state machine */
9795 + unsigned txfifo_reset: 1; /* TXFIFO reset for int_set only */
9796 + unsigned rxfifo_reset: 1; /* RXFIFO reset for int_set only */
9798 + unsigned idif_txfifo_flush: 1; /* flush TXFIFO and idif_txfifo */
9799 + unsigned idif_rxfifo_flush: 1; /* flush RXFIFO and idif_rxfifo */
9800 + unsigned pfsm_start: 1; /* input to fsm */
9801 + unsigned txfifo_uf: 1; /* TXFIFO underflow */
9802 + unsigned txfifo_wm: 1; /* TXFIFO watermark */
9803 + unsigned rxfifo_of: 1; /* RXFIFO overflow */
9804 + unsigned rxfifo_wm: 1; /* RXFIFO watermark */
9806 + unsigned lreg_int_addr_rd: 1; /* read from specified LREG address */
9807 + unsigned lreg_int_addr_wr: 1; /* write to specified LREG address */
9808 + unsigned extctl_int: 4; /* synchronized external interrupts */
9809 + unsigned pfsm_int: 1; /* state machine */
9814 + PLIO_PORT_MODE_DE,
9815 + PLIO_PORT_MODE_DI,
9816 + PLIO_PORT_MODE_DEI,
9817 + PLIO_PORT_MODE_DC,
9818 +} plio_port_mode_t;
9821 + PLIO_CLK_CORE, /* CORE CLK */
9822 + PLIO_CLK_IO, /* IO CLK */
9823 + PLIO_CLK_EXT, /* EXT CLK */
9827 + unsigned edif_iaena_sel: 1; /* Input Address Enable Select */
9828 + unsigned edif_iaclk_sel: 1; /* Input Address Clock Select */
9829 + unsigned edif_iald_inv: 1; /* Input Address Strobe Invert */
9830 + unsigned edif_idclk_sel: 1; /* Input Data Clock Select */
9831 + unsigned edif_idld_inv: 1; /* Input Data Strobe Invert */
9832 + unsigned edif_ds: 3; /* specify IDR and ODR data shift */
9833 + unsigned edif_cmp_mode: 1; /* configure IDR comparator output */
9834 + unsigned edif_idena_sel: 1; /* Input Data Enable Select */
9835 + unsigned ecif_extclk_ena: 1; /* plio_extctl output select */
9836 + unsigned idif_tx_fifo_cmd_sel: 1; /* select pfsm_cmd data word position */
9837 + unsigned ptif_porti_cfg: 2; /* select port I pin configuration */
9838 + unsigned ptif_portd_cfg: 3; /* select port D pin configuration */
9839 + plio_port_mode_t ptif_port_mode: 3; /* select other plio ports */
9840 + unsigned icif_clk_plio_ext_inv: 1; /* invert external plio clock when set */
9841 + unsigned icif_rst_plio: 1; /* reset plio function and io fifos */
9842 + plio_clk_src_t icif_clk_src_sel: 2; /* select plio clock source */
9843 + unsigned pfsm_prog: 1; /* enable pfsm programming */
9844 + unsigned pfsm_cmd: 3; /* software input to pfsm */
9849 + unsigned idif_byteswap_tx: 3; /* swap TXFIFO byte order */
9850 + unsigned idif_byteswap_rx: 3; /* swap RXFIFO byte order */
9852 + unsigned lreg_ena: 1; /* enable local register map */
9853 + unsigned lreg_addr_fifo_cmp_ena: 1; /* enable a specific LREG address from/to TX/RX fifos */
9854 + unsigned lreg_addr_fifo_cmp: 5; /* LREG address routed from/to TX/RX fifos */
9856 + unsigned dcod_iald_idld_sel: 2; /* select address/data strobes */
9857 + unsigned dcod_rw_src_sel: 1; /* select LREG strobe source */
9858 + unsigned dcod_rd_sel: 5; /* select read strobe source */
9859 + unsigned dcod_wr_sel: 5; /* select write strobe source */
9860 + unsigned dcod_rd_lvl: 1; /* select active level of read strobe */
9861 + unsigned dcod_wr_lvl: 1; /* select active level of read strobe */
9865 + unsigned icif_eclk_div: 16; /* external plio clock divider */
9866 + unsigned icif_iclk_div: 16; /* internal plio clock divider */
9871 + unsigned pfsm_state: 5; /* current pfsm state */
9876 + unsigned lreg_r_int_addr: 5;
9878 + unsigned lreg_w_int_addr: 5;
9879 + unsigned lreg_w_int_data: 8;
9889 +} plio_io_fifo_wm_t, plio_io_fifo_lvl_t;
9892 +/* plio blocking region register definitions
9936 + plio_grpsel_t grpsel[4];
9938 + plio_cs_lut_t cs_lut[4];
9939 + plio_extctl_t extctl_o_lut[8];
9951 + PLIO_ECIF_CLK_OUT = 9,
9952 + PLIO_ECIF_IALD = 9,
9953 + PLIO_ECIF_CLK_IN = 8,
9954 + PLIO_ECIF_IDLD = 8,
9955 + PLIO_ECIF_INT = 2,
9956 +} plio_ecif_output_t;
9959 + u32_t bypass_sync;
9961 + u32_t output_type;
9967 + u32_t idr_addr_pos_mask;
9973 + u32_t addr_rd_ena;
9974 + u32_t addr_wr_ena;
9975 + u32_t addr_rd_int_ena;
9976 + u32_t addr_wr_int_ena;
9981 + * PLIO configuration
9984 + plio_fctl0_t fctl0;
9985 + plio_fctl1_t fctl1;
9986 + plio_fctl2_t fctl2;
9998 + plio_io_function_t function;
9999 + plio_gpio_t gpio_ctl;
10000 + plio_gpio_t gpio_out;
10001 + plio_gpio_t gpio_in;
10002 + plio_intstat_t intstat;
10003 + plio_intstat_t intmask;
10004 + plio_intset_t intset;
10005 + plio_intstat_t intclr;
10010 + plio_fctl0_t fctl0;
10011 + plio_fctl1_t fctl1;
10012 + plio_fctl2_t fctl2;
10013 + plio_stat_0_t stat0;
10014 + plio_stat_1_t stat1;
10015 + plio_stat_2_t stat2;
10016 + plio_io_fifo_wm_t fifo_wm;
10017 + plio_io_fifo_lvl_t fifo_lvl;
10021 + u32_t pfsm_sram[256];
10022 + plio_config_t config;
10025 +#define PLIO_NBR ((plio_nbr_t *)(PLIO_PORT))
10026 +#define PLIO_BR ((plio_br_t *)((PLIO_PORT + IO_PORT_BR_OFFSET)))
10027 +#define PEXT_NBR ((plio_nbr_t *)(PLIO_EXT_PORT))
10029 +extern void plio_init(const plio_fctl_t *plio_fctl, const plio_config_t *plio_config, const plio_sram_t plio_sram_cfg[], int sram_cfg_size);
10031 +#endif // __PLIO__H__
10032 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/poll.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/poll.h
10033 --- linux-2.6.30.10/arch/ubicom32/include/asm/poll.h 1970-01-01 02:00:00.000000000 +0200
10034 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/poll.h 2009-12-11 11:45:11.000000000 +0200
10037 + * arch/ubicom32/include/asm/poll.h
10038 + * Ubicom32 specific poll() related flags definitions.
10040 + * (C) Copyright 2009, Ubicom, Inc.
10042 + * This file is part of the Ubicom32 Linux Kernel Port.
10044 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10045 + * it and/or modify it under the terms of the GNU General Public License
10046 + * as published by the Free Software Foundation, either version 2 of the
10047 + * License, or (at your option) any later version.
10049 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10050 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10051 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
10052 + * the GNU General Public License for more details.
10054 + * You should have received a copy of the GNU General Public License
10055 + * along with the Ubicom32 Linux Kernel Port. If not,
10056 + * see <http://www.gnu.org/licenses/>.
10058 + * Ubicom32 implementation derived from (with many thanks):
10063 +#ifndef _ASM_UBICOM32_POLL_H
10064 +#define _ASM_UBICOM32_POLL_H
10066 +#define POLLWRNORM POLLOUT
10067 +#define POLLWRBAND 0x0100
10069 +#include <asm-generic/poll.h>
10071 +#endif /* _ASM_UBICOM32_POLL_H */
10072 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/posix_types.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/posix_types.h
10073 --- linux-2.6.30.10/arch/ubicom32/include/asm/posix_types.h 1970-01-01 02:00:00.000000000 +0200
10074 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/posix_types.h 2009-12-11 11:45:11.000000000 +0200
10077 + * arch/ubicom32/include/asm/posix_types.h
10078 + * Ubicom32 architecture posix types.
10080 + * (C) Copyright 2009, Ubicom, Inc.
10081 + * Copyright (C) 2004 Microtronix Datacom Ltd
10083 + * This file is part of the Ubicom32 Linux Kernel Port.
10085 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10086 + * it and/or modify it under the terms of the GNU General Public License
10087 + * as published by the Free Software Foundation, either version 2 of the
10088 + * License, or (at your option) any later version.
10090 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10091 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10092 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
10093 + * the GNU General Public License for more details.
10095 + * You should have received a copy of the GNU General Public License
10096 + * along with the Ubicom32 Linux Kernel Port. If not,
10097 + * see <http://www.gnu.org/licenses/>.
10099 + * Ubicom32 implementation derived from (with many thanks):
10104 +#ifndef __ARCH_UBICOM32_POSIX_TYPES_H
10105 +#define __ARCH_UBICOM32_POSIX_TYPES_H
10108 + * This file is generally used by user-level software, so you need to
10109 + * be a little careful about namespace pollution etc. Also, we cannot
10110 + * assume GCC is being used.
10113 +typedef unsigned long __kernel_ino_t;
10114 +typedef unsigned short __kernel_mode_t;
10115 +typedef unsigned short __kernel_nlink_t;
10116 +typedef long __kernel_off_t;
10117 +typedef int __kernel_pid_t;
10118 +typedef unsigned short __kernel_ipc_pid_t;
10119 +typedef unsigned short __kernel_uid_t;
10120 +typedef unsigned short __kernel_gid_t;
10121 +typedef unsigned int __kernel_size_t;
10122 +typedef int __kernel_ssize_t;
10123 +typedef int __kernel_ptrdiff_t;
10124 +typedef long __kernel_time_t;
10125 +typedef long __kernel_suseconds_t;
10126 +typedef long __kernel_clock_t;
10127 +typedef int __kernel_timer_t;
10128 +typedef int __kernel_clockid_t;
10129 +typedef int __kernel_daddr_t;
10130 +typedef char * __kernel_caddr_t;
10131 +typedef unsigned short __kernel_uid16_t;
10132 +typedef unsigned short __kernel_gid16_t;
10133 +typedef unsigned int __kernel_uid32_t;
10134 +typedef unsigned int __kernel_gid32_t;
10136 +typedef unsigned short __kernel_old_uid_t;
10137 +typedef unsigned short __kernel_old_gid_t;
10138 +typedef unsigned short __kernel_old_dev_t;
10141 +typedef long long __kernel_loff_t;
10145 +#if defined(__KERNEL__) || defined(__USE_ALL)
10147 +#else /* !defined(__KERNEL__) && !defined(__USE_ALL) */
10149 +#endif /* !defined(__KERNEL__) && !defined(__USE_ALL) */
10150 +} __kernel_fsid_t;
10152 +#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
10155 +#define __FD_SET(d, set) ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d))
10158 +#define __FD_CLR(d, set) ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
10161 +#define __FD_ISSET(d, set) ((set)->fds_bits[__FDELT(d)] & __FDMASK(d))
10164 +#define __FD_ZERO(fdsetp) (memset (fdsetp, 0, sizeof(*(fd_set *)fdsetp)))
10166 +#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */
10169 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/processor.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/processor.h
10170 --- linux-2.6.30.10/arch/ubicom32/include/asm/processor.h 1970-01-01 02:00:00.000000000 +0200
10171 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/processor.h 2009-12-11 11:45:11.000000000 +0200
10174 + * arch/ubicom32/include/asm/processor.h
10175 + * Thread related definitions for Ubicom32 architecture.
10177 + * (C) Copyright 2009, Ubicom, Inc.
10178 + * Copyright (C) 1995 Hamish Macdonald
10180 + * This file is part of the Ubicom32 Linux Kernel Port.
10182 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10183 + * it and/or modify it under the terms of the GNU General Public License
10184 + * as published by the Free Software Foundation, either version 2 of the
10185 + * License, or (at your option) any later version.
10187 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10188 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10189 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
10190 + * the GNU General Public License for more details.
10192 + * You should have received a copy of the GNU General Public License
10193 + * along with the Ubicom32 Linux Kernel Port. If not,
10194 + * see <http://www.gnu.org/licenses/>.
10196 + * Ubicom32 implementation derived from (with many thanks):
10202 +#ifndef _ASM_UBICOM32_PROCESSOR_H
10203 +#define _ASM_UBICOM32_PROCESSOR_H
10206 + * Default implementation of macro that returns current
10207 + * instruction pointer ("program counter").
10209 +#define current_text_addr() ({ __label__ _l; _l: &&_l;})
10211 +#include <linux/compiler.h>
10212 +#include <linux/threads.h>
10213 +#include <asm/types.h>
10214 +#include <asm/segment.h>
10215 +#include <asm/fpu.h>
10216 +#include <asm/ptrace.h>
10217 +#include <asm/current.h>
10218 +#include <asm/thread_info.h>
10220 +#if defined(CONFIG_UBICOM32_V3)
10221 + #define CPU "IP5K"
10223 +#if defined(CONFIG_UBICOM32_V4)
10224 + #define CPU "IP7K"
10227 + #define CPU "UNKNOWN"
10231 + * User space process size: 1st byte beyond user address space.
10233 +extern unsigned long memory_end;
10234 +#define TASK_SIZE (memory_end)
10237 + * This decides where the kernel will search for a free chunk of vm
10238 + * space during mmap's. We won't be using it
10240 +#define TASK_UNMAPPED_BASE 0
10243 + * This is the structure where we are going to save callee-saved registers.
10244 + * A5 is the return address, A7 is the stack pointer, A6 is the frame
10245 + * pointer. This is the frame that is created because of switch_to. This
10246 + * is not the frame due to interrupt preemption or because of syscall entry.
10249 +struct thread_struct {
10250 + unsigned long d10; /* D10 */
10251 + unsigned long d11; /* D11 */
10252 + unsigned long d12; /* D12 */
10253 + unsigned long d13; /* D13 */
10254 + unsigned long a1; /* A1 */
10255 + unsigned long a2; /* A2 */
10256 + unsigned long a5; /* A5 return address. */
10257 + unsigned long a6; /* A6 */
10258 + unsigned long sp; /* A7 kernel stack pointer. */
10261 +#define INIT_THREAD { \
10262 + 0, 0, 0, 0, 0, 0, 0, 0, \
10263 + sizeof(init_stack) + (unsigned long) init_stack - 8, \
10267 + * Do necessary setup to start up a newly executed thread.
10269 + * pass the data segment into user programs if it exists,
10270 + * it can't hurt anything as far as I can tell
10273 + * Do necessary setup to start up a newly executed thread.
10275 +#define start_thread(regs, new_pc, new_sp) \
10277 + regs->pc = new_pc & ~3; \
10278 + regs->an[5] = new_pc & ~3; \
10279 + regs->an[7] = new_sp; \
10280 + regs->nesting_level = -1; \
10281 + regs->frame_type = UBICOM32_FRAME_TYPE_NEW_THREAD; \
10282 + regs->thread_type = NORMAL_THREAD; \
10285 +/* Forward declaration, a strange C thing */
10286 +struct task_struct;
10288 +/* Free all resources held by a thread. */
10289 +static inline void release_thread(struct task_struct *dead_task)
10293 +/* Prepare to copy thread state - unlazy all lazy status */
10294 +#define prepare_to_copy(tsk) do { } while (0)
10296 +extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
10299 + * Free current thread data structures etc..
10301 +static inline void exit_thread(void)
10305 +unsigned long thread_saved_pc(struct task_struct *tsk);
10306 +unsigned long get_wchan(struct task_struct *p);
10308 +#define KSTK_EIP(tsk) (tsk->thread.a5)
10309 +#define KSTK_ESP(tsk) (tsk->thread.sp)
10311 +#define cpu_relax() barrier()
10313 +extern void processor_init(void);
10314 +extern unsigned int processor_timers(void);
10315 +extern unsigned int processor_threads(void);
10316 +extern unsigned int processor_frequency(void);
10317 +extern int processor_interrupts(unsigned int *int0, unsigned int *int1);
10318 +extern void processor_ocm(unsigned long *socm, unsigned long *eocm);
10319 +extern void processor_dram(unsigned long *sdram, unsigned long *edram);
10321 +#define THREAD_SIZE_LONGS (THREAD_SIZE/sizeof(unsigned long))
10322 +#define KSTK_TOP(info) \
10324 + unsigned long *__ptr = (unsigned long *)(info); \
10325 + (unsigned long)(&__ptr[THREAD_SIZE_LONGS]); \
10328 +#define task_pt_regs(task) \
10330 + struct pt_regs *__regs__; \
10331 + __regs__ = (struct pt_regs *)(KSTK_TOP(task_stack_page(task))-8); \
10335 +#endif /* _ASM_UBICOM32_PROCESSOR_H */
10336 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/profilesample.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/profilesample.h
10337 --- linux-2.6.30.10/arch/ubicom32/include/asm/profilesample.h 1970-01-01 02:00:00.000000000 +0200
10338 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/profilesample.h 2009-12-11 11:45:11.000000000 +0200
10341 + * arch/ubicom32/mach-common/profile.h
10342 + * Private data for the profile module
10344 + * (C) Copyright 2009, Ubicom, Inc.
10346 + * This file is part of the Ubicom32 Linux Kernel Port.
10348 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10349 + * it and/or modify it under the terms of the GNU General Public License
10350 + * as published by the Free Software Foundation, either version 2 of the
10351 + * License, or (at your option) any later version.
10353 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10354 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10355 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
10356 + * the GNU General Public License for more details.
10358 + * You should have received a copy of the GNU General Public License
10359 + * along with the Ubicom32 Linux Kernel Port. If not,
10360 + * see <http://www.gnu.org/licenses/>.
10365 +#ifndef _PROFILESAMPLE_H_
10366 +#define _PROFILESAMPLE_H_
10369 + * a sample taken by the ipProfile package for sending to the profilertool
10371 +struct profile_sample {
10372 + unsigned int pc; /* PC value */
10373 + unsigned int a5; /* a5 contents for parent of leaf function */
10374 + unsigned int parent; /* return address from stack, to find the caller */
10375 + unsigned int latency; /* CPU clocks since the last message dispatch in this thread (thread 0 ony for now) */
10376 + unsigned short active; /* which threads are active - for accurate counting */
10377 + unsigned short d_blocked; /* which threads are blocked due to D cache misses */
10378 + unsigned short i_blocked; /* which threads are blocked due to I cache misses */
10379 + unsigned char cond_codes; /* for branch prediction */
10380 + unsigned char thread; /* I-blocked, D-blocked, 4-bit thread number */
10384 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ptrace.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ptrace.h
10385 --- linux-2.6.30.10/arch/ubicom32/include/asm/ptrace.h 1970-01-01 02:00:00.000000000 +0200
10386 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ptrace.h 2009-12-11 11:45:11.000000000 +0200
10389 + * arch/ubicom32/include/asm/ptrace.h
10390 + * Ubicom32 architecture ptrace support.
10392 + * (C) Copyright 2009, Ubicom, Inc.
10394 + * This file is part of the Ubicom32 Linux Kernel Port.
10396 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10397 + * it and/or modify it under the terms of the GNU General Public License
10398 + * as published by the Free Software Foundation, either version 2 of the
10399 + * License, or (at your option) any later version.
10401 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10402 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10403 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
10404 + * the GNU General Public License for more details.
10406 + * You should have received a copy of the GNU General Public License
10407 + * along with the Ubicom32 Linux Kernel Port. If not,
10408 + * see <http://www.gnu.org/licenses/>.
10410 + * Ubicom32 implementation derived from (with many thanks):
10415 +#ifndef _ASM_UBICOM32_PTRACE_H
10416 +#define _ASM_UBICOM32_PTRACE_H
10418 +#ifndef __ASSEMBLY__
10421 + * We use hard coded constants because this is shared with user
10422 + * space and the values are NOT allowed to change. Only fields
10423 + * that are intended to be exposed get values.
10450 +#define PT_ACC0HI 96
10451 +#define PT_ACC0LO 100
10452 +#define PT_MAC_RC16 104
10453 +#define PT_ACC1HI 108
10454 +#define PT_ACC1LO 112
10455 +#define PT_SOURCE3 116
10456 +#define PT_INST_CNT 120
10457 +#define PT_CSR 124
10458 +#define PT_DUMMY_UNUSED 128
10459 +#define PT_INT_MASK0 132
10460 +#define PT_INT_MASK1 136
10461 +#define PT_TRAP_CAUSE 140
10463 +#define PT_ORIGINAL_D0 148
10464 +#define PT_FRAME_TYPE 152
10467 + * The following 'registers' are not registers at all but are used
10468 + * locate the relocated sections.
10470 +#define PT_TEXT_ADDR 200
10471 +#define PT_TEXT_END_ADDR 204
10472 +#define PT_DATA_ADDR 208
10473 +#define PT_EXEC_FDPIC_LOADMAP 212
10474 +#define PT_INTERP_FDPIC_LOADMAP 216
10477 + * This struct defines the way the registers are stored on the
10478 + * stack during a system call.
10480 +enum thread_type {
10485 +#define UBICOM32_FRAME_TYPE_SYSCALL -1 /* System call frame */
10486 +#define UBICOM32_FRAME_TYPE_INVALID 0 /* Invalid frame, no longer in use */
10487 +#define UBICOM32_FRAME_TYPE_INTERRUPT 1 /* Interrupt frame */
10488 +#define UBICOM32_FRAME_TYPE_TRAP 2 /* Trap frame */
10489 +#define UBICOM32_FRAME_TYPE_SIGTRAMP 3 /* Signal trampoline frame. */
10490 +#define UBICOM32_FRAME_TYPE_NEW_THREAD 4 /* New Thread. */
10496 + unsigned long dn[16];
10499 + * Address Registers
10501 + unsigned long an[8];
10504 + * Per thread misc registers.
10506 + unsigned long acc0[2];
10507 + unsigned long mac_rc16;
10508 + unsigned long acc1[2];
10509 + unsigned long source3;
10510 + unsigned long inst_cnt;
10511 + unsigned long csr;
10512 + unsigned long dummy_unused;
10513 + unsigned long int_mask0;
10514 + unsigned long int_mask1;
10515 + unsigned long trap_cause;
10516 + unsigned long pc;
10517 + unsigned long original_dn_0;
10520 + * Frame type. Syscall frames are -1. For other types look above.
10522 + unsigned long frame_type;
10525 + * These fields are not exposed to ptrace.
10527 + unsigned long previous_pc;
10528 + long nesting_level; /* When the kernel in in user space this
10530 + unsigned long thread_type; /* This indicates if this is a kernel
10535 + * This is the extended stack used by signal handlers and the context
10536 + * switcher: it's pushed after the normal "struct pt_regs".
10538 +struct switch_stack {
10539 + unsigned long dummy;
10544 +/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
10545 +#define PTRACE_GETREGS 12
10546 +#define PTRACE_SETREGS 13
10549 +#define PS_S (0x2000)
10550 +#define PS_M (0x1000)
10553 +extern int __user_mode(unsigned long sp);
10555 +#define user_mode(regs) (__user_mode((regs->an[7])))
10556 +#define user_stack(regs) ((regs)->an[7])
10557 +#define instruction_pointer(regs) ((regs)->pc)
10558 +#define profile_pc(regs) instruction_pointer(regs)
10559 +extern void show_regs(struct pt_regs *);
10560 +#endif /* __KERNEL__ */
10562 +#endif /* __ASSEMBLY__ */
10564 +#endif /* _ASM_UBICOM32_PTRACE_H */
10565 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/range-protect-asm.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/range-protect-asm.h
10566 --- linux-2.6.30.10/arch/ubicom32/include/asm/range-protect-asm.h 1970-01-01 02:00:00.000000000 +0200
10567 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/range-protect-asm.h 2009-12-11 11:45:11.000000000 +0200
10570 + * arch/ubicom32/include/asm/range-protect-asm.h
10571 + * Assembly macros for enabling memory protection.
10573 + * (C) Copyright 2009, Ubicom, Inc.
10575 + * This file is part of the Ubicom32 Linux Kernel Port.
10577 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10578 + * it and/or modify it under the terms of the GNU General Public License
10579 + * as published by the Free Software Foundation, either version 2 of the
10580 + * License, or (at your option) any later version.
10582 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10583 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10584 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
10585 + * the GNU General Public License for more details.
10587 + * You should have received a copy of the GNU General Public License
10588 + * along with the Ubicom32 Linux Kernel Port. If not,
10589 + * see <http://www.gnu.org/licenses/>.
10591 + * Ubicom32 implementation derived from (with many thanks):
10597 +#ifndef _ASM_UBICOM32_RANGE_PROTECT_ASM_H
10598 +#define _ASM_UBICOM32_RANGE_PROTECT_ASM_H
10600 +#if defined(__ASSEMBLY__)
10602 +#include <asm/thread-asm.h>
10605 + * You should only use the enable/disable ranges when you have the atomic lock,
10606 + * if you do not there will be problems.
10610 + * enable_kernel_ranges
10611 + * Enable the kernel ranges (disabling protection) for thread,
10612 + * where thread == (1 << thread number)
10614 +.macro enable_kernel_ranges thread
10615 +#ifdef CONFIG_PROTECT_KERNEL
10616 + or.4 I_RANGE0_EN, I_RANGE0_EN, \thread /* Enable Range Register */
10617 + or.4 D_RANGE0_EN, D_RANGE0_EN, \thread
10618 + or.4 D_RANGE1_EN, D_RANGE1_EN, \thread
10623 + * enable_kernel_ranges_for_current
10624 + * Enable the kernel ranges (disabling protection) for this thread
10626 +.macro enable_kernel_ranges_for_current scratch_reg
10627 +#ifdef CONFIG_PROTECT_KERNEL
10628 + thread_get_self_mask \scratch_reg
10629 + enable_kernel_ranges \scratch_reg
10634 + * disable_kernel_ranges
10635 + * Disables the kernel ranges (enabling protection) for thread
10636 + * where thread == (1 << thread number)
10638 +.macro disable_kernel_ranges thread
10639 +#ifdef CONFIG_PROTECT_KERNEL
10640 + not.4 \thread, \thread
10641 + and.4 I_RANGE0_EN, I_RANGE0_EN, \thread /* Disable Range Register */
10642 + and.4 D_RANGE0_EN, D_RANGE0_EN, \thread
10643 + and.4 D_RANGE1_EN, D_RANGE1_EN, \thread
10648 + * disable_kernel_ranges_for_current
10649 + * Disable kernel ranges (enabling protection) for this thread
10651 +.macro disable_kernel_ranges_for_current scratch_reg
10652 +#ifdef CONFIG_PROTECT_KERNEL
10653 + thread_get_self_mask \scratch_reg
10654 + disable_kernel_ranges \scratch_reg
10659 +#endif /* _ASM_UBICOM32_RANGE_PROTECT_ASM_H */
10660 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/range-protect.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/range-protect.h
10661 --- linux-2.6.30.10/arch/ubicom32/include/asm/range-protect.h 1970-01-01 02:00:00.000000000 +0200
10662 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/range-protect.h 2009-12-11 11:45:11.000000000 +0200
10665 + * arch/ubicom32/include/asm/range-protect.h
10666 + * Assembly macros declared in C for enabling memory protection.
10668 + * (C) Copyright 2009, Ubicom, Inc.
10670 + * This file is part of the Ubicom32 Linux Kernel Port.
10672 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10673 + * it and/or modify it under the terms of the GNU General Public License
10674 + * as published by the Free Software Foundation, either version 2 of the
10675 + * License, or (at your option) any later version.
10677 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10678 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10679 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
10680 + * the GNU General Public License for more details.
10682 + * You should have received a copy of the GNU General Public License
10683 + * along with the Ubicom32 Linux Kernel Port. If not,
10684 + * see <http://www.gnu.org/licenses/>.
10686 + * Ubicom32 implementation derived from (with many thanks):
10692 +#ifndef _ASM_UBICOM32_RANGE_PROTECT_H
10693 +#define _ASM_UBICOM32_RANGE_PROTECT_H
10695 +#if !defined(__ASSEMBLY__)
10696 +#include <asm/thread.h>
10698 + * The following macros should be the identical to the ones in
10699 + * range-protect-asm.h
10701 + * You should only use the enable/disable ranges when you have the atomic lock,
10702 + * if you do not there will be problems.
10706 + * enable_kernel_ranges
10707 + * Enable the kernel ranges (disabling protection) for thread,
10708 + * where thread == (1 << thread number)
10711 + ".macro enable_kernel_ranges thread \n\t"
10712 +#ifdef CONFIG_PROTECT_KERNEL
10713 + " or.4 I_RANGE0_EN, I_RANGE0_EN, \\thread \n\t" /* Enable Range Register */
10714 + " or.4 D_RANGE0_EN, D_RANGE0_EN, \\thread \n\t"
10715 + " or.4 D_RANGE1_EN, D_RANGE1_EN, \\thread \n\t"
10720 +#else /* __ASSEMBLY__ */
10722 +#include <asm/range-protect-asm.h>
10725 +#endif /* _ASM_UBICOM32_RANGE_PROTECT_H */
10726 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/resource.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/resource.h
10727 --- linux-2.6.30.10/arch/ubicom32/include/asm/resource.h 1970-01-01 02:00:00.000000000 +0200
10728 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/resource.h 2009-12-11 11:45:11.000000000 +0200
10731 + * arch/ubicom32/include/asm/resource.h
10732 + * Generic definitions for Ubicom32 architecture.
10734 + * (C) Copyright 2009, Ubicom, Inc.
10736 + * This file is part of the Ubicom32 Linux Kernel Port.
10738 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10739 + * it and/or modify it under the terms of the GNU General Public License
10740 + * as published by the Free Software Foundation, either version 2 of the
10741 + * License, or (at your option) any later version.
10743 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10744 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10745 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
10746 + * the GNU General Public License for more details.
10748 + * You should have received a copy of the GNU General Public License
10749 + * along with the Ubicom32 Linux Kernel Port. If not,
10750 + * see <http://www.gnu.org/licenses/>.
10752 + * Ubicom32 implementation derived from (with many thanks):
10757 +#ifndef _ASM_UBICOM32_RESOURCE_H
10758 +#define _ASM_UBICOM32_RESOURCE_H
10760 +#include <asm-generic/resource.h>
10762 +#endif /* _ASM_UBICOM32_RESOURCE_H */
10763 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ring_tio.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ring_tio.h
10764 --- linux-2.6.30.10/arch/ubicom32/include/asm/ring_tio.h 1970-01-01 02:00:00.000000000 +0200
10765 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ring_tio.h 2009-12-11 11:45:11.000000000 +0200
10768 + * arch/ubicom32/include/asm/ring_tio.h
10769 + * Ubicom32 architecture Ring TIO definitions.
10771 + * (C) Copyright 2009, Ubicom, Inc.
10773 + * This file is part of the Ubicom32 Linux Kernel Port.
10775 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10776 + * it and/or modify it under the terms of the GNU General Public License
10777 + * as published by the Free Software Foundation, either version 2 of the
10778 + * License, or (at your option) any later version.
10780 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10781 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10782 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
10783 + * the GNU General Public License for more details.
10785 + * You should have received a copy of the GNU General Public License
10786 + * along with the Ubicom32 Linux Kernel Port. If not,
10787 + * see <http://www.gnu.org/licenses/>.
10789 +#ifndef _ASM_UBICOM32_RING_TIO_H
10790 +#define _ASM_UBICOM32_RING_TIO_H
10792 +#include <asm/devtree.h>
10794 +#define RING_TIO_NODE_VERSION 2
10797 + * Devtree node for ring
10799 +struct ring_tio_node {
10800 + struct devtree_node dn;
10806 +extern void ring_tio_init(const char *node_name);
10808 +#endif /* _ASM_UBICOM32_RING_TIO_H */
10809 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/scatterlist.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/scatterlist.h
10810 --- linux-2.6.30.10/arch/ubicom32/include/asm/scatterlist.h 1970-01-01 02:00:00.000000000 +0200
10811 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/scatterlist.h 2009-12-11 11:45:11.000000000 +0200
10814 + * arch/ubicom32/include/asm/scatterlist.h
10815 + * Definitions of struct scatterlist for Ubicom32 architecture.
10817 + * (C) Copyright 2009, Ubicom, Inc.
10819 + * This file is part of the Ubicom32 Linux Kernel Port.
10821 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10822 + * it and/or modify it under the terms of the GNU General Public License
10823 + * as published by the Free Software Foundation, either version 2 of the
10824 + * License, or (at your option) any later version.
10826 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10827 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10828 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
10829 + * the GNU General Public License for more details.
10831 + * You should have received a copy of the GNU General Public License
10832 + * along with the Ubicom32 Linux Kernel Port. If not,
10833 + * see <http://www.gnu.org/licenses/>.
10835 + * Ubicom32 implementation derived from (with many thanks):
10840 +#ifndef _ASM_UBICOM32_SCATTERLIST_H
10841 +#define _ASM_UBICOM32_SCATTERLIST_H
10843 +#include <linux/mm.h>
10844 +#include <asm/types.h>
10846 +struct scatterlist {
10847 +#ifdef CONFIG_DEBUG_SG
10848 + unsigned long sg_magic;
10850 + unsigned long page_link;
10851 + unsigned int offset;
10852 + dma_addr_t dma_address;
10853 + unsigned int length;
10856 +#define sg_dma_address(sg) ((sg)->dma_address)
10857 +#define sg_dma_len(sg) ((sg)->length)
10859 +#define ISA_DMA_THRESHOLD (0xffffffff)
10861 +#endif /* _ASM_UBICOM32_SCATTERLIST_H */
10862 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/sd_tio.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/sd_tio.h
10863 --- linux-2.6.30.10/arch/ubicom32/include/asm/sd_tio.h 1970-01-01 02:00:00.000000000 +0200
10864 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/sd_tio.h 2009-12-11 11:45:11.000000000 +0200
10867 + * arch/ubicom32/include/asm/sd_tio.h
10868 + * SD TIO definitions
10870 + * (C) Copyright 2009, Ubicom, Inc.
10872 + * This file is part of the Ubicom32 Linux Kernel Port.
10874 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10875 + * it and/or modify it under the terms of the GNU General Public License
10876 + * as published by the Free Software Foundation, either version 2 of the
10877 + * License, or (at your option) any later version.
10879 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10880 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10881 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
10882 + * the GNU General Public License for more details.
10884 + * You should have received a copy of the GNU General Public License
10885 + * along with the Ubicom32 Linux Kernel Port. If not,
10886 + * see <http://www.gnu.org/licenses/>.
10888 +#ifndef _ASM_UBICOM32_SD_TIO_H
10889 +#define _ASM_UBICOM32_SD_TIO_H
10891 +#include <asm/devtree.h>
10894 + * Devtree node for SD
10896 +struct sd_tio_node {
10897 + struct devtree_node dn;
10901 +#endif /* _ASM_UBICOM32_SD_TIO_H */
10902 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/sections.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/sections.h
10903 --- linux-2.6.30.10/arch/ubicom32/include/asm/sections.h 1970-01-01 02:00:00.000000000 +0200
10904 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/sections.h 2009-12-11 11:45:11.000000000 +0200
10907 + * arch/ubicom32/include/asm/sections.h
10908 + * Generic sections.h definitions for Ubicom32 architecture.
10910 + * (C) Copyright 2009, Ubicom, Inc.
10912 + * This file is part of the Ubicom32 Linux Kernel Port.
10914 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10915 + * it and/or modify it under the terms of the GNU General Public License
10916 + * as published by the Free Software Foundation, either version 2 of the
10917 + * License, or (at your option) any later version.
10919 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10920 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10921 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
10922 + * the GNU General Public License for more details.
10924 + * You should have received a copy of the GNU General Public License
10925 + * along with the Ubicom32 Linux Kernel Port. If not,
10926 + * see <http://www.gnu.org/licenses/>.
10928 + * Ubicom32 implementation derived from (with many thanks):
10933 +#ifndef _ASM_UBICOM32_SECTIONS_H
10934 +#define _ASM_UBICOM32_SECTIONS_H
10936 +#include <asm-generic/sections.h>
10938 +#endif /* _ASM_UBICOM32_SECTIONS_H */
10939 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/segment.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/segment.h
10940 --- linux-2.6.30.10/arch/ubicom32/include/asm/segment.h 1970-01-01 02:00:00.000000000 +0200
10941 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/segment.h 2009-12-11 11:45:11.000000000 +0200
10944 + * arch/ubicom32/include/asm/segment.h
10945 + * Memory segment definitions for Ubicom32 architecture.
10947 + * (C) Copyright 2009, Ubicom, Inc.
10949 + * This file is part of the Ubicom32 Linux Kernel Port.
10951 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10952 + * it and/or modify it under the terms of the GNU General Public License
10953 + * as published by the Free Software Foundation, either version 2 of the
10954 + * License, or (at your option) any later version.
10956 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10957 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10958 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
10959 + * the GNU General Public License for more details.
10961 + * You should have received a copy of the GNU General Public License
10962 + * along with the Ubicom32 Linux Kernel Port. If not,
10963 + * see <http://www.gnu.org/licenses/>.
10965 + * Ubicom32 implementation derived from (with many thanks):
10970 +#ifndef _ASM_UBICOM32_SEGMENT_H
10971 +#define _ASM_UBICOM32_SEGMENT_H
10973 +/* define constants */
10974 +/* Address spaces (FC0-FC2) */
10975 +#define USER_DATA (1)
10977 +#define __USER_DS (USER_DATA)
10979 +#define USER_PROGRAM (2)
10980 +#define SUPER_DATA (5)
10981 +#ifndef __KERNEL_DS
10982 +#define __KERNEL_DS (SUPER_DATA)
10984 +#define SUPER_PROGRAM (6)
10985 +#define CPU_SPACE (7)
10987 +#ifndef __ASSEMBLY__
10990 + unsigned long seg;
10993 +#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
10994 +#define USER_DS MAKE_MM_SEG(__USER_DS)
10995 +#define KERNEL_DS MAKE_MM_SEG(__KERNEL_DS)
10998 + * Get/set the SFC/DFC registers for MOVES instructions
11001 +static inline mm_segment_t get_fs(void)
11006 +static inline mm_segment_t get_ds(void)
11008 + /* return the supervisor data space code */
11009 + return KERNEL_DS;
11012 +static inline void set_fs(mm_segment_t val)
11016 +#define segment_eq(a,b) ((a).seg == (b).seg)
11018 +#endif /* __ASSEMBLY__ */
11020 +#endif /* _ASM_UBICOM32_SEGMENT_H */
11021 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/semaphore.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/semaphore.h
11022 --- linux-2.6.30.10/arch/ubicom32/include/asm/semaphore.h 1970-01-01 02:00:00.000000000 +0200
11023 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/semaphore.h 2009-12-11 11:45:11.000000000 +0200
11026 + * arch/ubicom32/include/asm/semaphore.h
11027 + * Interrupt-safe semaphores for Ubicom32 architecture.
11029 + * (C) Copyright 2009, Ubicom, Inc.
11030 + * (C) Copyright 1996 Linus Torvalds
11031 + * m68k version by Andreas Schwab
11032 + * Copyright (C) 2004 Microtronix Datacom Ltd
11034 + * This file is part of the Ubicom32 Linux Kernel Port.
11036 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
11037 + * it and/or modify it under the terms of the GNU General Public License
11038 + * as published by the Free Software Foundation, either version 2 of the
11039 + * License, or (at your option) any later version.
11041 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
11042 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11043 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
11044 + * the GNU General Public License for more details.
11046 + * You should have received a copy of the GNU General Public License
11047 + * along with the Ubicom32 Linux Kernel Port. If not,
11048 + * see <http://www.gnu.org/licenses/>.
11050 + * Ubicom32 implementation derived from (with many thanks):
11055 +#ifndef _ASM_UBICOM32_SEMAPHORE_H
11056 +#define _ASM_UBICOM32_SEMAPHORE_H
11058 +#define RW_LOCK_BIAS 0x01000000
11060 +#ifndef __ASSEMBLY__
11062 +#include <linux/linkage.h>
11063 +#include <linux/wait.h>
11064 +#include <linux/spinlock.h>
11065 +#include <linux/rwsem.h>
11067 +#include <asm/system.h>
11068 +#include <asm/atomic.h>
11070 +struct semaphore {
11073 + wait_queue_head_t wait;
11076 +#define __SEMAPHORE_INITIALIZER(name, n) \
11078 + .count = ATOMIC_INIT(n), \
11079 + .waking = ATOMIC_INIT(0), \
11080 + .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
11083 +#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
11084 + struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
11086 +#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
11087 +#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
11089 +static inline void sema_init (struct semaphore *sem, int val)
11091 + *sem = (struct semaphore)__SEMAPHORE_INITIALIZER(*sem, val);
11094 +static inline void init_MUTEX (struct semaphore *sem)
11096 + sema_init(sem, 1);
11099 +static inline void init_MUTEX_LOCKED (struct semaphore *sem)
11101 + sema_init(sem, 0);
11104 +asmlinkage void __down_failed(void /* special register calling convention */);
11105 +asmlinkage int __down_failed_interruptible(void /* params in registers */);
11106 +asmlinkage int __down_failed_trylock(void /* params in registers */);
11107 +asmlinkage void __up_wakeup(void /* special register calling convention */);
11109 +asmlinkage void __down(struct semaphore * sem);
11110 +asmlinkage int __down_interruptible(struct semaphore * sem);
11111 +asmlinkage int __down_trylock(struct semaphore * sem);
11112 +asmlinkage void __up(struct semaphore * sem);
11114 +extern spinlock_t semaphore_wake_lock;
11117 + * This is ugly, but we want the default case to fall through.
11118 + * "down_failed" is a special asm handler that calls the C
11119 + * routine that actually waits.
11121 +static inline void down(struct semaphore * sem)
11125 + if (atomic_dec_return(&sem->count) < 0)
11129 +static inline int down_interruptible(struct semaphore * sem)
11136 + if(atomic_dec_return(&sem->count) < 0)
11137 + ret = __down_interruptible(sem);
11141 +static inline int down_trylock(struct semaphore * sem)
11145 + if (atomic_dec_return (&sem->count) < 0)
11146 + ret = __down_trylock(sem);
11151 + * Note! This is subtle. We jump to wake people up only if
11152 + * the semaphore was negative (== somebody was waiting on it).
11153 + * The default case (no contention) will result in NO
11154 + * jumps for both down() and up().
11156 +static inline void up(struct semaphore * sem)
11158 + if (atomic_inc_return(&sem->count) <= 0)
11162 +#endif /* __ASSEMBLY__ */
11164 +#endif /* _ASM_UBICOM32_SEMAPHORE_H */
11165 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/semaphore-helper.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/semaphore-helper.h
11166 --- linux-2.6.30.10/arch/ubicom32/include/asm/semaphore-helper.h 1970-01-01 02:00:00.000000000 +0200
11167 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/semaphore-helper.h 2009-12-11 11:45:11.000000000 +0200
11170 + * arch/ubicom32/include/asm/semaphore-helper.h
11171 + * Semaphore related definitions for Ubicom32 architecture.
11173 + * (C) Copyright 2009, Ubicom, Inc.
11175 + * This file is part of the Ubicom32 Linux Kernel Port.
11177 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
11178 + * it and/or modify it under the terms of the GNU General Public License
11179 + * as published by the Free Software Foundation, either version 2 of the
11180 + * License, or (at your option) any later version.
11182 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
11183 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11184 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
11185 + * the GNU General Public License for more details.
11187 + * You should have received a copy of the GNU General Public License
11188 + * along with the Ubicom32 Linux Kernel Port. If not,
11189 + * see <http://www.gnu.org/licenses/>.
11191 + * Ubicom32 implementation derived from (with many thanks):
11196 +#ifndef _ASM_UBICOM32_SEMAPHORE_HELPER_H
11197 +#define _ASM_UBICOM32_SEMAPHORE_HELPER_H
11200 + * SMP- and interrupt-safe semaphores helper functions.
11202 + * (C) Copyright 1996 Linus Torvalds
11204 + * m68k version by Andreas Schwab
11209 + * These two _must_ execute atomically wrt each other.
11211 +static inline void wake_one_more(struct semaphore * sem)
11213 + atomic_inc(&sem->waking);
11216 +static inline int waking_non_zero(struct semaphore *sem)
11219 + unsigned long flags;
11221 + spin_lock_irqsave(&semaphore_wake_lock, flags);
11223 + if (atomic_read(&sem->waking) > 0) {
11224 + atomic_dec(&sem->waking);
11227 + spin_unlock_irqrestore(&semaphore_wake_lock, flags);
11232 + * waking_non_zero_interruptible:
11235 + * -EINTR interrupted
11237 +static inline int waking_non_zero_interruptible(struct semaphore *sem,
11238 + struct task_struct *tsk)
11241 + unsigned long flags;
11243 + spin_lock_irqsave(&semaphore_wake_lock, flags);
11245 + if (atomic_read(&sem->waking) > 0) {
11246 + atomic_dec(&sem->waking);
11248 + } else if (signal_pending(tsk)) {
11249 + atomic_inc(&sem->count);
11252 + spin_unlock_irqrestore(&semaphore_wake_lock, flags);
11257 + * waking_non_zero_trylock:
11258 + * 1 failed to lock
11261 +static inline int waking_non_zero_trylock(struct semaphore *sem)
11264 + unsigned long flags;
11266 + spin_lock_irqsave(&semaphore_wake_lock, flags);
11268 + if (atomic_read(&sem->waking) > 0) {
11269 + atomic_dec(&sem->waking);
11272 + atomic_inc(&sem->count);
11273 + spin_unlock_irqrestore(&semaphore_wake_lock, flags);
11277 +#endif /* _ASM_UBICOM32_SEMAPHORE_HELPER_H */
11278 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/sembuf.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/sembuf.h
11279 --- linux-2.6.30.10/arch/ubicom32/include/asm/sembuf.h 1970-01-01 02:00:00.000000000 +0200
11280 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/sembuf.h 2009-12-11 11:45:11.000000000 +0200
11283 + * arch/ubicom32/include/asm/sembuf.h
11284 + * The semid64_ds structure for Ubicom32 architecture.
11286 + * (C) Copyright 2009, Ubicom, Inc.
11288 + * This file is part of the Ubicom32 Linux Kernel Port.
11290 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
11291 + * it and/or modify it under the terms of the GNU General Public License
11292 + * as published by the Free Software Foundation, either version 2 of the
11293 + * License, or (at your option) any later version.
11295 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
11296 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11297 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
11298 + * the GNU General Public License for more details.
11300 + * You should have received a copy of the GNU General Public License
11301 + * along with the Ubicom32 Linux Kernel Port. If not,
11302 + * see <http://www.gnu.org/licenses/>.
11304 + * Ubicom32 implementation derived from (with many thanks):
11309 +#ifndef _ASM_UBICOM32_SEMBUF_H
11310 +#define _ASM_UBICOM32_SEMBUF_H
11313 + * The semid64_ds structure for ubicom32 architecture.
11314 + * Note extra padding because this structure is passed back and forth
11315 + * between kernel and user space.
11317 + * Pad space is left for:
11318 + * - 64-bit time_t to solve y2038 problem
11319 + * - 2 miscellaneous 32-bit values
11322 +struct semid64_ds {
11323 + struct ipc64_perm sem_perm; /* permissions .. see ipc.h */
11324 + __kernel_time_t sem_otime; /* last semop time */
11325 + unsigned long __unused1;
11326 + __kernel_time_t sem_ctime; /* last change time */
11327 + unsigned long __unused2;
11328 + unsigned long sem_nsems; /* no. of semaphores in array */
11329 + unsigned long __unused3;
11330 + unsigned long __unused4;
11333 +#endif /* _ASM_UBICOM32_SEMBUF_H */
11334 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/setup.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/setup.h
11335 --- linux-2.6.30.10/arch/ubicom32/include/asm/setup.h 1970-01-01 02:00:00.000000000 +0200
11336 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/setup.h 2009-12-11 11:45:11.000000000 +0200
11339 + * arch/ubicom32/include/asm/setup.h
11340 + * Kernel command line length definition.
11342 + * (C) Copyright 2009, Ubicom, Inc.
11343 + * Copyright (C) 2004, Microtronix Datacom Ltd., All rights reserved.
11345 + * This file is part of the Ubicom32 Linux Kernel Port.
11347 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
11348 + * it and/or modify it under the terms of the GNU General Public License
11349 + * as published by the Free Software Foundation, either version 2 of the
11350 + * License, or (at your option) any later version.
11352 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
11353 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11354 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
11355 + * the GNU General Public License for more details.
11357 + * You should have received a copy of the GNU General Public License
11358 + * along with the Ubicom32 Linux Kernel Port. If not,
11359 + * see <http://www.gnu.org/licenses/>.
11361 + * Ubicom32 implementation derived from (with many thanks):
11367 +#ifndef _ASM_UBICOM32_SETUP_H
11368 +#define _ASM_UBICOM32_SETUP_H
11370 +#define COMMAND_LINE_SIZE 512
11372 +#endif /* _ASM_UBICOM32_SETUP_H */
11373 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/shmbuf.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/shmbuf.h
11374 --- linux-2.6.30.10/arch/ubicom32/include/asm/shmbuf.h 1970-01-01 02:00:00.000000000 +0200
11375 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/shmbuf.h 2009-12-11 11:45:11.000000000 +0200
11378 + * arch/ubicom32/include/asm/shmbuf.h
11379 + * The shmid64_ds structure for the Ubicom32 architecture.
11381 + * (C) Copyright 2009, Ubicom, Inc.
11383 + * This file is part of the Ubicom32 Linux Kernel Port.
11385 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
11386 + * it and/or modify it under the terms of the GNU General Public License
11387 + * as published by the Free Software Foundation, either version 2 of the
11388 + * License, or (at your option) any later version.
11390 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
11391 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11392 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
11393 + * the GNU General Public License for more details.
11395 + * You should have received a copy of the GNU General Public License
11396 + * along with the Ubicom32 Linux Kernel Port. If not,
11397 + * see <http://www.gnu.org/licenses/>.
11399 + * Ubicom32 implementation derived from (with many thanks):
11404 +#ifndef _ASM_UBICOM32_SHMBUF_H
11405 +#define _ASM_UBICOM32_SHMBUF_H
11408 + * The shmid64_ds structure for m68k architecture.
11409 + * Note extra padding because this structure is passed back and forth
11410 + * between kernel and user space.
11412 + * Pad space is left for:
11413 + * - 64-bit time_t to solve y2038 problem
11414 + * - 2 miscellaneous 32-bit values
11417 +struct shmid64_ds {
11418 + struct ipc64_perm shm_perm; /* operation perms */
11419 + size_t shm_segsz; /* size of segment (bytes) */
11420 + __kernel_time_t shm_atime; /* last attach time */
11421 + unsigned long __unused1;
11422 + __kernel_time_t shm_dtime; /* last detach time */
11423 + unsigned long __unused2;
11424 + __kernel_time_t shm_ctime; /* last change time */
11425 + unsigned long __unused3;
11426 + __kernel_pid_t shm_cpid; /* pid of creator */
11427 + __kernel_pid_t shm_lpid; /* pid of last operator */
11428 + unsigned long shm_nattch; /* no. of current attaches */
11429 + unsigned long __unused4;
11430 + unsigned long __unused5;
11433 +struct shminfo64 {
11434 + unsigned long shmmax;
11435 + unsigned long shmmin;
11436 + unsigned long shmmni;
11437 + unsigned long shmseg;
11438 + unsigned long shmall;
11439 + unsigned long __unused1;
11440 + unsigned long __unused2;
11441 + unsigned long __unused3;
11442 + unsigned long __unused4;
11445 +#endif /* _ASM_UBICOM32_SHMBUF_H */
11446 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/shmparam.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/shmparam.h
11447 --- linux-2.6.30.10/arch/ubicom32/include/asm/shmparam.h 1970-01-01 02:00:00.000000000 +0200
11448 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/shmparam.h 2009-12-11 11:45:11.000000000 +0200
11451 + * arch/ubicom32/include/asm/shmparam.h
11452 + * Shared memory definitions for Ubicom32 architecture.
11454 + * (C) Copyright 2009, Ubicom, Inc.
11455 + * Copyright (C) 2004 Microtronix Datacom Ltd
11457 + * This file is part of the Ubicom32 Linux Kernel Port.
11459 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
11460 + * it and/or modify it under the terms of the GNU General Public License
11461 + * as published by the Free Software Foundation, either version 2 of the
11462 + * License, or (at your option) any later version.
11464 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
11465 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11466 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
11467 + * the GNU General Public License for more details.
11469 + * You should have received a copy of the GNU General Public License
11470 + * along with the Ubicom32 Linux Kernel Port. If not,
11471 + * see <http://www.gnu.org/licenses/>.
11473 + * Ubicom32 implementation derived from (with many thanks):
11477 + * Alpha, ix86, M68K, Sparc, ...et al
11479 +#ifndef _ASM_UBICOM32_SHMPARAM_H
11480 +#define _ASM_UBICOM32_SHMPARAM_H
11482 +#define SHMLBA PAGE_SIZE /* attach addr a multiple of this */
11484 +#endif /* _ASM_UBICOM32_SHMPARAM_H */
11485 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/sigcontext.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/sigcontext.h
11486 --- linux-2.6.30.10/arch/ubicom32/include/asm/sigcontext.h 1970-01-01 02:00:00.000000000 +0200
11487 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/sigcontext.h 2009-12-11 11:45:11.000000000 +0200
11490 + * arch/ubicom32/include/asm/sigcontext.h
11491 + * Definition of sigcontext struct for Ubicom32 architecture.
11493 + * (C) Copyright 2009, Ubicom, Inc.
11495 + * This file is part of the Ubicom32 Linux Kernel Port.
11497 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
11498 + * it and/or modify it under the terms of the GNU General Public License
11499 + * as published by the Free Software Foundation, either version 2 of the
11500 + * License, or (at your option) any later version.
11502 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
11503 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11504 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
11505 + * the GNU General Public License for more details.
11507 + * You should have received a copy of the GNU General Public License
11508 + * along with the Ubicom32 Linux Kernel Port. If not,
11509 + * see <http://www.gnu.org/licenses/>.
11511 + * Ubicom32 implementation derived from (with many thanks):
11516 +#ifndef _ASM_UBICOM32_SIGCONTEXT_H
11517 +#define _ASM_UBICOM32_SIGCONTEXT_H
11519 +#include <asm/ptrace.h>
11521 +struct sigcontext {
11522 + struct pt_regs sc_regs;
11525 +#endif /* _ASM_UBICOM32_SIGCONTEXT_H */
11526 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/siginfo.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/siginfo.h
11527 --- linux-2.6.30.10/arch/ubicom32/include/asm/siginfo.h 1970-01-01 02:00:00.000000000 +0200
11528 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/siginfo.h 2009-12-11 11:45:11.000000000 +0200
11531 + * arch/ubicom32/include/asm/siginfo.h
11532 + * Generic siginfo.h definitions for Ubicom32 architecture.
11534 + * (C) Copyright 2009, Ubicom, Inc.
11536 + * This file is part of the Ubicom32 Linux Kernel Port.
11538 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
11539 + * it and/or modify it under the terms of the GNU General Public License
11540 + * as published by the Free Software Foundation, either version 2 of the
11541 + * License, or (at your option) any later version.
11543 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
11544 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11545 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
11546 + * the GNU General Public License for more details.
11548 + * You should have received a copy of the GNU General Public License
11549 + * along with the Ubicom32 Linux Kernel Port. If not,
11550 + * see <http://www.gnu.org/licenses/>.
11552 + * Ubicom32 implementation derived from (with many thanks):
11557 +#ifndef _ASM_UBICOM32_SIGINFO_H
11558 +#define _ASM_UBICOM32_SIGINFO_H
11560 +#include <asm-generic/siginfo.h>
11562 +#endif /* _ASM_UBICOM32_SIGINFO_H */
11563 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/signal.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/signal.h
11564 --- linux-2.6.30.10/arch/ubicom32/include/asm/signal.h 1970-01-01 02:00:00.000000000 +0200
11565 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/signal.h 2009-12-11 11:45:11.000000000 +0200
11568 + * arch/ubicom32/include/asm/signal.h
11569 + * Signal related definitions for Ubicom32 architecture.
11571 + * (C) Copyright 2009, Ubicom, Inc.
11573 + * This file is part of the Ubicom32 Linux Kernel Port.
11575 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
11576 + * it and/or modify it under the terms of the GNU General Public License
11577 + * as published by the Free Software Foundation, either version 2 of the
11578 + * License, or (at your option) any later version.
11580 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
11581 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11582 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
11583 + * the GNU General Public License for more details.
11585 + * You should have received a copy of the GNU General Public License
11586 + * along with the Ubicom32 Linux Kernel Port. If not,
11587 + * see <http://www.gnu.org/licenses/>.
11589 + * Ubicom32 implementation derived from (with many thanks):
11594 +#ifndef _ASM_UBICOM32_SIGNAL_H
11595 +#define _ASM_UBICOM32_SIGNAL_H
11597 +#include <linux/types.h>
11599 +/* Avoid too many header ordering problems. */
11603 +/* Most things should be clean enough to redefine this at will, if care
11604 + is taken to make libc match. */
11607 +#define _NSIG_BPW 32
11608 +#define _NSIG_WORDS (_NSIG / _NSIG_BPW)
11610 +typedef unsigned long old_sigset_t; /* at least 32 bits */
11613 + unsigned long sig[_NSIG_WORDS];
11616 +#endif /* __KERNEL__ */
11628 +#define SIGUSR1 10
11629 +#define SIGSEGV 11
11630 +#define SIGUSR2 12
11631 +#define SIGPIPE 13
11632 +#define SIGALRM 14
11633 +#define SIGTERM 15
11634 +#define SIGSTKFLT 16
11635 +#define SIGCHLD 17
11636 +#define SIGCONT 18
11637 +#define SIGSTOP 19
11638 +#define SIGTSTP 20
11639 +#define SIGTTIN 21
11640 +#define SIGTTOU 22
11642 +#define SIGXCPU 24
11643 +#define SIGXFSZ 25
11644 +#define SIGVTALRM 26
11645 +#define SIGPROF 27
11646 +#define SIGWINCH 28
11648 +#define SIGPOLL SIGIO
11650 +#define SIGLOST 29
11654 +#define SIGUNUSED 31
11656 +/* These should not be considered constants from userland. */
11657 +#define SIGRTMIN 32
11658 +#define SIGRTMAX _NSIG
11661 + * SA_FLAGS values:
11663 + * SA_ONSTACK indicates that a registered stack_t will be used.
11664 + * SA_RESTART flag to get restarting signals (which were the default long ago)
11665 + * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
11666 + * SA_RESETHAND clears the handler when the signal is delivered.
11667 + * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
11668 + * SA_NODEFER prevents the current signal from being masked in the handler.
11670 + * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
11671 + * Unix names RESETHAND and NODEFER respectively.
11673 +#define SA_NOCLDSTOP 0x00000001
11674 +#define SA_NOCLDWAIT 0x00000002
11675 +#define SA_SIGINFO 0x00000004
11676 +#define SA_ONSTACK 0x08000000
11677 +#define SA_RESTART 0x10000000
11678 +#define SA_NODEFER 0x40000000
11679 +#define SA_RESETHAND 0x80000000
11681 +#define SA_NOMASK SA_NODEFER
11682 +#define SA_ONESHOT SA_RESETHAND
11685 + * sigaltstack controls
11687 +#define SS_ONSTACK 1
11688 +#define SS_DISABLE 2
11690 +#define MINSIGSTKSZ 2048
11691 +#define SIGSTKSZ 8192
11693 +#include <asm-generic/signal.h>
11696 +struct old_sigaction {
11697 + __sighandler_t sa_handler;
11698 + old_sigset_t sa_mask;
11699 + unsigned long sa_flags;
11700 + void (*sa_restorer)(void);
11703 +struct sigaction {
11704 + __sighandler_t sa_handler;
11705 + unsigned long sa_flags;
11706 + void (*sa_restorer)(void);
11707 + sigset_t sa_mask; /* mask last for extensibility */
11710 +struct k_sigaction {
11711 + struct sigaction sa;
11714 +/* Here we must cater to libcs that poke about in kernel headers. */
11716 +struct sigaction {
11718 + __sighandler_t _sa_handler;
11719 + void (*_sa_sigaction)(int, struct siginfo *, void *);
11721 + sigset_t sa_mask;
11722 + unsigned long sa_flags;
11723 + void (*sa_restorer)(void);
11726 +#define sa_handler _u._sa_handler
11727 +#define sa_sigaction _u._sa_sigaction
11729 +#endif /* __KERNEL__ */
11731 +typedef struct sigaltstack {
11739 +#include <asm/sigcontext.h>
11740 +#undef __HAVE_ARCH_SIG_BITOPS
11742 +#define ptrace_signal_deliver(regs, cookie) do { } while (0)
11744 +#endif /* __KERNEL__ */
11746 +#endif /* _ASM_UBICOM32_SIGNAL_H */
11747 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/smp.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/smp.h
11748 --- linux-2.6.30.10/arch/ubicom32/include/asm/smp.h 1970-01-01 02:00:00.000000000 +0200
11749 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/smp.h 2009-12-11 11:45:11.000000000 +0200
11752 + * arch/ubicom32/include/asm/smp.h
11753 + * SMP definitions for Ubicom32 architecture.
11755 + * (C) Copyright 2009, Ubicom, Inc.
11757 + * This file is part of the Ubicom32 Linux Kernel Port.
11759 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
11760 + * it and/or modify it under the terms of the GNU General Public License
11761 + * as published by the Free Software Foundation, either version 2 of the
11762 + * License, or (at your option) any later version.
11764 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
11765 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11766 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
11767 + * the GNU General Public License for more details.
11769 + * You should have received a copy of the GNU General Public License
11770 + * along with the Ubicom32 Linux Kernel Port. If not,
11771 + * see <http://www.gnu.org/licenses/>.
11773 + * Ubicom32 implementation derived from (with many thanks):
11778 +#ifndef _ASM_UBICOM32_SMP_H
11779 +#define _ASM_UBICOM32_SMP_H
11781 +#ifndef CONFIG_SMP
11782 +#error you should not include smp.h if smp is off
11786 +#include <linux/bitops.h>
11787 +#include <linux/threads.h>
11788 +#include <linux/cpumask.h>
11789 +#include <asm/ip5000.h>
11791 +typedef unsigned long address_t;
11792 +extern unsigned int smp_ipi_irq;
11795 + * This magic constant controls our willingness to transfer
11796 + * a process across CPUs.
11798 + * Such a transfer incurs cache and tlb
11799 + * misses. The current value is inherited from i386. Still needs
11800 + * to be tuned for parisc.
11802 +#define PROC_CHANGE_PENALTY 15 /* Schedule penalty */
11803 +#define NO_PROC_ID 0xFF /* No processor magic marker */
11804 +#define ANY_PROC_ID 0xFF /* Any processor magic marker */
11807 +#define raw_smp_processor_id() (current_thread_info()->cpu)
11808 +#endif /* CONFIG_SMP */
11810 +static inline int __cpu_disable (void)
11815 +static inline void __cpu_die (unsigned int cpu)
11821 +extern int __cpu_up(unsigned int cpu);
11822 +extern void smp_send_timer_all(void);
11823 +extern void smp_timer_broadcast(const struct cpumask *mask);
11824 +extern void smp_set_affinity(unsigned int irq, const struct cpumask *dest);
11825 +extern void arch_send_call_function_single_ipi(int cpu);
11826 +#define arch_send_call_function_ipi_mask arch_send_call_function_ipi_mask
11827 +extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
11830 + * TODO: Once these are fully tested, we should turn them into
11831 + * inline macros for performance.
11833 +extern unsigned long smp_get_affinity(unsigned int irq, int *all);
11834 +extern void smp_reset_ipi(unsigned long mask);
11836 +#endif /* !ASSEMBLY */
11837 +#endif /* _ASM_UBICOM32_SMP_H */
11838 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/socket.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/socket.h
11839 --- linux-2.6.30.10/arch/ubicom32/include/asm/socket.h 1970-01-01 02:00:00.000000000 +0200
11840 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/socket.h 2009-12-11 11:45:11.000000000 +0200
11843 + * arch/ubicom32/include/asm/socket.h
11844 + * Socket options definitions for Ubicom32 architecture.
11846 + * (C) Copyright 2009, Ubicom, Inc.
11848 + * This file is part of the Ubicom32 Linux Kernel Port.
11850 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
11851 + * it and/or modify it under the terms of the GNU General Public License
11852 + * as published by the Free Software Foundation, either version 2 of the
11853 + * License, or (at your option) any later version.
11855 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
11856 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11857 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
11858 + * the GNU General Public License for more details.
11860 + * You should have received a copy of the GNU General Public License
11861 + * along with the Ubicom32 Linux Kernel Port. If not,
11862 + * see <http://www.gnu.org/licenses/>.
11864 + * Ubicom32 implementation derived from (with many thanks):
11869 +#ifndef _ASM_UBICOM32_SOCKET_H
11870 +#define _ASM_UBICOM32_SOCKET_H
11872 +#include <asm/sockios.h>
11874 +/* For setsockopt(2) */
11875 +#define SOL_SOCKET 1
11877 +#define SO_DEBUG 1
11878 +#define SO_REUSEADDR 2
11880 +#define SO_ERROR 4
11881 +#define SO_DONTROUTE 5
11882 +#define SO_BROADCAST 6
11883 +#define SO_SNDBUF 7
11884 +#define SO_RCVBUF 8
11885 +#define SO_SNDBUFFORCE 32
11886 +#define SO_RCVBUFFORCE 33
11887 +#define SO_KEEPALIVE 9
11888 +#define SO_OOBINLINE 10
11889 +#define SO_NO_CHECK 11
11890 +#define SO_PRIORITY 12
11891 +#define SO_LINGER 13
11892 +#define SO_BSDCOMPAT 14
11893 +/* To add :#define SO_REUSEPORT 15 */
11894 +#define SO_PASSCRED 16
11895 +#define SO_PEERCRED 17
11896 +#define SO_RCVLOWAT 18
11897 +#define SO_SNDLOWAT 19
11898 +#define SO_RCVTIMEO 20
11899 +#define SO_SNDTIMEO 21
11901 +/* Security levels - as per NRL IPv6 - don't actually do anything */
11902 +#define SO_SECURITY_AUTHENTICATION 22
11903 +#define SO_SECURITY_ENCRYPTION_TRANSPORT 23
11904 +#define SO_SECURITY_ENCRYPTION_NETWORK 24
11906 +#define SO_BINDTODEVICE 25
11908 +/* Socket filtering */
11909 +#define SO_ATTACH_FILTER 26
11910 +#define SO_DETACH_FILTER 27
11912 +#define SO_PEERNAME 28
11913 +#define SO_TIMESTAMP 29
11914 +#define SCM_TIMESTAMP SO_TIMESTAMP
11916 +#define SO_ACCEPTCONN 30
11918 +#define SO_PEERSEC 31
11919 +#define SO_PASSSEC 34
11920 +#define SO_TIMESTAMPNS 35
11921 +#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
11923 +#define SO_MARK 36
11925 +#define SO_TIMESTAMPING 37
11926 +#define SCM_TIMESTAMPING SO_TIMESTAMPING
11928 +#endif /* _ASM_UBICOM32_SOCKET_H */
11929 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/sockios.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/sockios.h
11930 --- linux-2.6.30.10/arch/ubicom32/include/asm/sockios.h 1970-01-01 02:00:00.000000000 +0200
11931 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/sockios.h 2009-12-11 11:45:11.000000000 +0200
11934 + * arch/ubicom32/include/asm/sockios.h
11935 + * Socket-level ioctl definitions for Ubicom32 architecture.
11937 + * (C) Copyright 2009, Ubicom, Inc.
11939 + * This file is part of the Ubicom32 Linux Kernel Port.
11941 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
11942 + * it and/or modify it under the terms of the GNU General Public License
11943 + * as published by the Free Software Foundation, either version 2 of the
11944 + * License, or (at your option) any later version.
11946 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
11947 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11948 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
11949 + * the GNU General Public License for more details.
11951 + * You should have received a copy of the GNU General Public License
11952 + * along with the Ubicom32 Linux Kernel Port. If not,
11953 + * see <http://www.gnu.org/licenses/>.
11955 + * Ubicom32 implementation derived from (with many thanks):
11960 +#ifndef _ASM_UBICOM32_SOCKIOS_H
11961 +#define _ASM_UBICOM32_SOCKIOS_H
11963 +/* Socket-level I/O control calls. */
11964 +#define FIOSETOWN 0x8901
11965 +#define SIOCSPGRP 0x8902
11966 +#define FIOGETOWN 0x8903
11967 +#define SIOCGPGRP 0x8904
11968 +#define SIOCATMARK 0x8905
11969 +#define SIOCGSTAMP 0x8906 /* Get stamp (timeval) */
11970 +#define SIOCGSTAMPNS 0x8907 /* Get stamp (timespec) */
11972 +#endif /* _ASM_UBICOM32_SOCKIOS_H */
11973 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/spinlock.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/spinlock.h
11974 --- linux-2.6.30.10/arch/ubicom32/include/asm/spinlock.h 1970-01-01 02:00:00.000000000 +0200
11975 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/spinlock.h 2009-12-11 11:45:11.000000000 +0200
11978 + * arch/ubicom32/include/asm/spinlock.h
11979 + * Spinlock related definitions for Ubicom32 architecture.
11981 + * (C) Copyright 2009, Ubicom, Inc.
11983 + * This file is part of the Ubicom32 Linux Kernel Port.
11985 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
11986 + * it and/or modify it under the terms of the GNU General Public License
11987 + * as published by the Free Software Foundation, either version 2 of the
11988 + * License, or (at your option) any later version.
11990 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
11991 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11992 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
11993 + * the GNU General Public License for more details.
11995 + * You should have received a copy of the GNU General Public License
11996 + * along with the Ubicom32 Linux Kernel Port. If not,
11997 + * see <http://www.gnu.org/licenses/>.
11999 + * Ubicom32 implementation derived from (with many thanks):
12004 +#ifndef _ASM_UBICOM32_SPINLOCK_H
12005 +#define _ASM_UBICOM32_SPINLOCK_H
12007 +#include <asm/system.h>
12008 +#include <asm/processor.h>
12009 +#include <asm/spinlock_types.h>
12012 + * __raw_spin_lock()
12015 +static inline void __raw_spin_lock(raw_spinlock_t *x)
12018 + "1: bset %0, %0, #0 \n\t"
12019 + " jmpne.f 1b \n\t"
12020 + : "+U4" (x->lock)
12027 + * __raw_spin_unlock()
12028 + * Unlock the lock.
12030 +static inline void __raw_spin_unlock(raw_spinlock_t *x)
12033 + " bclr %0, %0, #0 \n\t"
12034 + : "+U4" (x->lock)
12041 + * __raw_spin_is_locked()
12042 + * Test if the lock is locked.
12044 +static inline int __raw_spin_is_locked(raw_spinlock_t *x)
12050 + * __raw_spin_unlock_wait()
12051 + * Wait for the lock to be unlocked.
12053 + * Note: the caller has not guarantee that the lock will not
12054 + * be acquired before they get to it.
12056 +static inline void __raw_spin_unlock_wait(raw_spinlock_t *x)
12060 + } while (__raw_spin_is_locked(x));
12064 + * __raw_spin_trylock()
12065 + * Try the lock, return 0 on failure, 1 on success.
12067 +static inline int __raw_spin_trylock(raw_spinlock_t *x)
12072 + " bset %1, %1, #0 \n\t"
12073 + " jmpne.f 1f \n\t"
12074 + " move.4 %0, #1 \n\t"
12076 + : "+r" (ret), "+U4" (x->lock)
12085 + * __raw_spin_lock_flags()
12086 + * Spin waiting for the lock (enabling IRQ(s))
12088 +static inline void __raw_spin_lock_flags(raw_spinlock_t *x, unsigned long flags)
12091 + while (!__raw_spin_trylock(x)) {
12093 + * If the flags from the IRQ are set, interrupts are disabled and we
12094 + * need to re-enable them.
12099 + raw_local_irq_enable();
12101 + raw_local_irq_disable();
12108 + * Read-write spinlocks, allowing multiple readers but only one writer.
12109 + * Linux rwlocks are unfair to writers; they can be starved for an indefinite
12110 + * time by readers. With care, they can also be taken in interrupt context.
12112 + * In Ubicom32 architecture implementation, we have a spinlock and a counter.
12113 + * Readers use the lock to serialise their access to the counter (which
12114 + * records how many readers currently hold the lock).
12115 + * Writers hold the spinlock, preventing any readers or other writers from
12116 + * grabbing the rwlock.
12120 + * __raw_read_lock()
12121 + * Increment the counter in the rwlock.
12123 + * Note that we have to ensure interrupts are disabled in case we're
12124 + * interrupted by some other code that wants to grab the same read lock
12126 +static inline void __raw_read_lock(raw_rwlock_t *rw)
12128 + unsigned long flags;
12129 + raw_local_irq_save(flags);
12130 + __raw_spin_lock_flags(&rw->lock, flags);
12132 + __raw_spin_unlock(&rw->lock);
12133 + raw_local_irq_restore(flags);
12137 + * __raw_read_unlock()
12138 + * Decrement the counter.
12140 + * Note that we have to ensure interrupts are disabled in case we're
12141 + * interrupted by some other code that wants to grab the same read lock
12143 +static inline void __raw_read_unlock(raw_rwlock_t *rw)
12145 + unsigned long flags;
12146 + raw_local_irq_save(flags);
12147 + __raw_spin_lock_flags(&rw->lock, flags);
12149 + __raw_spin_unlock(&rw->lock);
12150 + raw_local_irq_restore(flags);
12154 + * __raw_read_trylock()
12155 + * Increment the counter if we can.
12157 + * Note that we have to ensure interrupts are disabled in case we're
12158 + * interrupted by some other code that wants to grab the same read lock
12160 +static inline int __raw_read_trylock(raw_rwlock_t *rw)
12162 + unsigned long flags;
12164 + raw_local_irq_save(flags);
12165 + if (__raw_spin_trylock(&rw->lock)) {
12167 + __raw_spin_unlock(&rw->lock);
12168 + raw_local_irq_restore(flags);
12172 + raw_local_irq_restore(flags);
12175 + * If write-locked, we fail to acquire the lock
12177 + if (rw->counter < 0) {
12182 + * Wait until we have a realistic chance at the lock
12184 + while (__raw_spin_is_locked(&rw->lock) && rw->counter >= 0) {
12192 + * __raw_write_lock()
12194 + * Note that we have to ensure interrupts are disabled in case we're
12195 + * interrupted by some other code that wants to read_trylock() this lock
12197 +static inline void __raw_write_lock(raw_rwlock_t *rw)
12199 + unsigned long flags;
12201 + raw_local_irq_save(flags);
12202 + __raw_spin_lock_flags(&rw->lock, flags);
12204 + if (rw->counter != 0) {
12205 + __raw_spin_unlock(&rw->lock);
12206 + raw_local_irq_restore(flags);
12208 + while (rw->counter != 0)
12214 + rw->counter = -1; /* mark as write-locked */
12216 + raw_local_irq_restore(flags);
12219 +static inline void __raw_write_unlock(raw_rwlock_t *rw)
12222 + __raw_spin_unlock(&rw->lock);
12225 +/* Note that we have to ensure interrupts are disabled in case we're
12226 + * interrupted by some other code that wants to read_trylock() this lock */
12227 +static inline int __raw_write_trylock(raw_rwlock_t *rw)
12229 + unsigned long flags;
12232 + raw_local_irq_save(flags);
12233 + if (__raw_spin_trylock(&rw->lock)) {
12234 + if (rw->counter == 0) {
12235 + rw->counter = -1;
12238 + /* Read-locked. Oh well. */
12239 + __raw_spin_unlock(&rw->lock);
12242 + raw_local_irq_restore(flags);
12248 + * read_can_lock - would read_trylock() succeed?
12249 + * @lock: the rwlock in question.
12251 +static inline int __raw_read_can_lock(raw_rwlock_t *rw)
12253 + return rw->counter >= 0;
12257 + * write_can_lock - would write_trylock() succeed?
12258 + * @lock: the rwlock in question.
12260 +static inline int __raw_write_can_lock(raw_rwlock_t *rw)
12262 + return !rw->counter;
12265 +#define __raw_read_lock_flags(lock, flags) __raw_read_lock(lock)
12266 +#define __raw_write_lock_flags(lock, flags) __raw_write_lock(lock)
12268 +#define _raw_spin_relax(lock) cpu_relax()
12269 +#define _raw_read_relax(lock) cpu_relax()
12270 +#define _raw_write_relax(lock) cpu_relax()
12272 +#endif /* _ASM_UBICOM32_SPINLOCK_H */
12273 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/spinlock_types.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/spinlock_types.h
12274 --- linux-2.6.30.10/arch/ubicom32/include/asm/spinlock_types.h 1970-01-01 02:00:00.000000000 +0200
12275 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/spinlock_types.h 2009-12-11 11:45:11.000000000 +0200
12278 + * arch/ubicom32/include/asm/spinlock_types.h
12279 + * Spinlock related structure definitions for Ubicom32 architecture.
12281 + * (C) Copyright 2009, Ubicom, Inc.
12283 + * This file is part of the Ubicom32 Linux Kernel Port.
12285 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
12286 + * it and/or modify it under the terms of the GNU General Public License
12287 + * as published by the Free Software Foundation, either version 2 of the
12288 + * License, or (at your option) any later version.
12290 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
12291 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12292 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
12293 + * the GNU General Public License for more details.
12295 + * You should have received a copy of the GNU General Public License
12296 + * along with the Ubicom32 Linux Kernel Port. If not,
12297 + * see <http://www.gnu.org/licenses/>.
12299 + * Ubicom32 implementation derived from (with many thanks):
12304 +#ifndef _ASM_UBICOM32_SPINLOCK_TYPES_H
12305 +#define _ASM_UBICOM32_SPINLOCK_TYPES_H
12308 + volatile unsigned int lock;
12312 + raw_spinlock_t lock;
12313 + volatile int counter;
12316 +#define __RAW_SPIN_LOCK_UNLOCKED { 0 }
12317 +#define __RAW_RW_LOCK_UNLOCKED { __RAW_SPIN_LOCK_UNLOCKED, 0 }
12319 +#endif /* _ASM_UBICOM32_SPINLOCK_TYPES_H */
12320 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/stacktrace.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/stacktrace.h
12321 --- linux-2.6.30.10/arch/ubicom32/include/asm/stacktrace.h 1970-01-01 02:00:00.000000000 +0200
12322 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/stacktrace.h 2009-12-11 11:45:11.000000000 +0200
12325 + * arch/ubicom32/include/asm/stacktrace.h
12326 + * Stacktrace functions for the Ubicom32 architecture.
12328 + * (C) Copyright 2009, Ubicom, Inc.
12330 + * This file is part of the Ubicom32 Linux Kernel Port.
12332 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
12333 + * it and/or modify it under the terms of the GNU General Public License
12334 + * as published by the Free Software Foundation, either version 2 of the
12335 + * License, or (at your option) any later version.
12337 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
12338 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12339 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
12340 + * the GNU General Public License for more details.
12342 + * You should have received a copy of the GNU General Public License
12343 + * along with the Ubicom32 Linux Kernel Port. If not,
12344 + * see <http://www.gnu.org/licenses/>.
12346 + * Ubicom32 implementation derived from (with many thanks):
12351 +#ifndef _ASM_UBICOM32_STACKTRACE_H
12352 +#define _ASM_UBICOM32_STACKTRACE_H
12354 +#define between(a, b, c) (( \
12355 + ((unsigned long) a) >= ((unsigned long) b)) && \
12356 + (((unsigned long)a) <= ((unsigned long)c)))
12359 + * These symbols are filled in by the linker.
12361 +extern unsigned long _stext;
12362 +extern unsigned long _etext;
12364 +/* OCM text goes from __ocm_text_run_begin to __data_begin */
12365 +extern unsigned long __ocm_text_run_begin;
12366 +extern unsigned long __data_begin;
12368 +/* Account for OCM case - see stacktrace.c maybe combine(also trap.c) */
12370 + * ubicom32_is_kernel()
12372 + * Check to see if the given address belongs to the kernel.
12373 + * NOMMU does not permit any other means.
12375 +static inline int ubicom32_is_kernel(unsigned long addr)
12377 + int is_kernel = between(addr, &_stext, &_etext) || \
12378 + between(addr, &__ocm_text_run_begin, &__data_begin);
12380 +#ifdef CONFIG_MODULES
12382 + is_kernel = is_module_address(addr);
12384 + return is_kernel;
12387 +extern unsigned long stacktrace_iterate(
12388 + unsigned long **trace,
12389 + unsigned long stext, unsigned long etext,
12390 + unsigned long ocm_stext, unsigned long ocm_etext,
12391 + unsigned long sstack, unsigned long estack);
12392 +#ifdef CONFIG_STACKTRACE
12393 +void stacktrace_save_entries(struct task_struct *tsk, struct stack_trace *trace, unsigned long sp);
12395 +#endif /* _ASM_UBICOM32_STACKTRACE_H */
12396 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/statfs.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/statfs.h
12397 --- linux-2.6.30.10/arch/ubicom32/include/asm/statfs.h 1970-01-01 02:00:00.000000000 +0200
12398 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/statfs.h 2009-12-11 11:45:11.000000000 +0200
12401 + * arch/ubicom32/include/asm/statfs.h
12402 + * Generic statfs.h definitions
12404 + * (C) Copyright 2009, Ubicom, Inc.
12406 + * This file is part of the Ubicom32 Linux Kernel Port.
12408 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
12409 + * it and/or modify it under the terms of the GNU General Public License
12410 + * as published by the Free Software Foundation, either version 2 of the
12411 + * License, or (at your option) any later version.
12413 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
12414 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12415 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
12416 + * the GNU General Public License for more details.
12418 + * You should have received a copy of the GNU General Public License
12419 + * along with the Ubicom32 Linux Kernel Port. If not,
12420 + * see <http://www.gnu.org/licenses/>.
12422 + * Ubicom32 implementation derived from (with many thanks):
12427 +#ifndef _ASM_UBICOM32_STATFS_H
12428 +#define _ASM_UBICOM32_STATFS_H
12430 +#include <asm-generic/statfs.h>
12432 +#endif /* _ASM_UBICOM32_STATFS_H */
12433 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/stat.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/stat.h
12434 --- linux-2.6.30.10/arch/ubicom32/include/asm/stat.h 1970-01-01 02:00:00.000000000 +0200
12435 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/stat.h 2009-12-11 11:45:11.000000000 +0200
12438 + * arch/ubicom32/include/asm/stat.h
12439 + * File status definitions for Ubicom32 architecture.
12441 + * (C) Copyright 2009, Ubicom, Inc.
12443 + * This file is part of the Ubicom32 Linux Kernel Port.
12445 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
12446 + * it and/or modify it under the terms of the GNU General Public License
12447 + * as published by the Free Software Foundation, either version 2 of the
12448 + * License, or (at your option) any later version.
12450 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
12451 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12452 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
12453 + * the GNU General Public License for more details.
12455 + * You should have received a copy of the GNU General Public License
12456 + * along with the Ubicom32 Linux Kernel Port. If not,
12457 + * see <http://www.gnu.org/licenses/>.
12459 + * Ubicom32 implementation derived from (with many thanks):
12464 +#ifndef _ASM_UBICOM32_STAT_H
12465 +#define _ASM_UBICOM32_STAT_H
12467 +struct __old_kernel_stat {
12468 + unsigned short st_dev;
12469 + unsigned short st_ino;
12470 + unsigned short st_mode;
12471 + unsigned short st_nlink;
12472 + unsigned short st_uid;
12473 + unsigned short st_gid;
12474 + unsigned short st_rdev;
12475 + unsigned long st_size;
12476 + unsigned long st_atime;
12477 + unsigned long st_mtime;
12478 + unsigned long st_ctime;
12482 + unsigned short st_dev;
12483 + unsigned short __pad1;
12484 + unsigned long st_ino;
12485 + unsigned short st_mode;
12486 + unsigned short st_nlink;
12487 + unsigned short st_uid;
12488 + unsigned short st_gid;
12489 + unsigned short st_rdev;
12490 + unsigned short __pad2;
12491 + unsigned long st_size;
12492 + unsigned long st_blksize;
12493 + unsigned long st_blocks;
12494 + unsigned long st_atime;
12495 + unsigned long __unused1;
12496 + unsigned long st_mtime;
12497 + unsigned long __unused2;
12498 + unsigned long st_ctime;
12499 + unsigned long __unused3;
12500 + unsigned long __unused4;
12501 + unsigned long __unused5;
12504 +/* This matches struct stat64 in glibc2.1, hence the absolutely
12505 + * insane amounts of padding around dev_t's.
12508 + unsigned long long st_dev;
12509 + unsigned char __pad1[2];
12511 +#define STAT64_HAS_BROKEN_ST_INO 1
12512 + unsigned long __st_ino;
12514 + unsigned int st_mode;
12515 + unsigned int st_nlink;
12517 + unsigned long st_uid;
12518 + unsigned long st_gid;
12520 + unsigned long long st_rdev;
12521 + unsigned char __pad3[2];
12523 + long long st_size;
12524 + unsigned long st_blksize;
12526 + unsigned long long st_blocks; /* Number 512-byte blocks allocated. */
12528 + unsigned long st_atime;
12529 + unsigned long st_atime_nsec;
12531 + unsigned long st_mtime;
12532 + unsigned long st_mtime_nsec;
12534 + unsigned long st_ctime;
12535 + unsigned long st_ctime_nsec;
12537 + unsigned long long st_ino;
12540 +#endif /* _ASM_UBICOM32_STAT_H */
12541 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/string.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/string.h
12542 --- linux-2.6.30.10/arch/ubicom32/include/asm/string.h 1970-01-01 02:00:00.000000000 +0200
12543 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/string.h 2009-12-11 11:45:11.000000000 +0200
12546 + * arch/ubicom32/include/asm/string.h
12547 + * String operation definitions for Ubicom32 architecture.
12549 + * (C) Copyright 2009, Ubicom, Inc.
12551 + * This file is part of the Ubicom32 Linux Kernel Port.
12553 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
12554 + * it and/or modify it under the terms of the GNU General Public License
12555 + * as published by the Free Software Foundation, either version 2 of the
12556 + * License, or (at your option) any later version.
12558 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
12559 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12560 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
12561 + * the GNU General Public License for more details.
12563 + * You should have received a copy of the GNU General Public License
12564 + * along with the Ubicom32 Linux Kernel Port. If not,
12565 + * see <http://www.gnu.org/licenses/>.
12567 + * Ubicom32 implementation derived from (with many thanks):
12572 +#ifndef _ASM_UBICOM32_STRING_H
12573 +#define _ASM_UBICOM32_STRING_H
12575 +#define __HAVE_ARCH_MEMSET
12576 +extern void *memset(void *b, int c, size_t len);
12578 +#define __HAVE_ARCH_MEMCPY
12579 +extern void *memcpy(void *to, const void *from, size_t len);
12581 +#define __HAVE_ARCH_MEMMOVE
12582 +extern void * memmove(void *to, const void *from, size_t len);
12584 +#endif /* _ASM_UBICOM32_STRING_H */
12585 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/swab.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/swab.h
12586 --- linux-2.6.30.10/arch/ubicom32/include/asm/swab.h 1970-01-01 02:00:00.000000000 +0200
12587 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/swab.h 2009-12-11 11:45:11.000000000 +0200
12590 + * arch/ubicom32/include/asm/byteorder.h
12591 + * Byte order swapping utility routines.
12593 + * (C) Copyright 2009, Ubicom, Inc.
12595 + * This file is part of the Ubicom32 Linux Kernel Port.
12597 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
12598 + * it and/or modify it under the terms of the GNU General Public License
12599 + * as published by the Free Software Foundation, either version 2 of the
12600 + * License, or (at your option) any later version.
12602 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
12603 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12604 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
12605 + * the GNU General Public License for more details.
12607 + * You should have received a copy of the GNU General Public License
12608 + * along with the Ubicom32 Linux Kernel Port. If not,
12609 + * see <http://www.gnu.org/licenses/>.
12611 + * Ubicom32 implementation derived from (with many thanks):
12616 +#ifndef _ASM_UBICOM32_BYTEORDER_H
12617 +#define _ASM_UBICOM32_BYTEORDER_H
12619 +#include <linux/types.h>
12621 +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) || defined(__KERNEL__)
12622 +# define __BYTEORDER_HAS_U64__
12623 +# define __SWAB_64_THRU_32__
12626 +#if defined(IP7000) || defined(IP7000_REV2)
12628 +#define __arch__swab16 __builtin_ubicom32_swapb_2
12629 +#define __arch__swab32 __builtin_ubicom32_swapb_4
12631 +#endif /* IP7000 */
12633 +#endif /* _ASM_UBICOM32_BYTEORDER_H */
12634 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/switch-dev.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/switch-dev.h
12635 --- linux-2.6.30.10/arch/ubicom32/include/asm/switch-dev.h 1970-01-01 02:00:00.000000000 +0200
12636 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/switch-dev.h 2009-12-11 11:45:11.000000000 +0200
12639 + * arch/ubicom32/include/asm/switch-dev.h
12640 + * generic Ethernet switch platform data definitions for Ubicom32 architecture.
12642 + * (C) Copyright 2009, Ubicom, Inc.
12644 + * This file is part of the Ubicom32 Linux Kernel Port.
12646 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
12647 + * it and/or modify it under the terms of the GNU General Public License
12648 + * as published by the Free Software Foundation, either version 2 of the
12649 + * License, or (at your option) any later version.
12651 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
12652 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12653 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
12654 + * the GNU General Public License for more details.
12656 + * You should have received a copy of the GNU General Public License
12657 + * along with the Ubicom32 Linux Kernel Port. If not,
12658 + * see <http://www.gnu.org/licenses/>.
12660 + * Ubicom32 implementation derived from (with many thanks):
12665 +#ifndef _ASM_UBICOM32_SWITCH_DEV_H
12666 +#define _ASM_UBICOM32_SWITCH_DEV_H
12668 +#define SWITCH_DEV_FLAG_HW_RESET 0x01
12669 +#define SWITCH_DEV_FLAG_SW_RESET 0x02
12671 +struct switch_core_platform_data {
12673 + * See flags above
12678 + * GPIO to use for nReset
12683 + * Name of this switch
12685 + const char *name;
12688 +#endif /* _ASM_UBICOM32_SWITCH_DEV_H */
12689 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/system.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/system.h
12690 --- linux-2.6.30.10/arch/ubicom32/include/asm/system.h 1970-01-01 02:00:00.000000000 +0200
12691 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/system.h 2009-12-11 11:45:11.000000000 +0200
12694 + * arch/ubicom32/include/asm/system.h
12695 + * Low level switching definitions.
12697 + * (C) Copyright 2009, Ubicom, Inc.
12699 + * This file is part of the Ubicom32 Linux Kernel Port.
12701 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
12702 + * it and/or modify it under the terms of the GNU General Public License
12703 + * as published by the Free Software Foundation, either version 2 of the
12704 + * License, or (at your option) any later version.
12706 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
12707 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12708 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
12709 + * the GNU General Public License for more details.
12711 + * You should have received a copy of the GNU General Public License
12712 + * along with the Ubicom32 Linux Kernel Port. If not,
12713 + * see <http://www.gnu.org/licenses/>.
12715 + * Ubicom32 implementation derived from (with many thanks):
12720 +#ifndef _ASM_UBICOM32_SYSTEM_H
12721 +#define _ASM_UBICOM32_SYSTEM_H
12723 +#include <linux/irqflags.h>
12724 +#include <linux/linkage.h>
12725 +#include <asm/segment.h>
12726 +#include <asm/entry.h>
12727 +#include <asm/ldsr.h>
12728 +#include <asm/irq.h>
12729 +#include <asm/percpu.h>
12730 +#include <asm/ubicom32-common.h>
12731 +#include <asm/processor.h>
12734 + * switch_to(n) should switch tasks to task ptr, first checking that
12735 + * ptr isn't the current task, in which case it does nothing.
12737 +asmlinkage void resume(void);
12738 +extern void *__switch_to(struct task_struct *prev,
12739 + struct thread_struct *prev_switch,
12740 + struct thread_struct *next_switch);
12743 + * We will need a per linux thread sw_ksp for the switch_to macro to
12744 + * track the kernel stack pointer for the current thread on that linux thread.
12746 +#define switch_to(prev,next,last) \
12749 + _last = (void *) \
12750 + __switch_to(prev, &prev->thread, &next->thread); \
12751 + (last) = _last; \
12755 + * Force strict CPU ordering.
12756 + * Not really required on ubicom32...
12758 +#define nop() asm volatile ("nop"::)
12759 +#define mb() asm volatile ("" : : :"memory")
12760 +#define rmb() asm volatile ("" : : :"memory")
12761 +#define wmb() asm volatile ("" : : :"memory")
12762 +#define set_mb(var, value) ({ (var) = (value); wmb(); })
12765 +#define smp_mb() mb()
12766 +#define smp_rmb() rmb()
12767 +#define smp_wmb() wmb()
12768 +#define smp_read_barrier_depends() read_barrier_depends()
12770 +#define smp_mb() mb()
12771 +#define smp_rmb() rmb()
12772 +#define smp_wmb() wmb()
12773 +#define smp_read_barrier_depends() do { } while(0)
12776 +#define read_barrier_depends() ((void)0)
12779 + * The following defines change how the scheduler calls the switch_to()
12782 + * 1) The first causes the runqueue to be unlocked on entry to
12783 + * switch_to(). Since our ctx code does not play with the runqueue
12784 + * we do not need it unlocked.
12786 + * 2) The later turns interrupts on during a ctxsw to reduce the latency of
12787 + * interrupts during ctx. At this point in the port, we believe that this
12788 + * latency is not a problem since we have very little code to perform a ctxsw.
12790 +// #define __ARCH_WANT_UNLOCKED_CTXSW
12791 +// #define __ARCH_WANT_INTERRUPTS_ON_CTXSW
12793 +#endif /* _ASM_UBICOM32_SYSTEM_H */
12794 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/termbits.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/termbits.h
12795 --- linux-2.6.30.10/arch/ubicom32/include/asm/termbits.h 1970-01-01 02:00:00.000000000 +0200
12796 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/termbits.h 2009-12-11 11:45:11.000000000 +0200
12799 + * arch/ubicom32/include/asm/termbits.h
12800 + * Terminal/serial port definitions for Ubicom32 architecture.
12802 + * (C) Copyright 2009, Ubicom, Inc.
12804 + * This file is part of the Ubicom32 Linux Kernel Port.
12806 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
12807 + * it and/or modify it under the terms of the GNU General Public License
12808 + * as published by the Free Software Foundation, either version 2 of the
12809 + * License, or (at your option) any later version.
12811 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
12812 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12813 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
12814 + * the GNU General Public License for more details.
12816 + * You should have received a copy of the GNU General Public License
12817 + * along with the Ubicom32 Linux Kernel Port. If not,
12818 + * see <http://www.gnu.org/licenses/>.
12820 + * Ubicom32 implementation derived from (with many thanks):
12825 +#ifndef _ASM_UBICOM32_TERMBITS_H
12826 +#define _ASM_UBICOM32_TERMBITS_H
12828 +#include <linux/posix_types.h>
12830 +typedef unsigned char cc_t;
12831 +typedef unsigned int speed_t;
12832 +typedef unsigned int tcflag_t;
12836 + tcflag_t c_iflag; /* input mode flags */
12837 + tcflag_t c_oflag; /* output mode flags */
12838 + tcflag_t c_cflag; /* control mode flags */
12839 + tcflag_t c_lflag; /* local mode flags */
12840 + cc_t c_line; /* line discipline */
12841 + cc_t c_cc[NCCS]; /* control characters */
12845 + tcflag_t c_iflag; /* input mode flags */
12846 + tcflag_t c_oflag; /* output mode flags */
12847 + tcflag_t c_cflag; /* control mode flags */
12848 + tcflag_t c_lflag; /* local mode flags */
12849 + cc_t c_line; /* line discipline */
12850 + cc_t c_cc[NCCS]; /* control characters */
12851 + speed_t c_ispeed; /* input speed */
12852 + speed_t c_ospeed; /* output speed */
12856 + tcflag_t c_iflag; /* input mode flags */
12857 + tcflag_t c_oflag; /* output mode flags */
12858 + tcflag_t c_cflag; /* control mode flags */
12859 + tcflag_t c_lflag; /* local mode flags */
12860 + cc_t c_line; /* line discipline */
12861 + cc_t c_cc[NCCS]; /* control characters */
12862 + speed_t c_ispeed; /* input speed */
12863 + speed_t c_ospeed; /* output speed */
12866 +/* c_cc characters */
12879 +#define VREPRINT 12
12880 +#define VDISCARD 13
12881 +#define VWERASE 14
12886 +/* c_iflag bits */
12887 +#define IGNBRK 0000001
12888 +#define BRKINT 0000002
12889 +#define IGNPAR 0000004
12890 +#define PARMRK 0000010
12891 +#define INPCK 0000020
12892 +#define ISTRIP 0000040
12893 +#define INLCR 0000100
12894 +#define IGNCR 0000200
12895 +#define ICRNL 0000400
12896 +#define IUCLC 0001000
12897 +#define IXON 0002000
12898 +#define IXANY 0004000
12899 +#define IXOFF 0010000
12900 +#define IMAXBEL 0020000
12901 +#define IUTF8 0040000
12903 +/* c_oflag bits */
12904 +#define OPOST 0000001
12905 +#define OLCUC 0000002
12906 +#define ONLCR 0000004
12907 +#define OCRNL 0000010
12908 +#define ONOCR 0000020
12909 +#define ONLRET 0000040
12910 +#define OFILL 0000100
12911 +#define OFDEL 0000200
12912 +#define NLDLY 0000400
12913 +#define NL0 0000000
12914 +#define NL1 0000400
12915 +#define CRDLY 0003000
12916 +#define CR0 0000000
12917 +#define CR1 0001000
12918 +#define CR2 0002000
12919 +#define CR3 0003000
12920 +#define TABDLY 0014000
12921 +#define TAB0 0000000
12922 +#define TAB1 0004000
12923 +#define TAB2 0010000
12924 +#define TAB3 0014000
12925 +#define XTABS 0014000
12926 +#define BSDLY 0020000
12927 +#define BS0 0000000
12928 +#define BS1 0020000
12929 +#define VTDLY 0040000
12930 +#define VT0 0000000
12931 +#define VT1 0040000
12932 +#define FFDLY 0100000
12933 +#define FF0 0000000
12934 +#define FF1 0100000
12936 +/* c_cflag bit meaning */
12937 +#define CBAUD 0010017
12938 +#define B0 0000000 /* hang up */
12939 +#define B50 0000001
12940 +#define B75 0000002
12941 +#define B110 0000003
12942 +#define B134 0000004
12943 +#define B150 0000005
12944 +#define B200 0000006
12945 +#define B300 0000007
12946 +#define B600 0000010
12947 +#define B1200 0000011
12948 +#define B1800 0000012
12949 +#define B2400 0000013
12950 +#define B4800 0000014
12951 +#define B9600 0000015
12952 +#define B19200 0000016
12953 +#define B38400 0000017
12954 +#define EXTA B19200
12955 +#define EXTB B38400
12956 +#define CSIZE 0000060
12957 +#define CS5 0000000
12958 +#define CS6 0000020
12959 +#define CS7 0000040
12960 +#define CS8 0000060
12961 +#define CSTOPB 0000100
12962 +#define CREAD 0000200
12963 +#define PARENB 0000400
12964 +#define PARODD 0001000
12965 +#define HUPCL 0002000
12966 +#define CLOCAL 0004000
12967 +#define CBAUDEX 0010000
12968 +#define BOTHER 0010000
12969 +#define B57600 0010001
12970 +#define B115200 0010002
12971 +#define B230400 0010003
12972 +#define B460800 0010004
12973 +#define B500000 0010005
12974 +#define B576000 0010006
12975 +#define B921600 0010007
12976 +#define B1000000 0010010
12977 +#define B1152000 0010011
12978 +#define B1500000 0010012
12979 +#define B2000000 0010013
12980 +#define B2500000 0010014
12981 +#define B3000000 0010015
12982 +#define B3500000 0010016
12983 +#define B4000000 0010017
12984 +#define CIBAUD 002003600000 /* input baud rate */
12985 +#define CMSPAR 010000000000 /* mark or space (stick) parity */
12986 +#define CRTSCTS 020000000000 /* flow control */
12988 +#define IBSHIFT 16 /* Shift from CBAUD to CIBAUD */
12990 +/* c_lflag bits */
12991 +#define ISIG 0000001
12992 +#define ICANON 0000002
12993 +#define XCASE 0000004
12994 +#define ECHO 0000010
12995 +#define ECHOE 0000020
12996 +#define ECHOK 0000040
12997 +#define ECHONL 0000100
12998 +#define NOFLSH 0000200
12999 +#define TOSTOP 0000400
13000 +#define ECHOCTL 0001000
13001 +#define ECHOPRT 0002000
13002 +#define ECHOKE 0004000
13003 +#define FLUSHO 0010000
13004 +#define PENDIN 0040000
13005 +#define IEXTEN 0100000
13008 +/* tcflow() and TCXONC use these */
13014 +/* tcflush() and TCFLSH use these */
13015 +#define TCIFLUSH 0
13016 +#define TCOFLUSH 1
13017 +#define TCIOFLUSH 2
13019 +/* tcsetattr uses these */
13021 +#define TCSADRAIN 1
13022 +#define TCSAFLUSH 2
13024 +#endif /* _ASM_UBICOM32_TERMBITS_H */
13025 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/termios.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/termios.h
13026 --- linux-2.6.30.10/arch/ubicom32/include/asm/termios.h 1970-01-01 02:00:00.000000000 +0200
13027 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/termios.h 2009-12-11 11:45:11.000000000 +0200
13030 + * arch/ubicom32/include/asm/termios.h
13031 + * Ubicom32 termio definitions.
13033 + * (C) Copyright 2009, Ubicom, Inc.
13035 + * This file is part of the Ubicom32 Linux Kernel Port.
13037 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
13038 + * it and/or modify it under the terms of the GNU General Public License
13039 + * as published by the Free Software Foundation, either version 2 of the
13040 + * License, or (at your option) any later version.
13042 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
13043 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
13044 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13045 + * the GNU General Public License for more details.
13047 + * You should have received a copy of the GNU General Public License
13048 + * along with the Ubicom32 Linux Kernel Port. If not,
13049 + * see <http://www.gnu.org/licenses/>.
13051 + * Ubicom32 implementation derived from (with many thanks):
13056 +#ifndef _ASM_UBICOM32_TERMIOS_H
13057 +#define _ASM_UBICOM32_TERMIOS_H
13059 +#include <asm/termbits.h>
13060 +#include <asm/ioctls.h>
13063 + unsigned short ws_row;
13064 + unsigned short ws_col;
13065 + unsigned short ws_xpixel;
13066 + unsigned short ws_ypixel;
13071 + unsigned short c_iflag; /* input mode flags */
13072 + unsigned short c_oflag; /* output mode flags */
13073 + unsigned short c_cflag; /* control mode flags */
13074 + unsigned short c_lflag; /* local mode flags */
13075 + unsigned char c_line; /* line discipline */
13076 + unsigned char c_cc[NCC]; /* control characters */
13080 +/* intr=^C quit=^| erase=del kill=^U
13081 + eof=^D vtime=\0 vmin=\1 sxtc=\0
13082 + start=^Q stop=^S susp=^Z eol=\0
13083 + reprint=^R discard=^U werase=^W lnext=^V
13086 +#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
13090 +#define TIOCM_LE 0x001
13091 +#define TIOCM_DTR 0x002
13092 +#define TIOCM_RTS 0x004
13093 +#define TIOCM_ST 0x008
13094 +#define TIOCM_SR 0x010
13095 +#define TIOCM_CTS 0x020
13096 +#define TIOCM_CAR 0x040
13097 +#define TIOCM_RNG 0x080
13098 +#define TIOCM_DSR 0x100
13099 +#define TIOCM_CD TIOCM_CAR
13100 +#define TIOCM_RI TIOCM_RNG
13101 +#define TIOCM_OUT1 0x2000
13102 +#define TIOCM_OUT2 0x4000
13103 +#define TIOCM_LOOP 0x8000
13105 +/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
13110 + * Translate a "termio" structure into a "termios". Ugh.
13112 +#define user_termio_to_kernel_termios(termios, termio) \
13114 + unsigned short tmp; \
13115 + get_user(tmp, &(termio)->c_iflag); \
13116 + (termios)->c_iflag = (0xffff0000 & ((termios)->c_iflag)) | tmp; \
13117 + get_user(tmp, &(termio)->c_oflag); \
13118 + (termios)->c_oflag = (0xffff0000 & ((termios)->c_oflag)) | tmp; \
13119 + get_user(tmp, &(termio)->c_cflag); \
13120 + (termios)->c_cflag = (0xffff0000 & ((termios)->c_cflag)) | tmp; \
13121 + get_user(tmp, &(termio)->c_lflag); \
13122 + (termios)->c_lflag = (0xffff0000 & ((termios)->c_lflag)) | tmp; \
13123 + get_user((termios)->c_line, &(termio)->c_line); \
13124 + copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \
13128 + * Translate a "termios" structure into a "termio". Ugh.
13130 +#define kernel_termios_to_user_termio(termio, termios) \
13132 + put_user((termios)->c_iflag, &(termio)->c_iflag); \
13133 + put_user((termios)->c_oflag, &(termio)->c_oflag); \
13134 + put_user((termios)->c_cflag, &(termio)->c_cflag); \
13135 + put_user((termios)->c_lflag, &(termio)->c_lflag); \
13136 + put_user((termios)->c_line, &(termio)->c_line); \
13137 + copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
13140 +#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios2))
13141 +#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios2))
13142 +#define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios))
13143 +#define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios))
13145 +#endif /* __KERNEL__ */
13147 +#endif /* _ASM_UBICOM32_TERMIOS_H */
13148 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/thread-asm.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/thread-asm.h
13149 --- linux-2.6.30.10/arch/ubicom32/include/asm/thread-asm.h 1970-01-01 02:00:00.000000000 +0200
13150 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/thread-asm.h 2009-12-11 11:45:11.000000000 +0200
13153 + * arch/ubicom32/include/asm/thread-asm.h
13154 + * Ubicom32 architecture specific thread definitions.
13156 + * (C) Copyright 2009, Ubicom, Inc.
13158 + * This file is part of the Ubicom32 Linux Kernel Port.
13160 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
13161 + * it and/or modify it under the terms of the GNU General Public License
13162 + * as published by the Free Software Foundation, either version 2 of the
13163 + * License, or (at your option) any later version.
13165 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
13166 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
13167 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13168 + * the GNU General Public License for more details.
13170 + * You should have received a copy of the GNU General Public License
13171 + * along with the Ubicom32 Linux Kernel Port. If not,
13172 + * see <http://www.gnu.org/licenses/>.
13174 + * Ubicom32 implementation derived from (with many thanks):
13179 +#ifndef _ASM_UBICOM32_THREAD_ASM_H
13180 +#define _ASM_UBICOM32_THREAD_ASM_H
13183 + * thread_get_self
13184 + * Read and shift the current thread into reg
13186 + * Note that we don't need to mask the result as bits 6 through 31 of the
13187 + * ROSR are zeroes.
13189 +.macro thread_get_self reg
13190 + lsr.4 \reg, ROSR, #2
13194 + * thread_get_self_mask
13195 + * Read and shift the current thread mask into reg
13197 +.macro thread_get_self_mask reg
13198 + lsr.4 \reg, ROSR, #2
13199 + lsl.4 \reg, #1, \reg /* Thread bit */
13202 +#endif /* _ASM_UBICOM32_THREAD_ASM_H */
13203 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/thread.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/thread.h
13204 --- linux-2.6.30.10/arch/ubicom32/include/asm/thread.h 1970-01-01 02:00:00.000000000 +0200
13205 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/thread.h 2009-12-11 11:45:11.000000000 +0200
13208 + * arch/ubicom32/include/asm/thread.h
13209 + * Ubicom32 architecture specific thread definitions.
13211 + * (C) Copyright 2009, Ubicom, Inc.
13213 + * This file is part of the Ubicom32 Linux Kernel Port.
13215 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
13216 + * it and/or modify it under the terms of the GNU General Public License
13217 + * as published by the Free Software Foundation, either version 2 of the
13218 + * License, or (at your option) any later version.
13220 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
13221 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
13222 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13223 + * the GNU General Public License for more details.
13225 + * You should have received a copy of the GNU General Public License
13226 + * along with the Ubicom32 Linux Kernel Port. If not,
13227 + * see <http://www.gnu.org/licenses/>.
13229 + * Ubicom32 implementation derived from (with many thanks):
13234 +#ifndef _ASM_UBICOM32_THREAD_H
13235 +#define _ASM_UBICOM32_THREAD_H
13237 +#if !defined(__ASSEMBLY__)
13239 +#include <asm/ptrace.h>
13240 +#include <asm/ubicom32-common.h>
13242 +typedef int thread_t;
13243 +typedef unsigned char thread_type_t;
13244 +typedef void (*thread_exec_fn_t)(void *arg);
13246 +#define THREAD_NULL 0x40
13247 +#define THREAD_TYPE_HRT (1 << 0)
13248 +#define THREAD_TYPE_SPECIAL 0
13249 +#define THREAD_TYPE_NORMAL 0
13250 +#define THREAD_TYPE_BACKGROUND (1 << 1)
13253 + * This is the upper bound on the maximum hardware threads that one will find
13254 + * on a Ubicom processor. It is used to size per hardware thread data structures.
13256 +#define THREAD_ARCHITECTURAL_MAX 16
13259 + * TODO: Rename this at some point to be thread_
13261 +extern unsigned int sw_ksp[THREAD_ARCHITECTURAL_MAX];
13265 + * thread_get_self()
13267 +static inline thread_t thread_get_self(void)
13272 + * Note that ROSR has zeroes in bits 6 through 31 and so we don't need
13273 + * to do any additional bit masking here.
13276 + "lsr.4 %0, ROSR, #2 \n\t"
13286 + * thread_suspend()
13288 +static inline void thread_suspend(void)
13298 + * thread_resume()
13300 +static inline void thread_resume(thread_t thread)
13303 + "move.4 MT_ACTIVE_SET, %0 \n\t"
13304 + "pipe_flush 0 \n\t"
13305 + "pipe_flush 0 \n\t"
13307 + : "d" (1 << thread)
13314 + * thread_enable_mask()
13315 + * Enable all threads in the mask.
13317 + * All writes to MT_EN must be protected by the MT_EN_LOCK bit
13319 +static inline void thread_enable_mask(unsigned int mask)
13322 + * must flush the pipeline twice.
13323 + * first pipe_flush is to ensure write to MT_EN is completed
13324 + * second one is to ensure any new instructions from
13325 + * the targeted thread (the one being disabled), that
13326 + * are issued while the write to MT_EN is being executed,
13329 + UBICOM32_LOCK(MT_EN_LOCK_BIT);
13331 + "or.4 MT_EN, MT_EN, %0 \n\t"
13332 + "pipe_flush 0 \n\t"
13333 + "pipe_flush 0 \n\t"
13338 + UBICOM32_UNLOCK(MT_EN_LOCK_BIT);
13342 + * thread_enable()
13344 +static inline void thread_enable(thread_t thread)
13346 + thread_enable_mask(1 << thread);
13350 + * thread_disable_mask()
13351 + * Disable all threads in the mask.
13353 + * All writes to MT_EN must be protected by the MT_EN_LOCK bit
13355 +static inline void thread_disable_mask(unsigned int mask)
13358 + * must flush the pipeline twice.
13359 + * first pipe_flush is to ensure write to MT_EN is completed
13360 + * second one is to ensure any new instructions from
13361 + * the targeted thread (the one being disabled), that
13362 + * are issued while the write to MT_EN is being executed,
13365 + UBICOM32_LOCK(MT_EN_LOCK_BIT);
13367 + "and.4 MT_EN, MT_EN, %0 \n\t"
13368 + "pipe_flush 0 \n\t"
13369 + "pipe_flush 0 \n\t"
13374 + UBICOM32_UNLOCK(MT_EN_LOCK_BIT);
13378 + * thread_disable()
13380 +static inline void thread_disable(thread_t thread)
13382 + thread_disable_mask(1 << thread);
13386 + * thread_disable_others()
13387 + * Disable all other threads
13389 +static inline void thread_disable_others(void)
13391 + thread_t self = thread_get_self();
13392 + thread_disable_mask(~(1 << self));
13396 + * thread_is_trapped()
13397 + * Is the specified tid trapped?
13399 +static inline int thread_is_trapped(thread_t tid)
13401 + int thread_mask = (1 << tid);
13405 + "move.4 %0, MT_TRAP \n\t"
13406 + : "=d" (trap_thread)
13409 + return (trap_thread & thread_mask);
13413 + * thread_is_enabled()
13414 + * Is the specified tid enabled?
13416 +static inline int thread_is_enabled(thread_t tid)
13418 + int thread_mask = (1 << tid);
13419 + int enabled_threads;
13422 + "move.4 %0, MT_EN \n\t"
13423 + : "=d" (enabled_threads)
13426 + return (enabled_threads & thread_mask);
13430 + * thread_get_instruction_count()
13432 +static inline unsigned int thread_get_instruction_count(void)
13434 + unsigned int result;
13436 + "move.4 %0, INST_CNT \n\t"
13443 + * thread_get_pc()
13444 + * pc could point to a speculative and cancelled instruction unless thread is disabled
13446 +static inline void *thread_get_pc(thread_t thread)
13450 + "move.4 csr, %1 \n\t"
13451 + "setcsr_flush 0 \n\t"
13452 + "move.4 %0, pc \n\t"
13453 + "move.4 csr, #0 \n\t"
13454 + "setcsr_flush 0 \n\t"
13456 + : "r" ((thread << 9) | (1 << 8))
13462 + * thread_get_trap_cause()
13463 + * This should be called only when the thread is not running
13465 +static inline unsigned int thread_get_trap_cause(thread_t thread)
13467 + unsigned int result;
13469 + "move.4 csr, %1 \n\t"
13470 + "setcsr_flush 0 \n\t"
13471 + "move.4 %0, trap_cause \n\t"
13472 + "move.4 csr, #0 \n\t"
13473 + "setcsr_flush 0 \n\t"
13475 + : "r" ((thread << 9) | (1 << 8))
13481 + * THREAD_STALL macro.
13483 +#define THREAD_STALL \
13485 + "move.4 mt_dbg_active_clr, #-1 \n\t" \
13486 + "pipe_flush 0 \n\t" \
13491 +extern unsigned int thread_get_mainline(void);
13492 +extern void thread_set_mainline(thread_t tid);
13493 +extern thread_t thread_alloc(void);
13494 +extern thread_t thread_start(thread_t thread, thread_exec_fn_t exec, void *arg, unsigned int *sp_high, thread_type_t type);
13501 + * thread_get_self
13502 + * Read and shift the current thread into reg
13504 + * Note that we don't need to mask the result as bits 6 through 31 of the
13505 + * ROSR are zeroes.
13507 +".macro thread_get_self reg \n\t"
13508 +" lsr.4 \\reg, ROSR, #2 \n\t"
13512 + * thread_get_self_mask
13513 + * Read and shift the current thread mask into reg
13515 +".macro thread_get_self_mask reg \n\t"
13516 +" lsr.4 \\reg, ROSR, #2 \n\t"
13517 +" lsl.4 \\reg, #1, \\reg \n\t" /* Thread bit */
13521 +#else /* __ASSEMBLY__ */
13523 +#include <asm/thread-asm.h>
13525 +#endif /* __ASSEMBLY__ */
13526 +#endif /* _ASM_UBICOM32_THREAD_H */
13527 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/thread_info.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/thread_info.h
13528 --- linux-2.6.30.10/arch/ubicom32/include/asm/thread_info.h 1970-01-01 02:00:00.000000000 +0200
13529 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/thread_info.h 2009-12-11 11:45:11.000000000 +0200
13532 + * arch/ubicom32/include/asm/thread_info.h
13533 + * Ubicom32 architecture low-level thread information.
13535 + * (C) Copyright 2009, Ubicom, Inc.
13536 + * Adapted from the i386 and PPC versions by Greg Ungerer (gerg@snapgear.com)
13537 + * Copyright (C) 2002 David Howells (dhowells@redhat.com)
13538 + * - Incorporating suggestions made by Linus Torvalds and Dave Miller
13540 + * This file is part of the Ubicom32 Linux Kernel Port.
13542 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
13543 + * it and/or modify it under the terms of the GNU General Public License
13544 + * as published by the Free Software Foundation, either version 2 of the
13545 + * License, or (at your option) any later version.
13547 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
13548 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
13549 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13550 + * the GNU General Public License for more details.
13552 + * You should have received a copy of the GNU General Public License
13553 + * along with the Ubicom32 Linux Kernel Port. If not,
13554 + * see <http://www.gnu.org/licenses/>.
13556 + * Ubicom32 implementation derived from (with many thanks):
13562 +#ifndef _ASM_UBICOM32_THREAD_INFO_H
13563 +#define _ASM_UBICOM32_THREAD_INFO_H
13565 +#include <asm/page.h>
13568 + * Size of kernel stack for each process. This must be a power of 2...
13570 +#ifdef CONFIG_4KSTACKS
13571 +#define THREAD_SIZE_ORDER (0)
13573 +#define THREAD_SIZE_ORDER (1)
13577 + * for asm files, THREAD_SIZE is now generated by asm-offsets.c
13579 +#define THREAD_SIZE (PAGE_SIZE<<THREAD_SIZE_ORDER)
13583 +#ifndef __ASSEMBLY__
13586 + * low level task data.
13588 +struct thread_info {
13589 + struct task_struct *task; /* main task structure */
13590 + struct exec_domain *exec_domain; /* execution domain */
13591 + unsigned long flags; /* low level flags */
13592 + int cpu; /* cpu we're on */
13593 + int preempt_count; /* 0 => preemptable, <0 => BUG */
13594 + int interrupt_nesting; /* Interrupt nesting level. */
13595 + struct restart_block restart_block;
13599 + * macros/functions for gaining access to the thread information structure
13601 +#define INIT_THREAD_INFO(tsk) \
13604 + .exec_domain = &default_exec_domain, \
13607 + .interrupt_nesting = 0, \
13608 + .restart_block = { \
13609 + .fn = do_no_restart_syscall, \
13613 +#define init_thread_info (init_thread_union.thread_info)
13614 +#define init_stack (init_thread_union.stack)
13617 +/* how to get the thread information struct from C */
13618 +static inline struct thread_info *current_thread_info(void)
13620 + struct thread_info *ti;
13623 + "and.4 %0, sp, %1\n\t"
13625 + : "d" (~(THREAD_SIZE-1))
13632 +#define STACK_WARN (THREAD_SIZE / 8)
13634 +#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR 1
13636 +/* thread information allocation */
13637 +#define alloc_thread_info(tsk) ((struct thread_info *) \
13638 + __get_free_pages(GFP_KERNEL, THREAD_SIZE_ORDER))
13639 +#define free_thread_info(ti) free_pages((unsigned long) (ti), THREAD_SIZE_ORDER)
13640 +#endif /* __ASSEMBLY__ */
13642 +#define PREEMPT_ACTIVE 0x4000000
13645 + * thread information flag bit numbers
13647 +#define TIF_SYSCALL_TRACE 0 /* syscall trace active */
13648 +#define TIF_SIGPENDING 1 /* signal pending */
13649 +#define TIF_NEED_RESCHED 2 /* rescheduling necessary */
13650 +#define TIF_POLLING_NRFLAG 3 /* true if poll_idle() is polling
13651 + TIF_NEED_RESCHED */
13652 +#define TIF_MEMDIE 4
13654 +/* as above, but as bit values */
13655 +#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
13656 +#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
13657 +#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
13658 +#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
13660 +#define _TIF_WORK_MASK 0x0000FFFE /* work to do on interrupt/exception return */
13662 +#endif /* __KERNEL__ */
13664 +#endif /* _ASM_UBICOM32_THREAD_INFO_H */
13665 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/timex.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/timex.h
13666 --- linux-2.6.30.10/arch/ubicom32/include/asm/timex.h 1970-01-01 02:00:00.000000000 +0200
13667 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/timex.h 2009-12-11 11:45:11.000000000 +0200
13670 + * arch/ubicom32/include/asm/timex.h
13671 + * Ubicom32 architecture timex specifications.
13673 + * (C) Copyright 2009, Ubicom, Inc.
13675 + * This file is part of the Ubicom32 Linux Kernel Port.
13677 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
13678 + * it and/or modify it under the terms of the GNU General Public License
13679 + * as published by the Free Software Foundation, either version 2 of the
13680 + * License, or (at your option) any later version.
13682 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
13683 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
13684 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13685 + * the GNU General Public License for more details.
13687 + * You should have received a copy of the GNU General Public License
13688 + * along with the Ubicom32 Linux Kernel Port. If not,
13689 + * see <http://www.gnu.org/licenses/>.
13691 + * Ubicom32 implementation derived from (with many thanks):
13696 +#ifndef _ASM_UBICOM32_TIMEX_H
13697 +#define _ASM_UBICOM32_TIMEX_H
13699 +#define CLOCK_TICK_RATE 266000000
13701 +// #define ARCH_HAS_READ_CURRENT_TIMER
13703 +typedef unsigned long cycles_t;
13705 +static inline cycles_t get_cycles(void)
13710 +extern int timer_alloc(void);
13711 +extern void timer_set(int timervector, unsigned int cycles);
13712 +extern int timer_reset(int timervector, unsigned int cycles);
13713 +extern void timer_tick_init(void);
13714 +extern void timer_device_init(void);
13716 +#if defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)
13717 +extern void local_timer_interrupt(void);
13720 +#if defined(CONFIG_LOCAL_TIMERS) || defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)
13721 +extern int local_timer_setup(unsigned int cpu);
13724 +#endif /* _ASM_UBICOM32_TIMEX_H */
13725 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/tlbflush.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/tlbflush.h
13726 --- linux-2.6.30.10/arch/ubicom32/include/asm/tlbflush.h 1970-01-01 02:00:00.000000000 +0200
13727 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/tlbflush.h 2009-12-11 11:45:11.000000000 +0200
13730 + * arch/ubicom32/include/asm/tlbflush.h
13731 + * TLB operations for Ubicom32 architecture.
13733 + * (C) Copyright 2009, Ubicom, Inc.
13734 + * Copyright (C) 2000 Lineo, David McCullough <davidm@uclinux.org>
13735 + * Copyright (C) 2000-2002, Greg Ungerer <gerg@snapgear.com>
13737 + * This file is part of the Ubicom32 Linux Kernel Port.
13739 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
13740 + * it and/or modify it under the terms of the GNU General Public License
13741 + * as published by the Free Software Foundation, either version 2 of the
13742 + * License, or (at your option) any later version.
13744 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
13745 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
13746 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13747 + * the GNU General Public License for more details.
13749 + * You should have received a copy of the GNU General Public License
13750 + * along with the Ubicom32 Linux Kernel Port. If not,
13751 + * see <http://www.gnu.org/licenses/>.
13753 + * Ubicom32 implementation derived from (with many thanks):
13758 +#ifndef _ASM_UBICOM32_TLB_FLUSH_H
13759 +#define _ASM_UBICOM32_TLB_FLUSH_H
13761 +#include <asm/setup.h>
13764 + * flush all user-space atc entries.
13766 +static inline void __flush_tlb(void)
13771 +static inline void __flush_tlb_one(unsigned long addr)
13776 +#define flush_tlb() __flush_tlb()
13779 + * flush all atc entries (both kernel and user-space entries).
13781 +static inline void flush_tlb_all(void)
13786 +static inline void flush_tlb_mm(struct mm_struct *mm)
13791 +static inline void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
13796 +static inline void flush_tlb_range(struct mm_struct *mm,
13797 + unsigned long start, unsigned long end)
13802 +static inline void flush_tlb_kernel_page(unsigned long addr)
13807 +#endif /* _ASM_UBICOM32_TLB_FLUSH_H */
13808 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/tlb.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/tlb.h
13809 --- linux-2.6.30.10/arch/ubicom32/include/asm/tlb.h 1970-01-01 02:00:00.000000000 +0200
13810 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/tlb.h 2009-12-11 11:45:11.000000000 +0200
13813 + * arch/ubicom32/include/asm/tlb.h
13814 + * Ubicom32 architecture TLB operations.
13816 + * (C) Copyright 2009, Ubicom, Inc.
13818 + * This file is part of the Ubicom32 Linux Kernel Port.
13820 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
13821 + * it and/or modify it under the terms of the GNU General Public License
13822 + * as published by the Free Software Foundation, either version 2 of the
13823 + * License, or (at your option) any later version.
13825 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
13826 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
13827 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13828 + * the GNU General Public License for more details.
13830 + * You should have received a copy of the GNU General Public License
13831 + * along with the Ubicom32 Linux Kernel Port. If not,
13832 + * see <http://www.gnu.org/licenses/>.
13834 + * Ubicom32 implementation derived from (with many thanks):
13839 +#ifndef _ASM_UBICOM32_TLB_H
13840 +#define _ASM_UBICOM32_TLB_H
13843 + * ubicom32 doesn't need any special per-pte or
13844 + * per-vma handling..
13846 +#define tlb_start_vma(tlb, vma) do { } while (0)
13847 +#define tlb_end_vma(tlb, vma) do { } while (0)
13848 +#define __tlb_remove_tlb_entry(tlb, ptep, address) do { } while (0)
13851 + * .. because we flush the whole mm when it
13854 +#define tlb_flush(tlb)
13856 +#include <asm-generic/tlb.h>
13858 +#endif /* _ASM_UBICOM32_TLB_H */
13859 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/topology.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/topology.h
13860 --- linux-2.6.30.10/arch/ubicom32/include/asm/topology.h 1970-01-01 02:00:00.000000000 +0200
13861 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/topology.h 2009-12-11 11:45:11.000000000 +0200
13864 + * arch/ubicom32/include/asm/topology.h
13865 + * Generic topology.h definitions for Ubicom32 architecture.
13867 + * (C) Copyright 2009, Ubicom, Inc.
13869 + * This file is part of the Ubicom32 Linux Kernel Port.
13871 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
13872 + * it and/or modify it under the terms of the GNU General Public License
13873 + * as published by the Free Software Foundation, either version 2 of the
13874 + * License, or (at your option) any later version.
13876 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
13877 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
13878 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13879 + * the GNU General Public License for more details.
13881 + * You should have received a copy of the GNU General Public License
13882 + * along with the Ubicom32 Linux Kernel Port. If not,
13883 + * see <http://www.gnu.org/licenses/>.
13885 + * Ubicom32 implementation derived from (with many thanks):
13890 +#ifndef _ASM_UBICOM32_TOPOLOGY_H
13891 +#define _ASM_UBICOM32_TOPOLOGY_H
13893 +#include <asm-generic/topology.h>
13895 +#endif /* _ASM_UBICOM32_TOPOLOGY_H */
13896 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/traps.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/traps.h
13897 --- linux-2.6.30.10/arch/ubicom32/include/asm/traps.h 1970-01-01 02:00:00.000000000 +0200
13898 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/traps.h 2009-12-11 11:45:11.000000000 +0200
13901 + * arch/ubicom32/include/asm/traps.h
13902 + * Trap related definitions for Ubicom32 architecture.
13904 + * (C) Copyright 2009, Ubicom, Inc.
13906 + * This file is part of the Ubicom32 Linux Kernel Port.
13908 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
13909 + * it and/or modify it under the terms of the GNU General Public License
13910 + * as published by the Free Software Foundation, either version 2 of the
13911 + * License, or (at your option) any later version.
13913 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
13914 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
13915 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13916 + * the GNU General Public License for more details.
13918 + * You should have received a copy of the GNU General Public License
13919 + * along with the Ubicom32 Linux Kernel Port. If not,
13920 + * see <http://www.gnu.org/licenses/>.
13922 + * Ubicom32 implementation derived from (with many thanks):
13928 +#ifndef _ASM_UBICOM32_TRAPS_H
13929 +#define _ASM_UBICOM32_TRAPS_H
13932 + * Trap causes passed from ultra to Host OS
13934 +#define TRAP_CAUSE_TOTAL 13
13935 +#define TRAP_CAUSE_DST_RANGE_ERR 12
13936 +#define TRAP_CAUSE_SRC1_RANGE_ERR 11
13937 +#define TRAP_CAUSE_I_RANGE_ERR 10
13938 +#define TRAP_CAUSE_DCAPT 9
13939 +#define TRAP_CAUSE_DST_SERROR 8
13940 +#define TRAP_CAUSE_SRC1_SERROR 7
13941 +#define TRAP_CAUSE_DST_MISALIGNED 6
13942 +#define TRAP_CAUSE_SRC1_MISALIGNED 5
13943 +#define TRAP_CAUSE_DST_DECODE_ERR 4
13944 +#define TRAP_CAUSE_SRC1_DECODE_ERR 3
13945 +#define TRAP_CAUSE_ILLEGAL_INST 2
13946 +#define TRAP_CAUSE_I_SERROR 1
13947 +#define TRAP_CAUSE_I_DECODE_ERR 0
13949 +extern void trap_handler(int irq, struct pt_regs *regs);
13950 +extern void trap_init_interrupt(void);
13951 +extern void unaligned_emulate(unsigned int thread);
13952 +extern int unaligned_only(unsigned int cause);
13954 +#endif /* _ASM_UBICOM32_TRAPS_H */
13955 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/types.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/types.h
13956 --- linux-2.6.30.10/arch/ubicom32/include/asm/types.h 1970-01-01 02:00:00.000000000 +0200
13957 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/types.h 2009-12-11 11:45:11.000000000 +0200
13960 + * arch/ubicom32/include/asm/types.h
13961 + * Date type definitions for Ubicom32 architecture.
13963 + * (C) Copyright 2009, Ubicom, Inc.
13965 + * This file is part of the Ubicom32 Linux Kernel Port.
13967 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
13968 + * it and/or modify it under the terms of the GNU General Public License
13969 + * as published by the Free Software Foundation, either version 2 of the
13970 + * License, or (at your option) any later version.
13972 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
13973 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
13974 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13975 + * the GNU General Public License for more details.
13977 + * You should have received a copy of the GNU General Public License
13978 + * along with the Ubicom32 Linux Kernel Port. If not,
13979 + * see <http://www.gnu.org/licenses/>.
13981 + * Ubicom32 implementation derived from (with many thanks):
13986 +#ifndef _ASM_UBICOM32_TYPES_H
13987 +#define _ASM_UBICOM32_TYPES_H
13990 + * This file is never included by application software unless
13991 + * explicitly requested (e.g., via linux/types.h) in which case the
13992 + * application is Linux specific so (user-) name space pollution is
13993 + * not a major issue. However, for interoperability, libraries still
13994 + * need to be careful to avoid a name clashes.
13997 +#include <asm-generic/int-ll64.h>
13999 +#ifndef __ASSEMBLY__
14001 +typedef unsigned short umode_t;
14003 +#endif /* __ASSEMBLY__ */
14006 + * These aren't exported outside the kernel to avoid name space clashes
14010 +#define BITS_PER_LONG 32
14012 +#ifndef __ASSEMBLY__
14014 +/* DMA addresses are always 32-bits wide */
14016 +typedef u32 dma_addr_t;
14017 +typedef u32 dma64_addr_t;
14020 + * XXX These are "Ubicom style" typedefs. They should be removed in all files used by linux.
14022 +typedef u32 u32_t;
14023 +typedef s32 s32_t;
14024 +typedef u16 u16_t;
14025 +typedef s16 s16_t;
14029 +#endif /* __ASSEMBLY__ */
14031 +#endif /* __KERNEL__ */
14033 +#endif /* _ASM_UBICOM32_TYPES_H */
14034 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/uaccess.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/uaccess.h
14035 --- linux-2.6.30.10/arch/ubicom32/include/asm/uaccess.h 1970-01-01 02:00:00.000000000 +0200
14036 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/uaccess.h 2009-12-11 11:45:11.000000000 +0200
14039 + * arch/ubicom32/include/asm/uaccess.h
14040 + * User space memory access functions for Ubicom32 architecture.
14042 + * (C) Copyright 2009, Ubicom, Inc.
14044 + * This file is part of the Ubicom32 Linux Kernel Port.
14046 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
14047 + * it and/or modify it under the terms of the GNU General Public License
14048 + * as published by the Free Software Foundation, either version 2 of the
14049 + * License, or (at your option) any later version.
14051 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
14052 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
14053 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
14054 + * the GNU General Public License for more details.
14056 + * You should have received a copy of the GNU General Public License
14057 + * along with the Ubicom32 Linux Kernel Port. If not,
14058 + * see <http://www.gnu.org/licenses/>.
14060 + * Ubicom32 implementation derived from (with many thanks):
14066 +#ifndef _ASM_UBICOM32_UACCESS_H
14067 +#define _ASM_UBICOM32_UACCESS_H
14070 + * User space memory access functions
14072 +#include <linux/sched.h>
14073 +#include <linux/mm.h>
14074 +#include <linux/string.h>
14076 +#include <asm/segment.h>
14078 +#define VERIFY_READ 0
14079 +#define VERIFY_WRITE 1
14082 + * The exception table consists of pairs of addresses: the first is the
14083 + * address of an instruction that is allowed to fault, and the second is
14084 + * the address at which the program should continue. No registers are
14085 + * modified, so it is entirely up to the continuation code to figure out
14088 + * All the routines below use bits of fixup code that are out of line
14089 + * with the main instruction path. This means when everything is well,
14090 + * we don't even have to jump over them. Further, they do not intrude
14091 + * on our cache or tlb entries.
14093 +struct exception_table_entry
14095 + unsigned long insn, fixup;
14099 + * Ubicom32 does not currently support the exception table handling.
14101 +extern unsigned long search_exception_table(unsigned long);
14104 +#if defined(CONFIG_ACCESS_OK_CHECKS_ENABLED)
14105 +extern int __access_ok(unsigned long addr, unsigned long size);
14107 +static inline int __access_ok(unsigned long addr, unsigned long size)
14112 +#define access_ok(type, addr, size) \
14113 + likely(__access_ok((unsigned long)(addr), (size)))
14116 + * The following functions do not exist. They keep callers
14117 + * of put_user and get_user from passing unsupported argument
14118 + * types. They result in a link time error.
14120 +extern int __put_user_bad(void);
14121 +extern int __get_user_bad(void);
14124 + * __put_user_no_check()
14125 + * Put the requested data into the user space verifying the address
14128 + * (a) re-use the arguments for side effects (sizeof/typeof is ok)
14129 + * (b) require any knowledge of processes at this stage
14131 +#define __put_user_no_check(x, ptr, size) \
14133 + int __pu_err = 0; \
14134 + __typeof__(*(ptr)) __user *__pu_addr = (ptr); \
14135 + switch (size) { \
14140 + *__pu_addr = (__typeof__(*(ptr)))x; \
14143 + __pu_err = __put_user_bad(); \
14150 + * __put_user_check()
14151 + * Put the requested data into the user space verifying the address
14154 + * (a) re-use the arguments for side effects (sizeof/typeof is ok)
14155 + * (b) require any knowledge of processes at this stage
14157 + * If requested, access_ok() will verify that ptr is a valid user
14160 +#define __put_user_check(x, ptr, size) \
14162 + int __pu_err = -EFAULT; \
14163 + __typeof__(*(ptr)) __user *__pu_addr = (ptr); \
14164 + if (access_ok(VERIFY_WRITE, __pu_addr, size)) { \
14166 + switch (size) { \
14171 + *__pu_addr = (__typeof__(*(ptr)))x; \
14174 + __pu_err = __put_user_bad(); \
14182 + * __get_user_no_check()
14183 + * Read the value at ptr into x.
14185 + * If requested, access_ok() will verify that ptr is a valid user
14186 + * pointer. If the caller passes a modifying argument for ptr (e.g. x++)
14187 + * this macro will not work.
14189 +#define __get_user_no_check(x, ptr, size) \
14191 + int __gu_err = 0; \
14192 + __typeof__((x)) __gu_val = 0; \
14193 + const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \
14194 + switch (size) { \
14199 + __gu_val = (__typeof__((x)))*(__gu_addr); \
14202 + __gu_err = __get_user_bad(); \
14206 + (x) = __gu_val; \
14211 + * __get_user_check()
14212 + * Read the value at ptr into x.
14214 + * If requested, access_ok() will verify that ptr is a valid user
14217 +#define __get_user_check(x, ptr, size) \
14219 + int __gu_err = -EFAULT; \
14220 + __typeof__(x) __gu_val = 0; \
14221 + const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \
14222 + if (access_ok(VERIFY_READ, __gu_addr, size)) { \
14224 + switch (size) { \
14229 + __gu_val = (__typeof__((x)))*(__gu_addr); \
14232 + __gu_err = __get_user_bad(); \
14237 + (x) = __gu_val; \
14242 + * The "xxx" versions are allowed to perform some amount of address
14243 + * space checking. See access_ok().
14245 +#define put_user(x,ptr) \
14246 + __put_user_check((__typeof__(*(ptr)))(x),(ptr), sizeof(*(ptr)))
14247 +#define get_user(x,ptr) \
14248 + __get_user_check((x), (ptr), sizeof(*(ptr)))
14251 + * The "__xxx" versions do not do address space checking, useful when
14252 + * doing multiple accesses to the same area (the programmer has to do the
14253 + * checks by hand with "access_ok()")
14255 +#define __put_user(x,ptr) \
14256 + __put_user_no_check((__typeof__(*(ptr)))(x),(ptr), sizeof(*(ptr)))
14257 +#define __get_user(x,ptr) \
14258 + __get_user_no_check((x), (ptr), sizeof(*(ptr)))
14261 + * __copy_tofrom_user_no_check()
14262 + * Copy the data either to or from user space.
14264 + * Return the number of bytes NOT copied.
14266 +static inline unsigned long
14267 +__copy_tofrom_user_no_check(void *to, const void *from, unsigned long n)
14269 + memcpy(to, from, n);
14275 + * Copy the kernel data to user space.
14277 + * Return the number of bytes that were copied.
14279 +static inline unsigned long
14280 +copy_to_user(void __user *to, const void *from, unsigned long n)
14282 + if (!access_ok(VERIFY_WRITE, to, n)) {
14285 + return __copy_tofrom_user_no_check((__force void *)to, from, n);
14289 + * copy_from_user()
14290 + * Copy the user data to kernel space.
14292 + * Return the number of bytes that were copied. On error, we zero
14293 + * out the destination.
14295 +static inline unsigned long
14296 +copy_from_user(void *to, const void __user *from, unsigned long n)
14298 + if (!access_ok(VERIFY_READ, from, n)) {
14301 + return __copy_tofrom_user_no_check(to, (__force void *)from, n);
14304 +#define __copy_to_user(to, from, n) \
14305 + __copy_tofrom_user_no_check((__force void *)to, from, n)
14306 +#define __copy_from_user(to, from, n) \
14307 + __copy_tofrom_user_no_check(to, (__force void *)from, n)
14308 +#define __copy_to_user_inatomic(to, from, n) \
14309 + __copy_tofrom_user_no_check((__force void *)to, from, n)
14310 +#define __copy_from_user_inatomic(to, from, n) \
14311 + __copy_tofrom_user_no_check(to, (__force void *)from, n)
14313 +#define copy_to_user_ret(to, from, n, retval) \
14314 + ({ if (copy_to_user(to, from, n)) return retval; })
14316 +#define copy_from_user_ret(to, from, n, retval) \
14317 + ({ if (copy_from_user(to, from, n)) return retval; })
14320 + * strncpy_from_user()
14321 + * Copy a null terminated string from userspace.
14323 + * dst - Destination in kernel space. The buffer must be at least count.
14324 + * src - Address of string in user space.
14325 + * count - Maximum number of bytes to copy (including the trailing NULL).
14327 + * Returns the length of the string (not including the trailing NULL. If
14328 + * count is smaller than the length of the string, we copy count bytes
14329 + * and return count.
14332 +static inline long strncpy_from_user(char *dst, const __user char *src, long count)
14335 + if (!access_ok(VERIFY_READ, src, 1)) {
14339 + strncpy(dst, src, count);
14340 + for (tmp = dst; *tmp && count > 0; tmp++, count--) {
14343 + return(tmp - dst);
14348 + * Return the size of a string (including the ending 0)
14350 + * Return -EFAULT on exception, a value greater than <n> if too long
14352 +static inline long strnlen_user(const __user char *src, long n)
14354 + if (!access_ok(VERIFY_READ, src, 1)) {
14357 + return(strlen(src) + 1);
14360 +#define strlen_user(str) strnlen_user(str, 32767)
14366 +static inline unsigned long __clear_user(__user void *to, unsigned long n)
14368 + memset(to, 0, n);
14374 + * Zero user space (check for valid addresses)
14376 +static inline unsigned long clear_user(__user void *to, unsigned long n)
14378 + if (!access_ok(VERIFY_WRITE, to, n)) {
14381 + return __clear_user(to, n);
14384 +#endif /* _ASM_UBICOM32_UACCESS_H */
14385 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/uart_tio.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/uart_tio.h
14386 --- linux-2.6.30.10/arch/ubicom32/include/asm/uart_tio.h 1970-01-01 02:00:00.000000000 +0200
14387 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/uart_tio.h 2009-12-11 11:45:11.000000000 +0200
14390 + * arch/ubicom32/include/asm/uart_tio.h
14391 + * Ubicom32 architecture UART TIO definitions.
14393 + * (C) Copyright 2009, Ubicom, Inc.
14395 + * This file is part of the Ubicom32 Linux Kernel Port.
14397 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
14398 + * it and/or modify it under the terms of the GNU General Public License
14399 + * as published by the Free Software Foundation, either version 2 of the
14400 + * License, or (at your option) any later version.
14402 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
14403 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
14404 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
14405 + * the GNU General Public License for more details.
14407 + * You should have received a copy of the GNU General Public License
14408 + * along with the Ubicom32 Linux Kernel Port. If not,
14409 + * see <http://www.gnu.org/licenses/>.
14411 +#ifndef _ASM_UBICOM32_UART_TIO_H
14412 +#define _ASM_UBICOM32_UART_TIO_H
14414 +#include <asm/devtree.h>
14416 +#define UARTTIO_RX_FIFO_SIZE 16
14417 +#define UARTTIO_TX_FIFO_SIZE 16
14420 + * Interrupt flags
14422 +#define UARTTIO_UART_INT_RX 0x00000001 // set when a character has been recevied (TODO: add watermark)
14423 +#define UARTTIO_UART_INT_RXOVF 0x00000002 // set when the receive buffer has overflowed
14424 +#define UARTTIO_UART_INT_RXFRAME 0x00000004 // set when there has been a framing error
14426 +#define UARTTIO_UART_INT_TX 0x00000100 // set every time a character is transmitted
14427 +#define UARTTIO_UART_INT_TXBE 0x00000200 // set when the transmit buffer is empty (TODO: add watermark)
14429 +#define UARTTIO_UART_FLAG_ENABLED 0x80000000
14430 +#define UARTTIO_UART_FLAG_SET_RATE 0x00000001 // set to update baud rate
14431 +#define UARTTIO_UART_FLAG_RESET 0x00000002 // set to reset the port
14432 +struct uarttio_uart {
14433 + volatile u32_t flags;
14435 + volatile u32_t baud_rate;
14436 + volatile u32_t current_baud_rate;
14440 + * Modem status register
14442 + volatile u32_t status;
14445 + * Interrupt registers
14447 + volatile u32_t int_mask;
14448 + volatile u32_t int_flags;
14460 + * Configuration Data
14463 + u8_t rx_stop_bits;
14465 + u8_t tx_stop_bits;
14468 + * RX state machine data
14471 + u32_t rx_bit_pos;
14473 + u32_t rx_fifo_head;
14474 + u32_t rx_fifo_tail;
14475 + u32_t rx_fifo_size;
14478 + * TX state machine data
14481 + u32_t tx_bit_pos;
14483 + u32_t tx_fifo_head;
14484 + u32_t tx_fifo_tail;
14485 + u32_t tx_fifo_size;
14490 + u8_t rx_fifo[UARTTIO_RX_FIFO_SIZE];
14491 + u8_t tx_fifo[UARTTIO_TX_FIFO_SIZE];
14494 +#define UARTTIO_VP_VERSION 1
14495 +struct uarttio_regs {
14502 + struct uarttio_uart uarts[0];
14505 +#define UARTTIO_NODE_VERSION 1
14506 +struct uarttio_node {
14507 + struct devtree_node dn;
14510 + struct uarttio_regs *regs;
14514 +#endif /* _ASM_UBICOM32_UART_TIO_H */
14515 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ubi32-cs4384.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubi32-cs4384.h
14516 --- linux-2.6.30.10/arch/ubicom32/include/asm/ubi32-cs4384.h 1970-01-01 02:00:00.000000000 +0200
14517 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubi32-cs4384.h 2009-12-11 11:45:11.000000000 +0200
14520 + * arch/ubicom32/include/asm/ubi32-cs4384.h
14521 + * Ubicom32 architecture CS4384 driver platform data definitions.
14523 + * (C) Copyright 2009, Ubicom, Inc.
14525 + * This file is part of the Ubicom32 Linux Kernel Port.
14527 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
14528 + * it and/or modify it under the terms of the GNU General Public License
14529 + * as published by the Free Software Foundation, either version 2 of the
14530 + * License, or (at your option) any later version.
14532 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
14533 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
14534 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
14535 + * the GNU General Public License for more details.
14537 + * You should have received a copy of the GNU General Public License
14538 + * along with the Ubicom32 Linux Kernel Port. If not,
14539 + * see <http://www.gnu.org/licenses/>.
14541 +#ifndef _ASM_UBICOM32_UBI32_CS4384_H
14542 +#define _ASM_UBICOM32_UBI32_CS4384_H
14544 +enum ubi32_cs4384_mclk_source {
14545 + UBI32_CS4384_MCLK_PWM_0,
14546 + UBI32_CS4384_MCLK_PWM_1,
14547 + UBI32_CS4384_MCLK_PWM_2,
14548 + UBI32_CS4384_MCLK_CLKDIV_1,
14549 + UBI32_CS4384_MCLK_OTHER,
14552 +struct ubi32_cs4384_mclk_entry {
14554 + * Rate, in Hz, of this entry
14559 + * The divider to program to get the rate
14564 +struct ubi32_cs4384_platform_data {
14565 + enum ubi32_cs4384_mclk_source mclk_src;
14568 + struct ubi32_cs4384_mclk_entry *mclk_entries;
14570 +#endif /* _ASM_UBICOM32_UBI32_CS4384_H */
14571 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ubi32-pcm.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubi32-pcm.h
14572 --- linux-2.6.30.10/arch/ubicom32/include/asm/ubi32-pcm.h 1970-01-01 02:00:00.000000000 +0200
14573 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubi32-pcm.h 2009-12-11 11:45:11.000000000 +0200
14576 + * arch/ubicom32/include/asm/ubi32-pcm.h
14577 + * Ubicom32 architecture PCM driver platform data definitions.
14579 + * (C) Copyright 2009, Ubicom, Inc.
14581 + * This file is part of the Ubicom32 Linux Kernel Port.
14583 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
14584 + * it and/or modify it under the terms of the GNU General Public License
14585 + * as published by the Free Software Foundation, either version 2 of the
14586 + * License, or (at your option) any later version.
14588 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
14589 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
14590 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
14591 + * the GNU General Public License for more details.
14593 + * You should have received a copy of the GNU General Public License
14594 + * along with the Ubicom32 Linux Kernel Port. If not,
14595 + * see <http://www.gnu.org/licenses/>.
14597 +#ifndef _ASM_UBICOM32_UBI32_PCM_H
14598 +#define _ASM_UBICOM32_UBI32_PCM_H
14601 + * This function is called when the sample rate has changed
14603 +typedef int (*ubi32_pcm_set_rate_fn_t)(void *appdata, int rate);
14605 +struct ubi32pcm_platform_data {
14607 + * Name of the audio node/inst
14609 + const char *node_name;
14610 + const char *inst_name;
14614 + * Application specific data provided when calling functions
14619 + * Functions called when various things happen
14621 + ubi32_pcm_set_rate_fn_t set_rate;
14624 + * Pointer to optional upper layer data (i.e. DAC config, etc)
14628 +#endif /* _ASM_UBICOM32_UBI32_PCM_H */
14629 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32bl.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32bl.h
14630 --- linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32bl.h 1970-01-01 02:00:00.000000000 +0200
14631 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32bl.h 2009-12-11 11:45:11.000000000 +0200
14634 + * arch/ubicom32/include/asm/ubicom32bl.h
14635 + * Ubicom32 architecture backlight driver platform data definitions.
14637 + * (C) Copyright 2009, Ubicom, Inc.
14639 + * This file is part of the Ubicom32 Linux Kernel Port.
14641 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
14642 + * it and/or modify it under the terms of the GNU General Public License
14643 + * as published by the Free Software Foundation, either version 2 of the
14644 + * License, or (at your option) any later version.
14646 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
14647 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
14648 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
14649 + * the GNU General Public License for more details.
14651 + * You should have received a copy of the GNU General Public License
14652 + * along with the Ubicom32 Linux Kernel Port. If not,
14653 + * see <http://www.gnu.org/licenses/>.
14655 + * Ubicom32 implementation derived from (with many thanks):
14660 +#ifndef _ASM_UBICOM32_UBICOM32_BL_H
14661 +#define _ASM_UBICOM32_UBICOM32_BL_H
14664 + * Different backlight control mechanisms
14666 +enum ubicom32bl_pwm_types {
14668 + * PWM controlled backlight
14670 + UBICOM32BL_TYPE_PWM,
14673 + * HRT based PWM backlight
14675 + UBICOM32BL_TYPE_PWM_HRT,
14678 + * No dimming, just on or off
14680 + UBICOM32BL_TYPE_BINARY,
14683 +struct ubicom32bl_platform_data {
14685 + * Default intensity of the backlight 0-255
14687 + u8_t default_intensity;
14690 + * TRUE if the backlight sense is active low. (inverted)
14691 + * FALSE if the backlight sense is active high.
14696 + * Type of the backlight
14698 + enum ubicom32bl_pwm_types type;
14701 + * GPIO of the backlight if UBICOM32BL_TYPE_PWM_HRT, UBICOM32BL_TYPE_BINARY
14706 + * PWM channel and parameters of the backlight if UBICOM32BL_TYPE_PWM
14707 + * pre_scaler: sets the rate at which the PWM timer is clocked. (clk_core / 2^pre_scaler)
14708 + * period: sets the period of the timer in timer cycles
14709 + * The duty cycle will be directly proportional to the brightness setting.
14711 + u32_t pwm_channel;
14712 + u8_t pwm_prescale;
14713 + u16_t pwm_period;
14716 +#endif /* _ASM_UBICOM32_UBICOM32_BL_H */
14717 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32-common-asm.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32-common-asm.h
14718 --- linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32-common-asm.h 1970-01-01 02:00:00.000000000 +0200
14719 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32-common-asm.h 2009-12-11 11:45:11.000000000 +0200
14722 + * arch/ubicom32/include/asm/ubicom32-common-asm.h
14723 + * Ubicom32 atomic lock operations.
14725 + * (C) Copyright 2009, Ubicom, Inc.
14727 + * This file is part of the Ubicom32 Linux Kernel Port.
14729 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
14730 + * it and/or modify it under the terms of the GNU General Public License
14731 + * as published by the Free Software Foundation, either version 2 of the
14732 + * License, or (at your option) any later version.
14734 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
14735 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
14736 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
14737 + * the GNU General Public License for more details.
14739 + * You should have received a copy of the GNU General Public License
14740 + * along with the Ubicom32 Linux Kernel Port. If not,
14741 + * see <http://www.gnu.org/licenses/>.
14743 + * Ubicom32 implementation derived from (with many thanks):
14749 +#ifndef _ASM_UBICOM32_UBICOM32_COMMON_ASM_H
14750 +#define _ASM_UBICOM32_UBICOM32_COMMON_ASM_H
14753 + * atomic_lock_acquire macro
14754 + * Equivalent to __atomic_lock_acquire()
14756 +.macro atomic_lock_acquire
14757 + bset scratchpad1, scratchpad1, #ATOMIC_LOCK_BIT
14762 + * atomic_lock_release macro
14763 + * Equivalent to __atomic_lock_release()
14765 +.macro atomic_lock_release
14766 + bclr scratchpad1, scratchpad1, #ATOMIC_LOCK_BIT
14769 +#endif /* _ASM_UBICOM32_UBICOM32_COMMON_ASM_H */
14770 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32-common.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32-common.h
14771 --- linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32-common.h 1970-01-01 02:00:00.000000000 +0200
14772 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32-common.h 2009-12-11 11:45:11.000000000 +0200
14775 + * arch/ubicom32/include/asm/ubicom32-common.h
14776 + * Ubicom32 atomic lock operations.
14778 + * (C) Copyright 2009, Ubicom, Inc.
14780 + * This file is part of the Ubicom32 Linux Kernel Port.
14782 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
14783 + * it and/or modify it under the terms of the GNU General Public License
14784 + * as published by the Free Software Foundation, either version 2 of the
14785 + * License, or (at your option) any later version.
14787 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
14788 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
14789 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
14790 + * the GNU General Public License for more details.
14792 + * You should have received a copy of the GNU General Public License
14793 + * along with the Ubicom32 Linux Kernel Port. If not,
14794 + * see <http://www.gnu.org/licenses/>.
14796 + * Ubicom32 implementation derived from (with many thanks):
14802 +#ifndef _ASM_UBICOM32_UBICOM32_COMMON_H
14803 +#define _ASM_UBICOM32_UBICOM32_COMMON_H
14805 +#define S(arg) #arg
14806 +#define D(arg) S(arg)
14808 + * scratchpad1 is owned by the LDSR.
14810 + * The upper bits provide 16 global spinlocks. Acquiring one of these
14811 + * global spinlocks synchornizes across multiple threads and prevents
14812 + * the LDSR from delivering any interrupts while the lock is held.
14813 + * Use these locks only when absolutely required.
14815 + * The lower 16 bits of scratchpad1 are used as per thread interrupt
14816 + * enable/disable bits. These bits will prevent a thread from receiving
14817 + * any interrupts.
14820 + * - MT_EN_LOCK_BIT - Protects writes to MT_EN, so code can read current value
14821 + * then write a new value atomically (profiler for example)
14822 + * - ATOMIC_LOCK_BIT - Used to provide general purpose atomic handling.
14823 + * - LDSR_LOCK_BIT - Used by the LDSR exclusively to provide protection.
14824 + * - DCCR_LOCK_BIT - Used to limit access to the DCCR cache control peripheral
14825 + * - ICCR_LOCK_BIT - Used to limit access to the ICCR cache control peripheral
14826 + * - LSB 16 bits - Used by the LDSR to represent thread enable/disable bits.
14828 +#define MT_EN_LOCK_BIT 31
14829 +#define ATOMIC_LOCK_BIT 30
14830 +#define LDSR_LOCK_BIT 29
14831 +#define PCI_LOCK_BIT 28
14832 +#define ICCR_LOCK_BIT 27
14833 +#define DCCR_LOCK_BIT 26
14835 +#if !defined(__ASSEMBLY__)
14837 +#define UBICOM32_TRYLOCK(bit) \
14839 + " move.4 %0, #0 \n\t" \
14840 + " bset scratchpad1, scratchpad1, #"D(bit)" \n\t" \
14841 + " jmpne.f 1f \n\t" \
14842 + " move.4 %0, #1 \n\t" \
14846 + : "cc", "memory" \
14849 +#define UBICOM32_UNLOCK(bit) \
14851 + " bclr scratchpad1, scratchpad1, #"D(bit)" \n\t" \
14854 + : "cc", "memory" \
14857 +#define UBICOM32_LOCK(bit) \
14859 + "1: bset scratchpad1, scratchpad1, #"D(bit)" \n\t" \
14860 + " jmpne.f 1b \n\t" \
14863 + : "cc", "memory" \
14867 + * __atomic_lock_trylock()
14868 + * Attempt to acquire the lock, return TRUE if acquired.
14870 +static inline int __atomic_lock_trylock(void)
14873 + UBICOM32_TRYLOCK(ATOMIC_LOCK_BIT);
14878 + * __atomic_lock_release()
14879 + * Release the global atomic lock.
14881 + * Note: no one is suspended waiting since this lock is a spinning lock.
14883 +static inline void __atomic_lock_release(void)
14885 + UBICOM32_UNLOCK(ATOMIC_LOCK_BIT);
14889 + * __atomic_lock_acquire()
14890 + * Acquire the global atomic lock, spin if not available.
14892 +static inline void __atomic_lock_acquire(void)
14894 + UBICOM32_LOCK(ATOMIC_LOCK_BIT);
14896 +#else /* __ASSEMBLY__ */
14898 +#include <asm/ubicom32-common-asm.h>
14900 +#endif /* __ASSEMBLY__ */
14901 +#endif /* _ASM_UBICOM32_UBICOM32_COMMON_H */
14902 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32fb.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32fb.h
14903 --- linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32fb.h 1970-01-01 02:00:00.000000000 +0200
14904 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32fb.h 2009-12-11 11:45:11.000000000 +0200
14907 + * arch/ubicom32/include/asm/ubicom32fb.h
14908 + * Ubicom32 architecture video frame buffer definitions.
14910 + * (C) Copyright 2009, Ubicom, Inc.
14912 + * This file is part of the Ubicom32 Linux Kernel Port.
14914 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
14915 + * it and/or modify it under the terms of the GNU General Public License
14916 + * as published by the Free Software Foundation, either version 2 of the
14917 + * License, or (at your option) any later version.
14919 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
14920 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
14921 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
14922 + * the GNU General Public License for more details.
14924 + * You should have received a copy of the GNU General Public License
14925 + * along with the Ubicom32 Linux Kernel Port. If not,
14926 + * see <http://www.gnu.org/licenses/>.
14928 +#ifndef _ASM_UBICOM32_UBICOM32FB_H
14929 +#define _ASM_UBICOM32_UBICOM32FB_H
14931 +#include <linux/ioctl.h>
14936 +#define UBICOM32FB_IOCTL_SET_NEXT_FRAME _IOW('r', 1, void *)
14937 +#define UBICOM32FB_IOCTL_SET_NEXT_FRAME_SYNC _IOW('r', 2, void *)
14942 +#define UBICOM32FB_IOCTL_SET_MODE _IOW('r', 3, void *)
14943 +struct ubicom32fb_mode {
14944 + unsigned long width;
14945 + unsigned long height;
14946 + unsigned long flags;
14947 + void *next_frame;
14949 +#define UBICOM32FB_IOCTL_SET_MODE_FLAG_YUV_SCAN_ORDER (1 << 8)
14951 +#define UBICOM32FB_IOCTL_SET_MODE_FLAG_YUV_BLOCK_ORDER (1 << 7)
14952 +#define UBICOM32FB_IOCTL_SET_MODE_FLAG_YUV (1 << 6)
14953 +#define UBICOM32FB_IOCTL_SET_MODE_FLAG_VSUB (1 << 5)
14954 +#define UBICOM32FB_IOCTL_SET_MODE_FLAG_VRANGE_16_255 (1 << 4)
14956 +#define UBICOM32FB_IOCTL_SET_MODE_FLAG_VRANGE_0_255 (1 << 3)
14957 +#define UBICOM32FB_IOCTL_SET_MODE_FLAG_HSUB_2_1 (1 << 2)
14958 +#define UBICOM32FB_IOCTL_SET_MODE_FLAG_HSUB_1_1 (1 << 1)
14959 +#define UBICOM32FB_IOCTL_SET_MODE_FLAG_SCALE_ENABLE (1 << 0)
14961 +#endif /* _ASM_UBICOM32_UBICOM32FB_H */
14962 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32hid.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32hid.h
14963 --- linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32hid.h 1970-01-01 02:00:00.000000000 +0200
14964 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32hid.h 2009-12-11 11:45:11.000000000 +0200
14967 + * arch/ubicom32/include/asm/ubicom32hid.h
14968 + * Ubicom32 architecture HID driver platform data definitions.
14970 + * (C) Copyright 2009, Ubicom, Inc.
14972 + * This file is part of the Ubicom32 Linux Kernel Port.
14974 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
14975 + * it and/or modify it under the terms of the GNU General Public License
14976 + * as published by the Free Software Foundation, either version 2 of the
14977 + * License, or (at your option) any later version.
14979 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
14980 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
14981 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
14982 + * the GNU General Public License for more details.
14984 + * You should have received a copy of the GNU General Public License
14985 + * along with the Ubicom32 Linux Kernel Port. If not,
14986 + * see <http://www.gnu.org/licenses/>.
14988 + * Ubicom32 implementation derived from (with many thanks):
14993 +#ifndef _ASM_UBICOM32_UBICOM32_HID_H
14994 +#define _ASM_UBICOM32_UBICOM32_HID_H
14996 +enum ubicom32hid_bl_types {
14998 + * On or off, using command SET_BL_EN, PB4
15000 + UBICOM32HID_BL_TYPE_BINARY,
15003 + * Dimmable, using command SET_PWM, PB3
15005 + UBICOM32HID_BL_TYPE_PWM,
15009 + * IR code mapping to event code.
15010 + * If there are no button mappings and no ir mappings
15011 + * then no input driver will be registered.
15013 +struct ubicom32hid_ir {
15015 + * Input event code (KEY_*, SW_*, etc)
15020 + * Input event type (EV_KEY, EV_SW, etc)
15025 + * The IR code of this button.
15027 + uint32_t ir_code;
15031 + * Button mapping to event code.
15032 + * If there are no button mappings and no ir mappings
15033 + * then no input driver will be registered.
15035 +struct ubicom32hid_button {
15037 + * Input event code (KEY_*, SW_*, etc)
15042 + * Input event type (EV_KEY, EV_SW, etc)
15047 + * Bit number of this button.
15052 +struct ubicom32hid_platform_data {
15054 + * Default intensity of the backlight 0-255
15056 + u8_t default_intensity;
15059 + * GPIO number of the reset line and its polarity.
15061 + unsigned gpio_reset;
15062 + int gpio_reset_polarity;
15065 + * TRUE if the backlight sense is active low. (inverted)
15066 + * FALSE if the backlight sense is active high.
15071 + * Type of the backlight we are controlling
15073 + enum ubicom32hid_bl_types type;
15076 + * Optional polling rate for input, in ms, defaults to 100ms
15078 + int poll_interval;
15081 + * Optional name to register as input device
15083 + const char *input_name;
15086 + * Button mapping array
15088 + const struct ubicom32hid_button *buttons;
15092 + * IR mapping array
15094 + const struct ubicom32hid_ir *ircodes;
15098 +#endif /* _ASM_UBICOM32_UBICOM32_HID_H */
15099 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32input.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32input.h
15100 --- linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32input.h 1970-01-01 02:00:00.000000000 +0200
15101 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32input.h 2009-12-11 11:45:11.000000000 +0200
15104 + * arch/ubicom32/include/asm/ubicom32input.h
15105 + * Ubicom32 Input driver, based on gpio-keys
15107 + * (C) Copyright 2009, Ubicom, Inc.
15109 + * This file is part of the Ubicom32 Linux Kernel Port.
15111 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
15112 + * it and/or modify it under the terms of the GNU General Public License
15113 + * as published by the Free Software Foundation, either version 2 of the
15114 + * License, or (at your option) any later version.
15116 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15117 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
15118 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15119 + * the GNU General Public License for more details.
15121 + * You should have received a copy of the GNU General Public License
15122 + * along with the Ubicom32 Linux Kernel Port. If not,
15123 + * see <http://www.gnu.org/licenses/>.
15125 + * Ubicom32 implementation derived from (with many thanks):
15130 + * TODO: add groups for inputs which can be sampled together
15133 +#ifndef _ASM_UBICOM32_UBICOM32_INPUT_H
15134 +#define _ASM_UBICOM32_UBICOM32_INPUT_H
15136 +struct ubicom32input_button {
15138 + * Input event code (KEY_*, SW_*, etc)
15143 + * Input event type (EV_KEY, EV_SW, etc)
15153 + * 1 for active low, 0 for active high
15158 + * Description, used for reserving GPIOs
15160 + const char *desc;
15163 +struct ubicom32input_platform_data {
15164 + struct ubicom32input_button *buttons;
15168 + * Optional poll interval, in ms, defaults to 50ms
15170 + int poll_interval;
15173 + * Option Name of this driver
15175 + const char *name;
15178 +#endif /* _ASM_UBICOM32_UBICOM32_INPUT_H */
15179 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32input_i2c.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32input_i2c.h
15180 --- linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32input_i2c.h 1970-01-01 02:00:00.000000000 +0200
15181 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32input_i2c.h 2009-12-11 11:45:11.000000000 +0200
15184 + * arch/ubicom32/include/asm/ubicom32input_i2c.h
15185 + * Ubicom32 architecture Input driver over I2C platform data definitions.
15187 + * (C) Copyright 2009, Ubicom, Inc.
15189 + * This file is part of the Ubicom32 Linux Kernel Port.
15191 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
15192 + * it and/or modify it under the terms of the GNU General Public License
15193 + * as published by the Free Software Foundation, either version 2 of the
15194 + * License, or (at your option) any later version.
15196 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15197 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
15198 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15199 + * the GNU General Public License for more details.
15201 + * You should have received a copy of the GNU General Public License
15202 + * along with the Ubicom32 Linux Kernel Port. If not,
15203 + * see <http://www.gnu.org/licenses/>.
15205 + * Ubicom32 implementation derived from (with many thanks):
15210 + * TODO: add groups for inputs which can be sampled together
15213 +#ifndef _ASM_UBICOM32_UBICOM32_INPUT_I2C_H
15214 +#define _ASM_UBICOM32_UBICOM32_INPUT_I2C_H
15216 +struct ubicom32input_i2c_button {
15218 + * Input event code (KEY_*, SW_*, etc)
15223 + * Input event type (EV_KEY, EV_SW, etc)
15228 + * Bit number of this button. (0 - ngpio)
15233 + * 1 for active low, 0 for active high
15238 +struct ubicom32input_i2c_platform_data {
15239 + struct ubicom32input_i2c_button *buttons;
15243 + * Optional poll interval, in ms, defaults to 100ms
15245 + int poll_interval;
15248 + * Option Name of this driver
15250 + const char *name;
15253 +#endif /* _ASM_UBICOM32_UBICOM32_INPUT_I2C_H */
15254 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32lcd.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32lcd.h
15255 --- linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32lcd.h 1970-01-01 02:00:00.000000000 +0200
15256 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32lcd.h 2009-12-11 11:45:11.000000000 +0200
15259 + * arch/ubicom32/include/asm/ubicom32lcd.h
15260 + * Ubicom32 architecture LCD driver platform data definitions.
15262 + * (C) Copyright 2009, Ubicom, Inc.
15264 + * This file is part of the Ubicom32 Linux Kernel Port.
15266 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
15267 + * it and/or modify it under the terms of the GNU General Public License
15268 + * as published by the Free Software Foundation, either version 2 of the
15269 + * License, or (at your option) any later version.
15271 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15272 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
15273 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15274 + * the GNU General Public License for more details.
15276 + * You should have received a copy of the GNU General Public License
15277 + * along with the Ubicom32 Linux Kernel Port. If not,
15278 + * see <http://www.gnu.org/licenses/>.
15280 +#ifndef _ASM_UBICOM32_UBICOM32_LCD_H
15281 +#define _ASM_UBICOM32_UBICOM32_LCD_H
15283 +#include <asm/ip5000.h>
15285 +struct ubicom32lcd_platform_data {
15292 + struct ubicom32_io_port *port_data;
15295 +#endif /* _ASM_UBICOM32_UBICOM32_LCD_H */
15296 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32lcdpower.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32lcdpower.h
15297 --- linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32lcdpower.h 1970-01-01 02:00:00.000000000 +0200
15298 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32lcdpower.h 2009-12-11 11:45:11.000000000 +0200
15301 + * arch/ubicom32/include/asm/ubicom32lcdpower.h
15302 + * Ubicom32 architecture LCD driver platform data definitions.
15304 + * (C) Copyright 2009, Ubicom, Inc.
15306 + * This file is part of the Ubicom32 Linux Kernel Port.
15308 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
15309 + * it and/or modify it under the terms of the GNU General Public License
15310 + * as published by the Free Software Foundation, either version 2 of the
15311 + * License, or (at your option) any later version.
15313 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15314 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
15315 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15316 + * the GNU General Public License for more details.
15318 + * You should have received a copy of the GNU General Public License
15319 + * along with the Ubicom32 Linux Kernel Port. If not,
15320 + * see <http://www.gnu.org/licenses/>.
15322 + * Ubicom32 implementation derived from (with many thanks):
15327 +#ifndef _ASM_UBICOM32_UBICOM32_LCDPOWER_H
15328 +#define _ASM_UBICOM32_UBICOM32_LCDPOWER_H
15330 +struct ubicom32lcdpower_platform_data {
15332 + * GPIO and polarity for VGH signal. A FALSE polarity is active low, TRUE is active high.
15335 + bool vgh_polarity;
15338 +#endif /* _ASM_UBICOM32_UBICOM32_LCDPOWER_H */
15339 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32ring.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32ring.h
15340 --- linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32ring.h 1970-01-01 02:00:00.000000000 +0200
15341 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32ring.h 2009-12-11 11:45:11.000000000 +0200
15344 + * arch/ubicom32/include/asm/ubicom32ring.h
15345 + * Userspace I/O platform driver for Ubicom32 ring buffers
15347 + * (C) Copyright 2009, Ubicom, Inc.
15349 + * This file is part of the Ubicom32 Linux Kernel Port.
15351 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
15352 + * it and/or modify it under the terms of the GNU General Public License
15353 + * as published by the Free Software Foundation, either version 2 of the
15354 + * License, or (at your option) any later version.
15356 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15357 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
15358 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15359 + * the GNU General Public License for more details.
15361 + * You should have received a copy of the GNU General Public License
15362 + * along with the Ubicom32 Linux Kernel Port. If not,
15363 + * see <http://www.gnu.org/licenses/>.
15366 +#ifndef _ASM_UBICOM32_UBICOM32RING_H
15367 +#define _ASM_UBICOM32_UBICOM32RING_H
15369 +#define UIO_UBICOM32RING_REG_VERSION 2
15371 +struct uio_ubicom32ring_desc {
15372 + volatile unsigned int head;
15373 + volatile unsigned int tail;
15374 + unsigned int entries;
15375 + volatile unsigned int ring[0];
15378 +struct uio_ubicom32ring_regs {
15379 + unsigned int version;
15382 + * Magic type used to identify the ring set. Each driver will
15383 + * have a different magic value.
15385 + unsigned int magic;
15388 + * Registers defined by the driver
15390 + unsigned int regs_size;
15394 + * The locations of the rings
15396 + * DO NOT ADD ANYTHING BELOW THIS LINE
15398 + unsigned int num_rings;
15399 + struct uio_ubicom32ring_desc *rings[0];
15403 + * ringtio_ring_flush
15405 +static inline void ringtio_ring_flush(struct uio_ubicom32ring_desc *rd)
15407 + rd->head = rd->tail = 0;
15411 + * ringtio_ring_get
15413 +static inline int ringtio_ring_get(struct uio_ubicom32ring_desc *rd, void **val)
15415 + if (rd->head == rd->tail) {
15419 + *val = (void *)rd->ring[rd->head++];
15420 + if (rd->head == rd->entries) {
15427 + * ringtio_ring_put
15429 +static inline int ringtio_ring_put(struct uio_ubicom32ring_desc *rd, void *val)
15431 + unsigned int newtail = rd->tail + 1;
15432 + if (newtail == rd->entries) {
15436 + if (newtail == rd->head) {
15440 + rd->ring[rd->tail] = (unsigned int)val;
15441 + rd->tail = newtail;
15445 +#endif /* _ASM_UBICOM32_UBICOM32RING_H */
15446 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32sd.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32sd.h
15447 --- linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32sd.h 1970-01-01 02:00:00.000000000 +0200
15448 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32sd.h 2009-12-11 11:45:11.000000000 +0200
15451 + * arch/ubicom32/include/asm/ubicom32sd.h
15452 + * Ubicom32SD public include file
15454 + * (C) Copyright 2009, Ubicom, Inc.
15456 + * This file is part of the Ubicom32 Linux Kernel Port.
15458 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
15459 + * it and/or modify it under the terms of the GNU General Public License
15460 + * as published by the Free Software Foundation, either version 2 of the
15461 + * License, or (at your option) any later version.
15463 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15464 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
15465 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15466 + * the GNU General Public License for more details.
15468 + * You should have received a copy of the GNU General Public License
15469 + * along with the Ubicom32 Linux Kernel Port. If not,
15470 + * see <http://www.gnu.org/licenses/>.
15472 +#ifndef _ASM_UBICOM32_UBICOM32_SD_H
15473 +#define _ASM_UBICOM32_UBICOM32_SD_H
15475 +struct ubicom32sd_card {
15477 + * GPIOs of PWR, WP and CD lines.
15478 + * Polarity is 1 for active high and 0 for active low
15481 + bool pwr_polarity;
15483 + bool wp_polarity;
15485 + bool cd_polarity;
15488 +struct ubicom32sd_platform_data {
15491 + struct ubicom32sd_card *cards;
15494 +#endif /* _ASM_UBICOM32_UBICOM32_SD_H */
15495 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32-spi-gpio.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32-spi-gpio.h
15496 --- linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32-spi-gpio.h 1970-01-01 02:00:00.000000000 +0200
15497 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32-spi-gpio.h 2009-12-11 11:45:11.000000000 +0200
15500 + * arch/ubicom32/include/asm/ubicom32-spi-gpio.h
15501 + * Platform driver data definitions for GPIO based SPI driver.
15503 + * (C) Copyright 2009, Ubicom, Inc.
15505 + * This file is part of the Ubicom32 Linux Kernel Port.
15507 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
15508 + * it and/or modify it under the terms of the GNU General Public License
15509 + * as published by the Free Software Foundation, either version 2 of the
15510 + * License, or (at your option) any later version.
15512 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15513 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
15514 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15515 + * the GNU General Public License for more details.
15517 + * You should have received a copy of the GNU General Public License
15518 + * along with the Ubicom32 Linux Kernel Port. If not,
15519 + * see <http://www.gnu.org/licenses/>.
15521 + * Ubicom32 implementation derived from (with many thanks):
15526 +#ifndef _ASM_UBICOM32_UBICOM32_SPI_GPIO_H
15527 +#define _ASM_UBICOM32_UBICOM32_SPI_GPIO_H
15529 +struct ubicom32_spi_gpio_platform_data {
15531 + * GPIO to use for MOSI, MISO, CLK
15538 + * Default state of CLK line
15543 + * Number of chip selects on this bus
15545 + int num_chipselect;
15548 + * The bus number of this chip
15553 +struct ubicom32_spi_gpio_controller_data {
15555 + * GPIO to use for chip select
15560 +#endif /* _ASM_UBICOM32_UBICOM32_SPI_GPIO_H */
15561 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32suart.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32suart.h
15562 --- linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32suart.h 1970-01-01 02:00:00.000000000 +0200
15563 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32suart.h 2009-12-11 11:45:11.000000000 +0200
15566 + * arch/ubicom32/include/asm/ubicom32suart.h
15567 + * <TODO: Replace with short file description>
15569 + * (C) Copyright 2009, Ubicom, Inc.
15571 + * This file is part of the Ubicom32 Linux Kernel Port.
15573 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
15574 + * it and/or modify it under the terms of the GNU General Public License
15575 + * as published by the Free Software Foundation, either version 2 of the
15576 + * License, or (at your option) any later version.
15578 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15579 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
15580 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15581 + * the GNU General Public License for more details.
15583 + * You should have received a copy of the GNU General Public License
15584 + * along with the Ubicom32 Linux Kernel Port. If not,
15585 + * see <http://www.gnu.org/licenses/>.
15587 + * Ubicom32 implementation derived from (with many thanks):
15592 +#ifndef _ASM_UBICOM32_UBICOM32_SUART_H
15593 +#define _ASM_UBICOM32_UBICOM32_SUART_H
15596 + * Platform resource id for serdes uart clock parameter
15598 +#define UBICOM32_SUART_IORESOURCE_CLOCK (1)
15600 +#endif /* _ASM_UBICOM32_UBICOM32_SUART_H */
15601 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32-tio.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32-tio.h
15602 --- linux-2.6.30.10/arch/ubicom32/include/asm/ubicom32-tio.h 1970-01-01 02:00:00.000000000 +0200
15603 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ubicom32-tio.h 2009-12-11 11:45:11.000000000 +0200
15606 + * arch/ubicom32/include/asm/ubicom32-tio.h
15607 + * Threaded I/O interface definitions.
15609 + * (C) Copyright 2009, Ubicom, Inc.
15611 + * This file is part of the Ubicom32 Linux Kernel Port.
15613 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
15614 + * it and/or modify it under the terms of the GNU General Public License
15615 + * as published by the Free Software Foundation, either version 2 of the
15616 + * License, or (at your option) any later version.
15618 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15619 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
15620 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15621 + * the GNU General Public License for more details.
15623 + * You should have received a copy of the GNU General Public License
15624 + * along with the Ubicom32 Linux Kernel Port. If not,
15625 + * see <http://www.gnu.org/licenses/>.
15627 + * Ubicom32 implementation derived from (with many thanks):
15632 +#ifndef _ASM_UBICOM32_UBICOM32_TIO_H
15633 +#define _ASM_UBICOM32_UBICOM32_TIO_H
15635 +extern u8_t usb_tio_read_u16(u32_t address, u16_t *data);
15636 +extern u8_t usb_tio_read_u8(u32_t address, u8_t *data);
15638 +extern u8_t usb_tio_write_u16(u32_t address, u16_t data);
15639 +extern u8_t usb_tio_write_u8(u32_t address, u8_t data);
15641 +extern u8_t usb_tio_read_fifo(u32_t address, u32_t buffer, u32_t bytes);
15642 +extern u8_t usb_tio_write_fifo(u32_t address, u32_t buffer, u32_t bytes);
15643 +extern u8_t usb_tio_write_fifo_sync(u32_t address, u32_t buffer, u32_t bytes);
15644 +extern void usb_tio_read_int_status(u8_t *int_usb, u16_t *int_tx, u16_t *int_rx);
15646 +#endif /* _ASM_UBICOM32_UBICOM32_TIO_H */
15647 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/ucontext.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ucontext.h
15648 --- linux-2.6.30.10/arch/ubicom32/include/asm/ucontext.h 1970-01-01 02:00:00.000000000 +0200
15649 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/ucontext.h 2009-12-11 11:45:11.000000000 +0200
15652 + * arch/ubicom32/include/asm/ucontext.h
15653 + * Definition of ucontext structure for Ubicom32 architecture.
15655 + * (C) Copyright 2009, Ubicom, Inc.
15657 + * This file is part of the Ubicom32 Linux Kernel Port.
15659 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
15660 + * it and/or modify it under the terms of the GNU General Public License
15661 + * as published by the Free Software Foundation, either version 2 of the
15662 + * License, or (at your option) any later version.
15664 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15665 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
15666 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15667 + * the GNU General Public License for more details.
15669 + * You should have received a copy of the GNU General Public License
15670 + * along with the Ubicom32 Linux Kernel Port. If not,
15671 + * see <http://www.gnu.org/licenses/>.
15673 + * Ubicom32 implementation derived from (with many thanks):
15678 +#ifndef _ASM_UBICOM32_UCONTEXT_H
15679 +#define _ASM_UBICOM32_UCONTEXT_H
15682 + unsigned long uc_flags;
15683 + struct ucontext *uc_link;
15684 + stack_t uc_stack;
15685 + struct sigcontext uc_mcontext;
15686 + sigset_t uc_sigmask; /* mask last for extensibility */
15689 +#endif /* _ASM_UBICOM32_UCONTEXT_H */
15690 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/unaligned.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/unaligned.h
15691 --- linux-2.6.30.10/arch/ubicom32/include/asm/unaligned.h 1970-01-01 02:00:00.000000000 +0200
15692 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/unaligned.h 2009-12-11 11:45:11.000000000 +0200
15695 + * arch/ubicom32/include/asm/unaligned.h
15696 + * Ubicom32 architecture unaligned memory access definitions.
15698 + * (C) Copyright 2009, Ubicom, Inc.
15700 + * This file is part of the Ubicom32 Linux Kernel Port.
15702 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
15703 + * it and/or modify it under the terms of the GNU General Public License
15704 + * as published by the Free Software Foundation, either version 2 of the
15705 + * License, or (at your option) any later version.
15707 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15708 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
15709 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15710 + * the GNU General Public License for more details.
15712 + * You should have received a copy of the GNU General Public License
15713 + * along with the Ubicom32 Linux Kernel Port. If not,
15714 + * see <http://www.gnu.org/licenses/>.
15716 + * Ubicom32 implementation derived from (with many thanks):
15721 + * TODO: This is a copy of arm unaligned handling that probably needs
15722 + * to be optimized for UBICOM32, but it works for now.
15725 +#ifndef _ASM_UBICOM32_UNALIGNED_H
15726 +#define _ASM_UBICOM32_UNALIGNED_H
15728 +#include <asm/types.h>
15730 +#include <linux/unaligned/le_byteshift.h>
15731 +#include <linux/unaligned/be_byteshift.h>
15732 +#include <linux/unaligned/generic.h>
15734 +#define get_unaligned __get_unaligned_be
15735 +#define put_unaligned __put_unaligned_be
15737 +#endif /* _ASM_UBICOM32_UNALIGNED_H */
15738 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/unistd.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/unistd.h
15739 --- linux-2.6.30.10/arch/ubicom32/include/asm/unistd.h 1970-01-01 02:00:00.000000000 +0200
15740 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/unistd.h 2009-12-11 11:45:11.000000000 +0200
15743 + * arch/ubicom32/include/asm/unistd.h
15744 + * Ubicom32 architecture syscall definitions.
15746 + * (C) Copyright 2009, Ubicom, Inc.
15748 + * This file is part of the Ubicom32 Linux Kernel Port.
15750 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
15751 + * it and/or modify it under the terms of the GNU General Public License
15752 + * as published by the Free Software Foundation, either version 2 of the
15753 + * License, or (at your option) any later version.
15755 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15756 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
15757 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15758 + * the GNU General Public License for more details.
15760 + * You should have received a copy of the GNU General Public License
15761 + * along with the Ubicom32 Linux Kernel Port. If not,
15762 + * see <http://www.gnu.org/licenses/>.
15764 + * Ubicom32 implementation derived from (with many thanks):
15769 +#ifndef _ASM_UBICOM32_UNISTD_H
15770 +#define _ASM_UBICOM32_UNISTD_H
15773 + * This file contains the system call numbers.
15776 +#define __NR_restart_syscall 0
15777 +#define __NR_exit 1
15778 +#define __NR_fork 2
15779 +#define __NR_read 3
15780 +#define __NR_write 4
15781 +#define __NR_open 5
15782 +#define __NR_close 6
15783 +#define __NR_waitpid 7
15784 +#define __NR_creat 8
15785 +#define __NR_link 9
15786 +#define __NR_unlink 10
15787 +#define __NR_execve 11
15788 +#define __NR_chdir 12
15789 +#define __NR_time 13
15790 +#define __NR_mknod 14
15791 +#define __NR_chmod 15
15792 +#define __NR_chown 16
15793 +#define __NR_break 17
15794 +#define __NR_oldstat 18
15795 +#define __NR_lseek 19
15796 +#define __NR_getpid 20
15797 +#define __NR_mount 21
15798 +#define __NR_umount 22
15799 +#define __NR_setuid 23
15800 +#define __NR_getuid 24
15801 +#define __NR_stime 25
15802 +#define __NR_ptrace 26
15803 +#define __NR_alarm 27
15804 +#define __NR_oldfstat 28
15805 +#define __NR_pause 29
15806 +#define __NR_utime 30
15807 +#define __NR_stty 31
15808 +#define __NR_gtty 32
15809 +#define __NR_access 33
15810 +#define __NR_nice 34
15811 +#define __NR_ftime 35
15812 +#define __NR_sync 36
15813 +#define __NR_kill 37
15814 +#define __NR_rename 38
15815 +#define __NR_mkdir 39
15816 +#define __NR_rmdir 40
15817 +#define __NR_dup 41
15818 +#define __NR_pipe 42
15819 +#define __NR_times 43
15820 +#define __NR_prof 44
15821 +#define __NR_brk 45
15822 +#define __NR_setgid 46
15823 +#define __NR_getgid 47
15824 +#define __NR_signal 48
15825 +#define __NR_geteuid 49
15826 +#define __NR_getegid 50
15827 +#define __NR_acct 51
15828 +#define __NR_umount2 52
15829 +#define __NR_lock 53
15830 +#define __NR_ioctl 54
15831 +#define __NR_fcntl 55
15832 +#define __NR_mpx 56
15833 +#define __NR_setpgid 57
15834 +#define __NR_ulimit 58
15835 +#define __NR_oldolduname 59
15836 +#define __NR_umask 60
15837 +#define __NR_chroot 61
15838 +#define __NR_ustat 62
15839 +#define __NR_dup2 63
15840 +#define __NR_getppid 64
15841 +#define __NR_getpgrp 65
15842 +#define __NR_setsid 66
15843 +#define __NR_sigaction 67
15844 +#define __NR_sgetmask 68
15845 +#define __NR_ssetmask 69
15846 +#define __NR_setreuid 70
15847 +#define __NR_setregid 71
15848 +#define __NR_sigsuspend 72
15849 +#define __NR_sigpending 73
15850 +#define __NR_sethostname 74
15851 +#define __NR_setrlimit 75
15852 +#define __NR_getrlimit 76
15853 +#define __NR_getrusage 77
15854 +#define __NR_gettimeofday 78
15855 +#define __NR_settimeofday 79
15856 +#define __NR_getgroups 80
15857 +#define __NR_setgroups 81
15858 +#define __NR_select 82
15859 +#define __NR_symlink 83
15860 +#define __NR_oldlstat 84
15861 +#define __NR_readlink 85
15862 +#define __NR_uselib 86
15863 +#define __NR_swapon 87
15864 +#define __NR_reboot 88
15865 +#define __NR_readdir 89
15866 +#define __NR_mmap 90
15867 +#define __NR_munmap 91
15868 +#define __NR_truncate 92
15869 +#define __NR_ftruncate 93
15870 +#define __NR_fchmod 94
15871 +#define __NR_fchown 95
15872 +#define __NR_getpriority 96
15873 +#define __NR_setpriority 97
15874 +#define __NR_profil 98
15875 +#define __NR_statfs 99
15876 +#define __NR_fstatfs 100
15877 +#define __NR_ioperm 101
15878 +#define __NR_socketcall 102
15879 +#define __NR_syslog 103
15880 +#define __NR_setitimer 104
15881 +#define __NR_getitimer 105
15882 +#define __NR_stat 106
15883 +#define __NR_lstat 107
15884 +#define __NR_fstat 108
15885 +#define __NR_olduname 109
15886 +#define __NR_iopl /* 110 */ not supported
15887 +#define __NR_vhangup 111
15888 +#define __NR_idle /* 112 */ Obsolete
15889 +#define __NR_vm86 /* 113 */ not supported
15890 +#define __NR_wait4 114
15891 +#define __NR_swapoff 115
15892 +#define __NR_sysinfo 116
15893 +#define __NR_ipc 117
15894 +#define __NR_fsync 118
15895 +#define __NR_sigreturn 119
15896 +#define __NR_clone 120
15897 +#define __NR_setdomainname 121
15898 +#define __NR_uname 122
15899 +#define __NR_cacheflush 123
15900 +#define __NR_adjtimex 124
15901 +#define __NR_mprotect 125
15902 +#define __NR_sigprocmask 126
15903 +#define __NR_create_module 127
15904 +#define __NR_init_module 128
15905 +#define __NR_delete_module 129
15906 +#define __NR_get_kernel_syms 130
15907 +#define __NR_quotactl 131
15908 +#define __NR_getpgid 132
15909 +#define __NR_fchdir 133
15910 +#define __NR_bdflush 134
15911 +#define __NR_sysfs 135
15912 +#define __NR_personality 136
15913 +#define __NR_afs_syscall 137 /* Syscall for Andrew File System */
15914 +#define __NR_setfsuid 138
15915 +#define __NR_setfsgid 139
15916 +#define __NR__llseek 140
15917 +#define __NR_getdents 141
15918 +#define __NR__newselect 142
15919 +#define __NR_flock 143
15920 +#define __NR_msync 144
15921 +#define __NR_readv 145
15922 +#define __NR_writev 146
15923 +#define __NR_getsid 147
15924 +#define __NR_fdatasync 148
15925 +#define __NR__sysctl 149
15926 +#define __NR_mlock 150
15927 +#define __NR_munlock 151
15928 +#define __NR_mlockall 152
15929 +#define __NR_munlockall 153
15930 +#define __NR_sched_setparam 154
15931 +#define __NR_sched_getparam 155
15932 +#define __NR_sched_setscheduler 156
15933 +#define __NR_sched_getscheduler 157
15934 +#define __NR_sched_yield 158
15935 +#define __NR_sched_get_priority_max 159
15936 +#define __NR_sched_get_priority_min 160
15937 +#define __NR_sched_rr_get_interval 161
15938 +#define __NR_nanosleep 162
15939 +#define __NR_mremap 163
15940 +#define __NR_setresuid 164
15941 +#define __NR_getresuid 165
15942 +#define __NR_getpagesize 166
15943 +#define __NR_query_module 167
15944 +#define __NR_poll 168
15945 +#define __NR_nfsservctl 169
15946 +#define __NR_setresgid 170
15947 +#define __NR_getresgid 171
15948 +#define __NR_prctl 172
15949 +#define __NR_rt_sigreturn 173
15950 +#define __NR_rt_sigaction 174
15951 +#define __NR_rt_sigprocmask 175
15952 +#define __NR_rt_sigpending 176
15953 +#define __NR_rt_sigtimedwait 177
15954 +#define __NR_rt_sigqueueinfo 178
15955 +#define __NR_rt_sigsuspend 179
15956 +#define __NR_pread64 180
15957 +#define __NR_pwrite64 181
15958 +#define __NR_lchown 182
15959 +#define __NR_getcwd 183
15960 +#define __NR_capget 184
15961 +#define __NR_capset 185
15962 +#define __NR_sigaltstack 186
15963 +#define __NR_sendfile 187
15964 +#define __NR_getpmsg 188 /* some people actually want streams */
15965 +#define __NR_putpmsg 189 /* some people actually want streams */
15966 +#define __NR_vfork 190
15967 +#define __NR_ugetrlimit 191
15968 +#define __NR_mmap2 192
15969 +#define __NR_truncate64 193
15970 +#define __NR_ftruncate64 194
15971 +#define __NR_stat64 195
15972 +#define __NR_lstat64 196
15973 +#define __NR_fstat64 197
15974 +#define __NR_chown32 198
15975 +#define __NR_getuid32 199
15976 +#define __NR_getgid32 200
15977 +#define __NR_geteuid32 201
15978 +#define __NR_getegid32 202
15979 +#define __NR_setreuid32 203
15980 +#define __NR_setregid32 204
15981 +#define __NR_getgroups32 205
15982 +#define __NR_setgroups32 206
15983 +#define __NR_fchown32 207
15984 +#define __NR_setresuid32 208
15985 +#define __NR_getresuid32 209
15986 +#define __NR_setresgid32 210
15987 +#define __NR_getresgid32 211
15988 +#define __NR_lchown32 212
15989 +#define __NR_setuid32 213
15990 +#define __NR_setgid32 214
15991 +#define __NR_setfsuid32 215
15992 +#define __NR_setfsgid32 216
15993 +#define __NR_pivot_root 217
15994 +#define __NR_getdents64 220
15995 +#define __NR_gettid 221
15996 +#define __NR_tkill 222
15997 +#define __NR_setxattr 223
15998 +#define __NR_lsetxattr 224
15999 +#define __NR_fsetxattr 225
16000 +#define __NR_getxattr 226
16001 +#define __NR_lgetxattr 227
16002 +#define __NR_fgetxattr 228
16003 +#define __NR_listxattr 229
16004 +#define __NR_llistxattr 230
16005 +#define __NR_flistxattr 231
16006 +#define __NR_removexattr 232
16007 +#define __NR_lremovexattr 233
16008 +#define __NR_fremovexattr 234
16009 +#define __NR_futex 235
16010 +#define __NR_sendfile64 236
16011 +#define __NR_mincore 237
16012 +#define __NR_madvise 238
16013 +#define __NR_fcntl64 239
16014 +#define __NR_readahead 240
16015 +#define __NR_io_setup 241
16016 +#define __NR_io_destroy 242
16017 +#define __NR_io_getevents 243
16018 +#define __NR_io_submit 244
16019 +#define __NR_io_cancel 245
16020 +#define __NR_fadvise64 246
16021 +#define __NR_exit_group 247
16022 +#define __NR_lookup_dcookie 248
16023 +#define __NR_epoll_create 249
16024 +#define __NR_epoll_ctl 250
16025 +#define __NR_epoll_wait 251
16026 +#define __NR_remap_file_pages 252
16027 +#define __NR_set_tid_address 253
16028 +#define __NR_timer_create 254
16029 +#define __NR_timer_settime 255
16030 +#define __NR_timer_gettime 256
16031 +#define __NR_timer_getoverrun 257
16032 +#define __NR_timer_delete 258
16033 +#define __NR_clock_settime 259
16034 +#define __NR_clock_gettime 260
16035 +#define __NR_clock_getres 261
16036 +#define __NR_clock_nanosleep 262
16037 +#define __NR_statfs64 263
16038 +#define __NR_fstatfs64 264
16039 +#define __NR_tgkill 265
16040 +#define __NR_utimes 266
16041 +#define __NR_fadvise64_64 267
16042 +#define __NR_mbind 268
16043 +#define __NR_get_mempolicy 269
16044 +#define __NR_set_mempolicy 270
16045 +#define __NR_mq_open 271
16046 +#define __NR_mq_unlink 272
16047 +#define __NR_mq_timedsend 273
16048 +#define __NR_mq_timedreceive 274
16049 +#define __NR_mq_notify 275
16050 +#define __NR_mq_getsetattr 276
16051 +#define __NR_waitid 277
16052 +#define __NR_vserver 278
16053 +#define __NR_add_key 279
16054 +#define __NR_request_key 280
16055 +#define __NR_keyctl 281
16056 +#define __NR_ioprio_set 282
16057 +#define __NR_ioprio_get 283
16058 +#define __NR_inotify_init 284
16059 +#define __NR_inotify_add_watch 285
16060 +#define __NR_inotify_rm_watch 286
16061 +#define __NR_migrate_pages 287
16062 +#define __NR_openat 288
16063 +#define __NR_mkdirat 289
16064 +#define __NR_mknodat 290
16065 +#define __NR_fchownat 291
16066 +#define __NR_futimesat 292
16067 +#define __NR_fstatat64 293
16068 +#define __NR_unlinkat 294
16069 +#define __NR_renameat 295
16070 +#define __NR_linkat 296
16071 +#define __NR_symlinkat 297
16072 +#define __NR_readlinkat 298
16073 +#define __NR_fchmodat 299
16074 +#define __NR_faccessat 300
16075 +#define __NR_pselect6 301
16076 +#define __NR_ppoll 302
16077 +#define __NR_unshare 303
16078 +#define __NR_set_robust_list 304
16079 +#define __NR_get_robust_list 305
16080 +#define __NR_splice 306
16081 +#define __NR_sync_file_range 307
16082 +#define __NR_tee 308
16083 +#define __NR_vmsplice 309
16084 +#define __NR_move_pages 310
16085 +#define __NR_sched_setaffinity 311
16086 +#define __NR_sched_getaffinity 312
16087 +#define __NR_kexec_load 313
16088 +#define __NR_getcpu 314
16089 +#define __NR_epoll_pwait 315
16090 +#define __NR_utimensat 316
16091 +#define __NR_signalfd 317
16092 +#define __NR_timerfd_create 318
16093 +#define __NR_eventfd 319
16094 +#define __NR_fallocate 320
16095 +#define __NR_timerfd_settime 321
16096 +#define __NR_timerfd_gettime 322
16097 +#define __NR_signalfd4 323
16098 +#define __NR_eventfd2 324
16099 +#define __NR_epoll_create1 325
16100 +#define __NR_dup3 326
16101 +#define __NR_pipe2 327
16102 +#define __NR_inotify_init1 328
16106 +#define NR_syscalls 329
16108 +#define __ARCH_WANT_IPC_PARSE_VERSION
16109 +#define __ARCH_WANT_OLD_READDIR
16110 +#define __ARCH_WANT_OLD_STAT
16111 +#define __ARCH_WANT_STAT64
16112 +#define __ARCH_WANT_SYS_ALARM
16113 +#define __ARCH_WANT_SYS_GETHOSTNAME
16114 +#define __ARCH_WANT_SYS_PAUSE
16115 +#define __ARCH_WANT_SYS_SGETMASK
16116 +#define __ARCH_WANT_SYS_SIGNAL
16117 +#define __ARCH_WANT_SYS_TIME
16118 +#define __ARCH_WANT_SYS_UTIME
16119 +#define __ARCH_WANT_SYS_WAITPID
16120 +#define __ARCH_WANT_SYS_SOCKETCALL
16121 +#define __ARCH_WANT_SYS_FADVISE64
16122 +#define __ARCH_WANT_SYS_GETPGRP
16123 +#define __ARCH_WANT_SYS_LLSEEK
16124 +#define __ARCH_WANT_SYS_NICE
16125 +#define __ARCH_WANT_SYS_OLD_GETRLIMIT
16126 +#define __ARCH_WANT_SYS_OLDUMOUNT
16127 +#define __ARCH_WANT_SYS_SIGPENDING
16128 +#define __ARCH_WANT_SYS_SIGPROCMASK
16129 +#define __ARCH_WANT_SYS_RT_SIGACTION
16132 + * "Conditional" syscalls
16134 + * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
16135 + * but it doesn't work on all toolchains, so we just do it by hand
16137 +//#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
16138 +#define cond_syscall(x) long x(void) __attribute__((weak,alias("sys_ni_syscall")))
16139 +#endif /* __KERNEL__ */
16141 +#endif /* _ASM_UBICOM32_UNISTD_H */
16142 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/user.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/user.h
16143 --- linux-2.6.30.10/arch/ubicom32/include/asm/user.h 1970-01-01 02:00:00.000000000 +0200
16144 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/user.h 2009-12-11 11:45:11.000000000 +0200
16147 + * arch/ubicom32/include/asm/user.h
16148 + * Ubicom32 architecture core file definitions.
16150 + * (C) Copyright 2009, Ubicom, Inc.
16152 + * This file is part of the Ubicom32 Linux Kernel Port.
16154 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
16155 + * it and/or modify it under the terms of the GNU General Public License
16156 + * as published by the Free Software Foundation, either version 2 of the
16157 + * License, or (at your option) any later version.
16159 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
16160 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
16161 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
16162 + * the GNU General Public License for more details.
16164 + * You should have received a copy of the GNU General Public License
16165 + * along with the Ubicom32 Linux Kernel Port. If not,
16166 + * see <http://www.gnu.org/licenses/>.
16168 + * Ubicom32 implementation derived from (with many thanks):
16173 +#ifndef _ASM_UBICOM32_USER_H
16174 +#define _ASM_UBICOM32_USER_H
16176 +#include <asm/ptrace.h>
16177 +#include <asm/page.h>
16179 + * Adapted from <asm-powerpc/user.h>
16181 + * Core file format: The core file is written in such a way that gdb
16182 + * can understand it and provide useful information to the user (under
16183 + * linux we use the `trad-core' bfd, NOT the osf-core). The file contents
16184 + * are as follows:
16186 + * upage: 1 page consisting of a user struct that tells gdb
16187 + * what is present in the file. Directly after this is a
16188 + * copy of the task_struct, which is currently not used by gdb,
16189 + * but it may come in handy at some point. All of the registers
16190 + * are stored as part of the upage. The upage should always be
16191 + * only one page long.
16192 + * data: The data segment follows next. We use current->end_text to
16193 + * current->brk to pick up all of the user variables, plus any memory
16194 + * that may have been sbrk'ed. No attempt is made to determine if a
16195 + * page is demand-zero or if a page is totally unused, we just cover
16196 + * the entire range. All of the addresses are rounded in such a way
16197 + * that an integral number of pages is written.
16198 + * stack: We need the stack information in order to get a meaningful
16199 + * backtrace. We need to write the data from usp to
16200 + * current->start_stack, so we round each of these in order to be able
16201 + * to write an integer number of pages.
16204 +struct user_ubicom32fp_struct {
16208 + struct pt_regs regs; /* entire machine state */
16209 + size_t u_tsize; /* text size (pages) */
16210 + size_t u_dsize; /* data size (pages) */
16211 + size_t u_ssize; /* stack size (pages) */
16212 + unsigned long start_code; /* text starting address */
16213 + unsigned long start_data; /* data starting address */
16214 + unsigned long start_stack; /* stack starting address */
16215 + long int signal; /* signal causing core dump */
16216 + unsigned long u_ar0; /* help gdb find registers */
16217 + unsigned long magic; /* identifies a core file */
16218 + char u_comm[32]; /* user command name */
16221 +#define NBPG PAGE_SIZE
16223 +#define HOST_TEXT_START_ADDR (u.start_code)
16224 +#define HOST_DATA_START_ADDR (u.start_data)
16225 +#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG)
16227 +#endif /* _ASM_UBICOM32_USER_H */
16228 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/vdc_tio.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/vdc_tio.h
16229 --- linux-2.6.30.10/arch/ubicom32/include/asm/vdc_tio.h 1970-01-01 02:00:00.000000000 +0200
16230 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/vdc_tio.h 2009-12-11 11:45:11.000000000 +0200
16233 + * arch/ubicom32/include/asm/vdc_tio.h
16234 + * Ubicom32 architecture VDC TIO definitions.
16236 + * (C) Copyright 2009, Ubicom, Inc.
16238 + * This file is part of the Ubicom32 Linux Kernel Port.
16240 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
16241 + * it and/or modify it under the terms of the GNU General Public License
16242 + * as published by the Free Software Foundation, either version 2 of the
16243 + * License, or (at your option) any later version.
16245 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
16246 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
16247 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
16248 + * the GNU General Public License for more details.
16250 + * You should have received a copy of the GNU General Public License
16251 + * along with the Ubicom32 Linux Kernel Port. If not,
16252 + * see <http://www.gnu.org/licenses/>.
16254 + * Ubicom32 implementation derived from (with many thanks):
16259 +#ifndef _ASM_UBICOM32_VDC_TIO_H
16260 +#define _ASM_UBICOM32_VDC_TIO_H
16262 +#include <asm/devtree.h>
16264 +#define VDCTIO_VP_VERSION 5
16266 +#define VDCTIO_SCALE_FLAG_VSUB (1 << 9)
16267 +#define VDCTIO_SCALE_FLAG_YUV_SCAN_ORDER (1 << 8)
16268 +#define VDCTIO_SCALE_FLAG_YUV_BLOCK_ORDER (1 << 7)
16269 +#define VDCTIO_SCALE_FLAG_YUV (1 << 6)
16270 +#define VDCTIO_SCALE_FLAG_VRANGE_16_255 (1 << 5)
16271 +#define VDCTIO_SCALE_FLAG_VRANGE_0_255 (1 << 4)
16272 +#define VDCTIO_SCALE_FLAG_HSUB_2_1 (1 << 3)
16273 +#define VDCTIO_SCALE_FLAG_HSUB_1_1 (1 << 2)
16274 +#define VDCTIO_SCALE_FLAG_SET_FRAME_BUFFER (1 << 1)
16275 +#define VDCTIO_SCALE_FLAG_ENABLE (1 << 0)
16277 +#define VDCTIO_NEXT_FRAME_FLAG_YUV_BIT 0
16278 +#define VDCTIO_NEXT_FRAME_FLAG_YUV (1 << (VDCTIO_NEXT_FRAME_FLAG_YUV_BIT))
16280 +#define VDCTIO_CAPS_SUPPORTS_SCALING (1 << 0)
16282 +#define VDCTIO_COMMAND_START (1 << 3)
16283 +#define VDCTIO_COMMAND_SET_COEFF (1 << 2)
16284 +#define VDCTIO_COMMAND_SET_LUT (1 << 1)
16285 +#define VDCTIO_COMMAND_SET_SCALE_MODE (1 << 0)
16288 + * Command / Data registers to access the VDC
16290 +struct vdc_tio_vp_regs {
16292 + * Version of this TIO register map
16296 + volatile u32_t command;
16299 + * Next frame pointer, when the command VDCTIO_COMMAND_SET_FRAME_BUFFER is set,
16300 + * the vdc will take the pointer here and display it.
16302 + void *next_frame;
16303 + u32_t next_frame_flags;
16306 + * These map directly into the PIXP registers 0x20-0x80.
16307 + * DO NOT change the order of these three variables.
16309 + u32_t red_lut[6];
16310 + u32_t blue_lut[6];
16311 + u32_t green_lut[13];
16314 + * These map directly into the PIXP registers 0x04, 0x08
16320 + * There are used to set the scaling parameters
16326 + u32_t scale_flags;
16329 + * Current frame number, monotonically increasing number
16331 + u32_t frame_number;
16334 + * These variables tell the guest OS what the underlying hardware looks like
16350 + * Devtree node for VDC
16352 +struct vdc_tio_node {
16353 + struct devtree_node dn;
16355 + struct vdc_tio_vp_regs *regs;
16358 +extern void vdc_tio_init(void);
16360 +#endif /* _ASM_UBICOM32_VDC_TIO_H */
16361 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/vga.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/vga.h
16362 --- linux-2.6.30.10/arch/ubicom32/include/asm/vga.h 1970-01-01 02:00:00.000000000 +0200
16363 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/vga.h 2009-12-11 11:45:11.000000000 +0200
16366 + * arch/ubicom32/include/asm/vga.h
16367 + * Ubicom32 low level VGA/frame buffer definitions.
16369 + * (C) Copyright 2009, Ubicom, Inc.
16370 + * (c) 1998 Martin Mares <mj@ucw.cz>
16372 + * This file is part of the Ubicom32 Linux Kernel Port.
16374 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
16375 + * it and/or modify it under the terms of the GNU General Public License
16376 + * as published by the Free Software Foundation, either version 2 of the
16377 + * License, or (at your option) any later version.
16379 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
16380 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
16381 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
16382 + * the GNU General Public License for more details.
16384 + * You should have received a copy of the GNU General Public License
16385 + * along with the Ubicom32 Linux Kernel Port. If not,
16386 + * see <http://www.gnu.org/licenses/>.
16388 + * Ubicom32 implementation derived from (with many thanks):
16394 +#ifndef _ASM_UBICOM32_VGA_H
16395 +#define _ASM_UBICOM32_VGA_H
16397 +#include <asm/byteorder.h>
16400 + * On the PC, we can just recalculate addresses and then
16401 + * access the videoram directly without any black magic.
16404 +#define VGA_MAP_MEM(x, s) (0xb0000000L + (unsigned long)(x))
16406 +#define vga_readb(x) (*(x))
16407 +#define vga_writeb(x, y) (*(y) = (x))
16409 +#define VT_BUF_HAVE_RW
16411 + * These are only needed for supporting VGA or MDA text mode, which use little
16412 + * endian byte ordering.
16413 + * In other cases, we can optimize by using native byte ordering and
16414 + * <linux/vt_buffer.h> has already done the right job for us.
16420 +static inline void scr_writew(u16 val, volatile u16 *addr)
16422 + *addr = cpu_to_le16(val);
16425 +static inline u16 scr_readw(volatile const u16 *addr)
16427 + return le16_to_cpu(*addr);
16430 +#define scr_memcpyw(d, s, c) memcpy(d, s, c)
16431 +#define scr_memmovew(d, s, c) memmove(d, s, c)
16432 +#define VT_BUF_HAVE_MEMCPYW
16433 +#define VT_BUF_HAVE_MEMMOVEW
16435 +#endif /* _ASM_UBICOM32_VGA_H */
16436 diff -ruN linux-2.6.30.10/arch/ubicom32/include/asm/xor.h linux-2.6.30.10-ubi/arch/ubicom32/include/asm/xor.h
16437 --- linux-2.6.30.10/arch/ubicom32/include/asm/xor.h 1970-01-01 02:00:00.000000000 +0200
16438 +++ linux-2.6.30.10-ubi/arch/ubicom32/include/asm/xor.h 2009-12-11 11:45:11.000000000 +0200
16441 + * arch/ubicom32/include/asm/xor.h
16442 + * Generic xor.h definitions for Ubicom32 architecture.
16444 + * (C) Copyright 2009, Ubicom, Inc.
16446 + * This file is part of the Ubicom32 Linux Kernel Port.
16448 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
16449 + * it and/or modify it under the terms of the GNU General Public License
16450 + * as published by the Free Software Foundation, either version 2 of the
16451 + * License, or (at your option) any later version.
16453 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
16454 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
16455 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
16456 + * the GNU General Public License for more details.
16458 + * You should have received a copy of the GNU General Public License
16459 + * along with the Ubicom32 Linux Kernel Port. If not,
16460 + * see <http://www.gnu.org/licenses/>.
16462 + * Ubicom32 implementation derived from (with many thanks):
16467 +#ifndef _ASM_UBICOM32_XOR_H
16468 +#define _ASM_UBICOM32_XOR_H
16470 +#include <asm-generic/xor.h>
16472 +#endif /* _ASM_UBICOM32_XOR_H */
16473 diff -ruN linux-2.6.30.10/arch/ubicom32/Kconfig linux-2.6.30.10-ubi/arch/ubicom32/Kconfig
16474 --- linux-2.6.30.10/arch/ubicom32/Kconfig 1970-01-01 02:00:00.000000000 +0200
16475 +++ linux-2.6.30.10-ubi/arch/ubicom32/Kconfig 2009-12-11 11:45:11.000000000 +0200
16478 +# For a description of the syntax of this configuration file,
16479 +# see Documentation/kbuild/kconfig-language.txt.
16482 +mainmenu "uClinux/ubicom32 (w/o MMU) Kernel Configuration"
16486 + select HAVE_OPROFILE
16493 +config CPU_BIG_ENDIAN
16497 +config FORCE_MAX_ZONEORDER
16517 +config RWSEM_GENERIC_SPINLOCK
16521 +config RWSEM_XCHGADD_ALGORITHM
16525 +config ARCH_HAS_ILOG2_U32
16529 +config ARCH_HAS_ILOG2_U64
16533 +config GENERIC_FIND_NEXT_BIT
16537 +config GENERIC_GPIO
16545 +config GENERIC_HWEIGHT
16549 +config GENERIC_HARDIRQS
16553 +config STACKTRACE_SUPPORT
16557 +config LOCKDEP_SUPPORT
16561 +config GENERIC_CALIBRATE_DELAY
16565 +config GENERIC_TIME
16569 +config TIME_LOW_RES
16573 +config GENERIC_CLOCKEVENTS
16577 +config GENERIC_CLOCKEVENTS_BROADCAST
16579 + depends on GENERIC_CLOCKEVENTS
16580 + default y if SMP && !LOCAL_TIMERS
16585 +config ARCH_SUPPORTS_AOUT
16588 +config IRQ_PER_CPU
16592 +config SCHED_NO_NO_OMIT_FRAME_POINTER
16596 +config UBICOM32_PLIO
16600 +menu "Processor type and features"
16602 +comment "Processor type will be selected by Board"
16604 +config UBICOM32_V3
16607 + Ubicom IP5xxx series processor support.
16609 +config UBICOM32_V4
16612 + Ubicom IP7xxx series processor support.
16616 + prompt "Board type"
16618 + Select your board.
16621 + bool "No board selected"
16623 + Default. Don't select any board specific config. Will not build unless you change!
16625 +# Add your boards here
16626 +source "arch/ubicom32/mach-ip5k/Kconfig"
16627 +source "arch/ubicom32/mach-ip7k/Kconfig"
16631 +comment "Kernel Options"
16633 + bool "Symmetric multi-processing support"
16634 + select USE_GENERIC_SMP_HELPERS
16637 + Enables multithreading support. Enabling SMP support increases
16638 + the size of system data structures. SMP support can have either
16639 + positive or negative impact on performance depending on workloads.
16641 + If you do not know what to do here, say N.
16642 +config OLD_40400010_SYSTEM_CALL
16643 + bool "Provide old system call interface at 0x40400010"
16646 + Provides the old system call interface, does not affect the
16647 + new system_call interface.
16650 + int "Number of configured CPUs"
16655 + Upper bound on the number of CPUs. Space is reserved
16656 + at compile time for this many CPUs.
16658 +config LOCAL_TIMERS
16659 + bool "Use local timer interrupts"
16663 + Enable support for local timers on SMP platforms, rather then the
16664 + legacy IPI broadcast method. Local timers allows the system
16665 + accounting to be spread across the timer interval, preventing a
16666 + "thundering herd" at every timer tick. A physical timer is allocated
16669 +config TIMER_EXTRA_ALLOC
16670 + int "Number of additional physical timer events to create"
16671 + depends on GENERIC_CLOCKEVENTS
16674 + The Ubicom32 processor has a number of event timers that can be wrapped
16675 + in Linux clock event structures (assuming that the timers are not being
16676 + used for another purpose). Based on the value of LOCAL_TIMERS, either
16677 + 2 timers will be used or a timer will be used for every CPU. This value
16678 + allows the programmer to select additional timers over that amount.
16681 + bool "Create separate stacks for interrupt handling"
16684 + Selecting this causes interrupts to be created on a separate
16685 + stack instead of nesting the interrupts on the kernel stack.
16687 +config IRQSTACKS_USEOCM
16688 + bool "Use OCM for interrupt stacks"
16690 + depends on IRQSTACKS
16692 + Selecting this cause the interrupt stacks to be placed in OCM
16693 + reducing cache misses at the expense of using the OCM for servicing
16696 +menu "OCM Instruction Heap"
16698 +config OCM_MODULES_RESERVATION
16699 + int "OCM Instruction heap reservation. 0-192 kB"
16703 + The minimum amount of OCM memory to reserve for kernel loadable module
16704 + code. If you are not using this memory it cannot be used for anything
16705 + else. Leave it as 0 if you have prebuilt modules that are compiled with
16708 +config OCM_MODULES_MAY_CONSUME_REMAINING_CODESPACE
16709 + bool "Give all unused ocm code space to the ocm instruction heap."
16712 + Allow the OCM instruction heap allocation to consume any remaining
16713 + unused OCM code space. The result of this is that you will not have
16714 + and deterministic results, but you will not have any waste either.
16716 +config OCM_MODULES_FALLBACK_TO_DDR
16717 + bool "Loadable Modules requiring OCM may fallback to use DDR."
16720 + If a module cannot get the OCM code it requires allow DDR to
16725 + int "Frequency of 'jiffies' (for polling)"
16728 + 100 is common for embedded systems, but 1000 allows
16729 + you to do more drivers without actually having
16730 + interrupts working properly.
16732 +comment "RAM configuration"
16734 +config MIN_RAMSIZE
16735 + hex "Minimum Size of RAM (in bytes)"
16736 + range 0x01000000 0x08000000
16737 + default "0x02000000"
16739 + Define the minimum acceptable size of the system
16740 + RAM. Must be at least 16MB (0x01000000)
16742 +comment "Build options"
16743 +config LINKER_RELAXATION
16744 + bool "Linker Relaxation"
16747 + Turns on linker relaxation that will produce smaller
16748 + faster code. Increases link time.
16750 +comment "Driver options"
16756 + Enable/Disable PCI bus
16757 + source "drivers/pci/Kconfig"
16760 +config PCI_DEV0_IDSEL
16761 + hex "slot 0 address"
16763 + default "0x01000000"
16765 + Slot 0 address. This address should correspond to the address line
16766 + which the IDSEL bit for this slot is connected to.
16768 +config PCI_DEV1_IDSEL
16769 + hex "slot 1 address"
16771 + default "0x02000000"
16773 + Slot 1 address. This address should correspond to the address line
16774 + which the IDSEL bit for this slot is connected to.
16778 +menu "Input devices"
16779 +config UBICOM_INPUT
16780 + bool "Ubicom polled GPIO input driver"
16782 + select INPUT_POLLDEV
16784 + Polling input driver, much like the GPIO input driver, except that it doesn't
16785 + rely on interrupts. It will report events via the input subsystem.
16788 +config UBICOM_INPUT_I2C
16789 + bool "Ubicom polled GPIO input driver over I2C"
16791 + select INPUT_POLLDEV
16793 + Polling input driver, much like the PCA953x driver, it can support a variety of
16794 + different I2C I/O expanders. This device polls the I2C I/O expander for events
16795 + and reports them via the input subsystem.
16800 +source "arch/ubicom32/mach-common/Kconfig.switch"
16802 +menu "Misc devices"
16804 + bool "Ubicom HID driver"
16806 + select INPUT_POLLDEV
16807 + select LCD_CLASS_DEVICE
16809 + Driver for HID chip found on some Ubicom reference designs. This chip handles
16810 + PWM, button input, and IR remote control. It registers as an input device and
16811 + a backlight device.
16816 +config CMDLINE_BOOL
16817 + bool "Built-in kernel command line"
16820 + Allow for specifying boot arguments to the kernel at
16821 + build time. On some systems (e.g. embedded ones), it is
16822 + necessary or convenient to provide some or all of the
16823 + kernel boot arguments with the kernel itself (that is,
16824 + to not rely on the boot loader to provide them.)
16826 + To compile command line arguments into the kernel,
16827 + set this option to 'Y', then fill in the
16828 + the boot arguments in CONFIG_CMDLINE.
16830 + Systems with fully functional boot loaders (i.e. non-embedded)
16831 + should leave this option set to 'N'.
16834 + string "Built-in kernel command string"
16835 + depends on CMDLINE_BOOL
16838 + Enter arguments here that should be compiled into the kernel
16839 + image and used at boot time. If the boot loader provides a
16840 + command line at boot time, it is appended to this string to
16841 + form the full kernel command line, when the system boots.
16843 + However, you can use the CONFIG_CMDLINE_OVERRIDE option to
16844 + change this behavior.
16846 + In most cases, the command line (whether built-in or provided
16847 + by the boot loader) should specify the device for the root
16850 +config CMDLINE_OVERRIDE
16851 + bool "Built-in command line overrides boot loader arguments"
16853 + depends on CMDLINE_BOOL
16855 + Set this option to 'Y' to have the kernel ignore the boot loader
16856 + command line, and use ONLY the built-in command line.
16858 + This is used to work around broken boot loaders. This should
16859 + be set to 'N' under normal conditions.
16862 +# End Processor type and features
16864 +source "arch/ubicom32/Kconfig.debug"
16866 +menu "Executable file formats"
16867 +source "fs/Kconfig.binfmt"
16870 +source "init/Kconfig"
16871 +source "kernel/Kconfig.preempt"
16872 +source "kernel/time/Kconfig"
16873 +source "mm/Kconfig"
16874 +source "net/Kconfig"
16875 +source "drivers/Kconfig"
16876 +source "fs/Kconfig"
16877 +source "security/Kconfig"
16878 +source "crypto/Kconfig"
16879 +source "lib/Kconfig"
16880 diff -ruN linux-2.6.30.10/arch/ubicom32/Kconfig.debug linux-2.6.30.10-ubi/arch/ubicom32/Kconfig.debug
16881 --- linux-2.6.30.10/arch/ubicom32/Kconfig.debug 1970-01-01 02:00:00.000000000 +0200
16882 +++ linux-2.6.30.10-ubi/arch/ubicom32/Kconfig.debug 2009-12-11 11:45:11.000000000 +0200
16884 +menu "Kernel hacking"
16886 +config TRACE_IRQFLAGS_SUPPORT
16889 +config DEBUG_VERBOSE
16890 + bool "Verbose fault messages"
16894 + When a program crashes due to an exception, or the kernel detects
16895 + an internal error, the kernel can print a not so brief message
16896 + explaining what the problem was. This debugging information is
16897 + useful to developers and kernel hackers when tracking down problems,
16898 + but mostly meaningless to other people. This is always helpful for
16899 + debugging but serves no purpose on a production system.
16900 + Most people should say N here.
16902 +config PROTECT_KERNEL
16904 + bool 'Enable Kernel range register Protection'
16906 + Adds code to enable/disable range registers to protect static
16907 + kernel code/data from userspace. Currently the ranges covered
16908 + do no protect kernel loadable modules or dynamically allocated
16911 +config NO_KERNEL_MSG
16912 + bool "Suppress Kernel BUG Messages"
16914 + Do not output any debug BUG messages within the kernel.
16916 +config EARLY_PRINTK
16917 + bool "Use the driver that you selected as console also for early printk (to debug kernel bootup)."
16920 + If you want to use the serdes driver (console=ttyUS0) for
16921 + early printk, you must also supply an additional kernel boot
16922 + parameter like this:
16924 + serdes=ioportaddr,irq,clockrate,baud
16926 + For an IP7160RGW eval board, you could use this:
16928 + serdes=0x2004000,61,250000000,57600
16930 + which will let you see early printk output at 57600 baud.
16932 +config STOP_ON_TRAP
16933 + bool "Enable stopping at the LDSR for all traps"
16936 + Cause the LDSR to stop all threads whenever a trap is about to be serviced
16938 +config STOP_ON_BUG
16939 + bool "Enable stopping on failed BUG_ON()"
16942 + Cause all BUG_ON failures to stop all threads
16944 +config DEBUG_IRQMEASURE
16945 + bool "Enable IRQ handler measurements"
16948 + When enabled each IRQ's min/avg/max times will be printed. If the handler
16949 + re-enables interrupt, the times will show the full time including to service
16950 + nested interrupts. See /proc/irq_measurements.
16952 +config DEBUG_PCIMEASURE
16953 + bool "Enable PCI transaction measurements"
16956 + When enabled the system will measure the min/avg/max timer for each PCI transactions.
16957 + See /proc/pci_measurements.
16959 +config ACCESS_OK_CHECKS_ENABLED
16960 + bool "Enable user space access checks"
16963 + Enabling this check causes the kernel to verify that addresses passed
16964 + to the kernel by the user space code are within the processes
16965 + address space. On a no-mmu system, this is done by examining the
16966 + processes memory data structures (adversly affecting performance) but
16967 + ensuring that a process does not ask the kernel to violate another
16968 + processes address space. Sadly, the kernel uses access_ok() for
16969 + address that are in the kernel which results in a large volume of
16973 + prompt "Unaligned Access Support"
16974 + default UNALIGNED_ACCESS_ENABLED
16976 + Kernel / Userspace unaligned access handling.
16978 +config UNALIGNED_ACCESS_ENABLED
16979 + bool "Kernel and Userspace"
16982 +config UNALIGNED_ACCESS_USERSPACE_ONLY
16983 + bool "Userspace Only"
16986 +config UNALIGNED_ACCESS_DISABLED
16992 +config DEBUG_STACKOVERFLOW
16993 + bool "Check for stack overflows"
16995 + depends on DEBUG_KERNEL
16997 + This option will cause messages to be printed if free kernel stack space
16998 + drops below a certain limit (THREAD_SIZE /8).
17000 +config DEBUG_STACK_USAGE
17001 + bool "Stack utilization instrumentation"
17003 + depends on DEBUG_KERNEL
17005 + Enables the display of the minimum amount of free kernel stack which each
17006 + task has ever had available in the sysrq-T and sysrq-P debug output.
17008 + This option will slow down process creation somewhat.
17010 +source "lib/Kconfig.debug"
17013 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/asm-offsets.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/asm-offsets.c
17014 --- linux-2.6.30.10/arch/ubicom32/kernel/asm-offsets.c 1970-01-01 02:00:00.000000000 +0200
17015 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/asm-offsets.c 2009-12-11 11:45:11.000000000 +0200
17018 + * arch/ubicom32/kernel/asm-offsets.c
17019 + * Ubicom32 architecture definitions needed by assembly language modules.
17021 + * (C) Copyright 2009, Ubicom, Inc.
17023 + * This file is part of the Ubicom32 Linux Kernel Port.
17025 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
17026 + * it and/or modify it under the terms of the GNU General Public License
17027 + * as published by the Free Software Foundation, either version 2 of the
17028 + * License, or (at your option) any later version.
17030 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
17031 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
17032 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17033 + * the GNU General Public License for more details.
17035 + * You should have received a copy of the GNU General Public License
17036 + * along with the Ubicom32 Linux Kernel Port. If not,
17037 + * see <http://www.gnu.org/licenses/>.
17039 + * Ubicom32 implementation derived from (with many thanks):
17045 + * This program is used to generate definitions needed by
17046 + * assembly language modules.
17048 + * We use the technique used in the OSF Mach kernel code:
17049 + * generate asm statements containing #defines,
17050 + * compile this file to assembler, and then extract the
17051 + * #defines from the assembly-language output.
17054 +#include <linux/module.h>
17055 +#include <linux/stddef.h>
17056 +#include <linux/sched.h>
17057 +#include <linux/kernel_stat.h>
17058 +#include <linux/ptrace.h>
17059 +#include <linux/hardirq.h>
17060 +#include <asm/bootinfo.h>
17061 +#include <asm/irq.h>
17062 +#include <asm/thread_info.h>
17064 +#define DEFINE(sym, val) \
17065 + asm volatile("\n->" #sym " %0 " #val : : "i" (val))
17067 +#define BLANK() asm volatile("\n->" : : )
17071 + /* offsets into the task struct */
17072 + DEFINE(TASK_STATE, offsetof(struct task_struct, state));
17073 + DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags));
17074 + DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace));
17075 + DEFINE(TASK_BLOCKED, offsetof(struct task_struct, blocked));
17076 + DEFINE(TASK_THREAD, offsetof(struct task_struct, thread));
17077 + DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, stack));
17078 + DEFINE(TASK_MM, offsetof(struct task_struct, mm));
17079 + DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm));
17081 + /* offsets into the kernel_stat struct */
17082 +// DEFINE(STAT_IRQ, offsetof(struct kernel_stat, irqs));
17084 + /* offsets into the irq_cpustat_t struct */
17085 + DEFINE(CPUSTAT_SOFTIRQ_PENDING, offsetof(irq_cpustat_t, __softirq_pending));
17087 + /* offsets into the thread struct */
17088 + DEFINE(THREAD_D10, offsetof(struct thread_struct, d10));
17089 + DEFINE(THREAD_D11, offsetof(struct thread_struct, d11));
17090 + DEFINE(THREAD_D12, offsetof(struct thread_struct, d12));
17091 + DEFINE(THREAD_D13, offsetof(struct thread_struct, d13));
17092 + DEFINE(THREAD_A1, offsetof(struct thread_struct, a1));
17093 + DEFINE(THREAD_A2, offsetof(struct thread_struct, a2));
17094 + DEFINE(THREAD_A5, offsetof(struct thread_struct, a5));
17095 + DEFINE(THREAD_A6, offsetof(struct thread_struct, a6));
17096 + DEFINE(THREAD_SP, offsetof(struct thread_struct, sp));
17098 + /* offsets into the pt_regs */
17099 + DEFINE(PT_D0, offsetof(struct pt_regs, dn[0]));
17100 + DEFINE(PT_D1, offsetof(struct pt_regs, dn[1]));
17101 + DEFINE(PT_D2, offsetof(struct pt_regs, dn[2]));
17102 + DEFINE(PT_D3, offsetof(struct pt_regs, dn[3]));
17103 + DEFINE(PT_D4, offsetof(struct pt_regs, dn[4]));
17104 + DEFINE(PT_D5, offsetof(struct pt_regs, dn[5]));
17105 + DEFINE(PT_D6, offsetof(struct pt_regs, dn[6]));
17106 + DEFINE(PT_D7, offsetof(struct pt_regs, dn[7]));
17107 + DEFINE(PT_D8, offsetof(struct pt_regs, dn[8]));
17108 + DEFINE(PT_D9, offsetof(struct pt_regs, dn[9]));
17109 + DEFINE(PT_D10, offsetof(struct pt_regs, dn[10]));
17110 + DEFINE(PT_D11, offsetof(struct pt_regs, dn[11]));
17111 + DEFINE(PT_D12, offsetof(struct pt_regs, dn[12]));
17112 + DEFINE(PT_D13, offsetof(struct pt_regs, dn[13]));
17113 + DEFINE(PT_D14, offsetof(struct pt_regs, dn[14]));
17114 + DEFINE(PT_D15, offsetof(struct pt_regs, dn[15]));
17115 + DEFINE(PT_A0, offsetof(struct pt_regs, an[0]));
17116 + DEFINE(PT_A1, offsetof(struct pt_regs, an[1]));
17117 + DEFINE(PT_A2, offsetof(struct pt_regs, an[2]));
17118 + DEFINE(PT_A3, offsetof(struct pt_regs, an[3]));
17119 + DEFINE(PT_A4, offsetof(struct pt_regs, an[4]));
17120 + DEFINE(PT_A5, offsetof(struct pt_regs, an[5]));
17121 + DEFINE(PT_A6, offsetof(struct pt_regs, an[6]));
17122 + DEFINE(PT_A7, offsetof(struct pt_regs, an[7]));
17123 + DEFINE(PT_SP, offsetof(struct pt_regs, an[7]));
17125 + DEFINE(PT_ACC0HI, offsetof(struct pt_regs, acc0[0]));
17126 + DEFINE(PT_ACC0LO, offsetof(struct pt_regs, acc0[1]));
17127 + DEFINE(PT_MAC_RC16, offsetof(struct pt_regs, mac_rc16));
17129 + DEFINE(PT_ACC1HI, offsetof(struct pt_regs, acc1[0]));
17130 + DEFINE(PT_ACC1LO, offsetof(struct pt_regs, acc1[1]));
17132 + DEFINE(PT_SOURCE3, offsetof(struct pt_regs, source3));
17133 + DEFINE(PT_INST_CNT, offsetof(struct pt_regs, inst_cnt));
17134 + DEFINE(PT_CSR, offsetof(struct pt_regs, csr));
17135 + DEFINE(PT_DUMMY_UNUSED, offsetof(struct pt_regs, dummy_unused));
17137 + DEFINE(PT_INT_MASK0, offsetof(struct pt_regs, int_mask0));
17138 + DEFINE(PT_INT_MASK1, offsetof(struct pt_regs, int_mask1));
17140 + DEFINE(PT_PC, offsetof(struct pt_regs, pc));
17142 + DEFINE(PT_TRAP_CAUSE, offsetof(struct pt_regs, trap_cause));
17144 + DEFINE(PT_SIZE, sizeof(struct pt_regs));
17146 + DEFINE(PT_FRAME_TYPE, offsetof(struct pt_regs, frame_type));
17148 + DEFINE(PT_ORIGINAL_D0, offsetof(struct pt_regs, original_dn_0));
17149 + DEFINE(PT_PREVIOUS_PC, offsetof(struct pt_regs, previous_pc));
17151 + /* offsets into the kernel_stat struct */
17152 +// DEFINE(STAT_IRQ, offsetof(struct kernel_stat, irqs));
17154 + /* signal defines */
17155 + DEFINE(SIGSEGV, SIGSEGV);
17156 + //DEFINE(SEGV_MAPERR, SEGV_MAPERR);
17157 + DEFINE(SIGTRAP, SIGTRAP);
17158 + //DEFINE(TRAP_TRACE, TRAP_TRACE);
17160 + DEFINE(PT_PTRACED, PT_PTRACED);
17161 + DEFINE(PT_DTRACE, PT_DTRACE);
17163 + DEFINE(ASM_THREAD_SIZE, THREAD_SIZE);
17165 + /* Offsets in thread_info structure */
17166 + DEFINE(TI_TASK, offsetof(struct thread_info, task));
17167 + DEFINE(TI_EXECDOMAIN, offsetof(struct thread_info, exec_domain));
17168 + DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
17169 + DEFINE(TI_PREEMPTCOUNT, offsetof(struct thread_info, preempt_count));
17170 + DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
17171 + DEFINE(TI_INTR_NESTING, offsetof(struct thread_info, interrupt_nesting));
17172 + DEFINE(ASM_TIF_NEED_RESCHED, TIF_NEED_RESCHED);
17173 + DEFINE(ASM_TIF_SYSCALL_TRACE, TIF_SYSCALL_TRACE);
17174 + DEFINE(ASM_TIF_SIGPENDING, TIF_SIGPENDING);
17178 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/devtree.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/devtree.c
17179 --- linux-2.6.30.10/arch/ubicom32/kernel/devtree.c 1970-01-01 02:00:00.000000000 +0200
17180 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/devtree.c 2009-12-11 11:45:11.000000000 +0200
17183 + * arch/ubicom32/kernel/devtree.c
17184 + * Ubicom32 architecture device tree implementation.
17186 + * (C) Copyright 2009, Ubicom, Inc.
17188 + * This file is part of the Ubicom32 Linux Kernel Port.
17190 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
17191 + * it and/or modify it under the terms of the GNU General Public License
17192 + * as published by the Free Software Foundation, either version 2 of the
17193 + * License, or (at your option) any later version.
17195 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
17196 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
17197 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17198 + * the GNU General Public License for more details.
17200 + * You should have received a copy of the GNU General Public License
17201 + * along with the Ubicom32 Linux Kernel Port. If not,
17202 + * see <http://www.gnu.org/licenses/>.
17204 + * Ubicom32 implementation derived from (with many thanks):
17210 +#include <linux/module.h>
17211 +#include <linux/kernel.h>
17212 +#include <linux/string.h>
17213 +#include <linux/errno.h>
17214 +#include <asm/devtree.h>
17217 + * The device tree.
17219 +struct devtree_node *devtree;
17222 + * devtree_print()
17223 + * Print the device tree.
17225 +void devtree_print(void)
17227 + struct devtree_node *p = devtree;
17228 + printk(KERN_INFO "Device Tree:\n");
17230 + if (p->magic != DEVTREE_NODE_MAGIC) {
17231 + printk(KERN_EMERG
17232 + "device tree has improper node: %p\n", p);
17235 + printk(KERN_INFO "\t%p: sendirq=%03d, recvirq=%03d, "
17236 + " name=%s\n", p, p->sendirq, p->recvirq, p->name);
17240 +EXPORT_SYMBOL(devtree_print);
17244 + * Return the IRQ(s) associated with devtree node.
17246 +int devtree_irq(struct devtree_node *dn,
17247 + unsigned char *sendirq,
17248 + unsigned char *recvirq)
17250 + if (dn->magic != DEVTREE_NODE_MAGIC) {
17251 + printk(KERN_EMERG "improper node: %p\n", dn);
17253 + *sendirq = DEVTREE_IRQ_NONE;
17256 + *recvirq = DEVTREE_IRQ_NONE;
17262 + * Copy the devtree irq(s) to the output parameters.
17265 + *sendirq = dn->sendirq;
17268 + *recvirq = dn->recvirq;
17272 +EXPORT_SYMBOL(devtree_irq);
17275 + * devtree_find_next()
17276 + * Provide an iterator for walking the device tree.
17278 +struct devtree_node *devtree_find_next(struct devtree_node **cur)
17280 + struct devtree_node *p = *cur;
17291 + * devtree_find_by_irq()
17292 + * Return the node associated with a given irq.
17294 +struct devtree_node *devtree_find_by_irq(uint8_t sendirq, uint8_t recvirq)
17296 + struct devtree_node *p = devtree;
17298 + if (sendirq == recvirq) {
17299 + printk(KERN_EMERG "identical request makes no sense sendirq = "
17300 + "%d, recvirq= %d\n", sendirq, recvirq);
17305 + if (p->magic != DEVTREE_NODE_MAGIC) {
17306 + printk(KERN_EMERG
17307 + "device tree has improper node: %p\n", p);
17312 + * See if we can find a match on the IRQ(s) specified.
17314 + if ((sendirq == p->sendirq) && (recvirq == p->recvirq)) {
17318 + if ((sendirq == DEVTREE_IRQ_DONTCARE) &&
17319 + (p->recvirq == recvirq)) {
17323 + if ((recvirq == DEVTREE_IRQ_DONTCARE) &&
17324 + (p->sendirq == sendirq)) {
17332 +EXPORT_SYMBOL(devtree_find_by_irq);
17335 + * devtree_find_node()
17336 + * Find a node in the device tree by name.
17338 +struct devtree_node *devtree_find_node(const char *str)
17340 + struct devtree_node *p = devtree;
17342 + if (p->magic != DEVTREE_NODE_MAGIC) {
17343 + printk(KERN_EMERG
17344 + "device tree has improper node: %p\n", p);
17347 + if (strcmp(p->name, str) == 0) {
17354 +EXPORT_SYMBOL(devtree_find_node);
17355 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/dma.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/dma.c
17356 --- linux-2.6.30.10/arch/ubicom32/kernel/dma.c 1970-01-01 02:00:00.000000000 +0200
17357 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/dma.c 2009-12-11 11:45:11.000000000 +0200
17360 + * arch/ubicom32/kernel/dma.c
17361 + * Ubicom32 architecture dynamic DMA mapping support.
17363 + * (C) Copyright 2009, Ubicom, Inc.
17365 + * This file is part of the Ubicom32 Linux Kernel Port.
17367 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
17368 + * it and/or modify it under the terms of the GNU General Public License
17369 + * as published by the Free Software Foundation, either version 2 of the
17370 + * License, or (at your option) any later version.
17372 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
17373 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
17374 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17375 + * the GNU General Public License for more details.
17377 + * You should have received a copy of the GNU General Public License
17378 + * along with the Ubicom32 Linux Kernel Port. If not,
17379 + * see <http://www.gnu.org/licenses/>.
17381 + * Ubicom32 implementation derived from (with many thanks):
17386 + * We never have any address translations to worry about, so this
17387 + * is just alloc/free.
17390 +#include <linux/types.h>
17391 +#include <linux/mm.h>
17392 +#include <linux/string.h>
17393 +#include <linux/device.h>
17394 +#include <linux/io.h>
17396 +void *dma_alloc_coherent(struct device *dev, size_t size,
17397 + dma_addr_t *dma_handle, int gfp)
17400 + /* ignore region specifiers */
17401 + gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
17403 + if (dev == NULL || (*dev->dma_mask < 0xffffffff))
17405 + ret = (void *)__get_free_pages(gfp, get_order(size));
17407 + if (ret != NULL) {
17408 + memset(ret, 0, size);
17409 + *dma_handle = virt_to_phys(ret);
17414 +void dma_free_coherent(struct device *dev, size_t size,
17415 + void *vaddr, dma_addr_t dma_handle)
17417 + free_pages((unsigned long)vaddr, get_order(size));
17419 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/flat.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/flat.c
17420 --- linux-2.6.30.10/arch/ubicom32/kernel/flat.c 1970-01-01 02:00:00.000000000 +0200
17421 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/flat.c 2009-12-11 11:45:11.000000000 +0200
17424 + * arch/ubicom32/kernel/flat.c
17425 + * Ubicom32 architecture flat executable format support.
17427 + * (C) Copyright 2009, Ubicom, Inc.
17429 + * This file is part of the Ubicom32 Linux Kernel Port.
17431 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
17432 + * it and/or modify it under the terms of the GNU General Public License
17433 + * as published by the Free Software Foundation, either version 2 of the
17434 + * License, or (at your option) any later version.
17436 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
17437 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
17438 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17439 + * the GNU General Public License for more details.
17441 + * You should have received a copy of the GNU General Public License
17442 + * along with the Ubicom32 Linux Kernel Port. If not,
17443 + * see <http://www.gnu.org/licenses/>.
17445 + * Ubicom32 implementation derived from (with many thanks):
17450 +#include <linux/module.h>
17451 +#include <linux/types.h>
17452 +#include <linux/flat.h>
17454 +unsigned long ubicom32_flat_get_addr_from_rp(unsigned long *rp,
17457 + unsigned long *persistent)
17459 + u32_t relval_reloc_type = relval >> 27;
17460 + u32_t insn = *rp;
17462 + if (*persistent) {
17464 + * relval holds the relocation that has to be adjusted.
17466 + if (relval == 0) {
17473 + if (relval_reloc_type == R_UBICOM32_32) {
17475 + * insn holds the relocation
17481 + * We don't know this one.
17486 +void ubicom32_flat_put_addr_at_rp(unsigned long *rp,
17489 + unsigned long *persistent)
17491 + u32_t reloc_type = (relval >> 27) & 0x1f;
17492 + u32_t insn = *rp;
17495 + * If persistent is set then it contains the relocation type.
17497 + if (*persistent) {
17499 + * If persistent is set then it contains the relocation type.
17501 + reloc_type = (*persistent >> 27) & 0x1f;
17504 + switch (reloc_type) {
17505 + case R_UBICOM32_32:
17507 + * Store the 32 bits as is.
17511 + case R_UBICOM32_HI24:
17514 + * 24 bit relocation that is part of the MOVEAI
17515 + * instruction. The 24 bits come from bits 7 - 30 of the
17516 + * relocation. The 24 bits eventually get split into 2
17517 + * fields in the instruction encoding.
17519 + * - Bits 7 - 27 of the relocation are encoded into bits
17520 + * 0 - 20 of the instruction.
17522 + * - Bits 28 - 30 of the relocation are encoded into bit
17523 + * 24 - 26 of the instruction.
17525 + u32_t mask = 0x1fffff | (0x7 << 24);
17526 + u32_t valid24bits = (val >> 7) & 0xffffff;
17527 + u32_t bot_21 = valid24bits & 0x1fffff;
17528 + u32_t upper_3_bits = ((valid24bits & 0xe00000) << 3);
17532 + insn |= upper_3_bits;
17536 + case R_UBICOM32_LO7_S:
17537 + case R_UBICOM32_LO7_2_S:
17538 + case R_UBICOM32_LO7_4_S:
17541 + * Bits 0 - 6 of the relocation are encoded into the
17542 + * 7bit unsigned immediate fields of the SOURCE-1 field
17543 + * of the instruction. The immediate value is left
17544 + * shifted by (0, 1, 2) based on the operand size.
17546 + u32_t mask = 0x1f | (0x3 << 8);
17547 + u32_t bottom, top;
17549 + if (reloc_type == R_UBICOM32_LO7_2_S) {
17551 + } else if (reloc_type == R_UBICOM32_LO7_4_S) {
17555 + bottom = val & 0x1f;
17559 + insn |= (top << 8);
17560 + BUG_ON(*rp != insn);
17564 + case R_UBICOM32_LO7_D:
17565 + case R_UBICOM32_LO7_2_D:
17566 + case R_UBICOM32_LO7_4_D:
17569 + * Bits 0 - 6 of the relocation are encoded into the
17570 + * 7bit unsigned immediate fields of the DESTINATION
17571 + * field of the instruction. The immediate value is
17572 + * left shifted by (0, 1, 2) based on the operand size.
17574 + u32_t mask = (0x1f | (0x3 << 8)) << 16;
17575 + u32_t bottom, top;
17577 + if (reloc_type == R_UBICOM32_LO7_2_D) {
17579 + } else if (reloc_type == R_UBICOM32_LO7_4_D) {
17582 + bottom = (val & 0x1f) << 16;
17583 + top = (val >> 5) << 16;
17586 + insn |= (top << 8);
17587 + BUG_ON(*rp != insn);
17591 + case R_UBICOM32_LO7_CALLI:
17592 + case R_UBICOM32_LO16_CALLI:
17595 + * Extract the offset for a CALLI instruction. The
17596 + * offsets can be either 7 bits or 18 bits. Since all
17597 + * instructions in ubicom32 architecture are at work
17598 + * aligned addresses the truncated offset is right
17599 + * shifted by 2 before being encoded in the instruction.
17601 + if (reloc_type == R_UBICOM32_LO7_CALLI) {
17609 + insn &= ~0x071f071f;
17610 + insn |= (val & 0x1f) << 0;
17612 + insn |= (val & 0x07) << 8;
17614 + insn |= (val & 0x1f) << 16;
17616 + insn |= (val & 0x07) << 24;
17617 + if (reloc_type == R_UBICOM32_LO7_CALLI) {
17618 + BUG_ON(*rp != insn);
17625 + if (*persistent) {
17629 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/head.S linux-2.6.30.10-ubi/arch/ubicom32/kernel/head.S
17630 --- linux-2.6.30.10/arch/ubicom32/kernel/head.S 1970-01-01 02:00:00.000000000 +0200
17631 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/head.S 2009-12-11 11:45:11.000000000 +0200
17634 + * arch/ubicom32/kernel/head.S
17635 + * <TODO: Replace with short file description>
17637 + * (C) Copyright 2009, Ubicom, Inc.
17639 + * This file is part of the Ubicom32 Linux Kernel Port.
17641 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
17642 + * it and/or modify it under the terms of the GNU General Public License
17643 + * as published by the Free Software Foundation, either version 2 of the
17644 + * License, or (at your option) any later version.
17646 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
17647 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
17648 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17649 + * the GNU General Public License for more details.
17651 + * You should have received a copy of the GNU General Public License
17652 + * along with the Ubicom32 Linux Kernel Port. If not,
17653 + * see <http://www.gnu.org/licenses/>.
17655 + * Ubicom32 implementation derived from (with many thanks):
17660 +#include <linux/sys.h>
17661 +#include <linux/linkage.h>
17662 +#include <asm/asm-offsets.h>
17663 +#include <asm/page_offset.h>
17665 +#include <asm/ip5000.h>
17671 +#define PARAM_DN D0
17672 +#define TMP_DN D15
17673 +#define TMP2_DN D14
17676 + * The following code is placed at the start of the Linux section of memory.
17677 + * This is the primary entry point for Linux.
17679 + * However, we also want the syscall entry/exit code to be at a fixed address.
17680 + * So we take the primary entry point and reserve 16 bytes. That address is
17681 + * where the system_call entry point exists. This 16 bytes basically allows
17682 + * us to jump around the system_call entry point code to the actual startup
17685 + * Linux Memory Map (see vlinux.lds.S):
17686 + * 0x40400000 - Primary Entry Point for Linux (jump around code below).
17687 + * 0x40400010 - Old syscall Entry Point.
17690 + .sect .skip_syscall, "ax", @progbits
17691 + .global __skip_syscall_section
17692 +__skip_syscall_section:
17693 + moveai A3, #%hi(_start)
17694 + lea.1 A3, %lo(_start)(A3)
17697 + * __os_node_offset contains the offset from KERNELBASE to the os_node, it is
17698 + * not intended to be used by anything except the boot code.
17701 +.long (_os_node - KERNELSTART)
17708 + * This is the start of the Linux kernel.
17711 + move.4 SCRATCHPAD1, #0
17715 + * Setup the range registers... the loader has setup a few, but we will go ahead
17716 + * and correct them for our own limits. Note that once set these are never
17717 + * changed again. The ranges are as follows
17719 + * D_RANGE0 - io block (set up by loaded)
17721 + * I_RANGE0 and D_RANGE1 - kernel/ultra loader address space bottom of ocm-> top
17722 + * of ram typically 0x3ffc0000 - 0x440000000
17723 + * I_RANGE1 - kernel / userspace transition area (aka syscalls, context switches)
17724 + * typically 0x3FFC0030 - ~0x3FFC0200
17725 + * I_RANGE2 / D_RANGE2 - slab area
17726 + * typically 0x40A00000 - ~0x44000000
17728 + * old system call interface if enabled.
17730 + * D_RANGE3, D_RANGE4 - unused.
17732 + moveai SRC_AN, #%hi(PAGE_OFFSET_RAW)
17733 + lea.4 SRC_AN, %lo(PAGE_OFFSET_RAW)(SRC_AN)
17734 + move.4 D_RANGE1_LO, SRC_AN
17735 + move.4 I_RANGE0_LO, SRC_AN
17737 +; don't try to calculate I_RANGE_HI, see below
17738 +; moveai SRC_AN, #%hi(___init_end-4)
17739 +; lea.4 SRC_AN, %lo(___init_end-4)(SRC_AN)
17740 +; move.4 I_RANGE0_HI, SRC_AN
17742 + moveai SRC_AN, #%hi(SDRAMSTART + CONFIG_MIN_RAMSIZE-4)
17743 + lea.4 SRC_AN, %lo(SDRAMSTART + CONFIG_MIN_RAMSIZE-4)(SRC_AN)
17744 + move.4 D_RANGE1_HI, SRC_AN
17746 +; for now allow the whole ram to be executable as well so we don't run into problems
17747 +; once we load user more code.
17748 + move.4 I_RANGE0_HI, SRC_AN
17750 +#ifdef CONFIG_PROTECT_KERNEL
17751 +; when kernel protection is enabled, we only open up syscall and non kernel text
17752 +; for userspace apps, for now only irange registers registers 1 and 2 are used for userspace.
17755 + moveai SRC_AN, #%hi(__syscall_text_run_begin)
17756 + lea.4 SRC_AN, %lo(__syscall_text_run_begin)(SRC_AN)
17757 + move.4 I_RANGE1_LO, SRC_AN
17758 + moveai SRC_AN, #%hi(__syscall_text_run_end)
17759 + lea.4 SRC_AN, %lo(__syscall_text_run_end)(SRC_AN)
17760 + move.4 I_RANGE1_HI, SRC_AN
17762 + ;; slab instructions
17763 + moveai SRC_AN, #%hi(_edata)
17764 + lea.4 SRC_AN, %lo(_edata)(SRC_AN)
17765 + move.4 I_RANGE2_LO, SRC_AN
17766 + ;; End of DDR is already in range0 hi so just copy it.
17767 + move.4 I_RANGE2_HI, I_RANGE0_HI
17769 +#ifdef CONFIG_OLD_40400010_SYSTEM_CALL
17770 + ;; create a small hole for old syscall location
17771 + moveai SRC_AN, #%hi(0x40400000)
17772 + lea.4 I_RANGE3_LO, 0x10(SRC_AN)
17773 + lea.4 I_RANGE3_HI, 0x14(SRC_AN)
17775 + ;; slab data (same as slab instructions but starting a little earlier).
17776 + moveai SRC_AN, #%hi(_data_protection_end)
17777 + lea.4 SRC_AN, %lo(_data_protection_end)(SRC_AN)
17778 + move.4 D_RANGE2_LO, SRC_AN
17779 + move.4 D_RANGE2_HI, I_RANGE0_HI
17782 + ;; skip I_RANGE0_EN
17783 + move.4 I_RANGE1_EN, #-1
17784 + move.4 I_RANGE2_EN, #-1
17785 +#ifdef CONFIG_OLD_40400010_SYSTEM_CALL
17786 + move.4 I_RANGE3_EN, #-1
17788 + move.4 I_RANGE3_EN, #0
17790 + ;; skip D_RANGE0_EN or D_RANGE1_EN
17791 + move.4 D_RANGE2_EN, #-1
17792 + move.4 D_RANGE3_EN, #0
17793 + move.4 D_RANGE4_EN, #0
17797 +; If __ocm_free_begin is smaller than __ocm_free_end the
17798 +; setup OCM text and data ram banks properly
17800 + moveai DST_AN, #%hi(__ocm_free_begin)
17801 + lea.4 TMP_DN, %lo(__ocm_free_begin)(DST_AN)
17802 + moveai DST_AN, #%hi(__ocm_free_end)
17803 + lea.4 TMP2_DN, %lo(__ocm_free_end)(DST_AN)
17804 + sub.4 #0, TMP2_DN, TMP_DN
17806 + moveai DST_AN, #%hi(__data_begin)
17807 + lea.4 TMP_DN, %lo(__data_begin)(DST_AN)
17808 + moveai DST_AN, #%hi(OCMSTART)
17809 + lea.4 TMP2_DN, %lo(OCMSTART)(DST_AN)
17810 + sub.4 TMP_DN, TMP_DN, TMP2_DN
17811 + lsr.4 TMP_DN, TMP_DN, #15
17812 + lsl.4 TMP_DN, #1, TMP_DN
17813 + moveai DST_AN, #%hi(OCMC_BASE)
17814 + add.4 OCMC_BANK_MASK(DST_AN), #-1, TMP_DN
17820 + moveai DST_AN, #%hi(__ocm_text_run_end)
17821 + lea.4 TMP_DN, %lo(__ocm_text_run_end)(DST_AN)
17822 + moveai DST_AN, #%hi(__ocm_text_run_begin)
17823 + lea.4 DST_AN, %lo(__ocm_text_run_begin)(DST_AN)
17824 + moveai SRC_AN, #%hi(__ocm_text_load_begin)
17825 + lea.4 SRC_AN, %lo(__ocm_text_load_begin)(SRC_AN)
17828 +1: move.4 (DST_AN)4++, (SRC_AN)4++
17830 +2: sub.4 #0, DST_AN, TMP_DN
17833 +; Load .syscall_text
17835 + moveai DST_AN, #%hi(__syscall_text_run_end)
17836 + lea.4 TMP_DN, %lo(__syscall_text_run_end)(DST_AN)
17837 + moveai DST_AN, #%hi(__syscall_text_run_begin)
17838 + lea.4 DST_AN, %lo(__syscall_text_run_begin)(DST_AN)
17839 + moveai SRC_AN, #%hi(__syscall_text_load_begin)
17840 + lea.4 SRC_AN, %lo(__syscall_text_load_begin)(SRC_AN)
17843 +1: move.4 (DST_AN)4++, (SRC_AN)4++
17845 +2: sub.4 #0, DST_AN, TMP_DN
17851 + moveai DST_AN, #%hi(__ocm_data_run_end)
17852 + lea.4 TMP_DN, %lo(__ocm_data_run_end)(DST_AN)
17853 + moveai DST_AN, #%hi(__ocm_data_run_begin)
17854 + lea.4 DST_AN, %lo(__ocm_data_run_begin)(DST_AN)
17855 + moveai SRC_AN, #%hi(__ocm_data_load_begin)
17856 + lea.4 SRC_AN, %lo(__ocm_data_load_begin)(SRC_AN)
17859 +1: move.4 (DST_AN)4++, (SRC_AN)4++
17861 +2: sub.4 #0, DST_AN, TMP_DN
17866 + moveai SRC_AN, #%hi(_ebss)
17867 + lea.4 TMP_DN, %lo(_ebss)(SRC_AN)
17868 + moveai DST_AN, #%hi(_sbss)
17869 + lea.4 DST_AN, %lo(_sbss)(DST_AN)
17872 +1: move.4 (DST_AN)4++, #0
17874 +2: sub.4 #0, DST_AN, TMP_DN
17877 +; save our parameter to devtree (after clearing .bss)
17878 + moveai DST_AN, #%hi(devtree)
17879 + lea.4 DST_AN, %lo(devtree)(DST_AN)
17880 + move.4 (DST_AN), PARAM_DN
17882 + moveai sp, #%hi(init_thread_union)
17883 + lea.4 sp, %lo(init_thread_union)(sp)
17884 + movei TMP_DN, #ASM_THREAD_SIZE
17885 + add.4 sp, sp, TMP_DN
17886 + move.4 -4(sp)++, #0 ; nesting level = 0
17887 + move.4 -4(sp)++, #1 ; KERNEL_THREAD
17889 +;; ip3k-elf-gdb backend now sets scratchpad3 to 1 when either continue
17890 +;; or single step commands are issued. scratchpad3 is set to 0 when the
17891 +;; debugger detaches from the board.
17892 + move.4 TMP_DN, scratchpad3
17893 + lsl.4 TMP_DN, TMP_DN, #0x0
17894 + jmpeq.f _jump_to_start_kernel
17895 +_ok_to_set_break_points_in_linux:
17897 + move.4 mt_dbg_active_clr,#-1
17898 +;; stalling the threads isn't instantaneous.. need to flush the pipe.
17902 +_jump_to_start_kernel:
17903 + moveai SRC_AN, #%hi(start_kernel)
17904 + lea.4 SRC_AN, %lo(start_kernel)(SRC_AN)
17906 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/init_task.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/init_task.c
17907 --- linux-2.6.30.10/arch/ubicom32/kernel/init_task.c 1970-01-01 02:00:00.000000000 +0200
17908 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/init_task.c 2009-12-11 11:45:11.000000000 +0200
17911 + * arch/ubicom32/kernel/init_task.c
17912 + * Ubicom32 architecture task initialization implementation.
17914 + * (C) Copyright 2009, Ubicom, Inc.
17916 + * This file is part of the Ubicom32 Linux Kernel Port.
17918 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
17919 + * it and/or modify it under the terms of the GNU General Public License
17920 + * as published by the Free Software Foundation, either version 2 of the
17921 + * License, or (at your option) any later version.
17923 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
17924 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
17925 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17926 + * the GNU General Public License for more details.
17928 + * You should have received a copy of the GNU General Public License
17929 + * along with the Ubicom32 Linux Kernel Port. If not,
17930 + * see <http://www.gnu.org/licenses/>.
17932 + * Ubicom32 implementation derived from (with many thanks):
17937 +#include <linux/mm.h>
17938 +#include <linux/module.h>
17939 +#include <linux/sched.h>
17940 +#include <linux/init.h>
17941 +#include <linux/init_task.h>
17942 +#include <linux/fs.h>
17943 +#include <linux/mqueue.h>
17944 +#include <linux/uaccess.h>
17945 +#include <asm/pgtable.h>
17947 +///static struct fs_struct init_fs = INIT_FS;
17948 +static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
17949 +static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
17950 +struct mm_struct init_mm = INIT_MM(init_mm);
17951 +EXPORT_SYMBOL(init_mm);
17954 + * Initial task structure.
17956 + * All other task structs will be allocated on slabs in fork.c
17958 +struct task_struct init_task = INIT_TASK(init_task);
17960 +EXPORT_SYMBOL(init_task);
17963 + * Initial thread structure.
17965 + * We need to make sure that this is 8192-byte aligned due to the
17966 + * way process stacks are handled. This is done by having a special
17967 + * "init_task" linker map entry..
17969 +union thread_union init_thread_union
17970 + __attribute__((__section__(".data.init_task"))) =
17971 + { INIT_THREAD_INFO(init_task) };
17972 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/irq.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/irq.c
17973 --- linux-2.6.30.10/arch/ubicom32/kernel/irq.c 1970-01-01 02:00:00.000000000 +0200
17974 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/irq.c 2009-12-11 11:45:11.000000000 +0200
17977 + * arch/ubicom32/kernel/irq.c
17978 + * Ubicom32 architecture IRQ support.
17980 + * (C) Copyright 2009, Ubicom, Inc.
17981 + * (C) Copyright 2007, Greg Ungerer <gerg@snapgear.com>
17983 + * This file is part of the Ubicom32 Linux Kernel Port.
17985 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
17986 + * it and/or modify it under the terms of the GNU General Public License
17987 + * as published by the Free Software Foundation, either version 2 of the
17988 + * License, or (at your option) any later version.
17990 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
17991 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
17992 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17993 + * the GNU General Public License for more details.
17995 + * You should have received a copy of the GNU General Public License
17996 + * along with the Ubicom32 Linux Kernel Port. If not,
17997 + * see <http://www.gnu.org/licenses/>.
17999 + * Ubicom32 implementation derived from (with many thanks):
18005 +#include <linux/types.h>
18006 +#include <linux/irq.h>
18007 +#include <linux/init.h>
18008 +#include <linux/kernel.h>
18009 +#include <linux/kernel_stat.h>
18010 +#include <linux/module.h>
18011 +#include <linux/seq_file.h>
18012 +#include <linux/proc_fs.h>
18013 +#include <asm/system.h>
18014 +#include <asm/traps.h>
18015 +#include <asm/ldsr.h>
18016 +#include <asm/ip5000.h>
18017 +#include <asm/machdep.h>
18018 +#include <asm/asm-offsets.h>
18019 +#include <asm/thread.h>
18020 +#include <asm/devtree.h>
18022 +unsigned int irq_soft_avail;
18023 +static struct irqaction ubicom32_reserve_action[NR_IRQS];
18025 +#if !defined(CONFIG_DEBUG_IRQMEASURE)
18026 +#define IRQ_DECLARE_MEASUREMENT
18027 +#define IRQ_MEASUREMENT_START()
18028 +#define IRQ_MEASUREMENT_END(irq)
18030 +#define IRQ_DECLARE_MEASUREMENT \
18032 + unsigned int __tstart;
18034 +#define IRQ_MEASUREMENT_START() \
18035 + __tstart = UBICOM32_IO_TIMER->sysval;
18037 +#define IRQ_MEASUREMENT_END(irq) \
18038 + __diff = (int)UBICOM32_IO_TIMER->sysval - (int)__tstart; \
18039 + irq_measurement_update((irq), __diff);
18042 + * We keep track of the time spent in both irq_enter()
18043 + * and irq_exit().
18045 +#define IRQ_WEIGHT 32
18047 +struct irq_measurement {
18048 + volatile unsigned int min;
18049 + volatile unsigned int avg;
18050 + volatile unsigned int max;
18053 +static DEFINE_SPINLOCK(irq_measurement_lock);
18056 + * Add 1 in for softirq (irq_exit());
18058 +static struct irq_measurement irq_measurements[NR_IRQS + 1];
18061 + * irq_measurement_update()
18062 + * Update an entry in the measurement array for this irq.
18064 +static void irq_measurement_update(int irq, int sample)
18066 + struct irq_measurement *im = &irq_measurements[irq];
18067 + spin_lock(&irq_measurement_lock);
18068 + if ((im->min == 0) || (im->min > sample)) {
18069 + im->min = sample;
18071 + if (im->max < sample) {
18072 + im->max = sample;
18074 + im->avg = ((im->avg * (IRQ_WEIGHT - 1)) + sample) / IRQ_WEIGHT;
18075 + spin_unlock(&irq_measurement_lock);
18080 + * irq_kernel_stack_check()
18081 + * See if the kernel stack is within STACK_WARN of the end.
18083 +static void irq_kernel_stack_check(int irq, struct pt_regs *regs)
18085 +#ifdef CONFIG_DEBUG_STACKOVERFLOW
18086 + unsigned long sp;
18089 + * Make sure that we are not close to the top of the stack and thus
18090 + * can not really service this interrupt.
18093 + "and.4 %0, SP, %1 \n\t"
18095 + : "d" (THREAD_SIZE - 1)
18099 + if (sp < (sizeof(struct thread_info) + STACK_WARN)) {
18100 + printk(KERN_WARNING
18101 + "cpu[%d]: possible overflow detected sp remain: %p, "
18102 + "irq: %d, regs: %p\n",
18103 + thread_get_self(), (void *)sp, irq, regs);
18107 + if (sp < (sizeof(struct thread_info) + 16)) {
18115 + * Get the LSB set in value
18117 +static int irq_get_lsb(unsigned int value)
18119 + static unsigned char irq_bits[8] = {
18120 + 3, 0, 1, 0, 2, 0, 1, 0
18122 + u32_t nextbit = 0;
18124 + value = (value >> nextbit) | (value << ((sizeof(value) * 8) - nextbit));
18127 + * It's unlikely that we find that we execute the body of this while
18128 + * loop. 50% of the time we won't take this at all and then of the
18129 + * cases where we do about 50% of those we only execute once.
18131 + if (!(value & 0xffff)) {
18136 + if (!(value & 0xff)) {
18141 + if (!(value & 0xf)) {
18146 + nextbit += irq_bits[value & 0x7];
18147 + if (nextbit > 63) {
18148 + panic("nextbit out of range: %d\n", nextbit);
18154 + * ubicom32_reserve_handler()
18155 + * Bogus handler associated with pre-reserved IRQ(s).
18157 +static irqreturn_t ubicom32_reserve_handler(int irq, void *dev_id)
18160 + return IRQ_HANDLED;
18164 + * __irq_disable_vector()
18165 + * Disable the interrupt by clearing the appropriate bit in the
18166 + * LDSR Mask Register.
18168 +static void __irq_disable_vector(unsigned int irq)
18170 + ldsr_disable_vector(irq);
18174 + * __irq_ack_vector()
18175 + * Acknowledge the specific interrupt by clearing the associate bit in
18178 +static void __irq_ack_vector(unsigned int irq)
18181 + asm volatile ("move.4 INT_CLR0, %0" : : "d" (1 << irq));
18183 + asm volatile ("move.4 INT_CLR1, %0" : : "d" (1 << (irq - 32)));
18188 + * __irq_enable_vector()
18189 + * Clean and then enable the interrupt by setting the appropriate bit in
18190 + * the LDSR Mask Register.
18192 +static void __irq_enable_vector(unsigned int irq)
18195 + * Acknowledge, really clear the vector.
18197 + __irq_ack_vector(irq);
18198 + ldsr_enable_vector(irq);
18202 + * __irq_mask_vector()
18204 +static void __irq_mask_vector(unsigned int irq)
18206 + ldsr_mask_vector(irq);
18210 + * __irq_unmask_vector()
18212 +static void __irq_unmask_vector(unsigned int irq)
18214 + ldsr_unmask_vector(irq);
18218 + * __irq_end_vector()
18219 + * Called once an interrupt is completed (reset the LDSR mask).
18221 +static void __irq_end_vector(unsigned int irq)
18223 + ldsr_unmask_vector(irq);
18226 +#if defined(CONFIG_SMP)
18228 + * __irq_set_affinity()
18229 + * Set the cpu affinity for this interrupt.
18230 + * affinity container allocated at boot
18232 +static void __irq_set_affinity(unsigned int irq, const struct cpumask *dest)
18234 + smp_set_affinity(irq, dest);
18235 + cpumask_copy(irq_desc[irq].affinity, dest);
18240 + * On-Chip Generic Interrupt function handling.
18242 +static struct irq_chip ubicom32_irq_chip = {
18243 + .name = "Ubicom32",
18245 + .shutdown = NULL,
18246 + .enable = __irq_enable_vector,
18247 + .disable = __irq_disable_vector,
18248 + .ack = __irq_ack_vector,
18249 + .mask = __irq_mask_vector,
18250 + .unmask = __irq_unmask_vector,
18251 + .end = __irq_end_vector,
18252 +#if defined(CONFIG_SMP)
18253 + .set_affinity = __irq_set_affinity,
18259 + * Primary interface for handling IRQ() requests.
18261 +asmlinkage void do_IRQ(int irq, struct pt_regs *regs)
18263 + struct pt_regs *oldregs;
18264 + struct thread_info *ti = current_thread_info();
18266 + IRQ_DECLARE_MEASUREMENT;
18269 + * Mark that we are inside of an interrupt and
18270 + * that interrupts are disabled.
18272 + oldregs = set_irq_regs(regs);
18273 + ti->interrupt_nesting++;
18274 + trace_hardirqs_off();
18275 + irq_kernel_stack_check(irq, regs);
18278 + * Start the interrupt sequence
18283 + * Execute the IRQ handler and any pending SoftIRQ requests.
18285 + BUG_ON(!irqs_disabled());
18286 + IRQ_MEASUREMENT_START();
18288 + IRQ_MEASUREMENT_END(irq);
18289 + BUG_ON(!irqs_disabled());
18292 + * TODO: Since IRQ's are disabled when calling irq_exit()
18293 + * modify Kconfig to set __ARCH_IRQ_EXIT_IRQS_DISABLED flag.
18294 + * This will slightly improve performance by enabling
18295 + * softirq handling to avoid disabling/disabled interrupts.
18297 + IRQ_MEASUREMENT_START();
18299 + IRQ_MEASUREMENT_END(NR_IRQS);
18300 + BUG_ON(!irqs_disabled());
18303 + * Outside of an interrupt (or nested exit).
18305 + set_irq_regs(oldregs);
18306 + trace_hardirqs_on();
18307 + ti->interrupt_nesting--;
18311 + * irq_soft_alloc()
18312 + * Allocate a soft IRQ.
18314 +int irq_soft_alloc(unsigned int *soft)
18316 + if (irq_soft_avail == 0) {
18317 + printk(KERN_NOTICE "no soft irqs to allocate\n");
18321 + *soft = irq_get_lsb(irq_soft_avail);
18322 + irq_soft_avail &= ~(1 << *soft);
18328 + * Called to handle an bad irq request.
18330 +void ack_bad_irq(unsigned int irq)
18332 + printk(KERN_ERR "IRQ: unexpected irq=%d\n", irq);
18333 + __irq_end_vector(irq);
18337 + * show_interrupts()
18338 + * Return a string that displays the state of each of the interrupts.
18340 +int show_interrupts(struct seq_file *p, void *v)
18342 + struct irqaction *ap;
18343 + int irq = *((loff_t *) v);
18346 + if (irq >= NR_IRQS) {
18351 + seq_puts(p, " ");
18352 + for_each_online_cpu(j) {
18353 + seq_printf(p, "CPU%d ", j);
18355 + seq_putc(p, '\n');
18358 + ap = irq_desc[irq].action;
18360 + seq_printf(p, "%3d: ", irq);
18361 + for_each_online_cpu(j) {
18362 + seq_printf(p, "%10u ", kstat_irqs_cpu(irq, j));
18364 + seq_printf(p, "%14s ", irq_desc[irq].chip->name);
18365 + seq_printf(p, "%s", ap->name);
18366 + for (ap = ap->next; ap; ap = ap->next) {
18367 + seq_printf(p, ", %s", ap->name);
18369 + seq_putc(p, '\n');
18374 +#if defined(CONFIG_DEBUG_IRQMEASURE)
18375 +static unsigned int irq_cycles_to_micro(unsigned int cycles, unsigned int frequency)
18377 + unsigned int micro = (cycles / (frequency / 1000000));
18382 + * irq_measurement_show()
18383 + * Print out the min, avg, max values for each IRQ
18385 + * By request, the max value is reset after each dump.
18387 +static int irq_measurement_show(struct seq_file *p, void *v)
18389 + struct irqaction *ap;
18390 + unsigned int freq = processor_frequency();
18391 + int irq = *((loff_t *) v);
18395 + seq_puts(p, "\tmin\tavg\tmax\t(micro-seconds)\n");
18398 + if (irq > NR_IRQS) {
18402 + if (irq == NR_IRQS) {
18403 + unsigned int min, avg, max;
18404 + spin_lock(&irq_measurement_lock);
18405 + min = irq_cycles_to_micro(irq_measurements[irq].min, freq);
18406 + avg = irq_cycles_to_micro(irq_measurements[irq].avg, freq);
18407 + max = irq_cycles_to_micro(irq_measurements[irq].max, freq);
18408 + irq_measurements[irq].max = 0;
18409 + spin_unlock(&irq_measurement_lock);
18410 + seq_printf(p, " \t%u\t%u\t%u\tsoftirq\n", min, avg, max);
18414 + ap = irq_desc[irq].action;
18416 + unsigned int min, avg, max;
18417 + spin_lock(&irq_measurement_lock);
18418 + min = irq_cycles_to_micro(irq_measurements[irq].min, freq);
18419 + avg = irq_cycles_to_micro(irq_measurements[irq].avg, freq);
18420 + max = irq_cycles_to_micro(irq_measurements[irq].max, freq);
18421 + irq_measurements[irq].max = 0;
18422 + spin_unlock(&irq_measurement_lock);
18423 + seq_printf(p, "%2u:\t%u\t%u\t%u\t%s\n", irq, min, avg, max, ap->name);
18428 +static void *irq_measurement_start(struct seq_file *f, loff_t *pos)
18430 + return (*pos <= NR_IRQS) ? pos : NULL;
18433 +static void *irq_measurement_next(struct seq_file *f, void *v, loff_t *pos)
18436 + if (*pos > NR_IRQS)
18441 +static void irq_measurement_stop(struct seq_file *f, void *v)
18443 + /* Nothing to do */
18446 +static const struct seq_operations irq_measurement_seq_ops = {
18447 + .start = irq_measurement_start,
18448 + .next = irq_measurement_next,
18449 + .stop = irq_measurement_stop,
18450 + .show = irq_measurement_show,
18453 +static int irq_measurement_open(struct inode *inode, struct file *filp)
18455 + return seq_open(filp, &irq_measurement_seq_ops);
18458 +static const struct file_operations irq_measurement_fops = {
18459 + .open = irq_measurement_open,
18460 + .read = seq_read,
18461 + .llseek = seq_lseek,
18462 + .release = seq_release,
18465 +static int __init irq_measurement_init(void)
18467 + proc_create("irq_measurements", 0, NULL, &irq_measurement_fops);
18470 +module_init(irq_measurement_init);
18475 + * Initialize the on-chip IRQ subsystem.
18477 +void __init init_IRQ(void)
18480 + struct devtree_node *p = NULL;
18481 + struct devtree_node *iter = NULL;
18482 + unsigned int mask = 0;
18483 + unsigned int reserved = 0;
18486 + * Pull out the list of software interrupts that are avialable to
18487 + * Linux and provide an allocation function for them. The first
18488 + * 24 interrupts of INT0 are software interrupts.
18490 + irq_soft_avail = 0;
18491 + if (processor_interrupts(&irq_soft_avail, NULL) < 0) {
18492 + printk(KERN_WARNING "No Soft IRQ(s) available\n");
18494 + irq_soft_avail &= ((1 << 24) - 1);
18497 + * Initialize all of the on-chip interrupt handling
18498 + * to use a common set of interrupt functions.
18500 + for (irq = 0; irq < NR_IRQS; irq++) {
18501 + irq_desc[irq].status = IRQ_DISABLED;
18502 + irq_desc[irq].action = NULL;
18503 + irq_desc[irq].depth = 1;
18504 + set_irq_chip(irq, &ubicom32_irq_chip);
18508 + * The sendirq of a devnode is not registered within Linux but instead
18509 + * is used by the software I/O thread. These interrupts are reserved.
18510 + * The recvirq is used by Linux and registered by a device driver, these
18511 + * are not reserved.
18513 + * recvirq(s) that are in the software interrupt range are not supposed
18514 + * to be marked as reserved. We track this while we scan the device
18517 + p = devtree_find_next(&iter);
18519 + unsigned char sendirq, recvirq;
18520 + devtree_irq(p, &sendirq, &recvirq);
18523 + * If the sendirq is valid, mark that irq as taken by the
18526 + if (sendirq < NR_IRQS) {
18527 + ubicom32_reserve_action[sendirq].handler =
18528 + ubicom32_reserve_handler;
18529 + ubicom32_reserve_action[sendirq].name = p->name;
18530 + irq_desc[sendirq].action =
18531 + &ubicom32_reserve_action[sendirq];
18532 + mask |= (1 << sendirq);
18536 + * Track the relevant recieve IRQ(s)
18538 + if (recvirq < 24) {
18539 + mask |= (1 << recvirq);
18543 + * Move to the next node.
18545 + p = devtree_find_next(&iter);
18549 + * Remove these bits from the irq_soft_avail list and then use the
18550 + * result as the list of pre-reserved IRQ(s).
18552 + reserved = ~irq_soft_avail & ~mask;
18553 + for (irq = 0; irq < 24; irq++) {
18554 + if ((reserved & (1 << irq))) {
18555 + ubicom32_reserve_action[irq].handler =
18556 + ubicom32_reserve_handler;
18557 + ubicom32_reserve_action[irq].name = "reserved";
18558 + irq_desc[irq].action = &ubicom32_reserve_action[irq];
18563 + * Initialize the LDSR which is the Ubicom32 programmable
18564 + * interrupt controller.
18569 + * The Ubicom trap code needs a 2nd init after IRQ(s) are setup.
18571 + trap_init_interrupt();
18573 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/ldsr.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/ldsr.c
18574 --- linux-2.6.30.10/arch/ubicom32/kernel/ldsr.c 1970-01-01 02:00:00.000000000 +0200
18575 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/ldsr.c 2009-12-11 11:45:11.000000000 +0200
18578 + * arch/ubicom32/kernel/ldsr.c
18579 + * Ubicom32 architecture Linux Device Services Driver Interface
18581 + * (C) Copyright 2009, Ubicom, Inc.
18583 + * This file is part of the Ubicom32 Linux Kernel Port.
18585 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
18586 + * it and/or modify it under the terms of the GNU General Public License
18587 + * as published by the Free Software Foundation, either version 2 of the
18588 + * License, or (at your option) any later version.
18590 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
18591 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
18592 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
18593 + * the GNU General Public License for more details.
18595 + * You should have received a copy of the GNU General Public License
18596 + * along with the Ubicom32 Linux Kernel Port. If not,
18597 + * see <http://www.gnu.org/licenses/>.
18599 + * Ubicom32 implementation derived from (with many thanks):
18606 + * The LDSR is a programmable interrupt controller that is written in software.
18607 + * It emulates the behavior of an pic by fielding the interrupts, choosing a
18608 + * victim thread to take the interrupt and forcing that thread to take a context
18609 + * switch to the appropriate interrupt handler.
18611 + * Because traps are treated as just a special class of interrupts, the LDSR
18612 + * also handles the processing of traps.
18614 + * Because we compile Linux both UP and SMP, we need the LDSR to use
18615 + * architectural locking that is not "compiled out" when compiling UP. For now,
18616 + * we use the single atomic bit lock.
18618 +#include <linux/kernel.h>
18619 +#include <linux/init.h>
18620 +#include <linux/sched.h>
18621 +#include <linux/interrupt.h>
18622 +#include <linux/irq.h>
18623 +#include <linux/profile.h>
18624 +#include <linux/clocksource.h>
18625 +#include <linux/types.h>
18626 +#include <linux/module.h>
18627 +#include <linux/cpumask.h>
18628 +#include <linux/bug.h>
18629 +#include <linux/delay.h>
18630 +#include <asm/ip5000.h>
18631 +#include <asm/atomic.h>
18632 +#include <asm/machdep.h>
18633 +#include <asm/asm-offsets.h>
18634 +#include <asm/traps.h>
18635 +#include <asm/thread.h>
18636 +#include <asm/range-protect.h>
18639 + * One can not print from the LDSR so the best we can do is
18640 + * check a condition and stall all of the threads.
18643 +// #define DEBUG_LDSR 1
18644 +#if defined(DEBUG_LDSR)
18645 +#define DEBUG_ASSERT(cond) \
18650 +#define DEBUG_ASSERT(cond)
18654 + * Make global so that we can use it in the RFI code in assembly.
18656 +unsigned int ldsr_soft_irq_mask;
18657 +EXPORT_SYMBOL(ldsr_soft_irq_mask);
18659 +static unsigned int ldsr_suspend_mask;
18660 +static unsigned int ldsr_soft_irq;
18661 +static unsigned int ldsr_stack_space[1024];
18663 +static struct ldsr_register_bank {
18664 + volatile unsigned int enabled0;
18665 + volatile unsigned int enabled1;
18666 + volatile unsigned int mask0;
18667 + volatile unsigned int mask1;
18668 + unsigned int total;
18669 + unsigned int retry;
18670 + unsigned int backout;
18674 + * Which thread/cpu are we?
18676 +static int ldsr_tid = -1;
18678 +#if defined(CONFIG_IRQSTACKS)
18680 + * per-CPU IRQ stacks (thread information and stack)
18682 + * NOTE: Do not use DEFINE_PER_CPU() as it makes it harder
18683 + * to find the location of ctx from assembly language.
18686 + struct thread_info tinfo;
18687 + u32 stack[THREAD_SIZE/sizeof(u32)];
18689 +static union irq_ctx *percpu_irq_ctxs[NR_CPUS];
18692 + * Storage for the interrupt stack.
18694 +#if !defined(CONFIG_IRQSTACKS_USEOCM)
18695 +static char percpu_irq_stacks[(NR_CPUS * THREAD_SIZE) + (THREAD_SIZE - 1)];
18698 + * For OCM, the linker will ensure that space is allocated for the stack
18699 + * see (vmlinux.lds.S)
18701 +static char percpu_irq_stacks[];
18707 + * Save trap IRQ because we need to un-suspend if it gets set.
18709 +static unsigned int ldsr_trap_irq_mask;
18710 +static unsigned int ldsr_trap_irq;
18713 + * ret_from_interrupt_to_kernel
18714 + * Just restore the context and do nothing else.
18716 +asmlinkage void ret_from_interrupt_to_kernel(void)__attribute__((naked));
18719 + * ret_from_interrupt_to_user
18720 + * Call scheduler if needed. Just restore the context.
18722 +asmlinkage void ret_from_interrupt_to_user(void)__attribute__((naked));
18725 +u32_t old_sp, old_pc, old_a0, old_a5, old_a3;
18726 +struct pt_regs copy_regs, *copy_save_area;
18729 +int __user_mode(unsigned long sp)
18732 + u32_t saved_stack_base = sp & ~(ASM_THREAD_SIZE - 1);
18733 +#if defined(CONFIG_IRQSTACKS_USEOCM)
18734 + if ((union irq_ctx *)saved_stack_base == percpu_irq_ctxs[smp_processor_id()]) {
18736 + * On the interrupt stack.
18742 + if (!(u32_t)current) {
18745 + return saved_stack_base != ((u32_t)current->stack);
18749 + * ldsr_lock_release()
18750 + * Release the LDSR lock.
18752 +static void ldsr_lock_release(void)
18754 + UBICOM32_UNLOCK(LDSR_LOCK_BIT);
18758 + * ldsr_lock_acquire()
18759 + * Acquire the LDSR lock, spin if not available.
18761 +static void ldsr_lock_acquire(void)
18763 + UBICOM32_LOCK(LDSR_LOCK_BIT);
18767 + * ldsr_thread_irq_disable()
18768 + * Disable interrupts for the specified thread.
18770 +static void ldsr_thread_irq_disable(unsigned int tid)
18772 + unsigned int mask = (1 << tid);
18775 + " or.4 scratchpad1, scratchpad1, %0 \n\t"
18783 + * ldsr_thread_get_interrupts()
18784 + * Get the interrupt state for all threads.
18786 +static unsigned long ldsr_thread_get_interrupts(void)
18788 + unsigned long ret = 0;
18790 + " move.4 %0, scratchpad1 \n\t"
18798 + * ldsr_emulate_and_run()
18799 + * Emulate the instruction and then set the thread to run.
18801 +static void ldsr_emulate_and_run(unsigned int tid)
18803 + unsigned int thread_mask = (1 << tid);
18804 + u32_t write_csr = (tid << 15) | (1 << 14);
18807 + * Emulate the unaligned access.
18809 + unaligned_emulate(tid);
18812 + * Get the thread back in a running state.
18815 + " setcsr %0 \n\t"
18816 + " setcsr_flush 0 \n\t"
18817 + " move.4 trap_cause, #0 \n\t" /* Clear the trap cause
18819 + " setcsr #0 \n\t"
18820 + " setcsr_flush 0 \n\t"
18821 + " move.4 mt_dbg_active_set, %1 \n\t" /* Activate thread even if
18822 + * in dbg/fault state */
18823 + " move.4 mt_active_set, %1 \n\t" /* Restart target
18826 + : "r" (write_csr), "d" (thread_mask)
18829 + thread_enable_mask(thread_mask);
18833 + * ldsr_preemptive_context_save()
18834 + * save thread context from another hardware thread. The other thread must
18837 +static inline void ldsr_preemptive_context_save(u32_t thread,
18838 + struct pt_regs *regs)
18841 + * Save the current state of the specified thread
18844 + " move.4 a3, %0 \n\t"
18846 + /* set src1 from the target thread */
18847 + " move.4 csr, %1 \n\t"
18848 + " setcsr_flush 0 \n\t"
18849 + " setcsr_flush 0 \n\t"
18851 + /* copy state from the other thread */
18852 + " move.4 "D(PT_D0)"(a3), d0 \n\t"
18853 + " move.4 "D(PT_D1)"(a3), d1 \n\t"
18854 + " move.4 "D(PT_D2)"(a3), d2 \n\t"
18855 + " move.4 "D(PT_D3)"(a3), d3 \n\t"
18856 + " move.4 "D(PT_D4)"(a3), d4 \n\t"
18857 + " move.4 "D(PT_D5)"(a3), d5 \n\t"
18858 + " move.4 "D(PT_D6)"(a3), d6 \n\t"
18859 + " move.4 "D(PT_D7)"(a3), d7 \n\t"
18860 + " move.4 "D(PT_D8)"(a3), d8 \n\t"
18861 + " move.4 "D(PT_D9)"(a3), d9 \n\t"
18862 + " move.4 "D(PT_D10)"(a3), d10 \n\t"
18863 + " move.4 "D(PT_D11)"(a3), d11 \n\t"
18864 + " move.4 "D(PT_D12)"(a3), d12 \n\t"
18865 + " move.4 "D(PT_D13)"(a3), d13 \n\t"
18866 + " move.4 "D(PT_D14)"(a3), d14 \n\t"
18867 + " move.4 "D(PT_D15)"(a3), d15 \n\t"
18868 + " move.4 "D(PT_A0)"(a3), a0 \n\t"
18869 + " move.4 "D(PT_A1)"(a3), a1 \n\t"
18870 + " move.4 "D(PT_A2)"(a3), a2 \n\t"
18871 + " move.4 "D(PT_A3)"(a3), a3 \n\t"
18872 + " move.4 "D(PT_A4)"(a3), a4 \n\t"
18873 + " move.4 "D(PT_A5)"(a3), a5 \n\t"
18874 + " move.4 "D(PT_A6)"(a3), a6 \n\t"
18875 + " move.4 "D(PT_SP)"(a3), a7 \n\t"
18876 + " move.4 "D(PT_ACC0HI)"(a3), acc0_hi \n\t"
18877 + " move.4 "D(PT_ACC0LO)"(a3), acc0_lo \n\t"
18878 + " move.4 "D(PT_MAC_RC16)"(a3), mac_rc16 \n\t"
18879 + " move.4 "D(PT_ACC1HI)"(a3), acc1_hi \n\t"
18880 + " move.4 "D(PT_ACC1LO)"(a3), acc1_lo \n\t"
18881 + " move.4 "D(PT_SOURCE3)"(a3), source3 \n\t"
18882 + " move.4 "D(PT_INST_CNT)"(a3), inst_cnt \n\t"
18883 + " move.4 "D(PT_CSR)"(a3), csr \n\t"
18884 + " move.4 "D(PT_DUMMY_UNUSED)"(a3), #0 \n\t"
18885 + " move.4 "D(PT_INT_MASK0)"(a3), int_mask0 \n\t"
18886 + " move.4 "D(PT_INT_MASK1)"(a3), int_mask1 \n\t"
18887 + " move.4 "D(PT_TRAP_CAUSE)"(a3), trap_cause \n\t"
18888 + " move.4 "D(PT_PC)"(a3), pc \n\t"
18889 + " move.4 "D(PT_PREVIOUS_PC)"(a3), previous_pc \n\t"
18890 + /* disable csr thread select */
18891 + " movei csr, #0 \n\t"
18892 + " setcsr_flush 0 \n\t"
18894 + : "r" (regs->dn), "d" ((thread << 9) | (1 << 8))
18900 + * ldsr_rotate_threads()
18901 + * Simple round robin algorithm for choosing the next cpu
18903 +static int ldsr_rotate_threads(unsigned long cpus)
18905 + static unsigned char ldsr_bits[8] = {
18906 + 3, 0, 1, 0, 2, 0, 1, 0
18909 + static int nextbit;
18913 + * Move the interrupts down so that we consider interrupts from where
18914 + * we left off, then take the interrupts we would lose and move them
18915 + * to the top half of the interrupts value.
18917 + cpus = (cpus >> nextbit) | (cpus << ((sizeof(cpus) * 8) - nextbit));
18920 + * 50% of the time we won't take this at all and then of the cases where
18921 + * we do about 50% of those we only execute once.
18923 + if (!(cpus & 0xffff)) {
18928 + if (!(cpus & 0xff)) {
18933 + if (!(cpus & 0xf)) {
18938 + nextbit += ldsr_bits[cpus & 0x7];
18939 + thisbit = (nextbit & ((sizeof(cpus) * 8) - 1));
18940 + nextbit = (thisbit + 1) & ((sizeof(cpus) * 8) - 1);
18941 + DEBUG_ASSERT(thisbit < THREAD_ARCHITECTURAL_MAX);
18946 + * ldsr_rotate_interrupts()
18947 + * Get rotating next set bit value.
18949 +static int ldsr_rotate_interrupts(unsigned long long interrupts)
18951 + static unsigned char ldsr_bits[8] = {
18952 + 3, 0, 1, 0, 2, 0, 1, 0
18955 + static int nextbit;
18959 + * Move the interrupts down so that we consider interrupts from where
18960 + * we left off, then take the interrupts we would lose and move them
18961 + * to the top half of the interrupts value.
18963 + interrupts = (interrupts >> nextbit) |
18964 + (interrupts << ((sizeof(interrupts) * 8) - nextbit));
18967 + * 50% of the time we won't take this at all and then of the cases where
18968 + * we do about 50% of those we only execute once.
18970 + if (!(interrupts & 0xffffffff)) {
18972 + interrupts >>= 32;
18975 + if (!(interrupts & 0xffff)) {
18977 + interrupts >>= 16;
18980 + if (!(interrupts & 0xff)) {
18982 + interrupts >>= 8;
18985 + if (!(interrupts & 0xf)) {
18987 + interrupts >>= 4;
18990 + nextbit += ldsr_bits[interrupts & 0x7];
18991 + thisbit = (nextbit & ((sizeof(interrupts) * 8) - 1));
18992 + nextbit = (thisbit + 1) & ((sizeof(interrupts) * 8) - 1);
18994 + DEBUG_ASSERT(thisbit < (sizeof(interrupts) * 8));
18999 + * ldsr_backout_or_irq()
19001 + * One way or the other this interrupt is not being
19002 + * processed, make sure that it is reset. We are
19003 + * not going to call irq_end_vector() so unmask the
19006 +static void ldsr_backout_of_irq(int vector, unsigned long tid_mask)
19008 +#if defined(CONFIG_SMP)
19009 + if (unlikely(vector == smp_ipi_irq)) {
19010 + smp_reset_ipi(tid_mask);
19013 + ldsr_unmask_vector(vector);
19014 + ldsr_interrupt.backout++;
19017 +#if defined(CONFIG_IRQSTACKS)
19019 + * ldsr_choose_savearea_and_returnvec()
19020 + * Test our current state (user, kernel, interrupt) and set things up.
19022 + * This version of the function uses 3 stacks and nests interrupts
19023 + * on the interrupt stack.
19025 +static struct pt_regs *ldsr_choose_savearea_and_returnvec(thread_t tid, u32_t linux_sp, u32_t *pvec)
19027 + struct pt_regs *save_area;
19028 + u32_t masked_linux_sp = linux_sp & ~(THREAD_SIZE - 1);
19029 + struct thread_info * ti= (struct thread_info *)sw_ksp[tid];
19031 +#if defined(CONFIG_SMP)
19032 + union irq_ctx *icp = percpu_irq_ctxs[tid];
19034 + union irq_ctx *icp = percpu_irq_ctxs[0];
19037 + if (masked_linux_sp == (u32_t)icp) {
19039 + * Fault/Interrupt occurred while on the interrupt stack.
19041 + save_area = (struct pt_regs *)((char *)linux_sp - sizeof(struct pt_regs) - 8);
19042 + *pvec = (u32_t)(&ret_from_interrupt_to_kernel);
19045 + * Fault/Interrupt occurred while on user/kernel stack. This is a new
19046 + * first use of the interrupt stack.
19048 + save_area = (struct pt_regs *) ((char *)icp + sizeof(icp->stack) - sizeof(struct pt_regs) - 8);
19049 + if (masked_linux_sp == (u32_t)ti) {
19050 + *pvec = (u32_t)(&ret_from_interrupt_to_kernel);
19052 + *pvec = (u32_t)(&ret_from_interrupt_to_user);
19056 + * Because the softirq code will execute on the "interrupt" stack, we
19057 + * need to maintain the knowledge of what "task" was executing on the
19058 + * cpu. This is done by copying the thread_info->task from the cpu
19059 + * we are about to context switch into the interrupt contexts thread_info
19062 + icp->tinfo.task = ti->task;
19063 + icp->tinfo.preempt_count =
19064 + (icp->tinfo.preempt_count & ~SOFTIRQ_MASK) |
19065 + (ti->preempt_count & SOFTIRQ_MASK);
19066 + icp->tinfo.interrupt_nesting = 0;
19068 + save_area->nesting_level = icp->tinfo.interrupt_nesting;
19069 + return save_area;
19074 + * ldsr_choose_savearea_and_returnvec()
19075 + * Test our current state (user, kernel, interrupt) and set things up.
19077 + * The version of the function uses just the user & kernel stack and
19078 + * nests interrupts on the existing kernel stack.
19080 +static struct pt_regs *ldsr_choose_savearea_and_returnvec(thread_t tid, u32_t linux_sp, u32_t *pvec)
19082 + struct pt_regs *save_area;
19083 + u32_t masked_linux_sp = linux_sp & ~(THREAD_SIZE - 1);
19084 + struct thread_info *ti = (struct thread_info *)sw_ksp[tid];
19086 + if (masked_linux_sp == (u32_t)ti) {
19088 + * Fault/Interrupt occurred while on the kernel stack.
19090 + save_area = (struct pt_regs *)((char *)linux_sp - sizeof(struct pt_regs) - 8);
19091 + *pvec = (u32_t) (&ret_from_interrupt_to_kernel);
19094 + * Fault/Interrupt occurred while on user stack.
19096 + ti->interrupt_nesting = 0;
19097 + save_area = (struct pt_regs *)((u32_t)ti + THREAD_SIZE - sizeof(struct pt_regs) - 8);
19098 + *pvec = (u32_t) (&ret_from_interrupt_to_user);
19100 + save_area->nesting_level = ti->interrupt_nesting;
19101 + return save_area;
19106 + * ldsr_ctxsw_thread()
19107 + * Context switch a mainline thread to execute do_IRQ() for the specified
19110 +static void ldsr_ctxsw_thread(int vector, thread_t tid)
19113 + u32_t return_vector;
19114 + struct pt_regs *save_area, *regs;
19115 + u32_t thread_mask = (1 << tid);
19116 + u32_t read_csr = ((tid << 9) | (1 << 8));
19117 + u32_t write_csr = (tid << 15) | (1 << 14);
19118 + u32_t interrupt_vector = (u32_t)(&do_IRQ);
19120 + unsigned int frame_type = UBICOM32_FRAME_TYPE_INTERRUPT;
19123 + DEBUG_ASSERT(!thread_is_enabled(tid));
19126 + * Acquire the necessary global and per thread locks for tid.
19127 + * As a side effect, we ensure that the thread has not trapped
19128 + * and return true if it has.
19130 + if (unlikely(thread_is_trapped(tid))) {
19132 + * Read the trap cause, the sp and clear the MT_TRAP bits.
19134 + unsigned int cause;
19136 + " setcsr %3 \n\t"
19137 + " setcsr_flush 0 \n\t"
19138 + " setcsr_flush 0 \n\t"
19139 + " move.4 %0, TRAP_CAUSE \n\t"
19140 + " move.4 %1, SP \n\t"
19141 + " setcsr #0 \n\t"
19142 + " setcsr_flush 0 \n\t"
19143 + " move.4 MT_BREAK_CLR, %2\n\t"
19144 + " move.4 MT_TRAP_CLR, %2 \n\t"
19145 + : "=&r" (cause), "=&r" (linux_sp)
19146 + : "r" (thread_mask), "m" (read_csr)
19149 + ldsr_backout_of_irq(vector, (1 << tid));
19151 +#if !defined(CONFIG_UNALIGNED_ACCESS_DISABLED)
19153 + * See if the unaligned trap handler can deal with this.
19154 + * If so, emulate the instruction and then just restart
19157 + if (unaligned_only(cause)) {
19158 +#if defined(CONFIG_UNALIGNED_ACCESS_USERSPACE_ONLY)
19160 + * Check if this is a kernel stack if so we will not
19161 + * handle the trap
19163 + u32_t masked_linux_sp = linux_sp & ~(THREAD_SIZE - 1);
19164 + if ((masked_linux_sp != (u32_t)sw_ksp[tid]) &&
19165 + unaligned_only(cause)) {
19166 + ldsr_emulate_and_run(tid);
19170 + ldsr_emulate_and_run(tid);
19177 + interrupt_vector = (u32_t)(&trap_handler);
19178 + frame_type = UBICOM32_FRAME_TYPE_TRAP;
19181 + * Read the target thread's SP
19184 + " setcsr %1 \n\t"
19185 + " setcsr_flush 0 \n\t"
19186 + " setcsr_flush 0 \n\t"
19187 + " move.4 %0, SP \n\t"
19188 + " setcsr #0 \n\t"
19189 + " setcsr_flush 0 \n\t"
19190 + : "=m" (linux_sp)
19196 + * We are delivering an interrupt, count it.
19198 + ldsr_interrupt.total++;
19201 + * At this point, we will definitely force this thread to
19202 + * a new context, show its interrupts as disabled.
19204 + ldsr_thread_irq_disable(tid);
19207 + * Test our current state (user, kernel, interrupt). Save the
19208 + * appropriate data and setup for the return.
19210 + save_area = ldsr_choose_savearea_and_returnvec(tid, linux_sp, &return_vector);
19213 + * The pt_regs (save_area) contains the type of thread that we are dealing
19214 + * with (KERNEL/NORMAL) and is copied into each pt_regs area. We get this
19215 + * from the current tasks kernel pt_regs area that always exists at the
19216 + * top of the kernel stack.
19218 + regs = (struct pt_regs *)((u32_t)sw_ksp[tid] + THREAD_SIZE - sizeof(struct pt_regs) - 8);
19219 + save_area->thread_type = regs->thread_type;
19222 + * Preserve the context of the Linux thread.
19224 + ldsr_preemptive_context_save(tid, save_area);
19227 + * Load the fram_type into the save_area.
19229 + save_area->frame_type = frame_type;
19231 +#ifdef CONFIG_STOP_ON_TRAP
19233 + * Before we get backtrace and showing stacks working well, it sometimes
19234 + * helps to enter the debugger when a trap occurs before we change the
19235 + * thread to handle the fault. This optional code causes all threads to
19236 + * stop on every trap frame. One assumes that GDB connected via the
19237 + * mailbox interface will be used to recover from this state.
19239 + if (frame_type == UBICOM32_FRAME_TYPE_TRAP) {
19245 + copy_regs = *save_area;
19246 + copy_save_area = save_area;
19248 + old_a0 = save_area->an[0];
19249 + old_a3 = save_area->an[3];
19250 + old_sp = save_area->an[7];
19251 + old_a5 = save_area->an[5];
19252 + old_pc = save_area->pc;
19256 + * Now we have to switch the kernel thread to run do_IRQ function.
19257 + * Set pc to do_IRQ
19258 + * Set d0 to vector
19259 + * Set d1 to save_area.
19260 + * Set a5 to the proper return vector.
19263 + " setcsr %0 \n\t"
19264 + " setcsr_flush 0 \n\t"
19265 + " move.4 d0, %5 \n\t" /* d0 = 0 vector # */
19266 + " move.4 d1, %1 \n\t" /* d1 = save_area */
19267 + " move.4 sp, %1 \n\t" /* sp = save_area */
19268 + " move.4 a5, %2 \n\t" /* a5 = return_vector */
19269 + " move.4 pc, %3 \n\t" /* pc = do_IRQ routine. */
19270 + " move.4 trap_cause, #0 \n\t" /* Clear the trap cause
19272 + " setcsr #0 \n\t"
19273 + " setcsr_flush 0 \n\t"
19274 + " enable_kernel_ranges %4 \n\t"
19275 + " move.4 mt_dbg_active_set, %4 \n\t" /* Activate thread even if
19276 + * in dbg/fault state */
19277 + " move.4 mt_active_set, %4 \n\t" /* Restart target
19280 + : "r" (write_csr), "r" (save_area),
19281 + "r" (return_vector), "r" (interrupt_vector),
19282 + "d" (thread_mask), "r" (vector)
19285 + thread_enable_mask(thread_mask);
19289 + * ldsr_deliver_interrupt()
19290 + * Deliver the interrupt to one of the threads or all of the threads.
19292 +static void ldsr_deliver_interrupt(int vector,
19293 + unsigned long deliver_to,
19296 + unsigned long disabled_threads;
19297 + unsigned long possible_threads;
19298 + unsigned long trapped_threads;
19299 + unsigned long global_locks;
19302 + * Disable all of the threads that we might want to send
19303 + * this interrupt to.
19306 + DEBUG_ASSERT(deliver_to);
19307 + thread_disable_mask(deliver_to);
19310 + * If any threads are in the trap state, we have to service the
19311 + * trap for those threads first.
19314 + "move.4 %0, MT_TRAP \n\t"
19315 + : "=r" (trapped_threads)
19319 + trapped_threads &= deliver_to;
19320 + if (unlikely(trapped_threads)) {
19322 + * all traps will be handled, so clear the trap bit before restarting any threads
19324 + ubicom32_clear_interrupt(ldsr_trap_irq);
19327 + * Let the remaining untrapped threads, continue.
19329 + deliver_to &= ~trapped_threads;
19330 + if (deliver_to) {
19331 + thread_enable_mask(deliver_to);
19335 + * For the trapped threads force them to handle
19338 + while (trapped_threads) {
19339 + unsigned long which = ffz(~trapped_threads);
19340 + trapped_threads &= ~(1 << which);
19341 + ldsr_ctxsw_thread(vector, which);
19347 + * Can we deliver an interrupt to any of the threads?
19349 + disabled_threads = ldsr_thread_get_interrupts();
19350 + possible_threads = deliver_to & ~disabled_threads;
19351 + if (unlikely(!possible_threads)) {
19352 +#if defined(CONFIG_SMP)
19354 + * In the SMP case, we can not wait because 1 cpu might be
19355 + * sending an IPI to another cpu which is currently blocked.
19356 + * The only way to ensure IPI delivery is to backout and
19357 + * keep trying. For SMP, we don't sleep until the interrupts
19360 + thread_enable_mask(deliver_to);
19361 + ldsr_backout_of_irq(vector, deliver_to);
19365 + * In the UP case, we have nothing to do so we should wait.
19367 + * Since the INT_MASK0 and INT_MASK1 are "re-loaded" before we
19368 + * suspend in the outer loop, we do not need to save them here.
19370 + * We test that we were awakened for our specific interrupts
19371 + * because the ldsr mask/unmask operations will force the ldsr
19372 + * awake even if the interrupt on the mainline thread is not
19375 + unsigned int scratch = 0;
19376 + thread_enable_mask(deliver_to);
19378 + " move.4 INT_MASK0, %1 \n\t"
19379 + " move.4 INT_MASK1, #0 \n\t"
19381 + "1: suspend \n\t"
19382 + " move.4 %0, INT_STAT0 \n\t"
19383 + " and.4 %0, %0, %1 \n\t"
19384 + " jmpeq.f 1b \n\t"
19386 + " move.4 INT_CLR0, %2 \n\t"
19388 + : "d" (ldsr_suspend_mask), "r" (ldsr_soft_irq_mask)
19393 + * This delay is sized to coincide with the time it takes a
19394 + * thread to complete the exit (see return_from_interrupt).
19396 + ldsr_interrupt.retry++;
19403 + * If any of the global locks are held, we can not deliver any
19404 + * interrupts, we spin delay(10) and then try again. If our
19405 + * spinning becomes a bottle neck, we will need to suspend but for
19406 + * now lets just spin.
19409 + "move.4 %0, scratchpad1 \n\t"
19410 + : "=r" (global_locks)
19413 + if (unlikely(global_locks & 0xffff0000)) {
19414 + thread_enable_mask(deliver_to);
19417 + * This delay is sized to coincide with the average time it
19418 + * takes a thread to release a global lock.
19420 + ldsr_interrupt.retry++;
19426 + * Deliver to one cpu.
19430 + * Find our victim and then enable everyone else.
19432 + unsigned long victim = ldsr_rotate_threads(possible_threads);
19433 + DEBUG_ASSERT((deliver_to & (1 << victim)));
19434 + DEBUG_ASSERT((possible_threads & (1 << victim)));
19436 + deliver_to &= ~(1 << victim);
19437 + if (deliver_to) {
19438 + thread_enable_mask(deliver_to);
19440 + ldsr_ctxsw_thread(vector, victim);
19445 + * If we can't deliver to some threads, wake them
19446 + * back up and reset things to deliver to them.
19448 + deliver_to &= ~possible_threads;
19449 + if (unlikely(deliver_to)) {
19450 + thread_enable_mask(deliver_to);
19451 + ldsr_backout_of_irq(vector, deliver_to);
19455 + * Deliver to all possible threads(s).
19457 + while (possible_threads) {
19458 + unsigned long victim = ffz(~possible_threads);
19459 + possible_threads &= ~(1 << victim);
19460 + ldsr_ctxsw_thread(vector, victim);
19466 + * This thread acts as the interrupt controller for Linux.
19468 +static void ldsr_thread(void *arg)
19474 + long long interrupts;
19475 + unsigned long cpus;
19477 +#if !defined(CONFIG_SMP)
19479 + * In a non-smp configuration, we can not use the cpu(s) arrays because
19480 + * there is not a 1-1 correspondence between cpus(s) and our threads.
19481 + * Thus we must get a local idea of the mainline threads and use the
19482 + * one and only 1 set as the victim. We do this once before the ldsr
19485 + * In the SMP case, we will use the cpu(s) map to determine which cpu(s)
19486 + * are valid to send interrupts to.
19489 + unsigned int mainline = thread_get_mainline();
19490 + if (mainline == 0) {
19491 + panic("no mainline Linux threads to interrupt");
19494 + victim = ffz(~mainline);
19495 + cpus = (1 << victim);
19500 + * If one changes this code not to reload the INT_MASK(s), you
19501 + * need to know that code in the lock waiting above does not
19502 + * reset the MASK registers back; so that code will need to be
19505 + ldsr_lock_acquire();
19507 + " move.4 INT_MASK0, %0 \n\t"
19508 + " move.4 INT_MASK1, %1 \n\t"
19510 + : "U4" (ldsr_interrupt.mask0), "U4" (ldsr_interrupt.mask1)
19512 + ldsr_lock_release();
19513 + thread_suspend();
19516 + * Read the interrupt status registers
19519 + "move.4 %0, INT_STAT0 \n\t"
19520 + "move.4 %1, INT_STAT1 \n\t"
19521 + : "=r" (stat0), "=r" (stat1)
19526 + * We only care about interrupts that we have been told to care
19527 + * about. The interrupt must be enabled, unmasked, and have
19528 + * occurred in the hardware.
19530 + ldsr_lock_acquire();
19531 + interrupt0 = ldsr_interrupt.enabled0 &
19532 + ldsr_interrupt.mask0 & stat0;
19533 + interrupt1 = ldsr_interrupt.enabled1 &
19534 + ldsr_interrupt.mask1 & stat1;
19535 + ldsr_lock_release();
19538 + * For each interrupt in the "snapshot" we will mask the
19539 + * interrupt handle the interrupt (typically calling do_IRQ()).
19541 + * The interrupt is unmasked by desc->chip->end() function in
19542 + * the per chip generic interrupt handling code
19543 + * (arch/ubicom32/kernel/irq.c).8
19545 + interrupts = ((unsigned long long)interrupt1 << 32) |
19547 + while (interrupts) {
19549 + int vector = ldsr_rotate_interrupts(interrupts);
19550 + interrupts &= ~((unsigned long long)1 << vector);
19553 + * Now mask off this vector so that the LDSR ignores
19554 + * it until it is acknowledged.
19556 + ldsr_mask_vector(vector);
19557 +#if !defined(CONFIG_SMP)
19558 + ldsr_deliver_interrupt(vector, cpus, all);
19560 + cpus = smp_get_affinity(vector, &all);
19563 + * No CPU to deliver to so just leave
19564 + * the interrupt unmasked and increase
19565 + * the backout count. We will eventually
19566 + * return and deliver it again.
19568 + ldsr_unmask_vector(vector);
19569 + ldsr_interrupt.backout++;
19572 + ldsr_deliver_interrupt(vector, cpus, all);
19581 + * ldsr_mask_vector()
19582 + * Temporarily mask the interrupt vector, turn off the bit in the mask
19585 +void ldsr_mask_vector(unsigned int vector)
19587 + unsigned int mask;
19588 + if (vector < 32) {
19589 + mask = ~(1 << vector);
19590 + ldsr_lock_acquire();
19591 + ldsr_interrupt.mask0 &= mask;
19592 + ldsr_lock_release();
19593 + thread_resume(ldsr_tid);
19597 + mask = ~(1 << (vector - 32));
19598 + ldsr_lock_acquire();
19599 + ldsr_interrupt.mask1 &= mask;
19600 + ldsr_lock_release();
19601 + thread_resume(ldsr_tid);
19605 + * ldsr_unmask_vector()
19606 + * Unmask the interrupt vector so that it can be used, turn on the bit in
19607 + * the mask register.
19609 + * Because it is legal for the interrupt path to disable an interrupt,
19610 + * the unmasking code must ensure that disabled interrupts are not
19613 +void ldsr_unmask_vector(unsigned int vector)
19615 + unsigned int mask;
19616 + if (vector < 32) {
19617 + mask = (1 << vector);
19618 + ldsr_lock_acquire();
19619 + ldsr_interrupt.mask0 |= (mask & ldsr_interrupt.enabled0);
19620 + ldsr_lock_release();
19621 + thread_resume(ldsr_tid);
19625 + mask = (1 << (vector - 32));
19626 + ldsr_lock_acquire();
19627 + ldsr_interrupt.mask1 |= (mask & ldsr_interrupt.enabled1);
19628 + ldsr_lock_release();
19629 + thread_resume(ldsr_tid);
19633 + * ldsr_enable_vector()
19634 + * The LDSR implements an interrupt controller and has a local (to the
19635 + * LDSR) copy of its interrupt mask.
19637 +void ldsr_enable_vector(unsigned int vector)
19639 + unsigned int mask;
19640 + if (vector < 32) {
19641 + mask = (1 << vector);
19642 + ldsr_lock_acquire();
19643 + ldsr_interrupt.enabled0 |= mask;
19644 + ldsr_interrupt.mask0 |= mask;
19645 + ldsr_lock_release();
19646 + thread_resume(ldsr_tid);
19650 + mask = (1 << (vector - 32));
19651 + ldsr_lock_acquire();
19652 + ldsr_interrupt.enabled1 |= mask;
19653 + ldsr_interrupt.mask1 |= mask;
19654 + ldsr_lock_release();
19655 + thread_resume(ldsr_tid);
19659 + * ldsr_disable_vector()
19660 + * The LDSR implements an interrupt controller and has a local (to the
19661 + * LDSR) copy of its interrupt mask.
19663 +void ldsr_disable_vector(unsigned int vector)
19665 + unsigned int mask;
19667 + if (vector < 32) {
19668 + mask = ~(1 << vector);
19669 + ldsr_lock_acquire();
19670 + ldsr_interrupt.enabled0 &= mask;
19671 + ldsr_interrupt.mask0 &= mask;
19672 + ldsr_lock_release();
19673 + thread_resume(ldsr_tid);
19677 + mask = ~(1 << (vector - 32));
19678 + ldsr_lock_acquire();
19679 + ldsr_interrupt.enabled1 &= mask;
19680 + ldsr_interrupt.mask1 &= mask;
19681 + ldsr_lock_release();
19682 + thread_resume(ldsr_tid);
19686 + * ldsr_get_threadid()
19687 + * Return the threadid of the LDSR thread.
19689 +thread_t ldsr_get_threadid(void)
19695 + * ldsr_set_trap_irq()
19696 + * Save away the trap Soft IRQ
19698 + * See the per thread lock suspend code above for an explination.
19700 +void ldsr_set_trap_irq(unsigned int irq)
19702 + ldsr_trap_irq = irq;
19703 + ldsr_trap_irq_mask = (1 << irq);
19704 + ldsr_suspend_mask |= ldsr_trap_irq_mask;
19709 + * Initialize the LDSR (Interrupt Controller)
19711 +void ldsr_init(void)
19713 +#if defined(CONFIG_IRQSTACKS)
19715 + union irq_ctx *icp;
19718 + void *stack_high = (void *)ldsr_stack_space;
19719 + stack_high += sizeof(ldsr_stack_space);
19724 + * Obtain a soft IRQ to use
19726 + if (irq_soft_alloc(&ldsr_soft_irq) < 0) {
19727 + panic("no software IRQ is available\n");
19730 + ldsr_soft_irq_mask |= (1 << ldsr_soft_irq);
19731 + ldsr_suspend_mask |= ldsr_soft_irq_mask;
19734 + * Now allocate and start the LDSR thread.
19736 + ldsr_tid = thread_alloc();
19737 + if (ldsr_tid < 0) {
19738 + panic("no thread available to run LDSR");
19742 +#if defined(CONFIG_IRQSTACKS)
19744 + * Initialize the per-cpu irq thread_info structure that
19745 + * is at the top of each per-cpu irq stack.
19747 + icp = (union irq_ctx *)
19748 + (((unsigned long)percpu_irq_stacks + (THREAD_SIZE - 1)) & ~(THREAD_SIZE - 1));
19749 + for (i = 0; i < NR_CPUS; i++) {
19750 + struct thread_info *ti = &(icp->tinfo);
19752 + ti->exec_domain = NULL;
19754 + ti->preempt_count = 0;
19755 + ti->interrupt_nesting = 0;
19756 + percpu_irq_ctxs[i] = icp++;
19759 + thread_start(ldsr_tid, ldsr_thread, NULL,
19760 + stack_high, THREAD_TYPE_NORMAL);
19762 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/Makefile linux-2.6.30.10-ubi/arch/ubicom32/kernel/Makefile
19763 --- linux-2.6.30.10/arch/ubicom32/kernel/Makefile 1970-01-01 02:00:00.000000000 +0200
19764 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/Makefile 2009-12-11 11:45:11.000000000 +0200
19767 +# arch/ubicom32/kernel/Makefile
19768 +# Main Makefile for the Ubicom32 arch directory.
19770 +# (C) Copyright 2009, Ubicom, Inc.
19772 +# This file is part of the Ubicom32 Linux Kernel Port.
19774 +# The Ubicom32 Linux Kernel Port is free software: you can redistribute
19775 +# it and/or modify it under the terms of the GNU General Public License
19776 +# as published by the Free Software Foundation, either version 2 of the
19777 +# License, or (at your option) any later version.
19779 +# The Ubicom32 Linux Kernel Port is distributed in the hope that it
19780 +# will be useful, but WITHOUT ANY WARRANTY; without even the implied
19781 +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
19782 +# the GNU General Public License for more details.
19784 +# You should have received a copy of the GNU General Public License
19785 +# along with the Ubicom32 Linux Kernel Port. If not,
19786 +# see <http://www.gnu.org/licenses/>.
19788 +# Ubicom32 implementation derived from (with many thanks):
19794 +extra-y := head.o vmlinux.lds
19815 + ubicom32_context_switch.o \
19816 + ubicom32_ksyms.o \
19817 + ubicom32_syscall.o \
19820 +obj-$(CONFIG_MODULES) += module.o
19821 +obj-$(CONFIG_COMEMPCI) += comempci.o
19822 +obj-$(CONFIG_SMP) += smp.o topology.o
19823 +obj-$(CONFIG_ACCESS_OK_CHECKS_ENABLED) += uaccess.o
19824 +obj-$(CONFIG_GENERIC_CLOCKEVENTS) += timer_device.o
19825 +obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) += timer_broadcast.o
19827 +ifndef CONFIG_GENERIC_CLOCKEVENTS
19828 +obj-y += timer_tick.o
19830 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/module.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/module.c
19831 --- linux-2.6.30.10/arch/ubicom32/kernel/module.c 1970-01-01 02:00:00.000000000 +0200
19832 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/module.c 2009-12-11 11:45:11.000000000 +0200
19835 + * arch/ubicom32/kernel/module.c
19836 + * Ubicom32 architecture loadable module support.
19838 + * (C) Copyright 2009, Ubicom, Inc.
19840 + * This file is part of the Ubicom32 Linux Kernel Port.
19842 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
19843 + * it and/or modify it under the terms of the GNU General Public License
19844 + * as published by the Free Software Foundation, either version 2 of the
19845 + * License, or (at your option) any later version.
19847 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
19848 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
19849 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
19850 + * the GNU General Public License for more details.
19852 + * You should have received a copy of the GNU General Public License
19853 + * along with the Ubicom32 Linux Kernel Port. If not,
19854 + * see <http://www.gnu.org/licenses/>.
19856 + * Ubicom32 implementation derived from (with many thanks):
19861 +#include <linux/moduleloader.h>
19862 +#include <linux/bug.h>
19863 +#include <linux/elf.h>
19864 +#include <linux/vmalloc.h>
19865 +#include <linux/fs.h>
19866 +#include <linux/string.h>
19867 +#include <linux/kernel.h>
19868 +#include <asm/ocm-alloc.h>
19871 +#define DEBUGP printk
19873 +#define DEBUGP(fmt...)
19876 +static void _module_free_ocm(struct module *mod)
19878 + printk(KERN_INFO "module arch cleanup %s: OCM instruction memory free "
19879 + " of %d @%p\n", mod->name, mod->arch.ocm_inst_size,
19880 + mod->arch.ocm_inst);
19882 + if (mod->arch.ocm_inst) {
19883 + ocm_inst_free(mod->arch.ocm_inst);
19884 + mod->arch.ocm_inst = 0;
19885 + mod->arch.ocm_inst_size = 0;
19889 +void *module_alloc(unsigned long size)
19893 + return vmalloc(size);
19897 +/* Free memory returned from module_alloc */
19898 +void module_free(struct module *mod, void *module_region)
19900 + vfree(module_region);
19901 + /* FIXME: If module_region == mod->init_region, trim exception
19902 + table entries. */
19905 + * This is expected to be final module free, use this to prune the
19908 + if (module_region && module_region == mod->module_core)
19909 + _module_free_ocm(mod);
19914 + * module_frob_arch_sections()
19915 + * Called from kernel/module.c allowing arch specific handling of
19916 + * sections/headers.
19918 +int module_frob_arch_sections(Elf_Ehdr *hdr,
19919 + Elf_Shdr *sechdrs,
19920 + char *secstrings,
19921 + struct module *mod)
19923 + Elf_Shdr *s, *sechdrs_end;
19924 + void *ocm_inst = NULL;
19925 + int ocm_inst_size = 0;
19928 + * Ubicom32 v3 and v4 are almost binary compatible but not completely.
19929 + * To be safe check that the module was compiled with the correct -march
19930 + * which is flags.
19932 +#ifdef CONFIG_UBICOM32_V4
19933 + if ((hdr->e_flags & 0xFFFF) != EF_UBICOM32_V4) {
19934 + printk(KERN_WARNING "Module %s was not compiled for "
19935 + "ubicom32v4, elf_flags:%x,\n",
19936 + mod->name, hdr->e_flags);
19939 +#elif defined CONFIG_UBICOM32_V3
19940 + if ((hdr->e_flags & 0xFFFF) != EF_UBICOM32_V3) {
19941 + printk(KERN_WARNING "Module %s was not compiled for "
19942 + "ubicom32v3, elf_flags:%x\n",
19943 + mod->name, hdr->e_flags);
19947 +#error Unknown/Unsupported ubicom32 architecture.
19951 + * XXX: sechdrs are vmalloced in kernel/module.c
19952 + * and would be vfreed just after module is loaded,
19953 + * so we hack to keep the only information we needed
19954 + * in mod->arch to correctly free L1 I/D sram later.
19955 + * NOTE: this breaks the semantic of mod->arch structure.
19957 + sechdrs_end = sechdrs + hdr->e_shnum;
19958 + for (s = sechdrs; s < sechdrs_end; ++s) {
19959 + if (strncmp(".ocm_text", secstrings + s->sh_name, 9) == 0)
19960 + ocm_inst_size += s->sh_size;
19963 + if (!ocm_inst_size)
19966 + ocm_inst = ocm_inst_alloc(ocm_inst_size, 0 /* internal */);
19967 + if (ocm_inst == NULL) {
19968 +#ifdef CONFIG_OCM_MODULES_FALLBACK_TO_DDR
19969 + printk(KERN_WARNING
19970 + "module %s: OCM instruction memory allocation of %d"
19971 + "failed, fallback to DDR\n", mod->name, ocm_inst_size);
19975 + "module %s: OCM instruction memory allocation of %d"
19976 + "failed.\n", mod->name, ocm_inst_size);
19981 + mod->arch.ocm_inst = ocm_inst;
19982 + mod->arch.ocm_inst_size = ocm_inst_size;
19985 + "module %s: OCM instruction memory allocation of %d @%p\n",
19986 + mod->name, mod->arch.ocm_inst_size, mod->arch.ocm_inst);
19988 + for (s = sechdrs; s < sechdrs_end; ++s) {
19989 + if (strncmp(".ocm_text", secstrings + s->sh_name, 9) == 0) {
19990 + memcpy(ocm_inst, (void *)s->sh_addr, s->sh_size);
19991 + s->sh_flags &= ~SHF_ALLOC;
19992 + s->sh_addr = (unsigned long)ocm_inst;
19993 + ocm_inst += s->sh_size;
20000 +int apply_relocate(Elf32_Shdr *sechdrs,
20001 + const char *strtab,
20002 + unsigned int symindex,
20003 + unsigned int relsec,
20004 + struct module *me)
20006 + DEBUGP("Invalid Applying relocate section %u to %u\n", relsec,
20007 + sechdrs[relsec].sh_info);
20011 +int apply_relocate_add(Elf32_Shdr *sechdrs,
20012 + const char *strtab,
20013 + unsigned int symindex,
20014 + unsigned int relsec,
20015 + struct module *me)
20018 + Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
20020 + uint32_t *location;
20023 + DEBUGP("Applying relocate_add section %u to %u\n", relsec,
20024 + sechdrs[relsec].sh_info);
20025 + for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
20027 + const int elf32_rtype = ELF32_R_TYPE(rel[i].r_info);
20029 + /* This is where to make the change */
20030 + location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
20031 + + rel[i].r_offset;
20032 + /* This is the symbol it is referring to. Note that all
20033 + undefined symbols have been resolved. */
20034 + sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
20035 + + ELF32_R_SYM(rel[i].r_info);
20037 + v = rel[i].r_addend + sym->st_value;
20040 + switch (elf32_rtype) {
20041 + case R_UBICOM32_32:
20044 + * Store the 32 bit relocation as is.
20049 + case R_UBICOM32_HI24:
20052 + * 24 bit relocation that is part of the MOVEAI
20053 + * instruction. The 24 bits come from bits 7 - 30 of the
20054 + * relocation. Theses bits eventually get split into 2
20055 + * fields in the instruction encoding.
20057 + * - Bits 7 - 27 of the relocation are encoded into bits
20058 + * 0 - 20 of the instruction.
20060 + * - Bits 28 - 30 of the relocation are encoded into
20061 + * bit 24 - 26 of the instruction.
20063 + uint32_t valid24 = (v >> 7) & 0xffffff;
20064 + insn = *location;
20066 + insn &= ~(0x1fffff | (0x7 << 24));
20067 + insn |= (valid24 & 0x1fffff);
20068 + insn |= ((valid24 & 0xe00000) << 3);
20069 + *location = insn;
20072 + case R_UBICOM32_LO7_S:
20073 + case R_UBICOM32_LO7_2_S:
20074 + case R_UBICOM32_LO7_4_S:
20077 + * Bits 0 - 6 of the relocation are encoded into the
20078 + * 7bit unsigned immediate fields of the SOURCE-1 field
20079 + * of the instruction. The immediate value is left
20080 + * shifted by (0, 1, 2) based on the operand size.
20082 + uint32_t valid7 = v & 0x7f;
20083 + insn = *location;
20085 + if (elf32_rtype == R_UBICOM32_LO7_2_S) {
20087 + } else if (elf32_rtype == R_UBICOM32_LO7_4_S) {
20091 + insn &= ~(0x1f | (0x3 << 8));
20092 + insn |= (valid7 & 0x1f);
20093 + insn |= ((valid7 & 0x60) << 3);
20094 + *location = insn;
20097 + case R_UBICOM32_LO7_D:
20098 + case R_UBICOM32_LO7_2_D:
20099 + case R_UBICOM32_LO7_4_D:
20102 + * Bits 0 - 6 of the relocation are encoded into the
20103 + * 7bit unsigned immediate fields of the DESTINATION
20104 + * field of the instruction. The immediate value is
20105 + * left shifted by (0, 1, 2) based on the operand size.
20107 + uint32_t valid7 = v & 0x7f;
20108 + insn = *location;
20110 + if (elf32_rtype == R_UBICOM32_LO7_2_D) {
20112 + } else if (elf32_rtype == R_UBICOM32_LO7_4_D) {
20116 + insn &= ~((0x1f | (0x3 << 8)) << 16);
20117 + insn |= ((valid7 & 0x1f) << 16);
20118 + insn |= ((valid7 & 0x60) << 19);
20119 + *location = insn;
20122 + case R_UBICOM32_LO7_CALLI:
20123 + case R_UBICOM32_LO16_CALLI:
20126 + * Extract the offset for a CALLI instruction. The
20127 + * offsets can be either 7 bits or 18 bits. Since all
20128 + * instructions in ubicom32 architecture are at work
20129 + * aligned addresses the truncated offset is right
20130 + * shifted by 2 before being encoded in the instruction.
20133 + if (elf32_rtype == R_UBICOM32_LO7_CALLI) {
20136 + val = v & 0x3ffff;
20141 + insn = *location;
20143 + insn &= ~0x071f071f;
20144 + insn |= (val & 0x1f) << 0;
20146 + insn |= (val & 0x07) << 8;
20148 + insn |= (val & 0x1f) << 16;
20150 + insn |= (val & 0x07) << 24;
20151 + *location = insn;
20154 + case R_UBICOM32_24_PCREL:
20157 + * Extract 26 bit signed PC relative offset for CALL
20158 + * instructions. Since instruction addresses are word
20159 + * aligned the offset is right shited by 2 before
20160 + * encoding into instruction.
20162 + int32_t val = v - (int32_t)location;
20165 + * Check that the top 7 bits are all equal to the sign
20166 + * bit (26), i.e all 0's or all 1's. If they are not then
20167 + * the absolute difference is greater than 25 bits.
20169 + if (((uint32_t)val & 0xFE000000) != 0xFE000000 &&
20170 + ((uint32_t)val & 0xFE000000) != 0x0) {
20172 + * The relocation is beyond our addressable
20173 + * range with a 26 bit call.
20175 + printk(KERN_ERR "module %s: PC Relative "
20176 + "relocation out of range: "
20177 + "%u (%x->%x, %x)\n",
20178 + me->name, elf32_rtype,
20179 + v, (uint32_t) location, val);
20183 + val = (val & 0x3ffffff) >> 2;
20184 + insn = *location;
20185 + insn = insn & 0xf8e00000;
20187 + insn |= (val >> 21) << 24;
20188 + insn |= (val & 0x1fffff);
20189 + *location = insn;
20192 + case R_UBICOM32_LO16:
20193 + case R_UBICOM32_HI16:
20196 + * 16 bit immediate value that is encoded into bit 0 -
20197 + * 15 of the instruction.
20201 + if (elf32_rtype == R_UBICOM32_LO16) {
20202 + val = v & 0xffff;
20204 + val = (v >> 16) & 0xffff;
20207 + insn = *location;
20208 + insn &= 0xffff0000;
20211 + *location = insn;
20214 + case R_UBICOM32_21_PCREL:
20217 + * Extract 23 bit signed PC relative offset for JMP<cc>
20218 + * instructions. Since instruction addresses are word
20219 + * aligned the offset is right shited by 2 before
20220 + * encoding into instruction.
20222 + int32_t val = v - (int32_t)location;
20224 + val = (val & 0x7fffff) >> 2;
20225 + insn = *location;
20226 + insn = insn & 0xffe00000;
20228 + insn |= (val >> 21) << 24;
20230 + *location = insn;
20235 + printk(KERN_ERR "module %s: Unknown relocation: %u\n",
20236 + me->name, elf32_rtype);
20243 +int module_finalize(const Elf_Ehdr *hdr,
20244 + const Elf_Shdr *sechdrs,
20245 + struct module *mod)
20247 + unsigned int i, strindex = 0, symindex = 0;
20248 + char *secstrings;
20251 + err = module_bug_finalize(hdr, sechdrs, mod);
20255 + if (!mod->arch.ocm_inst) {
20257 + * No OCM code, so nothing more to do.
20262 + secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
20264 + for (i = 1; i < hdr->e_shnum; i++) {
20265 + /* Internal symbols and strings. */
20266 + if (sechdrs[i].sh_type == SHT_SYMTAB) {
20268 + strindex = sechdrs[i].sh_link;
20272 + for (i = 1; i < hdr->e_shnum; i++) {
20273 + const char *strtab = (char *)sechdrs[strindex].sh_addr;
20274 + unsigned int info = sechdrs[i].sh_info;
20276 + /* Not a valid relocation section? */
20277 + if (info >= hdr->e_shnum)
20280 + if ((sechdrs[i].sh_type == SHT_RELA) &&
20281 + (strncmp(".rela.ocm_text",
20282 + secstrings + sechdrs[i].sh_name, 5 + 9) == 0)) {
20283 + err = apply_relocate_add((Elf_Shdr *) sechdrs, strtab,
20284 + symindex, i, mod);
20293 +void module_arch_cleanup(struct module *mod)
20295 + module_bug_cleanup(mod);
20297 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/os_node.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/os_node.c
20298 --- linux-2.6.30.10/arch/ubicom32/kernel/os_node.c 1970-01-01 02:00:00.000000000 +0200
20299 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/os_node.c 2009-12-11 11:45:11.000000000 +0200
20302 + * arch/ubicom32/kernel/os_node.c
20303 + * <TODO: Replace with short file description>
20305 + * (C) Copyright 2009, Ubicom, Inc.
20307 + * This file is part of the Ubicom32 Linux Kernel Port.
20309 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
20310 + * it and/or modify it under the terms of the GNU General Public License
20311 + * as published by the Free Software Foundation, either version 2 of the
20312 + * License, or (at your option) any later version.
20314 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
20315 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
20316 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
20317 + * the GNU General Public License for more details.
20319 + * You should have received a copy of the GNU General Public License
20320 + * along with the Ubicom32 Linux Kernel Port. If not,
20321 + * see <http://www.gnu.org/licenses/>.
20324 +#include "linux/types.h"
20325 +#include "linux/linkage.h"
20326 +#include "linux/uts.h"
20327 +#include "linux/utsrelease.h"
20328 +#include "linux/version.h"
20329 +#include <asm/ocm_size.h>
20330 +#include <asm/devtree.h>
20331 +#include <asm/ip5000.h>
20333 +extern asmlinkage void *_start;
20336 + * This file provides static information to the boot code allowing it to decide
20337 + * if the os is compatible. Thus hopefully enabling the boot code to prevent
20338 + * accidentally booting a kernel that has no hope of running.
20341 + struct devtree_node node;
20342 + unsigned long version; /* Always 1 */
20343 + unsigned long entry_point;
20344 + const char os_name[32]; /* For diagnostic purposes only */
20345 + const char os_version_str[32];
20346 + unsigned long os_version_num;
20347 + unsigned long expected_ocm_code_start;/* OS Code */
20348 + unsigned long expected_ocm_data_end; /* OS Data */
20349 + unsigned long expected_ram_start;
20350 + unsigned long expected_ram_end;
20351 + unsigned long arch_version;
20352 + unsigned long expected_os_syscall_begin;
20353 + unsigned long expected_os_syscall_end;
20357 +extern void __os_syscall_begin;
20358 +extern void __os_syscall_end;
20360 + * The os_node is only referenced by head.S and should never be modified at
20363 +asmlinkage const struct os_node _os_node = {
20366 + .name = { "OS" },
20367 + .magic = 0x10203040,
20369 + .version = 0x10002,
20370 + .entry_point = (unsigned long)&_start,
20371 +#if APP_OCM_CODE_SIZE || APP_OCM_DATA_SIZE
20372 + .expected_ocm_code_start = OCMSTART + APP_OCM_CODE_SIZE,
20373 + .expected_ocm_data_end = OCMEND - APP_OCM_DATA_SIZE,
20375 + .expected_ocm_code_start = OCMEND,
20376 + .expected_ocm_data_end = OCMEND,
20378 + .os_name = { UTS_SYSNAME },
20379 + .os_version_str = { UTS_RELEASE },
20380 + .os_version_num = LINUX_VERSION_CODE,
20381 + .expected_ram_start = KERNELSTART,
20382 + .expected_ram_end = SDRAMSTART + CONFIG_MIN_RAMSIZE,
20383 + .arch_version = UBICOM32_ARCH_VERSION,
20384 + .expected_os_syscall_begin = (unsigned long)&__os_syscall_begin,
20385 + .expected_os_syscall_end = (unsigned long)&__os_syscall_end,
20389 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/process.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/process.c
20390 --- linux-2.6.30.10/arch/ubicom32/kernel/process.c 1970-01-01 02:00:00.000000000 +0200
20391 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/process.c 2009-12-11 11:45:11.000000000 +0200
20394 + * arch/ubicom32/kernel/process.c
20395 + * Ubicom32 architecture-dependent process handling.
20397 + * (C) Copyright 2009, Ubicom, Inc.
20398 + * Copyright (C) 1995 Hamish Macdonald
20400 + * 68060 fixes by Jesper Skov
20402 + * uClinux changes
20403 + * Copyright (C) 2000-2002, David McCullough <davidm@snapgear.com>
20405 + * This file is part of the Ubicom32 Linux Kernel Port.
20407 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
20408 + * it and/or modify it under the terms of the GNU General Public License
20409 + * as published by the Free Software Foundation, either version 2 of the
20410 + * License, or (at your option) any later version.
20412 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
20413 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
20414 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
20415 + * the GNU General Public License for more details.
20417 + * You should have received a copy of the GNU General Public License
20418 + * along with the Ubicom32 Linux Kernel Port. If not,
20419 + * see <http://www.gnu.org/licenses/>.
20421 + * Ubicom32 implementation derived from (with many thanks):
20428 + * This file handles the architecture-dependent parts of process handling..
20431 +#include <linux/module.h>
20432 +#include <linux/errno.h>
20433 +#include <linux/sched.h>
20434 +#include <linux/kernel.h>
20435 +#include <linux/mm.h>
20436 +#include <linux/smp.h>
20437 +#include <linux/smp_lock.h>
20438 +#include <linux/stddef.h>
20439 +#include <linux/unistd.h>
20440 +#include <linux/ptrace.h>
20441 +#include <linux/slab.h>
20442 +#include <linux/user.h>
20443 +#include <linux/a.out.h>
20444 +#include <linux/interrupt.h>
20445 +#include <linux/reboot.h>
20446 +#include <linux/fs.h>
20447 +#include <linux/pm.h>
20449 +#include <linux/uaccess.h>
20450 +#include <asm/system.h>
20451 +#include <asm/traps.h>
20452 +#include <asm/machdep.h>
20453 +#include <asm/setup.h>
20454 +#include <asm/pgtable.h>
20455 +#include <asm/ip5000.h>
20456 +#include <asm/range-protect.h>
20458 +#define DUMP_RANGE_REGISTER(REG, IDX) asm volatile ( \
20459 + " move.4 %0, "REG"_RANGE"IDX"_EN \n\t" \
20460 + " move.4 %1, "REG"_RANGE"IDX"_LO \n\t" \
20461 + " move.4 %2, "REG"_RANGE"IDX"_HI \n\t" \
20462 + : "=d"(en), "=d"(lo), "=d"(hi) \
20464 + printk(KERN_NOTICE REG"Range"IDX": en:%08x, range: %08x-%08x\n", \
20465 + (unsigned int)en, \
20466 + (unsigned int)lo, \
20467 + (unsigned int)hi)
20469 +asmlinkage void ret_from_fork(void);
20471 +void (*pm_power_off)(void) = machine_power_off;
20472 +EXPORT_SYMBOL(pm_power_off);
20474 +/* machine-dependent / hardware-specific power functions */
20475 +void (*mach_reset)(void);
20476 +void (*mach_halt)(void);
20477 +void (*mach_power_off)(void);
20481 + * The idle thread.
20483 + * Our idle loop suspends and is woken up by a timer interrupt.
20485 +void cpu_idle(void)
20488 + local_irq_disable();
20489 + while (!need_resched()) {
20490 + local_irq_enable();
20491 + thread_suspend();
20492 + local_irq_disable();
20494 + local_irq_enable();
20495 + preempt_enable_no_resched();
20497 + preempt_disable();
20504 + * Fill in the fpu structure for a core dump. (just a stub as we don't have
20507 +int dump_fpu(struct pt_regs *regs, elf_fpregset_t * fpregs)
20513 + * machine_restart()
20514 + * Resets the system.
20516 +void machine_restart(char *__unused)
20519 + * Disable all threads except myself. We can do this
20520 + * directly without needing to call smp_send_stop
20521 + * because we have a unique architecture where
20522 + * one thread can disable one or more other threads.
20524 + thread_disable_others();
20527 + * Call the hardware-specific machine reset function.
20529 + if (mach_reset) {
20533 + printk(KERN_EMERG "System Restarting\n");
20536 + * Set watchdog to trigger (after 1ms delay) (12 Mhz is the fixed OSC)
20538 + UBICOM32_IO_TIMER->tkey = TIMER_TKEYVAL;
20539 + UBICOM32_IO_TIMER->wdcom = UBICOM32_IO_TIMER->mptval +
20540 + (12000000 / 1000);
20541 + UBICOM32_IO_TIMER->wdcfg = 0;
20542 + UBICOM32_IO_TIMER->tkey = 0;
20545 + * Wait for watchdog
20548 + " move.4 MT_EN, #0 \n\t"
20549 + " pipe_flush 0 \n\t"
20552 + local_irq_disable();
20554 + thread_suspend();
20560 + * Halt the machine.
20562 + * Similar to machine_power_off, but don't shut off power. Add code
20563 + * here to freeze the system for e.g. post-mortem debug purpose when
20564 + * possible. This halt has nothing to do with the idle halt.
20566 +void machine_halt(void)
20569 + * Disable all threads except myself. We can do this
20570 + * directly without needing to call smp_send_stop
20571 + * because we have a unique architecture where
20572 + * one thread can disable one or more other threads.
20574 + thread_disable_others();
20577 + * Call the hardware-specific machine halt function.
20583 + printk(KERN_EMERG "System Halted, OK to turn off power\n");
20584 + local_irq_disable();
20586 + thread_suspend();
20591 + * machine_power_off()
20592 + * Turn the power off, if a power off handler is defined, otherwise, spin
20595 +void machine_power_off(void)
20598 + * Disable all threads except myself. We can do this
20599 + * directly without needing to call smp_send_stop
20600 + * because we have a unique architecture where
20601 + * one thread can disable one or more other threads.
20603 + thread_disable_others();
20606 + * Call the hardware-specific machine power off function.
20608 + if (mach_power_off) {
20609 + mach_power_off();
20612 + printk(KERN_EMERG "System Halted, OK to turn off power\n");
20613 + local_irq_disable();
20615 + thread_suspend();
20620 + * address_is_valid()
20621 + * check if an address is valid -- (for read access)
20623 +static bool address_is_valid(const void *address)
20625 + int addr = (int)address;
20626 + unsigned long socm, eocm, sdram, edram;
20631 + processor_ocm(&socm, &eocm);
20632 + processor_dram(&sdram, &edram);
20633 + if (addr >= socm && addr < eocm)
20636 + if (addr >= sdram && addr < edram)
20643 + * vma_path_name_is_valid()
20644 + * check if path_name of a vma is a valid string
20646 +static bool vma_path_name_is_valid(const char *str)
20648 +#define MAX_NAME_LEN 256
20650 + if (!address_is_valid(str))
20653 + for (; i < MAX_NAME_LEN; i++, str++) {
20654 + if (*str == '\0')
20663 + * show vma info of a process
20665 +void show_vmas(struct task_struct *task)
20667 +#ifdef CONFIG_DEBUG_VERBOSE
20668 +#define UBICOM32_MAX_VMA_COUNT 1024
20670 + struct vm_area_struct *vma;
20671 + struct file *file;
20673 + int flags, loop = 0;
20675 + printk(KERN_NOTICE "Start of vma list\n");
20677 + if (!address_is_valid(task) || !address_is_valid(task->mm))
20680 + vma = task->mm->mmap;
20682 + if (!address_is_valid(vma))
20685 + flags = vma->vm_flags;
20686 + file = vma->vm_file;
20689 + /* seems better to use dentry op here, but sanity check is easier this way */
20690 + if (!address_is_valid(file) || !address_is_valid(file->f_path.dentry) || !vma_path_name_is_valid(file->f_path.dentry->d_name.name))
20693 + name = (char *)file->f_path.dentry->d_name.name;
20696 + /* Similar to /proc/pid/maps format */
20697 + printk(KERN_NOTICE "%08lx-%08lx %c%c%c%c %08lx %s\n",
20700 + flags & VM_READ ? 'r' : '-',
20701 + flags & VM_WRITE ? 'w' : '-',
20702 + flags & VM_EXEC ? 'x' : '-',
20703 + flags & VM_MAYSHARE ? flags & VM_SHARED ? 'S' : 's' : 'p',
20704 + vma->vm_pgoff << PAGE_SHIFT,
20707 + vma = vma->vm_next;
20709 + if (loop++ > UBICOM32_MAX_VMA_COUNT)
20713 + printk(KERN_NOTICE "End of vma list\n");
20717 + printk(KERN_NOTICE "\nCorrupted vma list, abort!\n");
20723 + * Print out all of the registers.
20725 +void show_regs(struct pt_regs *regs)
20728 + unsigned int en, lo, hi;
20730 + printk(KERN_NOTICE "regs: %p, tid: %d\n",
20732 + thread_get_self());
20734 + printk(KERN_NOTICE "pc: %08x, previous_pc: %08x\n\n",
20735 + (unsigned int)regs->pc,
20736 + (unsigned int)regs->previous_pc);
20738 + printk(KERN_NOTICE "Data registers\n");
20739 + for (i = 0; i < 16; i++) {
20740 + printk("D%02d: %08x, ", i, (unsigned int)regs->dn[i]);
20741 + if ((i % 4) == 3) {
20747 + printk(KERN_NOTICE "Address registers\n");
20748 + for (i = 0; i < 8; i++) {
20749 + printk("A%02d: %08x, ", i, (unsigned int)regs->an[i]);
20750 + if ((i % 4) == 3) {
20756 + printk(KERN_NOTICE "acc0: %08x-%08x, acc1: %08x-%08x\n",
20757 + (unsigned int)regs->acc0[1],
20758 + (unsigned int)regs->acc0[0],
20759 + (unsigned int)regs->acc1[1],
20760 + (unsigned int)regs->acc1[0]);
20762 + printk(KERN_NOTICE "mac_rc16: %08x, source3: %08x\n",
20763 + (unsigned int)regs->mac_rc16,
20764 + (unsigned int)regs->source3);
20766 + printk(KERN_NOTICE "inst_cnt: %08x, csr: %08x\n",
20767 + (unsigned int)regs->inst_cnt,
20768 + (unsigned int)regs->csr);
20770 + printk(KERN_NOTICE "int_mask0: %08x, int_mask1: %08x\n",
20771 + (unsigned int)regs->int_mask0,
20772 + (unsigned int)regs->int_mask1);
20775 + * Dump range registers
20777 + DUMP_RANGE_REGISTER("I", "0");
20778 + DUMP_RANGE_REGISTER("I", "1");
20779 + DUMP_RANGE_REGISTER("I", "2");
20780 + DUMP_RANGE_REGISTER("I", "3");
20781 + DUMP_RANGE_REGISTER("D", "0");
20782 + DUMP_RANGE_REGISTER("D", "1");
20783 + DUMP_RANGE_REGISTER("D", "2");
20784 + DUMP_RANGE_REGISTER("D", "3");
20785 + DUMP_RANGE_REGISTER("D", "4");
20787 + printk(KERN_NOTICE "frame_type: %d, nesting_level: %d, thread_type %d\n\n",
20788 + (int)regs->frame_type,
20789 + (int)regs->nesting_level,
20790 + (int)regs->thread_type);
20794 + * kernel_thread_helper()
20795 + * On execution d0 will be 0, d1 will be the argument to be passed to the
20796 + * kernel function. d2 contains the kernel function that needs to get
20797 + * called. d3 will contain address to do_exit which need to get moved
20798 + * into a5. On return from fork the child thread d0 will be 0. We call
20799 + * this dummy function which in turn loads the argument
20801 +asmlinkage void kernel_thread_helper(void);
20804 + * kernel_thread()
20805 + * Create a kernel thread
20807 +int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
20809 + struct pt_regs regs;
20811 + memset(®s, 0, sizeof(regs));
20813 + regs.dn[1] = (unsigned long)arg;
20814 + regs.dn[2] = (unsigned long)fn;
20815 + regs.dn[3] = (unsigned long)do_exit;
20816 + regs.an[5] = (unsigned long)kernel_thread_helper;
20817 + regs.pc = (unsigned long)kernel_thread_helper;
20818 + regs.nesting_level = 0;
20819 + regs.thread_type = KERNEL_THREAD;
20821 + return do_fork(flags | CLONE_VM | CLONE_UNTRACED,
20822 + 0, ®s, 0, NULL, NULL);
20824 +EXPORT_SYMBOL(kernel_thread);
20830 +void flush_thread(void)
20837 + * Not implemented on no-mmu.
20839 +asmlinkage int sys_fork(struct pt_regs *regs)
20841 + /* fork almost works, enough to trick you into looking elsewhere :-( */
20847 + * By the time we get here, the non-volatile registers have also been saved
20848 + * on the stack. We do some ugly pointer stuff here.. (see also copy_thread
20849 + * which does context copy).
20851 +asmlinkage int sys_vfork(struct pt_regs *regs)
20853 + unsigned long old_sp = regs->an[7];
20854 + unsigned long old_a5 = regs->an[5];
20855 + unsigned long old_return_address;
20856 + long do_fork_return;
20859 + * Read the old retrun address from the stack.
20861 + if (copy_from_user(&old_return_address,
20862 + (void *)old_sp, sizeof(unsigned long))) {
20863 + force_sig(SIGSEGV, current);
20868 + * Pop the vfork call frame by setting a5 and pc to the old_return
20869 + * address and incrementing the stack pointer by 4.
20871 + regs->an[5] = old_return_address;
20872 + regs->pc = old_return_address;
20873 + regs->an[7] += 4;
20875 + do_fork_return = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,
20876 + regs->an[7], regs, 0, NULL, NULL);
20879 + * Now we have to test if the return code is an error. If it is an error
20880 + * then restore the frame and we will execute error processing in user
20881 + * space. Other wise the child and the parent will return to the correct
20884 + if ((unsigned long)(do_fork_return) >= (unsigned long)(-125)) {
20886 + * Error case. We need to restore the frame.
20888 + regs->an[5] = old_a5;
20889 + regs->pc = old_a5;
20890 + regs->an[7] = old_sp;
20893 + return do_fork_return;
20898 + * creates a child thread.
20900 +asmlinkage int sys_clone(unsigned long clone_flags,
20901 + unsigned long newsp,
20902 + struct pt_regs *regs)
20905 + newsp = regs->an[7];
20906 + return do_fork(clone_flags, newsp, regs, 0,
20912 + * low level thread copy, only used by do_fork in kernel/fork.c
20914 +int copy_thread(unsigned long clone_flags,
20915 + unsigned long usp, unsigned long topstk,
20916 + struct task_struct *p, struct pt_regs *regs)
20919 + struct pt_regs *childregs;
20921 + childregs = (struct pt_regs *)
20922 + (task_stack_page(p) + THREAD_SIZE - 8) - 1;
20924 + *childregs = *regs;
20927 + * Set return value for child to be 0.
20929 + childregs->dn[0] = 0;
20932 + childregs->an[7] = usp;
20934 + childregs->an[7] = (unsigned long)task_stack_page(p) +
20938 + * Set up the switch_to frame to return to "ret_from_fork"
20940 + p->thread.a5 = (unsigned long)ret_from_fork;
20941 + p->thread.sp = (unsigned long)childregs;
20948 + * executes a new program.
20950 +asmlinkage int sys_execve(char *name, char **argv,
20951 + char **envp, struct pt_regs *regs)
20957 + filename = getname(name);
20958 + error = PTR_ERR(filename);
20959 + if (IS_ERR(filename))
20961 + error = do_execve(filename, argv, envp, regs);
20962 + putname(filename);
20963 + asm (" .global sys_execve_complete\n"
20964 + " sys_execve_complete:");
20971 + * Return saved PC of a blocked thread.
20973 +unsigned long thread_saved_pc(struct task_struct *tsk)
20975 + return tsk->thread.a5;
20979 +unsigned long get_wchan(struct task_struct *p)
20981 + unsigned long pc;
20984 + * If we don't have a process, or it is not the current
20985 + * one or not RUNNING, it makes no sense to ask for a
20988 + if (!p || p == current || p->state == TASK_RUNNING)
20992 + * TODO: If the process is in the middle of schedule, we
20993 + * are supposed to do something different but for now we
20994 + * will return the same thing in both situations.
20996 + pc = thread_saved_pc(p);
20997 + if (in_sched_functions(pc))
21004 + * Infrequently used interface to dump task registers to core files.
21006 +int dump_task_regs(struct task_struct *task, elf_gregset_t *elfregs)
21008 + struct pt_regs *regs = task_pt_regs(task);
21009 + *(struct pt_regs *)elfregs = *regs;
21015 + * __switch_to is the function that implements the contex save and
21016 + * switch within the kernel. Since this is a function call very few
21017 + * registers have to be saved to pull this off. d0 holds prev and we
21018 + * want to preserve it. prev_switch is a pointer to task->thread
21019 + * structure. This is where we will save the register state. next_switch
21020 + * is pointer to the next task's thread structure that holds the
21023 +asmlinkage void *__switch_to(struct task_struct *prev,
21024 + struct thread_struct *prev_switch,
21025 + struct thread_struct *next_switch)
21026 + __attribute__((naked));
21027 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/processor.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/processor.c
21028 --- linux-2.6.30.10/arch/ubicom32/kernel/processor.c 1970-01-01 02:00:00.000000000 +0200
21029 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/processor.c 2009-12-11 11:45:11.000000000 +0200
21032 + * arch/ubicom32/kernel/processor.c
21033 + * Ubicom32 architecture processor info implementation.
21035 + * (C) Copyright 2009, Ubicom, Inc.
21037 + * This file is part of the Ubicom32 Linux Kernel Port.
21039 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
21040 + * it and/or modify it under the terms of the GNU General Public License
21041 + * as published by the Free Software Foundation, either version 2 of the
21042 + * License, or (at your option) any later version.
21044 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
21045 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
21046 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
21047 + * the GNU General Public License for more details.
21049 + * You should have received a copy of the GNU General Public License
21050 + * along with the Ubicom32 Linux Kernel Port. If not,
21051 + * see <http://www.gnu.org/licenses/>.
21053 + * Ubicom32 implementation derived from (with many thanks):
21058 +#include <linux/module.h>
21059 +#include <linux/kernel.h>
21060 +#include <linux/init.h>
21061 +#include <linux/sched.h>
21062 +#include <linux/interrupt.h>
21063 +#include <linux/irq.h>
21064 +#include <linux/profile.h>
21065 +#include <linux/clocksource.h>
21066 +#include <linux/types.h>
21067 +#include <linux/seq_file.h>
21068 +#include <linux/delay.h>
21069 +#include <linux/cpu.h>
21070 +#include <asm/devtree.h>
21071 +#include <asm/processor.h>
21072 +#include <asm/cpu.h>
21073 +#include <asm/ocm_size.h>
21076 + struct devtree_node dn;
21077 + unsigned int threads;
21078 + unsigned int timers;
21079 + unsigned int frequency;
21080 + unsigned int ddr_frequency;
21081 + unsigned int interrupt0;
21082 + unsigned int interrupt1;
21087 + unsigned int arch_version;
21088 + void *os_syscall_begin;
21089 + void *os_syscall_end;
21092 +struct procnode *pn;
21095 + * show_processorinfo()
21096 + * Print the actual processor information.
21098 +static void show_processorinfo(struct seq_file *m)
21100 + char *cpu, *mmu, *fpu;
21101 + unsigned int clockfreq;
21102 + unsigned int chipid;
21109 + "move.4 %0, CHIP_ID \n\t"
21114 + * General Processor Information.
21116 + seq_printf(m, "Vendor:\t\t%s\n", "Ubicom");
21117 + seq_printf(m, "CPU:\t\t%s\n", cpu);
21118 + seq_printf(m, "MMU:\t\t%s\n", mmu);
21119 + seq_printf(m, "FPU:\t\t%s\n", fpu);
21120 + seq_printf(m, "Arch:\t\t%hx\n", chipid >> 16);
21121 + seq_printf(m, "Rev:\t\t%hx\n", (chipid & 0xffff));
21124 + * Now compute the clock frequency in Mhz.
21126 + clockfreq = processor_frequency();
21127 + seq_printf(m, "Clock Freq:\t%u.0 MHz\n",
21128 + clockfreq / 1000000);
21129 + seq_printf(m, "DDR Freq:\t%u.0 MHz\n",
21130 + pn ? pn->ddr_frequency / 1000000 : 0);
21131 + seq_printf(m, "BogoMips:\t%lu.%02lu\n",
21132 + (loops_per_jiffy * HZ) / 500000,
21133 + ((loops_per_jiffy * HZ) / 5000) % 100);
21134 + seq_printf(m, "Calibration:\t%lu loops\n", (loops_per_jiffy * HZ));
21139 + * Get CPU information for use by the procfs.
21141 +static int show_cpuinfo(struct seq_file *m, void *v)
21143 + unsigned long n = (unsigned long)v - 1;
21145 +#if defined(CONFIG_SMP)
21146 + struct cpuinfo_ubicom32 *p = &per_cpu(cpu_data, n);
21150 + * Print the general processor information on the first
21154 + show_processorinfo(m);
21157 +#if defined(CONFIG_SMP)
21159 + * For each hwthread, print if this hwthread is running Linux
21160 + * or is an I/O thread.
21162 + if (cpu_isset(n, cpu_online_map)) {
21163 + seq_printf(m, "cpu[%02lu]:\tthread id - %lu\n", n, p->tid);
21165 + seq_printf(m, "cpu[%02lu]:\toff-line\n", n);
21172 +static void *c_start(struct seq_file *m, loff_t *pos)
21174 + unsigned long i = *pos;
21176 + return i < NR_CPUS ? (void *)(i + 1) : NULL;
21179 +static void *c_next(struct seq_file *m, void *v, loff_t *pos)
21182 + return c_start(m, pos);
21185 +static void c_stop(struct seq_file *m, void *v)
21189 +const struct seq_operations cpuinfo_op = {
21190 + .start = c_start,
21193 + .show = show_cpuinfo,
21197 + * processor_timers()
21198 + * Returns the timers available to Linux.
21200 +unsigned int processor_timers(void)
21205 + return pn->timers;
21209 + * processor_threads()
21210 + * Returns the threads available to Linux.
21212 +unsigned int processor_threads(void)
21217 + return pn->threads;
21221 + * processor_frequency()
21222 + * Returns the frequency of the system clock.
21224 +unsigned int processor_frequency(void)
21229 + return pn->frequency;
21231 +EXPORT_SYMBOL(processor_frequency);
21234 + * processor_interrupts()
21235 + * Return the interrupts that are setup at boot time.
21237 +int processor_interrupts(unsigned int *int0, unsigned int *int1)
21244 + *int0 = pn->interrupt0;
21248 + *int1 = pn->interrupt1;
21254 + * processor_ocm()
21255 + * Returns the start and end of OCM available to Linux.
21257 +void processor_ocm(unsigned long *socm, unsigned long *eocm)
21259 + *socm = (unsigned long)pn->socm;
21260 + *eocm = (unsigned long)pn->eocm;
21264 + * processor_dram()
21265 + * Returns the start and end of dram available to Linux.
21267 +void processor_dram(unsigned long *sdram, unsigned long *edram)
21269 + *sdram = (unsigned long)pn->sdram;
21270 + *edram = (unsigned long)pn->edram;
21274 + * processor_validate_failed()
21275 + * Returns the dram available to Linux.
21277 +static noinline void processor_validate_failed(void)
21284 + * processor_validate()
21285 + * Validates the procnode against limitations of this link/built.
21287 +static void processor_validate(void)
21289 + void *dram_start = (void *)(KERNELSTART);
21290 + void *dram_end = (void *)(SDRAMSTART + CONFIG_MIN_RAMSIZE);
21291 +#if APP_OCM_CODE_SIZE || APP_OCM_DATA_SIZE
21292 + void *ocm_code_start = (void *)(OCMSTART + APP_OCM_CODE_SIZE);
21293 + void *ocm_data_end = (void *)(OCMEND - APP_OCM_DATA_SIZE);
21295 + extern void __os_syscall_begin;
21296 + extern void __os_syscall_end;
21297 + int proc_node_valid = 1;
21300 + printk(KERN_ERR "ERROR: processor node not found\n");
21305 + if (dram_start < pn->sdram || dram_end > pn->edram) {
21306 + printk(KERN_ERR "ERROR: processor dram mismatch %p-%p "
21307 + "available but we are expecting %p-%p\n",
21308 + pn->sdram, pn->edram, dram_start, dram_end);
21309 + proc_node_valid = 0;
21311 + printk(KERN_ERR "processor dram %p-%p, expecting %p-%p\n",
21312 + pn->sdram, pn->edram, dram_start, dram_end);
21314 + if (&__os_syscall_begin < pn->os_syscall_begin ||
21315 + &__os_syscall_end > pn->os_syscall_end) {
21316 + printk(KERN_ERR "ERROR: processor syscall area mismatch "
21317 + "%p-%p available but we are expecting %p-%p\n",
21318 + pn->os_syscall_begin, pn->os_syscall_end,
21319 + &__os_syscall_begin, &__os_syscall_end);
21320 + proc_node_valid = 0;
21322 + printk(KERN_ERR "processor dram %p-%p, expecting %p-%p\n",
21323 + pn->sdram, pn->edram, dram_start, dram_end);
21325 +#if APP_OCM_CODE_SIZE || APP_OCM_DATA_SIZE
21326 + if (ocm_code_start < pn->socm || ocm_data_end > pn->eocm) {
21327 + printk(KERN_ERR "ERROR: processor ocm mismatch %p-%p "
21328 + "available but we are expecting %p-%p\n",
21329 + pn->socm, pn->eocm, ocm_code_start, ocm_data_end);
21330 + proc_node_valid = 0;
21332 + printk(KERN_INFO "processor ocm %p-%p, expecting %p-%p\n",
21333 + pn->socm, pn->eocm, ocm_code_start, ocm_data_end);
21338 + if (UBICOM32_ARCH_VERSION != pn->arch_version) {
21339 + printk(KERN_ERR "ERROR: processor arch mismatch, kernel"
21340 + "compiled for %d found %d\n",
21341 + UBICOM32_ARCH_VERSION, pn->arch_version);
21342 + proc_node_valid = 0;
21345 + if (proc_node_valid)
21348 + processor_validate_failed();
21351 +void __init processor_init(void)
21354 + * If we do not have a trap node in the device tree, we leave the fault
21355 + * handling to the underlying hardware.
21357 + pn = (struct procnode *)devtree_find_node("processor");
21359 + processor_validate();
21362 + * If necessary correct the initial range registers to cover the
21363 + * complete physical space
21365 + if (pn->edram > (void *)(SDRAMSTART + CONFIG_MIN_RAMSIZE)) {
21366 + printk(KERN_INFO "updating range registers for expanded dram\n");
21368 + " move.4 D_RANGE1_HI, %0 \t\n"
21369 + " move.4 I_RANGE0_HI, %0 \t\n"
21370 +#ifdef CONFIG_PROTECT_KERNEL
21371 + " move.4 D_RANGE2_HI, %0 \t\n"
21372 + " move.4 I_RANGE2_HI, %0 \t\n"
21374 + : : "a"((unsigned long)pn->edram - 4)
21379 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/ptrace.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/ptrace.c
21380 --- linux-2.6.30.10/arch/ubicom32/kernel/ptrace.c 1970-01-01 02:00:00.000000000 +0200
21381 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/ptrace.c 2009-12-11 11:45:11.000000000 +0200
21384 + * arch/ubicom32/kernel/ptrace.c
21385 + * Ubicom32 architecture ptrace implementation.
21387 + * (C) Copyright 2009, Ubicom, Inc.
21388 + * (C) 1994 by Hamish Macdonald
21389 + * Taken from linux/kernel/ptrace.c and modified for M680x0.
21390 + * linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds
21392 + * This file is part of the Ubicom32 Linux Kernel Port.
21394 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
21395 + * it and/or modify it under the terms of the GNU General Public License
21396 + * as published by the Free Software Foundation, either version 2 of the
21397 + * License, or (at your option) any later version.
21399 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
21400 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
21401 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
21402 + * the GNU General Public License for more details.
21404 + * You should have received a copy of the GNU General Public License
21405 + * along with the Ubicom32 Linux Kernel Port. If not,
21406 + * see <http://www.gnu.org/licenses/>.
21408 + * Ubicom32 implementation derived from (with many thanks):
21414 +#include <linux/module.h>
21415 +#include <linux/kernel.h>
21416 +#include <linux/sched.h>
21417 +#include <linux/mm.h>
21418 +#include <linux/smp.h>
21419 +#include <linux/errno.h>
21420 +#include <linux/ptrace.h>
21421 +#include <linux/user.h>
21422 +#include <linux/signal.h>
21423 +#include <linux/uaccess.h>
21425 +#include <asm/page.h>
21426 +#include <asm/pgtable.h>
21427 +#include <asm/system.h>
21428 +#include <asm/cacheflush.h>
21429 +#include <asm/processor.h>
21432 + * ptrace_getregs()
21434 + * Get all user integer registers.
21436 +static inline int ptrace_getregs(struct task_struct *task, void __user *uregs)
21438 + struct pt_regs *regs = task_pt_regs(task);
21439 + return copy_to_user(uregs, regs, sizeof(struct pt_regs)) ? -EFAULT : 0;
21443 + * ptrace_get_reg()
21445 + * Get contents of register REGNO in task TASK.
21447 +static unsigned long ptrace_get_reg(struct task_struct *task, int regno)
21449 + if (regno < sizeof(struct pt_regs)) {
21450 + struct pt_regs *pt_regs = task_pt_regs(task);
21451 + return *(unsigned long *)((long) pt_regs + regno);
21458 + * ptrace_put_reg()
21459 + * Write contents of register REGNO in task TASK.
21461 +static int ptrace_put_reg(struct task_struct *task, int regno,
21462 + unsigned long data)
21464 + if (regno <= sizeof(struct pt_regs) && regno != PT_FRAME_TYPE) {
21465 + struct pt_regs *pt_regs = task_pt_regs(task);
21466 + *(unsigned long *)((long) pt_regs + regno) = data;
21473 + * ptrace_disable_single_step()
21474 + * Disable Single Step
21476 +static int ptrace_disable_single_step(struct task_struct *task)
21479 + * Single Step not yet implemented, so must always be disabled
21485 + * ptrace_disable()
21486 + * Make sure the single step bit is not set.
21487 + * Called by kernel/ptrace.c when detaching..
21489 +void ptrace_disable(struct task_struct *child)
21491 + ptrace_disable_single_step(child);
21496 + * architecture specific ptrace routine.
21498 +long arch_ptrace(struct task_struct *child, long request, long addr, long data)
21501 + switch (request) {
21502 + /* when I and D space are separate, these will need to be fixed. */
21503 + case PTRACE_PEEKTEXT: /* read word at location addr. */
21504 + case PTRACE_PEEKDATA:
21505 + ret = generic_ptrace_peekdata(child, addr, data);
21508 + /* read the word at location addr in the USER area. */
21509 + case PTRACE_PEEKUSR: {
21510 + unsigned long tmp;
21513 + if (((unsigned long) addr > PT_INTERP_FDPIC_LOADMAP)
21517 + tmp = 0; /* Default return condition */
21520 + if (addr < sizeof(struct pt_regs)) {
21521 + tmp = ptrace_get_reg(child, addr);
21522 + } else if (addr == PT_TEXT_ADDR) {
21523 + tmp = child->mm->start_code;
21524 + } else if (addr == PT_TEXT_END_ADDR) {
21525 + tmp = child->mm->end_code;
21526 + } else if (addr == PT_DATA_ADDR) {
21527 + tmp = child->mm->start_data;
21528 + } else if (addr == PT_EXEC_FDPIC_LOADMAP) {
21529 +#ifdef CONFIG_BINFMT_ELF_FDPIC
21530 + tmp = child->mm->context.exec_fdpic_loadmap;
21532 + } else if (addr == PT_INTERP_FDPIC_LOADMAP) {
21533 +#ifdef CONFIG_BINFMT_ELF_FDPIC
21534 + tmp = child->mm->context.interp_fdpic_loadmap;
21540 + ret = put_user(tmp, (unsigned long *)data);
21544 + case PTRACE_POKETEXT: /* write the word at location addr. */
21545 + case PTRACE_POKEDATA:
21546 + ret = generic_ptrace_pokedata(child, addr, data);
21549 + * If we just changed some code so we need to
21550 + * correct the caches
21552 + if (request == PTRACE_POKETEXT && ret == 0) {
21553 + flush_icache_range(addr, addr + 4);
21557 + case PTRACE_POKEUSR: /* write the word at location addr
21558 + * in the USER area */
21561 + if (((unsigned long) addr > PT_DATA_ADDR) || (addr & 3))
21564 + if (addr < sizeof(struct pt_regs)) {
21565 + ret = ptrace_put_reg(child, addr, data);
21569 + case PTRACE_SYSCALL: /* continue and stop at next (return from)
21571 + case PTRACE_CONT: { /* restart after signal. */
21574 + if (!valid_signal(data))
21576 + if (request == PTRACE_SYSCALL)
21577 + set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
21579 + clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
21580 + child->exit_code = data;
21581 + /* make sure the single step bit is not set. */
21582 + ptrace_disable_single_step(child);
21583 + wake_up_process(child);
21589 + * make the child exit. Best I can do is send it a sigkill.
21590 + * perhaps it should be put in the status that it wants to exit.
21592 + case PTRACE_KILL: {
21594 + if (child->exit_state == EXIT_ZOMBIE) /* already dead */
21596 + child->exit_code = SIGKILL;
21597 + /* make sure the single step bit is not set. */
21598 + ptrace_disable_single_step(child);
21599 + wake_up_process(child);
21603 + case PTRACE_DETACH: /* detach a process that was attached. */
21604 + ret = ptrace_detach(child, data);
21607 + case PTRACE_GETREGS: /* Get all gp regs from the child. */
21608 + ptrace_getregs(child, (unsigned long *)data);
21612 + case PTRACE_SETREGS: { /* Set all gp regs in the child. */
21614 + unsigned long tmp;
21615 + int count = sizeof(struct pt_regs) / sizeof(unsigned long);
21616 + for (i = 0; i < count; i++) {
21617 + if (get_user(tmp, (unsigned long *) data)) {
21621 + ptrace_put_reg(child, sizeof(unsigned long) * i, tmp);
21622 + data += sizeof(long);
21629 + return ptrace_request(child, request, addr, data);
21637 + * called by syscall enter/exit when the TIF_SYSCALL_TRACE bit is set.
21639 +asmlinkage void syscall_trace(void)
21641 + struct task_struct *cur = current;
21642 + if (!test_thread_flag(TIF_SYSCALL_TRACE))
21644 + if (!(cur->ptrace & PT_PTRACED))
21646 + ptrace_notify(SIGTRAP | ((cur->ptrace & PT_TRACESYSGOOD)
21649 + * this isn't the same as continuing with a signal, but it will do
21650 + * for normal use. strace only continues with a signal if the
21651 + * stopping signal is not SIGTRAP. -brl
21653 + if (cur->exit_code) {
21654 + send_sig(cur->exit_code, current, 1);
21655 + current->exit_code = 0;
21658 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/semaphore.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/semaphore.c
21659 --- linux-2.6.30.10/arch/ubicom32/kernel/semaphore.c 1970-01-01 02:00:00.000000000 +0200
21660 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/semaphore.c 2009-12-11 11:45:11.000000000 +0200
21663 + * arch/ubicom32/kernel/semaphore.c
21664 + * Ubicom32 architecture semaphore implementation.
21666 + * (C) Copyright 2009, Ubicom, Inc.
21668 + * This file is part of the Ubicom32 Linux Kernel Port.
21670 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
21671 + * it and/or modify it under the terms of the GNU General Public License
21672 + * as published by the Free Software Foundation, either version 2 of the
21673 + * License, or (at your option) any later version.
21675 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
21676 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
21677 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
21678 + * the GNU General Public License for more details.
21680 + * You should have received a copy of the GNU General Public License
21681 + * along with the Ubicom32 Linux Kernel Port. If not,
21682 + * see <http://www.gnu.org/licenses/>.
21684 + * Ubicom32 implementation derived from (with many thanks):
21690 + * Generic semaphore code. Buyer beware. Do your own
21691 + * specific changes in <asm/semaphore-helper.h>
21694 +#include <linux/sched.h>
21695 +#include <linux/err.h>
21696 +#include <linux/init.h>
21697 +#include <asm/semaphore-helper.h>
21699 +#ifndef CONFIG_RMW_INSNS
21700 +spinlock_t semaphore_wake_lock;
21704 + * Semaphores are implemented using a two-way counter:
21705 + * The "count" variable is decremented for each process
21706 + * that tries to sleep, while the "waking" variable is
21707 + * incremented when the "up()" code goes to wake up waiting
21710 + * Notably, the inline "up()" and "down()" functions can
21711 + * efficiently test if they need to do any extra work (up
21712 + * needs to do something only if count was negative before
21713 + * the increment operation.
21715 + * waking_non_zero() (from asm/semaphore.h) must execute
21718 + * When __up() is called, the count was negative before
21719 + * incrementing it, and we need to wake up somebody.
21721 + * This routine adds one to the count of processes that need to
21722 + * wake up and exit. ALL waiting processes actually wake up but
21723 + * only the one that gets to the "waking" field first will gate
21724 + * through and acquire the semaphore. The others will go back
21727 + * Note that these functions are only called when there is
21728 + * contention on the lock, and as such all this is the
21729 + * "non-critical" part of the whole semaphore business. The
21730 + * critical part is the inline stuff in <asm/semaphore.h>
21731 + * where we want to avoid any extra jumps and calls.
21733 +void __up(struct semaphore *sem)
21735 + wake_one_more(sem);
21736 + wake_up(&sem->wait);
21740 + * Perform the "down" function. Return zero for semaphore acquired,
21741 + * return negative for signalled out of the function.
21743 + * If called from __down, the return is ignored and the wait loop is
21744 + * not interruptible. This means that a task waiting on a semaphore
21745 + * using "down()" cannot be killed until someone does an "up()" on
21748 + * If called from __down_interruptible, the return value gets checked
21749 + * upon return. If the return value is negative then the task continues
21750 + * with the negative value in the return register (it can be tested by
21753 + * Either form may be used in conjunction with "up()".
21758 +#define DOWN_HEAD(task_state) \
21761 + current->state = (task_state); \
21762 + add_wait_queue(&sem->wait, &wait); \
21765 + * Ok, we're set up. sem->count is known to be less than zero \
21766 + * so we must wait. \
21768 + * We can let go the lock for purposes of waiting. \
21769 + * We re-acquire it after awaking so as to protect \
21770 + * all semaphore operations. \
21772 + * If "up()" is called before we call waking_non_zero() then \
21773 + * we will catch it right away. If it is called later then \
21774 + * we will have to go through a wakeup cycle to catch it. \
21776 + * Multiple waiters contend for the semaphore lock to see \
21777 + * who gets to gate through and who has to wait some more. \
21781 +#define DOWN_TAIL(task_state) \
21782 + current->state = (task_state); \
21784 + current->state = TASK_RUNNING; \
21785 + remove_wait_queue(&sem->wait, &wait);
21787 +void __sched __down(struct semaphore *sem)
21789 + DECLARE_WAITQUEUE(wait, current);
21791 + DOWN_HEAD(TASK_UNINTERRUPTIBLE)
21792 + if (waking_non_zero(sem))
21795 + DOWN_TAIL(TASK_UNINTERRUPTIBLE)
21798 +int __sched __down_interruptible(struct semaphore *sem)
21800 + DECLARE_WAITQUEUE(wait, current);
21803 + DOWN_HEAD(TASK_INTERRUPTIBLE)
21805 + ret = waking_non_zero_interruptible(sem, current);
21808 + /* ret != 0 only if we get interrupted -arca */
21813 + DOWN_TAIL(TASK_INTERRUPTIBLE)
21817 +int __down_trylock(struct semaphore *sem)
21819 + return waking_non_zero_trylock(sem);
21821 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/setup.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/setup.c
21822 --- linux-2.6.30.10/arch/ubicom32/kernel/setup.c 1970-01-01 02:00:00.000000000 +0200
21823 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/setup.c 2009-12-11 11:45:11.000000000 +0200
21826 + * arch/ubicom32/kernel/setup.c
21827 + * Ubicom32 architecture-dependent parts of system setup.
21829 + * (C) Copyright 2009, Ubicom, Inc.
21830 + * Copyright (C) 1999-2007 Greg Ungerer (gerg@snapgear.com)
21831 + * Copyright (C) 1998,1999 D. Jeff Dionne <jeff@uClinux.org>
21832 + * Copyleft ()) 2000 James D. Schettine {james@telos-systems.com}
21833 + * Copyright (C) 1998 Kenneth Albanowski <kjahds@kjahds.com>
21834 + * Copyright (C) 1995 Hamish Macdonald
21835 + * Copyright (C) 2000 Lineo Inc. (www.lineo.com)
21836 + * Copyright (C) 2001 Lineo, Inc. <www.lineo.com>
21837 + * 68VZ328 Fixes/support Evan Stawnyczy <e@lineo.ca>
21839 + * This file is part of the Ubicom32 Linux Kernel Port.
21841 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
21842 + * it and/or modify it under the terms of the GNU General Public License
21843 + * as published by the Free Software Foundation, either version 2 of the
21844 + * License, or (at your option) any later version.
21846 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
21847 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
21848 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
21849 + * the GNU General Public License for more details.
21851 + * You should have received a copy of the GNU General Public License
21852 + * along with the Ubicom32 Linux Kernel Port. If not,
21853 + * see <http://www.gnu.org/licenses/>.
21855 + * Ubicom32 implementation derived from (with many thanks):
21861 +#include <linux/kernel.h>
21862 +#include <linux/sched.h>
21863 +#include <linux/delay.h>
21864 +#include <linux/interrupt.h>
21865 +#include <linux/fb.h>
21866 +#include <linux/module.h>
21867 +#include <linux/console.h>
21868 +#include <linux/errno.h>
21869 +#include <linux/string.h>
21870 +#include <linux/bootmem.h>
21871 +#include <linux/seq_file.h>
21872 +#include <linux/init.h>
21874 +#include <asm/devtree.h>
21875 +#include <asm/setup.h>
21876 +#include <asm/irq.h>
21877 +#include <asm/machdep.h>
21878 +#include <asm/pgtable.h>
21879 +#include <asm/pgalloc.h>
21880 +#include <asm/ubicom32-common.h>
21881 +#include <asm/processor.h>
21882 +#include <asm/bootargs.h>
21883 +#include <asm/thread.h>
21885 +unsigned long memory_start;
21886 +EXPORT_SYMBOL(memory_start);
21888 +unsigned long memory_end;
21889 +EXPORT_SYMBOL(memory_end);
21891 +static char __initdata command_line[COMMAND_LINE_SIZE];
21892 +#ifdef CONFIG_CMDLINE_BOOL
21893 +static char __initdata builtin_cmdline[COMMAND_LINE_SIZE] = CONFIG_CMDLINE;
21896 +extern int _stext, _etext, _sdata, _edata, _sbss, _ebss, _end;
21900 + * Setup the architecture dependent portions of the system.
21902 +void __init setup_arch(char **cmdline_p)
21904 + int bootmap_size;
21905 + unsigned long ram_start;
21907 + processor_init();
21911 + * Use the link for memory_start from the link and the processor
21912 + * node for memory_end.
21914 + memory_start = PAGE_ALIGN(((unsigned long)&_end));
21915 + processor_dram(&ram_start, &memory_end);
21917 + init_mm.start_code = (unsigned long) &_stext;
21918 + init_mm.end_code = (unsigned long) &_etext;
21919 + init_mm.end_data = (unsigned long) &_edata;
21920 + init_mm.brk = (unsigned long) 0;
21923 + * bootexec copies the original default command line to end of memory.
21924 + * u-boot can modify it there (i.e. to enable network boot) and the
21925 + * kernel picks up the modified version.
21927 + * mainexec creates a `new default' command_line which is in the
21928 + * bootargs devnode. It is updated on every firmware update but
21929 + * not used at the moment.
21931 + strlcpy(boot_command_line, (char *)(memory_end - COMMAND_LINE_SIZE), COMMAND_LINE_SIZE);
21933 +#ifdef CONFIG_CMDLINE_BOOL
21934 +#ifdef CONFIG_CMDLINE_OVERRIDE
21935 + strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE);
21937 + if (builtin_cmdline[0]) {
21938 + /* append boot loader cmdline to builtin */
21939 + strlcat(builtin_cmdline, " ", COMMAND_LINE_SIZE);
21940 + strlcat(builtin_cmdline, boot_command_line, COMMAND_LINE_SIZE);
21941 + strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE);
21946 + strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
21947 + *cmdline_p = command_line;
21949 + parse_early_param();
21951 + printk(KERN_INFO "%s Processor, Ubicom, Inc. <www.ubicom.com>\n", CPU);
21953 +#if defined(DEBUG)
21954 + printk(KERN_DEBUG "KERNEL -> TEXT=0x%06x-0x%06x DATA=0x%06x-0x%06x "
21955 + "BSS=0x%06x-0x%06x\n", (int) &_stext, (int) &_etext,
21956 + (int) &_sdata, (int) &_edata,
21957 + (int) &_sbss, (int) &_ebss);
21958 + printk(KERN_DEBUG "MEMORY -> ROMFS=0x%06x-0x%06x MEM=0x%06x-0x%06x\n ",
21959 + (int) &_ebss, (int) memory_start,
21960 + (int) memory_start, (int) memory_end);
21964 + if (strlen(*cmdline_p))
21965 + printk(KERN_DEBUG "Command line: '%s'\n", *cmdline_p);
21968 +#if defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_DUMMY_CONSOLE)
21969 + conswitchp = &dummy_con;
21973 + * If we have a device tree, see if we have the nodes we need.
21980 + * From the arm initialization comment:
21982 + * This doesn't seem to be used by the Linux memory manager any
21983 + * more, but is used by ll_rw_block. If we can get rid of it, we
21984 + * also get rid of some of the stuff above as well.
21986 + * Note: max_low_pfn and max_pfn reflect the number of _pages_ in
21987 + * the system, not the maximum PFN.
21989 + max_pfn = max_low_pfn = (memory_end - PAGE_OFFSET) >> PAGE_SHIFT;
21992 + * Give all the memory to the bootmap allocator, tell it to put the
21993 + * boot mem_map at the start of memory.
21995 + bootmap_size = init_bootmem_node(
21997 + memory_start >> PAGE_SHIFT, /* map goes here */
21998 + PAGE_OFFSET >> PAGE_SHIFT, /* 0 on coldfire */
21999 + memory_end >> PAGE_SHIFT);
22001 + * Free the usable memory, we have to make sure we do not free
22002 + * the bootmem bitmap so we then reserve it after freeing it :-)
22004 + free_bootmem(memory_start, memory_end - memory_start);
22005 + reserve_bootmem(memory_start, bootmap_size, BOOTMEM_DEFAULT);
22008 + * Get kmalloc into gear.
22013 + * Fix up the thread_info structure, indicate this is a mainline Linux
22014 + * thread and setup the sw_ksp().
22016 + sw_ksp[thread_get_self()] = (unsigned int) current_thread_info();
22017 + thread_set_mainline(thread_get_self());
22019 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/signal.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/signal.c
22020 --- linux-2.6.30.10/arch/ubicom32/kernel/signal.c 1970-01-01 02:00:00.000000000 +0200
22021 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/signal.c 2009-12-11 11:45:11.000000000 +0200
22024 + * arch/ubicom32/kernel/signal.c
22025 + * Ubicom32 architecture signal handling implementation.
22027 + * (C) Copyright 2009, Ubicom, Inc.
22028 + * Copyright (C) 1991, 1992 Linus Torvalds
22029 + * Linux/m68k support by Hamish Macdonald
22030 + * 68060 fixes by Jesper Skov
22031 + * 1997-12-01 Modified for POSIX.1b signals by Andreas Schwab
22032 + * mathemu support by Roman Zippel
22033 + * ++roman (07/09/96): implemented signal stacks
22035 + * This file is part of the Ubicom32 Linux Kernel Port.
22037 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
22038 + * it and/or modify it under the terms of the GNU General Public License
22039 + * as published by the Free Software Foundation, either version 2 of the
22040 + * License, or (at your option) any later version.
22042 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
22043 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
22044 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
22045 + * the GNU General Public License for more details.
22047 + * You should have received a copy of the GNU General Public License
22048 + * along with the Ubicom32 Linux Kernel Port. If not,
22049 + * see <http://www.gnu.org/licenses/>.
22051 + * Ubicom32 implementation derived from (with many thanks):
22056 + * mathemu support by Roman Zippel
22057 + * (Note: fpstate in the signal context is completely ignored for the emulator
22058 + * and the internal floating point format is put on stack)
22060 + * ++roman (07/09/96): implemented signal stacks (specially for tosemu on
22061 + * Atari :-) Current limitation: Only one sigstack can be active at one time.
22062 + * If a second signal with SA_ONSTACK set arrives while working on a sigstack,
22063 + * SA_ONSTACK is ignored. This behaviour avoids lots of trouble with nested
22064 + * signal handlers!
22067 +#include <linux/module.h>
22068 +#include <linux/sched.h>
22069 +#include <linux/mm.h>
22070 +#include <linux/kernel.h>
22071 +#include <linux/signal.h>
22072 +#include <linux/syscalls.h>
22073 +#include <linux/errno.h>
22074 +#include <linux/wait.h>
22075 +#include <linux/ptrace.h>
22076 +#include <linux/unistd.h>
22077 +#include <linux/stddef.h>
22078 +#include <linux/highuid.h>
22079 +#include <linux/tty.h>
22080 +#include <linux/personality.h>
22081 +#include <linux/binfmts.h>
22083 +#include <asm/setup.h>
22084 +#include <asm/uaccess.h>
22085 +#include <asm/pgtable.h>
22086 +#include <asm/traps.h>
22087 +#include <asm/ucontext.h>
22089 +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
22092 + * asm signal return handlers.
22094 +void ret_from_user_signal(void);
22095 +void ret_from_user_rt_signal(void);
22096 +asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs);
22099 + * Common signal suspend implementation
22101 +static int signal_suspend(sigset_t *saveset, struct pt_regs *regs)
22103 + regs->dn[0] = -EINTR;
22105 + current->state = TASK_INTERRUPTIBLE;
22107 + if (!do_signal(saveset, regs)) {
22111 + * If the current frame type is a signal trampoline we are
22112 + * actually going to call the signal handler so we return the
22113 + * desired d0 as the return value.
22115 + if (regs->frame_type == UBICOM32_FRAME_TYPE_SIGTRAMP) {
22116 + return regs->dn[0];
22121 + * Should never get here
22128 + * Atomically swap in the new signal mask, and wait for a signal.
22130 +asmlinkage int do_sigsuspend(struct pt_regs *regs)
22132 + old_sigset_t mask = regs->dn[0];
22133 + sigset_t saveset;
22135 + mask &= _BLOCKABLE;
22136 + spin_lock_irq(¤t->sighand->siglock);
22137 + saveset = current->blocked;
22138 + siginitset(¤t->blocked, mask);
22139 + recalc_sigpending();
22140 + spin_unlock_irq(¤t->sighand->siglock);
22143 + * Call common handler
22145 + return signal_suspend(&saveset, regs);
22149 +do_rt_sigsuspend(struct pt_regs *regs)
22151 + sigset_t *unewset = (sigset_t *)regs->dn[0];
22152 + size_t sigsetsize = (size_t)regs->dn[1];
22153 + sigset_t saveset, newset;
22155 + /* XXX: Don't preclude handling different sized sigset_t's. */
22156 + if (sigsetsize != sizeof(sigset_t))
22159 + if (copy_from_user(&newset, unewset, sizeof(newset)))
22161 + sigdelsetmask(&newset, ~_BLOCKABLE);
22163 + spin_lock_irq(¤t->sighand->siglock);
22164 + saveset = current->blocked;
22165 + current->blocked = newset;
22166 + recalc_sigpending();
22167 + spin_unlock_irq(¤t->sighand->siglock);
22170 + * Call common handler
22172 + return signal_suspend(&saveset, regs);
22176 +sys_sigaction(int sig, const struct old_sigaction *act,
22177 + struct old_sigaction *oact)
22179 + struct k_sigaction new_ka, old_ka;
22183 + old_sigset_t mask;
22184 + if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
22185 + __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
22186 + __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
22188 + __get_user(new_ka.sa.sa_flags, &act->sa_flags);
22189 + __get_user(mask, &act->sa_mask);
22190 + siginitset(&new_ka.sa.sa_mask, mask);
22193 + ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
22195 + if (!ret && oact) {
22196 + if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
22197 + __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
22198 + __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
22200 + __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
22201 + __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
22208 +do_sys_sigaltstack(struct pt_regs *regs)
22210 + const stack_t *uss = (stack_t *) regs->dn[0];
22211 + stack_t *uoss = (stack_t *)regs->dn[1];
22212 + return do_sigaltstack(uss, uoss, regs->an[7]);
22216 + * fdpic_func_descriptor describes sa_handler when the application is FDPIC
22218 +struct fdpic_func_descriptor {
22219 + unsigned long text;
22220 + unsigned long GOT;
22224 + * rt_sigframe is stored on the user stack immediately before (above)
22225 + * the signal handlers stack.
22227 +struct rt_sigframe
22229 + unsigned long syscall_number; /* This holds __NR_rt_sigreturn. */
22230 + unsigned long restore_all_regs; /* This field gets set to 1 if the frame
22231 + * type is TRAP or INTERRUPT. */
22233 + struct ucontext uc;
22239 + * Do a signal return; undo the signal stack.
22241 +asmlinkage int do_sigreturn(unsigned long __unused)
22247 +asmlinkage int do_rt_sigreturn(struct pt_regs *regs)
22249 + unsigned long usp = regs->an[7];
22250 + struct rt_sigframe *frame = (struct rt_sigframe *)(usp);
22253 + if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
22255 + if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
22258 + sigdelsetmask(&set, ~_BLOCKABLE);
22259 + spin_lock_irq(¤t->sighand->siglock);
22260 + current->blocked = set;
22261 + recalc_sigpending();
22262 + spin_unlock_irq(¤t->sighand->siglock);
22264 + if (copy_from_user(regs, &frame->uc.uc_mcontext, sizeof(struct pt_regs)))
22266 + return regs->dn[0];
22269 + force_sig(SIGSEGV, current);
22273 +static inline void *
22274 +get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
22276 + unsigned long usp;
22278 + /* Default to using normal stack. */
22279 + usp = regs->an[7];
22281 + /* This is the X/Open sanctioned signal stack switching. */
22282 + if (ka->sa.sa_flags & SA_ONSTACK) {
22283 + if (!sas_ss_flags(usp))
22284 + usp = current->sas_ss_sp + current->sas_ss_size;
22286 + return (void *)((usp - frame_size) & ~0x3);
22290 + * signal_trampoline: Defined in ubicom32_syscall.S
22292 +asmlinkage void signal_trampoline(void)__attribute__((naked));
22294 +static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
22295 + sigset_t *set, struct pt_regs *regs)
22297 + struct rt_sigframe *frame;
22300 + frame = (struct rt_sigframe *) get_sigframe(ka, regs, sizeof(*frame));
22303 + * The 'err |=' have been may criticized as bad code style, but I
22304 + * strongly suspect that we want this code to be fast. So for
22305 + * now it stays as is.
22307 + err |= __put_user( ( (current_thread_info()->exec_domain)
22308 + && (current_thread_info()->exec_domain->signal_invmap)
22310 + ? current_thread_info()->exec_domain->signal_invmap[sig]
22311 + : sig, &frame->sig);
22312 + err |= __put_user(info, &frame->info);
22314 + /* Create the ucontext. */
22315 + err |= __put_user(0, &frame->uc.uc_flags);
22316 + err |= __put_user(0, &frame->uc.uc_link);
22317 + err |= __put_user((void *)current->sas_ss_sp,
22318 + &frame->uc.uc_stack.ss_sp);
22319 + err |= __put_user(sas_ss_flags(regs->an[7]),
22320 + &frame->uc.uc_stack.ss_flags);
22321 + err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
22322 + err |= __put_user(__NR_rt_sigreturn, &frame->syscall_number);
22323 + if ((regs->frame_type == UBICOM32_FRAME_TYPE_TRAP) ||
22324 + (regs->frame_type == UBICOM32_FRAME_TYPE_INTERRUPT)) {
22325 + err |= __put_user(1, &frame->restore_all_regs);
22327 + err |= __put_user(0, &frame->restore_all_regs);
22329 + err |= copy_to_user (&frame->uc.uc_mcontext.sc_regs, regs, sizeof(struct pt_regs));
22330 + err |= copy_to_user (&frame->uc.uc_sigmask, set, sizeof(*set));
22333 + goto give_sigsegv;
22336 + * Set up registers for signal handler NOTE: Do not modify dn[14], it
22337 + * contains the userspace tls pointer, so it important that it carries
22338 + * over to the signal handler.
22340 + regs->an[7] = (unsigned long)frame;
22341 + regs->pc = (unsigned long) signal_trampoline;
22342 + regs->an[5] = (unsigned long) signal_trampoline;
22343 + regs->dn[0] = sig;
22344 + regs->dn[1] = (unsigned long) frame->info;
22345 + regs->dn[2] = (unsigned int) &frame->uc;
22348 + * If this is FDPIC then the signal handler is actually a function
22351 + if (current->personality & FDPIC_FUNCPTRS) {
22352 + struct fdpic_func_descriptor __user *funcptr =
22353 + (struct fdpic_func_descriptor *) ka->sa.sa_handler;
22354 + err |= __get_user(regs->dn[3], &funcptr->text);
22355 + err |= __get_user(regs->an[0], &funcptr->GOT);
22357 + goto give_sigsegv;
22360 + * The funcdesc must be in a3 as this is required for the lazy
22361 + * resolver in ld.so, if the application is not FDPIC a3 is not
22364 + regs->an[3] = (unsigned long) funcptr;
22367 + regs->dn[3] = (unsigned long)ka->sa.sa_handler;
22371 + regs->frame_type = UBICOM32_FRAME_TYPE_SIGTRAMP;
22376 + /* user space exception */
22377 + force_sigsegv(sig, current);
22380 +static inline void
22381 +handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
22383 + switch (regs->dn[0]) {
22384 + case -ERESTARTNOHAND:
22385 + if (!has_handler)
22387 + regs->dn[0] = -EINTR;
22390 + case -ERESTARTSYS:
22391 + if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) {
22392 + regs->dn[0] = -EINTR;
22395 + /* fallthrough */
22396 + case -ERESTARTNOINTR:
22398 + regs->dn[0] = regs->original_dn_0;
22400 + regs->an[5] -= 8;
22406 + * OK, we're invoking a handler
22409 +handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
22410 + sigset_t *oldset, struct pt_regs *regs)
22412 + /* are we from a system call? */
22413 + if (regs->frame_type == -1)
22414 + /* If so, check system call restarting.. */
22415 + handle_restart(regs, ka, 1);
22417 + /* set up the stack frame */
22418 + setup_rt_frame(sig, ka, info, oldset, regs);
22420 + if (ka->sa.sa_flags & SA_ONESHOT)
22421 + ka->sa.sa_handler = SIG_DFL;
22423 + spin_lock_irq(¤t->sighand->siglock);
22424 + sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
22425 + if (!(ka->sa.sa_flags & SA_NODEFER))
22426 + sigaddset(¤t->blocked,sig);
22427 + recalc_sigpending();
22428 + spin_unlock_irq(¤t->sighand->siglock);
22432 + * Note that 'init' is a special process: it doesn't get signals it doesn't
22433 + * want to handle. Thus you cannot kill init even with a SIGKILL even by
22436 +asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
22438 + struct k_sigaction ka;
22443 + * We want the common case to go fast, which
22444 + * is why we may in certain cases get here from
22445 + * kernel mode. Just return without doing anything
22448 + if (!user_mode(regs))
22452 + oldset = ¤t->blocked;
22454 + signr = get_signal_to_deliver(&info, &ka, regs, NULL);
22456 + /* Whee! Actually deliver the signal. */
22457 + handle_signal(signr, &ka, &info, oldset, regs);
22461 + /* Did we come from a system call? */
22462 + if (regs->frame_type == -1) {
22463 + /* Restart the system call - no handlers present */
22464 + handle_restart(regs, NULL, 0);
22471 + * sys_sigreturn()
22472 + * Return handler for signal clean-up.
22474 + * NOTE: Ubicom32 does not use this syscall. Instead we rely
22475 + * on do_rt_sigreturn().
22477 +asmlinkage long sys_sigreturn(void)
22481 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/smp.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/smp.c
22482 --- linux-2.6.30.10/arch/ubicom32/kernel/smp.c 1970-01-01 02:00:00.000000000 +0200
22483 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/smp.c 2009-12-11 11:45:11.000000000 +0200
22486 + * arch/ubicom32/kernel/smp.c
22487 + * SMP implementation for Ubicom32 processors.
22489 + * (C) Copyright 2009, Ubicom, Inc.
22490 + * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
22491 + * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
22492 + * Copyright (C) 2001,2004 Grant Grundler <grundler@parisc-linux.org>
22494 + * This file is part of the Ubicom32 Linux Kernel Port.
22496 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
22497 + * it and/or modify it under the terms of the GNU General Public License
22498 + * as published by the Free Software Foundation, either version 2 of the
22499 + * License, or (at your option) any later version.
22501 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
22502 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
22503 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
22504 + * the GNU General Public License for more details.
22506 + * You should have received a copy of the GNU General Public License
22507 + * along with the Ubicom32 Linux Kernel Port. If not,
22508 + * see <http://www.gnu.org/licenses/>.
22510 + * Ubicom32 implementation derived from (with many thanks):
22516 +#include <linux/types.h>
22517 +#include <linux/spinlock.h>
22518 +#include <linux/slab.h>
22520 +#include <linux/kernel.h>
22521 +#include <linux/bootmem.h>
22522 +#include <linux/module.h>
22523 +#include <linux/sched.h>
22524 +#include <linux/init.h>
22525 +#include <linux/interrupt.h>
22526 +#include <linux/smp.h>
22527 +#include <linux/kernel_stat.h>
22528 +#include <linux/mm.h>
22529 +#include <linux/err.h>
22530 +#include <linux/delay.h>
22531 +#include <linux/bitops.h>
22532 +#include <linux/cpu.h>
22533 +#include <linux/profile.h>
22534 +#include <linux/delay.h>
22535 +#include <linux/io.h>
22536 +#include <linux/ptrace.h>
22537 +#include <linux/unistd.h>
22538 +#include <linux/irq.h>
22540 +#include <asm/system.h>
22541 +#include <asm/atomic.h>
22542 +#include <asm/current.h>
22543 +#include <asm/tlbflush.h>
22544 +#include <asm/timex.h>
22545 +#include <asm/cpu.h>
22546 +#include <asm/irq.h>
22547 +#include <asm/processor.h>
22548 +#include <asm/thread.h>
22549 +#include <asm/sections.h>
22550 +#include <asm/ip5000.h>
22553 + * Mask the debug printout for IPI because they are too verbose
22554 + * for regular debugging.
22557 +// #define DEBUG_SMP 1
22558 +#if !defined(DEBUG_SMP)
22559 +#define smp_debug(lvl, ...)
22561 +static unsigned int smp_debug_lvl = 50;
22562 +#define smp_debug(lvl, printargs...) \
22563 + if (lvl >= smp_debug_lvl) { \
22564 + printk(printargs); \
22568 +#if !defined(DEBUG_SMP)
22569 +#define DEBUG_ASSERT(cond)
22571 +#define DEBUG_ASSERT(cond) \
22578 + * List of IPI Commands (more than one can be set at a time).
22580 +enum ipi_message_type {
22584 + IPI_CALL_FUNC_SINGLE,
22590 + * We maintain a hardware thread oriented view of online threads
22591 + * and those involved or needing IPI.
22593 +static volatile unsigned long smp_online_threads = 0;
22594 +static volatile unsigned long smp_needs_ipi = 0;
22595 +static volatile unsigned long smp_inside_ipi = 0;
22596 +static unsigned long smp_irq_affinity[NR_IRQS];
22599 + * What do we need to track on a per cpu/thread basis?
22601 +DEFINE_PER_CPU(struct cpuinfo_ubicom32, cpu_data);
22604 + * Each thread cpuinfo IPI information is guarded by a lock
22605 + * that is kept local to this file.
22607 +DEFINE_PER_CPU(spinlock_t, ipi_lock) = SPIN_LOCK_UNLOCKED;
22610 + * The IPI(s) are based on a software IRQ through the LDSR.
22612 +unsigned int smp_ipi_irq;
22615 + * Define a spinlock so that only one cpu is able to modify the
22616 + * smp_needs_ipi and to set/clear the IRQ at a time.
22618 +DEFINE_SPINLOCK(smp_ipi_lock);
22621 + * smp_halt_processor()
22622 + * Halt this hardware thread.
22624 +static void smp_halt_processor(void)
22626 + int cpuid = thread_get_self();
22627 + cpu_clear(smp_processor_id(), cpu_online_map);
22628 + local_irq_disable();
22629 + printk(KERN_EMERG "cpu[%d] has halted. It is not OK to turn off power \
22630 + until all cpu's are off.\n", cpuid);
22632 + thread_suspend();
22637 + * ipi_interrupt()
22638 + * Handle an Interprocessor Interrupt.
22640 +static irqreturn_t ipi_interrupt(int irq, void *dev_id)
22642 + int cpuid = smp_processor_id();
22643 + struct cpuinfo_ubicom32 *p = &per_cpu(cpu_data, cpuid);
22644 + unsigned long ops;
22647 + * Count this now; we may make a call that never returns.
22652 + * We are about to process all ops. If another cpu has stated
22653 + * that we need an IPI, we will have already processed it. By
22654 + * clearing our smp_needs_ipi, and processing all ops,
22655 + * we reduce the number of IPI interrupts. However, this introduces
22656 + * the possibility that smp_needs_ipi will be clear and the soft irq
22657 + * will have gone off; so we need to make the get_affinity() path
22658 + * tolerant of spurious interrupts.
22660 + spin_lock(&smp_ipi_lock);
22661 + smp_needs_ipi &= ~(1 << p->tid);
22662 + spin_unlock(&smp_ipi_lock);
22666 + * Read the set of IPI commands we should handle.
22668 + spinlock_t *lock = &per_cpu(ipi_lock, cpuid);
22670 + ops = p->ipi_pending;
22671 + p->ipi_pending = 0;
22672 + spin_unlock(lock);
22675 + * If we have no IPI commands to execute, break out.
22682 + * Execute the set of commands in the ops word, one command
22683 + * at a time in no particular order. Strip of each command
22684 + * as we execute it.
22687 + unsigned long which = ffz(~ops);
22688 + ops &= ~(1 << which);
22690 + BUG_ON(!irqs_disabled());
22693 + smp_debug(100, KERN_INFO "cpu[%d]: "
22694 + "IPI_NOP\n", cpuid);
22697 + case IPI_RESCHEDULE:
22699 + * Reschedule callback. Everything to be
22700 + * done is done by the interrupt return path.
22702 + smp_debug(200, KERN_INFO "cpu[%d]: "
22703 + "IPI_RESCHEDULE\n", cpuid);
22706 + case IPI_CALL_FUNC:
22707 + smp_debug(100, KERN_INFO "cpu[%d]: "
22708 + "IPI_CALL_FUNC\n", cpuid);
22709 + generic_smp_call_function_interrupt();
22712 + case IPI_CALL_FUNC_SINGLE:
22713 + smp_debug(100, KERN_INFO "cpu[%d]: "
22714 + "IPI_CALL_FUNC_SINGLE\n", cpuid);
22715 + generic_smp_call_function_single_interrupt();
22718 + case IPI_CPU_STOP:
22719 + smp_debug(100, KERN_INFO "cpu[%d]: "
22720 + "IPI_CPU_STOP\n", cpuid);
22721 + smp_halt_processor();
22724 +#if !defined(CONFIG_LOCAL_TIMERS)
22725 + case IPI_CPU_TIMER:
22726 + smp_debug(100, KERN_INFO "cpu[%d]: "
22727 + "IPI_CPU_TIMER\n", cpuid);
22728 +#if defined(CONFIG_GENERIC_CLOCKEVENTS)
22729 + local_timer_interrupt();
22731 + update_process_times(user_mode(get_irq_regs()));
22732 + profile_tick(CPU_PROFILING);
22738 + printk(KERN_CRIT "cpu[%d]: "
22739 + "Unknown IPI: %lu\n", cpuid, which);
22745 + * Let in any pending interrupts
22747 + BUG_ON(!irqs_disabled());
22748 + local_irq_enable();
22749 + local_irq_disable();
22752 + return IRQ_HANDLED;
22757 + * Send an Interprocessor Interrupt.
22759 +static void ipi_send(int cpu, enum ipi_message_type op)
22761 + struct cpuinfo_ubicom32 *p = &per_cpu(cpu_data, cpu);
22762 + spinlock_t *lock = &per_cpu(ipi_lock, cpu);
22763 + unsigned long flags;
22766 + * We protect the setting of the ipi_pending field and ensure
22767 + * that the ipi delivery mechanism and interrupt are atomically
22770 + spin_lock_irqsave(lock, flags);
22771 + p->ipi_pending |= 1 << op;
22772 + spin_unlock_irqrestore(lock, flags);
22774 + spin_lock_irqsave(&smp_ipi_lock, flags);
22775 + smp_needs_ipi |= (1 << p->tid);
22776 + ubicom32_set_interrupt(smp_ipi_irq);
22777 + spin_unlock_irqrestore(&smp_ipi_lock, flags);
22778 + smp_debug(100, KERN_INFO "cpu[%d]: send: %d\n", cpu, op);
22783 + * Send an IPI to each cpu in mask.
22785 +static inline void ipi_send_mask(unsigned int op, const struct cpumask mask)
22788 + for_each_cpu_mask(cpu, mask) {
22789 + ipi_send(cpu, op);
22794 + * ipi_send_allbutself()
22795 + * Send an IPI to all threads but ourselves.
22797 +static inline void ipi_send_allbutself(unsigned int op)
22799 + int self = smp_processor_id();
22800 + struct cpumask result;
22801 + cpumask_copy(&result, &cpu_online_map);
22802 + cpu_clear(self, result);
22803 + ipi_send_mask(op, result);
22807 + * smp_enable_vector()
22809 +static void smp_enable_vector(unsigned int irq)
22811 + ubicom32_clear_interrupt(smp_ipi_irq);
22812 + ldsr_enable_vector(irq);
22816 + * smp_disable_vector()
22817 + * Disable the interrupt by clearing the appropriate bit in the
22818 + * LDSR Mask Register.
22820 +static void smp_disable_vector(unsigned int irq)
22822 + ldsr_disable_vector(irq);
22826 + * smp_mask_vector()
22828 +static void smp_mask_vector(unsigned int irq)
22830 + ldsr_mask_vector(irq);
22834 + * smp_unmask_vector()
22836 +static void smp_unmask_vector(unsigned int irq)
22838 + ldsr_unmask_vector(irq);
22842 + * smp_end_vector()
22843 + * Called once an interrupt is completed (reset the LDSR mask).
22845 +static void smp_end_vector(unsigned int irq)
22847 + struct cpuinfo_ubicom32 *p = &per_cpu(cpu_data, smp_processor_id());
22848 + spin_lock(&smp_ipi_lock);
22849 + smp_inside_ipi &= ~(1 << p->tid);
22850 + if (smp_inside_ipi) {
22851 + spin_unlock(&smp_ipi_lock);
22854 + spin_unlock(&smp_ipi_lock);
22855 + ldsr_unmask_vector(irq);
22856 + smp_debug(100, KERN_INFO "cpu[%d]: unamesk vector\n", smp_processor_id());
22860 + * Special hanlder functions for SMP.
22862 +static struct irq_chip ubicom32_smp_chip = {
22863 + .name = "UbicoIPI",
22865 + .shutdown = NULL,
22866 + .enable = smp_enable_vector,
22867 + .disable = smp_disable_vector,
22869 + .mask = smp_mask_vector,
22870 + .unmask = smp_unmask_vector,
22871 + .end = smp_end_vector,
22875 + * smp_reset_ipi()
22876 + * None of these cpu(s) got their IPI, turn it back on.
22878 + * Note: This is called by the LDSR which is not a full
22879 + * Linux cpu. Thus you must use the raw form of locks
22880 + * because lock debugging will not work on the partial
22881 + * cpu nature of the LDSR.
22883 +void smp_reset_ipi(unsigned long mask)
22885 + __raw_spin_lock(&smp_ipi_lock.raw_lock);
22886 + smp_needs_ipi |= mask;
22887 + smp_inside_ipi &= ~mask;
22888 + ubicom32_set_interrupt(smp_ipi_irq);
22889 + __raw_spin_unlock(&smp_ipi_lock.raw_lock);
22890 + smp_debug(100, KERN_INFO "smp: reset IPIs for: 0x%x\n", mask);
22894 + * smp_get_affinity()
22895 + * Choose the thread affinity for this interrupt.
22897 + * Note: This is called by the LDSR which is not a full
22898 + * Linux cpu. Thus you must use the raw form of locks
22899 + * because lock debugging will not work on the partial
22900 + * cpu nature of the LDSR.
22902 +unsigned long smp_get_affinity(unsigned int irq, int *all)
22904 + unsigned long mask = 0;
22907 + * Most IRQ(s) are delivered in a round robin fashion.
22909 + if (irq != smp_ipi_irq) {
22910 + unsigned long result = smp_irq_affinity[irq] & smp_online_threads;
22911 + DEBUG_ASSERT(result);
22917 + * This is an IPI request. Return all cpu(s) scheduled for an IPI.
22918 + * We also track those cpu(s) that are going to be "receiving" IPI this
22919 + * round. When all CPU(s) have called smp_end_vector(),
22920 + * we will unmask the IPI interrupt.
22922 + __raw_spin_lock(&smp_ipi_lock.raw_lock);
22923 + ubicom32_clear_interrupt(smp_ipi_irq);
22924 + if (smp_needs_ipi) {
22925 + mask = smp_needs_ipi;
22926 + smp_inside_ipi |= smp_needs_ipi;
22927 + smp_needs_ipi = 0;
22929 + __raw_spin_unlock(&smp_ipi_lock.raw_lock);
22935 + * smp_set_affinity()
22936 + * Set the affinity for this irq but store the value in tid(s).
22938 +void smp_set_affinity(unsigned int irq, const struct cpumask *dest)
22941 + unsigned long *paffinity = &smp_irq_affinity[irq];
22944 + * If none specified, all cpus are allowed.
22946 + if (cpus_empty(*dest)) {
22947 + *paffinity = 0xffffffff;
22952 + * Make sure to clear the old value before setting up the
22956 + for_each_cpu_mask(cpuid, *dest) {
22957 + struct cpuinfo_ubicom32 *p = &per_cpu(cpu_data, cpuid);
22958 + *paffinity |= (1 << p->tid);
22963 + * smp_send_stop()
22964 + * Send a stop request to all CPU but this one.
22966 +void smp_send_stop(void)
22968 + ipi_send_allbutself(IPI_CPU_STOP);
22972 + * smp_send_timer_all()
22973 + * Send all cpu(s) but this one, a request to update times.
22975 +void smp_send_timer_all(void)
22977 + ipi_send_allbutself(IPI_CPU_TIMER);
22981 + * smp_timer_broadcast()
22982 + * Use an IPI to broadcast a timer message
22984 +void smp_timer_broadcast(const struct cpumask *mask)
22986 + ipi_send_mask(IPI_CPU_TIMER, *mask);
22990 + * smp_send_reschedule()
22991 + * Send a reschedule request to the specified cpu.
22993 +void smp_send_reschedule(int cpu)
22995 + ipi_send(cpu, IPI_RESCHEDULE);
22999 + * arch_send_call_function_ipi()
23000 + * Cause each cpu in the mask to call the generic function handler.
23002 +void arch_send_call_function_ipi_mask(const struct cpumask *mask)
23005 + for_each_cpu_mask(cpu, *mask) {
23006 + ipi_send(cpu, IPI_CALL_FUNC);
23011 + * arch_send_call_function_single_ipi()
23012 + * Cause the specified cpu to call the generic function handler.
23014 +void arch_send_call_function_single_ipi(int cpu)
23016 + ipi_send(cpu, IPI_CALL_FUNC_SINGLE);
23020 + * setup_profiling_timer()
23021 + * Dummy function created to keep Oprofile happy in the SMP case.
23023 +int setup_profiling_timer(unsigned int multiplier)
23029 + * smp_mainline_start()
23030 + * Start a slave thread executing a mainline Linux context.
23032 +static void __init smp_mainline_start(void *arg)
23034 + int cpuid = smp_processor_id();
23035 + struct cpuinfo_ubicom32 *p = &per_cpu(cpu_data, cpuid);
23037 + BUG_ON(p->tid != thread_get_self());
23040 + * Well, support 2.4 linux scheme as well.
23042 + if (cpu_test_and_set(cpuid, cpu_online_map)) {
23043 + printk(KERN_CRIT "cpu[%d]: already initialized!\n", cpuid);
23044 + smp_halt_processor();
23049 + * Initialise the idle task for this CPU
23051 + atomic_inc(&init_mm.mm_count);
23052 + current->active_mm = &init_mm;
23053 + if (current->mm) {
23054 + printk(KERN_CRIT "cpu[%d]: idle task already has memory "
23055 + "management\n", cpuid);
23056 + smp_halt_processor();
23061 + * TODO: X86 does this prior to calling notify, try to understand why?
23063 + preempt_disable();
23065 +#if defined(CONFIG_GENERIC_CLOCKEVENTS)
23067 + * Setup a local timer event so that this cpu will get timer interrupts
23069 + if (local_timer_setup(cpuid) == -1) {
23070 + printk(KERN_CRIT "cpu[%d]: timer alloc failed\n", cpuid);
23071 + smp_halt_processor();
23077 + * Notify those interested that we are up and alive. This must
23078 + * be done before interrupts are enabled. It must also be completed
23079 + * before the bootstrap cpu returns from __cpu_up() (see comment
23080 + * above cpu_set() of the cpu_online_map).
23082 + notify_cpu_starting(cpuid);
23085 + * Indicate that this thread is now online and present. Setting
23086 + * cpu_online_map has the side effect of allowing the bootstrap
23087 + * cpu to continue along; so anything that MUST be done prior to the
23088 + * bootstrap cpu returning from __cpu_up() needs to go above here.
23090 + cpu_set(cpuid, cpu_online_map);
23091 + cpu_set(cpuid, cpu_present_map);
23094 + * Maintain a thread mapping in addition to the cpu mapping.
23096 + smp_online_threads |= (1 << p->tid);
23099 + * Enable interrupts for this thread.
23101 + local_irq_enable();
23104 + * Enter the idle loop and wait for a timer to schedule some work.
23106 + printk(KERN_INFO "cpu[%d]: entering cpu_idle()\n", cpuid);
23109 + /* Not Reached */
23113 + * smp_cpus_done()
23114 + * Called once the kernel_init() has brought up all cpu(s).
23116 +void smp_cpus_done(unsigned int cpu_max)
23123 + * Called to startup a sepcific cpu.
23125 +int __cpuinit __cpu_up(unsigned int cpu)
23127 + struct task_struct *idle;
23128 + unsigned int *stack;
23130 + struct cpuinfo_ubicom32 *p = &per_cpu(cpu_data, cpu);
23133 + * Create an idle task for this CPU.
23135 + idle = fork_idle(cpu);
23136 + if (IS_ERR(idle)) {
23137 + panic("cpu[%d]: fork failed\n", cpu);
23140 + task_thread_info(idle)->cpu = cpu;
23143 + * Setup the sw_ksp[] to point to this new task.
23145 + sw_ksp[p->tid] = (unsigned int)idle->stack;
23146 + stack = (unsigned int *)(sw_ksp[p->tid] + PAGE_SIZE - 8);
23149 + * Cause the specified thread to execute our smp_mainline_start
23150 + * function as a TYPE_NORMAL thread.
23152 + printk(KERN_INFO "cpu[%d]: launching mainline Linux thread\n", cpu);
23153 + if (thread_start(p->tid, smp_mainline_start, (void *)NULL, stack,
23154 + THREAD_TYPE_NORMAL) == -1) {
23155 + printk(KERN_WARNING "cpu[%d]: failed thread_start\n", cpu);
23160 + * Wait for the thread to start up. The thread will set
23161 + * the online bit when it is running. Our caller execpts the
23162 + * cpu to be online if we return 0.
23164 + for (timeout = 0; timeout < 10000; timeout++) {
23165 + if (cpu_online(cpu)) {
23174 + if (!cpu_online(cpu)) {
23175 + printk(KERN_CRIT "cpu[%d]: failed to live after %ld us\n",
23176 + cpu, timeout * 100);
23180 + printk(KERN_INFO "cpu[%d]: came alive after %ld us\n",
23181 + cpu, timeout * 100);
23186 + * Data used by setup_irq for the IPI.
23188 +static struct irqaction ipi_irq = {
23190 + .flags = IRQF_DISABLED | IRQF_PERCPU,
23191 + .handler = ipi_interrupt,
23195 + * smp_prepare_cpus()
23196 + * Mark threads that are available to Linux as possible cpus(s).
23198 +void __init smp_prepare_cpus(unsigned int max_cpus)
23203 + * We will need a software IRQ to send IPI(s). We will use
23204 + * a single software IRQ for all IPI(s).
23206 + if (irq_soft_alloc(&smp_ipi_irq) < 0) {
23207 + panic("no software IRQ is available\n");
23212 + * For the IPI interrupt, we want to use our own chip definition.
23213 + * This allows us to define what happens in SMP IPI without affecting
23214 + * the performance of the other interrupts.
23216 + * Next, Register the IPI interrupt function against the soft IRQ.
23218 + set_irq_chip(smp_ipi_irq, &ubicom32_smp_chip);
23219 + setup_irq(smp_ipi_irq, &ipi_irq);
23222 + * We use the device tree node to determine how many
23223 + * free cpus we will have (up to NR_CPUS) and we indicate
23224 + * that those cpus are present.
23226 + * We need to do this very early in the SMP case
23227 + * because the Linux init code uses the cpu_present_map.
23229 + for_each_possible_cpu(i) {
23231 + struct cpuinfo_ubicom32 *p = &per_cpu(cpu_data, i);
23234 + * Skip the bootstrap cpu
23241 + * If we have a free thread left in the mask,
23242 + * indicate that the cpu is present.
23244 + tid = thread_alloc();
23245 + if (tid == (thread_t)-1) {
23250 + * Save the hardware thread id for this cpu.
23253 + cpu_set(i, cpu_present_map);
23254 + printk(KERN_INFO "cpu[%d]: added to cpu_present_map - tid: %d\n", i, tid);
23259 + * smp_prepare_boot_cpu()
23260 + * Copy the per_cpu data into the appropriate spot for the bootstrap cpu.
23262 + * The code in boot_cpu_init() has already set the boot cpu's
23263 + * state in the possible, present, and online maps.
23265 +void __devinit smp_prepare_boot_cpu(void)
23267 + struct cpuinfo_ubicom32 *p = &per_cpu(cpu_data, 0);
23269 + smp_online_threads |= (1 << p->tid);
23270 + printk(KERN_INFO "cpu[%d]: bootstrap CPU online - tid: %ld\n",
23271 + current_thread_info()->cpu, p->tid);
23275 + * smp_setup_processor_id()
23276 + * Set the current_thread_info() structure cpu value.
23278 + * We set the value to the true hardware thread value that we are running on.
23279 + * NOTE: this function overrides the weak alias function in main.c
23281 +void __init smp_setup_processor_id(void)
23283 + struct cpuinfo_ubicom32 *p = &per_cpu(cpu_data, 0);
23285 + for_each_cpu_mask(i, CPU_MASK_ALL)
23286 + set_cpu_possible(i, true);
23288 + current_thread_info()->cpu = 0;
23289 + p->tid = thread_get_self();
23291 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/stacktrace.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/stacktrace.c
23292 --- linux-2.6.30.10/arch/ubicom32/kernel/stacktrace.c 1970-01-01 02:00:00.000000000 +0200
23293 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/stacktrace.c 2009-12-11 11:45:11.000000000 +0200
23296 + * arch/ubicom32/kernel/stacktrace.c
23297 + * Ubicom32 architecture stack back trace implementation.
23299 + * (C) Copyright 2009, Ubicom, Inc.
23301 + * This file is part of the Ubicom32 Linux Kernel Port.
23303 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
23304 + * it and/or modify it under the terms of the GNU General Public License
23305 + * as published by the Free Software Foundation, either version 2 of the
23306 + * License, or (at your option) any later version.
23308 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
23309 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
23310 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
23311 + * the GNU General Public License for more details.
23313 + * You should have received a copy of the GNU General Public License
23314 + * along with the Ubicom32 Linux Kernel Port. If not,
23315 + * see <http://www.gnu.org/licenses/>.
23317 + * Ubicom32 implementation derived from (with many thanks):
23322 +#include <linux/sched.h>
23323 +#include <linux/stacktrace.h>
23324 +#include <linux/module.h>
23325 +#include <asm/stacktrace.h>
23326 +#include <asm/thread.h>
23327 +#include <asm/ip5000.h>
23330 + * These symbols are filled in by the linker.
23332 +extern unsigned long _stext;
23333 +extern unsigned long _etext;
23335 +extern unsigned long __ocm_text_run_begin;
23336 +extern unsigned long __data_begin;
23339 + * stacktrace_iterate()
23340 + * Walk the stack looking for call and calli instructions on an aligned
23343 + * Trace must point to the top of the current stack frame.
23345 +unsigned long stacktrace_iterate(unsigned long **trace,
23346 + unsigned long stext,
23347 + unsigned long etext,
23348 + unsigned long ocm_stext,
23349 + unsigned long ocm_etext,
23350 + unsigned long sstack,
23351 + unsigned long estack)
23353 + unsigned int thread_trap_en, instruction;
23354 + unsigned long address;
23355 + unsigned int limit = 0;
23356 + unsigned long result = 0;
23357 + unsigned long *sp = *trace;
23360 + * Exclude the current thread from being monitored for traps.
23363 + " thread_get_self_mask d15 \n\t"
23364 + /* save current trap status */
23365 + " and.4 %0, MT_TRAP_EN, d15 \n\t"
23366 + " not.4 d15, d15 \n\t"
23367 + /* disable trap */
23368 + " and.4 MT_TRAP_EN, MT_TRAP_EN, d15 \n\t"
23369 + " pipe_flush 0 \n\t"
23370 + : "=r" (thread_trap_en)
23375 + while (limit++ < 256) {
23377 + * See if we have a valid stack.
23379 + if (!between((unsigned long)sp, sstack, estack)) {
23380 +#ifdef TRAP_DEBUG_STACK_TRACE
23381 + printk(KERN_EMERG "stack address is out of range - "
23382 + "sp: %x, sstack: %x, estack: %x\n",
23383 + (unsigned int)sp, (unsigned int)sstack,
23384 + (unsigned int)estack);
23392 + * Get the value off the stack and back up 4 bytes to what
23393 + * should be the address of a call or calli.
23395 + address = (*sp++) - 4;
23398 + * If the address is not within the text segment, skip this
23401 + if (!between(address, stext, etext) &&
23402 + !between(address, ocm_stext, ocm_etext)) {
23403 +#ifdef TRAP_DEBUG_STACK_TRACE
23404 + printk(KERN_EMERG "not a text address - "
23405 + "address: %08x, stext: %08x, etext: %08x\n"
23406 + "ocm_stext: %08x, ocm_etext: %08x\n",
23407 + (unsigned int)address,
23408 + (unsigned int)stext,
23409 + (unsigned int)etext,
23410 + (unsigned int)ocm_stext,
23411 + (unsigned int)ocm_etext);
23418 + * If the address is not on an aligned boundary it can not be a
23419 + * return address.
23421 + if (address & 0x3) {
23426 + * Read the probable instruction.
23428 + instruction = *(unsigned int *)address;
23431 + * Is this a call instruction?
23433 + if ((instruction & 0xF8000000) == (u32_t)(0x1B << 27)) {
23434 +#ifdef TRAP_DEBUG_STACK_TRACE
23435 + printk(KERN_EMERG "call inst. result: %x, "
23436 + "test: %x\n", (unsigned int)address,
23437 + (unsigned int)instruction);
23440 + result = address;
23445 + * Is this a calli instruction?
23447 + if ((instruction & 0xF8000000) == (u32_t)(0x1E << 27)) {
23448 +#ifdef TRAP_DEBUG_STACK_TRACE
23449 + printk(KERN_EMERG "calli inst. result: %x, "
23450 + "test: %x\n", (unsigned int)address,
23451 + (unsigned int)instruction);
23454 + result = address;
23460 + * Restore the current thread to be monitored for traps.
23462 + if (thread_trap_en) {
23464 + " thread_get_self_mask d15 \n\t"
23465 + " or.4 MT_TRAP_EN, MT_TRAP_EN, d15 \n\t"
23474 +#ifdef CONFIG_STACKTRACE
23476 + * stacktrace_save_entries()
23477 + * Save stack back trace information into the provided trace structure.
23479 +void stacktrace_save_entries(struct task_struct *tsk,
23480 + struct stack_trace *trace,
23481 + unsigned long sp)
23483 + unsigned long code_start = (unsigned long)&_stext;
23484 + unsigned long code_end = (unsigned long)&_etext;
23485 + unsigned long ocm_code_start = (unsigned long)&__ocm_text_run_begin;
23486 + unsigned long ocm_code_end = (unsigned long)&__data_begin;
23487 + unsigned long stack_end = (unsigned long)(tsk->stack + THREAD_SIZE - 8);
23488 + unsigned long stack = (unsigned long)sp;
23489 + unsigned int idx = 0;
23490 + unsigned long *handle;
23491 + int skip = trace->skip;
23493 + handle = (unsigned long *)stack;
23494 + while (idx < trace->max_entries) {
23499 + trace->entries[idx] = stacktrace_iterate(&handle,
23500 + code_start, code_end,
23501 + ocm_code_start, ocm_code_end,
23502 + (unsigned long)stack, stack_end);
23503 + if (trace->entries[idx] == 0) {
23511 + * save_stack_trace()
23512 + * Save the specified amount of the kernel stack trace information
23513 + * for the current task.
23515 +void save_stack_trace(struct stack_trace *trace)
23517 + unsigned long sp = 0;
23519 + " move.4 %0, SP \n\t"
23522 + stacktrace_save_entries(current, trace, sp);
23524 +EXPORT_SYMBOL_GPL(save_stack_trace);
23527 + * save_stack_trace_tsk()
23528 + * Save the specified amount of the kernel stack trace information
23529 + * for the specified task.
23531 + * Note: We assume the specified task is not currently running.
23533 +void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
23535 + stacktrace_save_entries(tsk, trace, tsk->thread.sp);
23537 +EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
23538 +#endif /* CONFIG_STACKTRACE */
23539 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/syscalltable.S linux-2.6.30.10-ubi/arch/ubicom32/kernel/syscalltable.S
23540 --- linux-2.6.30.10/arch/ubicom32/kernel/syscalltable.S 1970-01-01 02:00:00.000000000 +0200
23541 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/syscalltable.S 2009-12-11 11:45:11.000000000 +0200
23544 + * arch/ubicom32/kernel/syscalltable.S
23545 + * <TODO: Replace with short file description>
23547 + * (C) Copyright 2009, Ubicom, Inc.
23549 + * This file is part of the Ubicom32 Linux Kernel Port.
23551 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
23552 + * it and/or modify it under the terms of the GNU General Public License
23553 + * as published by the Free Software Foundation, either version 2 of the
23554 + * License, or (at your option) any later version.
23556 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
23557 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
23558 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
23559 + * the GNU General Public License for more details.
23561 + * You should have received a copy of the GNU General Public License
23562 + * along with the Ubicom32 Linux Kernel Port. If not,
23563 + * see <http://www.gnu.org/licenses/>.
23565 + * Ubicom32 implementation derived from (with many thanks):
23572 + * Copyright (C) 2002, Greg Ungerer (gerg@snapgear.com)
23573 + * Copyright (C) 1998 D. Jeff Dionne <jeff@lineo.ca>, Kenneth Albanowski <kjahds@kjahds.com>,
23574 + * Copyright (C) 2000 Lineo Inc. (www.lineo.com)
23575 + * Copyright (C) 1991, 1992 Linus Torvalds
23578 +#include <linux/sys.h>
23579 +#include <linux/linkage.h>
23580 +#include <asm/unistd.h>
23584 + .global sys_call_table
23586 + .long sys_ni_syscall /* 0 - old "setup()" system call*/
23591 + .long sys_open /* 5 */
23593 + .long sys_waitpid
23596 + .long sys_unlink /* 10 */
23597 + .long execve_intercept
23601 + .long sys_chmod /* 15 */
23602 + .long sys_chown16
23603 + .long sys_ni_syscall /* old break syscall holder */
23606 + .long sys_getpid /* 20 */
23608 + .long sys_oldumount
23609 + .long sys_setuid16
23610 + .long sys_getuid16
23611 + .long sys_stime /* 25 */
23616 + .long sys_utime /* 30 */
23617 + .long sys_ni_syscall /* old stty syscall holder */
23618 + .long sys_ni_syscall /* old gtty syscall holder */
23621 + .long sys_ni_syscall /* 35 */ /* old ftime syscall holder */
23626 + .long sys_rmdir /* 40 */
23630 + .long sys_ni_syscall /* old prof syscall holder */
23631 + .long sys_brk /* 45 */
23632 + .long sys_setgid16
23633 + .long sys_getgid16
23635 + .long sys_geteuid16
23636 + .long sys_getegid16 /* 50 */
23638 + .long sys_umount /* recycled never used phys() */
23639 + .long sys_ni_syscall /* old lock syscall holder */
23641 + .long sys_fcntl /* 55 */
23642 + .long sys_ni_syscall /* old mpx syscall holder */
23643 + .long sys_setpgid
23644 + .long sys_ni_syscall /* old ulimit syscall holder */
23645 + .long sys_ni_syscall
23646 + .long sys_umask /* 60 */
23650 + .long sys_getppid
23651 + .long sys_getpgrp /* 65 */
23653 + .long sys_sigaction
23654 + .long sys_sgetmask
23655 + .long sys_ssetmask
23656 + .long sys_setreuid16 /* 70 */
23657 + .long sys_setregid16
23658 + .long sys_sigsuspend
23659 + .long sys_sigpending
23660 + .long sys_sethostname
23661 + .long sys_setrlimit /* 75 */
23662 + .long sys_old_getrlimit
23663 + .long sys_getrusage
23664 + .long sys_gettimeofday
23665 + .long sys_settimeofday
23666 + .long sys_getgroups16 /* 80 */
23667 + .long sys_setgroups16
23669 + .long sys_symlink
23671 + .long sys_readlink /* 85 */
23673 + .long sys_ni_syscall /* _sys_swapon */
23675 + .long sys_old_readdir
23676 + .long old_mmap /* 90 */
23678 + .long sys_truncate
23679 + .long sys_ftruncate
23681 + .long sys_fchown16 /* 95 */
23682 + .long sys_getpriority
23683 + .long sys_setpriority
23684 + .long sys_ni_syscall /* old profil syscall holder */
23686 + .long sys_fstatfs /* 100 */
23687 + .long sys_ni_syscall /* ioperm for i386 */
23688 + .long sys_socketcall
23690 + .long sys_setitimer
23691 + .long sys_getitimer /* 105 */
23692 + .long sys_newstat
23693 + .long sys_newlstat
23694 + .long sys_newfstat
23695 + .long sys_ni_syscall
23696 + .long sys_ni_syscall /* iopl for i386 */ /* 110 */
23697 + .long sys_vhangup
23698 + .long sys_ni_syscall /* obsolete idle() syscall */
23699 + .long sys_ni_syscall /* vm86old for i386 */
23701 + .long sys_ni_syscall /* 115 */ /* _sys_swapoff */
23702 + .long sys_sysinfo
23705 + .long sys_sigreturn
23706 + .long clone_intercept /* 120 */
23707 + .long sys_setdomainname
23708 + .long sys_newuname
23709 + .long sys_cacheflush /* modify_ldt for i386 */
23710 + .long sys_adjtimex
23711 + .long sys_ni_syscall /* 125 */ /* _sys_mprotect */
23712 + .long sys_sigprocmask
23713 + .long sys_ni_syscall /* old "creat_module" */
23714 + .long sys_init_module
23715 + .long sys_delete_module
23716 + .long sys_ni_syscall /* 130: old "get_kernel_syms" */
23717 + .long sys_quotactl
23718 + .long sys_getpgid
23720 + .long sys_bdflush
23721 + .long sys_sysfs /* 135 */
23722 + .long sys_personality
23723 + .long sys_ni_syscall /* for afs_syscall */
23724 + .long sys_setfsuid16
23725 + .long sys_setfsgid16
23726 + .long sys_llseek /* 140 */
23727 + .long sys_getdents
23730 + .long sys_ni_syscall /* _sys_msync */
23731 + .long sys_readv /* 145 */
23734 + .long sys_fdatasync
23736 + .long sys_ni_syscall /* 150 */ /* _sys_mlock */
23737 + .long sys_ni_syscall /* _sys_munlock */
23738 + .long sys_ni_syscall /* _sys_mlockall */
23739 + .long sys_ni_syscall /* _sys_munlockall */
23740 + .long sys_sched_setparam
23741 + .long sys_sched_getparam /* 155 */
23742 + .long sys_sched_setscheduler
23743 + .long sys_sched_getscheduler
23744 + .long sys_sched_yield
23745 + .long sys_sched_get_priority_max
23746 + .long sys_sched_get_priority_min /* 160 */
23747 + .long sys_sched_rr_get_interval
23748 + .long sys_nanosleep
23749 + .long sys_ni_syscall /* _sys_mremap */
23750 + .long sys_setresuid16
23751 + .long sys_getresuid16 /* 165 */
23752 + .long sys_getpagesize /* _sys_getpagesize */
23753 + .long sys_ni_syscall /* old "query_module" */
23755 + .long sys_ni_syscall /* _sys_nfsservctl */
23756 + .long sys_setresgid16 /* 170 */
23757 + .long sys_getresgid16
23759 + .long sys_rt_sigreturn
23760 + .long sys_rt_sigaction
23761 + .long sys_rt_sigprocmask /* 175 */
23762 + .long sys_rt_sigpending
23763 + .long sys_rt_sigtimedwait
23764 + .long sys_rt_sigqueueinfo
23765 + .long sys_rt_sigsuspend
23766 + .long sys_pread64 /* 180 */
23767 + .long sys_pwrite64
23768 + .long sys_lchown16
23771 + .long sys_capset /* 185 */
23772 + .long sys_sigaltstack
23773 + .long sys_sendfile
23774 + .long sys_ni_syscall /* streams1 */
23775 + .long sys_ni_syscall /* streams2 */
23776 + .long vfork_intercept /* 190 */
23777 + .long sys_getrlimit
23779 + .long sys_truncate64
23780 + .long sys_ftruncate64
23781 + .long sys_stat64 /* 195 */
23782 + .long sys_lstat64
23783 + .long sys_fstat64
23786 + .long sys_getgid /* 200 */
23787 + .long sys_geteuid
23788 + .long sys_getegid
23789 + .long sys_setreuid
23790 + .long sys_setregid
23791 + .long sys_getgroups /* 205 */
23792 + .long sys_setgroups
23794 + .long sys_setresuid
23795 + .long sys_getresuid
23796 + .long sys_setresgid /* 210 */
23797 + .long sys_getresgid
23801 + .long sys_setfsuid /* 215 */
23802 + .long sys_setfsgid
23803 + .long sys_pivot_root
23804 + .long sys_ni_syscall
23805 + .long sys_ni_syscall
23806 + .long sys_getdents64 /* 220 */
23809 + .long sys_setxattr
23810 + .long sys_lsetxattr
23811 + .long sys_fsetxattr /* 225 */
23812 + .long sys_getxattr
23813 + .long sys_lgetxattr
23814 + .long sys_fgetxattr
23815 + .long sys_listxattr
23816 + .long sys_llistxattr /* 230 */
23817 + .long sys_flistxattr
23818 + .long sys_removexattr
23819 + .long sys_lremovexattr
23820 + .long sys_fremovexattr
23821 + .long sys_futex /* 235 */
23822 + .long sys_sendfile64
23823 + .long sys_ni_syscall /* _sys_mincore */
23824 + .long sys_ni_syscall /* _sys_madvise */
23825 + .long sys_fcntl64
23826 + .long sys_readahead /* 240 */
23827 + .long sys_io_setup
23828 + .long sys_io_destroy
23829 + .long sys_io_getevents
23830 + .long sys_io_submit
23831 + .long sys_io_cancel /* 245 */
23832 + .long sys_fadvise64
23833 + .long sys_exit_group
23834 + .long sys_lookup_dcookie
23835 + .long sys_epoll_create
23836 + .long sys_epoll_ctl /* 250 */
23837 + .long sys_epoll_wait
23838 + .long sys_ni_syscall /* _sys_remap_file_pages */
23839 + .long sys_set_tid_address
23840 + .long sys_timer_create
23841 + .long sys_timer_settime /* 255 */
23842 + .long sys_timer_gettime
23843 + .long sys_timer_getoverrun
23844 + .long sys_timer_delete
23845 + .long sys_clock_settime
23846 + .long sys_clock_gettime /* 260 */
23847 + .long sys_clock_getres
23848 + .long sys_clock_nanosleep
23849 + .long sys_statfs64
23850 + .long sys_fstatfs64
23851 + .long sys_tgkill /* 265 */
23853 + .long sys_fadvise64_64
23855 + .long sys_get_mempolicy
23856 + .long sys_set_mempolicy /* 270 */
23857 + .long sys_mq_open
23858 + .long sys_mq_unlink
23859 + .long sys_mq_timedsend
23860 + .long sys_mq_timedreceive
23861 + .long sys_mq_notify /* 275 */
23862 + .long sys_mq_getsetattr
23864 + .long sys_ni_syscall /* for _sys_vserver */
23865 + .long sys_add_key
23866 + .long sys_request_key /* 280 */
23868 + .long sys_ioprio_set
23869 + .long sys_ioprio_get
23870 + .long sys_inotify_init
23871 + .long sys_inotify_add_watch /* 285 */
23872 + .long sys_inotify_rm_watch
23873 + .long sys_migrate_pages
23875 + .long sys_mkdirat
23876 + .long sys_mknodat /* 290 */
23877 + .long sys_fchownat
23878 + .long sys_futimesat
23879 + .long sys_fstatat64
23880 + .long sys_unlinkat
23881 + .long sys_renameat /* 295 */
23883 + .long sys_symlinkat
23884 + .long sys_readlinkat
23885 + .long sys_fchmodat
23886 + .long sys_faccessat /* 300 */
23887 + .long sys_ni_syscall /* Reserved for pselect6 */
23888 + .long sys_ni_syscall /* Reserved for ppoll */
23889 + .long sys_unshare
23890 + .long sys_set_robust_list
23891 + .long sys_get_robust_list /* 305 */
23893 + .long sys_sync_file_range
23895 + .long sys_vmsplice
23896 + .long sys_move_pages /* 310 */
23897 + .long sys_sched_setaffinity
23898 + .long sys_sched_getaffinity
23899 + .long sys_kexec_load
23901 + .long sys_epoll_pwait /* 315 */
23902 + .long sys_utimensat
23903 + .long sys_signalfd
23904 + .long sys_timerfd_create
23905 + .long sys_eventfd
23906 + .long sys_fallocate /* 320 */
23907 + .long sys_timerfd_settime
23908 + .long sys_timerfd_gettime
23909 + .long sys_ni_syscall /* sys_signalfd4 */
23910 + .long sys_ni_syscall /* sys_eventfd2 */
23911 + .long sys_ni_syscall /* sys_epoll_create1 */
23913 + .long sys_ni_syscall /* sys_dup3 */
23914 + .long sys_ni_syscall /* sys_pipe2 */
23915 + .long sys_ni_syscall /* sys_inotify_init1 */
23916 + .rept NR_syscalls-(.-sys_call_table)/4
23917 + .long sys_ni_syscall
23919 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/sys_ubicom32.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/sys_ubicom32.c
23920 --- linux-2.6.30.10/arch/ubicom32/kernel/sys_ubicom32.c 1970-01-01 02:00:00.000000000 +0200
23921 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/sys_ubicom32.c 2009-12-11 11:45:11.000000000 +0200
23924 + * arch/ubicom32/kernel/sys_ubicom32.c
23925 + * Ubicom32 architecture system call support implementation.
23927 + * (C) Copyright 2009, Ubicom, Inc.
23929 + * This file is part of the Ubicom32 Linux Kernel Port.
23931 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
23932 + * it and/or modify it under the terms of the GNU General Public License
23933 + * as published by the Free Software Foundation, either version 2 of the
23934 + * License, or (at your option) any later version.
23936 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
23937 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
23938 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
23939 + * the GNU General Public License for more details.
23941 + * You should have received a copy of the GNU General Public License
23942 + * along with the Ubicom32 Linux Kernel Port. If not,
23943 + * see <http://www.gnu.org/licenses/>.
23945 + * Ubicom32 implementation derived from (with many thanks):
23950 + * This file contains various random system calls that
23951 + * have a non-standard calling sequence on the Linux/ubicom32
23955 +#include <linux/module.h>
23956 +#include <linux/errno.h>
23957 +#include <linux/sched.h>
23958 +#include <linux/mm.h>
23959 +#include <linux/smp.h>
23960 +#include <linux/sem.h>
23961 +#include <linux/msg.h>
23962 +#include <linux/shm.h>
23963 +#include <linux/stat.h>
23964 +#include <linux/syscalls.h>
23965 +#include <linux/mman.h>
23966 +#include <linux/file.h>
23967 +#include <linux/utsname.h>
23968 +#include <linux/ipc.h>
23969 +#include <linux/fs.h>
23970 +#include <linux/uaccess.h>
23971 +#include <linux/unistd.h>
23973 +#include <asm/setup.h>
23974 +#include <asm/traps.h>
23975 +#include <asm/cacheflush.h>
23977 +/* common code for old and new mmaps */
23978 +static inline long do_mmap2(
23979 + unsigned long addr, unsigned long len,
23980 + unsigned long prot, unsigned long flags,
23981 + unsigned long fd, unsigned long pgoff)
23983 + int error = -EBADF;
23984 + struct file *file = NULL;
23986 + flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
23987 + if (!(flags & MAP_ANONYMOUS)) {
23993 + down_write(¤t->mm->mmap_sem);
23994 + error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
23995 + up_write(¤t->mm->mmap_sem);
24003 +asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
24004 + unsigned long prot, unsigned long flags,
24005 + unsigned long fd, unsigned long pgoff)
24007 + return do_mmap2(addr, len, prot, flags, fd, pgoff);
24011 + * Perform the select(nd, in, out, ex, tv) and mmap() system
24012 + * calls. Linux/m68k cloned Linux/i386, which didn't use to be able to
24013 + * handle more than 4 system call parameters, so these system calls
24014 + * used a memory block for parameter passing..
24017 +struct mmap_arg_struct {
24018 + unsigned long addr;
24019 + unsigned long len;
24020 + unsigned long prot;
24021 + unsigned long flags;
24022 + unsigned long fd;
24023 + unsigned long offset;
24026 +asmlinkage int old_mmap(struct mmap_arg_struct *arg)
24028 + struct mmap_arg_struct a;
24029 + int error = -EFAULT;
24031 + if (copy_from_user(&a, arg, sizeof(a)))
24035 + if (a.offset & ~PAGE_MASK)
24038 + a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
24040 + error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd,
24041 + a.offset >> PAGE_SHIFT);
24046 +struct sel_arg_struct {
24048 + fd_set *inp, *outp, *exp;
24049 + struct timeval *tvp;
24052 +asmlinkage int old_select(struct sel_arg_struct *arg)
24054 + struct sel_arg_struct a;
24056 + if (copy_from_user(&a, arg, sizeof(a)))
24058 + /* sys_select() does the appropriate kernel locking */
24059 + return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
24063 + * sys_ipc() is the de-multiplexer for the SysV IPC calls..
24065 + * This is really horribly ugly.
24067 +asmlinkage int sys_ipc(uint call, int first, int second,
24068 + int third, void *ptr, long fifth)
24070 + int version, ret;
24072 + version = call >> 16; /* hack for backward compatibility */
24075 + if (call <= SEMCTL)
24078 + return sys_semop(first, (struct sembuf *)ptr, second);
24080 + return sys_semget(first, second, third);
24082 + union semun fourth;
24085 + if (get_user(fourth.__pad, (void **) ptr))
24087 + return sys_semctl(first, second, third, fourth);
24092 + if (call <= MSGCTL)
24095 + return sys_msgsnd(first, (struct msgbuf *) ptr,
24098 + switch (version) {
24100 + struct ipc_kludge tmp;
24103 + if (copy_from_user(&tmp,
24104 + (struct ipc_kludge *)ptr,
24107 + return sys_msgrcv(first, tmp.msgp, second,
24108 + tmp.msgtyp, third);
24111 + return sys_msgrcv(first,
24112 + (struct msgbuf *) ptr,
24113 + second, fifth, third);
24116 + return sys_msgget((key_t) first, second);
24118 + return sys_msgctl(first, second,
24119 + (struct msqid_ds *) ptr);
24123 + if (call <= SHMCTL)
24126 + switch (version) {
24129 + ret = do_shmat(first, ptr, second, &raddr);
24132 + return put_user(raddr, (ulong __user *) third);
24136 + return sys_shmdt(ptr);
24138 + return sys_shmget(first, second, third);
24140 + return sys_shmctl(first, second, ptr);
24148 +/* sys_cacheflush -- flush (part of) the processor cache. */
24150 +sys_cacheflush(unsigned long addr, int scope, int cache, unsigned long len)
24152 + flush_cache_all();
24156 +asmlinkage int sys_getpagesize(void)
24158 + return PAGE_SIZE;
24160 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/thread.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/thread.c
24161 --- linux-2.6.30.10/arch/ubicom32/kernel/thread.c 1970-01-01 02:00:00.000000000 +0200
24162 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/thread.c 2009-12-11 11:45:11.000000000 +0200
24165 + * arch/ubicom32/kernel/thread.c
24166 + * Ubicom32 architecture hardware thread support.
24168 + * (C) Copyright 2009, Ubicom, Inc.
24170 + * This file is part of the Ubicom32 Linux Kernel Port.
24172 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
24173 + * it and/or modify it under the terms of the GNU General Public License
24174 + * as published by the Free Software Foundation, either version 2 of the
24175 + * License, or (at your option) any later version.
24177 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
24178 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
24179 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
24180 + * the GNU General Public License for more details.
24182 + * You should have received a copy of the GNU General Public License
24183 + * along with the Ubicom32 Linux Kernel Port. If not,
24184 + * see <http://www.gnu.org/licenses/>.
24186 + * Ubicom32 implementation derived from (with many thanks):
24192 +#include <linux/module.h>
24193 +#include <linux/kernel.h>
24194 +#include <linux/init.h>
24195 +#include <linux/sched.h>
24196 +#include <linux/interrupt.h>
24197 +#include <linux/irq.h>
24198 +#include <linux/profile.h>
24199 +#include <linux/clocksource.h>
24200 +#include <linux/types.h>
24201 +#include <asm/ip5000.h>
24202 +#include <asm/machdep.h>
24203 +#include <asm/asm-offsets.h>
24204 +#include <asm/thread.h>
24207 + * TODO: At some point change the name here to be thread_ksp
24209 +unsigned int sw_ksp[THREAD_ARCHITECTURAL_MAX];
24211 +static unsigned int thread_mask = -1;
24212 +static unsigned int thread_mainline_mask;
24216 + * Returning from the called function will disable the thread.
24218 + * This could be a naked call to allow for hwthreads that do not have stacks.
24219 + * However, with -O0, the code still writes to thex stack, and this was
24220 + * corrupting memory just after the callers stack.
24222 +static void thread_entry(void *arg, thread_exec_fn_t exec)
24225 + * Call thread function
24230 + * Complete => Disable self
24232 + thread_disable(thread_get_self());
24237 + * Start the specified function on the specified hardware thread.
24239 +thread_t thread_start(thread_t thread,
24240 + thread_exec_fn_t exec,
24242 + unsigned int *sp_high,
24243 + thread_type_t type)
24248 + unsigned int enabled, mask, csr;
24250 + "move.4 %0, MT_EN\n\t"
24254 + mask = 1 << thread;
24255 + if (enabled & mask) {
24256 + printk(KERN_WARNING "request to enable a previously enabled thread\n");
24257 + return (thread_t)-1;
24261 + * Update thread state
24263 + csr = (thread << 15) | (1 << 14);
24266 + "setcsr_flush 0 \n\t"
24268 + "move.4 A0, #0 \n\t"
24269 + "move.4 A1, #0 \n\t"
24270 + "move.4 A2, #0 \n\t"
24271 + "move.4 A3, #0 \n\t"
24272 + "move.4 A4, #0 \n\t"
24273 + "move.4 A5, #0 \n\t"
24274 + "move.4 A6, #0 \n\t"
24275 + "move.4 SP, %4 \n\t" /* A7 is SP */
24277 + "move.4 D0, %3 \n\t"
24278 + "move.4 D1, %2 \n\t"
24279 + "move.4 D2, #0 \n\t"
24280 + "move.4 D3, #0 \n\t"
24281 + "move.4 D4, #0 \n\t"
24282 + "move.4 D5, #0 \n\t"
24283 + "move.4 D6, #0 \n\t"
24284 + "move.4 D7, #0 \n\t"
24285 + "move.4 D8, #0 \n\t"
24286 + "move.4 D9, #0 \n\t"
24287 + "move.4 D10, #0 \n\t"
24288 + "move.4 D11, #0 \n\t"
24289 + "move.4 D12, #0 \n\t"
24290 + "move.4 D13, #0 \n\t"
24291 + "move.4 D14, #0 \n\t"
24292 + "move.4 D15, #0 \n\t"
24294 + "move.4 INT_MASK0, #0 \n\t"
24295 + "move.4 INT_MASK1, #0 \n\t"
24296 + "move.4 PC, %1 \n\t"
24298 + "setcsr_flush 0 \n\t"
24300 + : "r" (csr), "r" (thread_entry), "r" (exec),
24301 + "r" (arg), "r" (sp_high)
24305 + * Apply HRT state
24307 + if (type & THREAD_TYPE_HRT) {
24309 + "or.4 MT_HRT, MT_HRT, %0\n\t"
24316 + "and.4 MT_HRT, MT_HRT, %0\n\t"
24327 + "or.4 MT_HPRI, MT_HPRI, %0\n\t"
24337 + "move.4 MT_ACTIVE_SET, %0 \n\t"
24341 + thread_enable_mask(mask);
24346 + * thread_get_mainline()
24347 + * Return a mask of those threads that are Linux mainline threads.
24349 +unsigned int thread_get_mainline(void)
24351 + return thread_mainline_mask;
24355 + * thread_set_mainline()
24356 + * Indicate that the specified thread is a Linux mainline thread.
24358 +void thread_set_mainline(thread_t tid)
24360 + thread_mainline_mask |= (1 << tid);
24365 + * Allocate an unused hardware thread.
24367 +thread_t thread_alloc(void)
24372 + * If this is the first time we are here get the list of unused
24373 + * threads from the processor device tree node.
24375 + if (thread_mask == -1) {
24376 + thread_mask = processor_threads();
24379 + if (!thread_mask) {
24380 + return (thread_t)-1;
24383 + tid = ffs(thread_mask);
24386 + thread_mask &= ~(1 << tid);
24390 + return (thread_t)-1;
24392 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/time.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/time.c
24393 --- linux-2.6.30.10/arch/ubicom32/kernel/time.c 1970-01-01 02:00:00.000000000 +0200
24394 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/time.c 2009-12-11 11:45:11.000000000 +0200
24397 + * arch/ubicom32/kernel/time.c
24398 + * Initialize the timer list and start the appropriate timers.
24400 + * (C) Copyright 2009, Ubicom, Inc.
24401 + * Copyright (C) 1991, 1992, 1995 Linus Torvalds
24403 + * This file is part of the Ubicom32 Linux Kernel Port.
24405 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
24406 + * it and/or modify it under the terms of the GNU General Public License
24407 + * as published by the Free Software Foundation, either version 2 of the
24408 + * License, or (at your option) any later version.
24410 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
24411 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
24412 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
24413 + * the GNU General Public License for more details.
24415 + * You should have received a copy of the GNU General Public License
24416 + * along with the Ubicom32 Linux Kernel Port. If not,
24417 + * see <http://www.gnu.org/licenses/>.
24419 + * Ubicom32 implementation derived from (with many thanks):
24425 +#include <linux/profile.h>
24426 +#include <linux/smp.h>
24427 +#include <asm/ip5000.h>
24428 +#include <asm/machdep.h>
24431 + * A bitmap of the timers on the processor indicates
24432 + * that the timer is free or in-use.
24434 +static unsigned int timers;
24438 + * Init the specified compare register to go off <n> cycles from now.
24440 +void timer_set(int timervector, unsigned int cycles)
24442 + int idx = UBICOM32_VECTOR_TO_TIMER_INDEX(timervector);
24443 + UBICOM32_IO_TIMER->syscom[idx] =
24444 + UBICOM32_IO_TIMER->sysval + cycles;
24445 + ldsr_enable_vector(timervector);
24450 + * Set/reset the timer to go off again.
24452 + * Because sysval is a continuous timer, this function is able
24453 + * to ensure that we do not have clock sku by using the previous
24454 + * value in syscom to set the next value for syscom.
24456 + * Returns the number of ticks that transpired since the last event.
24458 +int timer_reset(int timervector, unsigned int cycles)
24461 + * Reset the timer in the LDSR thread to go off appropriately.
24463 + * Use the previous value of the timer to calculate the new stop
24464 + * time. This allows us to account for it taking an
24465 + * indeterminate amount of time to get here.
24467 + const int timer_index = UBICOM32_VECTOR_TO_TIMER_INDEX(timervector);
24468 + unsigned int prev = UBICOM32_IO_TIMER->syscom[timer_index];
24469 + unsigned int next = prev + cycles;
24475 + * If the difference is negative, we have missed at least one
24478 + * TODO: Decide if we want to "ignore" time (as done below) or
24479 + * if we want to process time (unevenly) by calling timer_tick()
24480 + * lost_ticks times.
24484 + * Set our future time first.
24486 + UBICOM32_IO_TIMER->syscom[timer_index] = next;
24489 + * Then check if we are really set time in the futrue.
24491 + diff = (int)next - (int)UBICOM32_IO_TIMER->sysval;
24497 + * Oops, we are too slow. Playing catch up.
24499 + * If the debugger is connected the there is a good
24500 + * chance that we lost time because we were in a
24501 + * break-point, so in this case we do not print out
24504 + asm volatile ("move.4 %0, scratchpad3"
24505 + : "=r" (scratchpad3));
24506 + if ((scratchpad3 & 0x1) == 0) {
24508 + * No debugger attached, print to the console
24510 + printk(KERN_EMERG "diff: %d, timer has lost %u "
24511 + "ticks [rounded up]\n",
24513 + (unsigned int)((-diff + cycles - 1) / cycles));
24518 + diff = (int)next - (int)UBICOM32_IO_TIMER->sysval;
24520 + } while (diff < 0);
24527 + * Returns current time in nano-second units.
24530 + * 1) This is an override for the weak alias in
24531 + * kernel/sched_clock.c.
24532 + * 2) Do not use xtime_lock as this function is
24533 + * sometimes called with xtime_lock held.
24534 + * 3) We use a retry algorithm to ensure that
24535 + * we get a consistent value.
24536 + * 4) sched_clock must be overwritten if IRQ tracing
24537 + * is enabled because the default implementation uses
24538 + * the xtime_lock sequence while holding xtime_lock.
24540 +unsigned long long sched_clock(void)
24542 + unsigned long long my_jiffies;
24543 + unsigned long jiffies_top;
24544 + unsigned long jiffies_bottom;
24547 + jiffies_top = jiffies_64 >> 32;
24548 + jiffies_bottom = jiffies_64 & 0xffffffff;
24549 + } while (unlikely(jiffies_top != (unsigned long)(jiffies_64 >> 32)));
24551 + my_jiffies = ((unsigned long long)jiffies_top << 32) | (jiffies_bottom);
24552 + return (my_jiffies - INITIAL_JIFFIES) * (NSEC_PER_SEC / HZ);
24557 + * Free a hardware timer.
24559 +void timer_free(int interrupt)
24561 + unsigned int bit = interrupt - TIMER_INT(0);
24564 + * The timer had not been allocated.
24566 + BUG_ON(timers & (1 << bit));
24567 + timers |= (1 << bit);
24572 + * Allocate a hardware timer.
24574 +int timer_alloc(void)
24576 + unsigned int bit = find_first_bit((unsigned long *)&timers, 32);
24578 + printk(KERN_WARNING "no more free timers\n");
24582 + timers &= ~(1 << bit);
24583 + return bit + TIMER_INT(0);
24588 + * Time init function.
24590 +void time_init(void)
24593 + * Find the processor node and determine what timers are
24594 + * available for us.
24596 + timers = processor_timers();
24597 + if (timers == 0) {
24598 + printk(KERN_WARNING "no timers are available for Linux\n");
24602 +#ifdef CONFIG_GENERIC_CLOCKEVENTS
24603 + timer_device_init();
24605 + timer_tick_init();
24608 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/timer_broadcast.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/timer_broadcast.c
24609 --- linux-2.6.30.10/arch/ubicom32/kernel/timer_broadcast.c 1970-01-01 02:00:00.000000000 +0200
24610 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/timer_broadcast.c 2009-12-11 11:45:11.000000000 +0200
24613 + * arch/ubicom32/kernel/timer_broadcast.c
24614 + * Implements a dummy clock event for each cpu.
24616 + * Copyright (C) 2008 Paul Mundt
24617 + * (C) Copyright 2009, Ubicom, Inc.
24619 + * This file is part of the Ubicom32 Linux Kernel Port.
24621 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
24622 + * it and/or modify it under the terms of the GNU General Public License
24623 + * as published by the Free Software Foundation, either version 2 of the
24624 + * License, or (at your option) any later version.
24626 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
24627 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
24628 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
24629 + * the GNU General Public License for more details.
24631 + * You should have received a copy of the GNU General Public License
24632 + * along with the Ubicom32 Linux Kernel Port. If not,
24633 + * see <http://www.gnu.org/licenses/>.
24635 + * Ubicom32 implementation derived from (with many thanks):
24642 +#include <linux/init.h>
24643 +#include <linux/kernel.h>
24644 +#include <linux/delay.h>
24645 +#include <linux/device.h>
24646 +#include <linux/smp.h>
24647 +#include <linux/jiffies.h>
24648 +#include <linux/percpu.h>
24649 +#include <linux/clockchips.h>
24650 +#include <linux/irq.h>
24652 +static DEFINE_PER_CPU(struct clock_event_device, local_clockevent);
24655 + * The broadcast trick only works when the timer will be used in a periodic mode.
24656 + * If the user has configured either NO_HZ or HIGH_RES_TIMERS they must have
24657 + * a per cpu timer.
24659 +#if defined(CONFIG_NO_HZ) || defined(CONFIG_HIGH_RES_TIMERS)
24660 +#error "Tickless and High Resolution Timers require per-CPU local timers: CONFIG_LOCAL_TIMERS"
24664 + * local_timer_interrupt()
24665 + * Used on SMP for local timer interrupt sent via an IPI.
24667 +void local_timer_interrupt(void)
24669 + struct clock_event_device *dev = &__get_cpu_var(local_clockevent);
24671 + dev->event_handler(dev);
24675 + * dummy_timer_set_next_event()
24676 + * Cause the timer to go off "cycles" from now.
24678 +static int dummy_timer_set_next_event(unsigned long cycles, struct clock_event_device *dev)
24684 + * dummy_timer_set_mode()
24687 +static void dummy_timer_set_mode(enum clock_event_mode mode,
24688 + struct clock_event_device *clk)
24693 + * local_timer_setup()
24694 + * Adds a clock event for the specified cpu.
24696 +int __cpuinit local_timer_setup(unsigned int cpu)
24698 + struct clock_event_device *dev = &per_cpu(local_clockevent, cpu);
24700 + dev->name = "timer-dummy";
24701 + dev->features = CLOCK_EVT_FEAT_DUMMY;
24702 + dev->rating = 200;
24704 + dev->set_mode = dummy_timer_set_mode;
24705 + dev->set_next_event = dummy_timer_set_next_event;
24706 + dev->broadcast = smp_timer_broadcast;
24707 + dev->cpumask = cpumask_of_cpu(cpu);
24709 + printk(KERN_NOTICE "timer[%d]: %s - created\n", dev->irq, dev->name);
24711 + clockevents_register_device(dev);
24714 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/timer_device.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/timer_device.c
24715 --- linux-2.6.30.10/arch/ubicom32/kernel/timer_device.c 1970-01-01 02:00:00.000000000 +0200
24716 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/timer_device.c 2009-12-11 11:45:11.000000000 +0200
24719 + * arch/ubicom32/kernel/timer_device.c
24720 + * Implements a Ubicom32 clock device and event devices.
24722 + * (C) Copyright 2009, Ubicom, Inc.
24724 + * This file is part of the Ubicom32 Linux Kernel Port.
24726 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
24727 + * it and/or modify it under the terms of the GNU General Public License
24728 + * as published by the Free Software Foundation, either version 2 of the
24729 + * License, or (at your option) any later version.
24731 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
24732 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
24733 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
24734 + * the GNU General Public License for more details.
24736 + * You should have received a copy of the GNU General Public License
24737 + * along with the Ubicom32 Linux Kernel Port. If not,
24738 + * see <http://www.gnu.org/licenses/>.
24740 + * Ubicom32 implementation derived from (with many thanks):
24745 +#include <linux/types.h>
24746 +#include <linux/clockchips.h>
24747 +#include <linux/clocksource.h>
24748 +#include <linux/spinlock.h>
24749 +#include <asm/ip5000.h>
24750 +#include <asm/machdep.h>
24752 +#if defined(CONFIG_SMP)
24753 +#include <asm/smp.h>
24756 +#if defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)
24757 +#define MAX_TIMERS (2 + CONFIG_TIMER_EXTRA_ALLOC)
24759 +#define MAX_TIMERS (NR_CPUS + CONFIG_TIMER_EXTRA_ALLOC)
24762 +#if (MAX_TIMERS > 10)
24763 +#error "Ubicom32 only has 10 timers"
24766 +static unsigned int frequency;
24767 +static struct clock_event_device timer_device_devs[MAX_TIMERS];
24768 +static struct irqaction timer_device_irqs[MAX_TIMERS];
24769 +static int timer_device_next_timer = 0;
24771 +DEFINE_SPINLOCK(timer_device_lock);
24774 + * timer_device_set_next_event()
24775 + * Cause the timer to go off "cycles" from now.
24777 +static int timer_device_set_next_event(unsigned long cycles, struct clock_event_device *dev)
24779 + timer_set(dev->irq, cycles);
24784 + * timer_device_set_mode()
24785 + * Handle the mode switch for a clock event device.
24787 +static void timer_device_set_mode(enum clock_event_mode mode, struct clock_event_device *dev)
24790 + case CLOCK_EVT_MODE_SHUTDOWN:
24792 + * Make sure the vector is disabled
24793 + * until the next event is set.
24795 + printk(KERN_NOTICE "timer[%d]: shutdown\n", dev->irq);
24796 + ldsr_disable_vector(dev->irq);
24799 + case CLOCK_EVT_MODE_ONESHOT:
24801 + * Make sure the vector is disabled
24802 + * until the next event is set.
24804 + printk(KERN_NOTICE "timer[%d]: oneshot\n", dev->irq);
24805 + ldsr_disable_vector(dev->irq);
24808 + case CLOCK_EVT_MODE_PERIODIC:
24810 + * The periodic request is 1 per jiffies
24812 + printk(KERN_NOTICE "timer[%d]: periodic: %d cycles\n",
24813 + dev->irq, frequency / CONFIG_HZ);
24814 + timer_set(dev->irq, frequency / CONFIG_HZ);
24817 + case CLOCK_EVT_MODE_UNUSED:
24818 + case CLOCK_EVT_MODE_RESUME:
24819 + printk(KERN_WARNING "timer[%d]: unimplemented mode: %d\n",
24826 + * timer_device_event()
24827 + * Call the device's event handler.
24829 + * The pointer is initialized by the generic Linux code
24830 + * to the function to be called.
24832 +static irqreturn_t timer_device_event(int irq, void *dev_id)
24834 + struct clock_event_device *dev = (struct clock_event_device *)dev_id;
24836 + if (dev->mode == CLOCK_EVT_MODE_PERIODIC) {
24838 + * The periodic request is 1 per jiffies
24840 + timer_reset(dev->irq, frequency / CONFIG_HZ);
24843 + * The timer will go off again at the rollover
24844 + * point. We must disable the IRQ to prevent
24845 + * getting a spurious interrupt.
24847 + ldsr_disable_vector(dev->irq);
24850 + if (!dev->event_handler) {
24851 + printk(KERN_CRIT "no registered event handler\n");
24852 + return IRQ_HANDLED;
24855 + dev->event_handler(dev);
24856 + return IRQ_HANDLED;
24860 + * timer_device_clockbase_read()
24861 + * Provide a primary clocksource around the sysval timer.
24863 +static cycle_t timer_device_clockbase_read(void)
24865 + return (cycle_t)UBICOM32_IO_TIMER->sysval;
24869 + * Primary Clock Source Description
24871 + * We use 24 for the shift factor because we want
24872 + * to ensure there are less than 2^24 clocks
24873 + * in a jiffie of 10 ms.
24875 +static struct clocksource timer_device_clockbase = {
24876 + .name = "sysval",
24878 + .flags = CLOCK_SOURCE_IS_CONTINUOUS,
24879 + .mask = CLOCKSOURCE_MASK(32),
24882 + .read = timer_device_clockbase_read,
24886 + * timer_device_alloc_event()
24887 + * Allocate a timer device event.
24889 +static int timer_device_alloc_event(const char *name, int cpuid, const cpumask_t *mask)
24891 + struct clock_event_device *dev;
24892 + struct irqaction *action;
24895 + * Are we out of configured timers?
24897 + spin_lock(&timer_device_lock);
24898 + if (timer_device_next_timer >= MAX_TIMERS) {
24899 + spin_unlock(&timer_device_lock);
24900 + printk(KERN_WARNING "out of timer event entries\n");
24903 + dev = &timer_device_devs[timer_device_next_timer];
24904 + action = &timer_device_irqs[timer_device_next_timer];
24905 + timer_device_next_timer++;
24906 + spin_unlock(&timer_device_lock);
24909 + * Now allocate a timer to ourselves.
24911 + dev->irq = timer_alloc();
24912 + if (dev->irq == -1) {
24913 + spin_lock(&timer_device_lock);
24914 + timer_device_next_timer--;
24915 + spin_unlock(&timer_device_lock);
24916 + printk(KERN_WARNING "out of hardware timers\n");
24921 + * Init the IRQ action structure. Make sure
24922 + * this in place before you register the clock
24925 + action->name = name;
24926 + action->flags = IRQF_DISABLED | IRQF_TIMER;
24927 + action->handler = timer_device_event;
24928 + cpumask_copy(&action->mask, mask);
24929 + action->dev_id = dev;
24930 + setup_irq(dev->irq, action);
24931 + irq_set_affinity(dev->irq, mask);
24932 + ldsr_disable_vector(dev->irq);
24935 + * init clock dev structure.
24937 + * The min_delta_ns is chosen to ensure that setting next
24938 + * event will never be requested with too small of value.
24940 + dev->name = name;
24941 + dev->rating = timer_device_clockbase.rating;
24942 + dev->shift = timer_device_clockbase.shift;
24943 + dev->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
24944 + dev->set_mode = timer_device_set_mode;
24945 + dev->set_next_event = timer_device_set_next_event;
24946 + dev->mult = div_sc(frequency, NSEC_PER_SEC, dev->shift);
24947 + dev->max_delta_ns = clockevent_delta2ns(0xffffffff, dev);
24948 + dev->min_delta_ns = clockevent_delta2ns(100, dev);
24949 + dev->cpumask = mask;
24950 + printk(KERN_NOTICE "timer[%d]: %s - created\n", dev->irq, dev->name);
24953 + * Now register the device.
24955 + clockevents_register_device(dev);
24959 +#if defined(CONFIG_LOCAL_TIMERS)
24961 + * local_timer_setup()
24962 + * Allocation function for creating a per cpu local timer.
24964 +int __cpuinit local_timer_setup(unsigned int cpu)
24966 + return timer_device_alloc_event("timer-cpu", cpu, cpumask_of(cpu));
24971 + * timer_device_init()
24972 + * Create and init a generic clock driver for Ubicom32.
24974 +void timer_device_init(void)
24979 + * Get the frequency from the processor device tree node or use
24980 + * the default if not available. We will store this as the frequency
24981 + * of the timer to avoid future calculations.
24983 + frequency = processor_frequency();
24984 + if (frequency == 0) {
24985 + frequency = CLOCK_TICK_RATE;
24989 + * Setup the primary clock source around sysval. Linux does not
24990 + * supply a Mhz multiplier so convert down to khz.
24992 + timer_device_clockbase.mult =
24993 + clocksource_khz2mult(frequency / 1000,
24994 + timer_device_clockbase.shift);
24995 + if (clocksource_register(&timer_device_clockbase)) {
24996 + printk(KERN_ERR "timer: clocksource failed to register\n");
25001 + * Always allocate a primary timer.
25003 + timer_device_alloc_event("timer-primary", -1, CPU_MASK_ALL_PTR);
25005 +#if defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)
25007 + * If BROADCAST is selected we need to add a broadcast timer.
25009 + timer_device_alloc_event("timer-broadcast", -1, CPU_MASK_ALL_PTR);
25013 + * Allocate extra timers that are requested.
25015 + for (i = 0; i < CONFIG_TIMER_EXTRA_ALLOC; i++) {
25016 + timer_device_alloc_event("timer-extra", -1, CPU_MASK_ALL_PTR);
25019 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/timer_tick.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/timer_tick.c
25020 --- linux-2.6.30.10/arch/ubicom32/kernel/timer_tick.c 1970-01-01 02:00:00.000000000 +0200
25021 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/timer_tick.c 2009-12-11 11:45:11.000000000 +0200
25024 + * arch/ubicom32/kernel/timer_tick.c
25025 + * Impelemets a perodic timer.
25027 + * (C) Copyright 2009, Ubicom, Inc.
25028 + * Copyright (C) 1991, 1992, 1995 Linus Torvalds
25030 + * This file is part of the Ubicom32 Linux Kernel Port.
25032 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
25033 + * it and/or modify it under the terms of the GNU General Public License
25034 + * as published by the Free Software Foundation, either version 2 of the
25035 + * License, or (at your option) any later version.
25037 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
25038 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
25039 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
25040 + * the GNU General Public License for more details.
25042 + * You should have received a copy of the GNU General Public License
25043 + * along with the Ubicom32 Linux Kernel Port. If not,
25044 + * see <http://www.gnu.org/licenses/>.
25046 + * Ubicom32 implementation derived from (with many thanks):
25052 +#include <linux/profile.h>
25054 +#include <asm/ip5000.h>
25055 +#include <asm/machdep.h>
25056 +#if defined(CONFIG_SMP)
25057 +#include <asm/smp.h>
25060 +static unsigned int timervector;
25061 +static unsigned int frequency;
25065 + * Kernel system timer support. Needs to keep up the real-time clock,
25066 + * as well as call the "do_timer()" routine every clocktick.
25068 +static irqreturn_t timer_tick(int irq, void *dummy)
25072 + BUG_ON(!irqs_disabled());
25073 + ticks = timer_reset(timervector, frequency);
25075 + write_seqlock(&xtime_lock);
25077 + write_sequnlock(&xtime_lock);
25079 + update_process_times(user_mode(get_irq_regs()));
25080 + profile_tick(CPU_PROFILING);
25082 +#if defined(CONFIG_SMP)
25083 + smp_send_timer_all();
25085 + return(IRQ_HANDLED);
25089 + * Data used by setup_irq for the timer.
25091 +static struct irqaction timer_irq = {
25093 + .flags = IRQF_DISABLED | IRQF_TIMER,
25094 + .handler = timer_tick,
25098 + * timer_tick_init()
25099 + * Implements a periodic timer
25101 + * This implementation directly calls the timer_tick() and move
25102 + * the Linux kernel forward. This is used when the user has not
25103 + * selected GENERIC_CLOCKEVENTS.
25105 +void timer_tick_init(void)
25108 + * Now allocate a timer to ourselves.
25110 + timervector = timer_alloc();
25111 + if (timervector == -1) {
25112 + printk(KERN_WARNING "where did the timer go?\n");
25116 + setup_irq(timervector, &timer_irq);
25119 + * Get the frequency from the processor device tree node or use
25120 + * the default if not available. We will store this as the frequency
25121 + * of the timer to avoid future calculations.
25123 + frequency = processor_frequency();
25124 + if (frequency == 0) {
25125 + frequency = CLOCK_TICK_RATE;
25127 + frequency /= CONFIG_HZ;
25129 + printk(KERN_NOTICE "timer will interrupt every: %d cycles\n", frequency);
25130 + timer_set(timervector, frequency);
25132 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/topology.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/topology.c
25133 --- linux-2.6.30.10/arch/ubicom32/kernel/topology.c 1970-01-01 02:00:00.000000000 +0200
25134 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/topology.c 2009-12-11 11:45:11.000000000 +0200
25137 + * arch/ubicom32/kernel/topology.c
25138 + * Ubicom32 architecture sysfs topology information.
25140 + * (C) Copyright 2009, Ubicom, Inc.
25142 + * This file is part of the Ubicom32 Linux Kernel Port.
25144 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
25145 + * it and/or modify it under the terms of the GNU General Public License
25146 + * as published by the Free Software Foundation, either version 2 of the
25147 + * License, or (at your option) any later version.
25149 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
25150 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
25151 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
25152 + * the GNU General Public License for more details.
25154 + * You should have received a copy of the GNU General Public License
25155 + * along with the Ubicom32 Linux Kernel Port. If not,
25156 + * see <http://www.gnu.org/licenses/>.
25158 + * Ubicom32 implementation derived from (with many thanks):
25164 +#include <linux/init.h>
25165 +#include <linux/smp.h>
25166 +#include <linux/cpu.h>
25167 +#include <linux/cache.h>
25169 +static struct cpu cpu_devices[NR_CPUS] __read_mostly;
25171 +static int __init topology_init(void)
25175 + for_each_present_cpu(num) {
25176 + cpu_devices[num].hotpluggable = 0;
25177 + register_cpu(&cpu_devices[num], num);
25182 +subsys_initcall(topology_init);
25183 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/traps.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/traps.c
25184 --- linux-2.6.30.10/arch/ubicom32/kernel/traps.c 1970-01-01 02:00:00.000000000 +0200
25185 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/traps.c 2009-12-11 11:45:11.000000000 +0200
25188 + * arch/ubicom32/kernel/traps.c
25189 + * Ubicom32 architecture trap handling support.
25191 + * (C) Copyright 2009, Ubicom, Inc.
25193 + * This file is part of the Ubicom32 Linux Kernel Port.
25195 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
25196 + * it and/or modify it under the terms of the GNU General Public License
25197 + * as published by the Free Software Foundation, either version 2 of the
25198 + * License, or (at your option) any later version.
25200 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
25201 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
25202 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
25203 + * the GNU General Public License for more details.
25205 + * You should have received a copy of the GNU General Public License
25206 + * along with the Ubicom32 Linux Kernel Port. If not,
25207 + * see <http://www.gnu.org/licenses/>.
25209 + * Ubicom32 implementation derived from (with many thanks):
25216 + * Sets up all exception vectors
25218 +#include <linux/sched.h>
25219 +#include <linux/signal.h>
25220 +#include <linux/kernel.h>
25221 +#include <linux/mm.h>
25222 +#include <linux/module.h>
25223 +#include <linux/types.h>
25224 +#include <linux/a.out.h>
25225 +#include <linux/user.h>
25226 +#include <linux/string.h>
25227 +#include <linux/linkage.h>
25228 +#include <linux/init.h>
25229 +#include <linux/ptrace.h>
25230 +#include <linux/kallsyms.h>
25231 +#include <linux/compiler.h>
25232 +#include <linux/stacktrace.h>
25233 +#include <linux/personality.h>
25235 +#include <asm/uaccess.h>
25236 +#include <asm/stacktrace.h>
25237 +#include <asm/devtree.h>
25238 +#include <asm/setup.h>
25239 +#include <asm/fpu.h>
25240 +#include <asm/system.h>
25241 +#include <asm/traps.h>
25242 +#include <asm/pgtable.h>
25243 +#include <asm/processor.h>
25244 +#include <asm/machdep.h>
25245 +#include <asm/siginfo.h>
25246 +#include <asm/ip5000.h>
25247 +#include <asm/thread.h>
25249 +#define TRAP_MAX_STACK_DEPTH 20
25252 + * These symbols are filled in by the linker.
25254 +extern unsigned long _stext;
25255 +extern unsigned long _etext;
25257 +extern unsigned long __ocm_text_run_begin;
25258 +extern unsigned long __data_begin;
25260 +extern void show_vmas(struct task_struct *task);
25262 +const char *trap_cause_strings[] = {
25263 + /*0*/ "inst address decode error",
25264 + /*1*/ "inst sync error",
25265 + /*2*/ "inst illegal",
25266 + /*3*/ "src1 address decode error",
25267 + /*4*/ "dst address decode error",
25268 + /*5*/ "src1 alignment error",
25269 + /*6*/ "dst alignment error",
25270 + /*7*/ "src1 sync error",
25271 + /*8*/ "dst sync error",
25272 + /*9*/ "DCAPT error",
25273 + /*10*/ "inst range error",
25274 + /*11*/ "src1 range error",
25275 + /*12*/ "dst range error",
25279 + * The device tree trap node definition.
25282 + struct devtree_node dn;
25283 + unsigned int intthread;
25286 +static struct trapnode *tn;;
25289 + * trap_interrupt_handler()
25290 + * Software Interrupt to ensure that a trap is serviced.
25292 +static irqreturn_t trap_interrupt_handler(int irq, void *dummy)
25295 + return IRQ_HANDLED;
25299 + * Data used by setup_irq for the timer.
25301 +static struct irqaction trap_irq = {
25303 + .flags = IRQF_DISABLED,
25304 + .handler = trap_interrupt_handler,
25308 + * trap_cause_to_str()
25309 + * Convert a trap_cause into a series of printk
25311 +static void trap_cause_to_str(long status)
25315 + if ((status & ((1 << TRAP_CAUSE_TOTAL) - 1)) == 0) {
25316 + printk(KERN_NOTICE "decode: UNKNOWN CAUSES\n");
25320 + for (bit = 0; bit < TRAP_CAUSE_TOTAL; bit++) {
25321 + if (status & (1 << bit)) {
25322 + printk(KERN_NOTICE "\tdecode: %08x %s\n",
25323 + 1 << bit, trap_cause_strings[bit]);
25329 + * trap_print_information()
25330 + * Print the cause of the trap and additional info.
25332 +static void trap_print_information(const char *str, struct pt_regs *regs)
25334 + printk(KERN_WARNING "\n");
25337 + printk(KERN_WARNING "Process %s (pid: %d)\n",
25338 + current->comm, current->pid);
25341 + if (current && current->mm) {
25342 + printk(KERN_NOTICE "text = 0x%p-0x%p data = 0x%p-0x%p\n"
25343 + KERN_NOTICE "bss = 0x%p-0x%p user-stack = 0x%p\n"
25344 + KERN_NOTICE "\n",
25345 + (void *)current->mm->start_code,
25346 + (void *)current->mm->end_code,
25347 + (void *)current->mm->start_data,
25348 + (void *)current->mm->end_data,
25349 + (void *)current->mm->end_data,
25350 + (void *)current->mm->brk,
25351 + (void *)current->mm->start_stack);
25354 + printk(KERN_WARNING "%s: Causes: 0x%08x\n", str,
25355 + (unsigned int)regs->trap_cause);
25356 + trap_cause_to_str(regs->trap_cause);
25358 + show_stack(NULL, (unsigned long *)regs->an[7]);
25359 + printk(KERN_NOTICE "--- End Trap --- \n");
25364 + * Dump the stack of the current task.
25366 +void dump_stack(void)
25368 + show_stack(NULL, NULL);
25370 +EXPORT_SYMBOL(dump_stack);
25374 + * Print out information from the current stack.
25376 +void show_stack(struct task_struct *task, unsigned long *sp)
25379 + * Allocate just enough entries on the stack.
25381 + unsigned int calls[TRAP_MAX_STACK_DEPTH];
25382 + unsigned long code_start;
25383 + unsigned long code_end;
25384 + unsigned long ocm_code_start = (unsigned long)&__ocm_text_run_begin;
25385 + unsigned long ocm_code_end = (unsigned long)&__data_begin;
25386 + unsigned long stack_end = (unsigned long)(current->stack + THREAD_SIZE - 8);
25387 + unsigned long stack = (unsigned long)sp;
25388 + int kernel_stack = 1;
25390 + processor_dram(&code_start, &code_end);
25393 + * Which task are we talking about.
25400 + * Find the stack for the task if one was not specified. Otherwise
25401 + * use the specified stack.
25404 + if (task != current) {
25405 + stack = task->thread.sp;
25406 + stack_end = (unsigned long)task->stack + THREAD_SIZE - 8;
25409 + "move.4 %0, SP \n\t"
25415 + printk(KERN_NOTICE "Starting backtrace: PID %d '%s'\n",
25416 + task->pid, task->comm);
25419 + * We do 2 passes the first pass is Kernel stack is the second
25422 + while (kernel_stack) {
25423 + unsigned long *handle;
25424 + unsigned int i, idx = 0;
25425 + struct pt_regs *pt = task_pt_regs(task);
25428 + * If the task is in user mode, reset the start
25429 + * and end values for text.
25431 + if (__user_mode(stack)) {
25432 + if (!(task->personality & FDPIC_FUNCPTRS)) {
25433 + printk(KERN_NOTICE " User Stack:\n");
25434 + code_start = task->mm->start_code;
25435 + code_end = task->mm->end_code;
25437 + printk(KERN_NOTICE " User Stack (fdpic):\n");
25440 + stack_end = task->mm->start_stack;
25441 + ocm_code_end = ocm_code_start = 0;
25442 + kernel_stack = 0;
25444 + printk(KERN_NOTICE " Kernel Stack:\n");
25448 + * Collect the stack back trace information.
25450 + printk(" code[0x%lx-0x%lx]", code_start, code_end);
25451 + if (ocm_code_start) {
25452 + printk(" ocm_code[0x%lx-0x%lx]",
25453 + ocm_code_start, ocm_code_end);
25455 + printk("\n stack[0x%lx-0x%lx]\n", stack, stack_end);
25457 + handle = (unsigned long*)stack;
25458 + while (idx < TRAP_MAX_STACK_DEPTH) {
25459 + calls[idx] = stacktrace_iterate(&handle,
25460 + code_start, code_end,
25461 + ocm_code_start, ocm_code_end,
25462 + (unsigned long)stack, stack_end);
25463 + if (calls[idx] == 0) {
25470 + * Now print out the data.
25472 + printk(KERN_NOTICE " CALL && CALLI on stack:");
25473 + for (i = 0; i < idx; i++) {
25474 + printk("%s0x%x, ", (i & 0x3) == 0 ? "\n " : "",
25477 + printk(idx == TRAP_MAX_STACK_DEPTH ? "...\n" : "\n");
25480 + * If we are doing user stack we are done
25482 + if (!kernel_stack) {
25487 + * Does this kernel stack have a mm (i.e. is it user)
25490 + printk("No mm for userspace stack.\n");
25494 + * Get the user-mode stack (if any)
25496 + stack = pt->an[7];
25497 + printk(KERN_NOTICE "Userspace stack at 0x%lx frame type %d\n",
25498 + stack, (int)pt->frame_type);
25499 + if (!__user_mode(stack)) {
25506 + * die_if_kernel()
25507 + * Determine if we are in kernel mode and if so print stuff out and die.
25509 +void die_if_kernel(char *str, struct pt_regs *regs, long trap_cause)
25511 + unsigned int s3value;
25513 + if (user_mode(regs)) {
25517 + console_verbose();
25518 + trap_print_information(str, regs);
25521 + * If the debugger is attached via the hardware mailbox protocol,
25522 + * go into an infinite loop and the debugger will figure things out.
25525 + "move.4 %0, scratchpad3"
25529 + asm volatile("1: jmpt.t 1b");
25533 + * Set the debug taint value.
25535 + add_taint(TAINT_DIE);
25536 + do_exit(SIGSEGV);
25543 + * Traps are treated as interrupts and registered with the LDSR. When
25544 + * the LDSR takes the interrupt, it will determine if a trap has occurred
25545 + * and service the trap prior to servicing the interrupt.
25547 + * This function is directly called by the LDSR.
25549 +void trap_handler(int irq, struct pt_regs *regs)
25551 + int sig = SIGSEGV;
25553 + unsigned int trap_cause = regs->trap_cause;
25555 + BUG_ON(!irqs_disabled());
25558 + * test if in kernel and die.
25560 + die_if_kernel("Kernel Trap", regs, trap_cause);
25563 + * User process problem, setup a signal for this process
25565 + if ((trap_cause & (1 << TRAP_CAUSE_DST_RANGE_ERR)) ||
25566 + (trap_cause & (1 << TRAP_CAUSE_SRC1_RANGE_ERR)) ||
25567 + (trap_cause & (1 << TRAP_CAUSE_I_RANGE_ERR))) {
25569 + info.si_code = SEGV_MAPERR;
25570 + } else if ((trap_cause & (1 << TRAP_CAUSE_DST_MISALIGNED)) ||
25571 + (trap_cause & (1 << TRAP_CAUSE_SRC1_MISALIGNED))) {
25573 + info.si_code = BUS_ADRALN;
25574 + } else if ((trap_cause & (1 << TRAP_CAUSE_DST_DECODE_ERR)) ||
25575 + (trap_cause & (1 << TRAP_CAUSE_SRC1_DECODE_ERR))) {
25577 + info.si_code = ILL_ILLOPN;
25578 + } else if ((trap_cause & (1 << TRAP_CAUSE_ILLEGAL_INST))) {
25580 + * Check for software break point and if found signal trap
25581 + * not illegal instruction.
25583 + unsigned long instruction;
25584 + if (between(regs->pc, KERNELSTART, memory_end) &&
25585 + (regs->pc & 3) == 0 &&
25586 + get_user(instruction, (unsigned long *)regs->pc) == 0) {
25589 + * This used to be 0xaabbccdd but it turns out
25590 + * that is now valid in ubicom32v4 isa so we
25591 + * have switched to 0xfabbccdd
25593 + if ((instruction == 0xfabbccdd) ||
25594 + (instruction == 0xaabbccdd)) {
25596 + info.si_code = TRAP_BRKPT;
25597 + goto send_signal;
25601 + info.si_code = ILL_ILLOPC;
25602 + } else if ((trap_cause & (1 << TRAP_CAUSE_I_DECODE_ERR))) {
25604 + info.si_code = ILL_ILLOPC;
25605 + } else if ((trap_cause & (1 << TRAP_CAUSE_DCAPT))) {
25607 + info.si_code = TRAP_TRACE;
25611 + * Print a trap information block to the console, do not
25612 + * print this above the case because we don't want it
25613 + * printed for software break points.
25615 + trap_print_information("User Trap", regs);
25619 + force_sig_info(sig, &info, current);
25622 + * Interrupts are disabled, re-enable them now.
25624 + if (!irqs_disabled()) {
25625 + printk(KERN_EMERG "interrupts enabled on exit, irq=%d, regs=%p",
25632 + * trap_init_interrupt()
25633 + * We need a 2nd trap handling init that will occur after init_IRQ().
25635 +void __init trap_init_interrupt(void)
25638 + unsigned char tirq;
25639 + struct devtree_node *dn = (struct devtree_node *)tn;
25642 + * Now setup the Software IRQ so that if a trap occurs the LDSR
25643 + * is started. The irq is there just to "force" the LDSR to run.
25646 + printk(KERN_WARNING "trap_init_interrupt skipped.\n");
25650 + err = devtree_irq(dn, NULL, &tirq);
25652 + printk(KERN_WARNING "error obtaining trap irq value: %d\n",
25657 + if (tirq == DEVTREE_IRQ_NONE) {
25658 + printk(KERN_WARNING "trap irq not available: %d\n", tirq);
25662 + err = setup_irq(tirq, &trap_irq);
25664 + printk(KERN_WARNING "trap irq setup failed: %d\n", err);
25669 + * Let ultra know which thread is handling the traps and
25670 + * what the interrupt to use is.
25672 + tn->intthread = ldsr_get_threadid();
25675 + * Tell the LDSR about our IRQ so that it will unsuspend
25676 + * if one occurs while waiting for the per thread lock.
25678 + ldsr_set_trap_irq(tirq);
25683 + * init trap handling
25685 + * Trap handling is done through the ldsr. Every time an interrupt
25686 + * occurs, the LDSR looks for threads that are listed in the TRAP
25687 + * register and forces a call to the trap handler.
25689 +void __init trap_init(void)
25692 + * If we do not have a trap node in the device tree, we leave the fault
25693 + * handling to the underlying hardware.
25695 + tn = (struct trapnode *)devtree_find_node("traps");
25697 + printk(KERN_WARNING "traps are not handled by linux\n");
25701 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/uaccess.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/uaccess.c
25702 --- linux-2.6.30.10/arch/ubicom32/kernel/uaccess.c 1970-01-01 02:00:00.000000000 +0200
25703 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/uaccess.c 2009-12-11 11:45:11.000000000 +0200
25706 + * arch/ubicom32/include/asm/uaccess.c
25707 + * User space memory access functions for Ubicom32 architecture.
25709 + * (C) Copyright 2009, Ubicom, Inc.
25711 + * This file is part of the Ubicom32 Linux Kernel Port.
25713 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
25714 + * it and/or modify it under the terms of the GNU General Public License
25715 + * as published by the Free Software Foundation, either version 2 of the
25716 + * License, or (at your option) any later version.
25718 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
25719 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
25720 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
25721 + * the GNU General Public License for more details.
25723 + * You should have received a copy of the GNU General Public License
25724 + * along with the Ubicom32 Linux Kernel Port. If not,
25725 + * see <http://www.gnu.org/licenses/>.
25727 + * Ubicom32 implementation derived from (with many thanks):
25733 +#include <linux/sched.h>
25734 +#include <linux/mm.h>
25735 +#include <linux/string.h>
25736 +#include <linux/module.h>
25738 +#include <asm/segment.h>
25739 +#include <asm/uaccess.h>
25741 +extern int _stext, _etext, _sdata, _edata, _sbss, _ebss, _end;
25745 + * Check that the address is in the current processes.
25747 + * NOTE: The kernel uses "pretend" user addresses that wind
25748 + * up calling access_ok() so this approach has only marginal
25749 + * value because you wind up with lots of false positives.
25751 +int __access_ok(unsigned long addr, unsigned long size)
25753 + // struct vm_area_struct *vma;
25756 + * Don't do anything if we are not a running system yet.
25758 + if (system_state != SYSTEM_RUNNING) {
25763 + * It appears that Linux will call this function even when we are not
25764 + * in the context of a user space application that has a VM address
25765 + * space. So we must check that current and mm are valid before
25766 + * performing the check.
25768 + if ((!current) || (!current->mm)) {
25773 + * We perform some basic checks on the address to ensure that it
25774 + * is at least within the range of DRAM.
25776 + if ((addr < (int)&_etext) || (addr > memory_end)) {
25777 + printk(KERN_WARNING "pid=%d[%s]: range [%lx - %lx] not in memory area: [%lx - %lx]\n",
25778 + current->pid, current->comm,
25779 + addr, addr + size,
25780 + memory_start, memory_end);
25785 + * For nommu Linux we can check this by looking at the allowed
25786 + * memory map for the process.
25788 + * TODO: Since the kernel passes addresses in it's own space as though
25789 + * they were user address, we can not validate the addresses this way.
25792 + if (!down_read_trylock(¤t->mm->mmap_sem)) {
25795 + vma = find_vma(current->mm, addr);
25797 + up_read(¤t->mm->mmap_sem);
25798 + printk(KERN_WARNING "pid=%d[%s]: possible invalid acesss on range: [%lx - %lx]\n",
25799 + current->pid, current->comm, addr, addr + size);
25802 + if ((addr + size) > vma->vm_end) {
25803 + up_read(¤t->mm->mmap_sem);
25804 + printk(KERN_WARNING "pid=%d[%s]: possible invalid length on range: [%lx - %lx]\n",
25805 + current->pid, current->comm, addr, addr + size);
25808 + up_read(¤t->mm->mmap_sem);
25813 +EXPORT_SYMBOL(__access_ok);
25814 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/ubicom32_context_switch.S linux-2.6.30.10-ubi/arch/ubicom32/kernel/ubicom32_context_switch.S
25815 --- linux-2.6.30.10/arch/ubicom32/kernel/ubicom32_context_switch.S 1970-01-01 02:00:00.000000000 +0200
25816 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/ubicom32_context_switch.S 2009-12-11 11:45:11.000000000 +0200
25819 + * arch/ubicom32/kernel/ubicom32_context_switch.S
25820 + * Implements context switch and return functions.
25822 + * (C) Copyright 2009, Ubicom, Inc.
25824 + * This file is part of the Ubicom32 Linux Kernel Port.
25826 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
25827 + * it and/or modify it under the terms of the GNU General Public License
25828 + * as published by the Free Software Foundation, either version 2 of the
25829 + * License, or (at your option) any later version.
25831 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
25832 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
25833 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
25834 + * the GNU General Public License for more details.
25836 + * You should have received a copy of the GNU General Public License
25837 + * along with the Ubicom32 Linux Kernel Port. If not,
25838 + * see <http://www.gnu.org/licenses/>.
25840 + * Ubicom32 implementation derived from (with many thanks):
25845 +#include <linux/sys.h>
25846 +#include <linux/linkage.h>
25847 +#include <asm/asm-offsets.h>
25848 +#include <asm/ubicom32-common.h>
25849 +#include <asm/ip5000.h>
25850 +#include <asm/range-protect.h>
25853 + * begin_restore_context()
25854 + * Restore most of the context from sp (struct pt_reg *)
25856 + * This *can* be called without the global atomic lock. (because sp is
25857 + * not restored!) Only d15 and a3 are allowed to be used after this
25858 + * before calling complete_restore_context
25860 +.macro begin_restore_context
25861 + move.4 d0, PT_D0(sp)
25862 + move.4 d1, PT_D1(sp)
25863 + move.4 d2, PT_D2(sp)
25864 + move.4 d3, PT_D3(sp)
25865 + move.4 d4, PT_D4(sp)
25866 + move.4 d5, PT_D5(sp)
25867 + move.4 d6, PT_D6(sp)
25868 + move.4 d7, PT_D7(sp)
25869 + move.4 d8, PT_D8(sp)
25870 + move.4 d9, PT_D9(sp)
25871 + move.4 d10, PT_D10(sp)
25872 + move.4 d11, PT_D11(sp)
25873 + move.4 d12, PT_D12(sp)
25874 + move.4 d13, PT_D13(sp)
25875 + move.4 d14, PT_D14(sp)
25876 +;; move.4 d15, PT_D15(sp)
25877 + move.4 a0, PT_A0(sp)
25878 + move.4 a1, PT_A1(sp)
25879 + move.4 a2, PT_A2(sp)
25880 +;; move.4 a3, PT_A3(sp)
25881 + move.4 a4, PT_A4(sp)
25882 + move.4 a5, PT_A5(sp)
25883 + move.4 a6, PT_A6(sp)
25884 + move.4 acc0_hi, PT_ACC0HI(sp)
25885 + move.4 acc0_lo, PT_ACC0LO(sp)
25886 + move.4 mac_rc16, PT_MAC_RC16(sp)
25887 + move.4 acc1_hi, PT_ACC1HI(sp)
25888 + move.4 acc1_lo, PT_ACC1LO(sp)
25889 + move.4 source3, PT_SOURCE3(sp)
25890 + move.4 int_mask0, PT_INT_MASK0(sp)
25891 + move.4 int_mask1, PT_INT_MASK1(sp)
25895 + * complete_restore_context()
25896 + * Completely restore the context from sp (struct pt_reg *)
25898 + * Note: Recovered PC and CSR are saved on the stack and are to be
25899 + * popped off before returning.
25901 +.macro complete_restore_context
25903 + move.4 d15, PT_D15(sp)
25904 + move.4 sp, PT_SP(a3) ; Recover Stack pointer from save area
25905 + move.4 -4(sp)++, PT_PC(a3) ; Recover saved PC and save to stack
25906 + move.4 -4(sp)++, PT_CSR(a3) ; Recover saved csr and save to stack
25907 + move.4 a3, PT_A3(a3)
25911 + * old restore_context macro
25913 +.macro restore_context
25914 + begin_restore_context
25915 + complete_restore_context
25919 + * ldsr_thread_enable_interrupts()
25920 + * An assembly version of the enable interrupts function.
25922 + * The stack is fair game but all registers MUST be preserved.
25925 +.macro ldsr_thread_enable_interrupts
25926 + move.4 -4(sp)++, d3 ; Push d3
25927 + move.4 -4(sp)++, a3 ; Push a3
25930 + * Read the ROSR and obtain ~(1 << tid)
25932 + lsr.4 d3, rosr, #0x2 ; Move the thread portion of ROSR into d3
25933 + lsl.4 d3, #1, d3 ; perform a (1 << tid)
25934 + not.4 d3, d3 ; Negate the value of d3 == ~(1 << threadid)
25937 + * Get the value of the ldsr_soft_irq_mask
25939 + moveai a3, #%hi(ldsr_soft_irq_mask)
25940 + move.4 a3, %lo(ldsr_soft_irq_mask)(a3)
25943 + * Now re-enable interrupts for this thread and then
25944 + * wakeup the LDSR.
25946 + and.4 scratchpad1, scratchpad1, d3
25947 + move.4 int_set0, a3
25950 + * Restore the registers.
25952 + move.4 a3, (sp)4++
25953 + move.4 d3, (sp)4++
25957 + * ret_from_interrupt_to_kernel()
25958 + * RFI function that is where do_IRQ() returns to if the thread was
25959 + * in kernel space.
25961 + .section .text.ret_from_interrupt_to_kernel, "ax", @progbits
25962 + .global ret_from_interrupt_to_kernel
25963 +ret_from_interrupt_to_kernel:
25964 + begin_restore_context ; Restore the thread context
25965 + atomic_lock_acquire ; Enter critical section
25966 + complete_restore_context ; Restore the thread context
25967 + atomic_lock_release ; Leave critical section
25968 + ldsr_thread_enable_interrupts ; enable the threads interrupts
25969 + move.4 csr, (sp)4++ ; Restore csr from the stack
25973 + * ret_from_interrupt_to_user()
25974 + * RFI function that is where do_IRQ() returns to if the thread was
25977 + * TODO: Do we really need the critical section handling in this code?
25980 + .section .text.ret_from_interrupt_to_user, "ax", @progbits
25981 + .global ret_from_interrupt_to_user
25982 +ret_from_interrupt_to_user:
25983 + ldsr_thread_enable_interrupts ; enable the threads interrupts
25985 + * Set a1 to the thread info pointer, no need to save it as we are
25986 + * restoring userspace and will never return
25988 + movei d0, #(~(ASM_THREAD_SIZE-1))
25992 + * Test if the scheduler needs to be called.
25994 + btst TI_FLAGS(a1), #ASM_TIF_NEED_RESCHED
25996 + call a5, schedule ; Call the scheduler. I will come back here.
25999 + * See if we have pending signals and call do_signal
26003 + btst TI_FLAGS(a1), #ASM_TIF_SIGPENDING ; Any signals needed?
26007 + * Now call do_signal()
26009 + move.4 d0, #0 ; oldset pointer is NULL
26010 + move.4 d1, sp ; d1 is the regs pointer
26011 + call a5, do_signal ; Call do_signal()
26014 + * Back from do_signal(), re-enter critical section.
26017 + begin_restore_context ; Restore the thread context
26018 + atomic_lock_acquire ; Enter critical section
26019 + call a3, __complete_and_return_to_userspace ; jump to unprotected section
26022 + * restore_all_registers()
26024 + * restore_all_registers will be the alternate exit route for
26025 + * preempted processes that have called a signal handler
26026 + * and are returning back to user space.
26028 + .section .text.restore_all_registers, "ax", @progbits
26029 + .global restore_all_registers
26030 +restore_all_registers:
26031 + begin_restore_context ; Restore the thread context
26032 + atomic_lock_acquire ; Enter critical section
26033 + call a3, __complete_and_return_to_userspace
26036 + * __complete_and_return_to_userspace
26038 + * restores the second half of the context and returns
26039 + * You must have the atomic lock when you call this function
26041 + .section .kernel_unprotected, "ax", @progbits
26042 +__complete_and_return_to_userspace:
26043 + disable_kernel_ranges_for_current d15 ; disable kernel ranges
26044 + complete_restore_context ; restore previous context
26045 + atomic_lock_release ; Leave critical section
26046 + move.4 csr, (sp)4++ ; Restore csr from the stack
26050 + * ret_from_fork()
26051 + * Called on the child's return from fork system call.
26053 + .section .text.ret_from_fork, "ax", @progbits
26054 + .global ret_from_fork
26056 + ;;; d0 contains the arg for schedule_tail
26057 + ;;; the others we don't care about as they are in PT_REGS (sp)
26058 + call a5, schedule_tail
26060 + atomic_lock_acquire ; Enter critical section
26063 + move.4 d0, PT_D0(a3) ; Restore D0
26064 + move.4 d1, PT_D1(a3) ; Restore D1
26065 + move.4 d2, PT_D2(a3) ; Restore D2
26066 + move.4 d3, PT_D3(a3) ; Restore D3
26067 + move.4 d10, PT_D10(a3) ; Restore D10
26068 + move.4 d11, PT_D11(a3) ; Restore D11
26069 + move.4 d12, PT_D12(a3) ; Restore D12
26070 + move.4 d13, PT_D13(a3) ; Restore D13
26071 + move.4 a1, PT_A1(a3) ; Restore A1
26072 + move.4 a2, PT_A2(a3) ; Restore A2
26073 + move.4 a5, PT_A5(a3) ; Restore A5
26074 + move.4 a6, PT_A6(a3) ; Restore A6
26075 + ;; I think atomic_lock_acquire could be moved here..
26076 + move.4 sp, PT_SP(a3) ; Restore sp
26077 + move.4 a4, PT_PC(a3) ; Restore pc in register a4
26078 + move.4 PT_FRAME_TYPE(a3), #0 ; Clear frame_type to indicate it is invalid.
26080 +#ifdef CONFIG_PROTECT_KERNEL
26081 + call a3, __ret_from_fork_bottom_half
26082 + .section .kernel_unprotected, "ax", @progbits
26083 +__ret_from_fork_bottom_half:
26084 + disable_kernel_ranges_for_current d15
26086 + atomic_lock_release ; Leave critical section
26087 + calli a4, 0(a4) ; Return.
26093 + * void *__switch_to(struct task_struct *prev, struct thread_struct *prev_switch,
26094 + * struct thread_struct *next_switch)
26096 + .section .text.__switch_to, "ax", @progbits
26097 + .global __switch_to
26101 + * Set up register a3 to point to save area.
26103 + movea a3, d1 ; a3 now holds prev_switch
26104 + move.4 (a3)4++, d10
26105 + move.4 (a3)4++, d11
26106 + move.4 (a3)4++, d12
26107 + move.4 (a3)4++, d13
26108 + move.4 (a3)4++, a1
26109 + move.4 (a3)4++, a2
26110 + move.4 (a3)4++, a5
26111 + move.4 (a3)4++, a6
26112 + move.4 (a3)4++, a7
26115 + * Set up register a3 to point to restore area.
26117 + movea a3, d2 ; a3 now holds next_switch
26118 + move.4 d10 , (a3)4++
26119 + move.4 d11 , (a3)4++
26120 + move.4 d12 , (a3)4++
26121 + move.4 d13 , (a3)4++
26122 + move.4 a1 , (a3)4++
26123 + move.4 a2 , (a3)4++
26124 + move.4 a5 , (a3)4++
26125 + move.4 a6 , (a3)4++
26126 + move.4 a7 , (a3)4++
26129 + * Load the sw_ksp with the proper thread_info pointer.
26131 + movei d15, #(~(ASM_THREAD_SIZE-1))
26132 + and.4 a3, sp, d15 ; a3 now has the thread info pointer
26133 + moveai a4, #%hi(sw_ksp)
26134 + lea.1 a4, %lo(sw_ksp)(a4) ; a4 now has the base address of sw_ksp array
26135 + lsr.4 d15, ROSR, #2 ; Thread number - bit's 6 through 31 are zeroes anyway.
26136 + move.4 (a4, d15), a3 ; Load the thread info pointer into the hw_ksp array..
26139 + * We are done with context switch. Time to return..
26142 + .size __switch_to, . - __switch_to
26145 + * ubicom32_emulate_insn()
26146 + * Emulates the instruction.
26149 + * unsigned int ubicom32_emulate_insn(int source1, int source2, int source3, int *save_acc, int *save_csr);
26151 + .section .text.ubicom32_emulate_insn, "ax", @progbits
26152 + .global ubicom32_emulate_insn
26153 + .global trap_emulate
26154 +ubicom32_emulate_insn:
26155 + movea a3, d3 ; a3 holds save_acc pointer
26156 + movea a4, d4 ; a4 hods save_csr pointer
26157 + move.4 source3, d2
26158 + move.4 acc0_lo, (a3)
26159 + move.4 acc0_hi, 4(a3)
26160 + move.4 acc1_lo, 8(a3)
26161 + move.4 acc1_hi, 12(a3)
26162 + move.4 mac_rc16, 16(a3)
26169 + move.4 (a4), CSR ; Save csr
26170 + move.4 (a3), acc0_lo
26171 + move.4 4(a3), acc0_hi
26172 + move.4 8(a3), acc1_lo
26173 + move.4 12(a3), acc1_hi
26174 + move.4 16(a3), mac_rc16
26176 + .size ubicom32_emulate_insn, . - ubicom32_emulate_insn
26177 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/ubicom32_ksyms.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/ubicom32_ksyms.c
26178 --- linux-2.6.30.10/arch/ubicom32/kernel/ubicom32_ksyms.c 1970-01-01 02:00:00.000000000 +0200
26179 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/ubicom32_ksyms.c 2009-12-11 11:45:11.000000000 +0200
26182 + * arch/ubicom32/kernel/ubicom32_ksyms.c
26183 + * Ubicom32 architecture compiler support and misc symbols.
26185 + * (C) Copyright 2009, Ubicom, Inc.
26187 + * This file is part of the Ubicom32 Linux Kernel Port.
26189 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
26190 + * it and/or modify it under the terms of the GNU General Public License
26191 + * as published by the Free Software Foundation, either version 2 of the
26192 + * License, or (at your option) any later version.
26194 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
26195 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
26196 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
26197 + * the GNU General Public License for more details.
26199 + * You should have received a copy of the GNU General Public License
26200 + * along with the Ubicom32 Linux Kernel Port. If not,
26201 + * see <http://www.gnu.org/licenses/>.
26203 + * Ubicom32 implementation derived from (with many thanks):
26208 +#include <linux/module.h>
26209 +#include <linux/linkage.h>
26210 +#include <linux/sched.h>
26211 +#include <linux/string.h>
26212 +#include <linux/mm.h>
26213 +#include <linux/user.h>
26214 +#include <linux/elfcore.h>
26215 +#include <linux/in6.h>
26216 +#include <linux/interrupt.h>
26217 +#include <linux/io.h>
26218 +#include <linux/semaphore.h>
26220 +#include <asm/setup.h>
26221 +#include <asm/machdep.h>
26222 +#include <asm/pgalloc.h>
26223 +#include <asm/irq.h>
26224 +#include <asm/checksum.h>
26225 +#include <asm/current.h>
26227 +/* platform dependent support */
26229 +EXPORT_SYMBOL(__ioremap);
26230 +EXPORT_SYMBOL(iounmap);
26232 +EXPORT_SYMBOL(ip_fast_csum);
26235 +/* Networking helper routines. */
26236 +EXPORT_SYMBOL(csum_partial_copy_nocheck);
26238 +/* The following are special because they're not called
26239 + explicitly (the C compiler generates them). Fortunately,
26240 + their interface isn't gonna change any time soon now, so
26241 + it's OK to leave it out of version control. */
26242 +EXPORT_SYMBOL(memcpy);
26243 +EXPORT_SYMBOL(memset);
26244 +EXPORT_SYMBOL(memmove);
26246 +#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) || __GNUC__ > 4
26248 + * libgcc functions - functions that are used internally by the
26249 + * compiler... (prototypes are not correct though, but that
26250 + * doesn't really matter since they're not versioned).
26252 +extern void __ashldi3(void);
26253 +extern void __ashrdi3(void);
26254 +extern void __divsi3(void);
26255 +extern void __divdi3(void);
26256 +extern void __lshrdi3(void);
26257 +extern void __modsi3(void);
26258 +extern void __muldi3(void);
26259 +extern void __udivsi3(void);
26260 +extern void __umodsi3(void);
26262 +/* gcc lib functions */
26263 +EXPORT_SYMBOL(__ashldi3);
26264 +EXPORT_SYMBOL(__ashrdi3);
26265 +EXPORT_SYMBOL(__divsi3);
26266 +EXPORT_SYMBOL(__divdi3);
26267 +EXPORT_SYMBOL(__lshrdi3);
26268 +EXPORT_SYMBOL(__modsi3);
26269 +EXPORT_SYMBOL(__muldi3);
26270 +EXPORT_SYMBOL(__udivsi3);
26271 +EXPORT_SYMBOL(__umodsi3);
26273 +extern void __libgcc_udivmodsi(void);
26274 +extern void __libgcc_divmodsi(void);
26276 +EXPORT_SYMBOL(__libgcc_udivmodsi);
26277 +EXPORT_SYMBOL(__libgcc_divmodsi);
26279 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/ubicom32_syscall.S linux-2.6.30.10-ubi/arch/ubicom32/kernel/ubicom32_syscall.S
26280 --- linux-2.6.30.10/arch/ubicom32/kernel/ubicom32_syscall.S 1970-01-01 02:00:00.000000000 +0200
26281 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/ubicom32_syscall.S 2009-12-11 11:45:11.000000000 +0200
26284 + * arch/ubicom32/kernel/ubicom32_syscall.S
26285 + * <TODO: Replace with short file description>
26287 + * (C) Copyright 2009, Ubicom, Inc.
26289 + * This file is part of the Ubicom32 Linux Kernel Port.
26291 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
26292 + * it and/or modify it under the terms of the GNU General Public License
26293 + * as published by the Free Software Foundation, either version 2 of the
26294 + * License, or (at your option) any later version.
26296 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
26297 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
26298 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
26299 + * the GNU General Public License for more details.
26301 + * You should have received a copy of the GNU General Public License
26302 + * along with the Ubicom32 Linux Kernel Port. If not,
26303 + * see <http://www.gnu.org/licenses/>.
26305 + * Ubicom32 implementation derived from (with many thanks):
26310 +#include <linux/sys.h>
26311 +#include <linux/linkage.h>
26312 +#include <linux/unistd.h>
26314 +#include <asm/ubicom32-common.h>
26315 +#include <asm/thread_info.h>
26316 +#include <asm/asm-offsets.h>
26317 +#include <asm/range-protect.h>
26320 + * __old_system_call()
26322 + .section .old_syscall_entry.text, "ax", @progbits
26323 +#ifdef CONFIG_OLD_40400010_SYSTEM_CALL
26324 +__old_system_call:
26325 + call a3, system_call
26326 + .size __old_system_call, . - __old_system_call ;
26329 + * something that will crash the userspace application, but
26330 + * should not take down the kernel, if protection is enabled
26331 + * this will never even get executed.
26333 + .long 0xFABBCCDE ; illegal instruction
26334 + bkpt #-1 ; we will never get here
26340 + .section .syscall_entry.text, "ax", @progbits
26341 + .global system_call
26344 + * Regular ABI rules for function calls apply for syscall. d8 holds
26345 + * the syscall number. We will use that to index into the syscall table.
26346 + * d0 - d5 hold the parameters.
26348 + * First we get the current thread_info and swap to the kernel stack.
26349 + * This is done by reading the current thread and looking up the ksp
26350 + * from the sw_ksp array and storing it in a3.
26352 + * Then we reserve space for the syscall context a struct pt_regs and
26353 + * save it using a4 initially and later as sp.
26354 + * Once sp is set to the kernel sp we can leave the critical section.
26356 + * For the user case the kernel stack will have the following layout.
26358 + * a3 ksp[0] +-----------------------+
26359 + * | Thread info area |
26360 + * | struct thread_info |
26361 + * +-----------------------+
26363 + * | Kernel Stack Area |
26365 + * a4 / sp >>> +-----------------------+
26366 + * | Context save area |
26367 + * | struct pt_reg |
26368 + * ksp[THREAD_SIZE-8] +-----------------------+
26369 + * | 8 Byte Buffer Zone |
26370 + * ksp[THREAD_SIZE] +-----------------------+
26373 + * For kernel syscalls the layout is as follows.
26375 + * a3 ksp[0] +-----------------------+
26376 + * | Thread info area |
26377 + * | struct thread_info |
26378 + * +-----------------------+
26380 + * | Kernel Stack Area |
26382 + * a4 / sp >>> +-----------------------+
26383 + * | Context save area |
26384 + * | struct pt_reg |
26385 + * sp at syscall entry +-----------------------+
26386 + * | Callers Kernel Stack |
26389 + * Once the context is saved we optionally call syscall_trace and setup
26390 + * the exit routine and jump to the syscall.
26394 + * load the base address for sw_ksp into a3
26395 + * Note.. we cannot access it just yet as protection is still on.
26397 + moveai a3, #%hi(sw_ksp)
26398 + lea.1 a3, %lo(sw_ksp)(a3)
26401 + * Enter critical section .
26403 + * The 'critical' aspects here are the switching the to the ksp and
26404 + * changing the protection registers, these both use per thread
26405 + * information so we need to protect from a context switch. For now this
26406 + * is done using the global atomic lock.
26408 + atomic_lock_acquire
26410 + thread_get_self d15 ; Load current thread number
26411 +#ifdef CONFIG_PROTECT_KERNEL
26412 + lsl.4 d9, #1, d15 ; Convert to thread bit
26413 + enable_kernel_ranges d9
26416 + * in order to reduce the size of code in the syscall section we get
26417 + * out of it right now
26419 + call a4, __system_call_bottom_half
26420 + .size system_call, . - system_call
26422 + .section .text.__system_call_bottom_half, "ax", @progbits
26423 +__system_call_bottom_half:
26426 + * We need to Determine if this is a kernel syscall or user syscall.
26427 + * Start by loading the pointer for the thread_info structure for the
26428 + * current process in to a3.
26430 + move.4 a3, (a3, d15) ; a3 = sw_ksp[d15]
26433 + * Now if this is a kernel thread the same value can be a acheived by
26434 + * masking off the lower bits on the current stack pointer.
26436 + movei d9, #(~(ASM_THREAD_SIZE-1)) ; load mask
26437 + and.4 d9, sp, d9 ; apply mask
26440 + * d9 now has the masked version of the sp. If this is identical to
26441 + * what is in a3 then don't switch to ksp as we are already in the
26447 + * if d9 and a3 are not equal. We are usespace and have to shift to
26453 + * Kernel Syscall.
26455 + * The kernel has called this routine. We have to pdec space for pt_regs
26458 + pdec a4, PT_SIZE(sp) ; a4 = ksp - PT_SIZE
26462 + * Userspace Syscall.
26464 + * Add THREAD_SIZE and subtract PT_SIZE to create the proper ksp
26466 +1: movei d15, #(ASM_THREAD_SIZE - 8 - PT_SIZE)
26467 + lea.1 a4, (a3, d15) ; a4 = ksp + d15
26470 + * Replace user stack pointer with kernel stack pointer (a4)
26471 + * Load -1 into frame_type in save area to indicate this is system call
26474 +2: move.4 PT_A7(a4), a7 ; Save old sp/A7 on kernel stack
26475 + move.4 PT_FRAME_TYPE(a4), #-1 ; Set the frame type.
26476 + move.4 sp, a4 ; Change to ksp.
26478 + * We are now officially back in the kernel!
26482 + * Now that we are on the ksp we can leave the critical section
26484 + atomic_lock_release
26487 + * We need to save a0 because we need to be able to restore it in
26488 + * the event that we need to handle a signal. It's not generally
26489 + * a callee-saved register but is the GOT pointer.
26491 + move.4 PT_A0(sp), a0 ; Save A0 on kernel stack
26494 + * We still need to save d10-d13, a1, a2, a5, a6 in the kernel frame
26495 + * for this process, we also save the system call params in the case of
26496 + * syscall restart. (note a7 was saved above)
26498 + move.4 PT_A1(sp), a1 ; Save A1 on kernel stack
26499 + move.4 PT_A2(sp), a2 ; Save A2 on kernel stack
26500 + move.4 PT_A5(sp), a5 ; Save A5 on kernel stack
26501 + move.4 PT_A6(sp), a6 ; Save A6 on kernel stack
26502 + move.4 PT_PC(sp), a5 ; Save A5 at the PC location
26503 + move.4 PT_D10(sp), d10 ; Save D10 on kernel stack
26504 + move.4 PT_D11(sp), d11 ; Save D11 on kernel stack
26505 + move.4 PT_D12(sp), d12 ; Save D12 on kernel stack
26506 + move.4 PT_D13(sp), d13 ; Save D13 on kernel stack
26509 + * Now save the syscall parameters
26511 + move.4 PT_D0(sp), d0 ; Save d0 on kernel stack
26512 + move.4 PT_ORIGINAL_D0(sp), d0 ; Save d0 on kernel stack
26513 + move.4 PT_D1(sp), d1 ; Save d1 on kernel stack
26514 + move.4 PT_D2(sp), d2 ; Save d2 on kernel stack
26515 + move.4 PT_D3(sp), d3 ; Save d3 on kernel stack
26516 + move.4 PT_D4(sp), d4 ; Save d4 on kernel stack
26517 + move.4 PT_D5(sp), d5 ; Save d5 on kernel stack
26518 + move.4 PT_D8(sp), d8 ; Save d8 on kernel stack
26521 + * Test if syscalls are being traced and if they are jump to syscall
26522 + * trace (it will comeback here)
26524 + btst TI_FLAGS(a3), #ASM_TIF_SYSCALL_TRACE
26525 + jmpne.f .Lsystem_call__trace
26526 +.Lsystem_call__trace_complete:
26528 + * Check for a valid call number [ 0 <= syscall_number < NR_syscalls ]
26532 + cmpi d8, #NR_syscalls
26536 + * They have passed an invalid number. Call sys_ni_syscall staring by
26537 + * load a4 with the base address of sys_ni_syscall
26539 +3: moveai a4, #%hi(sys_ni_syscall)
26540 + lea.1 a4, %lo(sys_ni_syscall)(a4)
26541 + jmpt.t 5f ; Jump to regular processing
26544 + * Validated syscall, load the syscall table base address into a3 and
26545 + * read the syscall ptr out.
26547 +4: moveai a3, #%hi(sys_call_table)
26548 + lea.1 a3, %lo(sys_call_table)(a3) ; a3 = sys_call_table
26549 + move.4 a4, (a3, d8) ; a4 = sys_call_table[d8]
26552 + * Before calling the syscall, setup a5 so that syscall_exit is called
26553 + * on return from syscall
26555 +5: moveai a5, #%hi(syscall_exit) ; Setup return address
26556 + lea.1 a5, %lo(syscall_exit)(a5) ; from system call
26559 + * If the syscall is __NR_rt_rigreturn then we have to test d1 to
26560 + * figure out if we have to change change the return routine to restore
26563 + cmpi d8, #__NR_rt_sigreturn
26567 + * Launch system call (it will return through a5 - syscall_exit)
26572 + * System call is rt_sigreturn. Test d1. If it is 1 we have to
26573 + * change the return address to restore_all_registers
26578 + moveai a5, #%hi(restore_all_registers) ; Setup return address
26579 + lea.1 a5, %lo(restore_all_registers)(a5) ; to restore_all_registers.
26582 + * Launch system call (it will return through a5)
26584 +7: calli a3, 0(a4) ; Launch system call
26586 +.Lsystem_call__trace:
26588 + * Syscalls are being traced.
26589 + * Call syscall_trace, (return here)
26591 + call a5, syscall_trace
26594 + * Restore syscall state (it would have been discarded during the
26597 + move.4 d0, PT_D0(sp) ; Restore d0 from kernel stack
26598 + move.4 d1, PT_D1(sp) ; Restore d1 from kernel stack
26599 + move.4 d2, PT_D2(sp) ; Restore d2 from kernel stack
26600 + move.4 d3, PT_D3(sp) ; Restore d3 from kernel stack
26601 + move.4 d4, PT_D4(sp) ; Restore d4 from kernel stack
26602 + move.4 d5, PT_D5(sp) ; Restore d5 from kernel stack
26603 + /* add this back if we ever have a syscall with 7 args */
26604 + move.4 d8, PT_D8(sp) ; Restore d8 from kernel stack
26607 + * return to syscall
26609 + jmpt.t .Lsystem_call__trace_complete
26610 + .size __system_call_bottom_half, . - __system_call_bottom_half
26615 + .section .text.syscall_exit
26616 + .global syscall_exit
26619 + * d0 contains the return value. We should move that into the kernel
26620 + * stack d0 location. We will be transitioning from kernel to user
26621 + * mode. Test the flags and see if we have to call schedule. If we are
26622 + * going to truly exit then all that has to be done is that from the
26623 + * kernel stack we have to restore d0, a0, a1, a2, a5, a6 and sp (a7)bb
26624 + * and then return via a5.
26628 + * Save d0 to pt_regs
26630 + move.4 PT_D0(sp), d0 ; Save d0 into the kernel stack
26633 + * load the thread_info structure by masking off the THREAD_SIZE
26636 + * Note: we used to push a1, but now we don't as we are going
26637 + * to eventually restore it to the userspace a1.
26639 + movei d9, #(~(ASM_THREAD_SIZE-1))
26643 + * Are any interesting bits set on TI flags, if there are jump
26644 + * aside to post_processing.
26646 + move.4 d9, #(_TIF_SYSCALL_TRACE | _TIF_NEED_RESCHED | _TIF_SIGPENDING)
26647 + and.4 #0, TI_FLAGS(a1), d9
26648 + jmpne.f .Lsyscall_exit__post_processing ; jump to handler
26649 +.Lsyscall_exit__post_processing_complete:
26651 + move.4 d0, PT_D0(sp) ; Restore D0 from kernel stack
26652 + move.4 d1, PT_D1(sp) ; Restore d1 from kernel stack
26653 + move.4 d2, PT_D2(sp) ; Restore d2 from kernel stack
26654 + move.4 d3, PT_D3(sp) ; Restore d3 from kernel stack
26655 + move.4 d4, PT_D4(sp) ; Restore d4 from kernel stack
26656 + move.4 d5, PT_D5(sp) ; Restore d5 from kernel stack
26657 + move.4 d8, PT_D8(sp) ; Restore d8 from kernel stack
26658 + move.4 d10, PT_D10(sp) ; Restore d10 from kernel stack
26659 + move.4 d11, PT_D11(sp) ; Restore d11 from kernel stack
26660 + move.4 d12, PT_D12(sp) ; Restore d12 from kernel stack
26661 + move.4 d13, PT_D13(sp) ; Restore d13 from kernel stack
26662 + move.4 a1, PT_A1(sp) ; Restore A1 from kernel stack
26663 + move.4 a2, PT_A2(sp) ; Restore A2 from kernel stack
26664 + move.4 a5, PT_A5(sp) ; Restore A5 from kernel stack
26665 + move.4 a6, PT_A6(sp) ; Restore A6 from kernel stack
26666 + move.4 a0, PT_A0(sp) ; Restore A6 from kernel stack
26669 + * this is only for debug, and could be removed for production builds
26671 + move.4 PT_FRAME_TYPE(sp), #0 ; invalidate frame_type
26673 +#ifdef CONFIG_PROTECT_KERNEL
26675 + call a4, __syscall_exit_bottom_half
26677 + .section .kernel_unprotected, "ax", @progbits
26678 +__syscall_exit_bottom_half:
26680 + * Enter critical section
26682 + atomic_lock_acquire
26683 + disable_kernel_ranges_for_current d15
26686 + * Lastly restore userspace stack ptr
26688 + * Note: that when protection is on we need to hold the lock around the
26689 + * stack swap as well because otherwise the protection could get
26690 + * inadvertently disabled again at the end of a context switch.
26692 + move.4 a7, PT_A7(sp) ; Restore A7 from kernel stack
26695 + * We are now officially back in userspace!
26698 +#ifdef CONFIG_PROTECT_KERNEL
26700 + * Leave critical section and return to user space.
26702 + atomic_lock_release
26704 + calli a5, 0(a5) ; Back to userspace code.
26706 + bkpt #-1 ; we will never get here
26709 + * Post syscall processing. (unlikely part of syscall_exit)
26711 + * Are we tracing syscalls. If TIF_SYSCALL_TRACE is set, call
26712 + * syscall_trace routine and return here.
26714 + .section .text.syscall_exit, "ax", @progbits
26715 +.Lsyscall_exit__post_processing:
26716 + btst TI_FLAGS(a1), #ASM_TIF_SYSCALL_TRACE
26718 + call a5, syscall_trace
26721 + * Do we need to resched ie call schedule. If TIF_NEED_RESCHED is set,
26722 + * call the scheduler, it will come back here.
26724 +1: btst TI_FLAGS(a1), #ASM_TIF_NEED_RESCHED
26726 + call a5, schedule
26729 + * Do we need to post a signal, if TIF_SIGPENDING is set call the
26732 +2: btst TI_FLAGS(a1), #ASM_TIF_SIGPENDING
26733 + jmpeq.t .Lsyscall_exit__post_processing_complete
26736 + * setup the do signal call
26738 + move.4 d0, #0 ; oldset pointer is NULL
26739 + lea.1 d1, (sp) ; d1 is the regs pointer.
26740 + call a5, do_signal
26742 + jmpt.t .Lsyscall_exit__post_processing_complete
26744 +/* .size syscall_exit, . - syscall_exit */
26747 + * kernel_execve()
26748 + * kernel_execv is called when we the kernel is starting a
26749 + * userspace application.
26751 + .section .kernel_unprotected, "ax", @progbits
26752 + .global kernel_execve
26754 + move.4 -4(sp)++, a5 ; Save return address
26758 + movei d8, #__NR_execve ; call execve
26759 + call a5, system_call
26760 + move.4 a5, (sp)4++
26763 + * protection was enabled again at syscall exit, but we want
26764 + * to return to kernel so we enable it again.
26766 +#ifdef CONFIG_PROTECT_KERNEL
26768 + * We are entering the kernel so we need to disable the protection.
26769 + * Enter critical section, disable ranges and leave critical section.
26771 + call a3, __enable_kernel_ranges ; and jump back to kernel
26773 + ret a5 ; jump back to the kernel
26776 + .size kernel_execve, . - kernel_execve
26779 + * signal_trampoline()
26781 + * Deals with transitioning from to userspace signal handlers and returning
26782 + * to userspace, only called from the kernel.
26785 + .section .kernel_unprotected, "ax", @progbits
26786 + .global signal_trampoline
26787 +signal_trampoline:
26789 + * signal_trampoline is called when we are jumping from the kernel to
26790 + * the userspace signal handler.
26792 + * The following registers are relevant. (set setup_rt_frame)
26793 + * sp is the user space stack not the kernel stack
26794 + * d0 = signal number
26795 + * d1 = siginfo_t *
26796 + * d2 = ucontext *
26797 + * d3 = the user space signal handler
26798 + * a0 is set to the GOT if userspace application is FDPIC, otherwise 0
26799 + * a3 is set to the FD for the signal if userspace application is FDPIC
26801 +#ifdef CONFIG_PROTECT_KERNEL
26803 + * We are leaving the kernel so we need to enable the protection.
26804 + * Enter critical section, disable ranges and leave critical section.
26806 + atomic_lock_acquire ; Enter critical section
26807 + disable_kernel_ranges_for_current d15 ; disable kernel ranges
26808 + atomic_lock_release ; Leave critical section
26811 + * The signal handler pointer is in register d3 so tranfer it to a4 and
26814 + movea a4, d3 ; signal handler
26818 + * Return to userspace through rt_syscall which is stored on top of the
26819 + * stack d1 contains ret_via_interrupt status.
26821 + move.4 d8, (sp) ; d8 (syscall #) = rt_syscall
26822 + move.4 d1, 4(sp) ; d1 = ret_via_interrupt
26823 + call a5, system_call ; as we are 'in' the kernel
26824 + ; we can call kernel_syscall
26826 + bkpt #-1 ; will never get here.
26827 + .size signal_trampoline, . - signal_trampoline
26830 + * kernel_thread_helper()
26832 + * Entry point for kernel threads (only referenced by kernel_thread()).
26834 + * On execution d0 will be 0, d1 will be the argument to be passed to the
26835 + * kernel function.
26836 + * d2 contains the kernel function that needs to get called.
26837 + * d3 will contain address to do_exit which needs to get moved into a5.
26839 + * On return from fork the child thread d0 will be 0. We call this dummy
26840 + * function which in turn loads the argument
26842 + .section .kernel_unprotected, "ax", @progbits
26843 + .global kernel_thread_helper
26844 +kernel_thread_helper:
26846 + * Create a kernel thread. This is called from ret_from_vfork (a
26847 + * userspace return routine) so we need to put it in an unprotected
26848 + * section and re-enable protection before calling the vector in d2.
26851 +#ifdef CONFIG_PROTECT_KERNEL
26853 + * We are entering the kernel so we need to disable the protection.
26854 + * Enter critical section, disable ranges and leave critical section.
26856 + call a5, __enable_kernel_ranges
26859 + * Move argument for kernel function into d0, and set a5 return address
26860 + * (a5) to do_exit and return through a2
26862 + move.4 d0, d1 ; d0 = arg
26863 + move.4 a5, d3 ; a5 = do_exit
26864 + ret d2 ; call function ptr in d2
26865 + .size kernel_thread_helper, . - kernel_thread_helper
26867 +#ifdef CONFIG_PROTECT_KERNEL
26868 + .section .kernel_unprotected, "ax", @progbits
26869 +__enable_kernel_ranges:
26870 + atomic_lock_acquire ; Enter critical section
26871 + enable_kernel_ranges_for_current d15
26872 + atomic_lock_release ; Leave critical section
26874 + .size __enable_kernel_ranges, . - __enable_kernel_ranges
26879 + * The following system call intercept functions where we setup the
26880 + * input to the real system call. In all cases these are just taking
26881 + * the current sp which is pointing to pt_regs and pushing it into the
26882 + * last arg of the system call.
26884 + * i.e. the public definition of sys_execv is
26885 + * sys_execve( char *name,
26888 + * but process.c defines it as
26889 + * sys_execve( char *name,
26892 + * struct pt_regs *regs )
26894 + * so execve_intercept needs to populate the 4th arg with pt_regs*,
26895 + * which is the stack pointer as we know we must be coming out of
26898 + * The intercept vectors are referenced by syscalltable.S
26902 + * execve_intercept()
26904 + .section .text.execve_intercept, "ax", @progbits
26905 + .global execve_intercept
26907 + move.4 d3, sp ; Save pt_regs address
26908 + call a3, sys_execve
26910 + .size execve_intercept, . - execve_intercept
26913 + * vfork_intercept()
26915 + .section .text.vfork_intercept, "ax", @progbits
26916 + .global vfork_intercept
26918 + move.4 d0, sp ; Save pt_regs address
26919 + call a3, sys_vfork
26921 + .size vfork_intercept, . - vfork_intercept
26924 + * clone_intercept()
26926 + .section .text.clone_intercept, "ax", @progbits
26927 + .global clone_intercept
26929 + move.4 d2, sp ; Save pt_regs address
26930 + call a3, sys_clone
26932 + .size clone_intercept, . - clone_intercept
26935 + * sys_sigsuspend()
26937 + .section .text.sigclone_intercept, "ax", @progbits
26938 + .global sys_sigsuspend
26940 + move.4 d0, sp ; Pass pointer to pt_regs in d0
26941 + call a3, do_sigsuspend
26943 + .size sys_sigsuspend, . - sys_sigsuspend
26946 + * sys_rt_sigsuspend()
26948 + .section .text.sys_rt_sigsuspend, "ax", @progbits
26949 + .global sys_rt_sigsuspend
26950 +sys_rt_sigsuspend:
26951 + move.4 d0, sp ; Pass pointer to pt_regs in d0
26952 + call a3, do_rt_sigsuspend
26954 + .size sys_rt_sigsuspend, . - sys_rt_sigsuspend
26957 + * sys_rt_sigreturn()
26959 + .section .text.sys_rt_sigreturn, "ax", @progbits
26960 + .global sys_rt_sigreturn
26962 + move.4 d0, sp ; Pass pointer to pt_regs in d0
26963 + call a3, do_rt_sigreturn
26965 + .size sys_rt_sigreturn, . - sys_rt_sigreturn
26968 + * sys_sigaltstack()
26970 + .section .text.sys_sigaltstack, "ax", @progbits
26971 + .global sys_sigaltstack
26973 + move.4 d0, sp ; Pass pointer to pt_regs in d0
26974 + call a3, do_sys_sigaltstack
26976 + .size sys_sigaltstack, . - sys_sigaltstack
26977 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/unaligned_trap.c linux-2.6.30.10-ubi/arch/ubicom32/kernel/unaligned_trap.c
26978 --- linux-2.6.30.10/arch/ubicom32/kernel/unaligned_trap.c 1970-01-01 02:00:00.000000000 +0200
26979 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/unaligned_trap.c 2009-12-11 11:45:11.000000000 +0200
26982 + * arch/ubicom32/kernel/unaligned_trap.c
26983 + * Handle unaligned traps in both user or kernel space.
26985 + * (C) Copyright 2009, Ubicom, Inc.
26987 + * This file is part of the Ubicom32 Linux Kernel Port.
26989 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
26990 + * it and/or modify it under the terms of the GNU General Public License
26991 + * as published by the Free Software Foundation, either version 2 of the
26992 + * License, or (at your option) any later version.
26994 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
26995 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
26996 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
26997 + * the GNU General Public License for more details.
26999 + * You should have received a copy of the GNU General Public License
27000 + * along with the Ubicom32 Linux Kernel Port. If not,
27001 + * see <http://www.gnu.org/licenses/>.
27003 + * Ubicom32 implementation derived from (with many thanks):
27009 +#include <linux/types.h>
27010 +#include <linux/kernel.h>
27011 +#include <asm/cacheflush.h>
27012 +#include <asm/traps.h>
27017 +/* no possible trap */
27019 +/* possible source operand trap */
27022 +/* possible destination operand trap */
27025 +/* can be either source or destination or both */
27027 +#define TWO_OP_2 6
27029 +/* TODO: What is the real value here, put something in to make it compile for
27031 +#define MOVE_2 0x0d
27032 +#define LSL_2 0x11
27033 +#define LSR_2 0x13
27034 +#define MOVEI 0x19
27037 +static int op_format[32] =
27039 + TWO_OP, /* 0x00 */
27043 + TWO_OP, /* 0x04 */
27047 + TWO_OP_2, /* 0x08 */
27051 + TWO_OP_2, /* 0x0C */
27055 + TWO_OP, /* 0x10 */
27059 + UNUSED, /* 0x14 */
27063 + SRC_2, /* 0x18 */
27067 + UNUSED, /* 0x1C */
27069 + UNUSED, /* unaligned CALLI will not be fixed. */
27073 +static int op_0_format[32] =
27075 + UNUSED, /* 0x00 */
27079 + UNUSED, /* 0x04 - ret don't fix - bad ret is always wrong */
27083 + UNUSED, /* 0x08 */
27087 + TWO_OP, /* 0x0c */
27090 + UNUSED, /* .1 can't trap */
27091 + UNUSED, /* 0x10 */
27095 + UNUSED, /* 0x14 */
27099 + UNUSED, /* 0x18 */
27106 + DEST, /* all lea have 32-bit destination */
27109 +static int op_2_format[32] =
27111 + UNUSED, /* 0x00 */
27115 + UNUSED, /* 0x04 */
27119 + UNUSED, /* 0x08 crcgen is .1 */
27123 + UNUSED, /* 0x0c */
27135 + UNUSED, /* 0x18 */
27145 +static int op_6_format[32] =
27147 + SRC_2, /* 0x00 */
27151 + SRC_2, /* 0x04 */
27155 + SRC, /* 0x08 MULS.4 */
27159 + UNUSED, /* 0x0c */
27167 + UNUSED, /* 0x14 */
27171 + UNUSED, /* 0x18 */
27175 + UNUSED, /* 0x1c */
27182 + * unaligned_get_address()
27183 + * get an address using save_an and save_dn registers, and updates save_an
27184 + * with side effects
27186 +unsigned char *unaligned_get_address(int thread, int specifier, int four_byte,
27187 + unsigned int save_an[],
27188 + unsigned int save_dn[], int *write_back_an)
27190 + unsigned char *address;
27192 + int areg = (specifier >> 5) & 7;
27193 + if ((specifier >> 8) == 2) {
27194 + int offset = specifier & 0xf;
27195 + offset = ((offset << 28) >> 28);
27196 + if (likely(four_byte)) {
27201 + if (specifier & 0x10) {
27202 + address = (unsigned char *)(save_an[areg] + offset);
27204 + address = (unsigned char *)save_an[areg];
27206 + save_an[areg] = save_an[areg] + offset;
27209 + * Let caller know An registers have been modified.
27211 + *write_back_an = 1;
27212 + } else if ((specifier >> 8) == 3) {
27213 + int dreg = specifier & 0xf;
27214 + if (likely(four_byte)) {
27215 + address = (unsigned char *)(save_an[areg] +
27216 + (save_dn[dreg] << 2));
27218 + address = (unsigned char *)(save_an[areg] +
27219 + (save_dn[dreg] << 1));
27222 + int offset = ((specifier >> 3) & 0x60) | (specifier & 0x1f);
27223 + if (likely(four_byte)) {
27224 + address = (unsigned char *)(save_an[areg] +
27227 + address = (unsigned char *)(save_an[areg] +
27235 +static int save_dn[16];
27236 +static int save_an[8];
27237 +static int save_acc[5];
27240 + * unaligned_emulate()
27241 + * emulate the instruction at thread's pc that has taken an unaligned data
27244 + * source or destination or both might be unaligned
27245 + * the instruction must have a memory source or destination or both
27246 + * the emulated instruction is copied and executed in this thread
27248 + * TODO: Protection is handled outside of this function
27249 + * TODO: handling simultaneous unaligned and memory protection traps
27251 + * Get thread state
27252 + * the PC and instruction (and local copy, emulate_inst), and An
27253 + * and Dn registers
27254 + * All implicit soruce state (source3, CSR, accumulators)
27256 + * if the instruction has a memory source
27257 + * Use the instruction, An and Dn registers to form src_address
27258 + * get unaligned source data from src_address (usually sign
27260 + * (2 bytes, with or without sign extension, or 4 bytes)
27261 + * modify emulate_inst to use d0 as source
27263 + * get the soure operand from one of thread's registers
27264 + * if instruction has a memory destination
27265 + * Use the instruction, An and Dn registers to form dest_address
27266 + * modify emulate_inst to use d0 as destination
27267 + * if there was a memory source
27268 + * put the source data in thread's d0
27269 + * get the source-2 Dn operand and source 3 operand from thread
27270 + * execute modified inst
27271 + * (save it, flush caches, set up local values for implicit
27272 + * sources, execute, save explicit and implicit results)
27273 + * if inst has destination address
27274 + * copy result to dest_address, possibly unaligned, 1, 2, or 4
27276 + * restore thread's implicit results (modified address registers, CSR,
27277 + * accumulators) add 4 to thread's pc
27279 +void unaligned_emulate(unsigned int thread)
27282 + unsigned int inst;
27284 + unsigned int subop;
27286 + unsigned int emulate_inst;
27288 + int src_operand, dest_operand;
27291 + unsigned int source1;
27292 + unsigned int source_data;
27293 + unsigned char *dest_address = NULL;
27295 + unsigned int result;
27296 + unsigned int write_back_an = 0;
27297 + unsigned int chip_id_copy;
27299 + extern unsigned int trap_emulate;
27300 + extern unsigned int ubicom32_emulate_insn(int source1, int source2,
27301 + int source3, int *save_acc,
27305 + * get the chip_id
27308 + " move.4 %0, chip_id \n\t" /* get chip_id. */
27309 + : "=r"(chip_id_copy)
27317 + " move.4 CSR, %1 \n\t" /* set source thread in
27319 + " setcsr_flush 0 \n\t"
27320 + " move.4 %0, pc \n\t"
27321 + " move.4 CSR, #0 \n\t" /* restore CSR */
27322 + " setcsr_flush 0 \n\t"
27324 + : "d" ((1 << 8) | (thread << 9))
27328 + inst = *((unsigned int *)pc);
27330 + if (unlikely(op == 2 || op == 6)) {
27331 + subop = (inst >> 21) & 0x1f;
27333 + subop = (inst >> 11) & 0x1f;
27335 + format = op_format[op];
27336 + emulate_inst = inst;
27339 + format = op_0_format[subop];
27340 + } else if (op == 2) {
27341 + format = op_2_format[subop];
27342 + } else if (op == 6) {
27343 + format = op_6_format[subop];
27346 + if (unlikely(format == UNUSED)) {
27348 + * We are not going to emulate this. Bump PC by 4 and move on.
27351 + " move.4 CSR, %0 \n\t"
27352 + " setcsr_flush 0 \n\t"
27353 + " move.4 pc, %1 \n\t"
27354 + " setcsr #0 \n\t"
27355 + " setcsr_flush 0 \n\t"
27357 + : "d"((1 << 14) | (thread << 15)), "d"(pc + 4)
27363 + four_byte = (format == TWO_OP || format == DEST || format == SRC);
27366 + * source or destination memory operand needs emulation
27368 + src_operand = (format == SRC ||
27369 + format == SRC_2 ||
27370 + format == TWO_OP ||
27371 + format == TWO_OP_2) &&
27372 + ((inst >> 8) & 7) > 1;
27374 + dest_operand = (format == DEST ||
27375 + format == DEST_2 ||
27376 + format == TWO_OP ||
27377 + format == TWO_OP_2) &&
27378 + ((inst >> 24) & 7) > 1;
27381 + * get thread's implicit sources (not covered by source context select).
27382 + * data and address registers and CSR (for flag bits) and src3 and
27386 + " move.4 CSR, %2 \n\t" /* set source thread in
27388 + " setcsr_flush 0 \n\t"
27389 + " move.4 (%3), d0 \n\t" /* get dn registers */
27390 + " move.4 4(%3), d1 \n\t"
27391 + " move.4 8(%3), d2 \n\t"
27392 + " move.4 12(%3), d3 \n\t"
27393 + " move.4 16(%3), d4 \n\t"
27394 + " move.4 20(%3), d5 \n\t"
27395 + " move.4 24(%3), d6 \n\t"
27396 + " move.4 28(%3), d7 \n\t"
27397 + " move.4 32(%3), d8 \n\t"
27398 + " move.4 36(%3), d9 \n\t"
27399 + " move.4 40(%3), d10 \n\t"
27400 + " move.4 44(%3), d11 \n\t"
27401 + " move.4 48(%3), d12 \n\t"
27402 + " move.4 52(%3), d13 \n\t"
27403 + " move.4 56(%3), d14 \n\t"
27404 + " move.4 60(%3), d15 \n\t"
27405 + " move.4 (%4), a0 \n\t" /* get an registers */
27406 + " move.4 4(%4), a1 \n\t"
27407 + " move.4 8(%4), a2 \n\t"
27408 + " move.4 12(%4), a3 \n\t"
27409 + " move.4 16(%4), a4 \n\t"
27410 + " move.4 20(%4), a5 \n\t"
27411 + " move.4 24(%4), a6 \n\t"
27412 + " move.4 28(%4), a7 \n\t"
27413 + " move.4 %0, CSR \n\t" /* get csr and source3
27414 + * implicit operands */
27415 + " move.4 %1, source3 \n\t"
27416 + " move.4 (%5), acc0_lo \n\t" /* get accumulators */
27417 + " move.4 4(%5), acc0_hi \n\t"
27418 + " move.4 8(%5), acc1_lo \n\t"
27419 + " move.4 12(%5), acc1_hi \n\t"
27420 + " move.4 16(%5), mac_rc16 \n\t"
27421 + " move.4 CSR, #0 \n\t" /* restore CSR */
27422 + " setcsr_flush 0 \n\t"
27423 + : "=m"(save_csr), "=m"(source3)
27424 + : "d"((1 << 8) | (thread << 9)),
27425 + "a"(save_dn), "a"(save_an), "a"(save_acc)
27430 + * turn off thread select bits if they were on
27432 + BUG_ON((save_csr & 0x04100) != 0);
27433 + if (unlikely(save_csr & 0x04100)) {
27435 + * Things are in funny state as thread select bits are on in
27438 + panic("In unaligned trap handler. Trap thread CSR has thread "
27439 + "select bits on.\n");
27442 + save_csr = save_csr & 0x1000ff;
27445 + * get the source1 operand
27448 + if (src_operand) {
27449 + unsigned char *src_address;
27452 + * source1 comes from memory
27454 + BUG_ON(!(format == TWO_OP || format == TWO_OP_2 ||
27455 + format == SRC || format == SRC_2));
27456 + src_address = unaligned_get_address(thread, inst & 0x7ff,
27457 + four_byte, save_an,
27458 + save_dn, &write_back_an);
27461 + * get data (possibly unaligned)
27463 + if (likely(four_byte)) {
27464 + source_data = (*src_address << 24) |
27465 + (*(src_address + 1) << 16) |
27466 + (*(src_address + 2) << 8) |
27467 + *(src_address + 3);
27468 + source1 = source_data;
27470 + source1 = *src_address << 8 |
27471 + *(src_address + 1);
27474 + * Source is not extended if the instrution is MOVE.2 or
27475 + * if the cpu CHIP_ID >= 0x30000 and the instruction is
27476 + * either LSL.2 or LSR.2. All other cases have to be
27479 + if ((!(op == 2 && subop == MOVE_2)) &&
27480 + (!((chip_id_copy >= 0x30000) &&
27481 + (subop == LSL_2 || subop == LSR_2)))) {
27483 + * Have to sign extend the .2 entry.
27485 + source1 = ((unsigned int)
27487 + ((signed short) source1)));
27490 + } else if (likely(op != MOVEI)) {
27492 + * source1 comes from a register, using move.4 d0, src1
27493 + * unaligned_emulate_get_source is pointer to code to insert remulated instruction
27495 + extern unsigned int unaligned_emulate_get_src;
27496 + *((int *)&unaligned_emulate_get_src) &= ~(0x7ff);
27497 + *((int *)&unaligned_emulate_get_src) |= (inst & 0x7ff);
27498 + flush_dcache_range((unsigned long)(&unaligned_emulate_get_src),
27499 + (unsigned long)(&unaligned_emulate_get_src) + 4);
27502 + /* source1 uses thread's registers */
27503 + " move.4 CSR, %1 \n\t"
27504 + " setcsr_flush 0 \n\t"
27505 + "unaligned_emulate_get_src: \n\t"
27506 + " move.4 %0, #0 \n\t"
27507 + " setcsr #0 \n\t"
27508 + " setcsr_flush 0 \n\t"
27510 + : "d" ((1 << 8) | (thread << 9))
27516 + * get the destination address
27518 + if (dest_operand) {
27519 + BUG_ON(!(format == TWO_OP || format == TWO_OP_2 ||
27520 + format == DEST || format == DEST_2));
27521 + dest_address = unaligned_get_address(thread,
27522 + ((inst >> 16) & 0x7ff),
27523 + four_byte, save_an,
27524 + save_dn, &write_back_an);
27527 + if (write_back_an) {
27529 + * restore any modified An registers
27532 + " move.4 CSR, %0 \n\t"
27533 + " setcsr_flush 0 \n\t"
27534 + " move.4 a0, (%1) \n\t"
27535 + " move.4 a1, 4(%1) \n\t"
27536 + " move.4 a2, 8(%1) \n\t"
27537 + " move.4 a3, 12(%1) \n\t"
27538 + " move.4 a4, 16(%1) \n\t"
27539 + " move.4 a5, 20(%1) \n\t"
27540 + " move.4 a6, 24(%1) \n\t"
27541 + " move.4 a7, 28(%1) \n\t"
27542 + " setcsr #0 \n\t"
27543 + " setcsr_flush 0 \n\t"
27545 + : "d" ((1 << 14) | (thread << 15)), "a" (save_an)
27551 + * get source 2 register if needed, and modify inst to use d1 for
27552 + * source-2 source-2 will come from this thread, not the trapping thread
27555 + if ((op >= 8 && op <= 0x17) ||
27556 + ((op == 2 || op == 6) && (inst & 0x4000000))) {
27557 + int src_dn = (inst >> 11) & 0xf;
27558 + source2 = save_dn[src_dn];
27560 + * force the emulated instruction to use d1 for source2 operand
27562 + emulate_inst = (emulate_inst & 0xffff07ff) | 0x800;
27565 + if (likely(op != MOVEI)) {
27567 + * change emulated instruction source1 to d0
27569 + emulate_inst &= ~0x7ff;
27570 + emulate_inst |= 1 << 8;
27573 + if (unlikely(op == 6 || op == 2)) {
27575 + * Set destination to d0
27577 + emulate_inst &= ~(0xf << 16);
27578 + } else if (likely(op != CMPI)) {
27580 + * Set general destination field to d0.
27582 + emulate_inst &= ~(0x7ff << 16);
27583 + emulate_inst |= 1 << 24;
27587 + * execute emulated instruction d0, to d0, no memory access
27588 + * source2 if needed will be in d1
27589 + * source3, CSR, and accumulators are set up before execution
27591 + *((unsigned int *)&trap_emulate) = emulate_inst;
27592 + flush_dcache_range((unsigned long)(&trap_emulate),
27593 + (unsigned long)(&trap_emulate) + 4);
27595 + result = ubicom32_emulate_insn(source1, source2, source3,
27596 + save_acc, &save_csr);
27599 + * set the result value
27601 + if (dest_operand) {
27603 + * copy result to memory
27606 + *dest_address++ =
27607 + (unsigned char)((result >> 24) & 0xff);
27608 + *dest_address++ =
27609 + (unsigned char)((result >> 16) & 0xff);
27611 + *dest_address++ = (unsigned char)((result >> 8) & 0xff);
27612 + *dest_address = (unsigned char)(result & 0xff);
27613 + } else if (likely(op != CMPI)) {
27615 + * copy result to a register, using move.4 dest, result
27617 + extern unsigned int unaligned_trap_set_result;
27618 + *((unsigned int *)&unaligned_trap_set_result) &= ~0x7ff0000;
27620 + if (op == 2 || op == 6) {
27621 + *((unsigned int *)&unaligned_trap_set_result) |=
27622 + ((inst & 0x000f0000) | 0x01000000);
27624 + *((unsigned int *)&unaligned_trap_set_result) |=
27625 + (inst & 0x7ff0000);
27627 + flush_dcache_range((unsigned long)&unaligned_trap_set_result,
27628 + ((unsigned long)(&unaligned_trap_set_result) + 4));
27631 + /* result uses thread's registers */
27632 + " move.4 CSR, %1 \n\t"
27633 + " setcsr_flush 0 \n\t"
27634 + "unaligned_trap_set_result: \n\t"
27635 + " move.4 #0, %0 \n\t"
27636 + " setcsr #0 \n\t"
27637 + " setcsr_flush 0 \n\t"
27639 + : "d"(result), "d" ((1 << 14) | (thread << 15))
27645 + * bump PC in thread and restore implicit register changes
27648 + " move.4 CSR, %0 \n\t"
27649 + " setcsr_flush 0 \n\t"
27650 + " move.4 pc, %1 \n\t"
27651 + " move.4 acc0_lo, (%3) \n\t"
27652 + " move.4 acc0_hi, 4(%3) \n\t"
27653 + " move.4 acc1_lo, 8(%3) \n\t"
27654 + " move.4 acc1_hi, 12(%3) \n\t"
27655 + " move.4 mac_rc16, 16(%3) \n\t"
27656 + " move.4 CSR, %2 \n\t"
27657 + " setcsr #0 \n\t"
27658 + " setcsr_flush 0 \n\t"
27660 + : "d"((1 << 14) | (thread << 15)),
27661 + "d"(pc + 4), "d"(save_csr), "a"(save_acc)
27667 + * unaligned_only()
27668 + * Return true if either of the unaligned causes are set (and no others).
27670 +int unaligned_only(unsigned int cause)
27672 + unsigned int unaligned_cause_mask =
27673 + (1 << TRAP_CAUSE_DST_MISALIGNED) |
27674 + (1 << TRAP_CAUSE_SRC1_MISALIGNED);
27676 + BUG_ON(cause == 0);
27677 + return (cause & unaligned_cause_mask) == cause;
27679 diff -ruN linux-2.6.30.10/arch/ubicom32/kernel/vmlinux.lds.S linux-2.6.30.10-ubi/arch/ubicom32/kernel/vmlinux.lds.S
27680 --- linux-2.6.30.10/arch/ubicom32/kernel/vmlinux.lds.S 1970-01-01 02:00:00.000000000 +0200
27681 +++ linux-2.6.30.10-ubi/arch/ubicom32/kernel/vmlinux.lds.S 2009-12-11 11:45:11.000000000 +0200
27684 + * arch/ubicom32/kernel/vmlinux.lds.S
27685 + * vmlinux primary linker script
27687 + * (C) Copyright 2009, Ubicom, Inc.
27689 + * This file is part of the Ubicom32 Linux Kernel Port.
27691 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
27692 + * it and/or modify it under the terms of the GNU General Public License
27693 + * as published by the Free Software Foundation, either version 2 of the
27694 + * License, or (at your option) any later version.
27696 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
27697 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
27698 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
27699 + * the GNU General Public License for more details.
27701 + * You should have received a copy of the GNU General Public License
27702 + * along with the Ubicom32 Linux Kernel Port. If not,
27703 + * see <http://www.gnu.org/licenses/>.
27705 + * Ubicom32 implementation derived from (with many thanks):
27710 +#include <asm-generic/vmlinux.lds.h>
27711 +#include <asm/ocm_size.h>
27712 +#include <asm/memory_map.h>
27713 +#include <asm/thread_info.h>
27714 +#include <linux/threads.h>
27717 + * Sanity checks to prevent errors later on that are much harder to understand
27719 +#if !defined APP_OCM_CODE_SIZE
27720 +#error APP_OCM_CODE_SIZE has not been defined in ocm_size.h
27723 +#if !defined APP_OCM_DATA_SIZE
27724 +#error APP_OCM_DATA_SIZE has not been defined in ocm_size.h
27728 + * The `free' ocm area that ultra does not use.
27730 +#if APP_OCM_CODE_SIZE || APP_OCM_DATA_SIZE
27731 +#define OCM_FREE_START (OCMSTART + APP_OCM_CODE_SIZE)
27732 +#define OCM_FREE_LENGTH (OCMSIZE - APP_OCM_CODE_SIZE - APP_OCM_DATA_SIZE)
27734 +#define OCM_FREE_START OCMEND
27735 +#define OCM_FREE_LENGTH 0
27739 + * If you want to limit OCM use for text/data or completely disable it
27740 + * you can change these values.
27742 +#define OCM_TEXT_LENGTH OCM_FREE_LENGTH
27743 +#define OCM_DATA_LENGTH OCM_FREE_LENGTH
27745 +#define RAM_START KERNELSTART
27746 +#define RAM_LENGTH ((SDRAMSTART + CONFIG_MIN_RAMSIZE) - RAM_START)
27756 +#include <asm-generic/vmlinux.lds.h>
27758 +OUTPUT_ARCH(ubicom32)
27762 + ram : ORIGIN = RAM_START, LENGTH = RAM_LENGTH
27763 + syscall : ORIGIN = OS_SYSCALL_BEGIN, LENGTH = (OS_SYSCALL_END - OS_SYSCALL_BEGIN)
27764 + ocm : ORIGIN = OCM_FREE_START, LENGTH = OCM_FREE_LENGTH
27767 +jiffies = jiffies_64 + 4;
27770 + * Fixed locations required by gdb coredumps.
27772 + * Note that the names are what gdb is expecting so renaming will break
27775 +__ocm_begin = OCMSTART;
27776 +__ocm_limit = __ocm_begin + OCMSIZE;
27777 +__sdram_begin = SDRAMSTART;
27778 +__sdram_limit = __sdram_begin + CONFIG_MIN_RAMSIZE;
27779 +__filemedia_begin_addr = FLASHSTART;
27780 +__filemedia_end_addr = __filemedia_begin_addr + 0x00800000;
27783 + * For internal diagnostics
27785 +__os_syscall_begin = OS_SYSCALL_BEGIN;
27786 +__os_syscall_end = OS_SYSCALL_END;
27793 + *(.old_syscall_entry.text)
27794 + __fixed_text_end = .;
27796 + . = _begin + SIZEOF(.fixed_text) ;
27799 + * System call text in lower ocm (fixed location, can never change)
27801 + __syscall_text_load_begin = .;
27802 + __syscall_text_run_begin = OS_SYSCALL_BEGIN;
27804 + .syscall_text __syscall_text_run_begin : AT(__syscall_text_load_begin) {
27805 + *(.syscall_entry.text) /* Must be at OS_SYSCALL_BEGIN 0x3ffc0040 */
27806 + *(.kernel_unprotected)
27808 + __syscall_text_run_end = .;
27809 + } > syscall /* .syscall_text */
27810 + . = __syscall_text_load_begin + __syscall_text_run_end - __syscall_text_run_begin ;
27811 + __ocm_text_load_begin = .;
27812 + __ocm_text_run_begin = OCM_FREE_START ;
27813 + .ocm_text __ocm_text_run_begin : AT(__ocm_text_load_begin) {
27814 +#if OCM_TEXT_LENGTH
27817 + *(.spinlock.text)
27818 +#include <asm/ocm_text.lds.inc>
27821 + __ocm_text_run_end = .;
27822 + __data_begin = ALIGN(OCM_SECTOR_SIZE);
27823 + } > ocm /* .ocm_text */
27825 + .ocm_module_text __ocm_text_run_end (NOLOAD) : AT(__ocm_text_run_end) {
27826 + __ocm_inst_heap_begin = .;
27827 + /* Reserve the min requested */
27828 + . += (CONFIG_OCM_MODULES_RESERVATION) * 1024;
27829 +#ifdef CONFIG_OCM_MODULES_MAY_CONSUME_REMAINING_CODESPACE
27830 + /* Round up to OCM sector size (we cannot use it for data) */
27831 + . = ALIGN(OCM_SECTOR_SIZE);
27833 + __ocm_inst_heap_end = .;
27834 + /* update __data_begin */
27835 + __data_begin = ALIGN(OCM_SECTOR_SIZE);
27836 + } > ocm /* .ocm_module_text */
27838 + . = __ocm_text_load_begin + __ocm_text_run_end - __ocm_text_run_begin ;
27839 + __ocm_text_load_end = .;
27841 + __ocm_data_load_begin = .;
27842 + __ocm_data_run_begin = __data_begin ;
27843 +#if OCM_DATA_LENGTH
27844 + .ocm_data __ocm_data_run_begin : AT(__ocm_data_load_begin) {
27845 +#if defined(CONFIG_IRQSTACKS_USEOCM)
27846 + percpu_irq_stacks = .;
27847 + . += NR_CPUS * THREAD_SIZE;
27851 + __ocm_data_run_end = .;
27853 + . = __ocm_data_load_begin + __ocm_data_run_end - __ocm_data_run_begin ;
27855 + __ocm_data_run_end = __ocm_data_run_begin;
27857 + __ocm_data_load_end = .;
27859 + __ocm_free_begin = __ocm_data_run_end;
27860 + __ocm_free_end = OCM_FREE_START + OCM_FREE_LENGTH;
27862 + .text __ocm_data_load_end : AT(__ocm_data_load_end) {
27870 + *(.text.__libgcc_udivmodsi)
27871 + *(.text.__libgcc_divmodsi)
27872 + *(.text.__libgcc_muldi3)
27873 + *(.text.__libgcc_udivmoddi)
27874 + *(.text.__libgcc_divmoddi)
27876 +#if OCM_TEXT_LENGTH == 0
27879 + *(.spinlock.text)
27881 + . = ALIGN(16); /* Exception table */
27882 + __start___ex_table = .;
27884 + __stop___ex_table = .;
27886 + *(.rodata) *(.rodata.*)
27887 + *(__vermagic) /* Kernel version magic */
27888 + *(__markers_strings)
27890 + *(.rodata.str1.1)
27891 + *(__tracepoints_strings)
27894 + __start_pci_fixups_early = . ;
27895 + *(.pci_fixup_early)
27896 + __end_pci_fixups_early = . ;
27897 + __start_pci_fixups_header = . ;
27898 + *(.pci_fixup_header)
27899 + __end_pci_fixups_header = . ;
27900 + __start_pci_fixups_final = . ;
27901 + *(.pci_fixup_final)
27902 + __end_pci_fixups_final = . ;
27903 + __start_pci_fixups_enable = . ;
27904 + *(.pci_fixup_enable)
27905 + __end_pci_fixups_enable = . ;
27906 + __start_pci_fixups_resume = . ;
27907 + *(.pci_fixup_resume)
27908 + __end_pci_fixups_resume = . ;
27909 + __start_pci_fixups_resume_early = . ;
27910 + *(.pci_fixup_resume_early)
27911 + __end_pci_fixups_resume_early = . ;
27912 + __start_pci_fixups_suspend = . ;
27913 + *(.pci_fixup_suspend)
27914 + __end_pci_fixups_suspend = . ;
27916 + __start_builtin_fw = . ;
27918 + __end_builtin_fw = . ;
27921 + /* Kernel symbol table: Normal symbols */
27923 + __start___ksymtab = .;
27925 + __stop___ksymtab = .;
27927 + /* Kernel symbol table: GPL-only symbols */
27928 + __start___ksymtab_gpl = .;
27930 + __stop___ksymtab_gpl = .;
27932 + /* Kernel symbol table: Normal unused symbols */
27933 + __start___ksymtab_unused = .;
27934 + *(__ksymtab_unused)
27935 + __stop___ksymtab_unused = .;
27937 + /* Kernel symbol table: GPL-only unused symbols */
27938 + __start___ksymtab_unused_gpl = .;
27939 + *(__ksymtab_unused_gpl)
27940 + __stop___ksymtab_unused_gpl = .;
27942 + /* Kernel symbol table: GPL-future symbols */
27943 + __start___ksymtab_gpl_future = .;
27944 + *(__ksymtab_gpl_future)
27945 + __stop___ksymtab_gpl_future = .;
27947 + /* Kernel symbol table: Normal symbols */
27948 + __start___kcrctab = .;
27950 + __stop___kcrctab = .;
27952 + /* Kernel symbol table: GPL-only symbols */
27953 + __start___kcrctab_gpl = .;
27955 + __stop___kcrctab_gpl = .;
27957 + /* Kernel symbol table: GPL-future symbols */
27958 + __start___kcrctab_gpl_future = .;
27959 + *(__kcrctab_gpl_future)
27960 + __stop___kcrctab_gpl_future = .;
27962 + /* Kernel symbol table: strings */
27963 + *(__ksymtab_strings)
27965 + /* Built-in module parameters */
27967 + __start___param = .;
27969 + __stop___param = .;
27975 + .data DATA_ADDR : {
27979 +#if OCM_DATA_LENGTH == 0
27982 + . = ALIGN(8192) ;
27983 + _data_protection_end = .;
27984 + *(.data.init_task)
27991 + __init_begin = .;
27998 + __setup_start = .;
28001 + __initcall_start = .;
28003 + __initcall_end = .;
28004 + __con_initcall_start = .;
28005 + *(.con_initcall.init)
28006 + __con_initcall_end = .;
28007 + ___security_initcall_start = .;
28008 + *(.security_initcall.init)
28009 + ___security_initcall_end = .;
28010 +#ifdef CONFIG_BLK_DEV_INITRD
28012 + __initramfs_start = .;
28014 + __initramfs_end = .;
28017 + __per_cpu_start = .;
28019 + *(.data.percpu.shared_aligned)
28020 + __per_cpu_end = .;
28028 + PROVIDE (___eh_frame_begin = .);
28031 + PROVIDE (___eh_frame_end = .);
28037 + *(.exitcall.exit)
28053 diff -ruN linux-2.6.30.10/arch/ubicom32/lib/checksum.c linux-2.6.30.10-ubi/arch/ubicom32/lib/checksum.c
28054 --- linux-2.6.30.10/arch/ubicom32/lib/checksum.c 1970-01-01 02:00:00.000000000 +0200
28055 +++ linux-2.6.30.10-ubi/arch/ubicom32/lib/checksum.c 2009-12-11 11:45:11.000000000 +0200
28058 + * arch/ubicom32/lib/checksum.c
28059 + * Optimized checksum utilities for IP.
28061 + * (C) Copyright 2009, Ubicom, Inc.
28063 + * This file is part of the Ubicom32 Linux Kernel Port.
28065 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
28066 + * it and/or modify it under the terms of the GNU General Public License
28067 + * as published by the Free Software Foundation, either version 2 of the
28068 + * License, or (at your option) any later version.
28070 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
28071 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
28072 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
28073 + * the GNU General Public License for more details.
28075 + * You should have received a copy of the GNU General Public License
28076 + * along with the Ubicom32 Linux Kernel Port. If not,
28077 + * see <http://www.gnu.org/licenses/>.
28079 + * Ubicom32 implementation derived from (with many thanks):
28085 + * INET An implementation of the TCP/IP protocol suite for the LINUX
28086 + * operating system. INET is implemented using the BSD Socket
28087 + * interface as the means of communication with the user level.
28089 + * IP/TCP/UDP checksumming routines
28091 + * Authors: Jorge Cwik, <jorge@laser.satlink.net>
28092 + * Arnt Gulbrandsen, <agulbra@nvg.unit.no>
28093 + * Tom May, <ftom@netcom.com>
28094 + * Andreas Schwab, <schwab@issan.informatik.uni-dortmund.de>
28095 + * Lots of code moved from tcp.c and ip.c; see those files
28096 + * for more names.
28098 + * 03/02/96 Jes Sorensen, Andreas Schwab, Roman Hodek:
28099 + * Fixed some nasty bugs, causing some horrible crashes.
28100 + * A: At some points, the sum (%0) was used as
28101 + * length-counter instead of the length counter
28102 + * (%1). Thanks to Roman Hodek for pointing this out.
28103 + * B: GCC seems to mess up if one uses too many
28104 + * data-registers to hold input values and one tries to
28105 + * specify d0 and d1 as scratch registers. Letting gcc choose these
28106 + * registers itself solves the problem.
28108 + * This program is free software; you can redistribute it and/or
28109 + * modify it under the terms of the GNU General Public License
28110 + * as published by the Free Software Foundation; either version
28111 + * 2 of the License, or (at your option) any later version.
28114 +/* Revised by Kenneth Albanowski for m68knommu. Basic problem: unaligned access kills, so most
28115 + of the assembly has to go. */
28117 +#include <linux/module.h>
28118 +#include <net/checksum.h>
28120 +static unsigned long do_csum(const unsigned char * buff, int len)
28123 + unsigned long result = 0;
28126 + * The following optimized assembly code cannot handle data length less than 7 bytes!
28128 + if (likely(len >= 7)) {
28129 + len -= (4 - (int)buff) & 3;
28130 + count = len >> 2;
28132 + " sub.4 d15, #0, %2 \n\t" // set up for jump table
28133 + " and.4 d15, #(32-1), d15 \n\t" // d15 = (-m) & (32 - 1)
28135 + " bfextu d14, %0, #2 \n\t" // test 2 LSB of buff
28136 + " jmpne.w.f 100f \n\t"
28137 + " add.4 %1, #0, %1 \n\t" // clear C
28138 + " moveai a3, #%%hi(1f) \n\t" // table jump
28139 + " lea.1 a3, %%lo(1f)(a3) \n\t"
28140 + " lea.4 a3, (a3,d15) \n\t"
28141 + " calli a3, 0(a3) \n\t"
28143 + "100: sub.4 %0, %0, d14 \n\t"
28144 + " sub.4 d14, #4, d14 \n\t"
28145 + " lsl.4 d14, d14, #3 \n\t"
28146 + " add.4 %1, #0, %1 \n\t" // clear C
28147 + " moveai a3, #%%hi(1f) \n\t" // table jump
28148 + " lea.1 a3, %%lo(1f)(a3) \n\t"
28149 + " lea.4 a3, (a3,d15) \n\t"
28150 + " bfextu %1, (%0)4++, d14 \n\t" // read first partial word
28151 + " calli a3, 0(a3) \n\t"
28153 + "200: lsl.4 %3, %3, #3 \n\t"
28154 + " bfrvrs d15, (%0), #0 \n\t" // read last word (partial)
28155 + " bfextu d15, d15, %3 \n\t"
28156 + " bfrvrs d15, d15, #0 \n\t"
28157 + " add.4 %1, d15, %1 \n\t"
28158 + " addc %1, #0, %1 \n\t" // sample C again
28159 + " jmpt.w.t 2f \n\t"
28161 + "200: move.1 d15, 0(%0) \n\t"
28162 + " lsl.4 d15, d15, #8 \n\t"
28163 + " add.4 %1, d15, %1 \n\t"
28164 + " addc %1, #0, %1 \n\t" // sample C again
28165 + " add.4 %3, #-1, %3 \n\t"
28166 + " jmpeq.w.t 2f \n\t"
28168 + " move.1 d15, 1(%0) \n\t"
28169 + " add.4 %1, d15, %1 \n\t"
28170 + " addc %1, #0, %1 \n\t" // sample C again
28171 + " add.4 %3, #-1, %3 \n\t"
28172 + " jmpeq.w.t 2f \n\t"
28174 + " move.1 d15, 2(%0) \n\t"
28175 + " lsl.4 d15, d15, #8 \n\t"
28176 + " add.4 %1, d15, %1 \n\t"
28177 + " addc %1, #0, %1 \n\t" // sample C again
28178 + " jmpt.w.t 2f \n\t"
28180 +#if defined(IP7000) || defined(IP7000_REV2)
28181 + "300: swapb.2 %1, %1 \n\t"
28183 + "300: shmrg.2 %1, %1, %1 \n\t"
28184 + " lsr.4 %1, %1, #8 \n\t"
28185 + " bfextu %1, %1, #16 \n\t"
28187 + " jmpt.w.t 3f \n\t"
28189 + "1: add.4 %1, (%0)4++, %1 \n\t" // first add without C
28191 + " addc %1, (%0)4++, %1 \n\t"
28193 + " addc %1, #0, %1 \n\t" // sample C again
28194 + " add.4 %2, #-32, %2 \n\t"
28195 + " jmpgt.w.t 1b \n\t"
28197 + " and.4 %3, #3, %3 \n\t" // check n
28198 + " jmpne.w.f 200b \n\t"
28200 + "2: .rept 2 \n\t"
28201 + " lsr.4 d15, %1, #16 \n\t"
28202 + " bfextu %1, %1, #16 \n\t"
28203 + " add.4 %1, d15, %1 \n\t"
28205 + " btst d14, #3 \n\t" // start from odd address (<< 3)?
28206 + " jmpne.w.f 300b \n\t"
28209 + : "+a"(buff), "+d"(result), "+d"(count), "+d"(len)
28211 + : "d15", "d14", "a3", "cc"
28218 + * handle a few bytes and fold result into 16-bit
28220 + while (len-- > 0) {
28221 + result += (*buff++ << 8);
28223 + result += *buff++;
28229 + " lsr.4 d15, %0, #16 \n\t"
28230 + " bfextu %0, %0, #16 \n\t"
28231 + " add.4 %0, d15, %0 \n\t"
28242 + * This is a version of ip_compute_csum() optimized for IP headers,
28243 + * which always checksum on 4 octet boundaries.
28245 +__sum16 ip_fast_csum(const void *iph, unsigned int ihl)
28247 + return (__force __sum16)~do_csum(iph,ihl*4);
28251 + * computes the checksum of a memory block at buff, length len,
28252 + * and adds in "sum" (32-bit)
28254 + * returns a 32-bit number suitable for feeding into itself
28255 + * or csum_tcpudp_magic
28257 + * this function must be called with even lengths, except
28258 + * for the last fragment, which may be odd
28260 + * it's best to have buff aligned on a 32-bit boundary
28262 +__wsum csum_partial(const void *buff, int len, __wsum sum)
28264 + unsigned int result = do_csum(buff, len);
28266 + /* add in old sum, and carry.. */
28267 + result += (__force u32)sum;
28268 + if ((__force u32)sum > result)
28270 + return (__force __wsum)result;
28273 +EXPORT_SYMBOL(csum_partial);
28276 + * this routine is used for miscellaneous IP-like checksums, mainly
28279 +__sum16 ip_compute_csum(const void *buff, int len)
28281 + return (__force __sum16)~do_csum(buff,len);
28285 + * copy from fs while checksumming, otherwise like csum_partial
28289 +csum_partial_copy_from_user(const void __user *src, void *dst,
28290 + int len, __wsum sum, int *csum_err)
28292 + if (csum_err) *csum_err = 0;
28293 + memcpy(dst, (__force const void *)src, len);
28294 + return csum_partial(dst, len, sum);
28298 + * copy from ds while checksumming, otherwise like csum_partial
28302 +csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum)
28304 + memcpy(dst, src, len);
28305 + return csum_partial(dst, len, sum);
28307 diff -ruN linux-2.6.30.10/arch/ubicom32/lib/delay.c linux-2.6.30.10-ubi/arch/ubicom32/lib/delay.c
28308 --- linux-2.6.30.10/arch/ubicom32/lib/delay.c 1970-01-01 02:00:00.000000000 +0200
28309 +++ linux-2.6.30.10-ubi/arch/ubicom32/lib/delay.c 2009-12-11 11:45:11.000000000 +0200
28312 + * arch/ubicom32/lib/delay.c
28313 + * Ubicom32 implementation of udelay()
28315 + * (C) Copyright 2009, Ubicom, Inc.
28317 + * This file is part of the Ubicom32 Linux Kernel Port.
28319 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
28320 + * it and/or modify it under the terms of the GNU General Public License
28321 + * as published by the Free Software Foundation, either version 2 of the
28322 + * License, or (at your option) any later version.
28324 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
28325 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
28326 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
28327 + * the GNU General Public License for more details.
28329 + * You should have received a copy of the GNU General Public License
28330 + * along with the Ubicom32 Linux Kernel Port. If not,
28331 + * see <http://www.gnu.org/licenses/>.
28333 + * Ubicom32 implementation derived from (with many thanks):
28339 +#include <linux/module.h>
28340 +#include <asm/param.h>
28341 +#include <asm/delay.h>
28342 +#include <asm/ip5000.h>
28345 + * read_current_timer()
28346 + * Return the current value of sysval.
28348 +int __devinit read_current_timer(unsigned long *timer_val)
28350 + *timer_val = (long)(UBICOM32_IO_TIMER->sysval);
28355 +void udelay(unsigned long usecs)
28359 +EXPORT_SYMBOL(udelay);
28360 diff -ruN linux-2.6.30.10/arch/ubicom32/lib/Makefile linux-2.6.30.10-ubi/arch/ubicom32/lib/Makefile
28361 --- linux-2.6.30.10/arch/ubicom32/lib/Makefile 1970-01-01 02:00:00.000000000 +0200
28362 +++ linux-2.6.30.10-ubi/arch/ubicom32/lib/Makefile 2009-12-11 11:45:11.000000000 +0200
28365 +# arch/ubicom32/lib/Makefile
28366 +# <TODO: Replace with short file description>
28368 +# (C) Copyright 2009, Ubicom, Inc.
28370 +# This file is part of the Ubicom32 Linux Kernel Port.
28372 +# The Ubicom32 Linux Kernel Port is free software: you can redistribute
28373 +# it and/or modify it under the terms of the GNU General Public License
28374 +# as published by the Free Software Foundation, either version 2 of the
28375 +# License, or (at your option) any later version.
28377 +# The Ubicom32 Linux Kernel Port is distributed in the hope that it
28378 +# will be useful, but WITHOUT ANY WARRANTY; without even the implied
28379 +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
28380 +# the GNU General Public License for more details.
28382 +# You should have received a copy of the GNU General Public License
28383 +# along with the Ubicom32 Linux Kernel Port. If not,
28384 +# see <http://www.gnu.org/licenses/>.
28386 +# Ubicom32 implementation derived from (with many thanks):
28392 +# Makefile for m68knommu specific library files..
28395 +lib-y := checksum.o delay.o mem_ubicom32.o
28396 diff -ruN linux-2.6.30.10/arch/ubicom32/lib/mem_ubicom32.c linux-2.6.30.10-ubi/arch/ubicom32/lib/mem_ubicom32.c
28397 --- linux-2.6.30.10/arch/ubicom32/lib/mem_ubicom32.c 1970-01-01 02:00:00.000000000 +0200
28398 +++ linux-2.6.30.10-ubi/arch/ubicom32/lib/mem_ubicom32.c 2009-12-11 11:45:11.000000000 +0200
28401 + * arch/ubicom32/lib/mem_ubicom32.c
28402 + * String functions.
28404 + * (C) Copyright 2009, Ubicom, Inc.
28406 + * This file is part of the Ubicom32 Linux Kernel Port.
28408 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
28409 + * it and/or modify it under the terms of the GNU General Public License
28410 + * as published by the Free Software Foundation, either version 2 of the
28411 + * License, or (at your option) any later version.
28413 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
28414 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
28415 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
28416 + * the GNU General Public License for more details.
28418 + * You should have received a copy of the GNU General Public License
28419 + * along with the Ubicom32 Linux Kernel Port. If not,
28420 + * see <http://www.gnu.org/licenses/>.
28422 + * Ubicom32 implementation derived from (with many thanks):
28428 +#include <linux/module.h>
28429 +#include <linux/types.h>
28430 +#include <linux/compiler.h>
28432 +#define LIKELY likely
28433 +#define UNLIKELY unlikely
28435 +typedef u32_t addr_t;
28440 +void *memcpy(void *dest, const void *src, size_t n)
28442 + void *dest_ret = dest;
28444 + if (LIKELY((((addr_t)dest ^ (addr_t)src) & 3) == 0) && LIKELY(n > 6)) {
28446 + n -= (4 - (addr_t)dest) & 0x03;
28449 + " sub.4 d15, #0, %2 \n\t" // set up for jump table
28450 + " and.4 d15, #(32-1), d15 \n\t" // d15 = (-m) & (32 - 1)
28451 + " moveai a3, #%%hi(1f) \n\t"
28452 + " lea.1 a3, %%lo(1f)(a3) \n\t"
28453 + " lea.4 a3, (a3,d15) \n\t"
28455 + " bfextu d15, %0, #2 \n\t" // d15 = (dest & 3)
28456 + " jmpne.w.f 100f \n\t"
28457 + " calli a3, 0(a3) \n\t" // 4-byte alignment
28459 + "100: cmpi d15, #2 \n\t"
28460 + " jmpne.s.f 101f \n\t"
28461 + " move.2 (%0)2++, (%1)2++ \n\t"
28462 + " calli a3, 0(a3) \n\t" // 2-byte alignment
28464 + "101: move.1 (%0)1++, (%1)1++ \n\t"
28465 + " jmpgt.s.f 102f \n\t" // 3-byte alignment
28466 + " move.2 (%0)2++, (%1)2++ \n\t" // 1-byte alignment
28467 + "102: calli a3, 0(a3) \n\t"
28469 + "200: cmpi %3, #2 \n\t"
28470 + " jmplt.s.f 201f \n\t"
28471 + " move.2 (%0)2++, (%1)2++ \n\t"
28472 + " jmpeq.s.t 2f \n\t"
28473 + "201: move.1 (%0)1++, (%1)1++ \n\t"
28474 + " jmpt.w.t 2f \n\t"
28476 + "1: .rept 25 \n\t"
28477 + " movea (%0)4++, (%1)4++ \n\t"
28480 + " move.4 (%0)4++, (%1)4++ \n\t"
28482 + " add.4 %2, #-32, %2 \n\t"
28483 + " jmpgt.w.f 1b \n\t"
28485 + " and.4 %3, #3, %3 \n\t" // check n
28486 + " jmpne.w.f 200b \n\t"
28488 + : "+a" (dest), "+a" (src), "+d" (m), "+d" (n)
28490 + : "d15", "a3", "memory", "cc"
28496 + if (LIKELY((((addr_t)dest ^ (addr_t)src) & 1) == 0) && LIKELY(n > 2)) {
28498 + n -= (addr_t)dest & 0x01;
28501 + " sub.4 d15, #0, %2 \n\t" // set up for jump table
28502 + " and.4 d15, #(32-1), d15 \n\t" // d15 = (-m) & (32 - 1)
28503 + " moveai a3, #%%hi(1f) \n\t"
28504 + " lea.1 a3, %%lo(1f)(a3) \n\t"
28505 + " lea.4 a3, (a3,d15) \n\t"
28507 + " btst %0, #0 \n\t" // check bit 0
28508 + " jmpne.w.f 100f \n\t"
28509 + " calli a3, 0(a3) \n\t" // 4-byte alignment
28511 + "100: move.1 (%0)1++, (%1)1++ \n\t"
28512 + " calli a3, 0(a3) \n\t"
28514 + "200: move.1 (%0)1++, (%1)1++ \n\t"
28515 + " jmpt.w.t 2f \n\t"
28517 + "1: .rept 32 \n\t"
28518 + " move.2 (%0)2++, (%1)2++ \n\t"
28520 + " add.4 %2, #-32, %2 \n\t"
28521 + " jmpgt.w.f 1b \n\t"
28523 + " and.4 %3, #1, %3 \n\t" // check n
28524 + " jmpne.w.f 200b \n\t"
28527 + : "+a" (dest), "+a" (src), "+d" (m), "+d" (n)
28529 + : "d15", "a3", "memory", "cc"
28536 + " sub.4 d15, #0, %2 \n\t"
28537 + " jmpeq.w.f 2f \n\t"
28538 + " and.4 d15, #(16-1), d15 \n\t" // d15 = (-n) & (16 - 1)
28539 + " moveai a3, #%%hi(1f) \n\t"
28540 + " lea.1 a3, %%lo(1f)(a3) \n\t"
28541 + " lea.4 a3, (a3,d15) \n\t"
28542 + " calli a3, 0(a3) \n\t"
28544 + "1: .rept 16 \n\t"
28545 + " move.1 (%0)1++, (%1)1++ \n\t"
28547 + " add.4 %2, #-16, %2 \n\t"
28548 + " jmpgt.w.f 1b \n\t"
28551 + : "+a" (dest), "+a" (src), "+d" (n)
28553 + : "d15", "a3", "memory", "cc"
28562 +void *memset(void *s, int c, size_t n)
28566 + if (LIKELY(n > 6)) {
28568 + n -= (4 - (addr_t)s) & 0x03;
28571 + " sub.4 d15, #0, %2 \n\t" // set up for jump table
28572 + " and.4 d15, #(32-1), d15 \n\t" // d15 = (-m) & (32 - 1)
28573 + " shmrg.1 %1, %1, %1 \n\t"
28574 + " shmrg.2 %1, %1, %1 \n\t" // %1 = (c<<24)|(c<<16)|(c<<8)|c
28575 + " moveai a3, #%%hi(1f) \n\t"
28576 + " lea.1 a3, %%lo(1f)(a3) \n\t"
28577 + " lea.4 a3, (a3,d15) \n\t"
28579 + " bfextu d15, %0, #2 \n\t" // d15 = (s & 3)
28580 + " jmpne.w.f 100f \n\t"
28581 + " calli a3, 0(a3) \n\t" // 4-byte alignment
28583 + "100: cmpi d15, #2 \n\t"
28584 + " jmpne.s.f 101f \n\t"
28585 + " move.2 (%0)2++, %1 \n\t"
28586 + " calli a3, 0(a3) \n\t" // 2-byte alignment
28588 + "101: move.1 (%0)1++, %1 \n\t"
28589 + " jmpgt.s.f 102f \n\t" // 3-byte alignment
28590 + " move.2 (%0)2++, %1 \n\t" // 1-byte alignment
28591 + "102: calli a3, 0(a3) \n\t"
28593 + "200: cmpi %3, #2 \n\t"
28594 + " jmplt.s.f 201f \n\t"
28595 + " move.2 (%0)2++, %1 \n\t"
28596 + " jmpeq.s.t 2f \n\t"
28597 + "201: move.1 (%0)1++, %1 \n\t"
28598 + " jmpt.w.t 2f \n\t"
28600 + "1: .rept 25 \n\t"
28601 + " movea (%0)4++, %1 \n\t"
28604 + " move.4 (%0)4++, %1 \n\t"
28606 + " add.4 %2, #-32, %2 \n\t"
28607 + " jmpgt.w.f 1b \n\t"
28609 + " and.4 %3, #3, %3 \n\t" // test bit 1 of n
28610 + " jmpne.w.f 200b \n\t"
28613 + : "+a" (s), "+d" (c), "+d" (m), "+d" (n)
28615 + : "d15", "a3", "memory", "cc"
28622 + " sub.4 d15, #0, %2 \n\t"
28623 + " jmpeq.w.f 2f \n\t"
28624 + " and.4 d15, #(8-1), d15 \n\t" // d15 = (-%2) & (16 - 1)
28625 + " moveai a3, #%%hi(1f) \n\t"
28626 + " lea.1 a3, %%lo(1f)(a3) \n\t"
28627 + " lea.4 a3, (a3,d15) \n\t"
28628 + " calli a3, 0(a3) \n\t"
28630 + "1: .rept 8 \n\t"
28631 + " move.1 (%0)1++, %1 \n\t"
28635 + : "+a" (s), "+d" (c), "+d" (n)
28637 + : "d15", "a3", "memory", "cc"
28643 +void *memmove(void *dest, const void *src, size_t n)
28655 + * Will perform 16-bit move if possible
28657 + if (likely((((u32)dest | (u32)src | n) & 1) == 0)) {
28658 + if (dest <= src) {
28660 + " sub.4 d15, #0, %2 \n\t" // set up for jump table
28661 + " and.4 d15, #(32-2), d15 \n\t" // d15 = (- count) & (32 - 2)
28662 + " moveai a3, #%%hi(1f) \n\t"
28663 + " lea.1 a3, %%lo(1f)(a3) \n\t"
28664 + " lea.2 a3, (a3,d15) \n\t"
28665 + " calli a3, 0(a3) \n\t"
28667 + "1: .rept 16 \n\t"
28668 + " move.2 (%0)2++, (%1)2++ \n\t"
28670 + " add.4 %2, #-32, %2 \n\t"
28671 + " jmpgt.w.f 1b \n\t"
28673 + : "+a" (tmp), "+a" (s), "+d" (n)
28675 + : "d15", "a3", "memory", "cc"
28681 + " sub.4 d15, #0, %2 \n\t" // set up for jump table
28682 + " and.4 d15, #(32-2), d15 \n\t" // d15 = (- count) & (32 - 2)
28683 + " moveai a3, #%%hi(1f) \n\t"
28684 + " lea.1 a3, %%lo(1f)(a3) \n\t"
28685 + " lea.2 a3, (a3,d15) \n\t"
28686 + " calli a3, 0(a3) \n\t"
28688 + "1: .rept 16 \n\t"
28689 + " move.2 -2(%0)++, -2(%1)++ \n\t"
28691 + " add.4 %2, #-32, %2 \n\t"
28692 + " jmpgt.w.f 1b \n\t"
28694 + : "+a" (tmp), "+a" (s), "+d" (n)
28696 + : "d15", "a3", "memory", "cc"
28702 + if (dest <= src) {
28704 + " sub.4 d15, #0, %2 \n\t" // set up for jump table
28705 + " and.4 d15, #(16-1), d15 \n\t" // d15 = (- count) & (16 - 1)
28706 + " moveai a3, #%%hi(1f) \n\t"
28707 + " lea.1 a3, %%lo(1f)(a3) \n\t"
28708 + " lea.4 a3, (a3,d15) \n\t"
28709 + " calli a3, 0(a3) \n\t"
28711 + "1: .rept 16 \n\t"
28712 + " move.1 (%0)1++, (%1)1++ \n\t"
28714 + " add.4 %2, #-16, %2 \n\t"
28715 + " jmpgt.w.f 1b \n\t"
28716 + : "+a" (tmp), "+a" (s), "+d" (n)
28718 + : "d15", "a3", "memory", "cc"
28724 + " sub.4 d15, #0, %2 \n\t" // set up for jump table
28725 + " and.4 d15, #(16-1), d15 \n\t" // d15 = (- count) & (16 - 1)
28726 + " moveai a3, #%%hi(1f) \n\t"
28727 + " lea.1 a3, %%lo(1f)(a3) \n\t"
28728 + " lea.4 a3, (a3,d15) \n\t"
28729 + " calli a3, 0(a3) \n\t"
28731 + "1: .rept 16 \n\t"
28732 + " move.1 -1(%0)++, -1(%1)++ \n\t"
28734 + " add.4 %2, #-16, %2 \n\t"
28735 + " jmpgt.w.f 1b \n\t"
28736 + : "+a" (tmp), "+a" (s), "+d" (n)
28738 + : "d15", "a3", "memory", "cc"
28743 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/audio.c linux-2.6.30.10-ubi/arch/ubicom32/mach-common/audio.c
28744 --- linux-2.6.30.10/arch/ubicom32/mach-common/audio.c 1970-01-01 02:00:00.000000000 +0200
28745 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/audio.c 2009-12-11 11:45:11.000000000 +0200
28748 + * arch/ubicom32/mach-common/audio.c
28749 + * Generic initialization for Ubicom32 Audio
28751 + * (C) Copyright 2009, Ubicom, Inc.
28753 + * This file is part of the Ubicom32 Linux Kernel Port.
28755 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
28756 + * it and/or modify it under the terms of the GNU General Public License
28757 + * as published by the Free Software Foundation, either version 2 of the
28758 + * License, or (at your option) any later version.
28760 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
28761 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
28762 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
28763 + * the GNU General Public License for more details.
28765 + * You should have received a copy of the GNU General Public License
28766 + * along with the Ubicom32 Linux Kernel Port. If not,
28767 + * see <http://www.gnu.org/licenses/>.
28770 +#include <linux/platform_device.h>
28771 +#include <linux/types.h>
28773 +#include <asm/devtree.h>
28774 +#include <asm/audio.h>
28775 +#include <asm/ubi32-pcm.h>
28778 + * The number of audio devices currently allocated, used for .id
28780 +static int __initdata audio_device_count;
28783 + * The maximum number of resources (cards) that the audio will have.
28784 + * Currently 3, a register space, and up to 2 interrupts.
28786 +#define AUDIO_MAX_RESOURCES 3
28789 + * audio_device_alloc
28790 + * Checks the device tree and allocates a platform_device if found
28792 +struct platform_device * __init audio_device_alloc(const char *driver_name,
28793 + const char *node_name, const char *inst_name, int priv_bytes)
28795 + struct platform_device *pdev;
28796 + struct resource *res;
28797 + struct audio_node *audio_node;
28798 + struct ubi32pcm_platform_data *pdata;
28799 + struct audio_dev_regs *adr;
28803 + * Check the device tree for the audio node
28805 + audio_node = (struct audio_node *)devtree_find_node(node_name);
28806 + if (!audio_node) {
28807 + printk(KERN_WARNING "audio device '%s' not found\n", node_name);
28811 + if (audio_node->version != AUDIONODE_VERSION) {
28812 + printk(KERN_WARNING "audio node not compatible\n");
28817 + * Find the instance in this node
28819 + adr = audio_node->regs->adr;
28820 + for (idx = 0; idx < audio_node->regs->max_devs; idx++) {
28821 + if ((adr->version == AUDIO_DEV_REGS_VERSION) &&
28822 + (strcmp(adr->name, inst_name) == 0)) {
28827 + if (idx == audio_node->regs->max_devs) {
28828 + printk(KERN_WARNING "audio inst '%s' not found in device '%s'\n", inst_name, node_name);
28833 + * Dynamically create the platform_device structure and resources
28835 + pdev = kzalloc(sizeof(struct platform_device) +
28836 + sizeof(struct ubi32pcm_platform_data) +
28837 + priv_bytes , GFP_KERNEL);
28839 + printk(KERN_WARNING "audio could not alloc pdev\n");
28843 + res = kzalloc(sizeof(struct resource) * AUDIO_MAX_RESOURCES,
28847 + printk(KERN_WARNING "audio could not alloc res\n");
28851 + pdev->name = driver_name;
28852 + pdev->id = audio_device_count++;
28853 + pdev->resource = res;
28856 + * Fill in the resources and platform data from devtree information
28858 + res[0].start = (u32_t)(audio_node->regs);
28859 + res[0].end = (u32_t)(audio_node->regs);
28860 + res[0].flags = IORESOURCE_MEM;
28861 + res[1 + AUDIO_TX_IRQ_RESOURCE].start = audio_node->dn.sendirq;
28862 + res[1 + AUDIO_TX_IRQ_RESOURCE].flags = IORESOURCE_IRQ;
28863 + res[1 + AUDIO_RX_IRQ_RESOURCE].start = audio_node->dn.recvirq;
28864 + res[1 + AUDIO_RX_IRQ_RESOURCE].flags = IORESOURCE_IRQ;
28865 + pdev->num_resources = 3;
28867 + printk(KERN_INFO "Audio.%d '%s':'%s' found irq=%d/%d.%d regs=%p pdev=%p/%p\n",
28868 + pdev->id, node_name, inst_name, audio_node->dn.sendirq,
28869 + audio_node->dn.recvirq, idx, audio_node->regs, pdev, res);
28870 + pdata = (struct ubi32pcm_platform_data *)(pdev + 1);
28871 + pdev->dev.platform_data = pdata;
28872 + pdata->node_name = node_name;
28873 + pdata->inst_name = inst_name;
28874 + pdata->inst_num = idx;
28875 + if (priv_bytes) {
28876 + pdata->priv_data = pdata + 1;
28881 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/board.c linux-2.6.30.10-ubi/arch/ubicom32/mach-common/board.c
28882 --- linux-2.6.30.10/arch/ubicom32/mach-common/board.c 1970-01-01 02:00:00.000000000 +0200
28883 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/board.c 2009-12-11 11:45:11.000000000 +0200
28886 + * arch/ubicom32/mach-common/board.c
28887 + * Board init and support code.
28889 + * (C) Copyright 2009, Ubicom, Inc.
28891 + * This file is part of the Ubicom32 Linux Kernel Port.
28893 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
28894 + * it and/or modify it under the terms of the GNU General Public License
28895 + * as published by the Free Software Foundation, either version 2 of the
28896 + * License, or (at your option) any later version.
28898 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
28899 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
28900 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
28901 + * the GNU General Public License for more details.
28903 + * You should have received a copy of the GNU General Public License
28904 + * along with the Ubicom32 Linux Kernel Port. If not,
28905 + * see <http://www.gnu.org/licenses/>.
28907 + * Ubicom32 implementation derived from (with many thanks):
28912 +#include <linux/module.h>
28913 +#include <linux/types.h>
28914 +#include <linux/cpu.h>
28915 +#include <asm/devtree.h>
28917 +struct boardnode {
28918 + struct devtree_node dn;
28919 + const char *revision;
28922 +static const struct boardnode *bn;
28925 + * board_get_revision()
28926 + * Returns revision string of the board.
28928 +const char *board_get_revision(void)
28934 + return bn->revision;
28940 +void __init board_init(void)
28942 + bn = (struct boardnode *)devtree_find_node("board");
28944 + printk(KERN_WARNING "board node not found\n");
28948 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/bootargs.c linux-2.6.30.10-ubi/arch/ubicom32/mach-common/bootargs.c
28949 --- linux-2.6.30.10/arch/ubicom32/mach-common/bootargs.c 1970-01-01 02:00:00.000000000 +0200
28950 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/bootargs.c 2009-12-11 11:45:11.000000000 +0200
28953 + * arch/ubicom32/mach-common/bootargs.c
28954 + * Board init and support code.
28956 + * (C) Copyright 2009, Ubicom, Inc.
28958 + * This file is part of the Ubicom32 Linux Kernel Port.
28960 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
28961 + * it and/or modify it under the terms of the GNU General Public License
28962 + * as published by the Free Software Foundation, either version 2 of the
28963 + * License, or (at your option) any later version.
28965 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
28966 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
28967 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
28968 + * the GNU General Public License for more details.
28970 + * You should have received a copy of the GNU General Public License
28971 + * along with the Ubicom32 Linux Kernel Port. If not,
28972 + * see <http://www.gnu.org/licenses/>.
28974 + * Ubicom32 implementation derived from (with many thanks):
28979 +#include <linux/module.h>
28980 +#include <linux/types.h>
28981 +#include <linux/cpu.h>
28982 +#include <asm/devtree.h>
28984 +struct bootargsnode {
28985 + struct devtree_node dn;
28986 + const char cmdline[512];
28989 +static const struct bootargsnode *ban;
28992 + * bootargs_get_cmdline()
28993 + * Returns kernel boot arguments set by the bootloader.
28995 +const char *bootargs_get_cmdline(void)
29001 + return ban->cmdline;
29007 +void __init bootargs_init(void)
29009 + ban = (struct bootargsnode *)devtree_find_node("bootargs");
29011 + printk(KERN_WARNING "bootargs node not found\n");
29015 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/cachectl.c linux-2.6.30.10-ubi/arch/ubicom32/mach-common/cachectl.c
29016 --- linux-2.6.30.10/arch/ubicom32/mach-common/cachectl.c 1970-01-01 02:00:00.000000000 +0200
29017 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/cachectl.c 2009-12-11 11:45:11.000000000 +0200
29020 + * arch/ubicom32/mach-common/cachectl.c
29021 + * Architecture cache control support
29023 + * (C) Copyright 2009, Ubicom, Inc.
29025 + * This file is part of the Ubicom32 Linux Kernel Port.
29027 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
29028 + * it and/or modify it under the terms of the GNU General Public License
29029 + * as published by the Free Software Foundation, either version 2 of the
29030 + * License, or (at your option) any later version.
29032 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
29033 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
29034 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
29035 + * the GNU General Public License for more details.
29037 + * You should have received a copy of the GNU General Public License
29038 + * along with the Ubicom32 Linux Kernel Port. If not,
29039 + * see <http://www.gnu.org/licenses/>.
29041 + * Ubicom32 implementation derived from (with many thanks):
29047 +#include <linux/types.h>
29048 +#include <linux/module.h>
29049 +#include <asm/cachectl.h>
29052 + * The write queue flush procedure in mem_cache_control needs to make
29053 + * DCACHE_WRITE_QUEUE_LENGTH writes to DDR (not OCM). Here we reserve some
29054 + * memory for this operation.
29055 + * Allocate array of cache lines of least DCACHE_WRITE_QUEUE_LENGTH + 1 words in
29056 + * length rounded up to the nearest cache line.
29058 +#define CACHE_WRITE_QUEUE_FLUSH_AREA_SIZE \
29059 + ALIGN(sizeof(int) * (DCACHE_WRITE_QUEUE_LENGTH + 1), CACHE_LINE_SIZE)
29061 +static char cache_write_queue_flush_area[CACHE_WRITE_QUEUE_FLUSH_AREA_SIZE]
29062 + __attribute__((aligned(CACHE_LINE_SIZE)));
29065 + * ONE_CCR_ADDR_OP is a helper macro that executes a single CCR operation.
29067 +#define ONE_CCR_ADDR_OP(cc, op_addr, op) \
29070 + " btst "D(CCR_CTRL)"(%0), #"D(CCR_CTRL_VALID)" \n\t" \
29071 + " jmpne.f .-4 \n\t" \
29072 + " move.4 "D(CCR_ADDR)"(%0), %1 \n\t" \
29073 + " move.1 "D(CCR_CTRL+3)"(%0), %2 \n\t" \
29074 + " bset "D(CCR_CTRL)"(%0), "D(CCR_CTRL)"(%0), #"D(CCR_CTRL_VALID)" \n\t" \
29075 + " cycles 2 \n\t" \
29076 + " btst "D(CCR_CTRL)"(%0), #"D(CCR_CTRL_DONE)" \n\t" \
29077 + " jmpeq.f .-4 \n\t" \
29079 + : "a"(cc), "r"(op_addr), "r"(op & 0xff) \
29085 + * mem_cache_control()
29086 + * Special cache control operation
29088 +void mem_cache_control(unsigned long cc, unsigned long begin_addr,
29089 + unsigned long end_addr, unsigned long op)
29091 + unsigned long op_addr;
29092 + int dccr = cc == DCCR_BASE;
29093 + if (dccr && op == CCR_CTRL_FLUSH_ADDR) {
29095 + * We ensure all previous writes have left the data cache write
29096 + * queue by sending DCACHE_WRITE_QUEUE_LENGTH writes (to
29097 + * different words) down the queue. If this is not done it's
29098 + * possible that the data we are trying to flush hasn't even
29099 + * entered the data cache.
29100 + * The +1 ensure that the final 'flush' is actually a flush.
29102 + int *flush_area = (int *)cache_write_queue_flush_area;
29104 + " .rept "D(DCACHE_WRITE_QUEUE_LENGTH + 1)" \n\t"
29105 + " move.4 (%0)4++, d0 \n\t"
29107 + : "+a"(flush_area)
29112 + UBICOM32_LOCK(DCCR_LOCK_BIT);
29114 + UBICOM32_LOCK(ICCR_LOCK_BIT);
29117 + * Calculate the cache lines we need to operate on that include
29118 + * begin_addr though end_addr.
29120 + begin_addr = begin_addr & ~(CACHE_LINE_SIZE - 1);
29121 + end_addr = (end_addr + CACHE_LINE_SIZE - 1) & ~(CACHE_LINE_SIZE - 1);
29122 + op_addr = begin_addr;
29125 + ONE_CCR_ADDR_OP(cc, op_addr, op);
29126 + op_addr += CACHE_LINE_SIZE;
29127 + } while (likely(op_addr < end_addr));
29129 + if (dccr && op == CCR_CTRL_FLUSH_ADDR) {
29131 + * It turns out that when flushing the data cache the last flush
29132 + * isn't actually complete at this point. This is because there
29133 + * is another write buffer on the DDR side of the cache that is
29134 + * arbitrated with the I-Cache.
29136 + * The only foolproof method that ensures that the last data
29137 + * cache flush *actually* completed is to do another flush on a
29138 + * dirty cache line. This flush will block until the DDR write
29139 + * buffer is empty.
29141 + * Rather than creating a another dirty cache line, we use the
29142 + * flush_area above as we know that it is dirty from previous
29145 + ONE_CCR_ADDR_OP(cc, cache_write_queue_flush_area, op);
29149 + UBICOM32_UNLOCK(DCCR_LOCK_BIT);
29151 + UBICOM32_UNLOCK(ICCR_LOCK_BIT);
29154 +EXPORT_SYMBOL(mem_cache_control);
29155 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/common.c linux-2.6.30.10-ubi/arch/ubicom32/mach-common/common.c
29156 --- linux-2.6.30.10/arch/ubicom32/mach-common/common.c 1970-01-01 02:00:00.000000000 +0200
29157 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/common.c 2009-12-11 11:45:11.000000000 +0200
29160 + * arch/ubicom32/mach-common/common.c
29161 + * Common platform support.
29163 + * (C) Copyright 2009, Ubicom, Inc.
29165 + * This file is part of the Ubicom32 Linux Kernel Port.
29167 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
29168 + * it and/or modify it under the terms of the GNU General Public License
29169 + * as published by the Free Software Foundation, either version 2 of the
29170 + * License, or (at your option) any later version.
29172 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
29173 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
29174 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
29175 + * the GNU General Public License for more details.
29177 + * You should have received a copy of the GNU General Public License
29178 + * along with the Ubicom32 Linux Kernel Port. If not,
29179 + * see <http://www.gnu.org/licenses/>.
29181 + * Ubicom32 implementation derived from (with many thanks):
29186 +#include <linux/version.h>
29187 +#include <linux/kernel.h>
29188 +#include <linux/init.h>
29189 +#include <linux/module.h>
29190 +#include <linux/list.h>
29191 +#include <linux/errno.h>
29192 +#include <linux/err.h>
29193 +#include <linux/string.h>
29194 +#include <linux/clk.h>
29195 +#include <linux/mutex.h>
29196 +#include <linux/platform_device.h>
29199 +/* Minimum CLK support */
29201 +struct clk *clk_get(struct device *dev, const char *id)
29203 + return ERR_PTR(-ENOENT);
29205 +EXPORT_SYMBOL(clk_get);
29207 +void clk_put(struct clk *clk)
29210 +EXPORT_SYMBOL(clk_put);
29212 +int clk_enable(struct clk *clk)
29216 +EXPORT_SYMBOL(clk_enable);
29219 +void clk_disable(struct clk *clk)
29222 +EXPORT_SYMBOL(clk_disable);
29223 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/io.c linux-2.6.30.10-ubi/arch/ubicom32/mach-common/io.c
29224 --- linux-2.6.30.10/arch/ubicom32/mach-common/io.c 1970-01-01 02:00:00.000000000 +0200
29225 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/io.c 2009-12-11 11:45:11.000000000 +0200
29228 + * arch/ubicom32/mach-common/io.c
29229 + * PCI I/O memory read/write support functions.
29231 + * (C) Copyright 2009, Ubicom, Inc.
29233 + * This file is part of the Ubicom32 Linux Kernel Port.
29235 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
29236 + * it and/or modify it under the terms of the GNU General Public License
29237 + * as published by the Free Software Foundation, either version 2 of the
29238 + * License, or (at your option) any later version.
29240 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
29241 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
29242 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
29243 + * the GNU General Public License for more details.
29245 + * You should have received a copy of the GNU General Public License
29246 + * along with the Ubicom32 Linux Kernel Port. If not,
29247 + * see <http://www.gnu.org/licenses/>.
29249 + * Ubicom32 implementation derived from (with many thanks):
29254 +#include <linux/module.h>
29255 +#include <linux/kernel.h>
29256 +#include <linux/io.h>
29259 +unsigned char ioread8(void __iomem *addr)
29261 + if (IS_PCI_ADDRESS(addr))
29262 + return ubi32_pci_read_u8(addr);
29264 + return (unsigned char)(*(volatile unsigned char *)addr);
29266 +EXPORT_SYMBOL(ioread8);
29268 +unsigned short ioread16(void __iomem *addr)
29270 + if (IS_PCI_ADDRESS(addr))
29271 + return ubi32_pci_read_u16(addr);
29273 + return (unsigned short)(*(volatile unsigned short *)addr);
29275 +EXPORT_SYMBOL(ioread16);
29277 +unsigned int ioread32(void __iomem *addr)
29279 + if (IS_PCI_ADDRESS(addr))
29280 + return ubi32_pci_read_u32(addr);
29282 + return (unsigned int)(*(volatile unsigned int *)addr);
29284 +EXPORT_SYMBOL(ioread32);
29286 +void iowrite32(unsigned int val, void __iomem *addr)
29288 + if (IS_PCI_ADDRESS(addr))
29289 + ubi32_pci_write_u32(val, addr);
29291 + *(volatile unsigned int *)addr = val;
29293 +EXPORT_SYMBOL(iowrite32);
29295 +void iowrite16(unsigned short val, void __iomem *addr)
29297 + if (IS_PCI_ADDRESS(addr))
29298 + ubi32_pci_write_u16(val, addr);
29300 + *(volatile unsigned short *)addr = val;
29302 +EXPORT_SYMBOL(iowrite16);
29304 +void iowrite8(unsigned char val, void __iomem *addr)
29306 + if (IS_PCI_ADDRESS(addr))
29307 + ubi32_pci_write_u8(val, addr);
29309 + *(volatile unsigned char *)addr = val;
29311 +EXPORT_SYMBOL(iowrite8);
29313 +void memcpy_fromio(void *to, const volatile void __iomem *from, unsigned len)
29315 + if (IS_PCI_ADDRESS(from)) {
29316 + if ((((u32_t)from & 0x3) == 0) && (((u32_t)to & 0x3) == 0)) {
29317 + while ((int)len >= 4) {
29318 + *(u32_t *)to = ubi32_pci_read_u32(from);
29323 + } else if ((((u32_t)from & 0x1) == 0) &&
29324 + (((u32_t)to & 0x1) == 0)) {
29325 + while ((int)len >= 2) {
29326 + *(u16_t *)to = ubi32_pci_read_u16(from);
29334 + *(u8_t *)to = ubi32_pci_read_u8(from);
29340 + memcpy(to, (void *)from, len);
29342 +EXPORT_SYMBOL(memcpy_fromio);
29344 +void memcpy_toio(volatile void __iomem *to, const void *from, unsigned len)
29346 + if (IS_PCI_ADDRESS(to)) {
29347 + if ((((u32_t)from & 0x3) == 0) && (((u32_t)to & 0x3) == 0)) {
29348 + while ((int)len >= 4) {
29349 + ubi32_pci_write_u32(*(u32_t *)from, to);
29354 + } else if ((((u32_t)from & 0x1) == 0) &&
29355 + (((u32_t)to & 0x1) == 0)) {
29356 + while ((int)len >= 2) {
29357 + ubi32_pci_write_u16(*(u16_t *)from, to);
29365 + ubi32_pci_write_u8(*(u8_t *)from, to);
29371 + memcpy((void *)to, from, len);
29374 +EXPORT_SYMBOL(memcpy_toio);
29376 +void memset_io(volatile void __iomem *addr, int val, size_t len)
29378 + if (IS_PCI_ADDRESS(addr)) {
29380 + ubi32_pci_write_u8((unsigned char)val, addr);
29385 + memset((void *)addr, val, len);
29388 +EXPORT_SYMBOL(memset_io);
29390 +void ioread8_rep(void __iomem *port, void *buf, unsigned long count)
29392 + if (IS_PCI_ADDRESS(port)) {
29394 + *(u8_t *)buf = ioread8(port);
29399 + insb((unsigned int)port, buf, count);
29403 +EXPORT_SYMBOL(ioread8_rep);
29405 +void ioread16_rep(void __iomem *port, void *buf, unsigned long count)
29407 + if (IS_PCI_ADDRESS(port)) {
29409 + *(u16_t *)buf = ioread16(port);
29414 + insw((unsigned int)port, buf, count);
29417 +EXPORT_SYMBOL(ioread16_rep);
29419 +void ioread32_rep(void __iomem *port, void *buf, unsigned long count)
29421 + if (IS_PCI_ADDRESS(port)) {
29423 + *(u32_t *)buf = ioread32(port);
29428 + insl((unsigned int)port, buf, count);
29431 +EXPORT_SYMBOL(ioread32_rep);
29433 +void iowrite8_rep(void __iomem *port, const void *buf, unsigned long count)
29435 + if (IS_PCI_ADDRESS(port)) {
29437 + iowrite8(*(u8_t *)buf, port);
29442 + outsb((unsigned int)port, buf, count);
29446 +EXPORT_SYMBOL(iowrite8_rep);
29448 +void iowrite16_rep(void __iomem *port, const void *buf, unsigned long count)
29450 + if (IS_PCI_ADDRESS(port)) {
29452 + iowrite16(*(u16_t *)buf, port);
29457 + outsw((unsigned int)port, buf, count);
29460 +EXPORT_SYMBOL(iowrite16_rep);
29462 +void iowrite32_rep(void __iomem *port, const void *buf, unsigned long count)
29464 + if (IS_PCI_ADDRESS(port)) {
29466 + iowrite32(*(u32_t *)buf, port);
29471 + outsl((unsigned int)port, buf, count);
29474 +EXPORT_SYMBOL(iowrite32_rep);
29476 +#endif /* CONFIG_PCI */
29477 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/Kconfig.switch linux-2.6.30.10-ubi/arch/ubicom32/mach-common/Kconfig.switch
29478 --- linux-2.6.30.10/arch/ubicom32/mach-common/Kconfig.switch 1970-01-01 02:00:00.000000000 +0200
29479 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/Kconfig.switch 2009-12-11 11:45:11.000000000 +0200
29481 +menuconfig UBICOM_SWITCH
29482 + tristate "Switch devices"
29484 + This option provides Ethernet switch management options via proc fs
29487 +config UBICOM_SWITCH_BCM539X
29488 + tristate "Broadcom BCM539X series (SPI)"
29489 + depends on SPI_MASTER
29491 + Supports Broadcom BCM539X Gigabit Ethernet Switches over SPI
29493 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/Makefile linux-2.6.30.10-ubi/arch/ubicom32/mach-common/Makefile
29494 --- linux-2.6.30.10/arch/ubicom32/mach-common/Makefile 1970-01-01 02:00:00.000000000 +0200
29495 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/Makefile 2009-12-11 11:45:11.000000000 +0200
29498 +# arch/ubicom32/mach-common/Makefile
29499 +# Makefile for Ubicom32 generic drivers/code.
29501 +# (C) Copyright 2009, Ubicom, Inc.
29503 +# This file is part of the Ubicom32 Linux Kernel Port.
29505 +# The Ubicom32 Linux Kernel Port is free software: you can redistribute
29506 +# it and/or modify it under the terms of the GNU General Public License
29507 +# as published by the Free Software Foundation, either version 2 of the
29508 +# License, or (at your option) any later version.
29510 +# The Ubicom32 Linux Kernel Port is distributed in the hope that it
29511 +# will be useful, but WITHOUT ANY WARRANTY; without even the implied
29512 +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
29513 +# the GNU General Public License for more details.
29515 +# You should have received a copy of the GNU General Public License
29516 +# along with the Ubicom32 Linux Kernel Port. If not,
29517 +# see <http://www.gnu.org/licenses/>.
29519 +# Ubicom32 implementation derived from (with many thanks):
29525 +obj-y += cachectl.o common.o usb_tio.o usb.o ubi32-gpio.o board.o bootargs.o profile.o
29526 +obj-$(CONFIG_PCI) += pci.o io.o
29528 +obj-$(CONFIG_FB_UBICOM32) += vdc_tio.o
29529 +obj-$(CONFIG_UBICOM_HID) += ubicom32hid.o
29530 +obj-$(CONFIG_UBICOM_INPUT) += ubicom32input.o
29531 +obj-$(CONFIG_UBICOM_INPUT_I2C) += ubicom32input_i2c.o
29532 +obj-$(CONFIG_UBICOM_SWITCH) += switch-core.o
29533 +obj-$(CONFIG_UBICOM_SWITCH_BCM539X) += switch-bcm539x.o
29534 +obj-$(CONFIG_UIO_UBICOM32RING) += ring_tio.o
29535 +obj-$(CONFIG_SND_UBI32) += audio.o
29536 +obj-$(CONFIG_UBICOM32_PLIO) += plio.o
29538 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/pci.c linux-2.6.30.10-ubi/arch/ubicom32/mach-common/pci.c
29539 --- linux-2.6.30.10/arch/ubicom32/mach-common/pci.c 1970-01-01 02:00:00.000000000 +0200
29540 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/pci.c 2009-12-11 11:45:11.000000000 +0200
29543 + * arch/ubicom32/mach-common/pci.c
29544 + * PCI interface management.
29546 + * (C) Copyright 2009, Ubicom, Inc.
29548 + * This file is part of the Ubicom32 Linux Kernel Port.
29550 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
29551 + * it and/or modify it under the terms of the GNU General Public License
29552 + * as published by the Free Software Foundation, either version 2 of the
29553 + * License, or (at your option) any later version.
29555 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
29556 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
29557 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
29558 + * the GNU General Public License for more details.
29560 + * You should have received a copy of the GNU General Public License
29561 + * along with the Ubicom32 Linux Kernel Port. If not,
29562 + * see <http://www.gnu.org/licenses/>.
29564 + * Ubicom32 implementation derived from (with many thanks):
29570 +#include <linux/module.h>
29571 +#include <linux/kernel.h>
29572 +#include <linux/pci.h>
29573 +#include <linux/slab.h>
29574 +#include <linux/init.h>
29575 +#include <linux/io.h>
29576 +#include <linux/seq_file.h>
29577 +#include <linux/proc_fs.h>
29579 +#include <asm/devtree.h>
29580 +#include <asm/ip5000.h>
29581 +#include <asm/ubicom32-common.h>
29583 +static int debug_pci = 1 ;
29585 +/* #define PCI_USE_INTERNAL_LOCK 1 */
29587 +#ifdef PCI_USE_INTERNAL_LOCK
29588 +#define PCI_LOCK(lock, irqflag) pci_lock_acquire(irqflag)
29589 +#define PCI_UNLOCK(lock, irqflag) pci_lock_release(irqflag)
29590 +#elif defined(CONFIG_SMP)
29591 +static DEFINE_SPINLOCK(pci_master_lock);
29592 +#define PCI_LOCK(lock, irqflag) spin_lock_irqsave(lock, irqflag)
29593 +#define PCI_UNLOCK(lock, irqflag) spin_unlock_irqrestore(lock, irqflag)
29595 +#define PCI_LOCK(lock, irqflag) local_irq_save(irqflag)
29596 +#define PCI_UNLOCK(lock, irqflag) local_irq_restore(irqflag)
29599 +#define PCI_DEV0_IDSEL CONFIG_PCI_DEV0_IDSEL
29600 +#define PCI_DEV1_IDSEL CONFIG_PCI_DEV1_IDSEL
29605 +#define PCI_CMD_INT_ACK 0x00 /* not supported */
29606 +#define PCI_CMD_SPECIAL 0x01 /* not supported */
29607 +#define PCI_CMD_IO_READ 0x02
29608 +#define PCI_CMD_IO_WRITE 0x03
29609 +#define PCI_CMD_MEM_READ 0x06
29610 +#define PCI_CMD_MEM_WRITE 0x07
29611 +#define PCI_CMD_CFG_READ 0x0a
29612 +#define PCI_CMD_CFG_WRITE 0x0b
29613 +#define PCI_CMD_MEM_READ_MULT 0x0c /* not supported */
29614 +#define PCI_CMD_DUAL_ADDR 0x0d /* not supported */
29615 +#define PCI_CMD_MEM_READ_LINE 0x0e /* not supported */
29616 +#define PCI_CMD_MEM_WRITE_INVAL 0x0f /* not supported */
29618 + * Status codes, returned by pci_read_u32() and pci_write_u32()
29620 +#define PCI_RESP_IN_PROGRESS 0xff /* request still in queue */
29621 +#define PCI_RESP_OK 0
29623 + * The following codes indicate that the request has completed
29625 +#define PCI_RESP_NO_DEVSEL 1 /* timeout before target asserted
29627 +#define PCI_RESP_LOST_DEVSEL 2 /* had DEVSEL, but went away before
29628 + * transfer completed! */
29629 +#define PCI_RESP_BAD_TRDY 3 /* target asserted TRDY without
29631 +#define PCI_RESP_NO_TRDY 4 /* timeout before target asserted
29633 +#define PCI_RESP_BAD_STOP 5 /* target asserted STOP and TRDY
29634 + * without DEVSEL! */
29635 +#define PCI_RESP_TARGET_ABORT 6
29636 +#define PCI_RESP_TARGET_RETRY 7
29637 +#define PCI_RESP_TARGET_DISCONNECT 8
29638 +#define PCI_RESP_MISMATCH 9 /* data read back doesn't match data
29639 + * written - debug only, the core PCI
29640 + * routines never return this */
29641 +#define PCI_RESP_DET_SERR 10
29642 +#define PCI_RESP_DET_PERR 11
29643 +#define PCI_RESP_MALFORMED_REQ 12 /* Could be due to misaligned
29644 + * requests or invalid address */
29645 +#define PCI_RESP_NO_RESOURCE 13 /* Could be memory or other resourse
29646 + * like queue space */
29647 +#define PCI_RESP_ERROR 14 /* All emcompassing error */
29649 +/* registers in PCI config space */
29650 +#define PCI_DEVICE_VENDOR_ID_REG 0x00
29651 +#define PCI_STATUS_COMMAND_REG 0x04
29652 +#define PCI_CLASS_REVISION_REG 0x08
29653 +#define PCI_BHLC_REG 0x0c /* BIST, Header type, Latency
29654 + * timer, Cache line size */
29655 +#define PCI_BASE_ADDR_REG 0x10
29656 +#define PCI_BASE_REG_COUNT 6
29657 +#define CARDBUS_CIS_PTR_REG 0x28
29658 +#define PCI_SUB_SYSTEM_ID_REG 0x2c
29659 +#define PCI_EXP_ROM_ADDR_REG 0x30
29660 +#define PCI_CAP_PTR_REG 0x34
29661 +#define PCI_LGPL_REG 0x3C /* max Latency, min Gnt, interrupt
29662 + * Pin, interrupt Line */
29664 +struct pci_master_request {
29665 + volatile u32_t pci_address; /* must be 4-byte aligned */
29666 + volatile u32_t data; /* must be 4-byte aligned */
29667 + volatile u8_t cmd;
29668 + volatile u8_t byte_valid;
29669 + volatile u8_t status;
29672 +struct pci_devnode {
29673 + struct devtree_node dn;
29674 + u32_t pci_idsel_0;
29675 + u32_t pci_idsel_1;
29676 + u32_t pci_cpu_address;
29677 + struct pci_master_request volatile *volatile req;
29680 +static struct pci_master_request req; /* globally used for faster master write
29681 + * (discarding result when possible) */
29682 +static struct pci_devnode *pci_node;
29684 +#if !defined(CONFIG_DEBUG_PCIMEASURE)
29685 +#define PCI_DECLARE_MEASUREMENT
29686 +#define PCI_MEASUREMENT_START()
29687 +#define PCI_MEASUREMENT_END(idx)
29689 +#define PCI_DECLARE_MEASUREMENT \
29691 + unsigned int __tstart;
29693 +#define PCI_MEASUREMENT_START() \
29694 + __tstart = UBICOM32_IO_TIMER->sysval;
29696 +#define PCI_MEASUREMENT_END(idx) \
29697 + __diff = (int)UBICOM32_IO_TIMER->sysval - (int)__tstart; \
29698 + pci_measurement_update((idx), __diff);
29700 +#define PCI_WEIGHT 32
29702 +struct pci_measurement {
29703 + volatile unsigned int min;
29704 + volatile unsigned int avg;
29705 + volatile unsigned int max;
29708 +enum pci_measurement_list {
29709 + PCI_MEASUREMENT_READ32,
29710 + PCI_MEASUREMENT_WRITE32,
29711 + PCI_MEASUREMENT_READ16,
29712 + PCI_MEASUREMENT_WRITE16,
29713 + PCI_MEASUREMENT_READ8,
29714 + PCI_MEASUREMENT_WRITE8,
29715 + PCI_MEASUREMENT_LAST,
29718 +static const char *pci_measurement_name_list[PCI_MEASUREMENT_LAST] = {
29726 +static struct pci_measurement pci_measurements[PCI_MEASUREMENT_LAST];
29729 + * pci_measurement_update()
29730 + * Update an entry in the measurement array for this idx.
29732 +static void pci_measurement_update(int idx, int sample)
29734 + struct pci_measurement *pm = &pci_measurements[idx];
29735 + if ((pm->min == 0) || (pm->min > sample)) {
29736 + pm->min = sample;
29738 + if (pm->max < sample) {
29739 + pm->max = sample;
29741 + pm->avg = ((pm->avg * (PCI_WEIGHT - 1)) + sample) / PCI_WEIGHT;
29745 +#if defined(PCI_USE_INTERNAL_LOCK)
29747 + * pci_lock_release()
29748 + * Release the PCI lock.
29750 +static void pci_lock_release(unsigned long irqflag)
29752 + UBICOM32_UNLOCK(PCI_LOCK_BIT);
29756 + * pci_lock_acquire()
29757 + * Acquire the PCI lock, spin if not available.
29759 +static void pci_lock_acquire(unsigned long irqflag)
29761 + UBICOM32_LOCK(PCI_LOCK_BIT);
29766 + * pci_set_hrt_interrupt()
29768 +static inline void pci_set_hrt_interrupt(struct pci_devnode *pci_node)
29770 + ubicom32_set_interrupt(pci_node->dn.sendirq);
29775 + * Synchronously read 32 bits from PCI space.
29777 +u8 pci_read_u32(u8 pci_cmd, u32 address, u32 *data)
29780 + unsigned long irqflag;
29784 + * Fill in the request.
29786 + volatile struct pci_master_request lreq;
29787 + PCI_DECLARE_MEASUREMENT;
29789 + lreq.pci_address = address;
29790 + lreq.cmd = pci_cmd;
29791 + lreq.byte_valid = 0xf; /* enable all bytes */
29794 + * Wait for any previous request to complete and then make this request.
29796 + PCI_MEASUREMENT_START();
29797 + PCI_LOCK(&pci_master_lock, irqflag);
29798 + while (unlikely(pci_node->req == &req))
29800 + pci_node->req = &lreq;
29801 + pci_set_hrt_interrupt(pci_node);
29802 + PCI_UNLOCK(&pci_master_lock, irqflag);
29805 + * Wait for the result to show up.
29807 + while (unlikely(pci_node->req == &lreq))
29809 + status = lreq.status;
29810 + if (likely(status == PCI_RESP_OK))
29811 + *data = le32_to_cpu(lreq.data);
29814 + PCI_MEASUREMENT_END(PCI_MEASUREMENT_READ32);
29819 + * pci_write_u32()
29820 + * Asyncrhnously or synchronously write 32 bits to PCI master space.
29822 +u8 pci_write_u32(u8 pci_cmd, u32 address, u32 data)
29824 + unsigned long irqflag;
29825 + PCI_DECLARE_MEASUREMENT;
29828 + * Wait for any previous write or pending read to complete.
29830 + * We use a global data block because once we write the request
29831 + * we do not wait for it to complete before exiting.
29833 + PCI_MEASUREMENT_START();
29834 + PCI_LOCK(&pci_master_lock, irqflag);
29835 + while (unlikely(pci_node->req == &req))
29837 + req.pci_address = address;
29838 + req.data = cpu_to_le32(data);
29839 + req.cmd = pci_cmd;
29840 + req.byte_valid = 0xf; /* enable all bytes */
29841 + pci_node->req = &req;
29842 + pci_set_hrt_interrupt(pci_node);
29843 + PCI_UNLOCK(&pci_master_lock, irqflag);
29844 + PCI_MEASUREMENT_END(PCI_MEASUREMENT_WRITE32);
29845 + return PCI_RESP_OK;
29850 + * Synchronously read 16 bits from PCI space.
29852 +u8 pci_read_u16(u8 pci_cmd, u32 address, u16 *data)
29855 + unsigned long irqflag;
29858 + * Fill in the request.
29860 + volatile struct pci_master_request lreq;
29861 + PCI_DECLARE_MEASUREMENT;
29863 + lreq.pci_address = address & ~2;
29864 + lreq.cmd = pci_cmd;
29865 + lreq.byte_valid = (address & 2) ? 0xc : 0x3;
29868 + * Wait for any previous request to complete and then make this request.
29870 + PCI_MEASUREMENT_START();
29871 + PCI_LOCK(&pci_master_lock, irqflag);
29872 + while (unlikely(pci_node->req == &req))
29874 + pci_node->req = &lreq;
29875 + pci_set_hrt_interrupt(pci_node);
29876 + PCI_UNLOCK(&pci_master_lock, irqflag);
29879 + * Wait for the result to show up.
29881 + while (unlikely(pci_node->req == &lreq))
29883 + status = lreq.status;
29884 + if (likely(status == PCI_RESP_OK)) {
29885 + lreq.data = le32_to_cpu(lreq.data);
29886 + *data = (u16)((address & 2) ? (lreq.data >> 16) : lreq.data);
29889 + PCI_MEASUREMENT_END(PCI_MEASUREMENT_READ16);
29894 + * pci_write_u16()
29895 + * Asyncrhnously or synchronously write 16 bits to PCI master space.
29897 +u8 pci_write_u16(u8 pci_cmd, u32 address, u16 data)
29899 + unsigned long irqflag;
29900 + PCI_DECLARE_MEASUREMENT;
29903 + * Wait for any previous write or pending read to complete.
29905 + * We use a global data block because once we write the request
29906 + * we do not wait for it to complete before exiting.
29908 + PCI_MEASUREMENT_START();
29909 + PCI_LOCK(&pci_master_lock, irqflag);
29910 + while (unlikely(pci_node->req == &req))
29912 + req.pci_address = address & ~2;
29913 + req.data = (u32)data;
29914 + req.data = cpu_to_le32((address & 2) ? (req.data << 16) : req.data);
29915 + req.cmd = pci_cmd;
29916 + req.byte_valid = (address & 2) ? 0xc : 0x3;
29917 + pci_node->req = &req;
29918 + pci_set_hrt_interrupt(pci_node);
29919 + PCI_UNLOCK(&pci_master_lock, irqflag);
29920 + PCI_MEASUREMENT_END(PCI_MEASUREMENT_WRITE16);
29921 + return PCI_RESP_OK;
29926 + * Synchronously read 8 bits from PCI space.
29928 +u8 pci_read_u8(u8 pci_cmd, u32 address, u8 *data)
29931 + unsigned long irqflag;
29934 + * Fill in the request.
29936 + volatile struct pci_master_request lreq;
29937 + PCI_DECLARE_MEASUREMENT;
29939 + lreq.pci_address = address & ~3;
29940 + lreq.cmd = pci_cmd;
29941 + lreq.byte_valid = 1 << (address & 0x3);
29944 + * Wait for any previous request to complete and then make this request.
29946 + PCI_MEASUREMENT_START();
29947 + PCI_LOCK(&pci_master_lock, irqflag);
29948 + while (unlikely(pci_node->req == &req))
29950 + pci_node->req = &lreq;
29951 + pci_set_hrt_interrupt(pci_node);
29952 + PCI_UNLOCK(&pci_master_lock, irqflag);
29955 + * Wait for the result to show up.
29957 + while (unlikely(pci_node->req == &lreq))
29959 + status = lreq.status;
29960 + if (likely(status == PCI_RESP_OK)) {
29961 + *data = (u8)(lreq.data >> (24 - ((address & 0x3) << 3)));
29964 + PCI_MEASUREMENT_END(PCI_MEASUREMENT_READ8);
29970 + * Asyncrhnously or synchronously write 8 bits to PCI master space.
29972 +u8 pci_write_u8(u8 pci_cmd, u32 address, u8 data)
29974 + unsigned long irqflag;
29975 + PCI_DECLARE_MEASUREMENT;
29978 + * Wait for any previous write or pending read to complete.
29980 + * We use a global data block because once we write the request
29981 + * we do not wait for it to complete before exiting.
29983 + PCI_MEASUREMENT_START();
29984 + PCI_LOCK(&pci_master_lock, irqflag);
29985 + while (unlikely(pci_node->req == &req))
29987 + req.pci_address = address & ~3;
29988 + req.data = ((u32)data << (24 - ((address & 0x3) << 3)));
29989 + req.cmd = pci_cmd;
29990 + req.byte_valid = 1 << (address & 0x3);
29991 + pci_node->req = &req;
29992 + pci_set_hrt_interrupt(pci_node);
29993 + PCI_UNLOCK(&pci_master_lock, irqflag);
29994 + PCI_MEASUREMENT_END(PCI_MEASUREMENT_WRITE8);
29995 + return PCI_RESP_OK;
29998 +unsigned int ubi32_pci_read_u32(const volatile void __iomem *addr)
30000 + unsigned int data;
30001 + pci_read_u32(PCI_CMD_MEM_READ, (u32)addr, &data);
30004 +EXPORT_SYMBOL(ubi32_pci_read_u32);
30006 +unsigned short ubi32_pci_read_u16(const volatile void __iomem *addr)
30008 + unsigned short data;
30009 + pci_read_u16(PCI_CMD_MEM_READ, (u32)addr, &data);
30012 +EXPORT_SYMBOL(ubi32_pci_read_u16);
30014 +unsigned char ubi32_pci_read_u8(const volatile void __iomem *addr)
30016 + unsigned char data;
30017 + pci_read_u8(PCI_CMD_MEM_READ, (u32)addr, &data);
30020 +EXPORT_SYMBOL(ubi32_pci_read_u8);
30022 +void ubi32_pci_write_u32(unsigned int val, const volatile void __iomem *addr)
30024 + pci_write_u32(PCI_CMD_MEM_WRITE, (u32)addr, val);
30026 +EXPORT_SYMBOL(ubi32_pci_write_u32);
30028 +void ubi32_pci_write_u16(unsigned short val, const volatile void __iomem *addr)
30030 + pci_write_u16(PCI_CMD_MEM_WRITE, (u32)addr, val);
30032 +EXPORT_SYMBOL(ubi32_pci_write_u16);
30034 +void ubi32_pci_write_u8(unsigned char val, const void volatile __iomem *addr)
30036 + pci_write_u8(PCI_CMD_MEM_WRITE, (u32)addr, val);
30038 +EXPORT_SYMBOL(ubi32_pci_write_u8);
30040 +#if defined(CONFIG_DEBUG_PCIMEASURE)
30041 +static unsigned int pci_cycles_to_nano(unsigned int cycles, unsigned int frequency)
30043 + unsigned int nano = ((cycles * 1000) / (frequency / 1000000));
30048 + * pci_measurement_show()
30049 + * Print out the min, avg, max values for each PCI transaction type.
30051 + * By request, the max value is reset after each dump.
30053 +static int pci_measurement_show(struct seq_file *p, void *v)
30055 + unsigned int min, avg, max;
30056 + unsigned int freq = processor_frequency();
30057 + int trans = *((loff_t *) v);
30059 + if (trans == 0) {
30060 + seq_puts(p, "min\tavg\tmax\t(nano-seconds)\n");
30063 + if (trans >= PCI_MEASUREMENT_LAST) {
30067 + min = pci_cycles_to_nano(pci_measurements[trans].min, freq);
30068 + avg = pci_cycles_to_nano(pci_measurements[trans].avg, freq);
30069 + max = pci_cycles_to_nano(pci_measurements[trans].max, freq);
30070 + pci_measurements[trans].max = 0;
30071 + seq_printf(p, "%u\t%u\t%u\t%s\n", min, avg, max, pci_measurement_name_list[trans]);
30075 +static void *pci_measurement_start(struct seq_file *f, loff_t *pos)
30077 + return (*pos < PCI_MEASUREMENT_LAST) ? pos : NULL;
30080 +static void *pci_measurement_next(struct seq_file *f, void *v, loff_t *pos)
30083 + if (*pos >= PCI_MEASUREMENT_LAST)
30088 +static void pci_measurement_stop(struct seq_file *f, void *v)
30090 + /* Nothing to do */
30093 +static const struct seq_operations pci_measurement_seq_ops = {
30094 + .start = pci_measurement_start,
30095 + .next = pci_measurement_next,
30096 + .stop = pci_measurement_stop,
30097 + .show = pci_measurement_show,
30100 +static int pci_measurement_open(struct inode *inode, struct file *filp)
30102 + return seq_open(filp, &pci_measurement_seq_ops);
30105 +static const struct file_operations pci_measurement_fops = {
30106 + .open = pci_measurement_open,
30107 + .read = seq_read,
30108 + .llseek = seq_lseek,
30109 + .release = seq_release,
30112 +static int __init pci_measurement_init(void)
30114 + proc_create("pci_measurements", 0, NULL, &pci_measurement_fops);
30117 +module_init(pci_measurement_init);
30120 +static int ubi32_pci_read_config(struct pci_bus *bus, unsigned int devfn,
30121 + int where, int size, u32 *value)
30128 + u8 slot = PCI_SLOT(devfn);
30129 + u8 fn = PCI_FUNC(devfn);
30132 + return PCIBIOS_DEVICE_NOT_FOUND;
30133 + } else if (slot == 0) {
30134 + addr = PCI_DEV0_IDSEL + where;
30136 + addr = PCI_DEV1_IDSEL + where;
30139 + addr += (fn << 8);
30141 + cmd = PCI_CMD_CFG_READ;
30143 + pci_read_u8(cmd, addr, &data8);
30144 + *value = (u32)data8;
30145 + } else if (size == 2) {
30146 + pci_read_u16(cmd, addr, &data16);
30147 + *value = (u32)data16;
30149 + pci_read_u32(cmd, addr, value);
30152 + return PCIBIOS_SUCCESSFUL;
30155 +static int ubi32_pci_write_config(struct pci_bus *bus, unsigned int devfn,
30156 + int where, int size, u32 value)
30160 + u8 slot = PCI_SLOT(devfn);
30161 + u8 fn = PCI_FUNC(devfn);
30164 + return PCIBIOS_DEVICE_NOT_FOUND;
30165 + } else if (slot == 0) {
30166 + addr = PCI_DEV0_IDSEL + where;
30168 + addr = PCI_DEV1_IDSEL + where;
30171 + addr += (fn << 8);
30173 + cmd = PCI_CMD_CFG_WRITE;
30175 + pci_write_u8(cmd, addr, (u8)value);
30176 + } else if (size == 2) {
30177 + pci_write_u16(cmd, addr, (u16)value);
30179 + pci_write_u32(cmd, addr, value);
30182 + return PCIBIOS_SUCCESSFUL;
30185 +int pci_set_dma_max_seg_size(struct pci_dev *dev, unsigned int size)
30189 +EXPORT_SYMBOL(pci_set_dma_max_seg_size);
30191 +int pci_set_dma_seg_boundary(struct pci_dev *dev, unsigned long mask)
30195 +EXPORT_SYMBOL(pci_set_dma_seg_boundary);
30197 +void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
30199 + resource_size_t start = pci_resource_start(dev, bar);
30200 + resource_size_t len = pci_resource_len(dev, bar);
30201 + unsigned long flags = pci_resource_flags(dev, bar);
30203 + if (!len || !start) {
30207 + if (maxlen && len > maxlen) {
30211 + if (flags & IORESOURCE_IO) {
30212 + return ioport_map(start, len);
30215 + if (flags & IORESOURCE_MEM) {
30216 + if (flags & IORESOURCE_CACHEABLE) {
30217 + return ioremap(start, len);
30219 + return ioremap_nocache(start, len);
30223 +EXPORT_SYMBOL(pci_iomap);
30225 +void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
30227 + if ((unsigned long)addr >= VMALLOC_START &&
30228 + (unsigned long)addr < VMALLOC_END) {
30232 +EXPORT_SYMBOL(pci_iounmap);
30235 + * From arch/arm/kernel/bios32.c
30237 + * PCI bios-type initialisation for PCI machines
30239 + * Bits taken from various places.
30241 +static void __init pcibios_init_hw(struct hw_pci *hw)
30243 + struct pci_sys_data *sys = NULL;
30247 + for (nr = busnr = 0; nr < hw->nr_controllers; nr++) {
30248 + sys = kzalloc(sizeof(struct pci_sys_data), GFP_KERNEL);
30250 + panic("PCI: unable to allocate sys data!");
30253 + sys->busnr = busnr;
30254 + sys->map_irq = hw->map_irq;
30255 + sys->resource[0] = &ioport_resource;
30256 + sys->resource[1] = &iomem_resource;
30258 + ret = hw->setup(nr, sys);
30261 + sys->bus = hw->scan(nr, sys);
30264 + panic("PCI: unable to scan bus!");
30266 + busnr = sys->bus->subordinate + 1;
30268 + list_add(&sys->node, &hw->buses);
30278 + * Swizzle the device pin each time we cross a bridge.
30279 + * This might update pin and returns the slot number.
30281 +static u8 __devinit pcibios_swizzle(struct pci_dev *dev, u8 *pin)
30283 + struct pci_sys_data *sys = dev->sysdata;
30284 + int slot = 0, oldpin = *pin;
30286 + if (sys->swizzle)
30287 + slot = sys->swizzle(dev, pin);
30290 + printk("PCI: %s swizzling pin %d => pin %d slot %d\n",
30291 + pci_name(dev), oldpin, *pin, slot);
30296 + * Map a slot/pin to an IRQ.
30298 +static int pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
30300 + struct pci_sys_data *sys = dev->sysdata;
30303 + if (sys->map_irq)
30304 + irq = sys->map_irq(dev, slot, pin);
30307 + printk("PCI: %s mapping slot %d pin %d => irq %d\n",
30308 + pci_name(dev), slot, pin, irq);
30313 +void __init pci_common_init(struct hw_pci *hw)
30315 + struct pci_sys_data *sys;
30317 + INIT_LIST_HEAD(&hw->buses);
30321 + pcibios_init_hw(hw);
30322 + if (hw->postinit)
30325 + pci_fixup_irqs(pcibios_swizzle, pcibios_map_irq);
30326 + list_for_each_entry(sys, &hw->buses, node) {
30327 + struct pci_bus *bus = sys->bus;
30329 + * Size the bridge windows.
30331 + pci_bus_size_bridges(bus);
30333 + * Assign resources.
30335 + pci_bus_assign_resources(bus);
30338 + * Tell drivers about devices found.
30340 + pci_bus_add_devices(bus);
30344 +char * __init pcibios_setup(char *str)
30346 + if (!strcmp(str, "debug")) {
30354 + * From arch/i386/kernel/pci-i386.c:
30356 + * We need to avoid collisions with `mirrored' VGA ports
30357 + * and other strange ISA hardware, so we always want the
30358 + * addresses to be allocated in the 0x000-0x0ff region
30361 + * Why? Because some silly external IO cards only decode
30362 + * the low 10 bits of the IO address. The 0x00-0xff region
30363 + * is reserved for motherboard devices that decode all 16
30364 + * bits, so it's ok to allocate at, say, 0x2800-0x28ff,
30365 + * but we want to try to avoid allocating at 0x2900-0x2bff
30366 + * which might be mirrored at 0x0100-0x03ff..
30368 +void pcibios_align_resource(void *data, struct resource *res,
30369 + resource_size_t size, resource_size_t align)
30371 + resource_size_t start = res->start;
30373 + if (res->flags & IORESOURCE_IO && start & 0x300)
30374 + start = (start + 0x3ff) & ~0x3ff;
30376 + res->start = (start + align - 1) & ~(align - 1);
30380 +void __devinit pcibios_update_irq(struct pci_dev *dev, int irq)
30383 + printk("PCI: Assigning IRQ %02d to %s\n", irq, pci_name(dev));
30384 + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
30388 + * If the bus contains any of these devices, then we must not turn on
30389 + * parity checking of any kind. Currently this is CyberPro 20x0 only.
30391 +static inline int pdev_bad_for_parity(struct pci_dev *dev)
30393 + return (dev->vendor == PCI_VENDOR_ID_INTERG &&
30394 + (dev->device == PCI_DEVICE_ID_INTERG_2000 ||
30395 + dev->device == PCI_DEVICE_ID_INTERG_2010)) ||
30396 + (dev->vendor == PCI_VENDOR_ID_ITE &&
30397 + dev->device == PCI_DEVICE_ID_ITE_8152);
30402 + * Adjust the device resources from bus-centric to Linux-centric.
30404 +static void __devinit
30405 +pdev_fixup_device_resources(struct pci_sys_data *root, struct pci_dev *dev)
30407 + resource_size_t offset;
30410 + for (i = 0; i < PCI_NUM_RESOURCES; i++) {
30411 + if (dev->resource[i].start == 0)
30413 + if (dev->resource[i].flags & IORESOURCE_MEM)
30414 + offset = root->mem_offset;
30416 + offset = root->io_offset;
30418 + dev->resource[i].start += offset;
30419 + dev->resource[i].end += offset;
30423 +static void __devinit
30424 +pbus_assign_bus_resources(struct pci_bus *bus, struct pci_sys_data *root)
30426 + struct pci_dev *dev = bus->self;
30431 + * Assign root bus resources.
30433 + for (i = 0; i < 3; i++)
30434 + bus->resource[i] = root->resource[i];
30439 + * pcibios_fixup_bus - Called after each bus is probed,
30440 + * but before its children are examined.
30442 +void pcibios_fixup_bus(struct pci_bus *bus)
30444 + struct pci_sys_data *root = bus->sysdata;
30445 + struct pci_dev *dev;
30446 + u16 features = PCI_COMMAND_SERR | PCI_COMMAND_PARITY |
30447 + PCI_COMMAND_FAST_BACK;
30449 + pbus_assign_bus_resources(bus, root);
30452 + * Walk the devices on this bus, working out what we can
30453 + * and can't support.
30455 + list_for_each_entry(dev, &bus->devices, bus_list) {
30458 + pdev_fixup_device_resources(root, dev);
30460 + pci_read_config_word(dev, PCI_STATUS, &status);
30463 + * If any device on this bus does not support fast back
30464 + * to back transfers, then the bus as a whole is not able
30465 + * to support them. Having fast back to back transfers
30466 + * on saves us one PCI cycle per transaction.
30468 + if (!(status & PCI_STATUS_FAST_BACK))
30469 + features &= ~PCI_COMMAND_FAST_BACK;
30471 + if (pdev_bad_for_parity(dev))
30472 + features &= ~(PCI_COMMAND_SERR | PCI_COMMAND_PARITY);
30474 + switch (dev->class >> 8) {
30475 + case PCI_CLASS_BRIDGE_PCI:
30476 + pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &status);
30477 + status |= PCI_BRIDGE_CTL_PARITY |
30478 + PCI_BRIDGE_CTL_MASTER_ABORT;
30479 + status &= ~(PCI_BRIDGE_CTL_BUS_RESET |
30480 + PCI_BRIDGE_CTL_FAST_BACK);
30481 + pci_write_config_word(dev, PCI_BRIDGE_CONTROL, status);
30484 + case PCI_CLASS_BRIDGE_CARDBUS:
30485 + pci_read_config_word(dev, PCI_CB_BRIDGE_CONTROL,
30487 + status |= PCI_CB_BRIDGE_CTL_PARITY |
30488 + PCI_CB_BRIDGE_CTL_MASTER_ABORT;
30489 + pci_write_config_word(dev, PCI_CB_BRIDGE_CONTROL,
30496 + * Now walk the devices again, this time setting them up.
30498 + list_for_each_entry(dev, &bus->devices, bus_list) {
30501 + pci_read_config_word(dev, PCI_COMMAND, &cmd);
30503 + pci_write_config_word(dev, PCI_COMMAND, cmd);
30505 + pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
30506 + L1_CACHE_BYTES >> 2);
30510 + * Propagate the flags to the PCI bridge.
30512 + if (bus->self && bus->self->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
30513 + if (features & PCI_COMMAND_FAST_BACK)
30514 + bus->bridge_ctl |= PCI_BRIDGE_CTL_FAST_BACK;
30515 + if (features & PCI_COMMAND_PARITY)
30516 + bus->bridge_ctl |= PCI_BRIDGE_CTL_PARITY;
30520 + * Report what we did for this bus
30522 + printk(KERN_INFO "PCI: bus%d: Fast back to back transfers %sabled\n",
30523 + bus->number, (features & PCI_COMMAND_FAST_BACK) ? "en" : "dis");
30526 + * Convert from Linux-centric to bus-centric addresses for bridge devices.
30529 +pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
30530 + struct resource *res)
30532 + struct pci_sys_data *root = dev->sysdata;
30533 + unsigned long offset = 0;
30535 + if (res->flags & IORESOURCE_IO)
30536 + offset = root->io_offset;
30537 + if (res->flags & IORESOURCE_MEM)
30538 + offset = root->mem_offset;
30540 + region->start = res->start - offset;
30541 + region->end = res->end - offset;
30545 +pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
30546 + struct pci_bus_region *region)
30548 + struct pci_sys_data *root = dev->sysdata;
30549 + unsigned long offset = 0;
30551 + if (res->flags & IORESOURCE_IO)
30552 + offset = root->io_offset;
30553 + if (res->flags & IORESOURCE_MEM)
30554 + offset = root->mem_offset;
30556 + res->start = region->start + offset;
30557 + res->end = region->end + offset;
30560 +#ifdef CONFIG_HOTPLUG
30561 +EXPORT_SYMBOL(pcibios_fixup_bus);
30562 +EXPORT_SYMBOL(pcibios_resource_to_bus);
30563 +EXPORT_SYMBOL(pcibios_bus_to_resource);
30567 + * pcibios_enable_device - Enable I/O and memory.
30568 + * @dev: PCI device to be enabled
30570 +int pcibios_enable_device(struct pci_dev *dev, int mask)
30572 + u16 cmd, old_cmd;
30574 + struct resource *r;
30576 + pci_read_config_word(dev, PCI_COMMAND, &cmd);
30578 + for (idx = 0; idx < 6; idx++) {
30579 + /* Only set up the requested stuff */
30580 + if (!(mask & (1 << idx)))
30583 + r = dev->resource + idx;
30584 + if (!r->start && r->end) {
30585 + printk(KERN_ERR "PCI: Device %s not available because"
30586 + " of resource collisions\n", pci_name(dev));
30589 + if (r->flags & IORESOURCE_IO)
30590 + cmd |= PCI_COMMAND_IO;
30591 + if (r->flags & IORESOURCE_MEM)
30592 + cmd |= PCI_COMMAND_MEMORY;
30596 + * Bridges (eg, cardbus bridges) need to be fully enabled
30598 + if ((dev->class >> 16) == PCI_BASE_CLASS_BRIDGE)
30599 + cmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
30601 + if (cmd != old_cmd) {
30602 + printk("PCI: enabling device %s (%04x -> %04x)\n",
30603 + pci_name(dev), old_cmd, cmd);
30604 + pci_write_config_word(dev, PCI_COMMAND, cmd);
30610 +struct pci_ops ubi32_pci_ops = {
30611 + .read = ubi32_pci_read_config,
30612 + .write = ubi32_pci_write_config,
30615 +static struct pci_bus *ubi32_pci_scan_bus(int nr, struct pci_sys_data *sys)
30617 + return pci_scan_bus(sys->busnr, &ubi32_pci_ops, sys);
30620 +#define UBI32_PCI_MEM_BASE PCI_DEV_REG_BASE
30621 +#define UBI32_PCI_MEM_LEN 0x80000000
30623 +#define UBI32_PCI_IO_BASE 0x0
30624 +#define UBI32_PCI_IO_END 0x0
30626 +static struct resource ubi32_pci_mem = {
30627 + .name = "PCI memory space",
30628 + .start = UBI32_PCI_MEM_BASE,
30629 + .end = UBI32_PCI_MEM_BASE + UBI32_PCI_MEM_LEN - 1,
30630 + .flags = IORESOURCE_MEM,
30633 +static struct resource ubi32_pci_io = {
30634 + .name = "PCI IO space",
30635 + .start = UBI32_PCI_IO_BASE,
30636 + .end = UBI32_PCI_IO_END,
30637 + .flags = IORESOURCE_IO,
30640 +static int __init ubi32_pci_setup(int nr, struct pci_sys_data *sys)
30645 + request_resource(&iomem_resource, &ubi32_pci_mem);
30646 + request_resource(&ioport_resource, &ubi32_pci_io);
30648 + sys->resource[0] = &ubi32_pci_io;
30649 + sys->resource[1] = &ubi32_pci_mem;
30650 + sys->resource[2] = NULL;
30655 +static void __init ubi32_pci_preinit(void)
30659 +static int __init ubi32_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
30661 + return pci_node->dn.recvirq;
30664 +struct hw_pci ubi32_pci __initdata = {
30665 + .nr_controllers = 1,
30666 + .preinit = ubi32_pci_preinit,
30667 + .setup = ubi32_pci_setup,
30668 + .scan = ubi32_pci_scan_bus,
30669 + .map_irq = ubi32_pci_map_irq,
30672 +static int __init ubi32_pci_init(void)
30674 + pci_node = (struct pci_devnode *)devtree_find_node("pci");
30675 + if (pci_node == NULL) {
30676 + printk(KERN_WARNING "PCI init failed\n");
30679 + pci_common_init(&ubi32_pci);
30683 +subsys_initcall(ubi32_pci_init);
30686 + * workaround for dual PCI card interrupt
30688 +#define PCI_COMMON_INT_BIT (1 << 19)
30689 +void ubi32_pci_int_wr(void)
30691 + volatile unsigned int pci_int_line;
30692 + pci_int_line = UBICOM32_IO_PORT(RB)->gpio_in;
30693 + if (!(pci_int_line & PCI_COMMON_INT_BIT))
30695 + ubicom32_set_interrupt(pci_node->dn.recvirq);
30698 +EXPORT_SYMBOL(ubi32_pci_int_wr);
30699 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/plio.c linux-2.6.30.10-ubi/arch/ubicom32/mach-common/plio.c
30700 --- linux-2.6.30.10/arch/ubicom32/mach-common/plio.c 1970-01-01 02:00:00.000000000 +0200
30701 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/plio.c 2009-12-11 11:45:11.000000000 +0200
30705 + * PLIO state machine support functions
30707 + * Copyright © 2009 Ubicom Inc. <www.ubicom.com>. All rights reserved.
30709 + * This file is part of the Ubicom32 Linux Kernel Port.
30711 + * The Ubicom32 Linux Kernel Port is free software: you can
30712 + * redistribute it and/or modify it under the terms of the GNU General
30713 + * Public License as published by the Free Software Foundation, either
30714 + * version 2 of the License, or (at your option) any later version.
30716 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
30717 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
30718 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
30719 + * See the GNU General Public License for more details.
30721 + * You should have received a copy of the GNU General Public License
30722 + * along with the Ubicom32 Linux Kernel Port. If not,
30723 + * see <http://www.gnu.org/licenses/>.
30726 +#include <linux/types.h>
30727 +#include <linux/string.h>
30728 +#include <linux/delay.h>
30729 +#include <asm/plio.h>
30733 + * Select and reset PLIO function
30735 +static void plio_reset(const plio_fctl_t *plio_fctl) {
30736 + plio_io_function_t plio_function = {
30737 + .fn_sel = PLIO_FN,
30742 + * enable extension port
30744 + PEXT_NBR->function = plio_function;
30747 + * program clock dividers
30749 + PLIO_NBR->fctl2 = plio_fctl->fctl2;
30752 + * select plio function and assert function reset
30754 + plio_function.br_thread = thread_get_self();
30755 + plio_function.fn_reset = 1;
30756 + PLIO_NBR->function = plio_function;
30759 + * program plio controls
30761 + PLIO_NBR->fctl0 = plio_fctl->fctl0;
30762 + PLIO_NBR->fctl1 = plio_fctl->fctl1;
30765 + * deassert function reset
30767 + plio_function.fn_reset = 0;
30768 + PLIO_NBR->function = plio_function;
30773 + * configure and initialize PLIO.
30775 +void plio_init(const plio_fctl_t *plio_fctl, const plio_config_t *plio_config, const plio_sram_t plio_sram_cfg[], int sram_cfg_size){
30777 + * first reset to start plio clock
30779 + plio_reset(plio_fctl);
30786 + PLIO_NBR->fctl0.pfsm_prog = 1;
30787 + memcpy(PLIO_BR->pfsm_sram, plio_sram_cfg, sram_cfg_size);
30788 + PLIO_NBR->fctl0.pfsm_prog = 0;
30791 + * program rest of plio
30793 + memcpy(&PLIO_BR->config, plio_config, sizeof(plio_config_t));
30795 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/profile.c linux-2.6.30.10-ubi/arch/ubicom32/mach-common/profile.c
30796 --- linux-2.6.30.10/arch/ubicom32/mach-common/profile.c 1970-01-01 02:00:00.000000000 +0200
30797 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/profile.c 2009-12-11 11:45:11.000000000 +0200
30800 + * arch/ubicom32/mach-common/profile.c
30801 + * Implementation for Ubicom32 Profiler
30803 + * (C) Copyright 2009, Ubicom, Inc.
30805 + * This file is part of the Ubicom32 Linux Kernel Port.
30807 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
30808 + * it and/or modify it under the terms of the GNU General Public License
30809 + * as published by the Free Software Foundation, either version 2 of the
30810 + * License, or (at your option) any later version.
30812 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
30813 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
30814 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
30815 + * the GNU General Public License for more details.
30817 + * You should have received a copy of the GNU General Public License
30818 + * along with the Ubicom32 Linux Kernel Port. If not,
30819 + * see <http://www.gnu.org/licenses/>.
30822 +#include <linux/platform_device.h>
30823 +#include "profile.h"
30824 +#include <linux/seq_file.h>
30825 +#include <linux/proc_fs.h>
30826 +#include <linux/mm.h>
30827 +#include <linux/mmzone.h>
30828 +#include <linux/fs.h>
30829 +#include <linux/page-flags.h>
30830 +#include <asm/uaccess.h>
30831 +#include <asm/devtree.h>
30832 +#include <asm/profilesample.h>
30833 +#include <asm/memory_map.h>
30834 +#include <asm/page.h>
30835 +#include <asm/ip5000.h>
30838 + * spacs for all memory blocks so we can hold locks for short time when walking tables
30840 +#define PROFILE_NUM_MAPS 5000
30841 +static struct profile_map profile_pm[PROFILE_NUM_MAPS];
30843 +static struct profilenode *node = NULL;
30844 +static int profile_first_packet = 1;
30846 +static int profile_open(struct inode *inode, struct file *filp)
30852 + if (!node->enabled) {
30853 + node->enabled = 1;
30855 + profile_first_packet = 1;
30862 +static int profile_sequence_num;
30865 + * make a packet full of sample data
30867 +static int profile_make_data_packet(char *buf, int count)
30869 + int samples; /* number of samples requested */
30871 + struct profile_header ph;
30874 + if (count < sizeof(struct profile_header) + sizeof(struct profile_sample)) {
30879 + * fill in the packet header
30881 + memset(&ph, 0, sizeof(struct profile_header));
30882 + ph.magic = PROF_MAGIC + PROFILE_VERSION;
30883 + ph.header_size = sizeof(struct profile_header);
30884 + ph.clocks = node->clocks;
30885 + for (i = 0; i < PROFILE_MAX_THREADS; ++i) {
30886 + ph.instruction_count[i] = node->inst_count[i];
30888 + ph.profile_instructions = 0;
30889 + ph.enabled = node->enabled_threads;
30890 + ph.hrt = node->hrt;
30892 + ph.profiler_thread = node->profiler_thread;
30893 + ph.clock_freq = node->clock_freq;
30894 + ph.seq_num = profile_sequence_num++;
30895 + ph.cpu_id = node->cpu_id;
30896 + ph.perf_counters[0] = node->stats[0];
30897 + ph.perf_counters[1] = node->stats[1];
30898 + ph.perf_counters[2] = node->stats[2];
30899 + ph.perf_counters[3] = node->stats[3];
30900 + ph.ddr_freq = node->ddr_freq;
30902 + ptr = buf + sizeof(struct profile_header);
30904 + samples = (count - sizeof(struct profile_header)) / sizeof(struct profile_sample);
30905 + for (i = 0; i < samples && node->count; ++i) {
30906 + if (copy_to_user(ptr, &node->samples[node->tail], sizeof(struct profile_sample)) != 0) {
30911 + if (node->tail >= node->max_samples) {
30914 + ptr += sizeof(struct profile_sample);
30916 + ph.sample_count = i;
30917 + if (copy_to_user(buf, &ph, sizeof(struct profile_header)) != 0) {
30920 + if (ph.sample_count == 0)
30923 + return sizeof(struct profile_header) + ph.sample_count * sizeof(struct profile_sample);
30926 +static void profile_get_memory_stats(unsigned int *total_free, unsigned int *max_free)
30928 + struct list_head *p;
30929 + struct zone *zone;
30930 + unsigned int size;
30936 + * get all the free regions. In each zone, the array of free_area lists contains the first page of each frame of size 1 << order
30938 + for_each_zone(zone) {
30939 + unsigned long order, flags, i;
30941 + if (!populated_zone(zone))
30944 + if (!is_normal(zone))
30947 + spin_lock_irqsave(&zone->lock, flags);
30948 + for_each_migratetype_order(order, i) {
30949 + size = ((1 << order) << PAGE_SHIFT) >> 10;
30950 + list_for_each(p, &(zone->free_area[order].free_list[i])) {
30951 + if (size > *max_free) {
30952 + *max_free = size;
30954 + *total_free += size;
30957 + spin_unlock_irqrestore(&zone->lock, flags);
30961 +struct profile_counter_pkt profile_builtin_stats[] =
30964 + "Free memory(KB)", 0
30967 + "Max free Block(KB)", 0
30972 + * make a packet full of performance counters
30974 +static char prof_pkt[PROFILE_MAX_PACKET_SIZE];
30975 +static int profile_make_stats_packet(char *buf, int count)
30977 + char *ptr = prof_pkt;
30978 + struct profile_header_counters hdr;
30979 + int stat_count = 0;
30981 + unsigned int total_free, max_free;
30982 + int builtin_count = sizeof(profile_builtin_stats) / sizeof(struct profile_counter_pkt);
30984 + if (count > PROFILE_MAX_PACKET_SIZE) {
30985 + count = PROFILE_MAX_PACKET_SIZE;
30987 + stat_count = (count - sizeof(struct profile_header_counters)) / sizeof (struct profile_counter_pkt);
30988 + stat_count -= builtin_count;
30990 + if (stat_count <= 0) {
30994 + if (stat_count > node->num_counters) {
30995 + stat_count = node->num_counters;
30998 + hdr.magic = PROF_MAGIC_COUNTERS;
30999 + hdr.ultra_sample_time = node->clocks;
31000 + hdr.ultra_count = stat_count;
31001 + hdr.linux_sample_time = UBICOM32_IO_TIMER->sysval;
31002 + hdr.linux_count = builtin_count;
31003 + memcpy(ptr, (void *)&hdr, sizeof(struct profile_header_counters));
31004 + ptr += sizeof(struct profile_header_counters);
31007 + for (i = 0; i < stat_count; ++i) {
31008 + memcpy(ptr, (void *)(&(node->counters[i])), sizeof(struct profile_counter));
31009 + ptr += sizeof(struct profile_counter);
31013 + * built in statistics
31015 + profile_get_memory_stats(&total_free, &max_free);
31016 + profile_builtin_stats[0].value = total_free;
31017 + profile_builtin_stats[1].value = max_free;
31018 + memcpy(ptr, (void *)profile_builtin_stats, sizeof(profile_builtin_stats));
31019 + ptr += sizeof(profile_builtin_stats);
31021 + if (copy_to_user(buf, prof_pkt, ptr - prof_pkt) != 0) {
31024 + return ptr - prof_pkt;
31028 + * return a udp packet ready to send to the profiler tool
31029 + * when there are no packets left to make, return 0
31031 +static int profile_read(struct file *filp, char *buf, size_t count, loff_t *f_pos)
31038 + if (!node->enabled) {
31042 + if (!node->samples) {
31047 + if (profile_first_packet) {
31048 + result = profile_make_stats_packet(buf, count);
31049 + profile_first_packet = 0;
31051 + if (result == 0) {
31052 + result = profile_make_data_packet(buf, count);
31053 + if (result == 0) {
31054 + profile_first_packet = 1;
31062 +static int profile_release(struct inode *inode, struct file *filp)
31068 + if (node->enabled) {
31069 + node->enabled = 0;
31071 + node->tail = node->head;
31076 + profile_first_packet = 1;
31080 +static const struct file_operations profile_fops = {
31081 + .open = profile_open,
31082 + .read = profile_read,
31083 + .release = profile_release,
31086 +static int page_aligned(void *x)
31088 + return !((unsigned int)x & ((1 << PAGE_SHIFT) - 1));
31091 +static int profile_maps_open(struct inode *inode, struct file *filp)
31093 + struct rb_node *rb;
31096 + struct vm_area_struct *vma;
31097 + int type = PROFILE_MAP_TYPE_UNKNOWN;
31099 + struct list_head *p;
31100 + struct zone *zone;
31103 + * get the slab data (first so dups will show up as vmas)
31105 + slab_start = num;
31106 + num += kmem_cache_block_info("size-512", (struct kmem_cache_size_info *)&profile_pm[num], PROFILE_NUM_MAPS - num);
31107 + num += kmem_cache_block_info("size-1024", (struct kmem_cache_size_info *)&profile_pm[num], PROFILE_NUM_MAPS - num);
31108 + num += kmem_cache_block_info("size-2048", (struct kmem_cache_size_info *)&profile_pm[num], PROFILE_NUM_MAPS - num);
31109 + num += kmem_cache_block_info("size-4096", (struct kmem_cache_size_info *)&profile_pm[num], PROFILE_NUM_MAPS - num);
31110 + num += kmem_cache_block_info("size-8192", (struct kmem_cache_size_info *)&profile_pm[num], PROFILE_NUM_MAPS - num);
31112 + for (i = slab_start; i < num; ++i) {
31113 + profile_pm[i].type_size |= PROFILE_MAP_TYPE_SMALL << PROFILE_MAP_TYPE_SHIFT;
31116 + slab_start = num;
31117 + num += kmem_cache_block_info("dentry", (struct kmem_cache_size_info *)&profile_pm[num], PROFILE_NUM_MAPS - num);
31118 + num += kmem_cache_block_info("inode_cache", (struct kmem_cache_size_info *)&profile_pm[num], PROFILE_NUM_MAPS - num);
31119 + num += kmem_cache_block_info("sysfs_dir_cache", (struct kmem_cache_size_info *)&profile_pm[num], PROFILE_NUM_MAPS - num);
31120 + num += kmem_cache_block_info("proc_inode_cache", (struct kmem_cache_size_info *)&profile_pm[num], PROFILE_NUM_MAPS - num);
31122 + for (i = slab_start; i < num; ++i) {
31123 + profile_pm[i].type_size |= PROFILE_MAP_TYPE_FS << PROFILE_MAP_TYPE_SHIFT;
31127 + * get all the vma regions (allocated by mmap, most likely
31130 + down_read(&nommu_vma_sem);
31131 + for (rb = rb_first(&nommu_vma_tree); rb && num < PROFILE_NUM_MAPS; rb = rb_next(rb)) {
31132 + vma = rb_entry(rb, struct vm_area_struct, vm_rb);
31133 + profile_pm[num].start = (vma->vm_start - SDRAMSTART) >> PAGE_SHIFT;
31134 + profile_pm[num].type_size = (vma->vm_end - vma->vm_start + (1 << PAGE_SHIFT) - 1) >> PAGE_SHIFT;
31135 + flags = vma->vm_flags & 0xf;
31136 + if (flags == (VM_READ | VM_EXEC)) {
31137 + type = PROFILE_MAP_TYPE_TEXT;
31138 + } else if (flags == (VM_READ | VM_WRITE | VM_EXEC)) {
31139 + type = PROFILE_MAP_TYPE_STACK;
31140 + } else if (flags == (VM_READ | VM_WRITE)) {
31141 + type = PROFILE_MAP_TYPE_APP_DATA;
31143 + profile_pm[num].type_size |= type << PROFILE_MAP_TYPE_SHIFT;
31146 + up_read(&nommu_vma_sem);
31153 + * get all the free regions. In each zone, the array of free_area lists contains the first page of each frame of size 1 << order
31155 + for_each_zone(zone) {
31156 + unsigned long order, flags, i;
31157 + struct page *page;
31159 + if (!populated_zone(zone))
31162 + if (!is_normal(zone))
31165 + spin_lock_irqsave(&zone->lock, flags);
31166 + for_each_migratetype_order(order, i) {
31167 + list_for_each(p, &(zone->free_area[order].free_list[i])) {
31168 + page = list_entry(p, struct page, lru);
31169 + profile_pm[num].start = ((page_to_phys(page) - SDRAMSTART) >> PAGE_SHIFT) - 0x40;
31170 + profile_pm[num].type_size = (PROFILE_MAP_TYPE_FREE << PROFILE_MAP_TYPE_SHIFT) | order;
31172 + if (num >= PROFILE_NUM_MAPS) {
31173 + spin_unlock_irqrestore(&zone->lock, flags);
31178 + spin_unlock_irqrestore(&zone->lock, flags);
31182 + * get the filesystem inodes
31184 + list_for_each(p, &(super_blocks)) {
31185 + struct super_block *sb;
31186 + struct list_head *q;
31187 + if (num >= PROFILE_NUM_MAPS)
31189 + sb = list_entry(p, struct super_block, s_list);
31190 + if (page_aligned(sb)) {
31191 + profile_pm[num].start = ((unsigned int)sb - SDRAMSTART) >> PAGE_SHIFT;
31192 + profile_pm[num].type_size = (PROFILE_MAP_TYPE_FS << PROFILE_MAP_TYPE_SHIFT);
31195 + list_for_each(q, &(sb->s_inodes)) {
31196 + struct inode *in;
31197 + if (num >= PROFILE_NUM_MAPS)
31199 + in = list_entry(q, struct inode, i_sb_list);
31200 + if (page_aligned(in)) {
31201 + profile_pm[num].start = ((unsigned int)in - SDRAMSTART) >> PAGE_SHIFT;
31202 + profile_pm[num].type_size = (PROFILE_MAP_TYPE_FS << PROFILE_MAP_TYPE_SHIFT);
31209 + * get the buffer cache pages
31211 + for (i = 0; i < num_physpages && num < PROFILE_NUM_MAPS; ++i) {
31212 + if ((mem_map + i)->flags & (1 << PG_lru)) {
31214 + while ((mem_map + i)->flags & (1 << PG_lru) && i < num_physpages)
31216 + profile_pm[num].start = start;
31217 + profile_pm[num].type_size = (i - start) | (PROFILE_MAP_TYPE_CACHE << PROFILE_MAP_TYPE_SHIFT);
31222 + filp->private_data = (void *)num;
31227 + * return one packet of map data, or 0 if all maps have been returned already
31229 +static int profile_maps_read(struct file *filp, char *buf, size_t count, loff_t *f_pos)
31231 + struct profile_header_maps header;
31232 + char *p = buf + sizeof(header);
31233 + int total = (int)filp->private_data;
31235 + header.count = (count - sizeof(header)) / sizeof(struct profile_map);
31236 + if (header.count > PROFILE_MAX_MAPS) {
31237 + header.count = PROFILE_MAX_MAPS;;
31239 + if (header.count > total - *f_pos) {
31240 + header.count = total - *f_pos;
31243 + if (header.count == 0) {
31247 + header.magic = PROF_MAGIC_MAPS;
31248 + header.page_shift = PAGE_SHIFT;
31250 + if (copy_to_user(buf, &header, sizeof(header)) != 0) {
31253 + if (copy_to_user(p, (void *)&profile_pm[*f_pos], sizeof(struct profile_map) * header.count) != 0) {
31256 + *f_pos += header.count;
31258 + return sizeof(header) + sizeof(struct profile_map) * header.count;
31261 +static int profile_maps_release(struct inode *inode, struct file *filp)
31266 +static const struct file_operations profile_maps_fops = {
31267 + .open = profile_maps_open,
31268 + .read = profile_maps_read,
31269 + .release = profile_maps_release,
31272 +static int profile_rate_show(struct seq_file *m, void *v)
31275 + seq_printf(m, "%d samples per second. %d virtual counters.\n", node->rate, node->num_counters);
31277 + seq_printf(m, "Profiler is not initialized.\n");
31282 +static int profile_rate_open(struct inode *inode, struct file *filp)
31284 + return single_open(filp, profile_rate_show, NULL);
31287 +static int profile_rate_write(struct file *filp, const char *buf, size_t len, loff_t *off)
31293 +static const struct file_operations profile_rate_fops = {
31294 + .open = profile_rate_open,
31295 + .read = seq_read,
31296 + .llseek = seq_lseek,
31297 + .release = single_release,
31298 + .write = profile_rate_write,
31301 +int ubi32_profile_init_module(void)
31303 + struct proc_dir_entry *pdir;
31306 + * find the device
31308 + node = (struct profilenode *)devtree_find_node("profiler");
31310 + printk(KERN_INFO "Profiler does not exist.\n");
31315 + * allocate the sample buffer
31317 + node->max_samples = PROFILE_MAX_SAMPLES;
31318 + node->samples = kmalloc(node->max_samples * sizeof(struct profile_sample), GFP_KERNEL);
31319 + if (!node->samples) {
31320 + printk(KERN_INFO "Profiler sample buffer kmalloc failed.\n");
31325 + * connect to the file system
31327 + pdir = proc_mkdir("profile", NULL);
31331 + if (!proc_create("data", 0, pdir, &profile_fops)) {
31334 + if (!proc_create("rate", 0, pdir, &profile_rate_fops)) {
31337 + if (!proc_create("maps", 0, pdir, &profile_maps_fops)) {
31344 +module_init(ubi32_profile_init_module);
31346 +MODULE_AUTHOR("David Fotland");
31347 +MODULE_LICENSE("GPL");
31348 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/profile.h linux-2.6.30.10-ubi/arch/ubicom32/mach-common/profile.h
31349 --- linux-2.6.30.10/arch/ubicom32/mach-common/profile.h 1970-01-01 02:00:00.000000000 +0200
31350 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/profile.h 2009-12-11 11:45:11.000000000 +0200
31353 + * arch/ubicom32/mach-common/profile.h
31354 + * Private data for the profile module
31356 + * (C) Copyright 2009, Ubicom, Inc.
31358 + * This file is part of the Ubicom32 Linux Kernel Port.
31360 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
31361 + * it and/or modify it under the terms of the GNU General Public License
31362 + * as published by the Free Software Foundation, either version 2 of the
31363 + * License, or (at your option) any later version.
31365 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
31366 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
31367 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
31368 + * the GNU General Public License for more details.
31370 + * You should have received a copy of the GNU General Public License
31371 + * along with the Ubicom32 Linux Kernel Port. If not,
31372 + * see <http://www.gnu.org/licenses/>.
31374 + * Ubicom32 implementation derived from (with many thanks):
31380 +#include <linux/types.h>
31381 +#include <asm/devtree.h>
31382 +#include "profpkt.h"
31384 +#ifndef _PROFILE_H_
31385 +#define _PROFILE_H_
31387 +#define PROFILE_MAX_THREADS 16
31388 +#define PROFILE_MAX_SAMPLES 1024
31390 +struct profile_sample;
31391 +struct oprofile_sample;
31394 + * values chosen so all counter values fit in a single UDP packet
31396 +#define PROFILE_NODE_MAX_COUNTERS 32
31398 +struct profile_counter {
31399 + char name[PROFILE_COUNTER_NAME_LENGTH];
31400 + unsigned int value;
31403 +struct profilenode {
31404 + struct devtree_node dn;
31405 + volatile u32_t enabled; /* Is the profiler enabled to take samples? */
31406 + volatile u32_t busy; /* set when the samples are being read by the driver */
31407 + volatile u32_t rate; /* What is the sampling rate? */
31408 + volatile u32_t enabled_threads; /* which threads were enabled at the last sample time */
31409 + volatile u32_t hrt; /* HRT threads */
31410 + volatile u32_t profiler_thread; /* thread running the profile sampler */
31411 + volatile u32_t clocks; /* system clock timer at last sample */
31412 + volatile u32_t clock_freq; /* clock frequency in Hz */
31413 + volatile u32_t ddr_freq; /* memory frequency */
31414 + volatile u32_t cpu_id; /* chip_id register */
31415 + volatile u32_t inst_count[PROFILE_MAX_THREADS]; /* sampled instruction counts at most recent sample */
31416 + volatile u32_t stats[4]; /* contents of the cache statistics counters */
31417 + volatile u16_t head; /* sample taker puts samples here */
31418 + volatile u16_t tail; /* packet filler takes samples here */
31419 + volatile u16_t count; /* number of valid samples */
31420 + volatile u16_t max_samples; /* how many samples can be in the samples array */
31421 + struct profile_sample *samples; /* samples array allocated by the linux driver */
31422 + volatile u32_t num_counters; /* how many registered performance counters */
31423 + volatile struct profile_counter counters[PROFILE_NODE_MAX_COUNTERS];
31425 + /* unimplemented interface for future oprofile work */
31426 + volatile u16_t oprofile_head; /* sample taker puts samples here */
31427 + volatile u16_t oprofile_tail; /* packet filler takes samples here */
31428 + volatile u16_t oprofile_count; /* how many oprofile sampels are are in use */
31429 + volatile u16_t oprofile_max_samples; /* samples array size for oprofile samples */
31430 + struct oprofile_sample *oprofile_samples; /* oprofile sample buffer */
31434 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/profpkt.h linux-2.6.30.10-ubi/arch/ubicom32/mach-common/profpkt.h
31435 --- linux-2.6.30.10/arch/ubicom32/mach-common/profpkt.h 1970-01-01 02:00:00.000000000 +0200
31436 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/profpkt.h 2009-12-11 11:45:11.000000000 +0200
31440 + * arch/ubicom32/mach-common/profpkt.c
31441 + * Ubicom32 Profiler packet formats for communication between the linux proc driver and the profiler display tool
31443 + * (C) Copyright 2009, Ubicom, Inc.
31445 + * This file is part of the Ubicom32 Linux Kernel Port.
31447 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
31448 + * it and/or modify it under the terms of the GNU General Public License
31449 + * as published by the Free Software Foundation, either version 2 of the
31450 + * License, or (at your option) any later version.
31452 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
31453 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
31454 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
31455 + * the GNU General Public License for more details.
31457 + * You should have received a copy of the GNU General Public License
31458 + * along with the Ubicom32 Linux Kernel Port. If not,
31459 + * see <http://www.gnu.org/licenses/>.
31462 +#define PROFILE_PORT 51080
31463 +#define PROFILE_POSIX_NAME_LENGTH 32
31466 + * profile UDP packet format for communicating between ip3k and host
31468 + * every packet starts with a header, followed by samples.
31469 + * samples are only taken for non-hrt threads that are
31472 +#define PROF_MAGIC 0x3ea0
31473 +#define PROF_MAGIC_COUNTERS 0x9ea0
31474 +#define PROF_MAGIC_MAPS 0xaea0
31477 + * Versions (31 max):
31478 + * 1 to 4 were before 6.0 release, development versions
31479 + * 5 was forward compatible version, shipped with 6.0 and 6.1
31480 + * 6 adds heap packets, and clock_freq to header, shipped with 6.2
31481 + * 7 adds a sequence numbers to check for dropped packets, shipped with 6.3.5
31482 + * 8 adds mqueue timing information, shipped with 6.3.5
31483 + * 9 adds sdram heap size information, shipped with 6.4
31484 + * 10 adds heapmem heap callers and long latency stack traces. shipped with 6.4
31485 + * 11 adds support for Mars (IP5K). shipped with 6.10
31486 + * 12 adds more support for Mars. Shipped with 7.0
31487 + * 13 adds per sample latency measurement. Shipped with 7.2
31488 + * 14 changes the heap format and adds a string packet. Shipped with 7.4
31489 + * 15 adds dsr stats and posix. shipped with 7.6
31490 + * 16 corrects maximum packet count for Ares. ships with 7.9
31491 + * 17 adds a5 register value to sample
31494 +#define PROFILE_VERSION 17
31495 +#define PROFILE_MAX_PACKET_SIZE 1440
31497 +#define PROFILE_MAX_THREADS 16
31500 + * each packet starts with a profile_header, then sample_count samples
31501 + * samples are gprof samples of pc, the return address, condition codes, and
31504 +struct profile_header {
31505 + u16_t magic; /* magic number and version */
31506 + u8_t header_size; /* number of bytes in profile header */
31507 + u8_t sample_count; /* number of samples in the packet */
31508 + u32_t clocks; /* clock counter value */
31509 + u32_t instruction_count[PROFILE_MAX_THREADS];
31510 + /* instructions executed per thread */
31511 + u32_t profile_instructions; /* instructions executed by profiler mainline */
31512 + u16_t enabled; /* which threads are enabled */
31513 + u16_t hrt; /* which threads are hrt */
31514 + u16_t high; /* which threads are high priority */
31515 + u16_t profiler_thread; /* which thread runs the profiler */
31516 + u32_t heap_free; /* current free on-cihp heap space in bytes */
31517 + u32_t heap_low_water; /* on-chip heap low water mark */
31518 + u32_t netpage_free; /* number of free on-chip net pages */
31519 + u32_t netpage_low_water; /* low water mark on free on-chip netpages */
31520 + u32_t min_sp[PROFILE_MAX_THREADS];
31521 + /* stack pointer values per thread */
31522 + u32_t clock_freq; /* clock frequency (Hz) of system being analyzed */
31523 + u32_t seq_num; /* to detect dropped profiler packets */
31524 + u32_t timing_sequence; /* sample number since boot */
31525 + u32_t timing_interval; /* second per sample timing interval */
31526 + u32_t timing_worst_time; /* duration of longest finction called, in core clocks */
31527 + u32_t timing_function; /* address of longest function */
31528 + u32_t timing_average; /* average time of all functions in last interval */
31529 + u32_t timing_count; /* number of functions called in last interval */
31530 + u32_t extheap_free; /* current free extmem heap space in bytes */
31531 + u32_t extheap_low_water; /* extmem heap low water mark */
31532 + u32_t cpu_id; /* CHIP_ID register contents */
31533 + u32_t perf_counters[4]; /* contents of the CPU performance counters */
31534 + u8_t perf_config[4]; /* what is being counted */
31535 + u32_t ddr_freq; /* DDR clock frequency */
31536 + u32_t extnetpage_free; /* number of free off chip net pages */
31537 + u32_t extnetpage_low_water; /* low water mark on off-chip free netpages */
31538 + u32_t dsr_max_latency; /* max time to process a dsr interrupt, in clocks, since last packet */
31539 + u32_t dsr_ave_latency; /* average dsr latency over last DSR_STATS_RECENT_COUNT interrupts */
31540 + u32_t dsr_count; /* number of dsr interrupts since last packet */
31543 +struct profile_header_counters {
31545 + u16_t ultra_count; /* how many ultra counters follow this */
31546 + u32_t ultra_sample_time; /* in chip clocks */
31547 + u32_t linux_count; /* how many linux counters follow this */
31548 + u32_t linux_sample_time;
31552 + * values chosen so all counter values fit in a single 1400 byte UDP packet
31554 +#define PROFILE_COUNTER_NAME_LENGTH 20
31555 +#define PROFILE_MAX_COUNTERS ((PROFILE_MAX_PACKET_SIZE - sizeof(struct profile_header_counters)) / (PROFILE_COUNTER_NAME_LENGTH + 4))
31557 +struct profile_counter_pkt {
31558 + char name[PROFILE_COUNTER_NAME_LENGTH];
31559 + unsigned int value;
31563 + * send memory maps from linux to profiler tool
31566 +struct profile_header_maps {
31569 + u32_t page_shift;
31572 +#define PROFILE_MAP_NUM_TYPES 32
31574 +/* types 0-15: size field is order. True size is 2^order */
31575 +#define PROFILE_MAP_TYPE_UNKNOWN 0
31576 +#define PROFILE_MAP_TYPE_FREE 1
31577 +#define PROFILE_MAP_TYPE_SMALL 2
31578 +#define PROFILE_MAP_TYPE_FS 3
31579 +/* types 16-31: size field is pages. True size is (1 << PAGE_SHIFT) * size */
31580 +#define PROFILE_MAP_SIZE_TYPE 16
31581 +#define PROFILE_MAP_TYPE_TEXT 16
31582 +#define PROFILE_MAP_TYPE_STACK 17
31583 +#define PROFILE_MAP_TYPE_APP_DATA 18
31584 +#define PROFILE_MAP_TYPE_CACHE 19
31585 +#define PROFILE_MAP_RESERVED 24
31587 +#define PROFILE_MAP_TYPE_SHIFT 11
31588 +#define PROFILE_MAP_SIZE_MASK 0x7ff
31590 +struct profile_map {
31591 + u16_t start; /* start page number of segment, relative to start of DRAM */
31592 + u16_t type_size; /* type (4 bits) of the segment and size in pages (12 bits) */
31595 +#define PROFILE_MAX_MAPS (PROFILE_MAX_PACKET_SIZE - sizeof(struct profile_header_maps)) / sizeof(struct profile_map)
31596 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/ring_tio.c linux-2.6.30.10-ubi/arch/ubicom32/mach-common/ring_tio.c
31597 --- linux-2.6.30.10/arch/ubicom32/mach-common/ring_tio.c 1970-01-01 02:00:00.000000000 +0200
31598 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/ring_tio.c 2009-12-11 11:45:11.000000000 +0200
31601 + * arch/ubicom32/mach-common/ring_tio.c
31602 + * Generic initialization for UIO Ubicom32 Ring
31604 + * (C) Copyright 2009, Ubicom, Inc.
31606 + * This file is part of the Ubicom32 Linux Kernel Port.
31608 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
31609 + * it and/or modify it under the terms of the GNU General Public License
31610 + * as published by the Free Software Foundation, either version 2 of the
31611 + * License, or (at your option) any later version.
31613 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
31614 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
31615 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
31616 + * the GNU General Public License for more details.
31618 + * You should have received a copy of the GNU General Public License
31619 + * along with the Ubicom32 Linux Kernel Port. If not,
31620 + * see <http://www.gnu.org/licenses/>.
31623 +#include <linux/platform_device.h>
31624 +#include <linux/types.h>
31626 +#include <asm/devtree.h>
31627 +#include <asm/ring_tio.h>
31629 +static const char *ring_tio_driver_name = "uio_ubicom32ring";
31632 + * The number of ring_tio's currently allocated, used for .id
31634 +static int __initdata ring_tio_count;
31637 + * The maximum number of resources that the ring_tio will have.
31638 + * Currently 3, a register space, and up to 2 interrupts.
31640 +#define RING_TIO_MAX_RESOURCES 3
31644 + * Checks the device tree and instantiates the driver if found
31646 +void __init ring_tio_init(const char *node_name)
31648 + struct platform_device *pdev;
31649 + struct resource *res;
31650 + int resource_idx = 0;
31651 + struct ring_tio_node *ring_node;
31654 + * Check the device tree for the ring_tio
31656 + ring_node = (struct ring_tio_node *)devtree_find_node(node_name);
31657 + if (!ring_node) {
31658 + printk(KERN_WARNING "Ring TIO '%s' not found\n", node_name);
31662 + if (ring_node->version != RING_TIO_NODE_VERSION) {
31663 + printk(KERN_WARNING "ring_tio not compatible\n");
31668 + * Dynamically create the platform_device structure and resources
31670 + pdev = kzalloc(sizeof(struct platform_device), GFP_KERNEL);
31672 + printk(KERN_WARNING "ring_tio could not alloc pdev\n");
31676 + res = kzalloc(sizeof(struct resource) * RING_TIO_MAX_RESOURCES,
31680 + printk(KERN_WARNING "ring_tio could not alloc res\n");
31684 + pdev->name = ring_tio_driver_name;
31685 + pdev->id = ring_tio_count++;
31686 + pdev->resource = res;
31689 + * Fill in the resources and platform data from devtree information
31691 + res[resource_idx].start = (u32_t)(ring_node->regs);
31692 + res[resource_idx].end = (u32_t)(ring_node->regs);
31693 + res[resource_idx].flags = IORESOURCE_MEM;
31696 + if (ring_node->dn.sendirq != 0xFF) {
31697 + res[resource_idx].start = ring_node->dn.sendirq;
31698 + res[resource_idx].flags = IORESOURCE_IRQ;
31702 + if (ring_node->dn.recvirq != 0xFF) {
31703 + res[resource_idx].start = ring_node->dn.recvirq;
31704 + res[resource_idx].flags = IORESOURCE_IRQ;
31707 + pdev->num_resources = resource_idx;
31709 + printk(KERN_INFO "RingTIO.%d '%s' found irq=%d/%d regs=%p pdev=%p/%p\n",
31710 + ring_tio_count - 1, node_name, ring_node->dn.sendirq,
31711 + ring_node->dn.recvirq, ring_node->regs, pdev, res);
31714 + * Try to get the device registered
31716 + pdev->dev.platform_data = (void *)node_name;
31717 + if (platform_device_register(pdev) < 0) {
31718 + printk(KERN_WARNING "Ring failed to register\n");
31723 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/switch-bcm539x.c linux-2.6.30.10-ubi/arch/ubicom32/mach-common/switch-bcm539x.c
31724 --- linux-2.6.30.10/arch/ubicom32/mach-common/switch-bcm539x.c 1970-01-01 02:00:00.000000000 +0200
31725 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/switch-bcm539x.c 2009-12-11 11:45:11.000000000 +0200
31728 + * arch/ubicom32/mach-common/switch-bcm539x.c
31729 + * BCM539X switch driver, SPI mode
31731 + * (C) Copyright 2009, Ubicom, Inc.
31733 + * This file is part of the Ubicom32 Linux Kernel Port.
31735 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
31736 + * it and/or modify it under the terms of the GNU General Public License
31737 + * as published by the Free Software Foundation, either version 2 of the
31738 + * License, or (at your option) any later version.
31740 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
31741 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
31742 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
31743 + * the GNU General Public License for more details.
31745 + * You should have received a copy of the GNU General Public License
31746 + * along with the Ubicom32 Linux Kernel Port. If not,
31747 + * see <http://www.gnu.org/licenses/>.
31749 + * Ubicom32 implementation derived from (with many thanks):
31755 +#include <linux/platform_device.h>
31756 +#include <linux/spi/spi.h>
31757 +#include <linux/gpio.h>
31758 +#include <linux/delay.h>
31759 +#include <linux/mii.h>
31761 +#include <asm/switch-dev.h>
31762 +#include <asm/ubicom32-spi-gpio.h>
31763 +#include "switch-core.h"
31764 +#include "switch-bcm539x-reg.h"
31766 +#define DRIVER_NAME "bcm539x-spi"
31767 +#define DRIVER_VERSION "1.0"
31769 +#undef BCM539X_DEBUG
31770 +#define BCM539X_SPI_RETRIES 100
31772 +struct bcm539x_data {
31773 + struct switch_device *switch_dev;
31776 + * Our private data
31778 + struct spi_device *spi;
31779 + struct switch_core_platform_data *pdata;
31782 + * Last page we accessed
31793 + * bcm539x_wait_status
31794 + * Waits for the specified bit in the status register to be set/cleared.
31796 +static int bcm539x_wait_status(struct bcm539x_data *bd, u8_t mask, int set)
31803 + txbuf[0] = BCM539X_CMD_READ;
31804 + txbuf[1] = BCM539X_GLOBAL_SPI_STATUS;
31805 + for (i = 0; i < BCM539X_SPI_RETRIES; i++) {
31806 + ret = spi_write_then_read(bd->spi, txbuf, 2, &rxbuf, 1);
31808 + if ((set && rxbuf) || (!set && !rxbuf)) {
31818 + * bcm539x_set_page
31819 + * Sets the register page for access (only if necessary)
31821 +static int bcm539x_set_page(struct bcm539x_data *bd, u8_t page)
31825 + if (page == bd->last_page) {
31829 + bd->last_page = page;
31831 + txbuf[0] = BCM539X_CMD_WRITE;
31832 + txbuf[1] = BCM539X_GLOBAL_PAGE;
31835 + return spi_write(bd->spi, txbuf, 3);
31839 + * bcm539x_write_bytes
31840 + * Writes a number of bytes to a given page and register
31842 +static int bcm539x_write_bytes(struct bcm539x_data *bd, u8_t page,
31843 + u8_t reg, void *buf, u8_t len)
31848 + txbuf = kmalloc(2 + len, GFP_KERNEL);
31854 + * Make sure the chip has finished processing our previous request
31856 + ret = bcm539x_wait_status(bd, BCM539X_GLOBAL_SPI_ST_SPIF, 0);
31864 + ret = bcm539x_set_page(bd, page);
31872 + txbuf[0] = BCM539X_CMD_WRITE;
31874 + memcpy(&txbuf[2], buf, len);
31876 +#ifdef BCM539X_DEBUG
31879 + printk("write page %02x reg %02x len=%d buf=", page, reg, len);
31880 + for (i = 0; i < len + 2; i++) {
31881 + printk("%02x ", txbuf[i]);
31887 + ret = spi_write(bd->spi, txbuf, 2 + len);
31895 + * bcm539x_write_32
31896 + * Writes 32 bits of data to the given page and register
31898 +static inline int bcm539x_write_32(struct bcm539x_data *bd, u8_t page,
31899 + u8_t reg, u32_t data)
31901 + data = cpu_to_le32(data);
31902 + return bcm539x_write_bytes(bd, page, reg, &data, 4);
31906 + * bcm539x_write_16
31907 + * Writes 16 bits of data to the given page and register
31909 +static inline int bcm539x_write_16(struct bcm539x_data *bd, u8_t page,
31910 + u8_t reg, u16_t data)
31912 + data = cpu_to_le16(data);
31913 + return bcm539x_write_bytes(bd, page, reg, &data, 2);
31917 + * bcm539x_write_8
31918 + * Writes 8 bits of data to the given page and register
31920 +static inline int bcm539x_write_8(struct bcm539x_data *bd, u8_t page,
31921 + u8_t reg, u8_t data)
31923 + return bcm539x_write_bytes(bd, page, reg, &data, 1);
31927 + * bcm539x_read_bytes
31928 + * Reads a number of bytes from a given page and register
31930 +static int bcm539x_read_bytes(struct bcm539x_data *bd, u8_t page,
31931 + u8_t reg, void *buf, u8_t len)
31937 + * (1) Make sure the chip has finished processing our previous request
31939 + ret = bcm539x_wait_status(bd, BCM539X_GLOBAL_SPI_ST_SPIF, 0);
31945 + * (2) Set the page
31947 + ret = bcm539x_set_page(bd, page);
31953 + * (3) Kick off the register read
31955 + txbuf[0] = BCM539X_CMD_READ;
31957 + ret = spi_write_then_read(bd->spi, txbuf, 2, txbuf, 1);
31963 + * (4) Wait for RACK
31965 + ret = bcm539x_wait_status(bd, BCM539X_GLOBAL_SPI_ST_RACK, 1);
31971 + * (5) Read the data
31973 + txbuf[0] = BCM539X_CMD_READ;
31974 + txbuf[1] = BCM539X_GLOBAL_SPI_DATA0;
31976 + ret = spi_write_then_read(bd->spi, txbuf, 2, buf, len);
31978 +#ifdef BCM539X_DEBUG
31981 + printk("read page %02x reg %02x len=%d rxbuf=",
31983 + for (i = 0; i < len; i++) {
31984 + printk("%02x ", ((u8_t *)buf)[i]);
31994 + * bcm539x_read_32
31995 + * Reads an 32 bit number from a given page and register
31997 +static int bcm539x_read_32(struct bcm539x_data *bd, u8_t page,
31998 + u8_t reg, u32_t *buf)
32000 + int ret = bcm539x_read_bytes(bd, page, reg, buf, 4);
32001 + *buf = le32_to_cpu(*buf);
32006 + * bcm539x_read_16
32007 + * Reads an 16 bit number from a given page and register
32009 +static int bcm539x_read_16(struct bcm539x_data *bd, u8_t page,
32010 + u8_t reg, u16_t *buf)
32012 + int ret = bcm539x_read_bytes(bd, page, reg, buf, 2);
32013 + *buf = le16_to_cpu(*buf);
32019 + * Reads an 8 bit number from a given page and register
32021 +static int bcm539x_read_8(struct bcm539x_data *bd, u8_t page,
32022 + u8_t reg, u8_t *buf)
32024 + return bcm539x_read_bytes(bd, page, reg, buf, 1);
32028 + * bcm539x_set_mode
32030 +static int bcm539x_set_mode(struct bcm539x_data *bd, int state)
32035 + ret = bcm539x_read_8(bd, PAGE_PORT_TC, REG_CTRL_MODE, &buf);
32040 + buf &= ~(1 << 1);
32041 + buf |= state ? (1 << 1) : 0;
32043 + ret = bcm539x_write_8(bd, PAGE_PORT_TC, REG_CTRL_MODE, buf);
32048 + * bcm539x_handle_reset
32050 +static int bcm539x_handle_reset(struct switch_device *dev, char *buf, int inst)
32052 + struct bcm539x_data *bd =
32053 + (struct bcm539x_data *)switch_get_drvdata(dev);
32056 + ret = bcm539x_write_8(bd, PAGE_PORT_TC, REG_CTRL_SRST,
32057 + (1 << 7) | (1 << 4));
32064 + ret = bcm539x_write_8(bd, PAGE_PORT_TC, REG_CTRL_SRST, 0);
32069 + * bcm539x_handle_vlan_ports_read
32071 +static int bcm539x_handle_vlan_ports_read(struct switch_device *dev,
32072 + char *buf, int inst)
32074 + struct bcm539x_data *bd =
32075 + (struct bcm539x_data *)switch_get_drvdata(dev);
32082 + ret = bcm539x_write_16(bd, PAGE_VTBL, REG_VTBL_INDX_5395, inst);
32087 + ret = bcm539x_write_8(bd, PAGE_VTBL, REG_VTBL_ACCESS_5395,
32094 + * Wait for completion
32096 + for (j = 0; j < BCM539X_SPI_RETRIES; j++) {
32097 + ret = bcm539x_read_8(bd, PAGE_VTBL, REG_VTBL_ACCESS_5395,
32102 + if (!(rxbuf8 & (1 << 7))) {
32107 + if (j == BCM539X_SPI_RETRIES) {
32112 + * Read the table entry
32114 + ret = bcm539x_read_32(bd, PAGE_VTBL, REG_VTBL_ENTRY_5395, &rxbuf32);
32119 + for (j = 0; j < 9; j++) {
32120 + if (rxbuf32 & (1 << j)) {
32122 + len += sprintf(buf + len, "%d", j);
32123 + if (rxbuf32 & (1 << (j + 9))) {
32124 + buf[len++] = 'u';
32126 + buf[len++] = 't';
32128 + ret = bcm539x_read_16(bd, PAGE_VLAN,
32129 + REG_VLAN_PTAG0 + (j << 1),
32134 + if (rxbuf16 == inst) {
32135 + buf[len++] = '*';
32137 + buf[len++] = '\t';
32141 + len += sprintf(buf + len, "\n");
32148 + * bcm539x_handle_vlan_ports_write
32150 +static int bcm539x_handle_vlan_ports_write(struct switch_device *dev,
32151 + char *buf, int inst)
32153 + struct bcm539x_data *bd =
32154 + (struct bcm539x_data *)switch_get_drvdata(dev);
32164 + switch_parse_vlan_ports(dev, buf, &untag, &ports, &def);
32166 +#ifdef BCM539X_DEBUG
32167 + printk(KERN_DEBUG "'%s' inst=%d untag=%08x ports=%08x def=%08x\n",
32168 + buf, inst, untag, ports, def);
32176 + * Change default vlan tag
32178 + for (j = 0; j < 9; j++) {
32179 + if ((untag | def) & (1 << j)) {
32180 + ret = bcm539x_write_16(bd, PAGE_VLAN,
32181 + REG_VLAN_PTAG0 + (j << 1),
32189 + if (!(dev->port_mask[0] & (1 << j))) {
32194 + * Remove any ports which are not listed anymore as members of
32197 + ret = bcm539x_read_16(bd, PAGE_VLAN,
32198 + REG_VLAN_PTAG0 + (j << 1), &rxbuf16);
32202 + if (rxbuf16 == inst) {
32203 + ret = bcm539x_write_16(bd, PAGE_VLAN,
32204 + REG_VLAN_PTAG0 + (j << 1), 0);
32212 + * Write the VLAN table
32214 + ret = bcm539x_write_16(bd, PAGE_VTBL, REG_VTBL_INDX_5395, inst);
32219 + ret = bcm539x_write_32(bd, PAGE_VTBL, REG_VTBL_ENTRY_5395,
32220 + (untag << 9) | ports);
32225 + ret = bcm539x_write_8(bd, PAGE_VTBL, REG_VTBL_ACCESS_5395,
32232 + * Wait for completion
32234 + for (j = 0; j < BCM539X_SPI_RETRIES; j++) {
32235 + ret = bcm539x_read_bytes(bd, PAGE_VTBL, REG_VTBL_ACCESS_5395,
32240 + if (!(rxbuf8 & (1 << 7))) {
32245 + return (j < BCM539X_SPI_RETRIES) ? 0 : -EIO;
32249 + * Handlers for <this_driver>/vlan/<vlan_id>
32251 +static const struct switch_handler bcm539x_switch_handlers_vlan_dir[] = {
32254 + .read = bcm539x_handle_vlan_ports_read,
32255 + .write = bcm539x_handle_vlan_ports_write,
32262 + * bcm539x_handle_vlan_delete_write
32264 +static int bcm539x_handle_vlan_delete_write(struct switch_device *dev,
32265 + char *buf, int inst)
32267 + struct bcm539x_data *bd =
32268 + (struct bcm539x_data *)switch_get_drvdata(dev);
32275 + vid = simple_strtoul(buf, NULL, 0);
32281 + * Disable this VLAN
32283 + * Go through the port-based vlan registers and clear the appropriate
32286 + for (j = 0; j < 9; j++) {
32288 + ret = bcm539x_read_16(bd, PAGE_VLAN, REG_VLAN_PTAG0 + (j << 1),
32293 + if (rxbuf16 == vid) {
32295 + ret = bcm539x_write_16(bd, PAGE_VLAN,
32296 + REG_VLAN_PTAG0 + (j << 1),
32305 + * Write the VLAN table
32308 + ret = bcm539x_write_16(bd, PAGE_VTBL, REG_VTBL_INDX_5395, txbuf);
32314 + ret = bcm539x_write_32(bd, PAGE_VTBL, REG_VTBL_ENTRY_5395, txbuf);
32319 + txbuf = (1 << 7) | (0);
32320 + ret = bcm539x_write_8(bd, PAGE_VTBL, REG_VTBL_ACCESS_5395, txbuf);
32326 + * Wait for completion
32328 + for (j = 0; j < BCM539X_SPI_RETRIES; j++) {
32329 + ret = bcm539x_read_bytes(bd, PAGE_VTBL, REG_VTBL_ACCESS_5395,
32334 + if (!(rxbuf8 & (1 << 7))) {
32339 + if (j == BCM539X_SPI_RETRIES) {
32343 + return switch_remove_vlan_dir(dev, vid);
32347 + * bcm539x_handle_vlan_create_write
32349 +static int bcm539x_handle_vlan_create_write(struct switch_device *dev,
32350 + char *buf, int inst)
32354 + vid = simple_strtoul(buf, NULL, 0);
32359 + return switch_create_vlan_dir(dev, vid,
32360 + bcm539x_switch_handlers_vlan_dir);
32364 + * bcm539x_handle_enable_read
32366 +static int bcm539x_handle_enable_read(struct switch_device *dev,
32367 + char *buf, int inst)
32369 + struct bcm539x_data *bd =
32370 + (struct bcm539x_data *)switch_get_drvdata(dev);
32374 + ret = bcm539x_read_8(bd, PAGE_PORT_TC, REG_CTRL_MODE, &rxbuf);
32378 + rxbuf = (rxbuf & (1 << 1)) ? 1 : 0;
32380 + return sprintf(buf, "%d\n", rxbuf);
32384 + * bcm539x_handle_enable_write
32386 +static int bcm539x_handle_enable_write(struct switch_device *dev,
32387 + char *buf, int inst)
32389 + struct bcm539x_data *bd =
32390 + (struct bcm539x_data *)switch_get_drvdata(dev);
32392 + return bcm539x_set_mode(bd, buf[0] == '1');
32396 + * bcm539x_handle_enable_vlan_read
32398 +static int bcm539x_handle_enable_vlan_read(struct switch_device *dev,
32399 + char *buf, int inst)
32401 + struct bcm539x_data *bd =
32402 + (struct bcm539x_data *)switch_get_drvdata(dev);
32406 + ret = bcm539x_read_8(bd, PAGE_VLAN, REG_VLAN_CTRL0, &rxbuf);
32410 + rxbuf = (rxbuf & (1 << 7)) ? 1 : 0;
32412 + return sprintf(buf, "%d\n", rxbuf);
32416 + * bcm539x_handle_enable_vlan_write
32418 +static int bcm539x_handle_enable_vlan_write(struct switch_device *dev,
32419 + char *buf, int inst)
32421 + struct bcm539x_data *bd =
32422 + (struct bcm539x_data *)switch_get_drvdata(dev);
32426 + * disable 802.1Q VLANs
32428 + if (buf[0] != '1') {
32429 + ret = bcm539x_write_8(bd, PAGE_VLAN, REG_VLAN_CTRL0, 0);
32434 + * enable 802.1Q VLANs
32436 + * Enable 802.1Q | IVL learning
32438 + ret = bcm539x_write_8(bd, PAGE_VLAN, REG_VLAN_CTRL0,
32439 + (1 << 7) | (3 << 5));
32445 + * RSV multicast fwd | RSV multicast chk
32447 + ret = bcm539x_write_8(bd, PAGE_VLAN, REG_VLAN_CTRL1,
32448 + (1 << 2) | (1 << 3));
32454 + * Drop invalid VID
32456 + ret = bcm539x_write_16(bd, PAGE_VLAN, REG_VLAN_CTRL3, 0x00FF);
32465 + * bcm539x_handle_port_enable_read
32467 +static int bcm539x_handle_port_enable_read(struct switch_device *dev,
32468 + char *buf, int inst)
32470 + return sprintf(buf, "%d\n", 1);
32474 + * bcm539x_handle_port_enable_write
32476 +static int bcm539x_handle_port_enable_write(struct switch_device *dev,
32477 + char *buf, int inst)
32482 + if (!(dev->port_mask[0] & (1 << inst))) {
32486 + if (buf[0] != '1') {
32487 + printk(KERN_WARNING "switch port[%d] disabling is not supported\n", inst);
32493 + * bcm539x_handle_port_state_read
32495 +static int bcm539x_handle_port_state_read(struct switch_device *dev,
32496 + char *buf, int inst)
32498 + struct bcm539x_data *bd =
32499 + (struct bcm539x_data *)switch_get_drvdata(dev);
32506 + if (!(dev->port_mask[0] & (1 << inst))) {
32511 + * check PHY link state - CPU port (port 8) is always up
32513 + ret = bcm539x_read_16(bd, PAGE_STATUS, REG_LINK_STATUS, &link);
32517 + link |= (1 << 8);
32519 + return sprintf(buf, "%d\n", (link & (1 << inst)) ? 1 : 0);
32523 + * bcm539x_handle_port_media_read
32525 +static int bcm539x_handle_port_media_read(struct switch_device *dev,
32526 + char *buf, int inst)
32528 + struct bcm539x_data *bd =
32529 + (struct bcm539x_data *)switch_get_drvdata(dev);
32531 + u16_t link, duplex;
32537 + if (!(dev->port_mask[0] & (1 << inst))) {
32542 + * check PHY link state first - CPU port (port 8) is always up
32544 + ret = bcm539x_read_16(bd, PAGE_STATUS, REG_LINK_STATUS, &link);
32548 + link |= (1 << 8);
32550 + if (!(link & (1 << inst))) {
32551 + return sprintf(buf, "UNKNOWN\n");
32555 + * get link speeda dn duplex - CPU port (port 8) is 1000/full
32557 + ret = bcm539x_read_32(bd, PAGE_STATUS, 4, &speed);
32561 + speed |= (2 << 16);
32562 + speed = (speed >> (2 * inst)) & 3;
32564 + ret = bcm539x_read_16(bd, PAGE_STATUS, 8, &duplex);
32568 + duplex |= (1 << 8);
32569 + duplex = (duplex >> inst) & 1;
32571 + return sprintf(buf, "%d%cD\n",
32572 + (speed == 0) ? 10 : ((speed == 1) ? 100 : 1000),
32573 + duplex ? 'F' : 'H');
32577 + * bcm539x_handle_port_meida_write
32579 +static int bcm539x_handle_port_meida_write(struct switch_device *dev,
32580 + char *buf, int inst)
32582 + struct bcm539x_data *bd =
32583 + (struct bcm539x_data *)switch_get_drvdata(dev);
32585 + u16_t ctrl_word, local_cap, local_giga_cap;
32588 + * validate port (not for CPU port)
32590 + if (!(dev->port_mask[0] & (1 << inst) & ~(1 << 8))) {
32595 + * Get the maximum capability from status
32596 + * SPI reg[0x00] = PHY[0x0] --- MII control
32597 + * SPI reg[0x08] = PHY[0x4] --- MII local capability
32598 + * SPI reg[0x12] = PHY[0x9] --- GMII control
32600 + ret = bcm539x_read_16(bd, REG_MII_PAGE + inst, (MII_ADVERTISE << 1), &local_cap);
32604 + ret = bcm539x_read_16(bd, REG_MII_PAGE + inst, (MII_CTRL1000 << 1), &local_giga_cap);
32609 + /* Configure to the requested speed */
32610 + if (strncmp(buf, "1000FD", 6) == 0) {
32612 + local_cap &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL);
32613 + local_cap &= ~(ADVERTISE_100HALF | ADVERTISE_100FULL);
32614 + local_giga_cap |= (ADVERTISE_1000HALF | ADVERTISE_1000FULL);
32616 + } else if (strncmp(buf, "100FD", 5) == 0) {
32618 + local_cap &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL);
32619 + local_cap |= (ADVERTISE_100HALF | ADVERTISE_100FULL);
32620 + local_giga_cap &= ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL);
32622 + local_cap &= ~(ADVERTISE_100HALF);
32623 + } else if (strncmp(buf, "100HD", 5) == 0) {
32625 + local_cap &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL);
32626 + local_cap |= (ADVERTISE_100HALF | ADVERTISE_100FULL);
32627 + local_giga_cap &= ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL);
32629 + local_cap &= ~(ADVERTISE_100FULL);
32630 + } else if (strncmp(buf, "10FD", 4) == 0) {
32632 + local_cap |= (ADVERTISE_10HALF | ADVERTISE_10FULL);
32633 + local_cap &= ~(ADVERTISE_100HALF | ADVERTISE_100FULL);
32634 + local_giga_cap &= ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL);
32636 + local_cap &= ~(ADVERTISE_10HALF);
32637 + } else if (strncmp(buf, "10HD", 4) == 0) {
32639 + local_cap |= (ADVERTISE_10HALF | ADVERTISE_10FULL);
32640 + local_cap &= ~(ADVERTISE_100HALF | ADVERTISE_100FULL);
32641 + local_giga_cap &= ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL);
32643 + local_cap &= ~(ADVERTISE_10FULL);
32644 + } else if (strncmp(buf, "AUTO", 4) == 0) {
32646 + local_cap |= (ADVERTISE_10HALF | ADVERTISE_10FULL);
32647 + local_cap |= (ADVERTISE_100HALF | ADVERTISE_100FULL);
32648 + local_giga_cap |= (ADVERTISE_1000HALF | ADVERTISE_1000FULL);
32653 + /* Active PHY with the requested speed for auto-negotiation */
32654 + ret = bcm539x_write_16(bd, REG_MII_PAGE + inst, (MII_ADVERTISE << 1), local_cap);
32658 + ret = bcm539x_write_16(bd, REG_MII_PAGE + inst, (MII_CTRL1000 << 1), local_giga_cap);
32663 + ret = bcm539x_read_16(bd, REG_MII_PAGE + inst, (MII_BMCR << 1), &ctrl_word);
32667 + ctrl_word |= (BMCR_ANENABLE | BMCR_ANRESTART);
32668 + ret = bcm539x_write_16(bd, REG_MII_PAGE + inst, (MII_BMCR << 1), ctrl_word);
32677 + * proc_fs entries for this switch
32679 +static const struct switch_handler bcm539x_switch_handlers[] = {
32681 + .name = "enable",
32682 + .read = bcm539x_handle_enable_read,
32683 + .write = bcm539x_handle_enable_write,
32686 + .name = "enable_vlan",
32687 + .read = bcm539x_handle_enable_vlan_read,
32688 + .write = bcm539x_handle_enable_vlan_write,
32692 + .write = bcm539x_handle_reset,
32699 + * Handlers for <this_driver>/vlan
32701 +static const struct switch_handler bcm539x_switch_handlers_vlan[] = {
32703 + .name = "delete",
32704 + .write = bcm539x_handle_vlan_delete_write,
32707 + .name = "create",
32708 + .write = bcm539x_handle_vlan_create_write,
32715 + * Handlers for <this_driver>/port/<port number>
32717 +static const struct switch_handler bcm539x_switch_handlers_port[] = {
32719 + .name = "enable",
32720 + .read = bcm539x_handle_port_enable_read,
32721 + .write = bcm539x_handle_port_enable_write,
32725 + .read = bcm539x_handle_port_state_read,
32729 + .read = bcm539x_handle_port_media_read,
32730 + .write = bcm539x_handle_port_meida_write,
32739 +static int __devinit bcm539x_probe(struct spi_device *spi)
32741 + struct bcm539x_data *bd;
32742 + struct switch_core_platform_data *pdata;
32743 + struct switch_device *switch_dev = NULL;
32747 + pdata = spi->dev.platform_data;
32752 + ret = spi_setup(spi);
32758 + * Reset the chip if requested
32760 + if (pdata->flags & SWITCH_DEV_FLAG_HW_RESET) {
32761 + ret = gpio_request(pdata->pin_reset, "switch-bcm539x-reset");
32763 + printk(KERN_WARNING "Could not request reset\n");
32767 + gpio_direction_output(pdata->pin_reset, 0);
32769 + gpio_set_value(pdata->pin_reset, 1);
32774 + * Allocate our private data structure
32776 + bd = kzalloc(sizeof(struct bcm539x_data), GFP_KERNEL);
32781 + dev_set_drvdata(&spi->dev, bd);
32782 + bd->pdata = pdata;
32784 + bd->last_page = 0xFF;
32787 + * First perform SW reset if needed
32789 + if (pdata->flags & SWITCH_DEV_FLAG_SW_RESET) {
32790 + txbuf[0] = (1 << 7) | (1 << 4);
32791 + ret = bcm539x_write_bytes(bd, PAGE_PORT_TC,
32792 + REG_CTRL_SRST, txbuf, 1);
32800 + ret = bcm539x_write_bytes(bd, PAGE_PORT_TC,
32801 + REG_CTRL_SRST, txbuf, 1);
32808 + * See if we can see the chip
32810 + for (i = 0; i < 10; i++) {
32811 + ret = bcm539x_read_bytes(bd, PAGE_MMR, REG_DEVICE_ID,
32812 + &bd->device_id, 1);
32822 + * We only support 5395, 5397, 5398
32824 + if ((bd->device_id != 0x95) && (bd->device_id != 0x97) &&
32825 + (bd->device_id != 0x98)) {
32831 + * Override CPU port config: fixed link @1000 with flow control
32833 + ret = bcm539x_read_8(bd, PAGE_PORT_TC, REG_CTRL_MIIPO, txbuf);
32834 + bcm539x_write_8(bd, PAGE_PORT_TC, REG_CTRL_MIIPO, 0xbb); // Override IMP port config
32835 + printk("Broadcom SW CPU port setting: 0x%x -> 0xbb\n", txbuf[0]);
32838 + * Setup the switch driver structure
32840 + switch_dev = switch_alloc();
32841 + if (!switch_dev) {
32845 + switch_dev->name = pdata->name;
32847 + switch_dev->ports = (bd->device_id == 0x98) ? 9 : 6;
32848 + switch_dev->port_mask[0] = (bd->device_id == 0x98) ? 0x1FF : 0x11F;
32849 + switch_dev->driver_handlers = bcm539x_switch_handlers;
32850 + switch_dev->reg_handlers = NULL;
32851 + switch_dev->vlan_handlers = bcm539x_switch_handlers_vlan;
32852 + switch_dev->port_handlers = bcm539x_switch_handlers_port;
32854 + bd->switch_dev = switch_dev;
32855 + switch_set_drvdata(switch_dev, (void *)bd);
32857 + ret = switch_register(bd->switch_dev);
32862 + printk(KERN_INFO "bcm53%02x switch chip initialized\n", bd->device_id);
32867 + if (switch_dev) {
32868 + switch_release(switch_dev);
32870 + dev_set_drvdata(&spi->dev, NULL);
32875 +static int __attribute__((unused)) bcm539x_remove(struct spi_device *spi)
32877 + struct bcm539x_data *bd;
32879 + bd = dev_get_drvdata(&spi->dev);
32881 + if (bd->pdata->flags & SWITCH_DEV_FLAG_HW_RESET) {
32882 + gpio_free(bd->pdata->pin_reset);
32885 + if (bd->switch_dev) {
32886 + switch_unregister(bd->switch_dev);
32887 + switch_release(bd->switch_dev);
32890 + dev_set_drvdata(&spi->dev, NULL);
32897 +static struct spi_driver bcm539x_driver = {
32899 + .name = DRIVER_NAME,
32900 + .owner = THIS_MODULE,
32902 + .probe = bcm539x_probe,
32903 + .remove = __devexit_p(bcm539x_remove),
32906 +static int __init bcm539x_init(void)
32908 + return spi_register_driver(&bcm539x_driver);
32911 +module_init(bcm539x_init);
32913 +static void __exit bcm539x_exit(void)
32915 + spi_unregister_driver(&bcm539x_driver);
32917 +module_exit(bcm539x_exit);
32919 +MODULE_AUTHOR("Pat Tjin");
32920 +MODULE_LICENSE("GPL v2");
32921 +MODULE_DESCRIPTION("bcm539x SPI switch chip driver");
32922 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/switch-bcm539x-reg.h linux-2.6.30.10-ubi/arch/ubicom32/mach-common/switch-bcm539x-reg.h
32923 --- linux-2.6.30.10/arch/ubicom32/mach-common/switch-bcm539x-reg.h 1970-01-01 02:00:00.000000000 +0200
32924 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/switch-bcm539x-reg.h 2009-12-11 11:45:11.000000000 +0200
32927 + * arch/ubicom32/mach-common/switch-bcm539x-reg.h
32928 + * Broadcom switch definitions for Ubicom32 architecture.
32930 + * (C) Copyright 2009, Ubicom, Inc.
32932 + * This file is part of the Ubicom32 Linux Kernel Port.
32934 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
32935 + * it and/or modify it under the terms of the GNU General Public License
32936 + * as published by the Free Software Foundation, either version 2 of the
32937 + * License, or (at your option) any later version.
32939 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
32940 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
32941 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
32942 + * the GNU General Public License for more details.
32944 + * You should have received a copy of the GNU General Public License
32945 + * along with the Ubicom32 Linux Kernel Port. If not,
32946 + * see <http://www.gnu.org/licenses/>.
32948 + * Ubicom32 implementation derived from (with many thanks):
32955 + * Broadcom 53xx RoboSwitch device driver.
32957 + * Copyright 2007, Broadcom Corporation
32958 + * All Rights Reserved.
32960 + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
32961 + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
32962 + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
32963 + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
32968 +#ifndef _SWITCH_BCM539X_REG_H_
32969 +#define _SWITCH_BCM539X_REG_H_
32971 +#define BCM539X_CMD_READ 0x60
32972 +#define BCM539X_CMD_WRITE 0x61
32974 +#define BCM539X_GLOBAL_SPI_DATA0 0xf0
32976 +#define BCM539X_GLOBAL_SPI_STATUS 0xfe
32977 +#define BCM539X_GLOBAL_SPI_ST_SPIF (1<<7)
32978 +#define BCM539X_GLOBAL_SPI_ST_RACK (1<<5)
32980 +#define BCM539X_GLOBAL_PAGE 0xff
32982 +#define PAGE_PORT_TC 0x00 // Port Traffic Control Register
32984 +#define PAGE_QOS_CTL 0x30 // QoS Global Control Register
32985 +#define PAGE_QOS_TAG 0x34 // Default IEEE 802.1Q TAG Register
32987 +#define PAGE_MII_CTL_PORT0 0x10 // Internal PHY MII Register
32988 +#define PAGE_MII_CTL_PORT1 0x11
32989 +#define PAGE_MII_CTL_PORT2 0x12
32990 +#define PAGE_MII_CTL_PORT3 0x13
32991 +#define PAGE_MII_CTL_PORT4 0x14
32993 +#define PAGE_STATUS 0x01 // Status Register Page
32994 +#define PAGE_RATE_CONTROL 0x41 // Broadcast Storm Suppression Register
32996 +#define REG_GRATE_CONTROL 0x00
32998 +#define REG_LED_POWER 0x12
33000 +// Ingress Rate Control
33001 +#define REG_IRATE_CONTROLP0 0x10
33002 +#define REG_IRATE_CONTROLP1 0x14
33003 +#define REG_IRATE_CONTROLP2 0x18
33004 +#define REG_IRATE_CONTROLP3 0x1C
33005 +#define REG_IRATE_CONTROLP4 0x20
33006 +#define REG_IRATE_CONTROLP7 0x2C
33007 +#define REG_IRATE_CONTROLPI 0x30
33009 +// Egress Rate Control
33010 +#define REG_ERATE_CONTROLP0 0x80
33011 +#define REG_ERATE_CONTROLP1 0x82
33012 +#define REG_ERATE_CONTROLP2 0x84
33013 +#define REG_ERATE_CONTROLP3 0x86
33014 +#define REG_ERATE_CONTROLP4 0x88
33015 +#define REG_ERATE_CONTROLP5 0x8A
33016 +#define REG_ERATE_CONTROLP6 0x8C
33017 +#define REG_ERATE_CONTROLP7 0x8E
33018 +#define REG_ERATE_CONTROLPI 0x90
33020 +#define REG_LINK_STATUS 0x00
33022 +#define REG_TC_PORT0 0x00
33023 +#define REG_TC_PORT1 0x01
33024 +#define REG_TC_PORT2 0x02
33025 +#define REG_TC_PORT3 0x03
33026 +#define REG_TC_PORT4 0x04
33027 +#define REG_TC_PORT5 0x05
33029 +#define REG_SPEED_CTL 0x00
33030 +#define REG_SPEED_ADV100 0x08
33031 +#define REG_SPEED_ADV1000 0x12
33033 +#define REG_QOS_EN 0x00
33034 +#define REG_QOS_TAG_PORT1 0x12 // Default IEEE 802.1Q TAG, PORT 1
33035 +#define REG_QOS_TAG_PORT2 0x14 // Default IEEE 802.1Q TAG, PORT 2
33036 +#define REG_QOS_TAG_PORT3 0x16 // Default IEEE 802.1Q TAG, PORT 3
33037 +#define REG_QOS_TAG_PORT4 0x18 // Default IEEE 802.1Q TAG, PORT 4
33038 +#define REG_QOS_PID_PORT1 0x52 // Ingress Port Priority ID MAP, PORT 1
33039 +#define REG_QOS_PID_PORT2 0x54 // Ingress Port Priority ID MAP, PORT 2
33040 +#define REG_QOS_PID_PORT3 0x56 // Ingress Port Priority ID MAP, PORT 3
33041 +#define REG_QOS_PID_PORT4 0x58 // Ingress Port Priority ID MAP, PORT 4
33042 +#define REG_QOS_TXQ_CTL 0x80 // Tx Queue Control Register
33043 +#define REG_QOS_TXQ_WHTQ0 0x81 // Tx Queue Weight Register Queue 0
33044 +#define REG_QOS_TXQ_WHTQ1 0x82 // Tx Queue Weight Register Queue 1
33045 +#define REG_QOS_TXQ_WHTQ2 0x83 // Tx Queue Weight Register Queue 2
33046 +#define REG_QOS_TXQ_WHTQ3 0x84 // Tx Queue Weight Register Queue 3
33048 +#define REG_CTRL_PPSEL 0x24 /* 5397: Protected port select register */
33050 +#define RATE_CONTROL_ENABLED (1 << 22)
33051 +#define RATE_CONTROL_BSIZE ((1 << 10) | (1 << 9) | (1 << 8))
33053 +#define RATE_CONTROL_HIGH ((1 << 7) | (1 << 6) | (1 << 5) | (1 << 4))
33054 +#define RATE_CONTROL_HIGH_N ~((1 << 3) | (1 << 2) | (1 << 1) | (1 << 0))
33056 +#define RATE_CONTROL_MEDIUM ((1 << 6) | (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2) | (1 << 1) | (1 << 0))
33057 +#define RATE_CONTROL_MEDIUM_N ~((1 << 7))
33059 +#define RATE_CONTROL_NORMAL ((1 << 5) | (1 << 2) | (1 << 0))
33060 +#define RATE_CONTROL_NORMAL_N ~((1 << 7) | (1 << 6) | (1 << 4) | (1 << 3) | (1 << 1))
33062 +#define RATE_CONTROL_LOW ((1 << 4) | (1 << 3) | (1 << 0))
33063 +#define RATE_CONTROL_LOW_N ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 2) | (1 << 1))
33065 +// --- Gemtek, Configure the switch to support Ethernet Port QoS
33067 +/* MII access registers */
33068 +#define PSEUDO_PHYAD 0x1E /* MII Pseudo PHY address */
33069 +#define REG_MII_PAGE 0x10 /* MII Page register */
33070 +#define REG_MII_ADDR 0x11 /* MII Address register */
33071 +#define REG_MII_DATA0 0x18 /* MII Data register 0 */
33072 +#define REG_MII_DATA1 0x19 /* MII Data register 1 */
33073 +#define REG_MII_DATA2 0x1a /* MII Data register 2 */
33074 +#define REG_MII_DATA3 0x1b /* MII Data register 3 */
33076 +/* Page numbers */
33077 +#define PAGE_CTRL 0x00 /* Control page */
33078 +#define PAGE_MMR 0x02 /* 5397 Management/Mirroring page */
33079 +#define PAGE_VTBL 0x05 /* ARL/VLAN Table access page */
33080 +#define PAGE_VLAN 0x34 /* VLAN page */
33082 +/* Control page registers */
33083 +#define REG_CTRL_PORT0 0x00 /* Port 0 traffic control register */
33084 +#define REG_CTRL_PORT1 0x01 /* Port 1 traffic control register */
33085 +#define REG_CTRL_PORT2 0x02 /* Port 2 traffic control register */
33086 +#define REG_CTRL_PORT3 0x03 /* Port 3 traffic control register */
33087 +#define REG_CTRL_PORT4 0x04 /* Port 4 traffic control register */
33088 +#define REG_CTRL_PORT5 0x05 /* Port 5 traffic control register */
33089 +#define REG_CTRL_PORT6 0x06 /* Port 6 traffic control register */
33090 +#define REG_CTRL_PORT7 0x07 /* Port 7 traffic control register */
33091 +#define REG_CTRL_MODE 0x0B /* Switch Mode register */
33092 +#define REG_CTRL_MIIPO 0x0E /* 5325: MII Port Override register */
33093 +#define REG_CTRL_SRST 0x79 /* Software reset control register */
33095 +#define REG_DEVICE_ID 0x30 /* 539x Device id: */
33096 +#define DEVID5395 0x95 /* 5395 */
33097 +#define DEVID5397 0x97 /* 5397 */
33098 +#define DEVID5398 0x98 /* 5398 */
33099 +#define REG_REVISION_ID 0x40 /* 539x Revision id: */
33101 +/* VLAN page registers */
33102 +#define REG_VLAN_CTRL0 0x00 /* VLAN Control 0 register */
33103 +#define REG_VLAN_CTRL1 0x01 /* VLAN Control 1 register */
33104 +#define REG_VLAN_CTRL2 0x02 /* VLAN Control 2 register */
33105 +#define REG_VLAN_CTRL3 0x03 /* VLAN Control 3 register */
33106 +#define REG_VLAN_CTRL4 0x04 /* VLAN Control 4 register */
33107 +#define REG_VLAN_CTRL5 0x05 /* VLAN Control 5 register */
33108 +#define REG_VLAN_ACCESS 0x06 /* VLAN Table Access register */
33109 +#define REG_VLAN_WRITE 0x08 /* VLAN Write register */
33110 +#define REG_VLAN_READ 0x0C /* VLAN Read register */
33111 +#define REG_VLAN_PTAG0 0x10 /* VLAN Default Port Tag register - port 0 */
33112 +#define REG_VLAN_PTAG1 0x12 /* VLAN Default Port Tag register - port 1 */
33113 +#define REG_VLAN_PTAG2 0x14 /* VLAN Default Port Tag register - port 2 */
33114 +#define REG_VLAN_PTAG3 0x16 /* VLAN Default Port Tag register - port 3 */
33115 +#define REG_VLAN_PTAG4 0x18 /* VLAN Default Port Tag register - port 4 */
33116 +#define REG_VLAN_PTAG5 0x1a /* VLAN Default Port Tag register - port 5 */
33117 +#define REG_VLAN_PTAG6 0x1c /* VLAN Default Port Tag register - port 6 */
33118 +#define REG_VLAN_PTAG7 0x1e /* VLAN Default Port Tag register - port 7 */
33119 +#define REG_VLAN_PTAG8 0x20 /* 539x: VLAN Default Port Tag register - IMP port */
33120 +#define REG_VLAN_PMAP 0x20 /* 5325: VLAN Priority Re-map register */
33122 +/* ARL/VLAN Table Access page registers */
33123 +#define REG_VTBL_CTRL 0x00 /* ARL Read/Write Control */
33124 +#define REG_VTBL_MINDX 0x02 /* MAC Address Index */
33125 +#define REG_VTBL_VINDX 0x08 /* VID Table Index */
33126 +#define REG_VTBL_ARL_E0 0x10 /* ARL Entry 0 */
33127 +#define REG_VTBL_ARL_E1 0x18 /* ARL Entry 1 */
33128 +#define REG_VTBL_DAT_E0 0x18 /* ARL Table Data Entry 0 */
33129 +#define REG_VTBL_SCTRL 0x20 /* ARL Search Control */
33130 +#define REG_VTBL_SADDR 0x22 /* ARL Search Address */
33131 +#define REG_VTBL_SRES 0x24 /* ARL Search Result */
33132 +#define REG_VTBL_SREXT 0x2c /* ARL Search Result */
33133 +#define REG_VTBL_VID_E0 0x30 /* VID Entry 0 */
33134 +#define REG_VTBL_VID_E1 0x32 /* VID Entry 1 */
33135 +#define REG_VTBL_PREG 0xFF /* Page Register */
33136 +#define REG_VTBL_ACCESS 0x60 /* VLAN table access register */
33137 +#define REG_VTBL_INDX 0x61 /* VLAN table address index register */
33138 +#define REG_VTBL_ENTRY 0x63 /* VLAN table entry register */
33139 +#define REG_VTBL_ACCESS_5395 0x80 /* VLAN table access register */
33140 +#define REG_VTBL_INDX_5395 0x81 /* VLAN table address index register */
33141 +#define REG_VTBL_ENTRY_5395 0x83 /* VLAN table entry register */
33143 +/* SPI registers */
33144 +#define REG_SPI_PAGE 0xff /* SPI Page register */
33147 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/switch-core.c linux-2.6.30.10-ubi/arch/ubicom32/mach-common/switch-core.c
33148 --- linux-2.6.30.10/arch/ubicom32/mach-common/switch-core.c 1970-01-01 02:00:00.000000000 +0200
33149 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/switch-core.c 2009-12-11 11:45:11.000000000 +0200
33152 + * arch/ubicom32/mach-common/switch-core.c
33153 + * Ubicom32 architecture switch and /proc/switch/... implementation.
33155 + * (C) Copyright 2009, Ubicom, Inc.
33156 + * Copyright (C) 2005 Felix Fietkau <openwrt@nbd.name>
33158 + * This file is part of the Ubicom32 Linux Kernel Port.
33160 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
33161 + * it and/or modify it under the terms of the GNU General Public License
33162 + * as published by the Free Software Foundation, either version 2 of the
33163 + * License, or (at your option) any later version.
33165 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
33166 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
33167 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
33168 + * the GNU General Public License for more details.
33170 + * You should have received a copy of the GNU General Public License
33171 + * along with the Ubicom32 Linux Kernel Port. If not,
33172 + * see <http://www.gnu.org/licenses/>.
33174 + * Ubicom32 implementation derived from (with many thanks):
33179 + * Basic doc of driver's /proc interface:
33180 + * /proc/switch/<interface>/
33181 + * registers: read-only
33182 + * counters: read-only
33183 + * reset: write causes hardware reset
33184 + * enable: "0", "1"
33185 + * enable_vlan: "0", "1"
33186 + * port/<port-number>/
33187 + * enabled: "0", "1"
33188 + * link state: read-only
33189 + * media: "AUTO", "1000FD", "100FD", "100HD", "10FD", "10HD"
33190 + * vlan/<port-number>/
33191 + * ports: same syntax as for nvram's vlan*ports (eg. "1 2 3 4 5*")
33194 +#include <linux/module.h>
33195 +#include <linux/init.h>
33196 +#include <linux/uaccess.h>
33197 +#include <linux/ctype.h>
33198 +#include <linux/proc_fs.h>
33199 +#include <linux/list.h>
33200 +#include <linux/rwsem.h>
33201 +#include <linux/device.h>
33203 +#include "switch-core.h"
33206 + * Pointer to the root of our filesystem
33208 +static struct proc_dir_entry *switch_root;
33211 + * Lock used to manage access to the switch list
33213 +DECLARE_RWSEM(switch_list_lock);
33214 +EXPORT_SYMBOL_GPL(switch_list_lock);
33217 + * List of switches we are managing
33219 +LIST_HEAD(switch_list);
33220 +EXPORT_SYMBOL_GPL(switch_list);
33223 + * List of handlers we have
33225 +LIST_HEAD(switch_handler_list);
33226 +EXPORT_SYMBOL_GPL(switch_handler_list);
33229 + * Keep track of all the handlers we added
33231 +struct switch_handler_entry {
33232 + struct list_head node;
33233 + struct proc_dir_entry *parent;
33234 + struct switch_device *dev;
33235 + const struct switch_handler *handler;
33240 + * Keep track of all VLAN dirs we created
33242 +struct switch_vlan_entry {
33243 + struct list_head node;
33244 + struct proc_dir_entry *pde;
33246 + const struct switch_handler *handlers;
33250 + * switch_parse_vlan_ports
33251 + * Parse the vlan properties written to <driver>/vlan/<vlan_id>/ports
33253 +void switch_parse_vlan_ports(struct switch_device *switch_dev,
33254 + char *buf, u32_t *untag,
33255 + u32_t *ports, u32_t *def)
33264 + * Skip any leading spaces
33266 + while (isspace(*buf)) {
33271 + * Parse out the string
33274 + u32_t port = simple_strtoul(buf, &buf, 10);
33275 + u32_t mask = (1 << port);
33278 + * Parse out any flags
33280 + while (*buf && !isspace(*buf)) {
33281 + switch (*buf++) {
33293 + * Skip any spaces
33295 + while (isspace(*buf)) {
33300 + *untag = ~tag & *ports;
33304 + * switch_proc_read
33305 + * Handle reads from the procfs, dispatches the driver specific handler
33307 +static ssize_t switch_proc_read(struct file *file, char *buf, size_t count,
33310 + struct proc_dir_entry *pde = PDE(file->f_dentry->d_inode);
33314 + page = kmalloc(SWITCH_MAX_BUFSZ, GFP_KERNEL);
33319 + if (pde->data != NULL) {
33320 + struct switch_handler_entry *she =
33321 + (struct switch_handler_entry *)pde->data;
33322 + if (she->handler->read) {
33323 + len += she->handler->read(she->dev, page + len,
33329 + if (*ppos < len) {
33330 + len = min_t(int, len - *ppos, count);
33331 + if (copy_to_user(buf, (page + *ppos), len)) {
33346 + * switch_proc_write
33347 + * Handle writes from the procfs, dispatches the driver specific handler
33349 +static ssize_t switch_proc_write(struct file *file, const char *buf,
33350 + size_t count, loff_t *data)
33352 + struct proc_dir_entry *pde = PDE(file->f_dentry->d_inode);
33354 + int ret = -EINVAL;
33356 + page = kmalloc(count + 1, GFP_KERNEL);
33357 + if (page == NULL)
33360 + if (copy_from_user(page, buf, count)) {
33366 + if (pde->data != NULL) {
33367 + struct switch_handler_entry *she =
33368 + (struct switch_handler_entry *)pde->data;
33369 + if (she->handler->write) {
33370 + ret = she->handler->write(she->dev, page, she->inst);
33382 + * File operations for the proc_fs, we must cast here since proc_fs' definitions
33383 + * differ from file_operations definitions.
33385 +static struct file_operations switch_proc_fops = {
33386 + .read = (ssize_t (*) (struct file *, char __user *,
33387 + size_t, loff_t *))switch_proc_read,
33388 + .write = (ssize_t (*) (struct file *, const char __user *,
33389 + size_t, loff_t *))switch_proc_write,
33393 + * switch_add_handler
33395 +static int switch_add_handler(struct switch_device *switch_dev,
33396 + struct proc_dir_entry *parent,
33397 + const struct switch_handler *handler,
33400 + struct switch_handler_entry *she;
33401 + struct proc_dir_entry *pde;
33404 + she = (struct switch_handler_entry *)
33405 + kzalloc(sizeof(struct switch_handler_entry), GFP_KERNEL);
33410 + INIT_LIST_HEAD(&she->node);
33411 + she->parent = parent;
33412 + she->dev = switch_dev;
33413 + she->inst = inst;
33414 + she->handler = handler;
33415 + list_add(&she->node, &switch_dev->handlers);
33418 + if (handler->read != NULL) {
33421 + if (handler->write != NULL) {
33425 + pde = create_proc_entry(handler->name, mode, parent);
33428 + printk("Failed to create node '%s' in parent %p\n",
33429 + handler->name, parent);
33432 + pde->data = (void *)she;
33433 + pde->proc_fops = &switch_proc_fops;
33439 + * switch_add_handlers
33441 +static int switch_add_handlers(struct switch_device *switch_dev,
33442 + struct proc_dir_entry *parent,
33443 + const struct switch_handler *handlers,
33446 + while (handlers->name) {
33447 + int ret = switch_add_handler(switch_dev,
33448 + parent, handlers, inst);
33459 + * switch_remove_vlan_dirs
33460 + * Removes all vlan directories
33462 + * Assumes all vlan directories are empty, should be called after
33463 + * switch_remove_handlers
33465 +static void switch_remove_vlan_dirs(struct switch_device *switch_dev)
33467 + struct list_head *pos;
33468 + struct list_head *tmp;
33469 + struct switch_vlan_entry *sve;
33471 + list_for_each_safe(pos, tmp, &switch_dev->vlan_dirs) {
33472 + sve = list_entry(pos, struct switch_vlan_entry, node);
33474 + remove_proc_entry(sve->pde->name, switch_dev->vlan_dir);
33480 + * switch_remove_handlers
33481 + * Removes all handlers registered to the given switch_device
33483 +static void switch_remove_handlers(struct switch_device *switch_dev)
33485 + struct list_head *pos;
33486 + struct list_head *tmp;
33487 + struct switch_handler_entry *she;
33489 + list_for_each_safe(pos, tmp, &switch_dev->handlers) {
33490 + she = list_entry(pos, struct switch_handler_entry, node);
33492 + remove_proc_entry(she->handler->name, she->parent);
33498 + * switch_unregister_proc_nodes
33499 + * Unregisters all proc nodes related to switch_dev
33501 +void switch_unregister_proc_nodes(struct switch_device *switch_dev)
33503 + switch_remove_handlers(switch_dev);
33505 + if (switch_dev->port_dirs) {
33508 + for (i = 0; i < switch_dev->ports; i++) {
33509 + if (switch_dev->port_dirs[i]) {
33510 + remove_proc_entry(
33511 + switch_dev->port_dirs[i]->name,
33512 + switch_dev->port_dir);
33517 + if (switch_dev->port_dir) {
33518 + remove_proc_entry("port", switch_dev->driver_dir);
33519 + switch_dev->port_dir = NULL;
33522 + if (switch_dev->reg_dir) {
33523 + remove_proc_entry("reg", switch_dev->reg_dir);
33524 + switch_dev->reg_dir = NULL;
33527 + if (switch_dev->vlan_dir) {
33528 + switch_remove_vlan_dirs(switch_dev);
33529 + remove_proc_entry("vlan", switch_dev->driver_dir);
33530 + switch_dev->vlan_dir = NULL;
33533 + if (switch_dev->driver_dir) {
33534 + remove_proc_entry(switch_dev->name, switch_root);
33535 + switch_dev->driver_dir = NULL;
33540 + * switch_remove_vlan_dir
33541 + * Removes vlan dir in switch/<switch_driver>/vlan/<vlan_id>
33543 +int switch_remove_vlan_dir(struct switch_device *switch_dev, int vlan_id)
33545 + struct list_head *pos;
33546 + struct switch_vlan_entry *sve = NULL;
33548 + list_for_each(pos, &switch_dev->vlan_dirs) {
33549 + struct switch_vlan_entry *tmp =
33550 + list_entry(pos, struct switch_vlan_entry, node);
33551 + if (tmp->vlan_id == vlan_id) {
33562 + * Remove it from the list
33567 + * Remove the handlers
33569 + while (sve->handlers->name) {
33570 + remove_proc_entry(sve->handlers->name, sve->pde);
33575 + * Remove the proc entry for the <vlan_id> dir
33577 + remove_proc_entry(sve->pde->name, switch_dev->vlan_dir);
33585 + * switch_create_vlan_dir
33586 + * Creates vlan dir in switch/<switch_driver>/vlan/<vlan_id>
33588 +int switch_create_vlan_dir(struct switch_device *switch_dev,
33589 + int vlan_id, const struct switch_handler *handlers)
33592 + struct proc_dir_entry *pde = NULL;
33593 + struct switch_vlan_entry *sve = NULL;
33595 + struct list_head *pos;
33598 + * Check to see if it exists already
33600 + list_for_each(pos, &switch_dev->vlan_dirs) {
33601 + sve = list_entry(pos, struct switch_vlan_entry, node);
33602 + if (sve->vlan_id == vlan_id) {
33609 + * Create the vlan directory if we didn't have it before
33611 + if (!switch_dev->vlan_dir) {
33612 + switch_dev->vlan_dir = proc_mkdir("vlan",
33613 + switch_dev->driver_dir);
33614 + if (!switch_dev->vlan_dir) {
33617 + if (switch_dev->vlan_handlers) {
33618 + ret = switch_add_handlers(switch_dev,
33619 + switch_dev->vlan_dir,
33620 + switch_dev->vlan_handlers, 0);
33628 + * Create the vlan_id directory
33630 + snprintf(s, 14, "%d", vlan_id);
33631 + pde = proc_mkdir(s, switch_dev->vlan_dir);
33637 + * Create the handlers for this vlan
33640 + ret = switch_add_handlers(switch_dev, pde, handlers, vlan_id);
33647 + * Keep track of all the switch vlan entries created
33649 + sve = (struct switch_vlan_entry *)
33650 + kzalloc(sizeof(struct switch_vlan_entry), GFP_KERNEL);
33654 + INIT_LIST_HEAD(&sve->node);
33655 + sve->handlers = handlers;
33656 + sve->vlan_id = vlan_id;
33658 + list_add(&sve->node, &switch_dev->vlan_dirs);
33669 + * Remove any proc entries we might have created
33671 + while (handlers->name) {
33672 + remove_proc_entry(handlers->name, pde);
33676 + remove_proc_entry(s, switch_dev->driver_dir);
33683 + * switch_register_proc_nodes
33685 +int switch_register_proc_nodes(struct switch_device *switch_dev)
33690 + switch_dev->port_dirs = kzalloc(switch_dev->ports *
33691 + sizeof(struct proc_dir_entry *),
33693 + if (!switch_dev->port_dirs) {
33698 + * Create a new proc entry for this switch
33700 + switch_dev->driver_dir = proc_mkdir(switch_dev->name, switch_root);
33701 + if (!switch_dev->driver_dir) {
33704 + if (switch_dev->driver_handlers) {
33705 + switch_add_handlers(switch_dev,
33706 + switch_dev->driver_dir,
33707 + switch_dev->driver_handlers,
33712 + * Create the ports
33714 + switch_dev->port_dir = proc_mkdir("port", switch_dev->driver_dir);
33715 + if (!switch_dev->port_dir) {
33718 + for (n = 0, i = 0; i < (SWITCH_PORT_MASK_SIZE * 32); i++) {
33719 + if (switch_dev->port_mask[i / 32] & (1 << i % 32)) {
33722 + snprintf(s, 14, "%d", i);
33723 + switch_dev->port_dirs[n] =
33724 + proc_mkdir(s, switch_dev->port_dir);
33725 + if (!switch_dev->port_dirs[n]) {
33728 + if (switch_dev->port_handlers) {
33729 + switch_add_handlers(switch_dev,
33730 + switch_dev->port_dirs[n],
33731 + switch_dev->port_handlers,
33739 + * Create the register directory for switch register access.
33741 + if (switch_dev->reg_handlers) {
33742 + switch_dev->reg_dir = proc_mkdir("reg", switch_dev->driver_dir);
33743 + if (!switch_dev->reg_dir) {
33747 + switch_add_handlers(switch_dev,
33748 + switch_dev->reg_dir,
33749 + switch_dev->reg_handlers,
33754 + * Create the vlan directory
33756 + if (switch_dev->vlan_handlers) {
33757 + switch_dev->vlan_dir = proc_mkdir("vlan",
33758 + switch_dev->driver_dir);
33759 + if (!switch_dev->vlan_dir) {
33762 + if (switch_dev->vlan_handlers) {
33763 + switch_add_handlers(switch_dev,
33764 + switch_dev->vlan_dir,
33765 + switch_dev->vlan_handlers,
33773 + switch_unregister_proc_nodes(switch_dev);
33780 +void switch_release(struct switch_device *switch_dev)
33782 + kfree(switch_dev);
33788 +struct switch_device *switch_alloc(void)
33790 + struct switch_device *switch_dev =
33791 + kzalloc(sizeof(struct switch_device),
33793 + INIT_LIST_HEAD(&switch_dev->node);
33794 + INIT_LIST_HEAD(&switch_dev->vlan_dirs);
33795 + INIT_LIST_HEAD(&switch_dev->handlers);
33796 + return switch_dev;
33800 + * switch_register
33802 +int switch_register(struct switch_device *switch_dev)
33808 + * Make sure that the number of ports and the port mask make sense
33810 + for (ret = 0, i = 0; i < (SWITCH_PORT_MASK_SIZE * 32); i++) {
33811 + if (switch_dev->port_mask[i / 32] & (1 << i % 32)) {
33815 + if (ret > switch_dev->ports) {
33820 + * Create the /proc entries
33822 + ret = switch_register_proc_nodes(switch_dev);
33828 + * Add it to the list of switches
33830 + down_write(&switch_list_lock);
33831 + list_add_tail(&switch_dev->node, &switch_list);
33832 + up_write(&switch_list_lock);
33834 + printk(KERN_INFO "Registered switch device: %s\n", switch_dev->name);
33838 +EXPORT_SYMBOL_GPL(switch_register);
33841 + * switch_unregister
33842 + * Unregisters a previously registered switch_device object
33844 +void switch_unregister(struct switch_device *switch_dev)
33847 + * remove the proc entries
33849 + switch_unregister_proc_nodes(switch_dev);
33852 + * Remove it from the list of switches
33854 + down_write(&switch_list_lock);
33855 + list_del(&switch_dev->node);
33856 + up_write(&switch_list_lock);
33858 + printk(KERN_INFO "Unregistered switch device: %s\n", switch_dev->name);
33860 +EXPORT_SYMBOL_GPL(switch_unregister);
33865 +static int __init switch_init(void)
33867 + switch_root = proc_mkdir("switch", NULL);
33868 + if (!switch_root) {
33869 + printk(KERN_WARNING "Failed to make root switch node\n");
33874 +module_init(switch_init);
33879 +static void __exit switch_exit(void)
33881 + remove_proc_entry("switch", NULL);
33883 +module_exit(switch_exit);
33885 +MODULE_AUTHOR("Patrick Tjin");
33886 +MODULE_LICENSE("GPL");
33887 +MODULE_DESCRIPTION("Ethernet Switch Class Interface");
33888 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/switch-core.h linux-2.6.30.10-ubi/arch/ubicom32/mach-common/switch-core.h
33889 --- linux-2.6.30.10/arch/ubicom32/mach-common/switch-core.h 1970-01-01 02:00:00.000000000 +0200
33890 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/switch-core.h 2009-12-11 11:45:11.000000000 +0200
33893 + * arch/ubicom32/mach-common/switch-core.h
33894 + * Private data for the switch module
33896 + * (C) Copyright 2009, Ubicom, Inc.
33898 + * This file is part of the Ubicom32 Linux Kernel Port.
33900 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
33901 + * it and/or modify it under the terms of the GNU General Public License
33902 + * as published by the Free Software Foundation, either version 2 of the
33903 + * License, or (at your option) any later version.
33905 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
33906 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
33907 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
33908 + * the GNU General Public License for more details.
33910 + * You should have received a copy of the GNU General Public License
33911 + * along with the Ubicom32 Linux Kernel Port. If not,
33912 + * see <http://www.gnu.org/licenses/>.
33914 + * Ubicom32 implementation derived from (with many thanks):
33919 +#ifndef _SWITCH_CORE_H_
33920 +#define _SWITCH_CORE_H_
33922 +struct switch_handler_entry;
33923 +struct switch_vlan_entry;
33925 +#define SWITCH_PORT_MASK_SIZE 2
33927 +struct switch_device {
33928 + struct list_head node;
33930 + const char *name;
33935 + struct proc_dir_entry *driver_dir;
33936 + const struct switch_handler *driver_handlers;
33938 + struct proc_dir_entry *port_dir;
33939 + struct proc_dir_entry **port_dirs;
33940 + const struct switch_handler *port_handlers;
33942 + struct proc_dir_entry *reg_dir;
33943 + const struct switch_handler *reg_handlers;
33945 + struct proc_dir_entry *vlan_dir;
33946 + const struct switch_handler *vlan_handlers;
33947 + struct list_head vlan_dirs;
33949 + struct list_head handlers;
33951 + u32_t port_mask[SWITCH_PORT_MASK_SIZE];
33954 +typedef int (*switch_handler_fn)(struct switch_device *, char *buf, int nr);
33955 +struct switch_handler {
33956 + const char *name;
33958 + switch_handler_fn read;
33959 + switch_handler_fn write;
33962 +#define SWITCH_MAX_BUFSZ 4096
33964 +static inline void switch_set_drvdata(struct switch_device *switch_dev, void *drvdata)
33966 + switch_dev->drvdata = drvdata;
33969 +static inline void *switch_get_drvdata(struct switch_device *switch_dev)
33971 + return switch_dev->drvdata;
33974 +extern int switch_create_vlan_dir(struct switch_device *switch_dev, int vlan_id, const struct switch_handler *handlers);
33975 +extern int switch_remove_vlan_dir(struct switch_device *switch_dev, int vlan_id);
33976 +extern void switch_parse_vlan_ports(struct switch_device *switch_dev, char *buf, u32_t *untag, u32_t *ports, u32_t *def);
33978 +extern void switch_release(struct switch_device *switch_dev);
33979 +extern struct switch_device *switch_alloc(void);
33980 +extern int switch_register(struct switch_device *switch_dev);
33981 +extern void switch_unregister(struct switch_device *switch_dev);
33984 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/ubi32-gpio.c linux-2.6.30.10-ubi/arch/ubicom32/mach-common/ubi32-gpio.c
33985 --- linux-2.6.30.10/arch/ubicom32/mach-common/ubi32-gpio.c 1970-01-01 02:00:00.000000000 +0200
33986 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/ubi32-gpio.c 2009-12-11 11:45:11.000000000 +0200
33989 + * arch/ubicom32/mach-common/ubi32-gpio.c
33990 + * Ubicom gpio driver
33992 + * (C) Copyright 2009, Ubicom, Inc.
33994 + * This file is part of the Ubicom32 Linux Kernel Port.
33996 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
33997 + * it and/or modify it under the terms of the GNU General Public License
33998 + * as published by the Free Software Foundation, either version 2 of the
33999 + * License, or (at your option) any later version.
34001 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
34002 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
34003 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
34004 + * the GNU General Public License for more details.
34006 + * You should have received a copy of the GNU General Public License
34007 + * along with the Ubicom32 Linux Kernel Port. If not,
34008 + * see <http://www.gnu.org/licenses/>.
34010 + * Ubicom32 implementation derived from (with many thanks):
34016 +#include <linux/module.h>
34017 +#include <linux/init.h>
34018 +#include <linux/errno.h>
34019 +#include <linux/kernel.h>
34020 +#include <linux/io.h>
34021 +#include <linux/gpio.h>
34022 +#include <linux/irq.h>
34023 +#include <linux/version.h>
34025 +#if defined(CONFIG_PROC_FS)
34026 +#include <linux/proc_fs.h>
34029 +#include <linux/io.h>
34030 +#include <asm/ip5000.h>
34031 +#include <linux/gpio.h>
34033 +#define UBI_GPIO_CHECK_RANGE 0 /* !0 enables range checking */
34037 + * Each I/O port can be configured to operate in one of several
34038 + * functional modes. One of these modes is GPIO, which causes the
34039 + * entire port to function as a GPIO port. Since the various port
34040 + * registers serve the system with other important functions, such as
34041 + * ethernet, serial, USB, etc., it isn't advantageous to set any of
34042 + * the ports to be entirely dedicated for GPIO use. The processor
34043 + * alternatively allows individual bits of a port to be assigned to be
34044 + * used as GPIO independently from the overall port function. This
34045 + * bit-by-bit assignment is selected by setting the corresponding bit
34046 + * in the port's gpio_mask register. When set, the selected bit is
34047 + * then enabled as a GPIO. If the corresponding bit is set in the
34048 + * gpio_ctl register of the port, the bit is configured as a GPIO
34049 + * output. Otherwise, it is an input.
34051 + * NOTE: This driver uses the bit-by-bit GPIO function assignment
34052 + * exclusively and *never* sets the port function registers to the
34055 + * GPIO is not the main function of any of the I/O ports. The port
34056 + * bit widths are variable from one port to the next, determined by
34057 + * the more common I/O functions of the ports. For simplicity, this
34058 + * driver assumes all the ports are 32 bits wide regardless of the
34059 + * real bit width of the port. GPIO bits are numbered from zero to
34060 + * MAX_UBICOM_GPIOS. Within a port, the least significant bit is
34061 + * numbered bit zero, the most significant is bit 31. Since the ports
34062 + * are considered logically contiguous, GPIO #32 is the zeroth bit in
34063 + * port #1, and so on. Due to the hardware definition, there are
34064 + * large gaps in the GPIO numbers representing real pins.
34066 + * NOTE: It is up to the programmer to refer to the processor data
34067 + * sheet to determine which bits in which ports can be accessed and
34073 +/* There are 9 ports, A through I. Not all 32 bits in each
34074 + * port can be a GPIO, but we pretend they are. Its up to the
34075 + * programmer to refer to the processor data sheet.
34077 +#define MAX_UBICOM_GPIOS (9 * 32) /* ARCH_NR_GPIOS */
34078 +#define NUM_GPIO_PORTS (gpio_bank(MAX_UBICOM_GPIOS))
34081 +/* GPIO reservation bit map array */
34082 +static int reserved_gpio_map[NUM_GPIO_PORTS];
34085 +/* Array of hardware io_port addresses */
34086 +static struct ubicom32_io_port *gpio_bank_addr[NUM_GPIO_PORTS] =
34088 + UBICOM32_IO_PORT(RA),
34089 + UBICOM32_IO_PORT(RB),
34090 + UBICOM32_IO_PORT(RC),
34091 + UBICOM32_IO_PORT(RD),
34092 + UBICOM32_IO_PORT(RE),
34093 + UBICOM32_IO_PORT(RF),
34094 + UBICOM32_IO_PORT(RG),
34095 + UBICOM32_IO_PORT(RH),
34096 + UBICOM32_IO_PORT(RI)
34100 +struct ubi_gpio_chip {
34102 + * Right now, nothing else lives here.
34104 + struct gpio_chip gpio_chip;
34108 +#if UBI_GPIO_CHECK_RANGE
34109 +inline int check_gpio(unsigned gpio)
34111 + if (gpio >= MAX_UBICOM_GPIOS)
34116 +#define check_gpio(n) (0)
34120 + * ubi_gpio_get_port
34121 + * Get the IO port associated with a certain gpio
34123 +struct ubicom32_io_port *ubi_gpio_get_port(unsigned gpio)
34125 + if (gpio_bank(gpio) > NUM_GPIO_PORTS) {
34128 + return gpio_bank_addr[gpio_bank(gpio)];
34132 + * ubi_gpio_error()
34134 +static void ubi_gpio_error(unsigned gpio)
34136 + printk(KERN_ERR "ubicom-gpio: GPIO %d wasn't requested!\n", gpio);
34140 + * ubi_port_setup()
34142 +static void ubi_port_setup(unsigned gpio, unsigned short usage)
34144 + if (!check_gpio(gpio)) {
34146 + UBICOM32_GPIO_ENABLE(gpio);
34148 + UBICOM32_GPIO_DISABLE(gpio);
34154 + * ubi_gpio_request()
34156 +static int ubi_gpio_request(struct gpio_chip *chip, unsigned gpio)
34158 + unsigned long flags;
34160 + if (check_gpio(gpio) < 0)
34163 + local_irq_save(flags);
34165 + if (unlikely(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
34166 + printk(KERN_ERR "ubi-gpio: GPIO %d is already reserved!\n",
34168 + local_irq_restore(flags);
34172 + reserved_gpio_map[gpio_bank(gpio)] |= gpio_bit(gpio);
34174 + ubi_port_setup(gpio, 1);
34176 + local_irq_restore(flags);
34182 + * ubi_gpio_free()
34184 +static void ubi_gpio_free(struct gpio_chip *chip, unsigned gpio)
34186 + unsigned long flags;
34188 + if (check_gpio(gpio) < 0)
34191 + local_irq_save(flags);
34193 + if (unlikely(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)))) {
34194 + ubi_gpio_error(gpio);
34195 + local_irq_restore(flags);
34199 + /* Assert the pin is no longer claimed */
34200 + reserved_gpio_map[gpio_bank(gpio)] &= ~gpio_bit(gpio);
34202 + /* Revert port bit to use specified by port->function */
34203 + ubi_port_setup(gpio, 0);
34205 + local_irq_restore(flags);
34209 + * ubi_gpio_direction_input()
34211 +static int ubi_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
34213 + unsigned long flags;
34215 + if (!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
34216 + ubi_gpio_error(gpio);
34220 + local_irq_save(flags);
34222 + /* Configure pin as gpio */
34223 + ubi_port_setup(gpio, 1);
34225 + /* Assert pin is an input */
34226 + UBICOM32_GPIO_SET_PIN_INPUT(gpio);
34228 + local_irq_restore(flags);
34235 + * ubi_gpio_direction_output()
34237 +static int ubi_gpio_direction_output(struct gpio_chip *chip,
34238 + unsigned gpio, int value)
34240 + unsigned long flags;
34242 + if (!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
34243 + ubi_gpio_error(gpio);
34247 + local_irq_save(flags);
34249 + /* Configure pin as gpio and set initial value in gpio_out register
34250 + * so that when we enable it as an output, it will have the correct
34253 + ubi_port_setup(gpio, 1);
34255 + UBICOM32_GPIO_SET_PIN_HIGH(gpio);
34257 + UBICOM32_GPIO_SET_PIN_LOW(gpio);
34260 + /* Enable the pin as an output */
34261 + UBICOM32_GPIO_SET_PIN_OUTPUT(gpio);
34263 + local_irq_restore(flags);
34270 + * ubi_gpio_get_value()
34272 +static int ubi_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
34274 + return 0 != (gpio_bank_addr[gpio_bank(gpio)]->gpio_in & gpio_bit(gpio));
34279 + * ubi_gpio_set_value()
34281 +static void ubi_gpio_set_value(struct gpio_chip *chip, unsigned gpio,
34284 + unsigned long flags;
34285 + local_irq_save(flags);
34288 + UBICOM32_GPIO_SET_PIN_HIGH(gpio);
34290 + UBICOM32_GPIO_SET_PIN_LOW(gpio);
34293 + local_irq_restore(flags);
34298 + * ubi_gpio_to_irq()
34300 +static int ubi_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
34302 + return gpio_to_irq(gpio);
34307 + * ubi_gpio_init()
34309 +int __init ubi_gpio_init(void)
34313 + struct ubi_gpio_chip *chip;
34314 + struct gpio_chip *gc;
34316 + printk(KERN_INFO "Ubicom GPIO Controller\n");
34318 + chip = kzalloc(sizeof(struct ubi_gpio_chip), GFP_KERNEL);
34319 + if (chip == NULL)
34322 + gc = &chip->gpio_chip;
34323 + gc->request = ubi_gpio_request;
34324 + gc->free = ubi_gpio_free;
34325 + gc->to_irq = ubi_gpio_to_irq;
34326 + gc->direction_input = ubi_gpio_direction_input;
34327 + gc->direction_output = ubi_gpio_direction_output;
34328 + gc->get = ubi_gpio_get_value;
34329 + gc->set = ubi_gpio_set_value;
34330 + gc->can_sleep = 0;
34332 + gc->ngpio = MAX_UBICOM_GPIOS; /* ARCH_NR_GPIOS - 1 */
34333 + gc->label = "ubi_gpio";
34335 + status = gpiochip_add(gc);
34336 + if (status != 0) {
34341 + /* Assert all pins are free */
34342 + for (k = 0; k < NUM_GPIO_PORTS; k++) {
34343 + reserved_gpio_map[k] = 0;
34349 +#if defined(CONFIG_PROC_FS)
34351 + * ubi_get_gpio_dir()
34353 +static int ubi_get_gpio_dir(unsigned gpio)
34355 + if (gpio_bank_addr[gpio_bank(gpio)]->gpio_ctl & gpio_bit(gpio))
34362 + * gpio_proc_read()
34364 +static int ubi_gpio_proc_read(char *buf, char **start, off_t offset,
34365 + int len, int *unused_i, void *unused_v)
34367 + int c, outlen = 0;
34369 + for (c = 0; c < MAX_UBICOM_GPIOS; c++) {
34370 + if (!check_gpio(c) &&
34371 + (reserved_gpio_map[gpio_bank(c)] & gpio_bit(c))) {
34372 + len = sprintf(buf, "GPIO_%d:\t\tGPIO %s\n", c,
34373 + ubi_get_gpio_dir(c) ? "OUTPUT" : "INPUT");
34385 + * ubi_gpio_register_proc()
34387 +static __init int ubi_gpio_register_proc(void)
34389 + struct proc_dir_entry *proc_gpio;
34391 + proc_gpio = create_proc_entry("gpio", S_IRUGO, NULL);
34393 + proc_gpio->read_proc = ubi_gpio_proc_read;
34395 + return proc_gpio != NULL;
34397 +device_initcall(ubi_gpio_register_proc);
34399 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/ubicom32hid.c linux-2.6.30.10-ubi/arch/ubicom32/mach-common/ubicom32hid.c
34400 --- linux-2.6.30.10/arch/ubicom32/mach-common/ubicom32hid.c 1970-01-01 02:00:00.000000000 +0200
34401 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/ubicom32hid.c 2009-12-11 11:45:11.000000000 +0200
34404 + * arch/ubicom32/mach-common/ubicom32hid.c
34405 + * I2C driver for HID coprocessor found on some DPF implementations.
34407 + * (C) Copyright 2009, Ubicom, Inc.
34409 + * This file is part of the Ubicom32 Linux Kernel Port.
34411 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
34412 + * it and/or modify it under the terms of the GNU General Public License
34413 + * as published by the Free Software Foundation, either version 2 of the
34414 + * License, or (at your option) any later version.
34416 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
34417 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
34418 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
34419 + * the GNU General Public License for more details.
34421 + * You should have received a copy of the GNU General Public License
34422 + * along with the Ubicom32 Linux Kernel Port. If not,
34423 + * see <http://www.gnu.org/licenses/>.
34425 + * Ubicom32 implementation derived from (with many thanks):
34431 +#include <linux/module.h>
34432 +#include <linux/init.h>
34433 +#include <linux/gpio.h>
34434 +#include <linux/delay.h>
34435 +#include <linux/platform_device.h>
34436 +#include <linux/i2c.h>
34437 +#include <linux/backlight.h>
34438 +#include <linux/fb.h>
34439 +#include <linux/input.h>
34440 +#include <linux/input-polldev.h>
34442 +#include <asm/ubicom32hid.h>
34444 +#define DRIVER_NAME "ubicom32hid"
34447 +static int ubicom32hid_debug;
34450 +static const struct i2c_device_id ubicom32hid_id[] = {
34451 + { DRIVER_NAME, },
34454 +MODULE_DEVICE_TABLE(i2c, ubicom32hid_id);
34457 + * Define this to make IR checking strict, in general, it's not needed
34459 +#undef UBICOM32HID_STRICT_IR_CHECK
34461 +#define UBICOM32HID_CMD_SET_PWM 0x01
34462 +#define UBICOM32HID_CMD_SET_BL_EN 0x02
34463 +#define UBICOM32HID_BL_EN_LOW 0x00
34464 +#define UBICOM32HID_BL_EN_HIZ 0x01
34465 +#define UBICOM32HID_BL_EN_HI 0x02
34466 +#define UBICOM32HID_CMD_FLUSH 0x99
34467 +#define UBICOM32HID_CMD_RESET 0x99
34468 +#define UBICOM32HID_CMD_GET_IR_SWITCH 0xC0
34469 +#define UBICOM32HID_CMD_GET_REVISION 0xfd
34470 +#define UBICOM32HID_CMD_GET_DEVICE_ID 0xfe
34471 +#define UBICOM32HID_CMD_GET_VERSION 0xff
34472 +#define UBICOM32HID_DEVICE_ID 0x49
34474 +#define UBICOM32HID_MAX_BRIGHTNESS_PWM 255
34477 + * Data structure returned by the HID device
34479 +struct ubicom32hid_input_data {
34481 + uint8_t sw_state;
34482 + uint8_t sw_changed;
34486 + * Our private data
34488 +struct ubicom32hid_data {
34490 + * Pointer to the platform data structure, we need the settings.
34492 + const struct ubicom32hid_platform_data *pdata;
34495 + * Backlight device
34497 + struct backlight_device *bldev;
34500 + * I2C client, for sending messages to the HID device
34502 + struct i2c_client *client;
34505 + * Current intensity, used for get_intensity.
34507 + int cur_intensity;
34510 + * Input subsystem
34511 + * We won't register an input subsystem if there are no mappings.
34513 + struct input_polled_dev *poll_dev;
34518 + * ubicom32hid_set_intensity
34520 +static int ubicom32hid_set_intensity(struct backlight_device *bd)
34522 + struct ubicom32hid_data *ud =
34523 + (struct ubicom32hid_data *)bl_get_data(bd);
34524 + int intensity = bd->props.brightness;
34530 + * If we're blanked the the intensity doesn't matter.
34532 + if ((bd->props.power != FB_BLANK_UNBLANK) ||
34533 + (bd->props.fb_blank != FB_BLANK_UNBLANK)) {
34538 + * Set the brightness based on the type of backlight
34540 + if (ud->pdata->type == UBICOM32HID_BL_TYPE_BINARY) {
34541 + reg = UBICOM32HID_CMD_SET_BL_EN;
34543 + val = ud->pdata->invert
34544 + ? UBICOM32HID_BL_EN_LOW : UBICOM32HID_BL_EN_HI;
34546 + val = ud->pdata->invert
34547 + ? UBICOM32HID_BL_EN_HI : UBICOM32HID_BL_EN_LOW;
34550 + reg = UBICOM32HID_CMD_SET_PWM;
34551 + val = ud->pdata->invert
34552 + ? (UBICOM32HID_MAX_BRIGHTNESS_PWM - intensity) :
34557 + * Send the command
34559 + ret = i2c_smbus_write_byte_data(ud->client, reg, val);
34561 + dev_warn(&ud->client->dev, "Unable to write backlight err=%d\n",
34566 + ud->cur_intensity = intensity;
34572 + * ubicom32hid_get_intensity
34573 + * Return the current intensity of the backlight.
34575 +static int ubicom32hid_get_intensity(struct backlight_device *bd)
34577 + struct ubicom32hid_data *ud =
34578 + (struct ubicom32hid_data *)bl_get_data(bd);
34580 + return ud->cur_intensity;
34584 + * ubicom32hid_verify_data
34585 + * Verify the data to see if there is any action to be taken
34587 + * Returns 0 if no action is to be taken, non-zero otherwise
34589 +static int ubicom32hid_verify_data(struct ubicom32hid_data *ud,
34590 + struct ubicom32hid_input_data *data)
34592 + uint8_t *ircmd = (uint8_t *)&(data->ircmd);
34595 + * ircmd == DEADBEEF means ir queue is empty. Since this is a
34596 + * meaningful code, that means the rest of the message is most likely
34597 + * correct, so only process the data if the switch state has changed.
34599 + if (data->ircmd == 0xDEADBEEF) {
34600 + return data->sw_changed != 0;
34604 + * We have an ircmd which is not empty:
34605 + * Data[1] should be the complement of Data[0]
34607 + if (ircmd[0] != (u8_t)~ircmd[1]) {
34611 +#ifdef UBICOM32HID_STRICT_IR_CHECK
34613 + * It seems that some remote controls don't follow the NEC protocol
34614 + * properly, so only do this check if the remote does indeed follow the
34615 + * spec. Data[3] should be the complement of Data[2]
34617 + if (ircmd[2] == (u8_t)~ircmd[3]) {
34622 + * For non-compliant remotes, check the system code according to what
34625 + if ((ircmd[2] != UBICOM32HID_IR_SYSTEM_CODE_CHECK) ||
34626 + (ircmd[3] != UBICOM32HID_IR_SYSTEM_CODE)) {
34632 + * Data checks out, process
34638 + * ubicom32hid_poll_input
34639 + * Poll the input from the HID device.
34641 +static void ubicom32hid_poll_input(struct input_polled_dev *dev)
34643 + struct ubicom32hid_data *ud = (struct ubicom32hid_data *)dev->private;
34644 + const struct ubicom32hid_platform_data *pdata = ud->pdata;
34645 + struct ubicom32hid_input_data data;
34646 + struct input_dev *id = dev->input;
34648 + int sync_needed = 0;
34653 + * Flush the queue
34655 + cmd = UBICOM32HID_CMD_FLUSH;
34656 + ret = i2c_master_send(ud->client, &cmd, 1);
34661 + ret = i2c_smbus_read_i2c_block_data(
34662 + ud->client, UBICOM32HID_CMD_GET_IR_SWITCH, 6, (void *)&data);
34668 + * Verify the data to see if there is any action to be taken
34670 + if (!ubicom32hid_verify_data(ud, &data)) {
34675 + if (ubicom32hid_debug) {
34676 + printk("Polled ircmd=%8x swstate=%2x swchanged=%2x\n",
34677 + data.ircmd, data.sw_state, data.sw_changed);
34682 + * Process changed switches
34684 + if (data.sw_changed) {
34685 + const struct ubicom32hid_button *ub = pdata->buttons;
34686 + for (i = 0; i < pdata->nbuttons; i++, ub++) {
34687 + uint8_t mask = (1 << ub->bit);
34688 + if (!(data.sw_changed & mask)) {
34693 + input_event(id, ub->type, ub->code,
34694 + (data.sw_state & mask) ? 1 : 0);
34697 + if (sync_needed) {
34702 + * Process ir codes
34704 + if (data.ircmd != 0xDEADBEEF) {
34705 + const struct ubicom32hid_ir *ui = pdata->ircodes;
34706 + for (i = 0; i < pdata->nircodes; i++, ui++) {
34707 + if (ui->ir_code == data.ircmd) {
34709 + * Simulate a up/down event
34711 + input_event(id, ui->type, ui->code, 1);
34713 + input_event(id, ui->type, ui->code, 0);
34724 +static struct backlight_ops ubicom32hid_blops = {
34725 + .get_brightness = ubicom32hid_get_intensity,
34726 + .update_status = ubicom32hid_set_intensity,
34730 + * ubicom32hid_probe
34732 +static int ubicom32hid_probe(struct i2c_client *client,
34733 + const struct i2c_device_id *id)
34735 + struct ubicom32hid_platform_data *pdata;
34736 + struct ubicom32hid_data *ud;
34742 + pdata = client->dev.platform_data;
34743 + if (pdata == NULL) {
34748 + * See if we even have a device available before allocating memory.
34750 + * Hard reset the device
34752 + ret = gpio_request(pdata->gpio_reset, "ubicom32hid-reset");
34756 + gpio_direction_output(pdata->gpio_reset, pdata->gpio_reset_polarity);
34758 + gpio_set_value(pdata->gpio_reset, !pdata->gpio_reset_polarity);
34762 + * soft reset the device. It sometimes takes a while to do this.
34764 + for (i = 0; i < 50; i++) {
34765 + buf[0] = UBICOM32HID_CMD_RESET;
34766 + ret = i2c_master_send(client, buf, 1);
34773 + dev_warn(&client->dev, "Unable to reset device\n");
34777 + ret = i2c_smbus_read_byte_data(client, UBICOM32HID_CMD_GET_DEVICE_ID);
34778 + if (ret != UBICOM32HID_DEVICE_ID) {
34779 + dev_warn(&client->dev, "Incorrect device id %02x\n", buf[0]);
34784 + ret = i2c_smbus_read_byte_data(client, UBICOM32HID_CMD_GET_VERSION);
34786 + dev_warn(&client->dev, "Unable to get version\n");
34789 + version[0] = ret;
34791 + ret = i2c_smbus_read_byte_data(client, UBICOM32HID_CMD_GET_REVISION);
34793 + dev_warn(&client->dev, "Unable to get revision\n");
34796 + version[1] = ret;
34799 + * Allocate our private data
34801 + ud = kzalloc(sizeof(struct ubicom32hid_data), GFP_KERNEL);
34806 + ud->pdata = pdata;
34807 + ud->client = client;
34810 + * Register our backlight device
34812 + ud->bldev = backlight_device_register(DRIVER_NAME, &client->dev,
34813 + ud, &ubicom32hid_blops);
34814 + if (IS_ERR(ud->bldev)) {
34815 + ret = PTR_ERR(ud->bldev);
34818 + platform_set_drvdata(client, ud);
34821 + * Start up the backlight with the requested intensity
34823 + ud->bldev->props.power = FB_BLANK_UNBLANK;
34824 + ud->bldev->props.max_brightness =
34825 + (pdata->type == UBICOM32HID_BL_TYPE_PWM) ?
34826 + UBICOM32HID_MAX_BRIGHTNESS_PWM : 1;
34827 + if (pdata->default_intensity < ud->bldev->props.max_brightness) {
34828 + ud->bldev->props.brightness = pdata->default_intensity;
34830 + dev_warn(&client->dev, "Default brightness out of range, "
34831 + "setting to max\n");
34832 + ud->bldev->props.brightness = ud->bldev->props.max_brightness;
34835 + ubicom32hid_set_intensity(ud->bldev);
34838 + * Check to see if we have any inputs
34840 + if (!pdata->nbuttons && !pdata->nircodes) {
34845 + * We have buttons or codes, we must register an input device
34847 + ud->poll_dev = input_allocate_polled_device();
34848 + if (!ud->poll_dev) {
34854 + * Setup the polling to default to 100ms
34856 + ud->poll_dev->poll = ubicom32hid_poll_input;
34857 + ud->poll_dev->poll_interval =
34858 + pdata->poll_interval ? pdata->poll_interval : 100;
34859 + ud->poll_dev->private = ud;
34861 + ud->poll_dev->input->name =
34862 + pdata->input_name ? pdata->input_name : "Ubicom32HID";
34863 + ud->poll_dev->input->phys = "ubicom32hid/input0";
34864 + ud->poll_dev->input->dev.parent = &client->dev;
34865 + ud->poll_dev->input->id.bustype = BUS_I2C;
34868 + * Set the capabilities by running through the buttons and ir codes
34870 + for (i = 0; i < pdata->nbuttons; i++) {
34871 + const struct ubicom32hid_button *ub = &pdata->buttons[i];
34873 + input_set_capability(ud->poll_dev->input,
34874 + ub->type ? ub->type : EV_KEY, ub->code);
34877 + for (i = 0; i < pdata->nircodes; i++) {
34878 + const struct ubicom32hid_ir *ui = &pdata->ircodes[i];
34880 + input_set_capability(ud->poll_dev->input,
34881 + ui->type ? ui->type : EV_KEY, ui->code);
34884 + ret = input_register_polled_device(ud->poll_dev);
34890 + printk(KERN_INFO DRIVER_NAME ": enabled, version=%02x.%02x\n",
34891 + version[0], version[1]);
34896 + gpio_free(ud->pdata->gpio_reset);
34897 + backlight_device_unregister(ud->bldev);
34901 + gpio_free(pdata->gpio_reset);
34906 + * ubicom32hid_remove
34908 +static int ubicom32hid_remove(struct i2c_client *client)
34910 + struct ubicom32hid_data *ud =
34911 + (struct ubicom32hid_data *)platform_get_drvdata(client);
34913 + gpio_free(ud->pdata->gpio_reset);
34915 + backlight_device_unregister(ud->bldev);
34917 + if (ud->poll_dev) {
34918 + input_unregister_polled_device(ud->poll_dev);
34919 + input_free_polled_device(ud->poll_dev);
34922 + platform_set_drvdata(client, NULL);
34929 +static struct i2c_driver ubicom32hid_driver = {
34931 + .name = DRIVER_NAME,
34932 + .owner = THIS_MODULE,
34934 + .probe = ubicom32hid_probe,
34935 + .remove = __exit_p(ubicom32hid_remove),
34936 + .id_table = ubicom32hid_id,
34940 + * ubicom32hid_init
34942 +static int __init ubicom32hid_init(void)
34944 + return i2c_add_driver(&ubicom32hid_driver);
34946 +module_init(ubicom32hid_init);
34949 + * ubicom32hid_exit
34951 +static void __exit ubicom32hid_exit(void)
34953 + i2c_del_driver(&ubicom32hid_driver);
34955 +module_exit(ubicom32hid_exit);
34957 +MODULE_AUTHOR("Pat Tjin <@ubicom.com>")
34958 +MODULE_DESCRIPTION("Ubicom HID driver");
34959 +MODULE_LICENSE("GPL");
34960 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/ubicom32input.c linux-2.6.30.10-ubi/arch/ubicom32/mach-common/ubicom32input.c
34961 --- linux-2.6.30.10/arch/ubicom32/mach-common/ubicom32input.c 1970-01-01 02:00:00.000000000 +0200
34962 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/ubicom32input.c 2009-12-11 11:45:11.000000000 +0200
34965 + * arch/ubicom32/mach-common/ubicom32input.c
34966 + * Ubicom32 Input driver
34968 + * based on gpio-keys
34970 + * (C) Copyright 2009, Ubicom, Inc.
34972 + * This file is part of the Ubicom32 Linux Kernel Port.
34974 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
34975 + * it and/or modify it under the terms of the GNU General Public License
34976 + * as published by the Free Software Foundation, either version 2 of the
34977 + * License, or (at your option) any later version.
34979 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
34980 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
34981 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
34982 + * the GNU General Public License for more details.
34984 + * You should have received a copy of the GNU General Public License
34985 + * along with the Ubicom32 Linux Kernel Port. If not,
34986 + * see <http://www.gnu.org/licenses/>.
34988 + * Ubicom32 implementation derived from (with many thanks):
34994 + * TODO: add groups for inputs which can be sampled together (i.e. I2C)
34997 +#include <linux/kernel.h>
34998 +#include <linux/module.h>
34999 +#include <linux/platform_device.h>
35000 +#include <linux/input.h>
35001 +#include <linux/input-polldev.h>
35002 +#include <linux/delay.h>
35003 +#include <linux/gpio.h>
35005 +#include <asm/ubicom32input.h>
35007 +struct ubicom32input_data {
35008 + struct ubicom32input_platform_data *pdata;
35010 + struct input_polled_dev *poll_dev;
35013 + * collection of previous states for buttons
35015 + u8 prev_state[0];
35019 + * ubicom32input_poll
35021 +static void ubicom32input_poll(struct input_polled_dev *dev)
35023 + struct ubicom32input_data *ud =
35024 + (struct ubicom32input_data *)dev->private;
35025 + struct ubicom32input_platform_data *pdata = ud->pdata;
35026 + struct input_dev *id = dev->input;
35028 + int sync_needed = 0;
35030 + for (i = 0; i < pdata->nbuttons; i++) {
35031 + const struct ubicom32input_button *ub = &pdata->buttons[i];
35034 + int val = gpio_get_value(ub->gpio);
35037 + * Check to see if the state changed from the last time we
35040 + if (val == ud->prev_state[i]) {
35045 + * The state has changed, determine if we are "up" or "down"
35047 + ud->prev_state[i] = val;
35049 + if ((!val && ub->active_low) || (val && !ub->active_low)) {
35053 + input_event(id, ub->type, ub->code, state);
35057 + if (sync_needed) {
35063 + * ubicom32input_probe
35065 +static int __devinit ubicom32input_probe(struct platform_device *pdev)
35068 + struct ubicom32input_data *ud;
35069 + struct input_polled_dev *poll_dev;
35070 + struct input_dev *input_dev;
35071 + struct ubicom32input_platform_data *pdata;
35074 + pdata = pdev->dev.platform_data;
35079 + ud = kzalloc(sizeof(struct ubicom32input_data) +
35080 + pdata->nbuttons, GFP_KERNEL);
35084 + ud->pdata = pdata;
35086 + poll_dev = input_allocate_polled_device();
35092 + platform_set_drvdata(pdev, ud);
35094 + ud->poll_dev = poll_dev;
35095 + poll_dev->private = ud;
35096 + poll_dev->poll = ubicom32input_poll;
35099 + * Set the poll interval requested, default to 50 msec
35101 + if (pdata->poll_interval) {
35102 + poll_dev->poll_interval = pdata->poll_interval;
35104 + poll_dev->poll_interval = 50;
35108 + * Setup the input device
35110 + input_dev = poll_dev->input;
35111 + input_dev->name = pdata->name ? pdata->name : "Ubicom32 Input";
35112 + input_dev->phys = "ubicom32input/input0";
35113 + input_dev->dev.parent = &pdev->dev;
35114 + input_dev->id.bustype = BUS_HOST;
35117 + * Reserve the GPIOs
35119 + for (i = 0; i < pdata->nbuttons; i++) {
35120 + const struct ubicom32input_button *ub = &pdata->buttons[i];
35122 + ret = gpio_request(ub->gpio,
35123 + ub->desc ? ub->desc : "ubicom32input");
35125 + pr_err("ubicom32input: failed to request "
35126 + "GPIO %d ret=%d\n", ub->gpio, ret);
35130 + ret = gpio_direction_input(ub->gpio);
35132 + pr_err("ubicom32input: failed to set "
35133 + "GPIO %d to input ret=%d\n", ub->gpio, ret);
35138 + * Set the previous state to the non-active stae
35140 + ud->prev_state[i] = ub->active_low;
35142 + input_set_capability(input_dev,
35143 + ub->type ? ub->type : EV_KEY, ub->code);
35149 + ret = input_register_polled_device(ud->poll_dev);
35158 + * release the GPIOs we have already requested.
35160 + while (--i >= 0) {
35161 + gpio_free(pdata->buttons[i].gpio);
35165 + printk(KERN_ERR "Ubicom32Input: Failed to register driver %d", ret);
35166 + platform_set_drvdata(pdev, NULL);
35167 + input_free_polled_device(poll_dev);
35173 + * ubicom32input_remove
35175 +static int __devexit ubicom32input_remove(struct platform_device *dev)
35177 + struct ubicom32input_data *ud =
35178 + (struct ubicom32input_data *)platform_get_drvdata(dev);
35184 + for (i = 0; i < ud->pdata->nbuttons; i++) {
35185 + gpio_free(ud->pdata->buttons[i].gpio);
35188 + platform_set_drvdata(dev, NULL);
35189 + input_unregister_polled_device(ud->poll_dev);
35190 + input_free_polled_device(ud->poll_dev);
35197 +static struct platform_driver ubicom32input_driver = {
35199 + .name = "ubicom32input",
35200 + .owner = THIS_MODULE,
35202 + .probe = ubicom32input_probe,
35203 + .remove = __devexit_p(ubicom32input_remove),
35207 + * ubicom32input_init
35209 +static int __devinit ubicom32input_init(void)
35211 + return platform_driver_register(&ubicom32input_driver);
35215 + * ubicom32input_exit
35217 +static void __exit ubicom32input_exit(void)
35219 + platform_driver_unregister(&ubicom32input_driver);
35222 +module_init(ubicom32input_init);
35223 +module_exit(ubicom32input_exit);
35225 +MODULE_AUTHOR("Pat Tjin <pattjin@ubicom.com>");
35226 +MODULE_DESCRIPTION("Ubicom32 Input Driver");
35227 +MODULE_LICENSE("GPL");
35228 +MODULE_ALIAS("platform:ubicom32-input");
35229 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/ubicom32input_i2c.c linux-2.6.30.10-ubi/arch/ubicom32/mach-common/ubicom32input_i2c.c
35230 --- linux-2.6.30.10/arch/ubicom32/mach-common/ubicom32input_i2c.c 1970-01-01 02:00:00.000000000 +0200
35231 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/ubicom32input_i2c.c 2009-12-11 11:45:11.000000000 +0200
35234 + * arch/ubicom32/mach-common/ubicom32input_i2c.c
35235 + * Ubicom32 Input driver for I2C
35236 + * Supports PCA953x and family
35238 + * We hog the I2C device, turning it all to input.
35240 + * Based on gpio-keys, pca953x
35242 + * (C) Copyright 2009, Ubicom, Inc.
35244 + * This file is part of the Ubicom32 Linux Kernel Port.
35246 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
35247 + * it and/or modify it under the terms of the GNU General Public License
35248 + * as published by the Free Software Foundation, either version 2 of the
35249 + * License, or (at your option) any later version.
35251 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
35252 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
35253 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
35254 + * the GNU General Public License for more details.
35256 + * You should have received a copy of the GNU General Public License
35257 + * along with the Ubicom32 Linux Kernel Port. If not,
35258 + * see <http://www.gnu.org/licenses/>.
35260 + * Ubicom32 implementation derived from (with many thanks):
35265 +#include <linux/kernel.h>
35266 +#include <linux/module.h>
35267 +#include <linux/platform_device.h>
35268 +#include <linux/input.h>
35269 +#include <linux/input-polldev.h>
35270 +#include <linux/i2c.h>
35272 +#include <asm/ubicom32input_i2c.h>
35274 +#define UBICOM32INPUT_I2C_REG_INPUT 0
35275 +#define UBICOM32INPUT_I2C_REG_OUTPUT 1
35276 +#define UBICOM32INPUT_I2C_REG_INVERT 2
35277 +#define UBICOM32INPUT_I2C_REG_DIRECTION 3
35279 +static const struct i2c_device_id ubicom32input_i2c_id[] = {
35280 + { "ubicom32in_pca9534", 8, },
35281 + { "ubicom32in_pca9535", 16, },
35282 + { "ubicom32in_pca9536", 4, },
35283 + { "ubicom32in_pca9537", 4, },
35284 + { "ubicom32in_pca9538", 8, },
35285 + { "ubicom32in_pca9539", 16, },
35286 + { "ubicom32in_pca9554", 8, },
35287 + { "ubicom32in_pca9555", 16, },
35288 + { "ubicom32in_pca9557", 8, },
35289 + { "ubicom32in_max7310", 8, },
35292 +MODULE_DEVICE_TABLE(i2c, ubicom32input_i2c_id);
35294 +struct ubicom32input_i2c_data {
35295 + struct ubicom32input_i2c_platform_data *pdata;
35297 + struct i2c_client *client;
35299 + struct input_polled_dev *poll_dev;
35302 + * collection of previous states for buttons
35304 + uint16_t prev_state;
35310 + * ubicom32input_i2c_write_reg
35311 + * writes a register to the I2C device.
35313 +static int ubicom32input_i2c_write_reg(struct ubicom32input_i2c_data *ud,
35314 + int reg, uint16_t val)
35318 + if (ud->ngpios <= 8) {
35319 + ret = i2c_smbus_write_byte_data(ud->client, reg, val);
35321 + ret = i2c_smbus_write_word_data(ud->client, reg << 1, val);
35332 + * ubicom32input_i2c_read_reg
35333 + * reads a register from the I2C device.
35335 +static int ubicom32input_i2c_read_reg(struct ubicom32input_i2c_data *ud,
35336 + int reg, uint16_t *val)
35340 + if (ud->ngpios <= 8) {
35341 + ret = i2c_smbus_read_byte_data(ud->client, reg);
35343 + ret = i2c_smbus_read_word_data(ud->client, reg);
35350 + *val = (uint16_t)ret;
35356 + * ubicom32input_i2c_poll
35358 +static void ubicom32input_i2c_poll(struct input_polled_dev *dev)
35360 + struct ubicom32input_i2c_data *ud =
35361 + (struct ubicom32input_i2c_data *)dev->private;
35362 + struct ubicom32input_i2c_platform_data *pdata = ud->pdata;
35363 + struct input_dev *id = dev->input;
35365 + int sync_needed = 0;
35367 + uint16_t change_mask;
35370 + * Try to get the input status, if we fail, bail out, maybe we can do it
35373 + if (ubicom32input_i2c_read_reg(ud, UBICOM32INPUT_I2C_REG_INPUT, &val)) {
35378 + * see if anything changed by using XOR
35380 + change_mask = ud->prev_state ^ val;
35381 + ud->prev_state = val;
35383 + for (i = 0; i < pdata->nbuttons; i++) {
35384 + const struct ubicom32input_i2c_button *ub = &pdata->buttons[i];
35385 + uint16_t mask = 1 << ub->bit;
35386 + int state = val & mask;
35389 + * Check to see if the state changed from the last time we
35392 + if (!(change_mask & mask)) {
35395 + input_event(id, ub->type, ub->code, state);
35399 + if (sync_needed) {
35405 + * ubicom32input_i2c_probe
35407 +static int __devinit ubicom32input_i2c_probe(struct i2c_client *client,
35408 + const struct i2c_device_id *id)
35411 + struct ubicom32input_i2c_data *ud;
35412 + struct input_polled_dev *poll_dev;
35413 + struct input_dev *input_dev;
35414 + struct ubicom32input_i2c_platform_data *pdata;
35416 + uint16_t invert_mask = 0;
35418 + pdata = client->dev.platform_data;
35423 + ud = kzalloc(sizeof(struct ubicom32input_i2c_data), GFP_KERNEL);
35427 + ud->pdata = pdata;
35428 + ud->client = client;
35429 + ud->ngpios = id->driver_data;
35431 + poll_dev = input_allocate_polled_device();
35437 + ud->poll_dev = poll_dev;
35438 + poll_dev->private = ud;
35439 + poll_dev->poll = ubicom32input_i2c_poll;
35442 + * Set the poll interval requested, default to 100 msec
35444 + if (pdata->poll_interval) {
35445 + poll_dev->poll_interval = pdata->poll_interval;
35447 + poll_dev->poll_interval = 100;
35451 + * Setup the input device
35453 + input_dev = poll_dev->input;
35454 + input_dev->name = pdata->name ? pdata->name : "Ubicom32 Input I2C";
35455 + input_dev->phys = "ubicom32input_i2c/input0";
35456 + input_dev->dev.parent = &client->dev;
35457 + input_dev->id.bustype = BUS_I2C;
35460 + * Set the capabilities
35462 + for (i = 0; i < pdata->nbuttons; i++) {
35463 + const struct ubicom32input_i2c_button *ub = &pdata->buttons[i];
35465 + if (ub->active_low) {
35466 + invert_mask |= (1 << ub->bit);
35469 + input_set_capability(input_dev,
35470 + ub->type ? ub->type : EV_KEY, ub->code);
35474 + * Setup the device (all inputs)
35476 + ret = ubicom32input_i2c_write_reg(ud, UBICOM32INPUT_I2C_REG_DIRECTION,
35482 + ret = ubicom32input_i2c_write_reg(ud, UBICOM32INPUT_I2C_REG_INVERT,
35491 + ret = input_register_polled_device(ud->poll_dev);
35496 + i2c_set_clientdata(client, ud);
35501 + printk(KERN_ERR "ubicom32input_i2c: Failed to register driver %d\n",
35503 + input_free_polled_device(poll_dev);
35509 + * ubicom32input_i2c_remove
35511 +static int __devexit ubicom32input_i2c_remove(struct i2c_client *client)
35513 + struct ubicom32input_i2c_data *ud =
35514 + (struct ubicom32input_i2c_data *)i2c_get_clientdata(client);
35516 + i2c_set_clientdata(client, NULL);
35517 + input_unregister_polled_device(ud->poll_dev);
35518 + input_free_polled_device(ud->poll_dev);
35525 +static struct i2c_driver ubicom32input_i2c_driver = {
35527 + .name = "ubicom32input_i2c",
35528 + .owner = THIS_MODULE,
35530 + .remove = __devexit_p(ubicom32input_i2c_remove),
35531 + .id_table = ubicom32input_i2c_id,
35532 + .probe = ubicom32input_i2c_probe,
35536 + * ubicom32input_i2c_init
35538 +static int __devinit ubicom32input_i2c_init(void)
35540 + return i2c_add_driver(&ubicom32input_i2c_driver);
35544 + * ubicom32input_i2c_exit
35546 +static void __exit ubicom32input_i2c_exit(void)
35548 + i2c_del_driver(&ubicom32input_i2c_driver);
35551 +module_init(ubicom32input_i2c_init);
35552 +module_exit(ubicom32input_i2c_exit);
35554 +MODULE_AUTHOR("Pat Tjin <pattjin@ubicom.com>");
35555 +MODULE_DESCRIPTION("Ubicom32 Input Driver I2C");
35556 +MODULE_LICENSE("GPL");
35557 +MODULE_ALIAS("platform:ubicom32-input");
35558 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/usb.c linux-2.6.30.10-ubi/arch/ubicom32/mach-common/usb.c
35559 --- linux-2.6.30.10/arch/ubicom32/mach-common/usb.c 1970-01-01 02:00:00.000000000 +0200
35560 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/usb.c 2009-12-11 11:45:11.000000000 +0200
35563 + * arch/ubicom32/mach-common/ip5k_usb.c
35564 + * Ubicom32 architecture usb support.
35566 + * (C) Copyright 2009, Ubicom, Inc.
35567 + * Copyright (C) 2007 MontaVista Software, Inc. <source@mvista.com>
35568 + * Author: Kevin Hilman
35570 + * This file is part of the Ubicom32 Linux Kernel Port.
35572 + * The Ubicom32 Linux Kernel Port is free software: you can
35573 + * redistribute it and/or modify it under the terms of the GNU General
35574 + * Public License as published by the Free Software Foundation, either
35575 + * version 2 of the License, or (at your option) any later version.
35577 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
35578 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
35579 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
35580 + * See the GNU General Public License for more details.
35582 + * You should have received a copy of the GNU General Public License
35583 + * along with the Ubicom32 Linux Kernel Port. If not,
35584 + * see <http://www.gnu.org/licenses/>.
35586 + * Ubicom32 implementation derived from (with many thanks):
35592 +#include <linux/types.h>
35593 +#include <linux/errno.h>
35594 +#include <linux/delay.h>
35595 +#include <linux/platform_device.h>
35596 +#include <linux/dma-mapping.h>
35597 +#include <linux/usb/musb.h>
35598 +#include <asm/devtree.h>
35599 +#include <asm/ip5000.h>
35600 +#include "usb_tio.h"
35602 +struct usbtionode *unode = NULL;
35604 +static struct resource usb_resources[] = {
35606 + .start = RJ + 0x800,
35607 + .end = RJ + 0x1000,
35608 + .flags = IORESOURCE_MEM,
35610 + [1] = { /* general IRQ */
35611 + .start = 1, /* this is a dummy value, the real irq number is passed from kernel_setup_param */
35612 + .flags = IORESOURCE_IRQ,
35617 +static struct musb_hdrc_eps_bits musb_eps[] = {
35618 + { "ep1_tx", 4, },
35619 + { "ep1_rx", 4, },
35620 + { "ep2_tx", 10, },
35621 + { "ep2_rx", 10, },
35622 + { "ep3_tx", 9, },
35623 + { "ep3_rx", 9, },
35624 + { "ep4_tx", 9, },
35625 + { "ep4_rx", 9, },
35626 + { "ep5_tx", 6, },
35627 + { "ep5_rx", 6, },
35630 +static struct musb_hdrc_config musb_config = {
35631 + .multipoint = true,
35632 + .dyn_fifo = false,
35633 + .soft_con = true,
35637 + .dma_channels = 0,
35639 + .eps_bits = musb_eps,
35642 +static struct musb_hdrc_platform_data usb_data = {
35643 +#ifdef CONFIG_USB_MUSB_OTG
35644 + .mode = MUSB_OTG,
35646 +#ifdef CONFIG_USB_MUSB_HDRC_HCD
35647 + .mode = MUSB_HOST,
35649 +#ifdef CONFIG_USB_GADGET_MUSB_HDRC
35650 + .mode = MUSB_PERIPHERAL,
35655 + .set_clock = NULL,
35656 + .config = &musb_config,
35659 +static struct platform_device musb_device = {
35660 + .name = "musb_hdrc",
35663 + .platform_data = &usb_data,
35664 + .dma_mask = NULL,
35665 + .coherent_dma_mask = 0,
35667 + .resource = usb_resources,
35668 + .num_resources = ARRAY_SIZE(usb_resources),
35671 +struct usbtio_node *usb_node = NULL;
35672 +void ubi32_usb_init(void)
35675 + * See if the usbtio is in the device tree.
35677 + usb_node = (struct usbtio_node *)devtree_find_node("usbtio");
35679 + printk(KERN_WARNING "usb init failed\n");
35683 + usb_resources[1].start = usb_node->dn.recvirq;
35684 + if (platform_device_register(&musb_device) < 0) {
35685 + printk(KERN_ERR "Unable to register HS-USB (MUSB) device\n");
35690 +void ubi32_usb_int_clr(void)
35692 + UBICOM32_IO_PORT(RJ)->int_clr = (1 << 3);
35694 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/usb_tio.c linux-2.6.30.10-ubi/arch/ubicom32/mach-common/usb_tio.c
35695 --- linux-2.6.30.10/arch/ubicom32/mach-common/usb_tio.c 1970-01-01 02:00:00.000000000 +0200
35696 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/usb_tio.c 2009-12-11 11:45:11.000000000 +0200
35699 + * arch/ubicom32/mach-common/usb_tio.c
35700 + * Linux side Ubicom USB TIO driver
35702 + * (C) Copyright 2009, Ubicom, Inc.
35704 + * This file is part of the Ubicom32 Linux Kernel Port.
35706 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
35707 + * it and/or modify it under the terms of the GNU General Public License
35708 + * as published by the Free Software Foundation, either version 2 of the
35709 + * License, or (at your option) any later version.
35711 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
35712 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
35713 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
35714 + * the GNU General Public License for more details.
35716 + * You should have received a copy of the GNU General Public License
35717 + * along with the Ubicom32 Linux Kernel Port. If not,
35718 + * see <http://www.gnu.org/licenses/>.
35720 + * Ubicom32 implementation derived from (with many thanks):
35725 +#include <linux/module.h>
35726 +#include <linux/spinlock.h>
35727 +#include <linux/slab.h>
35728 +#include <asm/devtree.h>
35729 +#include "usb_tio.h"
35732 +static DEFINE_SPINLOCK(tio_lock);
35733 +#define USB_TIO_LOCK(lock, flag) spin_lock_irqsave(lock, flag)
35734 +#define USB_TIO_UNLOCK(lock, flag) spin_unlock_irqrestore(lock, flag)
35735 +#define USB_TIO_LOCK_ISLOCKED(lock) spin_try_lock(lock)
35737 +#define USB_TIO_LOCK(lock, flag) local_irq_save(flag)
35738 +#define USB_TIO_UNLOCK(lock, flag) local_irq_restore(flag)
35741 +spinlock_t usb_tio_lock;
35744 + * usb_tio_set_hrt_interrupt()
35746 +static inline void usb_tio_set_hrt_interrupt(void)
35748 + ubicom32_set_interrupt(usb_node->dn.sendirq);
35751 +static inline void usb_tio_wait_hrt(void)
35753 + while (unlikely(usb_node->pdesc));
35756 +#if defined(USB_TIO_DEBUG)
35757 +static void usb_tio_request_verify_magic(volatile struct usb_tio_request *req)
35759 + BUG_ON(req->magic != USB_TIO_REQUEST_MAGIC2);
35762 +static void usb_tio_request_clear_magic(volatile struct usb_tio_request *req)
35768 +static void usb_tio_request_set_magic(volatile struct usb_tio_request *req)
35770 + req->magic = USB_TIO_REQUEST_MAGIC1;
35774 + * usb_tio_commit_request()
35776 +static inline void usb_tio_commit_request(volatile struct usb_tio_request *request)
35779 + usb_node->pdesc = request;
35782 + * next thing to do is alway checking if (usb_node->pdesc == NULL)
35783 + * to see if the request is done, so add a mb() here
35786 + usb_tio_set_hrt_interrupt();
35790 + * usb_tio_read_u16()
35791 + * Synchronously read 16 bits.
35793 +u8_t usb_tio_read_u16(u32_t address, u16_t *data)
35795 + volatile struct usb_tio_request *tio_req = &usb_node->request;
35796 + unsigned long flag;
35799 + * Wait for any previous request to complete and then make this request.
35801 + USB_TIO_LOCK(&tio_lock, flag);
35802 + usb_tio_wait_hrt();
35805 + * Fill in the request.
35807 + tio_req->address = address;
35808 + tio_req->cmd = USB_TIO_READ16_SYNC;
35809 + USB_TIO_REQUEST_SET_MAGIC(tio_req);
35810 + usb_tio_commit_request(tio_req);
35813 + * Wait for the result to show up.
35815 + usb_tio_wait_hrt();
35816 + USB_TIO_REQUEST_VERIFY_MAGIC(tio_req);
35817 + *data = (u16_t)tio_req->data;
35818 + USB_TIO_REQUEST_CLEAR_MAGIC(tio_req);
35819 + USB_TIO_UNLOCK(&tio_lock, flag);
35820 + return USB_TIO_OK;
35824 + * usb_tio_read_u8()
35825 + * Synchronously read 16 bits.
35827 +u8_t usb_tio_read_u8(u32_t address, u8_t *data)
35829 + volatile struct usb_tio_request *tio_req = &usb_node->request;
35830 + unsigned long flag;
35833 + * Wait for any previous request to complete and then make this request.
35835 + USB_TIO_LOCK(&tio_lock, flag);
35836 + usb_tio_wait_hrt();
35839 + * Fill in the request.
35841 + tio_req->address = address;
35842 + tio_req->cmd = USB_TIO_READ8_SYNC;
35843 + USB_TIO_REQUEST_SET_MAGIC(tio_req);
35846 + * commit the request
35848 + usb_tio_commit_request(tio_req);
35851 + * Wait for the result to show up.
35853 + usb_tio_wait_hrt();
35854 + USB_TIO_REQUEST_VERIFY_MAGIC(tio_req);
35855 + *data = (u8_t)tio_req->data;
35856 + USB_TIO_REQUEST_CLEAR_MAGIC(tio_req);
35857 + USB_TIO_UNLOCK(&tio_lock, flag);
35858 + return USB_TIO_OK;
35862 + * usb_tio_write_u16()
35863 + * Asynchronously write 16 bits.
35865 +u8_t usb_tio_write_u16(u32_t address, u16_t data)
35867 + volatile struct usb_tio_request *tio_req = &usb_node->request;
35868 + unsigned long flag;
35871 + * Wait for any previous write or pending read to complete.
35873 + USB_TIO_LOCK(&tio_lock, flag);
35874 + usb_tio_wait_hrt();
35876 + tio_req->address = address;
35877 + tio_req->data = data;
35878 + tio_req->cmd = USB_TIO_WRITE16_ASYNC;
35879 + USB_TIO_REQUEST_SET_MAGIC(tio_req);
35882 + * commit the request
35884 + usb_tio_commit_request(tio_req);
35885 + USB_TIO_UNLOCK(&tio_lock, flag);
35886 + return USB_TIO_OK;
35890 + * usb_tio_write_u8()
35891 + * Asynchronously write 8 bits.
35893 +u8_t usb_tio_write_u8(u32_t address, u8_t data)
35895 + volatile struct usb_tio_request *tio_req = &usb_node->request;
35896 + unsigned long flag;
35899 + * Wait for any previous write or pending read to complete.
35901 + USB_TIO_LOCK(&tio_lock, flag);
35902 + usb_tio_wait_hrt();
35904 + tio_req->address = address;
35905 + tio_req->data = data;
35906 + tio_req->cmd = USB_TIO_WRITE8_ASYNC;
35907 + USB_TIO_REQUEST_SET_MAGIC(tio_req);
35910 + * commit the request
35912 + usb_tio_commit_request(tio_req);
35913 + USB_TIO_UNLOCK(&tio_lock, flag);
35914 + return USB_TIO_OK;
35918 + * usb_tio_read_fifo()
35919 + * Synchronously read FIFO.
35921 +u8_t usb_tio_read_fifo(u32_t address, u32_t buffer, u32_t bytes)
35923 + volatile struct usb_tio_request *tio_req = &usb_node->request;
35924 + unsigned long flag;
35927 + * Wait for any previous request to complete and then make this request.
35929 + USB_TIO_LOCK(&tio_lock, flag);
35930 + usb_tio_wait_hrt();
35933 + * Fill in the request.
35935 + tio_req->address = address;
35936 + tio_req->cmd = USB_TIO_READ_FIFO_SYNC;
35937 + tio_req->buffer = buffer;
35938 + tio_req->transfer_length = bytes;
35939 + USB_TIO_REQUEST_SET_MAGIC(tio_req);
35942 + * commit the request
35944 + usb_tio_commit_request(tio_req);
35947 + * Wait for the result to show up.
35949 + usb_tio_wait_hrt();
35950 + USB_TIO_REQUEST_VERIFY_MAGIC(tio_req);
35951 + USB_TIO_REQUEST_CLEAR_MAGIC(tio_req);
35952 + USB_TIO_UNLOCK(&tio_lock, flag);
35953 + return USB_TIO_OK;
35957 + * usb_tio_write_fifo()
35958 + * Synchronously write 32 bits.
35960 +u8_t usb_tio_write_fifo(u32_t address, u32_t buffer, u32_t bytes)
35962 + volatile struct usb_tio_request *tio_req = &usb_node->request;
35963 + unsigned long flag;
35965 + USB_TIO_LOCK(&tio_lock, flag);
35966 + usb_tio_wait_hrt();
35968 + tio_req->address = address;
35969 + tio_req->buffer = buffer;
35970 + tio_req->cmd = USB_TIO_WRITE_FIFO_SYNC;
35971 + tio_req->transfer_length = bytes;
35972 + USB_TIO_REQUEST_SET_MAGIC(tio_req);
35974 + * commit the request
35976 + usb_tio_commit_request(tio_req);
35979 + * Wait for the result to show up.
35981 + usb_tio_wait_hrt();
35982 + USB_TIO_REQUEST_VERIFY_MAGIC(tio_req);
35983 + USB_TIO_REQUEST_CLEAR_MAGIC(tio_req);
35984 + USB_TIO_UNLOCK(&tio_lock, flag);
35985 + return USB_TIO_OK;
35989 + * usb_tio_write_fifo_async()
35990 + * Asynchronously write 32 bits.
35992 +u8_t usb_tio_write_fifo_async(u32_t address, u32_t buffer, u32_t bytes)
35994 + volatile struct usb_tio_request *tio_req = &usb_node->request;
35995 + unsigned long flag;
35997 + USB_TIO_LOCK(&tio_lock, flag);
35998 + usb_tio_wait_hrt();
36000 + tio_req->address = address;
36003 + * Is it necessary to make a local copy of the buffer? Any chance the URB is aborted before TIO finished the FIFO write?
36005 + tio_req->buffer = buffer;
36006 + tio_req->cmd = USB_TIO_WRITE_FIFO_SYNC;
36007 + tio_req->transfer_length = bytes;
36008 + USB_TIO_REQUEST_SET_MAGIC(tio_req);
36010 + * commit the request
36012 + usb_tio_commit_request(tio_req);
36013 + USB_TIO_UNLOCK(&tio_lock, flag);
36014 + return USB_TIO_OK;
36018 + * usb_tio_read_int_status()
36019 + * read and clear the interrupt status registers
36021 +void usb_tio_read_int_status(u8_t *int_usb, u16_t *int_tx, u16_t *int_rx)
36025 + * clear the interrupt must be syncronized with the TIO thread to prevent the racing condiiton
36026 + * that TIO thread try to set it at same time
36029 + "1: bset (%0), (%0), #0 \n\t" \
36030 + " jmpne.f 1b \n\t" \
36032 + : "a" (&usb_node->usb_vp_control)
36036 + *int_usb = usb_node->usb_vp_hw_int_usb;
36037 + *int_tx = cpu_to_le16(usb_node->usb_vp_hw_int_tx);
36038 + *int_rx = cpu_to_le16(usb_node->usb_vp_hw_int_rx);
36040 + //printk(KERN_INFO "int read %x, %x, %x\n", *int_usb, *int_tx, *int_rx);
36043 + * The interrupt status register is read-clean, so clear it now
36045 + usb_node->usb_vp_hw_int_usb = 0;
36046 + usb_node->usb_vp_hw_int_tx = 0;
36047 + usb_node->usb_vp_hw_int_rx = 0;
36050 + * release the lock bit
36052 + usb_node->usb_vp_control &= 0xfffe;
36054 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/usb_tio.h linux-2.6.30.10-ubi/arch/ubicom32/mach-common/usb_tio.h
36055 --- linux-2.6.30.10/arch/ubicom32/mach-common/usb_tio.h 1970-01-01 02:00:00.000000000 +0200
36056 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/usb_tio.h 2009-12-11 11:45:11.000000000 +0200
36059 + * arch/ubicom32/mach-common/usb_tio.h
36060 + * Definitions for usb_tio.c
36062 + * (C) Copyright 2009, Ubicom, Inc.
36064 + * This file is part of the Ubicom32 Linux Kernel Port.
36066 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
36067 + * it and/or modify it under the terms of the GNU General Public License
36068 + * as published by the Free Software Foundation, either version 2 of the
36069 + * License, or (at your option) any later version.
36071 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
36072 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
36073 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
36074 + * the GNU General Public License for more details.
36076 + * You should have received a copy of the GNU General Public License
36077 + * along with the Ubicom32 Linux Kernel Port. If not,
36078 + * see <http://www.gnu.org/licenses/>.
36080 + * Ubicom32 implementation derived from (with many thanks):
36086 +#include <linux/version.h>
36087 +#include <linux/kernel.h>
36088 +#include <linux/types.h>
36089 +#include <linux/errno.h>
36090 +#include <linux/err.h>
36091 +#include <asm/devtree.h>
36092 +#include <asm/ip5000.h>
36094 +#ifndef _USB_TIO_H
36095 +#define _USB_TIO_H
36097 +#undef USB_TIO_DEBUG
36099 +#define USB_TIO_REQUEST_MAGIC1 0x2307
36100 +#define USB_TIO_REQUEST_MAGIC2 0x0789
36101 +#if defined(USB_TIO_DEBUG)
36102 +#define USB_TIO_REQUEST_VERIFY_MAGIC(req) usb_tio_request_verify_magic(req)
36103 +#define USB_TIO_REQUEST_SET_MAGIC(req) usb_tio_request_set_magic(req)
36104 +#define USB_TIO_REQUEST_CLEAR_MAGIC(req) usb_tio_request_clear_magic(req)
36106 +#define USB_TIO_REQUEST_VERIFY_MAGIC(req)
36107 +#define USB_TIO_REQUEST_SET_MAGIC(req) usb_tio_request_set_magic(req)
36108 +#define USB_TIO_REQUEST_CLEAR_MAGIC(req)
36111 +enum USB_TIO_status {
36114 + USB_TIO_ERROR_COMMIT,
36117 +enum USB_TIO_cmds {
36118 + USB_TIO_READ16_SYNC,
36119 + USB_TIO_READ8_SYNC,
36120 + USB_TIO_READ_FIFO_SYNC,
36122 + USB_TIO_WRITE16_ASYNC,
36123 + USB_TIO_WRITE8_ASYNC,
36124 + USB_TIO_WRITE_FIFO_ASYNC,
36126 + USB_TIO_WRITE16_SYNC,
36127 + USB_TIO_WRITE8_SYNC,
36128 + USB_TIO_WRITE_FIFO_SYNC,
36132 +enum USB_TIO_state {
36134 + USB_TIO_DMA_SETUP,
36137 +struct usb_tio_request {
36138 + volatile u32_t address;
36140 + volatile u32_t data;
36141 + volatile u32_t buffer;
36143 + volatile u16_t cmd;
36144 + const volatile u16_t status;
36145 + volatile u32_t transfer_length;
36146 + volatile u32_t thread_mask;
36147 + volatile u16_t magic;
36150 +struct usbtio_node {
36151 + struct devtree_node dn;
36152 + volatile struct usb_tio_request * volatile pdesc;
36153 + struct usb_tio_request request;
36154 + volatile u32_t usb_vp_config;
36155 + volatile u32_t usb_vp_control;
36156 + const volatile u32_t usb_vp_status;
36157 + volatile u16_t usb_vp_hw_int_tx;
36158 + volatile u16_t usb_vp_hw_int_rx;
36159 + volatile u8_t usb_vp_hw_int_usb;
36160 + volatile u8_t usb_vp_hw_int_mask_usb;
36161 + volatile u16_t usb_vp_hw_int_mask_tx;
36162 + volatile u16_t usb_vp_hw_int_mask_rx;
36166 +extern struct usbtio_node *usb_node;
36167 +extern void ubi32_usb_init(void);
36169 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-common/vdc_tio.c linux-2.6.30.10-ubi/arch/ubicom32/mach-common/vdc_tio.c
36170 --- linux-2.6.30.10/arch/ubicom32/mach-common/vdc_tio.c 1970-01-01 02:00:00.000000000 +0200
36171 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-common/vdc_tio.c 2009-12-11 11:45:11.000000000 +0200
36174 + * arch/ubicom32/mach-common/vdc_tio.c
36175 + * Generic initialization for VDC
36177 + * (C) Copyright 2009, Ubicom, Inc.
36179 + * This file is part of the Ubicom32 Linux Kernel Port.
36181 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
36182 + * it and/or modify it under the terms of the GNU General Public License
36183 + * as published by the Free Software Foundation, either version 2 of the
36184 + * License, or (at your option) any later version.
36186 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
36187 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
36188 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
36189 + * the GNU General Public License for more details.
36191 + * You should have received a copy of the GNU General Public License
36192 + * along with the Ubicom32 Linux Kernel Port. If not,
36193 + * see <http://www.gnu.org/licenses/>.
36195 + * Ubicom32 implementation derived from (with many thanks):
36201 +#include <linux/platform_device.h>
36202 +#include <linux/types.h>
36204 +#include <asm/devtree.h>
36205 +#include <asm/vdc_tio.h>
36208 + * Resources that this driver uses
36210 +static struct resource vdc_tio_resources[] = {
36216 + * The init routine will query the devtree and fill this in
36218 + .flags = IORESOURCE_IRQ,
36222 + * Receive IRQ (optional)
36226 + * The init routine will query the devtree and fill this in
36228 + .flags = IORESOURCE_IRQ,
36232 + * Memory Mapped Registers
36236 + * The init routine will query the devtree and fill this in
36238 + .flags = IORESOURCE_MEM,
36243 + * The platform_device structure which is passed to the driver
36245 +static struct platform_device vdc_tio_platform_device = {
36246 + .name = "ubicom32fb",
36248 + .resource = vdc_tio_resources,
36249 + .num_resources = ARRAY_SIZE(vdc_tio_resources),
36254 + * Checks the device tree and instantiates the driver if found
36256 +void __init vdc_tio_init(void)
36259 + * Check the device tree for the vdc_tio
36261 + struct vdc_tio_node *vdc_node =
36262 + (struct vdc_tio_node *)devtree_find_node("vdctio");
36264 + printk(KERN_WARNING "No vdc_tio found\n");
36269 + * Fill in the resources and platform data from devtree information
36271 + vdc_tio_resources[0].start = vdc_node->dn.sendirq;
36272 + vdc_tio_resources[1].start = vdc_node->dn.recvirq;
36273 + vdc_tio_resources[2].start = (u32_t)vdc_node->regs;
36274 + vdc_tio_resources[2].end = (u32_t)vdc_node->regs +
36275 + sizeof(struct vdc_tio_vp_regs);
36278 + * Try to get the device registered
36280 + if (platform_device_register(&vdc_tio_platform_device) < 0) {
36281 + printk(KERN_WARNING "VDC failed to register\n");
36284 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-ip5k/board-ip5160dev.c linux-2.6.30.10-ubi/arch/ubicom32/mach-ip5k/board-ip5160dev.c
36285 --- linux-2.6.30.10/arch/ubicom32/mach-ip5k/board-ip5160dev.c 1970-01-01 02:00:00.000000000 +0200
36286 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-ip5k/board-ip5160dev.c 2009-12-11 11:45:11.000000000 +0200
36289 + * arch/ubicom32/mach-ip5k/board-ip5160dev.c
36290 + * Platform initialization for ip5160dev board.
36292 + * (C) Copyright 2009, Ubicom, Inc.
36294 + * This file is part of the Ubicom32 Linux Kernel Port.
36296 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
36297 + * it and/or modify it under the terms of the GNU General Public License
36298 + * as published by the Free Software Foundation, either version 2 of the
36299 + * License, or (at your option) any later version.
36301 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
36302 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
36303 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
36304 + * the GNU General Public License for more details.
36306 + * You should have received a copy of the GNU General Public License
36307 + * along with the Ubicom32 Linux Kernel Port. If not,
36308 + * see <http://www.gnu.org/licenses/>.
36310 + * Ubicom32 implementation derived from (with many thanks):
36315 +#include <linux/device.h>
36316 +#include <linux/platform_device.h>
36317 +#include <linux/gpio.h>
36319 +#include <asm/board.h>
36320 +#include <asm/machdep.h>
36321 +#ifdef CONFIG_SERIAL_UBI32_SERDES
36322 +#include <asm/ubicom32suart.h>
36326 + * Factory Default Button on the board at PXn
36327 + * TODO: This is just a placeholder and it needs to include proper header files
36329 +struct ubicom32fdb_platform_data {
36331 + bool fdb_polarity;
36334 +static struct ubicom32fdb_platform_data ip5160dev_fdb_data = {
36336 + .fdb_polarity = true,
36339 +static struct platform_device ip5160dev_fdb_device = {
36340 + .name = "ubicom32fdb",
36343 + .platform_data = &ip5160dev_fdb_data,
36347 +#ifdef CONFIG_SERIAL_UBI32_SERDES
36348 +static struct resource ip5160dev_ubicom32_suart_resources[] = {
36352 + .flags = IORESOURCE_MEM,
36355 + .start = PORT_OTHER_INT(RD),
36356 + .end = PORT_OTHER_INT(RD),
36357 + .flags = IORESOURCE_IRQ,
36360 + .start = 240000000,
36361 + .end = 240000000,
36362 + .flags = UBICOM32_SUART_IORESOURCE_CLOCK,
36366 +static struct platform_device ip5160dev_ubicom32_suart_device = {
36367 + .name = "ubicom32suart",
36369 + .num_resources = ARRAY_SIZE(ip5160dev_ubicom32_suart_resources),
36370 + .resource = ip5160dev_ubicom32_suart_resources,
36375 + * List of all devices in our system
36377 +static struct platform_device *ip5160dev_devices[] __initdata = {
36378 +#ifdef CONFIG_SERIAL_UBI32_SERDES
36379 + &ip5160dev_ubicom32_suart_device,
36381 + &ip5160dev_fdb_device,
36386 + * Called to add the devices which we have on this board
36388 +static int __init ip5160dev_init(void)
36391 + printk(KERN_INFO "%s: registering device resources\n", __FUNCTION__);
36392 + platform_add_devices(ip5160dev_devices, ARRAY_SIZE(ip5160dev_devices));
36396 +arch_initcall(ip5160dev_init);
36397 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-ip5k/board-ip5160rgw.c linux-2.6.30.10-ubi/arch/ubicom32/mach-ip5k/board-ip5160rgw.c
36398 --- linux-2.6.30.10/arch/ubicom32/mach-ip5k/board-ip5160rgw.c 1970-01-01 02:00:00.000000000 +0200
36399 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-ip5k/board-ip5160rgw.c 2009-12-11 11:45:11.000000000 +0200
36402 + * arch/ubicom32/mach-ip5k/board-ip5160rgw.c
36403 + * Platform initialization for ip5160rgw board.
36405 + * (C) Copyright 2009, Ubicom, Inc.
36407 + * This file is part of the Ubicom32 Linux Kernel Port.
36409 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
36410 + * it and/or modify it under the terms of the GNU General Public License
36411 + * as published by the Free Software Foundation, either version 2 of the
36412 + * License, or (at your option) any later version.
36414 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
36415 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
36416 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
36417 + * the GNU General Public License for more details.
36419 + * You should have received a copy of the GNU General Public License
36420 + * along with the Ubicom32 Linux Kernel Port. If not,
36421 + * see <http://www.gnu.org/licenses/>.
36423 + * Ubicom32 implementation derived from (with many thanks):
36428 +#include <linux/device.h>
36429 +#include <linux/platform_device.h>
36430 +#include <linux/gpio.h>
36431 +#include <asm/board.h>
36432 +#include <asm/machdep.h>
36435 + * Factory Default Button on the board at PXn
36436 + * TODO: This is just a placeholder and it needs to include proper header files
36438 +struct ubicom32fdb_platform_data {
36440 + bool fdb_polarity;
36443 +static struct ubicom32fdb_platform_data ip5160rgw_fdb_data = {
36445 + .fdb_polarity = true,
36448 +static struct platform_device ip5160rgw_fdb_device = {
36449 + .name = "ubicom32fdb",
36452 + .platform_data = &ip5160rgw_fdb_data,
36457 + * List of all devices in our system
36459 +static struct platform_device *ip5160rgw_devices[] __initdata = {
36460 + &ip5160rgw_fdb_device,
36465 + * Called to add the devices which we have on this board
36467 +static int __init ip5160rgw_init(void)
36470 + printk(KERN_INFO "%s: registering device resources\n", __FUNCTION__);
36471 + platform_add_devices(ip5160rgw_devices, ARRAY_SIZE(ip5160rgw_devices));
36475 +arch_initcall(ip5160rgw_init);
36476 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-ip5k/board-ip5170dpf.c linux-2.6.30.10-ubi/arch/ubicom32/mach-ip5k/board-ip5170dpf.c
36477 --- linux-2.6.30.10/arch/ubicom32/mach-ip5k/board-ip5170dpf.c 1970-01-01 02:00:00.000000000 +0200
36478 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-ip5k/board-ip5170dpf.c 2009-12-11 11:45:11.000000000 +0200
36481 + * arch/ubicom32/mach-ip5k/board-ip5170dpf.c
36482 + * Platform initialization for ip5160dpf board.
36484 + * (C) Copyright 2009, Ubicom, Inc.
36486 + * This file is part of the Ubicom32 Linux Kernel Port.
36488 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
36489 + * it and/or modify it under the terms of the GNU General Public License
36490 + * as published by the Free Software Foundation, either version 2 of the
36491 + * License, or (at your option) any later version.
36493 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
36494 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
36495 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
36496 + * the GNU General Public License for more details.
36498 + * You should have received a copy of the GNU General Public License
36499 + * along with the Ubicom32 Linux Kernel Port. If not,
36500 + * see <http://www.gnu.org/licenses/>.
36502 + * Ubicom32 implementation derived from (with many thanks):
36507 +#include <linux/device.h>
36508 +#include <linux/platform_device.h>
36509 +#include <linux/gpio.h>
36510 +#include <linux/leds.h>
36512 +#include <linux/i2c.h>
36513 +#include <linux/i2c-gpio.h>
36515 +#include <linux/input.h>
36516 +#include <asm/board.h>
36517 +#include <asm/machdep.h>
36518 +#include <asm/ubicom32hid.h>
36519 +#include <asm/vdc_tio.h>
36524 + * WLAN PD9 (Note this is shared with MISO, but we don't use it)
36527 + * TODO: check triggers, are they generic?
36529 +static struct gpio_led ip5170dpf_gpio_leds[] = {
36531 + .name = "d31:green:WLAN1",
36532 + .default_trigger = "WLAN1",
36533 + .gpio = GPIO_RD_9,
36537 + .name = "d30:green:WPS",
36538 + .default_trigger = "WPS",
36539 + .gpio = GPIO_RD_8,
36544 +static struct gpio_led_platform_data ip5170dpf_gpio_led_platform_data = {
36546 + .leds = ip5170dpf_gpio_leds,
36549 +static struct platform_device ip5170dpf_gpio_leds_device = {
36550 + .name = "leds-gpio",
36553 + .platform_data = &ip5170dpf_gpio_led_platform_data,
36558 + * Backlight on the board PD0, hardware PWM
36560 +static const struct ubicom32hid_button ip5170dpf_ubicom32hid_buttons[] = {
36568 + .code = KEY_LEFT,
36573 + .code = KEY_RIGHT,
36578 + .code = KEY_DOWN,
36583 + .code = KEY_ENTER,
36588 + .code = KEY_MENU,
36598 +static const struct ubicom32hid_ir ip5170dpf_ubicom32hid_ircodes[] = {
36602 + .ir_code = 0xF807916E
36606 + .code = KEY_DOWN,
36607 + .ir_code = 0xF20D916E
36611 + .code = KEY_LEFT,
36612 + .ir_code = 0xF609916E
36616 + .code = KEY_RIGHT,
36617 + .ir_code = 0xF40B916E
36621 + .code = KEY_ENTER,
36622 + .ir_code = 0xF50A916E
36626 + .code = KEY_FN_F1,
36627 + .ir_code = 0xF906916E
36631 + .code = KEY_MENU,
36632 + .ir_code = 0xF708916E
36634 + { /* font size */
36636 + .code = KEY_FN_F2,
36637 + .ir_code = 0xF30C916E
36642 + .ir_code = 0xF10E916E
36646 + .code = KEY_VOLUMEUP,
36647 + .ir_code = 0xF00F916E
36651 + .code = KEY_VOLUMEDOWN,
36652 + .ir_code = 0xED12916E
36656 + .code = KEY_MUTE,
36657 + .ir_code = 0xEA15916E
36661 + .code = KEY_INFO,
36662 + .ir_code = 0xEF10916E
36666 + .code = KEY_FN_F3,
36667 + .ir_code = 0xEE11916E
36671 + .code = KEY_FN_F4,
36672 + .ir_code = 0xEB14916E
36676 + .code = KEY_POWER,
36677 + .ir_code = 0xFD02916E
36681 +static struct ubicom32hid_platform_data ip5170dpf_ubicom32hid_platform_data = {
36682 + .gpio_reset = GPIO_RA_4,
36683 + .gpio_reset_polarity = 0,
36684 + .type = UBICOM32HID_BL_TYPE_BINARY,
36686 + .default_intensity = 1,
36687 + .buttons = ip5170dpf_ubicom32hid_buttons,
36688 + .nbuttons = ARRAY_SIZE(ip5170dpf_ubicom32hid_buttons),
36689 + .ircodes = ip5170dpf_ubicom32hid_ircodes,
36690 + .nircodes = ARRAY_SIZE(ip5170dpf_ubicom32hid_ircodes),
36694 + * Devices on the I2C bus
36696 +static struct i2c_board_info __initdata ip5170dpf_i2c_board_info[] = {
36698 + * U24, ubicom32hid
36701 + .type = "ubicom32hid",
36703 + .platform_data = &ip5170dpf_ubicom32hid_platform_data,
36707 + * U14, CS4350 DAC, address 0x4B
36712 + * I2C bus on the board, SDA PF13, SCL PF14
36714 +static struct i2c_gpio_platform_data ip5170dpf_i2c_data = {
36715 + .sda_pin = GPIO_RF_13,
36716 + .scl_pin = GPIO_RF_14,
36717 + .sda_is_open_drain = 0,
36718 + .scl_is_open_drain = 0,
36719 + .scl_is_output_only = 1,
36723 +static struct platform_device ip5170dpf_i2c_device = {
36724 + .name = "i2c-gpio",
36727 + .platform_data = &ip5170dpf_i2c_data,
36732 + * List of all devices in our system
36734 +static struct platform_device *ip5170dpf_devices[] __initdata = {
36735 + &ip5170dpf_i2c_device,
36736 + &ip5170dpf_gpio_leds_device,
36741 + * Called to add the devices which we have on this board
36743 +static int __init ip5170dpf_init(void)
36749 + printk(KERN_INFO "%s: registering device resources\n", __FUNCTION__);
36750 + platform_add_devices(ip5170dpf_devices, ARRAY_SIZE(ip5170dpf_devices));
36752 + printk(KERN_INFO "%s: registering i2c resources\n", __FUNCTION__);
36753 + i2c_register_board_info(0, ip5170dpf_i2c_board_info, ARRAY_SIZE(ip5170dpf_i2c_board_info));
36758 +arch_initcall(ip5170dpf_init);
36759 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-ip5k/Kconfig linux-2.6.30.10-ubi/arch/ubicom32/mach-ip5k/Kconfig
36760 --- linux-2.6.30.10/arch/ubicom32/mach-ip5k/Kconfig 1970-01-01 02:00:00.000000000 +0200
36761 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-ip5k/Kconfig 2009-12-11 11:45:11.000000000 +0200
36766 + select UBICOM32_V3
36770 + select FB_UBICOM32
36771 + select BACKLIGHT_LCD_SUPPORT
36772 + select BACKLIGHT_CLASS_DEVICE
36773 + select UBICOM_HID
36775 + select LEDS_CLASS
36778 + IP5170 Digital Picture Frame board, 8005-1113, IP5K-BEV-0011-13 v1.3
36781 + bool "IP5160Dev_Ver1Dot1"
36782 + select UBICOM32_V3
36784 + Ubicom StreamEngine 5000 Development Board, IP5K-BDV-0004-11 v1.1
36787 + bool "IP5160RGWEval_Ver2Rev2"
36788 + select UBICOM32_V3
36790 + Ubicom StreamEngine 5000 RGW Evaluation Board, IP5K-RGW-0004-11 v2.2
36791 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-ip5k/Makefile linux-2.6.30.10-ubi/arch/ubicom32/mach-ip5k/Makefile
36792 --- linux-2.6.30.10/arch/ubicom32/mach-ip5k/Makefile 1970-01-01 02:00:00.000000000 +0200
36793 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-ip5k/Makefile 2009-12-11 11:45:11.000000000 +0200
36796 +# arch/ubicom32/mach-ip5k/Makefile
36797 +# Makefile for boards which have an ip5k on them.
36799 +# (C) Copyright 2009, Ubicom, Inc.
36801 +# This file is part of the Ubicom32 Linux Kernel Port.
36803 +# The Ubicom32 Linux Kernel Port is free software: you can redistribute
36804 +# it and/or modify it under the terms of the GNU General Public License
36805 +# as published by the Free Software Foundation, either version 2 of the
36806 +# License, or (at your option) any later version.
36808 +# The Ubicom32 Linux Kernel Port is distributed in the hope that it
36809 +# will be useful, but WITHOUT ANY WARRANTY; without even the implied
36810 +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
36811 +# the GNU General Public License for more details.
36813 +# You should have received a copy of the GNU General Public License
36814 +# along with the Ubicom32 Linux Kernel Port. If not,
36815 +# see <http://www.gnu.org/licenses/>.
36817 +# Ubicom32 implementation derived from (with many thanks):
36823 +obj-$(CONFIG_IP5170DPF) += board-ip5170dpf.o
36824 +obj-$(CONFIG_IP5160DEV) += board-ip5160dev.o
36825 +obj-$(CONFIG_IP5160EVAL) += board-ip5160rgw.o
36826 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-ip7k/board-ip7145dpf.c linux-2.6.30.10-ubi/arch/ubicom32/mach-ip7k/board-ip7145dpf.c
36827 --- linux-2.6.30.10/arch/ubicom32/mach-ip7k/board-ip7145dpf.c 1970-01-01 02:00:00.000000000 +0200
36828 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-ip7k/board-ip7145dpf.c 2009-12-11 11:45:11.000000000 +0200
36831 + * arch/ubicom32/mach-ip7k/board-ip7145dpf.c
36832 + * Board file for IP7145DPF, rev 1.0, P/N 8007-0410
36834 + * (C) Copyright 2009, Ubicom, Inc.
36836 + * This file is part of the Ubicom32 Linux Kernel Port.
36838 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
36839 + * it and/or modify it under the terms of the GNU General Public License
36840 + * as published by the Free Software Foundation, either version 2 of the
36841 + * License, or (at your option) any later version.
36843 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
36844 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
36845 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
36846 + * the GNU General Public License for more details.
36848 + * You should have received a copy of the GNU General Public License
36849 + * along with the Ubicom32 Linux Kernel Port. If not,
36850 + * see <http://www.gnu.org/licenses/>.
36852 + * Ubicom32 implementation derived from (with many thanks):
36857 +#include <linux/device.h>
36858 +#include <linux/platform_device.h>
36859 +#include <linux/gpio.h>
36861 +#include <linux/input.h>
36863 +#include <linux/i2c.h>
36864 +#include <linux/i2c-gpio.h>
36865 +#include <linux/i2c/pca953x.h>
36867 +#include <asm/board.h>
36868 +#include <asm/machdep.h>
36869 +#include <asm/ubicom32input.h>
36870 +#include <asm/ubicom32input_i2c.h>
36871 +#include <asm/ubicom32bl.h>
36872 +#include <asm/ubicom32lcdpower.h>
36873 +#include <asm/vdc_tio.h>
36875 +#include <asm/ubicom32sd.h>
36876 +#include <asm/sd_tio.h>
36877 +#include <asm/devtree.h>
36878 +#include <asm/audio.h>
36880 +#include <asm/ring_tio.h>
36882 +/******************************************************************************
36883 + * SD/IO Port F (Slot 1) platform data
36885 +static struct resource ip7145dpf_portf_sd_resources[] = {
36891 + * The init routine will query the devtree and fill this in
36893 + .flags = IORESOURCE_IRQ,
36901 + * The init routine will query the devtree and fill this in
36903 + .flags = IORESOURCE_IRQ,
36907 + * Memory Mapped Registers
36911 + * The init routine will query the devtree and fill this in
36913 + .flags = IORESOURCE_MEM,
36917 +static struct ubicom32sd_card ip7145dpf_portf_sd_cards[] = {
36919 + .pin_wp = IP7145DPF_IOB0,
36920 + .wp_polarity = 1,
36921 + .pin_pwr = IP7145DPF_IOB4,
36922 + .pin_cd = GPIO_RA_4,
36925 + .pin_wp = IP7145DPF_IOB1,
36926 + .wp_polarity = 1,
36927 + .pin_pwr = IP7145DPF_IOB5,
36928 + .pin_cd = GPIO_RA_6,
36932 +static struct ubicom32sd_platform_data ip7145dpf_portf_sd_platform_data = {
36934 + .cards = ip7145dpf_portf_sd_cards,
36937 +static struct platform_device ip7145dpf_portf_sd_device = {
36938 + .name = "ubicom32sd",
36940 + .resource = ip7145dpf_portf_sd_resources,
36941 + .num_resources = ARRAY_SIZE(ip7145dpf_portf_sd_resources),
36943 + .platform_data = &ip7145dpf_portf_sd_platform_data,
36949 + * ip7145dpf_portf_sd_init
36951 +static void ip7145dpf_portf_sd_init(void)
36954 + * Check the device tree for the sd_tio
36956 + struct sd_tio_node *sd_node = (struct sd_tio_node *)devtree_find_node("portf_sd");
36958 + printk(KERN_INFO "PortF SDTIO not found\n");
36963 + * Fill in the resources and platform data from devtree information
36965 + ip7145dpf_portf_sd_resources[0].start = sd_node->dn.sendirq;
36966 + ip7145dpf_portf_sd_resources[1].start = sd_node->dn.recvirq;
36967 + ip7145dpf_portf_sd_resources[2].start = (u32_t)&(sd_node->regs);
36968 + ip7145dpf_portf_sd_resources[2].end = (u32_t)&(sd_node->regs) + sizeof(sd_node->regs);
36970 + platform_device_register(&ip7145dpf_portf_sd_device);
36973 +/******************************************************************************
36974 + * SD/IO Port B (Slot 2) platform data
36976 +static struct resource ip7145dpf_portb_sd_resources[] = {
36982 + * The init routine will query the devtree and fill this in
36984 + .flags = IORESOURCE_IRQ,
36992 + * The init routine will query the devtree and fill this in
36994 + .flags = IORESOURCE_IRQ,
36998 + * Memory Mapped Registers
37002 + * The init routine will query the devtree and fill this in
37004 + .flags = IORESOURCE_MEM,
37008 +static struct ubicom32sd_card ip7145dpf_portb_sd_cards[] = {
37010 + .pin_wp = IP7145DPF_IOB2,
37011 + .wp_polarity = 1,
37012 + .pin_pwr = IP7145DPF_IOB6,
37013 + .pin_cd = IP7145DPF_IOB3,
37017 +static struct ubicom32sd_platform_data ip7145dpf_portb_sd_platform_data = {
37019 + .cards = ip7145dpf_portb_sd_cards,
37022 +static struct platform_device ip7145dpf_portb_sd_device = {
37023 + .name = "ubicom32sd",
37025 + .resource = ip7145dpf_portb_sd_resources,
37026 + .num_resources = ARRAY_SIZE(ip7145dpf_portb_sd_resources),
37028 + .platform_data = &ip7145dpf_portb_sd_platform_data,
37034 + * ip7145dpf_portb_sd_init
37036 +static void ip7145dpf_portb_sd_init(void)
37039 + * Check the device tree for the sd_tio
37041 + struct sd_tio_node *sd_node = (struct sd_tio_node *)devtree_find_node("portb_sd");
37043 + printk(KERN_INFO "PortB SDTIO not found\n");
37048 + * Fill in the resources and platform data from devtree information
37050 + ip7145dpf_portb_sd_resources[0].start = sd_node->dn.sendirq;
37051 + ip7145dpf_portb_sd_resources[1].start = sd_node->dn.recvirq;
37052 + ip7145dpf_portb_sd_resources[2].start = (u32_t)&(sd_node->regs);
37053 + ip7145dpf_portb_sd_resources[2].end = (u32_t)&(sd_node->regs) + sizeof(sd_node->regs);
37055 + platform_device_register(&ip7145dpf_portb_sd_device);
37059 +#ifdef IP7145DPF_USE_MMC_SPI
37060 +/******************************************************************************
37061 + * SPI over GPIO (MMC_SPI)
37063 +#include <linux/spi/spi.h>
37064 +#include <linux/spi/mmc_spi.h>
37065 +#include <linux/mmc/host.h>
37066 +#include <asm/ubicom32-spi-gpio.h>
37068 +#define MMC_CS GPIO_RF_5 // PF5 D3
37069 +#define MMC_CD GPIO_RA_4 // PA4 CD
37070 +#define MMC_WP IP7145DPF_IOB0 // IOB0 WP
37071 +#define MMC_PWR IP7145DPF_IOB4 // IOB4 PWR
37074 + * SPI bus over GPIO (for SD card)
37076 +static struct ubicom32_spi_gpio_platform_data ip7145dpf_spi_gpio_data = {
37077 + .pin_mosi = GPIO_RF_0, // PF0 CMD
37078 + .pin_miso = GPIO_RF_2, // PF2 D0
37079 + .pin_clk = GPIO_RF_1, // PF1 CLK
37080 + .bus_num = 0, // We'll call this SPI bus 0
37081 + .num_chipselect = 1, // only one device on this SPI bus
37084 +static struct platform_device ip7145dpf_spi_gpio_device = {
37085 + .name = "ubicom32-spi-gpio",
37088 + .platform_data = &ip7145dpf_spi_gpio_data,
37093 + * ip7145dpf_mmc_spi_setpower_slot_a
37094 + * Set the power state for slot A
37096 +static void ip7145dpf_mmc_spi_setpower_slot_a(struct device *dev, unsigned int vdd)
37098 + struct mmc_spi_platform_data *pd = dev->platform_data;
37101 + * Power is inverted, we could tell the IOB to do it, but it's cleaner this way.
37103 + if ((1 << vdd) & pd->ocr_mask) {
37104 + gpio_set_value(MMC_PWR, 0);
37107 + gpio_set_value(MMC_PWR, 1);
37111 + * ip7145dpf_mmc_spi_get_cd_slot_a
37112 + * Get the CD bit for slot A
37114 +static int ip7145dpf_mmc_spi_get_cd_slot_a(struct device *dev)
37117 + * Note that the sense of the GPIO is inverted
37119 + return !gpio_get_value(MMC_CD);
37123 + * ip7145dpf_mmc_spi_get_ro_slot_a
37124 + * Get the WP bit for slot A
37126 +static int ip7145dpf_mmc_spi_get_ro_slot_a(struct device *dev)
37129 + * Note that the sense of the GPIO is inverted, we could tell the IOB to do it, but
37130 + * it's clearer this way.
37132 + return !gpio_get_value(MMC_WP);
37136 + * ip7145dpf_mmc_spi_exit_slot_a
37137 + * Free the appropriate GPIOs for slot A SD slot.
37139 +static void ip7145dpf_mmc_spi_exit_slot_a(struct device *dev, void *appdata)
37141 + gpio_free(MMC_CD);
37142 + gpio_free(MMC_CS);
37143 + gpio_free(MMC_WP);
37144 + gpio_free(MMC_PWR);
37145 + platform_device_unregister(&ip7145dpf_spi_gpio_device);
37149 + * ip7145dpf_mmc_spi_init_slot_a
37150 + * Allocate the appropriate GPIOs for slot A SD slot.
37151 + * WP is on IOB0, CD is PA4, CS is on PF5
37152 + * TODO: make CD an interrupt
37154 +static int ip7145dpf_mmc_spi_init_slot_a(void)
37156 + int ret = gpio_request(MMC_CD, "mmc-a-cd");
37158 + printk(KERN_ERR "%s: could not request mmc-a-cd pin\n", __FUNCTION__);
37161 + gpio_direction_input(MMC_CD);
37163 + ret = gpio_request(MMC_CS, "mmc-a-cs");
37165 + printk(KERN_ERR "%s: could not request mmc-a-cs pin\n", __FUNCTION__);
37168 + gpio_direction_output(MMC_CS, 0);
37170 + ret = gpio_request(MMC_WP, "mmc-a-wp");
37172 + printk(KERN_ERR "%s: could not request mmc-a-wp pin\n", __FUNCTION__);
37175 + gpio_direction_input(MMC_WP);
37178 + * Start off with power off
37180 + ret = gpio_request(MMC_PWR, "mmc-a-pwr");
37182 + printk(KERN_ERR "%s: could not request mmc-a-pwr pin\n", __FUNCTION__);
37185 + ret = gpio_direction_output(MMC_PWR, 1);
37190 + gpio_free(MMC_WP);
37193 + gpio_free(MMC_CS);
37196 + gpio_free(MMC_CD);
37201 + * MMC_SPI driver (currently bitbang)
37203 +static struct mmc_spi_platform_data ip7145dpf_mmc_platform_data = {
37204 + .ocr_mask = MMC_VDD_33_34,
37205 + .exit = ip7145dpf_mmc_spi_exit_slot_a,
37206 + .get_ro = ip7145dpf_mmc_spi_get_ro_slot_a,
37207 + .get_cd = ip7145dpf_mmc_spi_get_cd_slot_a,
37209 + .setpower = ip7145dpf_mmc_spi_setpower_slot_a,
37210 + .powerup_msecs = 500,
37212 + .detect_delay = 100,
37214 + .caps = MMC_CAP_NEEDS_POLL,
37217 +static struct ubicom32_spi_gpio_controller_data ip7145dpf_mmc_controller_data = {
37218 + .pin_cs = MMC_CS,
37221 +static struct spi_board_info ip7145dpf_spi_board_info[] = {
37223 + .modalias = "mmc_spi",
37225 + .chip_select = 0,
37226 + .max_speed_hz = 2000000,
37227 + .platform_data = &ip7145dpf_mmc_platform_data,
37228 + .controller_data = &ip7145dpf_mmc_controller_data,
37231 +#endif /* IP7145DPF_USE_MMC_SPI */
37234 + * ip7145dpf_u72_setup
37235 + * Called by I2C to tell us that u72 is setup.
37237 + * This function is called by I2C to tell us that u72 has been setup. All
37238 + * devices which rely on this chip being initialized (or even present) need to
37239 + * be initialized in this function otherwise they may get initialized too early.
37241 + * Currently the only device depending on u72 is the SPI
37243 +static int __init ip7145dpf_u72_setup(struct i2c_client *client, unsigned gpio, unsigned ngpio, void *context)
37245 +#ifdef IP7145DPF_USE_MMC_SPI
37246 + if (ip7145dpf_mmc_spi_init_slot_a()) {
37247 + printk(KERN_ERR "%s: could not request mmc resources\n", __FUNCTION__);
37249 + printk(KERN_INFO "%s: registering SPI resources\n", __FUNCTION__);
37250 + spi_register_board_info(ip7145dpf_spi_board_info, ARRAY_SIZE(ip7145dpf_spi_board_info));
37251 + platform_device_register(&ip7145dpf_spi_gpio_device);
37255 + * Initialize the Port F/Port B SD slots
37257 + ip7145dpf_portf_sd_init();
37258 + ip7145dpf_portb_sd_init();
37263 +/******************************************************************************
37264 + * LCD VGH on the board at PE6
37266 +static struct ubicom32lcdpower_platform_data ip7145dpf_lcdpower_data = {
37267 + .vgh_gpio = GPIO_RE_6,
37268 + .vgh_polarity = true,
37271 +static struct platform_device ip7145dpf_lcdpower_device = {
37272 + .name = "ubicom32lcdpower",
37275 + .platform_data = &ip7145dpf_lcdpower_data,
37279 +/******************************************************************************
37280 + * Backlight on the board PD0, hardware PWM
37282 +static struct ubicom32bl_platform_data ip7145dpf_backlight_data = {
37283 + .type = UBICOM32BL_TYPE_PWM,
37284 + .pwm_channel = 2,
37285 + .pwm_prescale = 15,
37286 + .pwm_period = 60,
37287 + .default_intensity = 0x80,
37290 +static struct platform_device ip7145dpf_backlight_device = {
37291 + .name = "ubicom32bl",
37294 + .platform_data = &ip7145dpf_backlight_data,
37298 +/******************************************************************************
37299 + * Ubicom32Input on I2C, U48 MAX7310, address 0x18, 8 bits
37301 +static struct ubicom32input_i2c_button ip7145dpf_ubicom32input_i2c_u48_buttons[] = {
37310 + .code = KEY_LEFT,
37316 + .code = KEY_RIGHT,
37322 + .code = KEY_DOWN,
37328 + .code = KEY_ENTER,
37334 + .code = KEY_MENU,
37346 +static struct ubicom32input_i2c_platform_data ip7145dpf_ubicom32input_i2c_u48_platform_data = {
37347 + .buttons = ip7145dpf_ubicom32input_i2c_u48_buttons,
37348 + .nbuttons = ARRAY_SIZE(ip7145dpf_ubicom32input_i2c_u48_buttons),
37349 + .name = "Ubicom32 Input I2C U48",
37352 +/******************************************************************************
37353 + * Additional GPIO chips
37355 +static struct pca953x_platform_data ip7145dpf_gpio_u72_platform_data = {
37356 + .gpio_base = IP7145DPF_U72_BASE,
37357 + .setup = ip7145dpf_u72_setup,
37360 +/******************************************************************************
37361 + * Devices on the I2C bus
37363 +static struct i2c_board_info __initdata ip7145dpf_i2c_board_info[] = {
37365 + * U51, S35390A RTC, address 0x30
37368 + .type = "s35390a",
37373 + * U48, MAX7310 IO expander, 8 bits, address 0x18
37376 + .type = "ubicom32in_max7310",
37378 + .platform_data = &ip7145dpf_ubicom32input_i2c_u48_platform_data,
37382 + * U72, MAX7310 IOB expander, 8 bits, address 0x19
37385 + .type = "max7310",
37387 + .platform_data = &ip7145dpf_gpio_u72_platform_data,
37392 + * I2C bus on the board, SDA PE1, SCL PE2
37394 +static struct i2c_gpio_platform_data ip7145dpf_i2c_data = {
37395 + .sda_pin = GPIO_RE_1,
37396 + .scl_pin = GPIO_RE_2,
37397 + .sda_is_open_drain = 0,
37398 + .scl_is_open_drain = 0,
37401 +static struct platform_device ip7145dpf_i2c_device = {
37402 + .name = "i2c-gpio",
37405 + .platform_data = &ip7145dpf_i2c_data,
37409 +/******************************************************************************
37410 + * Use ubicom32input driver to monitor the various pushbuttons on this board.
37413 + * FACT_DEFAULT PF13
37416 + * Not sutable for the keypad buttons since those run on I2C GPIO. The polling
37417 + * of ubicom32input would seem to be excessive for this.
37419 + * TODO: pick some ubicom understood EV_xxx define for WPS and Fact Default
37421 +static struct ubicom32input_button ip7145dpf_ubicom32input_buttons[] = {
37424 + .code = KEY_FN_F1,
37425 + .gpio = GPIO_RF_12,
37431 + .code = KEY_FN_F2,
37432 + .gpio = GPIO_RF_13,
37433 + .desc = "Factory Default",
37438 + .code = KEY_POWER,
37439 + .gpio = GPIO_RE_4,
37445 +static struct ubicom32input_platform_data ip7145dpf_ubicom32input_data = {
37446 + .buttons = ip7145dpf_ubicom32input_buttons,
37447 + .nbuttons = ARRAY_SIZE(ip7145dpf_ubicom32input_buttons),
37450 +static struct platform_device ip7145dpf_ubicom32input_device = {
37451 + .name = "ubicom32input",
37454 + .platform_data = &ip7145dpf_ubicom32input_data,
37459 + * List of all devices in our system
37461 +static struct platform_device *ip7145dpf_devices[] __initdata = {
37462 + &ip7145dpf_i2c_device,
37463 + &ip7145dpf_lcdpower_device,
37464 + &ip7145dpf_backlight_device,
37465 + &ip7145dpf_ubicom32input_device,
37469 + * ip7145dpf_power_off
37470 + * Called to turn the power off for this board
37472 +static void ip7145dpf_power_off(void)
37474 + gpio_set_value(GPIO_RE_5, 0);
37479 + * Called to add the devices which we have on this board
37481 +static int __init ip7145dpf_init(void)
37484 + struct platform_device *audio_dev;
37488 +#ifdef CONFIG_UIO_UBICOM32RING
37489 + ring_tio_init("decoder_ring");
37493 + * Start up the video driver first
37498 + * Take over holding of the power from the system
37500 + ret = gpio_request(GPIO_RE_5, "power_hold");
37502 + printk(KERN_ERR "%s: could not request power hold GPIO\n", __FUNCTION__);
37504 + gpio_direction_output(GPIO_RE_5, 1);
37505 + mach_power_off = ip7145dpf_power_off;
37508 + * USB SEL_HOST_USB line
37510 + ret = gpio_request(GPIO_RF_11, "SEL_HOST_USB");
37512 + printk(KERN_ERR "%s: could not request SEL_HOST_USB GPIO\n", __FUNCTION__);
37514 + gpio_direction_output(GPIO_RF_11, 0);
37519 + audio_dev = audio_device_alloc("snd-ubi32-generic", "audio", "audio-i2sout", 0);
37521 + platform_device_register(audio_dev);
37525 + * Register all of the devices we have on this board
37527 + printk(KERN_INFO "%s: registering device resources\n", __FUNCTION__);
37528 + platform_add_devices(ip7145dpf_devices, ARRAY_SIZE(ip7145dpf_devices));
37531 + * Register all of the devices which sit on the I2C bus
37533 + printk(KERN_INFO "%s: registering i2c resources\n", __FUNCTION__);
37534 + i2c_register_board_info(0, ip7145dpf_i2c_board_info, ARRAY_SIZE(ip7145dpf_i2c_board_info));
37537 + * We have to initialize the SPI after the I2C IOB gets setup. SPI is initialized in
37538 + * ip7145dpf_u72_setup
37544 +arch_initcall(ip7145dpf_init);
37545 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-ip7k/board-ip7160bringup.c linux-2.6.30.10-ubi/arch/ubicom32/mach-ip7k/board-ip7160bringup.c
37546 --- linux-2.6.30.10/arch/ubicom32/mach-ip7k/board-ip7160bringup.c 1970-01-01 02:00:00.000000000 +0200
37547 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-ip7k/board-ip7160bringup.c 2009-12-11 11:45:11.000000000 +0200
37550 + * arch/ubicom32/mach-ip7k/board-ip7160bringup.c
37551 + * Support for the IP7160 bringup board.
37553 + * (C) Copyright 2009, Ubicom, Inc.
37555 + * This file is part of the Ubicom32 Linux Kernel Port.
37557 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
37558 + * it and/or modify it under the terms of the GNU General Public License
37559 + * as published by the Free Software Foundation, either version 2 of the
37560 + * License, or (at your option) any later version.
37562 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
37563 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
37564 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
37565 + * the GNU General Public License for more details.
37567 + * You should have received a copy of the GNU General Public License
37568 + * along with the Ubicom32 Linux Kernel Port. If not,
37569 + * see <http://www.gnu.org/licenses/>.
37571 + * Ubicom32 implementation derived from (with many thanks):
37576 +#include <linux/device.h>
37577 +#include <linux/platform_device.h>
37578 +#include <linux/gpio.h>
37579 +#include <linux/leds.h>
37580 +#include <linux/delay.h>
37581 +#include <linux/input.h>
37583 +#include <asm/board.h>
37584 +#include <asm/machdep.h>
37585 +#include <asm/ubicom32input.h>
37587 +#ifdef CONFIG_SERIAL_UBI32_SERDES
37588 +#include <asm/ubicom32suart.h>
37592 + * Use ubicom32input driver to monitor the various pushbuttons on this board.
37595 + * FACT_DEFAULT PD6
37597 + * TODO: pick some ubicom understood EV_xxx define for WPS and Fact Default
37599 +static struct ubicom32input_button ip7160bringup_ubicom32input_buttons[] = {
37602 + .code = KEY_FN_F1,
37603 + .gpio = GPIO_RD_5,
37609 + .code = KEY_FN_F2,
37610 + .gpio = GPIO_RD_6,
37611 + .desc = "Factory Default",
37616 +static struct ubicom32input_platform_data ip7160bringup_ubicom32input_data = {
37617 + .buttons = ip7160bringup_ubicom32input_buttons,
37618 + .nbuttons = ARRAY_SIZE(ip7160bringup_ubicom32input_buttons),
37621 +static struct platform_device ip7160bringup_ubicom32input_device = {
37622 + .name = "ubicom32input",
37625 + .platform_data = &ip7160bringup_ubicom32input_data,
37629 +#ifdef CONFIG_SERIAL_UBI32_SERDES
37630 +static struct resource ip7160bringup_ubicom32_suart_resources[] = {
37634 + .flags = IORESOURCE_MEM,
37637 + .start = PORT_OTHER_INT(RE),
37638 + .end = PORT_OTHER_INT(RE),
37639 + .flags = IORESOURCE_IRQ,
37642 + .start = 250000000,
37643 + .end = 250000000,
37644 + .flags = UBICOM32_SUART_IORESOURCE_CLOCK,
37648 +static struct platform_device ip7160bringup_ubicom32_suart_device = {
37649 + .name = "ubicom32suart",
37651 + .num_resources = ARRAY_SIZE(ip7160bringup_ubicom32_suart_resources),
37652 + .resource = ip7160bringup_ubicom32_suart_resources,
37657 + * List of all devices in our system
37659 +static struct platform_device *ip7160bringup_devices[] __initdata = {
37660 +#ifdef CONFIG_SERIAL_UBI32_SERDES
37661 + &ip7160bringup_ubicom32_suart_device,
37663 + &ip7160bringup_ubicom32input_device,
37667 + * ip7160bringup_init
37668 + * Called to add the devices which we have on this board
37670 +static int __init ip7160bringup_init(void)
37676 + printk(KERN_INFO "%s: registering device resources\n", __FUNCTION__);
37677 + platform_add_devices(ip7160bringup_devices, ARRAY_SIZE(ip7160bringup_devices));
37682 +arch_initcall(ip7160bringup_init);
37683 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-ip7k/board-ip7160dpf.c linux-2.6.30.10-ubi/arch/ubicom32/mach-ip7k/board-ip7160dpf.c
37684 --- linux-2.6.30.10/arch/ubicom32/mach-ip7k/board-ip7160dpf.c 1970-01-01 02:00:00.000000000 +0200
37685 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-ip7k/board-ip7160dpf.c 2009-12-11 11:45:11.000000000 +0200
37688 + * arch/ubicom32/mach-ip7k/board-ip7160dpf.c
37689 + * Platform initialization for ip7160dpf board.
37691 + * (C) Copyright 2009, Ubicom, Inc.
37693 + * This file is part of the Ubicom32 Linux Kernel Port.
37695 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
37696 + * it and/or modify it under the terms of the GNU General Public License
37697 + * as published by the Free Software Foundation, either version 2 of the
37698 + * License, or (at your option) any later version.
37700 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
37701 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
37702 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
37703 + * the GNU General Public License for more details.
37705 + * You should have received a copy of the GNU General Public License
37706 + * along with the Ubicom32 Linux Kernel Port. If not,
37707 + * see <http://www.gnu.org/licenses/>.
37709 + * Ubicom32 implementation derived from (with many thanks):
37714 +#include <linux/device.h>
37715 +#include <linux/platform_device.h>
37716 +#include <linux/delay.h>
37717 +#include <linux/gpio.h>
37719 +#include <linux/i2c.h>
37720 +#include <linux/i2c-gpio.h>
37722 +#include <linux/input.h>
37724 +#include <asm/board.h>
37725 +#include <asm/machdep.h>
37726 +#include <asm/ubicom32hid.h>
37727 +#include <asm/vdc_tio.h>
37728 +#include <asm/audio.h>
37731 + * Backlight on the board PD0, hardware PWM
37733 +static const struct ubicom32hid_button ip7160dpf_ubicom32hid_buttons[] = {
37741 + .code = KEY_LEFT,
37746 + .code = KEY_RIGHT,
37751 + .code = KEY_DOWN,
37756 + .code = KEY_ENTER,
37761 + .code = KEY_MENU,
37771 +static const struct ubicom32hid_ir ip7160dpf_ubicom32hid_ircodes[] = {
37775 + .ir_code = 0xF807916E
37779 + .code = KEY_DOWN,
37780 + .ir_code = 0xF20D916E
37784 + .code = KEY_LEFT,
37785 + .ir_code = 0xF609916E
37789 + .code = KEY_RIGHT,
37790 + .ir_code = 0xF40B916E
37794 + .code = KEY_ENTER,
37795 + .ir_code = 0xF50A916E
37799 + .code = KEY_FN_F1,
37800 + .ir_code = 0xF906916E
37804 + .code = KEY_MENU,
37805 + .ir_code = 0xF708916E
37807 + { /* font size */
37809 + .code = KEY_FN_F2,
37810 + .ir_code = 0xF30C916E
37815 + .ir_code = 0xF10E916E
37819 + .code = KEY_VOLUMEUP,
37820 + .ir_code = 0xF00F916E
37824 + .code = KEY_VOLUMEDOWN,
37825 + .ir_code = 0xED12916E
37829 + .code = KEY_MUTE,
37830 + .ir_code = 0xEA15916E
37834 + .code = KEY_INFO,
37835 + .ir_code = 0xEF10916E
37839 + .code = KEY_FN_F3,
37840 + .ir_code = 0xEE11916E
37844 + .code = KEY_FN_F4,
37845 + .ir_code = 0xEB14916E
37849 + .code = KEY_POWER,
37850 + .ir_code = 0xFD02916E
37854 +static struct ubicom32hid_platform_data ip7160dpf_ubicom32hid_platform_data = {
37855 + .gpio_reset = GPIO_RI_5,
37856 + .gpio_reset_polarity = 0,
37857 + .type = UBICOM32HID_BL_TYPE_PWM,
37859 + .default_intensity = 128,
37860 + .buttons = ip7160dpf_ubicom32hid_buttons,
37861 + .nbuttons = ARRAY_SIZE(ip7160dpf_ubicom32hid_buttons),
37862 + .ircodes = ip7160dpf_ubicom32hid_ircodes,
37863 + .nircodes = ARRAY_SIZE(ip7160dpf_ubicom32hid_ircodes),
37867 + * Devices on the I2C bus
37868 + * This board has a "bus 2" which is isolated from the main bus by U47
37869 + * and pin RI0. It should be safe to always enable bus 2 by setting
37870 + * RI0 to low, however, it should be noted that on all existing configurations
37871 + * of this board, U49 and U51 are not populated.
37873 +static struct i2c_board_info __initdata ip7160dpf_i2c_board_info[] = {
37875 + * U37, CS4350 DAC, address 0x4B, bus 2
37876 + * THIS ENTRY MUST BE FIRST
37879 + .type = "cs4350",
37884 + * U24, ubicom32hid
37887 + .type = "ubicom32hid",
37889 + .platform_data = &ip7160dpf_ubicom32hid_platform_data,
37893 + * U49, ISL29001 Ambient Light Sensor, address 0x44, bus 2 (may not be stuffed)
37897 + * U51, S35390A RTC, address 0x30, bus 2 (may not be stuffed)
37899 +#ifdef CONFIG_RTC_DRV_S35390A
37901 + .type = "s35390a",
37908 + * I2C bus on the board, SDA PI1, SCL PI2
37910 +static struct i2c_gpio_platform_data ip7160dpf_i2c_data = {
37911 + .sda_pin = GPIO_RI_1,
37912 + .scl_pin = GPIO_RI_2,
37913 + .sda_is_open_drain = 0,
37914 + .scl_is_open_drain = 0,
37915 + .scl_is_output_only = 1,
37919 +static struct platform_device ip7160dpf_i2c_device = {
37920 + .name = "i2c-gpio",
37923 + .platform_data = &ip7160dpf_i2c_data,
37928 + * List of all devices in our system
37930 +static struct platform_device *ip7160dpf_devices[] __initdata = {
37931 + &ip7160dpf_i2c_device,
37935 + * ip7160dpf_power_off
37936 + * Called to turn the power off for this board
37938 +static void ip7160dpf_power_off(void)
37940 + gpio_set_value(GPIO_RF_14, 0);
37945 + * Called to add the devices which we have on this board
37947 +static int __init ip7160dpf_init(void)
37950 + struct platform_device *audio_dev;
37955 + * Hold the POWER_HOLD line
37957 + ret = gpio_request(GPIO_RF_14, "POWER_HOLD");
37959 + printk(KERN_ERR "%s: could not request POWER_HOLD GPIO\n", __FUNCTION__);
37961 + gpio_direction_output(GPIO_RF_14, 1);
37962 + mach_power_off = ip7160dpf_power_off;
37965 + * USB SEL_HOST_USB line
37967 + ret = gpio_request(GPIO_RI_13, "SEL_HOST_USB");
37969 + printk(KERN_ERR "%s: could not request SEL_HOST_USB GPIO\n", __FUNCTION__);
37971 + gpio_direction_output(GPIO_RI_13, 0);
37974 + * USB/DAC nRESET line
37976 + ret = gpio_request(GPIO_RI_3, "USB_DAC_nRESET");
37978 + printk(KERN_ERR "%s: could not request USB_DAC_nRESET GPIO\n", __FUNCTION__);
37980 + gpio_direction_output(GPIO_RI_3, 0);
37982 + gpio_direction_output(GPIO_RI_3, 1);
37985 + * I2C BUS2 Disable line
37987 + ret = gpio_request(GPIO_RI_0, "DISABLE_BUS2");
37989 + printk(KERN_ERR "%s: could not request DISABLE_BUS2 GPIO\n", __FUNCTION__);
37991 + gpio_direction_output(GPIO_RI_0, 0);
37995 + printk(KERN_INFO "%s: registering device resources\n", __FUNCTION__);
37996 + platform_add_devices(ip7160dpf_devices, ARRAY_SIZE(ip7160dpf_devices));
37999 + * Allocate the audio driver if we can
38001 + audio_dev = audio_device_alloc("snd-ubi32-cs4350", "audio-i2sout", 0);
38003 + ip7160dpf_i2c_board_info[0].platform_data = audio_dev;
38006 + printk(KERN_INFO "%s: registering i2c resources\n", __FUNCTION__);
38007 + i2c_register_board_info(0, ip7160dpf_i2c_board_info, ARRAY_SIZE(ip7160dpf_i2c_board_info));
38012 +arch_initcall(ip7160dpf_init);
38013 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-ip7k/board-ip7160rgw.c linux-2.6.30.10-ubi/arch/ubicom32/mach-ip7k/board-ip7160rgw.c
38014 --- linux-2.6.30.10/arch/ubicom32/mach-ip7k/board-ip7160rgw.c 1970-01-01 02:00:00.000000000 +0200
38015 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-ip7k/board-ip7160rgw.c 2009-12-11 11:45:11.000000000 +0200
38018 + * arch/ubicom32/mach-ip7k/board-ip7160rgw.c
38019 + * Platform initialization for ip7160rgw board.
38021 + * (C) Copyright 2009, Ubicom, Inc.
38023 + * This file is part of the Ubicom32 Linux Kernel Port.
38025 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
38026 + * it and/or modify it under the terms of the GNU General Public License
38027 + * as published by the Free Software Foundation, either version 2 of the
38028 + * License, or (at your option) any later version.
38030 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
38031 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
38032 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
38033 + * the GNU General Public License for more details.
38035 + * You should have received a copy of the GNU General Public License
38036 + * along with the Ubicom32 Linux Kernel Port. If not,
38037 + * see <http://www.gnu.org/licenses/>.
38039 + * Ubicom32 implementation derived from (with many thanks):
38044 +#include <linux/device.h>
38045 +#include <linux/platform_device.h>
38046 +#include <linux/gpio.h>
38047 +#include <linux/leds.h>
38048 +#include <linux/delay.h>
38049 +#include <linux/input.h>
38050 +#include <linux/spi/spi.h>
38052 +#include <asm/board.h>
38053 +#include <asm/machdep.h>
38054 +#include <asm/ubicom32input.h>
38056 +#ifdef CONFIG_SERIAL_UBI32_SERDES
38057 +#include <asm/ubicom32suart.h>
38060 +#include <asm/ubicom32-spi-gpio.h>
38061 +#include <asm/switch-dev.h>
38063 +#ifdef CONFIG_IP7160RGWLCD
38064 +#include <linux/i2c.h>
38065 +#include <linux/i2c-gpio.h>
38067 + * LCD Adapter board 8007-092x support
38069 + * Touch controller
38071 + * Connected via I2C bus, interrupt on PA6
38073 +#include <linux/i2c/tsc2007.h>
38076 + * ip7160rgwlcd_tsc2007_exit_platform_hw
38078 +static void ip7160rgwlcd_tsc2007_exit_platform_hw(void)
38080 + UBICOM32_IO_PORT(RA)->ctl0 &= ~(0x03 << 17);
38081 + gpio_free(GPIO_RA_5);
38085 + * ip7160rgwlcd_tsc2007_init_platform_hw
38087 +static int ip7160rgwlcd_tsc2007_init_platform_hw(void)
38089 + int res = gpio_request(GPIO_RA_5, "TSC2007_IRQ");
38094 + UBICOM32_IO_PORT(RA)->ctl0 &= ~(0x03 << 17);
38095 + UBICOM32_IO_PORT(RA)->ctl0 |= (0x02 << 17);
38100 + * ip7160rgwlcd_tsc2007_get_pendown_state
38102 +static int ip7160rgwlcd_tsc2007_get_pendown_state(void)
38104 + return !gpio_get_value(GPIO_RA_5);
38107 +static struct tsc2007_platform_data ip7160rgwlcd_tsc2007_data = {
38109 + .x_plate_ohms = 350,
38110 + .get_pendown_state = ip7160rgwlcd_tsc2007_get_pendown_state,
38111 + .init_platform_hw = ip7160rgwlcd_tsc2007_init_platform_hw,
38112 + .exit_platform_hw = ip7160rgwlcd_tsc2007_exit_platform_hw,
38115 +/******************************************************************************
38116 + * I2C bus on the board, SDA PI14, SCL PI13
38118 +static struct i2c_gpio_platform_data ip7160rgwlcd_i2c_data = {
38119 + .sda_pin = GPIO_RI_14,
38120 + .scl_pin = GPIO_RI_13,
38121 + .sda_is_open_drain = 0,
38122 + .scl_is_open_drain = 0,
38126 +static struct platform_device ip7160rgwlcd_i2c_device = {
38127 + .name = "i2c-gpio",
38130 + .platform_data = &ip7160rgwlcd_i2c_data,
38134 +static struct i2c_board_info __initdata ip7160rgwlcd_i2c_board_info[] = {
38136 + .type = "tsc2007",
38138 + .irq = 45, // RA5
38139 + .platform_data = &ip7160rgwlcd_tsc2007_data,
38146 + * SPI bus over GPIO for Gigabit Ethernet Switch
38153 +static struct ubicom32_spi_gpio_platform_data ip7160rgw_spi_gpio_data = {
38154 + .pin_mosi = GPIO_RE_0,
38155 + .pin_miso = GPIO_RE_1,
38156 + .pin_clk = GPIO_RE_3,
38157 + .bus_num = 0, // We'll call this SPI bus 0
38158 + .num_chipselect = 1, // only one device on this SPI bus
38159 + .clk_default = 1,
38162 +static struct platform_device ip7160rgw_spi_gpio_device = {
38163 + .name = "ubicom32-spi-gpio",
38166 + .platform_data = &ip7160rgw_spi_gpio_data,
38170 +static struct ubicom32_spi_gpio_controller_data ip7160rgw_bcm539x_controller_data = {
38171 + .pin_cs = GPIO_RE_2,
38174 +static struct switch_core_platform_data ip7160rgw_bcm539x_platform_data = {
38175 + .flags = SWITCH_DEV_FLAG_HW_RESET,
38176 + .pin_reset = GPIO_RE_4,
38177 + .name = "bcm539x",
38180 +static struct spi_board_info ip7160rgw_spi_board_info[] = {
38182 + .modalias = "bcm539x-spi",
38184 + .chip_select = 0,
38185 + .max_speed_hz = 2000000,
38186 + .platform_data = &ip7160rgw_bcm539x_platform_data,
38187 + .controller_data = &ip7160rgw_bcm539x_controller_data,
38188 + .mode = SPI_MODE_3,
38195 + * WLAN1 PD0 (PWM capable)
38201 + * TODO: check triggers, are they generic?
38203 +static struct gpio_led ip7160rgw_gpio_leds[] = {
38205 + .name = "d53:green:WLAN1",
38206 + .default_trigger = "WLAN1",
38207 + .gpio = GPIO_RD_0,
38211 + .name = "d54:green:WLAN2",
38212 + .default_trigger = "WLAN2",
38213 + .gpio = GPIO_RD_1,
38217 + .name = "d55:green:USB",
38218 + .default_trigger = "USB",
38219 + .gpio = GPIO_RD_2,
38223 + .name = "d56:green:Status",
38224 + .default_trigger = "Status",
38225 + .gpio = GPIO_RD_3,
38229 + .name = "d57:green:WPS",
38230 + .default_trigger = "WPS",
38231 + .gpio = GPIO_RD_4,
38236 +static struct gpio_led_platform_data ip7160rgw_gpio_led_platform_data = {
38238 + .leds = ip7160rgw_gpio_leds,
38241 +static struct platform_device ip7160rgw_gpio_leds_device = {
38242 + .name = "leds-gpio",
38245 + .platform_data = &ip7160rgw_gpio_led_platform_data,
38250 + * Use ubicom32input driver to monitor the various pushbuttons on this board.
38253 + * FACT_DEFAULT PD6
38255 + * TODO: pick some ubicom understood EV_xxx define for WPS and Fact Default
38257 +static struct ubicom32input_button ip7160rgw_ubicom32input_buttons[] = {
38260 + .code = KEY_FN_F1,
38261 + .gpio = GPIO_RD_5,
38267 + .code = KEY_FN_F2,
38268 + .gpio = GPIO_RD_6,
38269 + .desc = "Factory Default",
38274 +static struct ubicom32input_platform_data ip7160rgw_ubicom32input_data = {
38275 + .buttons = ip7160rgw_ubicom32input_buttons,
38276 + .nbuttons = ARRAY_SIZE(ip7160rgw_ubicom32input_buttons),
38279 +static struct platform_device ip7160rgw_ubicom32input_device = {
38280 + .name = "ubicom32input",
38283 + .platform_data = &ip7160rgw_ubicom32input_data,
38287 +#ifdef CONFIG_SERIAL_UBI32_SERDES
38288 +static struct resource ip7160rgw_ubicom32_suart_resources[] = {
38292 + .flags = IORESOURCE_MEM,
38295 + .start = PORT_OTHER_INT(RE),
38296 + .end = PORT_OTHER_INT(RE),
38297 + .flags = IORESOURCE_IRQ,
38300 + .start = 250000000,
38301 + .end = 250000000,
38302 + .flags = UBICOM32_SUART_IORESOURCE_CLOCK,
38306 +static struct platform_device ip7160rgw_ubicom32_suart_device = {
38307 + .name = "ubicom32suart",
38309 + .num_resources = ARRAY_SIZE(ip7160rgw_ubicom32_suart_resources),
38310 + .resource = ip7160rgw_ubicom32_suart_resources,
38315 + * List of all devices in our system
38317 +static struct platform_device *ip7160rgw_devices[] __initdata = {
38318 +#ifdef CONFIG_SERIAL_UBI32_SERDES
38319 + &ip7160rgw_ubicom32_suart_device,
38321 + &ip7160rgw_ubicom32input_device,
38322 + &ip7160rgw_gpio_leds_device,
38323 + &ip7160rgw_spi_gpio_device,
38324 +#ifdef CONFIG_IP7160RGWLCD
38325 + &ip7160rgwlcd_i2c_device,
38331 + * Called to add the devices which we have on this board
38333 +static int __init ip7160rgw_init(void)
38338 + * Rev 1.2 boards have spi in a different place than 1.1/1.0
38340 + if (strcmp(board_get_revision(), "1.2") == 0) {
38341 + ip7160rgw_spi_gpio_data.pin_mosi = GPIO_RD_7;
38347 + * Reserve switch SPI CS on behalf on switch driver
38349 + if (gpio_request(ip7160rgw_bcm539x_controller_data.pin_cs, "switch-bcm539x-cs")) {
38350 + printk(KERN_WARNING "Could not request cs of switch SPI I/F\n");
38353 + gpio_direction_output(ip7160rgw_bcm539x_controller_data.pin_cs, 1);
38355 + printk(KERN_INFO "%s: registering device resources\n", __FUNCTION__);
38356 + platform_add_devices(ip7160rgw_devices, ARRAY_SIZE(ip7160rgw_devices));
38358 + printk(KERN_INFO "%s: registering SPI resources\n", __FUNCTION__);
38359 + spi_register_board_info(ip7160rgw_spi_board_info, ARRAY_SIZE(ip7160rgw_spi_board_info));
38361 +#ifdef CONFIG_IP7160RGWLCD
38362 + printk(KERN_INFO "%s: registering i2c resources\n", __FUNCTION__);
38363 + i2c_register_board_info(0, ip7160rgwlcd_i2c_board_info, ARRAY_SIZE(ip7160rgwlcd_i2c_board_info));
38364 + printk(KERN_INFO "IP7160 RGW + LCD\n");
38366 + printk(KERN_INFO "IP7160 RGW\n");
38371 +arch_initcall(ip7160rgw_init);
38372 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-ip7k/board-ip7500av.c linux-2.6.30.10-ubi/arch/ubicom32/mach-ip7k/board-ip7500av.c
38373 --- linux-2.6.30.10/arch/ubicom32/mach-ip7k/board-ip7500av.c 1970-01-01 02:00:00.000000000 +0200
38374 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-ip7k/board-ip7500av.c 2009-12-11 11:45:11.000000000 +0200
38377 + * arch/ubicom32/mach-ip7k/board-ip7500av.c
38378 + * Support for IP7500 Audio Video Board + CPU module board.
38380 + * This file supports the IP7500 Audio Video Board:
38381 + * 8007-0810 Rev 1.0
38382 + * with one of the following CPU module boards:
38383 + * 8007-0510 Rev 1.0
38384 + * 8007-0510A Rev 1.0 (with ethernet)
38386 + * DIP Switch SW2 configuration: (*) default
38387 + * POS 1: on(*) = PCI enabled, off = PCI disabled
38388 + * POS 2: on(*) = TTYX => PA6, off = TTYX => PF12
38389 + * POS 3: on(*) = TTYY => PA7, off = TTYY => PF15
38392 + * (C) Copyright 2009, Ubicom, Inc.
38394 + * This file is part of the Ubicom32 Linux Kernel Port.
38396 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
38397 + * it and/or modify it under the terms of the GNU General Public License
38398 + * as published by the Free Software Foundation, either version 2 of the
38399 + * License, or (at your option) any later version.
38401 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
38402 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
38403 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
38404 + * the GNU General Public License for more details.
38406 + * You should have received a copy of the GNU General Public License
38407 + * along with the Ubicom32 Linux Kernel Port. If not,
38408 + * see <http://www.gnu.org/licenses/>.
38411 +#include <linux/platform_device.h>
38412 +#include <linux/device.h>
38413 +#include <linux/gpio.h>
38414 +#include <linux/i2c.h>
38415 +#include <linux/i2c-gpio.h>
38416 +#include <linux/delay.h>
38417 +#include <asm/board.h>
38418 +#include <asm/machdep.h>
38419 +#include <asm/ring_tio.h>
38420 +#include <asm/vdc_tio.h>
38421 +#include <asm/audio.h>
38422 +#include <asm/ubi32-pcm.h>
38423 +#include <asm/ubi32-cs4384.h>
38425 +/******************************************************************************
38426 + * Devices on the I2C bus
38428 + * BEWARE of changing the order of things in this array as we depend on
38429 + * certain things to be in certain places.
38431 +static struct i2c_board_info __initdata ip7500av_i2c_board_info[] = {
38433 + * U6, CS4384 DAC, address 0x19
38436 + .type = "cs4384",
38442 + * I2C bus on the board, SDA PD1, SCL PD2
38444 +static struct i2c_gpio_platform_data ip7500av_i2c_data = {
38445 + .sda_pin = GPIO_RD_6,
38446 + .scl_pin = GPIO_RD_3,
38447 + .sda_is_open_drain = 0,
38448 + .scl_is_open_drain = 0,
38452 +static struct platform_device ip7500av_i2c_device = {
38453 + .name = "i2c-gpio",
38456 + .platform_data = &ip7500av_i2c_data,
38461 + * List of possible mclks we can generate. This depends on the CPU frequency.
38463 +static struct ubi32_cs4384_mclk_entry ip7500av_cs4384_mclk_entries[] = {
38465 + .rate = 12288000,
38469 + .rate = 11289600,
38475 + * List of all devices in our system
38477 +static struct platform_device *ip7500av_devices[] __initdata = {
38478 + &ip7500av_i2c_device,
38482 + * ip7500av_vdac_write
38484 +static int __init ip7500av_vdac_write(int reg, int val)
38486 + struct i2c_adapter *adap;
38487 + struct i2c_msg msg[1];
38488 + unsigned char data[2];
38491 + adap = i2c_get_adapter(0);
38493 + printk(KERN_WARNING "%s: failed to get i2c adapter\n", __FUNCTION__);
38496 + msg->addr = 0x2B;
38502 + err = i2c_transfer(adap, msg, 1);
38503 + i2c_put_adapter(adap);
38511 + * ip7500av_vdac_init
38512 + * Initializes the video DAC via I2C
38514 + * Equivalent mode line: 720x480p = 27 Mhz, 720 736 800 858 480 484 492 525
38516 +static int __init ip7500av_vdac_init(void)
38520 + printk(KERN_INFO "Initializing ADV7393 DAC\n");
38525 + if (gpio_request(GPIO_RF_6, "VDAC Reset")) {
38526 + printk(KERN_WARNING "%s: failed to allocate VDAC Reset\n", __FUNCTION__);
38529 + gpio_direction_output(GPIO_RF_6, 0);
38531 + gpio_set_value(GPIO_RF_6, 1);
38534 + * See table 100 of ADV7393 data sheet: 16-bit 525p YCrCb In, YPbPr Out
38536 + err = ip7500av_vdac_write(0x17, 0x02);
38538 + printk(KERN_WARNING "%s: failed to write VDAC\n", __FUNCTION__);
38541 + err = ip7500av_vdac_write(0x00, 0x1c);
38543 + printk(KERN_WARNING "%s: failed to write VDAC\n", __FUNCTION__);
38546 + err = ip7500av_vdac_write(0x01, 0x10);
38548 + printk(KERN_WARNING "%s: failed to write VDAC\n", __FUNCTION__);
38551 + err = ip7500av_vdac_write(0x31, 0x01);
38553 + printk(KERN_WARNING "%s: failed to write VDAC\n", __FUNCTION__);
38556 +#ifdef IP7500AV_VDAC_SWAP_PBPR
38557 + err = ip7500av_vdac_write(0x35, 0x08);
38559 + printk(KERN_WARNING "%s: failed to write VDAC\n", __FUNCTION__);
38563 +#ifdef IP7500AV_VDAC_FULL_RANGE
38564 + err = ip7500av_vdac_write(0x30, 0x02);
38566 + printk(KERN_WARNING "%s: failed to write VDAC\n", __FUNCTION__);
38572 +late_initcall(ip7500av_vdac_init);
38576 + * Called to add the devices which we have on this board
38578 +static int __init ip7500av_init(void)
38580 + struct platform_device *audio_dev;
38581 + struct platform_device *audio_dev2;
38582 + struct ubi32_cs4384_platform_data *cs4384_pd;
38590 + printk(KERN_INFO "%s: registering device resources\n", __FUNCTION__);
38591 + platform_add_devices(ip7500av_devices, ARRAY_SIZE(ip7500av_devices));
38596 + audio_dev = audio_device_alloc("snd-ubi32-cs4384", "audio", "audio-i2sout",
38597 + sizeof(struct ubi32_cs4384_platform_data));
38600 + * Attempt to figure out a good divisor. This will only work
38601 + * assuming the core frequency is compatible.
38604 + unsigned int freq = processor_frequency();
38605 + for (i = 0; i < ARRAY_SIZE(ip7500av_cs4384_mclk_entries); i++) {
38606 + unsigned int div;
38607 + unsigned int rate = ip7500av_cs4384_mclk_entries[i].rate / 1000;
38608 + div = ((freq / rate) + 500) / 1000;
38609 + ip7500av_cs4384_mclk_entries[i].div = div;
38610 + printk("CS4384 mclk %d rate %u000Hz div %u act %u\n", i, rate, div, freq / div);
38613 + cs4384_pd = audio_device_priv(audio_dev);
38614 + cs4384_pd->mclk_src = UBI32_CS4384_MCLK_PWM_0;
38615 + cs4384_pd->n_mclk = ARRAY_SIZE(ip7500av_cs4384_mclk_entries);
38616 + cs4384_pd->mclk_entries = ip7500av_cs4384_mclk_entries;
38617 + ip7500av_i2c_board_info[0].platform_data = audio_dev;
38622 + if (gpio_request(GPIO_RF_4, "DAC Reset") == 0) {
38623 + gpio_direction_output(GPIO_RF_4, 0);
38625 + gpio_direction_output(GPIO_RF_4, 1);
38627 + printk("Unable to request DAC reset GPIO\n");
38634 + audio_dev2 = audio_device_alloc("snd-ubi32-generic", "audio", "audio-spdifout", 0);
38635 + if (audio_dev2) {
38636 + platform_device_register(audio_dev2);
38640 + * Register all of the devices which sit on the I2C bus
38642 + printk(KERN_INFO "%s: registering i2c resources\n", __FUNCTION__);
38643 + i2c_register_board_info(0, ip7500av_i2c_board_info, ARRAY_SIZE(ip7500av_i2c_board_info));
38645 + printk(KERN_INFO "IP7500 Audio/Video Board\n");
38648 +arch_initcall(ip7500av_init);
38649 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-ip7k/board-ip7500iap.c linux-2.6.30.10-ubi/arch/ubicom32/mach-ip7k/board-ip7500iap.c
38650 --- linux-2.6.30.10/arch/ubicom32/mach-ip7k/board-ip7500iap.c 1970-01-01 02:00:00.000000000 +0200
38651 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-ip7k/board-ip7500iap.c 2009-12-11 11:45:11.000000000 +0200
38654 + * arch/ubicom32/mach-ip7k/board-ip7500iap.c
38655 + * Support for IP7500 Internet Audio Player
38657 + * This file supports the IP7500 Internet Audio Player:
38658 + * 8007-1110 Rev 1.0
38660 + * (C) Copyright 2009, Ubicom, Inc.
38662 + * This file is part of the Ubicom32 Linux Kernel Port.
38664 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
38665 + * it and/or modify it under the terms of the GNU General Public License
38666 + * as published by the Free Software Foundation, either version 2 of the
38667 + * License, or (at your option) any later version.
38669 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
38670 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
38671 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
38672 + * the GNU General Public License for more details.
38674 + * You should have received a copy of the GNU General Public License
38675 + * along with the Ubicom32 Linux Kernel Port. If not,
38676 + * see <http://www.gnu.org/licenses/>.
38678 +#include <linux/device.h>
38679 +#include <linux/gpio.h>
38680 +#include <asm/board.h>
38682 +#include <linux/delay.h>
38684 +#include <linux/platform_device.h>
38685 +#include <asm/audio.h>
38686 +#include <linux/i2c.h>
38687 +#include <linux/i2c-gpio.h>
38689 +#include <asm/ubicom32sd.h>
38690 +#include <asm/sd_tio.h>
38692 +#include <asm/ubicom32bl.h>
38694 +#include <asm/machdep.h>
38696 +/******************************************************************************
38697 + * SD/IO Port F (Slot 1) platform data
38699 +static struct resource ip7500iap_portf_sd_resources[] = {
38705 + * The init routine will query the devtree and fill this in
38707 + .flags = IORESOURCE_IRQ,
38715 + * The init routine will query the devtree and fill this in
38717 + .flags = IORESOURCE_IRQ,
38721 + * Memory Mapped Registers
38725 + * The init routine will query the devtree and fill this in
38727 + .flags = IORESOURCE_MEM,
38731 +static struct ubicom32sd_card ip7500iap_portf_sd_cards[] = {
38733 + .pin_wp = GPIO_RF_7,
38734 + .wp_polarity = 1,
38735 + .pin_pwr = GPIO_RF_8,
38736 + .pin_cd = GPIO_RF_6,
38740 +static struct ubicom32sd_platform_data ip7500iap_portf_sd_platform_data = {
38742 + .cards = ip7500iap_portf_sd_cards,
38745 +static struct platform_device ip7500iap_portf_sd_device = {
38746 + .name = "ubicom32sd",
38748 + .resource = ip7500iap_portf_sd_resources,
38749 + .num_resources = ARRAY_SIZE(ip7500iap_portf_sd_resources),
38751 + .platform_data = &ip7500iap_portf_sd_platform_data,
38757 + * ip7500iap_portf_sd_init
38759 +static void ip7500iap_portf_sd_init(void)
38762 + * Check the device tree for the sd_tio
38764 + struct sd_tio_node *sd_node = (struct sd_tio_node *)devtree_find_node("portf_sd");
38766 + printk(KERN_INFO "PortF SDTIO not found\n");
38771 + * Fill in the resources and platform data from devtree information
38773 + ip7500iap_portf_sd_resources[0].start = sd_node->dn.sendirq;
38774 + ip7500iap_portf_sd_resources[1].start = sd_node->dn.recvirq;
38775 + ip7500iap_portf_sd_resources[2].start = (u32_t)&(sd_node->regs);
38776 + ip7500iap_portf_sd_resources[2].end = (u32_t)&(sd_node->regs) + sizeof(sd_node->regs);
38778 + platform_device_register(&ip7500iap_portf_sd_device);
38781 +/******************************************************************************
38782 + * SD/IO Port B (Slot 2) platform data
38784 +static struct resource ip7500iap_portb_sd_resources[] = {
38790 + * The init routine will query the devtree and fill this in
38792 + .flags = IORESOURCE_IRQ,
38800 + * The init routine will query the devtree and fill this in
38802 + .flags = IORESOURCE_IRQ,
38806 + * Memory Mapped Registers
38810 + * The init routine will query the devtree and fill this in
38812 + .flags = IORESOURCE_MEM,
38816 +static struct ubicom32sd_card ip7500iap_portb_sd_cards[] = {
38818 + .pin_wp = GPIO_RB_13,
38819 + .wp_polarity = 1,
38820 + .pin_pwr = GPIO_RB_11,
38821 + .pin_cd = GPIO_RB_12,
38825 +static struct ubicom32sd_platform_data ip7500iap_portb_sd_platform_data = {
38827 + .cards = ip7500iap_portb_sd_cards,
38830 +static struct platform_device ip7500iap_portb_sd_device = {
38831 + .name = "ubicom32sd",
38833 + .resource = ip7500iap_portb_sd_resources,
38834 + .num_resources = ARRAY_SIZE(ip7500iap_portb_sd_resources),
38836 + .platform_data = &ip7500iap_portb_sd_platform_data,
38842 + * ip7500iap_portb_sd_init
38844 +static void ip7500iap_portb_sd_init(void)
38847 + * Check the device tree for the sd_tio
38849 + struct sd_tio_node *sd_node = (struct sd_tio_node *)devtree_find_node("portb_sd");
38851 + printk(KERN_INFO "PortB SDTIO not found\n");
38856 + * Fill in the resources and platform data from devtree information
38858 + ip7500iap_portb_sd_resources[0].start = sd_node->dn.sendirq;
38859 + ip7500iap_portb_sd_resources[1].start = sd_node->dn.recvirq;
38860 + ip7500iap_portb_sd_resources[2].start = (u32_t)&(sd_node->regs);
38861 + ip7500iap_portb_sd_resources[2].end = (u32_t)&(sd_node->regs) + sizeof(sd_node->regs);
38863 + platform_device_register(&ip7500iap_portb_sd_device);
38866 +/******************************************************************************
38867 + * Touch controller
38869 + * Connected via I2C bus, interrupt on PA6
38871 +#include <linux/i2c/tsc2007.h>
38874 + * ip7500iap_tsc2007_exit_platform_hw
38876 +static void ip7500iap_tsc2007_exit_platform_hw(void)
38878 + UBICOM32_IO_PORT(RA)->ctl0 &= ~(0x03 << 19);
38879 + gpio_free(GPIO_RA_6);
38883 + * ip7500iap_tsc2007_init_platform_hw
38885 +static int ip7500iap_tsc2007_init_platform_hw(void)
38887 + int res = gpio_request(GPIO_RA_6, "TSC2007_IRQ");
38892 + UBICOM32_IO_PORT(RA)->ctl0 &= ~(0x03 << 19);
38893 + UBICOM32_IO_PORT(RA)->ctl0 |= (0x02 << 19);
38898 + * ip7500iap_tsc2007_get_pendown_state
38900 +static int ip7500iap_tsc2007_get_pendown_state(void)
38902 + return !gpio_get_value(GPIO_RA_6);
38905 +static struct tsc2007_platform_data ip7500iap_tsc2007_data = {
38907 + .x_plate_ohms = 350,
38908 + .get_pendown_state = ip7500iap_tsc2007_get_pendown_state,
38909 + .init_platform_hw = ip7500iap_tsc2007_init_platform_hw,
38910 + .exit_platform_hw = ip7500iap_tsc2007_exit_platform_hw,
38913 +/******************************************************************************
38916 + * DO NOT CHANGE THE ORDER HERE unless you know how this works. There
38917 + * are hardcoded indicies which refer to the order of drivers listed here.
38919 +static struct i2c_board_info __initdata ip7500iap_i2c_board_info[] = {
38921 + * U6, CS4350 DAC, address 0x4B
38924 + .type = "cs4350",
38929 + * U20, S35390A RTC, address 0x30
38932 + .type = "s35390a",
38937 + * U9, TSC2007 Touch screen controller, address 0x49, irq RA6
38940 + .type = "tsc2007",
38943 + .platform_data = &ip7500iap_tsc2007_data,
38948 + * I2C bus on the board, SDA PE4, SCL PE5
38950 +static struct i2c_gpio_platform_data ip7500iap_i2c_data = {
38951 + .sda_pin = GPIO_RF_14,
38952 + .scl_pin = GPIO_RF_13,
38953 + .sda_is_open_drain = 0,
38954 + .scl_is_open_drain = 0,
38958 +static struct platform_device ip7500iap_i2c_device = {
38959 + .name = "i2c-gpio",
38962 + .platform_data = &ip7500iap_i2c_data,
38966 +/******************************************************************************
38967 + * Backlight on the board PD0, hardware PWM
38969 +static struct ubicom32bl_platform_data ip7500iap_backlight_data = {
38970 + .type = UBICOM32BL_TYPE_PWM,
38971 + .pwm_channel = 2,
38972 + .pwm_prescale = 15,
38973 + .pwm_period = 60,
38974 + .default_intensity = 0x80,
38977 +static struct platform_device ip7500iap_backlight_device = {
38978 + .name = "ubicom32bl",
38981 + .platform_data = &ip7500iap_backlight_data,
38985 +/******************************************************************************
38986 + * Devices on this board
38988 +static struct platform_device *ip7500iap_devices[] __initdata = {
38989 + &ip7500iap_i2c_device,
38990 + &ip7500iap_backlight_device,
38994 + * ip7500iap_power_off
38995 + * Called to turn the power off for this board
38997 +static void ip7500iap_power_off(void)
38999 + gpio_set_value(GPIO_RF_11, 0);
39004 + * Called to add the devices which we have on this board
39006 +static int __init ip7500iap_init(void)
39008 + struct platform_device *audio_dev;
39009 + struct platform_device *audio_dev2;
39017 + * Hold the POWER_HOLD line
39019 + ret = gpio_request(GPIO_RF_11, "POWER_HOLD");
39021 + printk(KERN_ERR "%s: could not request POWER_HOLD GPIO\n", __FUNCTION__);
39023 + gpio_direction_output(GPIO_RF_11, 1);
39024 + mach_power_off = ip7500iap_power_off;
39027 + * DAC nRESET line
39029 + ret = gpio_request(GPIO_RE_7, "DAC_nRESET");
39031 + printk(KERN_ERR "%s: could not request DAC_nRESET GPIO\n", __FUNCTION__);
39033 + gpio_direction_output(GPIO_RE_7, 0);
39035 + gpio_set_value(GPIO_RE_7, 1);
39038 + * Bring up any SDIO slots
39040 + ip7500iap_portb_sd_init();
39041 + ip7500iap_portf_sd_init();
39044 + * Bring up audio devices
39046 + platform_add_devices(ip7500iap_devices, ARRAY_SIZE(ip7500iap_devices));
39048 + audio_dev = audio_device_alloc("snd-ubi32-cs4350", "audio", "audio-i2sout", 0);
39050 + ip7500iap_i2c_board_info[0].platform_data = audio_dev;
39053 + audio_dev2 = audio_device_alloc("snd-ubi32-generic", "audio", "audio-spdifout", 0);
39054 + if (audio_dev2) {
39055 + platform_device_register(audio_dev2);
39058 + printk(KERN_INFO "%s: registering i2c resources\n", __FUNCTION__);
39059 + i2c_register_board_info(0, ip7500iap_i2c_board_info, ARRAY_SIZE(ip7500iap_i2c_board_info));
39061 + printk(KERN_INFO "IP7500 Internet Audio Player\n");
39066 +arch_initcall(ip7500iap_init);
39067 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-ip7k/board-ip7500media.c linux-2.6.30.10-ubi/arch/ubicom32/mach-ip7k/board-ip7500media.c
39068 --- linux-2.6.30.10/arch/ubicom32/mach-ip7k/board-ip7500media.c 1970-01-01 02:00:00.000000000 +0200
39069 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-ip7k/board-ip7500media.c 2009-12-11 11:45:11.000000000 +0200
39072 + * arch/ubicom32/mach-ip7k/board-ip7500media.c
39073 + * Board file for IP7500 media board.
39075 + * Supports the following configuration
39077 + * P/N 8007-0510 rev 1.0 NOPHY
39078 + * P/N 8007-0511 rev 1.1 NOPHY
39079 + * DIP Switch SW2 configuration:
39080 + * POS 1: on = PCI enabled
39081 + * POS 2: off = TTYX => PF12
39082 + * POS 3: off = TTYY => PF15
39085 + * P/N 8007-0610 rev 1.0
39087 + * LCD Adapter Board: (optional)
39088 + * P/N 8007-0920 rev 2.0
39089 + * P/N 8007-0921 rev 2.1
39091 + * (C) Copyright 2009, Ubicom, Inc.
39093 + * This file is part of the Ubicom32 Linux Kernel Port.
39095 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
39096 + * it and/or modify it under the terms of the GNU General Public License
39097 + * as published by the Free Software Foundation, either version 2 of the
39098 + * License, or (at your option) any later version.
39100 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
39101 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
39102 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
39103 + * the GNU General Public License for more details.
39105 + * You should have received a copy of the GNU General Public License
39106 + * along with the Ubicom32 Linux Kernel Port. If not,
39107 + * see <http://www.gnu.org/licenses/>.
39109 + * Ubicom32 implementation derived from (with many thanks):
39114 +#include <linux/device.h>
39115 +#include <linux/platform_device.h>
39116 +#include <linux/gpio.h>
39118 +#include <linux/input.h>
39120 +#include <linux/i2c.h>
39121 +#include <linux/i2c-gpio.h>
39122 +#include <linux/i2c/pca953x.h>
39124 +#include <asm/board.h>
39125 +#include <asm/machdep.h>
39126 +#include <asm/ubicom32input_i2c.h>
39127 +#include <asm/ubicom32bl.h>
39128 +#include <asm/ubicom32lcdpower.h>
39129 +#include <asm/vdc_tio.h>
39131 +#include <asm/ubicom32sd.h>
39132 +#include <asm/sd_tio.h>
39133 +#include <asm/devtree.h>
39134 +#include <asm/audio.h>
39136 +#include <asm/ring_tio.h>
39138 +/******************************************************************************
39139 + * SD/IO Port F (Slot 1) platform data
39141 +static struct resource ip7500media_portf_sd_resources[] = {
39147 + * The init routine will query the devtree and fill this in
39149 + .flags = IORESOURCE_IRQ,
39157 + * The init routine will query the devtree and fill this in
39159 + .flags = IORESOURCE_IRQ,
39163 + * Memory Mapped Registers
39167 + * The init routine will query the devtree and fill this in
39169 + .flags = IORESOURCE_MEM,
39173 +static struct ubicom32sd_card ip7500media_portf_sd_cards[] = {
39175 + .pin_wp = IP7500MEDIA_IO16,
39176 + .wp_polarity = 1,
39177 + .pin_pwr = IP7500MEDIA_IO20,
39178 + .pin_cd = IP7500MEDIA_IO23,
39181 + .pin_wp = IP7500MEDIA_IO17,
39182 + .wp_polarity = 1,
39183 + .pin_pwr = IP7500MEDIA_IO21,
39184 + .pin_cd = IP7500MEDIA_IO24,
39188 +static struct ubicom32sd_platform_data ip7500media_portf_sd_platform_data = {
39190 + .cards = ip7500media_portf_sd_cards,
39193 +static struct platform_device ip7500media_portf_sd_device = {
39194 + .name = "ubicom32sd",
39196 + .resource = ip7500media_portf_sd_resources,
39197 + .num_resources = ARRAY_SIZE(ip7500media_portf_sd_resources),
39199 + .platform_data = &ip7500media_portf_sd_platform_data,
39205 + * ip7500media_portf_sd_init
39207 +static void ip7500media_portf_sd_init(void)
39210 + * Check the device tree for the sd_tio
39212 + struct sd_tio_node *sd_node = (struct sd_tio_node *)devtree_find_node("portf_sd");
39214 + printk(KERN_INFO "PortF SDTIO not found\n");
39219 + * Fill in the resources and platform data from devtree information
39221 + ip7500media_portf_sd_resources[0].start = sd_node->dn.sendirq;
39222 + ip7500media_portf_sd_resources[1].start = sd_node->dn.recvirq;
39223 + ip7500media_portf_sd_resources[2].start = (u32_t)&(sd_node->regs);
39224 + ip7500media_portf_sd_resources[2].end = (u32_t)&(sd_node->regs) + sizeof(sd_node->regs);
39226 + platform_device_register(&ip7500media_portf_sd_device);
39229 +/******************************************************************************
39230 + * SD/IO Port B (Slot 2) platform data
39232 +static struct resource ip7500media_portb_sd_resources[] = {
39238 + * The init routine will query the devtree and fill this in
39240 + .flags = IORESOURCE_IRQ,
39248 + * The init routine will query the devtree and fill this in
39250 + .flags = IORESOURCE_IRQ,
39254 + * Memory Mapped Registers
39258 + * The init routine will query the devtree and fill this in
39260 + .flags = IORESOURCE_MEM,
39264 +static struct ubicom32sd_card ip7500media_portb_sd_cards[] = {
39266 + .pin_wp = IP7500MEDIA_IO19,
39267 + .wp_polarity = 1,
39268 + .pin_pwr = IP7500MEDIA_IO22,
39269 + .pin_cd = IP7500MEDIA_IO18,
39273 +static struct ubicom32sd_platform_data ip7500media_portb_sd_platform_data = {
39275 + .cards = ip7500media_portb_sd_cards,
39278 +static struct platform_device ip7500media_portb_sd_device = {
39279 + .name = "ubicom32sd",
39281 + .resource = ip7500media_portb_sd_resources,
39282 + .num_resources = ARRAY_SIZE(ip7500media_portb_sd_resources),
39284 + .platform_data = &ip7500media_portb_sd_platform_data,
39290 + * ip7500media_portb_sd_init
39292 +static void ip7500media_portb_sd_init(void)
39295 + * Check the device tree for the sd_tio
39297 + struct sd_tio_node *sd_node = (struct sd_tio_node *)devtree_find_node("portb_sd");
39299 + printk(KERN_INFO "PortB SDTIO not found\n");
39304 + * Fill in the resources and platform data from devtree information
39306 + ip7500media_portb_sd_resources[0].start = sd_node->dn.sendirq;
39307 + ip7500media_portb_sd_resources[1].start = sd_node->dn.recvirq;
39308 + ip7500media_portb_sd_resources[2].start = (u32_t)&(sd_node->regs);
39309 + ip7500media_portb_sd_resources[2].end = (u32_t)&(sd_node->regs) + sizeof(sd_node->regs);
39311 + platform_device_register(&ip7500media_portb_sd_device);
39315 + * ip7500media_u17_setup
39316 + * Called by I2C to tell us that u17 is setup.
39318 + * This function is called by I2C to tell us that u17 has been setup. All
39319 + * devices which rely on this chip being initialized (or even present) need to
39320 + * be initialized in this function otherwise they may get initialized too early.
39322 + * Currently the only device depending on u17 is the SDIO
39324 +static int __init ip7500media_u17_setup(struct i2c_client *client, unsigned gpio, unsigned ngpio, void *context)
39327 + * Initialize the Port F/Port B SD slots (only the enabled ports will init)
39329 + ip7500media_portf_sd_init();
39330 + ip7500media_portb_sd_init();
39335 +/******************************************************************************
39336 + * LCD VGH on the board at PE6
39338 +static struct ubicom32lcdpower_platform_data ip7500media_lcdpower_data = {
39339 + .vgh_gpio = GPIO_RE_7,
39340 + .vgh_polarity = true,
39343 +static struct platform_device ip7500media_lcdpower_device = {
39344 + .name = "ubicom32lcdpower",
39347 + .platform_data = &ip7500media_lcdpower_data,
39351 +/******************************************************************************
39352 + * Backlight on the board PD0, hardware PWM
39354 +static struct ubicom32bl_platform_data ip7500media_backlight_data = {
39355 + .type = UBICOM32BL_TYPE_PWM,
39356 + .pwm_channel = 2,
39357 + .pwm_prescale = 15,
39358 + .pwm_period = 60,
39359 + .default_intensity = 0x80,
39362 +static struct platform_device ip7500media_backlight_device = {
39363 + .name = "ubicom32bl",
39366 + .platform_data = &ip7500media_backlight_data,
39370 +/******************************************************************************
39371 + * Ubicom32Input on I2C, U15 MAX7310, address 0x18, 8 bits
39373 +static struct ubicom32input_i2c_button ip7500media_ubicom32input_i2c_u15_buttons[] = {
39376 + .code = KEY_LEFT,
39382 + .code = KEY_RIGHT,
39394 + .code = KEY_DOWN,
39400 + .code = KEY_ENTER,
39406 + .code = KEY_MENU,
39418 +static struct ubicom32input_i2c_platform_data ip7500media_ubicom32input_i2c_u15_platform_data = {
39419 + .buttons = ip7500media_ubicom32input_i2c_u15_buttons,
39420 + .nbuttons = ARRAY_SIZE(ip7500media_ubicom32input_i2c_u15_buttons),
39421 + .name = "Ubicom32 Input I2C U15",
39424 +/******************************************************************************
39425 + * Additional GPIO chips
39427 +static struct pca953x_platform_data ip7500media_gpio_u16_platform_data = {
39428 + .gpio_base = IP7500MEDIA_U16_BASE,
39431 +static struct pca953x_platform_data ip7500media_gpio_u17_platform_data = {
39432 + .gpio_base = IP7500MEDIA_U17_BASE,
39433 + .setup = ip7500media_u17_setup,
39436 +static struct pca953x_platform_data ip7500media_gpio_u18_platform_data = {
39437 + .gpio_base = IP7500MEDIA_U18_BASE,
39441 +/******************************************************************************
39442 + * Touch controller present on LCD Adapter board
39444 + * Connected via I2C bus, interrupt on PD1
39446 +#include <linux/i2c/tsc2007.h>
39449 + * ip7500media_tsc2007_exit_platform_hw
39451 +static void ip7500media_tsc2007_exit_platform_hw(void)
39453 + UBICOM32_IO_PORT(RD)->int_mask &= ~(1 << 11);
39454 + UBICOM32_IO_PORT(RD)->ctl2 &= ~(0x03 << 16);
39455 + gpio_free(GPIO_RD_1);
39459 + * ip7500media_tsc2007_init_platform_hw
39461 +static int ip7500media_tsc2007_init_platform_hw(void)
39463 + int res = gpio_request(GPIO_RD_1, "TSC2007_IRQ");
39467 + UBICOM32_IO_PORT(RD)->function = 0;
39468 + UBICOM32_IO_PORT(RD)->int_mask = (1 << 11);
39469 + UBICOM32_IO_PORT(RD)->ctl2 &= ~(0x03 << 16);
39470 + UBICOM32_IO_PORT(RD)->ctl2 |= (0x02 << 16);
39476 + * ip7500media_tsc2007_clear_penirq
39478 +static void ip7500media_tsc2007_clear_penirq(void)
39480 + UBICOM32_IO_PORT(RD)->int_clr = (1 << 11);
39484 + * ip7500media_tsc2007_get_pendown_state
39486 +static int ip7500media_tsc2007_get_pendown_state(void)
39488 + return !gpio_get_value(GPIO_RD_1);
39491 +static struct tsc2007_platform_data ip7500media_tsc2007_data = {
39493 + .x_plate_ohms = 350,
39494 + .get_pendown_state = ip7500media_tsc2007_get_pendown_state,
39495 + .init_platform_hw = ip7500media_tsc2007_init_platform_hw,
39496 + .exit_platform_hw = ip7500media_tsc2007_exit_platform_hw,
39497 + .clear_penirq = ip7500media_tsc2007_clear_penirq,
39500 +/******************************************************************************
39501 + * Devices on the I2C bus
39503 + * BEWARE of changing the order of things in this array as we depend on
39504 + * certain things to be in certain places.
39506 +static struct i2c_board_info __initdata ip7500media_i2c_board_info[] = {
39508 + * U6, CS4350 DAC, address 0x4B
39511 + .type = "cs4350",
39516 + * U14, S35390A RTC, address 0x30
39519 + .type = "s35390a",
39524 + * U15, MAX7310 IO expander, 8 bits, address 0x18
39525 + * IO0: User I/O (J16-1) (Left) IO4: User I/O (J16-5) (Enter)
39526 + * IO1: User I/O (J16-2) (Right) IO5: User I/O (J16-6) (Menu)
39527 + * IO2: User I/O (J16-3) (Up) IO6: User I/O (J16-7) (Back)
39528 + * IO3: User I/O (J16-4) (Down) IO7: User I/O (J16-8)
39531 + .type = "ubicom32in_max7310",
39533 + .platform_data = &ip7500media_ubicom32input_i2c_u15_platform_data,
39537 + * U16, MAX7310 IO expander, 8 bits, address 0x1C
39538 + * IO8 : User I/O (J16-9) IO12: User I/O (J16-17)
39539 + * IO9 : User I/O (J16-10) IO13: User I/O (J16-18)
39540 + * IO10: User I/O (J16-15) IO14: User I/O (J16-19)
39541 + * IO11: User I/O (J16-16) IO15: User I/O (J16-20)
39544 + .type = "max7310",
39546 + .platform_data = &ip7500media_gpio_u16_platform_data,
39550 + * U17, MAX7310 IO expander, 8 bits, address 0x1A
39551 + * IO16: SDIO1A_WP IO20: SD1A_PWREN
39552 + * IO17: SDIO1B_WP IO21: SD1B_PWREN
39553 + * IO18: SDIO2_CD IO22: SD2_PWREN
39554 + * IO19: SDIO2_WP IO23: SDIO1A_CD
39558 + .type = "max7310",
39560 + .platform_data = &ip7500media_gpio_u17_platform_data,
39564 + * U18, MAX7310 IOB expander, 8 bits, address 0x1E
39565 + * IO24: SDIO1B_CD IO28: User I/O TP6
39566 + * IO25: User I/O TP9 IO29: User I/O TP5
39567 + * IO26: User I/O TP8 IO30: User I/O TP4
39568 + * IO27: User I/O TP7 IO31: User I/O TP3
39571 + .type = "max7310",
39573 + .platform_data = &ip7500media_gpio_u18_platform_data,
39578 + * Additional I2C devices to add when a LCD adapter board is present
39580 +static struct i2c_board_info __initdata ip7500media_lcd_adapter_i2c_board_info[] = {
39582 + I2C_BOARD_INFO("tsc2007", 0x48),
39583 + .irq = PORT_OTHER_INT(RD),
39584 + .platform_data = &ip7500media_tsc2007_data,
39589 + * I2C bus on the board, SDA PE4, SCL PE5
39591 +static struct i2c_gpio_platform_data ip7500media_i2c_data = {
39592 + .sda_pin = GPIO_RE_4,
39593 + .scl_pin = GPIO_RE_5,
39594 + .sda_is_open_drain = 0,
39595 + .scl_is_open_drain = 0,
39599 +static struct platform_device ip7500media_i2c_device = {
39600 + .name = "i2c-gpio",
39603 + .platform_data = &ip7500media_i2c_data,
39608 + * Virtual Frame Buffer device for use with LCD Adapter
39610 +static struct platform_device ip7500media_vfb_device = {
39611 + .name = "ubicom32vfb",
39617 + * 0: no override (auto-detect)
39618 + * 1: force vdc usage
39619 + * 2: force lcd adapter usage
39621 +static int __initdata vdc_override = 0;
39624 + * ip7500media_set_forcevdc
39625 + * Called when forcevdc is present on the kernel boot line
39627 +static int __init ip7500media_set_forcevdc(char *str)
39629 + if (str[0] == '1') {
39630 + vdc_override = 1;
39632 + vdc_override = 2;
39638 + * ip7500media_video_init
39639 + * Called late to determine what kind of video we have on this board
39641 +static int __init ip7500media_video_init(void)
39643 + struct i2c_adapter *adap;
39644 + struct i2c_msg msg[1];
39645 + unsigned char *data;
39646 + unsigned char checksum;
39650 + if (vdc_override == 1) {
39651 + printk(KERN_INFO "Force VDCTIO mode\n");
39654 + if (vdc_override == 2) {
39655 + printk(KERN_INFO "Force LCD Adapter Board mode\n");
39660 + * Check to see if there is an EEPROM out there. If we see an
39661 + * EEPROM then we will assume a LCD Adapter Board (8007-092x)
39664 + data = kmalloc(256, GFP_KERNEL);
39666 + printk(KERN_WARNING "%s: Failed to allocate memory\n", __FUNCTION__);
39670 + adap = i2c_get_adapter(0);
39672 + printk(KERN_WARNING "%s: Failed to get i2c adapter\n", __FUNCTION__);
39677 + msg->addr = 0x50;
39681 + err = i2c_transfer(adap, msg, 1);
39686 + msg->addr = 0x50;
39687 + msg->flags = I2C_M_RD;
39690 + err = i2c_transfer(adap, msg, 1);
39695 + i2c_put_adapter(adap);
39698 + * Verify the checksum
39701 + for (i = 0; i < 255; i++) {
39702 + checksum ^= data[i];
39704 + if (checksum != data[255]) {
39705 + printk(KERN_WARNING "%s: Checksum mismatch\n", __FUNCTION__);
39713 + platform_device_register(&ip7500media_vfb_device);
39716 + * Add the i2c devices on the LCD Adapter board. (We have to use i2c_new_device
39717 + * since it's late in the boot process.)
39719 + printk(KERN_INFO "%s: registering LCD Adapter board i2c resources\n", __FUNCTION__);
39720 + for (i = 0; i < ARRAY_SIZE(ip7500media_lcd_adapter_i2c_board_info); i++) {
39721 + i2c_new_device(adap, &ip7500media_lcd_adapter_i2c_board_info[i]);
39724 + i2c_put_adapter(adap);
39729 + * No LCD Adapter board, bring up VDC
39735 +late_initcall(ip7500media_video_init);
39736 +__setup("forcevdc=", ip7500media_set_forcevdc);
39739 + * ip7500media_init
39740 + * Called to add the devices which we have on this board
39742 +static int __init ip7500media_init(void)
39744 + struct platform_device *audio_dev;
39745 + int have_ethernet = (devtree_find_node("eth_lan") != 0);
39751 +#ifdef CONFIG_UIO_UBICOM32RING
39752 + ring_tio_init("decoder_ring");
39756 + * Register all of the devices we have on this board
39758 + printk(KERN_INFO "%s: registering device resources\n", __FUNCTION__);
39759 + platform_device_register(&ip7500media_i2c_device);
39760 + platform_device_register(&ip7500media_backlight_device);
39763 + * If ethernet doesn't exist then we can init the lcdpower
39765 + if (!have_ethernet) {
39766 + platform_device_register(&ip7500media_lcdpower_device);
39770 + * Allocate the audio drivers. SPDIF not supported on boards with ethernet.
39772 + audio_dev = audio_device_alloc("snd-ubi32-cs4350", "audio", "audio-i2sout", 0);
39774 + ip7500media_i2c_board_info[0].platform_data = audio_dev;
39777 + if (!have_ethernet) {
39778 + struct platform_device *audio_dev2;
39780 + audio_dev2 = audio_device_alloc("snd-ubi32-generic", "audio", "audio-spdifout", 0);
39781 + if (audio_dev2) {
39782 + platform_device_register(audio_dev2);
39787 + * Register all of the devices which sit on the I2C bus
39789 + printk(KERN_INFO "%s: registering i2c resources\n", __FUNCTION__);
39790 + i2c_register_board_info(0, ip7500media_i2c_board_info, ARRAY_SIZE(ip7500media_i2c_board_info));
39793 + * We have to initialize the SDIO after the I2C IOB gets setup. SDIO is initialized in
39794 + * ip7500media_u17_setup
39797 + printk("IP7500 Media Board\n");
39802 +arch_initcall(ip7500media_init);
39803 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-ip7k/board-ip7500module.c linux-2.6.30.10-ubi/arch/ubicom32/mach-ip7k/board-ip7500module.c
39804 --- linux-2.6.30.10/arch/ubicom32/mach-ip7k/board-ip7500module.c 1970-01-01 02:00:00.000000000 +0200
39805 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-ip7k/board-ip7500module.c 2009-12-11 11:45:11.000000000 +0200
39808 + * arch/ubicom32/mach-ip7k/board-ip7500module.c
39809 + * Support for IP7500 CPU module board.
39811 + * This file supports the IP7500 CPU module board:
39812 + * 8007-0510 Rev 1.0
39813 + * 8007-0510A Rev 1.0 (with ethernet)
39815 + * DIP Switch SW2 configuration: (*) default
39816 + * POS 1: on(*) = PCI enabled, off = PCI disabled
39817 + * POS 2: on(*) = TTYX => PA6, off = TTYX => PF12
39818 + * POS 3: on(*) = TTYY => PA7, off = TTYY => PF15
39821 + * (C) Copyright 2009, Ubicom, Inc.
39823 + * This file is part of the Ubicom32 Linux Kernel Port.
39825 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
39826 + * it and/or modify it under the terms of the GNU General Public License
39827 + * as published by the Free Software Foundation, either version 2 of the
39828 + * License, or (at your option) any later version.
39830 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
39831 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
39832 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
39833 + * the GNU General Public License for more details.
39835 + * You should have received a copy of the GNU General Public License
39836 + * along with the Ubicom32 Linux Kernel Port. If not,
39837 + * see <http://www.gnu.org/licenses/>.
39839 + * Ubicom32 implementation derived from (with many thanks):
39844 +#include <linux/device.h>
39845 +#include <linux/gpio.h>
39846 +#include <asm/board.h>
39849 + * ip7500module_init
39850 + * Called to add the devices which we have on this board
39852 +static int __init ip7500module_init(void)
39861 +arch_initcall(ip7500module_init);
39862 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-ip7k/board-ip7500wspkr.c linux-2.6.30.10-ubi/arch/ubicom32/mach-ip7k/board-ip7500wspkr.c
39863 --- linux-2.6.30.10/arch/ubicom32/mach-ip7k/board-ip7500wspkr.c 1970-01-01 02:00:00.000000000 +0200
39864 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-ip7k/board-ip7500wspkr.c 2009-12-11 11:45:11.000000000 +0200
39867 + * arch/ubicom32/mach-ip7k/board-ip7500wspkr.c
39868 + * Support for IP7500 Wireless Speaker board.
39870 + * This file supports the IP7500 Wireless Speaker board:
39871 + * 8007-1210 Rev 1.0
39873 + * (C) Copyright 2009, Ubicom, Inc.
39875 + * This file is part of the Ubicom32 Linux Kernel Port.
39877 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
39878 + * it and/or modify it under the terms of the GNU General Public License
39879 + * as published by the Free Software Foundation, either version 2 of the
39880 + * License, or (at your option) any later version.
39882 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
39883 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
39884 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
39885 + * the GNU General Public License for more details.
39887 + * You should have received a copy of the GNU General Public License
39888 + * along with the Ubicom32 Linux Kernel Port. If not,
39889 + * see <http://www.gnu.org/licenses/>.
39891 +#include <linux/device.h>
39892 +#include <linux/gpio.h>
39893 +#include <asm/board.h>
39895 +#include <linux/platform_device.h>
39896 +#include <asm/audio.h>
39897 +#include <linux/i2c.h>
39898 +#include <linux/i2c-gpio.h>
39900 +static struct i2c_board_info __initdata ip7500wspkr_i2c_board_info[] = {
39902 + * U6, CS4350 DAC, address 0x4B
39905 + .type = "cs4350",
39911 + * I2C bus on the board, SDA PE4, SCL PE5
39913 +static struct i2c_gpio_platform_data ip7500wspkr_i2c_data = {
39914 + .sda_pin = GPIO_RD_5,
39915 + .scl_pin = GPIO_RD_6,
39916 + .sda_is_open_drain = 0,
39917 + .scl_is_open_drain = 0,
39921 +static struct platform_device ip7500wspkr_i2c_device = {
39922 + .name = "i2c-gpio",
39925 + .platform_data = &ip7500wspkr_i2c_data,
39929 +static struct platform_device *ip7500wspkr_devices[] __initdata = {
39930 + &ip7500wspkr_i2c_device,
39934 + * ip7500wspkr_init
39935 + * Called to add the devices which we have on this board
39937 +static int __init ip7500wspkr_init(void)
39939 + struct platform_device *audio_dev;
39940 + struct platform_device *audio_dev2;
39946 + platform_add_devices(ip7500wspkr_devices, ARRAY_SIZE(ip7500wspkr_devices));
39948 + audio_dev = audio_device_alloc("snd-ubi32-cs4350", "audio", "audio-i2sout", 0);
39950 + ip7500wspkr_i2c_board_info[0].platform_data = audio_dev;
39953 + audio_dev2 = audio_device_alloc("snd-ubi32-generic", "audio", "audio-spdifout", 0);
39954 + if (audio_dev2) {
39955 + platform_device_register(audio_dev2);
39958 + printk(KERN_INFO "%s: registering i2c resources\n", __FUNCTION__);
39959 + i2c_register_board_info(0, ip7500wspkr_i2c_board_info, ARRAY_SIZE(ip7500wspkr_i2c_board_info));
39961 + printk(KERN_INFO "IP7500 Wireless Speaker Board\n");
39966 +arch_initcall(ip7500wspkr_init);
39967 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-ip7k/Kconfig linux-2.6.30.10-ubi/arch/ubicom32/mach-ip7k/Kconfig
39968 --- linux-2.6.30.10/arch/ubicom32/mach-ip7k/Kconfig 1970-01-01 02:00:00.000000000 +0200
39969 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-ip7k/Kconfig 2009-12-11 11:45:11.000000000 +0200
39973 + select UBICOM32_V4
39974 + select UBICOM_INPUT
39975 + select UBICOM_INPUT_I2C
39977 + select RTC_DRV_S35390A
39980 + select GPIO_PCA953X
39982 + select FB_UBICOM32
39983 + select LCD_CLASS_DEVICE
39984 + select LCD_UBICOM32POWER
39985 + select BACKLIGHT_LCD_SUPPORT
39986 + select BACKLIGHT_CLASS_DEVICE
39987 + select BACKLIGHT_UBICOM32
39989 + select MMC_UBICOM32
39993 + IP7145 Digital Picture Frame reference design, supports:
39998 + select UBICOM32_V4
39999 + select UBICOM_INPUT
40001 + select LEDS_CLASS
40004 + select SPI_UBICOM32_GPIO
40005 + select VLAN_8021Q
40006 + select UBICOM_SWITCH
40007 + select UBICOM_SWITCH_BCM539X
40009 + Ubicom IP7160 RGW Eval, supports:
40014 +config IP7160RGWLCD
40015 + bool "IP7160RGWLCD"
40016 + select UBICOM32_V4
40017 + select UBICOM_INPUT
40019 + select LEDS_CLASS
40022 + select SPI_UBICOM32_GPIO
40023 + select VLAN_8021Q
40024 + select UBICOM_SWITCH
40025 + select UBICOM_SWITCH_BCM539X
40026 + select INPUT_TOUCHSCREEN
40027 + select TOUCHSCREEN_TSC2007
40029 + select FB_UBICOM32_VIRTUAL
40033 + Ubicom IP7160 RGW Eval, supports:
40034 + 8007-0112 v1.2 + 8007-1410 v1.0
40036 + With Ubicom LCD Adapter
40041 +config IP7160BRINGUP
40042 + bool "IP7160BRINGUP"
40043 + select UBICOM32_V4
40045 + select LEDS_CLASS
40048 + Ubicom IP7160 Bringup, supports:
40053 + select UBICOM32_V4
40057 + select FB_UBICOM32
40058 + select BACKLIGHT_LCD_SUPPORT
40059 + select BACKLIGHT_CLASS_DEVICE
40061 + select SND_UBI32_AUDIO_CS4350
40062 + select UBICOM_HID
40064 + IP7160 Digital Picture Frame board, supports:
40065 + 8007-0211 Rev 1.1
40067 +config IP7500MODULE
40068 + bool "IP7500MODULE"
40069 + select UBICOM32_V4
40071 + Ubicom IP7500 CPU Module board, supports:
40075 + Please see ip7500module.c for more details.
40079 + select UBICOM32_V4
40083 + select SND_UBI32_AUDIO_CS4384
40085 + select FB_UBICOM32
40087 + Ubicom IP7500 Audio Video board, supports:
40090 + With Ubicom IP7500 CPU Module board:
40091 + 8007-0510 v1.0 -or-
40094 + Please see ip7500av.c for more details.
40096 +config IP7500MEDIA
40097 + bool "IP7500MEDIA"
40098 + select UBICOM32_V4
40099 + select UBICOM_INPUT_I2C
40101 + select RTC_DRV_S35390A
40104 + select GPIO_PCA953X
40106 + select FB_UBICOM32
40107 + select FB_UBICOM32_VIRTUAL
40108 + select FB_UBICOM32_VIRTUAL_NOAUTO
40109 + select LCD_CLASS_DEVICE
40110 + select LCD_UBICOM32POWER
40111 + select BACKLIGHT_LCD_SUPPORT
40112 + select BACKLIGHT_CLASS_DEVICE
40113 + select BACKLIGHT_UBICOM32
40114 + select INPUT_TOUCHSCREEN
40115 + select TOUCHSCREEN_TSC2007
40119 + select SND_UBI32_AUDIO_CS4350
40120 + select MMC_UBICOM32
40124 + IP7500 Media Board w/ IP7500 CPU Module board, supports:
40125 + 8007-0610 v1.0 w/ 8007-0510 v1.0
40126 + 8007-0610 v1.0 w/ 8007-0510 v1.0 NOPHY
40127 + 8007-0610 v1.0 w/ 8007-0511 v1.1 NOPHY
40129 + Also supports optional LCD Adapter board:
40133 + Please see ip7500media.c for more details.
40135 +config IP7500WSPKR
40136 + bool "IP7500WSPKR"
40137 + select UBICOM32_V4
40143 + select SND_UBI32_AUDIO_CS4350
40145 + IP7500 Wireless Speaker Board, supports:
40148 + Please see ip7500wspkr.c for more details.
40152 + select UBICOM32_V4
40156 + select FB_UBICOM32_VIRTUAL
40160 + select SND_UBI32_AUDIO_CS4350
40162 + select RTC_DRV_S35390A
40163 + select INPUT_TOUCHSCREEN
40164 + select TOUCHSCREEN_TSC2007
40165 + select BACKLIGHT_LCD_SUPPORT
40166 + select BACKLIGHT_CLASS_DEVICE
40167 + select BACKLIGHT_UBICOM32
40169 + IP7500 Internet Audio Player, supports:
40172 + Please see ip7500iap.c for more details.
40175 + Please see ip7500media.c for more details.
40176 diff -ruN linux-2.6.30.10/arch/ubicom32/mach-ip7k/Makefile linux-2.6.30.10-ubi/arch/ubicom32/mach-ip7k/Makefile
40177 --- linux-2.6.30.10/arch/ubicom32/mach-ip7k/Makefile 1970-01-01 02:00:00.000000000 +0200
40178 +++ linux-2.6.30.10-ubi/arch/ubicom32/mach-ip7k/Makefile 2009-12-11 11:45:11.000000000 +0200
40181 +# arch/ubicom32/mach-ip7k/Makefile
40182 +# Makefile for ip7k based boards.
40184 +# (C) Copyright 2009, Ubicom, Inc.
40186 +# This file is part of the Ubicom32 Linux Kernel Port.
40188 +# The Ubicom32 Linux Kernel Port is free software: you can redistribute
40189 +# it and/or modify it under the terms of the GNU General Public License
40190 +# as published by the Free Software Foundation, either version 2 of the
40191 +# License, or (at your option) any later version.
40193 +# The Ubicom32 Linux Kernel Port is distributed in the hope that it
40194 +# will be useful, but WITHOUT ANY WARRANTY; without even the implied
40195 +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
40196 +# the GNU General Public License for more details.
40198 +# You should have received a copy of the GNU General Public License
40199 +# along with the Ubicom32 Linux Kernel Port. If not,
40200 +# see <http://www.gnu.org/licenses/>.
40202 +# Ubicom32 implementation derived from (with many thanks):
40208 +obj-$(CONFIG_IP7145DPF) += board-ip7145dpf.o
40209 +obj-$(CONFIG_IP7160RGW) += board-ip7160rgw.o
40210 +obj-$(CONFIG_IP7160RGWLCD) += board-ip7160rgw.o
40211 +obj-$(CONFIG_IP7160BRINGUP) += board-ip7160bringup.o
40212 +obj-$(CONFIG_IP7160DPF) += board-ip7160dpf.o
40213 +obj-$(CONFIG_IP7500MODULE) += board-ip7500module.o
40214 +obj-$(CONFIG_IP7500MEDIA) += board-ip7500media.o
40215 +obj-$(CONFIG_IP7500AV) += board-ip7500av.o
40216 +obj-$(CONFIG_IP7500WSPKR) += board-ip7500wspkr.o
40217 +obj-$(CONFIG_IP7500IAP) += board-ip7500iap.o
40218 diff -ruN linux-2.6.30.10/arch/ubicom32/Makefile linux-2.6.30.10-ubi/arch/ubicom32/Makefile
40219 --- linux-2.6.30.10/arch/ubicom32/Makefile 1970-01-01 02:00:00.000000000 +0200
40220 +++ linux-2.6.30.10-ubi/arch/ubicom32/Makefile 2009-12-11 11:45:11.000000000 +0200
40223 +# arch/ubicom32/Makefile
40224 +# <TODO: Replace with short file description>
40226 +# (C) Copyright 2009, Ubicom, Inc.
40228 +# This file is part of the Ubicom32 Linux Kernel Port.
40230 +# The Ubicom32 Linux Kernel Port is free software: you can redistribute
40231 +# it and/or modify it under the terms of the GNU General Public License
40232 +# as published by the Free Software Foundation, either version 2 of the
40233 +# License, or (at your option) any later version.
40235 +# The Ubicom32 Linux Kernel Port is distributed in the hope that it
40236 +# will be useful, but WITHOUT ANY WARRANTY; without even the implied
40237 +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
40238 +# the GNU General Public License for more details.
40240 +# You should have received a copy of the GNU General Public License
40241 +# along with the Ubicom32 Linux Kernel Port. If not,
40242 +# see <http://www.gnu.org/licenses/>.
40244 +# Ubicom32 implementation derived from (with many thanks):
40250 +KBUILD_DEFCONFIG :=
40252 +# setup the machine name and machine dependent settings
40253 +machine-$(CONFIG_UBICOM32_V3) := ip5k
40254 +machine-$(CONFIG_UBICOM32_V4) := ip7k
40255 +MACHINE := $(machine-y)
40258 +model-$(CONFIG_RAMKERNEL) := ram
40259 +model-$(CONFIG_ROMKERNEL) := rom
40260 +MODEL := $(model-y)
40263 +CPUCLASS := $(cpuclass-y)
40268 +# We want the core kernel built using the fastcall ABI but modules need
40269 +# to be built using the slower calling convention because they could be
40270 +# loaded out of range for fast calls.
40272 +CFLAGS_KERNEL += -mfastcall
40273 +CFLAGS_MODULE += -mno-fastcall
40276 +# Some CFLAG additions based on specific CPU type.
40278 +cflags-$(CONFIG_UBICOM32_V3) := -march=ubicom32v3 -DIP5000
40279 +cflags-$(CONFIG_UBICOM32_V4) := -march=ubicom32v4 -DIP7000
40281 +ldflags-$(CONFIG_LINKER_RELAXATION) := --relax
40282 +LDFLAGS_vmlinux := $(ldflags-y)
40284 +GCCLIBDIR := $(dir $(shell $(CC) $(cflags-y) -print-libgcc-file-name))
40285 +GCC_LIBS := $(GCCLIBDIR)/libgcc.a
40287 +KBUILD_CFLAGS += $(cflags-y) -ffunction-sections
40288 +KBUILD_AFLAGS += $(cflags-y)
40290 +KBUILD_CFLAGS += -D__linux__ -Dlinux
40291 +KBUILD_CFLAGS += -DUTS_SYSNAME=\"uClinux\"
40293 +# include any machine specific directory
40294 +ifneq ($(machine-y),)
40295 +core-y += arch/$(ARCH)/mach-$(MACHINE)/
40298 +head-y := arch/$(ARCH)/kernel/head.o
40300 +core-y += arch/$(ARCH)/kernel/ \
40301 + arch/$(ARCH)/mm/ \
40302 + arch/$(ARCH)/crypto/ \
40303 + arch/$(ARCH)/mach-common/
40305 +drivers-$(CONFIG_OPROFILE) += arch/ubicom32/oprofile/
40307 +libs-y += arch/$(ARCH)/lib/
40308 +libs-y += $(GCC_LIBS)
40312 +# make sure developer has selected a valid board
40313 +ifeq ($(CONFIG_NOBOARD),y)
40314 +# $(error have to select a valid board file $(CONFIG_NOBOARD), please run kernel config again)
40315 +_all: config_board_error
40318 +config_board_error:
40319 + @echo "*************************************************"
40320 + @echo "You have not selected a proper board."
40321 + @echo "Please run menuconfig (or config) against your"
40322 + @echo "kernel and choose your board under Processor"
40324 + @echo "*************************************************"
40326 diff -ruN linux-2.6.30.10/arch/ubicom32/mm/fault.c linux-2.6.30.10-ubi/arch/ubicom32/mm/fault.c
40327 --- linux-2.6.30.10/arch/ubicom32/mm/fault.c 1970-01-01 02:00:00.000000000 +0200
40328 +++ linux-2.6.30.10-ubi/arch/ubicom32/mm/fault.c 2009-12-11 11:45:11.000000000 +0200
40331 + * arch/ubicom32/mm/fault.c
40332 + * Ubicom32 architecture page fault implementation.
40334 + * (C) Copyright 2009, Ubicom, Inc.
40335 + * Copyright (C) 1998 D. Jeff Dionne <jeff@lineo.ca>,
40336 + * Copyright (C) 2000 Lineo, Inc. (www.lineo.com)
40340 + * linux/arch/m68k/mm/fault.c
40342 + * Copyright (C) 1995 Hamish Macdonald
40344 + * This file is part of the Ubicom32 Linux Kernel Port.
40346 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
40347 + * it and/or modify it under the terms of the GNU General Public License
40348 + * as published by the Free Software Foundation, either version 2 of the
40349 + * License, or (at your option) any later version.
40351 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
40352 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
40353 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
40354 + * the GNU General Public License for more details.
40356 + * You should have received a copy of the GNU General Public License
40357 + * along with the Ubicom32 Linux Kernel Port. If not,
40358 + * see <http://www.gnu.org/licenses/>.
40360 + * Ubicom32 implementation derived from (with many thanks):
40366 +#include <linux/module.h>
40367 +#include <linux/mman.h>
40368 +#include <linux/mm.h>
40369 +#include <linux/kernel.h>
40370 +#include <linux/ptrace.h>
40372 +#include <asm/system.h>
40373 +#include <asm/pgtable.h>
40375 +extern void die_if_kernel(char *, struct pt_regs *, long);
40378 + * This routine handles page faults. It determines the problem, and
40379 + * then passes it off to one of the appropriate routines.
40382 + * bit 0 == 0 means no page found, 1 means protection fault
40383 + * bit 1 == 0 means read, 1 means write
40385 + * If this routine detects a bad access, it returns 1, otherwise it
40388 +asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
40389 + unsigned long error_code)
40392 + printk (KERN_DEBUG "regs->sr=%#x, regs->pc=%#lx, address=%#lx, %ld\n",
40393 + regs->sr, regs->pc, address, error_code);
40397 + * Oops. The kernel tried to access some bad page. We'll have to
40398 + * terminate things with extreme prejudice.
40400 + if ((unsigned long) address < PAGE_SIZE) {
40401 + printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
40403 + printk(KERN_ALERT "Unable to handle kernel access");
40404 + printk(KERN_ALERT " at virtual address %08lx\n",address);
40405 + die_if_kernel("Oops", regs, error_code);
40406 + do_exit(SIGKILL);
40410 diff -ruN linux-2.6.30.10/arch/ubicom32/mm/init.c linux-2.6.30.10-ubi/arch/ubicom32/mm/init.c
40411 --- linux-2.6.30.10/arch/ubicom32/mm/init.c 1970-01-01 02:00:00.000000000 +0200
40412 +++ linux-2.6.30.10-ubi/arch/ubicom32/mm/init.c 2009-12-11 11:45:11.000000000 +0200
40415 + * arch/ubicom32/mm/init.c
40416 + * Ubicom32 architecture virtual memory initialization.
40418 + * (C) Copyright 2009, Ubicom, Inc.
40419 + * Copyright (C) 1998 D. Jeff Dionne <jeff@lineo.ca>,
40420 + * Kenneth Albanowski <kjahds@kjahds.com>,
40421 + * Copyright (C) 2000 Lineo, Inc. (www.lineo.com)
40425 + * linux/arch/m68k/mm/init.c
40427 + * Copyright (C) 1995 Hamish Macdonald
40429 + * JAN/1999 -- hacked to support ColdFire (gerg@snapgear.com)
40430 + * DEC/2000 -- linux 2.4 support <davidm@snapgear.com>
40432 + * This file is part of the Ubicom32 Linux Kernel Port.
40434 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
40435 + * it and/or modify it under the terms of the GNU General Public License
40436 + * as published by the Free Software Foundation, either version 2 of the
40437 + * License, or (at your option) any later version.
40439 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
40440 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
40441 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
40442 + * the GNU General Public License for more details.
40444 + * You should have received a copy of the GNU General Public License
40445 + * along with the Ubicom32 Linux Kernel Port. If not,
40446 + * see <http://www.gnu.org/licenses/>.
40448 + * Ubicom32 implementation derived from (with many thanks):
40454 +#include <linux/signal.h>
40455 +#include <linux/sched.h>
40456 +#include <linux/kernel.h>
40457 +#include <linux/errno.h>
40458 +#include <linux/string.h>
40459 +#include <linux/types.h>
40460 +#include <linux/ptrace.h>
40461 +#include <linux/mman.h>
40462 +#include <linux/mm.h>
40463 +#include <linux/swap.h>
40464 +#include <linux/init.h>
40465 +#include <linux/highmem.h>
40466 +#include <linux/pagemap.h>
40467 +#include <linux/bootmem.h>
40468 +#include <linux/slab.h>
40470 +#include <asm/setup.h>
40471 +#include <asm/segment.h>
40472 +#include <asm/page.h>
40473 +#include <asm/pgtable.h>
40474 +#include <asm/system.h>
40475 +#include <asm/machdep.h>
40476 +#include <asm/ocm-alloc.h>
40477 +#include <asm/processor.h>
40481 +extern void die_if_kernel(char *,struct pt_regs *,long);
40482 +extern void free_initmem(void);
40485 + * BAD_PAGE is the page that is used for page faults when linux
40486 + * is out-of-memory. Older versions of linux just did a
40487 + * do_exit(), but using this instead means there is less risk
40488 + * for a process dying in kernel mode, possibly leaving a inode
40491 + * BAD_PAGETABLE is the accompanying page-table: it is initialized
40492 + * to point to BAD_PAGE entries.
40494 + * ZERO_PAGE is a special page that is used for zero-initialized
40497 +static unsigned long empty_bad_page_table;
40499 +static unsigned long empty_bad_page;
40501 +unsigned long empty_zero_page;
40503 +void show_mem(void)
40506 + int free = 0, total = 0, reserved = 0, shared = 0;
40509 + printk(KERN_INFO "\nMem-info:\n");
40510 + show_free_areas();
40512 + while (i-- > 0) {
40514 + if (PageReserved(mem_map+i))
40516 + else if (PageSwapCache(mem_map+i))
40518 + else if (!page_count(mem_map+i))
40521 + shared += page_count(mem_map+i) - 1;
40523 + printk(KERN_INFO "%d pages of RAM\n",total);
40524 + printk(KERN_INFO "%d free pages\n",free);
40525 + printk(KERN_INFO "%d reserved pages\n",reserved);
40526 + printk(KERN_INFO "%d pages shared\n",shared);
40527 + printk(KERN_INFO "%d pages swap cached\n",cached);
40530 +extern unsigned long memory_start;
40531 +extern unsigned long memory_end;
40532 +extern char __ocm_free_begin;
40533 +extern char __ocm_free_end;
40536 + * paging_init() continues the virtual memory environment setup which
40537 + * was begun by the code in arch/head.S.
40538 + * The parameters are pointers to where to stick the starting and ending
40539 + * addresses of available kernel virtual memory.
40541 +void __init paging_init(void)
40544 + * Make sure start_mem is page aligned, otherwise bootmem and
40545 + * page_alloc get different views of the world.
40548 + unsigned long start_mem = PAGE_ALIGN(memory_start);
40550 + unsigned long end_mem = memory_end & PAGE_MASK;
40553 + printk (KERN_DEBUG "start_mem is %#lx\nvirtual_end is %#lx\n",
40554 + start_mem, end_mem);
40558 + * Initialize the bad page table and bad page to point
40559 + * to a couple of allocated pages.
40561 + empty_bad_page_table = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
40562 + empty_bad_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
40563 + empty_zero_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
40564 + memset((void *)empty_zero_page, 0, PAGE_SIZE);
40567 + * TODO: enable setting up for user memory management interface.
40571 + printk (KERN_DEBUG "before free_area_init\n");
40573 + printk (KERN_DEBUG "free_area_init -> start_mem is %#lx\nvirtual_end is %#lx\n",
40574 + start_mem, end_mem);
40578 + unsigned long zones_size[MAX_NR_ZONES] = {0, };
40579 +#ifdef CONFIG_ZONE_DMA
40580 + zones_size[ZONE_DMA] = OCMSIZE >> PAGE_SHIFT;
40582 + zones_size[ZONE_NORMAL] = (end_mem - PAGE_OFFSET) >> PAGE_SHIFT;
40583 +#ifdef CONFIG_HIGHMEM
40584 + zones_size[ZONE_HIGHMEM] = 0;
40586 + free_area_init(zones_size);
40590 +void __init mem_init(void)
40592 + int codek = 0, datak = 0, initk = 0;
40593 + unsigned long tmp, ram_start, ram_end, len;
40594 + extern char _etext, _stext, _sdata, _ebss, __init_begin, __init_end;
40596 + unsigned long start_mem = memory_start; /* DAVIDM - these must start at end of kernel */
40597 + unsigned long end_mem = memory_end; /* DAVIDM - this must not include kernel stack at top */
40598 + processor_dram(&ram_start, &ram_end);
40599 + len = (ram_end - ram_start) + OCMSIZE;
40601 + printk(KERN_DEBUG "Mem_init: start=%lx, end=%lx\n", start_mem, end_mem);
40604 + end_mem &= PAGE_MASK;
40605 + high_memory = (void *) end_mem;
40607 + start_mem = PAGE_ALIGN(start_mem);
40608 + max_mapnr = num_physpages = (((unsigned long) high_memory) - PAGE_OFFSET) >> PAGE_SHIFT;
40610 + /* this will put all memory onto the freelists */
40611 +#ifdef CONFIG_ZONE_DMA
40613 + unsigned long ocm_free_begin = (unsigned long)&__ocm_free_begin;
40614 + unsigned long ocm_free_end = (unsigned long)&__ocm_free_end;
40615 + unsigned long zone_dma_begin = (ocm_free_begin + PAGE_SIZE - 1) & PAGE_MASK;
40616 + unsigned long zone_dma_end = ocm_free_end & PAGE_MASK;
40617 + if (zone_dma_end > zone_dma_begin)
40618 + free_bootmem(zone_dma_begin, zone_dma_end-zone_dma_begin);
40621 + totalram_pages = free_all_bootmem();
40623 + codek = (&_etext - &_stext) >> 10;
40624 + datak = (&_ebss - &_sdata) >> 10;
40625 + initk = (&__init_begin - &__init_end) >> 10;
40627 + tmp = nr_free_pages() << PAGE_SHIFT;
40628 + printk(KERN_INFO "Memory available: %luk/%luk RAM, (%dk kernel code, %dk data)\n",
40637 +#ifdef CONFIG_BLK_DEV_INITRD
40638 +void free_initrd_mem(unsigned long start, unsigned long end)
40641 + for (; start < end; start += PAGE_SIZE) {
40642 + ClearPageReserved(virt_to_page(start));
40643 + init_page_count(virt_to_page(start));
40644 + free_page(start);
40645 + totalram_pages++;
40648 + printk (KERN_NOTICE "Freeing initrd memory: %dk freed\n", pages);
40655 +#ifdef CONFIG_RAMKERNEL
40656 + unsigned long addr;
40657 + extern char __init_begin, __init_end;
40659 + * The following code should be cool even if these sections
40660 + * are not page aligned.
40662 + addr = PAGE_ALIGN((unsigned long)(&__init_begin));
40663 + /* next to check that the page we free is not a partial page */
40664 + for (; addr + PAGE_SIZE < (unsigned long)(&__init_end); addr +=PAGE_SIZE) {
40665 + ClearPageReserved(virt_to_page(addr));
40666 + init_page_count(virt_to_page(addr));
40668 + totalram_pages++;
40670 + printk(KERN_NOTICE "Freeing unused kernel memory: %ldk freed (0x%x - 0x%x)\n",
40671 + (addr - PAGE_ALIGN((long) &__init_begin)) >> 10,
40672 + (int)(PAGE_ALIGN((unsigned long)(&__init_begin))),
40673 + (int)(addr - PAGE_SIZE));
40676 diff -ruN linux-2.6.30.10/arch/ubicom32/mm/kmap.c linux-2.6.30.10-ubi/arch/ubicom32/mm/kmap.c
40677 --- linux-2.6.30.10/arch/ubicom32/mm/kmap.c 1970-01-01 02:00:00.000000000 +0200
40678 +++ linux-2.6.30.10-ubi/arch/ubicom32/mm/kmap.c 2009-12-11 11:45:11.000000000 +0200
40681 + * arch/ubicom32/mm/kmap.c
40682 + * Ubicom32 architecture non-mmu ioremap and friends implementation.
40684 + * (C) Copyright 2009, Ubicom, Inc.
40685 + * Copyright (C) 2000 Lineo, <davidm@snapgear.com>
40686 + * Copyright (C) 2000-2002 David McCullough <davidm@snapgear.com>
40688 + * This file is part of the Ubicom32 Linux Kernel Port.
40690 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
40691 + * it and/or modify it under the terms of the GNU General Public License
40692 + * as published by the Free Software Foundation, either version 2 of the
40693 + * License, or (at your option) any later version.
40695 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
40696 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
40697 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
40698 + * the GNU General Public License for more details.
40700 + * You should have received a copy of the GNU General Public License
40701 + * along with the Ubicom32 Linux Kernel Port. If not,
40702 + * see <http://www.gnu.org/licenses/>.
40704 + * Ubicom32 implementation derived from (with many thanks):
40710 +#include <linux/module.h>
40711 +#include <linux/mm.h>
40712 +#include <linux/kernel.h>
40713 +#include <linux/string.h>
40714 +#include <linux/types.h>
40715 +#include <linux/slab.h>
40716 +#include <linux/vmalloc.h>
40718 +#include <asm/setup.h>
40719 +#include <asm/segment.h>
40720 +#include <asm/page.h>
40721 +#include <asm/pgalloc.h>
40722 +#include <asm/io.h>
40723 +#include <asm/system.h>
40728 + * Map some physical address range into the kernel address space.
40730 +void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag)
40732 + return (void *)physaddr;
40736 + * Unmap a ioremap()ed region again.
40738 +void iounmap(void *addr)
40743 + * __iounmap unmaps nearly everything, so be careful
40744 + * it doesn't free currently pointer/page tables anymore but it
40745 + * wans't used anyway and might be added later.
40747 +void __iounmap(void *addr, unsigned long size)
40752 + * Set new cache mode for some kernel address space.
40753 + * The caller must push data for that range itself, if such data may already
40754 + * be in the cache.
40756 +void kernel_set_cachemode(void *addr, unsigned long size, int cmode)
40759 diff -ruN linux-2.6.30.10/arch/ubicom32/mm/Makefile linux-2.6.30.10-ubi/arch/ubicom32/mm/Makefile
40760 --- linux-2.6.30.10/arch/ubicom32/mm/Makefile 1970-01-01 02:00:00.000000000 +0200
40761 +++ linux-2.6.30.10-ubi/arch/ubicom32/mm/Makefile 2009-12-11 11:45:11.000000000 +0200
40764 +# arch/ubicom32/mm/Makefile
40765 +# <TODO: Replace with short file description>
40767 +# (C) Copyright 2009, Ubicom, Inc.
40769 +# This file is part of the Ubicom32 Linux Kernel Port.
40771 +# The Ubicom32 Linux Kernel Port is free software: you can redistribute
40772 +# it and/or modify it under the terms of the GNU General Public License
40773 +# as published by the Free Software Foundation, either version 2 of the
40774 +# License, or (at your option) any later version.
40776 +# The Ubicom32 Linux Kernel Port is distributed in the hope that it
40777 +# will be useful, but WITHOUT ANY WARRANTY; without even the implied
40778 +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
40779 +# the GNU General Public License for more details.
40781 +# You should have received a copy of the GNU General Public License
40782 +# along with the Ubicom32 Linux Kernel Port. If not,
40783 +# see <http://www.gnu.org/licenses/>.
40785 +# Ubicom32 implementation derived from (with many thanks):
40791 +# Makefile for the linux m68knommu specific parts of the memory manager.
40794 +obj-y += init.o fault.o memory.o kmap.o ocm-alloc.o
40795 diff -ruN linux-2.6.30.10/arch/ubicom32/mm/memory.c linux-2.6.30.10-ubi/arch/ubicom32/mm/memory.c
40796 --- linux-2.6.30.10/arch/ubicom32/mm/memory.c 1970-01-01 02:00:00.000000000 +0200
40797 +++ linux-2.6.30.10-ubi/arch/ubicom32/mm/memory.c 2009-12-11 11:45:11.000000000 +0200
40800 + * arch/ubicom32/mm/memory.c
40801 + * Ubicom32 architecture kernel_map() implementation.
40803 + * (C) Copyright 2009, Ubicom, Inc.
40804 + * Copyright (C) 1998 Kenneth Albanowski <kjahds@kjahds.com>,
40805 + * Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com)
40809 + * linux/arch/m68k/mm/memory.c
40811 + * Copyright (C) 1995 Hamish Macdonald
40813 + * This file is part of the Ubicom32 Linux Kernel Port.
40815 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
40816 + * it and/or modify it under the terms of the GNU General Public License
40817 + * as published by the Free Software Foundation, either version 2 of the
40818 + * License, or (at your option) any later version.
40820 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
40821 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
40822 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
40823 + * the GNU General Public License for more details.
40825 + * You should have received a copy of the GNU General Public License
40826 + * along with the Ubicom32 Linux Kernel Port. If not,
40827 + * see <http://www.gnu.org/licenses/>.
40829 + * Ubicom32 implementation derived from (with many thanks):
40835 +#include <linux/module.h>
40836 +#include <linux/mm.h>
40837 +#include <linux/kernel.h>
40838 +#include <linux/string.h>
40839 +#include <linux/types.h>
40840 +#include <linux/slab.h>
40842 +#include <asm/segment.h>
40843 +#include <asm/page.h>
40844 +#include <asm/pgtable.h>
40845 +#include <asm/system.h>
40848 + * Map some physical address range into the kernel address space.
40849 + * The code is copied and adapted from map_chunk().
40852 +unsigned long kernel_map(unsigned long paddr, unsigned long size,
40853 + int nocacheflag, unsigned long *memavailp )
40857 diff -ruN linux-2.6.30.10/arch/ubicom32/mm/ocm-alloc.c linux-2.6.30.10-ubi/arch/ubicom32/mm/ocm-alloc.c
40858 --- linux-2.6.30.10/arch/ubicom32/mm/ocm-alloc.c 1970-01-01 02:00:00.000000000 +0200
40859 +++ linux-2.6.30.10-ubi/arch/ubicom32/mm/ocm-alloc.c 2009-12-11 11:45:11.000000000 +0200
40862 + * arch/ubicom32/mm/ocm-alloc.c
40863 + * OCM allocator for Uibcom32 On-Chip memory
40865 + * (C) Copyright 2009, Ubicom, Inc.
40866 + * Copyright 2004-2008 Analog Devices Inc.
40870 + * arch/blackfin/mm/sram-alloc.c
40873 + * This file is part of the Ubicom32 Linux Kernel Port.
40875 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
40876 + * it and/or modify it under the terms of the GNU General Public License
40877 + * as published by the Free Software Foundation, either version 2 of the
40878 + * License, or (at your option) any later version.
40880 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
40881 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
40882 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
40883 + * the GNU General Public License for more details.
40885 + * You should have received a copy of the GNU General Public License
40886 + * along with the Ubicom32 Linux Kernel Port. If not,
40887 + * see <http://www.gnu.org/licenses/>.
40889 + * Ubicom32 implementation derived from (with many thanks):
40895 +#include <linux/module.h>
40896 +#include <linux/kernel.h>
40897 +#include <linux/types.h>
40898 +#include <linux/miscdevice.h>
40899 +#include <linux/ioport.h>
40900 +#include <linux/fcntl.h>
40901 +#include <linux/init.h>
40902 +#include <linux/poll.h>
40903 +#include <linux/proc_fs.h>
40904 +#include <linux/mutex.h>
40905 +#include <linux/rtc.h>
40906 +#include <asm/ocm-alloc.h>
40909 +#define DEBUGP printk
40911 +#define DEBUGP(fmt, a...)
40914 + * the data structure for OCM heap pieces
40916 +struct ocm_piece {
40920 + struct ocm_piece *next;
40924 + * struct ocm_heap
40927 + struct ocm_piece free_head;
40928 + struct ocm_piece used_head;
40929 + struct mutex lock;
40932 +static struct ocm_heap ocm_inst_heap;
40933 +int ubi32_ocm_skbuf_max = 21, ubi32_ocm_skbuf, ubi32_ddr_skbuf;
40936 + * OCM area for storing code
40938 +extern asmlinkage void *__ocm_free_begin;
40939 +extern asmlinkage void *__ocm_free_end;
40940 +extern asmlinkage void *__ocm_inst_heap_begin;
40941 +extern asmlinkage void *__ocm_inst_heap_end;
40942 +#define OCM_INST_HEAP_BEGIN ((unsigned int)&__ocm_inst_heap_begin)
40943 +#define OCM_INST_HEAP_END ((unsigned int)&__ocm_inst_heap_end)
40944 +#define OCM_INST_HEAP_LENGTH (OCM_INST_HEAP_END - OCM_INST_HEAP_BEGIN)
40946 +static struct kmem_cache *ocm_piece_cache;
40949 + * _ocm_heap_init()
40951 +static int __init _ocm_heap_init(struct ocm_heap *ocmh,
40952 + unsigned int start,
40953 + unsigned int size)
40955 + ocmh->free_head.next = kmem_cache_alloc(ocm_piece_cache, GFP_KERNEL);
40957 + if (!ocmh->free_head.next)
40960 + ocmh->free_head.next->paddr = (void *)start;
40961 + ocmh->free_head.next->size = size;
40962 + ocmh->free_head.next->pid = 0;
40963 + ocmh->free_head.next->next = 0;
40965 + ocmh->used_head.next = NULL;
40967 + /* mutex initialize */
40968 + mutex_init(&ocmh->lock);
40974 + * _ocm_alloc_init()
40976 + * starts the ocm heap(s)
40978 +static int __init _ocm_alloc_init(void)
40980 + if (OCM_INST_HEAP_LENGTH) {
40981 + ocm_piece_cache = kmem_cache_create("ocm_piece_cache",
40982 + sizeof(struct ocm_piece),
40983 + 0, SLAB_PANIC, NULL);
40985 + if (_ocm_heap_init(&ocm_inst_heap,
40986 + OCM_INST_HEAP_BEGIN,
40987 + OCM_INST_HEAP_LENGTH) == 0)
40988 + printk(KERN_INFO "OCM Instruction Heap %d KB\n",
40989 + OCM_INST_HEAP_LENGTH >> 10);
40991 + printk(KERN_INFO "Failed to initialize OCM "
40992 + "Instruction Heap\n");
40995 + printk(KERN_INFO "No space available for OCM "
40996 + "Instruction Heap\n");
41000 +pure_initcall(_ocm_alloc_init);
41004 + * generic alloc a block in the ocm heap, if successful
41005 + * returns the pointer.
41007 +static void *_ocm_alloc(size_t size, pid_t pid, struct ocm_heap *ocmheap)
41009 + struct ocm_piece *pslot, *plast, *pavail;
41010 + struct ocm_piece *pfree_head = &ocmheap->free_head;
41011 + struct ocm_piece *pused_head = &ocmheap->used_head;
41013 + if (size <= 0 || !pfree_head || !pused_head)
41016 + /* Align the size */
41017 + size = (size + 3) & ~3;
41019 + pslot = pfree_head->next;
41020 + plast = pfree_head;
41023 + * search an available piece slot
41025 + while (pslot != NULL && size > pslot->size) {
41027 + pslot = pslot->next;
41033 + if (pslot->size == size) {
41035 + * Unlink this block from the list
41037 + plast->next = pslot->next;
41041 + * Split this block in two.
41043 + pavail = kmem_cache_alloc(ocm_piece_cache, GFP_KERNEL);
41048 + pavail->paddr = pslot->paddr;
41049 + pavail->size = size;
41050 + pslot->paddr += size;
41051 + pslot->size -= size;
41054 + pavail->pid = pid;
41056 + pslot = pused_head->next;
41057 + plast = pused_head;
41060 + * insert new piece into used piece list !!!
41062 + while (pslot != NULL && pavail->paddr < pslot->paddr) {
41064 + pslot = pslot->next;
41067 + pavail->next = pslot;
41068 + plast->next = pavail;
41070 + DEBUGP("_ocm_alloc %d bytes at %p from in %p",
41071 + size, pavail->paddr, ocmheap);
41073 + return pavail->paddr;
41077 +/* Allocate the largest available block. */
41078 +static void *_ocm_alloc_max(struct ocm_heap *ocmheap,
41079 + unsigned long *psize)
41081 + struct ocm_piece *pfree_head = &ocmheap->free_head;
41082 + struct ocm_piece *pslot, *pmax;
41084 + pmax = pslot = pfree_head->next;
41086 + /* search an available piece slot */
41087 + while (pslot != NULL) {
41088 + if (pslot->size > pmax->size)
41090 + pslot = pslot->next;
41096 + *psize = pmax->size;
41098 + return _ocm_alloc(*psize, ocmheap);
41104 + * generic free a block in the ocm heap, if successful
41106 +static int _ocm_free(const void *addr,
41107 + struct ocm_heap *ocmheap)
41109 + struct ocm_piece *pslot, *plast, *pavail;
41110 + struct ocm_piece *pfree_head = &ocmheap->free_head;
41111 + struct ocm_piece *pused_head = &ocmheap->used_head;
41113 + /* search the relevant memory slot */
41114 + pslot = pused_head->next;
41115 + plast = pused_head;
41117 + /* search an available piece slot */
41118 + while (pslot != NULL && pslot->paddr != addr) {
41120 + pslot = pslot->next;
41124 + DEBUGP("_ocm_free %p not found in %p", addr, ocmheap);
41127 + DEBUGP("_ocm_free %p from in %p", addr, ocmheap);
41129 + plast->next = pslot->next;
41133 + /* insert free pieces back to the free list */
41134 + pslot = pfree_head->next;
41135 + plast = pfree_head;
41137 + while (pslot != NULL && addr > pslot->paddr) {
41139 + pslot = pslot->next;
41142 + if (plast != pfree_head &&
41143 + plast->paddr + plast->size == pavail->paddr) {
41144 + plast->size += pavail->size;
41145 + kmem_cache_free(ocm_piece_cache, pavail);
41147 + pavail->next = plast->next;
41148 + plast->next = pavail;
41152 + if (pslot && plast->paddr + plast->size == pslot->paddr) {
41153 + plast->size += pslot->size;
41154 + plast->next = pslot->next;
41155 + kmem_cache_free(ocm_piece_cache, pslot);
41162 + * ocm_inst_alloc()
41164 + * allocates a block of size in the ocm instrction heap, if
41165 + * successful returns address allocated.
41167 +void *ocm_inst_alloc(size_t size, pid_t pid)
41171 + if (!OCM_INST_HEAP_LENGTH)
41175 + mutex_lock(&ocm_inst_heap.lock);
41177 + addr = _ocm_alloc(size, pid, &ocm_inst_heap);
41179 + mutex_unlock(&ocm_inst_heap.lock);
41183 +EXPORT_SYMBOL(ocm_inst_alloc);
41186 + * ocm_inst_free()
41187 + * free a block in the ocm instrction heap, returns 0 if successful.
41189 +int ocm_inst_free(const void *addr)
41193 + if (!OCM_INST_HEAP_LENGTH)
41196 + mutex_lock(&ocm_inst_heap.lock);
41198 + ret = _ocm_free(addr, &ocm_inst_heap);
41200 + mutex_unlock(&ocm_inst_heap.lock);
41204 +EXPORT_SYMBOL(ocm_inst_free);
41208 + * free a block in one of the ocm heaps, returns 0 if successful.
41210 +int ocm_free(const void *addr)
41212 + if (addr >= (void *)OCM_INST_HEAP_BEGIN
41213 + && addr < (void *)(OCM_INST_HEAP_END))
41214 + return ocm_inst_free(addr);
41218 +EXPORT_SYMBOL(ocm_free);
41221 +#ifdef CONFIG_PROC_FS
41222 +/* Need to keep line of output the same. Currently, that is 46 bytes
41223 + * (including newline).
41225 +static int _ocm_proc_read(char *buf, int *len, int count, const char *desc,
41226 + struct ocm_heap *ocmheap)
41228 + struct ocm_piece *pslot;
41229 + struct ocm_piece *pfree_head = &ocmheap->free_head;
41230 + struct ocm_piece *pused_head = &ocmheap->used_head;
41232 + /* The format is the following
41233 + * --- OCM 123456789012345 Size PID State \n
41234 + * 12345678-12345678 1234567890 12345 1234567890\n
41237 + l = sprintf(&buf[*len], "--- OCM %-15s Size PID State \n",
41243 + mutex_lock(&ocm_inst_heap.lock);
41246 + * search the relevant memory slot
41248 + pslot = pused_head->next;
41250 + while (pslot != NULL && count > 46) {
41251 + l = sprintf(&buf[*len], "%p-%p %10i %5i %-10s\n",
41252 + pslot->paddr, pslot->paddr + pslot->size,
41253 + pslot->size, pslot->pid, "ALLOCATED");
41257 + pslot = pslot->next;
41260 + pslot = pfree_head->next;
41262 + while (pslot != NULL && count > 46) {
41263 + l = sprintf(&buf[*len], "%p-%p %10i %5i %-10s\n",
41264 + pslot->paddr, pslot->paddr + pslot->size,
41265 + pslot->size, pslot->pid, "FREE");
41269 + pslot = pslot->next;
41272 + mutex_unlock(&ocm_inst_heap.lock);
41277 +static int ocm_proc_read(char *buf, char **start, off_t offset, int count,
41278 + int *eof, void *data)
41282 + len = sprintf(&buf[len], "--- OCM SKB usage (max RX buf %d)\n"
41283 + "(SKB in OCM) %d - (SKB in DDR) %d\n",
41284 + ubi32_ocm_skbuf_max,
41286 + ubi32_ddr_skbuf);
41288 + len += sprintf(&buf[len], "--- OCM Data Heap Size\n"
41290 + ((void *)&__ocm_free_begin),
41291 + ((void *)&__ocm_free_end),
41292 + ((unsigned int)&__ocm_free_end) -
41293 + ((unsigned int)&__ocm_free_begin));
41295 + if (_ocm_proc_read(buf, &len, count - len, "Inst Heap",
41303 +static int ocm_proc_write(struct file *file, const char __user *buffer,
41304 + unsigned long count, void *data)
41309 + if (count > sizeof(in))
41312 + if (copy_from_user(in, buffer, count))
41316 + printk(KERN_INFO "OCM skb alloc max = %s\n", in);
41320 + while ((in[n] >= '0') && (in[n] <= '9')) {
41321 + v = v * 10 + (int)(in[n] - '0');
41328 + ubi32_ocm_skbuf_max = v;
41329 + ubi32_ocm_skbuf = ubi32_ddr_skbuf = 0;
41334 +static int __init sram_proc_init(void)
41336 + struct proc_dir_entry *ptr;
41337 + ptr = create_proc_entry("ocm", S_IFREG | S_IRUGO, NULL);
41339 + printk(KERN_WARNING "unable to create /proc/ocm\n");
41342 + ptr->read_proc = ocm_proc_read;
41343 + ptr->write_proc = ocm_proc_write;
41346 +late_initcall(sram_proc_init);
41348 diff -ruN linux-2.6.30.10/arch/ubicom32/oprofile/ipProf.h linux-2.6.30.10-ubi/arch/ubicom32/oprofile/ipProf.h
41349 --- linux-2.6.30.10/arch/ubicom32/oprofile/ipProf.h 1970-01-01 02:00:00.000000000 +0200
41350 +++ linux-2.6.30.10-ubi/arch/ubicom32/oprofile/ipProf.h 2009-12-11 11:45:11.000000000 +0200
41352 +#ifndef __IP_PROF_H__
41353 +#define __IP_PROF_H__
41355 +/* This number MUST match what is used in the ultra configuration! */
41356 +#define IPPROFILETIO_MAX_SAMPLES 600
41358 +/* Move to .h file used in both; avoid special types */
41359 +struct profile_sample {
41360 + unsigned int pc; /* PC value */
41361 + unsigned int parent; /* a5 contents, to find the caller */
41362 + unsigned char cond_codes; /* for branch prediction */
41363 + unsigned char thread; /* I-blocked, D-blocked,
41364 + 4-bit thread number */
41365 + unsigned short active; /* which threads are active -
41366 + for accurate counting */
41367 + unsigned short blocked; /* which threads are blocked due to
41368 + I or D cache misses */
41369 + unsigned int latency; /* CPU clocks since the last message
41370 + dispatch in this thread
41371 + (thread 0 only for now) */
41375 +struct profilenode {
41376 + struct devtree_node dn;
41377 + volatile unsigned char enabled; /* Is the tio enabled to
41379 + volatile unsigned char busy; /* set when the samples
41380 + are being read */
41381 + volatile unsigned int mask; /* Threads that change the MT_EN flag */
41382 + volatile unsigned short rate; /* What is the sampling rate? */
41383 + volatile unsigned short head; /* sample taker puts samples here */
41384 + volatile unsigned short tail; /* packet filler takes samples here */
41385 + volatile unsigned short count; /* number of valid samples */
41386 + volatile unsigned short total; /* Total samples */
41387 + struct profile_sample samples[IPPROFILETIO_MAX_SAMPLES];
41391 diff -ruN linux-2.6.30.10/arch/ubicom32/oprofile/Makefile linux-2.6.30.10-ubi/arch/ubicom32/oprofile/Makefile
41392 --- linux-2.6.30.10/arch/ubicom32/oprofile/Makefile 1970-01-01 02:00:00.000000000 +0200
41393 +++ linux-2.6.30.10-ubi/arch/ubicom32/oprofile/Makefile 2009-12-11 11:45:11.000000000 +0200
41396 +# arch/ubicom32/Makefile
41397 +# Makefile for Oprofile support on Ubicom32
41399 +# (C) Copyright 2009, Ubicom, Inc.
41401 +# This file is part of the Ubicom32 Linux Kernel Port.
41403 +# The Ubicom32 Linux Kernel Port is free software: you can redistribute
41404 +# it and/or modify it under the terms of the GNU General Public License
41405 +# as published by the Free Software Foundation, either version 2 of the
41406 +# License, or (at your option) any later version.
41408 +# The Ubicom32 Linux Kernel Port is distributed in the hope that it
41409 +# will be useful, but WITHOUT ANY WARRANTY; without even the implied
41410 +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
41411 +# the GNU General Public License for more details.
41413 +# You should have received a copy of the GNU General Public License
41414 +# along with the Ubicom32 Linux Kernel Port. If not,
41415 +# see <http://www.gnu.org/licenses/>.
41417 +# Ubicom32 implementation derived from (with many thanks):
41423 +obj-$(CONFIG_OPROFILE) += oprofile.o
41425 +DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \
41426 + oprof.o cpu_buffer.o buffer_sync.o \
41427 + event_buffer.o oprofile_files.o \
41428 + oprofilefs.o oprofile_stats.o \
41431 +oprofile-y := $(DRIVER_OBJS) profile.o
41432 diff -ruN linux-2.6.30.10/arch/ubicom32/oprofile/profile.c linux-2.6.30.10-ubi/arch/ubicom32/oprofile/profile.c
41433 --- linux-2.6.30.10/arch/ubicom32/oprofile/profile.c 1970-01-01 02:00:00.000000000 +0200
41434 +++ linux-2.6.30.10-ubi/arch/ubicom32/oprofile/profile.c 2009-12-11 11:45:11.000000000 +0200
41437 + * arch/ubicom32/oprofile/profile.c
41438 + * Oprofile support for arch Ubicom32
41440 + * (C) Copyright 2009, Ubicom, Inc.
41442 + * This file is part of the Ubicom32 Linux Kernel Port.
41444 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
41445 + * it and/or modify it under the terms of the GNU General Public License
41446 + * as published by the Free Software Foundation, either version 2 of the
41447 + * License, or (at your option)
41448 + * any later version.
41450 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it will
41451 + * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
41452 + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41453 + * General Public License for more details.
41455 + * You should have received a copy of the GNU General Public License
41456 + * along with the Ubicom32 Linux Kernel Port. If not, see
41457 + * <http://www.gnu.org/licenses/>.
41459 + * Ubicom32 implementation derived from (with many thanks):
41466 + * @file profile.c
41468 + * @remark Copyright 2002 OProfile authors
41469 + * @remark Read the file COPYING
41471 + * @author Hunyue Yau <hy@hy-research.com>
41474 +#include <linux/oprofile.h>
41475 +#include <linux/init.h>
41476 +#include <linux/errno.h>
41477 +#include <linux/interrupt.h>
41478 +#include <linux/module.h>
41479 +#include <linux/kernel.h>
41481 +#include <asm/devtree.h>
41482 +#include <asm/thread.h>
41484 +/* For identifying userland vs kernel address */
41485 +#include <asm/stacktrace.h>
41486 +#include "ipProf.h"
41488 +/* For communications with the backend */
41489 +static struct profilenode *profile_node;
41491 +/* Bitmask containing all Linux threads - as seen by the ROSR reg */
41492 +static unsigned long th_all_mask;
41494 +/* Lookup table to translate a hardware thread into a CPU identifier
41495 + * Table is indexed by the ROSR value which is assumed to be
41496 + * relatively small (0...15).
41498 +unsigned int cpu_map[THREAD_ARCHITECTURAL_MAX];
41500 +static struct pt_regs regs;
41503 + * For each sample returned, checked to see if they are relevant to
41504 + * us. This is necessary as the ubicom32 architecture has other software
41505 + * running outside of Linux. Only then, put the sample into the relevant
41508 + * To minimize overhead, a global mask with all possible threads of in
41509 + * interest to us is used as a first check. Then a second mask identifying
41510 + * the thread is used to obtain an identifier for that "CPU".
41514 + * ubicom32_build_cpu_th_mask()
41516 + * Build a lookup table for translation between hardware thread
41517 + * "ROSR" values and Linux CPU ids
41519 + * *** This gets executed on all CPUs at once! ***
41521 +static void ubicom32_build_cpu_th_mask(void *mask)
41523 + thread_t self = thread_get_self();
41524 + unsigned long *th_m = mask;
41526 + BUG_ON(self <= 0 || self >= THREAD_ARCHITECTURAL_MAX);
41527 + cpu_map[self] = smp_processor_id();
41529 + set_bit(self, th_m);
41533 + * profile_interrupt()
41535 + * Process samples returned from the profiler backend. The backend
41536 + * may return samples that are irrelevant to us or may even return
41537 + * multiple samples for the same CPU. Note that the sames may be
41538 + * for ANY cpu. At this time, this is unique and to support this requires
41539 + * Oprofile to expose an interface to accept the CPU that the same came
41542 +static irqreturn_t profile_interrupt(int irq, void *arg)
41544 + int i, buf_entry;
41546 + unsigned int bit_th;
41549 + if (!(profile_node->enabled) || profile_node->count < 0) {
41550 + printk(KERN_WARNING
41551 + "Unexpected interrupt, no samples or not enabled!\n");
41552 + return IRQ_HANDLED;
41555 + profile_node->busy = 1; /* Keep backend out */
41557 + for (i = 0; i < profile_node->count; i++) {
41558 + buf_entry = profile_node->tail;
41559 + profile_node->tail++;
41560 + profile_node->tail %= IPPROFILETIO_MAX_SAMPLES;
41562 + /* Note - the "thread" ID is only the lower 4 bits */
41563 + th = (0x0f & profile_node->samples[buf_entry].thread);
41564 + bit_th = (1 << th);
41566 + if ((bit_th & th_all_mask) == 0)
41569 + regs.pc = profile_node->samples[buf_entry].pc;
41571 + is_kernel = ubicom32_is_kernel(regs.pc);
41573 + oprofile_add_ext_sample_cpu(regs.pc, ®s, 0, is_kernel,
41576 + profile_node->count = 0;
41577 + profile_node->busy = 0;
41579 + return IRQ_HANDLED;
41583 + * profile_start()
41585 + * Notification from oprofile to start the profiler
41587 +static int profile_start(void)
41589 + if (!profile_node)
41592 + profile_node->enabled = 1;
41600 + * Notification from oprofile to stop the profiler
41602 +static void profile_stop(void)
41604 + if (profile_node)
41605 + profile_node->enabled = 0;
41609 + * oprofile_arch_init()
41611 + * Attach to Oprofile after qualify the availability of the backend
41612 + * profiler support.
41614 +int __init oprofile_arch_init(struct oprofile_operations *ops)
41618 + profile_node = (struct profilenode *)devtree_find_node("profiler");
41620 + if (profile_node == NULL) {
41621 + printk(KERN_WARNING "Cannot find profiler node\n");
41625 + r = request_irq(profile_node->dn.recvirq, profile_interrupt,
41626 + IRQF_DISABLED, "profiler", NULL);
41629 + profile_node = NULL;
41630 + printk(KERN_WARNING "Cannot get profiler IRQ\n");
41634 + ops->start = profile_start;
41635 + ops->stop = profile_stop;
41636 + ops->cpu_type = "timer";
41638 + memset(cpu_map, 0, sizeof(cpu_map));
41640 + on_each_cpu(ubicom32_build_cpu_th_mask, &th_all_mask, 1);
41642 + memset(®s, 0, sizeof(regs));
41648 + * oprofile_arch_exit()
41650 + * External call to take outselves out.
41651 + * Make sure backend is not running.
41653 +void oprofile_arch_exit(void)
41655 + BUG_ON(profile_node->enabled);
41657 diff -ruN linux-2.6.30.10/drivers/char/hw_random/Kconfig linux-2.6.30.10-ubi/drivers/char/hw_random/Kconfig
41658 --- linux-2.6.30.10/drivers/char/hw_random/Kconfig 2009-12-04 08:00:07.000000000 +0200
41659 +++ linux-2.6.30.10-ubi/drivers/char/hw_random/Kconfig 2009-12-11 11:45:13.000000000 +0200
41660 @@ -148,3 +148,16 @@
41662 To compile this driver as a module, choose M here: the
41663 module will be called virtio-rng. If unsure, say N.
41665 +config HW_RANDOM_UBICOM32
41666 + tristate "Ubicom32 HW Random Number Generator support"
41667 + depends on HW_RANDOM && UBICOM32
41668 + default HW_RANDOM
41670 + This driver provides kernel-side support for the Random Number
41671 + Generator hardware found on Ubicom32 processors.
41673 + To compile this driver as a module, choose M here: the
41674 + module will be called pasemi-rng.
41676 + If unsure, say Y.
41677 diff -ruN linux-2.6.30.10/drivers/char/hw_random/Makefile linux-2.6.30.10-ubi/drivers/char/hw_random/Makefile
41678 --- linux-2.6.30.10/drivers/char/hw_random/Makefile 2009-12-04 08:00:07.000000000 +0200
41679 +++ linux-2.6.30.10-ubi/drivers/char/hw_random/Makefile 2009-12-11 11:45:13.000000000 +0200
41681 obj-$(CONFIG_HW_RANDOM_OMAP) += omap-rng.o
41682 obj-$(CONFIG_HW_RANDOM_PASEMI) += pasemi-rng.o
41683 obj-$(CONFIG_HW_RANDOM_VIRTIO) += virtio-rng.o
41684 +obj-$(CONFIG_HW_RANDOM_UBICOM32) += ubicom32-rng.o
41685 diff -ruN linux-2.6.30.10/drivers/char/hw_random/ubicom32-rng.c linux-2.6.30.10-ubi/drivers/char/hw_random/ubicom32-rng.c
41686 --- linux-2.6.30.10/drivers/char/hw_random/ubicom32-rng.c 1970-01-01 02:00:00.000000000 +0200
41687 +++ linux-2.6.30.10-ubi/drivers/char/hw_random/ubicom32-rng.c 2009-12-11 11:45:13.000000000 +0200
41690 + * drivers/net/ubi32-eth.c
41691 + * Ubicom32 hardware random number generator driver.
41693 + * (C) Copyright 2009, Ubicom, Inc.
41695 + * This file is part of the Ubicom32 Linux Kernel Port.
41697 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
41698 + * it and/or modify it under the terms of the GNU General Public License
41699 + * as published by the Free Software Foundation, either version 2 of the
41700 + * License, or (at your option) any later version.
41702 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
41703 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
41704 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
41705 + * the GNU General Public License for more details.
41707 + * You should have received a copy of the GNU General Public License
41708 + * along with the Ubicom32 Linux Kernel Port. If not,
41709 + * see <http://www.gnu.org/licenses/>.
41711 + * Ubicom32 implementation derived from (with many thanks):
41717 +#include <linux/kernel.h>
41718 +#include <linux/module.h>
41719 +#include <linux/hw_random.h>
41720 +#include <linux/delay.h>
41721 +#include <asm/io.h>
41722 +#include <asm/ip5000.h>
41724 +#define MODULE_NAME "ubicom32_rng"
41726 +static int ubicom32_rng_data_present(struct hwrng *rng, int wait)
41730 + for (i = 0; i < 20; i++) {
41731 + data = *(int *)(TIMER_BASE + TIMER_TRN);
41732 + if (data || !wait)
41739 +static int ubicom32_rng_data_read(struct hwrng *rng, u32 *data)
41741 + *data = *(int *)(TIMER_BASE + TIMER_TRN);
41745 +static int ubicom32_rng_init(struct hwrng *rng)
41747 + printk(KERN_INFO "ubicom32 rng init\n");
41748 + *(int *)(TIMER_BASE + TIMER_TRN_CFG) = TIMER_TRN_CFG_ENABLE_OSC;
41752 +static void ubicom32_rng_cleanup(struct hwrng *rng)
41754 + printk(KERN_INFO "ubicom32 rng cleanup\n");
41755 + *(int *)(TIMER_BASE + TIMER_TRN_CFG) = 0;
41758 +static struct hwrng ubicom32_rng = {
41759 + .name = MODULE_NAME,
41760 + .init = ubicom32_rng_init,
41761 + .cleanup = ubicom32_rng_cleanup,
41762 + .data_present = ubicom32_rng_data_present,
41763 + .data_read = ubicom32_rng_data_read,
41767 +static int __init mod_init(void)
41771 + printk(KERN_INFO "ubicom32 rng started\n");
41772 + err = hwrng_register(&ubicom32_rng);
41774 + printk(KERN_ERR "ubicom32 rng register failed (%d)\n",
41781 +static void __exit mod_exit(void)
41783 + printk(KERN_INFO "ubicom32 rng stopped\n");
41784 + hwrng_unregister(&ubicom32_rng);
41787 +module_init(mod_init);
41788 +module_exit(mod_exit);
41790 +MODULE_LICENSE("GPL");
41791 +MODULE_AUTHOR("Ubicom, Inc.");
41792 +MODULE_DESCRIPTION("H/W rng driver for ubicom32 processor");
41793 +MODULE_VERSION("1:1.0.a");
41794 diff -ruN linux-2.6.30.10/drivers/crypto/Kconfig linux-2.6.30.10-ubi/drivers/crypto/Kconfig
41795 --- linux-2.6.30.10/drivers/crypto/Kconfig 2009-12-04 08:00:07.000000000 +0200
41796 +++ linux-2.6.30.10-ubi/drivers/crypto/Kconfig 2009-12-11 11:45:13.000000000 +0200
41798 To compile this driver as a module, choose M here: the module
41799 will be called geode-aes.
41801 +config CRYPTO_UBICOM32
41802 + bool "Ubicom32 Security Module"
41803 + depends on UBICOM32
41805 + This is the ubicom32 hardware acceleration common code.
41807 +config CRYPTO_AES_UBICOM32
41808 + tristate "Ubicom32 AES implementation"
41809 + depends on CRYPTO_UBICOM32
41810 + select CRYPTO_ALGAPI
41812 + This is the ubicom32 hardware AES implementation.
41814 +config CRYPTO_DES_UBICOM32
41815 + tristate "Ubicom32 DES implementation"
41816 + depends on CRYPTO_UBICOM32
41817 + select CRYPTO_ALGAPI
41819 + This is the ubicom32 hardware DES and 3DES implementation.
41821 +config CRYPTO_SHA1_UBICOM32
41822 + tristate "Ubicom32 SHA1 implementation"
41823 + depends on CRYPTO_UBICOM32
41824 + select CRYPTO_ALGAPI
41826 + This is the ubicom32 hardware SHA1 implementation.
41828 +config CRYPTO_MD5_UBICOM32
41829 + tristate "Ubicom32 MD5 implementation"
41830 + depends on CRYPTO_UBICOM32
41831 + select CRYPTO_ALGAPI
41833 + This is the ubicom32 hardware MD5 implementation.
41836 tristate "Support for PCI-attached cryptographic adapters"
41838 diff -ruN linux-2.6.30.10/drivers/mmc/host/Kconfig linux-2.6.30.10-ubi/drivers/mmc/host/Kconfig
41839 --- linux-2.6.30.10/drivers/mmc/host/Kconfig 2009-12-14 11:15:33.000000000 +0200
41840 +++ linux-2.6.30.10-ubi/drivers/mmc/host/Kconfig 2009-12-14 11:15:31.000000000 +0200
41841 @@ -266,3 +266,10 @@
41843 This option automatically enables configfs support for gpiommc
41844 if configfs is available.
41846 +config MMC_UBICOM32
41847 + tristate "Ubicom32 MMC/SD host controller"
41848 + depends on UBICOM32
41850 + This provides support for the SD/MMC hardware found on Ubicom32
41852 diff -ruN linux-2.6.30.10/drivers/mmc/host/Makefile linux-2.6.30.10-ubi/drivers/mmc/host/Makefile
41853 --- linux-2.6.30.10/drivers/mmc/host/Makefile 2009-12-14 11:37:36.000000000 +0200
41854 +++ linux-2.6.30.10-ubi/drivers/mmc/host/Makefile 2009-12-14 11:37:35.000000000 +0200
41856 obj-$(CONFIG_MMC_SDRICOH_CS) += sdricoh_cs.o
41857 obj-$(CONFIG_MMC_TMIO) += tmio_mmc.o
41858 obj-$(CONFIG_GPIOMMC) += gpiommc.o
41859 +obj-$(CONFIG_MMC_UBICOM32) += ubicom32sd.o
41861 diff -ruN linux-2.6.30.10/drivers/mmc/host/ubicom32sd.c linux-2.6.30.10-ubi/drivers/mmc/host/ubicom32sd.c
41862 --- linux-2.6.30.10/drivers/mmc/host/ubicom32sd.c 1970-01-01 02:00:00.000000000 +0200
41863 +++ linux-2.6.30.10-ubi/drivers/mmc/host/ubicom32sd.c 2009-12-11 11:45:16.000000000 +0200
41866 + * drivers/mmc/host/ubicom32sd.c
41867 + * Ubicom32 Secure Digital Host Controller Interface driver
41869 + * (C) Copyright 2009, Ubicom, Inc.
41871 + * This file is part of the Ubicom32 Linux Kernel Port.
41873 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
41874 + * it and/or modify it under the terms of the GNU General Public License
41875 + * as published by the Free Software Foundation, either version 2 of the
41876 + * License, or (at your option) any later version.
41878 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
41879 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
41880 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
41881 + * the GNU General Public License for more details.
41883 + * You should have received a copy of the GNU General Public License
41884 + * along with the Ubicom32 Linux Kernel Port. If not,
41885 + * see <http://www.gnu.org/licenses/>.
41888 +#include <linux/module.h>
41889 +#include <linux/platform_device.h>
41890 +#include <linux/delay.h>
41891 +#include <linux/scatterlist.h>
41892 +#include <linux/leds.h>
41893 +#include <linux/gpio.h>
41894 +#include <linux/mmc/host.h>
41896 +#include <asm/ubicom32sd.h>
41898 +#define DRIVER_NAME "ubicom32sd"
41900 +#define sd_printk(...)
41901 +//#define sd_printk printk
41903 +#define SDTIO_VP_VERSION 3
41905 +#define SDTIO_MAX_SG_BLOCKS 16
41907 +enum sdtio_commands {
41908 + SDTIO_COMMAND_NOP,
41909 + SDTIO_COMMAND_SETUP,
41910 + SDTIO_COMMAND_SETUP_SDIO,
41911 + SDTIO_COMMAND_EXECUTE,
41912 + SDTIO_COMMAND_RESET,
41915 +#define SDTIO_COMMAND_SHIFT 24
41916 +#define SDTIO_COMMAND_FLAG_STOP_RSP_CRC (1 << 10)
41917 +#define SDTIO_COMMAND_FLAG_STOP_RSP_136 (1 << 9)
41918 +#define SDTIO_COMMAND_FLAG_STOP_RSP (1 << 8)
41919 +#define SDTIO_COMMAND_FLAG_STOP_CMD (1 << 7)
41920 +#define SDTIO_COMMAND_FLAG_DATA_STREAM (1 << 6)
41921 +#define SDTIO_COMMAND_FLAG_DATA_RD (1 << 5)
41922 +#define SDTIO_COMMAND_FLAG_DATA_WR (1 << 4)
41923 +#define SDTIO_COMMAND_FLAG_CMD_RSP_CRC (1 << 3)
41924 +#define SDTIO_COMMAND_FLAG_CMD_RSP_136 (1 << 2)
41925 +#define SDTIO_COMMAND_FLAG_CMD_RSP (1 << 1)
41926 +#define SDTIO_COMMAND_FLAG_CMD (1 << 0)
41929 + * SDTIO_COMMAND_SETUP_SDIO
41931 +#define SDTIO_COMMAND_FLAG_SDIO_INT_EN (1 << 0)
41934 + * SDTIO_COMMAND_SETUP
41935 + * clock speed in arg
41937 +#define SDTIO_COMMAND_FLAG_4BIT (1 << 3)
41938 +#define SDTIO_COMMAND_FLAG_1BIT (1 << 2)
41939 +#define SDTIO_COMMAND_FLAG_SET_CLOCK (1 << 1)
41940 +#define SDTIO_COMMAND_FLAG_SET_WIDTH (1 << 0)
41942 +#define SDTIO_COMMAND_FLAG_CMD_RSP_MASK (SDTIO_COMMAND_FLAG_CMD_RSP | SDTIO_COMMAND_FLAG_CMD_RSP_136)
41943 +#define SDTIO_COMMAND_FLAG_STOP_RSP_MASK (SDTIO_COMMAND_FLAG_STOP_RSP | SDTIO_COMMAND_FLAG_STOP_RSP_136)
41944 +#define SDTIO_COMMAND_FLAG_RSP_MASK (SDTIO_COMMAND_FLAG_CMD_RSP_MASK | SDTIO_COMMAND_FLAG_STOP_RSP_MASK)
41946 +struct sdtio_vp_sg {
41947 + volatile void *addr;
41948 + volatile u32_t len;
41951 +#define SDTIO_VP_INT_STATUS_DONE (1 << 31)
41952 +#define SDTIO_VP_INT_STATUS_SDIO_INT (1 << 10)
41953 +#define SDTIO_VP_INT_STATUS_DATA_CRC_ERR (1 << 9)
41954 +#define SDTIO_VP_INT_STATUS_DATA_PROG_ERR (1 << 8)
41955 +#define SDTIO_VP_INT_STATUS_DATA_TIMEOUT (1 << 7)
41956 +#define SDTIO_VP_INT_STATUS_STOP_RSP_CRC (1 << 6)
41957 +#define SDTIO_VP_INT_STATUS_STOP_RSP_TIMEOUT (1 << 5)
41958 +#define SDTIO_VP_INT_STATUS_CMD_RSP_CRC (1 << 4)
41959 +#define SDTIO_VP_INT_STATUS_CMD_RSP_TIMEOUT (1 << 3)
41960 +#define SDTIO_VP_INT_STATUS_CMD_TIMEOUT (1 << 2)
41961 +#define SDTIO_VP_INT_STATUS_CARD1_INSERT (1 << 1)
41962 +#define SDTIO_VP_INT_STATUS_CARD0_INSERT (1 << 0)
41964 +struct sdtio_vp_regs {
41969 + volatile u32_t int_status;
41971 + volatile u32_t command;
41972 + volatile u32_t arg;
41974 + volatile u32_t cmd_opcode;
41975 + volatile u32_t cmd_arg;
41976 + volatile u32_t cmd_rsp0;
41977 + volatile u32_t cmd_rsp1;
41978 + volatile u32_t cmd_rsp2;
41979 + volatile u32_t cmd_rsp3;
41981 + volatile u32_t stop_opcode;
41982 + volatile u32_t stop_arg;
41983 + volatile u32_t stop_rsp0;
41984 + volatile u32_t stop_rsp1;
41985 + volatile u32_t stop_rsp2;
41986 + volatile u32_t stop_rsp3;
41988 + volatile u32_t data_timeout_ns;
41989 + volatile u16_t data_blksz;
41990 + volatile u16_t data_blkct;
41991 + volatile u32_t data_bytes_transferred;
41992 + volatile u32_t sg_len;
41993 + struct sdtio_vp_sg sg[SDTIO_MAX_SG_BLOCKS];
41996 +struct ubicom32sd_data {
41997 + const struct ubicom32sd_platform_data *pdata;
41999 + struct mmc_host *mmc;
42002 + * Lock used to protect the data structure
42009 + * Receive and transmit interrupts used for communicating
42016 + * Current outstanding mmc request
42018 + struct mmc_request *mrq;
42021 + * Hardware registers
42023 + struct sdtio_vp_regs *regs;
42026 +/*****************************************************************************\
42028 + * Suspend/resume *
42030 +\*****************************************************************************/
42032 +#if 0//def CONFIG_PM
42034 +int ubicom32sd_suspend_host(struct ubicom32sd_host *host, pm_message_t state)
42038 + ret = mmc_suspend_host(host->mmc, state);
42042 + free_irq(host->irq, host);
42047 +EXPORT_SYMBOL_GPL(ubicom32sd_suspend_host);
42049 +int ubicom32sd_resume_host(struct ubicom32sd_host *host)
42053 + if (host->flags & UBICOM32SD_USE_DMA) {
42054 + if (host->ops->enable_dma)
42055 + host->ops->enable_dma(host);
42058 + ret = request_irq(host->irq, ubicom32sd_irq, IRQF_SHARED,
42059 + mmc_hostname(host->mmc), host);
42063 + ubicom32sd_init(host);
42066 + ret = mmc_resume_host(host->mmc);
42073 +EXPORT_SYMBOL_GPL(ubicom32sd_resume_host);
42075 +#endif /* CONFIG_PM */
42078 + * ubicom32sd_send_command_sync
42080 +static void ubicom32sd_send_command_sync(struct ubicom32sd_data *ud, u32_t command, u32_t arg)
42082 + ud->regs->command = command;
42083 + ud->regs->arg = arg;
42084 + ubicom32_set_interrupt(ud->irq_tx);
42085 + while (ud->regs->command) {
42091 + * ubicom32sd_send_command
42093 +static void ubicom32sd_send_command(struct ubicom32sd_data *ud, u32_t command, u32_t arg)
42095 + ud->regs->command = command;
42096 + ud->regs->arg = arg;
42097 + ubicom32_set_interrupt(ud->irq_tx);
42101 + * ubicom32sd_reset
42103 +static void ubicom32sd_reset(struct ubicom32sd_data *ud)
42105 + ubicom32sd_send_command_sync(ud, SDTIO_COMMAND_RESET << SDTIO_COMMAND_SHIFT, 0);
42106 + ud->regs->int_status = 0;
42110 + * ubicom32sd_mmc_request
42112 +static void ubicom32sd_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
42114 + struct ubicom32sd_data *ud = (struct ubicom32sd_data *)mmc_priv(mmc);
42115 + u32_t command = SDTIO_COMMAND_EXECUTE << SDTIO_COMMAND_SHIFT;
42118 + WARN(ud->mrq != NULL, "ud->mrq still set to %p\n", ud->mrq);
42119 + //pr_debug("send cmd %08x arg %08x flags %08x\n", cmd->opcode, cmd->arg, cmd->flags);
42122 + struct mmc_command *cmd = mrq->cmd;
42124 + sd_printk("%s:\t\t\tsetup cmd %02d arg %08x flags %08x\n", mmc_hostname(mmc), cmd->opcode, cmd->arg, cmd->flags);
42126 + ud->regs->cmd_opcode = cmd->opcode;
42127 + ud->regs->cmd_arg = cmd->arg;
42129 + command |= SDTIO_COMMAND_FLAG_CMD;
42131 + if (cmd->flags & MMC_RSP_PRESENT) {
42132 + command |= SDTIO_COMMAND_FLAG_CMD_RSP;
42135 + if (cmd->flags & MMC_RSP_136) {
42136 + command |= SDTIO_COMMAND_FLAG_CMD_RSP_136;
42139 + if (cmd->flags & MMC_RSP_CRC) {
42140 + command |= SDTIO_COMMAND_FLAG_CMD_RSP_CRC;
42145 + struct mmc_data *data = mrq->data;
42146 + struct scatterlist *sg = data->sg;
42149 +printk("%s:\t\t\tsetup data blksz %d num %d sglen=%d fl=%08x Tns=%u\n", mmc_hostname(mmc), data->blksz, data->blocks, data->sg_len, data->flags, data->timeout_ns);
42151 + sd_printk("%s:\t\t\tsetup data blksz %d num %d sglen=%d fl=%08x Tns=%u\n",
42152 + mmc_hostname(mmc), data->blksz, data->blocks, data->sg_len,
42153 + data->flags, data->timeout_ns);
42155 + if (data->sg_len > SDTIO_MAX_SG_BLOCKS) {
42157 + data->error = -EINVAL;
42161 + ud->regs->data_timeout_ns = data->timeout_ns;
42162 + ud->regs->data_blksz = data->blksz;
42163 + ud->regs->data_blkct = data->blocks;
42164 + ud->regs->sg_len = data->sg_len;
42167 + * Load all of our sg list into the driver sg buffer
42169 + for (i = 0; i < data->sg_len; i++) {
42170 + sd_printk("%s: sg %d = %p %d\n", mmc_hostname(mmc), i, sg_virt(sg), sg->length);
42171 + ud->regs->sg[i].addr = sg_virt(sg);
42172 + ud->regs->sg[i].len = sg->length;
42173 + if (((u32_t)ud->regs->sg[i].addr & 0x03) || (sg->length & 0x03)) {
42174 + sd_printk("%s: Need aligned buffers\n", mmc_hostname(mmc));
42176 + data->error = -EINVAL;
42181 + if (data->flags & MMC_DATA_READ) {
42182 + command |= SDTIO_COMMAND_FLAG_DATA_RD;
42183 + } else if (data->flags & MMC_DATA_WRITE) {
42184 + command |= SDTIO_COMMAND_FLAG_DATA_WR;
42185 + } else if (data->flags & MMC_DATA_STREAM) {
42186 + command |= SDTIO_COMMAND_FLAG_DATA_STREAM;
42191 + struct mmc_command *stop = mrq->stop;
42192 + sd_printk("%s: \t\t\tsetup stop %02d arg %08x flags %08x\n", mmc_hostname(mmc), stop->opcode, stop->arg, stop->flags);
42194 + ud->regs->stop_opcode = stop->opcode;
42195 + ud->regs->stop_arg = stop->arg;
42197 + command |= SDTIO_COMMAND_FLAG_STOP_CMD;
42199 + if (stop->flags & MMC_RSP_PRESENT) {
42200 + command |= SDTIO_COMMAND_FLAG_STOP_RSP;
42203 + if (stop->flags & MMC_RSP_136) {
42204 + command |= SDTIO_COMMAND_FLAG_STOP_RSP_136;
42207 + if (stop->flags & MMC_RSP_CRC) {
42208 + command |= SDTIO_COMMAND_FLAG_STOP_RSP_CRC;
42214 + sd_printk("%s: Sending command %08x\n", mmc_hostname(mmc), command);
42216 + ubicom32sd_send_command(ud, command, 0);
42220 + sd_printk("%s: mmcreq ret = %d\n", mmc_hostname(mmc), ret);
42221 + mrq->cmd->error = ret;
42222 + mmc_request_done(mmc, mrq);
42226 + * ubicom32sd_mmc_set_ios
42228 +static void ubicom32sd_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
42230 + struct ubicom32sd_data *ud = (struct ubicom32sd_data *)mmc_priv(mmc);
42231 + u32_t command = SDTIO_COMMAND_SETUP << SDTIO_COMMAND_SHIFT;
42233 + sd_printk("%s: ios call bw:%u pm:%u clk:%u\n", mmc_hostname(mmc), 1 << ios->bus_width, ios->power_mode, ios->clock);
42235 + switch (ios->bus_width) {
42236 + case MMC_BUS_WIDTH_1:
42237 + command |= SDTIO_COMMAND_FLAG_SET_WIDTH | SDTIO_COMMAND_FLAG_1BIT;
42240 + case MMC_BUS_WIDTH_4:
42241 + command |= SDTIO_COMMAND_FLAG_SET_WIDTH | SDTIO_COMMAND_FLAG_4BIT;
42245 + if (ios->clock) {
42246 + arg = ios->clock;
42247 + command |= SDTIO_COMMAND_FLAG_SET_CLOCK;
42250 + switch (ios->power_mode) {
42253 + * Turn off the SD bus (power + clock)
42255 + case MMC_POWER_OFF:
42256 + gpio_set_value(ud->pdata->cards[0].pin_pwr, !ud->pdata->cards[0].pwr_polarity);
42257 + command |= SDTIO_COMMAND_FLAG_SET_CLOCK;
42261 + * Turn on the power to the SD bus
42263 + case MMC_POWER_ON:
42264 + gpio_set_value(ud->pdata->cards[0].pin_pwr, ud->pdata->cards[0].pwr_polarity);
42268 + * Turn on the clock to the SD bus
42270 + case MMC_POWER_UP:
42277 + ubicom32sd_send_command_sync(ud, command, arg);
42280 + * Let the power settle down
42286 + * ubicom32sd_mmc_get_cd
42288 +static int ubicom32sd_mmc_get_cd(struct mmc_host *mmc)
42290 + struct ubicom32sd_data *ud = (struct ubicom32sd_data *)mmc_priv(mmc);
42291 + sd_printk("%s: get cd %u %u\n", mmc_hostname(mmc), ud->pdata->cards[0].pin_cd, gpio_get_value(ud->pdata->cards[0].pin_cd));
42293 + return gpio_get_value(ud->pdata->cards[0].pin_cd) ?
42294 + ud->pdata->cards[0].cd_polarity :
42295 + !ud->pdata->cards[0].cd_polarity;
42299 + * ubicom32sd_mmc_get_ro
42301 +static int ubicom32sd_mmc_get_ro(struct mmc_host *mmc)
42303 + struct ubicom32sd_data *ud = (struct ubicom32sd_data *)mmc_priv(mmc);
42304 + sd_printk("%s: get ro %u %u\n", mmc_hostname(mmc), ud->pdata->cards[0].pin_wp, gpio_get_value(ud->pdata->cards[0].pin_wp));
42306 + return gpio_get_value(ud->pdata->cards[0].pin_wp) ?
42307 + ud->pdata->cards[0].wp_polarity :
42308 + !ud->pdata->cards[0].wp_polarity;
42312 + * ubicom32sd_mmc_enable_sdio_irq
42314 +static void ubicom32sd_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
42316 + struct ubicom32sd_data *ud = (struct ubicom32sd_data *)mmc_priv(mmc);
42318 + ud->int_en = enable;
42319 + if (enable && ud->int_pend) {
42320 + ud->int_pend = 0;
42321 + mmc_signal_sdio_irq(mmc);
42326 + * ubicom32sd_interrupt
42328 +static irqreturn_t ubicom32sd_interrupt(int irq, void *dev)
42330 + struct mmc_host *mmc = (struct mmc_host *)dev;
42331 + struct mmc_request *mrq;
42332 + struct ubicom32sd_data *ud;
42333 + u32_t int_status;
42336 + return IRQ_HANDLED;
42339 + ud = (struct ubicom32sd_data *)mmc_priv(mmc);
42341 + return IRQ_HANDLED;
42344 + int_status = ud->regs->int_status;
42345 + ud->regs->int_status &= ~int_status;
42347 + if (int_status & SDTIO_VP_INT_STATUS_SDIO_INT) {
42348 + if (ud->int_en) {
42349 + ud->int_pend = 0;
42350 + mmc_signal_sdio_irq(mmc);
42356 + if (!(int_status & SDTIO_VP_INT_STATUS_DONE)) {
42357 + return IRQ_HANDLED;
42362 + sd_printk("%s: Spurious interrupt", mmc_hostname(mmc));
42363 + return IRQ_HANDLED;
42368 + * SDTIO_VP_INT_DONE
42370 + if (mrq->cmd->flags & MMC_RSP_PRESENT) {
42371 + struct mmc_command *cmd = mrq->cmd;
42374 + if ((cmd->flags & MMC_RSP_CRC) && (int_status & SDTIO_VP_INT_STATUS_CMD_RSP_CRC)) {
42375 + cmd->error = -EILSEQ;
42376 + } else if (int_status & SDTIO_VP_INT_STATUS_CMD_RSP_TIMEOUT) {
42377 + cmd->error = -ETIMEDOUT;
42379 + } else if (cmd->flags & MMC_RSP_136) {
42380 + cmd->resp[0] = ud->regs->cmd_rsp0;
42381 + cmd->resp[1] = ud->regs->cmd_rsp1;
42382 + cmd->resp[2] = ud->regs->cmd_rsp2;
42383 + cmd->resp[3] = ud->regs->cmd_rsp3;
42385 + cmd->resp[0] = ud->regs->cmd_rsp0;
42387 + sd_printk("%s:\t\t\tResponse %08x %08x %08x %08x err=%d\n", mmc_hostname(mmc), cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3], cmd->error);
42391 + struct mmc_data *data = mrq->data;
42393 + if (int_status & SDTIO_VP_INT_STATUS_DATA_TIMEOUT) {
42394 + data->error = -ETIMEDOUT;
42395 + sd_printk("%s:\t\t\tData Timeout\n", mmc_hostname(mmc));
42397 + } else if (int_status & SDTIO_VP_INT_STATUS_DATA_CRC_ERR) {
42398 + data->error = -EILSEQ;
42399 + sd_printk("%s:\t\t\tData CRC\n", mmc_hostname(mmc));
42401 + } else if (int_status & SDTIO_VP_INT_STATUS_DATA_PROG_ERR) {
42402 + data->error = -EILSEQ;
42403 + sd_printk("%s:\t\t\tData Program Error\n", mmc_hostname(mmc));
42407 + data->bytes_xfered = ud->regs->data_bytes_transferred;
42411 + if (mrq->stop && (mrq->stop->flags & MMC_RSP_PRESENT)) {
42412 + struct mmc_command *stop = mrq->stop;
42415 + if ((stop->flags & MMC_RSP_CRC) && (int_status & SDTIO_VP_INT_STATUS_STOP_RSP_CRC)) {
42416 + stop->error = -EILSEQ;
42417 + } else if (int_status & SDTIO_VP_INT_STATUS_STOP_RSP_TIMEOUT) {
42418 + stop->error = -ETIMEDOUT;
42420 + } else if (stop->flags & MMC_RSP_136) {
42421 + stop->resp[0] = ud->regs->stop_rsp0;
42422 + stop->resp[1] = ud->regs->stop_rsp1;
42423 + stop->resp[2] = ud->regs->stop_rsp2;
42424 + stop->resp[3] = ud->regs->stop_rsp3;
42426 + stop->resp[0] = ud->regs->stop_rsp0;
42428 + sd_printk("%s:\t\t\tStop Response %08x %08x %08x %08x err=%d\n", mmc_hostname(mmc), stop->resp[0], stop->resp[1], stop->resp[2], stop->resp[3], stop->error);
42432 + mmc_request_done(mmc, mrq);
42434 + return IRQ_HANDLED;
42437 +static struct mmc_host_ops ubicom32sd_ops = {
42438 + .request = ubicom32sd_mmc_request,
42439 + .set_ios = ubicom32sd_mmc_set_ios,
42440 + .get_ro = ubicom32sd_mmc_get_ro,
42441 + .get_cd = ubicom32sd_mmc_get_cd,
42442 + .enable_sdio_irq = ubicom32sd_mmc_enable_sdio_irq,
42446 + * ubicom32sd_probe
42448 +static int __devinit ubicom32sd_probe(struct platform_device *pdev)
42450 + struct ubicom32sd_platform_data *pdata = (struct ubicom32sd_platform_data *)pdev->dev.platform_data;
42451 + struct mmc_host *mmc;
42452 + struct ubicom32sd_data *ud;
42453 + struct resource *res_regs;
42454 + struct resource *res_irq_tx;
42455 + struct resource *res_irq_rx;
42459 + * Get our resources, regs is the hardware driver base address
42460 + * and the tx and rx irqs are used to communicate with the
42461 + * hardware driver.
42463 + res_regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
42464 + res_irq_tx = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
42465 + res_irq_rx = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
42466 + if (!res_regs || !res_irq_tx || !res_irq_rx) {
42472 + * Reserve any gpios we need
42474 + ret = gpio_request(pdata->cards[0].pin_wp, "sd-wp");
42478 + gpio_direction_input(pdata->cards[0].pin_wp);
42480 + ret = gpio_request(pdata->cards[0].pin_cd, "sd-cd");
42484 + gpio_direction_input(pdata->cards[0].pin_cd);
42487 + * HACK: for the dual port controller on port F, we don't support the second port right now
42489 + if (pdata->ncards > 1) {
42490 + ret = gpio_request(pdata->cards[1].pin_pwr, "sd-pwr");
42491 + gpio_direction_output(pdata->cards[1].pin_pwr, !pdata->cards[1].pwr_polarity);
42492 + gpio_direction_output(pdata->cards[1].pin_pwr, pdata->cards[1].pwr_polarity);
42495 + ret = gpio_request(pdata->cards[0].pin_pwr, "sd-pwr");
42499 + gpio_direction_output(pdata->cards[0].pin_pwr, !pdata->cards[0].pwr_polarity);
42502 + * Allocate the MMC driver, it includes memory for our data.
42504 + mmc = mmc_alloc_host(sizeof(struct ubicom32sd_data), &pdev->dev);
42509 + ud = (struct ubicom32sd_data *)mmc_priv(mmc);
42511 + ud->pdata = pdata;
42512 + ud->regs = (struct sdtio_vp_regs *)res_regs->start;
42513 + ud->irq_tx = res_irq_tx->start;
42514 + ud->irq_rx = res_irq_rx->start;
42515 + platform_set_drvdata(pdev, mmc);
42517 + ret = request_irq(ud->irq_rx, ubicom32sd_interrupt, IRQF_DISABLED, mmc_hostname(mmc), mmc);
42523 + * Fill in the mmc structure
42525 + mmc->ops = &ubicom32sd_ops;
42526 + mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_NEEDS_POLL | MMC_CAP_SDIO_IRQ |
42527 + MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED;
42529 + mmc->f_min = ud->regs->f_min;
42530 + mmc->f_max = ud->regs->f_max;
42531 + mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
42534 + * Setup some restrictions on transfers
42536 + * We allow up to SDTIO_MAX_SG_BLOCKS of data to DMA into, there are
42537 + * not really any "max_seg_size", "max_req_size", or "max_blk_count"
42538 + * restrictions (must be less than U32_MAX though), pick
42539 + * something large?!...
42541 + * The hardware can do up to 4095 bytes per block, since the spec
42542 + * only requires 2048, we'll set it to that and not worry about
42543 + * potential weird blk lengths.
42545 + mmc->max_hw_segs = SDTIO_MAX_SG_BLOCKS;
42546 + mmc->max_phys_segs = SDTIO_MAX_SG_BLOCKS;
42547 + mmc->max_seg_size = 1024 * 1024;
42548 + mmc->max_req_size = 1024 * 1024;
42549 + mmc->max_blk_count = 1024;
42551 + mmc->max_blk_size = 2048;
42553 + ubicom32sd_reset(ud);
42556 + * enable interrupts
42559 + ubicom32sd_send_command_sync(ud, SDTIO_COMMAND_SETUP_SDIO << SDTIO_COMMAND_SHIFT | SDTIO_COMMAND_FLAG_SDIO_INT_EN, 0);
42561 + mmc_add_host(mmc);
42563 + printk(KERN_INFO "%s at %p, irq %d/%d\n", mmc_hostname(mmc),
42564 + ud->regs, ud->irq_tx, ud->irq_rx);
42568 + gpio_free(pdata->cards[0].pin_pwr);
42570 + gpio_free(pdata->cards[0].pin_cd);
42572 + gpio_free(pdata->cards[0].pin_wp);
42578 + * ubicom32sd_remove
42580 +static int __devexit ubicom32sd_remove(struct platform_device *pdev)
42582 + struct mmc_host *mmc = platform_get_drvdata(pdev);
42584 + platform_set_drvdata(pdev, NULL);
42587 + struct ubicom32sd_data *ud = (struct ubicom32sd_data *)mmc_priv(mmc);
42589 + gpio_free(ud->pdata->cards[0].pin_pwr);
42590 + gpio_free(ud->pdata->cards[0].pin_cd);
42591 + gpio_free(ud->pdata->cards[0].pin_wp);
42593 + mmc_remove_host(mmc);
42594 + mmc_free_host(mmc);
42598 + * Note that our data is allocated as part of the mmc structure
42599 + * so we don't need to free it.
42604 +static struct platform_driver ubicom32sd_driver = {
42606 + .name = DRIVER_NAME,
42607 + .owner = THIS_MODULE,
42609 + .probe = ubicom32sd_probe,
42610 + .remove = __devexit_p(ubicom32sd_remove),
42612 + .suspend = ubicom32sd_suspend,
42613 + .resume = ubicom32sd_resume,
42618 + * ubicom32sd_init
42620 +static int __init ubicom32sd_init(void)
42622 + return platform_driver_register(&ubicom32sd_driver);
42624 +module_init(ubicom32sd_init);
42627 + * ubicom32sd_exit
42629 +static void __exit ubicom32sd_exit(void)
42631 + platform_driver_unregister(&ubicom32sd_driver);
42633 +module_exit(ubicom32sd_exit);
42635 +MODULE_AUTHOR("Patrick Tjin");
42636 +MODULE_DESCRIPTION("Ubicom32 Secure Digital Host Controller Interface driver");
42637 +MODULE_LICENSE("GPL");
42638 diff -ruN linux-2.6.30.10/drivers/mtd/devices/Kconfig linux-2.6.30.10-ubi/drivers/mtd/devices/Kconfig
42639 --- linux-2.6.30.10/drivers/mtd/devices/Kconfig 2009-12-04 08:00:07.000000000 +0200
42640 +++ linux-2.6.30.10-ubi/drivers/mtd/devices/Kconfig 2009-12-11 11:45:16.000000000 +0200
42641 @@ -104,6 +104,31 @@
42643 This option enables FAST_READ access supported by ST M25Pxx.
42645 +config MTD_UBI32_NAND_SPI_ER
42646 + tristate "UBI32_NAND SPI-ER support"
42648 + This driver supports the Micron MT29F1G01 SPI-ER NAND flash chip
42649 + using the built in flash controller on the Ubicom32 architecture.
42650 + Partial page writes are not supported by this driver.
42652 +config MTD_NAND_SPI_ER
42653 + tristate "NAND SPI-ER support"
42655 + This driver supports the Micron MT29F1G01 SPI-ER NAND flash chip
42656 + using a generic SPI bus. Partial page writes are supported
42659 +config MTD_UBI32_M25P80
42660 + tristate "Ubicom processor support for most SPI Flash chips (AT26DF, M25P, W25X, ...)"
42661 + depends on UBICOM32
42664 + This enables access to most modern SPI flash chips, used for
42665 + program and data storage. Series supported include Atmel AT26DF,
42666 + Spansion S25SL, SST 25VF, ST M25P, and Winbond W25X. Other chips
42667 + are supported as well. See the driver source for the current list,
42668 + or to add other chips.
42671 tristate "Uncached system RAM"
42673 diff -ruN linux-2.6.30.10/drivers/mtd/devices/Makefile linux-2.6.30.10-ubi/drivers/mtd/devices/Makefile
42674 --- linux-2.6.30.10/drivers/mtd/devices/Makefile 2009-12-04 08:00:07.000000000 +0200
42675 +++ linux-2.6.30.10-ubi/drivers/mtd/devices/Makefile 2009-12-11 11:45:16.000000000 +0200
42677 obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o
42678 obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o
42679 obj-$(CONFIG_MTD_M25P80) += m25p80.o
42680 +obj-$(CONFIG_MTD_UBI32_M25P80) += ubi32-m25p80.o
42681 +obj-$(CONFIG_MTD_NAND_SPI_ER) += nand-spi-er.o
42682 +obj-$(CONFIG_MTD_UBI32_NAND_SPI_ER) += ubi32-nand-spi-er.o
42683 diff -ruN linux-2.6.30.10/drivers/mtd/devices/nand-spi-er.c linux-2.6.30.10-ubi/drivers/mtd/devices/nand-spi-er.c
42684 --- linux-2.6.30.10/drivers/mtd/devices/nand-spi-er.c 1970-01-01 02:00:00.000000000 +0200
42685 +++ linux-2.6.30.10-ubi/drivers/mtd/devices/nand-spi-er.c 2009-12-11 11:45:16.000000000 +0200
42688 + * Micron SPI-ER NAND Flash Memory
42690 + * (C) Copyright 2009, Ubicom, Inc.
42692 + * This file is part of the Ubicom32 Linux Kernel Port.
42694 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
42695 + * it and/or modify it under the terms of the GNU General Public License
42696 + * as published by the Free Software Foundation, either version 2 of the
42697 + * License, or (at your option) any later version.
42699 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
42700 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
42701 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
42702 + * the GNU General Public License for more details.
42704 + * You should have received a copy of the GNU General Public License
42705 + * along with the Ubicom32 Linux Kernel Port. If not,
42706 + * see <http://www.gnu.org/licenses/>.
42708 +#include <linux/module.h>
42709 +#include <linux/init.h>
42710 +#include <linux/slab.h>
42711 +#include <linux/delay.h>
42712 +#include <linux/device.h>
42713 +#include <linux/mutex.h>
42714 +#include <linux/err.h>
42716 +#include <linux/spi/spi.h>
42717 +#include <linux/spi/flash.h>
42719 +#include <linux/mtd/mtd.h>
42720 +#include <linux/mtd/partitions.h>
42722 +#define NAND_SPI_ER_BLOCK_FROM_ROW(row) (row >> 6)
42724 +#define NAND_SPI_ER_STATUS_P_FAIL (1 << 3)
42725 +#define NAND_SPI_ER_STATUS_E_FAIL (1 << 2)
42726 +#define NAND_SPI_ER_STATUS_OIP (1 << 0)
42728 +#define NAND_SPI_ER_LAST_ROW_INVALID 0xFFFFFFFF
42729 +#define NAND_SPI_ER_BAD_BLOCK_MARK_OFFSET 0x08
42731 +struct nand_spi_er_device {
42732 + const char *name;
42737 + unsigned int blocks;
42738 + unsigned int pages_per_block;
42739 + unsigned int page_size;
42740 + unsigned int write_size;
42741 + unsigned int erase_size;
42744 +struct nand_spi_er {
42747 + const struct nand_spi_er_device *device;
42749 + struct mutex lock;
42750 + struct spi_device *spi;
42752 + struct mtd_info mtd;
42754 + unsigned int last_row; /* the last row we fetched */
42757 + * Bad block table (MUST be last in strcuture)
42759 + unsigned long nbb;
42760 + unsigned long bbt[0];
42763 +const struct nand_spi_er_device nand_spi_er_devices[] = {
42765 + name: "MT29F1G01ZDC",
42769 + pages_per_block: 64,
42772 + erase_size: 64 * 2048,
42775 + name: "MT29F1G01ZDC",
42779 + pages_per_block: 64,
42782 + erase_size: 64 * 2048,
42786 +static int read_only = 0;
42787 +module_param(read_only, int, 0);
42788 +MODULE_PARM_DESC(read_only, "Leave device locked");
42791 + * nand_spi_er_get_feature
42792 + * Get Feature register
42794 +static int nand_spi_er_get_feature(struct nand_spi_er *chip, int reg, uint8_t *data)
42796 + uint8_t txbuf[2];
42797 + uint8_t rxbuf[1];
42802 + res = spi_write_then_read(chip->spi, txbuf, 2, rxbuf, 1);
42804 + DEBUG(MTD_DEBUG_LEVEL1, "%s: failed get feature res=%d\n", chip->name, res);
42807 + *data = rxbuf[0];
42812 + * nand_spi_er_busywait
42813 + * Wait until the chip is not busy
42815 +static int nand_spi_er_busywait(struct nand_spi_er *chip, uint8_t *data)
42819 + for (i = 0; i < 100; i++) {
42820 + int res = nand_spi_er_get_feature(chip, 0xC0, data);
42824 + if (!(*data & NAND_SPI_ER_STATUS_OIP)) {
42833 + * nand_spi_er_erase
42834 + * Erase a block, parameters must be block aligned
42836 +static int nand_spi_er_erase(struct mtd_info *mtd, struct erase_info *instr)
42838 + struct nand_spi_er *chip = mtd->priv;
42839 + struct spi_device *spi = chip->spi;
42840 + uint8_t txbuf[4];
42843 + DEBUG(MTD_DEBUG_LEVEL3, "%s: erase addr:%x len:%x\n", chip->name, instr->addr, instr->len);
42845 + if ((instr->addr + instr->len) > mtd->size) {
42849 + if (instr->addr & (chip->device->erase_size - 1)) {
42850 + DEBUG(MTD_DEBUG_LEVEL1, "%s: erase address is not aligned %x\n", chip->name, instr->addr);
42854 + if (instr->len & (chip->device->erase_size - 1)) {
42855 + DEBUG(MTD_DEBUG_LEVEL1, "%s: erase len is not aligned %x\n", chip->name, instr->len);
42859 + mutex_lock(&chip->lock);
42860 + chip->last_row = NAND_SPI_ER_LAST_ROW_INVALID;
42862 + while (instr->len) {
42863 + uint32_t block = instr->addr >> 17;
42864 + uint32_t row = block << 6;
42866 + DEBUG(MTD_DEBUG_LEVEL3, "%s: block erase row:%x block:%x addr:%x rem:%x\n", chip->name, row, block, instr->addr, instr->len);
42872 + res = spi_write(spi, txbuf, 1);
42874 + DEBUG(MTD_DEBUG_LEVEL1, "%s: failed write enable res=%d\n", chip->name, res);
42875 + mutex_unlock(&chip->lock);
42880 + * Test for bad block
42882 + if (test_bit(block, chip->bbt)) {
42883 + instr->fail_addr = block << 17;
42884 + instr->state = MTD_ERASE_FAILED;
42894 + txbuf[2] = row >> 8;
42895 + txbuf[3] = row & 0xFF;
42896 + res = spi_write(spi, txbuf, 4);
42898 + DEBUG(MTD_DEBUG_LEVEL1, "%s: failed block erase res=%d\n", chip->name, res);
42899 + instr->fail_addr = block << 17;
42900 + instr->state = MTD_ERASE_FAILED;
42907 + res = nand_spi_er_busywait(chip, &stat);
42908 + if (res || (stat & NAND_SPI_ER_STATUS_OIP)) {
42909 + instr->fail_addr = block << 17;
42910 + instr->state = MTD_ERASE_FAILED;
42911 + DEBUG(MTD_DEBUG_LEVEL1, "%s: chip is busy or nonresponsive res=%d stat=%02x\n", chip->name, res, stat);
42924 + * Check the status register
42926 + if (stat & NAND_SPI_ER_STATUS_E_FAIL) {
42927 + DEBUG(MTD_DEBUG_LEVEL1, "%s: E_FAIL signalled (%02x)\n", chip->name, stat);
42928 + instr->fail_addr = block << 17;
42929 + instr->state = MTD_ERASE_FAILED;
42937 + instr->len -= chip->device->erase_size;
42938 + instr->addr += chip->device->erase_size;
42941 + instr->state = MTD_ERASE_DONE;
42943 + mutex_unlock(&chip->lock);
42951 + res = spi_write(spi, txbuf, 1);
42953 + DEBUG(MTD_DEBUG_LEVEL1, "%s: failed write disable res=%d\n", chip->name, res);
42956 + mutex_unlock(&chip->lock);
42958 + mtd_erase_callback(instr);
42963 + * nand_spi_er_read
42965 + * return -EUCLEAN: ecc error recovered
42966 + * return -EBADMSG: ecc error not recovered
42968 +static int nand_spi_er_read(struct mtd_info *mtd, loff_t from, size_t len,
42969 + size_t *retlen, u_char *buf)
42971 + struct nand_spi_er *chip = mtd->priv;
42972 + struct spi_device *spi = chip->spi;
42979 + DEBUG(MTD_DEBUG_LEVEL2, "%s: read block from %llx len %d into %p\n", chip->name, from, len, buf);
42982 + * Zero length reads, nothing to do
42989 + * Reject reads which go over the end of the flash
42991 + if ((from + len) > mtd->size) {
42996 + * Get the row and column address to start at
42998 + row = from >> 11;
42999 + column = from & 0x7FF;
43000 + DEBUG(MTD_DEBUG_LEVEL3, "%s: row=%x %d column=%x %d last_row=%x %d\n", chip->name, row, row, column, column, chip->last_row, chip->last_row);
43003 + * Read the data from the chip
43005 + mutex_lock(&chip->lock);
43008 + uint8_t txbuf[4];
43009 + struct spi_message message;
43010 + struct spi_transfer x[2];
43015 + * Figure out how much to read
43017 + * If we are reading from the middle of a page then the most we
43018 + * can read is to the end of the page
43021 + if (toread > (chip->device->page_size - column)) {
43022 + toread = chip->device->page_size - column;
43025 + DEBUG(MTD_DEBUG_LEVEL3, "%s: buf=%p toread=%x row=%x column=%x last_row=%x\n", chip->name, buf, toread, row, column, chip->last_row);
43027 + if (chip->last_row != row) {
43029 + * Check if the block is bad
43031 + if (test_bit(NAND_SPI_ER_BLOCK_FROM_ROW(row), chip->bbt)) {
43032 + mutex_unlock(&chip->lock);
43037 + * Load the appropriate page
43041 + txbuf[2] = row >> 8;
43042 + txbuf[3] = row & 0xFF;
43043 + res = spi_write(spi, txbuf, 4);
43045 + DEBUG(MTD_DEBUG_LEVEL1, "%s: failed page load res=%d\n", chip->name, res);
43046 + mutex_unlock(&chip->lock);
43053 + res = nand_spi_er_busywait(chip, &stat);
43054 + if (res || (stat & NAND_SPI_ER_STATUS_OIP)) {
43055 + DEBUG(MTD_DEBUG_LEVEL1, "%s: chip is busy or nonresponsive res=%d stat=%02x\n", chip->name, res, stat);
43057 + mutex_unlock(&chip->lock);
43064 + mutex_unlock(&chip->lock);
43069 + * Check the ECC bits
43073 + DEBUG(MTD_DEBUG_LEVEL1, "%s: ECC recovered, row=%x\n", chip->name, row);
43074 + retval = -EUCLEAN;
43077 + DEBUG(MTD_DEBUG_LEVEL0, "%s: failed ECC, row=%x\n", chip->name, row);
43078 + chip->last_row = NAND_SPI_ER_LAST_ROW_INVALID;
43079 + mutex_unlock(&chip->lock);
43085 + chip->last_row = row;
43088 + * Read out the data
43090 + spi_message_init(&message);
43091 + memset(x, 0, sizeof(x));
43094 + txbuf[1] = column >> 8;
43095 + txbuf[2] = column & 0xFF;
43097 + x[0].tx_buf = txbuf;
43099 + spi_message_add_tail(&x[0], &message);
43101 + x[1].rx_buf = buf;
43102 + x[1].len = toread;
43103 + spi_message_add_tail(&x[1], &message);
43105 + res = spi_sync(spi, &message);
43107 + DEBUG(MTD_DEBUG_LEVEL1, "%s: failed data read res=%d\n", chip->name, res);
43108 + mutex_unlock(&chip->lock);
43113 + *retlen += toread;
43116 + * For the next page, increment the row and always start at column 0
43122 + mutex_unlock(&chip->lock);
43127 + * nand_spi_er_write
43129 +#define NOT_ALIGNED(x) ((x & (device->write_size - 1)) != 0)
43130 +static int nand_spi_er_write(struct mtd_info *mtd, loff_t to, size_t len,
43131 + size_t *retlen, const u_char *buf)
43133 + struct nand_spi_er *chip = mtd->priv;
43134 + struct spi_device *spi = chip->spi;
43135 + const struct nand_spi_er_device *device = chip->device;
43138 + uint8_t txbuf[4];
43142 + DEBUG(MTD_DEBUG_LEVEL2, "%s: write block to %llx len %d from %p\n", chip->name, to, len, buf);
43147 + * nothing to write
43154 + * Reject writes which go over the end of the flash
43156 + if ((to + len) > mtd->size) {
43161 + * Check to see if everything is page aligned
43163 + if (NOT_ALIGNED(to) || NOT_ALIGNED(len)) {
43164 + printk(KERN_NOTICE "nand_spi_er_write: Attempt to write non page aligned data\n");
43168 + mutex_lock(&chip->lock);
43169 + chip->last_row = NAND_SPI_ER_LAST_ROW_INVALID;
43172 + * If the first write is a partial write then write at most the number of
43173 + * bytes to get us page aligned and then the remainder will be
43174 + * page aligned. The last bit may be a partial page as well.
43176 + col = to & (device->page_size - 1);
43177 + towrite = device->page_size - col;
43178 + if (towrite > len) {
43187 + struct spi_message message;
43188 + struct spi_transfer x[2];
43191 + DEBUG(MTD_DEBUG_LEVEL3, "%s: write %p to row:%x col:%x len:%x rem:%x\n", chip->name, buf, row, col, towrite, len);
43197 + res = spi_write(spi, txbuf, 1);
43199 + DEBUG(MTD_DEBUG_LEVEL1, "%s: failed write enable res=%d\n", chip->name, res);
43200 + mutex_unlock(&chip->lock);
43205 + * Write the data into the cache
43207 + spi_message_init(&message);
43208 + memset(x, 0, sizeof(x));
43210 + txbuf[1] = col >> 8;
43211 + txbuf[2] = col & 0xFF;
43212 + x[0].tx_buf = txbuf;
43214 + spi_message_add_tail(&x[0], &message);
43215 + x[1].tx_buf = buf;
43216 + x[1].len = towrite;
43217 + spi_message_add_tail(&x[1], &message);
43218 + res = spi_sync(spi, &message);
43220 + DEBUG(MTD_DEBUG_LEVEL1, "%s: failed cache write res=%d\n", chip->name, res);
43225 + * Program execute
43229 + txbuf[2] = row >> 8;
43230 + txbuf[3] = row & 0xFF;
43231 + res = spi_write(spi, txbuf, 4);
43233 + DEBUG(MTD_DEBUG_LEVEL1, "%s: failed prog execute res=%d\n", chip->name, res);
43240 + res = nand_spi_er_busywait(chip, &stat);
43241 + if (res || (stat & NAND_SPI_ER_STATUS_OIP)) {
43242 + DEBUG(MTD_DEBUG_LEVEL1, "%s: chip is busy or nonresponsive res=%d stat=%02x\n", chip->name, res, stat);
43254 + if (stat & (1 << 3)) {
43262 + *retlen += towrite;
43265 + * At this point, we are always page aligned so start at column 0.
43266 + * Note we may not have a full page to write at the end, hence the
43267 + * check if towrite > len.
43270 + towrite = device->page_size;
43271 + if (towrite > len) {
43276 + mutex_unlock(&chip->lock);
43284 + res = spi_write(spi, txbuf, 1);
43286 + DEBUG(MTD_DEBUG_LEVEL1, "%s: failed write disable res=%d\n", chip->name, res);
43289 + mutex_unlock(&chip->lock);
43295 + * nand_spi_er_isbad
43297 +static int nand_spi_er_isbad(struct mtd_info *mtd, loff_t ofs)
43299 + struct nand_spi_er *chip = mtd->priv;
43302 + if (ofs & (chip->device->erase_size - 1)) {
43303 + DEBUG(MTD_DEBUG_LEVEL1, "%s: address not aligned %llx\n", chip->name, ofs);
43307 + block = ofs >> 17;
43309 + return test_bit(block, chip->bbt);
43313 + * nand_spi_er_markbad
43315 +static int nand_spi_er_markbad(struct mtd_info *mtd, loff_t ofs)
43317 + struct nand_spi_er *chip = mtd->priv;
43318 + struct spi_device *spi = chip->spi;
43321 + uint8_t txbuf[7];
43325 + if (ofs & (chip->device->erase_size - 1)) {
43326 + DEBUG(MTD_DEBUG_LEVEL1, "%s: address not aligned %llx\n", chip->name, ofs);
43330 + block = ofs >> 17;
43333 + * If it's already marked bad, no need to mark it
43335 + if (test_bit(block, chip->bbt)) {
43340 + * Mark it in our cache
43342 + __set_bit(block, chip->bbt);
43345 + * Write the user bad block mark. If it fails, then we really
43346 + * can't do anything about it.
43348 + mutex_lock(&chip->lock);
43349 + chip->last_row = NAND_SPI_ER_LAST_ROW_INVALID;
43355 + res = spi_write(spi, txbuf, 1);
43357 + DEBUG(MTD_DEBUG_LEVEL1, "%s: failed write enable res=%d\n", chip->name, res);
43358 + mutex_unlock(&chip->lock);
43367 + txbuf[2] = NAND_SPI_ER_BAD_BLOCK_MARK_OFFSET;
43372 + res = spi_write(spi, txbuf, 7);
43374 + DEBUG(MTD_DEBUG_LEVEL1, "%s: failed write mark res=%d\n", chip->name, res);
43379 + * Program execute
43384 + txbuf[2] = row >> 8;
43385 + txbuf[3] = row & 0xFF;
43386 + res = spi_write(spi, txbuf, 4);
43388 + DEBUG(MTD_DEBUG_LEVEL1, "%s: failed program execute res=%d\n", chip->name, res);
43395 + res = nand_spi_er_busywait(chip, &stat);
43396 + if (res || (stat & NAND_SPI_ER_STATUS_OIP)) {
43397 + DEBUG(MTD_DEBUG_LEVEL1, "%s: chip is busy or nonresponsive res=%d stat=%02x\n", chip->name, res, stat);
43409 + if (stat & (1 << 3)) {
43418 + res = spi_write(spi, txbuf, 1);
43420 + DEBUG(MTD_DEBUG_LEVEL1, "%s: failed write disable res=%d\n", chip->name, res);
43423 + mutex_unlock(&chip->lock);
43429 + * nand_spi_er_read_bbt
43431 +static int nand_spi_er_read_bbt(struct nand_spi_er *chip)
43434 + for (j = 0; j < chip->device->blocks; j++) {
43435 + uint8_t txbuf[4];
43436 + uint8_t rxbuf[16];
43439 + unsigned short row = j << 6;
43447 + txbuf[2] = row >> 8;
43448 + txbuf[3] = row & 0xFF;
43449 + res = spi_write(chip->spi, txbuf, 4);
43457 + res = nand_spi_er_busywait(chip, &stat);
43458 + if (res || (stat & NAND_SPI_ER_STATUS_OIP)) {
43459 + DEBUG(MTD_DEBUG_LEVEL1, "%s: chip is busy or nonresponsive res=%d stat=%02x\n", chip->name, res, stat);
43471 + * Check factory bad block mark
43477 + res = spi_write_then_read(chip->spi, txbuf, 4, rxbuf, 16);
43481 + if (rxbuf[0] != 0xFF) {
43483 + __set_bit(j, chip->bbt);
43487 + memcpy(&bbmark, &rxbuf[8], 4);
43488 + if (bbmark == 0xdeadbeef) {
43490 + __set_bit(j, chip->bbt);
43494 +#if defined(CONFIG_MTD_DEBUG) && (MTD_DEBUG_LEVEL3 <= CONFIG_MTD_DEBUG_VERBOSE)
43495 + printk("%s: Bad Block Table:", chip->name);
43496 + for (j = 0; j < chip->device->blocks; j++) {
43497 + if ((j % 64) == 0) {
43498 + printk("\n%s: block %03x: ", chip->name, j);
43500 + printk("%c", test_bit(j, chip->bbt) ? 'X' : '.');
43502 + printk("\n%s: Bad Block Numbers: ", chip->name);
43503 + for (j = 0; j < chip->device->blocks; j++) {
43504 + if (test_bit(j, chip->bbt)) {
43505 + printk("%x ", j);
43516 + * Called at boot time:
43518 + * nand_spi_er=read_only
43519 + * if read_only specified then do not unlock device
43521 +static int __init nand_spi_er_setup(char *str)
43523 + if (str && (strncasecmp(str, "read_only", 9) == 0)) {
43529 +__setup("nand_spi_er=", nand_spi_er_setup);
43533 + * nand_spi_er_probe
43534 + * Detect and initialize nand_spi_er device.
43536 +static int __devinit nand_spi_er_probe(struct spi_device *spi)
43538 + uint8_t txbuf[3];
43539 + uint8_t rxbuf[2];
43542 + size_t bbt_bytes;
43543 + struct nand_spi_er *chip;
43544 + const struct nand_spi_er_device *device;
43546 + res = spi_setup(spi);
43554 + for (i = 0; i < 2; i++) {
43556 + res = spi_write(spi, txbuf, 1);
43569 + res = spi_write_then_read(spi, txbuf, 2, rxbuf, 2);
43574 + device = nand_spi_er_devices;
43575 + for (i = 0; i < ARRAY_SIZE(nand_spi_er_devices); i++) {
43576 + if ((device->id0 == rxbuf[0]) && (device->id1 == rxbuf[1])) {
43581 + if (i == ARRAY_SIZE(nand_spi_er_devices)) {
43586 + * Initialize our chip structure
43588 + bbt_bytes = DIV_ROUND_UP(device->blocks, BITS_PER_BYTE);
43589 + chip = kzalloc(sizeof(struct nand_spi_er) + bbt_bytes, GFP_KERNEL);
43593 + snprintf(chip->name, sizeof(chip->name), "%s.%d.%d", device->name, spi->master->bus_num, spi->chip_select);
43596 + chip->device = device;
43597 + chip->last_row = NAND_SPI_ER_LAST_ROW_INVALID;
43599 + mutex_init(&chip->lock);
43601 + chip->mtd.type = MTD_NANDFLASH;
43602 + chip->mtd.flags = MTD_WRITEABLE;
43605 + * #blocks * block size * n blocks
43607 + chip->mtd.size = device->blocks * device->pages_per_block * device->page_size;
43608 + chip->mtd.erasesize = device->erase_size;
43611 + * 1 page, optionally we can support partial write (512)
43613 + chip->mtd.writesize = device->write_size;
43614 + chip->mtd.name = device->name;
43615 + chip->mtd.erase = nand_spi_er_erase;
43616 + chip->mtd.read = nand_spi_er_read;
43617 + chip->mtd.write = nand_spi_er_write;
43618 + chip->mtd.block_isbad = nand_spi_er_isbad;
43619 + chip->mtd.block_markbad = nand_spi_er_markbad;
43620 + chip->mtd.priv = chip;
43623 + * Cache the bad block table
43625 + res = nand_spi_er_read_bbt(chip);
43632 + * Un/lock the chip
43641 + res = spi_write(spi, txbuf, 3);
43643 + DEBUG(MTD_DEBUG_LEVEL1, "%s: failed lock operation res=%d\n", chip->name, res);
43644 + mutex_unlock(&chip->lock);
43648 + spi_set_drvdata(spi, chip);
43650 + printk(KERN_INFO "%s: added device %s size: %u KBytes %u bad blocks %s\n", spi->dev.bus_id, chip->mtd.name, DIV_ROUND_UP(chip->mtd.size, 1024), chip->nbb, read_only ? "[read only]" : "");
43651 + return add_mtd_device(&chip->mtd);
43655 + * nand_spi_er_remove
43657 +static int __devexit nand_spi_er_remove(struct spi_device *spi)
43659 + struct nand_spi_er *chip = spi_get_drvdata(spi);
43662 + DEBUG(MTD_DEBUG_LEVEL1, "%s: remove\n", spi->dev.bus_id);
43663 + status = del_mtd_device(&chip->mtd);
43669 +static struct spi_driver nand_spi_er_driver = {
43671 + .name = "nand-spi-er",
43672 + .bus = &spi_bus_type,
43673 + .owner = THIS_MODULE,
43676 + .probe = nand_spi_er_probe,
43677 + .remove = __devexit_p(nand_spi_er_remove),
43679 + /* FIXME: investigate suspend and resume... */
43683 + * nand_spi_er_init
43685 +static int __init nand_spi_er_init(void)
43687 + return spi_register_driver(&nand_spi_er_driver);
43689 +module_init(nand_spi_er_init);
43692 + * nand_spi_er_exit
43694 +static void __exit nand_spi_er_exit(void)
43696 + spi_unregister_driver(&nand_spi_er_driver);
43698 +module_exit(nand_spi_er_exit);
43701 +MODULE_LICENSE("GPL");
43702 +MODULE_AUTHOR("Patrick Tjin");
43703 +MODULE_DESCRIPTION("MTD nand_spi_er driver");
43704 diff -ruN linux-2.6.30.10/drivers/mtd/devices/ubi32-m25p80.c linux-2.6.30.10-ubi/drivers/mtd/devices/ubi32-m25p80.c
43705 --- linux-2.6.30.10/drivers/mtd/devices/ubi32-m25p80.c 1970-01-01 02:00:00.000000000 +0200
43706 +++ linux-2.6.30.10-ubi/drivers/mtd/devices/ubi32-m25p80.c 2009-12-11 11:45:16.000000000 +0200
43709 + * drivers/mtd/devices/ubi32-m25p80.c
43710 + * NOR flash driver, Ubicom processor internal SPI flash interface.
43712 + * This code instantiates the serial flash that contains the
43713 + * original bootcode. The serial flash start at address 0x60000000
43714 + * in both Ubicom32V3 and Ubicom32V4 ISAs.
43716 + * This piece of flash is made to appear as a Memory Technology
43717 + * Device (MTD) with this driver to allow Read/Write/Erase operations.
43719 + * (C) Copyright 2009, Ubicom, Inc.
43721 + * This file is part of the Ubicom32 Linux Kernel Port.
43723 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
43724 + * it and/or modify it under the terms of the GNU General Public License
43725 + * as published by the Free Software Foundation, either version 2 of the
43726 + * License, or (at your option) any later version.
43728 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
43729 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
43730 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
43731 + * the GNU General Public License for more details.
43733 + * You should have received a copy of the GNU General Public License
43734 + * along with the Ubicom32 Linux Kernel Port. If not,
43735 + * see <http://www.gnu.org/licenses/>.
43737 + * Ubicom32 implementation derived from (with many thanks):
43742 +#include <linux/types.h>
43743 +#include <linux/device.h>
43744 +#include <linux/platform_device.h>
43745 +#include <linux/mtd/mtd.h>
43746 +#include <linux/mtd/partitions.h>
43747 +#include <linux/mtd/physmap.h>
43748 +#include <linux/spi/spi.h>
43749 +#include <linux/spi/flash.h>
43751 +#include <linux/init.h>
43752 +#include <linux/module.h>
43753 +#include <linux/interrupt.h>
43754 +#include <linux/mutex.h>
43756 +#include <asm/ip5000.h>
43757 +#include <asm/devtree.h>
43759 +#define UBICOM32_FLASH_BASE 0x60000000
43760 +#define UBICOM32_FLASH_MAX_SIZE 0x01000000
43761 +#define UBICOM32_FLASH_START 0x00000000
43762 +#define UBICOM32_KERNEL_OFFSET 0x00010000 /* The kernel starts after Ubicom
43763 + * .protect section. */
43765 +static struct mtd_partition ubicom32_flash_partitions[] = {
43767 + .name = "Bootloader", /* Protected Section
43770 + .offset = UBICOM32_FLASH_START,
43771 +// .mask_flags = MTD_WRITEABLE /* Mark Read-only */
43774 + .name = "Kernel", /* Kernel Partition. */
43775 + .size = 0, /* this will be set up during
43776 + * probe stage. At that time we
43777 + * will know end of linux image
43779 + .offset = MTDPART_OFS_APPEND, /* Starts right after Protected
43781 +// .mask_flags = MTD_WRITEABLE /* Mark Read-only */
43784 + .name = "Rest", /* Rest of the flash. */
43785 + .size = 0x200000, /* Use up what remains in the
43787 + .offset = MTDPART_OFS_NXTBLK, /* Starts right after Protected
43792 +static struct flash_platform_data ubicom32_flash_data = {
43793 + .name = "ubicom32_boot_flash",
43794 + .parts = ubicom32_flash_partitions,
43795 + .nr_parts = ARRAY_SIZE(ubicom32_flash_partitions),
43798 +static struct resource ubicom32_flash_resource[] = {
43800 + .start = UBICOM32_FLASH_BASE,
43801 + .end = UBICOM32_FLASH_BASE +
43802 + UBICOM32_FLASH_MAX_SIZE - 1,
43803 + .flags = IORESOURCE_MEM,
43807 +static struct platform_device ubicom32_flash_device = {
43808 + .name = "ubicom32flashdriver",
43809 + .id = 0, /* Bus number */
43810 + .num_resources = ARRAY_SIZE(ubicom32_flash_resource),
43811 + .resource = ubicom32_flash_resource,
43813 + .platform_data = &ubicom32_flash_data,
43817 +static struct platform_device *ubicom32_flash_devices[] = {
43818 + &ubicom32_flash_device,
43821 +static int __init ubicom32_flash_init(void)
43823 + printk(KERN_INFO "%s(): registering device resources\n",
43825 + platform_add_devices(ubicom32_flash_devices,
43826 + ARRAY_SIZE(ubicom32_flash_devices));
43830 +arch_initcall(ubicom32_flash_init);
43833 + * MTD SPI driver for ST M25Pxx (and similar) serial flash chips through
43834 + * Ubicom32 SPI controller.
43836 + * Author: Mike Lavender, mike@steroidmicros.com
43838 + * Copyright (c) 2005, Intec Automation Inc.
43840 + * Some parts are based on lart.c by Abraham Van Der Merwe
43842 + * Cleaned up and generalized based on mtd_dataflash.c
43844 + * This code is free software; you can redistribute it and/or modify
43845 + * it under the terms of the GNU General Public License version 2 as
43846 + * published by the Free Software Foundation.
43850 +#define FLASH_PAGESIZE 256
43852 +/* Flash opcodes. */
43853 +#define OPCODE_WREN 0x06 /* Write enable */
43854 +#define OPCODE_RDSR 0x05 /* Read status register */
43855 +#define OPCODE_READ 0x03 /* Read data bytes (low frequency) */
43856 +#define OPCODE_FAST_READ 0x0b /* Read data bytes (high frequency) */
43857 +#define OPCODE_PP 0x02 /* Page program (up to 256 bytes) */
43858 +#define OPCODE_BE_4K 0x20 /* Erase 4KiB block */
43859 +#define OPCODE_BE_32K 0x52 /* Erase 32KiB block */
43860 +#define OPCODE_SE 0xd8 /* Sector erase (usually 64KiB) */
43861 +#define OPCODE_RDID 0x9f /* Read JEDEC ID */
43863 +/* Status Register bits. */
43864 +#define SR_WIP 1 /* Write in progress */
43865 +#define SR_WEL 2 /* Write enable latch */
43866 +/* meaning of other SR_* bits may differ between vendors */
43867 +#define SR_BP0 4 /* Block protect 0 */
43868 +#define SR_BP1 8 /* Block protect 1 */
43869 +#define SR_BP2 0x10 /* Block protect 2 */
43870 +#define SR_SRWD 0x80 /* SR write protect */
43872 +/* Define max times to check status register before we give up. */
43873 +#define MAX_READY_WAIT_COUNT 100000
43876 +#ifdef CONFIG_MTD_PARTITIONS
43877 +#define mtd_has_partitions() (1)
43879 +#define mtd_has_partitions() (0)
43883 + * Ubicom32 FLASH Command Set
43885 +#define FLASH_FC_INST_CMD 0x00 /* for SPI command only transaction */
43886 +#define FLASH_FC_INST_WR 0x01 /* for SPI write transaction */
43887 +#define FLASH_FC_INST_RD 0x02 /* for SPI read transaction */
43889 +#define ALIGN_DOWN(v, a) ((v) & ~((a) - 1))
43890 +#define ALIGN_UP(v, a) (((v) + ((a) - 1)) & ~((a) - 1))
43892 +#define FLASH_COMMAND_KICK_OFF(io) \
43894 + " bset "D(IO_INT_CLR)"(%0), #0, #%%bit("D(IO_XFL_INT_DONE)") \n\t" \
43895 + " jmpt.t .+4 \n\t" \
43896 + " bset "D(IO_INT_SET)"(%0), #0, #%%bit("D(IO_XFL_INT_START)") \n\t" \
43899 + : "memory", "cc" \
43902 +#define FLASH_COMMAND_WAIT_FOR_COMPLETION(io) \
43904 + " btst "D(IO_INT_STATUS)"(%0), #%%bit("D(IO_XFL_INT_DONE)") \n\t" \
43905 + " jmpeq.f .-4 \n\t" \
43908 + : "memory", "cc" \
43911 +#define FLASH_COMMAND_EXEC(io) \
43912 + FLASH_COMMAND_KICK_OFF(io) \
43913 + FLASH_COMMAND_WAIT_FOR_COMPLETION(io)
43916 +#define OSC1_FREQ 12000000
43917 +#define TEN_MICRO_SECONDS (OSC1_FREQ * 10 / 1000000)
43920 + * We will have to eventually replace this null definition with the real thing.
43922 +#define WATCHDOG_RESET()
43924 +#define EXTFLASH_WRITE_FIFO_SIZE 32
43925 +#define EXTFLASH_WRITE_BLOCK_SIZE EXTFLASH_WRITE_FIFO_SIZE /* limit the size to
43926 + * FIFO capacity, so
43927 + * the thread can be
43930 +#define JFFS2_FILESYSTEM_SIZE 0x100000
43932 +/****************************************************************************/
43935 + struct platform_device *plt_dev;
43936 + struct mutex lock;
43937 + struct mtd_info mtd;
43938 + unsigned partitioned:1;
43943 +static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd)
43945 + return container_of(mtd, struct m25p, mtd);
43948 +/****************************************************************************/
43951 + * Internal helper functions
43955 + * Read the status register, returning its value in the location
43956 + * Return the status register value.
43957 + * Returns negative if error occurred.
43959 +static int read_sr(struct m25p *flash)
43961 + struct ubicom32_io_port *io = (struct ubicom32_io_port *)RA;
43963 + io->ctl1 &= ~IO_XFL_CTL1_MASK;
43964 + io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_RD) |
43965 + IO_XFL_CTL1_FC_DATA(1);
43966 + io->ctl2 = IO_XFL_CTL2_FC_CMD(OPCODE_RDSR);
43967 + FLASH_COMMAND_EXEC(io);
43969 + return io->status1 & 0xff;
43973 + * mem_flash_io_read_u32()
43975 +static u32 mem_flash_io_read_u32(u32 addr)
43977 + struct ubicom32_io_port *io = (struct ubicom32_io_port *)RA;
43978 + io->ctl1 &= ~IO_XFL_CTL1_MASK;
43979 + io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_RD) |
43980 + IO_XFL_CTL1_FC_DATA(4) | IO_XFL_CTL1_FC_DUMMY(1) |
43981 + IO_XFL_CTL1_FC_ADDR;
43982 + io->ctl2 = IO_XFL_CTL2_FC_CMD(OPCODE_FAST_READ) |
43983 + IO_XFL_CTL2_FC_ADDR(addr);
43984 + FLASH_COMMAND_EXEC(io);
43985 + return io->status1;
43989 + * mem_flash_read_u8()
43991 +static u8 mem_flash_read_u8(u32 addr)
43993 + u32 tmp_addr = ALIGN_DOWN(addr, 4);
43994 + u32 tmp_data = mem_flash_io_read_u32(tmp_addr);
43995 + u8 *ptr = (u8 *)&tmp_data;
43996 + return ptr[addr & 0x3];
44000 + * mem_flash_read()
44001 + * No need to lock as read is implemented with ireads (same as normal flash
44004 +static void mem_flash_read(u32 addr, void *dst, size_t length)
44010 + * Fix source alignment.
44012 + while (addr & 0x03) {
44013 + if (length == 0) {
44016 + *((u8 *)dst) = mem_flash_read_u8(addr++);
44021 + while (length >= 4) {
44022 + u32 tmp_data = mem_flash_io_read_u32(addr);
44027 + * Send the data to the destination.
44029 + memcpy((void *)dst, (void *)&tmp_data, 4);
44033 + while (length--) {
44034 + *((u8 *)dst) = mem_flash_read_u8(addr++);
44040 + * mem_flash_wait_until_complete()
44042 +static void mem_flash_wait_until_complete(void)
44044 + struct ubicom32_io_port *io = (struct ubicom32_io_port *)RA;
44048 + * Put a delay here to deal with flash programming problem.
44050 + u32 mptval = UBICOM32_IO_TIMER->mptval + TEN_MICRO_SECONDS;
44051 + while (UBICOM32_IO_TIMER->mptval < mptval)
44054 + io->ctl1 &= ~IO_XFL_CTL1_MASK;
44055 + io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_RD) |
44056 + IO_XFL_CTL1_FC_DATA(1);
44057 + io->ctl2 = IO_XFL_CTL2_FC_CMD(OPCODE_RDSR);
44058 + FLASH_COMMAND_EXEC(io);
44059 + } while (io->status1 & SR_WIP);
44063 + * mem_flash_write_next()
44065 +static size_t mem_flash_write_next(u32 addr, u8 *buf, size_t length)
44067 + struct ubicom32_io_port *io = (struct ubicom32_io_port *)RA;
44068 + u32 data_start = addr;
44069 + u32 data_end = addr + length;
44074 + * Top limit address.
44076 + u32 block_start = ALIGN_DOWN(data_start, 4);
44077 + u32 block_end = block_start + EXTFLASH_WRITE_BLOCK_SIZE;
44080 + u8 byte[EXTFLASH_WRITE_BLOCK_SIZE];
44081 + u32 word[EXTFLASH_WRITE_BLOCK_SIZE / 4];
44084 + u32 *flash_addr = (u32 *)block_start;
44087 + * The write block must be limited by FLASH internal buffer.
44089 + u32 block_end_align = ALIGN_DOWN(block_end, 256);
44090 + bool write_needed;
44092 + block_end = (block_end_align > block_start)
44093 + ? block_end_align : block_end;
44094 + data_end = (data_end <= block_end) ? data_end : block_end;
44095 + block_end = ALIGN_UP(data_end, 4);
44096 + count = data_end - data_start;
44099 + * Transfer data to a buffer.
44101 + for (i = 0; i < (block_end - block_start) / 4; i++) {
44103 + * The FLASH read can hold D-cache for a long time.
44104 + * Use I/O operation to read FLASH to avoid starving other
44105 + * threads, especially HRT. (Do this for application only)
44107 + write_buf.word[i] = mem_flash_io_read_u32(
44108 + (u32)(&flash_addr[i]));
44111 + write_needed = false;
44112 + for (i = 0, j = (data_start - block_start);
44113 + i < (data_end - data_start); i++, j++) {
44114 + write_needed = write_needed || (write_buf.byte[j] != buf[i]);
44115 + write_buf.byte[j] &= buf[i];
44120 + * If the data in FLASH is identical to what to be written. Then skip
44123 + if (write_needed) {
44125 + * Write to flash.
44127 + void *tmp __attribute__((unused));
44131 + " move.4 %0, %2 \n\t"
44132 + " bset "D(IO_INT_SET)"(%1), #0, #%%bit("D(IO_PORTX_INT_FIFO_TX_RESET)") \n\t"
44133 + " pipe_flush 0 \n\t"
44134 + " .rept "D(EXTFLASH_WRITE_FIFO_SIZE / 4)" \n\t"
44135 + " move.4 "D(IO_TX_FIFO)"(%1), (%0)4++ \n\t"
44138 + : "a" (io), "r" (&write_buf.word[0])
44142 + /* Lock FLASH for write access. */
44143 + io->ctl0 |= IO_XFL_CTL0_MCB_LOCK;
44145 + /* Command: WREN */
44146 + io->ctl1 &= ~IO_XFL_CTL1_MASK;
44147 + io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_CMD);
44148 + io->ctl2 = IO_XFL_CTL2_FC_CMD(OPCODE_WREN);
44149 + FLASH_COMMAND_EXEC(io);
44151 + /* Command: BYTE PROGRAM */
44152 + io->ctl1 &= ~IO_XFL_CTL1_MASK;
44153 + io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_WR) |
44154 + IO_XFL_CTL1_FC_DATA(block_end - block_start) |
44155 + IO_XFL_CTL1_FC_ADDR;
44156 + io->ctl2 = IO_XFL_CTL2_FC_CMD(OPCODE_PP) |
44157 + IO_XFL_CTL2_FC_ADDR(block_start);
44158 + FLASH_COMMAND_KICK_OFF(io);
44160 + extra_words = (s32)(block_end - block_start -
44161 + EXTFLASH_WRITE_FIFO_SIZE) / 4;
44162 + if (extra_words > 0) {
44164 + " move.4 %0, %3 \n\t"
44165 + "1: cmpi "D(IO_FIFO_LEVEL)"(%1), #4 \n\t"
44166 + " jmpgt.s.t 1b \n\t"
44167 + " move.4 "D(IO_TX_FIFO)"(%1), (%0)4++ \n\t"
44168 + " add.4 %2, #-1, %2 \n\t"
44169 + " jmpgt.t 1b \n\t"
44171 + : "a" (io), "d" (extra_words),
44172 + "r" (&write_buf.word[EXTFLASH_WRITE_FIFO_SIZE / 4])
44176 + FLASH_COMMAND_WAIT_FOR_COMPLETION(io);
44178 + mem_flash_wait_until_complete();
44181 + /* Unlock FLASH for cache access. */
44182 + io->ctl0 &= ~IO_XFL_CTL0_MCB_LOCK;
44192 + * mem_flash_write()
44194 +static void mem_flash_write(u32 addr, const void *src, size_t length)
44199 + u8_t *ptr = (u8_t *)src;
44201 + size_t count = mem_flash_write_next(addr, ptr, length);
44209 + * Service routine to read status register until ready, or timeout occurs.
44210 + * Returns non-zero if error.
44212 +static int wait_till_ready(struct m25p *flash)
44217 + /* one chip guarantees max 5 msec wait here after page writes,
44218 + * but potentially three seconds (!) after page erase.
44220 + for (count = 0; count < MAX_READY_WAIT_COUNT; count++) {
44222 + sr = read_sr(flash);
44225 + else if (!(sr & SR_WIP))
44229 + * Put a 10us delay here to deal with flash programming problem.
44231 + mptval = UBICOM32_IO_TIMER->mptval + TEN_MICRO_SECONDS;
44232 + while ((s32)(mptval - UBICOM32_IO_TIMER->mptval) > 0) {
44233 + WATCHDOG_RESET();
44235 + /* REVISIT sometimes sleeping would be best */
44242 + * mem_flash_erase_page()
44244 +static void mem_flash_erase_page(u32 addr)
44246 + struct ubicom32_io_port *io = (struct ubicom32_io_port *)RA;
44248 + /* Lock FLASH for write access. */
44249 + io->ctl0 |= IO_XFL_CTL0_MCB_LOCK;
44251 + /* Command: WREN */
44252 + io->ctl1 &= ~IO_XFL_CTL1_MASK;
44253 + io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_CMD);
44254 + io->ctl2 = IO_XFL_CTL2_FC_CMD(OPCODE_WREN);
44255 + FLASH_COMMAND_EXEC(io);
44257 + /* Command: ERASE */
44258 + io->ctl1 &= ~IO_XFL_CTL1_MASK;
44259 + io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_CMD) |
44260 + IO_XFL_CTL1_FC_ADDR;
44261 + io->ctl2 = IO_XFL_CTL2_FC_CMD(OPCODE_SE) |
44262 + IO_XFL_CTL2_FC_ADDR(addr);
44263 + FLASH_COMMAND_EXEC(io);
44265 + mem_flash_wait_until_complete();
44267 + /* Unlock FLASH for cache access. */
44268 + io->ctl0 &= ~IO_XFL_CTL0_MCB_LOCK;
44272 + * mem_flash_erase()
44274 +static u32 mem_flash_erase(u32 addr, u32 length)
44277 + * Calculate the endaddress to be the first address of the page
44278 + * just beyond this erase section of pages.
44280 + u32 endaddr = addr + length;
44285 + while (addr < endaddr) {
44286 + u32 test_addr = addr;
44287 + mem_flash_erase_page(addr);
44290 + * Test how much was erased as actual flash page at this address
44291 + * may be smaller than the expected page size.
44293 + while (test_addr < endaddr) {
44295 + * The FLASH read can hold D-cache for a long time. Use
44296 + * I/O operation to read FLASH to avoid starving other
44297 + * threads, especially HRT. (Do this for application
44300 + if (mem_flash_io_read_u32(test_addr) != 0xFFFFFFFF) {
44305 + if (test_addr == addr) {
44306 + printk("erase failed at address 0x%x, skipping",
44311 + addr = test_addr;
44317 +/****************************************************************************/
44320 + * MTD implementation
44324 + * Erase an address range on the flash chip. The address range may extend
44325 + * one or more erase sectors. Return an error is there is a problem erasing.
44327 +static int ubicom32_flash_driver_erase(struct mtd_info *mtd,
44328 + struct erase_info *instr)
44330 + struct m25p *flash = mtd_to_m25p(mtd);
44333 + DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %lld\n",
44334 + dev_name(&flash->plt_dev->dev), __FUNCTION__, "at",
44335 + (u32)instr->addr, instr->len);
44337 + /* sanity checks */
44338 + if (instr->addr + instr->len > flash->mtd.size)
44340 + if ((instr->addr % mtd->erasesize) != 0
44341 + || (instr->len % mtd->erasesize) != 0) {
44345 + addr = instr->addr + UBICOM32_FLASH_BASE;
44346 + len = instr->len;
44348 + mutex_lock(&flash->lock);
44350 + /* REVISIT in some cases we could speed up erasing large regions
44351 + * by using OPCODE_SE instead of OPCODE_BE_4K
44354 + /* now erase those sectors */
44355 + if (mem_flash_erase(addr, len)) {
44356 + instr->state = MTD_ERASE_FAILED;
44357 + mutex_unlock(&flash->lock);
44361 + mutex_unlock(&flash->lock);
44362 + instr->state = MTD_ERASE_DONE;
44363 + mtd_erase_callback(instr);
44368 + * Read an address range from the flash chip. The address range
44369 + * may be any size provided it is within the physical boundaries.
44371 +static int ubicom32_flash_driver_read(struct mtd_info *mtd, loff_t from,
44372 + size_t len, size_t *retlen, u_char *buf)
44374 + struct m25p *flash = mtd_to_m25p(mtd);
44375 + u32 base_addr = UBICOM32_FLASH_BASE + from;
44377 + DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %d\n",
44378 + dev_name(&flash->plt_dev->dev), __FUNCTION__, "from",
44381 + /* sanity checks */
44385 + if (from + len > flash->mtd.size)
44388 + /* Byte count starts at zero. */
44392 + mutex_lock(&flash->lock);
44394 + /* Wait till previous write/erase is done. */
44395 + if (wait_till_ready(flash)) {
44396 + /* REVISIT status return?? */
44397 + mutex_unlock(&flash->lock);
44401 + mem_flash_read(base_addr, (void *)buf, len);
44406 + mutex_unlock(&flash->lock);
44412 + * Write an address range to the flash chip. Data must be written in
44413 + * FLASH_PAGESIZE chunks. The address range may be any size provided
44414 + * it is within the physical boundaries.
44416 +static int ubicom32_flash_driver_write(struct mtd_info *mtd, loff_t to,
44417 + size_t len, size_t *retlen,
44418 + const u_char *buf)
44420 + struct m25p *flash = mtd_to_m25p(mtd);
44421 + u32 base_addr = UBICOM32_FLASH_BASE + to;
44422 + DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %d\n",
44423 + dev_name(&flash->plt_dev->dev), __FUNCTION__, "to",
44429 + /* sanity checks */
44433 + if (to + len > flash->mtd.size)
44436 + mutex_lock(&flash->lock);
44438 + mem_flash_write(base_addr, (void *) buf, len);
44440 + /* Wait until finished previous write command. */
44441 + if (wait_till_ready(flash)) {
44442 + mutex_unlock(&flash->lock);
44449 + mutex_unlock(&flash->lock);
44454 +/****************************************************************************/
44457 + * SPI device driver setup and teardown
44460 +struct flash_info {
44463 + /* JEDEC id zero means "no ID" (most older chips); otherwise it has
44464 + * a high byte of zero plus three data bytes: the manufacturer id,
44465 + * then a two byte device id.
44469 + /* The size listed here is what works with OPCODE_SE, which isn't
44470 + * necessarily called a "sector" by the vendor.
44472 + unsigned sector_size;
44476 +#define SECT_4K 0x01 /* OPCODE_BE_4K works uniformly */
44480 +/* NOTE: double check command sets and memory organization when you add
44481 + * more flash chips. This current list focusses on newer chips, which
44482 + * have been converging on command sets which including JEDEC ID.
44484 +static struct flash_info __devinitdata m25p_data[] = {
44486 + /* Atmel -- some are (confusingly) marketed as "DataFlash" */
44487 + { "at25fs010", 0x1f6601, 32 * 1024, 4, SECT_4K, },
44488 + { "at25fs040", 0x1f6604, 64 * 1024, 8, SECT_4K, },
44490 + { "at25df041a", 0x1f4401, 64 * 1024, 8, SECT_4K, },
44492 + { "at26f004", 0x1f0400, 64 * 1024, 8, SECT_4K, },
44493 + { "at26df081a", 0x1f4501, 64 * 1024, 16, SECT_4K, },
44494 + { "at26df161a", 0x1f4601, 64 * 1024, 32, SECT_4K, },
44495 + { "at26df321", 0x1f4701, 64 * 1024, 64, SECT_4K, },
44497 + /* Spansion -- single (large) sector size only, at least
44498 + * for the chips listed here (without boot sectors).
44500 + { "s25sl004a", 0x010212, 64 * 1024, 8, },
44501 + { "s25sl008a", 0x010213, 64 * 1024, 16, },
44502 + { "s25sl016a", 0x010214, 64 * 1024, 32, },
44503 + { "s25sl032a", 0x010215, 64 * 1024, 64, },
44504 + { "s25sl064a", 0x010216, 64 * 1024, 128, },
44506 + /* SST -- large erase sizes are "overlays", "sectors" are 4K */
44507 + { "sst25vf040b", 0xbf258d, 64 * 1024, 8, SECT_4K, },
44508 + { "sst25vf080b", 0xbf258e, 64 * 1024, 16, SECT_4K, },
44509 + { "sst25vf016b", 0xbf2541, 64 * 1024, 32, SECT_4K, },
44510 + { "sst25vf032b", 0xbf254a, 64 * 1024, 64, SECT_4K, },
44512 + /* ST Microelectronics -- newer production may have feature updates */
44513 + { "m25p05", 0x202010, 32 * 1024, 2, },
44514 + { "m25p10", 0x202011, 32 * 1024, 4, },
44515 + { "m25p20", 0x202012, 64 * 1024, 4, },
44516 + { "m25p40", 0x202013, 64 * 1024, 8, },
44517 + { "m25p80", 0, 64 * 1024, 16, },
44518 + { "m25p16", 0x202015, 64 * 1024, 32, },
44519 + { "m25p32", 0x202016, 64 * 1024, 64, },
44520 + { "m25p64", 0x202017, 64 * 1024, 128, },
44521 + { "m25p128", 0x202018, 256 * 1024, 64, },
44523 + { "m45pe80", 0x204014, 64 * 1024, 16, },
44524 + { "m45pe16", 0x204015, 64 * 1024, 32, },
44526 + { "m25pe80", 0x208014, 64 * 1024, 16, },
44527 + { "m25pe16", 0x208015, 64 * 1024, 32, SECT_4K, },
44529 + /* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */
44530 + { "w25x10", 0xef3011, 64 * 1024, 2, SECT_4K, },
44531 + { "w25x20", 0xef3012, 64 * 1024, 4, SECT_4K, },
44532 + { "w25x40", 0xef3013, 64 * 1024, 8, SECT_4K, },
44533 + { "w25x80", 0xef3014, 64 * 1024, 16, SECT_4K, },
44534 + { "w25x16", 0xef3015, 64 * 1024, 32, SECT_4K, },
44535 + { "w25x32", 0xef3016, 64 * 1024, 64, SECT_4K, },
44536 + { "w25x64", 0xef3017, 64 * 1024, 128, SECT_4K, },
44538 + /* Macronix -- mx25lxxx */
44539 + { "mx25l32", 0xc22016, 64 * 1024, 64, },
44540 + { "mx25l64", 0xc22017, 64 * 1024, 128, },
44541 + { "mx25l128", 0xc22018, 64 * 1024, 256, },
44545 +struct flash_info *__devinit jedec_probe(struct platform_device *spi)
44549 + struct flash_info *info;
44550 + struct ubicom32_io_port *io = (struct ubicom32_io_port *)RA;
44553 + * Setup and run RDID command on the flash.
44555 + io->ctl1 &= ~IO_XFL_CTL1_MASK;
44556 + io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_RD) |
44557 + IO_XFL_CTL1_FC_DATA(3);
44558 + io->ctl2 = IO_XFL_CTL2_FC_CMD(OPCODE_RDID);
44559 + FLASH_COMMAND_EXEC(io);
44561 + jedec = io->status1 & 0x00ffffff;
44563 + for (tmp = 0, info = m25p_data;
44564 + tmp < ARRAY_SIZE(m25p_data);
44566 + if (info->jedec_id == jedec)
44569 + dev_err(&spi->dev, "unrecognized JEDEC id %06x\n", jedec);
44575 + * board specific setup should have ensured the SPI clock used here
44576 + * matches what the READ command supports, at least until this driver
44577 + * understands FAST_READ (for clocks over 25 MHz).
44579 +static int __devinit ubicom32_flash_probe(struct platform_device *spi)
44581 + struct flash_platform_data *data;
44582 + struct m25p *flash;
44583 + struct flash_info *info;
44586 + /* Platform data helps sort out which chip type we have, as
44587 + * well as how this board partitions it. If we don't have
44588 + * a chip ID, try the JEDEC id commands; they'll work for most
44589 + * newer chips, even if we don't recognize the particular chip.
44591 + data = spi->dev.platform_data;
44592 + if (data && data->type) {
44593 + for (i = 0, info = m25p_data;
44594 + i < ARRAY_SIZE(m25p_data);
44596 + if (strcmp(data->type, info->name) == 0)
44600 + /* unrecognized chip? */
44601 + if (i == ARRAY_SIZE(m25p_data)) {
44602 + DEBUG(MTD_DEBUG_LEVEL0, "%s: unrecognized id %s\n",
44603 + dev_name(&spi->dev), data->type);
44606 + /* recognized; is that chip really what's there? */
44607 + } else if (info->jedec_id) {
44608 + struct flash_info *chip = jedec_probe(spi);
44610 + if (!chip || chip != info) {
44611 + dev_warn(&spi->dev, "found %s, expected %s\n",
44612 + chip ? chip->name : "UNKNOWN",
44618 + info = jedec_probe(spi);
44623 + flash = kzalloc(sizeof *flash, GFP_KERNEL);
44627 + flash->plt_dev = spi;
44628 + mutex_init(&flash->lock);
44629 + dev_set_drvdata(&spi->dev, flash);
44631 + if (data && data->name)
44632 + flash->mtd.name = data->name;
44634 + flash->mtd.name = dev_name(&spi->dev);
44636 + flash->mtd.type = MTD_NORFLASH;
44637 + flash->mtd.writesize = 1;
44638 + flash->mtd.flags = MTD_CAP_NORFLASH;
44639 + flash->mtd.size = info->sector_size * info->n_sectors;
44640 + flash->mtd.erase = ubicom32_flash_driver_erase;
44641 + flash->mtd.read = ubicom32_flash_driver_read;
44642 + flash->mtd.write = ubicom32_flash_driver_write;
44644 + /* prefer "small sector" erase if possible */
44646 + * The Ubicom erase code does not use the opcode for smaller sectors,
44647 + * so disable that functionality and keep erasesize == sector_size
44648 + * so that the test in ubicom32_flash_driver_erase works properly.
44650 + * This was: `if (info->flags & SECT_4K) {' instead of `if (0) {'
44653 + flash->erase_opcode = OPCODE_BE_4K;
44654 + flash->mtd.erasesize = 4096;
44656 + flash->erase_opcode = OPCODE_SE;
44657 + flash->mtd.erasesize = info->sector_size;
44660 + dev_info(&spi->dev, "%s (%lld Kbytes)\n", info->name,
44661 + flash->mtd.size / 1024);
44663 + DEBUG(MTD_DEBUG_LEVEL2,
44664 + "mtd .name = %s, .size = 0x%.8llx (%lluMiB) "
44665 + ".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n",
44667 + flash->mtd.size, flash->mtd.size / (1024*1024),
44668 + flash->mtd.erasesize, flash->mtd.erasesize / 1024,
44669 + flash->mtd.numeraseregions);
44671 + if (flash->mtd.numeraseregions)
44672 + for (i = 0; i < flash->mtd.numeraseregions; i++)
44673 + DEBUG(MTD_DEBUG_LEVEL2,
44674 + "mtd.eraseregions[%d] = { .offset = 0x%.8llx, "
44675 + ".erasesize = 0x%.8x (%uKiB), "
44676 + ".numblocks = %d }\n",
44677 + i, flash->mtd.eraseregions[i].offset,
44678 + flash->mtd.eraseregions[i].erasesize,
44679 + flash->mtd.eraseregions[i].erasesize / 1024,
44680 + flash->mtd.eraseregions[i].numblocks);
44683 + /* partitions should match sector boundaries; and it may be good to
44684 + * use readonly partitions for writeprotected sectors (BP2..BP0).
44686 + if (mtd_has_partitions()) {
44687 + struct mtd_partition *parts = NULL;
44688 + int nr_parts = 0;
44690 +#ifdef CONFIG_MTD_CMDLINE_PARTS
44691 + static const char *part_probes[] = { "cmdlinepart", NULL, };
44693 + nr_parts = parse_mtd_partitions(&flash->mtd,
44694 + part_probes, &parts, 0);
44697 + if (nr_parts <= 0 && data && data->parts) {
44698 + parts = data->parts;
44699 + nr_parts = data->nr_parts;
44700 + if (nr_parts >= 2) {
44702 + * Set last partition size to be 1M.
44704 + parts[1].size = flash->mtd.size -
44705 + parts[0].size - JFFS2_FILESYSTEM_SIZE;
44706 + parts[2].size = JFFS2_FILESYSTEM_SIZE;
44710 + if (nr_parts > 0) {
44711 + for (i = 0; i < nr_parts; i++) {
44712 + DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = "
44713 + "{.name = %s, .offset = 0x%.8llx, "
44714 + ".size = 0x%.8llx (%lluKiB) }\n",
44715 + i, parts[i].name,
44718 + parts[i].size / 1024);
44720 + flash->partitioned = 1;
44721 + return add_mtd_partitions(&flash->mtd, parts, nr_parts);
44723 + } else if (data->nr_parts)
44724 + dev_warn(&spi->dev, "ignoring %d default partitions on %s\n",
44725 + data->nr_parts, data->name);
44727 + return add_mtd_device(&flash->mtd) == 1 ? -ENODEV : 0;
44731 +static int __devexit ubicom32_flash_remove(struct spi_device *spi)
44733 + struct m25p *flash = dev_get_drvdata(&spi->dev);
44736 + /* Clean up MTD stuff. */
44737 + if (mtd_has_partitions() && flash->partitioned)
44738 + status = del_mtd_partitions(&flash->mtd);
44740 + status = del_mtd_device(&flash->mtd);
44746 +static struct platform_driver ubicom32_flash_driver = {
44748 + .name = "ubicom32flashdriver",
44749 + .bus = &platform_bus_type,
44750 + .owner = THIS_MODULE,
44752 + .probe = ubicom32_flash_probe,
44756 +static int ubicom32_flash_driver_init(void)
44758 + return platform_driver_register(&ubicom32_flash_driver);
44762 +static void ubicom32_flash_driver_exit(void)
44764 + platform_driver_unregister(&ubicom32_flash_driver);
44768 +module_init(ubicom32_flash_driver_init);
44769 +module_exit(ubicom32_flash_driver_exit);
44771 +MODULE_LICENSE("GPL");
44772 +MODULE_AUTHOR("Mike Lavender");
44773 +MODULE_DESCRIPTION("Ubicom32 MTD SPI driver for ST M25Pxx flash chips");
44774 diff -ruN linux-2.6.30.10/drivers/mtd/devices/ubi32-nand-spi-er.c linux-2.6.30.10-ubi/drivers/mtd/devices/ubi32-nand-spi-er.c
44775 --- linux-2.6.30.10/drivers/mtd/devices/ubi32-nand-spi-er.c 1970-01-01 02:00:00.000000000 +0200
44776 +++ linux-2.6.30.10-ubi/drivers/mtd/devices/ubi32-nand-spi-er.c 2009-12-11 11:45:16.000000000 +0200
44779 + * Micron SPI-ER NAND Flash Memory
44780 + * This code uses the built in Ubicom flash controller
44782 + * (C) Copyright 2009, Ubicom, Inc.
44784 + * This file is part of the Ubicom32 Linux Kernel Port.
44786 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
44787 + * it and/or modify it under the terms of the GNU General Public License
44788 + * as published by the Free Software Foundation, either version 2 of the
44789 + * License, or (at your option) any later version.
44791 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
44792 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
44793 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
44794 + * the GNU General Public License for more details.
44796 + * You should have received a copy of the GNU General Public License
44797 + * along with the Ubicom32 Linux Kernel Port. If not,
44798 + * see <http://www.gnu.org/licenses/>.
44800 +#include <linux/module.h>
44801 +#include <linux/init.h>
44802 +#include <linux/slab.h>
44803 +#include <linux/delay.h>
44804 +#include <linux/device.h>
44805 +#include <linux/platform_device.h>
44806 +#include <linux/mutex.h>
44807 +#include <linux/err.h>
44809 +#include <linux/mtd/mtd.h>
44810 +#include <linux/mtd/partitions.h>
44812 +#define DRIVER_NAME "ubi32-nand-spi-er"
44813 +#define UBI32_NAND_SPI_ER_BLOCK_FROM_ROW(row) (row >> 6)
44815 +#define UBI32_NAND_SPI_ER_STATUS_P_FAIL (1 << 3)
44816 +#define UBI32_NAND_SPI_ER_STATUS_E_FAIL (1 << 2)
44817 +#define UBI32_NAND_SPI_ER_STATUS_OIP (1 << 0)
44819 +#define UBI32_NAND_SPI_ER_LAST_ROW_INVALID 0xFFFFFFFF
44820 +#define UBI32_NAND_SPI_ER_BAD_BLOCK_MARK_OFFSET 0x08
44822 +struct ubi32_nand_spi_er_device {
44823 + const char *name;
44827 + unsigned int blocks;
44828 + unsigned int pages_per_block;
44829 + unsigned int page_size;
44830 + unsigned int write_size;
44831 + unsigned int erase_size;
44834 +struct ubi32_nand_spi_er {
44837 + const struct ubi32_nand_spi_er_device *device;
44839 + struct mutex lock;
44840 + struct platform_device *pdev;
44842 + struct mtd_info mtd;
44844 + unsigned int last_row; /* the last row we fetched */
44847 + * Bad block table (MUST be last in strcuture)
44849 + unsigned long nbb;
44850 + unsigned long bbt[0];
44854 + * Chip supports a write_size of 512, but we cannot do partial
44855 + * page with command 0x84.
44857 + * We need to use command 0x84 because we cannot fill the FIFO fast
44858 + * enough to transfer the whole 512 bytes at a time. (maybe through
44861 +const struct ubi32_nand_spi_er_device ubi32_nand_spi_er_devices[] = {
44863 + name: "MT29F1G01ZDC",
44866 + pages_per_block: 64,
44868 + write_size: 2048,
44869 + erase_size: 64 * 2048,
44872 + name: "MT29F1G01ZDC",
44875 + pages_per_block: 64,
44877 + write_size: 2048,
44878 + erase_size: 64 * 2048,
44882 +static int read_only = 0;
44883 +module_param(read_only, int, 0);
44884 +MODULE_PARM_DESC(read_only, "Leave device locked");
44887 + * Ubicom32 FLASH Command Set
44889 +#define FLASH_PORT RA
44891 +#define FLASH_FC_INST_CMD 0x00 /* for SPI command only transaction */
44892 +#define FLASH_FC_INST_WR 0x01 /* for SPI write transaction */
44893 +#define FLASH_FC_INST_RD 0x02 /* for SPI read transaction */
44895 +#define FLASH_COMMAND_KICK_OFF(io) \
44897 + " bset "D(IO_INT_CLR)"(%0), #0, #%%bit("D(IO_XFL_INT_DONE)") \n\t" \
44898 + " jmpt.t .+4 \n\t" \
44899 + " bset "D(IO_INT_SET)"(%0), #0, #%%bit("D(IO_XFL_INT_START)") \n\t" \
44905 +#define FLASH_COMMAND_WAIT_FOR_COMPLETION(io) \
44907 + " btst "D(IO_INT_STATUS)"(%0), #%%bit("D(IO_XFL_INT_DONE)") \n\t" \
44908 + " jmpeq.f .-4 \n\t" \
44914 +#define FLASH_COMMAND_EXEC(io) \
44915 + FLASH_COMMAND_KICK_OFF(io) \
44916 + FLASH_COMMAND_WAIT_FOR_COMPLETION(io)
44919 + * ubi32_nand_spi_er_get_feature
44920 + * Get Feature register
44922 +static uint8_t ubi32_nand_spi_er_get_feature(uint32_t reg)
44924 + struct ubicom32_io_port *io = (struct ubicom32_io_port *)FLASH_PORT;
44927 + * Note that this will produce the sequence:
44928 + * SI [0F][REG][00][00]
44929 + * SO ---------[SR][SR][SR]
44930 + * Since the flash controller can only output 24 bits of address, this is
44931 + * ok for this command since the data will just repeat as long as the CS
44932 + * is asserted and the clock is running.
44934 + io->ctl1 &= ~IO_XFL_CTL1_MASK;
44935 + io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_RD) | IO_XFL_CTL1_FC_DATA(1) |
44936 + IO_XFL_CTL1_FC_ADDR;
44937 + io->ctl2 = IO_XFL_CTL2_FC_CMD(0x0F) | IO_XFL_CTL2_FC_ADDR(reg << 16);
44938 + FLASH_COMMAND_EXEC(io);
44940 + return io->status1 & 0xFF;
44944 + * ubi32_nand_spi_er_write_buf
44945 + * writes a buffer to the bus
44947 + * Writes 511 + 1 bytes to the bus, we have to stuff one data byte into the address.
44949 +static void ubi32_nand_spi_er_write_buf(const uint8_t *buf, uint32_t col)
44951 + struct ubicom32_io_port *io = (struct ubicom32_io_port *)FLASH_PORT;
44955 + " bset "D(IO_INT_SET)"(%[port]), #0, #%%bit("D(IO_PORTX_INT_FIFO_TX_RESET)") \n\t"
44956 + " pipe_flush 0 \n\t"
44958 + : [port] "a" (FLASH_PORT)
44963 + * Write the data into the cache
44965 + io->ctl1 &= ~IO_XFL_CTL1_MASK;
44966 +#ifdef SUPPORT_512_FIFO
44967 + io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_WR) | IO_XFL_CTL1_FC_DATA(511) |
44969 + io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_WR) | IO_XFL_CTL1_FC_DATA(31) |
44970 + IO_XFL_CTL1_FC_ADDR;
44973 + * Construct the address with the first byte of data
44975 + tmp = (col << 8) | *buf++;
44976 + io->ctl2 = IO_XFL_CTL2_FC_CMD(0x84) | IO_XFL_CTL2_FC_ADDR(tmp);
44983 + * The first word needs to be [11][22][33][33] to work around a flash
44984 + * controller bug.
44986 + " move.2 %[tmp], (%[data])2++ \n\t"
44987 + " shmrg.1 %[tmp], (%[data]), %[tmp] \n\t"
44988 + " shmrg.1 %[tmp], (%[data])1++, %[tmp] \n\t"
44989 + " move.4 "D(IO_TX_FIFO)"(%[port]), %[tmp] \n\t"
44992 + * We're aligned again!
44995 + " move.4 "D(IO_TX_FIFO)"(%[port]), (%[data])4++ \n\t"
44999 + * Kick off the flash command
45001 + " bset "D(IO_INT_CLR)"(%[port]), #0, #%%bit("D(IO_XFL_INT_DONE)") \n\t"
45002 + " jmpt.t .+4 \n\t"
45003 + " bset "D(IO_INT_SET)"(%[port]), #0, #%%bit("D(IO_XFL_INT_START)") \n\t"
45005 +#ifdef SUPPORT_512_FIFO
45007 + * Fill the remaining 120 words as space becomes available
45010 + " cmpi "D(IO_FIFO_LEVEL)"(%[port]), #4 \n\t"
45011 + " jmpgt.s.t 1b \n\t"
45012 + " move.4 "D(IO_TX_FIFO)"(%[port]), (%[data])4++ \n\t"
45013 + " move.4 "D(IO_TX_FIFO)"(%[port]), (%[data])4++ \n\t"
45014 + " move.4 "D(IO_TX_FIFO)"(%[port]), (%[data])4++ \n\t"
45015 + " move.4 "D(IO_TX_FIFO)"(%[port]), (%[data])4++ \n\t"
45016 + " add.4 %[cnt], #-4, %[cnt] \n\t"
45017 + " jmpgt.t 1b \n\t"
45020 + * Wait for the transaction to finish
45022 + " btst "D(IO_INT_STATUS)"(%[port]), #%%bit("D(IO_XFL_INT_DONE)") \n\t"
45023 + " jmpeq.f .-4 \n\t"
45025 + : [tmp] "=&d" (tmp),
45026 + [data] "+&a" (buf)
45027 + : [column] "d" (col),
45028 + [port] "a" (FLASH_PORT),
45029 + [cnt] "d" (120) // see above comment
45035 + * ubi32_nand_spi_er_send_rd_addr
45036 + * perform FC_RD: CMD + address
45038 +static void ubi32_nand_spi_er_send_rd_addr(uint8_t command, uint32_t address)
45040 + struct ubicom32_io_port *io = (struct ubicom32_io_port *)FLASH_PORT;
45042 + io->ctl1 &= ~IO_XFL_CTL1_MASK;
45043 + io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_RD) | IO_XFL_CTL1_FC_DATA(4) |
45044 + IO_XFL_CTL1_FC_ADDR;
45045 + io->ctl2 = IO_XFL_CTL2_FC_CMD(command) | IO_XFL_CTL2_FC_ADDR(address);
45046 + FLASH_COMMAND_EXEC(io);
45050 + * ubi32_nand_spi_er_send_cmd_addr
45051 + * perform FC_(xxx): CMD + address
45053 +static void ubi32_nand_spi_er_send_cmd_addr(uint8_t command, uint32_t address)
45055 + struct ubicom32_io_port *io = (struct ubicom32_io_port *)FLASH_PORT;
45057 + io->ctl1 &= ~IO_XFL_CTL1_MASK;
45058 + io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_CMD) | IO_XFL_CTL1_FC_ADDR;
45059 + io->ctl2 = IO_XFL_CTL2_FC_CMD(command) | IO_XFL_CTL2_FC_ADDR(address);
45060 + FLASH_COMMAND_EXEC(io);
45064 + * ubi32_nand_spi_er_write_disable
45065 + * clear the write enable bit
45067 +static void ubi32_nand_spi_er_write_disable(void)
45069 + struct ubicom32_io_port *io = (struct ubicom32_io_port *)FLASH_PORT;
45071 + io->ctl1 &= ~IO_XFL_CTL1_MASK;
45072 + io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_CMD);
45073 + io->ctl2 = IO_XFL_CTL2_FC_CMD(0x04);
45074 + FLASH_COMMAND_EXEC(io);
45078 + * ubi32_nand_spi_er_write_enable
45079 + * set the write enable bit
45081 +static void ubi32_nand_spi_er_write_enable(void)
45083 + struct ubicom32_io_port *io = (struct ubicom32_io_port *)FLASH_PORT;
45085 + io->ctl1 &= ~IO_XFL_CTL1_MASK;
45086 + io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_CMD);
45087 + io->ctl2 = IO_XFL_CTL2_FC_CMD(0x06);
45088 + FLASH_COMMAND_EXEC(io);
45092 + * ubi32_nand_spi_er_busywait
45093 + * Wait until the chip is not busy
45095 +static uint8_t ubi32_nand_spi_er_busywait(void)
45101 + * tRD is 100us, so don't delay too long, however, tERS is
45102 + * 10ms so you'd better loop enough.
45104 + for (i = 0; i < 200; i++) {
45105 + data = ubi32_nand_spi_er_get_feature(0xC0);
45106 + if (!(data & UBI32_NAND_SPI_ER_STATUS_OIP)) {
45117 + * ubi32_nand_spi_er_erase
45118 + * Erase a block, parameters must be block aligned
45120 +static int ubi32_nand_spi_er_erase(struct mtd_info *mtd, struct erase_info *instr)
45122 + struct ubi32_nand_spi_er *chip = mtd->priv;
45125 + DEBUG(MTD_DEBUG_LEVEL3, "%s: erase addr:%x len:%x\n", chip->name, instr->addr, instr->len);
45127 + if ((instr->addr + instr->len) > mtd->size) {
45131 + if (instr->addr & (chip->device->erase_size - 1)) {
45132 + DEBUG(MTD_DEBUG_LEVEL1, "%s: erase address is not aligned %x\n", chip->name, instr->addr);
45136 + if (instr->len & (chip->device->erase_size - 1)) {
45137 + DEBUG(MTD_DEBUG_LEVEL1, "%s: erase len is not aligned %x\n", chip->name, instr->len);
45141 + mutex_lock(&chip->lock);
45142 + chip->last_row = UBI32_NAND_SPI_ER_LAST_ROW_INVALID;
45144 + while (instr->len) {
45145 + uint32_t block = instr->addr >> 17;
45146 + uint32_t row = block << 6;
45148 + DEBUG(MTD_DEBUG_LEVEL3, "%s: block erase row:%x block:%x addr:%x rem:%x\n", chip->name, row, block, instr->addr, instr->len);
45151 + * Test for bad block
45153 + if (test_bit(block, chip->bbt)) {
45154 + instr->fail_addr = block << 17;
45155 + instr->state = MTD_ERASE_FAILED;
45160 + ubi32_nand_spi_er_write_enable();
45165 + ubi32_nand_spi_er_send_cmd_addr(0xD8, row);
45170 + stat = ubi32_nand_spi_er_busywait();
45171 + if (stat & UBI32_NAND_SPI_ER_STATUS_OIP) {
45172 + instr->fail_addr = block << 17;
45173 + instr->state = MTD_ERASE_FAILED;
45174 + DEBUG(MTD_DEBUG_LEVEL1, "%s: chip is busy or nonresponsive stat=%02x\n", chip->name, stat);
45184 + * Check the status register
45186 + if (stat & UBI32_NAND_SPI_ER_STATUS_E_FAIL) {
45187 + DEBUG(MTD_DEBUG_LEVEL1, "%s: E_FAIL signalled (%02x)\n", chip->name, stat);
45188 + instr->fail_addr = block << 17;
45189 + instr->state = MTD_ERASE_FAILED;
45197 + instr->len -= chip->device->erase_size;
45198 + instr->addr += chip->device->erase_size;
45201 + instr->state = MTD_ERASE_DONE;
45203 + mutex_unlock(&chip->lock);
45207 + ubi32_nand_spi_er_write_disable();
45209 + mutex_unlock(&chip->lock);
45211 + mtd_erase_callback(instr);
45216 + * ubi32_nand_spi_er_read
45218 + * return -EUCLEAN: ecc error recovered
45219 + * return -EBADMSG: ecc error not recovered
45221 +static int ubi32_nand_spi_er_read(struct mtd_info *mtd, loff_t from, size_t len,
45222 + size_t *retlen, u_char *buf)
45224 + struct ubi32_nand_spi_er *chip = mtd->priv;
45225 + struct ubicom32_io_port *io = (struct ubicom32_io_port *)FLASH_PORT;
45230 + uint32_t *pbuf = (uint32_t *)buf;
45233 + DEBUG(MTD_DEBUG_LEVEL2, "%s: read block from %llx len %d into %p\n", chip->name, from, len, buf);
45236 + * buf should be aligned
45238 + if ((uint32_t)buf & 0x03) {
45243 + * Zero length reads, nothing to do
45250 + * Reject reads which go over the end of the flash
45252 + if ((from + len) > mtd->size) {
45257 + * Get the row and column address to start at
45259 + row = from >> 11;
45260 + column = from & 0x7FF;
45261 + DEBUG(MTD_DEBUG_LEVEL3, "%s: row=%x %d column=%x %d last_row=%x %d\n", chip->name, row, row, column, column, chip->last_row, chip->last_row);
45264 + * Read the data from the chip
45266 + mutex_lock(&chip->lock);
45274 + * Figure out how much to read
45276 + * If we are reading from the middle of a page then the most we
45277 + * can read is to the end of the page
45280 + if (toread > (chip->device->page_size - column)) {
45281 + toread = chip->device->page_size - column;
45284 + DEBUG(MTD_DEBUG_LEVEL3, "%s: buf=%p toread=%x row=%x column=%x last_row=%x\n", chip->name, pbuf, toread, row, column, chip->last_row);
45286 + if (chip->last_row != row) {
45288 + * Check if the block is bad
45290 + if (test_bit(UBI32_NAND_SPI_ER_BLOCK_FROM_ROW(row), chip->bbt)) {
45291 + mutex_unlock(&chip->lock);
45296 + * Load the appropriate page
45298 + ubi32_nand_spi_er_send_cmd_addr(0x13, row);
45303 + stat = ubi32_nand_spi_er_busywait();
45304 + if (stat & UBI32_NAND_SPI_ER_STATUS_OIP) {
45305 + DEBUG(MTD_DEBUG_LEVEL1, "%s: chip is busy or nonresponsive stat=%02x\n", chip->name, stat);
45310 + mutex_unlock(&chip->lock);
45315 + * Check the ECC bits
45319 + DEBUG(MTD_DEBUG_LEVEL1, "%s: ECC recovered, row=%x\n", chip->name, row);
45320 + retval = -EUCLEAN;
45323 + DEBUG(MTD_DEBUG_LEVEL0, "%s: failed ECC, row=%x\n", chip->name, row);
45324 + chip->last_row = UBI32_NAND_SPI_ER_LAST_ROW_INVALID;
45325 + mutex_unlock(&chip->lock);
45331 + chip->last_row = row;
45334 + * Read out the data:
45335 + * We can always read a little too much since there is the
45336 + * OOB after byte addr 2047. The most we'll overread is 3 bytes.
45338 + if (((uint32_t)pbuf & 0x03) == 0) {
45342 + tmp = toread & (~0x03);
45343 + for (i = 0; i < tmp; i += 4) {
45344 + ubi32_nand_spi_er_send_rd_addr(0x03, column << 8);
45345 + *pbuf++ = io->status1;
45352 + tmp = toread & (~0x03);
45353 + for (i = 0; i < tmp; i += 4) {
45354 + ubi32_nand_spi_er_send_rd_addr(0x03, column << 8);
45355 + memcpy(pbuf, &io->status1, 4);
45361 + * Fill in any single bytes
45363 + tmp = toread & 0x03;
45365 + uint8_t *bbuf = pbuf;
45367 + ubi32_nand_spi_er_send_rd_addr(0x03, column << 8);
45368 + val = io->status1;
45369 + for (i = 0; i < tmp; i++) {
45370 + *bbuf++ = val >> 24;
45376 + *retlen += toread;
45379 + * For the next page, increment the row and always start at column 0
45385 + mutex_unlock(&chip->lock);
45390 + * ubi32_nand_spi_er_write
45392 +#define WRITE_NOT_ALIGNED(x) ((x & (device->write_size - 1)) != 0)
45393 +static int ubi32_nand_spi_er_write(struct mtd_info *mtd, loff_t to, size_t len,
45394 + size_t *retlen, const u_char *buf)
45396 + struct ubi32_nand_spi_er *chip = mtd->priv;
45397 + const struct ubi32_nand_spi_er_device *device = chip->device;
45398 + struct ubicom32_io_port *io = (struct ubicom32_io_port *)FLASH_PORT;
45404 + DEBUG(MTD_DEBUG_LEVEL2, "%s: write block to %llx len %d from %p\n", chip->name, to, len, buf);
45409 + * nothing to write
45416 + * Reject writes which go over the end of the flash
45418 + if ((to + len) > mtd->size) {
45423 + * buf should be aligned to 16 bits
45425 + if ((uint32_t)buf & 0x01) {
45430 + * Check to see if everything is page aligned
45432 + if (WRITE_NOT_ALIGNED(to) || WRITE_NOT_ALIGNED(len)) {
45433 + printk(KERN_NOTICE "ubi32_nand_spi_er_write: Attempt to write non page aligned data\n");
45437 + mutex_lock(&chip->lock);
45439 + io->ctl0 |= IO_XFL_CTL0_MCB_LOCK;
45441 + chip->last_row = UBI32_NAND_SPI_ER_LAST_ROW_INVALID;
45444 + * If the first write is a partial write then write at most the number of
45445 + * bytes to get us page aligned and then the remainder will be
45446 + * page aligned. The last bit may be a partial page as well.
45448 + col = to & (device->page_size - 1);
45449 + towrite = device->page_size - col;
45450 + if (towrite > len) {
45460 + uint32_t my_towrite;
45462 + DEBUG(MTD_DEBUG_LEVEL3, "%s: write %p to row:%x col:%x len:%x rem:%x\n", chip->name, buf, row, col, towrite, len);
45464 + ubi32_nand_spi_er_write_enable();
45467 + * Move the data into the cache
45469 + my_towrite = towrite;
45470 + while (my_towrite) {
45471 + uint32_t len = my_towrite;
45476 + ubi32_nand_spi_er_write_buf(buf, col);
45479 + my_towrite -= len;
45483 + * Program execute
45485 + ubi32_nand_spi_er_send_cmd_addr(0x10, row);
45490 + stat = ubi32_nand_spi_er_busywait();
45491 + if (stat & UBI32_NAND_SPI_ER_STATUS_OIP) {
45492 + DEBUG(MTD_DEBUG_LEVEL1, "%s: chip is busy or nonresponsive stat=%02x\n", chip->name, stat);
45501 + if (stat & (1 << 3)) {
45508 + *retlen += towrite;
45511 + * At this point, we are always page aligned so start at column 0.
45512 + * Note we may not have a full page to write at the end, hence the
45513 + * check if towrite > len.
45516 + towrite = device->page_size;
45517 + if (towrite > len) {
45522 + io->ctl0 &= ~IO_XFL_CTL0_MCB_LOCK;
45524 + mutex_unlock(&chip->lock);
45528 + ubi32_nand_spi_er_write_disable();
45530 + io->ctl0 &= ~IO_XFL_CTL0_MCB_LOCK;
45532 + mutex_unlock(&chip->lock);
45538 + * ubi32_nand_spi_er_isbad
45540 +static int ubi32_nand_spi_er_isbad(struct mtd_info *mtd, loff_t ofs)
45542 + struct ubi32_nand_spi_er *chip = mtd->priv;
45545 + if (ofs & (chip->device->erase_size - 1)) {
45546 + DEBUG(MTD_DEBUG_LEVEL1, "%s: address not aligned %llx\n", chip->name, ofs);
45550 + block = ofs >> 17;
45552 + return test_bit(block, chip->bbt);
45556 + * ubi32_nand_spi_er_markbad
45558 +static int ubi32_nand_spi_er_markbad(struct mtd_info *mtd, loff_t ofs)
45560 + struct ubi32_nand_spi_er *chip = mtd->priv;
45561 + struct ubicom32_io_port *io = (struct ubicom32_io_port *)FLASH_PORT;
45567 + if (ofs & (chip->device->erase_size - 1)) {
45568 + DEBUG(MTD_DEBUG_LEVEL1, "%s: address not aligned %llx\n", chip->name, ofs);
45572 + block = ofs >> 17;
45575 + * If it's already marked bad, no need to mark it
45577 + if (test_bit(block, chip->bbt)) {
45582 + * Mark it in our cache
45584 + __set_bit(block, chip->bbt);
45587 + * Write the user bad block mark. If it fails, then we really
45588 + * can't do anything about it.
45590 + mutex_lock(&chip->lock);
45591 + chip->last_row = UBI32_NAND_SPI_ER_LAST_ROW_INVALID;
45593 + ubi32_nand_spi_er_write_enable();
45598 + io->ctl0 |= IO_XFL_CTL0_MCB_LOCK;
45599 + io->ctl1 &= ~IO_XFL_CTL1_MASK;
45600 + io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_WR) | IO_XFL_CTL1_FC_DATA(6);
45601 + io->ctl2 = IO_XFL_CTL2_FC_CMD(0x84);
45604 + " bset "D(IO_INT_SET)"(%[port]), #0, #%%bit("D(IO_PORTX_INT_FIFO_TX_RESET)") \n\t"
45605 + " pipe_flush 0 \n\t"
45608 + * Move the data into the FIFO
45610 + " move.4 "D(IO_TX_FIFO)"(%[port]), %[word1] \n\t"
45611 + " move.4 "D(IO_TX_FIFO)"(%[port]), %[word2] \n\t"
45614 + * Kick off the flash command
45616 + " bset "D(IO_INT_CLR)"(%[port]), #0, #%%bit("D(IO_XFL_INT_DONE)") \n\t"
45617 + " jmpt.t .+4 \n\t"
45618 + " bset "D(IO_INT_SET)"(%[port]), #0, #%%bit("D(IO_XFL_INT_START)") \n\t"
45621 + * Wait for the transaction to finish
45623 + " btst "D(IO_INT_STATUS)"(%[port]), #%%bit("D(IO_XFL_INT_DONE)") \n\t"
45624 + " jmpeq.f .-4 \n\t"
45627 + : [word1] "d" (0x0800dead | (UBI32_NAND_SPI_ER_BAD_BLOCK_MARK_OFFSET << 16)),
45628 + [word2] "d" (0xbeef0000),
45629 + [port] "a" (FLASH_PORT)
45633 + io->ctl0 &= ~IO_XFL_CTL0_MCB_LOCK;
45636 + * Program execute
45638 + row = block << 6;
45639 + ubi32_nand_spi_er_send_cmd_addr(0x10, row);
45644 + stat = ubi32_nand_spi_er_busywait();
45645 + if (stat & UBI32_NAND_SPI_ER_STATUS_OIP) {
45646 + DEBUG(MTD_DEBUG_LEVEL1, "%s: chip is busy or nonresponsive stat=%02x\n", chip->name, stat);
45655 + if (stat & (1 << 3)) {
45660 + ubi32_nand_spi_er_write_disable();
45662 + mutex_unlock(&chip->lock);
45668 + * ubi32_nand_spi_er_read_bbt
45670 +static int ubi32_nand_spi_er_read_bbt(struct ubi32_nand_spi_er *chip)
45673 + struct ubicom32_io_port *io = (struct ubicom32_io_port *)FLASH_PORT;
45675 + for (j = 0; j < chip->device->blocks; j++) {
45676 + unsigned short row = j << 6;
45682 + ubi32_nand_spi_er_send_cmd_addr(0x13, row);
45687 + stat = ubi32_nand_spi_er_busywait();
45688 + if (stat & UBI32_NAND_SPI_ER_STATUS_OIP) {
45689 + DEBUG(MTD_DEBUG_LEVEL1, "%s: chip is busy or nonresponsive stat=%02x\n", chip->name, stat);
45698 + * Check factory bad block mark
45700 + ubi32_nand_spi_er_send_rd_addr(0x03, 0x080000);
45702 + if ((io->status1 >> 24) != 0xFF) {
45704 + __set_bit(j, chip->bbt);
45708 + ubi32_nand_spi_er_send_rd_addr(0x03, 0x080000 | (UBI32_NAND_SPI_ER_BAD_BLOCK_MARK_OFFSET << 8));
45709 + if (io->status1 == 0xdeadbeef) {
45711 + __set_bit(j, chip->bbt);
45715 +#if defined(CONFIG_MTD_DEBUG) && (MTD_DEBUG_LEVEL3 <= CONFIG_MTD_DEBUG_VERBOSE)
45716 + printk("%s: Bad Block Table:", chip->name);
45717 + for (j = 0; j < chip->device->blocks; j++) {
45718 + if ((j % 64) == 0) {
45719 + printk("\n%s: block %03x: ", chip->name, j);
45721 + printk("%c", test_bit(j, chip->bbt) ? 'X' : '.');
45723 + printk("\n%s: Bad Block Numbers: ", chip->name);
45724 + for (j = 0; j < chip->device->blocks; j++) {
45725 + if (test_bit(j, chip->bbt)) {
45726 + printk("%x ", j);
45737 + * Called at boot time:
45739 + * ubi32_nand_spi_er=read_only
45740 + * if read_only specified then do not unlock device
45742 +static int __init ubi32_nand_spi_er_setup(char *str)
45744 + if (str && (strncasecmp(str, "read_only", 9) == 0)) {
45750 +__setup("ubi32_nand_spi_er=", ubi32_nand_spi_er_setup);
45754 + * ubi32_nand_spi_er_probe
45755 + * Detect and initialize ubi32_nand_spi_er device.
45757 +static int __devinit ubi32_nand_spi_er_probe(struct platform_device *pdev)
45762 + size_t bbt_bytes;
45763 + struct ubi32_nand_spi_er *chip;
45764 + const struct ubi32_nand_spi_er_device *device;
45765 + struct ubicom32_io_port *io = (struct ubicom32_io_port *)FLASH_PORT;
45770 + for (i = 0; i < 2; i++) {
45771 + io->ctl1 &= ~IO_XFL_CTL1_MASK;
45772 + io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_CMD);
45773 + io->ctl2 = IO_XFL_CTL2_FC_CMD(0xFF);
45774 + FLASH_COMMAND_EXEC(io);
45782 + io->ctl1 &= ~IO_XFL_CTL1_MASK;
45783 + io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_RD) | IO_XFL_CTL1_FC_DATA(2) |
45784 + IO_XFL_CTL1_FC_ADDR;
45785 + io->ctl2 = IO_XFL_CTL2_FC_CMD(0x9F);
45786 + FLASH_COMMAND_EXEC(io);
45788 + id = io->status1 >> 16;
45789 + device = ubi32_nand_spi_er_devices;
45790 + for (i = 0; i < ARRAY_SIZE(ubi32_nand_spi_er_devices); i++) {
45791 + if (device->id == id) {
45796 + if (i == ARRAY_SIZE(ubi32_nand_spi_er_devices)) {
45801 + * Initialize our chip structure
45803 + bbt_bytes = DIV_ROUND_UP(device->blocks, BITS_PER_BYTE);
45804 + chip = kzalloc(sizeof(struct ubi32_nand_spi_er) + bbt_bytes, GFP_KERNEL);
45808 + snprintf(chip->name, sizeof(chip->name), "%s", device->name);
45810 + chip->device = device;
45811 + chip->last_row = UBI32_NAND_SPI_ER_LAST_ROW_INVALID;
45813 + mutex_init(&chip->lock);
45815 + chip->mtd.type = MTD_NANDFLASH;
45816 + chip->mtd.flags = MTD_WRITEABLE;
45819 + * #blocks * block size * n blocks
45821 + chip->mtd.size = device->blocks * device->pages_per_block * device->page_size;
45822 + chip->mtd.erasesize = device->erase_size;
45825 + * 1 page, optionally we can support partial write (512)
45827 + chip->mtd.writesize = device->write_size;
45828 + chip->mtd.name = device->name;
45829 + chip->mtd.erase = ubi32_nand_spi_er_erase;
45830 + chip->mtd.read = ubi32_nand_spi_er_read;
45831 + chip->mtd.write = ubi32_nand_spi_er_write;
45832 + chip->mtd.block_isbad = ubi32_nand_spi_er_isbad;
45833 + chip->mtd.block_markbad = ubi32_nand_spi_er_markbad;
45834 + chip->mtd.priv = chip;
45837 + * Cache the bad block table
45839 + res = ubi32_nand_spi_er_read_bbt(chip);
45846 + * Un/lock the chip
45848 + io->ctl0 |= IO_XFL_CTL0_MCB_LOCK;
45849 + io->ctl1 &= ~IO_XFL_CTL1_MASK;
45850 + io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_WR) | IO_XFL_CTL1_FC_DATA(2);
45851 + io->ctl2 = IO_XFL_CTL2_FC_CMD(0x1F);
45859 + " bset "D(IO_INT_SET)"(%[port]), #0, #%%bit("D(IO_PORTX_INT_FIFO_TX_RESET)") \n\t"
45860 + " pipe_flush 0 \n\t"
45863 + * Move the data into the FIFO
45865 + " move.4 "D(IO_TX_FIFO)"(%[port]), %[word1] \n\t"
45868 + * Kick off the flash command
45870 + " bset "D(IO_INT_CLR)"(%[port]), #0, #%%bit("D(IO_XFL_INT_DONE)") \n\t"
45871 + " jmpt.t .+4 \n\t"
45872 + " bset "D(IO_INT_SET)"(%[port]), #0, #%%bit("D(IO_XFL_INT_START)") \n\t"
45875 + * Wait for the transaction to finish
45877 + " btst "D(IO_INT_STATUS)"(%[port]), #%%bit("D(IO_XFL_INT_DONE)") \n\t"
45878 + " jmpeq.f .-4 \n\t"
45881 + : [word1] "d" (i),
45882 + [port] "a" (FLASH_PORT)
45885 + io->ctl0 &= ~IO_XFL_CTL0_MCB_LOCK;
45887 + dev_set_drvdata(&pdev->dev, chip);
45889 + printk(KERN_INFO "%s: added device size: %u KBytes %lu bad blocks %s\n", chip->mtd.name, DIV_ROUND_UP(chip->mtd.size, 1024), chip->nbb, read_only ? "[read only]" : "");
45890 + return add_mtd_device(&chip->mtd);
45894 + * ubi32_nand_spi_er_remove
45896 +static int __devexit ubi32_nand_spi_er_remove(struct platform_device *pdev)
45898 + struct ubi32_nand_spi_er *chip = dev_get_drvdata(&pdev->dev);
45901 + DEBUG(MTD_DEBUG_LEVEL1, "%s: remove\n", chip->name);
45903 + status = del_mtd_device(&chip->mtd);
45904 + if (status == 0) {
45908 + dev_set_drvdata(&pdev->dev, NULL);
45912 +static struct platform_device *ubi32_nand_spi_er_device;
45914 +static struct platform_driver ubi32_nand_spi_er_driver = {
45916 + .name = DRIVER_NAME,
45917 + .owner = THIS_MODULE,
45920 + .probe = ubi32_nand_spi_er_probe,
45921 + .remove = ubi32_nand_spi_er_remove,
45925 + * ubi32_nand_spi_er_init
45927 +static int __init ubi32_nand_spi_er_init(void)
45931 + ret = platform_driver_register(&ubi32_nand_spi_er_driver);
45937 + ubi32_nand_spi_er_device = platform_device_alloc(DRIVER_NAME, 0);
45938 + if (!ubi32_nand_spi_er_device) {
45942 + ret = platform_device_add(ubi32_nand_spi_er_device);
45944 + platform_device_put(ubi32_nand_spi_er_device);
45945 + platform_driver_unregister(&ubi32_nand_spi_er_driver);
45950 +module_init(ubi32_nand_spi_er_init);
45953 + * ubi32_nand_spi_er_exit
45955 +static void __exit ubi32_nand_spi_er_exit(void)
45957 + platform_device_unregister(ubi32_nand_spi_er_device);
45958 + platform_driver_unregister(&ubi32_nand_spi_er_driver);
45960 +module_exit(ubi32_nand_spi_er_exit);
45963 +MODULE_LICENSE("GPL");
45964 +MODULE_AUTHOR("Patrick Tjin");
45965 +MODULE_DESCRIPTION("MTD ubi32_nand_spi_er driver for ubicom32 SPI flash controller.");
45966 diff -ruN linux-2.6.30.10/drivers/net/Kconfig linux-2.6.30.10-ubi/drivers/net/Kconfig
45967 --- linux-2.6.30.10/drivers/net/Kconfig 2009-12-14 11:47:19.000000000 +0200
45968 +++ linux-2.6.30.10-ubi/drivers/net/Kconfig 2009-12-14 11:47:17.000000000 +0200
45969 @@ -2540,6 +2540,19 @@
45970 To compile this driver as a module, choose M here. The module
45971 will be called jme.
45973 +config UBICOM32_GMAC
45974 + tristate "Ubicom Gigabit Ethernet support"
45975 + depends on UBICOM32
45977 + Gigabit Ethernet support for ubicom32 processors
45979 +config UBICOM32_OCM_FOR_SKB
45980 + bool "USE OCM for SKB (EXPERIMENTAL)"
45981 + depends on UBICOM32_GMAC
45984 + Allocate skb from OCM for Ethernet Receive when possible
45986 endif # NETDEV_1000
45989 diff -ruN linux-2.6.30.10/drivers/net/Makefile linux-2.6.30.10-ubi/drivers/net/Makefile
45990 --- linux-2.6.30.10/drivers/net/Makefile 2009-12-14 11:48:38.000000000 +0200
45991 +++ linux-2.6.30.10-ubi/drivers/net/Makefile 2009-12-14 11:48:40.000000000 +0200
45992 @@ -272,3 +272,5 @@
45993 obj-$(CONFIG_SFC) += sfc/
45995 obj-$(CONFIG_WIMAX) += wimax/
45997 +obj-$(CONFIG_UBICOM32_GMAC) += ubi32-eth.o
45998 diff -ruN linux-2.6.30.10/drivers/net/ubi32-eth.c linux-2.6.30.10-ubi/drivers/net/ubi32-eth.c
45999 --- linux-2.6.30.10/drivers/net/ubi32-eth.c 1970-01-01 02:00:00.000000000 +0200
46000 +++ linux-2.6.30.10-ubi/drivers/net/ubi32-eth.c 2009-12-11 11:45:18.000000000 +0200
46003 + * drivers/net/ubi32-eth.c
46004 + * Ubicom32 ethernet TIO interface driver.
46006 + * (C) Copyright 2009, Ubicom, Inc.
46008 + * This file is part of the Ubicom32 Linux Kernel Port.
46010 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
46011 + * it and/or modify it under the terms of the GNU General Public License
46012 + * as published by the Free Software Foundation, either version 2 of the
46013 + * License, or (at your option) any later version.
46015 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
46016 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
46017 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
46018 + * the GNU General Public License for more details.
46020 + * You should have received a copy of the GNU General Public License
46021 + * along with the Ubicom32 Linux Kernel Port. If not,
46022 + * see <http://www.gnu.org/licenses/>.
46024 + * Ubicom32 implementation derived from (with many thanks):
46031 + * Ethernet driver for Ip5k/Ip7K
46034 +#include <linux/module.h>
46035 +#include <linux/init.h>
46036 +#include <linux/moduleparam.h>
46038 +#include <linux/sched.h>
46039 +#include <linux/kernel.h>
46040 +#include <linux/errno.h>
46041 +#include <linux/types.h>
46042 +#include <linux/interrupt.h>
46044 +#include <linux/in.h>
46045 +#include <linux/netdevice.h>
46046 +#include <linux/etherdevice.h>
46047 +#include <linux/mii.h>
46048 +#include <linux/if_vlan.h>
46049 +#include <linux/ip.h>
46050 +#include <linux/tcp.h>
46051 +#include <linux/skbuff.h>
46052 +#include <asm/checksum.h>
46053 +#include <asm/ip5000.h>
46054 +#include <asm/devtree.h>
46055 +#include <asm/system.h>
46057 +#define UBICOM32_USE_NAPI /* define this to use NAPI instead of tasklet */
46058 +//#define UBICOM32_USE_POLLING /* define this to use polling instead of interrupt */
46059 +#include "ubi32-eth.h"
46063 + * mac address from flash
46064 + * multicast filter
46065 + * ethtool support
46067 + * skb->nrfrag support
46069 + * monitor phy status
46072 +extern int ubi32_ocm_skbuf_max, ubi32_ocm_skbuf, ubi32_ddr_skbuf;
46073 +static const char *eth_if_name[UBI32_ETH_NUM_OF_DEVICES] =
46074 + {"eth_lan", "eth_wan"};
46075 +static struct net_device *ubi32_eth_devices[UBI32_ETH_NUM_OF_DEVICES] =
46077 +static u8_t mac_addr[UBI32_ETH_NUM_OF_DEVICES][ETH_ALEN] = {
46078 + {0x00, 0x03, 0x64, 'l', 'a', 'n'},
46079 + {0x00, 0x03, 0x64, 'w', 'a', 'n'}};
46081 +#if (defined(CONFIG_ZONE_DMA) && defined(CONFIG_UBICOM32_OCM_FOR_SKB))
46082 +static inline struct sk_buff *ubi32_alloc_skb_ocm(struct net_device *dev, unsigned int length)
46084 + return __dev_alloc_skb(length, GFP_ATOMIC | __GFP_NOWARN | __GFP_NORETRY | GFP_DMA);
46088 +static inline struct sk_buff *ubi32_alloc_skb(struct net_device *dev, unsigned int length)
46090 + return __dev_alloc_skb(length, GFP_ATOMIC | __GFP_NOWARN);
46093 +static void ubi32_eth_vp_rxtx_enable(struct net_device *dev)
46095 + struct ubi32_eth_private *priv = netdev_priv(dev);
46096 + priv->regs->command = UBI32_ETH_VP_CMD_RX_ENABLE | UBI32_ETH_VP_CMD_TX_ENABLE;
46097 + priv->regs->int_mask = (UBI32_ETH_VP_INT_RX | UBI32_ETH_VP_INT_TX);
46098 + ubicom32_set_interrupt(priv->vp_int_bit);
46101 +static void ubi32_eth_vp_rxtx_stop(struct net_device *dev)
46103 + struct ubi32_eth_private *priv = netdev_priv(dev);
46104 + priv->regs->command = 0;
46105 + priv->regs->int_mask = 0;
46106 + ubicom32_set_interrupt(priv->vp_int_bit);
46108 + /* Wait for graceful shutdown */
46109 + while (priv->regs->status & (UBI32_ETH_VP_STATUS_RX_STATE | UBI32_ETH_VP_STATUS_TX_STATE));
46113 + * ubi32_eth_tx_done()
46115 +static int ubi32_eth_tx_done(struct net_device *dev)
46117 + struct ubi32_eth_private *priv;
46118 + struct sk_buff *skb;
46119 + volatile void *pdata;
46120 + struct ubi32_eth_dma_desc *desc;
46123 + priv = netdev_priv(dev);
46125 + priv->regs->int_status &= ~UBI32_ETH_VP_INT_TX;
46126 + while (priv->tx_tail != priv->regs->tx_out) {
46127 + pdata = priv->regs->tx_dma_ring[priv->tx_tail];
46128 + BUG_ON(pdata == NULL);
46130 + skb = container_of((void *)pdata, struct sk_buff, cb);
46131 + desc = (struct ubi32_eth_dma_desc *)pdata;
46132 + if (unlikely(!(desc->status & UBI32_ETH_VP_TX_OK))) {
46133 + dev->stats.tx_errors++;
46135 + dev->stats.tx_packets++;
46136 + dev->stats.tx_bytes += skb->len;
46138 + dev_kfree_skb_any(skb);
46139 + priv->regs->tx_dma_ring[priv->tx_tail] = NULL;
46140 + priv->tx_tail = (priv->tx_tail + 1) & TX_DMA_RING_MASK;
46144 + if (unlikely(priv->regs->status & UBI32_ETH_VP_STATUS_TX_Q_FULL)) {
46145 + spin_lock(&priv->lock);
46146 + if (priv->regs->status & UBI32_ETH_VP_STATUS_TX_Q_FULL) {
46147 + priv->regs->status &= ~UBI32_ETH_VP_STATUS_TX_Q_FULL;
46148 + netif_wake_queue(dev);
46150 + spin_unlock(&priv->lock);
46156 + * ubi32_eth_receive()
46157 + * To avoid locking overhead, this is called only
46158 + * by tasklet when not using NAPI, or
46159 + * by NAPI poll when using NAPI.
46160 + * return number of frames processed
46162 +static int ubi32_eth_receive(struct net_device *dev, int quota)
46164 + struct ubi32_eth_private *priv = netdev_priv(dev);
46165 + unsigned short rx_in = priv->regs->rx_in;
46166 + struct sk_buff *skb;
46167 + struct ubi32_eth_dma_desc *desc = NULL;
46168 + volatile void *pdata;
46170 + int extra_reserve_adj;
46171 + int extra_alloc = UBI32_ETH_RESERVE_SPACE + UBI32_ETH_TRASHED_MEMORY;
46172 + int replenish_cnt, count = 0;
46173 + int replenish_max = RX_DMA_MAX_QUEUE_SIZE;
46174 +#if (defined(CONFIG_ZONE_DMA) && defined(CONFIG_UBICOM32_OCM_FOR_SKB))
46175 + if (likely(dev == ubi32_eth_devices[0]))
46176 + replenish_max = min(ubi32_ocm_skbuf_max, RX_DMA_MAX_QUEUE_SIZE);;
46179 + if (unlikely(rx_in == priv->regs->rx_out))
46180 + priv->vp_stats.rx_q_full_cnt++;
46182 + priv->regs->int_status &= ~UBI32_ETH_VP_INT_RX;
46183 + while (priv->rx_tail != priv->regs->rx_out) {
46184 + if (unlikely(count == quota)) {
46185 + /* There is still frame pending to be processed */
46186 + priv->vp_stats.rx_throttle++;
46190 + pdata = priv->regs->rx_dma_ring[priv->rx_tail];
46191 + BUG_ON(pdata == NULL);
46193 + desc = (struct ubi32_eth_dma_desc *)pdata;
46194 + skb = container_of((void *)pdata, struct sk_buff, cb);
46196 + priv->regs->rx_dma_ring[priv->rx_tail] = NULL;
46197 + priv->rx_tail = ((priv->rx_tail + 1) & RX_DMA_RING_MASK);
46200 + * Check only RX_OK bit here.
46201 + * The rest of status word is used as timestamp
46203 + if (unlikely(!(desc->status & UBI32_ETH_VP_RX_OK))) {
46204 + dev->stats.rx_errors++;
46205 + dev_kfree_skb_any(skb);
46209 + skb_put(skb, desc->data_len);
46211 + skb->protocol = eth_type_trans(skb, dev);
46212 + skb->ip_summed = CHECKSUM_NONE;
46213 + dev->stats.rx_bytes += skb->len;
46214 + dev->stats.rx_packets++;
46215 +#ifndef UBICOM32_USE_NAPI
46218 + netif_receive_skb(skb);
46222 + /* fill in more descripor for VP*/
46223 + replenish_cnt = replenish_max -
46224 + ((RX_DMA_RING_SIZE + rx_in - priv->rx_tail) & RX_DMA_RING_MASK);
46225 + if (replenish_cnt > 0) {
46226 +#if (defined(CONFIG_ZONE_DMA) && defined(CONFIG_UBICOM32_OCM_FOR_SKB))
46228 + * black magic for perforamnce:
46229 + * Try to allocate skb from OCM only for first Ethernet I/F.
46230 + * Also limit number of RX buffers to 21 due to limited OCM.
46232 + if (likely(dev == ubi32_eth_devices[0])) {
46234 + skb = ubi32_alloc_skb_ocm(dev, RX_BUF_SIZE + extra_alloc);
46238 + /* set up dma descriptor */
46239 + ubi32_ocm_skbuf++;
46240 + desc = (struct ubi32_eth_dma_desc *)skb->cb;
46241 + extra_reserve_adj =
46242 + ((u32)skb->data + UBI32_ETH_RESERVE_SPACE + ETH_HLEN) &
46243 + (CACHE_LINE_SIZE - 1);
46244 + skb_reserve(skb, UBI32_ETH_RESERVE_SPACE - extra_reserve_adj);
46245 + desc->data_pointer = skb->data;
46246 + desc->buffer_len = RX_BUF_SIZE + UBI32_ETH_TRASHED_MEMORY;
46247 + desc->data_len = 0;
46248 + desc->status = 0;
46249 + priv->regs->rx_dma_ring[rx_in] = desc;
46250 + rx_in = (rx_in + 1) & RX_DMA_RING_MASK;
46251 + } while (--replenish_cnt > 0);
46255 + while (replenish_cnt-- > 0) {
46256 + skb = ubi32_alloc_skb(dev, RX_BUF_SIZE + extra_alloc);
46258 + priv->vp_stats.rx_alloc_err++;
46261 + /* set up dma descriptor */
46262 + ubi32_ddr_skbuf++;
46263 + desc = (struct ubi32_eth_dma_desc *)skb->cb;
46264 + extra_reserve_adj =
46265 + ((u32)skb->data + UBI32_ETH_RESERVE_SPACE + ETH_HLEN) &
46266 + (CACHE_LINE_SIZE - 1);
46267 + skb_reserve(skb, UBI32_ETH_RESERVE_SPACE - extra_reserve_adj);
46268 + desc->data_pointer = skb->data;
46269 + desc->buffer_len = RX_BUF_SIZE + UBI32_ETH_TRASHED_MEMORY;
46270 + desc->data_len = 0;
46271 + desc->status = 0;
46272 + priv->regs->rx_dma_ring[rx_in] = desc;
46273 + rx_in = (rx_in + 1) & RX_DMA_RING_MASK;
46277 + priv->regs->rx_in = rx_in;
46278 + ubicom32_set_interrupt(priv->vp_int_bit);
46281 + if (likely(count > 0)) {
46282 + dev->last_rx = jiffies;
46287 +#ifdef UBICOM32_USE_NAPI
46288 +static int ubi32_eth_napi_poll(struct napi_struct *napi, int budget)
46290 + struct ubi32_eth_private *priv = container_of(napi, struct ubi32_eth_private, napi);
46291 + struct net_device *dev = priv->dev;
46294 + if (priv->tx_tail != priv->regs->tx_out) {
46295 + ubi32_eth_tx_done(dev);
46298 + count = ubi32_eth_receive(dev, budget);
46300 + if (count < budget) {
46301 + napi_complete(napi);
46302 + priv->regs->int_mask |= (UBI32_ETH_VP_INT_RX | UBI32_ETH_VP_INT_TX);
46303 + if ((priv->rx_tail != priv->regs->rx_out) || (priv->tx_tail != priv->regs->tx_out)) {
46304 + if (napi_reschedule(napi)) {
46305 + priv->regs->int_mask = 0;
46313 +static void ubi32_eth_do_tasklet(unsigned long arg)
46315 + struct net_device *dev = (struct net_device *)arg;
46316 + struct ubi32_eth_private *priv = netdev_priv(dev);
46318 + if (priv->tx_tail != priv->regs->tx_out) {
46319 + ubi32_eth_tx_done(dev);
46322 + /* always call receive to process new RX frame as well as replenish RX buffers */
46323 + ubi32_eth_receive(dev, UBI32_RX_BOUND);
46325 + priv->regs->int_mask |= (UBI32_ETH_VP_INT_RX | UBI32_ETH_VP_INT_TX);
46326 + if ((priv->rx_tail != priv->regs->rx_out) || (priv->tx_tail != priv->regs->tx_out)) {
46327 + priv->regs->int_mask = 0;
46328 + tasklet_schedule(&priv->tsk);
46333 +#if defined(UBICOM32_USE_POLLING)
46334 +static struct timer_list eth_poll_timer;
46336 +static void ubi32_eth_poll(unsigned long arg)
46338 + struct net_device *dev;
46339 + struct ubi32_eth_private *priv;
46342 + for (i = 0; i < UBI32_ETH_NUM_OF_DEVICES; i++) {
46343 + dev = ubi32_eth_devices[i];
46344 + if (dev && (dev->flags & IFF_UP)) {
46345 + priv = netdev_priv(dev);
46346 +#ifdef UBICOM32_USE_NAPI
46347 + napi_schedule(&priv->napi);
46349 + tasklet_schedule(&priv->tsk);
46354 + eth_poll_timer.expires = jiffies + 2;
46355 + add_timer(ð_poll_timer);
46359 +static irqreturn_t ubi32_eth_interrupt(int irq, void *dev_id)
46361 + struct ubi32_eth_private *priv;
46363 + struct net_device *dev = (struct net_device *)dev_id;
46364 + BUG_ON(irq != dev->irq);
46366 + priv = netdev_priv(dev);
46367 + if (unlikely(!(priv->regs->int_status & priv->regs->int_mask))) {
46372 + * Disable port interrupt
46374 +#ifdef UBICOM32_USE_NAPI
46375 + if (napi_schedule_prep(&priv->napi)) {
46376 + priv->regs->int_mask = 0;
46377 + __napi_schedule(&priv->napi);
46380 + priv->regs->int_mask = 0;
46381 + tasklet_schedule(&priv->tsk);
46383 + return IRQ_HANDLED;
46390 +static int ubi32_eth_open(struct net_device *dev)
46392 + struct ubi32_eth_private *priv = netdev_priv(dev);
46395 + printk(KERN_INFO "eth open %s\n",dev->name);
46396 +#ifndef UBICOM32_USE_POLLING
46397 + /* request_region() */
46398 + err = request_irq(dev->irq, ubi32_eth_interrupt, IRQF_DISABLED, dev->name, dev);
46400 + printk(KERN_WARNING "fail to request_irq %d\n",err);
46404 +#ifdef UBICOM32_USE_NAPI
46405 + napi_enable(&priv->napi);
46407 + tasklet_init(&priv->tsk, ubi32_eth_do_tasklet, (unsigned long)dev);
46410 + /* call receive to supply RX buffers */
46411 + ubi32_eth_receive(dev, RX_DMA_MAX_QUEUE_SIZE);
46413 + /* check phy status and call netif_carrier_on */
46414 + ubi32_eth_vp_rxtx_enable(dev);
46415 + netif_start_queue(dev);
46419 +static int ubi32_eth_close(struct net_device *dev)
46421 + struct ubi32_eth_private *priv = netdev_priv(dev);
46422 + volatile void *pdata;
46423 + struct sk_buff *skb;
46425 +#ifndef UBICOM32_USE_POLLING
46426 + free_irq(dev->irq, dev);
46428 + netif_stop_queue(dev); /* can't transmit any more */
46429 +#ifdef UBICOM32_USE_NAPI
46430 + napi_disable(&priv->napi);
46432 + tasklet_kill(&priv->tsk);
46434 + ubi32_eth_vp_rxtx_stop(dev);
46439 + while (priv->rx_tail != priv->regs->rx_in) {
46440 + pdata = priv->regs->rx_dma_ring[priv->rx_tail];
46441 + skb = container_of((void *)pdata, struct sk_buff, cb);
46442 + priv->regs->rx_dma_ring[priv->rx_tail] = NULL;
46443 + dev_kfree_skb_any(skb);
46444 + priv->rx_tail = ((priv->rx_tail + 1) & RX_DMA_RING_MASK);
46446 + priv->regs->rx_in = 0;
46447 + priv->regs->rx_out = priv->regs->rx_in;
46448 + priv->rx_tail = priv->regs->rx_in;
46453 + BUG_ON(priv->regs->tx_out != priv->regs->tx_in);
46454 + ubi32_eth_tx_done(dev);
46455 + BUG_ON(priv->tx_tail != priv->regs->tx_in);
46456 + priv->regs->tx_in = 0;
46457 + priv->regs->tx_out = priv->regs->tx_in;
46458 + priv->tx_tail = priv->regs->tx_in;
46464 + * ubi32_eth_set_config
46466 +static int ubi32_eth_set_config(struct net_device *dev, struct ifmap *map)
46468 + /* if must to down to config it */
46469 + printk(KERN_INFO "set_config %x\n", dev->flags);
46470 + if (dev->flags & IFF_UP)
46473 + /* I/O and IRQ can not be changed */
46474 + if (map->base_addr != dev->base_addr) {
46475 + printk(KERN_WARNING "%s: Can't change I/O address\n", dev->name);
46476 + return -EOPNOTSUPP;
46479 +#ifndef UBICOM32_USE_POLLING
46480 + if (map->irq != dev->irq) {
46481 + printk(KERN_WARNING "%s: Can't change IRQ\n", dev->name);
46482 + return -EOPNOTSUPP;
46486 + /* ignore other fields */
46490 +static int ubi32_eth_start_xmit(struct sk_buff *skb, struct net_device *dev)
46492 + struct ubi32_eth_private *priv = netdev_priv(dev);
46493 + struct ubi32_eth_dma_desc *desc = NULL;
46494 + unsigned short space, tx_in;
46496 + tx_in = priv->regs->tx_in;
46498 + dev->trans_start = jiffies; /* save the timestamp */
46499 + space = TX_DMA_RING_MASK - ((TX_DMA_RING_SIZE + tx_in - priv->tx_tail) & TX_DMA_RING_MASK);
46501 + if (unlikely(space == 0)) {
46502 + if (!(priv->regs->status & UBI32_ETH_VP_STATUS_TX_Q_FULL)) {
46503 + spin_lock(&priv->lock);
46504 + if (!(priv->regs->status & UBI32_ETH_VP_STATUS_TX_Q_FULL)) {
46505 + priv->regs->status |= UBI32_ETH_VP_STATUS_TX_Q_FULL;
46506 + priv->vp_stats.tx_q_full_cnt++;
46507 + netif_stop_queue(dev);
46509 + spin_unlock(&priv->lock);
46512 + /* give both HW and this driver an extra trigger */
46513 + priv->regs->int_mask |= UBI32_ETH_VP_INT_TX;
46514 +#ifndef UBICOM32_USE_POLLING
46515 + ubicom32_set_interrupt(dev->irq);
46517 + ubicom32_set_interrupt(priv->vp_int_bit);
46519 + return NETDEV_TX_BUSY;
46522 + /*still have room */
46523 + desc = (struct ubi32_eth_dma_desc *)skb->cb;
46524 + desc->data_pointer = skb->data;
46525 + desc->data_len = skb->len;
46526 + priv->regs->tx_dma_ring[tx_in] = desc;
46527 + tx_in = ((tx_in + 1) & TX_DMA_RING_MASK);
46529 + priv->regs->tx_in = tx_in;
46530 + /* kick the HRT */
46531 + ubicom32_set_interrupt(priv->vp_int_bit);
46533 + return NETDEV_TX_OK;
46537 + * Deal with a transmit timeout.
46539 +static void ubi32_eth_tx_timeout (struct net_device *dev)
46541 + struct ubi32_eth_private *priv = netdev_priv(dev);
46542 + dev->stats.tx_errors++;
46543 + priv->regs->int_mask |= UBI32_ETH_VP_INT_TX;
46544 +#ifndef UBICOM32_USE_POLLING
46545 + ubicom32_set_interrupt(dev->irq);
46547 + ubicom32_set_interrupt(priv->vp_int_bit);
46550 +static int ubi32_eth_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
46552 + struct ubi32_eth_private *priv = netdev_priv(dev);
46553 + struct mii_ioctl_data *data = if_mii(rq);
46555 + printk(KERN_INFO "ioctl %s, %d\n", dev->name, cmd);
46557 + case SIOCGMIIPHY:
46558 + data->phy_id = 0;
46561 + case SIOCGMIIREG:
46562 + if ((data->reg_num & 0x1F) == MII_BMCR) {
46563 + /* Make up MII control register value from what we know */
46564 + data->val_out = 0x0000
46565 + | ((priv->regs->status & UBI32_ETH_VP_STATUS_DUPLEX)
46566 + ? BMCR_FULLDPLX : 0)
46567 + | ((priv->regs->status & UBI32_ETH_VP_STATUS_SPEED100)
46568 + ? BMCR_SPEED100 : 0)
46569 + | ((priv->regs->status & UBI32_ETH_VP_STATUS_SPEED1000)
46570 + ? BMCR_SPEED1000 : 0);
46571 + } else if ((data->reg_num & 0x1F) == MII_BMSR) {
46572 + /* Make up MII status register value from what we know */
46574 + (BMSR_100FULL|BMSR_100HALF|BMSR_10FULL|BMSR_10HALF)
46575 + | ((priv->regs->status & UBI32_ETH_VP_STATUS_LINK)
46576 + ? BMSR_LSTATUS : 0);
46582 + case SIOCSMIIREG:
46583 + return -EOPNOTSUPP;
46587 + return -EOPNOTSUPP;
46594 + * Return statistics to the caller
46596 +static struct net_device_stats *ubi32_eth_get_stats(struct net_device *dev)
46598 + return &dev->stats;
46602 +static int ubi32_eth_change_mtu(struct net_device *dev, int new_mtu)
46604 + struct ubi32_eth_private *priv = netdev_priv(dev);
46605 + unsigned long flags;
46607 + if ((new_mtu < 68) || (new_mtu > 1500))
46610 + spin_lock_irqsave(&priv->lock, flags);
46611 + dev->mtu = new_mtu;
46612 + spin_unlock_irqrestore(&priv->lock, flags);
46613 + printk(KERN_INFO "set mtu to %d", new_mtu);
46618 + * ubi32_eth_cleanup: unload the module
46620 +void ubi32_eth_cleanup(void)
46622 + struct ubi32_eth_private *priv;
46623 + struct net_device *dev;
46626 + for (i = 0; i < UBI32_ETH_NUM_OF_DEVICES; i++) {
46627 + dev = ubi32_eth_devices[i];
46629 + priv = netdev_priv(dev);
46630 + kfree(priv->regs->tx_dma_ring);
46631 + unregister_netdev(dev);
46632 + free_netdev(dev);
46633 + ubi32_eth_devices[i] = NULL;
46638 +int ubi32_eth_init_module(void)
46640 + struct ethtionode *eth_node;
46641 + struct net_device *dev;
46642 + struct ubi32_eth_private *priv;
46646 + * Device allocation.
46649 + for (i = 0; i < UBI32_ETH_NUM_OF_DEVICES; i++) {
46651 + * See if the eth_vp is in the device tree.
46653 + eth_node = (struct ethtionode *)devtree_find_node(eth_if_name[i]);
46655 + printk(KERN_INFO "%s does not exist\n", eth_if_name[i]);
46659 + eth_node->tx_dma_ring = (struct ubi32_eth_dma_desc **)kmalloc(
46660 + sizeof(struct ubi32_eth_dma_desc *) *
46661 + (TX_DMA_RING_SIZE + RX_DMA_RING_SIZE),
46662 + GFP_ATOMIC | __GFP_NOWARN | __GFP_NORETRY | GFP_DMA);
46664 + if (eth_node->tx_dma_ring == NULL) {
46665 + eth_node->tx_dma_ring = (struct ubi32_eth_dma_desc **)kmalloc(
46666 + sizeof(struct ubi32_eth_dma_desc *) *
46667 + (TX_DMA_RING_SIZE + RX_DMA_RING_SIZE), GFP_KERNEL);
46668 + printk(KERN_INFO "fail to allocate from OCM\n");
46671 + if (!eth_node->tx_dma_ring) {
46675 + eth_node->rx_dma_ring = eth_node->tx_dma_ring + TX_DMA_RING_SIZE;
46676 + eth_node->tx_sz = TX_DMA_RING_SIZE - 1;
46677 + eth_node->rx_sz = RX_DMA_RING_SIZE - 1;
46679 + dev = alloc_etherdev(sizeof(struct ubi32_eth_private));
46681 + kfree(eth_node->tx_dma_ring);
46685 + priv = netdev_priv(dev);
46689 + * This just fill in some default Ubicom MAC address
46691 + memcpy(dev->dev_addr, mac_addr[i], ETH_ALEN);
46692 + memset(dev->broadcast, 0xff, ETH_ALEN);
46694 + priv->regs = eth_node;
46695 + priv->regs->command = 0;
46696 + priv->regs->int_mask = 0;
46697 + priv->regs->int_status = 0;
46698 + priv->regs->tx_out = 0;
46699 + priv->regs->rx_out = 0;
46700 + priv->regs->tx_in = 0;
46701 + priv->regs->rx_in = 0;
46702 + priv->rx_tail = 0;
46703 + priv->tx_tail = 0;
46705 + priv->vp_int_bit = eth_node->dn.sendirq;
46706 + dev->irq = eth_node->dn.recvirq;
46708 + spin_lock_init(&priv->lock);
46710 + dev->open = ubi32_eth_open;
46711 + dev->stop = ubi32_eth_close;
46712 + dev->hard_start_xmit = ubi32_eth_start_xmit;
46713 + dev->tx_timeout = ubi32_eth_tx_timeout;
46714 + dev->watchdog_timeo = UBI32_ETH_VP_TX_TIMEOUT;
46716 + dev->set_config = ubi32_eth_set_config;
46717 + dev->do_ioctl = ubi32_eth_ioctl;
46718 + dev->get_stats = ubi32_eth_get_stats;
46719 + dev->change_mtu = ubi32_eth_change_mtu;
46720 +#ifdef UBICOM32_USE_NAPI
46721 + netif_napi_add(dev, &priv->napi, ubi32_eth_napi_poll, UBI32_ETH_NAPI_WEIGHT);
46723 + err = register_netdev(dev);
46725 + printk(KERN_WARNING "Failed to register netdev %s\n", eth_if_name[i]);
46726 + //release_region();
46727 + free_netdev(dev);
46728 + kfree(eth_node->tx_dma_ring);
46732 + ubi32_eth_devices[i] = dev;
46733 + printk(KERN_INFO "%s vp_base:0x%p, tio_int:%d irq:%d feature:0x%lx\n",
46734 + dev->name, priv->regs, eth_node->dn.sendirq, dev->irq, dev->features);
46738 + ubi32_eth_cleanup();
46742 + if (!ubi32_eth_devices[0] && !ubi32_eth_devices[1]) {
46746 +#if defined(UBICOM32_USE_POLLING)
46747 + init_timer(ð_poll_timer);
46748 + eth_poll_timer.function = ubi32_eth_poll;
46749 + eth_poll_timer.data = (unsigned long)0;
46750 + eth_poll_timer.expires = jiffies + 2;
46751 + add_timer(ð_poll_timer);
46757 +module_init(ubi32_eth_init_module);
46758 +module_exit(ubi32_eth_cleanup);
46760 +MODULE_AUTHOR("Kan Yan, Greg Ren");
46761 +MODULE_LICENSE("GPL");
46762 diff -ruN linux-2.6.30.10/drivers/net/ubi32-eth.h linux-2.6.30.10-ubi/drivers/net/ubi32-eth.h
46763 --- linux-2.6.30.10/drivers/net/ubi32-eth.h 1970-01-01 02:00:00.000000000 +0200
46764 +++ linux-2.6.30.10-ubi/drivers/net/ubi32-eth.h 2009-12-11 11:45:18.000000000 +0200
46767 + * drivers/net/ubi32-eth.h
46768 + * Ubicom32 ethernet TIO interface driver definitions.
46770 + * (C) Copyright 2009, Ubicom, Inc.
46772 + * This file is part of the Ubicom32 Linux Kernel Port.
46774 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
46775 + * it and/or modify it under the terms of the GNU General Public License
46776 + * as published by the Free Software Foundation, either version 2 of the
46777 + * License, or (at your option) any later version.
46779 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
46780 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
46781 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
46782 + * the GNU General Public License for more details.
46784 + * You should have received a copy of the GNU General Public License
46785 + * along with the Ubicom32 Linux Kernel Port. If not,
46786 + * see <http://www.gnu.org/licenses/>.
46788 + * Ubicom32 implementation derived from (with many thanks):
46793 +#ifndef _UBI32_ETH_H
46794 +#define _UBI32_ETH_H
46796 +#include <asm/devtree.h>
46798 +#define UBI32_ETH_NUM_OF_DEVICES 2
46801 + * Number of bytes trashed beyond the packet data.
46803 +#define UBI32_ETH_TRASHED_MEMORY (CACHE_LINE_SIZE + ETH_HLEN - 1)
46806 + * Linux already reserves NET_SKB_PAD bytes of headroom in each sk_buff.
46807 + * We want to be able to reserve at least one cache line to align Ethernet
46808 + * and IP header to cache line.
46809 + * Note that the TIO expects a CACHE_LINE_SIZE - ETH_HLEN aligned Ethernet
46810 + * header, while satisfies NET_IP_ALIGN (= 2) automatically.
46811 + * (NET_SKB_PAD is 16, NET_IP_ALIGN is 2, CACHE_LINE_SIZE is 32).
46812 + * You can add more space by making UBI32_ETH_RESERVE_EXTRA != 0.
46814 +#define UBI32_ETH_RESERVE_EXTRA (1 * CACHE_LINE_SIZE)
46815 +#define UBI32_ETH_RESERVE_SPACE (UBI32_ETH_RESERVE_EXTRA + CACHE_LINE_SIZE)
46817 +struct ubi32_eth_dma_desc {
46818 + volatile void *data_pointer; /* pointer to the buffer */
46819 + volatile u16 buffer_len; /* the buffer size */
46820 + volatile u16 data_len; /* actual frame length */
46821 + volatile u32 status; /* bit0: status to be update by VP; bit[31:1] time stamp */
46824 +#define TX_DMA_RING_SIZE (1<<8)
46825 +#define TX_DMA_RING_MASK (TX_DMA_RING_SIZE - 1)
46826 +#define RX_DMA_RING_SIZE (1<<8)
46827 +#define RX_DMA_RING_MASK (RX_DMA_RING_SIZE - 1)
46829 +#define RX_DMA_MAX_QUEUE_SIZE (RX_DMA_RING_SIZE - 1) /* no more than (RX_DMA_RING_SIZE - 1) */
46830 +#define RX_MAX_PKT_SIZE (ETH_DATA_LEN + ETH_HLEN + VLAN_HLEN)
46831 +#define RX_MIN_PKT_SIZE ETH_ZLEN
46832 +#define RX_BUF_SIZE (RX_MAX_PKT_SIZE + VLAN_HLEN) /* allow double VLAN tag */
46834 +#define UBI32_ETH_VP_TX_TIMEOUT (10*HZ)
46836 +struct ubi32_eth_vp_stats {
46837 + u32 rx_alloc_err;
46838 + u32 tx_q_full_cnt;
46839 + u32 rx_q_full_cnt;
46843 +struct ubi32_eth_private {
46844 + struct net_device *dev;
46845 + struct ubi32_eth_vp_stats vp_stats;
46847 +#ifdef UBICOM32_USE_NAPI
46848 + struct napi_struct napi;
46850 + struct tasklet_struct tsk;
46852 + struct ethtionode *regs;
46858 +struct ethtionode {
46859 + struct devtree_node dn;
46860 + volatile u16 command;
46861 + volatile u16 status;
46862 + volatile u16 int_mask; /* interrupt mask */
46863 + volatile u16 int_status; /* interrupt mask */
46864 + volatile u16 tx_in; /* owned by driver */
46865 + volatile u16 tx_out; /* owned by vp */
46866 + volatile u16 rx_in; /* owned by driver */
46867 + volatile u16 rx_out; /* owned by vp */
46868 + u16 tx_sz; /* owned by driver */
46869 + u16 rx_sz; /* owned by driver */
46870 + struct ubi32_eth_dma_desc **tx_dma_ring;
46871 + struct ubi32_eth_dma_desc **rx_dma_ring;
46874 +#define UBI32_ETH_VP_STATUS_LINK (1<<0)
46875 +#define UBI32_ETH_VP_STATUS_SPEED100 (0x1<<1)
46876 +#define UBI32_ETH_VP_STATUS_SPEED1000 (0x1<<2)
46877 +#define UBI32_ETH_VP_STATUS_DUPLEX (0x1<<3)
46878 +#define UBI32_ETH_VP_STATUS_FLOW_CTRL (0x1<<4)
46880 +#define UBI32_ETH_VP_STATUS_RX_STATE (0x1<<5)
46881 +#define UBI32_ETH_VP_STATUS_TX_STATE (0x1<<6)
46883 +#define UBI32_ETH_VP_STATUS_TX_Q_FULL (1<<8)
46885 +#define UBI32_ETH_VP_INT_RX (1<<0)
46886 +#define UBI32_ETH_VP_INT_TX (1<<1)
46888 +#define UBI32_ETH_VP_CMD_RX_ENABLE (1<<0)
46889 +#define UBI32_ETH_VP_CMD_TX_ENABLE (1<<1)
46891 +#define UBI32_ETH_VP_RX_OK (1<<0)
46892 +#define UBI32_ETH_VP_TX_OK (1<<1)
46894 +#define UBI32_TX_BOUND TX_DMA_RING_SIZE
46895 +#define UBI32_RX_BOUND 64
46896 +#define UBI32_ETH_NAPI_WEIGHT 64 /* for GigE */
46898 diff -ruN linux-2.6.30.10/drivers/net/usb/asix.c linux-2.6.30.10-ubi/drivers/net/usb/asix.c
46899 --- linux-2.6.30.10/drivers/net/usb/asix.c 2009-12-04 08:00:07.000000000 +0200
46900 +++ linux-2.6.30.10-ubi/drivers/net/usb/asix.c 2009-12-11 11:45:18.000000000 +0200
46901 @@ -319,14 +319,33 @@
46902 /* get the packet length */
46903 size = (u16) (header & 0x0000ffff);
46905 - if ((skb->len) - ((size + 1) & 0xfffe) == 0)
46906 + if ((skb->len) - ((size + 1) & 0xfffe) == 0) {
46907 +#ifndef HAVE_EFFICIENT_UNALIGNED_ACCESS
46908 + if (((u32)packet & 0x02) == 0) {
46909 + memmove(packet - 2, packet, size);
46917 if (size > ETH_FRAME_LEN) {
46918 deverr(dev,"asix_rx_fixup() Bad RX Length %d", size);
46921 ax_skb = skb_clone(skb, GFP_ATOMIC);
46923 +#ifndef HAVE_EFFICIENT_UNALIGNED_ACCESS
46924 + if (((u32)packet & 0x02) == 0) {
46925 + memmove(packet - 2, packet, size);
46926 + ax_skb->data = packet - 2;
46928 + ax_skb->data = packet;
46931 + ax_skb->data = packet;
46933 ax_skb->len = size;
46934 ax_skb->data = packet;
46935 skb_set_tail_pointer(ax_skb, size);
46936 @@ -1125,13 +1144,19 @@
46937 mode = AX88178_MEDIUM_DEFAULT;
46939 if (ecmd.speed == SPEED_1000)
46940 +#ifdef HAVE_EFFICIENT_UNALIGNED_ACCESS
46941 mode |= AX_MEDIUM_GM;
46943 + mode |= AX_MEDIUM_GM | AX_MEDIUM_ENCK;
46945 else if (ecmd.speed == SPEED_100)
46946 mode |= AX_MEDIUM_PS;
46948 mode &= ~(AX_MEDIUM_PS | AX_MEDIUM_GM);
46950 +#ifdef HAVE_EFFICIENT_UNALIGNED_ACCESS
46951 mode |= AX_MEDIUM_ENCK;
46954 if (ecmd.duplex == DUPLEX_FULL)
46955 mode |= AX_MEDIUM_FD;
46956 diff -ruN linux-2.6.30.10/drivers/oprofile/cpu_buffer.c linux-2.6.30.10-ubi/drivers/oprofile/cpu_buffer.c
46957 --- linux-2.6.30.10/drivers/oprofile/cpu_buffer.c 2009-12-04 08:00:07.000000000 +0200
46958 +++ linux-2.6.30.10-ubi/drivers/oprofile/cpu_buffer.c 2009-12-11 11:45:18.000000000 +0200
46959 @@ -328,10 +328,10 @@
46963 -__oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs,
46964 - unsigned long event, int is_kernel)
46965 +__oprofile_add_ext_sample_cpu(unsigned long pc, struct pt_regs * const regs,
46966 + unsigned long event, int is_kernel, int cpu)
46968 - struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(cpu_buffer);
46969 + struct oprofile_cpu_buffer *cpu_buf = &per_cpu(cpu_buffer, cpu);
46970 unsigned long backtrace = oprofile_backtrace_depth;
46973 @@ -353,7 +353,8 @@
46974 void oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs,
46975 unsigned long event, int is_kernel)
46977 - __oprofile_add_ext_sample(pc, regs, event, is_kernel);
46978 + __oprofile_add_ext_sample_cpu(pc, regs, event,
46979 + is_kernel, smp_processor_id());
46982 void oprofile_add_sample(struct pt_regs * const regs, unsigned long event)
46983 @@ -361,7 +362,8 @@
46984 int is_kernel = !user_mode(regs);
46985 unsigned long pc = profile_pc(regs);
46987 - __oprofile_add_ext_sample(pc, regs, event, is_kernel);
46988 + __oprofile_add_ext_sample_cpu(pc, regs, event,
46989 + is_kernel, smp_processor_id());
46993 diff -ruN linux-2.6.30.10/drivers/pci/Makefile linux-2.6.30.10-ubi/drivers/pci/Makefile
46994 --- linux-2.6.30.10/drivers/pci/Makefile 2009-12-04 08:00:07.000000000 +0200
46995 +++ linux-2.6.30.10-ubi/drivers/pci/Makefile 2009-12-11 11:45:18.000000000 +0200
46997 obj-$(CONFIG_MIPS) += setup-bus.o setup-irq.o
46998 obj-$(CONFIG_X86_VISWS) += setup-irq.o
46999 obj-$(CONFIG_MN10300) += setup-bus.o
47000 +obj-$(CONFIG_UBICOM32) += setup-bus.o setup-irq.o
47003 # ACPI Related PCI FW Functions
47005 obj-$(CONFIG_ACPI) += pci-acpi.o
47006 diff -ruN linux-2.6.30.10/drivers/serial/Kconfig linux-2.6.30.10-ubi/drivers/serial/Kconfig
47007 --- linux-2.6.30.10/drivers/serial/Kconfig 2009-12-04 08:00:07.000000000 +0200
47008 +++ linux-2.6.30.10-ubi/drivers/serial/Kconfig 2009-12-11 11:45:19.000000000 +0200
47009 @@ -871,6 +871,57 @@
47010 console (the system console is the device which receives all kernel
47011 messages and warnings and which allows logins in single user mode).
47013 +config SERIAL_UBI32_UARTTIO
47014 + tristate "Ubicom UARTTIO support"
47015 + depends on UBICOM32=y
47016 + select SERIAL_CORE
47019 + Add support for the Ubicom virtual peripherial serial interface.
47021 +config SERIAL_UBI32_UARTTIO_NR_UARTS
47022 + int "Maximum number of UARTTIO virtual serial ports"
47023 + depends on SERIAL_UBI32_UARTTIO
47026 + Set this to the maximum number of serial ports you want the driver to support.
47028 +config SERIAL_UBI32_UARTTIO_CONSOLE
47029 + tristate "Ubicom UARTTIO console support"
47030 + depends on SERIAL_UBI32_UARTTIO=y
47031 + select SERIAL_CORE_CONSOLE
47034 + Add support for console on the Ubicom virtual peripherial serial interface.
47036 +config SERIAL_UBI32_SERDES
47037 + bool "Ubicom serial port support"
47038 + depends on UBICOM32=y
47039 + select SERIAL_CORE
47042 + Add support for the Ubicom serial interface.
47044 +config SERIAL_UBI32_SERDES_CONSOLE
47045 + bool "Ubicom serial console support"
47046 + depends on SERIAL_UBI32_SERDES=y
47047 + select SERIAL_CORE_CONSOLE
47050 +config SERIAL_UBI32_MAILBOX
47051 + bool "Ubicom mailbox support"
47052 + depends on UBICOM32=y
47053 + select SERIAL_CORE
47056 + Add support for the Ubicom mailbox interface.
47058 +config SERIAL_UBI32_MAILBOX_CONSOLE
47059 + bool "Ubicom mailbox console support"
47060 + depends on SERIAL_UBI32_MAILBOX=y
47061 + select SERIAL_CORE_CONSOLE
47064 config SERIAL_SUNCORE
47067 diff -ruN linux-2.6.30.10/drivers/serial/Makefile linux-2.6.30.10-ubi/drivers/serial/Makefile
47068 --- linux-2.6.30.10/drivers/serial/Makefile 2009-12-04 08:00:07.000000000 +0200
47069 +++ linux-2.6.30.10-ubi/drivers/serial/Makefile 2009-12-11 11:45:19.000000000 +0200
47071 obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o
47072 obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o
47073 obj-$(CONFIG_SERIAL_QE) += ucc_uart.o
47074 +obj-$(CONFIG_SERIAL_UBI32_SERDES) += ubi32_serdes.o
47075 +obj-$(CONFIG_SERIAL_UBI32_UARTTIO) += ubi32_uarttio.o
47076 +obj-$(CONFIG_SERIAL_UBI32_MAILBOX) += ubi32_mailbox.o
47077 diff -ruN linux-2.6.30.10/drivers/serial/ubi32_mailbox.c linux-2.6.30.10-ubi/drivers/serial/ubi32_mailbox.c
47078 --- linux-2.6.30.10/drivers/serial/ubi32_mailbox.c 1970-01-01 02:00:00.000000000 +0200
47079 +++ linux-2.6.30.10-ubi/drivers/serial/ubi32_mailbox.c 2009-12-11 11:45:19.000000000 +0200
47082 + * drivers/serial/ubi32_mailbox.c
47083 + * Ubicom32 On-Chip Mailbox Driver
47085 + * (C) Copyright 2009, Ubicom, Inc.
47087 + * This file is part of the Ubicom32 Linux Kernel Port.
47089 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
47090 + * it and/or modify it under the terms of the GNU General Public License
47091 + * as published by the Free Software Foundation, either version 2 of the
47092 + * License, or (at your option) any later version.
47094 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
47095 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
47096 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
47097 + * the GNU General Public License for more details.
47099 + * You should have received a copy of the GNU General Public License
47100 + * along with the Ubicom32 Linux Kernel Port. If not,
47101 + * see <http://www.gnu.org/licenses/>.
47103 + * Ubicom32 implementation derived from (with many thanks):
47108 +#include <linux/module.h>
47109 +#include <linux/ioport.h>
47110 +#include <linux/init.h>
47111 +#include <linux/console.h>
47112 +#include <linux/sysrq.h>
47113 +#include <linux/platform_device.h>
47114 +#include <linux/tty.h>
47115 +#include <linux/tty_flip.h>
47116 +#include <linux/serial_core.h>
47118 +#include <asm/ip5000.h>
47120 +#define SERIAL_UBICOM_BAUDRATE 115200
47121 +#define SERIAL_UBICOM_DATA_BIT 8 /* Fixed parameter - do not change */
47122 +#define SERIAL_UBICOM_PAR_BIT 0 /* Fixed parameter - do not change */
47123 +#define SERIAL_UBICOM_STOP_BIT 1 /* Fixed parameter - do not change */
47125 +/* UART name and device definitions */
47126 +#define UBI32_MAILBOX_NAME "ttyUM" // XXX
47127 +#define UBI32_MAILBOX_MAJOR 207 // XXX
47128 +#define UBI32_MAILBOX_MINOR 64
47130 +#define PORT_UBI32_MAILBOX 1235
47131 +#define NR_PORTS 1
47133 +#define get_sclk() 0
47135 +struct ubi32_mailbox_port {
47136 + struct uart_port port;
47138 + * NOTE (rkeller):
47139 + * the uart port is wrapped in another structure in case we need to hold more state than
47140 + * what we can hold in the uart_port.
47141 + * Not sure if we need this, I took over the concept from the blackfin driver.
47143 +} ubi32_mailbox_ports[NR_PORTS];
47145 +struct ubi32_mailbox_resource {
47146 + int uart_base_addr;
47148 +} ubi32_mailbox_resource[NR_PORTS] = {
47150 + * uart_base_addr has to be non-NULL because it is put in the uart_port membase.
47151 + * If membase if null the kernel skips the configuration and our port_type never gets set.
47153 + {ISD_MAILBOX_BASE, ISD_MAILBOX_INT}
47156 +static volatile struct ubicom32_isd_mailbox {
47157 + volatile u32_t in;
47158 + volatile u32_t out;
47159 + volatile u32_t status;
47160 +} *ubi32_mailbox = (struct ubicom32_isd_mailbox *)ISD_MAILBOX_BASE;
47162 +static void ubi32_mailbox_tx_chars(struct ubi32_mailbox_port *uart);
47164 +static void ubi32_mailbox_mctrl_check(struct ubi32_mailbox_port *uart);
47169 +static int mailbox_console_flg = TRUE;
47170 +static int num_timeouts = 0;
47173 + * dummy functions and defined to be able to compile the Blackfin code
47175 +#define UART_GET_LSR(port) (1)
47176 +#define UART_PUT_LSR(port, bits)
47177 +#define UART_CLEAR_LSR(port) (1)
47186 +#define UART_GET_LCR(port) (1)
47187 +#define UART_PUT_LCR(port, bits)
47194 +#define UART_GET_IER(port) (1)
47195 +#define UART_SET_IER(port, bits)
47196 +#define UART_CLEAR_IER(port, bits)
47199 +#define UART_GET_CHAR(port) ubi32_mailbox_get_char()
47200 +#define UART_PUT_CHAR(port, ch) ubi32_mailbox_put_char(ch)
47202 +#define UART_GET_DLL(port) 0
47203 +#define UART_PUT_DLL(port, ch)
47204 +#define UART_GET_DLH(port) 0
47205 +#define UART_PUT_DLH(port, ch)
47206 +#define UART_GET_GCTL(port) (0)
47207 +#define UART_PUT_GCTL(port, ch)
47211 + * ubi32_mailbox_get_char_avail()
47213 +static int ubi32_mailbox_get_char_avail(void)
47215 + return !(ubi32_mailbox->status & ISD_MAILBOX_STATUS_IN_EMPTY);
47219 + * ubi32_mailbox_get_char()
47221 +static u32_t ubi32_mailbox_get_char(void)
47223 + if (mailbox_console_flg == TRUE) {
47225 + * Mailbox console is connected.
47227 + while (ubi32_mailbox->status & ISD_MAILBOX_STATUS_IN_EMPTY);
47228 + return ubi32_mailbox->in & 0xff;
47232 + * Mailbox console was not connected.
47234 + if (ubi32_mailbox->status & ISD_MAILBOX_STATUS_IN_EMPTY) {
47239 + * Mailbox console is connecting.
47241 + mailbox_console_flg = TRUE;
47242 + num_timeouts = 0;
47243 + return ubi32_mailbox->in & 0xff;
47246 +#define MAILBOX_MAX_ATTEMPTS 1000000
47247 +#define MAILBOX_MAX_TIMEOUTS 5
47249 + * ubi32_mailbox_put_char()
47251 +static void ubi32_mailbox_put_char(u32_t v)
47254 + * Wait to be able to output.
47256 + u32_t num_attempts = 0;
47258 + if(mailbox_console_flg == TRUE) {
47259 + while(num_attempts++ < MAILBOX_MAX_ATTEMPTS) {
47260 + if(ubi32_mailbox->status & ISD_MAILBOX_STATUS_OUT_EMPTY) {
47266 + * If timed out more than 5 times on send, mailbox console is disconnected now.
47268 + if (num_attempts > MAILBOX_MAX_ATTEMPTS) {
47269 + if (num_timeouts++ > MAILBOX_MAX_TIMEOUTS) {
47270 + mailbox_console_flg = FALSE;
47276 + "pipe_flush 0 \n\t"
47277 + "pipe_flush 0 \n\t"
47278 + "pipe_flush 0 \n\t"
47279 + "pipe_flush 0 \n\t"
47280 + "pipe_flush 0 \n\t"
47281 + "pipe_flush 0 \n\t"
47282 + "pipe_flush 0 \n\t"
47285 + ubi32_mailbox->out = v & 0xff;
47288 +static void ubi32_mailbox_hw_init(struct ubi32_mailbox_port *uart)
47290 +// NOTE: It does not do any good to do these here because we are running on the linux hardware thread,
47291 +// and these have to be called on the ldsr thread.
47292 +// ubicom32_clear_interrupt(ISD_MAILBOX_INT);
47293 +// ubicom32_enable_interrupt(ISD_MAILBOX_INT);
47297 + * interrupts are disabled on entry
47299 +static void ubi32_mailbox_stop_tx(struct uart_port *port)
47301 +// struct ubi32_mailbox_port *uart = (struct ubi32_mailbox_port *)port;
47302 +// struct circ_buf *xmit = &uart->port.info->xmit;
47304 + while (!(UART_GET_LSR(uart) & TEMT))
47307 + /* Clear TFI bit */
47308 + UART_PUT_LSR(uart, TFI);
47309 + UART_CLEAR_IER(uart, ETBEI);
47313 + * port is locked and interrupts are disabled
47315 +static void ubi32_mailbox_start_tx(struct uart_port *port)
47317 + struct ubi32_mailbox_port *uart = (struct ubi32_mailbox_port *)port;
47319 + UART_SET_IER(uart, ETBEI);
47321 + ubi32_mailbox_tx_chars(uart);
47325 + * Interrupts are enabled
47327 +static void ubi32_mailbox_stop_rx(struct uart_port *port)
47329 +// struct ubi32_mailbox_port *uart = (struct ubi32_mailbox_port *)port;
47330 + UART_CLEAR_IER(uart, ERBFI);
47334 + * Set the modem control timer to fire immediately.
47336 +static void ubi32_mailbox_enable_ms(struct uart_port *port)
47340 +static void ubi32_mailbox_rx_chars(struct ubi32_mailbox_port *uart)
47342 + struct uart_info *info = uart->port.info;
47343 + struct tty_struct *tty = info->port.tty;
47344 + unsigned int status, ch, flg;
47346 + status = 0; // XXX? UART_GET_LSR(uart);
47347 + UART_CLEAR_LSR(uart);
47349 + ch = UART_GET_CHAR(uart);
47354 + uart->port.icount.rx++;
47356 + if (status & BI) {
47357 + uart->port.icount.brk++;
47358 + if (uart_handle_break(&uart->port))
47359 + goto ignore_char;
47360 + status &= ~(PE | FE);
47363 + uart->port.icount.parity++;
47365 + uart->port.icount.overrun++;
47367 + uart->port.icount.frame++;
47369 + status &= uart->port.read_status_mask;
47373 + else if (status & PE)
47374 + flg = TTY_PARITY;
47375 + else if (status & FE)
47378 + flg = TTY_NORMAL;
47380 + if (uart_handle_sysrq_char(&uart->port, ch))
47381 + goto ignore_char;
47383 + uart_insert_char(&uart->port, status, OE, ch, flg);
47386 + tty_flip_buffer_push(tty);
47389 +static void ubi32_mailbox_tx_chars(struct ubi32_mailbox_port *uart)
47391 + struct circ_buf *xmit = &uart->port.info->xmit;
47393 + if (uart->port.x_char) {
47394 + UART_PUT_CHAR(uart, uart->port.x_char);
47395 + uart->port.icount.tx++;
47396 + uart->port.x_char = 0;
47399 + * Check the modem control lines before
47400 + * transmitting anything.
47402 + ubi32_mailbox_mctrl_check(uart);
47404 + if (uart_circ_empty(xmit) || uart_tx_stopped(&uart->port)) {
47405 + ubi32_mailbox_stop_tx(&uart->port);
47409 + while ((UART_GET_LSR(uart) & THRE) && xmit->tail != xmit->head) {
47410 + UART_PUT_CHAR(uart, xmit->buf[xmit->tail]);
47411 + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
47412 + uart->port.icount.tx++;
47416 + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
47417 + uart_write_wakeup(&uart->port);
47419 + if (uart_circ_empty(xmit))
47420 + ubi32_mailbox_stop_tx(&uart->port);
47423 +static irqreturn_t ubi32_mailbox_isr(int irq, void *dev_id)
47425 + struct ubi32_mailbox_port *uart = dev_id;
47427 + spin_lock(&uart->port.lock);
47429 + //XXX?while (UART_GET_LSR(uart) & DR)
47434 + while (ubi32_mailbox_get_char_avail()) {
47435 + ubi32_mailbox_rx_chars(uart);
47442 + if (this_uart.tx_in == this_uart.tx_out) {
47443 + UBICOM32_IO_PORT(SERIAL_UBICOM_PORT)->int_mask &= ~IO_PORTX_INT_SERDES_TXBE;
47444 + } else if (UBICOM32_IO_PORT(SERIAL_UBICOM_PORT)->int_status & IO_PORTX_INT_SERDES_TXBE) {
47445 + uart_ubicom32_send(this_uart.tx_buf[this_uart.tx_out & (SERIAL_UBICOM_BUF_SIZE - 1)]);
47446 + this_uart.tx_out++;
47447 + UBICOM32_IO_PORT(SERIAL_UBICOM_PORT)->int_mask |= IO_PORTX_INT_SERDES_TXBE;
47451 + spin_unlock(&uart->port.lock);
47453 + return IRQ_HANDLED;
47456 +static irqreturn_t ubi32_mailbox_tx_int(int irq, void *dev_id)
47458 + struct ubi32_mailbox_port *uart = dev_id;
47460 + spin_lock(&uart->port.lock);
47461 + if (UART_GET_LSR(uart) & THRE)
47462 + ubi32_mailbox_tx_chars(uart);
47463 + spin_unlock(&uart->port.lock);
47465 + return IRQ_HANDLED;
47470 + * Return TIOCSER_TEMT when transmitter is not busy.
47472 +static unsigned int ubi32_mailbox_tx_empty(struct uart_port *port)
47474 +// struct ubi32_mailbox_port *uart = (struct ubi32_mailbox_port *)port;
47475 + unsigned short lsr;
47477 + lsr = UART_GET_LSR(uart);
47479 + return TIOCSER_TEMT;
47484 +static unsigned int ubi32_mailbox_get_mctrl(struct uart_port *port)
47486 + return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
47489 +static void ubi32_mailbox_set_mctrl(struct uart_port *port, unsigned int mctrl)
47494 + * Handle any change of modem status signal since we were last called.
47496 +static void ubi32_mailbox_mctrl_check(struct ubi32_mailbox_port *uart)
47501 + * Interrupts are always disabled.
47503 +static void ubi32_mailbox_break_ctl(struct uart_port *port, int break_state)
47505 +// struct ubi32_mailbox_port *uart = (struct ubi32_mailbox_port *)port;
47506 + u16 lcr = UART_GET_LCR(uart);
47511 + UART_PUT_LCR(uart, lcr);
47515 +static int ubi32_mailbox_startup(struct uart_port *port)
47517 + struct ubi32_mailbox_port *uart = (struct ubi32_mailbox_port *)port;
47519 + if (request_irq(uart->port.irq, ubi32_mailbox_isr, IRQF_DISABLED,
47520 + "UBI32_MAILBOX", uart)) {
47521 + printk(KERN_NOTICE "Unable to attach Ubicom32 SERDES interrupt\n");
47525 + UART_SET_IER(uart, ERBFI);
47529 +static void ubi32_mailbox_shutdown(struct uart_port *port)
47531 + struct ubi32_mailbox_port *uart = (struct ubi32_mailbox_port *)port;
47533 + free_irq(uart->port.irq, uart);
47537 +ubi32_mailbox_set_termios(struct uart_port *port, struct ktermios *termios,
47538 + struct ktermios *old)
47540 + struct ubi32_mailbox_port *uart = (struct ubi32_mailbox_port *)port;
47541 + unsigned long flags;
47542 + unsigned int baud, quot;
47543 + unsigned short val, ier, lsr, lcr = 0;
47545 + switch (termios->c_cflag & CSIZE) {
47559 + printk(KERN_ERR "%s: word lengh not supported\n",
47563 + if (termios->c_cflag & CSTOPB)
47565 + if (termios->c_cflag & PARENB)
47567 + if (!(termios->c_cflag & PARODD))
47569 + if (termios->c_cflag & CMSPAR)
47572 + port->read_status_mask = OE;
47573 + if (termios->c_iflag & INPCK)
47574 + port->read_status_mask |= (FE | PE);
47575 + if (termios->c_iflag & (BRKINT | PARMRK))
47576 + port->read_status_mask |= BI;
47579 + * Characters to ignore
47581 + port->ignore_status_mask = 0;
47582 + if (termios->c_iflag & IGNPAR)
47583 + port->ignore_status_mask |= FE | PE;
47584 + if (termios->c_iflag & IGNBRK) {
47585 + port->ignore_status_mask |= BI;
47587 + * If we're ignoring parity and break indicators,
47588 + * ignore overruns too (for real raw support).
47590 + if (termios->c_iflag & IGNPAR)
47591 + port->ignore_status_mask |= OE;
47594 + baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
47595 + quot = uart_get_divisor(port, baud);
47596 + spin_lock_irqsave(&uart->port.lock, flags);
47599 + lsr = UART_GET_LSR(uart);
47600 + } while (!(lsr & TEMT));
47602 + /* Disable UART */
47603 + ier = UART_GET_IER(uart);
47604 + UART_CLEAR_IER(uart, 0xF);
47606 + UART_PUT_DLL(uart, quot & 0xFF);
47608 + UART_PUT_DLH(uart, (quot >> 8) & 0xFF);
47611 + UART_PUT_LCR(uart, lcr);
47613 + /* Enable UART */
47614 + UART_SET_IER(uart, ier);
47616 + val = UART_GET_GCTL(uart);
47618 + UART_PUT_GCTL(uart, val);
47620 + spin_unlock_irqrestore(&uart->port.lock, flags);
47623 +static const char *ubi32_mailbox_type(struct uart_port *port)
47625 + struct ubi32_mailbox_port *uart = (struct ubi32_mailbox_port *)port;
47627 + return uart->port.type == PORT_UBI32_MAILBOX ? "UBI32_MAILBOX" : NULL;
47631 + * Release the memory region(s) being used by 'port'.
47633 +static void ubi32_mailbox_release_port(struct uart_port *port)
47638 + * Request the memory region(s) being used by 'port'.
47640 +static int ubi32_mailbox_request_port(struct uart_port *port)
47646 + * Configure/autoconfigure the port.
47648 +static void ubi32_mailbox_config_port(struct uart_port *port, int flags)
47650 + struct ubi32_mailbox_port *uart = (struct ubi32_mailbox_port *)port;
47652 + if (flags & UART_CONFIG_TYPE && ubi32_mailbox_request_port(&uart->port) == 0)
47653 + uart->port.type = PORT_UBI32_MAILBOX;
47657 + * Verify the new serial_struct (for TIOCSSERIAL).
47658 + * The only change we allow are to the flags and type, and
47659 + * even then only between PORT_UBI32_MAILBOX and PORT_UNKNOWN
47662 +ubi32_mailbox_verify_port(struct uart_port *port, struct serial_struct *ser)
47667 +static struct uart_ops ubi32_mailbox_pops = {
47668 + .tx_empty = ubi32_mailbox_tx_empty,
47669 + .set_mctrl = ubi32_mailbox_set_mctrl,
47670 + .get_mctrl = ubi32_mailbox_get_mctrl,
47671 + .stop_tx = ubi32_mailbox_stop_tx,
47672 + .start_tx = ubi32_mailbox_start_tx,
47673 + .stop_rx = ubi32_mailbox_stop_rx,
47674 + .enable_ms = ubi32_mailbox_enable_ms,
47675 + .break_ctl = ubi32_mailbox_break_ctl,
47676 + .startup = ubi32_mailbox_startup,
47677 + .shutdown = ubi32_mailbox_shutdown,
47678 + .set_termios = ubi32_mailbox_set_termios,
47679 + .type = ubi32_mailbox_type,
47680 + .release_port = ubi32_mailbox_release_port,
47681 + .request_port = ubi32_mailbox_request_port,
47682 + .config_port = ubi32_mailbox_config_port,
47683 + .verify_port = ubi32_mailbox_verify_port,
47686 +static void __init ubi32_mailbox_init_ports(void)
47688 + static int first = 1;
47695 + for (i = 0; i < NR_PORTS; i++) {
47696 + ubi32_mailbox_ports[i].port.uartclk = get_sclk();
47697 + ubi32_mailbox_ports[i].port.ops = &ubi32_mailbox_pops;
47698 + ubi32_mailbox_ports[i].port.line = i;
47699 + ubi32_mailbox_ports[i].port.iotype = UPIO_MEM;
47700 + ubi32_mailbox_ports[i].port.membase =
47701 + (void __iomem *)ubi32_mailbox_resource[i].uart_base_addr;
47702 + ubi32_mailbox_ports[i].port.mapbase =
47703 + ubi32_mailbox_resource[i].uart_base_addr;
47704 + ubi32_mailbox_ports[i].port.irq =
47705 + ubi32_mailbox_resource[i].uart_irq;
47706 + ubi32_mailbox_ports[i].port.flags = UPF_BOOT_AUTOCONF;
47707 + spin_lock_init(&ubi32_mailbox_ports[i].port.lock);
47709 + ubi32_mailbox_hw_init(&ubi32_mailbox_ports[i]);
47714 +#ifdef CONFIG_SERIAL_UBI32_MAILBOX_CONSOLE
47716 + * If the port was already initialised (eg, by a boot loader),
47717 + * try to determine the current setup.
47719 +static void __init
47720 +ubi32_mailbox_console_get_options(struct ubi32_mailbox_port *uart, int *baud,
47721 + int *parity, int *bits)
47723 + unsigned short status;
47725 + status = UART_GET_IER(uart) & (ERBFI | ETBEI);
47726 + if (status == (ERBFI | ETBEI)) {
47727 + /* ok, the port was enabled */
47728 + unsigned short lcr;
47729 + unsigned short dlh, dll;
47731 + lcr = UART_GET_LCR(uart);
47740 + switch (lcr & 0x03) {
47741 + case 0: *bits = 5; break;
47742 + case 1: *bits = 6; break;
47743 + case 2: *bits = 7; break;
47744 + case 3: *bits = 8; break;
47747 + dll = UART_GET_DLL(uart);
47748 + dlh = UART_GET_DLH(uart);
47750 + *baud = get_sclk() / (16*(dll | dlh << 8));
47752 + pr_debug("%s:baud = %d, parity = %c, bits= %d\n", __FUNCTION__, *baud, *parity, *bits);
47756 +#if defined(CONFIG_SERIAL_UBI32_MAILBOX_CONSOLE) || defined(CONFIG_EARLY_PRINTK)
47757 +static struct uart_driver ubi32_mailbox_reg;
47760 +ubi32_mailbox_console_setup(struct console *co, char *options)
47762 + struct ubi32_mailbox_port *uart;
47763 +# ifdef CONFIG_SERIAL_UBI32_MAILBOX_CONSOLE
47764 + int baud = SERIAL_UBICOM_BAUDRATE;
47766 + int parity = 'n';
47771 + * Check whether an invalid uart number has been specified, and
47772 + * if so, search for the first available port that does have
47773 + * console support.
47775 + if (co->index == -1 || co->index >= NR_PORTS)
47777 + uart = &ubi32_mailbox_ports[co->index];
47779 +# ifdef CONFIG_SERIAL_UBI32_MAILBOX_CONSOLE
47781 + uart_parse_options(options, &baud, &parity, &bits, &flow);
47783 + ubi32_mailbox_console_get_options(uart, &baud, &parity, &bits);
47785 + //JB return uart_set_options(&uart->port, co, baud, parity, bits, flow);
47791 +#endif /* defined (CONFIG_SERIAL_UBI32_MAILBOX_CONSOLE) ||
47792 + defined (CONFIG_EARLY_PRINTK) */
47794 +#ifdef CONFIG_SERIAL_UBI32_MAILBOX_CONSOLE
47795 +static void ubi32_mailbox_console_putchar(struct uart_port *port, int ch)
47797 +// struct ubi32_mailbox_port *uart = (struct ubi32_mailbox_port *)port;
47798 + while (!(UART_GET_LSR(uart) & THRE))
47800 + UART_PUT_CHAR(uart, ch);
47805 + * Interrupts are disabled on entering
47808 +ubi32_mailbox_console_write(struct console *co, const char *s, unsigned int count)
47810 + struct ubi32_mailbox_port *uart = &ubi32_mailbox_ports[co->index];
47811 + unsigned long flags = 0;
47813 + spin_lock_irqsave(&uart->port.lock, flags);
47814 + uart_console_write(&uart->port, s, count, ubi32_mailbox_console_putchar);
47815 + spin_unlock_irqrestore(&uart->port.lock, flags);
47819 +static struct console ubi32_mailbox_console = {
47820 + .name = UBI32_MAILBOX_NAME,
47821 + .write = ubi32_mailbox_console_write,
47822 + .device = uart_console_device,
47823 + .setup = ubi32_mailbox_console_setup,
47824 + .flags = CON_PRINTBUFFER,
47826 + .data = &ubi32_mailbox_reg,
47829 +static int __init ubi32_mailbox_console_init(void)
47831 + ubi32_mailbox_init_ports();
47832 + register_console(&ubi32_mailbox_console);
47835 +console_initcall(ubi32_mailbox_console_init);
47837 +#define UBI32_MAILBOX_CONSOLE &ubi32_mailbox_console
47839 +#define UBI32_MAILBOX_CONSOLE NULL
47840 +#endif /* CONFIG_SERIAL_UBI32_MAILBOX_CONSOLE */
47843 +#ifdef CONFIG_EARLY_PRINTK
47844 +static __init void ubi32_mailbox_early_putc(struct uart_port *port, int ch)
47846 + UART_PUT_CHAR(uart, ch);
47849 +static __init void ubi32_mailbox_early_write(struct console *con, const char *s,
47852 + struct ubi32_mailbox_port *uart = &ubi32_mailbox_ports[con->index];
47855 + for (i = 0; i < n; i++, s++) {
47857 + ubi32_mailbox_early_putc(&uart->port, '\r');
47858 + ubi32_mailbox_early_putc(&uart->port, *s);
47862 +static struct __init console ubi32_mailbox_early_console = {
47863 + .name = "early_UM",
47864 + .write = ubi32_mailbox_early_write,
47865 + .device = uart_console_device,
47866 + .flags = CON_PRINTBUFFER,
47867 + .setup = ubi32_mailbox_console_setup,
47869 + .data = &ubi32_mailbox_reg,
47873 + * XXX Unused in our driver. Need to find out what the termios initialization is good/needed for.
47875 +struct console __init *ubi32_mailbox_early_init(unsigned int port,
47876 + unsigned int cflag)
47878 + struct ubi32_mailbox_port *uart;
47879 + struct ktermios t;
47881 + if (port == -1 || port >= NR_PORTS)
47883 + ubi32_mailbox_init_ports();
47884 + ubi32_mailbox_early_console.index = port;
47885 + uart = &ubi32_mailbox_ports[port];
47886 + t.c_cflag = cflag;
47889 + t.c_lflag = ICANON;
47891 + ubi32_mailbox_set_termios(&uart->port, &t, &t);
47892 + return &ubi32_mailbox_early_console;
47895 +#endif /* CONFIG_SERIAL_UBI32_MAILBOX_CONSOLE */
47897 +static struct uart_driver ubi32_mailbox_reg = {
47898 + .owner = THIS_MODULE,
47899 + .driver_name = "ubi32_mailbox",
47900 + .dev_name = UBI32_MAILBOX_NAME,
47901 + .major = UBI32_MAILBOX_MAJOR,
47902 + .minor = UBI32_MAILBOX_MINOR,
47904 + .cons = UBI32_MAILBOX_CONSOLE,
47907 +static int ubi32_mailbox_suspend(struct platform_device *dev, pm_message_t state)
47909 + struct ubi32_mailbox_port *uart = platform_get_drvdata(dev);
47912 + uart_suspend_port(&ubi32_mailbox_reg, &uart->port);
47917 +static int ubi32_mailbox_resume(struct platform_device *dev)
47919 + struct ubi32_mailbox_port *uart = platform_get_drvdata(dev);
47922 + uart_resume_port(&ubi32_mailbox_reg, &uart->port);
47927 +static int ubi32_mailbox_probe(struct platform_device *dev)
47929 + struct resource *res = dev->resource;
47932 + for (i = 0; i < dev->num_resources; i++, res++)
47933 + if (res->flags & IORESOURCE_MEM)
47936 + if (i < dev->num_resources) {
47937 + for (i = 0; i < NR_PORTS; i++, res++) {
47938 + if (ubi32_mailbox_ports[i].port.mapbase != res->start)
47940 + ubi32_mailbox_ports[i].port.dev = &dev->dev;
47941 + uart_add_one_port(&ubi32_mailbox_reg, &ubi32_mailbox_ports[i].port);
47942 + platform_set_drvdata(dev, &ubi32_mailbox_ports[i]);
47949 +static int ubi32_mailbox_remove(struct platform_device *pdev)
47951 + struct ubi32_mailbox_port *uart = platform_get_drvdata(pdev);
47953 + platform_set_drvdata(pdev, NULL);
47956 + uart_remove_one_port(&ubi32_mailbox_reg, &uart->port);
47961 +static struct platform_driver ubi32_mailbox_driver = {
47962 + .probe = ubi32_mailbox_probe,
47963 + .remove = ubi32_mailbox_remove,
47964 + .suspend = ubi32_mailbox_suspend,
47965 + .resume = ubi32_mailbox_resume,
47967 + .name = "ubi32-mbox",
47968 + .owner = THIS_MODULE,
47972 +static int __init ubi32_mailbox_init(void)
47976 + pr_info("Serial: Ubicom32 mailbox serial driver.\n");
47978 + mailbox_console_flg = TRUE;
47979 + num_timeouts = 0;
47980 + ubi32_mailbox_init_ports();
47982 + ret = uart_register_driver(&ubi32_mailbox_reg);
47984 + ret = platform_driver_register(&ubi32_mailbox_driver);
47986 + pr_debug("uart register failed\n");
47987 + uart_unregister_driver(&ubi32_mailbox_reg);
47992 + * XXX HACK: currently probe does not get called, but the port needs to be added to work.
47994 + uart_add_one_port(&ubi32_mailbox_reg, &ubi32_mailbox_ports[0].port);
47998 +static void __exit ubi32_mailbox_exit(void)
48000 + platform_driver_unregister(&ubi32_mailbox_driver);
48001 + uart_unregister_driver(&ubi32_mailbox_reg);
48004 +module_init(ubi32_mailbox_init);
48005 +module_exit(ubi32_mailbox_exit);
48007 +MODULE_ALIAS_CHARDEV_MAJOR(UBI32_MAILBOX_MAJOR);
48008 +MODULE_ALIAS("platform:ubi32_mailbox");
48009 diff -ruN linux-2.6.30.10/drivers/serial/ubi32_serdes.c linux-2.6.30.10-ubi/drivers/serial/ubi32_serdes.c
48010 --- linux-2.6.30.10/drivers/serial/ubi32_serdes.c 1970-01-01 02:00:00.000000000 +0200
48011 +++ linux-2.6.30.10-ubi/drivers/serial/ubi32_serdes.c 2009-12-11 11:45:19.000000000 +0200
48014 + * drivers/serial/ubi32_serdes.c
48015 + * Ubicom32 On-Chip Serial Driver
48017 + * (C) Copyright 2009, Ubicom, Inc.
48019 + * This file is part of the Ubicom32 Linux Kernel Port.
48021 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
48022 + * it and/or modify it under the terms of the GNU General Public License
48023 + * as published by the Free Software Foundation, either version 2 of the
48024 + * License, or (at your option) any later version.
48026 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
48027 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
48028 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
48029 + * the GNU General Public License for more details.
48031 + * You should have received a copy of the GNU General Public License
48032 + * along with the Ubicom32 Linux Kernel Port. If not,
48033 + * see <http://www.gnu.org/licenses/>.
48035 + * Ubicom32 implementation derived from (with many thanks):
48040 +#include <linux/module.h>
48041 +#include <linux/ioport.h>
48042 +#include <linux/init.h>
48043 +#include <linux/console.h>
48044 +#include <linux/sysrq.h>
48045 +#include <linux/platform_device.h>
48046 +#include <linux/tty.h>
48047 +#include <linux/tty_flip.h>
48048 +#include <linux/serial_core.h>
48050 +#include <asm/ip5000.h>
48051 +#include <asm/ubicom32suart.h>
48054 +#define SERIAL_UBICOM_PIN_RXD (1 << 0)
48055 +#define SERIAL_UBICOM_PIN_TXD (1 << 6)
48056 +#define SERIAL_UBICOM_CTL0 0x8b300000
48057 +#define SERIAL_UBICOM_CTL1 0x00000009
48059 +#define SERIAL_UBICOM_DATA_BIT 8 /* Fixed parameter - do not change */
48060 +#define SERIAL_UBICOM_PAR_BIT 0 /* Fixed parameter - do not change */
48061 +#define SERIAL_UBICOM_STOP_BIT 1 /* Fixed parameter - do not change */
48063 +/* UART name and device definitions */
48064 +#define UBI32_SERDES_NAME "ttyUS" // XXX
48065 +#define UBI32_SERDES_MAJOR 206 // XXX
48066 +#define UBI32_SERDES_MINOR 64 // XXX
48068 +#define PORT_UBI32_SERDES 1234
48069 +#define NR_PORTS 1
48071 +struct uart_port ubi32_serdes_ports[NR_PORTS];
48073 +struct ubi32_serdes_resource {
48074 + void *uart_base_addr;
48077 +} ubi32_serdes_resource[NR_PORTS] = {
48079 + * Get params from kernel command line (required for early printk)
48080 + * or from platform resources.
48086 + * Can get overridden by 'serdes=' kernel command line.
48088 +static int ubi32_serdes_default_baud_rate = 115200;
48091 +#define IO_PORT(port) ((struct ubicom32_io_port *)port->membase)
48092 +#define IO_PORT_INT_STATUS(port) (IO_PORT(port)->int_status)
48093 +#define IO_PORT_INT_MASK(port) (IO_PORT(port)->int_mask)
48094 +#define IO_PORT_INT_CLR(port) (IO_PORT(port)->int_clr)
48098 + * ubi32_serdes_get_char()
48100 +static u8_t ubi32_serdes_get_char(struct ubicom32_io_port *io_port)
48103 + * Read from hardware (forced 32-bit atomic read).
48108 + io_port->int_clr = IO_PORTX_INT_SERDES_RXBF;
48110 + "move.4 %0, %1 \n\t"
48112 + : "m" (*(u32_t *)&(io_port->rx_fifo))
48116 + return (u8_t)(data & 0x000000ff);
48120 + * ubi32_serdes_put_char()
48122 +static void ubi32_serdes_put_char(struct ubicom32_io_port *io_port, u8_t c)
48124 + u32_t data = 0x0000fe00 | (c << 1);
48128 + * Fixed data format:
48129 + * [LSB]1 start bit - 8 data bits - no parity - 1 stop bit[MSB]
48131 + io_port->int_clr = IO_PORTX_INT_SERDES_TXBE;
48132 + io_port->ctl2 = data;
48133 + io_port->int_set = IO_PORTX_INT_SERDES_TXBUF_VALID;
48137 +static void ubi32_serdes_hw_init(struct uart_port *port, int baud)
48139 + struct ubicom32_io_port *io_port = IO_PORT(port);
48143 + * Put port functions 1-4 into reset state.
48144 + * Function 0 (GPIO) does not need or have a reset bit.
48146 + * Select SERDES function for restart below.
48148 + io_port->function =
48149 + IO_FUNC_FUNCTION_RESET(1) | IO_FUNC_FUNCTION_RESET(2) |
48150 + IO_FUNC_FUNCTION_RESET(3) | IO_FUNC_FUNCTION_RESET(4) |
48151 + IO_PORTX_FUNC_SERDES;
48154 + * Configure SERDES baudrate
48156 + if ( baud == 0 ) {
48157 + baud = ubi32_serdes_default_baud_rate;
48161 + SERIAL_UBICOM_CTL0 |
48162 + ((port->uartclk / (16 * baud)) - 1);
48165 + SERIAL_UBICOM_CTL1;
48168 + * don't interrupt until startup and start_tx
48170 + io_port->int_mask = 0;
48173 + * Set TXD pin output, RXD input and prevent GPIO
48174 + * override on the TXD & RXD pins
48176 + io_port->gpio_ctl &= ~SERIAL_UBICOM_PIN_RXD;
48177 + io_port->gpio_ctl |= SERIAL_UBICOM_PIN_TXD;
48178 + io_port->gpio_mask &= ~(SERIAL_UBICOM_PIN_RXD | SERIAL_UBICOM_PIN_TXD);
48181 + * Restart (un-reset) the port's SERDES function.
48183 + io_port->function &= ~(IO_FUNC_FUNCTION_RESET(IO_PORTX_FUNC_SERDES));
48187 +#define ULITE_STATUS_RXVALID IO_PORTX_INT_SERDES_RXBF
48188 +#define ULITE_STATUS_OVERRUN 0
48189 +#define ULITE_STATUS_FRAME 0
48190 +#define ULITE_STATUS_PARITY 0
48191 +#define ULITE_STATUS_TXEMPTY IO_PORTX_INT_SERDES_TXBE
48192 +#define ULITE_STATUS_TXFULL 0
48194 +static int ubi32_serdes_receive(struct uart_port *port, int stat)
48196 + struct tty_struct *tty = port->info->port.tty;
48197 + unsigned char ch = 0;
48198 + char flag = TTY_NORMAL;
48200 + if ((stat & (ULITE_STATUS_RXVALID | ULITE_STATUS_OVERRUN
48201 + | ULITE_STATUS_FRAME)) == 0)
48205 + if (stat & ULITE_STATUS_RXVALID) {
48206 + port->icount.rx++;
48207 + ch = ubi32_serdes_get_char((struct ubicom32_io_port *)port->membase);
48209 + if (stat & ULITE_STATUS_PARITY)
48210 + port->icount.parity++;
48213 + if (stat & ULITE_STATUS_OVERRUN)
48214 + port->icount.overrun++;
48216 + if (stat & ULITE_STATUS_FRAME)
48217 + port->icount.frame++;
48220 + /* drop byte with parity error if IGNPAR specificed */
48221 + if (stat & port->ignore_status_mask & ULITE_STATUS_PARITY)
48222 + stat &= ~ULITE_STATUS_RXVALID;
48224 + stat &= port->read_status_mask;
48226 + if (stat & ULITE_STATUS_PARITY)
48227 + flag = TTY_PARITY;
48229 + stat &= ~port->ignore_status_mask;
48231 + if (stat & ULITE_STATUS_RXVALID)
48232 + tty_insert_flip_char(tty, ch, flag);
48234 + if (stat & ULITE_STATUS_FRAME)
48235 + tty_insert_flip_char(tty, 0, TTY_FRAME);
48237 + if (stat & ULITE_STATUS_OVERRUN)
48238 + tty_insert_flip_char(tty, 0, TTY_OVERRUN);
48244 + * interrupts are disabled on entry
48246 +static void ubi32_serdes_stop_tx(struct uart_port *port)
48248 + IO_PORT_INT_MASK(port) = IO_PORT_INT_MASK(port) & ~IO_PORTX_INT_SERDES_TXBE;
48251 +static int ubi32_serdes_transmit(struct uart_port *port, int stat)
48253 + struct circ_buf *xmit = &port->info->xmit;
48255 + if (!(stat & IO_PORTX_INT_SERDES_TXBE))
48258 + if (port->x_char) {
48259 + ubi32_serdes_put_char(IO_PORT(port), port->x_char);
48260 + port->x_char = 0;
48261 + port->icount.tx++;
48265 + if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
48266 + ubi32_serdes_stop_tx(port);
48270 + ubi32_serdes_put_char(IO_PORT(port), xmit->buf[xmit->tail]);
48271 + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE-1);
48272 + port->icount.tx++;
48275 + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
48276 + uart_write_wakeup(port);
48278 + if (uart_circ_empty(xmit))
48279 + ubi32_serdes_stop_tx(port);
48285 + * port is locked and interrupts are disabled
48287 +static void ubi32_serdes_start_tx(struct uart_port *port)
48289 + IO_PORT_INT_MASK(port) = IO_PORT_INT_MASK(port) | IO_PORTX_INT_SERDES_TXBE;
48290 + ubi32_serdes_transmit(port, IO_PORT_INT_STATUS(port));
48294 + * Interrupts are enabled
48296 +static void ubi32_serdes_stop_rx(struct uart_port *port)
48298 + /* don't forward any more data (like !CREAD) */
48299 + port->ignore_status_mask = IO_PORTX_INT_SERDES_RXBF;
48303 + * Set the modem control timer to fire immediately.
48305 +static void ubi32_serdes_enable_ms(struct uart_port *port)
48310 +static irqreturn_t ubi32_serdes_isr(int irq, void *dev_id)
48312 + struct uart_port *port = dev_id;
48315 + spin_lock(&port->lock);
48318 + int stat = IO_PORT_INT_STATUS(port);
48319 + busy = ubi32_serdes_receive(port, stat);
48320 + busy |= ubi32_serdes_transmit(port, stat);
48323 + tty_flip_buffer_push(port->info->port.tty);
48325 + spin_unlock(&port->lock);
48327 + return IRQ_HANDLED;
48331 + * Return TIOCSER_TEMT when transmitter is not busy.
48333 +static unsigned int ubi32_serdes_tx_empty(struct uart_port *port)
48335 + unsigned long flags;
48336 + unsigned int ret;
48338 + spin_lock_irqsave(&port->lock, flags);
48339 + ret = IO_PORT_INT_STATUS(port);
48340 + spin_unlock_irqrestore(&port->lock, flags);
48342 + return ret & ULITE_STATUS_TXEMPTY ? TIOCSER_TEMT : 0;
48345 +static unsigned int ubi32_serdes_get_mctrl(struct uart_port *port)
48347 + return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
48350 +static void ubi32_serdes_set_mctrl(struct uart_port *port, unsigned int mctrl)
48356 + * Interrupts are always disabled.
48358 +static void ubi32_serdes_break_ctl(struct uart_port *port, int break_state)
48363 +static int ubi32_serdes_startup(struct uart_port *port)
48365 + if (request_irq(port->irq, ubi32_serdes_isr, IRQF_DISABLED,
48366 + "UBI32_SERDES", port)) {
48367 + printk(KERN_NOTICE "Unable to attach port interrupt\n");
48371 + IO_PORT_INT_CLR(port) = IO_PORTX_INT_SERDES_RXBF;
48372 + IO_PORT_INT_MASK(port) = IO_PORTX_INT_SERDES_RXBF;
48376 +static void ubi32_serdes_shutdown(struct uart_port *port)
48378 + struct ubi32_serdes_port *uart = (struct ubi32_serdes_port *)port;
48380 + IO_PORT_INT_MASK(port) = 0;
48381 + free_irq(port->irq, uart);
48385 +ubi32_serdes_set_termios(struct uart_port *port, struct ktermios *termios,
48386 + struct ktermios *old)
48388 + unsigned long flags;
48389 + unsigned int baud;
48391 + spin_lock_irqsave(&port->lock, flags);
48393 + port->read_status_mask = ULITE_STATUS_RXVALID | ULITE_STATUS_OVERRUN
48394 + | ULITE_STATUS_TXFULL;
48396 + if (termios->c_iflag & INPCK)
48397 + port->read_status_mask |=
48398 + ULITE_STATUS_PARITY | ULITE_STATUS_FRAME;
48400 + port->ignore_status_mask = 0;
48401 + if (termios->c_iflag & IGNPAR)
48402 + port->ignore_status_mask |= ULITE_STATUS_PARITY
48403 + | ULITE_STATUS_FRAME | ULITE_STATUS_OVERRUN;
48405 + /* ignore all characters if CREAD is not set */
48406 + if ((termios->c_cflag & CREAD) == 0)
48407 + port->ignore_status_mask |=
48408 + ULITE_STATUS_RXVALID | ULITE_STATUS_PARITY
48409 + | ULITE_STATUS_FRAME | ULITE_STATUS_OVERRUN;
48411 + /* update timeout */
48412 + baud = uart_get_baud_rate(port, termios, old, 0, 460800);
48413 + uart_update_timeout(port, termios->c_cflag, baud);
48415 + IO_PORT(port)->ctl0 = SERIAL_UBICOM_CTL0 |
48416 + ((port->uartclk / (16 * baud)) - 1);
48418 + spin_unlock_irqrestore(&port->lock, flags);
48421 +static const char *ubi32_serdes_type(struct uart_port *port)
48423 + return port->type == PORT_UBI32_SERDES ? "UBI32_SERDES" : NULL;
48427 + * Release the memory region(s) being used by 'port'.
48429 +static void ubi32_serdes_release_port(struct uart_port *port)
48434 + * Request the memory region(s) being used by 'port'.
48436 +static int ubi32_serdes_request_port(struct uart_port *port)
48442 + * Configure/autoconfigure the port.
48444 +static void ubi32_serdes_config_port(struct uart_port *port, int flags)
48446 + if (flags & UART_CONFIG_TYPE &&
48447 + ubi32_serdes_request_port(port) == 0)
48448 + port->type = PORT_UBI32_SERDES;
48452 + * Verify the new serial_struct (for TIOCSSERIAL).
48453 + * The only change we allow are to the flags and type, and
48454 + * even then only between PORT_UBI32_SERDES and PORT_UNKNOWN
48457 +ubi32_serdes_verify_port(struct uart_port *port, struct serial_struct *ser)
48462 +static struct uart_ops ubi32_serdes_pops = {
48463 + .tx_empty = ubi32_serdes_tx_empty,
48464 + .set_mctrl = ubi32_serdes_set_mctrl,
48465 + .get_mctrl = ubi32_serdes_get_mctrl,
48466 + .stop_tx = ubi32_serdes_stop_tx,
48467 + .start_tx = ubi32_serdes_start_tx,
48468 + .stop_rx = ubi32_serdes_stop_rx,
48469 + .enable_ms = ubi32_serdes_enable_ms,
48470 + .break_ctl = ubi32_serdes_break_ctl,
48471 + .startup = ubi32_serdes_startup,
48472 + .shutdown = ubi32_serdes_shutdown,
48473 + .set_termios = ubi32_serdes_set_termios,
48474 + .type = ubi32_serdes_type,
48475 + .release_port = ubi32_serdes_release_port,
48476 + .request_port = ubi32_serdes_request_port,
48477 + .config_port = ubi32_serdes_config_port,
48478 + .verify_port = ubi32_serdes_verify_port,
48481 +static void __init ubi32_serdes_init_ports(void)
48485 + for (i = 0; i < NR_PORTS; i++) {
48486 + ubi32_serdes_ports[i].uartclk = ubi32_serdes_resource[i].uart_clock;
48487 + ubi32_serdes_ports[i].ops = &ubi32_serdes_pops;
48488 + ubi32_serdes_ports[i].line = i;
48489 + ubi32_serdes_ports[i].iotype = UPIO_MEM;
48490 + ubi32_serdes_ports[i].membase =
48491 + (void __iomem *)ubi32_serdes_resource[i].uart_base_addr;
48492 + ubi32_serdes_ports[i].mapbase =
48493 + (resource_size_t)ubi32_serdes_resource[i].uart_base_addr;
48494 + ubi32_serdes_ports[i].irq =
48495 + ubi32_serdes_resource[i].uart_irq;
48496 + ubi32_serdes_ports[i].flags = UPF_BOOT_AUTOCONF;
48498 + ubi32_serdes_hw_init(&ubi32_serdes_ports[i], 0);
48503 +#ifdef CONFIG_SERIAL_UBI32_SERDES_CONSOLE
48505 + * If the port was already initialised (eg, by a boot loader),
48506 + * try to determine the current setup.
48508 +static void __init
48509 +ubi32_serdes_console_get_options(struct uart_port *port, int *baud)
48511 + u32 round_to = 1200;
48515 + * We might get called before platform init and with no
48516 + * kernel command line options, so port might be NULL.
48518 + *baud = ubi32_serdes_default_baud_rate;;
48519 + if ( IO_PORT(port) == 0 )
48522 + real_baud = port->uartclk
48523 + / (16 * ((IO_PORT(port)->ctl0 & ~SERIAL_UBICOM_CTL0) + 1));
48525 + *baud = ((real_baud + round_to - 1) / round_to) * round_to;
48527 + pr_debug("%s:baud = %d, real_baud = %d\n", __FUNCTION__, *baud, real_baud);
48531 +#if defined(CONFIG_SERIAL_UBI32_SERDES_CONSOLE) || defined(CONFIG_EARLY_PRINTK)
48532 +static struct uart_driver ubi32_serdes_reg;
48535 +ubi32_serdes_console_setup(struct console *co, char *options)
48537 + struct uart_port *port;
48538 +#ifdef CONFIG_SERIAL_UBI32_SERDES_CONSOLE
48539 + int baud = ubi32_serdes_default_baud_rate;
48541 + int parity = 'n';
48546 + * Check whether an invalid uart number has been specified, and
48547 + * if so, search for the first available port that does have
48548 + * console support.
48550 + if (co->index == -1 || co->index >= NR_PORTS)
48552 + port = &ubi32_serdes_ports[co->index];
48554 +#ifdef CONFIG_SERIAL_UBI32_SERDES_CONSOLE
48556 + uart_parse_options(options, &baud, &parity, &bits, &flow);
48557 + ubi32_serdes_hw_init(port, baud);
48560 + ubi32_serdes_console_get_options(port, &baud);
48562 + return uart_set_options(port, co, baud, parity, bits, flow);
48567 +#endif /* defined (CONFIG_SERIAL_UBI32_SERDES_CONSOLE) ||
48568 + defined (CONFIG_EARLY_PRINTK) */
48570 +#ifdef CONFIG_SERIAL_UBI32_SERDES_CONSOLE
48572 +ubi32_serdes_console_putchar(struct uart_port *port, int ch)
48574 + if ( IO_PORT(port) ) {
48575 + while (!(IO_PORT_INT_STATUS(port) & IO_PORTX_INT_SERDES_TXBE))
48577 + ubi32_serdes_put_char(IO_PORT(port), ch);
48582 + * Interrupts are disabled on entering
48585 +ubi32_serdes_console_write(struct console *co, const char *s, unsigned int count)
48587 + struct uart_port *port = &ubi32_serdes_ports[co->index];
48588 + unsigned long flags = 0;
48590 + spin_lock_irqsave(&port->lock, flags);
48591 + uart_console_write(port, s, count, ubi32_serdes_console_putchar);
48592 + spin_unlock_irqrestore(&port->lock, flags);
48596 +static struct console ubi32_serdes_console = {
48597 + .name = UBI32_SERDES_NAME,
48598 + .write = ubi32_serdes_console_write,
48599 + .device = uart_console_device,
48600 + .setup = ubi32_serdes_console_setup,
48601 + .flags = CON_PRINTBUFFER,
48603 + .data = &ubi32_serdes_reg,
48606 +static int __init ubi32_serdes_console_init(void)
48608 + ubi32_serdes_init_ports();
48609 + register_console(&ubi32_serdes_console);
48612 +console_initcall(ubi32_serdes_console_init);
48614 +#define UBI32_SERDES_CONSOLE &ubi32_serdes_console
48616 +#define UBI32_SERDES_CONSOLE NULL
48617 +#endif /* CONFIG_SERIAL_UBI32_SERDES_CONSOLE */
48620 +#ifdef CONFIG_EARLY_PRINTK
48621 +static __init void ubi32_serdes_early_putc(struct uart_port *port, int ch)
48623 + unsigned timeout = 0xffff;
48625 + while ((!(IO_PORT_INT_STATUS(port) & IO_PORTX_INT_SERDES_TXBE)) && --timeout)
48627 + ubi32_serdes_put_char(IO_PORT(port), ch);
48630 +static __init void ubi32_serdes_early_write(struct console *con, const char *s,
48633 + struct uart_port *port = &ubi32_serdes_ports[con->index];
48636 + for (i = 0; i < n; i++, s++) {
48638 + ubi32_serdes_early_putc(port, '\r');
48639 + ubi32_serdes_early_putc(port, *s);
48643 +static struct __init console ubi32_serdes_early_console = {
48644 + .name = "early_US",
48645 + .write = ubi32_serdes_early_write,
48646 + .device = uart_console_device,
48647 + .flags = CON_PRINTBUFFER,
48648 + .setup = ubi32_serdes_console_setup,
48650 + .data = &ubi32_serdes_reg,
48654 + * XXX Unused in our driver. Need to find out what the termios initialization is good/needed for.
48656 +struct console __init *ubi32_serdes_early_init(unsigned int port_index,
48657 + unsigned int cflag)
48659 + struct uart_port *uart;
48660 + struct ktermios t;
48662 + if (port_index == -1 || port_index >= NR_PORTS)
48664 + ubi32_serdes_init_ports();
48665 + ubi32_serdes_early_console.index = port_index;
48666 + uart = &ubi32_serdes_ports[port_index];
48667 + t.c_cflag = cflag;
48670 + t.c_lflag = ICANON;
48671 + t.c_line = port_index;
48672 + ubi32_serdes_set_termios(uart, &t, &t);
48673 + return &ubi32_serdes_early_console;
48676 +#endif /* CONFIG_SERIAL_UBI32_SERDES_CONSOLE */
48678 +static struct uart_driver ubi32_serdes_reg = {
48679 + .owner = THIS_MODULE,
48680 + .driver_name = "ubi32_serdes",
48681 + .dev_name = UBI32_SERDES_NAME,
48682 + .major = UBI32_SERDES_MAJOR,
48683 + .minor = UBI32_SERDES_MINOR,
48685 + .cons = UBI32_SERDES_CONSOLE,
48688 +static int ubi32_serdes_suspend(struct platform_device *dev, pm_message_t state)
48690 + struct uart_port *port = platform_get_drvdata(dev);
48693 + uart_suspend_port(&ubi32_serdes_reg, port);
48698 +static int ubi32_serdes_resume(struct platform_device *dev)
48700 + struct uart_port *port = platform_get_drvdata(dev);
48703 + uart_resume_port(&ubi32_serdes_reg, port);
48708 +static int ubi32_serdes_probe(struct platform_device *dev)
48710 + struct resource *res = dev->resource;
48713 + for (i = 0; i < dev->num_resources; i++, res++) {
48714 + if (res->flags & IORESOURCE_MEM) {
48715 + ubi32_serdes_resource[0].uart_base_addr = (void *) res->start;
48717 + else if (res->flags & IORESOURCE_IRQ) {
48718 + ubi32_serdes_resource[0].uart_irq = res->start;
48720 + else if (res->flags & UBICOM32_SUART_IORESOURCE_CLOCK) {
48721 + ubi32_serdes_resource[0].uart_clock = res->start;
48725 + ubi32_serdes_init_ports();
48730 +static int ubi32_serdes_remove(struct platform_device *pdev)
48732 + struct uart_port *port = platform_get_drvdata(pdev);
48734 + platform_set_drvdata(pdev, NULL);
48737 + uart_remove_one_port(&ubi32_serdes_reg, port);
48742 +static struct platform_driver ubi32_serdes_driver = {
48743 + .remove = ubi32_serdes_remove,
48744 + .suspend = ubi32_serdes_suspend,
48745 + .resume = ubi32_serdes_resume,
48747 + .name = "ubicom32suart",
48748 + .owner = THIS_MODULE,
48755 + * Called at boot time.
48757 + * You can specify IO base, IRQ, and clock for the serdes serial port
48758 + * using kernel command line "serdes=0xiobase,irq,clock". Values
48759 + * specified will be overwritten by platform device data, if present.
48761 +static int __init ubi32_serdes_setup(char *str)
48763 +#define N_PARMS (4+1)
48764 + int ints[N_PARMS];
48767 + str = get_options(str, ARRAY_SIZE(ints), ints);
48769 + for (i = 0; i < N_PARMS; i++) {
48770 + if (i < ints[0]) {
48772 + ubi32_serdes_resource[0].uart_base_addr = (void *) ints[i+1];
48774 + else if (i == 1) {
48775 + ubi32_serdes_resource[0].uart_irq = ints[i+1];
48777 + else if (i == 2) {
48778 + ubi32_serdes_resource[0].uart_clock = ints[i+1];
48780 + else if (i == 3) {
48781 + ubi32_serdes_default_baud_rate = ints[i+1];
48788 +__setup("serdes=", ubi32_serdes_setup);
48791 +static int __init ubi32_serdes_init(void)
48795 + pr_info("Serial: Ubicom32 serdes uart serial driver\n");
48797 + ret = platform_driver_probe(&ubi32_serdes_driver, ubi32_serdes_probe);
48799 + printk(KERN_INFO "serdes platform_driver_probe() failed: %d\n", ret);
48803 + ubi32_serdes_init_ports();
48805 + ret = uart_register_driver(&ubi32_serdes_reg);
48806 + if ( ret == 0 ) {
48807 + ret = uart_add_one_port(&ubi32_serdes_reg, &ubi32_serdes_ports[0]);
48808 + if ( ret != 0 ) {
48809 + uart_unregister_driver(&ubi32_serdes_reg);
48816 +static void __exit ubi32_serdes_exit(void)
48818 + platform_driver_unregister(&ubi32_serdes_driver);
48819 + uart_unregister_driver(&ubi32_serdes_reg);
48822 +module_init(ubi32_serdes_init);
48823 +module_exit(ubi32_serdes_exit);
48825 +MODULE_AUTHOR("Rainer Keller <rkeller@ubicom.com>");
48826 +MODULE_DESCRIPTION("Ubicom generic serial port driver");
48827 +MODULE_LICENSE("GPL");
48828 +MODULE_ALIAS_CHARDEV_MAJOR(UBI32_SERDES_MAJOR);
48829 +MODULE_ALIAS("platform:ubi32_serdes");
48830 diff -ruN linux-2.6.30.10/drivers/serial/ubi32_uarttio.c linux-2.6.30.10-ubi/drivers/serial/ubi32_uarttio.c
48831 --- linux-2.6.30.10/drivers/serial/ubi32_uarttio.c 1970-01-01 02:00:00.000000000 +0200
48832 +++ linux-2.6.30.10-ubi/drivers/serial/ubi32_uarttio.c 2009-12-11 11:45:19.000000000 +0200
48835 + * drivers/serial/ubi32_uarttio.c
48836 + * Ubicom32 Serial Virtual Peripherial Driver
48838 + * (C) Copyright 2009, Ubicom, Inc.
48840 + * This file is part of the Ubicom32 Linux Kernel Port.
48842 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
48843 + * it and/or modify it under the terms of the GNU General Public License
48844 + * as published by the Free Software Foundation, either version 2 of the
48845 + * License, or (at your option) any later version.
48847 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
48848 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
48849 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
48850 + * the GNU General Public License for more details.
48852 + * You should have received a copy of the GNU General Public License
48853 + * along with the Ubicom32 Linux Kernel Port. If not,
48854 + * see <http://www.gnu.org/licenses/>.
48857 +#include <linux/module.h>
48858 +#include <linux/ioport.h>
48859 +#include <linux/init.h>
48860 +#include <linux/console.h>
48861 +#include <linux/sysrq.h>
48862 +#include <linux/platform_device.h>
48863 +#include <linux/tty.h>
48864 +#include <linux/tty_flip.h>
48865 +#include <linux/serial_core.h>
48867 +#include <asm/ip5000.h>
48868 +#include <asm/gpio.h>
48869 +#include <asm/thread.h>
48870 +#include <asm/uart_tio.h>
48872 +#define DRIVER_NAME "ubi32_uarttio"
48875 + * For storing the module parameters.
48877 +#define UBI32_UARTTIO_MAX_PARAM_LEN 80
48878 +static char utio_ports_param[UBI32_UARTTIO_MAX_PARAM_LEN];
48881 + * UART name and device definitions
48883 +#define UBI32_UARTTIO_NAME "ttyUV" // XXX
48884 +#define UBI32_UARTTIO_MAJOR 206 // XXX
48885 +#define UBI32_UARTTIO_MINOR 64 // XXX
48888 + * The following structures are allocated statically because the
48889 + * memory allocation subsystem is not initialized this early on
48893 + * Per port structure
48895 +struct ubi32_uarttio_port {
48896 + struct uarttio_uart *uart;
48897 + unsigned int tx_pin;
48898 + unsigned int rx_pin;
48900 + struct uart_port port;
48905 + * If this value is set, the port has had its direction set already
48909 +static struct ubi32_uarttio_port uarttio_ports[CONFIG_SERIAL_UBI32_UARTTIO_NR_UARTS];
48912 + * Number of ports currently initialized
48914 +static int uarttio_nports;
48917 + * Per device structure
48919 +struct ubi32_uarttio_instance {
48920 + struct uarttio_regs *regs;
48921 + struct ubi32_uarttio_port *ports;
48923 + u8_t irq_requested;
48924 + u8_t driver_registered;
48927 +static struct ubi32_uarttio_instance uarttio_inst;
48929 +#ifdef CONFIG_SERIAL_UBI32_UARTTIO_CONSOLE
48930 +static struct console ubi32_uarttio_console;
48931 +#define UBI32_UARTTIO_CONSOLE &ubi32_uarttio_console
48933 +#define UBI32_UARTTIO_CONSOLE NULL
48936 +static struct uart_driver ubi32_uarttio_uart_driver = {
48937 + .owner = THIS_MODULE,
48938 + .driver_name = DRIVER_NAME,
48939 + .dev_name = UBI32_UARTTIO_NAME,
48940 + .major = UBI32_UARTTIO_MAJOR,
48941 + .minor = UBI32_UARTTIO_MINOR,
48942 + .cons = UBI32_UARTTIO_CONSOLE,
48945 +#ifdef UBI32_UARTTIO_UNUSED
48947 + * ubi32_uarttio_get_send_space
48949 +static int ubi32_uarttio_get_send_space(struct uarttio_uart *uart)
48951 + int count = uart->tx_fifo_head - uart->tx_fifo_tail;
48953 + count += uart->tx_fifo_size;
48955 + return uart->tx_fifo_size - count;
48960 + * ubi32_uarttio_get_recv_ready
48962 +static int ubi32_uarttio_get_recv_ready(struct uarttio_uart *uart)
48964 + int count = uart->rx_fifo_head - uart->rx_fifo_tail;
48966 + count += uart->rx_fifo_size;
48972 + * ubi32_uarttio_get_char()
48974 +static u8_t ubi32_uarttio_get_char(struct uarttio_uart *uart)
48979 + u32_t tail = uart->rx_fifo_tail;
48980 + u8_t data = uart->rx_fifo[tail];
48982 + if (++tail == uart->rx_fifo_size) {
48985 + uart->rx_fifo_tail = tail;
48991 + * ubi32_uarttio_put_char()
48993 +static int ubi32_uarttio_put_char(struct uarttio_uart *uart, u8_t c)
48995 + u32_t head = uart->tx_fifo_head;
48996 + u32_t prev = head;
49001 + if (++head == uart->tx_fifo_size) {
49006 + * If there isn't any space, return EBUSY
49008 + if (head == uart->tx_fifo_tail) {
49013 + * Put the character in the queue
49015 + uart->tx_fifo[prev] = c;
49016 + uart->tx_fifo_head = head;
49022 + * ubi32_uarttio_set_baud
49024 +static int ubi32_uarttio_set_baud(struct ubi32_uarttio_port *uup, unsigned int baud)
49026 + if (uup->uart->current_baud_rate == baud) {
49030 + uup->uart->baud_rate = baud;
49031 + uup->uart->flags |= UARTTIO_UART_FLAG_SET_RATE;
49032 + while (uup->uart->flags & UARTTIO_UART_FLAG_SET_RATE) {
49036 + if (uup->uart->current_baud_rate != baud) {
49038 + * Failed to set baud rate
49040 + printk(KERN_WARNING "Invalid baud rate %u, running at %u\n", baud, uup->uart->current_baud_rate);
49048 + * ubi32_uarttio_handle_receive
49050 +static void ubi32_uarttio_handle_receive(struct ubi32_uarttio_port *uup, int stat)
49052 + struct uarttio_uart *uart = uup->uart;
49053 + struct uart_port *port = &uup->port;
49054 + struct tty_struct *tty = port->info->port.tty;
49055 + unsigned char ch = 0;
49056 + char flag = TTY_NORMAL;
49059 + if ((stat & (UARTTIO_UART_INT_RX | UARTTIO_UART_INT_RXFRAME | UARTTIO_UART_INT_RXOVF)) == 0) {
49063 + if (stat & UARTTIO_UART_INT_RX) {
49064 + count = ubi32_uarttio_get_recv_ready(uart);
49065 + port->icount.rx += count;
49068 + if (stat & UARTTIO_UART_INT_RXOVF) {
49069 + port->icount.overrun++;
49072 + if (stat & UARTTIO_UART_INT_RXFRAME) {
49073 + port->icount.frame++;
49076 + stat &= ~port->ignore_status_mask;
49078 + if (stat & UARTTIO_UART_INT_RX) {
49080 + for (i = 0; i < count; i++) {
49081 + ch = ubi32_uarttio_get_char(uart);
49082 + tty_insert_flip_char(tty, ch, flag);
49086 + if (stat & UARTTIO_UART_INT_RXFRAME) {
49087 + tty_insert_flip_char(tty, 0, TTY_FRAME);
49090 + if (stat & UARTTIO_UART_INT_RXOVF) {
49091 + tty_insert_flip_char(tty, 0, TTY_OVERRUN);
49096 + * ubi32_uarttio_stop_tx
49097 + * interrupts are disabled on entry
49099 +static void ubi32_uarttio_stop_tx(struct uart_port *port)
49101 + struct ubi32_uarttio_port *uup = port->private_data;
49103 + uup->uart->int_mask &= ~UARTTIO_UART_INT_TXBE;
49107 + * ubi32_uarttio_handle_transmit
49109 +static void ubi32_uarttio_handle_transmit(struct ubi32_uarttio_port *uup, int stat)
49111 + struct uarttio_uart *uart = uup->uart;
49112 + struct uart_port *port = &uup->port;
49113 + struct circ_buf *xmit = &port->info->xmit;
49115 + if (!(stat & UARTTIO_UART_INT_TXBE)) {
49119 + if (port->x_char) {
49120 + if (ubi32_uarttio_put_char(uart, port->x_char)) {
49123 + port->x_char = 0;
49124 + port->icount.tx++;
49128 + if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
49129 + ubi32_uarttio_stop_tx(port);
49134 + * Send as many characters as we can
49136 + while (ubi32_uarttio_put_char(uart, xmit->buf[xmit->tail]) == 0) {
49137 + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
49138 + port->icount.tx++;
49139 + if (uart_circ_empty(xmit)) {
49145 + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) {
49146 + uart_write_wakeup(port);
49149 + if (uart_circ_empty(xmit)) {
49150 + ubi32_uarttio_stop_tx(port);
49155 + * ubi32_uarttio_start_tx
49156 + * port is locked and interrupts are disabled
49158 +static void ubi32_uarttio_start_tx(struct uart_port *port)
49160 + struct ubi32_uarttio_port *uup = port->private_data;
49161 + struct uarttio_uart *uart = uup->uart;
49163 + uart->int_mask |= UARTTIO_UART_INT_TXBE;
49167 + * ubi32_uarttio_stop_rx
49168 + * Interrupts are enabled
49170 +static void ubi32_uarttio_stop_rx(struct uart_port *port)
49172 + struct ubi32_uarttio_port *uup = port->private_data;
49173 + struct uarttio_uart *uart = uup->uart;
49176 + * don't forward any more data (like !CREAD)
49178 + uart->int_mask &= ~UARTTIO_UART_INT_RX;
49179 + port->ignore_status_mask = UARTTIO_UART_INT_RX;
49183 + * ubi32_uarttio_enable_ms
49184 + * Set the modem control timer to fire immediately.
49186 +static void ubi32_uarttio_enable_ms(struct uart_port *port)
49192 + * ubi32_uarttio_isr
49194 +static irqreturn_t ubi32_uarttio_isr(int irq, void *appdata)
49196 + struct ubi32_uarttio_port *uup = uarttio_ports;
49200 + * Service all of the ports
49202 + for (i = 0; i < uarttio_nports; i++) {
49203 + unsigned int flags;
49205 + if (!(uup->uart->flags & UARTTIO_UART_FLAG_ENABLED)) {
49210 + spin_lock(&uup->port.lock);
49212 + flags = uup->uart->int_flags;
49214 + uup->uart->int_flags = 0;
49216 + ubi32_uarttio_handle_receive(uup, flags);
49217 + ubi32_uarttio_handle_transmit(uup, flags);
49219 + tty_flip_buffer_push(uup->port.info->port.tty);
49221 + spin_unlock(&uup->port.lock);
49226 + return IRQ_HANDLED;
49230 + * ubi32_uarttio_tx_empty
49231 + * Return TIOCSER_TEMT when transmitter is not busy.
49233 +static unsigned int ubi32_uarttio_tx_empty(struct uart_port *port)
49235 + struct ubi32_uarttio_port *uup = port->private_data;
49237 + if (uup->uart->tx_fifo_head == uup->uart->tx_fifo_tail) {
49238 + return TIOCSER_TEMT;
49245 + * ubi32_uarttio_get_mctrl
49247 +static unsigned int ubi32_uarttio_get_mctrl(struct uart_port *port)
49249 + return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
49253 + * ubi32_uarttio_set_mctrl
49255 +static void ubi32_uarttio_set_mctrl(struct uart_port *port, unsigned int mctrl)
49261 + * ubi32_uarttio_break_ctl
49263 +static void ubi32_uarttio_break_ctl(struct uart_port *port, int break_state)
49269 + * ubi32_uarttio_startup
49271 +static int ubi32_uarttio_startup(struct uart_port *port)
49273 + struct ubi32_uarttio_port *uup = port->private_data;
49274 + struct uarttio_uart *uart = uup->uart;
49276 + uart->flags |= UARTTIO_UART_FLAG_ENABLED;
49278 + uart->int_mask |= UARTTIO_UART_INT_TXBE | UARTTIO_UART_INT_RX;
49284 + * ubi32_uarttio_shutdown
49286 +static void ubi32_uarttio_shutdown(struct uart_port *port)
49288 + struct ubi32_uarttio_port *uup = port->private_data;
49289 + struct uarttio_uart *uart = uup->uart;
49291 + uart->int_mask = 0;
49292 + uart->flags &= ~UARTTIO_UART_FLAG_ENABLED;
49296 + * ubi32_uarttio_set_termios
49298 +static void ubi32_uarttio_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old)
49300 + struct ubi32_uarttio_port *uup = port->private_data;
49301 + unsigned long flags;
49302 + unsigned int baud;
49304 + spin_lock_irqsave(&port->lock, flags);
49307 + port->read_status_mask = UBI32_UARTTIO_RX | UBI32_UARTTIO_RXOVF | UBI32_UARTTIO_TXOVF;
49309 + if (termios->c_iflag & INPCK) {
49310 + port->read_status_mask |= UBI32_UARTTIO_RXFRAME;
49314 + port->ignore_status_mask = 0;
49315 + if (termios->c_iflag & IGNPAR) {
49316 + port->ignore_status_mask |= UARTTIO_UART_INT_RXFRAME |
49317 + UARTTIO_UART_INT_RXOVF;
49321 + * ignore all characters if CREAD is not set
49323 + if ((termios->c_cflag & CREAD) == 0) {
49324 + port->ignore_status_mask |= UARTTIO_UART_INT_RX |
49325 + UARTTIO_UART_INT_RXFRAME |
49326 + UARTTIO_UART_INT_RXOVF;
49329 + /* update timeout */
49330 + baud = uart_get_baud_rate(port, termios, old, 0, 460800);
49331 + uart_update_timeout(port, termios->c_cflag, baud);
49333 + ubi32_uarttio_set_baud(uup, baud);
49334 + spin_unlock_irqrestore(&port->lock, flags);
49338 + * ubi32_uarttio_type
49340 +static const char *ubi32_uarttio_type(struct uart_port *port)
49342 + return (port->type == PORT_UBI32_UARTTIO) ? "UBI32_UARTTIO" : NULL;
49346 + * ubi32_uarttio_release_port
49347 + * Release the memory region(s) being used by 'port'.
49349 +static void ubi32_uarttio_release_port(struct uart_port *port)
49354 + * ubi32_uarttio_request_port
49355 + * Request the memory region(s) being used by 'port'.
49357 +static int ubi32_uarttio_request_port(struct uart_port *port)
49363 + * ubi32_uarttio_config_port
49364 + * Configure/autoconfigure the port.
49366 +static void ubi32_uarttio_config_port(struct uart_port *port, int flags)
49368 + if ((flags & UART_CONFIG_TYPE) && (ubi32_uarttio_request_port(port) == 0)) {
49369 + port->type = PORT_UBI32_UARTTIO;
49374 + * ubi32_uarttio_verify_port
49375 + * Verify the new serial_struct (for TIOCSSERIAL).
49377 + * The only change we allow are to the flags and type, and
49378 + * even then only between PORT_UBI32_UARTTIO and PORT_UNKNOWN
49380 +static int ubi32_uarttio_verify_port(struct uart_port *port, struct serial_struct *ser)
49385 +static struct uart_ops ubi32_uarttio_pops = {
49386 + .tx_empty = ubi32_uarttio_tx_empty,
49387 + .set_mctrl = ubi32_uarttio_set_mctrl,
49388 + .get_mctrl = ubi32_uarttio_get_mctrl,
49389 + .stop_tx = ubi32_uarttio_stop_tx,
49390 + .start_tx = ubi32_uarttio_start_tx,
49391 + .stop_rx = ubi32_uarttio_stop_rx,
49392 + .enable_ms = ubi32_uarttio_enable_ms,
49393 + .break_ctl = ubi32_uarttio_break_ctl,
49394 + .startup = ubi32_uarttio_startup,
49395 + .shutdown = ubi32_uarttio_shutdown,
49396 + .set_termios = ubi32_uarttio_set_termios,
49397 + .type = ubi32_uarttio_type,
49398 + .release_port = ubi32_uarttio_release_port,
49399 + .request_port = ubi32_uarttio_request_port,
49400 + .config_port = ubi32_uarttio_config_port,
49401 + .verify_port = ubi32_uarttio_verify_port,
49405 + * ubi32_uarttio_add_ports
49407 +static int __init ubi32_uarttio_add_ports(void)
49410 + struct ubi32_uarttio_port *uup = uarttio_ports;
49413 + for (i = 0; i < uarttio_nports; i++) {
49415 + * Setup the GPIOs
49417 + res = gpio_request(uup->tx_pin, "ubi32_uarttio_tx");
49419 + printk(KERN_WARNING "Failed to request GPIO %d\n", uup->tx_pin);
49424 + res = gpio_request(uup->rx_pin, "ubi32_uarttio_rx");
49426 + gpio_free(uup->tx_pin);
49427 + printk(KERN_WARNING "Failed to request GPIO %d\n", uup->rx_pin);
49432 + res = uart_add_one_port(&ubi32_uarttio_uart_driver, &uup->port);
49434 + gpio_free(uup->rx_pin);
49435 + gpio_free(uup->tx_pin);
49437 + printk(KERN_WARNING "Failed to add port %d,%d\n", uup->tx_pin, uup->rx_pin);
49443 + * Set the direction of the ports now, after we're sure that everything is ok
49445 + if (!uup->port_init) {
49446 + gpio_direction_output(uup->tx_pin, 1);
49447 + gpio_direction_input(uup->rx_pin);
49457 + * ubi32_uarttio_cleanup
49459 +static void ubi32_uarttio_cleanup(void)
49461 + struct ubi32_uarttio_port *uup;
49465 + * Stop the hardware thread
49467 + if (uarttio_inst.regs) {
49468 + thread_disable(uarttio_inst.regs->thread);
49470 + if (uarttio_inst.irq_requested) {
49471 + free_irq(uarttio_inst.irq, NULL);
49475 + * Get rid of the ports
49477 + uup = uarttio_inst.ports;
49478 + for (i = 0; i < uarttio_nports; i++) {
49479 + gpio_free(uup->tx_pin);
49480 + gpio_free(uup->rx_pin);
49481 + if (uup->added) {
49482 + uart_remove_one_port(&ubi32_uarttio_uart_driver, &uup->port);
49487 + if (uarttio_inst.driver_registered) {
49488 + uart_unregister_driver(&ubi32_uarttio_uart_driver);
49493 + * ubi32_uarttio_setup_port
49494 + * Setup a port in the TIO registers
49496 +static int ubi32_uarttio_setup_port(int index,
49497 + struct uarttio_uart *uart,
49498 + unsigned int baud, unsigned int tx_pin,
49499 + unsigned int rx_pin)
49501 + struct ubi32_uarttio_port *uup = &uarttio_ports[index];
49502 + void *tx_port = ubi_gpio_get_port(tx_pin);
49503 + void *rx_port = ubi_gpio_get_port(rx_pin);
49506 + * Verify the ports are on chip
49508 + if (!tx_port || !rx_port) {
49509 + printk(KERN_WARNING "Invalid port(s) specified: %u or %u\n", tx_pin, rx_pin);
49513 + uup->tx_pin = tx_pin;
49514 + uup->rx_pin = rx_pin;
49515 + uup->uart = uart;
49518 + * Setup the port structure
49520 + uup->port.ops = &ubi32_uarttio_pops;
49521 + uup->port.line = index;
49522 + uup->port.iotype = UPIO_MEM;
49523 + uup->port.flags = UPF_BOOT_AUTOCONF;
49524 + uup->port.fifosize = uup->uart->tx_fifo_size;
49525 + uup->port.private_data = uup;
49528 + * We share this IRQ across all ports
49530 + uup->port.irq = uarttio_inst.irq;
49533 + * We really don't have a mem/map base but without these variables
49534 + * set, the serial_core won't startup.
49536 + uup->port.membase = (void __iomem *)uup;
49537 + uup->port.mapbase = (resource_size_t)uup;
49538 + spin_lock_init(&uup->port.lock);
49541 + * Set up the hardware
49543 + uart->flags = UARTTIO_UART_FLAG_SET_RATE | UARTTIO_UART_FLAG_RESET;
49545 + uart->tx_port = (unsigned int)tx_port;
49546 + uart->tx_pin = gpio_pin_index(tx_pin);
49547 + uart->tx_bits = 8;
49548 + uart->tx_stop_bits = 1;
49550 + uart->rx_port = (unsigned int)rx_port;
49551 + uart->rx_pin = gpio_pin_index(rx_pin);
49552 + uart->rx_bits = 8;
49553 + uart->rx_stop_bits = 1;
49555 + uart->baud_rate = baud;
49560 +enum ubi32_uarttio_parse_states {
49561 + UBI32_UARTTIO_PARSE_STATE_BAUD,
49562 + UBI32_UARTTIO_PARSE_STATE_TX_PIN,
49563 + UBI32_UARTTIO_PARSE_STATE_RX_PIN,
49564 + UBI32_UARTTIO_PARSE_STATE_HS,
49565 + UBI32_UARTTIO_PARSE_STATE_CTS_PIN,
49566 + UBI32_UARTTIO_PARSE_STATE_RTS_PIN,
49570 + * ubi32_uarttio_parse_param
49572 +static int ubi32_uarttio_parse_param(char *str)
49583 + enum ubi32_uarttio_parse_states state = UBI32_UARTTIO_PARSE_STATE_BAUD;
49584 + struct uarttio_uart *uart = uarttio_inst.regs->uarts;
49587 + * Run though the options and generate the proper structures
49589 + res = get_option(&str, &i);
49590 + while ((res == 2) || (res == 1)) {
49592 + case UBI32_UARTTIO_PARSE_STATE_BAUD:
49594 + * If we are here and nfound > 0 then create the port
49595 + * based on the previous input
49599 + * Create the port
49601 + if (ubi32_uarttio_setup_port(nfound - 1, uart, baud, tx_pin, rx_pin)) {
49603 + * Port was invalid
49607 + printk(KERN_INFO "Serial port %d: tx=%d:rx=%d @ %d\n", nfound, tx_pin, rx_pin, baud);
49613 + * Reset the variables and go to the next state
49617 + state = UBI32_UARTTIO_PARSE_STATE_TX_PIN;
49620 + case UBI32_UARTTIO_PARSE_STATE_TX_PIN:
49622 + state = UBI32_UARTTIO_PARSE_STATE_RX_PIN;
49625 + case UBI32_UARTTIO_PARSE_STATE_RX_PIN:
49627 + state = UBI32_UARTTIO_PARSE_STATE_HS;
49630 + case UBI32_UARTTIO_PARSE_STATE_HS:
49633 + state = UBI32_UARTTIO_PARSE_STATE_CTS_PIN;
49637 + if (nfound == uarttio_inst.regs->max_uarts) {
49638 + printk(KERN_WARNING "Maximum number of serial ports reached\n");
49642 + state = UBI32_UARTTIO_PARSE_STATE_BAUD;
49645 + case UBI32_UARTTIO_PARSE_STATE_CTS_PIN:
49647 + state = UBI32_UARTTIO_PARSE_STATE_RTS_PIN;
49650 + case UBI32_UARTTIO_PARSE_STATE_RTS_PIN:
49653 + if (nfound == uarttio_inst.regs->max_uarts) {
49654 + printk(KERN_WARNING "Maximum number of serial ports reached\n");
49658 + state = UBI32_UARTTIO_PARSE_STATE_BAUD;
49661 + res = get_option(&str, &i);
49664 + if ((res > 2) || state != UBI32_UARTTIO_PARSE_STATE_BAUD) {
49665 + printk(KERN_WARNING "Parameter syntax error.\n");
49671 + * Create the final port
49673 + if (ubi32_uarttio_setup_port(nfound - 1, uart, baud, tx_pin, rx_pin)) {
49676 + printk(KERN_INFO "Serial port %d: tx=%d:rx=%d @ %d\n", nfound, tx_pin, rx_pin, baud);
49679 + uarttio_nports = nfound;
49681 + return nfound ? 0 : -ENODEV;
49685 + * Reset the ports
49687 + uart = uarttio_inst.regs->uarts;
49688 + for (i = 0; i < uarttio_inst.regs->max_uarts; i++) {
49697 + * ubi32_uarttio_probe
49699 +static int ubi32_uarttio_probe(void)
49702 + struct uarttio_node *uart_node;
49703 + char *str = utio_ports_param;
49704 + static int probed;
49705 + static int probe_result;
49708 + * We only want to be probed once, we could be probed twice
49709 + * for example if we are used as a console
49712 + return probe_result;
49717 + * Extract the TIO name from the setup string
49720 + if (*str == ',') {
49728 + probe_result = -EINVAL;
49732 + uart_node = (struct uarttio_node *)devtree_find_node(utio_ports_param);
49733 + if (!uart_node) {
49734 + probe_result = -ENODEV;
49738 + uarttio_inst.irq = uart_node->dn.recvirq;
49739 + uarttio_inst.regs = uart_node->regs;
49742 + * Parse module parameters.
49744 + ret = ubi32_uarttio_parse_param(str);
49746 + ubi32_uarttio_cleanup();
49747 + probe_result = ret;
49751 + ubi32_uarttio_uart_driver.nr = uarttio_nports;
49756 +#if defined(CONFIG_SERIAL_UBI32_UARTTIO_CONSOLE)
49758 + * ubi32_uarttio_console_setup
49760 +static int __init ubi32_uarttio_console_setup(struct console *co, char *options)
49764 + int parity = 'n';
49766 + struct ubi32_uarttio_port *uup;
49769 + * Check whether an invalid uart number has been specified, and
49770 + * if so, search for the first available port that does have
49771 + * console support.
49773 + if (co->index == -1 || co->index >= uarttio_nports) {
49776 + uup = &uarttio_ports[co->index];
49777 + baud = uup->uart->baud_rate;
49778 + uup->uart->flags |= UARTTIO_UART_FLAG_ENABLED;
49781 + * Setup the GPIOs
49782 + * We have to use the direct interface because the gpio
49783 + * subsystem is not available at this point.
49785 + uup->port_init = 1;
49786 + UBICOM32_GPIO_SET_PIN_HIGH(uup->tx_pin);
49787 + UBICOM32_GPIO_SET_PIN_OUTPUT(uup->tx_pin);
49788 + UBICOM32_GPIO_SET_PIN_INPUT(uup->rx_pin);
49791 + * Start the thread
49793 + thread_enable(uarttio_inst.regs->thread);
49796 + * Process options
49799 + uart_parse_options(options, &baud, &parity, &bits, &flow);
49800 + if (ubi32_uarttio_set_baud(uup, baud)) {
49801 + baud = uup->uart->current_baud_rate;
49805 + return uart_set_options(&uup->port, co, baud, 'n', 8, 'n');
49809 + * ubi32_uarttio_console_putchar
49811 +static void ubi32_uarttio_console_putchar(struct uart_port *port, int ch)
49813 + struct ubi32_uarttio_port *uup = port->private_data;
49815 + while (ubi32_uarttio_put_char(uup->uart, ch)) {
49821 + * ubi32_uarttio_console_write
49822 + * Interrupts are disabled on entering
49824 +static void ubi32_uarttio_console_write(struct console *co, const char *s, unsigned int count)
49826 + struct uart_port *port = &(uarttio_ports[co->index].port);
49827 + unsigned long flags = 0;
49829 + spin_lock_irqsave(&port->lock, flags);
49830 + uart_console_write(port, s, count, ubi32_uarttio_console_putchar);
49831 + spin_unlock_irqrestore(&port->lock, flags);
49834 +static struct console ubi32_uarttio_console = {
49835 + .name = UBI32_UARTTIO_NAME,
49836 + .write = ubi32_uarttio_console_write,
49837 + .device = uart_console_device,
49838 + .setup = ubi32_uarttio_console_setup,
49839 + .flags = CON_PRINTBUFFER,
49841 + .data = &ubi32_uarttio_uart_driver,
49844 +static int __init ubi32_uarttio_console_init(void)
49848 + res = ubi32_uarttio_probe();
49853 + register_console(&ubi32_uarttio_console);
49856 +console_initcall(ubi32_uarttio_console_init);
49857 +#endif /* CONFIG_SERIAL_UBI32_UARTTIO_CONSOLE */
49860 + * ubi32_serial_suspend
49862 +static int ubi32_uarttio_suspend(struct platform_device *pdev, pm_message_t state)
49865 + for (i = 0; i < uarttio_nports; i++) {
49866 + uart_suspend_port(&ubi32_uarttio_uart_driver, &uarttio_ports[i].port);
49873 + * ubi32_serial_resume
49875 +static int ubi32_uarttio_resume(struct platform_device *pdev)
49878 + for (i = 0; i < uarttio_nports; i++) {
49879 + uart_resume_port(&ubi32_uarttio_uart_driver, &uarttio_ports[i].port);
49886 + * ubi32_uarttio_remove
49888 +static int __devexit ubi32_uarttio_remove(struct platform_device *pdev)
49890 + ubi32_uarttio_cleanup();
49892 + uart_unregister_driver(&ubi32_uarttio_uart_driver);
49897 +static struct platform_driver ubi32_uarttio_platform_driver = {
49898 + .remove = __devexit_p(ubi32_uarttio_remove),
49899 + .suspend = ubi32_uarttio_suspend,
49900 + .resume = ubi32_uarttio_resume,
49902 + .name = DRIVER_NAME,
49903 + .owner = THIS_MODULE,
49909 + * Called at boot time.
49911 + * uarttio=TIONAME,(baud,tx_pin,rx_pin,handshake[,cts_pin,rts_pin],...)
49912 + * TIONAME is the name of the devtree node which describes the UARTTIO
49913 + * pin is the index of the pin, i.e. PA4 is 5 [(port * 32) + pin]
49914 + * handshake = 1 to enable handshaking, provide cts_pin, rts_pin (UNSUPPORTED)
49915 + * handshake = 0 to disable handshaking, do not provide cts_pin, rts_pin
49916 + * Ex: uarttio=UARTTIO,57600,7,6,0,9600,8,9,0
49918 +static int __init ubi32_uarttio_setup(char *str)
49920 + strncpy(utio_ports_param, str, UBI32_UARTTIO_MAX_PARAM_LEN);
49921 + utio_ports_param[UBI32_UARTTIO_MAX_PARAM_LEN - 1] = 0;
49924 +__setup("uarttio=", ubi32_uarttio_setup);
49928 + * ubi32_uarttio_init
49930 +static int __init ubi32_uarttio_init(void)
49935 + ret = ubi32_uarttio_probe();
49941 + * Request the IRQ (do it here since many ports share the same IRQ)
49943 + ret = request_irq(uarttio_inst.irq, ubi32_uarttio_isr, IRQF_DISABLED, DRIVER_NAME, NULL);
49945 + printk(KERN_WARNING "Could not request IRQ %d\n", uarttio_inst.irq);
49948 + uarttio_inst.irq_requested = 1;
49951 + * Register the UART driver and add the ports
49953 + ret = uart_register_driver(&ubi32_uarttio_uart_driver);
49957 + uarttio_inst.driver_registered = 1;
49959 + ret = ubi32_uarttio_add_ports();
49961 + ubi32_uarttio_cleanup();
49966 + * Start the thread
49968 + thread_enable(uarttio_inst.regs->thread);
49970 + for (i = 0; i < uarttio_nports; i++) {
49971 + pr_info("Serial: Ubicom32 uarttio #%d: tx:%d rx:%d baud:%d\n",
49972 + i, uarttio_ports[i].tx_pin, uarttio_ports[i].rx_pin,
49973 + uarttio_ports[i].uart->current_baud_rate);
49975 + pr_info("Serial: Ubicom32 uarttio started on thread:%d irq:%d\n", uarttio_inst.regs->thread, uarttio_inst.irq);
49980 + ubi32_uarttio_cleanup();
49983 +module_init(ubi32_uarttio_init);
49986 + * ubi32_uarttio_exit
49988 +static void __exit ubi32_uarttio_exit(void)
49990 + platform_driver_unregister(&ubi32_uarttio_platform_driver);
49992 +module_exit(ubi32_uarttio_exit);
49994 +module_param_string(ports, utio_ports_param, sizeof(utio_ports_param), 0444);
49995 +MODULE_PARM_DESC(ports, "Sets the ports to allocate: ports=TIONAME,(baud,txpin,rxpin,handshake[,ctspin,rtspin],...)\n"
49996 + " TIONAME is the name of the devtree node which describes the UARTTIO\n"
49997 + " pin is the index of the pin, i.e. PA4 is 5 [(port * 32) + pin]\n"
49998 + " handshake = 1 to enable handshaking, provide ctspin, rtspin (UNSUPPORTED)\n"
49999 + " handshake = 0 to disable handshaking, do not provide ctspin, rtspin\n"
50000 + " Ex: ports=UARTTIO,57600,7,6,0,9600,8,9,0\n");
50001 +MODULE_AUTHOR("Patrick Tjin <pat.tjin@ubicom.com>");
50002 +MODULE_DESCRIPTION("Ubicom serial virtual peripherial driver");
50003 +MODULE_LICENSE("GPL");
50004 +MODULE_ALIAS_CHARDEV_MAJOR(UBI32_UARTTIO_MAJOR);
50005 +MODULE_ALIAS("platform:" DRIVER_NAME);
50006 diff -ruN linux-2.6.30.10/drivers/spi/Kconfig linux-2.6.30.10-ubi/drivers/spi/Kconfig
50007 --- linux-2.6.30.10/drivers/spi/Kconfig 2009-12-14 11:54:29.000000000 +0200
50008 +++ linux-2.6.30.10-ubi/drivers/spi/Kconfig 2009-12-14 11:54:27.000000000 +0200
50009 @@ -196,6 +196,15 @@
50011 SPI driver for Samsung S3C24XX series ARM SoCs
50013 +config SPI_UBICOM32_GPIO
50014 + tristate "Ubicom32 SPI over GPIO"
50015 + depends on SPI_MASTER && UBICOM32 && EXPERIMENTAL
50016 + select SPI_BITBANG
50019 + SPI driver for the Ubicom32 architecture using
50020 + GPIO lines to provide the SPI bus.
50022 config SPI_S3C24XX_GPIO
50023 tristate "Samsung S3C24XX series SPI by GPIO"
50024 depends on ARCH_S3C2410 && EXPERIMENTAL
50025 diff -ruN linux-2.6.30.10/drivers/spi/Makefile linux-2.6.30.10-ubi/drivers/spi/Makefile
50026 --- linux-2.6.30.10/drivers/spi/Makefile 2009-12-14 11:55:29.000000000 +0200
50027 +++ linux-2.6.30.10-ubi/drivers/spi/Makefile 2009-12-14 11:55:25.000000000 +0200
50029 obj-$(CONFIG_SPI_MPC52xx_PSC) += mpc52xx_psc_spi.o
50030 obj-$(CONFIG_SPI_MPC83xx) += spi_mpc83xx.o
50031 obj-$(CONFIG_SPI_S3C24XX_GPIO) += spi_s3c24xx_gpio.o
50032 +obj-$(CONFIG_SPI_UBICOM32_GPIO) += spi_ubicom32_gpio.o
50033 obj-$(CONFIG_SPI_S3C24XX) += spi_s3c24xx.o
50034 obj-$(CONFIG_SPI_TXX9) += spi_txx9.o
50035 obj-$(CONFIG_SPI_XILINX) += xilinx_spi.o
50036 diff -ruN linux-2.6.30.10/drivers/spi/spi_ubicom32_gpio.c linux-2.6.30.10-ubi/drivers/spi/spi_ubicom32_gpio.c
50037 --- linux-2.6.30.10/drivers/spi/spi_ubicom32_gpio.c 1970-01-01 02:00:00.000000000 +0200
50038 +++ linux-2.6.30.10-ubi/drivers/spi/spi_ubicom32_gpio.c 2009-12-11 11:45:19.000000000 +0200
50041 + * drivers/spi_spi_ubicom32_gpio.c
50042 + * Ubicom32 GPIO based SPI driver
50044 + * (C) Copyright 2009, Ubicom, Inc.
50046 + * This file is part of the Ubicom32 Linux Kernel Port.
50048 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
50049 + * it and/or modify it under the terms of the GNU General Public License
50050 + * as published by the Free Software Foundation, either version 2 of the
50051 + * License, or (at your option) any later version.
50053 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
50054 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
50055 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
50056 + * the GNU General Public License for more details.
50058 + * You should have received a copy of the GNU General Public License
50059 + * along with the Ubicom32 Linux Kernel Port. If not,
50060 + * see <http://www.gnu.org/licenses/>.
50062 + * Ubicom32 implementation derived from (with many thanks):
50067 +#include <linux/kernel.h>
50068 +#include <linux/init.h>
50069 +#include <linux/delay.h>
50070 +#include <linux/spinlock.h>
50071 +#include <linux/workqueue.h>
50072 +#include <linux/platform_device.h>
50074 +#include <linux/spi/spi.h>
50075 +#include <linux/spi/spi_bitbang.h>
50077 +#include <linux/gpio.h>
50079 +#include <asm/ubicom32-spi-gpio.h>
50081 +#define DRIVER_NAME "ubicom32-spi-gpio"
50083 +struct ubicom32_spi_gpio {
50084 + struct spi_bitbang bitbang;
50086 + struct ubicom32_spi_gpio_platform_data *pdata;
50088 + struct platform_device *dev;
50092 + * The following 4 functions are used by EXPAND_BITBANG_TXRX to bitbang the data out.
50094 +static inline void setsck(struct spi_device *dev, int on)
50096 + struct ubicom32_spi_gpio *usg = (struct ubicom32_spi_gpio *)spi_master_get_devdata(dev->master);
50097 + gpio_set_value(usg->pdata->pin_clk, on ? 1 : 0);
50100 +static inline void setmosi(struct spi_device *dev, int on)
50102 + struct ubicom32_spi_gpio *usg = (struct ubicom32_spi_gpio *)spi_master_get_devdata(dev->master);
50103 + gpio_set_value(usg->pdata->pin_mosi, on ? 1 : 0);
50106 +static inline u32 getmiso(struct spi_device *dev)
50108 + struct ubicom32_spi_gpio *usg = (struct ubicom32_spi_gpio *)spi_master_get_devdata(dev->master);
50109 + return gpio_get_value(usg->pdata->pin_miso) ? 1 : 0;
50112 +#define spidelay(x) ndelay(x)
50114 +#define EXPAND_BITBANG_TXRX
50115 +#include <linux/spi/spi_bitbang.h>
50118 + * ubicom32_spi_gpio_txrx_mode0
50120 +static u32 ubicom32_spi_gpio_txrx_mode0(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits)
50122 + return bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits);
50126 + * ubicom32_spi_gpio_txrx_mode1
50128 +static u32 ubicom32_spi_gpio_txrx_mode1(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits)
50130 + return bitbang_txrx_be_cpha1(spi, nsecs, 0, word, bits);
50134 + * ubicom32_spi_gpio_txrx_mode2
50136 +static u32 ubicom32_spi_gpio_txrx_mode2(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits)
50138 + return bitbang_txrx_be_cpha0(spi, nsecs, 1, word, bits);
50142 + * ubicom32_spi_gpio_txrx_mode3
50144 +static u32 ubicom32_spi_gpio_txrx_mode3(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits)
50146 + return bitbang_txrx_be_cpha1(spi, nsecs, 1, word, bits);
50150 + * ubicom32_spi_gpio_chipselect
50152 +static void ubicom32_spi_gpio_chipselect(struct spi_device *dev, int value)
50154 + struct ubicom32_spi_gpio_controller_data *cd = (struct ubicom32_spi_gpio_controller_data *)dev->controller_data;
50155 + unsigned int cs_polarity = dev->mode & SPI_CS_HIGH ? 1 : 0;
50157 + if (value == BITBANG_CS_ACTIVE) {
50158 + gpio_set_value(cd->pin_cs, cs_polarity);
50161 + gpio_set_value(cd->pin_cs, !cs_polarity);
50165 + * ubicom32_spi_gpio_probe
50167 +static int ubicom32_spi_gpio_probe(struct platform_device *dev)
50169 + struct ubicom32_spi_gpio_platform_data *pdata;
50170 + struct spi_master *master;
50171 + struct ubicom32_spi_gpio *usg;
50174 + master = spi_alloc_master(&dev->dev, sizeof(struct ubicom32_spi_gpio));
50175 + if (master == NULL) {
50176 + dev_err(&dev->dev, "failed to allocate spi master\n");
50181 + usg = (struct ubicom32_spi_gpio *)spi_master_get_devdata(master);
50183 + platform_set_drvdata(dev, usg);
50186 + * Copy in the platform data
50188 + pdata = dev->dev.platform_data;
50189 + usg->pdata = dev->dev.platform_data;
50192 + * Request the GPIO lines
50194 + ret = gpio_request(pdata->pin_mosi, "spi-mosi");
50196 + dev_err(&dev->dev, "Failed to allocate spi-mosi GPIO\n");
50200 + ret = gpio_request(pdata->pin_miso, "spi-miso");
50202 + dev_err(&dev->dev, "Failed to allocate spi-miso GPIO\n");
50206 + ret = gpio_request(pdata->pin_clk, "spi-clk");
50208 + dev_err(&dev->dev, "Failed to allocate spi-clk GPIO\n");
50213 + * Setup spi-bitbang adaptor
50215 + usg->bitbang.flags |= SPI_CS_HIGH;
50216 + usg->bitbang.master = spi_master_get(master);
50217 + usg->bitbang.master->bus_num = pdata->bus_num;
50218 + usg->bitbang.master->num_chipselect = pdata->num_chipselect;
50219 + usg->bitbang.chipselect = ubicom32_spi_gpio_chipselect;
50221 + usg->bitbang.txrx_word[SPI_MODE_0] = ubicom32_spi_gpio_txrx_mode0;
50222 + usg->bitbang.txrx_word[SPI_MODE_1] = ubicom32_spi_gpio_txrx_mode1;
50223 + usg->bitbang.txrx_word[SPI_MODE_2] = ubicom32_spi_gpio_txrx_mode2;
50224 + usg->bitbang.txrx_word[SPI_MODE_3] = ubicom32_spi_gpio_txrx_mode3;
50227 + * Setup the GPIO pins
50229 + gpio_direction_output(pdata->pin_clk, pdata->clk_default);
50230 + gpio_direction_output(pdata->pin_mosi, 0);
50231 + gpio_direction_input(pdata->pin_miso);
50236 + ret = spi_bitbang_start(&usg->bitbang);
50238 + goto err_no_bitbang;
50244 + spi_master_put(usg->bitbang.master);
50246 + gpio_free(pdata->pin_clk);
50249 + gpio_free(pdata->pin_miso);
50252 + gpio_free(pdata->pin_mosi);
50259 + * ubicom32_spi_gpio_remove
50261 +static int ubicom32_spi_gpio_remove(struct platform_device *dev)
50263 + struct ubicom32_spi_gpio *sp = platform_get_drvdata(dev);
50265 + spi_bitbang_stop(&sp->bitbang);
50266 + spi_master_put(sp->bitbang.master);
50272 + * Work with hotplug and coldplug
50274 +MODULE_ALIAS("platform:ubicom32_spi_gpio");
50276 +static struct platform_driver ubicom32_spi_gpio_drv = {
50277 + .probe = ubicom32_spi_gpio_probe,
50278 + .remove = ubicom32_spi_gpio_remove,
50280 + .name = DRIVER_NAME,
50281 + .owner = THIS_MODULE,
50286 + * ubicom32_spi_gpio_init
50288 +static int __init ubicom32_spi_gpio_init(void)
50290 + return platform_driver_register(&ubicom32_spi_gpio_drv);
50294 + * ubicom32_spi_gpio_exit
50296 +static void __exit ubicom32_spi_gpio_exit(void)
50298 + platform_driver_unregister(&ubicom32_spi_gpio_drv);
50301 +module_init(ubicom32_spi_gpio_init);
50302 +module_exit(ubicom32_spi_gpio_exit);
50304 +MODULE_DESCRIPTION("Ubicom32 SPI-GPIO Driver");
50305 +MODULE_AUTHOR("Pat Tjin, <@ubicom.com>");
50306 +MODULE_LICENSE("GPL");
50307 diff -ruN linux-2.6.30.10/drivers/uio/Kconfig linux-2.6.30.10-ubi/drivers/uio/Kconfig
50308 --- linux-2.6.30.10/drivers/uio/Kconfig 2009-12-04 08:00:07.000000000 +0200
50309 +++ linux-2.6.30.10-ubi/drivers/uio/Kconfig 2009-12-11 11:45:20.000000000 +0200
50312 If you compile this as a module, it will be called uio_sercos3.
50314 +config UIO_UBICOM32RING
50315 + tristate "Ubicom32 Ring Buffer driver"
50318 + Userspace I/O interface for a Ubicom32 Ring Buffer.
50320 + If you compile this as a module, it will be called uio_ubicom32ring
50323 diff -ruN linux-2.6.30.10/drivers/uio/Makefile linux-2.6.30.10-ubi/drivers/uio/Makefile
50324 --- linux-2.6.30.10/drivers/uio/Makefile 2009-12-04 08:00:07.000000000 +0200
50325 +++ linux-2.6.30.10-ubi/drivers/uio/Makefile 2009-12-11 11:45:20.000000000 +0200
50327 obj-$(CONFIG_UIO_SMX) += uio_smx.o
50328 obj-$(CONFIG_UIO_AEC) += uio_aec.o
50329 obj-$(CONFIG_UIO_SERCOS3) += uio_sercos3.o
50330 +obj-$(CONFIG_UIO_UBICOM32RING) += uio_ubicom32ring.o
50331 diff -ruN linux-2.6.30.10/drivers/uio/uio_ubicom32ring.c linux-2.6.30.10-ubi/drivers/uio/uio_ubicom32ring.c
50332 --- linux-2.6.30.10/drivers/uio/uio_ubicom32ring.c 1970-01-01 02:00:00.000000000 +0200
50333 +++ linux-2.6.30.10-ubi/drivers/uio/uio_ubicom32ring.c 2009-12-11 11:45:20.000000000 +0200
50336 + * drivers/uio/uio_ubicom32ring.c
50338 + * Userspace I/O platform driver for Ubicom32 ring buffers
50340 + * (C) Copyright 2009, Ubicom, Inc.
50342 + * This file is part of the Ubicom32 Linux Kernel Port.
50344 + * Based on uio_ubicom32ring.c by Magnus Damm
50346 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
50347 + * it and/or modify it under the terms of the GNU General Public License
50348 + * as published by the Free Software Foundation, either version 2 of the
50349 + * License, or (at your option) any later version.
50351 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
50352 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
50353 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
50354 + * the GNU General Public License for more details.
50356 + * You should have received a copy of the GNU General Public License
50357 + * along with the Ubicom32 Linux Kernel Port. If not,
50358 + * see <http://www.gnu.org/licenses/>.
50361 +#include <linux/platform_device.h>
50362 +#include <linux/uio_driver.h>
50363 +#include <linux/spinlock.h>
50364 +#include <linux/bitops.h>
50365 +#include <linux/interrupt.h>
50366 +#include <linux/stringify.h>
50368 +#include <asm/ip5000.h>
50369 +#include <asm/ubicom32ring.h>
50371 +#define DRIVER_NAME "uio_ubicom32ring"
50373 +struct uio_ubicom32ring_data {
50374 + struct uio_info *uioinfo;
50376 + struct uio_ubicom32ring_regs *regs;
50379 + * IRQ used to kick the ring buffer
50386 + unsigned long flags;
50391 +static irqreturn_t uio_ubicom32ring_handler(int irq, struct uio_info *dev_info)
50393 + struct uio_ubicom32ring_data *priv = dev_info->priv;
50395 + /* Just disable the interrupt in the interrupt controller, and
50396 + * remember the state so we can allow user space to enable it later.
50399 + if (!test_and_set_bit(0, &priv->flags))
50400 + disable_irq_nosync(irq);
50402 + return IRQ_HANDLED;
50405 +static int uio_ubicom32ring_irqcontrol(struct uio_info *dev_info, s32 irq_on)
50407 + struct uio_ubicom32ring_data *priv = dev_info->priv;
50408 + unsigned long flags;
50410 + /* Allow user space to enable and disable the interrupt
50411 + * in the interrupt controller, but keep track of the
50412 + * state to prevent per-irq depth damage.
50414 + * Serialize this operation to support multiple tasks.
50417 + spin_lock_irqsave(&priv->lock, flags);
50419 + if (irq_on & 2) {
50421 + * Kick the ring buffer (if we can)
50423 + if (priv->irq_tx != 0xFF) {
50424 + ubicom32_set_interrupt(priv->irq_tx);
50428 + if (priv->irq_rx != 0xFF) {
50429 + if (irq_on & 1) {
50430 + if (test_and_clear_bit(0, &priv->flags))
50431 + enable_irq(dev_info->irq);
50433 + if (!test_and_set_bit(0, &priv->flags))
50434 + disable_irq(dev_info->irq);
50438 + spin_unlock_irqrestore(&priv->lock, flags);
50443 +static int uio_ubicom32ring_probe(struct platform_device *pdev)
50445 + struct uio_info *uioinfo;
50446 + struct uio_mem *uiomem;
50447 + struct uio_ubicom32ring_data *priv;
50448 + struct uio_ubicom32ring_regs *regs;
50449 + struct resource *mem_resource;
50450 + struct resource *irqtx_resource;
50451 + struct resource *irqrx_resource;
50452 + int ret = -EINVAL;
50455 + uioinfo = kzalloc(sizeof(struct uio_info), GFP_KERNEL);
50457 + dev_err(&pdev->dev, "unable to kmalloc\n");
50462 + * Allocate private data with some string space after
50464 + i = sizeof(DRIVER_NAME) + 1;
50465 + i += pdev->dev.platform_data ? strlen(pdev->dev.platform_data) : 0;
50466 + priv = kzalloc(sizeof(struct uio_ubicom32ring_data) + i, GFP_KERNEL);
50468 + dev_err(&pdev->dev, "unable to kmalloc\n");
50473 + strcpy(priv->name, DRIVER_NAME ":");
50474 + if (pdev->dev.platform_data) {
50475 + strcat(priv->name, pdev->dev.platform_data);
50477 + uioinfo->priv = priv;
50478 + uioinfo->name = priv->name;
50479 + uioinfo->version = "0.1";
50481 + priv->uioinfo = uioinfo;
50482 + spin_lock_init(&priv->lock);
50483 + priv->flags = 0; /* interrupt is enabled to begin with */
50486 + * Get our resources, the IRQ_TX and IRQ_RX are optional.
50488 + priv->irq_tx = 0xFF;
50489 + irqtx_resource = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
50490 + if (irqtx_resource) {
50491 + priv->irq_tx = irqtx_resource->start;
50494 + uioinfo->irq = -1;
50495 + priv->irq_rx = 0xFF;
50496 + irqrx_resource = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
50497 + if (irqrx_resource) {
50498 + priv->irq_rx = irqrx_resource->start;
50499 + uioinfo->irq = priv->irq_rx;
50500 + uioinfo->handler = uio_ubicom32ring_handler;
50503 + mem_resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
50504 + if (!mem_resource || !mem_resource->start) {
50505 + dev_err(&pdev->dev, "No valid memory resource found\n");
50509 + regs = (struct uio_ubicom32ring_regs *)mem_resource->start;
50510 + priv->regs = regs;
50512 + if (regs->version != UIO_UBICOM32RING_REG_VERSION) {
50513 + dev_err(&pdev->dev, "version %d not supported\n", regs->version);
50519 + * First range is the shared register space, if we have any
50521 + uiomem = &uioinfo->mem[0];
50522 + if (regs->regs_size) {
50523 + uiomem->memtype = UIO_MEM_PHYS;
50524 + uiomem->addr = (u32_t)regs->regs;
50525 + uiomem->size = regs->regs_size;
50527 + dev_info(&pdev->dev, "regs:%p (%u) / rings: %d found\n", regs->regs, regs->regs_size, regs->num_rings);
50529 + dev_info(&pdev->dev, "rings: %d found\n", regs->num_rings);
50533 + * The rest of the range correspond to the rings
50535 + for (i = 0; i < regs->num_rings; i++) {
50536 + dev_info(&pdev->dev, "\t%d: entries:%d ring:%p\n",
50537 + i, regs->rings[i]->entries, &(regs->rings[i]->ring));
50538 + if (uiomem >= &uioinfo->mem[MAX_UIO_MAPS]) {
50539 + dev_warn(&pdev->dev, "device has more than "
50540 + __stringify(MAX_UIO_MAPS)
50541 + " I/O memory resources.\n");
50545 + uiomem->memtype = UIO_MEM_PHYS;
50546 + uiomem->addr = (u32_t)&(regs->rings[i]->head);
50547 + uiomem->size = (regs->rings[i]->entries * sizeof(u32_t)) +
50548 + sizeof(struct uio_ubicom32ring_desc);
50552 + while (uiomem < &uioinfo->mem[MAX_UIO_MAPS]) {
50553 + uiomem->size = 0;
50557 + /* This driver requires no hardware specific kernel code to handle
50558 + * interrupts. Instead, the interrupt handler simply disables the
50559 + * interrupt in the interrupt controller. User space is responsible
50560 + * for performing hardware specific acknowledge and re-enabling of
50561 + * the interrupt in the interrupt controller.
50563 + * Interrupt sharing is not supported.
50565 + uioinfo->irq_flags = IRQF_DISABLED;
50566 + uioinfo->irqcontrol = uio_ubicom32ring_irqcontrol;
50568 + ret = uio_register_device(&pdev->dev, priv->uioinfo);
50570 + dev_err(&pdev->dev, "unable to register uio device\n");
50574 + platform_set_drvdata(pdev, priv);
50576 + dev_info(&pdev->dev, "'%s' using irq: rx %d tx %d, regs %p\n",
50577 + priv->name, priv->irq_rx, priv->irq_tx, priv->regs);
50587 +static int uio_ubicom32ring_remove(struct platform_device *pdev)
50589 + struct uio_ubicom32ring_data *priv = platform_get_drvdata(pdev);
50591 + uio_unregister_device(priv->uioinfo);
50592 + kfree(priv->uioinfo);
50597 +static struct platform_driver uio_ubicom32ring = {
50598 + .probe = uio_ubicom32ring_probe,
50599 + .remove = uio_ubicom32ring_remove,
50601 + .name = DRIVER_NAME,
50602 + .owner = THIS_MODULE,
50606 +static int __init uio_ubicom32ring_init(void)
50608 + return platform_driver_register(&uio_ubicom32ring);
50611 +static void __exit uio_ubicom32ring_exit(void)
50613 + platform_driver_unregister(&uio_ubicom32ring);
50616 +module_init(uio_ubicom32ring_init);
50617 +module_exit(uio_ubicom32ring_exit);
50619 +MODULE_AUTHOR("Patrick Tjin");
50620 +MODULE_DESCRIPTION("Userspace I/O driver for Ubicom32 ring buffers");
50621 +MODULE_LICENSE("GPL v2");
50622 +MODULE_ALIAS("platform:" DRIVER_NAME);
50623 diff -ruN linux-2.6.30.10/drivers/usb/gadget/epautoconf.c linux-2.6.30.10-ubi/drivers/usb/gadget/epautoconf.c
50624 --- linux-2.6.30.10/drivers/usb/gadget/epautoconf.c 2009-12-04 08:00:07.000000000 +0200
50625 +++ linux-2.6.30.10-ubi/drivers/usb/gadget/epautoconf.c 2009-12-11 11:45:20.000000000 +0200
50626 @@ -154,6 +154,10 @@
50627 /* configure your hardware with enough buffering!! */
50631 + case USB_ENDPOINT_XFER_BULK:
50632 + if ((gadget->is_dualspeed) && (ep->maxpacket < 512))
50637 diff -ruN linux-2.6.30.10/drivers/usb/Kconfig linux-2.6.30.10-ubi/drivers/usb/Kconfig
50638 --- linux-2.6.30.10/drivers/usb/Kconfig 2009-12-04 08:00:07.000000000 +0200
50639 +++ linux-2.6.30.10-ubi/drivers/usb/Kconfig 2009-12-11 11:45:20.000000000 +0200
50641 default y if PCMCIA && !M32R # sl811_cs
50642 default y if ARM # SL-811
50643 default y if SUPERH # r8a66597-hcd
50644 + default y if UBICOM32 # Ubicom's onchip USB Duial role controller
50647 # many non-PCI SOC chips embed OHCI
50648 diff -ruN linux-2.6.30.10/drivers/usb/musb/Kconfig linux-2.6.30.10-ubi/drivers/usb/musb/Kconfig
50649 --- linux-2.6.30.10/drivers/usb/musb/Kconfig 2009-12-04 08:00:07.000000000 +0200
50650 +++ linux-2.6.30.10-ubi/drivers/usb/musb/Kconfig 2009-12-11 11:45:20.000000000 +0200
50653 select TWL4030_USB if MACH_OMAP_3430SDP
50654 select USB_OTG_UTILS
50655 - tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)'
50656 + tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, Ubicom, ...)'
50658 Say Y here if your system has a dual role high speed USB
50659 controller based on the Mentor Graphics silicon IP. Then
50660 diff -ruN linux-2.6.30.10/drivers/usb/musb/Makefile linux-2.6.30.10-ubi/drivers/usb/musb/Makefile
50661 --- linux-2.6.30.10/drivers/usb/musb/Makefile 2009-12-04 08:00:07.000000000 +0200
50662 +++ linux-2.6.30.10-ubi/drivers/usb/musb/Makefile 2009-12-11 11:45:20.000000000 +0200
50664 musb_hdrc-objs += blackfin.o
50667 +ifeq ($(CONFIG_UBICOM32), y)
50668 + musb_hdrc-objs += ubi32_usb.o
50671 ifeq ($(CONFIG_USB_GADGET_MUSB_HDRC),y)
50672 musb_hdrc-objs += musb_gadget_ep0.o musb_gadget.o
50674 diff -ruN linux-2.6.30.10/drivers/usb/musb/musb_core.c linux-2.6.30.10-ubi/drivers/usb/musb/musb_core.c
50675 --- linux-2.6.30.10/drivers/usb/musb/musb_core.c 2009-12-04 08:00:07.000000000 +0200
50676 +++ linux-2.6.30.10-ubi/drivers/usb/musb/musb_core.c 2009-12-11 11:45:20.000000000 +0200
50677 @@ -105,6 +105,13 @@
50678 #include <asm/mach-types.h>
50681 +#ifdef CONFIG_UBICOM32
50682 +#include <asm/ip5000.h>
50683 +#include <asm/ubicom32-tio.h>
50684 +extern void ubi32_usb_init(void);
50685 +extern void ubi32_usb_int_clr(void);
50688 #include "musb_core.h"
50691 @@ -147,8 +154,37 @@
50694 /*-------------------------------------------------------------------------*/
50695 +#if defined(CONFIG_UBICOM32)
50698 + * Load an endpoint's FIFO
50700 +void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 wCount, const u8 *pSource)
50702 + void __iomem *fifo = hw_ep->fifo;
50704 + prefetch((u8 *)pSource);
50706 + DBG(4, "%cX ep%d fifo %p count %d buf %p\n",
50707 + 'T', hw_ep->epnum, fifo, wCount, pSource);
50709 + usb_tio_write_fifo((u32)fifo, (u32)pSource, wCount);
50714 + * Unload an endpoint's FIFO
50716 +void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 wCount, u8 *pDest)
50719 + void __iomem *fifo = hw_ep->fifo;
50720 + DBG(4, "%cX ep%d fifo %p count %d buf %p\n",
50721 + 'R', hw_ep->epnum, fifo, wCount, pDest);
50722 + usb_tio_read_fifo((u32)fifo, (u32)pDest, wCount);
50725 -#if !defined(CONFIG_USB_TUSB6010) && !defined(CONFIG_BLACKFIN)
50726 +#elif !defined(CONFIG_USB_TUSB6010) && !defined(CONFIG_BLACKFIN)
50729 * Load an endpoint's FIFO
50730 @@ -227,8 +263,7 @@
50731 readsb(fifo, dst, len);
50735 -#endif /* normal PIO */
50736 +#endif /* !T6010 && !BLACKFIN */
50739 /*-------------------------------------------------------------------------*/
50740 @@ -874,12 +909,19 @@
50741 musb_writeb(regs, MUSB_TESTMODE, 0);
50743 /* put into basic highspeed mode and start session */
50744 +#ifndef CONFIG_UBICOM32
50745 musb_writeb(regs, MUSB_POWER, MUSB_POWER_ISOUPDATE
50746 | MUSB_POWER_SOFTCONN
50747 | MUSB_POWER_HSENAB
50748 /* ENSUSPEND wedges tusb */
50749 /* | MUSB_POWER_ENSUSPEND */
50752 + musb_writeb(regs, MUSB_POWER, MUSB_POWER_HSENAB
50753 + /* ENSUSPEND wedges tusb */
50754 + /* | MUSB_POWER_ENSUSPEND */
50758 musb->is_active = 0;
50759 devctl = musb_readb(regs, MUSB_DEVCTL);
50760 @@ -1081,6 +1123,7 @@
50764 +#ifndef CONFIG_UBICOM32
50766 * configure a fifo; for non-shared endpoints, this may be called
50767 * once for a tx fifo and once for an rx fifo.
50768 @@ -1240,7 +1283,7 @@
50773 +#endif /* CONFIG_UBICOM32 */
50776 * ep_config_from_hw - when MUSB_C_DYNFIFO_DEF is false
50777 @@ -1256,6 +1299,11 @@
50778 DBG(2, "<== static silicon ep config\n");
50780 /* FIXME pick up ep0 maxpacket size */
50781 +#ifdef CONFIG_UBICOM32
50782 + /* set ep0 to shared_fifo, otherwise urb will be put to out_qh but ep0_irq try to get the urb from in_qh*/
50783 + hw_ep = musb->endpoints;
50784 + hw_ep->is_shared_fifo = true;
50787 for (epnum = 1; epnum < musb->config->num_eps; epnum++) {
50788 musb_ep_select(mbase, epnum);
50789 @@ -1276,14 +1324,27 @@
50790 /* REVISIT: this algorithm is lazy, we should at least
50791 * try to pick a double buffered endpoint.
50793 +#ifndef CONFIG_UBICOM32
50796 musb->bulk_ep = hw_ep;
50798 + if ((musb->bulk_ep_in) && (musb->bulk_ep_out))
50800 + /* Save theEP with 1024 Bytes FIFO for ISO */
50801 + if(hw_ep->max_packet_sz_tx == 512) {
50802 + if (!musb->bulk_ep_in) {
50803 + musb->bulk_ep_in = hw_ep;
50804 + } else if (!musb->bulk_ep_out) {
50805 + musb->bulk_ep_out = hw_ep;
50808 +#endif /* CONFIG_UBICOM32 */
50812 #ifdef CONFIG_USB_MUSB_HDRC_HCD
50813 - if (!musb->bulk_ep) {
50814 + if ((!musb->bulk_ep_in) || (!musb->bulk_ep_out)) {
50815 pr_debug("%s: missing bulk\n", musb_driver_name);
50818 @@ -1393,12 +1454,16 @@
50821 if (reg & MUSB_CONFIGDATA_DYNFIFO) {
50822 +#ifndef CONFIG_UBICOM32
50823 if (musb->config->dyn_fifo)
50824 status = ep_config_from_table(musb);
50829 ERR("reconfigure software for Dynamic FIFOs\n");
50834 if (!musb->config->dyn_fifo)
50835 status = ep_config_from_hw(musb);
50836 @@ -1462,8 +1527,8 @@
50838 /*-------------------------------------------------------------------------*/
50840 -#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3430)
50842 +#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3430) || defined(CONFIG_UBICOM32)
50843 +static u32_t musb_int_count = 0;
50844 static irqreturn_t generic_interrupt(int irq, void *__hci)
50846 unsigned long flags;
50847 @@ -1472,10 +1537,17 @@
50849 spin_lock_irqsave(&musb->lock, flags);
50851 +#ifndef CONFIG_UBICOM32
50852 musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
50853 musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
50854 musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX);
50856 + musb_read_int_status(&musb->int_usb, &musb->int_tx, &musb->int_rx);
50857 + //ubi32_usb_int_clr();
50858 + musb_int_count++;
50861 + DBG(4, "usb %x, tx %x, rx %x", musb->int_usb, musb->int_tx, musb->int_rx);
50862 if (musb->int_usb || musb->int_tx || musb->int_rx)
50863 retval = musb_interrupt(musb);
50865 @@ -2210,6 +2282,10 @@
50867 static int __init musb_init(void)
50869 +#ifdef CONFIG_UBICOM32
50870 + ubi32_usb_init();
50873 #ifdef CONFIG_USB_MUSB_HDRC_HCD
50874 if (usb_disabled())
50876 diff -ruN linux-2.6.30.10/drivers/usb/musb/musb_core.h linux-2.6.30.10-ubi/drivers/usb/musb/musb_core.h
50877 --- linux-2.6.30.10/drivers/usb/musb/musb_core.h 2009-12-04 08:00:07.000000000 +0200
50878 +++ linux-2.6.30.10-ubi/drivers/usb/musb/musb_core.h 2009-12-11 11:45:20.000000000 +0200
50879 @@ -326,7 +326,12 @@
50880 * queue until it completes or NAKs too much; then we try the next
50883 +#ifdef CONFIG_UBICOM32
50884 + struct musb_hw_ep *bulk_ep_in;
50885 + struct musb_hw_ep *bulk_ep_out;
50887 struct musb_hw_ep *bulk_ep;
50890 struct list_head control; /* of musb_qh */
50891 struct list_head in_bulk; /* of musb_qh */
50892 diff -ruN linux-2.6.30.10/drivers/usb/musb/musb_gadget.c linux-2.6.30.10-ubi/drivers/usb/musb/musb_gadget.c
50893 --- linux-2.6.30.10/drivers/usb/musb/musb_gadget.c 2009-12-04 08:00:07.000000000 +0200
50894 +++ linux-2.6.30.10-ubi/drivers/usb/musb/musb_gadget.c 2009-12-11 11:45:20.000000000 +0200
50895 @@ -432,7 +432,7 @@
50896 * probably rates reporting as a host error
50898 if (csr & MUSB_TXCSR_P_SENTSTALL) {
50899 - csr |= MUSB_TXCSR_P_WZC_BITS;
50900 + csr &= ~(MUSB_TXCSR_P_WZC_BITS);
50901 csr &= ~MUSB_TXCSR_P_SENTSTALL;
50902 musb_writew(epio, MUSB_TXCSR, csr);
50903 if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) {
50904 @@ -448,7 +448,7 @@
50906 if (csr & MUSB_TXCSR_P_UNDERRUN) {
50907 /* we NAKed, no big deal ... little reason to care */
50908 - csr |= MUSB_TXCSR_P_WZC_BITS;
50909 + csr &= ~(MUSB_TXCSR_P_WZC_BITS);
50910 csr &= ~(MUSB_TXCSR_P_UNDERRUN
50911 | MUSB_TXCSR_TXPKTRDY);
50912 musb_writew(epio, MUSB_TXCSR, csr);
50913 @@ -584,10 +584,16 @@
50915 const u8 epnum = req->epnum;
50916 struct usb_request *request = &req->request;
50917 - struct musb_ep *musb_ep = &musb->endpoints[epnum].ep_out;
50918 + struct musb_ep *musb_ep = NULL;
50919 void __iomem *epio = musb->endpoints[epnum].regs;
50920 - unsigned fifo_count = 0;
50921 - u16 len = musb_ep->packet_sz;
50922 + u16 fifo_count = 0;
50925 + if (musb->endpoints[epnum].is_shared_fifo)
50926 + musb_ep = &musb->endpoints[epnum].ep_in;
50928 + musb_ep = &musb->endpoints[epnum].ep_out;
50929 + len = musb_ep->packet_sz;
50931 csr = musb_readw(epio, MUSB_RXCSR);
50933 @@ -726,7 +732,7 @@
50936 /* ack the read! */
50937 - csr |= MUSB_RXCSR_P_WZC_BITS;
50938 + csr &= ~MUSB_RXCSR_P_WZC_BITS;
50939 csr &= ~MUSB_RXCSR_RXPKTRDY;
50940 musb_writew(epio, MUSB_RXCSR, csr);
50942 @@ -745,10 +751,15 @@
50944 struct usb_request *request;
50945 void __iomem *mbase = musb->mregs;
50946 - struct musb_ep *musb_ep = &musb->endpoints[epnum].ep_out;
50947 + struct musb_ep *musb_ep = NULL;
50948 void __iomem *epio = musb->endpoints[epnum].regs;
50949 struct dma_channel *dma;
50951 + if (musb->endpoints[epnum].is_shared_fifo)
50952 + musb_ep = &musb->endpoints[epnum].ep_in;
50954 + musb_ep = &musb->endpoints[epnum].ep_out;
50956 musb_ep_select(mbase, epnum);
50958 request = next_request(musb_ep);
50959 @@ -1769,7 +1780,9 @@
50964 +#ifndef CONFIG_USB_MUSB_OTG
50965 + musb_pullup(musb, 1);
50969 EXPORT_SYMBOL(usb_gadget_register_driver);
50970 diff -ruN linux-2.6.30.10/drivers/usb/musb/musb_gadget_ep0.c linux-2.6.30.10-ubi/drivers/usb/musb/musb_gadget_ep0.c
50971 --- linux-2.6.30.10/drivers/usb/musb/musb_gadget_ep0.c 2009-12-04 08:00:07.000000000 +0200
50972 +++ linux-2.6.30.10-ubi/drivers/usb/musb/musb_gadget_ep0.c 2009-12-11 11:45:20.000000000 +0200
50973 @@ -240,14 +240,14 @@
50974 case USB_REQ_SET_ADDRESS:
50975 /* change it after the status stage */
50976 musb->set_address = true;
50977 - musb->address = (u8) (ctrlrequest->wValue & 0x7f);
50978 + musb->address = (u8) (le16_to_cpu(ctrlrequest->wValue) & 0x7f);
50982 case USB_REQ_CLEAR_FEATURE:
50984 case USB_RECIP_DEVICE:
50985 - if (ctrlrequest->wValue
50986 + if (le16_to_cpu(ctrlrequest->wValue)
50987 != USB_DEVICE_REMOTE_WAKEUP)
50989 musb->may_wakeup = 0;
50990 @@ -261,8 +261,8 @@
50993 || num >= MUSB_C_NUM_EPS
50994 - || ctrlrequest->wValue
50995 - != USB_ENDPOINT_HALT)
50996 + || le16_to_cpu(ctrlrequest->wValue
50997 + != USB_ENDPOINT_HALT))
51000 if (ctrlrequest->wIndex & USB_DIR_IN)
51001 @@ -292,7 +292,7 @@
51003 case USB_RECIP_DEVICE:
51005 - switch (ctrlrequest->wValue) {
51006 + switch (le16_to_cpu(ctrlrequest->wValue)) {
51007 case USB_DEVICE_REMOTE_WAKEUP:
51008 musb->may_wakeup = 1;
51010 @@ -374,8 +374,8 @@
51013 || epnum >= MUSB_C_NUM_EPS
51014 - || ctrlrequest->wValue
51015 - != USB_ENDPOINT_HALT)
51016 + || le16_to_cpu(ctrlrequest->wValue
51017 + != USB_ENDPOINT_HALT))
51020 ep = musb->endpoints + epnum;
51021 diff -ruN linux-2.6.30.10/drivers/usb/musb/musb_host.c linux-2.6.30.10-ubi/drivers/usb/musb/musb_host.c
51022 --- linux-2.6.30.10/drivers/usb/musb/musb_host.c 2009-12-04 08:00:07.000000000 +0200
51023 +++ linux-2.6.30.10-ubi/drivers/usb/musb/musb_host.c 2009-12-11 11:45:20.000000000 +0200
51024 @@ -160,7 +160,11 @@
51025 /* NOTE: no locks here; caller should lock and select EP */
51027 txcsr = musb_readw(ep->regs, MUSB_TXCSR);
51028 +#ifndef CONFIG_UBICOM32
51029 txcsr |= MUSB_TXCSR_TXPKTRDY | MUSB_TXCSR_H_WZC_BITS;
51031 + txcsr |= (MUSB_TXCSR_TXPKTRDY & (~MUSB_TXCSR_H_WZC_BITS));
51033 musb_writew(ep->regs, MUSB_TXCSR, txcsr);
51035 txcsr = MUSB_CSR0_H_SETUPPKT | MUSB_CSR0_TXPKTRDY;
51036 @@ -223,6 +227,8 @@
51038 default: /* bulk, interrupt */
51039 /* actual_length may be nonzero on retry paths */
51040 + if (urb->actual_length)
51041 + DBG(3 ,"musb_start_urb: URB %p retried, len: %d\n", urb, urb->actual_length);
51042 buf = urb->transfer_buffer + urb->actual_length;
51043 len = urb->transfer_buffer_length - urb->actual_length;
51045 @@ -342,13 +348,13 @@
51047 csr = musb_readw(epio, MUSB_TXCSR);
51048 usb_settoggle(udev, qh->epnum, 1,
51049 - (csr & MUSB_TXCSR_H_DATATOGGLE)
51051 + ((csr & MUSB_TXCSR_H_DATATOGGLE)
51054 csr = musb_readw(epio, MUSB_RXCSR);
51055 usb_settoggle(udev, qh->epnum, 0,
51056 - (csr & MUSB_RXCSR_H_DATATOGGLE)
51058 + ((csr & MUSB_RXCSR_H_DATATOGGLE)
51063 @@ -556,7 +562,11 @@
51064 musb_read_fifo(hw_ep, length, buf);
51066 csr = musb_readw(epio, MUSB_RXCSR);
51067 +#ifndef CONFIG_UBICOM32
51068 csr |= MUSB_RXCSR_H_WZC_BITS;
51070 + csr &= ~MUSB_RXCSR_H_WZC_BITS;
51072 if (unlikely(do_flush))
51073 musb_h_flush_rxfifo(hw_ep, csr);
51075 @@ -590,6 +600,7 @@
51077 /* if programmed for Tx, put it in RX mode */
51078 if (ep->is_shared_fifo) {
51079 +#ifndef CONFIG_UBICOM32
51080 csr = musb_readw(ep->regs, MUSB_TXCSR);
51081 if (csr & MUSB_TXCSR_MODE) {
51082 musb_h_tx_flush_fifo(ep);
51083 @@ -604,7 +615,18 @@
51085 if (csr & MUSB_TXCSR_DMAMODE)
51086 musb_writew(ep->regs, MUSB_TXCSR, MUSB_TXCSR_DMAMODE);
51089 + /* clear mode (and everything else) to enable Rx */
51090 musb_writew(ep->regs, MUSB_TXCSR, 0);
51091 + /* scrub all previous state, clearing toggle */
51092 + csr = musb_readw(ep->regs, MUSB_RXCSR);
51093 + if (csr & MUSB_RXCSR_RXPKTRDY)
51094 + WARNING("rx%d, packet/%d ready?\n", ep->epnum,
51095 + musb_readw(ep->regs, MUSB_RXCOUNT));
51097 + musb_h_flush_rxfifo(ep, MUSB_RXCSR_CLRDATATOG);
51100 /* scrub all previous state, clearing toggle */
51102 @@ -1138,8 +1160,18 @@
51103 void __iomem *mbase = musb->mregs;
51104 struct dma_channel *dma;
51106 +#ifdef CONFIG_UBICOM32
51107 + if (hw_ep->is_shared_fifo) {
51108 + qh = hw_ep->in_qh;
51110 +#ifdef CONFIG_USB_SERIAL_SIERRAWIRELESS
51111 + printk(KERN_DEBUG "OUT/TX%d end, csr %04x%s\n", epnum, tx_csr,
51112 + dma ? ", dma" : "");
51115 urb = next_urb(qh);
51118 musb_ep_select(mbase, epnum);
51119 tx_csr = musb_readw(epio, MUSB_TXCSR);
51121 @@ -1180,9 +1212,14 @@
51122 * we have a candidate... NAKing is *NOT* an error
51124 musb_ep_select(mbase, epnum);
51125 +#ifndef CONFIG_UBICOM32
51126 musb_writew(epio, MUSB_TXCSR,
51127 MUSB_TXCSR_H_WZC_BITS
51128 | MUSB_TXCSR_TXPKTRDY);
51130 + musb_writew(epio, MUSB_TXCSR,
51131 + MUSB_TXCSR_TXPKTRDY);
51136 @@ -1353,8 +1390,14 @@
51137 qh->segsize = length;
51139 musb_ep_select(mbase, epnum);
51140 +#ifndef CONFIG_UBICOM32
51141 + musb_writew(epio, MUSB_TXCSR,
51142 + MUSB_TXCSR_H_WZC_BITS | MUSB_TXCSR_TXPKTRDY);
51144 musb_writew(epio, MUSB_TXCSR,
51145 - MUSB_TXCSR_H_WZC_BITS | MUSB_TXCSR_TXPKTRDY);
51146 + MUSB_TXCSR_MODE | MUSB_TXCSR_TXPKTRDY);
51152 @@ -1414,7 +1457,11 @@
51154 /* clear nak timeout bit */
51155 rx_csr = musb_readw(epio, MUSB_RXCSR);
51156 +#ifndef CONFIG_UBICOM32
51157 rx_csr |= MUSB_RXCSR_H_WZC_BITS;
51159 + rx_csr &= ~MUSB_RXCSR_H_WZC_BITS;
51161 rx_csr &= ~MUSB_RXCSR_DATAERROR;
51162 musb_writew(epio, MUSB_RXCSR, rx_csr);
51164 @@ -1483,6 +1530,13 @@
51168 +#ifdef CONFIG_UBICOM32
51169 +#ifdef CONFIG_USB_SERIAL_SIERRAWIRELESS
51170 + printk(KERN_DEBUG "RXCSR%d %04x, reqpkt, len %zu%s\n", epnum, rx_csr,
51171 + xfer_len, dma ? ", dma" : "");
51175 DBG(5, "<== hw %d rxcsr %04x, urb actual %d (+dma %zu)\n",
51176 epnum, rx_csr, urb->actual_length,
51177 dma ? dma->actual_len : 0);
51178 @@ -1521,8 +1575,15 @@
51181 musb_ep_select(mbase, epnum);
51182 +#ifndef CONFIG_UBICOM32
51183 rx_csr |= MUSB_RXCSR_H_WZC_BITS;
51184 rx_csr &= ~MUSB_RXCSR_DATAERROR;
51186 + /* NEED TO EVALUATE CHANGE */
51187 + rx_csr &= ~MUSB_RXCSR_H_WZC_BITS;
51188 + rx_csr &= ~MUSB_RXCSR_DATAERROR;
51189 +// musb_writew(epio, MUSB_RXCSR, (~(MUSB_RXCSR_H_WZC_BITS))| MUSB_RXCSR_H_REQPKT);
51191 musb_writew(epio, MUSB_RXCSR, rx_csr);
51194 @@ -1579,8 +1640,13 @@
51195 rx_csr &= ~MUSB_RXCSR_H_REQPKT;
51197 musb_ep_select(mbase, epnum);
51198 +#ifndef CONFIG_UBICOM32
51199 musb_writew(epio, MUSB_RXCSR,
51200 MUSB_RXCSR_H_WZC_BITS | rx_csr);
51202 + musb_writew(epio, MUSB_RXCSR,
51203 + (~MUSB_RXCSR_H_WZC_BITS) & rx_csr);
51207 if (dma && (rx_csr & MUSB_RXCSR_DMAENAB)) {
51208 @@ -1610,7 +1676,7 @@
51214 /* done if urb buffer is full or short packet is recd */
51215 done = (urb->actual_length + xfer_len >=
51216 urb->transfer_buffer_length
51217 @@ -1823,7 +1889,11 @@
51218 } else if (hw_ep->out_qh != NULL)
51221 +#ifndef CONFIG_UBICOM32
51222 if (hw_ep == musb->bulk_ep)
51224 + if ((hw_ep == musb->bulk_ep_in) || (hw_ep == musb->bulk_ep_out)) /* Ubicom */
51229 @@ -1836,7 +1906,14 @@
51234 +#ifdef CONFIG_UBICOM32
51235 + if (((best_diff >= qh->maxpacket)) && ((qh->type == USB_ENDPOINT_XFER_BULK) && (!is_in)))
51239 /* use bulk reserved ep1 if no other ep is free */
51240 +#ifndef CONFIG_UBICOM32
51241 if (best_end < 0 && qh->type == USB_ENDPOINT_XFER_BULK) {
51242 hw_ep = musb->bulk_ep;
51244 @@ -1858,6 +1935,22 @@
51245 } else if (best_end < 0) {
51249 + if (best_end < 0 && qh->type == USB_ENDPOINT_XFER_BULK) {
51250 + /* hw_ep = musb->bulk_ep; */
51252 + head = &musb->in_bulk;
51253 + hw_ep = musb->bulk_ep_in; /* UBICOM */
51256 + head = &musb->out_bulk;
51257 + hw_ep = musb->bulk_ep_out; /* UBICOM */
51260 + } else if (best_end < 0) {
51267 @@ -1869,6 +1962,13 @@
51268 list_add_tail(&qh->ring, head);
51272 + * It's not make sense to set NAK timeout when qh->mux = 0,
51273 + * There is nothing else to schedule
51275 + if ((qh->type == USB_ENDPOINT_XFER_BULK) && (qh->mux == 0))
51276 + qh->intv_reg = 0;
51279 qh->hep->hcpriv = qh;
51281 @@ -1975,6 +2075,15 @@
51282 /* ISO always uses logarithmic encoding */
51283 interval = min_t(u8, epd->bInterval, 16);
51285 +#ifdef COMFIG_UBICOM32
51286 + case USB_ENDPOINT_XFER_BULK:
51287 + if (epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
51288 + interval = (USB_SPEED_HIGH == urb->dev->speed) ? 16: 2;
51295 /* REVISIT we actually want to use NAK limits, hinting to the
51296 * transfer scheduling logic to try some other qh, e.g. try
51297 diff -ruN linux-2.6.30.10/drivers/usb/musb/musb_io.h linux-2.6.30.10-ubi/drivers/usb/musb/musb_io.h
51298 --- linux-2.6.30.10/drivers/usb/musb/musb_io.h 2009-12-04 08:00:07.000000000 +0200
51299 +++ linux-2.6.30.10-ubi/drivers/usb/musb/musb_io.h 2009-12-11 11:45:20.000000000 +0200
51302 #ifndef CONFIG_BLACKFIN
51304 +#ifndef CONFIG_UBICOM32
51305 /* NOTE: these offsets are all in bytes */
51307 static inline u16 musb_readw(const void __iomem *addr, unsigned offset)
51310 static inline void musb_writel(void __iomem *addr, unsigned offset, u32 data)
51311 { __raw_writel(data, addr + offset); }
51313 +#include <asm/ubicom32-tio.h>
51314 +static inline u16 musb_readw(const void __iomem *addr, unsigned offset)
51317 + usb_tio_read_u16((u32)(addr + offset), &data);
51321 +static inline u8 musb_readb(const void __iomem *addr, unsigned offset)
51324 + usb_tio_read_u8((u32)(addr + offset), &data);
51328 +static inline void musb_writew(void __iomem *addr, unsigned offset, u16 data)
51330 + usb_tio_write_u16((u32)(addr + offset), data);
51333 +static inline void musb_writeb(void __iomem *addr, unsigned offset, u8 data)
51335 + usb_tio_write_u8((u32)(addr + offset), data);
51338 +static inline void musb_read_int_status(u8_t *int_usb, u16_t *int_tx, u16_t *int_rx)
51340 + return usb_tio_read_int_status(int_usb, int_tx, int_rx);
51342 +#endif /* CONFIG_UBICOM32 */
51344 #ifdef CONFIG_USB_TUSB6010
51346 @@ -106,7 +137,7 @@
51347 __raw_writew(tmp, addr + (offset & ~1));
51351 +#elif !defined(CONFIG_UBICOM32)
51353 static inline u8 musb_readb(const void __iomem *addr, unsigned offset)
51354 { return __raw_readb(addr + offset); }
51355 diff -ruN linux-2.6.30.10/drivers/usb/musb/musb_regs.h linux-2.6.30.10-ubi/drivers/usb/musb/musb_regs.h
51356 --- linux-2.6.30.10/drivers/usb/musb/musb_regs.h 2009-12-04 08:00:07.000000000 +0200
51357 +++ linux-2.6.30.10-ubi/drivers/usb/musb/musb_regs.h 2009-12-11 11:45:20.000000000 +0200
51358 @@ -167,6 +167,7 @@
51359 (MUSB_TXCSR_H_NAKTIMEOUT | MUSB_TXCSR_H_RXSTALL \
51360 | MUSB_TXCSR_H_ERROR | MUSB_TXCSR_FIFONOTEMPTY)
51363 /* RXCSR in Peripheral and Host mode */
51364 #define MUSB_RXCSR_AUTOCLEAR 0x8000
51365 #define MUSB_RXCSR_DMAENAB 0x2000
51366 diff -ruN linux-2.6.30.10/drivers/usb/musb/ubi32_usb.c linux-2.6.30.10-ubi/drivers/usb/musb/ubi32_usb.c
51367 --- linux-2.6.30.10/drivers/usb/musb/ubi32_usb.c 1970-01-01 02:00:00.000000000 +0200
51368 +++ linux-2.6.30.10-ubi/drivers/usb/musb/ubi32_usb.c 2009-12-11 11:45:20.000000000 +0200
51371 + * drivers/usb/musb/ubi32_usb.c
51372 + * Ubicom32 usb controller driver.
51374 + * (C) Copyright 2009, Ubicom, Inc.
51375 + * Copyright (C) 2005-2006 by Texas Instruments
51377 + * Derived from the Texas Instruments Inventra Controller Driver for Linux.
51379 + * This file is part of the Ubicom32 Linux Kernel Port.
51381 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
51382 + * it and/or modify it under the terms of the GNU General Public License
51383 + * as published by the Free Software Foundation, either version 2 of the
51384 + * License, or (at your option) any later version.
51386 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
51387 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
51388 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
51389 + * the GNU General Public License for more details.
51391 + * You should have received a copy of the GNU General Public License
51392 + * along with the Ubicom32 Linux Kernel Port. If not,
51393 + * see <http://www.gnu.org/licenses/>.
51395 + * Ubicom32 implementation derived from (with many thanks):
51400 +#include <linux/module.h>
51401 +#include <linux/kernel.h>
51402 +#include <linux/sched.h>
51403 +#include <linux/slab.h>
51404 +#include <linux/init.h>
51405 +#include <linux/list.h>
51406 +#include <linux/clk.h>
51407 +#include <linux/io.h>
51409 +#include <asm/io.h>
51410 +#include <asm/ip5000.h>
51411 +#include "musb_core.h"
51413 +void musb_platform_enable(struct musb *musb)
51416 +void musb_platform_disable(struct musb *musb)
51420 +int musb_platform_set_mode(struct musb *musb, u8 musb_mode) {
51424 +static void ip5k_usb_hcd_vbus_power(struct musb *musb, int is_on, int sleeping)
51428 +static void ip5k_usb_hcd_set_vbus(struct musb *musb, int is_on)
51431 + /* HDRC controls CPEN, but beware current surges during device
51432 + * connect. They can trigger transient overcurrent conditions
51433 + * that must be ignored.
51436 + devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
51439 + musb->is_active = 1;
51440 + musb->xceiv.default_a = 1;
51441 + musb->xceiv.state = OTG_STATE_A_WAIT_VRISE;
51442 + devctl |= MUSB_DEVCTL_SESSION;
51444 + MUSB_HST_MODE(musb);
51446 + musb->is_active = 0;
51448 + /* NOTE: we're skipping A_WAIT_VFALL -> A_IDLE and
51449 + * jumping right to B_IDLE...
51452 + musb->xceiv.default_a = 0;
51453 + musb->xceiv.state = OTG_STATE_B_IDLE;
51454 + devctl &= ~MUSB_DEVCTL_SESSION;
51456 + MUSB_DEV_MODE(musb);
51458 + musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
51460 + DBG(1, "VBUS %s, devctl %02x "
51461 + /* otg %3x conf %08x prcm %08x */ "\n",
51462 + otg_state_string(musb),
51463 + musb_readb(musb->mregs, MUSB_DEVCTL));
51465 +static int ip5k_usb_hcd_set_power(struct otg_transceiver *x, unsigned mA)
51470 +static int musb_platform_resume(struct musb *musb);
51472 +int __init musb_platform_init(struct musb *musb)
51475 +#ifdef CONFIG_UBICOM32_V4
51478 + "move.4 %0, CHIP_ID \n\t"
51481 + if (chip_id == 0x30001) {
51482 + *((u32_t *)(GENERAL_CFG_BASE + GEN_USB_PHY_TEST)) &= ~(1 << 30);
51484 + *((u32_t *)(GENERAL_CFG_BASE + GEN_USB_PHY_TEST)) &= ~(1 << 31);
51486 + *((u32_t *)(GENERAL_CFG_BASE + GEN_USB_PHY_TEST)) &= ~(1 << 17);
51488 + *((u32_t *)(GENERAL_CFG_BASE + GEN_USB_PHY_TEST)) &= ~(1 << 14);
51492 + *((u32_t *)(GENERAL_CFG_BASE + GEN_USB_PHY_CFG)) |= ((1 << 14) | (1 <<15));
51494 + /* The i-clk is AUTO gated. Hence there is no need
51495 + * to disable it until the driver is shutdown */
51497 + clk_enable(musb->clock);
51498 + musb_platform_resume(musb);
51500 + ip5k_usb_hcd_vbus_power(musb, musb->board_mode == MUSB_HOST, 1);
51502 + if (is_host_enabled(musb))
51503 + musb->board_set_vbus = ip5k_usb_hcd_set_vbus;
51504 + if (is_peripheral_enabled(musb))
51505 + musb->xceiv.set_power = ip5k_usb_hcd_set_power;
51511 +int musb_platform_suspend(struct musb *musb)
51515 +int musb_platform_resume(struct musb *musb)
51520 +int musb_platform_exit(struct musb *musb)
51522 + ip5k_usb_hcd_vbus_power(musb, 0 /*off*/, 1);
51523 + musb_platform_suspend(musb);
51526 diff -ruN linux-2.6.30.10/drivers/video/backlight/Kconfig linux-2.6.30.10-ubi/drivers/video/backlight/Kconfig
51527 --- linux-2.6.30.10/drivers/video/backlight/Kconfig 2009-12-04 08:00:07.000000000 +0200
51528 +++ linux-2.6.30.10-ubi/drivers/video/backlight/Kconfig 2009-12-11 11:45:20.000000000 +0200
51530 If you have an HP Jornada 700 series handheld (710/720/728)
51531 say Y to enable LCD control driver.
51533 +config LCD_UBICOM32POWER
51534 + tristate "Ubicom LCD power Driver"
51535 + depends on LCD_CLASS_DEVICE && UBICOM32
51538 + If you have a Ubicom32 based system with an LCD panel that requires
51539 + power control, say Y to enable the power control driver for it.
51541 +config LCD_UBICOM32
51542 + tristate "Ubicom Backlight Driver"
51543 + depends on LCD_CLASS_DEVICE && UBICOM32
51546 + This driver takes care of initialization of LCD panels with
51547 + built in controllers.
51549 +menu "Ubicom32 LCD Panel Support"
51550 + depends on UBICOM32 && LCD_UBICOM32
51552 +config LCD_UBICOM32_TFT2N0369E_P
51553 + bool "TFT2N0369E (Portrait)"
51556 + Support for TFT2N0369 in portrait mode
51558 +config LCD_UBICOM32_TFT2N0369E_L
51559 + bool "TFT2N0369E (Landscape)"
51562 + Support for TFT2N0369 in landscape mode
51564 +config LCD_UBICOM32_CFAF240320KTTS
51565 + bool "CFAF240320KTTS"
51568 + Support for CFAF240320KTTS
51570 +config LCD_UBICOM32_CFAF240320KTTS_180
51571 + bool "CFAF240320KTTS (180 rotation)"
51574 + Support for CFAF240320KTTS rotated 180 degrees
51576 +config LCD_UBICOM32_CFAF240320D
51577 + bool "CFAF240320D"
51580 + Support for CFAF240320D
51582 +config LCD_UBICOM32_CFAF320240F
51583 + bool "CFAF320240F"
51586 + Support for CFAF320240F
51593 @@ -229,3 +286,11 @@
51595 If you have a Tabletkiosk Sahara Touch-iT, say y to enable the
51598 +config BACKLIGHT_UBICOM32
51599 + tristate "Ubicom Backlight Driver"
51600 + depends on BACKLIGHT_CLASS_DEVICE && UBICOM32
51603 + If you have a Ubicom32 based system with a backlight say Y to enable the
51604 + backlight driver.
51605 diff -ruN linux-2.6.30.10/drivers/video/backlight/Makefile linux-2.6.30.10-ubi/drivers/video/backlight/Makefile
51606 --- linux-2.6.30.10/drivers/video/backlight/Makefile 2009-12-04 08:00:07.000000000 +0200
51607 +++ linux-2.6.30.10-ubi/drivers/video/backlight/Makefile 2009-12-11 11:45:20.000000000 +0200
51609 obj-$(CONFIG_LCD_VGG2432A4) += vgg2432a4.o
51610 obj-$(CONFIG_LCD_TDO24M) += tdo24m.o
51611 obj-$(CONFIG_LCD_TOSA) += tosa_lcd.o
51612 +obj-$(CONFIG_LCD_LTV350QV) += ltv350qv.o
51613 +obj-$(CONFIG_LCD_UBICOM32POWER) += ubicom32lcdpower.o
51614 +obj-$(CONFIG_LCD_UBICOM32) += ubicom32lcd.o
51616 obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o
51617 obj-$(CONFIG_BACKLIGHT_ATMEL_PWM) += atmel-pwm-bl.o
51619 obj-$(CONFIG_BACKLIGHT_MBP_NVIDIA) += mbp_nvidia_bl.o
51620 obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o
51621 obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o
51623 +obj-$(CONFIG_BACKLIGHT_UBICOM32) += ubicom32bl.o
51624 diff -ruN linux-2.6.30.10/drivers/video/backlight/ubicom32bl.c linux-2.6.30.10-ubi/drivers/video/backlight/ubicom32bl.c
51625 --- linux-2.6.30.10/drivers/video/backlight/ubicom32bl.c 1970-01-01 02:00:00.000000000 +0200
51626 +++ linux-2.6.30.10-ubi/drivers/video/backlight/ubicom32bl.c 2009-12-11 11:45:20.000000000 +0200
51629 + * drivers/video/backlight/ubicom32bl.c
51630 + * Backlight driver for the Ubicom32 platform
51632 + * (C) Copyright 2009, Ubicom, Inc.
51634 + * This file is part of the Ubicom32 Linux Kernel Port.
51636 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
51637 + * it and/or modify it under the terms of the GNU General Public License
51638 + * as published by the Free Software Foundation, either version 2 of the
51639 + * License, or (at your option) any later version.
51641 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
51642 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
51643 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
51644 + * the GNU General Public License for more details.
51646 + * You should have received a copy of the GNU General Public License
51647 + * along with the Ubicom32 Linux Kernel Port. If not,
51648 + * see <http://www.gnu.org/licenses/>.
51650 + * Ubicom32 implementation derived from (with many thanks):
51655 +#include <linux/init.h>
51656 +#include <linux/kernel.h>
51657 +#include <linux/module.h>
51658 +#include <linux/platform_device.h>
51659 +#include <linux/backlight.h>
51660 +#include <linux/fb.h>
51662 +#include <asm/ubicom32bl.h>
51663 +#include <asm/ip5000.h>
51665 +#define DRIVER_NAME "ubicom32bl"
51666 +#define UBICOM32BL_MAX_BRIGHTNESS 255
51668 +struct ubicom32bl_data {
51670 + * Pointer to the platform data structure. Keep this around since we need values
51671 + * from it to set the backlight intensity.
51673 + const struct ubicom32bl_platform_data *pdata;
51676 + * Backlight device, we have to save this for use when we remove ourselves.
51678 + struct backlight_device *bldev;
51681 + * Current intensity, used for get_intensity.
51683 + int cur_intensity;
51686 + * Init function for PWM
51688 + int (*init_fn)(struct ubicom32bl_data *);
51691 + * Set intensity function depending on the backlight type
51693 + int (*set_intensity_fn)(struct ubicom32bl_data *, int);
51697 + * ubicom32bl_set_intensity_gpio
51699 +static int ubicom32bl_set_intensity_gpio(struct ubicom32bl_data *ud, int intensity)
51701 + ud->cur_intensity = intensity ? 255 : 0;
51713 + * ubicom32bl_set_intensity_hw
51715 +static int ubicom32bl_set_intensity_hw(struct ubicom32bl_data *ud, int intensity)
51717 + u16_t period = ud->pdata->pwm_period;
51721 + * Calculate the new duty cycle
51723 + duty = (period * intensity) / (UBICOM32BL_MAX_BRIGHTNESS + 1);
51726 + * Set the new duty cycle
51728 + switch (ud->pdata->pwm_channel) {
51731 + * Channel 0 is in the lower half of PORT C ctl0 and ctl1
51733 + UBICOM32_IO_PORT(RC)->ctl1 = (ud->pdata->pwm_period << 16) | duty;
51738 + * Channel 1 is in the upper half of PORT C ctl0 and ctl2
51740 + UBICOM32_IO_PORT(RC)->ctl2 = (ud->pdata->pwm_period << 16) | duty;
51745 + * Channel 2 is in PORT H ctl0 and ctl1
51747 + UBICOM32_IO_PORT(RH)->ctl1 = (ud->pdata->pwm_period << 16) | duty;
51751 + ud->cur_intensity = intensity;
51757 + * ubicom32bl_set_intensity
51759 +static int ubicom32bl_set_intensity(struct backlight_device *bd)
51761 + struct ubicom32bl_data *ud = (struct ubicom32bl_data *)bl_get_data(bd);
51762 + int intensity = bd->props.brightness;
51765 + * If we're blanked the the intensity doesn't matter.
51767 + if ((bd->props.power != FB_BLANK_UNBLANK) || (bd->props.fb_blank != FB_BLANK_UNBLANK)) {
51772 + * Check for inverted backlight.
51774 + if (ud->pdata->invert) {
51775 + intensity = UBICOM32BL_MAX_BRIGHTNESS - intensity;
51778 + if (ud->set_intensity_fn) {
51779 + return ud->set_intensity_fn(ud, intensity);
51786 + * ubicom32bl_get_intensity
51787 + * Return the current intensity of the backlight.
51789 +static int ubicom32bl_get_intensity(struct backlight_device *bd)
51791 + struct ubicom32bl_data *ud = (struct ubicom32bl_data *)bl_get_data(bd);
51793 + return ud->cur_intensity;
51797 + * ubicom32bl_init_hw_pwm
51798 + * Set the appropriate PWM registers
51800 +static int ubicom32bl_init_hw_pwm(struct ubicom32bl_data *ud)
51805 + u16_t pwm_cfg = (1 << 13) | (ud->pdata->pwm_prescale << 8) ;
51807 + switch (ud->pdata->pwm_channel) {
51810 + * Channel 0 is in the lower half of PORT C ctl0 and ctl1 (PA5)
51812 + UBICOM32_IO_PORT(RC)->ctl0 &= ~0xFFFF;
51813 + UBICOM32_IO_PORT(RC)->ctl0 |= pwm_cfg;
51814 + UBICOM32_IO_PORT(RC)->ctl1 = ud->pdata->pwm_period << 16;
51817 + * If the port function is not set, set it to GPIO/PWM
51819 + if (!UBICOM32_IO_PORT(RA)->function) {
51820 + UBICOM32_IO_PORT(RA)->function = 3;
51826 + * Channel 1 is in the upper half of PORT C ctl0 and ctl2 (PE4)
51828 + UBICOM32_IO_PORT(RC)->ctl0 &= ~0xFFFF0000;
51829 + UBICOM32_IO_PORT(RC)->ctl0 |= (pwm_cfg << 16);
51830 + UBICOM32_IO_PORT(RC)->ctl2 = ud->pdata->pwm_period << 16;
51833 + * If the port function is not set, set it to GPIO/ExtIOInt
51835 + if (!UBICOM32_IO_PORT(RE)->function) {
51836 + UBICOM32_IO_PORT(RE)->function = 3;
51842 + * Channel 2 is in PORT H ctl0 and ctl1 (PD0)
51844 + UBICOM32_IO_PORT(RH)->ctl0 &= ~0xFFFF0000;
51845 + UBICOM32_IO_PORT(RH)->ctl0 = pwm_cfg;
51846 + UBICOM32_IO_PORT(RH)->ctl1 = ud->pdata->pwm_period << 16;
51849 + * If the port function is not set, set it to GPIO
51851 + if (!UBICOM32_IO_PORT(RD)->function) {
51852 + UBICOM32_IO_PORT(RD)->function = 3;
51861 + * ubicom32bl_init_gpio
51862 + * Allocate the appropriate GPIO
51864 +static int ubicom32bl_init_gpio(struct ubicom32bl_data *ud)
51869 +static struct backlight_ops ubicom32bl_ops = {
51870 + .get_brightness = ubicom32bl_get_intensity,
51871 + .update_status = ubicom32bl_set_intensity,
51875 + * ubicom32bl_probe
51877 +static int ubicom32bl_probe(struct platform_device *pdev)
51879 + const struct ubicom32bl_platform_data *pdata = pdev->dev.platform_data;
51880 + struct ubicom32bl_data *ud;
51881 + struct backlight_device *bldev;
51885 + * Check to see if we have any platform data, if we don't then the backlight is not
51886 + * configured on this device.
51893 + * Allocate our private data
51895 + ud = kzalloc(sizeof(struct ubicom32bl_data), GFP_KERNEL);
51900 + ud->pdata = pdata;
51903 + * Check to see that the platform data is valid for this driver
51905 + switch (pdata->type) {
51906 + case UBICOM32BL_TYPE_PWM:
51909 + * Make sure we have a PWM peripheral
51913 + "move.4 %0, CHIP_ID \n\t"
51916 + if (chipid != 0x00030001) {
51917 + retval = -ENODEV;
51921 + if (pdata->pwm_channel > 3) {
51922 + retval = -ENODEV;
51925 + if (pdata->pwm_prescale > 16) {
51926 + retval = -EINVAL;
51930 + ud->init_fn = ubicom32bl_init_hw_pwm;
51931 + ud->set_intensity_fn = ubicom32bl_set_intensity_hw;
51935 + case UBICOM32BL_TYPE_PWM_HRT:
51936 + // For now, PWM HRT devices are treated as binary lights.
51938 + case UBICOM32BL_TYPE_BINARY:
51939 + ud->init_fn = ubicom32bl_init_gpio;
51940 + ud->set_intensity_fn = ubicom32bl_set_intensity_gpio;
51945 + * Register our backlight device
51947 + bldev = backlight_device_register(DRIVER_NAME, &pdev->dev, ud, &ubicom32bl_ops);
51948 + if (IS_ERR(bldev)) {
51949 + retval = PTR_ERR(bldev);
51953 + ud->bldev = bldev;
51954 + ud->cur_intensity = pdata->default_intensity;
51955 + platform_set_drvdata(pdev, ud);
51958 + * Start up the backlight at the prescribed default intensity
51960 + bldev->props.power = FB_BLANK_UNBLANK;
51961 + bldev->props.max_brightness = UBICOM32BL_MAX_BRIGHTNESS;
51962 + bldev->props.brightness = pdata->default_intensity;
51964 + if (ud->init_fn) {
51965 + if (ud->init_fn(ud) != 0) {
51966 + retval = -ENODEV;
51967 + backlight_device_unregister(ud->bldev);
51971 + ubicom32bl_set_intensity(bldev);
51973 + printk(KERN_INFO DRIVER_NAME ": Backlight driver started\n");
51978 + platform_set_drvdata(pdev, NULL);
51984 + * ubicom32bl_remove
51986 +static int __exit ubicom32bl_remove(struct platform_device *pdev)
51988 + struct ubicom32bl_data *ud = platform_get_drvdata(pdev);
51990 + backlight_device_unregister(ud->bldev);
51991 + platform_set_drvdata(pdev, NULL);
51997 +static struct platform_driver ubicom32bl_driver = {
51999 + .name = DRIVER_NAME,
52000 + .owner = THIS_MODULE,
52003 + .remove = __exit_p(ubicom32bl_remove),
52007 + * ubicom32bl_init
52009 +static int __init ubicom32bl_init(void)
52011 + return platform_driver_probe(&ubicom32bl_driver, ubicom32bl_probe);
52013 +module_init(ubicom32bl_init);
52016 + * ubicom32bl_exit
52018 +static void __exit ubicom32bl_exit(void)
52020 + platform_driver_unregister(&ubicom32bl_driver);
52022 +module_exit(ubicom32bl_exit);
52024 +MODULE_AUTHOR("Patrick Tjin <@ubicom.com>");
52025 +MODULE_DESCRIPTION("Ubicom32 backlight driver");
52026 +MODULE_LICENSE("GPL");
52027 diff -ruN linux-2.6.30.10/drivers/video/backlight/ubicom32lcd.c linux-2.6.30.10-ubi/drivers/video/backlight/ubicom32lcd.c
52028 --- linux-2.6.30.10/drivers/video/backlight/ubicom32lcd.c 1970-01-01 02:00:00.000000000 +0200
52029 +++ linux-2.6.30.10-ubi/drivers/video/backlight/ubicom32lcd.c 2009-12-11 11:45:20.000000000 +0200
52032 + * drivers/video/ubicom32lcd.c
52033 + * LCD initilization code
52035 + * (C) Copyright 2009, Ubicom, Inc.
52037 + * This file is part of the Ubicom32 Linux Kernel Port.
52039 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
52040 + * it and/or modify it under the terms of the GNU General Public License
52041 + * as published by the Free Software Foundation, either version 2 of the
52042 + * License, or (at your option) any later version.
52044 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
52045 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
52046 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
52047 + * the GNU General Public License for more details.
52049 + * You should have received a copy of the GNU General Public License
52050 + * along with the Ubicom32 Linux Kernel Port. If not,
52051 + * see <http://www.gnu.org/licenses/>.
52053 +#include <linux/init.h>
52054 +#include <linux/kernel.h>
52055 +#include <linux/module.h>
52056 +#include <linux/platform_device.h>
52057 +#include <linux/delay.h>
52059 +#include <asm/ip5000.h>
52060 +#include <asm/gpio.h>
52061 +#include <asm/ubicom32lcd.h>
52063 +#include "ubicom32lcd.h"
52065 +#define DRIVER_NAME "ubicom32lcd"
52067 +struct ubicom32lcd_data {
52068 + const struct ubicom32lcd_panel *panel;
52075 + struct ubicom32_io_port *port_data;
52080 + * ubicom32lcd_write
52081 + * Performs a write cycle on the bus (assumes CS asserted, RD & WR set)
52083 +static void ubicom32lcd_write(struct ubicom32lcd_data *ud, int command, u16 data)
52086 + UBICOM32_GPIO_SET_PIN_LOW(ud->pin_rs);
52088 + UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_rs);
52092 + "or.4 4(%[port]), 4(%[port]), %[mask] \n\t"
52093 + "not.4 %[mask], %[mask] \n\t"
52094 + "and.4 8(%[port]), 8(%[port]), %[mask] \n\t"
52095 + "or.4 8(%[port]), 8(%[port]), %[cmd] \n\t"
52097 + : [port] "a" (ud->port_data),
52098 + [mask] "d" (0xFFFF << ud->data_shift),
52099 + [cmd] "d" (data << ud->data_shift)
52103 + UBICOM32_GPIO_SET_PIN_LOW(ud->pin_wr);
52108 + UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_wr);
52115 + * ubicom32lcd_read_data
52116 + * Performs a read cycle on the bus (assumes CS asserted, RD & WR set)
52118 +static u16 ubicom32lcd_read_data(struct ubicom32lcd_data *ud)
52122 + UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_rs);
52125 + "and.4 4(%[port]), 4(%[port]), %[mask]\n\t"
52127 + : [port] "a" (ud->port_data),
52128 + [mask] "d" (~(0xFFFF << ud->data_shift))
52132 + UBICOM32_GPIO_SET_PIN_LOW(ud->pin_rd);
52137 + "lsr.4 %[data], 12(%[port]), %[shamt] \n\t"
52138 + "and.4 %[data], %[data], %[mask] \n\t"
52139 + : [data] "=d" (data)
52140 + : [port] "a" (ud->port_data),
52141 + [mask] "d" (0xFFFF),
52142 + [shamt] "d" (ud->data_shift)
52148 + UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_rd);
52156 + * ubicom32lcd_execute
52157 + * Executes a script for performing operations on the LCD (assumes CS set)
52159 +static void ubicom32lcd_execute(struct ubicom32lcd_data *ud, const struct ubicom32lcd_step *script)
52162 + switch (script->op) {
52163 + case LCD_STEP_CMD:
52164 + ubicom32lcd_write(ud, 1, script->cmd);
52167 + case LCD_STEP_DATA:
52168 + ubicom32lcd_write(ud, 0, script->data);
52171 + case LCD_STEP_CMD_DATA:
52172 + ubicom32lcd_write(ud, 1, script->cmd);
52173 + ubicom32lcd_write(ud, 0, script->data);
52176 + case LCD_STEP_SLEEP:
52177 + udelay(script->data);
52180 + case LCD_STEP_DONE:
52188 + * ubicom32lcd_goto
52189 + * Places the gram pointer at a specific X, Y address
52191 +static void ubicom32lcd_goto(struct ubicom32lcd_data *ud, int x, int y)
52193 + ubicom32lcd_write(ud, 1, ud->panel->horz_reg);
52194 + ubicom32lcd_write(ud, 0, x);
52195 + ubicom32lcd_write(ud, 1, ud->panel->vert_reg);
52196 + ubicom32lcd_write(ud, 0, y);
52197 + ubicom32lcd_write(ud, 1, ud->panel->gram_reg);
52201 + * ubicom32lcd_panel_init
52202 + * Initializes the lcd panel.
52204 +static int ubicom32lcd_panel_init(struct ubicom32lcd_data *ud)
52208 + UBICOM32_GPIO_SET_PIN_LOW(ud->pin_reset);
52209 + UBICOM32_GPIO_SET_PIN_OUTPUT(ud->pin_reset);
52210 + UBICOM32_GPIO_ENABLE(ud->pin_reset);
52213 + "or.4 0x50(%[port]), 0x50(%[port]), %[mask] \n\t"
52214 + "not.4 %[mask], %[mask] \n\t"
52215 + "and.4 0x04(%[port]), 0x04(%[port]), %[mask] \n\t"
52217 + : [port] "a" (ud->port_data),
52218 + [mask] "d" (0xFFFF << ud->data_shift)
52222 + UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_rs);
52223 + UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_rd);
52224 + UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_wr);
52225 + UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_cs);
52227 + UBICOM32_GPIO_SET_PIN_OUTPUT(ud->pin_rs);
52228 + UBICOM32_GPIO_SET_PIN_OUTPUT(ud->pin_rd);
52229 + UBICOM32_GPIO_SET_PIN_OUTPUT(ud->pin_wr);
52230 + UBICOM32_GPIO_SET_PIN_OUTPUT(ud->pin_cs);
52232 + UBICOM32_GPIO_ENABLE(ud->pin_rs);
52233 + UBICOM32_GPIO_ENABLE(ud->pin_rd);
52234 + UBICOM32_GPIO_ENABLE(ud->pin_wr);
52235 + UBICOM32_GPIO_ENABLE(ud->pin_cs);
52239 + UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_reset);
52243 + UBICOM32_GPIO_SET_PIN_LOW(ud->pin_cs);
52245 + id = ubicom32lcd_read_data(ud);
52248 + * We will try to figure out what kind of panel we have if we were not told.
52250 + if (!ud->panel) {
52251 + const struct ubicom32lcd_panel **p = ubicom32lcd_panels;
52253 + if ((*p)->id && ((*p)->id == id)) {
52259 + printk(KERN_WARNING DRIVER_NAME ":Could not find compatible panel, id=%x\n", id);
52266 + * Make sure panel ID matches if we were supplied a panel type
52268 + if (ud->panel->id && (ud->panel->id != id)) {
52269 + UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_cs);
52274 + ubicom32lcd_execute(ud, ud->panel->init_seq);
52276 + ubicom32lcd_goto(ud, 0, 0);
52278 + UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_cs);
52279 + UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_rd);
52280 + UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_wr);
52281 + UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_rs);
52283 + printk(KERN_INFO DRIVER_NAME ": Initialized panel %s\n", ud->panel->desc);
52289 + * ubicom32lcd_probe
52291 +static int ubicom32lcd_probe(struct platform_device *pdev)
52293 + const struct ubicom32lcd_platform_data *pdata = pdev->dev.platform_data;
52294 + struct ubicom32lcd_data *ud;
52298 + * Allocate our private data
52300 + ud = kzalloc(sizeof(struct ubicom32lcd_data), GFP_KERNEL);
52306 + ud->pin_cs = pdata->pin_cs;
52307 + ud->pin_rd = pdata->pin_rd;
52308 + ud->pin_wr = pdata->pin_wr;
52309 + ud->pin_rs = pdata->pin_rs;
52310 + ud->pin_reset = pdata->pin_reset;
52311 + ud->port_data = pdata->port_data;
52312 + ud->data_shift = pdata->data_shift;
52317 + ud->pin_cs = GPIO_RD_4;
52318 + ud->pin_rd = GPIO_RD_5;
52319 + ud->pin_rs = GPIO_RD_3;
52320 + ud->pin_wr = GPIO_RD_2;
52321 + ud->pin_reset = GPIO_RD_7;
52322 + ud->port_data = (struct ubicom32_io_port *)RI;
52323 + ud->data_shift = 0;
52327 + * Initialize the display
52329 + retval = ubicom32lcd_panel_init(ud);
52335 + printk(KERN_INFO DRIVER_NAME ": LCD initialized\n");
52341 + * ubicom32lcd_remove
52343 +static int __exit ubicom32lcd_remove(struct platform_device *pdev)
52345 + struct ubicom32lcd_data *ud = platform_get_drvdata(pdev);
52352 +static struct platform_driver ubicom32lcd_driver = {
52353 + .probe = ubicom32lcd_probe,
52354 + .remove = ubicom32lcd_remove,
52357 + .name = DRIVER_NAME,
52358 + .owner = THIS_MODULE,
52361 + .remove = __exit_p(ubicom32lcd_remove),
52364 +static struct platform_device *ubicom32lcd_device;
52367 + * ubicom32lcd_init
52369 +static int __init ubicom32lcd_init(void)
52373 + res = platform_driver_register(&ubicom32lcd_driver);
52375 + ubicom32lcd_device = platform_device_alloc(DRIVER_NAME, 0);
52376 + if (ubicom32lcd_device) {
52377 + res = platform_device_add(ubicom32lcd_device);
52382 + platform_device_put(ubicom32lcd_device);
52383 + platform_driver_unregister(&ubicom32lcd_driver);
52388 +module_init(ubicom32lcd_init);
52391 + * ubicom32lcd_exit
52393 +static void __exit ubicom32lcd_exit(void)
52395 + platform_device_unregister(ubicom32lcd_device);
52396 + platform_driver_unregister(&ubicom32lcd_driver);
52398 +module_exit(ubicom32lcd_exit);
52400 +MODULE_AUTHOR("Patrick Tjin <@ubicom.com>");
52401 +MODULE_DESCRIPTION("Ubicom32 LCD driver");
52402 +MODULE_LICENSE("GPL");
52403 diff -ruN linux-2.6.30.10/drivers/video/backlight/ubicom32lcd.h linux-2.6.30.10-ubi/drivers/video/backlight/ubicom32lcd.h
52404 --- linux-2.6.30.10/drivers/video/backlight/ubicom32lcd.h 1970-01-01 02:00:00.000000000 +0200
52405 +++ linux-2.6.30.10-ubi/drivers/video/backlight/ubicom32lcd.h 2009-12-11 11:45:20.000000000 +0200
52409 + * Ubicom32 lcd panel drivers
52411 + * (C) Copyright 2009, Ubicom, Inc.
52413 + * This file is part of the Ubicom32 Linux Kernel Port.
52415 + * This Ubicom32 library is free software: you can redistribute
52416 + * it and/or modify it under the terms of the GNU General Public License
52417 + * as published by the Free Software Foundation, either version 2 of the
52418 + * License, or (at your option) any later version.
52420 + * This Ubicom32 library is distributed in the hope that it
52421 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
52422 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
52423 + * the GNU General Public License for more details.
52425 + * You should have received a copy of the GNU General Public License
52426 + * along with the Ubicom32 Linux Kernel Port. If not,
52427 + * see <http://www.gnu.org/licenses/>.
52430 +#ifndef _UBICOM32LCD_H_
52431 +#define _UBICOM32LCD_H_
52433 +enum ubicom32lcd_op {
52435 + * Sleep for (data) ms
52440 + * Execute write of command
52445 + * Execute write of data
52450 + * Execute write of command/data
52452 + LCD_STEP_CMD_DATA,
52460 +struct ubicom32lcd_step {
52461 + enum ubicom32lcd_op op;
52466 +struct ubicom32lcd_panel {
52467 + const struct ubicom32lcd_step *init_seq;
52468 + const char *desc;
52481 +#ifdef CONFIG_LCD_UBICOM32_CFAF240320KTTS
52482 +static const struct ubicom32lcd_step cfaf240320ktts_init_0[] = {
52483 + {LCD_STEP_CMD_DATA, 0x0001, 0x0000,}, // Driver Output Control Register (R01h) Page 14, SPFD5408B Datasheet
52484 + {LCD_STEP_CMD_DATA, 0x0002, 0x0700,}, // LCD Driving Waveform Control (R02h) Page 15, SPFD5408B Datasheet
52485 + {LCD_STEP_CMD_DATA, 0x0003, 0x50A0,}, // Entry Mode (R03h) 0 degrees
52486 + {LCD_STEP_CMD_DATA, 0x0004, 0x0000,}, // Scaling Control register (R04h) Page 16, SPFD5408B Datasheet
52487 + {LCD_STEP_CMD_DATA, 0x0008, 0x0207,}, // Display Control 2 (R08h) Page 17, SPFD5408B Datasheet
52488 + {LCD_STEP_CMD_DATA, 0x0009, 0x0000,}, // Display Control 3 (R09h) Page 18, SPFD5408B Datasheet
52489 + {LCD_STEP_CMD_DATA, 0x000A, 0x0000,}, // Frame Cycle Control (R0Ah) Page 19, SPFD5408B Datasheet
52490 + {LCD_STEP_CMD_DATA, 0x000C, 0x0000,}, // External Display Interface Control 1 (R0Ch) Page 20, SPFD5408B Datasheet
52491 + {LCD_STEP_CMD_DATA, 0x000D, 0x0000,}, // Frame Maker Position (R0Dh) Page 21, SPFD5408B Datasheet
52492 + {LCD_STEP_CMD_DATA, 0x000F, 0x0000,}, // External Display Interface Control 2 (R0Fh) Page 21, SPFD5408B Datasheet
52493 + {LCD_STEP_CMD_DATA, 0x0010, 0x0000,}, // Power Control 1 (R10h) Page 22, SPFD5408B Datasheet
52494 + {LCD_STEP_CMD_DATA, 0x0011, 0x0007,}, // Power Control 2 (R11h) Page 23, SPFD5408B Datasheet
52495 + {LCD_STEP_CMD_DATA, 0x0012, 0x0000,}, // Power Control 3 (R12h) Page 24, SPFD5408B Datasheet
52496 + {LCD_STEP_CMD_DATA, 0x0013, 0x0000,}, // Power Control 4 (R13h) Page 25, SPFD5408B Datasheet
52497 + {LCD_STEP_SLEEP, 0, 200},
52498 + {LCD_STEP_CMD_DATA, 0x0007, 0x0101,}, // Display Control (R07h) Page 16, SPFD5408B Datasheet
52499 + {LCD_STEP_CMD_DATA, 0x0010, 0x12B0,}, // Power Control 1 (R10h) Page 22, SPFD5408B Datasheet
52500 + {LCD_STEP_CMD_DATA, 0x0011, 0x0007,}, // Power Control 2 (R11h) Page 23, SPFD5408B Datasheet
52501 + {LCD_STEP_CMD_DATA, 0x0012, 0x01BB,}, // Power Control 3 (R12h) Page 24, SPFD5408B Datasheet
52502 + {LCD_STEP_SLEEP, 0, 50},
52503 + {LCD_STEP_CMD_DATA, 0x0013, 0x1300,}, // Power Control 4 (R13h) Page 25, SPFD5408B Datasheet
52504 + {LCD_STEP_CMD_DATA, 0x0029, 0x0010,}, // NVM read data 2 (R29h) Page 30, SPFD5408B Datasheet
52505 + {LCD_STEP_SLEEP, 0, 50},
52506 + {LCD_STEP_CMD_DATA, 0x0030, 0x000A,}, // Gamma Control 1 Page 32, SPFD5408B Datasheet
52507 + {LCD_STEP_CMD_DATA, 0x0031, 0x1326,}, // Gamma Control 2 Page 32, SPFD5408B Datasheet
52508 + {LCD_STEP_CMD_DATA, 0x0032, 0x0A29,}, // Gamma Control 3 Page 32, SPFD5408B Datasheet
52509 + {LCD_STEP_CMD_DATA, 0x0033, 0x290A,}, // Gamma Control 4 Page 32, SPFD5408B Datasheet
52510 + {LCD_STEP_CMD_DATA, 0x0034, 0x2613,}, // Gamma Control 5 Page 32, SPFD5408B Datasheet
52511 + {LCD_STEP_CMD_DATA, 0x0035, 0x0A0A,}, // Gamma Control 6 Page 32, SPFD5408B Datasheet
52512 + {LCD_STEP_CMD_DATA, 0x0036, 0x1E03,}, // Gamma Control 7 Page 32, SPFD5408B Datasheet
52513 + {LCD_STEP_CMD_DATA, 0x0037, 0x031E,}, // Gamma Control 8 Page 32, SPFD5408B Datasheet
52514 + {LCD_STEP_CMD_DATA, 0x0038, 0x0706,}, // Gamma Control 9 Page 32, SPFD5408B Datasheet
52515 + {LCD_STEP_CMD_DATA, 0x0039, 0x0303,}, // Gamma Control 10 Page 32, SPFD5408B Datasheet
52516 + {LCD_STEP_CMD_DATA, 0x003A, 0x0E04,}, // Gamma Control 11 Page 32, SPFD5408B Datasheet
52517 + {LCD_STEP_CMD_DATA, 0x003B, 0x0E01,}, // Gamma Control 12 Page 32, SPFD5408B Datasheet
52518 + {LCD_STEP_CMD_DATA, 0x003C, 0x010E,}, // Gamma Control 13 Page 32, SPFD5408B Datasheet
52519 + {LCD_STEP_CMD_DATA, 0x003D, 0x040E,}, // Gamma Control 14 Page 32, SPFD5408B Datasheet
52520 + {LCD_STEP_CMD_DATA, 0x003E, 0x0303,}, // Gamma Control 15 Page 32, SPFD5408B Datasheet
52521 + {LCD_STEP_CMD_DATA, 0x003F, 0x0607,}, // Gamma Control 16 Page 32, SPFD5408B Datasheet
52522 + {LCD_STEP_CMD_DATA, 0x0050, 0x0000,}, // Window Horizontal RAM Address Start (R50h) Page 32, SPFD5408B Datasheet
52523 + {LCD_STEP_CMD_DATA, 0x0051, 0x00EF,}, // Window Horizontal RAM Address End (R51h) Page 32, SPFD5408B Datasheet
52524 + {LCD_STEP_CMD_DATA, 0x0052, 0x0000,}, // Window Vertical RAM Address Start (R52h) Page 33, SPFD5408B Datasheet
52525 + {LCD_STEP_CMD_DATA, 0x0053, 0x013F,}, // Window Vertical RAM Address End (R53h) Page 33, SPFD5408B Datasheet
52526 + {LCD_STEP_CMD_DATA, 0x0060, 0x2700,}, // Driver Output Control (R60h) Page 33, SPFD5408B Datasheet
52527 + {LCD_STEP_CMD_DATA, 0x0061, 0x0001,}, // Driver Output Control (R61h) Page 35, SPFD5408B Datasheet
52528 + {LCD_STEP_CMD_DATA, 0x006A, 0x0000,}, // Vertical Scroll Control (R6Ah) Page 35, SPFD5408B Datasheet
52529 + {LCD_STEP_CMD_DATA, 0x0080, 0x0000,}, // Display Position - Partial Display 1 (R80h) Page 35, SPFD5408B Datasheet
52530 + {LCD_STEP_CMD_DATA, 0x0081, 0x0000,}, // RAM Address Start - Partial Display 1 (R81h) Page 35, SPFD5408B Datasheet
52531 + {LCD_STEP_CMD_DATA, 0x0082, 0x0000,}, // RAM Address End - Partial Display 1 (R82h) Page 36, SPFD5408B Datasheet
52532 + {LCD_STEP_CMD_DATA, 0x0083, 0x0000,}, // Display Position - Partial Display 2 (R83h) Page 36, SPFD5408B Datasheet
52533 + {LCD_STEP_CMD_DATA, 0x0084, 0x0000,}, // RAM Address Start - Partial Display 2 (R84h) Page 36, SPFD5408B Datasheet
52534 + {LCD_STEP_CMD_DATA, 0x0085, 0x0000,}, // RAM Address End - Partial Display 2 (R85h) Page 36, SPFD5408B Datasheet
52535 + {LCD_STEP_CMD_DATA, 0x0090, 0x0010,}, // Panel Interface Control 1 (R90h) Page 36, SPFD5408B Datasheet
52536 + {LCD_STEP_CMD_DATA, 0x0092, 0x0000,}, // Panel Interface Control 2 (R92h) Page 37, SPFD5408B Datasheet
52537 + {LCD_STEP_CMD_DATA, 0x0093, 0x0103,}, // Panel Interface control 3 (R93h) Page 38, SPFD5408B Datasheet
52538 + {LCD_STEP_CMD_DATA, 0x0095, 0x0210,}, // Panel Interface control 4 (R95h) Page 38, SPFD5408B Datasheet
52539 + {LCD_STEP_CMD_DATA, 0x0097, 0x0000,}, // Panel Interface Control 5 (R97h) Page 40, SPFD5408B Datasheet
52540 + {LCD_STEP_CMD_DATA, 0x0098, 0x0000,}, // Panel Interface Control 6 (R98h) Page 41, SPFD5408B Datasheet
52541 + {LCD_STEP_CMD_DATA, 0x0007, 0x0173,}, // Display Control (R07h) Page 16, SPFD5408B Datasheet
52542 + {LCD_STEP_DONE, 0, 0},
52545 +const struct ubicom32lcd_panel cfaf240320ktts_0 = {
52546 + .desc = "CFAF240320KTTS",
52547 + .init_seq = cfaf240320ktts_init_0,
52548 + .horz_reg = 0x20,
52549 + .vert_reg = 0x21,
52550 + .gram_reg = 0x22,
52558 +#ifdef CONFIG_LCD_UBICOM32_CFAF240320KTTS_180
52559 +static const struct ubicom32lcd_step cfaf240320ktts_init_180[] = {
52560 + {LCD_STEP_CMD_DATA, 0x0001, 0x0000,}, // Driver Output Control Register (R01h) Page 14, SPFD5408B Datasheet
52561 + {LCD_STEP_CMD_DATA, 0x0002, 0x0700,}, // LCD Driving Waveform Control (R02h) Page 15, SPFD5408B Datasheet
52562 + {LCD_STEP_CMD_DATA, 0x0003, 0x5000,}, // Entry Mode (R03h) 180 degrees
52563 + {LCD_STEP_CMD_DATA, 0x0004, 0x0000,}, // Scaling Control register (R04h) Page 16, SPFD5408B Datasheet
52564 + {LCD_STEP_CMD_DATA, 0x0008, 0x0207,}, // Display Control 2 (R08h) Page 17, SPFD5408B Datasheet
52565 + {LCD_STEP_CMD_DATA, 0x0009, 0x0000,}, // Display Control 3 (R09h) Page 18, SPFD5408B Datasheet
52566 + {LCD_STEP_CMD_DATA, 0x000A, 0x0000,}, // Frame Cycle Control (R0Ah) Page 19, SPFD5408B Datasheet
52567 + {LCD_STEP_CMD_DATA, 0x000C, 0x0000,}, // External Display Interface Control 1 (R0Ch) Page 20, SPFD5408B Datasheet
52568 + {LCD_STEP_CMD_DATA, 0x000D, 0x0000,}, // Frame Maker Position (R0Dh) Page 21, SPFD5408B Datasheet
52569 + {LCD_STEP_CMD_DATA, 0x000F, 0x0000,}, // External Display Interface Control 2 (R0Fh) Page 21, SPFD5408B Datasheet
52570 + {LCD_STEP_CMD_DATA, 0x0010, 0x0000,}, // Power Control 1 (R10h) Page 22, SPFD5408B Datasheet
52571 + {LCD_STEP_CMD_DATA, 0x0011, 0x0007,}, // Power Control 2 (R11h) Page 23, SPFD5408B Datasheet
52572 + {LCD_STEP_CMD_DATA, 0x0012, 0x0000,}, // Power Control 3 (R12h) Page 24, SPFD5408B Datasheet
52573 + {LCD_STEP_CMD_DATA, 0x0013, 0x0000,}, // Power Control 4 (R13h) Page 25, SPFD5408B Datasheet
52574 + {LCD_STEP_SLEEP, 0, 200},
52575 + {LCD_STEP_CMD_DATA, 0x0007, 0x0101,}, // Display Control (R07h) Page 16, SPFD5408B Datasheet
52576 + {LCD_STEP_CMD_DATA, 0x0010, 0x12B0,}, // Power Control 1 (R10h) Page 22, SPFD5408B Datasheet
52577 + {LCD_STEP_CMD_DATA, 0x0011, 0x0007,}, // Power Control 2 (R11h) Page 23, SPFD5408B Datasheet
52578 + {LCD_STEP_CMD_DATA, 0x0012, 0x01BB,}, // Power Control 3 (R12h) Page 24, SPFD5408B Datasheet
52579 + {LCD_STEP_SLEEP, 0, 50},
52580 + {LCD_STEP_CMD_DATA, 0x0013, 0x1300,}, // Power Control 4 (R13h) Page 25, SPFD5408B Datasheet
52581 + {LCD_STEP_CMD_DATA, 0x0029, 0x0010,}, // NVM read data 2 (R29h) Page 30, SPFD5408B Datasheet
52582 + {LCD_STEP_SLEEP, 0, 50},
52583 + {LCD_STEP_CMD_DATA, 0x0030, 0x000A,}, // Gamma Control 1 Page 32, SPFD5408B Datasheet
52584 + {LCD_STEP_CMD_DATA, 0x0031, 0x1326,}, // Gamma Control 2 Page 32, SPFD5408B Datasheet
52585 + {LCD_STEP_CMD_DATA, 0x0032, 0x0A29,}, // Gamma Control 3 Page 32, SPFD5408B Datasheet
52586 + {LCD_STEP_CMD_DATA, 0x0033, 0x290A,}, // Gamma Control 4 Page 32, SPFD5408B Datasheet
52587 + {LCD_STEP_CMD_DATA, 0x0034, 0x2613,}, // Gamma Control 5 Page 32, SPFD5408B Datasheet
52588 + {LCD_STEP_CMD_DATA, 0x0035, 0x0A0A,}, // Gamma Control 6 Page 32, SPFD5408B Datasheet
52589 + {LCD_STEP_CMD_DATA, 0x0036, 0x1E03,}, // Gamma Control 7 Page 32, SPFD5408B Datasheet
52590 + {LCD_STEP_CMD_DATA, 0x0037, 0x031E,}, // Gamma Control 8 Page 32, SPFD5408B Datasheet
52591 + {LCD_STEP_CMD_DATA, 0x0038, 0x0706,}, // Gamma Control 9 Page 32, SPFD5408B Datasheet
52592 + {LCD_STEP_CMD_DATA, 0x0039, 0x0303,}, // Gamma Control 10 Page 32, SPFD5408B Datasheet
52593 + {LCD_STEP_CMD_DATA, 0x003A, 0x0E04,}, // Gamma Control 11 Page 32, SPFD5408B Datasheet
52594 + {LCD_STEP_CMD_DATA, 0x003B, 0x0E01,}, // Gamma Control 12 Page 32, SPFD5408B Datasheet
52595 + {LCD_STEP_CMD_DATA, 0x003C, 0x010E,}, // Gamma Control 13 Page 32, SPFD5408B Datasheet
52596 + {LCD_STEP_CMD_DATA, 0x003D, 0x040E,}, // Gamma Control 14 Page 32, SPFD5408B Datasheet
52597 + {LCD_STEP_CMD_DATA, 0x003E, 0x0303,}, // Gamma Control 15 Page 32, SPFD5408B Datasheet
52598 + {LCD_STEP_CMD_DATA, 0x003F, 0x0607,}, // Gamma Control 16 Page 32, SPFD5408B Datasheet
52599 + {LCD_STEP_CMD_DATA, 0x0050, 0x0000,}, // Window Horizontal RAM Address Start (R50h) Page 32, SPFD5408B Datasheet
52600 + {LCD_STEP_CMD_DATA, 0x0051, 0x00EF,}, // Window Horizontal RAM Address End (R51h) Page 32, SPFD5408B Datasheet
52601 + {LCD_STEP_CMD_DATA, 0x0052, 0x0000,}, // Window Vertical RAM Address Start (R52h) Page 33, SPFD5408B Datasheet
52602 + {LCD_STEP_CMD_DATA, 0x0053, 0x013F,}, // Window Vertical RAM Address End (R53h) Page 33, SPFD5408B Datasheet
52603 + {LCD_STEP_CMD_DATA, 0x0060, 0x2700,}, // Driver Output Control (R60h) Page 33, SPFD5408B Datasheet
52604 + {LCD_STEP_CMD_DATA, 0x0061, 0x0001,}, // Driver Output Control (R61h) Page 35, SPFD5408B Datasheet
52605 + {LCD_STEP_CMD_DATA, 0x006A, 0x0000,}, // Vertical Scroll Control (R6Ah) Page 35, SPFD5408B Datasheet
52606 + {LCD_STEP_CMD_DATA, 0x0080, 0x0000,}, // Display Position - Partial Display 1 (R80h) Page 35, SPFD5408B Datasheet
52607 + {LCD_STEP_CMD_DATA, 0x0081, 0x0000,}, // RAM Address Start - Partial Display 1 (R81h) Page 35, SPFD5408B Datasheet
52608 + {LCD_STEP_CMD_DATA, 0x0082, 0x0000,}, // RAM Address End - Partial Display 1 (R82h) Page 36, SPFD5408B Datasheet
52609 + {LCD_STEP_CMD_DATA, 0x0083, 0x0000,}, // Display Position - Partial Display 2 (R83h) Page 36, SPFD5408B Datasheet
52610 + {LCD_STEP_CMD_DATA, 0x0084, 0x0000,}, // RAM Address Start - Partial Display 2 (R84h) Page 36, SPFD5408B Datasheet
52611 + {LCD_STEP_CMD_DATA, 0x0085, 0x0000,}, // RAM Address End - Partial Display 2 (R85h) Page 36, SPFD5408B Datasheet
52612 + {LCD_STEP_CMD_DATA, 0x0090, 0x0010,}, // Panel Interface Control 1 (R90h) Page 36, SPFD5408B Datasheet
52613 + {LCD_STEP_CMD_DATA, 0x0092, 0x0000,}, // Panel Interface Control 2 (R92h) Page 37, SPFD5408B Datasheet
52614 + {LCD_STEP_CMD_DATA, 0x0093, 0x0103,}, // Panel Interface control 3 (R93h) Page 38, SPFD5408B Datasheet
52615 + {LCD_STEP_CMD_DATA, 0x0095, 0x0210,}, // Panel Interface control 4 (R95h) Page 38, SPFD5408B Datasheet
52616 + {LCD_STEP_CMD_DATA, 0x0097, 0x0000,}, // Panel Interface Control 5 (R97h) Page 40, SPFD5408B Datasheet
52617 + {LCD_STEP_CMD_DATA, 0x0098, 0x0000,}, // Panel Interface Control 6 (R98h) Page 41, SPFD5408B Datasheet
52618 + {LCD_STEP_CMD_DATA, 0x0007, 0x0173,}, // Display Control (R07h) Page 16, SPFD5408B Datasheet
52619 + {LCD_STEP_DONE, 0, 0},
52622 +const struct ubicom32lcd_panel cfaf240320ktts_180 = {
52623 + .desc = "CFAF240320KTTS 180",
52624 + .init_seq = cfaf240320ktts_init_180,
52625 + .horz_reg = 0x20,
52626 + .vert_reg = 0x21,
52627 + .gram_reg = 0x22,
52635 +#ifdef CONFIG_LCD_UBICOM32_TFT2N0369E_P
52636 +static const struct ubicom32lcd_step tft2n0369ep_init[] = {
52637 + {LCD_STEP_CMD_DATA, 0x0028, 0x0006},
52638 + {LCD_STEP_CMD_DATA, 0x0000, 0x0001},
52639 + {LCD_STEP_SLEEP, 0, 15},
52640 + {LCD_STEP_CMD_DATA, 0x002B, 0x9532},
52641 + {LCD_STEP_CMD_DATA, 0x0003, 0xAAAC},
52642 + {LCD_STEP_CMD_DATA, 0x000C, 0x0002},
52643 + {LCD_STEP_CMD_DATA, 0x000D, 0x000A},
52644 + {LCD_STEP_CMD_DATA, 0x000E, 0x2C00},
52645 + {LCD_STEP_CMD_DATA, 0x001E, 0x00AA},
52646 + {LCD_STEP_CMD_DATA, 0x0025, 0x8000},
52647 + {LCD_STEP_SLEEP, 0, 15},
52648 + {LCD_STEP_CMD_DATA, 0x0001, 0x2B3F},
52649 + {LCD_STEP_CMD_DATA, 0x0002, 0x0600},
52650 + {LCD_STEP_CMD_DATA, 0x0010, 0x0000},
52651 + {LCD_STEP_CMD_DATA, 0x0011, 0x6030},
52652 + {LCD_STEP_SLEEP, 0, 20},
52653 + {LCD_STEP_CMD_DATA, 0x0005, 0x0000},
52654 + {LCD_STEP_CMD_DATA, 0x0006, 0x0000},
52655 + {LCD_STEP_CMD_DATA, 0x0016, 0xEF1C},
52656 + {LCD_STEP_CMD_DATA, 0x0017, 0x0003},
52657 + {LCD_STEP_CMD_DATA, 0x0007, 0x0233},
52658 + {LCD_STEP_CMD_DATA, 0x000B, 0x5312},
52659 + {LCD_STEP_CMD_DATA, 0x000F, 0x0000},
52660 + {LCD_STEP_SLEEP, 0, 20},
52661 + {LCD_STEP_CMD_DATA, 0x0041, 0x0000},
52662 + {LCD_STEP_CMD_DATA, 0x0042, 0x0000},
52663 + {LCD_STEP_CMD_DATA, 0x0048, 0x0000},
52664 + {LCD_STEP_CMD_DATA, 0x0049, 0x013F},
52665 + {LCD_STEP_CMD_DATA, 0x0044, 0xEF00},
52666 + {LCD_STEP_CMD_DATA, 0x0045, 0x0000},
52667 + {LCD_STEP_CMD_DATA, 0x0046, 0x013F},
52668 + {LCD_STEP_CMD_DATA, 0x004A, 0x0000},
52669 + {LCD_STEP_CMD_DATA, 0x004B, 0x0000},
52670 + {LCD_STEP_SLEEP, 0, 20},
52671 + {LCD_STEP_CMD_DATA, 0x0030, 0x0707},
52672 + {LCD_STEP_CMD_DATA, 0x0031, 0x0704},
52673 + {LCD_STEP_CMD_DATA, 0x0032, 0x0204},
52674 + {LCD_STEP_CMD_DATA, 0x0033, 0x0201},
52675 + {LCD_STEP_CMD_DATA, 0x0034, 0x0203},
52676 + {LCD_STEP_CMD_DATA, 0x0035, 0x0204},
52677 + {LCD_STEP_CMD_DATA, 0x0036, 0x0204},
52678 + {LCD_STEP_CMD_DATA, 0x0037, 0x0502},
52679 + {LCD_STEP_CMD_DATA, 0x003A, 0x0302},
52680 + {LCD_STEP_CMD_DATA, 0x003B, 0x0500},
52681 + {LCD_STEP_SLEEP, 0, 20},
52682 + {LCD_STEP_CMD_DATA, 0x0044, 239 << 8 | 0},
52683 + {LCD_STEP_CMD_DATA, 0x0045, 0x0000},
52684 + {LCD_STEP_CMD_DATA, 0x0046, 319},
52685 + {LCD_STEP_DONE, 0, 0},
52688 +const struct ubicom32lcd_panel tft2n0369ep = {
52689 + .desc = "TFT2N0369E-Portrait",
52690 + .init_seq = tft2n0369ep_init,
52691 + .horz_reg = 0x4e,
52692 + .vert_reg = 0x4f,
52693 + .gram_reg = 0x22,
52701 +#ifdef CONFIG_LCD_UBICOM32_TFT2N0369E_L
52702 +static const struct ubicom32lcd_step tft2n0369e_init[] = {
52703 + {LCD_STEP_CMD_DATA, 0x0028, 0x0006},
52704 + {LCD_STEP_CMD_DATA, 0x0000, 0x0001},
52705 + {LCD_STEP_SLEEP, 0, 15},
52706 + {LCD_STEP_CMD_DATA, 0x002B, 0x9532},
52707 + {LCD_STEP_CMD_DATA, 0x0003, 0xAAAC},
52708 + {LCD_STEP_CMD_DATA, 0x000C, 0x0002},
52709 + {LCD_STEP_CMD_DATA, 0x000D, 0x000A},
52710 + {LCD_STEP_CMD_DATA, 0x000E, 0x2C00},
52711 + {LCD_STEP_CMD_DATA, 0x001E, 0x00AA},
52712 + {LCD_STEP_CMD_DATA, 0x0025, 0x8000},
52713 + {LCD_STEP_SLEEP, 0, 15},
52714 + {LCD_STEP_CMD_DATA, 0x0001, 0x2B3F},
52715 + {LCD_STEP_CMD_DATA, 0x0002, 0x0600},
52716 + {LCD_STEP_CMD_DATA, 0x0010, 0x0000},
52717 + {LCD_STEP_CMD_DATA, 0x0011, 0x60A8},
52718 + {LCD_STEP_SLEEP, 0, 20},
52719 + {LCD_STEP_CMD_DATA, 0x0005, 0x0000},
52720 + {LCD_STEP_CMD_DATA, 0x0006, 0x0000},
52721 + {LCD_STEP_CMD_DATA, 0x0016, 0xEF1C},
52722 + {LCD_STEP_CMD_DATA, 0x0017, 0x0003},
52723 + {LCD_STEP_CMD_DATA, 0x0007, 0x0233},
52724 + {LCD_STEP_CMD_DATA, 0x000B, 0x5312},
52725 + {LCD_STEP_CMD_DATA, 0x000F, 0x0000},
52726 + {LCD_STEP_SLEEP, 0, 20},
52727 + {LCD_STEP_CMD_DATA, 0x0041, 0x0000},
52728 + {LCD_STEP_CMD_DATA, 0x0042, 0x0000},
52729 + {LCD_STEP_CMD_DATA, 0x0048, 0x0000},
52730 + {LCD_STEP_CMD_DATA, 0x0049, 0x013F},
52731 + {LCD_STEP_CMD_DATA, 0x0044, 0xEF00},
52732 + {LCD_STEP_CMD_DATA, 0x0045, 0x0000},
52733 + {LCD_STEP_CMD_DATA, 0x0046, 0x013F},
52734 + {LCD_STEP_CMD_DATA, 0x004A, 0x0000},
52735 + {LCD_STEP_CMD_DATA, 0x004B, 0x0000},
52736 + {LCD_STEP_SLEEP, 0, 20},
52737 + {LCD_STEP_CMD_DATA, 0x0030, 0x0707},
52738 + {LCD_STEP_CMD_DATA, 0x0031, 0x0704},
52739 + {LCD_STEP_CMD_DATA, 0x0032, 0x0204},
52740 + {LCD_STEP_CMD_DATA, 0x0033, 0x0201},
52741 + {LCD_STEP_CMD_DATA, 0x0034, 0x0203},
52742 + {LCD_STEP_CMD_DATA, 0x0035, 0x0204},
52743 + {LCD_STEP_CMD_DATA, 0x0036, 0x0204},
52744 + {LCD_STEP_CMD_DATA, 0x0037, 0x0502},
52745 + {LCD_STEP_CMD_DATA, 0x003A, 0x0302},
52746 + {LCD_STEP_CMD_DATA, 0x003B, 0x0500},
52747 + {LCD_STEP_SLEEP, 0, 20},
52748 + {LCD_STEP_CMD_DATA, 0x0044, 239 << 8 | 0},
52749 + {LCD_STEP_CMD_DATA, 0x0045, 0x0000},
52750 + {LCD_STEP_CMD_DATA, 0x0046, 319},
52751 + {LCD_STEP_DONE, 0, 0},
52754 +const struct ubicom32lcd_panel tft2n0369e = {
52755 + .desc = "TFT2N0369E-Landscape",
52756 + .init_seq = tft2n0369e_init,
52757 + .horz_reg = 0x4e,
52758 + .vert_reg = 0x4f,
52759 + .gram_reg = 0x22,
52767 +#ifdef CONFIG_LCD_UBICOM32_CFAF240400D
52768 +static const struct ubicom32lcd_step cfaf240400d_init[] = {
52769 + {LCD_STEP_CMD_DATA, 0x0606, 0x0000}, // Pin Control (R606h) // Page 41 of SPFD5420A Datasheet
52770 + {LCD_STEP_SLEEP, 0, 50},
52771 + {LCD_STEP_CMD_DATA, 0x0007, 0x0001}, // Display Control 1 (R007h) // Page 16 of SPFD5420A Datasheet
52772 + {LCD_STEP_SLEEP, 0, 50},
52773 + {LCD_STEP_CMD_DATA, 0x0110, 0x0001}, // Power Control 6(R110h) // Page 30 of SPFD5420A Datasheet
52774 + {LCD_STEP_SLEEP, 0, 50},
52775 + {LCD_STEP_CMD_DATA, 0x0100, 0x17B0}, // Power Control 1 (R100h) // Page 26 of SPFD5420A Datasheet
52776 + {LCD_STEP_CMD_DATA, 0x0101, 0x0147}, // Power Control 2 (R101h) // Page 27 of SPFD5420A Datasheet
52777 + {LCD_STEP_CMD_DATA, 0x0102, 0x019D}, // Power Control 3 (R102h) // Page 28 of SPFD5420A Datasheet
52778 + {LCD_STEP_CMD_DATA, 0x0103, 0x3600}, // Power Control 4 (R103h) // Page 29 of SPFD5420A Datasheet
52779 + {LCD_STEP_CMD_DATA, 0x0281, 0x0010}, // NVM read data 2 (R281h) // Page 34 of SPFD5420A Datasheet
52780 + {LCD_STEP_SLEEP, 0, 50},
52781 + {LCD_STEP_CMD_DATA, 0x0102, 0x01BD}, // Power Control 3 (R102h) // Page 28 of SPFD5420A Datasheet
52782 + {LCD_STEP_SLEEP, 0, 50},
52784 + //--------------- Power control 1~6 ---------------//
52785 + {LCD_STEP_CMD_DATA, 0x0100, 0x16B0}, // Power Control 1 (R100h) // Page 26 of SPFD5420A Datasheet
52786 + {LCD_STEP_CMD_DATA, 0x0101, 0x0147}, // Power Control 2 (R101h) // Page 27 of SPFD5420A Datasheet
52787 + {LCD_STEP_CMD_DATA, 0x0102, 0x01BD}, // Power Control 3 (R102h) // Page 28 of SPFD5420A Datasheet
52788 + {LCD_STEP_CMD_DATA, 0x0103, 0x2d00}, // Power Control 4 (R103h) // Page 29 of SPFD5420A Datasheet
52789 + {LCD_STEP_CMD_DATA, 0x0107, 0x0000}, // Power Control 5 (R107h) // Page 30 of SPFD5420A Datasheet
52790 + {LCD_STEP_CMD_DATA, 0x0110, 0x0001}, // Power Control 6(R110h) // Page 30 of SPFD5420A Datasheet
52791 + {LCD_STEP_CMD_DATA, 0x0280, 0x0000}, // NVM read data 1 (R280h) // Page 33 of SPFD5420A Datasheet
52792 + {LCD_STEP_CMD_DATA, 0x0281, 0x0006}, // NVM read data 2 (R281h) // Page 34 of SPFD5420A Datasheet
52793 + {LCD_STEP_CMD_DATA, 0x0282, 0x0000}, // NVM read data 3 (R282h) // Page 34 of SPFD5420A Datasheet
52795 + //------- Gamma 2.2 control (R300h to R30Fh) ------//
52796 + {LCD_STEP_CMD_DATA, 0x0300, 0x0101},
52797 + {LCD_STEP_CMD_DATA, 0x0301, 0x0b27},
52798 + {LCD_STEP_CMD_DATA, 0x0302, 0x132a},
52799 + {LCD_STEP_CMD_DATA, 0x0303, 0x2a13},
52800 + {LCD_STEP_CMD_DATA, 0x0304, 0x270b},
52801 + {LCD_STEP_CMD_DATA, 0x0305, 0x0101},
52802 + {LCD_STEP_CMD_DATA, 0x0306, 0x1205},
52803 + {LCD_STEP_CMD_DATA, 0x0307, 0x0512},
52804 + {LCD_STEP_CMD_DATA, 0x0308, 0x0005},
52805 + {LCD_STEP_CMD_DATA, 0x0309, 0x0003},
52806 + {LCD_STEP_CMD_DATA, 0x030A, 0x0f04},
52807 + {LCD_STEP_CMD_DATA, 0x030B, 0x0f00},
52808 + {LCD_STEP_CMD_DATA, 0x030C, 0x000f},
52809 + {LCD_STEP_CMD_DATA, 0x030D, 0x040f},
52810 + {LCD_STEP_CMD_DATA, 0x030E, 0x0300},
52811 + {LCD_STEP_CMD_DATA, 0x030F, 0x0500},
52813 + {LCD_STEP_CMD_DATA, 0x0400, 0x3500}, // Base Image Number of Line (R400h) // Page 36 of SPFD5420A Datasheet
52814 + {LCD_STEP_CMD_DATA, 0x0401, 0x0001}, // Base Image Display Control (R401h) // Page 39 of SPFD5420A Datasheet
52815 + {LCD_STEP_CMD_DATA, 0x0404, 0x0000}, // Based Image Vertical Scroll Control (R404h) // Page 40 of SPFD5420A Datasheet
52817 + //--------------- Normal set ---------------//
52818 + {LCD_STEP_CMD_DATA, 0x0000, 0x0000}, // ID Read Register (R000h) // Page 13 of SPFD5420A Datasheet
52819 + {LCD_STEP_CMD_DATA, 0x0001, 0x0100}, // Driver Output Control Register (R001h) // Page 14 of SPFD5420A Datasheet
52820 + {LCD_STEP_CMD_DATA, 0x0002, 0x0100}, // LCD Driving Waveform Control (R002h) // Page 14 of SPFD5420A Datasheet
52821 + {LCD_STEP_CMD_DATA, 0x0003, 0x1030}, // Entry Mode (R003h) // Page 15 of SPFD5420A Datasheet
52822 + {LCD_STEP_CMD_DATA, 0x0006, 0x0000}, // Display Control 1 (R007h) // Page 16 of SPFD5420A Datasheet
52823 + {LCD_STEP_CMD_DATA, 0x0008, 0x0808}, // Display Control 2 (R008h) // Page 17 of SPFD5420A Datasheet
52824 + {LCD_STEP_CMD_DATA, 0x0009, 0x0001}, // Display Control 3 (R009h) // Page 18 of SPFD5420A Datasheet
52825 + {LCD_STEP_CMD_DATA, 0x000B, 0x0010}, // Low Power Control (R00Bh) // Page 19 of SPFD5420A Datasheet
52826 + {LCD_STEP_CMD_DATA, 0x000C, 0x0000}, // External Display Interface Control 1 (R00Ch) // Page 19 of SPFD5420A Datasheet
52827 + {LCD_STEP_CMD_DATA, 0x000F, 0x0000}, // External Display Interface Control 2 (R00Fh) // Page 20 of SPFD5420A Datasheet
52828 + {LCD_STEP_CMD_DATA, 0x0007, 0x0001}, // Display Control 1 (R007h) // Page 16 of SPFD5420A Datasheet
52830 + //--------------- Panel interface control 1~6 ---------------//
52831 + {LCD_STEP_CMD_DATA, 0x0010, 0x0012}, // Panel Interface Control 1 (R010h) // Page 20 of SPFD5420A Datasheet
52832 + {LCD_STEP_CMD_DATA, 0x0011, 0x0202}, // Panel Interface Control 2 (R011h) // Page 21 of SPFD5420A Datasheet
52833 + {LCD_STEP_CMD_DATA, 0x0012, 0x0300}, // Panel Interface control 3 (R012h) // Page 22 of SPFD5420A Datasheet
52834 + {LCD_STEP_CMD_DATA, 0x0020, 0x021E}, // Panel Interface control 4 (R020h) // Page 22 of SPFD5420A Datasheet
52835 + {LCD_STEP_CMD_DATA, 0x0021, 0x0202}, // Panel Interface Control 5 (021Rh) // Page 24 of SPFD5420A Datasheet
52836 + {LCD_STEP_CMD_DATA, 0x0022, 0x0100}, // Panel Interface Control 6 (R022h) // Page 25 of SPFD5420A Datasheet
52837 + {LCD_STEP_CMD_DATA, 0x0090, 0x8000}, // Frame Marker Control (R090h) // Page 25 of SPFD5420A Datasheet
52839 + //--------------- Partial display ---------------//
52840 + {LCD_STEP_CMD_DATA, 0x0210, 0x0000}, // Window Horizontal RAM Address Start (R210h) // Page 35 of SPFD5420A Datasheet
52841 + {LCD_STEP_CMD_DATA, 0x0211, 0x00EF}, // Window Horziontal RAM Address End (R211h) // Page 35 of SPFD5420A Datasheet
52842 + {LCD_STEP_CMD_DATA, 0x0212, 0x0000}, // Window Vertical RAM Address Start (R212h) // Page 35 of SPFD5420A Datasheet
52843 + {LCD_STEP_CMD_DATA, 0x0213, 0x018F}, // Window Vertical RAM Address End (R213h) // Page 35 of SPFD5420A Datasheet
52844 + {LCD_STEP_CMD_DATA, 0x0500, 0x0000}, // Display Position - Partial Display 1 (R500h) // Page 40 of SPFD5420A Datasheet
52845 + {LCD_STEP_CMD_DATA, 0x0501, 0x0000}, // RAM Address Start - Partial Display 1 (R501h)// Page 40 of SPFD5420A Datasheet
52846 + {LCD_STEP_CMD_DATA, 0x0502, 0x0000}, // RAM Address End - Partail Display 1 (R502h) // Page 40 of SPFD5420A Datasheet
52847 + {LCD_STEP_CMD_DATA, 0x0503, 0x0000}, // Display Position - Partial Display 2 (R503h) // Page 40 of SPFD5420A Datasheet
52848 + {LCD_STEP_CMD_DATA, 0x0504, 0x0000}, // RAM Address Start . Partial Display 2 (R504h)// Page 41 of SPFD5420A Datasheet
52849 + {LCD_STEP_CMD_DATA, 0x0505, 0x0000}, // RAM Address End . Partial Display 2 (R505h) // Page 41 of SPFD5420A Datasheet
52850 + {LCD_STEP_CMD_DATA, 0x0606, 0x0000}, // Pin Control (R606h) // Page 41 of SPFD5420A Datasheet
52851 + {LCD_STEP_CMD_DATA, 0x06F0, 0x0000}, // NVM Access Control (R6F0h) // Page 41 of SPFD5420A Datasheet
52852 + {LCD_STEP_CMD_DATA, 0x0007, 0x0173}, // Display Control 1 (R007h) // Page 16 of SPFD5420A Datasheet
52853 + {LCD_STEP_SLEEP, 0, 50},
52854 + {LCD_STEP_CMD_DATA, 0x0007, 0x0171}, // Display Control 1 (R007h) // Page 16 of SPFD5420A Datasheet
52855 + {LCD_STEP_SLEEP, 0, 10},
52856 + {LCD_STEP_CMD_DATA, 0x0007, 0x0173}, // Display Control 1 (R007h) // Page 16 of SPFD5420A Datasheet
52857 + {LCD_STEP_DONE, 0, 0},
52860 +const struct ubicom32lcd_panel cfaf240400d = {
52861 + .desc = "CFAF240400D",
52862 + .init_seq = cfaf240400d_init,
52863 + .horz_reg = 0x0200,
52864 + .vert_reg = 0x0201,
52865 + .gram_reg = 0x0202,
52873 +#ifdef CONFIG_LCD_UBICOM32_CFAF240400F
52874 +static const struct ubicom32lcd_step cfaf320240f_init[] = {
52875 + {LCD_STEP_CMD_DATA, 0x0028, 0x0006}, // VCOM OTP Page 55-56 of SSD2119 datasheet
52876 + {LCD_STEP_CMD_DATA, 0x0000, 0x0001}, // start Oscillator Page 36 of SSD2119 datasheet
52877 + {LCD_STEP_CMD_DATA, 0x0010, 0x0000}, // Sleep mode Page 49 of SSD2119 datasheet
52878 + {LCD_STEP_CMD_DATA, 0x0001, 0x32EF}, // Driver Output Control Page 36-39 of SSD2119 datasheet
52879 + {LCD_STEP_CMD_DATA, 0x0002, 0x0600}, // LCD Driving Waveform Control Page 40-42 of SSD2119 datasheet
52880 + {LCD_STEP_CMD_DATA, 0x0003, 0x6A38}, // Power Control 1 Page 43-44 of SSD2119 datasheet
52881 + {LCD_STEP_CMD_DATA, 0x0011, 0x6870}, // Entry Mode Page 50-52 of SSD2119 datasheet
52882 + {LCD_STEP_CMD_DATA, 0X000F, 0x0000}, // Gate Scan Position Page 49 of SSD2119 datasheet
52883 + {LCD_STEP_CMD_DATA, 0X000B, 0x5308}, // Frame Cycle Control Page 45 of SSD2119 datasheet
52884 + {LCD_STEP_CMD_DATA, 0x000C, 0x0003}, // Power Control 2 Page 47 of SSD2119 datasheet
52885 + {LCD_STEP_CMD_DATA, 0x000D, 0x000A}, // Power Control 3 Page 48 of SSD2119 datasheet
52886 + {LCD_STEP_CMD_DATA, 0x000E, 0x2E00}, // Power Control 4 Page 48 of SSD2119 datasheet
52887 + {LCD_STEP_CMD_DATA, 0x001E, 0x00BE}, // Power Control 5 Page 53 of SSD2119 datasheet
52888 + {LCD_STEP_CMD_DATA, 0x0025, 0x8000}, // Frame Frequency Control Page 53 of SSD2119 datasheet
52889 + {LCD_STEP_CMD_DATA, 0x0026, 0x7800}, // Analog setting Page 54 of SSD2119 datasheet
52890 + {LCD_STEP_CMD_DATA, 0x004E, 0x0000}, // Ram Address Set Page 58 of SSD2119 datasheet
52891 + {LCD_STEP_CMD_DATA, 0x004F, 0x0000}, // Ram Address Set Page 58 of SSD2119 datasheet
52892 + {LCD_STEP_CMD_DATA, 0x0012, 0x08D9}, // Sleep mode Page 49 of SSD2119 datasheet
52894 + // Gamma Control (R30h to R3Bh) -- Page 56 of SSD2119 datasheet
52895 + {LCD_STEP_CMD_DATA, 0x0030, 0x0000},
52896 + {LCD_STEP_CMD_DATA, 0x0031, 0x0104},
52897 + {LCD_STEP_CMD_DATA, 0x0032, 0x0100},
52898 + {LCD_STEP_CMD_DATA, 0x0033, 0x0305},
52899 + {LCD_STEP_CMD_DATA, 0x0034, 0x0505},
52900 + {LCD_STEP_CMD_DATA, 0x0035, 0x0305},
52901 + {LCD_STEP_CMD_DATA, 0x0036, 0x0707},
52902 + {LCD_STEP_CMD_DATA, 0x0037, 0x0300},
52903 + {LCD_STEP_CMD_DATA, 0x003A, 0x1200},
52904 + {LCD_STEP_CMD_DATA, 0x003B, 0x0800},
52906 + {LCD_STEP_CMD_DATA, 0x0007, 0x0033}, // Display Control Page 45 of SSD2119 datasheet
52908 + {LCD_STEP_CMD_DATA, 0x0044, 0xEF00}, // Vertical RAM address position Page 57 of SSD2119 datasheet
52909 + {LCD_STEP_CMD_DATA, 0x0045, 0x0000}, // Horizontal RAM address position Page 57 of SSD2119 datasheet
52910 + {LCD_STEP_CMD_DATA, 0x0046, 0x013F}, // Horizontal RAM address position Page 57 of SSD2119 datasheet
52912 + {LCD_STEP_SLEEP, 0, 150},
52914 + {LCD_STEP_DONE, 0, 0},
52917 +const struct ubicom32lcd_panel cfaf320240f = {
52918 + .desc = "CFAF320240F",
52919 + .init_seq = cfaf320240f_init,
52920 + .horz_reg = 0x4e,
52921 + .vert_reg = 0x4f,
52922 + .gram_reg = 0x22,
52930 +const struct ubicom32lcd_panel *ubicom32lcd_panels[] = {
52931 +#ifdef CONFIG_LCD_UBICOM32_CFAF240400KTTS_180
52932 + &cfaf240320ktts_180,
52934 +#ifdef CONFIG_LCD_UBICOM32_CFAF240400KTTS
52935 + &cfaf240320ktts_0,
52937 +#ifdef CONFIG_LCD_UBICOM32_CFAF240400D
52940 +#ifdef CONFIG_LCD_UBICOM32_TFT2N0369E_P
52943 +#ifdef CONFIG_LCD_UBICOM32_TFT2N0369E_L
52946 +#ifdef CONFIG_LCD_UBICOM32_CFAF240400F
52953 diff -ruN linux-2.6.30.10/drivers/video/backlight/ubicom32lcdpower.c linux-2.6.30.10-ubi/drivers/video/backlight/ubicom32lcdpower.c
52954 --- linux-2.6.30.10/drivers/video/backlight/ubicom32lcdpower.c 1970-01-01 02:00:00.000000000 +0200
52955 +++ linux-2.6.30.10-ubi/drivers/video/backlight/ubicom32lcdpower.c 2009-12-11 11:45:20.000000000 +0200
52958 + * drivers/video/backlight/ubicom32lcdpowerpower.c
52959 + * LCD power driver for the Ubicom32 platform
52961 + * (C) Copyright 2009, Ubicom, Inc.
52963 + * This file is part of the Ubicom32 Linux Kernel Port.
52965 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
52966 + * it and/or modify it under the terms of the GNU General Public License
52967 + * as published by the Free Software Foundation, either version 2 of the
52968 + * License, or (at your option) any later version.
52970 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
52971 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
52972 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
52973 + * the GNU General Public License for more details.
52975 + * You should have received a copy of the GNU General Public License
52976 + * along with the Ubicom32 Linux Kernel Port. If not,
52977 + * see <http://www.gnu.org/licenses/>.
52979 + * Ubicom32 implementation derived from (with many thanks):
52984 +#include <linux/init.h>
52985 +#include <linux/kernel.h>
52986 +#include <linux/module.h>
52987 +#include <linux/platform_device.h>
52988 +#include <linux/lcd.h>
52989 +#include <linux/fb.h>
52990 +#include <linux/gpio.h>
52992 +#include <asm/ubicom32lcdpower.h>
52993 +#include <asm/ip5000.h>
52995 +#define DRIVER_NAME "ubicom32lcdpower"
52997 +struct ubicom32lcdpower_data {
52999 + * Pointer to the platform data structure. Keep this around since we need values
53000 + * from it to set the backlight intensity.
53002 + const struct ubicom32lcdpower_platform_data *pdata;
53005 + * LCD device, we have to save this for use when we remove ourselves.
53007 + struct lcd_device *lcddev;
53011 + * ubicom32lcdpower_set_power
53013 +static int ubicom32lcdpower_set_power(struct lcd_device *ld, int power)
53015 + struct ubicom32lcdpower_data *ud = (struct ubicom32lcdpower_data *)lcd_get_data(ld);
53016 + if (power == FB_BLANK_UNBLANK) {
53017 + gpio_direction_output(ud->pdata->vgh_gpio, ud->pdata->vgh_polarity);
53021 + gpio_direction_output(ud->pdata->vgh_gpio, !ud->pdata->vgh_polarity);
53026 + * ubicom32lcdpower_get_power
53028 +static int ubicom32lcdpower_get_power(struct lcd_device *ld)
53030 + struct ubicom32lcdpower_data *ud = (struct ubicom32lcdpower_data *)lcd_get_data(ld);
53031 + int vgh = gpio_get_value(ud->pdata->vgh_gpio);
53032 + if ((vgh && ud->pdata->vgh_polarity) || (!vgh && !ud->pdata->vgh_polarity)) {
53039 +static struct lcd_ops ubicom32lcdpower_ops = {
53040 + .get_power = ubicom32lcdpower_get_power,
53041 + .set_power = ubicom32lcdpower_set_power,
53045 + * ubicom32lcdpower_probe
53047 +static int ubicom32lcdpower_probe(struct platform_device *pdev)
53049 + const struct ubicom32lcdpower_platform_data *pdata = pdev->dev.platform_data;
53050 + struct ubicom32lcdpower_data *ud;
53051 + struct lcd_device *lcddev;
53055 + * Check to see if we have any platform data, if we don't have a LCD to control
53062 + * Allocate our private data
53064 + ud = kzalloc(sizeof(struct ubicom32lcdpower_data), GFP_KERNEL);
53069 + ud->pdata = pdata;
53072 + * Request our GPIOs
53074 + retval = gpio_request(pdata->vgh_gpio, "vgh");
53076 + dev_err(&pdev->dev, "Failed to allocate vgh GPIO\n");
53081 + * Register our lcd device
53083 + lcddev = lcd_device_register(DRIVER_NAME, &pdev->dev, ud, &ubicom32lcdpower_ops);
53084 + if (IS_ERR(lcddev)) {
53085 + retval = PTR_ERR(lcddev);
53089 + ud->lcddev = lcddev;
53090 + platform_set_drvdata(pdev, ud);
53092 + ubicom32lcdpower_set_power(lcddev, FB_BLANK_UNBLANK);
53094 + printk(KERN_INFO DRIVER_NAME ": LCD driver started\n");
53099 + gpio_free(pdata->vgh_gpio);
53102 + platform_set_drvdata(pdev, NULL);
53108 + * ubicom32lcdpower_remove
53110 +static int __exit ubicom32lcdpower_remove(struct platform_device *pdev)
53112 + struct ubicom32lcdpower_data *ud = platform_get_drvdata(pdev);
53114 + lcd_device_unregister(ud->lcddev);
53115 + platform_set_drvdata(pdev, NULL);
53121 +static struct platform_driver ubicom32lcdpower_driver = {
53123 + .name = DRIVER_NAME,
53124 + .owner = THIS_MODULE,
53127 + .remove = __exit_p(ubicom32lcdpower_remove),
53131 + * ubicom32lcdpower_init
53133 +static int __init ubicom32lcdpower_init(void)
53135 + return platform_driver_probe(&ubicom32lcdpower_driver, ubicom32lcdpower_probe);
53137 +module_init(ubicom32lcdpower_init);
53140 + * ubicom32lcdpower_exit
53142 +static void __exit ubicom32lcdpower_exit(void)
53144 + platform_driver_unregister(&ubicom32lcdpower_driver);
53146 +module_exit(ubicom32lcdpower_exit);
53148 +MODULE_AUTHOR("Patrick Tjin <@ubicom.com>");
53149 +MODULE_DESCRIPTION("Ubicom32 lcd power driver");
53150 +MODULE_LICENSE("GPL");
53151 diff -ruN linux-2.6.30.10/drivers/video/Kconfig linux-2.6.30.10-ubi/drivers/video/Kconfig
53152 --- linux-2.6.30.10/drivers/video/Kconfig 2009-12-04 08:00:07.000000000 +0200
53153 +++ linux-2.6.30.10-ubi/drivers/video/Kconfig 2009-12-11 11:45:20.000000000 +0200
53154 @@ -609,6 +609,50 @@
53155 This display is a QVGA 320x240 24-bit RGB display interfaced by an 8-bit wide PPI
53156 It uses PPI[0..7] PPI_FS1, PPI_FS2 and PPI_CLK.
53158 +config FB_UBICOM32
53159 + tristate "Ubicom32 Frame Buffer driver"
53160 + depends on FB && UBICOM32
53161 + select FB_CFB_FILLRECT
53162 + select FB_CFB_COPYAREA
53163 + select FB_CFB_IMAGEBLIT
53164 + select FONT_6x11 if FRAMEBUFFER_CONSOLE
53166 + This is the framebuffer device driver for the Ubicom32 architecture.
53167 + You can configure video memory by using kernel command line parameters, for example:
53168 + video=ubicomfb:vram_size=512,init_value=0xffff
53170 +config FB_UBICOM32_PLIO80
53171 + tristate "Ubicom32 80 Bus PLIO Frame Buffer driver"
53172 + depends on FB && UBICOM32
53173 + select FB_CFB_FILLRECT
53174 + select FB_CFB_COPYAREA
53175 + select FB_CFB_IMAGEBLIT
53176 + select FONT_6x11 if FRAMEBUFFER_CONSOLE
53177 + select UBICOM32_PLIO
53179 + This is a framebuffer device driver for the Ubicom32 architecture.
53180 + You can configure the xres, yres and vram size (in kilobytes) by using
53181 + kernel command line parameters, for example:
53182 + video=ubicom32vfb:xres=320,yres=240,vram_size=512
53184 +config FB_UBICOM32_VIRTUAL
53185 + tristate "Ubicom32 Virtual Frame Buffer driver"
53186 + depends on FB && UBICOM32
53187 + select FB_CFB_FILLRECT
53188 + select FB_CFB_COPYAREA
53189 + select FB_CFB_IMAGEBLIT
53190 + select FONT_6x11 if FRAMEBUFFER_CONSOLE
53192 + This is a virtual framebuffer device driver for the Ubicom32 architecture.
53193 + You can configure the xres, yres and vram size (in kilobytes) by using
53194 + kernel command line parameters, for example:
53195 + video=ubicom32vfb:xres=320,yres=240,vram_size=512
53197 +config FB_UBICOM32_VIRTUAL_NOAUTO
53198 + bool "Do not automatically load"
53199 + depends on FB_UBICOM32_VIRTUAL
53201 + Select this option to prevent the VFB from automatically loading at boot.
53204 tristate "HP STI frame buffer device support"
53205 diff -ruN linux-2.6.30.10/drivers/video/Makefile linux-2.6.30.10-ubi/drivers/video/Makefile
53206 --- linux-2.6.30.10/drivers/video/Makefile 2009-12-04 08:00:07.000000000 +0200
53207 +++ linux-2.6.30.10-ubi/drivers/video/Makefile 2009-12-11 11:45:20.000000000 +0200
53208 @@ -136,6 +136,10 @@
53209 obj-$(CONFIG_FB_BFIN_T350MCQB) += bfin-t350mcqb-fb.o
53210 obj-$(CONFIG_FB_MX3) += mx3fb.o
53212 +obj-$(CONFIG_FB_UBICOM32) += ubicom32fb.o
53213 +obj-$(CONFIG_FB_UBICOM32_PLIO80) += ubicom32plio80.o
53214 +obj-$(CONFIG_FB_UBICOM32_VIRTUAL) += ubicom32vfb.o
53216 # the test framebuffer is last
53217 obj-$(CONFIG_FB_VIRTUAL) += vfb.o
53219 diff -ruN linux-2.6.30.10/drivers/video/ubicom32fb.c linux-2.6.30.10-ubi/drivers/video/ubicom32fb.c
53220 --- linux-2.6.30.10/drivers/video/ubicom32fb.c 1970-01-01 02:00:00.000000000 +0200
53221 +++ linux-2.6.30.10-ubi/drivers/video/ubicom32fb.c 2009-12-11 11:45:21.000000000 +0200
53224 + * drivers/video/ubicom32fb.c
53225 + * Ubicom32 frame buffer driver
53227 + * (C) Copyright 2009, Ubicom, Inc.
53229 + * This file is part of the Ubicom32 Linux Kernel Port.
53231 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
53232 + * it and/or modify it under the terms of the GNU General Public License
53233 + * as published by the Free Software Foundation, either version 2 of the
53234 + * License, or (at your option) any later version.
53236 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
53237 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
53238 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
53239 + * the GNU General Public License for more details.
53241 + * You should have received a copy of the GNU General Public License
53242 + * along with the Ubicom32 Linux Kernel Port. If not,
53243 + * see <http://www.gnu.org/licenses/>.
53245 + * Ubicom32 implementation derived from (with many thanks):
53252 + * This driver was based on skeletonfb.c, Skeleton for a frame buffer device by
53253 + * Geert Uytterhoeven.
53256 +#include <linux/device.h>
53257 +#include <linux/module.h>
53258 +#include <linux/kernel.h>
53259 +#include <linux/version.h>
53260 +#include <linux/errno.h>
53261 +#include <linux/string.h>
53262 +#include <linux/mm.h>
53263 +#include <linux/fb.h>
53264 +#include <linux/init.h>
53265 +#include <linux/dma-mapping.h>
53266 +#include <linux/platform_device.h>
53267 +#include <linux/device.h>
53268 +#include <linux/uaccess.h>
53269 +#include <linux/interrupt.h>
53271 +#include <asm/io.h>
53272 +#include <asm/ip5000.h>
53273 +#include <asm/vdc_tio.h>
53274 +#include <asm/ubicom32fb.h>
53276 +#define DRIVER_NAME "ubicom32fb"
53277 +#define DRIVER_DESCRIPTION "Ubicom32 frame buffer driver"
53279 +#define PALETTE_ENTRIES_NO 16
53282 + * Option variables
53284 + * vram_size: VRAM size in kilobytes, subject to alignment
53286 +static int vram_size = 0;
53287 +module_param(vram_size, int, 0);
53288 +MODULE_PARM_DESC(vram, "VRAM size, in kilobytes to allocate, should be at least the size of one screen, subject to alignment");
53289 +static int init_value = 0;
53290 +module_param(init_value, int, 0);
53291 +MODULE_PARM_DESC(init, "Initial value of the framebuffer (16-bit number).");
53294 + * fb_fix_screeninfo defines the non-changeable properties of the VDC, depending on what mode it is in.
53296 +static struct fb_fix_screeninfo ubicom32fb_fix = {
53297 + .id = "Ubicom32",
53298 + .type = FB_TYPE_PACKED_PIXELS,
53299 + .visual = FB_VISUAL_TRUECOLOR,
53300 + .accel = FB_ACCEL_UBICOM32,
53304 + * Filled in at probe time when we find out what the hardware supports
53306 +static struct fb_var_screeninfo ubicom32fb_var;
53309 + * Private data structure
53311 +struct ubicom32fb_drvdata {
53312 + struct fb_info *fbinfo;
53316 + * The address of the framebuffer in memory
53319 + void *fb_aligned;
53322 + * Total size of vram including alignment allowance
53324 + u32 total_vram_size;
53327 + * Interrupt to set when changing registers
53332 + * Optional: Interrupt used by TIO to signal us
53337 + * Base address of the regs for VDC_TIO
53339 + volatile struct vdc_tio_vp_regs *regs;
53342 + * non-zero if we are in yuv mode
53347 + * Fake palette of 16 colors
53349 + u32 pseudo_palette[PALETTE_ENTRIES_NO];
53352 + * Wait queue and lock used to block when we need to wait
53353 + * for something to happen.
53355 + wait_queue_head_t waitq;
53356 + struct mutex lock;
53361 + * ubicom32fb_set_next_frame
53362 + * Sets the next frame buffer to display
53364 + * if sync is TRUE then this function will block until the hardware
53365 + * acknowledges the change
53367 +static inline void ubicom32fb_set_next_frame(struct ubicom32fb_drvdata *ud, void *fb, u8_t sync)
53369 + ud->regs->next_frame_flags = ud->is_yuv ? VDCTIO_NEXT_FRAME_FLAG_YUV : 0;
53370 + ud->regs->next_frame = (void *)((u32_t)fb | 1);
53373 + * If we have interrupts, then we can wait on it
53375 + if (ud->rx_int != -1) {
53376 + DEFINE_WAIT(wait);
53377 + unsigned long flags;
53379 + spin_lock_irqsave(&ud->lock, flags);
53380 + prepare_to_wait(&ud->waitq, &wait, TASK_INTERRUPTIBLE);
53381 + spin_unlock_irqrestore(&ud->lock, flags);
53383 + finish_wait(&ud->waitq, &wait);
53388 + * No interrupt, we will just spin here
53390 + while (sync && ((u32_t)ud->regs->next_frame & 1));
53394 + * ubicom32fb_send_command
53395 + * Sends a command/data pair to the VDC
53397 +static inline void ubicom32fb_send_command(struct ubicom32fb_drvdata *ud, u16 command, u8_t block)
53399 + ud->regs->command = command;
53400 + ubicom32_set_interrupt(ud->vp_int);
53401 + while (block && ud->regs->command);
53405 + * ubicom32fb_ioctl
53406 + * Handles any ioctls sent to us
53408 +static int ubicom32fb_ioctl(struct fb_info *fbi, unsigned int cmd,
53409 + unsigned long arg)
53411 + struct ubicom32fb_drvdata *ud = (struct ubicom32fb_drvdata *)fbi->par;
53412 + void __user *argp = (void __user *)arg;
53413 + int retval = -EFAULT;
53416 + case UBICOM32FB_IOCTL_SET_NEXT_FRAME_SYNC:
53417 + // check alignment, return -EINVAL if necessary
53418 + ubicom32fb_set_next_frame(ud, argp, 1);
53422 + case UBICOM32FB_IOCTL_SET_NEXT_FRAME:
53423 + // check alignment, return -EINVAL if necessary
53424 + ubicom32fb_set_next_frame(ud, argp, 0);
53428 + case UBICOM32FB_IOCTL_SET_MODE:
53429 + if (!(ud->regs->caps & VDCTIO_CAPS_SUPPORTS_SCALING)) {
53432 + struct ubicom32fb_mode mode;
53433 + volatile struct vdc_tio_vp_regs *regs = ud->regs;
53436 + if (copy_from_user(&mode, argp, sizeof(mode))) {
53440 + regs->x_in = mode.width;
53441 + regs->y_in = mode.height;
53442 + regs->x_out = regs->xres;
53443 + regs->y_out = regs->yres;
53444 + if (mode.flags & UBICOM32FB_IOCTL_SET_MODE_FLAG_YUV_SCAN_ORDER) {
53445 + flags |= VDCTIO_SCALE_FLAG_YUV_SCAN_ORDER;
53447 + if (mode.flags & UBICOM32FB_IOCTL_SET_MODE_FLAG_YUV_BLOCK_ORDER) {
53448 + flags |= VDCTIO_SCALE_FLAG_YUV_BLOCK_ORDER;
53450 + ud->is_yuv = mode.flags & UBICOM32FB_IOCTL_SET_MODE_FLAG_YUV;
53451 + if (ud->is_yuv) {
53452 + flags |= VDCTIO_SCALE_FLAG_YUV;
53454 + if (mode.flags & UBICOM32FB_IOCTL_SET_MODE_FLAG_VRANGE_16_255) {
53455 + flags |= VDCTIO_SCALE_FLAG_VRANGE_16_255;
53457 + if (mode.flags & UBICOM32FB_IOCTL_SET_MODE_FLAG_VRANGE_0_255) {
53458 + flags |= VDCTIO_SCALE_FLAG_VRANGE_0_255;
53460 + if (mode.flags & UBICOM32FB_IOCTL_SET_MODE_FLAG_VSUB) {
53461 + flags |= VDCTIO_SCALE_FLAG_VSUB;
53463 + if (mode.flags & UBICOM32FB_IOCTL_SET_MODE_FLAG_HSUB_2_1) {
53464 + flags |= VDCTIO_SCALE_FLAG_HSUB_2_1;
53466 + if (mode.flags & UBICOM32FB_IOCTL_SET_MODE_FLAG_HSUB_1_1) {
53467 + flags |= VDCTIO_SCALE_FLAG_HSUB_1_1;
53469 + if (mode.flags & UBICOM32FB_IOCTL_SET_MODE_FLAG_SCALE_ENABLE) {
53470 + flags |= VDCTIO_SCALE_FLAG_ENABLE;
53472 + if (mode.next_frame) {
53473 + flags |= VDCTIO_SCALE_FLAG_SET_FRAME_BUFFER;
53474 + regs->next_frame = mode.next_frame;
53477 + regs->scale_flags = flags;
53478 + ubicom32fb_send_command(ud, VDCTIO_COMMAND_SET_SCALE_MODE, 1);
53484 + retval = -ENOIOCTLCMD;
53492 + * ubicom32fb_interrupt
53493 + * Called by the OS when the TIO has set the rx_int
53495 +static irqreturn_t ubicom32fb_interrupt(int vec, void *appdata)
53497 + struct ubicom32fb_drvdata *ud = (struct ubicom32fb_drvdata *)appdata;
53499 + spin_lock(&ud->lock);
53500 + if (waitqueue_active(&ud->waitq)) {
53501 + wake_up(&ud->waitq);
53503 + spin_unlock(&ud->lock);
53505 + return IRQ_HANDLED;
53509 + * ubicom32fb_pan_display
53510 + * Pans the display to a given location. Supports only y direction panning.
53512 +static int ubicom32fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *fbi)
53514 + struct ubicom32fb_drvdata *ud = (struct ubicom32fb_drvdata *)fbi->par;
53518 + * Get the last y line that would be displayed. Since we don't support YWRAP,
53519 + * it must be less than our virtual y size.
53521 + u32 lasty = var->yoffset + var->yres;
53522 + if (lasty > fbi->var.yres_virtual) {
53524 + * We would fall off the end of our frame buffer if we panned here.
53529 + if (var->xoffset) {
53531 + * We don't support panning in the x direction
53537 + * Everything looks sane, go ahead and pan
53539 + * We have to calculate a new address for the VDC to look at
53541 + new_addr = ud->fb_aligned + (var->yoffset * fbi->fix.line_length);
53544 + * Send down the command. The buffer will switch at the next vertical blank
53546 + ubicom32fb_set_next_frame(ud, (void *)new_addr, 0);
53552 + * ubicom32fb_setcolreg
53553 + * Sets a color in our virtual palette
53555 +static int ubicom32fb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *fbi)
53557 + u32 *palette = fbi->pseudo_palette;
53559 + if (regno >= PALETTE_ENTRIES_NO) {
53564 + * We only use 8 bits from each color
53571 + * Convert any grayscale values
53573 + if (fbi->var.grayscale) {
53574 + u16 gray = red + green + blue;
53575 + gray += (gray >> 2) + (gray >> 3) - (gray >> 7);
53577 + if (gray > 255) {
53585 + palette[regno] = (red << fbi->var.red.offset) | (green << fbi->var.green.offset) |
53586 + (blue << fbi->var.blue.offset);
53592 + * ubicom32fb_mmap
53594 +static int ubicom32fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
53596 + struct ubicom32fb_drvdata *drvdata = (struct ubicom32fb_drvdata *)info->par;
53598 + vma->vm_start = (unsigned long)(drvdata->fb_aligned);
53600 + vma->vm_end = vma->vm_start + info->fix.smem_len;
53602 + /* For those who don't understand how mmap works, go read
53603 + * Documentation/nommu-mmap.txt.
53604 + * For those that do, you will know that the VM_MAYSHARE flag
53605 + * must be set in the vma->vm_flags structure on noMMU
53606 + * Other flags can be set, and are documented in
53607 + * include/linux/mm.h
53610 + vma->vm_flags |= VM_MAYSHARE | VM_SHARED;
53616 + * ubicom32fb_blank
53618 +static int ubicom32fb_blank(int blank_mode, struct fb_info *fbi)
53622 + struct ubicom32fb_drvdata *drvdata = to_ubicom32fb_drvdata(fbi);
53624 + switch (blank_mode) {
53625 + case FB_BLANK_UNBLANK:
53626 + /* turn on panel */
53627 + ubicom32fb_out_be32(drvdata, REG_CTRL, drvdata->reg_ctrl_default);
53630 + case FB_BLANK_NORMAL:
53631 + case FB_BLANK_VSYNC_SUSPEND:
53632 + case FB_BLANK_HSYNC_SUSPEND:
53633 + case FB_BLANK_POWERDOWN:
53634 + /* turn off panel */
53635 + ubicom32fb_out_be32(drvdata, REG_CTRL, 0);
53640 + return 0; /* success */
53644 +static struct fb_ops ubicom32fb_ops =
53646 + .owner = THIS_MODULE,
53647 + .fb_pan_display = ubicom32fb_pan_display,
53648 + .fb_setcolreg = ubicom32fb_setcolreg,
53649 + .fb_blank = ubicom32fb_blank,
53650 + .fb_mmap = ubicom32fb_mmap,
53651 + .fb_ioctl = ubicom32fb_ioctl,
53652 + .fb_fillrect = cfb_fillrect,
53653 + .fb_copyarea = cfb_copyarea,
53654 + .fb_imageblit = cfb_imageblit,
53658 + * ubicom32fb_release
53660 +static int ubicom32fb_release(struct device *dev)
53662 + struct ubicom32fb_drvdata *ud = dev_get_drvdata(dev);
53664 +#if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO)
53665 + //ubicom32fb_blank(VESA_POWERDOWN, &drvdata->info);
53668 + unregister_framebuffer(ud->fbinfo);
53670 + if (ud->cmap_alloc) {
53671 + fb_dealloc_cmap(&ud->fbinfo->cmap);
53678 + if (ud->rx_int != -1) {
53679 + free_irq(ud->rx_int, ud);
53683 + * Turn off the display
53685 + //ubicom32fb_out_be32(drvdata, REG_CTRL, 0);
53686 + //iounmap(drvdata->regs);
53688 + framebuffer_release(ud->fbinfo);
53689 + dev_set_drvdata(dev, NULL);
53695 + * ubicom32fb_platform_probe
53697 +static int __init ubicom32fb_platform_probe(struct platform_device *pdev)
53699 + struct ubicom32fb_drvdata *ud;
53700 + struct resource *irq_resource_rx;
53701 + struct resource *irq_resource_tx;
53702 + struct resource *mem_resource;
53703 + struct fb_info *fbinfo;
53706 + struct device *dev = &pdev->dev;
53708 + struct vdc_tio_vp_regs *regs;
53711 + * Get our resources
53713 + irq_resource_tx = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
53714 + if (!irq_resource_tx) {
53715 + dev_err(dev, "No tx IRQ resource assigned\n");
53719 + irq_resource_rx = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
53720 + if (!irq_resource_rx) {
53721 + dev_err(dev, "No rx IRQ resource assigned\n");
53725 + mem_resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
53726 + if (!mem_resource || !mem_resource->start) {
53727 + dev_err(dev, "No mem resource assigned\n");
53730 + regs = (struct vdc_tio_vp_regs *)mem_resource->start;
53731 + if (regs->version != VDCTIO_VP_VERSION) {
53732 + dev_err(dev, "VDCTIO is not compatible with this driver tio:%x drv:%x\n",
53733 + regs->version, VDCTIO_VP_VERSION);
53738 + * This is the minimum VRAM size
53740 + fbsize = regs->xres * regs->yres * (regs->bpp / 8);
53741 + if (!vram_size) {
53742 + vram_size = (fbsize + 1023) / 1024;
53744 + if (fbsize > (vram_size * 1024)) {
53745 + dev_err(dev, "Not enough VRAM for display, need >= %u bytes\n", fbsize);
53746 + return -ENOMEM; // should be ebadparam?
53751 + * Allocate the framebuffer instance + our private data
53753 + fbinfo = framebuffer_alloc(sizeof(struct ubicom32fb_drvdata), &pdev->dev);
53755 + dev_err(dev, "Not enough memory to allocate instance.\n");
53760 + * Fill in our private data.
53762 + ud = (struct ubicom32fb_drvdata *)fbinfo->par;
53763 + ud->fbinfo = fbinfo;
53764 + ud->regs = (struct vdc_tio_vp_regs *)(mem_resource->start);
53765 + dev_set_drvdata(dev, ud);
53767 + ud->vp_int = irq_resource_tx->start;
53770 + * If we were provided an rx_irq then we need to init the appropriate
53771 + * queues, locks, and functions.
53774 + if (irq_resource_rx->start != DEVTREE_IRQ_NONE) {
53775 + init_waitqueue_head(&ud->waitq);
53776 + mutex_init(&ud->lock);
53777 + if (request_irq(ud->rx_int, ubicom32fb_interrupt, IRQF_SHARED, "ubicom32fb_rx", ud)) {
53778 + dev_err(dev, "Couldn't request rx IRQ\n");
53782 + ud->rx_int = irq_resource_rx->start;
53786 + * Allocate and align the requested amount of VRAM
53788 + ud->total_vram_size = (vram_size * 1024) + regs->fb_align;
53789 + ud->fb = kmalloc(ud->total_vram_size, GFP_KERNEL);
53790 + if (ud->fb == NULL) {
53791 + dev_err(dev, "Couldn't allocate VRAM\n");
53796 + offset = (u32_t)ud->fb & (regs->fb_align - 1);
53798 + ud->fb_aligned = ud->fb;
53800 + offset = regs->fb_align - offset;
53801 + ud->fb_aligned = ud->fb + offset;
53805 + * Clear the entire frame buffer
53807 + if (!init_value) {
53808 + memset(ud->fb_aligned, 0, vram_size * 1024);
53810 + unsigned short *p = ud->fb_aligned;
53812 + for (i = 0; i < ((vram_size * 1024) / sizeof(u16_t)); i++) {
53813 + *p++ = init_value;
53818 + * Fill in the fb_var_screeninfo structure
53820 + memset(&ubicom32fb_var, 0, sizeof(ubicom32fb_var));
53821 + ubicom32fb_var.bits_per_pixel = regs->bpp;
53822 + ubicom32fb_var.red.offset = regs->rshift;
53823 + ubicom32fb_var.green.offset = regs->gshift;
53824 + ubicom32fb_var.blue.offset = regs->bshift;
53825 + ubicom32fb_var.red.length = regs->rbits;
53826 + ubicom32fb_var.green.length = regs->gbits;
53827 + ubicom32fb_var.blue.length = regs->bbits;
53828 + ubicom32fb_var.activate = FB_ACTIVATE_NOW;
53832 + * Turn on the display
53834 + ud->reg_ctrl_default = REG_CTRL_ENABLE;
53835 + if (regs->rotate_screen)
53836 + ud->reg_ctrl_default |= REG_CTRL_ROTATE;
53837 + ubicom32fb_out_be32(ud, REG_CTRL, ud->reg_ctrl_default);
53841 + * Fill in the fb_info structure
53843 + ud->fbinfo->device = dev;
53844 + ud->fbinfo->screen_base = (void *)ud->fb_aligned;
53845 + ud->fbinfo->fbops = &ubicom32fb_ops;
53846 + ud->fbinfo->fix = ubicom32fb_fix;
53847 + ud->fbinfo->fix.smem_start = (u32)ud->fb_aligned;
53848 + ud->fbinfo->fix.smem_len = vram_size * 1024;
53849 + ud->fbinfo->fix.line_length = regs->xres * (regs->bpp / 8);
53850 + ud->fbinfo->fix.mmio_start = (u32)regs;
53851 + ud->fbinfo->fix.mmio_len = sizeof(struct vdc_tio_vp_regs);
53854 + * We support panning in the y direction only
53856 + ud->fbinfo->fix.xpanstep = 0;
53857 + ud->fbinfo->fix.ypanstep = 1;
53859 + ud->fbinfo->pseudo_palette = ud->pseudo_palette;
53860 + ud->fbinfo->flags = FBINFO_DEFAULT;
53861 + ud->fbinfo->var = ubicom32fb_var;
53862 + ud->fbinfo->var.xres = regs->xres;
53863 + ud->fbinfo->var.yres = regs->yres;
53866 + * We cannot pan in the X direction, so xres_virtual is regs->xres
53867 + * We can pan in the Y direction, so yres_virtual is vram_size / ud->fbinfo->fix.line_length
53869 + ud->fbinfo->var.xres_virtual = regs->xres;
53870 + ud->fbinfo->var.yres_virtual = (vram_size * 1024) / ud->fbinfo->fix.line_length;
53872 + //ud->fbinfo->var.height = regs->height_mm;
53873 + //ud->fbinfo->var.width = regs->width_mm;
53876 + * Allocate a color map
53878 + rc = fb_alloc_cmap(&ud->fbinfo->cmap, PALETTE_ENTRIES_NO, 0);
53880 + dev_err(dev, "Fail to allocate colormap (%d entries)\n",
53881 + PALETTE_ENTRIES_NO);
53884 + ud->cmap_alloc = true;
53887 + * Register new frame buffer
53889 + rc = register_framebuffer(ud->fbinfo);
53891 + dev_err(dev, "Could not register frame buffer\n");
53896 + * Start up the VDC
53898 + ud->regs->next_frame = ud->fb;
53899 + ubicom32fb_send_command(ud, VDCTIO_COMMAND_START, 0);
53902 + * Tell the log we are here
53904 + dev_info(dev, "fbaddr=%p align=%p, size=%uKB screen(%ux%u) virt(%ux%u), regs=%p irqtx=%u irqrx=%u\n",
53905 + ud->fb, ud->fb_aligned, vram_size, ud->fbinfo->var.xres, ud->fbinfo->var.yres,
53906 + ud->fbinfo->var.xres_virtual, ud->fbinfo->var.yres_virtual, ud->regs,
53907 + irq_resource_tx->start, irq_resource_rx->start);
53915 + ubicom32fb_release(dev);
53920 + * ubicom32fb_platform_remove
53922 +static int ubicom32fb_platform_remove(struct platform_device *pdev)
53924 + dev_info(&(pdev->dev), "Ubicom32 FB Driver Remove\n");
53925 + return ubicom32fb_release(&pdev->dev);
53928 +static struct platform_driver ubicom32fb_platform_driver = {
53929 + .probe = ubicom32fb_platform_probe,
53930 + .remove = ubicom32fb_platform_remove,
53932 + .name = DRIVER_NAME,
53933 + .owner = THIS_MODULE,
53939 + * ubicom32fb_setup
53940 + * Process kernel boot options
53942 +static int __init ubicom32fb_setup(char *options)
53946 + if (!options || !*options) {
53950 + while ((this_opt = strsep(&options, ",")) != NULL) {
53951 + if (!*this_opt) {
53955 + if (!strncmp(this_opt, "init_value=", 10)) {
53956 + init_value = simple_strtoul(this_opt + 11, NULL, 0);
53960 + if (!strncmp(this_opt, "vram_size=", 10)) {
53961 + vram_size = simple_strtoul(this_opt + 10, NULL, 0);
53967 +#endif /* MODULE */
53970 + * ubicom32fb_init
53972 +static int __devinit ubicom32fb_init(void)
53976 + * Get kernel boot options (in 'video=ubicom32fb:<options>')
53978 + char *option = NULL;
53980 + if (fb_get_options(DRIVER_NAME, &option)) {
53983 + ubicom32fb_setup(option);
53984 +#endif /* MODULE */
53986 + return platform_driver_register(&ubicom32fb_platform_driver);
53988 +module_init(ubicom32fb_init);
53991 + * ubicom32fb_exit
53993 +static void __exit ubicom32fb_exit(void)
53995 + platform_driver_unregister(&ubicom32fb_platform_driver);
53997 +module_exit(ubicom32fb_exit);
53999 +MODULE_LICENSE("GPL");
54000 +MODULE_AUTHOR("Patrick Tjin <@ubicom.com>");
54001 +MODULE_DESCRIPTION(DRIVER_DESCRIPTION);
54002 diff -ruN linux-2.6.30.10/drivers/video/ubicom32plio80.c linux-2.6.30.10-ubi/drivers/video/ubicom32plio80.c
54003 --- linux-2.6.30.10/drivers/video/ubicom32plio80.c 1970-01-01 02:00:00.000000000 +0200
54004 +++ linux-2.6.30.10-ubi/drivers/video/ubicom32plio80.c 2009-12-11 11:45:21.000000000 +0200
54007 + * drivers/video/ubicom32plio80.c
54008 + * Ubicom32 80 bus PLIO buffer driver
54010 + * (C) Copyright 2009, Ubicom, Inc.
54012 + * This file is part of the Ubicom32 Linux Kernel Port.
54014 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
54015 + * it and/or modify it under the terms of the GNU General Public License
54016 + * as published by the Free Software Foundation, either version 2 of the
54017 + * License, or (at your option) any later version.
54019 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
54020 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
54021 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
54022 + * the GNU General Public License for more details.
54024 + * You should have received a copy of the GNU General Public License
54025 + * along with the Ubicom32 Linux Kernel Port. If not,
54026 + * see <http://www.gnu.org/licenses/>.
54030 + * This driver was based on skeletonfb.c, Skeleton for a frame buffer device by
54031 + * Geert Uytterhoeven.
54034 +#include <linux/device.h>
54035 +#include <linux/module.h>
54036 +#include <linux/kernel.h>
54037 +#include <linux/version.h>
54038 +#include <linux/errno.h>
54039 +#include <linux/string.h>
54040 +#include <linux/mm.h>
54041 +#include <linux/fb.h>
54042 +#include <linux/init.h>
54043 +#include <linux/interrupt.h>
54044 +#include <linux/dma-mapping.h>
54045 +#include <linux/platform_device.h>
54046 +#include <linux/device.h>
54047 +#include <linux/uaccess.h>
54048 +#include <asm/plio.h>
54050 +#define DRIVER_NAME "ubicom32plio80"
54051 +#define DRIVER_DESCRIPTION "Ubicom32 80 bus PLIO frame buffer driver"
54053 +#define PALETTE_ENTRIES_NO 16
54056 + * Option variables
54058 + * vram_size: VRAM size in kilobytes, subject to alignment
54060 +static int vram_size = 0;
54061 +module_param(vram_size, int, 0);
54062 +MODULE_PARM_DESC(vram_size, "VRAM size, in kilobytes to allocate, should be at least the size of one screen, subject to alignment");
54064 +static int xres = 240;
54065 +module_param(xres, int, 0);
54066 +MODULE_PARM_DESC(xres, "x (horizontal) resolution");
54068 +static int yres = 320;
54069 +module_param(yres, int, 0);
54070 +MODULE_PARM_DESC(yres, "y (vertical) resolution");
54072 +static int bgr = 0;
54073 +module_param(bgr, int, 0);
54074 +MODULE_PARM_DESC(bgr, "display is BGR (Blue is MSB)");
54076 +#define BITS_PER_PIXEL 16
54079 + * Buffer alignment, must not be 0
54081 +#define UBICOM32PLIO80_ALIGNMENT 4
54085 + * 16-bit data bus on port I
54086 + * CS on EXTCTL[6]
54087 + * WR on EXTCTL[4]
54089 +static const plio_fctl_t plio_fctl = {
54091 + .ptif_port_mode = PLIO_PORT_MODE_DI,
54092 + .ptif_portd_cfg = 0,
54093 + .ptif_porti_cfg = 3,
54095 + .edif_cmp_mode = 1,
54096 + .ecif_extclk_ena = 0, // enable clock output on PD7 table 2.65/p111 says extctl[0]?
54097 + .icif_clk_src_sel = PLIO_CLK_IO,
54100 + .icif_eclk_div = 10,
54101 + .icif_iclk_div = 10,
54106 + static const plio_config_t plio_config = {
54111 + .grpsel[0] = {1,1,1,1,1,1,1,1,1,1},
54114 + * Table 12.66 Counter load value
54116 + .cs_lut[0] = {0,0,0,0,0,0,0,0},
54119 + * Table 2.75 PLIO PFSM Configuration Registers
54122 + .extctl_o_lut[0] = {0x3f, 0x2f, 0x3f, 0x3f},
54124 + .extctl_o_lut[1] = {0x3f, 0x3f, 0x3f, 0x2f},
54127 + .odr_oe = 0xffff,
54130 + .output_ena = (1 << 6) | (1 << 4),
54134 +static const u32_t ubicom32plio80_plio_fsm[] = {
54136 + 0x00070007, 0x00070007,
54137 + 0x00070007, 0x00070007,
54138 + 0x00070007, 0x00070007,
54139 + 0x00070007, 0x00070007,
54141 + 0x16260806, 0x16260806,
54142 + 0x16260806, 0x16260806,
54143 + 0x16260806, 0x16260806,
54144 + 0x16260806, 0x16260806,
54147 + 0x22061806, 0x22061806,
54148 + 0x22061806, 0x22061806,
54149 + 0x22061806, 0x22061806,
54150 + 0x22061806, 0x22061806,
54152 + 0x22061806, 0x22061806,
54153 + 0x22061806, 0x22061806,
54154 + 0x22061806, 0x22061806,
54155 + 0x22061806, 0x22061806,
54158 + 0x00070806, 0x00070806,
54159 + 0x00070806, 0x00070806,
54160 + 0x00070806, 0x00070806,
54161 + 0x00070806, 0x00070806,
54163 + 0x00070806, 0x00070806,
54164 + 0x00070806, 0x00070806,
54165 + 0x00070806, 0x00070806,
54166 + 0x00070806, 0x00070806,
54170 + * fb_fix_screeninfo defines the non-changeable properties of the VDC, depending on what mode it is in.
54172 +static struct fb_fix_screeninfo ubicom32plio80_fix = {
54173 + .id = "Ubicom32",
54174 + .type = FB_TYPE_PACKED_PIXELS,
54175 + .visual = FB_VISUAL_TRUECOLOR,
54176 + .accel = FB_ACCEL_UBICOM32_PLIO80,
54180 + * Filled in at probe time when we find out what the hardware supports
54182 +static struct fb_var_screeninfo ubicom32plio80_var;
54185 + * Private data structure
54187 +struct ubicom32plio80_drvdata {
54188 + struct fb_info *fbinfo;
54192 + * The address of the framebuffer in memory
54195 + void *fb_aligned;
54198 + * Total size of vram including alignment allowance
54200 + u32 total_vram_size;
54203 + * Fake palette of 16 colors
54205 + u32 pseudo_palette[PALETTE_ENTRIES_NO];
54210 + * Current pointer and bytes left to transfer with the PLIO
54213 + u32 bytes_to_xfer;
54217 +static struct platform_device *ubicom32plio80_platform_device;
54220 + * ubicom32plio80_isr
54222 +static int ubicom32plio80_isr(int irq, void *appdata)
54224 + struct ubicom32plio80_drvdata *ud = (struct ubicom32plio80_drvdata *)appdata;
54226 + if (!ud->bytes_to_xfer) {
54227 + ubicom32_disable_interrupt(TX_FIFO_INT(PLIO_PORT));
54228 + PLIO_NBR->intmask.txfifo_wm = 0;
54230 + return IRQ_HANDLED;
54235 + "move.4 (%[fifo]), (%[data])4++ \n\t"
54237 + : [data] "+a" (ud->xfer_ptr)
54238 + : [fifo] "a" (&PLIO_NBR->tx_lo)
54241 + ud->bytes_to_xfer -= 32;
54243 + return IRQ_HANDLED;
54247 + * ubicom32plio80_update
54249 +static void ubicom32plio80_update(struct ubicom32plio80_drvdata *ud, u32 *fb)
54251 + struct ubicom32_io_port *ri = (struct ubicom32_io_port *)RI;
54252 + struct ubicom32_io_port *rd = (struct ubicom32_io_port *)RD;
54254 + ud->xfer_ptr = fb;
54255 + ud->bytes_to_xfer = (xres * yres * 2) - 64;
54258 + ri->gpio_mask = 0;
54259 + rd->gpio_mask &= ~((1 << 4) | (1 << 2));
54261 + *(u32 *)(&PLIO_NBR->intclr) = ~0;
54262 + PLIO_NBR->intmask.txfifo_wm = 1;
54263 + PLIO_NBR->fifo_wm.tx = 8;
54264 + ubicom32_enable_interrupt(TX_FIFO_INT(PLIO_PORT));
54268 + "move.4 (%[fifo]), (%[data])4++ \n\t"
54270 + : [data] "+a" (ud->xfer_ptr)
54271 + : [fifo] "a" (&PLIO_NBR->tx_lo)
54276 + * ubicom32plio80_pan_display
54277 + * Pans the display to a given location. Supports only y direction panning.
54279 +static int ubicom32plio80_pan_display(struct fb_var_screeninfo *var, struct fb_info *fbi)
54281 + struct ubicom32plio80_drvdata *ud = (struct ubicom32plio80_drvdata *)fbi->par;
54285 + * Get the last y line that would be displayed. Since we don't support YWRAP,
54286 + * it must be less than our virtual y size.
54288 + u32 lasty = var->yoffset + var->yres;
54289 + if (lasty > fbi->var.yres_virtual) {
54291 + * We would fall off the end of our frame buffer if we panned here.
54296 + if (var->xoffset) {
54298 + * We don't support panning in the x direction
54304 + * Everything looks sane, go ahead and pan
54306 + * We have to calculate a new address for the VDC to look at
54308 + new_addr = ud->fb_aligned + (var->yoffset * fbi->fix.line_length);
54314 + * ubicom32plio80_setcolreg
54315 + * Sets a color in our virtual palette
54317 +static int ubicom32plio80_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *fbi)
54319 + u32 *palette = fbi->pseudo_palette;
54321 + if (regno >= PALETTE_ENTRIES_NO) {
54326 + * We only use 8 bits from each color
54333 + * Convert any grayscale values
54335 + if (fbi->var.grayscale) {
54336 + u16 gray = red + green + blue;
54337 + gray += (gray >> 2) + (gray >> 3) - (gray >> 7);
54339 + if (gray > 255) {
54347 + palette[regno] = (red << fbi->var.red.offset) | (green << fbi->var.green.offset) |
54348 + (blue << fbi->var.blue.offset);
54354 + * ubicom32plio80_mmap
54356 +static int ubicom32plio80_mmap(struct fb_info *info, struct vm_area_struct *vma)
54358 + struct ubicom32plio80_drvdata *ud = (struct ubicom32plio80_drvdata *)info->par;
54360 + vma->vm_start = (unsigned long)(ud->fb_aligned);
54362 + vma->vm_end = vma->vm_start + info->fix.smem_len;
54364 + /* For those who don't understand how mmap works, go read
54365 + * Documentation/nommu-mmap.txt.
54366 + * For those that do, you will know that the VM_MAYSHARE flag
54367 + * must be set in the vma->vm_flags structure on noMMU
54368 + * Other flags can be set, and are documented in
54369 + * include/linux/mm.h
54372 + vma->vm_flags |= VM_MAYSHARE | VM_SHARED;
54378 + * ubicom32plio80_check_var
54379 + * Check the var, tweak it but don't change operational parameters.
54381 +static int ubicom32plio80_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
54383 + struct ubicom32plio80_drvdata *ud = (struct ubicom32plio80_drvdata *)info->par;
54384 + u32 line_size = var->xres * (BITS_PER_PIXEL / 8);
54387 + * See if we can handle this bpp
54389 + if (var->bits_per_pixel > BITS_PER_PIXEL) {
54392 + var->bits_per_pixel = BITS_PER_PIXEL;
54395 + * See if we have enough memory to handle this resolution
54397 + if ((line_size * var->yres * BITS_PER_PIXEL / 8) > ud->total_vram_size) {
54401 + var->xres_virtual = var->xres;
54402 + var->yres_virtual = ud->total_vram_size / line_size;
54404 + var->red.length = 5;
54405 + var->green.length = 6;
54406 + var->green.offset = 5;
54407 + var->blue.length = 5;
54408 + var->transp.offset = var->transp.length = 0;
54411 + var->red.offset = 0;
54412 + var->blue.offset = 11;
54414 + var->red.offset = 11;
54415 + var->blue.offset = 0;
54419 + var->height = -1;
54421 + var->vmode = FB_VMODE_NONINTERLACED;
54428 + * ubicom32plio80_set_par
54429 + * Set the video mode according to info->var
54431 +static int ubicom32plio80_set_par(struct fb_info *info)
54434 + * Anything changed?
54436 + if ((xres == info->var.xres) && (yres == info->var.yres)) {
54441 + * Implement changes
54443 + xres = info->var.xres;
54444 + yres = info->var.yres;
54445 + info->fix.visual = FB_VISUAL_TRUECOLOR;
54446 + info->fix.xpanstep = 0;
54447 + info->fix.ypanstep = 1;
54448 + info->fix.line_length = xres * (BITS_PER_PIXEL / 8);
54454 + * ubicom32plio80_ops
54455 + * List of supported operations
54457 +static struct fb_ops ubicom32plio80_ops =
54459 + .owner = THIS_MODULE,
54460 + .fb_pan_display = ubicom32plio80_pan_display,
54461 + .fb_setcolreg = ubicom32plio80_setcolreg,
54462 + .fb_mmap = ubicom32plio80_mmap,
54463 + .fb_check_var = ubicom32plio80_check_var,
54464 + .fb_set_par = ubicom32plio80_set_par,
54465 + .fb_fillrect = cfb_fillrect,
54466 + .fb_copyarea = cfb_copyarea,
54467 + .fb_imageblit = cfb_imageblit,
54471 + * ubicom32plio80_release
54473 +static int ubicom32plio80_release(struct device *dev)
54475 + struct ubicom32plio80_drvdata *ud = dev_get_drvdata(dev);
54477 + unregister_framebuffer(ud->fbinfo);
54479 + if (ud->irq_req) {
54480 + free_irq(TX_FIFO_INT(PLIO_PORT), ud);
54482 + if (ud->cmap_alloc) {
54483 + fb_dealloc_cmap(&ud->fbinfo->cmap);
54490 + framebuffer_release(ud->fbinfo);
54491 + dev_set_drvdata(dev, NULL);
54497 + * ubicom32plio80_platform_probe
54499 +static int __init ubicom32plio80_platform_probe(struct platform_device *pdev)
54501 + struct ubicom32plio80_drvdata *ud;
54502 + struct fb_info *fbinfo;
54505 + struct device *dev = &pdev->dev;
54509 + * This is the minimum VRAM size
54511 + fbsize = xres * yres * 2;
54512 + if (!vram_size) {
54513 + vram_size = (fbsize + 1023) / 1024;
54515 + if (fbsize > (vram_size * 1024)) {
54516 + dev_err(dev, "Not enough VRAM for display, need >= %u bytes\n", fbsize);
54517 + return -ENOMEM; // should be ebadparam?
54522 + * Allocate the framebuffer instance + our private data
54524 + fbinfo = framebuffer_alloc(sizeof(struct ubicom32plio80_drvdata), &pdev->dev);
54526 + dev_err(dev, "Not enough memory to allocate instance.\n");
54531 + * Fill in our private data.
54533 + ud = (struct ubicom32plio80_drvdata *)fbinfo->par;
54534 + ud->fbinfo = fbinfo;
54535 + dev_set_drvdata(dev, ud);
54538 + * Allocate and align the requested amount of VRAM
54540 + ud->total_vram_size = (vram_size * 1024) + UBICOM32PLIO80_ALIGNMENT;
54541 + ud->fb = kmalloc(ud->total_vram_size, GFP_KERNEL);
54542 + if (ud->fb == NULL) {
54543 + dev_err(dev, "Couldn't allocate VRAM\n");
54548 + offset = (u32_t)ud->fb & (UBICOM32PLIO80_ALIGNMENT - 1);
54550 + ud->fb_aligned = ud->fb;
54552 + offset = UBICOM32PLIO80_ALIGNMENT - offset;
54553 + ud->fb_aligned = ud->fb + offset;
54557 + * Clear the entire frame buffer
54559 + memset(ud->fb_aligned, 0, vram_size * 1024);
54562 + * Fill in the fb_var_screeninfo structure
54564 + memset(&ubicom32plio80_var, 0, sizeof(ubicom32plio80_var));
54565 + ubicom32plio80_var.bits_per_pixel = BITS_PER_PIXEL;
54566 + ubicom32plio80_var.red.length = 5;
54567 + ubicom32plio80_var.green.length = 6;
54568 + ubicom32plio80_var.green.offset = 5;
54569 + ubicom32plio80_var.blue.length = 5;
54570 + ubicom32plio80_var.activate = FB_ACTIVATE_NOW;
54573 + ubicom32plio80_var.red.offset = 0;
54574 + ubicom32plio80_var.blue.offset = 11;
54576 + ubicom32plio80_var.red.offset = 11;
54577 + ubicom32plio80_var.blue.offset = 0;
54581 + * Fill in the fb_info structure
54583 + ud->fbinfo->device = dev;
54584 + ud->fbinfo->screen_base = (void *)ud->fb_aligned;
54585 + ud->fbinfo->fbops = &ubicom32plio80_ops;
54586 + ud->fbinfo->fix = ubicom32plio80_fix;
54587 + ud->fbinfo->fix.smem_start = (u32)ud->fb_aligned;
54588 + ud->fbinfo->fix.smem_len = vram_size * 1024;
54589 + ud->fbinfo->fix.line_length = xres * 2;
54590 + ud->fbinfo->fix.mmio_start = (u32)ud;
54591 + ud->fbinfo->fix.mmio_len = sizeof(struct ubicom32plio80_drvdata);
54594 + * We support panning in the y direction only
54596 + ud->fbinfo->fix.xpanstep = 0;
54597 + ud->fbinfo->fix.ypanstep = 1;
54599 + ud->fbinfo->pseudo_palette = ud->pseudo_palette;
54600 + ud->fbinfo->flags = FBINFO_DEFAULT;
54601 + ud->fbinfo->var = ubicom32plio80_var;
54602 + ud->fbinfo->var.xres = xres;
54603 + ud->fbinfo->var.yres = yres;
54606 + * We cannot pan in the X direction, so xres_virtual is xres
54607 + * We can pan in the Y direction, so yres_virtual is vram_size / ud->fbinfo->fix.line_length
54609 + ud->fbinfo->var.xres_virtual = xres;
54610 + ud->fbinfo->var.yres_virtual = (vram_size * 1024) / ud->fbinfo->fix.line_length;
54613 + * Allocate a color map
54615 + rc = fb_alloc_cmap(&ud->fbinfo->cmap, PALETTE_ENTRIES_NO, 0);
54617 + dev_err(dev, "Fail to allocate colormap (%d entries)\n",
54618 + PALETTE_ENTRIES_NO);
54621 + ud->cmap_alloc = true;
54624 + * Register new frame buffer
54626 + rc = register_framebuffer(ud->fbinfo);
54628 + dev_err(dev, "Could not register frame buffer\n");
54633 + * request the PLIO IRQ
54635 + rc = request_irq(TX_FIFO_INT(PLIO_PORT), ubicom32plio80_isr, IRQF_DISABLED, "ubicom32plio80", ud);
54637 + dev_err(dev, "Could not request IRQ\n");
54643 + * Clear any garbage out of the TX FIFOs (idif_txfifo_flush)
54645 + * cast through ubicom32_io_port to make sure the compiler does a word write
54647 + ((struct ubicom32_io_port *)PLIO_NBR)->int_set = (1 << 18);
54650 + * Start up the state machine
54652 + plio_init(&plio_fctl, &plio_config, (plio_sram_t *)ubicom32plio80_plio_fsm, sizeof(ubicom32plio80_plio_fsm));
54653 + PLIO_NBR->fctl0.pfsm_cmd = 0;
54655 + ubicom32plio80_update(ud, ud->fb_aligned);
54658 + * Tell the log we are here
54660 + dev_info(dev, "fbaddr=%p align=%p, size=%uKB screen(%ux%u) virt(%ux%u)\n",
54661 + ud->fb, ud->fb_aligned, vram_size, ud->fbinfo->var.xres, ud->fbinfo->var.yres,
54662 + ud->fbinfo->var.xres_virtual, ud->fbinfo->var.yres_virtual);
54670 + ubicom32plio80_release(dev);
54675 + * ubicom32plio80_platform_remove
54677 +static int ubicom32plio80_platform_remove(struct platform_device *pdev)
54679 + dev_info(&(pdev->dev), "Ubicom32 FB Driver Remove\n");
54680 + return ubicom32plio80_release(&pdev->dev);
54683 +static struct platform_driver ubicom32plio80_platform_driver = {
54684 + .probe = ubicom32plio80_platform_probe,
54685 + .remove = ubicom32plio80_platform_remove,
54687 + .name = DRIVER_NAME,
54688 + .owner = THIS_MODULE,
54694 + * ubicom32plio80_setup
54695 + * Process kernel boot options
54697 +static int __init ubicom32plio80_setup(char *options)
54701 + if (!options || !*options) {
54705 + while ((this_opt = strsep(&options, ",")) != NULL) {
54706 + if (!*this_opt) {
54710 + if (!strncmp(this_opt, "vram_size=", 10)) {
54711 + vram_size = simple_strtoul(this_opt + 10, NULL, 0);
54715 + if (!strncmp(this_opt, "bgr=", 4)) {
54716 + bgr = simple_strtoul(this_opt + 4, NULL, 0);
54720 + if (!strncmp(this_opt, "xres=", 5)) {
54721 + xres = simple_strtoul(this_opt + 5, NULL, 0);
54725 + if (!strncmp(this_opt, "yres=", 5)) {
54726 + yres = simple_strtoul(this_opt + 5, NULL, 0);
54732 +#endif /* MODULE */
54735 + * ubicom32plio80_init
54737 +static int __devinit ubicom32plio80_init(void)
54743 + * Get kernel boot options (in 'video=ubicom32plio80:<options>')
54745 + char *option = NULL;
54747 + if (fb_get_options(DRIVER_NAME, &option)) {
54750 + ubicom32plio80_setup(option);
54751 +#endif /* MODULE */
54753 + ret = platform_driver_register(&ubicom32plio80_platform_driver);
54756 + ubicom32plio80_platform_device = platform_device_alloc(DRIVER_NAME, 0);
54758 + if (ubicom32plio80_platform_device)
54759 + ret = platform_device_add(ubicom32plio80_platform_device);
54764 + platform_device_put(ubicom32plio80_platform_device);
54765 + platform_driver_unregister(&ubicom32plio80_platform_driver);
54771 +module_init(ubicom32plio80_init);
54774 + * ubicom32plio80_exit
54776 +static void __exit ubicom32plio80_exit(void)
54778 + platform_device_unregister(ubicom32plio80_platform_device);
54779 + platform_driver_unregister(&ubicom32plio80_platform_driver);
54781 +module_exit(ubicom32plio80_exit);
54783 +MODULE_LICENSE("GPL");
54784 +MODULE_AUTHOR("Patrick Tjin <@ubicom.com>");
54785 +MODULE_DESCRIPTION(DRIVER_DESCRIPTION);
54786 diff -ruN linux-2.6.30.10/drivers/video/ubicom32vfb.c linux-2.6.30.10-ubi/drivers/video/ubicom32vfb.c
54787 --- linux-2.6.30.10/drivers/video/ubicom32vfb.c 1970-01-01 02:00:00.000000000 +0200
54788 +++ linux-2.6.30.10-ubi/drivers/video/ubicom32vfb.c 2009-12-11 11:45:21.000000000 +0200
54791 + * drivers/video/ubicom32vfb.c
54792 + * Ubicom32 virtual frame buffer driver
54794 + * (C) Copyright 2009, Ubicom, Inc.
54796 + * This file is part of the Ubicom32 Linux Kernel Port.
54798 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
54799 + * it and/or modify it under the terms of the GNU General Public License
54800 + * as published by the Free Software Foundation, either version 2 of the
54801 + * License, or (at your option) any later version.
54803 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
54804 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
54805 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
54806 + * the GNU General Public License for more details.
54808 + * You should have received a copy of the GNU General Public License
54809 + * along with the Ubicom32 Linux Kernel Port. If not,
54810 + * see <http://www.gnu.org/licenses/>.
54814 + * This driver was based on skeletonfb.c, Skeleton for a frame buffer device by
54815 + * Geert Uytterhoeven.
54818 +#include <linux/device.h>
54819 +#include <linux/module.h>
54820 +#include <linux/kernel.h>
54821 +#include <linux/version.h>
54822 +#include <linux/errno.h>
54823 +#include <linux/string.h>
54824 +#include <linux/mm.h>
54825 +#include <linux/fb.h>
54826 +#include <linux/init.h>
54827 +#include <linux/dma-mapping.h>
54828 +#include <linux/platform_device.h>
54829 +#include <linux/device.h>
54830 +#include <linux/uaccess.h>
54832 +#define DRIVER_NAME "ubicom32vfb"
54833 +#define DRIVER_DESCRIPTION "Ubicom32 virtual frame buffer driver"
54835 +#define PALETTE_ENTRIES_NO 16
54838 + * Option variables
54840 + * vram_size: VRAM size in kilobytes, subject to alignment
54842 +static int vram_size = 0;
54843 +module_param(vram_size, int, 0);
54844 +MODULE_PARM_DESC(vram_size, "VRAM size, in kilobytes to allocate, should be at least the size of one screen, subject to alignment");
54846 +static int xres = 320;
54847 +module_param(xres, int, 0);
54848 +MODULE_PARM_DESC(xres, "x (horizontal) resolution");
54850 +static int yres = 240;
54851 +module_param(yres, int, 0);
54852 +MODULE_PARM_DESC(yres, "y (vertical) resolution");
54854 +static int bgr = 0;
54855 +module_param(bgr, int, 0);
54856 +MODULE_PARM_DESC(bgr, "display is BGR (Blue is MSB)");
54858 +#define BITS_PER_PIXEL 16
54861 + * Buffer alignment, must not be 0
54863 +#define UBICOM32VFB_ALIGNMENT 4
54866 + * fb_fix_screeninfo defines the non-changeable properties of the VDC, depending on what mode it is in.
54868 +static struct fb_fix_screeninfo ubicom32vfb_fix = {
54869 + .id = "Ubicom32",
54870 + .type = FB_TYPE_PACKED_PIXELS,
54871 + .visual = FB_VISUAL_TRUECOLOR,
54872 + .accel = FB_ACCEL_UBICOM32_VFB,
54876 + * Filled in at probe time when we find out what the hardware supports
54878 +static struct fb_var_screeninfo ubicom32vfb_var;
54881 + * Private data structure
54883 +struct ubicom32vfb_drvdata {
54884 + struct fb_info *fbinfo;
54888 + * The address of the framebuffer in memory
54891 + void *fb_aligned;
54894 + * Total size of vram including alignment allowance
54896 + u32 total_vram_size;
54899 + * Fake palette of 16 colors
54901 + u32 pseudo_palette[PALETTE_ENTRIES_NO];
54904 +static struct platform_device *ubicom32vfb_platform_device;
54907 + * ubicom32vfb_pan_display
54908 + * Pans the display to a given location. Supports only y direction panning.
54910 +static int ubicom32vfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *fbi)
54912 + struct ubicom32vfb_drvdata *ud = (struct ubicom32vfb_drvdata *)fbi->par;
54916 + * Get the last y line that would be displayed. Since we don't support YWRAP,
54917 + * it must be less than our virtual y size.
54919 + u32 lasty = var->yoffset + var->yres;
54920 + if (lasty > fbi->var.yres_virtual) {
54922 + * We would fall off the end of our frame buffer if we panned here.
54927 + if (var->xoffset) {
54929 + * We don't support panning in the x direction
54935 + * Everything looks sane, go ahead and pan
54937 + * We have to calculate a new address for the VDC to look at
54939 + new_addr = ud->fb_aligned + (var->yoffset * fbi->fix.line_length);
54945 + * ubicom32vfb_setcolreg
54946 + * Sets a color in our virtual palette
54948 +static int ubicom32vfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *fbi)
54950 + u32 *palette = fbi->pseudo_palette;
54952 + if (regno >= PALETTE_ENTRIES_NO) {
54957 + * We only use 8 bits from each color
54964 + * Convert any grayscale values
54966 + if (fbi->var.grayscale) {
54967 + u16 gray = red + green + blue;
54968 + gray += (gray >> 2) + (gray >> 3) - (gray >> 7);
54970 + if (gray > 255) {
54978 + palette[regno] = (red << fbi->var.red.offset) | (green << fbi->var.green.offset) |
54979 + (blue << fbi->var.blue.offset);
54985 + * ubicom32vfb_mmap
54987 +static int ubicom32vfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
54989 + struct ubicom32vfb_drvdata *ud = (struct ubicom32vfb_drvdata *)info->par;
54991 + vma->vm_start = (unsigned long)(ud->fb_aligned);
54993 + vma->vm_end = vma->vm_start + info->fix.smem_len;
54995 + /* For those who don't understand how mmap works, go read
54996 + * Documentation/nommu-mmap.txt.
54997 + * For those that do, you will know that the VM_MAYSHARE flag
54998 + * must be set in the vma->vm_flags structure on noMMU
54999 + * Other flags can be set, and are documented in
55000 + * include/linux/mm.h
55003 + vma->vm_flags |= VM_MAYSHARE | VM_SHARED;
55009 + * ubicom32vfb_check_var
55010 + * Check the var, tweak it but don't change operational parameters.
55012 +static int ubicom32vfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
55014 + struct ubicom32vfb_drvdata *ud = (struct ubicom32vfb_drvdata *)info->par;
55015 + u32 line_size = var->xres * (BITS_PER_PIXEL / 8);
55018 + * See if we can handle this bpp
55020 + if (var->bits_per_pixel > BITS_PER_PIXEL) {
55023 + var->bits_per_pixel = BITS_PER_PIXEL;
55026 + * See if we have enough memory to handle this resolution
55028 + if ((line_size * var->yres * BITS_PER_PIXEL / 8) > ud->total_vram_size) {
55032 + var->xres_virtual = var->xres;
55033 + var->yres_virtual = ud->total_vram_size / line_size;
55035 + var->red.length = 5;
55036 + var->green.length = 6;
55037 + var->green.offset = 5;
55038 + var->blue.length = 5;
55039 + var->transp.offset = var->transp.length = 0;
55042 + var->red.offset = 0;
55043 + var->blue.offset = 11;
55045 + var->red.offset = 11;
55046 + var->blue.offset = 0;
55050 + var->height = -1;
55052 + var->vmode = FB_VMODE_NONINTERLACED;
55059 + * ubicom32vfb_set_par
55060 + * Set the video mode according to info->var
55062 +static int ubicom32vfb_set_par(struct fb_info *info)
55065 + * Anything changed?
55067 + if ((xres == info->var.xres) && (yres == info->var.yres)) {
55072 + * Implement changes
55074 + xres = info->var.xres;
55075 + yres = info->var.yres;
55076 + info->fix.visual = FB_VISUAL_TRUECOLOR;
55077 + info->fix.xpanstep = 0;
55078 + info->fix.ypanstep = 1;
55079 + info->fix.line_length = xres * (BITS_PER_PIXEL / 8);
55085 + * ubicom32vfb_ops
55086 + * List of supported operations
55088 +static struct fb_ops ubicom32vfb_ops =
55090 + .owner = THIS_MODULE,
55091 + .fb_pan_display = ubicom32vfb_pan_display,
55092 + .fb_setcolreg = ubicom32vfb_setcolreg,
55093 + .fb_mmap = ubicom32vfb_mmap,
55094 + .fb_check_var = ubicom32vfb_check_var,
55095 + .fb_set_par = ubicom32vfb_set_par,
55096 + .fb_fillrect = cfb_fillrect,
55097 + .fb_copyarea = cfb_copyarea,
55098 + .fb_imageblit = cfb_imageblit,
55102 + * ubicom32vfb_release
55104 +static int ubicom32vfb_release(struct device *dev)
55106 + struct ubicom32vfb_drvdata *ud = dev_get_drvdata(dev);
55108 + unregister_framebuffer(ud->fbinfo);
55110 + if (ud->cmap_alloc) {
55111 + fb_dealloc_cmap(&ud->fbinfo->cmap);
55118 + framebuffer_release(ud->fbinfo);
55119 + dev_set_drvdata(dev, NULL);
55125 + * ubicom32vfb_platform_probe
55127 +static int __init ubicom32vfb_platform_probe(struct platform_device *pdev)
55129 + struct ubicom32vfb_drvdata *ud;
55130 + struct fb_info *fbinfo;
55133 + struct device *dev = &pdev->dev;
55137 + * This is the minimum VRAM size
55139 + fbsize = xres * yres * 2;
55140 + if (!vram_size) {
55141 + vram_size = (fbsize + 1023) / 1024;
55143 + if (fbsize > (vram_size * 1024)) {
55144 + dev_err(dev, "Not enough VRAM for display, need >= %u bytes\n", fbsize);
55145 + return -ENOMEM; // should be ebadparam?
55150 + * Allocate the framebuffer instance + our private data
55152 + fbinfo = framebuffer_alloc(sizeof(struct ubicom32vfb_drvdata), &pdev->dev);
55154 + dev_err(dev, "Not enough memory to allocate instance.\n");
55159 + * Fill in our private data.
55161 + ud = (struct ubicom32vfb_drvdata *)fbinfo->par;
55162 + ud->fbinfo = fbinfo;
55163 + dev_set_drvdata(dev, ud);
55166 + * Allocate and align the requested amount of VRAM
55168 + ud->total_vram_size = (vram_size * 1024) + UBICOM32VFB_ALIGNMENT;
55169 + ud->fb = kmalloc(ud->total_vram_size, GFP_KERNEL);
55170 + if (ud->fb == NULL) {
55171 + dev_err(dev, "Couldn't allocate VRAM\n");
55176 + offset = (u32_t)ud->fb & (UBICOM32VFB_ALIGNMENT - 1);
55178 + ud->fb_aligned = ud->fb;
55180 + offset = UBICOM32VFB_ALIGNMENT - offset;
55181 + ud->fb_aligned = ud->fb + offset;
55185 + * Clear the entire frame buffer
55187 + memset(ud->fb_aligned, 0, vram_size * 1024);
55190 + * Fill in the fb_var_screeninfo structure
55192 + memset(&ubicom32vfb_var, 0, sizeof(ubicom32vfb_var));
55193 + ubicom32vfb_var.bits_per_pixel = BITS_PER_PIXEL;
55194 + ubicom32vfb_var.red.length = 5;
55195 + ubicom32vfb_var.green.length = 6;
55196 + ubicom32vfb_var.green.offset = 5;
55197 + ubicom32vfb_var.blue.length = 5;
55198 + ubicom32vfb_var.activate = FB_ACTIVATE_NOW;
55201 + ubicom32vfb_var.red.offset = 0;
55202 + ubicom32vfb_var.blue.offset = 11;
55204 + ubicom32vfb_var.red.offset = 11;
55205 + ubicom32vfb_var.blue.offset = 0;
55209 + * Fill in the fb_info structure
55211 + ud->fbinfo->device = dev;
55212 + ud->fbinfo->screen_base = (void *)ud->fb_aligned;
55213 + ud->fbinfo->fbops = &ubicom32vfb_ops;
55214 + ud->fbinfo->fix = ubicom32vfb_fix;
55215 + ud->fbinfo->fix.smem_start = (u32)ud->fb_aligned;
55216 + ud->fbinfo->fix.smem_len = vram_size * 1024;
55217 + ud->fbinfo->fix.line_length = xres * 2;
55218 + ud->fbinfo->fix.mmio_start = (u32)ud;
55219 + ud->fbinfo->fix.mmio_len = sizeof(struct ubicom32vfb_drvdata);
55222 + * We support panning in the y direction only
55224 + ud->fbinfo->fix.xpanstep = 0;
55225 + ud->fbinfo->fix.ypanstep = 1;
55227 + ud->fbinfo->pseudo_palette = ud->pseudo_palette;
55228 + ud->fbinfo->flags = FBINFO_DEFAULT;
55229 + ud->fbinfo->var = ubicom32vfb_var;
55230 + ud->fbinfo->var.xres = xres;
55231 + ud->fbinfo->var.yres = yres;
55234 + * We cannot pan in the X direction, so xres_virtual is xres
55235 + * We can pan in the Y direction, so yres_virtual is vram_size / ud->fbinfo->fix.line_length
55237 + ud->fbinfo->var.xres_virtual = xres;
55238 + ud->fbinfo->var.yres_virtual = (vram_size * 1024) / ud->fbinfo->fix.line_length;
55241 + * Allocate a color map
55243 + rc = fb_alloc_cmap(&ud->fbinfo->cmap, PALETTE_ENTRIES_NO, 0);
55245 + dev_err(dev, "Fail to allocate colormap (%d entries)\n",
55246 + PALETTE_ENTRIES_NO);
55249 + ud->cmap_alloc = true;
55252 + * Register new frame buffer
55254 + rc = register_framebuffer(ud->fbinfo);
55256 + dev_err(dev, "Could not register frame buffer\n");
55261 + * Tell the log we are here
55263 + dev_info(dev, "fbaddr=%p align=%p, size=%uKB screen(%ux%u) virt(%ux%u)\n",
55264 + ud->fb, ud->fb_aligned, vram_size, ud->fbinfo->var.xres, ud->fbinfo->var.yres,
55265 + ud->fbinfo->var.xres_virtual, ud->fbinfo->var.yres_virtual);
55273 + ubicom32vfb_release(dev);
55278 + * ubicom32vfb_platform_remove
55280 +static int ubicom32vfb_platform_remove(struct platform_device *pdev)
55282 + dev_info(&(pdev->dev), "Ubicom32 FB Driver Remove\n");
55283 + return ubicom32vfb_release(&pdev->dev);
55286 +static struct platform_driver ubicom32vfb_platform_driver = {
55287 + .probe = ubicom32vfb_platform_probe,
55288 + .remove = ubicom32vfb_platform_remove,
55290 + .name = DRIVER_NAME,
55291 + .owner = THIS_MODULE,
55297 + * ubicom32vfb_setup
55298 + * Process kernel boot options
55300 +static int __init ubicom32vfb_setup(char *options)
55304 + if (!options || !*options) {
55308 + while ((this_opt = strsep(&options, ",")) != NULL) {
55309 + if (!*this_opt) {
55313 + if (!strncmp(this_opt, "vram_size=", 10)) {
55314 + vram_size = simple_strtoul(this_opt + 10, NULL, 0);
55318 + if (!strncmp(this_opt, "bgr=", 4)) {
55319 + bgr = simple_strtoul(this_opt + 4, NULL, 0);
55323 + if (!strncmp(this_opt, "xres=", 5)) {
55324 + xres = simple_strtoul(this_opt + 5, NULL, 0);
55328 + if (!strncmp(this_opt, "yres=", 5)) {
55329 + yres = simple_strtoul(this_opt + 5, NULL, 0);
55335 +#endif /* MODULE */
55338 + * ubicom32vfb_init
55340 +static int __devinit ubicom32vfb_init(void)
55346 + * Get kernel boot options (in 'video=ubicom32vfb:<options>')
55348 + char *option = NULL;
55350 + if (fb_get_options(DRIVER_NAME, &option)) {
55353 + ubicom32vfb_setup(option);
55354 +#endif /* MODULE */
55356 + ret = platform_driver_register(&ubicom32vfb_platform_driver);
55358 +#ifdef CONFIG_FB_UBICOM32_VIRTUAL_NOAUTO
55362 + ubicom32vfb_platform_device = platform_device_alloc(DRIVER_NAME, 0);
55364 + if (ubicom32vfb_platform_device)
55365 + ret = platform_device_add(ubicom32vfb_platform_device);
55370 + platform_device_put(ubicom32vfb_platform_device);
55371 + platform_driver_unregister(&ubicom32vfb_platform_driver);
55378 +module_init(ubicom32vfb_init);
55381 + * ubicom32vfb_exit
55383 +static void __exit ubicom32vfb_exit(void)
55385 + platform_device_unregister(ubicom32vfb_platform_device);
55386 + platform_driver_unregister(&ubicom32vfb_platform_driver);
55388 +module_exit(ubicom32vfb_exit);
55390 +MODULE_LICENSE("GPL");
55391 +MODULE_AUTHOR("Patrick Tjin <@ubicom.com>");
55392 +MODULE_DESCRIPTION(DRIVER_DESCRIPTION);
55393 diff -ruN linux-2.6.30.10/drivers/watchdog/Kconfig linux-2.6.30.10-ubi/drivers/watchdog/Kconfig
55394 --- linux-2.6.30.10/drivers/watchdog/Kconfig 2009-12-04 08:00:07.000000000 +0200
55395 +++ linux-2.6.30.10-ubi/drivers/watchdog/Kconfig 2009-12-11 11:45:21.000000000 +0200
55396 @@ -887,6 +887,19 @@
55397 machines. The watchdog timeout period is normally one minute but
55398 can be changed with a boot-time parameter.
55403 + tristate "Ubicom32 Hardware Watchdog support"
55404 + depends on UBICOM32
55406 + If you say yes here you will get support for the Ubicom32 On-Chip
55407 + Watchdog Timer. If you have one of these processors and wish to
55408 + have watchdog support enabled, say Y, otherwise say N.
55410 + To compile this driver as a module, choose M here: the
55411 + module will be called ubi32_wdt.
55413 # XTENSA Architecture
55416 diff -ruN linux-2.6.30.10/drivers/watchdog/Makefile linux-2.6.30.10-ubi/drivers/watchdog/Makefile
55417 --- linux-2.6.30.10/drivers/watchdog/Makefile 2009-12-04 08:00:07.000000000 +0200
55418 +++ linux-2.6.30.10-ubi/drivers/watchdog/Makefile 2009-12-11 11:45:21.000000000 +0200
55419 @@ -131,6 +131,9 @@
55420 obj-$(CONFIG_WATCHDOG_RIO) += riowd.o
55421 obj-$(CONFIG_WATCHDOG_CP1XXX) += cpwd.o
55423 +# Ubicom32 Architecture
55424 +obj-$(CONFIG_UBI32_WDT) += ubi32_wdt.o
55426 # XTENSA Architecture
55428 # Architecture Independant
55429 diff -ruN linux-2.6.30.10/drivers/watchdog/ubi32_wdt.c linux-2.6.30.10-ubi/drivers/watchdog/ubi32_wdt.c
55430 --- linux-2.6.30.10/drivers/watchdog/ubi32_wdt.c 1970-01-01 02:00:00.000000000 +0200
55431 +++ linux-2.6.30.10-ubi/drivers/watchdog/ubi32_wdt.c 2009-12-11 11:45:21.000000000 +0200
55434 + * drivers/watchdog/ubi32_wdt.c
55435 + * Ubicom32 Watchdog Driver
55437 + * Originally based on softdog.c
55438 + * Copyright 2006-2007 Analog Devices Inc.
55439 + * Copyright 2006-2007 Michele d'Amico
55440 + * Copyright 1996 Alan Cox <alan@lxorguk.ukuu.org.uk>
55441 + * (C) Copyright 2009, Ubicom, Inc.
55443 + * This file is part of the Ubicom32 Linux Kernel Port.
55445 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
55446 + * it and/or modify it under the terms of the GNU General Public License
55447 + * as published by the Free Software Foundation, either version 2 of the
55448 + * License, or (at your option) any later version.
55450 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
55451 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
55452 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
55453 + * the GNU General Public License for more details.
55455 + * You should have received a copy of the GNU General Public License
55456 + * along with the Ubicom32 Linux Kernel Port. If not,
55457 + * see <http://www.gnu.org/licenses/>.
55459 + * Ubicom32 implementation derived from (with many thanks):
55464 +#include <linux/platform_device.h>
55465 +#include <linux/module.h>
55466 +#include <linux/moduleparam.h>
55467 +#include <linux/types.h>
55468 +#include <linux/timer.h>
55469 +#include <linux/miscdevice.h>
55470 +#include <linux/watchdog.h>
55471 +#include <linux/fs.h>
55472 +#include <linux/notifier.h>
55473 +#include <linux/reboot.h>
55474 +#include <linux/init.h>
55475 +#include <linux/interrupt.h>
55476 +#include <linux/uaccess.h>
55477 +#include <asm/ip5000.h>
55479 +#define WATCHDOG_NAME "ubi32-wdt"
55480 +#define PFX WATCHDOG_NAME ": "
55482 +#define OSC1_FREQ 12000000
55483 +#define WATCHDOG_SEC_TO_CYC(x) (OSC1_FREQ * (x))
55484 +#define WATCHDOG_MAX_SEC (0xffffffff / OSC1_FREQ)
55486 +#define MIN_PROCESSOR_ADDRESS 0x03000000
55488 +static DEFINE_SPINLOCK(ubi32_wdt_spinlock);
55490 +#define WATCHDOG_TIMEOUT 20
55492 +#if defined(CONFIG_WATCHDOG_NOWAYOUT)
55493 +#define WATCHDOG_NOWAYOUT 1
55495 +#define WATCHDOG_NOWAYOUT 0
55498 +static unsigned int timeout = WATCHDOG_TIMEOUT;
55499 +static int nowayout = WATCHDOG_NOWAYOUT;
55500 +static struct watchdog_info ubi32_wdt_info;
55501 +static unsigned long open_check;
55502 +static char expect_close;
55504 +#if !defined(CONFIG_SMP)
55505 +#define UBI32_WDT_LOCK(lock, flags) local_irq_save(flags)
55506 +#define UBI32_WDT_UNLOCK(lock, flags) local_irq_restore(flags)
55507 +#define UBI32_WDT_LOCK_CHECK()
55509 +#define UBI32_WDT_LOCK(lock, flags) spin_lock_irqsave((lock), (flags));
55510 +#define UBI32_WDT_UNLOCK(lock, flags) spin_unlock_irqrestore((lock), (flags));
55511 +#define UBI32_WDT_LOCK_CHECK() BUG_ON(!spin_is_locked(&ubi32_wdt_spinlock));
55515 + * ubi32_wdt_remaining()
55516 + * Return the approximate number of seconds remaining
55518 +static int ubi32_wdt_remaining(void)
55523 + UBI32_WDT_LOCK_CHECK();
55525 + ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, TIMER_TKEYVAL);
55526 + compare = ubicom32_read_reg(&UBICOM32_IO_TIMER->wdcom);
55527 + curr = ubicom32_read_reg(&UBICOM32_IO_TIMER->mptval);
55528 + ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, 0);
55529 + return (compare - curr) / OSC1_FREQ;
55534 + * ubi32_wdt_keepalive()
55535 + * Keep the Userspace Watchdog Alive
55537 + * The Userspace watchdog got a KeepAlive: schedule the next timeout.
55539 +static int ubi32_wdt_keepalive(void)
55541 + UBI32_WDT_LOCK_CHECK();
55542 + ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, TIMER_TKEYVAL);
55543 + ubicom32_write_reg(&UBICOM32_IO_TIMER->wdcom,
55544 + ubicom32_read_reg(&UBICOM32_IO_TIMER->mptval)
55545 + + WATCHDOG_SEC_TO_CYC(timeout));
55546 + ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, 0);
55551 + * ubi32_wdt_stop()
55552 + * Stop the on-chip Watchdog
55554 +static int ubi32_wdt_stop(void)
55556 + UBI32_WDT_LOCK_CHECK();
55557 + ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, TIMER_TKEYVAL);
55558 + ubicom32_write_reg(&UBICOM32_IO_TIMER->wdcfg, TIMER_WATCHDOG_DISABLE);
55559 + ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, 0);
55564 + * ubi32_wdt_start()
55565 + * Start the on-chip Watchdog
55567 +static int ubi32_wdt_start(void)
55569 + UBI32_WDT_LOCK_CHECK();
55570 + ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, TIMER_TKEYVAL);
55571 + ubicom32_write_reg(&UBICOM32_IO_TIMER->wdcom,
55572 + ubicom32_read_reg(&UBICOM32_IO_TIMER->mptval)
55573 + + WATCHDOG_SEC_TO_CYC(timeout));
55574 + ubicom32_write_reg(&UBICOM32_IO_TIMER->wdcfg, ~TIMER_WATCHDOG_DISABLE);
55575 + ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, 0);
55580 + * ubi32_wdt_running()
55581 + * Return true if the watchdog is configured
55583 +static int ubi32_wdt_running(void)
55587 + UBI32_WDT_LOCK_CHECK();
55588 + ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, TIMER_TKEYVAL);
55589 + enabled = ubicom32_read_reg(&UBICOM32_IO_TIMER->wdcfg) == ~TIMER_WATCHDOG_DISABLE;
55590 + ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, 0);
55595 + * ubi32_wdt_set_timeout()
55596 + * Set the Userspace Watchdog timeout
55598 + * - @t: new timeout value (in seconds)
55600 +static int ubi32_wdt_set_timeout(unsigned long t)
55602 + UBI32_WDT_LOCK_CHECK();
55604 + if (t > WATCHDOG_MAX_SEC) {
55605 + printk(KERN_WARNING PFX "request to large: %ld [1-%d] sec)\n", t, WATCHDOG_MAX_SEC);
55610 + * If we are running, then reset the time value so
55611 + * that the new value has an immediate effect.
55614 + if (ubi32_wdt_running()) {
55615 + ubi32_wdt_keepalive();
55621 + * ubi32_wdt_open()
55622 + * Open the Device
55624 +static int ubi32_wdt_open(struct inode *inode, struct file *file)
55626 + unsigned long flags;
55628 + if (test_and_set_bit(0, &open_check))
55632 + __module_get(THIS_MODULE);
55634 + spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
55635 + ubi32_wdt_start();
55636 + spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
55638 + return nonseekable_open(inode, file);
55642 + * ubi32_wdt_close()
55643 + * Close the Device
55645 +static int ubi32_wdt_release(struct inode *inode, struct file *file)
55647 + unsigned long flags;
55650 + * If we don't expect a close, then the watchdog continues
55651 + * even though the device is closed. The caller will have
55652 + * a full timeout value to reopen the device and continue
55655 + if (expect_close != 42) {
55656 + printk(KERN_CRIT PFX
55657 + "Unexpected close, not stopping watchdog!\n");
55658 + spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
55659 + ubi32_wdt_keepalive();
55660 + spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
55662 + spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
55663 + ubi32_wdt_stop();
55664 + spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
55667 + expect_close = 0;
55668 + clear_bit(0, &open_check);
55673 + * ubi32_wdt_write()
55674 + * Write to Device
55676 + * If the user writes nothing, nothing happens.
55677 + * If the user writes a V, then we expect a close and allow a release.
55678 + * If the user writes anything else, it is ignored.
55680 +static ssize_t ubi32_wdt_write(struct file *file, const char __user *data,
55681 + size_t len, loff_t *ppos)
55684 + unsigned long flags;
55687 + * Every write resets the expect_close. The last write
55688 + * must be a V to allow shutdown on close.
55690 + expect_close = 0;
55693 + * Empty writes still ping.
55700 + * If nowayout is set, it does not matter if the caller
55701 + * is trying to send the magic 'V' we will not allow a
55702 + * close to stop us.
55709 + * See if the program wrote a 'V' and if so disable
55710 + * the watchdog on release.
55712 + for (i = 0; i < len; i++) {
55714 + if (get_user(c, data + i)) {
55719 + expect_close = 42;
55724 + spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
55725 + ubi32_wdt_keepalive();
55726 + spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
55731 + * ubi32_wdt_ioctl()
55732 + * Query the watchdog device.
55734 + * Query basic information from the device or ping it, as outlined by the
55737 +static long ubi32_wdt_ioctl(struct file *file,
55738 + unsigned int cmd, unsigned long arg)
55740 + void __user *argp = (void __user *)arg;
55741 + int __user *p = argp;
55744 + case WDIOC_GETSUPPORT:
55745 + if (copy_to_user(argp, &ubi32_wdt_info, sizeof(ubi32_wdt_info))) {
55750 + case WDIOC_GETSTATUS: {
55751 + unsigned long flags;
55754 + spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
55755 + running = ubi32_wdt_running();
55756 + spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
55760 + case WDIOC_GETBOOTSTATUS:
55761 + return ubicom32_get_reset_reason();
55763 + case WDIOC_SETOPTIONS: {
55764 + unsigned long flags;
55765 + int options, ret = -EINVAL;
55768 + * The sample application does not pass a pointer
55769 + * but directly passes a value of 1 or 2; however
55770 + * all of the implementations (and thus probably
55771 + * the real applications) pass a pointer to a value.
55773 + * It should be noted that WDIOC_SETOPTIONS is defined as
55774 + * _IOR(WATCHDOG_IOCTL_BASE, 4, int), which means
55775 + * that it should be an int and NOT a pointer.
55777 + * TODO: Examine this code for future chips.
55778 + * TODO: Report the sample code defect.
55780 + if ((int)p < MIN_PROCESSOR_ADDRESS) {
55781 + options = (int)p;
55783 + if (get_user(options, p))
55787 + spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
55788 + if (options & WDIOS_DISABLECARD) {
55789 + ubi32_wdt_stop();
55792 + if (options & WDIOS_ENABLECARD) {
55793 + ubi32_wdt_start();
55796 + spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
55800 + case WDIOC_KEEPALIVE: {
55801 + unsigned long flags;
55803 + spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
55804 + ubi32_wdt_keepalive();
55805 + spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
55809 + case WDIOC_SETTIMEOUT: {
55811 + unsigned long flags;
55814 + if (get_user(new_timeout, p))
55817 + spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
55818 + ret = ubi32_wdt_set_timeout(new_timeout);
55819 + spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
55824 + case WDIOC_GETTIMEOUT:
55825 + return put_user(timeout, p);
55827 + case WDIOC_GETTIMELEFT: {
55828 + unsigned long flags;
55829 + int remaining = 0;
55831 + spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
55832 + remaining = ubi32_wdt_remaining();
55833 + spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
55834 + return put_user(remaining, p);
55843 + * ubi32_wdt_notify_sys()
55844 + * Notification callback function for system events.
55846 + * Turn off the watchdog during a SYS_DOWN or SYS_HALT.
55848 +static int ubi32_wdt_notify_sys(struct notifier_block *this,
55849 + unsigned long code, void *unused)
55851 + if (code == SYS_DOWN || code == SYS_HALT) {
55852 + unsigned long flags;
55854 + spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
55855 + ubi32_wdt_stop();
55856 + spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
55859 + return NOTIFY_DONE;
55863 +static int state_before_suspend;
55866 + * ubi32_wdt_suspend()
55867 + * suspend the watchdog
55869 + * Remember if the watchdog was running and stop it.
55871 +static int ubi32_wdt_suspend(struct platform_device *pdev, pm_message_t state)
55873 + unsigned long flags;
55874 + spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
55875 + state_before_suspend = ubi32_wdt_running();
55876 + ubi32_wdt_stop();
55877 + spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
55883 + * ubi32_wdt_resume()
55884 + * Resume the watchdog
55886 + * If the watchdog was running, turn it back on.
55888 +static int ubi32_wdt_resume(struct platform_device *pdev)
55890 + if (state_before_suspend) {
55891 + unsigned long flags;
55892 + spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
55893 + ubi32_wdt_set_timeout(timeout);
55894 + ubi32_wdt_start();
55895 + spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
55901 +# define ubi32_wdt_suspend NULL
55902 +# define ubi32_wdt_resume NULL
55905 +static const struct file_operations ubi32_wdt_fops = {
55906 + .owner = THIS_MODULE,
55907 + .llseek = no_llseek,
55908 + .write = ubi32_wdt_write,
55909 + .unlocked_ioctl = ubi32_wdt_ioctl,
55910 + .open = ubi32_wdt_open,
55911 + .release = ubi32_wdt_release,
55914 +static struct miscdevice ubi32_wdt_miscdev = {
55915 + .minor = WATCHDOG_MINOR,
55916 + .name = "watchdog",
55917 + .fops = &ubi32_wdt_fops,
55920 +static struct watchdog_info ubi32_wdt_info = {
55921 + .identity = "Ubicom32 Watchdog",
55922 + .options = WDIOF_SETTIMEOUT |
55923 + WDIOF_KEEPALIVEPING |
55924 + WDIOF_MAGICCLOSE,
55927 +static struct notifier_block ubi32_wdt_notifier = {
55928 + .notifier_call = ubi32_wdt_notify_sys,
55932 + * ubi32_wdt_probe()
55933 + * Probe/register the watchdog module
55935 + * Registers the misc device and notifier handler. Actual device
55936 + * initialization is handled by ubi32_wdt_open().
55938 +static int __devinit ubi32_wdt_probe(struct platform_device *pdev)
55942 + ret = register_reboot_notifier(&ubi32_wdt_notifier);
55944 + printk(KERN_ERR PFX
55945 + "cannot register reboot notifier (err=%d)\n", ret);
55949 + ret = misc_register(&ubi32_wdt_miscdev);
55951 + printk(KERN_ERR PFX
55952 + "cannot register miscdev on minor=%d (err=%d)\n",
55953 + WATCHDOG_MINOR, ret);
55954 + unregister_reboot_notifier(&ubi32_wdt_notifier);
55958 + printk(KERN_INFO PFX "initialized: timeout=%d sec (nowayout=%d)\n",
55959 + timeout, nowayout);
55965 + * ubi32_wdt_remove()
55966 + * Uninstall the module
55968 + * Unregisters the misc device and notifier handler. Actual device
55969 + * deinitialization is handled by ubi32_wdt_close().
55971 +static int __devexit ubi32_wdt_remove(struct platform_device *pdev)
55973 + misc_deregister(&ubi32_wdt_miscdev);
55974 + unregister_reboot_notifier(&ubi32_wdt_notifier);
55978 +static struct platform_device *ubi32_wdt_device;
55980 +static struct platform_driver ubi32_wdt_driver = {
55981 + .probe = ubi32_wdt_probe,
55982 + .remove = __devexit_p(ubi32_wdt_remove),
55983 + .suspend = ubi32_wdt_suspend,
55984 + .resume = ubi32_wdt_resume,
55986 + .name = WATCHDOG_NAME,
55987 + .owner = THIS_MODULE,
55992 + * ubi32_wdt_init()
55993 + * Initialize the watchdog.
55995 + * Checks the module params and registers the platform device & driver.
55996 + * Real work is in the platform probe function.
55998 +static int __init ubi32_wdt_init(void)
56000 + unsigned long flags;
56004 + * Check that the timeout value is within range
56006 + spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
56007 + ret = ubi32_wdt_set_timeout(timeout);
56008 + spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
56014 + * Since this is an on-chip device and needs no board-specific
56015 + * resources, we'll handle all the platform device stuff here.
56017 + ret = platform_driver_register(&ubi32_wdt_driver);
56019 + printk(KERN_ERR PFX "unable to register driver\n");
56023 + ubi32_wdt_device = platform_device_register_simple(WATCHDOG_NAME, -1, NULL, 0);
56024 + if (IS_ERR(ubi32_wdt_device)) {
56025 + printk(KERN_ERR PFX "unable to register device\n");
56026 + platform_driver_unregister(&ubi32_wdt_driver);
56027 + return PTR_ERR(ubi32_wdt_device);
56034 + * ubi32_wdt_exit()
56035 + * Deinitialize module
56037 + * Back out the platform device & driver steps. Real work is in the
56038 + * platform remove function.
56040 +static void __exit ubi32_wdt_exit(void)
56042 + platform_device_unregister(ubi32_wdt_device);
56043 + platform_driver_unregister(&ubi32_wdt_driver);
56046 +module_init(ubi32_wdt_init);
56047 +module_exit(ubi32_wdt_exit);
56049 +MODULE_AUTHOR("Sol Kavy<sol@ubicom.com>");
56050 +MODULE_DESCRIPTION("Ubicom32 Watchdog Device Driver");
56051 +MODULE_LICENSE("GPL");
56052 +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
56054 +module_param(timeout, uint, 0);
56055 +MODULE_PARM_DESC(timeout,
56056 + "Watchdog timeout in seconds. (1<=timeout<=((2^32)/SCLK), default="
56057 + __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
56059 +module_param(nowayout, int, 0);
56060 +MODULE_PARM_DESC(nowayout,
56061 + "Watchdog cannot be stopped once started (default="
56062 + __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
56063 diff -ruN linux-2.6.30.10/fs/binfmt_flat.c linux-2.6.30.10-ubi/fs/binfmt_flat.c
56064 --- linux-2.6.30.10/fs/binfmt_flat.c 2009-12-04 08:00:07.000000000 +0200
56065 +++ linux-2.6.30.10-ubi/fs/binfmt_flat.c 2009-12-11 11:45:21.000000000 +0200
56067 #define FLAT_DATA_ALIGN (sizeof(void *))
56070 +#ifndef ARCH_FLAT_ALIGN
56071 +#undef FLAT_DATA_ALIGN
56072 +#define FLAT_DATA_ALIGN ARCH_FLAT_ALIGN
56075 #define RELOC_FAILED 0xff00ff01 /* Relocation incorrect somewhere */
56076 #define UNLOADED_LIB 0x7ff000ff /* Placeholder for unused library */
56078 @@ -436,6 +441,7 @@
56080 unsigned long start_code, end_code;
56082 + int flush_happened = 0;
56084 hdr = ((struct flat_hdr *) bprm->buf); /* exec-header */
56085 inode = bprm->file->f_path.dentry->d_inode;
56086 @@ -521,6 +527,7 @@
56088 /* OK, This is the point of no return */
56089 set_personality(PER_LINUX_32BIT);
56090 + flush_happened = 1;
56094 @@ -535,6 +542,12 @@
56097 if ((flags & (FLAT_FLAG_RAM|FLAT_FLAG_GZIP)) == 0) {
56099 +#ifdef ARCH_FLAT_ALIGN_TEXT
56100 + printk("Unable to mmap rom with ARCH alignment requirements\n");
56105 * this should give us a ROM ptr, but if it doesn't we don't
56107 @@ -553,7 +566,7 @@
56111 - len = data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long);
56112 + len = data_len + extra + ALIGN(MAX_SHARED_LIBS * sizeof(unsigned long), FLAT_DATA_ALIGN);
56113 len = PAGE_ALIGN(len);
56114 down_write(¤t->mm->mmap_sem);
56115 realdatastart = do_mmap(0, 0, len,
56116 @@ -572,6 +585,7 @@
56117 datapos = ALIGN(realdatastart +
56118 MAX_SHARED_LIBS * sizeof(unsigned long),
56120 + //datapos = realdatastart + ALIGN(MAX_SHARED_LIBS * sizeof(unsigned long), ARCH_FLAT_ALIGN);
56122 DBG_FLT("BINFMT_FLAT: Allocated data+bss+stack (%d bytes): %x\n",
56123 (int)(data_len + bss_len + stack_len), (int)datapos);
56124 @@ -600,7 +614,11 @@
56128 - len = text_len + data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long);
56129 + len = text_len + data_len + extra + ALIGN(MAX_SHARED_LIBS * sizeof(unsigned long), FLAT_DATA_ALIGN);
56130 +#ifdef ARCH_FLAT_ALIGN_TEXT
56131 + /* Reserve space for the text alignment. */
56132 + len += FLAT_DATA_ALIGN;
56134 len = PAGE_ALIGN(len);
56135 down_write(¤t->mm->mmap_sem);
56136 textpos = do_mmap(0, 0, len,
56137 @@ -616,10 +634,17 @@
56142 +#ifdef ARCH_FLAT_ALIGN_TEXT
56143 + textpos = ALIGN(textpos + sizeof(struct flat_hdr), FLAT_DATA_ALIGN) - sizeof(struct flat_hdr);
56145 realdatastart = textpos + ntohl(hdr->data_start);
56146 datapos = ALIGN(realdatastart +
56147 MAX_SHARED_LIBS * sizeof(unsigned long),
56149 +// datapos = realdatastart + ALIGN(MAX_SHARED_LIBS * sizeof(unsigned long), ARCH_FLAT_ALIGN);
56150 +// reloc = (unsigned long *) (textpos + ntohl(hdr->reloc_start) +
56151 +// ALIGN(MAX_SHARED_LIBS * sizeof(unsigned long), ARCH_FLAT_ALIGN));
56153 reloc = (unsigned long *)
56154 (datapos + (ntohl(hdr->reloc_start) - text_len));
56155 @@ -659,7 +684,7 @@
56157 if (result >= (unsigned long)-4096) {
56158 printk("Unable to read code+data+bss, errno %d\n",(int)-result);
56159 - do_munmap(current->mm, textpos, text_len + data_len + extra +
56160 + do_munmap(current->mm, memp, text_len + data_len + extra +
56161 MAX_SHARED_LIBS * sizeof(unsigned long));
56164 @@ -672,6 +697,9 @@
56166 /* The main program needs a little extra setup in the task structure */
56167 start_code = textpos + sizeof (struct flat_hdr);
56168 +#ifdef ARCH_FLAT_ALIGN_TEXT
56169 + BUG_ON(ALIGN(start_code, FLAT_DATA_ALIGN) != start_code);
56171 end_code = textpos + text_len;
56173 current->mm->start_code = start_code;
56174 @@ -800,6 +828,13 @@
56178 + if (flush_happened) {
56180 + * The parent process has already started running. We cannot allow the child to return back to user space
56181 + * as this child is still uning the parent stack and 2 will clobber each other. We are going to kill this child.
56183 + do_exit(SIGTERM);
56188 diff -ruN linux-2.6.30.10/fs/Kconfig.binfmt linux-2.6.30.10-ubi/fs/Kconfig.binfmt
56189 --- linux-2.6.30.10/fs/Kconfig.binfmt 2009-12-04 08:00:07.000000000 +0200
56190 +++ linux-2.6.30.10-ubi/fs/Kconfig.binfmt 2009-12-11 11:45:21.000000000 +0200
56192 config BINFMT_ELF_FDPIC
56193 bool "Kernel support for FDPIC ELF binaries"
56195 - depends on (FRV || BLACKFIN || (SUPERH32 && !MMU))
56196 + depends on (FRV || BLACKFIN || (SUPERH32 && !MMU) || UBICOM32)
56198 ELF FDPIC binaries are based on ELF, but allow the individual load
56199 segments of a binary to be located in memory independently of each
56200 diff -ruN linux-2.6.30.10/include/asm-generic/resource.h linux-2.6.30.10-ubi/include/asm-generic/resource.h
56201 --- linux-2.6.30.10/include/asm-generic/resource.h 2009-12-04 08:00:07.000000000 +0200
56202 +++ linux-2.6.30.10-ubi/include/asm-generic/resource.h 2009-12-11 11:45:23.000000000 +0200
56203 @@ -69,13 +69,16 @@
56205 * boot-time rlimit defaults for the init task:
56207 +#ifndef CONFIG_ELF_CORE
56208 +#define CONFIG_USER_ELF_CORE_SIZE 0
56210 #define INIT_RLIMITS \
56212 [RLIMIT_CPU] = { RLIM_INFINITY, RLIM_INFINITY }, \
56213 [RLIMIT_FSIZE] = { RLIM_INFINITY, RLIM_INFINITY }, \
56214 [RLIMIT_DATA] = { RLIM_INFINITY, RLIM_INFINITY }, \
56215 [RLIMIT_STACK] = { _STK_LIM, _STK_LIM_MAX }, \
56216 - [RLIMIT_CORE] = { 0, RLIM_INFINITY }, \
56217 + [RLIMIT_CORE] = { CONFIG_USER_ELF_CORE_SIZE, RLIM_INFINITY }, \
56218 [RLIMIT_RSS] = { RLIM_INFINITY, RLIM_INFINITY }, \
56219 [RLIMIT_NPROC] = { 0, 0 }, \
56220 [RLIMIT_NOFILE] = { INR_OPEN, INR_OPEN }, \
56221 diff -ruN linux-2.6.30.10/include/linux/elf-em.h linux-2.6.30.10-ubi/include/linux/elf-em.h
56222 --- linux-2.6.30.10/include/linux/elf-em.h 2009-12-04 08:00:07.000000000 +0200
56223 +++ linux-2.6.30.10-ubi/include/linux/elf-em.h 2009-12-11 11:45:23.000000000 +0200
56225 * up with a final number.
56227 #define EM_ALPHA 0x9026
56228 +#define EM_UBICOM32 0xde3d /* Ubicom32; no ABI */
56230 /* Bogus old v850 magic number, used by old tools. */
56231 #define EM_CYGNUS_V850 0x9080
56232 diff -ruN linux-2.6.30.10/include/linux/fb.h linux-2.6.30.10-ubi/include/linux/fb.h
56233 --- linux-2.6.30.10/include/linux/fb.h 2009-12-14 12:16:53.000000000 +0200
56234 +++ linux-2.6.30.10-ubi/include/linux/fb.h 2009-12-14 12:16:56.000000000 +0200
56235 @@ -151,6 +151,10 @@
56236 #define FB_ACCEL_PROSAVAGE_DDR 0x8d /* S3 ProSavage DDR */
56237 #define FB_ACCEL_PROSAVAGE_DDRK 0x8e /* S3 ProSavage DDR-K */
56239 +#define FB_ACCEL_UBICOM32 0x0100 /* Ubicom32 */
56240 +#define FB_ACCEL_UBICOM32_VFB 0x0101 /* Ubicom32 VFB */
56241 +#define FB_ACCEL_UBICOM32_PLIO80 0x0102 /* Ubicom32 PLIO80 */
56243 struct fb_fix_screeninfo {
56244 char id[16]; /* identification string eg "TT Builtin" */
56245 unsigned long smem_start; /* Start of frame buffer mem */
56246 diff -ruN linux-2.6.30.10/include/linux/if_ppp.h linux-2.6.30.10-ubi/include/linux/if_ppp.h
56247 --- linux-2.6.30.10/include/linux/if_ppp.h 2009-12-04 08:00:07.000000000 +0200
56248 +++ linux-2.6.30.10-ubi/include/linux/if_ppp.h 2009-12-11 11:45:23.000000000 +0200
56249 @@ -114,14 +114,14 @@
56250 __u16 tunnel_id; /* redundant */
56251 __u16 session_id; /* if zero, get tunnel stats */
56252 __u32 using_ipsec:1; /* valid only for session_id == 0 */
56253 - aligned_u64 tx_packets;
56254 - aligned_u64 tx_bytes;
56255 - aligned_u64 tx_errors;
56256 - aligned_u64 rx_packets;
56257 - aligned_u64 rx_bytes;
56258 - aligned_u64 rx_seq_discards;
56259 - aligned_u64 rx_oos_packets;
56260 - aligned_u64 rx_errors;
56261 + __u64 tx_packets;
56264 + __u64 rx_packets;
56266 + __u64 rx_seq_discards;
56267 + __u64 rx_oos_packets;
56271 #define ifr__name b.ifr_ifrn.ifrn_name
56272 diff -ruN linux-2.6.30.10/include/linux/oprofile.h linux-2.6.30.10-ubi/include/linux/oprofile.h
56273 --- linux-2.6.30.10/include/linux/oprofile.h 2009-12-04 08:00:07.000000000 +0200
56274 +++ linux-2.6.30.10-ubi/include/linux/oprofile.h 2009-12-11 11:45:23.000000000 +0200
56277 void oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs,
56278 unsigned long event, int is_kernel);
56279 +void oprofile_add_ext_sample_cpu(unsigned long pc, struct pt_regs * const regs,
56280 + unsigned long event, int is_kernel, int cpu);
56282 /* Use this instead when the PC value is not from the regs. Doesn't
56284 diff -ruN linux-2.6.30.10/include/linux/serial_core.h linux-2.6.30.10-ubi/include/linux/serial_core.h
56285 --- linux-2.6.30.10/include/linux/serial_core.h 2009-12-04 08:00:07.000000000 +0200
56286 +++ linux-2.6.30.10-ubi/include/linux/serial_core.h 2009-12-11 11:45:23.000000000 +0200
56287 @@ -167,6 +167,9 @@
56289 #define PORT_MAX3100 86
56292 +#define PORT_UBI32_UARTTIO 87
56296 #include <linux/compiler.h>
56297 diff -ruN linux-2.6.30.10/include/linux/slab.h linux-2.6.30.10-ubi/include/linux/slab.h
56298 --- linux-2.6.30.10/include/linux/slab.h 2009-12-04 08:00:07.000000000 +0200
56299 +++ linux-2.6.30.10-ubi/include/linux/slab.h 2009-12-11 11:45:23.000000000 +0200
56300 @@ -317,4 +317,14 @@
56301 return kmalloc_node(size, flags | __GFP_ZERO, node);
56304 +struct kmem_cache_size_info {
56305 + unsigned short page;
56306 + unsigned short order;
56310 + * get info on all the memory allocated by slab for this named cache
56312 +extern int kmem_cache_block_info(char *name, struct kmem_cache_size_info *data, int max_data);
56314 #endif /* _LINUX_SLAB_H */
56315 diff -ruN linux-2.6.30.10/init/Kconfig linux-2.6.30.10-ubi/init/Kconfig
56316 --- linux-2.6.30.10/init/Kconfig 2009-12-14 13:00:08.000000000 +0200
56317 +++ linux-2.6.30.10-ubi/init/Kconfig 2009-12-14 13:00:11.000000000 +0200
56318 @@ -865,6 +865,12 @@
56320 Enable support for generating core dumps. Disabling saves about 4k.
56322 +config USER_ELF_CORE_SIZE
56323 + int "user core dump size (10MB to 32MB)"
56324 + range 10485760 33554432
56326 + depends on ELF_CORE
56328 config PCSPKR_PLATFORM
56329 bool "Enable PC-Speaker support" if EMBEDDED
56330 depends on ALPHA || X86 || MIPS || PPC_PREP || PPC_CHRP || PPC_PSERIES
56331 diff -ruN linux-2.6.30.10/kernel/module.c linux-2.6.30.10-ubi/kernel/module.c
56332 --- linux-2.6.30.10/kernel/module.c 2009-12-04 08:00:07.000000000 +0200
56333 +++ linux-2.6.30.10-ubi/kernel/module.c 2009-12-11 11:45:24.000000000 +0200
56334 @@ -2688,6 +2688,9 @@
56335 /* Used by oprofile and other similar tools. */
56336 seq_printf(m, " 0x%p", mod->module_core);
56338 +#ifdef ARCH_PROC_MODULES_EXTRA
56339 + ARCH_PROC_MODULES_EXTRA(m, mod);
56343 seq_printf(m, " %s", module_flags(mod, buf));
56344 @@ -2840,8 +2843,12 @@
56345 printk("Modules linked in:");
56346 /* Most callers should already have preempt disabled, but make sure */
56348 - list_for_each_entry_rcu(mod, &modules, list)
56349 + list_for_each_entry_rcu(mod, &modules, list) {
56350 printk(" %s%s", mod->name, module_flags(mod, buf));
56351 +#ifdef ARCH_OOPS_MODULE_EXTRA
56352 + ARCH_OOPS_MODULE_EXTRA(mod);
56356 if (last_unloaded_module[0])
56357 printk(" [last unloaded: %s]", last_unloaded_module);
56358 diff -ruN linux-2.6.30.10/kernel/sched_clock.c linux-2.6.30.10-ubi/kernel/sched_clock.c
56359 --- linux-2.6.30.10/kernel/sched_clock.c 2009-12-04 08:00:07.000000000 +0200
56360 +++ linux-2.6.30.10-ubi/kernel/sched_clock.c 2009-12-11 11:45:24.000000000 +0200
56363 unsigned long long __attribute__((weak)) sched_clock(void)
56365 - return (unsigned long long)(jiffies - INITIAL_JIFFIES)
56366 - * (NSEC_PER_SEC / HZ);
56367 + return (get_jiffies_64() - INITIAL_JIFFIES) * (NSEC_PER_SEC / HZ);
56370 static __read_mostly int sched_clock_running;
56371 diff -ruN linux-2.6.30.10/lib/Kconfig.debug linux-2.6.30.10-ubi/lib/Kconfig.debug
56372 --- linux-2.6.30.10/lib/Kconfig.debug 2009-12-04 08:00:07.000000000 +0200
56373 +++ linux-2.6.30.10-ubi/lib/Kconfig.debug 2009-12-11 11:45:24.000000000 +0200
56374 @@ -621,7 +621,7 @@
56375 bool "Compile the kernel with frame pointers"
56376 depends on DEBUG_KERNEL && \
56377 (CRIS || M68K || M68KNOMMU || FRV || UML || \
56378 - AVR32 || SUPERH || BLACKFIN || MN10300) || \
56379 + AVR32 || SUPERH || BLACKFIN || MN10300 || UBICOM32) || \
56380 ARCH_WANT_FRAME_POINTERS
56381 default y if (DEBUG_INFO && UML) || ARCH_WANT_FRAME_POINTERS
56383 diff -ruN linux-2.6.30.10/mm/Makefile linux-2.6.30.10-ubi/mm/Makefile
56384 --- linux-2.6.30.10/mm/Makefile 2009-12-04 08:00:07.000000000 +0200
56385 +++ linux-2.6.30.10-ubi/mm/Makefile 2009-12-11 11:45:24.000000000 +0200
56388 obj-$(CONFIG_QUICKLIST) += quicklist.o
56389 obj-$(CONFIG_CGROUP_MEM_RES_CTLR) += memcontrol.o page_cgroup.o
56391 +CFLAGS_slab.o := $(PROFILING) -O2
56392 diff -ruN linux-2.6.30.10/mm/slab.c linux-2.6.30.10-ubi/mm/slab.c
56393 --- linux-2.6.30.10/mm/slab.c 2009-12-04 08:00:07.000000000 +0200
56394 +++ linux-2.6.30.10-ubi/mm/slab.c 2009-12-11 11:45:24.000000000 +0200
56395 @@ -4100,6 +4100,68 @@
56397 #ifdef CONFIG_SLABINFO
56401 + * get info on all the memory allocated by slab for this named cache
56403 +int kmem_cache_block_info(char *name, struct kmem_cache_size_info *data, int max_data)
56408 + struct kmem_cache *cachep;
56409 + struct kmem_list3 *l3;
56410 + struct slab *slabp;
56412 + /* Find the cache in the chain of caches. */
56413 + mutex_lock(&cache_chain_mutex);
56414 + list_for_each_entry(cachep, &cache_chain, next) {
56415 + if (strcmp(cachep->name, name) == 0) {
56420 + mutex_unlock(&cache_chain_mutex);
56424 + for_each_online_node(node) {
56425 + l3 = cachep->nodelists[node];
56428 + if (res >= max_data)
56431 + spin_lock_irq(&l3->list_lock);
56433 + list_for_each_entry(slabp, &l3->slabs_full, list) {
56434 + if (res >= max_data)
56436 + data[res].page = ((unsigned int)slabp->s_mem >> PAGE_SHIFT) & 0xffff;
56437 + data[res].order = cachep->gfporder;
56440 + list_for_each_entry(slabp, &l3->slabs_partial, list) {
56441 + if (res >= max_data)
56443 + data[res].page = ((unsigned int)slabp->s_mem >> PAGE_SHIFT) & 0xffff;
56444 + data[res].order = cachep->gfporder;
56447 + list_for_each_entry(slabp, &l3->slabs_free, list) {
56448 + if (res >= max_data)
56450 + data[res].page = ((unsigned int)slabp->s_mem >> PAGE_SHIFT) & 0xffff;
56451 + data[res].order = cachep->gfporder;
56455 + spin_unlock_irq(&l3->list_lock);
56461 static void print_slabinfo_header(struct seq_file *m)
56464 diff -ruN linux-2.6.30.10/scripts/mod/file2alias.c linux-2.6.30.10-ubi/scripts/mod/file2alias.c
56465 --- linux-2.6.30.10/scripts/mod/file2alias.c 2009-12-04 08:00:07.000000000 +0200
56466 +++ linux-2.6.30.10-ubi/scripts/mod/file2alias.c 2009-12-11 11:45:24.000000000 +0200
56467 @@ -774,6 +774,15 @@
56472 + * somehow our gcc is not generating st_size correctly and set 0 for some symbols.
56473 + * and 0 size will break do_table since it adjust size to (size - id_size)
56474 + * this is to make sure st_size fall in range.
56476 + if (sym->st_size == 0 || sym->st_size > info->sechdrs[sym->st_shndx].sh_size) {
56477 + sym->st_size = info->sechdrs[sym->st_shndx].sh_size;
56480 if (sym_is(symname, "__mod_pci_device_table"))
56481 do_table(symval, sym->st_size,
56482 sizeof(struct pci_device_id), "pci",
56483 diff -ruN linux-2.6.30.10/sound/Kconfig linux-2.6.30.10-ubi/sound/Kconfig
56484 --- linux-2.6.30.10/sound/Kconfig 2009-12-04 08:00:07.000000000 +0200
56485 +++ linux-2.6.30.10-ubi/sound/Kconfig 2009-12-11 11:45:24.000000000 +0200
56488 source "sound/soc/Kconfig"
56490 +source "sound/ubicom32/Kconfig"
56494 menuconfig SOUND_PRIME
56495 diff -ruN linux-2.6.30.10/sound/Makefile linux-2.6.30.10-ubi/sound/Makefile
56496 --- linux-2.6.30.10/sound/Makefile 2009-12-04 08:00:07.000000000 +0200
56497 +++ linux-2.6.30.10-ubi/sound/Makefile 2009-12-11 11:45:24.000000000 +0200
56499 obj-$(CONFIG_SOUND_PRIME) += oss/
56500 obj-$(CONFIG_DMASOUND) += oss/
56501 obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ sh/ synth/ usb/ \
56502 - sparc/ spi/ parisc/ pcmcia/ mips/ soc/ atmel/
56503 + sparc/ spi/ parisc/ pcmcia/ mips/ soc/ atmel/ ubicom32/
56504 obj-$(CONFIG_SND_AOA) += aoa/
56506 # This one must be compilable even if sound is configured out
56507 diff -ruN linux-2.6.30.10/sound/ubicom32/Kconfig linux-2.6.30.10-ubi/sound/ubicom32/Kconfig
56508 --- linux-2.6.30.10/sound/ubicom32/Kconfig 1970-01-01 02:00:00.000000000 +0200
56509 +++ linux-2.6.30.10-ubi/sound/ubicom32/Kconfig 2009-12-11 11:45:25.000000000 +0200
56511 +# ALSA Ubicom32 drivers
56513 +menuconfig SND_UBI32
56514 + tristate "Ubicom32 sound devices"
56518 + Say Y here to include support for audio on the Ubicom32 platform.
56519 + To compile this driver as a module, say M here: the module will be
56520 + called snd_ubi32.
56524 +config SND_UBI32_AUDIO_GENERIC_CAPTURE
56525 + bool "Generic Capture Support"
56528 + Use this option to support ADCs which don't require special drivers.
56530 +config SND_UBI32_AUDIO_GENERIC
56531 + bool "Generic Playback Support"
56534 + Use this option to support DACs which don't require special drivers.
56536 +comment "I2C Based Codecs"
56538 +config SND_UBI32_AUDIO_CS4350
56539 + bool "Cirrus Logic CS4350 DAC"
56543 + Support for the Cirrus Logic CS4350 DAC.
56545 +config SND_UBI32_AUDIO_CS4384
56546 + bool "Cirrus Logic CS4384 DAC"
56550 + Support for the Cirrus Logic CS4384 DAC.
56553 diff -ruN linux-2.6.30.10/sound/ubicom32/Makefile linux-2.6.30.10-ubi/sound/ubicom32/Makefile
56554 --- linux-2.6.30.10/sound/ubicom32/Makefile 1970-01-01 02:00:00.000000000 +0200
56555 +++ linux-2.6.30.10-ubi/sound/ubicom32/Makefile 2009-12-11 11:45:25.000000000 +0200
56558 +# sound/ubicom32/Makefile
56559 +# Makefile for ALSA
56561 +# (C) Copyright 2009, Ubicom, Inc.
56563 +# This file is part of the Ubicom32 Linux Kernel Port.
56565 +# The Ubicom32 Linux Kernel Port is free software: you can redistribute
56566 +# it and/or modify it under the terms of the GNU General Public License
56567 +# as published by the Free Software Foundation, either version 2 of the
56568 +# License, or (at your option) any later version.
56570 +# The Ubicom32 Linux Kernel Port is distributed in the hope that it
56571 +# will be useful, but WITHOUT ANY WARRANTY; without even the implied
56572 +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
56573 +# the GNU General Public License for more details.
56575 +# You should have received a copy of the GNU General Public License
56576 +# along with the Ubicom32 Linux Kernel Port. If not,
56577 +# see <http://www.gnu.org/licenses/>.
56579 +# Ubicom32 implementation derived from (with many thanks):
56585 +CFLAGS_ubi32.o += -O2
56586 +snd-ubi32-pcm-objs := ubi32-pcm.o
56587 +snd-ubi32-generic-objs := ubi32-generic.o
56588 +snd-ubi32-generic-capture-objs := ubi32-generic-capture.o
56589 +snd-ubi32-cs4350-objs := ubi32-cs4350.o
56590 +snd-ubi32-cs4384-objs := ubi32-cs4384.o
56592 +# Toplevel Module Dependency
56593 +obj-$(CONFIG_SND_UBI32) += snd-ubi32-pcm.o
56594 +obj-$(CONFIG_SND_UBI32_AUDIO_GENERIC) += snd-ubi32-generic.o
56595 +obj-$(CONFIG_SND_UBI32_AUDIO_GENERIC_CAPTURE) += snd-ubi32-generic-capture.o
56596 +obj-$(CONFIG_SND_UBI32_AUDIO_CS4350) += snd-ubi32-cs4350.o
56597 +obj-$(CONFIG_SND_UBI32_AUDIO_CS4384) += snd-ubi32-cs4384.o
56598 diff -ruN linux-2.6.30.10/sound/ubicom32/ubi32-cs4350.c linux-2.6.30.10-ubi/sound/ubicom32/ubi32-cs4350.c
56599 --- linux-2.6.30.10/sound/ubicom32/ubi32-cs4350.c 1970-01-01 02:00:00.000000000 +0200
56600 +++ linux-2.6.30.10-ubi/sound/ubicom32/ubi32-cs4350.c 2009-12-11 11:45:25.000000000 +0200
56603 + * sound/ubicom32/ubi32-cs4350.c
56604 + * Interface to ubicom32 virtual audio peripheral - using CS4350 DAC
56606 + * (C) Copyright 2009, Ubicom, Inc.
56608 + * This file is part of the Ubicom32 Linux Kernel Port.
56610 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
56611 + * it and/or modify it under the terms of the GNU General Public License
56612 + * as published by the Free Software Foundation, either version 2 of the
56613 + * License, or (at your option) any later version.
56615 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
56616 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
56617 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
56618 + * the GNU General Public License for more details.
56620 + * You should have received a copy of the GNU General Public License
56621 + * along with the Ubicom32 Linux Kernel Port. If not,
56622 + * see <http://www.gnu.org/licenses/>.
56625 +#include <linux/i2c.h>
56626 +#include <linux/module.h>
56627 +#include <linux/moduleparam.h>
56628 +#include <sound/core.h>
56629 +#include <sound/tlv.h>
56630 +#include <sound/control.h>
56631 +#include <sound/pcm.h>
56632 +#include <sound/initval.h>
56633 +#include "ubi32.h"
56635 +#define DRIVER_NAME "snd-ubi32-cs4350"
56638 + * Module properties
56640 +static const struct i2c_device_id snd_ubi32_cs4350_id[] = {
56644 +MODULE_DEVICE_TABLE(i2c, ubicom32audio_id);
56646 +static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */
56649 + * The dB scale for the Cirrus Logic cs4350. The output range is from
56650 + * -127.5 dB to 0 dB.
56652 +static const DECLARE_TLV_DB_SCALE(snd_ubi32_cs4350_db, -12750, 50, 0);
56654 +#define ubi32_cs4350_mute_info snd_ctl_boolean_stereo_info
56657 + * Private data for cs4350 chip
56659 +struct ubi32_cs4350_priv {
56661 + * The current volume settings
56663 + uint8_t volume[2];
56666 + * Bitmask of mutes MSB (unused, ..., unused, right_ch, left_ch) LSB
56671 + * Lock to protect this struct because callbacks are not atomic.
56677 + * The info for the cs4350. The volume currently has one channel,
56678 + * and 255 possible settings.
56680 +static int ubi32_cs4350_volume_info(struct snd_kcontrol *kcontrol,
56681 + struct snd_ctl_elem_info *uinfo)
56683 + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
56684 + uinfo->count = 2;
56685 + uinfo->value.integer.min = 0;
56686 + uinfo->value.integer.max = 255; // 8 bits in cirrus logic cs4350 volume register
56690 +static int ubi32_cs4350_volume_get(struct snd_kcontrol *kcontrol,
56691 + struct snd_ctl_elem_value *ucontrol)
56693 + struct ubi32_snd_priv *ubi32_priv = snd_kcontrol_chip(kcontrol);
56694 + struct ubi32_cs4350_priv *cs4350_priv;
56695 + unsigned long flags;
56697 + cs4350_priv = snd_ubi32_priv_get_drv(ubi32_priv);
56699 + spin_lock_irqsave(&cs4350_priv->lock, flags);
56701 + ucontrol->value.integer.value[0] = cs4350_priv->volume[0];
56702 + ucontrol->value.integer.value[1] = cs4350_priv->volume[1];
56704 + spin_unlock_irqrestore(&cs4350_priv->lock, flags);
56709 +static int ubi32_cs4350_volume_put(struct snd_kcontrol *kcontrol,
56710 + struct snd_ctl_elem_value *ucontrol)
56712 + struct ubi32_snd_priv *ubi32_priv = snd_kcontrol_chip(kcontrol);
56713 + struct i2c_client *client = (struct i2c_client *)ubi32_priv->client;
56714 + struct ubi32_cs4350_priv *cs4350_priv;
56715 + unsigned long flags;
56716 + int ret, changed;
56718 + uint8_t volume_reg_value_left, volume_reg_value_right;
56722 + cs4350_priv = snd_ubi32_priv_get_drv(ubi32_priv);
56723 + volume_reg_value_left = 255 - (ucontrol->value.integer.value[0] & 0xFF);
56724 + volume_reg_value_right = 255 - (ucontrol->value.integer.value[1] & 0xFF);
56726 +#if SND_UBI32_DEBUG
56727 + snd_printk(KERN_INFO "Setting volume: writing %d,%d to CS4350 volume registers\n", volume_reg_value_left, volume_reg_value_right);
56729 + spin_lock_irqsave(&cs4350_priv->lock, flags);
56731 + if (cs4350_priv->volume[0] != ucontrol->value.integer.value[0]) {
56732 + send[0] = 0x05; // left channel
56733 + send[1] = volume_reg_value_left;
56734 + ret = i2c_master_send(client, send, 2);
56736 + snd_printk(KERN_ERR "Failed to set channel A volume on CS4350\n");
56739 + cs4350_priv->volume[0] = ucontrol->value.integer.value[0];
56743 + if (cs4350_priv->volume[1] != ucontrol->value.integer.value[1]) {
56744 + send[0] = 0x06; // right channel
56745 + send[1] = volume_reg_value_right;
56746 + ret = i2c_master_send(client, send, 2);
56748 + snd_printk(KERN_ERR "Failed to set channel B volume on CS4350\n");
56751 + cs4350_priv->volume[1] = ucontrol->value.integer.value[1];
56755 + spin_unlock_irqrestore(&cs4350_priv->lock, flags);
56760 +static struct snd_kcontrol_new ubi32_cs4350_volume __devinitdata = {
56761 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
56762 + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
56763 + SNDRV_CTL_ELEM_ACCESS_TLV_READ,
56764 + .name = "PCM Playback Volume",
56765 + .info = ubi32_cs4350_volume_info,
56766 + .get = ubi32_cs4350_volume_get,
56767 + .put = ubi32_cs4350_volume_put,
56768 + .tlv.p = snd_ubi32_cs4350_db,
56771 +static int ubi32_cs4350_mute_get(struct snd_kcontrol *kcontrol,
56772 + struct snd_ctl_elem_value *ucontrol)
56774 + struct ubi32_snd_priv *ubi32_priv = snd_kcontrol_chip(kcontrol);
56775 + struct ubi32_cs4350_priv *cs4350_priv;
56776 + unsigned long flags;
56778 + cs4350_priv = snd_ubi32_priv_get_drv(ubi32_priv);
56780 + spin_lock_irqsave(&cs4350_priv->lock, flags);
56782 + ucontrol->value.integer.value[0] = cs4350_priv->mute & 1;
56783 + ucontrol->value.integer.value[1] = (cs4350_priv->mute & (1 << 1)) ? 1 : 0;
56785 + spin_unlock_irqrestore(&cs4350_priv->lock, flags);
56790 +static int ubi32_cs4350_mute_put(struct snd_kcontrol *kcontrol,
56791 + struct snd_ctl_elem_value *ucontrol)
56793 + struct ubi32_snd_priv *ubi32_priv = snd_kcontrol_chip(kcontrol);
56794 + struct i2c_client *client = (struct i2c_client *)ubi32_priv->client;
56795 + struct ubi32_cs4350_priv *cs4350_priv;
56796 + unsigned long flags;
56797 + int ret, changed;
56804 + cs4350_priv = snd_ubi32_priv_get_drv(ubi32_priv);
56806 + spin_lock_irqsave(&cs4350_priv->lock, flags);
56808 + if ((cs4350_priv->mute & 1) != ucontrol->value.integer.value[0]) {
56810 + ret = i2c_master_send(client, send, 1);
56812 + snd_printk(KERN_ERR "Failed to write to mute register: channel 0\n");
56816 + ret = i2c_master_recv(client, recv, 1);
56818 + snd_printk(KERN_ERR "Failed to read mute register: channel 0\n");
56824 + if (ucontrol->value.integer.value[0]) {
56825 + cs4350_priv->mute |= 1;
56826 + mute &= ~(1 << 4);
56827 +#if SND_UBI32_DEBUG
56828 + snd_printk(KERN_INFO "Unmuted channel A\n");
56831 + cs4350_priv->mute &= ~1;
56832 + mute |= (1 << 4);
56833 +#if SND_UBI32_DEBUG
56834 + snd_printk(KERN_INFO "Muted channel A\n");
56840 + ret = i2c_master_send(client, send, 2);
56842 + snd_printk(KERN_ERR "Failed to set channel A mute on CS4350\n");
56848 + if (((cs4350_priv->mute & 2) >> 1) != ucontrol->value.integer.value[1]) {
56850 + ret = i2c_master_send(client, send, 1);
56852 + snd_printk(KERN_ERR "Failed to write to mute register: channel 1\n");
56856 + ret = i2c_master_recv(client, recv, 1);
56858 + snd_printk(KERN_ERR "Failed to read mute register: channel 1\n");
56864 + if (ucontrol->value.integer.value[1]) {
56865 + cs4350_priv->mute |= (1 << 1);
56866 + mute &= ~(1 << 3);
56867 +#if SND_UBI32_DEBUG
56868 + snd_printk(KERN_INFO "Unmuted channel B\n");
56871 + cs4350_priv->mute &= ~(1 << 1);
56872 + mute |= (1 << 3);
56873 +#if SND_UBI32_DEBUG
56874 + snd_printk(KERN_INFO "Muted channel B\n");
56880 + ret = i2c_master_send(client, send, 2);
56882 + snd_printk(KERN_ERR "Failed to set channel A mute on CS4350\n");
56888 + spin_unlock_irqrestore(&cs4350_priv->lock, flags);
56893 +static struct snd_kcontrol_new ubi32_cs4350_mute __devinitdata = {
56894 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
56895 + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
56896 + .name = "PCM Playback Switch",
56897 + .info = ubi32_cs4350_mute_info,
56898 + .get = ubi32_cs4350_mute_get,
56899 + .put = ubi32_cs4350_mute_put,
56903 + * snd_ubi32_cs4350_free
56904 + * Card private data free function
56906 +void snd_ubi32_cs4350_free(struct snd_card *card)
56908 + struct ubi32_snd_priv *ubi32_priv;
56909 + struct ubi32_cs4350_priv *cs4350_priv;
56911 + ubi32_priv = card->private_data;
56912 + cs4350_priv = snd_ubi32_priv_get_drv(ubi32_priv);
56913 + if (cs4350_priv) {
56914 + kfree(cs4350_priv);
56919 + * snd_ubi32_cs4350_dac_init
56921 +static int snd_ubi32_cs4350_dac_init(struct i2c_client *client, const struct i2c_device_id *id)
56928 + * Initialize the CS4350 DAC over the I2C interface
56930 + snd_printk(KERN_INFO "Initializing CS4350 DAC\n");
56933 + * Register 0x01: device/revid
56936 + ret = i2c_master_send(client, send, 1);
56938 + snd_printk(KERN_ERR "Failed 1st attempt to write to CS4350 register 0x01\n");
56941 + ret = i2c_master_recv(client, recv, 1);
56943 + snd_printk(KERN_ERR "Failed initial read of CS4350 registers\n");
56946 + snd_printk(KERN_INFO "CS4350 DAC Device/Rev: %08x\n", recv[0]);
56949 + * Register 0x02: Mode control
56950 + * I2S DIF[2:0] = 001, no De-Emphasis, Auto speed mode
56954 + ret = i2c_master_send(client, send, 2);
56956 + snd_printk(KERN_ERR "Failed to set CS4350 to I2S mode\n");
56961 + * Register 0x05/0x06: Volume control
56962 + * Channel A volume set to 0 dB
56963 + * Channel B volume set to 0 dB
56967 + ret = i2c_master_send(client, send, 2);
56969 + snd_printk(KERN_ERR "Failed to set channel A volume on CS4350\n");
56975 + ret = i2c_master_send(client, send, 2);
56977 + snd_printk(KERN_ERR "Failed to set channel A volume on CS4350\n");
56982 + * Make sure the changes took place, this helps verify we are talking to
56983 + * the correct chip.
56986 + ret = i2c_master_send(client, send, 1);
56988 + snd_printk(KERN_ERR "Failed to initiate readback\n");
56992 + ret = i2c_master_recv(client, recv, 8);
56994 + snd_printk(KERN_ERR "Failed second read of CS4350 registers\n");
56998 + if ((recv[1] != 0x10) || (recv[4] != 0x00) || (recv[5] != 0x00)) {
56999 + snd_printk(KERN_ERR "Failed to initialize CS4350 DAC\n");
57003 + snd_printk(KERN_INFO "CS4350 DAC Initialized\n");
57011 + * snd_ubi32_cs4350_i2c_probe
57013 +static int snd_ubi32_cs4350_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
57015 + struct snd_card *card;
57016 + struct ubi32_snd_priv *ubi32_priv;
57017 + struct ubi32_cs4350_priv *cs4350_priv;
57019 + struct platform_device *pdev;
57021 + pdev = client->dev.platform_data;
57027 + * Initialize the CS4350 DAC
57029 + ret = snd_ubi32_cs4350_dac_init(client, id);
57032 + * Initialization failed. Propagate the error.
57038 + * Create a snd_card structure
57040 + card = snd_card_new(index, "Ubi32-CS4350", THIS_MODULE, sizeof(struct ubi32_snd_priv));
57041 + if (card == NULL) {
57045 + card->private_free = snd_ubi32_cs4350_free; /* Not sure if correct */
57046 + ubi32_priv = card->private_data;
57049 + * CS4350 DAC has a minimum sample rate of 30khz and an
57050 + * upper limit of 216khz for it's auto-detect.
57052 + ubi32_priv->min_sample_rate = 30000;
57053 + ubi32_priv->max_sample_rate = 216000;
57056 + * Initialize the snd_card's private data structure
57058 + ubi32_priv->card = card;
57059 + ubi32_priv->client = client;
57062 + * Create our private data structure
57064 + cs4350_priv = kzalloc(sizeof(struct ubi32_cs4350_priv), GFP_KERNEL);
57065 + if (!cs4350_priv) {
57066 + snd_card_free(card);
57069 + snd_ubi32_priv_set_drv(ubi32_priv, cs4350_priv);
57070 + spin_lock_init(&cs4350_priv->lock);
57073 + * Initial volume is set to max by probe function
57075 + cs4350_priv->volume[0] = 0xFF;
57076 + cs4350_priv->volume[1] = 0xFF;
57079 + * The CS4350 starts off unmuted (bit set = not muted)
57081 + cs4350_priv->mute = 3;
57084 + * Create the new PCM instance
57086 + err = snd_ubi32_pcm_probe(ubi32_priv, pdev);
57088 + snd_card_free(card);
57089 + return err; /* What is err? Need to include correct file */
57092 + strcpy(card->driver, "Ubi32-CS4350");
57093 + strcpy(card->shortname, "Ubi32-CS4350");
57094 + snprintf(card->longname, sizeof(card->longname),
57095 + "%s at sendirq=%d.%d recvirq=%d.%d regs=%p",
57096 + card->shortname, ubi32_priv->tx_irq, ubi32_priv->irq_idx,
57097 + ubi32_priv->rx_irq, ubi32_priv->irq_idx, ubi32_priv->adr);
57099 + snd_card_set_dev(card, &client->dev);
57102 + * Set up the mixer components
57104 + err = snd_ctl_add(card, snd_ctl_new1(&ubi32_cs4350_volume, ubi32_priv));
57106 + snd_printk(KERN_WARNING "Failed to add volume mixer control\n");
57108 + err = snd_ctl_add(card, snd_ctl_new1(&ubi32_cs4350_mute, ubi32_priv));
57110 + snd_printk(KERN_WARNING "Failed to add mute mixer control\n");
57114 + * Register the sound card
57116 + if ((err = snd_card_register(card)) != 0) {
57117 + snd_printk(KERN_WARNING "snd_card_register error\n");
57121 + * Store card for access from other methods
57123 + i2c_set_clientdata(client, card);
57129 + * snd_ubi32_cs4350_i2c_remove
57131 +static int __devexit snd_ubi32_cs4350_i2c_remove(struct i2c_client *client)
57133 + struct snd_card *card;
57134 + struct ubi32_snd_priv *ubi32_priv;
57136 + card = i2c_get_clientdata(client);
57138 + ubi32_priv = card->private_data;
57139 + snd_ubi32_pcm_remove(ubi32_priv);
57141 + snd_card_free(i2c_get_clientdata(client));
57142 + i2c_set_clientdata(client, NULL);
57148 + * I2C driver description
57150 +static struct i2c_driver snd_ubi32_cs4350_driver = {
57152 + .name = DRIVER_NAME,
57153 + .owner = THIS_MODULE,
57155 + .id_table = snd_ubi32_cs4350_id,
57156 + .probe = snd_ubi32_cs4350_i2c_probe,
57157 + .remove = __devexit_p(snd_ubi32_cs4350_i2c_remove),
57163 +static int __init snd_ubi32_cs4350_init(void)
57165 + return i2c_add_driver(&snd_ubi32_cs4350_driver);
57167 +module_init(snd_ubi32_cs4350_init);
57170 + * snd_ubi32_cs4350_exit
57172 +static void __exit snd_ubi32_cs4350_exit(void)
57174 + i2c_del_driver(&snd_ubi32_cs4350_driver);
57176 +module_exit(snd_ubi32_cs4350_exit);
57179 + * Module properties
57181 +MODULE_ALIAS("i2c:" DRIVER_NAME);
57182 +MODULE_AUTHOR("Patrick Tjin");
57183 +MODULE_DESCRIPTION("Driver for Ubicom32 audio devices CS4350");
57184 +MODULE_LICENSE("GPL");
57185 diff -ruN linux-2.6.30.10/sound/ubicom32/ubi32-cs4384.c linux-2.6.30.10-ubi/sound/ubicom32/ubi32-cs4384.c
57186 --- linux-2.6.30.10/sound/ubicom32/ubi32-cs4384.c 1970-01-01 02:00:00.000000000 +0200
57187 +++ linux-2.6.30.10-ubi/sound/ubicom32/ubi32-cs4384.c 2009-12-11 11:45:25.000000000 +0200
57190 + * sound/ubicom32/ubi32-cs4384.c
57191 + * Interface to ubicom32 virtual audio peripheral - using CS4384 DAC
57193 + * (C) Copyright 2009, Ubicom, Inc.
57195 + * This file is part of the Ubicom32 Linux Kernel Port.
57197 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
57198 + * it and/or modify it under the terms of the GNU General Public License
57199 + * as published by the Free Software Foundation, either version 2 of the
57200 + * License, or (at your option) any later version.
57202 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
57203 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
57204 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
57205 + * the GNU General Public License for more details.
57207 + * You should have received a copy of the GNU General Public License
57208 + * along with the Ubicom32 Linux Kernel Port. If not,
57209 + * see <http://www.gnu.org/licenses/>.
57212 +#include <linux/i2c.h>
57213 +#include <linux/module.h>
57214 +#include <linux/moduleparam.h>
57215 +#include <linux/delay.h>
57216 +#include <sound/core.h>
57217 +#include <sound/tlv.h>
57218 +#include <sound/control.h>
57219 +#include <sound/pcm.h>
57220 +#include <sound/initval.h>
57221 +#include <asm/ip5000.h>
57222 +#include <asm/gpio.h>
57223 +#include <asm/audio.h>
57224 +#include <asm/ubi32-cs4384.h>
57225 +#include "ubi32.h"
57227 +#define DRIVER_NAME "snd-ubi32-cs4384"
57230 + * Module properties
57232 +static const struct i2c_device_id snd_ubi32_cs4384_id[] = {
57236 +MODULE_DEVICE_TABLE(i2c, ubicom32audio_id);
57238 +static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */
57241 + * Mixer properties
57245 + * Be careful of changing the order of these IDs, they
57246 + * are used to index the volume array.
57248 + SND_UBI32_CS4384_FRONT_ID,
57249 + SND_UBI32_CS4384_SURROUND_ID,
57250 + SND_UBI32_CS4384_CENTER_ID,
57251 + SND_UBI32_CS4384_LFE_ID,
57252 + SND_UBI32_CS4384_REAR_ID,
57255 + * This should be the last ID
57257 + SND_UBI32_CS4384_LAST_ID,
57259 +static const u8_t snd_ubi32_cs4384_ch_ofs[] = {0, 2, 4, 5, 6};
57261 +static const DECLARE_TLV_DB_SCALE(snd_ubi32_cs4384_db, -12750, 50, 0);
57263 +#define snd_ubi32_cs4384_info_mute snd_ctl_boolean_stereo_info
57264 +#define snd_ubi32_cs4384_info_mute_mono snd_ctl_boolean_mono_info
57269 +static int snd_ubi32_cs4384_info_volume(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo);
57270 +static int snd_ubi32_cs4384_get_volume(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
57271 +static int snd_ubi32_cs4384_put_volume(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
57272 +static int snd_ubi32_cs4384_get_mute(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
57273 +static int snd_ubi32_cs4384_put_mute(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
57276 + * Make sure to update these if the structure below is changed
57278 +#define SND_UBI32_MUTE_CTL_START 5
57279 +#define SND_UBI32_MUTE_CTL_END 9
57280 +static struct snd_kcontrol_new snd_ubi32_cs4384_controls[] __devinitdata = {
57282 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
57283 + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
57284 + SNDRV_CTL_ELEM_ACCESS_TLV_READ,
57285 + .name = "Front Playback Volume",
57286 + .info = snd_ubi32_cs4384_info_volume,
57287 + .get = snd_ubi32_cs4384_get_volume,
57288 + .put = snd_ubi32_cs4384_put_volume,
57289 + .private_value = SND_UBI32_CS4384_FRONT_ID,
57291 + .p = snd_ubi32_cs4384_db,
57295 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
57296 + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
57297 + SNDRV_CTL_ELEM_ACCESS_TLV_READ,
57298 + .name = "Surround Playback Volume",
57299 + .info = snd_ubi32_cs4384_info_volume,
57300 + .get = snd_ubi32_cs4384_get_volume,
57301 + .put = snd_ubi32_cs4384_put_volume,
57302 + .private_value = SND_UBI32_CS4384_SURROUND_ID,
57304 + .p = snd_ubi32_cs4384_db,
57308 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
57309 + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
57310 + SNDRV_CTL_ELEM_ACCESS_TLV_READ,
57311 + .name = "Center Playback Volume",
57312 + .info = snd_ubi32_cs4384_info_volume,
57313 + .get = snd_ubi32_cs4384_get_volume,
57314 + .put = snd_ubi32_cs4384_put_volume,
57315 + .private_value = SND_UBI32_CS4384_CENTER_ID,
57317 + .p = snd_ubi32_cs4384_db,
57321 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
57322 + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
57323 + SNDRV_CTL_ELEM_ACCESS_TLV_READ,
57324 + .name = "LFE Playback Volume",
57325 + .info = snd_ubi32_cs4384_info_volume,
57326 + .get = snd_ubi32_cs4384_get_volume,
57327 + .put = snd_ubi32_cs4384_put_volume,
57328 + .private_value = SND_UBI32_CS4384_LFE_ID,
57330 + .p = snd_ubi32_cs4384_db,
57334 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
57335 + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
57336 + SNDRV_CTL_ELEM_ACCESS_TLV_READ,
57337 + .name = "Rear Playback Volume",
57338 + .info = snd_ubi32_cs4384_info_volume,
57339 + .get = snd_ubi32_cs4384_get_volume,
57340 + .put = snd_ubi32_cs4384_put_volume,
57341 + .private_value = SND_UBI32_CS4384_REAR_ID,
57343 + .p = snd_ubi32_cs4384_db,
57347 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
57348 + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
57349 + SNDRV_CTL_ELEM_ACCESS_TLV_READ,
57350 + .name = "Front Playback Switch",
57351 + .info = snd_ubi32_cs4384_info_mute,
57352 + .get = snd_ubi32_cs4384_get_mute,
57353 + .put = snd_ubi32_cs4384_put_mute,
57354 + .private_value = SND_UBI32_CS4384_FRONT_ID,
57357 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
57358 + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
57359 + SNDRV_CTL_ELEM_ACCESS_TLV_READ,
57360 + .name = "Surround Playback Switch",
57361 + .info = snd_ubi32_cs4384_info_mute,
57362 + .get = snd_ubi32_cs4384_get_mute,
57363 + .put = snd_ubi32_cs4384_put_mute,
57364 + .private_value = SND_UBI32_CS4384_SURROUND_ID,
57367 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
57368 + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
57369 + SNDRV_CTL_ELEM_ACCESS_TLV_READ,
57370 + .name = "Center Playback Switch",
57371 + .info = snd_ubi32_cs4384_info_mute_mono,
57372 + .get = snd_ubi32_cs4384_get_mute,
57373 + .put = snd_ubi32_cs4384_put_mute,
57374 + .private_value = SND_UBI32_CS4384_CENTER_ID,
57377 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
57378 + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
57379 + SNDRV_CTL_ELEM_ACCESS_TLV_READ,
57380 + .name = "LFE Playback Switch",
57381 + .info = snd_ubi32_cs4384_info_mute_mono,
57382 + .get = snd_ubi32_cs4384_get_mute,
57383 + .put = snd_ubi32_cs4384_put_mute,
57384 + .private_value = SND_UBI32_CS4384_LFE_ID,
57387 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
57388 + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
57389 + SNDRV_CTL_ELEM_ACCESS_TLV_READ,
57390 + .name = "Rear Playback Switch",
57391 + .info = snd_ubi32_cs4384_info_mute,
57392 + .get = snd_ubi32_cs4384_get_mute,
57393 + .put = snd_ubi32_cs4384_put_mute,
57394 + .private_value = SND_UBI32_CS4384_REAR_ID,
57399 + * Our private data
57401 +struct snd_ubi32_cs4384_priv {
57403 + * Array of current volumes
57404 + * (L, R, SL, SR, C, LFE, RL, RR)
57406 + uint8_t volume[8];
57409 + * Bitmask of mutes
57410 + * MSB (RR, RL, LFE, C, SR, SL, R, L) LSB
57415 + * Array of controls
57417 + struct snd_kcontrol *kctls[ARRAY_SIZE(snd_ubi32_cs4384_controls)];
57420 + * Lock to protect our card
57426 + * snd_ubi32_cs4384_info_volume
57428 +static int snd_ubi32_cs4384_info_volume(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
57430 + unsigned int id = (unsigned int)kcontrol->private_value;
57432 + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
57433 + uinfo->count = 1;
57434 + if ((id != SND_UBI32_CS4384_LFE_ID) &&
57435 + (id != SND_UBI32_CS4384_CENTER_ID)) {
57436 + uinfo->count = 2;
57438 + uinfo->value.integer.min = 0;
57439 + uinfo->value.integer.max = 255;
57444 + * snd_ubi32_cs4384_get_volume
57446 +static int snd_ubi32_cs4384_get_volume(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
57448 + struct ubi32_snd_priv *priv = snd_kcontrol_chip(kcontrol);
57449 + struct snd_ubi32_cs4384_priv *cs4384_priv;
57450 + unsigned int id = (unsigned int)kcontrol->private_value;
57451 + int ch = snd_ubi32_cs4384_ch_ofs[id];
57452 + unsigned long flags;
57454 + if (id >= SND_UBI32_CS4384_LAST_ID) {
57458 + cs4384_priv = snd_ubi32_priv_get_drv(priv);
57460 + spin_lock_irqsave(&cs4384_priv->lock, flags);
57462 + ucontrol->value.integer.value[0] = cs4384_priv->volume[ch];
57463 + if ((id != SND_UBI32_CS4384_LFE_ID) &&
57464 + (id != SND_UBI32_CS4384_CENTER_ID)) {
57466 + ucontrol->value.integer.value[1] = cs4384_priv->volume[ch];
57469 + spin_unlock_irqrestore(&cs4384_priv->lock, flags);
57475 + * snd_ubi32_cs4384_put_volume
57477 +static int snd_ubi32_cs4384_put_volume(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
57479 + struct ubi32_snd_priv *priv = snd_kcontrol_chip(kcontrol);
57480 + struct i2c_client *client = (struct i2c_client *)priv->client;
57481 + struct snd_ubi32_cs4384_priv *cs4384_priv;
57482 + unsigned int id = (unsigned int)kcontrol->private_value;
57483 + int ch = snd_ubi32_cs4384_ch_ofs[id];
57484 + unsigned long flags;
57485 + unsigned char send[3];
57487 + int ret = -EINVAL;
57489 + if (id >= SND_UBI32_CS4384_LAST_ID) {
57493 + cs4384_priv = snd_ubi32_priv_get_drv(priv);
57495 + spin_lock_irqsave(&cs4384_priv->lock, flags);
57499 + case SND_UBI32_CS4384_REAR_ID:
57506 + case SND_UBI32_CS4384_SURROUND_ID:
57513 + case SND_UBI32_CS4384_FRONT_ID:
57516 + send[1] = 255 - (ucontrol->value.integer.value[0] & 0xFF);
57517 + send[2] = 255 - (ucontrol->value.integer.value[1] & 0xFF);
57518 + cs4384_priv->volume[ch++] = send[1];
57519 + cs4384_priv->volume[ch] = send[2];
57522 + case SND_UBI32_CS4384_LFE_ID:
57529 + case SND_UBI32_CS4384_CENTER_ID:
57532 + send[1] = 255 - (ucontrol->value.integer.value[0] & 0xFF);
57533 + cs4384_priv->volume[ch] = send[1];
57537 + spin_unlock_irqrestore(&cs4384_priv->lock, flags);
57543 + * Send the volume to the chip
57546 + ret = i2c_master_send(client, send, nch);
57547 + if (ret != nch) {
57548 + snd_printk(KERN_ERR "Failed to set volume on CS4384\n");
57552 + spin_unlock_irqrestore(&cs4384_priv->lock, flags);
57558 + * snd_ubi32_cs4384_get_mute
57560 +static int snd_ubi32_cs4384_get_mute(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
57562 + struct ubi32_snd_priv *priv = snd_kcontrol_chip(kcontrol);
57563 + struct snd_ubi32_cs4384_priv *cs4384_priv;
57564 + unsigned int id = (unsigned int)kcontrol->private_value;
57565 + int ch = snd_ubi32_cs4384_ch_ofs[id];
57566 + unsigned long flags;
57568 + if (id >= SND_UBI32_CS4384_LAST_ID) {
57572 + cs4384_priv = snd_ubi32_priv_get_drv(priv);
57574 + spin_lock_irqsave(&cs4384_priv->lock, flags);
57576 + ucontrol->value.integer.value[0] = !(cs4384_priv->mute & (1 << ch));
57578 + if ((id != SND_UBI32_CS4384_LFE_ID) &&
57579 + (id != SND_UBI32_CS4384_CENTER_ID)) {
57581 + ucontrol->value.integer.value[1] = !(cs4384_priv->mute & (1 << ch));
57584 + spin_unlock_irqrestore(&cs4384_priv->lock, flags);
57590 + * snd_ubi32_cs4384_put_mute
57592 +static int snd_ubi32_cs4384_put_mute(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
57594 + struct ubi32_snd_priv *priv = snd_kcontrol_chip(kcontrol);
57595 + struct i2c_client *client = (struct i2c_client *)priv->client;
57596 + struct snd_ubi32_cs4384_priv *cs4384_priv;
57597 + unsigned int id = (unsigned int)kcontrol->private_value;
57598 + int ch = snd_ubi32_cs4384_ch_ofs[id];
57599 + unsigned long flags;
57600 + unsigned char send[2];
57601 + int ret = -EINVAL;
57603 + if (id >= SND_UBI32_CS4384_LAST_ID) {
57607 + cs4384_priv = snd_ubi32_priv_get_drv(priv);
57609 + spin_lock_irqsave(&cs4384_priv->lock, flags);
57611 + if (ucontrol->value.integer.value[0]) {
57612 + cs4384_priv->mute &= ~(1 << ch);
57614 + cs4384_priv->mute |= (1 << ch);
57617 + if ((id != SND_UBI32_CS4384_LFE_ID) && (id != SND_UBI32_CS4384_CENTER_ID)) {
57619 + if (ucontrol->value.integer.value[1]) {
57620 + cs4384_priv->mute &= ~(1 << ch);
57622 + cs4384_priv->mute |= (1 << ch);
57627 + * Update the chip's mute reigster
57630 + send[1] = cs4384_priv->mute;
57631 + ret = i2c_master_send(client, send, 2);
57633 + snd_printk(KERN_ERR "Failed to set mute on CS4384\n");
57636 + spin_unlock_irqrestore(&cs4384_priv->lock, flags);
57642 + * snd_ubi32_cs4384_mixer
57643 + * Setup the mixer controls
57645 +static int __devinit snd_ubi32_cs4384_mixer(struct ubi32_snd_priv *priv)
57647 + struct snd_card *card = priv->card;
57648 + struct snd_ubi32_cs4384_priv *cs4384_priv;
57651 + cs4384_priv = snd_ubi32_priv_get_drv(priv);
57652 + for (i = 0; i < ARRAY_SIZE(snd_ubi32_cs4384_controls); i++) {
57655 + cs4384_priv->kctls[i] = snd_ctl_new1(&snd_ubi32_cs4384_controls[i], priv);
57656 + err = snd_ctl_add(card, cs4384_priv->kctls[i]);
57658 + snd_printk(KERN_WARNING "Failed to add control %d\n", i);
57666 + * snd_ubi32_cs4384_free
57667 + * Card private data free function
57669 +void snd_ubi32_cs4384_free(struct snd_card *card)
57671 + struct snd_ubi32_cs4384_priv *cs4384_priv;
57672 + struct ubi32_snd_priv *ubi32_priv;
57674 + ubi32_priv = card->private_data;
57675 + cs4384_priv = snd_ubi32_priv_get_drv(ubi32_priv);
57676 + if (cs4384_priv) {
57677 + kfree(cs4384_priv);
57682 + * snd_ubi32_cs4384_setup_mclk
57684 +static int snd_ubi32_cs4384_setup_mclk(struct ubi32_cs4384_platform_data *pdata)
57686 + struct ubicom32_io_port *ioa = (struct ubicom32_io_port *)RA;
57687 + struct ubicom32_io_port *ioc = (struct ubicom32_io_port *)RC;
57688 + struct ubicom32_io_port *iod = (struct ubicom32_io_port *)RD;
57689 + struct ubicom32_io_port *ioe = (struct ubicom32_io_port *)RE;
57690 + struct ubicom32_io_port *ioh = (struct ubicom32_io_port *)RH;
57691 + unsigned int ctl0;
57692 + unsigned int ctlx;
57693 + unsigned int div;
57695 + div = pdata->mclk_entries[0].div;
57697 + ctl0 = (1 << 13);
57698 + ctlx = ((div - 1) << 16) | (div / 2);
57700 + switch (pdata->mclk_src) {
57701 + case UBI32_CS4384_MCLK_PWM_0:
57702 + ioc->function |= 2;
57703 + ioc->ctl0 |= ctl0;
57704 + ioc->ctl1 = ctlx;
57705 + if (!ioa->function) {
57706 + ioa->function = 3;
57710 + case UBI32_CS4384_MCLK_PWM_1:
57711 + ioc->function |= 2;
57712 + ioc->ctl0 |= ctl0 << 16;
57713 + ioc->ctl2 = ctlx;
57714 + if (!ioe->function) {
57715 + ioe->function = 3;
57719 + case UBI32_CS4384_MCLK_PWM_2:
57720 + ioh->ctl0 |= ctl0;
57721 + ioh->ctl1 = ctlx;
57722 + if (!iod->function) {
57723 + iod->function = 3;
57727 + case UBI32_CS4384_MCLK_CLKDIV_1:
57728 + ioa->gpio_mask &= (1 << 7);
57729 + ioa->ctl1 &= ~(0x7F << 14);
57730 + ioa->ctl1 |= ((div - 1) << 14);
57733 + case UBI32_CS4384_MCLK_OTHER:
57741 + * snd_ubi32_cs4384_set_rate
57743 +static int snd_ubi32_cs4384_set_rate(struct ubi32_snd_priv *priv, int rate)
57745 + struct ubi32_cs4384_platform_data *cpd = priv->pdata->priv_data;
57746 + struct ubicom32_io_port *ioa = (struct ubicom32_io_port *)RA;
57747 + struct ubicom32_io_port *ioc = (struct ubicom32_io_port *)RC;
57748 + struct ubicom32_io_port *ioh = (struct ubicom32_io_port *)RH;
57749 + unsigned int ctl;
57750 + unsigned int div = 0;
57751 + const u16_t mult[] = {64, 96, 128, 192, 256, 384, 512, 768, 1024};
57756 + for (i = 0; i < sizeof(mult) / sizeof(u16_t); i++) {
57757 + for (j = 0; j < cpd->n_mclk; j++) {
57758 + if (((unsigned int)rate * (unsigned int)mult[i]) ==
57759 + cpd->mclk_entries[j].rate) {
57760 + div = cpd->mclk_entries[j].div;
57766 + ctl = ((div - 1) << 16) | (div / 2);
57768 + switch (cpd->mclk_src) {
57769 + case UBI32_CS4384_MCLK_PWM_0:
57773 + case UBI32_CS4384_MCLK_PWM_1:
57777 + case UBI32_CS4384_MCLK_PWM_2:
57781 + case UBI32_CS4384_MCLK_CLKDIV_1:
57782 + ioa->ctl1 &= ~(0x7F << 14);
57783 + ioa->ctl1 |= ((div - 1) << 14);
57786 + case UBI32_CS4384_MCLK_OTHER:
57794 + * snd_ubi32_cs4384_set_channels
57795 + * Mute unused channels
57797 +static int snd_ubi32_cs4384_set_channels(struct ubi32_snd_priv *priv, int channels)
57799 + struct i2c_client *client = (struct i2c_client *)priv->client;
57800 + struct snd_ubi32_cs4384_priv *cs4384_priv;
57801 + unsigned char send[2];
57804 + unsigned long flags;
57807 + * Only support 0, 2, 4, 6, 8 channels
57809 + if ((channels > 8) || (channels & 1)) {
57813 + cs4384_priv = snd_ubi32_priv_get_drv(priv);
57814 + spin_lock_irqsave(&cs4384_priv->lock, flags);
57817 + * Address 09h, Mute control
57820 + send[1] = (unsigned char)(0xFF << channels);
57822 + ret = i2c_master_send(client, send, 2);
57824 + spin_unlock_irqrestore(&cs4384_priv->lock, flags);
57827 + * Notify the system that we changed the mutes
57829 + cs4384_priv->mute = (unsigned char)(0xFF << channels);
57831 + for (i = SND_UBI32_MUTE_CTL_START; i < SND_UBI32_MUTE_CTL_END; i++) {
57832 + snd_ctl_notify(priv->card, SNDRV_CTL_EVENT_MASK_VALUE,
57833 + &cs4384_priv->kctls[i]->id);
57844 + * snd_ubi32_cs4384_dac_init
57846 +static int snd_ubi32_cs4384_dac_init(struct i2c_client *client, const struct i2c_device_id *id)
57849 + unsigned char send[2];
57850 + unsigned char recv[2];
57853 + * Initialize the CS4384 DAC over the I2C interface
57855 + snd_printk(KERN_INFO "Initializing CS4384 DAC\n");
57858 + * Register 0x01: device/revid
57861 + ret = i2c_master_send(client, send, 1);
57863 + snd_printk(KERN_ERR "Failed 1st attempt to write to CS4384 register 0x01\n");
57866 + ret = i2c_master_recv(client, recv, 1);
57868 + snd_printk(KERN_ERR "Failed initial read of CS4384 registers\n");
57871 + snd_printk(KERN_INFO "CS4384 DAC Device/Rev: %08x\n", recv[0]);
57874 + * Register 0x02: Mode Control 1
57875 + * Control Port Enable, PCM, All DACs enabled, Power Down
57879 + ret = i2c_master_send(client, send, 2);
57881 + snd_printk(KERN_ERR "Failed to set CPEN CS4384\n");
57886 + * Register 0x08: Ramp and Mute
57887 + * RMP_UP, RMP_DN, PAMUTE, DAMUTE
57891 + ret = i2c_master_send(client, send, 2);
57893 + snd_printk(KERN_ERR "Failed to set CPEN CS4384\n");
57898 + * Register 0x03: PCM Control
57899 + * I2S DIF[3:0] = 0001, no De-Emphasis, Auto speed mode
57903 + ret = i2c_master_send(client, send, 2);
57905 + snd_printk(KERN_ERR "Failed to set CS4384 to I2S mode\n");
57910 + * Register 0x0B/0x0C: Volume control A1/B1
57911 + * Register 0x0E/0x0F: Volume control A2/B2
57912 + * Register 0x11/0x12: Volume control A3/B3
57913 + * Register 0x14/0x15: Volume control A4/B4
57915 + send[0] = 0x80 | 0x0B;
57918 + ret = i2c_master_send(client, send, 3);
57920 + snd_printk(KERN_ERR "Failed to set ch1 volume on CS4384\n");
57924 + send[0] = 0x80 | 0x0E;
57927 + ret = i2c_master_send(client, send, 3);
57929 + snd_printk(KERN_ERR "Failed to set ch2 volume on CS4384\n");
57933 + send[0] = 0x80 | 0x11;
57936 + ret = i2c_master_send(client, send, 3);
57938 + snd_printk(KERN_ERR "Failed to set ch3 volume on CS4384\n");
57942 + send[0] = 0x80 | 0x14;
57945 + ret = i2c_master_send(client, send, 3);
57947 + snd_printk(KERN_ERR "Failed to set ch4 volume on CS4384\n");
57952 + * Register 09h: Mute control
57953 + * Mute all (we will unmute channels as needed)
57957 + ret = i2c_master_send(client, send, 2);
57959 + snd_printk(KERN_ERR "Failed to power up CS4384\n");
57964 + * Register 0x02: Mode Control 1
57965 + * Control Port Enable, PCM, All DACs enabled, Power Up
57969 + ret = i2c_master_send(client, send, 2);
57971 + snd_printk(KERN_ERR "Failed to power up CS4384\n");
57976 + * Make sure the changes took place, this helps verify we are talking to
57977 + * the correct chip.
57979 + send[0] = 0x80 | 0x03;
57980 + ret = i2c_master_send(client, send, 1);
57982 + snd_printk(KERN_ERR "Failed to initiate readback\n");
57986 + ret = i2c_master_recv(client, recv, 1);
57988 + snd_printk(KERN_ERR "Failed second read of CS4384 registers\n");
57992 + if (recv[0] != 0x13) {
57993 + snd_printk(KERN_ERR "Failed to initialize CS4384 DAC\n");
57997 + snd_printk(KERN_INFO "CS4384 DAC Initialized\n");
58005 + * snd_ubi32_cs4384_i2c_probe
58007 +static int snd_ubi32_cs4384_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
58009 + struct snd_card *card;
58010 + struct ubi32_snd_priv *ubi32_priv;
58012 + struct platform_device *pdev;
58013 + struct ubi32_cs4384_platform_data *pdata;
58014 + struct snd_ubi32_cs4384_priv *cs4384_priv;
58017 + * pdev is audio device
58019 + pdev = client->dev.platform_data;
58025 + * pdev->dev.platform_data is ubi32-pcm platform_data
58027 + pdata = audio_device_priv(pdev);
58033 + * Initialize the CS4384 DAC
58035 + ret = snd_ubi32_cs4384_dac_init(client, id);
58038 + * Initialization failed. Propagate the error.
58043 + if (snd_ubi32_cs4384_setup_mclk(pdata)) {
58048 + * Create a snd_card structure
58050 + card = snd_card_new(index, "Ubi32-CS4384", THIS_MODULE, sizeof(struct ubi32_snd_priv));
58051 + if (card == NULL) {
58055 + card->private_free = snd_ubi32_cs4384_free;
58056 + ubi32_priv = card->private_data;
58059 + * Initialize the snd_card's private data structure
58061 + ubi32_priv->card = card;
58062 + ubi32_priv->client = client;
58063 + ubi32_priv->set_channels = snd_ubi32_cs4384_set_channels;
58064 + ubi32_priv->set_rate = snd_ubi32_cs4384_set_rate;
58067 + * CS4384 DAC has a minimum sample rate of 4khz and an
58068 + * upper limit of 216khz for it's auto-detect.
58070 + ubi32_priv->min_sample_rate = 4000;
58071 + ubi32_priv->max_sample_rate = 216000;
58074 + * Create our private data (to manage volume, etc)
58076 + cs4384_priv = kzalloc(sizeof(struct snd_ubi32_cs4384_priv), GFP_KERNEL);
58077 + if (!cs4384_priv) {
58078 + snd_card_free(card);
58081 + snd_ubi32_priv_set_drv(ubi32_priv, cs4384_priv);
58082 + spin_lock_init(&cs4384_priv->lock);
58085 + * We start off all muted and max volume
58087 + cs4384_priv->mute = 0xFF;
58088 + memset(cs4384_priv->volume, 0xFF, 8);
58091 + * Create the new PCM instance
58093 + err = snd_ubi32_pcm_probe(ubi32_priv, pdev);
58095 + snd_card_free(card);
58096 + return err; /* What is err? Need to include correct file */
58099 + strcpy(card->driver, "Ubi32-CS4384");
58100 + strcpy(card->shortname, "Ubi32-CS4384");
58101 + snprintf(card->longname, sizeof(card->longname),
58102 + "%s at sendirq=%d.%d recvirq=%d.%d regs=%p",
58103 + card->shortname, ubi32_priv->tx_irq, ubi32_priv->irq_idx,
58104 + ubi32_priv->rx_irq, ubi32_priv->irq_idx, ubi32_priv->adr);
58106 + snd_card_set_dev(card, &client->dev);
58109 + * Set up the mixer
58111 + snd_ubi32_cs4384_mixer(ubi32_priv);
58114 + * Register the sound card
58116 + if ((err = snd_card_register(card)) != 0) {
58117 + snd_printk(KERN_INFO "snd_card_register error\n");
58121 + * Store card for access from other methods
58123 + i2c_set_clientdata(client, card);
58129 + * snd_ubi32_cs4384_i2c_remove
58131 +static int __devexit snd_ubi32_cs4384_i2c_remove(struct i2c_client *client)
58133 + struct snd_card *card;
58134 + struct ubi32_snd_priv *ubi32_priv;
58136 + card = i2c_get_clientdata(client);
58138 + ubi32_priv = card->private_data;
58139 + snd_ubi32_pcm_remove(ubi32_priv);
58141 + snd_card_free(i2c_get_clientdata(client));
58142 + i2c_set_clientdata(client, NULL);
58148 + * I2C driver description
58150 +static struct i2c_driver snd_ubi32_cs4384_driver = {
58152 + .name = DRIVER_NAME,
58153 + .owner = THIS_MODULE,
58155 + .id_table = snd_ubi32_cs4384_id,
58156 + .probe = snd_ubi32_cs4384_i2c_probe,
58157 + .remove = __devexit_p(snd_ubi32_cs4384_i2c_remove),
58163 +static int __init snd_ubi32_cs4384_init(void)
58165 + return i2c_add_driver(&snd_ubi32_cs4384_driver);
58167 +module_init(snd_ubi32_cs4384_init);
58170 + * snd_ubi32_cs4384_exit
58172 +static void __exit snd_ubi32_cs4384_exit(void)
58174 + i2c_del_driver(&snd_ubi32_cs4384_driver);
58176 +module_exit(snd_ubi32_cs4384_exit);
58179 + * Module properties
58181 +MODULE_ALIAS("i2c:" DRIVER_NAME);
58182 +MODULE_AUTHOR("Patrick Tjin");
58183 +MODULE_DESCRIPTION("Driver for Ubicom32 audio devices CS4384");
58184 +MODULE_LICENSE("GPL");
58185 diff -ruN linux-2.6.30.10/sound/ubicom32/ubi32-generic.c linux-2.6.30.10-ubi/sound/ubicom32/ubi32-generic.c
58186 --- linux-2.6.30.10/sound/ubicom32/ubi32-generic.c 1970-01-01 02:00:00.000000000 +0200
58187 +++ linux-2.6.30.10-ubi/sound/ubicom32/ubi32-generic.c 2009-12-11 11:45:25.000000000 +0200
58190 + * sound/ubicom32/ubi32-generic.c
58191 + * Interface to ubicom32 virtual audio peripheral
58193 + * (C) Copyright 2009, Ubicom, Inc.
58195 + * This file is part of the Ubicom32 Linux Kernel Port.
58197 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
58198 + * it and/or modify it under the terms of the GNU General Public License
58199 + * as published by the Free Software Foundation, either version 2 of the
58200 + * License, or (at your option) any later version.
58202 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
58203 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
58204 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
58205 + * the GNU General Public License for more details.
58207 + * You should have received a copy of the GNU General Public License
58208 + * along with the Ubicom32 Linux Kernel Port. If not,
58209 + * see <http://www.gnu.org/licenses/>.
58211 + * Ubicom32 implementation derived from (with many thanks):
58217 +#include <linux/platform_device.h>
58218 +#include <linux/module.h>
58219 +#include <linux/moduleparam.h>
58220 +#include <sound/core.h>
58221 +#include <sound/pcm.h>
58222 +#include <sound/initval.h>
58223 +#include "ubi32.h"
58225 +#define DRIVER_NAME "snd-ubi32-generic"
58228 + * Module properties
58230 +static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */
58233 + * Card private data free function
58235 +void snd_ubi32_generic_free(struct snd_card *card)
58238 + * Free all the fields in the snd_ubi32_priv struct
58240 + // Nothing to free at this time because ubi32_priv just maintains pointers
58244 + * Ubicom audio driver probe() method. Args change depending on whether we use
58245 + * platform_device or i2c_device.
58247 +static int snd_ubi32_generic_probe(struct platform_device *dev)
58249 + struct snd_card *card;
58250 + struct ubi32_snd_priv *ubi32_priv;
58254 + * Create a snd_card structure
58256 + card = snd_card_new(index, "Ubi32-Generic", THIS_MODULE, sizeof(struct ubi32_snd_priv));
58258 + if (card == NULL) {
58262 + card->private_free = snd_ubi32_generic_free; /* Not sure if correct */
58263 + ubi32_priv = card->private_data;
58266 + * Initialize the snd_card's private data structure
58268 + ubi32_priv->card = card;
58271 + * Create the new PCM instance
58273 + err = snd_ubi32_pcm_probe(ubi32_priv, dev);
58275 + snd_card_free(card);
58279 + strcpy(card->driver, "Ubi32-Generic");
58280 + strcpy(card->shortname, "Ubi32-Generic");
58281 + snprintf(card->longname, sizeof(card->longname),
58282 + "%s at sendirq=%d.%d recvirq=%d.%d regs=%p",
58283 + card->shortname, ubi32_priv->tx_irq, ubi32_priv->irq_idx,
58284 + ubi32_priv->rx_irq, ubi32_priv->irq_idx, ubi32_priv->adr);
58286 + snd_card_set_dev(card, &dev->dev);
58288 + /* Register the sound card */
58289 + if ((err = snd_card_register(card)) != 0) {
58290 + snd_printk(KERN_INFO "snd_card_register error\n");
58293 + /* Store card for access from other methods */
58294 + platform_set_drvdata(dev, card);
58300 + * Ubicom audio driver remove() method
58302 +static int __devexit snd_ubi32_generic_remove(struct platform_device *dev)
58304 + struct snd_card *card;
58305 + struct ubi32_snd_priv *ubi32_priv;
58307 + card = platform_get_drvdata(dev);
58308 + ubi32_priv = card->private_data;
58309 + snd_ubi32_pcm_remove(ubi32_priv);
58311 + snd_card_free(platform_get_drvdata(dev));
58312 + platform_set_drvdata(dev, NULL);
58317 + * Platform driver definition
58319 +static struct platform_driver snd_ubi32_generic_driver = {
58321 + .name = DRIVER_NAME,
58322 + .owner = THIS_MODULE,
58324 + .probe = snd_ubi32_generic_probe,
58325 + .remove = __devexit_p(snd_ubi32_generic_remove),
58329 + * snd_ubi32_generic_init
58331 +static int __init snd_ubi32_generic_init(void)
58333 + return platform_driver_register(&snd_ubi32_generic_driver);
58335 +module_init(snd_ubi32_generic_init);
58338 + * snd_ubi32_generic_exit
58340 +static void __exit snd_ubi32_generic_exit(void)
58342 + platform_driver_unregister(&snd_ubi32_generic_driver);
58344 +module_exit(snd_ubi32_generic_exit);
58347 + * Module properties
58349 +//#if defined(CONFIG_SND_UBI32_AUDIO_I2C)
58350 +//MODULE_ALIAS("i2c:snd-ubi32");
58352 +MODULE_AUTHOR("Aaron Jow, Patrick Tjin");
58353 +MODULE_DESCRIPTION("Driver for Ubicom32 audio devices");
58354 +MODULE_LICENSE("GPL");
58355 diff -ruN linux-2.6.30.10/sound/ubicom32/ubi32-generic-capture.c linux-2.6.30.10-ubi/sound/ubicom32/ubi32-generic-capture.c
58356 --- linux-2.6.30.10/sound/ubicom32/ubi32-generic-capture.c 1970-01-01 02:00:00.000000000 +0200
58357 +++ linux-2.6.30.10-ubi/sound/ubicom32/ubi32-generic-capture.c 2009-12-11 11:45:25.000000000 +0200
58360 + * sound/ubicom32/ubi32-generic-capture.c
58361 + * Interface to ubicom32 virtual audio peripheral
58363 + * (C) Copyright 2009, Ubicom, Inc.
58365 + * This file is part of the Ubicom32 Linux Kernel Port.
58367 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
58368 + * it and/or modify it under the terms of the GNU General Public License
58369 + * as published by the Free Software Foundation, either version 2 of the
58370 + * License, or (at your option) any later version.
58372 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
58373 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
58374 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
58375 + * the GNU General Public License for more details.
58377 + * You should have received a copy of the GNU General Public License
58378 + * along with the Ubicom32 Linux Kernel Port. If not,
58379 + * see <http://www.gnu.org/licenses/>.
58381 + * Ubicom32 implementation derived from (with many thanks):
58387 +#include <linux/platform_device.h>
58388 +#include <linux/module.h>
58389 +#include <linux/moduleparam.h>
58390 +#include <sound/core.h>
58391 +#include <sound/pcm.h>
58392 +#include <sound/initval.h>
58393 +#include "ubi32.h"
58395 +#define DRIVER_NAME "snd-ubi32-generic-capture"
58398 + * Module properties
58400 +static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */
58403 + * Card private data free function
58405 +void snd_ubi32_generic_capture_free(struct snd_card *card)
58408 + * Free all the fields in the snd_ubi32_priv struct
58410 + // Nothing to free at this time because ubi32_priv just maintains pointers
58414 + * Ubicom audio driver probe() method. Args change depending on whether we use
58415 + * platform_device or i2c_device.
58417 +static int snd_ubi32_generic_capture_probe(struct platform_device *dev)
58419 + struct snd_card *card;
58420 + struct ubi32_snd_priv *ubi32_priv;
58424 + * Create a snd_card structure
58426 + card = snd_card_new(index, "Ubi32-Generic-C", THIS_MODULE, sizeof(struct ubi32_snd_priv));
58428 + if (card == NULL) {
58432 + card->private_free = snd_ubi32_generic_capture_free; /* Not sure if correct */
58433 + ubi32_priv = card->private_data;
58436 + * Initialize the snd_card's private data structure
58438 + ubi32_priv->card = card;
58439 + ubi32_priv->is_capture = 1;
58442 + * Create the new PCM instance
58444 + err = snd_ubi32_pcm_probe(ubi32_priv, dev);
58446 + snd_card_free(card);
58450 + strcpy(card->driver, "Ubi32-Generic-C");
58451 + strcpy(card->shortname, "Ubi32-Generic-C");
58452 + snprintf(card->longname, sizeof(card->longname),
58453 + "%s at sendirq=%d.%d recvirq=%d.%d regs=%p",
58454 + card->shortname, ubi32_priv->tx_irq, ubi32_priv->irq_idx,
58455 + ubi32_priv->rx_irq, ubi32_priv->irq_idx, ubi32_priv->adr);
58457 + snd_card_set_dev(card, &dev->dev);
58459 + /* Register the sound card */
58460 + if ((err = snd_card_register(card)) != 0) {
58461 + snd_printk(KERN_INFO "snd_card_register error\n");
58464 + /* Store card for access from other methods */
58465 + platform_set_drvdata(dev, card);
58471 + * Ubicom audio driver remove() method
58473 +static int __devexit snd_ubi32_generic_capture_remove(struct platform_device *dev)
58475 + struct snd_card *card;
58476 + struct ubi32_snd_priv *ubi32_priv;
58478 + card = platform_get_drvdata(dev);
58479 + ubi32_priv = card->private_data;
58480 + snd_ubi32_pcm_remove(ubi32_priv);
58482 + snd_card_free(platform_get_drvdata(dev));
58483 + platform_set_drvdata(dev, NULL);
58488 + * Platform driver definition
58490 +static struct platform_driver snd_ubi32_generic_capture_driver = {
58492 + .name = DRIVER_NAME,
58493 + .owner = THIS_MODULE,
58495 + .probe = snd_ubi32_generic_capture_probe,
58496 + .remove = __devexit_p(snd_ubi32_generic_capture_remove),
58500 + * snd_ubi32_generic_capture_init
58502 +static int __init snd_ubi32_generic_capture_init(void)
58504 + return platform_driver_register(&snd_ubi32_generic_capture_driver);
58506 +module_init(snd_ubi32_generic_capture_init);
58509 + * snd_ubi32_generic_capture_exit
58511 +static void __exit snd_ubi32_generic_capture_exit(void)
58513 + platform_driver_unregister(&snd_ubi32_generic_capture_driver);
58515 +module_exit(snd_ubi32_generic_capture_exit);
58518 + * Module properties
58520 +//#if defined(CONFIG_SND_UBI32_AUDIO_I2C)
58521 +//MODULE_ALIAS("i2c:snd-ubi32");
58523 +MODULE_AUTHOR("Patrick Tjin");
58524 +MODULE_DESCRIPTION("Driver for Ubicom32 audio devices");
58525 +MODULE_LICENSE("GPL");
58526 diff -ruN linux-2.6.30.10/sound/ubicom32/ubi32.h linux-2.6.30.10-ubi/sound/ubicom32/ubi32.h
58527 --- linux-2.6.30.10/sound/ubicom32/ubi32.h 1970-01-01 02:00:00.000000000 +0200
58528 +++ linux-2.6.30.10-ubi/sound/ubicom32/ubi32.h 2009-12-11 11:45:25.000000000 +0200
58531 + * sound/ubicom32/ubi32.h
58532 + * Common header file for all ubi32- sound drivers
58534 + * (C) Copyright 2009, Ubicom, Inc.
58536 + * This file is part of the Ubicom32 Linux Kernel Port.
58538 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
58539 + * it and/or modify it under the terms of the GNU General Public License
58540 + * as published by the Free Software Foundation, either version 2 of the
58541 + * License, or (at your option) any later version.
58543 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
58544 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
58545 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
58546 + * the GNU General Public License for more details.
58548 + * You should have received a copy of the GNU General Public License
58549 + * along with the Ubicom32 Linux Kernel Port. If not,
58550 + * see <http://www.gnu.org/licenses/>.
58556 +#define SND_UBI32_DEBUG 0 // Debug flag
58558 +#include <linux/platform_device.h>
58559 +#include <asm/devtree.h>
58560 +#include <asm/audio.h>
58561 +#include <asm/ubi32-pcm.h>
58563 +struct ubi32_snd_priv;
58565 +typedef int (*set_channels_t)(struct ubi32_snd_priv *priv, int channels);
58566 +typedef int (*set_rate_t)(struct ubi32_snd_priv *priv, int rate);
58568 +struct ubi32_snd_priv {
58570 + * Any variables that are needed locally here but NOT in
58571 + * the VP itself should go in here.
58573 + struct snd_card *card;
58574 + struct snd_pcm *pcm;
58577 + * capture (1) or playback (0)
58581 + * DAC parameters. These are the parameters for the specific
58582 + * DAC we are driving. The I2S component can run at a range
58583 + * of frequencies, but the DAC may be limited. We may want
58584 + * to make this an array of some sort in the future?
58586 + * min/max_sample_rate if set to 0 are ignored.
58588 + int max_sample_rate;
58589 + int min_sample_rate;
58592 + * The size a period (group) of audio samples. The VP does
58593 + * not need to know this; each DMA transfer is made to be
58596 + u32_t period_size;
58598 + spinlock_t ubi32_lock;
58600 + struct audio_regs *ar;
58601 + struct audio_dev_regs *adr;
58609 + * Operations which the base DAC driver can implement
58611 + set_channels_t set_channels;
58612 + set_rate_t set_rate;
58617 + struct ubi32pcm_platform_data *pdata;
58620 + * Private driver data (used for DAC driver control, etc)
58625 +#define snd_ubi32_priv_get_drv(priv) ((priv)->drvdata)
58626 +#define snd_ubi32_priv_set_drv(priv, data) (((priv)->drvdata) = (void *)(data))
58628 +extern int snd_ubi32_pcm_probe(struct ubi32_snd_priv *ubi32_priv, struct platform_device *pdev);
58629 +extern void snd_ubi32_pcm_remove(struct ubi32_snd_priv *ubi32_priv);
58632 diff -ruN linux-2.6.30.10/sound/ubicom32/ubi32-pcm.c linux-2.6.30.10-ubi/sound/ubicom32/ubi32-pcm.c
58633 --- linux-2.6.30.10/sound/ubicom32/ubi32-pcm.c 1970-01-01 02:00:00.000000000 +0200
58634 +++ linux-2.6.30.10-ubi/sound/ubicom32/ubi32-pcm.c 2009-12-11 11:45:25.000000000 +0200
58637 + * sound/ubicom32/ubi32-pcm.c
58638 + * Interface to ubicom32 virtual audio peripheral
58640 + * (C) Copyright 2009, Ubicom, Inc.
58642 + * This file is part of the Ubicom32 Linux Kernel Port.
58644 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
58645 + * it and/or modify it under the terms of the GNU General Public License
58646 + * as published by the Free Software Foundation, either version 2 of the
58647 + * License, or (at your option) any later version.
58649 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
58650 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
58651 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
58652 + * the GNU General Public License for more details.
58654 + * You should have received a copy of the GNU General Public License
58655 + * along with the Ubicom32 Linux Kernel Port. If not,
58656 + * see <http://www.gnu.org/licenses/>.
58658 + * Ubicom32 implementation derived from (with many thanks):
58664 +#include <linux/interrupt.h>
58665 +#include <sound/core.h>
58666 +#include <sound/pcm.h>
58667 +#include <sound/pcm_params.h>
58668 +#include <asm/ip5000.h>
58669 +#include <asm/ubi32-pcm.h>
58670 +#include <linux/dma-mapping.h>
58671 +#include <linux/delay.h>
58672 +#include "ubi32.h"
58674 +struct ubi32_snd_runtime_data {
58675 + dma_addr_t dma_buffer; /* Physical address of DMA buffer */
58676 + dma_addr_t dma_buffer_end; /* First address beyond end of DMA buffer */
58677 + size_t period_size;
58678 + dma_addr_t period_ptr; /* Physical address of next period */
58679 + unsigned int flags;
58682 +static void snd_ubi32_vp_int_set(struct snd_pcm *pcm)
58684 + struct ubi32_snd_priv *ubi32_priv = pcm->private_data;
58685 + ubi32_priv->ar->int_req |= (1 << ubi32_priv->irq_idx);
58686 + ubicom32_set_interrupt(ubi32_priv->tx_irq);
58689 +static snd_pcm_uframes_t snd_ubi32_pcm_pointer(struct snd_pcm_substream *substream)
58692 + struct ubi32_snd_priv *ubi32_priv = snd_pcm_substream_chip(substream);
58693 + struct audio_dev_regs *adr = ubi32_priv->adr;
58694 + struct snd_pcm_runtime *runtime = substream->runtime;
58695 + struct ubi32_snd_runtime_data *ubi32_rd = substream->runtime->private_data;
58697 + dma_addr_t read_pos;
58699 + snd_pcm_uframes_t frames;
58700 + if (!adr->primary_os_buffer_ptr) {
58702 + * If primary_os_buffer_ptr is NULL (e.g. right after the HW is started or
58703 + * when the HW is stopped), then handle this case separately.
58708 + read_pos = (dma_addr_t)adr->primary_os_buffer_ptr;
58709 + frames = bytes_to_frames(runtime, read_pos - ubi32_rd->dma_buffer);
58710 + if (frames == runtime->buffer_size) {
58719 +static int snd_ubi32_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
58721 + struct ubi32_snd_priv *ubi32_priv = substream->pcm->private_data;
58722 + struct audio_dev_regs *adr = ubi32_priv->adr;
58723 + struct ubi32_snd_runtime_data *ubi32_rd = substream->runtime->private_data;
58726 +#ifdef CONFIG_SND_DEBUG
58727 + snd_printk(KERN_INFO "snd_ubi32_pcm_trigger cmd=%d=", cmd);
58730 + if (adr->command != AUDIO_CMD_NONE) {
58731 + snd_printk(KERN_WARNING "Can't send command to audio device at this time\n");
58732 + // Set a timer to call this function back later. How to do this?
58737 + * Set interrupt flag to indicate that we interrupted audio device
58738 + * to send a command
58742 + case SNDRV_PCM_TRIGGER_START:
58744 +#ifdef CONFIG_SND_DEBUG
58745 + snd_printk(KERN_INFO "START\n");
58748 + * Ready the DMA transfer
58750 + ubi32_rd->period_ptr = ubi32_rd->dma_buffer;
58752 +#ifdef CONFIG_SND_DEBUG
58753 + snd_printk(KERN_INFO "trigger period_ptr=%lx\n", (unsigned long)ubi32_rd->period_ptr);
58755 + adr->dma_xfer_requests[0].ptr = (void *)ubi32_rd->period_ptr;
58756 + adr->dma_xfer_requests[0].ctr = ubi32_rd->period_size;
58757 + adr->dma_xfer_requests[0].active = 1;
58759 +#ifdef CONFIG_SND_DEBUG
58760 + snd_printk(KERN_INFO "xfer_request 0 ptr=0x%x ctr=%u\n", ubi32_rd->period_ptr, ubi32_rd->period_size);
58763 + ubi32_rd->period_ptr += ubi32_rd->period_size;
58764 + adr->dma_xfer_requests[1].ptr = (void *)ubi32_rd->period_ptr;
58765 + adr->dma_xfer_requests[1].ctr = ubi32_rd->period_size;
58766 + adr->dma_xfer_requests[1].active = 1;
58768 +#ifdef CONFIG_SND_DEBUG
58769 + snd_printk(KERN_INFO "xfer_request 1 ptr=0x%x ctr=%u\n", ubi32_rd->period_ptr, ubi32_rd->period_size);
58773 + * Tell the VP that we want to begin playback by filling in the
58774 + * command field and then interrupting the audio VP
58776 + adr->int_flags |= AUDIO_INT_FLAG_COMMAND;
58777 + adr->command = AUDIO_CMD_START;
58778 + snd_ubi32_vp_int_set(substream->pcm);
58781 + case SNDRV_PCM_TRIGGER_STOP:
58783 +#ifdef CONFIG_SND_DEBUG
58784 + snd_printk(KERN_INFO "STOP\n");
58788 + * Tell the VP that we want to stop playback by filling in the
58789 + * command field and then interrupting the audio VP
58791 + adr->int_flags |= AUDIO_INT_FLAG_COMMAND;
58792 + adr->command = AUDIO_CMD_STOP;
58793 + snd_ubi32_vp_int_set(substream->pcm);
58796 + case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
58798 +#ifdef CONFIG_SND_DEBUG
58799 + snd_printk(KERN_INFO "PAUSE_PUSH\n");
58803 + * Tell the VP that we want to pause playback by filling in the
58804 + * command field and then interrupting the audio VP
58806 + adr->int_flags |= AUDIO_INT_FLAG_COMMAND;
58807 + adr->command = AUDIO_CMD_PAUSE;
58808 + snd_ubi32_vp_int_set(substream->pcm);
58811 + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
58813 +#ifdef CONFIG_SND_DEBUG
58814 + snd_printk(KERN_INFO "PAUSE_RELEASE\n");
58817 + * Tell the VP that we want to resume paused playback by filling
58818 + * in the command field and then interrupting the audio VP
58820 + adr->int_flags |= AUDIO_INT_FLAG_COMMAND;
58821 + adr->command = AUDIO_CMD_RESUME;
58822 + snd_ubi32_vp_int_set(substream->pcm);
58826 + snd_printk(KERN_WARNING "Unhandled trigger\n");
58835 + * Prepare to transfer an audio stream to the codec
58837 +static int snd_ubi32_pcm_prepare(struct snd_pcm_substream *substream)
58840 + * Configure registers and setup the runtime instance for DMA transfers
58842 + struct ubi32_snd_priv *ubi32_priv = substream->pcm->private_data;
58843 + struct audio_dev_regs *adr = ubi32_priv->adr;
58845 +#ifdef CONFIG_SND_DEBUG
58846 + snd_printk(KERN_INFO "snd_ubi32_pcm_prepare: sending STOP command to audio device\n");
58850 + * Make sure the audio device is stopped
58854 + * Set interrupt flag to indicate that we interrupted audio device
58855 + * to send a command
58857 + adr->int_flags |= AUDIO_INT_FLAG_COMMAND;
58858 + adr->command = AUDIO_CMD_STOP;
58859 + snd_ubi32_vp_int_set(substream->pcm);
58865 + * Allocate DMA buffers from preallocated memory.
58866 + * Preallocation was done in snd_ubi32_pcm_new()
58868 +static int snd_ubi32_pcm_hw_params(struct snd_pcm_substream *substream,
58869 + struct snd_pcm_hw_params *hw_params)
58871 + struct snd_pcm_runtime *runtime = substream->runtime;
58872 + struct ubi32_snd_priv *ubi32_priv = substream->pcm->private_data;
58873 + struct audio_dev_regs *adr = ubi32_priv->adr;
58874 + struct ubi32_snd_runtime_data *ubi32_rd = substream->runtime->private_data;
58877 + * Use pre-allocated memory from ubi32_snd_pcm_new() to satisfy
58878 + * this memory request.
58880 + int ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
58885 +#ifdef CONFIG_SND_DEBUG
58886 + snd_printk(KERN_INFO "snd_ubi32_pcm_hw_params\n");
58889 + if (!(adr->channel_mask & (1 << params_channels(hw_params)))) {
58890 + snd_printk(KERN_INFO "snd_ubi32_pcm_hw_params unsupported number of channels %d mask %08x\n", params_channels(hw_params), adr->channel_mask);
58894 + if (ubi32_priv->set_channels) {
58895 + int ret = ubi32_priv->set_channels(ubi32_priv, params_channels(hw_params));
58897 + snd_printk(KERN_WARNING "Unable to set channels to %d, ret=%d\n", params_channels(hw_params), ret);
58902 + if (ubi32_priv->set_rate) {
58903 + int ret = ubi32_priv->set_rate(ubi32_priv, params_rate(hw_params));
58905 + snd_printk(KERN_WARNING "Unable to set rate to %d, ret=%d\n", params_rate(hw_params), ret);
58910 + if (ubi32_priv->pdata->set_rate) {
58911 + int ret = ubi32_priv->pdata->set_rate(ubi32_priv->pdata->appdata, params_rate(hw_params));
58913 + snd_printk(KERN_WARNING "Unable to set rate to %d, ret=%d\n", params_rate(hw_params), ret);
58918 + if (adr->command != AUDIO_CMD_NONE) {
58919 + snd_printk(KERN_WARNING "snd_ubi32_pcm_hw_params: tio busy\n");
58923 + if (params_format(hw_params) == SNDRV_PCM_FORMAT_S16_LE) {
58924 + adr->flags |= CMD_START_FLAG_LE;
58926 + adr->flags &= ~CMD_START_FLAG_LE;
58928 + adr->channels = params_channels(hw_params);
58929 + adr->sample_rate = params_rate(hw_params);
58930 + adr->command = AUDIO_CMD_SETUP;
58931 + adr->int_flags |= AUDIO_INT_FLAG_COMMAND;
58932 + snd_ubi32_vp_int_set(substream->pcm);
58935 + * Wait for the command to complete
58937 + while (adr->command != AUDIO_CMD_NONE) {
58942 + * Put the DMA info into the DMA descriptor that we will
58943 + * use to do transfers to our audio VP "hardware"
58947 + * Mark both DMA transfers as not ready/inactive
58949 + adr->dma_xfer_requests[0].active = 0;
58950 + adr->dma_xfer_requests[1].active = 0;
58953 + * Put the location of the buffer into the runtime data instance
58955 + ubi32_rd->dma_buffer = (dma_addr_t)runtime->dma_area;
58956 + ubi32_rd->dma_buffer_end = (dma_addr_t)(runtime->dma_area + runtime->dma_bytes);
58959 + * Get the period size
58961 + ubi32_rd->period_size = params_period_bytes(hw_params);
58963 +#ifdef CONFIG_SND_DEBUG
58964 + snd_printk(KERN_INFO "DMA for ubi32 audio initialized dma_area=0x%x dma_bytes=%d, period_size=%d\n", (unsigned int)runtime->dma_area, (unsigned int)runtime->dma_bytes, ubi32_rd->period_size);
58965 + snd_printk(KERN_INFO "Private buffer ubi32_rd: dma_buffer=0x%x dma_buffer_end=0x%x ret=%d\n", ubi32_rd->dma_buffer, ubi32_rd->dma_buffer_end, ret);
58972 + * This is the reverse of snd_ubi32_pcm_hw_params
58974 +static int snd_ubi32_pcm_hw_free(struct snd_pcm_substream *substream)
58976 +#ifdef CONFIG_SND_DEBUG
58977 + snd_printk(KERN_INFO "snd_ubi32_pcm_hw_free\n");
58979 + return snd_pcm_lib_free_pages(substream);
58983 + * Audio virtual peripheral capabilities (capture and playback are identical)
58985 +static struct snd_pcm_hardware snd_ubi32_pcm_hw =
58987 + .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
58988 + SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
58989 + .buffer_bytes_max = (64*1024),
58990 + .period_bytes_min = 64,
58991 + .period_bytes_max = 8184,//8184,//8176,
58992 + .periods_min = 2,
58993 + .periods_max = 255,
58994 + .fifo_size = 0, // THIS IS IGNORED BY ALSA
58998 + * We fill this in later
59000 +static struct snd_pcm_hw_constraint_list ubi32_pcm_rates;
59003 + * snd_ubi32_pcm_close
59005 +static int snd_ubi32_pcm_close(struct snd_pcm_substream *substream)
59007 + /* Disable codec, stop DMA, free private data structures */
59008 + //struct ubi32_snd_priv *ubi32_priv = snd_pcm_substream_chip(substream);
59009 + struct ubi32_snd_runtime_data *ubi32_rd = substream->runtime->private_data;
59011 +#ifdef CONFIG_SND_DEBUG
59012 + snd_printk(KERN_INFO "snd_ubi32_pcm_close\n");
59015 + substream->runtime->private_data = NULL;
59023 + * snd_ubi32_pcm_open
59025 +static int snd_ubi32_pcm_open(struct snd_pcm_substream *substream)
59027 + struct snd_pcm_runtime *runtime = substream->runtime;
59028 + struct ubi32_snd_runtime_data *ubi32_rd;
59031 +#ifdef CONFIG_SND_DEBUG
59032 + snd_printk(KERN_INFO "ubi32 pcm open\n");
59035 + /* Associate capabilities with component */
59036 + runtime->hw = snd_ubi32_pcm_hw;
59039 + * Inform ALSA about constraints of the audio device
59041 + ret = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &ubi32_pcm_rates);
59043 + snd_printk(KERN_INFO "invalid rate\n");
59047 + /* Force the buffer size to be an integer multiple of period size */
59048 + ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
59050 + snd_printk(KERN_INFO "invalid period\n");
59053 + /* Initialize structures/registers */
59054 + ubi32_rd = kzalloc(sizeof(struct ubi32_snd_runtime_data), GFP_KERNEL);
59055 + if (ubi32_rd == NULL) {
59060 + runtime->private_data = ubi32_rd;
59062 +#ifdef CONFIG_SND_DEBUG
59063 + snd_printk(KERN_INFO "snd_ubi32_pcm_open returned 0\n");
59068 +#ifdef CONFIG_SND_DEBUG
59069 + snd_printk(KERN_INFO "snd_ubi32_pcm_open returned %d\n", ret);
59075 +static struct snd_pcm_ops snd_ubi32_pcm_ops = {
59076 + .open = snd_ubi32_pcm_open, /* Open */
59077 + .close = snd_ubi32_pcm_close, /* Close */
59078 + .ioctl = snd_pcm_lib_ioctl, /* Generic IOCTL handler */
59079 + .hw_params = snd_ubi32_pcm_hw_params, /* Hardware parameters/capabilities */
59080 + .hw_free = snd_ubi32_pcm_hw_free, /* Free function for hw_params */
59081 + .prepare = snd_ubi32_pcm_prepare,
59082 + .trigger = snd_ubi32_pcm_trigger,
59083 + .pointer = snd_ubi32_pcm_pointer,
59087 + * Interrupt handler that gets called when the audio device
59088 + * interrupts Linux
59090 +static irqreturn_t snd_ubi32_pcm_interrupt(int irq, void *appdata)
59092 + struct snd_pcm *pcm = (struct snd_pcm *)appdata;
59093 + struct ubi32_snd_priv *ubi32_priv = pcm->private_data;
59094 + struct audio_dev_regs *adr = ubi32_priv->adr;
59095 + struct snd_pcm_substream *substream;
59096 + struct ubi32_snd_runtime_data *ubi32_rd;
59097 + int dma_to_fill = 0;
59100 + * Check to see if the interrupt is for us
59102 + if (!(ubi32_priv->ar->int_status & (1 << ubi32_priv->irq_idx))) {
59107 + * Clear the interrupt
59109 + ubi32_priv->ar->int_status &= ~(1 << ubi32_priv->irq_idx);
59112 + * We only have one stream since we don't mix. Therefore
59113 + * we don't need to search through substreams.
59115 + if (ubi32_priv->is_capture) {
59116 + substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
59118 + substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
59121 + if (!substream->runtime) {
59122 + snd_printk(KERN_WARNING "No runtime data\n");
59126 + ubi32_rd = substream->runtime->private_data;
59128 +#ifdef CONFIG_SND_DEBUG
59129 + snd_printk(KERN_INFO "Ubi32 ALSA interrupt\n");
59132 + if (ubi32_rd == NULL) {
59133 + snd_printk(KERN_WARNING "No private data\n");
59137 + // Check interrupt cause
59139 + // Handle the underflow case
59140 + } else if ((adr->status & AUDIO_STATUS_PLAY_DMA0_REQUEST) ||
59141 + (adr->status & AUDIO_STATUS_PLAY_DMA1_REQUEST)) {
59142 + if (adr->status & AUDIO_STATUS_PLAY_DMA0_REQUEST) {
59144 + adr->status &= ~AUDIO_STATUS_PLAY_DMA0_REQUEST;
59145 + } else if (adr->status & AUDIO_STATUS_PLAY_DMA1_REQUEST) {
59147 + adr->status &= ~AUDIO_STATUS_PLAY_DMA1_REQUEST;
59149 + ubi32_rd->period_ptr += ubi32_rd->period_size;
59150 + if (ubi32_rd->period_ptr >= ubi32_rd->dma_buffer_end) {
59151 + ubi32_rd->period_ptr = ubi32_rd->dma_buffer;
59153 + adr->dma_xfer_requests[dma_to_fill].ptr = (void *)ubi32_rd->period_ptr;
59154 + adr->dma_xfer_requests[dma_to_fill].ctr = ubi32_rd->period_size;
59155 + adr->dma_xfer_requests[dma_to_fill].active = 1;
59156 +#ifdef CONFIG_SND_DEBUG
59157 + snd_printk(KERN_INFO "xfer_request %d ptr=0x%x ctr=%u\n", dma_to_fill, ubi32_rd->period_ptr, ubi32_rd->period_size);
59159 + adr->int_flags |= AUDIO_INT_FLAG_MORE_SAMPLES;
59160 + snd_ubi32_vp_int_set(substream->pcm);
59162 + // If we are interrupted by the VP, that means we completed
59163 + // processing one period of audio. We need to inform the upper
59164 + // layers of ALSA of this.
59165 + snd_pcm_period_elapsed(substream);
59167 + return IRQ_HANDLED;
59170 +void __devexit snd_ubi32_pcm_remove(struct ubi32_snd_priv *ubi32_priv)
59172 + struct snd_pcm *pcm = ubi32_priv->pcm;
59173 + free_irq(ubi32_priv->rx_irq, pcm);
59176 +#if SNDRV_PCM_RATE_5512 != 1 << 0 || SNDRV_PCM_RATE_192000 != 1 << 12
59177 +#error "Change this table to match pcm.h"
59179 +static unsigned int rates[] __initdata = {5512, 8000, 11025, 16000, 22050,
59180 + 32000, 44100, 48000, 64000, 88200,
59181 + 96000, 176400, 192000};
59184 + * snd_ubi32_pcm_probe
59186 +int __devinit snd_ubi32_pcm_probe(struct ubi32_snd_priv *ubi32_priv, struct platform_device *pdev)
59188 + struct snd_pcm *pcm;
59193 + unsigned int rate_max = 0;
59194 + unsigned int rate_min = 0xFFFFFFFF;
59195 + unsigned int rate_mask = 0;
59196 + struct audio_dev_regs *adr;
59197 + struct resource *res_adr;
59198 + struct resource *res_irq_tx;
59199 + struct resource *res_irq_rx;
59200 + struct ubi32pcm_platform_data *pdata;
59202 + pdata = pdev->dev.platform_data;
59208 + * Get our resources, adr is the hardware driver base address
59209 + * and the tx and rx irqs are used to communicate with the
59210 + * hardware driver.
59212 + res_adr = platform_get_resource(pdev, IORESOURCE_MEM, AUDIO_MEM_RESOURCE);
59213 + res_irq_tx = platform_get_resource(pdev, IORESOURCE_IRQ, AUDIO_TX_IRQ_RESOURCE);
59214 + res_irq_rx = platform_get_resource(pdev, IORESOURCE_IRQ, AUDIO_RX_IRQ_RESOURCE);
59215 + if (!res_adr || !res_irq_tx || !res_irq_rx) {
59216 + snd_printk(KERN_WARNING "Could not get resources");
59220 + ubi32_priv->ar = (struct audio_regs *)res_adr->start;
59221 + ubi32_priv->tx_irq = res_irq_tx->start;
59222 + ubi32_priv->rx_irq = res_irq_rx->start;
59223 + ubi32_priv->irq_idx = pdata->inst_num;
59224 + ubi32_priv->adr = &(ubi32_priv->ar->adr[pdata->inst_num]);
59227 + * Check the version
59229 + adr = ubi32_priv->adr;
59230 + if (adr->version != AUDIO_DEV_REGS_VERSION) {
59231 + snd_printk(KERN_WARNING "This audio_dev_reg is not compatible with this driver\n");
59236 + * Find out the standard rates, also find max and min rates
59238 + for (i = 0; i < ARRAY_SIZE(rates); i++) {
59240 + for (j = 0; j < adr->n_sample_rates; j++) {
59241 + if (rates[i] == adr->sample_rates[j]) {
59243 + * Check to see if it is supported by the dac
59245 + if ((rates[i] >= ubi32_priv->min_sample_rate) &&
59246 + (!ubi32_priv->max_sample_rate ||
59247 + (ubi32_priv->max_sample_rate && (rates[i] <= ubi32_priv->max_sample_rate)))) {
59249 + rate_mask |= (1 << i);
59251 + if (rates[i] < rate_min) {
59252 + rate_min = rates[i];
59254 + if (rates[i] > rate_max) {
59255 + rate_max = rates[i];
59262 + rate_mask |= SNDRV_PCM_RATE_KNOT;
59266 + snd_ubi32_pcm_hw.rates = rate_mask;
59267 + snd_ubi32_pcm_hw.rate_min = rate_min;
59268 + snd_ubi32_pcm_hw.rate_max = rate_max;
59269 + ubi32_pcm_rates.count = adr->n_sample_rates;
59270 + ubi32_pcm_rates.list = (unsigned int *)adr->sample_rates;
59271 + ubi32_pcm_rates.mask = 0;
59273 + for (i = 0; i < 32; i++) {
59274 + if (adr->channel_mask & (1 << i)) {
59275 + if (!snd_ubi32_pcm_hw.channels_min) {
59276 + snd_ubi32_pcm_hw.channels_min = i;
59278 + snd_ubi32_pcm_hw.channels_max = i;
59281 + snd_printk(KERN_INFO "Ubi32PCM: channels_min:%u channels_max:%u\n",
59282 + snd_ubi32_pcm_hw.channels_min,
59283 + snd_ubi32_pcm_hw.channels_max);
59285 + if (adr->caps & AUDIONODE_CAP_BE) {
59286 + snd_ubi32_pcm_hw.formats |= SNDRV_PCM_FMTBIT_S16_BE;
59288 + if (adr->caps & AUDIONODE_CAP_LE) {
59289 + snd_ubi32_pcm_hw.formats |= SNDRV_PCM_FMTBIT_S16_LE;
59292 + snd_printk(KERN_INFO "Ubi32PCM: rates:%08x min:%u max:%u count:%d fmts:%016llx (%s)\n",
59293 + snd_ubi32_pcm_hw.rates,
59294 + snd_ubi32_pcm_hw.rate_min,
59295 + snd_ubi32_pcm_hw.rate_max,
59296 + ubi32_pcm_rates.count,
59297 + snd_ubi32_pcm_hw.formats,
59298 + ubi32_priv->is_capture ? "capture" : "playback");
59300 + if (ubi32_priv->is_capture) {
59301 + ret = snd_pcm_new(ubi32_priv->card, "Ubi32 PCM", 0, 0, 1, &pcm);
59303 + ret = snd_pcm_new(ubi32_priv->card, "Ubi32 PCM", 0, 1, 0, &pcm);
59310 + pcm->private_data = ubi32_priv;
59311 + ubi32_priv->pcm = pcm;
59312 + ubi32_priv->pdata = pdata;
59314 + pcm->info_flags = 0;
59316 + strcpy(pcm->name, "Ubi32-PCM");
59318 + snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
59319 + snd_dma_continuous_data(GFP_KERNEL),
59320 + 45*1024, 64*1024);
59322 + if (ubi32_priv->is_capture) {
59323 + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ubi32_pcm_ops);
59325 + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ubi32_pcm_ops);
59329 + * Start up the audio device
59331 + adr->int_flags |= AUDIO_INT_FLAG_COMMAND;
59332 + adr->command = AUDIO_CMD_ENABLE;
59333 + snd_ubi32_vp_int_set(pcm);
59338 + err = request_irq(ubi32_priv->rx_irq, snd_ubi32_pcm_interrupt, IRQF_SHARED | IRQF_DISABLED, pcm->name, pcm);
59340 + snd_printk(KERN_WARNING "request_irq failed: irq=%d err=%d\n", ubi32_priv->rx_irq, err);