2 +++ b/arch/ubicom32/crypto/aes_ubicom32.c
5 + * arch/ubicom32/crypto/aes_ubicom32.c
6 + * Ubicom32 implementation of the AES Cipher Algorithm.
8 + * (C) Copyright 2009, Ubicom, Inc.
10 + * This file is part of the Ubicom32 Linux Kernel Port.
12 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
13 + * it and/or modify it under the terms of the GNU General Public License
14 + * as published by the Free Software Foundation, either version 2 of the
15 + * License, or (at your option) any later version.
17 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
18 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
19 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
20 + * the GNU General Public License for more details.
22 + * You should have received a copy of the GNU General Public License
23 + * along with the Ubicom32 Linux Kernel Port. If not,
24 + * see <http://www.gnu.org/licenses/>.
26 + * Ubicom32 implementation derived from (with many thanks):
31 +#include <crypto/aes.h>
32 +#include <crypto/algapi.h>
33 +#include <linux/err.h>
34 +#include <linux/module.h>
35 +#include <linux/init.h>
36 +#include <linux/spinlock.h>
37 +#include "crypto_ubicom32.h"
38 +#include <asm/linkage.h>
40 +struct ubicom32_aes_ctx {
41 + u8 key[AES_MAX_KEY_SIZE];
46 +static inline void aes_hw_set_key(const u8 *key, u8 key_len)
49 + * switch case has more overhead than 4 move.4 instructions, so just copy 256 bits
51 + SEC_SET_KEY_256(key);
54 +static inline void aes_hw_set_iv(const u8 *iv)
59 +static inline void aes_hw_cipher(u8 *out, const u8 *in)
61 + SEC_SET_INPUT_4W(in);
64 + " ; start AES by writing 0x40(SECURITY_BASE) \n\t"
65 + " move.4 0x40(%0), #0x01 \n\t"
66 + " pipe_flush 0 \n\t"
68 + " ; wait for the module to calculate the output \n\t"
69 + " btst 0x04(%0), #0 \n\t"
76 + SEC_GET_OUTPUT_4W(out);
79 +static int __ocm_text aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
80 + unsigned int key_len)
82 + struct ubicom32_aes_ctx *uctx = crypto_tfm_ctx(tfm);
84 + uctx->key_len = key_len;
85 + memcpy(uctx->key, in_key, key_len);
88 + * leave out HASH_ALG (none = 0), CBC (no = 0), DIR (unknown) yet
90 + switch (uctx->key_len) {
92 + uctx->ctrl = SEC_KEY_128_BITS | SEC_ALG_AES;
95 + uctx->ctrl = SEC_KEY_192_BITS | SEC_ALG_AES;
98 + uctx->ctrl = SEC_KEY_256_BITS | SEC_ALG_AES;
105 +static inline void aes_cipher(struct crypto_tfm *tfm, u8 *out, const u8 *in, u32 extra_flags)
107 + const struct ubicom32_aes_ctx *uctx = crypto_tfm_ctx(tfm);
111 + hw_crypto_set_ctrl(uctx->ctrl | extra_flags);
113 + aes_hw_set_key(uctx->key, uctx->key_len);
114 + aes_hw_cipher(out, in);
116 + hw_crypto_unlock();
119 +static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
121 + aes_cipher(tfm, out, in, SEC_DIR_ENCRYPT);
124 +static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
126 + aes_cipher(tfm, out, in, SEC_DIR_DECRYPT);
129 +static struct crypto_alg aes_alg = {
131 + .cra_driver_name = "aes-ubicom32",
132 + .cra_priority = CRYPTO_UBICOM32_PRIORITY,
133 + .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
134 + .cra_blocksize = AES_BLOCK_SIZE,
135 + .cra_ctxsize = sizeof(struct ubicom32_aes_ctx),
136 + .cra_alignmask = CRYPTO_UBICOM32_ALIGNMENT - 1,
137 + .cra_module = THIS_MODULE,
138 + .cra_list = LIST_HEAD_INIT(aes_alg.cra_list),
141 + .cia_min_keysize = AES_MIN_KEY_SIZE,
142 + .cia_max_keysize = AES_MAX_KEY_SIZE,
143 + .cia_setkey = aes_set_key,
144 + .cia_encrypt = aes_encrypt,
145 + .cia_decrypt = aes_decrypt,
150 +static void __ocm_text ecb_aes_crypt_loop(u8 *out, u8 *in, unsigned int n)
152 + while (likely(n)) {
153 + aes_hw_cipher(out, in);
154 + out += AES_BLOCK_SIZE;
155 + in += AES_BLOCK_SIZE;
156 + n -= AES_BLOCK_SIZE;
160 +static int __ocm_text ecb_aes_crypt(struct blkcipher_desc *desc, struct scatterlist *dst,
161 + struct scatterlist *src, unsigned int nbytes, u32 extra_flags)
163 + const struct ubicom32_aes_ctx *uctx = crypto_blkcipher_ctx(desc->tfm);
166 + struct blkcipher_walk walk;
167 + blkcipher_walk_init(&walk, dst, src, nbytes);
168 + ret = blkcipher_walk_virt(desc, &walk);
176 + hw_crypto_set_ctrl(uctx->ctrl | extra_flags);
177 + aes_hw_set_key(uctx->key, uctx->key_len);
179 + while (likely((nbytes = walk.nbytes))) {
180 + /* only use complete blocks */
181 + unsigned int n = nbytes & ~(AES_BLOCK_SIZE - 1);
182 + u8 *out = walk.dst.virt.addr;
183 + u8 *in = walk.src.virt.addr;
185 + /* finish n/16 blocks */
186 + ecb_aes_crypt_loop(out, in, n);
188 + nbytes &= AES_BLOCK_SIZE - 1;
189 + ret = blkcipher_walk_done(desc, &walk, nbytes);
192 + hw_crypto_unlock();
196 +static int ecb_aes_encrypt(struct blkcipher_desc *desc,
197 + struct scatterlist *dst, struct scatterlist *src,
198 + unsigned int nbytes)
200 + return ecb_aes_crypt(desc, dst, src, nbytes, SEC_DIR_ENCRYPT);
203 +static int ecb_aes_decrypt(struct blkcipher_desc *desc,
204 + struct scatterlist *dst, struct scatterlist *src,
205 + unsigned int nbytes)
207 + return ecb_aes_crypt(desc, dst, src, nbytes, SEC_DIR_DECRYPT);
210 +static struct crypto_alg ecb_aes_alg = {
211 + .cra_name = "ecb(aes)",
212 + .cra_driver_name = "ecb-aes-ubicom32",
213 + .cra_priority = CRYPTO_UBICOM32_COMPOSITE_PRIORITY,
214 + .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
215 + .cra_blocksize = AES_BLOCK_SIZE,
216 + .cra_ctxsize = sizeof(struct ubicom32_aes_ctx),
217 + .cra_alignmask = CRYPTO_UBICOM32_ALIGNMENT - 1,
218 + .cra_type = &crypto_blkcipher_type,
219 + .cra_module = THIS_MODULE,
220 + .cra_list = LIST_HEAD_INIT(ecb_aes_alg.cra_list),
223 + .min_keysize = AES_MIN_KEY_SIZE,
224 + .max_keysize = AES_MAX_KEY_SIZE,
225 + .setkey = aes_set_key,
226 + .encrypt = ecb_aes_encrypt,
227 + .decrypt = ecb_aes_decrypt,
232 +#if CRYPTO_UBICOM32_LOOP_ASM
233 +void __ocm_text cbc_aes_encrypt_loop(u8 *out, u8 *in, u8 *iv, unsigned int n)
236 + "; set init. iv 4w \n\t"
237 + " move.4 0x50(%0), 0x0(%3) \n\t"
238 + " move.4 0x54(%0), 0x4(%3) \n\t"
239 + " move.4 0x58(%0), 0x8(%3) \n\t"
240 + " move.4 0x5c(%0), 0xc(%3) \n\t"
242 + "; we know n > 0, so we can always \n\t"
243 + "; load the first block \n\t"
244 + "; set input 4w \n\t"
245 + " move.4 0x30(%0), 0x0(%2) \n\t"
246 + " move.4 0x34(%0), 0x4(%2) \n\t"
247 + " move.4 0x38(%0), 0x8(%2) \n\t"
248 + " move.4 0x3c(%0), 0xc(%2) \n\t"
250 + "; kickoff hw \n\t"
251 + " move.4 0x40(%0), %2 \n\t"
253 + "; update n & flush \n\t"
254 + " add.4 %4, #-16, %4 \n\t"
255 + " pipe_flush 0 \n\t"
257 + "; while (n): work on 2nd block \n\t"
258 + " 1: lsl.4 d15, %4, #0x0 \n\t"
261 + "; set input 4w (2nd) \n\t"
262 + " move.4 0x30(%0), 0x10(%2) \n\t"
263 + " move.4 0x34(%0), 0x14(%2) \n\t"
264 + " move.4 0x38(%0), 0x18(%2) \n\t"
265 + " move.4 0x3c(%0), 0x1c(%2) \n\t"
267 + "; update n/in asap while waiting \n\t"
268 + " add.4 %4, #-16, %4 \n\t"
269 + " move.4 d15, 16(%2)++ \n\t"
271 + "; wait for the previous output \n\t"
272 + " btst 0x04(%0), #0 \n\t"
275 + "; read previous output \n\t"
276 + " move.4 0x0(%1), 0x50(%0) \n\t"
277 + " move.4 0x4(%1), 0x54(%0) \n\t"
278 + " move.4 0x8(%1), 0x58(%0) \n\t"
279 + " move.4 0xc(%1), 0x5c(%0) \n\t"
281 + "; kick off hw for 2nd input \n\t"
282 + " move.4 0x40(%0), %2 \n\t"
284 + "; update out asap \n\t"
285 + " move.4 d15, 16(%1)++ \n\t"
287 + "; go back to loop \n\t"
290 + "; wait for last output \n\t"
291 + " 5: btst 0x04(%0), #0 \n\t"
294 + "; read last output \n\t"
295 + " move.4 0x0(%1), 0x50(%0) \n\t"
296 + " move.4 0x4(%1), 0x54(%0) \n\t"
297 + " move.4 0x8(%1), 0x58(%0) \n\t"
298 + " move.4 0xc(%1), 0x5c(%0) \n\t"
300 + "; copy out iv \n\t"
301 + " move.4 0x0(%3), 0x50(%0) \n\t"
302 + " move.4 0x4(%3), 0x54(%0) \n\t"
303 + " move.4 0x8(%3), 0x58(%0) \n\t"
304 + " move.4 0xc(%3), 0x5c(%0) \n\t"
307 + : "a" (SEC_BASE), "a" (out), "a" (in), "a" (iv), "d" (n)
314 +static void __ocm_text cbc_aes_encrypt_loop(u8 *out, u8 *in, u8 *iv, unsigned int n)
317 + while (likely(n)) {
318 + aes_hw_cipher(out, in);
319 + out += AES_BLOCK_SIZE;
320 + in += AES_BLOCK_SIZE;
321 + n -= AES_BLOCK_SIZE;
323 + SEC_COPY_4W(iv, out - AES_BLOCK_SIZE);
328 +static void __ocm_text cbc_aes_decrypt_loop(u8 *out, u8 *in, u8 *iv, unsigned int n)
330 + while (likely(n)) {
332 + SEC_COPY_4W(iv, in);
333 + aes_hw_cipher(out, in);
334 + out += AES_BLOCK_SIZE;
335 + in += AES_BLOCK_SIZE;
336 + n -= AES_BLOCK_SIZE;
340 +static int __ocm_text cbc_aes_crypt(struct blkcipher_desc *desc,
341 + struct scatterlist *dst, struct scatterlist *src,
342 + unsigned int nbytes, u32 extra_flags)
344 + struct ubicom32_aes_ctx *uctx = crypto_blkcipher_ctx(desc->tfm);
347 + struct blkcipher_walk walk;
348 + blkcipher_walk_init(&walk, dst, src, nbytes);
349 + ret = blkcipher_walk_virt(desc, &walk);
350 + if (unlikely(ret)) {
357 + hw_crypto_set_ctrl(uctx->ctrl | extra_flags);
358 + aes_hw_set_key(uctx->key, uctx->key_len);
360 + while (likely((nbytes = walk.nbytes))) {
361 + /* only use complete blocks */
362 + unsigned int n = nbytes & ~(AES_BLOCK_SIZE - 1);
364 + u8 *out = walk.dst.virt.addr;
365 + u8 *in = walk.src.virt.addr;
367 + if (extra_flags & SEC_DIR_ENCRYPT) {
368 + cbc_aes_encrypt_loop(out, in, walk.iv, n);
370 + cbc_aes_decrypt_loop(out, in, walk.iv, n);
374 + nbytes &= AES_BLOCK_SIZE - 1;
375 + ret = blkcipher_walk_done(desc, &walk, nbytes);
377 + hw_crypto_unlock();
382 +static int __ocm_text cbc_aes_encrypt(struct blkcipher_desc *desc,
383 + struct scatterlist *dst, struct scatterlist *src,
384 + unsigned int nbytes)
386 + return cbc_aes_crypt(desc, dst, src, nbytes, SEC_DIR_ENCRYPT | SEC_CBC_SET);
389 +static int __ocm_text cbc_aes_decrypt(struct blkcipher_desc *desc,
390 + struct scatterlist *dst, struct scatterlist *src,
391 + unsigned int nbytes)
393 + return cbc_aes_crypt(desc, dst, src, nbytes, SEC_DIR_DECRYPT | SEC_CBC_SET);
396 +static struct crypto_alg cbc_aes_alg = {
397 + .cra_name = "cbc(aes)",
398 + .cra_driver_name = "cbc-aes-ubicom32",
399 + .cra_priority = CRYPTO_UBICOM32_COMPOSITE_PRIORITY,
400 + .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
401 + .cra_blocksize = AES_BLOCK_SIZE,
402 + .cra_ctxsize = sizeof(struct ubicom32_aes_ctx),
403 + .cra_alignmask = CRYPTO_UBICOM32_ALIGNMENT - 1,
404 + .cra_type = &crypto_blkcipher_type,
405 + .cra_module = THIS_MODULE,
406 + .cra_list = LIST_HEAD_INIT(cbc_aes_alg.cra_list),
409 + .min_keysize = AES_MIN_KEY_SIZE,
410 + .max_keysize = AES_MAX_KEY_SIZE,
411 + .ivsize = AES_BLOCK_SIZE,
412 + .setkey = aes_set_key,
413 + .encrypt = cbc_aes_encrypt,
414 + .decrypt = cbc_aes_decrypt,
419 +static int __init aes_init(void)
425 + ret = crypto_register_alg(&aes_alg);
429 + ret = crypto_register_alg(&ecb_aes_alg);
433 + ret = crypto_register_alg(&cbc_aes_alg);
441 + crypto_unregister_alg(&ecb_aes_alg);
443 + crypto_unregister_alg(&aes_alg);
448 +static void __exit aes_fini(void)
450 + crypto_unregister_alg(&cbc_aes_alg);
451 + crypto_unregister_alg(&ecb_aes_alg);
452 + crypto_unregister_alg(&aes_alg);
455 +module_init(aes_init);
456 +module_exit(aes_fini);
458 +MODULE_ALIAS("aes");
460 +MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm");
461 +MODULE_LICENSE("GPL");
463 +++ b/arch/ubicom32/crypto/crypto_des.h
466 + * arch/ubicom32/crypto/crypto_des.h
467 + * Function for checking keys for the DES and Triple DES Encryption
470 + * (C) Copyright 2009, Ubicom, Inc.
472 + * This file is part of the Ubicom32 Linux Kernel Port.
474 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
475 + * it and/or modify it under the terms of the GNU General Public License
476 + * as published by the Free Software Foundation, either version 2 of the
477 + * License, or (at your option) any later version.
479 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
480 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
481 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
482 + * the GNU General Public License for more details.
484 + * You should have received a copy of the GNU General Public License
485 + * along with the Ubicom32 Linux Kernel Port. If not,
486 + * see <http://www.gnu.org/licenses/>.
488 + * Ubicom32 implementation derived from (with many thanks):
493 +#ifndef __CRYPTO_DES_H__
494 +#define __CRYPTO_DES_H__
496 +extern int crypto_des_check_key(const u8*, unsigned int, u32*);
498 +#endif /* __CRYPTO_DES_H__ */
500 +++ b/arch/ubicom32/crypto/crypto_ubicom32.c
503 + * arch/ubicom32/crypto/crypto_ubicom32.c
504 + * Generic code to support ubicom32 hardware crypto accelerator
506 + * (C) Copyright 2009, Ubicom, Inc.
508 + * This file is part of the Ubicom32 Linux Kernel Port.
510 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
511 + * it and/or modify it under the terms of the GNU General Public License
512 + * as published by the Free Software Foundation, either version 2 of the
513 + * License, or (at your option) any later version.
515 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
516 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
517 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
518 + * the GNU General Public License for more details.
520 + * You should have received a copy of the GNU General Public License
521 + * along with the Ubicom32 Linux Kernel Port. If not,
522 + * see <http://www.gnu.org/licenses/>.
524 + * Ubicom32 implementation derived from (with many thanks):
529 +#include "crypto_ubicom32.h"
531 +spinlock_t crypto_ubicom32_lock;
532 +bool crypto_ubicom32_inited = false;
533 +volatile bool crypto_ubicom32_on = false;
534 +volatile unsigned long crypto_ubicom32_last_use;
536 +struct timer_list crypto_ubicom32_ps_timer;
537 +void crypto_ubicom32_ps_check(unsigned long data)
539 + unsigned long idle_time = msecs_to_jiffies(HW_CRYPTO_PS_MAX_IDLE_MS);
541 + BUG_ON(!crypto_ubicom32_on);
543 + if (((jiffies - crypto_ubicom32_last_use) > idle_time) && spin_trylock_bh(&crypto_ubicom32_lock)) {
544 + hw_crypto_turn_off();
545 + spin_unlock_bh(&crypto_ubicom32_lock);
549 + /* keep monitoring */
550 + hw_crypto_ps_start();
553 +++ b/arch/ubicom32/crypto/crypto_ubicom32.h
556 + * arch/ubicom32/crypto/crypto_ubicom32.h
557 + * Support for Ubicom32 cryptographic instructions.
559 + * (C) Copyright 2009, Ubicom, Inc.
561 + * This file is part of the Ubicom32 Linux Kernel Port.
563 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
564 + * it and/or modify it under the terms of the GNU General Public License
565 + * as published by the Free Software Foundation, either version 2 of the
566 + * License, or (at your option) any later version.
568 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
569 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
570 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
571 + * the GNU General Public License for more details.
573 + * You should have received a copy of the GNU General Public License
574 + * along with the Ubicom32 Linux Kernel Port. If not,
575 + * see <http://www.gnu.org/licenses/>.
577 + * Ubicom32 implementation derived from (with many thanks):
582 +#ifndef _CRYPTO_ARCH_UBICOM32_CRYPT_H
583 +#define _CRYPTO_ARCH_UBICOM32_CRYPT_H
585 +#include <linux/module.h>
586 +#include <linux/kernel.h>
587 +#include <linux/jiffies.h>
588 +#include <linux/timer.h>
589 +#include <linux/spinlock.h>
590 +#include <asm/errno.h>
592 +#include <asm/ip5000.h>
594 +#define CRYPTO_UBICOM32_LOOP_ASM 1
595 +#define CRYPTO_UBICOM32_ALIGNMENT 4
596 +#define SEC_ALIGNED(p) (((u32)p & 3) == 0)
598 +#define SEC_BASE SECURITY_BASE
599 +#define SEC_KEY_OFFSET SECURITY_KEY_VALUE(0)
600 +#define SEC_INPUT_OFFSET SECURITY_KEY_IN(0)
601 +#define SEC_OUTPUT_OFFSET SECURITY_KEY_OUT(0)
602 +#define SEC_HASH_OFFSET SECURITY_KEY_HASH(0)
604 +#define SEC_KEY_128_BITS SECURITY_CTRL_KEY_SIZE(0)
605 +#define SEC_KEY_192_BITS SECURITY_CTRL_KEY_SIZE(1)
606 +#define SEC_KEY_256_BITS SECURITY_CTRL_KEY_SIZE(2)
608 +#define SEC_HASH_NONE SECURITY_CTRL_HASH_ALG_NONE
609 +#define SEC_HASH_MD5 SECURITY_CTRL_HASH_ALG_MD5
610 +#define SEC_HASH_SHA1 SECURITY_CTRL_HASH_ALG_SHA1
612 +#define SEC_CBC_SET SECURITY_CTRL_CBC
613 +#define SEC_CBC_NONE 0
615 +#define SEC_ALG_AES SECURITY_CTRL_CIPHER_ALG_AES
616 +#define SEC_ALG_NONE SECURITY_CTRL_CIPHER_ALG_NONE
617 +#define SEC_ALG_DES SECURITY_CTRL_CIPHER_ALG_DES
618 +#define SEC_ALG_3DES SECURITY_CTRL_CIPHER_ALG_3DES
620 +#define SEC_DIR_ENCRYPT SECURITY_CTRL_ENCIPHER
621 +#define SEC_DIR_DECRYPT 0
623 +#define CRYPTO_UBICOM32_PRIORITY 300
624 +#define CRYPTO_UBICOM32_COMPOSITE_PRIORITY 400
626 +#define HW_CRYPTO_PS_MAX_IDLE_MS 100 /* idle time (ms) before shuting down sm */
628 +extern spinlock_t crypto_ubicom32_lock;
629 +extern bool crypto_ubicom32_inited;
630 +extern volatile bool crypto_ubicom32_on;
631 +extern volatile unsigned long crypto_ubicom32_last_use;
632 +extern struct timer_list crypto_ubicom32_ps_timer;
633 +extern void crypto_ubicom32_ps_check(unsigned long data);
635 +#define SEC_COPY_2W(t, s) \
637 + " move.4 0(%0), 0(%1) \n\t" \
638 + " move.4 4(%0), 4(%1) \n\t" \
641 + : "a" (t), "a" (s) \
644 +#define SEC_COPY_4W(t, s) \
646 + " move.4 0(%0), 0(%1) \n\t" \
647 + " move.4 4(%0), 4(%1) \n\t" \
648 + " move.4 8(%0), 8(%1) \n\t" \
649 + " move.4 12(%0), 12(%1) \n\t" \
651 + : "a" (t), "a" (s) \
654 +#define SEC_COPY_5W(t, s) \
656 + " move.4 0(%0), 0(%1) \n\t" \
657 + " move.4 4(%0), 4(%1) \n\t" \
658 + " move.4 8(%0), 8(%1) \n\t" \
659 + " move.4 12(%0), 12(%1) \n\t" \
660 + " move.4 16(%0), 16(%1) \n\t" \
662 + : "a" (t), "a" (s) \
665 +#define SEC_SET_KEY_2W(x) \
667 + " ; write key to Security Keyblock \n\t" \
668 + " move.4 0x10(%0), 0(%1) \n\t" \
669 + " move.4 0x14(%0), 4(%1) \n\t" \
671 + : "a" (SECURITY_BASE), "a" (x) \
674 +#define SEC_SET_KEY_4W(x) \
676 + " ; write key to Security Keyblock \n\t" \
677 + " move.4 0x10(%0), 0(%1) \n\t" \
678 + " move.4 0x14(%0), 4(%1) \n\t" \
679 + " move.4 0x18(%0), 8(%1) \n\t" \
680 + " move.4 0x1c(%0), 12(%1) \n\t" \
682 + : "a"(SECURITY_BASE), "a"(x) \
685 +#define SEC_SET_KEY_6W(x) \
687 + " ; write key to Security Keyblock \n\t" \
688 + " move.4 0x10(%0), 0(%1) \n\t" \
689 + " move.4 0x14(%0), 4(%1) \n\t" \
690 + " move.4 0x18(%0), 8(%1) \n\t" \
691 + " move.4 0x1c(%0), 12(%1) \n\t" \
692 + " move.4 0x20(%0), 16(%1) \n\t" \
693 + " move.4 0x24(%0), 20(%1) \n\t" \
695 + : "a" (SECURITY_BASE), "a" (x) \
698 +#define SEC_SET_KEY_8W(x) \
700 + " ; write key to Security Keyblock \n\t" \
701 + " move.4 0x10(%0), 0(%1) \n\t" \
702 + " move.4 0x14(%0), 4(%1) \n\t" \
703 + " move.4 0x18(%0), 8(%1) \n\t" \
704 + " move.4 0x1c(%0), 12(%1) \n\t" \
705 + " move.4 0x20(%0), 16(%1) \n\t" \
706 + " move.4 0x24(%0), 20(%1) \n\t" \
707 + " move.4 0x28(%0), 24(%1) \n\t" \
708 + " move.4 0x2c(%0), 28(%1) \n\t" \
710 + : "a" (SECURITY_BASE), "a" (x) \
713 +#define SEC_SET_KEY_64(k) SEC_SET_KEY_2W(k)
714 +#define SEC_SET_KEY_128(k) SEC_SET_KEY_4W(k)
715 +#define SEC_SET_KEY_192(k) SEC_SET_KEY_6W(k)
716 +#define SEC_SET_KEY_256(k) SEC_SET_KEY_8W(k)
718 +#define DES_SET_KEY(x) SEC_SET_KEY_64(x)
719 +#define DES3_SET_KEY(x) SEC_SET_KEY_192(x)
721 +#define SEC_SET_INPUT_2W(x) \
723 + " ; write key to Security Keyblock \n\t" \
724 + " move.4 0x30(%0), 0(%1) \n\t" \
725 + " move.4 0x34(%0), 4(%1) \n\t" \
727 + : "a" (SECURITY_BASE), "a" (x) \
730 +#define SEC_GET_OUTPUT_2W(x) \
732 + " ; write key to Security Keyblock \n\t" \
733 + " move.4 0(%1), 0x50(%0) \n\t" \
734 + " move.4 4(%1), 0x54(%0) \n\t" \
736 + : "a" (SECURITY_BASE), "a" (x) \
739 +#define SEC_SET_INPUT_4W(x) \
741 + " ; write key to Security Keyblock \n\t" \
742 + " move.4 0x30(%0), 0(%1) \n\t" \
743 + " move.4 0x34(%0), 4(%1) \n\t" \
744 + " move.4 0x38(%0), 8(%1) \n\t" \
745 + " move.4 0x3c(%0), 12(%1) \n\t" \
747 + : "a" (SECURITY_BASE), "a" (x) \
750 +#define SEC_GET_OUTPUT_4W(x) \
752 + " ; read output from Security Keyblock \n\t" \
753 + " move.4 0(%1), 0x50(%0) \n\t" \
754 + " move.4 4(%1), 0x54(%0) \n\t" \
755 + " move.4 8(%1), 0x58(%0) \n\t" \
756 + " move.4 12(%1), 0x5c(%0) \n\t" \
758 + : "a" (SECURITY_BASE), "a" (x) \
761 +#define SEC_SET_IV_4W(x) \
763 + " ; write IV to Security Keyblock \n\t" \
764 + " move.4 0x50(%0), 0(%1) \n\t" \
765 + " move.4 0x54(%0), 4(%1) \n\t" \
766 + " move.4 0x58(%0), 8(%1) \n\t" \
767 + " move.4 0x5c(%0), 12(%1) \n\t" \
769 + : "a" (SECURITY_BASE), "a" (x) \
772 +#define SEC_PIPE_FLUSH() asm volatile ( " pipe_flush 0 \n\t" )
774 +static inline void hw_crypto_set_ctrl(uint32_t c)
777 + " move.4 0(%0), %1 \n\t"
779 + : "a" (SECURITY_BASE + SECURITY_CTRL), "d" (c)
783 +static inline void hw_crypto_ps_start(void)
785 + crypto_ubicom32_ps_timer.expires = jiffies + msecs_to_jiffies(HW_CRYPTO_PS_MAX_IDLE_MS >> 1);
786 + add_timer(&crypto_ubicom32_ps_timer);
789 +static inline void hw_crypto_turn_on(void)
792 + " moveai A4, %0 \n\t"
793 + " bset 0x0(A4), 0x0(A4), %1 \n\t"
796 + : "i" (OCP_BASE >> 7), "i" (GEN_CLK_PLL_SECURITY_BIT_NO)
799 + crypto_ubicom32_on = true;
802 +static inline void hw_crypto_turn_off(void)
805 + " moveai A4, %0 \n\t"
806 + " bclr 0x0(A4), 0x0(A4), %1 \n\t"
808 + : "i" (OCP_BASE >> 7), "i" (GEN_CLK_PLL_SECURITY_BIT_NO)
811 + crypto_ubicom32_on = false;
816 + * Most probably hw crypto is called in clusters and it makes no sense to turn it off
817 + * and on and waster 13 cycles every time.
819 +static inline void hw_crypto_check(void)
821 + if (likely(crypto_ubicom32_on)) {
824 + crypto_ubicom32_last_use = jiffies;
825 + hw_crypto_turn_on();
826 + hw_crypto_ps_start();
830 + * hw_crypto_ps_init
831 + * Init power save timer
833 +static inline void hw_crypto_ps_init(void)
835 + init_timer_deferrable(&crypto_ubicom32_ps_timer);
836 + crypto_ubicom32_ps_timer.function = crypto_ubicom32_ps_check;
837 + crypto_ubicom32_ps_timer.data = 0;
842 + * Initialize OCP security module lock and disables its clock.
844 +static inline void hw_crypto_init(void)
846 + if (!crypto_ubicom32_inited) {
847 + crypto_ubicom32_inited = true;
848 + spin_lock_init(&crypto_ubicom32_lock);
849 + hw_crypto_ps_init();
850 + hw_crypto_turn_off();
856 + * Locks the OCP security module and enables its clock.
858 +static inline void hw_crypto_lock(void)
860 + spin_lock_bh(&crypto_ubicom32_lock);
864 + * hw_crypto_unlock()
865 + * Unlocks the OCP security module and disables its clock.
867 +static inline void hw_crypto_unlock(void)
869 + crypto_ubicom32_last_use = jiffies;
870 + spin_unlock_bh(&crypto_ubicom32_lock);
873 +#define CONFIG_CRYPTO_UBICOM32_DEBUG 1
875 +#ifdef CONFIG_CRYPTO_UBICOM32_DEBUG
876 +static inline void hex_dump(void *buf, int b_size, const char *msg)
881 + printk("%s:\t", msg);
884 + for (i=0; i < b_size; i++) {
885 + printk("%02x ", b[i]);
886 + if ((i & 3) == 3) {
889 + if ((i & 31) == 31) {
895 +#define UBICOM32_SEC_DUMP(a, b, c) hex_dump(a, b, c)
897 +#define UBICOM32_SEC_DUMP(a, b, c)
900 +#endif /* _CRYPTO_ARCH_UBICOM32_CRYPT_H */
902 +++ b/arch/ubicom32/crypto/des_check_key.c
905 + * arch/ubicom32/crypto/des_check_key.c
906 + * Ubicom32 architecture function for checking keys for the DES and
907 + * Tripple DES Encryption algorithms.
909 + * (C) Copyright 2009, Ubicom, Inc.
911 + * Originally released as descore by Dana L. How <how@isl.stanford.edu>.
912 + * Modified by Raimar Falke <rf13@inf.tu-dresden.de> for the Linux-Kernel.
913 + * Derived from Cryptoapi and Nettle implementations, adapted for in-place
914 + * scatterlist interface. Changed LGPL to GPL per section 3 of the LGPL.
917 + * Copyright IBM Corp. 2003
918 + * Author(s): Thomas Spatzier
919 + * Jan Glauber (jan.glauber@de.ibm.com)
921 + * Derived from "crypto/des.c"
922 + * Copyright (c) 1992 Dana L. How.
923 + * Copyright (c) Raimar Falke <rf13@inf.tu-dresden.de>
924 + * Copyright (c) Gisle Sflensminde <gisle@ii.uib.no>
925 + * Copyright (C) 2001 Niels Mvller.
926 + * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
928 + * This file is part of the Ubicom32 Linux Kernel Port.
930 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
931 + * it and/or modify it under the terms of the GNU General Public License
932 + * as published by the Free Software Foundation, either version 2 of the
933 + * License, or (at your option) any later version.
935 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
936 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
937 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
938 + * the GNU General Public License for more details.
940 + * You should have received a copy of the GNU General Public License
941 + * along with the Ubicom32 Linux Kernel Port. If not,
942 + * see <http://www.gnu.org/licenses/>.
944 + * Ubicom32 implementation derived from (with many thanks):
949 +#include <linux/init.h>
950 +#include <linux/module.h>
951 +#include <linux/errno.h>
952 +#include <linux/crypto.h>
953 +#include "crypto_des.h"
955 +#define ROR(d,c,o) ((d) = (d) >> (c) | (d) << (o))
957 +static const u8 parity[] = {
958 + 8,1,0,8,0,8,8,0,0,8,8,0,8,0,2,8,0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,3,
959 + 0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,
960 + 0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,
961 + 8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,
962 + 0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,
963 + 8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,
964 + 8,0,0,8,0,8,8,0,0,8,8,0,8,0,0,8,0,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,
965 + 4,8,8,0,8,0,0,8,8,0,0,8,0,8,8,0,8,5,0,8,0,8,8,0,0,8,8,0,8,0,6,8,
969 + * RFC2451: Weak key checks SHOULD be performed.
972 +crypto_des_check_key(const u8 *key, unsigned int keylen, u32 *flags)
976 + n = parity[key[0]]; n <<= 4;
977 + n |= parity[key[1]]; n <<= 4;
978 + n |= parity[key[2]]; n <<= 4;
979 + n |= parity[key[3]]; n <<= 4;
980 + n |= parity[key[4]]; n <<= 4;
981 + n |= parity[key[5]]; n <<= 4;
982 + n |= parity[key[6]]; n <<= 4;
983 + n |= parity[key[7]];
986 + if ((*flags & CRYPTO_TFM_REQ_WEAK_KEY)
987 + && !((n - (w >> 3)) & w)) { /* 1 in 10^10 keys passes this test */
988 + if (n < 0x41415151) {
989 + if (n < 0x31312121) {
990 + if (n < 0x14141515) {
991 + /* 01 01 01 01 01 01 01 01 */
992 + if (n == 0x11111111) goto weak;
993 + /* 01 1F 01 1F 01 0E 01 0E */
994 + if (n == 0x13131212) goto weak;
996 + /* 01 E0 01 E0 01 F1 01 F1 */
997 + if (n == 0x14141515) goto weak;
998 + /* 01 FE 01 FE 01 FE 01 FE */
999 + if (n == 0x16161616) goto weak;
1002 + if (n < 0x34342525) {
1003 + /* 1F 01 1F 01 0E 01 0E 01 */
1004 + if (n == 0x31312121) goto weak;
1005 + /* 1F 1F 1F 1F 0E 0E 0E 0E (?) */
1006 + if (n == 0x33332222) goto weak;
1008 + /* 1F E0 1F E0 0E F1 0E F1 */
1009 + if (n == 0x34342525) goto weak;
1010 + /* 1F FE 1F FE 0E FE 0E FE */
1011 + if (n == 0x36362626) goto weak;
1015 + if (n < 0x61616161) {
1016 + if (n < 0x44445555) {
1017 + /* E0 01 E0 01 F1 01 F1 01 */
1018 + if (n == 0x41415151) goto weak;
1019 + /* E0 1F E0 1F F1 0E F1 0E */
1020 + if (n == 0x43435252) goto weak;
1022 + /* E0 E0 E0 E0 F1 F1 F1 F1 (?) */
1023 + if (n == 0x44445555) goto weak;
1024 + /* E0 FE E0 FE F1 FE F1 FE */
1025 + if (n == 0x46465656) goto weak;
1028 + if (n < 0x64646565) {
1029 + /* FE 01 FE 01 FE 01 FE 01 */
1030 + if (n == 0x61616161) goto weak;
1031 + /* FE 1F FE 1F FE 0E FE 0E */
1032 + if (n == 0x63636262) goto weak;
1034 + /* FE E0 FE E0 FE F1 FE F1 */
1035 + if (n == 0x64646565) goto weak;
1036 + /* FE FE FE FE FE FE FE FE */
1037 + if (n == 0x66666666) goto weak;
1044 + *flags |= CRYPTO_TFM_RES_WEAK_KEY;
1048 +EXPORT_SYMBOL(crypto_des_check_key);
1050 +MODULE_LICENSE("GPL");
1051 +MODULE_DESCRIPTION("Key Check function for DES & DES3 Cipher Algorithms");
1053 +++ b/arch/ubicom32/crypto/des_ubicom32.c
1056 + * arch/ubicom32/crypto/des_ubicom32.c
1057 + * Ubicom32 implementation of the DES Cipher Algorithm.
1059 + * (C) Copyright 2009, Ubicom, Inc.
1061 + * This file is part of the Ubicom32 Linux Kernel Port.
1063 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
1064 + * it and/or modify it under the terms of the GNU General Public License
1065 + * as published by the Free Software Foundation, either version 2 of the
1066 + * License, or (at your option) any later version.
1068 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
1069 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
1070 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
1071 + * the GNU General Public License for more details.
1073 + * You should have received a copy of the GNU General Public License
1074 + * along with the Ubicom32 Linux Kernel Port. If not,
1075 + * see <http://www.gnu.org/licenses/>.
1077 + * Ubicom32 implementation derived from (with many thanks):
1082 +#include <crypto/algapi.h>
1083 +#include <linux/init.h>
1084 +#include <linux/module.h>
1086 +#include "crypto_ubicom32.h"
1087 +extern int crypto_des_check_key(const u8 *key, unsigned int keylen, u32 *flags);
1089 +#define DES_BLOCK_SIZE 8
1090 +#define DES_KEY_SIZE 8
1092 +#define DES3_192_KEY_SIZE (3 * DES_KEY_SIZE)
1093 +#define DES3_192_BLOCK_SIZE DES_BLOCK_SIZE
1095 +#define DES3_SUB_KEY(key, i) (((u8 *)key) + (i * DES_KEY_SIZE))
1110 +struct ubicom32_des_ctx {
1111 + u8 key[3 * DES_KEY_SIZE];
1116 +static inline void des_hw_set_key(const u8 *key, u8 key_len)
1119 + * HW 3DES is not tested yet, use DES just as ipOS
1124 +static inline void des_hw_cipher(u8 *out, const u8 *in)
1126 + SEC_SET_INPUT_2W(in);
1129 + " ; start DES by writing 0x38(SECURITY_BASE) \n\t"
1130 + " move.4 0x38(%0), #0x01 \n\t"
1131 + " pipe_flush 0 \n\t"
1133 + " ; wait for the module to calculate the output \n\t"
1134 + " btst 0x04(%0), #0 \n\t"
1135 + " jmpne.f .-4 \n\t"
1141 + SEC_GET_OUTPUT_2W(out);
1145 +static void inline des3_hw_ede_encrypt(u8 *keys, u8 *out, const u8 *in)
1147 + hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_ENCRYPT);
1148 + des_hw_set_key(DES3_SUB_KEY(keys, 0), DES_KEY_SIZE);
1149 + des_hw_cipher(out, in);
1151 + hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_DECRYPT);
1152 + des_hw_set_key(DES3_SUB_KEY(keys, 1), DES_KEY_SIZE);
1153 + des_hw_cipher(out, out);
1155 + hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_ENCRYPT);
1156 + des_hw_set_key(DES3_SUB_KEY(keys, 2), DES_KEY_SIZE);
1157 + des_hw_cipher(out, out);
1160 +static void inline des3_hw_ede_decrypt(u8 *keys, u8 *out, const u8 *in)
1162 + hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_DECRYPT);
1163 + des_hw_set_key(DES3_SUB_KEY(keys, 2), DES_KEY_SIZE);
1164 + des_hw_cipher(out, in);
1166 + hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_ENCRYPT);
1167 + des_hw_set_key(DES3_SUB_KEY(keys, 1), DES_KEY_SIZE);
1168 + des_hw_cipher(out, out);
1170 + hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_DECRYPT);
1171 + des_hw_set_key(DES3_SUB_KEY(keys, 0), DES_KEY_SIZE);
1172 + des_hw_cipher(out, out);
1176 +static void inline des3_hw_eee_encrypt(u8 *keys, u8 *out, const u8 *in)
1178 + hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_ENCRYPT);
1179 + des_hw_set_key(DES3_SUB_KEY(keys, 0), 2);
1180 + des_hw_cipher(out, in);
1182 + hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_ENCRYPT);
1183 + des_hw_set_key(DES3_SUB_KEY(keys, 1), 2);
1184 + des_hw_cipher(out, out);
1186 + hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_ENCRYPT);
1187 + des_hw_set_key(DES3_SUB_KEY(keys, 2), 2);
1188 + des_hw_cipher(out, out);
1191 +static void inline des3_hw_eee_decrypt(u8 *keys, u8 *out, const u8 *in)
1193 + hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_DECRYPT);
1194 + des_hw_set_key(DES3_SUB_KEY(keys, 2), 2);
1195 + des_hw_cipher(out, in);
1197 + hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_DECRYPT);
1198 + des_hw_set_key(DES3_SUB_KEY(keys, 1), 2);
1199 + des_hw_cipher(out, out);
1201 + hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_DECRYPT);
1202 + des_hw_set_key(DES3_SUB_KEY(keys, 0), 2);
1203 + des_hw_cipher(out, out);
1207 +static int des_setkey(struct crypto_tfm *tfm, const u8 *key,
1208 + unsigned int keylen)
1210 + struct ubicom32_des_ctx *dctx = crypto_tfm_ctx(tfm);
1211 + u32 *flags = &tfm->crt_flags;
1214 + /* test if key is valid (not a weak key) */
1215 + ret = crypto_des_check_key(key, keylen, flags);
1217 + memcpy(dctx->key, key, keylen);
1218 + dctx->key_len = keylen;
1219 + //dctx->ctrl = (keylen == DES_KEY_SIZE) ? SEC_ALG_DES : SEC_ALG_3DES
1220 + /* 2DES and 3DES are both implemented with DES hw function */
1221 + dctx->ctrl = SEC_ALG_DES;
1226 +static inline void des_cipher_1b(struct crypto_tfm *tfm, u8 *out, const u8 *in, u32 extra_flags)
1228 + const struct ubicom32_des_ctx *uctx = crypto_tfm_ctx(tfm);
1231 + hw_crypto_check();
1232 + hw_crypto_set_ctrl(uctx->ctrl | extra_flags);
1234 + des_hw_set_key(uctx->key, uctx->key_len);
1235 + des_hw_cipher(out, in);
1237 + hw_crypto_unlock();
1240 +static void des_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
1242 + des_cipher_1b(tfm, out, in, SEC_DIR_ENCRYPT);
1245 +static void des_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
1247 + des_cipher_1b(tfm, out, in, SEC_DIR_DECRYPT);
1250 +static struct crypto_alg des_alg = {
1251 + .cra_name = "des",
1252 + .cra_driver_name = "des-ubicom32",
1253 + .cra_priority = CRYPTO_UBICOM32_PRIORITY,
1254 + .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
1255 + .cra_blocksize = DES_BLOCK_SIZE,
1256 + .cra_ctxsize = sizeof(struct ubicom32_des_ctx),
1257 + .cra_alignmask = CRYPTO_UBICOM32_ALIGNMENT - 1,
1258 + .cra_alignmask = CRYPTO_UBICOM32_ALIGNMENT - 1,
1259 + .cra_module = THIS_MODULE,
1260 + .cra_list = LIST_HEAD_INIT(des_alg.cra_list),
1263 + .cia_min_keysize = DES_KEY_SIZE,
1264 + .cia_max_keysize = DES_KEY_SIZE,
1265 + .cia_setkey = des_setkey,
1266 + .cia_encrypt = des_encrypt,
1267 + .cia_decrypt = des_decrypt,
1272 +static void ecb_des_ciper_loop(u8 *out, u8 *in, unsigned int n)
1274 + while (likely(n)) {
1275 + des_hw_cipher(out, in);
1276 + out += DES_BLOCK_SIZE;
1277 + in += DES_BLOCK_SIZE;
1278 + n -= DES_BLOCK_SIZE;
1282 +static void ecb_des3_ede_encrypt_loop(u8 *keys, u8 *out, u8 *in, unsigned int n)
1284 + while (likely(n)) {
1285 + des3_hw_ede_encrypt(keys, out, in);
1287 + out += DES_BLOCK_SIZE;
1288 + in += DES_BLOCK_SIZE;
1289 + n -= DES_BLOCK_SIZE;
1293 +static void ecb_des3_ede_decrypt_loop(u8 *keys, u8 *out, u8 *in, unsigned int n)
1295 + while (likely(n)) {
1296 + des3_hw_ede_decrypt(keys, out, in);
1298 + out += DES_BLOCK_SIZE;
1299 + in += DES_BLOCK_SIZE;
1300 + n -= DES_BLOCK_SIZE;
1305 +static void ecb_des3_eee_encrypt_loop(u8 *keys, u8 *out, u8 *in, unsigned int n)
1307 + while (likely(n)) {
1308 + des3_hw_eee_encrypt(keys, out, in);
1310 + out += DES_BLOCK_SIZE;
1311 + in += DES_BLOCK_SIZE;
1312 + n -= DES_BLOCK_SIZE;
1316 +static void ecb_des3_eee_decrypt_loop(u8 *keys, u8 *out, u8 *in, unsigned int n)
1318 + while (likely(n)) {
1319 + des3_hw_eee_decrypt(keys, out, in);
1321 + out += DES_BLOCK_SIZE;
1322 + in += DES_BLOCK_SIZE;
1323 + n -= DES_BLOCK_SIZE;
1328 +static inline void ecb_des_cipher_n(struct ubicom32_des_ctx *uctx, enum des_ops op, u8 *out, u8 *in, unsigned int n)
1333 + /* set the right algo, direction and key once */
1334 + hw_crypto_set_ctrl(SEC_ALG_DES | (op == DES_ENCRYPT ? SEC_DIR_ENCRYPT : 0));
1335 + des_hw_set_key(uctx->key, uctx->key_len);
1336 + ecb_des_ciper_loop(out, in, n);
1339 + case DES3_EDE_ENCRYPT:
1340 + ecb_des3_ede_encrypt_loop(uctx->key, out, in, n);
1343 + case DES3_EDE_DECRYPT:
1344 + ecb_des3_ede_decrypt_loop(uctx->key, out, in, n);
1348 + case DES3_EEE_ENCRYPT:
1349 + ecb_des3_eee_encrypt_loop(uctx->key, out, in, n);
1352 + case DES3_EEE_DECRYPT:
1353 + ecb_des3_eee_decrypt_loop(uctx->key, out, in, n);
1359 +static inline void des_xor_2w(u32 *data, u32 *iv)
1365 +static void cbc_des_encrypt_loop(u8 *out, u8 *in, u8 *iv, unsigned int n)
1367 + while (likely(n)) {
1368 + des_xor_2w((u32 *)in, (u32 *)iv);
1369 + des_hw_cipher(out, in);
1370 + SEC_COPY_2W(iv, out);
1371 + out += DES_BLOCK_SIZE;
1372 + in += DES_BLOCK_SIZE;
1373 + n -= DES_BLOCK_SIZE;
1377 +static void cbc_des_decrypt_loop(u8 *out, u8 *in, u8 *iv, unsigned int n)
1379 + u8 next_iv[DES_BLOCK_SIZE];
1380 + while (likely(n)) {
1381 + SEC_COPY_2W(next_iv, in);
1382 + des_hw_cipher(out, in);
1383 + des_xor_2w((u32 *)out, (u32 *)iv);
1384 + SEC_COPY_2W(iv, next_iv);
1386 + out += DES_BLOCK_SIZE;
1387 + in += DES_BLOCK_SIZE;
1388 + n -= DES_BLOCK_SIZE;
1392 +static void cbc_des3_ede_encrypt_loop(u8 *keys, u8 *out, u8 *in, u8 *iv, unsigned int n)
1394 + while (likely(n)) {
1395 + des_xor_2w((u32 *)in, (u32 *)iv);
1396 + des3_hw_ede_encrypt(keys, out, in);
1397 + SEC_COPY_2W(iv, out);
1399 + out += DES_BLOCK_SIZE;
1400 + in += DES_BLOCK_SIZE;
1401 + n -= DES_BLOCK_SIZE;
1405 +static void cbc_des3_ede_decrypt_loop(u8 *keys, u8 *out, u8 *in, u8 *iv, unsigned int n)
1407 + u8 next_iv[DES_BLOCK_SIZE];
1408 + while (likely(n)) {
1409 + SEC_COPY_2W(next_iv, in);
1410 + des3_hw_ede_decrypt(keys, out, in);
1411 + des_xor_2w((u32 *)out, (u32 *)iv);
1412 + SEC_COPY_2W(iv, next_iv);
1414 + out += DES_BLOCK_SIZE;
1415 + in += DES_BLOCK_SIZE;
1416 + n -= DES_BLOCK_SIZE;
1421 +static void cbc_des3_eee_encrypt_loop(u8 *keys, u8 *out, u8 *in, u8 *iv, unsigned int n)
1423 + while (likely(n)) {
1424 + des_xor_2w((u32 *)in, (u32 *)iv);
1425 + des3_hw_eee_encrypt(keys, out, in);
1426 + SEC_COPY_2W(iv, out);
1428 + out += DES_BLOCK_SIZE;
1429 + in += DES_BLOCK_SIZE;
1430 + n -= DES_BLOCK_SIZE;
1434 +static void cbc_des3_eee_decrypt_loop(u8 *keys, u8 *out, u8 *in, u8 *iv, unsigned int n)
1436 + u8 next_iv[DES_BLOCK_SIZE];
1437 + while (likely(n)) {
1438 + SEC_COPY_2W(next_iv, in);
1439 + des3_hw_eee_decrypt(keys, out, in);
1440 + des_xor_2w((u32 *)out, (u32 *)iv);
1441 + SEC_COPY_2W(iv, next_iv);
1443 + out += DES_BLOCK_SIZE;
1444 + in += DES_BLOCK_SIZE;
1445 + n -= DES_BLOCK_SIZE;
1450 +static inline void cbc_des_cipher_n(struct ubicom32_des_ctx *uctx, enum des_ops op, u8 *out, u8 *in, u8 *iv, unsigned int n)
1454 + hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_ENCRYPT);
1455 + des_hw_set_key(uctx->key, uctx->key_len);
1456 + cbc_des_encrypt_loop(out, in, iv, n);
1460 + /* set the right algo, direction and key once */
1461 + hw_crypto_set_ctrl(SEC_ALG_DES | SEC_DIR_DECRYPT);
1462 + des_hw_set_key(uctx->key, uctx->key_len);
1463 + cbc_des_decrypt_loop(out, in, iv, n);
1466 + case DES3_EDE_ENCRYPT:
1467 + cbc_des3_ede_encrypt_loop(uctx->key, out, in, iv, n);
1470 + case DES3_EDE_DECRYPT:
1471 + cbc_des3_ede_decrypt_loop(uctx->key, out, in, iv, n);
1475 + case DES3_EEE_ENCRYPT:
1476 + cbc_des3_eee_encrypt_loop(uctx->key, out, in, iv, n);
1479 + case DES3_EEE_DECRYPT:
1480 + cbc_des3_eee_decrypt_loop(uctx->key, out, in, iv, n);
1486 +static int des_cipher(struct blkcipher_desc *desc, struct scatterlist *dst,
1487 + struct scatterlist *src, unsigned int nbytes, u32 extra_flags, enum des_ops op)
1489 + struct ubicom32_des_ctx *uctx = crypto_blkcipher_ctx(desc->tfm);
1492 + struct blkcipher_walk walk;
1493 + blkcipher_walk_init(&walk, dst, src, nbytes);
1494 + ret = blkcipher_walk_virt(desc, &walk);
1500 + hw_crypto_check();
1502 + while ((nbytes = walk.nbytes)) {
1503 + /* only use complete blocks */
1504 + unsigned int n = nbytes & ~(DES_BLOCK_SIZE - 1);
1505 + u8 *out = walk.dst.virt.addr;
1506 + u8 *in = walk.src.virt.addr;
1508 + /* finish n/16 blocks */
1509 + if (extra_flags & SEC_CBC_SET) {
1510 + cbc_des_cipher_n(uctx, op, out, in, walk.iv, n);
1512 + ecb_des_cipher_n(uctx, op, out, in, n);
1515 + nbytes &= DES_BLOCK_SIZE - 1;
1516 + ret = blkcipher_walk_done(desc, &walk, nbytes);
1519 + hw_crypto_unlock();
1523 +static int ecb_des_encrypt(struct blkcipher_desc *desc,
1524 + struct scatterlist *dst, struct scatterlist *src,
1525 + unsigned int nbytes)
1527 + return des_cipher(desc, dst, src, nbytes, SEC_CBC_NONE, DES_ENCRYPT);
1530 +static int ecb_des_decrypt(struct blkcipher_desc *desc,
1531 + struct scatterlist *dst, struct scatterlist *src,
1532 + unsigned int nbytes)
1534 + return des_cipher(desc, dst, src, nbytes, SEC_CBC_NONE, DES_DECRYPT);
1537 +static struct crypto_alg ecb_des_alg = {
1538 + .cra_name = "ecb(des)",
1539 + .cra_driver_name = "ecb-des-ubicom32",
1540 + .cra_priority = CRYPTO_UBICOM32_COMPOSITE_PRIORITY,
1541 + .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
1542 + .cra_blocksize = DES_BLOCK_SIZE,
1543 + .cra_ctxsize = sizeof(struct ubicom32_des_ctx),
1544 + .cra_alignmask = CRYPTO_UBICOM32_ALIGNMENT - 1,
1545 + .cra_type = &crypto_blkcipher_type,
1546 + .cra_module = THIS_MODULE,
1547 + .cra_list = LIST_HEAD_INIT(ecb_des_alg.cra_list),
1550 + .min_keysize = DES_KEY_SIZE,
1551 + .max_keysize = DES_KEY_SIZE,
1552 + .setkey = des_setkey,
1553 + .encrypt = ecb_des_encrypt,
1554 + .decrypt = ecb_des_decrypt,
1559 +static int cbc_des_encrypt(struct blkcipher_desc *desc,
1560 + struct scatterlist *dst, struct scatterlist *src,
1561 + unsigned int nbytes)
1563 + return des_cipher(desc, dst, src, nbytes, SEC_CBC_SET, DES_ENCRYPT);
1566 +static int cbc_des_decrypt(struct blkcipher_desc *desc,
1567 + struct scatterlist *dst, struct scatterlist *src,
1568 + unsigned int nbytes)
1570 + return des_cipher(desc, dst, src, nbytes, SEC_CBC_SET, DES_DECRYPT);
1573 +static struct crypto_alg cbc_des_alg = {
1574 + .cra_name = "cbc(des)",
1575 + .cra_driver_name = "cbc-des-ubicom32",
1576 + .cra_priority = CRYPTO_UBICOM32_COMPOSITE_PRIORITY,
1577 + .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
1578 + .cra_blocksize = DES_BLOCK_SIZE,
1579 + .cra_ctxsize = sizeof(struct ubicom32_des_ctx),
1580 + .cra_alignmask = CRYPTO_UBICOM32_ALIGNMENT - 1,
1581 + .cra_type = &crypto_blkcipher_type,
1582 + .cra_module = THIS_MODULE,
1583 + .cra_list = LIST_HEAD_INIT(cbc_des_alg.cra_list),
1586 + .min_keysize = DES_KEY_SIZE,
1587 + .max_keysize = DES_KEY_SIZE,
1588 + .ivsize = DES_BLOCK_SIZE,
1589 + .setkey = des_setkey,
1590 + .encrypt = cbc_des_encrypt,
1591 + .decrypt = cbc_des_decrypt,
1599 + * For DES-EDE3, there is no known need to reject weak or
1600 + * complementation keys. Any weakness is obviated by the use of
1603 + * However, if the first two or last two independent 64-bit keys are
1604 + * equal (k1 == k2 or k2 == k3), then the DES3 operation is simply the
1605 + * same as DES. Implementers MUST reject keys that exhibit this
1609 +static int des3_192_setkey(struct crypto_tfm *tfm, const u8 *key,
1610 + unsigned int keylen)
1613 + struct ubicom32_des_ctx *dctx = crypto_tfm_ctx(tfm);
1614 + const u8 *temp_key = key;
1615 + u32 *flags = &tfm->crt_flags;
1617 + if (!(memcmp(key, &key[DES_KEY_SIZE], DES_KEY_SIZE) &&
1618 + memcmp(&key[DES_KEY_SIZE], &key[DES_KEY_SIZE * 2],
1621 + *flags |= CRYPTO_TFM_RES_BAD_KEY_SCHED;
1624 + for (i = 0; i < 3; i++, temp_key += DES_KEY_SIZE) {
1625 + ret = crypto_des_check_key(temp_key, DES_KEY_SIZE, flags);
1629 + memcpy(dctx->key, key, keylen);
1630 + dctx->ctrl = SEC_ALG_DES; //hw 3DES not working yet
1631 + dctx->key_len = keylen;
1635 +static void des3_192_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
1637 + struct ubicom32_des_ctx *uctx = crypto_tfm_ctx(tfm);
1640 + hw_crypto_check();
1642 + des3_hw_ede_encrypt(uctx->key, dst, src);
1644 + hw_crypto_unlock();
1647 +static void des3_192_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
1649 + struct ubicom32_des_ctx *uctx = crypto_tfm_ctx(tfm);
1652 + hw_crypto_check();
1654 + des3_hw_ede_decrypt(uctx->key, dst, src);
1656 + hw_crypto_unlock();
1659 +static struct crypto_alg des3_192_alg = {
1660 + .cra_name = "des3_ede",
1661 + .cra_driver_name = "des3_ede-ubicom32",
1662 + .cra_priority = CRYPTO_UBICOM32_PRIORITY,
1663 + .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
1664 + .cra_blocksize = DES3_192_BLOCK_SIZE,
1665 + .cra_ctxsize = sizeof(struct ubicom32_des_ctx),
1666 + .cra_alignmask = CRYPTO_UBICOM32_ALIGNMENT - 1,
1667 + .cra_module = THIS_MODULE,
1668 + .cra_list = LIST_HEAD_INIT(des3_192_alg.cra_list),
1671 + .cia_min_keysize = DES3_192_KEY_SIZE,
1672 + .cia_max_keysize = DES3_192_KEY_SIZE,
1673 + .cia_setkey = des3_192_setkey,
1674 + .cia_encrypt = des3_192_encrypt,
1675 + .cia_decrypt = des3_192_decrypt,
1680 +static int ecb_des3_192_encrypt(struct blkcipher_desc *desc,
1681 + struct scatterlist *dst,
1682 + struct scatterlist *src, unsigned int nbytes)
1684 + return des_cipher(desc, dst, src, nbytes, SEC_CBC_NONE, DES3_EDE_ENCRYPT);
1687 +static int ecb_des3_192_decrypt(struct blkcipher_desc *desc,
1688 + struct scatterlist *dst,
1689 + struct scatterlist *src, unsigned int nbytes)
1691 + return des_cipher(desc, dst, src, nbytes, SEC_CBC_NONE, DES3_EDE_DECRYPT);
1694 +static struct crypto_alg ecb_des3_192_alg = {
1695 + .cra_name = "ecb(des3_ede)",
1696 + .cra_driver_name = "ecb-des3_ede-ubicom32",
1697 + .cra_priority = CRYPTO_UBICOM32_COMPOSITE_PRIORITY,
1698 + .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
1699 + .cra_blocksize = DES3_192_BLOCK_SIZE,
1700 + .cra_ctxsize = sizeof(struct ubicom32_des_ctx),
1701 + .cra_alignmask = CRYPTO_UBICOM32_ALIGNMENT - 1,
1702 + .cra_type = &crypto_blkcipher_type,
1703 + .cra_module = THIS_MODULE,
1704 + .cra_list = LIST_HEAD_INIT(
1705 + ecb_des3_192_alg.cra_list),
1708 + .min_keysize = DES3_192_KEY_SIZE,
1709 + .max_keysize = DES3_192_KEY_SIZE,
1710 + .setkey = des3_192_setkey,
1711 + .encrypt = ecb_des3_192_encrypt,
1712 + .decrypt = ecb_des3_192_decrypt,
1717 +static int cbc_des3_192_encrypt(struct blkcipher_desc *desc,
1718 + struct scatterlist *dst,
1719 + struct scatterlist *src, unsigned int nbytes)
1721 + return des_cipher(desc, dst, src, nbytes, SEC_CBC_SET, DES3_EDE_ENCRYPT);
1724 +static int cbc_des3_192_decrypt(struct blkcipher_desc *desc,
1725 + struct scatterlist *dst,
1726 + struct scatterlist *src, unsigned int nbytes)
1728 + return des_cipher(desc, dst, src, nbytes, SEC_CBC_SET, DES3_EDE_DECRYPT);
1731 +static struct crypto_alg cbc_des3_192_alg = {
1732 + .cra_name = "cbc(des3_ede)",
1733 + .cra_driver_name = "cbc-des3_ede-ubicom32",
1734 + .cra_priority = CRYPTO_UBICOM32_COMPOSITE_PRIORITY,
1735 + .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
1736 + .cra_blocksize = DES3_192_BLOCK_SIZE,
1737 + .cra_ctxsize = sizeof(struct ubicom32_des_ctx),
1738 + .cra_alignmask = CRYPTO_UBICOM32_ALIGNMENT - 1,
1739 + .cra_type = &crypto_blkcipher_type,
1740 + .cra_module = THIS_MODULE,
1741 + .cra_list = LIST_HEAD_INIT(
1742 + cbc_des3_192_alg.cra_list),
1745 + .min_keysize = DES3_192_KEY_SIZE,
1746 + .max_keysize = DES3_192_KEY_SIZE,
1747 + .ivsize = DES3_192_BLOCK_SIZE,
1748 + .setkey = des3_192_setkey,
1749 + .encrypt = cbc_des3_192_encrypt,
1750 + .decrypt = cbc_des3_192_decrypt,
1755 +static int init(void)
1761 + ret = crypto_register_alg(&des_alg);
1764 + ret = crypto_register_alg(&ecb_des_alg);
1767 + ret = crypto_register_alg(&cbc_des_alg);
1771 + ret = crypto_register_alg(&des3_192_alg);
1773 + goto des3_192_err;
1774 + ret = crypto_register_alg(&ecb_des3_192_alg);
1776 + goto ecb_des3_192_err;
1777 + ret = crypto_register_alg(&cbc_des3_192_alg);
1779 + goto cbc_des3_192_err;
1785 + crypto_unregister_alg(&ecb_des3_192_alg);
1787 + crypto_unregister_alg(&des3_192_alg);
1789 + crypto_unregister_alg(&cbc_des_alg);
1791 + crypto_unregister_alg(&ecb_des_alg);
1793 + crypto_unregister_alg(&des_alg);
1798 +static void __exit fini(void)
1800 + crypto_unregister_alg(&cbc_des3_192_alg);
1801 + crypto_unregister_alg(&ecb_des3_192_alg);
1802 + crypto_unregister_alg(&des3_192_alg);
1803 + crypto_unregister_alg(&cbc_des_alg);
1804 + crypto_unregister_alg(&ecb_des_alg);
1805 + crypto_unregister_alg(&des_alg);
1811 +MODULE_ALIAS("des");
1812 +MODULE_ALIAS("des3_ede");
1814 +MODULE_LICENSE("GPL");
1815 +MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms");
1817 +++ b/arch/ubicom32/crypto/Makefile
1820 +# arch/ubicom32/crypto/Makefile
1821 +# <TODO: Replace with short file description>
1823 +# (C) Copyright 2009, Ubicom, Inc.
1825 +# This file is part of the Ubicom32 Linux Kernel Port.
1827 +# The Ubicom32 Linux Kernel Port is free software: you can redistribute
1828 +# it and/or modify it under the terms of the GNU General Public License
1829 +# as published by the Free Software Foundation, either version 2 of the
1830 +# License, or (at your option) any later version.
1832 +# The Ubicom32 Linux Kernel Port is distributed in the hope that it
1833 +# will be useful, but WITHOUT ANY WARRANTY; without even the implied
1834 +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
1835 +# the GNU General Public License for more details.
1837 +# You should have received a copy of the GNU General Public License
1838 +# along with the Ubicom32 Linux Kernel Port. If not,
1839 +# see <http://www.gnu.org/licenses/>.
1841 +# Ubicom32 implementation derived from (with many thanks):
1846 +obj-$(CONFIG_CRYPTO_UBICOM32) += crypto_ubicom32.o
1847 +obj-$(CONFIG_CRYPTO_AES_UBICOM32) += aes_ubicom32.o
1848 +obj-$(CONFIG_CRYPTO_DES_UBICOM32) += des.o
1849 +obj-$(CONFIG_CRYPTO_MD5_UBICOM32) += md5.o
1850 +obj-$(CONFIG_CRYPTO_SHA1_UBICOM32) += sha1.o
1852 +des-y := des_ubicom32.o des_check_key.o
1853 +md5-y := md5_ubicom32.o md5_ubicom32_asm.o
1854 +sha1-y := sha1_ubicom32.o
1856 +++ b/arch/ubicom32/crypto/md5_ubicom32_asm.S
1859 + * arch/ubicom32/crypto/md5_ubicom32_asm.S
1860 + * MD5 (Message Digest 5) support for Ubicom32 v3 architecture
1862 + * (C) Copyright 2009, Ubicom, Inc.
1864 + * This file is part of the Ubicom32 Linux Kernel Port.
1866 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
1867 + * it and/or modify it under the terms of the GNU General Public License
1868 + * as published by the Free Software Foundation, either version 2 of the
1869 + * License, or (at your option) any later version.
1871 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
1872 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
1873 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
1874 + * the GNU General Public License for more details.
1876 + * You should have received a copy of the GNU General Public License
1877 + * along with the Ubicom32 Linux Kernel Port. If not,
1878 + * see <http://www.gnu.org/licenses/>.
1880 + * Ubicom32 implementation derived from (with many thanks):
1887 +#include <asm/ip5000.h>
1893 +;*****************************************************************************************
1894 +; The function prototypes
1895 +;*****************************************************************************************
1896 +; void md5_ip5k_init(void)
1897 +; void md5_ip5k_transform(u32_t *data_input)
1898 +; void md5_get_digest(u32_t *digest)
1900 +;*****************************************************************************************
1902 +;*****************************************************************************************;
1903 +; data_input is the pointer to the block of data over which the digest will be calculated.
1904 +; It should be word aligned.
1906 +; digest is the pointer to the block of data into which the digest (the output) will be written.
1907 +; It should be word aligned.
1910 +;*****************************************************************************************
1912 +;*****************************************************************************************
1915 +;*****************************************************************************************
1916 +; An: Address Registers
1917 +;*****************************************************************************************
1918 +#define an_digest A3
1919 +#define an_data_input A3
1920 +#define an_security_block A4
1922 +;*****************************************************************************************
1924 +;*****************************************************************************************
1925 +#define HASH_MD5_IN0 0x01234567
1926 +#define HASH_MD5_IN1 0x89abcdef
1927 +#define HASH_MD5_IN2 0xfedcba98
1928 +#define HASH_MD5_IN3 0x76543210
1930 +#define HASH_SECURITY_BLOCK_CONTROL_INIT_NO_ENCYPTION 2
1931 +#define HASH_SECURITY_BLOCK_CONTROL_INIT_MD5 ((1 << 4) | HASH_SECURITY_BLOCK_CONTROL_INIT_NO_ENCYPTION)
1933 +;*****************************************************************************************
1934 +; Hash related defines
1935 +;*****************************************************************************************
1936 +#define hash_control 0x00(an_security_block)
1937 +#define hash_control_low 0x02(an_security_block)
1938 +#define hash_status 0x04(an_security_block)
1940 +#define hash_input_0 0x30(an_security_block)
1941 +#define hash_input_1 0x34(an_security_block)
1942 +#define hash_input_2 0x38(an_security_block)
1943 +#define hash_input_3 0x3c(an_security_block)
1944 +#define hash_input_4 0x40(an_security_block)
1946 +#define hash_output_0 0x70(an_security_block)
1947 +#define hash_output_0_low 0x72(an_security_block)
1948 +#define hash_output_1 0x74(an_security_block)
1949 +#define hash_output_1_low 0x76(an_security_block)
1950 +#define hash_output_2 0x78(an_security_block)
1951 +#define hash_output_2_low 0x7a(an_security_block)
1952 +#define hash_output_3 0x7c(an_security_block)
1953 +#define hash_output_3_low 0x7e(an_security_block)
1955 +;*****************************************************************************************
1957 +;*****************************************************************************************
1958 + ; C compiler reserves RP (A5) for return address during subroutine call.
1959 + ; Use RP to return to caller
1960 +.macro call_return_macro
1965 +;*****************************************************************************************
1966 +; void md5_ip5k_init(void)
1967 +; initialize the output registers of the hash module
1969 + ;.section .text.md5_ip5k_init,"ax",@progbits
1971 + .global _md5_ip5k_init
1972 + .func md5_ip5k_init, _md5_ip5k_init
1975 + moveai an_security_block, #SECURITY_BASE_EFFECTIVE_ADDRESS
1977 + movei hash_control, #%hi(HASH_SECURITY_BLOCK_CONTROL_INIT_MD5)
1978 + movei hash_control_low, #%lo(HASH_SECURITY_BLOCK_CONTROL_INIT_MD5)
1980 + movei hash_output_0, #%hi(HASH_MD5_IN0)
1981 + movei hash_output_0_low, #%lo(HASH_MD5_IN0)
1983 + movei hash_output_1, #%hi(HASH_MD5_IN1)
1984 + movei hash_output_1_low, #%lo(HASH_MD5_IN1)
1986 + movei hash_output_2, #%hi(HASH_MD5_IN2)
1987 + movei hash_output_2_low, #%lo(HASH_MD5_IN2)
1989 + movei hash_output_3, #%hi(HASH_MD5_IN3)
1990 + movei hash_output_3_low, #%lo(HASH_MD5_IN3)
1996 +;*****************************************************************************************
1997 +; void md5_ip5k_init_digest(u32_t *hash_input)
1998 +; initialize the output registers of the hash module
2000 + ;.section .text.md5_ip5k_init_digest,"ax",@progbits
2002 + .global _md5_ip5k_init_digest
2003 + .func md5_ip5k_init_digest, _md5_ip5k_init_digest
2005 +_md5_ip5k_init_digest:
2006 + movea an_data_input, D0
2008 + moveai an_security_block, #SECURITY_BASE_EFFECTIVE_ADDRESS
2010 + movei hash_control, #%hi(HASH_SECURITY_BLOCK_CONTROL_INIT_MD5)
2011 + movei hash_control_low, #%lo(HASH_SECURITY_BLOCK_CONTROL_INIT_MD5)
2013 + move.4 hash_output_0, (an_data_input)4++
2014 + move.4 hash_output_1, (an_data_input)4++
2015 + move.4 hash_output_2, (an_data_input)4++
2016 + move.4 hash_output_3, (an_data_input)4++
2021 +;*****************************************************************************************
2022 +; void md5_ip5k_transform(u32_t *data_input)
2023 +; performs intermediate transformation step for the hash calculation
2025 + ;.sect .text.md5_ip5k_transform,"ax",@progbits
2027 + .global _md5_ip5k_transform
2028 + .func md5_ip5k_transform, _md5_ip5k_transform
2030 +_md5_ip5k_transform:
2031 + movea an_data_input, D0
2033 + moveai an_security_block, #SECURITY_BASE_EFFECTIVE_ADDRESS
2035 + ; Write the first 128bits (16 bytes)
2036 + move.4 hash_input_0, (an_data_input)4++
2037 + move.4 hash_input_1, (an_data_input)4++
2038 + move.4 hash_input_2, (an_data_input)4++
2039 + move.4 hash_input_3, (an_data_input)4++
2040 + move.4 hash_input_4, D0
2042 + move.4 hash_input_0, (an_data_input)4++
2043 + move.4 hash_input_1, (an_data_input)4++
2044 + move.4 hash_input_2, (an_data_input)4++
2045 + move.4 hash_input_3, (an_data_input)4++
2046 + move.4 hash_input_4, D0
2048 + move.4 hash_input_0, (an_data_input)4++
2049 + move.4 hash_input_1, (an_data_input)4++
2050 + move.4 hash_input_2, (an_data_input)4++
2051 + move.4 hash_input_3, (an_data_input)4++
2052 + move.4 hash_input_4, D0
2054 + move.4 hash_input_0, (an_data_input)4++
2055 + move.4 hash_input_1, (an_data_input)4++
2056 + move.4 hash_input_2, (an_data_input)4++
2057 + move.4 hash_input_3, (an_data_input)4++
2058 + move.4 hash_input_4, D0
2062 +md5_ip5k_transform_wait:
2063 + ; wait for the module to calculate the output hash
2064 + btst hash_status, #0
2065 + jmpne.f md5_ip5k_transform_wait
2070 +;*****************************************************************************************
2071 +; void md5_ip5k_get_digest(u32_t *digest)
2072 +; Return the hash of the input data
2074 + ;.sect .text.md5_get_digest,"ax",@progbits
2076 + .global _md5_ip5k_get_digest
2077 + .func md5_ip5k_get_digest, _md5_ip5k_get_digest
2079 +_md5_ip5k_get_digest:
2080 + movea an_digest, D0
2082 + moveai an_security_block, #SECURITY_BASE_EFFECTIVE_ADDRESS
2084 + ; we have finished
2085 + move.4 0(an_digest), hash_output_0
2086 + move.4 4(an_digest), hash_output_1
2087 + move.4 8(an_digest), hash_output_2
2088 + move.4 12(an_digest), hash_output_3
2093 +++ b/arch/ubicom32/crypto/md5_ubicom32.c
2096 + * arch/ubicom32/crypto/md5_ubicom32.c
2097 + * Ubicom32 implementation of the MD5 Secure Hash Algorithm
2099 + * (C) Copyright 2009, Ubicom, Inc.
2101 + * This file is part of the Ubicom32 Linux Kernel Port.
2103 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
2104 + * it and/or modify it under the terms of the GNU General Public License
2105 + * as published by the Free Software Foundation, either version 2 of the
2106 + * License, or (at your option) any later version.
2108 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
2109 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
2110 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
2111 + * the GNU General Public License for more details.
2113 + * You should have received a copy of the GNU General Public License
2114 + * along with the Ubicom32 Linux Kernel Port. If not,
2115 + * see <http://www.gnu.org/licenses/>.
2117 + * Ubicom32 implementation derived from (with many thanks):
2122 +#include <linux/init.h>
2123 +#include <linux/module.h>
2124 +#include <linux/crypto.h>
2126 +#include "crypto_ubicom32.h"
2128 +#define MD5_DIGEST_SIZE 16
2129 +#define MD5_BLOCK_SIZE 64
2130 +#define MD5_HASH_WORDS 4
2132 +extern void _md5_ip5k_init_digest(u32_t *digest);
2133 +extern void _md5_ip5k_transform(u32_t *data_input);
2134 +extern void _md5_ip5k_get_digest(u32_t *digest);
2136 +struct ubicom32_md5_ctx {
2137 + u64 count; /* message length */
2138 + u32 state[MD5_HASH_WORDS];
2139 + u8 buf[2 * MD5_BLOCK_SIZE];
2142 +static void md5_init(struct crypto_tfm *tfm)
2144 + struct ubicom32_md5_ctx *mctx = crypto_tfm_ctx(tfm);
2145 + mctx->state[0] = 0x01234567;
2146 + mctx->state[1] = 0x89abcdef;
2147 + mctx->state[2] = 0xfedcba98;
2148 + mctx->state[3] = 0x76543210;
2153 +static inline void _md5_process(u32 *digest, const u8 *data)
2155 + _md5_ip5k_transform((u32 *)data);
2158 +static void md5_update(struct crypto_tfm *tfm, const u8 *data,
2161 + struct ubicom32_md5_ctx *mctx = crypto_tfm_ctx(tfm);
2164 + /* how much is already in the buffer? */
2165 + index = mctx->count & 0x3f;
2167 + mctx->count += len;
2169 + if (index + len < MD5_BLOCK_SIZE) {
2174 + hw_crypto_check();
2176 + /* init digest set ctrl register too */
2177 + _md5_ip5k_init_digest(mctx->state);
2179 + if (unlikely(index == 0 && SEC_ALIGNED(data))) {
2181 + while (len >= MD5_BLOCK_SIZE) {
2182 + _md5_process(mctx->state, data);
2183 + data += MD5_BLOCK_SIZE;
2184 + len -= MD5_BLOCK_SIZE;
2189 + /* process one stored block */
2191 + clen = MD5_BLOCK_SIZE - index;
2192 + memcpy(mctx->buf + index, data, clen);
2193 + _md5_process(mctx->state, mctx->buf);
2199 + if (likely(SEC_ALIGNED(data))) {
2200 + goto fast_process;
2203 + /* process as many blocks as possible */
2204 + while (len >= MD5_BLOCK_SIZE) {
2205 + memcpy(mctx->buf, data, MD5_BLOCK_SIZE);
2206 + _md5_process(mctx->state, mctx->buf);
2207 + data += MD5_BLOCK_SIZE;
2208 + len -= MD5_BLOCK_SIZE;
2212 + _md5_ip5k_get_digest(mctx->state);
2213 + hw_crypto_unlock();
2216 + /* anything left? */
2218 + memcpy(mctx->buf + index , data, len);
2221 +/* Add padding and return the message digest. */
2222 +static void md5_final(struct crypto_tfm *tfm, u8 *out)
2224 + struct ubicom32_md5_ctx *mctx = crypto_tfm_ctx(tfm);
2226 + unsigned int index, end;
2228 + /* must perform manual padding */
2229 + index = mctx->count & 0x3f;
2230 + end = (index < 56) ? MD5_BLOCK_SIZE : (2 * MD5_BLOCK_SIZE);
2232 + /* start pad with 1 */
2233 + mctx->buf[index] = 0x80;
2235 + /* pad with zeros */
2237 + memset(mctx->buf + index, 0x00, end - index - 8);
2239 + /* append message length */
2240 + bits[0] = mctx->count << 3;
2241 + bits[1] = mctx->count >> 29;
2242 + __cpu_to_le32s(bits);
2243 + __cpu_to_le32s(bits + 1);
2245 + memcpy(mctx->buf + end - 8, &bits, sizeof(bits));
2247 + /* force to use the mctx->buf and ignore the partial buf */
2248 + mctx->count = mctx->count & ~0x3f;
2249 + md5_update(tfm, mctx->buf, end);
2251 + /* copy digest to out */
2252 + memcpy(out, mctx->state, MD5_DIGEST_SIZE);
2254 + /* wipe context */
2255 + memset(mctx, 0, sizeof *mctx);
2258 +static struct crypto_alg alg = {
2259 + .cra_name = "md5",
2260 + .cra_driver_name= "md5-ubicom32",
2261 + .cra_priority = CRYPTO_UBICOM32_PRIORITY,
2262 + .cra_flags = CRYPTO_ALG_TYPE_DIGEST,
2263 + .cra_blocksize = MD5_BLOCK_SIZE,
2264 + .cra_ctxsize = sizeof(struct ubicom32_md5_ctx),
2265 + .cra_module = THIS_MODULE,
2266 + .cra_list = LIST_HEAD_INIT(alg.cra_list),
2269 + .dia_digestsize = MD5_DIGEST_SIZE,
2270 + .dia_init = md5_init,
2271 + .dia_update = md5_update,
2272 + .dia_final = md5_final,
2277 +static int __init init(void)
2280 + return crypto_register_alg(&alg);
2283 +static void __exit fini(void)
2285 + crypto_unregister_alg(&alg);
2291 +MODULE_ALIAS("md5");
2293 +MODULE_LICENSE("GPL");
2294 +MODULE_DESCRIPTION("MD5 Secure Hash Algorithm");
2296 +++ b/arch/ubicom32/crypto/sha1_ubicom32_asm.S
2299 + * arch/ubicom32/crypto/sha1_ubicom32_asm.S
2300 + * SHA1 hash support for Ubicom32 architecture V3.
2302 + * (C) Copyright 2009, Ubicom, Inc.
2304 + * This file is part of the Ubicom32 Linux Kernel Port.
2306 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
2307 + * it and/or modify it under the terms of the GNU General Public License
2308 + * as published by the Free Software Foundation, either version 2 of the
2309 + * License, or (at your option) any later version.
2311 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
2312 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
2313 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
2314 + * the GNU General Public License for more details.
2316 + * You should have received a copy of the GNU General Public License
2317 + * along with the Ubicom32 Linux Kernel Port. If not,
2318 + * see <http://www.gnu.org/licenses/>.
2320 + * Ubicom32 implementation derived from (with many thanks):
2327 +#include <asm/ip5000.h>
2333 +;*****************************************************************************************
2334 +; The function prototype
2335 +;*****************************************************************************************
2336 +; void sha1_ip5k_init(void)
2337 +; void sha1_ip5k_transform(u32_t *data_input)
2338 +; void sha1_ip5k_output(u32_t *digest)
2340 +;*****************************************************************************************
2342 +;*****************************************************************************************
2343 +; data_input is the pointer to the block of data over which the digest will be calculated.
2344 +; It should be word aligned.
2346 +; digest is the pointer to the block of data into which the digest (the output) will be written.
2347 +; It should be word aligned.
2350 +;*****************************************************************************************
2352 +;*****************************************************************************************
2355 +;*****************************************************************************************
2357 +;*****************************************************************************************
2358 +#define HASH_SHA1_IN0 0x67452301
2359 +#define HASH_SHA1_IN1 0xefcdab89
2360 +#define HASH_SHA1_IN2 0x98badcfe
2361 +#define HASH_SHA1_IN3 0x10325476
2362 +#define HASH_SHA1_IN4 0xc3d2e1f0
2364 +#define HASH_SECURITY_BLOCK_CONTROL_INIT_NO_ENCYPTION 2
2365 +#define HASH_SECURITY_BLOCK_CONTROL_INIT_SHA1 ((1 << 5) | HASH_SECURITY_BLOCK_CONTROL_INIT_NO_ENCYPTION)
2367 +;*****************************************************************************************
2368 +; An: Address Registers
2369 +;*****************************************************************************************
2370 +#define an_digest a4
2371 +#define an_data_input a4
2372 +#define an_security_block a3
2374 +;*****************************************************************************************
2375 +; Hash related defines
2376 +;*****************************************************************************************
2377 +#define hash_control 0x00(an_security_block)
2378 +#define hash_control_low 0x02(an_security_block)
2379 +#define hash_status 0x04(an_security_block)
2381 +#define hash_input_0 0x30(an_security_block)
2382 +#define hash_input_1 0x34(an_security_block)
2383 +#define hash_input_2 0x38(an_security_block)
2384 +#define hash_input_3 0x3c(an_security_block)
2385 +#define hash_input_4 0x40(an_security_block)
2387 +#define hash_output_0 0x70(an_security_block)
2388 +#define hash_output_0_low 0x72(an_security_block)
2389 +#define hash_output_1 0x74(an_security_block)
2390 +#define hash_output_1_low 0x76(an_security_block)
2391 +#define hash_output_2 0x78(an_security_block)
2392 +#define hash_output_2_low 0x7a(an_security_block)
2393 +#define hash_output_3 0x7c(an_security_block)
2394 +#define hash_output_3_low 0x7e(an_security_block)
2395 +#define hash_output_4 0x80(an_security_block)
2396 +#define hash_output_4_low 0x82(an_security_block)
2398 +;*****************************************************************************************
2400 +;*****************************************************************************************
2401 + ; C compiler reserves RP (A5) for return address during subroutine call.
2402 + ; Use RP to return to caller
2403 +.macro call_return_macro
2407 +;*****************************************************************************************
2408 +; void sha1_ip5k_init(void)
2409 +; initialize the output registers of the hash module
2411 + ;.section .text.sha1_ip5k_init,"ax",@progbits
2412 + .section .ocm_text,"ax",@progbits
2413 + .global _sha1_ip5k_init
2414 + .func sha1_ip5k_init, _sha1_ip5k_init
2417 + moveai an_security_block, #SECURITY_BASE_EFFECTIVE_ADDRESS
2419 + movei hash_control, #%hi(HASH_SECURITY_BLOCK_CONTROL_INIT_SHA1)
2420 + movei hash_control_low, #%lo(HASH_SECURITY_BLOCK_CONTROL_INIT_SHA1)
2422 + movei hash_output_0, #%hi(HASH_SHA1_IN0)
2423 + movei hash_output_0_low, #%lo(HASH_SHA1_IN0)
2425 + movei hash_output_1, #%hi(HASH_SHA1_IN1)
2426 + movei hash_output_1_low, #%lo(HASH_SHA1_IN1)
2428 + movei hash_output_2, #%hi(HASH_SHA1_IN2)
2429 + movei hash_output_2_low, #%lo(HASH_SHA1_IN2)
2431 + movei hash_output_3, #%hi(HASH_SHA1_IN3)
2432 + movei hash_output_3_low, #%lo(HASH_SHA1_IN3)
2434 + movei hash_output_4, #%hi(HASH_SHA1_IN4)
2435 + movei hash_output_4_low, #%lo(HASH_SHA1_IN4)
2440 +;*****************************************************************************************
2441 +; void sha1_ip5k_init_digest(u32_t *hash_input)
2442 +; initialize the output registers of the hash module
2444 + ;.section .text.sha1_ip5k_init_digest,"ax",@progbits
2445 + .section .ocm_text,"ax",@progbits
2446 + .global _sha1_ip5k_init_digest
2447 + .func sha1_ip5k_init_digest, _sha1_ip5k_init_digest
2449 +_sha1_ip5k_init_digest:
2450 + movea an_data_input, D0
2452 + moveai an_security_block, #SECURITY_BASE_EFFECTIVE_ADDRESS
2454 + movei hash_control, #%hi(HASH_SECURITY_BLOCK_CONTROL_INIT_SHA1)
2455 + movei hash_control_low, #%lo(HASH_SECURITY_BLOCK_CONTROL_INIT_SHA1)
2457 + move.4 hash_output_0, (an_data_input)4++
2458 + move.4 hash_output_1, (an_data_input)4++
2459 + move.4 hash_output_2, (an_data_input)4++
2460 + move.4 hash_output_3, (an_data_input)4++
2461 + move.4 hash_output_4, (an_data_input)4++
2466 +;*****************************************************************************************
2467 +; void sha1_ip5k_transform(u32_t *data_input)
2468 +; performs intermediate transformation step for the hash calculation
2470 + ;.section .text.sha1_ip5k_transform,"ax",@progbits
2471 + .section .ocm_text,"ax",@progbits
2472 + .global _sha1_ip5k_transform
2473 + .func sha1_ip5k_transform, _sha1_ip5k_transform
2475 +_sha1_ip5k_transform:
2476 + movea an_data_input, D0
2478 + moveai an_security_block, #SECURITY_BASE_EFFECTIVE_ADDRESS
2480 + ; Write the first 128bits (16 bytes)
2481 + move.4 hash_input_0, (an_data_input)4++
2482 + move.4 hash_input_1, (an_data_input)4++
2483 + move.4 hash_input_2, (an_data_input)4++
2484 + move.4 hash_input_3, (an_data_input)4++
2485 + move.4 hash_input_4, D0
2487 + move.4 hash_input_0, (an_data_input)4++
2488 + move.4 hash_input_1, (an_data_input)4++
2489 + move.4 hash_input_2, (an_data_input)4++
2490 + move.4 hash_input_3, (an_data_input)4++
2491 + move.4 hash_input_4, D0
2493 + move.4 hash_input_0, (an_data_input)4++
2494 + move.4 hash_input_1, (an_data_input)4++
2495 + move.4 hash_input_2, (an_data_input)4++
2496 + move.4 hash_input_3, (an_data_input)4++
2497 + move.4 hash_input_4, D0
2499 + move.4 hash_input_0, (an_data_input)4++
2500 + move.4 hash_input_1, (an_data_input)4++
2501 + move.4 hash_input_2, (an_data_input)4++
2502 + move.4 hash_input_3, (an_data_input)4++
2503 + move.4 hash_input_4, D0
2507 +sha1_ip5k_transform_wait:
2508 + ; wait for the module to calculate the output hash
2509 + btst hash_status, #0
2510 + jmpne.f sha1_ip5k_transform_wait
2515 +;*****************************************************************************************
2516 +; void sha1_ip5k_output(u32_t *digest)
2517 +; Return the hash of the input data
2519 + ;.section .text.sha1_ip5k_output,"ax",@progbits
2520 + .section .ocm_text,"ax",@progbits
2521 + .global _sha1_ip5k_output
2522 + .func sha1_ip5k_output, _sha1_ip5k_output
2525 + movea an_digest, D0
2527 + moveai an_security_block, #SECURITY_BASE_EFFECTIVE_ADDRESS
2529 + ; we have finished
2530 + move.4 0(an_digest), hash_output_0
2531 + move.4 4(an_digest), hash_output_1
2532 + move.4 8(an_digest), hash_output_2
2533 + move.4 12(an_digest), hash_output_3
2534 + move.4 16(an_digest), hash_output_4
2539 +;*****************************************************************************************
2540 +;END ;End of program code
2541 +;*****************************************************************************************
2543 +++ b/arch/ubicom32/crypto/sha1_ubicom32.c
2546 + * arch/ubicom32/crypto/sha1_ubicom32.c
2547 + * Ubicom32 implementation of the SHA1 Secure Hash Algorithm.
2549 + * (C) Copyright 2009, Ubicom, Inc.
2551 + * This file is part of the Ubicom32 Linux Kernel Port.
2553 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
2554 + * it and/or modify it under the terms of the GNU General Public License
2555 + * as published by the Free Software Foundation, either version 2 of the
2556 + * License, or (at your option) any later version.
2558 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
2559 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
2560 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
2561 + * the GNU General Public License for more details.
2563 + * You should have received a copy of the GNU General Public License
2564 + * along with the Ubicom32 Linux Kernel Port. If not,
2565 + * see <http://www.gnu.org/licenses/>.
2567 + * Ubicom32 implementation derived from (with many thanks):
2572 +#include <linux/init.h>
2573 +#include <linux/module.h>
2574 +#include <linux/crypto.h>
2575 +#include <crypto/sha.h>
2576 +#include <asm/linkage.h>
2578 +#include "crypto_ubicom32.h"
2579 +#define HASH_SECURITY_BLOCK_CONTROL_INIT_NO_ENCYPTION 2
2580 +#define HASH_SECURITY_BLOCK_CONTROL_INIT_SHA1 ((1 << 5) | HASH_SECURITY_BLOCK_CONTROL_INIT_NO_ENCYPTION)
2582 +struct ubicom32_sha1_ctx {
2583 + u64 count; /* message length */
2585 + u8 buf[2 * SHA1_BLOCK_SIZE];
2588 +static inline void sha1_clear_2ws(u8 *buf, int wc)
2591 + "1: move.4 (%0)4++, #0 \n\t"
2592 + " move.4 (%0)4++, #0 \n\t"
2593 + " sub.4 %1, #2, %1 \n\t"
2594 + " jmple.f 1b \n\t"
2596 + : "a" (buf), "d" (wc)
2601 +/* only wipe out count, state, and 1st half of buf - 9 bytes at most */
2602 +#define sha1_wipe_out(sctx) sha1_clear_2ws((u8 *)sctx, 2 + 5 + 16 - 2)
2604 +static inline void sha1_init_digest(u32 *digest)
2606 + hw_crypto_set_ctrl(HASH_SECURITY_BLOCK_CONTROL_INIT_SHA1);
2608 + " ; move digests to hash_output regs \n\t"
2609 + " move.4 0x70(%0), 0x0(%1) \n\t"
2610 + " move.4 0x74(%0), 0x4(%1) \n\t"
2611 + " move.4 0x78(%0), 0x8(%1) \n\t"
2612 + " move.4 0x7c(%0), 0xc(%1) \n\t"
2613 + " move.4 0x80(%0), 0x10(%1) \n\t"
2615 + : "a" (SEC_BASE), "a" (digest)
2619 +static inline void sha1_transform_feed(const u8 *in)
2622 + " ; write the 1st 16 bytes \n\t"
2623 + " move.4 0x30(%0), 0x0(%1) \n\t"
2624 + " move.4 0x34(%0), 0x4(%1) \n\t"
2625 + " move.4 0x38(%0), 0x8(%1) \n\t"
2626 + " move.4 0x3c(%0), 0xc(%1) \n\t"
2627 + " move.4 0x40(%0), %1 \n\t"
2628 + " ; write the 2nd 16 bytes \n\t"
2629 + " move.4 0x30(%0), 0x10(%1) \n\t"
2630 + " move.4 0x34(%0), 0x14(%1) \n\t"
2631 + " move.4 0x38(%0), 0x18(%1) \n\t"
2632 + " move.4 0x3c(%0), 0x1c(%1) \n\t"
2633 + " move.4 0x40(%0), %1 \n\t"
2634 + " ; write the 3rd 16 bytes \n\t"
2635 + " move.4 0x30(%0), 0x20(%1) \n\t"
2636 + " move.4 0x34(%0), 0x24(%1) \n\t"
2637 + " move.4 0x38(%0), 0x28(%1) \n\t"
2638 + " move.4 0x3c(%0), 0x2c(%1) \n\t"
2639 + " move.4 0x40(%0), %1 \n\t"
2640 + " ; write the 4th 16 bytes \n\t"
2641 + " move.4 0x30(%0), 0x30(%1) \n\t"
2642 + " move.4 0x34(%0), 0x34(%1) \n\t"
2643 + " move.4 0x38(%0), 0x38(%1) \n\t"
2644 + " move.4 0x3c(%0), 0x3c(%1) \n\t"
2645 + " move.4 0x40(%0), %1 \n\t"
2646 + " pipe_flush 0 \n\t"
2648 + : "a"(SEC_BASE), "a"(in)
2652 +static inline void sha1_transform_wait(void)
2655 + " btst 0x04(%0), #0 \n\t"
2656 + " jmpne.f -4 \n\t"
2663 +static inline void sha1_output_digest(u32 *digest)
2666 + " move.4 0x0(%1), 0x70(%0) \n\t"
2667 + " move.4 0x4(%1), 0x74(%0) \n\t"
2668 + " move.4 0x8(%1), 0x78(%0) \n\t"
2669 + " move.4 0xc(%1), 0x7c(%0) \n\t"
2670 + " move.4 0x10(%1), 0x80(%0) \n\t"
2672 + : "a" (SEC_BASE), "a" (digest)
2676 +static __ocm_text void sha1_init(struct crypto_tfm *tfm)
2678 + struct ubicom32_sha1_ctx *sctx = crypto_tfm_ctx(tfm);
2680 + sctx->state[0] = SHA1_H0;
2681 + sctx->state[1] = SHA1_H1;
2682 + sctx->state[2] = SHA1_H2;
2683 + sctx->state[3] = SHA1_H3;
2684 + sctx->state[4] = SHA1_H4;
2688 +static void __ocm_text sha1_update(struct crypto_tfm *tfm, const u8 *data,
2691 + struct ubicom32_sha1_ctx *sctx = crypto_tfm_ctx(tfm);
2694 + /* how much is already in the buffer? */
2695 + index = sctx->count & 0x3f;
2697 + sctx->count += len;
2699 + if (index + len < SHA1_BLOCK_SIZE) {
2704 + hw_crypto_check();
2706 + /* init digest set ctrl register too */
2707 + sha1_init_digest(sctx->state);
2709 + if (unlikely(index == 0 && SEC_ALIGNED(data))) {
2711 +#if CRYPTO_UBICOM32_LOOP_ASM
2712 + if (likely(len >= SHA1_BLOCK_SIZE)) {
2713 + register unsigned int cnt = len >> 6; // loop = len / 64;
2714 + sha1_transform_feed(data);
2715 + data += SHA1_BLOCK_SIZE;
2717 + /* cnt is pre-decremented in the loop */
2719 + "; while (--loop): work on 2nd block \n\t"
2720 + "1: add.4 %2, #-1, %2 \n\t"
2721 + " jmpeq.f 5f \n\t"
2723 + " ; write the 1st 16 bytes \n\t"
2724 + " move.4 0x30(%1), (%0)4++ \n\t"
2725 + " move.4 0x34(%1), (%0)4++ \n\t"
2726 + " move.4 0x38(%1), (%0)4++ \n\t"
2727 + " move.4 0x3c(%1), (%0)4++ \n\t"
2728 + " ; can not kick off hw before it \n\t"
2729 + " ; is done with the prev block \n\t"
2731 + " btst 0x04(%1), #0 \n\t"
2732 + " jmpne.f -4 \n\t"
2734 + " ; tell hw to load 1st 16 bytes \n\t"
2735 + " move.4 0x40(%1), %2 \n\t"
2737 + " ; write the 2nd 16 bytes \n\t"
2738 + " move.4 0x30(%1), (%0)4++ \n\t"
2739 + " move.4 0x34(%1), (%0)4++ \n\t"
2740 + " move.4 0x38(%1), (%0)4++ \n\t"
2741 + " move.4 0x3c(%1), (%0)4++ \n\t"
2742 + " move.4 0x40(%1), %2 \n\t"
2744 + " ; write the 3rd 16 bytes \n\t"
2745 + " move.4 0x30(%1), (%0)4++ \n\t"
2746 + " move.4 0x34(%1), (%0)4++ \n\t"
2747 + " move.4 0x38(%1), (%0)4++ \n\t"
2748 + " move.4 0x3c(%1), (%0)4++ \n\t"
2749 + " move.4 0x40(%1), %2 \n\t"
2751 + " ; write the 4th 16 bytes \n\t"
2752 + " move.4 0x30(%1), (%0)4++ \n\t"
2753 + " move.4 0x34(%1), (%0)4++ \n\t"
2754 + " move.4 0x38(%1), (%0)4++ \n\t"
2755 + " move.4 0x3c(%1), (%0)4++ \n\t"
2756 + " move.4 0x40(%1), %2 \n\t"
2758 + "; no need flush, enough insts \n\t"
2759 + "; before next hw wait \n\t"
2761 + "; go back to loop \n\t"
2764 + "; wait hw for last block \n\t"
2765 + "5: btst 0x04(%1), #0 \n\t"
2766 + " jmpne.f -4 \n\t"
2769 + : "a"( SEC_BASE), "d" (cnt)
2773 + len = len & (64 - 1);
2776 + while (likely(len >= SHA1_BLOCK_SIZE)) {
2777 + sha1_transform_feed(data);
2778 + data += SHA1_BLOCK_SIZE;
2779 + len -= SHA1_BLOCK_SIZE;
2780 + sha1_transform_wait();
2786 + /* process one stored block */
2788 + clen = SHA1_BLOCK_SIZE - index;
2789 + memcpy(sctx->buf + index, data, clen);
2790 + sha1_transform_feed(sctx->buf);
2794 + sha1_transform_wait();
2797 + if (likely(SEC_ALIGNED(data))) {
2798 + goto fast_process;
2801 + /* process as many blocks as possible */
2802 + if (likely(len >= SHA1_BLOCK_SIZE)) {
2803 + memcpy(sctx->buf, data, SHA1_BLOCK_SIZE);
2805 + sha1_transform_feed(sctx->buf);
2806 + data += SHA1_BLOCK_SIZE;
2807 + len -= SHA1_BLOCK_SIZE;
2808 + if (likely(len >= SHA1_BLOCK_SIZE)) {
2809 + memcpy(sctx->buf, data, SHA1_BLOCK_SIZE);
2810 + sha1_transform_wait();
2813 + /* it is the last block */
2814 + sha1_transform_wait();
2820 + sha1_output_digest(sctx->state);
2821 + hw_crypto_unlock();
2824 + /* anything left? */
2826 + memcpy(sctx->buf + index , data, len);
2829 +/* Add padding and return the message digest. */
2830 +static void __ocm_text sha1_final(struct crypto_tfm *tfm, u8 *out)
2832 + struct ubicom32_sha1_ctx *sctx = crypto_tfm_ctx(tfm);
2834 + unsigned int index, end;
2836 + /* must perform manual padding */
2837 + index = sctx->count & 0x3f;
2838 + end = (index < 56) ? SHA1_BLOCK_SIZE : (2 * SHA1_BLOCK_SIZE);
2840 + /* start pad with 1 */
2841 + sctx->buf[index] = 0x80;
2843 + /* pad with zeros */
2845 + memset(sctx->buf + index, 0x00, end - index - 8);
2847 + /* append message length */
2848 + bits = sctx->count << 3 ;
2849 + SEC_COPY_2W(sctx->buf + end - 8, &bits);
2851 + /* force to use the sctx->buf and ignore the partial buf */
2852 + sctx->count = sctx->count & ~0x3f;
2853 + sha1_update(tfm, sctx->buf, end);
2855 + /* copy digest to out */
2856 + SEC_COPY_5W(out, sctx->state);
2858 + /* wipe context */
2859 + sha1_wipe_out(sctx);
2862 +static struct crypto_alg alg = {
2863 + .cra_name = "sha1",
2864 + .cra_driver_name= "sha1-ubicom32",
2865 + .cra_priority = CRYPTO_UBICOM32_PRIORITY,
2866 + .cra_flags = CRYPTO_ALG_TYPE_DIGEST,
2867 + .cra_blocksize = SHA1_BLOCK_SIZE,
2868 + .cra_ctxsize = sizeof(struct ubicom32_sha1_ctx),
2869 + .cra_module = THIS_MODULE,
2870 + .cra_list = LIST_HEAD_INIT(alg.cra_list),
2873 + .dia_digestsize = SHA1_DIGEST_SIZE,
2874 + .dia_init = sha1_init,
2875 + .dia_update = sha1_update,
2876 + .dia_final = sha1_final,
2881 +static int __init init(void)
2884 + return crypto_register_alg(&alg);
2887 +static void __exit fini(void)
2889 + crypto_unregister_alg(&alg);
2895 +MODULE_ALIAS("sha1");
2897 +MODULE_LICENSE("GPL");
2898 +MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm");
2900 +++ b/arch/ubicom32/include/asm/a.out.h
2903 + * arch/ubicom32/include/asm/a.out.h
2904 + * Definitions for Ubicom32 a.out executable format.
2906 + * (C) Copyright 2009, Ubicom, Inc.
2908 + * This file is part of the Ubicom32 Linux Kernel Port.
2910 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
2911 + * it and/or modify it under the terms of the GNU General Public License
2912 + * as published by the Free Software Foundation, either version 2 of the
2913 + * License, or (at your option) any later version.
2915 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
2916 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
2917 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
2918 + * the GNU General Public License for more details.
2920 + * You should have received a copy of the GNU General Public License
2921 + * along with the Ubicom32 Linux Kernel Port. If not,
2922 + * see <http://www.gnu.org/licenses/>.
2924 + * Ubicom32 implementation derived from (with many thanks):
2929 +#ifndef _ASM_UBICOM32_A_OUT_H
2930 +#define _ASM_UBICOM32_A_OUT_H
2934 + unsigned long a_info; /* Use macros N_MAGIC, etc for access */
2935 + unsigned a_text; /* length of text, in bytes */
2936 + unsigned a_data; /* length of data, in bytes */
2937 + unsigned a_bss; /* length of uninitialized data area for file, in bytes */
2938 + unsigned a_syms; /* length of symbol table data in file, in bytes */
2939 + unsigned a_entry; /* start address */
2940 + unsigned a_trsize; /* length of relocation info for text, in bytes */
2941 + unsigned a_drsize; /* length of relocation info for data, in bytes */
2944 +#define N_TRSIZE(a) ((a).a_trsize)
2945 +#define N_DRSIZE(a) ((a).a_drsize)
2946 +#define N_SYMSIZE(a) ((a).a_syms)
2948 +#endif /* _ASM_UBICOM32_A_OUT_H */
2950 +++ b/arch/ubicom32/include/asm/atomic.h
2953 + * arch/ubicom32/include/asm/atomic.h
2954 + * Atomic operations definitions for Ubicom32 architecture.
2956 + * (C) Copyright 2009, Ubicom, Inc.
2958 + * This file is part of the Ubicom32 Linux Kernel Port.
2960 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
2961 + * it and/or modify it under the terms of the GNU General Public License
2962 + * as published by the Free Software Foundation, either version 2 of the
2963 + * License, or (at your option) any later version.
2965 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
2966 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
2967 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
2968 + * the GNU General Public License for more details.
2970 + * You should have received a copy of the GNU General Public License
2971 + * along with the Ubicom32 Linux Kernel Port. If not,
2972 + * see <http://www.gnu.org/licenses/>.
2974 + * Ubicom32 implementation derived from (with many thanks):
2979 +#ifndef _ASM_UBICOM32_ATOMIC_H
2980 +#define _ASM_UBICOM32_ATOMIC_H
2982 +#include <asm/system.h>
2983 +#include <asm/ubicom32-common.h>
2984 +#include <asm/types.h>
2987 + * Most instructions on the Ubicom32 processor are atomic in that they
2988 + * execute in one clock cycle. However, Linux has several operations
2989 + * (e.g. compare and swap) which will require more than a single instruction
2990 + * to perform. To achieve this, the Ubicom32 processor uses a single
2991 + * global bit in a scratchpad register as a critical section lock. All
2992 + * atomic operations acquire this lock.
2994 + * NOTE: To AVOID DEADLOCK(s), the atomic lock must only be used for atomic
2995 + * operations or by the ldsr to avoid disabling a thread performing an atomic
2998 + * Do not attempt to disable interrupts while holding the atomic operations
2999 + * lock or you will DEADLOCK the system.
3002 +#define ATOMIC_INIT(i) { (i) }
3006 + * Add i to v and return the result.
3008 +static inline void __atomic_add(int i, atomic_t *v)
3012 + __atomic_lock_acquire();
3014 + __atomic_lock_release();
3019 + * Subtract i from v and return the result.
3021 +static inline void __atomic_sub(int i, atomic_t *v)
3025 + __atomic_lock_acquire();
3027 + __atomic_lock_release();
3031 + * __atomic_add_return()
3032 + * Add i to v and return the result.
3034 + * The implementation here looks rather odd because we appear to be doing
3035 + * the addition twice. In fact that's exactly what we're doing but with
3036 + * the ubicom32 instruction set we can do the inner load and add with two
3037 + * instructions whereas generating both the atomic result and the "ret"
3038 + * result requires three instructions. The second add is generally only as
3039 + * costly as a move instruction and in cases where we compare the result
3040 + * with a constant the compiler can fold two constant values and do a
3041 + * single instruction, thus saving an instruction overall!
3043 + * At the worst we save one instruction inside the atomic lock.
3045 +static inline int __atomic_add_return(int i, atomic_t *v)
3050 + __atomic_lock_acquire();
3051 + ret = vt->counter;
3052 + vt->counter = ret + i;
3053 + __atomic_lock_release();
3059 + * __atomic_sub_return()
3060 + * Subtract i from v and return the result.
3062 + * The implementation here looks rather odd because we appear to be doing
3063 + * the subtraction twice. In fact that's exactly what we're doing but with
3064 + * the ubicom32 instruction set we can do the inner load and sub with two
3065 + * instructions whereas generating both the atomic result and the "ret"
3066 + * result requires three instructions. The second sub is generally only as
3067 + * costly as a move instruction and in cases where we compare the result
3068 + * with a constant the compiler can fold two constant values and do a
3069 + * single instruction, thus saving an instruction overall!
3071 + * At the worst we save one instruction inside the atomic lock.
3073 +static inline int __atomic_sub_return(int i, atomic_t *v)
3078 + __atomic_lock_acquire();
3079 + ret = vt->counter;
3080 + vt->counter = ret - i;
3081 + __atomic_lock_release();
3087 + * PUBLIC API FOR ATOMIC!
3089 +#define atomic_add(i,v) (__atomic_add( ((int)i),(v)))
3090 +#define atomic_sub(i,v) (__atomic_sub( ((int)i),(v)))
3091 +#define atomic_inc(v) (__atomic_add( 1,(v)))
3092 +#define atomic_dec(v) (__atomic_sub( 1,(v)))
3093 +#define atomic_add_return(i,v) (__atomic_add_return( ((int)i),(v)))
3094 +#define atomic_sub_return(i,v) (__atomic_sub_return( ((int)i),(v)))
3095 +#define atomic_inc_return(v) (__atomic_add_return( 1,(v)))
3096 +#define atomic_dec_return(v) (__atomic_sub_return( 1,(v)))
3097 +#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0)
3098 +#define atomic_dec_and_test(v) (atomic_dec_return(v) == 0)
3099 +#define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0)
3100 +#define atomic_sub_and_test(i,v) (atomic_sub_return((i),(v)) == 0)
3104 + * Acquire the atomic lock and read the variable.
3106 +static inline int atomic_read(const atomic_t *v)
3109 + const atomic_t *vt = v;
3111 + __atomic_lock_acquire();
3112 + ret = vt->counter;
3113 + __atomic_lock_release();
3120 + * Acquire the atomic lock and set the variable.
3122 +static inline void atomic_set(atomic_t *v, int i)
3126 + __atomic_lock_acquire();
3128 + __atomic_lock_release();
3133 + * Acquire the atomic lock and exchange if current == old.
3135 +static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
3140 + __atomic_lock_acquire();
3141 + prev = vt->counter;
3142 + if (prev == old) {
3143 + vt->counter = new;
3145 + __atomic_lock_release();
3152 + * Acquire the atomic lock and exchange values.
3154 +static inline int atomic_xchg(atomic_t *v, int new)
3159 + __atomic_lock_acquire();
3160 + prev = vt->counter;
3161 + vt->counter = new;
3162 + __atomic_lock_release();
3168 + * atomic_add_unless()
3169 + * Acquire the atomic lock and add a unless the value is u.
3171 +static inline int atomic_add_unless(atomic_t *v, int a, int u)
3176 + __atomic_lock_acquire();
3177 + prev = vt->counter;
3180 + __atomic_lock_release();
3184 + __atomic_lock_release();
3188 +#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
3190 +#include <asm-generic/atomic.h>
3193 + * The following is not a real function. The compiler should remove the function
3194 + * call as long as the user does not pass in a size that __xchg and __cmpxchg
3195 + * are not prepared for. If the user does pass in an unknown size, the user
3196 + * will get a link time error.
3198 + * The no return is to prevent a compiler error that can occur when dealing with
3199 + * uninitialized variables. Given that the function doesn't exist there is no
3200 + * net effect (and if it did it would not return).
3202 +extern void __xchg_called_with_bad_pointer(void) __attribute__((noreturn));
3206 + * Xchange *ptr for x atomically.
3208 + * Must be both locally atomic and atomic on SMP. Ubicom32 does not have an
3209 + * atomic exchange instruction so we use the global atomic_lock.
3211 +static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
3213 + unsigned long ret;
3215 + __atomic_lock_acquire();
3219 + ret = *(volatile unsigned char *)ptr;
3220 + *(volatile unsigned char *)ptr = x;
3224 + ret = *(volatile unsigned short *)ptr;
3225 + *(volatile unsigned short *)ptr = x;
3229 + ret = *(volatile unsigned int *)ptr;
3230 + *(volatile unsigned int *)ptr = x;
3234 + __xchg_called_with_bad_pointer();
3237 + __atomic_lock_release();
3241 +#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
3245 + * Compare and Xchange *ptr for x atomically.
3247 + * Must be both locally atomic and atomic on SMP. Ubicom32 does not have an
3248 + * atomic exchange instruction so we use the global atomic_lock.
3250 +static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, unsigned long next, int size)
3252 + unsigned long prev;
3254 + __atomic_lock_acquire();
3257 + prev = *(u8 *)ptr;
3258 + if (prev == old) {
3259 + *(u8 *)ptr = (u8)next;
3264 + prev = *(u16 *)ptr;
3265 + if (prev == old) {
3266 + *(u16 *)ptr = (u16)next;
3271 + prev = *(u32 *)ptr;
3272 + if (prev == old) {
3273 + *(u32 *)ptr = (u32)next;
3278 + __xchg_called_with_bad_pointer();
3281 + __atomic_lock_release();
3286 + * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
3289 +#define cmpxchg_local(ptr, o, n) \
3290 + ((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o), (unsigned long)(n), sizeof(*(ptr))))
3292 +#define cmpxchg(ptr, o, n) __cmpxchg((ptr), (o), (n), sizeof(*(ptr)))
3294 +#define smp_mb__before_atomic_inc() asm volatile ("" : : : "memory")
3295 +#define smp_mb__after_atomic_inc() asm volatile ("" : : : "memory")
3296 +#define smp_mb__before_atomic_dec() asm volatile ("" : : : "memory")
3297 +#define smp_mb__after_atomic_dec() asm volatile ("" : : : "memory")
3299 +#endif /* _ASM_UBICOM32_ATOMIC_H */
3301 +++ b/arch/ubicom32/include/asm/audio.h
3304 + * arch/ubicom32/include/asm/audio.h
3305 + * Audio include file
3307 + * (C) Copyright 2009, Ubicom, Inc.
3309 + * This file is part of the Ubicom32 Linux Kernel Port.
3311 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
3312 + * it and/or modify it under the terms of the GNU General Public License
3313 + * as published by the Free Software Foundation, either version 2 of the
3314 + * License, or (at your option) any later version.
3316 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
3317 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
3318 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
3319 + * the GNU General Public License for more details.
3321 + * You should have received a copy of the GNU General Public License
3322 + * along with the Ubicom32 Linux Kernel Port. If not,
3323 + * see <http://www.gnu.org/licenses/>.
3329 +#include <asm/devtree.h>
3330 +#include <asm/audionode.h>
3333 + * Resource indices used to access IRQs via platform_get_resource
3335 +#define AUDIO_MEM_RESOURCE 0
3336 +#define AUDIO_TX_IRQ_RESOURCE 0
3337 +#define AUDIO_RX_IRQ_RESOURCE 1
3339 +extern struct platform_device * __init audio_device_alloc(const char *driver_name, const char *node_name, const char *inst_name, int priv_size);
3341 +#define audio_device_priv(pdev) (((struct ubi32pcm_platform_data *)(((struct platform_device *)(pdev))->dev.platform_data))->priv_data)
3344 +++ b/arch/ubicom32/include/asm/audionode.h
3348 + * audionode and DMA descriptors
3350 + * Copyright
\81© 2009 Ubicom Inc. <www.ubicom.com>. All rights reserved.
3352 + * This file contains confidential information of Ubicom, Inc. and your use of
3353 + * this file is subject to the Ubicom Software License Agreement distributed with
3354 + * this file. If you are uncertain whether you are an authorized user or to report
3355 + * any unauthorized use, please contact Ubicom, Inc. at +1-408-789-2200.
3356 + * Unauthorized reproduction or distribution of this file is subject to civil and
3357 + * criminal penalties.
3360 +#ifndef _AUDIONODE_H_
3361 +#define _AUDIONODE_H_
3363 +#define AUDIO_INT_FLAG_MORE_SAMPLES 0x00000001
3364 +#define AUDIO_INT_FLAG_COMMAND 0x00000002
3367 + * Commands the Primary OS sends to the audio device
3369 +enum audio_command {
3379 + AUDIO_CMD_DISABLE,
3383 + * Flag bits passed in the registers
3385 +#define CMD_START_FLAG_LE (1 << 0) /* Use Little Endian Mode */
3388 + * Status bits that audio device can set to indicate reason
3389 + * for interrupting the Primary OS
3391 +#define AUDIO_STATUS_PLAY_DMA0_REQUEST (1 << 0) /* Audio device needs samples in DMA0 for playback */
3392 +#define AUDIO_STATUS_PLAY_DMA1_REQUEST (1 << 1) /* Audio device needs samples in DMA1 for playback */
3396 + * NOTE: The active flag shall only be SET by the producer and CLEARED
3397 + * by the consumer, NEVER the other way around. For playback, the
3398 + * Primary OS sets this flag and ipAudio clears it.
3400 + * The producer shall not modify the ptr or ctr fields when the transfer
3401 + * is marked as active, as these are used by the consumer to do the
3404 + volatile u32_t active; /* Nonzero if data in ptr/ctr ready to be transferred */
3405 + volatile void *ptr; /* Pointer to data to be transferred */
3406 + volatile u32_t ctr; /* Counter: number of data units to transfer */
3409 +#define AUDIONODE_CAP_BE (1 << 0)
3410 +#define AUDIONODE_CAP_LE (1 << 1)
3412 +#define AUDIONODE_VERSION 7
3413 +struct audio_node {
3414 + struct devtree_node dn;
3417 + * Version of this node
3422 + * Pointer to the registers
3424 + struct audio_regs *regs;
3428 + * [OCM] Audio registers
3429 + * Registers exposed as part of our MMIO area
3431 +#define AUDIO_REGS_VERSION 7
3432 +struct audio_regs {
3434 + * Version of this register set
3439 + * Interrupt status
3441 + volatile u32_t int_status;
3444 + * Interrupt request
3446 + volatile u32_t int_req;
3449 + * Current IRQ being serviced
3454 + * Maximum number of devices supported
3459 + * [DDR] Device registers for each of the devices
3461 + struct audio_dev_regs *adr;
3464 +#define AUDIO_DEV_REGS_VERSION 2
3465 +struct audio_dev_regs {
3466 + u32_t version; /* Version of this register set */
3468 + u8_t name[32]; /* Name of this driver */
3469 + u32_t caps; /* Capabilities of this driver */
3470 + const u32_t *sample_rates; /* Sample Rates supported by this driver */
3471 + u32_t n_sample_rates; /* Number of sample rates supported by this driver */
3472 + u32_t channel_mask; /* A bit set in a particular position means we support this channel configuration */
3473 + volatile u32_t int_flags; /* Reason for interrupting audio device */
3474 + volatile enum audio_command command; /* Command from Primary OS */
3475 + volatile u32_t flags; /* Flag bits for this command */
3476 + volatile u32_t channels; /* Number of channels */
3477 + volatile u32_t sample_rate; /* Sample rate */
3478 + volatile u32_t status; /* Status bits sent from ipAudio to Primary OS */
3479 + void *primary_os_buffer_ptr; /*
3480 + * Playback: Pointer to next sample to be removed from
3481 + * Primary OS sample buffer
3482 + * Capture: Pointer to where next sample will be inserted
3483 + * into Primary OS sample buffer
3487 + * These are the transfer requests. They are used in alternating
3488 + * order so that when ipAudio is processing one request, the
3489 + * Primary OS can fill in the other one.
3491 + * NOTE: The active bit shall always be SET by the producer and
3492 + * CLEARED by the consumer, NEVER the other way around.
3494 + struct audio_dma dma_xfer_requests[2];
3499 +++ b/arch/ubicom32/include/asm/auxvec.h
3502 + * arch/ubicom32/include/asm/auxvec.h
3503 + * Symbolic values for the entries in the auxiliary table
3504 + * put on the initial stack.
3506 + * (C) Copyright 2009, Ubicom, Inc.
3508 + * This file is part of the Ubicom32 Linux Kernel Port.
3510 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
3511 + * it and/or modify it under the terms of the GNU General Public License
3512 + * as published by the Free Software Foundation, either version 2 of the
3513 + * License, or (at your option) any later version.
3515 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
3516 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
3517 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
3518 + * the GNU General Public License for more details.
3520 + * You should have received a copy of the GNU General Public License
3521 + * along with the Ubicom32 Linux Kernel Port. If not,
3522 + * see <http://www.gnu.org/licenses/>.
3524 + * Ubicom32 implementation derived from (with many thanks):
3529 +#ifndef _ASM_UBICOM32_AUXVEC_H
3530 +#define _ASM_UBICOM32_AUXVEC_H
3532 +#endif /* _ASM_UBICOM32_AUXVEC_H */
3534 +++ b/arch/ubicom32/include/asm/bitops.h
3537 + * arch/ubicom32/include/asm/bitops.h
3538 + * Bit manipulation definitions for Ubicom32 architecture.
3540 + * (C) Copyright 2009, Ubicom, Inc.
3542 + * This file is part of the Ubicom32 Linux Kernel Port.
3544 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
3545 + * it and/or modify it under the terms of the GNU General Public License
3546 + * as published by the Free Software Foundation, either version 2 of the
3547 + * License, or (at your option) any later version.
3549 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
3550 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
3551 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
3552 + * the GNU General Public License for more details.
3554 + * You should have received a copy of the GNU General Public License
3555 + * along with the Ubicom32 Linux Kernel Port. If not,
3556 + * see <http://www.gnu.org/licenses/>.
3558 + * Ubicom32 implementation derived from (with many thanks):
3563 +#ifndef _ASM_UBICOM32_BITOPS_H
3564 +#define _ASM_UBICOM32_BITOPS_H
3567 + * Copyright 1992, Linus Torvalds.
3570 +#include <linux/compiler.h>
3571 +#include <asm/byteorder.h> /* swab32 */
3575 +#ifndef _LINUX_BITOPS_H
3576 +#error only <linux/bitops.h> can be included directly
3579 +#include <asm-generic/bitops/ffs.h>
3580 +#include <asm-generic/bitops/__ffs.h>
3582 +#include <asm-generic/bitops/sched.h>
3583 +#include <asm-generic/bitops/ffz.h>
3585 +#include <asm/ubicom32-common.h>
3587 +static inline void set_bit(int bit, volatile unsigned long *p)
3589 + unsigned long mask = 1UL << (bit & 31);
3593 + __atomic_lock_acquire();
3595 + __atomic_lock_release();
3598 +static inline void clear_bit(int bit, volatile unsigned long *p)
3600 + unsigned long mask = 1UL << (bit & 31);
3604 + __atomic_lock_acquire();
3606 + __atomic_lock_release();
3610 + * clear_bit() doesn't provide any barrier for the compiler.
3612 +#define smp_mb__before_clear_bit() barrier()
3613 +#define smp_mb__after_clear_bit() barrier()
3615 +static inline void change_bit(int bit, volatile unsigned long *p)
3617 + unsigned long mask = 1UL << (bit & 31);
3621 + __atomic_lock_acquire();
3623 + __atomic_lock_release();
3626 +static inline int test_and_set_bit(int bit, volatile unsigned long *p)
3629 + unsigned long mask = 1UL << (bit & 31);
3633 + __atomic_lock_acquire();
3636 + __atomic_lock_release();
3638 + return res & mask;
3641 +static inline int test_and_clear_bit(int bit, volatile unsigned long *p)
3644 + unsigned long mask = 1UL << (bit & 31);
3648 + __atomic_lock_acquire();
3651 + __atomic_lock_release();
3653 + return res & mask;
3656 +static inline int test_and_change_bit(int bit, volatile unsigned long *p)
3659 + unsigned long mask = 1UL << (bit & 31);
3663 + __atomic_lock_acquire();
3666 + __atomic_lock_release();
3668 + return res & mask;
3671 +#include <asm-generic/bitops/non-atomic.h>
3674 + * This routine doesn't need to be atomic.
3676 +static inline int __constant_test_bit(int nr, const volatile unsigned long *addr)
3678 + return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0;
3681 +static inline int __test_bit(int nr, const volatile unsigned long *addr)
3683 + int * a = (int *) addr;
3687 + mask = 1 << (nr & 0x1f);
3688 + return ((mask & *a) != 0);
3691 +#define test_bit(nr,addr) (__builtin_constant_p(nr) ? __constant_test_bit((nr),(addr)) : __test_bit((nr),(addr)))
3693 +#include <asm-generic/bitops/find.h>
3694 +#include <asm-generic/bitops/hweight.h>
3695 +#include <asm-generic/bitops/lock.h>
3697 +#include <asm-generic/bitops/ext2-non-atomic.h>
3698 +#include <asm-generic/bitops/ext2-atomic.h>
3699 +#include <asm-generic/bitops/minix.h>
3701 +#endif /* __KERNEL__ */
3703 +#include <asm-generic/bitops/fls.h>
3704 +#include <asm-generic/bitops/__fls.h>
3705 +#include <asm-generic/bitops/fls64.h>
3707 +#endif /* _ASM_UBICOM32_BITOPS_H */
3709 +++ b/arch/ubicom32/include/asm/board.h
3712 + * arch/ubicom32/include/asm/board.h
3713 + * Board init and revision definitions for Ubicom32 architecture.
3715 + * (C) Copyright 2009, Ubicom, Inc.
3717 + * This file is part of the Ubicom32 Linux Kernel Port.
3719 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
3720 + * it and/or modify it under the terms of the GNU General Public License
3721 + * as published by the Free Software Foundation, either version 2 of the
3722 + * License, or (at your option) any later version.
3724 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
3725 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
3726 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
3727 + * the GNU General Public License for more details.
3729 + * You should have received a copy of the GNU General Public License
3730 + * along with the Ubicom32 Linux Kernel Port. If not,
3731 + * see <http://www.gnu.org/licenses/>.
3733 + * Ubicom32 implementation derived from (with many thanks):
3738 +#ifndef _ASM_UBICOM32_BOARD_H
3739 +#define _ASM_UBICOM32_BOARD_H
3741 +extern const char *board_get_revision(void);
3742 +extern void __init board_init(void);
3744 +#endif /* _ASM_UBICOM32_BOARD_H */
3746 +++ b/arch/ubicom32/include/asm/bootargs.h
3749 + * arch/ubicom32/include/asm/bootargs.h
3750 + * Kernel command line via the devtree API.
3752 + * (C) Copyright 2009, Ubicom, Inc.
3754 + * This file is part of the Ubicom32 Linux Kernel Port.
3756 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
3757 + * it and/or modify it under the terms of the GNU General Public License
3758 + * as published by the Free Software Foundation, either version 2 of the
3759 + * License, or (at your option) any later version.
3761 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
3762 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
3763 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
3764 + * the GNU General Public License for more details.
3766 + * You should have received a copy of the GNU General Public License
3767 + * along with the Ubicom32 Linux Kernel Port. If not,
3768 + * see <http://www.gnu.org/licenses/>.
3770 + * Ubicom32 implementation derived from (with many thanks):
3775 +#ifndef _ASM_UBICOM32_BOOTARGS_H
3776 +#define _ASM_UBICOM32_BOOTARGS_H
3778 +extern const char *bootargs_get_cmdline(void);
3779 +extern void __init bootargs_init(void);
3781 +#endif /* _ASM_UBICOM32_BOOTARGS_H */
3783 +++ b/arch/ubicom32/include/asm/bootinfo.h
3786 + * arch/ubicom32/include/asm/bootinfo.h
3787 + * Definitions of firmware boot parameters passed to the kernel.
3789 + * (C) Copyright 2009, Ubicom, Inc.
3791 + * This file is part of the Ubicom32 Linux Kernel Port.
3793 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
3794 + * it and/or modify it under the terms of the GNU General Public License
3795 + * as published by the Free Software Foundation, either version 2 of the
3796 + * License, or (at your option) any later version.
3798 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
3799 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
3800 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
3801 + * the GNU General Public License for more details.
3803 + * You should have received a copy of the GNU General Public License
3804 + * along with the Ubicom32 Linux Kernel Port. If not,
3805 + * see <http://www.gnu.org/licenses/>.
3807 + * Ubicom32 implementation derived from (with many thanks):
3813 +#ifndef _ASM_UBICOM32_BOOTINFO_H
3814 +#define _ASM_UBICOM32_BOOTINFO_H
3816 +/* Nothing for ubicom32 */
3818 +#endif /* _ASM_UBICOM32_BOOTINFO_H */
3820 +++ b/arch/ubicom32/include/asm/bug.h
3823 + * arch/ubicom32/include/asm/bug.h
3824 + * Generic bug.h for Ubicom32 architecture.
3826 + * (C) Copyright 2009, Ubicom, Inc.
3828 + * This file is part of the Ubicom32 Linux Kernel Port.
3830 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
3831 + * it and/or modify it under the terms of the GNU General Public License
3832 + * as published by the Free Software Foundation, either version 2 of the
3833 + * License, or (at your option) any later version.
3835 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
3836 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
3837 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
3838 + * the GNU General Public License for more details.
3840 + * You should have received a copy of the GNU General Public License
3841 + * along with the Ubicom32 Linux Kernel Port. If not,
3842 + * see <http://www.gnu.org/licenses/>.
3844 + * Ubicom32 implementation derived from (with many thanks):
3849 +#ifndef _ASM_UBICOM32_BUG_H
3850 +#define _ASM_UBICOM32_BUG_H
3852 +#include <linux/kernel.h>
3853 +#include <asm/thread.h>
3855 +#if defined(CONFIG_BUG) && defined(CONFIG_STOP_ON_BUG)
3859 + * Ubicom specific version of the BUG() macro.
3861 + * This implementation performs a THREAD_STALL stopping all threads before
3862 + * calling panic. This enables a developer to see the "real" state of the
3863 + * machine (since panic alters the system state). We do the printf first
3864 + * because while it is slow, it does not alter system state (like
3867 + * TODO: Implement the trap sequence used by other architectures.
3869 +#define BUG() do { \
3870 + printk("BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \
3878 + * WARN() using printk() for now.
3880 + * TODO: Implement the trap sequence used by other architectures.
3884 + printk("WARN: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \
3889 + * Ubicom specific version of the WARN_ON macro.
3891 + * This implementation performs a printk for the WARN_ON() instead
3892 + * of faulting into the kernel and using report_bug().
3894 + * TODO: Implement the trap sequence used by other architectures.
3896 +#define WARN_ON(x) ({ \
3897 + int __ret_warn_on = !!(x); \
3898 + if (__builtin_constant_p(__ret_warn_on)) { \
3899 + if (__ret_warn_on) \
3902 + if (unlikely(__ret_warn_on)) \
3905 + unlikely(__ret_warn_on); \
3909 +#define HAVE_ARCH_BUG
3910 +#define HAVE_ARCH_WARN_ON
3914 +#include <asm-generic/bug.h>
3916 +#endif /* _ASM_UBICOM32_BUG_H */
3918 +++ b/arch/ubicom32/include/asm/bugs.h
3921 + * arch/ubicom32/include/asm/bugs.h
3922 + * Definition of check_bugs() for Ubicom32 architecture.
3924 + * (C) Copyright 2009, Ubicom, Inc.
3925 + * Copyright (C) 1994 Linus Torvalds
3927 + * This file is part of the Ubicom32 Linux Kernel Port.
3929 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
3930 + * it and/or modify it under the terms of the GNU General Public License
3931 + * as published by the Free Software Foundation, either version 2 of the
3932 + * License, or (at your option) any later version.
3934 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
3935 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
3936 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
3937 + * the GNU General Public License for more details.
3939 + * You should have received a copy of the GNU General Public License
3940 + * along with the Ubicom32 Linux Kernel Port. If not,
3941 + * see <http://www.gnu.org/licenses/>.
3943 + * Ubicom32 implementation derived from (with many thanks):
3950 + * This is included by init/main.c to check for architecture-dependent bugs.
3953 + * void check_bugs(void);
3956 +#ifndef _ASM_UBICOM32_BUGS_H
3957 +#define _ASM_UBICOM32_BUGS_H
3959 +static void check_bugs(void)
3963 +#endif /* _ASM_UBICOM32_BUGS_H */
3965 +++ b/arch/ubicom32/include/asm/byteorder.h
3968 + * arch/ubicom32/include/asm/byteorder.h
3969 + * Byte order swapping utility routines.
3971 + * (C) Copyright 2009, Ubicom, Inc.
3973 + * This file is part of the Ubicom32 Linux Kernel Port.
3975 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
3976 + * it and/or modify it under the terms of the GNU General Public License
3977 + * as published by the Free Software Foundation, either version 2 of the
3978 + * License, or (at your option) any later version.
3980 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
3981 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
3982 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
3983 + * the GNU General Public License for more details.
3985 + * You should have received a copy of the GNU General Public License
3986 + * along with the Ubicom32 Linux Kernel Port. If not,
3987 + * see <http://www.gnu.org/licenses/>.
3989 + * Ubicom32 implementation derived from (with many thanks):
3994 +#ifndef _ASM_UBICOM32_BYTEORDER_H
3995 +#define _ASM_UBICOM32_BYTEORDER_H
3997 +#include <linux/byteorder/big_endian.h>
3999 +#endif /* _ASM_UBICOM32_BYTEORDER_H */
4001 +++ b/arch/ubicom32/include/asm/cachectl.h
4004 + * arch/ubicom32/include/asm/cachectl.h
4005 + * Ubicom32 cache control definitions.
4007 + * (C) Copyright 2009, Ubicom, Inc.
4009 + * This file is part of the Ubicom32 Linux Kernel Port.
4011 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4012 + * it and/or modify it under the terms of the GNU General Public License
4013 + * as published by the Free Software Foundation, either version 2 of the
4014 + * License, or (at your option) any later version.
4016 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4017 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4018 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
4019 + * the GNU General Public License for more details.
4021 + * You should have received a copy of the GNU General Public License
4022 + * along with the Ubicom32 Linux Kernel Port. If not,
4023 + * see <http://www.gnu.org/licenses/>.
4025 + * Ubicom32 implementation derived from (with many thanks):
4030 +#ifndef _ASM_UBICOM32_CACHECTL_H
4031 +#define _ASM_UBICOM32_CACHECTL_H
4033 +#include <asm/ip5000.h>
4036 + * mem_cache_control()
4037 + * Special cache control operation
4039 +extern void mem_cache_control(unsigned long cc, unsigned long begin_addr, unsigned long end_addr, unsigned long op);
4041 +#endif /* _ASM_UBICOM32_CACHECTL_H */
4043 +++ b/arch/ubicom32/include/asm/cacheflush.h
4046 + * arch/ubicom32/include/asm/cacheflush.h
4047 + * Cache flushing definitions for Ubicom32 architecture.
4049 + * (C) Copyright 2009, Ubicom, Inc.
4051 + * This file is part of the Ubicom32 Linux Kernel Port.
4053 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4054 + * it and/or modify it under the terms of the GNU General Public License
4055 + * as published by the Free Software Foundation, either version 2 of the
4056 + * License, or (at your option) any later version.
4058 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4059 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4060 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
4061 + * the GNU General Public License for more details.
4063 + * You should have received a copy of the GNU General Public License
4064 + * along with the Ubicom32 Linux Kernel Port. If not,
4065 + * see <http://www.gnu.org/licenses/>.
4067 + * Ubicom32 implementation derived from (with many thanks):
4072 +#ifndef _ASM_UBICOM32_CACHEFLUSH_H
4073 +#define _ASM_UBICOM32_CACHEFLUSH_H
4076 + * (C) Copyright 2000-2004, Greg Ungerer <gerg@snapgear.com>
4078 +#include <linux/mm.h>
4079 +#include <asm/cachectl.h>
4080 +#include <asm/ip5000.h>
4082 +#define flush_cache_all() __flush_cache_all()
4083 +#define flush_cache_mm(mm) do { } while (0)
4084 +#define flush_cache_dup_mm(mm) do { } while (0)
4085 +#define flush_cache_range(vma, start, end) __flush_cache_all()
4086 +#define flush_cache_page(vma, vmaddr) do { } while (0)
4087 +#define flush_dcache_page(page) do { } while (0)
4088 +#define flush_dcache_mmap_lock(mapping) do { } while (0)
4089 +#define flush_dcache_mmap_unlock(mapping) do { } while (0)
4091 +#define flush_dcache_range(start, end) \
4093 + /* Flush the data cache and invalidate the I cache. */ \
4094 + mem_cache_control(DCCR_BASE, start, end, CCR_CTRL_FLUSH_ADDR); \
4095 + mem_cache_control(ICCR_BASE, start, end, CCR_CTRL_INV_ADDR); \
4098 +#define flush_icache_range(start, end) \
4100 + /* Flush the data cache and invalidate the I cache. */ \
4101 + mem_cache_control(DCCR_BASE, start, end, CCR_CTRL_FLUSH_ADDR); \
4102 + mem_cache_control(ICCR_BASE, start, end, CCR_CTRL_INV_ADDR); \
4105 +#define flush_icache_page(vma,pg) do { } while (0)
4106 +#define flush_icache_user_range(vma,pg,adr,len) do { } while (0)
4107 +#define flush_cache_vmap(start, end) do { } while (0)
4108 +#define flush_cache_vunmap(start, end) do { } while (0)
4110 +#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
4111 + memcpy(dst, src, len)
4112 +#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
4113 + memcpy(dst, src, len)
4116 + * Cache handling for IP5000
4118 +extern inline void mem_cache_invalidate_all(unsigned long cc)
4120 + if (cc == DCCR_BASE)
4121 + UBICOM32_LOCK(DCCR_LOCK_BIT);
4123 + UBICOM32_LOCK(ICCR_LOCK_BIT);
4126 + " bset "D(CCR_CTRL)"(%0), "D(CCR_CTRL)"(%0), #"D(CCR_CTRL_RESET)" \n\t"
4128 + " bclr "D(CCR_CTRL)"(%0), "D(CCR_CTRL)"(%0), #"D(CCR_CTRL_RESET)" \n\t"
4129 + " pipe_flush 0 \n\t"
4135 + if (cc == DCCR_BASE)
4136 + UBICOM32_UNLOCK(DCCR_LOCK_BIT);
4138 + UBICOM32_UNLOCK(ICCR_LOCK_BIT);
4142 +static inline void __flush_cache_all(void)
4147 + mem_cache_invalidate_all(ICCR_BASE);
4152 + mem_cache_invalidate_all(DCCR_BASE);
4155 +#endif /* _ASM_UBICOM32_CACHEFLUSH_H */
4157 +++ b/arch/ubicom32/include/asm/cache.h
4160 + * arch/ubicom32/include/asm/cache.h
4161 + * Cache line definitions for Ubicom32 architecture.
4163 + * (C) Copyright 2009, Ubicom, Inc.
4165 + * This file is part of the Ubicom32 Linux Kernel Port.
4167 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4168 + * it and/or modify it under the terms of the GNU General Public License
4169 + * as published by the Free Software Foundation, either version 2 of the
4170 + * License, or (at your option) any later version.
4172 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4173 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4174 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
4175 + * the GNU General Public License for more details.
4177 + * You should have received a copy of the GNU General Public License
4178 + * along with the Ubicom32 Linux Kernel Port. If not,
4179 + * see <http://www.gnu.org/licenses/>.
4181 + * Ubicom32 implementation derived from (with many thanks):
4186 +#ifndef _ASM_UBICOM32_CACHE_H
4187 +#define _ASM_UBICOM32_CACHE_H
4190 + * bytes per L1 cache line
4192 +#define L1_CACHE_SHIFT 5
4193 +#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
4195 +#define __cacheline_aligned
4196 +#define ____cacheline_aligned
4198 +#endif /* _ASM_UBICOM32_CACHE_H */
4200 +++ b/arch/ubicom32/include/asm/checksum.h
4203 + * arch/ubicom32/include/asm/checksum.h
4204 + * Checksum utilities for Ubicom32 architecture.
4206 + * (C) Copyright 2009, Ubicom, Inc.
4208 + * This file is part of the Ubicom32 Linux Kernel Port.
4210 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4211 + * it and/or modify it under the terms of the GNU General Public License
4212 + * as published by the Free Software Foundation, either version 2 of the
4213 + * License, or (at your option) any later version.
4215 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4216 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4217 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
4218 + * the GNU General Public License for more details.
4220 + * You should have received a copy of the GNU General Public License
4221 + * along with the Ubicom32 Linux Kernel Port. If not,
4222 + * see <http://www.gnu.org/licenses/>.
4224 + * Ubicom32 implementation derived from (with many thanks):
4229 +#ifndef _ASM_UBICOM32_CHECKSUM_H
4230 +#define _ASM_UBICOM32_CHECKSUM_H
4232 +#include <linux/in6.h>
4235 + * computes the checksum of a memory block at buff, length len,
4236 + * and adds in "sum" (32-bit)
4238 + * returns a 32-bit number suitable for feeding into itself
4239 + * or csum_tcpudp_magic
4241 + * this function must be called with even lengths, except
4242 + * for the last fragment, which may be odd
4244 + * it's best to have buff aligned on a 32-bit boundary
4246 +__wsum csum_partial(const void *buff, int len, __wsum sum);
4249 + * the same as csum_partial, but copies from src while it
4252 + * here even more important to align src and dst on a 32-bit (or even
4253 + * better 64-bit) boundary
4256 +__wsum csum_partial_copy_nocheck(const void *src, void *dst,
4257 + int len, __wsum sum);
4261 + * the same as csum_partial_copy, but copies from user space.
4263 + * here even more important to align src and dst on a 32-bit (or even
4264 + * better 64-bit) boundary
4267 +extern __wsum csum_partial_copy_from_user(const void __user *src,
4268 + void *dst, int len, __wsum sum, int *csum_err);
4270 +__sum16 ip_fast_csum(const void *iph, unsigned int ihl);
4273 + * Fold a partial checksum
4276 +static inline __sum16 csum_fold(__wsum sum)
4279 + " lsr.4 d15, %0, #16 \n\t"
4280 + " bfextu %0, %0, #16 \n\t"
4281 + " add.4 %0, d15, %0 \n\t"
4282 + " lsr.4 d15, %0, #16 \n\t"
4283 + " bfextu %0, %0, #16 \n\t"
4284 + " add.4 %0, d15, %0 \n\t"
4289 + return (__force __sum16)~sum;
4294 + * computes the checksum of the TCP/UDP pseudo-header
4295 + * returns a 16-bit checksum, already complemented
4298 +static inline __wsum
4299 +csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
4300 + unsigned short proto, __wsum sum)
4303 + " add.4 %0, %2, %0 \n\t"
4304 + " addc %0, %3, %0 \n\t"
4305 + " addc %0, %4, %0 \n\t"
4306 + " addc %0, %5, %0 \n\t"
4307 + " addc %0, #0, %0 \n\t"
4309 + : "0"(sum), "r" (saddr), "r" (daddr), "r" (len), "r"(proto)
4314 +static inline __sum16
4315 +csum_tcpudp_magic(__be32 saddr, __be32 daddr, unsigned short len,
4316 + unsigned short proto, __wsum sum)
4318 + return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
4322 + * this routine is used for miscellaneous IP-like checksums, mainly
4325 +extern __sum16 ip_compute_csum(const void *buff, int len);
4327 +#define _HAVE_ARCH_IPV6_CSUM
4329 +static __inline__ __sum16
4330 +csum_ipv6_magic(const struct in6_addr *saddr, const struct in6_addr *daddr,
4331 + __u32 len, unsigned short proto, __wsum sum)
4334 + " add.4 %0, 0(%2), %0 \n\t"
4335 + " addc %0, 4(%2), %0 \n\t"
4336 + " addc %0, 8(%2), %0 \n\t"
4337 + " addc %0, 12(%2), %0 \n\t"
4338 + " addc %0, 0(%3), %0 \n\t"
4339 + " addc %0, 4(%3), %0 \n\t"
4340 + " addc %0, 8(%3), %0 \n\t"
4341 + " addc %0, 12(%3), %0 \n\t"
4342 + " addc %0, %4, %0 \n\t"
4343 + " addc %0, #0, %0 \n\t"
4345 + : "0" (sum), "a" (saddr), "a" (daddr), "d" (len + proto)
4347 + return csum_fold(sum);
4350 +#endif /* _ASM_UBICOM32_CHECKSUM_H */
4352 +++ b/arch/ubicom32/include/asm/cpu.h
4355 + * arch/ubicom32/include/asm/cpu.h
4356 + * CPU definitions for Ubicom32 architecture.
4358 + * (C) Copyright 2009, Ubicom, Inc.
4359 + * Copyright (C) 2004-2005 ARM Ltd.
4361 + * This file is part of the Ubicom32 Linux Kernel Port.
4363 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4364 + * it and/or modify it under the terms of the GNU General Public License
4365 + * as published by the Free Software Foundation, either version 2 of the
4366 + * License, or (at your option) any later version.
4368 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4369 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4370 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
4371 + * the GNU General Public License for more details.
4373 + * You should have received a copy of the GNU General Public License
4374 + * along with the Ubicom32 Linux Kernel Port. If not,
4375 + * see <http://www.gnu.org/licenses/>.
4377 + * Ubicom32 implementation derived from (with many thanks):
4382 +#ifndef _ASM_UBICOM32_CPU_H
4383 +#define _ASM_UBICOM32_CPU_H
4385 +#include <linux/percpu.h>
4387 +struct cpuinfo_ubicom32 {
4388 + unsigned long tid; /* Hardware thread number */
4391 + volatile unsigned long ipi_pending; /* Bit map of operations to execute */
4392 + unsigned long ipi_count; /* Number of IPI(s) taken on this cpu */
4396 +DECLARE_PER_CPU(struct cpuinfo_ubicom32, cpu_data);
4398 +#endif /* _ASM_UBICOM32_CPU_H */
4400 +++ b/arch/ubicom32/include/asm/cputime.h
4403 + * arch/ubicom32/include/asm/cputime.h
4404 + * Generic cputime.h for Ubicom32 architecture.
4406 + * (C) Copyright 2009, Ubicom, Inc.
4408 + * This file is part of the Ubicom32 Linux Kernel Port.
4410 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4411 + * it and/or modify it under the terms of the GNU General Public License
4412 + * as published by the Free Software Foundation, either version 2 of the
4413 + * License, or (at your option) any later version.
4415 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4416 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4417 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
4418 + * the GNU General Public License for more details.
4420 + * You should have received a copy of the GNU General Public License
4421 + * along with the Ubicom32 Linux Kernel Port. If not,
4422 + * see <http://www.gnu.org/licenses/>.
4424 + * Ubicom32 implementation derived from (with many thanks):
4429 +#ifndef _ASM_UBICOM32_CPUTIME_H
4430 +#define _ASM_UBICOM32_CPUTIME_H
4432 +#include <asm-generic/cputime.h>
4434 +#endif /* _ASM_UBICOM32_CPUTIME_H */
4436 +++ b/arch/ubicom32/include/asm/current.h
4439 + * arch/ubicom32/include/asm/current.h
4440 + * Definition of get_current() for Ubicom32 architecture.
4442 + * (C) Copyright 2009, Ubicom, Inc.
4443 + * (C) Copyright 2000, Lineo, David McCullough <davidm@uclinux.org>
4444 + * (C) Copyright 2002, Greg Ungerer (gerg@snapgear.com)
4446 + * This file is part of the Ubicom32 Linux Kernel Port.
4448 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4449 + * it and/or modify it under the terms of the GNU General Public License
4450 + * as published by the Free Software Foundation, either version 2 of the
4451 + * License, or (at your option) any later version.
4453 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4454 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4455 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
4456 + * the GNU General Public License for more details.
4458 + * You should have received a copy of the GNU General Public License
4459 + * along with the Ubicom32 Linux Kernel Port. If not,
4460 + * see <http://www.gnu.org/licenses/>.
4462 + * Ubicom32 implementation derived from (with many thanks):
4467 +#ifndef _ASM_UBICOM32_CURRENT_H
4468 +#define _ASM_UBICOM32_CURRENT_H
4470 +#include <linux/thread_info.h>
4472 +struct task_struct;
4474 +static inline struct task_struct *get_current(void)
4476 + return(current_thread_info()->task);
4479 +#define current get_current()
4481 +#endif /* _ASM_UBICOM32_CURRENT_H */
4483 +++ b/arch/ubicom32/include/asm/delay.h
4486 + * arch/ubicom32/include/asm/delay.h
4487 + * Definition of delay routines for Ubicom32 architecture.
4489 + * (C) Copyright 2009, Ubicom, Inc.
4491 + * This file is part of the Ubicom32 Linux Kernel Port.
4493 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4494 + * it and/or modify it under the terms of the GNU General Public License
4495 + * as published by the Free Software Foundation, either version 2 of the
4496 + * License, or (at your option) any later version.
4498 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4499 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4500 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
4501 + * the GNU General Public License for more details.
4503 + * You should have received a copy of the GNU General Public License
4504 + * along with the Ubicom32 Linux Kernel Port. If not,
4505 + * see <http://www.gnu.org/licenses/>.
4507 + * Ubicom32 implementation derived from (with many thanks):
4512 +#ifndef _ASM_UBICOM32_DELAY_H
4513 +#define _ASM_UBICOM32_DELAY_H
4515 +#include <asm/param.h>
4516 +#include <asm/ip5000.h>
4518 +static inline void __delay(unsigned long loops)
4525 + "1: add.4 %0, #-1, %0 \n\t"
4526 + " jmpne.t 1b \n\t"
4532 + * Ubicom32 processor uses fixed 12MHz external OSC.
4533 + * So we use that as reference to count 12 cycles/us
4536 +extern unsigned long loops_per_jiffy;
4538 +static inline void _udelay(unsigned long usecs)
4540 +#if defined(CONFIG_UBICOM32_V4) || defined(CONFIG_UBICOM32_V3)
4542 + " add.4 d15, 0(%0), %1 \n\t"
4543 + " sub.4 #0, 0(%0), d15 \n\t"
4544 + " jmpmi.w.f .-4 \n\t"
4546 + : "a"(TIMER_BASE + TIMER_MPTVAL), "d"(usecs * (12000000/1000000))
4555 + * Moved the udelay() function into library code, no longer inlined.
4557 +extern void udelay(unsigned long usecs);
4559 +#endif /* _ASM_UBICOM32_DELAY_H */
4561 +++ b/arch/ubicom32/include/asm/device.h
4564 + * arch/ubicom32/include/asm/device.h
4565 + * Generic device.h for Ubicom32 architecture.
4567 + * Used for arch specific extensions to struct device
4569 + * (C) Copyright 2009, Ubicom, Inc.
4571 + * This file is part of the Ubicom32 Linux Kernel Port.
4573 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4574 + * it and/or modify it under the terms of the GNU General Public License
4575 + * as published by the Free Software Foundation, either version 2 of the
4576 + * License, or (at your option) any later version.
4578 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4579 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4580 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
4581 + * the GNU General Public License for more details.
4583 + * You should have received a copy of the GNU General Public License
4584 + * along with the Ubicom32 Linux Kernel Port. If not,
4585 + * see <http://www.gnu.org/licenses/>.
4587 + * Ubicom32 implementation derived from (with many thanks):
4592 +#ifndef _ASM_UBICOM32_DEVICE_H
4593 +#define _ASM_UBICOM32_DEVICE_H
4595 +#include <asm-generic/device.h>
4597 +#endif /* _ASM_UBICOM32_DEVICE_H */
4599 +++ b/arch/ubicom32/include/asm/devtree.h
4602 + * arch/ubicom32/include/asm/devtree.h
4603 + * Device Tree Header File (Shared between ultra and the Host OS)
4605 + * (C) Copyright 2009, Ubicom, Inc.
4607 + * This file is part of the Ubicom32 Linux Kernel Port.
4609 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4610 + * it and/or modify it under the terms of the GNU General Public License
4611 + * as published by the Free Software Foundation, either version 2 of the
4612 + * License, or (at your option) any later version.
4614 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4615 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4616 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
4617 + * the GNU General Public License for more details.
4619 + * You should have received a copy of the GNU General Public License
4620 + * along with the Ubicom32 Linux Kernel Port. If not,
4621 + * see <http://www.gnu.org/licenses/>.
4623 + * Ubicom32 implementation derived from (with many thanks):
4629 +#ifndef _ASM_UBICOM32_DEVTREE_H
4630 +#define _ASM_UBICOM32_DEVTREE_H
4632 +#define DEVTREE_MAX_NAME 32
4633 +#define DEVTREE_IRQ_NONE 0xff
4634 +#define DEVTREE_IRQ_DONTCARE 0xff
4635 +#define DEVTREE_NODE_MAGIC 0x10203040
4637 +struct devtree_node {
4638 + struct devtree_node *next;
4639 + unsigned char sendirq;
4640 + unsigned char recvirq;
4641 + char name[DEVTREE_MAX_NAME];
4642 + unsigned int magic;
4645 +extern struct devtree_node *devtree;
4646 +extern struct devtree_node *devtree_find_by_irq(uint8_t sendirq, uint8_t recvirq);
4647 +extern struct devtree_node *devtree_find_node(const char *str);
4648 +extern struct devtree_node *devtree_find_next(struct devtree_node **cur);
4649 +extern int devtree_irq(struct devtree_node *dn, unsigned char *sendirq, unsigned char *recvirq);
4650 +extern void devtree_print(void);
4652 +#endif /* _ASM_UBICOM32_DEVTREE_H */
4654 +++ b/arch/ubicom32/include/asm/div64.h
4657 + * arch/ubicom32/include/asm/div64.h
4658 + * Generic div64.h for Ubicom32 architecture.
4660 + * (C) Copyright 2009, Ubicom, Inc.
4662 + * This file is part of the Ubicom32 Linux Kernel Port.
4664 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4665 + * it and/or modify it under the terms of the GNU General Public License
4666 + * as published by the Free Software Foundation, either version 2 of the
4667 + * License, or (at your option) any later version.
4669 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4670 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4671 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
4672 + * the GNU General Public License for more details.
4674 + * You should have received a copy of the GNU General Public License
4675 + * along with the Ubicom32 Linux Kernel Port. If not,
4676 + * see <http://www.gnu.org/licenses/>.
4678 + * Ubicom32 implementation derived from (with many thanks):
4683 +#ifndef _ASM_UBICOM32_DIV64_H
4684 +#define _ASM_UBICOM32_DIV64_H
4686 +#include <asm-generic/div64.h>
4688 +#endif /* _ASM_UBICOM32_DIV64_H */
4690 +++ b/arch/ubicom32/include/asm/dma.h
4693 + * arch/ubicom32/include/asm/dma.h
4694 + * DMA definitions for Ubicom32 architecture.
4696 + * (C) Copyright 2009, Ubicom, Inc.
4698 + * This file is part of the Ubicom32 Linux Kernel Port.
4700 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4701 + * it and/or modify it under the terms of the GNU General Public License
4702 + * as published by the Free Software Foundation, either version 2 of the
4703 + * License, or (at your option) any later version.
4705 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4706 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4707 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
4708 + * the GNU General Public License for more details.
4710 + * You should have received a copy of the GNU General Public License
4711 + * along with the Ubicom32 Linux Kernel Port. If not,
4712 + * see <http://www.gnu.org/licenses/>.
4714 + * Ubicom32 implementation derived from (with many thanks):
4719 +#ifndef _ASM_UBICOM32_DMA_H
4720 +#define _ASM_UBICOM32_DMA_H
4722 +/* Nothing so far */
4723 +#define MAX_DMA_ADDRESS 0x00 /* This is quite suspicious */
4725 +#endif /* _ASM_UBICOM32_DMA_H */
4727 +++ b/arch/ubicom32/include/asm/dma-mapping.h
4730 + * arch/ubicom32/include/asm/dma-mapping.h
4731 + * Generic dma-mapping.h for Ubicom32 architecture.
4733 + * (C) Copyright 2009, Ubicom, Inc.
4735 + * This file is part of the Ubicom32 Linux Kernel Port.
4737 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
4738 + * it and/or modify it under the terms of the GNU General Public License
4739 + * as published by the Free Software Foundation, either version 2 of the
4740 + * License, or (at your option) any later version.
4742 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
4743 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
4744 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
4745 + * the GNU General Public License for more details.
4747 + * You should have received a copy of the GNU General Public License
4748 + * along with the Ubicom32 Linux Kernel Port. If not,
4749 + * see <http://www.gnu.org/licenses/>.
4751 + * Ubicom32 implementation derived from (with many thanks):
4756 +#ifndef _ASM_UBICOM32_DMA_MAPPING_H
4757 +#define _ASM_UBICOM32_DMA_MAPPING_H
4759 +#include <linux/scatterlist.h>
4762 +/* we implement the API below in terms of the existing PCI one,
4763 + * so include it */
4764 +#include <linux/pci.h>
4765 +/* need struct page definitions */
4766 +#include <linux/mm.h>
4769 +dma_supported(struct device *dev, u64 mask)
4771 + BUG_ON(dev->bus != &pci_bus_type);
4773 + return pci_dma_supported(to_pci_dev(dev), mask);
4777 +dma_set_mask(struct device *dev, u64 dma_mask)
4779 + BUG_ON(dev->bus != &pci_bus_type);
4781 + return pci_set_dma_mask(to_pci_dev(dev), dma_mask);
4784 +static inline void *
4785 +dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
4788 + BUG_ON(dev->bus != &pci_bus_type);
4790 + return pci_alloc_consistent(to_pci_dev(dev), size, dma_handle);
4794 +dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
4795 + dma_addr_t dma_handle)
4797 + BUG_ON(dev->bus != &pci_bus_type);
4799 + pci_free_consistent(to_pci_dev(dev), size, cpu_addr, dma_handle);
4802 +static inline dma_addr_t
4803 +dma_map_single(struct device *dev, void *cpu_addr, size_t size,
4804 + enum dma_data_direction direction)
4806 + BUG_ON(dev->bus != &pci_bus_type);
4808 + return pci_map_single(to_pci_dev(dev), cpu_addr, size, (int)direction);
4812 +dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
4813 + enum dma_data_direction direction)
4815 + BUG_ON(dev->bus != &pci_bus_type);
4817 + pci_unmap_single(to_pci_dev(dev), dma_addr, size, (int)direction);
4820 +static inline dma_addr_t
4821 +dma_map_page(struct device *dev, struct page *page,
4822 + unsigned long offset, size_t size,
4823 + enum dma_data_direction direction)
4825 + BUG_ON(dev->bus != &pci_bus_type);
4827 + return pci_map_page(to_pci_dev(dev), page, offset, size, (int)direction);
4831 +dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
4832 + enum dma_data_direction direction)
4834 + BUG_ON(dev->bus != &pci_bus_type);
4836 + pci_unmap_page(to_pci_dev(dev), dma_address, size, (int)direction);
4840 +dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
4841 + enum dma_data_direction direction)
4843 + BUG_ON(dev->bus != &pci_bus_type);
4845 + return pci_map_sg(to_pci_dev(dev), sg, nents, (int)direction);
4849 +dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
4850 + enum dma_data_direction direction)
4852 + BUG_ON(dev->bus != &pci_bus_type);
4854 + pci_unmap_sg(to_pci_dev(dev), sg, nhwentries, (int)direction);
4858 +dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
4859 + enum dma_data_direction direction)
4861 + BUG_ON(dev->bus != &pci_bus_type);
4863 + pci_dma_sync_single_for_cpu(to_pci_dev(dev), dma_handle,
4864 + size, (int)direction);
4868 +dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size,
4869 + enum dma_data_direction direction)
4871 + BUG_ON(dev->bus != &pci_bus_type);
4873 + pci_dma_sync_single_for_device(to_pci_dev(dev), dma_handle,
4874 + size, (int)direction);
4878 +dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
4879 + enum dma_data_direction direction)
4881 + BUG_ON(dev->bus != &pci_bus_type);
4883 + pci_dma_sync_sg_for_cpu(to_pci_dev(dev), sg, nelems, (int)direction);
4887 +dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
4888 + enum dma_data_direction direction)
4890 + BUG_ON(dev->bus != &pci_bus_type);
4892 + pci_dma_sync_sg_for_device(to_pci_dev(dev), sg, nelems, (int)direction);
4896 +dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
4898 + return pci_dma_mapping_error(to_pci_dev(dev), dma_addr);
4905 +dma_supported(struct device *dev, u64 mask)
4911 +dma_set_mask(struct device *dev, u64 dma_mask)
4917 +static inline void *
4918 +dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
4926 +dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
4927 + dma_addr_t dma_handle)
4932 +static inline dma_addr_t
4933 +dma_map_single(struct device *dev, void *cpu_addr, size_t size,
4934 + enum dma_data_direction direction)
4941 +dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
4942 + enum dma_data_direction direction)
4947 +static inline dma_addr_t
4948 +dma_map_page(struct device *dev, struct page *page,
4949 + unsigned long offset, size_t size,
4950 + enum dma_data_direction direction)
4957 +dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
4958 + enum dma_data_direction direction)
4964 +dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
4965 + enum dma_data_direction direction)
4972 +dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
4973 + enum dma_data_direction direction)
4979 +dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
4980 + enum dma_data_direction direction)
4986 +dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size,
4987 + enum dma_data_direction direction)
4993 +dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
4994 + enum dma_data_direction direction)
5000 +dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
5001 + enum dma_data_direction direction)
5007 +dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
5014 +/* Now for the API extensions over the pci_ one */
5016 +#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
5017 +#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
5018 +#define dma_is_consistent(d, h) (1)
5021 +dma_get_cache_alignment(void)
5023 + /* no easy way to get cache size on all processors, so return
5024 + * the maximum possible, to be safe */
5025 + return (1 << INTERNODE_CACHE_SHIFT);
5029 +dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
5030 + unsigned long offset, size_t size,
5031 + enum dma_data_direction direction)
5033 + /* just sync everything, that's all the pci API can do */
5034 + dma_sync_single_for_cpu(dev, dma_handle, offset+size, direction);
5038 +dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
5039 + unsigned long offset, size_t size,
5040 + enum dma_data_direction direction)
5042 + /* just sync everything, that's all the pci API can do */
5043 + dma_sync_single_for_device(dev, dma_handle, offset+size, direction);
5047 +dma_cache_sync(struct device *dev, void *vaddr, size_t size,
5048 + enum dma_data_direction direction)
5050 + /* could define this in terms of the dma_cache ... operations,
5051 + * but if you get this on a platform, you should convert the platform
5052 + * to using the generic device DMA API */
5056 +#endif /* _ASM_UBICOM32_DMA_MAPPING_H */
5058 +++ b/arch/ubicom32/include/asm/elf.h
5061 + * arch/ubicom32/include/asm/elf.h
5062 + * Definitions for elf executable format for Ubicom32 architecture.
5064 + * (C) Copyright 2009, Ubicom, Inc.
5066 + * This file is part of the Ubicom32 Linux Kernel Port.
5068 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
5069 + * it and/or modify it under the terms of the GNU General Public License
5070 + * as published by the Free Software Foundation, either version 2 of the
5071 + * License, or (at your option) any later version.
5073 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
5074 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
5075 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
5076 + * the GNU General Public License for more details.
5078 + * You should have received a copy of the GNU General Public License
5079 + * along with the Ubicom32 Linux Kernel Port. If not,
5080 + * see <http://www.gnu.org/licenses/>.
5082 + * Ubicom32 implementation derived from (with many thanks):
5087 +#ifndef _ASM_UBICOM32_ELF_H
5088 +#define _ASM_UBICOM32_ELF_H
5091 + * ELF register definitions..
5094 +#include <asm/ptrace.h>
5095 +#include <asm/user.h>
5098 + * Processor specific flags for the ELF header e_flags field.
5100 +#define EF_UBICOM32_V3 0x00000001 /* -fmarch=ubicom32v3 */
5101 +#define EF_UBICOM32_V4 0x00000002 /* -fmarch=ubicom32v4 */
5102 +#define EF_UBICOM32_PIC 0x80000000 /* -fpic */
5103 +#define EF_UBICOM32_FDPIC 0x40000000 /* -mfdpic */
5106 + * Ubicom32 ELF relocation types
5108 +#define R_UBICOM32_NONE 0
5109 +#define R_UBICOM32_16 1
5110 +#define R_UBICOM32_32 2
5111 +#define R_UBICOM32_LO16 3
5112 +#define R_UBICOM32_HI16 4
5113 +#define R_UBICOM32_21_PCREL 5
5114 +#define R_UBICOM32_24_PCREL 6
5115 +#define R_UBICOM32_HI24 7
5116 +#define R_UBICOM32_LO7_S 8
5117 +#define R_UBICOM32_LO7_2_S 9
5118 +#define R_UBICOM32_LO7_4_S 10
5119 +#define R_UBICOM32_LO7_D 11
5120 +#define R_UBICOM32_LO7_2_D 12
5121 +#define R_UBICOM32_LO7_4_D 13
5122 +#define R_UBICOM32_32_HARVARD 14
5123 +#define R_UBICOM32_LO7_CALLI 15
5124 +#define R_UBICOM32_LO16_CALLI 16
5125 +#define R_UBICOM32_GOT_HI24 17
5126 +#define R_UBICOM32_GOT_LO7_S 18
5127 +#define R_UBICOM32_GOT_LO7_2_S 19
5128 +#define R_UBICOM32_GOT_LO7_4_S 20
5129 +#define R_UBICOM32_GOT_LO7_D 21
5130 +#define R_UBICOM32_GOT_LO7_2_D 22
5131 +#define R_UBICOM32_GOT_LO7_4_D 23
5132 +#define R_UBICOM32_FUNCDESC_GOT_HI24 24
5133 +#define R_UBICOM32_FUNCDESC_GOT_LO7_S 25
5134 +#define R_UBICOM32_FUNCDESC_GOT_LO7_2_S 26
5135 +#define R_UBICOM32_FUNCDESC_GOT_LO7_4_S 27
5136 +#define R_UBICOM32_FUNCDESC_GOT_LO7_D 28
5137 +#define R_UBICOM32_FUNCDESC_GOT_LO7_2_D 29
5138 +#define R_UBICOM32_FUNCDESC_GOT_LO7_4_D 30
5139 +#define R_UBICOM32_GOT_LO7_CALLI 31
5140 +#define R_UBICOM32_FUNCDESC_GOT_LO7_CALLI 32
5141 +#define R_UBICOM32_FUNCDESC_VALUE 33
5142 +#define R_UBICOM32_FUNCDESC 34
5143 +#define R_UBICOM32_GOTOFFSET_LO 35
5144 +#define R_UBICOM32_GOTOFFSET_HI 36
5145 +#define R_UBICOM32_FUNCDESC_GOTOFFSET_LO 37
5146 +#define R_UBICOM32_FUNCDESC_GOTOFFSET_HI 38
5147 +#define R_UBICOM32_GNU_VTINHERIT 200
5148 +#define R_UBICOM32_GNU_VTENTRY 201
5150 +typedef unsigned long elf_greg_t;
5152 +#define ELF_NGREG (sizeof(struct pt_regs) / sizeof(elf_greg_t))
5153 +typedef elf_greg_t elf_gregset_t[ELF_NGREG];
5155 +typedef struct user_ubicom32fp_struct elf_fpregset_t;
5158 + * This is used to ensure we don't load something for the wrong architecture.
5160 +#define elf_check_arch(x) ((x)->e_machine == EM_UBICOM32)
5162 +#define elf_check_fdpic(x) ((x)->e_flags & EF_UBICOM32_FDPIC)
5164 +#define elf_check_const_displacement(x) ((x)->e_flags & EF_UBICOM32_PIC)
5167 + * These are used to set parameters in the core dumps.
5169 +#define ELF_CLASS ELFCLASS32
5170 +#define ELF_DATA ELFDATA2MSB
5171 +#define ELF_ARCH EM_UBICOM32
5173 +/* For SVR4/m68k the function pointer to be registered with `atexit' is
5174 + passed in %a1. Although my copy of the ABI has no such statement, it
5175 + is actually used on ASV. */
5176 +#define ELF_PLAT_INIT(_r, load_addr) _r->a1 = 0
5178 +#define ELF_FDPIC_PLAT_INIT(_regs, _exec_map_addr, _interp_map_addr, \
5181 + _regs->dn[1] = _exec_map_addr; \
5182 + _regs->dn[2] = _interp_map_addr; \
5183 + _regs->dn[3] = _dynamic_addr; \
5184 + _regs->an[1] = 0; /* dl_fini will be set by ldso */ \
5187 +#define USE_ELF_CORE_DUMP
5188 +#define ELF_EXEC_PAGESIZE 4096
5191 +#ifdef CONFIG_UBICOM32_V4
5192 +#define ELF_FDPIC_CORE_EFLAGS (EF_UBICOM32_FDPIC | EF_UBICOM32_V4)
5193 +#elif defined CONFIG_UBICOM32_V3
5194 +#define ELF_FDPIC_CORE_EFLAGS (EF_UBICOM32_FDPIC | EF_UBICOM32_V3)
5196 +#error Unknown/Unsupported ubicom32 architecture.
5200 +/* This is the location that an ET_DYN program is loaded if exec'ed. Typical
5201 + use of this is to invoke "./ld.so someprog" to test out a new version of
5202 + the loader. We need to make sure that it is out of the way of the program
5203 + that it will "exec", and that there is sufficient room for the brk. */
5205 +#define ELF_ET_DYN_BASE 0xD0000000UL
5208 + * For Ubicom32, the elf_gregset_t and struct pt_regs are the same size
5209 + * data structure so a copy is performed instead of providing the
5210 + * ELF_CORE_COPY_REGS macro.
5214 + * ELF_CORE_COPY_TASK_REGS is needed to dump register state from multi threaded user projects.
5216 +extern int dump_task_regs(struct task_struct *, elf_gregset_t *);
5217 +#define ELF_CORE_COPY_TASK_REGS(tsk, elf_regs) dump_task_regs(tsk, elf_regs)
5219 +/* This yields a mask that user programs can use to figure out what
5220 + instruction set this cpu supports. */
5222 +#define ELF_HWCAP (0)
5224 +/* This yields a string that ld.so will use to load implementation
5225 + specific libraries for optimization. This is more specific in
5226 + intent than poking at uname or /proc/cpuinfo. */
5228 +#define ELF_PLATFORM (NULL)
5230 +#define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX)
5232 +#endif /* _ASM_UBICOM32_ELF_H */
5234 +++ b/arch/ubicom32/include/asm/emergency-restart.h
5237 + * arch/ubicom32/include/asm/emergency-restart.h
5238 + * Generic emergency-restart.h for Ubicom32 architecture.
5240 + * (C) Copyright 2009, Ubicom, Inc.
5242 + * This file is part of the Ubicom32 Linux Kernel Port.
5244 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
5245 + * it and/or modify it under the terms of the GNU General Public License
5246 + * as published by the Free Software Foundation, either version 2 of the
5247 + * License, or (at your option) any later version.
5249 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
5250 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
5251 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
5252 + * the GNU General Public License for more details.
5254 + * You should have received a copy of the GNU General Public License
5255 + * along with the Ubicom32 Linux Kernel Port. If not,
5256 + * see <http://www.gnu.org/licenses/>.
5258 + * Ubicom32 implementation derived from (with many thanks):
5263 +#ifndef _ASM_UBICOM32_EMERGENCY_RESTART_H
5264 +#define _ASM_UBICOM32_EMERGENCY_RESTART_H
5266 +#include <asm-generic/emergency-restart.h>
5268 +#endif /* _ASM_UBICOM32_EMERGENCY_RESTART_H */
5270 +++ b/arch/ubicom32/include/asm/entry.h
5273 + * arch/ubicom32/include/asm/entry.h
5274 + * Entry register/stack definitions for Ubicom32 architecture.
5276 + * (C) Copyright 2009, Ubicom, Inc.
5278 + * This file is part of the Ubicom32 Linux Kernel Port.
5280 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
5281 + * it and/or modify it under the terms of the GNU General Public License
5282 + * as published by the Free Software Foundation, either version 2 of the
5283 + * License, or (at your option) any later version.
5285 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
5286 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
5287 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
5288 + * the GNU General Public License for more details.
5290 + * You should have received a copy of the GNU General Public License
5291 + * along with the Ubicom32 Linux Kernel Port. If not,
5292 + * see <http://www.gnu.org/licenses/>.
5294 + * Ubicom32 implementation derived from (with many thanks):
5299 +#ifndef _ASM_UBICOM32_ENTRY_H
5300 +#define _ASM_UBICOM32_ENTRY_H
5302 +#include <asm/setup.h>
5303 +#include <asm/page.h>
5305 +#endif /* _ASM_UBICOM32_ENTRY_H */
5307 +++ b/arch/ubicom32/include/asm/errno.h
5310 + * arch/ubicom32/include/asm/errno.h
5311 + * Generic errno.h for Ubicom32 architecture.
5313 + * (C) Copyright 2009, Ubicom, Inc.
5315 + * This file is part of the Ubicom32 Linux Kernel Port.
5317 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
5318 + * it and/or modify it under the terms of the GNU General Public License
5319 + * as published by the Free Software Foundation, either version 2 of the
5320 + * License, or (at your option) any later version.
5322 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
5323 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
5324 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
5325 + * the GNU General Public License for more details.
5327 + * You should have received a copy of the GNU General Public License
5328 + * along with the Ubicom32 Linux Kernel Port. If not,
5329 + * see <http://www.gnu.org/licenses/>.
5331 + * Ubicom32 implementation derived from (with many thanks):
5336 +#ifndef _ASM_UBICOM32_ERRNO_H
5337 +#define _ASM_UBICOM32_ERRNO_H
5339 +#include <asm-generic/errno.h>
5341 +#endif /* _ASM_UBICOM32_ERRNO_H */
5343 +++ b/arch/ubicom32/include/asm/fb.h
5346 + * arch/ubicom32/include/asm/fb.h
5347 + * Definition of fb_is_primary_device() for Ubicom32 architecture.
5349 + * (C) Copyright 2009, Ubicom, Inc.
5351 + * This file is part of the Ubicom32 Linux Kernel Port.
5353 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
5354 + * it and/or modify it under the terms of the GNU General Public License
5355 + * as published by the Free Software Foundation, either version 2 of the
5356 + * License, or (at your option) any later version.
5358 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
5359 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
5360 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
5361 + * the GNU General Public License for more details.
5363 + * You should have received a copy of the GNU General Public License
5364 + * along with the Ubicom32 Linux Kernel Port. If not,
5365 + * see <http://www.gnu.org/licenses/>.
5367 + * Ubicom32 implementation derived from (with many thanks):
5372 +#ifndef _ASM_UBICOM32_FB_H
5373 +#define _ASM_UBICOM32_FB_H
5374 +#include <linux/fb.h>
5376 +#define fb_pgprotect(...) do {} while (0)
5378 +static inline int fb_is_primary_device(struct fb_info *info)
5383 +#endif /* _ASM_UBICOM32_FB_H */
5385 +++ b/arch/ubicom32/include/asm/fcntl.h
5388 + * arch/ubicom32/include/asm/fcntl.h
5389 + * File control bit definitions for Ubicom32 architecture.
5391 + * (C) Copyright 2009, Ubicom, Inc.
5393 + * This file is part of the Ubicom32 Linux Kernel Port.
5395 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
5396 + * it and/or modify it under the terms of the GNU General Public License
5397 + * as published by the Free Software Foundation, either version 2 of the
5398 + * License, or (at your option) any later version.
5400 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
5401 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
5402 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
5403 + * the GNU General Public License for more details.
5405 + * You should have received a copy of the GNU General Public License
5406 + * along with the Ubicom32 Linux Kernel Port. If not,
5407 + * see <http://www.gnu.org/licenses/>.
5409 + * Ubicom32 implementation derived from (with many thanks):
5414 +#ifndef _ASM_UBICOM32_FCNTL_H
5415 +#define _ASM_UBICOM32_FCNTL_H
5417 +#define O_DIRECTORY 040000 /* must be a directory */
5418 +#define O_NOFOLLOW 0100000 /* don't follow links */
5419 +#define O_DIRECT 0200000 /* direct disk access hint - currently ignored */
5420 +#define O_LARGEFILE 0400000
5422 +#include <asm-generic/fcntl.h>
5424 +#endif /* _ASM_UBICOM32_FCNTL_H */
5426 +++ b/arch/ubicom32/include/asm/flat.h
5429 + * arch/ubicom32/include/asm/flat.h
5430 + * Definitions to support flat-format executables.
5432 + * (C) Copyright 2009, Ubicom, Inc.
5434 + * This file is part of the Ubicom32 Linux Kernel Port.
5436 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
5437 + * it and/or modify it under the terms of the GNU General Public License
5438 + * as published by the Free Software Foundation, either version 2 of the
5439 + * License, or (at your option) any later version.
5441 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
5442 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
5443 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
5444 + * the GNU General Public License for more details.
5446 + * You should have received a copy of the GNU General Public License
5447 + * along with the Ubicom32 Linux Kernel Port. If not,
5448 + * see <http://www.gnu.org/licenses/>.
5450 + * Ubicom32 implementation derived from (with many thanks):
5456 +#ifndef _ASM_UBICOM32_FLAT_H
5457 +#define _ASM_UBICOM32_FLAT_H
5459 +#define ARCH_FLAT_ALIGN 0x80
5460 +#define ARCH_FLAT_ALIGN_TEXT 1
5462 +#define R_UBICOM32_32 2
5463 +#define R_UBICOM32_HI24 7
5464 +#define R_UBICOM32_LO7_S 8
5465 +#define R_UBICOM32_LO7_2_S 9
5466 +#define R_UBICOM32_LO7_4_S 10
5467 +#define R_UBICOM32_LO7_D 11
5468 +#define R_UBICOM32_LO7_2_D 12
5469 +#define R_UBICOM32_LO7_4_D 13
5470 +#define R_UBICOM32_LO7_CALLI 15
5471 +#define R_UBICOM32_LO16_CALLI 16
5473 +extern void ubicom32_flat_put_addr_at_rp(unsigned long *rp, u32_t val, u32_t rval, unsigned long *p);
5474 +extern unsigned long ubicom32_flat_get_addr_from_rp(unsigned long *rp, u32_t relval, u32_t flags, unsigned long *p);
5476 +#define flat_stack_align(sp) /* nothing needed */
5477 +#define flat_argvp_envp_on_stack() 1
5478 +#define flat_old_ram_flag(flags) (flags)
5479 +#define flat_reloc_valid(reloc, size) ((reloc) <= (size))
5480 +#define flat_get_addr_from_rp(rp, relval, flags, p) (ubicom32_flat_get_addr_from_rp(rp, relval,flags, p))
5481 +#define flat_put_addr_at_rp(rp, val, relval) do {ubicom32_flat_put_addr_at_rp(rp, val, relval, &persistent);} while(0)
5482 +#define flat_get_relocate_addr(rel) ((persistent) ? (persistent & 0x07ffffff) : (rel & 0x07ffffff))
5484 +static inline int flat_set_persistent(unsigned int relval, unsigned long *p)
5489 + if ((relval >> 27) != R_UBICOM32_32) {
5491 + * Something other than UBICOM32_32. The next entry has the relocation.
5500 +#endif /* _ASM_UBICOM32_FLAT_H */
5502 +++ b/arch/ubicom32/include/asm/fpu.h
5505 + * arch/ubicom32/include/asm/fpu.h
5506 + * Floating point state definitions for Ubicom32 architecture.
5508 + * (C) Copyright 2009, Ubicom, Inc.
5510 + * This file is part of the Ubicom32 Linux Kernel Port.
5512 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
5513 + * it and/or modify it under the terms of the GNU General Public License
5514 + * as published by the Free Software Foundation, either version 2 of the
5515 + * License, or (at your option) any later version.
5517 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
5518 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
5519 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
5520 + * the GNU General Public License for more details.
5522 + * You should have received a copy of the GNU General Public License
5523 + * along with the Ubicom32 Linux Kernel Port. If not,
5524 + * see <http://www.gnu.org/licenses/>.
5526 + * Ubicom32 implementation derived from (with many thanks):
5531 +#ifndef _ASM_UBICOM32_FPU_H
5532 +#define _ASM_UBICOM32_FPU_H
5535 + * MAX floating point unit state size (FSAVE/FRESTORE)
5537 +/* No FP unit present then... */
5538 +#define FPSTATESIZE (2) /* dummy size */
5540 +#endif /* _ASM_UBICOM32_FPU_H */
5542 +++ b/arch/ubicom32/include/asm/ftrace.h
5546 +++ b/arch/ubicom32/include/asm/futex.h
5549 + * arch/ubicom32/include/asm/futex.h
5550 + * Generic futex.h 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_FUTEX_H
5576 +#define _ASM_UBICOM32_FUTEX_H
5578 +#include <asm-generic/futex.h>
5580 +#endif /* _ASM_UBICOM32_FUTEX_H */
5582 +++ b/arch/ubicom32/include/asm/.gitignore
5586 +++ b/arch/ubicom32/include/asm/gpio.h
5589 + * arch/ubicom32/include/asm/gpio.h
5590 + * Definitions for GPIO operations on Ubicom32 architecture.
5592 + * (C) Copyright 2009, Ubicom, Inc.
5594 + * This file is part of the Ubicom32 Linux Kernel Port.
5596 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
5597 + * it and/or modify it under the terms of the GNU General Public License
5598 + * as published by the Free Software Foundation, either version 2 of the
5599 + * License, or (at your option) any later version.
5601 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
5602 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
5603 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
5604 + * the GNU General Public License for more details.
5606 + * You should have received a copy of the GNU General Public License
5607 + * along with the Ubicom32 Linux Kernel Port. If not,
5608 + * see <http://www.gnu.org/licenses/>.
5610 + * Ubicom32 implementation derived from (with many thanks):
5615 +#ifndef _ASM_UBICOM32_GPIO_H
5616 +#define _ASM_UBICOM32_GPIO_H
5618 +#include <linux/compiler.h>
5619 +#include <asm/irq.h>
5621 +#include <asm/ip5000.h>
5623 +#define ARCH_NR_GPIOS 512
5624 +#define MAX_UBICOM_ONCHIP_GPIO (9 * 32)
5627 + * Macros for manipulating GPIO numbers
5629 +#define gpio_bit(gn) (1 << (gn & 0x1f))
5630 +#define gpio_bank(gn) (gn >> 5)
5632 +#define gpio_pin_index(gn) (gn & 0x1f)
5633 +#define gpio_port_index(gn) (gn >> 5)
5635 +#define GPIO_RA_0 ((32 * 0) + 0)
5636 +#define GPIO_RA_1 ((32 * 0) + 1)
5637 +#define GPIO_RA_2 ((32 * 0) + 2)
5638 +#define GPIO_RA_3 ((32 * 0) + 3)
5639 +#define GPIO_RA_4 ((32 * 0) + 4)
5640 +#define GPIO_RA_5 ((32 * 0) + 5)
5641 +#define GPIO_RA_6 ((32 * 0) + 6)
5642 +#define GPIO_RA_7 ((32 * 0) + 7)
5644 +#define GPIO_RB_0 ((32 * 1) + 0)
5645 +#define GPIO_RB_1 ((32 * 1) + 1)
5646 +#define GPIO_RB_2 ((32 * 1) + 2)
5647 +#define GPIO_RB_3 ((32 * 1) + 3)
5648 +#define GPIO_RB_4 ((32 * 1) + 4)
5649 +#define GPIO_RB_5 ((32 * 1) + 5)
5650 +#define GPIO_RB_6 ((32 * 1) + 6)
5651 +#define GPIO_RB_7 ((32 * 1) + 7)
5652 +#define GPIO_RB_8 ((32 * 1) + 8)
5653 +#define GPIO_RB_9 ((32 * 1) + 9)
5654 +#define GPIO_RB_10 ((32 * 1) + 10)
5655 +#define GPIO_RB_11 ((32 * 1) + 11)
5656 +#define GPIO_RB_12 ((32 * 1) + 12)
5657 +#define GPIO_RB_13 ((32 * 1) + 13)
5658 +#define GPIO_RB_14 ((32 * 1) + 14)
5659 +#define GPIO_RB_15 ((32 * 1) + 15)
5660 +#define GPIO_RB_16 ((32 * 1) + 16)
5661 +#define GPIO_RB_17 ((32 * 1) + 17)
5662 +#define GPIO_RB_18 ((32 * 1) + 18)
5663 +#define GPIO_RB_19 ((32 * 1) + 19)
5665 +#define GPIO_RC_0 ((32 * 2) + 0)
5666 +#define GPIO_RC_1 ((32 * 2) + 1)
5667 +#define GPIO_RC_2 ((32 * 2) + 2)
5668 +#define GPIO_RC_3 ((32 * 2) + 3)
5669 +#define GPIO_RC_4 ((32 * 2) + 4)
5670 +#define GPIO_RC_5 ((32 * 2) + 5)
5671 +#define GPIO_RC_6 ((32 * 2) + 6)
5672 +#define GPIO_RC_7 ((32 * 2) + 7)
5673 +#define GPIO_RC_8 ((32 * 2) + 8)
5674 +#define GPIO_RC_9 ((32 * 2) + 9)
5675 +#define GPIO_RC_10 ((32 * 2) + 10)
5676 +#define GPIO_RC_11 ((32 * 2) + 11)
5677 +#define GPIO_RC_12 ((32 * 2) + 12)
5678 +#define GPIO_RC_13 ((32 * 2) + 13)
5679 +#define GPIO_RC_14 ((32 * 2) + 14)
5680 +#define GPIO_RC_15 ((32 * 2) + 15)
5681 +#define GPIO_RC_16 ((32 * 2) + 16)
5682 +#define GPIO_RC_17 ((32 * 2) + 17)
5683 +#define GPIO_RC_18 ((32 * 2) + 18)
5684 +#define GPIO_RC_19 ((32 * 2) + 19)
5685 +#define GPIO_RC_20 ((32 * 2) + 20)
5686 +#define GPIO_RC_21 ((32 * 2) + 21)
5687 +#define GPIO_RC_22 ((32 * 2) + 22)
5688 +#define GPIO_RC_23 ((32 * 2) + 23)
5689 +#define GPIO_RC_24 ((32 * 2) + 24)
5690 +#define GPIO_RC_25 ((32 * 2) + 25)
5691 +#define GPIO_RC_26 ((32 * 2) + 26)
5692 +#define GPIO_RC_27 ((32 * 2) + 27)
5693 +#define GPIO_RC_28 ((32 * 2) + 28)
5694 +#define GPIO_RC_29 ((32 * 2) + 29)
5695 +#define GPIO_RC_30 ((32 * 2) + 30)
5696 +#define GPIO_RC_31 ((32 * 2) + 31)
5698 +#define GPIO_RD_0 ((32 * 3) + 0)
5699 +#define GPIO_RD_1 ((32 * 3) + 1)
5700 +#define GPIO_RD_2 ((32 * 3) + 2)
5701 +#define GPIO_RD_3 ((32 * 3) + 3)
5702 +#define GPIO_RD_4 ((32 * 3) + 4)
5703 +#define GPIO_RD_5 ((32 * 3) + 5)
5704 +#define GPIO_RD_6 ((32 * 3) + 6)
5705 +#define GPIO_RD_7 ((32 * 3) + 7)
5706 +#define GPIO_RD_8 ((32 * 3) + 8)
5707 +#define GPIO_RD_9 ((32 * 3) + 9)
5708 +#define GPIO_RD_10 ((32 * 3) + 10)
5709 +#define GPIO_RD_11 ((32 * 3) + 11)
5711 +#define GPIO_RE_0 ((32 * 4) + 0)
5712 +#define GPIO_RE_1 ((32 * 4) + 1)
5713 +#define GPIO_RE_2 ((32 * 4) + 2)
5714 +#define GPIO_RE_3 ((32 * 4) + 3)
5715 +#define GPIO_RE_4 ((32 * 4) + 4)
5716 +#define GPIO_RE_5 ((32 * 4) + 5)
5717 +#define GPIO_RE_6 ((32 * 4) + 6)
5718 +#define GPIO_RE_7 ((32 * 4) + 7)
5720 +#define GPIO_RF_0 ((32 * 5) + 0)
5721 +#define GPIO_RF_1 ((32 * 5) + 1)
5722 +#define GPIO_RF_2 ((32 * 5) + 2)
5723 +#define GPIO_RF_3 ((32 * 5) + 3)
5724 +#define GPIO_RF_4 ((32 * 5) + 4)
5725 +#define GPIO_RF_5 ((32 * 5) + 5)
5726 +#define GPIO_RF_6 ((32 * 5) + 6)
5727 +#define GPIO_RF_7 ((32 * 5) + 7)
5728 +#define GPIO_RF_8 ((32 * 5) + 8)
5729 +#define GPIO_RF_9 ((32 * 5) + 9)
5730 +#define GPIO_RF_10 ((32 * 5) + 10)
5731 +#define GPIO_RF_11 ((32 * 5) + 11)
5732 +#define GPIO_RF_12 ((32 * 5) + 12)
5733 +#define GPIO_RF_13 ((32 * 5) + 13)
5734 +#define GPIO_RF_14 ((32 * 5) + 14)
5735 +#define GPIO_RF_15 ((32 * 5) + 15)
5737 +#define GPIO_RG_0 ((32 * 6) + 0)
5738 +#define GPIO_RG_1 ((32 * 6) + 1)
5739 +#define GPIO_RG_2 ((32 * 6) + 2)
5740 +#define GPIO_RG_3 ((32 * 6) + 3)
5741 +#define GPIO_RG_4 ((32 * 6) + 4)
5742 +#define GPIO_RG_5 ((32 * 6) + 5)
5743 +#define GPIO_RG_6 ((32 * 6) + 6)
5744 +#define GPIO_RG_7 ((32 * 6) + 7)
5745 +#define GPIO_RG_8 ((32 * 6) + 8)
5746 +#define GPIO_RG_9 ((32 * 6) + 9)
5747 +#define GPIO_RG_10 ((32 * 6) + 10)
5748 +#define GPIO_RG_11 ((32 * 6) + 11)
5749 +#define GPIO_RG_12 ((32 * 6) + 12)
5750 +#define GPIO_RG_13 ((32 * 6) + 13)
5751 +#define GPIO_RG_14 ((32 * 6) + 14)
5752 +#define GPIO_RG_15 ((32 * 6) + 15)
5753 +#define GPIO_RG_16 ((32 * 6) + 16)
5754 +#define GPIO_RG_17 ((32 * 6) + 17)
5755 +#define GPIO_RG_18 ((32 * 6) + 18)
5756 +#define GPIO_RG_19 ((32 * 6) + 19)
5757 +#define GPIO_RG_20 ((32 * 6) + 20)
5758 +#define GPIO_RG_21 ((32 * 6) + 21)
5759 +#define GPIO_RG_22 ((32 * 6) + 22)
5760 +#define GPIO_RG_23 ((32 * 6) + 23)
5761 +#define GPIO_RG_24 ((32 * 6) + 24)
5762 +#define GPIO_RG_25 ((32 * 6) + 25)
5763 +#define GPIO_RG_26 ((32 * 6) + 26)
5764 +#define GPIO_RG_27 ((32 * 6) + 27)
5765 +#define GPIO_RG_28 ((32 * 6) + 28)
5766 +#define GPIO_RG_29 ((32 * 6) + 29)
5767 +#define GPIO_RG_30 ((32 * 6) + 30)
5768 +#define GPIO_RG_31 ((32 * 6) + 31)
5770 +#define GPIO_RH_0 ((32 * 7) + 0)
5771 +#define GPIO_RH_1 ((32 * 7) + 1)
5772 +#define GPIO_RH_2 ((32 * 7) + 2)
5773 +#define GPIO_RH_3 ((32 * 7) + 3)
5774 +#define GPIO_RH_4 ((32 * 7) + 4)
5775 +#define GPIO_RH_5 ((32 * 7) + 5)
5776 +#define GPIO_RH_6 ((32 * 7) + 6)
5777 +#define GPIO_RH_7 ((32 * 7) + 7)
5778 +#define GPIO_RH_8 ((32 * 7) + 8)
5779 +#define GPIO_RH_9 ((32 * 7) + 9)
5781 +#define GPIO_RI_0 ((32 * 8) + 0)
5782 +#define GPIO_RI_1 ((32 * 8) + 1)
5783 +#define GPIO_RI_2 ((32 * 8) + 2)
5784 +#define GPIO_RI_3 ((32 * 8) + 3)
5785 +#define GPIO_RI_4 ((32 * 8) + 4)
5786 +#define GPIO_RI_5 ((32 * 8) + 5)
5787 +#define GPIO_RI_6 ((32 * 8) + 6)
5788 +#define GPIO_RI_7 ((32 * 8) + 7)
5789 +#define GPIO_RI_8 ((32 * 8) + 8)
5790 +#define GPIO_RI_9 ((32 * 8) + 9)
5791 +#define GPIO_RI_10 ((32 * 8) + 10)
5792 +#define GPIO_RI_11 ((32 * 8) + 11)
5793 +#define GPIO_RI_12 ((32 * 8) + 12)
5794 +#define GPIO_RI_13 ((32 * 8) + 13)
5795 +#define GPIO_RI_14 ((32 * 8) + 14)
5796 +#define GPIO_RI_15 ((32 * 8) + 15)
5799 + * The following section defines extra GPIO available to some boards.
5800 + * These GPIO are generally external to the processor (i.e. SPI/I2C
5801 + * expander chips).
5803 + * Note that these defines show all possible GPIO available, however,
5804 + * depending on the actual board configuration, some GPIO are not
5805 + * available for use.
5807 +#ifdef CONFIG_IP7500MEDIA
5811 +#define IP7500MEDIA_U15_BASE (32 * 10)
5812 +#define IP7500MEDIA_IO0 (IP7500MEDIA_U15_BASE + 0)
5813 +#define IP7500MEDIA_IO1 (IP7500MEDIA_U15_BASE + 1)
5814 +#define IP7500MEDIA_IO2 (IP7500MEDIA_U15_BASE + 2)
5815 +#define IP7500MEDIA_IO3 (IP7500MEDIA_U15_BASE + 3)
5816 +#define IP7500MEDIA_IO4 (IP7500MEDIA_U15_BASE + 4)
5817 +#define IP7500MEDIA_IO5 (IP7500MEDIA_U15_BASE + 5)
5818 +#define IP7500MEDIA_IO6 (IP7500MEDIA_U15_BASE + 6)
5819 +#define IP7500MEDIA_IO7 (IP7500MEDIA_U15_BASE + 7)
5824 +#define IP7500MEDIA_U16_BASE (32 * 11)
5825 +#define IP7500MEDIA_IO8 (IP7500MEDIA_U16_BASE + 0)
5826 +#define IP7500MEDIA_IO9 (IP7500MEDIA_U16_BASE + 1)
5827 +#define IP7500MEDIA_IO10 (IP7500MEDIA_U16_BASE + 2)
5828 +#define IP7500MEDIA_IO11 (IP7500MEDIA_U16_BASE + 3)
5829 +#define IP7500MEDIA_IO12 (IP7500MEDIA_U16_BASE + 4)
5830 +#define IP7500MEDIA_IO13 (IP7500MEDIA_U16_BASE + 5)
5831 +#define IP7500MEDIA_IO14 (IP7500MEDIA_U16_BASE + 6)
5832 +#define IP7500MEDIA_IO15 (IP7500MEDIA_U16_BASE + 7)
5837 +#define IP7500MEDIA_U17_BASE (32 * 12)
5838 +#define IP7500MEDIA_IO16 (IP7500MEDIA_U17_BASE + 0)
5839 +#define IP7500MEDIA_IO17 (IP7500MEDIA_U17_BASE + 1)
5840 +#define IP7500MEDIA_IO18 (IP7500MEDIA_U17_BASE + 2)
5841 +#define IP7500MEDIA_IO19 (IP7500MEDIA_U17_BASE + 3)
5842 +#define IP7500MEDIA_IO20 (IP7500MEDIA_U17_BASE + 4)
5843 +#define IP7500MEDIA_IO21 (IP7500MEDIA_U17_BASE + 5)
5844 +#define IP7500MEDIA_IO22 (IP7500MEDIA_U17_BASE + 6)
5845 +#define IP7500MEDIA_IO23 (IP7500MEDIA_U17_BASE + 7)
5850 +#define IP7500MEDIA_U18_BASE (32 * 13)
5851 +#define IP7500MEDIA_IO24 (IP7500MEDIA_U18_BASE + 0)
5852 +#define IP7500MEDIA_IO25 (IP7500MEDIA_U18_BASE + 1)
5853 +#define IP7500MEDIA_IO26 (IP7500MEDIA_U18_BASE + 2)
5854 +#define IP7500MEDIA_IO27 (IP7500MEDIA_U18_BASE + 3)
5855 +#define IP7500MEDIA_IO28 (IP7500MEDIA_U18_BASE + 4)
5856 +#define IP7500MEDIA_IO29 (IP7500MEDIA_U18_BASE + 5)
5857 +#define IP7500MEDIA_IO30 (IP7500MEDIA_U18_BASE + 6)
5858 +#define IP7500MEDIA_IO31 (IP7500MEDIA_U18_BASE + 7)
5861 +#ifdef CONFIG_IP7145DPF
5865 +#define IP7145DPF_U48_BASE (32 * 10)
5866 +#define IP7145DPF_IO0 (IP7145DPF_U48_BASE + 0)
5867 +#define IP7145DPF_IO1 (IP7145DPF_U48_BASE + 1)
5868 +#define IP7145DPF_IO2 (IP7145DPF_U48_BASE + 2)
5869 +#define IP7145DPF_IO3 (IP7145DPF_U48_BASE + 3)
5870 +#define IP7145DPF_IO4 (IP7145DPF_U48_BASE + 4)
5871 +#define IP7145DPF_IO5 (IP7145DPF_U48_BASE + 5)
5872 +#define IP7145DPF_IO6 (IP7145DPF_U48_BASE + 6)
5873 +#define IP7145DPF_IO7 (IP7145DPF_U48_BASE + 7)
5878 +#define IP7145DPF_U72_BASE (32 * 11)
5879 +#define IP7145DPF_IOB0 (IP7145DPF_U72_BASE + 0)
5880 +#define IP7145DPF_IOB1 (IP7145DPF_U72_BASE + 1)
5881 +#define IP7145DPF_IOB2 (IP7145DPF_U72_BASE + 2)
5882 +#define IP7145DPF_IOB3 (IP7145DPF_U72_BASE + 3)
5883 +#define IP7145DPF_IOB4 (IP7145DPF_U72_BASE + 4)
5884 +#define IP7145DPF_IOB5 (IP7145DPF_U72_BASE + 5)
5885 +#define IP7145DPF_IOB6 (IP7145DPF_U72_BASE + 6)
5886 +#define IP7145DPF_IOB7 (IP7145DPF_U72_BASE + 7)
5889 +#include <asm-generic/gpio.h>
5892 + * The following macros bypass gpiolib to generate direct references
5893 + * to the port registers. These assume, minimally, that either
5894 + * gpio_direction_input() or gpio_direction_output() have already been
5895 + * called to setup the pin direction and to enable the pin function to
5896 + * be gpio. These macros generate the hardware port address based on
5897 + * the assumption that all ports are 32 bits wide (even though we know
5898 + * they are not). This is so we can efficiently turn pin numbers into
5899 + * port addresses without a lookup.
5901 + * These operations must be done in one instruction to prevent clobbering
5902 + * other thread's accesses to the same port.
5904 +#define UBICOM32_GPIO_ENABLE(pin) \
5906 + asm volatile ("or.4 (%[port]), (%[port]), %[mask]\n\t" \
5908 + : [port] "a" (&UBICOM32_IO_PORT(IO_BASE + (gpio_bank(pin) << 12))->gpio_mask), \
5909 + [mask] "d" (gpio_bit(pin)) \
5910 + : "cc", "memory" \
5914 +#define UBICOM32_GPIO_DISABLE(pin) \
5916 + asm volatile ("and.4 (%[port]), (%[port]), %[mask]\n\t" \
5918 + : [port] "a" (&UBICOM32_IO_PORT(IO_BASE + (gpio_bank(pin) << 12))->gpio_mask), \
5919 + [mask] "d" (~gpio_bit(pin)) \
5920 + : "cc", "memory" \
5924 +#define UBICOM32_GPIO_SET_PIN_INPUT(pin) \
5926 + asm volatile ("and.4 (%[port]), (%[port]), %[mask]\n\t" \
5928 + : [port] "a" (&UBICOM32_IO_PORT(IO_BASE + (gpio_bank(pin) << 12))->gpio_ctl), \
5929 + [mask] "d" (~gpio_bit(pin)) \
5930 + : "cc", "memory" \
5934 +#define UBICOM32_GPIO_SET_PIN_OUTPUT(pin) \
5936 + asm volatile ("or.4 (%[port]), (%[port]), %[mask]\n\t" \
5938 + : [port] "a" (&UBICOM32_IO_PORT(IO_BASE + (gpio_bank(pin) << 12))->gpio_ctl), \
5939 + [mask] "d" (gpio_bit(pin)) \
5940 + : "cc", "memory" \
5944 +#define UBICOM32_GPIO_SET_PIN_TOGGLE(pin) \
5946 + asm volatile ("xor.4 (%[port]), (%[port]), %[mask]\n\t" \
5948 + : [port] "a" (&UBICOM32_IO_PORT(IO_BASE + (gpio_bank(pin) << 12))->gpio_out), \
5949 + [mask] "d" (gpio_bit(pin)) \
5950 + : "cc", "memory" \
5954 +#define UBICOM32_GPIO_SET_PIN_HIGH(pin) \
5956 + asm volatile ("or.4 (%[port]), (%[port]), %[mask]\n\t" \
5958 + : [port] "a" (&UBICOM32_IO_PORT(IO_BASE + (gpio_bank(pin) << 12))->gpio_out), \
5959 + [mask] "d" (gpio_bit(pin)) \
5960 + : "cc", "memory" \
5964 +#define UBICOM32_GPIO_SET_PIN_LOW(pin) \
5966 + asm volatile ("and.4 (%[port]), (%[port]), %[mask]\n\t" \
5968 + : [port] "a" (&UBICOM32_IO_PORT(IO_BASE + (gpio_bank(pin) << 12))->gpio_out), \
5969 + [mask] "d" (~gpio_bit(pin)) \
5970 + : "cc", "memory" \
5974 +#define UBICOM32_GPIO_SET_PIN(pin, val) \
5976 + UBICOM32_GPIO_SET_PIN_HIGH(pin); \
5978 + UBICOM32_GPIO_SET_PIN_LOW(pin); \
5981 +#define UBICOM32_GPIO_GET_PIN(pin) \
5982 + (0 != (UBICOM32_IO_PORT(IO_BASE + (gpio_bank(pin) << 12))->gpio_in \
5986 +static inline int gpio_get_value(unsigned gpio)
5988 + if (gpio <= MAX_UBICOM_ONCHIP_GPIO)
5989 + return UBICOM32_GPIO_GET_PIN(gpio);
5991 + return __gpio_get_value(gpio);
5994 +static inline void gpio_set_value(unsigned gpio, int value)
5996 + if (gpio <= MAX_UBICOM_ONCHIP_GPIO)
5998 + UBICOM32_GPIO_SET_PIN(gpio, value);
6002 + __gpio_set_value(gpio, value);
6006 +static inline int gpio_cansleep(unsigned gpio)
6008 + return __gpio_cansleep(gpio);
6011 +static inline int gpio_to_irq(unsigned gpio)
6013 +#if defined(IP5000) || defined(IP5000_REV2)
6014 + if ((gpio >= GPIO_RA_4) && (gpio <= GPIO_RA_6))
6019 +#elif defined(IP7000) || defined(IP7000_REV2)
6020 + if ((gpio >= GPIO_RA_4) && (gpio <= GPIO_RA_6))
6021 + return 44 + (gpio - GPIO_RA_4);
6031 +static inline int irq_to_gpio(unsigned gpio)
6036 +extern struct ubicom32_io_port *ubi_gpio_get_port(unsigned gpio);
6038 +extern int __init ubi_gpio_init(void);
6040 +#endif /* _ASM_UBICOM32_GPIO_H */
6042 +++ b/arch/ubicom32/include/asm/hardirq.h
6045 + * arch/ubicom32/include/asm/hardirq.h
6046 + * Definition of ack_bad_irq() for Ubicom32 architecture.
6048 + * (C) Copyright 2009, Ubicom, Inc.
6049 + * Copyright (C) 1997, 98, 99, 2000, 01, 05 Ralf Baechle (ralf@linux-mips.org)
6050 + * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
6051 + * Copyright (C) 2001 MIPS Technologies, Inc.
6053 + * This file is part of the Ubicom32 Linux Kernel Port.
6055 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
6056 + * it and/or modify it under the terms of the GNU General Public License
6057 + * as published by the Free Software Foundation, either version 2 of the
6058 + * License, or (at your option) any later version.
6060 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
6061 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
6062 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
6063 + * the GNU General Public License for more details.
6065 + * You should have received a copy of the GNU General Public License
6066 + * along with the Ubicom32 Linux Kernel Port. If not,
6067 + * see <http://www.gnu.org/licenses/>.
6069 + * Ubicom32 implementation derived from (with many thanks):
6074 +#ifndef _ASM_UBICOM32_HARDIRQ_H
6075 +#define _ASM_UBICOM32_HARDIRQ_H
6077 +#include <linux/threads.h>
6078 +#include <linux/irq.h>
6081 + * The hardirq mask has to be large enough to have space
6082 + * for potentially all IRQ sources in the system nesting
6083 + * on a single CPU. For Ubicom32, we have 64 IRQ sources.
6085 +#define HARDIRQ_BITS 6
6086 +#if (1 << HARDIRQ_BITS) < NR_IRQS
6087 +# error HARDIRQ_BITS is too low!
6091 + unsigned int __softirq_pending;
6092 +} ____cacheline_aligned irq_cpustat_t;
6094 +#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
6096 +extern void ack_bad_irq(unsigned int irq);
6098 +#endif /* _ASM_UBICOM32_HARDIRQ_H */
6100 +++ b/arch/ubicom32/include/asm/hw_irq.h
6103 + * arch/ubicom32/include/asm/hw_irq.h
6104 + * Ubicom32 architecture APIC support.
6106 + * (C) Copyright 2009, Ubicom, Inc.
6108 + * This file is part of the Ubicom32 Linux Kernel Port.
6110 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
6111 + * it and/or modify it under the terms of the GNU General Public License
6112 + * as published by the Free Software Foundation, either version 2 of the
6113 + * License, or (at your option) any later version.
6115 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
6116 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
6117 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
6118 + * the GNU General Public License for more details.
6120 + * You should have received a copy of the GNU General Public License
6121 + * along with the Ubicom32 Linux Kernel Port. If not,
6122 + * see <http://www.gnu.org/licenses/>.
6124 + * Ubicom32 implementation derived from (with many thanks):
6129 +#ifndef _ASM_UBICOM32_HW_IRQ_H
6130 +#define _ASM_UBICOM32_HW_IRQ_H
6132 +#endif /* _ASM_UBICOM32_HW_IRQ_H */
6134 +++ b/arch/ubicom32/include/asm/ioctl.h
6137 + * arch/ubicom32/include/asm/ioctl.h
6138 + * Generic ioctl.h for Ubicom32 architecture.
6140 + * (C) Copyright 2009, Ubicom, Inc.
6142 + * This file is part of the Ubicom32 Linux Kernel Port.
6144 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
6145 + * it and/or modify it under the terms of the GNU General Public License
6146 + * as published by the Free Software Foundation, either version 2 of the
6147 + * License, or (at your option) any later version.
6149 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
6150 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
6151 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
6152 + * the GNU General Public License for more details.
6154 + * You should have received a copy of the GNU General Public License
6155 + * along with the Ubicom32 Linux Kernel Port. If not,
6156 + * see <http://www.gnu.org/licenses/>.
6158 + * Ubicom32 implementation derived from (with many thanks):
6163 +#ifndef _ASM_UBICOM32_IOCTL_H
6164 +#define _ASM_UBICOM32_IOCTL_H
6166 +#include <asm-generic/ioctl.h>
6168 +#endif /* _ASM_UBICOM32_IOCTL_H */
6170 +++ b/arch/ubicom32/include/asm/ioctls.h
6173 + * arch/ubicom32/include/asm/ioctls.h
6174 + * Definitions of ioctls for Ubicom32 architecture.
6176 + * (C) Copyright 2009, Ubicom, Inc.
6178 + * This file is part of the Ubicom32 Linux Kernel Port.
6180 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
6181 + * it and/or modify it under the terms of the GNU General Public License
6182 + * as published by the Free Software Foundation, either version 2 of the
6183 + * License, or (at your option) any later version.
6185 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
6186 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
6187 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
6188 + * the GNU General Public License for more details.
6190 + * You should have received a copy of the GNU General Public License
6191 + * along with the Ubicom32 Linux Kernel Port. If not,
6192 + * see <http://www.gnu.org/licenses/>.
6194 + * Ubicom32 implementation derived from (with many thanks):
6199 +#ifndef _ASM_UBICOM32_IOCTLS_H
6200 +#define _ASM_UBICOM32_IOCTLS_H
6202 +#include <asm/ioctl.h>
6204 +/* 0x54 is just a magic number to make these relatively unique ('T') */
6206 +#define TCGETS 0x5401
6207 +#define TCSETS 0x5402
6208 +#define TCSETSW 0x5403
6209 +#define TCSETSF 0x5404
6210 +#define TCGETA 0x5405
6211 +#define TCSETA 0x5406
6212 +#define TCSETAW 0x5407
6213 +#define TCSETAF 0x5408
6214 +#define TCSBRK 0x5409
6215 +#define TCXONC 0x540A
6216 +#define TCFLSH 0x540B
6217 +#define TIOCEXCL 0x540C
6218 +#define TIOCNXCL 0x540D
6219 +#define TIOCSCTTY 0x540E
6220 +#define TIOCGPGRP 0x540F
6221 +#define TIOCSPGRP 0x5410
6222 +#define TIOCOUTQ 0x5411
6223 +#define TIOCSTI 0x5412
6224 +#define TIOCGWINSZ 0x5413
6225 +#define TIOCSWINSZ 0x5414
6226 +#define TIOCMGET 0x5415
6227 +#define TIOCMBIS 0x5416
6228 +#define TIOCMBIC 0x5417
6229 +#define TIOCMSET 0x5418
6230 +#define TIOCGSOFTCAR 0x5419
6231 +#define TIOCSSOFTCAR 0x541A
6232 +#define FIONREAD 0x541B
6233 +#define TIOCINQ FIONREAD
6234 +#define TIOCLINUX 0x541C
6235 +#define TIOCCONS 0x541D
6236 +#define TIOCGSERIAL 0x541E
6237 +#define TIOCSSERIAL 0x541F
6238 +#define TIOCPKT 0x5420
6239 +#define FIONBIO 0x5421
6240 +#define TIOCNOTTY 0x5422
6241 +#define TIOCSETD 0x5423
6242 +#define TIOCGETD 0x5424
6243 +#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */
6244 +#define TIOCSBRK 0x5427 /* BSD compatibility */
6245 +#define TIOCCBRK 0x5428 /* BSD compatibility */
6246 +#define TIOCGSID 0x5429 /* Return the session ID of FD */
6247 +#define TCGETS2 _IOR('T',0x2A, struct termios2)
6248 +#define TCSETS2 _IOW('T',0x2B, struct termios2)
6249 +#define TCSETSW2 _IOW('T',0x2C, struct termios2)
6250 +#define TCSETSF2 _IOW('T',0x2D, struct termios2)
6251 +#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
6252 +#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
6254 +#define FIONCLEX 0x5450 /* these numbers need to be adjusted. */
6255 +#define FIOCLEX 0x5451
6256 +#define FIOASYNC 0x5452
6257 +#define TIOCSERCONFIG 0x5453
6258 +#define TIOCSERGWILD 0x5454
6259 +#define TIOCSERSWILD 0x5455
6260 +#define TIOCGLCKTRMIOS 0x5456
6261 +#define TIOCSLCKTRMIOS 0x5457
6262 +#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
6263 +#define TIOCSERGETLSR 0x5459 /* Get line status register */
6264 +#define TIOCSERGETMULTI 0x545A /* Get multiport config */
6265 +#define TIOCSERSETMULTI 0x545B /* Set multiport config */
6267 +#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
6268 +#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
6269 +#define FIOQSIZE 0x545E
6271 +/* Used for packet mode */
6272 +#define TIOCPKT_DATA 0
6273 +#define TIOCPKT_FLUSHREAD 1
6274 +#define TIOCPKT_FLUSHWRITE 2
6275 +#define TIOCPKT_STOP 4
6276 +#define TIOCPKT_START 8
6277 +#define TIOCPKT_NOSTOP 16
6278 +#define TIOCPKT_DOSTOP 32
6280 +#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
6282 +#endif /* _ASM_UBICOM32_IOCTLS_H */
6284 +++ b/arch/ubicom32/include/asm/io.h
6287 + * arch/ubicom32/include/asm/io.h
6288 + * I/O memory accessor functions for Ubicom32 architecture.
6290 + * (C) Copyright 2009, Ubicom, Inc.
6292 + * This file is part of the Ubicom32 Linux Kernel Port.
6294 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
6295 + * it and/or modify it under the terms of the GNU General Public License
6296 + * as published by the Free Software Foundation, either version 2 of the
6297 + * License, or (at your option) any later version.
6299 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
6300 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
6301 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
6302 + * the GNU General Public License for more details.
6304 + * You should have received a copy of the GNU General Public License
6305 + * along with the Ubicom32 Linux Kernel Port. If not,
6306 + * see <http://www.gnu.org/licenses/>.
6308 + * Ubicom32 implementation derived from (with many thanks):
6313 +#ifndef _ASM_UBICOM32_IO_H
6314 +#define _ASM_UBICOM32_IO_H
6317 +#include <linux/string.h>
6318 +#include <linux/compiler.h>
6320 +static inline unsigned short _swapw(volatile unsigned short v)
6322 + return ((v << 8) | (v >> 8));
6325 +static inline unsigned int _swapl(volatile unsigned long v)
6327 + return ((v << 24) | ((v & 0xff00) << 8) | ((v & 0xff0000) >> 8) | (v >> 24));
6331 +#define readb(addr) \
6332 + ({ unsigned char __v = (*(volatile unsigned char *) (addr)); __v; })
6333 +#define readw(addr) \
6334 + ({ unsigned short __v = (*(volatile unsigned short *) (addr)); __v; })
6335 +#define readl(addr) \
6336 + ({ unsigned int __v = (*(volatile unsigned int *) (addr)); __v; })
6338 +#define writeb(b,addr) (void)((*(volatile unsigned char *) (addr)) = (b))
6339 +#define writew(b,addr) (void)((*(volatile unsigned short *) (addr)) = (b))
6340 +#define writel(b,addr) (void)((*(volatile unsigned int *) (addr)) = (b))
6341 +#else /*CONFIG_PCI */
6343 +#define PCI_CPU_REG_BASE (0x00000000UL) /* taking lower 2GB space */
6344 +#define PCI_DEV_REG_BASE (0x80000000UL)
6346 +#if PCI_CPU_REG_BASE > PCI_DEV_REG_BASE
6347 +#define IS_PCI_ADDRESS(x) (((unsigned int)(x)&(PCI_CPU_REG_BASE)) == 0)
6349 +#define IS_PCI_ADDRESS(x) ((unsigned int)(x)&(PCI_DEV_REG_BASE))
6352 +extern unsigned int ubi32_pci_read_u32(const volatile void __iomem *addr);
6353 +extern unsigned short ubi32_pci_read_u16(const volatile void __iomem *addr);
6354 +extern unsigned char ubi32_pci_read_u8(const volatile void __iomem *addr);
6355 +extern void ubi32_pci_write_u32(unsigned int val, const volatile void __iomem *addr);
6356 +extern void ubi32_pci_write_u16(unsigned short val, const volatile void __iomem *addr);
6357 +extern void ubi32_pci_write_u8(unsigned char val, const volatile void __iomem *addr);
6359 +static inline unsigned char readb(const volatile void __iomem *addr)
6361 + if (IS_PCI_ADDRESS(addr))
6362 + return ubi32_pci_read_u8(addr);
6364 + return (unsigned char)(*(volatile unsigned char *)addr);
6366 +static inline unsigned short readw(const volatile void __iomem *addr)
6368 + if (IS_PCI_ADDRESS(addr))
6369 + return ubi32_pci_read_u16(addr);
6371 + return (unsigned short)(*(volatile unsigned short *)addr);
6374 +static inline unsigned int readl(const volatile void __iomem *addr)
6376 + if (IS_PCI_ADDRESS(addr))
6377 + return ubi32_pci_read_u32(addr);
6379 + return (unsigned int)(*(volatile unsigned int *)addr);
6382 +static inline void writel(unsigned int val, volatile void __iomem *addr)
6384 + if (IS_PCI_ADDRESS(addr))
6385 + ubi32_pci_write_u32(val, addr);
6387 + *(volatile unsigned int *)addr = val;
6390 +static inline void writew(unsigned short val, volatile void __iomem *addr)
6392 + if (IS_PCI_ADDRESS(addr))
6393 + ubi32_pci_write_u16(val, addr);
6395 + *(volatile unsigned short *)addr = val;
6398 +static inline void writeb(unsigned char val, volatile void __iomem *addr)
6400 + if (IS_PCI_ADDRESS(addr))
6401 + ubi32_pci_write_u8(val, addr);
6403 + *(volatile unsigned char *)addr = val;
6407 +#define readb_relaxed(addr) readb(addr)
6408 +#define readw_relaxed(addr) readw(addr)
6409 +#define readl_relaxed(addr) readl(addr)
6412 +#define __raw_readb readb
6413 +#define __raw_readw readw
6414 +#define __raw_readl readl
6415 +#define __raw_writeb writeb
6416 +#define __raw_writew writew
6417 +#define __raw_writel writel
6419 +static inline void io_outsb(unsigned int addr, const void *buf, int len)
6421 + volatile unsigned char *ap = (volatile unsigned char *) addr;
6422 + unsigned char *bp = (unsigned char *) buf;
6427 +static inline void io_outsw(unsigned int addr, const void *buf, int len)
6429 + volatile unsigned short *ap = (volatile unsigned short *) addr;
6430 + unsigned short *bp = (unsigned short *) buf;
6432 + *ap = _swapw(*bp++);
6435 +static inline void io_outsl(unsigned int addr, const void *buf, int len)
6437 + volatile unsigned int *ap = (volatile unsigned int *) addr;
6438 + unsigned int *bp = (unsigned int *) buf;
6440 + *ap = _swapl(*bp++);
6443 +static inline void io_insb(unsigned int addr, void *buf, int len)
6445 + volatile unsigned char *ap = (volatile unsigned char *) addr;
6446 + unsigned char *bp = (unsigned char *) buf;
6451 +static inline void io_insw(unsigned int addr, void *buf, int len)
6453 + volatile unsigned short *ap = (volatile unsigned short *) addr;
6454 + unsigned short *bp = (unsigned short *) buf;
6456 + *bp++ = _swapw(*ap);
6459 +static inline void io_insl(unsigned int addr, void *buf, int len)
6461 + volatile unsigned int *ap = (volatile unsigned int *) addr;
6462 + unsigned int *bp = (unsigned int *) buf;
6464 + *bp++ = _swapl(*ap);
6470 + * make the short names macros so specific devices
6471 + * can override them as required
6474 +#define memset_io(a,b,c) memset((void *)(a),(b),(c))
6475 +#define memcpy_fromio(a,b,c) memcpy((a),(void *)(b),(c))
6476 +#define memcpy_toio(a,b,c) memcpy((void *)(a),(b),(c))
6478 +extern void memcpy_fromio(void *to, const volatile void __iomem *from, unsigned len);
6479 +extern void memcpy_toio(volatile void __iomem *to, const void *from, unsigned len);
6480 +extern void memset_io(volatile void __iomem *addr, int val, size_t count);
6483 +#define inb(addr) readb(addr)
6484 +#define inw(addr) readw(addr)
6485 +#define inl(addr) readl(addr)
6486 +#define outb(x,addr) ((void) writeb(x,addr))
6487 +#define outw(x,addr) ((void) writew(x,addr))
6488 +#define outl(x,addr) ((void) writel(x,addr))
6490 +#define inb_p(addr) inb(addr)
6491 +#define inw_p(addr) inw(addr)
6492 +#define inl_p(addr) inl(addr)
6493 +#define outb_p(x,addr) outb(x,addr)
6494 +#define outw_p(x,addr) outw(x,addr)
6495 +#define outl_p(x,addr) outl(x,addr)
6497 +#define outsb(a,b,l) io_outsb(a,b,l)
6498 +#define outsw(a,b,l) io_outsw(a,b,l)
6499 +#define outsl(a,b,l) io_outsl(a,b,l)
6501 +#define insb(a,b,l) io_insb(a,b,l)
6502 +#define insw(a,b,l) io_insw(a,b,l)
6503 +#define insl(a,b,l) io_insl(a,b,l)
6506 +#define ioread8_rep(a,d,c) insb(a,d,c)
6507 +#define ioread16_rep(a,d,c) insw(a,d,c)
6508 +#define ioread32_rep(a,d,c) insl(a,d,c)
6509 +#define iowrite8_rep(a,s,c) outsb(a,s,c)
6510 +#define iowrite16_rep(a,s,c) outsw(a,s,c)
6511 +#define iowrite32_rep(a,s,c) outsl(a,s,c)
6513 +extern void ioread8_rep(void __iomem *port, void *buf, unsigned long count);
6514 +extern void ioread16_rep(void __iomem *port, void *buf, unsigned long count);
6515 +extern void ioread32_rep(void __iomem *port, void *buf, unsigned long count);
6516 +extern void iowrite8_rep(void __iomem *port, const void *buf, unsigned long count);
6517 +extern void iowrite16_rep(void __iomem *port, const void *buf, unsigned long count);
6518 +extern void iowrite32_rep(void __iomem *port, const void *buf, unsigned long count);
6523 +#define ioread8(X) readb(X)
6524 +#define ioread16(X) readw(X)
6525 +#define ioread32(X) readl(X)
6526 +#define iowrite8(val,X) writeb(val,X)
6527 +#define iowrite16(val,X) writew(val,X)
6528 +#define iowrite32(val,X) writel(val,X)
6529 +#else /*CONFIG_PCI */
6530 +extern unsigned char ioread8(void __iomem *addr);
6531 +extern unsigned short ioread16(void __iomem *addr);
6532 +extern unsigned int ioread32(void __iomem *addr);
6533 +extern void iowrite8(unsigned char val, void __iomem *addr);
6534 +extern void iowrite16(unsigned short val, void __iomem *addr);
6535 +extern void iowrite32(unsigned int val, void __iomem *addr);
6536 +#endif /* CONFIG_PCI */
6538 +#define IO_SPACE_LIMIT 0xffff
6540 +/* Values for nocacheflag and cmode */
6541 +#define IOMAP_FULL_CACHING 0
6542 +#define IOMAP_NOCACHE_SER 1
6543 +#define IOMAP_NOCACHE_NONSER 2
6544 +#define IOMAP_WRITETHROUGH 3
6546 +extern void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag);
6547 +extern void __iounmap(void *addr, unsigned long size);
6549 +static inline void *ioremap(unsigned long physaddr, unsigned long size)
6551 + return __ioremap(physaddr, size, IOMAP_NOCACHE_SER);
6553 +static inline void *ioremap_nocache(unsigned long physaddr, unsigned long size)
6555 + return __ioremap(physaddr, size, IOMAP_NOCACHE_SER);
6557 +static inline void *ioremap_writethrough(unsigned long physaddr, unsigned long size)
6559 + return __ioremap(physaddr, size, IOMAP_WRITETHROUGH);
6561 +static inline void *ioremap_fullcache(unsigned long physaddr, unsigned long size)
6563 + return __ioremap(physaddr, size, IOMAP_FULL_CACHING);
6566 +extern void iounmap(void *addr);
6568 +#define ioport_map(port, nr) ((void __iomem*)(port))
6569 +#define ioport_unmap(addr)
6572 +/* Pages to physical address... */
6573 +#define page_to_phys(page) ((page - mem_map) << PAGE_SHIFT)
6574 +#define page_to_bus(page) ((page - mem_map) << PAGE_SHIFT)
6577 + * Macros used for converting between virtual and physical mappings.
6579 +#define phys_to_virt(vaddr) ((void *) (vaddr))
6580 +#define virt_to_phys(vaddr) ((unsigned long) (vaddr))
6582 +#define virt_to_bus virt_to_phys
6583 +#define bus_to_virt phys_to_virt
6586 + * Convert a physical pointer to a virtual kernel pointer for /dev/mem
6589 +#define xlate_dev_mem_ptr(p) __va(p)
6592 + * Convert a virtual cached pointer to an uncached pointer
6594 +#define xlate_dev_kmem_ptr(p) p
6596 +#endif /* __KERNEL__ */
6598 +#endif /* _ASM_UBICOM32_IO_H */
6600 +++ b/arch/ubicom32/include/asm/ip5000-asm.h
6603 + * arch/ubicom32/include/asm/ip5000-asm.h
6604 + * Instruction macros for the IP5000.
6606 + * (C) Copyright 2009, Ubicom, Inc.
6608 + * This file is part of the Ubicom32 Linux Kernel Port.
6610 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
6611 + * it and/or modify it under the terms of the GNU General Public License
6612 + * as published by the Free Software Foundation, either version 2 of the
6613 + * License, or (at your option) any later version.
6615 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
6616 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
6617 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
6618 + * the GNU General Public License for more details.
6620 + * You should have received a copy of the GNU General Public License
6621 + * along with the Ubicom32 Linux Kernel Port. If not,
6622 + * see <http://www.gnu.org/licenses/>.
6624 + * Ubicom32 implementation derived from (with many thanks):
6630 +#ifndef _ASM_UBICOM32_IP5000_ASM_H
6631 +#define _ASM_UBICOM32_IP5000_ASM_H
6633 +#if !defined(__LINKER__)
6635 +#if defined(__ASSEMBLY__)
6636 +.macro cycles quant
6640 +.if (((\quant) + 3) / 8) > 0
6641 +.rept (((\quant) + 3) / 8)
6645 +.if ((((\quant) + 3) % 8) / 4) > 0
6652 + * Same macro as above just in C inline asm
6655 +.macro cycles quant \n\
6656 +.if (\\quant) == 1 \n\
6659 +.if (((\\quant) + 3) / 8) > 0 \n\
6660 +.rept (((\\quant) + 3) / 8) \n\
6664 +.if ((((\\quant) + 3) % 8) / 4) > 0 \n\
6673 +#if defined(__ASSEMBLY__)
6674 +.macro pipe_flush cyc
6675 + cycles 11 - (\cyc)
6679 + * Same macro as above just in C inline asm
6682 +.macro pipe_flush cyc \n\
6683 + cycles 11 - (\\cyc) \n\
6689 +#if defined(__ASSEMBLY__)
6690 +.macro setcsr_flush cyc
6695 + * Same macro as above just in C inline asm
6698 +.macro setcsr_flush cyc \n\
6699 + cycles 5 - (\\cyc) \n\
6705 + * Macros for prefetch (using miss-aligned memory write)
6707 +#if defined(__ASSEMBLY__)
6709 +.macro pre_fetch_macro thread_num, Ascratch, Aaddress length
6710 + bclr MT_TRAP_EN, MT_TRAP_EN, #(\thread_num)
6711 + bset \Ascratch, \Aaddress, #0 ; force a miss-aligned address
6712 + jmpt.t .+4 ; delay for both address setup and trap disable
6713 + move.4 (\Ascratch), #0
6714 + .if (\length > 32)
6715 + move.4 32(\Ascratch), #0
6717 + .if (\length > 64)
6718 + move.4 64(\Ascratch), #0
6720 + .if (\length > 96)
6721 + move.4 96(\Ascratch), #0
6723 + .if (\length > 128)
6724 + invalid_instruction ; maximum pre-fetch size is 4 cache lines
6726 + bset MT_TRAP_EN, MT_TRAP_EN, #(\thread_num)
6731 + * Same macro as above just in C inline asm
6734 +.macro pre_fetch_macro thread_num, Ascratch, Aaddress length \n\
6735 + bclr MT_TRAP_EN, MT_TRAP_EN, #(\thread_num) \n\
6736 + bset \\Ascratch, \\Aaddress, #0 ; force a miss-aligned address \n\
6737 + jmpt.t .+4 ; delay for both address setup and trap disable \n\
6738 + move.4 (\\Ascratch), #0 \n\
6739 + .if (\\length > 32) \n\
6740 + move.4 32(\\Ascratch), #0 \n\
6742 + .if (\\length > 64) \n\
6743 + move.4 64(\\Ascratch), #0 \n\
6745 + .if (\\length > 96) \n\
6746 + move.4 96(\\Ascratch), #0 \n\
6748 + .if (\\length > 128) \n\
6749 + invalid_instruction ; maximum pre-fetch size is 4 cache lines \n\
6751 + bset MT_TRAP_EN, MT_TRAP_EN, #(\\thread_num) \n\
6756 +#endif /* !defined(__LINKER__) */
6757 +#endif /* defined _ASM_UBICOM32_IP5000_ASM_H */
6759 +++ b/arch/ubicom32/include/asm/ip5000.h
6762 + * arch/ubicom32/include/asm/ip5000.h
6763 + * Specific details for the Ubicom IP5000 processor.
6765 + * (C) Copyright 2009, Ubicom, Inc.
6767 + * This file is part of the Ubicom32 Linux Kernel Port.
6769 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
6770 + * it and/or modify it under the terms of the GNU General Public License
6771 + * as published by the Free Software Foundation, either version 2 of the
6772 + * License, or (at your option) any later version.
6774 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
6775 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
6776 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
6777 + * the GNU General Public License for more details.
6779 + * You should have received a copy of the GNU General Public License
6780 + * along with the Ubicom32 Linux Kernel Port. If not,
6781 + * see <http://www.gnu.org/licenses/>.
6783 + * Ubicom32 implementation derived from (with many thanks):
6789 +#ifndef _ASM_UBICOM32_IP5000_H
6790 +#define _ASM_UBICOM32_IP5000_H
6792 +#include <asm/memory_map.h>
6795 + * Inline assembly define
6797 +#define S(arg) #arg
6798 +#define D(arg) S(arg)
6801 + * Assembler include file
6803 +#include <asm/ip5000-asm.h>
6808 +#define JMPT_PENALTY 3
6809 +#define JMPF_PENALTY 7
6810 +#define RET_PENALTY 7
6815 +#if defined(IP5000) || defined(IP5000_REV2)
6816 +#define THREAD_COUNT 10
6817 +#elif defined(IP7000) || defined(IP7000_REV2)
6818 +#define THREAD_COUNT 12
6820 +#error "Unknown IP5K silicon"
6826 +#if defined(IP5000) || defined(IP5000_REV2)
6827 +#define UBICOM32_ARCH_VERSION 3
6828 +#elif defined(IP7000) || defined(IP7000_REV2)
6829 +#define UBICOM32_ARCH_VERSION 4
6831 +#error "Unknown IP5K silicon"
6838 +#define ROSR_INT (1 << 0)
6841 +#define INT_CHIP(reg, bit) (((reg) << 5) | (bit))
6842 +#define INT_REG(interrupt) (((interrupt) >> 5) * 4)
6843 +#define INT_SET(interrupt) 0x0114 + INT_REG(interrupt)
6844 +#define INT_CLR(interrupt) 0x0124 + INT_REG(interrupt)
6845 +#define INT_STAT(interrupt) 0x0104 + INT_REG(interrupt)
6846 +#define INT_MASK(interrupt) 0x00C0 + INT_REG(interrupt)
6847 +#define INT_BIT(interrupt) ((interrupt) & 0x1F)
6848 +#define INT_BIT_MASK(interrupt) (1 << INT_BIT(interrupt))
6851 + * The LOCK_INT and THREAD_INT are used to wake up corresponding thread. They are sharing
6852 + * the same set of SW interrupt resource.
6854 + * LOCK_INT(n): One SW INT per NRT thread that can participate lock operation.
6855 + * The threads that can participate lock are application threads and DSR thread.
6856 + * (Lock locks - numbers are hard-coded in lock.h)
6857 + * THREAD_INT(n): One SW INT per HRT thread for wake up trigger.
6859 +#define LOCK_INT(thread) INT_CHIP(0, (thread))
6860 +#define THREAD_INT(thread) INT_CHIP(0, (thread))
6863 + * The SYSTEM_INT and DSR_INT are sharing the same set of SW interrupt resource.
6865 + * SYSTEM_INT(n): One SW INT per NRT threads (application threads) as system queue interrupt,
6866 + * and for DSR as self-trigger interrupt.
6867 + * (The application threads include at least thread 0)
6868 + * DSR_INT(n): One SW INT per HRT thread to request DSR service.
6870 +#define SYSTEM_INT(thread) INT_CHIP(0, THREAD_COUNT + (thread))
6871 +#define DSR_INT(thread) INT_CHIP(0, THREAD_COUNT + (thread))
6874 +#define GLOBAL_CTRL_TRAP_RST_EN (1 << 9)
6875 +#define GLOBAL_CTRL_AERROR_RST_EN (1 << 8)
6876 +#define GLOBAL_CTRL_MT_MIN_DELAY(x) ((x) << 3)
6877 +#define GLOBAL_CTRL_HRT_BANK_SELECT (1 << 2)
6878 +#define GLOBAL_CTRL_INT_EN (1 << 0)
6883 +#define HRT_TABLE0_BASE 0x0800
6884 +#define HRT_TABLE1_BASE 0x0900
6885 +#define HRT_TABLE_SIZE 64
6888 + * Break Point Trap Register
6890 +#define ASYNCERROR_INT INT_CHIP(0, 31)
6891 +#define BREAKPOINT_INT INT_CHIP(1, 31)
6895 + * The non-existing FIFO INTs are mapped to INT2 for the ports.
6897 +#define IO_PORT_PTR_TO_NUM(port) (((port) & 0x0000ffff) >> 12)
6898 +#define RX_FIFO_INT(port) \
6899 + ((IO_PORT_PTR_TO_NUM(port) == 0) ? INT_CHIP(0, 25) : \
6900 + ((IO_PORT_PTR_TO_NUM(port) == 1) ? INT_CHIP(0, 26) : \
6901 + ((IO_PORT_PTR_TO_NUM(port) == 2) ? INT_CHIP(0, 29) : \
6902 + ((IO_PORT_PTR_TO_NUM(port) == 3) ? INT_CHIP(1, 24) : \
6903 + ((IO_PORT_PTR_TO_NUM(port) == 4) ? INT_CHIP(1, 27) : \
6904 + ((IO_PORT_PTR_TO_NUM(port) == 5) ? INT_CHIP(1, 16) : \
6905 + ((IO_PORT_PTR_TO_NUM(port) == 6) ? INT_CHIP(1, 19) : \
6906 + ((IO_PORT_PTR_TO_NUM(port) == 7) ? INT_CHIP(1, 20) : \
6907 + ((IO_PORT_PTR_TO_NUM(port) == 8) ? INT_CHIP(1, 21) : \
6908 + INT_CHIP(1, 15))))))))))
6909 +#define TX_FIFO_INT(port) \
6910 + ((IO_PORT_PTR_TO_NUM(port) == 0) ? INT_CHIP(0, 24) : \
6911 + ((IO_PORT_PTR_TO_NUM(port) == 1) ? INT_CHIP(0, 27) : \
6912 + ((IO_PORT_PTR_TO_NUM(port) == 2) ? INT_CHIP(0, 29) : \
6913 + ((IO_PORT_PTR_TO_NUM(port) == 3) ? INT_CHIP(1, 25) : \
6914 + ((IO_PORT_PTR_TO_NUM(port) == 4) ? INT_CHIP(1, 28) : \
6915 + ((IO_PORT_PTR_TO_NUM(port) == 5) ? INT_CHIP(1, 17) : \
6916 + ((IO_PORT_PTR_TO_NUM(port) == 6) ? INT_CHIP(1, 19) : \
6917 + ((IO_PORT_PTR_TO_NUM(port) == 7) ? INT_CHIP(1, 20) : \
6918 + ((IO_PORT_PTR_TO_NUM(port) == 8) ? INT_CHIP(1, 22) : \
6919 + INT_CHIP(1, 15))))))))))
6920 +#define PORT_OTHER_INT(port) \
6921 + ((IO_PORT_PTR_TO_NUM(port) == 0) ? INT_CHIP(0, 25) : \
6922 + ((IO_PORT_PTR_TO_NUM(port) == 1) ? INT_CHIP(0, 28) : \
6923 + ((IO_PORT_PTR_TO_NUM(port) == 2) ? INT_CHIP(0, 29) : \
6924 + ((IO_PORT_PTR_TO_NUM(port) == 3) ? INT_CHIP(1, 26) : \
6925 + ((IO_PORT_PTR_TO_NUM(port) == 4) ? INT_CHIP(1, 29) : \
6926 + ((IO_PORT_PTR_TO_NUM(port) == 5) ? INT_CHIP(1, 18) : \
6927 + ((IO_PORT_PTR_TO_NUM(port) == 6) ? INT_CHIP(1, 19) : \
6928 + ((IO_PORT_PTR_TO_NUM(port) == 7) ? INT_CHIP(1, 20) : \
6929 + ((IO_PORT_PTR_TO_NUM(port) == 8) ? INT_CHIP(1, 23) : \
6930 + INT_CHIP(1, 15))))))))))
6933 + * On Chip Peripherals Base.
6935 +#define OCP_BASE 0x01000000
6936 +#define OCP_GENERAL 0x000
6937 +#define OCP_TIMERS 0x100
6938 +#define OCP_TRNG 0x200 /* True Random Number Generator Control Reigsters */
6939 +#define OCP_DEBUG 0x300
6940 +#define OCP_SECURITY 0x400
6941 +#define OCP_ICCR 0x500 /* I-Cache Control Registers */
6942 +#define OCP_DCCR 0x600 /* D-Cache Control Registers */
6943 +#define OCP_OCMC 0x700 /* On Chip Memory Control Registers */
6944 +#define OCP_STATISTICS 0x800 /* Statistics Counters */
6945 +#define OCP_MTEST 0x900 /* Memory Test Registers */
6946 +#define OCP_MCFG 0xa00 /* Memory Configuration Registers -- IP7000 only */
6947 +#define OCP_DEBUG_INST 0x000 /* Up to 16M */
6950 + * General Configuration Registers (PLL)
6952 +#define GENERAL_CFG_BASE (OCP_BASE + OCP_GENERAL)
6953 +#define GEN_CLK_CORE_CFG 0x00
6954 +#define GEN_CLK_IO_CFG 0x04
6955 +#define GEN_CLK_DDR_CFG 0x08
6956 +#define GEN_CLK_DDRDS_CFG 0x0c
6957 +#define GEN_CLK_SLIP_CLR 0x10
6958 +#define GEN_CLK_SLIP_START 0x14
6959 +#define GEN_CLK_SERDES_SEL 0x18 /* IP7000 only */
6960 +#define GEN_CLK_DDR_CFG2 0x1c /* IP7000 only */
6961 +#define GEN_DDR_CAL_CTRL 0x30 /* IP5000 only */
6962 +#define GEN_DDR_CAL_STAT 0x34 /* IP5000 only */
6963 +#define GEN_USB_DFT_CTRL 0x38 /* IP5000 only */
6964 +#define GEN_USB_DFT_STAT 0x3c /* IP5000 only */
6965 +#define GEN_USB_PHY_CFG 0x40 /* IP7000 only */
6966 +#define GEN_USB_PHY_TEST 0x44 /* IP7000 only */
6967 +#define GEN_USB_PHY_STAT 0x48 /* IP7000 only */
6968 +#define GEN_SW_RESET 0x80
6969 +#define GEN_RESET_REASON 0x84
6970 +#define GEN_BOND_CFG 0x88
6971 +#define GEN_IO_PU_CFG 0x8c
6972 +#define GEN_MEM_RM_CFG 0x90
6973 +#define GEN_IO_CONFIG 0x94
6975 +#define GEN_CLK_PLL_SECURITY_BIT_NO 31
6976 +#define GEN_CLK_PLL_SECURITY (1 << GEN_CLK_PLL_SECURITY_BIT_NO)
6977 +#define GEN_CLK_PLL_ENSAT (1 << 30)
6978 +#define GEN_CLK_PLL_FASTEN (1 << 29)
6979 +#define GEN_CLK_PLL_NR(v) (((v) - 1) << 23)
6980 +#define GEN_CLK_PLL_NF(v) (((v) - 1) << 11)
6981 +#define GEN_CLK_PLL_OD(v) (((v) - 1) << 8)
6982 +#define GEN_CLK_PLL_RESET (1 << 7)
6983 +#define GEN_CLK_PLL_BYPASS (1 << 6)
6984 +#define GEN_CLK_PLL_POWERDOWN (1 << 5)
6985 +#define GEN_CLK_PLL_SELECT (1 << 4)
6987 +#define GEN_GET_CLK_PLL_NR(v) ((((v) >> 23) & 0x003f) + 1)
6988 +#define GEN_GET_CLK_PLL_NF(v) ((((v) >> 11) & 0x0fff) + 1)
6989 +#define GEN_GET_CLK_PLL_OD(v) ((((v) >> 8) & 0x7) + 1)
6992 +#define RESET_FLAG_DST_MEM_ERROR (1 << 18)
6993 +#define RESET_FLAG_SRC1_MEM_ERROR (1 << 17)
6994 +#define RESET_FLAG_WRITE_ADDR (1 << 16)
6995 +#define RESET_FLAG_DST_SYNC_ERROR (1 << 15)
6996 +#define RESET_FLAG_SRC1_SYNC_ERROR (1 << 14)
6997 +#define RESET_FLAG_DST_ALGN_ERROR (1 << 13)
6998 +#define RESET_FLAG_SRC1_ALGN_ERROR (1 << 12)
6999 +#define RESET_FLAG_DST_ADDR_ERROR (1 << 11)
7000 +#define RESET_FLAG_SRC1_ADDR_ERROR (1 << 10)
7001 +#define RESET_FLAG_ILLEGAL_INST (1 << 9)
7002 +#define RESET_FLAG_INST_SYNC_ERROR (1 << 8)
7003 +#define RESET_FLAG_INST_ADDR_ERROR (1 << 7)
7004 +#define RESET_FLAG_DATA_PORT_ERROR (1 << 6)
7005 +#define RESET_FLAG_INST_PORT_ERROR (1 << 5)
7006 +#define RESET_FLAG_SW_RESET (1 << 4)
7007 +#define RESET_FLAG_DEBUG (1 << 3)
7008 +#define RESET_FLAG_WATCHDOG (1 << 2)
7009 +#define RESET_FLAG_POWER_ON (1 << 1)
7010 +#define RESET_FLAG_EXTERNAL (1 << 0)
7015 +#define TIMER_BASE (OCP_BASE + OCP_TIMERS)
7016 +#define TIMER_MPTVAL 0x00
7017 +#define TIMER_RTCOM 0x04
7018 +#define TIMER_TKEY 0x08
7019 +#define TIMER_WDCOM 0x0c
7020 +#define TIMER_WDCFG 0x10
7021 +#define TIMER_SYSVAL 0x14
7022 +#define TIMER_SYSCOM(tmr) (0x18 + (tmr) * 4)
7023 +#define TIMER_TRN_CFG 0x100
7024 +#define TIMER_TRN 0x104
7026 +#define TIMER_COUNT 10
7027 +#define TIMER_INT(tmr) INT_CHIP(1, (tmr))
7028 +#define TIMER_TKEYVAL 0xa1b2c3d4
7029 +#define TIMER_WATCHDOG_DISABLE 0x4d3c2b1a
7030 +#define TIMER_TRN_CFG_ENABLE_OSC 0x00000007
7032 +#ifndef __ASSEMBLY__
7034 + * ubicom32_io_timer
7036 +struct ubicom32_io_timer {
7037 + volatile u32_t mptval;
7038 + volatile u32_t rtcom;
7039 + volatile u32_t tkey;
7040 + volatile u32_t wdcom;
7041 + volatile u32_t wdcfg;
7042 + volatile u32_t sysval;
7043 + volatile u32_t syscom[TIMER_COUNT];
7044 + volatile u32_t reserved[64 - 6 - TIMER_COUNT]; // skip all the way to OCP-TRNG section
7045 + volatile u32_t rsgcfg;
7046 + volatile u32_t trn;
7049 +#define UBICOM32_IO_TIMER ((struct ubicom32_io_timer *)TIMER_BASE)
7052 +#define UBICOM32_VECTOR_TO_TIMER_INDEX(vector) (vector - TIMER_INT(0))
7055 + * OCP-Debug Module (Mailbox)
7057 +#define ISD_MAILBOX_BASE (OCP_BASE + OCP_DEBUG)
7058 +#define ISD_MAILBOX_IN 0x00
7059 +#define ISD_MAILBOX_OUT 0x04
7060 +#define ISD_MAILBOX_STATUS 0x08
7062 +#define ISD_MAILBOX_INT INT_CHIP(1, 30)
7064 +#define ISD_MAILBOX_STATUS_IN_FULL (1 << 31)
7065 +#define ISD_MAILBOX_STATUS_IN_EMPTY (1 << 30)
7066 +#define ISD_MAILBOX_STATUS_OUT_FULL (1 << 29)
7067 +#define ISD_MAILBOX_STATUS_OUT_EMPTY (1 << 28)
7072 +#define SECURITY_BASE (OCP_BASE + OCP_SECURITY)
7073 +#define SECURITY_BASE_EFFECTIVE_ADDRESS (SECURITY_BASE >> 7) // To load the base address in a single instruction
7074 +#define SECURITY_CTRL 0x00
7075 +#define SECURITY_CTRL_BYTE_OFFSET(x) ((x) << 16)
7076 +#define SECURITY_CTRL_KEY_SIZE(x) ((x) << 8)
7077 +#define SECURITY_CTRL_HASH_ALG_NONE (0 << 4)
7078 +#define SECURITY_CTRL_HASH_ALG_MD5 (1 << 4)
7079 +#define SECURITY_CTRL_HASH_ALG_SHA1 (2 << 4)
7080 +#define SECURITY_CTRL_CBC (1 << 3)
7081 +#define SECURITY_CTRL_CIPHER_ALG_AES (0 << 1)
7082 +#define SECURITY_CTRL_CIPHER_ALG_NONE (1 << 1)
7083 +#define SECURITY_CTRL_CIPHER_ALG_DES (2 << 1)
7084 +#define SECURITY_CTRL_CIPHER_ALG_3DES (3 << 1)
7085 +#define SECURITY_CTRL_ENCIPHER (1 << 0)
7086 +#define SECURITY_CTRL_DECIPHER (0 << 0)
7087 +#define SECURITY_STAT 0x04
7088 +#define SECURITY_STAT_BUSY (1 << 0)
7089 +#define SECURITY_KEY_VALUE(x) (0x10 + (x) * 4)
7090 +#define SECURITY_KEY_IN(x) (0x30 + (x) * 4)
7091 +#define SECURITY_KEY_OUT(x) (0x50 + (x) * 4)
7092 +#define SECURITY_KEY_HASH(x) (0x70 + (x) * 4)
7097 +#define ICCR_BASE (OCP_BASE + OCP_ICCR)
7098 +#define ICACHE_TOTAL_SIZE 16384 /* in bytes */
7103 +#define DCCR_BASE (OCP_BASE + OCP_DCCR)
7104 +#if defined(IP5000) || defined(IP5000_REV2)
7105 +#define DCACHE_TOTAL_SIZE 8192 /* in bytes */
7106 +#elif defined(IP7000) || defined(IP7000_REV2)
7107 +#define DCACHE_TOTAL_SIZE 16384 /* in bytes */
7110 +#if defined(IP5000) || defined(IP5000_REV2) || defined(IP7000) || defined(IP7000_REV2)
7111 +#define DCACHE_WRITE_QUEUE_LENGTH 6
7113 +#error "Unknown IP5K silicon"
7116 +#define CACHE_LINE_SIZE 32 /* in bytes */
7118 +#define CCR_ADDR 0x00
7119 +#define CCR_RDD 0x04
7120 +#define CCR_WRD 0x08
7121 +#define CCR_STAT 0x0c
7122 +#define CCR_CTRL 0x10
7124 +#define CCR_STAT_MCBE 0
7125 +#define CCR_STAT_WIDEL 1 /* D-cache only */
7127 +#define CCR_CTRL_DONE 0
7128 +#define CCR_CTRL_RESET 2
7129 +#define CCR_CTRL_VALID 3
7130 +#define CCR_CTRL_RD_DATA (1 << 4)
7131 +#define CCR_CTRL_RD_TAG (2 << 4)
7132 +#define CCR_CTRL_WR_DATA (3 << 4)
7133 +#define CCR_CTRL_WR_TAG (4 << 4)
7134 +#define CCR_CTRL_INV_INDEX (5 << 4)
7135 +#define CCR_CTRL_INV_ADDR (6 << 4)
7136 +#define CCR_CTRL_FLUSH_INDEX (7 << 4) /* D-cache only */
7137 +#define CCR_CTRL_FLUSH_INV_INDEX (8 << 4) /* D-cache only */
7138 +#define CCR_CTRL_FLUSH_ADDR (9 << 4) /* D-cache only */
7139 +#define CCR_CTRL_FLUSH_INV_ADDR (10 << 4) /* D-cache only */
7144 +#define OCMC_BASE (OCP_BASE + OCP_OCMC)
7145 +#define OCMC_BANK_MASK 0x00
7146 +#define OCMC_BIST_CNTL 0x04 /* IP5000 only */
7147 +#define OCMC_BIST_STAT 0x08 /* IP5000 only */
7149 +#define OCMC_BANK_PROG(n) ((1<<(n))-1)
7151 +#define OCMC_BIST_WRCK (1 << 7)
7152 +#define OCMC_BIST_RESET (1 << 5)
7153 +#define OCMC_BIST_SMART (1 << 4)
7154 +#define OCMC_BIST_RUN (1 << 3)
7155 +#define OCMC_BIST_REPAIR (1 << 2)
7157 +#define OCMC_BIST_READY (1 << 3)
7158 +#define OCMC_BIST_FAIL (1 << 2)
7163 +#define STATISTICS_BASE (OCP_BASE + OCP_STATISTICS)
7164 +#define STAT_COUNTER_CTRL(n) ((n)*8)
7165 +#define STAT_COUNTER(n) ((n)*8 + 4)
7167 +#define STAT_EVENT_MP_INST 0
7168 +#define STAT_EVENT_OCM_ACCESS 4
7169 +#define STAT_EVENT_OCM_REQ 5
7170 +#define STAT_EVENT_IC_REQ_INVAL 13
7171 +#define STAT_EVENT_IC_MISS_INVAL 14
7172 +#define STAT_EVENT_IC_REQ_INVAL_NACK 15
7173 +#define STAT_EVENT_IC_REQ_VAL 16
7174 +#define STAT_EVENT_IC_MISS_VAL 17
7175 +#define STAT_EVENT_IC_REQ_VAL_NACK 18
7176 +#define STAT_EVENT_IC_MISS_Q 19
7177 +#define STAT_EVENT_DC_RD_REQ 20
7178 +#define STAT_EVENT_DC_RD_MISS 21
7179 +#define STAT_EVENT_DC_WR_REQ 22
7180 +#define STAT_EVENT_DC_WR_MISS 23
7181 +#define STAT_EVENT_DC_MISS_Q 24
7182 +#define STAT_EVENT_DC_WB_FULL 25
7183 +#define STAT_EVENT_DC_REQ_NACK 26
7184 +#define STAT_EVENT_DC_CORE_REQ 27
7185 +#define STAT_EVENT_DC_MISS 28
7186 +#define STAT_EVENT_DC_EVICT 29
7187 +#define STAT_EVENT_TRUE 30
7188 +#define STAT_EVENT_FALSE 31
7193 +#define MTEST_BASE (OCP_BASE + OCP_MTEST)
7194 +#define MTEST_ADDR 0x00
7195 +#define MTEST_WR 0x04
7196 +#define MTEST_RD 0x08
7197 +#define MTEST_CTRL 0x0c
7200 + * OCP_MCFG (IP7000 only)
7202 +#define MCFG_BASE (OCP_BASE + OCP_MCFG)
7203 +#define MCFG_CTRL 0x00
7204 +#define MCFG_WCFG 0x04
7205 +#define MCFG_RCFG 0x08
7210 +#define IO_BASE 0x02000000
7211 +#define RA (IO_BASE + 0x00000000)
7212 +#define RB (IO_BASE + 0x00001000)
7213 +#define RC (IO_BASE + 0x00002000)
7214 +#define RD (IO_BASE + 0x00003000)
7215 +#define RE (IO_BASE + 0x00004000)
7216 +#define RF (IO_BASE + 0x00005000)
7217 +#define RG (IO_BASE + 0x00006000)
7218 +#define RH (IO_BASE + 0x00007000)
7219 +#define RI (IO_BASE + 0x00008000)
7220 +#define RJ (IO_BASE + 0x00009000)
7221 +#define RLATCH (IO_BASE + 0x00ff0000) // For latched output only
7222 +#define IO_PORT_BR_OFFSET 0x00000800
7225 + * General I/O Register Map (per port)
7227 +#define IO_FUNC 0x00
7228 +#define IO_GPIO_CTL 0x04
7229 +#define IO_GPIO_OUT 0x08
7230 +#define IO_GPIO_IN 0x0C
7231 +#define IO_INT_STATUS 0x10
7232 +#define IO_INT_MASK 0x14
7233 +#define IO_INT_SET 0x18
7234 +#define IO_INT_CLR 0x1C
7235 +#define IO_TX_FIFO 0x20
7236 +#define IO_TX_FIFO_HI 0x24
7237 +#define IO_RX_FIFO 0x28
7238 +#define IO_RX_FIFO_HI 0x2c
7239 +#define IO_CTL0 0x30
7240 +#define IO_CTL1 0x34
7241 +#define IO_CTL2 0x38
7242 +#define IO_STATUS0 0x3c
7243 +#define IO_STATUS1 0x40
7244 +#define IO_STATUS2 0x44
7245 +#define IO_FIFO_WATER 0x48
7246 +#define IO_FIFO_LEVEL 0x4c
7247 +#define IO_GPIO_MASK 0x50
7249 +#define IO_FUNC_FUNCTION_RESET(func) ((1 << ((func) - 1)) << 4) /* Function 0 doesn't need reset */
7250 +#define IO_FUNC_RX_FIFO (1 << 3)
7251 +#define IO_FUNC_SELECT(func) ((func) << 0)
7254 + * External interrupt pins.
7256 +#define EXT_INT_IO_BIT(pin) ((pin) + 5) // Interrupt pin number -> I/O INT bit
7257 +#define EXT_INT_RISING_EDGE(pin) (0x2 << (2*(pin) + 7))
7258 +#define EXT_INT_FALLING_EDGE(pin) (0x1 << (2*(pin) + 7))
7263 +#define IO_XFL_BASE RA
7265 +#define IO_XFL_INT_START (1 << 16)
7266 +#define IO_XFL_INT_ERR (1 << 8)
7267 +#define IO_XFL_INT_DONE (1 << 0)
7269 +#define IO_XFL_CTL0_MASK (0xffe07fff)
7270 +#define IO_XFL_CTL0_RD_CMD(cmd) (((cmd) & 0xff) << 24)
7271 +#define IO_XFL_CTL0_RD_DUMMY(n) (((n) & 0x7) << 21)
7272 +#define IO_XFL_CTL0_CLK_WIDTH(core_cycles) ((((core_cycles) + 1) & 0x7e) << 8) /* must be even number */
7273 +#define IO_XFL_CTL0_CE_WAIT(spi_cycles) (((spi_cycles) & 0x3f) << 2)
7274 +#define IO_XFL_CTL0_MCB_LOCK (1 << 1)
7275 +#define IO_XFL_CTL0_ENABLE (1 << 0)
7276 +#define IO_XFL_CTL0_FAST_VALUE(div, wait) (IO_XFL_CTL0_RD_CMD(0xb) | IO_XFL_CTL0_RD_DUMMY(1) | IO_XFL_CTL0_CLK_WIDTH(div) | IO_XFL_CTL0_CE_WAIT(wait) | IO_XFL_CTL0_ENABLE)
7277 +#define IO_XFL_CTL0_VALUE(div, wait) (IO_XFL_CTL0_RD_CMD(3) | IO_XFL_CTL0_CLK_WIDTH(div) | IO_XFL_CTL0_CE_WAIT(wait) | IO_XFL_CTL0_ENABLE)
7279 +#define IO_XFL_CTL1_MASK (0xc0003fff)
7280 +#define IO_XFL_CTL1_FC_INST(inst) (((inst) & 0x3) << 30)
7281 +#define IO_XFL_CTL1_FC_DATA(n) (((n) & 0x3ff) << 4)
7282 +#define IO_XFL_CTL1_FC_DUMMY(n) (((n) & 0x7) << 1)
7283 +#define IO_XFL_CTL1_FC_ADDR (1 << 0)
7285 +#define IO_XFL_CTL2_FC_CMD(cmd) (((cmd) & 0xff) << 24)
7286 +#define IO_XFL_CTL2_FC_ADDR(addr) ((addr) & 0x00ffffff) /* Only up to 24 bits */
7288 +#define IO_XFL_STATUS0_MCB_ACTIVE (1 << 0)
7289 +#define IO_XFL_STATUS0_IOPCS_ACTIVE (1 << 1)
7294 +#define IO_SDRAM_DATA_BASE RG
7295 +#define IO_SDRAM_CNTL_BASE RH
7297 +#define IO_SDRAM_CTRL0_EN_REF (1 << 0)
7300 + * Port function code (common fucntion codes for all I/O ports)
7302 +#define IO_PORTX_FUNC_GPIO 0x00
7303 +#define IO_PORTX_FUNC_XFL 0x01
7304 +#define IO_PORTX_FUNC_PCI 0x01
7305 +#define IO_PORTX_FUNC_SERDES 0x01
7306 +#define IO_PORTX_FUNC_GMII 0x01
7307 +#define IO_PORTX_FUNC_DDR 0x01
7308 +#define IO_PORTX_FUNC_PCIX 0x01
7309 +#define IO_PORTX_FUNC_USB2_0 0x01
7310 +#define IO_PORTX_FUNC_GPIO_INT_CLK 0x02
7311 +#define IO_PORTX_FUNC_PLIO 0x02
7312 +#define IO_PORTX_FUNC_GPIO_INT 0x03
7313 +#define IO_PORTX_FUNC_MII 0x03
7318 +#define IO_PORT0_FUNC_GPIO IO_PORTX_FUNC_GPIO
7319 +#define IO_PORT0_FUNC_XFL_INT_CLK IO_PORTX_FUNC_XFL // Default mode after reset
7320 +#define IO_PORT0_FUNC_GPIO_INT_CLK IO_PORTX_FUNC_GPIO_INT_CLK
7321 +#define IO_PORT0_FUNC_GPIO_INT IO_PORTX_FUNC_GPIO_INT
7326 +#define IO_PORT1_FUNC_GPIO IO_PORTX_FUNC_GPIO
7327 +#define IO_PORT1_FUNC_PCI IO_PORTX_FUNC_PCI // PCI control
7328 +#define IO_PORT1_FUNC_MII IO_PORTX_FUNC_MII // port 4 MII extension
7333 +#define IO_PORT2_FUNC_GPIO IO_PORTX_FUNC_GPIO
7334 +#define IO_PORT2_FUNC_PCI IO_PORTX_FUNC_PCI // PCI data I/O
7335 +#define IO_PORT2_FUNC_PLIO IO_PORTX_FUNC_PLIO // Extended LM
7340 +#define IO_PORT3_FUNC_GPIO IO_PORTX_FUNC_GPIO
7341 +#define IO_PORT3_FUNC_SERDES IO_PORTX_FUNC_SERDES
7342 +#define IO_PORT3_FUNC_PLIO IO_PORTX_FUNC_PLIO
7347 +#define IO_PORT4_FUNC_GPIO IO_PORTX_FUNC_GPIO
7348 +#define IO_PORT4_FUNC_SERDES IO_PORTX_FUNC_SERDES
7349 +#define IO_PORT4_FUNC_PLIO IO_PORTX_FUNC_PLIO // Extended LM
7350 +#define IO_PORT4_FUNC_MII IO_PORTX_FUNC_MII
7355 +#define IO_PORT5_FUNC_GPIO IO_PORTX_FUNC_GPIO
7356 +#define IO_PORT5_FUNC_GMII IO_PORTX_FUNC_GMII
7361 +#define IO_PORT6_FUNC_GPIO IO_PORTX_FUNC_GPIO
7362 +#define IO_PORT6_FUNC_DDR IO_PORTX_FUNC_DDR
7367 +#define IO_PORT7_FUNC_GPIO IO_PORTX_FUNC_GPIO
7368 +#define IO_PORT7_FUNC_DDR IO_PORTX_FUNC_DDR
7373 +#define IO_PORT8_FUNC_GPIO IO_PORTX_FUNC_GPIO
7374 +#define IO_PORT8_FUNC_PCIX IO_PORTX_FUNC_PCIX
7375 +#define IO_PORT8_FUNC_PLIO IO_PORTX_FUNC_PLIO // Extended LM
7376 +#define IO_PORT8_FUNC_MII IO_PORTX_FUNC_MII // port 4 MII extension
7381 +#define IO_PORT9_FUNC_USB2_0 IO_PORTX_FUNC_USB2_0
7386 +#define IO_PORTX_INT_FIFO_TX_RESET (1 << 31)
7387 +#define IO_PORTX_INT_FIFO_RX_RESET (1 << 30)
7388 +#define IO_PORTX_INT_FIFO_TX_UF (1 << 15)
7389 +#define IO_PORTX_INT_FIFO_TX_WM (1 << 14)
7390 +#define IO_PORTX_INT_FIFO_RX_OF (1 << 13)
7391 +#define IO_PORTX_INT_FIFO_RX_WM (1 << 12)
7393 +#define IO_PORTX_FUNC_FIFO_TX_WM(n) ((n) << 16)
7394 +#define IO_PORTX_FUNC_FIFO_RX_WM(n) ((n) << 0)
7399 +#define IO_PORTX_INT_MII_TX_ERR_SEND (1 << 18)
7400 +#define IO_PORTX_INT_MII_TX_HALT (1 << 17)
7401 +#define IO_PORTX_INT_MII_TX_START (1 << 16)
7402 +#define IO_PORTX_INT_MII_THRESHOLD (1 << 8)
7403 +#define IO_PORTX_INT_MII_RX_EOP (1 << 7)
7404 +#define IO_PORTX_INT_MII_RX_SFD (1 << 6)
7405 +#define IO_PORTX_INT_MII_RX_ERR (1 << 5)
7406 +#define IO_PORTX_INT_MII_TX_EOP (1 << 4)
7407 +#define IO_PORTX_INT_MII_COL (1 << 3)
7408 +#define IO_PORTX_INT_MII_CRS (1 << 2)
7409 +#define IO_PORTX_INT_MII_ODD_NIB_ERR (1 << 1)
7410 +#define IO_PORTX_INT_MII_FALSE_CARRIER (1 << 0)
7415 +#define IO_PORTX_INT_SERDES_TXBUF_VALID (1 << 16)
7416 +#define IO_PORTX_INT_SERDES_RXERR (1 << 7)
7417 +#define IO_PORTX_INT_SERDES_RXEOP (1 << 6)
7418 +#define IO_PORTX_INT_SERDES_SYND (1 << 5)
7419 +#define IO_PORTX_INT_SERDES_TXBE (1 << 4)
7420 +#define IO_PORTX_INT_SERDES_TXEOP (1 << 3)
7421 +#define IO_PORTX_INT_SERDES_SXLP (1 << 2)
7422 +#define IO_PORTX_INT_SERDES_RXBF (1 << 1)
7423 +#define IO_PORTX_INT_SERDES_RXCRS (1 << 0)
7425 +#ifndef __ASSEMBLY__
7426 +struct ubicom32_io_port {
7427 + volatile u32_t function;
7428 + volatile u32_t gpio_ctl;
7429 + volatile u32_t gpio_out;
7430 + volatile u32_t gpio_in;
7431 + volatile u32_t int_status;
7432 + volatile u32_t int_mask;
7433 + volatile u32_t int_set;
7434 + volatile u32_t int_clr;
7435 + volatile u32_t tx_fifo;
7436 + volatile u32_t tx_fifo_hi;
7437 + volatile u32_t rx_fifo;
7438 + volatile u32_t rx_fifo_hi;
7439 + volatile u32_t ctl0;
7440 + volatile u32_t ctl1;
7441 + volatile u32_t ctl2;
7442 + volatile u32_t status0;
7443 + volatile u32_t status1;
7444 + volatile u32_t status2;
7445 + volatile u32_t fifo_watermark;
7446 + volatile u32_t fifo_level;
7447 + volatile u32_t gpio_mask;
7450 +#define UBICOM32_IO_PORT(port) ((struct ubicom32_io_port *)((port)))
7453 +#ifndef __ASSEMBLY__
7455 + * ubicom32_set_interrupt()
7457 +extern inline void ubicom32_set_interrupt(u8_t interrupt)
7459 + u32_t ibit = INT_BIT_MASK(interrupt);
7461 + if (INT_REG(interrupt) == INT_REG(INT_CHIP(0, 0))) {
7463 + "move.4 "D(INT_SET(INT_CHIP(0, 0)))", %0\n\t"
7472 + "move.4 "D(INT_SET(INT_CHIP(1, 0)))", %0\n\t"
7479 + * ubicom32_clear_interrupt()
7481 +extern inline void ubicom32_clear_interrupt(u8_t interrupt)
7483 + u32_t ibit = INT_BIT_MASK(interrupt);
7485 + if (INT_REG(interrupt) == INT_REG(INT_CHIP(0, 0))) {
7487 + "move.4 "D(INT_CLR(INT_CHIP(0, 0)))", %0\n\t"
7496 + "move.4 "D(INT_CLR(INT_CHIP(1, 0)))", %0\n\t"
7503 + * ubicom32_enable_interrupt()
7505 +extern inline void ubicom32_enable_interrupt(u8_t interrupt)
7507 + u32_t ibit = INT_BIT_MASK(interrupt);
7509 + if (INT_REG(interrupt) == INT_REG(INT_CHIP(0, 0))) {
7511 + "or.4 "D(INT_MASK(INT_CHIP(0, 0)))", "D(INT_MASK(INT_CHIP(0, 0)))", %0\n\t"
7520 + "or.4 "D(INT_MASK(INT_CHIP(1, 0)))", "D(INT_MASK(INT_CHIP(1, 0)))", %0\n\t"
7527 + * ubicom32_disable_interrupt()
7529 +extern inline void ubicom32_disable_interrupt(u8_t interrupt)
7531 + u32_t ibit = ~INT_BIT_MASK(interrupt);
7533 + if (INT_REG(interrupt) == INT_REG(INT_CHIP(0, 0))) {
7535 + "and.4 "D(INT_MASK(INT_CHIP(0, 0)))", "D(INT_MASK(INT_CHIP(0, 0)))", %0\n\t"
7544 + "and.4 "D(INT_MASK(INT_CHIP(1, 0)))", "D(INT_MASK(INT_CHIP(1, 0)))", %0\n\t"
7551 + * ubicom32_enable_global_interrupts()
7553 +extern inline void ubicom32_enable_global_interrupts(void)
7556 + "bset GLOBAL_CTRL, GLOBAL_CTRL, #%bit("D(GLOBAL_CTRL_INT_EN)")"
7561 + * ubicom32_disable_global_interrupts()
7563 +extern inline void ubicom32_disable_global_interrupts(void)
7566 + "bclr GLOBAL_CTRL, GLOBAL_CTRL, #%bit("D(GLOBAL_CTRL_INT_EN)")"
7571 + * ubicom32_get_reset_reason()
7573 +extern inline u32_t ubicom32_get_reset_reason(void)
7575 + return *(u32_t *)(GENERAL_CFG_BASE + GEN_RESET_REASON);
7579 + * ubicom32_read_reg()
7581 +extern inline u32_t ubicom32_read_reg(volatile void *reg)
7585 + "move.4 %[dest], %[src] \n\t"
7587 + : [src] "m" (*(u32_t *)reg)
7593 + * ubicom32_write_reg()
7595 +extern inline void ubicom32_write_reg(volatile void *reg, u32_t v)
7598 + "move.4 %[dest], %[src] \n\t"
7600 + : [src] "r" (v), [dest] "m" (*(u32_t *)reg)
7604 +#endif /* __ASSEMBLY__ */
7605 +#endif /* _ASM_UBICOM32_IP5000_H */
7607 +++ b/arch/ubicom32/include/asm/ipcbuf.h
7610 + * arch/ubicom32/include/asm/ipcbuf.h
7611 + * Definition of ipc64_perm struct for Ubicom32 architecture.
7613 + * (C) Copyright 2009, Ubicom, Inc.
7615 + * This file is part of the Ubicom32 Linux Kernel Port.
7617 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
7618 + * it and/or modify it under the terms of the GNU General Public License
7619 + * as published by the Free Software Foundation, either version 2 of the
7620 + * License, or (at your option) any later version.
7622 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
7623 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
7624 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
7625 + * the GNU General Public License for more details.
7627 + * You should have received a copy of the GNU General Public License
7628 + * along with the Ubicom32 Linux Kernel Port. If not,
7629 + * see <http://www.gnu.org/licenses/>.
7631 + * Ubicom32 implementation derived from (with many thanks):
7636 +#ifndef _ASM_UBICOM32_IPCBUF_H
7637 +#define _ASM_UBICOM32_IPCBUF_H
7640 + * The user_ipc_perm structure for m68k architecture.
7641 + * Note extra padding because this structure is passed back and forth
7642 + * between kernel and user space.
7644 + * Pad space is left for:
7645 + * - 32-bit mode_t and seq
7646 + * - 2 miscellaneous 32-bit values
7650 + __kernel_key_t key;
7651 + __kernel_uid32_t uid;
7652 + __kernel_gid32_t gid;
7653 + __kernel_uid32_t cuid;
7654 + __kernel_gid32_t cgid;
7655 + __kernel_mode_t mode;
7656 + unsigned short __pad1;
7657 + unsigned short seq;
7658 + unsigned short __pad2;
7659 + unsigned long __unused1;
7660 + unsigned long __unused2;
7663 +#endif /* _ASM_UBICOM32_IPCBUF_H */
7665 +++ b/arch/ubicom32/include/asm/irqflags.h
7668 + * arch/ubicom32/include/asm/irqflags.h
7669 + * Raw implementation of local IRQ functions.
7671 + * (C) Copyright 2009, Ubicom, Inc.
7673 + * This file is part of the Ubicom32 Linux Kernel Port.
7675 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
7676 + * it and/or modify it under the terms of the GNU General Public License
7677 + * as published by the Free Software Foundation, either version 2 of the
7678 + * License, or (at your option) any later version.
7680 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
7681 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
7682 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
7683 + * the GNU General Public License for more details.
7685 + * You should have received a copy of the GNU General Public License
7686 + * along with the Ubicom32 Linux Kernel Port. If not,
7687 + * see <http://www.gnu.org/licenses/>.
7689 + * Ubicom32 implementation derived from (with many thanks):
7694 +#ifndef _ASM_UBICOM32_IRQFLAGS_H
7695 +#define _ASM_UBICOM32_IRQFLAGS_H
7697 +#include <linux/thread_info.h>
7698 +#include <asm/ubicom32-common.h>
7699 +#if defined(CONFIG_SMP)
7700 +#include <asm/smp.h>
7702 +#include <asm/ldsr.h>
7704 +#if defined(CONFIG_PREEMPT)
7705 +#error Not supported by Ubicom32 irq handling, yet!
7709 + * raw_local_irq_enable()
7710 + * Enable interrupts for this thread.
7712 +static inline void raw_local_irq_enable(void)
7714 + ldsr_local_irq_enable();
7718 + * raw_local_irq_disable()
7719 + * Disable interrupts for this thread.
7721 +static inline void raw_local_irq_disable(void)
7723 + ldsr_local_irq_disable();
7727 + * raw_local_save_flags()
7728 + * Get the current IRQ state.
7730 +#define raw_local_save_flags(flags) \
7732 + (flags) = ldsr_local_irq_is_disabled(); \
7736 + * raw_local_irq_save()
7737 + * Save the current interrupt state and disable interrupts.
7739 +#define raw_local_irq_save(flags) \
7741 + (flags) = ldsr_local_irq_save(); \
7745 + * raw_local_irq_restore()
7746 + * Restore the IRQ state back to flags.
7748 +static inline void raw_local_irq_restore(unsigned long flags)
7750 + ldsr_local_irq_restore(flags);
7754 + * raw_irqs_disabled_flags()
7755 + * Return true if the flags indicate that IRQ(s) are disabled.
7757 +static inline int raw_irqs_disabled_flags(unsigned long flags)
7762 +#endif /* _ASM_UBICOM32_IRQFLAGS_H */
7764 +++ b/arch/ubicom32/include/asm/irq.h
7767 + * arch/ubicom32/include/asm/irq.h
7768 + * IRQ definitions for Ubicom32 architecture.
7770 + * (C) Copyright 2009, Ubicom, Inc.
7772 + * This file is part of the Ubicom32 Linux Kernel Port.
7774 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
7775 + * it and/or modify it under the terms of the GNU General Public License
7776 + * as published by the Free Software Foundation, either version 2 of the
7777 + * License, or (at your option) any later version.
7779 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
7780 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
7781 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
7782 + * the GNU General Public License for more details.
7784 + * You should have received a copy of the GNU General Public License
7785 + * along with the Ubicom32 Linux Kernel Port. If not,
7786 + * see <http://www.gnu.org/licenses/>.
7788 + * Ubicom32 implementation derived from (with many thanks):
7793 +#ifndef _ASM_UBICOM32_IRQ_H
7794 +#define _ASM_UBICOM32_IRQ_H
7796 +#include <asm/irqflags.h>
7799 + * We setup the IRQS to cover the full range of interrupt registers in
7804 +#define irq_canonicalize(irq) (irq)
7806 +extern int irq_soft_alloc(unsigned int *soft);
7807 +extern void ack_bad_irq(unsigned int irq);
7808 +extern void do_IRQ(int irq, struct pt_regs *fp);
7810 +#endif /* _ASM_UBICOM32_IRQ_H */
7812 +++ b/arch/ubicom32/include/asm/irq_regs.h
7815 + * arch/ubicom32/include/asm/irq_regs.h
7816 + * Generic irq_regs.h for Ubicom32 architecture.
7818 + * (C) Copyright 2009, Ubicom, Inc.
7820 + * This file is part of the Ubicom32 Linux Kernel Port.
7822 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
7823 + * it and/or modify it under the terms of the GNU General Public License
7824 + * as published by the Free Software Foundation, either version 2 of the
7825 + * License, or (at your option) any later version.
7827 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
7828 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
7829 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
7830 + * the GNU General Public License for more details.
7832 + * You should have received a copy of the GNU General Public License
7833 + * along with the Ubicom32 Linux Kernel Port. If not,
7834 + * see <http://www.gnu.org/licenses/>.
7836 + * Ubicom32 implementation derived from (with many thanks):
7841 +#ifndef _ASM_UBICOM32_IRQ_REGS_H
7842 +#define _ASM_UBICOM32_IRQ_REGS_H
7844 +#include <asm-generic/irq_regs.h>
7846 +#endif /* _ASM_UBICOM32_IRQ_REGS_H */
7848 +++ b/arch/ubicom32/include/asm/Kbuild
7850 +include include/asm-generic/Kbuild.asm
7852 +++ b/arch/ubicom32/include/asm/kdebug.h
7855 + * arch/ubicom32/include/asm/kdebug.h
7856 + * Generic kdebug.h for Ubicom32 architecture.
7858 + * (C) Copyright 2009, Ubicom, Inc.
7860 + * This file is part of the Ubicom32 Linux Kernel Port.
7862 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
7863 + * it and/or modify it under the terms of the GNU General Public License
7864 + * as published by the Free Software Foundation, either version 2 of the
7865 + * License, or (at your option) any later version.
7867 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
7868 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
7869 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
7870 + * the GNU General Public License for more details.
7872 + * You should have received a copy of the GNU General Public License
7873 + * along with the Ubicom32 Linux Kernel Port. If not,
7874 + * see <http://www.gnu.org/licenses/>.
7876 + * Ubicom32 implementation derived from (with many thanks):
7881 +#ifndef _ASM_UBICOM32_KDEBUG_H
7882 +#define _ASM_UBICOM32_KDEBUG_H
7884 +#include <asm-generic/kdebug.h>
7886 +#endif /* _ASM_UBICOM32_KDEBUG_H */
7888 +++ b/arch/ubicom32/include/asm/kmap_types.h
7891 + * arch/ubicom32/include/asm/kmap_types.h
7892 + * Definition of km_type's for Ubicom32 architecture.
7894 + * (C) Copyright 2009, Ubicom, Inc.
7896 + * This file is part of the Ubicom32 Linux Kernel Port.
7898 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
7899 + * it and/or modify it under the terms of the GNU General Public License
7900 + * as published by the Free Software Foundation, either version 2 of the
7901 + * License, or (at your option) any later version.
7903 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
7904 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
7905 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
7906 + * the GNU General Public License for more details.
7908 + * You should have received a copy of the GNU General Public License
7909 + * along with the Ubicom32 Linux Kernel Port. If not,
7910 + * see <http://www.gnu.org/licenses/>.
7912 + * Ubicom32 implementation derived from (with many thanks):
7917 +#ifndef _ASM_UBICOM32_KMAP_TYPES_H
7918 +#define _ASM_UBICOM32_KMAP_TYPES_H
7922 + KM_SKB_SUNRPC_DATA,
7923 + KM_SKB_DATA_SOFTIRQ,
7937 +#endif /* _ASM_UBICOM32_KMAP_TYPES_H */
7939 +++ b/arch/ubicom32/include/asm/ldsr.h
7942 + * arch/ubicom32/include/asm/ldsr.h
7943 + * Ubicom32 LDSR interface definitions.
7945 + * (C) Copyright 2009, Ubicom, Inc.
7947 + * This file is part of the Ubicom32 Linux Kernel Port.
7949 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
7950 + * it and/or modify it under the terms of the GNU General Public License
7951 + * as published by the Free Software Foundation, either version 2 of the
7952 + * License, or (at your option) any later version.
7954 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
7955 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
7956 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
7957 + * the GNU General Public License for more details.
7959 + * You should have received a copy of the GNU General Public License
7960 + * along with the Ubicom32 Linux Kernel Port. If not,
7961 + * see <http://www.gnu.org/licenses/>.
7963 + * Ubicom32 implementation derived from (with many thanks):
7968 +#ifndef _ASM_UBICOM32_LDSR_H
7969 +#define _ASM_UBICOM32_LDSR_H
7971 +#include <asm/ubicom32-common.h>
7972 +#include <asm/types.h>
7973 +#include <asm/thread.h>
7975 +extern unsigned int ldsr_soft_irq_mask;
7978 + * ldsr_local_irq_is_disabled()
7979 + * Test if interrupts are disabled for this thread?
7981 +static inline int ldsr_local_irq_is_disabled(void)
7984 + thread_t self = thread_get_self();
7985 + unsigned int mask = (1 << self);
7988 + " and.4 %0, scratchpad1, %1 \n\t"
7995 + * We return a simple 1 == disabled, 0 == enabled
7996 + * losing which tid this is for, because Linux
7997 + * can restore interrupts on a different thread.
7999 + return ret >> self;
8003 + * ldsr_local_irq_save()
8004 + * Get the current interrupt state and disable interrupts.
8006 +static inline unsigned int ldsr_local_irq_save(void)
8009 + thread_t self = thread_get_self();
8010 + unsigned int mask = (1 << self);
8013 + * Ensure the compiler can not optimize out the code
8014 + * (volatile) and that it does not "cache" values around
8015 + * the interrupt state change (memory). This ensures
8016 + * that interrupt changes are treated as a critical
8020 + " and.4 %0, scratchpad1, %1 \n\t"
8021 + " or.4 scratchpad1, scratchpad1, %1 \n\t"
8028 + * We return a simple 1 == disabled, 0 == enabled
8029 + * losing which tid this is for, because Linux
8030 + * can restore interrupts on a different thread.
8032 + return ret >> self;
8036 + * ldsr_local_irq_restore()
8037 + * Restore this cpu's interrupt enable/disable state.
8039 + * Note: flags is either 0 or 1.
8041 +static inline void ldsr_local_irq_restore(unsigned int flags)
8043 + unsigned int temp;
8044 + thread_t self = thread_get_self();
8045 + unsigned int mask = (1 << self);
8046 + flags = (flags << self);
8049 + * Ensure the compiler can not optimize out the code
8050 + * (volatile) and that it does not "cache" values around
8051 + * the interrupt state change (memory). This ensures
8052 + * that interrupt changes are treated as a critical
8055 + * Atomic change to our bit in scratchpad1 without
8056 + * causing any temporary glitch in the value and
8057 + * without effecting other values. Also this uses
8058 + * no branches so no penalties.
8061 + " xor.4 %0, scratchpad1, %1 \n\t"
8062 + " and.4 %0, %2, %0 \n\t"
8063 + " xor.4 scratchpad1, scratchpad1, %0 \n\t"
8064 + " move.4 int_set0, %3 \n\t"
8066 + : "d"(flags), "r"(mask), "r"(ldsr_soft_irq_mask)
8072 + * ldsr_local_irq_disable_interrupt()
8073 + * Disable ints for this thread.
8075 +static inline void ldsr_local_irq_disable(void)
8077 + unsigned int mask = (1 << thread_get_self());
8080 + * Ensure the compiler can not optimize out the code
8081 + * (volatile) and that it does not "cache" values around
8082 + * the interrupt state change (memory). This ensures
8083 + * that interrupt changes are treated as a critical
8087 + " or.4 scratchpad1, scratchpad1, %0 \n\t"
8095 + * ldsr_local_irq_enable_interrupt
8096 + * Enable ints for this thread.
8098 +static inline void ldsr_local_irq_enable(void)
8100 + unsigned int mask = (1 << thread_get_self());
8103 + * Ensure the compiler can not optimize out the code
8104 + * (volatile) and that it does not "cache" values around
8105 + * the interrupt state change (memory). This ensures
8106 + * that interrupt changes are treated as a critical
8110 + " and.4 scratchpad1, scratchpad1, %0 \n\t"
8111 + " move.4 int_set0, %1 \n\t"
8113 + : "d" (~mask), "r" (ldsr_soft_irq_mask)
8118 +extern void ldsr_init(void);
8119 +extern void ldsr_set_trap_irq(unsigned int irq);
8120 +extern void ldsr_mask_vector(unsigned int vector);
8121 +extern void ldsr_unmask_vector(unsigned int vector);
8122 +extern void ldsr_enable_vector(unsigned int vector);
8123 +extern void ldsr_disable_vector(unsigned int vector);
8124 +extern thread_t ldsr_get_threadid(void);
8126 +#endif /* _ASM_UBICOM32_LDSR_H */
8128 +++ b/arch/ubicom32/include/asm/linkage.h
8131 + * arch/ubicom32/include/asm/linkage.h
8132 + * Definition of Ubicom32 architecture specific linkage types.
8134 + * (C) Copyright 2009, Ubicom, Inc.
8136 + * This file is part of the Ubicom32 Linux Kernel Port.
8138 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8139 + * it and/or modify it under the terms of the GNU General Public License
8140 + * as published by the Free Software Foundation, either version 2 of the
8141 + * License, or (at your option) any later version.
8143 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8144 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8145 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
8146 + * the GNU General Public License for more details.
8148 + * You should have received a copy of the GNU General Public License
8149 + * along with the Ubicom32 Linux Kernel Port. If not,
8150 + * see <http://www.gnu.org/licenses/>.
8152 + * Ubicom32 implementation derived from (with many thanks):
8157 +#ifndef _ASM_UBICOM32_LINKAGE_H
8158 +#define _ASM_UBICOM32_LINKAGE_H
8160 +#define __ocm_text __section(.ocm_text)
8161 +#define __ocm_data __section(.ocm_data)
8163 +#endif /* _ASM_UBICOM32_LINKAGE_H */
8165 +++ b/arch/ubicom32/include/asm/local.h
8168 + * arch/ubicom32/include/asm/local.h
8169 + * Generic local.h for Ubicom32 architecture.
8171 + * (C) Copyright 2009, Ubicom, Inc.
8173 + * This file is part of the Ubicom32 Linux Kernel Port.
8175 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8176 + * it and/or modify it under the terms of the GNU General Public License
8177 + * as published by the Free Software Foundation, either version 2 of the
8178 + * License, or (at your option) any later version.
8180 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8181 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8182 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
8183 + * the GNU General Public License for more details.
8185 + * You should have received a copy of the GNU General Public License
8186 + * along with the Ubicom32 Linux Kernel Port. If not,
8187 + * see <http://www.gnu.org/licenses/>.
8189 + * Ubicom32 implementation derived from (with many thanks):
8194 +#ifndef _ASM_UBICOM32_LOCAL_H
8195 +#define _ASM_UBICOM32_LOCAL_H
8197 +#include <asm-generic/local.h>
8199 +#endif /* _ASM_UBICOM32_LOCAL_H */
8201 +++ b/arch/ubicom32/include/asm/machdep.h
8204 + * arch/ubicom32/include/asm/machdep.h
8205 + * Machine dependent utility routines.
8207 + * (C) Copyright 2009, Ubicom, Inc.
8209 + * This file is part of the Ubicom32 Linux Kernel Port.
8211 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8212 + * it and/or modify it under the terms of the GNU General Public License
8213 + * as published by the Free Software Foundation, either version 2 of the
8214 + * License, or (at your option) any later version.
8216 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8217 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8218 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
8219 + * the GNU General Public License for more details.
8221 + * You should have received a copy of the GNU General Public License
8222 + * along with the Ubicom32 Linux Kernel Port. If not,
8223 + * see <http://www.gnu.org/licenses/>.
8225 + * Ubicom32 implementation derived from (with many thanks):
8230 +#ifndef _ASM_UBICOM32_MACHDEP_H
8231 +#define _ASM_UBICOM32_MACHDEP_H
8233 +#include <linux/interrupt.h>
8235 +/* Hardware clock functions */
8236 +extern unsigned long hw_timer_offset(void);
8238 +/* machine dependent power off functions */
8239 +extern void (*mach_reset)(void);
8240 +extern void (*mach_halt)(void);
8241 +extern void (*mach_power_off)(void);
8243 +extern void config_BSP(char *command, int len);
8245 +#endif /* _ASM_UBICOM32_MACHDEP_H */
8247 +++ b/arch/ubicom32/include/asm/mc146818rtc.h
8250 + * arch/ubicom32/include/asm/mc146818rtc.h
8251 + * Generic mc146818rtc.h for Ubicom32 architecture.
8253 + * (C) Copyright 2009, Ubicom, Inc.
8255 + * This file is part of the Ubicom32 Linux Kernel Port.
8257 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8258 + * it and/or modify it under the terms of the GNU General Public License
8259 + * as published by the Free Software Foundation, either version 2 of the
8260 + * License, or (at your option) any later version.
8262 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8263 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8264 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
8265 + * the GNU General Public License for more details.
8267 + * You should have received a copy of the GNU General Public License
8268 + * along with the Ubicom32 Linux Kernel Port. If not,
8269 + * see <http://www.gnu.org/licenses/>.
8271 + * Ubicom32 implementation derived from (with many thanks):
8277 + * Machine dependent access functions for RTC registers.
8279 +#ifndef _ASM_UBICOM32_MC146818RTC_H
8280 +#define _ASM_UBICOM32_MC146818RTC_H
8282 +/* empty include file to satisfy the include in genrtc.c/ide-geometry.c */
8284 +#endif /* _ASM_UBICOM32_MC146818RTC_H */
8286 +++ b/arch/ubicom32/include/asm/memory_map.h
8289 + * arch/ubicom32/include/asm/memory_map.h
8290 + * Machine memory maps/
8292 + * (C) Copyright 2009, Ubicom, Inc.
8294 + * This file is part of the Ubicom32 Linux Kernel Port.
8296 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8297 + * it and/or modify it under the terms of the GNU General Public License
8298 + * as published by the Free Software Foundation, either version 2 of the
8299 + * License, or (at your option) any later version.
8301 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8302 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8303 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
8304 + * the GNU General Public License for more details.
8306 + * You should have received a copy of the GNU General Public License
8307 + * along with the Ubicom32 Linux Kernel Port. If not,
8308 + * see <http://www.gnu.org/licenses/>.
8310 + * Ubicom32 implementation derived from (with many thanks):
8315 +#ifndef _ASM_UBICOM32_MEMORY_MAP_H
8316 +#define _ASM_UBICOM32_MEMORY_MAP_H
8321 +#define OCM_SECTOR_SIZE 0x00008000 /* 32K */
8323 +#if defined(CONFIG_UBICOM32_V3)
8324 +#define OCMSIZE 0x00030000 /* 192K on-chip RAM for both program and data */
8325 +#elif defined(CONFIG_UBICOM32_V4)
8326 +#define OCMSIZE 0x0003C000 /* 240K on-chip RAM for both program and data */
8328 +#error "Unknown IP5K silicon"
8331 +#define OCMSTART 0x3ffc0000 /* alias from 0x03000000 for easy
8332 + * jump to/from SDRAM */
8333 +#define OCMEND (OCMSTART + OCMSIZE)
8335 +#define SDRAMSTART 0x40000000
8337 +#define KERNELSTART (SDRAMSTART + 0x00400000)
8339 +#define FLASHSTART 0x60000000
8342 + * CODELOADER / OS_SYSCALL OCM Reservations
8343 + * Don't change these unless you know what you are doing.
8345 +#define CODELOADER_SIZE 0x30
8346 +#define CODELOADER_BEGIN OCMSTART /* Must be OCM start for gdb to work. */
8347 +#define CODELOADER_END (CODELOADER_BEGIN + CODELOADER_SIZE)
8349 +#define OS_SYSCALL_BEGIN CODELOADER_END /* system_call at this address */
8350 +#define OS_SYSCALL_SIZE (512 - CODELOADER_SIZE)
8351 +#define OS_SYSCALL_END (OS_SYSCALL_BEGIN + OS_SYSCALL_SIZE)
8353 +#endif /* _ASM_UBICOM32_MEMORY_MAP_H */
8355 +++ b/arch/ubicom32/include/asm/mman.h
8358 + * arch/ubicom32/include/asm/mman.h
8359 + * Memory mapping definitions for Ubicom32 architecture.
8361 + * (C) Copyright 2009, Ubicom, Inc.
8363 + * This file is part of the Ubicom32 Linux Kernel Port.
8365 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8366 + * it and/or modify it under the terms of the GNU General Public License
8367 + * as published by the Free Software Foundation, either version 2 of the
8368 + * License, or (at your option) any later version.
8370 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8371 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8372 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
8373 + * the GNU General Public License for more details.
8375 + * You should have received a copy of the GNU General Public License
8376 + * along with the Ubicom32 Linux Kernel Port. If not,
8377 + * see <http://www.gnu.org/licenses/>.
8379 + * Ubicom32 implementation derived from (with many thanks):
8384 +#ifndef _ASM_UBICOM32_MMAN_H
8385 +#define _ASM_UBICOM32_MMAN_H
8387 +#include <asm-generic/mman.h>
8389 +#define MAP_GROWSDOWN 0x0100 /* stack-like segment */
8390 +#define MAP_DENYWRITE 0x0800 /* ETXTBSY */
8391 +#define MAP_EXECUTABLE 0x1000 /* mark it as an executable */
8392 +#define MAP_LOCKED 0x2000 /* pages are locked */
8393 +#define MAP_NORESERVE 0x4000 /* don't check for reservations */
8394 +#define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */
8395 +#define MAP_NONBLOCK 0x10000 /* do not block on IO */
8397 +#define MCL_CURRENT 1 /* lock all current mappings */
8398 +#define MCL_FUTURE 2 /* lock all future mappings */
8400 +#endif /* _ASM_UBICOM32_MMAN_H */
8402 +++ b/arch/ubicom32/include/asm/mmu_context.h
8405 + * arch/ubicom32/include/asm/mmu_context.h
8406 + * MMU context definitions for Ubicom32 architecture.
8408 + * (C) Copyright 2009, Ubicom, Inc.
8409 + * Copyright (C) 2004, Microtronix Datacom Ltd., All rights reserved.
8411 + * This file is part of the Ubicom32 Linux Kernel Port.
8413 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8414 + * it and/or modify it under the terms of the GNU General Public License
8415 + * as published by the Free Software Foundation, either version 2 of the
8416 + * License, or (at your option) any later version.
8418 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8419 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8420 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
8421 + * the GNU General Public License for more details.
8423 + * You should have received a copy of the GNU General Public License
8424 + * along with the Ubicom32 Linux Kernel Port. If not,
8425 + * see <http://www.gnu.org/licenses/>.
8427 + * Ubicom32 implementation derived from (with many thanks):
8433 +#ifndef _ASM_UBICOM32_MMU_CONTEXT_H
8434 +#define _ASM_UBICOM32_MMU_CONTEXT_H
8436 +#include <asm/setup.h>
8437 +#include <asm/page.h>
8438 +#include <asm/pgalloc.h>
8440 +static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
8445 +init_new_context(struct task_struct *tsk, struct mm_struct *mm)
8447 + // mm->context = virt_to_phys(mm->pgd);
8451 +#define destroy_context(mm) do { } while(0)
8453 +static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk)
8457 +#define deactivate_mm(tsk,mm) do { } while (0)
8459 +extern inline void activate_mm(struct mm_struct *prev_mm, struct mm_struct *next_mm)
8463 +#endif /* _ASM_UBICOM32_MMU_CONTEXT_H */
8465 +++ b/arch/ubicom32/include/asm/mmu.h
8468 + * arch/ubicom32/include/asm/mmu.h
8469 + * Definition of mm_context_t struct for Ubicom32 architecture.
8471 + * (C) Copyright 2009, Ubicom, Inc.
8472 + * Copyright (C) 2002, David McCullough <davidm@snapgear.com>
8474 + * This file is part of the Ubicom32 Linux Kernel Port.
8476 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8477 + * it and/or modify it under the terms of the GNU General Public License
8478 + * as published by the Free Software Foundation, either version 2 of the
8479 + * License, or (at your option) any later version.
8481 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8482 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8483 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
8484 + * the GNU General Public License for more details.
8486 + * You should have received a copy of the GNU General Public License
8487 + * along with the Ubicom32 Linux Kernel Port. If not,
8488 + * see <http://www.gnu.org/licenses/>.
8490 + * Ubicom32 implementation derived from (with many thanks):
8495 +#ifndef _ASM_UBICOM32_MMU_H
8496 +#define _ASM_UBICOM32_MMU_H
8499 + struct vm_list_struct *vmlist;
8500 + unsigned long end_brk;
8501 +#ifdef CONFIG_BINFMT_ELF_FDPIC
8502 + unsigned long exec_fdpic_loadmap;
8503 + unsigned long interp_fdpic_loadmap;
8507 +#endif /* _ASM_UBICOM32_MMU_H */
8509 +++ b/arch/ubicom32/include/asm/module.h
8512 + * arch/ubicom32/include/asm/module.h
8513 + * Ubicom32 architecture specific module definitions.
8515 + * (C) Copyright 2009, Ubicom, Inc.
8517 + * This file is part of the Ubicom32 Linux Kernel Port.
8519 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8520 + * it and/or modify it under the terms of the GNU General Public License
8521 + * as published by the Free Software Foundation, either version 2 of the
8522 + * License, or (at your option) any later version.
8524 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8525 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8526 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
8527 + * the GNU General Public License for more details.
8529 + * You should have received a copy of the GNU General Public License
8530 + * along with the Ubicom32 Linux Kernel Port. If not,
8531 + * see <http://www.gnu.org/licenses/>.
8533 + * Ubicom32 implementation derived from (with many thanks):
8538 +#ifndef _ASM_UBICOM32_MODULE_H
8539 +#define _ASM_UBICOM32_MODULE_H
8541 +struct mod_arch_specific {
8543 + int ocm_inst_size;
8546 +#define Elf_Shdr Elf32_Shdr
8547 +#define Elf_Sym Elf32_Sym
8548 +#define Elf_Ehdr Elf32_Ehdr
8550 +#define ARCH_PROC_MODULES_EXTRA(m,mod) \
8551 + seq_printf(m, " OCM(%d bytes @ 0x%p)", \
8552 + (mod)->arch.ocm_inst_size, (mod)->arch.ocm_inst)
8554 +#define ARCH_OOPS_MODULE_EXTRA(mod) \
8555 + printk(KERN_INFO "%p %u OCM(%p %u)\n", \
8556 + (mod)->module_core, (mod)->core_size, \
8557 + (mod)->arch.ocm_inst, (mod)->arch.ocm_inst_size)
8558 +#endif /* _ASM_UBICOM32_MODULE_H */
8560 +++ b/arch/ubicom32/include/asm/msgbuf.h
8563 + * arch/ubicom32/include/asm/msgbuf.h
8564 + * Definition of msqid64_ds struct for Ubicom32 architecture.
8566 + * (C) Copyright 2009, Ubicom, Inc.
8568 + * This file is part of the Ubicom32 Linux Kernel Port.
8570 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8571 + * it and/or modify it under the terms of the GNU General Public License
8572 + * as published by the Free Software Foundation, either version 2 of the
8573 + * License, or (at your option) any later version.
8575 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8576 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8577 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
8578 + * the GNU General Public License for more details.
8580 + * You should have received a copy of the GNU General Public License
8581 + * along with the Ubicom32 Linux Kernel Port. If not,
8582 + * see <http://www.gnu.org/licenses/>.
8584 + * Ubicom32 implementation derived from (with many thanks):
8589 +#ifndef _ASM_UBICOM32_MSGBUF_H
8590 +#define _ASM_UBICOM32_MSGBUF_H
8593 + * The msqid64_ds structure for ubicom32 architecture.
8594 + * Note extra padding because this structure is passed back and forth
8595 + * between kernel and user space.
8597 + * Pad space is left for:
8598 + * - 64-bit time_t to solve y2038 problem
8599 + * - 2 miscellaneous 32-bit values
8602 +struct msqid64_ds {
8603 + struct ipc64_perm msg_perm;
8604 + __kernel_time_t msg_stime; /* last msgsnd time */
8605 + unsigned long __unused1;
8606 + __kernel_time_t msg_rtime; /* last msgrcv time */
8607 + unsigned long __unused2;
8608 + __kernel_time_t msg_ctime; /* last change time */
8609 + unsigned long __unused3;
8610 + unsigned long msg_cbytes; /* current number of bytes on queue */
8611 + unsigned long msg_qnum; /* number of messages in queue */
8612 + unsigned long msg_qbytes; /* max number of bytes on queue */
8613 + __kernel_pid_t msg_lspid; /* pid of last msgsnd */
8614 + __kernel_pid_t msg_lrpid; /* last receive pid */
8615 + unsigned long __unused4;
8616 + unsigned long __unused5;
8619 +#endif /* _ASM_UBICOM32_MSGBUF_H */
8621 +++ b/arch/ubicom32/include/asm/mutex.h
8624 + * arch/ubicom32/include/asm/mutex.h
8625 + * Generic mutex.h for Ubicom32 architecture.
8627 + * (C) Copyright 2009, Ubicom, Inc.
8629 + * This file is part of the Ubicom32 Linux Kernel Port.
8631 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8632 + * it and/or modify it under the terms of the GNU General Public License
8633 + * as published by the Free Software Foundation, either version 2 of the
8634 + * License, or (at your option) any later version.
8636 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8637 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8638 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
8639 + * the GNU General Public License for more details.
8641 + * You should have received a copy of the GNU General Public License
8642 + * along with the Ubicom32 Linux Kernel Port. If not,
8643 + * see <http://www.gnu.org/licenses/>.
8645 + * Ubicom32 implementation derived from (with many thanks):
8651 + * Pull in the generic implementation for the mutex fastpath.
8653 + * TODO: implement optimized primitives instead, or leave the generic
8654 + * implementation in place, or pick the atomic_xchg() based generic
8655 + * implementation. (see asm-generic/mutex-xchg.h for details)
8658 +#ifndef _ASM_UBICOM32_MUTEX_H
8659 +#define _ASM_UBICOM32_MUTEX_H
8661 +#include <asm-generic/mutex-dec.h>
8663 +#endif /* _ASM_UBICOM32_MUTEX_H */
8665 +++ b/arch/ubicom32/include/asm/namei.h
8668 + * arch/ubicom32/include/asm/namei.h
8669 + * Definition of __emul_prefix() for Ubicom32 architecture.
8671 + * (C) Copyright 2009, Ubicom, Inc.
8673 + * This file is part of the Ubicom32 Linux Kernel Port.
8675 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8676 + * it and/or modify it under the terms of the GNU General Public License
8677 + * as published by the Free Software Foundation, either version 2 of the
8678 + * License, or (at your option) any later version.
8680 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8681 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8682 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
8683 + * the GNU General Public License for more details.
8685 + * You should have received a copy of the GNU General Public License
8686 + * along with the Ubicom32 Linux Kernel Port. If not,
8687 + * see <http://www.gnu.org/licenses/>.
8689 + * Ubicom32 implementation derived from (with many thanks):
8694 +#ifndef _ASM_UBICOM32_NAMEI_H
8695 +#define _ASM_UBICOM32_NAMEI_H
8697 +/* This dummy routine maybe changed to something useful
8698 + * for /usr/gnemul/ emulation stuff.
8699 + * Look at asm-sparc/namei.h for details.
8702 +#define __emul_prefix() NULL
8704 +#endif /* _ASM_UBICOM32_NAMEI_H */
8706 +++ b/arch/ubicom32/include/asm/ocm-alloc.h
8709 + * arch/ubicom32/include/asm/ocm-alloc.h
8710 + * Ubicom32 architecture specific ocm definitions.
8712 + * (C) Copyright 2009, Ubicom, Inc.
8714 + * This file is part of the Ubicom32 Linux Kernel Port.
8716 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8717 + * it and/or modify it under the terms of the GNU General Public License
8718 + * as published by the Free Software Foundation, either version 2 of the
8719 + * License, or (at your option) any later version.
8721 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8722 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8723 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
8724 + * the GNU General Public License for more details.
8726 + * You should have received a copy of the GNU General Public License
8727 + * along with the Ubicom32 Linux Kernel Port. If not,
8728 + * see <http://www.gnu.org/licenses/>.
8730 + * Ubicom32 implementation derived from (with many thanks):
8735 +#ifndef _ASM_UBICOM32_OCM_ALLOC_H
8736 +#define _ASM_UBICOM32_OCM_ALLOC_H
8739 +extern void *ocm_inst_alloc(size_t size, pid_t pid);
8740 +extern int ocm_free(const void *ptr);
8741 +extern int ocm_inst_free(const void *ptr);
8743 +#endif /* _ASM_UBICOM32_OCM_ALLOC_H */
8745 +++ b/arch/ubicom32/include/asm/ocm_size.h
8747 +#define APP_OCM_CODE_SIZE (0x3ffc2e00-0x3ffc0000)
8748 +#define APP_OCM_DATA_SIZE (0x3ffd3500-0x3ffc8000)
8751 +++ b/arch/ubicom32/include/asm/ocm_text.lds.inc
8754 + * arch/ubicom32/include/asm/ocm_text.lds.inc
8755 + * <TODO: Replace with short file description>
8757 + * (C) Copyright 2009, Ubicom, Inc.
8759 + * This file is part of the Ubicom32 Linux Kernel Port.
8761 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8762 + * it and/or modify it under the terms of the GNU General Public License
8763 + * as published by the Free Software Foundation, either version 2 of the
8764 + * License, or (at your option) any later version.
8766 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8767 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8768 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
8769 + * the GNU General Public License for more details.
8771 + * You should have received a copy of the GNU General Public License
8772 + * along with the Ubicom32 Linux Kernel Port. If not,
8773 + * see <http://www.gnu.org/licenses/>.
8775 + * Ubicom32 implementation derived from (with many thanks):
8781 +*(.text.tcp_packet)
8782 +*(.text.ipt_do_table)
8783 +*(.text.nf_conntrack_in)
8784 +*(.text.ip_forward)
8785 +*(.text.dev_queue_xmit)
8786 +*(.text.netif_receive_skb)
8787 +*(.text.ip_route_input)
8788 +*(.text.ip_finish_output)
8789 +*(.text.nf_iterate)
8790 +*(.text.__hash_conntrack)
8794 +*(.text.__nf_conntrack_find)
8795 +*(.text.dev_hard_start_xmit)
8796 +*(.text.vlan_dev_hard_start_xmit)
8797 +*(.text.vlan_dev_hard_header)
8798 +*(.text.__nf_ct_refresh_acct)
8800 +*(.text.pfifo_fast_enqueue)
8801 +*(.text.ipv4_confirm)
8803 +*(.text.neigh_connected_output)
8804 +*(.text.nf_hook_slow)
8805 +*(.text.nf_nat_packet)
8806 +*(.text.local_bh_enable)
8807 +*(.text.pfifo_fast_dequeue)
8808 +*(.text.ubi32_eth_receive)
8810 +*(.text.skb_checksum)
8812 +*(.text.ubi32_eth_tx_done)
8813 +*(.text.eth_header)
8814 +*(.text.skb_release_data)
8815 +*(.text.nf_conntrack_find_get)
8816 +*(.text.process_backlog)
8817 +*(.text.vlan_skb_recv)
8818 +*(.text.ip_rcv_finish)
8819 +*(.text.__qdisc_run)
8821 +*(.text.eth_type_trans)
8822 +*(.text.__alloc_skb)
8824 +*(.text.nf_ip_checksum)
8825 +*(.text.__skb_checksum_complete_head)
8826 +*(.text.ipv4_conntrack_defrag)
8827 +*(.text.tcp_pkt_to_tuple)
8829 +*(.text.tcp_manip_pkt)
8831 +*(.text.nf_ct_get_tuple)
8833 +*(.text.ubi32_eth_start_xmit)
8834 +*(.text.free_block)
8836 +*(.text.kmem_cache_free)
8837 +*(.text.skb_pull_rcsum)
8838 +*(.text.cache_alloc_refill)
8839 +*(.text.skb_release_head_state)
8841 +*(.text.ip_sabotage_in)
8842 +*(.text.ip_forward_finish)
8843 +*(.text.kmem_cache_alloc)
8844 +*(.text.local_bh_disable)
8845 +*(.text.ipv4_pkt_to_tuple)
8846 +*(.text.inet_proto_csum_replace4)
8847 +*(.text.__nf_ct_l4proto_find)
8848 +*(.text.csum_partial)
8849 +*(.text.neigh_resolve_output)
8850 +*(.text.__kfree_skb)
8852 +*(.text.__find_vlan_dev)
8853 +*(.text.ldsr_ctxsw_thread)
8856 +*(.text.ipv4_invert_tuple)
8857 +*(.text.nf_ct_invert_tuplepr)
8858 +*(.text.skb_make_writable)
8859 +*(.text.ipv4_get_l4proto)
8860 +*(.text.handle_IRQ_event)
8861 +*(.text.net_rx_action)
8862 +*(.text.__do_softirq)
8864 +*(.text.note_interrupt)
8865 +*(.text.ipv4_conntrack_in)
8866 +*(.text.dst_release)
8867 +*(.text.tasklet_action)
8868 +*(.text.nf_nat_out)
8869 +*(.text.nf_ct_invert_tuple)
8871 +*(.text.__tasklet_schedule)
8872 +*(.text.__skb_checksum_complete)
8873 +*(.text.ubi32_eth_interrupt)
8874 +*(.text.dev_kfree_skb_any)
8875 +*(.text.ret_from_interrupt_to_kernel)
8876 +*(.text.preemptive_context_save)
8877 +*(.text.irq_ack_vector)
8878 +*(.text.update_wall_time)
8879 +*(.text.ldsr_thread)
8881 +*(.text.ubi32_eth_do_tasklet)
8882 +*(.text.__napi_schedule)
8884 +*(.text.run_timer_softirq)
8885 +*(.text.ldsr_mask_vector)
8887 +*(.text.ldsr_get_lsb)
8888 +*(.text.ldsr_unmask_vector)
8889 +*(.text.ip_fast_csum)
8890 +*(.text.hrtimer_run_queues)
8891 +*(.text.tcp_invert_tuple)
8893 +*(.text.run_posix_cpu_timers)
8894 +*(.text.free_hot_cold_page)
8895 +*(.text.lock_timer_base)
8896 +*(.text.calc_delta_mine)
8897 +*(.text.slab_destroy)
8898 +*(.text.rcu_pending)
8899 +*(.text.scheduler_tick)
8900 +*(.text.hrtimer_run_pending)
8901 +*(.text.do_softirq)
8903 +*(.text.irq_end_vector)
8904 +*(.text.pci_read_u32)
8905 +*(.text.udivmodsi4)
8908 +*(.text.__slab_alloc)
8909 +*(.text.br_handle_frame)
8910 +*(.text.br_fdb_update)
8911 +*(.text.__br_fdb_get)
8912 +*(.text.br_forward)
8913 +*(.text.br_handle_frame_finish)
8914 +*(.text.pci_write_u32)
8915 +*(.text.kmem_freepages)
8916 +*(.text.br_dev_queue_push_xmit)
8918 +*(.text.next_zones_zonelist)
8919 +*(.text.ubi32_pci_read_u32)
8920 +*(.text.zone_watermark_ok)
8921 +*(.text.__rmqueue_smallest)
8922 +*(.text.ubi32_eth_napi_poll)
8923 +*(.text.ubi32_pci_write_u32)
8924 +*(.text.ubi32_pci_read_u32)
8925 +*(.text._local_bh_enable)
8926 +*(.text._local_bh_disable)
8929 +++ b/arch/ubicom32/include/asm/page.h
8932 + * arch/ubicom32/include/asm/page.h
8933 + * Memory page related operations and definitions.
8935 + * (C) Copyright 2009, Ubicom, Inc.
8937 + * This file is part of the Ubicom32 Linux Kernel Port.
8939 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
8940 + * it and/or modify it under the terms of the GNU General Public License
8941 + * as published by the Free Software Foundation, either version 2 of the
8942 + * License, or (at your option) any later version.
8944 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
8945 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
8946 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
8947 + * the GNU General Public License for more details.
8949 + * You should have received a copy of the GNU General Public License
8950 + * along with the Ubicom32 Linux Kernel Port. If not,
8951 + * see <http://www.gnu.org/licenses/>.
8953 + * Ubicom32 implementation derived from (with many thanks):
8958 +#ifndef _ASM_UBICOM32_PAGE_H
8959 +#define _ASM_UBICOM32_PAGE_H
8961 +/* PAGE_SHIFT determines the page size */
8963 +#define PAGE_SHIFT 12
8964 +#define PAGE_SIZE (1 << PAGE_SHIFT)
8965 +#define PAGE_MASK (~(PAGE_SIZE-1))
8967 +#include <asm/setup.h>
8969 +#ifndef __ASSEMBLY__
8971 +#define get_user_page(vaddr) __get_free_page(GFP_KERNEL)
8972 +#define free_user_page(page, addr) free_page(addr)
8974 +#define clear_page(page) memset((page), 0, PAGE_SIZE)
8975 +#define copy_page(to,from) memcpy((to), (from), PAGE_SIZE)
8977 +#define clear_user_page(page, vaddr, pg) clear_page(page)
8978 +#define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
8980 +#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \
8981 + alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr)
8982 +#define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
8985 + * These are used to make use of C type-checking..
8987 +typedef struct { unsigned long pte; } pte_t;
8988 +typedef struct { unsigned long pmd[16]; } pmd_t;
8989 +typedef struct { unsigned long pgd; } pgd_t;
8990 +typedef struct { unsigned long pgprot; } pgprot_t;
8991 +typedef struct page *pgtable_t;
8993 +#define pte_val(x) ((x).pte)
8994 +#define pmd_val(x) ((&x)->pmd[0])
8995 +#define pgd_val(x) ((x).pgd)
8996 +#define pgprot_val(x) ((x).pgprot)
8998 +#define __pte(x) ((pte_t) { (x) } )
8999 +#define __pmd(x) ((pmd_t) { (x) } )
9000 +#define __pgd(x) ((pgd_t) { (x) } )
9001 +#define __pgprot(x) ((pgprot_t) { (x) } )
9003 +extern unsigned long memory_start;
9004 +extern unsigned long memory_end;
9006 +#endif /* !__ASSEMBLY__ */
9008 +#include <asm/page_offset.h>
9010 +#define PAGE_OFFSET (PAGE_OFFSET_RAW)
9012 +#ifndef __ASSEMBLY__
9014 +#define __pa(vaddr) virt_to_phys((void *)(vaddr))
9015 +#define __va(paddr) phys_to_virt((unsigned long)(paddr))
9017 +#define virt_to_pfn(kaddr) (__pa(kaddr) >> PAGE_SHIFT)
9018 +#define pfn_to_virt(pfn) __va((pfn) << PAGE_SHIFT)
9020 +#define virt_to_page(addr) (mem_map + (((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT))
9021 +#define page_to_virt(page) ((((page) - mem_map) << PAGE_SHIFT) + PAGE_OFFSET)
9023 +#define pfn_to_page(pfn) virt_to_page(pfn_to_virt(pfn))
9024 +#define page_to_pfn(page) virt_to_pfn(page_to_virt(page))
9025 +#define pfn_valid(pfn) ((pfn) < max_mapnr)
9027 +#define virt_addr_valid(kaddr) (((void *)(kaddr) >= (void *)PAGE_OFFSET) && \
9028 + ((void *)(kaddr) < (void *)memory_end))
9030 +#endif /* __ASSEMBLY__ */
9033 +#include <asm-generic/page.h>
9036 +#endif /* _ASM_UBICOM32_PAGE_H */
9038 +++ b/arch/ubicom32/include/asm/page_offset.h
9041 + * arch/ubicom32/include/asm/page_offset.h
9042 + * Definition of PAGE_OFFSET_RAW for Ubicom32 architecture.
9044 + * (C) Copyright 2009, Ubicom, Inc.
9046 + * This file is part of the Ubicom32 Linux Kernel Port.
9048 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
9049 + * it and/or modify it under the terms of the GNU General Public License
9050 + * as published by the Free Software Foundation, either version 2 of the
9051 + * License, or (at your option) any later version.
9053 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
9054 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
9055 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
9056 + * the GNU General Public License for more details.
9058 + * You should have received a copy of the GNU General Public License
9059 + * along with the Ubicom32 Linux Kernel Port. If not,
9060 + * see <http://www.gnu.org/licenses/>.
9062 + * Ubicom32 implementation derived from (with many thanks):
9068 +#ifndef _ASM_UBICOM32_PAGE_OFFSET_H
9069 +#define _ASM_UBICOM32_PAGE_OFFSET_H
9071 +/* This handles the memory map.. */
9072 +#define PAGE_OFFSET_RAW 0x3ffc0000
9074 +#endif /* _ASM_UBICOM32_PAGE_OFFSET_H */
9076 +++ b/arch/ubicom32/include/asm/param.h
9079 + * arch/ubicom32/include/asm/param.h
9080 + * Definition of miscellaneous constants, including HZ.
9082 + * (C) Copyright 2009, Ubicom, Inc.
9084 + * This file is part of the Ubicom32 Linux Kernel Port.
9086 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
9087 + * it and/or modify it under the terms of the GNU General Public License
9088 + * as published by the Free Software Foundation, either version 2 of the
9089 + * License, or (at your option) any later version.
9091 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
9092 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
9093 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
9094 + * the GNU General Public License for more details.
9096 + * You should have received a copy of the GNU General Public License
9097 + * along with the Ubicom32 Linux Kernel Port. If not,
9098 + * see <http://www.gnu.org/licenses/>.
9100 + * Ubicom32 implementation derived from (with many thanks):
9105 +#ifndef _ASM_UBICOM32_PARAM_H
9106 +#define _ASM_UBICOM32_PARAM_H
9109 +#define HZ CONFIG_HZ
9111 +#define CLOCKS_PER_SEC (USER_HZ)
9118 +#define EXEC_PAGESIZE 4096
9121 +#define NOGROUP (-1)
9124 +#define MAXHOSTNAMELEN 64 /* max length of hostname */
9126 +#endif /* _ASM_UBICOM32_PARAM_H */
9128 +++ b/arch/ubicom32/include/asm/pci.h
9131 + * arch/ubicom32/include/asm/pci.h
9132 + * Definitions of PCI operations for Ubicom32 architecture.
9134 + * (C) Copyright 2009, Ubicom, Inc.
9136 + * This file is part of the Ubicom32 Linux Kernel Port.
9138 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
9139 + * it and/or modify it under the terms of the GNU General Public License
9140 + * as published by the Free Software Foundation, either version 2 of the
9141 + * License, or (at your option) any later version.
9143 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
9144 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
9145 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
9146 + * the GNU General Public License for more details.
9148 + * You should have received a copy of the GNU General Public License
9149 + * along with the Ubicom32 Linux Kernel Port. If not,
9150 + * see <http://www.gnu.org/licenses/>.
9152 + * Ubicom32 implementation derived from (with many thanks):
9157 +#ifndef _ASM_UBICOM32_PCI_H
9158 +#define _ASM_UBICOM32_PCI_H
9160 +#include <asm/io.h>
9162 +/* The PCI address space does equal the physical memory
9163 + * address space. The networking and block device layers use
9164 + * this boolean for bounce buffer decisions.
9166 +#define PCI_DMA_BUS_IS_PHYS (1)
9171 + * Perform a master read/write to the PCI bus.
9172 + * These functions return a PCI_RESP_xxx code.
9174 +extern u8 pci_read_u32(u8 pci_cmd, u32 address, u32 *data);
9175 +extern u8 pci_write_u32(u8 pci_cmd, u32 address, u32 data);
9176 +extern u8 pci_read_u16(u8 pci_cmd, u32 address, u16 *data);
9177 +extern u8 pci_write_u16(u8 pci_cmd, u32 address, u16 data);
9178 +extern u8 pci_read_u8(u8 pci_cmd, u32 address, u8 *data);
9179 +extern u8 pci_write_u8(u8 pci_cmd, u32 address, u8 data);
9182 +#define PCIBIOS_MIN_IO 0x100
9183 +#define PCIBIOS_MIN_MEM 0x10000000
9185 +#define pcibios_assign_all_busses() 0
9186 +#define pcibios_scan_all_fns(a, b) 0
9187 +extern void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
9188 + struct resource *res);
9190 +extern void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
9191 + struct pci_bus_region *region);
9193 +struct pci_sys_data;
9197 + struct list_head buses;
9198 + int nr_controllers;
9199 + int (*setup)(int nr, struct pci_sys_data *);
9200 + struct pci_bus *(*scan)(int nr, struct pci_sys_data *);
9201 + void (*preinit)(void);
9202 + void (*postinit)(void);
9203 + u8 (*swizzle)(struct pci_dev *dev, u8 *pin);
9204 + int (*map_irq)(struct pci_dev *dev, u8 slot, u8 pin);
9208 + * Per-controller structure
9210 +struct pci_sys_data {
9211 + struct list_head node;
9212 + int busnr; /* primary bus number */
9213 + u64 mem_offset; /* bus->cpu memory mapping offset */
9214 + unsigned long io_offset; /* bus->cpu IO mapping offset */
9215 + struct pci_bus *bus; /* PCI bus */
9216 + struct resource *resource[3]; /* Primary PCI bus resources */
9217 + /* Bridge swizzling */
9218 + u8 (*swizzle)(struct pci_dev *, u8 *);
9220 + int (*map_irq)(struct pci_dev *, u8, u8);
9221 + struct hw_pci *hw;
9224 +static inline struct resource *
9225 +pcibios_select_root(struct pci_dev *pdev, struct resource *res)
9227 + struct resource *root = NULL;
9229 + if (res->flags & IORESOURCE_IO)
9230 + root = &ioport_resource;
9231 + if (res->flags & IORESOURCE_MEM)
9232 + root = &iomem_resource;
9237 +static inline void pcibios_set_master(struct pci_dev *dev)
9239 + /* No special bus mastering setup handling */
9241 +#define HAVE_ARCH_PCI_SET_DMA_MAX_SEGMENT_SIZE 1
9242 +#define HAVE_ARCH_PCI_SET_DMA_SEGMENT_BOUNDARY 1
9245 +static inline void * pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
9246 + dma_addr_t *dma_handle)
9248 + void *vaddr = kmalloc(size, GFP_KERNEL);
9249 + if(vaddr != NULL) {
9250 + *dma_handle = virt_to_phys(vaddr);
9255 +static inline int pci_dma_supported(struct pci_dev *hwdev, dma_addr_t mask)
9260 +static inline void pci_free_consistent(struct pci_dev *hwdev, size_t size,
9261 + void *cpu_addr, dma_addr_t dma_handle)
9267 +static inline dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr,
9268 + size_t size, int direction)
9270 + return virt_to_phys(ptr);
9273 +static inline void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr,
9274 + size_t size, int direction)
9279 +static inline dma_addr_t
9280 +pci_map_page(struct pci_dev *hwdev, struct page *page,
9281 + unsigned long offset, size_t size, int direction)
9283 + return pci_map_single(hwdev, page_address(page) + offset, size, (int)direction);
9287 +pci_unmap_page(struct pci_dev *hwdev, dma_addr_t dma_address,
9288 + size_t size, int direction)
9290 + pci_unmap_single(hwdev, dma_address, size, direction);
9294 +pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
9295 + int nents, int direction)
9301 +pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg,
9302 + int nents, int direction)
9307 +pci_dma_sync_sg_for_cpu(struct pci_dev *hwdev, struct scatterlist *sg,
9308 + int nelems, int direction)
9313 +pci_dma_sync_sg_for_device(struct pci_dev *hwdev, struct scatterlist *sg,
9314 + int nelems, int direction)
9319 +pci_dma_sync_single_for_cpu(struct pci_dev *hwdev, dma_addr_t dma_handle,
9320 + size_t size, int direction)
9325 +pci_dma_sync_single_for_device(struct pci_dev *hwdev, dma_addr_t dma_handle,
9326 + size_t size, int direction)
9331 +pci_dma_mapping_error(struct pci_dev *hwdev, dma_addr_t dma_addr)
9333 + return dma_addr == 0;
9335 +extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max);
9336 +extern void pci_iounmap(struct pci_dev *dev, void __iomem *);
9339 +#endif /* _ASM_UBICOM32_PCI_H */
9341 +++ b/arch/ubicom32/include/asm/pcm_tio.h
9344 + * arch/ubicom32/include/asm/pcm_tio.h
9345 + * Ubicom32 architecture PCM TIO definitions.
9347 + * (C) Copyright 2009, Ubicom, Inc.
9349 + * This file is part of the Ubicom32 Linux Kernel Port.
9351 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
9352 + * it and/or modify it under the terms of the GNU General Public License
9353 + * as published by the Free Software Foundation, either version 2 of the
9354 + * License, or (at your option) any later version.
9356 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
9357 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
9358 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
9359 + * the GNU General Public License for more details.
9361 + * You should have received a copy of the GNU General Public License
9362 + * along with the Ubicom32 Linux Kernel Port. If not,
9363 + * see <http://www.gnu.org/licenses/>.
9365 +#ifndef _ASM_UBICOM32_PCM_TIO_H
9366 +#define _ASM_UBICOM32_PCM_TIO_H
9368 +#include <asm/devtree.h>
9370 +#define PCM_TIO_REGS_VERSION 2
9371 +struct pcm_tio_regs {
9373 + * set this value to 1 to reload the parameters and restart the HRT
9378 + * Pointers to the input and output buffers
9384 + * Buffer size (see pcm_hrt.S for constraints)
9386 + u32_t buffer_size;
9389 + * Current cycle. This variable increases every time half the buffer
9395 + * Fields below this line are not accessed by the HRT. They are purely
9396 + * informational for the user of this TIO.
9400 + * Version of this structure
9405 + * Number of channels supported
9410 + * Maximum buffer size
9412 + u32_t max_buffer_size;
9418 +#define PCM_TIO_NODE_VERSION 1
9419 +struct pcm_tio_node {
9420 + struct devtree_node dn;
9422 + struct pcm_tio_regs *regs;
9428 +++ b/arch/ubicom32/include/asm/percpu.h
9431 + * arch/ubicom32/include/asm/percpu.h
9432 + * Generic percpu.h for the Ubicom32 architecture.
9434 + * (C) Copyright 2009, Ubicom, Inc.
9436 + * This file is part of the Ubicom32 Linux Kernel Port.
9438 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
9439 + * it and/or modify it under the terms of the GNU General Public License
9440 + * as published by the Free Software Foundation, either version 2 of the
9441 + * License, or (at your option) any later version.
9443 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
9444 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
9445 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
9446 + * the GNU General Public License for more details.
9448 + * You should have received a copy of the GNU General Public License
9449 + * along with the Ubicom32 Linux Kernel Port. If not,
9450 + * see <http://www.gnu.org/licenses/>.
9452 + * Ubicom32 implementation derived from (with many thanks):
9457 +#ifndef _ASM_UBICOM32_PERCPU_H
9458 +#define _ASM_UBICOM32_PERCPU_H
9460 +#include <asm-generic/percpu.h>
9462 +#endif /* _ASM_UBICOM32_PERCPU_H */
9464 +++ b/arch/ubicom32/include/asm/pgalloc.h
9467 + * arch/ubicom32/include/asm/pgalloc.h
9468 + * Page table allocation definitions.
9470 + * (C) Copyright 2009, Ubicom, Inc.
9472 + * This file is part of the Ubicom32 Linux Kernel Port.
9474 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
9475 + * it and/or modify it under the terms of the GNU General Public License
9476 + * as published by the Free Software Foundation, either version 2 of the
9477 + * License, or (at your option) any later version.
9479 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
9480 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
9481 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
9482 + * the GNU General Public License for more details.
9484 + * You should have received a copy of the GNU General Public License
9485 + * along with the Ubicom32 Linux Kernel Port. If not,
9486 + * see <http://www.gnu.org/licenses/>.
9488 + * Ubicom32 implementation derived from (with many thanks):
9493 +#ifndef _ASM_UBICOM32_PGALLOC_H
9494 +#define _ASM_UBICOM32_PGALLOC_H
9496 +#include <linux/mm.h>
9497 +#include <asm/setup.h>
9499 +#define check_pgt_cache() do { } while (0)
9501 +#endif /* _ASM_UBICOM32_PGALLOC_H */
9503 +++ b/arch/ubicom32/include/asm/pgtable.h
9506 + * arch/ubicom32/include/asm/pgtable.h
9507 + * Ubicom32 pseudo page table definitions and operations.
9509 + * (C) Copyright 2009, Ubicom, Inc.
9510 + * Copyright (C) 2004 Microtronix Datacom Ltd
9512 + * This file is part of the Ubicom32 Linux Kernel Port.
9514 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
9515 + * it and/or modify it under the terms of the GNU General Public License
9516 + * as published by the Free Software Foundation, either version 2 of the
9517 + * License, or (at your option) any later version.
9519 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
9520 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
9521 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
9522 + * the GNU General Public License for more details.
9524 + * You should have received a copy of the GNU General Public License
9525 + * along with the Ubicom32 Linux Kernel Port. If not,
9526 + * see <http://www.gnu.org/licenses/>.
9528 + * Ubicom32 implementation derived from (with many thanks):
9532 + * and various works, Alpha, ix86, M68K, Sparc, ...et al
9534 +#ifndef _ASM_UBICOM32_PGTABLE_H
9535 +#define _ASM_UBICOM32_PGTABLE_H
9537 +#include <asm-generic/4level-fixup.h>
9539 +//vic - this bit copied from m68knommu version
9540 +#include <asm/setup.h>
9541 +#include <asm/io.h>
9542 +#include <linux/sched.h>
9544 +typedef pte_t *pte_addr_t;
9546 +#define pgd_present(pgd) (1) /* pages are always present on NO_MM */
9547 +#define pgd_none(pgd) (0)
9548 +#define pgd_bad(pgd) (0)
9549 +#define pgd_clear(pgdp)
9550 +#define kern_addr_valid(addr) (1)
9551 +#define pmd_offset(a, b) ((void *)0)
9553 +#define PAGE_NONE __pgprot(0) /* these mean nothing to NO_MM */
9554 +#define PAGE_SHARED __pgprot(0) /* these mean nothing to NO_MM */
9555 +#define PAGE_COPY __pgprot(0) /* these mean nothing to NO_MM */
9556 +#define PAGE_READONLY __pgprot(0) /* these mean nothing to NO_MM */
9557 +#define PAGE_KERNEL __pgprot(0) /* these mean nothing to NO_MM */
9558 +//vic - this bit copied from m68knommu version
9560 +extern void paging_init(void);
9561 +#define swapper_pg_dir ((pgd_t *) 0)
9563 +#define __swp_type(x) (0)
9564 +#define __swp_offset(x) (0)
9565 +#define __swp_entry(typ,off) ((swp_entry_t) { ((typ) | ((off) << 7)) })
9566 +#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
9567 +#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
9570 + * pgprot_noncached() is only for infiniband pci support, and a real
9571 + * implementation for RAM would be more complicated.
9573 +#define pgprot_noncached(prot) (prot)
9575 +static inline int pte_file(pte_t pte) { return 0; }
9578 + * ZERO_PAGE is a global shared page that is always zero: used
9579 + * for zero-mapped memory areas etc..
9581 +#define ZERO_PAGE(vaddr) (virt_to_page(0))
9583 +extern unsigned int kobjsize(const void *objp);
9584 +extern int is_in_rom(unsigned long);
9587 + * No page table caches to initialise
9589 +#define pgtable_cache_init() do { } while (0)
9591 +#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
9592 + remap_pfn_range(vma, vaddr, pfn, size, prot)
9594 +extern inline void flush_cache_mm(struct mm_struct *mm)
9598 +extern inline void flush_cache_range(struct mm_struct *mm,
9599 + unsigned long start,
9600 + unsigned long end)
9604 +/* Push the page at kernel virtual address and clear the icache */
9605 +extern inline void flush_page_to_ram (unsigned long address)
9609 +/* Push n pages at kernel virtual address and clear the icache */
9610 +extern inline void flush_pages_to_ram (unsigned long address, int n)
9615 + * All 32bit addresses are effectively valid for vmalloc...
9616 + * Sort of meaningless for non-VM targets.
9618 +#define VMALLOC_START 0
9619 +#define VMALLOC_END 0xffffffff
9621 +#define arch_enter_lazy_mmu_mode() do {} while (0)
9622 +#define arch_leave_lazy_mmu_mode() do {} while (0)
9623 +#define arch_flush_lazy_mmu_mode() do {} while (0)
9624 +#define arch_enter_lazy_cpu_mode() do {} while (0)
9625 +#define arch_leave_lazy_cpu_mode() do {} while (0)
9626 +#define arch_flush_lazy_cpu_mode() do {} while (0)
9628 +#endif /* _ASM_UBICOM32_PGTABLE_H */
9630 +++ b/arch/ubicom32/include/asm/plio.h
9636 + * Copyright © 2009 Ubicom Inc. <www.ubicom.com>. All Rights Reserved.
9638 + * This file is part of the Ubicom32 Linux Kernel Port.
9640 + * The Ubicom32 Linux Kernel Port is free software: you can
9641 + * redistribute it and/or modify it under the terms of the GNU General
9642 + * Public License as published by the Free Software Foundation, either
9643 + * version 2 of the License, or (at your option) any later version.
9645 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
9646 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
9647 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9648 + * See the GNU General Public License for more details.
9650 + * You should have received a copy of the GNU General Public License
9651 + * along with the Ubicom32 Linux Kernel Port. If not,
9652 + * see <http://www.gnu.org/licenses/>.
9653 + * This file contains confidential information of Ubicom, Inc. and your use of
9654 + * this file is subject to the Ubicom Software License Agreement distributed with
9655 + * this file. If you are uncertain whether you are an authorized user or to report
9656 + * any unauthorized use, please contact Ubicom, Inc. at +1-408-789-2200.
9657 + * Unauthorized reproduction or distribution of this file is subject to civil and
9658 + * criminal penalties.
9661 +#ifndef __PLIO__H__
9662 +#define __PLIO__H__
9664 +#include <asm/ip5000.h>
9665 +#include <asm/thread.h>
9667 +#define PLIO_PORT RD
9668 +#define PLIO_EXT_PORT RI
9670 +#define TRANSMIT_FIFO_WATERMARK 8
9673 + * PLIO non-blocking register definitions
9679 + unsigned rxfifo_thread_enable: 1; /* allowed rxfifo thread enable */
9681 + unsigned rxfifo_thread: 4; /* allowed rxfifo thread access */
9683 + unsigned br_thread: 4; /* allowed blocking region thread access */
9684 + unsigned fn_reset: 4; /* function reset bit vector */
9685 + unsigned rxfifo_sel: 1; /* select between RXFIFO 0 and 1 */
9686 + unsigned fn_sel: 3; /* select port function */
9687 +} plio_io_function_t;
9696 + unsigned txfifo_uf: 1; /* TXFIFO underflow */
9697 + unsigned txfifo_wm: 1; /* TXFIFO watermark */
9698 + unsigned rxfifo_of: 1; /* RXFIFO overflow */
9699 + unsigned rxfifo_wm: 1; /* RXFIFO watermark */
9701 + unsigned lreg_int_addr_rd: 1; /* read from specified LREG address */
9702 + unsigned lreg_int_addr_wr: 1; /* write to specified LREG address */
9703 + unsigned extctl_int: 4; /* synchronized external interrupts */
9704 + unsigned pfsm_int: 1; /* state machine */
9708 + unsigned txfifo_reset: 1; /* TXFIFO reset for int_set only */
9709 + unsigned rxfifo_reset: 1; /* RXFIFO reset for int_set only */
9711 + unsigned idif_txfifo_flush: 1; /* flush TXFIFO and idif_txfifo */
9712 + unsigned idif_rxfifo_flush: 1; /* flush RXFIFO and idif_rxfifo */
9713 + unsigned pfsm_start: 1; /* input to fsm */
9714 + unsigned txfifo_uf: 1; /* TXFIFO underflow */
9715 + unsigned txfifo_wm: 1; /* TXFIFO watermark */
9716 + unsigned rxfifo_of: 1; /* RXFIFO overflow */
9717 + unsigned rxfifo_wm: 1; /* RXFIFO watermark */
9719 + unsigned lreg_int_addr_rd: 1; /* read from specified LREG address */
9720 + unsigned lreg_int_addr_wr: 1; /* write to specified LREG address */
9721 + unsigned extctl_int: 4; /* synchronized external interrupts */
9722 + unsigned pfsm_int: 1; /* state machine */
9727 + PLIO_PORT_MODE_DE,
9728 + PLIO_PORT_MODE_DI,
9729 + PLIO_PORT_MODE_DEI,
9730 + PLIO_PORT_MODE_DC,
9731 +} plio_port_mode_t;
9734 + PLIO_CLK_CORE, /* CORE CLK */
9735 + PLIO_CLK_IO, /* IO CLK */
9736 + PLIO_CLK_EXT, /* EXT CLK */
9740 + unsigned edif_iaena_sel: 1; /* Input Address Enable Select */
9741 + unsigned edif_iaclk_sel: 1; /* Input Address Clock Select */
9742 + unsigned edif_iald_inv: 1; /* Input Address Strobe Invert */
9743 + unsigned edif_idclk_sel: 1; /* Input Data Clock Select */
9744 + unsigned edif_idld_inv: 1; /* Input Data Strobe Invert */
9745 + unsigned edif_ds: 3; /* specify IDR and ODR data shift */
9746 + unsigned edif_cmp_mode: 1; /* configure IDR comparator output */
9747 + unsigned edif_idena_sel: 1; /* Input Data Enable Select */
9748 + unsigned ecif_extclk_ena: 1; /* plio_extctl output select */
9749 + unsigned idif_tx_fifo_cmd_sel: 1; /* select pfsm_cmd data word position */
9750 + unsigned ptif_porti_cfg: 2; /* select port I pin configuration */
9751 + unsigned ptif_portd_cfg: 3; /* select port D pin configuration */
9752 + plio_port_mode_t ptif_port_mode: 3; /* select other plio ports */
9753 + unsigned icif_clk_plio_ext_inv: 1; /* invert external plio clock when set */
9754 + unsigned icif_rst_plio: 1; /* reset plio function and io fifos */
9755 + plio_clk_src_t icif_clk_src_sel: 2; /* select plio clock source */
9756 + unsigned pfsm_prog: 1; /* enable pfsm programming */
9757 + unsigned pfsm_cmd: 3; /* software input to pfsm */
9762 + unsigned idif_byteswap_tx: 3; /* swap TXFIFO byte order */
9763 + unsigned idif_byteswap_rx: 3; /* swap RXFIFO byte order */
9765 + unsigned lreg_ena: 1; /* enable local register map */
9766 + unsigned lreg_addr_fifo_cmp_ena: 1; /* enable a specific LREG address from/to TX/RX fifos */
9767 + unsigned lreg_addr_fifo_cmp: 5; /* LREG address routed from/to TX/RX fifos */
9769 + unsigned dcod_iald_idld_sel: 2; /* select address/data strobes */
9770 + unsigned dcod_rw_src_sel: 1; /* select LREG strobe source */
9771 + unsigned dcod_rd_sel: 5; /* select read strobe source */
9772 + unsigned dcod_wr_sel: 5; /* select write strobe source */
9773 + unsigned dcod_rd_lvl: 1; /* select active level of read strobe */
9774 + unsigned dcod_wr_lvl: 1; /* select active level of read strobe */
9778 + unsigned icif_eclk_div: 16; /* external plio clock divider */
9779 + unsigned icif_iclk_div: 16; /* internal plio clock divider */
9784 + unsigned pfsm_state: 5; /* current pfsm state */
9789 + unsigned lreg_r_int_addr: 5;
9791 + unsigned lreg_w_int_addr: 5;
9792 + unsigned lreg_w_int_data: 8;
9802 +} plio_io_fifo_wm_t, plio_io_fifo_lvl_t;
9805 +/* plio blocking region register definitions
9849 + plio_grpsel_t grpsel[4];
9851 + plio_cs_lut_t cs_lut[4];
9852 + plio_extctl_t extctl_o_lut[8];
9864 + PLIO_ECIF_CLK_OUT = 9,
9865 + PLIO_ECIF_IALD = 9,
9866 + PLIO_ECIF_CLK_IN = 8,
9867 + PLIO_ECIF_IDLD = 8,
9868 + PLIO_ECIF_INT = 2,
9869 +} plio_ecif_output_t;
9872 + u32_t bypass_sync;
9874 + u32_t output_type;
9880 + u32_t idr_addr_pos_mask;
9886 + u32_t addr_rd_ena;
9887 + u32_t addr_wr_ena;
9888 + u32_t addr_rd_int_ena;
9889 + u32_t addr_wr_int_ena;
9894 + * PLIO configuration
9897 + plio_fctl0_t fctl0;
9898 + plio_fctl1_t fctl1;
9899 + plio_fctl2_t fctl2;
9911 + plio_io_function_t function;
9912 + plio_gpio_t gpio_ctl;
9913 + plio_gpio_t gpio_out;
9914 + plio_gpio_t gpio_in;
9915 + plio_intstat_t intstat;
9916 + plio_intstat_t intmask;
9917 + plio_intset_t intset;
9918 + plio_intstat_t intclr;
9923 + plio_fctl0_t fctl0;
9924 + plio_fctl1_t fctl1;
9925 + plio_fctl2_t fctl2;
9926 + plio_stat_0_t stat0;
9927 + plio_stat_1_t stat1;
9928 + plio_stat_2_t stat2;
9929 + plio_io_fifo_wm_t fifo_wm;
9930 + plio_io_fifo_lvl_t fifo_lvl;
9934 + u32_t pfsm_sram[256];
9935 + plio_config_t config;
9938 +#define PLIO_NBR ((plio_nbr_t *)(PLIO_PORT))
9939 +#define PLIO_BR ((plio_br_t *)((PLIO_PORT + IO_PORT_BR_OFFSET)))
9940 +#define PEXT_NBR ((plio_nbr_t *)(PLIO_EXT_PORT))
9942 +extern void plio_init(const plio_fctl_t *plio_fctl, const plio_config_t *plio_config, const plio_sram_t plio_sram_cfg[], int sram_cfg_size);
9944 +#endif // __PLIO__H__
9946 +++ b/arch/ubicom32/include/asm/poll.h
9949 + * arch/ubicom32/include/asm/poll.h
9950 + * Ubicom32 specific poll() related flags definitions.
9952 + * (C) Copyright 2009, Ubicom, Inc.
9954 + * This file is part of the Ubicom32 Linux Kernel Port.
9956 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
9957 + * it and/or modify it under the terms of the GNU General Public License
9958 + * as published by the Free Software Foundation, either version 2 of the
9959 + * License, or (at your option) any later version.
9961 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
9962 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
9963 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
9964 + * the GNU General Public License for more details.
9966 + * You should have received a copy of the GNU General Public License
9967 + * along with the Ubicom32 Linux Kernel Port. If not,
9968 + * see <http://www.gnu.org/licenses/>.
9970 + * Ubicom32 implementation derived from (with many thanks):
9975 +#ifndef _ASM_UBICOM32_POLL_H
9976 +#define _ASM_UBICOM32_POLL_H
9978 +#define POLLWRNORM POLLOUT
9979 +#define POLLWRBAND 0x0100
9981 +#include <asm-generic/poll.h>
9983 +#endif /* _ASM_UBICOM32_POLL_H */
9985 +++ b/arch/ubicom32/include/asm/posix_types.h
9988 + * arch/ubicom32/include/asm/posix_types.h
9989 + * Ubicom32 architecture posix types.
9991 + * (C) Copyright 2009, Ubicom, Inc.
9992 + * Copyright (C) 2004 Microtronix Datacom Ltd
9994 + * This file is part of the Ubicom32 Linux Kernel Port.
9996 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
9997 + * it and/or modify it under the terms of the GNU General Public License
9998 + * as published by the Free Software Foundation, either version 2 of the
9999 + * License, or (at your option) any later version.
10001 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10002 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10003 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
10004 + * the GNU General Public License for more details.
10006 + * You should have received a copy of the GNU General Public License
10007 + * along with the Ubicom32 Linux Kernel Port. If not,
10008 + * see <http://www.gnu.org/licenses/>.
10010 + * Ubicom32 implementation derived from (with many thanks):
10015 +#ifndef __ARCH_UBICOM32_POSIX_TYPES_H
10016 +#define __ARCH_UBICOM32_POSIX_TYPES_H
10019 + * This file is generally used by user-level software, so you need to
10020 + * be a little careful about namespace pollution etc. Also, we cannot
10021 + * assume GCC is being used.
10024 +typedef unsigned long __kernel_ino_t;
10025 +typedef unsigned short __kernel_mode_t;
10026 +typedef unsigned short __kernel_nlink_t;
10027 +typedef long __kernel_off_t;
10028 +typedef int __kernel_pid_t;
10029 +typedef unsigned short __kernel_ipc_pid_t;
10030 +typedef unsigned short __kernel_uid_t;
10031 +typedef unsigned short __kernel_gid_t;
10032 +typedef unsigned int __kernel_size_t;
10033 +typedef int __kernel_ssize_t;
10034 +typedef int __kernel_ptrdiff_t;
10035 +typedef long __kernel_time_t;
10036 +typedef long __kernel_suseconds_t;
10037 +typedef long __kernel_clock_t;
10038 +typedef int __kernel_timer_t;
10039 +typedef int __kernel_clockid_t;
10040 +typedef int __kernel_daddr_t;
10041 +typedef char * __kernel_caddr_t;
10042 +typedef unsigned short __kernel_uid16_t;
10043 +typedef unsigned short __kernel_gid16_t;
10044 +typedef unsigned int __kernel_uid32_t;
10045 +typedef unsigned int __kernel_gid32_t;
10047 +typedef unsigned short __kernel_old_uid_t;
10048 +typedef unsigned short __kernel_old_gid_t;
10049 +typedef unsigned short __kernel_old_dev_t;
10052 +typedef long long __kernel_loff_t;
10056 +#if defined(__KERNEL__) || defined(__USE_ALL)
10058 +#else /* !defined(__KERNEL__) && !defined(__USE_ALL) */
10060 +#endif /* !defined(__KERNEL__) && !defined(__USE_ALL) */
10061 +} __kernel_fsid_t;
10063 +#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
10066 +#define __FD_SET(d, set) ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d))
10069 +#define __FD_CLR(d, set) ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
10072 +#define __FD_ISSET(d, set) ((set)->fds_bits[__FDELT(d)] & __FDMASK(d))
10075 +#define __FD_ZERO(fdsetp) (memset (fdsetp, 0, sizeof(*(fd_set *)fdsetp)))
10077 +#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */
10081 +++ b/arch/ubicom32/include/asm/processor.h
10084 + * arch/ubicom32/include/asm/processor.h
10085 + * Thread related definitions for Ubicom32 architecture.
10087 + * (C) Copyright 2009, Ubicom, Inc.
10088 + * Copyright (C) 1995 Hamish Macdonald
10090 + * This file is part of the Ubicom32 Linux Kernel Port.
10092 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10093 + * it and/or modify it under the terms of the GNU General Public License
10094 + * as published by the Free Software Foundation, either version 2 of the
10095 + * License, or (at your option) any later version.
10097 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10098 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10099 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
10100 + * the GNU General Public License for more details.
10102 + * You should have received a copy of the GNU General Public License
10103 + * along with the Ubicom32 Linux Kernel Port. If not,
10104 + * see <http://www.gnu.org/licenses/>.
10106 + * Ubicom32 implementation derived from (with many thanks):
10112 +#ifndef _ASM_UBICOM32_PROCESSOR_H
10113 +#define _ASM_UBICOM32_PROCESSOR_H
10116 + * Default implementation of macro that returns current
10117 + * instruction pointer ("program counter").
10119 +#define current_text_addr() ({ __label__ _l; _l: &&_l;})
10121 +#include <linux/compiler.h>
10122 +#include <linux/threads.h>
10123 +#include <asm/types.h>
10124 +#include <asm/segment.h>
10125 +#include <asm/fpu.h>
10126 +#include <asm/ptrace.h>
10127 +#include <asm/current.h>
10128 +#include <asm/thread_info.h>
10130 +#if defined(CONFIG_UBICOM32_V3)
10131 + #define CPU "IP5K"
10133 +#if defined(CONFIG_UBICOM32_V4)
10134 + #define CPU "IP7K"
10137 + #define CPU "UNKNOWN"
10141 + * User space process size: 1st byte beyond user address space.
10143 +extern unsigned long memory_end;
10144 +#define TASK_SIZE (memory_end)
10147 + * This decides where the kernel will search for a free chunk of vm
10148 + * space during mmap's. We won't be using it
10150 +#define TASK_UNMAPPED_BASE 0
10153 + * This is the structure where we are going to save callee-saved registers.
10154 + * A5 is the return address, A7 is the stack pointer, A6 is the frame
10155 + * pointer. This is the frame that is created because of switch_to. This
10156 + * is not the frame due to interrupt preemption or because of syscall entry.
10159 +struct thread_struct {
10160 + unsigned long d10; /* D10 */
10161 + unsigned long d11; /* D11 */
10162 + unsigned long d12; /* D12 */
10163 + unsigned long d13; /* D13 */
10164 + unsigned long a1; /* A1 */
10165 + unsigned long a2; /* A2 */
10166 + unsigned long a5; /* A5 return address. */
10167 + unsigned long a6; /* A6 */
10168 + unsigned long sp; /* A7 kernel stack pointer. */
10171 +#define INIT_THREAD { \
10172 + 0, 0, 0, 0, 0, 0, 0, 0, \
10173 + sizeof(init_stack) + (unsigned long) init_stack - 8, \
10177 + * Do necessary setup to start up a newly executed thread.
10179 + * pass the data segment into user programs if it exists,
10180 + * it can't hurt anything as far as I can tell
10183 + * Do necessary setup to start up a newly executed thread.
10185 +#define start_thread(regs, new_pc, new_sp) \
10187 + regs->pc = new_pc & ~3; \
10188 + regs->an[5] = new_pc & ~3; \
10189 + regs->an[7] = new_sp; \
10190 + regs->nesting_level = -1; \
10191 + regs->frame_type = UBICOM32_FRAME_TYPE_NEW_THREAD; \
10192 + regs->thread_type = NORMAL_THREAD; \
10195 +/* Forward declaration, a strange C thing */
10196 +struct task_struct;
10198 +/* Free all resources held by a thread. */
10199 +static inline void release_thread(struct task_struct *dead_task)
10203 +/* Prepare to copy thread state - unlazy all lazy status */
10204 +#define prepare_to_copy(tsk) do { } while (0)
10206 +extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
10209 + * Free current thread data structures etc..
10211 +static inline void exit_thread(void)
10215 +unsigned long thread_saved_pc(struct task_struct *tsk);
10216 +unsigned long get_wchan(struct task_struct *p);
10218 +#define KSTK_EIP(tsk) (tsk->thread.a5)
10219 +#define KSTK_ESP(tsk) (tsk->thread.sp)
10221 +#define cpu_relax() barrier()
10223 +extern void processor_init(void);
10224 +extern unsigned int processor_timers(void);
10225 +extern unsigned int processor_threads(void);
10226 +extern unsigned int processor_frequency(void);
10227 +extern int processor_interrupts(unsigned int *int0, unsigned int *int1);
10228 +extern void processor_ocm(unsigned long *socm, unsigned long *eocm);
10229 +extern void processor_dram(unsigned long *sdram, unsigned long *edram);
10231 +#define THREAD_SIZE_LONGS (THREAD_SIZE/sizeof(unsigned long))
10232 +#define KSTK_TOP(info) \
10234 + unsigned long *__ptr = (unsigned long *)(info); \
10235 + (unsigned long)(&__ptr[THREAD_SIZE_LONGS]); \
10238 +#define task_pt_regs(task) \
10240 + struct pt_regs *__regs__; \
10241 + __regs__ = (struct pt_regs *)(KSTK_TOP(task_stack_page(task))-8); \
10245 +#endif /* _ASM_UBICOM32_PROCESSOR_H */
10247 +++ b/arch/ubicom32/include/asm/profilesample.h
10250 + * arch/ubicom32/mach-common/profile.h
10251 + * Private data for the profile module
10253 + * (C) Copyright 2009, Ubicom, Inc.
10255 + * This file is part of the Ubicom32 Linux Kernel Port.
10257 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10258 + * it and/or modify it under the terms of the GNU General Public License
10259 + * as published by the Free Software Foundation, either version 2 of the
10260 + * License, or (at your option) any later version.
10262 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10263 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10264 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
10265 + * the GNU General Public License for more details.
10267 + * You should have received a copy of the GNU General Public License
10268 + * along with the Ubicom32 Linux Kernel Port. If not,
10269 + * see <http://www.gnu.org/licenses/>.
10274 +#ifndef _PROFILESAMPLE_H_
10275 +#define _PROFILESAMPLE_H_
10278 + * a sample taken by the ipProfile package for sending to the profilertool
10280 +struct profile_sample {
10281 + unsigned int pc; /* PC value */
10282 + unsigned int a5; /* a5 contents for parent of leaf function */
10283 + unsigned int parent; /* return address from stack, to find the caller */
10284 + unsigned int latency; /* CPU clocks since the last message dispatch in this thread (thread 0 ony for now) */
10285 + unsigned short active; /* which threads are active - for accurate counting */
10286 + unsigned short d_blocked; /* which threads are blocked due to D cache misses */
10287 + unsigned short i_blocked; /* which threads are blocked due to I cache misses */
10288 + unsigned char cond_codes; /* for branch prediction */
10289 + unsigned char thread; /* I-blocked, D-blocked, 4-bit thread number */
10294 +++ b/arch/ubicom32/include/asm/ptrace.h
10297 + * arch/ubicom32/include/asm/ptrace.h
10298 + * Ubicom32 architecture ptrace support.
10300 + * (C) Copyright 2009, Ubicom, Inc.
10302 + * This file is part of the Ubicom32 Linux Kernel Port.
10304 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10305 + * it and/or modify it under the terms of the GNU General Public License
10306 + * as published by the Free Software Foundation, either version 2 of the
10307 + * License, or (at your option) any later version.
10309 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10310 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10311 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
10312 + * the GNU General Public License for more details.
10314 + * You should have received a copy of the GNU General Public License
10315 + * along with the Ubicom32 Linux Kernel Port. If not,
10316 + * see <http://www.gnu.org/licenses/>.
10318 + * Ubicom32 implementation derived from (with many thanks):
10323 +#ifndef _ASM_UBICOM32_PTRACE_H
10324 +#define _ASM_UBICOM32_PTRACE_H
10326 +#ifndef __ASSEMBLY__
10329 + * We use hard coded constants because this is shared with user
10330 + * space and the values are NOT allowed to change. Only fields
10331 + * that are intended to be exposed get values.
10358 +#define PT_ACC0HI 96
10359 +#define PT_ACC0LO 100
10360 +#define PT_MAC_RC16 104
10361 +#define PT_ACC1HI 108
10362 +#define PT_ACC1LO 112
10363 +#define PT_SOURCE3 116
10364 +#define PT_INST_CNT 120
10365 +#define PT_CSR 124
10366 +#define PT_DUMMY_UNUSED 128
10367 +#define PT_INT_MASK0 132
10368 +#define PT_INT_MASK1 136
10369 +#define PT_TRAP_CAUSE 140
10371 +#define PT_ORIGINAL_D0 148
10372 +#define PT_FRAME_TYPE 152
10375 + * The following 'registers' are not registers at all but are used
10376 + * locate the relocated sections.
10378 +#define PT_TEXT_ADDR 200
10379 +#define PT_TEXT_END_ADDR 204
10380 +#define PT_DATA_ADDR 208
10381 +#define PT_EXEC_FDPIC_LOADMAP 212
10382 +#define PT_INTERP_FDPIC_LOADMAP 216
10385 + * This struct defines the way the registers are stored on the
10386 + * stack during a system call.
10388 +enum thread_type {
10393 +#define UBICOM32_FRAME_TYPE_SYSCALL -1 /* System call frame */
10394 +#define UBICOM32_FRAME_TYPE_INVALID 0 /* Invalid frame, no longer in use */
10395 +#define UBICOM32_FRAME_TYPE_INTERRUPT 1 /* Interrupt frame */
10396 +#define UBICOM32_FRAME_TYPE_TRAP 2 /* Trap frame */
10397 +#define UBICOM32_FRAME_TYPE_SIGTRAMP 3 /* Signal trampoline frame. */
10398 +#define UBICOM32_FRAME_TYPE_NEW_THREAD 4 /* New Thread. */
10404 + unsigned long dn[16];
10407 + * Address Registers
10409 + unsigned long an[8];
10412 + * Per thread misc registers.
10414 + unsigned long acc0[2];
10415 + unsigned long mac_rc16;
10416 + unsigned long acc1[2];
10417 + unsigned long source3;
10418 + unsigned long inst_cnt;
10419 + unsigned long csr;
10420 + unsigned long dummy_unused;
10421 + unsigned long int_mask0;
10422 + unsigned long int_mask1;
10423 + unsigned long trap_cause;
10424 + unsigned long pc;
10425 + unsigned long original_dn_0;
10428 + * Frame type. Syscall frames are -1. For other types look above.
10430 + unsigned long frame_type;
10433 + * These fields are not exposed to ptrace.
10435 + unsigned long previous_pc;
10436 + long nesting_level; /* When the kernel in in user space this
10438 + unsigned long thread_type; /* This indicates if this is a kernel
10443 + * This is the extended stack used by signal handlers and the context
10444 + * switcher: it's pushed after the normal "struct pt_regs".
10446 +struct switch_stack {
10447 + unsigned long dummy;
10452 +/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
10453 +#define PTRACE_GETREGS 12
10454 +#define PTRACE_SETREGS 13
10457 +#define PS_S (0x2000)
10458 +#define PS_M (0x1000)
10461 +extern int __user_mode(unsigned long sp);
10463 +#define user_mode(regs) (__user_mode((regs->an[7])))
10464 +#define user_stack(regs) ((regs)->an[7])
10465 +#define instruction_pointer(regs) ((regs)->pc)
10466 +#define profile_pc(regs) instruction_pointer(regs)
10467 +extern void show_regs(struct pt_regs *);
10468 +#endif /* __KERNEL__ */
10470 +#endif /* __ASSEMBLY__ */
10472 +#endif /* _ASM_UBICOM32_PTRACE_H */
10474 +++ b/arch/ubicom32/include/asm/range-protect-asm.h
10477 + * arch/ubicom32/include/asm/range-protect-asm.h
10478 + * Assembly macros for enabling memory protection.
10480 + * (C) Copyright 2009, Ubicom, Inc.
10482 + * This file is part of the Ubicom32 Linux Kernel Port.
10484 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10485 + * it and/or modify it under the terms of the GNU General Public License
10486 + * as published by the Free Software Foundation, either version 2 of the
10487 + * License, or (at your option) any later version.
10489 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10490 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10491 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
10492 + * the GNU General Public License for more details.
10494 + * You should have received a copy of the GNU General Public License
10495 + * along with the Ubicom32 Linux Kernel Port. If not,
10496 + * see <http://www.gnu.org/licenses/>.
10498 + * Ubicom32 implementation derived from (with many thanks):
10504 +#ifndef _ASM_UBICOM32_RANGE_PROTECT_ASM_H
10505 +#define _ASM_UBICOM32_RANGE_PROTECT_ASM_H
10507 +#if defined(__ASSEMBLY__)
10509 +#include <asm/thread-asm.h>
10512 + * You should only use the enable/disable ranges when you have the atomic lock,
10513 + * if you do not there will be problems.
10517 + * enable_kernel_ranges
10518 + * Enable the kernel ranges (disabling protection) for thread,
10519 + * where thread == (1 << thread number)
10521 +.macro enable_kernel_ranges thread
10522 +#ifdef CONFIG_PROTECT_KERNEL
10523 + or.4 I_RANGE0_EN, I_RANGE0_EN, \thread /* Enable Range Register */
10524 + or.4 D_RANGE0_EN, D_RANGE0_EN, \thread
10525 + or.4 D_RANGE1_EN, D_RANGE1_EN, \thread
10530 + * enable_kernel_ranges_for_current
10531 + * Enable the kernel ranges (disabling protection) for this thread
10533 +.macro enable_kernel_ranges_for_current scratch_reg
10534 +#ifdef CONFIG_PROTECT_KERNEL
10535 + thread_get_self_mask \scratch_reg
10536 + enable_kernel_ranges \scratch_reg
10541 + * disable_kernel_ranges
10542 + * Disables the kernel ranges (enabling protection) for thread
10543 + * where thread == (1 << thread number)
10545 +.macro disable_kernel_ranges thread
10546 +#ifdef CONFIG_PROTECT_KERNEL
10547 + not.4 \thread, \thread
10548 + and.4 I_RANGE0_EN, I_RANGE0_EN, \thread /* Disable Range Register */
10549 + and.4 D_RANGE0_EN, D_RANGE0_EN, \thread
10550 + and.4 D_RANGE1_EN, D_RANGE1_EN, \thread
10555 + * disable_kernel_ranges_for_current
10556 + * Disable kernel ranges (enabling protection) for this thread
10558 +.macro disable_kernel_ranges_for_current scratch_reg
10559 +#ifdef CONFIG_PROTECT_KERNEL
10560 + thread_get_self_mask \scratch_reg
10561 + disable_kernel_ranges \scratch_reg
10566 +#endif /* _ASM_UBICOM32_RANGE_PROTECT_ASM_H */
10568 +++ b/arch/ubicom32/include/asm/range-protect.h
10571 + * arch/ubicom32/include/asm/range-protect.h
10572 + * Assembly macros declared in C for enabling memory protection.
10574 + * (C) Copyright 2009, Ubicom, Inc.
10576 + * This file is part of the Ubicom32 Linux Kernel Port.
10578 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10579 + * it and/or modify it under the terms of the GNU General Public License
10580 + * as published by the Free Software Foundation, either version 2 of the
10581 + * License, or (at your option) any later version.
10583 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10584 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10585 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
10586 + * the GNU General Public License for more details.
10588 + * You should have received a copy of the GNU General Public License
10589 + * along with the Ubicom32 Linux Kernel Port. If not,
10590 + * see <http://www.gnu.org/licenses/>.
10592 + * Ubicom32 implementation derived from (with many thanks):
10598 +#ifndef _ASM_UBICOM32_RANGE_PROTECT_H
10599 +#define _ASM_UBICOM32_RANGE_PROTECT_H
10601 +#if !defined(__ASSEMBLY__)
10602 +#include <asm/thread.h>
10604 + * The following macros should be the identical to the ones in
10605 + * range-protect-asm.h
10607 + * You should only use the enable/disable ranges when you have the atomic lock,
10608 + * if you do not there will be problems.
10612 + * enable_kernel_ranges
10613 + * Enable the kernel ranges (disabling protection) for thread,
10614 + * where thread == (1 << thread number)
10617 + ".macro enable_kernel_ranges thread \n\t"
10618 +#ifdef CONFIG_PROTECT_KERNEL
10619 + " or.4 I_RANGE0_EN, I_RANGE0_EN, \\thread \n\t" /* Enable Range Register */
10620 + " or.4 D_RANGE0_EN, D_RANGE0_EN, \\thread \n\t"
10621 + " or.4 D_RANGE1_EN, D_RANGE1_EN, \\thread \n\t"
10626 +#else /* __ASSEMBLY__ */
10628 +#include <asm/range-protect-asm.h>
10631 +#endif /* _ASM_UBICOM32_RANGE_PROTECT_H */
10633 +++ b/arch/ubicom32/include/asm/resource.h
10636 + * arch/ubicom32/include/asm/resource.h
10637 + * Generic definitions for Ubicom32 architecture.
10639 + * (C) Copyright 2009, Ubicom, Inc.
10641 + * This file is part of the Ubicom32 Linux Kernel Port.
10643 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10644 + * it and/or modify it under the terms of the GNU General Public License
10645 + * as published by the Free Software Foundation, either version 2 of the
10646 + * License, or (at your option) any later version.
10648 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10649 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10650 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
10651 + * the GNU General Public License for more details.
10653 + * You should have received a copy of the GNU General Public License
10654 + * along with the Ubicom32 Linux Kernel Port. If not,
10655 + * see <http://www.gnu.org/licenses/>.
10657 + * Ubicom32 implementation derived from (with many thanks):
10662 +#ifndef _ASM_UBICOM32_RESOURCE_H
10663 +#define _ASM_UBICOM32_RESOURCE_H
10665 +#include <asm-generic/resource.h>
10667 +#endif /* _ASM_UBICOM32_RESOURCE_H */
10669 +++ b/arch/ubicom32/include/asm/ring_tio.h
10672 + * arch/ubicom32/include/asm/ring_tio.h
10673 + * Ubicom32 architecture Ring TIO definitions.
10675 + * (C) Copyright 2009, Ubicom, Inc.
10677 + * This file is part of the Ubicom32 Linux Kernel Port.
10679 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10680 + * it and/or modify it under the terms of the GNU General Public License
10681 + * as published by the Free Software Foundation, either version 2 of the
10682 + * License, or (at your option) any later version.
10684 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10685 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10686 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
10687 + * the GNU General Public License for more details.
10689 + * You should have received a copy of the GNU General Public License
10690 + * along with the Ubicom32 Linux Kernel Port. If not,
10691 + * see <http://www.gnu.org/licenses/>.
10693 +#ifndef _ASM_UBICOM32_RING_TIO_H
10694 +#define _ASM_UBICOM32_RING_TIO_H
10696 +#include <asm/devtree.h>
10698 +#define RING_TIO_NODE_VERSION 2
10701 + * Devtree node for ring
10703 +struct ring_tio_node {
10704 + struct devtree_node dn;
10710 +extern void ring_tio_init(const char *node_name);
10712 +#endif /* _ASM_UBICOM32_RING_TIO_H */
10714 +++ b/arch/ubicom32/include/asm/scatterlist.h
10717 + * arch/ubicom32/include/asm/scatterlist.h
10718 + * Definitions of struct scatterlist for Ubicom32 architecture.
10720 + * (C) Copyright 2009, Ubicom, Inc.
10722 + * This file is part of the Ubicom32 Linux Kernel Port.
10724 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10725 + * it and/or modify it under the terms of the GNU General Public License
10726 + * as published by the Free Software Foundation, either version 2 of the
10727 + * License, or (at your option) any later version.
10729 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10730 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10731 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
10732 + * the GNU General Public License for more details.
10734 + * You should have received a copy of the GNU General Public License
10735 + * along with the Ubicom32 Linux Kernel Port. If not,
10736 + * see <http://www.gnu.org/licenses/>.
10738 + * Ubicom32 implementation derived from (with many thanks):
10743 +#ifndef _ASM_UBICOM32_SCATTERLIST_H
10744 +#define _ASM_UBICOM32_SCATTERLIST_H
10746 +#include <linux/mm.h>
10747 +#include <asm/types.h>
10749 +struct scatterlist {
10750 +#ifdef CONFIG_DEBUG_SG
10751 + unsigned long sg_magic;
10753 + unsigned long page_link;
10754 + unsigned int offset;
10755 + dma_addr_t dma_address;
10756 + unsigned int length;
10759 +#define sg_dma_address(sg) ((sg)->dma_address)
10760 +#define sg_dma_len(sg) ((sg)->length)
10762 +#define ISA_DMA_THRESHOLD (0xffffffff)
10764 +#endif /* _ASM_UBICOM32_SCATTERLIST_H */
10766 +++ b/arch/ubicom32/include/asm/sd_tio.h
10769 + * arch/ubicom32/include/asm/sd_tio.h
10770 + * SD TIO definitions
10772 + * (C) Copyright 2009, Ubicom, Inc.
10774 + * This file is part of the Ubicom32 Linux Kernel Port.
10776 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10777 + * it and/or modify it under the terms of the GNU General Public License
10778 + * as published by the Free Software Foundation, either version 2 of the
10779 + * License, or (at your option) any later version.
10781 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10782 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10783 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
10784 + * the GNU General Public License for more details.
10786 + * You should have received a copy of the GNU General Public License
10787 + * along with the Ubicom32 Linux Kernel Port. If not,
10788 + * see <http://www.gnu.org/licenses/>.
10790 +#ifndef _ASM_UBICOM32_SD_TIO_H
10791 +#define _ASM_UBICOM32_SD_TIO_H
10793 +#include <asm/devtree.h>
10796 + * Devtree node for SD
10798 +struct sd_tio_node {
10799 + struct devtree_node dn;
10803 +#endif /* _ASM_UBICOM32_SD_TIO_H */
10805 +++ b/arch/ubicom32/include/asm/sections.h
10808 + * arch/ubicom32/include/asm/sections.h
10809 + * Generic sections.h definitions for Ubicom32 architecture.
10811 + * (C) Copyright 2009, Ubicom, Inc.
10813 + * This file is part of the Ubicom32 Linux Kernel Port.
10815 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10816 + * it and/or modify it under the terms of the GNU General Public License
10817 + * as published by the Free Software Foundation, either version 2 of the
10818 + * License, or (at your option) any later version.
10820 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10821 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10822 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
10823 + * the GNU General Public License for more details.
10825 + * You should have received a copy of the GNU General Public License
10826 + * along with the Ubicom32 Linux Kernel Port. If not,
10827 + * see <http://www.gnu.org/licenses/>.
10829 + * Ubicom32 implementation derived from (with many thanks):
10834 +#ifndef _ASM_UBICOM32_SECTIONS_H
10835 +#define _ASM_UBICOM32_SECTIONS_H
10837 +#include <asm-generic/sections.h>
10839 +#endif /* _ASM_UBICOM32_SECTIONS_H */
10841 +++ b/arch/ubicom32/include/asm/segment.h
10844 + * arch/ubicom32/include/asm/segment.h
10845 + * Memory segment definitions for Ubicom32 architecture.
10847 + * (C) Copyright 2009, Ubicom, Inc.
10849 + * This file is part of the Ubicom32 Linux Kernel Port.
10851 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10852 + * it and/or modify it under the terms of the GNU General Public License
10853 + * as published by the Free Software Foundation, either version 2 of the
10854 + * License, or (at your option) any later version.
10856 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10857 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10858 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
10859 + * the GNU General Public License for more details.
10861 + * You should have received a copy of the GNU General Public License
10862 + * along with the Ubicom32 Linux Kernel Port. If not,
10863 + * see <http://www.gnu.org/licenses/>.
10865 + * Ubicom32 implementation derived from (with many thanks):
10870 +#ifndef _ASM_UBICOM32_SEGMENT_H
10871 +#define _ASM_UBICOM32_SEGMENT_H
10873 +/* define constants */
10874 +/* Address spaces (FC0-FC2) */
10875 +#define USER_DATA (1)
10877 +#define __USER_DS (USER_DATA)
10879 +#define USER_PROGRAM (2)
10880 +#define SUPER_DATA (5)
10881 +#ifndef __KERNEL_DS
10882 +#define __KERNEL_DS (SUPER_DATA)
10884 +#define SUPER_PROGRAM (6)
10885 +#define CPU_SPACE (7)
10887 +#ifndef __ASSEMBLY__
10890 + unsigned long seg;
10893 +#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
10894 +#define USER_DS MAKE_MM_SEG(__USER_DS)
10895 +#define KERNEL_DS MAKE_MM_SEG(__KERNEL_DS)
10898 + * Get/set the SFC/DFC registers for MOVES instructions
10901 +static inline mm_segment_t get_fs(void)
10906 +static inline mm_segment_t get_ds(void)
10908 + /* return the supervisor data space code */
10909 + return KERNEL_DS;
10912 +static inline void set_fs(mm_segment_t val)
10916 +#define segment_eq(a,b) ((a).seg == (b).seg)
10918 +#endif /* __ASSEMBLY__ */
10920 +#endif /* _ASM_UBICOM32_SEGMENT_H */
10922 +++ b/arch/ubicom32/include/asm/semaphore.h
10925 + * arch/ubicom32/include/asm/semaphore.h
10926 + * Interrupt-safe semaphores for Ubicom32 architecture.
10928 + * (C) Copyright 2009, Ubicom, Inc.
10929 + * (C) Copyright 1996 Linus Torvalds
10930 + * m68k version by Andreas Schwab
10931 + * Copyright (C) 2004 Microtronix Datacom Ltd
10933 + * This file is part of the Ubicom32 Linux Kernel Port.
10935 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10936 + * it and/or modify it under the terms of the GNU General Public License
10937 + * as published by the Free Software Foundation, either version 2 of the
10938 + * License, or (at your option) any later version.
10940 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
10941 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
10942 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
10943 + * the GNU General Public License for more details.
10945 + * You should have received a copy of the GNU General Public License
10946 + * along with the Ubicom32 Linux Kernel Port. If not,
10947 + * see <http://www.gnu.org/licenses/>.
10949 + * Ubicom32 implementation derived from (with many thanks):
10954 +#ifndef _ASM_UBICOM32_SEMAPHORE_H
10955 +#define _ASM_UBICOM32_SEMAPHORE_H
10957 +#define RW_LOCK_BIAS 0x01000000
10959 +#ifndef __ASSEMBLY__
10961 +#include <linux/linkage.h>
10962 +#include <linux/wait.h>
10963 +#include <linux/spinlock.h>
10964 +#include <linux/rwsem.h>
10966 +#include <asm/system.h>
10967 +#include <asm/atomic.h>
10969 +struct semaphore {
10972 + wait_queue_head_t wait;
10975 +#define __SEMAPHORE_INITIALIZER(name, n) \
10977 + .count = ATOMIC_INIT(n), \
10978 + .waking = ATOMIC_INIT(0), \
10979 + .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
10982 +#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
10983 + struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
10985 +#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
10986 +#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
10988 +static inline void sema_init (struct semaphore *sem, int val)
10990 + *sem = (struct semaphore)__SEMAPHORE_INITIALIZER(*sem, val);
10993 +static inline void init_MUTEX (struct semaphore *sem)
10995 + sema_init(sem, 1);
10998 +static inline void init_MUTEX_LOCKED (struct semaphore *sem)
11000 + sema_init(sem, 0);
11003 +asmlinkage void __down_failed(void /* special register calling convention */);
11004 +asmlinkage int __down_failed_interruptible(void /* params in registers */);
11005 +asmlinkage int __down_failed_trylock(void /* params in registers */);
11006 +asmlinkage void __up_wakeup(void /* special register calling convention */);
11008 +asmlinkage void __down(struct semaphore * sem);
11009 +asmlinkage int __down_interruptible(struct semaphore * sem);
11010 +asmlinkage int __down_trylock(struct semaphore * sem);
11011 +asmlinkage void __up(struct semaphore * sem);
11013 +extern spinlock_t semaphore_wake_lock;
11016 + * This is ugly, but we want the default case to fall through.
11017 + * "down_failed" is a special asm handler that calls the C
11018 + * routine that actually waits.
11020 +static inline void down(struct semaphore * sem)
11024 + if (atomic_dec_return(&sem->count) < 0)
11028 +static inline int down_interruptible(struct semaphore * sem)
11035 + if(atomic_dec_return(&sem->count) < 0)
11036 + ret = __down_interruptible(sem);
11040 +static inline int down_trylock(struct semaphore * sem)
11044 + if (atomic_dec_return (&sem->count) < 0)
11045 + ret = __down_trylock(sem);
11050 + * Note! This is subtle. We jump to wake people up only if
11051 + * the semaphore was negative (== somebody was waiting on it).
11052 + * The default case (no contention) will result in NO
11053 + * jumps for both down() and up().
11055 +static inline void up(struct semaphore * sem)
11057 + if (atomic_inc_return(&sem->count) <= 0)
11061 +#endif /* __ASSEMBLY__ */
11063 +#endif /* _ASM_UBICOM32_SEMAPHORE_H */
11065 +++ b/arch/ubicom32/include/asm/semaphore-helper.h
11068 + * arch/ubicom32/include/asm/semaphore-helper.h
11069 + * Semaphore related definitions for Ubicom32 architecture.
11071 + * (C) Copyright 2009, Ubicom, Inc.
11073 + * This file is part of the Ubicom32 Linux Kernel Port.
11075 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
11076 + * it and/or modify it under the terms of the GNU General Public License
11077 + * as published by the Free Software Foundation, either version 2 of the
11078 + * License, or (at your option) any later version.
11080 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
11081 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11082 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
11083 + * the GNU General Public License for more details.
11085 + * You should have received a copy of the GNU General Public License
11086 + * along with the Ubicom32 Linux Kernel Port. If not,
11087 + * see <http://www.gnu.org/licenses/>.
11089 + * Ubicom32 implementation derived from (with many thanks):
11094 +#ifndef _ASM_UBICOM32_SEMAPHORE_HELPER_H
11095 +#define _ASM_UBICOM32_SEMAPHORE_HELPER_H
11098 + * SMP- and interrupt-safe semaphores helper functions.
11100 + * (C) Copyright 1996 Linus Torvalds
11102 + * m68k version by Andreas Schwab
11107 + * These two _must_ execute atomically wrt each other.
11109 +static inline void wake_one_more(struct semaphore * sem)
11111 + atomic_inc(&sem->waking);
11114 +static inline int waking_non_zero(struct semaphore *sem)
11117 + unsigned long flags;
11119 + spin_lock_irqsave(&semaphore_wake_lock, flags);
11121 + if (atomic_read(&sem->waking) > 0) {
11122 + atomic_dec(&sem->waking);
11125 + spin_unlock_irqrestore(&semaphore_wake_lock, flags);
11130 + * waking_non_zero_interruptible:
11133 + * -EINTR interrupted
11135 +static inline int waking_non_zero_interruptible(struct semaphore *sem,
11136 + struct task_struct *tsk)
11139 + unsigned long flags;
11141 + spin_lock_irqsave(&semaphore_wake_lock, flags);
11143 + if (atomic_read(&sem->waking) > 0) {
11144 + atomic_dec(&sem->waking);
11146 + } else if (signal_pending(tsk)) {
11147 + atomic_inc(&sem->count);
11150 + spin_unlock_irqrestore(&semaphore_wake_lock, flags);
11155 + * waking_non_zero_trylock:
11156 + * 1 failed to lock
11159 +static inline int waking_non_zero_trylock(struct semaphore *sem)
11162 + unsigned long flags;
11164 + spin_lock_irqsave(&semaphore_wake_lock, flags);
11166 + if (atomic_read(&sem->waking) > 0) {
11167 + atomic_dec(&sem->waking);
11170 + atomic_inc(&sem->count);
11171 + spin_unlock_irqrestore(&semaphore_wake_lock, flags);
11175 +#endif /* _ASM_UBICOM32_SEMAPHORE_HELPER_H */
11177 +++ b/arch/ubicom32/include/asm/sembuf.h
11180 + * arch/ubicom32/include/asm/sembuf.h
11181 + * The semid64_ds structure for Ubicom32 architecture.
11183 + * (C) Copyright 2009, Ubicom, Inc.
11185 + * This file is part of the Ubicom32 Linux Kernel Port.
11187 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
11188 + * it and/or modify it under the terms of the GNU General Public License
11189 + * as published by the Free Software Foundation, either version 2 of the
11190 + * License, or (at your option) any later version.
11192 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
11193 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11194 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
11195 + * the GNU General Public License for more details.
11197 + * You should have received a copy of the GNU General Public License
11198 + * along with the Ubicom32 Linux Kernel Port. If not,
11199 + * see <http://www.gnu.org/licenses/>.
11201 + * Ubicom32 implementation derived from (with many thanks):
11206 +#ifndef _ASM_UBICOM32_SEMBUF_H
11207 +#define _ASM_UBICOM32_SEMBUF_H
11210 + * The semid64_ds structure for ubicom32 architecture.
11211 + * Note extra padding because this structure is passed back and forth
11212 + * between kernel and user space.
11214 + * Pad space is left for:
11215 + * - 64-bit time_t to solve y2038 problem
11216 + * - 2 miscellaneous 32-bit values
11219 +struct semid64_ds {
11220 + struct ipc64_perm sem_perm; /* permissions .. see ipc.h */
11221 + __kernel_time_t sem_otime; /* last semop time */
11222 + unsigned long __unused1;
11223 + __kernel_time_t sem_ctime; /* last change time */
11224 + unsigned long __unused2;
11225 + unsigned long sem_nsems; /* no. of semaphores in array */
11226 + unsigned long __unused3;
11227 + unsigned long __unused4;
11230 +#endif /* _ASM_UBICOM32_SEMBUF_H */
11232 +++ b/arch/ubicom32/include/asm/setup.h
11235 + * arch/ubicom32/include/asm/setup.h
11236 + * Kernel command line length definition.
11238 + * (C) Copyright 2009, Ubicom, Inc.
11239 + * Copyright (C) 2004, Microtronix Datacom Ltd., All rights reserved.
11241 + * This file is part of the Ubicom32 Linux Kernel Port.
11243 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
11244 + * it and/or modify it under the terms of the GNU General Public License
11245 + * as published by the Free Software Foundation, either version 2 of the
11246 + * License, or (at your option) any later version.
11248 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
11249 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11250 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
11251 + * the GNU General Public License for more details.
11253 + * You should have received a copy of the GNU General Public License
11254 + * along with the Ubicom32 Linux Kernel Port. If not,
11255 + * see <http://www.gnu.org/licenses/>.
11257 + * Ubicom32 implementation derived from (with many thanks):
11263 +#ifndef _ASM_UBICOM32_SETUP_H
11264 +#define _ASM_UBICOM32_SETUP_H
11266 +#define COMMAND_LINE_SIZE 512
11268 +#endif /* _ASM_UBICOM32_SETUP_H */
11270 +++ b/arch/ubicom32/include/asm/shmbuf.h
11273 + * arch/ubicom32/include/asm/shmbuf.h
11274 + * The shmid64_ds structure for the Ubicom32 architecture.
11276 + * (C) Copyright 2009, Ubicom, Inc.
11278 + * This file is part of the Ubicom32 Linux Kernel Port.
11280 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
11281 + * it and/or modify it under the terms of the GNU General Public License
11282 + * as published by the Free Software Foundation, either version 2 of the
11283 + * License, or (at your option) any later version.
11285 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
11286 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11287 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
11288 + * the GNU General Public License for more details.
11290 + * You should have received a copy of the GNU General Public License
11291 + * along with the Ubicom32 Linux Kernel Port. If not,
11292 + * see <http://www.gnu.org/licenses/>.
11294 + * Ubicom32 implementation derived from (with many thanks):
11299 +#ifndef _ASM_UBICOM32_SHMBUF_H
11300 +#define _ASM_UBICOM32_SHMBUF_H
11303 + * The shmid64_ds structure for m68k architecture.
11304 + * Note extra padding because this structure is passed back and forth
11305 + * between kernel and user space.
11307 + * Pad space is left for:
11308 + * - 64-bit time_t to solve y2038 problem
11309 + * - 2 miscellaneous 32-bit values
11312 +struct shmid64_ds {
11313 + struct ipc64_perm shm_perm; /* operation perms */
11314 + size_t shm_segsz; /* size of segment (bytes) */
11315 + __kernel_time_t shm_atime; /* last attach time */
11316 + unsigned long __unused1;
11317 + __kernel_time_t shm_dtime; /* last detach time */
11318 + unsigned long __unused2;
11319 + __kernel_time_t shm_ctime; /* last change time */
11320 + unsigned long __unused3;
11321 + __kernel_pid_t shm_cpid; /* pid of creator */
11322 + __kernel_pid_t shm_lpid; /* pid of last operator */
11323 + unsigned long shm_nattch; /* no. of current attaches */
11324 + unsigned long __unused4;
11325 + unsigned long __unused5;
11328 +struct shminfo64 {
11329 + unsigned long shmmax;
11330 + unsigned long shmmin;
11331 + unsigned long shmmni;
11332 + unsigned long shmseg;
11333 + unsigned long shmall;
11334 + unsigned long __unused1;
11335 + unsigned long __unused2;
11336 + unsigned long __unused3;
11337 + unsigned long __unused4;
11340 +#endif /* _ASM_UBICOM32_SHMBUF_H */
11342 +++ b/arch/ubicom32/include/asm/shmparam.h
11345 + * arch/ubicom32/include/asm/shmparam.h
11346 + * Shared memory definitions for Ubicom32 architecture.
11348 + * (C) Copyright 2009, Ubicom, Inc.
11349 + * Copyright (C) 2004 Microtronix Datacom Ltd
11351 + * This file is part of the Ubicom32 Linux Kernel Port.
11353 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
11354 + * it and/or modify it under the terms of the GNU General Public License
11355 + * as published by the Free Software Foundation, either version 2 of the
11356 + * License, or (at your option) any later version.
11358 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
11359 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11360 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
11361 + * the GNU General Public License for more details.
11363 + * You should have received a copy of the GNU General Public License
11364 + * along with the Ubicom32 Linux Kernel Port. If not,
11365 + * see <http://www.gnu.org/licenses/>.
11367 + * Ubicom32 implementation derived from (with many thanks):
11371 + * Alpha, ix86, M68K, Sparc, ...et al
11373 +#ifndef _ASM_UBICOM32_SHMPARAM_H
11374 +#define _ASM_UBICOM32_SHMPARAM_H
11376 +#define SHMLBA PAGE_SIZE /* attach addr a multiple of this */
11378 +#endif /* _ASM_UBICOM32_SHMPARAM_H */
11380 +++ b/arch/ubicom32/include/asm/sigcontext.h
11383 + * arch/ubicom32/include/asm/sigcontext.h
11384 + * Definition of sigcontext struct for Ubicom32 architecture.
11386 + * (C) Copyright 2009, Ubicom, Inc.
11388 + * This file is part of the Ubicom32 Linux Kernel Port.
11390 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
11391 + * it and/or modify it under the terms of the GNU General Public License
11392 + * as published by the Free Software Foundation, either version 2 of the
11393 + * License, or (at your option) any later version.
11395 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
11396 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11397 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
11398 + * the GNU General Public License for more details.
11400 + * You should have received a copy of the GNU General Public License
11401 + * along with the Ubicom32 Linux Kernel Port. If not,
11402 + * see <http://www.gnu.org/licenses/>.
11404 + * Ubicom32 implementation derived from (with many thanks):
11409 +#ifndef _ASM_UBICOM32_SIGCONTEXT_H
11410 +#define _ASM_UBICOM32_SIGCONTEXT_H
11412 +#include <asm/ptrace.h>
11414 +struct sigcontext {
11415 + struct pt_regs sc_regs;
11418 +#endif /* _ASM_UBICOM32_SIGCONTEXT_H */
11420 +++ b/arch/ubicom32/include/asm/siginfo.h
11423 + * arch/ubicom32/include/asm/siginfo.h
11424 + * Generic siginfo.h definitions for Ubicom32 architecture.
11426 + * (C) Copyright 2009, Ubicom, Inc.
11428 + * This file is part of the Ubicom32 Linux Kernel Port.
11430 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
11431 + * it and/or modify it under the terms of the GNU General Public License
11432 + * as published by the Free Software Foundation, either version 2 of the
11433 + * License, or (at your option) any later version.
11435 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
11436 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11437 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
11438 + * the GNU General Public License for more details.
11440 + * You should have received a copy of the GNU General Public License
11441 + * along with the Ubicom32 Linux Kernel Port. If not,
11442 + * see <http://www.gnu.org/licenses/>.
11444 + * Ubicom32 implementation derived from (with many thanks):
11449 +#ifndef _ASM_UBICOM32_SIGINFO_H
11450 +#define _ASM_UBICOM32_SIGINFO_H
11452 +#include <asm-generic/siginfo.h>
11454 +#endif /* _ASM_UBICOM32_SIGINFO_H */
11456 +++ b/arch/ubicom32/include/asm/signal.h
11459 + * arch/ubicom32/include/asm/signal.h
11460 + * Signal related definitions for Ubicom32 architecture.
11462 + * (C) Copyright 2009, Ubicom, Inc.
11464 + * This file is part of the Ubicom32 Linux Kernel Port.
11466 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
11467 + * it and/or modify it under the terms of the GNU General Public License
11468 + * as published by the Free Software Foundation, either version 2 of the
11469 + * License, or (at your option) any later version.
11471 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
11472 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11473 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
11474 + * the GNU General Public License for more details.
11476 + * You should have received a copy of the GNU General Public License
11477 + * along with the Ubicom32 Linux Kernel Port. If not,
11478 + * see <http://www.gnu.org/licenses/>.
11480 + * Ubicom32 implementation derived from (with many thanks):
11485 +#ifndef _ASM_UBICOM32_SIGNAL_H
11486 +#define _ASM_UBICOM32_SIGNAL_H
11488 +#include <linux/types.h>
11490 +/* Avoid too many header ordering problems. */
11494 +/* Most things should be clean enough to redefine this at will, if care
11495 + is taken to make libc match. */
11498 +#define _NSIG_BPW 32
11499 +#define _NSIG_WORDS (_NSIG / _NSIG_BPW)
11501 +typedef unsigned long old_sigset_t; /* at least 32 bits */
11504 + unsigned long sig[_NSIG_WORDS];
11507 +#endif /* __KERNEL__ */
11519 +#define SIGUSR1 10
11520 +#define SIGSEGV 11
11521 +#define SIGUSR2 12
11522 +#define SIGPIPE 13
11523 +#define SIGALRM 14
11524 +#define SIGTERM 15
11525 +#define SIGSTKFLT 16
11526 +#define SIGCHLD 17
11527 +#define SIGCONT 18
11528 +#define SIGSTOP 19
11529 +#define SIGTSTP 20
11530 +#define SIGTTIN 21
11531 +#define SIGTTOU 22
11533 +#define SIGXCPU 24
11534 +#define SIGXFSZ 25
11535 +#define SIGVTALRM 26
11536 +#define SIGPROF 27
11537 +#define SIGWINCH 28
11539 +#define SIGPOLL SIGIO
11541 +#define SIGLOST 29
11545 +#define SIGUNUSED 31
11547 +/* These should not be considered constants from userland. */
11548 +#define SIGRTMIN 32
11549 +#define SIGRTMAX _NSIG
11552 + * SA_FLAGS values:
11554 + * SA_ONSTACK indicates that a registered stack_t will be used.
11555 + * SA_RESTART flag to get restarting signals (which were the default long ago)
11556 + * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
11557 + * SA_RESETHAND clears the handler when the signal is delivered.
11558 + * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
11559 + * SA_NODEFER prevents the current signal from being masked in the handler.
11561 + * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
11562 + * Unix names RESETHAND and NODEFER respectively.
11564 +#define SA_NOCLDSTOP 0x00000001
11565 +#define SA_NOCLDWAIT 0x00000002
11566 +#define SA_SIGINFO 0x00000004
11567 +#define SA_ONSTACK 0x08000000
11568 +#define SA_RESTART 0x10000000
11569 +#define SA_NODEFER 0x40000000
11570 +#define SA_RESETHAND 0x80000000
11572 +#define SA_NOMASK SA_NODEFER
11573 +#define SA_ONESHOT SA_RESETHAND
11576 + * sigaltstack controls
11578 +#define SS_ONSTACK 1
11579 +#define SS_DISABLE 2
11581 +#define MINSIGSTKSZ 2048
11582 +#define SIGSTKSZ 8192
11584 +#include <asm-generic/signal.h>
11587 +struct old_sigaction {
11588 + __sighandler_t sa_handler;
11589 + old_sigset_t sa_mask;
11590 + unsigned long sa_flags;
11591 + void (*sa_restorer)(void);
11594 +struct sigaction {
11595 + __sighandler_t sa_handler;
11596 + unsigned long sa_flags;
11597 + void (*sa_restorer)(void);
11598 + sigset_t sa_mask; /* mask last for extensibility */
11601 +struct k_sigaction {
11602 + struct sigaction sa;
11605 +/* Here we must cater to libcs that poke about in kernel headers. */
11607 +struct sigaction {
11609 + __sighandler_t _sa_handler;
11610 + void (*_sa_sigaction)(int, struct siginfo *, void *);
11612 + sigset_t sa_mask;
11613 + unsigned long sa_flags;
11614 + void (*sa_restorer)(void);
11617 +#define sa_handler _u._sa_handler
11618 +#define sa_sigaction _u._sa_sigaction
11620 +#endif /* __KERNEL__ */
11622 +typedef struct sigaltstack {
11630 +#include <asm/sigcontext.h>
11631 +#undef __HAVE_ARCH_SIG_BITOPS
11633 +#define ptrace_signal_deliver(regs, cookie) do { } while (0)
11635 +#endif /* __KERNEL__ */
11637 +#endif /* _ASM_UBICOM32_SIGNAL_H */
11639 +++ b/arch/ubicom32/include/asm/smp.h
11642 + * arch/ubicom32/include/asm/smp.h
11643 + * SMP definitions for Ubicom32 architecture.
11645 + * (C) Copyright 2009, Ubicom, Inc.
11647 + * This file is part of the Ubicom32 Linux Kernel Port.
11649 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
11650 + * it and/or modify it under the terms of the GNU General Public License
11651 + * as published by the Free Software Foundation, either version 2 of the
11652 + * License, or (at your option) any later version.
11654 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
11655 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11656 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
11657 + * the GNU General Public License for more details.
11659 + * You should have received a copy of the GNU General Public License
11660 + * along with the Ubicom32 Linux Kernel Port. If not,
11661 + * see <http://www.gnu.org/licenses/>.
11663 + * Ubicom32 implementation derived from (with many thanks):
11668 +#ifndef _ASM_UBICOM32_SMP_H
11669 +#define _ASM_UBICOM32_SMP_H
11671 +#ifndef CONFIG_SMP
11672 +#error you should not include smp.h if smp is off
11676 +#include <linux/bitops.h>
11677 +#include <linux/threads.h>
11678 +#include <linux/cpumask.h>
11679 +#include <asm/ip5000.h>
11681 +typedef unsigned long address_t;
11682 +extern unsigned int smp_ipi_irq;
11685 + * This magic constant controls our willingness to transfer
11686 + * a process across CPUs.
11688 + * Such a transfer incurs cache and tlb
11689 + * misses. The current value is inherited from i386. Still needs
11690 + * to be tuned for parisc.
11692 +#define PROC_CHANGE_PENALTY 15 /* Schedule penalty */
11693 +#define NO_PROC_ID 0xFF /* No processor magic marker */
11694 +#define ANY_PROC_ID 0xFF /* Any processor magic marker */
11697 +#define raw_smp_processor_id() (current_thread_info()->cpu)
11698 +#endif /* CONFIG_SMP */
11700 +static inline int __cpu_disable (void)
11705 +static inline void __cpu_die (unsigned int cpu)
11711 +extern int __cpu_up(unsigned int cpu);
11712 +extern void smp_send_timer_all(void);
11713 +extern void smp_timer_broadcast(const struct cpumask *mask);
11714 +extern void smp_set_affinity(unsigned int irq, const struct cpumask *dest);
11715 +extern void arch_send_call_function_single_ipi(int cpu);
11716 +#define arch_send_call_function_ipi_mask arch_send_call_function_ipi_mask
11717 +extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
11720 + * TODO: Once these are fully tested, we should turn them into
11721 + * inline macros for performance.
11723 +extern unsigned long smp_get_affinity(unsigned int irq, int *all);
11724 +extern void smp_reset_ipi(unsigned long mask);
11726 +#endif /* !ASSEMBLY */
11727 +#endif /* _ASM_UBICOM32_SMP_H */
11729 +++ b/arch/ubicom32/include/asm/socket.h
11732 + * arch/ubicom32/include/asm/socket.h
11733 + * Socket options definitions for Ubicom32 architecture.
11735 + * (C) Copyright 2009, Ubicom, Inc.
11737 + * This file is part of the Ubicom32 Linux Kernel Port.
11739 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
11740 + * it and/or modify it under the terms of the GNU General Public License
11741 + * as published by the Free Software Foundation, either version 2 of the
11742 + * License, or (at your option) any later version.
11744 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
11745 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11746 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
11747 + * the GNU General Public License for more details.
11749 + * You should have received a copy of the GNU General Public License
11750 + * along with the Ubicom32 Linux Kernel Port. If not,
11751 + * see <http://www.gnu.org/licenses/>.
11753 + * Ubicom32 implementation derived from (with many thanks):
11758 +#ifndef _ASM_UBICOM32_SOCKET_H
11759 +#define _ASM_UBICOM32_SOCKET_H
11761 +#include <asm/sockios.h>
11763 +/* For setsockopt(2) */
11764 +#define SOL_SOCKET 1
11766 +#define SO_DEBUG 1
11767 +#define SO_REUSEADDR 2
11769 +#define SO_ERROR 4
11770 +#define SO_DONTROUTE 5
11771 +#define SO_BROADCAST 6
11772 +#define SO_SNDBUF 7
11773 +#define SO_RCVBUF 8
11774 +#define SO_SNDBUFFORCE 32
11775 +#define SO_RCVBUFFORCE 33
11776 +#define SO_KEEPALIVE 9
11777 +#define SO_OOBINLINE 10
11778 +#define SO_NO_CHECK 11
11779 +#define SO_PRIORITY 12
11780 +#define SO_LINGER 13
11781 +#define SO_BSDCOMPAT 14
11782 +/* To add :#define SO_REUSEPORT 15 */
11783 +#define SO_PASSCRED 16
11784 +#define SO_PEERCRED 17
11785 +#define SO_RCVLOWAT 18
11786 +#define SO_SNDLOWAT 19
11787 +#define SO_RCVTIMEO 20
11788 +#define SO_SNDTIMEO 21
11790 +/* Security levels - as per NRL IPv6 - don't actually do anything */
11791 +#define SO_SECURITY_AUTHENTICATION 22
11792 +#define SO_SECURITY_ENCRYPTION_TRANSPORT 23
11793 +#define SO_SECURITY_ENCRYPTION_NETWORK 24
11795 +#define SO_BINDTODEVICE 25
11797 +/* Socket filtering */
11798 +#define SO_ATTACH_FILTER 26
11799 +#define SO_DETACH_FILTER 27
11801 +#define SO_PEERNAME 28
11802 +#define SO_TIMESTAMP 29
11803 +#define SCM_TIMESTAMP SO_TIMESTAMP
11805 +#define SO_ACCEPTCONN 30
11807 +#define SO_PEERSEC 31
11808 +#define SO_PASSSEC 34
11809 +#define SO_TIMESTAMPNS 35
11810 +#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
11812 +#define SO_MARK 36
11814 +#define SO_TIMESTAMPING 37
11815 +#define SCM_TIMESTAMPING SO_TIMESTAMPING
11817 +#endif /* _ASM_UBICOM32_SOCKET_H */
11819 +++ b/arch/ubicom32/include/asm/sockios.h
11822 + * arch/ubicom32/include/asm/sockios.h
11823 + * Socket-level ioctl definitions for Ubicom32 architecture.
11825 + * (C) Copyright 2009, Ubicom, Inc.
11827 + * This file is part of the Ubicom32 Linux Kernel Port.
11829 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
11830 + * it and/or modify it under the terms of the GNU General Public License
11831 + * as published by the Free Software Foundation, either version 2 of the
11832 + * License, or (at your option) any later version.
11834 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
11835 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11836 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
11837 + * the GNU General Public License for more details.
11839 + * You should have received a copy of the GNU General Public License
11840 + * along with the Ubicom32 Linux Kernel Port. If not,
11841 + * see <http://www.gnu.org/licenses/>.
11843 + * Ubicom32 implementation derived from (with many thanks):
11848 +#ifndef _ASM_UBICOM32_SOCKIOS_H
11849 +#define _ASM_UBICOM32_SOCKIOS_H
11851 +/* Socket-level I/O control calls. */
11852 +#define FIOSETOWN 0x8901
11853 +#define SIOCSPGRP 0x8902
11854 +#define FIOGETOWN 0x8903
11855 +#define SIOCGPGRP 0x8904
11856 +#define SIOCATMARK 0x8905
11857 +#define SIOCGSTAMP 0x8906 /* Get stamp (timeval) */
11858 +#define SIOCGSTAMPNS 0x8907 /* Get stamp (timespec) */
11860 +#endif /* _ASM_UBICOM32_SOCKIOS_H */
11862 +++ b/arch/ubicom32/include/asm/spinlock.h
11865 + * arch/ubicom32/include/asm/spinlock.h
11866 + * Spinlock related definitions for Ubicom32 architecture.
11868 + * (C) Copyright 2009, Ubicom, Inc.
11870 + * This file is part of the Ubicom32 Linux Kernel Port.
11872 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
11873 + * it and/or modify it under the terms of the GNU General Public License
11874 + * as published by the Free Software Foundation, either version 2 of the
11875 + * License, or (at your option) any later version.
11877 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
11878 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11879 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
11880 + * the GNU General Public License for more details.
11882 + * You should have received a copy of the GNU General Public License
11883 + * along with the Ubicom32 Linux Kernel Port. If not,
11884 + * see <http://www.gnu.org/licenses/>.
11886 + * Ubicom32 implementation derived from (with many thanks):
11891 +#ifndef _ASM_UBICOM32_SPINLOCK_H
11892 +#define _ASM_UBICOM32_SPINLOCK_H
11894 +#include <asm/system.h>
11895 +#include <asm/processor.h>
11896 +#include <asm/spinlock_types.h>
11899 + * __raw_spin_lock()
11902 +static inline void __raw_spin_lock(raw_spinlock_t *x)
11905 + "1: bset %0, %0, #0 \n\t"
11906 + " jmpne.f 1b \n\t"
11907 + : "+U4" (x->lock)
11914 + * __raw_spin_unlock()
11915 + * Unlock the lock.
11917 +static inline void __raw_spin_unlock(raw_spinlock_t *x)
11920 + " bclr %0, %0, #0 \n\t"
11921 + : "+U4" (x->lock)
11928 + * __raw_spin_is_locked()
11929 + * Test if the lock is locked.
11931 +static inline int __raw_spin_is_locked(raw_spinlock_t *x)
11937 + * __raw_spin_unlock_wait()
11938 + * Wait for the lock to be unlocked.
11940 + * Note: the caller has not guarantee that the lock will not
11941 + * be acquired before they get to it.
11943 +static inline void __raw_spin_unlock_wait(raw_spinlock_t *x)
11947 + } while (__raw_spin_is_locked(x));
11951 + * __raw_spin_trylock()
11952 + * Try the lock, return 0 on failure, 1 on success.
11954 +static inline int __raw_spin_trylock(raw_spinlock_t *x)
11959 + " bset %1, %1, #0 \n\t"
11960 + " jmpne.f 1f \n\t"
11961 + " move.4 %0, #1 \n\t"
11963 + : "+r" (ret), "+U4" (x->lock)
11972 + * __raw_spin_lock_flags()
11973 + * Spin waiting for the lock (enabling IRQ(s))
11975 +static inline void __raw_spin_lock_flags(raw_spinlock_t *x, unsigned long flags)
11978 + while (!__raw_spin_trylock(x)) {
11980 + * If the flags from the IRQ are set, interrupts are disabled and we
11981 + * need to re-enable them.
11986 + raw_local_irq_enable();
11988 + raw_local_irq_disable();
11995 + * Read-write spinlocks, allowing multiple readers but only one writer.
11996 + * Linux rwlocks are unfair to writers; they can be starved for an indefinite
11997 + * time by readers. With care, they can also be taken in interrupt context.
11999 + * In Ubicom32 architecture implementation, we have a spinlock and a counter.
12000 + * Readers use the lock to serialise their access to the counter (which
12001 + * records how many readers currently hold the lock).
12002 + * Writers hold the spinlock, preventing any readers or other writers from
12003 + * grabbing the rwlock.
12007 + * __raw_read_lock()
12008 + * Increment the counter in the rwlock.
12010 + * Note that we have to ensure interrupts are disabled in case we're
12011 + * interrupted by some other code that wants to grab the same read lock
12013 +static inline void __raw_read_lock(raw_rwlock_t *rw)
12015 + unsigned long flags;
12016 + raw_local_irq_save(flags);
12017 + __raw_spin_lock_flags(&rw->lock, flags);
12019 + __raw_spin_unlock(&rw->lock);
12020 + raw_local_irq_restore(flags);
12024 + * __raw_read_unlock()
12025 + * Decrement the counter.
12027 + * Note that we have to ensure interrupts are disabled in case we're
12028 + * interrupted by some other code that wants to grab the same read lock
12030 +static inline void __raw_read_unlock(raw_rwlock_t *rw)
12032 + unsigned long flags;
12033 + raw_local_irq_save(flags);
12034 + __raw_spin_lock_flags(&rw->lock, flags);
12036 + __raw_spin_unlock(&rw->lock);
12037 + raw_local_irq_restore(flags);
12041 + * __raw_read_trylock()
12042 + * Increment the counter if we can.
12044 + * Note that we have to ensure interrupts are disabled in case we're
12045 + * interrupted by some other code that wants to grab the same read lock
12047 +static inline int __raw_read_trylock(raw_rwlock_t *rw)
12049 + unsigned long flags;
12051 + raw_local_irq_save(flags);
12052 + if (__raw_spin_trylock(&rw->lock)) {
12054 + __raw_spin_unlock(&rw->lock);
12055 + raw_local_irq_restore(flags);
12059 + raw_local_irq_restore(flags);
12062 + * If write-locked, we fail to acquire the lock
12064 + if (rw->counter < 0) {
12069 + * Wait until we have a realistic chance at the lock
12071 + while (__raw_spin_is_locked(&rw->lock) && rw->counter >= 0) {
12079 + * __raw_write_lock()
12081 + * Note that we have to ensure interrupts are disabled in case we're
12082 + * interrupted by some other code that wants to read_trylock() this lock
12084 +static inline void __raw_write_lock(raw_rwlock_t *rw)
12086 + unsigned long flags;
12088 + raw_local_irq_save(flags);
12089 + __raw_spin_lock_flags(&rw->lock, flags);
12091 + if (rw->counter != 0) {
12092 + __raw_spin_unlock(&rw->lock);
12093 + raw_local_irq_restore(flags);
12095 + while (rw->counter != 0)
12101 + rw->counter = -1; /* mark as write-locked */
12103 + raw_local_irq_restore(flags);
12106 +static inline void __raw_write_unlock(raw_rwlock_t *rw)
12109 + __raw_spin_unlock(&rw->lock);
12112 +/* Note that we have to ensure interrupts are disabled in case we're
12113 + * interrupted by some other code that wants to read_trylock() this lock */
12114 +static inline int __raw_write_trylock(raw_rwlock_t *rw)
12116 + unsigned long flags;
12119 + raw_local_irq_save(flags);
12120 + if (__raw_spin_trylock(&rw->lock)) {
12121 + if (rw->counter == 0) {
12122 + rw->counter = -1;
12125 + /* Read-locked. Oh well. */
12126 + __raw_spin_unlock(&rw->lock);
12129 + raw_local_irq_restore(flags);
12135 + * read_can_lock - would read_trylock() succeed?
12136 + * @lock: the rwlock in question.
12138 +static inline int __raw_read_can_lock(raw_rwlock_t *rw)
12140 + return rw->counter >= 0;
12144 + * write_can_lock - would write_trylock() succeed?
12145 + * @lock: the rwlock in question.
12147 +static inline int __raw_write_can_lock(raw_rwlock_t *rw)
12149 + return !rw->counter;
12152 +#define __raw_read_lock_flags(lock, flags) __raw_read_lock(lock)
12153 +#define __raw_write_lock_flags(lock, flags) __raw_write_lock(lock)
12155 +#define _raw_spin_relax(lock) cpu_relax()
12156 +#define _raw_read_relax(lock) cpu_relax()
12157 +#define _raw_write_relax(lock) cpu_relax()
12159 +#endif /* _ASM_UBICOM32_SPINLOCK_H */
12161 +++ b/arch/ubicom32/include/asm/spinlock_types.h
12164 + * arch/ubicom32/include/asm/spinlock_types.h
12165 + * Spinlock related structure definitions for Ubicom32 architecture.
12167 + * (C) Copyright 2009, Ubicom, Inc.
12169 + * This file is part of the Ubicom32 Linux Kernel Port.
12171 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
12172 + * it and/or modify it under the terms of the GNU General Public License
12173 + * as published by the Free Software Foundation, either version 2 of the
12174 + * License, or (at your option) any later version.
12176 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
12177 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12178 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
12179 + * the GNU General Public License for more details.
12181 + * You should have received a copy of the GNU General Public License
12182 + * along with the Ubicom32 Linux Kernel Port. If not,
12183 + * see <http://www.gnu.org/licenses/>.
12185 + * Ubicom32 implementation derived from (with many thanks):
12190 +#ifndef _ASM_UBICOM32_SPINLOCK_TYPES_H
12191 +#define _ASM_UBICOM32_SPINLOCK_TYPES_H
12194 + volatile unsigned int lock;
12198 + raw_spinlock_t lock;
12199 + volatile int counter;
12202 +#define __RAW_SPIN_LOCK_UNLOCKED { 0 }
12203 +#define __RAW_RW_LOCK_UNLOCKED { __RAW_SPIN_LOCK_UNLOCKED, 0 }
12205 +#endif /* _ASM_UBICOM32_SPINLOCK_TYPES_H */
12207 +++ b/arch/ubicom32/include/asm/stacktrace.h
12210 + * arch/ubicom32/include/asm/stacktrace.h
12211 + * Stacktrace functions for the Ubicom32 architecture.
12213 + * (C) Copyright 2009, Ubicom, Inc.
12215 + * This file is part of the Ubicom32 Linux Kernel Port.
12217 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
12218 + * it and/or modify it under the terms of the GNU General Public License
12219 + * as published by the Free Software Foundation, either version 2 of the
12220 + * License, or (at your option) any later version.
12222 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
12223 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12224 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
12225 + * the GNU General Public License for more details.
12227 + * You should have received a copy of the GNU General Public License
12228 + * along with the Ubicom32 Linux Kernel Port. If not,
12229 + * see <http://www.gnu.org/licenses/>.
12231 + * Ubicom32 implementation derived from (with many thanks):
12236 +#ifndef _ASM_UBICOM32_STACKTRACE_H
12237 +#define _ASM_UBICOM32_STACKTRACE_H
12239 +#define between(a, b, c) (( \
12240 + ((unsigned long) a) >= ((unsigned long) b)) && \
12241 + (((unsigned long)a) <= ((unsigned long)c)))
12244 + * These symbols are filled in by the linker.
12246 +extern unsigned long _stext;
12247 +extern unsigned long _etext;
12249 +/* OCM text goes from __ocm_text_run_begin to __data_begin */
12250 +extern unsigned long __ocm_text_run_begin;
12251 +extern unsigned long __data_begin;
12253 +/* Account for OCM case - see stacktrace.c maybe combine(also trap.c) */
12255 + * ubicom32_is_kernel()
12257 + * Check to see if the given address belongs to the kernel.
12258 + * NOMMU does not permit any other means.
12260 +static inline int ubicom32_is_kernel(unsigned long addr)
12262 + int is_kernel = between(addr, &_stext, &_etext) || \
12263 + between(addr, &__ocm_text_run_begin, &__data_begin);
12265 +#ifdef CONFIG_MODULES
12267 + is_kernel = is_module_address(addr);
12269 + return is_kernel;
12272 +extern unsigned long stacktrace_iterate(
12273 + unsigned long **trace,
12274 + unsigned long stext, unsigned long etext,
12275 + unsigned long ocm_stext, unsigned long ocm_etext,
12276 + unsigned long sstack, unsigned long estack);
12277 +#ifdef CONFIG_STACKTRACE
12278 +void stacktrace_save_entries(struct task_struct *tsk, struct stack_trace *trace, unsigned long sp);
12280 +#endif /* _ASM_UBICOM32_STACKTRACE_H */
12282 +++ b/arch/ubicom32/include/asm/statfs.h
12285 + * arch/ubicom32/include/asm/statfs.h
12286 + * Generic statfs.h definitions
12288 + * (C) Copyright 2009, Ubicom, Inc.
12290 + * This file is part of the Ubicom32 Linux Kernel Port.
12292 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
12293 + * it and/or modify it under the terms of the GNU General Public License
12294 + * as published by the Free Software Foundation, either version 2 of the
12295 + * License, or (at your option) any later version.
12297 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
12298 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12299 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
12300 + * the GNU General Public License for more details.
12302 + * You should have received a copy of the GNU General Public License
12303 + * along with the Ubicom32 Linux Kernel Port. If not,
12304 + * see <http://www.gnu.org/licenses/>.
12306 + * Ubicom32 implementation derived from (with many thanks):
12311 +#ifndef _ASM_UBICOM32_STATFS_H
12312 +#define _ASM_UBICOM32_STATFS_H
12314 +#include <asm-generic/statfs.h>
12316 +#endif /* _ASM_UBICOM32_STATFS_H */
12318 +++ b/arch/ubicom32/include/asm/stat.h
12321 + * arch/ubicom32/include/asm/stat.h
12322 + * File status definitions for Ubicom32 architecture.
12324 + * (C) Copyright 2009, Ubicom, Inc.
12326 + * This file is part of the Ubicom32 Linux Kernel Port.
12328 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
12329 + * it and/or modify it under the terms of the GNU General Public License
12330 + * as published by the Free Software Foundation, either version 2 of the
12331 + * License, or (at your option) any later version.
12333 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
12334 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12335 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
12336 + * the GNU General Public License for more details.
12338 + * You should have received a copy of the GNU General Public License
12339 + * along with the Ubicom32 Linux Kernel Port. If not,
12340 + * see <http://www.gnu.org/licenses/>.
12342 + * Ubicom32 implementation derived from (with many thanks):
12347 +#ifndef _ASM_UBICOM32_STAT_H
12348 +#define _ASM_UBICOM32_STAT_H
12350 +struct __old_kernel_stat {
12351 + unsigned short st_dev;
12352 + unsigned short st_ino;
12353 + unsigned short st_mode;
12354 + unsigned short st_nlink;
12355 + unsigned short st_uid;
12356 + unsigned short st_gid;
12357 + unsigned short st_rdev;
12358 + unsigned long st_size;
12359 + unsigned long st_atime;
12360 + unsigned long st_mtime;
12361 + unsigned long st_ctime;
12365 + unsigned short st_dev;
12366 + unsigned short __pad1;
12367 + unsigned long st_ino;
12368 + unsigned short st_mode;
12369 + unsigned short st_nlink;
12370 + unsigned short st_uid;
12371 + unsigned short st_gid;
12372 + unsigned short st_rdev;
12373 + unsigned short __pad2;
12374 + unsigned long st_size;
12375 + unsigned long st_blksize;
12376 + unsigned long st_blocks;
12377 + unsigned long st_atime;
12378 + unsigned long __unused1;
12379 + unsigned long st_mtime;
12380 + unsigned long __unused2;
12381 + unsigned long st_ctime;
12382 + unsigned long __unused3;
12383 + unsigned long __unused4;
12384 + unsigned long __unused5;
12387 +/* This matches struct stat64 in glibc2.1, hence the absolutely
12388 + * insane amounts of padding around dev_t's.
12391 + unsigned long long st_dev;
12392 + unsigned char __pad1[2];
12394 +#define STAT64_HAS_BROKEN_ST_INO 1
12395 + unsigned long __st_ino;
12397 + unsigned int st_mode;
12398 + unsigned int st_nlink;
12400 + unsigned long st_uid;
12401 + unsigned long st_gid;
12403 + unsigned long long st_rdev;
12404 + unsigned char __pad3[2];
12406 + long long st_size;
12407 + unsigned long st_blksize;
12409 + unsigned long long st_blocks; /* Number 512-byte blocks allocated. */
12411 + unsigned long st_atime;
12412 + unsigned long st_atime_nsec;
12414 + unsigned long st_mtime;
12415 + unsigned long st_mtime_nsec;
12417 + unsigned long st_ctime;
12418 + unsigned long st_ctime_nsec;
12420 + unsigned long long st_ino;
12423 +#endif /* _ASM_UBICOM32_STAT_H */
12425 +++ b/arch/ubicom32/include/asm/string.h
12428 + * arch/ubicom32/include/asm/string.h
12429 + * String operation definitions for Ubicom32 architecture.
12431 + * (C) Copyright 2009, Ubicom, Inc.
12433 + * This file is part of the Ubicom32 Linux Kernel Port.
12435 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
12436 + * it and/or modify it under the terms of the GNU General Public License
12437 + * as published by the Free Software Foundation, either version 2 of the
12438 + * License, or (at your option) any later version.
12440 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
12441 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12442 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
12443 + * the GNU General Public License for more details.
12445 + * You should have received a copy of the GNU General Public License
12446 + * along with the Ubicom32 Linux Kernel Port. If not,
12447 + * see <http://www.gnu.org/licenses/>.
12449 + * Ubicom32 implementation derived from (with many thanks):
12454 +#ifndef _ASM_UBICOM32_STRING_H
12455 +#define _ASM_UBICOM32_STRING_H
12457 +#define __HAVE_ARCH_MEMSET
12458 +extern void *memset(void *b, int c, size_t len);
12460 +#define __HAVE_ARCH_MEMCPY
12461 +extern void *memcpy(void *to, const void *from, size_t len);
12463 +#define __HAVE_ARCH_MEMMOVE
12464 +extern void * memmove(void *to, const void *from, size_t len);
12466 +#endif /* _ASM_UBICOM32_STRING_H */
12468 +++ b/arch/ubicom32/include/asm/swab.h
12471 + * arch/ubicom32/include/asm/byteorder.h
12472 + * Byte order swapping utility routines.
12474 + * (C) Copyright 2009, Ubicom, Inc.
12476 + * This file is part of the Ubicom32 Linux Kernel Port.
12478 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
12479 + * it and/or modify it under the terms of the GNU General Public License
12480 + * as published by the Free Software Foundation, either version 2 of the
12481 + * License, or (at your option) any later version.
12483 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
12484 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12485 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
12486 + * the GNU General Public License for more details.
12488 + * You should have received a copy of the GNU General Public License
12489 + * along with the Ubicom32 Linux Kernel Port. If not,
12490 + * see <http://www.gnu.org/licenses/>.
12492 + * Ubicom32 implementation derived from (with many thanks):
12497 +#ifndef _ASM_UBICOM32_BYTEORDER_H
12498 +#define _ASM_UBICOM32_BYTEORDER_H
12500 +#include <linux/types.h>
12502 +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) || defined(__KERNEL__)
12503 +# define __BYTEORDER_HAS_U64__
12504 +# define __SWAB_64_THRU_32__
12507 +#if defined(IP7000) || defined(IP7000_REV2)
12509 +#define __arch__swab16 __builtin_ubicom32_swapb_2
12510 +#define __arch__swab32 __builtin_ubicom32_swapb_4
12512 +#endif /* IP7000 */
12514 +#endif /* _ASM_UBICOM32_BYTEORDER_H */
12516 +++ b/arch/ubicom32/include/asm/switch-dev.h
12519 + * arch/ubicom32/include/asm/switch-dev.h
12520 + * generic Ethernet switch platform data definitions for Ubicom32 architecture.
12522 + * (C) Copyright 2009, Ubicom, Inc.
12524 + * This file is part of the Ubicom32 Linux Kernel Port.
12526 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
12527 + * it and/or modify it under the terms of the GNU General Public License
12528 + * as published by the Free Software Foundation, either version 2 of the
12529 + * License, or (at your option) any later version.
12531 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
12532 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12533 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
12534 + * the GNU General Public License for more details.
12536 + * You should have received a copy of the GNU General Public License
12537 + * along with the Ubicom32 Linux Kernel Port. If not,
12538 + * see <http://www.gnu.org/licenses/>.
12540 + * Ubicom32 implementation derived from (with many thanks):
12545 +#ifndef _ASM_UBICOM32_SWITCH_DEV_H
12546 +#define _ASM_UBICOM32_SWITCH_DEV_H
12548 +#define SWITCH_DEV_FLAG_HW_RESET 0x01
12549 +#define SWITCH_DEV_FLAG_SW_RESET 0x02
12551 +struct switch_core_platform_data {
12553 + * See flags above
12558 + * GPIO to use for nReset
12563 + * Name of this switch
12565 + const char *name;
12568 +#endif /* _ASM_UBICOM32_SWITCH_DEV_H */
12570 +++ b/arch/ubicom32/include/asm/system.h
12573 + * arch/ubicom32/include/asm/system.h
12574 + * Low level switching definitions.
12576 + * (C) Copyright 2009, Ubicom, Inc.
12578 + * This file is part of the Ubicom32 Linux Kernel Port.
12580 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
12581 + * it and/or modify it under the terms of the GNU General Public License
12582 + * as published by the Free Software Foundation, either version 2 of the
12583 + * License, or (at your option) any later version.
12585 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
12586 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12587 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
12588 + * the GNU General Public License for more details.
12590 + * You should have received a copy of the GNU General Public License
12591 + * along with the Ubicom32 Linux Kernel Port. If not,
12592 + * see <http://www.gnu.org/licenses/>.
12594 + * Ubicom32 implementation derived from (with many thanks):
12599 +#ifndef _ASM_UBICOM32_SYSTEM_H
12600 +#define _ASM_UBICOM32_SYSTEM_H
12602 +#include <linux/irqflags.h>
12603 +#include <linux/linkage.h>
12604 +#include <asm/segment.h>
12605 +#include <asm/entry.h>
12606 +#include <asm/ldsr.h>
12607 +#include <asm/irq.h>
12608 +#include <asm/percpu.h>
12609 +#include <asm/ubicom32-common.h>
12610 +#include <asm/processor.h>
12613 + * switch_to(n) should switch tasks to task ptr, first checking that
12614 + * ptr isn't the current task, in which case it does nothing.
12616 +asmlinkage void resume(void);
12617 +extern void *__switch_to(struct task_struct *prev,
12618 + struct thread_struct *prev_switch,
12619 + struct thread_struct *next_switch);
12622 + * We will need a per linux thread sw_ksp for the switch_to macro to
12623 + * track the kernel stack pointer for the current thread on that linux thread.
12625 +#define switch_to(prev,next,last) \
12628 + _last = (void *) \
12629 + __switch_to(prev, &prev->thread, &next->thread); \
12630 + (last) = _last; \
12634 + * Force strict CPU ordering.
12635 + * Not really required on ubicom32...
12637 +#define nop() asm volatile ("nop"::)
12638 +#define mb() asm volatile ("" : : :"memory")
12639 +#define rmb() asm volatile ("" : : :"memory")
12640 +#define wmb() asm volatile ("" : : :"memory")
12641 +#define set_mb(var, value) ({ (var) = (value); wmb(); })
12644 +#define smp_mb() mb()
12645 +#define smp_rmb() rmb()
12646 +#define smp_wmb() wmb()
12647 +#define smp_read_barrier_depends() read_barrier_depends()
12649 +#define smp_mb() mb()
12650 +#define smp_rmb() rmb()
12651 +#define smp_wmb() wmb()
12652 +#define smp_read_barrier_depends() do { } while(0)
12655 +#define read_barrier_depends() ((void)0)
12658 + * The following defines change how the scheduler calls the switch_to()
12661 + * 1) The first causes the runqueue to be unlocked on entry to
12662 + * switch_to(). Since our ctx code does not play with the runqueue
12663 + * we do not need it unlocked.
12665 + * 2) The later turns interrupts on during a ctxsw to reduce the latency of
12666 + * interrupts during ctx. At this point in the port, we believe that this
12667 + * latency is not a problem since we have very little code to perform a ctxsw.
12669 +// #define __ARCH_WANT_UNLOCKED_CTXSW
12670 +// #define __ARCH_WANT_INTERRUPTS_ON_CTXSW
12672 +#endif /* _ASM_UBICOM32_SYSTEM_H */
12674 +++ b/arch/ubicom32/include/asm/termbits.h
12677 + * arch/ubicom32/include/asm/termbits.h
12678 + * Terminal/serial port definitions for Ubicom32 architecture.
12680 + * (C) Copyright 2009, Ubicom, Inc.
12682 + * This file is part of the Ubicom32 Linux Kernel Port.
12684 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
12685 + * it and/or modify it under the terms of the GNU General Public License
12686 + * as published by the Free Software Foundation, either version 2 of the
12687 + * License, or (at your option) any later version.
12689 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
12690 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12691 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
12692 + * the GNU General Public License for more details.
12694 + * You should have received a copy of the GNU General Public License
12695 + * along with the Ubicom32 Linux Kernel Port. If not,
12696 + * see <http://www.gnu.org/licenses/>.
12698 + * Ubicom32 implementation derived from (with many thanks):
12703 +#ifndef _ASM_UBICOM32_TERMBITS_H
12704 +#define _ASM_UBICOM32_TERMBITS_H
12706 +#include <linux/posix_types.h>
12708 +typedef unsigned char cc_t;
12709 +typedef unsigned int speed_t;
12710 +typedef unsigned int tcflag_t;
12714 + tcflag_t c_iflag; /* input mode flags */
12715 + tcflag_t c_oflag; /* output mode flags */
12716 + tcflag_t c_cflag; /* control mode flags */
12717 + tcflag_t c_lflag; /* local mode flags */
12718 + cc_t c_line; /* line discipline */
12719 + cc_t c_cc[NCCS]; /* control characters */
12723 + tcflag_t c_iflag; /* input mode flags */
12724 + tcflag_t c_oflag; /* output mode flags */
12725 + tcflag_t c_cflag; /* control mode flags */
12726 + tcflag_t c_lflag; /* local mode flags */
12727 + cc_t c_line; /* line discipline */
12728 + cc_t c_cc[NCCS]; /* control characters */
12729 + speed_t c_ispeed; /* input speed */
12730 + speed_t c_ospeed; /* output speed */
12734 + tcflag_t c_iflag; /* input mode flags */
12735 + tcflag_t c_oflag; /* output mode flags */
12736 + tcflag_t c_cflag; /* control mode flags */
12737 + tcflag_t c_lflag; /* local mode flags */
12738 + cc_t c_line; /* line discipline */
12739 + cc_t c_cc[NCCS]; /* control characters */
12740 + speed_t c_ispeed; /* input speed */
12741 + speed_t c_ospeed; /* output speed */
12744 +/* c_cc characters */
12757 +#define VREPRINT 12
12758 +#define VDISCARD 13
12759 +#define VWERASE 14
12764 +/* c_iflag bits */
12765 +#define IGNBRK 0000001
12766 +#define BRKINT 0000002
12767 +#define IGNPAR 0000004
12768 +#define PARMRK 0000010
12769 +#define INPCK 0000020
12770 +#define ISTRIP 0000040
12771 +#define INLCR 0000100
12772 +#define IGNCR 0000200
12773 +#define ICRNL 0000400
12774 +#define IUCLC 0001000
12775 +#define IXON 0002000
12776 +#define IXANY 0004000
12777 +#define IXOFF 0010000
12778 +#define IMAXBEL 0020000
12779 +#define IUTF8 0040000
12781 +/* c_oflag bits */
12782 +#define OPOST 0000001
12783 +#define OLCUC 0000002
12784 +#define ONLCR 0000004
12785 +#define OCRNL 0000010
12786 +#define ONOCR 0000020
12787 +#define ONLRET 0000040
12788 +#define OFILL 0000100
12789 +#define OFDEL 0000200
12790 +#define NLDLY 0000400
12791 +#define NL0 0000000
12792 +#define NL1 0000400
12793 +#define CRDLY 0003000
12794 +#define CR0 0000000
12795 +#define CR1 0001000
12796 +#define CR2 0002000
12797 +#define CR3 0003000
12798 +#define TABDLY 0014000
12799 +#define TAB0 0000000
12800 +#define TAB1 0004000
12801 +#define TAB2 0010000
12802 +#define TAB3 0014000
12803 +#define XTABS 0014000
12804 +#define BSDLY 0020000
12805 +#define BS0 0000000
12806 +#define BS1 0020000
12807 +#define VTDLY 0040000
12808 +#define VT0 0000000
12809 +#define VT1 0040000
12810 +#define FFDLY 0100000
12811 +#define FF0 0000000
12812 +#define FF1 0100000
12814 +/* c_cflag bit meaning */
12815 +#define CBAUD 0010017
12816 +#define B0 0000000 /* hang up */
12817 +#define B50 0000001
12818 +#define B75 0000002
12819 +#define B110 0000003
12820 +#define B134 0000004
12821 +#define B150 0000005
12822 +#define B200 0000006
12823 +#define B300 0000007
12824 +#define B600 0000010
12825 +#define B1200 0000011
12826 +#define B1800 0000012
12827 +#define B2400 0000013
12828 +#define B4800 0000014
12829 +#define B9600 0000015
12830 +#define B19200 0000016
12831 +#define B38400 0000017
12832 +#define EXTA B19200
12833 +#define EXTB B38400
12834 +#define CSIZE 0000060
12835 +#define CS5 0000000
12836 +#define CS6 0000020
12837 +#define CS7 0000040
12838 +#define CS8 0000060
12839 +#define CSTOPB 0000100
12840 +#define CREAD 0000200
12841 +#define PARENB 0000400
12842 +#define PARODD 0001000
12843 +#define HUPCL 0002000
12844 +#define CLOCAL 0004000
12845 +#define CBAUDEX 0010000
12846 +#define BOTHER 0010000
12847 +#define B57600 0010001
12848 +#define B115200 0010002
12849 +#define B230400 0010003
12850 +#define B460800 0010004
12851 +#define B500000 0010005
12852 +#define B576000 0010006
12853 +#define B921600 0010007
12854 +#define B1000000 0010010
12855 +#define B1152000 0010011
12856 +#define B1500000 0010012
12857 +#define B2000000 0010013
12858 +#define B2500000 0010014
12859 +#define B3000000 0010015
12860 +#define B3500000 0010016
12861 +#define B4000000 0010017
12862 +#define CIBAUD 002003600000 /* input baud rate */
12863 +#define CMSPAR 010000000000 /* mark or space (stick) parity */
12864 +#define CRTSCTS 020000000000 /* flow control */
12866 +#define IBSHIFT 16 /* Shift from CBAUD to CIBAUD */
12868 +/* c_lflag bits */
12869 +#define ISIG 0000001
12870 +#define ICANON 0000002
12871 +#define XCASE 0000004
12872 +#define ECHO 0000010
12873 +#define ECHOE 0000020
12874 +#define ECHOK 0000040
12875 +#define ECHONL 0000100
12876 +#define NOFLSH 0000200
12877 +#define TOSTOP 0000400
12878 +#define ECHOCTL 0001000
12879 +#define ECHOPRT 0002000
12880 +#define ECHOKE 0004000
12881 +#define FLUSHO 0010000
12882 +#define PENDIN 0040000
12883 +#define IEXTEN 0100000
12886 +/* tcflow() and TCXONC use these */
12892 +/* tcflush() and TCFLSH use these */
12893 +#define TCIFLUSH 0
12894 +#define TCOFLUSH 1
12895 +#define TCIOFLUSH 2
12897 +/* tcsetattr uses these */
12899 +#define TCSADRAIN 1
12900 +#define TCSAFLUSH 2
12902 +#endif /* _ASM_UBICOM32_TERMBITS_H */
12904 +++ b/arch/ubicom32/include/asm/termios.h
12907 + * arch/ubicom32/include/asm/termios.h
12908 + * Ubicom32 termio definitions.
12910 + * (C) Copyright 2009, Ubicom, Inc.
12912 + * This file is part of the Ubicom32 Linux Kernel Port.
12914 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
12915 + * it and/or modify it under the terms of the GNU General Public License
12916 + * as published by the Free Software Foundation, either version 2 of the
12917 + * License, or (at your option) any later version.
12919 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
12920 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12921 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
12922 + * the GNU General Public License for more details.
12924 + * You should have received a copy of the GNU General Public License
12925 + * along with the Ubicom32 Linux Kernel Port. If not,
12926 + * see <http://www.gnu.org/licenses/>.
12928 + * Ubicom32 implementation derived from (with many thanks):
12933 +#ifndef _ASM_UBICOM32_TERMIOS_H
12934 +#define _ASM_UBICOM32_TERMIOS_H
12936 +#include <asm/termbits.h>
12937 +#include <asm/ioctls.h>
12940 + unsigned short ws_row;
12941 + unsigned short ws_col;
12942 + unsigned short ws_xpixel;
12943 + unsigned short ws_ypixel;
12948 + unsigned short c_iflag; /* input mode flags */
12949 + unsigned short c_oflag; /* output mode flags */
12950 + unsigned short c_cflag; /* control mode flags */
12951 + unsigned short c_lflag; /* local mode flags */
12952 + unsigned char c_line; /* line discipline */
12953 + unsigned char c_cc[NCC]; /* control characters */
12957 +/* intr=^C quit=^| erase=del kill=^U
12958 + eof=^D vtime=\0 vmin=\1 sxtc=\0
12959 + start=^Q stop=^S susp=^Z eol=\0
12960 + reprint=^R discard=^U werase=^W lnext=^V
12963 +#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
12967 +#define TIOCM_LE 0x001
12968 +#define TIOCM_DTR 0x002
12969 +#define TIOCM_RTS 0x004
12970 +#define TIOCM_ST 0x008
12971 +#define TIOCM_SR 0x010
12972 +#define TIOCM_CTS 0x020
12973 +#define TIOCM_CAR 0x040
12974 +#define TIOCM_RNG 0x080
12975 +#define TIOCM_DSR 0x100
12976 +#define TIOCM_CD TIOCM_CAR
12977 +#define TIOCM_RI TIOCM_RNG
12978 +#define TIOCM_OUT1 0x2000
12979 +#define TIOCM_OUT2 0x4000
12980 +#define TIOCM_LOOP 0x8000
12982 +/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
12987 + * Translate a "termio" structure into a "termios". Ugh.
12989 +#define user_termio_to_kernel_termios(termios, termio) \
12991 + unsigned short tmp; \
12992 + get_user(tmp, &(termio)->c_iflag); \
12993 + (termios)->c_iflag = (0xffff0000 & ((termios)->c_iflag)) | tmp; \
12994 + get_user(tmp, &(termio)->c_oflag); \
12995 + (termios)->c_oflag = (0xffff0000 & ((termios)->c_oflag)) | tmp; \
12996 + get_user(tmp, &(termio)->c_cflag); \
12997 + (termios)->c_cflag = (0xffff0000 & ((termios)->c_cflag)) | tmp; \
12998 + get_user(tmp, &(termio)->c_lflag); \
12999 + (termios)->c_lflag = (0xffff0000 & ((termios)->c_lflag)) | tmp; \
13000 + get_user((termios)->c_line, &(termio)->c_line); \
13001 + copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \
13005 + * Translate a "termios" structure into a "termio". Ugh.
13007 +#define kernel_termios_to_user_termio(termio, termios) \
13009 + put_user((termios)->c_iflag, &(termio)->c_iflag); \
13010 + put_user((termios)->c_oflag, &(termio)->c_oflag); \
13011 + put_user((termios)->c_cflag, &(termio)->c_cflag); \
13012 + put_user((termios)->c_lflag, &(termio)->c_lflag); \
13013 + put_user((termios)->c_line, &(termio)->c_line); \
13014 + copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
13017 +#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios2))
13018 +#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios2))
13019 +#define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios))
13020 +#define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios))
13022 +#endif /* __KERNEL__ */
13024 +#endif /* _ASM_UBICOM32_TERMIOS_H */
13026 +++ b/arch/ubicom32/include/asm/thread-asm.h
13029 + * arch/ubicom32/include/asm/thread-asm.h
13030 + * Ubicom32 architecture specific thread definitions.
13032 + * (C) Copyright 2009, Ubicom, Inc.
13034 + * This file is part of the Ubicom32 Linux Kernel Port.
13036 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
13037 + * it and/or modify it under the terms of the GNU General Public License
13038 + * as published by the Free Software Foundation, either version 2 of the
13039 + * License, or (at your option) any later version.
13041 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
13042 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
13043 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13044 + * the GNU General Public License for more details.
13046 + * You should have received a copy of the GNU General Public License
13047 + * along with the Ubicom32 Linux Kernel Port. If not,
13048 + * see <http://www.gnu.org/licenses/>.
13050 + * Ubicom32 implementation derived from (with many thanks):
13055 +#ifndef _ASM_UBICOM32_THREAD_ASM_H
13056 +#define _ASM_UBICOM32_THREAD_ASM_H
13059 + * thread_get_self
13060 + * Read and shift the current thread into reg
13062 + * Note that we don't need to mask the result as bits 6 through 31 of the
13063 + * ROSR are zeroes.
13065 +.macro thread_get_self reg
13066 + lsr.4 \reg, ROSR, #2
13070 + * thread_get_self_mask
13071 + * Read and shift the current thread mask into reg
13073 +.macro thread_get_self_mask reg
13074 + lsr.4 \reg, ROSR, #2
13075 + lsl.4 \reg, #1, \reg /* Thread bit */
13078 +#endif /* _ASM_UBICOM32_THREAD_ASM_H */
13080 +++ b/arch/ubicom32/include/asm/thread.h
13083 + * arch/ubicom32/include/asm/thread.h
13084 + * Ubicom32 architecture specific thread definitions.
13086 + * (C) Copyright 2009, Ubicom, Inc.
13088 + * This file is part of the Ubicom32 Linux Kernel Port.
13090 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
13091 + * it and/or modify it under the terms of the GNU General Public License
13092 + * as published by the Free Software Foundation, either version 2 of the
13093 + * License, or (at your option) any later version.
13095 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
13096 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
13097 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13098 + * the GNU General Public License for more details.
13100 + * You should have received a copy of the GNU General Public License
13101 + * along with the Ubicom32 Linux Kernel Port. If not,
13102 + * see <http://www.gnu.org/licenses/>.
13104 + * Ubicom32 implementation derived from (with many thanks):
13109 +#ifndef _ASM_UBICOM32_THREAD_H
13110 +#define _ASM_UBICOM32_THREAD_H
13112 +#if !defined(__ASSEMBLY__)
13114 +#include <asm/ptrace.h>
13115 +#include <asm/ubicom32-common.h>
13117 +typedef int thread_t;
13118 +typedef unsigned char thread_type_t;
13119 +typedef void (*thread_exec_fn_t)(void *arg);
13121 +#define THREAD_NULL 0x40
13122 +#define THREAD_TYPE_HRT (1 << 0)
13123 +#define THREAD_TYPE_SPECIAL 0
13124 +#define THREAD_TYPE_NORMAL 0
13125 +#define THREAD_TYPE_BACKGROUND (1 << 1)
13128 + * This is the upper bound on the maximum hardware threads that one will find
13129 + * on a Ubicom processor. It is used to size per hardware thread data structures.
13131 +#define THREAD_ARCHITECTURAL_MAX 16
13134 + * TODO: Rename this at some point to be thread_
13136 +extern unsigned int sw_ksp[THREAD_ARCHITECTURAL_MAX];
13140 + * thread_get_self()
13142 +static inline thread_t thread_get_self(void)
13147 + * Note that ROSR has zeroes in bits 6 through 31 and so we don't need
13148 + * to do any additional bit masking here.
13151 + "lsr.4 %0, ROSR, #2 \n\t"
13161 + * thread_suspend()
13163 +static inline void thread_suspend(void)
13173 + * thread_resume()
13175 +static inline void thread_resume(thread_t thread)
13178 + "move.4 MT_ACTIVE_SET, %0 \n\t"
13179 + "pipe_flush 0 \n\t"
13180 + "pipe_flush 0 \n\t"
13182 + : "d" (1 << thread)
13189 + * thread_enable_mask()
13190 + * Enable all threads in the mask.
13192 + * All writes to MT_EN must be protected by the MT_EN_LOCK bit
13194 +static inline void thread_enable_mask(unsigned int mask)
13197 + * must flush the pipeline twice.
13198 + * first pipe_flush is to ensure write to MT_EN is completed
13199 + * second one is to ensure any new instructions from
13200 + * the targeted thread (the one being disabled), that
13201 + * are issued while the write to MT_EN is being executed,
13204 + UBICOM32_LOCK(MT_EN_LOCK_BIT);
13206 + "or.4 MT_EN, MT_EN, %0 \n\t"
13207 + "pipe_flush 0 \n\t"
13208 + "pipe_flush 0 \n\t"
13213 + UBICOM32_UNLOCK(MT_EN_LOCK_BIT);
13217 + * thread_enable()
13219 +static inline void thread_enable(thread_t thread)
13221 + thread_enable_mask(1 << thread);
13225 + * thread_disable_mask()
13226 + * Disable all threads in the mask.
13228 + * All writes to MT_EN must be protected by the MT_EN_LOCK bit
13230 +static inline void thread_disable_mask(unsigned int mask)
13233 + * must flush the pipeline twice.
13234 + * first pipe_flush is to ensure write to MT_EN is completed
13235 + * second one is to ensure any new instructions from
13236 + * the targeted thread (the one being disabled), that
13237 + * are issued while the write to MT_EN is being executed,
13240 + UBICOM32_LOCK(MT_EN_LOCK_BIT);
13242 + "and.4 MT_EN, MT_EN, %0 \n\t"
13243 + "pipe_flush 0 \n\t"
13244 + "pipe_flush 0 \n\t"
13249 + UBICOM32_UNLOCK(MT_EN_LOCK_BIT);
13253 + * thread_disable()
13255 +static inline void thread_disable(thread_t thread)
13257 + thread_disable_mask(1 << thread);
13261 + * thread_disable_others()
13262 + * Disable all other threads
13264 +static inline void thread_disable_others(void)
13266 + thread_t self = thread_get_self();
13267 + thread_disable_mask(~(1 << self));
13271 + * thread_is_trapped()
13272 + * Is the specified tid trapped?
13274 +static inline int thread_is_trapped(thread_t tid)
13276 + int thread_mask = (1 << tid);
13280 + "move.4 %0, MT_TRAP \n\t"
13281 + : "=d" (trap_thread)
13284 + return (trap_thread & thread_mask);
13288 + * thread_is_enabled()
13289 + * Is the specified tid enabled?
13291 +static inline int thread_is_enabled(thread_t tid)
13293 + int thread_mask = (1 << tid);
13294 + int enabled_threads;
13297 + "move.4 %0, MT_EN \n\t"
13298 + : "=d" (enabled_threads)
13301 + return (enabled_threads & thread_mask);
13305 + * thread_get_instruction_count()
13307 +static inline unsigned int thread_get_instruction_count(void)
13309 + unsigned int result;
13311 + "move.4 %0, INST_CNT \n\t"
13318 + * thread_get_pc()
13319 + * pc could point to a speculative and cancelled instruction unless thread is disabled
13321 +static inline void *thread_get_pc(thread_t thread)
13325 + "move.4 csr, %1 \n\t"
13326 + "setcsr_flush 0 \n\t"
13327 + "move.4 %0, pc \n\t"
13328 + "move.4 csr, #0 \n\t"
13329 + "setcsr_flush 0 \n\t"
13331 + : "r" ((thread << 9) | (1 << 8))
13337 + * thread_get_trap_cause()
13338 + * This should be called only when the thread is not running
13340 +static inline unsigned int thread_get_trap_cause(thread_t thread)
13342 + unsigned int result;
13344 + "move.4 csr, %1 \n\t"
13345 + "setcsr_flush 0 \n\t"
13346 + "move.4 %0, trap_cause \n\t"
13347 + "move.4 csr, #0 \n\t"
13348 + "setcsr_flush 0 \n\t"
13350 + : "r" ((thread << 9) | (1 << 8))
13356 + * THREAD_STALL macro.
13358 +#define THREAD_STALL \
13360 + "move.4 mt_dbg_active_clr, #-1 \n\t" \
13361 + "pipe_flush 0 \n\t" \
13366 +extern unsigned int thread_get_mainline(void);
13367 +extern void thread_set_mainline(thread_t tid);
13368 +extern thread_t thread_alloc(void);
13369 +extern thread_t thread_start(thread_t thread, thread_exec_fn_t exec, void *arg, unsigned int *sp_high, thread_type_t type);
13376 + * thread_get_self
13377 + * Read and shift the current thread into reg
13379 + * Note that we don't need to mask the result as bits 6 through 31 of the
13380 + * ROSR are zeroes.
13382 +".macro thread_get_self reg \n\t"
13383 +" lsr.4 \\reg, ROSR, #2 \n\t"
13387 + * thread_get_self_mask
13388 + * Read and shift the current thread mask into reg
13390 +".macro thread_get_self_mask reg \n\t"
13391 +" lsr.4 \\reg, ROSR, #2 \n\t"
13392 +" lsl.4 \\reg, #1, \\reg \n\t" /* Thread bit */
13396 +#else /* __ASSEMBLY__ */
13398 +#include <asm/thread-asm.h>
13400 +#endif /* __ASSEMBLY__ */
13401 +#endif /* _ASM_UBICOM32_THREAD_H */
13403 +++ b/arch/ubicom32/include/asm/thread_info.h
13406 + * arch/ubicom32/include/asm/thread_info.h
13407 + * Ubicom32 architecture low-level thread information.
13409 + * (C) Copyright 2009, Ubicom, Inc.
13410 + * Adapted from the i386 and PPC versions by Greg Ungerer (gerg@snapgear.com)
13411 + * Copyright (C) 2002 David Howells (dhowells@redhat.com)
13412 + * - Incorporating suggestions made by Linus Torvalds and Dave Miller
13414 + * This file is part of the Ubicom32 Linux Kernel Port.
13416 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
13417 + * it and/or modify it under the terms of the GNU General Public License
13418 + * as published by the Free Software Foundation, either version 2 of the
13419 + * License, or (at your option) any later version.
13421 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
13422 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
13423 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13424 + * the GNU General Public License for more details.
13426 + * You should have received a copy of the GNU General Public License
13427 + * along with the Ubicom32 Linux Kernel Port. If not,
13428 + * see <http://www.gnu.org/licenses/>.
13430 + * Ubicom32 implementation derived from (with many thanks):
13436 +#ifndef _ASM_UBICOM32_THREAD_INFO_H
13437 +#define _ASM_UBICOM32_THREAD_INFO_H
13439 +#include <asm/page.h>
13442 + * Size of kernel stack for each process. This must be a power of 2...
13444 +#ifdef CONFIG_4KSTACKS
13445 +#define THREAD_SIZE_ORDER (0)
13447 +#define THREAD_SIZE_ORDER (1)
13451 + * for asm files, THREAD_SIZE is now generated by asm-offsets.c
13453 +#define THREAD_SIZE (PAGE_SIZE<<THREAD_SIZE_ORDER)
13457 +#ifndef __ASSEMBLY__
13460 + * low level task data.
13462 +struct thread_info {
13463 + struct task_struct *task; /* main task structure */
13464 + struct exec_domain *exec_domain; /* execution domain */
13465 + unsigned long flags; /* low level flags */
13466 + int cpu; /* cpu we're on */
13467 + int preempt_count; /* 0 => preemptable, <0 => BUG */
13468 + int interrupt_nesting; /* Interrupt nesting level. */
13469 + struct restart_block restart_block;
13473 + * macros/functions for gaining access to the thread information structure
13475 +#define INIT_THREAD_INFO(tsk) \
13478 + .exec_domain = &default_exec_domain, \
13481 + .interrupt_nesting = 0, \
13482 + .restart_block = { \
13483 + .fn = do_no_restart_syscall, \
13487 +#define init_thread_info (init_thread_union.thread_info)
13488 +#define init_stack (init_thread_union.stack)
13491 +/* how to get the thread information struct from C */
13492 +static inline struct thread_info *current_thread_info(void)
13494 + struct thread_info *ti;
13497 + "and.4 %0, sp, %1\n\t"
13499 + : "d" (~(THREAD_SIZE-1))
13506 +#define STACK_WARN (THREAD_SIZE / 8)
13508 +#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR 1
13510 +/* thread information allocation */
13511 +#define alloc_thread_info(tsk) ((struct thread_info *) \
13512 + __get_free_pages(GFP_KERNEL, THREAD_SIZE_ORDER))
13513 +#define free_thread_info(ti) free_pages((unsigned long) (ti), THREAD_SIZE_ORDER)
13514 +#endif /* __ASSEMBLY__ */
13516 +#define PREEMPT_ACTIVE 0x4000000
13519 + * thread information flag bit numbers
13521 +#define TIF_SYSCALL_TRACE 0 /* syscall trace active */
13522 +#define TIF_SIGPENDING 1 /* signal pending */
13523 +#define TIF_NEED_RESCHED 2 /* rescheduling necessary */
13524 +#define TIF_POLLING_NRFLAG 3 /* true if poll_idle() is polling
13525 + TIF_NEED_RESCHED */
13526 +#define TIF_MEMDIE 4
13528 +/* as above, but as bit values */
13529 +#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
13530 +#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
13531 +#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
13532 +#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
13534 +#define _TIF_WORK_MASK 0x0000FFFE /* work to do on interrupt/exception return */
13536 +#endif /* __KERNEL__ */
13538 +#endif /* _ASM_UBICOM32_THREAD_INFO_H */
13540 +++ b/arch/ubicom32/include/asm/timex.h
13543 + * arch/ubicom32/include/asm/timex.h
13544 + * Ubicom32 architecture timex specifications.
13546 + * (C) Copyright 2009, Ubicom, Inc.
13548 + * This file is part of the Ubicom32 Linux Kernel Port.
13550 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
13551 + * it and/or modify it under the terms of the GNU General Public License
13552 + * as published by the Free Software Foundation, either version 2 of the
13553 + * License, or (at your option) any later version.
13555 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
13556 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
13557 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13558 + * the GNU General Public License for more details.
13560 + * You should have received a copy of the GNU General Public License
13561 + * along with the Ubicom32 Linux Kernel Port. If not,
13562 + * see <http://www.gnu.org/licenses/>.
13564 + * Ubicom32 implementation derived from (with many thanks):
13569 +#ifndef _ASM_UBICOM32_TIMEX_H
13570 +#define _ASM_UBICOM32_TIMEX_H
13572 +#define CLOCK_TICK_RATE 266000000
13574 +// #define ARCH_HAS_READ_CURRENT_TIMER
13576 +typedef unsigned long cycles_t;
13578 +static inline cycles_t get_cycles(void)
13583 +extern int timer_alloc(void);
13584 +extern void timer_set(int timervector, unsigned int cycles);
13585 +extern int timer_reset(int timervector, unsigned int cycles);
13586 +extern void timer_tick_init(void);
13587 +extern void timer_device_init(void);
13589 +#if defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)
13590 +extern void local_timer_interrupt(void);
13593 +#if defined(CONFIG_LOCAL_TIMERS) || defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)
13594 +extern int local_timer_setup(unsigned int cpu);
13597 +#endif /* _ASM_UBICOM32_TIMEX_H */
13599 +++ b/arch/ubicom32/include/asm/tlbflush.h
13602 + * arch/ubicom32/include/asm/tlbflush.h
13603 + * TLB operations for Ubicom32 architecture.
13605 + * (C) Copyright 2009, Ubicom, Inc.
13606 + * Copyright (C) 2000 Lineo, David McCullough <davidm@uclinux.org>
13607 + * Copyright (C) 2000-2002, Greg Ungerer <gerg@snapgear.com>
13609 + * This file is part of the Ubicom32 Linux Kernel Port.
13611 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
13612 + * it and/or modify it under the terms of the GNU General Public License
13613 + * as published by the Free Software Foundation, either version 2 of the
13614 + * License, or (at your option) any later version.
13616 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
13617 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
13618 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13619 + * the GNU General Public License for more details.
13621 + * You should have received a copy of the GNU General Public License
13622 + * along with the Ubicom32 Linux Kernel Port. If not,
13623 + * see <http://www.gnu.org/licenses/>.
13625 + * Ubicom32 implementation derived from (with many thanks):
13630 +#ifndef _ASM_UBICOM32_TLB_FLUSH_H
13631 +#define _ASM_UBICOM32_TLB_FLUSH_H
13633 +#include <asm/setup.h>
13636 + * flush all user-space atc entries.
13638 +static inline void __flush_tlb(void)
13643 +static inline void __flush_tlb_one(unsigned long addr)
13648 +#define flush_tlb() __flush_tlb()
13651 + * flush all atc entries (both kernel and user-space entries).
13653 +static inline void flush_tlb_all(void)
13658 +static inline void flush_tlb_mm(struct mm_struct *mm)
13663 +static inline void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
13668 +static inline void flush_tlb_range(struct mm_struct *mm,
13669 + unsigned long start, unsigned long end)
13674 +static inline void flush_tlb_kernel_page(unsigned long addr)
13679 +#endif /* _ASM_UBICOM32_TLB_FLUSH_H */
13681 +++ b/arch/ubicom32/include/asm/tlb.h
13684 + * arch/ubicom32/include/asm/tlb.h
13685 + * Ubicom32 architecture TLB operations.
13687 + * (C) Copyright 2009, Ubicom, Inc.
13689 + * This file is part of the Ubicom32 Linux Kernel Port.
13691 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
13692 + * it and/or modify it under the terms of the GNU General Public License
13693 + * as published by the Free Software Foundation, either version 2 of the
13694 + * License, or (at your option) any later version.
13696 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
13697 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
13698 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13699 + * the GNU General Public License for more details.
13701 + * You should have received a copy of the GNU General Public License
13702 + * along with the Ubicom32 Linux Kernel Port. If not,
13703 + * see <http://www.gnu.org/licenses/>.
13705 + * Ubicom32 implementation derived from (with many thanks):
13710 +#ifndef _ASM_UBICOM32_TLB_H
13711 +#define _ASM_UBICOM32_TLB_H
13714 + * ubicom32 doesn't need any special per-pte or
13715 + * per-vma handling..
13717 +#define tlb_start_vma(tlb, vma) do { } while (0)
13718 +#define tlb_end_vma(tlb, vma) do { } while (0)
13719 +#define __tlb_remove_tlb_entry(tlb, ptep, address) do { } while (0)
13722 + * .. because we flush the whole mm when it
13725 +#define tlb_flush(tlb)
13727 +#include <asm-generic/tlb.h>
13729 +#endif /* _ASM_UBICOM32_TLB_H */
13731 +++ b/arch/ubicom32/include/asm/topology.h
13734 + * arch/ubicom32/include/asm/topology.h
13735 + * Generic topology.h definitions for Ubicom32 architecture.
13737 + * (C) Copyright 2009, Ubicom, Inc.
13739 + * This file is part of the Ubicom32 Linux Kernel Port.
13741 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
13742 + * it and/or modify it under the terms of the GNU General Public License
13743 + * as published by the Free Software Foundation, either version 2 of the
13744 + * License, or (at your option) any later version.
13746 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
13747 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
13748 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13749 + * the GNU General Public License for more details.
13751 + * You should have received a copy of the GNU General Public License
13752 + * along with the Ubicom32 Linux Kernel Port. If not,
13753 + * see <http://www.gnu.org/licenses/>.
13755 + * Ubicom32 implementation derived from (with many thanks):
13760 +#ifndef _ASM_UBICOM32_TOPOLOGY_H
13761 +#define _ASM_UBICOM32_TOPOLOGY_H
13763 +#include <asm-generic/topology.h>
13765 +#endif /* _ASM_UBICOM32_TOPOLOGY_H */
13767 +++ b/arch/ubicom32/include/asm/traps.h
13770 + * arch/ubicom32/include/asm/traps.h
13771 + * Trap related definitions for Ubicom32 architecture.
13773 + * (C) Copyright 2009, Ubicom, Inc.
13775 + * This file is part of the Ubicom32 Linux Kernel Port.
13777 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
13778 + * it and/or modify it under the terms of the GNU General Public License
13779 + * as published by the Free Software Foundation, either version 2 of the
13780 + * License, or (at your option) any later version.
13782 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
13783 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
13784 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13785 + * the GNU General Public License for more details.
13787 + * You should have received a copy of the GNU General Public License
13788 + * along with the Ubicom32 Linux Kernel Port. If not,
13789 + * see <http://www.gnu.org/licenses/>.
13791 + * Ubicom32 implementation derived from (with many thanks):
13797 +#ifndef _ASM_UBICOM32_TRAPS_H
13798 +#define _ASM_UBICOM32_TRAPS_H
13801 + * Trap causes passed from ultra to Host OS
13803 +#define TRAP_CAUSE_TOTAL 13
13804 +#define TRAP_CAUSE_DST_RANGE_ERR 12
13805 +#define TRAP_CAUSE_SRC1_RANGE_ERR 11
13806 +#define TRAP_CAUSE_I_RANGE_ERR 10
13807 +#define TRAP_CAUSE_DCAPT 9
13808 +#define TRAP_CAUSE_DST_SERROR 8
13809 +#define TRAP_CAUSE_SRC1_SERROR 7
13810 +#define TRAP_CAUSE_DST_MISALIGNED 6
13811 +#define TRAP_CAUSE_SRC1_MISALIGNED 5
13812 +#define TRAP_CAUSE_DST_DECODE_ERR 4
13813 +#define TRAP_CAUSE_SRC1_DECODE_ERR 3
13814 +#define TRAP_CAUSE_ILLEGAL_INST 2
13815 +#define TRAP_CAUSE_I_SERROR 1
13816 +#define TRAP_CAUSE_I_DECODE_ERR 0
13818 +extern void trap_handler(int irq, struct pt_regs *regs);
13819 +extern void trap_init_interrupt(void);
13820 +extern void unaligned_emulate(unsigned int thread);
13821 +extern int unaligned_only(unsigned int cause);
13823 +#endif /* _ASM_UBICOM32_TRAPS_H */
13825 +++ b/arch/ubicom32/include/asm/types.h
13828 + * arch/ubicom32/include/asm/types.h
13829 + * Date type definitions for Ubicom32 architecture.
13831 + * (C) Copyright 2009, Ubicom, Inc.
13833 + * This file is part of the Ubicom32 Linux Kernel Port.
13835 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
13836 + * it and/or modify it under the terms of the GNU General Public License
13837 + * as published by the Free Software Foundation, either version 2 of the
13838 + * License, or (at your option) any later version.
13840 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
13841 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
13842 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13843 + * the GNU General Public License for more details.
13845 + * You should have received a copy of the GNU General Public License
13846 + * along with the Ubicom32 Linux Kernel Port. If not,
13847 + * see <http://www.gnu.org/licenses/>.
13849 + * Ubicom32 implementation derived from (with many thanks):
13854 +#ifndef _ASM_UBICOM32_TYPES_H
13855 +#define _ASM_UBICOM32_TYPES_H
13858 + * This file is never included by application software unless
13859 + * explicitly requested (e.g., via linux/types.h) in which case the
13860 + * application is Linux specific so (user-) name space pollution is
13861 + * not a major issue. However, for interoperability, libraries still
13862 + * need to be careful to avoid a name clashes.
13865 +#include <asm-generic/int-ll64.h>
13867 +#ifndef __ASSEMBLY__
13869 +typedef unsigned short umode_t;
13871 +#endif /* __ASSEMBLY__ */
13874 + * These aren't exported outside the kernel to avoid name space clashes
13878 +#define BITS_PER_LONG 32
13880 +#ifndef __ASSEMBLY__
13882 +/* DMA addresses are always 32-bits wide */
13884 +typedef u32 dma_addr_t;
13885 +typedef u32 dma64_addr_t;
13888 + * XXX These are "Ubicom style" typedefs. They should be removed in all files used by linux.
13890 +typedef u32 u32_t;
13891 +typedef s32 s32_t;
13892 +typedef u16 u16_t;
13893 +typedef s16 s16_t;
13897 +#endif /* __ASSEMBLY__ */
13899 +#endif /* __KERNEL__ */
13901 +#endif /* _ASM_UBICOM32_TYPES_H */
13903 +++ b/arch/ubicom32/include/asm/uaccess.h
13906 + * arch/ubicom32/include/asm/uaccess.h
13907 + * User space memory access functions for Ubicom32 architecture.
13909 + * (C) Copyright 2009, Ubicom, Inc.
13911 + * This file is part of the Ubicom32 Linux Kernel Port.
13913 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
13914 + * it and/or modify it under the terms of the GNU General Public License
13915 + * as published by the Free Software Foundation, either version 2 of the
13916 + * License, or (at your option) any later version.
13918 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
13919 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
13920 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13921 + * the GNU General Public License for more details.
13923 + * You should have received a copy of the GNU General Public License
13924 + * along with the Ubicom32 Linux Kernel Port. If not,
13925 + * see <http://www.gnu.org/licenses/>.
13927 + * Ubicom32 implementation derived from (with many thanks):
13933 +#ifndef _ASM_UBICOM32_UACCESS_H
13934 +#define _ASM_UBICOM32_UACCESS_H
13937 + * User space memory access functions
13939 +#include <linux/sched.h>
13940 +#include <linux/mm.h>
13941 +#include <linux/string.h>
13943 +#include <asm/segment.h>
13945 +#define VERIFY_READ 0
13946 +#define VERIFY_WRITE 1
13949 + * The exception table consists of pairs of addresses: the first is the
13950 + * address of an instruction that is allowed to fault, and the second is
13951 + * the address at which the program should continue. No registers are
13952 + * modified, so it is entirely up to the continuation code to figure out
13955 + * All the routines below use bits of fixup code that are out of line
13956 + * with the main instruction path. This means when everything is well,
13957 + * we don't even have to jump over them. Further, they do not intrude
13958 + * on our cache or tlb entries.
13960 +struct exception_table_entry
13962 + unsigned long insn, fixup;
13966 + * Ubicom32 does not currently support the exception table handling.
13968 +extern unsigned long search_exception_table(unsigned long);
13971 +#if defined(CONFIG_ACCESS_OK_CHECKS_ENABLED)
13972 +extern int __access_ok(unsigned long addr, unsigned long size);
13974 +static inline int __access_ok(unsigned long addr, unsigned long size)
13979 +#define access_ok(type, addr, size) \
13980 + likely(__access_ok((unsigned long)(addr), (size)))
13983 + * The following functions do not exist. They keep callers
13984 + * of put_user and get_user from passing unsupported argument
13985 + * types. They result in a link time error.
13987 +extern int __put_user_bad(void);
13988 +extern int __get_user_bad(void);
13991 + * __put_user_no_check()
13992 + * Put the requested data into the user space verifying the address
13995 + * (a) re-use the arguments for side effects (sizeof/typeof is ok)
13996 + * (b) require any knowledge of processes at this stage
13998 +#define __put_user_no_check(x, ptr, size) \
14000 + int __pu_err = 0; \
14001 + __typeof__(*(ptr)) __user *__pu_addr = (ptr); \
14002 + switch (size) { \
14007 + *__pu_addr = (__typeof__(*(ptr)))x; \
14010 + __pu_err = __put_user_bad(); \
14017 + * __put_user_check()
14018 + * Put the requested data into the user space verifying the address
14021 + * (a) re-use the arguments for side effects (sizeof/typeof is ok)
14022 + * (b) require any knowledge of processes at this stage
14024 + * If requested, access_ok() will verify that ptr is a valid user
14027 +#define __put_user_check(x, ptr, size) \
14029 + int __pu_err = -EFAULT; \
14030 + __typeof__(*(ptr)) __user *__pu_addr = (ptr); \
14031 + if (access_ok(VERIFY_WRITE, __pu_addr, size)) { \
14033 + switch (size) { \
14038 + *__pu_addr = (__typeof__(*(ptr)))x; \
14041 + __pu_err = __put_user_bad(); \
14049 + * __get_user_no_check()
14050 + * Read the value at ptr into x.
14052 + * If requested, access_ok() will verify that ptr is a valid user
14053 + * pointer. If the caller passes a modifying argument for ptr (e.g. x++)
14054 + * this macro will not work.
14056 +#define __get_user_no_check(x, ptr, size) \
14058 + int __gu_err = 0; \
14059 + __typeof__((x)) __gu_val = 0; \
14060 + const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \
14061 + switch (size) { \
14066 + __gu_val = (__typeof__((x)))*(__gu_addr); \
14069 + __gu_err = __get_user_bad(); \
14073 + (x) = __gu_val; \
14078 + * __get_user_check()
14079 + * Read the value at ptr into x.
14081 + * If requested, access_ok() will verify that ptr is a valid user
14084 +#define __get_user_check(x, ptr, size) \
14086 + int __gu_err = -EFAULT; \
14087 + __typeof__(x) __gu_val = 0; \
14088 + const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \
14089 + if (access_ok(VERIFY_READ, __gu_addr, size)) { \
14091 + switch (size) { \
14096 + __gu_val = (__typeof__((x)))*(__gu_addr); \
14099 + __gu_err = __get_user_bad(); \
14104 + (x) = __gu_val; \
14109 + * The "xxx" versions are allowed to perform some amount of address
14110 + * space checking. See access_ok().
14112 +#define put_user(x,ptr) \
14113 + __put_user_check((__typeof__(*(ptr)))(x),(ptr), sizeof(*(ptr)))
14114 +#define get_user(x,ptr) \
14115 + __get_user_check((x), (ptr), sizeof(*(ptr)))
14118 + * The "__xxx" versions do not do address space checking, useful when
14119 + * doing multiple accesses to the same area (the programmer has to do the
14120 + * checks by hand with "access_ok()")
14122 +#define __put_user(x,ptr) \
14123 + __put_user_no_check((__typeof__(*(ptr)))(x),(ptr), sizeof(*(ptr)))
14124 +#define __get_user(x,ptr) \
14125 + __get_user_no_check((x), (ptr), sizeof(*(ptr)))
14128 + * __copy_tofrom_user_no_check()
14129 + * Copy the data either to or from user space.
14131 + * Return the number of bytes NOT copied.
14133 +static inline unsigned long
14134 +__copy_tofrom_user_no_check(void *to, const void *from, unsigned long n)
14136 + memcpy(to, from, n);
14142 + * Copy the kernel data to user space.
14144 + * Return the number of bytes that were copied.
14146 +static inline unsigned long
14147 +copy_to_user(void __user *to, const void *from, unsigned long n)
14149 + if (!access_ok(VERIFY_WRITE, to, n)) {
14152 + return __copy_tofrom_user_no_check((__force void *)to, from, n);
14156 + * copy_from_user()
14157 + * Copy the user data to kernel space.
14159 + * Return the number of bytes that were copied. On error, we zero
14160 + * out the destination.
14162 +static inline unsigned long
14163 +copy_from_user(void *to, const void __user *from, unsigned long n)
14165 + if (!access_ok(VERIFY_READ, from, n)) {
14168 + return __copy_tofrom_user_no_check(to, (__force void *)from, n);
14171 +#define __copy_to_user(to, from, n) \
14172 + __copy_tofrom_user_no_check((__force void *)to, from, n)
14173 +#define __copy_from_user(to, from, n) \
14174 + __copy_tofrom_user_no_check(to, (__force void *)from, n)
14175 +#define __copy_to_user_inatomic(to, from, n) \
14176 + __copy_tofrom_user_no_check((__force void *)to, from, n)
14177 +#define __copy_from_user_inatomic(to, from, n) \
14178 + __copy_tofrom_user_no_check(to, (__force void *)from, n)
14180 +#define copy_to_user_ret(to, from, n, retval) \
14181 + ({ if (copy_to_user(to, from, n)) return retval; })
14183 +#define copy_from_user_ret(to, from, n, retval) \
14184 + ({ if (copy_from_user(to, from, n)) return retval; })
14187 + * strncpy_from_user()
14188 + * Copy a null terminated string from userspace.
14190 + * dst - Destination in kernel space. The buffer must be at least count.
14191 + * src - Address of string in user space.
14192 + * count - Maximum number of bytes to copy (including the trailing NULL).
14194 + * Returns the length of the string (not including the trailing NULL. If
14195 + * count is smaller than the length of the string, we copy count bytes
14196 + * and return count.
14199 +static inline long strncpy_from_user(char *dst, const __user char *src, long count)
14202 + if (!access_ok(VERIFY_READ, src, 1)) {
14206 + strncpy(dst, src, count);
14207 + for (tmp = dst; *tmp && count > 0; tmp++, count--) {
14210 + return(tmp - dst);
14215 + * Return the size of a string (including the ending 0)
14217 + * Return -EFAULT on exception, a value greater than <n> if too long
14219 +static inline long strnlen_user(const __user char *src, long n)
14221 + if (!access_ok(VERIFY_READ, src, 1)) {
14224 + return(strlen(src) + 1);
14227 +#define strlen_user(str) strnlen_user(str, 32767)
14233 +static inline unsigned long __clear_user(__user void *to, unsigned long n)
14235 + memset(to, 0, n);
14241 + * Zero user space (check for valid addresses)
14243 +static inline unsigned long clear_user(__user void *to, unsigned long n)
14245 + if (!access_ok(VERIFY_WRITE, to, n)) {
14248 + return __clear_user(to, n);
14251 +#endif /* _ASM_UBICOM32_UACCESS_H */
14253 +++ b/arch/ubicom32/include/asm/uart_tio.h
14256 + * arch/ubicom32/include/asm/uart_tio.h
14257 + * Ubicom32 architecture UART TIO definitions.
14259 + * (C) Copyright 2009, Ubicom, Inc.
14261 + * This file is part of the Ubicom32 Linux Kernel Port.
14263 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
14264 + * it and/or modify it under the terms of the GNU General Public License
14265 + * as published by the Free Software Foundation, either version 2 of the
14266 + * License, or (at your option) any later version.
14268 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
14269 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
14270 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
14271 + * the GNU General Public License for more details.
14273 + * You should have received a copy of the GNU General Public License
14274 + * along with the Ubicom32 Linux Kernel Port. If not,
14275 + * see <http://www.gnu.org/licenses/>.
14277 +#ifndef _ASM_UBICOM32_UART_TIO_H
14278 +#define _ASM_UBICOM32_UART_TIO_H
14280 +#include <asm/devtree.h>
14282 +#define UARTTIO_RX_FIFO_SIZE 16
14283 +#define UARTTIO_TX_FIFO_SIZE 16
14286 + * Interrupt flags
14288 +#define UARTTIO_UART_INT_RX 0x00000001 // set when a character has been recevied (TODO: add watermark)
14289 +#define UARTTIO_UART_INT_RXOVF 0x00000002 // set when the receive buffer has overflowed
14290 +#define UARTTIO_UART_INT_RXFRAME 0x00000004 // set when there has been a framing error
14292 +#define UARTTIO_UART_INT_TX 0x00000100 // set every time a character is transmitted
14293 +#define UARTTIO_UART_INT_TXBE 0x00000200 // set when the transmit buffer is empty (TODO: add watermark)
14295 +#define UARTTIO_UART_FLAG_ENABLED 0x80000000
14296 +#define UARTTIO_UART_FLAG_SET_RATE 0x00000001 // set to update baud rate
14297 +#define UARTTIO_UART_FLAG_RESET 0x00000002 // set to reset the port
14298 +struct uarttio_uart {
14299 + volatile u32_t flags;
14301 + volatile u32_t baud_rate;
14302 + volatile u32_t current_baud_rate;
14306 + * Modem status register
14308 + volatile u32_t status;
14311 + * Interrupt registers
14313 + volatile u32_t int_mask;
14314 + volatile u32_t int_flags;
14326 + * Configuration Data
14329 + u8_t rx_stop_bits;
14331 + u8_t tx_stop_bits;
14334 + * RX state machine data
14337 + u32_t rx_bit_pos;
14339 + u32_t rx_fifo_head;
14340 + u32_t rx_fifo_tail;
14341 + u32_t rx_fifo_size;
14344 + * TX state machine data
14347 + u32_t tx_bit_pos;
14349 + u32_t tx_fifo_head;
14350 + u32_t tx_fifo_tail;
14351 + u32_t tx_fifo_size;
14356 + u8_t rx_fifo[UARTTIO_RX_FIFO_SIZE];
14357 + u8_t tx_fifo[UARTTIO_TX_FIFO_SIZE];
14360 +#define UARTTIO_VP_VERSION 1
14361 +struct uarttio_regs {
14368 + struct uarttio_uart uarts[0];
14371 +#define UARTTIO_NODE_VERSION 1
14372 +struct uarttio_node {
14373 + struct devtree_node dn;
14376 + struct uarttio_regs *regs;
14380 +#endif /* _ASM_UBICOM32_UART_TIO_H */
14382 +++ b/arch/ubicom32/include/asm/ubi32-cs4384.h
14385 + * arch/ubicom32/include/asm/ubi32-cs4384.h
14386 + * Ubicom32 architecture CS4384 driver platform data definitions.
14388 + * (C) Copyright 2009, Ubicom, Inc.
14390 + * This file is part of the Ubicom32 Linux Kernel Port.
14392 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
14393 + * it and/or modify it under the terms of the GNU General Public License
14394 + * as published by the Free Software Foundation, either version 2 of the
14395 + * License, or (at your option) any later version.
14397 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
14398 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
14399 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
14400 + * the GNU General Public License for more details.
14402 + * You should have received a copy of the GNU General Public License
14403 + * along with the Ubicom32 Linux Kernel Port. If not,
14404 + * see <http://www.gnu.org/licenses/>.
14406 +#ifndef _ASM_UBICOM32_UBI32_CS4384_H
14407 +#define _ASM_UBICOM32_UBI32_CS4384_H
14409 +enum ubi32_cs4384_mclk_source {
14410 + UBI32_CS4384_MCLK_PWM_0,
14411 + UBI32_CS4384_MCLK_PWM_1,
14412 + UBI32_CS4384_MCLK_PWM_2,
14413 + UBI32_CS4384_MCLK_CLKDIV_1,
14414 + UBI32_CS4384_MCLK_OTHER,
14417 +struct ubi32_cs4384_mclk_entry {
14419 + * Rate, in Hz, of this entry
14424 + * The divider to program to get the rate
14429 +struct ubi32_cs4384_platform_data {
14430 + enum ubi32_cs4384_mclk_source mclk_src;
14433 + struct ubi32_cs4384_mclk_entry *mclk_entries;
14435 +#endif /* _ASM_UBICOM32_UBI32_CS4384_H */
14437 +++ b/arch/ubicom32/include/asm/ubi32-pcm.h
14440 + * arch/ubicom32/include/asm/ubi32-pcm.h
14441 + * Ubicom32 architecture PCM driver platform data definitions.
14443 + * (C) Copyright 2009, Ubicom, Inc.
14445 + * This file is part of the Ubicom32 Linux Kernel Port.
14447 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
14448 + * it and/or modify it under the terms of the GNU General Public License
14449 + * as published by the Free Software Foundation, either version 2 of the
14450 + * License, or (at your option) any later version.
14452 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
14453 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
14454 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
14455 + * the GNU General Public License for more details.
14457 + * You should have received a copy of the GNU General Public License
14458 + * along with the Ubicom32 Linux Kernel Port. If not,
14459 + * see <http://www.gnu.org/licenses/>.
14461 +#ifndef _ASM_UBICOM32_UBI32_PCM_H
14462 +#define _ASM_UBICOM32_UBI32_PCM_H
14465 + * This function is called when the sample rate has changed
14467 +typedef int (*ubi32_pcm_set_rate_fn_t)(void *appdata, int rate);
14469 +struct ubi32pcm_platform_data {
14471 + * Name of the audio node/inst
14473 + const char *node_name;
14474 + const char *inst_name;
14478 + * Application specific data provided when calling functions
14483 + * Functions called when various things happen
14485 + ubi32_pcm_set_rate_fn_t set_rate;
14488 + * Pointer to optional upper layer data (i.e. DAC config, etc)
14492 +#endif /* _ASM_UBICOM32_UBI32_PCM_H */
14494 +++ b/arch/ubicom32/include/asm/ubicom32bl.h
14497 + * arch/ubicom32/include/asm/ubicom32bl.h
14498 + * Ubicom32 architecture backlight driver platform data definitions.
14500 + * (C) Copyright 2009, Ubicom, Inc.
14502 + * This file is part of the Ubicom32 Linux Kernel Port.
14504 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
14505 + * it and/or modify it under the terms of the GNU General Public License
14506 + * as published by the Free Software Foundation, either version 2 of the
14507 + * License, or (at your option) any later version.
14509 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
14510 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
14511 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
14512 + * the GNU General Public License for more details.
14514 + * You should have received a copy of the GNU General Public License
14515 + * along with the Ubicom32 Linux Kernel Port. If not,
14516 + * see <http://www.gnu.org/licenses/>.
14518 + * Ubicom32 implementation derived from (with many thanks):
14523 +#ifndef _ASM_UBICOM32_UBICOM32_BL_H
14524 +#define _ASM_UBICOM32_UBICOM32_BL_H
14527 + * Different backlight control mechanisms
14529 +enum ubicom32bl_pwm_types {
14531 + * PWM controlled backlight
14533 + UBICOM32BL_TYPE_PWM,
14536 + * HRT based PWM backlight
14538 + UBICOM32BL_TYPE_PWM_HRT,
14541 + * No dimming, just on or off
14543 + UBICOM32BL_TYPE_BINARY,
14546 +struct ubicom32bl_platform_data {
14548 + * Default intensity of the backlight 0-255
14550 + u8_t default_intensity;
14553 + * TRUE if the backlight sense is active low. (inverted)
14554 + * FALSE if the backlight sense is active high.
14559 + * Type of the backlight
14561 + enum ubicom32bl_pwm_types type;
14564 + * GPIO of the backlight if UBICOM32BL_TYPE_PWM_HRT, UBICOM32BL_TYPE_BINARY
14569 + * PWM channel and parameters of the backlight if UBICOM32BL_TYPE_PWM
14570 + * pre_scaler: sets the rate at which the PWM timer is clocked. (clk_core / 2^pre_scaler)
14571 + * period: sets the period of the timer in timer cycles
14572 + * The duty cycle will be directly proportional to the brightness setting.
14574 + u32_t pwm_channel;
14575 + u8_t pwm_prescale;
14576 + u16_t pwm_period;
14579 +#endif /* _ASM_UBICOM32_UBICOM32_BL_H */
14581 +++ b/arch/ubicom32/include/asm/ubicom32-common-asm.h
14584 + * arch/ubicom32/include/asm/ubicom32-common-asm.h
14585 + * Ubicom32 atomic lock operations.
14587 + * (C) Copyright 2009, Ubicom, Inc.
14589 + * This file is part of the Ubicom32 Linux Kernel Port.
14591 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
14592 + * it and/or modify it under the terms of the GNU General Public License
14593 + * as published by the Free Software Foundation, either version 2 of the
14594 + * License, or (at your option) any later version.
14596 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
14597 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
14598 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
14599 + * the GNU General Public License for more details.
14601 + * You should have received a copy of the GNU General Public License
14602 + * along with the Ubicom32 Linux Kernel Port. If not,
14603 + * see <http://www.gnu.org/licenses/>.
14605 + * Ubicom32 implementation derived from (with many thanks):
14611 +#ifndef _ASM_UBICOM32_UBICOM32_COMMON_ASM_H
14612 +#define _ASM_UBICOM32_UBICOM32_COMMON_ASM_H
14615 + * atomic_lock_acquire macro
14616 + * Equivalent to __atomic_lock_acquire()
14618 +.macro atomic_lock_acquire
14619 + bset scratchpad1, scratchpad1, #ATOMIC_LOCK_BIT
14624 + * atomic_lock_release macro
14625 + * Equivalent to __atomic_lock_release()
14627 +.macro atomic_lock_release
14628 + bclr scratchpad1, scratchpad1, #ATOMIC_LOCK_BIT
14631 +#endif /* _ASM_UBICOM32_UBICOM32_COMMON_ASM_H */
14633 +++ b/arch/ubicom32/include/asm/ubicom32-common.h
14636 + * arch/ubicom32/include/asm/ubicom32-common.h
14637 + * Ubicom32 atomic lock operations.
14639 + * (C) Copyright 2009, Ubicom, Inc.
14641 + * This file is part of the Ubicom32 Linux Kernel Port.
14643 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
14644 + * it and/or modify it under the terms of the GNU General Public License
14645 + * as published by the Free Software Foundation, either version 2 of the
14646 + * License, or (at your option) any later version.
14648 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
14649 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
14650 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
14651 + * the GNU General Public License for more details.
14653 + * You should have received a copy of the GNU General Public License
14654 + * along with the Ubicom32 Linux Kernel Port. If not,
14655 + * see <http://www.gnu.org/licenses/>.
14657 + * Ubicom32 implementation derived from (with many thanks):
14663 +#ifndef _ASM_UBICOM32_UBICOM32_COMMON_H
14664 +#define _ASM_UBICOM32_UBICOM32_COMMON_H
14666 +#define S(arg) #arg
14667 +#define D(arg) S(arg)
14669 + * scratchpad1 is owned by the LDSR.
14671 + * The upper bits provide 16 global spinlocks. Acquiring one of these
14672 + * global spinlocks synchornizes across multiple threads and prevents
14673 + * the LDSR from delivering any interrupts while the lock is held.
14674 + * Use these locks only when absolutely required.
14676 + * The lower 16 bits of scratchpad1 are used as per thread interrupt
14677 + * enable/disable bits. These bits will prevent a thread from receiving
14678 + * any interrupts.
14681 + * - MT_EN_LOCK_BIT - Protects writes to MT_EN, so code can read current value
14682 + * then write a new value atomically (profiler for example)
14683 + * - ATOMIC_LOCK_BIT - Used to provide general purpose atomic handling.
14684 + * - LDSR_LOCK_BIT - Used by the LDSR exclusively to provide protection.
14685 + * - DCCR_LOCK_BIT - Used to limit access to the DCCR cache control peripheral
14686 + * - ICCR_LOCK_BIT - Used to limit access to the ICCR cache control peripheral
14687 + * - LSB 16 bits - Used by the LDSR to represent thread enable/disable bits.
14689 +#define MT_EN_LOCK_BIT 31
14690 +#define ATOMIC_LOCK_BIT 30
14691 +#define LDSR_LOCK_BIT 29
14692 +#define PCI_LOCK_BIT 28
14693 +#define ICCR_LOCK_BIT 27
14694 +#define DCCR_LOCK_BIT 26
14696 +#if !defined(__ASSEMBLY__)
14698 +#define UBICOM32_TRYLOCK(bit) \
14700 + " move.4 %0, #0 \n\t" \
14701 + " bset scratchpad1, scratchpad1, #"D(bit)" \n\t" \
14702 + " jmpne.f 1f \n\t" \
14703 + " move.4 %0, #1 \n\t" \
14707 + : "cc", "memory" \
14710 +#define UBICOM32_UNLOCK(bit) \
14712 + " bclr scratchpad1, scratchpad1, #"D(bit)" \n\t" \
14715 + : "cc", "memory" \
14718 +#define UBICOM32_LOCK(bit) \
14720 + "1: bset scratchpad1, scratchpad1, #"D(bit)" \n\t" \
14721 + " jmpne.f 1b \n\t" \
14724 + : "cc", "memory" \
14728 + * __atomic_lock_trylock()
14729 + * Attempt to acquire the lock, return TRUE if acquired.
14731 +static inline int __atomic_lock_trylock(void)
14734 + UBICOM32_TRYLOCK(ATOMIC_LOCK_BIT);
14739 + * __atomic_lock_release()
14740 + * Release the global atomic lock.
14742 + * Note: no one is suspended waiting since this lock is a spinning lock.
14744 +static inline void __atomic_lock_release(void)
14746 + UBICOM32_UNLOCK(ATOMIC_LOCK_BIT);
14750 + * __atomic_lock_acquire()
14751 + * Acquire the global atomic lock, spin if not available.
14753 +static inline void __atomic_lock_acquire(void)
14755 + UBICOM32_LOCK(ATOMIC_LOCK_BIT);
14757 +#else /* __ASSEMBLY__ */
14759 +#include <asm/ubicom32-common-asm.h>
14761 +#endif /* __ASSEMBLY__ */
14762 +#endif /* _ASM_UBICOM32_UBICOM32_COMMON_H */
14764 +++ b/arch/ubicom32/include/asm/ubicom32fb.h
14767 + * arch/ubicom32/include/asm/ubicom32fb.h
14768 + * Ubicom32 architecture video frame buffer definitions.
14770 + * (C) Copyright 2009, Ubicom, Inc.
14772 + * This file is part of the Ubicom32 Linux Kernel Port.
14774 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
14775 + * it and/or modify it under the terms of the GNU General Public License
14776 + * as published by the Free Software Foundation, either version 2 of the
14777 + * License, or (at your option) any later version.
14779 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
14780 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
14781 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
14782 + * the GNU General Public License for more details.
14784 + * You should have received a copy of the GNU General Public License
14785 + * along with the Ubicom32 Linux Kernel Port. If not,
14786 + * see <http://www.gnu.org/licenses/>.
14788 +#ifndef _ASM_UBICOM32_UBICOM32FB_H
14789 +#define _ASM_UBICOM32_UBICOM32FB_H
14791 +#include <linux/ioctl.h>
14796 +#define UBICOM32FB_IOCTL_SET_NEXT_FRAME _IOW('r', 1, void *)
14797 +#define UBICOM32FB_IOCTL_SET_NEXT_FRAME_SYNC _IOW('r', 2, void *)
14802 +#define UBICOM32FB_IOCTL_SET_MODE _IOW('r', 3, void *)
14803 +struct ubicom32fb_mode {
14804 + unsigned long width;
14805 + unsigned long height;
14806 + unsigned long flags;
14807 + void *next_frame;
14809 +#define UBICOM32FB_IOCTL_SET_MODE_FLAG_YUV_SCAN_ORDER (1 << 8)
14811 +#define UBICOM32FB_IOCTL_SET_MODE_FLAG_YUV_BLOCK_ORDER (1 << 7)
14812 +#define UBICOM32FB_IOCTL_SET_MODE_FLAG_YUV (1 << 6)
14813 +#define UBICOM32FB_IOCTL_SET_MODE_FLAG_VSUB (1 << 5)
14814 +#define UBICOM32FB_IOCTL_SET_MODE_FLAG_VRANGE_16_255 (1 << 4)
14816 +#define UBICOM32FB_IOCTL_SET_MODE_FLAG_VRANGE_0_255 (1 << 3)
14817 +#define UBICOM32FB_IOCTL_SET_MODE_FLAG_HSUB_2_1 (1 << 2)
14818 +#define UBICOM32FB_IOCTL_SET_MODE_FLAG_HSUB_1_1 (1 << 1)
14819 +#define UBICOM32FB_IOCTL_SET_MODE_FLAG_SCALE_ENABLE (1 << 0)
14821 +#endif /* _ASM_UBICOM32_UBICOM32FB_H */
14823 +++ b/arch/ubicom32/include/asm/ubicom32hid.h
14826 + * arch/ubicom32/include/asm/ubicom32hid.h
14827 + * Ubicom32 architecture HID driver platform data definitions.
14829 + * (C) Copyright 2009, Ubicom, Inc.
14831 + * This file is part of the Ubicom32 Linux Kernel Port.
14833 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
14834 + * it and/or modify it under the terms of the GNU General Public License
14835 + * as published by the Free Software Foundation, either version 2 of the
14836 + * License, or (at your option) any later version.
14838 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
14839 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
14840 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
14841 + * the GNU General Public License for more details.
14843 + * You should have received a copy of the GNU General Public License
14844 + * along with the Ubicom32 Linux Kernel Port. If not,
14845 + * see <http://www.gnu.org/licenses/>.
14847 + * Ubicom32 implementation derived from (with many thanks):
14852 +#ifndef _ASM_UBICOM32_UBICOM32_HID_H
14853 +#define _ASM_UBICOM32_UBICOM32_HID_H
14855 +enum ubicom32hid_bl_types {
14857 + * On or off, using command SET_BL_EN, PB4
14859 + UBICOM32HID_BL_TYPE_BINARY,
14862 + * Dimmable, using command SET_PWM, PB3
14864 + UBICOM32HID_BL_TYPE_PWM,
14868 + * IR code mapping to event code.
14869 + * If there are no button mappings and no ir mappings
14870 + * then no input driver will be registered.
14872 +struct ubicom32hid_ir {
14874 + * Input event code (KEY_*, SW_*, etc)
14879 + * Input event type (EV_KEY, EV_SW, etc)
14884 + * The IR code of this button.
14886 + uint32_t ir_code;
14890 + * Button mapping to event code.
14891 + * If there are no button mappings and no ir mappings
14892 + * then no input driver will be registered.
14894 +struct ubicom32hid_button {
14896 + * Input event code (KEY_*, SW_*, etc)
14901 + * Input event type (EV_KEY, EV_SW, etc)
14906 + * Bit number of this button.
14911 +struct ubicom32hid_platform_data {
14913 + * Default intensity of the backlight 0-255
14915 + u8_t default_intensity;
14918 + * GPIO number of the reset line and its polarity.
14920 + unsigned gpio_reset;
14921 + int gpio_reset_polarity;
14924 + * TRUE if the backlight sense is active low. (inverted)
14925 + * FALSE if the backlight sense is active high.
14930 + * Type of the backlight we are controlling
14932 + enum ubicom32hid_bl_types type;
14935 + * Optional polling rate for input, in ms, defaults to 100ms
14937 + int poll_interval;
14940 + * Optional name to register as input device
14942 + const char *input_name;
14945 + * Button mapping array
14947 + const struct ubicom32hid_button *buttons;
14951 + * IR mapping array
14953 + const struct ubicom32hid_ir *ircodes;
14957 +#endif /* _ASM_UBICOM32_UBICOM32_HID_H */
14959 +++ b/arch/ubicom32/include/asm/ubicom32input.h
14962 + * arch/ubicom32/include/asm/ubicom32input.h
14963 + * Ubicom32 Input driver, based on gpio-keys
14965 + * (C) Copyright 2009, Ubicom, Inc.
14967 + * This file is part of the Ubicom32 Linux Kernel Port.
14969 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
14970 + * it and/or modify it under the terms of the GNU General Public License
14971 + * as published by the Free Software Foundation, either version 2 of the
14972 + * License, or (at your option) any later version.
14974 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
14975 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
14976 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
14977 + * the GNU General Public License for more details.
14979 + * You should have received a copy of the GNU General Public License
14980 + * along with the Ubicom32 Linux Kernel Port. If not,
14981 + * see <http://www.gnu.org/licenses/>.
14983 + * Ubicom32 implementation derived from (with many thanks):
14988 + * TODO: add groups for inputs which can be sampled together
14991 +#ifndef _ASM_UBICOM32_UBICOM32_INPUT_H
14992 +#define _ASM_UBICOM32_UBICOM32_INPUT_H
14994 +struct ubicom32input_button {
14996 + * Input event code (KEY_*, SW_*, etc)
15001 + * Input event type (EV_KEY, EV_SW, etc)
15011 + * 1 for active low, 0 for active high
15016 + * Description, used for reserving GPIOs
15018 + const char *desc;
15021 +struct ubicom32input_platform_data {
15022 + struct ubicom32input_button *buttons;
15026 + * Optional poll interval, in ms, defaults to 50ms
15028 + int poll_interval;
15031 + * Option Name of this driver
15033 + const char *name;
15036 +#endif /* _ASM_UBICOM32_UBICOM32_INPUT_H */
15038 +++ b/arch/ubicom32/include/asm/ubicom32input_i2c.h
15041 + * arch/ubicom32/include/asm/ubicom32input_i2c.h
15042 + * Ubicom32 architecture Input driver over I2C platform data definitions.
15044 + * (C) Copyright 2009, Ubicom, Inc.
15046 + * This file is part of the Ubicom32 Linux Kernel Port.
15048 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
15049 + * it and/or modify it under the terms of the GNU General Public License
15050 + * as published by the Free Software Foundation, either version 2 of the
15051 + * License, or (at your option) any later version.
15053 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15054 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
15055 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15056 + * the GNU General Public License for more details.
15058 + * You should have received a copy of the GNU General Public License
15059 + * along with the Ubicom32 Linux Kernel Port. If not,
15060 + * see <http://www.gnu.org/licenses/>.
15062 + * Ubicom32 implementation derived from (with many thanks):
15067 + * TODO: add groups for inputs which can be sampled together
15070 +#ifndef _ASM_UBICOM32_UBICOM32_INPUT_I2C_H
15071 +#define _ASM_UBICOM32_UBICOM32_INPUT_I2C_H
15073 +struct ubicom32input_i2c_button {
15075 + * Input event code (KEY_*, SW_*, etc)
15080 + * Input event type (EV_KEY, EV_SW, etc)
15085 + * Bit number of this button. (0 - ngpio)
15090 + * 1 for active low, 0 for active high
15095 +struct ubicom32input_i2c_platform_data {
15096 + struct ubicom32input_i2c_button *buttons;
15100 + * Optional poll interval, in ms, defaults to 100ms
15102 + int poll_interval;
15105 + * Option Name of this driver
15107 + const char *name;
15110 +#endif /* _ASM_UBICOM32_UBICOM32_INPUT_I2C_H */
15112 +++ b/arch/ubicom32/include/asm/ubicom32lcd.h
15115 + * arch/ubicom32/include/asm/ubicom32lcd.h
15116 + * Ubicom32 architecture LCD driver platform data definitions.
15118 + * (C) Copyright 2009, Ubicom, Inc.
15120 + * This file is part of the Ubicom32 Linux Kernel Port.
15122 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
15123 + * it and/or modify it under the terms of the GNU General Public License
15124 + * as published by the Free Software Foundation, either version 2 of the
15125 + * License, or (at your option) any later version.
15127 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15128 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
15129 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15130 + * the GNU General Public License for more details.
15132 + * You should have received a copy of the GNU General Public License
15133 + * along with the Ubicom32 Linux Kernel Port. If not,
15134 + * see <http://www.gnu.org/licenses/>.
15136 +#ifndef _ASM_UBICOM32_UBICOM32_LCD_H
15137 +#define _ASM_UBICOM32_UBICOM32_LCD_H
15139 +#include <asm/ip5000.h>
15141 +struct ubicom32lcd_platform_data {
15148 + struct ubicom32_io_port *port_data;
15151 +#endif /* _ASM_UBICOM32_UBICOM32_LCD_H */
15153 +++ b/arch/ubicom32/include/asm/ubicom32lcdpower.h
15156 + * arch/ubicom32/include/asm/ubicom32lcdpower.h
15157 + * Ubicom32 architecture LCD driver platform data definitions.
15159 + * (C) Copyright 2009, Ubicom, Inc.
15161 + * This file is part of the Ubicom32 Linux Kernel Port.
15163 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
15164 + * it and/or modify it under the terms of the GNU General Public License
15165 + * as published by the Free Software Foundation, either version 2 of the
15166 + * License, or (at your option) any later version.
15168 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15169 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
15170 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15171 + * the GNU General Public License for more details.
15173 + * You should have received a copy of the GNU General Public License
15174 + * along with the Ubicom32 Linux Kernel Port. If not,
15175 + * see <http://www.gnu.org/licenses/>.
15177 + * Ubicom32 implementation derived from (with many thanks):
15182 +#ifndef _ASM_UBICOM32_UBICOM32_LCDPOWER_H
15183 +#define _ASM_UBICOM32_UBICOM32_LCDPOWER_H
15185 +struct ubicom32lcdpower_platform_data {
15187 + * GPIO and polarity for VGH signal. A FALSE polarity is active low, TRUE is active high.
15190 + bool vgh_polarity;
15193 +#endif /* _ASM_UBICOM32_UBICOM32_LCDPOWER_H */
15195 +++ b/arch/ubicom32/include/asm/ubicom32ring.h
15198 + * arch/ubicom32/include/asm/ubicom32ring.h
15199 + * Userspace I/O platform driver for Ubicom32 ring buffers
15201 + * (C) Copyright 2009, Ubicom, Inc.
15203 + * This file is part of the Ubicom32 Linux Kernel Port.
15205 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
15206 + * it and/or modify it under the terms of the GNU General Public License
15207 + * as published by the Free Software Foundation, either version 2 of the
15208 + * License, or (at your option) any later version.
15210 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15211 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
15212 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15213 + * the GNU General Public License for more details.
15215 + * You should have received a copy of the GNU General Public License
15216 + * along with the Ubicom32 Linux Kernel Port. If not,
15217 + * see <http://www.gnu.org/licenses/>.
15220 +#ifndef _ASM_UBICOM32_UBICOM32RING_H
15221 +#define _ASM_UBICOM32_UBICOM32RING_H
15223 +#define UIO_UBICOM32RING_REG_VERSION 2
15225 +struct uio_ubicom32ring_desc {
15226 + volatile unsigned int head;
15227 + volatile unsigned int tail;
15228 + unsigned int entries;
15229 + volatile unsigned int ring[0];
15232 +struct uio_ubicom32ring_regs {
15233 + unsigned int version;
15236 + * Magic type used to identify the ring set. Each driver will
15237 + * have a different magic value.
15239 + unsigned int magic;
15242 + * Registers defined by the driver
15244 + unsigned int regs_size;
15248 + * The locations of the rings
15250 + * DO NOT ADD ANYTHING BELOW THIS LINE
15252 + unsigned int num_rings;
15253 + struct uio_ubicom32ring_desc *rings[0];
15257 + * ringtio_ring_flush
15259 +static inline void ringtio_ring_flush(struct uio_ubicom32ring_desc *rd)
15261 + rd->head = rd->tail = 0;
15265 + * ringtio_ring_get
15267 +static inline int ringtio_ring_get(struct uio_ubicom32ring_desc *rd, void **val)
15269 + if (rd->head == rd->tail) {
15273 + *val = (void *)rd->ring[rd->head++];
15274 + if (rd->head == rd->entries) {
15281 + * ringtio_ring_put
15283 +static inline int ringtio_ring_put(struct uio_ubicom32ring_desc *rd, void *val)
15285 + unsigned int newtail = rd->tail + 1;
15286 + if (newtail == rd->entries) {
15290 + if (newtail == rd->head) {
15294 + rd->ring[rd->tail] = (unsigned int)val;
15295 + rd->tail = newtail;
15299 +#endif /* _ASM_UBICOM32_UBICOM32RING_H */
15301 +++ b/arch/ubicom32/include/asm/ubicom32sd.h
15304 + * arch/ubicom32/include/asm/ubicom32sd.h
15305 + * Ubicom32SD public include file
15307 + * (C) Copyright 2009, Ubicom, Inc.
15309 + * This file is part of the Ubicom32 Linux Kernel Port.
15311 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
15312 + * it and/or modify it under the terms of the GNU General Public License
15313 + * as published by the Free Software Foundation, either version 2 of the
15314 + * License, or (at your option) any later version.
15316 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15317 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
15318 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15319 + * the GNU General Public License for more details.
15321 + * You should have received a copy of the GNU General Public License
15322 + * along with the Ubicom32 Linux Kernel Port. If not,
15323 + * see <http://www.gnu.org/licenses/>.
15325 +#ifndef _ASM_UBICOM32_UBICOM32_SD_H
15326 +#define _ASM_UBICOM32_UBICOM32_SD_H
15328 +struct ubicom32sd_card {
15330 + * GPIOs of PWR, WP and CD lines.
15331 + * Polarity is 1 for active high and 0 for active low
15334 + bool pwr_polarity;
15336 + bool wp_polarity;
15338 + bool cd_polarity;
15341 +struct ubicom32sd_platform_data {
15344 + struct ubicom32sd_card *cards;
15347 +#endif /* _ASM_UBICOM32_UBICOM32_SD_H */
15349 +++ b/arch/ubicom32/include/asm/ubicom32-spi-gpio.h
15352 + * arch/ubicom32/include/asm/ubicom32-spi-gpio.h
15353 + * Platform driver data definitions for GPIO based SPI driver.
15355 + * (C) Copyright 2009, Ubicom, Inc.
15357 + * This file is part of the Ubicom32 Linux Kernel Port.
15359 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
15360 + * it and/or modify it under the terms of the GNU General Public License
15361 + * as published by the Free Software Foundation, either version 2 of the
15362 + * License, or (at your option) any later version.
15364 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15365 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
15366 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15367 + * the GNU General Public License for more details.
15369 + * You should have received a copy of the GNU General Public License
15370 + * along with the Ubicom32 Linux Kernel Port. If not,
15371 + * see <http://www.gnu.org/licenses/>.
15373 + * Ubicom32 implementation derived from (with many thanks):
15378 +#ifndef _ASM_UBICOM32_UBICOM32_SPI_GPIO_H
15379 +#define _ASM_UBICOM32_UBICOM32_SPI_GPIO_H
15381 +struct ubicom32_spi_gpio_platform_data {
15383 + * GPIO to use for MOSI, MISO, CLK
15390 + * Default state of CLK line
15395 + * Number of chip selects on this bus
15397 + int num_chipselect;
15400 + * The bus number of this chip
15405 +struct ubicom32_spi_gpio_controller_data {
15407 + * GPIO to use for chip select
15412 +#endif /* _ASM_UBICOM32_UBICOM32_SPI_GPIO_H */
15414 +++ b/arch/ubicom32/include/asm/ubicom32suart.h
15417 + * arch/ubicom32/include/asm/ubicom32suart.h
15418 + * <TODO: Replace with short file description>
15420 + * (C) Copyright 2009, Ubicom, Inc.
15422 + * This file is part of the Ubicom32 Linux Kernel Port.
15424 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
15425 + * it and/or modify it under the terms of the GNU General Public License
15426 + * as published by the Free Software Foundation, either version 2 of the
15427 + * License, or (at your option) any later version.
15429 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15430 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
15431 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15432 + * the GNU General Public License for more details.
15434 + * You should have received a copy of the GNU General Public License
15435 + * along with the Ubicom32 Linux Kernel Port. If not,
15436 + * see <http://www.gnu.org/licenses/>.
15438 + * Ubicom32 implementation derived from (with many thanks):
15443 +#ifndef _ASM_UBICOM32_UBICOM32_SUART_H
15444 +#define _ASM_UBICOM32_UBICOM32_SUART_H
15447 + * Platform resource id for serdes uart clock parameter
15449 +#define UBICOM32_SUART_IORESOURCE_CLOCK (1)
15451 +#endif /* _ASM_UBICOM32_UBICOM32_SUART_H */
15453 +++ b/arch/ubicom32/include/asm/ubicom32-tio.h
15456 + * arch/ubicom32/include/asm/ubicom32-tio.h
15457 + * Threaded I/O interface definitions.
15459 + * (C) Copyright 2009, Ubicom, Inc.
15461 + * This file is part of the Ubicom32 Linux Kernel Port.
15463 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
15464 + * it and/or modify it under the terms of the GNU General Public License
15465 + * as published by the Free Software Foundation, either version 2 of the
15466 + * License, or (at your option) any later version.
15468 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15469 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
15470 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15471 + * the GNU General Public License for more details.
15473 + * You should have received a copy of the GNU General Public License
15474 + * along with the Ubicom32 Linux Kernel Port. If not,
15475 + * see <http://www.gnu.org/licenses/>.
15477 + * Ubicom32 implementation derived from (with many thanks):
15482 +#ifndef _ASM_UBICOM32_UBICOM32_TIO_H
15483 +#define _ASM_UBICOM32_UBICOM32_TIO_H
15485 +extern u8_t usb_tio_read_u16(u32_t address, u16_t *data);
15486 +extern u8_t usb_tio_read_u8(u32_t address, u8_t *data);
15488 +extern u8_t usb_tio_write_u16(u32_t address, u16_t data);
15489 +extern u8_t usb_tio_write_u8(u32_t address, u8_t data);
15491 +extern u8_t usb_tio_read_fifo(u32_t address, u32_t buffer, u32_t bytes);
15492 +extern u8_t usb_tio_write_fifo(u32_t address, u32_t buffer, u32_t bytes);
15493 +extern u8_t usb_tio_write_fifo_sync(u32_t address, u32_t buffer, u32_t bytes);
15494 +extern void usb_tio_read_int_status(u8_t *int_usb, u16_t *int_tx, u16_t *int_rx);
15496 +#endif /* _ASM_UBICOM32_UBICOM32_TIO_H */
15498 +++ b/arch/ubicom32/include/asm/ucontext.h
15501 + * arch/ubicom32/include/asm/ucontext.h
15502 + * Definition of ucontext structure for Ubicom32 architecture.
15504 + * (C) Copyright 2009, Ubicom, Inc.
15506 + * This file is part of the Ubicom32 Linux Kernel Port.
15508 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
15509 + * it and/or modify it under the terms of the GNU General Public License
15510 + * as published by the Free Software Foundation, either version 2 of the
15511 + * License, or (at your option) any later version.
15513 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15514 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
15515 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15516 + * the GNU General Public License for more details.
15518 + * You should have received a copy of the GNU General Public License
15519 + * along with the Ubicom32 Linux Kernel Port. If not,
15520 + * see <http://www.gnu.org/licenses/>.
15522 + * Ubicom32 implementation derived from (with many thanks):
15527 +#ifndef _ASM_UBICOM32_UCONTEXT_H
15528 +#define _ASM_UBICOM32_UCONTEXT_H
15531 + unsigned long uc_flags;
15532 + struct ucontext *uc_link;
15533 + stack_t uc_stack;
15534 + struct sigcontext uc_mcontext;
15535 + sigset_t uc_sigmask; /* mask last for extensibility */
15538 +#endif /* _ASM_UBICOM32_UCONTEXT_H */
15540 +++ b/arch/ubicom32/include/asm/unaligned.h
15543 + * arch/ubicom32/include/asm/unaligned.h
15544 + * Ubicom32 architecture unaligned memory access definitions.
15546 + * (C) Copyright 2009, Ubicom, Inc.
15548 + * This file is part of the Ubicom32 Linux Kernel Port.
15550 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
15551 + * it and/or modify it under the terms of the GNU General Public License
15552 + * as published by the Free Software Foundation, either version 2 of the
15553 + * License, or (at your option) any later version.
15555 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15556 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
15557 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15558 + * the GNU General Public License for more details.
15560 + * You should have received a copy of the GNU General Public License
15561 + * along with the Ubicom32 Linux Kernel Port. If not,
15562 + * see <http://www.gnu.org/licenses/>.
15564 + * Ubicom32 implementation derived from (with many thanks):
15569 + * TODO: This is a copy of arm unaligned handling that probably needs
15570 + * to be optimized for UBICOM32, but it works for now.
15573 +#ifndef _ASM_UBICOM32_UNALIGNED_H
15574 +#define _ASM_UBICOM32_UNALIGNED_H
15576 +#include <asm/types.h>
15578 +#include <linux/unaligned/le_byteshift.h>
15579 +#include <linux/unaligned/be_byteshift.h>
15580 +#include <linux/unaligned/generic.h>
15582 +#define get_unaligned __get_unaligned_be
15583 +#define put_unaligned __put_unaligned_be
15585 +#endif /* _ASM_UBICOM32_UNALIGNED_H */
15587 +++ b/arch/ubicom32/include/asm/unistd.h
15590 + * arch/ubicom32/include/asm/unistd.h
15591 + * Ubicom32 architecture syscall definitions.
15593 + * (C) Copyright 2009, Ubicom, Inc.
15595 + * This file is part of the Ubicom32 Linux Kernel Port.
15597 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
15598 + * it and/or modify it under the terms of the GNU General Public License
15599 + * as published by the Free Software Foundation, either version 2 of the
15600 + * License, or (at your option) any later version.
15602 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15603 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
15604 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15605 + * the GNU General Public License for more details.
15607 + * You should have received a copy of the GNU General Public License
15608 + * along with the Ubicom32 Linux Kernel Port. If not,
15609 + * see <http://www.gnu.org/licenses/>.
15611 + * Ubicom32 implementation derived from (with many thanks):
15616 +#ifndef _ASM_UBICOM32_UNISTD_H
15617 +#define _ASM_UBICOM32_UNISTD_H
15620 + * This file contains the system call numbers.
15623 +#define __NR_restart_syscall 0
15624 +#define __NR_exit 1
15625 +#define __NR_fork 2
15626 +#define __NR_read 3
15627 +#define __NR_write 4
15628 +#define __NR_open 5
15629 +#define __NR_close 6
15630 +#define __NR_waitpid 7
15631 +#define __NR_creat 8
15632 +#define __NR_link 9
15633 +#define __NR_unlink 10
15634 +#define __NR_execve 11
15635 +#define __NR_chdir 12
15636 +#define __NR_time 13
15637 +#define __NR_mknod 14
15638 +#define __NR_chmod 15
15639 +#define __NR_chown 16
15640 +#define __NR_break 17
15641 +#define __NR_oldstat 18
15642 +#define __NR_lseek 19
15643 +#define __NR_getpid 20
15644 +#define __NR_mount 21
15645 +#define __NR_umount 22
15646 +#define __NR_setuid 23
15647 +#define __NR_getuid 24
15648 +#define __NR_stime 25
15649 +#define __NR_ptrace 26
15650 +#define __NR_alarm 27
15651 +#define __NR_oldfstat 28
15652 +#define __NR_pause 29
15653 +#define __NR_utime 30
15654 +#define __NR_stty 31
15655 +#define __NR_gtty 32
15656 +#define __NR_access 33
15657 +#define __NR_nice 34
15658 +#define __NR_ftime 35
15659 +#define __NR_sync 36
15660 +#define __NR_kill 37
15661 +#define __NR_rename 38
15662 +#define __NR_mkdir 39
15663 +#define __NR_rmdir 40
15664 +#define __NR_dup 41
15665 +#define __NR_pipe 42
15666 +#define __NR_times 43
15667 +#define __NR_prof 44
15668 +#define __NR_brk 45
15669 +#define __NR_setgid 46
15670 +#define __NR_getgid 47
15671 +#define __NR_signal 48
15672 +#define __NR_geteuid 49
15673 +#define __NR_getegid 50
15674 +#define __NR_acct 51
15675 +#define __NR_umount2 52
15676 +#define __NR_lock 53
15677 +#define __NR_ioctl 54
15678 +#define __NR_fcntl 55
15679 +#define __NR_mpx 56
15680 +#define __NR_setpgid 57
15681 +#define __NR_ulimit 58
15682 +#define __NR_oldolduname 59
15683 +#define __NR_umask 60
15684 +#define __NR_chroot 61
15685 +#define __NR_ustat 62
15686 +#define __NR_dup2 63
15687 +#define __NR_getppid 64
15688 +#define __NR_getpgrp 65
15689 +#define __NR_setsid 66
15690 +#define __NR_sigaction 67
15691 +#define __NR_sgetmask 68
15692 +#define __NR_ssetmask 69
15693 +#define __NR_setreuid 70
15694 +#define __NR_setregid 71
15695 +#define __NR_sigsuspend 72
15696 +#define __NR_sigpending 73
15697 +#define __NR_sethostname 74
15698 +#define __NR_setrlimit 75
15699 +#define __NR_getrlimit 76
15700 +#define __NR_getrusage 77
15701 +#define __NR_gettimeofday 78
15702 +#define __NR_settimeofday 79
15703 +#define __NR_getgroups 80
15704 +#define __NR_setgroups 81
15705 +#define __NR_select 82
15706 +#define __NR_symlink 83
15707 +#define __NR_oldlstat 84
15708 +#define __NR_readlink 85
15709 +#define __NR_uselib 86
15710 +#define __NR_swapon 87
15711 +#define __NR_reboot 88
15712 +#define __NR_readdir 89
15713 +#define __NR_mmap 90
15714 +#define __NR_munmap 91
15715 +#define __NR_truncate 92
15716 +#define __NR_ftruncate 93
15717 +#define __NR_fchmod 94
15718 +#define __NR_fchown 95
15719 +#define __NR_getpriority 96
15720 +#define __NR_setpriority 97
15721 +#define __NR_profil 98
15722 +#define __NR_statfs 99
15723 +#define __NR_fstatfs 100
15724 +#define __NR_ioperm 101
15725 +#define __NR_socketcall 102
15726 +#define __NR_syslog 103
15727 +#define __NR_setitimer 104
15728 +#define __NR_getitimer 105
15729 +#define __NR_stat 106
15730 +#define __NR_lstat 107
15731 +#define __NR_fstat 108
15732 +#define __NR_olduname 109
15733 +#define __NR_iopl /* 110 */ not supported
15734 +#define __NR_vhangup 111
15735 +#define __NR_idle /* 112 */ Obsolete
15736 +#define __NR_vm86 /* 113 */ not supported
15737 +#define __NR_wait4 114
15738 +#define __NR_swapoff 115
15739 +#define __NR_sysinfo 116
15740 +#define __NR_ipc 117
15741 +#define __NR_fsync 118
15742 +#define __NR_sigreturn 119
15743 +#define __NR_clone 120
15744 +#define __NR_setdomainname 121
15745 +#define __NR_uname 122
15746 +#define __NR_cacheflush 123
15747 +#define __NR_adjtimex 124
15748 +#define __NR_mprotect 125
15749 +#define __NR_sigprocmask 126
15750 +#define __NR_create_module 127
15751 +#define __NR_init_module 128
15752 +#define __NR_delete_module 129
15753 +#define __NR_get_kernel_syms 130
15754 +#define __NR_quotactl 131
15755 +#define __NR_getpgid 132
15756 +#define __NR_fchdir 133
15757 +#define __NR_bdflush 134
15758 +#define __NR_sysfs 135
15759 +#define __NR_personality 136
15760 +#define __NR_afs_syscall 137 /* Syscall for Andrew File System */
15761 +#define __NR_setfsuid 138
15762 +#define __NR_setfsgid 139
15763 +#define __NR__llseek 140
15764 +#define __NR_getdents 141
15765 +#define __NR__newselect 142
15766 +#define __NR_flock 143
15767 +#define __NR_msync 144
15768 +#define __NR_readv 145
15769 +#define __NR_writev 146
15770 +#define __NR_getsid 147
15771 +#define __NR_fdatasync 148
15772 +#define __NR__sysctl 149
15773 +#define __NR_mlock 150
15774 +#define __NR_munlock 151
15775 +#define __NR_mlockall 152
15776 +#define __NR_munlockall 153
15777 +#define __NR_sched_setparam 154
15778 +#define __NR_sched_getparam 155
15779 +#define __NR_sched_setscheduler 156
15780 +#define __NR_sched_getscheduler 157
15781 +#define __NR_sched_yield 158
15782 +#define __NR_sched_get_priority_max 159
15783 +#define __NR_sched_get_priority_min 160
15784 +#define __NR_sched_rr_get_interval 161
15785 +#define __NR_nanosleep 162
15786 +#define __NR_mremap 163
15787 +#define __NR_setresuid 164
15788 +#define __NR_getresuid 165
15789 +#define __NR_getpagesize 166
15790 +#define __NR_query_module 167
15791 +#define __NR_poll 168
15792 +#define __NR_nfsservctl 169
15793 +#define __NR_setresgid 170
15794 +#define __NR_getresgid 171
15795 +#define __NR_prctl 172
15796 +#define __NR_rt_sigreturn 173
15797 +#define __NR_rt_sigaction 174
15798 +#define __NR_rt_sigprocmask 175
15799 +#define __NR_rt_sigpending 176
15800 +#define __NR_rt_sigtimedwait 177
15801 +#define __NR_rt_sigqueueinfo 178
15802 +#define __NR_rt_sigsuspend 179
15803 +#define __NR_pread64 180
15804 +#define __NR_pwrite64 181
15805 +#define __NR_lchown 182
15806 +#define __NR_getcwd 183
15807 +#define __NR_capget 184
15808 +#define __NR_capset 185
15809 +#define __NR_sigaltstack 186
15810 +#define __NR_sendfile 187
15811 +#define __NR_getpmsg 188 /* some people actually want streams */
15812 +#define __NR_putpmsg 189 /* some people actually want streams */
15813 +#define __NR_vfork 190
15814 +#define __NR_ugetrlimit 191
15815 +#define __NR_mmap2 192
15816 +#define __NR_truncate64 193
15817 +#define __NR_ftruncate64 194
15818 +#define __NR_stat64 195
15819 +#define __NR_lstat64 196
15820 +#define __NR_fstat64 197
15821 +#define __NR_chown32 198
15822 +#define __NR_getuid32 199
15823 +#define __NR_getgid32 200
15824 +#define __NR_geteuid32 201
15825 +#define __NR_getegid32 202
15826 +#define __NR_setreuid32 203
15827 +#define __NR_setregid32 204
15828 +#define __NR_getgroups32 205
15829 +#define __NR_setgroups32 206
15830 +#define __NR_fchown32 207
15831 +#define __NR_setresuid32 208
15832 +#define __NR_getresuid32 209
15833 +#define __NR_setresgid32 210
15834 +#define __NR_getresgid32 211
15835 +#define __NR_lchown32 212
15836 +#define __NR_setuid32 213
15837 +#define __NR_setgid32 214
15838 +#define __NR_setfsuid32 215
15839 +#define __NR_setfsgid32 216
15840 +#define __NR_pivot_root 217
15841 +#define __NR_getdents64 220
15842 +#define __NR_gettid 221
15843 +#define __NR_tkill 222
15844 +#define __NR_setxattr 223
15845 +#define __NR_lsetxattr 224
15846 +#define __NR_fsetxattr 225
15847 +#define __NR_getxattr 226
15848 +#define __NR_lgetxattr 227
15849 +#define __NR_fgetxattr 228
15850 +#define __NR_listxattr 229
15851 +#define __NR_llistxattr 230
15852 +#define __NR_flistxattr 231
15853 +#define __NR_removexattr 232
15854 +#define __NR_lremovexattr 233
15855 +#define __NR_fremovexattr 234
15856 +#define __NR_futex 235
15857 +#define __NR_sendfile64 236
15858 +#define __NR_mincore 237
15859 +#define __NR_madvise 238
15860 +#define __NR_fcntl64 239
15861 +#define __NR_readahead 240
15862 +#define __NR_io_setup 241
15863 +#define __NR_io_destroy 242
15864 +#define __NR_io_getevents 243
15865 +#define __NR_io_submit 244
15866 +#define __NR_io_cancel 245
15867 +#define __NR_fadvise64 246
15868 +#define __NR_exit_group 247
15869 +#define __NR_lookup_dcookie 248
15870 +#define __NR_epoll_create 249
15871 +#define __NR_epoll_ctl 250
15872 +#define __NR_epoll_wait 251
15873 +#define __NR_remap_file_pages 252
15874 +#define __NR_set_tid_address 253
15875 +#define __NR_timer_create 254
15876 +#define __NR_timer_settime 255
15877 +#define __NR_timer_gettime 256
15878 +#define __NR_timer_getoverrun 257
15879 +#define __NR_timer_delete 258
15880 +#define __NR_clock_settime 259
15881 +#define __NR_clock_gettime 260
15882 +#define __NR_clock_getres 261
15883 +#define __NR_clock_nanosleep 262
15884 +#define __NR_statfs64 263
15885 +#define __NR_fstatfs64 264
15886 +#define __NR_tgkill 265
15887 +#define __NR_utimes 266
15888 +#define __NR_fadvise64_64 267
15889 +#define __NR_mbind 268
15890 +#define __NR_get_mempolicy 269
15891 +#define __NR_set_mempolicy 270
15892 +#define __NR_mq_open 271
15893 +#define __NR_mq_unlink 272
15894 +#define __NR_mq_timedsend 273
15895 +#define __NR_mq_timedreceive 274
15896 +#define __NR_mq_notify 275
15897 +#define __NR_mq_getsetattr 276
15898 +#define __NR_waitid 277
15899 +#define __NR_vserver 278
15900 +#define __NR_add_key 279
15901 +#define __NR_request_key 280
15902 +#define __NR_keyctl 281
15903 +#define __NR_ioprio_set 282
15904 +#define __NR_ioprio_get 283
15905 +#define __NR_inotify_init 284
15906 +#define __NR_inotify_add_watch 285
15907 +#define __NR_inotify_rm_watch 286
15908 +#define __NR_migrate_pages 287
15909 +#define __NR_openat 288
15910 +#define __NR_mkdirat 289
15911 +#define __NR_mknodat 290
15912 +#define __NR_fchownat 291
15913 +#define __NR_futimesat 292
15914 +#define __NR_fstatat64 293
15915 +#define __NR_unlinkat 294
15916 +#define __NR_renameat 295
15917 +#define __NR_linkat 296
15918 +#define __NR_symlinkat 297
15919 +#define __NR_readlinkat 298
15920 +#define __NR_fchmodat 299
15921 +#define __NR_faccessat 300
15922 +#define __NR_pselect6 301
15923 +#define __NR_ppoll 302
15924 +#define __NR_unshare 303
15925 +#define __NR_set_robust_list 304
15926 +#define __NR_get_robust_list 305
15927 +#define __NR_splice 306
15928 +#define __NR_sync_file_range 307
15929 +#define __NR_tee 308
15930 +#define __NR_vmsplice 309
15931 +#define __NR_move_pages 310
15932 +#define __NR_sched_setaffinity 311
15933 +#define __NR_sched_getaffinity 312
15934 +#define __NR_kexec_load 313
15935 +#define __NR_getcpu 314
15936 +#define __NR_epoll_pwait 315
15937 +#define __NR_utimensat 316
15938 +#define __NR_signalfd 317
15939 +#define __NR_timerfd_create 318
15940 +#define __NR_eventfd 319
15941 +#define __NR_fallocate 320
15942 +#define __NR_timerfd_settime 321
15943 +#define __NR_timerfd_gettime 322
15944 +#define __NR_signalfd4 323
15945 +#define __NR_eventfd2 324
15946 +#define __NR_epoll_create1 325
15947 +#define __NR_dup3 326
15948 +#define __NR_pipe2 327
15949 +#define __NR_inotify_init1 328
15953 +#define NR_syscalls 329
15955 +#define __ARCH_WANT_IPC_PARSE_VERSION
15956 +#define __ARCH_WANT_OLD_READDIR
15957 +#define __ARCH_WANT_OLD_STAT
15958 +#define __ARCH_WANT_STAT64
15959 +#define __ARCH_WANT_SYS_ALARM
15960 +#define __ARCH_WANT_SYS_GETHOSTNAME
15961 +#define __ARCH_WANT_SYS_PAUSE
15962 +#define __ARCH_WANT_SYS_SGETMASK
15963 +#define __ARCH_WANT_SYS_SIGNAL
15964 +#define __ARCH_WANT_SYS_TIME
15965 +#define __ARCH_WANT_SYS_UTIME
15966 +#define __ARCH_WANT_SYS_WAITPID
15967 +#define __ARCH_WANT_SYS_SOCKETCALL
15968 +#define __ARCH_WANT_SYS_FADVISE64
15969 +#define __ARCH_WANT_SYS_GETPGRP
15970 +#define __ARCH_WANT_SYS_LLSEEK
15971 +#define __ARCH_WANT_SYS_NICE
15972 +#define __ARCH_WANT_SYS_OLD_GETRLIMIT
15973 +#define __ARCH_WANT_SYS_OLDUMOUNT
15974 +#define __ARCH_WANT_SYS_SIGPENDING
15975 +#define __ARCH_WANT_SYS_SIGPROCMASK
15976 +#define __ARCH_WANT_SYS_RT_SIGACTION
15979 + * "Conditional" syscalls
15981 + * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
15982 + * but it doesn't work on all toolchains, so we just do it by hand
15984 +//#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
15985 +#define cond_syscall(x) long x(void) __attribute__((weak,alias("sys_ni_syscall")))
15986 +#endif /* __KERNEL__ */
15988 +#endif /* _ASM_UBICOM32_UNISTD_H */
15990 +++ b/arch/ubicom32/include/asm/user.h
15993 + * arch/ubicom32/include/asm/user.h
15994 + * Ubicom32 architecture core file definitions.
15996 + * (C) Copyright 2009, Ubicom, Inc.
15998 + * This file is part of the Ubicom32 Linux Kernel Port.
16000 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
16001 + * it and/or modify it under the terms of the GNU General Public License
16002 + * as published by the Free Software Foundation, either version 2 of the
16003 + * License, or (at your option) any later version.
16005 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
16006 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
16007 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
16008 + * the GNU General Public License for more details.
16010 + * You should have received a copy of the GNU General Public License
16011 + * along with the Ubicom32 Linux Kernel Port. If not,
16012 + * see <http://www.gnu.org/licenses/>.
16014 + * Ubicom32 implementation derived from (with many thanks):
16019 +#ifndef _ASM_UBICOM32_USER_H
16020 +#define _ASM_UBICOM32_USER_H
16022 +#include <asm/ptrace.h>
16023 +#include <asm/page.h>
16025 + * Adapted from <asm-powerpc/user.h>
16027 + * Core file format: The core file is written in such a way that gdb
16028 + * can understand it and provide useful information to the user (under
16029 + * linux we use the `trad-core' bfd, NOT the osf-core). The file contents
16030 + * are as follows:
16032 + * upage: 1 page consisting of a user struct that tells gdb
16033 + * what is present in the file. Directly after this is a
16034 + * copy of the task_struct, which is currently not used by gdb,
16035 + * but it may come in handy at some point. All of the registers
16036 + * are stored as part of the upage. The upage should always be
16037 + * only one page long.
16038 + * data: The data segment follows next. We use current->end_text to
16039 + * current->brk to pick up all of the user variables, plus any memory
16040 + * that may have been sbrk'ed. No attempt is made to determine if a
16041 + * page is demand-zero or if a page is totally unused, we just cover
16042 + * the entire range. All of the addresses are rounded in such a way
16043 + * that an integral number of pages is written.
16044 + * stack: We need the stack information in order to get a meaningful
16045 + * backtrace. We need to write the data from usp to
16046 + * current->start_stack, so we round each of these in order to be able
16047 + * to write an integer number of pages.
16050 +struct user_ubicom32fp_struct {
16054 + struct pt_regs regs; /* entire machine state */
16055 + size_t u_tsize; /* text size (pages) */
16056 + size_t u_dsize; /* data size (pages) */
16057 + size_t u_ssize; /* stack size (pages) */
16058 + unsigned long start_code; /* text starting address */
16059 + unsigned long start_data; /* data starting address */
16060 + unsigned long start_stack; /* stack starting address */
16061 + long int signal; /* signal causing core dump */
16062 + unsigned long u_ar0; /* help gdb find registers */
16063 + unsigned long magic; /* identifies a core file */
16064 + char u_comm[32]; /* user command name */
16067 +#define NBPG PAGE_SIZE
16069 +#define HOST_TEXT_START_ADDR (u.start_code)
16070 +#define HOST_DATA_START_ADDR (u.start_data)
16071 +#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG)
16073 +#endif /* _ASM_UBICOM32_USER_H */
16075 +++ b/arch/ubicom32/include/asm/vdc_tio.h
16078 + * arch/ubicom32/include/asm/vdc_tio.h
16079 + * Ubicom32 architecture VDC TIO definitions.
16081 + * (C) Copyright 2009, Ubicom, Inc.
16083 + * This file is part of the Ubicom32 Linux Kernel Port.
16085 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
16086 + * it and/or modify it under the terms of the GNU General Public License
16087 + * as published by the Free Software Foundation, either version 2 of the
16088 + * License, or (at your option) any later version.
16090 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
16091 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
16092 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
16093 + * the GNU General Public License for more details.
16095 + * You should have received a copy of the GNU General Public License
16096 + * along with the Ubicom32 Linux Kernel Port. If not,
16097 + * see <http://www.gnu.org/licenses/>.
16099 + * Ubicom32 implementation derived from (with many thanks):
16104 +#ifndef _ASM_UBICOM32_VDC_TIO_H
16105 +#define _ASM_UBICOM32_VDC_TIO_H
16107 +#include <asm/devtree.h>
16109 +#define VDCTIO_VP_VERSION 5
16111 +#define VDCTIO_SCALE_FLAG_VSUB (1 << 9)
16112 +#define VDCTIO_SCALE_FLAG_YUV_SCAN_ORDER (1 << 8)
16113 +#define VDCTIO_SCALE_FLAG_YUV_BLOCK_ORDER (1 << 7)
16114 +#define VDCTIO_SCALE_FLAG_YUV (1 << 6)
16115 +#define VDCTIO_SCALE_FLAG_VRANGE_16_255 (1 << 5)
16116 +#define VDCTIO_SCALE_FLAG_VRANGE_0_255 (1 << 4)
16117 +#define VDCTIO_SCALE_FLAG_HSUB_2_1 (1 << 3)
16118 +#define VDCTIO_SCALE_FLAG_HSUB_1_1 (1 << 2)
16119 +#define VDCTIO_SCALE_FLAG_SET_FRAME_BUFFER (1 << 1)
16120 +#define VDCTIO_SCALE_FLAG_ENABLE (1 << 0)
16122 +#define VDCTIO_NEXT_FRAME_FLAG_YUV_BIT 0
16123 +#define VDCTIO_NEXT_FRAME_FLAG_YUV (1 << (VDCTIO_NEXT_FRAME_FLAG_YUV_BIT))
16125 +#define VDCTIO_CAPS_SUPPORTS_SCALING (1 << 0)
16127 +#define VDCTIO_COMMAND_START (1 << 3)
16128 +#define VDCTIO_COMMAND_SET_COEFF (1 << 2)
16129 +#define VDCTIO_COMMAND_SET_LUT (1 << 1)
16130 +#define VDCTIO_COMMAND_SET_SCALE_MODE (1 << 0)
16133 + * Command / Data registers to access the VDC
16135 +struct vdc_tio_vp_regs {
16137 + * Version of this TIO register map
16141 + volatile u32_t command;
16144 + * Next frame pointer, when the command VDCTIO_COMMAND_SET_FRAME_BUFFER is set,
16145 + * the vdc will take the pointer here and display it.
16147 + void *next_frame;
16148 + u32_t next_frame_flags;
16151 + * These map directly into the PIXP registers 0x20-0x80.
16152 + * DO NOT change the order of these three variables.
16154 + u32_t red_lut[6];
16155 + u32_t blue_lut[6];
16156 + u32_t green_lut[13];
16159 + * These map directly into the PIXP registers 0x04, 0x08
16165 + * There are used to set the scaling parameters
16171 + u32_t scale_flags;
16174 + * Current frame number, monotonically increasing number
16176 + u32_t frame_number;
16179 + * These variables tell the guest OS what the underlying hardware looks like
16195 + * Devtree node for VDC
16197 +struct vdc_tio_node {
16198 + struct devtree_node dn;
16200 + struct vdc_tio_vp_regs *regs;
16203 +extern void vdc_tio_init(void);
16205 +#endif /* _ASM_UBICOM32_VDC_TIO_H */
16207 +++ b/arch/ubicom32/include/asm/vga.h
16210 + * arch/ubicom32/include/asm/vga.h
16211 + * Ubicom32 low level VGA/frame buffer definitions.
16213 + * (C) Copyright 2009, Ubicom, Inc.
16214 + * (c) 1998 Martin Mares <mj@ucw.cz>
16216 + * This file is part of the Ubicom32 Linux Kernel Port.
16218 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
16219 + * it and/or modify it under the terms of the GNU General Public License
16220 + * as published by the Free Software Foundation, either version 2 of the
16221 + * License, or (at your option) any later version.
16223 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
16224 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
16225 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
16226 + * the GNU General Public License for more details.
16228 + * You should have received a copy of the GNU General Public License
16229 + * along with the Ubicom32 Linux Kernel Port. If not,
16230 + * see <http://www.gnu.org/licenses/>.
16232 + * Ubicom32 implementation derived from (with many thanks):
16238 +#ifndef _ASM_UBICOM32_VGA_H
16239 +#define _ASM_UBICOM32_VGA_H
16241 +#include <asm/byteorder.h>
16244 + * On the PC, we can just recalculate addresses and then
16245 + * access the videoram directly without any black magic.
16248 +#define VGA_MAP_MEM(x, s) (0xb0000000L + (unsigned long)(x))
16250 +#define vga_readb(x) (*(x))
16251 +#define vga_writeb(x, y) (*(y) = (x))
16253 +#define VT_BUF_HAVE_RW
16255 + * These are only needed for supporting VGA or MDA text mode, which use little
16256 + * endian byte ordering.
16257 + * In other cases, we can optimize by using native byte ordering and
16258 + * <linux/vt_buffer.h> has already done the right job for us.
16264 +static inline void scr_writew(u16 val, volatile u16 *addr)
16266 + *addr = cpu_to_le16(val);
16269 +static inline u16 scr_readw(volatile const u16 *addr)
16271 + return le16_to_cpu(*addr);
16274 +#define scr_memcpyw(d, s, c) memcpy(d, s, c)
16275 +#define scr_memmovew(d, s, c) memmove(d, s, c)
16276 +#define VT_BUF_HAVE_MEMCPYW
16277 +#define VT_BUF_HAVE_MEMMOVEW
16279 +#endif /* _ASM_UBICOM32_VGA_H */
16281 +++ b/arch/ubicom32/include/asm/xor.h
16284 + * arch/ubicom32/include/asm/xor.h
16285 + * Generic xor.h definitions for Ubicom32 architecture.
16287 + * (C) Copyright 2009, Ubicom, Inc.
16289 + * This file is part of the Ubicom32 Linux Kernel Port.
16291 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
16292 + * it and/or modify it under the terms of the GNU General Public License
16293 + * as published by the Free Software Foundation, either version 2 of the
16294 + * License, or (at your option) any later version.
16296 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
16297 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
16298 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
16299 + * the GNU General Public License for more details.
16301 + * You should have received a copy of the GNU General Public License
16302 + * along with the Ubicom32 Linux Kernel Port. If not,
16303 + * see <http://www.gnu.org/licenses/>.
16305 + * Ubicom32 implementation derived from (with many thanks):
16310 +#ifndef _ASM_UBICOM32_XOR_H
16311 +#define _ASM_UBICOM32_XOR_H
16313 +#include <asm-generic/xor.h>
16315 +#endif /* _ASM_UBICOM32_XOR_H */
16317 +++ b/arch/ubicom32/Kconfig
16320 +# For a description of the syntax of this configuration file,
16321 +# see Documentation/kbuild/kconfig-language.txt.
16324 +mainmenu "uClinux/ubicom32 (w/o MMU) Kernel Configuration"
16328 + select HAVE_OPROFILE
16335 +config CPU_BIG_ENDIAN
16339 +config FORCE_MAX_ZONEORDER
16359 +config RWSEM_GENERIC_SPINLOCK
16363 +config RWSEM_XCHGADD_ALGORITHM
16367 +config ARCH_HAS_ILOG2_U32
16371 +config ARCH_HAS_ILOG2_U64
16375 +config GENERIC_FIND_NEXT_BIT
16379 +config GENERIC_GPIO
16387 +config GENERIC_HWEIGHT
16391 +config GENERIC_HARDIRQS
16395 +config STACKTRACE_SUPPORT
16399 +config LOCKDEP_SUPPORT
16403 +config GENERIC_CALIBRATE_DELAY
16407 +config GENERIC_TIME
16411 +config TIME_LOW_RES
16415 +config GENERIC_CLOCKEVENTS
16419 +config GENERIC_CLOCKEVENTS_BROADCAST
16421 + depends on GENERIC_CLOCKEVENTS
16422 + default y if SMP && !LOCAL_TIMERS
16427 +config ARCH_SUPPORTS_AOUT
16430 +config IRQ_PER_CPU
16434 +config SCHED_NO_NO_OMIT_FRAME_POINTER
16438 +config UBICOM32_PLIO
16442 +menu "Processor type and features"
16444 +comment "Processor type will be selected by Board"
16446 +config UBICOM32_V3
16449 + Ubicom IP5xxx series processor support.
16451 +config UBICOM32_V4
16454 + Ubicom IP7xxx series processor support.
16458 + prompt "Board type"
16460 + Select your board.
16463 + bool "No board selected"
16465 + Default. Don't select any board specific config. Will not build unless you change!
16467 +# Add your boards here
16468 +source "arch/ubicom32/mach-ip5k/Kconfig"
16469 +source "arch/ubicom32/mach-ip7k/Kconfig"
16473 +comment "Kernel Options"
16475 + bool "Symmetric multi-processing support"
16476 + select USE_GENERIC_SMP_HELPERS
16479 + Enables multithreading support. Enabling SMP support increases
16480 + the size of system data structures. SMP support can have either
16481 + positive or negative impact on performance depending on workloads.
16483 + If you do not know what to do here, say N.
16484 +config OLD_40400010_SYSTEM_CALL
16485 + bool "Provide old system call interface at 0x40400010"
16488 + Provides the old system call interface, does not affect the
16489 + new system_call interface.
16492 + int "Number of configured CPUs"
16497 + Upper bound on the number of CPUs. Space is reserved
16498 + at compile time for this many CPUs.
16500 +config LOCAL_TIMERS
16501 + bool "Use local timer interrupts"
16505 + Enable support for local timers on SMP platforms, rather then the
16506 + legacy IPI broadcast method. Local timers allows the system
16507 + accounting to be spread across the timer interval, preventing a
16508 + "thundering herd" at every timer tick. A physical timer is allocated
16511 +config TIMER_EXTRA_ALLOC
16512 + int "Number of additional physical timer events to create"
16513 + depends on GENERIC_CLOCKEVENTS
16516 + The Ubicom32 processor has a number of event timers that can be wrapped
16517 + in Linux clock event structures (assuming that the timers are not being
16518 + used for another purpose). Based on the value of LOCAL_TIMERS, either
16519 + 2 timers will be used or a timer will be used for every CPU. This value
16520 + allows the programmer to select additional timers over that amount.
16523 + bool "Create separate stacks for interrupt handling"
16526 + Selecting this causes interrupts to be created on a separate
16527 + stack instead of nesting the interrupts on the kernel stack.
16529 +config IRQSTACKS_USEOCM
16530 + bool "Use OCM for interrupt stacks"
16532 + depends on IRQSTACKS
16534 + Selecting this cause the interrupt stacks to be placed in OCM
16535 + reducing cache misses at the expense of using the OCM for servicing
16538 +menu "OCM Instruction Heap"
16540 +config OCM_MODULES_RESERVATION
16541 + int "OCM Instruction heap reservation. 0-192 kB"
16545 + The minimum amount of OCM memory to reserve for kernel loadable module
16546 + code. If you are not using this memory it cannot be used for anything
16547 + else. Leave it as 0 if you have prebuilt modules that are compiled with
16550 +config OCM_MODULES_MAY_CONSUME_REMAINING_CODESPACE
16551 + bool "Give all unused ocm code space to the ocm instruction heap."
16554 + Allow the OCM instruction heap allocation to consume any remaining
16555 + unused OCM code space. The result of this is that you will not have
16556 + and deterministic results, but you will not have any waste either.
16558 +config OCM_MODULES_FALLBACK_TO_DDR
16559 + bool "Loadable Modules requiring OCM may fallback to use DDR."
16562 + If a module cannot get the OCM code it requires allow DDR to
16567 + int "Frequency of 'jiffies' (for polling)"
16570 + 100 is common for embedded systems, but 1000 allows
16571 + you to do more drivers without actually having
16572 + interrupts working properly.
16574 +comment "RAM configuration"
16576 +config MIN_RAMSIZE
16577 + hex "Minimum Size of RAM (in bytes)"
16578 + range 0x01000000 0x08000000
16579 + default "0x02000000"
16581 + Define the minimum acceptable size of the system
16582 + RAM. Must be at least 16MB (0x01000000)
16584 +comment "Build options"
16585 +config LINKER_RELAXATION
16586 + bool "Linker Relaxation"
16589 + Turns on linker relaxation that will produce smaller
16590 + faster code. Increases link time.
16592 +comment "Driver options"
16598 + Enable/Disable PCI bus
16599 + source "drivers/pci/Kconfig"
16602 +config PCI_DEV0_IDSEL
16603 + hex "slot 0 address"
16605 + default "0x01000000"
16607 + Slot 0 address. This address should correspond to the address line
16608 + which the IDSEL bit for this slot is connected to.
16610 +config PCI_DEV1_IDSEL
16611 + hex "slot 1 address"
16613 + default "0x02000000"
16615 + Slot 1 address. This address should correspond to the address line
16616 + which the IDSEL bit for this slot is connected to.
16620 +menu "Input devices"
16621 +config UBICOM_INPUT
16622 + bool "Ubicom polled GPIO input driver"
16624 + select INPUT_POLLDEV
16626 + Polling input driver, much like the GPIO input driver, except that it doesn't
16627 + rely on interrupts. It will report events via the input subsystem.
16630 +config UBICOM_INPUT_I2C
16631 + bool "Ubicom polled GPIO input driver over I2C"
16633 + select INPUT_POLLDEV
16635 + Polling input driver, much like the PCA953x driver, it can support a variety of
16636 + different I2C I/O expanders. This device polls the I2C I/O expander for events
16637 + and reports them via the input subsystem.
16642 +source "arch/ubicom32/mach-common/Kconfig.switch"
16644 +menu "Misc devices"
16646 + bool "Ubicom HID driver"
16648 + select INPUT_POLLDEV
16649 + select LCD_CLASS_DEVICE
16651 + Driver for HID chip found on some Ubicom reference designs. This chip handles
16652 + PWM, button input, and IR remote control. It registers as an input device and
16653 + a backlight device.
16658 +config CMDLINE_BOOL
16659 + bool "Built-in kernel command line"
16662 + Allow for specifying boot arguments to the kernel at
16663 + build time. On some systems (e.g. embedded ones), it is
16664 + necessary or convenient to provide some or all of the
16665 + kernel boot arguments with the kernel itself (that is,
16666 + to not rely on the boot loader to provide them.)
16668 + To compile command line arguments into the kernel,
16669 + set this option to 'Y', then fill in the
16670 + the boot arguments in CONFIG_CMDLINE.
16672 + Systems with fully functional boot loaders (i.e. non-embedded)
16673 + should leave this option set to 'N'.
16676 + string "Built-in kernel command string"
16677 + depends on CMDLINE_BOOL
16680 + Enter arguments here that should be compiled into the kernel
16681 + image and used at boot time. If the boot loader provides a
16682 + command line at boot time, it is appended to this string to
16683 + form the full kernel command line, when the system boots.
16685 + However, you can use the CONFIG_CMDLINE_OVERRIDE option to
16686 + change this behavior.
16688 + In most cases, the command line (whether built-in or provided
16689 + by the boot loader) should specify the device for the root
16692 +config CMDLINE_OVERRIDE
16693 + bool "Built-in command line overrides boot loader arguments"
16695 + depends on CMDLINE_BOOL
16697 + Set this option to 'Y' to have the kernel ignore the boot loader
16698 + command line, and use ONLY the built-in command line.
16700 + This is used to work around broken boot loaders. This should
16701 + be set to 'N' under normal conditions.
16704 +# End Processor type and features
16706 +source "arch/ubicom32/Kconfig.debug"
16708 +menu "Executable file formats"
16709 +source "fs/Kconfig.binfmt"
16712 +source "init/Kconfig"
16713 +source "kernel/Kconfig.preempt"
16714 +source "kernel/time/Kconfig"
16715 +source "mm/Kconfig"
16716 +source "net/Kconfig"
16717 +source "drivers/Kconfig"
16718 +source "fs/Kconfig"
16719 +source "security/Kconfig"
16720 +source "crypto/Kconfig"
16721 +source "lib/Kconfig"
16723 +++ b/arch/ubicom32/Kconfig.debug
16725 +menu "Kernel hacking"
16727 +config TRACE_IRQFLAGS_SUPPORT
16730 +config DEBUG_VERBOSE
16731 + bool "Verbose fault messages"
16735 + When a program crashes due to an exception, or the kernel detects
16736 + an internal error, the kernel can print a not so brief message
16737 + explaining what the problem was. This debugging information is
16738 + useful to developers and kernel hackers when tracking down problems,
16739 + but mostly meaningless to other people. This is always helpful for
16740 + debugging but serves no purpose on a production system.
16741 + Most people should say N here.
16743 +config PROTECT_KERNEL
16745 + bool 'Enable Kernel range register Protection'
16747 + Adds code to enable/disable range registers to protect static
16748 + kernel code/data from userspace. Currently the ranges covered
16749 + do no protect kernel loadable modules or dynamically allocated
16752 +config NO_KERNEL_MSG
16753 + bool "Suppress Kernel BUG Messages"
16755 + Do not output any debug BUG messages within the kernel.
16757 +config EARLY_PRINTK
16758 + bool "Use the driver that you selected as console also for early printk (to debug kernel bootup)."
16761 + If you want to use the serdes driver (console=ttyUS0) for
16762 + early printk, you must also supply an additional kernel boot
16763 + parameter like this:
16765 + serdes=ioportaddr,irq,clockrate,baud
16767 + For an IP7160RGW eval board, you could use this:
16769 + serdes=0x2004000,61,250000000,57600
16771 + which will let you see early printk output at 57600 baud.
16773 +config STOP_ON_TRAP
16774 + bool "Enable stopping at the LDSR for all traps"
16777 + Cause the LDSR to stop all threads whenever a trap is about to be serviced
16779 +config STOP_ON_BUG
16780 + bool "Enable stopping on failed BUG_ON()"
16783 + Cause all BUG_ON failures to stop all threads
16785 +config DEBUG_IRQMEASURE
16786 + bool "Enable IRQ handler measurements"
16789 + When enabled each IRQ's min/avg/max times will be printed. If the handler
16790 + re-enables interrupt, the times will show the full time including to service
16791 + nested interrupts. See /proc/irq_measurements.
16793 +config DEBUG_PCIMEASURE
16794 + bool "Enable PCI transaction measurements"
16797 + When enabled the system will measure the min/avg/max timer for each PCI transactions.
16798 + See /proc/pci_measurements.
16800 +config ACCESS_OK_CHECKS_ENABLED
16801 + bool "Enable user space access checks"
16804 + Enabling this check causes the kernel to verify that addresses passed
16805 + to the kernel by the user space code are within the processes
16806 + address space. On a no-mmu system, this is done by examining the
16807 + processes memory data structures (adversly affecting performance) but
16808 + ensuring that a process does not ask the kernel to violate another
16809 + processes address space. Sadly, the kernel uses access_ok() for
16810 + address that are in the kernel which results in a large volume of
16814 + prompt "Unaligned Access Support"
16815 + default UNALIGNED_ACCESS_ENABLED
16817 + Kernel / Userspace unaligned access handling.
16819 +config UNALIGNED_ACCESS_ENABLED
16820 + bool "Kernel and Userspace"
16823 +config UNALIGNED_ACCESS_USERSPACE_ONLY
16824 + bool "Userspace Only"
16827 +config UNALIGNED_ACCESS_DISABLED
16833 +config DEBUG_STACKOVERFLOW
16834 + bool "Check for stack overflows"
16836 + depends on DEBUG_KERNEL
16838 + This option will cause messages to be printed if free kernel stack space
16839 + drops below a certain limit (THREAD_SIZE /8).
16841 +config DEBUG_STACK_USAGE
16842 + bool "Stack utilization instrumentation"
16844 + depends on DEBUG_KERNEL
16846 + Enables the display of the minimum amount of free kernel stack which each
16847 + task has ever had available in the sysrq-T and sysrq-P debug output.
16849 + This option will slow down process creation somewhat.
16851 +source "lib/Kconfig.debug"
16855 +++ b/arch/ubicom32/kernel/asm-offsets.c
16858 + * arch/ubicom32/kernel/asm-offsets.c
16859 + * Ubicom32 architecture definitions needed by assembly language modules.
16861 + * (C) Copyright 2009, Ubicom, Inc.
16863 + * This file is part of the Ubicom32 Linux Kernel Port.
16865 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
16866 + * it and/or modify it under the terms of the GNU General Public License
16867 + * as published by the Free Software Foundation, either version 2 of the
16868 + * License, or (at your option) any later version.
16870 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
16871 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
16872 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
16873 + * the GNU General Public License for more details.
16875 + * You should have received a copy of the GNU General Public License
16876 + * along with the Ubicom32 Linux Kernel Port. If not,
16877 + * see <http://www.gnu.org/licenses/>.
16879 + * Ubicom32 implementation derived from (with many thanks):
16885 + * This program is used to generate definitions needed by
16886 + * assembly language modules.
16888 + * We use the technique used in the OSF Mach kernel code:
16889 + * generate asm statements containing #defines,
16890 + * compile this file to assembler, and then extract the
16891 + * #defines from the assembly-language output.
16894 +#include <linux/module.h>
16895 +#include <linux/stddef.h>
16896 +#include <linux/sched.h>
16897 +#include <linux/kernel_stat.h>
16898 +#include <linux/ptrace.h>
16899 +#include <linux/hardirq.h>
16900 +#include <asm/bootinfo.h>
16901 +#include <asm/irq.h>
16902 +#include <asm/thread_info.h>
16904 +#define DEFINE(sym, val) \
16905 + asm volatile("\n->" #sym " %0 " #val : : "i" (val))
16907 +#define BLANK() asm volatile("\n->" : : )
16911 + /* offsets into the task struct */
16912 + DEFINE(TASK_STATE, offsetof(struct task_struct, state));
16913 + DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags));
16914 + DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace));
16915 + DEFINE(TASK_BLOCKED, offsetof(struct task_struct, blocked));
16916 + DEFINE(TASK_THREAD, offsetof(struct task_struct, thread));
16917 + DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, stack));
16918 + DEFINE(TASK_MM, offsetof(struct task_struct, mm));
16919 + DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm));
16921 + /* offsets into the kernel_stat struct */
16922 +// DEFINE(STAT_IRQ, offsetof(struct kernel_stat, irqs));
16924 + /* offsets into the irq_cpustat_t struct */
16925 + DEFINE(CPUSTAT_SOFTIRQ_PENDING, offsetof(irq_cpustat_t, __softirq_pending));
16927 + /* offsets into the thread struct */
16928 + DEFINE(THREAD_D10, offsetof(struct thread_struct, d10));
16929 + DEFINE(THREAD_D11, offsetof(struct thread_struct, d11));
16930 + DEFINE(THREAD_D12, offsetof(struct thread_struct, d12));
16931 + DEFINE(THREAD_D13, offsetof(struct thread_struct, d13));
16932 + DEFINE(THREAD_A1, offsetof(struct thread_struct, a1));
16933 + DEFINE(THREAD_A2, offsetof(struct thread_struct, a2));
16934 + DEFINE(THREAD_A5, offsetof(struct thread_struct, a5));
16935 + DEFINE(THREAD_A6, offsetof(struct thread_struct, a6));
16936 + DEFINE(THREAD_SP, offsetof(struct thread_struct, sp));
16938 + /* offsets into the pt_regs */
16939 + DEFINE(PT_D0, offsetof(struct pt_regs, dn[0]));
16940 + DEFINE(PT_D1, offsetof(struct pt_regs, dn[1]));
16941 + DEFINE(PT_D2, offsetof(struct pt_regs, dn[2]));
16942 + DEFINE(PT_D3, offsetof(struct pt_regs, dn[3]));
16943 + DEFINE(PT_D4, offsetof(struct pt_regs, dn[4]));
16944 + DEFINE(PT_D5, offsetof(struct pt_regs, dn[5]));
16945 + DEFINE(PT_D6, offsetof(struct pt_regs, dn[6]));
16946 + DEFINE(PT_D7, offsetof(struct pt_regs, dn[7]));
16947 + DEFINE(PT_D8, offsetof(struct pt_regs, dn[8]));
16948 + DEFINE(PT_D9, offsetof(struct pt_regs, dn[9]));
16949 + DEFINE(PT_D10, offsetof(struct pt_regs, dn[10]));
16950 + DEFINE(PT_D11, offsetof(struct pt_regs, dn[11]));
16951 + DEFINE(PT_D12, offsetof(struct pt_regs, dn[12]));
16952 + DEFINE(PT_D13, offsetof(struct pt_regs, dn[13]));
16953 + DEFINE(PT_D14, offsetof(struct pt_regs, dn[14]));
16954 + DEFINE(PT_D15, offsetof(struct pt_regs, dn[15]));
16955 + DEFINE(PT_A0, offsetof(struct pt_regs, an[0]));
16956 + DEFINE(PT_A1, offsetof(struct pt_regs, an[1]));
16957 + DEFINE(PT_A2, offsetof(struct pt_regs, an[2]));
16958 + DEFINE(PT_A3, offsetof(struct pt_regs, an[3]));
16959 + DEFINE(PT_A4, offsetof(struct pt_regs, an[4]));
16960 + DEFINE(PT_A5, offsetof(struct pt_regs, an[5]));
16961 + DEFINE(PT_A6, offsetof(struct pt_regs, an[6]));
16962 + DEFINE(PT_A7, offsetof(struct pt_regs, an[7]));
16963 + DEFINE(PT_SP, offsetof(struct pt_regs, an[7]));
16965 + DEFINE(PT_ACC0HI, offsetof(struct pt_regs, acc0[0]));
16966 + DEFINE(PT_ACC0LO, offsetof(struct pt_regs, acc0[1]));
16967 + DEFINE(PT_MAC_RC16, offsetof(struct pt_regs, mac_rc16));
16969 + DEFINE(PT_ACC1HI, offsetof(struct pt_regs, acc1[0]));
16970 + DEFINE(PT_ACC1LO, offsetof(struct pt_regs, acc1[1]));
16972 + DEFINE(PT_SOURCE3, offsetof(struct pt_regs, source3));
16973 + DEFINE(PT_INST_CNT, offsetof(struct pt_regs, inst_cnt));
16974 + DEFINE(PT_CSR, offsetof(struct pt_regs, csr));
16975 + DEFINE(PT_DUMMY_UNUSED, offsetof(struct pt_regs, dummy_unused));
16977 + DEFINE(PT_INT_MASK0, offsetof(struct pt_regs, int_mask0));
16978 + DEFINE(PT_INT_MASK1, offsetof(struct pt_regs, int_mask1));
16980 + DEFINE(PT_PC, offsetof(struct pt_regs, pc));
16982 + DEFINE(PT_TRAP_CAUSE, offsetof(struct pt_regs, trap_cause));
16984 + DEFINE(PT_SIZE, sizeof(struct pt_regs));
16986 + DEFINE(PT_FRAME_TYPE, offsetof(struct pt_regs, frame_type));
16988 + DEFINE(PT_ORIGINAL_D0, offsetof(struct pt_regs, original_dn_0));
16989 + DEFINE(PT_PREVIOUS_PC, offsetof(struct pt_regs, previous_pc));
16991 + /* offsets into the kernel_stat struct */
16992 +// DEFINE(STAT_IRQ, offsetof(struct kernel_stat, irqs));
16994 + /* signal defines */
16995 + DEFINE(SIGSEGV, SIGSEGV);
16996 + //DEFINE(SEGV_MAPERR, SEGV_MAPERR);
16997 + DEFINE(SIGTRAP, SIGTRAP);
16998 + //DEFINE(TRAP_TRACE, TRAP_TRACE);
17000 + DEFINE(PT_PTRACED, PT_PTRACED);
17001 + DEFINE(PT_DTRACE, PT_DTRACE);
17003 + DEFINE(ASM_THREAD_SIZE, THREAD_SIZE);
17005 + /* Offsets in thread_info structure */
17006 + DEFINE(TI_TASK, offsetof(struct thread_info, task));
17007 + DEFINE(TI_EXECDOMAIN, offsetof(struct thread_info, exec_domain));
17008 + DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
17009 + DEFINE(TI_PREEMPTCOUNT, offsetof(struct thread_info, preempt_count));
17010 + DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
17011 + DEFINE(TI_INTR_NESTING, offsetof(struct thread_info, interrupt_nesting));
17012 + DEFINE(ASM_TIF_NEED_RESCHED, TIF_NEED_RESCHED);
17013 + DEFINE(ASM_TIF_SYSCALL_TRACE, TIF_SYSCALL_TRACE);
17014 + DEFINE(ASM_TIF_SIGPENDING, TIF_SIGPENDING);
17019 +++ b/arch/ubicom32/kernel/devtree.c
17022 + * arch/ubicom32/kernel/devtree.c
17023 + * Ubicom32 architecture device tree implementation.
17025 + * (C) Copyright 2009, Ubicom, Inc.
17027 + * This file is part of the Ubicom32 Linux Kernel Port.
17029 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
17030 + * it and/or modify it under the terms of the GNU General Public License
17031 + * as published by the Free Software Foundation, either version 2 of the
17032 + * License, or (at your option) any later version.
17034 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
17035 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
17036 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17037 + * the GNU General Public License for more details.
17039 + * You should have received a copy of the GNU General Public License
17040 + * along with the Ubicom32 Linux Kernel Port. If not,
17041 + * see <http://www.gnu.org/licenses/>.
17043 + * Ubicom32 implementation derived from (with many thanks):
17049 +#include <linux/module.h>
17050 +#include <linux/kernel.h>
17051 +#include <linux/string.h>
17052 +#include <linux/errno.h>
17053 +#include <asm/devtree.h>
17056 + * The device tree.
17058 +struct devtree_node *devtree;
17061 + * devtree_print()
17062 + * Print the device tree.
17064 +void devtree_print(void)
17066 + struct devtree_node *p = devtree;
17067 + printk(KERN_INFO "Device Tree:\n");
17069 + if (p->magic != DEVTREE_NODE_MAGIC) {
17070 + printk(KERN_EMERG
17071 + "device tree has improper node: %p\n", p);
17074 + printk(KERN_INFO "\t%p: sendirq=%03d, recvirq=%03d, "
17075 + " name=%s\n", p, p->sendirq, p->recvirq, p->name);
17079 +EXPORT_SYMBOL(devtree_print);
17083 + * Return the IRQ(s) associated with devtree node.
17085 +int devtree_irq(struct devtree_node *dn,
17086 + unsigned char *sendirq,
17087 + unsigned char *recvirq)
17089 + if (dn->magic != DEVTREE_NODE_MAGIC) {
17090 + printk(KERN_EMERG "improper node: %p\n", dn);
17092 + *sendirq = DEVTREE_IRQ_NONE;
17095 + *recvirq = DEVTREE_IRQ_NONE;
17101 + * Copy the devtree irq(s) to the output parameters.
17104 + *sendirq = dn->sendirq;
17107 + *recvirq = dn->recvirq;
17111 +EXPORT_SYMBOL(devtree_irq);
17114 + * devtree_find_next()
17115 + * Provide an iterator for walking the device tree.
17117 +struct devtree_node *devtree_find_next(struct devtree_node **cur)
17119 + struct devtree_node *p = *cur;
17130 + * devtree_find_by_irq()
17131 + * Return the node associated with a given irq.
17133 +struct devtree_node *devtree_find_by_irq(uint8_t sendirq, uint8_t recvirq)
17135 + struct devtree_node *p = devtree;
17137 + if (sendirq == recvirq) {
17138 + printk(KERN_EMERG "identical request makes no sense sendirq = "
17139 + "%d, recvirq= %d\n", sendirq, recvirq);
17144 + if (p->magic != DEVTREE_NODE_MAGIC) {
17145 + printk(KERN_EMERG
17146 + "device tree has improper node: %p\n", p);
17151 + * See if we can find a match on the IRQ(s) specified.
17153 + if ((sendirq == p->sendirq) && (recvirq == p->recvirq)) {
17157 + if ((sendirq == DEVTREE_IRQ_DONTCARE) &&
17158 + (p->recvirq == recvirq)) {
17162 + if ((recvirq == DEVTREE_IRQ_DONTCARE) &&
17163 + (p->sendirq == sendirq)) {
17171 +EXPORT_SYMBOL(devtree_find_by_irq);
17174 + * devtree_find_node()
17175 + * Find a node in the device tree by name.
17177 +struct devtree_node *devtree_find_node(const char *str)
17179 + struct devtree_node *p = devtree;
17181 + if (p->magic != DEVTREE_NODE_MAGIC) {
17182 + printk(KERN_EMERG
17183 + "device tree has improper node: %p\n", p);
17186 + if (strcmp(p->name, str) == 0) {
17193 +EXPORT_SYMBOL(devtree_find_node);
17195 +++ b/arch/ubicom32/kernel/dma.c
17198 + * arch/ubicom32/kernel/dma.c
17199 + * Ubicom32 architecture dynamic DMA mapping support.
17201 + * (C) Copyright 2009, Ubicom, Inc.
17203 + * This file is part of the Ubicom32 Linux Kernel Port.
17205 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
17206 + * it and/or modify it under the terms of the GNU General Public License
17207 + * as published by the Free Software Foundation, either version 2 of the
17208 + * License, or (at your option) any later version.
17210 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
17211 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
17212 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17213 + * the GNU General Public License for more details.
17215 + * You should have received a copy of the GNU General Public License
17216 + * along with the Ubicom32 Linux Kernel Port. If not,
17217 + * see <http://www.gnu.org/licenses/>.
17219 + * Ubicom32 implementation derived from (with many thanks):
17224 + * We never have any address translations to worry about, so this
17225 + * is just alloc/free.
17228 +#include <linux/types.h>
17229 +#include <linux/mm.h>
17230 +#include <linux/string.h>
17231 +#include <linux/device.h>
17232 +#include <linux/io.h>
17234 +void *dma_alloc_coherent(struct device *dev, size_t size,
17235 + dma_addr_t *dma_handle, int gfp)
17238 + /* ignore region specifiers */
17239 + gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
17241 + if (dev == NULL || (*dev->dma_mask < 0xffffffff))
17243 + ret = (void *)__get_free_pages(gfp, get_order(size));
17245 + if (ret != NULL) {
17246 + memset(ret, 0, size);
17247 + *dma_handle = virt_to_phys(ret);
17252 +void dma_free_coherent(struct device *dev, size_t size,
17253 + void *vaddr, dma_addr_t dma_handle)
17255 + free_pages((unsigned long)vaddr, get_order(size));
17258 +++ b/arch/ubicom32/kernel/flat.c
17261 + * arch/ubicom32/kernel/flat.c
17262 + * Ubicom32 architecture flat executable format support.
17264 + * (C) Copyright 2009, Ubicom, Inc.
17266 + * This file is part of the Ubicom32 Linux Kernel Port.
17268 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
17269 + * it and/or modify it under the terms of the GNU General Public License
17270 + * as published by the Free Software Foundation, either version 2 of the
17271 + * License, or (at your option) any later version.
17273 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
17274 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
17275 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17276 + * the GNU General Public License for more details.
17278 + * You should have received a copy of the GNU General Public License
17279 + * along with the Ubicom32 Linux Kernel Port. If not,
17280 + * see <http://www.gnu.org/licenses/>.
17282 + * Ubicom32 implementation derived from (with many thanks):
17287 +#include <linux/module.h>
17288 +#include <linux/types.h>
17289 +#include <linux/flat.h>
17291 +unsigned long ubicom32_flat_get_addr_from_rp(unsigned long *rp,
17294 + unsigned long *persistent)
17296 + u32_t relval_reloc_type = relval >> 27;
17297 + u32_t insn = *rp;
17299 + if (*persistent) {
17301 + * relval holds the relocation that has to be adjusted.
17303 + if (relval == 0) {
17310 + if (relval_reloc_type == R_UBICOM32_32) {
17312 + * insn holds the relocation
17318 + * We don't know this one.
17323 +void ubicom32_flat_put_addr_at_rp(unsigned long *rp,
17326 + unsigned long *persistent)
17328 + u32_t reloc_type = (relval >> 27) & 0x1f;
17329 + u32_t insn = *rp;
17332 + * If persistent is set then it contains the relocation type.
17334 + if (*persistent) {
17336 + * If persistent is set then it contains the relocation type.
17338 + reloc_type = (*persistent >> 27) & 0x1f;
17341 + switch (reloc_type) {
17342 + case R_UBICOM32_32:
17344 + * Store the 32 bits as is.
17348 + case R_UBICOM32_HI24:
17351 + * 24 bit relocation that is part of the MOVEAI
17352 + * instruction. The 24 bits come from bits 7 - 30 of the
17353 + * relocation. The 24 bits eventually get split into 2
17354 + * fields in the instruction encoding.
17356 + * - Bits 7 - 27 of the relocation are encoded into bits
17357 + * 0 - 20 of the instruction.
17359 + * - Bits 28 - 30 of the relocation are encoded into bit
17360 + * 24 - 26 of the instruction.
17362 + u32_t mask = 0x1fffff | (0x7 << 24);
17363 + u32_t valid24bits = (val >> 7) & 0xffffff;
17364 + u32_t bot_21 = valid24bits & 0x1fffff;
17365 + u32_t upper_3_bits = ((valid24bits & 0xe00000) << 3);
17369 + insn |= upper_3_bits;
17373 + case R_UBICOM32_LO7_S:
17374 + case R_UBICOM32_LO7_2_S:
17375 + case R_UBICOM32_LO7_4_S:
17378 + * Bits 0 - 6 of the relocation are encoded into the
17379 + * 7bit unsigned immediate fields of the SOURCE-1 field
17380 + * of the instruction. The immediate value is left
17381 + * shifted by (0, 1, 2) based on the operand size.
17383 + u32_t mask = 0x1f | (0x3 << 8);
17384 + u32_t bottom, top;
17386 + if (reloc_type == R_UBICOM32_LO7_2_S) {
17388 + } else if (reloc_type == R_UBICOM32_LO7_4_S) {
17392 + bottom = val & 0x1f;
17396 + insn |= (top << 8);
17397 + BUG_ON(*rp != insn);
17401 + case R_UBICOM32_LO7_D:
17402 + case R_UBICOM32_LO7_2_D:
17403 + case R_UBICOM32_LO7_4_D:
17406 + * Bits 0 - 6 of the relocation are encoded into the
17407 + * 7bit unsigned immediate fields of the DESTINATION
17408 + * field of the instruction. The immediate value is
17409 + * left shifted by (0, 1, 2) based on the operand size.
17411 + u32_t mask = (0x1f | (0x3 << 8)) << 16;
17412 + u32_t bottom, top;
17414 + if (reloc_type == R_UBICOM32_LO7_2_D) {
17416 + } else if (reloc_type == R_UBICOM32_LO7_4_D) {
17419 + bottom = (val & 0x1f) << 16;
17420 + top = (val >> 5) << 16;
17423 + insn |= (top << 8);
17424 + BUG_ON(*rp != insn);
17428 + case R_UBICOM32_LO7_CALLI:
17429 + case R_UBICOM32_LO16_CALLI:
17432 + * Extract the offset for a CALLI instruction. The
17433 + * offsets can be either 7 bits or 18 bits. Since all
17434 + * instructions in ubicom32 architecture are at work
17435 + * aligned addresses the truncated offset is right
17436 + * shifted by 2 before being encoded in the instruction.
17438 + if (reloc_type == R_UBICOM32_LO7_CALLI) {
17446 + insn &= ~0x071f071f;
17447 + insn |= (val & 0x1f) << 0;
17449 + insn |= (val & 0x07) << 8;
17451 + insn |= (val & 0x1f) << 16;
17453 + insn |= (val & 0x07) << 24;
17454 + if (reloc_type == R_UBICOM32_LO7_CALLI) {
17455 + BUG_ON(*rp != insn);
17462 + if (*persistent) {
17467 +++ b/arch/ubicom32/kernel/head.S
17470 + * arch/ubicom32/kernel/head.S
17471 + * <TODO: Replace with short file description>
17473 + * (C) Copyright 2009, Ubicom, Inc.
17475 + * This file is part of the Ubicom32 Linux Kernel Port.
17477 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
17478 + * it and/or modify it under the terms of the GNU General Public License
17479 + * as published by the Free Software Foundation, either version 2 of the
17480 + * License, or (at your option) any later version.
17482 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
17483 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
17484 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17485 + * the GNU General Public License for more details.
17487 + * You should have received a copy of the GNU General Public License
17488 + * along with the Ubicom32 Linux Kernel Port. If not,
17489 + * see <http://www.gnu.org/licenses/>.
17491 + * Ubicom32 implementation derived from (with many thanks):
17496 +#include <linux/sys.h>
17497 +#include <linux/linkage.h>
17498 +#include <asm/asm-offsets.h>
17499 +#include <asm/page_offset.h>
17501 +#include <asm/ip5000.h>
17507 +#define PARAM_DN D0
17508 +#define TMP_DN D15
17509 +#define TMP2_DN D14
17512 + * The following code is placed at the start of the Linux section of memory.
17513 + * This is the primary entry point for Linux.
17515 + * However, we also want the syscall entry/exit code to be at a fixed address.
17516 + * So we take the primary entry point and reserve 16 bytes. That address is
17517 + * where the system_call entry point exists. This 16 bytes basically allows
17518 + * us to jump around the system_call entry point code to the actual startup
17521 + * Linux Memory Map (see vlinux.lds.S):
17522 + * 0x40400000 - Primary Entry Point for Linux (jump around code below).
17523 + * 0x40400010 - Old syscall Entry Point.
17526 + .sect .skip_syscall, "ax", @progbits
17527 + .global __skip_syscall_section
17528 +__skip_syscall_section:
17529 + moveai A3, #%hi(_start)
17530 + lea.1 A3, %lo(_start)(A3)
17533 + * __os_node_offset contains the offset from KERNELBASE to the os_node, it is
17534 + * not intended to be used by anything except the boot code.
17537 +.long (_os_node - KERNELSTART)
17544 + * This is the start of the Linux kernel.
17547 + move.4 SCRATCHPAD1, #0
17551 + * Setup the range registers... the loader has setup a few, but we will go ahead
17552 + * and correct them for our own limits. Note that once set these are never
17553 + * changed again. The ranges are as follows
17555 + * D_RANGE0 - io block (set up by loaded)
17557 + * I_RANGE0 and D_RANGE1 - kernel/ultra loader address space bottom of ocm-> top
17558 + * of ram typically 0x3ffc0000 - 0x440000000
17559 + * I_RANGE1 - kernel / userspace transition area (aka syscalls, context switches)
17560 + * typically 0x3FFC0030 - ~0x3FFC0200
17561 + * I_RANGE2 / D_RANGE2 - slab area
17562 + * typically 0x40A00000 - ~0x44000000
17564 + * old system call interface if enabled.
17566 + * D_RANGE3, D_RANGE4 - unused.
17568 + moveai SRC_AN, #%hi(PAGE_OFFSET_RAW)
17569 + lea.4 SRC_AN, %lo(PAGE_OFFSET_RAW)(SRC_AN)
17570 + move.4 D_RANGE1_LO, SRC_AN
17571 + move.4 I_RANGE0_LO, SRC_AN
17573 +; don't try to calculate I_RANGE_HI, see below
17574 +; moveai SRC_AN, #%hi(___init_end-4)
17575 +; lea.4 SRC_AN, %lo(___init_end-4)(SRC_AN)
17576 +; move.4 I_RANGE0_HI, SRC_AN
17578 + moveai SRC_AN, #%hi(SDRAMSTART + CONFIG_MIN_RAMSIZE-4)
17579 + lea.4 SRC_AN, %lo(SDRAMSTART + CONFIG_MIN_RAMSIZE-4)(SRC_AN)
17580 + move.4 D_RANGE1_HI, SRC_AN
17582 +; for now allow the whole ram to be executable as well so we don't run into problems
17583 +; once we load user more code.
17584 + move.4 I_RANGE0_HI, SRC_AN
17586 +#ifdef CONFIG_PROTECT_KERNEL
17587 +; when kernel protection is enabled, we only open up syscall and non kernel text
17588 +; for userspace apps, for now only irange registers registers 1 and 2 are used for userspace.
17591 + moveai SRC_AN, #%hi(__syscall_text_run_begin)
17592 + lea.4 SRC_AN, %lo(__syscall_text_run_begin)(SRC_AN)
17593 + move.4 I_RANGE1_LO, SRC_AN
17594 + moveai SRC_AN, #%hi(__syscall_text_run_end)
17595 + lea.4 SRC_AN, %lo(__syscall_text_run_end)(SRC_AN)
17596 + move.4 I_RANGE1_HI, SRC_AN
17598 + ;; slab instructions
17599 + moveai SRC_AN, #%hi(_edata)
17600 + lea.4 SRC_AN, %lo(_edata)(SRC_AN)
17601 + move.4 I_RANGE2_LO, SRC_AN
17602 + ;; End of DDR is already in range0 hi so just copy it.
17603 + move.4 I_RANGE2_HI, I_RANGE0_HI
17605 +#ifdef CONFIG_OLD_40400010_SYSTEM_CALL
17606 + ;; create a small hole for old syscall location
17607 + moveai SRC_AN, #%hi(0x40400000)
17608 + lea.4 I_RANGE3_LO, 0x10(SRC_AN)
17609 + lea.4 I_RANGE3_HI, 0x14(SRC_AN)
17611 + ;; slab data (same as slab instructions but starting a little earlier).
17612 + moveai SRC_AN, #%hi(_data_protection_end)
17613 + lea.4 SRC_AN, %lo(_data_protection_end)(SRC_AN)
17614 + move.4 D_RANGE2_LO, SRC_AN
17615 + move.4 D_RANGE2_HI, I_RANGE0_HI
17618 + ;; skip I_RANGE0_EN
17619 + move.4 I_RANGE1_EN, #-1
17620 + move.4 I_RANGE2_EN, #-1
17621 +#ifdef CONFIG_OLD_40400010_SYSTEM_CALL
17622 + move.4 I_RANGE3_EN, #-1
17624 + move.4 I_RANGE3_EN, #0
17626 + ;; skip D_RANGE0_EN or D_RANGE1_EN
17627 + move.4 D_RANGE2_EN, #-1
17628 + move.4 D_RANGE3_EN, #0
17629 + move.4 D_RANGE4_EN, #0
17633 +; If __ocm_free_begin is smaller than __ocm_free_end the
17634 +; setup OCM text and data ram banks properly
17636 + moveai DST_AN, #%hi(__ocm_free_begin)
17637 + lea.4 TMP_DN, %lo(__ocm_free_begin)(DST_AN)
17638 + moveai DST_AN, #%hi(__ocm_free_end)
17639 + lea.4 TMP2_DN, %lo(__ocm_free_end)(DST_AN)
17640 + sub.4 #0, TMP2_DN, TMP_DN
17642 + moveai DST_AN, #%hi(__data_begin)
17643 + lea.4 TMP_DN, %lo(__data_begin)(DST_AN)
17644 + moveai DST_AN, #%hi(OCMSTART)
17645 + lea.4 TMP2_DN, %lo(OCMSTART)(DST_AN)
17646 + sub.4 TMP_DN, TMP_DN, TMP2_DN
17647 + lsr.4 TMP_DN, TMP_DN, #15
17648 + lsl.4 TMP_DN, #1, TMP_DN
17649 + moveai DST_AN, #%hi(OCMC_BASE)
17650 + add.4 OCMC_BANK_MASK(DST_AN), #-1, TMP_DN
17656 + moveai DST_AN, #%hi(__ocm_text_run_end)
17657 + lea.4 TMP_DN, %lo(__ocm_text_run_end)(DST_AN)
17658 + moveai DST_AN, #%hi(__ocm_text_run_begin)
17659 + lea.4 DST_AN, %lo(__ocm_text_run_begin)(DST_AN)
17660 + moveai SRC_AN, #%hi(__ocm_text_load_begin)
17661 + lea.4 SRC_AN, %lo(__ocm_text_load_begin)(SRC_AN)
17664 +1: move.4 (DST_AN)4++, (SRC_AN)4++
17666 +2: sub.4 #0, DST_AN, TMP_DN
17669 +; Load .syscall_text
17671 + moveai DST_AN, #%hi(__syscall_text_run_end)
17672 + lea.4 TMP_DN, %lo(__syscall_text_run_end)(DST_AN)
17673 + moveai DST_AN, #%hi(__syscall_text_run_begin)
17674 + lea.4 DST_AN, %lo(__syscall_text_run_begin)(DST_AN)
17675 + moveai SRC_AN, #%hi(__syscall_text_load_begin)
17676 + lea.4 SRC_AN, %lo(__syscall_text_load_begin)(SRC_AN)
17679 +1: move.4 (DST_AN)4++, (SRC_AN)4++
17681 +2: sub.4 #0, DST_AN, TMP_DN
17687 + moveai DST_AN, #%hi(__ocm_data_run_end)
17688 + lea.4 TMP_DN, %lo(__ocm_data_run_end)(DST_AN)
17689 + moveai DST_AN, #%hi(__ocm_data_run_begin)
17690 + lea.4 DST_AN, %lo(__ocm_data_run_begin)(DST_AN)
17691 + moveai SRC_AN, #%hi(__ocm_data_load_begin)
17692 + lea.4 SRC_AN, %lo(__ocm_data_load_begin)(SRC_AN)
17695 +1: move.4 (DST_AN)4++, (SRC_AN)4++
17697 +2: sub.4 #0, DST_AN, TMP_DN
17702 + moveai SRC_AN, #%hi(_ebss)
17703 + lea.4 TMP_DN, %lo(_ebss)(SRC_AN)
17704 + moveai DST_AN, #%hi(_sbss)
17705 + lea.4 DST_AN, %lo(_sbss)(DST_AN)
17708 +1: move.4 (DST_AN)4++, #0
17710 +2: sub.4 #0, DST_AN, TMP_DN
17713 +; save our parameter to devtree (after clearing .bss)
17714 + moveai DST_AN, #%hi(devtree)
17715 + lea.4 DST_AN, %lo(devtree)(DST_AN)
17716 + move.4 (DST_AN), PARAM_DN
17718 + moveai sp, #%hi(init_thread_union)
17719 + lea.4 sp, %lo(init_thread_union)(sp)
17720 + movei TMP_DN, #ASM_THREAD_SIZE
17721 + add.4 sp, sp, TMP_DN
17722 + move.4 -4(sp)++, #0 ; nesting level = 0
17723 + move.4 -4(sp)++, #1 ; KERNEL_THREAD
17725 +;; ip3k-elf-gdb backend now sets scratchpad3 to 1 when either continue
17726 +;; or single step commands are issued. scratchpad3 is set to 0 when the
17727 +;; debugger detaches from the board.
17728 + move.4 TMP_DN, scratchpad3
17729 + lsl.4 TMP_DN, TMP_DN, #0x0
17730 + jmpeq.f _jump_to_start_kernel
17731 +_ok_to_set_break_points_in_linux:
17733 + move.4 mt_dbg_active_clr,#-1
17734 +;; stalling the threads isn't instantaneous.. need to flush the pipe.
17738 +_jump_to_start_kernel:
17739 + moveai SRC_AN, #%hi(start_kernel)
17740 + lea.4 SRC_AN, %lo(start_kernel)(SRC_AN)
17743 +++ b/arch/ubicom32/kernel/init_task.c
17746 + * arch/ubicom32/kernel/init_task.c
17747 + * Ubicom32 architecture task initialization implementation.
17749 + * (C) Copyright 2009, Ubicom, Inc.
17751 + * This file is part of the Ubicom32 Linux Kernel Port.
17753 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
17754 + * it and/or modify it under the terms of the GNU General Public License
17755 + * as published by the Free Software Foundation, either version 2 of the
17756 + * License, or (at your option) any later version.
17758 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
17759 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
17760 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17761 + * the GNU General Public License for more details.
17763 + * You should have received a copy of the GNU General Public License
17764 + * along with the Ubicom32 Linux Kernel Port. If not,
17765 + * see <http://www.gnu.org/licenses/>.
17767 + * Ubicom32 implementation derived from (with many thanks):
17772 +#include <linux/mm.h>
17773 +#include <linux/module.h>
17774 +#include <linux/sched.h>
17775 +#include <linux/init.h>
17776 +#include <linux/init_task.h>
17777 +#include <linux/fs.h>
17778 +#include <linux/mqueue.h>
17779 +#include <linux/uaccess.h>
17780 +#include <asm/pgtable.h>
17782 +///static struct fs_struct init_fs = INIT_FS;
17783 +static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
17784 +static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
17785 +struct mm_struct init_mm = INIT_MM(init_mm);
17786 +EXPORT_SYMBOL(init_mm);
17789 + * Initial task structure.
17791 + * All other task structs will be allocated on slabs in fork.c
17793 +struct task_struct init_task = INIT_TASK(init_task);
17795 +EXPORT_SYMBOL(init_task);
17798 + * Initial thread structure.
17800 + * We need to make sure that this is 8192-byte aligned due to the
17801 + * way process stacks are handled. This is done by having a special
17802 + * "init_task" linker map entry..
17804 +union thread_union init_thread_union
17805 + __attribute__((__section__(".data.init_task"))) =
17806 + { INIT_THREAD_INFO(init_task) };
17808 +++ b/arch/ubicom32/kernel/irq.c
17811 + * arch/ubicom32/kernel/irq.c
17812 + * Ubicom32 architecture IRQ support.
17814 + * (C) Copyright 2009, Ubicom, Inc.
17815 + * (C) Copyright 2007, Greg Ungerer <gerg@snapgear.com>
17817 + * This file is part of the Ubicom32 Linux Kernel Port.
17819 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
17820 + * it and/or modify it under the terms of the GNU General Public License
17821 + * as published by the Free Software Foundation, either version 2 of the
17822 + * License, or (at your option) any later version.
17824 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
17825 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
17826 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17827 + * the GNU General Public License for more details.
17829 + * You should have received a copy of the GNU General Public License
17830 + * along with the Ubicom32 Linux Kernel Port. If not,
17831 + * see <http://www.gnu.org/licenses/>.
17833 + * Ubicom32 implementation derived from (with many thanks):
17839 +#include <linux/types.h>
17840 +#include <linux/irq.h>
17841 +#include <linux/init.h>
17842 +#include <linux/kernel.h>
17843 +#include <linux/kernel_stat.h>
17844 +#include <linux/module.h>
17845 +#include <linux/seq_file.h>
17846 +#include <linux/proc_fs.h>
17847 +#include <asm/system.h>
17848 +#include <asm/traps.h>
17849 +#include <asm/ldsr.h>
17850 +#include <asm/ip5000.h>
17851 +#include <asm/machdep.h>
17852 +#include <asm/asm-offsets.h>
17853 +#include <asm/thread.h>
17854 +#include <asm/devtree.h>
17856 +unsigned int irq_soft_avail;
17857 +static struct irqaction ubicom32_reserve_action[NR_IRQS];
17859 +#if !defined(CONFIG_DEBUG_IRQMEASURE)
17860 +#define IRQ_DECLARE_MEASUREMENT
17861 +#define IRQ_MEASUREMENT_START()
17862 +#define IRQ_MEASUREMENT_END(irq)
17864 +#define IRQ_DECLARE_MEASUREMENT \
17866 + unsigned int __tstart;
17868 +#define IRQ_MEASUREMENT_START() \
17869 + __tstart = UBICOM32_IO_TIMER->sysval;
17871 +#define IRQ_MEASUREMENT_END(irq) \
17872 + __diff = (int)UBICOM32_IO_TIMER->sysval - (int)__tstart; \
17873 + irq_measurement_update((irq), __diff);
17876 + * We keep track of the time spent in both irq_enter()
17877 + * and irq_exit().
17879 +#define IRQ_WEIGHT 32
17881 +struct irq_measurement {
17882 + volatile unsigned int min;
17883 + volatile unsigned int avg;
17884 + volatile unsigned int max;
17887 +static DEFINE_SPINLOCK(irq_measurement_lock);
17890 + * Add 1 in for softirq (irq_exit());
17892 +static struct irq_measurement irq_measurements[NR_IRQS + 1];
17895 + * irq_measurement_update()
17896 + * Update an entry in the measurement array for this irq.
17898 +static void irq_measurement_update(int irq, int sample)
17900 + struct irq_measurement *im = &irq_measurements[irq];
17901 + spin_lock(&irq_measurement_lock);
17902 + if ((im->min == 0) || (im->min > sample)) {
17903 + im->min = sample;
17905 + if (im->max < sample) {
17906 + im->max = sample;
17908 + im->avg = ((im->avg * (IRQ_WEIGHT - 1)) + sample) / IRQ_WEIGHT;
17909 + spin_unlock(&irq_measurement_lock);
17914 + * irq_kernel_stack_check()
17915 + * See if the kernel stack is within STACK_WARN of the end.
17917 +static void irq_kernel_stack_check(int irq, struct pt_regs *regs)
17919 +#ifdef CONFIG_DEBUG_STACKOVERFLOW
17920 + unsigned long sp;
17923 + * Make sure that we are not close to the top of the stack and thus
17924 + * can not really service this interrupt.
17927 + "and.4 %0, SP, %1 \n\t"
17929 + : "d" (THREAD_SIZE - 1)
17933 + if (sp < (sizeof(struct thread_info) + STACK_WARN)) {
17934 + printk(KERN_WARNING
17935 + "cpu[%d]: possible overflow detected sp remain: %p, "
17936 + "irq: %d, regs: %p\n",
17937 + thread_get_self(), (void *)sp, irq, regs);
17941 + if (sp < (sizeof(struct thread_info) + 16)) {
17949 + * Get the LSB set in value
17951 +static int irq_get_lsb(unsigned int value)
17953 + static unsigned char irq_bits[8] = {
17954 + 3, 0, 1, 0, 2, 0, 1, 0
17956 + u32_t nextbit = 0;
17958 + value = (value >> nextbit) | (value << ((sizeof(value) * 8) - nextbit));
17961 + * It's unlikely that we find that we execute the body of this while
17962 + * loop. 50% of the time we won't take this at all and then of the
17963 + * cases where we do about 50% of those we only execute once.
17965 + if (!(value & 0xffff)) {
17970 + if (!(value & 0xff)) {
17975 + if (!(value & 0xf)) {
17980 + nextbit += irq_bits[value & 0x7];
17981 + if (nextbit > 63) {
17982 + panic("nextbit out of range: %d\n", nextbit);
17988 + * ubicom32_reserve_handler()
17989 + * Bogus handler associated with pre-reserved IRQ(s).
17991 +static irqreturn_t ubicom32_reserve_handler(int irq, void *dev_id)
17994 + return IRQ_HANDLED;
17998 + * __irq_disable_vector()
17999 + * Disable the interrupt by clearing the appropriate bit in the
18000 + * LDSR Mask Register.
18002 +static void __irq_disable_vector(unsigned int irq)
18004 + ldsr_disable_vector(irq);
18008 + * __irq_ack_vector()
18009 + * Acknowledge the specific interrupt by clearing the associate bit in
18012 +static void __irq_ack_vector(unsigned int irq)
18015 + asm volatile ("move.4 INT_CLR0, %0" : : "d" (1 << irq));
18017 + asm volatile ("move.4 INT_CLR1, %0" : : "d" (1 << (irq - 32)));
18022 + * __irq_enable_vector()
18023 + * Clean and then enable the interrupt by setting the appropriate bit in
18024 + * the LDSR Mask Register.
18026 +static void __irq_enable_vector(unsigned int irq)
18029 + * Acknowledge, really clear the vector.
18031 + __irq_ack_vector(irq);
18032 + ldsr_enable_vector(irq);
18036 + * __irq_mask_vector()
18038 +static void __irq_mask_vector(unsigned int irq)
18040 + ldsr_mask_vector(irq);
18044 + * __irq_unmask_vector()
18046 +static void __irq_unmask_vector(unsigned int irq)
18048 + ldsr_unmask_vector(irq);
18052 + * __irq_end_vector()
18053 + * Called once an interrupt is completed (reset the LDSR mask).
18055 +static void __irq_end_vector(unsigned int irq)
18057 + ldsr_unmask_vector(irq);
18060 +#if defined(CONFIG_SMP)
18062 + * __irq_set_affinity()
18063 + * Set the cpu affinity for this interrupt.
18064 + * affinity container allocated at boot
18066 +static void __irq_set_affinity(unsigned int irq, const struct cpumask *dest)
18068 + smp_set_affinity(irq, dest);
18069 + cpumask_copy(irq_desc[irq].affinity, dest);
18074 + * On-Chip Generic Interrupt function handling.
18076 +static struct irq_chip ubicom32_irq_chip = {
18077 + .name = "Ubicom32",
18079 + .shutdown = NULL,
18080 + .enable = __irq_enable_vector,
18081 + .disable = __irq_disable_vector,
18082 + .ack = __irq_ack_vector,
18083 + .mask = __irq_mask_vector,
18084 + .unmask = __irq_unmask_vector,
18085 + .end = __irq_end_vector,
18086 +#if defined(CONFIG_SMP)
18087 + .set_affinity = __irq_set_affinity,
18093 + * Primary interface for handling IRQ() requests.
18095 +asmlinkage void do_IRQ(int irq, struct pt_regs *regs)
18097 + struct pt_regs *oldregs;
18098 + struct thread_info *ti = current_thread_info();
18100 + IRQ_DECLARE_MEASUREMENT;
18103 + * Mark that we are inside of an interrupt and
18104 + * that interrupts are disabled.
18106 + oldregs = set_irq_regs(regs);
18107 + ti->interrupt_nesting++;
18108 + trace_hardirqs_off();
18109 + irq_kernel_stack_check(irq, regs);
18112 + * Start the interrupt sequence
18117 + * Execute the IRQ handler and any pending SoftIRQ requests.
18119 + BUG_ON(!irqs_disabled());
18120 + IRQ_MEASUREMENT_START();
18122 + IRQ_MEASUREMENT_END(irq);
18123 + BUG_ON(!irqs_disabled());
18126 + * TODO: Since IRQ's are disabled when calling irq_exit()
18127 + * modify Kconfig to set __ARCH_IRQ_EXIT_IRQS_DISABLED flag.
18128 + * This will slightly improve performance by enabling
18129 + * softirq handling to avoid disabling/disabled interrupts.
18131 + IRQ_MEASUREMENT_START();
18133 + IRQ_MEASUREMENT_END(NR_IRQS);
18134 + BUG_ON(!irqs_disabled());
18137 + * Outside of an interrupt (or nested exit).
18139 + set_irq_regs(oldregs);
18140 + trace_hardirqs_on();
18141 + ti->interrupt_nesting--;
18145 + * irq_soft_alloc()
18146 + * Allocate a soft IRQ.
18148 +int irq_soft_alloc(unsigned int *soft)
18150 + if (irq_soft_avail == 0) {
18151 + printk(KERN_NOTICE "no soft irqs to allocate\n");
18155 + *soft = irq_get_lsb(irq_soft_avail);
18156 + irq_soft_avail &= ~(1 << *soft);
18162 + * Called to handle an bad irq request.
18164 +void ack_bad_irq(unsigned int irq)
18166 + printk(KERN_ERR "IRQ: unexpected irq=%d\n", irq);
18167 + __irq_end_vector(irq);
18171 + * show_interrupts()
18172 + * Return a string that displays the state of each of the interrupts.
18174 +int show_interrupts(struct seq_file *p, void *v)
18176 + struct irqaction *ap;
18177 + int irq = *((loff_t *) v);
18180 + if (irq >= NR_IRQS) {
18185 + seq_puts(p, " ");
18186 + for_each_online_cpu(j) {
18187 + seq_printf(p, "CPU%d ", j);
18189 + seq_putc(p, '\n');
18192 + ap = irq_desc[irq].action;
18194 + seq_printf(p, "%3d: ", irq);
18195 + for_each_online_cpu(j) {
18196 + seq_printf(p, "%10u ", kstat_irqs_cpu(irq, j));
18198 + seq_printf(p, "%14s ", irq_desc[irq].chip->name);
18199 + seq_printf(p, "%s", ap->name);
18200 + for (ap = ap->next; ap; ap = ap->next) {
18201 + seq_printf(p, ", %s", ap->name);
18203 + seq_putc(p, '\n');
18208 +#if defined(CONFIG_DEBUG_IRQMEASURE)
18209 +static unsigned int irq_cycles_to_micro(unsigned int cycles, unsigned int frequency)
18211 + unsigned int micro = (cycles / (frequency / 1000000));
18216 + * irq_measurement_show()
18217 + * Print out the min, avg, max values for each IRQ
18219 + * By request, the max value is reset after each dump.
18221 +static int irq_measurement_show(struct seq_file *p, void *v)
18223 + struct irqaction *ap;
18224 + unsigned int freq = processor_frequency();
18225 + int irq = *((loff_t *) v);
18229 + seq_puts(p, "\tmin\tavg\tmax\t(micro-seconds)\n");
18232 + if (irq > NR_IRQS) {
18236 + if (irq == NR_IRQS) {
18237 + unsigned int min, avg, max;
18238 + spin_lock(&irq_measurement_lock);
18239 + min = irq_cycles_to_micro(irq_measurements[irq].min, freq);
18240 + avg = irq_cycles_to_micro(irq_measurements[irq].avg, freq);
18241 + max = irq_cycles_to_micro(irq_measurements[irq].max, freq);
18242 + irq_measurements[irq].max = 0;
18243 + spin_unlock(&irq_measurement_lock);
18244 + seq_printf(p, " \t%u\t%u\t%u\tsoftirq\n", min, avg, max);
18248 + ap = irq_desc[irq].action;
18250 + unsigned int min, avg, max;
18251 + spin_lock(&irq_measurement_lock);
18252 + min = irq_cycles_to_micro(irq_measurements[irq].min, freq);
18253 + avg = irq_cycles_to_micro(irq_measurements[irq].avg, freq);
18254 + max = irq_cycles_to_micro(irq_measurements[irq].max, freq);
18255 + irq_measurements[irq].max = 0;
18256 + spin_unlock(&irq_measurement_lock);
18257 + seq_printf(p, "%2u:\t%u\t%u\t%u\t%s\n", irq, min, avg, max, ap->name);
18262 +static void *irq_measurement_start(struct seq_file *f, loff_t *pos)
18264 + return (*pos <= NR_IRQS) ? pos : NULL;
18267 +static void *irq_measurement_next(struct seq_file *f, void *v, loff_t *pos)
18270 + if (*pos > NR_IRQS)
18275 +static void irq_measurement_stop(struct seq_file *f, void *v)
18277 + /* Nothing to do */
18280 +static const struct seq_operations irq_measurement_seq_ops = {
18281 + .start = irq_measurement_start,
18282 + .next = irq_measurement_next,
18283 + .stop = irq_measurement_stop,
18284 + .show = irq_measurement_show,
18287 +static int irq_measurement_open(struct inode *inode, struct file *filp)
18289 + return seq_open(filp, &irq_measurement_seq_ops);
18292 +static const struct file_operations irq_measurement_fops = {
18293 + .open = irq_measurement_open,
18294 + .read = seq_read,
18295 + .llseek = seq_lseek,
18296 + .release = seq_release,
18299 +static int __init irq_measurement_init(void)
18301 + proc_create("irq_measurements", 0, NULL, &irq_measurement_fops);
18304 +module_init(irq_measurement_init);
18309 + * Initialize the on-chip IRQ subsystem.
18311 +void __init init_IRQ(void)
18314 + struct devtree_node *p = NULL;
18315 + struct devtree_node *iter = NULL;
18316 + unsigned int mask = 0;
18317 + unsigned int reserved = 0;
18320 + * Pull out the list of software interrupts that are avialable to
18321 + * Linux and provide an allocation function for them. The first
18322 + * 24 interrupts of INT0 are software interrupts.
18324 + irq_soft_avail = 0;
18325 + if (processor_interrupts(&irq_soft_avail, NULL) < 0) {
18326 + printk(KERN_WARNING "No Soft IRQ(s) available\n");
18328 + irq_soft_avail &= ((1 << 24) - 1);
18331 + * Initialize all of the on-chip interrupt handling
18332 + * to use a common set of interrupt functions.
18334 + for (irq = 0; irq < NR_IRQS; irq++) {
18335 + irq_desc[irq].status = IRQ_DISABLED;
18336 + irq_desc[irq].action = NULL;
18337 + irq_desc[irq].depth = 1;
18338 + set_irq_chip(irq, &ubicom32_irq_chip);
18342 + * The sendirq of a devnode is not registered within Linux but instead
18343 + * is used by the software I/O thread. These interrupts are reserved.
18344 + * The recvirq is used by Linux and registered by a device driver, these
18345 + * are not reserved.
18347 + * recvirq(s) that are in the software interrupt range are not supposed
18348 + * to be marked as reserved. We track this while we scan the device
18351 + p = devtree_find_next(&iter);
18353 + unsigned char sendirq, recvirq;
18354 + devtree_irq(p, &sendirq, &recvirq);
18357 + * If the sendirq is valid, mark that irq as taken by the
18360 + if (sendirq < NR_IRQS) {
18361 + ubicom32_reserve_action[sendirq].handler =
18362 + ubicom32_reserve_handler;
18363 + ubicom32_reserve_action[sendirq].name = p->name;
18364 + irq_desc[sendirq].action =
18365 + &ubicom32_reserve_action[sendirq];
18366 + mask |= (1 << sendirq);
18370 + * Track the relevant recieve IRQ(s)
18372 + if (recvirq < 24) {
18373 + mask |= (1 << recvirq);
18377 + * Move to the next node.
18379 + p = devtree_find_next(&iter);
18383 + * Remove these bits from the irq_soft_avail list and then use the
18384 + * result as the list of pre-reserved IRQ(s).
18386 + reserved = ~irq_soft_avail & ~mask;
18387 + for (irq = 0; irq < 24; irq++) {
18388 + if ((reserved & (1 << irq))) {
18389 + ubicom32_reserve_action[irq].handler =
18390 + ubicom32_reserve_handler;
18391 + ubicom32_reserve_action[irq].name = "reserved";
18392 + irq_desc[irq].action = &ubicom32_reserve_action[irq];
18397 + * Initialize the LDSR which is the Ubicom32 programmable
18398 + * interrupt controller.
18403 + * The Ubicom trap code needs a 2nd init after IRQ(s) are setup.
18405 + trap_init_interrupt();
18408 +++ b/arch/ubicom32/kernel/ldsr.c
18411 + * arch/ubicom32/kernel/ldsr.c
18412 + * Ubicom32 architecture Linux Device Services Driver Interface
18414 + * (C) Copyright 2009, Ubicom, Inc.
18416 + * This file is part of the Ubicom32 Linux Kernel Port.
18418 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
18419 + * it and/or modify it under the terms of the GNU General Public License
18420 + * as published by the Free Software Foundation, either version 2 of the
18421 + * License, or (at your option) any later version.
18423 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
18424 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
18425 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
18426 + * the GNU General Public License for more details.
18428 + * You should have received a copy of the GNU General Public License
18429 + * along with the Ubicom32 Linux Kernel Port. If not,
18430 + * see <http://www.gnu.org/licenses/>.
18432 + * Ubicom32 implementation derived from (with many thanks):
18439 + * The LDSR is a programmable interrupt controller that is written in software.
18440 + * It emulates the behavior of an pic by fielding the interrupts, choosing a
18441 + * victim thread to take the interrupt and forcing that thread to take a context
18442 + * switch to the appropriate interrupt handler.
18444 + * Because traps are treated as just a special class of interrupts, the LDSR
18445 + * also handles the processing of traps.
18447 + * Because we compile Linux both UP and SMP, we need the LDSR to use
18448 + * architectural locking that is not "compiled out" when compiling UP. For now,
18449 + * we use the single atomic bit lock.
18451 +#include <linux/kernel.h>
18452 +#include <linux/init.h>
18453 +#include <linux/sched.h>
18454 +#include <linux/interrupt.h>
18455 +#include <linux/irq.h>
18456 +#include <linux/profile.h>
18457 +#include <linux/clocksource.h>
18458 +#include <linux/types.h>
18459 +#include <linux/module.h>
18460 +#include <linux/cpumask.h>
18461 +#include <linux/bug.h>
18462 +#include <linux/delay.h>
18463 +#include <asm/ip5000.h>
18464 +#include <asm/atomic.h>
18465 +#include <asm/machdep.h>
18466 +#include <asm/asm-offsets.h>
18467 +#include <asm/traps.h>
18468 +#include <asm/thread.h>
18469 +#include <asm/range-protect.h>
18472 + * One can not print from the LDSR so the best we can do is
18473 + * check a condition and stall all of the threads.
18476 +// #define DEBUG_LDSR 1
18477 +#if defined(DEBUG_LDSR)
18478 +#define DEBUG_ASSERT(cond) \
18483 +#define DEBUG_ASSERT(cond)
18487 + * Make global so that we can use it in the RFI code in assembly.
18489 +unsigned int ldsr_soft_irq_mask;
18490 +EXPORT_SYMBOL(ldsr_soft_irq_mask);
18492 +static unsigned int ldsr_suspend_mask;
18493 +static unsigned int ldsr_soft_irq;
18494 +static unsigned int ldsr_stack_space[1024];
18496 +static struct ldsr_register_bank {
18497 + volatile unsigned int enabled0;
18498 + volatile unsigned int enabled1;
18499 + volatile unsigned int mask0;
18500 + volatile unsigned int mask1;
18501 + unsigned int total;
18502 + unsigned int retry;
18503 + unsigned int backout;
18507 + * Which thread/cpu are we?
18509 +static int ldsr_tid = -1;
18511 +#if defined(CONFIG_IRQSTACKS)
18513 + * per-CPU IRQ stacks (thread information and stack)
18515 + * NOTE: Do not use DEFINE_PER_CPU() as it makes it harder
18516 + * to find the location of ctx from assembly language.
18519 + struct thread_info tinfo;
18520 + u32 stack[THREAD_SIZE/sizeof(u32)];
18522 +static union irq_ctx *percpu_irq_ctxs[NR_CPUS];
18525 + * Storage for the interrupt stack.
18527 +#if !defined(CONFIG_IRQSTACKS_USEOCM)
18528 +static char percpu_irq_stacks[(NR_CPUS * THREAD_SIZE) + (THREAD_SIZE - 1)];
18531 + * For OCM, the linker will ensure that space is allocated for the stack
18532 + * see (vmlinux.lds.S)
18534 +static char percpu_irq_stacks[];
18540 + * Save trap IRQ because we need to un-suspend if it gets set.
18542 +static unsigned int ldsr_trap_irq_mask;
18543 +static unsigned int ldsr_trap_irq;
18546 + * ret_from_interrupt_to_kernel
18547 + * Just restore the context and do nothing else.
18549 +asmlinkage void ret_from_interrupt_to_kernel(void)__attribute__((naked));
18552 + * ret_from_interrupt_to_user
18553 + * Call scheduler if needed. Just restore the context.
18555 +asmlinkage void ret_from_interrupt_to_user(void)__attribute__((naked));
18558 +u32_t old_sp, old_pc, old_a0, old_a5, old_a3;
18559 +struct pt_regs copy_regs, *copy_save_area;
18562 +int __user_mode(unsigned long sp)
18565 + u32_t saved_stack_base = sp & ~(ASM_THREAD_SIZE - 1);
18566 +#if defined(CONFIG_IRQSTACKS_USEOCM)
18567 + if ((union irq_ctx *)saved_stack_base == percpu_irq_ctxs[smp_processor_id()]) {
18569 + * On the interrupt stack.
18575 + if (!(u32_t)current) {
18578 + return saved_stack_base != ((u32_t)current->stack);
18582 + * ldsr_lock_release()
18583 + * Release the LDSR lock.
18585 +static void ldsr_lock_release(void)
18587 + UBICOM32_UNLOCK(LDSR_LOCK_BIT);
18591 + * ldsr_lock_acquire()
18592 + * Acquire the LDSR lock, spin if not available.
18594 +static void ldsr_lock_acquire(void)
18596 + UBICOM32_LOCK(LDSR_LOCK_BIT);
18600 + * ldsr_thread_irq_disable()
18601 + * Disable interrupts for the specified thread.
18603 +static void ldsr_thread_irq_disable(unsigned int tid)
18605 + unsigned int mask = (1 << tid);
18608 + " or.4 scratchpad1, scratchpad1, %0 \n\t"
18616 + * ldsr_thread_get_interrupts()
18617 + * Get the interrupt state for all threads.
18619 +static unsigned long ldsr_thread_get_interrupts(void)
18621 + unsigned long ret = 0;
18623 + " move.4 %0, scratchpad1 \n\t"
18631 + * ldsr_emulate_and_run()
18632 + * Emulate the instruction and then set the thread to run.
18634 +static void ldsr_emulate_and_run(unsigned int tid)
18636 + unsigned int thread_mask = (1 << tid);
18637 + u32_t write_csr = (tid << 15) | (1 << 14);
18640 + * Emulate the unaligned access.
18642 + unaligned_emulate(tid);
18645 + * Get the thread back in a running state.
18648 + " setcsr %0 \n\t"
18649 + " setcsr_flush 0 \n\t"
18650 + " move.4 trap_cause, #0 \n\t" /* Clear the trap cause
18652 + " setcsr #0 \n\t"
18653 + " setcsr_flush 0 \n\t"
18654 + " move.4 mt_dbg_active_set, %1 \n\t" /* Activate thread even if
18655 + * in dbg/fault state */
18656 + " move.4 mt_active_set, %1 \n\t" /* Restart target
18659 + : "r" (write_csr), "d" (thread_mask)
18662 + thread_enable_mask(thread_mask);
18666 + * ldsr_preemptive_context_save()
18667 + * save thread context from another hardware thread. The other thread must
18670 +static inline void ldsr_preemptive_context_save(u32_t thread,
18671 + struct pt_regs *regs)
18674 + * Save the current state of the specified thread
18677 + " move.4 a3, %0 \n\t"
18679 + /* set src1 from the target thread */
18680 + " move.4 csr, %1 \n\t"
18681 + " setcsr_flush 0 \n\t"
18682 + " setcsr_flush 0 \n\t"
18684 + /* copy state from the other thread */
18685 + " move.4 "D(PT_D0)"(a3), d0 \n\t"
18686 + " move.4 "D(PT_D1)"(a3), d1 \n\t"
18687 + " move.4 "D(PT_D2)"(a3), d2 \n\t"
18688 + " move.4 "D(PT_D3)"(a3), d3 \n\t"
18689 + " move.4 "D(PT_D4)"(a3), d4 \n\t"
18690 + " move.4 "D(PT_D5)"(a3), d5 \n\t"
18691 + " move.4 "D(PT_D6)"(a3), d6 \n\t"
18692 + " move.4 "D(PT_D7)"(a3), d7 \n\t"
18693 + " move.4 "D(PT_D8)"(a3), d8 \n\t"
18694 + " move.4 "D(PT_D9)"(a3), d9 \n\t"
18695 + " move.4 "D(PT_D10)"(a3), d10 \n\t"
18696 + " move.4 "D(PT_D11)"(a3), d11 \n\t"
18697 + " move.4 "D(PT_D12)"(a3), d12 \n\t"
18698 + " move.4 "D(PT_D13)"(a3), d13 \n\t"
18699 + " move.4 "D(PT_D14)"(a3), d14 \n\t"
18700 + " move.4 "D(PT_D15)"(a3), d15 \n\t"
18701 + " move.4 "D(PT_A0)"(a3), a0 \n\t"
18702 + " move.4 "D(PT_A1)"(a3), a1 \n\t"
18703 + " move.4 "D(PT_A2)"(a3), a2 \n\t"
18704 + " move.4 "D(PT_A3)"(a3), a3 \n\t"
18705 + " move.4 "D(PT_A4)"(a3), a4 \n\t"
18706 + " move.4 "D(PT_A5)"(a3), a5 \n\t"
18707 + " move.4 "D(PT_A6)"(a3), a6 \n\t"
18708 + " move.4 "D(PT_SP)"(a3), a7 \n\t"
18709 + " move.4 "D(PT_ACC0HI)"(a3), acc0_hi \n\t"
18710 + " move.4 "D(PT_ACC0LO)"(a3), acc0_lo \n\t"
18711 + " move.4 "D(PT_MAC_RC16)"(a3), mac_rc16 \n\t"
18712 + " move.4 "D(PT_ACC1HI)"(a3), acc1_hi \n\t"
18713 + " move.4 "D(PT_ACC1LO)"(a3), acc1_lo \n\t"
18714 + " move.4 "D(PT_SOURCE3)"(a3), source3 \n\t"
18715 + " move.4 "D(PT_INST_CNT)"(a3), inst_cnt \n\t"
18716 + " move.4 "D(PT_CSR)"(a3), csr \n\t"
18717 + " move.4 "D(PT_DUMMY_UNUSED)"(a3), #0 \n\t"
18718 + " move.4 "D(PT_INT_MASK0)"(a3), int_mask0 \n\t"
18719 + " move.4 "D(PT_INT_MASK1)"(a3), int_mask1 \n\t"
18720 + " move.4 "D(PT_TRAP_CAUSE)"(a3), trap_cause \n\t"
18721 + " move.4 "D(PT_PC)"(a3), pc \n\t"
18722 + " move.4 "D(PT_PREVIOUS_PC)"(a3), previous_pc \n\t"
18723 + /* disable csr thread select */
18724 + " movei csr, #0 \n\t"
18725 + " setcsr_flush 0 \n\t"
18727 + : "r" (regs->dn), "d" ((thread << 9) | (1 << 8))
18733 + * ldsr_rotate_threads()
18734 + * Simple round robin algorithm for choosing the next cpu
18736 +static int ldsr_rotate_threads(unsigned long cpus)
18738 + static unsigned char ldsr_bits[8] = {
18739 + 3, 0, 1, 0, 2, 0, 1, 0
18742 + static int nextbit;
18746 + * Move the interrupts down so that we consider interrupts from where
18747 + * we left off, then take the interrupts we would lose and move them
18748 + * to the top half of the interrupts value.
18750 + cpus = (cpus >> nextbit) | (cpus << ((sizeof(cpus) * 8) - nextbit));
18753 + * 50% of the time we won't take this at all and then of the cases where
18754 + * we do about 50% of those we only execute once.
18756 + if (!(cpus & 0xffff)) {
18761 + if (!(cpus & 0xff)) {
18766 + if (!(cpus & 0xf)) {
18771 + nextbit += ldsr_bits[cpus & 0x7];
18772 + thisbit = (nextbit & ((sizeof(cpus) * 8) - 1));
18773 + nextbit = (thisbit + 1) & ((sizeof(cpus) * 8) - 1);
18774 + DEBUG_ASSERT(thisbit < THREAD_ARCHITECTURAL_MAX);
18779 + * ldsr_rotate_interrupts()
18780 + * Get rotating next set bit value.
18782 +static int ldsr_rotate_interrupts(unsigned long long interrupts)
18784 + static unsigned char ldsr_bits[8] = {
18785 + 3, 0, 1, 0, 2, 0, 1, 0
18788 + static int nextbit;
18792 + * Move the interrupts down so that we consider interrupts from where
18793 + * we left off, then take the interrupts we would lose and move them
18794 + * to the top half of the interrupts value.
18796 + interrupts = (interrupts >> nextbit) |
18797 + (interrupts << ((sizeof(interrupts) * 8) - nextbit));
18800 + * 50% of the time we won't take this at all and then of the cases where
18801 + * we do about 50% of those we only execute once.
18803 + if (!(interrupts & 0xffffffff)) {
18805 + interrupts >>= 32;
18808 + if (!(interrupts & 0xffff)) {
18810 + interrupts >>= 16;
18813 + if (!(interrupts & 0xff)) {
18815 + interrupts >>= 8;
18818 + if (!(interrupts & 0xf)) {
18820 + interrupts >>= 4;
18823 + nextbit += ldsr_bits[interrupts & 0x7];
18824 + thisbit = (nextbit & ((sizeof(interrupts) * 8) - 1));
18825 + nextbit = (thisbit + 1) & ((sizeof(interrupts) * 8) - 1);
18827 + DEBUG_ASSERT(thisbit < (sizeof(interrupts) * 8));
18832 + * ldsr_backout_or_irq()
18834 + * One way or the other this interrupt is not being
18835 + * processed, make sure that it is reset. We are
18836 + * not going to call irq_end_vector() so unmask the
18839 +static void ldsr_backout_of_irq(int vector, unsigned long tid_mask)
18841 +#if defined(CONFIG_SMP)
18842 + if (unlikely(vector == smp_ipi_irq)) {
18843 + smp_reset_ipi(tid_mask);
18846 + ldsr_unmask_vector(vector);
18847 + ldsr_interrupt.backout++;
18850 +#if defined(CONFIG_IRQSTACKS)
18852 + * ldsr_choose_savearea_and_returnvec()
18853 + * Test our current state (user, kernel, interrupt) and set things up.
18855 + * This version of the function uses 3 stacks and nests interrupts
18856 + * on the interrupt stack.
18858 +static struct pt_regs *ldsr_choose_savearea_and_returnvec(thread_t tid, u32_t linux_sp, u32_t *pvec)
18860 + struct pt_regs *save_area;
18861 + u32_t masked_linux_sp = linux_sp & ~(THREAD_SIZE - 1);
18862 + struct thread_info * ti= (struct thread_info *)sw_ksp[tid];
18864 +#if defined(CONFIG_SMP)
18865 + union irq_ctx *icp = percpu_irq_ctxs[tid];
18867 + union irq_ctx *icp = percpu_irq_ctxs[0];
18870 + if (masked_linux_sp == (u32_t)icp) {
18872 + * Fault/Interrupt occurred while on the interrupt stack.
18874 + save_area = (struct pt_regs *)((char *)linux_sp - sizeof(struct pt_regs) - 8);
18875 + *pvec = (u32_t)(&ret_from_interrupt_to_kernel);
18878 + * Fault/Interrupt occurred while on user/kernel stack. This is a new
18879 + * first use of the interrupt stack.
18881 + save_area = (struct pt_regs *) ((char *)icp + sizeof(icp->stack) - sizeof(struct pt_regs) - 8);
18882 + if (masked_linux_sp == (u32_t)ti) {
18883 + *pvec = (u32_t)(&ret_from_interrupt_to_kernel);
18885 + *pvec = (u32_t)(&ret_from_interrupt_to_user);
18889 + * Because the softirq code will execute on the "interrupt" stack, we
18890 + * need to maintain the knowledge of what "task" was executing on the
18891 + * cpu. This is done by copying the thread_info->task from the cpu
18892 + * we are about to context switch into the interrupt contexts thread_info
18895 + icp->tinfo.task = ti->task;
18896 + icp->tinfo.preempt_count =
18897 + (icp->tinfo.preempt_count & ~SOFTIRQ_MASK) |
18898 + (ti->preempt_count & SOFTIRQ_MASK);
18899 + icp->tinfo.interrupt_nesting = 0;
18901 + save_area->nesting_level = icp->tinfo.interrupt_nesting;
18902 + return save_area;
18907 + * ldsr_choose_savearea_and_returnvec()
18908 + * Test our current state (user, kernel, interrupt) and set things up.
18910 + * The version of the function uses just the user & kernel stack and
18911 + * nests interrupts on the existing kernel stack.
18913 +static struct pt_regs *ldsr_choose_savearea_and_returnvec(thread_t tid, u32_t linux_sp, u32_t *pvec)
18915 + struct pt_regs *save_area;
18916 + u32_t masked_linux_sp = linux_sp & ~(THREAD_SIZE - 1);
18917 + struct thread_info *ti = (struct thread_info *)sw_ksp[tid];
18919 + if (masked_linux_sp == (u32_t)ti) {
18921 + * Fault/Interrupt occurred while on the kernel stack.
18923 + save_area = (struct pt_regs *)((char *)linux_sp - sizeof(struct pt_regs) - 8);
18924 + *pvec = (u32_t) (&ret_from_interrupt_to_kernel);
18927 + * Fault/Interrupt occurred while on user stack.
18929 + ti->interrupt_nesting = 0;
18930 + save_area = (struct pt_regs *)((u32_t)ti + THREAD_SIZE - sizeof(struct pt_regs) - 8);
18931 + *pvec = (u32_t) (&ret_from_interrupt_to_user);
18933 + save_area->nesting_level = ti->interrupt_nesting;
18934 + return save_area;
18939 + * ldsr_ctxsw_thread()
18940 + * Context switch a mainline thread to execute do_IRQ() for the specified
18943 +static void ldsr_ctxsw_thread(int vector, thread_t tid)
18946 + u32_t return_vector;
18947 + struct pt_regs *save_area, *regs;
18948 + u32_t thread_mask = (1 << tid);
18949 + u32_t read_csr = ((tid << 9) | (1 << 8));
18950 + u32_t write_csr = (tid << 15) | (1 << 14);
18951 + u32_t interrupt_vector = (u32_t)(&do_IRQ);
18953 + unsigned int frame_type = UBICOM32_FRAME_TYPE_INTERRUPT;
18956 + DEBUG_ASSERT(!thread_is_enabled(tid));
18959 + * Acquire the necessary global and per thread locks for tid.
18960 + * As a side effect, we ensure that the thread has not trapped
18961 + * and return true if it has.
18963 + if (unlikely(thread_is_trapped(tid))) {
18965 + * Read the trap cause, the sp and clear the MT_TRAP bits.
18967 + unsigned int cause;
18969 + " setcsr %3 \n\t"
18970 + " setcsr_flush 0 \n\t"
18971 + " setcsr_flush 0 \n\t"
18972 + " move.4 %0, TRAP_CAUSE \n\t"
18973 + " move.4 %1, SP \n\t"
18974 + " setcsr #0 \n\t"
18975 + " setcsr_flush 0 \n\t"
18976 + " move.4 MT_BREAK_CLR, %2\n\t"
18977 + " move.4 MT_TRAP_CLR, %2 \n\t"
18978 + : "=&r" (cause), "=&r" (linux_sp)
18979 + : "r" (thread_mask), "m" (read_csr)
18982 + ldsr_backout_of_irq(vector, (1 << tid));
18984 +#if !defined(CONFIG_UNALIGNED_ACCESS_DISABLED)
18986 + * See if the unaligned trap handler can deal with this.
18987 + * If so, emulate the instruction and then just restart
18990 + if (unaligned_only(cause)) {
18991 +#if defined(CONFIG_UNALIGNED_ACCESS_USERSPACE_ONLY)
18993 + * Check if this is a kernel stack if so we will not
18994 + * handle the trap
18996 + u32_t masked_linux_sp = linux_sp & ~(THREAD_SIZE - 1);
18997 + if ((masked_linux_sp != (u32_t)sw_ksp[tid]) &&
18998 + unaligned_only(cause)) {
18999 + ldsr_emulate_and_run(tid);
19003 + ldsr_emulate_and_run(tid);
19010 + interrupt_vector = (u32_t)(&trap_handler);
19011 + frame_type = UBICOM32_FRAME_TYPE_TRAP;
19014 + * Read the target thread's SP
19017 + " setcsr %1 \n\t"
19018 + " setcsr_flush 0 \n\t"
19019 + " setcsr_flush 0 \n\t"
19020 + " move.4 %0, SP \n\t"
19021 + " setcsr #0 \n\t"
19022 + " setcsr_flush 0 \n\t"
19023 + : "=m" (linux_sp)
19029 + * We are delivering an interrupt, count it.
19031 + ldsr_interrupt.total++;
19034 + * At this point, we will definitely force this thread to
19035 + * a new context, show its interrupts as disabled.
19037 + ldsr_thread_irq_disable(tid);
19040 + * Test our current state (user, kernel, interrupt). Save the
19041 + * appropriate data and setup for the return.
19043 + save_area = ldsr_choose_savearea_and_returnvec(tid, linux_sp, &return_vector);
19046 + * The pt_regs (save_area) contains the type of thread that we are dealing
19047 + * with (KERNEL/NORMAL) and is copied into each pt_regs area. We get this
19048 + * from the current tasks kernel pt_regs area that always exists at the
19049 + * top of the kernel stack.
19051 + regs = (struct pt_regs *)((u32_t)sw_ksp[tid] + THREAD_SIZE - sizeof(struct pt_regs) - 8);
19052 + save_area->thread_type = regs->thread_type;
19055 + * Preserve the context of the Linux thread.
19057 + ldsr_preemptive_context_save(tid, save_area);
19060 + * Load the fram_type into the save_area.
19062 + save_area->frame_type = frame_type;
19064 +#ifdef CONFIG_STOP_ON_TRAP
19066 + * Before we get backtrace and showing stacks working well, it sometimes
19067 + * helps to enter the debugger when a trap occurs before we change the
19068 + * thread to handle the fault. This optional code causes all threads to
19069 + * stop on every trap frame. One assumes that GDB connected via the
19070 + * mailbox interface will be used to recover from this state.
19072 + if (frame_type == UBICOM32_FRAME_TYPE_TRAP) {
19078 + copy_regs = *save_area;
19079 + copy_save_area = save_area;
19081 + old_a0 = save_area->an[0];
19082 + old_a3 = save_area->an[3];
19083 + old_sp = save_area->an[7];
19084 + old_a5 = save_area->an[5];
19085 + old_pc = save_area->pc;
19089 + * Now we have to switch the kernel thread to run do_IRQ function.
19090 + * Set pc to do_IRQ
19091 + * Set d0 to vector
19092 + * Set d1 to save_area.
19093 + * Set a5 to the proper return vector.
19096 + " setcsr %0 \n\t"
19097 + " setcsr_flush 0 \n\t"
19098 + " move.4 d0, %5 \n\t" /* d0 = 0 vector # */
19099 + " move.4 d1, %1 \n\t" /* d1 = save_area */
19100 + " move.4 sp, %1 \n\t" /* sp = save_area */
19101 + " move.4 a5, %2 \n\t" /* a5 = return_vector */
19102 + " move.4 pc, %3 \n\t" /* pc = do_IRQ routine. */
19103 + " move.4 trap_cause, #0 \n\t" /* Clear the trap cause
19105 + " setcsr #0 \n\t"
19106 + " setcsr_flush 0 \n\t"
19107 + " enable_kernel_ranges %4 \n\t"
19108 + " move.4 mt_dbg_active_set, %4 \n\t" /* Activate thread even if
19109 + * in dbg/fault state */
19110 + " move.4 mt_active_set, %4 \n\t" /* Restart target
19113 + : "r" (write_csr), "r" (save_area),
19114 + "r" (return_vector), "r" (interrupt_vector),
19115 + "d" (thread_mask), "r" (vector)
19118 + thread_enable_mask(thread_mask);
19122 + * ldsr_deliver_interrupt()
19123 + * Deliver the interrupt to one of the threads or all of the threads.
19125 +static void ldsr_deliver_interrupt(int vector,
19126 + unsigned long deliver_to,
19129 + unsigned long disabled_threads;
19130 + unsigned long possible_threads;
19131 + unsigned long trapped_threads;
19132 + unsigned long global_locks;
19135 + * Disable all of the threads that we might want to send
19136 + * this interrupt to.
19139 + DEBUG_ASSERT(deliver_to);
19140 + thread_disable_mask(deliver_to);
19143 + * If any threads are in the trap state, we have to service the
19144 + * trap for those threads first.
19147 + "move.4 %0, MT_TRAP \n\t"
19148 + : "=r" (trapped_threads)
19152 + trapped_threads &= deliver_to;
19153 + if (unlikely(trapped_threads)) {
19155 + * all traps will be handled, so clear the trap bit before restarting any threads
19157 + ubicom32_clear_interrupt(ldsr_trap_irq);
19160 + * Let the remaining untrapped threads, continue.
19162 + deliver_to &= ~trapped_threads;
19163 + if (deliver_to) {
19164 + thread_enable_mask(deliver_to);
19168 + * For the trapped threads force them to handle
19171 + while (trapped_threads) {
19172 + unsigned long which = ffz(~trapped_threads);
19173 + trapped_threads &= ~(1 << which);
19174 + ldsr_ctxsw_thread(vector, which);
19180 + * Can we deliver an interrupt to any of the threads?
19182 + disabled_threads = ldsr_thread_get_interrupts();
19183 + possible_threads = deliver_to & ~disabled_threads;
19184 + if (unlikely(!possible_threads)) {
19185 +#if defined(CONFIG_SMP)
19187 + * In the SMP case, we can not wait because 1 cpu might be
19188 + * sending an IPI to another cpu which is currently blocked.
19189 + * The only way to ensure IPI delivery is to backout and
19190 + * keep trying. For SMP, we don't sleep until the interrupts
19193 + thread_enable_mask(deliver_to);
19194 + ldsr_backout_of_irq(vector, deliver_to);
19198 + * In the UP case, we have nothing to do so we should wait.
19200 + * Since the INT_MASK0 and INT_MASK1 are "re-loaded" before we
19201 + * suspend in the outer loop, we do not need to save them here.
19203 + * We test that we were awakened for our specific interrupts
19204 + * because the ldsr mask/unmask operations will force the ldsr
19205 + * awake even if the interrupt on the mainline thread is not
19208 + unsigned int scratch = 0;
19209 + thread_enable_mask(deliver_to);
19211 + " move.4 INT_MASK0, %1 \n\t"
19212 + " move.4 INT_MASK1, #0 \n\t"
19214 + "1: suspend \n\t"
19215 + " move.4 %0, INT_STAT0 \n\t"
19216 + " and.4 %0, %0, %1 \n\t"
19217 + " jmpeq.f 1b \n\t"
19219 + " move.4 INT_CLR0, %2 \n\t"
19221 + : "d" (ldsr_suspend_mask), "r" (ldsr_soft_irq_mask)
19226 + * This delay is sized to coincide with the time it takes a
19227 + * thread to complete the exit (see return_from_interrupt).
19229 + ldsr_interrupt.retry++;
19236 + * If any of the global locks are held, we can not deliver any
19237 + * interrupts, we spin delay(10) and then try again. If our
19238 + * spinning becomes a bottle neck, we will need to suspend but for
19239 + * now lets just spin.
19242 + "move.4 %0, scratchpad1 \n\t"
19243 + : "=r" (global_locks)
19246 + if (unlikely(global_locks & 0xffff0000)) {
19247 + thread_enable_mask(deliver_to);
19250 + * This delay is sized to coincide with the average time it
19251 + * takes a thread to release a global lock.
19253 + ldsr_interrupt.retry++;
19259 + * Deliver to one cpu.
19263 + * Find our victim and then enable everyone else.
19265 + unsigned long victim = ldsr_rotate_threads(possible_threads);
19266 + DEBUG_ASSERT((deliver_to & (1 << victim)));
19267 + DEBUG_ASSERT((possible_threads & (1 << victim)));
19269 + deliver_to &= ~(1 << victim);
19270 + if (deliver_to) {
19271 + thread_enable_mask(deliver_to);
19273 + ldsr_ctxsw_thread(vector, victim);
19278 + * If we can't deliver to some threads, wake them
19279 + * back up and reset things to deliver to them.
19281 + deliver_to &= ~possible_threads;
19282 + if (unlikely(deliver_to)) {
19283 + thread_enable_mask(deliver_to);
19284 + ldsr_backout_of_irq(vector, deliver_to);
19288 + * Deliver to all possible threads(s).
19290 + while (possible_threads) {
19291 + unsigned long victim = ffz(~possible_threads);
19292 + possible_threads &= ~(1 << victim);
19293 + ldsr_ctxsw_thread(vector, victim);
19299 + * This thread acts as the interrupt controller for Linux.
19301 +static void ldsr_thread(void *arg)
19307 + long long interrupts;
19308 + unsigned long cpus;
19310 +#if !defined(CONFIG_SMP)
19312 + * In a non-smp configuration, we can not use the cpu(s) arrays because
19313 + * there is not a 1-1 correspondence between cpus(s) and our threads.
19314 + * Thus we must get a local idea of the mainline threads and use the
19315 + * one and only 1 set as the victim. We do this once before the ldsr
19318 + * In the SMP case, we will use the cpu(s) map to determine which cpu(s)
19319 + * are valid to send interrupts to.
19322 + unsigned int mainline = thread_get_mainline();
19323 + if (mainline == 0) {
19324 + panic("no mainline Linux threads to interrupt");
19327 + victim = ffz(~mainline);
19328 + cpus = (1 << victim);
19333 + * If one changes this code not to reload the INT_MASK(s), you
19334 + * need to know that code in the lock waiting above does not
19335 + * reset the MASK registers back; so that code will need to be
19338 + ldsr_lock_acquire();
19340 + " move.4 INT_MASK0, %0 \n\t"
19341 + " move.4 INT_MASK1, %1 \n\t"
19343 + : "U4" (ldsr_interrupt.mask0), "U4" (ldsr_interrupt.mask1)
19345 + ldsr_lock_release();
19346 + thread_suspend();
19349 + * Read the interrupt status registers
19352 + "move.4 %0, INT_STAT0 \n\t"
19353 + "move.4 %1, INT_STAT1 \n\t"
19354 + : "=r" (stat0), "=r" (stat1)
19359 + * We only care about interrupts that we have been told to care
19360 + * about. The interrupt must be enabled, unmasked, and have
19361 + * occurred in the hardware.
19363 + ldsr_lock_acquire();
19364 + interrupt0 = ldsr_interrupt.enabled0 &
19365 + ldsr_interrupt.mask0 & stat0;
19366 + interrupt1 = ldsr_interrupt.enabled1 &
19367 + ldsr_interrupt.mask1 & stat1;
19368 + ldsr_lock_release();
19371 + * For each interrupt in the "snapshot" we will mask the
19372 + * interrupt handle the interrupt (typically calling do_IRQ()).
19374 + * The interrupt is unmasked by desc->chip->end() function in
19375 + * the per chip generic interrupt handling code
19376 + * (arch/ubicom32/kernel/irq.c).8
19378 + interrupts = ((unsigned long long)interrupt1 << 32) |
19380 + while (interrupts) {
19382 + int vector = ldsr_rotate_interrupts(interrupts);
19383 + interrupts &= ~((unsigned long long)1 << vector);
19386 + * Now mask off this vector so that the LDSR ignores
19387 + * it until it is acknowledged.
19389 + ldsr_mask_vector(vector);
19390 +#if !defined(CONFIG_SMP)
19391 + ldsr_deliver_interrupt(vector, cpus, all);
19393 + cpus = smp_get_affinity(vector, &all);
19396 + * No CPU to deliver to so just leave
19397 + * the interrupt unmasked and increase
19398 + * the backout count. We will eventually
19399 + * return and deliver it again.
19401 + ldsr_unmask_vector(vector);
19402 + ldsr_interrupt.backout++;
19405 + ldsr_deliver_interrupt(vector, cpus, all);
19414 + * ldsr_mask_vector()
19415 + * Temporarily mask the interrupt vector, turn off the bit in the mask
19418 +void ldsr_mask_vector(unsigned int vector)
19420 + unsigned int mask;
19421 + if (vector < 32) {
19422 + mask = ~(1 << vector);
19423 + ldsr_lock_acquire();
19424 + ldsr_interrupt.mask0 &= mask;
19425 + ldsr_lock_release();
19426 + thread_resume(ldsr_tid);
19430 + mask = ~(1 << (vector - 32));
19431 + ldsr_lock_acquire();
19432 + ldsr_interrupt.mask1 &= mask;
19433 + ldsr_lock_release();
19434 + thread_resume(ldsr_tid);
19438 + * ldsr_unmask_vector()
19439 + * Unmask the interrupt vector so that it can be used, turn on the bit in
19440 + * the mask register.
19442 + * Because it is legal for the interrupt path to disable an interrupt,
19443 + * the unmasking code must ensure that disabled interrupts are not
19446 +void ldsr_unmask_vector(unsigned int vector)
19448 + unsigned int mask;
19449 + if (vector < 32) {
19450 + mask = (1 << vector);
19451 + ldsr_lock_acquire();
19452 + ldsr_interrupt.mask0 |= (mask & ldsr_interrupt.enabled0);
19453 + ldsr_lock_release();
19454 + thread_resume(ldsr_tid);
19458 + mask = (1 << (vector - 32));
19459 + ldsr_lock_acquire();
19460 + ldsr_interrupt.mask1 |= (mask & ldsr_interrupt.enabled1);
19461 + ldsr_lock_release();
19462 + thread_resume(ldsr_tid);
19466 + * ldsr_enable_vector()
19467 + * The LDSR implements an interrupt controller and has a local (to the
19468 + * LDSR) copy of its interrupt mask.
19470 +void ldsr_enable_vector(unsigned int vector)
19472 + unsigned int mask;
19473 + if (vector < 32) {
19474 + mask = (1 << vector);
19475 + ldsr_lock_acquire();
19476 + ldsr_interrupt.enabled0 |= mask;
19477 + ldsr_interrupt.mask0 |= mask;
19478 + ldsr_lock_release();
19479 + thread_resume(ldsr_tid);
19483 + mask = (1 << (vector - 32));
19484 + ldsr_lock_acquire();
19485 + ldsr_interrupt.enabled1 |= mask;
19486 + ldsr_interrupt.mask1 |= mask;
19487 + ldsr_lock_release();
19488 + thread_resume(ldsr_tid);
19492 + * ldsr_disable_vector()
19493 + * The LDSR implements an interrupt controller and has a local (to the
19494 + * LDSR) copy of its interrupt mask.
19496 +void ldsr_disable_vector(unsigned int vector)
19498 + unsigned int mask;
19500 + if (vector < 32) {
19501 + mask = ~(1 << vector);
19502 + ldsr_lock_acquire();
19503 + ldsr_interrupt.enabled0 &= mask;
19504 + ldsr_interrupt.mask0 &= mask;
19505 + ldsr_lock_release();
19506 + thread_resume(ldsr_tid);
19510 + mask = ~(1 << (vector - 32));
19511 + ldsr_lock_acquire();
19512 + ldsr_interrupt.enabled1 &= mask;
19513 + ldsr_interrupt.mask1 &= mask;
19514 + ldsr_lock_release();
19515 + thread_resume(ldsr_tid);
19519 + * ldsr_get_threadid()
19520 + * Return the threadid of the LDSR thread.
19522 +thread_t ldsr_get_threadid(void)
19528 + * ldsr_set_trap_irq()
19529 + * Save away the trap Soft IRQ
19531 + * See the per thread lock suspend code above for an explination.
19533 +void ldsr_set_trap_irq(unsigned int irq)
19535 + ldsr_trap_irq = irq;
19536 + ldsr_trap_irq_mask = (1 << irq);
19537 + ldsr_suspend_mask |= ldsr_trap_irq_mask;
19542 + * Initialize the LDSR (Interrupt Controller)
19544 +void ldsr_init(void)
19546 +#if defined(CONFIG_IRQSTACKS)
19548 + union irq_ctx *icp;
19551 + void *stack_high = (void *)ldsr_stack_space;
19552 + stack_high += sizeof(ldsr_stack_space);
19557 + * Obtain a soft IRQ to use
19559 + if (irq_soft_alloc(&ldsr_soft_irq) < 0) {
19560 + panic("no software IRQ is available\n");
19563 + ldsr_soft_irq_mask |= (1 << ldsr_soft_irq);
19564 + ldsr_suspend_mask |= ldsr_soft_irq_mask;
19567 + * Now allocate and start the LDSR thread.
19569 + ldsr_tid = thread_alloc();
19570 + if (ldsr_tid < 0) {
19571 + panic("no thread available to run LDSR");
19575 +#if defined(CONFIG_IRQSTACKS)
19577 + * Initialize the per-cpu irq thread_info structure that
19578 + * is at the top of each per-cpu irq stack.
19580 + icp = (union irq_ctx *)
19581 + (((unsigned long)percpu_irq_stacks + (THREAD_SIZE - 1)) & ~(THREAD_SIZE - 1));
19582 + for (i = 0; i < NR_CPUS; i++) {
19583 + struct thread_info *ti = &(icp->tinfo);
19585 + ti->exec_domain = NULL;
19587 + ti->preempt_count = 0;
19588 + ti->interrupt_nesting = 0;
19589 + percpu_irq_ctxs[i] = icp++;
19592 + thread_start(ldsr_tid, ldsr_thread, NULL,
19593 + stack_high, THREAD_TYPE_NORMAL);
19596 +++ b/arch/ubicom32/kernel/Makefile
19599 +# arch/ubicom32/kernel/Makefile
19600 +# Main Makefile for the Ubicom32 arch directory.
19602 +# (C) Copyright 2009, Ubicom, Inc.
19604 +# This file is part of the Ubicom32 Linux Kernel Port.
19606 +# The Ubicom32 Linux Kernel Port is free software: you can redistribute
19607 +# it and/or modify it under the terms of the GNU General Public License
19608 +# as published by the Free Software Foundation, either version 2 of the
19609 +# License, or (at your option) any later version.
19611 +# The Ubicom32 Linux Kernel Port is distributed in the hope that it
19612 +# will be useful, but WITHOUT ANY WARRANTY; without even the implied
19613 +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
19614 +# the GNU General Public License for more details.
19616 +# You should have received a copy of the GNU General Public License
19617 +# along with the Ubicom32 Linux Kernel Port. If not,
19618 +# see <http://www.gnu.org/licenses/>.
19620 +# Ubicom32 implementation derived from (with many thanks):
19626 +extra-y := head.o vmlinux.lds
19647 + ubicom32_context_switch.o \
19648 + ubicom32_ksyms.o \
19649 + ubicom32_syscall.o \
19652 +obj-$(CONFIG_MODULES) += module.o
19653 +obj-$(CONFIG_COMEMPCI) += comempci.o
19654 +obj-$(CONFIG_SMP) += smp.o topology.o
19655 +obj-$(CONFIG_ACCESS_OK_CHECKS_ENABLED) += uaccess.o
19656 +obj-$(CONFIG_GENERIC_CLOCKEVENTS) += timer_device.o
19657 +obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) += timer_broadcast.o
19659 +ifndef CONFIG_GENERIC_CLOCKEVENTS
19660 +obj-y += timer_tick.o
19663 +++ b/arch/ubicom32/kernel/module.c
19666 + * arch/ubicom32/kernel/module.c
19667 + * Ubicom32 architecture loadable module support.
19669 + * (C) Copyright 2009, Ubicom, Inc.
19671 + * This file is part of the Ubicom32 Linux Kernel Port.
19673 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
19674 + * it and/or modify it under the terms of the GNU General Public License
19675 + * as published by the Free Software Foundation, either version 2 of the
19676 + * License, or (at your option) any later version.
19678 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
19679 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
19680 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
19681 + * the GNU General Public License for more details.
19683 + * You should have received a copy of the GNU General Public License
19684 + * along with the Ubicom32 Linux Kernel Port. If not,
19685 + * see <http://www.gnu.org/licenses/>.
19687 + * Ubicom32 implementation derived from (with many thanks):
19692 +#include <linux/moduleloader.h>
19693 +#include <linux/bug.h>
19694 +#include <linux/elf.h>
19695 +#include <linux/vmalloc.h>
19696 +#include <linux/fs.h>
19697 +#include <linux/string.h>
19698 +#include <linux/kernel.h>
19699 +#include <asm/ocm-alloc.h>
19702 +#define DEBUGP printk
19704 +#define DEBUGP(fmt...)
19707 +static void _module_free_ocm(struct module *mod)
19709 + printk(KERN_INFO "module arch cleanup %s: OCM instruction memory free "
19710 + " of %d @%p\n", mod->name, mod->arch.ocm_inst_size,
19711 + mod->arch.ocm_inst);
19713 + if (mod->arch.ocm_inst) {
19714 + ocm_inst_free(mod->arch.ocm_inst);
19715 + mod->arch.ocm_inst = 0;
19716 + mod->arch.ocm_inst_size = 0;
19720 +void *module_alloc(unsigned long size)
19724 + return vmalloc(size);
19728 +/* Free memory returned from module_alloc */
19729 +void module_free(struct module *mod, void *module_region)
19731 + vfree(module_region);
19732 + /* FIXME: If module_region == mod->init_region, trim exception
19733 + table entries. */
19736 + * This is expected to be final module free, use this to prune the
19739 + if (module_region && module_region == mod->module_core)
19740 + _module_free_ocm(mod);
19745 + * module_frob_arch_sections()
19746 + * Called from kernel/module.c allowing arch specific handling of
19747 + * sections/headers.
19749 +int module_frob_arch_sections(Elf_Ehdr *hdr,
19750 + Elf_Shdr *sechdrs,
19751 + char *secstrings,
19752 + struct module *mod)
19754 + Elf_Shdr *s, *sechdrs_end;
19755 + void *ocm_inst = NULL;
19756 + int ocm_inst_size = 0;
19759 + * Ubicom32 v3 and v4 are almost binary compatible but not completely.
19760 + * To be safe check that the module was compiled with the correct -march
19761 + * which is flags.
19763 +#ifdef CONFIG_UBICOM32_V4
19764 + if ((hdr->e_flags & 0xFFFF) != EF_UBICOM32_V4) {
19765 + printk(KERN_WARNING "Module %s was not compiled for "
19766 + "ubicom32v4, elf_flags:%x,\n",
19767 + mod->name, hdr->e_flags);
19770 +#elif defined CONFIG_UBICOM32_V3
19771 + if ((hdr->e_flags & 0xFFFF) != EF_UBICOM32_V3) {
19772 + printk(KERN_WARNING "Module %s was not compiled for "
19773 + "ubicom32v3, elf_flags:%x\n",
19774 + mod->name, hdr->e_flags);
19778 +#error Unknown/Unsupported ubicom32 architecture.
19782 + * XXX: sechdrs are vmalloced in kernel/module.c
19783 + * and would be vfreed just after module is loaded,
19784 + * so we hack to keep the only information we needed
19785 + * in mod->arch to correctly free L1 I/D sram later.
19786 + * NOTE: this breaks the semantic of mod->arch structure.
19788 + sechdrs_end = sechdrs + hdr->e_shnum;
19789 + for (s = sechdrs; s < sechdrs_end; ++s) {
19790 + if (strncmp(".ocm_text", secstrings + s->sh_name, 9) == 0)
19791 + ocm_inst_size += s->sh_size;
19794 + if (!ocm_inst_size)
19797 + ocm_inst = ocm_inst_alloc(ocm_inst_size, 0 /* internal */);
19798 + if (ocm_inst == NULL) {
19799 +#ifdef CONFIG_OCM_MODULES_FALLBACK_TO_DDR
19800 + printk(KERN_WARNING
19801 + "module %s: OCM instruction memory allocation of %d"
19802 + "failed, fallback to DDR\n", mod->name, ocm_inst_size);
19806 + "module %s: OCM instruction memory allocation of %d"
19807 + "failed.\n", mod->name, ocm_inst_size);
19812 + mod->arch.ocm_inst = ocm_inst;
19813 + mod->arch.ocm_inst_size = ocm_inst_size;
19816 + "module %s: OCM instruction memory allocation of %d @%p\n",
19817 + mod->name, mod->arch.ocm_inst_size, mod->arch.ocm_inst);
19819 + for (s = sechdrs; s < sechdrs_end; ++s) {
19820 + if (strncmp(".ocm_text", secstrings + s->sh_name, 9) == 0) {
19821 + memcpy(ocm_inst, (void *)s->sh_addr, s->sh_size);
19822 + s->sh_flags &= ~SHF_ALLOC;
19823 + s->sh_addr = (unsigned long)ocm_inst;
19824 + ocm_inst += s->sh_size;
19831 +int apply_relocate(Elf32_Shdr *sechdrs,
19832 + const char *strtab,
19833 + unsigned int symindex,
19834 + unsigned int relsec,
19835 + struct module *me)
19837 + DEBUGP("Invalid Applying relocate section %u to %u\n", relsec,
19838 + sechdrs[relsec].sh_info);
19842 +int apply_relocate_add(Elf32_Shdr *sechdrs,
19843 + const char *strtab,
19844 + unsigned int symindex,
19845 + unsigned int relsec,
19846 + struct module *me)
19849 + Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
19851 + uint32_t *location;
19854 + DEBUGP("Applying relocate_add section %u to %u\n", relsec,
19855 + sechdrs[relsec].sh_info);
19856 + for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
19858 + const int elf32_rtype = ELF32_R_TYPE(rel[i].r_info);
19860 + /* This is where to make the change */
19861 + location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
19862 + + rel[i].r_offset;
19863 + /* This is the symbol it is referring to. Note that all
19864 + undefined symbols have been resolved. */
19865 + sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
19866 + + ELF32_R_SYM(rel[i].r_info);
19868 + v = rel[i].r_addend + sym->st_value;
19871 + switch (elf32_rtype) {
19872 + case R_UBICOM32_32:
19875 + * Store the 32 bit relocation as is.
19880 + case R_UBICOM32_HI24:
19883 + * 24 bit relocation that is part of the MOVEAI
19884 + * instruction. The 24 bits come from bits 7 - 30 of the
19885 + * relocation. Theses bits eventually get split into 2
19886 + * fields in the instruction encoding.
19888 + * - Bits 7 - 27 of the relocation are encoded into bits
19889 + * 0 - 20 of the instruction.
19891 + * - Bits 28 - 30 of the relocation are encoded into
19892 + * bit 24 - 26 of the instruction.
19894 + uint32_t valid24 = (v >> 7) & 0xffffff;
19895 + insn = *location;
19897 + insn &= ~(0x1fffff | (0x7 << 24));
19898 + insn |= (valid24 & 0x1fffff);
19899 + insn |= ((valid24 & 0xe00000) << 3);
19900 + *location = insn;
19903 + case R_UBICOM32_LO7_S:
19904 + case R_UBICOM32_LO7_2_S:
19905 + case R_UBICOM32_LO7_4_S:
19908 + * Bits 0 - 6 of the relocation are encoded into the
19909 + * 7bit unsigned immediate fields of the SOURCE-1 field
19910 + * of the instruction. The immediate value is left
19911 + * shifted by (0, 1, 2) based on the operand size.
19913 + uint32_t valid7 = v & 0x7f;
19914 + insn = *location;
19916 + if (elf32_rtype == R_UBICOM32_LO7_2_S) {
19918 + } else if (elf32_rtype == R_UBICOM32_LO7_4_S) {
19922 + insn &= ~(0x1f | (0x3 << 8));
19923 + insn |= (valid7 & 0x1f);
19924 + insn |= ((valid7 & 0x60) << 3);
19925 + *location = insn;
19928 + case R_UBICOM32_LO7_D:
19929 + case R_UBICOM32_LO7_2_D:
19930 + case R_UBICOM32_LO7_4_D:
19933 + * Bits 0 - 6 of the relocation are encoded into the
19934 + * 7bit unsigned immediate fields of the DESTINATION
19935 + * field of the instruction. The immediate value is
19936 + * left shifted by (0, 1, 2) based on the operand size.
19938 + uint32_t valid7 = v & 0x7f;
19939 + insn = *location;
19941 + if (elf32_rtype == R_UBICOM32_LO7_2_D) {
19943 + } else if (elf32_rtype == R_UBICOM32_LO7_4_D) {
19947 + insn &= ~((0x1f | (0x3 << 8)) << 16);
19948 + insn |= ((valid7 & 0x1f) << 16);
19949 + insn |= ((valid7 & 0x60) << 19);
19950 + *location = insn;
19953 + case R_UBICOM32_LO7_CALLI:
19954 + case R_UBICOM32_LO16_CALLI:
19957 + * Extract the offset for a CALLI instruction. The
19958 + * offsets can be either 7 bits or 18 bits. Since all
19959 + * instructions in ubicom32 architecture are at work
19960 + * aligned addresses the truncated offset is right
19961 + * shifted by 2 before being encoded in the instruction.
19964 + if (elf32_rtype == R_UBICOM32_LO7_CALLI) {
19967 + val = v & 0x3ffff;
19972 + insn = *location;
19974 + insn &= ~0x071f071f;
19975 + insn |= (val & 0x1f) << 0;
19977 + insn |= (val & 0x07) << 8;
19979 + insn |= (val & 0x1f) << 16;
19981 + insn |= (val & 0x07) << 24;
19982 + *location = insn;
19985 + case R_UBICOM32_24_PCREL:
19988 + * Extract 26 bit signed PC relative offset for CALL
19989 + * instructions. Since instruction addresses are word
19990 + * aligned the offset is right shited by 2 before
19991 + * encoding into instruction.
19993 + int32_t val = v - (int32_t)location;
19996 + * Check that the top 7 bits are all equal to the sign
19997 + * bit (26), i.e all 0's or all 1's. If they are not then
19998 + * the absolute difference is greater than 25 bits.
20000 + if (((uint32_t)val & 0xFE000000) != 0xFE000000 &&
20001 + ((uint32_t)val & 0xFE000000) != 0x0) {
20003 + * The relocation is beyond our addressable
20004 + * range with a 26 bit call.
20006 + printk(KERN_ERR "module %s: PC Relative "
20007 + "relocation out of range: "
20008 + "%u (%x->%x, %x)\n",
20009 + me->name, elf32_rtype,
20010 + v, (uint32_t) location, val);
20014 + val = (val & 0x3ffffff) >> 2;
20015 + insn = *location;
20016 + insn = insn & 0xf8e00000;
20018 + insn |= (val >> 21) << 24;
20019 + insn |= (val & 0x1fffff);
20020 + *location = insn;
20023 + case R_UBICOM32_LO16:
20024 + case R_UBICOM32_HI16:
20027 + * 16 bit immediate value that is encoded into bit 0 -
20028 + * 15 of the instruction.
20032 + if (elf32_rtype == R_UBICOM32_LO16) {
20033 + val = v & 0xffff;
20035 + val = (v >> 16) & 0xffff;
20038 + insn = *location;
20039 + insn &= 0xffff0000;
20042 + *location = insn;
20045 + case R_UBICOM32_21_PCREL:
20048 + * Extract 23 bit signed PC relative offset for JMP<cc>
20049 + * instructions. Since instruction addresses are word
20050 + * aligned the offset is right shited by 2 before
20051 + * encoding into instruction.
20053 + int32_t val = v - (int32_t)location;
20055 + val = (val & 0x7fffff) >> 2;
20056 + insn = *location;
20057 + insn = insn & 0xffe00000;
20059 + insn |= (val >> 21) << 24;
20061 + *location = insn;
20066 + printk(KERN_ERR "module %s: Unknown relocation: %u\n",
20067 + me->name, elf32_rtype);
20074 +int module_finalize(const Elf_Ehdr *hdr,
20075 + const Elf_Shdr *sechdrs,
20076 + struct module *mod)
20078 + unsigned int i, strindex = 0, symindex = 0;
20079 + char *secstrings;
20082 + err = module_bug_finalize(hdr, sechdrs, mod);
20086 + if (!mod->arch.ocm_inst) {
20088 + * No OCM code, so nothing more to do.
20093 + secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
20095 + for (i = 1; i < hdr->e_shnum; i++) {
20096 + /* Internal symbols and strings. */
20097 + if (sechdrs[i].sh_type == SHT_SYMTAB) {
20099 + strindex = sechdrs[i].sh_link;
20103 + for (i = 1; i < hdr->e_shnum; i++) {
20104 + const char *strtab = (char *)sechdrs[strindex].sh_addr;
20105 + unsigned int info = sechdrs[i].sh_info;
20107 + /* Not a valid relocation section? */
20108 + if (info >= hdr->e_shnum)
20111 + if ((sechdrs[i].sh_type == SHT_RELA) &&
20112 + (strncmp(".rela.ocm_text",
20113 + secstrings + sechdrs[i].sh_name, 5 + 9) == 0)) {
20114 + err = apply_relocate_add((Elf_Shdr *) sechdrs, strtab,
20115 + symindex, i, mod);
20124 +void module_arch_cleanup(struct module *mod)
20126 + module_bug_cleanup(mod);
20129 +++ b/arch/ubicom32/kernel/os_node.c
20132 + * arch/ubicom32/kernel/os_node.c
20133 + * <TODO: Replace with short file description>
20135 + * (C) Copyright 2009, Ubicom, Inc.
20137 + * This file is part of the Ubicom32 Linux Kernel Port.
20139 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
20140 + * it and/or modify it under the terms of the GNU General Public License
20141 + * as published by the Free Software Foundation, either version 2 of the
20142 + * License, or (at your option) any later version.
20144 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
20145 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
20146 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
20147 + * the GNU General Public License for more details.
20149 + * You should have received a copy of the GNU General Public License
20150 + * along with the Ubicom32 Linux Kernel Port. If not,
20151 + * see <http://www.gnu.org/licenses/>.
20154 +#include "linux/types.h"
20155 +#include "linux/linkage.h"
20156 +#include "linux/uts.h"
20157 +#include "linux/utsrelease.h"
20158 +#include "linux/version.h"
20159 +#include <asm/ocm_size.h>
20160 +#include <asm/devtree.h>
20161 +#include <asm/ip5000.h>
20163 +extern asmlinkage void *_start;
20166 + * This file provides static information to the boot code allowing it to decide
20167 + * if the os is compatible. Thus hopefully enabling the boot code to prevent
20168 + * accidentally booting a kernel that has no hope of running.
20171 + struct devtree_node node;
20172 + unsigned long version; /* Always 1 */
20173 + unsigned long entry_point;
20174 + const char os_name[32]; /* For diagnostic purposes only */
20175 + const char os_version_str[32];
20176 + unsigned long os_version_num;
20177 + unsigned long expected_ocm_code_start;/* OS Code */
20178 + unsigned long expected_ocm_data_end; /* OS Data */
20179 + unsigned long expected_ram_start;
20180 + unsigned long expected_ram_end;
20181 + unsigned long arch_version;
20182 + unsigned long expected_os_syscall_begin;
20183 + unsigned long expected_os_syscall_end;
20187 +extern void __os_syscall_begin;
20188 +extern void __os_syscall_end;
20190 + * The os_node is only referenced by head.S and should never be modified at
20193 +asmlinkage const struct os_node _os_node = {
20196 + .name = { "OS" },
20197 + .magic = 0x10203040,
20199 + .version = 0x10002,
20200 + .entry_point = (unsigned long)&_start,
20201 +#if APP_OCM_CODE_SIZE || APP_OCM_DATA_SIZE
20202 + .expected_ocm_code_start = OCMSTART + APP_OCM_CODE_SIZE,
20203 + .expected_ocm_data_end = OCMEND - APP_OCM_DATA_SIZE,
20205 + .expected_ocm_code_start = OCMEND,
20206 + .expected_ocm_data_end = OCMEND,
20208 + .os_name = { UTS_SYSNAME },
20209 + .os_version_str = { UTS_RELEASE },
20210 + .os_version_num = LINUX_VERSION_CODE,
20211 + .expected_ram_start = KERNELSTART,
20212 + .expected_ram_end = SDRAMSTART + CONFIG_MIN_RAMSIZE,
20213 + .arch_version = UBICOM32_ARCH_VERSION,
20214 + .expected_os_syscall_begin = (unsigned long)&__os_syscall_begin,
20215 + .expected_os_syscall_end = (unsigned long)&__os_syscall_end,
20220 +++ b/arch/ubicom32/kernel/process.c
20223 + * arch/ubicom32/kernel/process.c
20224 + * Ubicom32 architecture-dependent process handling.
20226 + * (C) Copyright 2009, Ubicom, Inc.
20227 + * Copyright (C) 1995 Hamish Macdonald
20229 + * 68060 fixes by Jesper Skov
20231 + * uClinux changes
20232 + * Copyright (C) 2000-2002, David McCullough <davidm@snapgear.com>
20234 + * This file is part of the Ubicom32 Linux Kernel Port.
20236 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
20237 + * it and/or modify it under the terms of the GNU General Public License
20238 + * as published by the Free Software Foundation, either version 2 of the
20239 + * License, or (at your option) any later version.
20241 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
20242 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
20243 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
20244 + * the GNU General Public License for more details.
20246 + * You should have received a copy of the GNU General Public License
20247 + * along with the Ubicom32 Linux Kernel Port. If not,
20248 + * see <http://www.gnu.org/licenses/>.
20250 + * Ubicom32 implementation derived from (with many thanks):
20257 + * This file handles the architecture-dependent parts of process handling..
20260 +#include <linux/module.h>
20261 +#include <linux/errno.h>
20262 +#include <linux/sched.h>
20263 +#include <linux/kernel.h>
20264 +#include <linux/mm.h>
20265 +#include <linux/smp.h>
20266 +#include <linux/smp_lock.h>
20267 +#include <linux/stddef.h>
20268 +#include <linux/unistd.h>
20269 +#include <linux/ptrace.h>
20270 +#include <linux/slab.h>
20271 +#include <linux/user.h>
20272 +#include <linux/a.out.h>
20273 +#include <linux/interrupt.h>
20274 +#include <linux/reboot.h>
20275 +#include <linux/fs.h>
20276 +#include <linux/pm.h>
20278 +#include <linux/uaccess.h>
20279 +#include <asm/system.h>
20280 +#include <asm/traps.h>
20281 +#include <asm/machdep.h>
20282 +#include <asm/setup.h>
20283 +#include <asm/pgtable.h>
20284 +#include <asm/ip5000.h>
20285 +#include <asm/range-protect.h>
20287 +#define DUMP_RANGE_REGISTER(REG, IDX) asm volatile ( \
20288 + " move.4 %0, "REG"_RANGE"IDX"_EN \n\t" \
20289 + " move.4 %1, "REG"_RANGE"IDX"_LO \n\t" \
20290 + " move.4 %2, "REG"_RANGE"IDX"_HI \n\t" \
20291 + : "=d"(en), "=d"(lo), "=d"(hi) \
20293 + printk(KERN_NOTICE REG"Range"IDX": en:%08x, range: %08x-%08x\n", \
20294 + (unsigned int)en, \
20295 + (unsigned int)lo, \
20296 + (unsigned int)hi)
20298 +asmlinkage void ret_from_fork(void);
20300 +void (*pm_power_off)(void) = machine_power_off;
20301 +EXPORT_SYMBOL(pm_power_off);
20303 +/* machine-dependent / hardware-specific power functions */
20304 +void (*mach_reset)(void);
20305 +void (*mach_halt)(void);
20306 +void (*mach_power_off)(void);
20310 + * The idle thread.
20312 + * Our idle loop suspends and is woken up by a timer interrupt.
20314 +void cpu_idle(void)
20317 + local_irq_disable();
20318 + while (!need_resched()) {
20319 + local_irq_enable();
20320 + thread_suspend();
20321 + local_irq_disable();
20323 + local_irq_enable();
20324 + preempt_enable_no_resched();
20326 + preempt_disable();
20333 + * Fill in the fpu structure for a core dump. (just a stub as we don't have
20336 +int dump_fpu(struct pt_regs *regs, elf_fpregset_t * fpregs)
20342 + * machine_restart()
20343 + * Resets the system.
20345 +void machine_restart(char *__unused)
20348 + * Disable all threads except myself. We can do this
20349 + * directly without needing to call smp_send_stop
20350 + * because we have a unique architecture where
20351 + * one thread can disable one or more other threads.
20353 + thread_disable_others();
20356 + * Call the hardware-specific machine reset function.
20358 + if (mach_reset) {
20362 + printk(KERN_EMERG "System Restarting\n");
20365 + * Set watchdog to trigger (after 1ms delay) (12 Mhz is the fixed OSC)
20367 + UBICOM32_IO_TIMER->tkey = TIMER_TKEYVAL;
20368 + UBICOM32_IO_TIMER->wdcom = UBICOM32_IO_TIMER->mptval +
20369 + (12000000 / 1000);
20370 + UBICOM32_IO_TIMER->wdcfg = 0;
20371 + UBICOM32_IO_TIMER->tkey = 0;
20374 + * Wait for watchdog
20377 + " move.4 MT_EN, #0 \n\t"
20378 + " pipe_flush 0 \n\t"
20381 + local_irq_disable();
20383 + thread_suspend();
20389 + * Halt the machine.
20391 + * Similar to machine_power_off, but don't shut off power. Add code
20392 + * here to freeze the system for e.g. post-mortem debug purpose when
20393 + * possible. This halt has nothing to do with the idle halt.
20395 +void machine_halt(void)
20398 + * Disable all threads except myself. We can do this
20399 + * directly without needing to call smp_send_stop
20400 + * because we have a unique architecture where
20401 + * one thread can disable one or more other threads.
20403 + thread_disable_others();
20406 + * Call the hardware-specific machine halt function.
20412 + printk(KERN_EMERG "System Halted, OK to turn off power\n");
20413 + local_irq_disable();
20415 + thread_suspend();
20420 + * machine_power_off()
20421 + * Turn the power off, if a power off handler is defined, otherwise, spin
20424 +void machine_power_off(void)
20427 + * Disable all threads except myself. We can do this
20428 + * directly without needing to call smp_send_stop
20429 + * because we have a unique architecture where
20430 + * one thread can disable one or more other threads.
20432 + thread_disable_others();
20435 + * Call the hardware-specific machine power off function.
20437 + if (mach_power_off) {
20438 + mach_power_off();
20441 + printk(KERN_EMERG "System Halted, OK to turn off power\n");
20442 + local_irq_disable();
20444 + thread_suspend();
20449 + * address_is_valid()
20450 + * check if an address is valid -- (for read access)
20452 +static bool address_is_valid(const void *address)
20454 + int addr = (int)address;
20455 + unsigned long socm, eocm, sdram, edram;
20460 + processor_ocm(&socm, &eocm);
20461 + processor_dram(&sdram, &edram);
20462 + if (addr >= socm && addr < eocm)
20465 + if (addr >= sdram && addr < edram)
20472 + * vma_path_name_is_valid()
20473 + * check if path_name of a vma is a valid string
20475 +static bool vma_path_name_is_valid(const char *str)
20477 +#define MAX_NAME_LEN 256
20479 + if (!address_is_valid(str))
20482 + for (; i < MAX_NAME_LEN; i++, str++) {
20483 + if (*str == '\0')
20492 + * show vma info of a process
20494 +void show_vmas(struct task_struct *task)
20496 +#ifdef CONFIG_DEBUG_VERBOSE
20497 +#define UBICOM32_MAX_VMA_COUNT 1024
20499 + struct vm_area_struct *vma;
20500 + struct file *file;
20502 + int flags, loop = 0;
20504 + printk(KERN_NOTICE "Start of vma list\n");
20506 + if (!address_is_valid(task) || !address_is_valid(task->mm))
20509 + vma = task->mm->mmap;
20511 + if (!address_is_valid(vma))
20514 + flags = vma->vm_flags;
20515 + file = vma->vm_file;
20518 + /* seems better to use dentry op here, but sanity check is easier this way */
20519 + if (!address_is_valid(file) || !address_is_valid(file->f_path.dentry) || !vma_path_name_is_valid(file->f_path.dentry->d_name.name))
20522 + name = (char *)file->f_path.dentry->d_name.name;
20525 + /* Similar to /proc/pid/maps format */
20526 + printk(KERN_NOTICE "%08lx-%08lx %c%c%c%c %08lx %s\n",
20529 + flags & VM_READ ? 'r' : '-',
20530 + flags & VM_WRITE ? 'w' : '-',
20531 + flags & VM_EXEC ? 'x' : '-',
20532 + flags & VM_MAYSHARE ? flags & VM_SHARED ? 'S' : 's' : 'p',
20533 + vma->vm_pgoff << PAGE_SHIFT,
20536 + vma = vma->vm_next;
20538 + if (loop++ > UBICOM32_MAX_VMA_COUNT)
20542 + printk(KERN_NOTICE "End of vma list\n");
20546 + printk(KERN_NOTICE "\nCorrupted vma list, abort!\n");
20552 + * Print out all of the registers.
20554 +void show_regs(struct pt_regs *regs)
20557 + unsigned int en, lo, hi;
20559 + printk(KERN_NOTICE "regs: %p, tid: %d\n",
20561 + thread_get_self());
20563 + printk(KERN_NOTICE "pc: %08x, previous_pc: %08x\n\n",
20564 + (unsigned int)regs->pc,
20565 + (unsigned int)regs->previous_pc);
20567 + printk(KERN_NOTICE "Data registers\n");
20568 + for (i = 0; i < 16; i++) {
20569 + printk("D%02d: %08x, ", i, (unsigned int)regs->dn[i]);
20570 + if ((i % 4) == 3) {
20576 + printk(KERN_NOTICE "Address registers\n");
20577 + for (i = 0; i < 8; i++) {
20578 + printk("A%02d: %08x, ", i, (unsigned int)regs->an[i]);
20579 + if ((i % 4) == 3) {
20585 + printk(KERN_NOTICE "acc0: %08x-%08x, acc1: %08x-%08x\n",
20586 + (unsigned int)regs->acc0[1],
20587 + (unsigned int)regs->acc0[0],
20588 + (unsigned int)regs->acc1[1],
20589 + (unsigned int)regs->acc1[0]);
20591 + printk(KERN_NOTICE "mac_rc16: %08x, source3: %08x\n",
20592 + (unsigned int)regs->mac_rc16,
20593 + (unsigned int)regs->source3);
20595 + printk(KERN_NOTICE "inst_cnt: %08x, csr: %08x\n",
20596 + (unsigned int)regs->inst_cnt,
20597 + (unsigned int)regs->csr);
20599 + printk(KERN_NOTICE "int_mask0: %08x, int_mask1: %08x\n",
20600 + (unsigned int)regs->int_mask0,
20601 + (unsigned int)regs->int_mask1);
20604 + * Dump range registers
20606 + DUMP_RANGE_REGISTER("I", "0");
20607 + DUMP_RANGE_REGISTER("I", "1");
20608 + DUMP_RANGE_REGISTER("I", "2");
20609 + DUMP_RANGE_REGISTER("I", "3");
20610 + DUMP_RANGE_REGISTER("D", "0");
20611 + DUMP_RANGE_REGISTER("D", "1");
20612 + DUMP_RANGE_REGISTER("D", "2");
20613 + DUMP_RANGE_REGISTER("D", "3");
20614 + DUMP_RANGE_REGISTER("D", "4");
20616 + printk(KERN_NOTICE "frame_type: %d, nesting_level: %d, thread_type %d\n\n",
20617 + (int)regs->frame_type,
20618 + (int)regs->nesting_level,
20619 + (int)regs->thread_type);
20623 + * kernel_thread_helper()
20624 + * On execution d0 will be 0, d1 will be the argument to be passed to the
20625 + * kernel function. d2 contains the kernel function that needs to get
20626 + * called. d3 will contain address to do_exit which need to get moved
20627 + * into a5. On return from fork the child thread d0 will be 0. We call
20628 + * this dummy function which in turn loads the argument
20630 +asmlinkage void kernel_thread_helper(void);
20633 + * kernel_thread()
20634 + * Create a kernel thread
20636 +int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
20638 + struct pt_regs regs;
20640 + memset(®s, 0, sizeof(regs));
20642 + regs.dn[1] = (unsigned long)arg;
20643 + regs.dn[2] = (unsigned long)fn;
20644 + regs.dn[3] = (unsigned long)do_exit;
20645 + regs.an[5] = (unsigned long)kernel_thread_helper;
20646 + regs.pc = (unsigned long)kernel_thread_helper;
20647 + regs.nesting_level = 0;
20648 + regs.thread_type = KERNEL_THREAD;
20650 + return do_fork(flags | CLONE_VM | CLONE_UNTRACED,
20651 + 0, ®s, 0, NULL, NULL);
20653 +EXPORT_SYMBOL(kernel_thread);
20659 +void flush_thread(void)
20666 + * Not implemented on no-mmu.
20668 +asmlinkage int sys_fork(struct pt_regs *regs)
20670 + /* fork almost works, enough to trick you into looking elsewhere :-( */
20676 + * By the time we get here, the non-volatile registers have also been saved
20677 + * on the stack. We do some ugly pointer stuff here.. (see also copy_thread
20678 + * which does context copy).
20680 +asmlinkage int sys_vfork(struct pt_regs *regs)
20682 + unsigned long old_sp = regs->an[7];
20683 + unsigned long old_a5 = regs->an[5];
20684 + unsigned long old_return_address;
20685 + long do_fork_return;
20688 + * Read the old retrun address from the stack.
20690 + if (copy_from_user(&old_return_address,
20691 + (void *)old_sp, sizeof(unsigned long))) {
20692 + force_sig(SIGSEGV, current);
20697 + * Pop the vfork call frame by setting a5 and pc to the old_return
20698 + * address and incrementing the stack pointer by 4.
20700 + regs->an[5] = old_return_address;
20701 + regs->pc = old_return_address;
20702 + regs->an[7] += 4;
20704 + do_fork_return = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,
20705 + regs->an[7], regs, 0, NULL, NULL);
20708 + * Now we have to test if the return code is an error. If it is an error
20709 + * then restore the frame and we will execute error processing in user
20710 + * space. Other wise the child and the parent will return to the correct
20713 + if ((unsigned long)(do_fork_return) >= (unsigned long)(-125)) {
20715 + * Error case. We need to restore the frame.
20717 + regs->an[5] = old_a5;
20718 + regs->pc = old_a5;
20719 + regs->an[7] = old_sp;
20722 + return do_fork_return;
20727 + * creates a child thread.
20729 +asmlinkage int sys_clone(unsigned long clone_flags,
20730 + unsigned long newsp,
20731 + struct pt_regs *regs)
20734 + newsp = regs->an[7];
20735 + return do_fork(clone_flags, newsp, regs, 0,
20741 + * low level thread copy, only used by do_fork in kernel/fork.c
20743 +int copy_thread(unsigned long clone_flags,
20744 + unsigned long usp, unsigned long topstk,
20745 + struct task_struct *p, struct pt_regs *regs)
20748 + struct pt_regs *childregs;
20750 + childregs = (struct pt_regs *)
20751 + (task_stack_page(p) + THREAD_SIZE - 8) - 1;
20753 + *childregs = *regs;
20756 + * Set return value for child to be 0.
20758 + childregs->dn[0] = 0;
20761 + childregs->an[7] = usp;
20763 + childregs->an[7] = (unsigned long)task_stack_page(p) +
20767 + * Set up the switch_to frame to return to "ret_from_fork"
20769 + p->thread.a5 = (unsigned long)ret_from_fork;
20770 + p->thread.sp = (unsigned long)childregs;
20777 + * executes a new program.
20779 +asmlinkage int sys_execve(char *name, char **argv,
20780 + char **envp, struct pt_regs *regs)
20786 + filename = getname(name);
20787 + error = PTR_ERR(filename);
20788 + if (IS_ERR(filename))
20790 + error = do_execve(filename, argv, envp, regs);
20791 + putname(filename);
20792 + asm (" .global sys_execve_complete\n"
20793 + " sys_execve_complete:");
20800 + * Return saved PC of a blocked thread.
20802 +unsigned long thread_saved_pc(struct task_struct *tsk)
20804 + return tsk->thread.a5;
20808 +unsigned long get_wchan(struct task_struct *p)
20810 + unsigned long pc;
20813 + * If we don't have a process, or it is not the current
20814 + * one or not RUNNING, it makes no sense to ask for a
20817 + if (!p || p == current || p->state == TASK_RUNNING)
20821 + * TODO: If the process is in the middle of schedule, we
20822 + * are supposed to do something different but for now we
20823 + * will return the same thing in both situations.
20825 + pc = thread_saved_pc(p);
20826 + if (in_sched_functions(pc))
20833 + * Infrequently used interface to dump task registers to core files.
20835 +int dump_task_regs(struct task_struct *task, elf_gregset_t *elfregs)
20837 + struct pt_regs *regs = task_pt_regs(task);
20838 + *(struct pt_regs *)elfregs = *regs;
20844 + * __switch_to is the function that implements the contex save and
20845 + * switch within the kernel. Since this is a function call very few
20846 + * registers have to be saved to pull this off. d0 holds prev and we
20847 + * want to preserve it. prev_switch is a pointer to task->thread
20848 + * structure. This is where we will save the register state. next_switch
20849 + * is pointer to the next task's thread structure that holds the
20852 +asmlinkage void *__switch_to(struct task_struct *prev,
20853 + struct thread_struct *prev_switch,
20854 + struct thread_struct *next_switch)
20855 + __attribute__((naked));
20857 +++ b/arch/ubicom32/kernel/processor.c
20860 + * arch/ubicom32/kernel/processor.c
20861 + * Ubicom32 architecture processor info implementation.
20863 + * (C) Copyright 2009, Ubicom, Inc.
20865 + * This file is part of the Ubicom32 Linux Kernel Port.
20867 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
20868 + * it and/or modify it under the terms of the GNU General Public License
20869 + * as published by the Free Software Foundation, either version 2 of the
20870 + * License, or (at your option) any later version.
20872 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
20873 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
20874 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
20875 + * the GNU General Public License for more details.
20877 + * You should have received a copy of the GNU General Public License
20878 + * along with the Ubicom32 Linux Kernel Port. If not,
20879 + * see <http://www.gnu.org/licenses/>.
20881 + * Ubicom32 implementation derived from (with many thanks):
20886 +#include <linux/module.h>
20887 +#include <linux/kernel.h>
20888 +#include <linux/init.h>
20889 +#include <linux/sched.h>
20890 +#include <linux/interrupt.h>
20891 +#include <linux/irq.h>
20892 +#include <linux/profile.h>
20893 +#include <linux/clocksource.h>
20894 +#include <linux/types.h>
20895 +#include <linux/seq_file.h>
20896 +#include <linux/delay.h>
20897 +#include <linux/cpu.h>
20898 +#include <asm/devtree.h>
20899 +#include <asm/processor.h>
20900 +#include <asm/cpu.h>
20901 +#include <asm/ocm_size.h>
20904 + struct devtree_node dn;
20905 + unsigned int threads;
20906 + unsigned int timers;
20907 + unsigned int frequency;
20908 + unsigned int ddr_frequency;
20909 + unsigned int interrupt0;
20910 + unsigned int interrupt1;
20915 + unsigned int arch_version;
20916 + void *os_syscall_begin;
20917 + void *os_syscall_end;
20920 +struct procnode *pn;
20923 + * show_processorinfo()
20924 + * Print the actual processor information.
20926 +static void show_processorinfo(struct seq_file *m)
20928 + char *cpu, *mmu, *fpu;
20929 + unsigned int clockfreq;
20930 + unsigned int chipid;
20937 + "move.4 %0, CHIP_ID \n\t"
20942 + * General Processor Information.
20944 + seq_printf(m, "Vendor:\t\t%s\n", "Ubicom");
20945 + seq_printf(m, "CPU:\t\t%s\n", cpu);
20946 + seq_printf(m, "MMU:\t\t%s\n", mmu);
20947 + seq_printf(m, "FPU:\t\t%s\n", fpu);
20948 + seq_printf(m, "Arch:\t\t%hx\n", chipid >> 16);
20949 + seq_printf(m, "Rev:\t\t%hx\n", (chipid & 0xffff));
20952 + * Now compute the clock frequency in Mhz.
20954 + clockfreq = processor_frequency();
20955 + seq_printf(m, "Clock Freq:\t%u.0 MHz\n",
20956 + clockfreq / 1000000);
20957 + seq_printf(m, "DDR Freq:\t%u.0 MHz\n",
20958 + pn ? pn->ddr_frequency / 1000000 : 0);
20959 + seq_printf(m, "BogoMips:\t%lu.%02lu\n",
20960 + (loops_per_jiffy * HZ) / 500000,
20961 + ((loops_per_jiffy * HZ) / 5000) % 100);
20962 + seq_printf(m, "Calibration:\t%lu loops\n", (loops_per_jiffy * HZ));
20967 + * Get CPU information for use by the procfs.
20969 +static int show_cpuinfo(struct seq_file *m, void *v)
20971 + unsigned long n = (unsigned long)v - 1;
20973 +#if defined(CONFIG_SMP)
20974 + struct cpuinfo_ubicom32 *p = &per_cpu(cpu_data, n);
20978 + * Print the general processor information on the first
20982 + show_processorinfo(m);
20985 +#if defined(CONFIG_SMP)
20987 + * For each hwthread, print if this hwthread is running Linux
20988 + * or is an I/O thread.
20990 + if (cpu_isset(n, cpu_online_map)) {
20991 + seq_printf(m, "cpu[%02lu]:\tthread id - %lu\n", n, p->tid);
20993 + seq_printf(m, "cpu[%02lu]:\toff-line\n", n);
21000 +static void *c_start(struct seq_file *m, loff_t *pos)
21002 + unsigned long i = *pos;
21004 + return i < NR_CPUS ? (void *)(i + 1) : NULL;
21007 +static void *c_next(struct seq_file *m, void *v, loff_t *pos)
21010 + return c_start(m, pos);
21013 +static void c_stop(struct seq_file *m, void *v)
21017 +const struct seq_operations cpuinfo_op = {
21018 + .start = c_start,
21021 + .show = show_cpuinfo,
21025 + * processor_timers()
21026 + * Returns the timers available to Linux.
21028 +unsigned int processor_timers(void)
21033 + return pn->timers;
21037 + * processor_threads()
21038 + * Returns the threads available to Linux.
21040 +unsigned int processor_threads(void)
21045 + return pn->threads;
21049 + * processor_frequency()
21050 + * Returns the frequency of the system clock.
21052 +unsigned int processor_frequency(void)
21057 + return pn->frequency;
21059 +EXPORT_SYMBOL(processor_frequency);
21062 + * processor_interrupts()
21063 + * Return the interrupts that are setup at boot time.
21065 +int processor_interrupts(unsigned int *int0, unsigned int *int1)
21072 + *int0 = pn->interrupt0;
21076 + *int1 = pn->interrupt1;
21082 + * processor_ocm()
21083 + * Returns the start and end of OCM available to Linux.
21085 +void processor_ocm(unsigned long *socm, unsigned long *eocm)
21087 + *socm = (unsigned long)pn->socm;
21088 + *eocm = (unsigned long)pn->eocm;
21092 + * processor_dram()
21093 + * Returns the start and end of dram available to Linux.
21095 +void processor_dram(unsigned long *sdram, unsigned long *edram)
21097 + *sdram = (unsigned long)pn->sdram;
21098 + *edram = (unsigned long)pn->edram;
21102 + * processor_validate_failed()
21103 + * Returns the dram available to Linux.
21105 +static noinline void processor_validate_failed(void)
21112 + * processor_validate()
21113 + * Validates the procnode against limitations of this link/built.
21115 +static void processor_validate(void)
21117 + void *dram_start = (void *)(KERNELSTART);
21118 + void *dram_end = (void *)(SDRAMSTART + CONFIG_MIN_RAMSIZE);
21119 +#if APP_OCM_CODE_SIZE || APP_OCM_DATA_SIZE
21120 + void *ocm_code_start = (void *)(OCMSTART + APP_OCM_CODE_SIZE);
21121 + void *ocm_data_end = (void *)(OCMEND - APP_OCM_DATA_SIZE);
21123 + extern void __os_syscall_begin;
21124 + extern void __os_syscall_end;
21125 + int proc_node_valid = 1;
21128 + printk(KERN_ERR "ERROR: processor node not found\n");
21133 + if (dram_start < pn->sdram || dram_end > pn->edram) {
21134 + printk(KERN_ERR "ERROR: processor dram mismatch %p-%p "
21135 + "available but we are expecting %p-%p\n",
21136 + pn->sdram, pn->edram, dram_start, dram_end);
21137 + proc_node_valid = 0;
21139 + printk(KERN_ERR "processor dram %p-%p, expecting %p-%p\n",
21140 + pn->sdram, pn->edram, dram_start, dram_end);
21142 + if (&__os_syscall_begin < pn->os_syscall_begin ||
21143 + &__os_syscall_end > pn->os_syscall_end) {
21144 + printk(KERN_ERR "ERROR: processor syscall area mismatch "
21145 + "%p-%p available but we are expecting %p-%p\n",
21146 + pn->os_syscall_begin, pn->os_syscall_end,
21147 + &__os_syscall_begin, &__os_syscall_end);
21148 + proc_node_valid = 0;
21150 + printk(KERN_ERR "processor dram %p-%p, expecting %p-%p\n",
21151 + pn->sdram, pn->edram, dram_start, dram_end);
21153 +#if APP_OCM_CODE_SIZE || APP_OCM_DATA_SIZE
21154 + if (ocm_code_start < pn->socm || ocm_data_end > pn->eocm) {
21155 + printk(KERN_ERR "ERROR: processor ocm mismatch %p-%p "
21156 + "available but we are expecting %p-%p\n",
21157 + pn->socm, pn->eocm, ocm_code_start, ocm_data_end);
21158 + proc_node_valid = 0;
21160 + printk(KERN_INFO "processor ocm %p-%p, expecting %p-%p\n",
21161 + pn->socm, pn->eocm, ocm_code_start, ocm_data_end);
21166 + if (UBICOM32_ARCH_VERSION != pn->arch_version) {
21167 + printk(KERN_ERR "ERROR: processor arch mismatch, kernel"
21168 + "compiled for %d found %d\n",
21169 + UBICOM32_ARCH_VERSION, pn->arch_version);
21170 + proc_node_valid = 0;
21173 + if (proc_node_valid)
21176 + processor_validate_failed();
21179 +void __init processor_init(void)
21182 + * If we do not have a trap node in the device tree, we leave the fault
21183 + * handling to the underlying hardware.
21185 + pn = (struct procnode *)devtree_find_node("processor");
21187 + processor_validate();
21190 + * If necessary correct the initial range registers to cover the
21191 + * complete physical space
21193 + if (pn->edram > (void *)(SDRAMSTART + CONFIG_MIN_RAMSIZE)) {
21194 + printk(KERN_INFO "updating range registers for expanded dram\n");
21196 + " move.4 D_RANGE1_HI, %0 \t\n"
21197 + " move.4 I_RANGE0_HI, %0 \t\n"
21198 +#ifdef CONFIG_PROTECT_KERNEL
21199 + " move.4 D_RANGE2_HI, %0 \t\n"
21200 + " move.4 I_RANGE2_HI, %0 \t\n"
21202 + : : "a"((unsigned long)pn->edram - 4)
21208 +++ b/arch/ubicom32/kernel/ptrace.c
21211 + * arch/ubicom32/kernel/ptrace.c
21212 + * Ubicom32 architecture ptrace implementation.
21214 + * (C) Copyright 2009, Ubicom, Inc.
21215 + * (C) 1994 by Hamish Macdonald
21216 + * Taken from linux/kernel/ptrace.c and modified for M680x0.
21217 + * linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds
21219 + * This file is part of the Ubicom32 Linux Kernel Port.
21221 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
21222 + * it and/or modify it under the terms of the GNU General Public License
21223 + * as published by the Free Software Foundation, either version 2 of the
21224 + * License, or (at your option) any later version.
21226 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
21227 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
21228 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
21229 + * the GNU General Public License for more details.
21231 + * You should have received a copy of the GNU General Public License
21232 + * along with the Ubicom32 Linux Kernel Port. If not,
21233 + * see <http://www.gnu.org/licenses/>.
21235 + * Ubicom32 implementation derived from (with many thanks):
21241 +#include <linux/module.h>
21242 +#include <linux/kernel.h>
21243 +#include <linux/sched.h>
21244 +#include <linux/mm.h>
21245 +#include <linux/smp.h>
21246 +#include <linux/errno.h>
21247 +#include <linux/ptrace.h>
21248 +#include <linux/user.h>
21249 +#include <linux/signal.h>
21250 +#include <linux/uaccess.h>
21252 +#include <asm/page.h>
21253 +#include <asm/pgtable.h>
21254 +#include <asm/system.h>
21255 +#include <asm/cacheflush.h>
21256 +#include <asm/processor.h>
21259 + * ptrace_getregs()
21261 + * Get all user integer registers.
21263 +static inline int ptrace_getregs(struct task_struct *task, void __user *uregs)
21265 + struct pt_regs *regs = task_pt_regs(task);
21266 + return copy_to_user(uregs, regs, sizeof(struct pt_regs)) ? -EFAULT : 0;
21270 + * ptrace_get_reg()
21272 + * Get contents of register REGNO in task TASK.
21274 +static unsigned long ptrace_get_reg(struct task_struct *task, int regno)
21276 + if (regno < sizeof(struct pt_regs)) {
21277 + struct pt_regs *pt_regs = task_pt_regs(task);
21278 + return *(unsigned long *)((long) pt_regs + regno);
21285 + * ptrace_put_reg()
21286 + * Write contents of register REGNO in task TASK.
21288 +static int ptrace_put_reg(struct task_struct *task, int regno,
21289 + unsigned long data)
21291 + if (regno <= sizeof(struct pt_regs) && regno != PT_FRAME_TYPE) {
21292 + struct pt_regs *pt_regs = task_pt_regs(task);
21293 + *(unsigned long *)((long) pt_regs + regno) = data;
21300 + * ptrace_disable_single_step()
21301 + * Disable Single Step
21303 +static int ptrace_disable_single_step(struct task_struct *task)
21306 + * Single Step not yet implemented, so must always be disabled
21312 + * ptrace_disable()
21313 + * Make sure the single step bit is not set.
21314 + * Called by kernel/ptrace.c when detaching..
21316 +void ptrace_disable(struct task_struct *child)
21318 + ptrace_disable_single_step(child);
21323 + * architecture specific ptrace routine.
21325 +long arch_ptrace(struct task_struct *child, long request, long addr, long data)
21328 + switch (request) {
21329 + /* when I and D space are separate, these will need to be fixed. */
21330 + case PTRACE_PEEKTEXT: /* read word at location addr. */
21331 + case PTRACE_PEEKDATA:
21332 + ret = generic_ptrace_peekdata(child, addr, data);
21335 + /* read the word at location addr in the USER area. */
21336 + case PTRACE_PEEKUSR: {
21337 + unsigned long tmp;
21340 + if (((unsigned long) addr > PT_INTERP_FDPIC_LOADMAP)
21344 + tmp = 0; /* Default return condition */
21347 + if (addr < sizeof(struct pt_regs)) {
21348 + tmp = ptrace_get_reg(child, addr);
21349 + } else if (addr == PT_TEXT_ADDR) {
21350 + tmp = child->mm->start_code;
21351 + } else if (addr == PT_TEXT_END_ADDR) {
21352 + tmp = child->mm->end_code;
21353 + } else if (addr == PT_DATA_ADDR) {
21354 + tmp = child->mm->start_data;
21355 + } else if (addr == PT_EXEC_FDPIC_LOADMAP) {
21356 +#ifdef CONFIG_BINFMT_ELF_FDPIC
21357 + tmp = child->mm->context.exec_fdpic_loadmap;
21359 + } else if (addr == PT_INTERP_FDPIC_LOADMAP) {
21360 +#ifdef CONFIG_BINFMT_ELF_FDPIC
21361 + tmp = child->mm->context.interp_fdpic_loadmap;
21367 + ret = put_user(tmp, (unsigned long *)data);
21371 + case PTRACE_POKETEXT: /* write the word at location addr. */
21372 + case PTRACE_POKEDATA:
21373 + ret = generic_ptrace_pokedata(child, addr, data);
21376 + * If we just changed some code so we need to
21377 + * correct the caches
21379 + if (request == PTRACE_POKETEXT && ret == 0) {
21380 + flush_icache_range(addr, addr + 4);
21384 + case PTRACE_POKEUSR: /* write the word at location addr
21385 + * in the USER area */
21388 + if (((unsigned long) addr > PT_DATA_ADDR) || (addr & 3))
21391 + if (addr < sizeof(struct pt_regs)) {
21392 + ret = ptrace_put_reg(child, addr, data);
21396 + case PTRACE_SYSCALL: /* continue and stop at next (return from)
21398 + case PTRACE_CONT: { /* restart after signal. */
21401 + if (!valid_signal(data))
21403 + if (request == PTRACE_SYSCALL)
21404 + set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
21406 + clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
21407 + child->exit_code = data;
21408 + /* make sure the single step bit is not set. */
21409 + ptrace_disable_single_step(child);
21410 + wake_up_process(child);
21416 + * make the child exit. Best I can do is send it a sigkill.
21417 + * perhaps it should be put in the status that it wants to exit.
21419 + case PTRACE_KILL: {
21421 + if (child->exit_state == EXIT_ZOMBIE) /* already dead */
21423 + child->exit_code = SIGKILL;
21424 + /* make sure the single step bit is not set. */
21425 + ptrace_disable_single_step(child);
21426 + wake_up_process(child);
21430 + case PTRACE_DETACH: /* detach a process that was attached. */
21431 + ret = ptrace_detach(child, data);
21434 + case PTRACE_GETREGS: /* Get all gp regs from the child. */
21435 + ptrace_getregs(child, (unsigned long *)data);
21439 + case PTRACE_SETREGS: { /* Set all gp regs in the child. */
21441 + unsigned long tmp;
21442 + int count = sizeof(struct pt_regs) / sizeof(unsigned long);
21443 + for (i = 0; i < count; i++) {
21444 + if (get_user(tmp, (unsigned long *) data)) {
21448 + ptrace_put_reg(child, sizeof(unsigned long) * i, tmp);
21449 + data += sizeof(long);
21456 + return ptrace_request(child, request, addr, data);
21464 + * called by syscall enter/exit when the TIF_SYSCALL_TRACE bit is set.
21466 +asmlinkage void syscall_trace(void)
21468 + struct task_struct *cur = current;
21469 + if (!test_thread_flag(TIF_SYSCALL_TRACE))
21471 + if (!(cur->ptrace & PT_PTRACED))
21473 + ptrace_notify(SIGTRAP | ((cur->ptrace & PT_TRACESYSGOOD)
21476 + * this isn't the same as continuing with a signal, but it will do
21477 + * for normal use. strace only continues with a signal if the
21478 + * stopping signal is not SIGTRAP. -brl
21480 + if (cur->exit_code) {
21481 + send_sig(cur->exit_code, current, 1);
21482 + current->exit_code = 0;
21486 +++ b/arch/ubicom32/kernel/semaphore.c
21489 + * arch/ubicom32/kernel/semaphore.c
21490 + * Ubicom32 architecture semaphore implementation.
21492 + * (C) Copyright 2009, Ubicom, Inc.
21494 + * This file is part of the Ubicom32 Linux Kernel Port.
21496 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
21497 + * it and/or modify it under the terms of the GNU General Public License
21498 + * as published by the Free Software Foundation, either version 2 of the
21499 + * License, or (at your option) any later version.
21501 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
21502 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
21503 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
21504 + * the GNU General Public License for more details.
21506 + * You should have received a copy of the GNU General Public License
21507 + * along with the Ubicom32 Linux Kernel Port. If not,
21508 + * see <http://www.gnu.org/licenses/>.
21510 + * Ubicom32 implementation derived from (with many thanks):
21516 + * Generic semaphore code. Buyer beware. Do your own
21517 + * specific changes in <asm/semaphore-helper.h>
21520 +#include <linux/sched.h>
21521 +#include <linux/err.h>
21522 +#include <linux/init.h>
21523 +#include <asm/semaphore-helper.h>
21525 +#ifndef CONFIG_RMW_INSNS
21526 +spinlock_t semaphore_wake_lock;
21530 + * Semaphores are implemented using a two-way counter:
21531 + * The "count" variable is decremented for each process
21532 + * that tries to sleep, while the "waking" variable is
21533 + * incremented when the "up()" code goes to wake up waiting
21536 + * Notably, the inline "up()" and "down()" functions can
21537 + * efficiently test if they need to do any extra work (up
21538 + * needs to do something only if count was negative before
21539 + * the increment operation.
21541 + * waking_non_zero() (from asm/semaphore.h) must execute
21544 + * When __up() is called, the count was negative before
21545 + * incrementing it, and we need to wake up somebody.
21547 + * This routine adds one to the count of processes that need to
21548 + * wake up and exit. ALL waiting processes actually wake up but
21549 + * only the one that gets to the "waking" field first will gate
21550 + * through and acquire the semaphore. The others will go back
21553 + * Note that these functions are only called when there is
21554 + * contention on the lock, and as such all this is the
21555 + * "non-critical" part of the whole semaphore business. The
21556 + * critical part is the inline stuff in <asm/semaphore.h>
21557 + * where we want to avoid any extra jumps and calls.
21559 +void __up(struct semaphore *sem)
21561 + wake_one_more(sem);
21562 + wake_up(&sem->wait);
21566 + * Perform the "down" function. Return zero for semaphore acquired,
21567 + * return negative for signalled out of the function.
21569 + * If called from __down, the return is ignored and the wait loop is
21570 + * not interruptible. This means that a task waiting on a semaphore
21571 + * using "down()" cannot be killed until someone does an "up()" on
21574 + * If called from __down_interruptible, the return value gets checked
21575 + * upon return. If the return value is negative then the task continues
21576 + * with the negative value in the return register (it can be tested by
21579 + * Either form may be used in conjunction with "up()".
21584 +#define DOWN_HEAD(task_state) \
21587 + current->state = (task_state); \
21588 + add_wait_queue(&sem->wait, &wait); \
21591 + * Ok, we're set up. sem->count is known to be less than zero \
21592 + * so we must wait. \
21594 + * We can let go the lock for purposes of waiting. \
21595 + * We re-acquire it after awaking so as to protect \
21596 + * all semaphore operations. \
21598 + * If "up()" is called before we call waking_non_zero() then \
21599 + * we will catch it right away. If it is called later then \
21600 + * we will have to go through a wakeup cycle to catch it. \
21602 + * Multiple waiters contend for the semaphore lock to see \
21603 + * who gets to gate through and who has to wait some more. \
21607 +#define DOWN_TAIL(task_state) \
21608 + current->state = (task_state); \
21610 + current->state = TASK_RUNNING; \
21611 + remove_wait_queue(&sem->wait, &wait);
21613 +void __sched __down(struct semaphore *sem)
21615 + DECLARE_WAITQUEUE(wait, current);
21617 + DOWN_HEAD(TASK_UNINTERRUPTIBLE)
21618 + if (waking_non_zero(sem))
21621 + DOWN_TAIL(TASK_UNINTERRUPTIBLE)
21624 +int __sched __down_interruptible(struct semaphore *sem)
21626 + DECLARE_WAITQUEUE(wait, current);
21629 + DOWN_HEAD(TASK_INTERRUPTIBLE)
21631 + ret = waking_non_zero_interruptible(sem, current);
21634 + /* ret != 0 only if we get interrupted -arca */
21639 + DOWN_TAIL(TASK_INTERRUPTIBLE)
21643 +int __down_trylock(struct semaphore *sem)
21645 + return waking_non_zero_trylock(sem);
21648 +++ b/arch/ubicom32/kernel/setup.c
21651 + * arch/ubicom32/kernel/setup.c
21652 + * Ubicom32 architecture-dependent parts of system setup.
21654 + * (C) Copyright 2009, Ubicom, Inc.
21655 + * Copyright (C) 1999-2007 Greg Ungerer (gerg@snapgear.com)
21656 + * Copyright (C) 1998,1999 D. Jeff Dionne <jeff@uClinux.org>
21657 + * Copyleft ()) 2000 James D. Schettine {james@telos-systems.com}
21658 + * Copyright (C) 1998 Kenneth Albanowski <kjahds@kjahds.com>
21659 + * Copyright (C) 1995 Hamish Macdonald
21660 + * Copyright (C) 2000 Lineo Inc. (www.lineo.com)
21661 + * Copyright (C) 2001 Lineo, Inc. <www.lineo.com>
21662 + * 68VZ328 Fixes/support Evan Stawnyczy <e@lineo.ca>
21664 + * This file is part of the Ubicom32 Linux Kernel Port.
21666 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
21667 + * it and/or modify it under the terms of the GNU General Public License
21668 + * as published by the Free Software Foundation, either version 2 of the
21669 + * License, or (at your option) any later version.
21671 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
21672 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
21673 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
21674 + * the GNU General Public License for more details.
21676 + * You should have received a copy of the GNU General Public License
21677 + * along with the Ubicom32 Linux Kernel Port. If not,
21678 + * see <http://www.gnu.org/licenses/>.
21680 + * Ubicom32 implementation derived from (with many thanks):
21686 +#include <linux/kernel.h>
21687 +#include <linux/sched.h>
21688 +#include <linux/delay.h>
21689 +#include <linux/interrupt.h>
21690 +#include <linux/fb.h>
21691 +#include <linux/module.h>
21692 +#include <linux/console.h>
21693 +#include <linux/errno.h>
21694 +#include <linux/string.h>
21695 +#include <linux/bootmem.h>
21696 +#include <linux/seq_file.h>
21697 +#include <linux/init.h>
21699 +#include <asm/devtree.h>
21700 +#include <asm/setup.h>
21701 +#include <asm/irq.h>
21702 +#include <asm/machdep.h>
21703 +#include <asm/pgtable.h>
21704 +#include <asm/pgalloc.h>
21705 +#include <asm/ubicom32-common.h>
21706 +#include <asm/processor.h>
21707 +#include <asm/bootargs.h>
21708 +#include <asm/thread.h>
21710 +unsigned long memory_start;
21711 +EXPORT_SYMBOL(memory_start);
21713 +unsigned long memory_end;
21714 +EXPORT_SYMBOL(memory_end);
21716 +static char __initdata command_line[COMMAND_LINE_SIZE];
21717 +#ifdef CONFIG_CMDLINE_BOOL
21718 +static char __initdata builtin_cmdline[COMMAND_LINE_SIZE] = CONFIG_CMDLINE;
21721 +extern int _stext, _etext, _sdata, _edata, _sbss, _ebss, _end;
21725 + * Setup the architecture dependent portions of the system.
21727 +void __init setup_arch(char **cmdline_p)
21729 + int bootmap_size;
21730 + unsigned long ram_start;
21732 + processor_init();
21736 + * Use the link for memory_start from the link and the processor
21737 + * node for memory_end.
21739 + memory_start = PAGE_ALIGN(((unsigned long)&_end));
21740 + processor_dram(&ram_start, &memory_end);
21742 + init_mm.start_code = (unsigned long) &_stext;
21743 + init_mm.end_code = (unsigned long) &_etext;
21744 + init_mm.end_data = (unsigned long) &_edata;
21745 + init_mm.brk = (unsigned long) 0;
21748 + * bootexec copies the original default command line to end of memory.
21749 + * u-boot can modify it there (i.e. to enable network boot) and the
21750 + * kernel picks up the modified version.
21752 + * mainexec creates a `new default' command_line which is in the
21753 + * bootargs devnode. It is updated on every firmware update but
21754 + * not used at the moment.
21756 + strlcpy(boot_command_line, (char *)(memory_end - COMMAND_LINE_SIZE), COMMAND_LINE_SIZE);
21758 +#ifdef CONFIG_CMDLINE_BOOL
21759 +#ifdef CONFIG_CMDLINE_OVERRIDE
21760 + strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE);
21762 + if (builtin_cmdline[0]) {
21763 + /* append boot loader cmdline to builtin */
21764 + strlcat(builtin_cmdline, " ", COMMAND_LINE_SIZE);
21765 + strlcat(builtin_cmdline, boot_command_line, COMMAND_LINE_SIZE);
21766 + strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE);
21771 + strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
21772 + *cmdline_p = command_line;
21774 + parse_early_param();
21776 + printk(KERN_INFO "%s Processor, Ubicom, Inc. <www.ubicom.com>\n", CPU);
21778 +#if defined(DEBUG)
21779 + printk(KERN_DEBUG "KERNEL -> TEXT=0x%06x-0x%06x DATA=0x%06x-0x%06x "
21780 + "BSS=0x%06x-0x%06x\n", (int) &_stext, (int) &_etext,
21781 + (int) &_sdata, (int) &_edata,
21782 + (int) &_sbss, (int) &_ebss);
21783 + printk(KERN_DEBUG "MEMORY -> ROMFS=0x%06x-0x%06x MEM=0x%06x-0x%06x\n ",
21784 + (int) &_ebss, (int) memory_start,
21785 + (int) memory_start, (int) memory_end);
21789 + if (strlen(*cmdline_p))
21790 + printk(KERN_DEBUG "Command line: '%s'\n", *cmdline_p);
21793 +#if defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_DUMMY_CONSOLE)
21794 + conswitchp = &dummy_con;
21798 + * If we have a device tree, see if we have the nodes we need.
21805 + * From the arm initialization comment:
21807 + * This doesn't seem to be used by the Linux memory manager any
21808 + * more, but is used by ll_rw_block. If we can get rid of it, we
21809 + * also get rid of some of the stuff above as well.
21811 + * Note: max_low_pfn and max_pfn reflect the number of _pages_ in
21812 + * the system, not the maximum PFN.
21814 + max_pfn = max_low_pfn = (memory_end - PAGE_OFFSET) >> PAGE_SHIFT;
21817 + * Give all the memory to the bootmap allocator, tell it to put the
21818 + * boot mem_map at the start of memory.
21820 + bootmap_size = init_bootmem_node(
21822 + memory_start >> PAGE_SHIFT, /* map goes here */
21823 + PAGE_OFFSET >> PAGE_SHIFT, /* 0 on coldfire */
21824 + memory_end >> PAGE_SHIFT);
21826 + * Free the usable memory, we have to make sure we do not free
21827 + * the bootmem bitmap so we then reserve it after freeing it :-)
21829 + free_bootmem(memory_start, memory_end - memory_start);
21830 + reserve_bootmem(memory_start, bootmap_size, BOOTMEM_DEFAULT);
21833 + * Get kmalloc into gear.
21838 + * Fix up the thread_info structure, indicate this is a mainline Linux
21839 + * thread and setup the sw_ksp().
21841 + sw_ksp[thread_get_self()] = (unsigned int) current_thread_info();
21842 + thread_set_mainline(thread_get_self());
21845 +++ b/arch/ubicom32/kernel/signal.c
21848 + * arch/ubicom32/kernel/signal.c
21849 + * Ubicom32 architecture signal handling implementation.
21851 + * (C) Copyright 2009, Ubicom, Inc.
21852 + * Copyright (C) 1991, 1992 Linus Torvalds
21853 + * Linux/m68k support by Hamish Macdonald
21854 + * 68060 fixes by Jesper Skov
21855 + * 1997-12-01 Modified for POSIX.1b signals by Andreas Schwab
21856 + * mathemu support by Roman Zippel
21857 + * ++roman (07/09/96): implemented signal stacks
21859 + * This file is part of the Ubicom32 Linux Kernel Port.
21861 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
21862 + * it and/or modify it under the terms of the GNU General Public License
21863 + * as published by the Free Software Foundation, either version 2 of the
21864 + * License, or (at your option) any later version.
21866 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
21867 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
21868 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
21869 + * the GNU General Public License for more details.
21871 + * You should have received a copy of the GNU General Public License
21872 + * along with the Ubicom32 Linux Kernel Port. If not,
21873 + * see <http://www.gnu.org/licenses/>.
21875 + * Ubicom32 implementation derived from (with many thanks):
21880 + * mathemu support by Roman Zippel
21881 + * (Note: fpstate in the signal context is completely ignored for the emulator
21882 + * and the internal floating point format is put on stack)
21884 + * ++roman (07/09/96): implemented signal stacks (specially for tosemu on
21885 + * Atari :-) Current limitation: Only one sigstack can be active at one time.
21886 + * If a second signal with SA_ONSTACK set arrives while working on a sigstack,
21887 + * SA_ONSTACK is ignored. This behaviour avoids lots of trouble with nested
21888 + * signal handlers!
21891 +#include <linux/module.h>
21892 +#include <linux/sched.h>
21893 +#include <linux/mm.h>
21894 +#include <linux/kernel.h>
21895 +#include <linux/signal.h>
21896 +#include <linux/syscalls.h>
21897 +#include <linux/errno.h>
21898 +#include <linux/wait.h>
21899 +#include <linux/ptrace.h>
21900 +#include <linux/unistd.h>
21901 +#include <linux/stddef.h>
21902 +#include <linux/highuid.h>
21903 +#include <linux/tty.h>
21904 +#include <linux/personality.h>
21905 +#include <linux/binfmts.h>
21907 +#include <asm/setup.h>
21908 +#include <asm/uaccess.h>
21909 +#include <asm/pgtable.h>
21910 +#include <asm/traps.h>
21911 +#include <asm/ucontext.h>
21913 +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
21916 + * asm signal return handlers.
21918 +void ret_from_user_signal(void);
21919 +void ret_from_user_rt_signal(void);
21920 +asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs);
21923 + * Common signal suspend implementation
21925 +static int signal_suspend(sigset_t *saveset, struct pt_regs *regs)
21927 + regs->dn[0] = -EINTR;
21929 + current->state = TASK_INTERRUPTIBLE;
21931 + if (!do_signal(saveset, regs)) {
21935 + * If the current frame type is a signal trampoline we are
21936 + * actually going to call the signal handler so we return the
21937 + * desired d0 as the return value.
21939 + if (regs->frame_type == UBICOM32_FRAME_TYPE_SIGTRAMP) {
21940 + return regs->dn[0];
21945 + * Should never get here
21952 + * Atomically swap in the new signal mask, and wait for a signal.
21954 +asmlinkage int do_sigsuspend(struct pt_regs *regs)
21956 + old_sigset_t mask = regs->dn[0];
21957 + sigset_t saveset;
21959 + mask &= _BLOCKABLE;
21960 + spin_lock_irq(¤t->sighand->siglock);
21961 + saveset = current->blocked;
21962 + siginitset(¤t->blocked, mask);
21963 + recalc_sigpending();
21964 + spin_unlock_irq(¤t->sighand->siglock);
21967 + * Call common handler
21969 + return signal_suspend(&saveset, regs);
21973 +do_rt_sigsuspend(struct pt_regs *regs)
21975 + sigset_t *unewset = (sigset_t *)regs->dn[0];
21976 + size_t sigsetsize = (size_t)regs->dn[1];
21977 + sigset_t saveset, newset;
21979 + /* XXX: Don't preclude handling different sized sigset_t's. */
21980 + if (sigsetsize != sizeof(sigset_t))
21983 + if (copy_from_user(&newset, unewset, sizeof(newset)))
21985 + sigdelsetmask(&newset, ~_BLOCKABLE);
21987 + spin_lock_irq(¤t->sighand->siglock);
21988 + saveset = current->blocked;
21989 + current->blocked = newset;
21990 + recalc_sigpending();
21991 + spin_unlock_irq(¤t->sighand->siglock);
21994 + * Call common handler
21996 + return signal_suspend(&saveset, regs);
22000 +sys_sigaction(int sig, const struct old_sigaction *act,
22001 + struct old_sigaction *oact)
22003 + struct k_sigaction new_ka, old_ka;
22007 + old_sigset_t mask;
22008 + if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
22009 + __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
22010 + __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
22012 + __get_user(new_ka.sa.sa_flags, &act->sa_flags);
22013 + __get_user(mask, &act->sa_mask);
22014 + siginitset(&new_ka.sa.sa_mask, mask);
22017 + ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
22019 + if (!ret && oact) {
22020 + if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
22021 + __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
22022 + __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
22024 + __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
22025 + __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
22032 +do_sys_sigaltstack(struct pt_regs *regs)
22034 + const stack_t *uss = (stack_t *) regs->dn[0];
22035 + stack_t *uoss = (stack_t *)regs->dn[1];
22036 + return do_sigaltstack(uss, uoss, regs->an[7]);
22040 + * fdpic_func_descriptor describes sa_handler when the application is FDPIC
22042 +struct fdpic_func_descriptor {
22043 + unsigned long text;
22044 + unsigned long GOT;
22048 + * rt_sigframe is stored on the user stack immediately before (above)
22049 + * the signal handlers stack.
22051 +struct rt_sigframe
22053 + unsigned long syscall_number; /* This holds __NR_rt_sigreturn. */
22054 + unsigned long restore_all_regs; /* This field gets set to 1 if the frame
22055 + * type is TRAP or INTERRUPT. */
22057 + struct ucontext uc;
22063 + * Do a signal return; undo the signal stack.
22065 +asmlinkage int do_sigreturn(unsigned long __unused)
22071 +asmlinkage int do_rt_sigreturn(struct pt_regs *regs)
22073 + unsigned long usp = regs->an[7];
22074 + struct rt_sigframe *frame = (struct rt_sigframe *)(usp);
22077 + if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
22079 + if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
22082 + sigdelsetmask(&set, ~_BLOCKABLE);
22083 + spin_lock_irq(¤t->sighand->siglock);
22084 + current->blocked = set;
22085 + recalc_sigpending();
22086 + spin_unlock_irq(¤t->sighand->siglock);
22088 + if (copy_from_user(regs, &frame->uc.uc_mcontext, sizeof(struct pt_regs)))
22090 + return regs->dn[0];
22093 + force_sig(SIGSEGV, current);
22097 +static inline void *
22098 +get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
22100 + unsigned long usp;
22102 + /* Default to using normal stack. */
22103 + usp = regs->an[7];
22105 + /* This is the X/Open sanctioned signal stack switching. */
22106 + if (ka->sa.sa_flags & SA_ONSTACK) {
22107 + if (!sas_ss_flags(usp))
22108 + usp = current->sas_ss_sp + current->sas_ss_size;
22110 + return (void *)((usp - frame_size) & ~0x3);
22114 + * signal_trampoline: Defined in ubicom32_syscall.S
22116 +asmlinkage void signal_trampoline(void)__attribute__((naked));
22118 +static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
22119 + sigset_t *set, struct pt_regs *regs)
22121 + struct rt_sigframe *frame;
22124 + frame = (struct rt_sigframe *) get_sigframe(ka, regs, sizeof(*frame));
22127 + * The 'err |=' have been may criticized as bad code style, but I
22128 + * strongly suspect that we want this code to be fast. So for
22129 + * now it stays as is.
22131 + err |= __put_user( ( (current_thread_info()->exec_domain)
22132 + && (current_thread_info()->exec_domain->signal_invmap)
22134 + ? current_thread_info()->exec_domain->signal_invmap[sig]
22135 + : sig, &frame->sig);
22136 + err |= __put_user(info, &frame->info);
22138 + /* Create the ucontext. */
22139 + err |= __put_user(0, &frame->uc.uc_flags);
22140 + err |= __put_user(0, &frame->uc.uc_link);
22141 + err |= __put_user((void *)current->sas_ss_sp,
22142 + &frame->uc.uc_stack.ss_sp);
22143 + err |= __put_user(sas_ss_flags(regs->an[7]),
22144 + &frame->uc.uc_stack.ss_flags);
22145 + err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
22146 + err |= __put_user(__NR_rt_sigreturn, &frame->syscall_number);
22147 + if ((regs->frame_type == UBICOM32_FRAME_TYPE_TRAP) ||
22148 + (regs->frame_type == UBICOM32_FRAME_TYPE_INTERRUPT)) {
22149 + err |= __put_user(1, &frame->restore_all_regs);
22151 + err |= __put_user(0, &frame->restore_all_regs);
22153 + err |= copy_to_user (&frame->uc.uc_mcontext.sc_regs, regs, sizeof(struct pt_regs));
22154 + err |= copy_to_user (&frame->uc.uc_sigmask, set, sizeof(*set));
22157 + goto give_sigsegv;
22160 + * Set up registers for signal handler NOTE: Do not modify dn[14], it
22161 + * contains the userspace tls pointer, so it important that it carries
22162 + * over to the signal handler.
22164 + regs->an[7] = (unsigned long)frame;
22165 + regs->pc = (unsigned long) signal_trampoline;
22166 + regs->an[5] = (unsigned long) signal_trampoline;
22167 + regs->dn[0] = sig;
22168 + regs->dn[1] = (unsigned long) frame->info;
22169 + regs->dn[2] = (unsigned int) &frame->uc;
22172 + * If this is FDPIC then the signal handler is actually a function
22175 + if (current->personality & FDPIC_FUNCPTRS) {
22176 + struct fdpic_func_descriptor __user *funcptr =
22177 + (struct fdpic_func_descriptor *) ka->sa.sa_handler;
22178 + err |= __get_user(regs->dn[3], &funcptr->text);
22179 + err |= __get_user(regs->an[0], &funcptr->GOT);
22181 + goto give_sigsegv;
22184 + * The funcdesc must be in a3 as this is required for the lazy
22185 + * resolver in ld.so, if the application is not FDPIC a3 is not
22188 + regs->an[3] = (unsigned long) funcptr;
22191 + regs->dn[3] = (unsigned long)ka->sa.sa_handler;
22195 + regs->frame_type = UBICOM32_FRAME_TYPE_SIGTRAMP;
22200 + /* user space exception */
22201 + force_sigsegv(sig, current);
22204 +static inline void
22205 +handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
22207 + switch (regs->dn[0]) {
22208 + case -ERESTARTNOHAND:
22209 + if (!has_handler)
22211 + regs->dn[0] = -EINTR;
22214 + case -ERESTARTSYS:
22215 + if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) {
22216 + regs->dn[0] = -EINTR;
22219 + /* fallthrough */
22220 + case -ERESTARTNOINTR:
22222 + regs->dn[0] = regs->original_dn_0;
22224 + regs->an[5] -= 8;
22230 + * OK, we're invoking a handler
22233 +handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
22234 + sigset_t *oldset, struct pt_regs *regs)
22236 + /* are we from a system call? */
22237 + if (regs->frame_type == -1)
22238 + /* If so, check system call restarting.. */
22239 + handle_restart(regs, ka, 1);
22241 + /* set up the stack frame */
22242 + setup_rt_frame(sig, ka, info, oldset, regs);
22244 + if (ka->sa.sa_flags & SA_ONESHOT)
22245 + ka->sa.sa_handler = SIG_DFL;
22247 + spin_lock_irq(¤t->sighand->siglock);
22248 + sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
22249 + if (!(ka->sa.sa_flags & SA_NODEFER))
22250 + sigaddset(¤t->blocked,sig);
22251 + recalc_sigpending();
22252 + spin_unlock_irq(¤t->sighand->siglock);
22256 + * Note that 'init' is a special process: it doesn't get signals it doesn't
22257 + * want to handle. Thus you cannot kill init even with a SIGKILL even by
22260 +asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
22262 + struct k_sigaction ka;
22267 + * We want the common case to go fast, which
22268 + * is why we may in certain cases get here from
22269 + * kernel mode. Just return without doing anything
22272 + if (!user_mode(regs))
22276 + oldset = ¤t->blocked;
22278 + signr = get_signal_to_deliver(&info, &ka, regs, NULL);
22280 + /* Whee! Actually deliver the signal. */
22281 + handle_signal(signr, &ka, &info, oldset, regs);
22285 + /* Did we come from a system call? */
22286 + if (regs->frame_type == -1) {
22287 + /* Restart the system call - no handlers present */
22288 + handle_restart(regs, NULL, 0);
22295 + * sys_sigreturn()
22296 + * Return handler for signal clean-up.
22298 + * NOTE: Ubicom32 does not use this syscall. Instead we rely
22299 + * on do_rt_sigreturn().
22301 +asmlinkage long sys_sigreturn(void)
22306 +++ b/arch/ubicom32/kernel/smp.c
22309 + * arch/ubicom32/kernel/smp.c
22310 + * SMP implementation for Ubicom32 processors.
22312 + * (C) Copyright 2009, Ubicom, Inc.
22313 + * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
22314 + * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
22315 + * Copyright (C) 2001,2004 Grant Grundler <grundler@parisc-linux.org>
22317 + * This file is part of the Ubicom32 Linux Kernel Port.
22319 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
22320 + * it and/or modify it under the terms of the GNU General Public License
22321 + * as published by the Free Software Foundation, either version 2 of the
22322 + * License, or (at your option) any later version.
22324 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
22325 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
22326 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
22327 + * the GNU General Public License for more details.
22329 + * You should have received a copy of the GNU General Public License
22330 + * along with the Ubicom32 Linux Kernel Port. If not,
22331 + * see <http://www.gnu.org/licenses/>.
22333 + * Ubicom32 implementation derived from (with many thanks):
22339 +#include <linux/types.h>
22340 +#include <linux/spinlock.h>
22341 +#include <linux/slab.h>
22343 +#include <linux/kernel.h>
22344 +#include <linux/bootmem.h>
22345 +#include <linux/module.h>
22346 +#include <linux/sched.h>
22347 +#include <linux/init.h>
22348 +#include <linux/interrupt.h>
22349 +#include <linux/smp.h>
22350 +#include <linux/kernel_stat.h>
22351 +#include <linux/mm.h>
22352 +#include <linux/err.h>
22353 +#include <linux/delay.h>
22354 +#include <linux/bitops.h>
22355 +#include <linux/cpu.h>
22356 +#include <linux/profile.h>
22357 +#include <linux/delay.h>
22358 +#include <linux/io.h>
22359 +#include <linux/ptrace.h>
22360 +#include <linux/unistd.h>
22361 +#include <linux/irq.h>
22363 +#include <asm/system.h>
22364 +#include <asm/atomic.h>
22365 +#include <asm/current.h>
22366 +#include <asm/tlbflush.h>
22367 +#include <asm/timex.h>
22368 +#include <asm/cpu.h>
22369 +#include <asm/irq.h>
22370 +#include <asm/processor.h>
22371 +#include <asm/thread.h>
22372 +#include <asm/sections.h>
22373 +#include <asm/ip5000.h>
22376 + * Mask the debug printout for IPI because they are too verbose
22377 + * for regular debugging.
22380 +// #define DEBUG_SMP 1
22381 +#if !defined(DEBUG_SMP)
22382 +#define smp_debug(lvl, ...)
22384 +static unsigned int smp_debug_lvl = 50;
22385 +#define smp_debug(lvl, printargs...) \
22386 + if (lvl >= smp_debug_lvl) { \
22387 + printk(printargs); \
22391 +#if !defined(DEBUG_SMP)
22392 +#define DEBUG_ASSERT(cond)
22394 +#define DEBUG_ASSERT(cond) \
22401 + * List of IPI Commands (more than one can be set at a time).
22403 +enum ipi_message_type {
22407 + IPI_CALL_FUNC_SINGLE,
22413 + * We maintain a hardware thread oriented view of online threads
22414 + * and those involved or needing IPI.
22416 +static volatile unsigned long smp_online_threads = 0;
22417 +static volatile unsigned long smp_needs_ipi = 0;
22418 +static volatile unsigned long smp_inside_ipi = 0;
22419 +static unsigned long smp_irq_affinity[NR_IRQS];
22422 + * What do we need to track on a per cpu/thread basis?
22424 +DEFINE_PER_CPU(struct cpuinfo_ubicom32, cpu_data);
22427 + * Each thread cpuinfo IPI information is guarded by a lock
22428 + * that is kept local to this file.
22430 +DEFINE_PER_CPU(spinlock_t, ipi_lock) = SPIN_LOCK_UNLOCKED;
22433 + * The IPI(s) are based on a software IRQ through the LDSR.
22435 +unsigned int smp_ipi_irq;
22438 + * Define a spinlock so that only one cpu is able to modify the
22439 + * smp_needs_ipi and to set/clear the IRQ at a time.
22441 +DEFINE_SPINLOCK(smp_ipi_lock);
22444 + * smp_halt_processor()
22445 + * Halt this hardware thread.
22447 +static void smp_halt_processor(void)
22449 + int cpuid = thread_get_self();
22450 + cpu_clear(smp_processor_id(), cpu_online_map);
22451 + local_irq_disable();
22452 + printk(KERN_EMERG "cpu[%d] has halted. It is not OK to turn off power \
22453 + until all cpu's are off.\n", cpuid);
22455 + thread_suspend();
22460 + * ipi_interrupt()
22461 + * Handle an Interprocessor Interrupt.
22463 +static irqreturn_t ipi_interrupt(int irq, void *dev_id)
22465 + int cpuid = smp_processor_id();
22466 + struct cpuinfo_ubicom32 *p = &per_cpu(cpu_data, cpuid);
22467 + unsigned long ops;
22470 + * Count this now; we may make a call that never returns.
22475 + * We are about to process all ops. If another cpu has stated
22476 + * that we need an IPI, we will have already processed it. By
22477 + * clearing our smp_needs_ipi, and processing all ops,
22478 + * we reduce the number of IPI interrupts. However, this introduces
22479 + * the possibility that smp_needs_ipi will be clear and the soft irq
22480 + * will have gone off; so we need to make the get_affinity() path
22481 + * tolerant of spurious interrupts.
22483 + spin_lock(&smp_ipi_lock);
22484 + smp_needs_ipi &= ~(1 << p->tid);
22485 + spin_unlock(&smp_ipi_lock);
22489 + * Read the set of IPI commands we should handle.
22491 + spinlock_t *lock = &per_cpu(ipi_lock, cpuid);
22493 + ops = p->ipi_pending;
22494 + p->ipi_pending = 0;
22495 + spin_unlock(lock);
22498 + * If we have no IPI commands to execute, break out.
22505 + * Execute the set of commands in the ops word, one command
22506 + * at a time in no particular order. Strip of each command
22507 + * as we execute it.
22510 + unsigned long which = ffz(~ops);
22511 + ops &= ~(1 << which);
22513 + BUG_ON(!irqs_disabled());
22516 + smp_debug(100, KERN_INFO "cpu[%d]: "
22517 + "IPI_NOP\n", cpuid);
22520 + case IPI_RESCHEDULE:
22522 + * Reschedule callback. Everything to be
22523 + * done is done by the interrupt return path.
22525 + smp_debug(200, KERN_INFO "cpu[%d]: "
22526 + "IPI_RESCHEDULE\n", cpuid);
22529 + case IPI_CALL_FUNC:
22530 + smp_debug(100, KERN_INFO "cpu[%d]: "
22531 + "IPI_CALL_FUNC\n", cpuid);
22532 + generic_smp_call_function_interrupt();
22535 + case IPI_CALL_FUNC_SINGLE:
22536 + smp_debug(100, KERN_INFO "cpu[%d]: "
22537 + "IPI_CALL_FUNC_SINGLE\n", cpuid);
22538 + generic_smp_call_function_single_interrupt();
22541 + case IPI_CPU_STOP:
22542 + smp_debug(100, KERN_INFO "cpu[%d]: "
22543 + "IPI_CPU_STOP\n", cpuid);
22544 + smp_halt_processor();
22547 +#if !defined(CONFIG_LOCAL_TIMERS)
22548 + case IPI_CPU_TIMER:
22549 + smp_debug(100, KERN_INFO "cpu[%d]: "
22550 + "IPI_CPU_TIMER\n", cpuid);
22551 +#if defined(CONFIG_GENERIC_CLOCKEVENTS)
22552 + local_timer_interrupt();
22554 + update_process_times(user_mode(get_irq_regs()));
22555 + profile_tick(CPU_PROFILING);
22561 + printk(KERN_CRIT "cpu[%d]: "
22562 + "Unknown IPI: %lu\n", cpuid, which);
22568 + * Let in any pending interrupts
22570 + BUG_ON(!irqs_disabled());
22571 + local_irq_enable();
22572 + local_irq_disable();
22575 + return IRQ_HANDLED;
22580 + * Send an Interprocessor Interrupt.
22582 +static void ipi_send(int cpu, enum ipi_message_type op)
22584 + struct cpuinfo_ubicom32 *p = &per_cpu(cpu_data, cpu);
22585 + spinlock_t *lock = &per_cpu(ipi_lock, cpu);
22586 + unsigned long flags;
22589 + * We protect the setting of the ipi_pending field and ensure
22590 + * that the ipi delivery mechanism and interrupt are atomically
22593 + spin_lock_irqsave(lock, flags);
22594 + p->ipi_pending |= 1 << op;
22595 + spin_unlock_irqrestore(lock, flags);
22597 + spin_lock_irqsave(&smp_ipi_lock, flags);
22598 + smp_needs_ipi |= (1 << p->tid);
22599 + ubicom32_set_interrupt(smp_ipi_irq);
22600 + spin_unlock_irqrestore(&smp_ipi_lock, flags);
22601 + smp_debug(100, KERN_INFO "cpu[%d]: send: %d\n", cpu, op);
22606 + * Send an IPI to each cpu in mask.
22608 +static inline void ipi_send_mask(unsigned int op, const struct cpumask mask)
22611 + for_each_cpu_mask(cpu, mask) {
22612 + ipi_send(cpu, op);
22617 + * ipi_send_allbutself()
22618 + * Send an IPI to all threads but ourselves.
22620 +static inline void ipi_send_allbutself(unsigned int op)
22622 + int self = smp_processor_id();
22623 + struct cpumask result;
22624 + cpumask_copy(&result, &cpu_online_map);
22625 + cpu_clear(self, result);
22626 + ipi_send_mask(op, result);
22630 + * smp_enable_vector()
22632 +static void smp_enable_vector(unsigned int irq)
22634 + ubicom32_clear_interrupt(smp_ipi_irq);
22635 + ldsr_enable_vector(irq);
22639 + * smp_disable_vector()
22640 + * Disable the interrupt by clearing the appropriate bit in the
22641 + * LDSR Mask Register.
22643 +static void smp_disable_vector(unsigned int irq)
22645 + ldsr_disable_vector(irq);
22649 + * smp_mask_vector()
22651 +static void smp_mask_vector(unsigned int irq)
22653 + ldsr_mask_vector(irq);
22657 + * smp_unmask_vector()
22659 +static void smp_unmask_vector(unsigned int irq)
22661 + ldsr_unmask_vector(irq);
22665 + * smp_end_vector()
22666 + * Called once an interrupt is completed (reset the LDSR mask).
22668 +static void smp_end_vector(unsigned int irq)
22670 + struct cpuinfo_ubicom32 *p = &per_cpu(cpu_data, smp_processor_id());
22671 + spin_lock(&smp_ipi_lock);
22672 + smp_inside_ipi &= ~(1 << p->tid);
22673 + if (smp_inside_ipi) {
22674 + spin_unlock(&smp_ipi_lock);
22677 + spin_unlock(&smp_ipi_lock);
22678 + ldsr_unmask_vector(irq);
22679 + smp_debug(100, KERN_INFO "cpu[%d]: unamesk vector\n", smp_processor_id());
22683 + * Special hanlder functions for SMP.
22685 +static struct irq_chip ubicom32_smp_chip = {
22686 + .name = "UbicoIPI",
22688 + .shutdown = NULL,
22689 + .enable = smp_enable_vector,
22690 + .disable = smp_disable_vector,
22692 + .mask = smp_mask_vector,
22693 + .unmask = smp_unmask_vector,
22694 + .end = smp_end_vector,
22698 + * smp_reset_ipi()
22699 + * None of these cpu(s) got their IPI, turn it back on.
22701 + * Note: This is called by the LDSR which is not a full
22702 + * Linux cpu. Thus you must use the raw form of locks
22703 + * because lock debugging will not work on the partial
22704 + * cpu nature of the LDSR.
22706 +void smp_reset_ipi(unsigned long mask)
22708 + __raw_spin_lock(&smp_ipi_lock.raw_lock);
22709 + smp_needs_ipi |= mask;
22710 + smp_inside_ipi &= ~mask;
22711 + ubicom32_set_interrupt(smp_ipi_irq);
22712 + __raw_spin_unlock(&smp_ipi_lock.raw_lock);
22713 + smp_debug(100, KERN_INFO "smp: reset IPIs for: 0x%x\n", mask);
22717 + * smp_get_affinity()
22718 + * Choose the thread affinity for this interrupt.
22720 + * Note: This is called by the LDSR which is not a full
22721 + * Linux cpu. Thus you must use the raw form of locks
22722 + * because lock debugging will not work on the partial
22723 + * cpu nature of the LDSR.
22725 +unsigned long smp_get_affinity(unsigned int irq, int *all)
22727 + unsigned long mask = 0;
22730 + * Most IRQ(s) are delivered in a round robin fashion.
22732 + if (irq != smp_ipi_irq) {
22733 + unsigned long result = smp_irq_affinity[irq] & smp_online_threads;
22734 + DEBUG_ASSERT(result);
22740 + * This is an IPI request. Return all cpu(s) scheduled for an IPI.
22741 + * We also track those cpu(s) that are going to be "receiving" IPI this
22742 + * round. When all CPU(s) have called smp_end_vector(),
22743 + * we will unmask the IPI interrupt.
22745 + __raw_spin_lock(&smp_ipi_lock.raw_lock);
22746 + ubicom32_clear_interrupt(smp_ipi_irq);
22747 + if (smp_needs_ipi) {
22748 + mask = smp_needs_ipi;
22749 + smp_inside_ipi |= smp_needs_ipi;
22750 + smp_needs_ipi = 0;
22752 + __raw_spin_unlock(&smp_ipi_lock.raw_lock);
22758 + * smp_set_affinity()
22759 + * Set the affinity for this irq but store the value in tid(s).
22761 +void smp_set_affinity(unsigned int irq, const struct cpumask *dest)
22764 + unsigned long *paffinity = &smp_irq_affinity[irq];
22767 + * If none specified, all cpus are allowed.
22769 + if (cpus_empty(*dest)) {
22770 + *paffinity = 0xffffffff;
22775 + * Make sure to clear the old value before setting up the
22779 + for_each_cpu_mask(cpuid, *dest) {
22780 + struct cpuinfo_ubicom32 *p = &per_cpu(cpu_data, cpuid);
22781 + *paffinity |= (1 << p->tid);
22786 + * smp_send_stop()
22787 + * Send a stop request to all CPU but this one.
22789 +void smp_send_stop(void)
22791 + ipi_send_allbutself(IPI_CPU_STOP);
22795 + * smp_send_timer_all()
22796 + * Send all cpu(s) but this one, a request to update times.
22798 +void smp_send_timer_all(void)
22800 + ipi_send_allbutself(IPI_CPU_TIMER);
22804 + * smp_timer_broadcast()
22805 + * Use an IPI to broadcast a timer message
22807 +void smp_timer_broadcast(const struct cpumask *mask)
22809 + ipi_send_mask(IPI_CPU_TIMER, *mask);
22813 + * smp_send_reschedule()
22814 + * Send a reschedule request to the specified cpu.
22816 +void smp_send_reschedule(int cpu)
22818 + ipi_send(cpu, IPI_RESCHEDULE);
22822 + * arch_send_call_function_ipi()
22823 + * Cause each cpu in the mask to call the generic function handler.
22825 +void arch_send_call_function_ipi_mask(const struct cpumask *mask)
22828 + for_each_cpu_mask(cpu, *mask) {
22829 + ipi_send(cpu, IPI_CALL_FUNC);
22834 + * arch_send_call_function_single_ipi()
22835 + * Cause the specified cpu to call the generic function handler.
22837 +void arch_send_call_function_single_ipi(int cpu)
22839 + ipi_send(cpu, IPI_CALL_FUNC_SINGLE);
22843 + * setup_profiling_timer()
22844 + * Dummy function created to keep Oprofile happy in the SMP case.
22846 +int setup_profiling_timer(unsigned int multiplier)
22852 + * smp_mainline_start()
22853 + * Start a slave thread executing a mainline Linux context.
22855 +static void __init smp_mainline_start(void *arg)
22857 + int cpuid = smp_processor_id();
22858 + struct cpuinfo_ubicom32 *p = &per_cpu(cpu_data, cpuid);
22860 + BUG_ON(p->tid != thread_get_self());
22863 + * Well, support 2.4 linux scheme as well.
22865 + if (cpu_test_and_set(cpuid, cpu_online_map)) {
22866 + printk(KERN_CRIT "cpu[%d]: already initialized!\n", cpuid);
22867 + smp_halt_processor();
22872 + * Initialise the idle task for this CPU
22874 + atomic_inc(&init_mm.mm_count);
22875 + current->active_mm = &init_mm;
22876 + if (current->mm) {
22877 + printk(KERN_CRIT "cpu[%d]: idle task already has memory "
22878 + "management\n", cpuid);
22879 + smp_halt_processor();
22884 + * TODO: X86 does this prior to calling notify, try to understand why?
22886 + preempt_disable();
22888 +#if defined(CONFIG_GENERIC_CLOCKEVENTS)
22890 + * Setup a local timer event so that this cpu will get timer interrupts
22892 + if (local_timer_setup(cpuid) == -1) {
22893 + printk(KERN_CRIT "cpu[%d]: timer alloc failed\n", cpuid);
22894 + smp_halt_processor();
22900 + * Notify those interested that we are up and alive. This must
22901 + * be done before interrupts are enabled. It must also be completed
22902 + * before the bootstrap cpu returns from __cpu_up() (see comment
22903 + * above cpu_set() of the cpu_online_map).
22905 + notify_cpu_starting(cpuid);
22908 + * Indicate that this thread is now online and present. Setting
22909 + * cpu_online_map has the side effect of allowing the bootstrap
22910 + * cpu to continue along; so anything that MUST be done prior to the
22911 + * bootstrap cpu returning from __cpu_up() needs to go above here.
22913 + cpu_set(cpuid, cpu_online_map);
22914 + cpu_set(cpuid, cpu_present_map);
22917 + * Maintain a thread mapping in addition to the cpu mapping.
22919 + smp_online_threads |= (1 << p->tid);
22922 + * Enable interrupts for this thread.
22924 + local_irq_enable();
22927 + * Enter the idle loop and wait for a timer to schedule some work.
22929 + printk(KERN_INFO "cpu[%d]: entering cpu_idle()\n", cpuid);
22932 + /* Not Reached */
22936 + * smp_cpus_done()
22937 + * Called once the kernel_init() has brought up all cpu(s).
22939 +void smp_cpus_done(unsigned int cpu_max)
22946 + * Called to startup a sepcific cpu.
22948 +int __cpuinit __cpu_up(unsigned int cpu)
22950 + struct task_struct *idle;
22951 + unsigned int *stack;
22953 + struct cpuinfo_ubicom32 *p = &per_cpu(cpu_data, cpu);
22956 + * Create an idle task for this CPU.
22958 + idle = fork_idle(cpu);
22959 + if (IS_ERR(idle)) {
22960 + panic("cpu[%d]: fork failed\n", cpu);
22963 + task_thread_info(idle)->cpu = cpu;
22966 + * Setup the sw_ksp[] to point to this new task.
22968 + sw_ksp[p->tid] = (unsigned int)idle->stack;
22969 + stack = (unsigned int *)(sw_ksp[p->tid] + PAGE_SIZE - 8);
22972 + * Cause the specified thread to execute our smp_mainline_start
22973 + * function as a TYPE_NORMAL thread.
22975 + printk(KERN_INFO "cpu[%d]: launching mainline Linux thread\n", cpu);
22976 + if (thread_start(p->tid, smp_mainline_start, (void *)NULL, stack,
22977 + THREAD_TYPE_NORMAL) == -1) {
22978 + printk(KERN_WARNING "cpu[%d]: failed thread_start\n", cpu);
22983 + * Wait for the thread to start up. The thread will set
22984 + * the online bit when it is running. Our caller execpts the
22985 + * cpu to be online if we return 0.
22987 + for (timeout = 0; timeout < 10000; timeout++) {
22988 + if (cpu_online(cpu)) {
22997 + if (!cpu_online(cpu)) {
22998 + printk(KERN_CRIT "cpu[%d]: failed to live after %ld us\n",
22999 + cpu, timeout * 100);
23003 + printk(KERN_INFO "cpu[%d]: came alive after %ld us\n",
23004 + cpu, timeout * 100);
23009 + * Data used by setup_irq for the IPI.
23011 +static struct irqaction ipi_irq = {
23013 + .flags = IRQF_DISABLED | IRQF_PERCPU,
23014 + .handler = ipi_interrupt,
23018 + * smp_prepare_cpus()
23019 + * Mark threads that are available to Linux as possible cpus(s).
23021 +void __init smp_prepare_cpus(unsigned int max_cpus)
23026 + * We will need a software IRQ to send IPI(s). We will use
23027 + * a single software IRQ for all IPI(s).
23029 + if (irq_soft_alloc(&smp_ipi_irq) < 0) {
23030 + panic("no software IRQ is available\n");
23035 + * For the IPI interrupt, we want to use our own chip definition.
23036 + * This allows us to define what happens in SMP IPI without affecting
23037 + * the performance of the other interrupts.
23039 + * Next, Register the IPI interrupt function against the soft IRQ.
23041 + set_irq_chip(smp_ipi_irq, &ubicom32_smp_chip);
23042 + setup_irq(smp_ipi_irq, &ipi_irq);
23045 + * We use the device tree node to determine how many
23046 + * free cpus we will have (up to NR_CPUS) and we indicate
23047 + * that those cpus are present.
23049 + * We need to do this very early in the SMP case
23050 + * because the Linux init code uses the cpu_present_map.
23052 + for_each_possible_cpu(i) {
23054 + struct cpuinfo_ubicom32 *p = &per_cpu(cpu_data, i);
23057 + * Skip the bootstrap cpu
23064 + * If we have a free thread left in the mask,
23065 + * indicate that the cpu is present.
23067 + tid = thread_alloc();
23068 + if (tid == (thread_t)-1) {
23073 + * Save the hardware thread id for this cpu.
23076 + cpu_set(i, cpu_present_map);
23077 + printk(KERN_INFO "cpu[%d]: added to cpu_present_map - tid: %d\n", i, tid);
23082 + * smp_prepare_boot_cpu()
23083 + * Copy the per_cpu data into the appropriate spot for the bootstrap cpu.
23085 + * The code in boot_cpu_init() has already set the boot cpu's
23086 + * state in the possible, present, and online maps.
23088 +void __devinit smp_prepare_boot_cpu(void)
23090 + struct cpuinfo_ubicom32 *p = &per_cpu(cpu_data, 0);
23092 + smp_online_threads |= (1 << p->tid);
23093 + printk(KERN_INFO "cpu[%d]: bootstrap CPU online - tid: %ld\n",
23094 + current_thread_info()->cpu, p->tid);
23098 + * smp_setup_processor_id()
23099 + * Set the current_thread_info() structure cpu value.
23101 + * We set the value to the true hardware thread value that we are running on.
23102 + * NOTE: this function overrides the weak alias function in main.c
23104 +void __init smp_setup_processor_id(void)
23106 + struct cpuinfo_ubicom32 *p = &per_cpu(cpu_data, 0);
23108 + for_each_cpu_mask(i, CPU_MASK_ALL)
23109 + set_cpu_possible(i, true);
23111 + current_thread_info()->cpu = 0;
23112 + p->tid = thread_get_self();
23115 +++ b/arch/ubicom32/kernel/stacktrace.c
23118 + * arch/ubicom32/kernel/stacktrace.c
23119 + * Ubicom32 architecture stack back trace implementation.
23121 + * (C) Copyright 2009, Ubicom, Inc.
23123 + * This file is part of the Ubicom32 Linux Kernel Port.
23125 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
23126 + * it and/or modify it under the terms of the GNU General Public License
23127 + * as published by the Free Software Foundation, either version 2 of the
23128 + * License, or (at your option) any later version.
23130 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
23131 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
23132 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
23133 + * the GNU General Public License for more details.
23135 + * You should have received a copy of the GNU General Public License
23136 + * along with the Ubicom32 Linux Kernel Port. If not,
23137 + * see <http://www.gnu.org/licenses/>.
23139 + * Ubicom32 implementation derived from (with many thanks):
23144 +#include <linux/sched.h>
23145 +#include <linux/stacktrace.h>
23146 +#include <linux/module.h>
23147 +#include <asm/stacktrace.h>
23148 +#include <asm/thread.h>
23149 +#include <asm/ip5000.h>
23152 + * These symbols are filled in by the linker.
23154 +extern unsigned long _stext;
23155 +extern unsigned long _etext;
23157 +extern unsigned long __ocm_text_run_begin;
23158 +extern unsigned long __data_begin;
23161 + * stacktrace_iterate()
23162 + * Walk the stack looking for call and calli instructions on an aligned
23165 + * Trace must point to the top of the current stack frame.
23167 +unsigned long stacktrace_iterate(unsigned long **trace,
23168 + unsigned long stext,
23169 + unsigned long etext,
23170 + unsigned long ocm_stext,
23171 + unsigned long ocm_etext,
23172 + unsigned long sstack,
23173 + unsigned long estack)
23175 + unsigned int thread_trap_en, instruction;
23176 + unsigned long address;
23177 + unsigned int limit = 0;
23178 + unsigned long result = 0;
23179 + unsigned long *sp = *trace;
23182 + * Exclude the current thread from being monitored for traps.
23185 + " thread_get_self_mask d15 \n\t"
23186 + /* save current trap status */
23187 + " and.4 %0, MT_TRAP_EN, d15 \n\t"
23188 + " not.4 d15, d15 \n\t"
23189 + /* disable trap */
23190 + " and.4 MT_TRAP_EN, MT_TRAP_EN, d15 \n\t"
23191 + " pipe_flush 0 \n\t"
23192 + : "=r" (thread_trap_en)
23197 + while (limit++ < 256) {
23199 + * See if we have a valid stack.
23201 + if (!between((unsigned long)sp, sstack, estack)) {
23202 +#ifdef TRAP_DEBUG_STACK_TRACE
23203 + printk(KERN_EMERG "stack address is out of range - "
23204 + "sp: %x, sstack: %x, estack: %x\n",
23205 + (unsigned int)sp, (unsigned int)sstack,
23206 + (unsigned int)estack);
23214 + * Get the value off the stack and back up 4 bytes to what
23215 + * should be the address of a call or calli.
23217 + address = (*sp++) - 4;
23220 + * If the address is not within the text segment, skip this
23223 + if (!between(address, stext, etext) &&
23224 + !between(address, ocm_stext, ocm_etext)) {
23225 +#ifdef TRAP_DEBUG_STACK_TRACE
23226 + printk(KERN_EMERG "not a text address - "
23227 + "address: %08x, stext: %08x, etext: %08x\n"
23228 + "ocm_stext: %08x, ocm_etext: %08x\n",
23229 + (unsigned int)address,
23230 + (unsigned int)stext,
23231 + (unsigned int)etext,
23232 + (unsigned int)ocm_stext,
23233 + (unsigned int)ocm_etext);
23240 + * If the address is not on an aligned boundary it can not be a
23241 + * return address.
23243 + if (address & 0x3) {
23248 + * Read the probable instruction.
23250 + instruction = *(unsigned int *)address;
23253 + * Is this a call instruction?
23255 + if ((instruction & 0xF8000000) == (u32_t)(0x1B << 27)) {
23256 +#ifdef TRAP_DEBUG_STACK_TRACE
23257 + printk(KERN_EMERG "call inst. result: %x, "
23258 + "test: %x\n", (unsigned int)address,
23259 + (unsigned int)instruction);
23262 + result = address;
23267 + * Is this a calli instruction?
23269 + if ((instruction & 0xF8000000) == (u32_t)(0x1E << 27)) {
23270 +#ifdef TRAP_DEBUG_STACK_TRACE
23271 + printk(KERN_EMERG "calli inst. result: %x, "
23272 + "test: %x\n", (unsigned int)address,
23273 + (unsigned int)instruction);
23276 + result = address;
23282 + * Restore the current thread to be monitored for traps.
23284 + if (thread_trap_en) {
23286 + " thread_get_self_mask d15 \n\t"
23287 + " or.4 MT_TRAP_EN, MT_TRAP_EN, d15 \n\t"
23296 +#ifdef CONFIG_STACKTRACE
23298 + * stacktrace_save_entries()
23299 + * Save stack back trace information into the provided trace structure.
23301 +void stacktrace_save_entries(struct task_struct *tsk,
23302 + struct stack_trace *trace,
23303 + unsigned long sp)
23305 + unsigned long code_start = (unsigned long)&_stext;
23306 + unsigned long code_end = (unsigned long)&_etext;
23307 + unsigned long ocm_code_start = (unsigned long)&__ocm_text_run_begin;
23308 + unsigned long ocm_code_end = (unsigned long)&__data_begin;
23309 + unsigned long stack_end = (unsigned long)(tsk->stack + THREAD_SIZE - 8);
23310 + unsigned long stack = (unsigned long)sp;
23311 + unsigned int idx = 0;
23312 + unsigned long *handle;
23313 + int skip = trace->skip;
23315 + handle = (unsigned long *)stack;
23316 + while (idx < trace->max_entries) {
23321 + trace->entries[idx] = stacktrace_iterate(&handle,
23322 + code_start, code_end,
23323 + ocm_code_start, ocm_code_end,
23324 + (unsigned long)stack, stack_end);
23325 + if (trace->entries[idx] == 0) {
23333 + * save_stack_trace()
23334 + * Save the specified amount of the kernel stack trace information
23335 + * for the current task.
23337 +void save_stack_trace(struct stack_trace *trace)
23339 + unsigned long sp = 0;
23341 + " move.4 %0, SP \n\t"
23344 + stacktrace_save_entries(current, trace, sp);
23346 +EXPORT_SYMBOL_GPL(save_stack_trace);
23349 + * save_stack_trace_tsk()
23350 + * Save the specified amount of the kernel stack trace information
23351 + * for the specified task.
23353 + * Note: We assume the specified task is not currently running.
23355 +void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
23357 + stacktrace_save_entries(tsk, trace, tsk->thread.sp);
23359 +EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
23360 +#endif /* CONFIG_STACKTRACE */
23362 +++ b/arch/ubicom32/kernel/syscalltable.S
23365 + * arch/ubicom32/kernel/syscalltable.S
23366 + * <TODO: Replace with short file description>
23368 + * (C) Copyright 2009, Ubicom, Inc.
23370 + * This file is part of the Ubicom32 Linux Kernel Port.
23372 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
23373 + * it and/or modify it under the terms of the GNU General Public License
23374 + * as published by the Free Software Foundation, either version 2 of the
23375 + * License, or (at your option) any later version.
23377 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
23378 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
23379 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
23380 + * the GNU General Public License for more details.
23382 + * You should have received a copy of the GNU General Public License
23383 + * along with the Ubicom32 Linux Kernel Port. If not,
23384 + * see <http://www.gnu.org/licenses/>.
23386 + * Ubicom32 implementation derived from (with many thanks):
23393 + * Copyright (C) 2002, Greg Ungerer (gerg@snapgear.com)
23394 + * Copyright (C) 1998 D. Jeff Dionne <jeff@lineo.ca>, Kenneth Albanowski <kjahds@kjahds.com>,
23395 + * Copyright (C) 2000 Lineo Inc. (www.lineo.com)
23396 + * Copyright (C) 1991, 1992 Linus Torvalds
23399 +#include <linux/sys.h>
23400 +#include <linux/linkage.h>
23401 +#include <asm/unistd.h>
23405 + .global sys_call_table
23407 + .long sys_ni_syscall /* 0 - old "setup()" system call*/
23412 + .long sys_open /* 5 */
23414 + .long sys_waitpid
23417 + .long sys_unlink /* 10 */
23418 + .long execve_intercept
23422 + .long sys_chmod /* 15 */
23423 + .long sys_chown16
23424 + .long sys_ni_syscall /* old break syscall holder */
23427 + .long sys_getpid /* 20 */
23429 + .long sys_oldumount
23430 + .long sys_setuid16
23431 + .long sys_getuid16
23432 + .long sys_stime /* 25 */
23437 + .long sys_utime /* 30 */
23438 + .long sys_ni_syscall /* old stty syscall holder */
23439 + .long sys_ni_syscall /* old gtty syscall holder */
23442 + .long sys_ni_syscall /* 35 */ /* old ftime syscall holder */
23447 + .long sys_rmdir /* 40 */
23451 + .long sys_ni_syscall /* old prof syscall holder */
23452 + .long sys_brk /* 45 */
23453 + .long sys_setgid16
23454 + .long sys_getgid16
23456 + .long sys_geteuid16
23457 + .long sys_getegid16 /* 50 */
23459 + .long sys_umount /* recycled never used phys() */
23460 + .long sys_ni_syscall /* old lock syscall holder */
23462 + .long sys_fcntl /* 55 */
23463 + .long sys_ni_syscall /* old mpx syscall holder */
23464 + .long sys_setpgid
23465 + .long sys_ni_syscall /* old ulimit syscall holder */
23466 + .long sys_ni_syscall
23467 + .long sys_umask /* 60 */
23471 + .long sys_getppid
23472 + .long sys_getpgrp /* 65 */
23474 + .long sys_sigaction
23475 + .long sys_sgetmask
23476 + .long sys_ssetmask
23477 + .long sys_setreuid16 /* 70 */
23478 + .long sys_setregid16
23479 + .long sys_sigsuspend
23480 + .long sys_sigpending
23481 + .long sys_sethostname
23482 + .long sys_setrlimit /* 75 */
23483 + .long sys_old_getrlimit
23484 + .long sys_getrusage
23485 + .long sys_gettimeofday
23486 + .long sys_settimeofday
23487 + .long sys_getgroups16 /* 80 */
23488 + .long sys_setgroups16
23490 + .long sys_symlink
23492 + .long sys_readlink /* 85 */
23494 + .long sys_ni_syscall /* _sys_swapon */
23496 + .long sys_old_readdir
23497 + .long old_mmap /* 90 */
23499 + .long sys_truncate
23500 + .long sys_ftruncate
23502 + .long sys_fchown16 /* 95 */
23503 + .long sys_getpriority
23504 + .long sys_setpriority
23505 + .long sys_ni_syscall /* old profil syscall holder */
23507 + .long sys_fstatfs /* 100 */
23508 + .long sys_ni_syscall /* ioperm for i386 */
23509 + .long sys_socketcall
23511 + .long sys_setitimer
23512 + .long sys_getitimer /* 105 */
23513 + .long sys_newstat
23514 + .long sys_newlstat
23515 + .long sys_newfstat
23516 + .long sys_ni_syscall
23517 + .long sys_ni_syscall /* iopl for i386 */ /* 110 */
23518 + .long sys_vhangup
23519 + .long sys_ni_syscall /* obsolete idle() syscall */
23520 + .long sys_ni_syscall /* vm86old for i386 */
23522 + .long sys_ni_syscall /* 115 */ /* _sys_swapoff */
23523 + .long sys_sysinfo
23526 + .long sys_sigreturn
23527 + .long clone_intercept /* 120 */
23528 + .long sys_setdomainname
23529 + .long sys_newuname
23530 + .long sys_cacheflush /* modify_ldt for i386 */
23531 + .long sys_adjtimex
23532 + .long sys_ni_syscall /* 125 */ /* _sys_mprotect */
23533 + .long sys_sigprocmask
23534 + .long sys_ni_syscall /* old "creat_module" */
23535 + .long sys_init_module
23536 + .long sys_delete_module
23537 + .long sys_ni_syscall /* 130: old "get_kernel_syms" */
23538 + .long sys_quotactl
23539 + .long sys_getpgid
23541 + .long sys_bdflush
23542 + .long sys_sysfs /* 135 */
23543 + .long sys_personality
23544 + .long sys_ni_syscall /* for afs_syscall */
23545 + .long sys_setfsuid16
23546 + .long sys_setfsgid16
23547 + .long sys_llseek /* 140 */
23548 + .long sys_getdents
23551 + .long sys_ni_syscall /* _sys_msync */
23552 + .long sys_readv /* 145 */
23555 + .long sys_fdatasync
23557 + .long sys_ni_syscall /* 150 */ /* _sys_mlock */
23558 + .long sys_ni_syscall /* _sys_munlock */
23559 + .long sys_ni_syscall /* _sys_mlockall */
23560 + .long sys_ni_syscall /* _sys_munlockall */
23561 + .long sys_sched_setparam
23562 + .long sys_sched_getparam /* 155 */
23563 + .long sys_sched_setscheduler
23564 + .long sys_sched_getscheduler
23565 + .long sys_sched_yield
23566 + .long sys_sched_get_priority_max
23567 + .long sys_sched_get_priority_min /* 160 */
23568 + .long sys_sched_rr_get_interval
23569 + .long sys_nanosleep
23570 + .long sys_ni_syscall /* _sys_mremap */
23571 + .long sys_setresuid16
23572 + .long sys_getresuid16 /* 165 */
23573 + .long sys_getpagesize /* _sys_getpagesize */
23574 + .long sys_ni_syscall /* old "query_module" */
23576 + .long sys_ni_syscall /* _sys_nfsservctl */
23577 + .long sys_setresgid16 /* 170 */
23578 + .long sys_getresgid16
23580 + .long sys_rt_sigreturn
23581 + .long sys_rt_sigaction
23582 + .long sys_rt_sigprocmask /* 175 */
23583 + .long sys_rt_sigpending
23584 + .long sys_rt_sigtimedwait
23585 + .long sys_rt_sigqueueinfo
23586 + .long sys_rt_sigsuspend
23587 + .long sys_pread64 /* 180 */
23588 + .long sys_pwrite64
23589 + .long sys_lchown16
23592 + .long sys_capset /* 185 */
23593 + .long sys_sigaltstack
23594 + .long sys_sendfile
23595 + .long sys_ni_syscall /* streams1 */
23596 + .long sys_ni_syscall /* streams2 */
23597 + .long vfork_intercept /* 190 */
23598 + .long sys_getrlimit
23600 + .long sys_truncate64
23601 + .long sys_ftruncate64
23602 + .long sys_stat64 /* 195 */
23603 + .long sys_lstat64
23604 + .long sys_fstat64
23607 + .long sys_getgid /* 200 */
23608 + .long sys_geteuid
23609 + .long sys_getegid
23610 + .long sys_setreuid
23611 + .long sys_setregid
23612 + .long sys_getgroups /* 205 */
23613 + .long sys_setgroups
23615 + .long sys_setresuid
23616 + .long sys_getresuid
23617 + .long sys_setresgid /* 210 */
23618 + .long sys_getresgid
23622 + .long sys_setfsuid /* 215 */
23623 + .long sys_setfsgid
23624 + .long sys_pivot_root
23625 + .long sys_ni_syscall
23626 + .long sys_ni_syscall
23627 + .long sys_getdents64 /* 220 */
23630 + .long sys_setxattr
23631 + .long sys_lsetxattr
23632 + .long sys_fsetxattr /* 225 */
23633 + .long sys_getxattr
23634 + .long sys_lgetxattr
23635 + .long sys_fgetxattr
23636 + .long sys_listxattr
23637 + .long sys_llistxattr /* 230 */
23638 + .long sys_flistxattr
23639 + .long sys_removexattr
23640 + .long sys_lremovexattr
23641 + .long sys_fremovexattr
23642 + .long sys_futex /* 235 */
23643 + .long sys_sendfile64
23644 + .long sys_ni_syscall /* _sys_mincore */
23645 + .long sys_ni_syscall /* _sys_madvise */
23646 + .long sys_fcntl64
23647 + .long sys_readahead /* 240 */
23648 + .long sys_io_setup
23649 + .long sys_io_destroy
23650 + .long sys_io_getevents
23651 + .long sys_io_submit
23652 + .long sys_io_cancel /* 245 */
23653 + .long sys_fadvise64
23654 + .long sys_exit_group
23655 + .long sys_lookup_dcookie
23656 + .long sys_epoll_create
23657 + .long sys_epoll_ctl /* 250 */
23658 + .long sys_epoll_wait
23659 + .long sys_ni_syscall /* _sys_remap_file_pages */
23660 + .long sys_set_tid_address
23661 + .long sys_timer_create
23662 + .long sys_timer_settime /* 255 */
23663 + .long sys_timer_gettime
23664 + .long sys_timer_getoverrun
23665 + .long sys_timer_delete
23666 + .long sys_clock_settime
23667 + .long sys_clock_gettime /* 260 */
23668 + .long sys_clock_getres
23669 + .long sys_clock_nanosleep
23670 + .long sys_statfs64
23671 + .long sys_fstatfs64
23672 + .long sys_tgkill /* 265 */
23674 + .long sys_fadvise64_64
23676 + .long sys_get_mempolicy
23677 + .long sys_set_mempolicy /* 270 */
23678 + .long sys_mq_open
23679 + .long sys_mq_unlink
23680 + .long sys_mq_timedsend
23681 + .long sys_mq_timedreceive
23682 + .long sys_mq_notify /* 275 */
23683 + .long sys_mq_getsetattr
23685 + .long sys_ni_syscall /* for _sys_vserver */
23686 + .long sys_add_key
23687 + .long sys_request_key /* 280 */
23689 + .long sys_ioprio_set
23690 + .long sys_ioprio_get
23691 + .long sys_inotify_init
23692 + .long sys_inotify_add_watch /* 285 */
23693 + .long sys_inotify_rm_watch
23694 + .long sys_migrate_pages
23696 + .long sys_mkdirat
23697 + .long sys_mknodat /* 290 */
23698 + .long sys_fchownat
23699 + .long sys_futimesat
23700 + .long sys_fstatat64
23701 + .long sys_unlinkat
23702 + .long sys_renameat /* 295 */
23704 + .long sys_symlinkat
23705 + .long sys_readlinkat
23706 + .long sys_fchmodat
23707 + .long sys_faccessat /* 300 */
23708 + .long sys_ni_syscall /* Reserved for pselect6 */
23709 + .long sys_ni_syscall /* Reserved for ppoll */
23710 + .long sys_unshare
23711 + .long sys_set_robust_list
23712 + .long sys_get_robust_list /* 305 */
23714 + .long sys_sync_file_range
23716 + .long sys_vmsplice
23717 + .long sys_move_pages /* 310 */
23718 + .long sys_sched_setaffinity
23719 + .long sys_sched_getaffinity
23720 + .long sys_kexec_load
23722 + .long sys_epoll_pwait /* 315 */
23723 + .long sys_utimensat
23724 + .long sys_signalfd
23725 + .long sys_timerfd_create
23726 + .long sys_eventfd
23727 + .long sys_fallocate /* 320 */
23728 + .long sys_timerfd_settime
23729 + .long sys_timerfd_gettime
23730 + .long sys_ni_syscall /* sys_signalfd4 */
23731 + .long sys_ni_syscall /* sys_eventfd2 */
23732 + .long sys_ni_syscall /* sys_epoll_create1 */
23734 + .long sys_ni_syscall /* sys_dup3 */
23735 + .long sys_ni_syscall /* sys_pipe2 */
23736 + .long sys_ni_syscall /* sys_inotify_init1 */
23737 + .rept NR_syscalls-(.-sys_call_table)/4
23738 + .long sys_ni_syscall
23741 +++ b/arch/ubicom32/kernel/sys_ubicom32.c
23744 + * arch/ubicom32/kernel/sys_ubicom32.c
23745 + * Ubicom32 architecture system call support implementation.
23747 + * (C) Copyright 2009, Ubicom, Inc.
23749 + * This file is part of the Ubicom32 Linux Kernel Port.
23751 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
23752 + * it and/or modify it under the terms of the GNU General Public License
23753 + * as published by the Free Software Foundation, either version 2 of the
23754 + * License, or (at your option) any later version.
23756 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
23757 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
23758 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
23759 + * the GNU General Public License for more details.
23761 + * You should have received a copy of the GNU General Public License
23762 + * along with the Ubicom32 Linux Kernel Port. If not,
23763 + * see <http://www.gnu.org/licenses/>.
23765 + * Ubicom32 implementation derived from (with many thanks):
23770 + * This file contains various random system calls that
23771 + * have a non-standard calling sequence on the Linux/ubicom32
23775 +#include <linux/module.h>
23776 +#include <linux/errno.h>
23777 +#include <linux/sched.h>
23778 +#include <linux/mm.h>
23779 +#include <linux/smp.h>
23780 +#include <linux/sem.h>
23781 +#include <linux/msg.h>
23782 +#include <linux/shm.h>
23783 +#include <linux/stat.h>
23784 +#include <linux/syscalls.h>
23785 +#include <linux/mman.h>
23786 +#include <linux/file.h>
23787 +#include <linux/utsname.h>
23788 +#include <linux/ipc.h>
23789 +#include <linux/fs.h>
23790 +#include <linux/uaccess.h>
23791 +#include <linux/unistd.h>
23793 +#include <asm/setup.h>
23794 +#include <asm/traps.h>
23795 +#include <asm/cacheflush.h>
23797 +/* common code for old and new mmaps */
23798 +static inline long do_mmap2(
23799 + unsigned long addr, unsigned long len,
23800 + unsigned long prot, unsigned long flags,
23801 + unsigned long fd, unsigned long pgoff)
23803 + int error = -EBADF;
23804 + struct file *file = NULL;
23806 + flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
23807 + if (!(flags & MAP_ANONYMOUS)) {
23813 + down_write(¤t->mm->mmap_sem);
23814 + error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
23815 + up_write(¤t->mm->mmap_sem);
23823 +asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
23824 + unsigned long prot, unsigned long flags,
23825 + unsigned long fd, unsigned long pgoff)
23827 + return do_mmap2(addr, len, prot, flags, fd, pgoff);
23831 + * Perform the select(nd, in, out, ex, tv) and mmap() system
23832 + * calls. Linux/m68k cloned Linux/i386, which didn't use to be able to
23833 + * handle more than 4 system call parameters, so these system calls
23834 + * used a memory block for parameter passing..
23837 +struct mmap_arg_struct {
23838 + unsigned long addr;
23839 + unsigned long len;
23840 + unsigned long prot;
23841 + unsigned long flags;
23842 + unsigned long fd;
23843 + unsigned long offset;
23846 +asmlinkage int old_mmap(struct mmap_arg_struct *arg)
23848 + struct mmap_arg_struct a;
23849 + int error = -EFAULT;
23851 + if (copy_from_user(&a, arg, sizeof(a)))
23855 + if (a.offset & ~PAGE_MASK)
23858 + a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
23860 + error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd,
23861 + a.offset >> PAGE_SHIFT);
23866 +struct sel_arg_struct {
23868 + fd_set *inp, *outp, *exp;
23869 + struct timeval *tvp;
23872 +asmlinkage int old_select(struct sel_arg_struct *arg)
23874 + struct sel_arg_struct a;
23876 + if (copy_from_user(&a, arg, sizeof(a)))
23878 + /* sys_select() does the appropriate kernel locking */
23879 + return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
23883 + * sys_ipc() is the de-multiplexer for the SysV IPC calls..
23885 + * This is really horribly ugly.
23887 +asmlinkage int sys_ipc(uint call, int first, int second,
23888 + int third, void *ptr, long fifth)
23890 + int version, ret;
23892 + version = call >> 16; /* hack for backward compatibility */
23895 + if (call <= SEMCTL)
23898 + return sys_semop(first, (struct sembuf *)ptr, second);
23900 + return sys_semget(first, second, third);
23902 + union semun fourth;
23905 + if (get_user(fourth.__pad, (void **) ptr))
23907 + return sys_semctl(first, second, third, fourth);
23912 + if (call <= MSGCTL)
23915 + return sys_msgsnd(first, (struct msgbuf *) ptr,
23918 + switch (version) {
23920 + struct ipc_kludge tmp;
23923 + if (copy_from_user(&tmp,
23924 + (struct ipc_kludge *)ptr,
23927 + return sys_msgrcv(first, tmp.msgp, second,
23928 + tmp.msgtyp, third);
23931 + return sys_msgrcv(first,
23932 + (struct msgbuf *) ptr,
23933 + second, fifth, third);
23936 + return sys_msgget((key_t) first, second);
23938 + return sys_msgctl(first, second,
23939 + (struct msqid_ds *) ptr);
23943 + if (call <= SHMCTL)
23946 + switch (version) {
23949 + ret = do_shmat(first, ptr, second, &raddr);
23952 + return put_user(raddr, (ulong __user *) third);
23956 + return sys_shmdt(ptr);
23958 + return sys_shmget(first, second, third);
23960 + return sys_shmctl(first, second, ptr);
23968 +/* sys_cacheflush -- flush (part of) the processor cache. */
23970 +sys_cacheflush(unsigned long addr, int scope, int cache, unsigned long len)
23972 + flush_cache_all();
23976 +asmlinkage int sys_getpagesize(void)
23978 + return PAGE_SIZE;
23981 +++ b/arch/ubicom32/kernel/thread.c
23984 + * arch/ubicom32/kernel/thread.c
23985 + * Ubicom32 architecture hardware thread support.
23987 + * (C) Copyright 2009, Ubicom, Inc.
23989 + * This file is part of the Ubicom32 Linux Kernel Port.
23991 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
23992 + * it and/or modify it under the terms of the GNU General Public License
23993 + * as published by the Free Software Foundation, either version 2 of the
23994 + * License, or (at your option) any later version.
23996 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
23997 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
23998 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
23999 + * the GNU General Public License for more details.
24001 + * You should have received a copy of the GNU General Public License
24002 + * along with the Ubicom32 Linux Kernel Port. If not,
24003 + * see <http://www.gnu.org/licenses/>.
24005 + * Ubicom32 implementation derived from (with many thanks):
24011 +#include <linux/module.h>
24012 +#include <linux/kernel.h>
24013 +#include <linux/init.h>
24014 +#include <linux/sched.h>
24015 +#include <linux/interrupt.h>
24016 +#include <linux/irq.h>
24017 +#include <linux/profile.h>
24018 +#include <linux/clocksource.h>
24019 +#include <linux/types.h>
24020 +#include <asm/ip5000.h>
24021 +#include <asm/machdep.h>
24022 +#include <asm/asm-offsets.h>
24023 +#include <asm/thread.h>
24026 + * TODO: At some point change the name here to be thread_ksp
24028 +unsigned int sw_ksp[THREAD_ARCHITECTURAL_MAX];
24030 +static unsigned int thread_mask = -1;
24031 +static unsigned int thread_mainline_mask;
24035 + * Returning from the called function will disable the thread.
24037 + * This could be a naked call to allow for hwthreads that do not have stacks.
24038 + * However, with -O0, the code still writes to thex stack, and this was
24039 + * corrupting memory just after the callers stack.
24041 +static void thread_entry(void *arg, thread_exec_fn_t exec)
24044 + * Call thread function
24049 + * Complete => Disable self
24051 + thread_disable(thread_get_self());
24056 + * Start the specified function on the specified hardware thread.
24058 +thread_t thread_start(thread_t thread,
24059 + thread_exec_fn_t exec,
24061 + unsigned int *sp_high,
24062 + thread_type_t type)
24067 + unsigned int enabled, mask, csr;
24069 + "move.4 %0, MT_EN\n\t"
24073 + mask = 1 << thread;
24074 + if (enabled & mask) {
24075 + printk(KERN_WARNING "request to enable a previously enabled thread\n");
24076 + return (thread_t)-1;
24080 + * Update thread state
24082 + csr = (thread << 15) | (1 << 14);
24085 + "setcsr_flush 0 \n\t"
24087 + "move.4 A0, #0 \n\t"
24088 + "move.4 A1, #0 \n\t"
24089 + "move.4 A2, #0 \n\t"
24090 + "move.4 A3, #0 \n\t"
24091 + "move.4 A4, #0 \n\t"
24092 + "move.4 A5, #0 \n\t"
24093 + "move.4 A6, #0 \n\t"
24094 + "move.4 SP, %4 \n\t" /* A7 is SP */
24096 + "move.4 D0, %3 \n\t"
24097 + "move.4 D1, %2 \n\t"
24098 + "move.4 D2, #0 \n\t"
24099 + "move.4 D3, #0 \n\t"
24100 + "move.4 D4, #0 \n\t"
24101 + "move.4 D5, #0 \n\t"
24102 + "move.4 D6, #0 \n\t"
24103 + "move.4 D7, #0 \n\t"
24104 + "move.4 D8, #0 \n\t"
24105 + "move.4 D9, #0 \n\t"
24106 + "move.4 D10, #0 \n\t"
24107 + "move.4 D11, #0 \n\t"
24108 + "move.4 D12, #0 \n\t"
24109 + "move.4 D13, #0 \n\t"
24110 + "move.4 D14, #0 \n\t"
24111 + "move.4 D15, #0 \n\t"
24113 + "move.4 INT_MASK0, #0 \n\t"
24114 + "move.4 INT_MASK1, #0 \n\t"
24115 + "move.4 PC, %1 \n\t"
24117 + "setcsr_flush 0 \n\t"
24119 + : "r" (csr), "r" (thread_entry), "r" (exec),
24120 + "r" (arg), "r" (sp_high)
24124 + * Apply HRT state
24126 + if (type & THREAD_TYPE_HRT) {
24128 + "or.4 MT_HRT, MT_HRT, %0\n\t"
24135 + "and.4 MT_HRT, MT_HRT, %0\n\t"
24146 + "or.4 MT_HPRI, MT_HPRI, %0\n\t"
24156 + "move.4 MT_ACTIVE_SET, %0 \n\t"
24160 + thread_enable_mask(mask);
24165 + * thread_get_mainline()
24166 + * Return a mask of those threads that are Linux mainline threads.
24168 +unsigned int thread_get_mainline(void)
24170 + return thread_mainline_mask;
24174 + * thread_set_mainline()
24175 + * Indicate that the specified thread is a Linux mainline thread.
24177 +void thread_set_mainline(thread_t tid)
24179 + thread_mainline_mask |= (1 << tid);
24184 + * Allocate an unused hardware thread.
24186 +thread_t thread_alloc(void)
24191 + * If this is the first time we are here get the list of unused
24192 + * threads from the processor device tree node.
24194 + if (thread_mask == -1) {
24195 + thread_mask = processor_threads();
24198 + if (!thread_mask) {
24199 + return (thread_t)-1;
24202 + tid = ffs(thread_mask);
24205 + thread_mask &= ~(1 << tid);
24209 + return (thread_t)-1;
24212 +++ b/arch/ubicom32/kernel/time.c
24215 + * arch/ubicom32/kernel/time.c
24216 + * Initialize the timer list and start the appropriate timers.
24218 + * (C) Copyright 2009, Ubicom, Inc.
24219 + * Copyright (C) 1991, 1992, 1995 Linus Torvalds
24221 + * This file is part of the Ubicom32 Linux Kernel Port.
24223 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
24224 + * it and/or modify it under the terms of the GNU General Public License
24225 + * as published by the Free Software Foundation, either version 2 of the
24226 + * License, or (at your option) any later version.
24228 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
24229 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
24230 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
24231 + * the GNU General Public License for more details.
24233 + * You should have received a copy of the GNU General Public License
24234 + * along with the Ubicom32 Linux Kernel Port. If not,
24235 + * see <http://www.gnu.org/licenses/>.
24237 + * Ubicom32 implementation derived from (with many thanks):
24243 +#include <linux/profile.h>
24244 +#include <linux/smp.h>
24245 +#include <asm/ip5000.h>
24246 +#include <asm/machdep.h>
24249 + * A bitmap of the timers on the processor indicates
24250 + * that the timer is free or in-use.
24252 +static unsigned int timers;
24256 + * Init the specified compare register to go off <n> cycles from now.
24258 +void timer_set(int timervector, unsigned int cycles)
24260 + int idx = UBICOM32_VECTOR_TO_TIMER_INDEX(timervector);
24261 + UBICOM32_IO_TIMER->syscom[idx] =
24262 + UBICOM32_IO_TIMER->sysval + cycles;
24263 + ldsr_enable_vector(timervector);
24268 + * Set/reset the timer to go off again.
24270 + * Because sysval is a continuous timer, this function is able
24271 + * to ensure that we do not have clock sku by using the previous
24272 + * value in syscom to set the next value for syscom.
24274 + * Returns the number of ticks that transpired since the last event.
24276 +int timer_reset(int timervector, unsigned int cycles)
24279 + * Reset the timer in the LDSR thread to go off appropriately.
24281 + * Use the previous value of the timer to calculate the new stop
24282 + * time. This allows us to account for it taking an
24283 + * indeterminate amount of time to get here.
24285 + const int timer_index = UBICOM32_VECTOR_TO_TIMER_INDEX(timervector);
24286 + unsigned int prev = UBICOM32_IO_TIMER->syscom[timer_index];
24287 + unsigned int next = prev + cycles;
24293 + * If the difference is negative, we have missed at least one
24296 + * TODO: Decide if we want to "ignore" time (as done below) or
24297 + * if we want to process time (unevenly) by calling timer_tick()
24298 + * lost_ticks times.
24302 + * Set our future time first.
24304 + UBICOM32_IO_TIMER->syscom[timer_index] = next;
24307 + * Then check if we are really set time in the futrue.
24309 + diff = (int)next - (int)UBICOM32_IO_TIMER->sysval;
24315 + * Oops, we are too slow. Playing catch up.
24317 + * If the debugger is connected the there is a good
24318 + * chance that we lost time because we were in a
24319 + * break-point, so in this case we do not print out
24322 + asm volatile ("move.4 %0, scratchpad3"
24323 + : "=r" (scratchpad3));
24324 + if ((scratchpad3 & 0x1) == 0) {
24326 + * No debugger attached, print to the console
24328 + printk(KERN_EMERG "diff: %d, timer has lost %u "
24329 + "ticks [rounded up]\n",
24331 + (unsigned int)((-diff + cycles - 1) / cycles));
24336 + diff = (int)next - (int)UBICOM32_IO_TIMER->sysval;
24338 + } while (diff < 0);
24345 + * Returns current time in nano-second units.
24348 + * 1) This is an override for the weak alias in
24349 + * kernel/sched_clock.c.
24350 + * 2) Do not use xtime_lock as this function is
24351 + * sometimes called with xtime_lock held.
24352 + * 3) We use a retry algorithm to ensure that
24353 + * we get a consistent value.
24354 + * 4) sched_clock must be overwritten if IRQ tracing
24355 + * is enabled because the default implementation uses
24356 + * the xtime_lock sequence while holding xtime_lock.
24358 +unsigned long long sched_clock(void)
24360 + unsigned long long my_jiffies;
24361 + unsigned long jiffies_top;
24362 + unsigned long jiffies_bottom;
24365 + jiffies_top = jiffies_64 >> 32;
24366 + jiffies_bottom = jiffies_64 & 0xffffffff;
24367 + } while (unlikely(jiffies_top != (unsigned long)(jiffies_64 >> 32)));
24369 + my_jiffies = ((unsigned long long)jiffies_top << 32) | (jiffies_bottom);
24370 + return (my_jiffies - INITIAL_JIFFIES) * (NSEC_PER_SEC / HZ);
24375 + * Free a hardware timer.
24377 +void timer_free(int interrupt)
24379 + unsigned int bit = interrupt - TIMER_INT(0);
24382 + * The timer had not been allocated.
24384 + BUG_ON(timers & (1 << bit));
24385 + timers |= (1 << bit);
24390 + * Allocate a hardware timer.
24392 +int timer_alloc(void)
24394 + unsigned int bit = find_first_bit((unsigned long *)&timers, 32);
24396 + printk(KERN_WARNING "no more free timers\n");
24400 + timers &= ~(1 << bit);
24401 + return bit + TIMER_INT(0);
24406 + * Time init function.
24408 +void time_init(void)
24411 + * Find the processor node and determine what timers are
24412 + * available for us.
24414 + timers = processor_timers();
24415 + if (timers == 0) {
24416 + printk(KERN_WARNING "no timers are available for Linux\n");
24420 +#ifdef CONFIG_GENERIC_CLOCKEVENTS
24421 + timer_device_init();
24423 + timer_tick_init();
24427 +++ b/arch/ubicom32/kernel/timer_broadcast.c
24430 + * arch/ubicom32/kernel/timer_broadcast.c
24431 + * Implements a dummy clock event for each cpu.
24433 + * Copyright (C) 2008 Paul Mundt
24434 + * (C) Copyright 2009, Ubicom, Inc.
24436 + * This file is part of the Ubicom32 Linux Kernel Port.
24438 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
24439 + * it and/or modify it under the terms of the GNU General Public License
24440 + * as published by the Free Software Foundation, either version 2 of the
24441 + * License, or (at your option) any later version.
24443 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
24444 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
24445 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
24446 + * the GNU General Public License for more details.
24448 + * You should have received a copy of the GNU General Public License
24449 + * along with the Ubicom32 Linux Kernel Port. If not,
24450 + * see <http://www.gnu.org/licenses/>.
24452 + * Ubicom32 implementation derived from (with many thanks):
24459 +#include <linux/init.h>
24460 +#include <linux/kernel.h>
24461 +#include <linux/delay.h>
24462 +#include <linux/device.h>
24463 +#include <linux/smp.h>
24464 +#include <linux/jiffies.h>
24465 +#include <linux/percpu.h>
24466 +#include <linux/clockchips.h>
24467 +#include <linux/irq.h>
24469 +static DEFINE_PER_CPU(struct clock_event_device, local_clockevent);
24472 + * The broadcast trick only works when the timer will be used in a periodic mode.
24473 + * If the user has configured either NO_HZ or HIGH_RES_TIMERS they must have
24474 + * a per cpu timer.
24476 +#if defined(CONFIG_NO_HZ) || defined(CONFIG_HIGH_RES_TIMERS)
24477 +#error "Tickless and High Resolution Timers require per-CPU local timers: CONFIG_LOCAL_TIMERS"
24481 + * local_timer_interrupt()
24482 + * Used on SMP for local timer interrupt sent via an IPI.
24484 +void local_timer_interrupt(void)
24486 + struct clock_event_device *dev = &__get_cpu_var(local_clockevent);
24488 + dev->event_handler(dev);
24492 + * dummy_timer_set_next_event()
24493 + * Cause the timer to go off "cycles" from now.
24495 +static int dummy_timer_set_next_event(unsigned long cycles, struct clock_event_device *dev)
24501 + * dummy_timer_set_mode()
24504 +static void dummy_timer_set_mode(enum clock_event_mode mode,
24505 + struct clock_event_device *clk)
24510 + * local_timer_setup()
24511 + * Adds a clock event for the specified cpu.
24513 +int __cpuinit local_timer_setup(unsigned int cpu)
24515 + struct clock_event_device *dev = &per_cpu(local_clockevent, cpu);
24517 + dev->name = "timer-dummy";
24518 + dev->features = CLOCK_EVT_FEAT_DUMMY;
24519 + dev->rating = 200;
24521 + dev->set_mode = dummy_timer_set_mode;
24522 + dev->set_next_event = dummy_timer_set_next_event;
24523 + dev->broadcast = smp_timer_broadcast;
24524 + dev->cpumask = cpumask_of_cpu(cpu);
24526 + printk(KERN_NOTICE "timer[%d]: %s - created\n", dev->irq, dev->name);
24528 + clockevents_register_device(dev);
24532 +++ b/arch/ubicom32/kernel/timer_device.c
24535 + * arch/ubicom32/kernel/timer_device.c
24536 + * Implements a Ubicom32 clock device and event devices.
24538 + * (C) Copyright 2009, Ubicom, Inc.
24540 + * This file is part of the Ubicom32 Linux Kernel Port.
24542 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
24543 + * it and/or modify it under the terms of the GNU General Public License
24544 + * as published by the Free Software Foundation, either version 2 of the
24545 + * License, or (at your option) any later version.
24547 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
24548 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
24549 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
24550 + * the GNU General Public License for more details.
24552 + * You should have received a copy of the GNU General Public License
24553 + * along with the Ubicom32 Linux Kernel Port. If not,
24554 + * see <http://www.gnu.org/licenses/>.
24556 + * Ubicom32 implementation derived from (with many thanks):
24561 +#include <linux/types.h>
24562 +#include <linux/clockchips.h>
24563 +#include <linux/clocksource.h>
24564 +#include <linux/spinlock.h>
24565 +#include <asm/ip5000.h>
24566 +#include <asm/machdep.h>
24568 +#if defined(CONFIG_SMP)
24569 +#include <asm/smp.h>
24572 +#if defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)
24573 +#define MAX_TIMERS (2 + CONFIG_TIMER_EXTRA_ALLOC)
24575 +#define MAX_TIMERS (NR_CPUS + CONFIG_TIMER_EXTRA_ALLOC)
24578 +#if (MAX_TIMERS > 10)
24579 +#error "Ubicom32 only has 10 timers"
24582 +static unsigned int frequency;
24583 +static struct clock_event_device timer_device_devs[MAX_TIMERS];
24584 +static struct irqaction timer_device_irqs[MAX_TIMERS];
24585 +static int timer_device_next_timer = 0;
24587 +DEFINE_SPINLOCK(timer_device_lock);
24590 + * timer_device_set_next_event()
24591 + * Cause the timer to go off "cycles" from now.
24593 +static int timer_device_set_next_event(unsigned long cycles, struct clock_event_device *dev)
24595 + timer_set(dev->irq, cycles);
24600 + * timer_device_set_mode()
24601 + * Handle the mode switch for a clock event device.
24603 +static void timer_device_set_mode(enum clock_event_mode mode, struct clock_event_device *dev)
24606 + case CLOCK_EVT_MODE_SHUTDOWN:
24608 + * Make sure the vector is disabled
24609 + * until the next event is set.
24611 + printk(KERN_NOTICE "timer[%d]: shutdown\n", dev->irq);
24612 + ldsr_disable_vector(dev->irq);
24615 + case CLOCK_EVT_MODE_ONESHOT:
24617 + * Make sure the vector is disabled
24618 + * until the next event is set.
24620 + printk(KERN_NOTICE "timer[%d]: oneshot\n", dev->irq);
24621 + ldsr_disable_vector(dev->irq);
24624 + case CLOCK_EVT_MODE_PERIODIC:
24626 + * The periodic request is 1 per jiffies
24628 + printk(KERN_NOTICE "timer[%d]: periodic: %d cycles\n",
24629 + dev->irq, frequency / CONFIG_HZ);
24630 + timer_set(dev->irq, frequency / CONFIG_HZ);
24633 + case CLOCK_EVT_MODE_UNUSED:
24634 + case CLOCK_EVT_MODE_RESUME:
24635 + printk(KERN_WARNING "timer[%d]: unimplemented mode: %d\n",
24642 + * timer_device_event()
24643 + * Call the device's event handler.
24645 + * The pointer is initialized by the generic Linux code
24646 + * to the function to be called.
24648 +static irqreturn_t timer_device_event(int irq, void *dev_id)
24650 + struct clock_event_device *dev = (struct clock_event_device *)dev_id;
24652 + if (dev->mode == CLOCK_EVT_MODE_PERIODIC) {
24654 + * The periodic request is 1 per jiffies
24656 + timer_reset(dev->irq, frequency / CONFIG_HZ);
24659 + * The timer will go off again at the rollover
24660 + * point. We must disable the IRQ to prevent
24661 + * getting a spurious interrupt.
24663 + ldsr_disable_vector(dev->irq);
24666 + if (!dev->event_handler) {
24667 + printk(KERN_CRIT "no registered event handler\n");
24668 + return IRQ_HANDLED;
24671 + dev->event_handler(dev);
24672 + return IRQ_HANDLED;
24676 + * timer_device_clockbase_read()
24677 + * Provide a primary clocksource around the sysval timer.
24679 +static cycle_t timer_device_clockbase_read(void)
24681 + return (cycle_t)UBICOM32_IO_TIMER->sysval;
24685 + * Primary Clock Source Description
24687 + * We use 24 for the shift factor because we want
24688 + * to ensure there are less than 2^24 clocks
24689 + * in a jiffie of 10 ms.
24691 +static struct clocksource timer_device_clockbase = {
24692 + .name = "sysval",
24694 + .flags = CLOCK_SOURCE_IS_CONTINUOUS,
24695 + .mask = CLOCKSOURCE_MASK(32),
24698 + .read = timer_device_clockbase_read,
24702 + * timer_device_alloc_event()
24703 + * Allocate a timer device event.
24705 +static int timer_device_alloc_event(const char *name, int cpuid, const cpumask_t *mask)
24707 + struct clock_event_device *dev;
24708 + struct irqaction *action;
24711 + * Are we out of configured timers?
24713 + spin_lock(&timer_device_lock);
24714 + if (timer_device_next_timer >= MAX_TIMERS) {
24715 + spin_unlock(&timer_device_lock);
24716 + printk(KERN_WARNING "out of timer event entries\n");
24719 + dev = &timer_device_devs[timer_device_next_timer];
24720 + action = &timer_device_irqs[timer_device_next_timer];
24721 + timer_device_next_timer++;
24722 + spin_unlock(&timer_device_lock);
24725 + * Now allocate a timer to ourselves.
24727 + dev->irq = timer_alloc();
24728 + if (dev->irq == -1) {
24729 + spin_lock(&timer_device_lock);
24730 + timer_device_next_timer--;
24731 + spin_unlock(&timer_device_lock);
24732 + printk(KERN_WARNING "out of hardware timers\n");
24737 + * Init the IRQ action structure. Make sure
24738 + * this in place before you register the clock
24741 + action->name = name;
24742 + action->flags = IRQF_DISABLED | IRQF_TIMER;
24743 + action->handler = timer_device_event;
24744 + cpumask_copy(&action->mask, mask);
24745 + action->dev_id = dev;
24746 + setup_irq(dev->irq, action);
24747 + irq_set_affinity(dev->irq, mask);
24748 + ldsr_disable_vector(dev->irq);
24751 + * init clock dev structure.
24753 + * The min_delta_ns is chosen to ensure that setting next
24754 + * event will never be requested with too small of value.
24756 + dev->name = name;
24757 + dev->rating = timer_device_clockbase.rating;
24758 + dev->shift = timer_device_clockbase.shift;
24759 + dev->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
24760 + dev->set_mode = timer_device_set_mode;
24761 + dev->set_next_event = timer_device_set_next_event;
24762 + dev->mult = div_sc(frequency, NSEC_PER_SEC, dev->shift);
24763 + dev->max_delta_ns = clockevent_delta2ns(0xffffffff, dev);
24764 + dev->min_delta_ns = clockevent_delta2ns(100, dev);
24765 + dev->cpumask = mask;
24766 + printk(KERN_NOTICE "timer[%d]: %s - created\n", dev->irq, dev->name);
24769 + * Now register the device.
24771 + clockevents_register_device(dev);
24775 +#if defined(CONFIG_LOCAL_TIMERS)
24777 + * local_timer_setup()
24778 + * Allocation function for creating a per cpu local timer.
24780 +int __cpuinit local_timer_setup(unsigned int cpu)
24782 + return timer_device_alloc_event("timer-cpu", cpu, cpumask_of(cpu));
24787 + * timer_device_init()
24788 + * Create and init a generic clock driver for Ubicom32.
24790 +void timer_device_init(void)
24795 + * Get the frequency from the processor device tree node or use
24796 + * the default if not available. We will store this as the frequency
24797 + * of the timer to avoid future calculations.
24799 + frequency = processor_frequency();
24800 + if (frequency == 0) {
24801 + frequency = CLOCK_TICK_RATE;
24805 + * Setup the primary clock source around sysval. Linux does not
24806 + * supply a Mhz multiplier so convert down to khz.
24808 + timer_device_clockbase.mult =
24809 + clocksource_khz2mult(frequency / 1000,
24810 + timer_device_clockbase.shift);
24811 + if (clocksource_register(&timer_device_clockbase)) {
24812 + printk(KERN_ERR "timer: clocksource failed to register\n");
24817 + * Always allocate a primary timer.
24819 + timer_device_alloc_event("timer-primary", -1, CPU_MASK_ALL_PTR);
24821 +#if defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)
24823 + * If BROADCAST is selected we need to add a broadcast timer.
24825 + timer_device_alloc_event("timer-broadcast", -1, CPU_MASK_ALL_PTR);
24829 + * Allocate extra timers that are requested.
24831 + for (i = 0; i < CONFIG_TIMER_EXTRA_ALLOC; i++) {
24832 + timer_device_alloc_event("timer-extra", -1, CPU_MASK_ALL_PTR);
24836 +++ b/arch/ubicom32/kernel/timer_tick.c
24839 + * arch/ubicom32/kernel/timer_tick.c
24840 + * Impelemets a perodic timer.
24842 + * (C) Copyright 2009, Ubicom, Inc.
24843 + * Copyright (C) 1991, 1992, 1995 Linus Torvalds
24845 + * This file is part of the Ubicom32 Linux Kernel Port.
24847 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
24848 + * it and/or modify it under the terms of the GNU General Public License
24849 + * as published by the Free Software Foundation, either version 2 of the
24850 + * License, or (at your option) any later version.
24852 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
24853 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
24854 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
24855 + * the GNU General Public License for more details.
24857 + * You should have received a copy of the GNU General Public License
24858 + * along with the Ubicom32 Linux Kernel Port. If not,
24859 + * see <http://www.gnu.org/licenses/>.
24861 + * Ubicom32 implementation derived from (with many thanks):
24867 +#include <linux/profile.h>
24869 +#include <asm/ip5000.h>
24870 +#include <asm/machdep.h>
24871 +#if defined(CONFIG_SMP)
24872 +#include <asm/smp.h>
24875 +static unsigned int timervector;
24876 +static unsigned int frequency;
24880 + * Kernel system timer support. Needs to keep up the real-time clock,
24881 + * as well as call the "do_timer()" routine every clocktick.
24883 +static irqreturn_t timer_tick(int irq, void *dummy)
24887 + BUG_ON(!irqs_disabled());
24888 + ticks = timer_reset(timervector, frequency);
24890 + write_seqlock(&xtime_lock);
24892 + write_sequnlock(&xtime_lock);
24894 + update_process_times(user_mode(get_irq_regs()));
24895 + profile_tick(CPU_PROFILING);
24897 +#if defined(CONFIG_SMP)
24898 + smp_send_timer_all();
24900 + return(IRQ_HANDLED);
24904 + * Data used by setup_irq for the timer.
24906 +static struct irqaction timer_irq = {
24908 + .flags = IRQF_DISABLED | IRQF_TIMER,
24909 + .handler = timer_tick,
24913 + * timer_tick_init()
24914 + * Implements a periodic timer
24916 + * This implementation directly calls the timer_tick() and move
24917 + * the Linux kernel forward. This is used when the user has not
24918 + * selected GENERIC_CLOCKEVENTS.
24920 +void timer_tick_init(void)
24923 + * Now allocate a timer to ourselves.
24925 + timervector = timer_alloc();
24926 + if (timervector == -1) {
24927 + printk(KERN_WARNING "where did the timer go?\n");
24931 + setup_irq(timervector, &timer_irq);
24934 + * Get the frequency from the processor device tree node or use
24935 + * the default if not available. We will store this as the frequency
24936 + * of the timer to avoid future calculations.
24938 + frequency = processor_frequency();
24939 + if (frequency == 0) {
24940 + frequency = CLOCK_TICK_RATE;
24942 + frequency /= CONFIG_HZ;
24944 + printk(KERN_NOTICE "timer will interrupt every: %d cycles\n", frequency);
24945 + timer_set(timervector, frequency);
24948 +++ b/arch/ubicom32/kernel/topology.c
24951 + * arch/ubicom32/kernel/topology.c
24952 + * Ubicom32 architecture sysfs topology information.
24954 + * (C) Copyright 2009, Ubicom, Inc.
24956 + * This file is part of the Ubicom32 Linux Kernel Port.
24958 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
24959 + * it and/or modify it under the terms of the GNU General Public License
24960 + * as published by the Free Software Foundation, either version 2 of the
24961 + * License, or (at your option) any later version.
24963 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
24964 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
24965 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
24966 + * the GNU General Public License for more details.
24968 + * You should have received a copy of the GNU General Public License
24969 + * along with the Ubicom32 Linux Kernel Port. If not,
24970 + * see <http://www.gnu.org/licenses/>.
24972 + * Ubicom32 implementation derived from (with many thanks):
24978 +#include <linux/init.h>
24979 +#include <linux/smp.h>
24980 +#include <linux/cpu.h>
24981 +#include <linux/cache.h>
24983 +static struct cpu cpu_devices[NR_CPUS] __read_mostly;
24985 +static int __init topology_init(void)
24989 + for_each_present_cpu(num) {
24990 + cpu_devices[num].hotpluggable = 0;
24991 + register_cpu(&cpu_devices[num], num);
24996 +subsys_initcall(topology_init);
24998 +++ b/arch/ubicom32/kernel/traps.c
25001 + * arch/ubicom32/kernel/traps.c
25002 + * Ubicom32 architecture trap handling support.
25004 + * (C) Copyright 2009, Ubicom, Inc.
25006 + * This file is part of the Ubicom32 Linux Kernel Port.
25008 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
25009 + * it and/or modify it under the terms of the GNU General Public License
25010 + * as published by the Free Software Foundation, either version 2 of the
25011 + * License, or (at your option) any later version.
25013 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
25014 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
25015 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
25016 + * the GNU General Public License for more details.
25018 + * You should have received a copy of the GNU General Public License
25019 + * along with the Ubicom32 Linux Kernel Port. If not,
25020 + * see <http://www.gnu.org/licenses/>.
25022 + * Ubicom32 implementation derived from (with many thanks):
25029 + * Sets up all exception vectors
25031 +#include <linux/sched.h>
25032 +#include <linux/signal.h>
25033 +#include <linux/kernel.h>
25034 +#include <linux/mm.h>
25035 +#include <linux/module.h>
25036 +#include <linux/types.h>
25037 +#include <linux/a.out.h>
25038 +#include <linux/user.h>
25039 +#include <linux/string.h>
25040 +#include <linux/linkage.h>
25041 +#include <linux/init.h>
25042 +#include <linux/ptrace.h>
25043 +#include <linux/kallsyms.h>
25044 +#include <linux/compiler.h>
25045 +#include <linux/stacktrace.h>
25046 +#include <linux/personality.h>
25048 +#include <asm/uaccess.h>
25049 +#include <asm/stacktrace.h>
25050 +#include <asm/devtree.h>
25051 +#include <asm/setup.h>
25052 +#include <asm/fpu.h>
25053 +#include <asm/system.h>
25054 +#include <asm/traps.h>
25055 +#include <asm/pgtable.h>
25056 +#include <asm/processor.h>
25057 +#include <asm/machdep.h>
25058 +#include <asm/siginfo.h>
25059 +#include <asm/ip5000.h>
25060 +#include <asm/thread.h>
25062 +#define TRAP_MAX_STACK_DEPTH 20
25065 + * These symbols are filled in by the linker.
25067 +extern unsigned long _stext;
25068 +extern unsigned long _etext;
25070 +extern unsigned long __ocm_text_run_begin;
25071 +extern unsigned long __data_begin;
25073 +extern void show_vmas(struct task_struct *task);
25075 +const char *trap_cause_strings[] = {
25076 + /*0*/ "inst address decode error",
25077 + /*1*/ "inst sync error",
25078 + /*2*/ "inst illegal",
25079 + /*3*/ "src1 address decode error",
25080 + /*4*/ "dst address decode error",
25081 + /*5*/ "src1 alignment error",
25082 + /*6*/ "dst alignment error",
25083 + /*7*/ "src1 sync error",
25084 + /*8*/ "dst sync error",
25085 + /*9*/ "DCAPT error",
25086 + /*10*/ "inst range error",
25087 + /*11*/ "src1 range error",
25088 + /*12*/ "dst range error",
25092 + * The device tree trap node definition.
25095 + struct devtree_node dn;
25096 + unsigned int intthread;
25099 +static struct trapnode *tn;;
25102 + * trap_interrupt_handler()
25103 + * Software Interrupt to ensure that a trap is serviced.
25105 +static irqreturn_t trap_interrupt_handler(int irq, void *dummy)
25108 + return IRQ_HANDLED;
25112 + * Data used by setup_irq for the timer.
25114 +static struct irqaction trap_irq = {
25116 + .flags = IRQF_DISABLED,
25117 + .handler = trap_interrupt_handler,
25121 + * trap_cause_to_str()
25122 + * Convert a trap_cause into a series of printk
25124 +static void trap_cause_to_str(long status)
25128 + if ((status & ((1 << TRAP_CAUSE_TOTAL) - 1)) == 0) {
25129 + printk(KERN_NOTICE "decode: UNKNOWN CAUSES\n");
25133 + for (bit = 0; bit < TRAP_CAUSE_TOTAL; bit++) {
25134 + if (status & (1 << bit)) {
25135 + printk(KERN_NOTICE "\tdecode: %08x %s\n",
25136 + 1 << bit, trap_cause_strings[bit]);
25142 + * trap_print_information()
25143 + * Print the cause of the trap and additional info.
25145 +static void trap_print_information(const char *str, struct pt_regs *regs)
25147 + printk(KERN_WARNING "\n");
25150 + printk(KERN_WARNING "Process %s (pid: %d)\n",
25151 + current->comm, current->pid);
25154 + if (current && current->mm) {
25155 + printk(KERN_NOTICE "text = 0x%p-0x%p data = 0x%p-0x%p\n"
25156 + KERN_NOTICE "bss = 0x%p-0x%p user-stack = 0x%p\n"
25157 + KERN_NOTICE "\n",
25158 + (void *)current->mm->start_code,
25159 + (void *)current->mm->end_code,
25160 + (void *)current->mm->start_data,
25161 + (void *)current->mm->end_data,
25162 + (void *)current->mm->end_data,
25163 + (void *)current->mm->brk,
25164 + (void *)current->mm->start_stack);
25167 + printk(KERN_WARNING "%s: Causes: 0x%08x\n", str,
25168 + (unsigned int)regs->trap_cause);
25169 + trap_cause_to_str(regs->trap_cause);
25171 + show_stack(NULL, (unsigned long *)regs->an[7]);
25172 + printk(KERN_NOTICE "--- End Trap --- \n");
25177 + * Dump the stack of the current task.
25179 +void dump_stack(void)
25181 + show_stack(NULL, NULL);
25183 +EXPORT_SYMBOL(dump_stack);
25187 + * Print out information from the current stack.
25189 +void show_stack(struct task_struct *task, unsigned long *sp)
25192 + * Allocate just enough entries on the stack.
25194 + unsigned int calls[TRAP_MAX_STACK_DEPTH];
25195 + unsigned long code_start;
25196 + unsigned long code_end;
25197 + unsigned long ocm_code_start = (unsigned long)&__ocm_text_run_begin;
25198 + unsigned long ocm_code_end = (unsigned long)&__data_begin;
25199 + unsigned long stack_end = (unsigned long)(current->stack + THREAD_SIZE - 8);
25200 + unsigned long stack = (unsigned long)sp;
25201 + int kernel_stack = 1;
25203 + processor_dram(&code_start, &code_end);
25206 + * Which task are we talking about.
25213 + * Find the stack for the task if one was not specified. Otherwise
25214 + * use the specified stack.
25217 + if (task != current) {
25218 + stack = task->thread.sp;
25219 + stack_end = (unsigned long)task->stack + THREAD_SIZE - 8;
25222 + "move.4 %0, SP \n\t"
25228 + printk(KERN_NOTICE "Starting backtrace: PID %d '%s'\n",
25229 + task->pid, task->comm);
25232 + * We do 2 passes the first pass is Kernel stack is the second
25235 + while (kernel_stack) {
25236 + unsigned long *handle;
25237 + unsigned int i, idx = 0;
25238 + struct pt_regs *pt = task_pt_regs(task);
25241 + * If the task is in user mode, reset the start
25242 + * and end values for text.
25244 + if (__user_mode(stack)) {
25245 + if (!(task->personality & FDPIC_FUNCPTRS)) {
25246 + printk(KERN_NOTICE " User Stack:\n");
25247 + code_start = task->mm->start_code;
25248 + code_end = task->mm->end_code;
25250 + printk(KERN_NOTICE " User Stack (fdpic):\n");
25253 + stack_end = task->mm->start_stack;
25254 + ocm_code_end = ocm_code_start = 0;
25255 + kernel_stack = 0;
25257 + printk(KERN_NOTICE " Kernel Stack:\n");
25261 + * Collect the stack back trace information.
25263 + printk(" code[0x%lx-0x%lx]", code_start, code_end);
25264 + if (ocm_code_start) {
25265 + printk(" ocm_code[0x%lx-0x%lx]",
25266 + ocm_code_start, ocm_code_end);
25268 + printk("\n stack[0x%lx-0x%lx]\n", stack, stack_end);
25270 + handle = (unsigned long*)stack;
25271 + while (idx < TRAP_MAX_STACK_DEPTH) {
25272 + calls[idx] = stacktrace_iterate(&handle,
25273 + code_start, code_end,
25274 + ocm_code_start, ocm_code_end,
25275 + (unsigned long)stack, stack_end);
25276 + if (calls[idx] == 0) {
25283 + * Now print out the data.
25285 + printk(KERN_NOTICE " CALL && CALLI on stack:");
25286 + for (i = 0; i < idx; i++) {
25287 + printk("%s0x%x, ", (i & 0x3) == 0 ? "\n " : "",
25290 + printk(idx == TRAP_MAX_STACK_DEPTH ? "...\n" : "\n");
25293 + * If we are doing user stack we are done
25295 + if (!kernel_stack) {
25300 + * Does this kernel stack have a mm (i.e. is it user)
25303 + printk("No mm for userspace stack.\n");
25307 + * Get the user-mode stack (if any)
25309 + stack = pt->an[7];
25310 + printk(KERN_NOTICE "Userspace stack at 0x%lx frame type %d\n",
25311 + stack, (int)pt->frame_type);
25312 + if (!__user_mode(stack)) {
25319 + * die_if_kernel()
25320 + * Determine if we are in kernel mode and if so print stuff out and die.
25322 +void die_if_kernel(char *str, struct pt_regs *regs, long trap_cause)
25324 + unsigned int s3value;
25326 + if (user_mode(regs)) {
25330 + console_verbose();
25331 + trap_print_information(str, regs);
25334 + * If the debugger is attached via the hardware mailbox protocol,
25335 + * go into an infinite loop and the debugger will figure things out.
25338 + "move.4 %0, scratchpad3"
25342 + asm volatile("1: jmpt.t 1b");
25346 + * Set the debug taint value.
25348 + add_taint(TAINT_DIE);
25349 + do_exit(SIGSEGV);
25356 + * Traps are treated as interrupts and registered with the LDSR. When
25357 + * the LDSR takes the interrupt, it will determine if a trap has occurred
25358 + * and service the trap prior to servicing the interrupt.
25360 + * This function is directly called by the LDSR.
25362 +void trap_handler(int irq, struct pt_regs *regs)
25364 + int sig = SIGSEGV;
25366 + unsigned int trap_cause = regs->trap_cause;
25368 + BUG_ON(!irqs_disabled());
25371 + * test if in kernel and die.
25373 + die_if_kernel("Kernel Trap", regs, trap_cause);
25376 + * User process problem, setup a signal for this process
25378 + if ((trap_cause & (1 << TRAP_CAUSE_DST_RANGE_ERR)) ||
25379 + (trap_cause & (1 << TRAP_CAUSE_SRC1_RANGE_ERR)) ||
25380 + (trap_cause & (1 << TRAP_CAUSE_I_RANGE_ERR))) {
25382 + info.si_code = SEGV_MAPERR;
25383 + } else if ((trap_cause & (1 << TRAP_CAUSE_DST_MISALIGNED)) ||
25384 + (trap_cause & (1 << TRAP_CAUSE_SRC1_MISALIGNED))) {
25386 + info.si_code = BUS_ADRALN;
25387 + } else if ((trap_cause & (1 << TRAP_CAUSE_DST_DECODE_ERR)) ||
25388 + (trap_cause & (1 << TRAP_CAUSE_SRC1_DECODE_ERR))) {
25390 + info.si_code = ILL_ILLOPN;
25391 + } else if ((trap_cause & (1 << TRAP_CAUSE_ILLEGAL_INST))) {
25393 + * Check for software break point and if found signal trap
25394 + * not illegal instruction.
25396 + unsigned long instruction;
25397 + if (between(regs->pc, KERNELSTART, memory_end) &&
25398 + (regs->pc & 3) == 0 &&
25399 + get_user(instruction, (unsigned long *)regs->pc) == 0) {
25402 + * This used to be 0xaabbccdd but it turns out
25403 + * that is now valid in ubicom32v4 isa so we
25404 + * have switched to 0xfabbccdd
25406 + if ((instruction == 0xfabbccdd) ||
25407 + (instruction == 0xaabbccdd)) {
25409 + info.si_code = TRAP_BRKPT;
25410 + goto send_signal;
25414 + info.si_code = ILL_ILLOPC;
25415 + } else if ((trap_cause & (1 << TRAP_CAUSE_I_DECODE_ERR))) {
25417 + info.si_code = ILL_ILLOPC;
25418 + } else if ((trap_cause & (1 << TRAP_CAUSE_DCAPT))) {
25420 + info.si_code = TRAP_TRACE;
25424 + * Print a trap information block to the console, do not
25425 + * print this above the case because we don't want it
25426 + * printed for software break points.
25428 + trap_print_information("User Trap", regs);
25432 + force_sig_info(sig, &info, current);
25435 + * Interrupts are disabled, re-enable them now.
25437 + if (!irqs_disabled()) {
25438 + printk(KERN_EMERG "interrupts enabled on exit, irq=%d, regs=%p",
25445 + * trap_init_interrupt()
25446 + * We need a 2nd trap handling init that will occur after init_IRQ().
25448 +void __init trap_init_interrupt(void)
25451 + unsigned char tirq;
25452 + struct devtree_node *dn = (struct devtree_node *)tn;
25455 + * Now setup the Software IRQ so that if a trap occurs the LDSR
25456 + * is started. The irq is there just to "force" the LDSR to run.
25459 + printk(KERN_WARNING "trap_init_interrupt skipped.\n");
25463 + err = devtree_irq(dn, NULL, &tirq);
25465 + printk(KERN_WARNING "error obtaining trap irq value: %d\n",
25470 + if (tirq == DEVTREE_IRQ_NONE) {
25471 + printk(KERN_WARNING "trap irq not available: %d\n", tirq);
25475 + err = setup_irq(tirq, &trap_irq);
25477 + printk(KERN_WARNING "trap irq setup failed: %d\n", err);
25482 + * Let ultra know which thread is handling the traps and
25483 + * what the interrupt to use is.
25485 + tn->intthread = ldsr_get_threadid();
25488 + * Tell the LDSR about our IRQ so that it will unsuspend
25489 + * if one occurs while waiting for the per thread lock.
25491 + ldsr_set_trap_irq(tirq);
25496 + * init trap handling
25498 + * Trap handling is done through the ldsr. Every time an interrupt
25499 + * occurs, the LDSR looks for threads that are listed in the TRAP
25500 + * register and forces a call to the trap handler.
25502 +void __init trap_init(void)
25505 + * If we do not have a trap node in the device tree, we leave the fault
25506 + * handling to the underlying hardware.
25508 + tn = (struct trapnode *)devtree_find_node("traps");
25510 + printk(KERN_WARNING "traps are not handled by linux\n");
25515 +++ b/arch/ubicom32/kernel/uaccess.c
25518 + * arch/ubicom32/include/asm/uaccess.c
25519 + * User space memory access functions for Ubicom32 architecture.
25521 + * (C) Copyright 2009, Ubicom, Inc.
25523 + * This file is part of the Ubicom32 Linux Kernel Port.
25525 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
25526 + * it and/or modify it under the terms of the GNU General Public License
25527 + * as published by the Free Software Foundation, either version 2 of the
25528 + * License, or (at your option) any later version.
25530 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
25531 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
25532 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
25533 + * the GNU General Public License for more details.
25535 + * You should have received a copy of the GNU General Public License
25536 + * along with the Ubicom32 Linux Kernel Port. If not,
25537 + * see <http://www.gnu.org/licenses/>.
25539 + * Ubicom32 implementation derived from (with many thanks):
25545 +#include <linux/sched.h>
25546 +#include <linux/mm.h>
25547 +#include <linux/string.h>
25548 +#include <linux/module.h>
25550 +#include <asm/segment.h>
25551 +#include <asm/uaccess.h>
25553 +extern int _stext, _etext, _sdata, _edata, _sbss, _ebss, _end;
25557 + * Check that the address is in the current processes.
25559 + * NOTE: The kernel uses "pretend" user addresses that wind
25560 + * up calling access_ok() so this approach has only marginal
25561 + * value because you wind up with lots of false positives.
25563 +int __access_ok(unsigned long addr, unsigned long size)
25565 + // struct vm_area_struct *vma;
25568 + * Don't do anything if we are not a running system yet.
25570 + if (system_state != SYSTEM_RUNNING) {
25575 + * It appears that Linux will call this function even when we are not
25576 + * in the context of a user space application that has a VM address
25577 + * space. So we must check that current and mm are valid before
25578 + * performing the check.
25580 + if ((!current) || (!current->mm)) {
25585 + * We perform some basic checks on the address to ensure that it
25586 + * is at least within the range of DRAM.
25588 + if ((addr < (int)&_etext) || (addr > memory_end)) {
25589 + printk(KERN_WARNING "pid=%d[%s]: range [%lx - %lx] not in memory area: [%lx - %lx]\n",
25590 + current->pid, current->comm,
25591 + addr, addr + size,
25592 + memory_start, memory_end);
25597 + * For nommu Linux we can check this by looking at the allowed
25598 + * memory map for the process.
25600 + * TODO: Since the kernel passes addresses in it's own space as though
25601 + * they were user address, we can not validate the addresses this way.
25604 + if (!down_read_trylock(¤t->mm->mmap_sem)) {
25607 + vma = find_vma(current->mm, addr);
25609 + up_read(¤t->mm->mmap_sem);
25610 + printk(KERN_WARNING "pid=%d[%s]: possible invalid acesss on range: [%lx - %lx]\n",
25611 + current->pid, current->comm, addr, addr + size);
25614 + if ((addr + size) > vma->vm_end) {
25615 + up_read(¤t->mm->mmap_sem);
25616 + printk(KERN_WARNING "pid=%d[%s]: possible invalid length on range: [%lx - %lx]\n",
25617 + current->pid, current->comm, addr, addr + size);
25620 + up_read(¤t->mm->mmap_sem);
25625 +EXPORT_SYMBOL(__access_ok);
25627 +++ b/arch/ubicom32/kernel/ubicom32_context_switch.S
25630 + * arch/ubicom32/kernel/ubicom32_context_switch.S
25631 + * Implements context switch and return functions.
25633 + * (C) Copyright 2009, Ubicom, Inc.
25635 + * This file is part of the Ubicom32 Linux Kernel Port.
25637 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
25638 + * it and/or modify it under the terms of the GNU General Public License
25639 + * as published by the Free Software Foundation, either version 2 of the
25640 + * License, or (at your option) any later version.
25642 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
25643 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
25644 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
25645 + * the GNU General Public License for more details.
25647 + * You should have received a copy of the GNU General Public License
25648 + * along with the Ubicom32 Linux Kernel Port. If not,
25649 + * see <http://www.gnu.org/licenses/>.
25651 + * Ubicom32 implementation derived from (with many thanks):
25656 +#include <linux/sys.h>
25657 +#include <linux/linkage.h>
25658 +#include <asm/asm-offsets.h>
25659 +#include <asm/ubicom32-common.h>
25660 +#include <asm/ip5000.h>
25661 +#include <asm/range-protect.h>
25664 + * begin_restore_context()
25665 + * Restore most of the context from sp (struct pt_reg *)
25667 + * This *can* be called without the global atomic lock. (because sp is
25668 + * not restored!) Only d15 and a3 are allowed to be used after this
25669 + * before calling complete_restore_context
25671 +.macro begin_restore_context
25672 + move.4 d0, PT_D0(sp)
25673 + move.4 d1, PT_D1(sp)
25674 + move.4 d2, PT_D2(sp)
25675 + move.4 d3, PT_D3(sp)
25676 + move.4 d4, PT_D4(sp)
25677 + move.4 d5, PT_D5(sp)
25678 + move.4 d6, PT_D6(sp)
25679 + move.4 d7, PT_D7(sp)
25680 + move.4 d8, PT_D8(sp)
25681 + move.4 d9, PT_D9(sp)
25682 + move.4 d10, PT_D10(sp)
25683 + move.4 d11, PT_D11(sp)
25684 + move.4 d12, PT_D12(sp)
25685 + move.4 d13, PT_D13(sp)
25686 + move.4 d14, PT_D14(sp)
25687 +;; move.4 d15, PT_D15(sp)
25688 + move.4 a0, PT_A0(sp)
25689 + move.4 a1, PT_A1(sp)
25690 + move.4 a2, PT_A2(sp)
25691 +;; move.4 a3, PT_A3(sp)
25692 + move.4 a4, PT_A4(sp)
25693 + move.4 a5, PT_A5(sp)
25694 + move.4 a6, PT_A6(sp)
25695 + move.4 acc0_hi, PT_ACC0HI(sp)
25696 + move.4 acc0_lo, PT_ACC0LO(sp)
25697 + move.4 mac_rc16, PT_MAC_RC16(sp)
25698 + move.4 acc1_hi, PT_ACC1HI(sp)
25699 + move.4 acc1_lo, PT_ACC1LO(sp)
25700 + move.4 source3, PT_SOURCE3(sp)
25701 + move.4 int_mask0, PT_INT_MASK0(sp)
25702 + move.4 int_mask1, PT_INT_MASK1(sp)
25706 + * complete_restore_context()
25707 + * Completely restore the context from sp (struct pt_reg *)
25709 + * Note: Recovered PC and CSR are saved on the stack and are to be
25710 + * popped off before returning.
25712 +.macro complete_restore_context
25714 + move.4 d15, PT_D15(sp)
25715 + move.4 sp, PT_SP(a3) ; Recover Stack pointer from save area
25716 + move.4 -4(sp)++, PT_PC(a3) ; Recover saved PC and save to stack
25717 + move.4 -4(sp)++, PT_CSR(a3) ; Recover saved csr and save to stack
25718 + move.4 a3, PT_A3(a3)
25722 + * old restore_context macro
25724 +.macro restore_context
25725 + begin_restore_context
25726 + complete_restore_context
25730 + * ldsr_thread_enable_interrupts()
25731 + * An assembly version of the enable interrupts function.
25733 + * The stack is fair game but all registers MUST be preserved.
25736 +.macro ldsr_thread_enable_interrupts
25737 + move.4 -4(sp)++, d3 ; Push d3
25738 + move.4 -4(sp)++, a3 ; Push a3
25741 + * Read the ROSR and obtain ~(1 << tid)
25743 + lsr.4 d3, rosr, #0x2 ; Move the thread portion of ROSR into d3
25744 + lsl.4 d3, #1, d3 ; perform a (1 << tid)
25745 + not.4 d3, d3 ; Negate the value of d3 == ~(1 << threadid)
25748 + * Get the value of the ldsr_soft_irq_mask
25750 + moveai a3, #%hi(ldsr_soft_irq_mask)
25751 + move.4 a3, %lo(ldsr_soft_irq_mask)(a3)
25754 + * Now re-enable interrupts for this thread and then
25755 + * wakeup the LDSR.
25757 + and.4 scratchpad1, scratchpad1, d3
25758 + move.4 int_set0, a3
25761 + * Restore the registers.
25763 + move.4 a3, (sp)4++
25764 + move.4 d3, (sp)4++
25768 + * ret_from_interrupt_to_kernel()
25769 + * RFI function that is where do_IRQ() returns to if the thread was
25770 + * in kernel space.
25772 + .section .text.ret_from_interrupt_to_kernel, "ax", @progbits
25773 + .global ret_from_interrupt_to_kernel
25774 +ret_from_interrupt_to_kernel:
25775 + begin_restore_context ; Restore the thread context
25776 + atomic_lock_acquire ; Enter critical section
25777 + complete_restore_context ; Restore the thread context
25778 + atomic_lock_release ; Leave critical section
25779 + ldsr_thread_enable_interrupts ; enable the threads interrupts
25780 + move.4 csr, (sp)4++ ; Restore csr from the stack
25784 + * ret_from_interrupt_to_user()
25785 + * RFI function that is where do_IRQ() returns to if the thread was
25788 + * TODO: Do we really need the critical section handling in this code?
25791 + .section .text.ret_from_interrupt_to_user, "ax", @progbits
25792 + .global ret_from_interrupt_to_user
25793 +ret_from_interrupt_to_user:
25794 + ldsr_thread_enable_interrupts ; enable the threads interrupts
25796 + * Set a1 to the thread info pointer, no need to save it as we are
25797 + * restoring userspace and will never return
25799 + movei d0, #(~(ASM_THREAD_SIZE-1))
25803 + * Test if the scheduler needs to be called.
25805 + btst TI_FLAGS(a1), #ASM_TIF_NEED_RESCHED
25807 + call a5, schedule ; Call the scheduler. I will come back here.
25810 + * See if we have pending signals and call do_signal
25814 + btst TI_FLAGS(a1), #ASM_TIF_SIGPENDING ; Any signals needed?
25818 + * Now call do_signal()
25820 + move.4 d0, #0 ; oldset pointer is NULL
25821 + move.4 d1, sp ; d1 is the regs pointer
25822 + call a5, do_signal ; Call do_signal()
25825 + * Back from do_signal(), re-enter critical section.
25828 + begin_restore_context ; Restore the thread context
25829 + atomic_lock_acquire ; Enter critical section
25830 + call a3, __complete_and_return_to_userspace ; jump to unprotected section
25833 + * restore_all_registers()
25835 + * restore_all_registers will be the alternate exit route for
25836 + * preempted processes that have called a signal handler
25837 + * and are returning back to user space.
25839 + .section .text.restore_all_registers, "ax", @progbits
25840 + .global restore_all_registers
25841 +restore_all_registers:
25842 + begin_restore_context ; Restore the thread context
25843 + atomic_lock_acquire ; Enter critical section
25844 + call a3, __complete_and_return_to_userspace
25847 + * __complete_and_return_to_userspace
25849 + * restores the second half of the context and returns
25850 + * You must have the atomic lock when you call this function
25852 + .section .kernel_unprotected, "ax", @progbits
25853 +__complete_and_return_to_userspace:
25854 + disable_kernel_ranges_for_current d15 ; disable kernel ranges
25855 + complete_restore_context ; restore previous context
25856 + atomic_lock_release ; Leave critical section
25857 + move.4 csr, (sp)4++ ; Restore csr from the stack
25861 + * ret_from_fork()
25862 + * Called on the child's return from fork system call.
25864 + .section .text.ret_from_fork, "ax", @progbits
25865 + .global ret_from_fork
25867 + ;;; d0 contains the arg for schedule_tail
25868 + ;;; the others we don't care about as they are in PT_REGS (sp)
25869 + call a5, schedule_tail
25871 + atomic_lock_acquire ; Enter critical section
25874 + move.4 d0, PT_D0(a3) ; Restore D0
25875 + move.4 d1, PT_D1(a3) ; Restore D1
25876 + move.4 d2, PT_D2(a3) ; Restore D2
25877 + move.4 d3, PT_D3(a3) ; Restore D3
25878 + move.4 d10, PT_D10(a3) ; Restore D10
25879 + move.4 d11, PT_D11(a3) ; Restore D11
25880 + move.4 d12, PT_D12(a3) ; Restore D12
25881 + move.4 d13, PT_D13(a3) ; Restore D13
25882 + move.4 a1, PT_A1(a3) ; Restore A1
25883 + move.4 a2, PT_A2(a3) ; Restore A2
25884 + move.4 a5, PT_A5(a3) ; Restore A5
25885 + move.4 a6, PT_A6(a3) ; Restore A6
25886 + ;; I think atomic_lock_acquire could be moved here..
25887 + move.4 sp, PT_SP(a3) ; Restore sp
25888 + move.4 a4, PT_PC(a3) ; Restore pc in register a4
25889 + move.4 PT_FRAME_TYPE(a3), #0 ; Clear frame_type to indicate it is invalid.
25891 +#ifdef CONFIG_PROTECT_KERNEL
25892 + call a3, __ret_from_fork_bottom_half
25893 + .section .kernel_unprotected, "ax", @progbits
25894 +__ret_from_fork_bottom_half:
25895 + disable_kernel_ranges_for_current d15
25897 + atomic_lock_release ; Leave critical section
25898 + calli a4, 0(a4) ; Return.
25904 + * void *__switch_to(struct task_struct *prev, struct thread_struct *prev_switch,
25905 + * struct thread_struct *next_switch)
25907 + .section .text.__switch_to, "ax", @progbits
25908 + .global __switch_to
25912 + * Set up register a3 to point to save area.
25914 + movea a3, d1 ; a3 now holds prev_switch
25915 + move.4 (a3)4++, d10
25916 + move.4 (a3)4++, d11
25917 + move.4 (a3)4++, d12
25918 + move.4 (a3)4++, d13
25919 + move.4 (a3)4++, a1
25920 + move.4 (a3)4++, a2
25921 + move.4 (a3)4++, a5
25922 + move.4 (a3)4++, a6
25923 + move.4 (a3)4++, a7
25926 + * Set up register a3 to point to restore area.
25928 + movea a3, d2 ; a3 now holds next_switch
25929 + move.4 d10 , (a3)4++
25930 + move.4 d11 , (a3)4++
25931 + move.4 d12 , (a3)4++
25932 + move.4 d13 , (a3)4++
25933 + move.4 a1 , (a3)4++
25934 + move.4 a2 , (a3)4++
25935 + move.4 a5 , (a3)4++
25936 + move.4 a6 , (a3)4++
25937 + move.4 a7 , (a3)4++
25940 + * Load the sw_ksp with the proper thread_info pointer.
25942 + movei d15, #(~(ASM_THREAD_SIZE-1))
25943 + and.4 a3, sp, d15 ; a3 now has the thread info pointer
25944 + moveai a4, #%hi(sw_ksp)
25945 + lea.1 a4, %lo(sw_ksp)(a4) ; a4 now has the base address of sw_ksp array
25946 + lsr.4 d15, ROSR, #2 ; Thread number - bit's 6 through 31 are zeroes anyway.
25947 + move.4 (a4, d15), a3 ; Load the thread info pointer into the hw_ksp array..
25950 + * We are done with context switch. Time to return..
25953 + .size __switch_to, . - __switch_to
25956 + * ubicom32_emulate_insn()
25957 + * Emulates the instruction.
25960 + * unsigned int ubicom32_emulate_insn(int source1, int source2, int source3, int *save_acc, int *save_csr);
25962 + .section .text.ubicom32_emulate_insn, "ax", @progbits
25963 + .global ubicom32_emulate_insn
25964 + .global trap_emulate
25965 +ubicom32_emulate_insn:
25966 + movea a3, d3 ; a3 holds save_acc pointer
25967 + movea a4, d4 ; a4 hods save_csr pointer
25968 + move.4 source3, d2
25969 + move.4 acc0_lo, (a3)
25970 + move.4 acc0_hi, 4(a3)
25971 + move.4 acc1_lo, 8(a3)
25972 + move.4 acc1_hi, 12(a3)
25973 + move.4 mac_rc16, 16(a3)
25980 + move.4 (a4), CSR ; Save csr
25981 + move.4 (a3), acc0_lo
25982 + move.4 4(a3), acc0_hi
25983 + move.4 8(a3), acc1_lo
25984 + move.4 12(a3), acc1_hi
25985 + move.4 16(a3), mac_rc16
25987 + .size ubicom32_emulate_insn, . - ubicom32_emulate_insn
25989 +++ b/arch/ubicom32/kernel/ubicom32_ksyms.c
25992 + * arch/ubicom32/kernel/ubicom32_ksyms.c
25993 + * Ubicom32 architecture compiler support and misc symbols.
25995 + * (C) Copyright 2009, Ubicom, Inc.
25997 + * This file is part of the Ubicom32 Linux Kernel Port.
25999 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
26000 + * it and/or modify it under the terms of the GNU General Public License
26001 + * as published by the Free Software Foundation, either version 2 of the
26002 + * License, or (at your option) any later version.
26004 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
26005 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
26006 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
26007 + * the GNU General Public License for more details.
26009 + * You should have received a copy of the GNU General Public License
26010 + * along with the Ubicom32 Linux Kernel Port. If not,
26011 + * see <http://www.gnu.org/licenses/>.
26013 + * Ubicom32 implementation derived from (with many thanks):
26018 +#include <linux/module.h>
26019 +#include <linux/linkage.h>
26020 +#include <linux/sched.h>
26021 +#include <linux/string.h>
26022 +#include <linux/mm.h>
26023 +#include <linux/user.h>
26024 +#include <linux/elfcore.h>
26025 +#include <linux/in6.h>
26026 +#include <linux/interrupt.h>
26027 +#include <linux/io.h>
26028 +#include <linux/semaphore.h>
26030 +#include <asm/setup.h>
26031 +#include <asm/machdep.h>
26032 +#include <asm/pgalloc.h>
26033 +#include <asm/irq.h>
26034 +#include <asm/checksum.h>
26035 +#include <asm/current.h>
26037 +/* platform dependent support */
26039 +EXPORT_SYMBOL(__ioremap);
26040 +EXPORT_SYMBOL(iounmap);
26042 +EXPORT_SYMBOL(ip_fast_csum);
26045 +/* Networking helper routines. */
26046 +EXPORT_SYMBOL(csum_partial_copy_nocheck);
26048 +/* The following are special because they're not called
26049 + explicitly (the C compiler generates them). Fortunately,
26050 + their interface isn't gonna change any time soon now, so
26051 + it's OK to leave it out of version control. */
26052 +EXPORT_SYMBOL(memcpy);
26053 +EXPORT_SYMBOL(memset);
26054 +EXPORT_SYMBOL(memmove);
26056 +#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) || __GNUC__ > 4
26058 + * libgcc functions - functions that are used internally by the
26059 + * compiler... (prototypes are not correct though, but that
26060 + * doesn't really matter since they're not versioned).
26062 +extern void __ashldi3(void);
26063 +extern void __ashrdi3(void);
26064 +extern void __divsi3(void);
26065 +extern void __divdi3(void);
26066 +extern void __lshrdi3(void);
26067 +extern void __modsi3(void);
26068 +extern void __muldi3(void);
26069 +extern void __udivsi3(void);
26070 +extern void __umodsi3(void);
26072 +/* gcc lib functions */
26073 +EXPORT_SYMBOL(__ashldi3);
26074 +EXPORT_SYMBOL(__ashrdi3);
26075 +EXPORT_SYMBOL(__divsi3);
26076 +EXPORT_SYMBOL(__divdi3);
26077 +EXPORT_SYMBOL(__lshrdi3);
26078 +EXPORT_SYMBOL(__modsi3);
26079 +EXPORT_SYMBOL(__muldi3);
26080 +EXPORT_SYMBOL(__udivsi3);
26081 +EXPORT_SYMBOL(__umodsi3);
26083 +extern void __libgcc_udivmodsi(void);
26084 +extern void __libgcc_divmodsi(void);
26086 +EXPORT_SYMBOL(__libgcc_udivmodsi);
26087 +EXPORT_SYMBOL(__libgcc_divmodsi);
26090 +++ b/arch/ubicom32/kernel/ubicom32_syscall.S
26093 + * arch/ubicom32/kernel/ubicom32_syscall.S
26094 + * <TODO: Replace with short file description>
26096 + * (C) Copyright 2009, Ubicom, Inc.
26098 + * This file is part of the Ubicom32 Linux Kernel Port.
26100 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
26101 + * it and/or modify it under the terms of the GNU General Public License
26102 + * as published by the Free Software Foundation, either version 2 of the
26103 + * License, or (at your option) any later version.
26105 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
26106 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
26107 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
26108 + * the GNU General Public License for more details.
26110 + * You should have received a copy of the GNU General Public License
26111 + * along with the Ubicom32 Linux Kernel Port. If not,
26112 + * see <http://www.gnu.org/licenses/>.
26114 + * Ubicom32 implementation derived from (with many thanks):
26119 +#include <linux/sys.h>
26120 +#include <linux/linkage.h>
26121 +#include <linux/unistd.h>
26123 +#include <asm/ubicom32-common.h>
26124 +#include <asm/thread_info.h>
26125 +#include <asm/asm-offsets.h>
26126 +#include <asm/range-protect.h>
26129 + * __old_system_call()
26131 + .section .old_syscall_entry.text, "ax", @progbits
26132 +#ifdef CONFIG_OLD_40400010_SYSTEM_CALL
26133 +__old_system_call:
26134 + call a3, system_call
26135 + .size __old_system_call, . - __old_system_call ;
26138 + * something that will crash the userspace application, but
26139 + * should not take down the kernel, if protection is enabled
26140 + * this will never even get executed.
26142 + .long 0xFABBCCDE ; illegal instruction
26143 + bkpt #-1 ; we will never get here
26149 + .section .syscall_entry.text, "ax", @progbits
26150 + .global system_call
26153 + * Regular ABI rules for function calls apply for syscall. d8 holds
26154 + * the syscall number. We will use that to index into the syscall table.
26155 + * d0 - d5 hold the parameters.
26157 + * First we get the current thread_info and swap to the kernel stack.
26158 + * This is done by reading the current thread and looking up the ksp
26159 + * from the sw_ksp array and storing it in a3.
26161 + * Then we reserve space for the syscall context a struct pt_regs and
26162 + * save it using a4 initially and later as sp.
26163 + * Once sp is set to the kernel sp we can leave the critical section.
26165 + * For the user case the kernel stack will have the following layout.
26167 + * a3 ksp[0] +-----------------------+
26168 + * | Thread info area |
26169 + * | struct thread_info |
26170 + * +-----------------------+
26172 + * | Kernel Stack Area |
26174 + * a4 / sp >>> +-----------------------+
26175 + * | Context save area |
26176 + * | struct pt_reg |
26177 + * ksp[THREAD_SIZE-8] +-----------------------+
26178 + * | 8 Byte Buffer Zone |
26179 + * ksp[THREAD_SIZE] +-----------------------+
26182 + * For kernel syscalls the layout is as follows.
26184 + * a3 ksp[0] +-----------------------+
26185 + * | Thread info area |
26186 + * | struct thread_info |
26187 + * +-----------------------+
26189 + * | Kernel Stack Area |
26191 + * a4 / sp >>> +-----------------------+
26192 + * | Context save area |
26193 + * | struct pt_reg |
26194 + * sp at syscall entry +-----------------------+
26195 + * | Callers Kernel Stack |
26198 + * Once the context is saved we optionally call syscall_trace and setup
26199 + * the exit routine and jump to the syscall.
26203 + * load the base address for sw_ksp into a3
26204 + * Note.. we cannot access it just yet as protection is still on.
26206 + moveai a3, #%hi(sw_ksp)
26207 + lea.1 a3, %lo(sw_ksp)(a3)
26210 + * Enter critical section .
26212 + * The 'critical' aspects here are the switching the to the ksp and
26213 + * changing the protection registers, these both use per thread
26214 + * information so we need to protect from a context switch. For now this
26215 + * is done using the global atomic lock.
26217 + atomic_lock_acquire
26219 + thread_get_self d15 ; Load current thread number
26220 +#ifdef CONFIG_PROTECT_KERNEL
26221 + lsl.4 d9, #1, d15 ; Convert to thread bit
26222 + enable_kernel_ranges d9
26225 + * in order to reduce the size of code in the syscall section we get
26226 + * out of it right now
26228 + call a4, __system_call_bottom_half
26229 + .size system_call, . - system_call
26231 + .section .text.__system_call_bottom_half, "ax", @progbits
26232 +__system_call_bottom_half:
26235 + * We need to Determine if this is a kernel syscall or user syscall.
26236 + * Start by loading the pointer for the thread_info structure for the
26237 + * current process in to a3.
26239 + move.4 a3, (a3, d15) ; a3 = sw_ksp[d15]
26242 + * Now if this is a kernel thread the same value can be a acheived by
26243 + * masking off the lower bits on the current stack pointer.
26245 + movei d9, #(~(ASM_THREAD_SIZE-1)) ; load mask
26246 + and.4 d9, sp, d9 ; apply mask
26249 + * d9 now has the masked version of the sp. If this is identical to
26250 + * what is in a3 then don't switch to ksp as we are already in the
26256 + * if d9 and a3 are not equal. We are usespace and have to shift to
26262 + * Kernel Syscall.
26264 + * The kernel has called this routine. We have to pdec space for pt_regs
26267 + pdec a4, PT_SIZE(sp) ; a4 = ksp - PT_SIZE
26271 + * Userspace Syscall.
26273 + * Add THREAD_SIZE and subtract PT_SIZE to create the proper ksp
26275 +1: movei d15, #(ASM_THREAD_SIZE - 8 - PT_SIZE)
26276 + lea.1 a4, (a3, d15) ; a4 = ksp + d15
26279 + * Replace user stack pointer with kernel stack pointer (a4)
26280 + * Load -1 into frame_type in save area to indicate this is system call
26283 +2: move.4 PT_A7(a4), a7 ; Save old sp/A7 on kernel stack
26284 + move.4 PT_FRAME_TYPE(a4), #-1 ; Set the frame type.
26285 + move.4 sp, a4 ; Change to ksp.
26287 + * We are now officially back in the kernel!
26291 + * Now that we are on the ksp we can leave the critical section
26293 + atomic_lock_release
26296 + * We need to save a0 because we need to be able to restore it in
26297 + * the event that we need to handle a signal. It's not generally
26298 + * a callee-saved register but is the GOT pointer.
26300 + move.4 PT_A0(sp), a0 ; Save A0 on kernel stack
26303 + * We still need to save d10-d13, a1, a2, a5, a6 in the kernel frame
26304 + * for this process, we also save the system call params in the case of
26305 + * syscall restart. (note a7 was saved above)
26307 + move.4 PT_A1(sp), a1 ; Save A1 on kernel stack
26308 + move.4 PT_A2(sp), a2 ; Save A2 on kernel stack
26309 + move.4 PT_A5(sp), a5 ; Save A5 on kernel stack
26310 + move.4 PT_A6(sp), a6 ; Save A6 on kernel stack
26311 + move.4 PT_PC(sp), a5 ; Save A5 at the PC location
26312 + move.4 PT_D10(sp), d10 ; Save D10 on kernel stack
26313 + move.4 PT_D11(sp), d11 ; Save D11 on kernel stack
26314 + move.4 PT_D12(sp), d12 ; Save D12 on kernel stack
26315 + move.4 PT_D13(sp), d13 ; Save D13 on kernel stack
26318 + * Now save the syscall parameters
26320 + move.4 PT_D0(sp), d0 ; Save d0 on kernel stack
26321 + move.4 PT_ORIGINAL_D0(sp), d0 ; Save d0 on kernel stack
26322 + move.4 PT_D1(sp), d1 ; Save d1 on kernel stack
26323 + move.4 PT_D2(sp), d2 ; Save d2 on kernel stack
26324 + move.4 PT_D3(sp), d3 ; Save d3 on kernel stack
26325 + move.4 PT_D4(sp), d4 ; Save d4 on kernel stack
26326 + move.4 PT_D5(sp), d5 ; Save d5 on kernel stack
26327 + move.4 PT_D8(sp), d8 ; Save d8 on kernel stack
26330 + * Test if syscalls are being traced and if they are jump to syscall
26331 + * trace (it will comeback here)
26333 + btst TI_FLAGS(a3), #ASM_TIF_SYSCALL_TRACE
26334 + jmpne.f .Lsystem_call__trace
26335 +.Lsystem_call__trace_complete:
26337 + * Check for a valid call number [ 0 <= syscall_number < NR_syscalls ]
26341 + cmpi d8, #NR_syscalls
26345 + * They have passed an invalid number. Call sys_ni_syscall staring by
26346 + * load a4 with the base address of sys_ni_syscall
26348 +3: moveai a4, #%hi(sys_ni_syscall)
26349 + lea.1 a4, %lo(sys_ni_syscall)(a4)
26350 + jmpt.t 5f ; Jump to regular processing
26353 + * Validated syscall, load the syscall table base address into a3 and
26354 + * read the syscall ptr out.
26356 +4: moveai a3, #%hi(sys_call_table)
26357 + lea.1 a3, %lo(sys_call_table)(a3) ; a3 = sys_call_table
26358 + move.4 a4, (a3, d8) ; a4 = sys_call_table[d8]
26361 + * Before calling the syscall, setup a5 so that syscall_exit is called
26362 + * on return from syscall
26364 +5: moveai a5, #%hi(syscall_exit) ; Setup return address
26365 + lea.1 a5, %lo(syscall_exit)(a5) ; from system call
26368 + * If the syscall is __NR_rt_rigreturn then we have to test d1 to
26369 + * figure out if we have to change change the return routine to restore
26372 + cmpi d8, #__NR_rt_sigreturn
26376 + * Launch system call (it will return through a5 - syscall_exit)
26381 + * System call is rt_sigreturn. Test d1. If it is 1 we have to
26382 + * change the return address to restore_all_registers
26387 + moveai a5, #%hi(restore_all_registers) ; Setup return address
26388 + lea.1 a5, %lo(restore_all_registers)(a5) ; to restore_all_registers.
26391 + * Launch system call (it will return through a5)
26393 +7: calli a3, 0(a4) ; Launch system call
26395 +.Lsystem_call__trace:
26397 + * Syscalls are being traced.
26398 + * Call syscall_trace, (return here)
26400 + call a5, syscall_trace
26403 + * Restore syscall state (it would have been discarded during the
26406 + move.4 d0, PT_D0(sp) ; Restore d0 from kernel stack
26407 + move.4 d1, PT_D1(sp) ; Restore d1 from kernel stack
26408 + move.4 d2, PT_D2(sp) ; Restore d2 from kernel stack
26409 + move.4 d3, PT_D3(sp) ; Restore d3 from kernel stack
26410 + move.4 d4, PT_D4(sp) ; Restore d4 from kernel stack
26411 + move.4 d5, PT_D5(sp) ; Restore d5 from kernel stack
26412 + /* add this back if we ever have a syscall with 7 args */
26413 + move.4 d8, PT_D8(sp) ; Restore d8 from kernel stack
26416 + * return to syscall
26418 + jmpt.t .Lsystem_call__trace_complete
26419 + .size __system_call_bottom_half, . - __system_call_bottom_half
26424 + .section .text.syscall_exit
26425 + .global syscall_exit
26428 + * d0 contains the return value. We should move that into the kernel
26429 + * stack d0 location. We will be transitioning from kernel to user
26430 + * mode. Test the flags and see if we have to call schedule. If we are
26431 + * going to truly exit then all that has to be done is that from the
26432 + * kernel stack we have to restore d0, a0, a1, a2, a5, a6 and sp (a7)bb
26433 + * and then return via a5.
26437 + * Save d0 to pt_regs
26439 + move.4 PT_D0(sp), d0 ; Save d0 into the kernel stack
26442 + * load the thread_info structure by masking off the THREAD_SIZE
26445 + * Note: we used to push a1, but now we don't as we are going
26446 + * to eventually restore it to the userspace a1.
26448 + movei d9, #(~(ASM_THREAD_SIZE-1))
26452 + * Are any interesting bits set on TI flags, if there are jump
26453 + * aside to post_processing.
26455 + move.4 d9, #(_TIF_SYSCALL_TRACE | _TIF_NEED_RESCHED | _TIF_SIGPENDING)
26456 + and.4 #0, TI_FLAGS(a1), d9
26457 + jmpne.f .Lsyscall_exit__post_processing ; jump to handler
26458 +.Lsyscall_exit__post_processing_complete:
26460 + move.4 d0, PT_D0(sp) ; Restore D0 from kernel stack
26461 + move.4 d1, PT_D1(sp) ; Restore d1 from kernel stack
26462 + move.4 d2, PT_D2(sp) ; Restore d2 from kernel stack
26463 + move.4 d3, PT_D3(sp) ; Restore d3 from kernel stack
26464 + move.4 d4, PT_D4(sp) ; Restore d4 from kernel stack
26465 + move.4 d5, PT_D5(sp) ; Restore d5 from kernel stack
26466 + move.4 d8, PT_D8(sp) ; Restore d8 from kernel stack
26467 + move.4 d10, PT_D10(sp) ; Restore d10 from kernel stack
26468 + move.4 d11, PT_D11(sp) ; Restore d11 from kernel stack
26469 + move.4 d12, PT_D12(sp) ; Restore d12 from kernel stack
26470 + move.4 d13, PT_D13(sp) ; Restore d13 from kernel stack
26471 + move.4 a1, PT_A1(sp) ; Restore A1 from kernel stack
26472 + move.4 a2, PT_A2(sp) ; Restore A2 from kernel stack
26473 + move.4 a5, PT_A5(sp) ; Restore A5 from kernel stack
26474 + move.4 a6, PT_A6(sp) ; Restore A6 from kernel stack
26475 + move.4 a0, PT_A0(sp) ; Restore A6 from kernel stack
26478 + * this is only for debug, and could be removed for production builds
26480 + move.4 PT_FRAME_TYPE(sp), #0 ; invalidate frame_type
26482 +#ifdef CONFIG_PROTECT_KERNEL
26484 + call a4, __syscall_exit_bottom_half
26486 + .section .kernel_unprotected, "ax", @progbits
26487 +__syscall_exit_bottom_half:
26489 + * Enter critical section
26491 + atomic_lock_acquire
26492 + disable_kernel_ranges_for_current d15
26495 + * Lastly restore userspace stack ptr
26497 + * Note: that when protection is on we need to hold the lock around the
26498 + * stack swap as well because otherwise the protection could get
26499 + * inadvertently disabled again at the end of a context switch.
26501 + move.4 a7, PT_A7(sp) ; Restore A7 from kernel stack
26504 + * We are now officially back in userspace!
26507 +#ifdef CONFIG_PROTECT_KERNEL
26509 + * Leave critical section and return to user space.
26511 + atomic_lock_release
26513 + calli a5, 0(a5) ; Back to userspace code.
26515 + bkpt #-1 ; we will never get here
26518 + * Post syscall processing. (unlikely part of syscall_exit)
26520 + * Are we tracing syscalls. If TIF_SYSCALL_TRACE is set, call
26521 + * syscall_trace routine and return here.
26523 + .section .text.syscall_exit, "ax", @progbits
26524 +.Lsyscall_exit__post_processing:
26525 + btst TI_FLAGS(a1), #ASM_TIF_SYSCALL_TRACE
26527 + call a5, syscall_trace
26530 + * Do we need to resched ie call schedule. If TIF_NEED_RESCHED is set,
26531 + * call the scheduler, it will come back here.
26533 +1: btst TI_FLAGS(a1), #ASM_TIF_NEED_RESCHED
26535 + call a5, schedule
26538 + * Do we need to post a signal, if TIF_SIGPENDING is set call the
26541 +2: btst TI_FLAGS(a1), #ASM_TIF_SIGPENDING
26542 + jmpeq.t .Lsyscall_exit__post_processing_complete
26545 + * setup the do signal call
26547 + move.4 d0, #0 ; oldset pointer is NULL
26548 + lea.1 d1, (sp) ; d1 is the regs pointer.
26549 + call a5, do_signal
26551 + jmpt.t .Lsyscall_exit__post_processing_complete
26553 +/* .size syscall_exit, . - syscall_exit */
26556 + * kernel_execve()
26557 + * kernel_execv is called when we the kernel is starting a
26558 + * userspace application.
26560 + .section .kernel_unprotected, "ax", @progbits
26561 + .global kernel_execve
26563 + move.4 -4(sp)++, a5 ; Save return address
26567 + movei d8, #__NR_execve ; call execve
26568 + call a5, system_call
26569 + move.4 a5, (sp)4++
26572 + * protection was enabled again at syscall exit, but we want
26573 + * to return to kernel so we enable it again.
26575 +#ifdef CONFIG_PROTECT_KERNEL
26577 + * We are entering the kernel so we need to disable the protection.
26578 + * Enter critical section, disable ranges and leave critical section.
26580 + call a3, __enable_kernel_ranges ; and jump back to kernel
26582 + ret a5 ; jump back to the kernel
26585 + .size kernel_execve, . - kernel_execve
26588 + * signal_trampoline()
26590 + * Deals with transitioning from to userspace signal handlers and returning
26591 + * to userspace, only called from the kernel.
26594 + .section .kernel_unprotected, "ax", @progbits
26595 + .global signal_trampoline
26596 +signal_trampoline:
26598 + * signal_trampoline is called when we are jumping from the kernel to
26599 + * the userspace signal handler.
26601 + * The following registers are relevant. (set setup_rt_frame)
26602 + * sp is the user space stack not the kernel stack
26603 + * d0 = signal number
26604 + * d1 = siginfo_t *
26605 + * d2 = ucontext *
26606 + * d3 = the user space signal handler
26607 + * a0 is set to the GOT if userspace application is FDPIC, otherwise 0
26608 + * a3 is set to the FD for the signal if userspace application is FDPIC
26610 +#ifdef CONFIG_PROTECT_KERNEL
26612 + * We are leaving the kernel so we need to enable the protection.
26613 + * Enter critical section, disable ranges and leave critical section.
26615 + atomic_lock_acquire ; Enter critical section
26616 + disable_kernel_ranges_for_current d15 ; disable kernel ranges
26617 + atomic_lock_release ; Leave critical section
26620 + * The signal handler pointer is in register d3 so tranfer it to a4 and
26623 + movea a4, d3 ; signal handler
26627 + * Return to userspace through rt_syscall which is stored on top of the
26628 + * stack d1 contains ret_via_interrupt status.
26630 + move.4 d8, (sp) ; d8 (syscall #) = rt_syscall
26631 + move.4 d1, 4(sp) ; d1 = ret_via_interrupt
26632 + call a5, system_call ; as we are 'in' the kernel
26633 + ; we can call kernel_syscall
26635 + bkpt #-1 ; will never get here.
26636 + .size signal_trampoline, . - signal_trampoline
26639 + * kernel_thread_helper()
26641 + * Entry point for kernel threads (only referenced by kernel_thread()).
26643 + * On execution d0 will be 0, d1 will be the argument to be passed to the
26644 + * kernel function.
26645 + * d2 contains the kernel function that needs to get called.
26646 + * d3 will contain address to do_exit which needs to get moved into a5.
26648 + * On return from fork the child thread d0 will be 0. We call this dummy
26649 + * function which in turn loads the argument
26651 + .section .kernel_unprotected, "ax", @progbits
26652 + .global kernel_thread_helper
26653 +kernel_thread_helper:
26655 + * Create a kernel thread. This is called from ret_from_vfork (a
26656 + * userspace return routine) so we need to put it in an unprotected
26657 + * section and re-enable protection before calling the vector in d2.
26660 +#ifdef CONFIG_PROTECT_KERNEL
26662 + * We are entering the kernel so we need to disable the protection.
26663 + * Enter critical section, disable ranges and leave critical section.
26665 + call a5, __enable_kernel_ranges
26668 + * Move argument for kernel function into d0, and set a5 return address
26669 + * (a5) to do_exit and return through a2
26671 + move.4 d0, d1 ; d0 = arg
26672 + move.4 a5, d3 ; a5 = do_exit
26673 + ret d2 ; call function ptr in d2
26674 + .size kernel_thread_helper, . - kernel_thread_helper
26676 +#ifdef CONFIG_PROTECT_KERNEL
26677 + .section .kernel_unprotected, "ax", @progbits
26678 +__enable_kernel_ranges:
26679 + atomic_lock_acquire ; Enter critical section
26680 + enable_kernel_ranges_for_current d15
26681 + atomic_lock_release ; Leave critical section
26683 + .size __enable_kernel_ranges, . - __enable_kernel_ranges
26688 + * The following system call intercept functions where we setup the
26689 + * input to the real system call. In all cases these are just taking
26690 + * the current sp which is pointing to pt_regs and pushing it into the
26691 + * last arg of the system call.
26693 + * i.e. the public definition of sys_execv is
26694 + * sys_execve( char *name,
26697 + * but process.c defines it as
26698 + * sys_execve( char *name,
26701 + * struct pt_regs *regs )
26703 + * so execve_intercept needs to populate the 4th arg with pt_regs*,
26704 + * which is the stack pointer as we know we must be coming out of
26707 + * The intercept vectors are referenced by syscalltable.S
26711 + * execve_intercept()
26713 + .section .text.execve_intercept, "ax", @progbits
26714 + .global execve_intercept
26716 + move.4 d3, sp ; Save pt_regs address
26717 + call a3, sys_execve
26719 + .size execve_intercept, . - execve_intercept
26722 + * vfork_intercept()
26724 + .section .text.vfork_intercept, "ax", @progbits
26725 + .global vfork_intercept
26727 + move.4 d0, sp ; Save pt_regs address
26728 + call a3, sys_vfork
26730 + .size vfork_intercept, . - vfork_intercept
26733 + * clone_intercept()
26735 + .section .text.clone_intercept, "ax", @progbits
26736 + .global clone_intercept
26738 + move.4 d2, sp ; Save pt_regs address
26739 + call a3, sys_clone
26741 + .size clone_intercept, . - clone_intercept
26744 + * sys_sigsuspend()
26746 + .section .text.sigclone_intercept, "ax", @progbits
26747 + .global sys_sigsuspend
26749 + move.4 d0, sp ; Pass pointer to pt_regs in d0
26750 + call a3, do_sigsuspend
26752 + .size sys_sigsuspend, . - sys_sigsuspend
26755 + * sys_rt_sigsuspend()
26757 + .section .text.sys_rt_sigsuspend, "ax", @progbits
26758 + .global sys_rt_sigsuspend
26759 +sys_rt_sigsuspend:
26760 + move.4 d0, sp ; Pass pointer to pt_regs in d0
26761 + call a3, do_rt_sigsuspend
26763 + .size sys_rt_sigsuspend, . - sys_rt_sigsuspend
26766 + * sys_rt_sigreturn()
26768 + .section .text.sys_rt_sigreturn, "ax", @progbits
26769 + .global sys_rt_sigreturn
26771 + move.4 d0, sp ; Pass pointer to pt_regs in d0
26772 + call a3, do_rt_sigreturn
26774 + .size sys_rt_sigreturn, . - sys_rt_sigreturn
26777 + * sys_sigaltstack()
26779 + .section .text.sys_sigaltstack, "ax", @progbits
26780 + .global sys_sigaltstack
26782 + move.4 d0, sp ; Pass pointer to pt_regs in d0
26783 + call a3, do_sys_sigaltstack
26785 + .size sys_sigaltstack, . - sys_sigaltstack
26787 +++ b/arch/ubicom32/kernel/unaligned_trap.c
26790 + * arch/ubicom32/kernel/unaligned_trap.c
26791 + * Handle unaligned traps in both user or kernel space.
26793 + * (C) Copyright 2009, Ubicom, Inc.
26795 + * This file is part of the Ubicom32 Linux Kernel Port.
26797 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
26798 + * it and/or modify it under the terms of the GNU General Public License
26799 + * as published by the Free Software Foundation, either version 2 of the
26800 + * License, or (at your option) any later version.
26802 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
26803 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
26804 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
26805 + * the GNU General Public License for more details.
26807 + * You should have received a copy of the GNU General Public License
26808 + * along with the Ubicom32 Linux Kernel Port. If not,
26809 + * see <http://www.gnu.org/licenses/>.
26811 + * Ubicom32 implementation derived from (with many thanks):
26817 +#include <linux/types.h>
26818 +#include <linux/kernel.h>
26819 +#include <asm/cacheflush.h>
26820 +#include <asm/traps.h>
26825 +/* no possible trap */
26827 +/* possible source operand trap */
26830 +/* possible destination operand trap */
26833 +/* can be either source or destination or both */
26835 +#define TWO_OP_2 6
26837 +/* TODO: What is the real value here, put something in to make it compile for
26839 +#define MOVE_2 0x0d
26840 +#define LSL_2 0x11
26841 +#define LSR_2 0x13
26842 +#define MOVEI 0x19
26845 +static int op_format[32] =
26847 + TWO_OP, /* 0x00 */
26851 + TWO_OP, /* 0x04 */
26855 + TWO_OP_2, /* 0x08 */
26859 + TWO_OP_2, /* 0x0C */
26863 + TWO_OP, /* 0x10 */
26867 + UNUSED, /* 0x14 */
26871 + SRC_2, /* 0x18 */
26875 + UNUSED, /* 0x1C */
26877 + UNUSED, /* unaligned CALLI will not be fixed. */
26881 +static int op_0_format[32] =
26883 + UNUSED, /* 0x00 */
26887 + UNUSED, /* 0x04 - ret don't fix - bad ret is always wrong */
26891 + UNUSED, /* 0x08 */
26895 + TWO_OP, /* 0x0c */
26898 + UNUSED, /* .1 can't trap */
26899 + UNUSED, /* 0x10 */
26903 + UNUSED, /* 0x14 */
26907 + UNUSED, /* 0x18 */
26914 + DEST, /* all lea have 32-bit destination */
26917 +static int op_2_format[32] =
26919 + UNUSED, /* 0x00 */
26923 + UNUSED, /* 0x04 */
26927 + UNUSED, /* 0x08 crcgen is .1 */
26931 + UNUSED, /* 0x0c */
26943 + UNUSED, /* 0x18 */
26953 +static int op_6_format[32] =
26955 + SRC_2, /* 0x00 */
26959 + SRC_2, /* 0x04 */
26963 + SRC, /* 0x08 MULS.4 */
26967 + UNUSED, /* 0x0c */
26975 + UNUSED, /* 0x14 */
26979 + UNUSED, /* 0x18 */
26983 + UNUSED, /* 0x1c */
26990 + * unaligned_get_address()
26991 + * get an address using save_an and save_dn registers, and updates save_an
26992 + * with side effects
26994 +unsigned char *unaligned_get_address(int thread, int specifier, int four_byte,
26995 + unsigned int save_an[],
26996 + unsigned int save_dn[], int *write_back_an)
26998 + unsigned char *address;
27000 + int areg = (specifier >> 5) & 7;
27001 + if ((specifier >> 8) == 2) {
27002 + int offset = specifier & 0xf;
27003 + offset = ((offset << 28) >> 28);
27004 + if (likely(four_byte)) {
27009 + if (specifier & 0x10) {
27010 + address = (unsigned char *)(save_an[areg] + offset);
27012 + address = (unsigned char *)save_an[areg];
27014 + save_an[areg] = save_an[areg] + offset;
27017 + * Let caller know An registers have been modified.
27019 + *write_back_an = 1;
27020 + } else if ((specifier >> 8) == 3) {
27021 + int dreg = specifier & 0xf;
27022 + if (likely(four_byte)) {
27023 + address = (unsigned char *)(save_an[areg] +
27024 + (save_dn[dreg] << 2));
27026 + address = (unsigned char *)(save_an[areg] +
27027 + (save_dn[dreg] << 1));
27030 + int offset = ((specifier >> 3) & 0x60) | (specifier & 0x1f);
27031 + if (likely(four_byte)) {
27032 + address = (unsigned char *)(save_an[areg] +
27035 + address = (unsigned char *)(save_an[areg] +
27043 +static int save_dn[16];
27044 +static int save_an[8];
27045 +static int save_acc[5];
27048 + * unaligned_emulate()
27049 + * emulate the instruction at thread's pc that has taken an unaligned data
27052 + * source or destination or both might be unaligned
27053 + * the instruction must have a memory source or destination or both
27054 + * the emulated instruction is copied and executed in this thread
27056 + * TODO: Protection is handled outside of this function
27057 + * TODO: handling simultaneous unaligned and memory protection traps
27059 + * Get thread state
27060 + * the PC and instruction (and local copy, emulate_inst), and An
27061 + * and Dn registers
27062 + * All implicit soruce state (source3, CSR, accumulators)
27064 + * if the instruction has a memory source
27065 + * Use the instruction, An and Dn registers to form src_address
27066 + * get unaligned source data from src_address (usually sign
27068 + * (2 bytes, with or without sign extension, or 4 bytes)
27069 + * modify emulate_inst to use d0 as source
27071 + * get the soure operand from one of thread's registers
27072 + * if instruction has a memory destination
27073 + * Use the instruction, An and Dn registers to form dest_address
27074 + * modify emulate_inst to use d0 as destination
27075 + * if there was a memory source
27076 + * put the source data in thread's d0
27077 + * get the source-2 Dn operand and source 3 operand from thread
27078 + * execute modified inst
27079 + * (save it, flush caches, set up local values for implicit
27080 + * sources, execute, save explicit and implicit results)
27081 + * if inst has destination address
27082 + * copy result to dest_address, possibly unaligned, 1, 2, or 4
27084 + * restore thread's implicit results (modified address registers, CSR,
27085 + * accumulators) add 4 to thread's pc
27087 +void unaligned_emulate(unsigned int thread)
27090 + unsigned int inst;
27092 + unsigned int subop;
27094 + unsigned int emulate_inst;
27096 + int src_operand, dest_operand;
27099 + unsigned int source1;
27100 + unsigned int source_data;
27101 + unsigned char *dest_address = NULL;
27103 + unsigned int result;
27104 + unsigned int write_back_an = 0;
27105 + unsigned int chip_id_copy;
27107 + extern unsigned int trap_emulate;
27108 + extern unsigned int ubicom32_emulate_insn(int source1, int source2,
27109 + int source3, int *save_acc,
27113 + * get the chip_id
27116 + " move.4 %0, chip_id \n\t" /* get chip_id. */
27117 + : "=r"(chip_id_copy)
27125 + " move.4 CSR, %1 \n\t" /* set source thread in
27127 + " setcsr_flush 0 \n\t"
27128 + " move.4 %0, pc \n\t"
27129 + " move.4 CSR, #0 \n\t" /* restore CSR */
27130 + " setcsr_flush 0 \n\t"
27132 + : "d" ((1 << 8) | (thread << 9))
27136 + inst = *((unsigned int *)pc);
27138 + if (unlikely(op == 2 || op == 6)) {
27139 + subop = (inst >> 21) & 0x1f;
27141 + subop = (inst >> 11) & 0x1f;
27143 + format = op_format[op];
27144 + emulate_inst = inst;
27147 + format = op_0_format[subop];
27148 + } else if (op == 2) {
27149 + format = op_2_format[subop];
27150 + } else if (op == 6) {
27151 + format = op_6_format[subop];
27154 + if (unlikely(format == UNUSED)) {
27156 + * We are not going to emulate this. Bump PC by 4 and move on.
27159 + " move.4 CSR, %0 \n\t"
27160 + " setcsr_flush 0 \n\t"
27161 + " move.4 pc, %1 \n\t"
27162 + " setcsr #0 \n\t"
27163 + " setcsr_flush 0 \n\t"
27165 + : "d"((1 << 14) | (thread << 15)), "d"(pc + 4)
27171 + four_byte = (format == TWO_OP || format == DEST || format == SRC);
27174 + * source or destination memory operand needs emulation
27176 + src_operand = (format == SRC ||
27177 + format == SRC_2 ||
27178 + format == TWO_OP ||
27179 + format == TWO_OP_2) &&
27180 + ((inst >> 8) & 7) > 1;
27182 + dest_operand = (format == DEST ||
27183 + format == DEST_2 ||
27184 + format == TWO_OP ||
27185 + format == TWO_OP_2) &&
27186 + ((inst >> 24) & 7) > 1;
27189 + * get thread's implicit sources (not covered by source context select).
27190 + * data and address registers and CSR (for flag bits) and src3 and
27194 + " move.4 CSR, %2 \n\t" /* set source thread in
27196 + " setcsr_flush 0 \n\t"
27197 + " move.4 (%3), d0 \n\t" /* get dn registers */
27198 + " move.4 4(%3), d1 \n\t"
27199 + " move.4 8(%3), d2 \n\t"
27200 + " move.4 12(%3), d3 \n\t"
27201 + " move.4 16(%3), d4 \n\t"
27202 + " move.4 20(%3), d5 \n\t"
27203 + " move.4 24(%3), d6 \n\t"
27204 + " move.4 28(%3), d7 \n\t"
27205 + " move.4 32(%3), d8 \n\t"
27206 + " move.4 36(%3), d9 \n\t"
27207 + " move.4 40(%3), d10 \n\t"
27208 + " move.4 44(%3), d11 \n\t"
27209 + " move.4 48(%3), d12 \n\t"
27210 + " move.4 52(%3), d13 \n\t"
27211 + " move.4 56(%3), d14 \n\t"
27212 + " move.4 60(%3), d15 \n\t"
27213 + " move.4 (%4), a0 \n\t" /* get an registers */
27214 + " move.4 4(%4), a1 \n\t"
27215 + " move.4 8(%4), a2 \n\t"
27216 + " move.4 12(%4), a3 \n\t"
27217 + " move.4 16(%4), a4 \n\t"
27218 + " move.4 20(%4), a5 \n\t"
27219 + " move.4 24(%4), a6 \n\t"
27220 + " move.4 28(%4), a7 \n\t"
27221 + " move.4 %0, CSR \n\t" /* get csr and source3
27222 + * implicit operands */
27223 + " move.4 %1, source3 \n\t"
27224 + " move.4 (%5), acc0_lo \n\t" /* get accumulators */
27225 + " move.4 4(%5), acc0_hi \n\t"
27226 + " move.4 8(%5), acc1_lo \n\t"
27227 + " move.4 12(%5), acc1_hi \n\t"
27228 + " move.4 16(%5), mac_rc16 \n\t"
27229 + " move.4 CSR, #0 \n\t" /* restore CSR */
27230 + " setcsr_flush 0 \n\t"
27231 + : "=m"(save_csr), "=m"(source3)
27232 + : "d"((1 << 8) | (thread << 9)),
27233 + "a"(save_dn), "a"(save_an), "a"(save_acc)
27238 + * turn off thread select bits if they were on
27240 + BUG_ON((save_csr & 0x04100) != 0);
27241 + if (unlikely(save_csr & 0x04100)) {
27243 + * Things are in funny state as thread select bits are on in
27246 + panic("In unaligned trap handler. Trap thread CSR has thread "
27247 + "select bits on.\n");
27250 + save_csr = save_csr & 0x1000ff;
27253 + * get the source1 operand
27256 + if (src_operand) {
27257 + unsigned char *src_address;
27260 + * source1 comes from memory
27262 + BUG_ON(!(format == TWO_OP || format == TWO_OP_2 ||
27263 + format == SRC || format == SRC_2));
27264 + src_address = unaligned_get_address(thread, inst & 0x7ff,
27265 + four_byte, save_an,
27266 + save_dn, &write_back_an);
27269 + * get data (possibly unaligned)
27271 + if (likely(four_byte)) {
27272 + source_data = (*src_address << 24) |
27273 + (*(src_address + 1) << 16) |
27274 + (*(src_address + 2) << 8) |
27275 + *(src_address + 3);
27276 + source1 = source_data;
27278 + source1 = *src_address << 8 |
27279 + *(src_address + 1);
27282 + * Source is not extended if the instrution is MOVE.2 or
27283 + * if the cpu CHIP_ID >= 0x30000 and the instruction is
27284 + * either LSL.2 or LSR.2. All other cases have to be
27287 + if ((!(op == 2 && subop == MOVE_2)) &&
27288 + (!((chip_id_copy >= 0x30000) &&
27289 + (subop == LSL_2 || subop == LSR_2)))) {
27291 + * Have to sign extend the .2 entry.
27293 + source1 = ((unsigned int)
27295 + ((signed short) source1)));
27298 + } else if (likely(op != MOVEI)) {
27300 + * source1 comes from a register, using move.4 d0, src1
27301 + * unaligned_emulate_get_source is pointer to code to insert remulated instruction
27303 + extern unsigned int unaligned_emulate_get_src;
27304 + *((int *)&unaligned_emulate_get_src) &= ~(0x7ff);
27305 + *((int *)&unaligned_emulate_get_src) |= (inst & 0x7ff);
27306 + flush_dcache_range((unsigned long)(&unaligned_emulate_get_src),
27307 + (unsigned long)(&unaligned_emulate_get_src) + 4);
27310 + /* source1 uses thread's registers */
27311 + " move.4 CSR, %1 \n\t"
27312 + " setcsr_flush 0 \n\t"
27313 + "unaligned_emulate_get_src: \n\t"
27314 + " move.4 %0, #0 \n\t"
27315 + " setcsr #0 \n\t"
27316 + " setcsr_flush 0 \n\t"
27318 + : "d" ((1 << 8) | (thread << 9))
27324 + * get the destination address
27326 + if (dest_operand) {
27327 + BUG_ON(!(format == TWO_OP || format == TWO_OP_2 ||
27328 + format == DEST || format == DEST_2));
27329 + dest_address = unaligned_get_address(thread,
27330 + ((inst >> 16) & 0x7ff),
27331 + four_byte, save_an,
27332 + save_dn, &write_back_an);
27335 + if (write_back_an) {
27337 + * restore any modified An registers
27340 + " move.4 CSR, %0 \n\t"
27341 + " setcsr_flush 0 \n\t"
27342 + " move.4 a0, (%1) \n\t"
27343 + " move.4 a1, 4(%1) \n\t"
27344 + " move.4 a2, 8(%1) \n\t"
27345 + " move.4 a3, 12(%1) \n\t"
27346 + " move.4 a4, 16(%1) \n\t"
27347 + " move.4 a5, 20(%1) \n\t"
27348 + " move.4 a6, 24(%1) \n\t"
27349 + " move.4 a7, 28(%1) \n\t"
27350 + " setcsr #0 \n\t"
27351 + " setcsr_flush 0 \n\t"
27353 + : "d" ((1 << 14) | (thread << 15)), "a" (save_an)
27359 + * get source 2 register if needed, and modify inst to use d1 for
27360 + * source-2 source-2 will come from this thread, not the trapping thread
27363 + if ((op >= 8 && op <= 0x17) ||
27364 + ((op == 2 || op == 6) && (inst & 0x4000000))) {
27365 + int src_dn = (inst >> 11) & 0xf;
27366 + source2 = save_dn[src_dn];
27368 + * force the emulated instruction to use d1 for source2 operand
27370 + emulate_inst = (emulate_inst & 0xffff07ff) | 0x800;
27373 + if (likely(op != MOVEI)) {
27375 + * change emulated instruction source1 to d0
27377 + emulate_inst &= ~0x7ff;
27378 + emulate_inst |= 1 << 8;
27381 + if (unlikely(op == 6 || op == 2)) {
27383 + * Set destination to d0
27385 + emulate_inst &= ~(0xf << 16);
27386 + } else if (likely(op != CMPI)) {
27388 + * Set general destination field to d0.
27390 + emulate_inst &= ~(0x7ff << 16);
27391 + emulate_inst |= 1 << 24;
27395 + * execute emulated instruction d0, to d0, no memory access
27396 + * source2 if needed will be in d1
27397 + * source3, CSR, and accumulators are set up before execution
27399 + *((unsigned int *)&trap_emulate) = emulate_inst;
27400 + flush_dcache_range((unsigned long)(&trap_emulate),
27401 + (unsigned long)(&trap_emulate) + 4);
27403 + result = ubicom32_emulate_insn(source1, source2, source3,
27404 + save_acc, &save_csr);
27407 + * set the result value
27409 + if (dest_operand) {
27411 + * copy result to memory
27414 + *dest_address++ =
27415 + (unsigned char)((result >> 24) & 0xff);
27416 + *dest_address++ =
27417 + (unsigned char)((result >> 16) & 0xff);
27419 + *dest_address++ = (unsigned char)((result >> 8) & 0xff);
27420 + *dest_address = (unsigned char)(result & 0xff);
27421 + } else if (likely(op != CMPI)) {
27423 + * copy result to a register, using move.4 dest, result
27425 + extern unsigned int unaligned_trap_set_result;
27426 + *((unsigned int *)&unaligned_trap_set_result) &= ~0x7ff0000;
27428 + if (op == 2 || op == 6) {
27429 + *((unsigned int *)&unaligned_trap_set_result) |=
27430 + ((inst & 0x000f0000) | 0x01000000);
27432 + *((unsigned int *)&unaligned_trap_set_result) |=
27433 + (inst & 0x7ff0000);
27435 + flush_dcache_range((unsigned long)&unaligned_trap_set_result,
27436 + ((unsigned long)(&unaligned_trap_set_result) + 4));
27439 + /* result uses thread's registers */
27440 + " move.4 CSR, %1 \n\t"
27441 + " setcsr_flush 0 \n\t"
27442 + "unaligned_trap_set_result: \n\t"
27443 + " move.4 #0, %0 \n\t"
27444 + " setcsr #0 \n\t"
27445 + " setcsr_flush 0 \n\t"
27447 + : "d"(result), "d" ((1 << 14) | (thread << 15))
27453 + * bump PC in thread and restore implicit register changes
27456 + " move.4 CSR, %0 \n\t"
27457 + " setcsr_flush 0 \n\t"
27458 + " move.4 pc, %1 \n\t"
27459 + " move.4 acc0_lo, (%3) \n\t"
27460 + " move.4 acc0_hi, 4(%3) \n\t"
27461 + " move.4 acc1_lo, 8(%3) \n\t"
27462 + " move.4 acc1_hi, 12(%3) \n\t"
27463 + " move.4 mac_rc16, 16(%3) \n\t"
27464 + " move.4 CSR, %2 \n\t"
27465 + " setcsr #0 \n\t"
27466 + " setcsr_flush 0 \n\t"
27468 + : "d"((1 << 14) | (thread << 15)),
27469 + "d"(pc + 4), "d"(save_csr), "a"(save_acc)
27475 + * unaligned_only()
27476 + * Return true if either of the unaligned causes are set (and no others).
27478 +int unaligned_only(unsigned int cause)
27480 + unsigned int unaligned_cause_mask =
27481 + (1 << TRAP_CAUSE_DST_MISALIGNED) |
27482 + (1 << TRAP_CAUSE_SRC1_MISALIGNED);
27484 + BUG_ON(cause == 0);
27485 + return (cause & unaligned_cause_mask) == cause;
27488 +++ b/arch/ubicom32/kernel/vmlinux.lds.S
27491 + * arch/ubicom32/kernel/vmlinux.lds.S
27492 + * vmlinux primary linker script
27494 + * (C) Copyright 2009, Ubicom, Inc.
27496 + * This file is part of the Ubicom32 Linux Kernel Port.
27498 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
27499 + * it and/or modify it under the terms of the GNU General Public License
27500 + * as published by the Free Software Foundation, either version 2 of the
27501 + * License, or (at your option) any later version.
27503 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
27504 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
27505 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
27506 + * the GNU General Public License for more details.
27508 + * You should have received a copy of the GNU General Public License
27509 + * along with the Ubicom32 Linux Kernel Port. If not,
27510 + * see <http://www.gnu.org/licenses/>.
27512 + * Ubicom32 implementation derived from (with many thanks):
27517 +#include <asm-generic/vmlinux.lds.h>
27518 +#include <asm/ocm_size.h>
27519 +#include <asm/memory_map.h>
27520 +#include <asm/thread_info.h>
27521 +#include <linux/threads.h>
27524 + * Sanity checks to prevent errors later on that are much harder to understand
27526 +#if !defined APP_OCM_CODE_SIZE
27527 +#error APP_OCM_CODE_SIZE has not been defined in ocm_size.h
27530 +#if !defined APP_OCM_DATA_SIZE
27531 +#error APP_OCM_DATA_SIZE has not been defined in ocm_size.h
27535 + * The `free' ocm area that ultra does not use.
27537 +#if APP_OCM_CODE_SIZE || APP_OCM_DATA_SIZE
27538 +#define OCM_FREE_START (OCMSTART + APP_OCM_CODE_SIZE)
27539 +#define OCM_FREE_LENGTH (OCMSIZE - APP_OCM_CODE_SIZE - APP_OCM_DATA_SIZE)
27541 +#define OCM_FREE_START OCMEND
27542 +#define OCM_FREE_LENGTH 0
27546 + * If you want to limit OCM use for text/data or completely disable it
27547 + * you can change these values.
27549 +#define OCM_TEXT_LENGTH OCM_FREE_LENGTH
27550 +#define OCM_DATA_LENGTH OCM_FREE_LENGTH
27552 +#define RAM_START KERNELSTART
27553 +#define RAM_LENGTH ((SDRAMSTART + CONFIG_MIN_RAMSIZE) - RAM_START)
27563 +#include <asm-generic/vmlinux.lds.h>
27565 +OUTPUT_ARCH(ubicom32)
27569 + ram : ORIGIN = RAM_START, LENGTH = RAM_LENGTH
27570 + syscall : ORIGIN = OS_SYSCALL_BEGIN, LENGTH = (OS_SYSCALL_END - OS_SYSCALL_BEGIN)
27571 + ocm : ORIGIN = OCM_FREE_START, LENGTH = OCM_FREE_LENGTH
27574 +jiffies = jiffies_64 + 4;
27577 + * Fixed locations required by gdb coredumps.
27579 + * Note that the names are what gdb is expecting so renaming will break
27582 +__ocm_begin = OCMSTART;
27583 +__ocm_limit = __ocm_begin + OCMSIZE;
27584 +__sdram_begin = SDRAMSTART;
27585 +__sdram_limit = __sdram_begin + CONFIG_MIN_RAMSIZE;
27586 +__filemedia_begin_addr = FLASHSTART;
27587 +__filemedia_end_addr = __filemedia_begin_addr + 0x00800000;
27590 + * For internal diagnostics
27592 +__os_syscall_begin = OS_SYSCALL_BEGIN;
27593 +__os_syscall_end = OS_SYSCALL_END;
27600 + *(.old_syscall_entry.text)
27601 + __fixed_text_end = .;
27603 + . = _begin + SIZEOF(.fixed_text) ;
27606 + * System call text in lower ocm (fixed location, can never change)
27608 + __syscall_text_load_begin = .;
27609 + __syscall_text_run_begin = OS_SYSCALL_BEGIN;
27611 + .syscall_text __syscall_text_run_begin : AT(__syscall_text_load_begin) {
27612 + *(.syscall_entry.text) /* Must be at OS_SYSCALL_BEGIN 0x3ffc0040 */
27613 + *(.kernel_unprotected)
27615 + __syscall_text_run_end = .;
27616 + } > syscall /* .syscall_text */
27617 + . = __syscall_text_load_begin + __syscall_text_run_end - __syscall_text_run_begin ;
27618 + __ocm_text_load_begin = .;
27619 + __ocm_text_run_begin = OCM_FREE_START ;
27620 + .ocm_text __ocm_text_run_begin : AT(__ocm_text_load_begin) {
27621 +#if OCM_TEXT_LENGTH
27624 + *(.spinlock.text)
27625 +#include <asm/ocm_text.lds.inc>
27628 + __ocm_text_run_end = .;
27629 + __data_begin = ALIGN(OCM_SECTOR_SIZE);
27630 + } > ocm /* .ocm_text */
27632 + .ocm_module_text __ocm_text_run_end (NOLOAD) : AT(__ocm_text_run_end) {
27633 + __ocm_inst_heap_begin = .;
27634 + /* Reserve the min requested */
27635 + . += (CONFIG_OCM_MODULES_RESERVATION) * 1024;
27636 +#ifdef CONFIG_OCM_MODULES_MAY_CONSUME_REMAINING_CODESPACE
27637 + /* Round up to OCM sector size (we cannot use it for data) */
27638 + . = ALIGN(OCM_SECTOR_SIZE);
27640 + __ocm_inst_heap_end = .;
27641 + /* update __data_begin */
27642 + __data_begin = ALIGN(OCM_SECTOR_SIZE);
27643 + } > ocm /* .ocm_module_text */
27645 + . = __ocm_text_load_begin + __ocm_text_run_end - __ocm_text_run_begin ;
27646 + __ocm_text_load_end = .;
27648 + __ocm_data_load_begin = .;
27649 + __ocm_data_run_begin = __data_begin ;
27650 +#if OCM_DATA_LENGTH
27651 + .ocm_data __ocm_data_run_begin : AT(__ocm_data_load_begin) {
27652 +#if defined(CONFIG_IRQSTACKS_USEOCM)
27653 + percpu_irq_stacks = .;
27654 + . += NR_CPUS * THREAD_SIZE;
27658 + __ocm_data_run_end = .;
27660 + . = __ocm_data_load_begin + __ocm_data_run_end - __ocm_data_run_begin ;
27662 + __ocm_data_run_end = __ocm_data_run_begin;
27664 + __ocm_data_load_end = .;
27666 + __ocm_free_begin = __ocm_data_run_end;
27667 + __ocm_free_end = OCM_FREE_START + OCM_FREE_LENGTH;
27669 + .text __ocm_data_load_end : AT(__ocm_data_load_end) {
27677 + *(.text.__libgcc_udivmodsi)
27678 + *(.text.__libgcc_divmodsi)
27679 + *(.text.__libgcc_muldi3)
27680 + *(.text.__libgcc_udivmoddi)
27681 + *(.text.__libgcc_divmoddi)
27683 +#if OCM_TEXT_LENGTH == 0
27686 + *(.spinlock.text)
27688 + . = ALIGN(16); /* Exception table */
27689 + __start___ex_table = .;
27691 + __stop___ex_table = .;
27693 + *(.rodata) *(.rodata.*)
27694 + *(__vermagic) /* Kernel version magic */
27695 + *(__markers_strings)
27697 + *(.rodata.str1.1)
27698 + *(__tracepoints_strings)
27701 + __start_pci_fixups_early = . ;
27702 + *(.pci_fixup_early)
27703 + __end_pci_fixups_early = . ;
27704 + __start_pci_fixups_header = . ;
27705 + *(.pci_fixup_header)
27706 + __end_pci_fixups_header = . ;
27707 + __start_pci_fixups_final = . ;
27708 + *(.pci_fixup_final)
27709 + __end_pci_fixups_final = . ;
27710 + __start_pci_fixups_enable = . ;
27711 + *(.pci_fixup_enable)
27712 + __end_pci_fixups_enable = . ;
27713 + __start_pci_fixups_resume = . ;
27714 + *(.pci_fixup_resume)
27715 + __end_pci_fixups_resume = . ;
27716 + __start_pci_fixups_resume_early = . ;
27717 + *(.pci_fixup_resume_early)
27718 + __end_pci_fixups_resume_early = . ;
27719 + __start_pci_fixups_suspend = . ;
27720 + *(.pci_fixup_suspend)
27721 + __end_pci_fixups_suspend = . ;
27723 + __start_builtin_fw = . ;
27725 + __end_builtin_fw = . ;
27728 + /* Kernel symbol table: Normal symbols */
27730 + __start___ksymtab = .;
27732 + __stop___ksymtab = .;
27734 + /* Kernel symbol table: GPL-only symbols */
27735 + __start___ksymtab_gpl = .;
27737 + __stop___ksymtab_gpl = .;
27739 + /* Kernel symbol table: Normal unused symbols */
27740 + __start___ksymtab_unused = .;
27741 + *(__ksymtab_unused)
27742 + __stop___ksymtab_unused = .;
27744 + /* Kernel symbol table: GPL-only unused symbols */
27745 + __start___ksymtab_unused_gpl = .;
27746 + *(__ksymtab_unused_gpl)
27747 + __stop___ksymtab_unused_gpl = .;
27749 + /* Kernel symbol table: GPL-future symbols */
27750 + __start___ksymtab_gpl_future = .;
27751 + *(__ksymtab_gpl_future)
27752 + __stop___ksymtab_gpl_future = .;
27754 + /* Kernel symbol table: Normal symbols */
27755 + __start___kcrctab = .;
27757 + __stop___kcrctab = .;
27759 + /* Kernel symbol table: GPL-only symbols */
27760 + __start___kcrctab_gpl = .;
27762 + __stop___kcrctab_gpl = .;
27764 + /* Kernel symbol table: GPL-future symbols */
27765 + __start___kcrctab_gpl_future = .;
27766 + *(__kcrctab_gpl_future)
27767 + __stop___kcrctab_gpl_future = .;
27769 + /* Kernel symbol table: strings */
27770 + *(__ksymtab_strings)
27772 + /* Built-in module parameters */
27774 + __start___param = .;
27776 + __stop___param = .;
27782 + .data DATA_ADDR : {
27786 +#if OCM_DATA_LENGTH == 0
27789 + . = ALIGN(8192) ;
27790 + _data_protection_end = .;
27791 + *(.data.init_task)
27798 + __init_begin = .;
27805 + __setup_start = .;
27808 + __initcall_start = .;
27810 + __initcall_end = .;
27811 + __con_initcall_start = .;
27812 + *(.con_initcall.init)
27813 + __con_initcall_end = .;
27814 + ___security_initcall_start = .;
27815 + *(.security_initcall.init)
27816 + ___security_initcall_end = .;
27817 +#ifdef CONFIG_BLK_DEV_INITRD
27819 + __initramfs_start = .;
27821 + __initramfs_end = .;
27824 + __per_cpu_start = .;
27826 + *(.data.percpu.shared_aligned)
27827 + __per_cpu_end = .;
27835 + PROVIDE (___eh_frame_begin = .);
27838 + PROVIDE (___eh_frame_end = .);
27844 + *(.exitcall.exit)
27861 +++ b/arch/ubicom32/lib/checksum.c
27864 + * arch/ubicom32/lib/checksum.c
27865 + * Optimized checksum utilities for IP.
27867 + * (C) Copyright 2009, Ubicom, Inc.
27869 + * This file is part of the Ubicom32 Linux Kernel Port.
27871 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
27872 + * it and/or modify it under the terms of the GNU General Public License
27873 + * as published by the Free Software Foundation, either version 2 of the
27874 + * License, or (at your option) any later version.
27876 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
27877 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
27878 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
27879 + * the GNU General Public License for more details.
27881 + * You should have received a copy of the GNU General Public License
27882 + * along with the Ubicom32 Linux Kernel Port. If not,
27883 + * see <http://www.gnu.org/licenses/>.
27885 + * Ubicom32 implementation derived from (with many thanks):
27891 + * INET An implementation of the TCP/IP protocol suite for the LINUX
27892 + * operating system. INET is implemented using the BSD Socket
27893 + * interface as the means of communication with the user level.
27895 + * IP/TCP/UDP checksumming routines
27897 + * Authors: Jorge Cwik, <jorge@laser.satlink.net>
27898 + * Arnt Gulbrandsen, <agulbra@nvg.unit.no>
27899 + * Tom May, <ftom@netcom.com>
27900 + * Andreas Schwab, <schwab@issan.informatik.uni-dortmund.de>
27901 + * Lots of code moved from tcp.c and ip.c; see those files
27902 + * for more names.
27904 + * 03/02/96 Jes Sorensen, Andreas Schwab, Roman Hodek:
27905 + * Fixed some nasty bugs, causing some horrible crashes.
27906 + * A: At some points, the sum (%0) was used as
27907 + * length-counter instead of the length counter
27908 + * (%1). Thanks to Roman Hodek for pointing this out.
27909 + * B: GCC seems to mess up if one uses too many
27910 + * data-registers to hold input values and one tries to
27911 + * specify d0 and d1 as scratch registers. Letting gcc choose these
27912 + * registers itself solves the problem.
27914 + * This program is free software; you can redistribute it and/or
27915 + * modify it under the terms of the GNU General Public License
27916 + * as published by the Free Software Foundation; either version
27917 + * 2 of the License, or (at your option) any later version.
27920 +/* Revised by Kenneth Albanowski for m68knommu. Basic problem: unaligned access kills, so most
27921 + of the assembly has to go. */
27923 +#include <linux/module.h>
27924 +#include <net/checksum.h>
27926 +static unsigned long do_csum(const unsigned char * buff, int len)
27929 + unsigned long result = 0;
27932 + * The following optimized assembly code cannot handle data length less than 7 bytes!
27934 + if (likely(len >= 7)) {
27935 + len -= (4 - (int)buff) & 3;
27936 + count = len >> 2;
27938 + " sub.4 d15, #0, %2 \n\t" // set up for jump table
27939 + " and.4 d15, #(32-1), d15 \n\t" // d15 = (-m) & (32 - 1)
27941 + " bfextu d14, %0, #2 \n\t" // test 2 LSB of buff
27942 + " jmpne.w.f 100f \n\t"
27943 + " add.4 %1, #0, %1 \n\t" // clear C
27944 + " moveai a3, #%%hi(1f) \n\t" // table jump
27945 + " lea.1 a3, %%lo(1f)(a3) \n\t"
27946 + " lea.4 a3, (a3,d15) \n\t"
27947 + " calli a3, 0(a3) \n\t"
27949 + "100: sub.4 %0, %0, d14 \n\t"
27950 + " sub.4 d14, #4, d14 \n\t"
27951 + " lsl.4 d14, d14, #3 \n\t"
27952 + " add.4 %1, #0, %1 \n\t" // clear C
27953 + " moveai a3, #%%hi(1f) \n\t" // table jump
27954 + " lea.1 a3, %%lo(1f)(a3) \n\t"
27955 + " lea.4 a3, (a3,d15) \n\t"
27956 + " bfextu %1, (%0)4++, d14 \n\t" // read first partial word
27957 + " calli a3, 0(a3) \n\t"
27959 + "200: lsl.4 %3, %3, #3 \n\t"
27960 + " bfrvrs d15, (%0), #0 \n\t" // read last word (partial)
27961 + " bfextu d15, d15, %3 \n\t"
27962 + " bfrvrs d15, d15, #0 \n\t"
27963 + " add.4 %1, d15, %1 \n\t"
27964 + " addc %1, #0, %1 \n\t" // sample C again
27965 + " jmpt.w.t 2f \n\t"
27967 + "200: move.1 d15, 0(%0) \n\t"
27968 + " lsl.4 d15, d15, #8 \n\t"
27969 + " add.4 %1, d15, %1 \n\t"
27970 + " addc %1, #0, %1 \n\t" // sample C again
27971 + " add.4 %3, #-1, %3 \n\t"
27972 + " jmpeq.w.t 2f \n\t"
27974 + " move.1 d15, 1(%0) \n\t"
27975 + " add.4 %1, d15, %1 \n\t"
27976 + " addc %1, #0, %1 \n\t" // sample C again
27977 + " add.4 %3, #-1, %3 \n\t"
27978 + " jmpeq.w.t 2f \n\t"
27980 + " move.1 d15, 2(%0) \n\t"
27981 + " lsl.4 d15, d15, #8 \n\t"
27982 + " add.4 %1, d15, %1 \n\t"
27983 + " addc %1, #0, %1 \n\t" // sample C again
27984 + " jmpt.w.t 2f \n\t"
27986 +#if defined(IP7000) || defined(IP7000_REV2)
27987 + "300: swapb.2 %1, %1 \n\t"
27989 + "300: shmrg.2 %1, %1, %1 \n\t"
27990 + " lsr.4 %1, %1, #8 \n\t"
27991 + " bfextu %1, %1, #16 \n\t"
27993 + " jmpt.w.t 3f \n\t"
27995 + "1: add.4 %1, (%0)4++, %1 \n\t" // first add without C
27997 + " addc %1, (%0)4++, %1 \n\t"
27999 + " addc %1, #0, %1 \n\t" // sample C again
28000 + " add.4 %2, #-32, %2 \n\t"
28001 + " jmpgt.w.t 1b \n\t"
28003 + " and.4 %3, #3, %3 \n\t" // check n
28004 + " jmpne.w.f 200b \n\t"
28006 + "2: .rept 2 \n\t"
28007 + " lsr.4 d15, %1, #16 \n\t"
28008 + " bfextu %1, %1, #16 \n\t"
28009 + " add.4 %1, d15, %1 \n\t"
28011 + " btst d14, #3 \n\t" // start from odd address (<< 3)?
28012 + " jmpne.w.f 300b \n\t"
28015 + : "+a"(buff), "+d"(result), "+d"(count), "+d"(len)
28017 + : "d15", "d14", "a3", "cc"
28024 + * handle a few bytes and fold result into 16-bit
28026 + while (len-- > 0) {
28027 + result += (*buff++ << 8);
28029 + result += *buff++;
28035 + " lsr.4 d15, %0, #16 \n\t"
28036 + " bfextu %0, %0, #16 \n\t"
28037 + " add.4 %0, d15, %0 \n\t"
28048 + * This is a version of ip_compute_csum() optimized for IP headers,
28049 + * which always checksum on 4 octet boundaries.
28051 +__sum16 ip_fast_csum(const void *iph, unsigned int ihl)
28053 + return (__force __sum16)~do_csum(iph,ihl*4);
28057 + * computes the checksum of a memory block at buff, length len,
28058 + * and adds in "sum" (32-bit)
28060 + * returns a 32-bit number suitable for feeding into itself
28061 + * or csum_tcpudp_magic
28063 + * this function must be called with even lengths, except
28064 + * for the last fragment, which may be odd
28066 + * it's best to have buff aligned on a 32-bit boundary
28068 +__wsum csum_partial(const void *buff, int len, __wsum sum)
28070 + unsigned int result = do_csum(buff, len);
28072 + /* add in old sum, and carry.. */
28073 + result += (__force u32)sum;
28074 + if ((__force u32)sum > result)
28076 + return (__force __wsum)result;
28079 +EXPORT_SYMBOL(csum_partial);
28082 + * this routine is used for miscellaneous IP-like checksums, mainly
28085 +__sum16 ip_compute_csum(const void *buff, int len)
28087 + return (__force __sum16)~do_csum(buff,len);
28091 + * copy from fs while checksumming, otherwise like csum_partial
28095 +csum_partial_copy_from_user(const void __user *src, void *dst,
28096 + int len, __wsum sum, int *csum_err)
28098 + if (csum_err) *csum_err = 0;
28099 + memcpy(dst, (__force const void *)src, len);
28100 + return csum_partial(dst, len, sum);
28104 + * copy from ds while checksumming, otherwise like csum_partial
28108 +csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum)
28110 + memcpy(dst, src, len);
28111 + return csum_partial(dst, len, sum);
28114 +++ b/arch/ubicom32/lib/delay.c
28117 + * arch/ubicom32/lib/delay.c
28118 + * Ubicom32 implementation of udelay()
28120 + * (C) Copyright 2009, Ubicom, Inc.
28122 + * This file is part of the Ubicom32 Linux Kernel Port.
28124 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
28125 + * it and/or modify it under the terms of the GNU General Public License
28126 + * as published by the Free Software Foundation, either version 2 of the
28127 + * License, or (at your option) any later version.
28129 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
28130 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
28131 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
28132 + * the GNU General Public License for more details.
28134 + * You should have received a copy of the GNU General Public License
28135 + * along with the Ubicom32 Linux Kernel Port. If not,
28136 + * see <http://www.gnu.org/licenses/>.
28138 + * Ubicom32 implementation derived from (with many thanks):
28144 +#include <linux/module.h>
28145 +#include <asm/param.h>
28146 +#include <asm/delay.h>
28147 +#include <asm/ip5000.h>
28150 + * read_current_timer()
28151 + * Return the current value of sysval.
28153 +int __devinit read_current_timer(unsigned long *timer_val)
28155 + *timer_val = (long)(UBICOM32_IO_TIMER->sysval);
28160 +void udelay(unsigned long usecs)
28164 +EXPORT_SYMBOL(udelay);
28166 +++ b/arch/ubicom32/lib/Makefile
28169 +# arch/ubicom32/lib/Makefile
28170 +# <TODO: Replace with short file description>
28172 +# (C) Copyright 2009, Ubicom, Inc.
28174 +# This file is part of the Ubicom32 Linux Kernel Port.
28176 +# The Ubicom32 Linux Kernel Port is free software: you can redistribute
28177 +# it and/or modify it under the terms of the GNU General Public License
28178 +# as published by the Free Software Foundation, either version 2 of the
28179 +# License, or (at your option) any later version.
28181 +# The Ubicom32 Linux Kernel Port is distributed in the hope that it
28182 +# will be useful, but WITHOUT ANY WARRANTY; without even the implied
28183 +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
28184 +# the GNU General Public License for more details.
28186 +# You should have received a copy of the GNU General Public License
28187 +# along with the Ubicom32 Linux Kernel Port. If not,
28188 +# see <http://www.gnu.org/licenses/>.
28190 +# Ubicom32 implementation derived from (with many thanks):
28196 +# Makefile for m68knommu specific library files..
28199 +lib-y := checksum.o delay.o mem_ubicom32.o
28201 +++ b/arch/ubicom32/lib/mem_ubicom32.c
28204 + * arch/ubicom32/lib/mem_ubicom32.c
28205 + * String functions.
28207 + * (C) Copyright 2009, Ubicom, Inc.
28209 + * This file is part of the Ubicom32 Linux Kernel Port.
28211 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
28212 + * it and/or modify it under the terms of the GNU General Public License
28213 + * as published by the Free Software Foundation, either version 2 of the
28214 + * License, or (at your option) any later version.
28216 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
28217 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
28218 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
28219 + * the GNU General Public License for more details.
28221 + * You should have received a copy of the GNU General Public License
28222 + * along with the Ubicom32 Linux Kernel Port. If not,
28223 + * see <http://www.gnu.org/licenses/>.
28225 + * Ubicom32 implementation derived from (with many thanks):
28231 +#include <linux/module.h>
28232 +#include <linux/types.h>
28233 +#include <linux/compiler.h>
28235 +#define LIKELY likely
28236 +#define UNLIKELY unlikely
28238 +typedef u32_t addr_t;
28243 +void *memcpy(void *dest, const void *src, size_t n)
28245 + void *dest_ret = dest;
28247 + if (LIKELY((((addr_t)dest ^ (addr_t)src) & 3) == 0) && LIKELY(n > 6)) {
28249 + n -= (4 - (addr_t)dest) & 0x03;
28252 + " sub.4 d15, #0, %2 \n\t" // set up for jump table
28253 + " and.4 d15, #(32-1), d15 \n\t" // d15 = (-m) & (32 - 1)
28254 + " moveai a3, #%%hi(1f) \n\t"
28255 + " lea.1 a3, %%lo(1f)(a3) \n\t"
28256 + " lea.4 a3, (a3,d15) \n\t"
28258 + " bfextu d15, %0, #2 \n\t" // d15 = (dest & 3)
28259 + " jmpne.w.f 100f \n\t"
28260 + " calli a3, 0(a3) \n\t" // 4-byte alignment
28262 + "100: cmpi d15, #2 \n\t"
28263 + " jmpne.s.f 101f \n\t"
28264 + " move.2 (%0)2++, (%1)2++ \n\t"
28265 + " calli a3, 0(a3) \n\t" // 2-byte alignment
28267 + "101: move.1 (%0)1++, (%1)1++ \n\t"
28268 + " jmpgt.s.f 102f \n\t" // 3-byte alignment
28269 + " move.2 (%0)2++, (%1)2++ \n\t" // 1-byte alignment
28270 + "102: calli a3, 0(a3) \n\t"
28272 + "200: cmpi %3, #2 \n\t"
28273 + " jmplt.s.f 201f \n\t"
28274 + " move.2 (%0)2++, (%1)2++ \n\t"
28275 + " jmpeq.s.t 2f \n\t"
28276 + "201: move.1 (%0)1++, (%1)1++ \n\t"
28277 + " jmpt.w.t 2f \n\t"
28279 + "1: .rept 25 \n\t"
28280 + " movea (%0)4++, (%1)4++ \n\t"
28283 + " move.4 (%0)4++, (%1)4++ \n\t"
28285 + " add.4 %2, #-32, %2 \n\t"
28286 + " jmpgt.w.f 1b \n\t"
28288 + " and.4 %3, #3, %3 \n\t" // check n
28289 + " jmpne.w.f 200b \n\t"
28291 + : "+a" (dest), "+a" (src), "+d" (m), "+d" (n)
28293 + : "d15", "a3", "memory", "cc"
28299 + if (LIKELY((((addr_t)dest ^ (addr_t)src) & 1) == 0) && LIKELY(n > 2)) {
28301 + n -= (addr_t)dest & 0x01;
28304 + " sub.4 d15, #0, %2 \n\t" // set up for jump table
28305 + " and.4 d15, #(32-1), d15 \n\t" // d15 = (-m) & (32 - 1)
28306 + " moveai a3, #%%hi(1f) \n\t"
28307 + " lea.1 a3, %%lo(1f)(a3) \n\t"
28308 + " lea.4 a3, (a3,d15) \n\t"
28310 + " btst %0, #0 \n\t" // check bit 0
28311 + " jmpne.w.f 100f \n\t"
28312 + " calli a3, 0(a3) \n\t" // 4-byte alignment
28314 + "100: move.1 (%0)1++, (%1)1++ \n\t"
28315 + " calli a3, 0(a3) \n\t"
28317 + "200: move.1 (%0)1++, (%1)1++ \n\t"
28318 + " jmpt.w.t 2f \n\t"
28320 + "1: .rept 32 \n\t"
28321 + " move.2 (%0)2++, (%1)2++ \n\t"
28323 + " add.4 %2, #-32, %2 \n\t"
28324 + " jmpgt.w.f 1b \n\t"
28326 + " and.4 %3, #1, %3 \n\t" // check n
28327 + " jmpne.w.f 200b \n\t"
28330 + : "+a" (dest), "+a" (src), "+d" (m), "+d" (n)
28332 + : "d15", "a3", "memory", "cc"
28339 + " sub.4 d15, #0, %2 \n\t"
28340 + " jmpeq.w.f 2f \n\t"
28341 + " and.4 d15, #(16-1), d15 \n\t" // d15 = (-n) & (16 - 1)
28342 + " moveai a3, #%%hi(1f) \n\t"
28343 + " lea.1 a3, %%lo(1f)(a3) \n\t"
28344 + " lea.4 a3, (a3,d15) \n\t"
28345 + " calli a3, 0(a3) \n\t"
28347 + "1: .rept 16 \n\t"
28348 + " move.1 (%0)1++, (%1)1++ \n\t"
28350 + " add.4 %2, #-16, %2 \n\t"
28351 + " jmpgt.w.f 1b \n\t"
28354 + : "+a" (dest), "+a" (src), "+d" (n)
28356 + : "d15", "a3", "memory", "cc"
28365 +void *memset(void *s, int c, size_t n)
28369 + if (LIKELY(n > 6)) {
28371 + n -= (4 - (addr_t)s) & 0x03;
28374 + " sub.4 d15, #0, %2 \n\t" // set up for jump table
28375 + " and.4 d15, #(32-1), d15 \n\t" // d15 = (-m) & (32 - 1)
28376 + " shmrg.1 %1, %1, %1 \n\t"
28377 + " shmrg.2 %1, %1, %1 \n\t" // %1 = (c<<24)|(c<<16)|(c<<8)|c
28378 + " moveai a3, #%%hi(1f) \n\t"
28379 + " lea.1 a3, %%lo(1f)(a3) \n\t"
28380 + " lea.4 a3, (a3,d15) \n\t"
28382 + " bfextu d15, %0, #2 \n\t" // d15 = (s & 3)
28383 + " jmpne.w.f 100f \n\t"
28384 + " calli a3, 0(a3) \n\t" // 4-byte alignment
28386 + "100: cmpi d15, #2 \n\t"
28387 + " jmpne.s.f 101f \n\t"
28388 + " move.2 (%0)2++, %1 \n\t"
28389 + " calli a3, 0(a3) \n\t" // 2-byte alignment
28391 + "101: move.1 (%0)1++, %1 \n\t"
28392 + " jmpgt.s.f 102f \n\t" // 3-byte alignment
28393 + " move.2 (%0)2++, %1 \n\t" // 1-byte alignment
28394 + "102: calli a3, 0(a3) \n\t"
28396 + "200: cmpi %3, #2 \n\t"
28397 + " jmplt.s.f 201f \n\t"
28398 + " move.2 (%0)2++, %1 \n\t"
28399 + " jmpeq.s.t 2f \n\t"
28400 + "201: move.1 (%0)1++, %1 \n\t"
28401 + " jmpt.w.t 2f \n\t"
28403 + "1: .rept 25 \n\t"
28404 + " movea (%0)4++, %1 \n\t"
28407 + " move.4 (%0)4++, %1 \n\t"
28409 + " add.4 %2, #-32, %2 \n\t"
28410 + " jmpgt.w.f 1b \n\t"
28412 + " and.4 %3, #3, %3 \n\t" // test bit 1 of n
28413 + " jmpne.w.f 200b \n\t"
28416 + : "+a" (s), "+d" (c), "+d" (m), "+d" (n)
28418 + : "d15", "a3", "memory", "cc"
28425 + " sub.4 d15, #0, %2 \n\t"
28426 + " jmpeq.w.f 2f \n\t"
28427 + " and.4 d15, #(8-1), d15 \n\t" // d15 = (-%2) & (16 - 1)
28428 + " moveai a3, #%%hi(1f) \n\t"
28429 + " lea.1 a3, %%lo(1f)(a3) \n\t"
28430 + " lea.4 a3, (a3,d15) \n\t"
28431 + " calli a3, 0(a3) \n\t"
28433 + "1: .rept 8 \n\t"
28434 + " move.1 (%0)1++, %1 \n\t"
28438 + : "+a" (s), "+d" (c), "+d" (n)
28440 + : "d15", "a3", "memory", "cc"
28446 +void *memmove(void *dest, const void *src, size_t n)
28458 + * Will perform 16-bit move if possible
28460 + if (likely((((u32)dest | (u32)src | n) & 1) == 0)) {
28461 + if (dest <= src) {
28463 + " sub.4 d15, #0, %2 \n\t" // set up for jump table
28464 + " and.4 d15, #(32-2), d15 \n\t" // d15 = (- count) & (32 - 2)
28465 + " moveai a3, #%%hi(1f) \n\t"
28466 + " lea.1 a3, %%lo(1f)(a3) \n\t"
28467 + " lea.2 a3, (a3,d15) \n\t"
28468 + " calli a3, 0(a3) \n\t"
28470 + "1: .rept 16 \n\t"
28471 + " move.2 (%0)2++, (%1)2++ \n\t"
28473 + " add.4 %2, #-32, %2 \n\t"
28474 + " jmpgt.w.f 1b \n\t"
28476 + : "+a" (tmp), "+a" (s), "+d" (n)
28478 + : "d15", "a3", "memory", "cc"
28484 + " sub.4 d15, #0, %2 \n\t" // set up for jump table
28485 + " and.4 d15, #(32-2), d15 \n\t" // d15 = (- count) & (32 - 2)
28486 + " moveai a3, #%%hi(1f) \n\t"
28487 + " lea.1 a3, %%lo(1f)(a3) \n\t"
28488 + " lea.2 a3, (a3,d15) \n\t"
28489 + " calli a3, 0(a3) \n\t"
28491 + "1: .rept 16 \n\t"
28492 + " move.2 -2(%0)++, -2(%1)++ \n\t"
28494 + " add.4 %2, #-32, %2 \n\t"
28495 + " jmpgt.w.f 1b \n\t"
28497 + : "+a" (tmp), "+a" (s), "+d" (n)
28499 + : "d15", "a3", "memory", "cc"
28505 + if (dest <= src) {
28507 + " sub.4 d15, #0, %2 \n\t" // set up for jump table
28508 + " and.4 d15, #(16-1), d15 \n\t" // d15 = (- count) & (16 - 1)
28509 + " moveai a3, #%%hi(1f) \n\t"
28510 + " lea.1 a3, %%lo(1f)(a3) \n\t"
28511 + " lea.4 a3, (a3,d15) \n\t"
28512 + " calli a3, 0(a3) \n\t"
28514 + "1: .rept 16 \n\t"
28515 + " move.1 (%0)1++, (%1)1++ \n\t"
28517 + " add.4 %2, #-16, %2 \n\t"
28518 + " jmpgt.w.f 1b \n\t"
28519 + : "+a" (tmp), "+a" (s), "+d" (n)
28521 + : "d15", "a3", "memory", "cc"
28527 + " sub.4 d15, #0, %2 \n\t" // set up for jump table
28528 + " and.4 d15, #(16-1), d15 \n\t" // d15 = (- count) & (16 - 1)
28529 + " moveai a3, #%%hi(1f) \n\t"
28530 + " lea.1 a3, %%lo(1f)(a3) \n\t"
28531 + " lea.4 a3, (a3,d15) \n\t"
28532 + " calli a3, 0(a3) \n\t"
28534 + "1: .rept 16 \n\t"
28535 + " move.1 -1(%0)++, -1(%1)++ \n\t"
28537 + " add.4 %2, #-16, %2 \n\t"
28538 + " jmpgt.w.f 1b \n\t"
28539 + : "+a" (tmp), "+a" (s), "+d" (n)
28541 + : "d15", "a3", "memory", "cc"
28547 +++ b/arch/ubicom32/mach-common/audio.c
28550 + * arch/ubicom32/mach-common/audio.c
28551 + * Generic initialization for Ubicom32 Audio
28553 + * (C) Copyright 2009, Ubicom, Inc.
28555 + * This file is part of the Ubicom32 Linux Kernel Port.
28557 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
28558 + * it and/or modify it under the terms of the GNU General Public License
28559 + * as published by the Free Software Foundation, either version 2 of the
28560 + * License, or (at your option) any later version.
28562 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
28563 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
28564 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
28565 + * the GNU General Public License for more details.
28567 + * You should have received a copy of the GNU General Public License
28568 + * along with the Ubicom32 Linux Kernel Port. If not,
28569 + * see <http://www.gnu.org/licenses/>.
28572 +#include <linux/platform_device.h>
28573 +#include <linux/types.h>
28575 +#include <asm/devtree.h>
28576 +#include <asm/audio.h>
28577 +#include <asm/ubi32-pcm.h>
28580 + * The number of audio devices currently allocated, used for .id
28582 +static int __initdata audio_device_count;
28585 + * The maximum number of resources (cards) that the audio will have.
28586 + * Currently 3, a register space, and up to 2 interrupts.
28588 +#define AUDIO_MAX_RESOURCES 3
28591 + * audio_device_alloc
28592 + * Checks the device tree and allocates a platform_device if found
28594 +struct platform_device * __init audio_device_alloc(const char *driver_name,
28595 + const char *node_name, const char *inst_name, int priv_bytes)
28597 + struct platform_device *pdev;
28598 + struct resource *res;
28599 + struct audio_node *audio_node;
28600 + struct ubi32pcm_platform_data *pdata;
28601 + struct audio_dev_regs *adr;
28605 + * Check the device tree for the audio node
28607 + audio_node = (struct audio_node *)devtree_find_node(node_name);
28608 + if (!audio_node) {
28609 + printk(KERN_WARNING "audio device '%s' not found\n", node_name);
28613 + if (audio_node->version != AUDIONODE_VERSION) {
28614 + printk(KERN_WARNING "audio node not compatible\n");
28619 + * Find the instance in this node
28621 + adr = audio_node->regs->adr;
28622 + for (idx = 0; idx < audio_node->regs->max_devs; idx++) {
28623 + if ((adr->version == AUDIO_DEV_REGS_VERSION) &&
28624 + (strcmp(adr->name, inst_name) == 0)) {
28629 + if (idx == audio_node->regs->max_devs) {
28630 + printk(KERN_WARNING "audio inst '%s' not found in device '%s'\n", inst_name, node_name);
28635 + * Dynamically create the platform_device structure and resources
28637 + pdev = kzalloc(sizeof(struct platform_device) +
28638 + sizeof(struct ubi32pcm_platform_data) +
28639 + priv_bytes , GFP_KERNEL);
28641 + printk(KERN_WARNING "audio could not alloc pdev\n");
28645 + res = kzalloc(sizeof(struct resource) * AUDIO_MAX_RESOURCES,
28649 + printk(KERN_WARNING "audio could not alloc res\n");
28653 + pdev->name = driver_name;
28654 + pdev->id = audio_device_count++;
28655 + pdev->resource = res;
28658 + * Fill in the resources and platform data from devtree information
28660 + res[0].start = (u32_t)(audio_node->regs);
28661 + res[0].end = (u32_t)(audio_node->regs);
28662 + res[0].flags = IORESOURCE_MEM;
28663 + res[1 + AUDIO_TX_IRQ_RESOURCE].start = audio_node->dn.sendirq;
28664 + res[1 + AUDIO_TX_IRQ_RESOURCE].flags = IORESOURCE_IRQ;
28665 + res[1 + AUDIO_RX_IRQ_RESOURCE].start = audio_node->dn.recvirq;
28666 + res[1 + AUDIO_RX_IRQ_RESOURCE].flags = IORESOURCE_IRQ;
28667 + pdev->num_resources = 3;
28669 + printk(KERN_INFO "Audio.%d '%s':'%s' found irq=%d/%d.%d regs=%p pdev=%p/%p\n",
28670 + pdev->id, node_name, inst_name, audio_node->dn.sendirq,
28671 + audio_node->dn.recvirq, idx, audio_node->regs, pdev, res);
28672 + pdata = (struct ubi32pcm_platform_data *)(pdev + 1);
28673 + pdev->dev.platform_data = pdata;
28674 + pdata->node_name = node_name;
28675 + pdata->inst_name = inst_name;
28676 + pdata->inst_num = idx;
28677 + if (priv_bytes) {
28678 + pdata->priv_data = pdata + 1;
28684 +++ b/arch/ubicom32/mach-common/board.c
28687 + * arch/ubicom32/mach-common/board.c
28688 + * Board init and support code.
28690 + * (C) Copyright 2009, Ubicom, Inc.
28692 + * This file is part of the Ubicom32 Linux Kernel Port.
28694 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
28695 + * it and/or modify it under the terms of the GNU General Public License
28696 + * as published by the Free Software Foundation, either version 2 of the
28697 + * License, or (at your option) any later version.
28699 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
28700 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
28701 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
28702 + * the GNU General Public License for more details.
28704 + * You should have received a copy of the GNU General Public License
28705 + * along with the Ubicom32 Linux Kernel Port. If not,
28706 + * see <http://www.gnu.org/licenses/>.
28708 + * Ubicom32 implementation derived from (with many thanks):
28713 +#include <linux/module.h>
28714 +#include <linux/types.h>
28715 +#include <linux/cpu.h>
28716 +#include <asm/devtree.h>
28718 +struct boardnode {
28719 + struct devtree_node dn;
28720 + const char *revision;
28723 +static const struct boardnode *bn;
28726 + * board_get_revision()
28727 + * Returns revision string of the board.
28729 +const char *board_get_revision(void)
28735 + return bn->revision;
28741 +void __init board_init(void)
28743 + bn = (struct boardnode *)devtree_find_node("board");
28745 + printk(KERN_WARNING "board node not found\n");
28750 +++ b/arch/ubicom32/mach-common/bootargs.c
28753 + * arch/ubicom32/mach-common/bootargs.c
28754 + * Board init and support code.
28756 + * (C) Copyright 2009, Ubicom, Inc.
28758 + * This file is part of the Ubicom32 Linux Kernel Port.
28760 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
28761 + * it and/or modify it under the terms of the GNU General Public License
28762 + * as published by the Free Software Foundation, either version 2 of the
28763 + * License, or (at your option) any later version.
28765 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
28766 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
28767 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
28768 + * the GNU General Public License for more details.
28770 + * You should have received a copy of the GNU General Public License
28771 + * along with the Ubicom32 Linux Kernel Port. If not,
28772 + * see <http://www.gnu.org/licenses/>.
28774 + * Ubicom32 implementation derived from (with many thanks):
28779 +#include <linux/module.h>
28780 +#include <linux/types.h>
28781 +#include <linux/cpu.h>
28782 +#include <asm/devtree.h>
28784 +struct bootargsnode {
28785 + struct devtree_node dn;
28786 + const char cmdline[512];
28789 +static const struct bootargsnode *ban;
28792 + * bootargs_get_cmdline()
28793 + * Returns kernel boot arguments set by the bootloader.
28795 +const char *bootargs_get_cmdline(void)
28801 + return ban->cmdline;
28807 +void __init bootargs_init(void)
28809 + ban = (struct bootargsnode *)devtree_find_node("bootargs");
28811 + printk(KERN_WARNING "bootargs node not found\n");
28816 +++ b/arch/ubicom32/mach-common/cachectl.c
28819 + * arch/ubicom32/mach-common/cachectl.c
28820 + * Architecture cache control support
28822 + * (C) Copyright 2009, Ubicom, Inc.
28824 + * This file is part of the Ubicom32 Linux Kernel Port.
28826 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
28827 + * it and/or modify it under the terms of the GNU General Public License
28828 + * as published by the Free Software Foundation, either version 2 of the
28829 + * License, or (at your option) any later version.
28831 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
28832 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
28833 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
28834 + * the GNU General Public License for more details.
28836 + * You should have received a copy of the GNU General Public License
28837 + * along with the Ubicom32 Linux Kernel Port. If not,
28838 + * see <http://www.gnu.org/licenses/>.
28840 + * Ubicom32 implementation derived from (with many thanks):
28846 +#include <linux/types.h>
28847 +#include <linux/module.h>
28848 +#include <asm/cachectl.h>
28851 + * The write queue flush procedure in mem_cache_control needs to make
28852 + * DCACHE_WRITE_QUEUE_LENGTH writes to DDR (not OCM). Here we reserve some
28853 + * memory for this operation.
28854 + * Allocate array of cache lines of least DCACHE_WRITE_QUEUE_LENGTH + 1 words in
28855 + * length rounded up to the nearest cache line.
28857 +#define CACHE_WRITE_QUEUE_FLUSH_AREA_SIZE \
28858 + ALIGN(sizeof(int) * (DCACHE_WRITE_QUEUE_LENGTH + 1), CACHE_LINE_SIZE)
28860 +static char cache_write_queue_flush_area[CACHE_WRITE_QUEUE_FLUSH_AREA_SIZE]
28861 + __attribute__((aligned(CACHE_LINE_SIZE)));
28864 + * ONE_CCR_ADDR_OP is a helper macro that executes a single CCR operation.
28866 +#define ONE_CCR_ADDR_OP(cc, op_addr, op) \
28869 + " btst "D(CCR_CTRL)"(%0), #"D(CCR_CTRL_VALID)" \n\t" \
28870 + " jmpne.f .-4 \n\t" \
28871 + " move.4 "D(CCR_ADDR)"(%0), %1 \n\t" \
28872 + " move.1 "D(CCR_CTRL+3)"(%0), %2 \n\t" \
28873 + " bset "D(CCR_CTRL)"(%0), "D(CCR_CTRL)"(%0), #"D(CCR_CTRL_VALID)" \n\t" \
28874 + " cycles 2 \n\t" \
28875 + " btst "D(CCR_CTRL)"(%0), #"D(CCR_CTRL_DONE)" \n\t" \
28876 + " jmpeq.f .-4 \n\t" \
28878 + : "a"(cc), "r"(op_addr), "r"(op & 0xff) \
28884 + * mem_cache_control()
28885 + * Special cache control operation
28887 +void mem_cache_control(unsigned long cc, unsigned long begin_addr,
28888 + unsigned long end_addr, unsigned long op)
28890 + unsigned long op_addr;
28891 + int dccr = cc == DCCR_BASE;
28892 + if (dccr && op == CCR_CTRL_FLUSH_ADDR) {
28894 + * We ensure all previous writes have left the data cache write
28895 + * queue by sending DCACHE_WRITE_QUEUE_LENGTH writes (to
28896 + * different words) down the queue. If this is not done it's
28897 + * possible that the data we are trying to flush hasn't even
28898 + * entered the data cache.
28899 + * The +1 ensure that the final 'flush' is actually a flush.
28901 + int *flush_area = (int *)cache_write_queue_flush_area;
28903 + " .rept "D(DCACHE_WRITE_QUEUE_LENGTH + 1)" \n\t"
28904 + " move.4 (%0)4++, d0 \n\t"
28906 + : "+a"(flush_area)
28911 + UBICOM32_LOCK(DCCR_LOCK_BIT);
28913 + UBICOM32_LOCK(ICCR_LOCK_BIT);
28916 + * Calculate the cache lines we need to operate on that include
28917 + * begin_addr though end_addr.
28919 + begin_addr = begin_addr & ~(CACHE_LINE_SIZE - 1);
28920 + end_addr = (end_addr + CACHE_LINE_SIZE - 1) & ~(CACHE_LINE_SIZE - 1);
28921 + op_addr = begin_addr;
28924 + ONE_CCR_ADDR_OP(cc, op_addr, op);
28925 + op_addr += CACHE_LINE_SIZE;
28926 + } while (likely(op_addr < end_addr));
28928 + if (dccr && op == CCR_CTRL_FLUSH_ADDR) {
28930 + * It turns out that when flushing the data cache the last flush
28931 + * isn't actually complete at this point. This is because there
28932 + * is another write buffer on the DDR side of the cache that is
28933 + * arbitrated with the I-Cache.
28935 + * The only foolproof method that ensures that the last data
28936 + * cache flush *actually* completed is to do another flush on a
28937 + * dirty cache line. This flush will block until the DDR write
28938 + * buffer is empty.
28940 + * Rather than creating a another dirty cache line, we use the
28941 + * flush_area above as we know that it is dirty from previous
28944 + ONE_CCR_ADDR_OP(cc, cache_write_queue_flush_area, op);
28948 + UBICOM32_UNLOCK(DCCR_LOCK_BIT);
28950 + UBICOM32_UNLOCK(ICCR_LOCK_BIT);
28953 +EXPORT_SYMBOL(mem_cache_control);
28955 +++ b/arch/ubicom32/mach-common/common.c
28958 + * arch/ubicom32/mach-common/common.c
28959 + * Common platform support.
28961 + * (C) Copyright 2009, Ubicom, Inc.
28963 + * This file is part of the Ubicom32 Linux Kernel Port.
28965 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
28966 + * it and/or modify it under the terms of the GNU General Public License
28967 + * as published by the Free Software Foundation, either version 2 of the
28968 + * License, or (at your option) any later version.
28970 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
28971 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
28972 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
28973 + * the GNU General Public License for more details.
28975 + * You should have received a copy of the GNU General Public License
28976 + * along with the Ubicom32 Linux Kernel Port. If not,
28977 + * see <http://www.gnu.org/licenses/>.
28979 + * Ubicom32 implementation derived from (with many thanks):
28984 +#include <linux/version.h>
28985 +#include <linux/kernel.h>
28986 +#include <linux/init.h>
28987 +#include <linux/module.h>
28988 +#include <linux/list.h>
28989 +#include <linux/errno.h>
28990 +#include <linux/err.h>
28991 +#include <linux/string.h>
28992 +#include <linux/clk.h>
28993 +#include <linux/mutex.h>
28994 +#include <linux/platform_device.h>
28997 +/* Minimum CLK support */
28999 +struct clk *clk_get(struct device *dev, const char *id)
29001 + return ERR_PTR(-ENOENT);
29003 +EXPORT_SYMBOL(clk_get);
29005 +void clk_put(struct clk *clk)
29008 +EXPORT_SYMBOL(clk_put);
29010 +int clk_enable(struct clk *clk)
29014 +EXPORT_SYMBOL(clk_enable);
29017 +void clk_disable(struct clk *clk)
29020 +EXPORT_SYMBOL(clk_disable);
29022 +++ b/arch/ubicom32/mach-common/io.c
29025 + * arch/ubicom32/mach-common/io.c
29026 + * PCI I/O memory read/write support functions.
29028 + * (C) Copyright 2009, Ubicom, Inc.
29030 + * This file is part of the Ubicom32 Linux Kernel Port.
29032 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
29033 + * it and/or modify it under the terms of the GNU General Public License
29034 + * as published by the Free Software Foundation, either version 2 of the
29035 + * License, or (at your option) any later version.
29037 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
29038 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
29039 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
29040 + * the GNU General Public License for more details.
29042 + * You should have received a copy of the GNU General Public License
29043 + * along with the Ubicom32 Linux Kernel Port. If not,
29044 + * see <http://www.gnu.org/licenses/>.
29046 + * Ubicom32 implementation derived from (with many thanks):
29051 +#include <linux/module.h>
29052 +#include <linux/kernel.h>
29053 +#include <linux/io.h>
29056 +unsigned char ioread8(void __iomem *addr)
29058 + if (IS_PCI_ADDRESS(addr))
29059 + return ubi32_pci_read_u8(addr);
29061 + return (unsigned char)(*(volatile unsigned char *)addr);
29063 +EXPORT_SYMBOL(ioread8);
29065 +unsigned short ioread16(void __iomem *addr)
29067 + if (IS_PCI_ADDRESS(addr))
29068 + return ubi32_pci_read_u16(addr);
29070 + return (unsigned short)(*(volatile unsigned short *)addr);
29072 +EXPORT_SYMBOL(ioread16);
29074 +unsigned int ioread32(void __iomem *addr)
29076 + if (IS_PCI_ADDRESS(addr))
29077 + return ubi32_pci_read_u32(addr);
29079 + return (unsigned int)(*(volatile unsigned int *)addr);
29081 +EXPORT_SYMBOL(ioread32);
29083 +void iowrite32(unsigned int val, void __iomem *addr)
29085 + if (IS_PCI_ADDRESS(addr))
29086 + ubi32_pci_write_u32(val, addr);
29088 + *(volatile unsigned int *)addr = val;
29090 +EXPORT_SYMBOL(iowrite32);
29092 +void iowrite16(unsigned short val, void __iomem *addr)
29094 + if (IS_PCI_ADDRESS(addr))
29095 + ubi32_pci_write_u16(val, addr);
29097 + *(volatile unsigned short *)addr = val;
29099 +EXPORT_SYMBOL(iowrite16);
29101 +void iowrite8(unsigned char val, void __iomem *addr)
29103 + if (IS_PCI_ADDRESS(addr))
29104 + ubi32_pci_write_u8(val, addr);
29106 + *(volatile unsigned char *)addr = val;
29108 +EXPORT_SYMBOL(iowrite8);
29110 +void memcpy_fromio(void *to, const volatile void __iomem *from, unsigned len)
29112 + if (IS_PCI_ADDRESS(from)) {
29113 + if ((((u32_t)from & 0x3) == 0) && (((u32_t)to & 0x3) == 0)) {
29114 + while ((int)len >= 4) {
29115 + *(u32_t *)to = ubi32_pci_read_u32(from);
29120 + } else if ((((u32_t)from & 0x1) == 0) &&
29121 + (((u32_t)to & 0x1) == 0)) {
29122 + while ((int)len >= 2) {
29123 + *(u16_t *)to = ubi32_pci_read_u16(from);
29131 + *(u8_t *)to = ubi32_pci_read_u8(from);
29137 + memcpy(to, (void *)from, len);
29139 +EXPORT_SYMBOL(memcpy_fromio);
29141 +void memcpy_toio(volatile void __iomem *to, const void *from, unsigned len)
29143 + if (IS_PCI_ADDRESS(to)) {
29144 + if ((((u32_t)from & 0x3) == 0) && (((u32_t)to & 0x3) == 0)) {
29145 + while ((int)len >= 4) {
29146 + ubi32_pci_write_u32(*(u32_t *)from, to);
29151 + } else if ((((u32_t)from & 0x1) == 0) &&
29152 + (((u32_t)to & 0x1) == 0)) {
29153 + while ((int)len >= 2) {
29154 + ubi32_pci_write_u16(*(u16_t *)from, to);
29162 + ubi32_pci_write_u8(*(u8_t *)from, to);
29168 + memcpy((void *)to, from, len);
29171 +EXPORT_SYMBOL(memcpy_toio);
29173 +void memset_io(volatile void __iomem *addr, int val, size_t len)
29175 + if (IS_PCI_ADDRESS(addr)) {
29177 + ubi32_pci_write_u8((unsigned char)val, addr);
29182 + memset((void *)addr, val, len);
29185 +EXPORT_SYMBOL(memset_io);
29187 +void ioread8_rep(void __iomem *port, void *buf, unsigned long count)
29189 + if (IS_PCI_ADDRESS(port)) {
29191 + *(u8_t *)buf = ioread8(port);
29196 + insb((unsigned int)port, buf, count);
29200 +EXPORT_SYMBOL(ioread8_rep);
29202 +void ioread16_rep(void __iomem *port, void *buf, unsigned long count)
29204 + if (IS_PCI_ADDRESS(port)) {
29206 + *(u16_t *)buf = ioread16(port);
29211 + insw((unsigned int)port, buf, count);
29214 +EXPORT_SYMBOL(ioread16_rep);
29216 +void ioread32_rep(void __iomem *port, void *buf, unsigned long count)
29218 + if (IS_PCI_ADDRESS(port)) {
29220 + *(u32_t *)buf = ioread32(port);
29225 + insl((unsigned int)port, buf, count);
29228 +EXPORT_SYMBOL(ioread32_rep);
29230 +void iowrite8_rep(void __iomem *port, const void *buf, unsigned long count)
29232 + if (IS_PCI_ADDRESS(port)) {
29234 + iowrite8(*(u8_t *)buf, port);
29239 + outsb((unsigned int)port, buf, count);
29243 +EXPORT_SYMBOL(iowrite8_rep);
29245 +void iowrite16_rep(void __iomem *port, const void *buf, unsigned long count)
29247 + if (IS_PCI_ADDRESS(port)) {
29249 + iowrite16(*(u16_t *)buf, port);
29254 + outsw((unsigned int)port, buf, count);
29257 +EXPORT_SYMBOL(iowrite16_rep);
29259 +void iowrite32_rep(void __iomem *port, const void *buf, unsigned long count)
29261 + if (IS_PCI_ADDRESS(port)) {
29263 + iowrite32(*(u32_t *)buf, port);
29268 + outsl((unsigned int)port, buf, count);
29271 +EXPORT_SYMBOL(iowrite32_rep);
29273 +#endif /* CONFIG_PCI */
29275 +++ b/arch/ubicom32/mach-common/Kconfig.switch
29277 +menuconfig UBICOM_SWITCH
29278 + tristate "Switch devices"
29280 + This option provides Ethernet switch management options via proc fs
29283 +config UBICOM_SWITCH_BCM539X
29284 + tristate "Broadcom BCM539X series (SPI)"
29285 + depends on SPI_MASTER
29287 + Supports Broadcom BCM539X Gigabit Ethernet Switches over SPI
29290 +++ b/arch/ubicom32/mach-common/Makefile
29293 +# arch/ubicom32/mach-common/Makefile
29294 +# Makefile for Ubicom32 generic drivers/code.
29296 +# (C) Copyright 2009, Ubicom, Inc.
29298 +# This file is part of the Ubicom32 Linux Kernel Port.
29300 +# The Ubicom32 Linux Kernel Port is free software: you can redistribute
29301 +# it and/or modify it under the terms of the GNU General Public License
29302 +# as published by the Free Software Foundation, either version 2 of the
29303 +# License, or (at your option) any later version.
29305 +# The Ubicom32 Linux Kernel Port is distributed in the hope that it
29306 +# will be useful, but WITHOUT ANY WARRANTY; without even the implied
29307 +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
29308 +# the GNU General Public License for more details.
29310 +# You should have received a copy of the GNU General Public License
29311 +# along with the Ubicom32 Linux Kernel Port. If not,
29312 +# see <http://www.gnu.org/licenses/>.
29314 +# Ubicom32 implementation derived from (with many thanks):
29320 +obj-y += cachectl.o common.o usb_tio.o usb.o ubi32-gpio.o board.o bootargs.o profile.o
29321 +obj-$(CONFIG_PCI) += pci.o io.o
29323 +obj-$(CONFIG_FB_UBICOM32) += vdc_tio.o
29324 +obj-$(CONFIG_UBICOM_HID) += ubicom32hid.o
29325 +obj-$(CONFIG_UBICOM_INPUT) += ubicom32input.o
29326 +obj-$(CONFIG_UBICOM_INPUT_I2C) += ubicom32input_i2c.o
29327 +obj-$(CONFIG_UBICOM_SWITCH) += switch-core.o
29328 +obj-$(CONFIG_UBICOM_SWITCH_BCM539X) += switch-bcm539x.o
29329 +obj-$(CONFIG_UIO_UBICOM32RING) += ring_tio.o
29330 +obj-$(CONFIG_SND_UBI32) += audio.o
29331 +obj-$(CONFIG_UBICOM32_PLIO) += plio.o
29334 +++ b/arch/ubicom32/mach-common/pci.c
29337 + * arch/ubicom32/mach-common/pci.c
29338 + * PCI interface management.
29340 + * (C) Copyright 2009, Ubicom, Inc.
29342 + * This file is part of the Ubicom32 Linux Kernel Port.
29344 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
29345 + * it and/or modify it under the terms of the GNU General Public License
29346 + * as published by the Free Software Foundation, either version 2 of the
29347 + * License, or (at your option) any later version.
29349 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
29350 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
29351 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
29352 + * the GNU General Public License for more details.
29354 + * You should have received a copy of the GNU General Public License
29355 + * along with the Ubicom32 Linux Kernel Port. If not,
29356 + * see <http://www.gnu.org/licenses/>.
29358 + * Ubicom32 implementation derived from (with many thanks):
29364 +#include <linux/module.h>
29365 +#include <linux/kernel.h>
29366 +#include <linux/pci.h>
29367 +#include <linux/slab.h>
29368 +#include <linux/init.h>
29369 +#include <linux/io.h>
29370 +#include <linux/seq_file.h>
29371 +#include <linux/proc_fs.h>
29373 +#include <asm/devtree.h>
29374 +#include <asm/ip5000.h>
29375 +#include <asm/ubicom32-common.h>
29377 +static int debug_pci = 1 ;
29379 +/* #define PCI_USE_INTERNAL_LOCK 1 */
29381 +#ifdef PCI_USE_INTERNAL_LOCK
29382 +#define PCI_LOCK(lock, irqflag) pci_lock_acquire(irqflag)
29383 +#define PCI_UNLOCK(lock, irqflag) pci_lock_release(irqflag)
29384 +#elif defined(CONFIG_SMP)
29385 +static DEFINE_SPINLOCK(pci_master_lock);
29386 +#define PCI_LOCK(lock, irqflag) spin_lock_irqsave(lock, irqflag)
29387 +#define PCI_UNLOCK(lock, irqflag) spin_unlock_irqrestore(lock, irqflag)
29389 +#define PCI_LOCK(lock, irqflag) local_irq_save(irqflag)
29390 +#define PCI_UNLOCK(lock, irqflag) local_irq_restore(irqflag)
29393 +#define PCI_DEV0_IDSEL CONFIG_PCI_DEV0_IDSEL
29394 +#define PCI_DEV1_IDSEL CONFIG_PCI_DEV1_IDSEL
29399 +#define PCI_CMD_INT_ACK 0x00 /* not supported */
29400 +#define PCI_CMD_SPECIAL 0x01 /* not supported */
29401 +#define PCI_CMD_IO_READ 0x02
29402 +#define PCI_CMD_IO_WRITE 0x03
29403 +#define PCI_CMD_MEM_READ 0x06
29404 +#define PCI_CMD_MEM_WRITE 0x07
29405 +#define PCI_CMD_CFG_READ 0x0a
29406 +#define PCI_CMD_CFG_WRITE 0x0b
29407 +#define PCI_CMD_MEM_READ_MULT 0x0c /* not supported */
29408 +#define PCI_CMD_DUAL_ADDR 0x0d /* not supported */
29409 +#define PCI_CMD_MEM_READ_LINE 0x0e /* not supported */
29410 +#define PCI_CMD_MEM_WRITE_INVAL 0x0f /* not supported */
29412 + * Status codes, returned by pci_read_u32() and pci_write_u32()
29414 +#define PCI_RESP_IN_PROGRESS 0xff /* request still in queue */
29415 +#define PCI_RESP_OK 0
29417 + * The following codes indicate that the request has completed
29419 +#define PCI_RESP_NO_DEVSEL 1 /* timeout before target asserted
29421 +#define PCI_RESP_LOST_DEVSEL 2 /* had DEVSEL, but went away before
29422 + * transfer completed! */
29423 +#define PCI_RESP_BAD_TRDY 3 /* target asserted TRDY without
29425 +#define PCI_RESP_NO_TRDY 4 /* timeout before target asserted
29427 +#define PCI_RESP_BAD_STOP 5 /* target asserted STOP and TRDY
29428 + * without DEVSEL! */
29429 +#define PCI_RESP_TARGET_ABORT 6
29430 +#define PCI_RESP_TARGET_RETRY 7
29431 +#define PCI_RESP_TARGET_DISCONNECT 8
29432 +#define PCI_RESP_MISMATCH 9 /* data read back doesn't match data
29433 + * written - debug only, the core PCI
29434 + * routines never return this */
29435 +#define PCI_RESP_DET_SERR 10
29436 +#define PCI_RESP_DET_PERR 11
29437 +#define PCI_RESP_MALFORMED_REQ 12 /* Could be due to misaligned
29438 + * requests or invalid address */
29439 +#define PCI_RESP_NO_RESOURCE 13 /* Could be memory or other resourse
29440 + * like queue space */
29441 +#define PCI_RESP_ERROR 14 /* All emcompassing error */
29443 +/* registers in PCI config space */
29444 +#define PCI_DEVICE_VENDOR_ID_REG 0x00
29445 +#define PCI_STATUS_COMMAND_REG 0x04
29446 +#define PCI_CLASS_REVISION_REG 0x08
29447 +#define PCI_BHLC_REG 0x0c /* BIST, Header type, Latency
29448 + * timer, Cache line size */
29449 +#define PCI_BASE_ADDR_REG 0x10
29450 +#define PCI_BASE_REG_COUNT 6
29451 +#define CARDBUS_CIS_PTR_REG 0x28
29452 +#define PCI_SUB_SYSTEM_ID_REG 0x2c
29453 +#define PCI_EXP_ROM_ADDR_REG 0x30
29454 +#define PCI_CAP_PTR_REG 0x34
29455 +#define PCI_LGPL_REG 0x3C /* max Latency, min Gnt, interrupt
29456 + * Pin, interrupt Line */
29458 +struct pci_master_request {
29459 + volatile u32_t pci_address; /* must be 4-byte aligned */
29460 + volatile u32_t data; /* must be 4-byte aligned */
29461 + volatile u8_t cmd;
29462 + volatile u8_t byte_valid;
29463 + volatile u8_t status;
29466 +struct pci_devnode {
29467 + struct devtree_node dn;
29468 + u32_t pci_idsel_0;
29469 + u32_t pci_idsel_1;
29470 + u32_t pci_cpu_address;
29471 + struct pci_master_request volatile *volatile req;
29474 +static struct pci_master_request req; /* globally used for faster master write
29475 + * (discarding result when possible) */
29476 +static struct pci_devnode *pci_node;
29478 +#if !defined(CONFIG_DEBUG_PCIMEASURE)
29479 +#define PCI_DECLARE_MEASUREMENT
29480 +#define PCI_MEASUREMENT_START()
29481 +#define PCI_MEASUREMENT_END(idx)
29483 +#define PCI_DECLARE_MEASUREMENT \
29485 + unsigned int __tstart;
29487 +#define PCI_MEASUREMENT_START() \
29488 + __tstart = UBICOM32_IO_TIMER->sysval;
29490 +#define PCI_MEASUREMENT_END(idx) \
29491 + __diff = (int)UBICOM32_IO_TIMER->sysval - (int)__tstart; \
29492 + pci_measurement_update((idx), __diff);
29494 +#define PCI_WEIGHT 32
29496 +struct pci_measurement {
29497 + volatile unsigned int min;
29498 + volatile unsigned int avg;
29499 + volatile unsigned int max;
29502 +enum pci_measurement_list {
29503 + PCI_MEASUREMENT_READ32,
29504 + PCI_MEASUREMENT_WRITE32,
29505 + PCI_MEASUREMENT_READ16,
29506 + PCI_MEASUREMENT_WRITE16,
29507 + PCI_MEASUREMENT_READ8,
29508 + PCI_MEASUREMENT_WRITE8,
29509 + PCI_MEASUREMENT_LAST,
29512 +static const char *pci_measurement_name_list[PCI_MEASUREMENT_LAST] = {
29520 +static struct pci_measurement pci_measurements[PCI_MEASUREMENT_LAST];
29523 + * pci_measurement_update()
29524 + * Update an entry in the measurement array for this idx.
29526 +static void pci_measurement_update(int idx, int sample)
29528 + struct pci_measurement *pm = &pci_measurements[idx];
29529 + if ((pm->min == 0) || (pm->min > sample)) {
29530 + pm->min = sample;
29532 + if (pm->max < sample) {
29533 + pm->max = sample;
29535 + pm->avg = ((pm->avg * (PCI_WEIGHT - 1)) + sample) / PCI_WEIGHT;
29539 +#if defined(PCI_USE_INTERNAL_LOCK)
29541 + * pci_lock_release()
29542 + * Release the PCI lock.
29544 +static void pci_lock_release(unsigned long irqflag)
29546 + UBICOM32_UNLOCK(PCI_LOCK_BIT);
29550 + * pci_lock_acquire()
29551 + * Acquire the PCI lock, spin if not available.
29553 +static void pci_lock_acquire(unsigned long irqflag)
29555 + UBICOM32_LOCK(PCI_LOCK_BIT);
29560 + * pci_set_hrt_interrupt()
29562 +static inline void pci_set_hrt_interrupt(struct pci_devnode *pci_node)
29564 + ubicom32_set_interrupt(pci_node->dn.sendirq);
29569 + * Synchronously read 32 bits from PCI space.
29571 +u8 pci_read_u32(u8 pci_cmd, u32 address, u32 *data)
29574 + unsigned long irqflag;
29578 + * Fill in the request.
29580 + volatile struct pci_master_request lreq;
29581 + PCI_DECLARE_MEASUREMENT;
29583 + lreq.pci_address = address;
29584 + lreq.cmd = pci_cmd;
29585 + lreq.byte_valid = 0xf; /* enable all bytes */
29588 + * Wait for any previous request to complete and then make this request.
29590 + PCI_MEASUREMENT_START();
29591 + PCI_LOCK(&pci_master_lock, irqflag);
29592 + while (unlikely(pci_node->req == &req))
29594 + pci_node->req = &lreq;
29595 + pci_set_hrt_interrupt(pci_node);
29596 + PCI_UNLOCK(&pci_master_lock, irqflag);
29599 + * Wait for the result to show up.
29601 + while (unlikely(pci_node->req == &lreq))
29603 + status = lreq.status;
29604 + if (likely(status == PCI_RESP_OK))
29605 + *data = le32_to_cpu(lreq.data);
29608 + PCI_MEASUREMENT_END(PCI_MEASUREMENT_READ32);
29613 + * pci_write_u32()
29614 + * Asyncrhnously or synchronously write 32 bits to PCI master space.
29616 +u8 pci_write_u32(u8 pci_cmd, u32 address, u32 data)
29618 + unsigned long irqflag;
29619 + PCI_DECLARE_MEASUREMENT;
29622 + * Wait for any previous write or pending read to complete.
29624 + * We use a global data block because once we write the request
29625 + * we do not wait for it to complete before exiting.
29627 + PCI_MEASUREMENT_START();
29628 + PCI_LOCK(&pci_master_lock, irqflag);
29629 + while (unlikely(pci_node->req == &req))
29631 + req.pci_address = address;
29632 + req.data = cpu_to_le32(data);
29633 + req.cmd = pci_cmd;
29634 + req.byte_valid = 0xf; /* enable all bytes */
29635 + pci_node->req = &req;
29636 + pci_set_hrt_interrupt(pci_node);
29637 + PCI_UNLOCK(&pci_master_lock, irqflag);
29638 + PCI_MEASUREMENT_END(PCI_MEASUREMENT_WRITE32);
29639 + return PCI_RESP_OK;
29644 + * Synchronously read 16 bits from PCI space.
29646 +u8 pci_read_u16(u8 pci_cmd, u32 address, u16 *data)
29649 + unsigned long irqflag;
29652 + * Fill in the request.
29654 + volatile struct pci_master_request lreq;
29655 + PCI_DECLARE_MEASUREMENT;
29657 + lreq.pci_address = address & ~2;
29658 + lreq.cmd = pci_cmd;
29659 + lreq.byte_valid = (address & 2) ? 0xc : 0x3;
29662 + * Wait for any previous request to complete and then make this request.
29664 + PCI_MEASUREMENT_START();
29665 + PCI_LOCK(&pci_master_lock, irqflag);
29666 + while (unlikely(pci_node->req == &req))
29668 + pci_node->req = &lreq;
29669 + pci_set_hrt_interrupt(pci_node);
29670 + PCI_UNLOCK(&pci_master_lock, irqflag);
29673 + * Wait for the result to show up.
29675 + while (unlikely(pci_node->req == &lreq))
29677 + status = lreq.status;
29678 + if (likely(status == PCI_RESP_OK)) {
29679 + lreq.data = le32_to_cpu(lreq.data);
29680 + *data = (u16)((address & 2) ? (lreq.data >> 16) : lreq.data);
29683 + PCI_MEASUREMENT_END(PCI_MEASUREMENT_READ16);
29688 + * pci_write_u16()
29689 + * Asyncrhnously or synchronously write 16 bits to PCI master space.
29691 +u8 pci_write_u16(u8 pci_cmd, u32 address, u16 data)
29693 + unsigned long irqflag;
29694 + PCI_DECLARE_MEASUREMENT;
29697 + * Wait for any previous write or pending read to complete.
29699 + * We use a global data block because once we write the request
29700 + * we do not wait for it to complete before exiting.
29702 + PCI_MEASUREMENT_START();
29703 + PCI_LOCK(&pci_master_lock, irqflag);
29704 + while (unlikely(pci_node->req == &req))
29706 + req.pci_address = address & ~2;
29707 + req.data = (u32)data;
29708 + req.data = cpu_to_le32((address & 2) ? (req.data << 16) : req.data);
29709 + req.cmd = pci_cmd;
29710 + req.byte_valid = (address & 2) ? 0xc : 0x3;
29711 + pci_node->req = &req;
29712 + pci_set_hrt_interrupt(pci_node);
29713 + PCI_UNLOCK(&pci_master_lock, irqflag);
29714 + PCI_MEASUREMENT_END(PCI_MEASUREMENT_WRITE16);
29715 + return PCI_RESP_OK;
29720 + * Synchronously read 8 bits from PCI space.
29722 +u8 pci_read_u8(u8 pci_cmd, u32 address, u8 *data)
29725 + unsigned long irqflag;
29728 + * Fill in the request.
29730 + volatile struct pci_master_request lreq;
29731 + PCI_DECLARE_MEASUREMENT;
29733 + lreq.pci_address = address & ~3;
29734 + lreq.cmd = pci_cmd;
29735 + lreq.byte_valid = 1 << (address & 0x3);
29738 + * Wait for any previous request to complete and then make this request.
29740 + PCI_MEASUREMENT_START();
29741 + PCI_LOCK(&pci_master_lock, irqflag);
29742 + while (unlikely(pci_node->req == &req))
29744 + pci_node->req = &lreq;
29745 + pci_set_hrt_interrupt(pci_node);
29746 + PCI_UNLOCK(&pci_master_lock, irqflag);
29749 + * Wait for the result to show up.
29751 + while (unlikely(pci_node->req == &lreq))
29753 + status = lreq.status;
29754 + if (likely(status == PCI_RESP_OK)) {
29755 + *data = (u8)(lreq.data >> (24 - ((address & 0x3) << 3)));
29758 + PCI_MEASUREMENT_END(PCI_MEASUREMENT_READ8);
29764 + * Asyncrhnously or synchronously write 8 bits to PCI master space.
29766 +u8 pci_write_u8(u8 pci_cmd, u32 address, u8 data)
29768 + unsigned long irqflag;
29769 + PCI_DECLARE_MEASUREMENT;
29772 + * Wait for any previous write or pending read to complete.
29774 + * We use a global data block because once we write the request
29775 + * we do not wait for it to complete before exiting.
29777 + PCI_MEASUREMENT_START();
29778 + PCI_LOCK(&pci_master_lock, irqflag);
29779 + while (unlikely(pci_node->req == &req))
29781 + req.pci_address = address & ~3;
29782 + req.data = ((u32)data << (24 - ((address & 0x3) << 3)));
29783 + req.cmd = pci_cmd;
29784 + req.byte_valid = 1 << (address & 0x3);
29785 + pci_node->req = &req;
29786 + pci_set_hrt_interrupt(pci_node);
29787 + PCI_UNLOCK(&pci_master_lock, irqflag);
29788 + PCI_MEASUREMENT_END(PCI_MEASUREMENT_WRITE8);
29789 + return PCI_RESP_OK;
29792 +unsigned int ubi32_pci_read_u32(const volatile void __iomem *addr)
29794 + unsigned int data;
29795 + pci_read_u32(PCI_CMD_MEM_READ, (u32)addr, &data);
29798 +EXPORT_SYMBOL(ubi32_pci_read_u32);
29800 +unsigned short ubi32_pci_read_u16(const volatile void __iomem *addr)
29802 + unsigned short data;
29803 + pci_read_u16(PCI_CMD_MEM_READ, (u32)addr, &data);
29806 +EXPORT_SYMBOL(ubi32_pci_read_u16);
29808 +unsigned char ubi32_pci_read_u8(const volatile void __iomem *addr)
29810 + unsigned char data;
29811 + pci_read_u8(PCI_CMD_MEM_READ, (u32)addr, &data);
29814 +EXPORT_SYMBOL(ubi32_pci_read_u8);
29816 +void ubi32_pci_write_u32(unsigned int val, const volatile void __iomem *addr)
29818 + pci_write_u32(PCI_CMD_MEM_WRITE, (u32)addr, val);
29820 +EXPORT_SYMBOL(ubi32_pci_write_u32);
29822 +void ubi32_pci_write_u16(unsigned short val, const volatile void __iomem *addr)
29824 + pci_write_u16(PCI_CMD_MEM_WRITE, (u32)addr, val);
29826 +EXPORT_SYMBOL(ubi32_pci_write_u16);
29828 +void ubi32_pci_write_u8(unsigned char val, const void volatile __iomem *addr)
29830 + pci_write_u8(PCI_CMD_MEM_WRITE, (u32)addr, val);
29832 +EXPORT_SYMBOL(ubi32_pci_write_u8);
29834 +#if defined(CONFIG_DEBUG_PCIMEASURE)
29835 +static unsigned int pci_cycles_to_nano(unsigned int cycles, unsigned int frequency)
29837 + unsigned int nano = ((cycles * 1000) / (frequency / 1000000));
29842 + * pci_measurement_show()
29843 + * Print out the min, avg, max values for each PCI transaction type.
29845 + * By request, the max value is reset after each dump.
29847 +static int pci_measurement_show(struct seq_file *p, void *v)
29849 + unsigned int min, avg, max;
29850 + unsigned int freq = processor_frequency();
29851 + int trans = *((loff_t *) v);
29853 + if (trans == 0) {
29854 + seq_puts(p, "min\tavg\tmax\t(nano-seconds)\n");
29857 + if (trans >= PCI_MEASUREMENT_LAST) {
29861 + min = pci_cycles_to_nano(pci_measurements[trans].min, freq);
29862 + avg = pci_cycles_to_nano(pci_measurements[trans].avg, freq);
29863 + max = pci_cycles_to_nano(pci_measurements[trans].max, freq);
29864 + pci_measurements[trans].max = 0;
29865 + seq_printf(p, "%u\t%u\t%u\t%s\n", min, avg, max, pci_measurement_name_list[trans]);
29869 +static void *pci_measurement_start(struct seq_file *f, loff_t *pos)
29871 + return (*pos < PCI_MEASUREMENT_LAST) ? pos : NULL;
29874 +static void *pci_measurement_next(struct seq_file *f, void *v, loff_t *pos)
29877 + if (*pos >= PCI_MEASUREMENT_LAST)
29882 +static void pci_measurement_stop(struct seq_file *f, void *v)
29884 + /* Nothing to do */
29887 +static const struct seq_operations pci_measurement_seq_ops = {
29888 + .start = pci_measurement_start,
29889 + .next = pci_measurement_next,
29890 + .stop = pci_measurement_stop,
29891 + .show = pci_measurement_show,
29894 +static int pci_measurement_open(struct inode *inode, struct file *filp)
29896 + return seq_open(filp, &pci_measurement_seq_ops);
29899 +static const struct file_operations pci_measurement_fops = {
29900 + .open = pci_measurement_open,
29901 + .read = seq_read,
29902 + .llseek = seq_lseek,
29903 + .release = seq_release,
29906 +static int __init pci_measurement_init(void)
29908 + proc_create("pci_measurements", 0, NULL, &pci_measurement_fops);
29911 +module_init(pci_measurement_init);
29914 +static int ubi32_pci_read_config(struct pci_bus *bus, unsigned int devfn,
29915 + int where, int size, u32 *value)
29922 + u8 slot = PCI_SLOT(devfn);
29923 + u8 fn = PCI_FUNC(devfn);
29926 + return PCIBIOS_DEVICE_NOT_FOUND;
29927 + } else if (slot == 0) {
29928 + addr = PCI_DEV0_IDSEL + where;
29930 + addr = PCI_DEV1_IDSEL + where;
29933 + addr += (fn << 8);
29935 + cmd = PCI_CMD_CFG_READ;
29937 + pci_read_u8(cmd, addr, &data8);
29938 + *value = (u32)data8;
29939 + } else if (size == 2) {
29940 + pci_read_u16(cmd, addr, &data16);
29941 + *value = (u32)data16;
29943 + pci_read_u32(cmd, addr, value);
29946 + return PCIBIOS_SUCCESSFUL;
29949 +static int ubi32_pci_write_config(struct pci_bus *bus, unsigned int devfn,
29950 + int where, int size, u32 value)
29954 + u8 slot = PCI_SLOT(devfn);
29955 + u8 fn = PCI_FUNC(devfn);
29958 + return PCIBIOS_DEVICE_NOT_FOUND;
29959 + } else if (slot == 0) {
29960 + addr = PCI_DEV0_IDSEL + where;
29962 + addr = PCI_DEV1_IDSEL + where;
29965 + addr += (fn << 8);
29967 + cmd = PCI_CMD_CFG_WRITE;
29969 + pci_write_u8(cmd, addr, (u8)value);
29970 + } else if (size == 2) {
29971 + pci_write_u16(cmd, addr, (u16)value);
29973 + pci_write_u32(cmd, addr, value);
29976 + return PCIBIOS_SUCCESSFUL;
29979 +int pci_set_dma_max_seg_size(struct pci_dev *dev, unsigned int size)
29983 +EXPORT_SYMBOL(pci_set_dma_max_seg_size);
29985 +int pci_set_dma_seg_boundary(struct pci_dev *dev, unsigned long mask)
29989 +EXPORT_SYMBOL(pci_set_dma_seg_boundary);
29991 +void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
29993 + resource_size_t start = pci_resource_start(dev, bar);
29994 + resource_size_t len = pci_resource_len(dev, bar);
29995 + unsigned long flags = pci_resource_flags(dev, bar);
29997 + if (!len || !start) {
30001 + if (maxlen && len > maxlen) {
30005 + if (flags & IORESOURCE_IO) {
30006 + return ioport_map(start, len);
30009 + if (flags & IORESOURCE_MEM) {
30010 + if (flags & IORESOURCE_CACHEABLE) {
30011 + return ioremap(start, len);
30013 + return ioremap_nocache(start, len);
30017 +EXPORT_SYMBOL(pci_iomap);
30019 +void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
30021 + if ((unsigned long)addr >= VMALLOC_START &&
30022 + (unsigned long)addr < VMALLOC_END) {
30026 +EXPORT_SYMBOL(pci_iounmap);
30029 + * From arch/arm/kernel/bios32.c
30031 + * PCI bios-type initialisation for PCI machines
30033 + * Bits taken from various places.
30035 +static void __init pcibios_init_hw(struct hw_pci *hw)
30037 + struct pci_sys_data *sys = NULL;
30041 + for (nr = busnr = 0; nr < hw->nr_controllers; nr++) {
30042 + sys = kzalloc(sizeof(struct pci_sys_data), GFP_KERNEL);
30044 + panic("PCI: unable to allocate sys data!");
30047 + sys->busnr = busnr;
30048 + sys->map_irq = hw->map_irq;
30049 + sys->resource[0] = &ioport_resource;
30050 + sys->resource[1] = &iomem_resource;
30052 + ret = hw->setup(nr, sys);
30055 + sys->bus = hw->scan(nr, sys);
30058 + panic("PCI: unable to scan bus!");
30060 + busnr = sys->bus->subordinate + 1;
30062 + list_add(&sys->node, &hw->buses);
30072 + * Swizzle the device pin each time we cross a bridge.
30073 + * This might update pin and returns the slot number.
30075 +static u8 __devinit pcibios_swizzle(struct pci_dev *dev, u8 *pin)
30077 + struct pci_sys_data *sys = dev->sysdata;
30078 + int slot = 0, oldpin = *pin;
30080 + if (sys->swizzle)
30081 + slot = sys->swizzle(dev, pin);
30084 + printk("PCI: %s swizzling pin %d => pin %d slot %d\n",
30085 + pci_name(dev), oldpin, *pin, slot);
30090 + * Map a slot/pin to an IRQ.
30092 +static int pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
30094 + struct pci_sys_data *sys = dev->sysdata;
30097 + if (sys->map_irq)
30098 + irq = sys->map_irq(dev, slot, pin);
30101 + printk("PCI: %s mapping slot %d pin %d => irq %d\n",
30102 + pci_name(dev), slot, pin, irq);
30107 +void __init pci_common_init(struct hw_pci *hw)
30109 + struct pci_sys_data *sys;
30111 + INIT_LIST_HEAD(&hw->buses);
30115 + pcibios_init_hw(hw);
30116 + if (hw->postinit)
30119 + pci_fixup_irqs(pcibios_swizzle, pcibios_map_irq);
30120 + list_for_each_entry(sys, &hw->buses, node) {
30121 + struct pci_bus *bus = sys->bus;
30123 + * Size the bridge windows.
30125 + pci_bus_size_bridges(bus);
30127 + * Assign resources.
30129 + pci_bus_assign_resources(bus);
30132 + * Tell drivers about devices found.
30134 + pci_bus_add_devices(bus);
30138 +char * __init pcibios_setup(char *str)
30140 + if (!strcmp(str, "debug")) {
30148 + * From arch/i386/kernel/pci-i386.c:
30150 + * We need to avoid collisions with `mirrored' VGA ports
30151 + * and other strange ISA hardware, so we always want the
30152 + * addresses to be allocated in the 0x000-0x0ff region
30155 + * Why? Because some silly external IO cards only decode
30156 + * the low 10 bits of the IO address. The 0x00-0xff region
30157 + * is reserved for motherboard devices that decode all 16
30158 + * bits, so it's ok to allocate at, say, 0x2800-0x28ff,
30159 + * but we want to try to avoid allocating at 0x2900-0x2bff
30160 + * which might be mirrored at 0x0100-0x03ff..
30162 +void pcibios_align_resource(void *data, struct resource *res,
30163 + resource_size_t size, resource_size_t align)
30165 + resource_size_t start = res->start;
30167 + if (res->flags & IORESOURCE_IO && start & 0x300)
30168 + start = (start + 0x3ff) & ~0x3ff;
30170 + res->start = (start + align - 1) & ~(align - 1);
30174 +void __devinit pcibios_update_irq(struct pci_dev *dev, int irq)
30177 + printk("PCI: Assigning IRQ %02d to %s\n", irq, pci_name(dev));
30178 + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
30182 + * If the bus contains any of these devices, then we must not turn on
30183 + * parity checking of any kind. Currently this is CyberPro 20x0 only.
30185 +static inline int pdev_bad_for_parity(struct pci_dev *dev)
30187 + return (dev->vendor == PCI_VENDOR_ID_INTERG &&
30188 + (dev->device == PCI_DEVICE_ID_INTERG_2000 ||
30189 + dev->device == PCI_DEVICE_ID_INTERG_2010)) ||
30190 + (dev->vendor == PCI_VENDOR_ID_ITE &&
30191 + dev->device == PCI_DEVICE_ID_ITE_8152);
30196 + * Adjust the device resources from bus-centric to Linux-centric.
30198 +static void __devinit
30199 +pdev_fixup_device_resources(struct pci_sys_data *root, struct pci_dev *dev)
30201 + resource_size_t offset;
30204 + for (i = 0; i < PCI_NUM_RESOURCES; i++) {
30205 + if (dev->resource[i].start == 0)
30207 + if (dev->resource[i].flags & IORESOURCE_MEM)
30208 + offset = root->mem_offset;
30210 + offset = root->io_offset;
30212 + dev->resource[i].start += offset;
30213 + dev->resource[i].end += offset;
30217 +static void __devinit
30218 +pbus_assign_bus_resources(struct pci_bus *bus, struct pci_sys_data *root)
30220 + struct pci_dev *dev = bus->self;
30225 + * Assign root bus resources.
30227 + for (i = 0; i < 3; i++)
30228 + bus->resource[i] = root->resource[i];
30233 + * pcibios_fixup_bus - Called after each bus is probed,
30234 + * but before its children are examined.
30236 +void pcibios_fixup_bus(struct pci_bus *bus)
30238 + struct pci_sys_data *root = bus->sysdata;
30239 + struct pci_dev *dev;
30240 + u16 features = PCI_COMMAND_SERR | PCI_COMMAND_PARITY |
30241 + PCI_COMMAND_FAST_BACK;
30243 + pbus_assign_bus_resources(bus, root);
30246 + * Walk the devices on this bus, working out what we can
30247 + * and can't support.
30249 + list_for_each_entry(dev, &bus->devices, bus_list) {
30252 + pdev_fixup_device_resources(root, dev);
30254 + pci_read_config_word(dev, PCI_STATUS, &status);
30257 + * If any device on this bus does not support fast back
30258 + * to back transfers, then the bus as a whole is not able
30259 + * to support them. Having fast back to back transfers
30260 + * on saves us one PCI cycle per transaction.
30262 + if (!(status & PCI_STATUS_FAST_BACK))
30263 + features &= ~PCI_COMMAND_FAST_BACK;
30265 + if (pdev_bad_for_parity(dev))
30266 + features &= ~(PCI_COMMAND_SERR | PCI_COMMAND_PARITY);
30268 + switch (dev->class >> 8) {
30269 + case PCI_CLASS_BRIDGE_PCI:
30270 + pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &status);
30271 + status |= PCI_BRIDGE_CTL_PARITY |
30272 + PCI_BRIDGE_CTL_MASTER_ABORT;
30273 + status &= ~(PCI_BRIDGE_CTL_BUS_RESET |
30274 + PCI_BRIDGE_CTL_FAST_BACK);
30275 + pci_write_config_word(dev, PCI_BRIDGE_CONTROL, status);
30278 + case PCI_CLASS_BRIDGE_CARDBUS:
30279 + pci_read_config_word(dev, PCI_CB_BRIDGE_CONTROL,
30281 + status |= PCI_CB_BRIDGE_CTL_PARITY |
30282 + PCI_CB_BRIDGE_CTL_MASTER_ABORT;
30283 + pci_write_config_word(dev, PCI_CB_BRIDGE_CONTROL,
30290 + * Now walk the devices again, this time setting them up.
30292 + list_for_each_entry(dev, &bus->devices, bus_list) {
30295 + pci_read_config_word(dev, PCI_COMMAND, &cmd);
30297 + pci_write_config_word(dev, PCI_COMMAND, cmd);
30299 + pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
30300 + L1_CACHE_BYTES >> 2);
30304 + * Propagate the flags to the PCI bridge.
30306 + if (bus->self && bus->self->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
30307 + if (features & PCI_COMMAND_FAST_BACK)
30308 + bus->bridge_ctl |= PCI_BRIDGE_CTL_FAST_BACK;
30309 + if (features & PCI_COMMAND_PARITY)
30310 + bus->bridge_ctl |= PCI_BRIDGE_CTL_PARITY;
30314 + * Report what we did for this bus
30316 + printk(KERN_INFO "PCI: bus%d: Fast back to back transfers %sabled\n",
30317 + bus->number, (features & PCI_COMMAND_FAST_BACK) ? "en" : "dis");
30320 + * Convert from Linux-centric to bus-centric addresses for bridge devices.
30323 +pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
30324 + struct resource *res)
30326 + struct pci_sys_data *root = dev->sysdata;
30327 + unsigned long offset = 0;
30329 + if (res->flags & IORESOURCE_IO)
30330 + offset = root->io_offset;
30331 + if (res->flags & IORESOURCE_MEM)
30332 + offset = root->mem_offset;
30334 + region->start = res->start - offset;
30335 + region->end = res->end - offset;
30339 +pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
30340 + struct pci_bus_region *region)
30342 + struct pci_sys_data *root = dev->sysdata;
30343 + unsigned long offset = 0;
30345 + if (res->flags & IORESOURCE_IO)
30346 + offset = root->io_offset;
30347 + if (res->flags & IORESOURCE_MEM)
30348 + offset = root->mem_offset;
30350 + res->start = region->start + offset;
30351 + res->end = region->end + offset;
30354 +#ifdef CONFIG_HOTPLUG
30355 +EXPORT_SYMBOL(pcibios_fixup_bus);
30356 +EXPORT_SYMBOL(pcibios_resource_to_bus);
30357 +EXPORT_SYMBOL(pcibios_bus_to_resource);
30361 + * pcibios_enable_device - Enable I/O and memory.
30362 + * @dev: PCI device to be enabled
30364 +int pcibios_enable_device(struct pci_dev *dev, int mask)
30366 + u16 cmd, old_cmd;
30368 + struct resource *r;
30370 + pci_read_config_word(dev, PCI_COMMAND, &cmd);
30372 + for (idx = 0; idx < 6; idx++) {
30373 + /* Only set up the requested stuff */
30374 + if (!(mask & (1 << idx)))
30377 + r = dev->resource + idx;
30378 + if (!r->start && r->end) {
30379 + printk(KERN_ERR "PCI: Device %s not available because"
30380 + " of resource collisions\n", pci_name(dev));
30383 + if (r->flags & IORESOURCE_IO)
30384 + cmd |= PCI_COMMAND_IO;
30385 + if (r->flags & IORESOURCE_MEM)
30386 + cmd |= PCI_COMMAND_MEMORY;
30390 + * Bridges (eg, cardbus bridges) need to be fully enabled
30392 + if ((dev->class >> 16) == PCI_BASE_CLASS_BRIDGE)
30393 + cmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
30395 + if (cmd != old_cmd) {
30396 + printk("PCI: enabling device %s (%04x -> %04x)\n",
30397 + pci_name(dev), old_cmd, cmd);
30398 + pci_write_config_word(dev, PCI_COMMAND, cmd);
30404 +struct pci_ops ubi32_pci_ops = {
30405 + .read = ubi32_pci_read_config,
30406 + .write = ubi32_pci_write_config,
30409 +static struct pci_bus *ubi32_pci_scan_bus(int nr, struct pci_sys_data *sys)
30411 + return pci_scan_bus(sys->busnr, &ubi32_pci_ops, sys);
30414 +#define UBI32_PCI_MEM_BASE PCI_DEV_REG_BASE
30415 +#define UBI32_PCI_MEM_LEN 0x80000000
30417 +#define UBI32_PCI_IO_BASE 0x0
30418 +#define UBI32_PCI_IO_END 0x0
30420 +static struct resource ubi32_pci_mem = {
30421 + .name = "PCI memory space",
30422 + .start = UBI32_PCI_MEM_BASE,
30423 + .end = UBI32_PCI_MEM_BASE + UBI32_PCI_MEM_LEN - 1,
30424 + .flags = IORESOURCE_MEM,
30427 +static struct resource ubi32_pci_io = {
30428 + .name = "PCI IO space",
30429 + .start = UBI32_PCI_IO_BASE,
30430 + .end = UBI32_PCI_IO_END,
30431 + .flags = IORESOURCE_IO,
30434 +static int __init ubi32_pci_setup(int nr, struct pci_sys_data *sys)
30439 + request_resource(&iomem_resource, &ubi32_pci_mem);
30440 + request_resource(&ioport_resource, &ubi32_pci_io);
30442 + sys->resource[0] = &ubi32_pci_io;
30443 + sys->resource[1] = &ubi32_pci_mem;
30444 + sys->resource[2] = NULL;
30449 +static void __init ubi32_pci_preinit(void)
30453 +static int __init ubi32_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
30455 + return pci_node->dn.recvirq;
30458 +struct hw_pci ubi32_pci __initdata = {
30459 + .nr_controllers = 1,
30460 + .preinit = ubi32_pci_preinit,
30461 + .setup = ubi32_pci_setup,
30462 + .scan = ubi32_pci_scan_bus,
30463 + .map_irq = ubi32_pci_map_irq,
30466 +static int __init ubi32_pci_init(void)
30468 + pci_node = (struct pci_devnode *)devtree_find_node("pci");
30469 + if (pci_node == NULL) {
30470 + printk(KERN_WARNING "PCI init failed\n");
30473 + pci_common_init(&ubi32_pci);
30477 +subsys_initcall(ubi32_pci_init);
30480 + * workaround for dual PCI card interrupt
30482 +#define PCI_COMMON_INT_BIT (1 << 19)
30483 +void ubi32_pci_int_wr(void)
30485 + volatile unsigned int pci_int_line;
30486 + pci_int_line = UBICOM32_IO_PORT(RB)->gpio_in;
30487 + if (!(pci_int_line & PCI_COMMON_INT_BIT))
30489 + ubicom32_set_interrupt(pci_node->dn.recvirq);
30492 +EXPORT_SYMBOL(ubi32_pci_int_wr);
30494 +++ b/arch/ubicom32/mach-common/plio.c
30498 + * PLIO state machine support functions
30500 + * Copyright © 2009 Ubicom Inc. <www.ubicom.com>. All rights reserved.
30502 + * This file is part of the Ubicom32 Linux Kernel Port.
30504 + * The Ubicom32 Linux Kernel Port is free software: you can
30505 + * redistribute it and/or modify it under the terms of the GNU General
30506 + * Public License as published by the Free Software Foundation, either
30507 + * version 2 of the License, or (at your option) any later version.
30509 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
30510 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
30511 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
30512 + * See the GNU General Public License for more details.
30514 + * You should have received a copy of the GNU General Public License
30515 + * along with the Ubicom32 Linux Kernel Port. If not,
30516 + * see <http://www.gnu.org/licenses/>.
30519 +#include <linux/types.h>
30520 +#include <linux/string.h>
30521 +#include <linux/delay.h>
30522 +#include <asm/plio.h>
30526 + * Select and reset PLIO function
30528 +static void plio_reset(const plio_fctl_t *plio_fctl) {
30529 + plio_io_function_t plio_function = {
30530 + .fn_sel = PLIO_FN,
30535 + * enable extension port
30537 + PEXT_NBR->function = plio_function;
30540 + * program clock dividers
30542 + PLIO_NBR->fctl2 = plio_fctl->fctl2;
30545 + * select plio function and assert function reset
30547 + plio_function.br_thread = thread_get_self();
30548 + plio_function.fn_reset = 1;
30549 + PLIO_NBR->function = plio_function;
30552 + * program plio controls
30554 + PLIO_NBR->fctl0 = plio_fctl->fctl0;
30555 + PLIO_NBR->fctl1 = plio_fctl->fctl1;
30558 + * deassert function reset
30560 + plio_function.fn_reset = 0;
30561 + PLIO_NBR->function = plio_function;
30566 + * configure and initialize PLIO.
30568 +void plio_init(const plio_fctl_t *plio_fctl, const plio_config_t *plio_config, const plio_sram_t plio_sram_cfg[], int sram_cfg_size){
30570 + * first reset to start plio clock
30572 + plio_reset(plio_fctl);
30579 + PLIO_NBR->fctl0.pfsm_prog = 1;
30580 + memcpy(PLIO_BR->pfsm_sram, plio_sram_cfg, sram_cfg_size);
30581 + PLIO_NBR->fctl0.pfsm_prog = 0;
30584 + * program rest of plio
30586 + memcpy(&PLIO_BR->config, plio_config, sizeof(plio_config_t));
30589 +++ b/arch/ubicom32/mach-common/profile.c
30592 + * arch/ubicom32/mach-common/profile.c
30593 + * Implementation for Ubicom32 Profiler
30595 + * (C) Copyright 2009, Ubicom, Inc.
30597 + * This file is part of the Ubicom32 Linux Kernel Port.
30599 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
30600 + * it and/or modify it under the terms of the GNU General Public License
30601 + * as published by the Free Software Foundation, either version 2 of the
30602 + * License, or (at your option) any later version.
30604 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
30605 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
30606 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
30607 + * the GNU General Public License for more details.
30609 + * You should have received a copy of the GNU General Public License
30610 + * along with the Ubicom32 Linux Kernel Port. If not,
30611 + * see <http://www.gnu.org/licenses/>.
30614 +#include <linux/platform_device.h>
30615 +#include "profile.h"
30616 +#include <linux/seq_file.h>
30617 +#include <linux/proc_fs.h>
30618 +#include <linux/mm.h>
30619 +#include <linux/mmzone.h>
30620 +#include <linux/fs.h>
30621 +#include <linux/page-flags.h>
30622 +#include <asm/uaccess.h>
30623 +#include <asm/devtree.h>
30624 +#include <asm/profilesample.h>
30625 +#include <asm/memory_map.h>
30626 +#include <asm/page.h>
30627 +#include <asm/ip5000.h>
30630 + * spacs for all memory blocks so we can hold locks for short time when walking tables
30632 +#define PROFILE_NUM_MAPS 5000
30633 +static struct profile_map profile_pm[PROFILE_NUM_MAPS];
30635 +static struct profilenode *node = NULL;
30636 +static int profile_first_packet = 1;
30638 +static int profile_open(struct inode *inode, struct file *filp)
30644 + if (!node->enabled) {
30645 + node->enabled = 1;
30647 + profile_first_packet = 1;
30654 +static int profile_sequence_num;
30657 + * make a packet full of sample data
30659 +static int profile_make_data_packet(char *buf, int count)
30661 + int samples; /* number of samples requested */
30663 + struct profile_header ph;
30666 + if (count < sizeof(struct profile_header) + sizeof(struct profile_sample)) {
30671 + * fill in the packet header
30673 + memset(&ph, 0, sizeof(struct profile_header));
30674 + ph.magic = PROF_MAGIC + PROFILE_VERSION;
30675 + ph.header_size = sizeof(struct profile_header);
30676 + ph.clocks = node->clocks;
30677 + for (i = 0; i < PROFILE_MAX_THREADS; ++i) {
30678 + ph.instruction_count[i] = node->inst_count[i];
30680 + ph.profile_instructions = 0;
30681 + ph.enabled = node->enabled_threads;
30682 + ph.hrt = node->hrt;
30684 + ph.profiler_thread = node->profiler_thread;
30685 + ph.clock_freq = node->clock_freq;
30686 + ph.seq_num = profile_sequence_num++;
30687 + ph.cpu_id = node->cpu_id;
30688 + ph.perf_counters[0] = node->stats[0];
30689 + ph.perf_counters[1] = node->stats[1];
30690 + ph.perf_counters[2] = node->stats[2];
30691 + ph.perf_counters[3] = node->stats[3];
30692 + ph.ddr_freq = node->ddr_freq;
30694 + ptr = buf + sizeof(struct profile_header);
30696 + samples = (count - sizeof(struct profile_header)) / sizeof(struct profile_sample);
30697 + for (i = 0; i < samples && node->count; ++i) {
30698 + if (copy_to_user(ptr, &node->samples[node->tail], sizeof(struct profile_sample)) != 0) {
30703 + if (node->tail >= node->max_samples) {
30706 + ptr += sizeof(struct profile_sample);
30708 + ph.sample_count = i;
30709 + if (copy_to_user(buf, &ph, sizeof(struct profile_header)) != 0) {
30712 + if (ph.sample_count == 0)
30715 + return sizeof(struct profile_header) + ph.sample_count * sizeof(struct profile_sample);
30718 +static void profile_get_memory_stats(unsigned int *total_free, unsigned int *max_free)
30720 + struct list_head *p;
30721 + struct zone *zone;
30722 + unsigned int size;
30728 + * get all the free regions. In each zone, the array of free_area lists contains the first page of each frame of size 1 << order
30730 + for_each_zone(zone) {
30731 + unsigned long order, flags, i;
30733 + if (!populated_zone(zone))
30736 + if (!is_normal(zone))
30739 + spin_lock_irqsave(&zone->lock, flags);
30740 + for_each_migratetype_order(order, i) {
30741 + size = ((1 << order) << PAGE_SHIFT) >> 10;
30742 + list_for_each(p, &(zone->free_area[order].free_list[i])) {
30743 + if (size > *max_free) {
30744 + *max_free = size;
30746 + *total_free += size;
30749 + spin_unlock_irqrestore(&zone->lock, flags);
30753 +struct profile_counter_pkt profile_builtin_stats[] =
30756 + "Free memory(KB)", 0
30759 + "Max free Block(KB)", 0
30764 + * make a packet full of performance counters
30766 +static char prof_pkt[PROFILE_MAX_PACKET_SIZE];
30767 +static int profile_make_stats_packet(char *buf, int count)
30769 + char *ptr = prof_pkt;
30770 + struct profile_header_counters hdr;
30771 + int stat_count = 0;
30773 + unsigned int total_free, max_free;
30774 + int builtin_count = sizeof(profile_builtin_stats) / sizeof(struct profile_counter_pkt);
30776 + if (count > PROFILE_MAX_PACKET_SIZE) {
30777 + count = PROFILE_MAX_PACKET_SIZE;
30779 + stat_count = (count - sizeof(struct profile_header_counters)) / sizeof (struct profile_counter_pkt);
30780 + stat_count -= builtin_count;
30782 + if (stat_count <= 0) {
30786 + if (stat_count > node->num_counters) {
30787 + stat_count = node->num_counters;
30790 + hdr.magic = PROF_MAGIC_COUNTERS;
30791 + hdr.ultra_sample_time = node->clocks;
30792 + hdr.ultra_count = stat_count;
30793 + hdr.linux_sample_time = UBICOM32_IO_TIMER->sysval;
30794 + hdr.linux_count = builtin_count;
30795 + memcpy(ptr, (void *)&hdr, sizeof(struct profile_header_counters));
30796 + ptr += sizeof(struct profile_header_counters);
30799 + for (i = 0; i < stat_count; ++i) {
30800 + memcpy(ptr, (void *)(&(node->counters[i])), sizeof(struct profile_counter));
30801 + ptr += sizeof(struct profile_counter);
30805 + * built in statistics
30807 + profile_get_memory_stats(&total_free, &max_free);
30808 + profile_builtin_stats[0].value = total_free;
30809 + profile_builtin_stats[1].value = max_free;
30810 + memcpy(ptr, (void *)profile_builtin_stats, sizeof(profile_builtin_stats));
30811 + ptr += sizeof(profile_builtin_stats);
30813 + if (copy_to_user(buf, prof_pkt, ptr - prof_pkt) != 0) {
30816 + return ptr - prof_pkt;
30820 + * return a udp packet ready to send to the profiler tool
30821 + * when there are no packets left to make, return 0
30823 +static int profile_read(struct file *filp, char *buf, size_t count, loff_t *f_pos)
30830 + if (!node->enabled) {
30834 + if (!node->samples) {
30839 + if (profile_first_packet) {
30840 + result = profile_make_stats_packet(buf, count);
30841 + profile_first_packet = 0;
30843 + if (result == 0) {
30844 + result = profile_make_data_packet(buf, count);
30845 + if (result == 0) {
30846 + profile_first_packet = 1;
30854 +static int profile_release(struct inode *inode, struct file *filp)
30860 + if (node->enabled) {
30861 + node->enabled = 0;
30863 + node->tail = node->head;
30868 + profile_first_packet = 1;
30872 +static const struct file_operations profile_fops = {
30873 + .open = profile_open,
30874 + .read = profile_read,
30875 + .release = profile_release,
30878 +static int page_aligned(void *x)
30880 + return !((unsigned int)x & ((1 << PAGE_SHIFT) - 1));
30883 +static int profile_maps_open(struct inode *inode, struct file *filp)
30885 + struct rb_node *rb;
30888 + struct vm_area_struct *vma;
30889 + int type = PROFILE_MAP_TYPE_UNKNOWN;
30891 + struct list_head *p;
30892 + struct zone *zone;
30895 + * get the slab data (first so dups will show up as vmas)
30897 + slab_start = num;
30898 + num += kmem_cache_block_info("size-512", (struct kmem_cache_size_info *)&profile_pm[num], PROFILE_NUM_MAPS - num);
30899 + num += kmem_cache_block_info("size-1024", (struct kmem_cache_size_info *)&profile_pm[num], PROFILE_NUM_MAPS - num);
30900 + num += kmem_cache_block_info("size-2048", (struct kmem_cache_size_info *)&profile_pm[num], PROFILE_NUM_MAPS - num);
30901 + num += kmem_cache_block_info("size-4096", (struct kmem_cache_size_info *)&profile_pm[num], PROFILE_NUM_MAPS - num);
30902 + num += kmem_cache_block_info("size-8192", (struct kmem_cache_size_info *)&profile_pm[num], PROFILE_NUM_MAPS - num);
30904 + for (i = slab_start; i < num; ++i) {
30905 + profile_pm[i].type_size |= PROFILE_MAP_TYPE_SMALL << PROFILE_MAP_TYPE_SHIFT;
30908 + slab_start = num;
30909 + num += kmem_cache_block_info("dentry", (struct kmem_cache_size_info *)&profile_pm[num], PROFILE_NUM_MAPS - num);
30910 + num += kmem_cache_block_info("inode_cache", (struct kmem_cache_size_info *)&profile_pm[num], PROFILE_NUM_MAPS - num);
30911 + num += kmem_cache_block_info("sysfs_dir_cache", (struct kmem_cache_size_info *)&profile_pm[num], PROFILE_NUM_MAPS - num);
30912 + num += kmem_cache_block_info("proc_inode_cache", (struct kmem_cache_size_info *)&profile_pm[num], PROFILE_NUM_MAPS - num);
30914 + for (i = slab_start; i < num; ++i) {
30915 + profile_pm[i].type_size |= PROFILE_MAP_TYPE_FS << PROFILE_MAP_TYPE_SHIFT;
30919 + * get all the vma regions (allocated by mmap, most likely
30922 + down_read(&nommu_vma_sem);
30923 + for (rb = rb_first(&nommu_vma_tree); rb && num < PROFILE_NUM_MAPS; rb = rb_next(rb)) {
30924 + vma = rb_entry(rb, struct vm_area_struct, vm_rb);
30925 + profile_pm[num].start = (vma->vm_start - SDRAMSTART) >> PAGE_SHIFT;
30926 + profile_pm[num].type_size = (vma->vm_end - vma->vm_start + (1 << PAGE_SHIFT) - 1) >> PAGE_SHIFT;
30927 + flags = vma->vm_flags & 0xf;
30928 + if (flags == (VM_READ | VM_EXEC)) {
30929 + type = PROFILE_MAP_TYPE_TEXT;
30930 + } else if (flags == (VM_READ | VM_WRITE | VM_EXEC)) {
30931 + type = PROFILE_MAP_TYPE_STACK;
30932 + } else if (flags == (VM_READ | VM_WRITE)) {
30933 + type = PROFILE_MAP_TYPE_APP_DATA;
30935 + profile_pm[num].type_size |= type << PROFILE_MAP_TYPE_SHIFT;
30938 + up_read(&nommu_vma_sem);
30945 + * get all the free regions. In each zone, the array of free_area lists contains the first page of each frame of size 1 << order
30947 + for_each_zone(zone) {
30948 + unsigned long order, flags, i;
30949 + struct page *page;
30951 + if (!populated_zone(zone))
30954 + if (!is_normal(zone))
30957 + spin_lock_irqsave(&zone->lock, flags);
30958 + for_each_migratetype_order(order, i) {
30959 + list_for_each(p, &(zone->free_area[order].free_list[i])) {
30960 + page = list_entry(p, struct page, lru);
30961 + profile_pm[num].start = ((page_to_phys(page) - SDRAMSTART) >> PAGE_SHIFT) - 0x40;
30962 + profile_pm[num].type_size = (PROFILE_MAP_TYPE_FREE << PROFILE_MAP_TYPE_SHIFT) | order;
30964 + if (num >= PROFILE_NUM_MAPS) {
30965 + spin_unlock_irqrestore(&zone->lock, flags);
30970 + spin_unlock_irqrestore(&zone->lock, flags);
30974 + * get the filesystem inodes
30976 + list_for_each(p, &(super_blocks)) {
30977 + struct super_block *sb;
30978 + struct list_head *q;
30979 + if (num >= PROFILE_NUM_MAPS)
30981 + sb = list_entry(p, struct super_block, s_list);
30982 + if (page_aligned(sb)) {
30983 + profile_pm[num].start = ((unsigned int)sb - SDRAMSTART) >> PAGE_SHIFT;
30984 + profile_pm[num].type_size = (PROFILE_MAP_TYPE_FS << PROFILE_MAP_TYPE_SHIFT);
30987 + list_for_each(q, &(sb->s_inodes)) {
30988 + struct inode *in;
30989 + if (num >= PROFILE_NUM_MAPS)
30991 + in = list_entry(q, struct inode, i_sb_list);
30992 + if (page_aligned(in)) {
30993 + profile_pm[num].start = ((unsigned int)in - SDRAMSTART) >> PAGE_SHIFT;
30994 + profile_pm[num].type_size = (PROFILE_MAP_TYPE_FS << PROFILE_MAP_TYPE_SHIFT);
31001 + * get the buffer cache pages
31003 + for (i = 0; i < num_physpages && num < PROFILE_NUM_MAPS; ++i) {
31004 + if ((mem_map + i)->flags & (1 << PG_lru)) {
31006 + while ((mem_map + i)->flags & (1 << PG_lru) && i < num_physpages)
31008 + profile_pm[num].start = start;
31009 + profile_pm[num].type_size = (i - start) | (PROFILE_MAP_TYPE_CACHE << PROFILE_MAP_TYPE_SHIFT);
31014 + filp->private_data = (void *)num;
31019 + * return one packet of map data, or 0 if all maps have been returned already
31021 +static int profile_maps_read(struct file *filp, char *buf, size_t count, loff_t *f_pos)
31023 + struct profile_header_maps header;
31024 + char *p = buf + sizeof(header);
31025 + int total = (int)filp->private_data;
31027 + header.count = (count - sizeof(header)) / sizeof(struct profile_map);
31028 + if (header.count > PROFILE_MAX_MAPS) {
31029 + header.count = PROFILE_MAX_MAPS;;
31031 + if (header.count > total - *f_pos) {
31032 + header.count = total - *f_pos;
31035 + if (header.count == 0) {
31039 + header.magic = PROF_MAGIC_MAPS;
31040 + header.page_shift = PAGE_SHIFT;
31042 + if (copy_to_user(buf, &header, sizeof(header)) != 0) {
31045 + if (copy_to_user(p, (void *)&profile_pm[*f_pos], sizeof(struct profile_map) * header.count) != 0) {
31048 + *f_pos += header.count;
31050 + return sizeof(header) + sizeof(struct profile_map) * header.count;
31053 +static int profile_maps_release(struct inode *inode, struct file *filp)
31058 +static const struct file_operations profile_maps_fops = {
31059 + .open = profile_maps_open,
31060 + .read = profile_maps_read,
31061 + .release = profile_maps_release,
31064 +static int profile_rate_show(struct seq_file *m, void *v)
31067 + seq_printf(m, "%d samples per second. %d virtual counters.\n", node->rate, node->num_counters);
31069 + seq_printf(m, "Profiler is not initialized.\n");
31074 +static int profile_rate_open(struct inode *inode, struct file *filp)
31076 + return single_open(filp, profile_rate_show, NULL);
31079 +static int profile_rate_write(struct file *filp, const char *buf, size_t len, loff_t *off)
31085 +static const struct file_operations profile_rate_fops = {
31086 + .open = profile_rate_open,
31087 + .read = seq_read,
31088 + .llseek = seq_lseek,
31089 + .release = single_release,
31090 + .write = profile_rate_write,
31093 +int ubi32_profile_init_module(void)
31095 + struct proc_dir_entry *pdir;
31098 + * find the device
31100 + node = (struct profilenode *)devtree_find_node("profiler");
31102 + printk(KERN_INFO "Profiler does not exist.\n");
31107 + * allocate the sample buffer
31109 + node->max_samples = PROFILE_MAX_SAMPLES;
31110 + node->samples = kmalloc(node->max_samples * sizeof(struct profile_sample), GFP_KERNEL);
31111 + if (!node->samples) {
31112 + printk(KERN_INFO "Profiler sample buffer kmalloc failed.\n");
31117 + * connect to the file system
31119 + pdir = proc_mkdir("profile", NULL);
31123 + if (!proc_create("data", 0, pdir, &profile_fops)) {
31126 + if (!proc_create("rate", 0, pdir, &profile_rate_fops)) {
31129 + if (!proc_create("maps", 0, pdir, &profile_maps_fops)) {
31136 +module_init(ubi32_profile_init_module);
31138 +MODULE_AUTHOR("David Fotland");
31139 +MODULE_LICENSE("GPL");
31141 +++ b/arch/ubicom32/mach-common/profile.h
31144 + * arch/ubicom32/mach-common/profile.h
31145 + * Private data for the profile module
31147 + * (C) Copyright 2009, Ubicom, Inc.
31149 + * This file is part of the Ubicom32 Linux Kernel Port.
31151 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
31152 + * it and/or modify it under the terms of the GNU General Public License
31153 + * as published by the Free Software Foundation, either version 2 of the
31154 + * License, or (at your option) any later version.
31156 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
31157 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
31158 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
31159 + * the GNU General Public License for more details.
31161 + * You should have received a copy of the GNU General Public License
31162 + * along with the Ubicom32 Linux Kernel Port. If not,
31163 + * see <http://www.gnu.org/licenses/>.
31165 + * Ubicom32 implementation derived from (with many thanks):
31171 +#include <linux/types.h>
31172 +#include <asm/devtree.h>
31173 +#include "profpkt.h"
31175 +#ifndef _PROFILE_H_
31176 +#define _PROFILE_H_
31178 +#define PROFILE_MAX_THREADS 16
31179 +#define PROFILE_MAX_SAMPLES 1024
31181 +struct profile_sample;
31182 +struct oprofile_sample;
31185 + * values chosen so all counter values fit in a single UDP packet
31187 +#define PROFILE_NODE_MAX_COUNTERS 32
31189 +struct profile_counter {
31190 + char name[PROFILE_COUNTER_NAME_LENGTH];
31191 + unsigned int value;
31194 +struct profilenode {
31195 + struct devtree_node dn;
31196 + volatile u32_t enabled; /* Is the profiler enabled to take samples? */
31197 + volatile u32_t busy; /* set when the samples are being read by the driver */
31198 + volatile u32_t rate; /* What is the sampling rate? */
31199 + volatile u32_t enabled_threads; /* which threads were enabled at the last sample time */
31200 + volatile u32_t hrt; /* HRT threads */
31201 + volatile u32_t profiler_thread; /* thread running the profile sampler */
31202 + volatile u32_t clocks; /* system clock timer at last sample */
31203 + volatile u32_t clock_freq; /* clock frequency in Hz */
31204 + volatile u32_t ddr_freq; /* memory frequency */
31205 + volatile u32_t cpu_id; /* chip_id register */
31206 + volatile u32_t inst_count[PROFILE_MAX_THREADS]; /* sampled instruction counts at most recent sample */
31207 + volatile u32_t stats[4]; /* contents of the cache statistics counters */
31208 + volatile u16_t head; /* sample taker puts samples here */
31209 + volatile u16_t tail; /* packet filler takes samples here */
31210 + volatile u16_t count; /* number of valid samples */
31211 + volatile u16_t max_samples; /* how many samples can be in the samples array */
31212 + struct profile_sample *samples; /* samples array allocated by the linux driver */
31213 + volatile u32_t num_counters; /* how many registered performance counters */
31214 + volatile struct profile_counter counters[PROFILE_NODE_MAX_COUNTERS];
31216 + /* unimplemented interface for future oprofile work */
31217 + volatile u16_t oprofile_head; /* sample taker puts samples here */
31218 + volatile u16_t oprofile_tail; /* packet filler takes samples here */
31219 + volatile u16_t oprofile_count; /* how many oprofile sampels are are in use */
31220 + volatile u16_t oprofile_max_samples; /* samples array size for oprofile samples */
31221 + struct oprofile_sample *oprofile_samples; /* oprofile sample buffer */
31226 +++ b/arch/ubicom32/mach-common/profpkt.h
31230 + * arch/ubicom32/mach-common/profpkt.c
31231 + * Ubicom32 Profiler packet formats for communication between the linux proc driver and the profiler display tool
31233 + * (C) Copyright 2009, Ubicom, Inc.
31235 + * This file is part of the Ubicom32 Linux Kernel Port.
31237 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
31238 + * it and/or modify it under the terms of the GNU General Public License
31239 + * as published by the Free Software Foundation, either version 2 of the
31240 + * License, or (at your option) any later version.
31242 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
31243 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
31244 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
31245 + * the GNU General Public License for more details.
31247 + * You should have received a copy of the GNU General Public License
31248 + * along with the Ubicom32 Linux Kernel Port. If not,
31249 + * see <http://www.gnu.org/licenses/>.
31252 +#define PROFILE_PORT 51080
31253 +#define PROFILE_POSIX_NAME_LENGTH 32
31256 + * profile UDP packet format for communicating between ip3k and host
31258 + * every packet starts with a header, followed by samples.
31259 + * samples are only taken for non-hrt threads that are
31262 +#define PROF_MAGIC 0x3ea0
31263 +#define PROF_MAGIC_COUNTERS 0x9ea0
31264 +#define PROF_MAGIC_MAPS 0xaea0
31267 + * Versions (31 max):
31268 + * 1 to 4 were before 6.0 release, development versions
31269 + * 5 was forward compatible version, shipped with 6.0 and 6.1
31270 + * 6 adds heap packets, and clock_freq to header, shipped with 6.2
31271 + * 7 adds a sequence numbers to check for dropped packets, shipped with 6.3.5
31272 + * 8 adds mqueue timing information, shipped with 6.3.5
31273 + * 9 adds sdram heap size information, shipped with 6.4
31274 + * 10 adds heapmem heap callers and long latency stack traces. shipped with 6.4
31275 + * 11 adds support for Mars (IP5K). shipped with 6.10
31276 + * 12 adds more support for Mars. Shipped with 7.0
31277 + * 13 adds per sample latency measurement. Shipped with 7.2
31278 + * 14 changes the heap format and adds a string packet. Shipped with 7.4
31279 + * 15 adds dsr stats and posix. shipped with 7.6
31280 + * 16 corrects maximum packet count for Ares. ships with 7.9
31281 + * 17 adds a5 register value to sample
31284 +#define PROFILE_VERSION 17
31285 +#define PROFILE_MAX_PACKET_SIZE 1440
31287 +#define PROFILE_MAX_THREADS 16
31290 + * each packet starts with a profile_header, then sample_count samples
31291 + * samples are gprof samples of pc, the return address, condition codes, and
31294 +struct profile_header {
31295 + u16_t magic; /* magic number and version */
31296 + u8_t header_size; /* number of bytes in profile header */
31297 + u8_t sample_count; /* number of samples in the packet */
31298 + u32_t clocks; /* clock counter value */
31299 + u32_t instruction_count[PROFILE_MAX_THREADS];
31300 + /* instructions executed per thread */
31301 + u32_t profile_instructions; /* instructions executed by profiler mainline */
31302 + u16_t enabled; /* which threads are enabled */
31303 + u16_t hrt; /* which threads are hrt */
31304 + u16_t high; /* which threads are high priority */
31305 + u16_t profiler_thread; /* which thread runs the profiler */
31306 + u32_t heap_free; /* current free on-cihp heap space in bytes */
31307 + u32_t heap_low_water; /* on-chip heap low water mark */
31308 + u32_t netpage_free; /* number of free on-chip net pages */
31309 + u32_t netpage_low_water; /* low water mark on free on-chip netpages */
31310 + u32_t min_sp[PROFILE_MAX_THREADS];
31311 + /* stack pointer values per thread */
31312 + u32_t clock_freq; /* clock frequency (Hz) of system being analyzed */
31313 + u32_t seq_num; /* to detect dropped profiler packets */
31314 + u32_t timing_sequence; /* sample number since boot */
31315 + u32_t timing_interval; /* second per sample timing interval */
31316 + u32_t timing_worst_time; /* duration of longest finction called, in core clocks */
31317 + u32_t timing_function; /* address of longest function */
31318 + u32_t timing_average; /* average time of all functions in last interval */
31319 + u32_t timing_count; /* number of functions called in last interval */
31320 + u32_t extheap_free; /* current free extmem heap space in bytes */
31321 + u32_t extheap_low_water; /* extmem heap low water mark */
31322 + u32_t cpu_id; /* CHIP_ID register contents */
31323 + u32_t perf_counters[4]; /* contents of the CPU performance counters */
31324 + u8_t perf_config[4]; /* what is being counted */
31325 + u32_t ddr_freq; /* DDR clock frequency */
31326 + u32_t extnetpage_free; /* number of free off chip net pages */
31327 + u32_t extnetpage_low_water; /* low water mark on off-chip free netpages */
31328 + u32_t dsr_max_latency; /* max time to process a dsr interrupt, in clocks, since last packet */
31329 + u32_t dsr_ave_latency; /* average dsr latency over last DSR_STATS_RECENT_COUNT interrupts */
31330 + u32_t dsr_count; /* number of dsr interrupts since last packet */
31333 +struct profile_header_counters {
31335 + u16_t ultra_count; /* how many ultra counters follow this */
31336 + u32_t ultra_sample_time; /* in chip clocks */
31337 + u32_t linux_count; /* how many linux counters follow this */
31338 + u32_t linux_sample_time;
31342 + * values chosen so all counter values fit in a single 1400 byte UDP packet
31344 +#define PROFILE_COUNTER_NAME_LENGTH 20
31345 +#define PROFILE_MAX_COUNTERS ((PROFILE_MAX_PACKET_SIZE - sizeof(struct profile_header_counters)) / (PROFILE_COUNTER_NAME_LENGTH + 4))
31347 +struct profile_counter_pkt {
31348 + char name[PROFILE_COUNTER_NAME_LENGTH];
31349 + unsigned int value;
31353 + * send memory maps from linux to profiler tool
31356 +struct profile_header_maps {
31359 + u32_t page_shift;
31362 +#define PROFILE_MAP_NUM_TYPES 32
31364 +/* types 0-15: size field is order. True size is 2^order */
31365 +#define PROFILE_MAP_TYPE_UNKNOWN 0
31366 +#define PROFILE_MAP_TYPE_FREE 1
31367 +#define PROFILE_MAP_TYPE_SMALL 2
31368 +#define PROFILE_MAP_TYPE_FS 3
31369 +/* types 16-31: size field is pages. True size is (1 << PAGE_SHIFT) * size */
31370 +#define PROFILE_MAP_SIZE_TYPE 16
31371 +#define PROFILE_MAP_TYPE_TEXT 16
31372 +#define PROFILE_MAP_TYPE_STACK 17
31373 +#define PROFILE_MAP_TYPE_APP_DATA 18
31374 +#define PROFILE_MAP_TYPE_CACHE 19
31375 +#define PROFILE_MAP_RESERVED 24
31377 +#define PROFILE_MAP_TYPE_SHIFT 11
31378 +#define PROFILE_MAP_SIZE_MASK 0x7ff
31380 +struct profile_map {
31381 + u16_t start; /* start page number of segment, relative to start of DRAM */
31382 + u16_t type_size; /* type (4 bits) of the segment and size in pages (12 bits) */
31385 +#define PROFILE_MAX_MAPS (PROFILE_MAX_PACKET_SIZE - sizeof(struct profile_header_maps)) / sizeof(struct profile_map)
31387 +++ b/arch/ubicom32/mach-common/ring_tio.c
31390 + * arch/ubicom32/mach-common/ring_tio.c
31391 + * Generic initialization for UIO Ubicom32 Ring
31393 + * (C) Copyright 2009, Ubicom, Inc.
31395 + * This file is part of the Ubicom32 Linux Kernel Port.
31397 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
31398 + * it and/or modify it under the terms of the GNU General Public License
31399 + * as published by the Free Software Foundation, either version 2 of the
31400 + * License, or (at your option) any later version.
31402 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
31403 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
31404 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
31405 + * the GNU General Public License for more details.
31407 + * You should have received a copy of the GNU General Public License
31408 + * along with the Ubicom32 Linux Kernel Port. If not,
31409 + * see <http://www.gnu.org/licenses/>.
31412 +#include <linux/platform_device.h>
31413 +#include <linux/types.h>
31415 +#include <asm/devtree.h>
31416 +#include <asm/ring_tio.h>
31418 +static const char *ring_tio_driver_name = "uio_ubicom32ring";
31421 + * The number of ring_tio's currently allocated, used for .id
31423 +static int __initdata ring_tio_count;
31426 + * The maximum number of resources that the ring_tio will have.
31427 + * Currently 3, a register space, and up to 2 interrupts.
31429 +#define RING_TIO_MAX_RESOURCES 3
31433 + * Checks the device tree and instantiates the driver if found
31435 +void __init ring_tio_init(const char *node_name)
31437 + struct platform_device *pdev;
31438 + struct resource *res;
31439 + int resource_idx = 0;
31440 + struct ring_tio_node *ring_node;
31443 + * Check the device tree for the ring_tio
31445 + ring_node = (struct ring_tio_node *)devtree_find_node(node_name);
31446 + if (!ring_node) {
31447 + printk(KERN_WARNING "Ring TIO '%s' not found\n", node_name);
31451 + if (ring_node->version != RING_TIO_NODE_VERSION) {
31452 + printk(KERN_WARNING "ring_tio not compatible\n");
31457 + * Dynamically create the platform_device structure and resources
31459 + pdev = kzalloc(sizeof(struct platform_device), GFP_KERNEL);
31461 + printk(KERN_WARNING "ring_tio could not alloc pdev\n");
31465 + res = kzalloc(sizeof(struct resource) * RING_TIO_MAX_RESOURCES,
31469 + printk(KERN_WARNING "ring_tio could not alloc res\n");
31473 + pdev->name = ring_tio_driver_name;
31474 + pdev->id = ring_tio_count++;
31475 + pdev->resource = res;
31478 + * Fill in the resources and platform data from devtree information
31480 + res[resource_idx].start = (u32_t)(ring_node->regs);
31481 + res[resource_idx].end = (u32_t)(ring_node->regs);
31482 + res[resource_idx].flags = IORESOURCE_MEM;
31485 + if (ring_node->dn.sendirq != 0xFF) {
31486 + res[resource_idx].start = ring_node->dn.sendirq;
31487 + res[resource_idx].flags = IORESOURCE_IRQ;
31491 + if (ring_node->dn.recvirq != 0xFF) {
31492 + res[resource_idx].start = ring_node->dn.recvirq;
31493 + res[resource_idx].flags = IORESOURCE_IRQ;
31496 + pdev->num_resources = resource_idx;
31498 + printk(KERN_INFO "RingTIO.%d '%s' found irq=%d/%d regs=%p pdev=%p/%p\n",
31499 + ring_tio_count - 1, node_name, ring_node->dn.sendirq,
31500 + ring_node->dn.recvirq, ring_node->regs, pdev, res);
31503 + * Try to get the device registered
31505 + pdev->dev.platform_data = (void *)node_name;
31506 + if (platform_device_register(pdev) < 0) {
31507 + printk(KERN_WARNING "Ring failed to register\n");
31513 +++ b/arch/ubicom32/mach-common/switch-bcm539x.c
31516 + * arch/ubicom32/mach-common/switch-bcm539x.c
31517 + * BCM539X switch driver, SPI mode
31519 + * (C) Copyright 2009, Ubicom, Inc.
31521 + * This file is part of the Ubicom32 Linux Kernel Port.
31523 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
31524 + * it and/or modify it under the terms of the GNU General Public License
31525 + * as published by the Free Software Foundation, either version 2 of the
31526 + * License, or (at your option) any later version.
31528 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
31529 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
31530 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
31531 + * the GNU General Public License for more details.
31533 + * You should have received a copy of the GNU General Public License
31534 + * along with the Ubicom32 Linux Kernel Port. If not,
31535 + * see <http://www.gnu.org/licenses/>.
31537 + * Ubicom32 implementation derived from (with many thanks):
31543 +#include <linux/platform_device.h>
31544 +#include <linux/spi/spi.h>
31545 +#include <linux/gpio.h>
31546 +#include <linux/delay.h>
31547 +#include <linux/mii.h>
31549 +#include <asm/switch-dev.h>
31550 +#include <asm/ubicom32-spi-gpio.h>
31551 +#include "switch-core.h"
31552 +#include "switch-bcm539x-reg.h"
31554 +#define DRIVER_NAME "bcm539x-spi"
31555 +#define DRIVER_VERSION "1.0"
31557 +#undef BCM539X_DEBUG
31558 +#define BCM539X_SPI_RETRIES 100
31560 +struct bcm539x_data {
31561 + struct switch_device *switch_dev;
31564 + * Our private data
31566 + struct spi_device *spi;
31567 + struct switch_core_platform_data *pdata;
31570 + * Last page we accessed
31581 + * bcm539x_wait_status
31582 + * Waits for the specified bit in the status register to be set/cleared.
31584 +static int bcm539x_wait_status(struct bcm539x_data *bd, u8_t mask, int set)
31591 + txbuf[0] = BCM539X_CMD_READ;
31592 + txbuf[1] = BCM539X_GLOBAL_SPI_STATUS;
31593 + for (i = 0; i < BCM539X_SPI_RETRIES; i++) {
31594 + ret = spi_write_then_read(bd->spi, txbuf, 2, &rxbuf, 1);
31596 + if ((set && rxbuf) || (!set && !rxbuf)) {
31606 + * bcm539x_set_page
31607 + * Sets the register page for access (only if necessary)
31609 +static int bcm539x_set_page(struct bcm539x_data *bd, u8_t page)
31613 + if (page == bd->last_page) {
31617 + bd->last_page = page;
31619 + txbuf[0] = BCM539X_CMD_WRITE;
31620 + txbuf[1] = BCM539X_GLOBAL_PAGE;
31623 + return spi_write(bd->spi, txbuf, 3);
31627 + * bcm539x_write_bytes
31628 + * Writes a number of bytes to a given page and register
31630 +static int bcm539x_write_bytes(struct bcm539x_data *bd, u8_t page,
31631 + u8_t reg, void *buf, u8_t len)
31636 + txbuf = kmalloc(2 + len, GFP_KERNEL);
31642 + * Make sure the chip has finished processing our previous request
31644 + ret = bcm539x_wait_status(bd, BCM539X_GLOBAL_SPI_ST_SPIF, 0);
31652 + ret = bcm539x_set_page(bd, page);
31660 + txbuf[0] = BCM539X_CMD_WRITE;
31662 + memcpy(&txbuf[2], buf, len);
31664 +#ifdef BCM539X_DEBUG
31667 + printk("write page %02x reg %02x len=%d buf=", page, reg, len);
31668 + for (i = 0; i < len + 2; i++) {
31669 + printk("%02x ", txbuf[i]);
31675 + ret = spi_write(bd->spi, txbuf, 2 + len);
31683 + * bcm539x_write_32
31684 + * Writes 32 bits of data to the given page and register
31686 +static inline int bcm539x_write_32(struct bcm539x_data *bd, u8_t page,
31687 + u8_t reg, u32_t data)
31689 + data = cpu_to_le32(data);
31690 + return bcm539x_write_bytes(bd, page, reg, &data, 4);
31694 + * bcm539x_write_16
31695 + * Writes 16 bits of data to the given page and register
31697 +static inline int bcm539x_write_16(struct bcm539x_data *bd, u8_t page,
31698 + u8_t reg, u16_t data)
31700 + data = cpu_to_le16(data);
31701 + return bcm539x_write_bytes(bd, page, reg, &data, 2);
31705 + * bcm539x_write_8
31706 + * Writes 8 bits of data to the given page and register
31708 +static inline int bcm539x_write_8(struct bcm539x_data *bd, u8_t page,
31709 + u8_t reg, u8_t data)
31711 + return bcm539x_write_bytes(bd, page, reg, &data, 1);
31715 + * bcm539x_read_bytes
31716 + * Reads a number of bytes from a given page and register
31718 +static int bcm539x_read_bytes(struct bcm539x_data *bd, u8_t page,
31719 + u8_t reg, void *buf, u8_t len)
31725 + * (1) Make sure the chip has finished processing our previous request
31727 + ret = bcm539x_wait_status(bd, BCM539X_GLOBAL_SPI_ST_SPIF, 0);
31733 + * (2) Set the page
31735 + ret = bcm539x_set_page(bd, page);
31741 + * (3) Kick off the register read
31743 + txbuf[0] = BCM539X_CMD_READ;
31745 + ret = spi_write_then_read(bd->spi, txbuf, 2, txbuf, 1);
31751 + * (4) Wait for RACK
31753 + ret = bcm539x_wait_status(bd, BCM539X_GLOBAL_SPI_ST_RACK, 1);
31759 + * (5) Read the data
31761 + txbuf[0] = BCM539X_CMD_READ;
31762 + txbuf[1] = BCM539X_GLOBAL_SPI_DATA0;
31764 + ret = spi_write_then_read(bd->spi, txbuf, 2, buf, len);
31766 +#ifdef BCM539X_DEBUG
31769 + printk("read page %02x reg %02x len=%d rxbuf=",
31771 + for (i = 0; i < len; i++) {
31772 + printk("%02x ", ((u8_t *)buf)[i]);
31782 + * bcm539x_read_32
31783 + * Reads an 32 bit number from a given page and register
31785 +static int bcm539x_read_32(struct bcm539x_data *bd, u8_t page,
31786 + u8_t reg, u32_t *buf)
31788 + int ret = bcm539x_read_bytes(bd, page, reg, buf, 4);
31789 + *buf = le32_to_cpu(*buf);
31794 + * bcm539x_read_16
31795 + * Reads an 16 bit number from a given page and register
31797 +static int bcm539x_read_16(struct bcm539x_data *bd, u8_t page,
31798 + u8_t reg, u16_t *buf)
31800 + int ret = bcm539x_read_bytes(bd, page, reg, buf, 2);
31801 + *buf = le16_to_cpu(*buf);
31807 + * Reads an 8 bit number from a given page and register
31809 +static int bcm539x_read_8(struct bcm539x_data *bd, u8_t page,
31810 + u8_t reg, u8_t *buf)
31812 + return bcm539x_read_bytes(bd, page, reg, buf, 1);
31816 + * bcm539x_set_mode
31818 +static int bcm539x_set_mode(struct bcm539x_data *bd, int state)
31823 + ret = bcm539x_read_8(bd, PAGE_PORT_TC, REG_CTRL_MODE, &buf);
31828 + buf &= ~(1 << 1);
31829 + buf |= state ? (1 << 1) : 0;
31831 + ret = bcm539x_write_8(bd, PAGE_PORT_TC, REG_CTRL_MODE, buf);
31836 + * bcm539x_handle_reset
31838 +static int bcm539x_handle_reset(struct switch_device *dev, char *buf, int inst)
31840 + struct bcm539x_data *bd =
31841 + (struct bcm539x_data *)switch_get_drvdata(dev);
31844 + ret = bcm539x_write_8(bd, PAGE_PORT_TC, REG_CTRL_SRST,
31845 + (1 << 7) | (1 << 4));
31852 + ret = bcm539x_write_8(bd, PAGE_PORT_TC, REG_CTRL_SRST, 0);
31857 + * bcm539x_handle_vlan_ports_read
31859 +static int bcm539x_handle_vlan_ports_read(struct switch_device *dev,
31860 + char *buf, int inst)
31862 + struct bcm539x_data *bd =
31863 + (struct bcm539x_data *)switch_get_drvdata(dev);
31870 + ret = bcm539x_write_16(bd, PAGE_VTBL, REG_VTBL_INDX_5395, inst);
31875 + ret = bcm539x_write_8(bd, PAGE_VTBL, REG_VTBL_ACCESS_5395,
31882 + * Wait for completion
31884 + for (j = 0; j < BCM539X_SPI_RETRIES; j++) {
31885 + ret = bcm539x_read_8(bd, PAGE_VTBL, REG_VTBL_ACCESS_5395,
31890 + if (!(rxbuf8 & (1 << 7))) {
31895 + if (j == BCM539X_SPI_RETRIES) {
31900 + * Read the table entry
31902 + ret = bcm539x_read_32(bd, PAGE_VTBL, REG_VTBL_ENTRY_5395, &rxbuf32);
31907 + for (j = 0; j < 9; j++) {
31908 + if (rxbuf32 & (1 << j)) {
31910 + len += sprintf(buf + len, "%d", j);
31911 + if (rxbuf32 & (1 << (j + 9))) {
31912 + buf[len++] = 'u';
31914 + buf[len++] = 't';
31916 + ret = bcm539x_read_16(bd, PAGE_VLAN,
31917 + REG_VLAN_PTAG0 + (j << 1),
31922 + if (rxbuf16 == inst) {
31923 + buf[len++] = '*';
31925 + buf[len++] = '\t';
31929 + len += sprintf(buf + len, "\n");
31936 + * bcm539x_handle_vlan_ports_write
31938 +static int bcm539x_handle_vlan_ports_write(struct switch_device *dev,
31939 + char *buf, int inst)
31941 + struct bcm539x_data *bd =
31942 + (struct bcm539x_data *)switch_get_drvdata(dev);
31952 + switch_parse_vlan_ports(dev, buf, &untag, &ports, &def);
31954 +#ifdef BCM539X_DEBUG
31955 + printk(KERN_DEBUG "'%s' inst=%d untag=%08x ports=%08x def=%08x\n",
31956 + buf, inst, untag, ports, def);
31964 + * Change default vlan tag
31966 + for (j = 0; j < 9; j++) {
31967 + if ((untag | def) & (1 << j)) {
31968 + ret = bcm539x_write_16(bd, PAGE_VLAN,
31969 + REG_VLAN_PTAG0 + (j << 1),
31977 + if (!(dev->port_mask[0] & (1 << j))) {
31982 + * Remove any ports which are not listed anymore as members of
31985 + ret = bcm539x_read_16(bd, PAGE_VLAN,
31986 + REG_VLAN_PTAG0 + (j << 1), &rxbuf16);
31990 + if (rxbuf16 == inst) {
31991 + ret = bcm539x_write_16(bd, PAGE_VLAN,
31992 + REG_VLAN_PTAG0 + (j << 1), 0);
32000 + * Write the VLAN table
32002 + ret = bcm539x_write_16(bd, PAGE_VTBL, REG_VTBL_INDX_5395, inst);
32007 + ret = bcm539x_write_32(bd, PAGE_VTBL, REG_VTBL_ENTRY_5395,
32008 + (untag << 9) | ports);
32013 + ret = bcm539x_write_8(bd, PAGE_VTBL, REG_VTBL_ACCESS_5395,
32020 + * Wait for completion
32022 + for (j = 0; j < BCM539X_SPI_RETRIES; j++) {
32023 + ret = bcm539x_read_bytes(bd, PAGE_VTBL, REG_VTBL_ACCESS_5395,
32028 + if (!(rxbuf8 & (1 << 7))) {
32033 + return (j < BCM539X_SPI_RETRIES) ? 0 : -EIO;
32037 + * Handlers for <this_driver>/vlan/<vlan_id>
32039 +static const struct switch_handler bcm539x_switch_handlers_vlan_dir[] = {
32042 + .read = bcm539x_handle_vlan_ports_read,
32043 + .write = bcm539x_handle_vlan_ports_write,
32050 + * bcm539x_handle_vlan_delete_write
32052 +static int bcm539x_handle_vlan_delete_write(struct switch_device *dev,
32053 + char *buf, int inst)
32055 + struct bcm539x_data *bd =
32056 + (struct bcm539x_data *)switch_get_drvdata(dev);
32063 + vid = simple_strtoul(buf, NULL, 0);
32069 + * Disable this VLAN
32071 + * Go through the port-based vlan registers and clear the appropriate
32074 + for (j = 0; j < 9; j++) {
32076 + ret = bcm539x_read_16(bd, PAGE_VLAN, REG_VLAN_PTAG0 + (j << 1),
32081 + if (rxbuf16 == vid) {
32083 + ret = bcm539x_write_16(bd, PAGE_VLAN,
32084 + REG_VLAN_PTAG0 + (j << 1),
32093 + * Write the VLAN table
32096 + ret = bcm539x_write_16(bd, PAGE_VTBL, REG_VTBL_INDX_5395, txbuf);
32102 + ret = bcm539x_write_32(bd, PAGE_VTBL, REG_VTBL_ENTRY_5395, txbuf);
32107 + txbuf = (1 << 7) | (0);
32108 + ret = bcm539x_write_8(bd, PAGE_VTBL, REG_VTBL_ACCESS_5395, txbuf);
32114 + * Wait for completion
32116 + for (j = 0; j < BCM539X_SPI_RETRIES; j++) {
32117 + ret = bcm539x_read_bytes(bd, PAGE_VTBL, REG_VTBL_ACCESS_5395,
32122 + if (!(rxbuf8 & (1 << 7))) {
32127 + if (j == BCM539X_SPI_RETRIES) {
32131 + return switch_remove_vlan_dir(dev, vid);
32135 + * bcm539x_handle_vlan_create_write
32137 +static int bcm539x_handle_vlan_create_write(struct switch_device *dev,
32138 + char *buf, int inst)
32142 + vid = simple_strtoul(buf, NULL, 0);
32147 + return switch_create_vlan_dir(dev, vid,
32148 + bcm539x_switch_handlers_vlan_dir);
32152 + * bcm539x_handle_enable_read
32154 +static int bcm539x_handle_enable_read(struct switch_device *dev,
32155 + char *buf, int inst)
32157 + struct bcm539x_data *bd =
32158 + (struct bcm539x_data *)switch_get_drvdata(dev);
32162 + ret = bcm539x_read_8(bd, PAGE_PORT_TC, REG_CTRL_MODE, &rxbuf);
32166 + rxbuf = (rxbuf & (1 << 1)) ? 1 : 0;
32168 + return sprintf(buf, "%d\n", rxbuf);
32172 + * bcm539x_handle_enable_write
32174 +static int bcm539x_handle_enable_write(struct switch_device *dev,
32175 + char *buf, int inst)
32177 + struct bcm539x_data *bd =
32178 + (struct bcm539x_data *)switch_get_drvdata(dev);
32180 + return bcm539x_set_mode(bd, buf[0] == '1');
32184 + * bcm539x_handle_enable_vlan_read
32186 +static int bcm539x_handle_enable_vlan_read(struct switch_device *dev,
32187 + char *buf, int inst)
32189 + struct bcm539x_data *bd =
32190 + (struct bcm539x_data *)switch_get_drvdata(dev);
32194 + ret = bcm539x_read_8(bd, PAGE_VLAN, REG_VLAN_CTRL0, &rxbuf);
32198 + rxbuf = (rxbuf & (1 << 7)) ? 1 : 0;
32200 + return sprintf(buf, "%d\n", rxbuf);
32204 + * bcm539x_handle_enable_vlan_write
32206 +static int bcm539x_handle_enable_vlan_write(struct switch_device *dev,
32207 + char *buf, int inst)
32209 + struct bcm539x_data *bd =
32210 + (struct bcm539x_data *)switch_get_drvdata(dev);
32214 + * disable 802.1Q VLANs
32216 + if (buf[0] != '1') {
32217 + ret = bcm539x_write_8(bd, PAGE_VLAN, REG_VLAN_CTRL0, 0);
32222 + * enable 802.1Q VLANs
32224 + * Enable 802.1Q | IVL learning
32226 + ret = bcm539x_write_8(bd, PAGE_VLAN, REG_VLAN_CTRL0,
32227 + (1 << 7) | (3 << 5));
32233 + * RSV multicast fwd | RSV multicast chk
32235 + ret = bcm539x_write_8(bd, PAGE_VLAN, REG_VLAN_CTRL1,
32236 + (1 << 2) | (1 << 3));
32242 + * Drop invalid VID
32244 + ret = bcm539x_write_16(bd, PAGE_VLAN, REG_VLAN_CTRL3, 0x00FF);
32253 + * bcm539x_handle_port_enable_read
32255 +static int bcm539x_handle_port_enable_read(struct switch_device *dev,
32256 + char *buf, int inst)
32258 + return sprintf(buf, "%d\n", 1);
32262 + * bcm539x_handle_port_enable_write
32264 +static int bcm539x_handle_port_enable_write(struct switch_device *dev,
32265 + char *buf, int inst)
32270 + if (!(dev->port_mask[0] & (1 << inst))) {
32274 + if (buf[0] != '1') {
32275 + printk(KERN_WARNING "switch port[%d] disabling is not supported\n", inst);
32281 + * bcm539x_handle_port_state_read
32283 +static int bcm539x_handle_port_state_read(struct switch_device *dev,
32284 + char *buf, int inst)
32286 + struct bcm539x_data *bd =
32287 + (struct bcm539x_data *)switch_get_drvdata(dev);
32294 + if (!(dev->port_mask[0] & (1 << inst))) {
32299 + * check PHY link state - CPU port (port 8) is always up
32301 + ret = bcm539x_read_16(bd, PAGE_STATUS, REG_LINK_STATUS, &link);
32305 + link |= (1 << 8);
32307 + return sprintf(buf, "%d\n", (link & (1 << inst)) ? 1 : 0);
32311 + * bcm539x_handle_port_media_read
32313 +static int bcm539x_handle_port_media_read(struct switch_device *dev,
32314 + char *buf, int inst)
32316 + struct bcm539x_data *bd =
32317 + (struct bcm539x_data *)switch_get_drvdata(dev);
32319 + u16_t link, duplex;
32325 + if (!(dev->port_mask[0] & (1 << inst))) {
32330 + * check PHY link state first - CPU port (port 8) is always up
32332 + ret = bcm539x_read_16(bd, PAGE_STATUS, REG_LINK_STATUS, &link);
32336 + link |= (1 << 8);
32338 + if (!(link & (1 << inst))) {
32339 + return sprintf(buf, "UNKNOWN\n");
32343 + * get link speeda dn duplex - CPU port (port 8) is 1000/full
32345 + ret = bcm539x_read_32(bd, PAGE_STATUS, 4, &speed);
32349 + speed |= (2 << 16);
32350 + speed = (speed >> (2 * inst)) & 3;
32352 + ret = bcm539x_read_16(bd, PAGE_STATUS, 8, &duplex);
32356 + duplex |= (1 << 8);
32357 + duplex = (duplex >> inst) & 1;
32359 + return sprintf(buf, "%d%cD\n",
32360 + (speed == 0) ? 10 : ((speed == 1) ? 100 : 1000),
32361 + duplex ? 'F' : 'H');
32365 + * bcm539x_handle_port_meida_write
32367 +static int bcm539x_handle_port_meida_write(struct switch_device *dev,
32368 + char *buf, int inst)
32370 + struct bcm539x_data *bd =
32371 + (struct bcm539x_data *)switch_get_drvdata(dev);
32373 + u16_t ctrl_word, local_cap, local_giga_cap;
32376 + * validate port (not for CPU port)
32378 + if (!(dev->port_mask[0] & (1 << inst) & ~(1 << 8))) {
32383 + * Get the maximum capability from status
32384 + * SPI reg[0x00] = PHY[0x0] --- MII control
32385 + * SPI reg[0x08] = PHY[0x4] --- MII local capability
32386 + * SPI reg[0x12] = PHY[0x9] --- GMII control
32388 + ret = bcm539x_read_16(bd, REG_MII_PAGE + inst, (MII_ADVERTISE << 1), &local_cap);
32392 + ret = bcm539x_read_16(bd, REG_MII_PAGE + inst, (MII_CTRL1000 << 1), &local_giga_cap);
32397 + /* Configure to the requested speed */
32398 + if (strncmp(buf, "1000FD", 6) == 0) {
32400 + local_cap &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL);
32401 + local_cap &= ~(ADVERTISE_100HALF | ADVERTISE_100FULL);
32402 + local_giga_cap |= (ADVERTISE_1000HALF | ADVERTISE_1000FULL);
32404 + } else if (strncmp(buf, "100FD", 5) == 0) {
32406 + local_cap &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL);
32407 + local_cap |= (ADVERTISE_100HALF | ADVERTISE_100FULL);
32408 + local_giga_cap &= ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL);
32410 + local_cap &= ~(ADVERTISE_100HALF);
32411 + } else if (strncmp(buf, "100HD", 5) == 0) {
32413 + local_cap &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL);
32414 + local_cap |= (ADVERTISE_100HALF | ADVERTISE_100FULL);
32415 + local_giga_cap &= ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL);
32417 + local_cap &= ~(ADVERTISE_100FULL);
32418 + } else if (strncmp(buf, "10FD", 4) == 0) {
32420 + local_cap |= (ADVERTISE_10HALF | ADVERTISE_10FULL);
32421 + local_cap &= ~(ADVERTISE_100HALF | ADVERTISE_100FULL);
32422 + local_giga_cap &= ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL);
32424 + local_cap &= ~(ADVERTISE_10HALF);
32425 + } else if (strncmp(buf, "10HD", 4) == 0) {
32427 + local_cap |= (ADVERTISE_10HALF | ADVERTISE_10FULL);
32428 + local_cap &= ~(ADVERTISE_100HALF | ADVERTISE_100FULL);
32429 + local_giga_cap &= ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL);
32431 + local_cap &= ~(ADVERTISE_10FULL);
32432 + } else if (strncmp(buf, "AUTO", 4) == 0) {
32434 + local_cap |= (ADVERTISE_10HALF | ADVERTISE_10FULL);
32435 + local_cap |= (ADVERTISE_100HALF | ADVERTISE_100FULL);
32436 + local_giga_cap |= (ADVERTISE_1000HALF | ADVERTISE_1000FULL);
32441 + /* Active PHY with the requested speed for auto-negotiation */
32442 + ret = bcm539x_write_16(bd, REG_MII_PAGE + inst, (MII_ADVERTISE << 1), local_cap);
32446 + ret = bcm539x_write_16(bd, REG_MII_PAGE + inst, (MII_CTRL1000 << 1), local_giga_cap);
32451 + ret = bcm539x_read_16(bd, REG_MII_PAGE + inst, (MII_BMCR << 1), &ctrl_word);
32455 + ctrl_word |= (BMCR_ANENABLE | BMCR_ANRESTART);
32456 + ret = bcm539x_write_16(bd, REG_MII_PAGE + inst, (MII_BMCR << 1), ctrl_word);
32465 + * proc_fs entries for this switch
32467 +static const struct switch_handler bcm539x_switch_handlers[] = {
32469 + .name = "enable",
32470 + .read = bcm539x_handle_enable_read,
32471 + .write = bcm539x_handle_enable_write,
32474 + .name = "enable_vlan",
32475 + .read = bcm539x_handle_enable_vlan_read,
32476 + .write = bcm539x_handle_enable_vlan_write,
32480 + .write = bcm539x_handle_reset,
32487 + * Handlers for <this_driver>/vlan
32489 +static const struct switch_handler bcm539x_switch_handlers_vlan[] = {
32491 + .name = "delete",
32492 + .write = bcm539x_handle_vlan_delete_write,
32495 + .name = "create",
32496 + .write = bcm539x_handle_vlan_create_write,
32503 + * Handlers for <this_driver>/port/<port number>
32505 +static const struct switch_handler bcm539x_switch_handlers_port[] = {
32507 + .name = "enable",
32508 + .read = bcm539x_handle_port_enable_read,
32509 + .write = bcm539x_handle_port_enable_write,
32513 + .read = bcm539x_handle_port_state_read,
32517 + .read = bcm539x_handle_port_media_read,
32518 + .write = bcm539x_handle_port_meida_write,
32527 +static int __devinit bcm539x_probe(struct spi_device *spi)
32529 + struct bcm539x_data *bd;
32530 + struct switch_core_platform_data *pdata;
32531 + struct switch_device *switch_dev = NULL;
32535 + pdata = spi->dev.platform_data;
32540 + ret = spi_setup(spi);
32546 + * Reset the chip if requested
32548 + if (pdata->flags & SWITCH_DEV_FLAG_HW_RESET) {
32549 + ret = gpio_request(pdata->pin_reset, "switch-bcm539x-reset");
32551 + printk(KERN_WARNING "Could not request reset\n");
32555 + gpio_direction_output(pdata->pin_reset, 0);
32557 + gpio_set_value(pdata->pin_reset, 1);
32562 + * Allocate our private data structure
32564 + bd = kzalloc(sizeof(struct bcm539x_data), GFP_KERNEL);
32569 + dev_set_drvdata(&spi->dev, bd);
32570 + bd->pdata = pdata;
32572 + bd->last_page = 0xFF;
32575 + * First perform SW reset if needed
32577 + if (pdata->flags & SWITCH_DEV_FLAG_SW_RESET) {
32578 + txbuf[0] = (1 << 7) | (1 << 4);
32579 + ret = bcm539x_write_bytes(bd, PAGE_PORT_TC,
32580 + REG_CTRL_SRST, txbuf, 1);
32588 + ret = bcm539x_write_bytes(bd, PAGE_PORT_TC,
32589 + REG_CTRL_SRST, txbuf, 1);
32596 + * See if we can see the chip
32598 + for (i = 0; i < 10; i++) {
32599 + ret = bcm539x_read_bytes(bd, PAGE_MMR, REG_DEVICE_ID,
32600 + &bd->device_id, 1);
32610 + * We only support 5395, 5397, 5398
32612 + if ((bd->device_id != 0x95) && (bd->device_id != 0x97) &&
32613 + (bd->device_id != 0x98)) {
32619 + * Override CPU port config: fixed link @1000 with flow control
32621 + ret = bcm539x_read_8(bd, PAGE_PORT_TC, REG_CTRL_MIIPO, txbuf);
32622 + bcm539x_write_8(bd, PAGE_PORT_TC, REG_CTRL_MIIPO, 0xbb); // Override IMP port config
32623 + printk("Broadcom SW CPU port setting: 0x%x -> 0xbb\n", txbuf[0]);
32626 + * Setup the switch driver structure
32628 + switch_dev = switch_alloc();
32629 + if (!switch_dev) {
32633 + switch_dev->name = pdata->name;
32635 + switch_dev->ports = (bd->device_id == 0x98) ? 9 : 6;
32636 + switch_dev->port_mask[0] = (bd->device_id == 0x98) ? 0x1FF : 0x11F;
32637 + switch_dev->driver_handlers = bcm539x_switch_handlers;
32638 + switch_dev->reg_handlers = NULL;
32639 + switch_dev->vlan_handlers = bcm539x_switch_handlers_vlan;
32640 + switch_dev->port_handlers = bcm539x_switch_handlers_port;
32642 + bd->switch_dev = switch_dev;
32643 + switch_set_drvdata(switch_dev, (void *)bd);
32645 + ret = switch_register(bd->switch_dev);
32650 + printk(KERN_INFO "bcm53%02x switch chip initialized\n", bd->device_id);
32655 + if (switch_dev) {
32656 + switch_release(switch_dev);
32658 + dev_set_drvdata(&spi->dev, NULL);
32663 +static int __attribute__((unused)) bcm539x_remove(struct spi_device *spi)
32665 + struct bcm539x_data *bd;
32667 + bd = dev_get_drvdata(&spi->dev);
32669 + if (bd->pdata->flags & SWITCH_DEV_FLAG_HW_RESET) {
32670 + gpio_free(bd->pdata->pin_reset);
32673 + if (bd->switch_dev) {
32674 + switch_unregister(bd->switch_dev);
32675 + switch_release(bd->switch_dev);
32678 + dev_set_drvdata(&spi->dev, NULL);
32685 +static struct spi_driver bcm539x_driver = {
32687 + .name = DRIVER_NAME,
32688 + .owner = THIS_MODULE,
32690 + .probe = bcm539x_probe,
32691 + .remove = __devexit_p(bcm539x_remove),
32694 +static int __init bcm539x_init(void)
32696 + return spi_register_driver(&bcm539x_driver);
32699 +module_init(bcm539x_init);
32701 +static void __exit bcm539x_exit(void)
32703 + spi_unregister_driver(&bcm539x_driver);
32705 +module_exit(bcm539x_exit);
32707 +MODULE_AUTHOR("Pat Tjin");
32708 +MODULE_LICENSE("GPL v2");
32709 +MODULE_DESCRIPTION("bcm539x SPI switch chip driver");
32711 +++ b/arch/ubicom32/mach-common/switch-bcm539x-reg.h
32714 + * arch/ubicom32/mach-common/switch-bcm539x-reg.h
32715 + * Broadcom switch definitions for Ubicom32 architecture.
32717 + * (C) Copyright 2009, Ubicom, Inc.
32719 + * This file is part of the Ubicom32 Linux Kernel Port.
32721 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
32722 + * it and/or modify it under the terms of the GNU General Public License
32723 + * as published by the Free Software Foundation, either version 2 of the
32724 + * License, or (at your option) any later version.
32726 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
32727 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
32728 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
32729 + * the GNU General Public License for more details.
32731 + * You should have received a copy of the GNU General Public License
32732 + * along with the Ubicom32 Linux Kernel Port. If not,
32733 + * see <http://www.gnu.org/licenses/>.
32735 + * Ubicom32 implementation derived from (with many thanks):
32742 + * Broadcom 53xx RoboSwitch device driver.
32744 + * Copyright 2007, Broadcom Corporation
32745 + * All Rights Reserved.
32747 + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
32748 + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
32749 + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
32750 + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
32755 +#ifndef _SWITCH_BCM539X_REG_H_
32756 +#define _SWITCH_BCM539X_REG_H_
32758 +#define BCM539X_CMD_READ 0x60
32759 +#define BCM539X_CMD_WRITE 0x61
32761 +#define BCM539X_GLOBAL_SPI_DATA0 0xf0
32763 +#define BCM539X_GLOBAL_SPI_STATUS 0xfe
32764 +#define BCM539X_GLOBAL_SPI_ST_SPIF (1<<7)
32765 +#define BCM539X_GLOBAL_SPI_ST_RACK (1<<5)
32767 +#define BCM539X_GLOBAL_PAGE 0xff
32769 +#define PAGE_PORT_TC 0x00 // Port Traffic Control Register
32771 +#define PAGE_QOS_CTL 0x30 // QoS Global Control Register
32772 +#define PAGE_QOS_TAG 0x34 // Default IEEE 802.1Q TAG Register
32774 +#define PAGE_MII_CTL_PORT0 0x10 // Internal PHY MII Register
32775 +#define PAGE_MII_CTL_PORT1 0x11
32776 +#define PAGE_MII_CTL_PORT2 0x12
32777 +#define PAGE_MII_CTL_PORT3 0x13
32778 +#define PAGE_MII_CTL_PORT4 0x14
32780 +#define PAGE_STATUS 0x01 // Status Register Page
32781 +#define PAGE_RATE_CONTROL 0x41 // Broadcast Storm Suppression Register
32783 +#define REG_GRATE_CONTROL 0x00
32785 +#define REG_LED_POWER 0x12
32787 +// Ingress Rate Control
32788 +#define REG_IRATE_CONTROLP0 0x10
32789 +#define REG_IRATE_CONTROLP1 0x14
32790 +#define REG_IRATE_CONTROLP2 0x18
32791 +#define REG_IRATE_CONTROLP3 0x1C
32792 +#define REG_IRATE_CONTROLP4 0x20
32793 +#define REG_IRATE_CONTROLP7 0x2C
32794 +#define REG_IRATE_CONTROLPI 0x30
32796 +// Egress Rate Control
32797 +#define REG_ERATE_CONTROLP0 0x80
32798 +#define REG_ERATE_CONTROLP1 0x82
32799 +#define REG_ERATE_CONTROLP2 0x84
32800 +#define REG_ERATE_CONTROLP3 0x86
32801 +#define REG_ERATE_CONTROLP4 0x88
32802 +#define REG_ERATE_CONTROLP5 0x8A
32803 +#define REG_ERATE_CONTROLP6 0x8C
32804 +#define REG_ERATE_CONTROLP7 0x8E
32805 +#define REG_ERATE_CONTROLPI 0x90
32807 +#define REG_LINK_STATUS 0x00
32809 +#define REG_TC_PORT0 0x00
32810 +#define REG_TC_PORT1 0x01
32811 +#define REG_TC_PORT2 0x02
32812 +#define REG_TC_PORT3 0x03
32813 +#define REG_TC_PORT4 0x04
32814 +#define REG_TC_PORT5 0x05
32816 +#define REG_SPEED_CTL 0x00
32817 +#define REG_SPEED_ADV100 0x08
32818 +#define REG_SPEED_ADV1000 0x12
32820 +#define REG_QOS_EN 0x00
32821 +#define REG_QOS_TAG_PORT1 0x12 // Default IEEE 802.1Q TAG, PORT 1
32822 +#define REG_QOS_TAG_PORT2 0x14 // Default IEEE 802.1Q TAG, PORT 2
32823 +#define REG_QOS_TAG_PORT3 0x16 // Default IEEE 802.1Q TAG, PORT 3
32824 +#define REG_QOS_TAG_PORT4 0x18 // Default IEEE 802.1Q TAG, PORT 4
32825 +#define REG_QOS_PID_PORT1 0x52 // Ingress Port Priority ID MAP, PORT 1
32826 +#define REG_QOS_PID_PORT2 0x54 // Ingress Port Priority ID MAP, PORT 2
32827 +#define REG_QOS_PID_PORT3 0x56 // Ingress Port Priority ID MAP, PORT 3
32828 +#define REG_QOS_PID_PORT4 0x58 // Ingress Port Priority ID MAP, PORT 4
32829 +#define REG_QOS_TXQ_CTL 0x80 // Tx Queue Control Register
32830 +#define REG_QOS_TXQ_WHTQ0 0x81 // Tx Queue Weight Register Queue 0
32831 +#define REG_QOS_TXQ_WHTQ1 0x82 // Tx Queue Weight Register Queue 1
32832 +#define REG_QOS_TXQ_WHTQ2 0x83 // Tx Queue Weight Register Queue 2
32833 +#define REG_QOS_TXQ_WHTQ3 0x84 // Tx Queue Weight Register Queue 3
32835 +#define REG_CTRL_PPSEL 0x24 /* 5397: Protected port select register */
32837 +#define RATE_CONTROL_ENABLED (1 << 22)
32838 +#define RATE_CONTROL_BSIZE ((1 << 10) | (1 << 9) | (1 << 8))
32840 +#define RATE_CONTROL_HIGH ((1 << 7) | (1 << 6) | (1 << 5) | (1 << 4))
32841 +#define RATE_CONTROL_HIGH_N ~((1 << 3) | (1 << 2) | (1 << 1) | (1 << 0))
32843 +#define RATE_CONTROL_MEDIUM ((1 << 6) | (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2) | (1 << 1) | (1 << 0))
32844 +#define RATE_CONTROL_MEDIUM_N ~((1 << 7))
32846 +#define RATE_CONTROL_NORMAL ((1 << 5) | (1 << 2) | (1 << 0))
32847 +#define RATE_CONTROL_NORMAL_N ~((1 << 7) | (1 << 6) | (1 << 4) | (1 << 3) | (1 << 1))
32849 +#define RATE_CONTROL_LOW ((1 << 4) | (1 << 3) | (1 << 0))
32850 +#define RATE_CONTROL_LOW_N ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 2) | (1 << 1))
32852 +// --- Gemtek, Configure the switch to support Ethernet Port QoS
32854 +/* MII access registers */
32855 +#define PSEUDO_PHYAD 0x1E /* MII Pseudo PHY address */
32856 +#define REG_MII_PAGE 0x10 /* MII Page register */
32857 +#define REG_MII_ADDR 0x11 /* MII Address register */
32858 +#define REG_MII_DATA0 0x18 /* MII Data register 0 */
32859 +#define REG_MII_DATA1 0x19 /* MII Data register 1 */
32860 +#define REG_MII_DATA2 0x1a /* MII Data register 2 */
32861 +#define REG_MII_DATA3 0x1b /* MII Data register 3 */
32863 +/* Page numbers */
32864 +#define PAGE_CTRL 0x00 /* Control page */
32865 +#define PAGE_MMR 0x02 /* 5397 Management/Mirroring page */
32866 +#define PAGE_VTBL 0x05 /* ARL/VLAN Table access page */
32867 +#define PAGE_VLAN 0x34 /* VLAN page */
32869 +/* Control page registers */
32870 +#define REG_CTRL_PORT0 0x00 /* Port 0 traffic control register */
32871 +#define REG_CTRL_PORT1 0x01 /* Port 1 traffic control register */
32872 +#define REG_CTRL_PORT2 0x02 /* Port 2 traffic control register */
32873 +#define REG_CTRL_PORT3 0x03 /* Port 3 traffic control register */
32874 +#define REG_CTRL_PORT4 0x04 /* Port 4 traffic control register */
32875 +#define REG_CTRL_PORT5 0x05 /* Port 5 traffic control register */
32876 +#define REG_CTRL_PORT6 0x06 /* Port 6 traffic control register */
32877 +#define REG_CTRL_PORT7 0x07 /* Port 7 traffic control register */
32878 +#define REG_CTRL_MODE 0x0B /* Switch Mode register */
32879 +#define REG_CTRL_MIIPO 0x0E /* 5325: MII Port Override register */
32880 +#define REG_CTRL_SRST 0x79 /* Software reset control register */
32882 +#define REG_DEVICE_ID 0x30 /* 539x Device id: */
32883 +#define DEVID5395 0x95 /* 5395 */
32884 +#define DEVID5397 0x97 /* 5397 */
32885 +#define DEVID5398 0x98 /* 5398 */
32886 +#define REG_REVISION_ID 0x40 /* 539x Revision id: */
32888 +/* VLAN page registers */
32889 +#define REG_VLAN_CTRL0 0x00 /* VLAN Control 0 register */
32890 +#define REG_VLAN_CTRL1 0x01 /* VLAN Control 1 register */
32891 +#define REG_VLAN_CTRL2 0x02 /* VLAN Control 2 register */
32892 +#define REG_VLAN_CTRL3 0x03 /* VLAN Control 3 register */
32893 +#define REG_VLAN_CTRL4 0x04 /* VLAN Control 4 register */
32894 +#define REG_VLAN_CTRL5 0x05 /* VLAN Control 5 register */
32895 +#define REG_VLAN_ACCESS 0x06 /* VLAN Table Access register */
32896 +#define REG_VLAN_WRITE 0x08 /* VLAN Write register */
32897 +#define REG_VLAN_READ 0x0C /* VLAN Read register */
32898 +#define REG_VLAN_PTAG0 0x10 /* VLAN Default Port Tag register - port 0 */
32899 +#define REG_VLAN_PTAG1 0x12 /* VLAN Default Port Tag register - port 1 */
32900 +#define REG_VLAN_PTAG2 0x14 /* VLAN Default Port Tag register - port 2 */
32901 +#define REG_VLAN_PTAG3 0x16 /* VLAN Default Port Tag register - port 3 */
32902 +#define REG_VLAN_PTAG4 0x18 /* VLAN Default Port Tag register - port 4 */
32903 +#define REG_VLAN_PTAG5 0x1a /* VLAN Default Port Tag register - port 5 */
32904 +#define REG_VLAN_PTAG6 0x1c /* VLAN Default Port Tag register - port 6 */
32905 +#define REG_VLAN_PTAG7 0x1e /* VLAN Default Port Tag register - port 7 */
32906 +#define REG_VLAN_PTAG8 0x20 /* 539x: VLAN Default Port Tag register - IMP port */
32907 +#define REG_VLAN_PMAP 0x20 /* 5325: VLAN Priority Re-map register */
32909 +/* ARL/VLAN Table Access page registers */
32910 +#define REG_VTBL_CTRL 0x00 /* ARL Read/Write Control */
32911 +#define REG_VTBL_MINDX 0x02 /* MAC Address Index */
32912 +#define REG_VTBL_VINDX 0x08 /* VID Table Index */
32913 +#define REG_VTBL_ARL_E0 0x10 /* ARL Entry 0 */
32914 +#define REG_VTBL_ARL_E1 0x18 /* ARL Entry 1 */
32915 +#define REG_VTBL_DAT_E0 0x18 /* ARL Table Data Entry 0 */
32916 +#define REG_VTBL_SCTRL 0x20 /* ARL Search Control */
32917 +#define REG_VTBL_SADDR 0x22 /* ARL Search Address */
32918 +#define REG_VTBL_SRES 0x24 /* ARL Search Result */
32919 +#define REG_VTBL_SREXT 0x2c /* ARL Search Result */
32920 +#define REG_VTBL_VID_E0 0x30 /* VID Entry 0 */
32921 +#define REG_VTBL_VID_E1 0x32 /* VID Entry 1 */
32922 +#define REG_VTBL_PREG 0xFF /* Page Register */
32923 +#define REG_VTBL_ACCESS 0x60 /* VLAN table access register */
32924 +#define REG_VTBL_INDX 0x61 /* VLAN table address index register */
32925 +#define REG_VTBL_ENTRY 0x63 /* VLAN table entry register */
32926 +#define REG_VTBL_ACCESS_5395 0x80 /* VLAN table access register */
32927 +#define REG_VTBL_INDX_5395 0x81 /* VLAN table address index register */
32928 +#define REG_VTBL_ENTRY_5395 0x83 /* VLAN table entry register */
32930 +/* SPI registers */
32931 +#define REG_SPI_PAGE 0xff /* SPI Page register */
32935 +++ b/arch/ubicom32/mach-common/switch-core.c
32938 + * arch/ubicom32/mach-common/switch-core.c
32939 + * Ubicom32 architecture switch and /proc/switch/... implementation.
32941 + * (C) Copyright 2009, Ubicom, Inc.
32942 + * Copyright (C) 2005 Felix Fietkau <openwrt@nbd.name>
32944 + * This file is part of the Ubicom32 Linux Kernel Port.
32946 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
32947 + * it and/or modify it under the terms of the GNU General Public License
32948 + * as published by the Free Software Foundation, either version 2 of the
32949 + * License, or (at your option) any later version.
32951 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
32952 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
32953 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
32954 + * the GNU General Public License for more details.
32956 + * You should have received a copy of the GNU General Public License
32957 + * along with the Ubicom32 Linux Kernel Port. If not,
32958 + * see <http://www.gnu.org/licenses/>.
32960 + * Ubicom32 implementation derived from (with many thanks):
32965 + * Basic doc of driver's /proc interface:
32966 + * /proc/switch/<interface>/
32967 + * registers: read-only
32968 + * counters: read-only
32969 + * reset: write causes hardware reset
32970 + * enable: "0", "1"
32971 + * enable_vlan: "0", "1"
32972 + * port/<port-number>/
32973 + * enabled: "0", "1"
32974 + * link state: read-only
32975 + * media: "AUTO", "1000FD", "100FD", "100HD", "10FD", "10HD"
32976 + * vlan/<port-number>/
32977 + * ports: same syntax as for nvram's vlan*ports (eg. "1 2 3 4 5*")
32980 +#include <linux/module.h>
32981 +#include <linux/init.h>
32982 +#include <linux/uaccess.h>
32983 +#include <linux/ctype.h>
32984 +#include <linux/proc_fs.h>
32985 +#include <linux/list.h>
32986 +#include <linux/rwsem.h>
32987 +#include <linux/device.h>
32989 +#include "switch-core.h"
32992 + * Pointer to the root of our filesystem
32994 +static struct proc_dir_entry *switch_root;
32997 + * Lock used to manage access to the switch list
32999 +DECLARE_RWSEM(switch_list_lock);
33000 +EXPORT_SYMBOL_GPL(switch_list_lock);
33003 + * List of switches we are managing
33005 +LIST_HEAD(switch_list);
33006 +EXPORT_SYMBOL_GPL(switch_list);
33009 + * List of handlers we have
33011 +LIST_HEAD(switch_handler_list);
33012 +EXPORT_SYMBOL_GPL(switch_handler_list);
33015 + * Keep track of all the handlers we added
33017 +struct switch_handler_entry {
33018 + struct list_head node;
33019 + struct proc_dir_entry *parent;
33020 + struct switch_device *dev;
33021 + const struct switch_handler *handler;
33026 + * Keep track of all VLAN dirs we created
33028 +struct switch_vlan_entry {
33029 + struct list_head node;
33030 + struct proc_dir_entry *pde;
33032 + const struct switch_handler *handlers;
33036 + * switch_parse_vlan_ports
33037 + * Parse the vlan properties written to <driver>/vlan/<vlan_id>/ports
33039 +void switch_parse_vlan_ports(struct switch_device *switch_dev,
33040 + char *buf, u32_t *untag,
33041 + u32_t *ports, u32_t *def)
33050 + * Skip any leading spaces
33052 + while (isspace(*buf)) {
33057 + * Parse out the string
33060 + u32_t port = simple_strtoul(buf, &buf, 10);
33061 + u32_t mask = (1 << port);
33064 + * Parse out any flags
33066 + while (*buf && !isspace(*buf)) {
33067 + switch (*buf++) {
33079 + * Skip any spaces
33081 + while (isspace(*buf)) {
33086 + *untag = ~tag & *ports;
33090 + * switch_proc_read
33091 + * Handle reads from the procfs, dispatches the driver specific handler
33093 +static ssize_t switch_proc_read(struct file *file, char *buf, size_t count,
33096 + struct proc_dir_entry *pde = PDE(file->f_dentry->d_inode);
33100 + page = kmalloc(SWITCH_MAX_BUFSZ, GFP_KERNEL);
33105 + if (pde->data != NULL) {
33106 + struct switch_handler_entry *she =
33107 + (struct switch_handler_entry *)pde->data;
33108 + if (she->handler->read) {
33109 + len += she->handler->read(she->dev, page + len,
33115 + if (*ppos < len) {
33116 + len = min_t(int, len - *ppos, count);
33117 + if (copy_to_user(buf, (page + *ppos), len)) {
33132 + * switch_proc_write
33133 + * Handle writes from the procfs, dispatches the driver specific handler
33135 +static ssize_t switch_proc_write(struct file *file, const char *buf,
33136 + size_t count, loff_t *data)
33138 + struct proc_dir_entry *pde = PDE(file->f_dentry->d_inode);
33140 + int ret = -EINVAL;
33142 + page = kmalloc(count + 1, GFP_KERNEL);
33143 + if (page == NULL)
33146 + if (copy_from_user(page, buf, count)) {
33152 + if (pde->data != NULL) {
33153 + struct switch_handler_entry *she =
33154 + (struct switch_handler_entry *)pde->data;
33155 + if (she->handler->write) {
33156 + ret = she->handler->write(she->dev, page, she->inst);
33168 + * File operations for the proc_fs, we must cast here since proc_fs' definitions
33169 + * differ from file_operations definitions.
33171 +static struct file_operations switch_proc_fops = {
33172 + .read = (ssize_t (*) (struct file *, char __user *,
33173 + size_t, loff_t *))switch_proc_read,
33174 + .write = (ssize_t (*) (struct file *, const char __user *,
33175 + size_t, loff_t *))switch_proc_write,
33179 + * switch_add_handler
33181 +static int switch_add_handler(struct switch_device *switch_dev,
33182 + struct proc_dir_entry *parent,
33183 + const struct switch_handler *handler,
33186 + struct switch_handler_entry *she;
33187 + struct proc_dir_entry *pde;
33190 + she = (struct switch_handler_entry *)
33191 + kzalloc(sizeof(struct switch_handler_entry), GFP_KERNEL);
33196 + INIT_LIST_HEAD(&she->node);
33197 + she->parent = parent;
33198 + she->dev = switch_dev;
33199 + she->inst = inst;
33200 + she->handler = handler;
33201 + list_add(&she->node, &switch_dev->handlers);
33204 + if (handler->read != NULL) {
33207 + if (handler->write != NULL) {
33211 + pde = create_proc_entry(handler->name, mode, parent);
33214 + printk("Failed to create node '%s' in parent %p\n",
33215 + handler->name, parent);
33218 + pde->data = (void *)she;
33219 + pde->proc_fops = &switch_proc_fops;
33225 + * switch_add_handlers
33227 +static int switch_add_handlers(struct switch_device *switch_dev,
33228 + struct proc_dir_entry *parent,
33229 + const struct switch_handler *handlers,
33232 + while (handlers->name) {
33233 + int ret = switch_add_handler(switch_dev,
33234 + parent, handlers, inst);
33245 + * switch_remove_vlan_dirs
33246 + * Removes all vlan directories
33248 + * Assumes all vlan directories are empty, should be called after
33249 + * switch_remove_handlers
33251 +static void switch_remove_vlan_dirs(struct switch_device *switch_dev)
33253 + struct list_head *pos;
33254 + struct list_head *tmp;
33255 + struct switch_vlan_entry *sve;
33257 + list_for_each_safe(pos, tmp, &switch_dev->vlan_dirs) {
33258 + sve = list_entry(pos, struct switch_vlan_entry, node);
33260 + remove_proc_entry(sve->pde->name, switch_dev->vlan_dir);
33266 + * switch_remove_handlers
33267 + * Removes all handlers registered to the given switch_device
33269 +static void switch_remove_handlers(struct switch_device *switch_dev)
33271 + struct list_head *pos;
33272 + struct list_head *tmp;
33273 + struct switch_handler_entry *she;
33275 + list_for_each_safe(pos, tmp, &switch_dev->handlers) {
33276 + she = list_entry(pos, struct switch_handler_entry, node);
33278 + remove_proc_entry(she->handler->name, she->parent);
33284 + * switch_unregister_proc_nodes
33285 + * Unregisters all proc nodes related to switch_dev
33287 +void switch_unregister_proc_nodes(struct switch_device *switch_dev)
33289 + switch_remove_handlers(switch_dev);
33291 + if (switch_dev->port_dirs) {
33294 + for (i = 0; i < switch_dev->ports; i++) {
33295 + if (switch_dev->port_dirs[i]) {
33296 + remove_proc_entry(
33297 + switch_dev->port_dirs[i]->name,
33298 + switch_dev->port_dir);
33303 + if (switch_dev->port_dir) {
33304 + remove_proc_entry("port", switch_dev->driver_dir);
33305 + switch_dev->port_dir = NULL;
33308 + if (switch_dev->reg_dir) {
33309 + remove_proc_entry("reg", switch_dev->reg_dir);
33310 + switch_dev->reg_dir = NULL;
33313 + if (switch_dev->vlan_dir) {
33314 + switch_remove_vlan_dirs(switch_dev);
33315 + remove_proc_entry("vlan", switch_dev->driver_dir);
33316 + switch_dev->vlan_dir = NULL;
33319 + if (switch_dev->driver_dir) {
33320 + remove_proc_entry(switch_dev->name, switch_root);
33321 + switch_dev->driver_dir = NULL;
33326 + * switch_remove_vlan_dir
33327 + * Removes vlan dir in switch/<switch_driver>/vlan/<vlan_id>
33329 +int switch_remove_vlan_dir(struct switch_device *switch_dev, int vlan_id)
33331 + struct list_head *pos;
33332 + struct switch_vlan_entry *sve = NULL;
33334 + list_for_each(pos, &switch_dev->vlan_dirs) {
33335 + struct switch_vlan_entry *tmp =
33336 + list_entry(pos, struct switch_vlan_entry, node);
33337 + if (tmp->vlan_id == vlan_id) {
33348 + * Remove it from the list
33353 + * Remove the handlers
33355 + while (sve->handlers->name) {
33356 + remove_proc_entry(sve->handlers->name, sve->pde);
33361 + * Remove the proc entry for the <vlan_id> dir
33363 + remove_proc_entry(sve->pde->name, switch_dev->vlan_dir);
33371 + * switch_create_vlan_dir
33372 + * Creates vlan dir in switch/<switch_driver>/vlan/<vlan_id>
33374 +int switch_create_vlan_dir(struct switch_device *switch_dev,
33375 + int vlan_id, const struct switch_handler *handlers)
33378 + struct proc_dir_entry *pde = NULL;
33379 + struct switch_vlan_entry *sve = NULL;
33381 + struct list_head *pos;
33384 + * Check to see if it exists already
33386 + list_for_each(pos, &switch_dev->vlan_dirs) {
33387 + sve = list_entry(pos, struct switch_vlan_entry, node);
33388 + if (sve->vlan_id == vlan_id) {
33395 + * Create the vlan directory if we didn't have it before
33397 + if (!switch_dev->vlan_dir) {
33398 + switch_dev->vlan_dir = proc_mkdir("vlan",
33399 + switch_dev->driver_dir);
33400 + if (!switch_dev->vlan_dir) {
33403 + if (switch_dev->vlan_handlers) {
33404 + ret = switch_add_handlers(switch_dev,
33405 + switch_dev->vlan_dir,
33406 + switch_dev->vlan_handlers, 0);
33414 + * Create the vlan_id directory
33416 + snprintf(s, 14, "%d", vlan_id);
33417 + pde = proc_mkdir(s, switch_dev->vlan_dir);
33423 + * Create the handlers for this vlan
33426 + ret = switch_add_handlers(switch_dev, pde, handlers, vlan_id);
33433 + * Keep track of all the switch vlan entries created
33435 + sve = (struct switch_vlan_entry *)
33436 + kzalloc(sizeof(struct switch_vlan_entry), GFP_KERNEL);
33440 + INIT_LIST_HEAD(&sve->node);
33441 + sve->handlers = handlers;
33442 + sve->vlan_id = vlan_id;
33444 + list_add(&sve->node, &switch_dev->vlan_dirs);
33455 + * Remove any proc entries we might have created
33457 + while (handlers->name) {
33458 + remove_proc_entry(handlers->name, pde);
33462 + remove_proc_entry(s, switch_dev->driver_dir);
33469 + * switch_register_proc_nodes
33471 +int switch_register_proc_nodes(struct switch_device *switch_dev)
33476 + switch_dev->port_dirs = kzalloc(switch_dev->ports *
33477 + sizeof(struct proc_dir_entry *),
33479 + if (!switch_dev->port_dirs) {
33484 + * Create a new proc entry for this switch
33486 + switch_dev->driver_dir = proc_mkdir(switch_dev->name, switch_root);
33487 + if (!switch_dev->driver_dir) {
33490 + if (switch_dev->driver_handlers) {
33491 + switch_add_handlers(switch_dev,
33492 + switch_dev->driver_dir,
33493 + switch_dev->driver_handlers,
33498 + * Create the ports
33500 + switch_dev->port_dir = proc_mkdir("port", switch_dev->driver_dir);
33501 + if (!switch_dev->port_dir) {
33504 + for (n = 0, i = 0; i < (SWITCH_PORT_MASK_SIZE * 32); i++) {
33505 + if (switch_dev->port_mask[i / 32] & (1 << i % 32)) {
33508 + snprintf(s, 14, "%d", i);
33509 + switch_dev->port_dirs[n] =
33510 + proc_mkdir(s, switch_dev->port_dir);
33511 + if (!switch_dev->port_dirs[n]) {
33514 + if (switch_dev->port_handlers) {
33515 + switch_add_handlers(switch_dev,
33516 + switch_dev->port_dirs[n],
33517 + switch_dev->port_handlers,
33525 + * Create the register directory for switch register access.
33527 + if (switch_dev->reg_handlers) {
33528 + switch_dev->reg_dir = proc_mkdir("reg", switch_dev->driver_dir);
33529 + if (!switch_dev->reg_dir) {
33533 + switch_add_handlers(switch_dev,
33534 + switch_dev->reg_dir,
33535 + switch_dev->reg_handlers,
33540 + * Create the vlan directory
33542 + if (switch_dev->vlan_handlers) {
33543 + switch_dev->vlan_dir = proc_mkdir("vlan",
33544 + switch_dev->driver_dir);
33545 + if (!switch_dev->vlan_dir) {
33548 + if (switch_dev->vlan_handlers) {
33549 + switch_add_handlers(switch_dev,
33550 + switch_dev->vlan_dir,
33551 + switch_dev->vlan_handlers,
33559 + switch_unregister_proc_nodes(switch_dev);
33566 +void switch_release(struct switch_device *switch_dev)
33568 + kfree(switch_dev);
33574 +struct switch_device *switch_alloc(void)
33576 + struct switch_device *switch_dev =
33577 + kzalloc(sizeof(struct switch_device),
33579 + INIT_LIST_HEAD(&switch_dev->node);
33580 + INIT_LIST_HEAD(&switch_dev->vlan_dirs);
33581 + INIT_LIST_HEAD(&switch_dev->handlers);
33582 + return switch_dev;
33586 + * switch_register
33588 +int switch_register(struct switch_device *switch_dev)
33594 + * Make sure that the number of ports and the port mask make sense
33596 + for (ret = 0, i = 0; i < (SWITCH_PORT_MASK_SIZE * 32); i++) {
33597 + if (switch_dev->port_mask[i / 32] & (1 << i % 32)) {
33601 + if (ret > switch_dev->ports) {
33606 + * Create the /proc entries
33608 + ret = switch_register_proc_nodes(switch_dev);
33614 + * Add it to the list of switches
33616 + down_write(&switch_list_lock);
33617 + list_add_tail(&switch_dev->node, &switch_list);
33618 + up_write(&switch_list_lock);
33620 + printk(KERN_INFO "Registered switch device: %s\n", switch_dev->name);
33624 +EXPORT_SYMBOL_GPL(switch_register);
33627 + * switch_unregister
33628 + * Unregisters a previously registered switch_device object
33630 +void switch_unregister(struct switch_device *switch_dev)
33633 + * remove the proc entries
33635 + switch_unregister_proc_nodes(switch_dev);
33638 + * Remove it from the list of switches
33640 + down_write(&switch_list_lock);
33641 + list_del(&switch_dev->node);
33642 + up_write(&switch_list_lock);
33644 + printk(KERN_INFO "Unregistered switch device: %s\n", switch_dev->name);
33646 +EXPORT_SYMBOL_GPL(switch_unregister);
33651 +static int __init switch_init(void)
33653 + switch_root = proc_mkdir("switch", NULL);
33654 + if (!switch_root) {
33655 + printk(KERN_WARNING "Failed to make root switch node\n");
33660 +module_init(switch_init);
33665 +static void __exit switch_exit(void)
33667 + remove_proc_entry("switch", NULL);
33669 +module_exit(switch_exit);
33671 +MODULE_AUTHOR("Patrick Tjin");
33672 +MODULE_LICENSE("GPL");
33673 +MODULE_DESCRIPTION("Ethernet Switch Class Interface");
33675 +++ b/arch/ubicom32/mach-common/switch-core.h
33678 + * arch/ubicom32/mach-common/switch-core.h
33679 + * Private data for the switch module
33681 + * (C) Copyright 2009, Ubicom, Inc.
33683 + * This file is part of the Ubicom32 Linux Kernel Port.
33685 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
33686 + * it and/or modify it under the terms of the GNU General Public License
33687 + * as published by the Free Software Foundation, either version 2 of the
33688 + * License, or (at your option) any later version.
33690 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
33691 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
33692 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
33693 + * the GNU General Public License for more details.
33695 + * You should have received a copy of the GNU General Public License
33696 + * along with the Ubicom32 Linux Kernel Port. If not,
33697 + * see <http://www.gnu.org/licenses/>.
33699 + * Ubicom32 implementation derived from (with many thanks):
33704 +#ifndef _SWITCH_CORE_H_
33705 +#define _SWITCH_CORE_H_
33707 +struct switch_handler_entry;
33708 +struct switch_vlan_entry;
33710 +#define SWITCH_PORT_MASK_SIZE 2
33712 +struct switch_device {
33713 + struct list_head node;
33715 + const char *name;
33720 + struct proc_dir_entry *driver_dir;
33721 + const struct switch_handler *driver_handlers;
33723 + struct proc_dir_entry *port_dir;
33724 + struct proc_dir_entry **port_dirs;
33725 + const struct switch_handler *port_handlers;
33727 + struct proc_dir_entry *reg_dir;
33728 + const struct switch_handler *reg_handlers;
33730 + struct proc_dir_entry *vlan_dir;
33731 + const struct switch_handler *vlan_handlers;
33732 + struct list_head vlan_dirs;
33734 + struct list_head handlers;
33736 + u32_t port_mask[SWITCH_PORT_MASK_SIZE];
33739 +typedef int (*switch_handler_fn)(struct switch_device *, char *buf, int nr);
33740 +struct switch_handler {
33741 + const char *name;
33743 + switch_handler_fn read;
33744 + switch_handler_fn write;
33747 +#define SWITCH_MAX_BUFSZ 4096
33749 +static inline void switch_set_drvdata(struct switch_device *switch_dev, void *drvdata)
33751 + switch_dev->drvdata = drvdata;
33754 +static inline void *switch_get_drvdata(struct switch_device *switch_dev)
33756 + return switch_dev->drvdata;
33759 +extern int switch_create_vlan_dir(struct switch_device *switch_dev, int vlan_id, const struct switch_handler *handlers);
33760 +extern int switch_remove_vlan_dir(struct switch_device *switch_dev, int vlan_id);
33761 +extern void switch_parse_vlan_ports(struct switch_device *switch_dev, char *buf, u32_t *untag, u32_t *ports, u32_t *def);
33763 +extern void switch_release(struct switch_device *switch_dev);
33764 +extern struct switch_device *switch_alloc(void);
33765 +extern int switch_register(struct switch_device *switch_dev);
33766 +extern void switch_unregister(struct switch_device *switch_dev);
33770 +++ b/arch/ubicom32/mach-common/ubi32-gpio.c
33773 + * arch/ubicom32/mach-common/ubi32-gpio.c
33774 + * Ubicom gpio driver
33776 + * (C) Copyright 2009, Ubicom, Inc.
33778 + * This file is part of the Ubicom32 Linux Kernel Port.
33780 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
33781 + * it and/or modify it under the terms of the GNU General Public License
33782 + * as published by the Free Software Foundation, either version 2 of the
33783 + * License, or (at your option) any later version.
33785 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
33786 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
33787 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
33788 + * the GNU General Public License for more details.
33790 + * You should have received a copy of the GNU General Public License
33791 + * along with the Ubicom32 Linux Kernel Port. If not,
33792 + * see <http://www.gnu.org/licenses/>.
33794 + * Ubicom32 implementation derived from (with many thanks):
33800 +#include <linux/module.h>
33801 +#include <linux/init.h>
33802 +#include <linux/errno.h>
33803 +#include <linux/kernel.h>
33804 +#include <linux/io.h>
33805 +#include <linux/gpio.h>
33806 +#include <linux/irq.h>
33807 +#include <linux/version.h>
33809 +#if defined(CONFIG_PROC_FS)
33810 +#include <linux/proc_fs.h>
33813 +#include <linux/io.h>
33814 +#include <asm/ip5000.h>
33815 +#include <linux/gpio.h>
33817 +#define UBI_GPIO_CHECK_RANGE 0 /* !0 enables range checking */
33821 + * Each I/O port can be configured to operate in one of several
33822 + * functional modes. One of these modes is GPIO, which causes the
33823 + * entire port to function as a GPIO port. Since the various port
33824 + * registers serve the system with other important functions, such as
33825 + * ethernet, serial, USB, etc., it isn't advantageous to set any of
33826 + * the ports to be entirely dedicated for GPIO use. The processor
33827 + * alternatively allows individual bits of a port to be assigned to be
33828 + * used as GPIO independently from the overall port function. This
33829 + * bit-by-bit assignment is selected by setting the corresponding bit
33830 + * in the port's gpio_mask register. When set, the selected bit is
33831 + * then enabled as a GPIO. If the corresponding bit is set in the
33832 + * gpio_ctl register of the port, the bit is configured as a GPIO
33833 + * output. Otherwise, it is an input.
33835 + * NOTE: This driver uses the bit-by-bit GPIO function assignment
33836 + * exclusively and *never* sets the port function registers to the
33839 + * GPIO is not the main function of any of the I/O ports. The port
33840 + * bit widths are variable from one port to the next, determined by
33841 + * the more common I/O functions of the ports. For simplicity, this
33842 + * driver assumes all the ports are 32 bits wide regardless of the
33843 + * real bit width of the port. GPIO bits are numbered from zero to
33844 + * MAX_UBICOM_GPIOS. Within a port, the least significant bit is
33845 + * numbered bit zero, the most significant is bit 31. Since the ports
33846 + * are considered logically contiguous, GPIO #32 is the zeroth bit in
33847 + * port #1, and so on. Due to the hardware definition, there are
33848 + * large gaps in the GPIO numbers representing real pins.
33850 + * NOTE: It is up to the programmer to refer to the processor data
33851 + * sheet to determine which bits in which ports can be accessed and
33857 +/* There are 9 ports, A through I. Not all 32 bits in each
33858 + * port can be a GPIO, but we pretend they are. Its up to the
33859 + * programmer to refer to the processor data sheet.
33861 +#define MAX_UBICOM_GPIOS (9 * 32) /* ARCH_NR_GPIOS */
33862 +#define NUM_GPIO_PORTS (gpio_bank(MAX_UBICOM_GPIOS))
33865 +/* GPIO reservation bit map array */
33866 +static int reserved_gpio_map[NUM_GPIO_PORTS];
33869 +/* Array of hardware io_port addresses */
33870 +static struct ubicom32_io_port *gpio_bank_addr[NUM_GPIO_PORTS] =
33872 + UBICOM32_IO_PORT(RA),
33873 + UBICOM32_IO_PORT(RB),
33874 + UBICOM32_IO_PORT(RC),
33875 + UBICOM32_IO_PORT(RD),
33876 + UBICOM32_IO_PORT(RE),
33877 + UBICOM32_IO_PORT(RF),
33878 + UBICOM32_IO_PORT(RG),
33879 + UBICOM32_IO_PORT(RH),
33880 + UBICOM32_IO_PORT(RI)
33884 +struct ubi_gpio_chip {
33886 + * Right now, nothing else lives here.
33888 + struct gpio_chip gpio_chip;
33892 +#if UBI_GPIO_CHECK_RANGE
33893 +inline int check_gpio(unsigned gpio)
33895 + if (gpio >= MAX_UBICOM_GPIOS)
33900 +#define check_gpio(n) (0)
33904 + * ubi_gpio_get_port
33905 + * Get the IO port associated with a certain gpio
33907 +struct ubicom32_io_port *ubi_gpio_get_port(unsigned gpio)
33909 + if (gpio_bank(gpio) > NUM_GPIO_PORTS) {
33912 + return gpio_bank_addr[gpio_bank(gpio)];
33916 + * ubi_gpio_error()
33918 +static void ubi_gpio_error(unsigned gpio)
33920 + printk(KERN_ERR "ubicom-gpio: GPIO %d wasn't requested!\n", gpio);
33924 + * ubi_port_setup()
33926 +static void ubi_port_setup(unsigned gpio, unsigned short usage)
33928 + if (!check_gpio(gpio)) {
33930 + UBICOM32_GPIO_ENABLE(gpio);
33932 + UBICOM32_GPIO_DISABLE(gpio);
33938 + * ubi_gpio_request()
33940 +static int ubi_gpio_request(struct gpio_chip *chip, unsigned gpio)
33942 + unsigned long flags;
33944 + if (check_gpio(gpio) < 0)
33947 + local_irq_save(flags);
33949 + if (unlikely(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
33950 + printk(KERN_ERR "ubi-gpio: GPIO %d is already reserved!\n",
33952 + local_irq_restore(flags);
33956 + reserved_gpio_map[gpio_bank(gpio)] |= gpio_bit(gpio);
33958 + ubi_port_setup(gpio, 1);
33960 + local_irq_restore(flags);
33966 + * ubi_gpio_free()
33968 +static void ubi_gpio_free(struct gpio_chip *chip, unsigned gpio)
33970 + unsigned long flags;
33972 + if (check_gpio(gpio) < 0)
33975 + local_irq_save(flags);
33977 + if (unlikely(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)))) {
33978 + ubi_gpio_error(gpio);
33979 + local_irq_restore(flags);
33983 + /* Assert the pin is no longer claimed */
33984 + reserved_gpio_map[gpio_bank(gpio)] &= ~gpio_bit(gpio);
33986 + /* Revert port bit to use specified by port->function */
33987 + ubi_port_setup(gpio, 0);
33989 + local_irq_restore(flags);
33993 + * ubi_gpio_direction_input()
33995 +static int ubi_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
33997 + unsigned long flags;
33999 + if (!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
34000 + ubi_gpio_error(gpio);
34004 + local_irq_save(flags);
34006 + /* Configure pin as gpio */
34007 + ubi_port_setup(gpio, 1);
34009 + /* Assert pin is an input */
34010 + UBICOM32_GPIO_SET_PIN_INPUT(gpio);
34012 + local_irq_restore(flags);
34019 + * ubi_gpio_direction_output()
34021 +static int ubi_gpio_direction_output(struct gpio_chip *chip,
34022 + unsigned gpio, int value)
34024 + unsigned long flags;
34026 + if (!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
34027 + ubi_gpio_error(gpio);
34031 + local_irq_save(flags);
34033 + /* Configure pin as gpio and set initial value in gpio_out register
34034 + * so that when we enable it as an output, it will have the correct
34037 + ubi_port_setup(gpio, 1);
34039 + UBICOM32_GPIO_SET_PIN_HIGH(gpio);
34041 + UBICOM32_GPIO_SET_PIN_LOW(gpio);
34044 + /* Enable the pin as an output */
34045 + UBICOM32_GPIO_SET_PIN_OUTPUT(gpio);
34047 + local_irq_restore(flags);
34054 + * ubi_gpio_get_value()
34056 +static int ubi_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
34058 + return 0 != (gpio_bank_addr[gpio_bank(gpio)]->gpio_in & gpio_bit(gpio));
34063 + * ubi_gpio_set_value()
34065 +static void ubi_gpio_set_value(struct gpio_chip *chip, unsigned gpio,
34068 + unsigned long flags;
34069 + local_irq_save(flags);
34072 + UBICOM32_GPIO_SET_PIN_HIGH(gpio);
34074 + UBICOM32_GPIO_SET_PIN_LOW(gpio);
34077 + local_irq_restore(flags);
34082 + * ubi_gpio_to_irq()
34084 +static int ubi_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
34086 + return gpio_to_irq(gpio);
34091 + * ubi_gpio_init()
34093 +int __init ubi_gpio_init(void)
34097 + struct ubi_gpio_chip *chip;
34098 + struct gpio_chip *gc;
34100 + printk(KERN_INFO "Ubicom GPIO Controller\n");
34102 + chip = kzalloc(sizeof(struct ubi_gpio_chip), GFP_KERNEL);
34103 + if (chip == NULL)
34106 + gc = &chip->gpio_chip;
34107 + gc->request = ubi_gpio_request;
34108 + gc->free = ubi_gpio_free;
34109 + gc->to_irq = ubi_gpio_to_irq;
34110 + gc->direction_input = ubi_gpio_direction_input;
34111 + gc->direction_output = ubi_gpio_direction_output;
34112 + gc->get = ubi_gpio_get_value;
34113 + gc->set = ubi_gpio_set_value;
34114 + gc->can_sleep = 0;
34116 + gc->ngpio = MAX_UBICOM_GPIOS; /* ARCH_NR_GPIOS - 1 */
34117 + gc->label = "ubi_gpio";
34119 + status = gpiochip_add(gc);
34120 + if (status != 0) {
34125 + /* Assert all pins are free */
34126 + for (k = 0; k < NUM_GPIO_PORTS; k++) {
34127 + reserved_gpio_map[k] = 0;
34133 +#if defined(CONFIG_PROC_FS)
34135 + * ubi_get_gpio_dir()
34137 +static int ubi_get_gpio_dir(unsigned gpio)
34139 + if (gpio_bank_addr[gpio_bank(gpio)]->gpio_ctl & gpio_bit(gpio))
34146 + * gpio_proc_read()
34148 +static int ubi_gpio_proc_read(char *buf, char **start, off_t offset,
34149 + int len, int *unused_i, void *unused_v)
34151 + int c, outlen = 0;
34153 + for (c = 0; c < MAX_UBICOM_GPIOS; c++) {
34154 + if (!check_gpio(c) &&
34155 + (reserved_gpio_map[gpio_bank(c)] & gpio_bit(c))) {
34156 + len = sprintf(buf, "GPIO_%d:\t\tGPIO %s\n", c,
34157 + ubi_get_gpio_dir(c) ? "OUTPUT" : "INPUT");
34169 + * ubi_gpio_register_proc()
34171 +static __init int ubi_gpio_register_proc(void)
34173 + struct proc_dir_entry *proc_gpio;
34175 + proc_gpio = create_proc_entry("gpio", S_IRUGO, NULL);
34177 + proc_gpio->read_proc = ubi_gpio_proc_read;
34179 + return proc_gpio != NULL;
34181 +device_initcall(ubi_gpio_register_proc);
34184 +++ b/arch/ubicom32/mach-common/ubicom32hid.c
34187 + * arch/ubicom32/mach-common/ubicom32hid.c
34188 + * I2C driver for HID coprocessor found on some DPF implementations.
34190 + * (C) Copyright 2009, Ubicom, Inc.
34192 + * This file is part of the Ubicom32 Linux Kernel Port.
34194 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
34195 + * it and/or modify it under the terms of the GNU General Public License
34196 + * as published by the Free Software Foundation, either version 2 of the
34197 + * License, or (at your option) any later version.
34199 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
34200 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
34201 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
34202 + * the GNU General Public License for more details.
34204 + * You should have received a copy of the GNU General Public License
34205 + * along with the Ubicom32 Linux Kernel Port. If not,
34206 + * see <http://www.gnu.org/licenses/>.
34208 + * Ubicom32 implementation derived from (with many thanks):
34214 +#include <linux/module.h>
34215 +#include <linux/init.h>
34216 +#include <linux/gpio.h>
34217 +#include <linux/delay.h>
34218 +#include <linux/platform_device.h>
34219 +#include <linux/i2c.h>
34220 +#include <linux/backlight.h>
34221 +#include <linux/fb.h>
34222 +#include <linux/input.h>
34223 +#include <linux/input-polldev.h>
34225 +#include <asm/ubicom32hid.h>
34227 +#define DRIVER_NAME "ubicom32hid"
34230 +static int ubicom32hid_debug;
34233 +static const struct i2c_device_id ubicom32hid_id[] = {
34234 + { DRIVER_NAME, },
34237 +MODULE_DEVICE_TABLE(i2c, ubicom32hid_id);
34240 + * Define this to make IR checking strict, in general, it's not needed
34242 +#undef UBICOM32HID_STRICT_IR_CHECK
34244 +#define UBICOM32HID_CMD_SET_PWM 0x01
34245 +#define UBICOM32HID_CMD_SET_BL_EN 0x02
34246 +#define UBICOM32HID_BL_EN_LOW 0x00
34247 +#define UBICOM32HID_BL_EN_HIZ 0x01
34248 +#define UBICOM32HID_BL_EN_HI 0x02
34249 +#define UBICOM32HID_CMD_FLUSH 0x99
34250 +#define UBICOM32HID_CMD_RESET 0x99
34251 +#define UBICOM32HID_CMD_GET_IR_SWITCH 0xC0
34252 +#define UBICOM32HID_CMD_GET_REVISION 0xfd
34253 +#define UBICOM32HID_CMD_GET_DEVICE_ID 0xfe
34254 +#define UBICOM32HID_CMD_GET_VERSION 0xff
34255 +#define UBICOM32HID_DEVICE_ID 0x49
34257 +#define UBICOM32HID_MAX_BRIGHTNESS_PWM 255
34260 + * Data structure returned by the HID device
34262 +struct ubicom32hid_input_data {
34264 + uint8_t sw_state;
34265 + uint8_t sw_changed;
34269 + * Our private data
34271 +struct ubicom32hid_data {
34273 + * Pointer to the platform data structure, we need the settings.
34275 + const struct ubicom32hid_platform_data *pdata;
34278 + * Backlight device
34280 + struct backlight_device *bldev;
34283 + * I2C client, for sending messages to the HID device
34285 + struct i2c_client *client;
34288 + * Current intensity, used for get_intensity.
34290 + int cur_intensity;
34293 + * Input subsystem
34294 + * We won't register an input subsystem if there are no mappings.
34296 + struct input_polled_dev *poll_dev;
34301 + * ubicom32hid_set_intensity
34303 +static int ubicom32hid_set_intensity(struct backlight_device *bd)
34305 + struct ubicom32hid_data *ud =
34306 + (struct ubicom32hid_data *)bl_get_data(bd);
34307 + int intensity = bd->props.brightness;
34313 + * If we're blanked the the intensity doesn't matter.
34315 + if ((bd->props.power != FB_BLANK_UNBLANK) ||
34316 + (bd->props.fb_blank != FB_BLANK_UNBLANK)) {
34321 + * Set the brightness based on the type of backlight
34323 + if (ud->pdata->type == UBICOM32HID_BL_TYPE_BINARY) {
34324 + reg = UBICOM32HID_CMD_SET_BL_EN;
34326 + val = ud->pdata->invert
34327 + ? UBICOM32HID_BL_EN_LOW : UBICOM32HID_BL_EN_HI;
34329 + val = ud->pdata->invert
34330 + ? UBICOM32HID_BL_EN_HI : UBICOM32HID_BL_EN_LOW;
34333 + reg = UBICOM32HID_CMD_SET_PWM;
34334 + val = ud->pdata->invert
34335 + ? (UBICOM32HID_MAX_BRIGHTNESS_PWM - intensity) :
34340 + * Send the command
34342 + ret = i2c_smbus_write_byte_data(ud->client, reg, val);
34344 + dev_warn(&ud->client->dev, "Unable to write backlight err=%d\n",
34349 + ud->cur_intensity = intensity;
34355 + * ubicom32hid_get_intensity
34356 + * Return the current intensity of the backlight.
34358 +static int ubicom32hid_get_intensity(struct backlight_device *bd)
34360 + struct ubicom32hid_data *ud =
34361 + (struct ubicom32hid_data *)bl_get_data(bd);
34363 + return ud->cur_intensity;
34367 + * ubicom32hid_verify_data
34368 + * Verify the data to see if there is any action to be taken
34370 + * Returns 0 if no action is to be taken, non-zero otherwise
34372 +static int ubicom32hid_verify_data(struct ubicom32hid_data *ud,
34373 + struct ubicom32hid_input_data *data)
34375 + uint8_t *ircmd = (uint8_t *)&(data->ircmd);
34378 + * ircmd == DEADBEEF means ir queue is empty. Since this is a
34379 + * meaningful code, that means the rest of the message is most likely
34380 + * correct, so only process the data if the switch state has changed.
34382 + if (data->ircmd == 0xDEADBEEF) {
34383 + return data->sw_changed != 0;
34387 + * We have an ircmd which is not empty:
34388 + * Data[1] should be the complement of Data[0]
34390 + if (ircmd[0] != (u8_t)~ircmd[1]) {
34394 +#ifdef UBICOM32HID_STRICT_IR_CHECK
34396 + * It seems that some remote controls don't follow the NEC protocol
34397 + * properly, so only do this check if the remote does indeed follow the
34398 + * spec. Data[3] should be the complement of Data[2]
34400 + if (ircmd[2] == (u8_t)~ircmd[3]) {
34405 + * For non-compliant remotes, check the system code according to what
34408 + if ((ircmd[2] != UBICOM32HID_IR_SYSTEM_CODE_CHECK) ||
34409 + (ircmd[3] != UBICOM32HID_IR_SYSTEM_CODE)) {
34415 + * Data checks out, process
34421 + * ubicom32hid_poll_input
34422 + * Poll the input from the HID device.
34424 +static void ubicom32hid_poll_input(struct input_polled_dev *dev)
34426 + struct ubicom32hid_data *ud = (struct ubicom32hid_data *)dev->private;
34427 + const struct ubicom32hid_platform_data *pdata = ud->pdata;
34428 + struct ubicom32hid_input_data data;
34429 + struct input_dev *id = dev->input;
34431 + int sync_needed = 0;
34436 + * Flush the queue
34438 + cmd = UBICOM32HID_CMD_FLUSH;
34439 + ret = i2c_master_send(ud->client, &cmd, 1);
34444 + ret = i2c_smbus_read_i2c_block_data(
34445 + ud->client, UBICOM32HID_CMD_GET_IR_SWITCH, 6, (void *)&data);
34451 + * Verify the data to see if there is any action to be taken
34453 + if (!ubicom32hid_verify_data(ud, &data)) {
34458 + if (ubicom32hid_debug) {
34459 + printk("Polled ircmd=%8x swstate=%2x swchanged=%2x\n",
34460 + data.ircmd, data.sw_state, data.sw_changed);
34465 + * Process changed switches
34467 + if (data.sw_changed) {
34468 + const struct ubicom32hid_button *ub = pdata->buttons;
34469 + for (i = 0; i < pdata->nbuttons; i++, ub++) {
34470 + uint8_t mask = (1 << ub->bit);
34471 + if (!(data.sw_changed & mask)) {
34476 + input_event(id, ub->type, ub->code,
34477 + (data.sw_state & mask) ? 1 : 0);
34480 + if (sync_needed) {
34485 + * Process ir codes
34487 + if (data.ircmd != 0xDEADBEEF) {
34488 + const struct ubicom32hid_ir *ui = pdata->ircodes;
34489 + for (i = 0; i < pdata->nircodes; i++, ui++) {
34490 + if (ui->ir_code == data.ircmd) {
34492 + * Simulate a up/down event
34494 + input_event(id, ui->type, ui->code, 1);
34496 + input_event(id, ui->type, ui->code, 0);
34507 +static struct backlight_ops ubicom32hid_blops = {
34508 + .get_brightness = ubicom32hid_get_intensity,
34509 + .update_status = ubicom32hid_set_intensity,
34513 + * ubicom32hid_probe
34515 +static int ubicom32hid_probe(struct i2c_client *client,
34516 + const struct i2c_device_id *id)
34518 + struct ubicom32hid_platform_data *pdata;
34519 + struct ubicom32hid_data *ud;
34525 + pdata = client->dev.platform_data;
34526 + if (pdata == NULL) {
34531 + * See if we even have a device available before allocating memory.
34533 + * Hard reset the device
34535 + ret = gpio_request(pdata->gpio_reset, "ubicom32hid-reset");
34539 + gpio_direction_output(pdata->gpio_reset, pdata->gpio_reset_polarity);
34541 + gpio_set_value(pdata->gpio_reset, !pdata->gpio_reset_polarity);
34545 + * soft reset the device. It sometimes takes a while to do this.
34547 + for (i = 0; i < 50; i++) {
34548 + buf[0] = UBICOM32HID_CMD_RESET;
34549 + ret = i2c_master_send(client, buf, 1);
34556 + dev_warn(&client->dev, "Unable to reset device\n");
34560 + ret = i2c_smbus_read_byte_data(client, UBICOM32HID_CMD_GET_DEVICE_ID);
34561 + if (ret != UBICOM32HID_DEVICE_ID) {
34562 + dev_warn(&client->dev, "Incorrect device id %02x\n", buf[0]);
34567 + ret = i2c_smbus_read_byte_data(client, UBICOM32HID_CMD_GET_VERSION);
34569 + dev_warn(&client->dev, "Unable to get version\n");
34572 + version[0] = ret;
34574 + ret = i2c_smbus_read_byte_data(client, UBICOM32HID_CMD_GET_REVISION);
34576 + dev_warn(&client->dev, "Unable to get revision\n");
34579 + version[1] = ret;
34582 + * Allocate our private data
34584 + ud = kzalloc(sizeof(struct ubicom32hid_data), GFP_KERNEL);
34589 + ud->pdata = pdata;
34590 + ud->client = client;
34593 + * Register our backlight device
34595 + ud->bldev = backlight_device_register(DRIVER_NAME, &client->dev,
34596 + ud, &ubicom32hid_blops);
34597 + if (IS_ERR(ud->bldev)) {
34598 + ret = PTR_ERR(ud->bldev);
34601 + platform_set_drvdata(client, ud);
34604 + * Start up the backlight with the requested intensity
34606 + ud->bldev->props.power = FB_BLANK_UNBLANK;
34607 + ud->bldev->props.max_brightness =
34608 + (pdata->type == UBICOM32HID_BL_TYPE_PWM) ?
34609 + UBICOM32HID_MAX_BRIGHTNESS_PWM : 1;
34610 + if (pdata->default_intensity < ud->bldev->props.max_brightness) {
34611 + ud->bldev->props.brightness = pdata->default_intensity;
34613 + dev_warn(&client->dev, "Default brightness out of range, "
34614 + "setting to max\n");
34615 + ud->bldev->props.brightness = ud->bldev->props.max_brightness;
34618 + ubicom32hid_set_intensity(ud->bldev);
34621 + * Check to see if we have any inputs
34623 + if (!pdata->nbuttons && !pdata->nircodes) {
34628 + * We have buttons or codes, we must register an input device
34630 + ud->poll_dev = input_allocate_polled_device();
34631 + if (!ud->poll_dev) {
34637 + * Setup the polling to default to 100ms
34639 + ud->poll_dev->poll = ubicom32hid_poll_input;
34640 + ud->poll_dev->poll_interval =
34641 + pdata->poll_interval ? pdata->poll_interval : 100;
34642 + ud->poll_dev->private = ud;
34644 + ud->poll_dev->input->name =
34645 + pdata->input_name ? pdata->input_name : "Ubicom32HID";
34646 + ud->poll_dev->input->phys = "ubicom32hid/input0";
34647 + ud->poll_dev->input->dev.parent = &client->dev;
34648 + ud->poll_dev->input->id.bustype = BUS_I2C;
34651 + * Set the capabilities by running through the buttons and ir codes
34653 + for (i = 0; i < pdata->nbuttons; i++) {
34654 + const struct ubicom32hid_button *ub = &pdata->buttons[i];
34656 + input_set_capability(ud->poll_dev->input,
34657 + ub->type ? ub->type : EV_KEY, ub->code);
34660 + for (i = 0; i < pdata->nircodes; i++) {
34661 + const struct ubicom32hid_ir *ui = &pdata->ircodes[i];
34663 + input_set_capability(ud->poll_dev->input,
34664 + ui->type ? ui->type : EV_KEY, ui->code);
34667 + ret = input_register_polled_device(ud->poll_dev);
34673 + printk(KERN_INFO DRIVER_NAME ": enabled, version=%02x.%02x\n",
34674 + version[0], version[1]);
34679 + gpio_free(ud->pdata->gpio_reset);
34680 + backlight_device_unregister(ud->bldev);
34684 + gpio_free(pdata->gpio_reset);
34689 + * ubicom32hid_remove
34691 +static int ubicom32hid_remove(struct i2c_client *client)
34693 + struct ubicom32hid_data *ud =
34694 + (struct ubicom32hid_data *)platform_get_drvdata(client);
34696 + gpio_free(ud->pdata->gpio_reset);
34698 + backlight_device_unregister(ud->bldev);
34700 + if (ud->poll_dev) {
34701 + input_unregister_polled_device(ud->poll_dev);
34702 + input_free_polled_device(ud->poll_dev);
34705 + platform_set_drvdata(client, NULL);
34712 +static struct i2c_driver ubicom32hid_driver = {
34714 + .name = DRIVER_NAME,
34715 + .owner = THIS_MODULE,
34717 + .probe = ubicom32hid_probe,
34718 + .remove = __exit_p(ubicom32hid_remove),
34719 + .id_table = ubicom32hid_id,
34723 + * ubicom32hid_init
34725 +static int __init ubicom32hid_init(void)
34727 + return i2c_add_driver(&ubicom32hid_driver);
34729 +module_init(ubicom32hid_init);
34732 + * ubicom32hid_exit
34734 +static void __exit ubicom32hid_exit(void)
34736 + i2c_del_driver(&ubicom32hid_driver);
34738 +module_exit(ubicom32hid_exit);
34740 +MODULE_AUTHOR("Pat Tjin <@ubicom.com>")
34741 +MODULE_DESCRIPTION("Ubicom HID driver");
34742 +MODULE_LICENSE("GPL");
34744 +++ b/arch/ubicom32/mach-common/ubicom32input.c
34747 + * arch/ubicom32/mach-common/ubicom32input.c
34748 + * Ubicom32 Input driver
34750 + * based on gpio-keys
34752 + * (C) Copyright 2009, Ubicom, Inc.
34754 + * This file is part of the Ubicom32 Linux Kernel Port.
34756 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
34757 + * it and/or modify it under the terms of the GNU General Public License
34758 + * as published by the Free Software Foundation, either version 2 of the
34759 + * License, or (at your option) any later version.
34761 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
34762 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
34763 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
34764 + * the GNU General Public License for more details.
34766 + * You should have received a copy of the GNU General Public License
34767 + * along with the Ubicom32 Linux Kernel Port. If not,
34768 + * see <http://www.gnu.org/licenses/>.
34770 + * Ubicom32 implementation derived from (with many thanks):
34776 + * TODO: add groups for inputs which can be sampled together (i.e. I2C)
34779 +#include <linux/kernel.h>
34780 +#include <linux/module.h>
34781 +#include <linux/platform_device.h>
34782 +#include <linux/input.h>
34783 +#include <linux/input-polldev.h>
34784 +#include <linux/delay.h>
34785 +#include <linux/gpio.h>
34787 +#include <asm/ubicom32input.h>
34789 +struct ubicom32input_data {
34790 + struct ubicom32input_platform_data *pdata;
34792 + struct input_polled_dev *poll_dev;
34795 + * collection of previous states for buttons
34797 + u8 prev_state[0];
34801 + * ubicom32input_poll
34803 +static void ubicom32input_poll(struct input_polled_dev *dev)
34805 + struct ubicom32input_data *ud =
34806 + (struct ubicom32input_data *)dev->private;
34807 + struct ubicom32input_platform_data *pdata = ud->pdata;
34808 + struct input_dev *id = dev->input;
34810 + int sync_needed = 0;
34812 + for (i = 0; i < pdata->nbuttons; i++) {
34813 + const struct ubicom32input_button *ub = &pdata->buttons[i];
34816 + int val = gpio_get_value(ub->gpio);
34819 + * Check to see if the state changed from the last time we
34822 + if (val == ud->prev_state[i]) {
34827 + * The state has changed, determine if we are "up" or "down"
34829 + ud->prev_state[i] = val;
34831 + if ((!val && ub->active_low) || (val && !ub->active_low)) {
34835 + input_event(id, ub->type, ub->code, state);
34839 + if (sync_needed) {
34845 + * ubicom32input_probe
34847 +static int __devinit ubicom32input_probe(struct platform_device *pdev)
34850 + struct ubicom32input_data *ud;
34851 + struct input_polled_dev *poll_dev;
34852 + struct input_dev *input_dev;
34853 + struct ubicom32input_platform_data *pdata;
34856 + pdata = pdev->dev.platform_data;
34861 + ud = kzalloc(sizeof(struct ubicom32input_data) +
34862 + pdata->nbuttons, GFP_KERNEL);
34866 + ud->pdata = pdata;
34868 + poll_dev = input_allocate_polled_device();
34874 + platform_set_drvdata(pdev, ud);
34876 + ud->poll_dev = poll_dev;
34877 + poll_dev->private = ud;
34878 + poll_dev->poll = ubicom32input_poll;
34881 + * Set the poll interval requested, default to 50 msec
34883 + if (pdata->poll_interval) {
34884 + poll_dev->poll_interval = pdata->poll_interval;
34886 + poll_dev->poll_interval = 50;
34890 + * Setup the input device
34892 + input_dev = poll_dev->input;
34893 + input_dev->name = pdata->name ? pdata->name : "Ubicom32 Input";
34894 + input_dev->phys = "ubicom32input/input0";
34895 + input_dev->dev.parent = &pdev->dev;
34896 + input_dev->id.bustype = BUS_HOST;
34899 + * Reserve the GPIOs
34901 + for (i = 0; i < pdata->nbuttons; i++) {
34902 + const struct ubicom32input_button *ub = &pdata->buttons[i];
34904 + ret = gpio_request(ub->gpio,
34905 + ub->desc ? ub->desc : "ubicom32input");
34907 + pr_err("ubicom32input: failed to request "
34908 + "GPIO %d ret=%d\n", ub->gpio, ret);
34912 + ret = gpio_direction_input(ub->gpio);
34914 + pr_err("ubicom32input: failed to set "
34915 + "GPIO %d to input ret=%d\n", ub->gpio, ret);
34920 + * Set the previous state to the non-active stae
34922 + ud->prev_state[i] = ub->active_low;
34924 + input_set_capability(input_dev,
34925 + ub->type ? ub->type : EV_KEY, ub->code);
34931 + ret = input_register_polled_device(ud->poll_dev);
34940 + * release the GPIOs we have already requested.
34942 + while (--i >= 0) {
34943 + gpio_free(pdata->buttons[i].gpio);
34947 + printk(KERN_ERR "Ubicom32Input: Failed to register driver %d", ret);
34948 + platform_set_drvdata(pdev, NULL);
34949 + input_free_polled_device(poll_dev);
34955 + * ubicom32input_remove
34957 +static int __devexit ubicom32input_remove(struct platform_device *dev)
34959 + struct ubicom32input_data *ud =
34960 + (struct ubicom32input_data *)platform_get_drvdata(dev);
34966 + for (i = 0; i < ud->pdata->nbuttons; i++) {
34967 + gpio_free(ud->pdata->buttons[i].gpio);
34970 + platform_set_drvdata(dev, NULL);
34971 + input_unregister_polled_device(ud->poll_dev);
34972 + input_free_polled_device(ud->poll_dev);
34979 +static struct platform_driver ubicom32input_driver = {
34981 + .name = "ubicom32input",
34982 + .owner = THIS_MODULE,
34984 + .probe = ubicom32input_probe,
34985 + .remove = __devexit_p(ubicom32input_remove),
34989 + * ubicom32input_init
34991 +static int __devinit ubicom32input_init(void)
34993 + return platform_driver_register(&ubicom32input_driver);
34997 + * ubicom32input_exit
34999 +static void __exit ubicom32input_exit(void)
35001 + platform_driver_unregister(&ubicom32input_driver);
35004 +module_init(ubicom32input_init);
35005 +module_exit(ubicom32input_exit);
35007 +MODULE_AUTHOR("Pat Tjin <pattjin@ubicom.com>");
35008 +MODULE_DESCRIPTION("Ubicom32 Input Driver");
35009 +MODULE_LICENSE("GPL");
35010 +MODULE_ALIAS("platform:ubicom32-input");
35012 +++ b/arch/ubicom32/mach-common/ubicom32input_i2c.c
35015 + * arch/ubicom32/mach-common/ubicom32input_i2c.c
35016 + * Ubicom32 Input driver for I2C
35017 + * Supports PCA953x and family
35019 + * We hog the I2C device, turning it all to input.
35021 + * Based on gpio-keys, pca953x
35023 + * (C) Copyright 2009, Ubicom, Inc.
35025 + * This file is part of the Ubicom32 Linux Kernel Port.
35027 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
35028 + * it and/or modify it under the terms of the GNU General Public License
35029 + * as published by the Free Software Foundation, either version 2 of the
35030 + * License, or (at your option) any later version.
35032 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
35033 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
35034 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
35035 + * the GNU General Public License for more details.
35037 + * You should have received a copy of the GNU General Public License
35038 + * along with the Ubicom32 Linux Kernel Port. If not,
35039 + * see <http://www.gnu.org/licenses/>.
35041 + * Ubicom32 implementation derived from (with many thanks):
35046 +#include <linux/kernel.h>
35047 +#include <linux/module.h>
35048 +#include <linux/platform_device.h>
35049 +#include <linux/input.h>
35050 +#include <linux/input-polldev.h>
35051 +#include <linux/i2c.h>
35053 +#include <asm/ubicom32input_i2c.h>
35055 +#define UBICOM32INPUT_I2C_REG_INPUT 0
35056 +#define UBICOM32INPUT_I2C_REG_OUTPUT 1
35057 +#define UBICOM32INPUT_I2C_REG_INVERT 2
35058 +#define UBICOM32INPUT_I2C_REG_DIRECTION 3
35060 +static const struct i2c_device_id ubicom32input_i2c_id[] = {
35061 + { "ubicom32in_pca9534", 8, },
35062 + { "ubicom32in_pca9535", 16, },
35063 + { "ubicom32in_pca9536", 4, },
35064 + { "ubicom32in_pca9537", 4, },
35065 + { "ubicom32in_pca9538", 8, },
35066 + { "ubicom32in_pca9539", 16, },
35067 + { "ubicom32in_pca9554", 8, },
35068 + { "ubicom32in_pca9555", 16, },
35069 + { "ubicom32in_pca9557", 8, },
35070 + { "ubicom32in_max7310", 8, },
35073 +MODULE_DEVICE_TABLE(i2c, ubicom32input_i2c_id);
35075 +struct ubicom32input_i2c_data {
35076 + struct ubicom32input_i2c_platform_data *pdata;
35078 + struct i2c_client *client;
35080 + struct input_polled_dev *poll_dev;
35083 + * collection of previous states for buttons
35085 + uint16_t prev_state;
35091 + * ubicom32input_i2c_write_reg
35092 + * writes a register to the I2C device.
35094 +static int ubicom32input_i2c_write_reg(struct ubicom32input_i2c_data *ud,
35095 + int reg, uint16_t val)
35099 + if (ud->ngpios <= 8) {
35100 + ret = i2c_smbus_write_byte_data(ud->client, reg, val);
35102 + ret = i2c_smbus_write_word_data(ud->client, reg << 1, val);
35113 + * ubicom32input_i2c_read_reg
35114 + * reads a register from the I2C device.
35116 +static int ubicom32input_i2c_read_reg(struct ubicom32input_i2c_data *ud,
35117 + int reg, uint16_t *val)
35121 + if (ud->ngpios <= 8) {
35122 + ret = i2c_smbus_read_byte_data(ud->client, reg);
35124 + ret = i2c_smbus_read_word_data(ud->client, reg);
35131 + *val = (uint16_t)ret;
35137 + * ubicom32input_i2c_poll
35139 +static void ubicom32input_i2c_poll(struct input_polled_dev *dev)
35141 + struct ubicom32input_i2c_data *ud =
35142 + (struct ubicom32input_i2c_data *)dev->private;
35143 + struct ubicom32input_i2c_platform_data *pdata = ud->pdata;
35144 + struct input_dev *id = dev->input;
35146 + int sync_needed = 0;
35148 + uint16_t change_mask;
35151 + * Try to get the input status, if we fail, bail out, maybe we can do it
35154 + if (ubicom32input_i2c_read_reg(ud, UBICOM32INPUT_I2C_REG_INPUT, &val)) {
35159 + * see if anything changed by using XOR
35161 + change_mask = ud->prev_state ^ val;
35162 + ud->prev_state = val;
35164 + for (i = 0; i < pdata->nbuttons; i++) {
35165 + const struct ubicom32input_i2c_button *ub = &pdata->buttons[i];
35166 + uint16_t mask = 1 << ub->bit;
35167 + int state = val & mask;
35170 + * Check to see if the state changed from the last time we
35173 + if (!(change_mask & mask)) {
35176 + input_event(id, ub->type, ub->code, state);
35180 + if (sync_needed) {
35186 + * ubicom32input_i2c_probe
35188 +static int __devinit ubicom32input_i2c_probe(struct i2c_client *client,
35189 + const struct i2c_device_id *id)
35192 + struct ubicom32input_i2c_data *ud;
35193 + struct input_polled_dev *poll_dev;
35194 + struct input_dev *input_dev;
35195 + struct ubicom32input_i2c_platform_data *pdata;
35197 + uint16_t invert_mask = 0;
35199 + pdata = client->dev.platform_data;
35204 + ud = kzalloc(sizeof(struct ubicom32input_i2c_data), GFP_KERNEL);
35208 + ud->pdata = pdata;
35209 + ud->client = client;
35210 + ud->ngpios = id->driver_data;
35212 + poll_dev = input_allocate_polled_device();
35218 + ud->poll_dev = poll_dev;
35219 + poll_dev->private = ud;
35220 + poll_dev->poll = ubicom32input_i2c_poll;
35223 + * Set the poll interval requested, default to 100 msec
35225 + if (pdata->poll_interval) {
35226 + poll_dev->poll_interval = pdata->poll_interval;
35228 + poll_dev->poll_interval = 100;
35232 + * Setup the input device
35234 + input_dev = poll_dev->input;
35235 + input_dev->name = pdata->name ? pdata->name : "Ubicom32 Input I2C";
35236 + input_dev->phys = "ubicom32input_i2c/input0";
35237 + input_dev->dev.parent = &client->dev;
35238 + input_dev->id.bustype = BUS_I2C;
35241 + * Set the capabilities
35243 + for (i = 0; i < pdata->nbuttons; i++) {
35244 + const struct ubicom32input_i2c_button *ub = &pdata->buttons[i];
35246 + if (ub->active_low) {
35247 + invert_mask |= (1 << ub->bit);
35250 + input_set_capability(input_dev,
35251 + ub->type ? ub->type : EV_KEY, ub->code);
35255 + * Setup the device (all inputs)
35257 + ret = ubicom32input_i2c_write_reg(ud, UBICOM32INPUT_I2C_REG_DIRECTION,
35263 + ret = ubicom32input_i2c_write_reg(ud, UBICOM32INPUT_I2C_REG_INVERT,
35272 + ret = input_register_polled_device(ud->poll_dev);
35277 + i2c_set_clientdata(client, ud);
35282 + printk(KERN_ERR "ubicom32input_i2c: Failed to register driver %d\n",
35284 + input_free_polled_device(poll_dev);
35290 + * ubicom32input_i2c_remove
35292 +static int __devexit ubicom32input_i2c_remove(struct i2c_client *client)
35294 + struct ubicom32input_i2c_data *ud =
35295 + (struct ubicom32input_i2c_data *)i2c_get_clientdata(client);
35297 + i2c_set_clientdata(client, NULL);
35298 + input_unregister_polled_device(ud->poll_dev);
35299 + input_free_polled_device(ud->poll_dev);
35306 +static struct i2c_driver ubicom32input_i2c_driver = {
35308 + .name = "ubicom32input_i2c",
35309 + .owner = THIS_MODULE,
35311 + .remove = __devexit_p(ubicom32input_i2c_remove),
35312 + .id_table = ubicom32input_i2c_id,
35313 + .probe = ubicom32input_i2c_probe,
35317 + * ubicom32input_i2c_init
35319 +static int __devinit ubicom32input_i2c_init(void)
35321 + return i2c_add_driver(&ubicom32input_i2c_driver);
35325 + * ubicom32input_i2c_exit
35327 +static void __exit ubicom32input_i2c_exit(void)
35329 + i2c_del_driver(&ubicom32input_i2c_driver);
35332 +module_init(ubicom32input_i2c_init);
35333 +module_exit(ubicom32input_i2c_exit);
35335 +MODULE_AUTHOR("Pat Tjin <pattjin@ubicom.com>");
35336 +MODULE_DESCRIPTION("Ubicom32 Input Driver I2C");
35337 +MODULE_LICENSE("GPL");
35338 +MODULE_ALIAS("platform:ubicom32-input");
35340 +++ b/arch/ubicom32/mach-common/usb.c
35343 + * arch/ubicom32/mach-common/ip5k_usb.c
35344 + * Ubicom32 architecture usb support.
35346 + * (C) Copyright 2009, Ubicom, Inc.
35347 + * Copyright (C) 2007 MontaVista Software, Inc. <source@mvista.com>
35348 + * Author: Kevin Hilman
35350 + * This file is part of the Ubicom32 Linux Kernel Port.
35352 + * The Ubicom32 Linux Kernel Port is free software: you can
35353 + * redistribute it and/or modify it under the terms of the GNU General
35354 + * Public License as published by the Free Software Foundation, either
35355 + * version 2 of the License, or (at your option) any later version.
35357 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
35358 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
35359 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
35360 + * See the GNU General Public License for more details.
35362 + * You should have received a copy of the GNU General Public License
35363 + * along with the Ubicom32 Linux Kernel Port. If not,
35364 + * see <http://www.gnu.org/licenses/>.
35366 + * Ubicom32 implementation derived from (with many thanks):
35372 +#include <linux/types.h>
35373 +#include <linux/errno.h>
35374 +#include <linux/delay.h>
35375 +#include <linux/platform_device.h>
35376 +#include <linux/dma-mapping.h>
35377 +#include <linux/usb/musb.h>
35378 +#include <asm/devtree.h>
35379 +#include <asm/ip5000.h>
35380 +#include "usb_tio.h"
35382 +struct usbtionode *unode = NULL;
35384 +static struct resource usb_resources[] = {
35386 + .start = RJ + 0x800,
35387 + .end = RJ + 0x1000,
35388 + .flags = IORESOURCE_MEM,
35390 + [1] = { /* general IRQ */
35391 + .start = 1, /* this is a dummy value, the real irq number is passed from kernel_setup_param */
35392 + .flags = IORESOURCE_IRQ,
35397 +static struct musb_hdrc_eps_bits musb_eps[] = {
35398 + { "ep1_tx", 4, },
35399 + { "ep1_rx", 4, },
35400 + { "ep2_tx", 10, },
35401 + { "ep2_rx", 10, },
35402 + { "ep3_tx", 9, },
35403 + { "ep3_rx", 9, },
35404 + { "ep4_tx", 9, },
35405 + { "ep4_rx", 9, },
35406 + { "ep5_tx", 6, },
35407 + { "ep5_rx", 6, },
35410 +static struct musb_hdrc_config musb_config = {
35411 + .multipoint = true,
35412 + .dyn_fifo = false,
35413 + .soft_con = true,
35417 + .dma_channels = 0,
35419 + .eps_bits = musb_eps,
35422 +static struct musb_hdrc_platform_data usb_data = {
35423 +#ifdef CONFIG_USB_MUSB_OTG
35424 + .mode = MUSB_OTG,
35426 +#ifdef CONFIG_USB_MUSB_HDRC_HCD
35427 + .mode = MUSB_HOST,
35429 +#ifdef CONFIG_USB_GADGET_MUSB_HDRC
35430 + .mode = MUSB_PERIPHERAL,
35435 + .set_clock = NULL,
35436 + .config = &musb_config,
35439 +static struct platform_device musb_device = {
35440 + .name = "musb_hdrc",
35443 + .platform_data = &usb_data,
35444 + .dma_mask = NULL,
35445 + .coherent_dma_mask = 0,
35447 + .resource = usb_resources,
35448 + .num_resources = ARRAY_SIZE(usb_resources),
35451 +struct usbtio_node *usb_node = NULL;
35452 +void ubi32_usb_init(void)
35455 + * See if the usbtio is in the device tree.
35457 + usb_node = (struct usbtio_node *)devtree_find_node("usbtio");
35459 + printk(KERN_WARNING "usb init failed\n");
35463 + usb_resources[1].start = usb_node->dn.recvirq;
35464 + if (platform_device_register(&musb_device) < 0) {
35465 + printk(KERN_ERR "Unable to register HS-USB (MUSB) device\n");
35470 +void ubi32_usb_int_clr(void)
35472 + UBICOM32_IO_PORT(RJ)->int_clr = (1 << 3);
35475 +++ b/arch/ubicom32/mach-common/usb_tio.c
35478 + * arch/ubicom32/mach-common/usb_tio.c
35479 + * Linux side Ubicom USB TIO driver
35481 + * (C) Copyright 2009, Ubicom, Inc.
35483 + * This file is part of the Ubicom32 Linux Kernel Port.
35485 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
35486 + * it and/or modify it under the terms of the GNU General Public License
35487 + * as published by the Free Software Foundation, either version 2 of the
35488 + * License, or (at your option) any later version.
35490 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
35491 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
35492 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
35493 + * the GNU General Public License for more details.
35495 + * You should have received a copy of the GNU General Public License
35496 + * along with the Ubicom32 Linux Kernel Port. If not,
35497 + * see <http://www.gnu.org/licenses/>.
35499 + * Ubicom32 implementation derived from (with many thanks):
35504 +#include <linux/module.h>
35505 +#include <linux/spinlock.h>
35506 +#include <linux/slab.h>
35507 +#include <asm/devtree.h>
35508 +#include "usb_tio.h"
35511 +static DEFINE_SPINLOCK(tio_lock);
35512 +#define USB_TIO_LOCK(lock, flag) spin_lock_irqsave(lock, flag)
35513 +#define USB_TIO_UNLOCK(lock, flag) spin_unlock_irqrestore(lock, flag)
35514 +#define USB_TIO_LOCK_ISLOCKED(lock) spin_try_lock(lock)
35516 +#define USB_TIO_LOCK(lock, flag) local_irq_save(flag)
35517 +#define USB_TIO_UNLOCK(lock, flag) local_irq_restore(flag)
35520 +spinlock_t usb_tio_lock;
35523 + * usb_tio_set_hrt_interrupt()
35525 +static inline void usb_tio_set_hrt_interrupt(void)
35527 + ubicom32_set_interrupt(usb_node->dn.sendirq);
35530 +static inline void usb_tio_wait_hrt(void)
35532 + while (unlikely(usb_node->pdesc));
35535 +#if defined(USB_TIO_DEBUG)
35536 +static void usb_tio_request_verify_magic(volatile struct usb_tio_request *req)
35538 + BUG_ON(req->magic != USB_TIO_REQUEST_MAGIC2);
35541 +static void usb_tio_request_clear_magic(volatile struct usb_tio_request *req)
35547 +static void usb_tio_request_set_magic(volatile struct usb_tio_request *req)
35549 + req->magic = USB_TIO_REQUEST_MAGIC1;
35553 + * usb_tio_commit_request()
35555 +static inline void usb_tio_commit_request(volatile struct usb_tio_request *request)
35558 + usb_node->pdesc = request;
35561 + * next thing to do is alway checking if (usb_node->pdesc == NULL)
35562 + * to see if the request is done, so add a mb() here
35565 + usb_tio_set_hrt_interrupt();
35569 + * usb_tio_read_u16()
35570 + * Synchronously read 16 bits.
35572 +u8_t usb_tio_read_u16(u32_t address, u16_t *data)
35574 + volatile struct usb_tio_request *tio_req = &usb_node->request;
35575 + unsigned long flag;
35578 + * Wait for any previous request to complete and then make this request.
35580 + USB_TIO_LOCK(&tio_lock, flag);
35581 + usb_tio_wait_hrt();
35584 + * Fill in the request.
35586 + tio_req->address = address;
35587 + tio_req->cmd = USB_TIO_READ16_SYNC;
35588 + USB_TIO_REQUEST_SET_MAGIC(tio_req);
35589 + usb_tio_commit_request(tio_req);
35592 + * Wait for the result to show up.
35594 + usb_tio_wait_hrt();
35595 + USB_TIO_REQUEST_VERIFY_MAGIC(tio_req);
35596 + *data = (u16_t)tio_req->data;
35597 + USB_TIO_REQUEST_CLEAR_MAGIC(tio_req);
35598 + USB_TIO_UNLOCK(&tio_lock, flag);
35599 + return USB_TIO_OK;
35603 + * usb_tio_read_u8()
35604 + * Synchronously read 16 bits.
35606 +u8_t usb_tio_read_u8(u32_t address, u8_t *data)
35608 + volatile struct usb_tio_request *tio_req = &usb_node->request;
35609 + unsigned long flag;
35612 + * Wait for any previous request to complete and then make this request.
35614 + USB_TIO_LOCK(&tio_lock, flag);
35615 + usb_tio_wait_hrt();
35618 + * Fill in the request.
35620 + tio_req->address = address;
35621 + tio_req->cmd = USB_TIO_READ8_SYNC;
35622 + USB_TIO_REQUEST_SET_MAGIC(tio_req);
35625 + * commit the request
35627 + usb_tio_commit_request(tio_req);
35630 + * Wait for the result to show up.
35632 + usb_tio_wait_hrt();
35633 + USB_TIO_REQUEST_VERIFY_MAGIC(tio_req);
35634 + *data = (u8_t)tio_req->data;
35635 + USB_TIO_REQUEST_CLEAR_MAGIC(tio_req);
35636 + USB_TIO_UNLOCK(&tio_lock, flag);
35637 + return USB_TIO_OK;
35641 + * usb_tio_write_u16()
35642 + * Asynchronously write 16 bits.
35644 +u8_t usb_tio_write_u16(u32_t address, u16_t data)
35646 + volatile struct usb_tio_request *tio_req = &usb_node->request;
35647 + unsigned long flag;
35650 + * Wait for any previous write or pending read to complete.
35652 + USB_TIO_LOCK(&tio_lock, flag);
35653 + usb_tio_wait_hrt();
35655 + tio_req->address = address;
35656 + tio_req->data = data;
35657 + tio_req->cmd = USB_TIO_WRITE16_ASYNC;
35658 + USB_TIO_REQUEST_SET_MAGIC(tio_req);
35661 + * commit the request
35663 + usb_tio_commit_request(tio_req);
35664 + USB_TIO_UNLOCK(&tio_lock, flag);
35665 + return USB_TIO_OK;
35669 + * usb_tio_write_u8()
35670 + * Asynchronously write 8 bits.
35672 +u8_t usb_tio_write_u8(u32_t address, u8_t data)
35674 + volatile struct usb_tio_request *tio_req = &usb_node->request;
35675 + unsigned long flag;
35678 + * Wait for any previous write or pending read to complete.
35680 + USB_TIO_LOCK(&tio_lock, flag);
35681 + usb_tio_wait_hrt();
35683 + tio_req->address = address;
35684 + tio_req->data = data;
35685 + tio_req->cmd = USB_TIO_WRITE8_ASYNC;
35686 + USB_TIO_REQUEST_SET_MAGIC(tio_req);
35689 + * commit the request
35691 + usb_tio_commit_request(tio_req);
35692 + USB_TIO_UNLOCK(&tio_lock, flag);
35693 + return USB_TIO_OK;
35697 + * usb_tio_read_fifo()
35698 + * Synchronously read FIFO.
35700 +u8_t usb_tio_read_fifo(u32_t address, u32_t buffer, u32_t bytes)
35702 + volatile struct usb_tio_request *tio_req = &usb_node->request;
35703 + unsigned long flag;
35706 + * Wait for any previous request to complete and then make this request.
35708 + USB_TIO_LOCK(&tio_lock, flag);
35709 + usb_tio_wait_hrt();
35712 + * Fill in the request.
35714 + tio_req->address = address;
35715 + tio_req->cmd = USB_TIO_READ_FIFO_SYNC;
35716 + tio_req->buffer = buffer;
35717 + tio_req->transfer_length = bytes;
35718 + USB_TIO_REQUEST_SET_MAGIC(tio_req);
35721 + * commit the request
35723 + usb_tio_commit_request(tio_req);
35726 + * Wait for the result to show up.
35728 + usb_tio_wait_hrt();
35729 + USB_TIO_REQUEST_VERIFY_MAGIC(tio_req);
35730 + USB_TIO_REQUEST_CLEAR_MAGIC(tio_req);
35731 + USB_TIO_UNLOCK(&tio_lock, flag);
35732 + return USB_TIO_OK;
35736 + * usb_tio_write_fifo()
35737 + * Synchronously write 32 bits.
35739 +u8_t usb_tio_write_fifo(u32_t address, u32_t buffer, u32_t bytes)
35741 + volatile struct usb_tio_request *tio_req = &usb_node->request;
35742 + unsigned long flag;
35744 + USB_TIO_LOCK(&tio_lock, flag);
35745 + usb_tio_wait_hrt();
35747 + tio_req->address = address;
35748 + tio_req->buffer = buffer;
35749 + tio_req->cmd = USB_TIO_WRITE_FIFO_SYNC;
35750 + tio_req->transfer_length = bytes;
35751 + USB_TIO_REQUEST_SET_MAGIC(tio_req);
35753 + * commit the request
35755 + usb_tio_commit_request(tio_req);
35758 + * Wait for the result to show up.
35760 + usb_tio_wait_hrt();
35761 + USB_TIO_REQUEST_VERIFY_MAGIC(tio_req);
35762 + USB_TIO_REQUEST_CLEAR_MAGIC(tio_req);
35763 + USB_TIO_UNLOCK(&tio_lock, flag);
35764 + return USB_TIO_OK;
35768 + * usb_tio_write_fifo_async()
35769 + * Asynchronously write 32 bits.
35771 +u8_t usb_tio_write_fifo_async(u32_t address, u32_t buffer, u32_t bytes)
35773 + volatile struct usb_tio_request *tio_req = &usb_node->request;
35774 + unsigned long flag;
35776 + USB_TIO_LOCK(&tio_lock, flag);
35777 + usb_tio_wait_hrt();
35779 + tio_req->address = address;
35782 + * Is it necessary to make a local copy of the buffer? Any chance the URB is aborted before TIO finished the FIFO write?
35784 + tio_req->buffer = buffer;
35785 + tio_req->cmd = USB_TIO_WRITE_FIFO_SYNC;
35786 + tio_req->transfer_length = bytes;
35787 + USB_TIO_REQUEST_SET_MAGIC(tio_req);
35789 + * commit the request
35791 + usb_tio_commit_request(tio_req);
35792 + USB_TIO_UNLOCK(&tio_lock, flag);
35793 + return USB_TIO_OK;
35797 + * usb_tio_read_int_status()
35798 + * read and clear the interrupt status registers
35800 +void usb_tio_read_int_status(u8_t *int_usb, u16_t *int_tx, u16_t *int_rx)
35804 + * clear the interrupt must be syncronized with the TIO thread to prevent the racing condiiton
35805 + * that TIO thread try to set it at same time
35808 + "1: bset (%0), (%0), #0 \n\t" \
35809 + " jmpne.f 1b \n\t" \
35811 + : "a" (&usb_node->usb_vp_control)
35815 + *int_usb = usb_node->usb_vp_hw_int_usb;
35816 + *int_tx = cpu_to_le16(usb_node->usb_vp_hw_int_tx);
35817 + *int_rx = cpu_to_le16(usb_node->usb_vp_hw_int_rx);
35819 + //printk(KERN_INFO "int read %x, %x, %x\n", *int_usb, *int_tx, *int_rx);
35822 + * The interrupt status register is read-clean, so clear it now
35824 + usb_node->usb_vp_hw_int_usb = 0;
35825 + usb_node->usb_vp_hw_int_tx = 0;
35826 + usb_node->usb_vp_hw_int_rx = 0;
35829 + * release the lock bit
35831 + usb_node->usb_vp_control &= 0xfffe;
35834 +++ b/arch/ubicom32/mach-common/usb_tio.h
35837 + * arch/ubicom32/mach-common/usb_tio.h
35838 + * Definitions for usb_tio.c
35840 + * (C) Copyright 2009, Ubicom, Inc.
35842 + * This file is part of the Ubicom32 Linux Kernel Port.
35844 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
35845 + * it and/or modify it under the terms of the GNU General Public License
35846 + * as published by the Free Software Foundation, either version 2 of the
35847 + * License, or (at your option) any later version.
35849 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
35850 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
35851 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
35852 + * the GNU General Public License for more details.
35854 + * You should have received a copy of the GNU General Public License
35855 + * along with the Ubicom32 Linux Kernel Port. If not,
35856 + * see <http://www.gnu.org/licenses/>.
35858 + * Ubicom32 implementation derived from (with many thanks):
35864 +#include <linux/version.h>
35865 +#include <linux/kernel.h>
35866 +#include <linux/types.h>
35867 +#include <linux/errno.h>
35868 +#include <linux/err.h>
35869 +#include <asm/devtree.h>
35870 +#include <asm/ip5000.h>
35872 +#ifndef _USB_TIO_H
35873 +#define _USB_TIO_H
35875 +#undef USB_TIO_DEBUG
35877 +#define USB_TIO_REQUEST_MAGIC1 0x2307
35878 +#define USB_TIO_REQUEST_MAGIC2 0x0789
35879 +#if defined(USB_TIO_DEBUG)
35880 +#define USB_TIO_REQUEST_VERIFY_MAGIC(req) usb_tio_request_verify_magic(req)
35881 +#define USB_TIO_REQUEST_SET_MAGIC(req) usb_tio_request_set_magic(req)
35882 +#define USB_TIO_REQUEST_CLEAR_MAGIC(req) usb_tio_request_clear_magic(req)
35884 +#define USB_TIO_REQUEST_VERIFY_MAGIC(req)
35885 +#define USB_TIO_REQUEST_SET_MAGIC(req) usb_tio_request_set_magic(req)
35886 +#define USB_TIO_REQUEST_CLEAR_MAGIC(req)
35889 +enum USB_TIO_status {
35892 + USB_TIO_ERROR_COMMIT,
35895 +enum USB_TIO_cmds {
35896 + USB_TIO_READ16_SYNC,
35897 + USB_TIO_READ8_SYNC,
35898 + USB_TIO_READ_FIFO_SYNC,
35900 + USB_TIO_WRITE16_ASYNC,
35901 + USB_TIO_WRITE8_ASYNC,
35902 + USB_TIO_WRITE_FIFO_ASYNC,
35904 + USB_TIO_WRITE16_SYNC,
35905 + USB_TIO_WRITE8_SYNC,
35906 + USB_TIO_WRITE_FIFO_SYNC,
35910 +enum USB_TIO_state {
35912 + USB_TIO_DMA_SETUP,
35915 +struct usb_tio_request {
35916 + volatile u32_t address;
35918 + volatile u32_t data;
35919 + volatile u32_t buffer;
35921 + volatile u16_t cmd;
35922 + const volatile u16_t status;
35923 + volatile u32_t transfer_length;
35924 + volatile u32_t thread_mask;
35925 + volatile u16_t magic;
35928 +struct usbtio_node {
35929 + struct devtree_node dn;
35930 + volatile struct usb_tio_request * volatile pdesc;
35931 + struct usb_tio_request request;
35932 + volatile u32_t usb_vp_config;
35933 + volatile u32_t usb_vp_control;
35934 + const volatile u32_t usb_vp_status;
35935 + volatile u16_t usb_vp_hw_int_tx;
35936 + volatile u16_t usb_vp_hw_int_rx;
35937 + volatile u8_t usb_vp_hw_int_usb;
35938 + volatile u8_t usb_vp_hw_int_mask_usb;
35939 + volatile u16_t usb_vp_hw_int_mask_tx;
35940 + volatile u16_t usb_vp_hw_int_mask_rx;
35944 +extern struct usbtio_node *usb_node;
35945 +extern void ubi32_usb_init(void);
35948 +++ b/arch/ubicom32/mach-common/vdc_tio.c
35951 + * arch/ubicom32/mach-common/vdc_tio.c
35952 + * Generic initialization for VDC
35954 + * (C) Copyright 2009, Ubicom, Inc.
35956 + * This file is part of the Ubicom32 Linux Kernel Port.
35958 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
35959 + * it and/or modify it under the terms of the GNU General Public License
35960 + * as published by the Free Software Foundation, either version 2 of the
35961 + * License, or (at your option) any later version.
35963 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
35964 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
35965 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
35966 + * the GNU General Public License for more details.
35968 + * You should have received a copy of the GNU General Public License
35969 + * along with the Ubicom32 Linux Kernel Port. If not,
35970 + * see <http://www.gnu.org/licenses/>.
35972 + * Ubicom32 implementation derived from (with many thanks):
35978 +#include <linux/platform_device.h>
35979 +#include <linux/types.h>
35981 +#include <asm/devtree.h>
35982 +#include <asm/vdc_tio.h>
35985 + * Resources that this driver uses
35987 +static struct resource vdc_tio_resources[] = {
35993 + * The init routine will query the devtree and fill this in
35995 + .flags = IORESOURCE_IRQ,
35999 + * Receive IRQ (optional)
36003 + * The init routine will query the devtree and fill this in
36005 + .flags = IORESOURCE_IRQ,
36009 + * Memory Mapped Registers
36013 + * The init routine will query the devtree and fill this in
36015 + .flags = IORESOURCE_MEM,
36020 + * The platform_device structure which is passed to the driver
36022 +static struct platform_device vdc_tio_platform_device = {
36023 + .name = "ubicom32fb",
36025 + .resource = vdc_tio_resources,
36026 + .num_resources = ARRAY_SIZE(vdc_tio_resources),
36031 + * Checks the device tree and instantiates the driver if found
36033 +void __init vdc_tio_init(void)
36036 + * Check the device tree for the vdc_tio
36038 + struct vdc_tio_node *vdc_node =
36039 + (struct vdc_tio_node *)devtree_find_node("vdctio");
36041 + printk(KERN_WARNING "No vdc_tio found\n");
36046 + * Fill in the resources and platform data from devtree information
36048 + vdc_tio_resources[0].start = vdc_node->dn.sendirq;
36049 + vdc_tio_resources[1].start = vdc_node->dn.recvirq;
36050 + vdc_tio_resources[2].start = (u32_t)vdc_node->regs;
36051 + vdc_tio_resources[2].end = (u32_t)vdc_node->regs +
36052 + sizeof(struct vdc_tio_vp_regs);
36055 + * Try to get the device registered
36057 + if (platform_device_register(&vdc_tio_platform_device) < 0) {
36058 + printk(KERN_WARNING "VDC failed to register\n");
36062 +++ b/arch/ubicom32/mach-ip5k/board-ip5160dev.c
36065 + * arch/ubicom32/mach-ip5k/board-ip5160dev.c
36066 + * Platform initialization for ip5160dev board.
36068 + * (C) Copyright 2009, Ubicom, Inc.
36070 + * This file is part of the Ubicom32 Linux Kernel Port.
36072 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
36073 + * it and/or modify it under the terms of the GNU General Public License
36074 + * as published by the Free Software Foundation, either version 2 of the
36075 + * License, or (at your option) any later version.
36077 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
36078 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
36079 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
36080 + * the GNU General Public License for more details.
36082 + * You should have received a copy of the GNU General Public License
36083 + * along with the Ubicom32 Linux Kernel Port. If not,
36084 + * see <http://www.gnu.org/licenses/>.
36086 + * Ubicom32 implementation derived from (with many thanks):
36091 +#include <linux/device.h>
36092 +#include <linux/platform_device.h>
36093 +#include <linux/gpio.h>
36095 +#include <asm/board.h>
36096 +#include <asm/machdep.h>
36097 +#ifdef CONFIG_SERIAL_UBI32_SERDES
36098 +#include <asm/ubicom32suart.h>
36102 + * Factory Default Button on the board at PXn
36103 + * TODO: This is just a placeholder and it needs to include proper header files
36105 +struct ubicom32fdb_platform_data {
36107 + bool fdb_polarity;
36110 +static struct ubicom32fdb_platform_data ip5160dev_fdb_data = {
36112 + .fdb_polarity = true,
36115 +static struct platform_device ip5160dev_fdb_device = {
36116 + .name = "ubicom32fdb",
36119 + .platform_data = &ip5160dev_fdb_data,
36123 +#ifdef CONFIG_SERIAL_UBI32_SERDES
36124 +static struct resource ip5160dev_ubicom32_suart_resources[] = {
36128 + .flags = IORESOURCE_MEM,
36131 + .start = PORT_OTHER_INT(RD),
36132 + .end = PORT_OTHER_INT(RD),
36133 + .flags = IORESOURCE_IRQ,
36136 + .start = 240000000,
36137 + .end = 240000000,
36138 + .flags = UBICOM32_SUART_IORESOURCE_CLOCK,
36142 +static struct platform_device ip5160dev_ubicom32_suart_device = {
36143 + .name = "ubicom32suart",
36145 + .num_resources = ARRAY_SIZE(ip5160dev_ubicom32_suart_resources),
36146 + .resource = ip5160dev_ubicom32_suart_resources,
36151 + * List of all devices in our system
36153 +static struct platform_device *ip5160dev_devices[] __initdata = {
36154 +#ifdef CONFIG_SERIAL_UBI32_SERDES
36155 + &ip5160dev_ubicom32_suart_device,
36157 + &ip5160dev_fdb_device,
36162 + * Called to add the devices which we have on this board
36164 +static int __init ip5160dev_init(void)
36167 + printk(KERN_INFO "%s: registering device resources\n", __FUNCTION__);
36168 + platform_add_devices(ip5160dev_devices, ARRAY_SIZE(ip5160dev_devices));
36172 +arch_initcall(ip5160dev_init);
36174 +++ b/arch/ubicom32/mach-ip5k/board-ip5160rgw.c
36177 + * arch/ubicom32/mach-ip5k/board-ip5160rgw.c
36178 + * Platform initialization for ip5160rgw board.
36180 + * (C) Copyright 2009, Ubicom, Inc.
36182 + * This file is part of the Ubicom32 Linux Kernel Port.
36184 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
36185 + * it and/or modify it under the terms of the GNU General Public License
36186 + * as published by the Free Software Foundation, either version 2 of the
36187 + * License, or (at your option) any later version.
36189 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
36190 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
36191 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
36192 + * the GNU General Public License for more details.
36194 + * You should have received a copy of the GNU General Public License
36195 + * along with the Ubicom32 Linux Kernel Port. If not,
36196 + * see <http://www.gnu.org/licenses/>.
36198 + * Ubicom32 implementation derived from (with many thanks):
36203 +#include <linux/device.h>
36204 +#include <linux/platform_device.h>
36205 +#include <linux/gpio.h>
36206 +#include <asm/board.h>
36207 +#include <asm/machdep.h>
36210 + * Factory Default Button on the board at PXn
36211 + * TODO: This is just a placeholder and it needs to include proper header files
36213 +struct ubicom32fdb_platform_data {
36215 + bool fdb_polarity;
36218 +static struct ubicom32fdb_platform_data ip5160rgw_fdb_data = {
36220 + .fdb_polarity = true,
36223 +static struct platform_device ip5160rgw_fdb_device = {
36224 + .name = "ubicom32fdb",
36227 + .platform_data = &ip5160rgw_fdb_data,
36232 + * List of all devices in our system
36234 +static struct platform_device *ip5160rgw_devices[] __initdata = {
36235 + &ip5160rgw_fdb_device,
36240 + * Called to add the devices which we have on this board
36242 +static int __init ip5160rgw_init(void)
36245 + printk(KERN_INFO "%s: registering device resources\n", __FUNCTION__);
36246 + platform_add_devices(ip5160rgw_devices, ARRAY_SIZE(ip5160rgw_devices));
36250 +arch_initcall(ip5160rgw_init);
36252 +++ b/arch/ubicom32/mach-ip5k/board-ip5170dpf.c
36255 + * arch/ubicom32/mach-ip5k/board-ip5170dpf.c
36256 + * Platform initialization for ip5160dpf board.
36258 + * (C) Copyright 2009, Ubicom, Inc.
36260 + * This file is part of the Ubicom32 Linux Kernel Port.
36262 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
36263 + * it and/or modify it under the terms of the GNU General Public License
36264 + * as published by the Free Software Foundation, either version 2 of the
36265 + * License, or (at your option) any later version.
36267 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
36268 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
36269 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
36270 + * the GNU General Public License for more details.
36272 + * You should have received a copy of the GNU General Public License
36273 + * along with the Ubicom32 Linux Kernel Port. If not,
36274 + * see <http://www.gnu.org/licenses/>.
36276 + * Ubicom32 implementation derived from (with many thanks):
36281 +#include <linux/device.h>
36282 +#include <linux/platform_device.h>
36283 +#include <linux/gpio.h>
36284 +#include <linux/leds.h>
36286 +#include <linux/i2c.h>
36287 +#include <linux/i2c-gpio.h>
36289 +#include <linux/input.h>
36290 +#include <asm/board.h>
36291 +#include <asm/machdep.h>
36292 +#include <asm/ubicom32hid.h>
36293 +#include <asm/vdc_tio.h>
36298 + * WLAN PD9 (Note this is shared with MISO, but we don't use it)
36301 + * TODO: check triggers, are they generic?
36303 +static struct gpio_led ip5170dpf_gpio_leds[] = {
36305 + .name = "d31:green:WLAN1",
36306 + .default_trigger = "WLAN1",
36307 + .gpio = GPIO_RD_9,
36311 + .name = "d30:green:WPS",
36312 + .default_trigger = "WPS",
36313 + .gpio = GPIO_RD_8,
36318 +static struct gpio_led_platform_data ip5170dpf_gpio_led_platform_data = {
36320 + .leds = ip5170dpf_gpio_leds,
36323 +static struct platform_device ip5170dpf_gpio_leds_device = {
36324 + .name = "leds-gpio",
36327 + .platform_data = &ip5170dpf_gpio_led_platform_data,
36332 + * Backlight on the board PD0, hardware PWM
36334 +static const struct ubicom32hid_button ip5170dpf_ubicom32hid_buttons[] = {
36342 + .code = KEY_LEFT,
36347 + .code = KEY_RIGHT,
36352 + .code = KEY_DOWN,
36357 + .code = KEY_ENTER,
36362 + .code = KEY_MENU,
36372 +static const struct ubicom32hid_ir ip5170dpf_ubicom32hid_ircodes[] = {
36376 + .ir_code = 0xF807916E
36380 + .code = KEY_DOWN,
36381 + .ir_code = 0xF20D916E
36385 + .code = KEY_LEFT,
36386 + .ir_code = 0xF609916E
36390 + .code = KEY_RIGHT,
36391 + .ir_code = 0xF40B916E
36395 + .code = KEY_ENTER,
36396 + .ir_code = 0xF50A916E
36400 + .code = KEY_FN_F1,
36401 + .ir_code = 0xF906916E
36405 + .code = KEY_MENU,
36406 + .ir_code = 0xF708916E
36408 + { /* font size */
36410 + .code = KEY_FN_F2,
36411 + .ir_code = 0xF30C916E
36416 + .ir_code = 0xF10E916E
36420 + .code = KEY_VOLUMEUP,
36421 + .ir_code = 0xF00F916E
36425 + .code = KEY_VOLUMEDOWN,
36426 + .ir_code = 0xED12916E
36430 + .code = KEY_MUTE,
36431 + .ir_code = 0xEA15916E
36435 + .code = KEY_INFO,
36436 + .ir_code = 0xEF10916E
36440 + .code = KEY_FN_F3,
36441 + .ir_code = 0xEE11916E
36445 + .code = KEY_FN_F4,
36446 + .ir_code = 0xEB14916E
36450 + .code = KEY_POWER,
36451 + .ir_code = 0xFD02916E
36455 +static struct ubicom32hid_platform_data ip5170dpf_ubicom32hid_platform_data = {
36456 + .gpio_reset = GPIO_RA_4,
36457 + .gpio_reset_polarity = 0,
36458 + .type = UBICOM32HID_BL_TYPE_BINARY,
36460 + .default_intensity = 1,
36461 + .buttons = ip5170dpf_ubicom32hid_buttons,
36462 + .nbuttons = ARRAY_SIZE(ip5170dpf_ubicom32hid_buttons),
36463 + .ircodes = ip5170dpf_ubicom32hid_ircodes,
36464 + .nircodes = ARRAY_SIZE(ip5170dpf_ubicom32hid_ircodes),
36468 + * Devices on the I2C bus
36470 +static struct i2c_board_info __initdata ip5170dpf_i2c_board_info[] = {
36472 + * U24, ubicom32hid
36475 + .type = "ubicom32hid",
36477 + .platform_data = &ip5170dpf_ubicom32hid_platform_data,
36481 + * U14, CS4350 DAC, address 0x4B
36486 + * I2C bus on the board, SDA PF13, SCL PF14
36488 +static struct i2c_gpio_platform_data ip5170dpf_i2c_data = {
36489 + .sda_pin = GPIO_RF_13,
36490 + .scl_pin = GPIO_RF_14,
36491 + .sda_is_open_drain = 0,
36492 + .scl_is_open_drain = 0,
36493 + .scl_is_output_only = 1,
36497 +static struct platform_device ip5170dpf_i2c_device = {
36498 + .name = "i2c-gpio",
36501 + .platform_data = &ip5170dpf_i2c_data,
36506 + * List of all devices in our system
36508 +static struct platform_device *ip5170dpf_devices[] __initdata = {
36509 + &ip5170dpf_i2c_device,
36510 + &ip5170dpf_gpio_leds_device,
36515 + * Called to add the devices which we have on this board
36517 +static int __init ip5170dpf_init(void)
36523 + printk(KERN_INFO "%s: registering device resources\n", __FUNCTION__);
36524 + platform_add_devices(ip5170dpf_devices, ARRAY_SIZE(ip5170dpf_devices));
36526 + printk(KERN_INFO "%s: registering i2c resources\n", __FUNCTION__);
36527 + i2c_register_board_info(0, ip5170dpf_i2c_board_info, ARRAY_SIZE(ip5170dpf_i2c_board_info));
36532 +arch_initcall(ip5170dpf_init);
36534 +++ b/arch/ubicom32/mach-ip5k/Kconfig
36539 + select UBICOM32_V3
36543 + select FB_UBICOM32
36544 + select BACKLIGHT_LCD_SUPPORT
36545 + select BACKLIGHT_CLASS_DEVICE
36546 + select UBICOM_HID
36548 + select LEDS_CLASS
36551 + IP5170 Digital Picture Frame board, 8005-1113, IP5K-BEV-0011-13 v1.3
36554 + bool "IP5160Dev_Ver1Dot1"
36555 + select UBICOM32_V3
36557 + Ubicom StreamEngine 5000 Development Board, IP5K-BDV-0004-11 v1.1
36560 + bool "IP5160RGWEval_Ver2Rev2"
36561 + select UBICOM32_V3
36563 + Ubicom StreamEngine 5000 RGW Evaluation Board, IP5K-RGW-0004-11 v2.2
36565 +++ b/arch/ubicom32/mach-ip5k/Makefile
36568 +# arch/ubicom32/mach-ip5k/Makefile
36569 +# Makefile for boards which have an ip5k on them.
36571 +# (C) Copyright 2009, Ubicom, Inc.
36573 +# This file is part of the Ubicom32 Linux Kernel Port.
36575 +# The Ubicom32 Linux Kernel Port is free software: you can redistribute
36576 +# it and/or modify it under the terms of the GNU General Public License
36577 +# as published by the Free Software Foundation, either version 2 of the
36578 +# License, or (at your option) any later version.
36580 +# The Ubicom32 Linux Kernel Port is distributed in the hope that it
36581 +# will be useful, but WITHOUT ANY WARRANTY; without even the implied
36582 +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
36583 +# the GNU General Public License for more details.
36585 +# You should have received a copy of the GNU General Public License
36586 +# along with the Ubicom32 Linux Kernel Port. If not,
36587 +# see <http://www.gnu.org/licenses/>.
36589 +# Ubicom32 implementation derived from (with many thanks):
36595 +obj-$(CONFIG_IP5170DPF) += board-ip5170dpf.o
36596 +obj-$(CONFIG_IP5160DEV) += board-ip5160dev.o
36597 +obj-$(CONFIG_IP5160EVAL) += board-ip5160rgw.o
36599 +++ b/arch/ubicom32/mach-ip7k/board-ip7145dpf.c
36602 + * arch/ubicom32/mach-ip7k/board-ip7145dpf.c
36603 + * Board file for IP7145DPF, rev 1.0, P/N 8007-0410
36605 + * (C) Copyright 2009, Ubicom, Inc.
36607 + * This file is part of the Ubicom32 Linux Kernel Port.
36609 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
36610 + * it and/or modify it under the terms of the GNU General Public License
36611 + * as published by the Free Software Foundation, either version 2 of the
36612 + * License, or (at your option) any later version.
36614 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
36615 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
36616 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
36617 + * the GNU General Public License for more details.
36619 + * You should have received a copy of the GNU General Public License
36620 + * along with the Ubicom32 Linux Kernel Port. If not,
36621 + * see <http://www.gnu.org/licenses/>.
36623 + * Ubicom32 implementation derived from (with many thanks):
36628 +#include <linux/device.h>
36629 +#include <linux/platform_device.h>
36630 +#include <linux/gpio.h>
36632 +#include <linux/input.h>
36634 +#include <linux/i2c.h>
36635 +#include <linux/i2c-gpio.h>
36636 +#include <linux/i2c/pca953x.h>
36638 +#include <asm/board.h>
36639 +#include <asm/machdep.h>
36640 +#include <asm/ubicom32input.h>
36641 +#include <asm/ubicom32input_i2c.h>
36642 +#include <asm/ubicom32bl.h>
36643 +#include <asm/ubicom32lcdpower.h>
36644 +#include <asm/vdc_tio.h>
36646 +#include <asm/ubicom32sd.h>
36647 +#include <asm/sd_tio.h>
36648 +#include <asm/devtree.h>
36649 +#include <asm/audio.h>
36651 +#include <asm/ring_tio.h>
36653 +/******************************************************************************
36654 + * SD/IO Port F (Slot 1) platform data
36656 +static struct resource ip7145dpf_portf_sd_resources[] = {
36662 + * The init routine will query the devtree and fill this in
36664 + .flags = IORESOURCE_IRQ,
36672 + * The init routine will query the devtree and fill this in
36674 + .flags = IORESOURCE_IRQ,
36678 + * Memory Mapped Registers
36682 + * The init routine will query the devtree and fill this in
36684 + .flags = IORESOURCE_MEM,
36688 +static struct ubicom32sd_card ip7145dpf_portf_sd_cards[] = {
36690 + .pin_wp = IP7145DPF_IOB0,
36691 + .wp_polarity = 1,
36692 + .pin_pwr = IP7145DPF_IOB4,
36693 + .pin_cd = GPIO_RA_4,
36696 + .pin_wp = IP7145DPF_IOB1,
36697 + .wp_polarity = 1,
36698 + .pin_pwr = IP7145DPF_IOB5,
36699 + .pin_cd = GPIO_RA_6,
36703 +static struct ubicom32sd_platform_data ip7145dpf_portf_sd_platform_data = {
36705 + .cards = ip7145dpf_portf_sd_cards,
36708 +static struct platform_device ip7145dpf_portf_sd_device = {
36709 + .name = "ubicom32sd",
36711 + .resource = ip7145dpf_portf_sd_resources,
36712 + .num_resources = ARRAY_SIZE(ip7145dpf_portf_sd_resources),
36714 + .platform_data = &ip7145dpf_portf_sd_platform_data,
36720 + * ip7145dpf_portf_sd_init
36722 +static void ip7145dpf_portf_sd_init(void)
36725 + * Check the device tree for the sd_tio
36727 + struct sd_tio_node *sd_node = (struct sd_tio_node *)devtree_find_node("portf_sd");
36729 + printk(KERN_INFO "PortF SDTIO not found\n");
36734 + * Fill in the resources and platform data from devtree information
36736 + ip7145dpf_portf_sd_resources[0].start = sd_node->dn.sendirq;
36737 + ip7145dpf_portf_sd_resources[1].start = sd_node->dn.recvirq;
36738 + ip7145dpf_portf_sd_resources[2].start = (u32_t)&(sd_node->regs);
36739 + ip7145dpf_portf_sd_resources[2].end = (u32_t)&(sd_node->regs) + sizeof(sd_node->regs);
36741 + platform_device_register(&ip7145dpf_portf_sd_device);
36744 +/******************************************************************************
36745 + * SD/IO Port B (Slot 2) platform data
36747 +static struct resource ip7145dpf_portb_sd_resources[] = {
36753 + * The init routine will query the devtree and fill this in
36755 + .flags = IORESOURCE_IRQ,
36763 + * The init routine will query the devtree and fill this in
36765 + .flags = IORESOURCE_IRQ,
36769 + * Memory Mapped Registers
36773 + * The init routine will query the devtree and fill this in
36775 + .flags = IORESOURCE_MEM,
36779 +static struct ubicom32sd_card ip7145dpf_portb_sd_cards[] = {
36781 + .pin_wp = IP7145DPF_IOB2,
36782 + .wp_polarity = 1,
36783 + .pin_pwr = IP7145DPF_IOB6,
36784 + .pin_cd = IP7145DPF_IOB3,
36788 +static struct ubicom32sd_platform_data ip7145dpf_portb_sd_platform_data = {
36790 + .cards = ip7145dpf_portb_sd_cards,
36793 +static struct platform_device ip7145dpf_portb_sd_device = {
36794 + .name = "ubicom32sd",
36796 + .resource = ip7145dpf_portb_sd_resources,
36797 + .num_resources = ARRAY_SIZE(ip7145dpf_portb_sd_resources),
36799 + .platform_data = &ip7145dpf_portb_sd_platform_data,
36805 + * ip7145dpf_portb_sd_init
36807 +static void ip7145dpf_portb_sd_init(void)
36810 + * Check the device tree for the sd_tio
36812 + struct sd_tio_node *sd_node = (struct sd_tio_node *)devtree_find_node("portb_sd");
36814 + printk(KERN_INFO "PortB SDTIO not found\n");
36819 + * Fill in the resources and platform data from devtree information
36821 + ip7145dpf_portb_sd_resources[0].start = sd_node->dn.sendirq;
36822 + ip7145dpf_portb_sd_resources[1].start = sd_node->dn.recvirq;
36823 + ip7145dpf_portb_sd_resources[2].start = (u32_t)&(sd_node->regs);
36824 + ip7145dpf_portb_sd_resources[2].end = (u32_t)&(sd_node->regs) + sizeof(sd_node->regs);
36826 + platform_device_register(&ip7145dpf_portb_sd_device);
36830 +#ifdef IP7145DPF_USE_MMC_SPI
36831 +/******************************************************************************
36832 + * SPI over GPIO (MMC_SPI)
36834 +#include <linux/spi/spi.h>
36835 +#include <linux/spi/mmc_spi.h>
36836 +#include <linux/mmc/host.h>
36837 +#include <asm/ubicom32-spi-gpio.h>
36839 +#define MMC_CS GPIO_RF_5 // PF5 D3
36840 +#define MMC_CD GPIO_RA_4 // PA4 CD
36841 +#define MMC_WP IP7145DPF_IOB0 // IOB0 WP
36842 +#define MMC_PWR IP7145DPF_IOB4 // IOB4 PWR
36845 + * SPI bus over GPIO (for SD card)
36847 +static struct ubicom32_spi_gpio_platform_data ip7145dpf_spi_gpio_data = {
36848 + .pin_mosi = GPIO_RF_0, // PF0 CMD
36849 + .pin_miso = GPIO_RF_2, // PF2 D0
36850 + .pin_clk = GPIO_RF_1, // PF1 CLK
36851 + .bus_num = 0, // We'll call this SPI bus 0
36852 + .num_chipselect = 1, // only one device on this SPI bus
36855 +static struct platform_device ip7145dpf_spi_gpio_device = {
36856 + .name = "ubicom32-spi-gpio",
36859 + .platform_data = &ip7145dpf_spi_gpio_data,
36864 + * ip7145dpf_mmc_spi_setpower_slot_a
36865 + * Set the power state for slot A
36867 +static void ip7145dpf_mmc_spi_setpower_slot_a(struct device *dev, unsigned int vdd)
36869 + struct mmc_spi_platform_data *pd = dev->platform_data;
36872 + * Power is inverted, we could tell the IOB to do it, but it's cleaner this way.
36874 + if ((1 << vdd) & pd->ocr_mask) {
36875 + gpio_set_value(MMC_PWR, 0);
36878 + gpio_set_value(MMC_PWR, 1);
36882 + * ip7145dpf_mmc_spi_get_cd_slot_a
36883 + * Get the CD bit for slot A
36885 +static int ip7145dpf_mmc_spi_get_cd_slot_a(struct device *dev)
36888 + * Note that the sense of the GPIO is inverted
36890 + return !gpio_get_value(MMC_CD);
36894 + * ip7145dpf_mmc_spi_get_ro_slot_a
36895 + * Get the WP bit for slot A
36897 +static int ip7145dpf_mmc_spi_get_ro_slot_a(struct device *dev)
36900 + * Note that the sense of the GPIO is inverted, we could tell the IOB to do it, but
36901 + * it's clearer this way.
36903 + return !gpio_get_value(MMC_WP);
36907 + * ip7145dpf_mmc_spi_exit_slot_a
36908 + * Free the appropriate GPIOs for slot A SD slot.
36910 +static void ip7145dpf_mmc_spi_exit_slot_a(struct device *dev, void *appdata)
36912 + gpio_free(MMC_CD);
36913 + gpio_free(MMC_CS);
36914 + gpio_free(MMC_WP);
36915 + gpio_free(MMC_PWR);
36916 + platform_device_unregister(&ip7145dpf_spi_gpio_device);
36920 + * ip7145dpf_mmc_spi_init_slot_a
36921 + * Allocate the appropriate GPIOs for slot A SD slot.
36922 + * WP is on IOB0, CD is PA4, CS is on PF5
36923 + * TODO: make CD an interrupt
36925 +static int ip7145dpf_mmc_spi_init_slot_a(void)
36927 + int ret = gpio_request(MMC_CD, "mmc-a-cd");
36929 + printk(KERN_ERR "%s: could not request mmc-a-cd pin\n", __FUNCTION__);
36932 + gpio_direction_input(MMC_CD);
36934 + ret = gpio_request(MMC_CS, "mmc-a-cs");
36936 + printk(KERN_ERR "%s: could not request mmc-a-cs pin\n", __FUNCTION__);
36939 + gpio_direction_output(MMC_CS, 0);
36941 + ret = gpio_request(MMC_WP, "mmc-a-wp");
36943 + printk(KERN_ERR "%s: could not request mmc-a-wp pin\n", __FUNCTION__);
36946 + gpio_direction_input(MMC_WP);
36949 + * Start off with power off
36951 + ret = gpio_request(MMC_PWR, "mmc-a-pwr");
36953 + printk(KERN_ERR "%s: could not request mmc-a-pwr pin\n", __FUNCTION__);
36956 + ret = gpio_direction_output(MMC_PWR, 1);
36961 + gpio_free(MMC_WP);
36964 + gpio_free(MMC_CS);
36967 + gpio_free(MMC_CD);
36972 + * MMC_SPI driver (currently bitbang)
36974 +static struct mmc_spi_platform_data ip7145dpf_mmc_platform_data = {
36975 + .ocr_mask = MMC_VDD_33_34,
36976 + .exit = ip7145dpf_mmc_spi_exit_slot_a,
36977 + .get_ro = ip7145dpf_mmc_spi_get_ro_slot_a,
36978 + .get_cd = ip7145dpf_mmc_spi_get_cd_slot_a,
36980 + .setpower = ip7145dpf_mmc_spi_setpower_slot_a,
36981 + .powerup_msecs = 500,
36983 + .detect_delay = 100,
36985 + .caps = MMC_CAP_NEEDS_POLL,
36988 +static struct ubicom32_spi_gpio_controller_data ip7145dpf_mmc_controller_data = {
36989 + .pin_cs = MMC_CS,
36992 +static struct spi_board_info ip7145dpf_spi_board_info[] = {
36994 + .modalias = "mmc_spi",
36996 + .chip_select = 0,
36997 + .max_speed_hz = 2000000,
36998 + .platform_data = &ip7145dpf_mmc_platform_data,
36999 + .controller_data = &ip7145dpf_mmc_controller_data,
37002 +#endif /* IP7145DPF_USE_MMC_SPI */
37005 + * ip7145dpf_u72_setup
37006 + * Called by I2C to tell us that u72 is setup.
37008 + * This function is called by I2C to tell us that u72 has been setup. All
37009 + * devices which rely on this chip being initialized (or even present) need to
37010 + * be initialized in this function otherwise they may get initialized too early.
37012 + * Currently the only device depending on u72 is the SPI
37014 +static int __init ip7145dpf_u72_setup(struct i2c_client *client, unsigned gpio, unsigned ngpio, void *context)
37016 +#ifdef IP7145DPF_USE_MMC_SPI
37017 + if (ip7145dpf_mmc_spi_init_slot_a()) {
37018 + printk(KERN_ERR "%s: could not request mmc resources\n", __FUNCTION__);
37020 + printk(KERN_INFO "%s: registering SPI resources\n", __FUNCTION__);
37021 + spi_register_board_info(ip7145dpf_spi_board_info, ARRAY_SIZE(ip7145dpf_spi_board_info));
37022 + platform_device_register(&ip7145dpf_spi_gpio_device);
37026 + * Initialize the Port F/Port B SD slots
37028 + ip7145dpf_portf_sd_init();
37029 + ip7145dpf_portb_sd_init();
37034 +/******************************************************************************
37035 + * LCD VGH on the board at PE6
37037 +static struct ubicom32lcdpower_platform_data ip7145dpf_lcdpower_data = {
37038 + .vgh_gpio = GPIO_RE_6,
37039 + .vgh_polarity = true,
37042 +static struct platform_device ip7145dpf_lcdpower_device = {
37043 + .name = "ubicom32lcdpower",
37046 + .platform_data = &ip7145dpf_lcdpower_data,
37050 +/******************************************************************************
37051 + * Backlight on the board PD0, hardware PWM
37053 +static struct ubicom32bl_platform_data ip7145dpf_backlight_data = {
37054 + .type = UBICOM32BL_TYPE_PWM,
37055 + .pwm_channel = 2,
37056 + .pwm_prescale = 15,
37057 + .pwm_period = 60,
37058 + .default_intensity = 0x80,
37061 +static struct platform_device ip7145dpf_backlight_device = {
37062 + .name = "ubicom32bl",
37065 + .platform_data = &ip7145dpf_backlight_data,
37069 +/******************************************************************************
37070 + * Ubicom32Input on I2C, U48 MAX7310, address 0x18, 8 bits
37072 +static struct ubicom32input_i2c_button ip7145dpf_ubicom32input_i2c_u48_buttons[] = {
37081 + .code = KEY_LEFT,
37087 + .code = KEY_RIGHT,
37093 + .code = KEY_DOWN,
37099 + .code = KEY_ENTER,
37105 + .code = KEY_MENU,
37117 +static struct ubicom32input_i2c_platform_data ip7145dpf_ubicom32input_i2c_u48_platform_data = {
37118 + .buttons = ip7145dpf_ubicom32input_i2c_u48_buttons,
37119 + .nbuttons = ARRAY_SIZE(ip7145dpf_ubicom32input_i2c_u48_buttons),
37120 + .name = "Ubicom32 Input I2C U48",
37123 +/******************************************************************************
37124 + * Additional GPIO chips
37126 +static struct pca953x_platform_data ip7145dpf_gpio_u72_platform_data = {
37127 + .gpio_base = IP7145DPF_U72_BASE,
37128 + .setup = ip7145dpf_u72_setup,
37131 +/******************************************************************************
37132 + * Devices on the I2C bus
37134 +static struct i2c_board_info __initdata ip7145dpf_i2c_board_info[] = {
37136 + * U51, S35390A RTC, address 0x30
37139 + .type = "s35390a",
37144 + * U48, MAX7310 IO expander, 8 bits, address 0x18
37147 + .type = "ubicom32in_max7310",
37149 + .platform_data = &ip7145dpf_ubicom32input_i2c_u48_platform_data,
37153 + * U72, MAX7310 IOB expander, 8 bits, address 0x19
37156 + .type = "max7310",
37158 + .platform_data = &ip7145dpf_gpio_u72_platform_data,
37163 + * I2C bus on the board, SDA PE1, SCL PE2
37165 +static struct i2c_gpio_platform_data ip7145dpf_i2c_data = {
37166 + .sda_pin = GPIO_RE_1,
37167 + .scl_pin = GPIO_RE_2,
37168 + .sda_is_open_drain = 0,
37169 + .scl_is_open_drain = 0,
37172 +static struct platform_device ip7145dpf_i2c_device = {
37173 + .name = "i2c-gpio",
37176 + .platform_data = &ip7145dpf_i2c_data,
37180 +/******************************************************************************
37181 + * Use ubicom32input driver to monitor the various pushbuttons on this board.
37184 + * FACT_DEFAULT PF13
37187 + * Not sutable for the keypad buttons since those run on I2C GPIO. The polling
37188 + * of ubicom32input would seem to be excessive for this.
37190 + * TODO: pick some ubicom understood EV_xxx define for WPS and Fact Default
37192 +static struct ubicom32input_button ip7145dpf_ubicom32input_buttons[] = {
37195 + .code = KEY_FN_F1,
37196 + .gpio = GPIO_RF_12,
37202 + .code = KEY_FN_F2,
37203 + .gpio = GPIO_RF_13,
37204 + .desc = "Factory Default",
37209 + .code = KEY_POWER,
37210 + .gpio = GPIO_RE_4,
37216 +static struct ubicom32input_platform_data ip7145dpf_ubicom32input_data = {
37217 + .buttons = ip7145dpf_ubicom32input_buttons,
37218 + .nbuttons = ARRAY_SIZE(ip7145dpf_ubicom32input_buttons),
37221 +static struct platform_device ip7145dpf_ubicom32input_device = {
37222 + .name = "ubicom32input",
37225 + .platform_data = &ip7145dpf_ubicom32input_data,
37230 + * List of all devices in our system
37232 +static struct platform_device *ip7145dpf_devices[] __initdata = {
37233 + &ip7145dpf_i2c_device,
37234 + &ip7145dpf_lcdpower_device,
37235 + &ip7145dpf_backlight_device,
37236 + &ip7145dpf_ubicom32input_device,
37240 + * ip7145dpf_power_off
37241 + * Called to turn the power off for this board
37243 +static void ip7145dpf_power_off(void)
37245 + gpio_set_value(GPIO_RE_5, 0);
37250 + * Called to add the devices which we have on this board
37252 +static int __init ip7145dpf_init(void)
37255 + struct platform_device *audio_dev;
37259 +#ifdef CONFIG_UIO_UBICOM32RING
37260 + ring_tio_init("decoder_ring");
37264 + * Start up the video driver first
37269 + * Take over holding of the power from the system
37271 + ret = gpio_request(GPIO_RE_5, "power_hold");
37273 + printk(KERN_ERR "%s: could not request power hold GPIO\n", __FUNCTION__);
37275 + gpio_direction_output(GPIO_RE_5, 1);
37276 + mach_power_off = ip7145dpf_power_off;
37279 + * USB SEL_HOST_USB line
37281 + ret = gpio_request(GPIO_RF_11, "SEL_HOST_USB");
37283 + printk(KERN_ERR "%s: could not request SEL_HOST_USB GPIO\n", __FUNCTION__);
37285 + gpio_direction_output(GPIO_RF_11, 0);
37290 + audio_dev = audio_device_alloc("snd-ubi32-generic", "audio", "audio-i2sout", 0);
37292 + platform_device_register(audio_dev);
37296 + * Register all of the devices we have on this board
37298 + printk(KERN_INFO "%s: registering device resources\n", __FUNCTION__);
37299 + platform_add_devices(ip7145dpf_devices, ARRAY_SIZE(ip7145dpf_devices));
37302 + * Register all of the devices which sit on the I2C bus
37304 + printk(KERN_INFO "%s: registering i2c resources\n", __FUNCTION__);
37305 + i2c_register_board_info(0, ip7145dpf_i2c_board_info, ARRAY_SIZE(ip7145dpf_i2c_board_info));
37308 + * We have to initialize the SPI after the I2C IOB gets setup. SPI is initialized in
37309 + * ip7145dpf_u72_setup
37315 +arch_initcall(ip7145dpf_init);
37317 +++ b/arch/ubicom32/mach-ip7k/board-ip7160bringup.c
37320 + * arch/ubicom32/mach-ip7k/board-ip7160bringup.c
37321 + * Support for the IP7160 bringup board.
37323 + * (C) Copyright 2009, Ubicom, Inc.
37325 + * This file is part of the Ubicom32 Linux Kernel Port.
37327 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
37328 + * it and/or modify it under the terms of the GNU General Public License
37329 + * as published by the Free Software Foundation, either version 2 of the
37330 + * License, or (at your option) any later version.
37332 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
37333 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
37334 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
37335 + * the GNU General Public License for more details.
37337 + * You should have received a copy of the GNU General Public License
37338 + * along with the Ubicom32 Linux Kernel Port. If not,
37339 + * see <http://www.gnu.org/licenses/>.
37341 + * Ubicom32 implementation derived from (with many thanks):
37346 +#include <linux/device.h>
37347 +#include <linux/platform_device.h>
37348 +#include <linux/gpio.h>
37349 +#include <linux/leds.h>
37350 +#include <linux/delay.h>
37351 +#include <linux/input.h>
37353 +#include <asm/board.h>
37354 +#include <asm/machdep.h>
37355 +#include <asm/ubicom32input.h>
37357 +#ifdef CONFIG_SERIAL_UBI32_SERDES
37358 +#include <asm/ubicom32suart.h>
37362 + * Use ubicom32input driver to monitor the various pushbuttons on this board.
37365 + * FACT_DEFAULT PD6
37367 + * TODO: pick some ubicom understood EV_xxx define for WPS and Fact Default
37369 +static struct ubicom32input_button ip7160bringup_ubicom32input_buttons[] = {
37372 + .code = KEY_FN_F1,
37373 + .gpio = GPIO_RD_5,
37379 + .code = KEY_FN_F2,
37380 + .gpio = GPIO_RD_6,
37381 + .desc = "Factory Default",
37386 +static struct ubicom32input_platform_data ip7160bringup_ubicom32input_data = {
37387 + .buttons = ip7160bringup_ubicom32input_buttons,
37388 + .nbuttons = ARRAY_SIZE(ip7160bringup_ubicom32input_buttons),
37391 +static struct platform_device ip7160bringup_ubicom32input_device = {
37392 + .name = "ubicom32input",
37395 + .platform_data = &ip7160bringup_ubicom32input_data,
37399 +#ifdef CONFIG_SERIAL_UBI32_SERDES
37400 +static struct resource ip7160bringup_ubicom32_suart_resources[] = {
37404 + .flags = IORESOURCE_MEM,
37407 + .start = PORT_OTHER_INT(RE),
37408 + .end = PORT_OTHER_INT(RE),
37409 + .flags = IORESOURCE_IRQ,
37412 + .start = 250000000,
37413 + .end = 250000000,
37414 + .flags = UBICOM32_SUART_IORESOURCE_CLOCK,
37418 +static struct platform_device ip7160bringup_ubicom32_suart_device = {
37419 + .name = "ubicom32suart",
37421 + .num_resources = ARRAY_SIZE(ip7160bringup_ubicom32_suart_resources),
37422 + .resource = ip7160bringup_ubicom32_suart_resources,
37427 + * List of all devices in our system
37429 +static struct platform_device *ip7160bringup_devices[] __initdata = {
37430 +#ifdef CONFIG_SERIAL_UBI32_SERDES
37431 + &ip7160bringup_ubicom32_suart_device,
37433 + &ip7160bringup_ubicom32input_device,
37437 + * ip7160bringup_init
37438 + * Called to add the devices which we have on this board
37440 +static int __init ip7160bringup_init(void)
37446 + printk(KERN_INFO "%s: registering device resources\n", __FUNCTION__);
37447 + platform_add_devices(ip7160bringup_devices, ARRAY_SIZE(ip7160bringup_devices));
37452 +arch_initcall(ip7160bringup_init);
37454 +++ b/arch/ubicom32/mach-ip7k/board-ip7160dpf.c
37457 + * arch/ubicom32/mach-ip7k/board-ip7160dpf.c
37458 + * Platform initialization for ip7160dpf board.
37460 + * (C) Copyright 2009, Ubicom, Inc.
37462 + * This file is part of the Ubicom32 Linux Kernel Port.
37464 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
37465 + * it and/or modify it under the terms of the GNU General Public License
37466 + * as published by the Free Software Foundation, either version 2 of the
37467 + * License, or (at your option) any later version.
37469 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
37470 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
37471 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
37472 + * the GNU General Public License for more details.
37474 + * You should have received a copy of the GNU General Public License
37475 + * along with the Ubicom32 Linux Kernel Port. If not,
37476 + * see <http://www.gnu.org/licenses/>.
37478 + * Ubicom32 implementation derived from (with many thanks):
37483 +#include <linux/device.h>
37484 +#include <linux/platform_device.h>
37485 +#include <linux/delay.h>
37486 +#include <linux/gpio.h>
37488 +#include <linux/i2c.h>
37489 +#include <linux/i2c-gpio.h>
37491 +#include <linux/input.h>
37493 +#include <asm/board.h>
37494 +#include <asm/machdep.h>
37495 +#include <asm/ubicom32hid.h>
37496 +#include <asm/vdc_tio.h>
37497 +#include <asm/audio.h>
37500 + * Backlight on the board PD0, hardware PWM
37502 +static const struct ubicom32hid_button ip7160dpf_ubicom32hid_buttons[] = {
37510 + .code = KEY_LEFT,
37515 + .code = KEY_RIGHT,
37520 + .code = KEY_DOWN,
37525 + .code = KEY_ENTER,
37530 + .code = KEY_MENU,
37540 +static const struct ubicom32hid_ir ip7160dpf_ubicom32hid_ircodes[] = {
37544 + .ir_code = 0xF807916E
37548 + .code = KEY_DOWN,
37549 + .ir_code = 0xF20D916E
37553 + .code = KEY_LEFT,
37554 + .ir_code = 0xF609916E
37558 + .code = KEY_RIGHT,
37559 + .ir_code = 0xF40B916E
37563 + .code = KEY_ENTER,
37564 + .ir_code = 0xF50A916E
37568 + .code = KEY_FN_F1,
37569 + .ir_code = 0xF906916E
37573 + .code = KEY_MENU,
37574 + .ir_code = 0xF708916E
37576 + { /* font size */
37578 + .code = KEY_FN_F2,
37579 + .ir_code = 0xF30C916E
37584 + .ir_code = 0xF10E916E
37588 + .code = KEY_VOLUMEUP,
37589 + .ir_code = 0xF00F916E
37593 + .code = KEY_VOLUMEDOWN,
37594 + .ir_code = 0xED12916E
37598 + .code = KEY_MUTE,
37599 + .ir_code = 0xEA15916E
37603 + .code = KEY_INFO,
37604 + .ir_code = 0xEF10916E
37608 + .code = KEY_FN_F3,
37609 + .ir_code = 0xEE11916E
37613 + .code = KEY_FN_F4,
37614 + .ir_code = 0xEB14916E
37618 + .code = KEY_POWER,
37619 + .ir_code = 0xFD02916E
37623 +static struct ubicom32hid_platform_data ip7160dpf_ubicom32hid_platform_data = {
37624 + .gpio_reset = GPIO_RI_5,
37625 + .gpio_reset_polarity = 0,
37626 + .type = UBICOM32HID_BL_TYPE_PWM,
37628 + .default_intensity = 128,
37629 + .buttons = ip7160dpf_ubicom32hid_buttons,
37630 + .nbuttons = ARRAY_SIZE(ip7160dpf_ubicom32hid_buttons),
37631 + .ircodes = ip7160dpf_ubicom32hid_ircodes,
37632 + .nircodes = ARRAY_SIZE(ip7160dpf_ubicom32hid_ircodes),
37636 + * Devices on the I2C bus
37637 + * This board has a "bus 2" which is isolated from the main bus by U47
37638 + * and pin RI0. It should be safe to always enable bus 2 by setting
37639 + * RI0 to low, however, it should be noted that on all existing configurations
37640 + * of this board, U49 and U51 are not populated.
37642 +static struct i2c_board_info __initdata ip7160dpf_i2c_board_info[] = {
37644 + * U37, CS4350 DAC, address 0x4B, bus 2
37645 + * THIS ENTRY MUST BE FIRST
37648 + .type = "cs4350",
37653 + * U24, ubicom32hid
37656 + .type = "ubicom32hid",
37658 + .platform_data = &ip7160dpf_ubicom32hid_platform_data,
37662 + * U49, ISL29001 Ambient Light Sensor, address 0x44, bus 2 (may not be stuffed)
37666 + * U51, S35390A RTC, address 0x30, bus 2 (may not be stuffed)
37668 +#ifdef CONFIG_RTC_DRV_S35390A
37670 + .type = "s35390a",
37677 + * I2C bus on the board, SDA PI1, SCL PI2
37679 +static struct i2c_gpio_platform_data ip7160dpf_i2c_data = {
37680 + .sda_pin = GPIO_RI_1,
37681 + .scl_pin = GPIO_RI_2,
37682 + .sda_is_open_drain = 0,
37683 + .scl_is_open_drain = 0,
37684 + .scl_is_output_only = 1,
37688 +static struct platform_device ip7160dpf_i2c_device = {
37689 + .name = "i2c-gpio",
37692 + .platform_data = &ip7160dpf_i2c_data,
37697 + * List of all devices in our system
37699 +static struct platform_device *ip7160dpf_devices[] __initdata = {
37700 + &ip7160dpf_i2c_device,
37704 + * ip7160dpf_power_off
37705 + * Called to turn the power off for this board
37707 +static void ip7160dpf_power_off(void)
37709 + gpio_set_value(GPIO_RF_14, 0);
37714 + * Called to add the devices which we have on this board
37716 +static int __init ip7160dpf_init(void)
37719 + struct platform_device *audio_dev;
37724 + * Hold the POWER_HOLD line
37726 + ret = gpio_request(GPIO_RF_14, "POWER_HOLD");
37728 + printk(KERN_ERR "%s: could not request POWER_HOLD GPIO\n", __FUNCTION__);
37730 + gpio_direction_output(GPIO_RF_14, 1);
37731 + mach_power_off = ip7160dpf_power_off;
37734 + * USB SEL_HOST_USB line
37736 + ret = gpio_request(GPIO_RI_13, "SEL_HOST_USB");
37738 + printk(KERN_ERR "%s: could not request SEL_HOST_USB GPIO\n", __FUNCTION__);
37740 + gpio_direction_output(GPIO_RI_13, 0);
37743 + * USB/DAC nRESET line
37745 + ret = gpio_request(GPIO_RI_3, "USB_DAC_nRESET");
37747 + printk(KERN_ERR "%s: could not request USB_DAC_nRESET GPIO\n", __FUNCTION__);
37749 + gpio_direction_output(GPIO_RI_3, 0);
37751 + gpio_direction_output(GPIO_RI_3, 1);
37754 + * I2C BUS2 Disable line
37756 + ret = gpio_request(GPIO_RI_0, "DISABLE_BUS2");
37758 + printk(KERN_ERR "%s: could not request DISABLE_BUS2 GPIO\n", __FUNCTION__);
37760 + gpio_direction_output(GPIO_RI_0, 0);
37764 + printk(KERN_INFO "%s: registering device resources\n", __FUNCTION__);
37765 + platform_add_devices(ip7160dpf_devices, ARRAY_SIZE(ip7160dpf_devices));
37768 + * Allocate the audio driver if we can
37770 + audio_dev = audio_device_alloc("snd-ubi32-cs4350", "audio-i2sout", 0);
37772 + ip7160dpf_i2c_board_info[0].platform_data = audio_dev;
37775 + printk(KERN_INFO "%s: registering i2c resources\n", __FUNCTION__);
37776 + i2c_register_board_info(0, ip7160dpf_i2c_board_info, ARRAY_SIZE(ip7160dpf_i2c_board_info));
37781 +arch_initcall(ip7160dpf_init);
37783 +++ b/arch/ubicom32/mach-ip7k/board-ip7160rgw.c
37786 + * arch/ubicom32/mach-ip7k/board-ip7160rgw.c
37787 + * Platform initialization for ip7160rgw board.
37789 + * (C) Copyright 2009, Ubicom, Inc.
37791 + * This file is part of the Ubicom32 Linux Kernel Port.
37793 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
37794 + * it and/or modify it under the terms of the GNU General Public License
37795 + * as published by the Free Software Foundation, either version 2 of the
37796 + * License, or (at your option) any later version.
37798 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
37799 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
37800 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
37801 + * the GNU General Public License for more details.
37803 + * You should have received a copy of the GNU General Public License
37804 + * along with the Ubicom32 Linux Kernel Port. If not,
37805 + * see <http://www.gnu.org/licenses/>.
37807 + * Ubicom32 implementation derived from (with many thanks):
37812 +#include <linux/device.h>
37813 +#include <linux/platform_device.h>
37814 +#include <linux/gpio.h>
37815 +#include <linux/leds.h>
37816 +#include <linux/delay.h>
37817 +#include <linux/input.h>
37818 +#include <linux/spi/spi.h>
37820 +#include <asm/board.h>
37821 +#include <asm/machdep.h>
37822 +#include <asm/ubicom32input.h>
37824 +#ifdef CONFIG_SERIAL_UBI32_SERDES
37825 +#include <asm/ubicom32suart.h>
37828 +#include <asm/ubicom32-spi-gpio.h>
37829 +#include <asm/switch-dev.h>
37831 +#ifdef CONFIG_IP7160RGWLCD
37832 +#include <linux/i2c.h>
37833 +#include <linux/i2c-gpio.h>
37835 + * LCD Adapter board 8007-092x support
37837 + * Touch controller
37839 + * Connected via I2C bus, interrupt on PA6
37841 +#include <linux/i2c/tsc2007.h>
37844 + * ip7160rgwlcd_tsc2007_exit_platform_hw
37846 +static void ip7160rgwlcd_tsc2007_exit_platform_hw(void)
37848 + UBICOM32_IO_PORT(RA)->ctl0 &= ~(0x03 << 17);
37849 + gpio_free(GPIO_RA_5);
37853 + * ip7160rgwlcd_tsc2007_init_platform_hw
37855 +static int ip7160rgwlcd_tsc2007_init_platform_hw(void)
37857 + int res = gpio_request(GPIO_RA_5, "TSC2007_IRQ");
37862 + UBICOM32_IO_PORT(RA)->ctl0 &= ~(0x03 << 17);
37863 + UBICOM32_IO_PORT(RA)->ctl0 |= (0x02 << 17);
37868 + * ip7160rgwlcd_tsc2007_get_pendown_state
37870 +static int ip7160rgwlcd_tsc2007_get_pendown_state(void)
37872 + return !gpio_get_value(GPIO_RA_5);
37875 +static struct tsc2007_platform_data ip7160rgwlcd_tsc2007_data = {
37877 + .x_plate_ohms = 350,
37878 + .get_pendown_state = ip7160rgwlcd_tsc2007_get_pendown_state,
37879 + .init_platform_hw = ip7160rgwlcd_tsc2007_init_platform_hw,
37880 + .exit_platform_hw = ip7160rgwlcd_tsc2007_exit_platform_hw,
37883 +/******************************************************************************
37884 + * I2C bus on the board, SDA PI14, SCL PI13
37886 +static struct i2c_gpio_platform_data ip7160rgwlcd_i2c_data = {
37887 + .sda_pin = GPIO_RI_14,
37888 + .scl_pin = GPIO_RI_13,
37889 + .sda_is_open_drain = 0,
37890 + .scl_is_open_drain = 0,
37894 +static struct platform_device ip7160rgwlcd_i2c_device = {
37895 + .name = "i2c-gpio",
37898 + .platform_data = &ip7160rgwlcd_i2c_data,
37902 +static struct i2c_board_info __initdata ip7160rgwlcd_i2c_board_info[] = {
37904 + .type = "tsc2007",
37906 + .irq = 45, // RA5
37907 + .platform_data = &ip7160rgwlcd_tsc2007_data,
37914 + * SPI bus over GPIO for Gigabit Ethernet Switch
37921 +static struct ubicom32_spi_gpio_platform_data ip7160rgw_spi_gpio_data = {
37922 + .pin_mosi = GPIO_RE_0,
37923 + .pin_miso = GPIO_RE_1,
37924 + .pin_clk = GPIO_RE_3,
37925 + .bus_num = 0, // We'll call this SPI bus 0
37926 + .num_chipselect = 1, // only one device on this SPI bus
37927 + .clk_default = 1,
37930 +static struct platform_device ip7160rgw_spi_gpio_device = {
37931 + .name = "ubicom32-spi-gpio",
37934 + .platform_data = &ip7160rgw_spi_gpio_data,
37938 +static struct ubicom32_spi_gpio_controller_data ip7160rgw_bcm539x_controller_data = {
37939 + .pin_cs = GPIO_RE_2,
37942 +static struct switch_core_platform_data ip7160rgw_bcm539x_platform_data = {
37943 + .flags = SWITCH_DEV_FLAG_HW_RESET,
37944 + .pin_reset = GPIO_RE_4,
37945 + .name = "bcm539x",
37948 +static struct spi_board_info ip7160rgw_spi_board_info[] = {
37950 + .modalias = "bcm539x-spi",
37952 + .chip_select = 0,
37953 + .max_speed_hz = 2000000,
37954 + .platform_data = &ip7160rgw_bcm539x_platform_data,
37955 + .controller_data = &ip7160rgw_bcm539x_controller_data,
37956 + .mode = SPI_MODE_3,
37963 + * WLAN1 PD0 (PWM capable)
37969 + * TODO: check triggers, are they generic?
37971 +static struct gpio_led ip7160rgw_gpio_leds[] = {
37973 + .name = "d53:green:WLAN1",
37974 + .default_trigger = "WLAN1",
37975 + .gpio = GPIO_RD_0,
37979 + .name = "d54:green:WLAN2",
37980 + .default_trigger = "WLAN2",
37981 + .gpio = GPIO_RD_1,
37985 + .name = "d55:green:USB",
37986 + .default_trigger = "USB",
37987 + .gpio = GPIO_RD_2,
37991 + .name = "d56:green:Status",
37992 + .default_trigger = "Status",
37993 + .gpio = GPIO_RD_3,
37997 + .name = "d57:green:WPS",
37998 + .default_trigger = "WPS",
37999 + .gpio = GPIO_RD_4,
38004 +static struct gpio_led_platform_data ip7160rgw_gpio_led_platform_data = {
38006 + .leds = ip7160rgw_gpio_leds,
38009 +static struct platform_device ip7160rgw_gpio_leds_device = {
38010 + .name = "leds-gpio",
38013 + .platform_data = &ip7160rgw_gpio_led_platform_data,
38018 + * Use ubicom32input driver to monitor the various pushbuttons on this board.
38021 + * FACT_DEFAULT PD6
38023 + * TODO: pick some ubicom understood EV_xxx define for WPS and Fact Default
38025 +static struct ubicom32input_button ip7160rgw_ubicom32input_buttons[] = {
38028 + .code = KEY_FN_F1,
38029 + .gpio = GPIO_RD_5,
38035 + .code = KEY_FN_F2,
38036 + .gpio = GPIO_RD_6,
38037 + .desc = "Factory Default",
38042 +static struct ubicom32input_platform_data ip7160rgw_ubicom32input_data = {
38043 + .buttons = ip7160rgw_ubicom32input_buttons,
38044 + .nbuttons = ARRAY_SIZE(ip7160rgw_ubicom32input_buttons),
38047 +static struct platform_device ip7160rgw_ubicom32input_device = {
38048 + .name = "ubicom32input",
38051 + .platform_data = &ip7160rgw_ubicom32input_data,
38055 +#ifdef CONFIG_SERIAL_UBI32_SERDES
38056 +static struct resource ip7160rgw_ubicom32_suart_resources[] = {
38060 + .flags = IORESOURCE_MEM,
38063 + .start = PORT_OTHER_INT(RE),
38064 + .end = PORT_OTHER_INT(RE),
38065 + .flags = IORESOURCE_IRQ,
38068 + .start = 250000000,
38069 + .end = 250000000,
38070 + .flags = UBICOM32_SUART_IORESOURCE_CLOCK,
38074 +static struct platform_device ip7160rgw_ubicom32_suart_device = {
38075 + .name = "ubicom32suart",
38077 + .num_resources = ARRAY_SIZE(ip7160rgw_ubicom32_suart_resources),
38078 + .resource = ip7160rgw_ubicom32_suart_resources,
38083 + * List of all devices in our system
38085 +static struct platform_device *ip7160rgw_devices[] __initdata = {
38086 +#ifdef CONFIG_SERIAL_UBI32_SERDES
38087 + &ip7160rgw_ubicom32_suart_device,
38089 + &ip7160rgw_ubicom32input_device,
38090 + &ip7160rgw_gpio_leds_device,
38091 + &ip7160rgw_spi_gpio_device,
38092 +#ifdef CONFIG_IP7160RGWLCD
38093 + &ip7160rgwlcd_i2c_device,
38099 + * Called to add the devices which we have on this board
38101 +static int __init ip7160rgw_init(void)
38106 + * Rev 1.2 boards have spi in a different place than 1.1/1.0
38108 + if (strcmp(board_get_revision(), "1.2") == 0) {
38109 + ip7160rgw_spi_gpio_data.pin_mosi = GPIO_RD_7;
38115 + * Reserve switch SPI CS on behalf on switch driver
38117 + if (gpio_request(ip7160rgw_bcm539x_controller_data.pin_cs, "switch-bcm539x-cs")) {
38118 + printk(KERN_WARNING "Could not request cs of switch SPI I/F\n");
38121 + gpio_direction_output(ip7160rgw_bcm539x_controller_data.pin_cs, 1);
38123 + printk(KERN_INFO "%s: registering device resources\n", __FUNCTION__);
38124 + platform_add_devices(ip7160rgw_devices, ARRAY_SIZE(ip7160rgw_devices));
38126 + printk(KERN_INFO "%s: registering SPI resources\n", __FUNCTION__);
38127 + spi_register_board_info(ip7160rgw_spi_board_info, ARRAY_SIZE(ip7160rgw_spi_board_info));
38129 +#ifdef CONFIG_IP7160RGWLCD
38130 + printk(KERN_INFO "%s: registering i2c resources\n", __FUNCTION__);
38131 + i2c_register_board_info(0, ip7160rgwlcd_i2c_board_info, ARRAY_SIZE(ip7160rgwlcd_i2c_board_info));
38132 + printk(KERN_INFO "IP7160 RGW + LCD\n");
38134 + printk(KERN_INFO "IP7160 RGW\n");
38139 +arch_initcall(ip7160rgw_init);
38141 +++ b/arch/ubicom32/mach-ip7k/board-ip7500av.c
38144 + * arch/ubicom32/mach-ip7k/board-ip7500av.c
38145 + * Support for IP7500 Audio Video Board + CPU module board.
38147 + * This file supports the IP7500 Audio Video Board:
38148 + * 8007-0810 Rev 1.0
38149 + * with one of the following CPU module boards:
38150 + * 8007-0510 Rev 1.0
38151 + * 8007-0510A Rev 1.0 (with ethernet)
38153 + * DIP Switch SW2 configuration: (*) default
38154 + * POS 1: on(*) = PCI enabled, off = PCI disabled
38155 + * POS 2: on(*) = TTYX => PA6, off = TTYX => PF12
38156 + * POS 3: on(*) = TTYY => PA7, off = TTYY => PF15
38159 + * (C) Copyright 2009, Ubicom, Inc.
38161 + * This file is part of the Ubicom32 Linux Kernel Port.
38163 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
38164 + * it and/or modify it under the terms of the GNU General Public License
38165 + * as published by the Free Software Foundation, either version 2 of the
38166 + * License, or (at your option) any later version.
38168 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
38169 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
38170 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
38171 + * the GNU General Public License for more details.
38173 + * You should have received a copy of the GNU General Public License
38174 + * along with the Ubicom32 Linux Kernel Port. If not,
38175 + * see <http://www.gnu.org/licenses/>.
38178 +#include <linux/platform_device.h>
38179 +#include <linux/device.h>
38180 +#include <linux/gpio.h>
38181 +#include <linux/i2c.h>
38182 +#include <linux/i2c-gpio.h>
38183 +#include <linux/delay.h>
38184 +#include <asm/board.h>
38185 +#include <asm/machdep.h>
38186 +#include <asm/ring_tio.h>
38187 +#include <asm/vdc_tio.h>
38188 +#include <asm/audio.h>
38189 +#include <asm/ubi32-pcm.h>
38190 +#include <asm/ubi32-cs4384.h>
38192 +/******************************************************************************
38193 + * Devices on the I2C bus
38195 + * BEWARE of changing the order of things in this array as we depend on
38196 + * certain things to be in certain places.
38198 +static struct i2c_board_info __initdata ip7500av_i2c_board_info[] = {
38200 + * U6, CS4384 DAC, address 0x19
38203 + .type = "cs4384",
38209 + * I2C bus on the board, SDA PD1, SCL PD2
38211 +static struct i2c_gpio_platform_data ip7500av_i2c_data = {
38212 + .sda_pin = GPIO_RD_6,
38213 + .scl_pin = GPIO_RD_3,
38214 + .sda_is_open_drain = 0,
38215 + .scl_is_open_drain = 0,
38219 +static struct platform_device ip7500av_i2c_device = {
38220 + .name = "i2c-gpio",
38223 + .platform_data = &ip7500av_i2c_data,
38228 + * List of possible mclks we can generate. This depends on the CPU frequency.
38230 +static struct ubi32_cs4384_mclk_entry ip7500av_cs4384_mclk_entries[] = {
38232 + .rate = 12288000,
38236 + .rate = 11289600,
38242 + * List of all devices in our system
38244 +static struct platform_device *ip7500av_devices[] __initdata = {
38245 + &ip7500av_i2c_device,
38249 + * ip7500av_vdac_write
38251 +static int __init ip7500av_vdac_write(int reg, int val)
38253 + struct i2c_adapter *adap;
38254 + struct i2c_msg msg[1];
38255 + unsigned char data[2];
38258 + adap = i2c_get_adapter(0);
38260 + printk(KERN_WARNING "%s: failed to get i2c adapter\n", __FUNCTION__);
38263 + msg->addr = 0x2B;
38269 + err = i2c_transfer(adap, msg, 1);
38270 + i2c_put_adapter(adap);
38278 + * ip7500av_vdac_init
38279 + * Initializes the video DAC via I2C
38281 + * Equivalent mode line: 720x480p = 27 Mhz, 720 736 800 858 480 484 492 525
38283 +static int __init ip7500av_vdac_init(void)
38287 + printk(KERN_INFO "Initializing ADV7393 DAC\n");
38292 + if (gpio_request(GPIO_RF_6, "VDAC Reset")) {
38293 + printk(KERN_WARNING "%s: failed to allocate VDAC Reset\n", __FUNCTION__);
38296 + gpio_direction_output(GPIO_RF_6, 0);
38298 + gpio_set_value(GPIO_RF_6, 1);
38301 + * See table 100 of ADV7393 data sheet: 16-bit 525p YCrCb In, YPbPr Out
38303 + err = ip7500av_vdac_write(0x17, 0x02);
38305 + printk(KERN_WARNING "%s: failed to write VDAC\n", __FUNCTION__);
38308 + err = ip7500av_vdac_write(0x00, 0x1c);
38310 + printk(KERN_WARNING "%s: failed to write VDAC\n", __FUNCTION__);
38313 + err = ip7500av_vdac_write(0x01, 0x10);
38315 + printk(KERN_WARNING "%s: failed to write VDAC\n", __FUNCTION__);
38318 + err = ip7500av_vdac_write(0x31, 0x01);
38320 + printk(KERN_WARNING "%s: failed to write VDAC\n", __FUNCTION__);
38323 +#ifdef IP7500AV_VDAC_SWAP_PBPR
38324 + err = ip7500av_vdac_write(0x35, 0x08);
38326 + printk(KERN_WARNING "%s: failed to write VDAC\n", __FUNCTION__);
38330 +#ifdef IP7500AV_VDAC_FULL_RANGE
38331 + err = ip7500av_vdac_write(0x30, 0x02);
38333 + printk(KERN_WARNING "%s: failed to write VDAC\n", __FUNCTION__);
38339 +late_initcall(ip7500av_vdac_init);
38343 + * Called to add the devices which we have on this board
38345 +static int __init ip7500av_init(void)
38347 + struct platform_device *audio_dev;
38348 + struct platform_device *audio_dev2;
38349 + struct ubi32_cs4384_platform_data *cs4384_pd;
38357 + printk(KERN_INFO "%s: registering device resources\n", __FUNCTION__);
38358 + platform_add_devices(ip7500av_devices, ARRAY_SIZE(ip7500av_devices));
38363 + audio_dev = audio_device_alloc("snd-ubi32-cs4384", "audio", "audio-i2sout",
38364 + sizeof(struct ubi32_cs4384_platform_data));
38367 + * Attempt to figure out a good divisor. This will only work
38368 + * assuming the core frequency is compatible.
38371 + unsigned int freq = processor_frequency();
38372 + for (i = 0; i < ARRAY_SIZE(ip7500av_cs4384_mclk_entries); i++) {
38373 + unsigned int div;
38374 + unsigned int rate = ip7500av_cs4384_mclk_entries[i].rate / 1000;
38375 + div = ((freq / rate) + 500) / 1000;
38376 + ip7500av_cs4384_mclk_entries[i].div = div;
38377 + printk("CS4384 mclk %d rate %u000Hz div %u act %u\n", i, rate, div, freq / div);
38380 + cs4384_pd = audio_device_priv(audio_dev);
38381 + cs4384_pd->mclk_src = UBI32_CS4384_MCLK_PWM_0;
38382 + cs4384_pd->n_mclk = ARRAY_SIZE(ip7500av_cs4384_mclk_entries);
38383 + cs4384_pd->mclk_entries = ip7500av_cs4384_mclk_entries;
38384 + ip7500av_i2c_board_info[0].platform_data = audio_dev;
38389 + if (gpio_request(GPIO_RF_4, "DAC Reset") == 0) {
38390 + gpio_direction_output(GPIO_RF_4, 0);
38392 + gpio_direction_output(GPIO_RF_4, 1);
38394 + printk("Unable to request DAC reset GPIO\n");
38401 + audio_dev2 = audio_device_alloc("snd-ubi32-generic", "audio", "audio-spdifout", 0);
38402 + if (audio_dev2) {
38403 + platform_device_register(audio_dev2);
38407 + * Register all of the devices which sit on the I2C bus
38409 + printk(KERN_INFO "%s: registering i2c resources\n", __FUNCTION__);
38410 + i2c_register_board_info(0, ip7500av_i2c_board_info, ARRAY_SIZE(ip7500av_i2c_board_info));
38412 + printk(KERN_INFO "IP7500 Audio/Video Board\n");
38415 +arch_initcall(ip7500av_init);
38417 +++ b/arch/ubicom32/mach-ip7k/board-ip7500iap.c
38420 + * arch/ubicom32/mach-ip7k/board-ip7500iap.c
38421 + * Support for IP7500 Internet Audio Player
38423 + * This file supports the IP7500 Internet Audio Player:
38424 + * 8007-1110 Rev 1.0
38426 + * (C) Copyright 2009, Ubicom, Inc.
38428 + * This file is part of the Ubicom32 Linux Kernel Port.
38430 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
38431 + * it and/or modify it under the terms of the GNU General Public License
38432 + * as published by the Free Software Foundation, either version 2 of the
38433 + * License, or (at your option) any later version.
38435 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
38436 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
38437 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
38438 + * the GNU General Public License for more details.
38440 + * You should have received a copy of the GNU General Public License
38441 + * along with the Ubicom32 Linux Kernel Port. If not,
38442 + * see <http://www.gnu.org/licenses/>.
38444 +#include <linux/device.h>
38445 +#include <linux/gpio.h>
38446 +#include <asm/board.h>
38448 +#include <linux/delay.h>
38450 +#include <linux/platform_device.h>
38451 +#include <asm/audio.h>
38452 +#include <linux/i2c.h>
38453 +#include <linux/i2c-gpio.h>
38455 +#include <asm/ubicom32sd.h>
38456 +#include <asm/sd_tio.h>
38458 +#include <asm/ubicom32bl.h>
38460 +#include <asm/machdep.h>
38462 +/******************************************************************************
38463 + * SD/IO Port F (Slot 1) platform data
38465 +static struct resource ip7500iap_portf_sd_resources[] = {
38471 + * The init routine will query the devtree and fill this in
38473 + .flags = IORESOURCE_IRQ,
38481 + * The init routine will query the devtree and fill this in
38483 + .flags = IORESOURCE_IRQ,
38487 + * Memory Mapped Registers
38491 + * The init routine will query the devtree and fill this in
38493 + .flags = IORESOURCE_MEM,
38497 +static struct ubicom32sd_card ip7500iap_portf_sd_cards[] = {
38499 + .pin_wp = GPIO_RF_7,
38500 + .wp_polarity = 1,
38501 + .pin_pwr = GPIO_RF_8,
38502 + .pin_cd = GPIO_RF_6,
38506 +static struct ubicom32sd_platform_data ip7500iap_portf_sd_platform_data = {
38508 + .cards = ip7500iap_portf_sd_cards,
38511 +static struct platform_device ip7500iap_portf_sd_device = {
38512 + .name = "ubicom32sd",
38514 + .resource = ip7500iap_portf_sd_resources,
38515 + .num_resources = ARRAY_SIZE(ip7500iap_portf_sd_resources),
38517 + .platform_data = &ip7500iap_portf_sd_platform_data,
38523 + * ip7500iap_portf_sd_init
38525 +static void ip7500iap_portf_sd_init(void)
38528 + * Check the device tree for the sd_tio
38530 + struct sd_tio_node *sd_node = (struct sd_tio_node *)devtree_find_node("portf_sd");
38532 + printk(KERN_INFO "PortF SDTIO not found\n");
38537 + * Fill in the resources and platform data from devtree information
38539 + ip7500iap_portf_sd_resources[0].start = sd_node->dn.sendirq;
38540 + ip7500iap_portf_sd_resources[1].start = sd_node->dn.recvirq;
38541 + ip7500iap_portf_sd_resources[2].start = (u32_t)&(sd_node->regs);
38542 + ip7500iap_portf_sd_resources[2].end = (u32_t)&(sd_node->regs) + sizeof(sd_node->regs);
38544 + platform_device_register(&ip7500iap_portf_sd_device);
38547 +/******************************************************************************
38548 + * SD/IO Port B (Slot 2) platform data
38550 +static struct resource ip7500iap_portb_sd_resources[] = {
38556 + * The init routine will query the devtree and fill this in
38558 + .flags = IORESOURCE_IRQ,
38566 + * The init routine will query the devtree and fill this in
38568 + .flags = IORESOURCE_IRQ,
38572 + * Memory Mapped Registers
38576 + * The init routine will query the devtree and fill this in
38578 + .flags = IORESOURCE_MEM,
38582 +static struct ubicom32sd_card ip7500iap_portb_sd_cards[] = {
38584 + .pin_wp = GPIO_RB_13,
38585 + .wp_polarity = 1,
38586 + .pin_pwr = GPIO_RB_11,
38587 + .pin_cd = GPIO_RB_12,
38591 +static struct ubicom32sd_platform_data ip7500iap_portb_sd_platform_data = {
38593 + .cards = ip7500iap_portb_sd_cards,
38596 +static struct platform_device ip7500iap_portb_sd_device = {
38597 + .name = "ubicom32sd",
38599 + .resource = ip7500iap_portb_sd_resources,
38600 + .num_resources = ARRAY_SIZE(ip7500iap_portb_sd_resources),
38602 + .platform_data = &ip7500iap_portb_sd_platform_data,
38608 + * ip7500iap_portb_sd_init
38610 +static void ip7500iap_portb_sd_init(void)
38613 + * Check the device tree for the sd_tio
38615 + struct sd_tio_node *sd_node = (struct sd_tio_node *)devtree_find_node("portb_sd");
38617 + printk(KERN_INFO "PortB SDTIO not found\n");
38622 + * Fill in the resources and platform data from devtree information
38624 + ip7500iap_portb_sd_resources[0].start = sd_node->dn.sendirq;
38625 + ip7500iap_portb_sd_resources[1].start = sd_node->dn.recvirq;
38626 + ip7500iap_portb_sd_resources[2].start = (u32_t)&(sd_node->regs);
38627 + ip7500iap_portb_sd_resources[2].end = (u32_t)&(sd_node->regs) + sizeof(sd_node->regs);
38629 + platform_device_register(&ip7500iap_portb_sd_device);
38632 +/******************************************************************************
38633 + * Touch controller
38635 + * Connected via I2C bus, interrupt on PA6
38637 +#include <linux/i2c/tsc2007.h>
38640 + * ip7500iap_tsc2007_exit_platform_hw
38642 +static void ip7500iap_tsc2007_exit_platform_hw(void)
38644 + UBICOM32_IO_PORT(RA)->ctl0 &= ~(0x03 << 19);
38645 + gpio_free(GPIO_RA_6);
38649 + * ip7500iap_tsc2007_init_platform_hw
38651 +static int ip7500iap_tsc2007_init_platform_hw(void)
38653 + int res = gpio_request(GPIO_RA_6, "TSC2007_IRQ");
38658 + UBICOM32_IO_PORT(RA)->ctl0 &= ~(0x03 << 19);
38659 + UBICOM32_IO_PORT(RA)->ctl0 |= (0x02 << 19);
38664 + * ip7500iap_tsc2007_get_pendown_state
38666 +static int ip7500iap_tsc2007_get_pendown_state(void)
38668 + return !gpio_get_value(GPIO_RA_6);
38671 +static struct tsc2007_platform_data ip7500iap_tsc2007_data = {
38673 + .x_plate_ohms = 350,
38674 + .get_pendown_state = ip7500iap_tsc2007_get_pendown_state,
38675 + .init_platform_hw = ip7500iap_tsc2007_init_platform_hw,
38676 + .exit_platform_hw = ip7500iap_tsc2007_exit_platform_hw,
38679 +/******************************************************************************
38682 + * DO NOT CHANGE THE ORDER HERE unless you know how this works. There
38683 + * are hardcoded indicies which refer to the order of drivers listed here.
38685 +static struct i2c_board_info __initdata ip7500iap_i2c_board_info[] = {
38687 + * U6, CS4350 DAC, address 0x4B
38690 + .type = "cs4350",
38695 + * U20, S35390A RTC, address 0x30
38698 + .type = "s35390a",
38703 + * U9, TSC2007 Touch screen controller, address 0x49, irq RA6
38706 + .type = "tsc2007",
38709 + .platform_data = &ip7500iap_tsc2007_data,
38714 + * I2C bus on the board, SDA PE4, SCL PE5
38716 +static struct i2c_gpio_platform_data ip7500iap_i2c_data = {
38717 + .sda_pin = GPIO_RF_14,
38718 + .scl_pin = GPIO_RF_13,
38719 + .sda_is_open_drain = 0,
38720 + .scl_is_open_drain = 0,
38724 +static struct platform_device ip7500iap_i2c_device = {
38725 + .name = "i2c-gpio",
38728 + .platform_data = &ip7500iap_i2c_data,
38732 +/******************************************************************************
38733 + * Backlight on the board PD0, hardware PWM
38735 +static struct ubicom32bl_platform_data ip7500iap_backlight_data = {
38736 + .type = UBICOM32BL_TYPE_PWM,
38737 + .pwm_channel = 2,
38738 + .pwm_prescale = 15,
38739 + .pwm_period = 60,
38740 + .default_intensity = 0x80,
38743 +static struct platform_device ip7500iap_backlight_device = {
38744 + .name = "ubicom32bl",
38747 + .platform_data = &ip7500iap_backlight_data,
38751 +/******************************************************************************
38752 + * Devices on this board
38754 +static struct platform_device *ip7500iap_devices[] __initdata = {
38755 + &ip7500iap_i2c_device,
38756 + &ip7500iap_backlight_device,
38760 + * ip7500iap_power_off
38761 + * Called to turn the power off for this board
38763 +static void ip7500iap_power_off(void)
38765 + gpio_set_value(GPIO_RF_11, 0);
38770 + * Called to add the devices which we have on this board
38772 +static int __init ip7500iap_init(void)
38774 + struct platform_device *audio_dev;
38775 + struct platform_device *audio_dev2;
38783 + * Hold the POWER_HOLD line
38785 + ret = gpio_request(GPIO_RF_11, "POWER_HOLD");
38787 + printk(KERN_ERR "%s: could not request POWER_HOLD GPIO\n", __FUNCTION__);
38789 + gpio_direction_output(GPIO_RF_11, 1);
38790 + mach_power_off = ip7500iap_power_off;
38793 + * DAC nRESET line
38795 + ret = gpio_request(GPIO_RE_7, "DAC_nRESET");
38797 + printk(KERN_ERR "%s: could not request DAC_nRESET GPIO\n", __FUNCTION__);
38799 + gpio_direction_output(GPIO_RE_7, 0);
38801 + gpio_set_value(GPIO_RE_7, 1);
38804 + * Bring up any SDIO slots
38806 + ip7500iap_portb_sd_init();
38807 + ip7500iap_portf_sd_init();
38810 + * Bring up audio devices
38812 + platform_add_devices(ip7500iap_devices, ARRAY_SIZE(ip7500iap_devices));
38814 + audio_dev = audio_device_alloc("snd-ubi32-cs4350", "audio", "audio-i2sout", 0);
38816 + ip7500iap_i2c_board_info[0].platform_data = audio_dev;
38819 + audio_dev2 = audio_device_alloc("snd-ubi32-generic", "audio", "audio-spdifout", 0);
38820 + if (audio_dev2) {
38821 + platform_device_register(audio_dev2);
38824 + printk(KERN_INFO "%s: registering i2c resources\n", __FUNCTION__);
38825 + i2c_register_board_info(0, ip7500iap_i2c_board_info, ARRAY_SIZE(ip7500iap_i2c_board_info));
38827 + printk(KERN_INFO "IP7500 Internet Audio Player\n");
38832 +arch_initcall(ip7500iap_init);
38834 +++ b/arch/ubicom32/mach-ip7k/board-ip7500media.c
38837 + * arch/ubicom32/mach-ip7k/board-ip7500media.c
38838 + * Board file for IP7500 media board.
38840 + * Supports the following configuration
38842 + * P/N 8007-0510 rev 1.0 NOPHY
38843 + * P/N 8007-0511 rev 1.1 NOPHY
38844 + * DIP Switch SW2 configuration:
38845 + * POS 1: on = PCI enabled
38846 + * POS 2: off = TTYX => PF12
38847 + * POS 3: off = TTYY => PF15
38850 + * P/N 8007-0610 rev 1.0
38852 + * LCD Adapter Board: (optional)
38853 + * P/N 8007-0920 rev 2.0
38854 + * P/N 8007-0921 rev 2.1
38856 + * (C) Copyright 2009, Ubicom, Inc.
38858 + * This file is part of the Ubicom32 Linux Kernel Port.
38860 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
38861 + * it and/or modify it under the terms of the GNU General Public License
38862 + * as published by the Free Software Foundation, either version 2 of the
38863 + * License, or (at your option) any later version.
38865 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
38866 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
38867 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
38868 + * the GNU General Public License for more details.
38870 + * You should have received a copy of the GNU General Public License
38871 + * along with the Ubicom32 Linux Kernel Port. If not,
38872 + * see <http://www.gnu.org/licenses/>.
38874 + * Ubicom32 implementation derived from (with many thanks):
38879 +#include <linux/device.h>
38880 +#include <linux/platform_device.h>
38881 +#include <linux/gpio.h>
38883 +#include <linux/input.h>
38885 +#include <linux/i2c.h>
38886 +#include <linux/i2c-gpio.h>
38887 +#include <linux/i2c/pca953x.h>
38889 +#include <asm/board.h>
38890 +#include <asm/machdep.h>
38891 +#include <asm/ubicom32input_i2c.h>
38892 +#include <asm/ubicom32bl.h>
38893 +#include <asm/ubicom32lcdpower.h>
38894 +#include <asm/vdc_tio.h>
38896 +#include <asm/ubicom32sd.h>
38897 +#include <asm/sd_tio.h>
38898 +#include <asm/devtree.h>
38899 +#include <asm/audio.h>
38901 +#include <asm/ring_tio.h>
38903 +/******************************************************************************
38904 + * SD/IO Port F (Slot 1) platform data
38906 +static struct resource ip7500media_portf_sd_resources[] = {
38912 + * The init routine will query the devtree and fill this in
38914 + .flags = IORESOURCE_IRQ,
38922 + * The init routine will query the devtree and fill this in
38924 + .flags = IORESOURCE_IRQ,
38928 + * Memory Mapped Registers
38932 + * The init routine will query the devtree and fill this in
38934 + .flags = IORESOURCE_MEM,
38938 +static struct ubicom32sd_card ip7500media_portf_sd_cards[] = {
38940 + .pin_wp = IP7500MEDIA_IO16,
38941 + .wp_polarity = 1,
38942 + .pin_pwr = IP7500MEDIA_IO20,
38943 + .pin_cd = IP7500MEDIA_IO23,
38946 + .pin_wp = IP7500MEDIA_IO17,
38947 + .wp_polarity = 1,
38948 + .pin_pwr = IP7500MEDIA_IO21,
38949 + .pin_cd = IP7500MEDIA_IO24,
38953 +static struct ubicom32sd_platform_data ip7500media_portf_sd_platform_data = {
38955 + .cards = ip7500media_portf_sd_cards,
38958 +static struct platform_device ip7500media_portf_sd_device = {
38959 + .name = "ubicom32sd",
38961 + .resource = ip7500media_portf_sd_resources,
38962 + .num_resources = ARRAY_SIZE(ip7500media_portf_sd_resources),
38964 + .platform_data = &ip7500media_portf_sd_platform_data,
38970 + * ip7500media_portf_sd_init
38972 +static void ip7500media_portf_sd_init(void)
38975 + * Check the device tree for the sd_tio
38977 + struct sd_tio_node *sd_node = (struct sd_tio_node *)devtree_find_node("portf_sd");
38979 + printk(KERN_INFO "PortF SDTIO not found\n");
38984 + * Fill in the resources and platform data from devtree information
38986 + ip7500media_portf_sd_resources[0].start = sd_node->dn.sendirq;
38987 + ip7500media_portf_sd_resources[1].start = sd_node->dn.recvirq;
38988 + ip7500media_portf_sd_resources[2].start = (u32_t)&(sd_node->regs);
38989 + ip7500media_portf_sd_resources[2].end = (u32_t)&(sd_node->regs) + sizeof(sd_node->regs);
38991 + platform_device_register(&ip7500media_portf_sd_device);
38994 +/******************************************************************************
38995 + * SD/IO Port B (Slot 2) platform data
38997 +static struct resource ip7500media_portb_sd_resources[] = {
39003 + * The init routine will query the devtree and fill this in
39005 + .flags = IORESOURCE_IRQ,
39013 + * The init routine will query the devtree and fill this in
39015 + .flags = IORESOURCE_IRQ,
39019 + * Memory Mapped Registers
39023 + * The init routine will query the devtree and fill this in
39025 + .flags = IORESOURCE_MEM,
39029 +static struct ubicom32sd_card ip7500media_portb_sd_cards[] = {
39031 + .pin_wp = IP7500MEDIA_IO19,
39032 + .wp_polarity = 1,
39033 + .pin_pwr = IP7500MEDIA_IO22,
39034 + .pin_cd = IP7500MEDIA_IO18,
39038 +static struct ubicom32sd_platform_data ip7500media_portb_sd_platform_data = {
39040 + .cards = ip7500media_portb_sd_cards,
39043 +static struct platform_device ip7500media_portb_sd_device = {
39044 + .name = "ubicom32sd",
39046 + .resource = ip7500media_portb_sd_resources,
39047 + .num_resources = ARRAY_SIZE(ip7500media_portb_sd_resources),
39049 + .platform_data = &ip7500media_portb_sd_platform_data,
39055 + * ip7500media_portb_sd_init
39057 +static void ip7500media_portb_sd_init(void)
39060 + * Check the device tree for the sd_tio
39062 + struct sd_tio_node *sd_node = (struct sd_tio_node *)devtree_find_node("portb_sd");
39064 + printk(KERN_INFO "PortB SDTIO not found\n");
39069 + * Fill in the resources and platform data from devtree information
39071 + ip7500media_portb_sd_resources[0].start = sd_node->dn.sendirq;
39072 + ip7500media_portb_sd_resources[1].start = sd_node->dn.recvirq;
39073 + ip7500media_portb_sd_resources[2].start = (u32_t)&(sd_node->regs);
39074 + ip7500media_portb_sd_resources[2].end = (u32_t)&(sd_node->regs) + sizeof(sd_node->regs);
39076 + platform_device_register(&ip7500media_portb_sd_device);
39080 + * ip7500media_u17_setup
39081 + * Called by I2C to tell us that u17 is setup.
39083 + * This function is called by I2C to tell us that u17 has been setup. All
39084 + * devices which rely on this chip being initialized (or even present) need to
39085 + * be initialized in this function otherwise they may get initialized too early.
39087 + * Currently the only device depending on u17 is the SDIO
39089 +static int __init ip7500media_u17_setup(struct i2c_client *client, unsigned gpio, unsigned ngpio, void *context)
39092 + * Initialize the Port F/Port B SD slots (only the enabled ports will init)
39094 + ip7500media_portf_sd_init();
39095 + ip7500media_portb_sd_init();
39100 +/******************************************************************************
39101 + * LCD VGH on the board at PE6
39103 +static struct ubicom32lcdpower_platform_data ip7500media_lcdpower_data = {
39104 + .vgh_gpio = GPIO_RE_7,
39105 + .vgh_polarity = true,
39108 +static struct platform_device ip7500media_lcdpower_device = {
39109 + .name = "ubicom32lcdpower",
39112 + .platform_data = &ip7500media_lcdpower_data,
39116 +/******************************************************************************
39117 + * Backlight on the board PD0, hardware PWM
39119 +static struct ubicom32bl_platform_data ip7500media_backlight_data = {
39120 + .type = UBICOM32BL_TYPE_PWM,
39121 + .pwm_channel = 2,
39122 + .pwm_prescale = 15,
39123 + .pwm_period = 60,
39124 + .default_intensity = 0x80,
39127 +static struct platform_device ip7500media_backlight_device = {
39128 + .name = "ubicom32bl",
39131 + .platform_data = &ip7500media_backlight_data,
39135 +/******************************************************************************
39136 + * Ubicom32Input on I2C, U15 MAX7310, address 0x18, 8 bits
39138 +static struct ubicom32input_i2c_button ip7500media_ubicom32input_i2c_u15_buttons[] = {
39141 + .code = KEY_LEFT,
39147 + .code = KEY_RIGHT,
39159 + .code = KEY_DOWN,
39165 + .code = KEY_ENTER,
39171 + .code = KEY_MENU,
39183 +static struct ubicom32input_i2c_platform_data ip7500media_ubicom32input_i2c_u15_platform_data = {
39184 + .buttons = ip7500media_ubicom32input_i2c_u15_buttons,
39185 + .nbuttons = ARRAY_SIZE(ip7500media_ubicom32input_i2c_u15_buttons),
39186 + .name = "Ubicom32 Input I2C U15",
39189 +/******************************************************************************
39190 + * Additional GPIO chips
39192 +static struct pca953x_platform_data ip7500media_gpio_u16_platform_data = {
39193 + .gpio_base = IP7500MEDIA_U16_BASE,
39196 +static struct pca953x_platform_data ip7500media_gpio_u17_platform_data = {
39197 + .gpio_base = IP7500MEDIA_U17_BASE,
39198 + .setup = ip7500media_u17_setup,
39201 +static struct pca953x_platform_data ip7500media_gpio_u18_platform_data = {
39202 + .gpio_base = IP7500MEDIA_U18_BASE,
39206 +/******************************************************************************
39207 + * Touch controller present on LCD Adapter board
39209 + * Connected via I2C bus, interrupt on PD1
39211 +#include <linux/i2c/tsc2007.h>
39214 + * ip7500media_tsc2007_exit_platform_hw
39216 +static void ip7500media_tsc2007_exit_platform_hw(void)
39218 + UBICOM32_IO_PORT(RD)->int_mask &= ~(1 << 11);
39219 + UBICOM32_IO_PORT(RD)->ctl2 &= ~(0x03 << 16);
39220 + gpio_free(GPIO_RD_1);
39224 + * ip7500media_tsc2007_init_platform_hw
39226 +static int ip7500media_tsc2007_init_platform_hw(void)
39228 + int res = gpio_request(GPIO_RD_1, "TSC2007_IRQ");
39232 + UBICOM32_IO_PORT(RD)->function = 0;
39233 + UBICOM32_IO_PORT(RD)->int_mask = (1 << 11);
39234 + UBICOM32_IO_PORT(RD)->ctl2 &= ~(0x03 << 16);
39235 + UBICOM32_IO_PORT(RD)->ctl2 |= (0x02 << 16);
39241 + * ip7500media_tsc2007_clear_penirq
39243 +static void ip7500media_tsc2007_clear_penirq(void)
39245 + UBICOM32_IO_PORT(RD)->int_clr = (1 << 11);
39249 + * ip7500media_tsc2007_get_pendown_state
39251 +static int ip7500media_tsc2007_get_pendown_state(void)
39253 + return !gpio_get_value(GPIO_RD_1);
39256 +static struct tsc2007_platform_data ip7500media_tsc2007_data = {
39258 + .x_plate_ohms = 350,
39259 + .get_pendown_state = ip7500media_tsc2007_get_pendown_state,
39260 + .init_platform_hw = ip7500media_tsc2007_init_platform_hw,
39261 + .exit_platform_hw = ip7500media_tsc2007_exit_platform_hw,
39262 + .clear_penirq = ip7500media_tsc2007_clear_penirq,
39265 +/******************************************************************************
39266 + * Devices on the I2C bus
39268 + * BEWARE of changing the order of things in this array as we depend on
39269 + * certain things to be in certain places.
39271 +static struct i2c_board_info __initdata ip7500media_i2c_board_info[] = {
39273 + * U6, CS4350 DAC, address 0x4B
39276 + .type = "cs4350",
39281 + * U14, S35390A RTC, address 0x30
39284 + .type = "s35390a",
39289 + * U15, MAX7310 IO expander, 8 bits, address 0x18
39290 + * IO0: User I/O (J16-1) (Left) IO4: User I/O (J16-5) (Enter)
39291 + * IO1: User I/O (J16-2) (Right) IO5: User I/O (J16-6) (Menu)
39292 + * IO2: User I/O (J16-3) (Up) IO6: User I/O (J16-7) (Back)
39293 + * IO3: User I/O (J16-4) (Down) IO7: User I/O (J16-8)
39296 + .type = "ubicom32in_max7310",
39298 + .platform_data = &ip7500media_ubicom32input_i2c_u15_platform_data,
39302 + * U16, MAX7310 IO expander, 8 bits, address 0x1C
39303 + * IO8 : User I/O (J16-9) IO12: User I/O (J16-17)
39304 + * IO9 : User I/O (J16-10) IO13: User I/O (J16-18)
39305 + * IO10: User I/O (J16-15) IO14: User I/O (J16-19)
39306 + * IO11: User I/O (J16-16) IO15: User I/O (J16-20)
39309 + .type = "max7310",
39311 + .platform_data = &ip7500media_gpio_u16_platform_data,
39315 + * U17, MAX7310 IO expander, 8 bits, address 0x1A
39316 + * IO16: SDIO1A_WP IO20: SD1A_PWREN
39317 + * IO17: SDIO1B_WP IO21: SD1B_PWREN
39318 + * IO18: SDIO2_CD IO22: SD2_PWREN
39319 + * IO19: SDIO2_WP IO23: SDIO1A_CD
39323 + .type = "max7310",
39325 + .platform_data = &ip7500media_gpio_u17_platform_data,
39329 + * U18, MAX7310 IOB expander, 8 bits, address 0x1E
39330 + * IO24: SDIO1B_CD IO28: User I/O TP6
39331 + * IO25: User I/O TP9 IO29: User I/O TP5
39332 + * IO26: User I/O TP8 IO30: User I/O TP4
39333 + * IO27: User I/O TP7 IO31: User I/O TP3
39336 + .type = "max7310",
39338 + .platform_data = &ip7500media_gpio_u18_platform_data,
39343 + * Additional I2C devices to add when a LCD adapter board is present
39345 +static struct i2c_board_info __initdata ip7500media_lcd_adapter_i2c_board_info[] = {
39347 + I2C_BOARD_INFO("tsc2007", 0x48),
39348 + .irq = PORT_OTHER_INT(RD),
39349 + .platform_data = &ip7500media_tsc2007_data,
39354 + * I2C bus on the board, SDA PE4, SCL PE5
39356 +static struct i2c_gpio_platform_data ip7500media_i2c_data = {
39357 + .sda_pin = GPIO_RE_4,
39358 + .scl_pin = GPIO_RE_5,
39359 + .sda_is_open_drain = 0,
39360 + .scl_is_open_drain = 0,
39364 +static struct platform_device ip7500media_i2c_device = {
39365 + .name = "i2c-gpio",
39368 + .platform_data = &ip7500media_i2c_data,
39373 + * Virtual Frame Buffer device for use with LCD Adapter
39375 +static struct platform_device ip7500media_vfb_device = {
39376 + .name = "ubicom32vfb",
39382 + * 0: no override (auto-detect)
39383 + * 1: force vdc usage
39384 + * 2: force lcd adapter usage
39386 +static int __initdata vdc_override = 0;
39389 + * ip7500media_set_forcevdc
39390 + * Called when forcevdc is present on the kernel boot line
39392 +static int __init ip7500media_set_forcevdc(char *str)
39394 + if (str[0] == '1') {
39395 + vdc_override = 1;
39397 + vdc_override = 2;
39403 + * ip7500media_video_init
39404 + * Called late to determine what kind of video we have on this board
39406 +static int __init ip7500media_video_init(void)
39408 + struct i2c_adapter *adap;
39409 + struct i2c_msg msg[1];
39410 + unsigned char *data;
39411 + unsigned char checksum;
39415 + if (vdc_override == 1) {
39416 + printk(KERN_INFO "Force VDCTIO mode\n");
39419 + if (vdc_override == 2) {
39420 + printk(KERN_INFO "Force LCD Adapter Board mode\n");
39425 + * Check to see if there is an EEPROM out there. If we see an
39426 + * EEPROM then we will assume a LCD Adapter Board (8007-092x)
39429 + data = kmalloc(256, GFP_KERNEL);
39431 + printk(KERN_WARNING "%s: Failed to allocate memory\n", __FUNCTION__);
39435 + adap = i2c_get_adapter(0);
39437 + printk(KERN_WARNING "%s: Failed to get i2c adapter\n", __FUNCTION__);
39442 + msg->addr = 0x50;
39446 + err = i2c_transfer(adap, msg, 1);
39451 + msg->addr = 0x50;
39452 + msg->flags = I2C_M_RD;
39455 + err = i2c_transfer(adap, msg, 1);
39460 + i2c_put_adapter(adap);
39463 + * Verify the checksum
39466 + for (i = 0; i < 255; i++) {
39467 + checksum ^= data[i];
39469 + if (checksum != data[255]) {
39470 + printk(KERN_WARNING "%s: Checksum mismatch\n", __FUNCTION__);
39478 + platform_device_register(&ip7500media_vfb_device);
39481 + * Add the i2c devices on the LCD Adapter board. (We have to use i2c_new_device
39482 + * since it's late in the boot process.)
39484 + printk(KERN_INFO "%s: registering LCD Adapter board i2c resources\n", __FUNCTION__);
39485 + for (i = 0; i < ARRAY_SIZE(ip7500media_lcd_adapter_i2c_board_info); i++) {
39486 + i2c_new_device(adap, &ip7500media_lcd_adapter_i2c_board_info[i]);
39489 + i2c_put_adapter(adap);
39494 + * No LCD Adapter board, bring up VDC
39500 +late_initcall(ip7500media_video_init);
39501 +__setup("forcevdc=", ip7500media_set_forcevdc);
39504 + * ip7500media_init
39505 + * Called to add the devices which we have on this board
39507 +static int __init ip7500media_init(void)
39509 + struct platform_device *audio_dev;
39510 + int have_ethernet = (devtree_find_node("eth_lan") != 0);
39516 +#ifdef CONFIG_UIO_UBICOM32RING
39517 + ring_tio_init("decoder_ring");
39521 + * Register all of the devices we have on this board
39523 + printk(KERN_INFO "%s: registering device resources\n", __FUNCTION__);
39524 + platform_device_register(&ip7500media_i2c_device);
39525 + platform_device_register(&ip7500media_backlight_device);
39528 + * If ethernet doesn't exist then we can init the lcdpower
39530 + if (!have_ethernet) {
39531 + platform_device_register(&ip7500media_lcdpower_device);
39535 + * Allocate the audio drivers. SPDIF not supported on boards with ethernet.
39537 + audio_dev = audio_device_alloc("snd-ubi32-cs4350", "audio", "audio-i2sout", 0);
39539 + ip7500media_i2c_board_info[0].platform_data = audio_dev;
39542 + if (!have_ethernet) {
39543 + struct platform_device *audio_dev2;
39545 + audio_dev2 = audio_device_alloc("snd-ubi32-generic", "audio", "audio-spdifout", 0);
39546 + if (audio_dev2) {
39547 + platform_device_register(audio_dev2);
39552 + * Register all of the devices which sit on the I2C bus
39554 + printk(KERN_INFO "%s: registering i2c resources\n", __FUNCTION__);
39555 + i2c_register_board_info(0, ip7500media_i2c_board_info, ARRAY_SIZE(ip7500media_i2c_board_info));
39558 + * We have to initialize the SDIO after the I2C IOB gets setup. SDIO is initialized in
39559 + * ip7500media_u17_setup
39562 + printk("IP7500 Media Board\n");
39567 +arch_initcall(ip7500media_init);
39569 +++ b/arch/ubicom32/mach-ip7k/board-ip7500module.c
39572 + * arch/ubicom32/mach-ip7k/board-ip7500module.c
39573 + * Support for IP7500 CPU module board.
39575 + * This file supports the IP7500 CPU module board:
39576 + * 8007-0510 Rev 1.0
39577 + * 8007-0510A Rev 1.0 (with ethernet)
39579 + * DIP Switch SW2 configuration: (*) default
39580 + * POS 1: on(*) = PCI enabled, off = PCI disabled
39581 + * POS 2: on(*) = TTYX => PA6, off = TTYX => PF12
39582 + * POS 3: on(*) = TTYY => PA7, off = TTYY => PF15
39585 + * (C) Copyright 2009, Ubicom, Inc.
39587 + * This file is part of the Ubicom32 Linux Kernel Port.
39589 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
39590 + * it and/or modify it under the terms of the GNU General Public License
39591 + * as published by the Free Software Foundation, either version 2 of the
39592 + * License, or (at your option) any later version.
39594 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
39595 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
39596 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
39597 + * the GNU General Public License for more details.
39599 + * You should have received a copy of the GNU General Public License
39600 + * along with the Ubicom32 Linux Kernel Port. If not,
39601 + * see <http://www.gnu.org/licenses/>.
39603 + * Ubicom32 implementation derived from (with many thanks):
39608 +#include <linux/device.h>
39609 +#include <linux/gpio.h>
39610 +#include <asm/board.h>
39613 + * ip7500module_init
39614 + * Called to add the devices which we have on this board
39616 +static int __init ip7500module_init(void)
39625 +arch_initcall(ip7500module_init);
39627 +++ b/arch/ubicom32/mach-ip7k/board-ip7500wspkr.c
39630 + * arch/ubicom32/mach-ip7k/board-ip7500wspkr.c
39631 + * Support for IP7500 Wireless Speaker board.
39633 + * This file supports the IP7500 Wireless Speaker board:
39634 + * 8007-1210 Rev 1.0
39636 + * (C) Copyright 2009, Ubicom, Inc.
39638 + * This file is part of the Ubicom32 Linux Kernel Port.
39640 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
39641 + * it and/or modify it under the terms of the GNU General Public License
39642 + * as published by the Free Software Foundation, either version 2 of the
39643 + * License, or (at your option) any later version.
39645 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
39646 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
39647 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
39648 + * the GNU General Public License for more details.
39650 + * You should have received a copy of the GNU General Public License
39651 + * along with the Ubicom32 Linux Kernel Port. If not,
39652 + * see <http://www.gnu.org/licenses/>.
39654 +#include <linux/device.h>
39655 +#include <linux/gpio.h>
39656 +#include <asm/board.h>
39658 +#include <linux/platform_device.h>
39659 +#include <asm/audio.h>
39660 +#include <linux/i2c.h>
39661 +#include <linux/i2c-gpio.h>
39663 +static struct i2c_board_info __initdata ip7500wspkr_i2c_board_info[] = {
39665 + * U6, CS4350 DAC, address 0x4B
39668 + .type = "cs4350",
39674 + * I2C bus on the board, SDA PE4, SCL PE5
39676 +static struct i2c_gpio_platform_data ip7500wspkr_i2c_data = {
39677 + .sda_pin = GPIO_RD_5,
39678 + .scl_pin = GPIO_RD_6,
39679 + .sda_is_open_drain = 0,
39680 + .scl_is_open_drain = 0,
39684 +static struct platform_device ip7500wspkr_i2c_device = {
39685 + .name = "i2c-gpio",
39688 + .platform_data = &ip7500wspkr_i2c_data,
39692 +static struct platform_device *ip7500wspkr_devices[] __initdata = {
39693 + &ip7500wspkr_i2c_device,
39697 + * ip7500wspkr_init
39698 + * Called to add the devices which we have on this board
39700 +static int __init ip7500wspkr_init(void)
39702 + struct platform_device *audio_dev;
39703 + struct platform_device *audio_dev2;
39709 + platform_add_devices(ip7500wspkr_devices, ARRAY_SIZE(ip7500wspkr_devices));
39711 + audio_dev = audio_device_alloc("snd-ubi32-cs4350", "audio", "audio-i2sout", 0);
39713 + ip7500wspkr_i2c_board_info[0].platform_data = audio_dev;
39716 + audio_dev2 = audio_device_alloc("snd-ubi32-generic", "audio", "audio-spdifout", 0);
39717 + if (audio_dev2) {
39718 + platform_device_register(audio_dev2);
39721 + printk(KERN_INFO "%s: registering i2c resources\n", __FUNCTION__);
39722 + i2c_register_board_info(0, ip7500wspkr_i2c_board_info, ARRAY_SIZE(ip7500wspkr_i2c_board_info));
39724 + printk(KERN_INFO "IP7500 Wireless Speaker Board\n");
39729 +arch_initcall(ip7500wspkr_init);
39731 +++ b/arch/ubicom32/mach-ip7k/Kconfig
39735 + select UBICOM32_V4
39736 + select UBICOM_INPUT
39737 + select UBICOM_INPUT_I2C
39739 + select RTC_DRV_S35390A
39742 + select GPIO_PCA953X
39744 + select FB_UBICOM32
39745 + select LCD_CLASS_DEVICE
39746 + select LCD_UBICOM32POWER
39747 + select BACKLIGHT_LCD_SUPPORT
39748 + select BACKLIGHT_CLASS_DEVICE
39749 + select BACKLIGHT_UBICOM32
39751 + select MMC_UBICOM32
39755 + IP7145 Digital Picture Frame reference design, supports:
39760 + select UBICOM32_V4
39761 + select UBICOM_INPUT
39763 + select LEDS_CLASS
39766 + select SPI_UBICOM32_GPIO
39767 + select VLAN_8021Q
39768 + select UBICOM_SWITCH
39769 + select UBICOM_SWITCH_BCM539X
39771 + Ubicom IP7160 RGW Eval, supports:
39776 +config IP7160RGWLCD
39777 + bool "IP7160RGWLCD"
39778 + select UBICOM32_V4
39779 + select UBICOM_INPUT
39781 + select LEDS_CLASS
39784 + select SPI_UBICOM32_GPIO
39785 + select VLAN_8021Q
39786 + select UBICOM_SWITCH
39787 + select UBICOM_SWITCH_BCM539X
39788 + select INPUT_TOUCHSCREEN
39789 + select TOUCHSCREEN_TSC2007
39791 + select FB_UBICOM32_VIRTUAL
39795 + Ubicom IP7160 RGW Eval, supports:
39796 + 8007-0112 v1.2 + 8007-1410 v1.0
39798 + With Ubicom LCD Adapter
39803 +config IP7160BRINGUP
39804 + bool "IP7160BRINGUP"
39805 + select UBICOM32_V4
39807 + select LEDS_CLASS
39810 + Ubicom IP7160 Bringup, supports:
39815 + select UBICOM32_V4
39819 + select FB_UBICOM32
39820 + select BACKLIGHT_LCD_SUPPORT
39821 + select BACKLIGHT_CLASS_DEVICE
39823 + select SND_UBI32_AUDIO_CS4350
39824 + select UBICOM_HID
39826 + IP7160 Digital Picture Frame board, supports:
39827 + 8007-0211 Rev 1.1
39829 +config IP7500MODULE
39830 + bool "IP7500MODULE"
39831 + select UBICOM32_V4
39833 + Ubicom IP7500 CPU Module board, supports:
39837 + Please see ip7500module.c for more details.
39841 + select UBICOM32_V4
39845 + select SND_UBI32_AUDIO_CS4384
39847 + select FB_UBICOM32
39849 + Ubicom IP7500 Audio Video board, supports:
39852 + With Ubicom IP7500 CPU Module board:
39853 + 8007-0510 v1.0 -or-
39856 + Please see ip7500av.c for more details.
39858 +config IP7500MEDIA
39859 + bool "IP7500MEDIA"
39860 + select UBICOM32_V4
39861 + select UBICOM_INPUT_I2C
39863 + select RTC_DRV_S35390A
39866 + select GPIO_PCA953X
39868 + select FB_UBICOM32
39869 + select FB_UBICOM32_VIRTUAL
39870 + select FB_UBICOM32_VIRTUAL_NOAUTO
39871 + select LCD_CLASS_DEVICE
39872 + select LCD_UBICOM32POWER
39873 + select BACKLIGHT_LCD_SUPPORT
39874 + select BACKLIGHT_CLASS_DEVICE
39875 + select BACKLIGHT_UBICOM32
39876 + select INPUT_TOUCHSCREEN
39877 + select TOUCHSCREEN_TSC2007
39881 + select SND_UBI32_AUDIO_CS4350
39882 + select MMC_UBICOM32
39886 + IP7500 Media Board w/ IP7500 CPU Module board, supports:
39887 + 8007-0610 v1.0 w/ 8007-0510 v1.0
39888 + 8007-0610 v1.0 w/ 8007-0510 v1.0 NOPHY
39889 + 8007-0610 v1.0 w/ 8007-0511 v1.1 NOPHY
39891 + Also supports optional LCD Adapter board:
39895 + Please see ip7500media.c for more details.
39897 +config IP7500WSPKR
39898 + bool "IP7500WSPKR"
39899 + select UBICOM32_V4
39905 + select SND_UBI32_AUDIO_CS4350
39907 + IP7500 Wireless Speaker Board, supports:
39910 + Please see ip7500wspkr.c for more details.
39914 + select UBICOM32_V4
39918 + select FB_UBICOM32_VIRTUAL
39922 + select SND_UBI32_AUDIO_CS4350
39924 + select RTC_DRV_S35390A
39925 + select INPUT_TOUCHSCREEN
39926 + select TOUCHSCREEN_TSC2007
39927 + select BACKLIGHT_LCD_SUPPORT
39928 + select BACKLIGHT_CLASS_DEVICE
39929 + select BACKLIGHT_UBICOM32
39931 + IP7500 Internet Audio Player, supports:
39934 + Please see ip7500iap.c for more details.
39937 + Please see ip7500media.c for more details.
39939 +++ b/arch/ubicom32/mach-ip7k/Makefile
39942 +# arch/ubicom32/mach-ip7k/Makefile
39943 +# Makefile for ip7k based boards.
39945 +# (C) Copyright 2009, Ubicom, Inc.
39947 +# This file is part of the Ubicom32 Linux Kernel Port.
39949 +# The Ubicom32 Linux Kernel Port is free software: you can redistribute
39950 +# it and/or modify it under the terms of the GNU General Public License
39951 +# as published by the Free Software Foundation, either version 2 of the
39952 +# License, or (at your option) any later version.
39954 +# The Ubicom32 Linux Kernel Port is distributed in the hope that it
39955 +# will be useful, but WITHOUT ANY WARRANTY; without even the implied
39956 +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
39957 +# the GNU General Public License for more details.
39959 +# You should have received a copy of the GNU General Public License
39960 +# along with the Ubicom32 Linux Kernel Port. If not,
39961 +# see <http://www.gnu.org/licenses/>.
39963 +# Ubicom32 implementation derived from (with many thanks):
39969 +obj-$(CONFIG_IP7145DPF) += board-ip7145dpf.o
39970 +obj-$(CONFIG_IP7160RGW) += board-ip7160rgw.o
39971 +obj-$(CONFIG_IP7160RGWLCD) += board-ip7160rgw.o
39972 +obj-$(CONFIG_IP7160BRINGUP) += board-ip7160bringup.o
39973 +obj-$(CONFIG_IP7160DPF) += board-ip7160dpf.o
39974 +obj-$(CONFIG_IP7500MODULE) += board-ip7500module.o
39975 +obj-$(CONFIG_IP7500MEDIA) += board-ip7500media.o
39976 +obj-$(CONFIG_IP7500AV) += board-ip7500av.o
39977 +obj-$(CONFIG_IP7500WSPKR) += board-ip7500wspkr.o
39978 +obj-$(CONFIG_IP7500IAP) += board-ip7500iap.o
39980 +++ b/arch/ubicom32/Makefile
39983 +# arch/ubicom32/Makefile
39984 +# <TODO: Replace with short file description>
39986 +# (C) Copyright 2009, Ubicom, Inc.
39988 +# This file is part of the Ubicom32 Linux Kernel Port.
39990 +# The Ubicom32 Linux Kernel Port is free software: you can redistribute
39991 +# it and/or modify it under the terms of the GNU General Public License
39992 +# as published by the Free Software Foundation, either version 2 of the
39993 +# License, or (at your option) any later version.
39995 +# The Ubicom32 Linux Kernel Port is distributed in the hope that it
39996 +# will be useful, but WITHOUT ANY WARRANTY; without even the implied
39997 +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
39998 +# the GNU General Public License for more details.
40000 +# You should have received a copy of the GNU General Public License
40001 +# along with the Ubicom32 Linux Kernel Port. If not,
40002 +# see <http://www.gnu.org/licenses/>.
40004 +# Ubicom32 implementation derived from (with many thanks):
40010 +KBUILD_DEFCONFIG :=
40012 +# setup the machine name and machine dependent settings
40013 +machine-$(CONFIG_UBICOM32_V3) := ip5k
40014 +machine-$(CONFIG_UBICOM32_V4) := ip7k
40015 +MACHINE := $(machine-y)
40018 +model-$(CONFIG_RAMKERNEL) := ram
40019 +model-$(CONFIG_ROMKERNEL) := rom
40020 +MODEL := $(model-y)
40023 +CPUCLASS := $(cpuclass-y)
40028 +# We want the core kernel built using the fastcall ABI but modules need
40029 +# to be built using the slower calling convention because they could be
40030 +# loaded out of range for fast calls.
40032 +CFLAGS_KERNEL += -mfastcall
40033 +CFLAGS_MODULE += -mno-fastcall
40036 +# Some CFLAG additions based on specific CPU type.
40038 +cflags-$(CONFIG_UBICOM32_V3) := -march=ubicom32v3 -DIP5000
40039 +cflags-$(CONFIG_UBICOM32_V4) := -march=ubicom32v4 -DIP7000
40041 +ldflags-$(CONFIG_LINKER_RELAXATION) := --relax
40042 +LDFLAGS_vmlinux := $(ldflags-y)
40044 +GCCLIBDIR := $(dir $(shell $(CC) $(cflags-y) -print-libgcc-file-name))
40045 +GCC_LIBS := $(GCCLIBDIR)/libgcc.a
40047 +KBUILD_CFLAGS += $(cflags-y) -ffunction-sections
40048 +KBUILD_AFLAGS += $(cflags-y)
40050 +KBUILD_CFLAGS += -D__linux__ -Dlinux
40051 +KBUILD_CFLAGS += -DUTS_SYSNAME=\"uClinux\"
40053 +# include any machine specific directory
40054 +ifneq ($(machine-y),)
40055 +core-y += arch/$(ARCH)/mach-$(MACHINE)/
40058 +head-y := arch/$(ARCH)/kernel/head.o
40060 +core-y += arch/$(ARCH)/kernel/ \
40061 + arch/$(ARCH)/mm/ \
40062 + arch/$(ARCH)/crypto/ \
40063 + arch/$(ARCH)/mach-common/
40065 +drivers-$(CONFIG_OPROFILE) += arch/ubicom32/oprofile/
40067 +libs-y += arch/$(ARCH)/lib/
40068 +libs-y += $(GCC_LIBS)
40072 +# make sure developer has selected a valid board
40073 +ifeq ($(CONFIG_NOBOARD),y)
40074 +# $(error have to select a valid board file $(CONFIG_NOBOARD), please run kernel config again)
40075 +_all: config_board_error
40078 +config_board_error:
40079 + @echo "*************************************************"
40080 + @echo "You have not selected a proper board."
40081 + @echo "Please run menuconfig (or config) against your"
40082 + @echo "kernel and choose your board under Processor"
40084 + @echo "*************************************************"
40087 +++ b/arch/ubicom32/mm/fault.c
40090 + * arch/ubicom32/mm/fault.c
40091 + * Ubicom32 architecture page fault implementation.
40093 + * (C) Copyright 2009, Ubicom, Inc.
40094 + * Copyright (C) 1998 D. Jeff Dionne <jeff@lineo.ca>,
40095 + * Copyright (C) 2000 Lineo, Inc. (www.lineo.com)
40099 + * linux/arch/m68k/mm/fault.c
40101 + * Copyright (C) 1995 Hamish Macdonald
40103 + * This file is part of the Ubicom32 Linux Kernel Port.
40105 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
40106 + * it and/or modify it under the terms of the GNU General Public License
40107 + * as published by the Free Software Foundation, either version 2 of the
40108 + * License, or (at your option) any later version.
40110 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
40111 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
40112 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
40113 + * the GNU General Public License for more details.
40115 + * You should have received a copy of the GNU General Public License
40116 + * along with the Ubicom32 Linux Kernel Port. If not,
40117 + * see <http://www.gnu.org/licenses/>.
40119 + * Ubicom32 implementation derived from (with many thanks):
40125 +#include <linux/module.h>
40126 +#include <linux/mman.h>
40127 +#include <linux/mm.h>
40128 +#include <linux/kernel.h>
40129 +#include <linux/ptrace.h>
40131 +#include <asm/system.h>
40132 +#include <asm/pgtable.h>
40134 +extern void die_if_kernel(char *, struct pt_regs *, long);
40137 + * This routine handles page faults. It determines the problem, and
40138 + * then passes it off to one of the appropriate routines.
40141 + * bit 0 == 0 means no page found, 1 means protection fault
40142 + * bit 1 == 0 means read, 1 means write
40144 + * If this routine detects a bad access, it returns 1, otherwise it
40147 +asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
40148 + unsigned long error_code)
40151 + printk (KERN_DEBUG "regs->sr=%#x, regs->pc=%#lx, address=%#lx, %ld\n",
40152 + regs->sr, regs->pc, address, error_code);
40156 + * Oops. The kernel tried to access some bad page. We'll have to
40157 + * terminate things with extreme prejudice.
40159 + if ((unsigned long) address < PAGE_SIZE) {
40160 + printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
40162 + printk(KERN_ALERT "Unable to handle kernel access");
40163 + printk(KERN_ALERT " at virtual address %08lx\n",address);
40164 + die_if_kernel("Oops", regs, error_code);
40165 + do_exit(SIGKILL);
40170 +++ b/arch/ubicom32/mm/init.c
40173 + * arch/ubicom32/mm/init.c
40174 + * Ubicom32 architecture virtual memory initialization.
40176 + * (C) Copyright 2009, Ubicom, Inc.
40177 + * Copyright (C) 1998 D. Jeff Dionne <jeff@lineo.ca>,
40178 + * Kenneth Albanowski <kjahds@kjahds.com>,
40179 + * Copyright (C) 2000 Lineo, Inc. (www.lineo.com)
40183 + * linux/arch/m68k/mm/init.c
40185 + * Copyright (C) 1995 Hamish Macdonald
40187 + * JAN/1999 -- hacked to support ColdFire (gerg@snapgear.com)
40188 + * DEC/2000 -- linux 2.4 support <davidm@snapgear.com>
40190 + * This file is part of the Ubicom32 Linux Kernel Port.
40192 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
40193 + * it and/or modify it under the terms of the GNU General Public License
40194 + * as published by the Free Software Foundation, either version 2 of the
40195 + * License, or (at your option) any later version.
40197 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
40198 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
40199 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
40200 + * the GNU General Public License for more details.
40202 + * You should have received a copy of the GNU General Public License
40203 + * along with the Ubicom32 Linux Kernel Port. If not,
40204 + * see <http://www.gnu.org/licenses/>.
40206 + * Ubicom32 implementation derived from (with many thanks):
40212 +#include <linux/signal.h>
40213 +#include <linux/sched.h>
40214 +#include <linux/kernel.h>
40215 +#include <linux/errno.h>
40216 +#include <linux/string.h>
40217 +#include <linux/types.h>
40218 +#include <linux/ptrace.h>
40219 +#include <linux/mman.h>
40220 +#include <linux/mm.h>
40221 +#include <linux/swap.h>
40222 +#include <linux/init.h>
40223 +#include <linux/highmem.h>
40224 +#include <linux/pagemap.h>
40225 +#include <linux/bootmem.h>
40226 +#include <linux/slab.h>
40228 +#include <asm/setup.h>
40229 +#include <asm/segment.h>
40230 +#include <asm/page.h>
40231 +#include <asm/pgtable.h>
40232 +#include <asm/system.h>
40233 +#include <asm/machdep.h>
40234 +#include <asm/ocm-alloc.h>
40235 +#include <asm/processor.h>
40239 +extern void die_if_kernel(char *,struct pt_regs *,long);
40240 +extern void free_initmem(void);
40243 + * BAD_PAGE is the page that is used for page faults when linux
40244 + * is out-of-memory. Older versions of linux just did a
40245 + * do_exit(), but using this instead means there is less risk
40246 + * for a process dying in kernel mode, possibly leaving a inode
40249 + * BAD_PAGETABLE is the accompanying page-table: it is initialized
40250 + * to point to BAD_PAGE entries.
40252 + * ZERO_PAGE is a special page that is used for zero-initialized
40255 +static unsigned long empty_bad_page_table;
40257 +static unsigned long empty_bad_page;
40259 +unsigned long empty_zero_page;
40261 +void show_mem(void)
40264 + int free = 0, total = 0, reserved = 0, shared = 0;
40267 + printk(KERN_INFO "\nMem-info:\n");
40268 + show_free_areas();
40270 + while (i-- > 0) {
40272 + if (PageReserved(mem_map+i))
40274 + else if (PageSwapCache(mem_map+i))
40276 + else if (!page_count(mem_map+i))
40279 + shared += page_count(mem_map+i) - 1;
40281 + printk(KERN_INFO "%d pages of RAM\n",total);
40282 + printk(KERN_INFO "%d free pages\n",free);
40283 + printk(KERN_INFO "%d reserved pages\n",reserved);
40284 + printk(KERN_INFO "%d pages shared\n",shared);
40285 + printk(KERN_INFO "%d pages swap cached\n",cached);
40288 +extern unsigned long memory_start;
40289 +extern unsigned long memory_end;
40290 +extern char __ocm_free_begin;
40291 +extern char __ocm_free_end;
40294 + * paging_init() continues the virtual memory environment setup which
40295 + * was begun by the code in arch/head.S.
40296 + * The parameters are pointers to where to stick the starting and ending
40297 + * addresses of available kernel virtual memory.
40299 +void __init paging_init(void)
40302 + * Make sure start_mem is page aligned, otherwise bootmem and
40303 + * page_alloc get different views of the world.
40306 + unsigned long start_mem = PAGE_ALIGN(memory_start);
40308 + unsigned long end_mem = memory_end & PAGE_MASK;
40311 + printk (KERN_DEBUG "start_mem is %#lx\nvirtual_end is %#lx\n",
40312 + start_mem, end_mem);
40316 + * Initialize the bad page table and bad page to point
40317 + * to a couple of allocated pages.
40319 + empty_bad_page_table = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
40320 + empty_bad_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
40321 + empty_zero_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
40322 + memset((void *)empty_zero_page, 0, PAGE_SIZE);
40325 + * TODO: enable setting up for user memory management interface.
40329 + printk (KERN_DEBUG "before free_area_init\n");
40331 + printk (KERN_DEBUG "free_area_init -> start_mem is %#lx\nvirtual_end is %#lx\n",
40332 + start_mem, end_mem);
40336 + unsigned long zones_size[MAX_NR_ZONES] = {0, };
40337 +#ifdef CONFIG_ZONE_DMA
40338 + zones_size[ZONE_DMA] = OCMSIZE >> PAGE_SHIFT;
40340 + zones_size[ZONE_NORMAL] = (end_mem - PAGE_OFFSET) >> PAGE_SHIFT;
40341 +#ifdef CONFIG_HIGHMEM
40342 + zones_size[ZONE_HIGHMEM] = 0;
40344 + free_area_init(zones_size);
40348 +void __init mem_init(void)
40350 + int codek = 0, datak = 0, initk = 0;
40351 + unsigned long tmp, ram_start, ram_end, len;
40352 + extern char _etext, _stext, _sdata, _ebss, __init_begin, __init_end;
40354 + unsigned long start_mem = memory_start; /* DAVIDM - these must start at end of kernel */
40355 + unsigned long end_mem = memory_end; /* DAVIDM - this must not include kernel stack at top */
40356 + processor_dram(&ram_start, &ram_end);
40357 + len = (ram_end - ram_start) + OCMSIZE;
40359 + printk(KERN_DEBUG "Mem_init: start=%lx, end=%lx\n", start_mem, end_mem);
40362 + end_mem &= PAGE_MASK;
40363 + high_memory = (void *) end_mem;
40365 + start_mem = PAGE_ALIGN(start_mem);
40366 + max_mapnr = num_physpages = (((unsigned long) high_memory) - PAGE_OFFSET) >> PAGE_SHIFT;
40368 + /* this will put all memory onto the freelists */
40369 +#ifdef CONFIG_ZONE_DMA
40371 + unsigned long ocm_free_begin = (unsigned long)&__ocm_free_begin;
40372 + unsigned long ocm_free_end = (unsigned long)&__ocm_free_end;
40373 + unsigned long zone_dma_begin = (ocm_free_begin + PAGE_SIZE - 1) & PAGE_MASK;
40374 + unsigned long zone_dma_end = ocm_free_end & PAGE_MASK;
40375 + if (zone_dma_end > zone_dma_begin)
40376 + free_bootmem(zone_dma_begin, zone_dma_end-zone_dma_begin);
40379 + totalram_pages = free_all_bootmem();
40381 + codek = (&_etext - &_stext) >> 10;
40382 + datak = (&_ebss - &_sdata) >> 10;
40383 + initk = (&__init_begin - &__init_end) >> 10;
40385 + tmp = nr_free_pages() << PAGE_SHIFT;
40386 + printk(KERN_INFO "Memory available: %luk/%luk RAM, (%dk kernel code, %dk data)\n",
40395 +#ifdef CONFIG_BLK_DEV_INITRD
40396 +void free_initrd_mem(unsigned long start, unsigned long end)
40399 + for (; start < end; start += PAGE_SIZE) {
40400 + ClearPageReserved(virt_to_page(start));
40401 + init_page_count(virt_to_page(start));
40402 + free_page(start);
40403 + totalram_pages++;
40406 + printk (KERN_NOTICE "Freeing initrd memory: %dk freed\n", pages);
40413 +#ifdef CONFIG_RAMKERNEL
40414 + unsigned long addr;
40415 + extern char __init_begin, __init_end;
40417 + * The following code should be cool even if these sections
40418 + * are not page aligned.
40420 + addr = PAGE_ALIGN((unsigned long)(&__init_begin));
40421 + /* next to check that the page we free is not a partial page */
40422 + for (; addr + PAGE_SIZE < (unsigned long)(&__init_end); addr +=PAGE_SIZE) {
40423 + ClearPageReserved(virt_to_page(addr));
40424 + init_page_count(virt_to_page(addr));
40426 + totalram_pages++;
40428 + printk(KERN_NOTICE "Freeing unused kernel memory: %ldk freed (0x%x - 0x%x)\n",
40429 + (addr - PAGE_ALIGN((long) &__init_begin)) >> 10,
40430 + (int)(PAGE_ALIGN((unsigned long)(&__init_begin))),
40431 + (int)(addr - PAGE_SIZE));
40435 +++ b/arch/ubicom32/mm/kmap.c
40438 + * arch/ubicom32/mm/kmap.c
40439 + * Ubicom32 architecture non-mmu ioremap and friends implementation.
40441 + * (C) Copyright 2009, Ubicom, Inc.
40442 + * Copyright (C) 2000 Lineo, <davidm@snapgear.com>
40443 + * Copyright (C) 2000-2002 David McCullough <davidm@snapgear.com>
40445 + * This file is part of the Ubicom32 Linux Kernel Port.
40447 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
40448 + * it and/or modify it under the terms of the GNU General Public License
40449 + * as published by the Free Software Foundation, either version 2 of the
40450 + * License, or (at your option) any later version.
40452 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
40453 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
40454 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
40455 + * the GNU General Public License for more details.
40457 + * You should have received a copy of the GNU General Public License
40458 + * along with the Ubicom32 Linux Kernel Port. If not,
40459 + * see <http://www.gnu.org/licenses/>.
40461 + * Ubicom32 implementation derived from (with many thanks):
40467 +#include <linux/module.h>
40468 +#include <linux/mm.h>
40469 +#include <linux/kernel.h>
40470 +#include <linux/string.h>
40471 +#include <linux/types.h>
40472 +#include <linux/slab.h>
40473 +#include <linux/vmalloc.h>
40475 +#include <asm/setup.h>
40476 +#include <asm/segment.h>
40477 +#include <asm/page.h>
40478 +#include <asm/pgalloc.h>
40479 +#include <asm/io.h>
40480 +#include <asm/system.h>
40485 + * Map some physical address range into the kernel address space.
40487 +void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag)
40489 + return (void *)physaddr;
40493 + * Unmap a ioremap()ed region again.
40495 +void iounmap(void *addr)
40500 + * __iounmap unmaps nearly everything, so be careful
40501 + * it doesn't free currently pointer/page tables anymore but it
40502 + * wans't used anyway and might be added later.
40504 +void __iounmap(void *addr, unsigned long size)
40509 + * Set new cache mode for some kernel address space.
40510 + * The caller must push data for that range itself, if such data may already
40511 + * be in the cache.
40513 +void kernel_set_cachemode(void *addr, unsigned long size, int cmode)
40517 +++ b/arch/ubicom32/mm/Makefile
40520 +# arch/ubicom32/mm/Makefile
40521 +# <TODO: Replace with short file description>
40523 +# (C) Copyright 2009, Ubicom, Inc.
40525 +# This file is part of the Ubicom32 Linux Kernel Port.
40527 +# The Ubicom32 Linux Kernel Port is free software: you can redistribute
40528 +# it and/or modify it under the terms of the GNU General Public License
40529 +# as published by the Free Software Foundation, either version 2 of the
40530 +# License, or (at your option) any later version.
40532 +# The Ubicom32 Linux Kernel Port is distributed in the hope that it
40533 +# will be useful, but WITHOUT ANY WARRANTY; without even the implied
40534 +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
40535 +# the GNU General Public License for more details.
40537 +# You should have received a copy of the GNU General Public License
40538 +# along with the Ubicom32 Linux Kernel Port. If not,
40539 +# see <http://www.gnu.org/licenses/>.
40541 +# Ubicom32 implementation derived from (with many thanks):
40547 +# Makefile for the linux m68knommu specific parts of the memory manager.
40550 +obj-y += init.o fault.o memory.o kmap.o ocm-alloc.o
40552 +++ b/arch/ubicom32/mm/memory.c
40555 + * arch/ubicom32/mm/memory.c
40556 + * Ubicom32 architecture kernel_map() implementation.
40558 + * (C) Copyright 2009, Ubicom, Inc.
40559 + * Copyright (C) 1998 Kenneth Albanowski <kjahds@kjahds.com>,
40560 + * Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com)
40564 + * linux/arch/m68k/mm/memory.c
40566 + * Copyright (C) 1995 Hamish Macdonald
40568 + * This file is part of the Ubicom32 Linux Kernel Port.
40570 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
40571 + * it and/or modify it under the terms of the GNU General Public License
40572 + * as published by the Free Software Foundation, either version 2 of the
40573 + * License, or (at your option) any later version.
40575 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
40576 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
40577 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
40578 + * the GNU General Public License for more details.
40580 + * You should have received a copy of the GNU General Public License
40581 + * along with the Ubicom32 Linux Kernel Port. If not,
40582 + * see <http://www.gnu.org/licenses/>.
40584 + * Ubicom32 implementation derived from (with many thanks):
40590 +#include <linux/module.h>
40591 +#include <linux/mm.h>
40592 +#include <linux/kernel.h>
40593 +#include <linux/string.h>
40594 +#include <linux/types.h>
40595 +#include <linux/slab.h>
40597 +#include <asm/segment.h>
40598 +#include <asm/page.h>
40599 +#include <asm/pgtable.h>
40600 +#include <asm/system.h>
40603 + * Map some physical address range into the kernel address space.
40604 + * The code is copied and adapted from map_chunk().
40607 +unsigned long kernel_map(unsigned long paddr, unsigned long size,
40608 + int nocacheflag, unsigned long *memavailp )
40613 +++ b/arch/ubicom32/mm/ocm-alloc.c
40616 + * arch/ubicom32/mm/ocm-alloc.c
40617 + * OCM allocator for Uibcom32 On-Chip memory
40619 + * (C) Copyright 2009, Ubicom, Inc.
40620 + * Copyright 2004-2008 Analog Devices Inc.
40624 + * arch/blackfin/mm/sram-alloc.c
40627 + * This file is part of the Ubicom32 Linux Kernel Port.
40629 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
40630 + * it and/or modify it under the terms of the GNU General Public License
40631 + * as published by the Free Software Foundation, either version 2 of the
40632 + * License, or (at your option) any later version.
40634 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
40635 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
40636 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
40637 + * the GNU General Public License for more details.
40639 + * You should have received a copy of the GNU General Public License
40640 + * along with the Ubicom32 Linux Kernel Port. If not,
40641 + * see <http://www.gnu.org/licenses/>.
40643 + * Ubicom32 implementation derived from (with many thanks):
40649 +#include <linux/module.h>
40650 +#include <linux/kernel.h>
40651 +#include <linux/types.h>
40652 +#include <linux/miscdevice.h>
40653 +#include <linux/ioport.h>
40654 +#include <linux/fcntl.h>
40655 +#include <linux/init.h>
40656 +#include <linux/poll.h>
40657 +#include <linux/proc_fs.h>
40658 +#include <linux/mutex.h>
40659 +#include <linux/rtc.h>
40660 +#include <asm/ocm-alloc.h>
40663 +#define DEBUGP printk
40665 +#define DEBUGP(fmt, a...)
40668 + * the data structure for OCM heap pieces
40670 +struct ocm_piece {
40674 + struct ocm_piece *next;
40678 + * struct ocm_heap
40681 + struct ocm_piece free_head;
40682 + struct ocm_piece used_head;
40683 + struct mutex lock;
40686 +static struct ocm_heap ocm_inst_heap;
40687 +int ubi32_ocm_skbuf_max = 21, ubi32_ocm_skbuf, ubi32_ddr_skbuf;
40690 + * OCM area for storing code
40692 +extern asmlinkage void *__ocm_free_begin;
40693 +extern asmlinkage void *__ocm_free_end;
40694 +extern asmlinkage void *__ocm_inst_heap_begin;
40695 +extern asmlinkage void *__ocm_inst_heap_end;
40696 +#define OCM_INST_HEAP_BEGIN ((unsigned int)&__ocm_inst_heap_begin)
40697 +#define OCM_INST_HEAP_END ((unsigned int)&__ocm_inst_heap_end)
40698 +#define OCM_INST_HEAP_LENGTH (OCM_INST_HEAP_END - OCM_INST_HEAP_BEGIN)
40700 +static struct kmem_cache *ocm_piece_cache;
40703 + * _ocm_heap_init()
40705 +static int __init _ocm_heap_init(struct ocm_heap *ocmh,
40706 + unsigned int start,
40707 + unsigned int size)
40709 + ocmh->free_head.next = kmem_cache_alloc(ocm_piece_cache, GFP_KERNEL);
40711 + if (!ocmh->free_head.next)
40714 + ocmh->free_head.next->paddr = (void *)start;
40715 + ocmh->free_head.next->size = size;
40716 + ocmh->free_head.next->pid = 0;
40717 + ocmh->free_head.next->next = 0;
40719 + ocmh->used_head.next = NULL;
40721 + /* mutex initialize */
40722 + mutex_init(&ocmh->lock);
40728 + * _ocm_alloc_init()
40730 + * starts the ocm heap(s)
40732 +static int __init _ocm_alloc_init(void)
40734 + if (OCM_INST_HEAP_LENGTH) {
40735 + ocm_piece_cache = kmem_cache_create("ocm_piece_cache",
40736 + sizeof(struct ocm_piece),
40737 + 0, SLAB_PANIC, NULL);
40739 + if (_ocm_heap_init(&ocm_inst_heap,
40740 + OCM_INST_HEAP_BEGIN,
40741 + OCM_INST_HEAP_LENGTH) == 0)
40742 + printk(KERN_INFO "OCM Instruction Heap %d KB\n",
40743 + OCM_INST_HEAP_LENGTH >> 10);
40745 + printk(KERN_INFO "Failed to initialize OCM "
40746 + "Instruction Heap\n");
40749 + printk(KERN_INFO "No space available for OCM "
40750 + "Instruction Heap\n");
40754 +pure_initcall(_ocm_alloc_init);
40758 + * generic alloc a block in the ocm heap, if successful
40759 + * returns the pointer.
40761 +static void *_ocm_alloc(size_t size, pid_t pid, struct ocm_heap *ocmheap)
40763 + struct ocm_piece *pslot, *plast, *pavail;
40764 + struct ocm_piece *pfree_head = &ocmheap->free_head;
40765 + struct ocm_piece *pused_head = &ocmheap->used_head;
40767 + if (size <= 0 || !pfree_head || !pused_head)
40770 + /* Align the size */
40771 + size = (size + 3) & ~3;
40773 + pslot = pfree_head->next;
40774 + plast = pfree_head;
40777 + * search an available piece slot
40779 + while (pslot != NULL && size > pslot->size) {
40781 + pslot = pslot->next;
40787 + if (pslot->size == size) {
40789 + * Unlink this block from the list
40791 + plast->next = pslot->next;
40795 + * Split this block in two.
40797 + pavail = kmem_cache_alloc(ocm_piece_cache, GFP_KERNEL);
40802 + pavail->paddr = pslot->paddr;
40803 + pavail->size = size;
40804 + pslot->paddr += size;
40805 + pslot->size -= size;
40808 + pavail->pid = pid;
40810 + pslot = pused_head->next;
40811 + plast = pused_head;
40814 + * insert new piece into used piece list !!!
40816 + while (pslot != NULL && pavail->paddr < pslot->paddr) {
40818 + pslot = pslot->next;
40821 + pavail->next = pslot;
40822 + plast->next = pavail;
40824 + DEBUGP("_ocm_alloc %d bytes at %p from in %p",
40825 + size, pavail->paddr, ocmheap);
40827 + return pavail->paddr;
40831 +/* Allocate the largest available block. */
40832 +static void *_ocm_alloc_max(struct ocm_heap *ocmheap,
40833 + unsigned long *psize)
40835 + struct ocm_piece *pfree_head = &ocmheap->free_head;
40836 + struct ocm_piece *pslot, *pmax;
40838 + pmax = pslot = pfree_head->next;
40840 + /* search an available piece slot */
40841 + while (pslot != NULL) {
40842 + if (pslot->size > pmax->size)
40844 + pslot = pslot->next;
40850 + *psize = pmax->size;
40852 + return _ocm_alloc(*psize, ocmheap);
40858 + * generic free a block in the ocm heap, if successful
40860 +static int _ocm_free(const void *addr,
40861 + struct ocm_heap *ocmheap)
40863 + struct ocm_piece *pslot, *plast, *pavail;
40864 + struct ocm_piece *pfree_head = &ocmheap->free_head;
40865 + struct ocm_piece *pused_head = &ocmheap->used_head;
40867 + /* search the relevant memory slot */
40868 + pslot = pused_head->next;
40869 + plast = pused_head;
40871 + /* search an available piece slot */
40872 + while (pslot != NULL && pslot->paddr != addr) {
40874 + pslot = pslot->next;
40878 + DEBUGP("_ocm_free %p not found in %p", addr, ocmheap);
40881 + DEBUGP("_ocm_free %p from in %p", addr, ocmheap);
40883 + plast->next = pslot->next;
40887 + /* insert free pieces back to the free list */
40888 + pslot = pfree_head->next;
40889 + plast = pfree_head;
40891 + while (pslot != NULL && addr > pslot->paddr) {
40893 + pslot = pslot->next;
40896 + if (plast != pfree_head &&
40897 + plast->paddr + plast->size == pavail->paddr) {
40898 + plast->size += pavail->size;
40899 + kmem_cache_free(ocm_piece_cache, pavail);
40901 + pavail->next = plast->next;
40902 + plast->next = pavail;
40906 + if (pslot && plast->paddr + plast->size == pslot->paddr) {
40907 + plast->size += pslot->size;
40908 + plast->next = pslot->next;
40909 + kmem_cache_free(ocm_piece_cache, pslot);
40916 + * ocm_inst_alloc()
40918 + * allocates a block of size in the ocm instrction heap, if
40919 + * successful returns address allocated.
40921 +void *ocm_inst_alloc(size_t size, pid_t pid)
40925 + if (!OCM_INST_HEAP_LENGTH)
40929 + mutex_lock(&ocm_inst_heap.lock);
40931 + addr = _ocm_alloc(size, pid, &ocm_inst_heap);
40933 + mutex_unlock(&ocm_inst_heap.lock);
40937 +EXPORT_SYMBOL(ocm_inst_alloc);
40940 + * ocm_inst_free()
40941 + * free a block in the ocm instrction heap, returns 0 if successful.
40943 +int ocm_inst_free(const void *addr)
40947 + if (!OCM_INST_HEAP_LENGTH)
40950 + mutex_lock(&ocm_inst_heap.lock);
40952 + ret = _ocm_free(addr, &ocm_inst_heap);
40954 + mutex_unlock(&ocm_inst_heap.lock);
40958 +EXPORT_SYMBOL(ocm_inst_free);
40962 + * free a block in one of the ocm heaps, returns 0 if successful.
40964 +int ocm_free(const void *addr)
40966 + if (addr >= (void *)OCM_INST_HEAP_BEGIN
40967 + && addr < (void *)(OCM_INST_HEAP_END))
40968 + return ocm_inst_free(addr);
40972 +EXPORT_SYMBOL(ocm_free);
40975 +#ifdef CONFIG_PROC_FS
40976 +/* Need to keep line of output the same. Currently, that is 46 bytes
40977 + * (including newline).
40979 +static int _ocm_proc_read(char *buf, int *len, int count, const char *desc,
40980 + struct ocm_heap *ocmheap)
40982 + struct ocm_piece *pslot;
40983 + struct ocm_piece *pfree_head = &ocmheap->free_head;
40984 + struct ocm_piece *pused_head = &ocmheap->used_head;
40986 + /* The format is the following
40987 + * --- OCM 123456789012345 Size PID State \n
40988 + * 12345678-12345678 1234567890 12345 1234567890\n
40991 + l = sprintf(&buf[*len], "--- OCM %-15s Size PID State \n",
40997 + mutex_lock(&ocm_inst_heap.lock);
41000 + * search the relevant memory slot
41002 + pslot = pused_head->next;
41004 + while (pslot != NULL && count > 46) {
41005 + l = sprintf(&buf[*len], "%p-%p %10i %5i %-10s\n",
41006 + pslot->paddr, pslot->paddr + pslot->size,
41007 + pslot->size, pslot->pid, "ALLOCATED");
41011 + pslot = pslot->next;
41014 + pslot = pfree_head->next;
41016 + while (pslot != NULL && count > 46) {
41017 + l = sprintf(&buf[*len], "%p-%p %10i %5i %-10s\n",
41018 + pslot->paddr, pslot->paddr + pslot->size,
41019 + pslot->size, pslot->pid, "FREE");
41023 + pslot = pslot->next;
41026 + mutex_unlock(&ocm_inst_heap.lock);
41031 +static int ocm_proc_read(char *buf, char **start, off_t offset, int count,
41032 + int *eof, void *data)
41036 + len = sprintf(&buf[len], "--- OCM SKB usage (max RX buf %d)\n"
41037 + "(SKB in OCM) %d - (SKB in DDR) %d\n",
41038 + ubi32_ocm_skbuf_max,
41040 + ubi32_ddr_skbuf);
41042 + len += sprintf(&buf[len], "--- OCM Data Heap Size\n"
41044 + ((void *)&__ocm_free_begin),
41045 + ((void *)&__ocm_free_end),
41046 + ((unsigned int)&__ocm_free_end) -
41047 + ((unsigned int)&__ocm_free_begin));
41049 + if (_ocm_proc_read(buf, &len, count - len, "Inst Heap",
41057 +static int ocm_proc_write(struct file *file, const char __user *buffer,
41058 + unsigned long count, void *data)
41063 + if (count > sizeof(in))
41066 + if (copy_from_user(in, buffer, count))
41070 + printk(KERN_INFO "OCM skb alloc max = %s\n", in);
41074 + while ((in[n] >= '0') && (in[n] <= '9')) {
41075 + v = v * 10 + (int)(in[n] - '0');
41082 + ubi32_ocm_skbuf_max = v;
41083 + ubi32_ocm_skbuf = ubi32_ddr_skbuf = 0;
41088 +static int __init sram_proc_init(void)
41090 + struct proc_dir_entry *ptr;
41091 + ptr = create_proc_entry("ocm", S_IFREG | S_IRUGO, NULL);
41093 + printk(KERN_WARNING "unable to create /proc/ocm\n");
41096 + ptr->read_proc = ocm_proc_read;
41097 + ptr->write_proc = ocm_proc_write;
41100 +late_initcall(sram_proc_init);
41103 +++ b/arch/ubicom32/oprofile/ipProf.h
41105 +#ifndef __IP_PROF_H__
41106 +#define __IP_PROF_H__
41108 +/* This number MUST match what is used in the ultra configuration! */
41109 +#define IPPROFILETIO_MAX_SAMPLES 600
41111 +/* Move to .h file used in both; avoid special types */
41112 +struct profile_sample {
41113 + unsigned int pc; /* PC value */
41114 + unsigned int parent; /* a5 contents, to find the caller */
41115 + unsigned char cond_codes; /* for branch prediction */
41116 + unsigned char thread; /* I-blocked, D-blocked,
41117 + 4-bit thread number */
41118 + unsigned short active; /* which threads are active -
41119 + for accurate counting */
41120 + unsigned short blocked; /* which threads are blocked due to
41121 + I or D cache misses */
41122 + unsigned int latency; /* CPU clocks since the last message
41123 + dispatch in this thread
41124 + (thread 0 only for now) */
41128 +struct profilenode {
41129 + struct devtree_node dn;
41130 + volatile unsigned char enabled; /* Is the tio enabled to
41132 + volatile unsigned char busy; /* set when the samples
41133 + are being read */
41134 + volatile unsigned int mask; /* Threads that change the MT_EN flag */
41135 + volatile unsigned short rate; /* What is the sampling rate? */
41136 + volatile unsigned short head; /* sample taker puts samples here */
41137 + volatile unsigned short tail; /* packet filler takes samples here */
41138 + volatile unsigned short count; /* number of valid samples */
41139 + volatile unsigned short total; /* Total samples */
41140 + struct profile_sample samples[IPPROFILETIO_MAX_SAMPLES];
41145 +++ b/arch/ubicom32/oprofile/Makefile
41148 +# arch/ubicom32/Makefile
41149 +# Makefile for Oprofile support on Ubicom32
41151 +# (C) Copyright 2009, Ubicom, Inc.
41153 +# This file is part of the Ubicom32 Linux Kernel Port.
41155 +# The Ubicom32 Linux Kernel Port is free software: you can redistribute
41156 +# it and/or modify it under the terms of the GNU General Public License
41157 +# as published by the Free Software Foundation, either version 2 of the
41158 +# License, or (at your option) any later version.
41160 +# The Ubicom32 Linux Kernel Port is distributed in the hope that it
41161 +# will be useful, but WITHOUT ANY WARRANTY; without even the implied
41162 +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
41163 +# the GNU General Public License for more details.
41165 +# You should have received a copy of the GNU General Public License
41166 +# along with the Ubicom32 Linux Kernel Port. If not,
41167 +# see <http://www.gnu.org/licenses/>.
41169 +# Ubicom32 implementation derived from (with many thanks):
41175 +obj-$(CONFIG_OPROFILE) += oprofile.o
41177 +DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \
41178 + oprof.o cpu_buffer.o buffer_sync.o \
41179 + event_buffer.o oprofile_files.o \
41180 + oprofilefs.o oprofile_stats.o \
41183 +oprofile-y := $(DRIVER_OBJS) profile.o
41185 +++ b/arch/ubicom32/oprofile/profile.c
41188 + * arch/ubicom32/oprofile/profile.c
41189 + * Oprofile support for arch Ubicom32
41191 + * (C) Copyright 2009, Ubicom, Inc.
41193 + * This file is part of the Ubicom32 Linux Kernel Port.
41195 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
41196 + * it and/or modify it under the terms of the GNU General Public License
41197 + * as published by the Free Software Foundation, either version 2 of the
41198 + * License, or (at your option)
41199 + * any later version.
41201 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it will
41202 + * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
41203 + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41204 + * General Public License for more details.
41206 + * You should have received a copy of the GNU General Public License
41207 + * along with the Ubicom32 Linux Kernel Port. If not, see
41208 + * <http://www.gnu.org/licenses/>.
41210 + * Ubicom32 implementation derived from (with many thanks):
41217 + * @file profile.c
41219 + * @remark Copyright 2002 OProfile authors
41220 + * @remark Read the file COPYING
41222 + * @author Hunyue Yau <hy@hy-research.com>
41225 +#include <linux/oprofile.h>
41226 +#include <linux/init.h>
41227 +#include <linux/errno.h>
41228 +#include <linux/interrupt.h>
41229 +#include <linux/module.h>
41230 +#include <linux/kernel.h>
41232 +#include <asm/devtree.h>
41233 +#include <asm/thread.h>
41235 +/* For identifying userland vs kernel address */
41236 +#include <asm/stacktrace.h>
41237 +#include "ipProf.h"
41239 +/* For communications with the backend */
41240 +static struct profilenode *profile_node;
41242 +/* Bitmask containing all Linux threads - as seen by the ROSR reg */
41243 +static unsigned long th_all_mask;
41245 +/* Lookup table to translate a hardware thread into a CPU identifier
41246 + * Table is indexed by the ROSR value which is assumed to be
41247 + * relatively small (0...15).
41249 +unsigned int cpu_map[THREAD_ARCHITECTURAL_MAX];
41251 +static struct pt_regs regs;
41254 + * For each sample returned, checked to see if they are relevant to
41255 + * us. This is necessary as the ubicom32 architecture has other software
41256 + * running outside of Linux. Only then, put the sample into the relevant
41259 + * To minimize overhead, a global mask with all possible threads of in
41260 + * interest to us is used as a first check. Then a second mask identifying
41261 + * the thread is used to obtain an identifier for that "CPU".
41265 + * ubicom32_build_cpu_th_mask()
41267 + * Build a lookup table for translation between hardware thread
41268 + * "ROSR" values and Linux CPU ids
41270 + * *** This gets executed on all CPUs at once! ***
41272 +static void ubicom32_build_cpu_th_mask(void *mask)
41274 + thread_t self = thread_get_self();
41275 + unsigned long *th_m = mask;
41277 + BUG_ON(self <= 0 || self >= THREAD_ARCHITECTURAL_MAX);
41278 + cpu_map[self] = smp_processor_id();
41280 + set_bit(self, th_m);
41284 + * profile_interrupt()
41286 + * Process samples returned from the profiler backend. The backend
41287 + * may return samples that are irrelevant to us or may even return
41288 + * multiple samples for the same CPU. Note that the sames may be
41289 + * for ANY cpu. At this time, this is unique and to support this requires
41290 + * Oprofile to expose an interface to accept the CPU that the same came
41293 +static irqreturn_t profile_interrupt(int irq, void *arg)
41295 + int i, buf_entry;
41297 + unsigned int bit_th;
41300 + if (!(profile_node->enabled) || profile_node->count < 0) {
41301 + printk(KERN_WARNING
41302 + "Unexpected interrupt, no samples or not enabled!\n");
41303 + return IRQ_HANDLED;
41306 + profile_node->busy = 1; /* Keep backend out */
41308 + for (i = 0; i < profile_node->count; i++) {
41309 + buf_entry = profile_node->tail;
41310 + profile_node->tail++;
41311 + profile_node->tail %= IPPROFILETIO_MAX_SAMPLES;
41313 + /* Note - the "thread" ID is only the lower 4 bits */
41314 + th = (0x0f & profile_node->samples[buf_entry].thread);
41315 + bit_th = (1 << th);
41317 + if ((bit_th & th_all_mask) == 0)
41320 + regs.pc = profile_node->samples[buf_entry].pc;
41322 + is_kernel = ubicom32_is_kernel(regs.pc);
41324 + oprofile_add_ext_sample_cpu(regs.pc, ®s, 0, is_kernel,
41327 + profile_node->count = 0;
41328 + profile_node->busy = 0;
41330 + return IRQ_HANDLED;
41334 + * profile_start()
41336 + * Notification from oprofile to start the profiler
41338 +static int profile_start(void)
41340 + if (!profile_node)
41343 + profile_node->enabled = 1;
41351 + * Notification from oprofile to stop the profiler
41353 +static void profile_stop(void)
41355 + if (profile_node)
41356 + profile_node->enabled = 0;
41360 + * oprofile_arch_init()
41362 + * Attach to Oprofile after qualify the availability of the backend
41363 + * profiler support.
41365 +int __init oprofile_arch_init(struct oprofile_operations *ops)
41369 + profile_node = (struct profilenode *)devtree_find_node("profiler");
41371 + if (profile_node == NULL) {
41372 + printk(KERN_WARNING "Cannot find profiler node\n");
41376 + r = request_irq(profile_node->dn.recvirq, profile_interrupt,
41377 + IRQF_DISABLED, "profiler", NULL);
41380 + profile_node = NULL;
41381 + printk(KERN_WARNING "Cannot get profiler IRQ\n");
41385 + ops->start = profile_start;
41386 + ops->stop = profile_stop;
41387 + ops->cpu_type = "timer";
41389 + memset(cpu_map, 0, sizeof(cpu_map));
41391 + on_each_cpu(ubicom32_build_cpu_th_mask, &th_all_mask, 1);
41393 + memset(®s, 0, sizeof(regs));
41399 + * oprofile_arch_exit()
41401 + * External call to take outselves out.
41402 + * Make sure backend is not running.
41404 +void oprofile_arch_exit(void)
41406 + BUG_ON(profile_node->enabled);
41408 --- a/drivers/char/hw_random/Kconfig
41409 +++ b/drivers/char/hw_random/Kconfig
41410 @@ -148,3 +148,16 @@ config HW_RANDOM_VIRTIO
41412 To compile this driver as a module, choose M here: the
41413 module will be called virtio-rng. If unsure, say N.
41415 +config HW_RANDOM_UBICOM32
41416 + tristate "Ubicom32 HW Random Number Generator support"
41417 + depends on HW_RANDOM && UBICOM32
41418 + default HW_RANDOM
41420 + This driver provides kernel-side support for the Random Number
41421 + Generator hardware found on Ubicom32 processors.
41423 + To compile this driver as a module, choose M here: the
41424 + module will be called pasemi-rng.
41426 + If unsure, say Y.
41427 --- a/drivers/char/hw_random/Makefile
41428 +++ b/drivers/char/hw_random/Makefile
41429 @@ -15,3 +15,4 @@ obj-$(CONFIG_HW_RANDOM_IXP4XX) += ixp4xx
41430 obj-$(CONFIG_HW_RANDOM_OMAP) += omap-rng.o
41431 obj-$(CONFIG_HW_RANDOM_PASEMI) += pasemi-rng.o
41432 obj-$(CONFIG_HW_RANDOM_VIRTIO) += virtio-rng.o
41433 +obj-$(CONFIG_HW_RANDOM_UBICOM32) += ubicom32-rng.o
41435 +++ b/drivers/char/hw_random/ubicom32-rng.c
41438 + * drivers/net/ubi32-eth.c
41439 + * Ubicom32 hardware random number generator driver.
41441 + * (C) Copyright 2009, Ubicom, Inc.
41443 + * This file is part of the Ubicom32 Linux Kernel Port.
41445 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
41446 + * it and/or modify it under the terms of the GNU General Public License
41447 + * as published by the Free Software Foundation, either version 2 of the
41448 + * License, or (at your option) any later version.
41450 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
41451 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
41452 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
41453 + * the GNU General Public License for more details.
41455 + * You should have received a copy of the GNU General Public License
41456 + * along with the Ubicom32 Linux Kernel Port. If not,
41457 + * see <http://www.gnu.org/licenses/>.
41459 + * Ubicom32 implementation derived from (with many thanks):
41465 +#include <linux/kernel.h>
41466 +#include <linux/module.h>
41467 +#include <linux/hw_random.h>
41468 +#include <linux/delay.h>
41469 +#include <asm/io.h>
41470 +#include <asm/ip5000.h>
41472 +#define MODULE_NAME "ubicom32_rng"
41474 +static int ubicom32_rng_data_present(struct hwrng *rng, int wait)
41478 + for (i = 0; i < 20; i++) {
41479 + data = *(int *)(TIMER_BASE + TIMER_TRN);
41480 + if (data || !wait)
41487 +static int ubicom32_rng_data_read(struct hwrng *rng, u32 *data)
41489 + *data = *(int *)(TIMER_BASE + TIMER_TRN);
41493 +static int ubicom32_rng_init(struct hwrng *rng)
41495 + printk(KERN_INFO "ubicom32 rng init\n");
41496 + *(int *)(TIMER_BASE + TIMER_TRN_CFG) = TIMER_TRN_CFG_ENABLE_OSC;
41500 +static void ubicom32_rng_cleanup(struct hwrng *rng)
41502 + printk(KERN_INFO "ubicom32 rng cleanup\n");
41503 + *(int *)(TIMER_BASE + TIMER_TRN_CFG) = 0;
41506 +static struct hwrng ubicom32_rng = {
41507 + .name = MODULE_NAME,
41508 + .init = ubicom32_rng_init,
41509 + .cleanup = ubicom32_rng_cleanup,
41510 + .data_present = ubicom32_rng_data_present,
41511 + .data_read = ubicom32_rng_data_read,
41515 +static int __init mod_init(void)
41519 + printk(KERN_INFO "ubicom32 rng started\n");
41520 + err = hwrng_register(&ubicom32_rng);
41522 + printk(KERN_ERR "ubicom32 rng register failed (%d)\n",
41529 +static void __exit mod_exit(void)
41531 + printk(KERN_INFO "ubicom32 rng stopped\n");
41532 + hwrng_unregister(&ubicom32_rng);
41535 +module_init(mod_init);
41536 +module_exit(mod_exit);
41538 +MODULE_LICENSE("GPL");
41539 +MODULE_AUTHOR("Ubicom, Inc.");
41540 +MODULE_DESCRIPTION("H/W rng driver for ubicom32 processor");
41541 +MODULE_VERSION("1:1.0.a");
41542 --- a/drivers/crypto/Kconfig
41543 +++ b/drivers/crypto/Kconfig
41544 @@ -61,6 +61,40 @@ config CRYPTO_DEV_GEODE
41545 To compile this driver as a module, choose M here: the module
41546 will be called geode-aes.
41548 +config CRYPTO_UBICOM32
41549 + bool "Ubicom32 Security Module"
41550 + depends on UBICOM32
41552 + This is the ubicom32 hardware acceleration common code.
41554 +config CRYPTO_AES_UBICOM32
41555 + tristate "Ubicom32 AES implementation"
41556 + depends on CRYPTO_UBICOM32
41557 + select CRYPTO_ALGAPI
41559 + This is the ubicom32 hardware AES implementation.
41561 +config CRYPTO_DES_UBICOM32
41562 + tristate "Ubicom32 DES implementation"
41563 + depends on CRYPTO_UBICOM32
41564 + select CRYPTO_ALGAPI
41566 + This is the ubicom32 hardware DES and 3DES implementation.
41568 +config CRYPTO_SHA1_UBICOM32
41569 + tristate "Ubicom32 SHA1 implementation"
41570 + depends on CRYPTO_UBICOM32
41571 + select CRYPTO_ALGAPI
41573 + This is the ubicom32 hardware SHA1 implementation.
41575 +config CRYPTO_MD5_UBICOM32
41576 + tristate "Ubicom32 MD5 implementation"
41577 + depends on CRYPTO_UBICOM32
41578 + select CRYPTO_ALGAPI
41580 + This is the ubicom32 hardware MD5 implementation.
41583 tristate "Support for PCI-attached cryptographic adapters"
41585 --- a/drivers/mmc/host/Kconfig
41586 +++ b/drivers/mmc/host/Kconfig
41587 @@ -266,3 +266,10 @@ config GPIOMMC_CONFIGFS
41589 This option automatically enables configfs support for gpiommc
41590 if configfs is available.
41592 +config MMC_UBICOM32
41593 + tristate "Ubicom32 MMC/SD host controller"
41594 + depends on UBICOM32
41596 + This provides support for the SD/MMC hardware found on Ubicom32
41598 --- a/drivers/mmc/host/Makefile
41599 +++ b/drivers/mmc/host/Makefile
41600 @@ -30,4 +30,5 @@ obj-$(CONFIG_MMC_S3C) += s3cmci.o
41601 obj-$(CONFIG_MMC_SDRICOH_CS) += sdricoh_cs.o
41602 obj-$(CONFIG_MMC_TMIO) += tmio_mmc.o
41603 obj-$(CONFIG_GPIOMMC) += gpiommc.o
41604 +obj-$(CONFIG_MMC_UBICOM32) += ubicom32sd.o
41607 +++ b/drivers/mmc/host/ubicom32sd.c
41610 + * drivers/mmc/host/ubicom32sd.c
41611 + * Ubicom32 Secure Digital Host Controller Interface driver
41613 + * (C) Copyright 2009, Ubicom, Inc.
41615 + * This file is part of the Ubicom32 Linux Kernel Port.
41617 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
41618 + * it and/or modify it under the terms of the GNU General Public License
41619 + * as published by the Free Software Foundation, either version 2 of the
41620 + * License, or (at your option) any later version.
41622 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
41623 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
41624 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
41625 + * the GNU General Public License for more details.
41627 + * You should have received a copy of the GNU General Public License
41628 + * along with the Ubicom32 Linux Kernel Port. If not,
41629 + * see <http://www.gnu.org/licenses/>.
41632 +#include <linux/module.h>
41633 +#include <linux/platform_device.h>
41634 +#include <linux/delay.h>
41635 +#include <linux/scatterlist.h>
41636 +#include <linux/leds.h>
41637 +#include <linux/gpio.h>
41638 +#include <linux/mmc/host.h>
41640 +#include <asm/ubicom32sd.h>
41642 +#define DRIVER_NAME "ubicom32sd"
41644 +#define sd_printk(...)
41645 +//#define sd_printk printk
41647 +#define SDTIO_VP_VERSION 3
41649 +#define SDTIO_MAX_SG_BLOCKS 16
41651 +enum sdtio_commands {
41652 + SDTIO_COMMAND_NOP,
41653 + SDTIO_COMMAND_SETUP,
41654 + SDTIO_COMMAND_SETUP_SDIO,
41655 + SDTIO_COMMAND_EXECUTE,
41656 + SDTIO_COMMAND_RESET,
41659 +#define SDTIO_COMMAND_SHIFT 24
41660 +#define SDTIO_COMMAND_FLAG_STOP_RSP_CRC (1 << 10)
41661 +#define SDTIO_COMMAND_FLAG_STOP_RSP_136 (1 << 9)
41662 +#define SDTIO_COMMAND_FLAG_STOP_RSP (1 << 8)
41663 +#define SDTIO_COMMAND_FLAG_STOP_CMD (1 << 7)
41664 +#define SDTIO_COMMAND_FLAG_DATA_STREAM (1 << 6)
41665 +#define SDTIO_COMMAND_FLAG_DATA_RD (1 << 5)
41666 +#define SDTIO_COMMAND_FLAG_DATA_WR (1 << 4)
41667 +#define SDTIO_COMMAND_FLAG_CMD_RSP_CRC (1 << 3)
41668 +#define SDTIO_COMMAND_FLAG_CMD_RSP_136 (1 << 2)
41669 +#define SDTIO_COMMAND_FLAG_CMD_RSP (1 << 1)
41670 +#define SDTIO_COMMAND_FLAG_CMD (1 << 0)
41673 + * SDTIO_COMMAND_SETUP_SDIO
41675 +#define SDTIO_COMMAND_FLAG_SDIO_INT_EN (1 << 0)
41678 + * SDTIO_COMMAND_SETUP
41679 + * clock speed in arg
41681 +#define SDTIO_COMMAND_FLAG_4BIT (1 << 3)
41682 +#define SDTIO_COMMAND_FLAG_1BIT (1 << 2)
41683 +#define SDTIO_COMMAND_FLAG_SET_CLOCK (1 << 1)
41684 +#define SDTIO_COMMAND_FLAG_SET_WIDTH (1 << 0)
41686 +#define SDTIO_COMMAND_FLAG_CMD_RSP_MASK (SDTIO_COMMAND_FLAG_CMD_RSP | SDTIO_COMMAND_FLAG_CMD_RSP_136)
41687 +#define SDTIO_COMMAND_FLAG_STOP_RSP_MASK (SDTIO_COMMAND_FLAG_STOP_RSP | SDTIO_COMMAND_FLAG_STOP_RSP_136)
41688 +#define SDTIO_COMMAND_FLAG_RSP_MASK (SDTIO_COMMAND_FLAG_CMD_RSP_MASK | SDTIO_COMMAND_FLAG_STOP_RSP_MASK)
41690 +struct sdtio_vp_sg {
41691 + volatile void *addr;
41692 + volatile u32_t len;
41695 +#define SDTIO_VP_INT_STATUS_DONE (1 << 31)
41696 +#define SDTIO_VP_INT_STATUS_SDIO_INT (1 << 10)
41697 +#define SDTIO_VP_INT_STATUS_DATA_CRC_ERR (1 << 9)
41698 +#define SDTIO_VP_INT_STATUS_DATA_PROG_ERR (1 << 8)
41699 +#define SDTIO_VP_INT_STATUS_DATA_TIMEOUT (1 << 7)
41700 +#define SDTIO_VP_INT_STATUS_STOP_RSP_CRC (1 << 6)
41701 +#define SDTIO_VP_INT_STATUS_STOP_RSP_TIMEOUT (1 << 5)
41702 +#define SDTIO_VP_INT_STATUS_CMD_RSP_CRC (1 << 4)
41703 +#define SDTIO_VP_INT_STATUS_CMD_RSP_TIMEOUT (1 << 3)
41704 +#define SDTIO_VP_INT_STATUS_CMD_TIMEOUT (1 << 2)
41705 +#define SDTIO_VP_INT_STATUS_CARD1_INSERT (1 << 1)
41706 +#define SDTIO_VP_INT_STATUS_CARD0_INSERT (1 << 0)
41708 +struct sdtio_vp_regs {
41713 + volatile u32_t int_status;
41715 + volatile u32_t command;
41716 + volatile u32_t arg;
41718 + volatile u32_t cmd_opcode;
41719 + volatile u32_t cmd_arg;
41720 + volatile u32_t cmd_rsp0;
41721 + volatile u32_t cmd_rsp1;
41722 + volatile u32_t cmd_rsp2;
41723 + volatile u32_t cmd_rsp3;
41725 + volatile u32_t stop_opcode;
41726 + volatile u32_t stop_arg;
41727 + volatile u32_t stop_rsp0;
41728 + volatile u32_t stop_rsp1;
41729 + volatile u32_t stop_rsp2;
41730 + volatile u32_t stop_rsp3;
41732 + volatile u32_t data_timeout_ns;
41733 + volatile u16_t data_blksz;
41734 + volatile u16_t data_blkct;
41735 + volatile u32_t data_bytes_transferred;
41736 + volatile u32_t sg_len;
41737 + struct sdtio_vp_sg sg[SDTIO_MAX_SG_BLOCKS];
41740 +struct ubicom32sd_data {
41741 + const struct ubicom32sd_platform_data *pdata;
41743 + struct mmc_host *mmc;
41746 + * Lock used to protect the data structure
41753 + * Receive and transmit interrupts used for communicating
41760 + * Current outstanding mmc request
41762 + struct mmc_request *mrq;
41765 + * Hardware registers
41767 + struct sdtio_vp_regs *regs;
41770 +/*****************************************************************************\
41772 + * Suspend/resume *
41774 +\*****************************************************************************/
41776 +#if 0//def CONFIG_PM
41778 +int ubicom32sd_suspend_host(struct ubicom32sd_host *host, pm_message_t state)
41782 + ret = mmc_suspend_host(host->mmc, state);
41786 + free_irq(host->irq, host);
41791 +EXPORT_SYMBOL_GPL(ubicom32sd_suspend_host);
41793 +int ubicom32sd_resume_host(struct ubicom32sd_host *host)
41797 + if (host->flags & UBICOM32SD_USE_DMA) {
41798 + if (host->ops->enable_dma)
41799 + host->ops->enable_dma(host);
41802 + ret = request_irq(host->irq, ubicom32sd_irq, IRQF_SHARED,
41803 + mmc_hostname(host->mmc), host);
41807 + ubicom32sd_init(host);
41810 + ret = mmc_resume_host(host->mmc);
41817 +EXPORT_SYMBOL_GPL(ubicom32sd_resume_host);
41819 +#endif /* CONFIG_PM */
41822 + * ubicom32sd_send_command_sync
41824 +static void ubicom32sd_send_command_sync(struct ubicom32sd_data *ud, u32_t command, u32_t arg)
41826 + ud->regs->command = command;
41827 + ud->regs->arg = arg;
41828 + ubicom32_set_interrupt(ud->irq_tx);
41829 + while (ud->regs->command) {
41835 + * ubicom32sd_send_command
41837 +static void ubicom32sd_send_command(struct ubicom32sd_data *ud, u32_t command, u32_t arg)
41839 + ud->regs->command = command;
41840 + ud->regs->arg = arg;
41841 + ubicom32_set_interrupt(ud->irq_tx);
41845 + * ubicom32sd_reset
41847 +static void ubicom32sd_reset(struct ubicom32sd_data *ud)
41849 + ubicom32sd_send_command_sync(ud, SDTIO_COMMAND_RESET << SDTIO_COMMAND_SHIFT, 0);
41850 + ud->regs->int_status = 0;
41854 + * ubicom32sd_mmc_request
41856 +static void ubicom32sd_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
41858 + struct ubicom32sd_data *ud = (struct ubicom32sd_data *)mmc_priv(mmc);
41859 + u32_t command = SDTIO_COMMAND_EXECUTE << SDTIO_COMMAND_SHIFT;
41862 + WARN(ud->mrq != NULL, "ud->mrq still set to %p\n", ud->mrq);
41863 + //pr_debug("send cmd %08x arg %08x flags %08x\n", cmd->opcode, cmd->arg, cmd->flags);
41866 + struct mmc_command *cmd = mrq->cmd;
41868 + sd_printk("%s:\t\t\tsetup cmd %02d arg %08x flags %08x\n", mmc_hostname(mmc), cmd->opcode, cmd->arg, cmd->flags);
41870 + ud->regs->cmd_opcode = cmd->opcode;
41871 + ud->regs->cmd_arg = cmd->arg;
41873 + command |= SDTIO_COMMAND_FLAG_CMD;
41875 + if (cmd->flags & MMC_RSP_PRESENT) {
41876 + command |= SDTIO_COMMAND_FLAG_CMD_RSP;
41879 + if (cmd->flags & MMC_RSP_136) {
41880 + command |= SDTIO_COMMAND_FLAG_CMD_RSP_136;
41883 + if (cmd->flags & MMC_RSP_CRC) {
41884 + command |= SDTIO_COMMAND_FLAG_CMD_RSP_CRC;
41889 + struct mmc_data *data = mrq->data;
41890 + struct scatterlist *sg = data->sg;
41893 +printk("%s:\t\t\tsetup data blksz %d num %d sglen=%d fl=%08x Tns=%u\n", mmc_hostname(mmc), data->blksz, data->blocks, data->sg_len, data->flags, data->timeout_ns);
41895 + sd_printk("%s:\t\t\tsetup data blksz %d num %d sglen=%d fl=%08x Tns=%u\n",
41896 + mmc_hostname(mmc), data->blksz, data->blocks, data->sg_len,
41897 + data->flags, data->timeout_ns);
41899 + if (data->sg_len > SDTIO_MAX_SG_BLOCKS) {
41901 + data->error = -EINVAL;
41905 + ud->regs->data_timeout_ns = data->timeout_ns;
41906 + ud->regs->data_blksz = data->blksz;
41907 + ud->regs->data_blkct = data->blocks;
41908 + ud->regs->sg_len = data->sg_len;
41911 + * Load all of our sg list into the driver sg buffer
41913 + for (i = 0; i < data->sg_len; i++) {
41914 + sd_printk("%s: sg %d = %p %d\n", mmc_hostname(mmc), i, sg_virt(sg), sg->length);
41915 + ud->regs->sg[i].addr = sg_virt(sg);
41916 + ud->regs->sg[i].len = sg->length;
41917 + if (((u32_t)ud->regs->sg[i].addr & 0x03) || (sg->length & 0x03)) {
41918 + sd_printk("%s: Need aligned buffers\n", mmc_hostname(mmc));
41920 + data->error = -EINVAL;
41925 + if (data->flags & MMC_DATA_READ) {
41926 + command |= SDTIO_COMMAND_FLAG_DATA_RD;
41927 + } else if (data->flags & MMC_DATA_WRITE) {
41928 + command |= SDTIO_COMMAND_FLAG_DATA_WR;
41929 + } else if (data->flags & MMC_DATA_STREAM) {
41930 + command |= SDTIO_COMMAND_FLAG_DATA_STREAM;
41935 + struct mmc_command *stop = mrq->stop;
41936 + sd_printk("%s: \t\t\tsetup stop %02d arg %08x flags %08x\n", mmc_hostname(mmc), stop->opcode, stop->arg, stop->flags);
41938 + ud->regs->stop_opcode = stop->opcode;
41939 + ud->regs->stop_arg = stop->arg;
41941 + command |= SDTIO_COMMAND_FLAG_STOP_CMD;
41943 + if (stop->flags & MMC_RSP_PRESENT) {
41944 + command |= SDTIO_COMMAND_FLAG_STOP_RSP;
41947 + if (stop->flags & MMC_RSP_136) {
41948 + command |= SDTIO_COMMAND_FLAG_STOP_RSP_136;
41951 + if (stop->flags & MMC_RSP_CRC) {
41952 + command |= SDTIO_COMMAND_FLAG_STOP_RSP_CRC;
41958 + sd_printk("%s: Sending command %08x\n", mmc_hostname(mmc), command);
41960 + ubicom32sd_send_command(ud, command, 0);
41964 + sd_printk("%s: mmcreq ret = %d\n", mmc_hostname(mmc), ret);
41965 + mrq->cmd->error = ret;
41966 + mmc_request_done(mmc, mrq);
41970 + * ubicom32sd_mmc_set_ios
41972 +static void ubicom32sd_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
41974 + struct ubicom32sd_data *ud = (struct ubicom32sd_data *)mmc_priv(mmc);
41975 + u32_t command = SDTIO_COMMAND_SETUP << SDTIO_COMMAND_SHIFT;
41977 + sd_printk("%s: ios call bw:%u pm:%u clk:%u\n", mmc_hostname(mmc), 1 << ios->bus_width, ios->power_mode, ios->clock);
41979 + switch (ios->bus_width) {
41980 + case MMC_BUS_WIDTH_1:
41981 + command |= SDTIO_COMMAND_FLAG_SET_WIDTH | SDTIO_COMMAND_FLAG_1BIT;
41984 + case MMC_BUS_WIDTH_4:
41985 + command |= SDTIO_COMMAND_FLAG_SET_WIDTH | SDTIO_COMMAND_FLAG_4BIT;
41989 + if (ios->clock) {
41990 + arg = ios->clock;
41991 + command |= SDTIO_COMMAND_FLAG_SET_CLOCK;
41994 + switch (ios->power_mode) {
41997 + * Turn off the SD bus (power + clock)
41999 + case MMC_POWER_OFF:
42000 + gpio_set_value(ud->pdata->cards[0].pin_pwr, !ud->pdata->cards[0].pwr_polarity);
42001 + command |= SDTIO_COMMAND_FLAG_SET_CLOCK;
42005 + * Turn on the power to the SD bus
42007 + case MMC_POWER_ON:
42008 + gpio_set_value(ud->pdata->cards[0].pin_pwr, ud->pdata->cards[0].pwr_polarity);
42012 + * Turn on the clock to the SD bus
42014 + case MMC_POWER_UP:
42021 + ubicom32sd_send_command_sync(ud, command, arg);
42024 + * Let the power settle down
42030 + * ubicom32sd_mmc_get_cd
42032 +static int ubicom32sd_mmc_get_cd(struct mmc_host *mmc)
42034 + struct ubicom32sd_data *ud = (struct ubicom32sd_data *)mmc_priv(mmc);
42035 + sd_printk("%s: get cd %u %u\n", mmc_hostname(mmc), ud->pdata->cards[0].pin_cd, gpio_get_value(ud->pdata->cards[0].pin_cd));
42037 + return gpio_get_value(ud->pdata->cards[0].pin_cd) ?
42038 + ud->pdata->cards[0].cd_polarity :
42039 + !ud->pdata->cards[0].cd_polarity;
42043 + * ubicom32sd_mmc_get_ro
42045 +static int ubicom32sd_mmc_get_ro(struct mmc_host *mmc)
42047 + struct ubicom32sd_data *ud = (struct ubicom32sd_data *)mmc_priv(mmc);
42048 + sd_printk("%s: get ro %u %u\n", mmc_hostname(mmc), ud->pdata->cards[0].pin_wp, gpio_get_value(ud->pdata->cards[0].pin_wp));
42050 + return gpio_get_value(ud->pdata->cards[0].pin_wp) ?
42051 + ud->pdata->cards[0].wp_polarity :
42052 + !ud->pdata->cards[0].wp_polarity;
42056 + * ubicom32sd_mmc_enable_sdio_irq
42058 +static void ubicom32sd_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
42060 + struct ubicom32sd_data *ud = (struct ubicom32sd_data *)mmc_priv(mmc);
42062 + ud->int_en = enable;
42063 + if (enable && ud->int_pend) {
42064 + ud->int_pend = 0;
42065 + mmc_signal_sdio_irq(mmc);
42070 + * ubicom32sd_interrupt
42072 +static irqreturn_t ubicom32sd_interrupt(int irq, void *dev)
42074 + struct mmc_host *mmc = (struct mmc_host *)dev;
42075 + struct mmc_request *mrq;
42076 + struct ubicom32sd_data *ud;
42077 + u32_t int_status;
42080 + return IRQ_HANDLED;
42083 + ud = (struct ubicom32sd_data *)mmc_priv(mmc);
42085 + return IRQ_HANDLED;
42088 + int_status = ud->regs->int_status;
42089 + ud->regs->int_status &= ~int_status;
42091 + if (int_status & SDTIO_VP_INT_STATUS_SDIO_INT) {
42092 + if (ud->int_en) {
42093 + ud->int_pend = 0;
42094 + mmc_signal_sdio_irq(mmc);
42100 + if (!(int_status & SDTIO_VP_INT_STATUS_DONE)) {
42101 + return IRQ_HANDLED;
42106 + sd_printk("%s: Spurious interrupt", mmc_hostname(mmc));
42107 + return IRQ_HANDLED;
42112 + * SDTIO_VP_INT_DONE
42114 + if (mrq->cmd->flags & MMC_RSP_PRESENT) {
42115 + struct mmc_command *cmd = mrq->cmd;
42118 + if ((cmd->flags & MMC_RSP_CRC) && (int_status & SDTIO_VP_INT_STATUS_CMD_RSP_CRC)) {
42119 + cmd->error = -EILSEQ;
42120 + } else if (int_status & SDTIO_VP_INT_STATUS_CMD_RSP_TIMEOUT) {
42121 + cmd->error = -ETIMEDOUT;
42123 + } else if (cmd->flags & MMC_RSP_136) {
42124 + cmd->resp[0] = ud->regs->cmd_rsp0;
42125 + cmd->resp[1] = ud->regs->cmd_rsp1;
42126 + cmd->resp[2] = ud->regs->cmd_rsp2;
42127 + cmd->resp[3] = ud->regs->cmd_rsp3;
42129 + cmd->resp[0] = ud->regs->cmd_rsp0;
42131 + sd_printk("%s:\t\t\tResponse %08x %08x %08x %08x err=%d\n", mmc_hostname(mmc), cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3], cmd->error);
42135 + struct mmc_data *data = mrq->data;
42137 + if (int_status & SDTIO_VP_INT_STATUS_DATA_TIMEOUT) {
42138 + data->error = -ETIMEDOUT;
42139 + sd_printk("%s:\t\t\tData Timeout\n", mmc_hostname(mmc));
42141 + } else if (int_status & SDTIO_VP_INT_STATUS_DATA_CRC_ERR) {
42142 + data->error = -EILSEQ;
42143 + sd_printk("%s:\t\t\tData CRC\n", mmc_hostname(mmc));
42145 + } else if (int_status & SDTIO_VP_INT_STATUS_DATA_PROG_ERR) {
42146 + data->error = -EILSEQ;
42147 + sd_printk("%s:\t\t\tData Program Error\n", mmc_hostname(mmc));
42151 + data->bytes_xfered = ud->regs->data_bytes_transferred;
42155 + if (mrq->stop && (mrq->stop->flags & MMC_RSP_PRESENT)) {
42156 + struct mmc_command *stop = mrq->stop;
42159 + if ((stop->flags & MMC_RSP_CRC) && (int_status & SDTIO_VP_INT_STATUS_STOP_RSP_CRC)) {
42160 + stop->error = -EILSEQ;
42161 + } else if (int_status & SDTIO_VP_INT_STATUS_STOP_RSP_TIMEOUT) {
42162 + stop->error = -ETIMEDOUT;
42164 + } else if (stop->flags & MMC_RSP_136) {
42165 + stop->resp[0] = ud->regs->stop_rsp0;
42166 + stop->resp[1] = ud->regs->stop_rsp1;
42167 + stop->resp[2] = ud->regs->stop_rsp2;
42168 + stop->resp[3] = ud->regs->stop_rsp3;
42170 + stop->resp[0] = ud->regs->stop_rsp0;
42172 + sd_printk("%s:\t\t\tStop Response %08x %08x %08x %08x err=%d\n", mmc_hostname(mmc), stop->resp[0], stop->resp[1], stop->resp[2], stop->resp[3], stop->error);
42176 + mmc_request_done(mmc, mrq);
42178 + return IRQ_HANDLED;
42181 +static struct mmc_host_ops ubicom32sd_ops = {
42182 + .request = ubicom32sd_mmc_request,
42183 + .set_ios = ubicom32sd_mmc_set_ios,
42184 + .get_ro = ubicom32sd_mmc_get_ro,
42185 + .get_cd = ubicom32sd_mmc_get_cd,
42186 + .enable_sdio_irq = ubicom32sd_mmc_enable_sdio_irq,
42190 + * ubicom32sd_probe
42192 +static int __devinit ubicom32sd_probe(struct platform_device *pdev)
42194 + struct ubicom32sd_platform_data *pdata = (struct ubicom32sd_platform_data *)pdev->dev.platform_data;
42195 + struct mmc_host *mmc;
42196 + struct ubicom32sd_data *ud;
42197 + struct resource *res_regs;
42198 + struct resource *res_irq_tx;
42199 + struct resource *res_irq_rx;
42203 + * Get our resources, regs is the hardware driver base address
42204 + * and the tx and rx irqs are used to communicate with the
42205 + * hardware driver.
42207 + res_regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
42208 + res_irq_tx = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
42209 + res_irq_rx = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
42210 + if (!res_regs || !res_irq_tx || !res_irq_rx) {
42216 + * Reserve any gpios we need
42218 + ret = gpio_request(pdata->cards[0].pin_wp, "sd-wp");
42222 + gpio_direction_input(pdata->cards[0].pin_wp);
42224 + ret = gpio_request(pdata->cards[0].pin_cd, "sd-cd");
42228 + gpio_direction_input(pdata->cards[0].pin_cd);
42231 + * HACK: for the dual port controller on port F, we don't support the second port right now
42233 + if (pdata->ncards > 1) {
42234 + ret = gpio_request(pdata->cards[1].pin_pwr, "sd-pwr");
42235 + gpio_direction_output(pdata->cards[1].pin_pwr, !pdata->cards[1].pwr_polarity);
42236 + gpio_direction_output(pdata->cards[1].pin_pwr, pdata->cards[1].pwr_polarity);
42239 + ret = gpio_request(pdata->cards[0].pin_pwr, "sd-pwr");
42243 + gpio_direction_output(pdata->cards[0].pin_pwr, !pdata->cards[0].pwr_polarity);
42246 + * Allocate the MMC driver, it includes memory for our data.
42248 + mmc = mmc_alloc_host(sizeof(struct ubicom32sd_data), &pdev->dev);
42253 + ud = (struct ubicom32sd_data *)mmc_priv(mmc);
42255 + ud->pdata = pdata;
42256 + ud->regs = (struct sdtio_vp_regs *)res_regs->start;
42257 + ud->irq_tx = res_irq_tx->start;
42258 + ud->irq_rx = res_irq_rx->start;
42259 + platform_set_drvdata(pdev, mmc);
42261 + ret = request_irq(ud->irq_rx, ubicom32sd_interrupt, IRQF_DISABLED, mmc_hostname(mmc), mmc);
42267 + * Fill in the mmc structure
42269 + mmc->ops = &ubicom32sd_ops;
42270 + mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_NEEDS_POLL | MMC_CAP_SDIO_IRQ |
42271 + MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED;
42273 + mmc->f_min = ud->regs->f_min;
42274 + mmc->f_max = ud->regs->f_max;
42275 + mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
42278 + * Setup some restrictions on transfers
42280 + * We allow up to SDTIO_MAX_SG_BLOCKS of data to DMA into, there are
42281 + * not really any "max_seg_size", "max_req_size", or "max_blk_count"
42282 + * restrictions (must be less than U32_MAX though), pick
42283 + * something large?!...
42285 + * The hardware can do up to 4095 bytes per block, since the spec
42286 + * only requires 2048, we'll set it to that and not worry about
42287 + * potential weird blk lengths.
42289 + mmc->max_hw_segs = SDTIO_MAX_SG_BLOCKS;
42290 + mmc->max_phys_segs = SDTIO_MAX_SG_BLOCKS;
42291 + mmc->max_seg_size = 1024 * 1024;
42292 + mmc->max_req_size = 1024 * 1024;
42293 + mmc->max_blk_count = 1024;
42295 + mmc->max_blk_size = 2048;
42297 + ubicom32sd_reset(ud);
42300 + * enable interrupts
42303 + ubicom32sd_send_command_sync(ud, SDTIO_COMMAND_SETUP_SDIO << SDTIO_COMMAND_SHIFT | SDTIO_COMMAND_FLAG_SDIO_INT_EN, 0);
42305 + mmc_add_host(mmc);
42307 + printk(KERN_INFO "%s at %p, irq %d/%d\n", mmc_hostname(mmc),
42308 + ud->regs, ud->irq_tx, ud->irq_rx);
42312 + gpio_free(pdata->cards[0].pin_pwr);
42314 + gpio_free(pdata->cards[0].pin_cd);
42316 + gpio_free(pdata->cards[0].pin_wp);
42322 + * ubicom32sd_remove
42324 +static int __devexit ubicom32sd_remove(struct platform_device *pdev)
42326 + struct mmc_host *mmc = platform_get_drvdata(pdev);
42328 + platform_set_drvdata(pdev, NULL);
42331 + struct ubicom32sd_data *ud = (struct ubicom32sd_data *)mmc_priv(mmc);
42333 + gpio_free(ud->pdata->cards[0].pin_pwr);
42334 + gpio_free(ud->pdata->cards[0].pin_cd);
42335 + gpio_free(ud->pdata->cards[0].pin_wp);
42337 + mmc_remove_host(mmc);
42338 + mmc_free_host(mmc);
42342 + * Note that our data is allocated as part of the mmc structure
42343 + * so we don't need to free it.
42348 +static struct platform_driver ubicom32sd_driver = {
42350 + .name = DRIVER_NAME,
42351 + .owner = THIS_MODULE,
42353 + .probe = ubicom32sd_probe,
42354 + .remove = __devexit_p(ubicom32sd_remove),
42356 + .suspend = ubicom32sd_suspend,
42357 + .resume = ubicom32sd_resume,
42362 + * ubicom32sd_init
42364 +static int __init ubicom32sd_init(void)
42366 + return platform_driver_register(&ubicom32sd_driver);
42368 +module_init(ubicom32sd_init);
42371 + * ubicom32sd_exit
42373 +static void __exit ubicom32sd_exit(void)
42375 + platform_driver_unregister(&ubicom32sd_driver);
42377 +module_exit(ubicom32sd_exit);
42379 +MODULE_AUTHOR("Patrick Tjin");
42380 +MODULE_DESCRIPTION("Ubicom32 Secure Digital Host Controller Interface driver");
42381 +MODULE_LICENSE("GPL");
42382 --- a/drivers/mtd/devices/Kconfig
42383 +++ b/drivers/mtd/devices/Kconfig
42384 @@ -104,6 +104,31 @@ config M25PXX_USE_FAST_READ
42386 This option enables FAST_READ access supported by ST M25Pxx.
42388 +config MTD_UBI32_NAND_SPI_ER
42389 + tristate "UBI32_NAND SPI-ER support"
42391 + This driver supports the Micron MT29F1G01 SPI-ER NAND flash chip
42392 + using the built in flash controller on the Ubicom32 architecture.
42393 + Partial page writes are not supported by this driver.
42395 +config MTD_NAND_SPI_ER
42396 + tristate "NAND SPI-ER support"
42398 + This driver supports the Micron MT29F1G01 SPI-ER NAND flash chip
42399 + using a generic SPI bus. Partial page writes are supported
42402 +config MTD_UBI32_M25P80
42403 + tristate "Ubicom processor support for most SPI Flash chips (AT26DF, M25P, W25X, ...)"
42404 + depends on UBICOM32
42407 + This enables access to most modern SPI flash chips, used for
42408 + program and data storage. Series supported include Atmel AT26DF,
42409 + Spansion S25SL, SST 25VF, ST M25P, and Winbond W25X. Other chips
42410 + are supported as well. See the driver source for the current list,
42411 + or to add other chips.
42414 tristate "Uncached system RAM"
42416 --- a/drivers/mtd/devices/Makefile
42417 +++ b/drivers/mtd/devices/Makefile
42418 @@ -16,3 +16,6 @@ obj-$(CONFIG_MTD_LART) += lart.o
42419 obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o
42420 obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o
42421 obj-$(CONFIG_MTD_M25P80) += m25p80.o
42422 +obj-$(CONFIG_MTD_UBI32_M25P80) += ubi32-m25p80.o
42423 +obj-$(CONFIG_MTD_NAND_SPI_ER) += nand-spi-er.o
42424 +obj-$(CONFIG_MTD_UBI32_NAND_SPI_ER) += ubi32-nand-spi-er.o
42426 +++ b/drivers/mtd/devices/nand-spi-er.c
42429 + * Micron SPI-ER NAND Flash Memory
42431 + * (C) Copyright 2009, Ubicom, Inc.
42433 + * This file is part of the Ubicom32 Linux Kernel Port.
42435 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
42436 + * it and/or modify it under the terms of the GNU General Public License
42437 + * as published by the Free Software Foundation, either version 2 of the
42438 + * License, or (at your option) any later version.
42440 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
42441 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
42442 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
42443 + * the GNU General Public License for more details.
42445 + * You should have received a copy of the GNU General Public License
42446 + * along with the Ubicom32 Linux Kernel Port. If not,
42447 + * see <http://www.gnu.org/licenses/>.
42449 +#include <linux/module.h>
42450 +#include <linux/init.h>
42451 +#include <linux/slab.h>
42452 +#include <linux/delay.h>
42453 +#include <linux/device.h>
42454 +#include <linux/mutex.h>
42455 +#include <linux/err.h>
42457 +#include <linux/spi/spi.h>
42458 +#include <linux/spi/flash.h>
42460 +#include <linux/mtd/mtd.h>
42461 +#include <linux/mtd/partitions.h>
42463 +#define NAND_SPI_ER_BLOCK_FROM_ROW(row) (row >> 6)
42465 +#define NAND_SPI_ER_STATUS_P_FAIL (1 << 3)
42466 +#define NAND_SPI_ER_STATUS_E_FAIL (1 << 2)
42467 +#define NAND_SPI_ER_STATUS_OIP (1 << 0)
42469 +#define NAND_SPI_ER_LAST_ROW_INVALID 0xFFFFFFFF
42470 +#define NAND_SPI_ER_BAD_BLOCK_MARK_OFFSET 0x08
42472 +struct nand_spi_er_device {
42473 + const char *name;
42478 + unsigned int blocks;
42479 + unsigned int pages_per_block;
42480 + unsigned int page_size;
42481 + unsigned int write_size;
42482 + unsigned int erase_size;
42485 +struct nand_spi_er {
42488 + const struct nand_spi_er_device *device;
42490 + struct mutex lock;
42491 + struct spi_device *spi;
42493 + struct mtd_info mtd;
42495 + unsigned int last_row; /* the last row we fetched */
42498 + * Bad block table (MUST be last in strcuture)
42500 + unsigned long nbb;
42501 + unsigned long bbt[0];
42504 +const struct nand_spi_er_device nand_spi_er_devices[] = {
42506 + name: "MT29F1G01ZDC",
42510 + pages_per_block: 64,
42513 + erase_size: 64 * 2048,
42516 + name: "MT29F1G01ZDC",
42520 + pages_per_block: 64,
42523 + erase_size: 64 * 2048,
42527 +static int read_only = 0;
42528 +module_param(read_only, int, 0);
42529 +MODULE_PARM_DESC(read_only, "Leave device locked");
42532 + * nand_spi_er_get_feature
42533 + * Get Feature register
42535 +static int nand_spi_er_get_feature(struct nand_spi_er *chip, int reg, uint8_t *data)
42537 + uint8_t txbuf[2];
42538 + uint8_t rxbuf[1];
42543 + res = spi_write_then_read(chip->spi, txbuf, 2, rxbuf, 1);
42545 + DEBUG(MTD_DEBUG_LEVEL1, "%s: failed get feature res=%d\n", chip->name, res);
42548 + *data = rxbuf[0];
42553 + * nand_spi_er_busywait
42554 + * Wait until the chip is not busy
42556 +static int nand_spi_er_busywait(struct nand_spi_er *chip, uint8_t *data)
42560 + for (i = 0; i < 100; i++) {
42561 + int res = nand_spi_er_get_feature(chip, 0xC0, data);
42565 + if (!(*data & NAND_SPI_ER_STATUS_OIP)) {
42574 + * nand_spi_er_erase
42575 + * Erase a block, parameters must be block aligned
42577 +static int nand_spi_er_erase(struct mtd_info *mtd, struct erase_info *instr)
42579 + struct nand_spi_er *chip = mtd->priv;
42580 + struct spi_device *spi = chip->spi;
42581 + uint8_t txbuf[4];
42584 + DEBUG(MTD_DEBUG_LEVEL3, "%s: erase addr:%x len:%x\n", chip->name, instr->addr, instr->len);
42586 + if ((instr->addr + instr->len) > mtd->size) {
42590 + if (instr->addr & (chip->device->erase_size - 1)) {
42591 + DEBUG(MTD_DEBUG_LEVEL1, "%s: erase address is not aligned %x\n", chip->name, instr->addr);
42595 + if (instr->len & (chip->device->erase_size - 1)) {
42596 + DEBUG(MTD_DEBUG_LEVEL1, "%s: erase len is not aligned %x\n", chip->name, instr->len);
42600 + mutex_lock(&chip->lock);
42601 + chip->last_row = NAND_SPI_ER_LAST_ROW_INVALID;
42603 + while (instr->len) {
42604 + uint32_t block = instr->addr >> 17;
42605 + uint32_t row = block << 6;
42607 + DEBUG(MTD_DEBUG_LEVEL3, "%s: block erase row:%x block:%x addr:%x rem:%x\n", chip->name, row, block, instr->addr, instr->len);
42613 + res = spi_write(spi, txbuf, 1);
42615 + DEBUG(MTD_DEBUG_LEVEL1, "%s: failed write enable res=%d\n", chip->name, res);
42616 + mutex_unlock(&chip->lock);
42621 + * Test for bad block
42623 + if (test_bit(block, chip->bbt)) {
42624 + instr->fail_addr = block << 17;
42625 + instr->state = MTD_ERASE_FAILED;
42635 + txbuf[2] = row >> 8;
42636 + txbuf[3] = row & 0xFF;
42637 + res = spi_write(spi, txbuf, 4);
42639 + DEBUG(MTD_DEBUG_LEVEL1, "%s: failed block erase res=%d\n", chip->name, res);
42640 + instr->fail_addr = block << 17;
42641 + instr->state = MTD_ERASE_FAILED;
42648 + res = nand_spi_er_busywait(chip, &stat);
42649 + if (res || (stat & NAND_SPI_ER_STATUS_OIP)) {
42650 + instr->fail_addr = block << 17;
42651 + instr->state = MTD_ERASE_FAILED;
42652 + DEBUG(MTD_DEBUG_LEVEL1, "%s: chip is busy or nonresponsive res=%d stat=%02x\n", chip->name, res, stat);
42665 + * Check the status register
42667 + if (stat & NAND_SPI_ER_STATUS_E_FAIL) {
42668 + DEBUG(MTD_DEBUG_LEVEL1, "%s: E_FAIL signalled (%02x)\n", chip->name, stat);
42669 + instr->fail_addr = block << 17;
42670 + instr->state = MTD_ERASE_FAILED;
42678 + instr->len -= chip->device->erase_size;
42679 + instr->addr += chip->device->erase_size;
42682 + instr->state = MTD_ERASE_DONE;
42684 + mutex_unlock(&chip->lock);
42692 + res = spi_write(spi, txbuf, 1);
42694 + DEBUG(MTD_DEBUG_LEVEL1, "%s: failed write disable res=%d\n", chip->name, res);
42697 + mutex_unlock(&chip->lock);
42699 + mtd_erase_callback(instr);
42704 + * nand_spi_er_read
42706 + * return -EUCLEAN: ecc error recovered
42707 + * return -EBADMSG: ecc error not recovered
42709 +static int nand_spi_er_read(struct mtd_info *mtd, loff_t from, size_t len,
42710 + size_t *retlen, u_char *buf)
42712 + struct nand_spi_er *chip = mtd->priv;
42713 + struct spi_device *spi = chip->spi;
42720 + DEBUG(MTD_DEBUG_LEVEL2, "%s: read block from %llx len %d into %p\n", chip->name, from, len, buf);
42723 + * Zero length reads, nothing to do
42730 + * Reject reads which go over the end of the flash
42732 + if ((from + len) > mtd->size) {
42737 + * Get the row and column address to start at
42739 + row = from >> 11;
42740 + column = from & 0x7FF;
42741 + DEBUG(MTD_DEBUG_LEVEL3, "%s: row=%x %d column=%x %d last_row=%x %d\n", chip->name, row, row, column, column, chip->last_row, chip->last_row);
42744 + * Read the data from the chip
42746 + mutex_lock(&chip->lock);
42749 + uint8_t txbuf[4];
42750 + struct spi_message message;
42751 + struct spi_transfer x[2];
42756 + * Figure out how much to read
42758 + * If we are reading from the middle of a page then the most we
42759 + * can read is to the end of the page
42762 + if (toread > (chip->device->page_size - column)) {
42763 + toread = chip->device->page_size - column;
42766 + DEBUG(MTD_DEBUG_LEVEL3, "%s: buf=%p toread=%x row=%x column=%x last_row=%x\n", chip->name, buf, toread, row, column, chip->last_row);
42768 + if (chip->last_row != row) {
42770 + * Check if the block is bad
42772 + if (test_bit(NAND_SPI_ER_BLOCK_FROM_ROW(row), chip->bbt)) {
42773 + mutex_unlock(&chip->lock);
42778 + * Load the appropriate page
42782 + txbuf[2] = row >> 8;
42783 + txbuf[3] = row & 0xFF;
42784 + res = spi_write(spi, txbuf, 4);
42786 + DEBUG(MTD_DEBUG_LEVEL1, "%s: failed page load res=%d\n", chip->name, res);
42787 + mutex_unlock(&chip->lock);
42794 + res = nand_spi_er_busywait(chip, &stat);
42795 + if (res || (stat & NAND_SPI_ER_STATUS_OIP)) {
42796 + DEBUG(MTD_DEBUG_LEVEL1, "%s: chip is busy or nonresponsive res=%d stat=%02x\n", chip->name, res, stat);
42798 + mutex_unlock(&chip->lock);
42805 + mutex_unlock(&chip->lock);
42810 + * Check the ECC bits
42814 + DEBUG(MTD_DEBUG_LEVEL1, "%s: ECC recovered, row=%x\n", chip->name, row);
42815 + retval = -EUCLEAN;
42818 + DEBUG(MTD_DEBUG_LEVEL0, "%s: failed ECC, row=%x\n", chip->name, row);
42819 + chip->last_row = NAND_SPI_ER_LAST_ROW_INVALID;
42820 + mutex_unlock(&chip->lock);
42826 + chip->last_row = row;
42829 + * Read out the data
42831 + spi_message_init(&message);
42832 + memset(x, 0, sizeof(x));
42835 + txbuf[1] = column >> 8;
42836 + txbuf[2] = column & 0xFF;
42838 + x[0].tx_buf = txbuf;
42840 + spi_message_add_tail(&x[0], &message);
42842 + x[1].rx_buf = buf;
42843 + x[1].len = toread;
42844 + spi_message_add_tail(&x[1], &message);
42846 + res = spi_sync(spi, &message);
42848 + DEBUG(MTD_DEBUG_LEVEL1, "%s: failed data read res=%d\n", chip->name, res);
42849 + mutex_unlock(&chip->lock);
42854 + *retlen += toread;
42857 + * For the next page, increment the row and always start at column 0
42863 + mutex_unlock(&chip->lock);
42868 + * nand_spi_er_write
42870 +#define NOT_ALIGNED(x) ((x & (device->write_size - 1)) != 0)
42871 +static int nand_spi_er_write(struct mtd_info *mtd, loff_t to, size_t len,
42872 + size_t *retlen, const u_char *buf)
42874 + struct nand_spi_er *chip = mtd->priv;
42875 + struct spi_device *spi = chip->spi;
42876 + const struct nand_spi_er_device *device = chip->device;
42879 + uint8_t txbuf[4];
42883 + DEBUG(MTD_DEBUG_LEVEL2, "%s: write block to %llx len %d from %p\n", chip->name, to, len, buf);
42888 + * nothing to write
42895 + * Reject writes which go over the end of the flash
42897 + if ((to + len) > mtd->size) {
42902 + * Check to see if everything is page aligned
42904 + if (NOT_ALIGNED(to) || NOT_ALIGNED(len)) {
42905 + printk(KERN_NOTICE "nand_spi_er_write: Attempt to write non page aligned data\n");
42909 + mutex_lock(&chip->lock);
42910 + chip->last_row = NAND_SPI_ER_LAST_ROW_INVALID;
42913 + * If the first write is a partial write then write at most the number of
42914 + * bytes to get us page aligned and then the remainder will be
42915 + * page aligned. The last bit may be a partial page as well.
42917 + col = to & (device->page_size - 1);
42918 + towrite = device->page_size - col;
42919 + if (towrite > len) {
42928 + struct spi_message message;
42929 + struct spi_transfer x[2];
42932 + DEBUG(MTD_DEBUG_LEVEL3, "%s: write %p to row:%x col:%x len:%x rem:%x\n", chip->name, buf, row, col, towrite, len);
42938 + res = spi_write(spi, txbuf, 1);
42940 + DEBUG(MTD_DEBUG_LEVEL1, "%s: failed write enable res=%d\n", chip->name, res);
42941 + mutex_unlock(&chip->lock);
42946 + * Write the data into the cache
42948 + spi_message_init(&message);
42949 + memset(x, 0, sizeof(x));
42951 + txbuf[1] = col >> 8;
42952 + txbuf[2] = col & 0xFF;
42953 + x[0].tx_buf = txbuf;
42955 + spi_message_add_tail(&x[0], &message);
42956 + x[1].tx_buf = buf;
42957 + x[1].len = towrite;
42958 + spi_message_add_tail(&x[1], &message);
42959 + res = spi_sync(spi, &message);
42961 + DEBUG(MTD_DEBUG_LEVEL1, "%s: failed cache write res=%d\n", chip->name, res);
42966 + * Program execute
42970 + txbuf[2] = row >> 8;
42971 + txbuf[3] = row & 0xFF;
42972 + res = spi_write(spi, txbuf, 4);
42974 + DEBUG(MTD_DEBUG_LEVEL1, "%s: failed prog execute res=%d\n", chip->name, res);
42981 + res = nand_spi_er_busywait(chip, &stat);
42982 + if (res || (stat & NAND_SPI_ER_STATUS_OIP)) {
42983 + DEBUG(MTD_DEBUG_LEVEL1, "%s: chip is busy or nonresponsive res=%d stat=%02x\n", chip->name, res, stat);
42995 + if (stat & (1 << 3)) {
43003 + *retlen += towrite;
43006 + * At this point, we are always page aligned so start at column 0.
43007 + * Note we may not have a full page to write at the end, hence the
43008 + * check if towrite > len.
43011 + towrite = device->page_size;
43012 + if (towrite > len) {
43017 + mutex_unlock(&chip->lock);
43025 + res = spi_write(spi, txbuf, 1);
43027 + DEBUG(MTD_DEBUG_LEVEL1, "%s: failed write disable res=%d\n", chip->name, res);
43030 + mutex_unlock(&chip->lock);
43036 + * nand_spi_er_isbad
43038 +static int nand_spi_er_isbad(struct mtd_info *mtd, loff_t ofs)
43040 + struct nand_spi_er *chip = mtd->priv;
43043 + if (ofs & (chip->device->erase_size - 1)) {
43044 + DEBUG(MTD_DEBUG_LEVEL1, "%s: address not aligned %llx\n", chip->name, ofs);
43048 + block = ofs >> 17;
43050 + return test_bit(block, chip->bbt);
43054 + * nand_spi_er_markbad
43056 +static int nand_spi_er_markbad(struct mtd_info *mtd, loff_t ofs)
43058 + struct nand_spi_er *chip = mtd->priv;
43059 + struct spi_device *spi = chip->spi;
43062 + uint8_t txbuf[7];
43066 + if (ofs & (chip->device->erase_size - 1)) {
43067 + DEBUG(MTD_DEBUG_LEVEL1, "%s: address not aligned %llx\n", chip->name, ofs);
43071 + block = ofs >> 17;
43074 + * If it's already marked bad, no need to mark it
43076 + if (test_bit(block, chip->bbt)) {
43081 + * Mark it in our cache
43083 + __set_bit(block, chip->bbt);
43086 + * Write the user bad block mark. If it fails, then we really
43087 + * can't do anything about it.
43089 + mutex_lock(&chip->lock);
43090 + chip->last_row = NAND_SPI_ER_LAST_ROW_INVALID;
43096 + res = spi_write(spi, txbuf, 1);
43098 + DEBUG(MTD_DEBUG_LEVEL1, "%s: failed write enable res=%d\n", chip->name, res);
43099 + mutex_unlock(&chip->lock);
43108 + txbuf[2] = NAND_SPI_ER_BAD_BLOCK_MARK_OFFSET;
43113 + res = spi_write(spi, txbuf, 7);
43115 + DEBUG(MTD_DEBUG_LEVEL1, "%s: failed write mark res=%d\n", chip->name, res);
43120 + * Program execute
43125 + txbuf[2] = row >> 8;
43126 + txbuf[3] = row & 0xFF;
43127 + res = spi_write(spi, txbuf, 4);
43129 + DEBUG(MTD_DEBUG_LEVEL1, "%s: failed program execute res=%d\n", chip->name, res);
43136 + res = nand_spi_er_busywait(chip, &stat);
43137 + if (res || (stat & NAND_SPI_ER_STATUS_OIP)) {
43138 + DEBUG(MTD_DEBUG_LEVEL1, "%s: chip is busy or nonresponsive res=%d stat=%02x\n", chip->name, res, stat);
43150 + if (stat & (1 << 3)) {
43159 + res = spi_write(spi, txbuf, 1);
43161 + DEBUG(MTD_DEBUG_LEVEL1, "%s: failed write disable res=%d\n", chip->name, res);
43164 + mutex_unlock(&chip->lock);
43170 + * nand_spi_er_read_bbt
43172 +static int nand_spi_er_read_bbt(struct nand_spi_er *chip)
43175 + for (j = 0; j < chip->device->blocks; j++) {
43176 + uint8_t txbuf[4];
43177 + uint8_t rxbuf[16];
43180 + unsigned short row = j << 6;
43188 + txbuf[2] = row >> 8;
43189 + txbuf[3] = row & 0xFF;
43190 + res = spi_write(chip->spi, txbuf, 4);
43198 + res = nand_spi_er_busywait(chip, &stat);
43199 + if (res || (stat & NAND_SPI_ER_STATUS_OIP)) {
43200 + DEBUG(MTD_DEBUG_LEVEL1, "%s: chip is busy or nonresponsive res=%d stat=%02x\n", chip->name, res, stat);
43212 + * Check factory bad block mark
43218 + res = spi_write_then_read(chip->spi, txbuf, 4, rxbuf, 16);
43222 + if (rxbuf[0] != 0xFF) {
43224 + __set_bit(j, chip->bbt);
43228 + memcpy(&bbmark, &rxbuf[8], 4);
43229 + if (bbmark == 0xdeadbeef) {
43231 + __set_bit(j, chip->bbt);
43235 +#if defined(CONFIG_MTD_DEBUG) && (MTD_DEBUG_LEVEL3 <= CONFIG_MTD_DEBUG_VERBOSE)
43236 + printk("%s: Bad Block Table:", chip->name);
43237 + for (j = 0; j < chip->device->blocks; j++) {
43238 + if ((j % 64) == 0) {
43239 + printk("\n%s: block %03x: ", chip->name, j);
43241 + printk("%c", test_bit(j, chip->bbt) ? 'X' : '.');
43243 + printk("\n%s: Bad Block Numbers: ", chip->name);
43244 + for (j = 0; j < chip->device->blocks; j++) {
43245 + if (test_bit(j, chip->bbt)) {
43246 + printk("%x ", j);
43257 + * Called at boot time:
43259 + * nand_spi_er=read_only
43260 + * if read_only specified then do not unlock device
43262 +static int __init nand_spi_er_setup(char *str)
43264 + if (str && (strncasecmp(str, "read_only", 9) == 0)) {
43270 +__setup("nand_spi_er=", nand_spi_er_setup);
43274 + * nand_spi_er_probe
43275 + * Detect and initialize nand_spi_er device.
43277 +static int __devinit nand_spi_er_probe(struct spi_device *spi)
43279 + uint8_t txbuf[3];
43280 + uint8_t rxbuf[2];
43283 + size_t bbt_bytes;
43284 + struct nand_spi_er *chip;
43285 + const struct nand_spi_er_device *device;
43287 + res = spi_setup(spi);
43295 + for (i = 0; i < 2; i++) {
43297 + res = spi_write(spi, txbuf, 1);
43310 + res = spi_write_then_read(spi, txbuf, 2, rxbuf, 2);
43315 + device = nand_spi_er_devices;
43316 + for (i = 0; i < ARRAY_SIZE(nand_spi_er_devices); i++) {
43317 + if ((device->id0 == rxbuf[0]) && (device->id1 == rxbuf[1])) {
43322 + if (i == ARRAY_SIZE(nand_spi_er_devices)) {
43327 + * Initialize our chip structure
43329 + bbt_bytes = DIV_ROUND_UP(device->blocks, BITS_PER_BYTE);
43330 + chip = kzalloc(sizeof(struct nand_spi_er) + bbt_bytes, GFP_KERNEL);
43334 + snprintf(chip->name, sizeof(chip->name), "%s.%d.%d", device->name, spi->master->bus_num, spi->chip_select);
43337 + chip->device = device;
43338 + chip->last_row = NAND_SPI_ER_LAST_ROW_INVALID;
43340 + mutex_init(&chip->lock);
43342 + chip->mtd.type = MTD_NANDFLASH;
43343 + chip->mtd.flags = MTD_WRITEABLE;
43346 + * #blocks * block size * n blocks
43348 + chip->mtd.size = device->blocks * device->pages_per_block * device->page_size;
43349 + chip->mtd.erasesize = device->erase_size;
43352 + * 1 page, optionally we can support partial write (512)
43354 + chip->mtd.writesize = device->write_size;
43355 + chip->mtd.name = device->name;
43356 + chip->mtd.erase = nand_spi_er_erase;
43357 + chip->mtd.read = nand_spi_er_read;
43358 + chip->mtd.write = nand_spi_er_write;
43359 + chip->mtd.block_isbad = nand_spi_er_isbad;
43360 + chip->mtd.block_markbad = nand_spi_er_markbad;
43361 + chip->mtd.priv = chip;
43364 + * Cache the bad block table
43366 + res = nand_spi_er_read_bbt(chip);
43373 + * Un/lock the chip
43382 + res = spi_write(spi, txbuf, 3);
43384 + DEBUG(MTD_DEBUG_LEVEL1, "%s: failed lock operation res=%d\n", chip->name, res);
43385 + mutex_unlock(&chip->lock);
43389 + spi_set_drvdata(spi, chip);
43391 + printk(KERN_INFO "%s: added device %s size: %u KBytes %u bad blocks %s\n", spi->dev.bus_id, chip->mtd.name, DIV_ROUND_UP(chip->mtd.size, 1024), chip->nbb, read_only ? "[read only]" : "");
43392 + return add_mtd_device(&chip->mtd);
43396 + * nand_spi_er_remove
43398 +static int __devexit nand_spi_er_remove(struct spi_device *spi)
43400 + struct nand_spi_er *chip = spi_get_drvdata(spi);
43403 + DEBUG(MTD_DEBUG_LEVEL1, "%s: remove\n", spi->dev.bus_id);
43404 + status = del_mtd_device(&chip->mtd);
43410 +static struct spi_driver nand_spi_er_driver = {
43412 + .name = "nand-spi-er",
43413 + .bus = &spi_bus_type,
43414 + .owner = THIS_MODULE,
43417 + .probe = nand_spi_er_probe,
43418 + .remove = __devexit_p(nand_spi_er_remove),
43420 + /* FIXME: investigate suspend and resume... */
43424 + * nand_spi_er_init
43426 +static int __init nand_spi_er_init(void)
43428 + return spi_register_driver(&nand_spi_er_driver);
43430 +module_init(nand_spi_er_init);
43433 + * nand_spi_er_exit
43435 +static void __exit nand_spi_er_exit(void)
43437 + spi_unregister_driver(&nand_spi_er_driver);
43439 +module_exit(nand_spi_er_exit);
43442 +MODULE_LICENSE("GPL");
43443 +MODULE_AUTHOR("Patrick Tjin");
43444 +MODULE_DESCRIPTION("MTD nand_spi_er driver");
43446 +++ b/drivers/mtd/devices/ubi32-m25p80.c
43449 + * drivers/mtd/devices/ubi32-m25p80.c
43450 + * NOR flash driver, Ubicom processor internal SPI flash interface.
43452 + * This code instantiates the serial flash that contains the
43453 + * original bootcode. The serial flash start at address 0x60000000
43454 + * in both Ubicom32V3 and Ubicom32V4 ISAs.
43456 + * This piece of flash is made to appear as a Memory Technology
43457 + * Device (MTD) with this driver to allow Read/Write/Erase operations.
43459 + * (C) Copyright 2009, Ubicom, Inc.
43461 + * This file is part of the Ubicom32 Linux Kernel Port.
43463 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
43464 + * it and/or modify it under the terms of the GNU General Public License
43465 + * as published by the Free Software Foundation, either version 2 of the
43466 + * License, or (at your option) any later version.
43468 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
43469 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
43470 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
43471 + * the GNU General Public License for more details.
43473 + * You should have received a copy of the GNU General Public License
43474 + * along with the Ubicom32 Linux Kernel Port. If not,
43475 + * see <http://www.gnu.org/licenses/>.
43477 + * Ubicom32 implementation derived from (with many thanks):
43482 +#include <linux/types.h>
43483 +#include <linux/device.h>
43484 +#include <linux/platform_device.h>
43485 +#include <linux/mtd/mtd.h>
43486 +#include <linux/mtd/partitions.h>
43487 +#include <linux/mtd/physmap.h>
43488 +#include <linux/spi/spi.h>
43489 +#include <linux/spi/flash.h>
43491 +#include <linux/init.h>
43492 +#include <linux/module.h>
43493 +#include <linux/interrupt.h>
43494 +#include <linux/mutex.h>
43496 +#include <asm/ip5000.h>
43497 +#include <asm/devtree.h>
43499 +#define UBICOM32_FLASH_BASE 0x60000000
43500 +#define UBICOM32_FLASH_MAX_SIZE 0x01000000
43501 +#define UBICOM32_FLASH_START 0x00000000
43502 +#define UBICOM32_KERNEL_OFFSET 0x00010000 /* The kernel starts after Ubicom
43503 + * .protect section. */
43505 +static struct mtd_partition ubicom32_flash_partitions[] = {
43507 + .name = "Bootloader", /* Protected Section
43510 + .offset = UBICOM32_FLASH_START,
43511 +// .mask_flags = MTD_WRITEABLE /* Mark Read-only */
43514 + .name = "Kernel", /* Kernel Partition. */
43515 + .size = 0, /* this will be set up during
43516 + * probe stage. At that time we
43517 + * will know end of linux image
43519 + .offset = MTDPART_OFS_APPEND, /* Starts right after Protected
43521 +// .mask_flags = MTD_WRITEABLE /* Mark Read-only */
43524 + .name = "Rest", /* Rest of the flash. */
43525 + .size = 0x200000, /* Use up what remains in the
43527 + .offset = MTDPART_OFS_NXTBLK, /* Starts right after Protected
43532 +static struct flash_platform_data ubicom32_flash_data = {
43533 + .name = "ubicom32_boot_flash",
43534 + .parts = ubicom32_flash_partitions,
43535 + .nr_parts = ARRAY_SIZE(ubicom32_flash_partitions),
43538 +static struct resource ubicom32_flash_resource[] = {
43540 + .start = UBICOM32_FLASH_BASE,
43541 + .end = UBICOM32_FLASH_BASE +
43542 + UBICOM32_FLASH_MAX_SIZE - 1,
43543 + .flags = IORESOURCE_MEM,
43547 +static struct platform_device ubicom32_flash_device = {
43548 + .name = "ubicom32flashdriver",
43549 + .id = 0, /* Bus number */
43550 + .num_resources = ARRAY_SIZE(ubicom32_flash_resource),
43551 + .resource = ubicom32_flash_resource,
43553 + .platform_data = &ubicom32_flash_data,
43557 +static struct platform_device *ubicom32_flash_devices[] = {
43558 + &ubicom32_flash_device,
43561 +static int __init ubicom32_flash_init(void)
43563 + printk(KERN_INFO "%s(): registering device resources\n",
43565 + platform_add_devices(ubicom32_flash_devices,
43566 + ARRAY_SIZE(ubicom32_flash_devices));
43570 +arch_initcall(ubicom32_flash_init);
43573 + * MTD SPI driver for ST M25Pxx (and similar) serial flash chips through
43574 + * Ubicom32 SPI controller.
43576 + * Author: Mike Lavender, mike@steroidmicros.com
43578 + * Copyright (c) 2005, Intec Automation Inc.
43580 + * Some parts are based on lart.c by Abraham Van Der Merwe
43582 + * Cleaned up and generalized based on mtd_dataflash.c
43584 + * This code is free software; you can redistribute it and/or modify
43585 + * it under the terms of the GNU General Public License version 2 as
43586 + * published by the Free Software Foundation.
43590 +#define FLASH_PAGESIZE 256
43592 +/* Flash opcodes. */
43593 +#define OPCODE_WREN 0x06 /* Write enable */
43594 +#define OPCODE_RDSR 0x05 /* Read status register */
43595 +#define OPCODE_READ 0x03 /* Read data bytes (low frequency) */
43596 +#define OPCODE_FAST_READ 0x0b /* Read data bytes (high frequency) */
43597 +#define OPCODE_PP 0x02 /* Page program (up to 256 bytes) */
43598 +#define OPCODE_BE_4K 0x20 /* Erase 4KiB block */
43599 +#define OPCODE_BE_32K 0x52 /* Erase 32KiB block */
43600 +#define OPCODE_SE 0xd8 /* Sector erase (usually 64KiB) */
43601 +#define OPCODE_RDID 0x9f /* Read JEDEC ID */
43603 +/* Status Register bits. */
43604 +#define SR_WIP 1 /* Write in progress */
43605 +#define SR_WEL 2 /* Write enable latch */
43606 +/* meaning of other SR_* bits may differ between vendors */
43607 +#define SR_BP0 4 /* Block protect 0 */
43608 +#define SR_BP1 8 /* Block protect 1 */
43609 +#define SR_BP2 0x10 /* Block protect 2 */
43610 +#define SR_SRWD 0x80 /* SR write protect */
43612 +/* Define max times to check status register before we give up. */
43613 +#define MAX_READY_WAIT_COUNT 100000
43616 +#ifdef CONFIG_MTD_PARTITIONS
43617 +#define mtd_has_partitions() (1)
43619 +#define mtd_has_partitions() (0)
43623 + * Ubicom32 FLASH Command Set
43625 +#define FLASH_FC_INST_CMD 0x00 /* for SPI command only transaction */
43626 +#define FLASH_FC_INST_WR 0x01 /* for SPI write transaction */
43627 +#define FLASH_FC_INST_RD 0x02 /* for SPI read transaction */
43629 +#define ALIGN_DOWN(v, a) ((v) & ~((a) - 1))
43630 +#define ALIGN_UP(v, a) (((v) + ((a) - 1)) & ~((a) - 1))
43632 +#define FLASH_COMMAND_KICK_OFF(io) \
43634 + " bset "D(IO_INT_CLR)"(%0), #0, #%%bit("D(IO_XFL_INT_DONE)") \n\t" \
43635 + " jmpt.t .+4 \n\t" \
43636 + " bset "D(IO_INT_SET)"(%0), #0, #%%bit("D(IO_XFL_INT_START)") \n\t" \
43639 + : "memory", "cc" \
43642 +#define FLASH_COMMAND_WAIT_FOR_COMPLETION(io) \
43644 + " btst "D(IO_INT_STATUS)"(%0), #%%bit("D(IO_XFL_INT_DONE)") \n\t" \
43645 + " jmpeq.f .-4 \n\t" \
43648 + : "memory", "cc" \
43651 +#define FLASH_COMMAND_EXEC(io) \
43652 + FLASH_COMMAND_KICK_OFF(io) \
43653 + FLASH_COMMAND_WAIT_FOR_COMPLETION(io)
43656 +#define OSC1_FREQ 12000000
43657 +#define TEN_MICRO_SECONDS (OSC1_FREQ * 10 / 1000000)
43660 + * We will have to eventually replace this null definition with the real thing.
43662 +#define WATCHDOG_RESET()
43664 +#define EXTFLASH_WRITE_FIFO_SIZE 32
43665 +#define EXTFLASH_WRITE_BLOCK_SIZE EXTFLASH_WRITE_FIFO_SIZE /* limit the size to
43666 + * FIFO capacity, so
43667 + * the thread can be
43670 +#define JFFS2_FILESYSTEM_SIZE 0x100000
43672 +/****************************************************************************/
43675 + struct platform_device *plt_dev;
43676 + struct mutex lock;
43677 + struct mtd_info mtd;
43678 + unsigned partitioned:1;
43683 +static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd)
43685 + return container_of(mtd, struct m25p, mtd);
43688 +/****************************************************************************/
43691 + * Internal helper functions
43695 + * Read the status register, returning its value in the location
43696 + * Return the status register value.
43697 + * Returns negative if error occurred.
43699 +static int read_sr(struct m25p *flash)
43701 + struct ubicom32_io_port *io = (struct ubicom32_io_port *)RA;
43703 + io->ctl1 &= ~IO_XFL_CTL1_MASK;
43704 + io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_RD) |
43705 + IO_XFL_CTL1_FC_DATA(1);
43706 + io->ctl2 = IO_XFL_CTL2_FC_CMD(OPCODE_RDSR);
43707 + FLASH_COMMAND_EXEC(io);
43709 + return io->status1 & 0xff;
43713 + * mem_flash_io_read_u32()
43715 +static u32 mem_flash_io_read_u32(u32 addr)
43717 + struct ubicom32_io_port *io = (struct ubicom32_io_port *)RA;
43718 + io->ctl1 &= ~IO_XFL_CTL1_MASK;
43719 + io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_RD) |
43720 + IO_XFL_CTL1_FC_DATA(4) | IO_XFL_CTL1_FC_DUMMY(1) |
43721 + IO_XFL_CTL1_FC_ADDR;
43722 + io->ctl2 = IO_XFL_CTL2_FC_CMD(OPCODE_FAST_READ) |
43723 + IO_XFL_CTL2_FC_ADDR(addr);
43724 + FLASH_COMMAND_EXEC(io);
43725 + return io->status1;
43729 + * mem_flash_read_u8()
43731 +static u8 mem_flash_read_u8(u32 addr)
43733 + u32 tmp_addr = ALIGN_DOWN(addr, 4);
43734 + u32 tmp_data = mem_flash_io_read_u32(tmp_addr);
43735 + u8 *ptr = (u8 *)&tmp_data;
43736 + return ptr[addr & 0x3];
43740 + * mem_flash_read()
43741 + * No need to lock as read is implemented with ireads (same as normal flash
43744 +static void mem_flash_read(u32 addr, void *dst, size_t length)
43750 + * Fix source alignment.
43752 + while (addr & 0x03) {
43753 + if (length == 0) {
43756 + *((u8 *)dst) = mem_flash_read_u8(addr++);
43761 + while (length >= 4) {
43762 + u32 tmp_data = mem_flash_io_read_u32(addr);
43767 + * Send the data to the destination.
43769 + memcpy((void *)dst, (void *)&tmp_data, 4);
43773 + while (length--) {
43774 + *((u8 *)dst) = mem_flash_read_u8(addr++);
43780 + * mem_flash_wait_until_complete()
43782 +static void mem_flash_wait_until_complete(void)
43784 + struct ubicom32_io_port *io = (struct ubicom32_io_port *)RA;
43788 + * Put a delay here to deal with flash programming problem.
43790 + u32 mptval = UBICOM32_IO_TIMER->mptval + TEN_MICRO_SECONDS;
43791 + while (UBICOM32_IO_TIMER->mptval < mptval)
43794 + io->ctl1 &= ~IO_XFL_CTL1_MASK;
43795 + io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_RD) |
43796 + IO_XFL_CTL1_FC_DATA(1);
43797 + io->ctl2 = IO_XFL_CTL2_FC_CMD(OPCODE_RDSR);
43798 + FLASH_COMMAND_EXEC(io);
43799 + } while (io->status1 & SR_WIP);
43803 + * mem_flash_write_next()
43805 +static size_t mem_flash_write_next(u32 addr, u8 *buf, size_t length)
43807 + struct ubicom32_io_port *io = (struct ubicom32_io_port *)RA;
43808 + u32 data_start = addr;
43809 + u32 data_end = addr + length;
43814 + * Top limit address.
43816 + u32 block_start = ALIGN_DOWN(data_start, 4);
43817 + u32 block_end = block_start + EXTFLASH_WRITE_BLOCK_SIZE;
43820 + u8 byte[EXTFLASH_WRITE_BLOCK_SIZE];
43821 + u32 word[EXTFLASH_WRITE_BLOCK_SIZE / 4];
43824 + u32 *flash_addr = (u32 *)block_start;
43827 + * The write block must be limited by FLASH internal buffer.
43829 + u32 block_end_align = ALIGN_DOWN(block_end, 256);
43830 + bool write_needed;
43832 + block_end = (block_end_align > block_start)
43833 + ? block_end_align : block_end;
43834 + data_end = (data_end <= block_end) ? data_end : block_end;
43835 + block_end = ALIGN_UP(data_end, 4);
43836 + count = data_end - data_start;
43839 + * Transfer data to a buffer.
43841 + for (i = 0; i < (block_end - block_start) / 4; i++) {
43843 + * The FLASH read can hold D-cache for a long time.
43844 + * Use I/O operation to read FLASH to avoid starving other
43845 + * threads, especially HRT. (Do this for application only)
43847 + write_buf.word[i] = mem_flash_io_read_u32(
43848 + (u32)(&flash_addr[i]));
43851 + write_needed = false;
43852 + for (i = 0, j = (data_start - block_start);
43853 + i < (data_end - data_start); i++, j++) {
43854 + write_needed = write_needed || (write_buf.byte[j] != buf[i]);
43855 + write_buf.byte[j] &= buf[i];
43860 + * If the data in FLASH is identical to what to be written. Then skip
43863 + if (write_needed) {
43865 + * Write to flash.
43867 + void *tmp __attribute__((unused));
43871 + " move.4 %0, %2 \n\t"
43872 + " bset "D(IO_INT_SET)"(%1), #0, #%%bit("D(IO_PORTX_INT_FIFO_TX_RESET)") \n\t"
43873 + " pipe_flush 0 \n\t"
43874 + " .rept "D(EXTFLASH_WRITE_FIFO_SIZE / 4)" \n\t"
43875 + " move.4 "D(IO_TX_FIFO)"(%1), (%0)4++ \n\t"
43878 + : "a" (io), "r" (&write_buf.word[0])
43882 + /* Lock FLASH for write access. */
43883 + io->ctl0 |= IO_XFL_CTL0_MCB_LOCK;
43885 + /* Command: WREN */
43886 + io->ctl1 &= ~IO_XFL_CTL1_MASK;
43887 + io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_CMD);
43888 + io->ctl2 = IO_XFL_CTL2_FC_CMD(OPCODE_WREN);
43889 + FLASH_COMMAND_EXEC(io);
43891 + /* Command: BYTE PROGRAM */
43892 + io->ctl1 &= ~IO_XFL_CTL1_MASK;
43893 + io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_WR) |
43894 + IO_XFL_CTL1_FC_DATA(block_end - block_start) |
43895 + IO_XFL_CTL1_FC_ADDR;
43896 + io->ctl2 = IO_XFL_CTL2_FC_CMD(OPCODE_PP) |
43897 + IO_XFL_CTL2_FC_ADDR(block_start);
43898 + FLASH_COMMAND_KICK_OFF(io);
43900 + extra_words = (s32)(block_end - block_start -
43901 + EXTFLASH_WRITE_FIFO_SIZE) / 4;
43902 + if (extra_words > 0) {
43904 + " move.4 %0, %3 \n\t"
43905 + "1: cmpi "D(IO_FIFO_LEVEL)"(%1), #4 \n\t"
43906 + " jmpgt.s.t 1b \n\t"
43907 + " move.4 "D(IO_TX_FIFO)"(%1), (%0)4++ \n\t"
43908 + " add.4 %2, #-1, %2 \n\t"
43909 + " jmpgt.t 1b \n\t"
43911 + : "a" (io), "d" (extra_words),
43912 + "r" (&write_buf.word[EXTFLASH_WRITE_FIFO_SIZE / 4])
43916 + FLASH_COMMAND_WAIT_FOR_COMPLETION(io);
43918 + mem_flash_wait_until_complete();
43921 + /* Unlock FLASH for cache access. */
43922 + io->ctl0 &= ~IO_XFL_CTL0_MCB_LOCK;
43932 + * mem_flash_write()
43934 +static void mem_flash_write(u32 addr, const void *src, size_t length)
43939 + u8_t *ptr = (u8_t *)src;
43941 + size_t count = mem_flash_write_next(addr, ptr, length);
43949 + * Service routine to read status register until ready, or timeout occurs.
43950 + * Returns non-zero if error.
43952 +static int wait_till_ready(struct m25p *flash)
43957 + /* one chip guarantees max 5 msec wait here after page writes,
43958 + * but potentially three seconds (!) after page erase.
43960 + for (count = 0; count < MAX_READY_WAIT_COUNT; count++) {
43962 + sr = read_sr(flash);
43965 + else if (!(sr & SR_WIP))
43969 + * Put a 10us delay here to deal with flash programming problem.
43971 + mptval = UBICOM32_IO_TIMER->mptval + TEN_MICRO_SECONDS;
43972 + while ((s32)(mptval - UBICOM32_IO_TIMER->mptval) > 0) {
43973 + WATCHDOG_RESET();
43975 + /* REVISIT sometimes sleeping would be best */
43982 + * mem_flash_erase_page()
43984 +static void mem_flash_erase_page(u32 addr)
43986 + struct ubicom32_io_port *io = (struct ubicom32_io_port *)RA;
43988 + /* Lock FLASH for write access. */
43989 + io->ctl0 |= IO_XFL_CTL0_MCB_LOCK;
43991 + /* Command: WREN */
43992 + io->ctl1 &= ~IO_XFL_CTL1_MASK;
43993 + io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_CMD);
43994 + io->ctl2 = IO_XFL_CTL2_FC_CMD(OPCODE_WREN);
43995 + FLASH_COMMAND_EXEC(io);
43997 + /* Command: ERASE */
43998 + io->ctl1 &= ~IO_XFL_CTL1_MASK;
43999 + io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_CMD) |
44000 + IO_XFL_CTL1_FC_ADDR;
44001 + io->ctl2 = IO_XFL_CTL2_FC_CMD(OPCODE_SE) |
44002 + IO_XFL_CTL2_FC_ADDR(addr);
44003 + FLASH_COMMAND_EXEC(io);
44005 + mem_flash_wait_until_complete();
44007 + /* Unlock FLASH for cache access. */
44008 + io->ctl0 &= ~IO_XFL_CTL0_MCB_LOCK;
44012 + * mem_flash_erase()
44014 +static u32 mem_flash_erase(u32 addr, u32 length)
44017 + * Calculate the endaddress to be the first address of the page
44018 + * just beyond this erase section of pages.
44020 + u32 endaddr = addr + length;
44025 + while (addr < endaddr) {
44026 + u32 test_addr = addr;
44027 + mem_flash_erase_page(addr);
44030 + * Test how much was erased as actual flash page at this address
44031 + * may be smaller than the expected page size.
44033 + while (test_addr < endaddr) {
44035 + * The FLASH read can hold D-cache for a long time. Use
44036 + * I/O operation to read FLASH to avoid starving other
44037 + * threads, especially HRT. (Do this for application
44040 + if (mem_flash_io_read_u32(test_addr) != 0xFFFFFFFF) {
44045 + if (test_addr == addr) {
44046 + printk("erase failed at address 0x%x, skipping",
44051 + addr = test_addr;
44057 +/****************************************************************************/
44060 + * MTD implementation
44064 + * Erase an address range on the flash chip. The address range may extend
44065 + * one or more erase sectors. Return an error is there is a problem erasing.
44067 +static int ubicom32_flash_driver_erase(struct mtd_info *mtd,
44068 + struct erase_info *instr)
44070 + struct m25p *flash = mtd_to_m25p(mtd);
44073 + DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %lld\n",
44074 + dev_name(&flash->plt_dev->dev), __FUNCTION__, "at",
44075 + (u32)instr->addr, instr->len);
44077 + /* sanity checks */
44078 + if (instr->addr + instr->len > flash->mtd.size)
44080 + if ((instr->addr % mtd->erasesize) != 0
44081 + || (instr->len % mtd->erasesize) != 0) {
44085 + addr = instr->addr + UBICOM32_FLASH_BASE;
44086 + len = instr->len;
44088 + mutex_lock(&flash->lock);
44090 + /* REVISIT in some cases we could speed up erasing large regions
44091 + * by using OPCODE_SE instead of OPCODE_BE_4K
44094 + /* now erase those sectors */
44095 + if (mem_flash_erase(addr, len)) {
44096 + instr->state = MTD_ERASE_FAILED;
44097 + mutex_unlock(&flash->lock);
44101 + mutex_unlock(&flash->lock);
44102 + instr->state = MTD_ERASE_DONE;
44103 + mtd_erase_callback(instr);
44108 + * Read an address range from the flash chip. The address range
44109 + * may be any size provided it is within the physical boundaries.
44111 +static int ubicom32_flash_driver_read(struct mtd_info *mtd, loff_t from,
44112 + size_t len, size_t *retlen, u_char *buf)
44114 + struct m25p *flash = mtd_to_m25p(mtd);
44115 + u32 base_addr = UBICOM32_FLASH_BASE + from;
44117 + DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %d\n",
44118 + dev_name(&flash->plt_dev->dev), __FUNCTION__, "from",
44121 + /* sanity checks */
44125 + if (from + len > flash->mtd.size)
44128 + /* Byte count starts at zero. */
44132 + mutex_lock(&flash->lock);
44134 + /* Wait till previous write/erase is done. */
44135 + if (wait_till_ready(flash)) {
44136 + /* REVISIT status return?? */
44137 + mutex_unlock(&flash->lock);
44141 + mem_flash_read(base_addr, (void *)buf, len);
44146 + mutex_unlock(&flash->lock);
44152 + * Write an address range to the flash chip. Data must be written in
44153 + * FLASH_PAGESIZE chunks. The address range may be any size provided
44154 + * it is within the physical boundaries.
44156 +static int ubicom32_flash_driver_write(struct mtd_info *mtd, loff_t to,
44157 + size_t len, size_t *retlen,
44158 + const u_char *buf)
44160 + struct m25p *flash = mtd_to_m25p(mtd);
44161 + u32 base_addr = UBICOM32_FLASH_BASE + to;
44162 + DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %d\n",
44163 + dev_name(&flash->plt_dev->dev), __FUNCTION__, "to",
44169 + /* sanity checks */
44173 + if (to + len > flash->mtd.size)
44176 + mutex_lock(&flash->lock);
44178 + mem_flash_write(base_addr, (void *) buf, len);
44180 + /* Wait until finished previous write command. */
44181 + if (wait_till_ready(flash)) {
44182 + mutex_unlock(&flash->lock);
44189 + mutex_unlock(&flash->lock);
44194 +/****************************************************************************/
44197 + * SPI device driver setup and teardown
44200 +struct flash_info {
44203 + /* JEDEC id zero means "no ID" (most older chips); otherwise it has
44204 + * a high byte of zero plus three data bytes: the manufacturer id,
44205 + * then a two byte device id.
44209 + /* The size listed here is what works with OPCODE_SE, which isn't
44210 + * necessarily called a "sector" by the vendor.
44212 + unsigned sector_size;
44216 +#define SECT_4K 0x01 /* OPCODE_BE_4K works uniformly */
44220 +/* NOTE: double check command sets and memory organization when you add
44221 + * more flash chips. This current list focusses on newer chips, which
44222 + * have been converging on command sets which including JEDEC ID.
44224 +static struct flash_info __devinitdata m25p_data[] = {
44226 + /* Atmel -- some are (confusingly) marketed as "DataFlash" */
44227 + { "at25fs010", 0x1f6601, 32 * 1024, 4, SECT_4K, },
44228 + { "at25fs040", 0x1f6604, 64 * 1024, 8, SECT_4K, },
44230 + { "at25df041a", 0x1f4401, 64 * 1024, 8, SECT_4K, },
44232 + { "at26f004", 0x1f0400, 64 * 1024, 8, SECT_4K, },
44233 + { "at26df081a", 0x1f4501, 64 * 1024, 16, SECT_4K, },
44234 + { "at26df161a", 0x1f4601, 64 * 1024, 32, SECT_4K, },
44235 + { "at26df321", 0x1f4701, 64 * 1024, 64, SECT_4K, },
44237 + /* Spansion -- single (large) sector size only, at least
44238 + * for the chips listed here (without boot sectors).
44240 + { "s25sl004a", 0x010212, 64 * 1024, 8, },
44241 + { "s25sl008a", 0x010213, 64 * 1024, 16, },
44242 + { "s25sl016a", 0x010214, 64 * 1024, 32, },
44243 + { "s25sl032a", 0x010215, 64 * 1024, 64, },
44244 + { "s25sl064a", 0x010216, 64 * 1024, 128, },
44246 + /* SST -- large erase sizes are "overlays", "sectors" are 4K */
44247 + { "sst25vf040b", 0xbf258d, 64 * 1024, 8, SECT_4K, },
44248 + { "sst25vf080b", 0xbf258e, 64 * 1024, 16, SECT_4K, },
44249 + { "sst25vf016b", 0xbf2541, 64 * 1024, 32, SECT_4K, },
44250 + { "sst25vf032b", 0xbf254a, 64 * 1024, 64, SECT_4K, },
44252 + /* ST Microelectronics -- newer production may have feature updates */
44253 + { "m25p05", 0x202010, 32 * 1024, 2, },
44254 + { "m25p10", 0x202011, 32 * 1024, 4, },
44255 + { "m25p20", 0x202012, 64 * 1024, 4, },
44256 + { "m25p40", 0x202013, 64 * 1024, 8, },
44257 + { "m25p80", 0, 64 * 1024, 16, },
44258 + { "m25p16", 0x202015, 64 * 1024, 32, },
44259 + { "m25p32", 0x202016, 64 * 1024, 64, },
44260 + { "m25p64", 0x202017, 64 * 1024, 128, },
44261 + { "m25p128", 0x202018, 256 * 1024, 64, },
44263 + { "m45pe80", 0x204014, 64 * 1024, 16, },
44264 + { "m45pe16", 0x204015, 64 * 1024, 32, },
44266 + { "m25pe80", 0x208014, 64 * 1024, 16, },
44267 + { "m25pe16", 0x208015, 64 * 1024, 32, SECT_4K, },
44269 + /* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */
44270 + { "w25x10", 0xef3011, 64 * 1024, 2, SECT_4K, },
44271 + { "w25x20", 0xef3012, 64 * 1024, 4, SECT_4K, },
44272 + { "w25x40", 0xef3013, 64 * 1024, 8, SECT_4K, },
44273 + { "w25x80", 0xef3014, 64 * 1024, 16, SECT_4K, },
44274 + { "w25x16", 0xef3015, 64 * 1024, 32, SECT_4K, },
44275 + { "w25x32", 0xef3016, 64 * 1024, 64, SECT_4K, },
44276 + { "w25x64", 0xef3017, 64 * 1024, 128, SECT_4K, },
44278 + /* Macronix -- mx25lxxx */
44279 + { "mx25l32", 0xc22016, 64 * 1024, 64, },
44280 + { "mx25l64", 0xc22017, 64 * 1024, 128, },
44281 + { "mx25l128", 0xc22018, 64 * 1024, 256, },
44285 +struct flash_info *__devinit jedec_probe(struct platform_device *spi)
44289 + struct flash_info *info;
44290 + struct ubicom32_io_port *io = (struct ubicom32_io_port *)RA;
44293 + * Setup and run RDID command on the flash.
44295 + io->ctl1 &= ~IO_XFL_CTL1_MASK;
44296 + io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_RD) |
44297 + IO_XFL_CTL1_FC_DATA(3);
44298 + io->ctl2 = IO_XFL_CTL2_FC_CMD(OPCODE_RDID);
44299 + FLASH_COMMAND_EXEC(io);
44301 + jedec = io->status1 & 0x00ffffff;
44303 + for (tmp = 0, info = m25p_data;
44304 + tmp < ARRAY_SIZE(m25p_data);
44306 + if (info->jedec_id == jedec)
44309 + dev_err(&spi->dev, "unrecognized JEDEC id %06x\n", jedec);
44315 + * board specific setup should have ensured the SPI clock used here
44316 + * matches what the READ command supports, at least until this driver
44317 + * understands FAST_READ (for clocks over 25 MHz).
44319 +static int __devinit ubicom32_flash_probe(struct platform_device *spi)
44321 + struct flash_platform_data *data;
44322 + struct m25p *flash;
44323 + struct flash_info *info;
44326 + /* Platform data helps sort out which chip type we have, as
44327 + * well as how this board partitions it. If we don't have
44328 + * a chip ID, try the JEDEC id commands; they'll work for most
44329 + * newer chips, even if we don't recognize the particular chip.
44331 + data = spi->dev.platform_data;
44332 + if (data && data->type) {
44333 + for (i = 0, info = m25p_data;
44334 + i < ARRAY_SIZE(m25p_data);
44336 + if (strcmp(data->type, info->name) == 0)
44340 + /* unrecognized chip? */
44341 + if (i == ARRAY_SIZE(m25p_data)) {
44342 + DEBUG(MTD_DEBUG_LEVEL0, "%s: unrecognized id %s\n",
44343 + dev_name(&spi->dev), data->type);
44346 + /* recognized; is that chip really what's there? */
44347 + } else if (info->jedec_id) {
44348 + struct flash_info *chip = jedec_probe(spi);
44350 + if (!chip || chip != info) {
44351 + dev_warn(&spi->dev, "found %s, expected %s\n",
44352 + chip ? chip->name : "UNKNOWN",
44358 + info = jedec_probe(spi);
44363 + flash = kzalloc(sizeof *flash, GFP_KERNEL);
44367 + flash->plt_dev = spi;
44368 + mutex_init(&flash->lock);
44369 + dev_set_drvdata(&spi->dev, flash);
44371 + if (data && data->name)
44372 + flash->mtd.name = data->name;
44374 + flash->mtd.name = dev_name(&spi->dev);
44376 + flash->mtd.type = MTD_NORFLASH;
44377 + flash->mtd.writesize = 1;
44378 + flash->mtd.flags = MTD_CAP_NORFLASH;
44379 + flash->mtd.size = info->sector_size * info->n_sectors;
44380 + flash->mtd.erase = ubicom32_flash_driver_erase;
44381 + flash->mtd.read = ubicom32_flash_driver_read;
44382 + flash->mtd.write = ubicom32_flash_driver_write;
44384 + /* prefer "small sector" erase if possible */
44386 + * The Ubicom erase code does not use the opcode for smaller sectors,
44387 + * so disable that functionality and keep erasesize == sector_size
44388 + * so that the test in ubicom32_flash_driver_erase works properly.
44390 + * This was: `if (info->flags & SECT_4K) {' instead of `if (0) {'
44393 + flash->erase_opcode = OPCODE_BE_4K;
44394 + flash->mtd.erasesize = 4096;
44396 + flash->erase_opcode = OPCODE_SE;
44397 + flash->mtd.erasesize = info->sector_size;
44400 + dev_info(&spi->dev, "%s (%lld Kbytes)\n", info->name,
44401 + flash->mtd.size / 1024);
44403 + DEBUG(MTD_DEBUG_LEVEL2,
44404 + "mtd .name = %s, .size = 0x%.8llx (%lluMiB) "
44405 + ".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n",
44407 + flash->mtd.size, flash->mtd.size / (1024*1024),
44408 + flash->mtd.erasesize, flash->mtd.erasesize / 1024,
44409 + flash->mtd.numeraseregions);
44411 + if (flash->mtd.numeraseregions)
44412 + for (i = 0; i < flash->mtd.numeraseregions; i++)
44413 + DEBUG(MTD_DEBUG_LEVEL2,
44414 + "mtd.eraseregions[%d] = { .offset = 0x%.8llx, "
44415 + ".erasesize = 0x%.8x (%uKiB), "
44416 + ".numblocks = %d }\n",
44417 + i, flash->mtd.eraseregions[i].offset,
44418 + flash->mtd.eraseregions[i].erasesize,
44419 + flash->mtd.eraseregions[i].erasesize / 1024,
44420 + flash->mtd.eraseregions[i].numblocks);
44423 + /* partitions should match sector boundaries; and it may be good to
44424 + * use readonly partitions for writeprotected sectors (BP2..BP0).
44426 + if (mtd_has_partitions()) {
44427 + struct mtd_partition *parts = NULL;
44428 + int nr_parts = 0;
44430 +#ifdef CONFIG_MTD_CMDLINE_PARTS
44431 + static const char *part_probes[] = { "cmdlinepart", NULL, };
44433 + nr_parts = parse_mtd_partitions(&flash->mtd,
44434 + part_probes, &parts, 0);
44437 + if (nr_parts <= 0 && data && data->parts) {
44438 + parts = data->parts;
44439 + nr_parts = data->nr_parts;
44440 + if (nr_parts >= 2) {
44442 + * Set last partition size to be 1M.
44444 + parts[1].size = flash->mtd.size -
44445 + parts[0].size - JFFS2_FILESYSTEM_SIZE;
44446 + parts[2].size = JFFS2_FILESYSTEM_SIZE;
44450 + if (nr_parts > 0) {
44451 + for (i = 0; i < nr_parts; i++) {
44452 + DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = "
44453 + "{.name = %s, .offset = 0x%.8llx, "
44454 + ".size = 0x%.8llx (%lluKiB) }\n",
44455 + i, parts[i].name,
44458 + parts[i].size / 1024);
44460 + flash->partitioned = 1;
44461 + return add_mtd_partitions(&flash->mtd, parts, nr_parts);
44463 + } else if (data->nr_parts)
44464 + dev_warn(&spi->dev, "ignoring %d default partitions on %s\n",
44465 + data->nr_parts, data->name);
44467 + return add_mtd_device(&flash->mtd) == 1 ? -ENODEV : 0;
44471 +static int __devexit ubicom32_flash_remove(struct spi_device *spi)
44473 + struct m25p *flash = dev_get_drvdata(&spi->dev);
44476 + /* Clean up MTD stuff. */
44477 + if (mtd_has_partitions() && flash->partitioned)
44478 + status = del_mtd_partitions(&flash->mtd);
44480 + status = del_mtd_device(&flash->mtd);
44486 +static struct platform_driver ubicom32_flash_driver = {
44488 + .name = "ubicom32flashdriver",
44489 + .bus = &platform_bus_type,
44490 + .owner = THIS_MODULE,
44492 + .probe = ubicom32_flash_probe,
44496 +static int ubicom32_flash_driver_init(void)
44498 + return platform_driver_register(&ubicom32_flash_driver);
44502 +static void ubicom32_flash_driver_exit(void)
44504 + platform_driver_unregister(&ubicom32_flash_driver);
44508 +module_init(ubicom32_flash_driver_init);
44509 +module_exit(ubicom32_flash_driver_exit);
44511 +MODULE_LICENSE("GPL");
44512 +MODULE_AUTHOR("Mike Lavender");
44513 +MODULE_DESCRIPTION("Ubicom32 MTD SPI driver for ST M25Pxx flash chips");
44515 +++ b/drivers/mtd/devices/ubi32-nand-spi-er.c
44518 + * Micron SPI-ER NAND Flash Memory
44519 + * This code uses the built in Ubicom flash controller
44521 + * (C) Copyright 2009, Ubicom, Inc.
44523 + * This file is part of the Ubicom32 Linux Kernel Port.
44525 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
44526 + * it and/or modify it under the terms of the GNU General Public License
44527 + * as published by the Free Software Foundation, either version 2 of the
44528 + * License, or (at your option) any later version.
44530 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
44531 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
44532 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
44533 + * the GNU General Public License for more details.
44535 + * You should have received a copy of the GNU General Public License
44536 + * along with the Ubicom32 Linux Kernel Port. If not,
44537 + * see <http://www.gnu.org/licenses/>.
44539 +#include <linux/module.h>
44540 +#include <linux/init.h>
44541 +#include <linux/slab.h>
44542 +#include <linux/delay.h>
44543 +#include <linux/device.h>
44544 +#include <linux/platform_device.h>
44545 +#include <linux/mutex.h>
44546 +#include <linux/err.h>
44548 +#include <linux/mtd/mtd.h>
44549 +#include <linux/mtd/partitions.h>
44551 +#define DRIVER_NAME "ubi32-nand-spi-er"
44552 +#define UBI32_NAND_SPI_ER_BLOCK_FROM_ROW(row) (row >> 6)
44554 +#define UBI32_NAND_SPI_ER_STATUS_P_FAIL (1 << 3)
44555 +#define UBI32_NAND_SPI_ER_STATUS_E_FAIL (1 << 2)
44556 +#define UBI32_NAND_SPI_ER_STATUS_OIP (1 << 0)
44558 +#define UBI32_NAND_SPI_ER_LAST_ROW_INVALID 0xFFFFFFFF
44559 +#define UBI32_NAND_SPI_ER_BAD_BLOCK_MARK_OFFSET 0x08
44561 +struct ubi32_nand_spi_er_device {
44562 + const char *name;
44566 + unsigned int blocks;
44567 + unsigned int pages_per_block;
44568 + unsigned int page_size;
44569 + unsigned int write_size;
44570 + unsigned int erase_size;
44573 +struct ubi32_nand_spi_er {
44576 + const struct ubi32_nand_spi_er_device *device;
44578 + struct mutex lock;
44579 + struct platform_device *pdev;
44581 + struct mtd_info mtd;
44583 + unsigned int last_row; /* the last row we fetched */
44586 + * Bad block table (MUST be last in strcuture)
44588 + unsigned long nbb;
44589 + unsigned long bbt[0];
44593 + * Chip supports a write_size of 512, but we cannot do partial
44594 + * page with command 0x84.
44596 + * We need to use command 0x84 because we cannot fill the FIFO fast
44597 + * enough to transfer the whole 512 bytes at a time. (maybe through
44600 +const struct ubi32_nand_spi_er_device ubi32_nand_spi_er_devices[] = {
44602 + name: "MT29F1G01ZDC",
44605 + pages_per_block: 64,
44607 + write_size: 2048,
44608 + erase_size: 64 * 2048,
44611 + name: "MT29F1G01ZDC",
44614 + pages_per_block: 64,
44616 + write_size: 2048,
44617 + erase_size: 64 * 2048,
44621 +static int read_only = 0;
44622 +module_param(read_only, int, 0);
44623 +MODULE_PARM_DESC(read_only, "Leave device locked");
44626 + * Ubicom32 FLASH Command Set
44628 +#define FLASH_PORT RA
44630 +#define FLASH_FC_INST_CMD 0x00 /* for SPI command only transaction */
44631 +#define FLASH_FC_INST_WR 0x01 /* for SPI write transaction */
44632 +#define FLASH_FC_INST_RD 0x02 /* for SPI read transaction */
44634 +#define FLASH_COMMAND_KICK_OFF(io) \
44636 + " bset "D(IO_INT_CLR)"(%0), #0, #%%bit("D(IO_XFL_INT_DONE)") \n\t" \
44637 + " jmpt.t .+4 \n\t" \
44638 + " bset "D(IO_INT_SET)"(%0), #0, #%%bit("D(IO_XFL_INT_START)") \n\t" \
44644 +#define FLASH_COMMAND_WAIT_FOR_COMPLETION(io) \
44646 + " btst "D(IO_INT_STATUS)"(%0), #%%bit("D(IO_XFL_INT_DONE)") \n\t" \
44647 + " jmpeq.f .-4 \n\t" \
44653 +#define FLASH_COMMAND_EXEC(io) \
44654 + FLASH_COMMAND_KICK_OFF(io) \
44655 + FLASH_COMMAND_WAIT_FOR_COMPLETION(io)
44658 + * ubi32_nand_spi_er_get_feature
44659 + * Get Feature register
44661 +static uint8_t ubi32_nand_spi_er_get_feature(uint32_t reg)
44663 + struct ubicom32_io_port *io = (struct ubicom32_io_port *)FLASH_PORT;
44666 + * Note that this will produce the sequence:
44667 + * SI [0F][REG][00][00]
44668 + * SO ---------[SR][SR][SR]
44669 + * Since the flash controller can only output 24 bits of address, this is
44670 + * ok for this command since the data will just repeat as long as the CS
44671 + * is asserted and the clock is running.
44673 + io->ctl1 &= ~IO_XFL_CTL1_MASK;
44674 + io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_RD) | IO_XFL_CTL1_FC_DATA(1) |
44675 + IO_XFL_CTL1_FC_ADDR;
44676 + io->ctl2 = IO_XFL_CTL2_FC_CMD(0x0F) | IO_XFL_CTL2_FC_ADDR(reg << 16);
44677 + FLASH_COMMAND_EXEC(io);
44679 + return io->status1 & 0xFF;
44683 + * ubi32_nand_spi_er_write_buf
44684 + * writes a buffer to the bus
44686 + * Writes 511 + 1 bytes to the bus, we have to stuff one data byte into the address.
44688 +static void ubi32_nand_spi_er_write_buf(const uint8_t *buf, uint32_t col)
44690 + struct ubicom32_io_port *io = (struct ubicom32_io_port *)FLASH_PORT;
44694 + " bset "D(IO_INT_SET)"(%[port]), #0, #%%bit("D(IO_PORTX_INT_FIFO_TX_RESET)") \n\t"
44695 + " pipe_flush 0 \n\t"
44697 + : [port] "a" (FLASH_PORT)
44702 + * Write the data into the cache
44704 + io->ctl1 &= ~IO_XFL_CTL1_MASK;
44705 +#ifdef SUPPORT_512_FIFO
44706 + io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_WR) | IO_XFL_CTL1_FC_DATA(511) |
44708 + io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_WR) | IO_XFL_CTL1_FC_DATA(31) |
44709 + IO_XFL_CTL1_FC_ADDR;
44712 + * Construct the address with the first byte of data
44714 + tmp = (col << 8) | *buf++;
44715 + io->ctl2 = IO_XFL_CTL2_FC_CMD(0x84) | IO_XFL_CTL2_FC_ADDR(tmp);
44722 + * The first word needs to be [11][22][33][33] to work around a flash
44723 + * controller bug.
44725 + " move.2 %[tmp], (%[data])2++ \n\t"
44726 + " shmrg.1 %[tmp], (%[data]), %[tmp] \n\t"
44727 + " shmrg.1 %[tmp], (%[data])1++, %[tmp] \n\t"
44728 + " move.4 "D(IO_TX_FIFO)"(%[port]), %[tmp] \n\t"
44731 + * We're aligned again!
44734 + " move.4 "D(IO_TX_FIFO)"(%[port]), (%[data])4++ \n\t"
44738 + * Kick off the flash command
44740 + " bset "D(IO_INT_CLR)"(%[port]), #0, #%%bit("D(IO_XFL_INT_DONE)") \n\t"
44741 + " jmpt.t .+4 \n\t"
44742 + " bset "D(IO_INT_SET)"(%[port]), #0, #%%bit("D(IO_XFL_INT_START)") \n\t"
44744 +#ifdef SUPPORT_512_FIFO
44746 + * Fill the remaining 120 words as space becomes available
44749 + " cmpi "D(IO_FIFO_LEVEL)"(%[port]), #4 \n\t"
44750 + " jmpgt.s.t 1b \n\t"
44751 + " move.4 "D(IO_TX_FIFO)"(%[port]), (%[data])4++ \n\t"
44752 + " move.4 "D(IO_TX_FIFO)"(%[port]), (%[data])4++ \n\t"
44753 + " move.4 "D(IO_TX_FIFO)"(%[port]), (%[data])4++ \n\t"
44754 + " move.4 "D(IO_TX_FIFO)"(%[port]), (%[data])4++ \n\t"
44755 + " add.4 %[cnt], #-4, %[cnt] \n\t"
44756 + " jmpgt.t 1b \n\t"
44759 + * Wait for the transaction to finish
44761 + " btst "D(IO_INT_STATUS)"(%[port]), #%%bit("D(IO_XFL_INT_DONE)") \n\t"
44762 + " jmpeq.f .-4 \n\t"
44764 + : [tmp] "=&d" (tmp),
44765 + [data] "+&a" (buf)
44766 + : [column] "d" (col),
44767 + [port] "a" (FLASH_PORT),
44768 + [cnt] "d" (120) // see above comment
44774 + * ubi32_nand_spi_er_send_rd_addr
44775 + * perform FC_RD: CMD + address
44777 +static void ubi32_nand_spi_er_send_rd_addr(uint8_t command, uint32_t address)
44779 + struct ubicom32_io_port *io = (struct ubicom32_io_port *)FLASH_PORT;
44781 + io->ctl1 &= ~IO_XFL_CTL1_MASK;
44782 + io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_RD) | IO_XFL_CTL1_FC_DATA(4) |
44783 + IO_XFL_CTL1_FC_ADDR;
44784 + io->ctl2 = IO_XFL_CTL2_FC_CMD(command) | IO_XFL_CTL2_FC_ADDR(address);
44785 + FLASH_COMMAND_EXEC(io);
44789 + * ubi32_nand_spi_er_send_cmd_addr
44790 + * perform FC_(xxx): CMD + address
44792 +static void ubi32_nand_spi_er_send_cmd_addr(uint8_t command, uint32_t address)
44794 + struct ubicom32_io_port *io = (struct ubicom32_io_port *)FLASH_PORT;
44796 + io->ctl1 &= ~IO_XFL_CTL1_MASK;
44797 + io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_CMD) | IO_XFL_CTL1_FC_ADDR;
44798 + io->ctl2 = IO_XFL_CTL2_FC_CMD(command) | IO_XFL_CTL2_FC_ADDR(address);
44799 + FLASH_COMMAND_EXEC(io);
44803 + * ubi32_nand_spi_er_write_disable
44804 + * clear the write enable bit
44806 +static void ubi32_nand_spi_er_write_disable(void)
44808 + struct ubicom32_io_port *io = (struct ubicom32_io_port *)FLASH_PORT;
44810 + io->ctl1 &= ~IO_XFL_CTL1_MASK;
44811 + io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_CMD);
44812 + io->ctl2 = IO_XFL_CTL2_FC_CMD(0x04);
44813 + FLASH_COMMAND_EXEC(io);
44817 + * ubi32_nand_spi_er_write_enable
44818 + * set the write enable bit
44820 +static void ubi32_nand_spi_er_write_enable(void)
44822 + struct ubicom32_io_port *io = (struct ubicom32_io_port *)FLASH_PORT;
44824 + io->ctl1 &= ~IO_XFL_CTL1_MASK;
44825 + io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_CMD);
44826 + io->ctl2 = IO_XFL_CTL2_FC_CMD(0x06);
44827 + FLASH_COMMAND_EXEC(io);
44831 + * ubi32_nand_spi_er_busywait
44832 + * Wait until the chip is not busy
44834 +static uint8_t ubi32_nand_spi_er_busywait(void)
44840 + * tRD is 100us, so don't delay too long, however, tERS is
44841 + * 10ms so you'd better loop enough.
44843 + for (i = 0; i < 200; i++) {
44844 + data = ubi32_nand_spi_er_get_feature(0xC0);
44845 + if (!(data & UBI32_NAND_SPI_ER_STATUS_OIP)) {
44856 + * ubi32_nand_spi_er_erase
44857 + * Erase a block, parameters must be block aligned
44859 +static int ubi32_nand_spi_er_erase(struct mtd_info *mtd, struct erase_info *instr)
44861 + struct ubi32_nand_spi_er *chip = mtd->priv;
44864 + DEBUG(MTD_DEBUG_LEVEL3, "%s: erase addr:%x len:%x\n", chip->name, instr->addr, instr->len);
44866 + if ((instr->addr + instr->len) > mtd->size) {
44870 + if (instr->addr & (chip->device->erase_size - 1)) {
44871 + DEBUG(MTD_DEBUG_LEVEL1, "%s: erase address is not aligned %x\n", chip->name, instr->addr);
44875 + if (instr->len & (chip->device->erase_size - 1)) {
44876 + DEBUG(MTD_DEBUG_LEVEL1, "%s: erase len is not aligned %x\n", chip->name, instr->len);
44880 + mutex_lock(&chip->lock);
44881 + chip->last_row = UBI32_NAND_SPI_ER_LAST_ROW_INVALID;
44883 + while (instr->len) {
44884 + uint32_t block = instr->addr >> 17;
44885 + uint32_t row = block << 6;
44887 + DEBUG(MTD_DEBUG_LEVEL3, "%s: block erase row:%x block:%x addr:%x rem:%x\n", chip->name, row, block, instr->addr, instr->len);
44890 + * Test for bad block
44892 + if (test_bit(block, chip->bbt)) {
44893 + instr->fail_addr = block << 17;
44894 + instr->state = MTD_ERASE_FAILED;
44899 + ubi32_nand_spi_er_write_enable();
44904 + ubi32_nand_spi_er_send_cmd_addr(0xD8, row);
44909 + stat = ubi32_nand_spi_er_busywait();
44910 + if (stat & UBI32_NAND_SPI_ER_STATUS_OIP) {
44911 + instr->fail_addr = block << 17;
44912 + instr->state = MTD_ERASE_FAILED;
44913 + DEBUG(MTD_DEBUG_LEVEL1, "%s: chip is busy or nonresponsive stat=%02x\n", chip->name, stat);
44923 + * Check the status register
44925 + if (stat & UBI32_NAND_SPI_ER_STATUS_E_FAIL) {
44926 + DEBUG(MTD_DEBUG_LEVEL1, "%s: E_FAIL signalled (%02x)\n", chip->name, stat);
44927 + instr->fail_addr = block << 17;
44928 + instr->state = MTD_ERASE_FAILED;
44936 + instr->len -= chip->device->erase_size;
44937 + instr->addr += chip->device->erase_size;
44940 + instr->state = MTD_ERASE_DONE;
44942 + mutex_unlock(&chip->lock);
44946 + ubi32_nand_spi_er_write_disable();
44948 + mutex_unlock(&chip->lock);
44950 + mtd_erase_callback(instr);
44955 + * ubi32_nand_spi_er_read
44957 + * return -EUCLEAN: ecc error recovered
44958 + * return -EBADMSG: ecc error not recovered
44960 +static int ubi32_nand_spi_er_read(struct mtd_info *mtd, loff_t from, size_t len,
44961 + size_t *retlen, u_char *buf)
44963 + struct ubi32_nand_spi_er *chip = mtd->priv;
44964 + struct ubicom32_io_port *io = (struct ubicom32_io_port *)FLASH_PORT;
44969 + uint32_t *pbuf = (uint32_t *)buf;
44972 + DEBUG(MTD_DEBUG_LEVEL2, "%s: read block from %llx len %d into %p\n", chip->name, from, len, buf);
44975 + * buf should be aligned
44977 + if ((uint32_t)buf & 0x03) {
44982 + * Zero length reads, nothing to do
44989 + * Reject reads which go over the end of the flash
44991 + if ((from + len) > mtd->size) {
44996 + * Get the row and column address to start at
44998 + row = from >> 11;
44999 + column = from & 0x7FF;
45000 + DEBUG(MTD_DEBUG_LEVEL3, "%s: row=%x %d column=%x %d last_row=%x %d\n", chip->name, row, row, column, column, chip->last_row, chip->last_row);
45003 + * Read the data from the chip
45005 + mutex_lock(&chip->lock);
45013 + * Figure out how much to read
45015 + * If we are reading from the middle of a page then the most we
45016 + * can read is to the end of the page
45019 + if (toread > (chip->device->page_size - column)) {
45020 + toread = chip->device->page_size - column;
45023 + DEBUG(MTD_DEBUG_LEVEL3, "%s: buf=%p toread=%x row=%x column=%x last_row=%x\n", chip->name, pbuf, toread, row, column, chip->last_row);
45025 + if (chip->last_row != row) {
45027 + * Check if the block is bad
45029 + if (test_bit(UBI32_NAND_SPI_ER_BLOCK_FROM_ROW(row), chip->bbt)) {
45030 + mutex_unlock(&chip->lock);
45035 + * Load the appropriate page
45037 + ubi32_nand_spi_er_send_cmd_addr(0x13, row);
45042 + stat = ubi32_nand_spi_er_busywait();
45043 + if (stat & UBI32_NAND_SPI_ER_STATUS_OIP) {
45044 + DEBUG(MTD_DEBUG_LEVEL1, "%s: chip is busy or nonresponsive stat=%02x\n", chip->name, stat);
45049 + mutex_unlock(&chip->lock);
45054 + * Check the ECC bits
45058 + DEBUG(MTD_DEBUG_LEVEL1, "%s: ECC recovered, row=%x\n", chip->name, row);
45059 + retval = -EUCLEAN;
45062 + DEBUG(MTD_DEBUG_LEVEL0, "%s: failed ECC, row=%x\n", chip->name, row);
45063 + chip->last_row = UBI32_NAND_SPI_ER_LAST_ROW_INVALID;
45064 + mutex_unlock(&chip->lock);
45070 + chip->last_row = row;
45073 + * Read out the data:
45074 + * We can always read a little too much since there is the
45075 + * OOB after byte addr 2047. The most we'll overread is 3 bytes.
45077 + if (((uint32_t)pbuf & 0x03) == 0) {
45081 + tmp = toread & (~0x03);
45082 + for (i = 0; i < tmp; i += 4) {
45083 + ubi32_nand_spi_er_send_rd_addr(0x03, column << 8);
45084 + *pbuf++ = io->status1;
45091 + tmp = toread & (~0x03);
45092 + for (i = 0; i < tmp; i += 4) {
45093 + ubi32_nand_spi_er_send_rd_addr(0x03, column << 8);
45094 + memcpy(pbuf, &io->status1, 4);
45100 + * Fill in any single bytes
45102 + tmp = toread & 0x03;
45104 + uint8_t *bbuf = pbuf;
45106 + ubi32_nand_spi_er_send_rd_addr(0x03, column << 8);
45107 + val = io->status1;
45108 + for (i = 0; i < tmp; i++) {
45109 + *bbuf++ = val >> 24;
45115 + *retlen += toread;
45118 + * For the next page, increment the row and always start at column 0
45124 + mutex_unlock(&chip->lock);
45129 + * ubi32_nand_spi_er_write
45131 +#define WRITE_NOT_ALIGNED(x) ((x & (device->write_size - 1)) != 0)
45132 +static int ubi32_nand_spi_er_write(struct mtd_info *mtd, loff_t to, size_t len,
45133 + size_t *retlen, const u_char *buf)
45135 + struct ubi32_nand_spi_er *chip = mtd->priv;
45136 + const struct ubi32_nand_spi_er_device *device = chip->device;
45137 + struct ubicom32_io_port *io = (struct ubicom32_io_port *)FLASH_PORT;
45143 + DEBUG(MTD_DEBUG_LEVEL2, "%s: write block to %llx len %d from %p\n", chip->name, to, len, buf);
45148 + * nothing to write
45155 + * Reject writes which go over the end of the flash
45157 + if ((to + len) > mtd->size) {
45162 + * buf should be aligned to 16 bits
45164 + if ((uint32_t)buf & 0x01) {
45169 + * Check to see if everything is page aligned
45171 + if (WRITE_NOT_ALIGNED(to) || WRITE_NOT_ALIGNED(len)) {
45172 + printk(KERN_NOTICE "ubi32_nand_spi_er_write: Attempt to write non page aligned data\n");
45176 + mutex_lock(&chip->lock);
45178 + io->ctl0 |= IO_XFL_CTL0_MCB_LOCK;
45180 + chip->last_row = UBI32_NAND_SPI_ER_LAST_ROW_INVALID;
45183 + * If the first write is a partial write then write at most the number of
45184 + * bytes to get us page aligned and then the remainder will be
45185 + * page aligned. The last bit may be a partial page as well.
45187 + col = to & (device->page_size - 1);
45188 + towrite = device->page_size - col;
45189 + if (towrite > len) {
45199 + uint32_t my_towrite;
45201 + DEBUG(MTD_DEBUG_LEVEL3, "%s: write %p to row:%x col:%x len:%x rem:%x\n", chip->name, buf, row, col, towrite, len);
45203 + ubi32_nand_spi_er_write_enable();
45206 + * Move the data into the cache
45208 + my_towrite = towrite;
45209 + while (my_towrite) {
45210 + uint32_t len = my_towrite;
45215 + ubi32_nand_spi_er_write_buf(buf, col);
45218 + my_towrite -= len;
45222 + * Program execute
45224 + ubi32_nand_spi_er_send_cmd_addr(0x10, row);
45229 + stat = ubi32_nand_spi_er_busywait();
45230 + if (stat & UBI32_NAND_SPI_ER_STATUS_OIP) {
45231 + DEBUG(MTD_DEBUG_LEVEL1, "%s: chip is busy or nonresponsive stat=%02x\n", chip->name, stat);
45240 + if (stat & (1 << 3)) {
45247 + *retlen += towrite;
45250 + * At this point, we are always page aligned so start at column 0.
45251 + * Note we may not have a full page to write at the end, hence the
45252 + * check if towrite > len.
45255 + towrite = device->page_size;
45256 + if (towrite > len) {
45261 + io->ctl0 &= ~IO_XFL_CTL0_MCB_LOCK;
45263 + mutex_unlock(&chip->lock);
45267 + ubi32_nand_spi_er_write_disable();
45269 + io->ctl0 &= ~IO_XFL_CTL0_MCB_LOCK;
45271 + mutex_unlock(&chip->lock);
45277 + * ubi32_nand_spi_er_isbad
45279 +static int ubi32_nand_spi_er_isbad(struct mtd_info *mtd, loff_t ofs)
45281 + struct ubi32_nand_spi_er *chip = mtd->priv;
45284 + if (ofs & (chip->device->erase_size - 1)) {
45285 + DEBUG(MTD_DEBUG_LEVEL1, "%s: address not aligned %llx\n", chip->name, ofs);
45289 + block = ofs >> 17;
45291 + return test_bit(block, chip->bbt);
45295 + * ubi32_nand_spi_er_markbad
45297 +static int ubi32_nand_spi_er_markbad(struct mtd_info *mtd, loff_t ofs)
45299 + struct ubi32_nand_spi_er *chip = mtd->priv;
45300 + struct ubicom32_io_port *io = (struct ubicom32_io_port *)FLASH_PORT;
45306 + if (ofs & (chip->device->erase_size - 1)) {
45307 + DEBUG(MTD_DEBUG_LEVEL1, "%s: address not aligned %llx\n", chip->name, ofs);
45311 + block = ofs >> 17;
45314 + * If it's already marked bad, no need to mark it
45316 + if (test_bit(block, chip->bbt)) {
45321 + * Mark it in our cache
45323 + __set_bit(block, chip->bbt);
45326 + * Write the user bad block mark. If it fails, then we really
45327 + * can't do anything about it.
45329 + mutex_lock(&chip->lock);
45330 + chip->last_row = UBI32_NAND_SPI_ER_LAST_ROW_INVALID;
45332 + ubi32_nand_spi_er_write_enable();
45337 + io->ctl0 |= IO_XFL_CTL0_MCB_LOCK;
45338 + io->ctl1 &= ~IO_XFL_CTL1_MASK;
45339 + io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_WR) | IO_XFL_CTL1_FC_DATA(6);
45340 + io->ctl2 = IO_XFL_CTL2_FC_CMD(0x84);
45343 + " bset "D(IO_INT_SET)"(%[port]), #0, #%%bit("D(IO_PORTX_INT_FIFO_TX_RESET)") \n\t"
45344 + " pipe_flush 0 \n\t"
45347 + * Move the data into the FIFO
45349 + " move.4 "D(IO_TX_FIFO)"(%[port]), %[word1] \n\t"
45350 + " move.4 "D(IO_TX_FIFO)"(%[port]), %[word2] \n\t"
45353 + * Kick off the flash command
45355 + " bset "D(IO_INT_CLR)"(%[port]), #0, #%%bit("D(IO_XFL_INT_DONE)") \n\t"
45356 + " jmpt.t .+4 \n\t"
45357 + " bset "D(IO_INT_SET)"(%[port]), #0, #%%bit("D(IO_XFL_INT_START)") \n\t"
45360 + * Wait for the transaction to finish
45362 + " btst "D(IO_INT_STATUS)"(%[port]), #%%bit("D(IO_XFL_INT_DONE)") \n\t"
45363 + " jmpeq.f .-4 \n\t"
45366 + : [word1] "d" (0x0800dead | (UBI32_NAND_SPI_ER_BAD_BLOCK_MARK_OFFSET << 16)),
45367 + [word2] "d" (0xbeef0000),
45368 + [port] "a" (FLASH_PORT)
45372 + io->ctl0 &= ~IO_XFL_CTL0_MCB_LOCK;
45375 + * Program execute
45377 + row = block << 6;
45378 + ubi32_nand_spi_er_send_cmd_addr(0x10, row);
45383 + stat = ubi32_nand_spi_er_busywait();
45384 + if (stat & UBI32_NAND_SPI_ER_STATUS_OIP) {
45385 + DEBUG(MTD_DEBUG_LEVEL1, "%s: chip is busy or nonresponsive stat=%02x\n", chip->name, stat);
45394 + if (stat & (1 << 3)) {
45399 + ubi32_nand_spi_er_write_disable();
45401 + mutex_unlock(&chip->lock);
45407 + * ubi32_nand_spi_er_read_bbt
45409 +static int ubi32_nand_spi_er_read_bbt(struct ubi32_nand_spi_er *chip)
45412 + struct ubicom32_io_port *io = (struct ubicom32_io_port *)FLASH_PORT;
45414 + for (j = 0; j < chip->device->blocks; j++) {
45415 + unsigned short row = j << 6;
45421 + ubi32_nand_spi_er_send_cmd_addr(0x13, row);
45426 + stat = ubi32_nand_spi_er_busywait();
45427 + if (stat & UBI32_NAND_SPI_ER_STATUS_OIP) {
45428 + DEBUG(MTD_DEBUG_LEVEL1, "%s: chip is busy or nonresponsive stat=%02x\n", chip->name, stat);
45437 + * Check factory bad block mark
45439 + ubi32_nand_spi_er_send_rd_addr(0x03, 0x080000);
45441 + if ((io->status1 >> 24) != 0xFF) {
45443 + __set_bit(j, chip->bbt);
45447 + ubi32_nand_spi_er_send_rd_addr(0x03, 0x080000 | (UBI32_NAND_SPI_ER_BAD_BLOCK_MARK_OFFSET << 8));
45448 + if (io->status1 == 0xdeadbeef) {
45450 + __set_bit(j, chip->bbt);
45454 +#if defined(CONFIG_MTD_DEBUG) && (MTD_DEBUG_LEVEL3 <= CONFIG_MTD_DEBUG_VERBOSE)
45455 + printk("%s: Bad Block Table:", chip->name);
45456 + for (j = 0; j < chip->device->blocks; j++) {
45457 + if ((j % 64) == 0) {
45458 + printk("\n%s: block %03x: ", chip->name, j);
45460 + printk("%c", test_bit(j, chip->bbt) ? 'X' : '.');
45462 + printk("\n%s: Bad Block Numbers: ", chip->name);
45463 + for (j = 0; j < chip->device->blocks; j++) {
45464 + if (test_bit(j, chip->bbt)) {
45465 + printk("%x ", j);
45476 + * Called at boot time:
45478 + * ubi32_nand_spi_er=read_only
45479 + * if read_only specified then do not unlock device
45481 +static int __init ubi32_nand_spi_er_setup(char *str)
45483 + if (str && (strncasecmp(str, "read_only", 9) == 0)) {
45489 +__setup("ubi32_nand_spi_er=", ubi32_nand_spi_er_setup);
45493 + * ubi32_nand_spi_er_probe
45494 + * Detect and initialize ubi32_nand_spi_er device.
45496 +static int __devinit ubi32_nand_spi_er_probe(struct platform_device *pdev)
45501 + size_t bbt_bytes;
45502 + struct ubi32_nand_spi_er *chip;
45503 + const struct ubi32_nand_spi_er_device *device;
45504 + struct ubicom32_io_port *io = (struct ubicom32_io_port *)FLASH_PORT;
45509 + for (i = 0; i < 2; i++) {
45510 + io->ctl1 &= ~IO_XFL_CTL1_MASK;
45511 + io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_CMD);
45512 + io->ctl2 = IO_XFL_CTL2_FC_CMD(0xFF);
45513 + FLASH_COMMAND_EXEC(io);
45521 + io->ctl1 &= ~IO_XFL_CTL1_MASK;
45522 + io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_RD) | IO_XFL_CTL1_FC_DATA(2) |
45523 + IO_XFL_CTL1_FC_ADDR;
45524 + io->ctl2 = IO_XFL_CTL2_FC_CMD(0x9F);
45525 + FLASH_COMMAND_EXEC(io);
45527 + id = io->status1 >> 16;
45528 + device = ubi32_nand_spi_er_devices;
45529 + for (i = 0; i < ARRAY_SIZE(ubi32_nand_spi_er_devices); i++) {
45530 + if (device->id == id) {
45535 + if (i == ARRAY_SIZE(ubi32_nand_spi_er_devices)) {
45540 + * Initialize our chip structure
45542 + bbt_bytes = DIV_ROUND_UP(device->blocks, BITS_PER_BYTE);
45543 + chip = kzalloc(sizeof(struct ubi32_nand_spi_er) + bbt_bytes, GFP_KERNEL);
45547 + snprintf(chip->name, sizeof(chip->name), "%s", device->name);
45549 + chip->device = device;
45550 + chip->last_row = UBI32_NAND_SPI_ER_LAST_ROW_INVALID;
45552 + mutex_init(&chip->lock);
45554 + chip->mtd.type = MTD_NANDFLASH;
45555 + chip->mtd.flags = MTD_WRITEABLE;
45558 + * #blocks * block size * n blocks
45560 + chip->mtd.size = device->blocks * device->pages_per_block * device->page_size;
45561 + chip->mtd.erasesize = device->erase_size;
45564 + * 1 page, optionally we can support partial write (512)
45566 + chip->mtd.writesize = device->write_size;
45567 + chip->mtd.name = device->name;
45568 + chip->mtd.erase = ubi32_nand_spi_er_erase;
45569 + chip->mtd.read = ubi32_nand_spi_er_read;
45570 + chip->mtd.write = ubi32_nand_spi_er_write;
45571 + chip->mtd.block_isbad = ubi32_nand_spi_er_isbad;
45572 + chip->mtd.block_markbad = ubi32_nand_spi_er_markbad;
45573 + chip->mtd.priv = chip;
45576 + * Cache the bad block table
45578 + res = ubi32_nand_spi_er_read_bbt(chip);
45585 + * Un/lock the chip
45587 + io->ctl0 |= IO_XFL_CTL0_MCB_LOCK;
45588 + io->ctl1 &= ~IO_XFL_CTL1_MASK;
45589 + io->ctl1 |= IO_XFL_CTL1_FC_INST(FLASH_FC_INST_WR) | IO_XFL_CTL1_FC_DATA(2);
45590 + io->ctl2 = IO_XFL_CTL2_FC_CMD(0x1F);
45598 + " bset "D(IO_INT_SET)"(%[port]), #0, #%%bit("D(IO_PORTX_INT_FIFO_TX_RESET)") \n\t"
45599 + " pipe_flush 0 \n\t"
45602 + * Move the data into the FIFO
45604 + " move.4 "D(IO_TX_FIFO)"(%[port]), %[word1] \n\t"
45607 + * Kick off the flash command
45609 + " bset "D(IO_INT_CLR)"(%[port]), #0, #%%bit("D(IO_XFL_INT_DONE)") \n\t"
45610 + " jmpt.t .+4 \n\t"
45611 + " bset "D(IO_INT_SET)"(%[port]), #0, #%%bit("D(IO_XFL_INT_START)") \n\t"
45614 + * Wait for the transaction to finish
45616 + " btst "D(IO_INT_STATUS)"(%[port]), #%%bit("D(IO_XFL_INT_DONE)") \n\t"
45617 + " jmpeq.f .-4 \n\t"
45620 + : [word1] "d" (i),
45621 + [port] "a" (FLASH_PORT)
45624 + io->ctl0 &= ~IO_XFL_CTL0_MCB_LOCK;
45626 + dev_set_drvdata(&pdev->dev, chip);
45628 + printk(KERN_INFO "%s: added device size: %u KBytes %lu bad blocks %s\n", chip->mtd.name, DIV_ROUND_UP(chip->mtd.size, 1024), chip->nbb, read_only ? "[read only]" : "");
45629 + return add_mtd_device(&chip->mtd);
45633 + * ubi32_nand_spi_er_remove
45635 +static int __devexit ubi32_nand_spi_er_remove(struct platform_device *pdev)
45637 + struct ubi32_nand_spi_er *chip = dev_get_drvdata(&pdev->dev);
45640 + DEBUG(MTD_DEBUG_LEVEL1, "%s: remove\n", chip->name);
45642 + status = del_mtd_device(&chip->mtd);
45643 + if (status == 0) {
45647 + dev_set_drvdata(&pdev->dev, NULL);
45651 +static struct platform_device *ubi32_nand_spi_er_device;
45653 +static struct platform_driver ubi32_nand_spi_er_driver = {
45655 + .name = DRIVER_NAME,
45656 + .owner = THIS_MODULE,
45659 + .probe = ubi32_nand_spi_er_probe,
45660 + .remove = ubi32_nand_spi_er_remove,
45664 + * ubi32_nand_spi_er_init
45666 +static int __init ubi32_nand_spi_er_init(void)
45670 + ret = platform_driver_register(&ubi32_nand_spi_er_driver);
45676 + ubi32_nand_spi_er_device = platform_device_alloc(DRIVER_NAME, 0);
45677 + if (!ubi32_nand_spi_er_device) {
45681 + ret = platform_device_add(ubi32_nand_spi_er_device);
45683 + platform_device_put(ubi32_nand_spi_er_device);
45684 + platform_driver_unregister(&ubi32_nand_spi_er_driver);
45689 +module_init(ubi32_nand_spi_er_init);
45692 + * ubi32_nand_spi_er_exit
45694 +static void __exit ubi32_nand_spi_er_exit(void)
45696 + platform_device_unregister(ubi32_nand_spi_er_device);
45697 + platform_driver_unregister(&ubi32_nand_spi_er_driver);
45699 +module_exit(ubi32_nand_spi_er_exit);
45702 +MODULE_LICENSE("GPL");
45703 +MODULE_AUTHOR("Patrick Tjin");
45704 +MODULE_DESCRIPTION("MTD ubi32_nand_spi_er driver for ubicom32 SPI flash controller.");
45705 --- a/drivers/net/Kconfig
45706 +++ b/drivers/net/Kconfig
45707 @@ -2540,6 +2540,19 @@ config JME
45708 To compile this driver as a module, choose M here. The module
45709 will be called jme.
45711 +config UBICOM32_GMAC
45712 + tristate "Ubicom Gigabit Ethernet support"
45713 + depends on UBICOM32
45715 + Gigabit Ethernet support for ubicom32 processors
45717 +config UBICOM32_OCM_FOR_SKB
45718 + bool "USE OCM for SKB (EXPERIMENTAL)"
45719 + depends on UBICOM32_GMAC
45722 + Allocate skb from OCM for Ethernet Receive when possible
45724 endif # NETDEV_1000
45727 --- a/drivers/net/Makefile
45728 +++ b/drivers/net/Makefile
45729 @@ -272,3 +272,5 @@ obj-$(CONFIG_VIRTIO_NET) += virtio_net.o
45730 obj-$(CONFIG_SFC) += sfc/
45732 obj-$(CONFIG_WIMAX) += wimax/
45734 +obj-$(CONFIG_UBICOM32_GMAC) += ubi32-eth.o
45736 +++ b/drivers/net/ubi32-eth.c
45739 + * drivers/net/ubi32-eth.c
45740 + * Ubicom32 ethernet TIO interface driver.
45742 + * (C) Copyright 2009, Ubicom, Inc.
45744 + * This file is part of the Ubicom32 Linux Kernel Port.
45746 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
45747 + * it and/or modify it under the terms of the GNU General Public License
45748 + * as published by the Free Software Foundation, either version 2 of the
45749 + * License, or (at your option) any later version.
45751 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
45752 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
45753 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
45754 + * the GNU General Public License for more details.
45756 + * You should have received a copy of the GNU General Public License
45757 + * along with the Ubicom32 Linux Kernel Port. If not,
45758 + * see <http://www.gnu.org/licenses/>.
45760 + * Ubicom32 implementation derived from (with many thanks):
45767 + * Ethernet driver for Ip5k/Ip7K
45770 +#include <linux/module.h>
45771 +#include <linux/init.h>
45772 +#include <linux/moduleparam.h>
45774 +#include <linux/sched.h>
45775 +#include <linux/kernel.h>
45776 +#include <linux/errno.h>
45777 +#include <linux/types.h>
45778 +#include <linux/interrupt.h>
45780 +#include <linux/in.h>
45781 +#include <linux/netdevice.h>
45782 +#include <linux/etherdevice.h>
45783 +#include <linux/mii.h>
45784 +#include <linux/if_vlan.h>
45785 +#include <linux/ip.h>
45786 +#include <linux/tcp.h>
45787 +#include <linux/skbuff.h>
45788 +#include <asm/checksum.h>
45789 +#include <asm/ip5000.h>
45790 +#include <asm/devtree.h>
45791 +#include <asm/system.h>
45793 +#define UBICOM32_USE_NAPI /* define this to use NAPI instead of tasklet */
45794 +//#define UBICOM32_USE_POLLING /* define this to use polling instead of interrupt */
45795 +#include "ubi32-eth.h"
45799 + * mac address from flash
45800 + * multicast filter
45801 + * ethtool support
45803 + * skb->nrfrag support
45805 + * monitor phy status
45808 +extern int ubi32_ocm_skbuf_max, ubi32_ocm_skbuf, ubi32_ddr_skbuf;
45809 +static const char *eth_if_name[UBI32_ETH_NUM_OF_DEVICES] =
45810 + {"eth_lan", "eth_wan"};
45811 +static struct net_device *ubi32_eth_devices[UBI32_ETH_NUM_OF_DEVICES] =
45813 +static u8_t mac_addr[UBI32_ETH_NUM_OF_DEVICES][ETH_ALEN] = {
45814 + {0x00, 0x03, 0x64, 'l', 'a', 'n'},
45815 + {0x00, 0x03, 0x64, 'w', 'a', 'n'}};
45817 +#if (defined(CONFIG_ZONE_DMA) && defined(CONFIG_UBICOM32_OCM_FOR_SKB))
45818 +static inline struct sk_buff *ubi32_alloc_skb_ocm(struct net_device *dev, unsigned int length)
45820 + return __dev_alloc_skb(length, GFP_ATOMIC | __GFP_NOWARN | __GFP_NORETRY | GFP_DMA);
45824 +static inline struct sk_buff *ubi32_alloc_skb(struct net_device *dev, unsigned int length)
45826 + return __dev_alloc_skb(length, GFP_ATOMIC | __GFP_NOWARN);
45829 +static void ubi32_eth_vp_rxtx_enable(struct net_device *dev)
45831 + struct ubi32_eth_private *priv = netdev_priv(dev);
45832 + priv->regs->command = UBI32_ETH_VP_CMD_RX_ENABLE | UBI32_ETH_VP_CMD_TX_ENABLE;
45833 + priv->regs->int_mask = (UBI32_ETH_VP_INT_RX | UBI32_ETH_VP_INT_TX);
45834 + ubicom32_set_interrupt(priv->vp_int_bit);
45837 +static void ubi32_eth_vp_rxtx_stop(struct net_device *dev)
45839 + struct ubi32_eth_private *priv = netdev_priv(dev);
45840 + priv->regs->command = 0;
45841 + priv->regs->int_mask = 0;
45842 + ubicom32_set_interrupt(priv->vp_int_bit);
45844 + /* Wait for graceful shutdown */
45845 + while (priv->regs->status & (UBI32_ETH_VP_STATUS_RX_STATE | UBI32_ETH_VP_STATUS_TX_STATE));
45849 + * ubi32_eth_tx_done()
45851 +static int ubi32_eth_tx_done(struct net_device *dev)
45853 + struct ubi32_eth_private *priv;
45854 + struct sk_buff *skb;
45855 + volatile void *pdata;
45856 + struct ubi32_eth_dma_desc *desc;
45859 + priv = netdev_priv(dev);
45861 + priv->regs->int_status &= ~UBI32_ETH_VP_INT_TX;
45862 + while (priv->tx_tail != priv->regs->tx_out) {
45863 + pdata = priv->regs->tx_dma_ring[priv->tx_tail];
45864 + BUG_ON(pdata == NULL);
45866 + skb = container_of((void *)pdata, struct sk_buff, cb);
45867 + desc = (struct ubi32_eth_dma_desc *)pdata;
45868 + if (unlikely(!(desc->status & UBI32_ETH_VP_TX_OK))) {
45869 + dev->stats.tx_errors++;
45871 + dev->stats.tx_packets++;
45872 + dev->stats.tx_bytes += skb->len;
45874 + dev_kfree_skb_any(skb);
45875 + priv->regs->tx_dma_ring[priv->tx_tail] = NULL;
45876 + priv->tx_tail = (priv->tx_tail + 1) & TX_DMA_RING_MASK;
45880 + if (unlikely(priv->regs->status & UBI32_ETH_VP_STATUS_TX_Q_FULL)) {
45881 + spin_lock(&priv->lock);
45882 + if (priv->regs->status & UBI32_ETH_VP_STATUS_TX_Q_FULL) {
45883 + priv->regs->status &= ~UBI32_ETH_VP_STATUS_TX_Q_FULL;
45884 + netif_wake_queue(dev);
45886 + spin_unlock(&priv->lock);
45892 + * ubi32_eth_receive()
45893 + * To avoid locking overhead, this is called only
45894 + * by tasklet when not using NAPI, or
45895 + * by NAPI poll when using NAPI.
45896 + * return number of frames processed
45898 +static int ubi32_eth_receive(struct net_device *dev, int quota)
45900 + struct ubi32_eth_private *priv = netdev_priv(dev);
45901 + unsigned short rx_in = priv->regs->rx_in;
45902 + struct sk_buff *skb;
45903 + struct ubi32_eth_dma_desc *desc = NULL;
45904 + volatile void *pdata;
45906 + int extra_reserve_adj;
45907 + int extra_alloc = UBI32_ETH_RESERVE_SPACE + UBI32_ETH_TRASHED_MEMORY;
45908 + int replenish_cnt, count = 0;
45909 + int replenish_max = RX_DMA_MAX_QUEUE_SIZE;
45910 +#if (defined(CONFIG_ZONE_DMA) && defined(CONFIG_UBICOM32_OCM_FOR_SKB))
45911 + if (likely(dev == ubi32_eth_devices[0]))
45912 + replenish_max = min(ubi32_ocm_skbuf_max, RX_DMA_MAX_QUEUE_SIZE);;
45915 + if (unlikely(rx_in == priv->regs->rx_out))
45916 + priv->vp_stats.rx_q_full_cnt++;
45918 + priv->regs->int_status &= ~UBI32_ETH_VP_INT_RX;
45919 + while (priv->rx_tail != priv->regs->rx_out) {
45920 + if (unlikely(count == quota)) {
45921 + /* There is still frame pending to be processed */
45922 + priv->vp_stats.rx_throttle++;
45926 + pdata = priv->regs->rx_dma_ring[priv->rx_tail];
45927 + BUG_ON(pdata == NULL);
45929 + desc = (struct ubi32_eth_dma_desc *)pdata;
45930 + skb = container_of((void *)pdata, struct sk_buff, cb);
45932 + priv->regs->rx_dma_ring[priv->rx_tail] = NULL;
45933 + priv->rx_tail = ((priv->rx_tail + 1) & RX_DMA_RING_MASK);
45936 + * Check only RX_OK bit here.
45937 + * The rest of status word is used as timestamp
45939 + if (unlikely(!(desc->status & UBI32_ETH_VP_RX_OK))) {
45940 + dev->stats.rx_errors++;
45941 + dev_kfree_skb_any(skb);
45945 + skb_put(skb, desc->data_len);
45947 + skb->protocol = eth_type_trans(skb, dev);
45948 + skb->ip_summed = CHECKSUM_NONE;
45949 + dev->stats.rx_bytes += skb->len;
45950 + dev->stats.rx_packets++;
45951 +#ifndef UBICOM32_USE_NAPI
45954 + netif_receive_skb(skb);
45958 + /* fill in more descripor for VP*/
45959 + replenish_cnt = replenish_max -
45960 + ((RX_DMA_RING_SIZE + rx_in - priv->rx_tail) & RX_DMA_RING_MASK);
45961 + if (replenish_cnt > 0) {
45962 +#if (defined(CONFIG_ZONE_DMA) && defined(CONFIG_UBICOM32_OCM_FOR_SKB))
45964 + * black magic for perforamnce:
45965 + * Try to allocate skb from OCM only for first Ethernet I/F.
45966 + * Also limit number of RX buffers to 21 due to limited OCM.
45968 + if (likely(dev == ubi32_eth_devices[0])) {
45970 + skb = ubi32_alloc_skb_ocm(dev, RX_BUF_SIZE + extra_alloc);
45974 + /* set up dma descriptor */
45975 + ubi32_ocm_skbuf++;
45976 + desc = (struct ubi32_eth_dma_desc *)skb->cb;
45977 + extra_reserve_adj =
45978 + ((u32)skb->data + UBI32_ETH_RESERVE_SPACE + ETH_HLEN) &
45979 + (CACHE_LINE_SIZE - 1);
45980 + skb_reserve(skb, UBI32_ETH_RESERVE_SPACE - extra_reserve_adj);
45981 + desc->data_pointer = skb->data;
45982 + desc->buffer_len = RX_BUF_SIZE + UBI32_ETH_TRASHED_MEMORY;
45983 + desc->data_len = 0;
45984 + desc->status = 0;
45985 + priv->regs->rx_dma_ring[rx_in] = desc;
45986 + rx_in = (rx_in + 1) & RX_DMA_RING_MASK;
45987 + } while (--replenish_cnt > 0);
45991 + while (replenish_cnt-- > 0) {
45992 + skb = ubi32_alloc_skb(dev, RX_BUF_SIZE + extra_alloc);
45994 + priv->vp_stats.rx_alloc_err++;
45997 + /* set up dma descriptor */
45998 + ubi32_ddr_skbuf++;
45999 + desc = (struct ubi32_eth_dma_desc *)skb->cb;
46000 + extra_reserve_adj =
46001 + ((u32)skb->data + UBI32_ETH_RESERVE_SPACE + ETH_HLEN) &
46002 + (CACHE_LINE_SIZE - 1);
46003 + skb_reserve(skb, UBI32_ETH_RESERVE_SPACE - extra_reserve_adj);
46004 + desc->data_pointer = skb->data;
46005 + desc->buffer_len = RX_BUF_SIZE + UBI32_ETH_TRASHED_MEMORY;
46006 + desc->data_len = 0;
46007 + desc->status = 0;
46008 + priv->regs->rx_dma_ring[rx_in] = desc;
46009 + rx_in = (rx_in + 1) & RX_DMA_RING_MASK;
46013 + priv->regs->rx_in = rx_in;
46014 + ubicom32_set_interrupt(priv->vp_int_bit);
46017 + if (likely(count > 0)) {
46018 + dev->last_rx = jiffies;
46023 +#ifdef UBICOM32_USE_NAPI
46024 +static int ubi32_eth_napi_poll(struct napi_struct *napi, int budget)
46026 + struct ubi32_eth_private *priv = container_of(napi, struct ubi32_eth_private, napi);
46027 + struct net_device *dev = priv->dev;
46030 + if (priv->tx_tail != priv->regs->tx_out) {
46031 + ubi32_eth_tx_done(dev);
46034 + count = ubi32_eth_receive(dev, budget);
46036 + if (count < budget) {
46037 + napi_complete(napi);
46038 + priv->regs->int_mask |= (UBI32_ETH_VP_INT_RX | UBI32_ETH_VP_INT_TX);
46039 + if ((priv->rx_tail != priv->regs->rx_out) || (priv->tx_tail != priv->regs->tx_out)) {
46040 + if (napi_reschedule(napi)) {
46041 + priv->regs->int_mask = 0;
46049 +static void ubi32_eth_do_tasklet(unsigned long arg)
46051 + struct net_device *dev = (struct net_device *)arg;
46052 + struct ubi32_eth_private *priv = netdev_priv(dev);
46054 + if (priv->tx_tail != priv->regs->tx_out) {
46055 + ubi32_eth_tx_done(dev);
46058 + /* always call receive to process new RX frame as well as replenish RX buffers */
46059 + ubi32_eth_receive(dev, UBI32_RX_BOUND);
46061 + priv->regs->int_mask |= (UBI32_ETH_VP_INT_RX | UBI32_ETH_VP_INT_TX);
46062 + if ((priv->rx_tail != priv->regs->rx_out) || (priv->tx_tail != priv->regs->tx_out)) {
46063 + priv->regs->int_mask = 0;
46064 + tasklet_schedule(&priv->tsk);
46069 +#if defined(UBICOM32_USE_POLLING)
46070 +static struct timer_list eth_poll_timer;
46072 +static void ubi32_eth_poll(unsigned long arg)
46074 + struct net_device *dev;
46075 + struct ubi32_eth_private *priv;
46078 + for (i = 0; i < UBI32_ETH_NUM_OF_DEVICES; i++) {
46079 + dev = ubi32_eth_devices[i];
46080 + if (dev && (dev->flags & IFF_UP)) {
46081 + priv = netdev_priv(dev);
46082 +#ifdef UBICOM32_USE_NAPI
46083 + napi_schedule(&priv->napi);
46085 + tasklet_schedule(&priv->tsk);
46090 + eth_poll_timer.expires = jiffies + 2;
46091 + add_timer(ð_poll_timer);
46095 +static irqreturn_t ubi32_eth_interrupt(int irq, void *dev_id)
46097 + struct ubi32_eth_private *priv;
46099 + struct net_device *dev = (struct net_device *)dev_id;
46100 + BUG_ON(irq != dev->irq);
46102 + priv = netdev_priv(dev);
46103 + if (unlikely(!(priv->regs->int_status & priv->regs->int_mask))) {
46108 + * Disable port interrupt
46110 +#ifdef UBICOM32_USE_NAPI
46111 + if (napi_schedule_prep(&priv->napi)) {
46112 + priv->regs->int_mask = 0;
46113 + __napi_schedule(&priv->napi);
46116 + priv->regs->int_mask = 0;
46117 + tasklet_schedule(&priv->tsk);
46119 + return IRQ_HANDLED;
46126 +static int ubi32_eth_open(struct net_device *dev)
46128 + struct ubi32_eth_private *priv = netdev_priv(dev);
46131 + printk(KERN_INFO "eth open %s\n",dev->name);
46132 +#ifndef UBICOM32_USE_POLLING
46133 + /* request_region() */
46134 + err = request_irq(dev->irq, ubi32_eth_interrupt, IRQF_DISABLED, dev->name, dev);
46136 + printk(KERN_WARNING "fail to request_irq %d\n",err);
46140 +#ifdef UBICOM32_USE_NAPI
46141 + napi_enable(&priv->napi);
46143 + tasklet_init(&priv->tsk, ubi32_eth_do_tasklet, (unsigned long)dev);
46146 + /* call receive to supply RX buffers */
46147 + ubi32_eth_receive(dev, RX_DMA_MAX_QUEUE_SIZE);
46149 + /* check phy status and call netif_carrier_on */
46150 + ubi32_eth_vp_rxtx_enable(dev);
46151 + netif_start_queue(dev);
46155 +static int ubi32_eth_close(struct net_device *dev)
46157 + struct ubi32_eth_private *priv = netdev_priv(dev);
46158 + volatile void *pdata;
46159 + struct sk_buff *skb;
46161 +#ifndef UBICOM32_USE_POLLING
46162 + free_irq(dev->irq, dev);
46164 + netif_stop_queue(dev); /* can't transmit any more */
46165 +#ifdef UBICOM32_USE_NAPI
46166 + napi_disable(&priv->napi);
46168 + tasklet_kill(&priv->tsk);
46170 + ubi32_eth_vp_rxtx_stop(dev);
46175 + while (priv->rx_tail != priv->regs->rx_in) {
46176 + pdata = priv->regs->rx_dma_ring[priv->rx_tail];
46177 + skb = container_of((void *)pdata, struct sk_buff, cb);
46178 + priv->regs->rx_dma_ring[priv->rx_tail] = NULL;
46179 + dev_kfree_skb_any(skb);
46180 + priv->rx_tail = ((priv->rx_tail + 1) & RX_DMA_RING_MASK);
46182 + priv->regs->rx_in = 0;
46183 + priv->regs->rx_out = priv->regs->rx_in;
46184 + priv->rx_tail = priv->regs->rx_in;
46189 + BUG_ON(priv->regs->tx_out != priv->regs->tx_in);
46190 + ubi32_eth_tx_done(dev);
46191 + BUG_ON(priv->tx_tail != priv->regs->tx_in);
46192 + priv->regs->tx_in = 0;
46193 + priv->regs->tx_out = priv->regs->tx_in;
46194 + priv->tx_tail = priv->regs->tx_in;
46200 + * ubi32_eth_set_config
46202 +static int ubi32_eth_set_config(struct net_device *dev, struct ifmap *map)
46204 + /* if must to down to config it */
46205 + printk(KERN_INFO "set_config %x\n", dev->flags);
46206 + if (dev->flags & IFF_UP)
46209 + /* I/O and IRQ can not be changed */
46210 + if (map->base_addr != dev->base_addr) {
46211 + printk(KERN_WARNING "%s: Can't change I/O address\n", dev->name);
46212 + return -EOPNOTSUPP;
46215 +#ifndef UBICOM32_USE_POLLING
46216 + if (map->irq != dev->irq) {
46217 + printk(KERN_WARNING "%s: Can't change IRQ\n", dev->name);
46218 + return -EOPNOTSUPP;
46222 + /* ignore other fields */
46226 +static int ubi32_eth_start_xmit(struct sk_buff *skb, struct net_device *dev)
46228 + struct ubi32_eth_private *priv = netdev_priv(dev);
46229 + struct ubi32_eth_dma_desc *desc = NULL;
46230 + unsigned short space, tx_in;
46232 + tx_in = priv->regs->tx_in;
46234 + dev->trans_start = jiffies; /* save the timestamp */
46235 + space = TX_DMA_RING_MASK - ((TX_DMA_RING_SIZE + tx_in - priv->tx_tail) & TX_DMA_RING_MASK);
46237 + if (unlikely(space == 0)) {
46238 + if (!(priv->regs->status & UBI32_ETH_VP_STATUS_TX_Q_FULL)) {
46239 + spin_lock(&priv->lock);
46240 + if (!(priv->regs->status & UBI32_ETH_VP_STATUS_TX_Q_FULL)) {
46241 + priv->regs->status |= UBI32_ETH_VP_STATUS_TX_Q_FULL;
46242 + priv->vp_stats.tx_q_full_cnt++;
46243 + netif_stop_queue(dev);
46245 + spin_unlock(&priv->lock);
46248 + /* give both HW and this driver an extra trigger */
46249 + priv->regs->int_mask |= UBI32_ETH_VP_INT_TX;
46250 +#ifndef UBICOM32_USE_POLLING
46251 + ubicom32_set_interrupt(dev->irq);
46253 + ubicom32_set_interrupt(priv->vp_int_bit);
46255 + return NETDEV_TX_BUSY;
46258 + /*still have room */
46259 + desc = (struct ubi32_eth_dma_desc *)skb->cb;
46260 + desc->data_pointer = skb->data;
46261 + desc->data_len = skb->len;
46262 + priv->regs->tx_dma_ring[tx_in] = desc;
46263 + tx_in = ((tx_in + 1) & TX_DMA_RING_MASK);
46265 + priv->regs->tx_in = tx_in;
46266 + /* kick the HRT */
46267 + ubicom32_set_interrupt(priv->vp_int_bit);
46269 + return NETDEV_TX_OK;
46273 + * Deal with a transmit timeout.
46275 +static void ubi32_eth_tx_timeout (struct net_device *dev)
46277 + struct ubi32_eth_private *priv = netdev_priv(dev);
46278 + dev->stats.tx_errors++;
46279 + priv->regs->int_mask |= UBI32_ETH_VP_INT_TX;
46280 +#ifndef UBICOM32_USE_POLLING
46281 + ubicom32_set_interrupt(dev->irq);
46283 + ubicom32_set_interrupt(priv->vp_int_bit);
46286 +static int ubi32_eth_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
46288 + struct ubi32_eth_private *priv = netdev_priv(dev);
46289 + struct mii_ioctl_data *data = if_mii(rq);
46291 + printk(KERN_INFO "ioctl %s, %d\n", dev->name, cmd);
46293 + case SIOCGMIIPHY:
46294 + data->phy_id = 0;
46297 + case SIOCGMIIREG:
46298 + if ((data->reg_num & 0x1F) == MII_BMCR) {
46299 + /* Make up MII control register value from what we know */
46300 + data->val_out = 0x0000
46301 + | ((priv->regs->status & UBI32_ETH_VP_STATUS_DUPLEX)
46302 + ? BMCR_FULLDPLX : 0)
46303 + | ((priv->regs->status & UBI32_ETH_VP_STATUS_SPEED100)
46304 + ? BMCR_SPEED100 : 0)
46305 + | ((priv->regs->status & UBI32_ETH_VP_STATUS_SPEED1000)
46306 + ? BMCR_SPEED1000 : 0);
46307 + } else if ((data->reg_num & 0x1F) == MII_BMSR) {
46308 + /* Make up MII status register value from what we know */
46310 + (BMSR_100FULL|BMSR_100HALF|BMSR_10FULL|BMSR_10HALF)
46311 + | ((priv->regs->status & UBI32_ETH_VP_STATUS_LINK)
46312 + ? BMSR_LSTATUS : 0);
46318 + case SIOCSMIIREG:
46319 + return -EOPNOTSUPP;
46323 + return -EOPNOTSUPP;
46330 + * Return statistics to the caller
46332 +static struct net_device_stats *ubi32_eth_get_stats(struct net_device *dev)
46334 + return &dev->stats;
46338 +static int ubi32_eth_change_mtu(struct net_device *dev, int new_mtu)
46340 + struct ubi32_eth_private *priv = netdev_priv(dev);
46341 + unsigned long flags;
46343 + if ((new_mtu < 68) || (new_mtu > 1500))
46346 + spin_lock_irqsave(&priv->lock, flags);
46347 + dev->mtu = new_mtu;
46348 + spin_unlock_irqrestore(&priv->lock, flags);
46349 + printk(KERN_INFO "set mtu to %d", new_mtu);
46354 + * ubi32_eth_cleanup: unload the module
46356 +void ubi32_eth_cleanup(void)
46358 + struct ubi32_eth_private *priv;
46359 + struct net_device *dev;
46362 + for (i = 0; i < UBI32_ETH_NUM_OF_DEVICES; i++) {
46363 + dev = ubi32_eth_devices[i];
46365 + priv = netdev_priv(dev);
46366 + kfree(priv->regs->tx_dma_ring);
46367 + unregister_netdev(dev);
46368 + free_netdev(dev);
46369 + ubi32_eth_devices[i] = NULL;
46374 +int ubi32_eth_init_module(void)
46376 + struct ethtionode *eth_node;
46377 + struct net_device *dev;
46378 + struct ubi32_eth_private *priv;
46382 + * Device allocation.
46385 + for (i = 0; i < UBI32_ETH_NUM_OF_DEVICES; i++) {
46387 + * See if the eth_vp is in the device tree.
46389 + eth_node = (struct ethtionode *)devtree_find_node(eth_if_name[i]);
46391 + printk(KERN_INFO "%s does not exist\n", eth_if_name[i]);
46395 + eth_node->tx_dma_ring = (struct ubi32_eth_dma_desc **)kmalloc(
46396 + sizeof(struct ubi32_eth_dma_desc *) *
46397 + (TX_DMA_RING_SIZE + RX_DMA_RING_SIZE),
46398 + GFP_ATOMIC | __GFP_NOWARN | __GFP_NORETRY | GFP_DMA);
46400 + if (eth_node->tx_dma_ring == NULL) {
46401 + eth_node->tx_dma_ring = (struct ubi32_eth_dma_desc **)kmalloc(
46402 + sizeof(struct ubi32_eth_dma_desc *) *
46403 + (TX_DMA_RING_SIZE + RX_DMA_RING_SIZE), GFP_KERNEL);
46404 + printk(KERN_INFO "fail to allocate from OCM\n");
46407 + if (!eth_node->tx_dma_ring) {
46411 + eth_node->rx_dma_ring = eth_node->tx_dma_ring + TX_DMA_RING_SIZE;
46412 + eth_node->tx_sz = TX_DMA_RING_SIZE - 1;
46413 + eth_node->rx_sz = RX_DMA_RING_SIZE - 1;
46415 + dev = alloc_etherdev(sizeof(struct ubi32_eth_private));
46417 + kfree(eth_node->tx_dma_ring);
46421 + priv = netdev_priv(dev);
46425 + * This just fill in some default Ubicom MAC address
46427 + memcpy(dev->dev_addr, mac_addr[i], ETH_ALEN);
46428 + memset(dev->broadcast, 0xff, ETH_ALEN);
46430 + priv->regs = eth_node;
46431 + priv->regs->command = 0;
46432 + priv->regs->int_mask = 0;
46433 + priv->regs->int_status = 0;
46434 + priv->regs->tx_out = 0;
46435 + priv->regs->rx_out = 0;
46436 + priv->regs->tx_in = 0;
46437 + priv->regs->rx_in = 0;
46438 + priv->rx_tail = 0;
46439 + priv->tx_tail = 0;
46441 + priv->vp_int_bit = eth_node->dn.sendirq;
46442 + dev->irq = eth_node->dn.recvirq;
46444 + spin_lock_init(&priv->lock);
46446 + dev->open = ubi32_eth_open;
46447 + dev->stop = ubi32_eth_close;
46448 + dev->hard_start_xmit = ubi32_eth_start_xmit;
46449 + dev->tx_timeout = ubi32_eth_tx_timeout;
46450 + dev->watchdog_timeo = UBI32_ETH_VP_TX_TIMEOUT;
46452 + dev->set_config = ubi32_eth_set_config;
46453 + dev->do_ioctl = ubi32_eth_ioctl;
46454 + dev->get_stats = ubi32_eth_get_stats;
46455 + dev->change_mtu = ubi32_eth_change_mtu;
46456 +#ifdef UBICOM32_USE_NAPI
46457 + netif_napi_add(dev, &priv->napi, ubi32_eth_napi_poll, UBI32_ETH_NAPI_WEIGHT);
46459 + err = register_netdev(dev);
46461 + printk(KERN_WARNING "Failed to register netdev %s\n", eth_if_name[i]);
46462 + //release_region();
46463 + free_netdev(dev);
46464 + kfree(eth_node->tx_dma_ring);
46468 + ubi32_eth_devices[i] = dev;
46469 + printk(KERN_INFO "%s vp_base:0x%p, tio_int:%d irq:%d feature:0x%lx\n",
46470 + dev->name, priv->regs, eth_node->dn.sendirq, dev->irq, dev->features);
46474 + ubi32_eth_cleanup();
46478 + if (!ubi32_eth_devices[0] && !ubi32_eth_devices[1]) {
46482 +#if defined(UBICOM32_USE_POLLING)
46483 + init_timer(ð_poll_timer);
46484 + eth_poll_timer.function = ubi32_eth_poll;
46485 + eth_poll_timer.data = (unsigned long)0;
46486 + eth_poll_timer.expires = jiffies + 2;
46487 + add_timer(ð_poll_timer);
46493 +module_init(ubi32_eth_init_module);
46494 +module_exit(ubi32_eth_cleanup);
46496 +MODULE_AUTHOR("Kan Yan, Greg Ren");
46497 +MODULE_LICENSE("GPL");
46499 +++ b/drivers/net/ubi32-eth.h
46502 + * drivers/net/ubi32-eth.h
46503 + * Ubicom32 ethernet TIO interface driver definitions.
46505 + * (C) Copyright 2009, Ubicom, Inc.
46507 + * This file is part of the Ubicom32 Linux Kernel Port.
46509 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
46510 + * it and/or modify it under the terms of the GNU General Public License
46511 + * as published by the Free Software Foundation, either version 2 of the
46512 + * License, or (at your option) any later version.
46514 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
46515 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
46516 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
46517 + * the GNU General Public License for more details.
46519 + * You should have received a copy of the GNU General Public License
46520 + * along with the Ubicom32 Linux Kernel Port. If not,
46521 + * see <http://www.gnu.org/licenses/>.
46523 + * Ubicom32 implementation derived from (with many thanks):
46528 +#ifndef _UBI32_ETH_H
46529 +#define _UBI32_ETH_H
46531 +#include <asm/devtree.h>
46533 +#define UBI32_ETH_NUM_OF_DEVICES 2
46536 + * Number of bytes trashed beyond the packet data.
46538 +#define UBI32_ETH_TRASHED_MEMORY (CACHE_LINE_SIZE + ETH_HLEN - 1)
46541 + * Linux already reserves NET_SKB_PAD bytes of headroom in each sk_buff.
46542 + * We want to be able to reserve at least one cache line to align Ethernet
46543 + * and IP header to cache line.
46544 + * Note that the TIO expects a CACHE_LINE_SIZE - ETH_HLEN aligned Ethernet
46545 + * header, while satisfies NET_IP_ALIGN (= 2) automatically.
46546 + * (NET_SKB_PAD is 16, NET_IP_ALIGN is 2, CACHE_LINE_SIZE is 32).
46547 + * You can add more space by making UBI32_ETH_RESERVE_EXTRA != 0.
46549 +#define UBI32_ETH_RESERVE_EXTRA (1 * CACHE_LINE_SIZE)
46550 +#define UBI32_ETH_RESERVE_SPACE (UBI32_ETH_RESERVE_EXTRA + CACHE_LINE_SIZE)
46552 +struct ubi32_eth_dma_desc {
46553 + volatile void *data_pointer; /* pointer to the buffer */
46554 + volatile u16 buffer_len; /* the buffer size */
46555 + volatile u16 data_len; /* actual frame length */
46556 + volatile u32 status; /* bit0: status to be update by VP; bit[31:1] time stamp */
46559 +#define TX_DMA_RING_SIZE (1<<8)
46560 +#define TX_DMA_RING_MASK (TX_DMA_RING_SIZE - 1)
46561 +#define RX_DMA_RING_SIZE (1<<8)
46562 +#define RX_DMA_RING_MASK (RX_DMA_RING_SIZE - 1)
46564 +#define RX_DMA_MAX_QUEUE_SIZE (RX_DMA_RING_SIZE - 1) /* no more than (RX_DMA_RING_SIZE - 1) */
46565 +#define RX_MAX_PKT_SIZE (ETH_DATA_LEN + ETH_HLEN + VLAN_HLEN)
46566 +#define RX_MIN_PKT_SIZE ETH_ZLEN
46567 +#define RX_BUF_SIZE (RX_MAX_PKT_SIZE + VLAN_HLEN) /* allow double VLAN tag */
46569 +#define UBI32_ETH_VP_TX_TIMEOUT (10*HZ)
46571 +struct ubi32_eth_vp_stats {
46572 + u32 rx_alloc_err;
46573 + u32 tx_q_full_cnt;
46574 + u32 rx_q_full_cnt;
46578 +struct ubi32_eth_private {
46579 + struct net_device *dev;
46580 + struct ubi32_eth_vp_stats vp_stats;
46582 +#ifdef UBICOM32_USE_NAPI
46583 + struct napi_struct napi;
46585 + struct tasklet_struct tsk;
46587 + struct ethtionode *regs;
46593 +struct ethtionode {
46594 + struct devtree_node dn;
46595 + volatile u16 command;
46596 + volatile u16 status;
46597 + volatile u16 int_mask; /* interrupt mask */
46598 + volatile u16 int_status; /* interrupt mask */
46599 + volatile u16 tx_in; /* owned by driver */
46600 + volatile u16 tx_out; /* owned by vp */
46601 + volatile u16 rx_in; /* owned by driver */
46602 + volatile u16 rx_out; /* owned by vp */
46603 + u16 tx_sz; /* owned by driver */
46604 + u16 rx_sz; /* owned by driver */
46605 + struct ubi32_eth_dma_desc **tx_dma_ring;
46606 + struct ubi32_eth_dma_desc **rx_dma_ring;
46609 +#define UBI32_ETH_VP_STATUS_LINK (1<<0)
46610 +#define UBI32_ETH_VP_STATUS_SPEED100 (0x1<<1)
46611 +#define UBI32_ETH_VP_STATUS_SPEED1000 (0x1<<2)
46612 +#define UBI32_ETH_VP_STATUS_DUPLEX (0x1<<3)
46613 +#define UBI32_ETH_VP_STATUS_FLOW_CTRL (0x1<<4)
46615 +#define UBI32_ETH_VP_STATUS_RX_STATE (0x1<<5)
46616 +#define UBI32_ETH_VP_STATUS_TX_STATE (0x1<<6)
46618 +#define UBI32_ETH_VP_STATUS_TX_Q_FULL (1<<8)
46620 +#define UBI32_ETH_VP_INT_RX (1<<0)
46621 +#define UBI32_ETH_VP_INT_TX (1<<1)
46623 +#define UBI32_ETH_VP_CMD_RX_ENABLE (1<<0)
46624 +#define UBI32_ETH_VP_CMD_TX_ENABLE (1<<1)
46626 +#define UBI32_ETH_VP_RX_OK (1<<0)
46627 +#define UBI32_ETH_VP_TX_OK (1<<1)
46629 +#define UBI32_TX_BOUND TX_DMA_RING_SIZE
46630 +#define UBI32_RX_BOUND 64
46631 +#define UBI32_ETH_NAPI_WEIGHT 64 /* for GigE */
46633 --- a/drivers/net/usb/asix.c
46634 +++ b/drivers/net/usb/asix.c
46635 @@ -319,14 +319,33 @@ static int asix_rx_fixup(struct usbnet *
46636 /* get the packet length */
46637 size = (u16) (header & 0x0000ffff);
46639 - if ((skb->len) - ((size + 1) & 0xfffe) == 0)
46640 + if ((skb->len) - ((size + 1) & 0xfffe) == 0) {
46641 +#ifndef HAVE_EFFICIENT_UNALIGNED_ACCESS
46642 + if (((u32)packet & 0x02) == 0) {
46643 + memmove(packet - 2, packet, size);
46651 if (size > ETH_FRAME_LEN) {
46652 deverr(dev,"asix_rx_fixup() Bad RX Length %d", size);
46655 ax_skb = skb_clone(skb, GFP_ATOMIC);
46657 +#ifndef HAVE_EFFICIENT_UNALIGNED_ACCESS
46658 + if (((u32)packet & 0x02) == 0) {
46659 + memmove(packet - 2, packet, size);
46660 + ax_skb->data = packet - 2;
46662 + ax_skb->data = packet;
46665 + ax_skb->data = packet;
46667 ax_skb->len = size;
46668 ax_skb->data = packet;
46669 skb_set_tail_pointer(ax_skb, size);
46670 @@ -1125,13 +1144,19 @@ static int ax88178_link_reset(struct usb
46671 mode = AX88178_MEDIUM_DEFAULT;
46673 if (ecmd.speed == SPEED_1000)
46674 +#ifdef HAVE_EFFICIENT_UNALIGNED_ACCESS
46675 mode |= AX_MEDIUM_GM;
46677 + mode |= AX_MEDIUM_GM | AX_MEDIUM_ENCK;
46679 else if (ecmd.speed == SPEED_100)
46680 mode |= AX_MEDIUM_PS;
46682 mode &= ~(AX_MEDIUM_PS | AX_MEDIUM_GM);
46684 +#ifdef HAVE_EFFICIENT_UNALIGNED_ACCESS
46685 mode |= AX_MEDIUM_ENCK;
46688 if (ecmd.duplex == DUPLEX_FULL)
46689 mode |= AX_MEDIUM_FD;
46690 --- a/drivers/oprofile/cpu_buffer.c
46691 +++ b/drivers/oprofile/cpu_buffer.c
46692 @@ -328,10 +328,10 @@ static inline void oprofile_end_trace(st
46696 -__oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs,
46697 - unsigned long event, int is_kernel)
46698 +__oprofile_add_ext_sample_cpu(unsigned long pc, struct pt_regs * const regs,
46699 + unsigned long event, int is_kernel, int cpu)
46701 - struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(cpu_buffer);
46702 + struct oprofile_cpu_buffer *cpu_buf = &per_cpu(cpu_buffer, cpu);
46703 unsigned long backtrace = oprofile_backtrace_depth;
46706 @@ -353,7 +353,8 @@ __oprofile_add_ext_sample(unsigned long
46707 void oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs,
46708 unsigned long event, int is_kernel)
46710 - __oprofile_add_ext_sample(pc, regs, event, is_kernel);
46711 + __oprofile_add_ext_sample_cpu(pc, regs, event,
46712 + is_kernel, smp_processor_id());
46715 void oprofile_add_sample(struct pt_regs * const regs, unsigned long event)
46716 @@ -361,7 +362,8 @@ void oprofile_add_sample(struct pt_regs
46717 int is_kernel = !user_mode(regs);
46718 unsigned long pc = profile_pc(regs);
46720 - __oprofile_add_ext_sample(pc, regs, event, is_kernel);
46721 + __oprofile_add_ext_sample_cpu(pc, regs, event,
46722 + is_kernel, smp_processor_id());
46726 --- a/drivers/pci/Makefile
46727 +++ b/drivers/pci/Makefile
46728 @@ -44,8 +44,8 @@ obj-$(CONFIG_PPC) += setup-bus.o
46729 obj-$(CONFIG_MIPS) += setup-bus.o setup-irq.o
46730 obj-$(CONFIG_X86_VISWS) += setup-irq.o
46731 obj-$(CONFIG_MN10300) += setup-bus.o
46732 +obj-$(CONFIG_UBICOM32) += setup-bus.o setup-irq.o
46735 # ACPI Related PCI FW Functions
46737 obj-$(CONFIG_ACPI) += pci-acpi.o
46738 --- a/drivers/serial/Kconfig
46739 +++ b/drivers/serial/Kconfig
46740 @@ -871,6 +871,57 @@ config SERIAL_UARTLITE_CONSOLE
46741 console (the system console is the device which receives all kernel
46742 messages and warnings and which allows logins in single user mode).
46744 +config SERIAL_UBI32_UARTTIO
46745 + tristate "Ubicom UARTTIO support"
46746 + depends on UBICOM32=y
46747 + select SERIAL_CORE
46750 + Add support for the Ubicom virtual peripherial serial interface.
46752 +config SERIAL_UBI32_UARTTIO_NR_UARTS
46753 + int "Maximum number of UARTTIO virtual serial ports"
46754 + depends on SERIAL_UBI32_UARTTIO
46757 + Set this to the maximum number of serial ports you want the driver to support.
46759 +config SERIAL_UBI32_UARTTIO_CONSOLE
46760 + tristate "Ubicom UARTTIO console support"
46761 + depends on SERIAL_UBI32_UARTTIO=y
46762 + select SERIAL_CORE_CONSOLE
46765 + Add support for console on the Ubicom virtual peripherial serial interface.
46767 +config SERIAL_UBI32_SERDES
46768 + bool "Ubicom serial port support"
46769 + depends on UBICOM32=y
46770 + select SERIAL_CORE
46773 + Add support for the Ubicom serial interface.
46775 +config SERIAL_UBI32_SERDES_CONSOLE
46776 + bool "Ubicom serial console support"
46777 + depends on SERIAL_UBI32_SERDES=y
46778 + select SERIAL_CORE_CONSOLE
46781 +config SERIAL_UBI32_MAILBOX
46782 + bool "Ubicom mailbox support"
46783 + depends on UBICOM32=y
46784 + select SERIAL_CORE
46787 + Add support for the Ubicom mailbox interface.
46789 +config SERIAL_UBI32_MAILBOX_CONSOLE
46790 + bool "Ubicom mailbox console support"
46791 + depends on SERIAL_UBI32_MAILBOX=y
46792 + select SERIAL_CORE_CONSOLE
46795 config SERIAL_SUNCORE
46798 --- a/drivers/serial/Makefile
46799 +++ b/drivers/serial/Makefile
46800 @@ -77,3 +77,6 @@ obj-$(CONFIG_SERIAL_OF_PLATFORM_NWPSERIA
46801 obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o
46802 obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o
46803 obj-$(CONFIG_SERIAL_QE) += ucc_uart.o
46804 +obj-$(CONFIG_SERIAL_UBI32_SERDES) += ubi32_serdes.o
46805 +obj-$(CONFIG_SERIAL_UBI32_UARTTIO) += ubi32_uarttio.o
46806 +obj-$(CONFIG_SERIAL_UBI32_MAILBOX) += ubi32_mailbox.o
46808 +++ b/drivers/serial/ubi32_mailbox.c
46811 + * drivers/serial/ubi32_mailbox.c
46812 + * Ubicom32 On-Chip Mailbox Driver
46814 + * (C) Copyright 2009, Ubicom, Inc.
46816 + * This file is part of the Ubicom32 Linux Kernel Port.
46818 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
46819 + * it and/or modify it under the terms of the GNU General Public License
46820 + * as published by the Free Software Foundation, either version 2 of the
46821 + * License, or (at your option) any later version.
46823 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
46824 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
46825 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
46826 + * the GNU General Public License for more details.
46828 + * You should have received a copy of the GNU General Public License
46829 + * along with the Ubicom32 Linux Kernel Port. If not,
46830 + * see <http://www.gnu.org/licenses/>.
46832 + * Ubicom32 implementation derived from (with many thanks):
46837 +#include <linux/module.h>
46838 +#include <linux/ioport.h>
46839 +#include <linux/init.h>
46840 +#include <linux/console.h>
46841 +#include <linux/sysrq.h>
46842 +#include <linux/platform_device.h>
46843 +#include <linux/tty.h>
46844 +#include <linux/tty_flip.h>
46845 +#include <linux/serial_core.h>
46847 +#include <asm/ip5000.h>
46849 +#define SERIAL_UBICOM_BAUDRATE 115200
46850 +#define SERIAL_UBICOM_DATA_BIT 8 /* Fixed parameter - do not change */
46851 +#define SERIAL_UBICOM_PAR_BIT 0 /* Fixed parameter - do not change */
46852 +#define SERIAL_UBICOM_STOP_BIT 1 /* Fixed parameter - do not change */
46854 +/* UART name and device definitions */
46855 +#define UBI32_MAILBOX_NAME "ttyUM" // XXX
46856 +#define UBI32_MAILBOX_MAJOR 207 // XXX
46857 +#define UBI32_MAILBOX_MINOR 64
46859 +#define PORT_UBI32_MAILBOX 1235
46860 +#define NR_PORTS 1
46862 +#define get_sclk() 0
46864 +struct ubi32_mailbox_port {
46865 + struct uart_port port;
46867 + * NOTE (rkeller):
46868 + * the uart port is wrapped in another structure in case we need to hold more state than
46869 + * what we can hold in the uart_port.
46870 + * Not sure if we need this, I took over the concept from the blackfin driver.
46872 +} ubi32_mailbox_ports[NR_PORTS];
46874 +struct ubi32_mailbox_resource {
46875 + int uart_base_addr;
46877 +} ubi32_mailbox_resource[NR_PORTS] = {
46879 + * uart_base_addr has to be non-NULL because it is put in the uart_port membase.
46880 + * If membase if null the kernel skips the configuration and our port_type never gets set.
46882 + {ISD_MAILBOX_BASE, ISD_MAILBOX_INT}
46885 +static volatile struct ubicom32_isd_mailbox {
46886 + volatile u32_t in;
46887 + volatile u32_t out;
46888 + volatile u32_t status;
46889 +} *ubi32_mailbox = (struct ubicom32_isd_mailbox *)ISD_MAILBOX_BASE;
46891 +static void ubi32_mailbox_tx_chars(struct ubi32_mailbox_port *uart);
46893 +static void ubi32_mailbox_mctrl_check(struct ubi32_mailbox_port *uart);
46898 +static int mailbox_console_flg = TRUE;
46899 +static int num_timeouts = 0;
46902 + * dummy functions and defined to be able to compile the Blackfin code
46904 +#define UART_GET_LSR(port) (1)
46905 +#define UART_PUT_LSR(port, bits)
46906 +#define UART_CLEAR_LSR(port) (1)
46915 +#define UART_GET_LCR(port) (1)
46916 +#define UART_PUT_LCR(port, bits)
46923 +#define UART_GET_IER(port) (1)
46924 +#define UART_SET_IER(port, bits)
46925 +#define UART_CLEAR_IER(port, bits)
46928 +#define UART_GET_CHAR(port) ubi32_mailbox_get_char()
46929 +#define UART_PUT_CHAR(port, ch) ubi32_mailbox_put_char(ch)
46931 +#define UART_GET_DLL(port) 0
46932 +#define UART_PUT_DLL(port, ch)
46933 +#define UART_GET_DLH(port) 0
46934 +#define UART_PUT_DLH(port, ch)
46935 +#define UART_GET_GCTL(port) (0)
46936 +#define UART_PUT_GCTL(port, ch)
46940 + * ubi32_mailbox_get_char_avail()
46942 +static int ubi32_mailbox_get_char_avail(void)
46944 + return !(ubi32_mailbox->status & ISD_MAILBOX_STATUS_IN_EMPTY);
46948 + * ubi32_mailbox_get_char()
46950 +static u32_t ubi32_mailbox_get_char(void)
46952 + if (mailbox_console_flg == TRUE) {
46954 + * Mailbox console is connected.
46956 + while (ubi32_mailbox->status & ISD_MAILBOX_STATUS_IN_EMPTY);
46957 + return ubi32_mailbox->in & 0xff;
46961 + * Mailbox console was not connected.
46963 + if (ubi32_mailbox->status & ISD_MAILBOX_STATUS_IN_EMPTY) {
46968 + * Mailbox console is connecting.
46970 + mailbox_console_flg = TRUE;
46971 + num_timeouts = 0;
46972 + return ubi32_mailbox->in & 0xff;
46975 +#define MAILBOX_MAX_ATTEMPTS 1000000
46976 +#define MAILBOX_MAX_TIMEOUTS 5
46978 + * ubi32_mailbox_put_char()
46980 +static void ubi32_mailbox_put_char(u32_t v)
46983 + * Wait to be able to output.
46985 + u32_t num_attempts = 0;
46987 + if(mailbox_console_flg == TRUE) {
46988 + while(num_attempts++ < MAILBOX_MAX_ATTEMPTS) {
46989 + if(ubi32_mailbox->status & ISD_MAILBOX_STATUS_OUT_EMPTY) {
46995 + * If timed out more than 5 times on send, mailbox console is disconnected now.
46997 + if (num_attempts > MAILBOX_MAX_ATTEMPTS) {
46998 + if (num_timeouts++ > MAILBOX_MAX_TIMEOUTS) {
46999 + mailbox_console_flg = FALSE;
47005 + "pipe_flush 0 \n\t"
47006 + "pipe_flush 0 \n\t"
47007 + "pipe_flush 0 \n\t"
47008 + "pipe_flush 0 \n\t"
47009 + "pipe_flush 0 \n\t"
47010 + "pipe_flush 0 \n\t"
47011 + "pipe_flush 0 \n\t"
47014 + ubi32_mailbox->out = v & 0xff;
47017 +static void ubi32_mailbox_hw_init(struct ubi32_mailbox_port *uart)
47019 +// NOTE: It does not do any good to do these here because we are running on the linux hardware thread,
47020 +// and these have to be called on the ldsr thread.
47021 +// ubicom32_clear_interrupt(ISD_MAILBOX_INT);
47022 +// ubicom32_enable_interrupt(ISD_MAILBOX_INT);
47026 + * interrupts are disabled on entry
47028 +static void ubi32_mailbox_stop_tx(struct uart_port *port)
47030 +// struct ubi32_mailbox_port *uart = (struct ubi32_mailbox_port *)port;
47031 +// struct circ_buf *xmit = &uart->port.info->xmit;
47033 + while (!(UART_GET_LSR(uart) & TEMT))
47036 + /* Clear TFI bit */
47037 + UART_PUT_LSR(uart, TFI);
47038 + UART_CLEAR_IER(uart, ETBEI);
47042 + * port is locked and interrupts are disabled
47044 +static void ubi32_mailbox_start_tx(struct uart_port *port)
47046 + struct ubi32_mailbox_port *uart = (struct ubi32_mailbox_port *)port;
47048 + UART_SET_IER(uart, ETBEI);
47050 + ubi32_mailbox_tx_chars(uart);
47054 + * Interrupts are enabled
47056 +static void ubi32_mailbox_stop_rx(struct uart_port *port)
47058 +// struct ubi32_mailbox_port *uart = (struct ubi32_mailbox_port *)port;
47059 + UART_CLEAR_IER(uart, ERBFI);
47063 + * Set the modem control timer to fire immediately.
47065 +static void ubi32_mailbox_enable_ms(struct uart_port *port)
47069 +static void ubi32_mailbox_rx_chars(struct ubi32_mailbox_port *uart)
47071 + struct uart_info *info = uart->port.info;
47072 + struct tty_struct *tty = info->port.tty;
47073 + unsigned int status, ch, flg;
47075 + status = 0; // XXX? UART_GET_LSR(uart);
47076 + UART_CLEAR_LSR(uart);
47078 + ch = UART_GET_CHAR(uart);
47083 + uart->port.icount.rx++;
47085 + if (status & BI) {
47086 + uart->port.icount.brk++;
47087 + if (uart_handle_break(&uart->port))
47088 + goto ignore_char;
47089 + status &= ~(PE | FE);
47092 + uart->port.icount.parity++;
47094 + uart->port.icount.overrun++;
47096 + uart->port.icount.frame++;
47098 + status &= uart->port.read_status_mask;
47102 + else if (status & PE)
47103 + flg = TTY_PARITY;
47104 + else if (status & FE)
47107 + flg = TTY_NORMAL;
47109 + if (uart_handle_sysrq_char(&uart->port, ch))
47110 + goto ignore_char;
47112 + uart_insert_char(&uart->port, status, OE, ch, flg);
47115 + tty_flip_buffer_push(tty);
47118 +static void ubi32_mailbox_tx_chars(struct ubi32_mailbox_port *uart)
47120 + struct circ_buf *xmit = &uart->port.info->xmit;
47122 + if (uart->port.x_char) {
47123 + UART_PUT_CHAR(uart, uart->port.x_char);
47124 + uart->port.icount.tx++;
47125 + uart->port.x_char = 0;
47128 + * Check the modem control lines before
47129 + * transmitting anything.
47131 + ubi32_mailbox_mctrl_check(uart);
47133 + if (uart_circ_empty(xmit) || uart_tx_stopped(&uart->port)) {
47134 + ubi32_mailbox_stop_tx(&uart->port);
47138 + while ((UART_GET_LSR(uart) & THRE) && xmit->tail != xmit->head) {
47139 + UART_PUT_CHAR(uart, xmit->buf[xmit->tail]);
47140 + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
47141 + uart->port.icount.tx++;
47145 + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
47146 + uart_write_wakeup(&uart->port);
47148 + if (uart_circ_empty(xmit))
47149 + ubi32_mailbox_stop_tx(&uart->port);
47152 +static irqreturn_t ubi32_mailbox_isr(int irq, void *dev_id)
47154 + struct ubi32_mailbox_port *uart = dev_id;
47156 + spin_lock(&uart->port.lock);
47158 + //XXX?while (UART_GET_LSR(uart) & DR)
47163 + while (ubi32_mailbox_get_char_avail()) {
47164 + ubi32_mailbox_rx_chars(uart);
47171 + if (this_uart.tx_in == this_uart.tx_out) {
47172 + UBICOM32_IO_PORT(SERIAL_UBICOM_PORT)->int_mask &= ~IO_PORTX_INT_SERDES_TXBE;
47173 + } else if (UBICOM32_IO_PORT(SERIAL_UBICOM_PORT)->int_status & IO_PORTX_INT_SERDES_TXBE) {
47174 + uart_ubicom32_send(this_uart.tx_buf[this_uart.tx_out & (SERIAL_UBICOM_BUF_SIZE - 1)]);
47175 + this_uart.tx_out++;
47176 + UBICOM32_IO_PORT(SERIAL_UBICOM_PORT)->int_mask |= IO_PORTX_INT_SERDES_TXBE;
47180 + spin_unlock(&uart->port.lock);
47182 + return IRQ_HANDLED;
47185 +static irqreturn_t ubi32_mailbox_tx_int(int irq, void *dev_id)
47187 + struct ubi32_mailbox_port *uart = dev_id;
47189 + spin_lock(&uart->port.lock);
47190 + if (UART_GET_LSR(uart) & THRE)
47191 + ubi32_mailbox_tx_chars(uart);
47192 + spin_unlock(&uart->port.lock);
47194 + return IRQ_HANDLED;
47199 + * Return TIOCSER_TEMT when transmitter is not busy.
47201 +static unsigned int ubi32_mailbox_tx_empty(struct uart_port *port)
47203 +// struct ubi32_mailbox_port *uart = (struct ubi32_mailbox_port *)port;
47204 + unsigned short lsr;
47206 + lsr = UART_GET_LSR(uart);
47208 + return TIOCSER_TEMT;
47213 +static unsigned int ubi32_mailbox_get_mctrl(struct uart_port *port)
47215 + return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
47218 +static void ubi32_mailbox_set_mctrl(struct uart_port *port, unsigned int mctrl)
47223 + * Handle any change of modem status signal since we were last called.
47225 +static void ubi32_mailbox_mctrl_check(struct ubi32_mailbox_port *uart)
47230 + * Interrupts are always disabled.
47232 +static void ubi32_mailbox_break_ctl(struct uart_port *port, int break_state)
47234 +// struct ubi32_mailbox_port *uart = (struct ubi32_mailbox_port *)port;
47235 + u16 lcr = UART_GET_LCR(uart);
47240 + UART_PUT_LCR(uart, lcr);
47244 +static int ubi32_mailbox_startup(struct uart_port *port)
47246 + struct ubi32_mailbox_port *uart = (struct ubi32_mailbox_port *)port;
47248 + if (request_irq(uart->port.irq, ubi32_mailbox_isr, IRQF_DISABLED,
47249 + "UBI32_MAILBOX", uart)) {
47250 + printk(KERN_NOTICE "Unable to attach Ubicom32 SERDES interrupt\n");
47254 + UART_SET_IER(uart, ERBFI);
47258 +static void ubi32_mailbox_shutdown(struct uart_port *port)
47260 + struct ubi32_mailbox_port *uart = (struct ubi32_mailbox_port *)port;
47262 + free_irq(uart->port.irq, uart);
47266 +ubi32_mailbox_set_termios(struct uart_port *port, struct ktermios *termios,
47267 + struct ktermios *old)
47269 + struct ubi32_mailbox_port *uart = (struct ubi32_mailbox_port *)port;
47270 + unsigned long flags;
47271 + unsigned int baud, quot;
47272 + unsigned short val, ier, lsr, lcr = 0;
47274 + switch (termios->c_cflag & CSIZE) {
47288 + printk(KERN_ERR "%s: word lengh not supported\n",
47292 + if (termios->c_cflag & CSTOPB)
47294 + if (termios->c_cflag & PARENB)
47296 + if (!(termios->c_cflag & PARODD))
47298 + if (termios->c_cflag & CMSPAR)
47301 + port->read_status_mask = OE;
47302 + if (termios->c_iflag & INPCK)
47303 + port->read_status_mask |= (FE | PE);
47304 + if (termios->c_iflag & (BRKINT | PARMRK))
47305 + port->read_status_mask |= BI;
47308 + * Characters to ignore
47310 + port->ignore_status_mask = 0;
47311 + if (termios->c_iflag & IGNPAR)
47312 + port->ignore_status_mask |= FE | PE;
47313 + if (termios->c_iflag & IGNBRK) {
47314 + port->ignore_status_mask |= BI;
47316 + * If we're ignoring parity and break indicators,
47317 + * ignore overruns too (for real raw support).
47319 + if (termios->c_iflag & IGNPAR)
47320 + port->ignore_status_mask |= OE;
47323 + baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
47324 + quot = uart_get_divisor(port, baud);
47325 + spin_lock_irqsave(&uart->port.lock, flags);
47328 + lsr = UART_GET_LSR(uart);
47329 + } while (!(lsr & TEMT));
47331 + /* Disable UART */
47332 + ier = UART_GET_IER(uart);
47333 + UART_CLEAR_IER(uart, 0xF);
47335 + UART_PUT_DLL(uart, quot & 0xFF);
47337 + UART_PUT_DLH(uart, (quot >> 8) & 0xFF);
47340 + UART_PUT_LCR(uart, lcr);
47342 + /* Enable UART */
47343 + UART_SET_IER(uart, ier);
47345 + val = UART_GET_GCTL(uart);
47347 + UART_PUT_GCTL(uart, val);
47349 + spin_unlock_irqrestore(&uart->port.lock, flags);
47352 +static const char *ubi32_mailbox_type(struct uart_port *port)
47354 + struct ubi32_mailbox_port *uart = (struct ubi32_mailbox_port *)port;
47356 + return uart->port.type == PORT_UBI32_MAILBOX ? "UBI32_MAILBOX" : NULL;
47360 + * Release the memory region(s) being used by 'port'.
47362 +static void ubi32_mailbox_release_port(struct uart_port *port)
47367 + * Request the memory region(s) being used by 'port'.
47369 +static int ubi32_mailbox_request_port(struct uart_port *port)
47375 + * Configure/autoconfigure the port.
47377 +static void ubi32_mailbox_config_port(struct uart_port *port, int flags)
47379 + struct ubi32_mailbox_port *uart = (struct ubi32_mailbox_port *)port;
47381 + if (flags & UART_CONFIG_TYPE && ubi32_mailbox_request_port(&uart->port) == 0)
47382 + uart->port.type = PORT_UBI32_MAILBOX;
47386 + * Verify the new serial_struct (for TIOCSSERIAL).
47387 + * The only change we allow are to the flags and type, and
47388 + * even then only between PORT_UBI32_MAILBOX and PORT_UNKNOWN
47391 +ubi32_mailbox_verify_port(struct uart_port *port, struct serial_struct *ser)
47396 +static struct uart_ops ubi32_mailbox_pops = {
47397 + .tx_empty = ubi32_mailbox_tx_empty,
47398 + .set_mctrl = ubi32_mailbox_set_mctrl,
47399 + .get_mctrl = ubi32_mailbox_get_mctrl,
47400 + .stop_tx = ubi32_mailbox_stop_tx,
47401 + .start_tx = ubi32_mailbox_start_tx,
47402 + .stop_rx = ubi32_mailbox_stop_rx,
47403 + .enable_ms = ubi32_mailbox_enable_ms,
47404 + .break_ctl = ubi32_mailbox_break_ctl,
47405 + .startup = ubi32_mailbox_startup,
47406 + .shutdown = ubi32_mailbox_shutdown,
47407 + .set_termios = ubi32_mailbox_set_termios,
47408 + .type = ubi32_mailbox_type,
47409 + .release_port = ubi32_mailbox_release_port,
47410 + .request_port = ubi32_mailbox_request_port,
47411 + .config_port = ubi32_mailbox_config_port,
47412 + .verify_port = ubi32_mailbox_verify_port,
47415 +static void __init ubi32_mailbox_init_ports(void)
47417 + static int first = 1;
47424 + for (i = 0; i < NR_PORTS; i++) {
47425 + ubi32_mailbox_ports[i].port.uartclk = get_sclk();
47426 + ubi32_mailbox_ports[i].port.ops = &ubi32_mailbox_pops;
47427 + ubi32_mailbox_ports[i].port.line = i;
47428 + ubi32_mailbox_ports[i].port.iotype = UPIO_MEM;
47429 + ubi32_mailbox_ports[i].port.membase =
47430 + (void __iomem *)ubi32_mailbox_resource[i].uart_base_addr;
47431 + ubi32_mailbox_ports[i].port.mapbase =
47432 + ubi32_mailbox_resource[i].uart_base_addr;
47433 + ubi32_mailbox_ports[i].port.irq =
47434 + ubi32_mailbox_resource[i].uart_irq;
47435 + ubi32_mailbox_ports[i].port.flags = UPF_BOOT_AUTOCONF;
47436 + spin_lock_init(&ubi32_mailbox_ports[i].port.lock);
47438 + ubi32_mailbox_hw_init(&ubi32_mailbox_ports[i]);
47443 +#ifdef CONFIG_SERIAL_UBI32_MAILBOX_CONSOLE
47445 + * If the port was already initialised (eg, by a boot loader),
47446 + * try to determine the current setup.
47448 +static void __init
47449 +ubi32_mailbox_console_get_options(struct ubi32_mailbox_port *uart, int *baud,
47450 + int *parity, int *bits)
47452 + unsigned short status;
47454 + status = UART_GET_IER(uart) & (ERBFI | ETBEI);
47455 + if (status == (ERBFI | ETBEI)) {
47456 + /* ok, the port was enabled */
47457 + unsigned short lcr;
47458 + unsigned short dlh, dll;
47460 + lcr = UART_GET_LCR(uart);
47469 + switch (lcr & 0x03) {
47470 + case 0: *bits = 5; break;
47471 + case 1: *bits = 6; break;
47472 + case 2: *bits = 7; break;
47473 + case 3: *bits = 8; break;
47476 + dll = UART_GET_DLL(uart);
47477 + dlh = UART_GET_DLH(uart);
47479 + *baud = get_sclk() / (16*(dll | dlh << 8));
47481 + pr_debug("%s:baud = %d, parity = %c, bits= %d\n", __FUNCTION__, *baud, *parity, *bits);
47485 +#if defined(CONFIG_SERIAL_UBI32_MAILBOX_CONSOLE) || defined(CONFIG_EARLY_PRINTK)
47486 +static struct uart_driver ubi32_mailbox_reg;
47489 +ubi32_mailbox_console_setup(struct console *co, char *options)
47491 + struct ubi32_mailbox_port *uart;
47492 +# ifdef CONFIG_SERIAL_UBI32_MAILBOX_CONSOLE
47493 + int baud = SERIAL_UBICOM_BAUDRATE;
47495 + int parity = 'n';
47500 + * Check whether an invalid uart number has been specified, and
47501 + * if so, search for the first available port that does have
47502 + * console support.
47504 + if (co->index == -1 || co->index >= NR_PORTS)
47506 + uart = &ubi32_mailbox_ports[co->index];
47508 +# ifdef CONFIG_SERIAL_UBI32_MAILBOX_CONSOLE
47510 + uart_parse_options(options, &baud, &parity, &bits, &flow);
47512 + ubi32_mailbox_console_get_options(uart, &baud, &parity, &bits);
47514 + //JB return uart_set_options(&uart->port, co, baud, parity, bits, flow);
47520 +#endif /* defined (CONFIG_SERIAL_UBI32_MAILBOX_CONSOLE) ||
47521 + defined (CONFIG_EARLY_PRINTK) */
47523 +#ifdef CONFIG_SERIAL_UBI32_MAILBOX_CONSOLE
47524 +static void ubi32_mailbox_console_putchar(struct uart_port *port, int ch)
47526 +// struct ubi32_mailbox_port *uart = (struct ubi32_mailbox_port *)port;
47527 + while (!(UART_GET_LSR(uart) & THRE))
47529 + UART_PUT_CHAR(uart, ch);
47534 + * Interrupts are disabled on entering
47537 +ubi32_mailbox_console_write(struct console *co, const char *s, unsigned int count)
47539 + struct ubi32_mailbox_port *uart = &ubi32_mailbox_ports[co->index];
47540 + unsigned long flags = 0;
47542 + spin_lock_irqsave(&uart->port.lock, flags);
47543 + uart_console_write(&uart->port, s, count, ubi32_mailbox_console_putchar);
47544 + spin_unlock_irqrestore(&uart->port.lock, flags);
47548 +static struct console ubi32_mailbox_console = {
47549 + .name = UBI32_MAILBOX_NAME,
47550 + .write = ubi32_mailbox_console_write,
47551 + .device = uart_console_device,
47552 + .setup = ubi32_mailbox_console_setup,
47553 + .flags = CON_PRINTBUFFER,
47555 + .data = &ubi32_mailbox_reg,
47558 +static int __init ubi32_mailbox_console_init(void)
47560 + ubi32_mailbox_init_ports();
47561 + register_console(&ubi32_mailbox_console);
47564 +console_initcall(ubi32_mailbox_console_init);
47566 +#define UBI32_MAILBOX_CONSOLE &ubi32_mailbox_console
47568 +#define UBI32_MAILBOX_CONSOLE NULL
47569 +#endif /* CONFIG_SERIAL_UBI32_MAILBOX_CONSOLE */
47572 +#ifdef CONFIG_EARLY_PRINTK
47573 +static __init void ubi32_mailbox_early_putc(struct uart_port *port, int ch)
47575 + UART_PUT_CHAR(uart, ch);
47578 +static __init void ubi32_mailbox_early_write(struct console *con, const char *s,
47581 + struct ubi32_mailbox_port *uart = &ubi32_mailbox_ports[con->index];
47584 + for (i = 0; i < n; i++, s++) {
47586 + ubi32_mailbox_early_putc(&uart->port, '\r');
47587 + ubi32_mailbox_early_putc(&uart->port, *s);
47591 +static struct __init console ubi32_mailbox_early_console = {
47592 + .name = "early_UM",
47593 + .write = ubi32_mailbox_early_write,
47594 + .device = uart_console_device,
47595 + .flags = CON_PRINTBUFFER,
47596 + .setup = ubi32_mailbox_console_setup,
47598 + .data = &ubi32_mailbox_reg,
47602 + * XXX Unused in our driver. Need to find out what the termios initialization is good/needed for.
47604 +struct console __init *ubi32_mailbox_early_init(unsigned int port,
47605 + unsigned int cflag)
47607 + struct ubi32_mailbox_port *uart;
47608 + struct ktermios t;
47610 + if (port == -1 || port >= NR_PORTS)
47612 + ubi32_mailbox_init_ports();
47613 + ubi32_mailbox_early_console.index = port;
47614 + uart = &ubi32_mailbox_ports[port];
47615 + t.c_cflag = cflag;
47618 + t.c_lflag = ICANON;
47620 + ubi32_mailbox_set_termios(&uart->port, &t, &t);
47621 + return &ubi32_mailbox_early_console;
47624 +#endif /* CONFIG_SERIAL_UBI32_MAILBOX_CONSOLE */
47626 +static struct uart_driver ubi32_mailbox_reg = {
47627 + .owner = THIS_MODULE,
47628 + .driver_name = "ubi32_mailbox",
47629 + .dev_name = UBI32_MAILBOX_NAME,
47630 + .major = UBI32_MAILBOX_MAJOR,
47631 + .minor = UBI32_MAILBOX_MINOR,
47633 + .cons = UBI32_MAILBOX_CONSOLE,
47636 +static int ubi32_mailbox_suspend(struct platform_device *dev, pm_message_t state)
47638 + struct ubi32_mailbox_port *uart = platform_get_drvdata(dev);
47641 + uart_suspend_port(&ubi32_mailbox_reg, &uart->port);
47646 +static int ubi32_mailbox_resume(struct platform_device *dev)
47648 + struct ubi32_mailbox_port *uart = platform_get_drvdata(dev);
47651 + uart_resume_port(&ubi32_mailbox_reg, &uart->port);
47656 +static int ubi32_mailbox_probe(struct platform_device *dev)
47658 + struct resource *res = dev->resource;
47661 + for (i = 0; i < dev->num_resources; i++, res++)
47662 + if (res->flags & IORESOURCE_MEM)
47665 + if (i < dev->num_resources) {
47666 + for (i = 0; i < NR_PORTS; i++, res++) {
47667 + if (ubi32_mailbox_ports[i].port.mapbase != res->start)
47669 + ubi32_mailbox_ports[i].port.dev = &dev->dev;
47670 + uart_add_one_port(&ubi32_mailbox_reg, &ubi32_mailbox_ports[i].port);
47671 + platform_set_drvdata(dev, &ubi32_mailbox_ports[i]);
47678 +static int ubi32_mailbox_remove(struct platform_device *pdev)
47680 + struct ubi32_mailbox_port *uart = platform_get_drvdata(pdev);
47682 + platform_set_drvdata(pdev, NULL);
47685 + uart_remove_one_port(&ubi32_mailbox_reg, &uart->port);
47690 +static struct platform_driver ubi32_mailbox_driver = {
47691 + .probe = ubi32_mailbox_probe,
47692 + .remove = ubi32_mailbox_remove,
47693 + .suspend = ubi32_mailbox_suspend,
47694 + .resume = ubi32_mailbox_resume,
47696 + .name = "ubi32-mbox",
47697 + .owner = THIS_MODULE,
47701 +static int __init ubi32_mailbox_init(void)
47705 + pr_info("Serial: Ubicom32 mailbox serial driver.\n");
47707 + mailbox_console_flg = TRUE;
47708 + num_timeouts = 0;
47709 + ubi32_mailbox_init_ports();
47711 + ret = uart_register_driver(&ubi32_mailbox_reg);
47713 + ret = platform_driver_register(&ubi32_mailbox_driver);
47715 + pr_debug("uart register failed\n");
47716 + uart_unregister_driver(&ubi32_mailbox_reg);
47721 + * XXX HACK: currently probe does not get called, but the port needs to be added to work.
47723 + uart_add_one_port(&ubi32_mailbox_reg, &ubi32_mailbox_ports[0].port);
47727 +static void __exit ubi32_mailbox_exit(void)
47729 + platform_driver_unregister(&ubi32_mailbox_driver);
47730 + uart_unregister_driver(&ubi32_mailbox_reg);
47733 +module_init(ubi32_mailbox_init);
47734 +module_exit(ubi32_mailbox_exit);
47736 +MODULE_ALIAS_CHARDEV_MAJOR(UBI32_MAILBOX_MAJOR);
47737 +MODULE_ALIAS("platform:ubi32_mailbox");
47739 +++ b/drivers/serial/ubi32_serdes.c
47742 + * drivers/serial/ubi32_serdes.c
47743 + * Ubicom32 On-Chip Serial Driver
47745 + * (C) Copyright 2009, Ubicom, Inc.
47747 + * This file is part of the Ubicom32 Linux Kernel Port.
47749 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
47750 + * it and/or modify it under the terms of the GNU General Public License
47751 + * as published by the Free Software Foundation, either version 2 of the
47752 + * License, or (at your option) any later version.
47754 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
47755 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
47756 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
47757 + * the GNU General Public License for more details.
47759 + * You should have received a copy of the GNU General Public License
47760 + * along with the Ubicom32 Linux Kernel Port. If not,
47761 + * see <http://www.gnu.org/licenses/>.
47763 + * Ubicom32 implementation derived from (with many thanks):
47768 +#include <linux/module.h>
47769 +#include <linux/ioport.h>
47770 +#include <linux/init.h>
47771 +#include <linux/console.h>
47772 +#include <linux/sysrq.h>
47773 +#include <linux/platform_device.h>
47774 +#include <linux/tty.h>
47775 +#include <linux/tty_flip.h>
47776 +#include <linux/serial_core.h>
47778 +#include <asm/ip5000.h>
47779 +#include <asm/ubicom32suart.h>
47782 +#define SERIAL_UBICOM_PIN_RXD (1 << 0)
47783 +#define SERIAL_UBICOM_PIN_TXD (1 << 6)
47784 +#define SERIAL_UBICOM_CTL0 0x8b300000
47785 +#define SERIAL_UBICOM_CTL1 0x00000009
47787 +#define SERIAL_UBICOM_DATA_BIT 8 /* Fixed parameter - do not change */
47788 +#define SERIAL_UBICOM_PAR_BIT 0 /* Fixed parameter - do not change */
47789 +#define SERIAL_UBICOM_STOP_BIT 1 /* Fixed parameter - do not change */
47791 +/* UART name and device definitions */
47792 +#define UBI32_SERDES_NAME "ttyUS" // XXX
47793 +#define UBI32_SERDES_MAJOR 206 // XXX
47794 +#define UBI32_SERDES_MINOR 64 // XXX
47796 +#define PORT_UBI32_SERDES 1234
47797 +#define NR_PORTS 1
47799 +struct uart_port ubi32_serdes_ports[NR_PORTS];
47801 +struct ubi32_serdes_resource {
47802 + void *uart_base_addr;
47805 +} ubi32_serdes_resource[NR_PORTS] = {
47807 + * Get params from kernel command line (required for early printk)
47808 + * or from platform resources.
47814 + * Can get overridden by 'serdes=' kernel command line.
47816 +static int ubi32_serdes_default_baud_rate = 115200;
47819 +#define IO_PORT(port) ((struct ubicom32_io_port *)port->membase)
47820 +#define IO_PORT_INT_STATUS(port) (IO_PORT(port)->int_status)
47821 +#define IO_PORT_INT_MASK(port) (IO_PORT(port)->int_mask)
47822 +#define IO_PORT_INT_CLR(port) (IO_PORT(port)->int_clr)
47826 + * ubi32_serdes_get_char()
47828 +static u8_t ubi32_serdes_get_char(struct ubicom32_io_port *io_port)
47831 + * Read from hardware (forced 32-bit atomic read).
47836 + io_port->int_clr = IO_PORTX_INT_SERDES_RXBF;
47838 + "move.4 %0, %1 \n\t"
47840 + : "m" (*(u32_t *)&(io_port->rx_fifo))
47844 + return (u8_t)(data & 0x000000ff);
47848 + * ubi32_serdes_put_char()
47850 +static void ubi32_serdes_put_char(struct ubicom32_io_port *io_port, u8_t c)
47852 + u32_t data = 0x0000fe00 | (c << 1);
47856 + * Fixed data format:
47857 + * [LSB]1 start bit - 8 data bits - no parity - 1 stop bit[MSB]
47859 + io_port->int_clr = IO_PORTX_INT_SERDES_TXBE;
47860 + io_port->ctl2 = data;
47861 + io_port->int_set = IO_PORTX_INT_SERDES_TXBUF_VALID;
47865 +static void ubi32_serdes_hw_init(struct uart_port *port, int baud)
47867 + struct ubicom32_io_port *io_port = IO_PORT(port);
47871 + * Put port functions 1-4 into reset state.
47872 + * Function 0 (GPIO) does not need or have a reset bit.
47874 + * Select SERDES function for restart below.
47876 + io_port->function =
47877 + IO_FUNC_FUNCTION_RESET(1) | IO_FUNC_FUNCTION_RESET(2) |
47878 + IO_FUNC_FUNCTION_RESET(3) | IO_FUNC_FUNCTION_RESET(4) |
47879 + IO_PORTX_FUNC_SERDES;
47882 + * Configure SERDES baudrate
47884 + if ( baud == 0 ) {
47885 + baud = ubi32_serdes_default_baud_rate;
47889 + SERIAL_UBICOM_CTL0 |
47890 + ((port->uartclk / (16 * baud)) - 1);
47893 + SERIAL_UBICOM_CTL1;
47896 + * don't interrupt until startup and start_tx
47898 + io_port->int_mask = 0;
47901 + * Set TXD pin output, RXD input and prevent GPIO
47902 + * override on the TXD & RXD pins
47904 + io_port->gpio_ctl &= ~SERIAL_UBICOM_PIN_RXD;
47905 + io_port->gpio_ctl |= SERIAL_UBICOM_PIN_TXD;
47906 + io_port->gpio_mask &= ~(SERIAL_UBICOM_PIN_RXD | SERIAL_UBICOM_PIN_TXD);
47909 + * Restart (un-reset) the port's SERDES function.
47911 + io_port->function &= ~(IO_FUNC_FUNCTION_RESET(IO_PORTX_FUNC_SERDES));
47915 +#define ULITE_STATUS_RXVALID IO_PORTX_INT_SERDES_RXBF
47916 +#define ULITE_STATUS_OVERRUN 0
47917 +#define ULITE_STATUS_FRAME 0
47918 +#define ULITE_STATUS_PARITY 0
47919 +#define ULITE_STATUS_TXEMPTY IO_PORTX_INT_SERDES_TXBE
47920 +#define ULITE_STATUS_TXFULL 0
47922 +static int ubi32_serdes_receive(struct uart_port *port, int stat)
47924 + struct tty_struct *tty = port->info->port.tty;
47925 + unsigned char ch = 0;
47926 + char flag = TTY_NORMAL;
47928 + if ((stat & (ULITE_STATUS_RXVALID | ULITE_STATUS_OVERRUN
47929 + | ULITE_STATUS_FRAME)) == 0)
47933 + if (stat & ULITE_STATUS_RXVALID) {
47934 + port->icount.rx++;
47935 + ch = ubi32_serdes_get_char((struct ubicom32_io_port *)port->membase);
47937 + if (stat & ULITE_STATUS_PARITY)
47938 + port->icount.parity++;
47941 + if (stat & ULITE_STATUS_OVERRUN)
47942 + port->icount.overrun++;
47944 + if (stat & ULITE_STATUS_FRAME)
47945 + port->icount.frame++;
47948 + /* drop byte with parity error if IGNPAR specificed */
47949 + if (stat & port->ignore_status_mask & ULITE_STATUS_PARITY)
47950 + stat &= ~ULITE_STATUS_RXVALID;
47952 + stat &= port->read_status_mask;
47954 + if (stat & ULITE_STATUS_PARITY)
47955 + flag = TTY_PARITY;
47957 + stat &= ~port->ignore_status_mask;
47959 + if (stat & ULITE_STATUS_RXVALID)
47960 + tty_insert_flip_char(tty, ch, flag);
47962 + if (stat & ULITE_STATUS_FRAME)
47963 + tty_insert_flip_char(tty, 0, TTY_FRAME);
47965 + if (stat & ULITE_STATUS_OVERRUN)
47966 + tty_insert_flip_char(tty, 0, TTY_OVERRUN);
47972 + * interrupts are disabled on entry
47974 +static void ubi32_serdes_stop_tx(struct uart_port *port)
47976 + IO_PORT_INT_MASK(port) = IO_PORT_INT_MASK(port) & ~IO_PORTX_INT_SERDES_TXBE;
47979 +static int ubi32_serdes_transmit(struct uart_port *port, int stat)
47981 + struct circ_buf *xmit = &port->info->xmit;
47983 + if (!(stat & IO_PORTX_INT_SERDES_TXBE))
47986 + if (port->x_char) {
47987 + ubi32_serdes_put_char(IO_PORT(port), port->x_char);
47988 + port->x_char = 0;
47989 + port->icount.tx++;
47993 + if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
47994 + ubi32_serdes_stop_tx(port);
47998 + ubi32_serdes_put_char(IO_PORT(port), xmit->buf[xmit->tail]);
47999 + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE-1);
48000 + port->icount.tx++;
48003 + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
48004 + uart_write_wakeup(port);
48006 + if (uart_circ_empty(xmit))
48007 + ubi32_serdes_stop_tx(port);
48013 + * port is locked and interrupts are disabled
48015 +static void ubi32_serdes_start_tx(struct uart_port *port)
48017 + IO_PORT_INT_MASK(port) = IO_PORT_INT_MASK(port) | IO_PORTX_INT_SERDES_TXBE;
48018 + ubi32_serdes_transmit(port, IO_PORT_INT_STATUS(port));
48022 + * Interrupts are enabled
48024 +static void ubi32_serdes_stop_rx(struct uart_port *port)
48026 + /* don't forward any more data (like !CREAD) */
48027 + port->ignore_status_mask = IO_PORTX_INT_SERDES_RXBF;
48031 + * Set the modem control timer to fire immediately.
48033 +static void ubi32_serdes_enable_ms(struct uart_port *port)
48038 +static irqreturn_t ubi32_serdes_isr(int irq, void *dev_id)
48040 + struct uart_port *port = dev_id;
48043 + spin_lock(&port->lock);
48046 + int stat = IO_PORT_INT_STATUS(port);
48047 + busy = ubi32_serdes_receive(port, stat);
48048 + busy |= ubi32_serdes_transmit(port, stat);
48051 + tty_flip_buffer_push(port->info->port.tty);
48053 + spin_unlock(&port->lock);
48055 + return IRQ_HANDLED;
48059 + * Return TIOCSER_TEMT when transmitter is not busy.
48061 +static unsigned int ubi32_serdes_tx_empty(struct uart_port *port)
48063 + unsigned long flags;
48064 + unsigned int ret;
48066 + spin_lock_irqsave(&port->lock, flags);
48067 + ret = IO_PORT_INT_STATUS(port);
48068 + spin_unlock_irqrestore(&port->lock, flags);
48070 + return ret & ULITE_STATUS_TXEMPTY ? TIOCSER_TEMT : 0;
48073 +static unsigned int ubi32_serdes_get_mctrl(struct uart_port *port)
48075 + return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
48078 +static void ubi32_serdes_set_mctrl(struct uart_port *port, unsigned int mctrl)
48084 + * Interrupts are always disabled.
48086 +static void ubi32_serdes_break_ctl(struct uart_port *port, int break_state)
48091 +static int ubi32_serdes_startup(struct uart_port *port)
48093 + if (request_irq(port->irq, ubi32_serdes_isr, IRQF_DISABLED,
48094 + "UBI32_SERDES", port)) {
48095 + printk(KERN_NOTICE "Unable to attach port interrupt\n");
48099 + IO_PORT_INT_CLR(port) = IO_PORTX_INT_SERDES_RXBF;
48100 + IO_PORT_INT_MASK(port) = IO_PORTX_INT_SERDES_RXBF;
48104 +static void ubi32_serdes_shutdown(struct uart_port *port)
48106 + struct ubi32_serdes_port *uart = (struct ubi32_serdes_port *)port;
48108 + IO_PORT_INT_MASK(port) = 0;
48109 + free_irq(port->irq, uart);
48113 +ubi32_serdes_set_termios(struct uart_port *port, struct ktermios *termios,
48114 + struct ktermios *old)
48116 + unsigned long flags;
48117 + unsigned int baud;
48119 + spin_lock_irqsave(&port->lock, flags);
48121 + port->read_status_mask = ULITE_STATUS_RXVALID | ULITE_STATUS_OVERRUN
48122 + | ULITE_STATUS_TXFULL;
48124 + if (termios->c_iflag & INPCK)
48125 + port->read_status_mask |=
48126 + ULITE_STATUS_PARITY | ULITE_STATUS_FRAME;
48128 + port->ignore_status_mask = 0;
48129 + if (termios->c_iflag & IGNPAR)
48130 + port->ignore_status_mask |= ULITE_STATUS_PARITY
48131 + | ULITE_STATUS_FRAME | ULITE_STATUS_OVERRUN;
48133 + /* ignore all characters if CREAD is not set */
48134 + if ((termios->c_cflag & CREAD) == 0)
48135 + port->ignore_status_mask |=
48136 + ULITE_STATUS_RXVALID | ULITE_STATUS_PARITY
48137 + | ULITE_STATUS_FRAME | ULITE_STATUS_OVERRUN;
48139 + /* update timeout */
48140 + baud = uart_get_baud_rate(port, termios, old, 0, 460800);
48141 + uart_update_timeout(port, termios->c_cflag, baud);
48143 + IO_PORT(port)->ctl0 = SERIAL_UBICOM_CTL0 |
48144 + ((port->uartclk / (16 * baud)) - 1);
48146 + spin_unlock_irqrestore(&port->lock, flags);
48149 +static const char *ubi32_serdes_type(struct uart_port *port)
48151 + return port->type == PORT_UBI32_SERDES ? "UBI32_SERDES" : NULL;
48155 + * Release the memory region(s) being used by 'port'.
48157 +static void ubi32_serdes_release_port(struct uart_port *port)
48162 + * Request the memory region(s) being used by 'port'.
48164 +static int ubi32_serdes_request_port(struct uart_port *port)
48170 + * Configure/autoconfigure the port.
48172 +static void ubi32_serdes_config_port(struct uart_port *port, int flags)
48174 + if (flags & UART_CONFIG_TYPE &&
48175 + ubi32_serdes_request_port(port) == 0)
48176 + port->type = PORT_UBI32_SERDES;
48180 + * Verify the new serial_struct (for TIOCSSERIAL).
48181 + * The only change we allow are to the flags and type, and
48182 + * even then only between PORT_UBI32_SERDES and PORT_UNKNOWN
48185 +ubi32_serdes_verify_port(struct uart_port *port, struct serial_struct *ser)
48190 +static struct uart_ops ubi32_serdes_pops = {
48191 + .tx_empty = ubi32_serdes_tx_empty,
48192 + .set_mctrl = ubi32_serdes_set_mctrl,
48193 + .get_mctrl = ubi32_serdes_get_mctrl,
48194 + .stop_tx = ubi32_serdes_stop_tx,
48195 + .start_tx = ubi32_serdes_start_tx,
48196 + .stop_rx = ubi32_serdes_stop_rx,
48197 + .enable_ms = ubi32_serdes_enable_ms,
48198 + .break_ctl = ubi32_serdes_break_ctl,
48199 + .startup = ubi32_serdes_startup,
48200 + .shutdown = ubi32_serdes_shutdown,
48201 + .set_termios = ubi32_serdes_set_termios,
48202 + .type = ubi32_serdes_type,
48203 + .release_port = ubi32_serdes_release_port,
48204 + .request_port = ubi32_serdes_request_port,
48205 + .config_port = ubi32_serdes_config_port,
48206 + .verify_port = ubi32_serdes_verify_port,
48209 +static void __init ubi32_serdes_init_ports(void)
48213 + for (i = 0; i < NR_PORTS; i++) {
48214 + ubi32_serdes_ports[i].uartclk = ubi32_serdes_resource[i].uart_clock;
48215 + ubi32_serdes_ports[i].ops = &ubi32_serdes_pops;
48216 + ubi32_serdes_ports[i].line = i;
48217 + ubi32_serdes_ports[i].iotype = UPIO_MEM;
48218 + ubi32_serdes_ports[i].membase =
48219 + (void __iomem *)ubi32_serdes_resource[i].uart_base_addr;
48220 + ubi32_serdes_ports[i].mapbase =
48221 + (resource_size_t)ubi32_serdes_resource[i].uart_base_addr;
48222 + ubi32_serdes_ports[i].irq =
48223 + ubi32_serdes_resource[i].uart_irq;
48224 + ubi32_serdes_ports[i].flags = UPF_BOOT_AUTOCONF;
48226 + ubi32_serdes_hw_init(&ubi32_serdes_ports[i], 0);
48231 +#ifdef CONFIG_SERIAL_UBI32_SERDES_CONSOLE
48233 + * If the port was already initialised (eg, by a boot loader),
48234 + * try to determine the current setup.
48236 +static void __init
48237 +ubi32_serdes_console_get_options(struct uart_port *port, int *baud)
48239 + u32 round_to = 1200;
48243 + * We might get called before platform init and with no
48244 + * kernel command line options, so port might be NULL.
48246 + *baud = ubi32_serdes_default_baud_rate;;
48247 + if ( IO_PORT(port) == 0 )
48250 + real_baud = port->uartclk
48251 + / (16 * ((IO_PORT(port)->ctl0 & ~SERIAL_UBICOM_CTL0) + 1));
48253 + *baud = ((real_baud + round_to - 1) / round_to) * round_to;
48255 + pr_debug("%s:baud = %d, real_baud = %d\n", __FUNCTION__, *baud, real_baud);
48259 +#if defined(CONFIG_SERIAL_UBI32_SERDES_CONSOLE) || defined(CONFIG_EARLY_PRINTK)
48260 +static struct uart_driver ubi32_serdes_reg;
48263 +ubi32_serdes_console_setup(struct console *co, char *options)
48265 + struct uart_port *port;
48266 +#ifdef CONFIG_SERIAL_UBI32_SERDES_CONSOLE
48267 + int baud = ubi32_serdes_default_baud_rate;
48269 + int parity = 'n';
48274 + * Check whether an invalid uart number has been specified, and
48275 + * if so, search for the first available port that does have
48276 + * console support.
48278 + if (co->index == -1 || co->index >= NR_PORTS)
48280 + port = &ubi32_serdes_ports[co->index];
48282 +#ifdef CONFIG_SERIAL_UBI32_SERDES_CONSOLE
48284 + uart_parse_options(options, &baud, &parity, &bits, &flow);
48285 + ubi32_serdes_hw_init(port, baud);
48288 + ubi32_serdes_console_get_options(port, &baud);
48290 + return uart_set_options(port, co, baud, parity, bits, flow);
48295 +#endif /* defined (CONFIG_SERIAL_UBI32_SERDES_CONSOLE) ||
48296 + defined (CONFIG_EARLY_PRINTK) */
48298 +#ifdef CONFIG_SERIAL_UBI32_SERDES_CONSOLE
48300 +ubi32_serdes_console_putchar(struct uart_port *port, int ch)
48302 + if ( IO_PORT(port) ) {
48303 + while (!(IO_PORT_INT_STATUS(port) & IO_PORTX_INT_SERDES_TXBE))
48305 + ubi32_serdes_put_char(IO_PORT(port), ch);
48310 + * Interrupts are disabled on entering
48313 +ubi32_serdes_console_write(struct console *co, const char *s, unsigned int count)
48315 + struct uart_port *port = &ubi32_serdes_ports[co->index];
48316 + unsigned long flags = 0;
48318 + spin_lock_irqsave(&port->lock, flags);
48319 + uart_console_write(port, s, count, ubi32_serdes_console_putchar);
48320 + spin_unlock_irqrestore(&port->lock, flags);
48324 +static struct console ubi32_serdes_console = {
48325 + .name = UBI32_SERDES_NAME,
48326 + .write = ubi32_serdes_console_write,
48327 + .device = uart_console_device,
48328 + .setup = ubi32_serdes_console_setup,
48329 + .flags = CON_PRINTBUFFER,
48331 + .data = &ubi32_serdes_reg,
48334 +static int __init ubi32_serdes_console_init(void)
48336 + ubi32_serdes_init_ports();
48337 + register_console(&ubi32_serdes_console);
48340 +console_initcall(ubi32_serdes_console_init);
48342 +#define UBI32_SERDES_CONSOLE &ubi32_serdes_console
48344 +#define UBI32_SERDES_CONSOLE NULL
48345 +#endif /* CONFIG_SERIAL_UBI32_SERDES_CONSOLE */
48348 +#ifdef CONFIG_EARLY_PRINTK
48349 +static __init void ubi32_serdes_early_putc(struct uart_port *port, int ch)
48351 + unsigned timeout = 0xffff;
48353 + while ((!(IO_PORT_INT_STATUS(port) & IO_PORTX_INT_SERDES_TXBE)) && --timeout)
48355 + ubi32_serdes_put_char(IO_PORT(port), ch);
48358 +static __init void ubi32_serdes_early_write(struct console *con, const char *s,
48361 + struct uart_port *port = &ubi32_serdes_ports[con->index];
48364 + for (i = 0; i < n; i++, s++) {
48366 + ubi32_serdes_early_putc(port, '\r');
48367 + ubi32_serdes_early_putc(port, *s);
48371 +static struct __init console ubi32_serdes_early_console = {
48372 + .name = "early_US",
48373 + .write = ubi32_serdes_early_write,
48374 + .device = uart_console_device,
48375 + .flags = CON_PRINTBUFFER,
48376 + .setup = ubi32_serdes_console_setup,
48378 + .data = &ubi32_serdes_reg,
48382 + * XXX Unused in our driver. Need to find out what the termios initialization is good/needed for.
48384 +struct console __init *ubi32_serdes_early_init(unsigned int port_index,
48385 + unsigned int cflag)
48387 + struct uart_port *uart;
48388 + struct ktermios t;
48390 + if (port_index == -1 || port_index >= NR_PORTS)
48392 + ubi32_serdes_init_ports();
48393 + ubi32_serdes_early_console.index = port_index;
48394 + uart = &ubi32_serdes_ports[port_index];
48395 + t.c_cflag = cflag;
48398 + t.c_lflag = ICANON;
48399 + t.c_line = port_index;
48400 + ubi32_serdes_set_termios(uart, &t, &t);
48401 + return &ubi32_serdes_early_console;
48404 +#endif /* CONFIG_SERIAL_UBI32_SERDES_CONSOLE */
48406 +static struct uart_driver ubi32_serdes_reg = {
48407 + .owner = THIS_MODULE,
48408 + .driver_name = "ubi32_serdes",
48409 + .dev_name = UBI32_SERDES_NAME,
48410 + .major = UBI32_SERDES_MAJOR,
48411 + .minor = UBI32_SERDES_MINOR,
48413 + .cons = UBI32_SERDES_CONSOLE,
48416 +static int ubi32_serdes_suspend(struct platform_device *dev, pm_message_t state)
48418 + struct uart_port *port = platform_get_drvdata(dev);
48421 + uart_suspend_port(&ubi32_serdes_reg, port);
48426 +static int ubi32_serdes_resume(struct platform_device *dev)
48428 + struct uart_port *port = platform_get_drvdata(dev);
48431 + uart_resume_port(&ubi32_serdes_reg, port);
48436 +static int ubi32_serdes_probe(struct platform_device *dev)
48438 + struct resource *res = dev->resource;
48441 + for (i = 0; i < dev->num_resources; i++, res++) {
48442 + if (res->flags & IORESOURCE_MEM) {
48443 + ubi32_serdes_resource[0].uart_base_addr = (void *) res->start;
48445 + else if (res->flags & IORESOURCE_IRQ) {
48446 + ubi32_serdes_resource[0].uart_irq = res->start;
48448 + else if (res->flags & UBICOM32_SUART_IORESOURCE_CLOCK) {
48449 + ubi32_serdes_resource[0].uart_clock = res->start;
48453 + ubi32_serdes_init_ports();
48458 +static int ubi32_serdes_remove(struct platform_device *pdev)
48460 + struct uart_port *port = platform_get_drvdata(pdev);
48462 + platform_set_drvdata(pdev, NULL);
48465 + uart_remove_one_port(&ubi32_serdes_reg, port);
48470 +static struct platform_driver ubi32_serdes_driver = {
48471 + .remove = ubi32_serdes_remove,
48472 + .suspend = ubi32_serdes_suspend,
48473 + .resume = ubi32_serdes_resume,
48475 + .name = "ubicom32suart",
48476 + .owner = THIS_MODULE,
48483 + * Called at boot time.
48485 + * You can specify IO base, IRQ, and clock for the serdes serial port
48486 + * using kernel command line "serdes=0xiobase,irq,clock". Values
48487 + * specified will be overwritten by platform device data, if present.
48489 +static int __init ubi32_serdes_setup(char *str)
48491 +#define N_PARMS (4+1)
48492 + int ints[N_PARMS];
48495 + str = get_options(str, ARRAY_SIZE(ints), ints);
48497 + for (i = 0; i < N_PARMS; i++) {
48498 + if (i < ints[0]) {
48500 + ubi32_serdes_resource[0].uart_base_addr = (void *) ints[i+1];
48502 + else if (i == 1) {
48503 + ubi32_serdes_resource[0].uart_irq = ints[i+1];
48505 + else if (i == 2) {
48506 + ubi32_serdes_resource[0].uart_clock = ints[i+1];
48508 + else if (i == 3) {
48509 + ubi32_serdes_default_baud_rate = ints[i+1];
48516 +__setup("serdes=", ubi32_serdes_setup);
48519 +static int __init ubi32_serdes_init(void)
48523 + pr_info("Serial: Ubicom32 serdes uart serial driver\n");
48525 + ret = platform_driver_probe(&ubi32_serdes_driver, ubi32_serdes_probe);
48527 + printk(KERN_INFO "serdes platform_driver_probe() failed: %d\n", ret);
48531 + ubi32_serdes_init_ports();
48533 + ret = uart_register_driver(&ubi32_serdes_reg);
48534 + if ( ret == 0 ) {
48535 + ret = uart_add_one_port(&ubi32_serdes_reg, &ubi32_serdes_ports[0]);
48536 + if ( ret != 0 ) {
48537 + uart_unregister_driver(&ubi32_serdes_reg);
48544 +static void __exit ubi32_serdes_exit(void)
48546 + platform_driver_unregister(&ubi32_serdes_driver);
48547 + uart_unregister_driver(&ubi32_serdes_reg);
48550 +module_init(ubi32_serdes_init);
48551 +module_exit(ubi32_serdes_exit);
48553 +MODULE_AUTHOR("Rainer Keller <rkeller@ubicom.com>");
48554 +MODULE_DESCRIPTION("Ubicom generic serial port driver");
48555 +MODULE_LICENSE("GPL");
48556 +MODULE_ALIAS_CHARDEV_MAJOR(UBI32_SERDES_MAJOR);
48557 +MODULE_ALIAS("platform:ubi32_serdes");
48559 +++ b/drivers/serial/ubi32_uarttio.c
48562 + * drivers/serial/ubi32_uarttio.c
48563 + * Ubicom32 Serial Virtual Peripherial Driver
48565 + * (C) Copyright 2009, Ubicom, Inc.
48567 + * This file is part of the Ubicom32 Linux Kernel Port.
48569 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
48570 + * it and/or modify it under the terms of the GNU General Public License
48571 + * as published by the Free Software Foundation, either version 2 of the
48572 + * License, or (at your option) any later version.
48574 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
48575 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
48576 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
48577 + * the GNU General Public License for more details.
48579 + * You should have received a copy of the GNU General Public License
48580 + * along with the Ubicom32 Linux Kernel Port. If not,
48581 + * see <http://www.gnu.org/licenses/>.
48584 +#include <linux/module.h>
48585 +#include <linux/ioport.h>
48586 +#include <linux/init.h>
48587 +#include <linux/console.h>
48588 +#include <linux/sysrq.h>
48589 +#include <linux/platform_device.h>
48590 +#include <linux/tty.h>
48591 +#include <linux/tty_flip.h>
48592 +#include <linux/serial_core.h>
48594 +#include <asm/ip5000.h>
48595 +#include <asm/gpio.h>
48596 +#include <asm/thread.h>
48597 +#include <asm/uart_tio.h>
48599 +#define DRIVER_NAME "ubi32_uarttio"
48602 + * For storing the module parameters.
48604 +#define UBI32_UARTTIO_MAX_PARAM_LEN 80
48605 +static char utio_ports_param[UBI32_UARTTIO_MAX_PARAM_LEN];
48608 + * UART name and device definitions
48610 +#define UBI32_UARTTIO_NAME "ttyUV" // XXX
48611 +#define UBI32_UARTTIO_MAJOR 206 // XXX
48612 +#define UBI32_UARTTIO_MINOR 64 // XXX
48615 + * The following structures are allocated statically because the
48616 + * memory allocation subsystem is not initialized this early on
48620 + * Per port structure
48622 +struct ubi32_uarttio_port {
48623 + struct uarttio_uart *uart;
48624 + unsigned int tx_pin;
48625 + unsigned int rx_pin;
48627 + struct uart_port port;
48632 + * If this value is set, the port has had its direction set already
48636 +static struct ubi32_uarttio_port uarttio_ports[CONFIG_SERIAL_UBI32_UARTTIO_NR_UARTS];
48639 + * Number of ports currently initialized
48641 +static int uarttio_nports;
48644 + * Per device structure
48646 +struct ubi32_uarttio_instance {
48647 + struct uarttio_regs *regs;
48648 + struct ubi32_uarttio_port *ports;
48650 + u8_t irq_requested;
48651 + u8_t driver_registered;
48654 +static struct ubi32_uarttio_instance uarttio_inst;
48656 +#ifdef CONFIG_SERIAL_UBI32_UARTTIO_CONSOLE
48657 +static struct console ubi32_uarttio_console;
48658 +#define UBI32_UARTTIO_CONSOLE &ubi32_uarttio_console
48660 +#define UBI32_UARTTIO_CONSOLE NULL
48663 +static struct uart_driver ubi32_uarttio_uart_driver = {
48664 + .owner = THIS_MODULE,
48665 + .driver_name = DRIVER_NAME,
48666 + .dev_name = UBI32_UARTTIO_NAME,
48667 + .major = UBI32_UARTTIO_MAJOR,
48668 + .minor = UBI32_UARTTIO_MINOR,
48669 + .cons = UBI32_UARTTIO_CONSOLE,
48672 +#ifdef UBI32_UARTTIO_UNUSED
48674 + * ubi32_uarttio_get_send_space
48676 +static int ubi32_uarttio_get_send_space(struct uarttio_uart *uart)
48678 + int count = uart->tx_fifo_head - uart->tx_fifo_tail;
48680 + count += uart->tx_fifo_size;
48682 + return uart->tx_fifo_size - count;
48687 + * ubi32_uarttio_get_recv_ready
48689 +static int ubi32_uarttio_get_recv_ready(struct uarttio_uart *uart)
48691 + int count = uart->rx_fifo_head - uart->rx_fifo_tail;
48693 + count += uart->rx_fifo_size;
48699 + * ubi32_uarttio_get_char()
48701 +static u8_t ubi32_uarttio_get_char(struct uarttio_uart *uart)
48706 + u32_t tail = uart->rx_fifo_tail;
48707 + u8_t data = uart->rx_fifo[tail];
48709 + if (++tail == uart->rx_fifo_size) {
48712 + uart->rx_fifo_tail = tail;
48718 + * ubi32_uarttio_put_char()
48720 +static int ubi32_uarttio_put_char(struct uarttio_uart *uart, u8_t c)
48722 + u32_t head = uart->tx_fifo_head;
48723 + u32_t prev = head;
48728 + if (++head == uart->tx_fifo_size) {
48733 + * If there isn't any space, return EBUSY
48735 + if (head == uart->tx_fifo_tail) {
48740 + * Put the character in the queue
48742 + uart->tx_fifo[prev] = c;
48743 + uart->tx_fifo_head = head;
48749 + * ubi32_uarttio_set_baud
48751 +static int ubi32_uarttio_set_baud(struct ubi32_uarttio_port *uup, unsigned int baud)
48753 + if (uup->uart->current_baud_rate == baud) {
48757 + uup->uart->baud_rate = baud;
48758 + uup->uart->flags |= UARTTIO_UART_FLAG_SET_RATE;
48759 + while (uup->uart->flags & UARTTIO_UART_FLAG_SET_RATE) {
48763 + if (uup->uart->current_baud_rate != baud) {
48765 + * Failed to set baud rate
48767 + printk(KERN_WARNING "Invalid baud rate %u, running at %u\n", baud, uup->uart->current_baud_rate);
48775 + * ubi32_uarttio_handle_receive
48777 +static void ubi32_uarttio_handle_receive(struct ubi32_uarttio_port *uup, int stat)
48779 + struct uarttio_uart *uart = uup->uart;
48780 + struct uart_port *port = &uup->port;
48781 + struct tty_struct *tty = port->info->port.tty;
48782 + unsigned char ch = 0;
48783 + char flag = TTY_NORMAL;
48786 + if ((stat & (UARTTIO_UART_INT_RX | UARTTIO_UART_INT_RXFRAME | UARTTIO_UART_INT_RXOVF)) == 0) {
48790 + if (stat & UARTTIO_UART_INT_RX) {
48791 + count = ubi32_uarttio_get_recv_ready(uart);
48792 + port->icount.rx += count;
48795 + if (stat & UARTTIO_UART_INT_RXOVF) {
48796 + port->icount.overrun++;
48799 + if (stat & UARTTIO_UART_INT_RXFRAME) {
48800 + port->icount.frame++;
48803 + stat &= ~port->ignore_status_mask;
48805 + if (stat & UARTTIO_UART_INT_RX) {
48807 + for (i = 0; i < count; i++) {
48808 + ch = ubi32_uarttio_get_char(uart);
48809 + tty_insert_flip_char(tty, ch, flag);
48813 + if (stat & UARTTIO_UART_INT_RXFRAME) {
48814 + tty_insert_flip_char(tty, 0, TTY_FRAME);
48817 + if (stat & UARTTIO_UART_INT_RXOVF) {
48818 + tty_insert_flip_char(tty, 0, TTY_OVERRUN);
48823 + * ubi32_uarttio_stop_tx
48824 + * interrupts are disabled on entry
48826 +static void ubi32_uarttio_stop_tx(struct uart_port *port)
48828 + struct ubi32_uarttio_port *uup = port->private_data;
48830 + uup->uart->int_mask &= ~UARTTIO_UART_INT_TXBE;
48834 + * ubi32_uarttio_handle_transmit
48836 +static void ubi32_uarttio_handle_transmit(struct ubi32_uarttio_port *uup, int stat)
48838 + struct uarttio_uart *uart = uup->uart;
48839 + struct uart_port *port = &uup->port;
48840 + struct circ_buf *xmit = &port->info->xmit;
48842 + if (!(stat & UARTTIO_UART_INT_TXBE)) {
48846 + if (port->x_char) {
48847 + if (ubi32_uarttio_put_char(uart, port->x_char)) {
48850 + port->x_char = 0;
48851 + port->icount.tx++;
48855 + if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
48856 + ubi32_uarttio_stop_tx(port);
48861 + * Send as many characters as we can
48863 + while (ubi32_uarttio_put_char(uart, xmit->buf[xmit->tail]) == 0) {
48864 + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
48865 + port->icount.tx++;
48866 + if (uart_circ_empty(xmit)) {
48872 + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) {
48873 + uart_write_wakeup(port);
48876 + if (uart_circ_empty(xmit)) {
48877 + ubi32_uarttio_stop_tx(port);
48882 + * ubi32_uarttio_start_tx
48883 + * port is locked and interrupts are disabled
48885 +static void ubi32_uarttio_start_tx(struct uart_port *port)
48887 + struct ubi32_uarttio_port *uup = port->private_data;
48888 + struct uarttio_uart *uart = uup->uart;
48890 + uart->int_mask |= UARTTIO_UART_INT_TXBE;
48894 + * ubi32_uarttio_stop_rx
48895 + * Interrupts are enabled
48897 +static void ubi32_uarttio_stop_rx(struct uart_port *port)
48899 + struct ubi32_uarttio_port *uup = port->private_data;
48900 + struct uarttio_uart *uart = uup->uart;
48903 + * don't forward any more data (like !CREAD)
48905 + uart->int_mask &= ~UARTTIO_UART_INT_RX;
48906 + port->ignore_status_mask = UARTTIO_UART_INT_RX;
48910 + * ubi32_uarttio_enable_ms
48911 + * Set the modem control timer to fire immediately.
48913 +static void ubi32_uarttio_enable_ms(struct uart_port *port)
48919 + * ubi32_uarttio_isr
48921 +static irqreturn_t ubi32_uarttio_isr(int irq, void *appdata)
48923 + struct ubi32_uarttio_port *uup = uarttio_ports;
48927 + * Service all of the ports
48929 + for (i = 0; i < uarttio_nports; i++) {
48930 + unsigned int flags;
48932 + if (!(uup->uart->flags & UARTTIO_UART_FLAG_ENABLED)) {
48937 + spin_lock(&uup->port.lock);
48939 + flags = uup->uart->int_flags;
48941 + uup->uart->int_flags = 0;
48943 + ubi32_uarttio_handle_receive(uup, flags);
48944 + ubi32_uarttio_handle_transmit(uup, flags);
48946 + tty_flip_buffer_push(uup->port.info->port.tty);
48948 + spin_unlock(&uup->port.lock);
48953 + return IRQ_HANDLED;
48957 + * ubi32_uarttio_tx_empty
48958 + * Return TIOCSER_TEMT when transmitter is not busy.
48960 +static unsigned int ubi32_uarttio_tx_empty(struct uart_port *port)
48962 + struct ubi32_uarttio_port *uup = port->private_data;
48964 + if (uup->uart->tx_fifo_head == uup->uart->tx_fifo_tail) {
48965 + return TIOCSER_TEMT;
48972 + * ubi32_uarttio_get_mctrl
48974 +static unsigned int ubi32_uarttio_get_mctrl(struct uart_port *port)
48976 + return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
48980 + * ubi32_uarttio_set_mctrl
48982 +static void ubi32_uarttio_set_mctrl(struct uart_port *port, unsigned int mctrl)
48988 + * ubi32_uarttio_break_ctl
48990 +static void ubi32_uarttio_break_ctl(struct uart_port *port, int break_state)
48996 + * ubi32_uarttio_startup
48998 +static int ubi32_uarttio_startup(struct uart_port *port)
49000 + struct ubi32_uarttio_port *uup = port->private_data;
49001 + struct uarttio_uart *uart = uup->uart;
49003 + uart->flags |= UARTTIO_UART_FLAG_ENABLED;
49005 + uart->int_mask |= UARTTIO_UART_INT_TXBE | UARTTIO_UART_INT_RX;
49011 + * ubi32_uarttio_shutdown
49013 +static void ubi32_uarttio_shutdown(struct uart_port *port)
49015 + struct ubi32_uarttio_port *uup = port->private_data;
49016 + struct uarttio_uart *uart = uup->uart;
49018 + uart->int_mask = 0;
49019 + uart->flags &= ~UARTTIO_UART_FLAG_ENABLED;
49023 + * ubi32_uarttio_set_termios
49025 +static void ubi32_uarttio_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old)
49027 + struct ubi32_uarttio_port *uup = port->private_data;
49028 + unsigned long flags;
49029 + unsigned int baud;
49031 + spin_lock_irqsave(&port->lock, flags);
49034 + port->read_status_mask = UBI32_UARTTIO_RX | UBI32_UARTTIO_RXOVF | UBI32_UARTTIO_TXOVF;
49036 + if (termios->c_iflag & INPCK) {
49037 + port->read_status_mask |= UBI32_UARTTIO_RXFRAME;
49041 + port->ignore_status_mask = 0;
49042 + if (termios->c_iflag & IGNPAR) {
49043 + port->ignore_status_mask |= UARTTIO_UART_INT_RXFRAME |
49044 + UARTTIO_UART_INT_RXOVF;
49048 + * ignore all characters if CREAD is not set
49050 + if ((termios->c_cflag & CREAD) == 0) {
49051 + port->ignore_status_mask |= UARTTIO_UART_INT_RX |
49052 + UARTTIO_UART_INT_RXFRAME |
49053 + UARTTIO_UART_INT_RXOVF;
49056 + /* update timeout */
49057 + baud = uart_get_baud_rate(port, termios, old, 0, 460800);
49058 + uart_update_timeout(port, termios->c_cflag, baud);
49060 + ubi32_uarttio_set_baud(uup, baud);
49061 + spin_unlock_irqrestore(&port->lock, flags);
49065 + * ubi32_uarttio_type
49067 +static const char *ubi32_uarttio_type(struct uart_port *port)
49069 + return (port->type == PORT_UBI32_UARTTIO) ? "UBI32_UARTTIO" : NULL;
49073 + * ubi32_uarttio_release_port
49074 + * Release the memory region(s) being used by 'port'.
49076 +static void ubi32_uarttio_release_port(struct uart_port *port)
49081 + * ubi32_uarttio_request_port
49082 + * Request the memory region(s) being used by 'port'.
49084 +static int ubi32_uarttio_request_port(struct uart_port *port)
49090 + * ubi32_uarttio_config_port
49091 + * Configure/autoconfigure the port.
49093 +static void ubi32_uarttio_config_port(struct uart_port *port, int flags)
49095 + if ((flags & UART_CONFIG_TYPE) && (ubi32_uarttio_request_port(port) == 0)) {
49096 + port->type = PORT_UBI32_UARTTIO;
49101 + * ubi32_uarttio_verify_port
49102 + * Verify the new serial_struct (for TIOCSSERIAL).
49104 + * The only change we allow are to the flags and type, and
49105 + * even then only between PORT_UBI32_UARTTIO and PORT_UNKNOWN
49107 +static int ubi32_uarttio_verify_port(struct uart_port *port, struct serial_struct *ser)
49112 +static struct uart_ops ubi32_uarttio_pops = {
49113 + .tx_empty = ubi32_uarttio_tx_empty,
49114 + .set_mctrl = ubi32_uarttio_set_mctrl,
49115 + .get_mctrl = ubi32_uarttio_get_mctrl,
49116 + .stop_tx = ubi32_uarttio_stop_tx,
49117 + .start_tx = ubi32_uarttio_start_tx,
49118 + .stop_rx = ubi32_uarttio_stop_rx,
49119 + .enable_ms = ubi32_uarttio_enable_ms,
49120 + .break_ctl = ubi32_uarttio_break_ctl,
49121 + .startup = ubi32_uarttio_startup,
49122 + .shutdown = ubi32_uarttio_shutdown,
49123 + .set_termios = ubi32_uarttio_set_termios,
49124 + .type = ubi32_uarttio_type,
49125 + .release_port = ubi32_uarttio_release_port,
49126 + .request_port = ubi32_uarttio_request_port,
49127 + .config_port = ubi32_uarttio_config_port,
49128 + .verify_port = ubi32_uarttio_verify_port,
49132 + * ubi32_uarttio_add_ports
49134 +static int __init ubi32_uarttio_add_ports(void)
49137 + struct ubi32_uarttio_port *uup = uarttio_ports;
49140 + for (i = 0; i < uarttio_nports; i++) {
49142 + * Setup the GPIOs
49144 + res = gpio_request(uup->tx_pin, "ubi32_uarttio_tx");
49146 + printk(KERN_WARNING "Failed to request GPIO %d\n", uup->tx_pin);
49151 + res = gpio_request(uup->rx_pin, "ubi32_uarttio_rx");
49153 + gpio_free(uup->tx_pin);
49154 + printk(KERN_WARNING "Failed to request GPIO %d\n", uup->rx_pin);
49159 + res = uart_add_one_port(&ubi32_uarttio_uart_driver, &uup->port);
49161 + gpio_free(uup->rx_pin);
49162 + gpio_free(uup->tx_pin);
49164 + printk(KERN_WARNING "Failed to add port %d,%d\n", uup->tx_pin, uup->rx_pin);
49170 + * Set the direction of the ports now, after we're sure that everything is ok
49172 + if (!uup->port_init) {
49173 + gpio_direction_output(uup->tx_pin, 1);
49174 + gpio_direction_input(uup->rx_pin);
49184 + * ubi32_uarttio_cleanup
49186 +static void ubi32_uarttio_cleanup(void)
49188 + struct ubi32_uarttio_port *uup;
49192 + * Stop the hardware thread
49194 + if (uarttio_inst.regs) {
49195 + thread_disable(uarttio_inst.regs->thread);
49197 + if (uarttio_inst.irq_requested) {
49198 + free_irq(uarttio_inst.irq, NULL);
49202 + * Get rid of the ports
49204 + uup = uarttio_inst.ports;
49205 + for (i = 0; i < uarttio_nports; i++) {
49206 + gpio_free(uup->tx_pin);
49207 + gpio_free(uup->rx_pin);
49208 + if (uup->added) {
49209 + uart_remove_one_port(&ubi32_uarttio_uart_driver, &uup->port);
49214 + if (uarttio_inst.driver_registered) {
49215 + uart_unregister_driver(&ubi32_uarttio_uart_driver);
49220 + * ubi32_uarttio_setup_port
49221 + * Setup a port in the TIO registers
49223 +static int ubi32_uarttio_setup_port(int index,
49224 + struct uarttio_uart *uart,
49225 + unsigned int baud, unsigned int tx_pin,
49226 + unsigned int rx_pin)
49228 + struct ubi32_uarttio_port *uup = &uarttio_ports[index];
49229 + void *tx_port = ubi_gpio_get_port(tx_pin);
49230 + void *rx_port = ubi_gpio_get_port(rx_pin);
49233 + * Verify the ports are on chip
49235 + if (!tx_port || !rx_port) {
49236 + printk(KERN_WARNING "Invalid port(s) specified: %u or %u\n", tx_pin, rx_pin);
49240 + uup->tx_pin = tx_pin;
49241 + uup->rx_pin = rx_pin;
49242 + uup->uart = uart;
49245 + * Setup the port structure
49247 + uup->port.ops = &ubi32_uarttio_pops;
49248 + uup->port.line = index;
49249 + uup->port.iotype = UPIO_MEM;
49250 + uup->port.flags = UPF_BOOT_AUTOCONF;
49251 + uup->port.fifosize = uup->uart->tx_fifo_size;
49252 + uup->port.private_data = uup;
49255 + * We share this IRQ across all ports
49257 + uup->port.irq = uarttio_inst.irq;
49260 + * We really don't have a mem/map base but without these variables
49261 + * set, the serial_core won't startup.
49263 + uup->port.membase = (void __iomem *)uup;
49264 + uup->port.mapbase = (resource_size_t)uup;
49265 + spin_lock_init(&uup->port.lock);
49268 + * Set up the hardware
49270 + uart->flags = UARTTIO_UART_FLAG_SET_RATE | UARTTIO_UART_FLAG_RESET;
49272 + uart->tx_port = (unsigned int)tx_port;
49273 + uart->tx_pin = gpio_pin_index(tx_pin);
49274 + uart->tx_bits = 8;
49275 + uart->tx_stop_bits = 1;
49277 + uart->rx_port = (unsigned int)rx_port;
49278 + uart->rx_pin = gpio_pin_index(rx_pin);
49279 + uart->rx_bits = 8;
49280 + uart->rx_stop_bits = 1;
49282 + uart->baud_rate = baud;
49287 +enum ubi32_uarttio_parse_states {
49288 + UBI32_UARTTIO_PARSE_STATE_BAUD,
49289 + UBI32_UARTTIO_PARSE_STATE_TX_PIN,
49290 + UBI32_UARTTIO_PARSE_STATE_RX_PIN,
49291 + UBI32_UARTTIO_PARSE_STATE_HS,
49292 + UBI32_UARTTIO_PARSE_STATE_CTS_PIN,
49293 + UBI32_UARTTIO_PARSE_STATE_RTS_PIN,
49297 + * ubi32_uarttio_parse_param
49299 +static int ubi32_uarttio_parse_param(char *str)
49310 + enum ubi32_uarttio_parse_states state = UBI32_UARTTIO_PARSE_STATE_BAUD;
49311 + struct uarttio_uart *uart = uarttio_inst.regs->uarts;
49314 + * Run though the options and generate the proper structures
49316 + res = get_option(&str, &i);
49317 + while ((res == 2) || (res == 1)) {
49319 + case UBI32_UARTTIO_PARSE_STATE_BAUD:
49321 + * If we are here and nfound > 0 then create the port
49322 + * based on the previous input
49326 + * Create the port
49328 + if (ubi32_uarttio_setup_port(nfound - 1, uart, baud, tx_pin, rx_pin)) {
49330 + * Port was invalid
49334 + printk(KERN_INFO "Serial port %d: tx=%d:rx=%d @ %d\n", nfound, tx_pin, rx_pin, baud);
49340 + * Reset the variables and go to the next state
49344 + state = UBI32_UARTTIO_PARSE_STATE_TX_PIN;
49347 + case UBI32_UARTTIO_PARSE_STATE_TX_PIN:
49349 + state = UBI32_UARTTIO_PARSE_STATE_RX_PIN;
49352 + case UBI32_UARTTIO_PARSE_STATE_RX_PIN:
49354 + state = UBI32_UARTTIO_PARSE_STATE_HS;
49357 + case UBI32_UARTTIO_PARSE_STATE_HS:
49360 + state = UBI32_UARTTIO_PARSE_STATE_CTS_PIN;
49364 + if (nfound == uarttio_inst.regs->max_uarts) {
49365 + printk(KERN_WARNING "Maximum number of serial ports reached\n");
49369 + state = UBI32_UARTTIO_PARSE_STATE_BAUD;
49372 + case UBI32_UARTTIO_PARSE_STATE_CTS_PIN:
49374 + state = UBI32_UARTTIO_PARSE_STATE_RTS_PIN;
49377 + case UBI32_UARTTIO_PARSE_STATE_RTS_PIN:
49380 + if (nfound == uarttio_inst.regs->max_uarts) {
49381 + printk(KERN_WARNING "Maximum number of serial ports reached\n");
49385 + state = UBI32_UARTTIO_PARSE_STATE_BAUD;
49388 + res = get_option(&str, &i);
49391 + if ((res > 2) || state != UBI32_UARTTIO_PARSE_STATE_BAUD) {
49392 + printk(KERN_WARNING "Parameter syntax error.\n");
49398 + * Create the final port
49400 + if (ubi32_uarttio_setup_port(nfound - 1, uart, baud, tx_pin, rx_pin)) {
49403 + printk(KERN_INFO "Serial port %d: tx=%d:rx=%d @ %d\n", nfound, tx_pin, rx_pin, baud);
49406 + uarttio_nports = nfound;
49408 + return nfound ? 0 : -ENODEV;
49412 + * Reset the ports
49414 + uart = uarttio_inst.regs->uarts;
49415 + for (i = 0; i < uarttio_inst.regs->max_uarts; i++) {
49424 + * ubi32_uarttio_probe
49426 +static int ubi32_uarttio_probe(void)
49429 + struct uarttio_node *uart_node;
49430 + char *str = utio_ports_param;
49431 + static int probed;
49432 + static int probe_result;
49435 + * We only want to be probed once, we could be probed twice
49436 + * for example if we are used as a console
49439 + return probe_result;
49444 + * Extract the TIO name from the setup string
49447 + if (*str == ',') {
49455 + probe_result = -EINVAL;
49459 + uart_node = (struct uarttio_node *)devtree_find_node(utio_ports_param);
49460 + if (!uart_node) {
49461 + probe_result = -ENODEV;
49465 + uarttio_inst.irq = uart_node->dn.recvirq;
49466 + uarttio_inst.regs = uart_node->regs;
49469 + * Parse module parameters.
49471 + ret = ubi32_uarttio_parse_param(str);
49473 + ubi32_uarttio_cleanup();
49474 + probe_result = ret;
49478 + ubi32_uarttio_uart_driver.nr = uarttio_nports;
49483 +#if defined(CONFIG_SERIAL_UBI32_UARTTIO_CONSOLE)
49485 + * ubi32_uarttio_console_setup
49487 +static int __init ubi32_uarttio_console_setup(struct console *co, char *options)
49491 + int parity = 'n';
49493 + struct ubi32_uarttio_port *uup;
49496 + * Check whether an invalid uart number has been specified, and
49497 + * if so, search for the first available port that does have
49498 + * console support.
49500 + if (co->index == -1 || co->index >= uarttio_nports) {
49503 + uup = &uarttio_ports[co->index];
49504 + baud = uup->uart->baud_rate;
49505 + uup->uart->flags |= UARTTIO_UART_FLAG_ENABLED;
49508 + * Setup the GPIOs
49509 + * We have to use the direct interface because the gpio
49510 + * subsystem is not available at this point.
49512 + uup->port_init = 1;
49513 + UBICOM32_GPIO_SET_PIN_HIGH(uup->tx_pin);
49514 + UBICOM32_GPIO_SET_PIN_OUTPUT(uup->tx_pin);
49515 + UBICOM32_GPIO_SET_PIN_INPUT(uup->rx_pin);
49518 + * Start the thread
49520 + thread_enable(uarttio_inst.regs->thread);
49523 + * Process options
49526 + uart_parse_options(options, &baud, &parity, &bits, &flow);
49527 + if (ubi32_uarttio_set_baud(uup, baud)) {
49528 + baud = uup->uart->current_baud_rate;
49532 + return uart_set_options(&uup->port, co, baud, 'n', 8, 'n');
49536 + * ubi32_uarttio_console_putchar
49538 +static void ubi32_uarttio_console_putchar(struct uart_port *port, int ch)
49540 + struct ubi32_uarttio_port *uup = port->private_data;
49542 + while (ubi32_uarttio_put_char(uup->uart, ch)) {
49548 + * ubi32_uarttio_console_write
49549 + * Interrupts are disabled on entering
49551 +static void ubi32_uarttio_console_write(struct console *co, const char *s, unsigned int count)
49553 + struct uart_port *port = &(uarttio_ports[co->index].port);
49554 + unsigned long flags = 0;
49556 + spin_lock_irqsave(&port->lock, flags);
49557 + uart_console_write(port, s, count, ubi32_uarttio_console_putchar);
49558 + spin_unlock_irqrestore(&port->lock, flags);
49561 +static struct console ubi32_uarttio_console = {
49562 + .name = UBI32_UARTTIO_NAME,
49563 + .write = ubi32_uarttio_console_write,
49564 + .device = uart_console_device,
49565 + .setup = ubi32_uarttio_console_setup,
49566 + .flags = CON_PRINTBUFFER,
49568 + .data = &ubi32_uarttio_uart_driver,
49571 +static int __init ubi32_uarttio_console_init(void)
49575 + res = ubi32_uarttio_probe();
49580 + register_console(&ubi32_uarttio_console);
49583 +console_initcall(ubi32_uarttio_console_init);
49584 +#endif /* CONFIG_SERIAL_UBI32_UARTTIO_CONSOLE */
49587 + * ubi32_serial_suspend
49589 +static int ubi32_uarttio_suspend(struct platform_device *pdev, pm_message_t state)
49592 + for (i = 0; i < uarttio_nports; i++) {
49593 + uart_suspend_port(&ubi32_uarttio_uart_driver, &uarttio_ports[i].port);
49600 + * ubi32_serial_resume
49602 +static int ubi32_uarttio_resume(struct platform_device *pdev)
49605 + for (i = 0; i < uarttio_nports; i++) {
49606 + uart_resume_port(&ubi32_uarttio_uart_driver, &uarttio_ports[i].port);
49613 + * ubi32_uarttio_remove
49615 +static int __devexit ubi32_uarttio_remove(struct platform_device *pdev)
49617 + ubi32_uarttio_cleanup();
49619 + uart_unregister_driver(&ubi32_uarttio_uart_driver);
49624 +static struct platform_driver ubi32_uarttio_platform_driver = {
49625 + .remove = __devexit_p(ubi32_uarttio_remove),
49626 + .suspend = ubi32_uarttio_suspend,
49627 + .resume = ubi32_uarttio_resume,
49629 + .name = DRIVER_NAME,
49630 + .owner = THIS_MODULE,
49636 + * Called at boot time.
49638 + * uarttio=TIONAME,(baud,tx_pin,rx_pin,handshake[,cts_pin,rts_pin],...)
49639 + * TIONAME is the name of the devtree node which describes the UARTTIO
49640 + * pin is the index of the pin, i.e. PA4 is 5 [(port * 32) + pin]
49641 + * handshake = 1 to enable handshaking, provide cts_pin, rts_pin (UNSUPPORTED)
49642 + * handshake = 0 to disable handshaking, do not provide cts_pin, rts_pin
49643 + * Ex: uarttio=UARTTIO,57600,7,6,0,9600,8,9,0
49645 +static int __init ubi32_uarttio_setup(char *str)
49647 + strncpy(utio_ports_param, str, UBI32_UARTTIO_MAX_PARAM_LEN);
49648 + utio_ports_param[UBI32_UARTTIO_MAX_PARAM_LEN - 1] = 0;
49651 +__setup("uarttio=", ubi32_uarttio_setup);
49655 + * ubi32_uarttio_init
49657 +static int __init ubi32_uarttio_init(void)
49662 + ret = ubi32_uarttio_probe();
49668 + * Request the IRQ (do it here since many ports share the same IRQ)
49670 + ret = request_irq(uarttio_inst.irq, ubi32_uarttio_isr, IRQF_DISABLED, DRIVER_NAME, NULL);
49672 + printk(KERN_WARNING "Could not request IRQ %d\n", uarttio_inst.irq);
49675 + uarttio_inst.irq_requested = 1;
49678 + * Register the UART driver and add the ports
49680 + ret = uart_register_driver(&ubi32_uarttio_uart_driver);
49684 + uarttio_inst.driver_registered = 1;
49686 + ret = ubi32_uarttio_add_ports();
49688 + ubi32_uarttio_cleanup();
49693 + * Start the thread
49695 + thread_enable(uarttio_inst.regs->thread);
49697 + for (i = 0; i < uarttio_nports; i++) {
49698 + pr_info("Serial: Ubicom32 uarttio #%d: tx:%d rx:%d baud:%d\n",
49699 + i, uarttio_ports[i].tx_pin, uarttio_ports[i].rx_pin,
49700 + uarttio_ports[i].uart->current_baud_rate);
49702 + pr_info("Serial: Ubicom32 uarttio started on thread:%d irq:%d\n", uarttio_inst.regs->thread, uarttio_inst.irq);
49707 + ubi32_uarttio_cleanup();
49710 +module_init(ubi32_uarttio_init);
49713 + * ubi32_uarttio_exit
49715 +static void __exit ubi32_uarttio_exit(void)
49717 + platform_driver_unregister(&ubi32_uarttio_platform_driver);
49719 +module_exit(ubi32_uarttio_exit);
49721 +module_param_string(ports, utio_ports_param, sizeof(utio_ports_param), 0444);
49722 +MODULE_PARM_DESC(ports, "Sets the ports to allocate: ports=TIONAME,(baud,txpin,rxpin,handshake[,ctspin,rtspin],...)\n"
49723 + " TIONAME is the name of the devtree node which describes the UARTTIO\n"
49724 + " pin is the index of the pin, i.e. PA4 is 5 [(port * 32) + pin]\n"
49725 + " handshake = 1 to enable handshaking, provide ctspin, rtspin (UNSUPPORTED)\n"
49726 + " handshake = 0 to disable handshaking, do not provide ctspin, rtspin\n"
49727 + " Ex: ports=UARTTIO,57600,7,6,0,9600,8,9,0\n");
49728 +MODULE_AUTHOR("Patrick Tjin <pat.tjin@ubicom.com>");
49729 +MODULE_DESCRIPTION("Ubicom serial virtual peripherial driver");
49730 +MODULE_LICENSE("GPL");
49731 +MODULE_ALIAS_CHARDEV_MAJOR(UBI32_UARTTIO_MAJOR);
49732 +MODULE_ALIAS("platform:" DRIVER_NAME);
49733 --- a/drivers/spi/Kconfig
49734 +++ b/drivers/spi/Kconfig
49735 @@ -196,6 +196,15 @@ config SPI_S3C24XX
49737 SPI driver for Samsung S3C24XX series ARM SoCs
49739 +config SPI_UBICOM32_GPIO
49740 + tristate "Ubicom32 SPI over GPIO"
49741 + depends on SPI_MASTER && UBICOM32 && EXPERIMENTAL
49742 + select SPI_BITBANG
49745 + SPI driver for the Ubicom32 architecture using
49746 + GPIO lines to provide the SPI bus.
49748 config SPI_S3C24XX_GPIO
49749 tristate "Samsung S3C24XX series SPI by GPIO"
49750 depends on ARCH_S3C2410 && EXPERIMENTAL
49751 --- a/drivers/spi/Makefile
49752 +++ b/drivers/spi/Makefile
49753 @@ -27,6 +27,7 @@ obj-$(CONFIG_SPI_ORION) += orion_spi.o
49754 obj-$(CONFIG_SPI_MPC52xx_PSC) += mpc52xx_psc_spi.o
49755 obj-$(CONFIG_SPI_MPC83xx) += spi_mpc83xx.o
49756 obj-$(CONFIG_SPI_S3C24XX_GPIO) += spi_s3c24xx_gpio.o
49757 +obj-$(CONFIG_SPI_UBICOM32_GPIO) += spi_ubicom32_gpio.o
49758 obj-$(CONFIG_SPI_S3C24XX) += spi_s3c24xx.o
49759 obj-$(CONFIG_SPI_TXX9) += spi_txx9.o
49760 obj-$(CONFIG_SPI_XILINX) += xilinx_spi.o
49762 +++ b/drivers/spi/spi_ubicom32_gpio.c
49765 + * drivers/spi_spi_ubicom32_gpio.c
49766 + * Ubicom32 GPIO based SPI driver
49768 + * (C) Copyright 2009, Ubicom, Inc.
49770 + * This file is part of the Ubicom32 Linux Kernel Port.
49772 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
49773 + * it and/or modify it under the terms of the GNU General Public License
49774 + * as published by the Free Software Foundation, either version 2 of the
49775 + * License, or (at your option) any later version.
49777 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
49778 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
49779 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
49780 + * the GNU General Public License for more details.
49782 + * You should have received a copy of the GNU General Public License
49783 + * along with the Ubicom32 Linux Kernel Port. If not,
49784 + * see <http://www.gnu.org/licenses/>.
49786 + * Ubicom32 implementation derived from (with many thanks):
49791 +#include <linux/kernel.h>
49792 +#include <linux/init.h>
49793 +#include <linux/delay.h>
49794 +#include <linux/spinlock.h>
49795 +#include <linux/workqueue.h>
49796 +#include <linux/platform_device.h>
49798 +#include <linux/spi/spi.h>
49799 +#include <linux/spi/spi_bitbang.h>
49801 +#include <linux/gpio.h>
49803 +#include <asm/ubicom32-spi-gpio.h>
49805 +#define DRIVER_NAME "ubicom32-spi-gpio"
49807 +struct ubicom32_spi_gpio {
49808 + struct spi_bitbang bitbang;
49810 + struct ubicom32_spi_gpio_platform_data *pdata;
49812 + struct platform_device *dev;
49816 + * The following 4 functions are used by EXPAND_BITBANG_TXRX to bitbang the data out.
49818 +static inline void setsck(struct spi_device *dev, int on)
49820 + struct ubicom32_spi_gpio *usg = (struct ubicom32_spi_gpio *)spi_master_get_devdata(dev->master);
49821 + gpio_set_value(usg->pdata->pin_clk, on ? 1 : 0);
49824 +static inline void setmosi(struct spi_device *dev, int on)
49826 + struct ubicom32_spi_gpio *usg = (struct ubicom32_spi_gpio *)spi_master_get_devdata(dev->master);
49827 + gpio_set_value(usg->pdata->pin_mosi, on ? 1 : 0);
49830 +static inline u32 getmiso(struct spi_device *dev)
49832 + struct ubicom32_spi_gpio *usg = (struct ubicom32_spi_gpio *)spi_master_get_devdata(dev->master);
49833 + return gpio_get_value(usg->pdata->pin_miso) ? 1 : 0;
49836 +#define spidelay(x) ndelay(x)
49838 +#define EXPAND_BITBANG_TXRX
49839 +#include <linux/spi/spi_bitbang.h>
49842 + * ubicom32_spi_gpio_txrx_mode0
49844 +static u32 ubicom32_spi_gpio_txrx_mode0(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits)
49846 + return bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits);
49850 + * ubicom32_spi_gpio_txrx_mode1
49852 +static u32 ubicom32_spi_gpio_txrx_mode1(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits)
49854 + return bitbang_txrx_be_cpha1(spi, nsecs, 0, word, bits);
49858 + * ubicom32_spi_gpio_txrx_mode2
49860 +static u32 ubicom32_spi_gpio_txrx_mode2(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits)
49862 + return bitbang_txrx_be_cpha0(spi, nsecs, 1, word, bits);
49866 + * ubicom32_spi_gpio_txrx_mode3
49868 +static u32 ubicom32_spi_gpio_txrx_mode3(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits)
49870 + return bitbang_txrx_be_cpha1(spi, nsecs, 1, word, bits);
49874 + * ubicom32_spi_gpio_chipselect
49876 +static void ubicom32_spi_gpio_chipselect(struct spi_device *dev, int value)
49878 + struct ubicom32_spi_gpio_controller_data *cd = (struct ubicom32_spi_gpio_controller_data *)dev->controller_data;
49879 + unsigned int cs_polarity = dev->mode & SPI_CS_HIGH ? 1 : 0;
49881 + if (value == BITBANG_CS_ACTIVE) {
49882 + gpio_set_value(cd->pin_cs, cs_polarity);
49885 + gpio_set_value(cd->pin_cs, !cs_polarity);
49889 + * ubicom32_spi_gpio_probe
49891 +static int ubicom32_spi_gpio_probe(struct platform_device *dev)
49893 + struct ubicom32_spi_gpio_platform_data *pdata;
49894 + struct spi_master *master;
49895 + struct ubicom32_spi_gpio *usg;
49898 + master = spi_alloc_master(&dev->dev, sizeof(struct ubicom32_spi_gpio));
49899 + if (master == NULL) {
49900 + dev_err(&dev->dev, "failed to allocate spi master\n");
49905 + usg = (struct ubicom32_spi_gpio *)spi_master_get_devdata(master);
49907 + platform_set_drvdata(dev, usg);
49910 + * Copy in the platform data
49912 + pdata = dev->dev.platform_data;
49913 + usg->pdata = dev->dev.platform_data;
49916 + * Request the GPIO lines
49918 + ret = gpio_request(pdata->pin_mosi, "spi-mosi");
49920 + dev_err(&dev->dev, "Failed to allocate spi-mosi GPIO\n");
49924 + ret = gpio_request(pdata->pin_miso, "spi-miso");
49926 + dev_err(&dev->dev, "Failed to allocate spi-miso GPIO\n");
49930 + ret = gpio_request(pdata->pin_clk, "spi-clk");
49932 + dev_err(&dev->dev, "Failed to allocate spi-clk GPIO\n");
49937 + * Setup spi-bitbang adaptor
49939 + usg->bitbang.flags |= SPI_CS_HIGH;
49940 + usg->bitbang.master = spi_master_get(master);
49941 + usg->bitbang.master->bus_num = pdata->bus_num;
49942 + usg->bitbang.master->num_chipselect = pdata->num_chipselect;
49943 + usg->bitbang.chipselect = ubicom32_spi_gpio_chipselect;
49945 + usg->bitbang.txrx_word[SPI_MODE_0] = ubicom32_spi_gpio_txrx_mode0;
49946 + usg->bitbang.txrx_word[SPI_MODE_1] = ubicom32_spi_gpio_txrx_mode1;
49947 + usg->bitbang.txrx_word[SPI_MODE_2] = ubicom32_spi_gpio_txrx_mode2;
49948 + usg->bitbang.txrx_word[SPI_MODE_3] = ubicom32_spi_gpio_txrx_mode3;
49951 + * Setup the GPIO pins
49953 + gpio_direction_output(pdata->pin_clk, pdata->clk_default);
49954 + gpio_direction_output(pdata->pin_mosi, 0);
49955 + gpio_direction_input(pdata->pin_miso);
49960 + ret = spi_bitbang_start(&usg->bitbang);
49962 + goto err_no_bitbang;
49968 + spi_master_put(usg->bitbang.master);
49970 + gpio_free(pdata->pin_clk);
49973 + gpio_free(pdata->pin_miso);
49976 + gpio_free(pdata->pin_mosi);
49983 + * ubicom32_spi_gpio_remove
49985 +static int ubicom32_spi_gpio_remove(struct platform_device *dev)
49987 + struct ubicom32_spi_gpio *sp = platform_get_drvdata(dev);
49989 + spi_bitbang_stop(&sp->bitbang);
49990 + spi_master_put(sp->bitbang.master);
49996 + * Work with hotplug and coldplug
49998 +MODULE_ALIAS("platform:ubicom32_spi_gpio");
50000 +static struct platform_driver ubicom32_spi_gpio_drv = {
50001 + .probe = ubicom32_spi_gpio_probe,
50002 + .remove = ubicom32_spi_gpio_remove,
50004 + .name = DRIVER_NAME,
50005 + .owner = THIS_MODULE,
50010 + * ubicom32_spi_gpio_init
50012 +static int __init ubicom32_spi_gpio_init(void)
50014 + return platform_driver_register(&ubicom32_spi_gpio_drv);
50018 + * ubicom32_spi_gpio_exit
50020 +static void __exit ubicom32_spi_gpio_exit(void)
50022 + platform_driver_unregister(&ubicom32_spi_gpio_drv);
50025 +module_init(ubicom32_spi_gpio_init);
50026 +module_exit(ubicom32_spi_gpio_exit);
50028 +MODULE_DESCRIPTION("Ubicom32 SPI-GPIO Driver");
50029 +MODULE_AUTHOR("Pat Tjin, <@ubicom.com>");
50030 +MODULE_LICENSE("GPL");
50031 --- a/drivers/uio/Kconfig
50032 +++ b/drivers/uio/Kconfig
50033 @@ -89,4 +89,12 @@ config UIO_SERCOS3
50035 If you compile this as a module, it will be called uio_sercos3.
50037 +config UIO_UBICOM32RING
50038 + tristate "Ubicom32 Ring Buffer driver"
50041 + Userspace I/O interface for a Ubicom32 Ring Buffer.
50043 + If you compile this as a module, it will be called uio_ubicom32ring
50046 --- a/drivers/uio/Makefile
50047 +++ b/drivers/uio/Makefile
50048 @@ -5,3 +5,4 @@ obj-$(CONFIG_UIO_PDRV_GENIRQ) += uio_pdr
50049 obj-$(CONFIG_UIO_SMX) += uio_smx.o
50050 obj-$(CONFIG_UIO_AEC) += uio_aec.o
50051 obj-$(CONFIG_UIO_SERCOS3) += uio_sercos3.o
50052 +obj-$(CONFIG_UIO_UBICOM32RING) += uio_ubicom32ring.o
50054 +++ b/drivers/uio/uio_ubicom32ring.c
50057 + * drivers/uio/uio_ubicom32ring.c
50059 + * Userspace I/O platform driver for Ubicom32 ring buffers
50061 + * (C) Copyright 2009, Ubicom, Inc.
50063 + * This file is part of the Ubicom32 Linux Kernel Port.
50065 + * Based on uio_ubicom32ring.c by Magnus Damm
50067 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
50068 + * it and/or modify it under the terms of the GNU General Public License
50069 + * as published by the Free Software Foundation, either version 2 of the
50070 + * License, or (at your option) any later version.
50072 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
50073 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
50074 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
50075 + * the GNU General Public License for more details.
50077 + * You should have received a copy of the GNU General Public License
50078 + * along with the Ubicom32 Linux Kernel Port. If not,
50079 + * see <http://www.gnu.org/licenses/>.
50082 +#include <linux/platform_device.h>
50083 +#include <linux/uio_driver.h>
50084 +#include <linux/spinlock.h>
50085 +#include <linux/bitops.h>
50086 +#include <linux/interrupt.h>
50087 +#include <linux/stringify.h>
50089 +#include <asm/ip5000.h>
50090 +#include <asm/ubicom32ring.h>
50092 +#define DRIVER_NAME "uio_ubicom32ring"
50094 +struct uio_ubicom32ring_data {
50095 + struct uio_info *uioinfo;
50097 + struct uio_ubicom32ring_regs *regs;
50100 + * IRQ used to kick the ring buffer
50107 + unsigned long flags;
50112 +static irqreturn_t uio_ubicom32ring_handler(int irq, struct uio_info *dev_info)
50114 + struct uio_ubicom32ring_data *priv = dev_info->priv;
50116 + /* Just disable the interrupt in the interrupt controller, and
50117 + * remember the state so we can allow user space to enable it later.
50120 + if (!test_and_set_bit(0, &priv->flags))
50121 + disable_irq_nosync(irq);
50123 + return IRQ_HANDLED;
50126 +static int uio_ubicom32ring_irqcontrol(struct uio_info *dev_info, s32 irq_on)
50128 + struct uio_ubicom32ring_data *priv = dev_info->priv;
50129 + unsigned long flags;
50131 + /* Allow user space to enable and disable the interrupt
50132 + * in the interrupt controller, but keep track of the
50133 + * state to prevent per-irq depth damage.
50135 + * Serialize this operation to support multiple tasks.
50138 + spin_lock_irqsave(&priv->lock, flags);
50140 + if (irq_on & 2) {
50142 + * Kick the ring buffer (if we can)
50144 + if (priv->irq_tx != 0xFF) {
50145 + ubicom32_set_interrupt(priv->irq_tx);
50149 + if (priv->irq_rx != 0xFF) {
50150 + if (irq_on & 1) {
50151 + if (test_and_clear_bit(0, &priv->flags))
50152 + enable_irq(dev_info->irq);
50154 + if (!test_and_set_bit(0, &priv->flags))
50155 + disable_irq(dev_info->irq);
50159 + spin_unlock_irqrestore(&priv->lock, flags);
50164 +static int uio_ubicom32ring_probe(struct platform_device *pdev)
50166 + struct uio_info *uioinfo;
50167 + struct uio_mem *uiomem;
50168 + struct uio_ubicom32ring_data *priv;
50169 + struct uio_ubicom32ring_regs *regs;
50170 + struct resource *mem_resource;
50171 + struct resource *irqtx_resource;
50172 + struct resource *irqrx_resource;
50173 + int ret = -EINVAL;
50176 + uioinfo = kzalloc(sizeof(struct uio_info), GFP_KERNEL);
50178 + dev_err(&pdev->dev, "unable to kmalloc\n");
50183 + * Allocate private data with some string space after
50185 + i = sizeof(DRIVER_NAME) + 1;
50186 + i += pdev->dev.platform_data ? strlen(pdev->dev.platform_data) : 0;
50187 + priv = kzalloc(sizeof(struct uio_ubicom32ring_data) + i, GFP_KERNEL);
50189 + dev_err(&pdev->dev, "unable to kmalloc\n");
50194 + strcpy(priv->name, DRIVER_NAME ":");
50195 + if (pdev->dev.platform_data) {
50196 + strcat(priv->name, pdev->dev.platform_data);
50198 + uioinfo->priv = priv;
50199 + uioinfo->name = priv->name;
50200 + uioinfo->version = "0.1";
50202 + priv->uioinfo = uioinfo;
50203 + spin_lock_init(&priv->lock);
50204 + priv->flags = 0; /* interrupt is enabled to begin with */
50207 + * Get our resources, the IRQ_TX and IRQ_RX are optional.
50209 + priv->irq_tx = 0xFF;
50210 + irqtx_resource = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
50211 + if (irqtx_resource) {
50212 + priv->irq_tx = irqtx_resource->start;
50215 + uioinfo->irq = -1;
50216 + priv->irq_rx = 0xFF;
50217 + irqrx_resource = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
50218 + if (irqrx_resource) {
50219 + priv->irq_rx = irqrx_resource->start;
50220 + uioinfo->irq = priv->irq_rx;
50221 + uioinfo->handler = uio_ubicom32ring_handler;
50224 + mem_resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
50225 + if (!mem_resource || !mem_resource->start) {
50226 + dev_err(&pdev->dev, "No valid memory resource found\n");
50230 + regs = (struct uio_ubicom32ring_regs *)mem_resource->start;
50231 + priv->regs = regs;
50233 + if (regs->version != UIO_UBICOM32RING_REG_VERSION) {
50234 + dev_err(&pdev->dev, "version %d not supported\n", regs->version);
50240 + * First range is the shared register space, if we have any
50242 + uiomem = &uioinfo->mem[0];
50243 + if (regs->regs_size) {
50244 + uiomem->memtype = UIO_MEM_PHYS;
50245 + uiomem->addr = (u32_t)regs->regs;
50246 + uiomem->size = regs->regs_size;
50248 + dev_info(&pdev->dev, "regs:%p (%u) / rings: %d found\n", regs->regs, regs->regs_size, regs->num_rings);
50250 + dev_info(&pdev->dev, "rings: %d found\n", regs->num_rings);
50254 + * The rest of the range correspond to the rings
50256 + for (i = 0; i < regs->num_rings; i++) {
50257 + dev_info(&pdev->dev, "\t%d: entries:%d ring:%p\n",
50258 + i, regs->rings[i]->entries, &(regs->rings[i]->ring));
50259 + if (uiomem >= &uioinfo->mem[MAX_UIO_MAPS]) {
50260 + dev_warn(&pdev->dev, "device has more than "
50261 + __stringify(MAX_UIO_MAPS)
50262 + " I/O memory resources.\n");
50266 + uiomem->memtype = UIO_MEM_PHYS;
50267 + uiomem->addr = (u32_t)&(regs->rings[i]->head);
50268 + uiomem->size = (regs->rings[i]->entries * sizeof(u32_t)) +
50269 + sizeof(struct uio_ubicom32ring_desc);
50273 + while (uiomem < &uioinfo->mem[MAX_UIO_MAPS]) {
50274 + uiomem->size = 0;
50278 + /* This driver requires no hardware specific kernel code to handle
50279 + * interrupts. Instead, the interrupt handler simply disables the
50280 + * interrupt in the interrupt controller. User space is responsible
50281 + * for performing hardware specific acknowledge and re-enabling of
50282 + * the interrupt in the interrupt controller.
50284 + * Interrupt sharing is not supported.
50286 + uioinfo->irq_flags = IRQF_DISABLED;
50287 + uioinfo->irqcontrol = uio_ubicom32ring_irqcontrol;
50289 + ret = uio_register_device(&pdev->dev, priv->uioinfo);
50291 + dev_err(&pdev->dev, "unable to register uio device\n");
50295 + platform_set_drvdata(pdev, priv);
50297 + dev_info(&pdev->dev, "'%s' using irq: rx %d tx %d, regs %p\n",
50298 + priv->name, priv->irq_rx, priv->irq_tx, priv->regs);
50308 +static int uio_ubicom32ring_remove(struct platform_device *pdev)
50310 + struct uio_ubicom32ring_data *priv = platform_get_drvdata(pdev);
50312 + uio_unregister_device(priv->uioinfo);
50313 + kfree(priv->uioinfo);
50318 +static struct platform_driver uio_ubicom32ring = {
50319 + .probe = uio_ubicom32ring_probe,
50320 + .remove = uio_ubicom32ring_remove,
50322 + .name = DRIVER_NAME,
50323 + .owner = THIS_MODULE,
50327 +static int __init uio_ubicom32ring_init(void)
50329 + return platform_driver_register(&uio_ubicom32ring);
50332 +static void __exit uio_ubicom32ring_exit(void)
50334 + platform_driver_unregister(&uio_ubicom32ring);
50337 +module_init(uio_ubicom32ring_init);
50338 +module_exit(uio_ubicom32ring_exit);
50340 +MODULE_AUTHOR("Patrick Tjin");
50341 +MODULE_DESCRIPTION("Userspace I/O driver for Ubicom32 ring buffers");
50342 +MODULE_LICENSE("GPL v2");
50343 +MODULE_ALIAS("platform:" DRIVER_NAME);
50344 --- a/drivers/usb/gadget/epautoconf.c
50345 +++ b/drivers/usb/gadget/epautoconf.c
50346 @@ -154,6 +154,10 @@ ep_matches (
50347 /* configure your hardware with enough buffering!! */
50351 + case USB_ENDPOINT_XFER_BULK:
50352 + if ((gadget->is_dualspeed) && (ep->maxpacket < 512))
50357 --- a/drivers/usb/Kconfig
50358 +++ b/drivers/usb/Kconfig
50359 @@ -22,6 +22,7 @@ config USB_ARCH_HAS_HCD
50360 default y if PCMCIA && !M32R # sl811_cs
50361 default y if ARM # SL-811
50362 default y if SUPERH # r8a66597-hcd
50363 + default y if UBICOM32 # Ubicom's onchip USB Duial role controller
50366 # many non-PCI SOC chips embed OHCI
50367 --- a/drivers/usb/musb/Kconfig
50368 +++ b/drivers/usb/musb/Kconfig
50369 @@ -12,7 +12,7 @@ config USB_MUSB_HDRC
50371 select TWL4030_USB if MACH_OMAP_3430SDP
50372 select USB_OTG_UTILS
50373 - tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)'
50374 + tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, Ubicom, ...)'
50376 Say Y here if your system has a dual role high speed USB
50377 controller based on the Mentor Graphics silicon IP. Then
50378 --- a/drivers/usb/musb/Makefile
50379 +++ b/drivers/usb/musb/Makefile
50380 @@ -30,6 +30,10 @@ ifeq ($(CONFIG_BF52x),y)
50381 musb_hdrc-objs += blackfin.o
50384 +ifeq ($(CONFIG_UBICOM32), y)
50385 + musb_hdrc-objs += ubi32_usb.o
50388 ifeq ($(CONFIG_USB_GADGET_MUSB_HDRC),y)
50389 musb_hdrc-objs += musb_gadget_ep0.o musb_gadget.o
50391 --- a/drivers/usb/musb/musb_core.c
50392 +++ b/drivers/usb/musb/musb_core.c
50393 @@ -105,6 +105,13 @@
50394 #include <asm/mach-types.h>
50397 +#ifdef CONFIG_UBICOM32
50398 +#include <asm/ip5000.h>
50399 +#include <asm/ubicom32-tio.h>
50400 +extern void ubi32_usb_init(void);
50401 +extern void ubi32_usb_int_clr(void);
50404 #include "musb_core.h"
50407 @@ -147,8 +154,37 @@ static inline struct musb *dev_to_musb(s
50410 /*-------------------------------------------------------------------------*/
50411 +#if defined(CONFIG_UBICOM32)
50414 + * Load an endpoint's FIFO
50416 +void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 wCount, const u8 *pSource)
50418 + void __iomem *fifo = hw_ep->fifo;
50420 + prefetch((u8 *)pSource);
50422 + DBG(4, "%cX ep%d fifo %p count %d buf %p\n",
50423 + 'T', hw_ep->epnum, fifo, wCount, pSource);
50425 + usb_tio_write_fifo((u32)fifo, (u32)pSource, wCount);
50430 + * Unload an endpoint's FIFO
50432 +void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 wCount, u8 *pDest)
50435 + void __iomem *fifo = hw_ep->fifo;
50436 + DBG(4, "%cX ep%d fifo %p count %d buf %p\n",
50437 + 'R', hw_ep->epnum, fifo, wCount, pDest);
50438 + usb_tio_read_fifo((u32)fifo, (u32)pDest, wCount);
50441 -#if !defined(CONFIG_USB_TUSB6010) && !defined(CONFIG_BLACKFIN)
50442 +#elif !defined(CONFIG_USB_TUSB6010) && !defined(CONFIG_BLACKFIN)
50445 * Load an endpoint's FIFO
50446 @@ -227,8 +263,7 @@ void musb_read_fifo(struct musb_hw_ep *h
50447 readsb(fifo, dst, len);
50451 -#endif /* normal PIO */
50452 +#endif /* !T6010 && !BLACKFIN */
50455 /*-------------------------------------------------------------------------*/
50456 @@ -874,12 +909,19 @@ void musb_start(struct musb *musb)
50457 musb_writeb(regs, MUSB_TESTMODE, 0);
50459 /* put into basic highspeed mode and start session */
50460 +#ifndef CONFIG_UBICOM32
50461 musb_writeb(regs, MUSB_POWER, MUSB_POWER_ISOUPDATE
50462 | MUSB_POWER_SOFTCONN
50463 | MUSB_POWER_HSENAB
50464 /* ENSUSPEND wedges tusb */
50465 /* | MUSB_POWER_ENSUSPEND */
50468 + musb_writeb(regs, MUSB_POWER, MUSB_POWER_HSENAB
50469 + /* ENSUSPEND wedges tusb */
50470 + /* | MUSB_POWER_ENSUSPEND */
50474 musb->is_active = 0;
50475 devctl = musb_readb(regs, MUSB_DEVCTL);
50476 @@ -1081,6 +1123,7 @@ static struct fifo_cfg __initdata mode_4
50480 +#ifndef CONFIG_UBICOM32
50482 * configure a fifo; for non-shared endpoints, this may be called
50483 * once for a tx fifo and once for an rx fifo.
50484 @@ -1240,7 +1283,7 @@ static int __init ep_config_from_table(s
50489 +#endif /* CONFIG_UBICOM32 */
50492 * ep_config_from_hw - when MUSB_C_DYNFIFO_DEF is false
50493 @@ -1256,6 +1299,11 @@ static int __init ep_config_from_hw(stru
50494 DBG(2, "<== static silicon ep config\n");
50496 /* FIXME pick up ep0 maxpacket size */
50497 +#ifdef CONFIG_UBICOM32
50498 + /* set ep0 to shared_fifo, otherwise urb will be put to out_qh but ep0_irq try to get the urb from in_qh*/
50499 + hw_ep = musb->endpoints;
50500 + hw_ep->is_shared_fifo = true;
50503 for (epnum = 1; epnum < musb->config->num_eps; epnum++) {
50504 musb_ep_select(mbase, epnum);
50505 @@ -1276,14 +1324,27 @@ static int __init ep_config_from_hw(stru
50506 /* REVISIT: this algorithm is lazy, we should at least
50507 * try to pick a double buffered endpoint.
50509 +#ifndef CONFIG_UBICOM32
50512 musb->bulk_ep = hw_ep;
50514 + if ((musb->bulk_ep_in) && (musb->bulk_ep_out))
50516 + /* Save theEP with 1024 Bytes FIFO for ISO */
50517 + if(hw_ep->max_packet_sz_tx == 512) {
50518 + if (!musb->bulk_ep_in) {
50519 + musb->bulk_ep_in = hw_ep;
50520 + } else if (!musb->bulk_ep_out) {
50521 + musb->bulk_ep_out = hw_ep;
50524 +#endif /* CONFIG_UBICOM32 */
50528 #ifdef CONFIG_USB_MUSB_HDRC_HCD
50529 - if (!musb->bulk_ep) {
50530 + if ((!musb->bulk_ep_in) || (!musb->bulk_ep_out)) {
50531 pr_debug("%s: missing bulk\n", musb_driver_name);
50534 @@ -1393,12 +1454,16 @@ static int __init musb_core_init(u16 mus
50537 if (reg & MUSB_CONFIGDATA_DYNFIFO) {
50538 +#ifndef CONFIG_UBICOM32
50539 if (musb->config->dyn_fifo)
50540 status = ep_config_from_table(musb);
50545 ERR("reconfigure software for Dynamic FIFOs\n");
50550 if (!musb->config->dyn_fifo)
50551 status = ep_config_from_hw(musb);
50552 @@ -1462,8 +1527,8 @@ static int __init musb_core_init(u16 mus
50554 /*-------------------------------------------------------------------------*/
50556 -#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3430)
50558 +#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3430) || defined(CONFIG_UBICOM32)
50559 +static u32_t musb_int_count = 0;
50560 static irqreturn_t generic_interrupt(int irq, void *__hci)
50562 unsigned long flags;
50563 @@ -1472,10 +1537,17 @@ static irqreturn_t generic_interrupt(int
50565 spin_lock_irqsave(&musb->lock, flags);
50567 +#ifndef CONFIG_UBICOM32
50568 musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
50569 musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
50570 musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX);
50572 + musb_read_int_status(&musb->int_usb, &musb->int_tx, &musb->int_rx);
50573 + //ubi32_usb_int_clr();
50574 + musb_int_count++;
50577 + DBG(4, "usb %x, tx %x, rx %x", musb->int_usb, musb->int_tx, musb->int_rx);
50578 if (musb->int_usb || musb->int_tx || musb->int_rx)
50579 retval = musb_interrupt(musb);
50581 @@ -2210,6 +2282,10 @@ static struct platform_driver musb_drive
50583 static int __init musb_init(void)
50585 +#ifdef CONFIG_UBICOM32
50586 + ubi32_usb_init();
50589 #ifdef CONFIG_USB_MUSB_HDRC_HCD
50590 if (usb_disabled())
50592 --- a/drivers/usb/musb/musb_core.h
50593 +++ b/drivers/usb/musb/musb_core.h
50594 @@ -326,7 +326,12 @@ struct musb {
50595 * queue until it completes or NAKs too much; then we try the next
50598 +#ifdef CONFIG_UBICOM32
50599 + struct musb_hw_ep *bulk_ep_in;
50600 + struct musb_hw_ep *bulk_ep_out;
50602 struct musb_hw_ep *bulk_ep;
50605 struct list_head control; /* of musb_qh */
50606 struct list_head in_bulk; /* of musb_qh */
50607 --- a/drivers/usb/musb/musb_gadget.c
50608 +++ b/drivers/usb/musb/musb_gadget.c
50609 @@ -432,7 +432,7 @@ void musb_g_tx(struct musb *musb, u8 epn
50610 * probably rates reporting as a host error
50612 if (csr & MUSB_TXCSR_P_SENTSTALL) {
50613 - csr |= MUSB_TXCSR_P_WZC_BITS;
50614 + csr &= ~(MUSB_TXCSR_P_WZC_BITS);
50615 csr &= ~MUSB_TXCSR_P_SENTSTALL;
50616 musb_writew(epio, MUSB_TXCSR, csr);
50617 if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) {
50618 @@ -448,7 +448,7 @@ void musb_g_tx(struct musb *musb, u8 epn
50620 if (csr & MUSB_TXCSR_P_UNDERRUN) {
50621 /* we NAKed, no big deal ... little reason to care */
50622 - csr |= MUSB_TXCSR_P_WZC_BITS;
50623 + csr &= ~(MUSB_TXCSR_P_WZC_BITS);
50624 csr &= ~(MUSB_TXCSR_P_UNDERRUN
50625 | MUSB_TXCSR_TXPKTRDY);
50626 musb_writew(epio, MUSB_TXCSR, csr);
50627 @@ -584,10 +584,16 @@ static void rxstate(struct musb *musb, s
50629 const u8 epnum = req->epnum;
50630 struct usb_request *request = &req->request;
50631 - struct musb_ep *musb_ep = &musb->endpoints[epnum].ep_out;
50632 + struct musb_ep *musb_ep = NULL;
50633 void __iomem *epio = musb->endpoints[epnum].regs;
50634 - unsigned fifo_count = 0;
50635 - u16 len = musb_ep->packet_sz;
50636 + u16 fifo_count = 0;
50639 + if (musb->endpoints[epnum].is_shared_fifo)
50640 + musb_ep = &musb->endpoints[epnum].ep_in;
50642 + musb_ep = &musb->endpoints[epnum].ep_out;
50643 + len = musb_ep->packet_sz;
50645 csr = musb_readw(epio, MUSB_RXCSR);
50647 @@ -726,7 +732,7 @@ static void rxstate(struct musb *musb, s
50650 /* ack the read! */
50651 - csr |= MUSB_RXCSR_P_WZC_BITS;
50652 + csr &= ~MUSB_RXCSR_P_WZC_BITS;
50653 csr &= ~MUSB_RXCSR_RXPKTRDY;
50654 musb_writew(epio, MUSB_RXCSR, csr);
50656 @@ -745,10 +751,15 @@ void musb_g_rx(struct musb *musb, u8 epn
50658 struct usb_request *request;
50659 void __iomem *mbase = musb->mregs;
50660 - struct musb_ep *musb_ep = &musb->endpoints[epnum].ep_out;
50661 + struct musb_ep *musb_ep = NULL;
50662 void __iomem *epio = musb->endpoints[epnum].regs;
50663 struct dma_channel *dma;
50665 + if (musb->endpoints[epnum].is_shared_fifo)
50666 + musb_ep = &musb->endpoints[epnum].ep_in;
50668 + musb_ep = &musb->endpoints[epnum].ep_out;
50670 musb_ep_select(mbase, epnum);
50672 request = next_request(musb_ep);
50673 @@ -1769,7 +1780,9 @@ int usb_gadget_register_driver(struct us
50678 +#ifndef CONFIG_USB_MUSB_OTG
50679 + musb_pullup(musb, 1);
50683 EXPORT_SYMBOL(usb_gadget_register_driver);
50684 --- a/drivers/usb/musb/musb_gadget_ep0.c
50685 +++ b/drivers/usb/musb/musb_gadget_ep0.c
50686 @@ -240,14 +240,14 @@ __acquires(musb->lock)
50687 case USB_REQ_SET_ADDRESS:
50688 /* change it after the status stage */
50689 musb->set_address = true;
50690 - musb->address = (u8) (ctrlrequest->wValue & 0x7f);
50691 + musb->address = (u8) (le16_to_cpu(ctrlrequest->wValue) & 0x7f);
50695 case USB_REQ_CLEAR_FEATURE:
50697 case USB_RECIP_DEVICE:
50698 - if (ctrlrequest->wValue
50699 + if (le16_to_cpu(ctrlrequest->wValue)
50700 != USB_DEVICE_REMOTE_WAKEUP)
50702 musb->may_wakeup = 0;
50703 @@ -261,8 +261,8 @@ __acquires(musb->lock)
50706 || num >= MUSB_C_NUM_EPS
50707 - || ctrlrequest->wValue
50708 - != USB_ENDPOINT_HALT)
50709 + || le16_to_cpu(ctrlrequest->wValue
50710 + != USB_ENDPOINT_HALT))
50713 if (ctrlrequest->wIndex & USB_DIR_IN)
50714 @@ -292,7 +292,7 @@ __acquires(musb->lock)
50716 case USB_RECIP_DEVICE:
50718 - switch (ctrlrequest->wValue) {
50719 + switch (le16_to_cpu(ctrlrequest->wValue)) {
50720 case USB_DEVICE_REMOTE_WAKEUP:
50721 musb->may_wakeup = 1;
50723 @@ -374,8 +374,8 @@ stall:
50726 || epnum >= MUSB_C_NUM_EPS
50727 - || ctrlrequest->wValue
50728 - != USB_ENDPOINT_HALT)
50729 + || le16_to_cpu(ctrlrequest->wValue
50730 + != USB_ENDPOINT_HALT))
50733 ep = musb->endpoints + epnum;
50734 --- a/drivers/usb/musb/musb_host.c
50735 +++ b/drivers/usb/musb/musb_host.c
50736 @@ -160,7 +160,11 @@ static inline void musb_h_tx_start(struc
50737 /* NOTE: no locks here; caller should lock and select EP */
50739 txcsr = musb_readw(ep->regs, MUSB_TXCSR);
50740 +#ifndef CONFIG_UBICOM32
50741 txcsr |= MUSB_TXCSR_TXPKTRDY | MUSB_TXCSR_H_WZC_BITS;
50743 + txcsr |= (MUSB_TXCSR_TXPKTRDY & (~MUSB_TXCSR_H_WZC_BITS));
50745 musb_writew(ep->regs, MUSB_TXCSR, txcsr);
50747 txcsr = MUSB_CSR0_H_SETUPPKT | MUSB_CSR0_TXPKTRDY;
50748 @@ -223,6 +227,8 @@ musb_start_urb(struct musb *musb, int is
50750 default: /* bulk, interrupt */
50751 /* actual_length may be nonzero on retry paths */
50752 + if (urb->actual_length)
50753 + DBG(3 ,"musb_start_urb: URB %p retried, len: %d\n", urb, urb->actual_length);
50754 buf = urb->transfer_buffer + urb->actual_length;
50755 len = urb->transfer_buffer_length - urb->actual_length;
50757 @@ -342,13 +348,13 @@ musb_save_toggle(struct musb_hw_ep *ep,
50759 csr = musb_readw(epio, MUSB_TXCSR);
50760 usb_settoggle(udev, qh->epnum, 1,
50761 - (csr & MUSB_TXCSR_H_DATATOGGLE)
50763 + ((csr & MUSB_TXCSR_H_DATATOGGLE)
50766 csr = musb_readw(epio, MUSB_RXCSR);
50767 usb_settoggle(udev, qh->epnum, 0,
50768 - (csr & MUSB_RXCSR_H_DATATOGGLE)
50770 + ((csr & MUSB_RXCSR_H_DATATOGGLE)
50775 @@ -556,7 +562,11 @@ musb_host_packet_rx(struct musb *musb, s
50776 musb_read_fifo(hw_ep, length, buf);
50778 csr = musb_readw(epio, MUSB_RXCSR);
50779 +#ifndef CONFIG_UBICOM32
50780 csr |= MUSB_RXCSR_H_WZC_BITS;
50782 + csr &= ~MUSB_RXCSR_H_WZC_BITS;
50784 if (unlikely(do_flush))
50785 musb_h_flush_rxfifo(hw_ep, csr);
50787 @@ -590,6 +600,7 @@ musb_rx_reinit(struct musb *musb, struct
50789 /* if programmed for Tx, put it in RX mode */
50790 if (ep->is_shared_fifo) {
50791 +#ifndef CONFIG_UBICOM32
50792 csr = musb_readw(ep->regs, MUSB_TXCSR);
50793 if (csr & MUSB_TXCSR_MODE) {
50794 musb_h_tx_flush_fifo(ep);
50795 @@ -604,7 +615,18 @@ musb_rx_reinit(struct musb *musb, struct
50797 if (csr & MUSB_TXCSR_DMAMODE)
50798 musb_writew(ep->regs, MUSB_TXCSR, MUSB_TXCSR_DMAMODE);
50801 + /* clear mode (and everything else) to enable Rx */
50802 musb_writew(ep->regs, MUSB_TXCSR, 0);
50803 + /* scrub all previous state, clearing toggle */
50804 + csr = musb_readw(ep->regs, MUSB_RXCSR);
50805 + if (csr & MUSB_RXCSR_RXPKTRDY)
50806 + WARNING("rx%d, packet/%d ready?\n", ep->epnum,
50807 + musb_readw(ep->regs, MUSB_RXCOUNT));
50809 + musb_h_flush_rxfifo(ep, MUSB_RXCSR_CLRDATATOG);
50812 /* scrub all previous state, clearing toggle */
50814 @@ -1138,8 +1160,18 @@ void musb_host_tx(struct musb *musb, u8
50815 void __iomem *mbase = musb->mregs;
50816 struct dma_channel *dma;
50818 +#ifdef CONFIG_UBICOM32
50819 + if (hw_ep->is_shared_fifo) {
50820 + qh = hw_ep->in_qh;
50822 +#ifdef CONFIG_USB_SERIAL_SIERRAWIRELESS
50823 + printk(KERN_DEBUG "OUT/TX%d end, csr %04x%s\n", epnum, tx_csr,
50824 + dma ? ", dma" : "");
50827 urb = next_urb(qh);
50830 musb_ep_select(mbase, epnum);
50831 tx_csr = musb_readw(epio, MUSB_TXCSR);
50833 @@ -1180,9 +1212,14 @@ void musb_host_tx(struct musb *musb, u8
50834 * we have a candidate... NAKing is *NOT* an error
50836 musb_ep_select(mbase, epnum);
50837 +#ifndef CONFIG_UBICOM32
50838 musb_writew(epio, MUSB_TXCSR,
50839 MUSB_TXCSR_H_WZC_BITS
50840 | MUSB_TXCSR_TXPKTRDY);
50842 + musb_writew(epio, MUSB_TXCSR,
50843 + MUSB_TXCSR_TXPKTRDY);
50848 @@ -1353,8 +1390,14 @@ void musb_host_tx(struct musb *musb, u8
50849 qh->segsize = length;
50851 musb_ep_select(mbase, epnum);
50852 +#ifndef CONFIG_UBICOM32
50853 + musb_writew(epio, MUSB_TXCSR,
50854 + MUSB_TXCSR_H_WZC_BITS | MUSB_TXCSR_TXPKTRDY);
50856 musb_writew(epio, MUSB_TXCSR,
50857 - MUSB_TXCSR_H_WZC_BITS | MUSB_TXCSR_TXPKTRDY);
50858 + MUSB_TXCSR_MODE | MUSB_TXCSR_TXPKTRDY);
50864 @@ -1414,7 +1457,11 @@ static void musb_bulk_rx_nak_timeout(str
50866 /* clear nak timeout bit */
50867 rx_csr = musb_readw(epio, MUSB_RXCSR);
50868 +#ifndef CONFIG_UBICOM32
50869 rx_csr |= MUSB_RXCSR_H_WZC_BITS;
50871 + rx_csr &= ~MUSB_RXCSR_H_WZC_BITS;
50873 rx_csr &= ~MUSB_RXCSR_DATAERROR;
50874 musb_writew(epio, MUSB_RXCSR, rx_csr);
50876 @@ -1483,6 +1530,13 @@ void musb_host_rx(struct musb *musb, u8
50880 +#ifdef CONFIG_UBICOM32
50881 +#ifdef CONFIG_USB_SERIAL_SIERRAWIRELESS
50882 + printk(KERN_DEBUG "RXCSR%d %04x, reqpkt, len %zu%s\n", epnum, rx_csr,
50883 + xfer_len, dma ? ", dma" : "");
50887 DBG(5, "<== hw %d rxcsr %04x, urb actual %d (+dma %zu)\n",
50888 epnum, rx_csr, urb->actual_length,
50889 dma ? dma->actual_len : 0);
50890 @@ -1521,8 +1575,15 @@ void musb_host_rx(struct musb *musb, u8
50893 musb_ep_select(mbase, epnum);
50894 +#ifndef CONFIG_UBICOM32
50895 rx_csr |= MUSB_RXCSR_H_WZC_BITS;
50896 rx_csr &= ~MUSB_RXCSR_DATAERROR;
50898 + /* NEED TO EVALUATE CHANGE */
50899 + rx_csr &= ~MUSB_RXCSR_H_WZC_BITS;
50900 + rx_csr &= ~MUSB_RXCSR_DATAERROR;
50901 +// musb_writew(epio, MUSB_RXCSR, (~(MUSB_RXCSR_H_WZC_BITS))| MUSB_RXCSR_H_REQPKT);
50903 musb_writew(epio, MUSB_RXCSR, rx_csr);
50906 @@ -1579,8 +1640,13 @@ void musb_host_rx(struct musb *musb, u8
50907 rx_csr &= ~MUSB_RXCSR_H_REQPKT;
50909 musb_ep_select(mbase, epnum);
50910 +#ifndef CONFIG_UBICOM32
50911 musb_writew(epio, MUSB_RXCSR,
50912 MUSB_RXCSR_H_WZC_BITS | rx_csr);
50914 + musb_writew(epio, MUSB_RXCSR,
50915 + (~MUSB_RXCSR_H_WZC_BITS) & rx_csr);
50919 if (dma && (rx_csr & MUSB_RXCSR_DMAENAB)) {
50920 @@ -1610,7 +1676,7 @@ void musb_host_rx(struct musb *musb, u8
50926 /* done if urb buffer is full or short packet is recd */
50927 done = (urb->actual_length + xfer_len >=
50928 urb->transfer_buffer_length
50929 @@ -1823,7 +1889,11 @@ static int musb_schedule(
50930 } else if (hw_ep->out_qh != NULL)
50933 +#ifndef CONFIG_UBICOM32
50934 if (hw_ep == musb->bulk_ep)
50936 + if ((hw_ep == musb->bulk_ep_in) || (hw_ep == musb->bulk_ep_out)) /* Ubicom */
50941 @@ -1836,7 +1906,14 @@ static int musb_schedule(
50946 +#ifdef CONFIG_UBICOM32
50947 + if (((best_diff >= qh->maxpacket)) && ((qh->type == USB_ENDPOINT_XFER_BULK) && (!is_in)))
50951 /* use bulk reserved ep1 if no other ep is free */
50952 +#ifndef CONFIG_UBICOM32
50953 if (best_end < 0 && qh->type == USB_ENDPOINT_XFER_BULK) {
50954 hw_ep = musb->bulk_ep;
50956 @@ -1858,6 +1935,22 @@ static int musb_schedule(
50957 } else if (best_end < 0) {
50961 + if (best_end < 0 && qh->type == USB_ENDPOINT_XFER_BULK) {
50962 + /* hw_ep = musb->bulk_ep; */
50964 + head = &musb->in_bulk;
50965 + hw_ep = musb->bulk_ep_in; /* UBICOM */
50968 + head = &musb->out_bulk;
50969 + hw_ep = musb->bulk_ep_out; /* UBICOM */
50972 + } else if (best_end < 0) {
50979 @@ -1869,6 +1962,13 @@ success:
50980 list_add_tail(&qh->ring, head);
50984 + * It's not make sense to set NAK timeout when qh->mux = 0,
50985 + * There is nothing else to schedule
50987 + if ((qh->type == USB_ENDPOINT_XFER_BULK) && (qh->mux == 0))
50988 + qh->intv_reg = 0;
50991 qh->hep->hcpriv = qh;
50993 @@ -1975,6 +2075,15 @@ static int musb_urb_enqueue(
50994 /* ISO always uses logarithmic encoding */
50995 interval = min_t(u8, epd->bInterval, 16);
50997 +#ifdef COMFIG_UBICOM32
50998 + case USB_ENDPOINT_XFER_BULK:
50999 + if (epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
51000 + interval = (USB_SPEED_HIGH == urb->dev->speed) ? 16: 2;
51007 /* REVISIT we actually want to use NAK limits, hinting to the
51008 * transfer scheduling logic to try some other qh, e.g. try
51009 --- a/drivers/usb/musb/musb_io.h
51010 +++ b/drivers/usb/musb/musb_io.h
51011 @@ -58,6 +58,7 @@ static inline void writesb(const void __
51013 #ifndef CONFIG_BLACKFIN
51015 +#ifndef CONFIG_UBICOM32
51016 /* NOTE: these offsets are all in bytes */
51018 static inline u16 musb_readw(const void __iomem *addr, unsigned offset)
51019 @@ -72,7 +73,37 @@ static inline void musb_writew(void __io
51021 static inline void musb_writel(void __iomem *addr, unsigned offset, u32 data)
51022 { __raw_writel(data, addr + offset); }
51024 +#include <asm/ubicom32-tio.h>
51025 +static inline u16 musb_readw(const void __iomem *addr, unsigned offset)
51028 + usb_tio_read_u16((u32)(addr + offset), &data);
51032 +static inline u8 musb_readb(const void __iomem *addr, unsigned offset)
51035 + usb_tio_read_u8((u32)(addr + offset), &data);
51039 +static inline void musb_writew(void __iomem *addr, unsigned offset, u16 data)
51041 + usb_tio_write_u16((u32)(addr + offset), data);
51044 +static inline void musb_writeb(void __iomem *addr, unsigned offset, u8 data)
51046 + usb_tio_write_u8((u32)(addr + offset), data);
51049 +static inline void musb_read_int_status(u8_t *int_usb, u16_t *int_tx, u16_t *int_rx)
51051 + return usb_tio_read_int_status(int_usb, int_tx, int_rx);
51053 +#endif /* CONFIG_UBICOM32 */
51055 #ifdef CONFIG_USB_TUSB6010
51057 @@ -106,7 +137,7 @@ static inline void musb_writeb(void __io
51058 __raw_writew(tmp, addr + (offset & ~1));
51062 +#elif !defined(CONFIG_UBICOM32)
51064 static inline u8 musb_readb(const void __iomem *addr, unsigned offset)
51065 { return __raw_readb(addr + offset); }
51066 --- a/drivers/usb/musb/musb_regs.h
51067 +++ b/drivers/usb/musb/musb_regs.h
51068 @@ -167,6 +167,7 @@
51069 (MUSB_TXCSR_H_NAKTIMEOUT | MUSB_TXCSR_H_RXSTALL \
51070 | MUSB_TXCSR_H_ERROR | MUSB_TXCSR_FIFONOTEMPTY)
51073 /* RXCSR in Peripheral and Host mode */
51074 #define MUSB_RXCSR_AUTOCLEAR 0x8000
51075 #define MUSB_RXCSR_DMAENAB 0x2000
51077 +++ b/drivers/usb/musb/ubi32_usb.c
51080 + * drivers/usb/musb/ubi32_usb.c
51081 + * Ubicom32 usb controller driver.
51083 + * (C) Copyright 2009, Ubicom, Inc.
51084 + * Copyright (C) 2005-2006 by Texas Instruments
51086 + * Derived from the Texas Instruments Inventra Controller Driver for Linux.
51088 + * This file is part of the Ubicom32 Linux Kernel Port.
51090 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
51091 + * it and/or modify it under the terms of the GNU General Public License
51092 + * as published by the Free Software Foundation, either version 2 of the
51093 + * License, or (at your option) any later version.
51095 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
51096 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
51097 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
51098 + * the GNU General Public License for more details.
51100 + * You should have received a copy of the GNU General Public License
51101 + * along with the Ubicom32 Linux Kernel Port. If not,
51102 + * see <http://www.gnu.org/licenses/>.
51104 + * Ubicom32 implementation derived from (with many thanks):
51109 +#include <linux/module.h>
51110 +#include <linux/kernel.h>
51111 +#include <linux/sched.h>
51112 +#include <linux/slab.h>
51113 +#include <linux/init.h>
51114 +#include <linux/list.h>
51115 +#include <linux/clk.h>
51116 +#include <linux/io.h>
51118 +#include <asm/io.h>
51119 +#include <asm/ip5000.h>
51120 +#include "musb_core.h"
51122 +void musb_platform_enable(struct musb *musb)
51125 +void musb_platform_disable(struct musb *musb)
51129 +int musb_platform_set_mode(struct musb *musb, u8 musb_mode) {
51133 +static void ip5k_usb_hcd_vbus_power(struct musb *musb, int is_on, int sleeping)
51137 +static void ip5k_usb_hcd_set_vbus(struct musb *musb, int is_on)
51140 + /* HDRC controls CPEN, but beware current surges during device
51141 + * connect. They can trigger transient overcurrent conditions
51142 + * that must be ignored.
51145 + devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
51148 + musb->is_active = 1;
51149 + musb->xceiv.default_a = 1;
51150 + musb->xceiv.state = OTG_STATE_A_WAIT_VRISE;
51151 + devctl |= MUSB_DEVCTL_SESSION;
51153 + MUSB_HST_MODE(musb);
51155 + musb->is_active = 0;
51157 + /* NOTE: we're skipping A_WAIT_VFALL -> A_IDLE and
51158 + * jumping right to B_IDLE...
51161 + musb->xceiv.default_a = 0;
51162 + musb->xceiv.state = OTG_STATE_B_IDLE;
51163 + devctl &= ~MUSB_DEVCTL_SESSION;
51165 + MUSB_DEV_MODE(musb);
51167 + musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
51169 + DBG(1, "VBUS %s, devctl %02x "
51170 + /* otg %3x conf %08x prcm %08x */ "\n",
51171 + otg_state_string(musb),
51172 + musb_readb(musb->mregs, MUSB_DEVCTL));
51174 +static int ip5k_usb_hcd_set_power(struct otg_transceiver *x, unsigned mA)
51179 +static int musb_platform_resume(struct musb *musb);
51181 +int __init musb_platform_init(struct musb *musb)
51184 +#ifdef CONFIG_UBICOM32_V4
51187 + "move.4 %0, CHIP_ID \n\t"
51190 + if (chip_id == 0x30001) {
51191 + *((u32_t *)(GENERAL_CFG_BASE + GEN_USB_PHY_TEST)) &= ~(1 << 30);
51193 + *((u32_t *)(GENERAL_CFG_BASE + GEN_USB_PHY_TEST)) &= ~(1 << 31);
51195 + *((u32_t *)(GENERAL_CFG_BASE + GEN_USB_PHY_TEST)) &= ~(1 << 17);
51197 + *((u32_t *)(GENERAL_CFG_BASE + GEN_USB_PHY_TEST)) &= ~(1 << 14);
51201 + *((u32_t *)(GENERAL_CFG_BASE + GEN_USB_PHY_CFG)) |= ((1 << 14) | (1 <<15));
51203 + /* The i-clk is AUTO gated. Hence there is no need
51204 + * to disable it until the driver is shutdown */
51206 + clk_enable(musb->clock);
51207 + musb_platform_resume(musb);
51209 + ip5k_usb_hcd_vbus_power(musb, musb->board_mode == MUSB_HOST, 1);
51211 + if (is_host_enabled(musb))
51212 + musb->board_set_vbus = ip5k_usb_hcd_set_vbus;
51213 + if (is_peripheral_enabled(musb))
51214 + musb->xceiv.set_power = ip5k_usb_hcd_set_power;
51220 +int musb_platform_suspend(struct musb *musb)
51224 +int musb_platform_resume(struct musb *musb)
51229 +int musb_platform_exit(struct musb *musb)
51231 + ip5k_usb_hcd_vbus_power(musb, 0 /*off*/, 1);
51232 + musb_platform_suspend(musb);
51235 --- a/drivers/video/backlight/Kconfig
51236 +++ b/drivers/video/backlight/Kconfig
51237 @@ -93,6 +93,63 @@ config LCD_HP700
51238 If you have an HP Jornada 700 series handheld (710/720/728)
51239 say Y to enable LCD control driver.
51241 +config LCD_UBICOM32POWER
51242 + tristate "Ubicom LCD power Driver"
51243 + depends on LCD_CLASS_DEVICE && UBICOM32
51246 + If you have a Ubicom32 based system with an LCD panel that requires
51247 + power control, say Y to enable the power control driver for it.
51249 +config LCD_UBICOM32
51250 + tristate "Ubicom Backlight Driver"
51251 + depends on LCD_CLASS_DEVICE && UBICOM32
51254 + This driver takes care of initialization of LCD panels with
51255 + built in controllers.
51257 +menu "Ubicom32 LCD Panel Support"
51258 + depends on UBICOM32 && LCD_UBICOM32
51260 +config LCD_UBICOM32_TFT2N0369E_P
51261 + bool "TFT2N0369E (Portrait)"
51264 + Support for TFT2N0369 in portrait mode
51266 +config LCD_UBICOM32_TFT2N0369E_L
51267 + bool "TFT2N0369E (Landscape)"
51270 + Support for TFT2N0369 in landscape mode
51272 +config LCD_UBICOM32_CFAF240320KTTS
51273 + bool "CFAF240320KTTS"
51276 + Support for CFAF240320KTTS
51278 +config LCD_UBICOM32_CFAF240320KTTS_180
51279 + bool "CFAF240320KTTS (180 rotation)"
51282 + Support for CFAF240320KTTS rotated 180 degrees
51284 +config LCD_UBICOM32_CFAF240320D
51285 + bool "CFAF240320D"
51288 + Support for CFAF240320D
51290 +config LCD_UBICOM32_CFAF320240F
51291 + bool "CFAF320240F"
51294 + Support for CFAF320240F
51301 @@ -229,3 +286,11 @@ config BACKLIGHT_SAHARA
51303 If you have a Tabletkiosk Sahara Touch-iT, say y to enable the
51306 +config BACKLIGHT_UBICOM32
51307 + tristate "Ubicom Backlight Driver"
51308 + depends on BACKLIGHT_CLASS_DEVICE && UBICOM32
51311 + If you have a Ubicom32 based system with a backlight say Y to enable the
51312 + backlight driver.
51313 --- a/drivers/video/backlight/Makefile
51314 +++ b/drivers/video/backlight/Makefile
51315 @@ -9,6 +9,9 @@ obj-$(CONFIG_LCD_PLATFORM) += platfor
51316 obj-$(CONFIG_LCD_VGG2432A4) += vgg2432a4.o
51317 obj-$(CONFIG_LCD_TDO24M) += tdo24m.o
51318 obj-$(CONFIG_LCD_TOSA) += tosa_lcd.o
51319 +obj-$(CONFIG_LCD_LTV350QV) += ltv350qv.o
51320 +obj-$(CONFIG_LCD_UBICOM32POWER) += ubicom32lcdpower.o
51321 +obj-$(CONFIG_LCD_UBICOM32) += ubicom32lcd.o
51323 obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o
51324 obj-$(CONFIG_BACKLIGHT_ATMEL_PWM) += atmel-pwm-bl.o
51325 @@ -24,4 +27,4 @@ obj-$(CONFIG_BACKLIGHT_DA903X) += da903x
51326 obj-$(CONFIG_BACKLIGHT_MBP_NVIDIA) += mbp_nvidia_bl.o
51327 obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o
51328 obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o
51330 +obj-$(CONFIG_BACKLIGHT_UBICOM32) += ubicom32bl.o
51332 +++ b/drivers/video/backlight/ubicom32bl.c
51335 + * drivers/video/backlight/ubicom32bl.c
51336 + * Backlight driver for the Ubicom32 platform
51338 + * (C) Copyright 2009, Ubicom, Inc.
51340 + * This file is part of the Ubicom32 Linux Kernel Port.
51342 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
51343 + * it and/or modify it under the terms of the GNU General Public License
51344 + * as published by the Free Software Foundation, either version 2 of the
51345 + * License, or (at your option) any later version.
51347 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
51348 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
51349 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
51350 + * the GNU General Public License for more details.
51352 + * You should have received a copy of the GNU General Public License
51353 + * along with the Ubicom32 Linux Kernel Port. If not,
51354 + * see <http://www.gnu.org/licenses/>.
51356 + * Ubicom32 implementation derived from (with many thanks):
51361 +#include <linux/init.h>
51362 +#include <linux/kernel.h>
51363 +#include <linux/module.h>
51364 +#include <linux/platform_device.h>
51365 +#include <linux/backlight.h>
51366 +#include <linux/fb.h>
51368 +#include <asm/ubicom32bl.h>
51369 +#include <asm/ip5000.h>
51371 +#define DRIVER_NAME "ubicom32bl"
51372 +#define UBICOM32BL_MAX_BRIGHTNESS 255
51374 +struct ubicom32bl_data {
51376 + * Pointer to the platform data structure. Keep this around since we need values
51377 + * from it to set the backlight intensity.
51379 + const struct ubicom32bl_platform_data *pdata;
51382 + * Backlight device, we have to save this for use when we remove ourselves.
51384 + struct backlight_device *bldev;
51387 + * Current intensity, used for get_intensity.
51389 + int cur_intensity;
51392 + * Init function for PWM
51394 + int (*init_fn)(struct ubicom32bl_data *);
51397 + * Set intensity function depending on the backlight type
51399 + int (*set_intensity_fn)(struct ubicom32bl_data *, int);
51403 + * ubicom32bl_set_intensity_gpio
51405 +static int ubicom32bl_set_intensity_gpio(struct ubicom32bl_data *ud, int intensity)
51407 + ud->cur_intensity = intensity ? 255 : 0;
51419 + * ubicom32bl_set_intensity_hw
51421 +static int ubicom32bl_set_intensity_hw(struct ubicom32bl_data *ud, int intensity)
51423 + u16_t period = ud->pdata->pwm_period;
51427 + * Calculate the new duty cycle
51429 + duty = (period * intensity) / (UBICOM32BL_MAX_BRIGHTNESS + 1);
51432 + * Set the new duty cycle
51434 + switch (ud->pdata->pwm_channel) {
51437 + * Channel 0 is in the lower half of PORT C ctl0 and ctl1
51439 + UBICOM32_IO_PORT(RC)->ctl1 = (ud->pdata->pwm_period << 16) | duty;
51444 + * Channel 1 is in the upper half of PORT C ctl0 and ctl2
51446 + UBICOM32_IO_PORT(RC)->ctl2 = (ud->pdata->pwm_period << 16) | duty;
51451 + * Channel 2 is in PORT H ctl0 and ctl1
51453 + UBICOM32_IO_PORT(RH)->ctl1 = (ud->pdata->pwm_period << 16) | duty;
51457 + ud->cur_intensity = intensity;
51463 + * ubicom32bl_set_intensity
51465 +static int ubicom32bl_set_intensity(struct backlight_device *bd)
51467 + struct ubicom32bl_data *ud = (struct ubicom32bl_data *)bl_get_data(bd);
51468 + int intensity = bd->props.brightness;
51471 + * If we're blanked the the intensity doesn't matter.
51473 + if ((bd->props.power != FB_BLANK_UNBLANK) || (bd->props.fb_blank != FB_BLANK_UNBLANK)) {
51478 + * Check for inverted backlight.
51480 + if (ud->pdata->invert) {
51481 + intensity = UBICOM32BL_MAX_BRIGHTNESS - intensity;
51484 + if (ud->set_intensity_fn) {
51485 + return ud->set_intensity_fn(ud, intensity);
51492 + * ubicom32bl_get_intensity
51493 + * Return the current intensity of the backlight.
51495 +static int ubicom32bl_get_intensity(struct backlight_device *bd)
51497 + struct ubicom32bl_data *ud = (struct ubicom32bl_data *)bl_get_data(bd);
51499 + return ud->cur_intensity;
51503 + * ubicom32bl_init_hw_pwm
51504 + * Set the appropriate PWM registers
51506 +static int ubicom32bl_init_hw_pwm(struct ubicom32bl_data *ud)
51511 + u16_t pwm_cfg = (1 << 13) | (ud->pdata->pwm_prescale << 8) ;
51513 + switch (ud->pdata->pwm_channel) {
51516 + * Channel 0 is in the lower half of PORT C ctl0 and ctl1 (PA5)
51518 + UBICOM32_IO_PORT(RC)->ctl0 &= ~0xFFFF;
51519 + UBICOM32_IO_PORT(RC)->ctl0 |= pwm_cfg;
51520 + UBICOM32_IO_PORT(RC)->ctl1 = ud->pdata->pwm_period << 16;
51523 + * If the port function is not set, set it to GPIO/PWM
51525 + if (!UBICOM32_IO_PORT(RA)->function) {
51526 + UBICOM32_IO_PORT(RA)->function = 3;
51532 + * Channel 1 is in the upper half of PORT C ctl0 and ctl2 (PE4)
51534 + UBICOM32_IO_PORT(RC)->ctl0 &= ~0xFFFF0000;
51535 + UBICOM32_IO_PORT(RC)->ctl0 |= (pwm_cfg << 16);
51536 + UBICOM32_IO_PORT(RC)->ctl2 = ud->pdata->pwm_period << 16;
51539 + * If the port function is not set, set it to GPIO/ExtIOInt
51541 + if (!UBICOM32_IO_PORT(RE)->function) {
51542 + UBICOM32_IO_PORT(RE)->function = 3;
51548 + * Channel 2 is in PORT H ctl0 and ctl1 (PD0)
51550 + UBICOM32_IO_PORT(RH)->ctl0 &= ~0xFFFF0000;
51551 + UBICOM32_IO_PORT(RH)->ctl0 = pwm_cfg;
51552 + UBICOM32_IO_PORT(RH)->ctl1 = ud->pdata->pwm_period << 16;
51555 + * If the port function is not set, set it to GPIO
51557 + if (!UBICOM32_IO_PORT(RD)->function) {
51558 + UBICOM32_IO_PORT(RD)->function = 3;
51567 + * ubicom32bl_init_gpio
51568 + * Allocate the appropriate GPIO
51570 +static int ubicom32bl_init_gpio(struct ubicom32bl_data *ud)
51575 +static struct backlight_ops ubicom32bl_ops = {
51576 + .get_brightness = ubicom32bl_get_intensity,
51577 + .update_status = ubicom32bl_set_intensity,
51581 + * ubicom32bl_probe
51583 +static int ubicom32bl_probe(struct platform_device *pdev)
51585 + const struct ubicom32bl_platform_data *pdata = pdev->dev.platform_data;
51586 + struct ubicom32bl_data *ud;
51587 + struct backlight_device *bldev;
51591 + * Check to see if we have any platform data, if we don't then the backlight is not
51592 + * configured on this device.
51599 + * Allocate our private data
51601 + ud = kzalloc(sizeof(struct ubicom32bl_data), GFP_KERNEL);
51606 + ud->pdata = pdata;
51609 + * Check to see that the platform data is valid for this driver
51611 + switch (pdata->type) {
51612 + case UBICOM32BL_TYPE_PWM:
51615 + * Make sure we have a PWM peripheral
51619 + "move.4 %0, CHIP_ID \n\t"
51622 + if (chipid != 0x00030001) {
51623 + retval = -ENODEV;
51627 + if (pdata->pwm_channel > 3) {
51628 + retval = -ENODEV;
51631 + if (pdata->pwm_prescale > 16) {
51632 + retval = -EINVAL;
51636 + ud->init_fn = ubicom32bl_init_hw_pwm;
51637 + ud->set_intensity_fn = ubicom32bl_set_intensity_hw;
51641 + case UBICOM32BL_TYPE_PWM_HRT:
51642 + // For now, PWM HRT devices are treated as binary lights.
51644 + case UBICOM32BL_TYPE_BINARY:
51645 + ud->init_fn = ubicom32bl_init_gpio;
51646 + ud->set_intensity_fn = ubicom32bl_set_intensity_gpio;
51651 + * Register our backlight device
51653 + bldev = backlight_device_register(DRIVER_NAME, &pdev->dev, ud, &ubicom32bl_ops);
51654 + if (IS_ERR(bldev)) {
51655 + retval = PTR_ERR(bldev);
51659 + ud->bldev = bldev;
51660 + ud->cur_intensity = pdata->default_intensity;
51661 + platform_set_drvdata(pdev, ud);
51664 + * Start up the backlight at the prescribed default intensity
51666 + bldev->props.power = FB_BLANK_UNBLANK;
51667 + bldev->props.max_brightness = UBICOM32BL_MAX_BRIGHTNESS;
51668 + bldev->props.brightness = pdata->default_intensity;
51670 + if (ud->init_fn) {
51671 + if (ud->init_fn(ud) != 0) {
51672 + retval = -ENODEV;
51673 + backlight_device_unregister(ud->bldev);
51677 + ubicom32bl_set_intensity(bldev);
51679 + printk(KERN_INFO DRIVER_NAME ": Backlight driver started\n");
51684 + platform_set_drvdata(pdev, NULL);
51690 + * ubicom32bl_remove
51692 +static int __exit ubicom32bl_remove(struct platform_device *pdev)
51694 + struct ubicom32bl_data *ud = platform_get_drvdata(pdev);
51696 + backlight_device_unregister(ud->bldev);
51697 + platform_set_drvdata(pdev, NULL);
51703 +static struct platform_driver ubicom32bl_driver = {
51705 + .name = DRIVER_NAME,
51706 + .owner = THIS_MODULE,
51709 + .remove = __exit_p(ubicom32bl_remove),
51713 + * ubicom32bl_init
51715 +static int __init ubicom32bl_init(void)
51717 + return platform_driver_probe(&ubicom32bl_driver, ubicom32bl_probe);
51719 +module_init(ubicom32bl_init);
51722 + * ubicom32bl_exit
51724 +static void __exit ubicom32bl_exit(void)
51726 + platform_driver_unregister(&ubicom32bl_driver);
51728 +module_exit(ubicom32bl_exit);
51730 +MODULE_AUTHOR("Patrick Tjin <@ubicom.com>");
51731 +MODULE_DESCRIPTION("Ubicom32 backlight driver");
51732 +MODULE_LICENSE("GPL");
51734 +++ b/drivers/video/backlight/ubicom32lcd.c
51737 + * drivers/video/ubicom32lcd.c
51738 + * LCD initilization code
51740 + * (C) Copyright 2009, Ubicom, Inc.
51742 + * This file is part of the Ubicom32 Linux Kernel Port.
51744 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
51745 + * it and/or modify it under the terms of the GNU General Public License
51746 + * as published by the Free Software Foundation, either version 2 of the
51747 + * License, or (at your option) any later version.
51749 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
51750 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
51751 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
51752 + * the GNU General Public License for more details.
51754 + * You should have received a copy of the GNU General Public License
51755 + * along with the Ubicom32 Linux Kernel Port. If not,
51756 + * see <http://www.gnu.org/licenses/>.
51758 +#include <linux/init.h>
51759 +#include <linux/kernel.h>
51760 +#include <linux/module.h>
51761 +#include <linux/platform_device.h>
51762 +#include <linux/delay.h>
51764 +#include <asm/ip5000.h>
51765 +#include <asm/gpio.h>
51766 +#include <asm/ubicom32lcd.h>
51768 +#include "ubicom32lcd.h"
51770 +#define DRIVER_NAME "ubicom32lcd"
51772 +struct ubicom32lcd_data {
51773 + const struct ubicom32lcd_panel *panel;
51780 + struct ubicom32_io_port *port_data;
51785 + * ubicom32lcd_write
51786 + * Performs a write cycle on the bus (assumes CS asserted, RD & WR set)
51788 +static void ubicom32lcd_write(struct ubicom32lcd_data *ud, int command, u16 data)
51791 + UBICOM32_GPIO_SET_PIN_LOW(ud->pin_rs);
51793 + UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_rs);
51797 + "or.4 4(%[port]), 4(%[port]), %[mask] \n\t"
51798 + "not.4 %[mask], %[mask] \n\t"
51799 + "and.4 8(%[port]), 8(%[port]), %[mask] \n\t"
51800 + "or.4 8(%[port]), 8(%[port]), %[cmd] \n\t"
51802 + : [port] "a" (ud->port_data),
51803 + [mask] "d" (0xFFFF << ud->data_shift),
51804 + [cmd] "d" (data << ud->data_shift)
51808 + UBICOM32_GPIO_SET_PIN_LOW(ud->pin_wr);
51813 + UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_wr);
51820 + * ubicom32lcd_read_data
51821 + * Performs a read cycle on the bus (assumes CS asserted, RD & WR set)
51823 +static u16 ubicom32lcd_read_data(struct ubicom32lcd_data *ud)
51827 + UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_rs);
51830 + "and.4 4(%[port]), 4(%[port]), %[mask]\n\t"
51832 + : [port] "a" (ud->port_data),
51833 + [mask] "d" (~(0xFFFF << ud->data_shift))
51837 + UBICOM32_GPIO_SET_PIN_LOW(ud->pin_rd);
51842 + "lsr.4 %[data], 12(%[port]), %[shamt] \n\t"
51843 + "and.4 %[data], %[data], %[mask] \n\t"
51844 + : [data] "=d" (data)
51845 + : [port] "a" (ud->port_data),
51846 + [mask] "d" (0xFFFF),
51847 + [shamt] "d" (ud->data_shift)
51853 + UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_rd);
51861 + * ubicom32lcd_execute
51862 + * Executes a script for performing operations on the LCD (assumes CS set)
51864 +static void ubicom32lcd_execute(struct ubicom32lcd_data *ud, const struct ubicom32lcd_step *script)
51867 + switch (script->op) {
51868 + case LCD_STEP_CMD:
51869 + ubicom32lcd_write(ud, 1, script->cmd);
51872 + case LCD_STEP_DATA:
51873 + ubicom32lcd_write(ud, 0, script->data);
51876 + case LCD_STEP_CMD_DATA:
51877 + ubicom32lcd_write(ud, 1, script->cmd);
51878 + ubicom32lcd_write(ud, 0, script->data);
51881 + case LCD_STEP_SLEEP:
51882 + udelay(script->data);
51885 + case LCD_STEP_DONE:
51893 + * ubicom32lcd_goto
51894 + * Places the gram pointer at a specific X, Y address
51896 +static void ubicom32lcd_goto(struct ubicom32lcd_data *ud, int x, int y)
51898 + ubicom32lcd_write(ud, 1, ud->panel->horz_reg);
51899 + ubicom32lcd_write(ud, 0, x);
51900 + ubicom32lcd_write(ud, 1, ud->panel->vert_reg);
51901 + ubicom32lcd_write(ud, 0, y);
51902 + ubicom32lcd_write(ud, 1, ud->panel->gram_reg);
51906 + * ubicom32lcd_panel_init
51907 + * Initializes the lcd panel.
51909 +static int ubicom32lcd_panel_init(struct ubicom32lcd_data *ud)
51913 + UBICOM32_GPIO_SET_PIN_LOW(ud->pin_reset);
51914 + UBICOM32_GPIO_SET_PIN_OUTPUT(ud->pin_reset);
51915 + UBICOM32_GPIO_ENABLE(ud->pin_reset);
51918 + "or.4 0x50(%[port]), 0x50(%[port]), %[mask] \n\t"
51919 + "not.4 %[mask], %[mask] \n\t"
51920 + "and.4 0x04(%[port]), 0x04(%[port]), %[mask] \n\t"
51922 + : [port] "a" (ud->port_data),
51923 + [mask] "d" (0xFFFF << ud->data_shift)
51927 + UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_rs);
51928 + UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_rd);
51929 + UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_wr);
51930 + UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_cs);
51932 + UBICOM32_GPIO_SET_PIN_OUTPUT(ud->pin_rs);
51933 + UBICOM32_GPIO_SET_PIN_OUTPUT(ud->pin_rd);
51934 + UBICOM32_GPIO_SET_PIN_OUTPUT(ud->pin_wr);
51935 + UBICOM32_GPIO_SET_PIN_OUTPUT(ud->pin_cs);
51937 + UBICOM32_GPIO_ENABLE(ud->pin_rs);
51938 + UBICOM32_GPIO_ENABLE(ud->pin_rd);
51939 + UBICOM32_GPIO_ENABLE(ud->pin_wr);
51940 + UBICOM32_GPIO_ENABLE(ud->pin_cs);
51944 + UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_reset);
51948 + UBICOM32_GPIO_SET_PIN_LOW(ud->pin_cs);
51950 + id = ubicom32lcd_read_data(ud);
51953 + * We will try to figure out what kind of panel we have if we were not told.
51955 + if (!ud->panel) {
51956 + const struct ubicom32lcd_panel **p = ubicom32lcd_panels;
51958 + if ((*p)->id && ((*p)->id == id)) {
51964 + printk(KERN_WARNING DRIVER_NAME ":Could not find compatible panel, id=%x\n", id);
51971 + * Make sure panel ID matches if we were supplied a panel type
51973 + if (ud->panel->id && (ud->panel->id != id)) {
51974 + UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_cs);
51979 + ubicom32lcd_execute(ud, ud->panel->init_seq);
51981 + ubicom32lcd_goto(ud, 0, 0);
51983 + UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_cs);
51984 + UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_rd);
51985 + UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_wr);
51986 + UBICOM32_GPIO_SET_PIN_HIGH(ud->pin_rs);
51988 + printk(KERN_INFO DRIVER_NAME ": Initialized panel %s\n", ud->panel->desc);
51994 + * ubicom32lcd_probe
51996 +static int ubicom32lcd_probe(struct platform_device *pdev)
51998 + const struct ubicom32lcd_platform_data *pdata = pdev->dev.platform_data;
51999 + struct ubicom32lcd_data *ud;
52003 + * Allocate our private data
52005 + ud = kzalloc(sizeof(struct ubicom32lcd_data), GFP_KERNEL);
52011 + ud->pin_cs = pdata->pin_cs;
52012 + ud->pin_rd = pdata->pin_rd;
52013 + ud->pin_wr = pdata->pin_wr;
52014 + ud->pin_rs = pdata->pin_rs;
52015 + ud->pin_reset = pdata->pin_reset;
52016 + ud->port_data = pdata->port_data;
52017 + ud->data_shift = pdata->data_shift;
52022 + ud->pin_cs = GPIO_RD_4;
52023 + ud->pin_rd = GPIO_RD_5;
52024 + ud->pin_rs = GPIO_RD_3;
52025 + ud->pin_wr = GPIO_RD_2;
52026 + ud->pin_reset = GPIO_RD_7;
52027 + ud->port_data = (struct ubicom32_io_port *)RI;
52028 + ud->data_shift = 0;
52032 + * Initialize the display
52034 + retval = ubicom32lcd_panel_init(ud);
52040 + printk(KERN_INFO DRIVER_NAME ": LCD initialized\n");
52046 + * ubicom32lcd_remove
52048 +static int __exit ubicom32lcd_remove(struct platform_device *pdev)
52050 + struct ubicom32lcd_data *ud = platform_get_drvdata(pdev);
52057 +static struct platform_driver ubicom32lcd_driver = {
52058 + .probe = ubicom32lcd_probe,
52059 + .remove = ubicom32lcd_remove,
52062 + .name = DRIVER_NAME,
52063 + .owner = THIS_MODULE,
52066 + .remove = __exit_p(ubicom32lcd_remove),
52069 +static struct platform_device *ubicom32lcd_device;
52072 + * ubicom32lcd_init
52074 +static int __init ubicom32lcd_init(void)
52078 + res = platform_driver_register(&ubicom32lcd_driver);
52080 + ubicom32lcd_device = platform_device_alloc(DRIVER_NAME, 0);
52081 + if (ubicom32lcd_device) {
52082 + res = platform_device_add(ubicom32lcd_device);
52087 + platform_device_put(ubicom32lcd_device);
52088 + platform_driver_unregister(&ubicom32lcd_driver);
52093 +module_init(ubicom32lcd_init);
52096 + * ubicom32lcd_exit
52098 +static void __exit ubicom32lcd_exit(void)
52100 + platform_device_unregister(ubicom32lcd_device);
52101 + platform_driver_unregister(&ubicom32lcd_driver);
52103 +module_exit(ubicom32lcd_exit);
52105 +MODULE_AUTHOR("Patrick Tjin <@ubicom.com>");
52106 +MODULE_DESCRIPTION("Ubicom32 LCD driver");
52107 +MODULE_LICENSE("GPL");
52109 +++ b/drivers/video/backlight/ubicom32lcd.h
52113 + * Ubicom32 lcd panel drivers
52115 + * (C) Copyright 2009, Ubicom, Inc.
52117 + * This file is part of the Ubicom32 Linux Kernel Port.
52119 + * This Ubicom32 library is free software: you can redistribute
52120 + * it and/or modify it under the terms of the GNU General Public License
52121 + * as published by the Free Software Foundation, either version 2 of the
52122 + * License, or (at your option) any later version.
52124 + * This Ubicom32 library is distributed in the hope that it
52125 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
52126 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
52127 + * the GNU General Public License for more details.
52129 + * You should have received a copy of the GNU General Public License
52130 + * along with the Ubicom32 Linux Kernel Port. If not,
52131 + * see <http://www.gnu.org/licenses/>.
52134 +#ifndef _UBICOM32LCD_H_
52135 +#define _UBICOM32LCD_H_
52137 +enum ubicom32lcd_op {
52139 + * Sleep for (data) ms
52144 + * Execute write of command
52149 + * Execute write of data
52154 + * Execute write of command/data
52156 + LCD_STEP_CMD_DATA,
52164 +struct ubicom32lcd_step {
52165 + enum ubicom32lcd_op op;
52170 +struct ubicom32lcd_panel {
52171 + const struct ubicom32lcd_step *init_seq;
52172 + const char *desc;
52185 +#ifdef CONFIG_LCD_UBICOM32_CFAF240320KTTS
52186 +static const struct ubicom32lcd_step cfaf240320ktts_init_0[] = {
52187 + {LCD_STEP_CMD_DATA, 0x0001, 0x0000,}, // Driver Output Control Register (R01h) Page 14, SPFD5408B Datasheet
52188 + {LCD_STEP_CMD_DATA, 0x0002, 0x0700,}, // LCD Driving Waveform Control (R02h) Page 15, SPFD5408B Datasheet
52189 + {LCD_STEP_CMD_DATA, 0x0003, 0x50A0,}, // Entry Mode (R03h) 0 degrees
52190 + {LCD_STEP_CMD_DATA, 0x0004, 0x0000,}, // Scaling Control register (R04h) Page 16, SPFD5408B Datasheet
52191 + {LCD_STEP_CMD_DATA, 0x0008, 0x0207,}, // Display Control 2 (R08h) Page 17, SPFD5408B Datasheet
52192 + {LCD_STEP_CMD_DATA, 0x0009, 0x0000,}, // Display Control 3 (R09h) Page 18, SPFD5408B Datasheet
52193 + {LCD_STEP_CMD_DATA, 0x000A, 0x0000,}, // Frame Cycle Control (R0Ah) Page 19, SPFD5408B Datasheet
52194 + {LCD_STEP_CMD_DATA, 0x000C, 0x0000,}, // External Display Interface Control 1 (R0Ch) Page 20, SPFD5408B Datasheet
52195 + {LCD_STEP_CMD_DATA, 0x000D, 0x0000,}, // Frame Maker Position (R0Dh) Page 21, SPFD5408B Datasheet
52196 + {LCD_STEP_CMD_DATA, 0x000F, 0x0000,}, // External Display Interface Control 2 (R0Fh) Page 21, SPFD5408B Datasheet
52197 + {LCD_STEP_CMD_DATA, 0x0010, 0x0000,}, // Power Control 1 (R10h) Page 22, SPFD5408B Datasheet
52198 + {LCD_STEP_CMD_DATA, 0x0011, 0x0007,}, // Power Control 2 (R11h) Page 23, SPFD5408B Datasheet
52199 + {LCD_STEP_CMD_DATA, 0x0012, 0x0000,}, // Power Control 3 (R12h) Page 24, SPFD5408B Datasheet
52200 + {LCD_STEP_CMD_DATA, 0x0013, 0x0000,}, // Power Control 4 (R13h) Page 25, SPFD5408B Datasheet
52201 + {LCD_STEP_SLEEP, 0, 200},
52202 + {LCD_STEP_CMD_DATA, 0x0007, 0x0101,}, // Display Control (R07h) Page 16, SPFD5408B Datasheet
52203 + {LCD_STEP_CMD_DATA, 0x0010, 0x12B0,}, // Power Control 1 (R10h) Page 22, SPFD5408B Datasheet
52204 + {LCD_STEP_CMD_DATA, 0x0011, 0x0007,}, // Power Control 2 (R11h) Page 23, SPFD5408B Datasheet
52205 + {LCD_STEP_CMD_DATA, 0x0012, 0x01BB,}, // Power Control 3 (R12h) Page 24, SPFD5408B Datasheet
52206 + {LCD_STEP_SLEEP, 0, 50},
52207 + {LCD_STEP_CMD_DATA, 0x0013, 0x1300,}, // Power Control 4 (R13h) Page 25, SPFD5408B Datasheet
52208 + {LCD_STEP_CMD_DATA, 0x0029, 0x0010,}, // NVM read data 2 (R29h) Page 30, SPFD5408B Datasheet
52209 + {LCD_STEP_SLEEP, 0, 50},
52210 + {LCD_STEP_CMD_DATA, 0x0030, 0x000A,}, // Gamma Control 1 Page 32, SPFD5408B Datasheet
52211 + {LCD_STEP_CMD_DATA, 0x0031, 0x1326,}, // Gamma Control 2 Page 32, SPFD5408B Datasheet
52212 + {LCD_STEP_CMD_DATA, 0x0032, 0x0A29,}, // Gamma Control 3 Page 32, SPFD5408B Datasheet
52213 + {LCD_STEP_CMD_DATA, 0x0033, 0x290A,}, // Gamma Control 4 Page 32, SPFD5408B Datasheet
52214 + {LCD_STEP_CMD_DATA, 0x0034, 0x2613,}, // Gamma Control 5 Page 32, SPFD5408B Datasheet
52215 + {LCD_STEP_CMD_DATA, 0x0035, 0x0A0A,}, // Gamma Control 6 Page 32, SPFD5408B Datasheet
52216 + {LCD_STEP_CMD_DATA, 0x0036, 0x1E03,}, // Gamma Control 7 Page 32, SPFD5408B Datasheet
52217 + {LCD_STEP_CMD_DATA, 0x0037, 0x031E,}, // Gamma Control 8 Page 32, SPFD5408B Datasheet
52218 + {LCD_STEP_CMD_DATA, 0x0038, 0x0706,}, // Gamma Control 9 Page 32, SPFD5408B Datasheet
52219 + {LCD_STEP_CMD_DATA, 0x0039, 0x0303,}, // Gamma Control 10 Page 32, SPFD5408B Datasheet
52220 + {LCD_STEP_CMD_DATA, 0x003A, 0x0E04,}, // Gamma Control 11 Page 32, SPFD5408B Datasheet
52221 + {LCD_STEP_CMD_DATA, 0x003B, 0x0E01,}, // Gamma Control 12 Page 32, SPFD5408B Datasheet
52222 + {LCD_STEP_CMD_DATA, 0x003C, 0x010E,}, // Gamma Control 13 Page 32, SPFD5408B Datasheet
52223 + {LCD_STEP_CMD_DATA, 0x003D, 0x040E,}, // Gamma Control 14 Page 32, SPFD5408B Datasheet
52224 + {LCD_STEP_CMD_DATA, 0x003E, 0x0303,}, // Gamma Control 15 Page 32, SPFD5408B Datasheet
52225 + {LCD_STEP_CMD_DATA, 0x003F, 0x0607,}, // Gamma Control 16 Page 32, SPFD5408B Datasheet
52226 + {LCD_STEP_CMD_DATA, 0x0050, 0x0000,}, // Window Horizontal RAM Address Start (R50h) Page 32, SPFD5408B Datasheet
52227 + {LCD_STEP_CMD_DATA, 0x0051, 0x00EF,}, // Window Horizontal RAM Address End (R51h) Page 32, SPFD5408B Datasheet
52228 + {LCD_STEP_CMD_DATA, 0x0052, 0x0000,}, // Window Vertical RAM Address Start (R52h) Page 33, SPFD5408B Datasheet
52229 + {LCD_STEP_CMD_DATA, 0x0053, 0x013F,}, // Window Vertical RAM Address End (R53h) Page 33, SPFD5408B Datasheet
52230 + {LCD_STEP_CMD_DATA, 0x0060, 0x2700,}, // Driver Output Control (R60h) Page 33, SPFD5408B Datasheet
52231 + {LCD_STEP_CMD_DATA, 0x0061, 0x0001,}, // Driver Output Control (R61h) Page 35, SPFD5408B Datasheet
52232 + {LCD_STEP_CMD_DATA, 0x006A, 0x0000,}, // Vertical Scroll Control (R6Ah) Page 35, SPFD5408B Datasheet
52233 + {LCD_STEP_CMD_DATA, 0x0080, 0x0000,}, // Display Position - Partial Display 1 (R80h) Page 35, SPFD5408B Datasheet
52234 + {LCD_STEP_CMD_DATA, 0x0081, 0x0000,}, // RAM Address Start - Partial Display 1 (R81h) Page 35, SPFD5408B Datasheet
52235 + {LCD_STEP_CMD_DATA, 0x0082, 0x0000,}, // RAM Address End - Partial Display 1 (R82h) Page 36, SPFD5408B Datasheet
52236 + {LCD_STEP_CMD_DATA, 0x0083, 0x0000,}, // Display Position - Partial Display 2 (R83h) Page 36, SPFD5408B Datasheet
52237 + {LCD_STEP_CMD_DATA, 0x0084, 0x0000,}, // RAM Address Start - Partial Display 2 (R84h) Page 36, SPFD5408B Datasheet
52238 + {LCD_STEP_CMD_DATA, 0x0085, 0x0000,}, // RAM Address End - Partial Display 2 (R85h) Page 36, SPFD5408B Datasheet
52239 + {LCD_STEP_CMD_DATA, 0x0090, 0x0010,}, // Panel Interface Control 1 (R90h) Page 36, SPFD5408B Datasheet
52240 + {LCD_STEP_CMD_DATA, 0x0092, 0x0000,}, // Panel Interface Control 2 (R92h) Page 37, SPFD5408B Datasheet
52241 + {LCD_STEP_CMD_DATA, 0x0093, 0x0103,}, // Panel Interface control 3 (R93h) Page 38, SPFD5408B Datasheet
52242 + {LCD_STEP_CMD_DATA, 0x0095, 0x0210,}, // Panel Interface control 4 (R95h) Page 38, SPFD5408B Datasheet
52243 + {LCD_STEP_CMD_DATA, 0x0097, 0x0000,}, // Panel Interface Control 5 (R97h) Page 40, SPFD5408B Datasheet
52244 + {LCD_STEP_CMD_DATA, 0x0098, 0x0000,}, // Panel Interface Control 6 (R98h) Page 41, SPFD5408B Datasheet
52245 + {LCD_STEP_CMD_DATA, 0x0007, 0x0173,}, // Display Control (R07h) Page 16, SPFD5408B Datasheet
52246 + {LCD_STEP_DONE, 0, 0},
52249 +const struct ubicom32lcd_panel cfaf240320ktts_0 = {
52250 + .desc = "CFAF240320KTTS",
52251 + .init_seq = cfaf240320ktts_init_0,
52252 + .horz_reg = 0x20,
52253 + .vert_reg = 0x21,
52254 + .gram_reg = 0x22,
52262 +#ifdef CONFIG_LCD_UBICOM32_CFAF240320KTTS_180
52263 +static const struct ubicom32lcd_step cfaf240320ktts_init_180[] = {
52264 + {LCD_STEP_CMD_DATA, 0x0001, 0x0000,}, // Driver Output Control Register (R01h) Page 14, SPFD5408B Datasheet
52265 + {LCD_STEP_CMD_DATA, 0x0002, 0x0700,}, // LCD Driving Waveform Control (R02h) Page 15, SPFD5408B Datasheet
52266 + {LCD_STEP_CMD_DATA, 0x0003, 0x5000,}, // Entry Mode (R03h) 180 degrees
52267 + {LCD_STEP_CMD_DATA, 0x0004, 0x0000,}, // Scaling Control register (R04h) Page 16, SPFD5408B Datasheet
52268 + {LCD_STEP_CMD_DATA, 0x0008, 0x0207,}, // Display Control 2 (R08h) Page 17, SPFD5408B Datasheet
52269 + {LCD_STEP_CMD_DATA, 0x0009, 0x0000,}, // Display Control 3 (R09h) Page 18, SPFD5408B Datasheet
52270 + {LCD_STEP_CMD_DATA, 0x000A, 0x0000,}, // Frame Cycle Control (R0Ah) Page 19, SPFD5408B Datasheet
52271 + {LCD_STEP_CMD_DATA, 0x000C, 0x0000,}, // External Display Interface Control 1 (R0Ch) Page 20, SPFD5408B Datasheet
52272 + {LCD_STEP_CMD_DATA, 0x000D, 0x0000,}, // Frame Maker Position (R0Dh) Page 21, SPFD5408B Datasheet
52273 + {LCD_STEP_CMD_DATA, 0x000F, 0x0000,}, // External Display Interface Control 2 (R0Fh) Page 21, SPFD5408B Datasheet
52274 + {LCD_STEP_CMD_DATA, 0x0010, 0x0000,}, // Power Control 1 (R10h) Page 22, SPFD5408B Datasheet
52275 + {LCD_STEP_CMD_DATA, 0x0011, 0x0007,}, // Power Control 2 (R11h) Page 23, SPFD5408B Datasheet
52276 + {LCD_STEP_CMD_DATA, 0x0012, 0x0000,}, // Power Control 3 (R12h) Page 24, SPFD5408B Datasheet
52277 + {LCD_STEP_CMD_DATA, 0x0013, 0x0000,}, // Power Control 4 (R13h) Page 25, SPFD5408B Datasheet
52278 + {LCD_STEP_SLEEP, 0, 200},
52279 + {LCD_STEP_CMD_DATA, 0x0007, 0x0101,}, // Display Control (R07h) Page 16, SPFD5408B Datasheet
52280 + {LCD_STEP_CMD_DATA, 0x0010, 0x12B0,}, // Power Control 1 (R10h) Page 22, SPFD5408B Datasheet
52281 + {LCD_STEP_CMD_DATA, 0x0011, 0x0007,}, // Power Control 2 (R11h) Page 23, SPFD5408B Datasheet
52282 + {LCD_STEP_CMD_DATA, 0x0012, 0x01BB,}, // Power Control 3 (R12h) Page 24, SPFD5408B Datasheet
52283 + {LCD_STEP_SLEEP, 0, 50},
52284 + {LCD_STEP_CMD_DATA, 0x0013, 0x1300,}, // Power Control 4 (R13h) Page 25, SPFD5408B Datasheet
52285 + {LCD_STEP_CMD_DATA, 0x0029, 0x0010,}, // NVM read data 2 (R29h) Page 30, SPFD5408B Datasheet
52286 + {LCD_STEP_SLEEP, 0, 50},
52287 + {LCD_STEP_CMD_DATA, 0x0030, 0x000A,}, // Gamma Control 1 Page 32, SPFD5408B Datasheet
52288 + {LCD_STEP_CMD_DATA, 0x0031, 0x1326,}, // Gamma Control 2 Page 32, SPFD5408B Datasheet
52289 + {LCD_STEP_CMD_DATA, 0x0032, 0x0A29,}, // Gamma Control 3 Page 32, SPFD5408B Datasheet
52290 + {LCD_STEP_CMD_DATA, 0x0033, 0x290A,}, // Gamma Control 4 Page 32, SPFD5408B Datasheet
52291 + {LCD_STEP_CMD_DATA, 0x0034, 0x2613,}, // Gamma Control 5 Page 32, SPFD5408B Datasheet
52292 + {LCD_STEP_CMD_DATA, 0x0035, 0x0A0A,}, // Gamma Control 6 Page 32, SPFD5408B Datasheet
52293 + {LCD_STEP_CMD_DATA, 0x0036, 0x1E03,}, // Gamma Control 7 Page 32, SPFD5408B Datasheet
52294 + {LCD_STEP_CMD_DATA, 0x0037, 0x031E,}, // Gamma Control 8 Page 32, SPFD5408B Datasheet
52295 + {LCD_STEP_CMD_DATA, 0x0038, 0x0706,}, // Gamma Control 9 Page 32, SPFD5408B Datasheet
52296 + {LCD_STEP_CMD_DATA, 0x0039, 0x0303,}, // Gamma Control 10 Page 32, SPFD5408B Datasheet
52297 + {LCD_STEP_CMD_DATA, 0x003A, 0x0E04,}, // Gamma Control 11 Page 32, SPFD5408B Datasheet
52298 + {LCD_STEP_CMD_DATA, 0x003B, 0x0E01,}, // Gamma Control 12 Page 32, SPFD5408B Datasheet
52299 + {LCD_STEP_CMD_DATA, 0x003C, 0x010E,}, // Gamma Control 13 Page 32, SPFD5408B Datasheet
52300 + {LCD_STEP_CMD_DATA, 0x003D, 0x040E,}, // Gamma Control 14 Page 32, SPFD5408B Datasheet
52301 + {LCD_STEP_CMD_DATA, 0x003E, 0x0303,}, // Gamma Control 15 Page 32, SPFD5408B Datasheet
52302 + {LCD_STEP_CMD_DATA, 0x003F, 0x0607,}, // Gamma Control 16 Page 32, SPFD5408B Datasheet
52303 + {LCD_STEP_CMD_DATA, 0x0050, 0x0000,}, // Window Horizontal RAM Address Start (R50h) Page 32, SPFD5408B Datasheet
52304 + {LCD_STEP_CMD_DATA, 0x0051, 0x00EF,}, // Window Horizontal RAM Address End (R51h) Page 32, SPFD5408B Datasheet
52305 + {LCD_STEP_CMD_DATA, 0x0052, 0x0000,}, // Window Vertical RAM Address Start (R52h) Page 33, SPFD5408B Datasheet
52306 + {LCD_STEP_CMD_DATA, 0x0053, 0x013F,}, // Window Vertical RAM Address End (R53h) Page 33, SPFD5408B Datasheet
52307 + {LCD_STEP_CMD_DATA, 0x0060, 0x2700,}, // Driver Output Control (R60h) Page 33, SPFD5408B Datasheet
52308 + {LCD_STEP_CMD_DATA, 0x0061, 0x0001,}, // Driver Output Control (R61h) Page 35, SPFD5408B Datasheet
52309 + {LCD_STEP_CMD_DATA, 0x006A, 0x0000,}, // Vertical Scroll Control (R6Ah) Page 35, SPFD5408B Datasheet
52310 + {LCD_STEP_CMD_DATA, 0x0080, 0x0000,}, // Display Position - Partial Display 1 (R80h) Page 35, SPFD5408B Datasheet
52311 + {LCD_STEP_CMD_DATA, 0x0081, 0x0000,}, // RAM Address Start - Partial Display 1 (R81h) Page 35, SPFD5408B Datasheet
52312 + {LCD_STEP_CMD_DATA, 0x0082, 0x0000,}, // RAM Address End - Partial Display 1 (R82h) Page 36, SPFD5408B Datasheet
52313 + {LCD_STEP_CMD_DATA, 0x0083, 0x0000,}, // Display Position - Partial Display 2 (R83h) Page 36, SPFD5408B Datasheet
52314 + {LCD_STEP_CMD_DATA, 0x0084, 0x0000,}, // RAM Address Start - Partial Display 2 (R84h) Page 36, SPFD5408B Datasheet
52315 + {LCD_STEP_CMD_DATA, 0x0085, 0x0000,}, // RAM Address End - Partial Display 2 (R85h) Page 36, SPFD5408B Datasheet
52316 + {LCD_STEP_CMD_DATA, 0x0090, 0x0010,}, // Panel Interface Control 1 (R90h) Page 36, SPFD5408B Datasheet
52317 + {LCD_STEP_CMD_DATA, 0x0092, 0x0000,}, // Panel Interface Control 2 (R92h) Page 37, SPFD5408B Datasheet
52318 + {LCD_STEP_CMD_DATA, 0x0093, 0x0103,}, // Panel Interface control 3 (R93h) Page 38, SPFD5408B Datasheet
52319 + {LCD_STEP_CMD_DATA, 0x0095, 0x0210,}, // Panel Interface control 4 (R95h) Page 38, SPFD5408B Datasheet
52320 + {LCD_STEP_CMD_DATA, 0x0097, 0x0000,}, // Panel Interface Control 5 (R97h) Page 40, SPFD5408B Datasheet
52321 + {LCD_STEP_CMD_DATA, 0x0098, 0x0000,}, // Panel Interface Control 6 (R98h) Page 41, SPFD5408B Datasheet
52322 + {LCD_STEP_CMD_DATA, 0x0007, 0x0173,}, // Display Control (R07h) Page 16, SPFD5408B Datasheet
52323 + {LCD_STEP_DONE, 0, 0},
52326 +const struct ubicom32lcd_panel cfaf240320ktts_180 = {
52327 + .desc = "CFAF240320KTTS 180",
52328 + .init_seq = cfaf240320ktts_init_180,
52329 + .horz_reg = 0x20,
52330 + .vert_reg = 0x21,
52331 + .gram_reg = 0x22,
52339 +#ifdef CONFIG_LCD_UBICOM32_TFT2N0369E_P
52340 +static const struct ubicom32lcd_step tft2n0369ep_init[] = {
52341 + {LCD_STEP_CMD_DATA, 0x0028, 0x0006},
52342 + {LCD_STEP_CMD_DATA, 0x0000, 0x0001},
52343 + {LCD_STEP_SLEEP, 0, 15},
52344 + {LCD_STEP_CMD_DATA, 0x002B, 0x9532},
52345 + {LCD_STEP_CMD_DATA, 0x0003, 0xAAAC},
52346 + {LCD_STEP_CMD_DATA, 0x000C, 0x0002},
52347 + {LCD_STEP_CMD_DATA, 0x000D, 0x000A},
52348 + {LCD_STEP_CMD_DATA, 0x000E, 0x2C00},
52349 + {LCD_STEP_CMD_DATA, 0x001E, 0x00AA},
52350 + {LCD_STEP_CMD_DATA, 0x0025, 0x8000},
52351 + {LCD_STEP_SLEEP, 0, 15},
52352 + {LCD_STEP_CMD_DATA, 0x0001, 0x2B3F},
52353 + {LCD_STEP_CMD_DATA, 0x0002, 0x0600},
52354 + {LCD_STEP_CMD_DATA, 0x0010, 0x0000},
52355 + {LCD_STEP_CMD_DATA, 0x0011, 0x6030},
52356 + {LCD_STEP_SLEEP, 0, 20},
52357 + {LCD_STEP_CMD_DATA, 0x0005, 0x0000},
52358 + {LCD_STEP_CMD_DATA, 0x0006, 0x0000},
52359 + {LCD_STEP_CMD_DATA, 0x0016, 0xEF1C},
52360 + {LCD_STEP_CMD_DATA, 0x0017, 0x0003},
52361 + {LCD_STEP_CMD_DATA, 0x0007, 0x0233},
52362 + {LCD_STEP_CMD_DATA, 0x000B, 0x5312},
52363 + {LCD_STEP_CMD_DATA, 0x000F, 0x0000},
52364 + {LCD_STEP_SLEEP, 0, 20},
52365 + {LCD_STEP_CMD_DATA, 0x0041, 0x0000},
52366 + {LCD_STEP_CMD_DATA, 0x0042, 0x0000},
52367 + {LCD_STEP_CMD_DATA, 0x0048, 0x0000},
52368 + {LCD_STEP_CMD_DATA, 0x0049, 0x013F},
52369 + {LCD_STEP_CMD_DATA, 0x0044, 0xEF00},
52370 + {LCD_STEP_CMD_DATA, 0x0045, 0x0000},
52371 + {LCD_STEP_CMD_DATA, 0x0046, 0x013F},
52372 + {LCD_STEP_CMD_DATA, 0x004A, 0x0000},
52373 + {LCD_STEP_CMD_DATA, 0x004B, 0x0000},
52374 + {LCD_STEP_SLEEP, 0, 20},
52375 + {LCD_STEP_CMD_DATA, 0x0030, 0x0707},
52376 + {LCD_STEP_CMD_DATA, 0x0031, 0x0704},
52377 + {LCD_STEP_CMD_DATA, 0x0032, 0x0204},
52378 + {LCD_STEP_CMD_DATA, 0x0033, 0x0201},
52379 + {LCD_STEP_CMD_DATA, 0x0034, 0x0203},
52380 + {LCD_STEP_CMD_DATA, 0x0035, 0x0204},
52381 + {LCD_STEP_CMD_DATA, 0x0036, 0x0204},
52382 + {LCD_STEP_CMD_DATA, 0x0037, 0x0502},
52383 + {LCD_STEP_CMD_DATA, 0x003A, 0x0302},
52384 + {LCD_STEP_CMD_DATA, 0x003B, 0x0500},
52385 + {LCD_STEP_SLEEP, 0, 20},
52386 + {LCD_STEP_CMD_DATA, 0x0044, 239 << 8 | 0},
52387 + {LCD_STEP_CMD_DATA, 0x0045, 0x0000},
52388 + {LCD_STEP_CMD_DATA, 0x0046, 319},
52389 + {LCD_STEP_DONE, 0, 0},
52392 +const struct ubicom32lcd_panel tft2n0369ep = {
52393 + .desc = "TFT2N0369E-Portrait",
52394 + .init_seq = tft2n0369ep_init,
52395 + .horz_reg = 0x4e,
52396 + .vert_reg = 0x4f,
52397 + .gram_reg = 0x22,
52405 +#ifdef CONFIG_LCD_UBICOM32_TFT2N0369E_L
52406 +static const struct ubicom32lcd_step tft2n0369e_init[] = {
52407 + {LCD_STEP_CMD_DATA, 0x0028, 0x0006},
52408 + {LCD_STEP_CMD_DATA, 0x0000, 0x0001},
52409 + {LCD_STEP_SLEEP, 0, 15},
52410 + {LCD_STEP_CMD_DATA, 0x002B, 0x9532},
52411 + {LCD_STEP_CMD_DATA, 0x0003, 0xAAAC},
52412 + {LCD_STEP_CMD_DATA, 0x000C, 0x0002},
52413 + {LCD_STEP_CMD_DATA, 0x000D, 0x000A},
52414 + {LCD_STEP_CMD_DATA, 0x000E, 0x2C00},
52415 + {LCD_STEP_CMD_DATA, 0x001E, 0x00AA},
52416 + {LCD_STEP_CMD_DATA, 0x0025, 0x8000},
52417 + {LCD_STEP_SLEEP, 0, 15},
52418 + {LCD_STEP_CMD_DATA, 0x0001, 0x2B3F},
52419 + {LCD_STEP_CMD_DATA, 0x0002, 0x0600},
52420 + {LCD_STEP_CMD_DATA, 0x0010, 0x0000},
52421 + {LCD_STEP_CMD_DATA, 0x0011, 0x60A8},
52422 + {LCD_STEP_SLEEP, 0, 20},
52423 + {LCD_STEP_CMD_DATA, 0x0005, 0x0000},
52424 + {LCD_STEP_CMD_DATA, 0x0006, 0x0000},
52425 + {LCD_STEP_CMD_DATA, 0x0016, 0xEF1C},
52426 + {LCD_STEP_CMD_DATA, 0x0017, 0x0003},
52427 + {LCD_STEP_CMD_DATA, 0x0007, 0x0233},
52428 + {LCD_STEP_CMD_DATA, 0x000B, 0x5312},
52429 + {LCD_STEP_CMD_DATA, 0x000F, 0x0000},
52430 + {LCD_STEP_SLEEP, 0, 20},
52431 + {LCD_STEP_CMD_DATA, 0x0041, 0x0000},
52432 + {LCD_STEP_CMD_DATA, 0x0042, 0x0000},
52433 + {LCD_STEP_CMD_DATA, 0x0048, 0x0000},
52434 + {LCD_STEP_CMD_DATA, 0x0049, 0x013F},
52435 + {LCD_STEP_CMD_DATA, 0x0044, 0xEF00},
52436 + {LCD_STEP_CMD_DATA, 0x0045, 0x0000},
52437 + {LCD_STEP_CMD_DATA, 0x0046, 0x013F},
52438 + {LCD_STEP_CMD_DATA, 0x004A, 0x0000},
52439 + {LCD_STEP_CMD_DATA, 0x004B, 0x0000},
52440 + {LCD_STEP_SLEEP, 0, 20},
52441 + {LCD_STEP_CMD_DATA, 0x0030, 0x0707},
52442 + {LCD_STEP_CMD_DATA, 0x0031, 0x0704},
52443 + {LCD_STEP_CMD_DATA, 0x0032, 0x0204},
52444 + {LCD_STEP_CMD_DATA, 0x0033, 0x0201},
52445 + {LCD_STEP_CMD_DATA, 0x0034, 0x0203},
52446 + {LCD_STEP_CMD_DATA, 0x0035, 0x0204},
52447 + {LCD_STEP_CMD_DATA, 0x0036, 0x0204},
52448 + {LCD_STEP_CMD_DATA, 0x0037, 0x0502},
52449 + {LCD_STEP_CMD_DATA, 0x003A, 0x0302},
52450 + {LCD_STEP_CMD_DATA, 0x003B, 0x0500},
52451 + {LCD_STEP_SLEEP, 0, 20},
52452 + {LCD_STEP_CMD_DATA, 0x0044, 239 << 8 | 0},
52453 + {LCD_STEP_CMD_DATA, 0x0045, 0x0000},
52454 + {LCD_STEP_CMD_DATA, 0x0046, 319},
52455 + {LCD_STEP_DONE, 0, 0},
52458 +const struct ubicom32lcd_panel tft2n0369e = {
52459 + .desc = "TFT2N0369E-Landscape",
52460 + .init_seq = tft2n0369e_init,
52461 + .horz_reg = 0x4e,
52462 + .vert_reg = 0x4f,
52463 + .gram_reg = 0x22,
52471 +#ifdef CONFIG_LCD_UBICOM32_CFAF240400D
52472 +static const struct ubicom32lcd_step cfaf240400d_init[] = {
52473 + {LCD_STEP_CMD_DATA, 0x0606, 0x0000}, // Pin Control (R606h) // Page 41 of SPFD5420A Datasheet
52474 + {LCD_STEP_SLEEP, 0, 50},
52475 + {LCD_STEP_CMD_DATA, 0x0007, 0x0001}, // Display Control 1 (R007h) // Page 16 of SPFD5420A Datasheet
52476 + {LCD_STEP_SLEEP, 0, 50},
52477 + {LCD_STEP_CMD_DATA, 0x0110, 0x0001}, // Power Control 6(R110h) // Page 30 of SPFD5420A Datasheet
52478 + {LCD_STEP_SLEEP, 0, 50},
52479 + {LCD_STEP_CMD_DATA, 0x0100, 0x17B0}, // Power Control 1 (R100h) // Page 26 of SPFD5420A Datasheet
52480 + {LCD_STEP_CMD_DATA, 0x0101, 0x0147}, // Power Control 2 (R101h) // Page 27 of SPFD5420A Datasheet
52481 + {LCD_STEP_CMD_DATA, 0x0102, 0x019D}, // Power Control 3 (R102h) // Page 28 of SPFD5420A Datasheet
52482 + {LCD_STEP_CMD_DATA, 0x0103, 0x3600}, // Power Control 4 (R103h) // Page 29 of SPFD5420A Datasheet
52483 + {LCD_STEP_CMD_DATA, 0x0281, 0x0010}, // NVM read data 2 (R281h) // Page 34 of SPFD5420A Datasheet
52484 + {LCD_STEP_SLEEP, 0, 50},
52485 + {LCD_STEP_CMD_DATA, 0x0102, 0x01BD}, // Power Control 3 (R102h) // Page 28 of SPFD5420A Datasheet
52486 + {LCD_STEP_SLEEP, 0, 50},
52488 + //--------------- Power control 1~6 ---------------//
52489 + {LCD_STEP_CMD_DATA, 0x0100, 0x16B0}, // Power Control 1 (R100h) // Page 26 of SPFD5420A Datasheet
52490 + {LCD_STEP_CMD_DATA, 0x0101, 0x0147}, // Power Control 2 (R101h) // Page 27 of SPFD5420A Datasheet
52491 + {LCD_STEP_CMD_DATA, 0x0102, 0x01BD}, // Power Control 3 (R102h) // Page 28 of SPFD5420A Datasheet
52492 + {LCD_STEP_CMD_DATA, 0x0103, 0x2d00}, // Power Control 4 (R103h) // Page 29 of SPFD5420A Datasheet
52493 + {LCD_STEP_CMD_DATA, 0x0107, 0x0000}, // Power Control 5 (R107h) // Page 30 of SPFD5420A Datasheet
52494 + {LCD_STEP_CMD_DATA, 0x0110, 0x0001}, // Power Control 6(R110h) // Page 30 of SPFD5420A Datasheet
52495 + {LCD_STEP_CMD_DATA, 0x0280, 0x0000}, // NVM read data 1 (R280h) // Page 33 of SPFD5420A Datasheet
52496 + {LCD_STEP_CMD_DATA, 0x0281, 0x0006}, // NVM read data 2 (R281h) // Page 34 of SPFD5420A Datasheet
52497 + {LCD_STEP_CMD_DATA, 0x0282, 0x0000}, // NVM read data 3 (R282h) // Page 34 of SPFD5420A Datasheet
52499 + //------- Gamma 2.2 control (R300h to R30Fh) ------//
52500 + {LCD_STEP_CMD_DATA, 0x0300, 0x0101},
52501 + {LCD_STEP_CMD_DATA, 0x0301, 0x0b27},
52502 + {LCD_STEP_CMD_DATA, 0x0302, 0x132a},
52503 + {LCD_STEP_CMD_DATA, 0x0303, 0x2a13},
52504 + {LCD_STEP_CMD_DATA, 0x0304, 0x270b},
52505 + {LCD_STEP_CMD_DATA, 0x0305, 0x0101},
52506 + {LCD_STEP_CMD_DATA, 0x0306, 0x1205},
52507 + {LCD_STEP_CMD_DATA, 0x0307, 0x0512},
52508 + {LCD_STEP_CMD_DATA, 0x0308, 0x0005},
52509 + {LCD_STEP_CMD_DATA, 0x0309, 0x0003},
52510 + {LCD_STEP_CMD_DATA, 0x030A, 0x0f04},
52511 + {LCD_STEP_CMD_DATA, 0x030B, 0x0f00},
52512 + {LCD_STEP_CMD_DATA, 0x030C, 0x000f},
52513 + {LCD_STEP_CMD_DATA, 0x030D, 0x040f},
52514 + {LCD_STEP_CMD_DATA, 0x030E, 0x0300},
52515 + {LCD_STEP_CMD_DATA, 0x030F, 0x0500},
52517 + {LCD_STEP_CMD_DATA, 0x0400, 0x3500}, // Base Image Number of Line (R400h) // Page 36 of SPFD5420A Datasheet
52518 + {LCD_STEP_CMD_DATA, 0x0401, 0x0001}, // Base Image Display Control (R401h) // Page 39 of SPFD5420A Datasheet
52519 + {LCD_STEP_CMD_DATA, 0x0404, 0x0000}, // Based Image Vertical Scroll Control (R404h) // Page 40 of SPFD5420A Datasheet
52521 + //--------------- Normal set ---------------//
52522 + {LCD_STEP_CMD_DATA, 0x0000, 0x0000}, // ID Read Register (R000h) // Page 13 of SPFD5420A Datasheet
52523 + {LCD_STEP_CMD_DATA, 0x0001, 0x0100}, // Driver Output Control Register (R001h) // Page 14 of SPFD5420A Datasheet
52524 + {LCD_STEP_CMD_DATA, 0x0002, 0x0100}, // LCD Driving Waveform Control (R002h) // Page 14 of SPFD5420A Datasheet
52525 + {LCD_STEP_CMD_DATA, 0x0003, 0x1030}, // Entry Mode (R003h) // Page 15 of SPFD5420A Datasheet
52526 + {LCD_STEP_CMD_DATA, 0x0006, 0x0000}, // Display Control 1 (R007h) // Page 16 of SPFD5420A Datasheet
52527 + {LCD_STEP_CMD_DATA, 0x0008, 0x0808}, // Display Control 2 (R008h) // Page 17 of SPFD5420A Datasheet
52528 + {LCD_STEP_CMD_DATA, 0x0009, 0x0001}, // Display Control 3 (R009h) // Page 18 of SPFD5420A Datasheet
52529 + {LCD_STEP_CMD_DATA, 0x000B, 0x0010}, // Low Power Control (R00Bh) // Page 19 of SPFD5420A Datasheet
52530 + {LCD_STEP_CMD_DATA, 0x000C, 0x0000}, // External Display Interface Control 1 (R00Ch) // Page 19 of SPFD5420A Datasheet
52531 + {LCD_STEP_CMD_DATA, 0x000F, 0x0000}, // External Display Interface Control 2 (R00Fh) // Page 20 of SPFD5420A Datasheet
52532 + {LCD_STEP_CMD_DATA, 0x0007, 0x0001}, // Display Control 1 (R007h) // Page 16 of SPFD5420A Datasheet
52534 + //--------------- Panel interface control 1~6 ---------------//
52535 + {LCD_STEP_CMD_DATA, 0x0010, 0x0012}, // Panel Interface Control 1 (R010h) // Page 20 of SPFD5420A Datasheet
52536 + {LCD_STEP_CMD_DATA, 0x0011, 0x0202}, // Panel Interface Control 2 (R011h) // Page 21 of SPFD5420A Datasheet
52537 + {LCD_STEP_CMD_DATA, 0x0012, 0x0300}, // Panel Interface control 3 (R012h) // Page 22 of SPFD5420A Datasheet
52538 + {LCD_STEP_CMD_DATA, 0x0020, 0x021E}, // Panel Interface control 4 (R020h) // Page 22 of SPFD5420A Datasheet
52539 + {LCD_STEP_CMD_DATA, 0x0021, 0x0202}, // Panel Interface Control 5 (021Rh) // Page 24 of SPFD5420A Datasheet
52540 + {LCD_STEP_CMD_DATA, 0x0022, 0x0100}, // Panel Interface Control 6 (R022h) // Page 25 of SPFD5420A Datasheet
52541 + {LCD_STEP_CMD_DATA, 0x0090, 0x8000}, // Frame Marker Control (R090h) // Page 25 of SPFD5420A Datasheet
52543 + //--------------- Partial display ---------------//
52544 + {LCD_STEP_CMD_DATA, 0x0210, 0x0000}, // Window Horizontal RAM Address Start (R210h) // Page 35 of SPFD5420A Datasheet
52545 + {LCD_STEP_CMD_DATA, 0x0211, 0x00EF}, // Window Horziontal RAM Address End (R211h) // Page 35 of SPFD5420A Datasheet
52546 + {LCD_STEP_CMD_DATA, 0x0212, 0x0000}, // Window Vertical RAM Address Start (R212h) // Page 35 of SPFD5420A Datasheet
52547 + {LCD_STEP_CMD_DATA, 0x0213, 0x018F}, // Window Vertical RAM Address End (R213h) // Page 35 of SPFD5420A Datasheet
52548 + {LCD_STEP_CMD_DATA, 0x0500, 0x0000}, // Display Position - Partial Display 1 (R500h) // Page 40 of SPFD5420A Datasheet
52549 + {LCD_STEP_CMD_DATA, 0x0501, 0x0000}, // RAM Address Start - Partial Display 1 (R501h)// Page 40 of SPFD5420A Datasheet
52550 + {LCD_STEP_CMD_DATA, 0x0502, 0x0000}, // RAM Address End - Partail Display 1 (R502h) // Page 40 of SPFD5420A Datasheet
52551 + {LCD_STEP_CMD_DATA, 0x0503, 0x0000}, // Display Position - Partial Display 2 (R503h) // Page 40 of SPFD5420A Datasheet
52552 + {LCD_STEP_CMD_DATA, 0x0504, 0x0000}, // RAM Address Start . Partial Display 2 (R504h)// Page 41 of SPFD5420A Datasheet
52553 + {LCD_STEP_CMD_DATA, 0x0505, 0x0000}, // RAM Address End . Partial Display 2 (R505h) // Page 41 of SPFD5420A Datasheet
52554 + {LCD_STEP_CMD_DATA, 0x0606, 0x0000}, // Pin Control (R606h) // Page 41 of SPFD5420A Datasheet
52555 + {LCD_STEP_CMD_DATA, 0x06F0, 0x0000}, // NVM Access Control (R6F0h) // Page 41 of SPFD5420A Datasheet
52556 + {LCD_STEP_CMD_DATA, 0x0007, 0x0173}, // Display Control 1 (R007h) // Page 16 of SPFD5420A Datasheet
52557 + {LCD_STEP_SLEEP, 0, 50},
52558 + {LCD_STEP_CMD_DATA, 0x0007, 0x0171}, // Display Control 1 (R007h) // Page 16 of SPFD5420A Datasheet
52559 + {LCD_STEP_SLEEP, 0, 10},
52560 + {LCD_STEP_CMD_DATA, 0x0007, 0x0173}, // Display Control 1 (R007h) // Page 16 of SPFD5420A Datasheet
52561 + {LCD_STEP_DONE, 0, 0},
52564 +const struct ubicom32lcd_panel cfaf240400d = {
52565 + .desc = "CFAF240400D",
52566 + .init_seq = cfaf240400d_init,
52567 + .horz_reg = 0x0200,
52568 + .vert_reg = 0x0201,
52569 + .gram_reg = 0x0202,
52577 +#ifdef CONFIG_LCD_UBICOM32_CFAF240400F
52578 +static const struct ubicom32lcd_step cfaf320240f_init[] = {
52579 + {LCD_STEP_CMD_DATA, 0x0028, 0x0006}, // VCOM OTP Page 55-56 of SSD2119 datasheet
52580 + {LCD_STEP_CMD_DATA, 0x0000, 0x0001}, // start Oscillator Page 36 of SSD2119 datasheet
52581 + {LCD_STEP_CMD_DATA, 0x0010, 0x0000}, // Sleep mode Page 49 of SSD2119 datasheet
52582 + {LCD_STEP_CMD_DATA, 0x0001, 0x32EF}, // Driver Output Control Page 36-39 of SSD2119 datasheet
52583 + {LCD_STEP_CMD_DATA, 0x0002, 0x0600}, // LCD Driving Waveform Control Page 40-42 of SSD2119 datasheet
52584 + {LCD_STEP_CMD_DATA, 0x0003, 0x6A38}, // Power Control 1 Page 43-44 of SSD2119 datasheet
52585 + {LCD_STEP_CMD_DATA, 0x0011, 0x6870}, // Entry Mode Page 50-52 of SSD2119 datasheet
52586 + {LCD_STEP_CMD_DATA, 0X000F, 0x0000}, // Gate Scan Position Page 49 of SSD2119 datasheet
52587 + {LCD_STEP_CMD_DATA, 0X000B, 0x5308}, // Frame Cycle Control Page 45 of SSD2119 datasheet
52588 + {LCD_STEP_CMD_DATA, 0x000C, 0x0003}, // Power Control 2 Page 47 of SSD2119 datasheet
52589 + {LCD_STEP_CMD_DATA, 0x000D, 0x000A}, // Power Control 3 Page 48 of SSD2119 datasheet
52590 + {LCD_STEP_CMD_DATA, 0x000E, 0x2E00}, // Power Control 4 Page 48 of SSD2119 datasheet
52591 + {LCD_STEP_CMD_DATA, 0x001E, 0x00BE}, // Power Control 5 Page 53 of SSD2119 datasheet
52592 + {LCD_STEP_CMD_DATA, 0x0025, 0x8000}, // Frame Frequency Control Page 53 of SSD2119 datasheet
52593 + {LCD_STEP_CMD_DATA, 0x0026, 0x7800}, // Analog setting Page 54 of SSD2119 datasheet
52594 + {LCD_STEP_CMD_DATA, 0x004E, 0x0000}, // Ram Address Set Page 58 of SSD2119 datasheet
52595 + {LCD_STEP_CMD_DATA, 0x004F, 0x0000}, // Ram Address Set Page 58 of SSD2119 datasheet
52596 + {LCD_STEP_CMD_DATA, 0x0012, 0x08D9}, // Sleep mode Page 49 of SSD2119 datasheet
52598 + // Gamma Control (R30h to R3Bh) -- Page 56 of SSD2119 datasheet
52599 + {LCD_STEP_CMD_DATA, 0x0030, 0x0000},
52600 + {LCD_STEP_CMD_DATA, 0x0031, 0x0104},
52601 + {LCD_STEP_CMD_DATA, 0x0032, 0x0100},
52602 + {LCD_STEP_CMD_DATA, 0x0033, 0x0305},
52603 + {LCD_STEP_CMD_DATA, 0x0034, 0x0505},
52604 + {LCD_STEP_CMD_DATA, 0x0035, 0x0305},
52605 + {LCD_STEP_CMD_DATA, 0x0036, 0x0707},
52606 + {LCD_STEP_CMD_DATA, 0x0037, 0x0300},
52607 + {LCD_STEP_CMD_DATA, 0x003A, 0x1200},
52608 + {LCD_STEP_CMD_DATA, 0x003B, 0x0800},
52610 + {LCD_STEP_CMD_DATA, 0x0007, 0x0033}, // Display Control Page 45 of SSD2119 datasheet
52612 + {LCD_STEP_CMD_DATA, 0x0044, 0xEF00}, // Vertical RAM address position Page 57 of SSD2119 datasheet
52613 + {LCD_STEP_CMD_DATA, 0x0045, 0x0000}, // Horizontal RAM address position Page 57 of SSD2119 datasheet
52614 + {LCD_STEP_CMD_DATA, 0x0046, 0x013F}, // Horizontal RAM address position Page 57 of SSD2119 datasheet
52616 + {LCD_STEP_SLEEP, 0, 150},
52618 + {LCD_STEP_DONE, 0, 0},
52621 +const struct ubicom32lcd_panel cfaf320240f = {
52622 + .desc = "CFAF320240F",
52623 + .init_seq = cfaf320240f_init,
52624 + .horz_reg = 0x4e,
52625 + .vert_reg = 0x4f,
52626 + .gram_reg = 0x22,
52634 +const struct ubicom32lcd_panel *ubicom32lcd_panels[] = {
52635 +#ifdef CONFIG_LCD_UBICOM32_CFAF240400KTTS_180
52636 + &cfaf240320ktts_180,
52638 +#ifdef CONFIG_LCD_UBICOM32_CFAF240400KTTS
52639 + &cfaf240320ktts_0,
52641 +#ifdef CONFIG_LCD_UBICOM32_CFAF240400D
52644 +#ifdef CONFIG_LCD_UBICOM32_TFT2N0369E_P
52647 +#ifdef CONFIG_LCD_UBICOM32_TFT2N0369E_L
52650 +#ifdef CONFIG_LCD_UBICOM32_CFAF240400F
52658 +++ b/drivers/video/backlight/ubicom32lcdpower.c
52661 + * drivers/video/backlight/ubicom32lcdpowerpower.c
52662 + * LCD power driver for the Ubicom32 platform
52664 + * (C) Copyright 2009, Ubicom, Inc.
52666 + * This file is part of the Ubicom32 Linux Kernel Port.
52668 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
52669 + * it and/or modify it under the terms of the GNU General Public License
52670 + * as published by the Free Software Foundation, either version 2 of the
52671 + * License, or (at your option) any later version.
52673 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
52674 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
52675 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
52676 + * the GNU General Public License for more details.
52678 + * You should have received a copy of the GNU General Public License
52679 + * along with the Ubicom32 Linux Kernel Port. If not,
52680 + * see <http://www.gnu.org/licenses/>.
52682 + * Ubicom32 implementation derived from (with many thanks):
52687 +#include <linux/init.h>
52688 +#include <linux/kernel.h>
52689 +#include <linux/module.h>
52690 +#include <linux/platform_device.h>
52691 +#include <linux/lcd.h>
52692 +#include <linux/fb.h>
52693 +#include <linux/gpio.h>
52695 +#include <asm/ubicom32lcdpower.h>
52696 +#include <asm/ip5000.h>
52698 +#define DRIVER_NAME "ubicom32lcdpower"
52700 +struct ubicom32lcdpower_data {
52702 + * Pointer to the platform data structure. Keep this around since we need values
52703 + * from it to set the backlight intensity.
52705 + const struct ubicom32lcdpower_platform_data *pdata;
52708 + * LCD device, we have to save this for use when we remove ourselves.
52710 + struct lcd_device *lcddev;
52714 + * ubicom32lcdpower_set_power
52716 +static int ubicom32lcdpower_set_power(struct lcd_device *ld, int power)
52718 + struct ubicom32lcdpower_data *ud = (struct ubicom32lcdpower_data *)lcd_get_data(ld);
52719 + if (power == FB_BLANK_UNBLANK) {
52720 + gpio_direction_output(ud->pdata->vgh_gpio, ud->pdata->vgh_polarity);
52724 + gpio_direction_output(ud->pdata->vgh_gpio, !ud->pdata->vgh_polarity);
52729 + * ubicom32lcdpower_get_power
52731 +static int ubicom32lcdpower_get_power(struct lcd_device *ld)
52733 + struct ubicom32lcdpower_data *ud = (struct ubicom32lcdpower_data *)lcd_get_data(ld);
52734 + int vgh = gpio_get_value(ud->pdata->vgh_gpio);
52735 + if ((vgh && ud->pdata->vgh_polarity) || (!vgh && !ud->pdata->vgh_polarity)) {
52742 +static struct lcd_ops ubicom32lcdpower_ops = {
52743 + .get_power = ubicom32lcdpower_get_power,
52744 + .set_power = ubicom32lcdpower_set_power,
52748 + * ubicom32lcdpower_probe
52750 +static int ubicom32lcdpower_probe(struct platform_device *pdev)
52752 + const struct ubicom32lcdpower_platform_data *pdata = pdev->dev.platform_data;
52753 + struct ubicom32lcdpower_data *ud;
52754 + struct lcd_device *lcddev;
52758 + * Check to see if we have any platform data, if we don't have a LCD to control
52765 + * Allocate our private data
52767 + ud = kzalloc(sizeof(struct ubicom32lcdpower_data), GFP_KERNEL);
52772 + ud->pdata = pdata;
52775 + * Request our GPIOs
52777 + retval = gpio_request(pdata->vgh_gpio, "vgh");
52779 + dev_err(&pdev->dev, "Failed to allocate vgh GPIO\n");
52784 + * Register our lcd device
52786 + lcddev = lcd_device_register(DRIVER_NAME, &pdev->dev, ud, &ubicom32lcdpower_ops);
52787 + if (IS_ERR(lcddev)) {
52788 + retval = PTR_ERR(lcddev);
52792 + ud->lcddev = lcddev;
52793 + platform_set_drvdata(pdev, ud);
52795 + ubicom32lcdpower_set_power(lcddev, FB_BLANK_UNBLANK);
52797 + printk(KERN_INFO DRIVER_NAME ": LCD driver started\n");
52802 + gpio_free(pdata->vgh_gpio);
52805 + platform_set_drvdata(pdev, NULL);
52811 + * ubicom32lcdpower_remove
52813 +static int __exit ubicom32lcdpower_remove(struct platform_device *pdev)
52815 + struct ubicom32lcdpower_data *ud = platform_get_drvdata(pdev);
52817 + lcd_device_unregister(ud->lcddev);
52818 + platform_set_drvdata(pdev, NULL);
52824 +static struct platform_driver ubicom32lcdpower_driver = {
52826 + .name = DRIVER_NAME,
52827 + .owner = THIS_MODULE,
52830 + .remove = __exit_p(ubicom32lcdpower_remove),
52834 + * ubicom32lcdpower_init
52836 +static int __init ubicom32lcdpower_init(void)
52838 + return platform_driver_probe(&ubicom32lcdpower_driver, ubicom32lcdpower_probe);
52840 +module_init(ubicom32lcdpower_init);
52843 + * ubicom32lcdpower_exit
52845 +static void __exit ubicom32lcdpower_exit(void)
52847 + platform_driver_unregister(&ubicom32lcdpower_driver);
52849 +module_exit(ubicom32lcdpower_exit);
52851 +MODULE_AUTHOR("Patrick Tjin <@ubicom.com>");
52852 +MODULE_DESCRIPTION("Ubicom32 lcd power driver");
52853 +MODULE_LICENSE("GPL");
52854 --- a/drivers/video/Kconfig
52855 +++ b/drivers/video/Kconfig
52856 @@ -609,6 +609,50 @@ config FB_BFIN_T350MCQB
52857 This display is a QVGA 320x240 24-bit RGB display interfaced by an 8-bit wide PPI
52858 It uses PPI[0..7] PPI_FS1, PPI_FS2 and PPI_CLK.
52860 +config FB_UBICOM32
52861 + tristate "Ubicom32 Frame Buffer driver"
52862 + depends on FB && UBICOM32
52863 + select FB_CFB_FILLRECT
52864 + select FB_CFB_COPYAREA
52865 + select FB_CFB_IMAGEBLIT
52866 + select FONT_6x11 if FRAMEBUFFER_CONSOLE
52868 + This is the framebuffer device driver for the Ubicom32 architecture.
52869 + You can configure video memory by using kernel command line parameters, for example:
52870 + video=ubicomfb:vram_size=512,init_value=0xffff
52872 +config FB_UBICOM32_PLIO80
52873 + tristate "Ubicom32 80 Bus PLIO Frame Buffer driver"
52874 + depends on FB && UBICOM32
52875 + select FB_CFB_FILLRECT
52876 + select FB_CFB_COPYAREA
52877 + select FB_CFB_IMAGEBLIT
52878 + select FONT_6x11 if FRAMEBUFFER_CONSOLE
52879 + select UBICOM32_PLIO
52881 + This is a framebuffer device driver for the Ubicom32 architecture.
52882 + You can configure the xres, yres and vram size (in kilobytes) by using
52883 + kernel command line parameters, for example:
52884 + video=ubicom32vfb:xres=320,yres=240,vram_size=512
52886 +config FB_UBICOM32_VIRTUAL
52887 + tristate "Ubicom32 Virtual Frame Buffer driver"
52888 + depends on FB && UBICOM32
52889 + select FB_CFB_FILLRECT
52890 + select FB_CFB_COPYAREA
52891 + select FB_CFB_IMAGEBLIT
52892 + select FONT_6x11 if FRAMEBUFFER_CONSOLE
52894 + This is a virtual framebuffer device driver for the Ubicom32 architecture.
52895 + You can configure the xres, yres and vram size (in kilobytes) by using
52896 + kernel command line parameters, for example:
52897 + video=ubicom32vfb:xres=320,yres=240,vram_size=512
52899 +config FB_UBICOM32_VIRTUAL_NOAUTO
52900 + bool "Do not automatically load"
52901 + depends on FB_UBICOM32_VIRTUAL
52903 + Select this option to prevent the VFB from automatically loading at boot.
52906 tristate "HP STI frame buffer device support"
52907 --- a/drivers/video/Makefile
52908 +++ b/drivers/video/Makefile
52909 @@ -136,6 +136,10 @@ obj-$(CONFIG_FB_BF54X_LQ043) += bf54x-
52910 obj-$(CONFIG_FB_BFIN_T350MCQB) += bfin-t350mcqb-fb.o
52911 obj-$(CONFIG_FB_MX3) += mx3fb.o
52913 +obj-$(CONFIG_FB_UBICOM32) += ubicom32fb.o
52914 +obj-$(CONFIG_FB_UBICOM32_PLIO80) += ubicom32plio80.o
52915 +obj-$(CONFIG_FB_UBICOM32_VIRTUAL) += ubicom32vfb.o
52917 # the test framebuffer is last
52918 obj-$(CONFIG_FB_VIRTUAL) += vfb.o
52921 +++ b/drivers/video/ubicom32fb.c
52924 + * drivers/video/ubicom32fb.c
52925 + * Ubicom32 frame buffer driver
52927 + * (C) Copyright 2009, Ubicom, Inc.
52929 + * This file is part of the Ubicom32 Linux Kernel Port.
52931 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
52932 + * it and/or modify it under the terms of the GNU General Public License
52933 + * as published by the Free Software Foundation, either version 2 of the
52934 + * License, or (at your option) any later version.
52936 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
52937 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
52938 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
52939 + * the GNU General Public License for more details.
52941 + * You should have received a copy of the GNU General Public License
52942 + * along with the Ubicom32 Linux Kernel Port. If not,
52943 + * see <http://www.gnu.org/licenses/>.
52945 + * Ubicom32 implementation derived from (with many thanks):
52952 + * This driver was based on skeletonfb.c, Skeleton for a frame buffer device by
52953 + * Geert Uytterhoeven.
52956 +#include <linux/device.h>
52957 +#include <linux/module.h>
52958 +#include <linux/kernel.h>
52959 +#include <linux/version.h>
52960 +#include <linux/errno.h>
52961 +#include <linux/string.h>
52962 +#include <linux/mm.h>
52963 +#include <linux/fb.h>
52964 +#include <linux/init.h>
52965 +#include <linux/dma-mapping.h>
52966 +#include <linux/platform_device.h>
52967 +#include <linux/device.h>
52968 +#include <linux/uaccess.h>
52969 +#include <linux/interrupt.h>
52971 +#include <asm/io.h>
52972 +#include <asm/ip5000.h>
52973 +#include <asm/vdc_tio.h>
52974 +#include <asm/ubicom32fb.h>
52976 +#define DRIVER_NAME "ubicom32fb"
52977 +#define DRIVER_DESCRIPTION "Ubicom32 frame buffer driver"
52979 +#define PALETTE_ENTRIES_NO 16
52982 + * Option variables
52984 + * vram_size: VRAM size in kilobytes, subject to alignment
52986 +static int vram_size = 0;
52987 +module_param(vram_size, int, 0);
52988 +MODULE_PARM_DESC(vram, "VRAM size, in kilobytes to allocate, should be at least the size of one screen, subject to alignment");
52989 +static int init_value = 0;
52990 +module_param(init_value, int, 0);
52991 +MODULE_PARM_DESC(init, "Initial value of the framebuffer (16-bit number).");
52994 + * fb_fix_screeninfo defines the non-changeable properties of the VDC, depending on what mode it is in.
52996 +static struct fb_fix_screeninfo ubicom32fb_fix = {
52997 + .id = "Ubicom32",
52998 + .type = FB_TYPE_PACKED_PIXELS,
52999 + .visual = FB_VISUAL_TRUECOLOR,
53000 + .accel = FB_ACCEL_UBICOM32,
53004 + * Filled in at probe time when we find out what the hardware supports
53006 +static struct fb_var_screeninfo ubicom32fb_var;
53009 + * Private data structure
53011 +struct ubicom32fb_drvdata {
53012 + struct fb_info *fbinfo;
53016 + * The address of the framebuffer in memory
53019 + void *fb_aligned;
53022 + * Total size of vram including alignment allowance
53024 + u32 total_vram_size;
53027 + * Interrupt to set when changing registers
53032 + * Optional: Interrupt used by TIO to signal us
53037 + * Base address of the regs for VDC_TIO
53039 + volatile struct vdc_tio_vp_regs *regs;
53042 + * non-zero if we are in yuv mode
53047 + * Fake palette of 16 colors
53049 + u32 pseudo_palette[PALETTE_ENTRIES_NO];
53052 + * Wait queue and lock used to block when we need to wait
53053 + * for something to happen.
53055 + wait_queue_head_t waitq;
53056 + struct mutex lock;
53061 + * ubicom32fb_set_next_frame
53062 + * Sets the next frame buffer to display
53064 + * if sync is TRUE then this function will block until the hardware
53065 + * acknowledges the change
53067 +static inline void ubicom32fb_set_next_frame(struct ubicom32fb_drvdata *ud, void *fb, u8_t sync)
53069 + ud->regs->next_frame_flags = ud->is_yuv ? VDCTIO_NEXT_FRAME_FLAG_YUV : 0;
53070 + ud->regs->next_frame = (void *)((u32_t)fb | 1);
53073 + * If we have interrupts, then we can wait on it
53075 + if (ud->rx_int != -1) {
53076 + DEFINE_WAIT(wait);
53077 + unsigned long flags;
53079 + spin_lock_irqsave(&ud->lock, flags);
53080 + prepare_to_wait(&ud->waitq, &wait, TASK_INTERRUPTIBLE);
53081 + spin_unlock_irqrestore(&ud->lock, flags);
53083 + finish_wait(&ud->waitq, &wait);
53088 + * No interrupt, we will just spin here
53090 + while (sync && ((u32_t)ud->regs->next_frame & 1));
53094 + * ubicom32fb_send_command
53095 + * Sends a command/data pair to the VDC
53097 +static inline void ubicom32fb_send_command(struct ubicom32fb_drvdata *ud, u16 command, u8_t block)
53099 + ud->regs->command = command;
53100 + ubicom32_set_interrupt(ud->vp_int);
53101 + while (block && ud->regs->command);
53105 + * ubicom32fb_ioctl
53106 + * Handles any ioctls sent to us
53108 +static int ubicom32fb_ioctl(struct fb_info *fbi, unsigned int cmd,
53109 + unsigned long arg)
53111 + struct ubicom32fb_drvdata *ud = (struct ubicom32fb_drvdata *)fbi->par;
53112 + void __user *argp = (void __user *)arg;
53113 + int retval = -EFAULT;
53116 + case UBICOM32FB_IOCTL_SET_NEXT_FRAME_SYNC:
53117 + // check alignment, return -EINVAL if necessary
53118 + ubicom32fb_set_next_frame(ud, argp, 1);
53122 + case UBICOM32FB_IOCTL_SET_NEXT_FRAME:
53123 + // check alignment, return -EINVAL if necessary
53124 + ubicom32fb_set_next_frame(ud, argp, 0);
53128 + case UBICOM32FB_IOCTL_SET_MODE:
53129 + if (!(ud->regs->caps & VDCTIO_CAPS_SUPPORTS_SCALING)) {
53132 + struct ubicom32fb_mode mode;
53133 + volatile struct vdc_tio_vp_regs *regs = ud->regs;
53136 + if (copy_from_user(&mode, argp, sizeof(mode))) {
53140 + regs->x_in = mode.width;
53141 + regs->y_in = mode.height;
53142 + regs->x_out = regs->xres;
53143 + regs->y_out = regs->yres;
53144 + if (mode.flags & UBICOM32FB_IOCTL_SET_MODE_FLAG_YUV_SCAN_ORDER) {
53145 + flags |= VDCTIO_SCALE_FLAG_YUV_SCAN_ORDER;
53147 + if (mode.flags & UBICOM32FB_IOCTL_SET_MODE_FLAG_YUV_BLOCK_ORDER) {
53148 + flags |= VDCTIO_SCALE_FLAG_YUV_BLOCK_ORDER;
53150 + ud->is_yuv = mode.flags & UBICOM32FB_IOCTL_SET_MODE_FLAG_YUV;
53151 + if (ud->is_yuv) {
53152 + flags |= VDCTIO_SCALE_FLAG_YUV;
53154 + if (mode.flags & UBICOM32FB_IOCTL_SET_MODE_FLAG_VRANGE_16_255) {
53155 + flags |= VDCTIO_SCALE_FLAG_VRANGE_16_255;
53157 + if (mode.flags & UBICOM32FB_IOCTL_SET_MODE_FLAG_VRANGE_0_255) {
53158 + flags |= VDCTIO_SCALE_FLAG_VRANGE_0_255;
53160 + if (mode.flags & UBICOM32FB_IOCTL_SET_MODE_FLAG_VSUB) {
53161 + flags |= VDCTIO_SCALE_FLAG_VSUB;
53163 + if (mode.flags & UBICOM32FB_IOCTL_SET_MODE_FLAG_HSUB_2_1) {
53164 + flags |= VDCTIO_SCALE_FLAG_HSUB_2_1;
53166 + if (mode.flags & UBICOM32FB_IOCTL_SET_MODE_FLAG_HSUB_1_1) {
53167 + flags |= VDCTIO_SCALE_FLAG_HSUB_1_1;
53169 + if (mode.flags & UBICOM32FB_IOCTL_SET_MODE_FLAG_SCALE_ENABLE) {
53170 + flags |= VDCTIO_SCALE_FLAG_ENABLE;
53172 + if (mode.next_frame) {
53173 + flags |= VDCTIO_SCALE_FLAG_SET_FRAME_BUFFER;
53174 + regs->next_frame = mode.next_frame;
53177 + regs->scale_flags = flags;
53178 + ubicom32fb_send_command(ud, VDCTIO_COMMAND_SET_SCALE_MODE, 1);
53184 + retval = -ENOIOCTLCMD;
53192 + * ubicom32fb_interrupt
53193 + * Called by the OS when the TIO has set the rx_int
53195 +static irqreturn_t ubicom32fb_interrupt(int vec, void *appdata)
53197 + struct ubicom32fb_drvdata *ud = (struct ubicom32fb_drvdata *)appdata;
53199 + spin_lock(&ud->lock);
53200 + if (waitqueue_active(&ud->waitq)) {
53201 + wake_up(&ud->waitq);
53203 + spin_unlock(&ud->lock);
53205 + return IRQ_HANDLED;
53209 + * ubicom32fb_pan_display
53210 + * Pans the display to a given location. Supports only y direction panning.
53212 +static int ubicom32fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *fbi)
53214 + struct ubicom32fb_drvdata *ud = (struct ubicom32fb_drvdata *)fbi->par;
53218 + * Get the last y line that would be displayed. Since we don't support YWRAP,
53219 + * it must be less than our virtual y size.
53221 + u32 lasty = var->yoffset + var->yres;
53222 + if (lasty > fbi->var.yres_virtual) {
53224 + * We would fall off the end of our frame buffer if we panned here.
53229 + if (var->xoffset) {
53231 + * We don't support panning in the x direction
53237 + * Everything looks sane, go ahead and pan
53239 + * We have to calculate a new address for the VDC to look at
53241 + new_addr = ud->fb_aligned + (var->yoffset * fbi->fix.line_length);
53244 + * Send down the command. The buffer will switch at the next vertical blank
53246 + ubicom32fb_set_next_frame(ud, (void *)new_addr, 0);
53252 + * ubicom32fb_setcolreg
53253 + * Sets a color in our virtual palette
53255 +static int ubicom32fb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *fbi)
53257 + u32 *palette = fbi->pseudo_palette;
53259 + if (regno >= PALETTE_ENTRIES_NO) {
53264 + * We only use 8 bits from each color
53271 + * Convert any grayscale values
53273 + if (fbi->var.grayscale) {
53274 + u16 gray = red + green + blue;
53275 + gray += (gray >> 2) + (gray >> 3) - (gray >> 7);
53277 + if (gray > 255) {
53285 + palette[regno] = (red << fbi->var.red.offset) | (green << fbi->var.green.offset) |
53286 + (blue << fbi->var.blue.offset);
53292 + * ubicom32fb_mmap
53294 +static int ubicom32fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
53296 + struct ubicom32fb_drvdata *drvdata = (struct ubicom32fb_drvdata *)info->par;
53298 + vma->vm_start = (unsigned long)(drvdata->fb_aligned);
53300 + vma->vm_end = vma->vm_start + info->fix.smem_len;
53302 + /* For those who don't understand how mmap works, go read
53303 + * Documentation/nommu-mmap.txt.
53304 + * For those that do, you will know that the VM_MAYSHARE flag
53305 + * must be set in the vma->vm_flags structure on noMMU
53306 + * Other flags can be set, and are documented in
53307 + * include/linux/mm.h
53310 + vma->vm_flags |= VM_MAYSHARE | VM_SHARED;
53316 + * ubicom32fb_blank
53318 +static int ubicom32fb_blank(int blank_mode, struct fb_info *fbi)
53322 + struct ubicom32fb_drvdata *drvdata = to_ubicom32fb_drvdata(fbi);
53324 + switch (blank_mode) {
53325 + case FB_BLANK_UNBLANK:
53326 + /* turn on panel */
53327 + ubicom32fb_out_be32(drvdata, REG_CTRL, drvdata->reg_ctrl_default);
53330 + case FB_BLANK_NORMAL:
53331 + case FB_BLANK_VSYNC_SUSPEND:
53332 + case FB_BLANK_HSYNC_SUSPEND:
53333 + case FB_BLANK_POWERDOWN:
53334 + /* turn off panel */
53335 + ubicom32fb_out_be32(drvdata, REG_CTRL, 0);
53340 + return 0; /* success */
53344 +static struct fb_ops ubicom32fb_ops =
53346 + .owner = THIS_MODULE,
53347 + .fb_pan_display = ubicom32fb_pan_display,
53348 + .fb_setcolreg = ubicom32fb_setcolreg,
53349 + .fb_blank = ubicom32fb_blank,
53350 + .fb_mmap = ubicom32fb_mmap,
53351 + .fb_ioctl = ubicom32fb_ioctl,
53352 + .fb_fillrect = cfb_fillrect,
53353 + .fb_copyarea = cfb_copyarea,
53354 + .fb_imageblit = cfb_imageblit,
53358 + * ubicom32fb_release
53360 +static int ubicom32fb_release(struct device *dev)
53362 + struct ubicom32fb_drvdata *ud = dev_get_drvdata(dev);
53364 +#if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO)
53365 + //ubicom32fb_blank(VESA_POWERDOWN, &drvdata->info);
53368 + unregister_framebuffer(ud->fbinfo);
53370 + if (ud->cmap_alloc) {
53371 + fb_dealloc_cmap(&ud->fbinfo->cmap);
53378 + if (ud->rx_int != -1) {
53379 + free_irq(ud->rx_int, ud);
53383 + * Turn off the display
53385 + //ubicom32fb_out_be32(drvdata, REG_CTRL, 0);
53386 + //iounmap(drvdata->regs);
53388 + framebuffer_release(ud->fbinfo);
53389 + dev_set_drvdata(dev, NULL);
53395 + * ubicom32fb_platform_probe
53397 +static int __init ubicom32fb_platform_probe(struct platform_device *pdev)
53399 + struct ubicom32fb_drvdata *ud;
53400 + struct resource *irq_resource_rx;
53401 + struct resource *irq_resource_tx;
53402 + struct resource *mem_resource;
53403 + struct fb_info *fbinfo;
53406 + struct device *dev = &pdev->dev;
53408 + struct vdc_tio_vp_regs *regs;
53411 + * Get our resources
53413 + irq_resource_tx = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
53414 + if (!irq_resource_tx) {
53415 + dev_err(dev, "No tx IRQ resource assigned\n");
53419 + irq_resource_rx = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
53420 + if (!irq_resource_rx) {
53421 + dev_err(dev, "No rx IRQ resource assigned\n");
53425 + mem_resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
53426 + if (!mem_resource || !mem_resource->start) {
53427 + dev_err(dev, "No mem resource assigned\n");
53430 + regs = (struct vdc_tio_vp_regs *)mem_resource->start;
53431 + if (regs->version != VDCTIO_VP_VERSION) {
53432 + dev_err(dev, "VDCTIO is not compatible with this driver tio:%x drv:%x\n",
53433 + regs->version, VDCTIO_VP_VERSION);
53438 + * This is the minimum VRAM size
53440 + fbsize = regs->xres * regs->yres * (regs->bpp / 8);
53441 + if (!vram_size) {
53442 + vram_size = (fbsize + 1023) / 1024;
53444 + if (fbsize > (vram_size * 1024)) {
53445 + dev_err(dev, "Not enough VRAM for display, need >= %u bytes\n", fbsize);
53446 + return -ENOMEM; // should be ebadparam?
53451 + * Allocate the framebuffer instance + our private data
53453 + fbinfo = framebuffer_alloc(sizeof(struct ubicom32fb_drvdata), &pdev->dev);
53455 + dev_err(dev, "Not enough memory to allocate instance.\n");
53460 + * Fill in our private data.
53462 + ud = (struct ubicom32fb_drvdata *)fbinfo->par;
53463 + ud->fbinfo = fbinfo;
53464 + ud->regs = (struct vdc_tio_vp_regs *)(mem_resource->start);
53465 + dev_set_drvdata(dev, ud);
53467 + ud->vp_int = irq_resource_tx->start;
53470 + * If we were provided an rx_irq then we need to init the appropriate
53471 + * queues, locks, and functions.
53474 + if (irq_resource_rx->start != DEVTREE_IRQ_NONE) {
53475 + init_waitqueue_head(&ud->waitq);
53476 + mutex_init(&ud->lock);
53477 + if (request_irq(ud->rx_int, ubicom32fb_interrupt, IRQF_SHARED, "ubicom32fb_rx", ud)) {
53478 + dev_err(dev, "Couldn't request rx IRQ\n");
53482 + ud->rx_int = irq_resource_rx->start;
53486 + * Allocate and align the requested amount of VRAM
53488 + ud->total_vram_size = (vram_size * 1024) + regs->fb_align;
53489 + ud->fb = kmalloc(ud->total_vram_size, GFP_KERNEL);
53490 + if (ud->fb == NULL) {
53491 + dev_err(dev, "Couldn't allocate VRAM\n");
53496 + offset = (u32_t)ud->fb & (regs->fb_align - 1);
53498 + ud->fb_aligned = ud->fb;
53500 + offset = regs->fb_align - offset;
53501 + ud->fb_aligned = ud->fb + offset;
53505 + * Clear the entire frame buffer
53507 + if (!init_value) {
53508 + memset(ud->fb_aligned, 0, vram_size * 1024);
53510 + unsigned short *p = ud->fb_aligned;
53512 + for (i = 0; i < ((vram_size * 1024) / sizeof(u16_t)); i++) {
53513 + *p++ = init_value;
53518 + * Fill in the fb_var_screeninfo structure
53520 + memset(&ubicom32fb_var, 0, sizeof(ubicom32fb_var));
53521 + ubicom32fb_var.bits_per_pixel = regs->bpp;
53522 + ubicom32fb_var.red.offset = regs->rshift;
53523 + ubicom32fb_var.green.offset = regs->gshift;
53524 + ubicom32fb_var.blue.offset = regs->bshift;
53525 + ubicom32fb_var.red.length = regs->rbits;
53526 + ubicom32fb_var.green.length = regs->gbits;
53527 + ubicom32fb_var.blue.length = regs->bbits;
53528 + ubicom32fb_var.activate = FB_ACTIVATE_NOW;
53532 + * Turn on the display
53534 + ud->reg_ctrl_default = REG_CTRL_ENABLE;
53535 + if (regs->rotate_screen)
53536 + ud->reg_ctrl_default |= REG_CTRL_ROTATE;
53537 + ubicom32fb_out_be32(ud, REG_CTRL, ud->reg_ctrl_default);
53541 + * Fill in the fb_info structure
53543 + ud->fbinfo->device = dev;
53544 + ud->fbinfo->screen_base = (void *)ud->fb_aligned;
53545 + ud->fbinfo->fbops = &ubicom32fb_ops;
53546 + ud->fbinfo->fix = ubicom32fb_fix;
53547 + ud->fbinfo->fix.smem_start = (u32)ud->fb_aligned;
53548 + ud->fbinfo->fix.smem_len = vram_size * 1024;
53549 + ud->fbinfo->fix.line_length = regs->xres * (regs->bpp / 8);
53550 + ud->fbinfo->fix.mmio_start = (u32)regs;
53551 + ud->fbinfo->fix.mmio_len = sizeof(struct vdc_tio_vp_regs);
53554 + * We support panning in the y direction only
53556 + ud->fbinfo->fix.xpanstep = 0;
53557 + ud->fbinfo->fix.ypanstep = 1;
53559 + ud->fbinfo->pseudo_palette = ud->pseudo_palette;
53560 + ud->fbinfo->flags = FBINFO_DEFAULT;
53561 + ud->fbinfo->var = ubicom32fb_var;
53562 + ud->fbinfo->var.xres = regs->xres;
53563 + ud->fbinfo->var.yres = regs->yres;
53566 + * We cannot pan in the X direction, so xres_virtual is regs->xres
53567 + * We can pan in the Y direction, so yres_virtual is vram_size / ud->fbinfo->fix.line_length
53569 + ud->fbinfo->var.xres_virtual = regs->xres;
53570 + ud->fbinfo->var.yres_virtual = (vram_size * 1024) / ud->fbinfo->fix.line_length;
53572 + //ud->fbinfo->var.height = regs->height_mm;
53573 + //ud->fbinfo->var.width = regs->width_mm;
53576 + * Allocate a color map
53578 + rc = fb_alloc_cmap(&ud->fbinfo->cmap, PALETTE_ENTRIES_NO, 0);
53580 + dev_err(dev, "Fail to allocate colormap (%d entries)\n",
53581 + PALETTE_ENTRIES_NO);
53584 + ud->cmap_alloc = true;
53587 + * Register new frame buffer
53589 + rc = register_framebuffer(ud->fbinfo);
53591 + dev_err(dev, "Could not register frame buffer\n");
53596 + * Start up the VDC
53598 + ud->regs->next_frame = ud->fb;
53599 + ubicom32fb_send_command(ud, VDCTIO_COMMAND_START, 0);
53602 + * Tell the log we are here
53604 + dev_info(dev, "fbaddr=%p align=%p, size=%uKB screen(%ux%u) virt(%ux%u), regs=%p irqtx=%u irqrx=%u\n",
53605 + ud->fb, ud->fb_aligned, vram_size, ud->fbinfo->var.xres, ud->fbinfo->var.yres,
53606 + ud->fbinfo->var.xres_virtual, ud->fbinfo->var.yres_virtual, ud->regs,
53607 + irq_resource_tx->start, irq_resource_rx->start);
53615 + ubicom32fb_release(dev);
53620 + * ubicom32fb_platform_remove
53622 +static int ubicom32fb_platform_remove(struct platform_device *pdev)
53624 + dev_info(&(pdev->dev), "Ubicom32 FB Driver Remove\n");
53625 + return ubicom32fb_release(&pdev->dev);
53628 +static struct platform_driver ubicom32fb_platform_driver = {
53629 + .probe = ubicom32fb_platform_probe,
53630 + .remove = ubicom32fb_platform_remove,
53632 + .name = DRIVER_NAME,
53633 + .owner = THIS_MODULE,
53639 + * ubicom32fb_setup
53640 + * Process kernel boot options
53642 +static int __init ubicom32fb_setup(char *options)
53646 + if (!options || !*options) {
53650 + while ((this_opt = strsep(&options, ",")) != NULL) {
53651 + if (!*this_opt) {
53655 + if (!strncmp(this_opt, "init_value=", 10)) {
53656 + init_value = simple_strtoul(this_opt + 11, NULL, 0);
53660 + if (!strncmp(this_opt, "vram_size=", 10)) {
53661 + vram_size = simple_strtoul(this_opt + 10, NULL, 0);
53667 +#endif /* MODULE */
53670 + * ubicom32fb_init
53672 +static int __devinit ubicom32fb_init(void)
53676 + * Get kernel boot options (in 'video=ubicom32fb:<options>')
53678 + char *option = NULL;
53680 + if (fb_get_options(DRIVER_NAME, &option)) {
53683 + ubicom32fb_setup(option);
53684 +#endif /* MODULE */
53686 + return platform_driver_register(&ubicom32fb_platform_driver);
53688 +module_init(ubicom32fb_init);
53691 + * ubicom32fb_exit
53693 +static void __exit ubicom32fb_exit(void)
53695 + platform_driver_unregister(&ubicom32fb_platform_driver);
53697 +module_exit(ubicom32fb_exit);
53699 +MODULE_LICENSE("GPL");
53700 +MODULE_AUTHOR("Patrick Tjin <@ubicom.com>");
53701 +MODULE_DESCRIPTION(DRIVER_DESCRIPTION);
53703 +++ b/drivers/video/ubicom32plio80.c
53706 + * drivers/video/ubicom32plio80.c
53707 + * Ubicom32 80 bus PLIO buffer driver
53709 + * (C) Copyright 2009, Ubicom, Inc.
53711 + * This file is part of the Ubicom32 Linux Kernel Port.
53713 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
53714 + * it and/or modify it under the terms of the GNU General Public License
53715 + * as published by the Free Software Foundation, either version 2 of the
53716 + * License, or (at your option) any later version.
53718 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
53719 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
53720 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
53721 + * the GNU General Public License for more details.
53723 + * You should have received a copy of the GNU General Public License
53724 + * along with the Ubicom32 Linux Kernel Port. If not,
53725 + * see <http://www.gnu.org/licenses/>.
53729 + * This driver was based on skeletonfb.c, Skeleton for a frame buffer device by
53730 + * Geert Uytterhoeven.
53733 +#include <linux/device.h>
53734 +#include <linux/module.h>
53735 +#include <linux/kernel.h>
53736 +#include <linux/version.h>
53737 +#include <linux/errno.h>
53738 +#include <linux/string.h>
53739 +#include <linux/mm.h>
53740 +#include <linux/fb.h>
53741 +#include <linux/init.h>
53742 +#include <linux/interrupt.h>
53743 +#include <linux/dma-mapping.h>
53744 +#include <linux/platform_device.h>
53745 +#include <linux/device.h>
53746 +#include <linux/uaccess.h>
53747 +#include <asm/plio.h>
53749 +#define DRIVER_NAME "ubicom32plio80"
53750 +#define DRIVER_DESCRIPTION "Ubicom32 80 bus PLIO frame buffer driver"
53752 +#define PALETTE_ENTRIES_NO 16
53755 + * Option variables
53757 + * vram_size: VRAM size in kilobytes, subject to alignment
53759 +static int vram_size = 0;
53760 +module_param(vram_size, int, 0);
53761 +MODULE_PARM_DESC(vram_size, "VRAM size, in kilobytes to allocate, should be at least the size of one screen, subject to alignment");
53763 +static int xres = 240;
53764 +module_param(xres, int, 0);
53765 +MODULE_PARM_DESC(xres, "x (horizontal) resolution");
53767 +static int yres = 320;
53768 +module_param(yres, int, 0);
53769 +MODULE_PARM_DESC(yres, "y (vertical) resolution");
53771 +static int bgr = 0;
53772 +module_param(bgr, int, 0);
53773 +MODULE_PARM_DESC(bgr, "display is BGR (Blue is MSB)");
53775 +#define BITS_PER_PIXEL 16
53778 + * Buffer alignment, must not be 0
53780 +#define UBICOM32PLIO80_ALIGNMENT 4
53784 + * 16-bit data bus on port I
53785 + * CS on EXTCTL[6]
53786 + * WR on EXTCTL[4]
53788 +static const plio_fctl_t plio_fctl = {
53790 + .ptif_port_mode = PLIO_PORT_MODE_DI,
53791 + .ptif_portd_cfg = 0,
53792 + .ptif_porti_cfg = 3,
53794 + .edif_cmp_mode = 1,
53795 + .ecif_extclk_ena = 0, // enable clock output on PD7 table 2.65/p111 says extctl[0]?
53796 + .icif_clk_src_sel = PLIO_CLK_IO,
53799 + .icif_eclk_div = 10,
53800 + .icif_iclk_div = 10,
53805 + static const plio_config_t plio_config = {
53810 + .grpsel[0] = {1,1,1,1,1,1,1,1,1,1},
53813 + * Table 12.66 Counter load value
53815 + .cs_lut[0] = {0,0,0,0,0,0,0,0},
53818 + * Table 2.75 PLIO PFSM Configuration Registers
53821 + .extctl_o_lut[0] = {0x3f, 0x2f, 0x3f, 0x3f},
53823 + .extctl_o_lut[1] = {0x3f, 0x3f, 0x3f, 0x2f},
53826 + .odr_oe = 0xffff,
53829 + .output_ena = (1 << 6) | (1 << 4),
53833 +static const u32_t ubicom32plio80_plio_fsm[] = {
53835 + 0x00070007, 0x00070007,
53836 + 0x00070007, 0x00070007,
53837 + 0x00070007, 0x00070007,
53838 + 0x00070007, 0x00070007,
53840 + 0x16260806, 0x16260806,
53841 + 0x16260806, 0x16260806,
53842 + 0x16260806, 0x16260806,
53843 + 0x16260806, 0x16260806,
53846 + 0x22061806, 0x22061806,
53847 + 0x22061806, 0x22061806,
53848 + 0x22061806, 0x22061806,
53849 + 0x22061806, 0x22061806,
53851 + 0x22061806, 0x22061806,
53852 + 0x22061806, 0x22061806,
53853 + 0x22061806, 0x22061806,
53854 + 0x22061806, 0x22061806,
53857 + 0x00070806, 0x00070806,
53858 + 0x00070806, 0x00070806,
53859 + 0x00070806, 0x00070806,
53860 + 0x00070806, 0x00070806,
53862 + 0x00070806, 0x00070806,
53863 + 0x00070806, 0x00070806,
53864 + 0x00070806, 0x00070806,
53865 + 0x00070806, 0x00070806,
53869 + * fb_fix_screeninfo defines the non-changeable properties of the VDC, depending on what mode it is in.
53871 +static struct fb_fix_screeninfo ubicom32plio80_fix = {
53872 + .id = "Ubicom32",
53873 + .type = FB_TYPE_PACKED_PIXELS,
53874 + .visual = FB_VISUAL_TRUECOLOR,
53875 + .accel = FB_ACCEL_UBICOM32_PLIO80,
53879 + * Filled in at probe time when we find out what the hardware supports
53881 +static struct fb_var_screeninfo ubicom32plio80_var;
53884 + * Private data structure
53886 +struct ubicom32plio80_drvdata {
53887 + struct fb_info *fbinfo;
53891 + * The address of the framebuffer in memory
53894 + void *fb_aligned;
53897 + * Total size of vram including alignment allowance
53899 + u32 total_vram_size;
53902 + * Fake palette of 16 colors
53904 + u32 pseudo_palette[PALETTE_ENTRIES_NO];
53909 + * Current pointer and bytes left to transfer with the PLIO
53912 + u32 bytes_to_xfer;
53916 +static struct platform_device *ubicom32plio80_platform_device;
53919 + * ubicom32plio80_isr
53921 +static int ubicom32plio80_isr(int irq, void *appdata)
53923 + struct ubicom32plio80_drvdata *ud = (struct ubicom32plio80_drvdata *)appdata;
53925 + if (!ud->bytes_to_xfer) {
53926 + ubicom32_disable_interrupt(TX_FIFO_INT(PLIO_PORT));
53927 + PLIO_NBR->intmask.txfifo_wm = 0;
53929 + return IRQ_HANDLED;
53934 + "move.4 (%[fifo]), (%[data])4++ \n\t"
53936 + : [data] "+a" (ud->xfer_ptr)
53937 + : [fifo] "a" (&PLIO_NBR->tx_lo)
53940 + ud->bytes_to_xfer -= 32;
53942 + return IRQ_HANDLED;
53946 + * ubicom32plio80_update
53948 +static void ubicom32plio80_update(struct ubicom32plio80_drvdata *ud, u32 *fb)
53950 + struct ubicom32_io_port *ri = (struct ubicom32_io_port *)RI;
53951 + struct ubicom32_io_port *rd = (struct ubicom32_io_port *)RD;
53953 + ud->xfer_ptr = fb;
53954 + ud->bytes_to_xfer = (xres * yres * 2) - 64;
53957 + ri->gpio_mask = 0;
53958 + rd->gpio_mask &= ~((1 << 4) | (1 << 2));
53960 + *(u32 *)(&PLIO_NBR->intclr) = ~0;
53961 + PLIO_NBR->intmask.txfifo_wm = 1;
53962 + PLIO_NBR->fifo_wm.tx = 8;
53963 + ubicom32_enable_interrupt(TX_FIFO_INT(PLIO_PORT));
53967 + "move.4 (%[fifo]), (%[data])4++ \n\t"
53969 + : [data] "+a" (ud->xfer_ptr)
53970 + : [fifo] "a" (&PLIO_NBR->tx_lo)
53975 + * ubicom32plio80_pan_display
53976 + * Pans the display to a given location. Supports only y direction panning.
53978 +static int ubicom32plio80_pan_display(struct fb_var_screeninfo *var, struct fb_info *fbi)
53980 + struct ubicom32plio80_drvdata *ud = (struct ubicom32plio80_drvdata *)fbi->par;
53984 + * Get the last y line that would be displayed. Since we don't support YWRAP,
53985 + * it must be less than our virtual y size.
53987 + u32 lasty = var->yoffset + var->yres;
53988 + if (lasty > fbi->var.yres_virtual) {
53990 + * We would fall off the end of our frame buffer if we panned here.
53995 + if (var->xoffset) {
53997 + * We don't support panning in the x direction
54003 + * Everything looks sane, go ahead and pan
54005 + * We have to calculate a new address for the VDC to look at
54007 + new_addr = ud->fb_aligned + (var->yoffset * fbi->fix.line_length);
54013 + * ubicom32plio80_setcolreg
54014 + * Sets a color in our virtual palette
54016 +static int ubicom32plio80_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *fbi)
54018 + u32 *palette = fbi->pseudo_palette;
54020 + if (regno >= PALETTE_ENTRIES_NO) {
54025 + * We only use 8 bits from each color
54032 + * Convert any grayscale values
54034 + if (fbi->var.grayscale) {
54035 + u16 gray = red + green + blue;
54036 + gray += (gray >> 2) + (gray >> 3) - (gray >> 7);
54038 + if (gray > 255) {
54046 + palette[regno] = (red << fbi->var.red.offset) | (green << fbi->var.green.offset) |
54047 + (blue << fbi->var.blue.offset);
54053 + * ubicom32plio80_mmap
54055 +static int ubicom32plio80_mmap(struct fb_info *info, struct vm_area_struct *vma)
54057 + struct ubicom32plio80_drvdata *ud = (struct ubicom32plio80_drvdata *)info->par;
54059 + vma->vm_start = (unsigned long)(ud->fb_aligned);
54061 + vma->vm_end = vma->vm_start + info->fix.smem_len;
54063 + /* For those who don't understand how mmap works, go read
54064 + * Documentation/nommu-mmap.txt.
54065 + * For those that do, you will know that the VM_MAYSHARE flag
54066 + * must be set in the vma->vm_flags structure on noMMU
54067 + * Other flags can be set, and are documented in
54068 + * include/linux/mm.h
54071 + vma->vm_flags |= VM_MAYSHARE | VM_SHARED;
54077 + * ubicom32plio80_check_var
54078 + * Check the var, tweak it but don't change operational parameters.
54080 +static int ubicom32plio80_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
54082 + struct ubicom32plio80_drvdata *ud = (struct ubicom32plio80_drvdata *)info->par;
54083 + u32 line_size = var->xres * (BITS_PER_PIXEL / 8);
54086 + * See if we can handle this bpp
54088 + if (var->bits_per_pixel > BITS_PER_PIXEL) {
54091 + var->bits_per_pixel = BITS_PER_PIXEL;
54094 + * See if we have enough memory to handle this resolution
54096 + if ((line_size * var->yres * BITS_PER_PIXEL / 8) > ud->total_vram_size) {
54100 + var->xres_virtual = var->xres;
54101 + var->yres_virtual = ud->total_vram_size / line_size;
54103 + var->red.length = 5;
54104 + var->green.length = 6;
54105 + var->green.offset = 5;
54106 + var->blue.length = 5;
54107 + var->transp.offset = var->transp.length = 0;
54110 + var->red.offset = 0;
54111 + var->blue.offset = 11;
54113 + var->red.offset = 11;
54114 + var->blue.offset = 0;
54118 + var->height = -1;
54120 + var->vmode = FB_VMODE_NONINTERLACED;
54127 + * ubicom32plio80_set_par
54128 + * Set the video mode according to info->var
54130 +static int ubicom32plio80_set_par(struct fb_info *info)
54133 + * Anything changed?
54135 + if ((xres == info->var.xres) && (yres == info->var.yres)) {
54140 + * Implement changes
54142 + xres = info->var.xres;
54143 + yres = info->var.yres;
54144 + info->fix.visual = FB_VISUAL_TRUECOLOR;
54145 + info->fix.xpanstep = 0;
54146 + info->fix.ypanstep = 1;
54147 + info->fix.line_length = xres * (BITS_PER_PIXEL / 8);
54153 + * ubicom32plio80_ops
54154 + * List of supported operations
54156 +static struct fb_ops ubicom32plio80_ops =
54158 + .owner = THIS_MODULE,
54159 + .fb_pan_display = ubicom32plio80_pan_display,
54160 + .fb_setcolreg = ubicom32plio80_setcolreg,
54161 + .fb_mmap = ubicom32plio80_mmap,
54162 + .fb_check_var = ubicom32plio80_check_var,
54163 + .fb_set_par = ubicom32plio80_set_par,
54164 + .fb_fillrect = cfb_fillrect,
54165 + .fb_copyarea = cfb_copyarea,
54166 + .fb_imageblit = cfb_imageblit,
54170 + * ubicom32plio80_release
54172 +static int ubicom32plio80_release(struct device *dev)
54174 + struct ubicom32plio80_drvdata *ud = dev_get_drvdata(dev);
54176 + unregister_framebuffer(ud->fbinfo);
54178 + if (ud->irq_req) {
54179 + free_irq(TX_FIFO_INT(PLIO_PORT), ud);
54181 + if (ud->cmap_alloc) {
54182 + fb_dealloc_cmap(&ud->fbinfo->cmap);
54189 + framebuffer_release(ud->fbinfo);
54190 + dev_set_drvdata(dev, NULL);
54196 + * ubicom32plio80_platform_probe
54198 +static int __init ubicom32plio80_platform_probe(struct platform_device *pdev)
54200 + struct ubicom32plio80_drvdata *ud;
54201 + struct fb_info *fbinfo;
54204 + struct device *dev = &pdev->dev;
54208 + * This is the minimum VRAM size
54210 + fbsize = xres * yres * 2;
54211 + if (!vram_size) {
54212 + vram_size = (fbsize + 1023) / 1024;
54214 + if (fbsize > (vram_size * 1024)) {
54215 + dev_err(dev, "Not enough VRAM for display, need >= %u bytes\n", fbsize);
54216 + return -ENOMEM; // should be ebadparam?
54221 + * Allocate the framebuffer instance + our private data
54223 + fbinfo = framebuffer_alloc(sizeof(struct ubicom32plio80_drvdata), &pdev->dev);
54225 + dev_err(dev, "Not enough memory to allocate instance.\n");
54230 + * Fill in our private data.
54232 + ud = (struct ubicom32plio80_drvdata *)fbinfo->par;
54233 + ud->fbinfo = fbinfo;
54234 + dev_set_drvdata(dev, ud);
54237 + * Allocate and align the requested amount of VRAM
54239 + ud->total_vram_size = (vram_size * 1024) + UBICOM32PLIO80_ALIGNMENT;
54240 + ud->fb = kmalloc(ud->total_vram_size, GFP_KERNEL);
54241 + if (ud->fb == NULL) {
54242 + dev_err(dev, "Couldn't allocate VRAM\n");
54247 + offset = (u32_t)ud->fb & (UBICOM32PLIO80_ALIGNMENT - 1);
54249 + ud->fb_aligned = ud->fb;
54251 + offset = UBICOM32PLIO80_ALIGNMENT - offset;
54252 + ud->fb_aligned = ud->fb + offset;
54256 + * Clear the entire frame buffer
54258 + memset(ud->fb_aligned, 0, vram_size * 1024);
54261 + * Fill in the fb_var_screeninfo structure
54263 + memset(&ubicom32plio80_var, 0, sizeof(ubicom32plio80_var));
54264 + ubicom32plio80_var.bits_per_pixel = BITS_PER_PIXEL;
54265 + ubicom32plio80_var.red.length = 5;
54266 + ubicom32plio80_var.green.length = 6;
54267 + ubicom32plio80_var.green.offset = 5;
54268 + ubicom32plio80_var.blue.length = 5;
54269 + ubicom32plio80_var.activate = FB_ACTIVATE_NOW;
54272 + ubicom32plio80_var.red.offset = 0;
54273 + ubicom32plio80_var.blue.offset = 11;
54275 + ubicom32plio80_var.red.offset = 11;
54276 + ubicom32plio80_var.blue.offset = 0;
54280 + * Fill in the fb_info structure
54282 + ud->fbinfo->device = dev;
54283 + ud->fbinfo->screen_base = (void *)ud->fb_aligned;
54284 + ud->fbinfo->fbops = &ubicom32plio80_ops;
54285 + ud->fbinfo->fix = ubicom32plio80_fix;
54286 + ud->fbinfo->fix.smem_start = (u32)ud->fb_aligned;
54287 + ud->fbinfo->fix.smem_len = vram_size * 1024;
54288 + ud->fbinfo->fix.line_length = xres * 2;
54289 + ud->fbinfo->fix.mmio_start = (u32)ud;
54290 + ud->fbinfo->fix.mmio_len = sizeof(struct ubicom32plio80_drvdata);
54293 + * We support panning in the y direction only
54295 + ud->fbinfo->fix.xpanstep = 0;
54296 + ud->fbinfo->fix.ypanstep = 1;
54298 + ud->fbinfo->pseudo_palette = ud->pseudo_palette;
54299 + ud->fbinfo->flags = FBINFO_DEFAULT;
54300 + ud->fbinfo->var = ubicom32plio80_var;
54301 + ud->fbinfo->var.xres = xres;
54302 + ud->fbinfo->var.yres = yres;
54305 + * We cannot pan in the X direction, so xres_virtual is xres
54306 + * We can pan in the Y direction, so yres_virtual is vram_size / ud->fbinfo->fix.line_length
54308 + ud->fbinfo->var.xres_virtual = xres;
54309 + ud->fbinfo->var.yres_virtual = (vram_size * 1024) / ud->fbinfo->fix.line_length;
54312 + * Allocate a color map
54314 + rc = fb_alloc_cmap(&ud->fbinfo->cmap, PALETTE_ENTRIES_NO, 0);
54316 + dev_err(dev, "Fail to allocate colormap (%d entries)\n",
54317 + PALETTE_ENTRIES_NO);
54320 + ud->cmap_alloc = true;
54323 + * Register new frame buffer
54325 + rc = register_framebuffer(ud->fbinfo);
54327 + dev_err(dev, "Could not register frame buffer\n");
54332 + * request the PLIO IRQ
54334 + rc = request_irq(TX_FIFO_INT(PLIO_PORT), ubicom32plio80_isr, IRQF_DISABLED, "ubicom32plio80", ud);
54336 + dev_err(dev, "Could not request IRQ\n");
54342 + * Clear any garbage out of the TX FIFOs (idif_txfifo_flush)
54344 + * cast through ubicom32_io_port to make sure the compiler does a word write
54346 + ((struct ubicom32_io_port *)PLIO_NBR)->int_set = (1 << 18);
54349 + * Start up the state machine
54351 + plio_init(&plio_fctl, &plio_config, (plio_sram_t *)ubicom32plio80_plio_fsm, sizeof(ubicom32plio80_plio_fsm));
54352 + PLIO_NBR->fctl0.pfsm_cmd = 0;
54354 + ubicom32plio80_update(ud, ud->fb_aligned);
54357 + * Tell the log we are here
54359 + dev_info(dev, "fbaddr=%p align=%p, size=%uKB screen(%ux%u) virt(%ux%u)\n",
54360 + ud->fb, ud->fb_aligned, vram_size, ud->fbinfo->var.xres, ud->fbinfo->var.yres,
54361 + ud->fbinfo->var.xres_virtual, ud->fbinfo->var.yres_virtual);
54369 + ubicom32plio80_release(dev);
54374 + * ubicom32plio80_platform_remove
54376 +static int ubicom32plio80_platform_remove(struct platform_device *pdev)
54378 + dev_info(&(pdev->dev), "Ubicom32 FB Driver Remove\n");
54379 + return ubicom32plio80_release(&pdev->dev);
54382 +static struct platform_driver ubicom32plio80_platform_driver = {
54383 + .probe = ubicom32plio80_platform_probe,
54384 + .remove = ubicom32plio80_platform_remove,
54386 + .name = DRIVER_NAME,
54387 + .owner = THIS_MODULE,
54393 + * ubicom32plio80_setup
54394 + * Process kernel boot options
54396 +static int __init ubicom32plio80_setup(char *options)
54400 + if (!options || !*options) {
54404 + while ((this_opt = strsep(&options, ",")) != NULL) {
54405 + if (!*this_opt) {
54409 + if (!strncmp(this_opt, "vram_size=", 10)) {
54410 + vram_size = simple_strtoul(this_opt + 10, NULL, 0);
54414 + if (!strncmp(this_opt, "bgr=", 4)) {
54415 + bgr = simple_strtoul(this_opt + 4, NULL, 0);
54419 + if (!strncmp(this_opt, "xres=", 5)) {
54420 + xres = simple_strtoul(this_opt + 5, NULL, 0);
54424 + if (!strncmp(this_opt, "yres=", 5)) {
54425 + yres = simple_strtoul(this_opt + 5, NULL, 0);
54431 +#endif /* MODULE */
54434 + * ubicom32plio80_init
54436 +static int __devinit ubicom32plio80_init(void)
54442 + * Get kernel boot options (in 'video=ubicom32plio80:<options>')
54444 + char *option = NULL;
54446 + if (fb_get_options(DRIVER_NAME, &option)) {
54449 + ubicom32plio80_setup(option);
54450 +#endif /* MODULE */
54452 + ret = platform_driver_register(&ubicom32plio80_platform_driver);
54455 + ubicom32plio80_platform_device = platform_device_alloc(DRIVER_NAME, 0);
54457 + if (ubicom32plio80_platform_device)
54458 + ret = platform_device_add(ubicom32plio80_platform_device);
54463 + platform_device_put(ubicom32plio80_platform_device);
54464 + platform_driver_unregister(&ubicom32plio80_platform_driver);
54470 +module_init(ubicom32plio80_init);
54473 + * ubicom32plio80_exit
54475 +static void __exit ubicom32plio80_exit(void)
54477 + platform_device_unregister(ubicom32plio80_platform_device);
54478 + platform_driver_unregister(&ubicom32plio80_platform_driver);
54480 +module_exit(ubicom32plio80_exit);
54482 +MODULE_LICENSE("GPL");
54483 +MODULE_AUTHOR("Patrick Tjin <@ubicom.com>");
54484 +MODULE_DESCRIPTION(DRIVER_DESCRIPTION);
54486 +++ b/drivers/video/ubicom32vfb.c
54489 + * drivers/video/ubicom32vfb.c
54490 + * Ubicom32 virtual frame buffer driver
54492 + * (C) Copyright 2009, Ubicom, Inc.
54494 + * This file is part of the Ubicom32 Linux Kernel Port.
54496 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
54497 + * it and/or modify it under the terms of the GNU General Public License
54498 + * as published by the Free Software Foundation, either version 2 of the
54499 + * License, or (at your option) any later version.
54501 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
54502 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
54503 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
54504 + * the GNU General Public License for more details.
54506 + * You should have received a copy of the GNU General Public License
54507 + * along with the Ubicom32 Linux Kernel Port. If not,
54508 + * see <http://www.gnu.org/licenses/>.
54512 + * This driver was based on skeletonfb.c, Skeleton for a frame buffer device by
54513 + * Geert Uytterhoeven.
54516 +#include <linux/device.h>
54517 +#include <linux/module.h>
54518 +#include <linux/kernel.h>
54519 +#include <linux/version.h>
54520 +#include <linux/errno.h>
54521 +#include <linux/string.h>
54522 +#include <linux/mm.h>
54523 +#include <linux/fb.h>
54524 +#include <linux/init.h>
54525 +#include <linux/dma-mapping.h>
54526 +#include <linux/platform_device.h>
54527 +#include <linux/device.h>
54528 +#include <linux/uaccess.h>
54530 +#define DRIVER_NAME "ubicom32vfb"
54531 +#define DRIVER_DESCRIPTION "Ubicom32 virtual frame buffer driver"
54533 +#define PALETTE_ENTRIES_NO 16
54536 + * Option variables
54538 + * vram_size: VRAM size in kilobytes, subject to alignment
54540 +static int vram_size = 0;
54541 +module_param(vram_size, int, 0);
54542 +MODULE_PARM_DESC(vram_size, "VRAM size, in kilobytes to allocate, should be at least the size of one screen, subject to alignment");
54544 +static int xres = 320;
54545 +module_param(xres, int, 0);
54546 +MODULE_PARM_DESC(xres, "x (horizontal) resolution");
54548 +static int yres = 240;
54549 +module_param(yres, int, 0);
54550 +MODULE_PARM_DESC(yres, "y (vertical) resolution");
54552 +static int bgr = 0;
54553 +module_param(bgr, int, 0);
54554 +MODULE_PARM_DESC(bgr, "display is BGR (Blue is MSB)");
54556 +#define BITS_PER_PIXEL 16
54559 + * Buffer alignment, must not be 0
54561 +#define UBICOM32VFB_ALIGNMENT 4
54564 + * fb_fix_screeninfo defines the non-changeable properties of the VDC, depending on what mode it is in.
54566 +static struct fb_fix_screeninfo ubicom32vfb_fix = {
54567 + .id = "Ubicom32",
54568 + .type = FB_TYPE_PACKED_PIXELS,
54569 + .visual = FB_VISUAL_TRUECOLOR,
54570 + .accel = FB_ACCEL_UBICOM32_VFB,
54574 + * Filled in at probe time when we find out what the hardware supports
54576 +static struct fb_var_screeninfo ubicom32vfb_var;
54579 + * Private data structure
54581 +struct ubicom32vfb_drvdata {
54582 + struct fb_info *fbinfo;
54586 + * The address of the framebuffer in memory
54589 + void *fb_aligned;
54592 + * Total size of vram including alignment allowance
54594 + u32 total_vram_size;
54597 + * Fake palette of 16 colors
54599 + u32 pseudo_palette[PALETTE_ENTRIES_NO];
54602 +static struct platform_device *ubicom32vfb_platform_device;
54605 + * ubicom32vfb_pan_display
54606 + * Pans the display to a given location. Supports only y direction panning.
54608 +static int ubicom32vfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *fbi)
54610 + struct ubicom32vfb_drvdata *ud = (struct ubicom32vfb_drvdata *)fbi->par;
54614 + * Get the last y line that would be displayed. Since we don't support YWRAP,
54615 + * it must be less than our virtual y size.
54617 + u32 lasty = var->yoffset + var->yres;
54618 + if (lasty > fbi->var.yres_virtual) {
54620 + * We would fall off the end of our frame buffer if we panned here.
54625 + if (var->xoffset) {
54627 + * We don't support panning in the x direction
54633 + * Everything looks sane, go ahead and pan
54635 + * We have to calculate a new address for the VDC to look at
54637 + new_addr = ud->fb_aligned + (var->yoffset * fbi->fix.line_length);
54643 + * ubicom32vfb_setcolreg
54644 + * Sets a color in our virtual palette
54646 +static int ubicom32vfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *fbi)
54648 + u32 *palette = fbi->pseudo_palette;
54650 + if (regno >= PALETTE_ENTRIES_NO) {
54655 + * We only use 8 bits from each color
54662 + * Convert any grayscale values
54664 + if (fbi->var.grayscale) {
54665 + u16 gray = red + green + blue;
54666 + gray += (gray >> 2) + (gray >> 3) - (gray >> 7);
54668 + if (gray > 255) {
54676 + palette[regno] = (red << fbi->var.red.offset) | (green << fbi->var.green.offset) |
54677 + (blue << fbi->var.blue.offset);
54683 + * ubicom32vfb_mmap
54685 +static int ubicom32vfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
54687 + struct ubicom32vfb_drvdata *ud = (struct ubicom32vfb_drvdata *)info->par;
54689 + vma->vm_start = (unsigned long)(ud->fb_aligned);
54691 + vma->vm_end = vma->vm_start + info->fix.smem_len;
54693 + /* For those who don't understand how mmap works, go read
54694 + * Documentation/nommu-mmap.txt.
54695 + * For those that do, you will know that the VM_MAYSHARE flag
54696 + * must be set in the vma->vm_flags structure on noMMU
54697 + * Other flags can be set, and are documented in
54698 + * include/linux/mm.h
54701 + vma->vm_flags |= VM_MAYSHARE | VM_SHARED;
54707 + * ubicom32vfb_check_var
54708 + * Check the var, tweak it but don't change operational parameters.
54710 +static int ubicom32vfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
54712 + struct ubicom32vfb_drvdata *ud = (struct ubicom32vfb_drvdata *)info->par;
54713 + u32 line_size = var->xres * (BITS_PER_PIXEL / 8);
54716 + * See if we can handle this bpp
54718 + if (var->bits_per_pixel > BITS_PER_PIXEL) {
54721 + var->bits_per_pixel = BITS_PER_PIXEL;
54724 + * See if we have enough memory to handle this resolution
54726 + if ((line_size * var->yres * BITS_PER_PIXEL / 8) > ud->total_vram_size) {
54730 + var->xres_virtual = var->xres;
54731 + var->yres_virtual = ud->total_vram_size / line_size;
54733 + var->red.length = 5;
54734 + var->green.length = 6;
54735 + var->green.offset = 5;
54736 + var->blue.length = 5;
54737 + var->transp.offset = var->transp.length = 0;
54740 + var->red.offset = 0;
54741 + var->blue.offset = 11;
54743 + var->red.offset = 11;
54744 + var->blue.offset = 0;
54748 + var->height = -1;
54750 + var->vmode = FB_VMODE_NONINTERLACED;
54757 + * ubicom32vfb_set_par
54758 + * Set the video mode according to info->var
54760 +static int ubicom32vfb_set_par(struct fb_info *info)
54763 + * Anything changed?
54765 + if ((xres == info->var.xres) && (yres == info->var.yres)) {
54770 + * Implement changes
54772 + xres = info->var.xres;
54773 + yres = info->var.yres;
54774 + info->fix.visual = FB_VISUAL_TRUECOLOR;
54775 + info->fix.xpanstep = 0;
54776 + info->fix.ypanstep = 1;
54777 + info->fix.line_length = xres * (BITS_PER_PIXEL / 8);
54783 + * ubicom32vfb_ops
54784 + * List of supported operations
54786 +static struct fb_ops ubicom32vfb_ops =
54788 + .owner = THIS_MODULE,
54789 + .fb_pan_display = ubicom32vfb_pan_display,
54790 + .fb_setcolreg = ubicom32vfb_setcolreg,
54791 + .fb_mmap = ubicom32vfb_mmap,
54792 + .fb_check_var = ubicom32vfb_check_var,
54793 + .fb_set_par = ubicom32vfb_set_par,
54794 + .fb_fillrect = cfb_fillrect,
54795 + .fb_copyarea = cfb_copyarea,
54796 + .fb_imageblit = cfb_imageblit,
54800 + * ubicom32vfb_release
54802 +static int ubicom32vfb_release(struct device *dev)
54804 + struct ubicom32vfb_drvdata *ud = dev_get_drvdata(dev);
54806 + unregister_framebuffer(ud->fbinfo);
54808 + if (ud->cmap_alloc) {
54809 + fb_dealloc_cmap(&ud->fbinfo->cmap);
54816 + framebuffer_release(ud->fbinfo);
54817 + dev_set_drvdata(dev, NULL);
54823 + * ubicom32vfb_platform_probe
54825 +static int __init ubicom32vfb_platform_probe(struct platform_device *pdev)
54827 + struct ubicom32vfb_drvdata *ud;
54828 + struct fb_info *fbinfo;
54831 + struct device *dev = &pdev->dev;
54835 + * This is the minimum VRAM size
54837 + fbsize = xres * yres * 2;
54838 + if (!vram_size) {
54839 + vram_size = (fbsize + 1023) / 1024;
54841 + if (fbsize > (vram_size * 1024)) {
54842 + dev_err(dev, "Not enough VRAM for display, need >= %u bytes\n", fbsize);
54843 + return -ENOMEM; // should be ebadparam?
54848 + * Allocate the framebuffer instance + our private data
54850 + fbinfo = framebuffer_alloc(sizeof(struct ubicom32vfb_drvdata), &pdev->dev);
54852 + dev_err(dev, "Not enough memory to allocate instance.\n");
54857 + * Fill in our private data.
54859 + ud = (struct ubicom32vfb_drvdata *)fbinfo->par;
54860 + ud->fbinfo = fbinfo;
54861 + dev_set_drvdata(dev, ud);
54864 + * Allocate and align the requested amount of VRAM
54866 + ud->total_vram_size = (vram_size * 1024) + UBICOM32VFB_ALIGNMENT;
54867 + ud->fb = kmalloc(ud->total_vram_size, GFP_KERNEL);
54868 + if (ud->fb == NULL) {
54869 + dev_err(dev, "Couldn't allocate VRAM\n");
54874 + offset = (u32_t)ud->fb & (UBICOM32VFB_ALIGNMENT - 1);
54876 + ud->fb_aligned = ud->fb;
54878 + offset = UBICOM32VFB_ALIGNMENT - offset;
54879 + ud->fb_aligned = ud->fb + offset;
54883 + * Clear the entire frame buffer
54885 + memset(ud->fb_aligned, 0, vram_size * 1024);
54888 + * Fill in the fb_var_screeninfo structure
54890 + memset(&ubicom32vfb_var, 0, sizeof(ubicom32vfb_var));
54891 + ubicom32vfb_var.bits_per_pixel = BITS_PER_PIXEL;
54892 + ubicom32vfb_var.red.length = 5;
54893 + ubicom32vfb_var.green.length = 6;
54894 + ubicom32vfb_var.green.offset = 5;
54895 + ubicom32vfb_var.blue.length = 5;
54896 + ubicom32vfb_var.activate = FB_ACTIVATE_NOW;
54899 + ubicom32vfb_var.red.offset = 0;
54900 + ubicom32vfb_var.blue.offset = 11;
54902 + ubicom32vfb_var.red.offset = 11;
54903 + ubicom32vfb_var.blue.offset = 0;
54907 + * Fill in the fb_info structure
54909 + ud->fbinfo->device = dev;
54910 + ud->fbinfo->screen_base = (void *)ud->fb_aligned;
54911 + ud->fbinfo->fbops = &ubicom32vfb_ops;
54912 + ud->fbinfo->fix = ubicom32vfb_fix;
54913 + ud->fbinfo->fix.smem_start = (u32)ud->fb_aligned;
54914 + ud->fbinfo->fix.smem_len = vram_size * 1024;
54915 + ud->fbinfo->fix.line_length = xres * 2;
54916 + ud->fbinfo->fix.mmio_start = (u32)ud;
54917 + ud->fbinfo->fix.mmio_len = sizeof(struct ubicom32vfb_drvdata);
54920 + * We support panning in the y direction only
54922 + ud->fbinfo->fix.xpanstep = 0;
54923 + ud->fbinfo->fix.ypanstep = 1;
54925 + ud->fbinfo->pseudo_palette = ud->pseudo_palette;
54926 + ud->fbinfo->flags = FBINFO_DEFAULT;
54927 + ud->fbinfo->var = ubicom32vfb_var;
54928 + ud->fbinfo->var.xres = xres;
54929 + ud->fbinfo->var.yres = yres;
54932 + * We cannot pan in the X direction, so xres_virtual is xres
54933 + * We can pan in the Y direction, so yres_virtual is vram_size / ud->fbinfo->fix.line_length
54935 + ud->fbinfo->var.xres_virtual = xres;
54936 + ud->fbinfo->var.yres_virtual = (vram_size * 1024) / ud->fbinfo->fix.line_length;
54939 + * Allocate a color map
54941 + rc = fb_alloc_cmap(&ud->fbinfo->cmap, PALETTE_ENTRIES_NO, 0);
54943 + dev_err(dev, "Fail to allocate colormap (%d entries)\n",
54944 + PALETTE_ENTRIES_NO);
54947 + ud->cmap_alloc = true;
54950 + * Register new frame buffer
54952 + rc = register_framebuffer(ud->fbinfo);
54954 + dev_err(dev, "Could not register frame buffer\n");
54959 + * Tell the log we are here
54961 + dev_info(dev, "fbaddr=%p align=%p, size=%uKB screen(%ux%u) virt(%ux%u)\n",
54962 + ud->fb, ud->fb_aligned, vram_size, ud->fbinfo->var.xres, ud->fbinfo->var.yres,
54963 + ud->fbinfo->var.xres_virtual, ud->fbinfo->var.yres_virtual);
54971 + ubicom32vfb_release(dev);
54976 + * ubicom32vfb_platform_remove
54978 +static int ubicom32vfb_platform_remove(struct platform_device *pdev)
54980 + dev_info(&(pdev->dev), "Ubicom32 FB Driver Remove\n");
54981 + return ubicom32vfb_release(&pdev->dev);
54984 +static struct platform_driver ubicom32vfb_platform_driver = {
54985 + .probe = ubicom32vfb_platform_probe,
54986 + .remove = ubicom32vfb_platform_remove,
54988 + .name = DRIVER_NAME,
54989 + .owner = THIS_MODULE,
54995 + * ubicom32vfb_setup
54996 + * Process kernel boot options
54998 +static int __init ubicom32vfb_setup(char *options)
55002 + if (!options || !*options) {
55006 + while ((this_opt = strsep(&options, ",")) != NULL) {
55007 + if (!*this_opt) {
55011 + if (!strncmp(this_opt, "vram_size=", 10)) {
55012 + vram_size = simple_strtoul(this_opt + 10, NULL, 0);
55016 + if (!strncmp(this_opt, "bgr=", 4)) {
55017 + bgr = simple_strtoul(this_opt + 4, NULL, 0);
55021 + if (!strncmp(this_opt, "xres=", 5)) {
55022 + xres = simple_strtoul(this_opt + 5, NULL, 0);
55026 + if (!strncmp(this_opt, "yres=", 5)) {
55027 + yres = simple_strtoul(this_opt + 5, NULL, 0);
55033 +#endif /* MODULE */
55036 + * ubicom32vfb_init
55038 +static int __devinit ubicom32vfb_init(void)
55044 + * Get kernel boot options (in 'video=ubicom32vfb:<options>')
55046 + char *option = NULL;
55048 + if (fb_get_options(DRIVER_NAME, &option)) {
55051 + ubicom32vfb_setup(option);
55052 +#endif /* MODULE */
55054 + ret = platform_driver_register(&ubicom32vfb_platform_driver);
55056 +#ifdef CONFIG_FB_UBICOM32_VIRTUAL_NOAUTO
55060 + ubicom32vfb_platform_device = platform_device_alloc(DRIVER_NAME, 0);
55062 + if (ubicom32vfb_platform_device)
55063 + ret = platform_device_add(ubicom32vfb_platform_device);
55068 + platform_device_put(ubicom32vfb_platform_device);
55069 + platform_driver_unregister(&ubicom32vfb_platform_driver);
55076 +module_init(ubicom32vfb_init);
55079 + * ubicom32vfb_exit
55081 +static void __exit ubicom32vfb_exit(void)
55083 + platform_device_unregister(ubicom32vfb_platform_device);
55084 + platform_driver_unregister(&ubicom32vfb_platform_driver);
55086 +module_exit(ubicom32vfb_exit);
55088 +MODULE_LICENSE("GPL");
55089 +MODULE_AUTHOR("Patrick Tjin <@ubicom.com>");
55090 +MODULE_DESCRIPTION(DRIVER_DESCRIPTION);
55091 --- a/drivers/watchdog/Kconfig
55092 +++ b/drivers/watchdog/Kconfig
55093 @@ -887,6 +887,19 @@ config WATCHDOG_RIO
55094 machines. The watchdog timeout period is normally one minute but
55095 can be changed with a boot-time parameter.
55100 + tristate "Ubicom32 Hardware Watchdog support"
55101 + depends on UBICOM32
55103 + If you say yes here you will get support for the Ubicom32 On-Chip
55104 + Watchdog Timer. If you have one of these processors and wish to
55105 + have watchdog support enabled, say Y, otherwise say N.
55107 + To compile this driver as a module, choose M here: the
55108 + module will be called ubi32_wdt.
55110 # XTENSA Architecture
55113 --- a/drivers/watchdog/Makefile
55114 +++ b/drivers/watchdog/Makefile
55115 @@ -131,6 +131,9 @@ obj-$(CONFIG_SH_WDT) += shwdt.o
55116 obj-$(CONFIG_WATCHDOG_RIO) += riowd.o
55117 obj-$(CONFIG_WATCHDOG_CP1XXX) += cpwd.o
55119 +# Ubicom32 Architecture
55120 +obj-$(CONFIG_UBI32_WDT) += ubi32_wdt.o
55122 # XTENSA Architecture
55124 # Architecture Independant
55126 +++ b/drivers/watchdog/ubi32_wdt.c
55129 + * drivers/watchdog/ubi32_wdt.c
55130 + * Ubicom32 Watchdog Driver
55132 + * Originally based on softdog.c
55133 + * Copyright 2006-2007 Analog Devices Inc.
55134 + * Copyright 2006-2007 Michele d'Amico
55135 + * Copyright 1996 Alan Cox <alan@lxorguk.ukuu.org.uk>
55136 + * (C) Copyright 2009, Ubicom, Inc.
55138 + * This file is part of the Ubicom32 Linux Kernel Port.
55140 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
55141 + * it and/or modify it under the terms of the GNU General Public License
55142 + * as published by the Free Software Foundation, either version 2 of the
55143 + * License, or (at your option) any later version.
55145 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
55146 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
55147 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
55148 + * the GNU General Public License for more details.
55150 + * You should have received a copy of the GNU General Public License
55151 + * along with the Ubicom32 Linux Kernel Port. If not,
55152 + * see <http://www.gnu.org/licenses/>.
55154 + * Ubicom32 implementation derived from (with many thanks):
55159 +#include <linux/platform_device.h>
55160 +#include <linux/module.h>
55161 +#include <linux/moduleparam.h>
55162 +#include <linux/types.h>
55163 +#include <linux/timer.h>
55164 +#include <linux/miscdevice.h>
55165 +#include <linux/watchdog.h>
55166 +#include <linux/fs.h>
55167 +#include <linux/notifier.h>
55168 +#include <linux/reboot.h>
55169 +#include <linux/init.h>
55170 +#include <linux/interrupt.h>
55171 +#include <linux/uaccess.h>
55172 +#include <asm/ip5000.h>
55174 +#define WATCHDOG_NAME "ubi32-wdt"
55175 +#define PFX WATCHDOG_NAME ": "
55177 +#define OSC1_FREQ 12000000
55178 +#define WATCHDOG_SEC_TO_CYC(x) (OSC1_FREQ * (x))
55179 +#define WATCHDOG_MAX_SEC (0xffffffff / OSC1_FREQ)
55181 +#define MIN_PROCESSOR_ADDRESS 0x03000000
55183 +static DEFINE_SPINLOCK(ubi32_wdt_spinlock);
55185 +#define WATCHDOG_TIMEOUT 20
55187 +#if defined(CONFIG_WATCHDOG_NOWAYOUT)
55188 +#define WATCHDOG_NOWAYOUT 1
55190 +#define WATCHDOG_NOWAYOUT 0
55193 +static unsigned int timeout = WATCHDOG_TIMEOUT;
55194 +static int nowayout = WATCHDOG_NOWAYOUT;
55195 +static struct watchdog_info ubi32_wdt_info;
55196 +static unsigned long open_check;
55197 +static char expect_close;
55199 +#if !defined(CONFIG_SMP)
55200 +#define UBI32_WDT_LOCK(lock, flags) local_irq_save(flags)
55201 +#define UBI32_WDT_UNLOCK(lock, flags) local_irq_restore(flags)
55202 +#define UBI32_WDT_LOCK_CHECK()
55204 +#define UBI32_WDT_LOCK(lock, flags) spin_lock_irqsave((lock), (flags));
55205 +#define UBI32_WDT_UNLOCK(lock, flags) spin_unlock_irqrestore((lock), (flags));
55206 +#define UBI32_WDT_LOCK_CHECK() BUG_ON(!spin_is_locked(&ubi32_wdt_spinlock));
55210 + * ubi32_wdt_remaining()
55211 + * Return the approximate number of seconds remaining
55213 +static int ubi32_wdt_remaining(void)
55218 + UBI32_WDT_LOCK_CHECK();
55220 + ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, TIMER_TKEYVAL);
55221 + compare = ubicom32_read_reg(&UBICOM32_IO_TIMER->wdcom);
55222 + curr = ubicom32_read_reg(&UBICOM32_IO_TIMER->mptval);
55223 + ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, 0);
55224 + return (compare - curr) / OSC1_FREQ;
55229 + * ubi32_wdt_keepalive()
55230 + * Keep the Userspace Watchdog Alive
55232 + * The Userspace watchdog got a KeepAlive: schedule the next timeout.
55234 +static int ubi32_wdt_keepalive(void)
55236 + UBI32_WDT_LOCK_CHECK();
55237 + ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, TIMER_TKEYVAL);
55238 + ubicom32_write_reg(&UBICOM32_IO_TIMER->wdcom,
55239 + ubicom32_read_reg(&UBICOM32_IO_TIMER->mptval)
55240 + + WATCHDOG_SEC_TO_CYC(timeout));
55241 + ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, 0);
55246 + * ubi32_wdt_stop()
55247 + * Stop the on-chip Watchdog
55249 +static int ubi32_wdt_stop(void)
55251 + UBI32_WDT_LOCK_CHECK();
55252 + ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, TIMER_TKEYVAL);
55253 + ubicom32_write_reg(&UBICOM32_IO_TIMER->wdcfg, TIMER_WATCHDOG_DISABLE);
55254 + ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, 0);
55259 + * ubi32_wdt_start()
55260 + * Start the on-chip Watchdog
55262 +static int ubi32_wdt_start(void)
55264 + UBI32_WDT_LOCK_CHECK();
55265 + ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, TIMER_TKEYVAL);
55266 + ubicom32_write_reg(&UBICOM32_IO_TIMER->wdcom,
55267 + ubicom32_read_reg(&UBICOM32_IO_TIMER->mptval)
55268 + + WATCHDOG_SEC_TO_CYC(timeout));
55269 + ubicom32_write_reg(&UBICOM32_IO_TIMER->wdcfg, ~TIMER_WATCHDOG_DISABLE);
55270 + ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, 0);
55275 + * ubi32_wdt_running()
55276 + * Return true if the watchdog is configured
55278 +static int ubi32_wdt_running(void)
55282 + UBI32_WDT_LOCK_CHECK();
55283 + ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, TIMER_TKEYVAL);
55284 + enabled = ubicom32_read_reg(&UBICOM32_IO_TIMER->wdcfg) == ~TIMER_WATCHDOG_DISABLE;
55285 + ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, 0);
55290 + * ubi32_wdt_set_timeout()
55291 + * Set the Userspace Watchdog timeout
55293 + * - @t: new timeout value (in seconds)
55295 +static int ubi32_wdt_set_timeout(unsigned long t)
55297 + UBI32_WDT_LOCK_CHECK();
55299 + if (t > WATCHDOG_MAX_SEC) {
55300 + printk(KERN_WARNING PFX "request to large: %ld [1-%d] sec)\n", t, WATCHDOG_MAX_SEC);
55305 + * If we are running, then reset the time value so
55306 + * that the new value has an immediate effect.
55309 + if (ubi32_wdt_running()) {
55310 + ubi32_wdt_keepalive();
55316 + * ubi32_wdt_open()
55317 + * Open the Device
55319 +static int ubi32_wdt_open(struct inode *inode, struct file *file)
55321 + unsigned long flags;
55323 + if (test_and_set_bit(0, &open_check))
55327 + __module_get(THIS_MODULE);
55329 + spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
55330 + ubi32_wdt_start();
55331 + spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
55333 + return nonseekable_open(inode, file);
55337 + * ubi32_wdt_close()
55338 + * Close the Device
55340 +static int ubi32_wdt_release(struct inode *inode, struct file *file)
55342 + unsigned long flags;
55345 + * If we don't expect a close, then the watchdog continues
55346 + * even though the device is closed. The caller will have
55347 + * a full timeout value to reopen the device and continue
55350 + if (expect_close != 42) {
55351 + printk(KERN_CRIT PFX
55352 + "Unexpected close, not stopping watchdog!\n");
55353 + spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
55354 + ubi32_wdt_keepalive();
55355 + spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
55357 + spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
55358 + ubi32_wdt_stop();
55359 + spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
55362 + expect_close = 0;
55363 + clear_bit(0, &open_check);
55368 + * ubi32_wdt_write()
55369 + * Write to Device
55371 + * If the user writes nothing, nothing happens.
55372 + * If the user writes a V, then we expect a close and allow a release.
55373 + * If the user writes anything else, it is ignored.
55375 +static ssize_t ubi32_wdt_write(struct file *file, const char __user *data,
55376 + size_t len, loff_t *ppos)
55379 + unsigned long flags;
55382 + * Every write resets the expect_close. The last write
55383 + * must be a V to allow shutdown on close.
55385 + expect_close = 0;
55388 + * Empty writes still ping.
55395 + * If nowayout is set, it does not matter if the caller
55396 + * is trying to send the magic 'V' we will not allow a
55397 + * close to stop us.
55404 + * See if the program wrote a 'V' and if so disable
55405 + * the watchdog on release.
55407 + for (i = 0; i < len; i++) {
55409 + if (get_user(c, data + i)) {
55414 + expect_close = 42;
55419 + spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
55420 + ubi32_wdt_keepalive();
55421 + spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
55426 + * ubi32_wdt_ioctl()
55427 + * Query the watchdog device.
55429 + * Query basic information from the device or ping it, as outlined by the
55432 +static long ubi32_wdt_ioctl(struct file *file,
55433 + unsigned int cmd, unsigned long arg)
55435 + void __user *argp = (void __user *)arg;
55436 + int __user *p = argp;
55439 + case WDIOC_GETSUPPORT:
55440 + if (copy_to_user(argp, &ubi32_wdt_info, sizeof(ubi32_wdt_info))) {
55445 + case WDIOC_GETSTATUS: {
55446 + unsigned long flags;
55449 + spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
55450 + running = ubi32_wdt_running();
55451 + spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
55455 + case WDIOC_GETBOOTSTATUS:
55456 + return ubicom32_get_reset_reason();
55458 + case WDIOC_SETOPTIONS: {
55459 + unsigned long flags;
55460 + int options, ret = -EINVAL;
55463 + * The sample application does not pass a pointer
55464 + * but directly passes a value of 1 or 2; however
55465 + * all of the implementations (and thus probably
55466 + * the real applications) pass a pointer to a value.
55468 + * It should be noted that WDIOC_SETOPTIONS is defined as
55469 + * _IOR(WATCHDOG_IOCTL_BASE, 4, int), which means
55470 + * that it should be an int and NOT a pointer.
55472 + * TODO: Examine this code for future chips.
55473 + * TODO: Report the sample code defect.
55475 + if ((int)p < MIN_PROCESSOR_ADDRESS) {
55476 + options = (int)p;
55478 + if (get_user(options, p))
55482 + spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
55483 + if (options & WDIOS_DISABLECARD) {
55484 + ubi32_wdt_stop();
55487 + if (options & WDIOS_ENABLECARD) {
55488 + ubi32_wdt_start();
55491 + spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
55495 + case WDIOC_KEEPALIVE: {
55496 + unsigned long flags;
55498 + spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
55499 + ubi32_wdt_keepalive();
55500 + spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
55504 + case WDIOC_SETTIMEOUT: {
55506 + unsigned long flags;
55509 + if (get_user(new_timeout, p))
55512 + spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
55513 + ret = ubi32_wdt_set_timeout(new_timeout);
55514 + spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
55519 + case WDIOC_GETTIMEOUT:
55520 + return put_user(timeout, p);
55522 + case WDIOC_GETTIMELEFT: {
55523 + unsigned long flags;
55524 + int remaining = 0;
55526 + spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
55527 + remaining = ubi32_wdt_remaining();
55528 + spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
55529 + return put_user(remaining, p);
55538 + * ubi32_wdt_notify_sys()
55539 + * Notification callback function for system events.
55541 + * Turn off the watchdog during a SYS_DOWN or SYS_HALT.
55543 +static int ubi32_wdt_notify_sys(struct notifier_block *this,
55544 + unsigned long code, void *unused)
55546 + if (code == SYS_DOWN || code == SYS_HALT) {
55547 + unsigned long flags;
55549 + spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
55550 + ubi32_wdt_stop();
55551 + spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
55554 + return NOTIFY_DONE;
55558 +static int state_before_suspend;
55561 + * ubi32_wdt_suspend()
55562 + * suspend the watchdog
55564 + * Remember if the watchdog was running and stop it.
55566 +static int ubi32_wdt_suspend(struct platform_device *pdev, pm_message_t state)
55568 + unsigned long flags;
55569 + spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
55570 + state_before_suspend = ubi32_wdt_running();
55571 + ubi32_wdt_stop();
55572 + spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
55578 + * ubi32_wdt_resume()
55579 + * Resume the watchdog
55581 + * If the watchdog was running, turn it back on.
55583 +static int ubi32_wdt_resume(struct platform_device *pdev)
55585 + if (state_before_suspend) {
55586 + unsigned long flags;
55587 + spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
55588 + ubi32_wdt_set_timeout(timeout);
55589 + ubi32_wdt_start();
55590 + spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
55596 +# define ubi32_wdt_suspend NULL
55597 +# define ubi32_wdt_resume NULL
55600 +static const struct file_operations ubi32_wdt_fops = {
55601 + .owner = THIS_MODULE,
55602 + .llseek = no_llseek,
55603 + .write = ubi32_wdt_write,
55604 + .unlocked_ioctl = ubi32_wdt_ioctl,
55605 + .open = ubi32_wdt_open,
55606 + .release = ubi32_wdt_release,
55609 +static struct miscdevice ubi32_wdt_miscdev = {
55610 + .minor = WATCHDOG_MINOR,
55611 + .name = "watchdog",
55612 + .fops = &ubi32_wdt_fops,
55615 +static struct watchdog_info ubi32_wdt_info = {
55616 + .identity = "Ubicom32 Watchdog",
55617 + .options = WDIOF_SETTIMEOUT |
55618 + WDIOF_KEEPALIVEPING |
55619 + WDIOF_MAGICCLOSE,
55622 +static struct notifier_block ubi32_wdt_notifier = {
55623 + .notifier_call = ubi32_wdt_notify_sys,
55627 + * ubi32_wdt_probe()
55628 + * Probe/register the watchdog module
55630 + * Registers the misc device and notifier handler. Actual device
55631 + * initialization is handled by ubi32_wdt_open().
55633 +static int __devinit ubi32_wdt_probe(struct platform_device *pdev)
55637 + ret = register_reboot_notifier(&ubi32_wdt_notifier);
55639 + printk(KERN_ERR PFX
55640 + "cannot register reboot notifier (err=%d)\n", ret);
55644 + ret = misc_register(&ubi32_wdt_miscdev);
55646 + printk(KERN_ERR PFX
55647 + "cannot register miscdev on minor=%d (err=%d)\n",
55648 + WATCHDOG_MINOR, ret);
55649 + unregister_reboot_notifier(&ubi32_wdt_notifier);
55653 + printk(KERN_INFO PFX "initialized: timeout=%d sec (nowayout=%d)\n",
55654 + timeout, nowayout);
55660 + * ubi32_wdt_remove()
55661 + * Uninstall the module
55663 + * Unregisters the misc device and notifier handler. Actual device
55664 + * deinitialization is handled by ubi32_wdt_close().
55666 +static int __devexit ubi32_wdt_remove(struct platform_device *pdev)
55668 + misc_deregister(&ubi32_wdt_miscdev);
55669 + unregister_reboot_notifier(&ubi32_wdt_notifier);
55673 +static struct platform_device *ubi32_wdt_device;
55675 +static struct platform_driver ubi32_wdt_driver = {
55676 + .probe = ubi32_wdt_probe,
55677 + .remove = __devexit_p(ubi32_wdt_remove),
55678 + .suspend = ubi32_wdt_suspend,
55679 + .resume = ubi32_wdt_resume,
55681 + .name = WATCHDOG_NAME,
55682 + .owner = THIS_MODULE,
55687 + * ubi32_wdt_init()
55688 + * Initialize the watchdog.
55690 + * Checks the module params and registers the platform device & driver.
55691 + * Real work is in the platform probe function.
55693 +static int __init ubi32_wdt_init(void)
55695 + unsigned long flags;
55699 + * Check that the timeout value is within range
55701 + spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
55702 + ret = ubi32_wdt_set_timeout(timeout);
55703 + spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
55709 + * Since this is an on-chip device and needs no board-specific
55710 + * resources, we'll handle all the platform device stuff here.
55712 + ret = platform_driver_register(&ubi32_wdt_driver);
55714 + printk(KERN_ERR PFX "unable to register driver\n");
55718 + ubi32_wdt_device = platform_device_register_simple(WATCHDOG_NAME, -1, NULL, 0);
55719 + if (IS_ERR(ubi32_wdt_device)) {
55720 + printk(KERN_ERR PFX "unable to register device\n");
55721 + platform_driver_unregister(&ubi32_wdt_driver);
55722 + return PTR_ERR(ubi32_wdt_device);
55729 + * ubi32_wdt_exit()
55730 + * Deinitialize module
55732 + * Back out the platform device & driver steps. Real work is in the
55733 + * platform remove function.
55735 +static void __exit ubi32_wdt_exit(void)
55737 + platform_device_unregister(ubi32_wdt_device);
55738 + platform_driver_unregister(&ubi32_wdt_driver);
55741 +module_init(ubi32_wdt_init);
55742 +module_exit(ubi32_wdt_exit);
55744 +MODULE_AUTHOR("Sol Kavy<sol@ubicom.com>");
55745 +MODULE_DESCRIPTION("Ubicom32 Watchdog Device Driver");
55746 +MODULE_LICENSE("GPL");
55747 +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
55749 +module_param(timeout, uint, 0);
55750 +MODULE_PARM_DESC(timeout,
55751 + "Watchdog timeout in seconds. (1<=timeout<=((2^32)/SCLK), default="
55752 + __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
55754 +module_param(nowayout, int, 0);
55755 +MODULE_PARM_DESC(nowayout,
55756 + "Watchdog cannot be stopped once started (default="
55757 + __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
55758 --- a/fs/binfmt_flat.c
55759 +++ b/fs/binfmt_flat.c
55761 #define FLAT_DATA_ALIGN (sizeof(void *))
55764 +#ifndef ARCH_FLAT_ALIGN
55765 +#undef FLAT_DATA_ALIGN
55766 +#define FLAT_DATA_ALIGN ARCH_FLAT_ALIGN
55769 #define RELOC_FAILED 0xff00ff01 /* Relocation incorrect somewhere */
55770 #define UNLOADED_LIB 0x7ff000ff /* Placeholder for unused library */
55772 @@ -436,6 +441,7 @@ static int load_flat_file(struct linux_b
55774 unsigned long start_code, end_code;
55776 + int flush_happened = 0;
55778 hdr = ((struct flat_hdr *) bprm->buf); /* exec-header */
55779 inode = bprm->file->f_path.dentry->d_inode;
55780 @@ -521,6 +527,7 @@ static int load_flat_file(struct linux_b
55782 /* OK, This is the point of no return */
55783 set_personality(PER_LINUX_32BIT);
55784 + flush_happened = 1;
55788 @@ -535,6 +542,12 @@ static int load_flat_file(struct linux_b
55791 if ((flags & (FLAT_FLAG_RAM|FLAT_FLAG_GZIP)) == 0) {
55793 +#ifdef ARCH_FLAT_ALIGN_TEXT
55794 + printk("Unable to mmap rom with ARCH alignment requirements\n");
55799 * this should give us a ROM ptr, but if it doesn't we don't
55801 @@ -553,7 +566,7 @@ static int load_flat_file(struct linux_b
55805 - len = data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long);
55806 + len = data_len + extra + ALIGN(MAX_SHARED_LIBS * sizeof(unsigned long), FLAT_DATA_ALIGN);
55807 len = PAGE_ALIGN(len);
55808 down_write(¤t->mm->mmap_sem);
55809 realdatastart = do_mmap(0, 0, len,
55810 @@ -572,6 +585,7 @@ static int load_flat_file(struct linux_b
55811 datapos = ALIGN(realdatastart +
55812 MAX_SHARED_LIBS * sizeof(unsigned long),
55814 + //datapos = realdatastart + ALIGN(MAX_SHARED_LIBS * sizeof(unsigned long), ARCH_FLAT_ALIGN);
55816 DBG_FLT("BINFMT_FLAT: Allocated data+bss+stack (%d bytes): %x\n",
55817 (int)(data_len + bss_len + stack_len), (int)datapos);
55818 @@ -600,7 +614,11 @@ static int load_flat_file(struct linux_b
55822 - len = text_len + data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long);
55823 + len = text_len + data_len + extra + ALIGN(MAX_SHARED_LIBS * sizeof(unsigned long), FLAT_DATA_ALIGN);
55824 +#ifdef ARCH_FLAT_ALIGN_TEXT
55825 + /* Reserve space for the text alignment. */
55826 + len += FLAT_DATA_ALIGN;
55828 len = PAGE_ALIGN(len);
55829 down_write(¤t->mm->mmap_sem);
55830 textpos = do_mmap(0, 0, len,
55831 @@ -616,10 +634,17 @@ static int load_flat_file(struct linux_b
55836 +#ifdef ARCH_FLAT_ALIGN_TEXT
55837 + textpos = ALIGN(textpos + sizeof(struct flat_hdr), FLAT_DATA_ALIGN) - sizeof(struct flat_hdr);
55839 realdatastart = textpos + ntohl(hdr->data_start);
55840 datapos = ALIGN(realdatastart +
55841 MAX_SHARED_LIBS * sizeof(unsigned long),
55843 +// datapos = realdatastart + ALIGN(MAX_SHARED_LIBS * sizeof(unsigned long), ARCH_FLAT_ALIGN);
55844 +// reloc = (unsigned long *) (textpos + ntohl(hdr->reloc_start) +
55845 +// ALIGN(MAX_SHARED_LIBS * sizeof(unsigned long), ARCH_FLAT_ALIGN));
55847 reloc = (unsigned long *)
55848 (datapos + (ntohl(hdr->reloc_start) - text_len));
55849 @@ -659,7 +684,7 @@ static int load_flat_file(struct linux_b
55851 if (result >= (unsigned long)-4096) {
55852 printk("Unable to read code+data+bss, errno %d\n",(int)-result);
55853 - do_munmap(current->mm, textpos, text_len + data_len + extra +
55854 + do_munmap(current->mm, memp, text_len + data_len + extra +
55855 MAX_SHARED_LIBS * sizeof(unsigned long));
55858 @@ -672,6 +697,9 @@ static int load_flat_file(struct linux_b
55860 /* The main program needs a little extra setup in the task structure */
55861 start_code = textpos + sizeof (struct flat_hdr);
55862 +#ifdef ARCH_FLAT_ALIGN_TEXT
55863 + BUG_ON(ALIGN(start_code, FLAT_DATA_ALIGN) != start_code);
55865 end_code = textpos + text_len;
55867 current->mm->start_code = start_code;
55868 @@ -800,6 +828,13 @@ static int load_flat_file(struct linux_b
55872 + if (flush_happened) {
55874 + * The parent process has already started running. We cannot allow the child to return back to user space
55875 + * as this child is still uning the parent stack and 2 will clobber each other. We are going to kill this child.
55877 + do_exit(SIGTERM);
55882 --- a/fs/Kconfig.binfmt
55883 +++ b/fs/Kconfig.binfmt
55884 @@ -30,7 +30,7 @@ config COMPAT_BINFMT_ELF
55885 config BINFMT_ELF_FDPIC
55886 bool "Kernel support for FDPIC ELF binaries"
55888 - depends on (FRV || BLACKFIN || (SUPERH32 && !MMU))
55889 + depends on (FRV || BLACKFIN || (SUPERH32 && !MMU) || UBICOM32)
55891 ELF FDPIC binaries are based on ELF, but allow the individual load
55892 segments of a binary to be located in memory independently of each
55893 --- a/include/asm-generic/resource.h
55894 +++ b/include/asm-generic/resource.h
55895 @@ -69,13 +69,16 @@
55897 * boot-time rlimit defaults for the init task:
55899 +#ifndef CONFIG_ELF_CORE
55900 +#define CONFIG_USER_ELF_CORE_SIZE 0
55902 #define INIT_RLIMITS \
55904 [RLIMIT_CPU] = { RLIM_INFINITY, RLIM_INFINITY }, \
55905 [RLIMIT_FSIZE] = { RLIM_INFINITY, RLIM_INFINITY }, \
55906 [RLIMIT_DATA] = { RLIM_INFINITY, RLIM_INFINITY }, \
55907 [RLIMIT_STACK] = { _STK_LIM, _STK_LIM_MAX }, \
55908 - [RLIMIT_CORE] = { 0, RLIM_INFINITY }, \
55909 + [RLIMIT_CORE] = { CONFIG_USER_ELF_CORE_SIZE, RLIM_INFINITY }, \
55910 [RLIMIT_RSS] = { RLIM_INFINITY, RLIM_INFINITY }, \
55911 [RLIMIT_NPROC] = { 0, 0 }, \
55912 [RLIMIT_NOFILE] = { INR_OPEN, INR_OPEN }, \
55913 --- a/include/linux/elf-em.h
55914 +++ b/include/linux/elf-em.h
55916 * up with a final number.
55918 #define EM_ALPHA 0x9026
55919 +#define EM_UBICOM32 0xde3d /* Ubicom32; no ABI */
55921 /* Bogus old v850 magic number, used by old tools. */
55922 #define EM_CYGNUS_V850 0x9080
55923 --- a/include/linux/fb.h
55924 +++ b/include/linux/fb.h
55925 @@ -151,6 +151,10 @@ struct dentry;
55926 #define FB_ACCEL_PROSAVAGE_DDR 0x8d /* S3 ProSavage DDR */
55927 #define FB_ACCEL_PROSAVAGE_DDRK 0x8e /* S3 ProSavage DDR-K */
55929 +#define FB_ACCEL_UBICOM32 0x0100 /* Ubicom32 */
55930 +#define FB_ACCEL_UBICOM32_VFB 0x0101 /* Ubicom32 VFB */
55931 +#define FB_ACCEL_UBICOM32_PLIO80 0x0102 /* Ubicom32 PLIO80 */
55933 struct fb_fix_screeninfo {
55934 char id[16]; /* identification string eg "TT Builtin" */
55935 unsigned long smem_start; /* Start of frame buffer mem */
55936 --- a/include/linux/if_ppp.h
55937 +++ b/include/linux/if_ppp.h
55938 @@ -114,14 +114,14 @@ struct pppol2tp_ioc_stats {
55939 __u16 tunnel_id; /* redundant */
55940 __u16 session_id; /* if zero, get tunnel stats */
55941 __u32 using_ipsec:1; /* valid only for session_id == 0 */
55942 - aligned_u64 tx_packets;
55943 - aligned_u64 tx_bytes;
55944 - aligned_u64 tx_errors;
55945 - aligned_u64 rx_packets;
55946 - aligned_u64 rx_bytes;
55947 - aligned_u64 rx_seq_discards;
55948 - aligned_u64 rx_oos_packets;
55949 - aligned_u64 rx_errors;
55950 + __u64 tx_packets;
55953 + __u64 rx_packets;
55955 + __u64 rx_seq_discards;
55956 + __u64 rx_oos_packets;
55960 #define ifr__name b.ifr_ifrn.ifrn_name
55961 --- a/include/linux/oprofile.h
55962 +++ b/include/linux/oprofile.h
55963 @@ -99,6 +99,8 @@ void oprofile_add_sample(struct pt_regs
55965 void oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs,
55966 unsigned long event, int is_kernel);
55967 +void oprofile_add_ext_sample_cpu(unsigned long pc, struct pt_regs * const regs,
55968 + unsigned long event, int is_kernel, int cpu);
55970 /* Use this instead when the PC value is not from the regs. Doesn't
55972 --- a/include/linux/serial_core.h
55973 +++ b/include/linux/serial_core.h
55974 @@ -167,6 +167,9 @@
55976 #define PORT_MAX3100 86
55979 +#define PORT_UBI32_UARTTIO 87
55983 #include <linux/compiler.h>
55984 --- a/include/linux/slab.h
55985 +++ b/include/linux/slab.h
55986 @@ -317,4 +317,14 @@ static inline void *kzalloc_node(size_t
55987 return kmalloc_node(size, flags | __GFP_ZERO, node);
55990 +struct kmem_cache_size_info {
55991 + unsigned short page;
55992 + unsigned short order;
55996 + * get info on all the memory allocated by slab for this named cache
55998 +extern int kmem_cache_block_info(char *name, struct kmem_cache_size_info *data, int max_data);
56000 #endif /* _LINUX_SLAB_H */
56003 @@ -865,6 +865,12 @@ config ELF_CORE
56005 Enable support for generating core dumps. Disabling saves about 4k.
56007 +config USER_ELF_CORE_SIZE
56008 + int "user core dump size (10MB to 32MB)"
56009 + range 10485760 33554432
56011 + depends on ELF_CORE
56013 config PCSPKR_PLATFORM
56014 bool "Enable PC-Speaker support" if EMBEDDED
56015 depends on ALPHA || X86 || MIPS || PPC_PREP || PPC_CHRP || PPC_PSERIES
56016 --- a/kernel/module.c
56017 +++ b/kernel/module.c
56018 @@ -2688,6 +2688,9 @@ static int m_show(struct seq_file *m, vo
56019 /* Used by oprofile and other similar tools. */
56020 seq_printf(m, " 0x%p", mod->module_core);
56022 +#ifdef ARCH_PROC_MODULES_EXTRA
56023 + ARCH_PROC_MODULES_EXTRA(m, mod);
56027 seq_printf(m, " %s", module_flags(mod, buf));
56028 @@ -2840,8 +2843,12 @@ void print_modules(void)
56029 printk("Modules linked in:");
56030 /* Most callers should already have preempt disabled, but make sure */
56032 - list_for_each_entry_rcu(mod, &modules, list)
56033 + list_for_each_entry_rcu(mod, &modules, list) {
56034 printk(" %s%s", mod->name, module_flags(mod, buf));
56035 +#ifdef ARCH_OOPS_MODULE_EXTRA
56036 + ARCH_OOPS_MODULE_EXTRA(mod);
56040 if (last_unloaded_module[0])
56041 printk(" [last unloaded: %s]", last_unloaded_module);
56042 --- a/kernel/sched_clock.c
56043 +++ b/kernel/sched_clock.c
56046 unsigned long long __attribute__((weak)) sched_clock(void)
56048 - return (unsigned long long)(jiffies - INITIAL_JIFFIES)
56049 - * (NSEC_PER_SEC / HZ);
56050 + return (get_jiffies_64() - INITIAL_JIFFIES) * (NSEC_PER_SEC / HZ);
56053 static __read_mostly int sched_clock_running;
56054 --- a/lib/Kconfig.debug
56055 +++ b/lib/Kconfig.debug
56056 @@ -621,7 +621,7 @@ config FRAME_POINTER
56057 bool "Compile the kernel with frame pointers"
56058 depends on DEBUG_KERNEL && \
56059 (CRIS || M68K || M68KNOMMU || FRV || UML || \
56060 - AVR32 || SUPERH || BLACKFIN || MN10300) || \
56061 + AVR32 || SUPERH || BLACKFIN || MN10300 || UBICOM32) || \
56062 ARCH_WANT_FRAME_POINTERS
56063 default y if (DEBUG_INFO && UML) || ARCH_WANT_FRAME_POINTERS
56067 @@ -38,3 +38,5 @@ obj-$(CONFIG_SMP) += allocpercpu.o
56069 obj-$(CONFIG_QUICKLIST) += quicklist.o
56070 obj-$(CONFIG_CGROUP_MEM_RES_CTLR) += memcontrol.o page_cgroup.o
56072 +CFLAGS_slab.o := $(PROFILING) -O2
56075 @@ -4100,6 +4100,68 @@ out:
56077 #ifdef CONFIG_SLABINFO
56081 + * get info on all the memory allocated by slab for this named cache
56083 +int kmem_cache_block_info(char *name, struct kmem_cache_size_info *data, int max_data)
56088 + struct kmem_cache *cachep;
56089 + struct kmem_list3 *l3;
56090 + struct slab *slabp;
56092 + /* Find the cache in the chain of caches. */
56093 + mutex_lock(&cache_chain_mutex);
56094 + list_for_each_entry(cachep, &cache_chain, next) {
56095 + if (strcmp(cachep->name, name) == 0) {
56100 + mutex_unlock(&cache_chain_mutex);
56104 + for_each_online_node(node) {
56105 + l3 = cachep->nodelists[node];
56108 + if (res >= max_data)
56111 + spin_lock_irq(&l3->list_lock);
56113 + list_for_each_entry(slabp, &l3->slabs_full, list) {
56114 + if (res >= max_data)
56116 + data[res].page = ((unsigned int)slabp->s_mem >> PAGE_SHIFT) & 0xffff;
56117 + data[res].order = cachep->gfporder;
56120 + list_for_each_entry(slabp, &l3->slabs_partial, list) {
56121 + if (res >= max_data)
56123 + data[res].page = ((unsigned int)slabp->s_mem >> PAGE_SHIFT) & 0xffff;
56124 + data[res].order = cachep->gfporder;
56127 + list_for_each_entry(slabp, &l3->slabs_free, list) {
56128 + if (res >= max_data)
56130 + data[res].page = ((unsigned int)slabp->s_mem >> PAGE_SHIFT) & 0xffff;
56131 + data[res].order = cachep->gfporder;
56135 + spin_unlock_irq(&l3->list_lock);
56141 static void print_slabinfo_header(struct seq_file *m)
56144 --- a/scripts/mod/file2alias.c
56145 +++ b/scripts/mod/file2alias.c
56146 @@ -774,6 +774,15 @@ void handle_moddevtable(struct module *m
56151 + * somehow our gcc is not generating st_size correctly and set 0 for some symbols.
56152 + * and 0 size will break do_table since it adjust size to (size - id_size)
56153 + * this is to make sure st_size fall in range.
56155 + if (sym->st_size == 0 || sym->st_size > info->sechdrs[sym->st_shndx].sh_size) {
56156 + sym->st_size = info->sechdrs[sym->st_shndx].sh_size;
56159 if (sym_is(symname, "__mod_pci_device_table"))
56160 do_table(symval, sym->st_size,
56161 sizeof(struct pci_device_id), "pci",
56162 --- a/sound/Kconfig
56163 +++ b/sound/Kconfig
56164 @@ -82,6 +82,8 @@ source "sound/parisc/Kconfig"
56166 source "sound/soc/Kconfig"
56168 +source "sound/ubicom32/Kconfig"
56172 menuconfig SOUND_PRIME
56173 --- a/sound/Makefile
56174 +++ b/sound/Makefile
56175 @@ -6,7 +6,7 @@ obj-$(CONFIG_SOUND_PRIME) += sound_firmw
56176 obj-$(CONFIG_SOUND_PRIME) += oss/
56177 obj-$(CONFIG_DMASOUND) += oss/
56178 obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ sh/ synth/ usb/ \
56179 - sparc/ spi/ parisc/ pcmcia/ mips/ soc/ atmel/
56180 + sparc/ spi/ parisc/ pcmcia/ mips/ soc/ atmel/ ubicom32/
56181 obj-$(CONFIG_SND_AOA) += aoa/
56183 # This one must be compilable even if sound is configured out
56185 +++ b/sound/ubicom32/Kconfig
56187 +# ALSA Ubicom32 drivers
56189 +menuconfig SND_UBI32
56190 + tristate "Ubicom32 sound devices"
56194 + Say Y here to include support for audio on the Ubicom32 platform.
56195 + To compile this driver as a module, say M here: the module will be
56196 + called snd_ubi32.
56200 +config SND_UBI32_AUDIO_GENERIC_CAPTURE
56201 + bool "Generic Capture Support"
56204 + Use this option to support ADCs which don't require special drivers.
56206 +config SND_UBI32_AUDIO_GENERIC
56207 + bool "Generic Playback Support"
56210 + Use this option to support DACs which don't require special drivers.
56212 +comment "I2C Based Codecs"
56214 +config SND_UBI32_AUDIO_CS4350
56215 + bool "Cirrus Logic CS4350 DAC"
56219 + Support for the Cirrus Logic CS4350 DAC.
56221 +config SND_UBI32_AUDIO_CS4384
56222 + bool "Cirrus Logic CS4384 DAC"
56226 + Support for the Cirrus Logic CS4384 DAC.
56230 +++ b/sound/ubicom32/Makefile
56233 +# sound/ubicom32/Makefile
56234 +# Makefile for ALSA
56236 +# (C) Copyright 2009, Ubicom, Inc.
56238 +# This file is part of the Ubicom32 Linux Kernel Port.
56240 +# The Ubicom32 Linux Kernel Port is free software: you can redistribute
56241 +# it and/or modify it under the terms of the GNU General Public License
56242 +# as published by the Free Software Foundation, either version 2 of the
56243 +# License, or (at your option) any later version.
56245 +# The Ubicom32 Linux Kernel Port is distributed in the hope that it
56246 +# will be useful, but WITHOUT ANY WARRANTY; without even the implied
56247 +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
56248 +# the GNU General Public License for more details.
56250 +# You should have received a copy of the GNU General Public License
56251 +# along with the Ubicom32 Linux Kernel Port. If not,
56252 +# see <http://www.gnu.org/licenses/>.
56254 +# Ubicom32 implementation derived from (with many thanks):
56260 +CFLAGS_ubi32.o += -O2
56261 +snd-ubi32-pcm-objs := ubi32-pcm.o
56262 +snd-ubi32-generic-objs := ubi32-generic.o
56263 +snd-ubi32-generic-capture-objs := ubi32-generic-capture.o
56264 +snd-ubi32-cs4350-objs := ubi32-cs4350.o
56265 +snd-ubi32-cs4384-objs := ubi32-cs4384.o
56267 +# Toplevel Module Dependency
56268 +obj-$(CONFIG_SND_UBI32) += snd-ubi32-pcm.o
56269 +obj-$(CONFIG_SND_UBI32_AUDIO_GENERIC) += snd-ubi32-generic.o
56270 +obj-$(CONFIG_SND_UBI32_AUDIO_GENERIC_CAPTURE) += snd-ubi32-generic-capture.o
56271 +obj-$(CONFIG_SND_UBI32_AUDIO_CS4350) += snd-ubi32-cs4350.o
56272 +obj-$(CONFIG_SND_UBI32_AUDIO_CS4384) += snd-ubi32-cs4384.o
56274 +++ b/sound/ubicom32/ubi32-cs4350.c
56277 + * sound/ubicom32/ubi32-cs4350.c
56278 + * Interface to ubicom32 virtual audio peripheral - using CS4350 DAC
56280 + * (C) Copyright 2009, Ubicom, Inc.
56282 + * This file is part of the Ubicom32 Linux Kernel Port.
56284 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
56285 + * it and/or modify it under the terms of the GNU General Public License
56286 + * as published by the Free Software Foundation, either version 2 of the
56287 + * License, or (at your option) any later version.
56289 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
56290 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
56291 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
56292 + * the GNU General Public License for more details.
56294 + * You should have received a copy of the GNU General Public License
56295 + * along with the Ubicom32 Linux Kernel Port. If not,
56296 + * see <http://www.gnu.org/licenses/>.
56299 +#include <linux/i2c.h>
56300 +#include <linux/module.h>
56301 +#include <linux/moduleparam.h>
56302 +#include <sound/core.h>
56303 +#include <sound/tlv.h>
56304 +#include <sound/control.h>
56305 +#include <sound/pcm.h>
56306 +#include <sound/initval.h>
56307 +#include "ubi32.h"
56309 +#define DRIVER_NAME "snd-ubi32-cs4350"
56312 + * Module properties
56314 +static const struct i2c_device_id snd_ubi32_cs4350_id[] = {
56318 +MODULE_DEVICE_TABLE(i2c, ubicom32audio_id);
56320 +static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */
56323 + * The dB scale for the Cirrus Logic cs4350. The output range is from
56324 + * -127.5 dB to 0 dB.
56326 +static const DECLARE_TLV_DB_SCALE(snd_ubi32_cs4350_db, -12750, 50, 0);
56328 +#define ubi32_cs4350_mute_info snd_ctl_boolean_stereo_info
56331 + * Private data for cs4350 chip
56333 +struct ubi32_cs4350_priv {
56335 + * The current volume settings
56337 + uint8_t volume[2];
56340 + * Bitmask of mutes MSB (unused, ..., unused, right_ch, left_ch) LSB
56345 + * Lock to protect this struct because callbacks are not atomic.
56351 + * The info for the cs4350. The volume currently has one channel,
56352 + * and 255 possible settings.
56354 +static int ubi32_cs4350_volume_info(struct snd_kcontrol *kcontrol,
56355 + struct snd_ctl_elem_info *uinfo)
56357 + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
56358 + uinfo->count = 2;
56359 + uinfo->value.integer.min = 0;
56360 + uinfo->value.integer.max = 255; // 8 bits in cirrus logic cs4350 volume register
56364 +static int ubi32_cs4350_volume_get(struct snd_kcontrol *kcontrol,
56365 + struct snd_ctl_elem_value *ucontrol)
56367 + struct ubi32_snd_priv *ubi32_priv = snd_kcontrol_chip(kcontrol);
56368 + struct ubi32_cs4350_priv *cs4350_priv;
56369 + unsigned long flags;
56371 + cs4350_priv = snd_ubi32_priv_get_drv(ubi32_priv);
56373 + spin_lock_irqsave(&cs4350_priv->lock, flags);
56375 + ucontrol->value.integer.value[0] = cs4350_priv->volume[0];
56376 + ucontrol->value.integer.value[1] = cs4350_priv->volume[1];
56378 + spin_unlock_irqrestore(&cs4350_priv->lock, flags);
56383 +static int ubi32_cs4350_volume_put(struct snd_kcontrol *kcontrol,
56384 + struct snd_ctl_elem_value *ucontrol)
56386 + struct ubi32_snd_priv *ubi32_priv = snd_kcontrol_chip(kcontrol);
56387 + struct i2c_client *client = (struct i2c_client *)ubi32_priv->client;
56388 + struct ubi32_cs4350_priv *cs4350_priv;
56389 + unsigned long flags;
56390 + int ret, changed;
56392 + uint8_t volume_reg_value_left, volume_reg_value_right;
56396 + cs4350_priv = snd_ubi32_priv_get_drv(ubi32_priv);
56397 + volume_reg_value_left = 255 - (ucontrol->value.integer.value[0] & 0xFF);
56398 + volume_reg_value_right = 255 - (ucontrol->value.integer.value[1] & 0xFF);
56400 +#if SND_UBI32_DEBUG
56401 + snd_printk(KERN_INFO "Setting volume: writing %d,%d to CS4350 volume registers\n", volume_reg_value_left, volume_reg_value_right);
56403 + spin_lock_irqsave(&cs4350_priv->lock, flags);
56405 + if (cs4350_priv->volume[0] != ucontrol->value.integer.value[0]) {
56406 + send[0] = 0x05; // left channel
56407 + send[1] = volume_reg_value_left;
56408 + ret = i2c_master_send(client, send, 2);
56410 + snd_printk(KERN_ERR "Failed to set channel A volume on CS4350\n");
56413 + cs4350_priv->volume[0] = ucontrol->value.integer.value[0];
56417 + if (cs4350_priv->volume[1] != ucontrol->value.integer.value[1]) {
56418 + send[0] = 0x06; // right channel
56419 + send[1] = volume_reg_value_right;
56420 + ret = i2c_master_send(client, send, 2);
56422 + snd_printk(KERN_ERR "Failed to set channel B volume on CS4350\n");
56425 + cs4350_priv->volume[1] = ucontrol->value.integer.value[1];
56429 + spin_unlock_irqrestore(&cs4350_priv->lock, flags);
56434 +static struct snd_kcontrol_new ubi32_cs4350_volume __devinitdata = {
56435 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
56436 + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
56437 + SNDRV_CTL_ELEM_ACCESS_TLV_READ,
56438 + .name = "PCM Playback Volume",
56439 + .info = ubi32_cs4350_volume_info,
56440 + .get = ubi32_cs4350_volume_get,
56441 + .put = ubi32_cs4350_volume_put,
56442 + .tlv.p = snd_ubi32_cs4350_db,
56445 +static int ubi32_cs4350_mute_get(struct snd_kcontrol *kcontrol,
56446 + struct snd_ctl_elem_value *ucontrol)
56448 + struct ubi32_snd_priv *ubi32_priv = snd_kcontrol_chip(kcontrol);
56449 + struct ubi32_cs4350_priv *cs4350_priv;
56450 + unsigned long flags;
56452 + cs4350_priv = snd_ubi32_priv_get_drv(ubi32_priv);
56454 + spin_lock_irqsave(&cs4350_priv->lock, flags);
56456 + ucontrol->value.integer.value[0] = cs4350_priv->mute & 1;
56457 + ucontrol->value.integer.value[1] = (cs4350_priv->mute & (1 << 1)) ? 1 : 0;
56459 + spin_unlock_irqrestore(&cs4350_priv->lock, flags);
56464 +static int ubi32_cs4350_mute_put(struct snd_kcontrol *kcontrol,
56465 + struct snd_ctl_elem_value *ucontrol)
56467 + struct ubi32_snd_priv *ubi32_priv = snd_kcontrol_chip(kcontrol);
56468 + struct i2c_client *client = (struct i2c_client *)ubi32_priv->client;
56469 + struct ubi32_cs4350_priv *cs4350_priv;
56470 + unsigned long flags;
56471 + int ret, changed;
56478 + cs4350_priv = snd_ubi32_priv_get_drv(ubi32_priv);
56480 + spin_lock_irqsave(&cs4350_priv->lock, flags);
56482 + if ((cs4350_priv->mute & 1) != ucontrol->value.integer.value[0]) {
56484 + ret = i2c_master_send(client, send, 1);
56486 + snd_printk(KERN_ERR "Failed to write to mute register: channel 0\n");
56490 + ret = i2c_master_recv(client, recv, 1);
56492 + snd_printk(KERN_ERR "Failed to read mute register: channel 0\n");
56498 + if (ucontrol->value.integer.value[0]) {
56499 + cs4350_priv->mute |= 1;
56500 + mute &= ~(1 << 4);
56501 +#if SND_UBI32_DEBUG
56502 + snd_printk(KERN_INFO "Unmuted channel A\n");
56505 + cs4350_priv->mute &= ~1;
56506 + mute |= (1 << 4);
56507 +#if SND_UBI32_DEBUG
56508 + snd_printk(KERN_INFO "Muted channel A\n");
56514 + ret = i2c_master_send(client, send, 2);
56516 + snd_printk(KERN_ERR "Failed to set channel A mute on CS4350\n");
56522 + if (((cs4350_priv->mute & 2) >> 1) != ucontrol->value.integer.value[1]) {
56524 + ret = i2c_master_send(client, send, 1);
56526 + snd_printk(KERN_ERR "Failed to write to mute register: channel 1\n");
56530 + ret = i2c_master_recv(client, recv, 1);
56532 + snd_printk(KERN_ERR "Failed to read mute register: channel 1\n");
56538 + if (ucontrol->value.integer.value[1]) {
56539 + cs4350_priv->mute |= (1 << 1);
56540 + mute &= ~(1 << 3);
56541 +#if SND_UBI32_DEBUG
56542 + snd_printk(KERN_INFO "Unmuted channel B\n");
56545 + cs4350_priv->mute &= ~(1 << 1);
56546 + mute |= (1 << 3);
56547 +#if SND_UBI32_DEBUG
56548 + snd_printk(KERN_INFO "Muted channel B\n");
56554 + ret = i2c_master_send(client, send, 2);
56556 + snd_printk(KERN_ERR "Failed to set channel A mute on CS4350\n");
56562 + spin_unlock_irqrestore(&cs4350_priv->lock, flags);
56567 +static struct snd_kcontrol_new ubi32_cs4350_mute __devinitdata = {
56568 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
56569 + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
56570 + .name = "PCM Playback Switch",
56571 + .info = ubi32_cs4350_mute_info,
56572 + .get = ubi32_cs4350_mute_get,
56573 + .put = ubi32_cs4350_mute_put,
56577 + * snd_ubi32_cs4350_free
56578 + * Card private data free function
56580 +void snd_ubi32_cs4350_free(struct snd_card *card)
56582 + struct ubi32_snd_priv *ubi32_priv;
56583 + struct ubi32_cs4350_priv *cs4350_priv;
56585 + ubi32_priv = card->private_data;
56586 + cs4350_priv = snd_ubi32_priv_get_drv(ubi32_priv);
56587 + if (cs4350_priv) {
56588 + kfree(cs4350_priv);
56593 + * snd_ubi32_cs4350_dac_init
56595 +static int snd_ubi32_cs4350_dac_init(struct i2c_client *client, const struct i2c_device_id *id)
56602 + * Initialize the CS4350 DAC over the I2C interface
56604 + snd_printk(KERN_INFO "Initializing CS4350 DAC\n");
56607 + * Register 0x01: device/revid
56610 + ret = i2c_master_send(client, send, 1);
56612 + snd_printk(KERN_ERR "Failed 1st attempt to write to CS4350 register 0x01\n");
56615 + ret = i2c_master_recv(client, recv, 1);
56617 + snd_printk(KERN_ERR "Failed initial read of CS4350 registers\n");
56620 + snd_printk(KERN_INFO "CS4350 DAC Device/Rev: %08x\n", recv[0]);
56623 + * Register 0x02: Mode control
56624 + * I2S DIF[2:0] = 001, no De-Emphasis, Auto speed mode
56628 + ret = i2c_master_send(client, send, 2);
56630 + snd_printk(KERN_ERR "Failed to set CS4350 to I2S mode\n");
56635 + * Register 0x05/0x06: Volume control
56636 + * Channel A volume set to 0 dB
56637 + * Channel B volume set to 0 dB
56641 + ret = i2c_master_send(client, send, 2);
56643 + snd_printk(KERN_ERR "Failed to set channel A volume on CS4350\n");
56649 + ret = i2c_master_send(client, send, 2);
56651 + snd_printk(KERN_ERR "Failed to set channel A volume on CS4350\n");
56656 + * Make sure the changes took place, this helps verify we are talking to
56657 + * the correct chip.
56660 + ret = i2c_master_send(client, send, 1);
56662 + snd_printk(KERN_ERR "Failed to initiate readback\n");
56666 + ret = i2c_master_recv(client, recv, 8);
56668 + snd_printk(KERN_ERR "Failed second read of CS4350 registers\n");
56672 + if ((recv[1] != 0x10) || (recv[4] != 0x00) || (recv[5] != 0x00)) {
56673 + snd_printk(KERN_ERR "Failed to initialize CS4350 DAC\n");
56677 + snd_printk(KERN_INFO "CS4350 DAC Initialized\n");
56685 + * snd_ubi32_cs4350_i2c_probe
56687 +static int snd_ubi32_cs4350_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
56689 + struct snd_card *card;
56690 + struct ubi32_snd_priv *ubi32_priv;
56691 + struct ubi32_cs4350_priv *cs4350_priv;
56693 + struct platform_device *pdev;
56695 + pdev = client->dev.platform_data;
56701 + * Initialize the CS4350 DAC
56703 + ret = snd_ubi32_cs4350_dac_init(client, id);
56706 + * Initialization failed. Propagate the error.
56712 + * Create a snd_card structure
56714 + card = snd_card_new(index, "Ubi32-CS4350", THIS_MODULE, sizeof(struct ubi32_snd_priv));
56715 + if (card == NULL) {
56719 + card->private_free = snd_ubi32_cs4350_free; /* Not sure if correct */
56720 + ubi32_priv = card->private_data;
56723 + * CS4350 DAC has a minimum sample rate of 30khz and an
56724 + * upper limit of 216khz for it's auto-detect.
56726 + ubi32_priv->min_sample_rate = 30000;
56727 + ubi32_priv->max_sample_rate = 216000;
56730 + * Initialize the snd_card's private data structure
56732 + ubi32_priv->card = card;
56733 + ubi32_priv->client = client;
56736 + * Create our private data structure
56738 + cs4350_priv = kzalloc(sizeof(struct ubi32_cs4350_priv), GFP_KERNEL);
56739 + if (!cs4350_priv) {
56740 + snd_card_free(card);
56743 + snd_ubi32_priv_set_drv(ubi32_priv, cs4350_priv);
56744 + spin_lock_init(&cs4350_priv->lock);
56747 + * Initial volume is set to max by probe function
56749 + cs4350_priv->volume[0] = 0xFF;
56750 + cs4350_priv->volume[1] = 0xFF;
56753 + * The CS4350 starts off unmuted (bit set = not muted)
56755 + cs4350_priv->mute = 3;
56758 + * Create the new PCM instance
56760 + err = snd_ubi32_pcm_probe(ubi32_priv, pdev);
56762 + snd_card_free(card);
56763 + return err; /* What is err? Need to include correct file */
56766 + strcpy(card->driver, "Ubi32-CS4350");
56767 + strcpy(card->shortname, "Ubi32-CS4350");
56768 + snprintf(card->longname, sizeof(card->longname),
56769 + "%s at sendirq=%d.%d recvirq=%d.%d regs=%p",
56770 + card->shortname, ubi32_priv->tx_irq, ubi32_priv->irq_idx,
56771 + ubi32_priv->rx_irq, ubi32_priv->irq_idx, ubi32_priv->adr);
56773 + snd_card_set_dev(card, &client->dev);
56776 + * Set up the mixer components
56778 + err = snd_ctl_add(card, snd_ctl_new1(&ubi32_cs4350_volume, ubi32_priv));
56780 + snd_printk(KERN_WARNING "Failed to add volume mixer control\n");
56782 + err = snd_ctl_add(card, snd_ctl_new1(&ubi32_cs4350_mute, ubi32_priv));
56784 + snd_printk(KERN_WARNING "Failed to add mute mixer control\n");
56788 + * Register the sound card
56790 + if ((err = snd_card_register(card)) != 0) {
56791 + snd_printk(KERN_WARNING "snd_card_register error\n");
56795 + * Store card for access from other methods
56797 + i2c_set_clientdata(client, card);
56803 + * snd_ubi32_cs4350_i2c_remove
56805 +static int __devexit snd_ubi32_cs4350_i2c_remove(struct i2c_client *client)
56807 + struct snd_card *card;
56808 + struct ubi32_snd_priv *ubi32_priv;
56810 + card = i2c_get_clientdata(client);
56812 + ubi32_priv = card->private_data;
56813 + snd_ubi32_pcm_remove(ubi32_priv);
56815 + snd_card_free(i2c_get_clientdata(client));
56816 + i2c_set_clientdata(client, NULL);
56822 + * I2C driver description
56824 +static struct i2c_driver snd_ubi32_cs4350_driver = {
56826 + .name = DRIVER_NAME,
56827 + .owner = THIS_MODULE,
56829 + .id_table = snd_ubi32_cs4350_id,
56830 + .probe = snd_ubi32_cs4350_i2c_probe,
56831 + .remove = __devexit_p(snd_ubi32_cs4350_i2c_remove),
56837 +static int __init snd_ubi32_cs4350_init(void)
56839 + return i2c_add_driver(&snd_ubi32_cs4350_driver);
56841 +module_init(snd_ubi32_cs4350_init);
56844 + * snd_ubi32_cs4350_exit
56846 +static void __exit snd_ubi32_cs4350_exit(void)
56848 + i2c_del_driver(&snd_ubi32_cs4350_driver);
56850 +module_exit(snd_ubi32_cs4350_exit);
56853 + * Module properties
56855 +MODULE_ALIAS("i2c:" DRIVER_NAME);
56856 +MODULE_AUTHOR("Patrick Tjin");
56857 +MODULE_DESCRIPTION("Driver for Ubicom32 audio devices CS4350");
56858 +MODULE_LICENSE("GPL");
56860 +++ b/sound/ubicom32/ubi32-cs4384.c
56863 + * sound/ubicom32/ubi32-cs4384.c
56864 + * Interface to ubicom32 virtual audio peripheral - using CS4384 DAC
56866 + * (C) Copyright 2009, Ubicom, Inc.
56868 + * This file is part of the Ubicom32 Linux Kernel Port.
56870 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
56871 + * it and/or modify it under the terms of the GNU General Public License
56872 + * as published by the Free Software Foundation, either version 2 of the
56873 + * License, or (at your option) any later version.
56875 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
56876 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
56877 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
56878 + * the GNU General Public License for more details.
56880 + * You should have received a copy of the GNU General Public License
56881 + * along with the Ubicom32 Linux Kernel Port. If not,
56882 + * see <http://www.gnu.org/licenses/>.
56885 +#include <linux/i2c.h>
56886 +#include <linux/module.h>
56887 +#include <linux/moduleparam.h>
56888 +#include <linux/delay.h>
56889 +#include <sound/core.h>
56890 +#include <sound/tlv.h>
56891 +#include <sound/control.h>
56892 +#include <sound/pcm.h>
56893 +#include <sound/initval.h>
56894 +#include <asm/ip5000.h>
56895 +#include <asm/gpio.h>
56896 +#include <asm/audio.h>
56897 +#include <asm/ubi32-cs4384.h>
56898 +#include "ubi32.h"
56900 +#define DRIVER_NAME "snd-ubi32-cs4384"
56903 + * Module properties
56905 +static const struct i2c_device_id snd_ubi32_cs4384_id[] = {
56909 +MODULE_DEVICE_TABLE(i2c, ubicom32audio_id);
56911 +static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */
56914 + * Mixer properties
56918 + * Be careful of changing the order of these IDs, they
56919 + * are used to index the volume array.
56921 + SND_UBI32_CS4384_FRONT_ID,
56922 + SND_UBI32_CS4384_SURROUND_ID,
56923 + SND_UBI32_CS4384_CENTER_ID,
56924 + SND_UBI32_CS4384_LFE_ID,
56925 + SND_UBI32_CS4384_REAR_ID,
56928 + * This should be the last ID
56930 + SND_UBI32_CS4384_LAST_ID,
56932 +static const u8_t snd_ubi32_cs4384_ch_ofs[] = {0, 2, 4, 5, 6};
56934 +static const DECLARE_TLV_DB_SCALE(snd_ubi32_cs4384_db, -12750, 50, 0);
56936 +#define snd_ubi32_cs4384_info_mute snd_ctl_boolean_stereo_info
56937 +#define snd_ubi32_cs4384_info_mute_mono snd_ctl_boolean_mono_info
56942 +static int snd_ubi32_cs4384_info_volume(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo);
56943 +static int snd_ubi32_cs4384_get_volume(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
56944 +static int snd_ubi32_cs4384_put_volume(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
56945 +static int snd_ubi32_cs4384_get_mute(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
56946 +static int snd_ubi32_cs4384_put_mute(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
56949 + * Make sure to update these if the structure below is changed
56951 +#define SND_UBI32_MUTE_CTL_START 5
56952 +#define SND_UBI32_MUTE_CTL_END 9
56953 +static struct snd_kcontrol_new snd_ubi32_cs4384_controls[] __devinitdata = {
56955 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
56956 + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
56957 + SNDRV_CTL_ELEM_ACCESS_TLV_READ,
56958 + .name = "Front Playback Volume",
56959 + .info = snd_ubi32_cs4384_info_volume,
56960 + .get = snd_ubi32_cs4384_get_volume,
56961 + .put = snd_ubi32_cs4384_put_volume,
56962 + .private_value = SND_UBI32_CS4384_FRONT_ID,
56964 + .p = snd_ubi32_cs4384_db,
56968 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
56969 + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
56970 + SNDRV_CTL_ELEM_ACCESS_TLV_READ,
56971 + .name = "Surround Playback Volume",
56972 + .info = snd_ubi32_cs4384_info_volume,
56973 + .get = snd_ubi32_cs4384_get_volume,
56974 + .put = snd_ubi32_cs4384_put_volume,
56975 + .private_value = SND_UBI32_CS4384_SURROUND_ID,
56977 + .p = snd_ubi32_cs4384_db,
56981 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
56982 + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
56983 + SNDRV_CTL_ELEM_ACCESS_TLV_READ,
56984 + .name = "Center Playback Volume",
56985 + .info = snd_ubi32_cs4384_info_volume,
56986 + .get = snd_ubi32_cs4384_get_volume,
56987 + .put = snd_ubi32_cs4384_put_volume,
56988 + .private_value = SND_UBI32_CS4384_CENTER_ID,
56990 + .p = snd_ubi32_cs4384_db,
56994 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
56995 + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
56996 + SNDRV_CTL_ELEM_ACCESS_TLV_READ,
56997 + .name = "LFE Playback Volume",
56998 + .info = snd_ubi32_cs4384_info_volume,
56999 + .get = snd_ubi32_cs4384_get_volume,
57000 + .put = snd_ubi32_cs4384_put_volume,
57001 + .private_value = SND_UBI32_CS4384_LFE_ID,
57003 + .p = snd_ubi32_cs4384_db,
57007 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
57008 + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
57009 + SNDRV_CTL_ELEM_ACCESS_TLV_READ,
57010 + .name = "Rear Playback Volume",
57011 + .info = snd_ubi32_cs4384_info_volume,
57012 + .get = snd_ubi32_cs4384_get_volume,
57013 + .put = snd_ubi32_cs4384_put_volume,
57014 + .private_value = SND_UBI32_CS4384_REAR_ID,
57016 + .p = snd_ubi32_cs4384_db,
57020 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
57021 + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
57022 + SNDRV_CTL_ELEM_ACCESS_TLV_READ,
57023 + .name = "Front Playback Switch",
57024 + .info = snd_ubi32_cs4384_info_mute,
57025 + .get = snd_ubi32_cs4384_get_mute,
57026 + .put = snd_ubi32_cs4384_put_mute,
57027 + .private_value = SND_UBI32_CS4384_FRONT_ID,
57030 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
57031 + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
57032 + SNDRV_CTL_ELEM_ACCESS_TLV_READ,
57033 + .name = "Surround Playback Switch",
57034 + .info = snd_ubi32_cs4384_info_mute,
57035 + .get = snd_ubi32_cs4384_get_mute,
57036 + .put = snd_ubi32_cs4384_put_mute,
57037 + .private_value = SND_UBI32_CS4384_SURROUND_ID,
57040 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
57041 + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
57042 + SNDRV_CTL_ELEM_ACCESS_TLV_READ,
57043 + .name = "Center Playback Switch",
57044 + .info = snd_ubi32_cs4384_info_mute_mono,
57045 + .get = snd_ubi32_cs4384_get_mute,
57046 + .put = snd_ubi32_cs4384_put_mute,
57047 + .private_value = SND_UBI32_CS4384_CENTER_ID,
57050 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
57051 + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
57052 + SNDRV_CTL_ELEM_ACCESS_TLV_READ,
57053 + .name = "LFE Playback Switch",
57054 + .info = snd_ubi32_cs4384_info_mute_mono,
57055 + .get = snd_ubi32_cs4384_get_mute,
57056 + .put = snd_ubi32_cs4384_put_mute,
57057 + .private_value = SND_UBI32_CS4384_LFE_ID,
57060 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
57061 + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
57062 + SNDRV_CTL_ELEM_ACCESS_TLV_READ,
57063 + .name = "Rear Playback Switch",
57064 + .info = snd_ubi32_cs4384_info_mute,
57065 + .get = snd_ubi32_cs4384_get_mute,
57066 + .put = snd_ubi32_cs4384_put_mute,
57067 + .private_value = SND_UBI32_CS4384_REAR_ID,
57072 + * Our private data
57074 +struct snd_ubi32_cs4384_priv {
57076 + * Array of current volumes
57077 + * (L, R, SL, SR, C, LFE, RL, RR)
57079 + uint8_t volume[8];
57082 + * Bitmask of mutes
57083 + * MSB (RR, RL, LFE, C, SR, SL, R, L) LSB
57088 + * Array of controls
57090 + struct snd_kcontrol *kctls[ARRAY_SIZE(snd_ubi32_cs4384_controls)];
57093 + * Lock to protect our card
57099 + * snd_ubi32_cs4384_info_volume
57101 +static int snd_ubi32_cs4384_info_volume(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
57103 + unsigned int id = (unsigned int)kcontrol->private_value;
57105 + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
57106 + uinfo->count = 1;
57107 + if ((id != SND_UBI32_CS4384_LFE_ID) &&
57108 + (id != SND_UBI32_CS4384_CENTER_ID)) {
57109 + uinfo->count = 2;
57111 + uinfo->value.integer.min = 0;
57112 + uinfo->value.integer.max = 255;
57117 + * snd_ubi32_cs4384_get_volume
57119 +static int snd_ubi32_cs4384_get_volume(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
57121 + struct ubi32_snd_priv *priv = snd_kcontrol_chip(kcontrol);
57122 + struct snd_ubi32_cs4384_priv *cs4384_priv;
57123 + unsigned int id = (unsigned int)kcontrol->private_value;
57124 + int ch = snd_ubi32_cs4384_ch_ofs[id];
57125 + unsigned long flags;
57127 + if (id >= SND_UBI32_CS4384_LAST_ID) {
57131 + cs4384_priv = snd_ubi32_priv_get_drv(priv);
57133 + spin_lock_irqsave(&cs4384_priv->lock, flags);
57135 + ucontrol->value.integer.value[0] = cs4384_priv->volume[ch];
57136 + if ((id != SND_UBI32_CS4384_LFE_ID) &&
57137 + (id != SND_UBI32_CS4384_CENTER_ID)) {
57139 + ucontrol->value.integer.value[1] = cs4384_priv->volume[ch];
57142 + spin_unlock_irqrestore(&cs4384_priv->lock, flags);
57148 + * snd_ubi32_cs4384_put_volume
57150 +static int snd_ubi32_cs4384_put_volume(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
57152 + struct ubi32_snd_priv *priv = snd_kcontrol_chip(kcontrol);
57153 + struct i2c_client *client = (struct i2c_client *)priv->client;
57154 + struct snd_ubi32_cs4384_priv *cs4384_priv;
57155 + unsigned int id = (unsigned int)kcontrol->private_value;
57156 + int ch = snd_ubi32_cs4384_ch_ofs[id];
57157 + unsigned long flags;
57158 + unsigned char send[3];
57160 + int ret = -EINVAL;
57162 + if (id >= SND_UBI32_CS4384_LAST_ID) {
57166 + cs4384_priv = snd_ubi32_priv_get_drv(priv);
57168 + spin_lock_irqsave(&cs4384_priv->lock, flags);
57172 + case SND_UBI32_CS4384_REAR_ID:
57179 + case SND_UBI32_CS4384_SURROUND_ID:
57186 + case SND_UBI32_CS4384_FRONT_ID:
57189 + send[1] = 255 - (ucontrol->value.integer.value[0] & 0xFF);
57190 + send[2] = 255 - (ucontrol->value.integer.value[1] & 0xFF);
57191 + cs4384_priv->volume[ch++] = send[1];
57192 + cs4384_priv->volume[ch] = send[2];
57195 + case SND_UBI32_CS4384_LFE_ID:
57202 + case SND_UBI32_CS4384_CENTER_ID:
57205 + send[1] = 255 - (ucontrol->value.integer.value[0] & 0xFF);
57206 + cs4384_priv->volume[ch] = send[1];
57210 + spin_unlock_irqrestore(&cs4384_priv->lock, flags);
57216 + * Send the volume to the chip
57219 + ret = i2c_master_send(client, send, nch);
57220 + if (ret != nch) {
57221 + snd_printk(KERN_ERR "Failed to set volume on CS4384\n");
57225 + spin_unlock_irqrestore(&cs4384_priv->lock, flags);
57231 + * snd_ubi32_cs4384_get_mute
57233 +static int snd_ubi32_cs4384_get_mute(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
57235 + struct ubi32_snd_priv *priv = snd_kcontrol_chip(kcontrol);
57236 + struct snd_ubi32_cs4384_priv *cs4384_priv;
57237 + unsigned int id = (unsigned int)kcontrol->private_value;
57238 + int ch = snd_ubi32_cs4384_ch_ofs[id];
57239 + unsigned long flags;
57241 + if (id >= SND_UBI32_CS4384_LAST_ID) {
57245 + cs4384_priv = snd_ubi32_priv_get_drv(priv);
57247 + spin_lock_irqsave(&cs4384_priv->lock, flags);
57249 + ucontrol->value.integer.value[0] = !(cs4384_priv->mute & (1 << ch));
57251 + if ((id != SND_UBI32_CS4384_LFE_ID) &&
57252 + (id != SND_UBI32_CS4384_CENTER_ID)) {
57254 + ucontrol->value.integer.value[1] = !(cs4384_priv->mute & (1 << ch));
57257 + spin_unlock_irqrestore(&cs4384_priv->lock, flags);
57263 + * snd_ubi32_cs4384_put_mute
57265 +static int snd_ubi32_cs4384_put_mute(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
57267 + struct ubi32_snd_priv *priv = snd_kcontrol_chip(kcontrol);
57268 + struct i2c_client *client = (struct i2c_client *)priv->client;
57269 + struct snd_ubi32_cs4384_priv *cs4384_priv;
57270 + unsigned int id = (unsigned int)kcontrol->private_value;
57271 + int ch = snd_ubi32_cs4384_ch_ofs[id];
57272 + unsigned long flags;
57273 + unsigned char send[2];
57274 + int ret = -EINVAL;
57276 + if (id >= SND_UBI32_CS4384_LAST_ID) {
57280 + cs4384_priv = snd_ubi32_priv_get_drv(priv);
57282 + spin_lock_irqsave(&cs4384_priv->lock, flags);
57284 + if (ucontrol->value.integer.value[0]) {
57285 + cs4384_priv->mute &= ~(1 << ch);
57287 + cs4384_priv->mute |= (1 << ch);
57290 + if ((id != SND_UBI32_CS4384_LFE_ID) && (id != SND_UBI32_CS4384_CENTER_ID)) {
57292 + if (ucontrol->value.integer.value[1]) {
57293 + cs4384_priv->mute &= ~(1 << ch);
57295 + cs4384_priv->mute |= (1 << ch);
57300 + * Update the chip's mute reigster
57303 + send[1] = cs4384_priv->mute;
57304 + ret = i2c_master_send(client, send, 2);
57306 + snd_printk(KERN_ERR "Failed to set mute on CS4384\n");
57309 + spin_unlock_irqrestore(&cs4384_priv->lock, flags);
57315 + * snd_ubi32_cs4384_mixer
57316 + * Setup the mixer controls
57318 +static int __devinit snd_ubi32_cs4384_mixer(struct ubi32_snd_priv *priv)
57320 + struct snd_card *card = priv->card;
57321 + struct snd_ubi32_cs4384_priv *cs4384_priv;
57324 + cs4384_priv = snd_ubi32_priv_get_drv(priv);
57325 + for (i = 0; i < ARRAY_SIZE(snd_ubi32_cs4384_controls); i++) {
57328 + cs4384_priv->kctls[i] = snd_ctl_new1(&snd_ubi32_cs4384_controls[i], priv);
57329 + err = snd_ctl_add(card, cs4384_priv->kctls[i]);
57331 + snd_printk(KERN_WARNING "Failed to add control %d\n", i);
57339 + * snd_ubi32_cs4384_free
57340 + * Card private data free function
57342 +void snd_ubi32_cs4384_free(struct snd_card *card)
57344 + struct snd_ubi32_cs4384_priv *cs4384_priv;
57345 + struct ubi32_snd_priv *ubi32_priv;
57347 + ubi32_priv = card->private_data;
57348 + cs4384_priv = snd_ubi32_priv_get_drv(ubi32_priv);
57349 + if (cs4384_priv) {
57350 + kfree(cs4384_priv);
57355 + * snd_ubi32_cs4384_setup_mclk
57357 +static int snd_ubi32_cs4384_setup_mclk(struct ubi32_cs4384_platform_data *pdata)
57359 + struct ubicom32_io_port *ioa = (struct ubicom32_io_port *)RA;
57360 + struct ubicom32_io_port *ioc = (struct ubicom32_io_port *)RC;
57361 + struct ubicom32_io_port *iod = (struct ubicom32_io_port *)RD;
57362 + struct ubicom32_io_port *ioe = (struct ubicom32_io_port *)RE;
57363 + struct ubicom32_io_port *ioh = (struct ubicom32_io_port *)RH;
57364 + unsigned int ctl0;
57365 + unsigned int ctlx;
57366 + unsigned int div;
57368 + div = pdata->mclk_entries[0].div;
57370 + ctl0 = (1 << 13);
57371 + ctlx = ((div - 1) << 16) | (div / 2);
57373 + switch (pdata->mclk_src) {
57374 + case UBI32_CS4384_MCLK_PWM_0:
57375 + ioc->function |= 2;
57376 + ioc->ctl0 |= ctl0;
57377 + ioc->ctl1 = ctlx;
57378 + if (!ioa->function) {
57379 + ioa->function = 3;
57383 + case UBI32_CS4384_MCLK_PWM_1:
57384 + ioc->function |= 2;
57385 + ioc->ctl0 |= ctl0 << 16;
57386 + ioc->ctl2 = ctlx;
57387 + if (!ioe->function) {
57388 + ioe->function = 3;
57392 + case UBI32_CS4384_MCLK_PWM_2:
57393 + ioh->ctl0 |= ctl0;
57394 + ioh->ctl1 = ctlx;
57395 + if (!iod->function) {
57396 + iod->function = 3;
57400 + case UBI32_CS4384_MCLK_CLKDIV_1:
57401 + ioa->gpio_mask &= (1 << 7);
57402 + ioa->ctl1 &= ~(0x7F << 14);
57403 + ioa->ctl1 |= ((div - 1) << 14);
57406 + case UBI32_CS4384_MCLK_OTHER:
57414 + * snd_ubi32_cs4384_set_rate
57416 +static int snd_ubi32_cs4384_set_rate(struct ubi32_snd_priv *priv, int rate)
57418 + struct ubi32_cs4384_platform_data *cpd = priv->pdata->priv_data;
57419 + struct ubicom32_io_port *ioa = (struct ubicom32_io_port *)RA;
57420 + struct ubicom32_io_port *ioc = (struct ubicom32_io_port *)RC;
57421 + struct ubicom32_io_port *ioh = (struct ubicom32_io_port *)RH;
57422 + unsigned int ctl;
57423 + unsigned int div = 0;
57424 + const u16_t mult[] = {64, 96, 128, 192, 256, 384, 512, 768, 1024};
57429 + for (i = 0; i < sizeof(mult) / sizeof(u16_t); i++) {
57430 + for (j = 0; j < cpd->n_mclk; j++) {
57431 + if (((unsigned int)rate * (unsigned int)mult[i]) ==
57432 + cpd->mclk_entries[j].rate) {
57433 + div = cpd->mclk_entries[j].div;
57439 + ctl = ((div - 1) << 16) | (div / 2);
57441 + switch (cpd->mclk_src) {
57442 + case UBI32_CS4384_MCLK_PWM_0:
57446 + case UBI32_CS4384_MCLK_PWM_1:
57450 + case UBI32_CS4384_MCLK_PWM_2:
57454 + case UBI32_CS4384_MCLK_CLKDIV_1:
57455 + ioa->ctl1 &= ~(0x7F << 14);
57456 + ioa->ctl1 |= ((div - 1) << 14);
57459 + case UBI32_CS4384_MCLK_OTHER:
57467 + * snd_ubi32_cs4384_set_channels
57468 + * Mute unused channels
57470 +static int snd_ubi32_cs4384_set_channels(struct ubi32_snd_priv *priv, int channels)
57472 + struct i2c_client *client = (struct i2c_client *)priv->client;
57473 + struct snd_ubi32_cs4384_priv *cs4384_priv;
57474 + unsigned char send[2];
57477 + unsigned long flags;
57480 + * Only support 0, 2, 4, 6, 8 channels
57482 + if ((channels > 8) || (channels & 1)) {
57486 + cs4384_priv = snd_ubi32_priv_get_drv(priv);
57487 + spin_lock_irqsave(&cs4384_priv->lock, flags);
57490 + * Address 09h, Mute control
57493 + send[1] = (unsigned char)(0xFF << channels);
57495 + ret = i2c_master_send(client, send, 2);
57497 + spin_unlock_irqrestore(&cs4384_priv->lock, flags);
57500 + * Notify the system that we changed the mutes
57502 + cs4384_priv->mute = (unsigned char)(0xFF << channels);
57504 + for (i = SND_UBI32_MUTE_CTL_START; i < SND_UBI32_MUTE_CTL_END; i++) {
57505 + snd_ctl_notify(priv->card, SNDRV_CTL_EVENT_MASK_VALUE,
57506 + &cs4384_priv->kctls[i]->id);
57517 + * snd_ubi32_cs4384_dac_init
57519 +static int snd_ubi32_cs4384_dac_init(struct i2c_client *client, const struct i2c_device_id *id)
57522 + unsigned char send[2];
57523 + unsigned char recv[2];
57526 + * Initialize the CS4384 DAC over the I2C interface
57528 + snd_printk(KERN_INFO "Initializing CS4384 DAC\n");
57531 + * Register 0x01: device/revid
57534 + ret = i2c_master_send(client, send, 1);
57536 + snd_printk(KERN_ERR "Failed 1st attempt to write to CS4384 register 0x01\n");
57539 + ret = i2c_master_recv(client, recv, 1);
57541 + snd_printk(KERN_ERR "Failed initial read of CS4384 registers\n");
57544 + snd_printk(KERN_INFO "CS4384 DAC Device/Rev: %08x\n", recv[0]);
57547 + * Register 0x02: Mode Control 1
57548 + * Control Port Enable, PCM, All DACs enabled, Power Down
57552 + ret = i2c_master_send(client, send, 2);
57554 + snd_printk(KERN_ERR "Failed to set CPEN CS4384\n");
57559 + * Register 0x08: Ramp and Mute
57560 + * RMP_UP, RMP_DN, PAMUTE, DAMUTE
57564 + ret = i2c_master_send(client, send, 2);
57566 + snd_printk(KERN_ERR "Failed to set CPEN CS4384\n");
57571 + * Register 0x03: PCM Control
57572 + * I2S DIF[3:0] = 0001, no De-Emphasis, Auto speed mode
57576 + ret = i2c_master_send(client, send, 2);
57578 + snd_printk(KERN_ERR "Failed to set CS4384 to I2S mode\n");
57583 + * Register 0x0B/0x0C: Volume control A1/B1
57584 + * Register 0x0E/0x0F: Volume control A2/B2
57585 + * Register 0x11/0x12: Volume control A3/B3
57586 + * Register 0x14/0x15: Volume control A4/B4
57588 + send[0] = 0x80 | 0x0B;
57591 + ret = i2c_master_send(client, send, 3);
57593 + snd_printk(KERN_ERR "Failed to set ch1 volume on CS4384\n");
57597 + send[0] = 0x80 | 0x0E;
57600 + ret = i2c_master_send(client, send, 3);
57602 + snd_printk(KERN_ERR "Failed to set ch2 volume on CS4384\n");
57606 + send[0] = 0x80 | 0x11;
57609 + ret = i2c_master_send(client, send, 3);
57611 + snd_printk(KERN_ERR "Failed to set ch3 volume on CS4384\n");
57615 + send[0] = 0x80 | 0x14;
57618 + ret = i2c_master_send(client, send, 3);
57620 + snd_printk(KERN_ERR "Failed to set ch4 volume on CS4384\n");
57625 + * Register 09h: Mute control
57626 + * Mute all (we will unmute channels as needed)
57630 + ret = i2c_master_send(client, send, 2);
57632 + snd_printk(KERN_ERR "Failed to power up CS4384\n");
57637 + * Register 0x02: Mode Control 1
57638 + * Control Port Enable, PCM, All DACs enabled, Power Up
57642 + ret = i2c_master_send(client, send, 2);
57644 + snd_printk(KERN_ERR "Failed to power up CS4384\n");
57649 + * Make sure the changes took place, this helps verify we are talking to
57650 + * the correct chip.
57652 + send[0] = 0x80 | 0x03;
57653 + ret = i2c_master_send(client, send, 1);
57655 + snd_printk(KERN_ERR "Failed to initiate readback\n");
57659 + ret = i2c_master_recv(client, recv, 1);
57661 + snd_printk(KERN_ERR "Failed second read of CS4384 registers\n");
57665 + if (recv[0] != 0x13) {
57666 + snd_printk(KERN_ERR "Failed to initialize CS4384 DAC\n");
57670 + snd_printk(KERN_INFO "CS4384 DAC Initialized\n");
57678 + * snd_ubi32_cs4384_i2c_probe
57680 +static int snd_ubi32_cs4384_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
57682 + struct snd_card *card;
57683 + struct ubi32_snd_priv *ubi32_priv;
57685 + struct platform_device *pdev;
57686 + struct ubi32_cs4384_platform_data *pdata;
57687 + struct snd_ubi32_cs4384_priv *cs4384_priv;
57690 + * pdev is audio device
57692 + pdev = client->dev.platform_data;
57698 + * pdev->dev.platform_data is ubi32-pcm platform_data
57700 + pdata = audio_device_priv(pdev);
57706 + * Initialize the CS4384 DAC
57708 + ret = snd_ubi32_cs4384_dac_init(client, id);
57711 + * Initialization failed. Propagate the error.
57716 + if (snd_ubi32_cs4384_setup_mclk(pdata)) {
57721 + * Create a snd_card structure
57723 + card = snd_card_new(index, "Ubi32-CS4384", THIS_MODULE, sizeof(struct ubi32_snd_priv));
57724 + if (card == NULL) {
57728 + card->private_free = snd_ubi32_cs4384_free;
57729 + ubi32_priv = card->private_data;
57732 + * Initialize the snd_card's private data structure
57734 + ubi32_priv->card = card;
57735 + ubi32_priv->client = client;
57736 + ubi32_priv->set_channels = snd_ubi32_cs4384_set_channels;
57737 + ubi32_priv->set_rate = snd_ubi32_cs4384_set_rate;
57740 + * CS4384 DAC has a minimum sample rate of 4khz and an
57741 + * upper limit of 216khz for it's auto-detect.
57743 + ubi32_priv->min_sample_rate = 4000;
57744 + ubi32_priv->max_sample_rate = 216000;
57747 + * Create our private data (to manage volume, etc)
57749 + cs4384_priv = kzalloc(sizeof(struct snd_ubi32_cs4384_priv), GFP_KERNEL);
57750 + if (!cs4384_priv) {
57751 + snd_card_free(card);
57754 + snd_ubi32_priv_set_drv(ubi32_priv, cs4384_priv);
57755 + spin_lock_init(&cs4384_priv->lock);
57758 + * We start off all muted and max volume
57760 + cs4384_priv->mute = 0xFF;
57761 + memset(cs4384_priv->volume, 0xFF, 8);
57764 + * Create the new PCM instance
57766 + err = snd_ubi32_pcm_probe(ubi32_priv, pdev);
57768 + snd_card_free(card);
57769 + return err; /* What is err? Need to include correct file */
57772 + strcpy(card->driver, "Ubi32-CS4384");
57773 + strcpy(card->shortname, "Ubi32-CS4384");
57774 + snprintf(card->longname, sizeof(card->longname),
57775 + "%s at sendirq=%d.%d recvirq=%d.%d regs=%p",
57776 + card->shortname, ubi32_priv->tx_irq, ubi32_priv->irq_idx,
57777 + ubi32_priv->rx_irq, ubi32_priv->irq_idx, ubi32_priv->adr);
57779 + snd_card_set_dev(card, &client->dev);
57782 + * Set up the mixer
57784 + snd_ubi32_cs4384_mixer(ubi32_priv);
57787 + * Register the sound card
57789 + if ((err = snd_card_register(card)) != 0) {
57790 + snd_printk(KERN_INFO "snd_card_register error\n");
57794 + * Store card for access from other methods
57796 + i2c_set_clientdata(client, card);
57802 + * snd_ubi32_cs4384_i2c_remove
57804 +static int __devexit snd_ubi32_cs4384_i2c_remove(struct i2c_client *client)
57806 + struct snd_card *card;
57807 + struct ubi32_snd_priv *ubi32_priv;
57809 + card = i2c_get_clientdata(client);
57811 + ubi32_priv = card->private_data;
57812 + snd_ubi32_pcm_remove(ubi32_priv);
57814 + snd_card_free(i2c_get_clientdata(client));
57815 + i2c_set_clientdata(client, NULL);
57821 + * I2C driver description
57823 +static struct i2c_driver snd_ubi32_cs4384_driver = {
57825 + .name = DRIVER_NAME,
57826 + .owner = THIS_MODULE,
57828 + .id_table = snd_ubi32_cs4384_id,
57829 + .probe = snd_ubi32_cs4384_i2c_probe,
57830 + .remove = __devexit_p(snd_ubi32_cs4384_i2c_remove),
57836 +static int __init snd_ubi32_cs4384_init(void)
57838 + return i2c_add_driver(&snd_ubi32_cs4384_driver);
57840 +module_init(snd_ubi32_cs4384_init);
57843 + * snd_ubi32_cs4384_exit
57845 +static void __exit snd_ubi32_cs4384_exit(void)
57847 + i2c_del_driver(&snd_ubi32_cs4384_driver);
57849 +module_exit(snd_ubi32_cs4384_exit);
57852 + * Module properties
57854 +MODULE_ALIAS("i2c:" DRIVER_NAME);
57855 +MODULE_AUTHOR("Patrick Tjin");
57856 +MODULE_DESCRIPTION("Driver for Ubicom32 audio devices CS4384");
57857 +MODULE_LICENSE("GPL");
57859 +++ b/sound/ubicom32/ubi32-generic.c
57862 + * sound/ubicom32/ubi32-generic.c
57863 + * Interface to ubicom32 virtual audio peripheral
57865 + * (C) Copyright 2009, Ubicom, Inc.
57867 + * This file is part of the Ubicom32 Linux Kernel Port.
57869 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
57870 + * it and/or modify it under the terms of the GNU General Public License
57871 + * as published by the Free Software Foundation, either version 2 of the
57872 + * License, or (at your option) any later version.
57874 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
57875 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
57876 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
57877 + * the GNU General Public License for more details.
57879 + * You should have received a copy of the GNU General Public License
57880 + * along with the Ubicom32 Linux Kernel Port. If not,
57881 + * see <http://www.gnu.org/licenses/>.
57883 + * Ubicom32 implementation derived from (with many thanks):
57889 +#include <linux/platform_device.h>
57890 +#include <linux/module.h>
57891 +#include <linux/moduleparam.h>
57892 +#include <sound/core.h>
57893 +#include <sound/pcm.h>
57894 +#include <sound/initval.h>
57895 +#include "ubi32.h"
57897 +#define DRIVER_NAME "snd-ubi32-generic"
57900 + * Module properties
57902 +static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */
57905 + * Card private data free function
57907 +void snd_ubi32_generic_free(struct snd_card *card)
57910 + * Free all the fields in the snd_ubi32_priv struct
57912 + // Nothing to free at this time because ubi32_priv just maintains pointers
57916 + * Ubicom audio driver probe() method. Args change depending on whether we use
57917 + * platform_device or i2c_device.
57919 +static int snd_ubi32_generic_probe(struct platform_device *dev)
57921 + struct snd_card *card;
57922 + struct ubi32_snd_priv *ubi32_priv;
57926 + * Create a snd_card structure
57928 + card = snd_card_new(index, "Ubi32-Generic", THIS_MODULE, sizeof(struct ubi32_snd_priv));
57930 + if (card == NULL) {
57934 + card->private_free = snd_ubi32_generic_free; /* Not sure if correct */
57935 + ubi32_priv = card->private_data;
57938 + * Initialize the snd_card's private data structure
57940 + ubi32_priv->card = card;
57943 + * Create the new PCM instance
57945 + err = snd_ubi32_pcm_probe(ubi32_priv, dev);
57947 + snd_card_free(card);
57951 + strcpy(card->driver, "Ubi32-Generic");
57952 + strcpy(card->shortname, "Ubi32-Generic");
57953 + snprintf(card->longname, sizeof(card->longname),
57954 + "%s at sendirq=%d.%d recvirq=%d.%d regs=%p",
57955 + card->shortname, ubi32_priv->tx_irq, ubi32_priv->irq_idx,
57956 + ubi32_priv->rx_irq, ubi32_priv->irq_idx, ubi32_priv->adr);
57958 + snd_card_set_dev(card, &dev->dev);
57960 + /* Register the sound card */
57961 + if ((err = snd_card_register(card)) != 0) {
57962 + snd_printk(KERN_INFO "snd_card_register error\n");
57965 + /* Store card for access from other methods */
57966 + platform_set_drvdata(dev, card);
57972 + * Ubicom audio driver remove() method
57974 +static int __devexit snd_ubi32_generic_remove(struct platform_device *dev)
57976 + struct snd_card *card;
57977 + struct ubi32_snd_priv *ubi32_priv;
57979 + card = platform_get_drvdata(dev);
57980 + ubi32_priv = card->private_data;
57981 + snd_ubi32_pcm_remove(ubi32_priv);
57983 + snd_card_free(platform_get_drvdata(dev));
57984 + platform_set_drvdata(dev, NULL);
57989 + * Platform driver definition
57991 +static struct platform_driver snd_ubi32_generic_driver = {
57993 + .name = DRIVER_NAME,
57994 + .owner = THIS_MODULE,
57996 + .probe = snd_ubi32_generic_probe,
57997 + .remove = __devexit_p(snd_ubi32_generic_remove),
58001 + * snd_ubi32_generic_init
58003 +static int __init snd_ubi32_generic_init(void)
58005 + return platform_driver_register(&snd_ubi32_generic_driver);
58007 +module_init(snd_ubi32_generic_init);
58010 + * snd_ubi32_generic_exit
58012 +static void __exit snd_ubi32_generic_exit(void)
58014 + platform_driver_unregister(&snd_ubi32_generic_driver);
58016 +module_exit(snd_ubi32_generic_exit);
58019 + * Module properties
58021 +//#if defined(CONFIG_SND_UBI32_AUDIO_I2C)
58022 +//MODULE_ALIAS("i2c:snd-ubi32");
58024 +MODULE_AUTHOR("Aaron Jow, Patrick Tjin");
58025 +MODULE_DESCRIPTION("Driver for Ubicom32 audio devices");
58026 +MODULE_LICENSE("GPL");
58028 +++ b/sound/ubicom32/ubi32-generic-capture.c
58031 + * sound/ubicom32/ubi32-generic-capture.c
58032 + * Interface to ubicom32 virtual audio peripheral
58034 + * (C) Copyright 2009, Ubicom, Inc.
58036 + * This file is part of the Ubicom32 Linux Kernel Port.
58038 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
58039 + * it and/or modify it under the terms of the GNU General Public License
58040 + * as published by the Free Software Foundation, either version 2 of the
58041 + * License, or (at your option) any later version.
58043 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
58044 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
58045 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
58046 + * the GNU General Public License for more details.
58048 + * You should have received a copy of the GNU General Public License
58049 + * along with the Ubicom32 Linux Kernel Port. If not,
58050 + * see <http://www.gnu.org/licenses/>.
58052 + * Ubicom32 implementation derived from (with many thanks):
58058 +#include <linux/platform_device.h>
58059 +#include <linux/module.h>
58060 +#include <linux/moduleparam.h>
58061 +#include <sound/core.h>
58062 +#include <sound/pcm.h>
58063 +#include <sound/initval.h>
58064 +#include "ubi32.h"
58066 +#define DRIVER_NAME "snd-ubi32-generic-capture"
58069 + * Module properties
58071 +static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */
58074 + * Card private data free function
58076 +void snd_ubi32_generic_capture_free(struct snd_card *card)
58079 + * Free all the fields in the snd_ubi32_priv struct
58081 + // Nothing to free at this time because ubi32_priv just maintains pointers
58085 + * Ubicom audio driver probe() method. Args change depending on whether we use
58086 + * platform_device or i2c_device.
58088 +static int snd_ubi32_generic_capture_probe(struct platform_device *dev)
58090 + struct snd_card *card;
58091 + struct ubi32_snd_priv *ubi32_priv;
58095 + * Create a snd_card structure
58097 + card = snd_card_new(index, "Ubi32-Generic-C", THIS_MODULE, sizeof(struct ubi32_snd_priv));
58099 + if (card == NULL) {
58103 + card->private_free = snd_ubi32_generic_capture_free; /* Not sure if correct */
58104 + ubi32_priv = card->private_data;
58107 + * Initialize the snd_card's private data structure
58109 + ubi32_priv->card = card;
58110 + ubi32_priv->is_capture = 1;
58113 + * Create the new PCM instance
58115 + err = snd_ubi32_pcm_probe(ubi32_priv, dev);
58117 + snd_card_free(card);
58121 + strcpy(card->driver, "Ubi32-Generic-C");
58122 + strcpy(card->shortname, "Ubi32-Generic-C");
58123 + snprintf(card->longname, sizeof(card->longname),
58124 + "%s at sendirq=%d.%d recvirq=%d.%d regs=%p",
58125 + card->shortname, ubi32_priv->tx_irq, ubi32_priv->irq_idx,
58126 + ubi32_priv->rx_irq, ubi32_priv->irq_idx, ubi32_priv->adr);
58128 + snd_card_set_dev(card, &dev->dev);
58130 + /* Register the sound card */
58131 + if ((err = snd_card_register(card)) != 0) {
58132 + snd_printk(KERN_INFO "snd_card_register error\n");
58135 + /* Store card for access from other methods */
58136 + platform_set_drvdata(dev, card);
58142 + * Ubicom audio driver remove() method
58144 +static int __devexit snd_ubi32_generic_capture_remove(struct platform_device *dev)
58146 + struct snd_card *card;
58147 + struct ubi32_snd_priv *ubi32_priv;
58149 + card = platform_get_drvdata(dev);
58150 + ubi32_priv = card->private_data;
58151 + snd_ubi32_pcm_remove(ubi32_priv);
58153 + snd_card_free(platform_get_drvdata(dev));
58154 + platform_set_drvdata(dev, NULL);
58159 + * Platform driver definition
58161 +static struct platform_driver snd_ubi32_generic_capture_driver = {
58163 + .name = DRIVER_NAME,
58164 + .owner = THIS_MODULE,
58166 + .probe = snd_ubi32_generic_capture_probe,
58167 + .remove = __devexit_p(snd_ubi32_generic_capture_remove),
58171 + * snd_ubi32_generic_capture_init
58173 +static int __init snd_ubi32_generic_capture_init(void)
58175 + return platform_driver_register(&snd_ubi32_generic_capture_driver);
58177 +module_init(snd_ubi32_generic_capture_init);
58180 + * snd_ubi32_generic_capture_exit
58182 +static void __exit snd_ubi32_generic_capture_exit(void)
58184 + platform_driver_unregister(&snd_ubi32_generic_capture_driver);
58186 +module_exit(snd_ubi32_generic_capture_exit);
58189 + * Module properties
58191 +//#if defined(CONFIG_SND_UBI32_AUDIO_I2C)
58192 +//MODULE_ALIAS("i2c:snd-ubi32");
58194 +MODULE_AUTHOR("Patrick Tjin");
58195 +MODULE_DESCRIPTION("Driver for Ubicom32 audio devices");
58196 +MODULE_LICENSE("GPL");
58198 +++ b/sound/ubicom32/ubi32.h
58201 + * sound/ubicom32/ubi32.h
58202 + * Common header file for all ubi32- sound drivers
58204 + * (C) Copyright 2009, Ubicom, Inc.
58206 + * This file is part of the Ubicom32 Linux Kernel Port.
58208 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
58209 + * it and/or modify it under the terms of the GNU General Public License
58210 + * as published by the Free Software Foundation, either version 2 of the
58211 + * License, or (at your option) any later version.
58213 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
58214 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
58215 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
58216 + * the GNU General Public License for more details.
58218 + * You should have received a copy of the GNU General Public License
58219 + * along with the Ubicom32 Linux Kernel Port. If not,
58220 + * see <http://www.gnu.org/licenses/>.
58226 +#define SND_UBI32_DEBUG 0 // Debug flag
58228 +#include <linux/platform_device.h>
58229 +#include <asm/devtree.h>
58230 +#include <asm/audio.h>
58231 +#include <asm/ubi32-pcm.h>
58233 +struct ubi32_snd_priv;
58235 +typedef int (*set_channels_t)(struct ubi32_snd_priv *priv, int channels);
58236 +typedef int (*set_rate_t)(struct ubi32_snd_priv *priv, int rate);
58238 +struct ubi32_snd_priv {
58240 + * Any variables that are needed locally here but NOT in
58241 + * the VP itself should go in here.
58243 + struct snd_card *card;
58244 + struct snd_pcm *pcm;
58247 + * capture (1) or playback (0)
58251 + * DAC parameters. These are the parameters for the specific
58252 + * DAC we are driving. The I2S component can run at a range
58253 + * of frequencies, but the DAC may be limited. We may want
58254 + * to make this an array of some sort in the future?
58256 + * min/max_sample_rate if set to 0 are ignored.
58258 + int max_sample_rate;
58259 + int min_sample_rate;
58262 + * The size a period (group) of audio samples. The VP does
58263 + * not need to know this; each DMA transfer is made to be
58266 + u32_t period_size;
58268 + spinlock_t ubi32_lock;
58270 + struct audio_regs *ar;
58271 + struct audio_dev_regs *adr;
58279 + * Operations which the base DAC driver can implement
58281 + set_channels_t set_channels;
58282 + set_rate_t set_rate;
58287 + struct ubi32pcm_platform_data *pdata;
58290 + * Private driver data (used for DAC driver control, etc)
58295 +#define snd_ubi32_priv_get_drv(priv) ((priv)->drvdata)
58296 +#define snd_ubi32_priv_set_drv(priv, data) (((priv)->drvdata) = (void *)(data))
58298 +extern int snd_ubi32_pcm_probe(struct ubi32_snd_priv *ubi32_priv, struct platform_device *pdev);
58299 +extern void snd_ubi32_pcm_remove(struct ubi32_snd_priv *ubi32_priv);
58303 +++ b/sound/ubicom32/ubi32-pcm.c
58306 + * sound/ubicom32/ubi32-pcm.c
58307 + * Interface to ubicom32 virtual audio peripheral
58309 + * (C) Copyright 2009, Ubicom, Inc.
58311 + * This file is part of the Ubicom32 Linux Kernel Port.
58313 + * The Ubicom32 Linux Kernel Port is free software: you can redistribute
58314 + * it and/or modify it under the terms of the GNU General Public License
58315 + * as published by the Free Software Foundation, either version 2 of the
58316 + * License, or (at your option) any later version.
58318 + * The Ubicom32 Linux Kernel Port is distributed in the hope that it
58319 + * will be useful, but WITHOUT ANY WARRANTY; without even the implied
58320 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
58321 + * the GNU General Public License for more details.
58323 + * You should have received a copy of the GNU General Public License
58324 + * along with the Ubicom32 Linux Kernel Port. If not,
58325 + * see <http://www.gnu.org/licenses/>.
58327 + * Ubicom32 implementation derived from (with many thanks):
58333 +#include <linux/interrupt.h>
58334 +#include <sound/core.h>
58335 +#include <sound/pcm.h>
58336 +#include <sound/pcm_params.h>
58337 +#include <asm/ip5000.h>
58338 +#include <asm/ubi32-pcm.h>
58339 +#include <linux/dma-mapping.h>
58340 +#include <linux/delay.h>
58341 +#include "ubi32.h"
58343 +struct ubi32_snd_runtime_data {
58344 + dma_addr_t dma_buffer; /* Physical address of DMA buffer */
58345 + dma_addr_t dma_buffer_end; /* First address beyond end of DMA buffer */
58346 + size_t period_size;
58347 + dma_addr_t period_ptr; /* Physical address of next period */
58348 + unsigned int flags;
58351 +static void snd_ubi32_vp_int_set(struct snd_pcm *pcm)
58353 + struct ubi32_snd_priv *ubi32_priv = pcm->private_data;
58354 + ubi32_priv->ar->int_req |= (1 << ubi32_priv->irq_idx);
58355 + ubicom32_set_interrupt(ubi32_priv->tx_irq);
58358 +static snd_pcm_uframes_t snd_ubi32_pcm_pointer(struct snd_pcm_substream *substream)
58361 + struct ubi32_snd_priv *ubi32_priv = snd_pcm_substream_chip(substream);
58362 + struct audio_dev_regs *adr = ubi32_priv->adr;
58363 + struct snd_pcm_runtime *runtime = substream->runtime;
58364 + struct ubi32_snd_runtime_data *ubi32_rd = substream->runtime->private_data;
58366 + dma_addr_t read_pos;
58368 + snd_pcm_uframes_t frames;
58369 + if (!adr->primary_os_buffer_ptr) {
58371 + * If primary_os_buffer_ptr is NULL (e.g. right after the HW is started or
58372 + * when the HW is stopped), then handle this case separately.
58377 + read_pos = (dma_addr_t)adr->primary_os_buffer_ptr;
58378 + frames = bytes_to_frames(runtime, read_pos - ubi32_rd->dma_buffer);
58379 + if (frames == runtime->buffer_size) {
58388 +static int snd_ubi32_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
58390 + struct ubi32_snd_priv *ubi32_priv = substream->pcm->private_data;
58391 + struct audio_dev_regs *adr = ubi32_priv->adr;
58392 + struct ubi32_snd_runtime_data *ubi32_rd = substream->runtime->private_data;
58395 +#ifdef CONFIG_SND_DEBUG
58396 + snd_printk(KERN_INFO "snd_ubi32_pcm_trigger cmd=%d=", cmd);
58399 + if (adr->command != AUDIO_CMD_NONE) {
58400 + snd_printk(KERN_WARNING "Can't send command to audio device at this time\n");
58401 + // Set a timer to call this function back later. How to do this?
58406 + * Set interrupt flag to indicate that we interrupted audio device
58407 + * to send a command
58411 + case SNDRV_PCM_TRIGGER_START:
58413 +#ifdef CONFIG_SND_DEBUG
58414 + snd_printk(KERN_INFO "START\n");
58417 + * Ready the DMA transfer
58419 + ubi32_rd->period_ptr = ubi32_rd->dma_buffer;
58421 +#ifdef CONFIG_SND_DEBUG
58422 + snd_printk(KERN_INFO "trigger period_ptr=%lx\n", (unsigned long)ubi32_rd->period_ptr);
58424 + adr->dma_xfer_requests[0].ptr = (void *)ubi32_rd->period_ptr;
58425 + adr->dma_xfer_requests[0].ctr = ubi32_rd->period_size;
58426 + adr->dma_xfer_requests[0].active = 1;
58428 +#ifdef CONFIG_SND_DEBUG
58429 + snd_printk(KERN_INFO "xfer_request 0 ptr=0x%x ctr=%u\n", ubi32_rd->period_ptr, ubi32_rd->period_size);
58432 + ubi32_rd->period_ptr += ubi32_rd->period_size;
58433 + adr->dma_xfer_requests[1].ptr = (void *)ubi32_rd->period_ptr;
58434 + adr->dma_xfer_requests[1].ctr = ubi32_rd->period_size;
58435 + adr->dma_xfer_requests[1].active = 1;
58437 +#ifdef CONFIG_SND_DEBUG
58438 + snd_printk(KERN_INFO "xfer_request 1 ptr=0x%x ctr=%u\n", ubi32_rd->period_ptr, ubi32_rd->period_size);
58442 + * Tell the VP that we want to begin playback by filling in the
58443 + * command field and then interrupting the audio VP
58445 + adr->int_flags |= AUDIO_INT_FLAG_COMMAND;
58446 + adr->command = AUDIO_CMD_START;
58447 + snd_ubi32_vp_int_set(substream->pcm);
58450 + case SNDRV_PCM_TRIGGER_STOP:
58452 +#ifdef CONFIG_SND_DEBUG
58453 + snd_printk(KERN_INFO "STOP\n");
58457 + * Tell the VP that we want to stop playback by filling in the
58458 + * command field and then interrupting the audio VP
58460 + adr->int_flags |= AUDIO_INT_FLAG_COMMAND;
58461 + adr->command = AUDIO_CMD_STOP;
58462 + snd_ubi32_vp_int_set(substream->pcm);
58465 + case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
58467 +#ifdef CONFIG_SND_DEBUG
58468 + snd_printk(KERN_INFO "PAUSE_PUSH\n");
58472 + * Tell the VP that we want to pause playback by filling in the
58473 + * command field and then interrupting the audio VP
58475 + adr->int_flags |= AUDIO_INT_FLAG_COMMAND;
58476 + adr->command = AUDIO_CMD_PAUSE;
58477 + snd_ubi32_vp_int_set(substream->pcm);
58480 + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
58482 +#ifdef CONFIG_SND_DEBUG
58483 + snd_printk(KERN_INFO "PAUSE_RELEASE\n");
58486 + * Tell the VP that we want to resume paused playback by filling
58487 + * in the command field and then interrupting the audio VP
58489 + adr->int_flags |= AUDIO_INT_FLAG_COMMAND;
58490 + adr->command = AUDIO_CMD_RESUME;
58491 + snd_ubi32_vp_int_set(substream->pcm);
58495 + snd_printk(KERN_WARNING "Unhandled trigger\n");
58504 + * Prepare to transfer an audio stream to the codec
58506 +static int snd_ubi32_pcm_prepare(struct snd_pcm_substream *substream)
58509 + * Configure registers and setup the runtime instance for DMA transfers
58511 + struct ubi32_snd_priv *ubi32_priv = substream->pcm->private_data;
58512 + struct audio_dev_regs *adr = ubi32_priv->adr;
58514 +#ifdef CONFIG_SND_DEBUG
58515 + snd_printk(KERN_INFO "snd_ubi32_pcm_prepare: sending STOP command to audio device\n");
58519 + * Make sure the audio device is stopped
58523 + * Set interrupt flag to indicate that we interrupted audio device
58524 + * to send a command
58526 + adr->int_flags |= AUDIO_INT_FLAG_COMMAND;
58527 + adr->command = AUDIO_CMD_STOP;
58528 + snd_ubi32_vp_int_set(substream->pcm);
58534 + * Allocate DMA buffers from preallocated memory.
58535 + * Preallocation was done in snd_ubi32_pcm_new()
58537 +static int snd_ubi32_pcm_hw_params(struct snd_pcm_substream *substream,
58538 + struct snd_pcm_hw_params *hw_params)
58540 + struct snd_pcm_runtime *runtime = substream->runtime;
58541 + struct ubi32_snd_priv *ubi32_priv = substream->pcm->private_data;
58542 + struct audio_dev_regs *adr = ubi32_priv->adr;
58543 + struct ubi32_snd_runtime_data *ubi32_rd = substream->runtime->private_data;
58546 + * Use pre-allocated memory from ubi32_snd_pcm_new() to satisfy
58547 + * this memory request.
58549 + int ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
58554 +#ifdef CONFIG_SND_DEBUG
58555 + snd_printk(KERN_INFO "snd_ubi32_pcm_hw_params\n");
58558 + if (!(adr->channel_mask & (1 << params_channels(hw_params)))) {
58559 + snd_printk(KERN_INFO "snd_ubi32_pcm_hw_params unsupported number of channels %d mask %08x\n", params_channels(hw_params), adr->channel_mask);
58563 + if (ubi32_priv->set_channels) {
58564 + int ret = ubi32_priv->set_channels(ubi32_priv, params_channels(hw_params));
58566 + snd_printk(KERN_WARNING "Unable to set channels to %d, ret=%d\n", params_channels(hw_params), ret);
58571 + if (ubi32_priv->set_rate) {
58572 + int ret = ubi32_priv->set_rate(ubi32_priv, params_rate(hw_params));
58574 + snd_printk(KERN_WARNING "Unable to set rate to %d, ret=%d\n", params_rate(hw_params), ret);
58579 + if (ubi32_priv->pdata->set_rate) {
58580 + int ret = ubi32_priv->pdata->set_rate(ubi32_priv->pdata->appdata, params_rate(hw_params));
58582 + snd_printk(KERN_WARNING "Unable to set rate to %d, ret=%d\n", params_rate(hw_params), ret);
58587 + if (adr->command != AUDIO_CMD_NONE) {
58588 + snd_printk(KERN_WARNING "snd_ubi32_pcm_hw_params: tio busy\n");
58592 + if (params_format(hw_params) == SNDRV_PCM_FORMAT_S16_LE) {
58593 + adr->flags |= CMD_START_FLAG_LE;
58595 + adr->flags &= ~CMD_START_FLAG_LE;
58597 + adr->channels = params_channels(hw_params);
58598 + adr->sample_rate = params_rate(hw_params);
58599 + adr->command = AUDIO_CMD_SETUP;
58600 + adr->int_flags |= AUDIO_INT_FLAG_COMMAND;
58601 + snd_ubi32_vp_int_set(substream->pcm);
58604 + * Wait for the command to complete
58606 + while (adr->command != AUDIO_CMD_NONE) {
58611 + * Put the DMA info into the DMA descriptor that we will
58612 + * use to do transfers to our audio VP "hardware"
58616 + * Mark both DMA transfers as not ready/inactive
58618 + adr->dma_xfer_requests[0].active = 0;
58619 + adr->dma_xfer_requests[1].active = 0;
58622 + * Put the location of the buffer into the runtime data instance
58624 + ubi32_rd->dma_buffer = (dma_addr_t)runtime->dma_area;
58625 + ubi32_rd->dma_buffer_end = (dma_addr_t)(runtime->dma_area + runtime->dma_bytes);
58628 + * Get the period size
58630 + ubi32_rd->period_size = params_period_bytes(hw_params);
58632 +#ifdef CONFIG_SND_DEBUG
58633 + snd_printk(KERN_INFO "DMA for ubi32 audio initialized dma_area=0x%x dma_bytes=%d, period_size=%d\n", (unsigned int)runtime->dma_area, (unsigned int)runtime->dma_bytes, ubi32_rd->period_size);
58634 + snd_printk(KERN_INFO "Private buffer ubi32_rd: dma_buffer=0x%x dma_buffer_end=0x%x ret=%d\n", ubi32_rd->dma_buffer, ubi32_rd->dma_buffer_end, ret);
58641 + * This is the reverse of snd_ubi32_pcm_hw_params
58643 +static int snd_ubi32_pcm_hw_free(struct snd_pcm_substream *substream)
58645 +#ifdef CONFIG_SND_DEBUG
58646 + snd_printk(KERN_INFO "snd_ubi32_pcm_hw_free\n");
58648 + return snd_pcm_lib_free_pages(substream);
58652 + * Audio virtual peripheral capabilities (capture and playback are identical)
58654 +static struct snd_pcm_hardware snd_ubi32_pcm_hw =
58656 + .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
58657 + SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
58658 + .buffer_bytes_max = (64*1024),
58659 + .period_bytes_min = 64,
58660 + .period_bytes_max = 8184,//8184,//8176,
58661 + .periods_min = 2,
58662 + .periods_max = 255,
58663 + .fifo_size = 0, // THIS IS IGNORED BY ALSA
58667 + * We fill this in later
58669 +static struct snd_pcm_hw_constraint_list ubi32_pcm_rates;
58672 + * snd_ubi32_pcm_close
58674 +static int snd_ubi32_pcm_close(struct snd_pcm_substream *substream)
58676 + /* Disable codec, stop DMA, free private data structures */
58677 + //struct ubi32_snd_priv *ubi32_priv = snd_pcm_substream_chip(substream);
58678 + struct ubi32_snd_runtime_data *ubi32_rd = substream->runtime->private_data;
58680 +#ifdef CONFIG_SND_DEBUG
58681 + snd_printk(KERN_INFO "snd_ubi32_pcm_close\n");
58684 + substream->runtime->private_data = NULL;
58692 + * snd_ubi32_pcm_open
58694 +static int snd_ubi32_pcm_open(struct snd_pcm_substream *substream)
58696 + struct snd_pcm_runtime *runtime = substream->runtime;
58697 + struct ubi32_snd_runtime_data *ubi32_rd;
58700 +#ifdef CONFIG_SND_DEBUG
58701 + snd_printk(KERN_INFO "ubi32 pcm open\n");
58704 + /* Associate capabilities with component */
58705 + runtime->hw = snd_ubi32_pcm_hw;
58708 + * Inform ALSA about constraints of the audio device
58710 + ret = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &ubi32_pcm_rates);
58712 + snd_printk(KERN_INFO "invalid rate\n");
58716 + /* Force the buffer size to be an integer multiple of period size */
58717 + ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
58719 + snd_printk(KERN_INFO "invalid period\n");
58722 + /* Initialize structures/registers */
58723 + ubi32_rd = kzalloc(sizeof(struct ubi32_snd_runtime_data), GFP_KERNEL);
58724 + if (ubi32_rd == NULL) {
58729 + runtime->private_data = ubi32_rd;
58731 +#ifdef CONFIG_SND_DEBUG
58732 + snd_printk(KERN_INFO "snd_ubi32_pcm_open returned 0\n");
58737 +#ifdef CONFIG_SND_DEBUG
58738 + snd_printk(KERN_INFO "snd_ubi32_pcm_open returned %d\n", ret);
58744 +static struct snd_pcm_ops snd_ubi32_pcm_ops = {
58745 + .open = snd_ubi32_pcm_open, /* Open */
58746 + .close = snd_ubi32_pcm_close, /* Close */
58747 + .ioctl = snd_pcm_lib_ioctl, /* Generic IOCTL handler */
58748 + .hw_params = snd_ubi32_pcm_hw_params, /* Hardware parameters/capabilities */
58749 + .hw_free = snd_ubi32_pcm_hw_free, /* Free function for hw_params */
58750 + .prepare = snd_ubi32_pcm_prepare,
58751 + .trigger = snd_ubi32_pcm_trigger,
58752 + .pointer = snd_ubi32_pcm_pointer,
58756 + * Interrupt handler that gets called when the audio device
58757 + * interrupts Linux
58759 +static irqreturn_t snd_ubi32_pcm_interrupt(int irq, void *appdata)
58761 + struct snd_pcm *pcm = (struct snd_pcm *)appdata;
58762 + struct ubi32_snd_priv *ubi32_priv = pcm->private_data;
58763 + struct audio_dev_regs *adr = ubi32_priv->adr;
58764 + struct snd_pcm_substream *substream;
58765 + struct ubi32_snd_runtime_data *ubi32_rd;
58766 + int dma_to_fill = 0;
58769 + * Check to see if the interrupt is for us
58771 + if (!(ubi32_priv->ar->int_status & (1 << ubi32_priv->irq_idx))) {
58776 + * Clear the interrupt
58778 + ubi32_priv->ar->int_status &= ~(1 << ubi32_priv->irq_idx);
58781 + * We only have one stream since we don't mix. Therefore
58782 + * we don't need to search through substreams.
58784 + if (ubi32_priv->is_capture) {
58785 + substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
58787 + substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
58790 + if (!substream->runtime) {
58791 + snd_printk(KERN_WARNING "No runtime data\n");
58795 + ubi32_rd = substream->runtime->private_data;
58797 +#ifdef CONFIG_SND_DEBUG
58798 + snd_printk(KERN_INFO "Ubi32 ALSA interrupt\n");
58801 + if (ubi32_rd == NULL) {
58802 + snd_printk(KERN_WARNING "No private data\n");
58806 + // Check interrupt cause
58808 + // Handle the underflow case
58809 + } else if ((adr->status & AUDIO_STATUS_PLAY_DMA0_REQUEST) ||
58810 + (adr->status & AUDIO_STATUS_PLAY_DMA1_REQUEST)) {
58811 + if (adr->status & AUDIO_STATUS_PLAY_DMA0_REQUEST) {
58813 + adr->status &= ~AUDIO_STATUS_PLAY_DMA0_REQUEST;
58814 + } else if (adr->status & AUDIO_STATUS_PLAY_DMA1_REQUEST) {
58816 + adr->status &= ~AUDIO_STATUS_PLAY_DMA1_REQUEST;
58818 + ubi32_rd->period_ptr += ubi32_rd->period_size;
58819 + if (ubi32_rd->period_ptr >= ubi32_rd->dma_buffer_end) {
58820 + ubi32_rd->period_ptr = ubi32_rd->dma_buffer;
58822 + adr->dma_xfer_requests[dma_to_fill].ptr = (void *)ubi32_rd->period_ptr;
58823 + adr->dma_xfer_requests[dma_to_fill].ctr = ubi32_rd->period_size;
58824 + adr->dma_xfer_requests[dma_to_fill].active = 1;
58825 +#ifdef CONFIG_SND_DEBUG
58826 + snd_printk(KERN_INFO "xfer_request %d ptr=0x%x ctr=%u\n", dma_to_fill, ubi32_rd->period_ptr, ubi32_rd->period_size);
58828 + adr->int_flags |= AUDIO_INT_FLAG_MORE_SAMPLES;
58829 + snd_ubi32_vp_int_set(substream->pcm);
58831 + // If we are interrupted by the VP, that means we completed
58832 + // processing one period of audio. We need to inform the upper
58833 + // layers of ALSA of this.
58834 + snd_pcm_period_elapsed(substream);
58836 + return IRQ_HANDLED;
58839 +void __devexit snd_ubi32_pcm_remove(struct ubi32_snd_priv *ubi32_priv)
58841 + struct snd_pcm *pcm = ubi32_priv->pcm;
58842 + free_irq(ubi32_priv->rx_irq, pcm);
58845 +#if SNDRV_PCM_RATE_5512 != 1 << 0 || SNDRV_PCM_RATE_192000 != 1 << 12
58846 +#error "Change this table to match pcm.h"
58848 +static unsigned int rates[] __initdata = {5512, 8000, 11025, 16000, 22050,
58849 + 32000, 44100, 48000, 64000, 88200,
58850 + 96000, 176400, 192000};
58853 + * snd_ubi32_pcm_probe
58855 +int __devinit snd_ubi32_pcm_probe(struct ubi32_snd_priv *ubi32_priv, struct platform_device *pdev)
58857 + struct snd_pcm *pcm;
58862 + unsigned int rate_max = 0;
58863 + unsigned int rate_min = 0xFFFFFFFF;
58864 + unsigned int rate_mask = 0;
58865 + struct audio_dev_regs *adr;
58866 + struct resource *res_adr;
58867 + struct resource *res_irq_tx;
58868 + struct resource *res_irq_rx;
58869 + struct ubi32pcm_platform_data *pdata;
58871 + pdata = pdev->dev.platform_data;
58877 + * Get our resources, adr is the hardware driver base address
58878 + * and the tx and rx irqs are used to communicate with the
58879 + * hardware driver.
58881 + res_adr = platform_get_resource(pdev, IORESOURCE_MEM, AUDIO_MEM_RESOURCE);
58882 + res_irq_tx = platform_get_resource(pdev, IORESOURCE_IRQ, AUDIO_TX_IRQ_RESOURCE);
58883 + res_irq_rx = platform_get_resource(pdev, IORESOURCE_IRQ, AUDIO_RX_IRQ_RESOURCE);
58884 + if (!res_adr || !res_irq_tx || !res_irq_rx) {
58885 + snd_printk(KERN_WARNING "Could not get resources");
58889 + ubi32_priv->ar = (struct audio_regs *)res_adr->start;
58890 + ubi32_priv->tx_irq = res_irq_tx->start;
58891 + ubi32_priv->rx_irq = res_irq_rx->start;
58892 + ubi32_priv->irq_idx = pdata->inst_num;
58893 + ubi32_priv->adr = &(ubi32_priv->ar->adr[pdata->inst_num]);
58896 + * Check the version
58898 + adr = ubi32_priv->adr;
58899 + if (adr->version != AUDIO_DEV_REGS_VERSION) {
58900 + snd_printk(KERN_WARNING "This audio_dev_reg is not compatible with this driver\n");
58905 + * Find out the standard rates, also find max and min rates
58907 + for (i = 0; i < ARRAY_SIZE(rates); i++) {
58909 + for (j = 0; j < adr->n_sample_rates; j++) {
58910 + if (rates[i] == adr->sample_rates[j]) {
58912 + * Check to see if it is supported by the dac
58914 + if ((rates[i] >= ubi32_priv->min_sample_rate) &&
58915 + (!ubi32_priv->max_sample_rate ||
58916 + (ubi32_priv->max_sample_rate && (rates[i] <= ubi32_priv->max_sample_rate)))) {
58918 + rate_mask |= (1 << i);
58920 + if (rates[i] < rate_min) {
58921 + rate_min = rates[i];
58923 + if (rates[i] > rate_max) {
58924 + rate_max = rates[i];
58931 + rate_mask |= SNDRV_PCM_RATE_KNOT;
58935 + snd_ubi32_pcm_hw.rates = rate_mask;
58936 + snd_ubi32_pcm_hw.rate_min = rate_min;
58937 + snd_ubi32_pcm_hw.rate_max = rate_max;
58938 + ubi32_pcm_rates.count = adr->n_sample_rates;
58939 + ubi32_pcm_rates.list = (unsigned int *)adr->sample_rates;
58940 + ubi32_pcm_rates.mask = 0;
58942 + for (i = 0; i < 32; i++) {
58943 + if (adr->channel_mask & (1 << i)) {
58944 + if (!snd_ubi32_pcm_hw.channels_min) {
58945 + snd_ubi32_pcm_hw.channels_min = i;
58947 + snd_ubi32_pcm_hw.channels_max = i;
58950 + snd_printk(KERN_INFO "Ubi32PCM: channels_min:%u channels_max:%u\n",
58951 + snd_ubi32_pcm_hw.channels_min,
58952 + snd_ubi32_pcm_hw.channels_max);
58954 + if (adr->caps & AUDIONODE_CAP_BE) {
58955 + snd_ubi32_pcm_hw.formats |= SNDRV_PCM_FMTBIT_S16_BE;
58957 + if (adr->caps & AUDIONODE_CAP_LE) {
58958 + snd_ubi32_pcm_hw.formats |= SNDRV_PCM_FMTBIT_S16_LE;
58961 + snd_printk(KERN_INFO "Ubi32PCM: rates:%08x min:%u max:%u count:%d fmts:%016llx (%s)\n",
58962 + snd_ubi32_pcm_hw.rates,
58963 + snd_ubi32_pcm_hw.rate_min,
58964 + snd_ubi32_pcm_hw.rate_max,
58965 + ubi32_pcm_rates.count,
58966 + snd_ubi32_pcm_hw.formats,
58967 + ubi32_priv->is_capture ? "capture" : "playback");
58969 + if (ubi32_priv->is_capture) {
58970 + ret = snd_pcm_new(ubi32_priv->card, "Ubi32 PCM", 0, 0, 1, &pcm);
58972 + ret = snd_pcm_new(ubi32_priv->card, "Ubi32 PCM", 0, 1, 0, &pcm);
58979 + pcm->private_data = ubi32_priv;
58980 + ubi32_priv->pcm = pcm;
58981 + ubi32_priv->pdata = pdata;
58983 + pcm->info_flags = 0;
58985 + strcpy(pcm->name, "Ubi32-PCM");
58987 + snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
58988 + snd_dma_continuous_data(GFP_KERNEL),
58989 + 45*1024, 64*1024);
58991 + if (ubi32_priv->is_capture) {
58992 + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ubi32_pcm_ops);
58994 + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ubi32_pcm_ops);
58998 + * Start up the audio device
59000 + adr->int_flags |= AUDIO_INT_FLAG_COMMAND;
59001 + adr->command = AUDIO_CMD_ENABLE;
59002 + snd_ubi32_vp_int_set(pcm);
59007 + err = request_irq(ubi32_priv->rx_irq, snd_ubi32_pcm_interrupt, IRQF_SHARED | IRQF_DISABLED, pcm->name, pcm);
59009 + snd_printk(KERN_WARNING "request_irq failed: irq=%d err=%d\n", ubi32_priv->rx_irq, err);