diff options
Diffstat (limited to 'drivers')
55 files changed, 3560 insertions, 3288 deletions
diff --git a/drivers/acorn/char/Makefile b/drivers/acorn/char/Makefile deleted file mode 100644 index d006c9f168d..00000000000 --- a/drivers/acorn/char/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -# -# Makefile for the acorn character device drivers. -# - -obj-$(CONFIG_L7200_KEYB) += defkeymap-l7200.o keyb_l7200.o diff --git a/drivers/acorn/char/defkeymap-l7200.c b/drivers/acorn/char/defkeymap-l7200.c deleted file mode 100644 index 93d80a1c36f..00000000000 --- a/drivers/acorn/char/defkeymap-l7200.c +++ /dev/null @@ -1,386 +0,0 @@ -/* - * linux/drivers/acorn/char/defkeymap-l7200.c - * - * Default keyboard maps for LinkUp Systems L7200 board - * - * Copyright (C) 2000 Steve Hill (sjhill@cotw.com) - * - * Changelog: - * 08-04-2000 SJH Created file - */ - -#include <linux/types.h> -#include <linux/keyboard.h> -#include <linux/kd.h> - -/* Normal (maps 1:1 with no processing) */ -#define KTn 0xF0 -/* Function keys */ -#define KTf 0xF1 -/* Special (Performs special house-keeping funcs) */ -#define KTs 0xF2 -#define KIGNORE K(KTs, 0) /* Ignore */ -#define KENTER K(KTs, 1) /* Enter */ -#define KREGS K(KTs, 2) /* Regs */ -#define KMEM K(KTs, 3) /* Mem */ -#define KSTAT K(KTs, 4) /* State */ -#define KINTR K(KTs, 5) /* Intr */ -#define Ksl 6 /* Last console */ -#define KCAPSLK K(KTs, 7) /* Caps lock */ -#define KNUMLK K(KTs, 8) /* Num-lock */ -#define KSCRLLK K(KTs, 9) /* Scroll-lock */ -#define KSCRLFOR K(KTs,10) /* Scroll forward */ -#define KSCRLBAK K(KTs,11) /* Scroll back */ -#define KREBOOT K(KTs,12) /* Reboot */ -#define KCAPSON K(KTs,13) /* Caps on */ -#define KCOMPOSE K(KTs,14) /* Compose */ -#define KSAK K(KTs,15) /* SAK */ -#define CONS_DEC K(KTs,16) /* Dec console */ -#define CONS_INC K(KTs,17) /* Incr console */ -#define KFLOPPY K(KTs,18) /* Floppy */ -/* Key pad (0-9 = digits, 10=+, 11=-, 12=*, 13=/, 14=enter, 16=., 17=# */ -#define KTp 0xF3 -#define KPAD_0 K(KTp, 0 ) -#define KPAD_1 K(KTp, 1 ) -#define KPAD_2 K(KTp, 2 ) -#define KPAD_3 K(KTp, 3 ) -#define KPAD_4 K(KTp, 4 ) -#define KPAD_5 K(KTp, 5 ) -#define KPAD_6 K(KTp, 6 ) -#define KPAD_7 K(KTp, 7 ) -#define KPAD_8 K(KTp, 8 ) -#define KPAD_9 K(KTp, 9 ) -#define KPAD_PL K(KTp,10 ) -#define KPAD_MI K(KTp,11 ) -#define KPAD_ML K(KTp,12 ) -#define KPAD_DV K(KTp,13 ) -#define KPAD_EN K(KTp,14 ) -#define KPAD_DT K(KTp,16 ) -#define KPAD_HS K(KTp,20 ) -/* Console switching */ -#define KCn 0xF5 -/* Cursor */ -#define KTc 0xF6 -#define Kcd 0 /* Cursor down */ -#define Kcl 1 /* Cursor left */ -#define Kcr 2 /* Cursor right */ -#define Kcu 3 /* Cursor up */ -/* Shift/alt modifiers etc */ -#define KMd 0xF7 -#define KSHIFT K(KMd, 0 ) -#define KALTGR K(KMd, 1 ) -#define KCTRL K(KMd, 2 ) -#define KALT K(KMd, 3 ) -/* Meta */ -#define KMt 0xF8 -#define KAs 0xF9 -#define KPADA_0 K(KAs, 0 ) -#define KPADA_1 K(KAs, 1 ) -#define KPADA_2 K(KAs, 2 ) -#define KPADA_3 K(KAs, 3 ) -#define KPADA_4 K(KAs, 4 ) -#define KPADA_5 K(KAs, 5 ) -#define KPADA_6 K(KAs, 6 ) -#define KPADA_7 K(KAs, 7 ) -#define KPADA_8 K(KAs, 8 ) -#define KPADA_9 K(KAs, 9 ) -#define KPADB_0 K(KAs,10 ) -#define KPADB_1 K(KAs,11 ) -#define KPADB_2 K(KAs,12 ) -#define KPADB_3 K(KAs,13 ) -#define KPADB_4 K(KAs,14 ) -#define KPADB_5 K(KAs,15 ) -#define KPADB_6 K(KAs,16 ) -#define KPADB_7 K(KAs,17 ) -#define KPADB_8 K(KAs,18 ) -#define KPADB_9 K(KAs,19 ) -/* Locking keys */ -#define KLk 0xFA -/* Letters */ -#define KTl 0xFB - -/* - * Here is the layout of the keys for the Fujitsu QWERTY - * style keyboard: - * - * static char Fujitsu_Key_Table[] = - * { - * KALT, '`' , KNUL, KCTL, KFUN, KESC, '1' , '2' , - * '9' , '0' , '-' , '=' , KNUL, KBSP, KNUL, KNUL, - * KNUL, KBSL, KSHF, KNUL, KNUL, KDEL, KNUL, 't' , - * 'y' , 'u' , 'i' , KRET, KSHF, KPGD, KNUL, KNUL, - * KNUL, KTAB, KNUL, KNUL, KNUL, 'q' , 'w' , 'e' , - * 'r' , 'o' , 'p' , '[' , KNUL, ']' , KNUL, KNUL, - * KNUL, 'z' , KNUL, KNUL, KNUL, KSHL, KNUL, KNUL, - * 'k' , 'l' , ';' , KSQT, KNUL, KPGU, KNUL, KNUL, - * KNUL, 'a' , KNUL, KNUL, KNUL, 's' , 'd' , 'f' , - * 'g' , 'h' , 'j' , '/' , KNUL, KHME, KNUL, KNUL, - * KNUL, 'x' , KNUL, KNUL, KNUL, 'c' , 'v' , 'b' , - * 'n' , 'm' , ',' , '.' , KNUL, ' ' , KNUL, KNUL, - * KNUL, KNUL, KNUL, KNUL, KNUL, '3' , '4' , '5' , - * '6' , '7' , '8' , KNUL, KPRG, KNUL, KEND, KNUL, - * }; - */ - -u_short plain_map[NR_KEYS]= -{ - 0xf703, 0xf060, 0xf200, 0xf702, 0xf200, 0xf01b, 0xf031, 0xf032, - 0xf039, 0xf030, 0xf02d, 0xf03d, 0xf200, 0xf07f, 0xf200, 0xf200, - 0xf200, 0xf05c, 0xf700, 0xf200, 0xf200, 0xf116, 0xf000, 0xfb74, - 0xfb79, 0xfb75, 0xfb69, 0xf201, 0xf700, 0xf600, 0xf200, 0xf200, - 0xf200, 0xf009, 0xf200, 0xf200, 0xf200, 0xfb71, 0xfb77, 0xfb65, - 0xfb72, 0xfb6f, 0xfb70, 0xf05b, 0xf200, 0xf05d, 0xf200, 0xf200, - 0xf200, 0xfb7a, 0xf200, 0xf200, 0xf200, 0xf207, 0xf200, 0xf200, - 0xfb6b, 0xfb6c, 0xf03b, 0xf027, 0xf200, 0xf603, 0xf200, 0xf200, - 0xf200, 0xfb61, 0xf200, 0xf200, 0xf200, 0xfb73, 0xfb64, 0xfb66, - 0xfb67, 0xfb68, 0xfb6a, 0xf02f, 0xf200, 0xf601, 0xf200, 0xf200, - 0xf200, 0xfb78, 0xf200, 0xf200, 0xf200, 0xfb63, 0xfb76, 0xfb62, - 0xfb6e, 0xfb6d, 0xf02c, 0xf02e, 0xf200, 0xf020, 0xf200, 0xf200, - 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf033, 0xf034, 0xf035, - 0xf036, 0xf037, 0xf038, 0xf200, 0xf200, 0xf200, 0xf602, 0xf200, - 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, - 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -}; - -u_short shift_map[NR_KEYS]= -{ - 0xf703, 0xf07e, 0xf200, 0xf702, 0xf200, 0xf01b, 0xf021, 0xf040, - 0xf028, 0xf029, 0xf05f, 0xf02b, 0xf200, 0xf07f, 0xf200, 0xf200, - 0xf200, 0xf07c, 0xf700, 0xf200, 0xf200, 0xf116, 0xf000, 0xfb54, - 0xfb59, 0xfb55, 0xfb49, 0xf201, 0xf700, 0xf600, 0xf200, 0xf200, - 0xf200, 0xf009, 0xf200, 0xf200, 0xf200, 0xfb51, 0xfb57, 0xfb45, - 0xfb52, 0xfb4f, 0xfb50, 0xf07b, 0xf200, 0xf07d, 0xf200, 0xf200, - 0xf200, 0xfb5a, 0xf200, 0xf200, 0xf200, 0xf207, 0xf200, 0xf200, - 0xfb4b, 0xfb4c, 0xf03a, 0xf022, 0xf200, 0xf603, 0xf200, 0xf200, - 0xf200, 0xfb41, 0xf200, 0xf200, 0xf200, 0xfb53, 0xfb44, 0xfb46, - 0xfb47, 0xfb48, 0xfb4a, 0xf03f, 0xf200, 0xf601, 0xf200, 0xf200, - 0xf200, 0xfb58, 0xf200, 0xf200, 0xf200, 0xfb43, 0xfb56, 0xfb42, - 0xfb4e, 0xfb4d, 0xf03c, 0xf03e, 0xf200, 0xf020, 0xf200, 0xf200, - 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf023, 0xf024, 0xf025, - 0xf05e, 0xf026, 0xf02a, 0xf200, 0xf200, 0xf200, 0xf602, 0xf200, - 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, - 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -}; - -u_short altgr_map[NR_KEYS]= -{ - KIGNORE ,K(KCn,12 ),K(KCn,13 ),K(KCn,14 ),K(KCn,15 ),K(KCn,16 ),K(KCn,17 ),K(KCn, 18), - K(KCn, 19),K(KCn,20 ),K(KCn,21 ),K(KCn,22 ),K(KCn,23 ),KIGNORE ,KREGS ,KINTR , - KIGNORE ,KIGNORE ,K(KTn,'@'),KIGNORE ,K(KTn,'$'),KIGNORE ,KIGNORE ,K(KTn,'{'), - K(KTn,'['),K(KTn,']'),K(KTn,'}'),K(KTn,'\\'),KIGNORE ,KIGNORE ,KIGNORE ,K(KTf,21 ), - K(KTf,20 ),K(KTf,24 ),KNUMLK ,KPAD_DV ,KPAD_ML ,KPAD_HS ,KIGNORE ,K(KTl,'q'), - K(KTl,'w'),K(KTl,'e'),K(KTl,'r'),K(KTl,'t' ),K(KTl,'y'),K(KTl,'u'),K(KTl,'i' ),K(KTl,'o'), - K(KTl,'p'),KIGNORE ,K(KTn,'~'),KIGNORE ,K(KTf,22 ),K(KTf,23 ),K(KTf,25 ),KPADB_7 , - KPADB_8 ,KPADB_9 ,KPAD_MI ,KCTRL ,K(KAs,20 ),K(KTl,'s'),K(KAs,23 ),K(KAs,25 ), - K(KTl,'g'),K(KTl,'h'),K(KTl,'j'),K(KTl,'k' ),K(KTl,'l'),KIGNORE ,KIGNORE ,KENTER , - KPADB_4 ,KPADB_5 ,KPADB_6 ,KPAD_PL ,KSHIFT ,KIGNORE ,K(KTl,'z' ),K(KTl,'x'), - K(KAs,22 ),K(KTl,'v'),K(KTl,21 ),K(KTl,'n' ),K(KTl,'m'),KIGNORE ,KIGNORE ,KIGNORE , - KSHIFT ,K(KTc,Kcu),KPADB_1 ,KPADB_2 ,KPADB_3 ,KCAPSLK ,KALT ,KIGNORE , - KALTGR ,KCTRL ,K(KTc,Kcl),K(KTc,Kcd ),K(KTc,Kcr),KPADB_0 ,KPAD_DT ,KPAD_EN , - KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , - KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , - KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , -}; - -u_short ctrl_map[NR_KEYS]= -{ - 0xf703, 0xf200, 0xf200, 0xf702, 0xf200, 0xf200, 0xf001, 0xf002, - 0xf009, 0xf000, 0xf031, 0xf200, 0xf200, 0xf07f, 0xf200, 0xf200, - 0xf200, 0xf01c, 0xf700, 0xf200, 0xf200, 0xf116, 0xf000, 0xf020, - 0xf019, 0xf015, 0xf009, 0xf201, 0xf700, 0xf600, 0xf200, 0xf200, - 0xf200, 0xf009, 0xf200, 0xf200, 0xf200, 0xf011, 0xf017, 0xf005, - 0xf012, 0xf00f, 0xf010, 0xf01b, 0xf200, 0xf01d, 0xf200, 0xf200, - 0xf200, 0xf01a, 0xf200, 0xf200, 0xf200, 0xf207, 0xf200, 0xf200, - 0xf00b, 0xf00c, 0xf200, 0xf007, 0xf200, 0xf603, 0xf200, 0xf200, - 0xf200, 0xf001, 0xf200, 0xf200, 0xf200, 0xf001, 0xf013, 0xf006, - 0xf007, 0xf008, 0xf00a, 0xf07f, 0xf200, 0xf601, 0xf200, 0xf200, - 0xf200, 0xf018, 0xf200, 0xf200, 0xf200, 0xf003, 0xf016, 0xf002, - 0xf00e, 0xf00d, 0xf200, 0xf200, 0xf200, 0xf000, 0xf200, 0xf200, - 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf01b, 0xf01c, 0xf01d, - 0xf036, 0xf037, 0xf038, 0xf200, 0xf200, 0xf200, 0xf602, 0xf200, - 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, - 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf602, 0xf200, -}; - -u_short shift_ctrl_map[NR_KEYS]= -{ - KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , - KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KFLOPPY ,KINTR , - KIGNORE ,KIGNORE ,K(KTn, 0 ),KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , - KIGNORE ,KIGNORE ,KIGNORE ,K(KTn,31 ),KIGNORE ,KIGNORE ,KIGNORE ,K(KTf,21 ), - K(KTf,20 ),K(KTf,24 ),KNUMLK ,KPAD_DV ,KPAD_ML ,KPAD_HS ,KIGNORE ,K(KTn,17 ), - K(KTn,23 ),K(KTn, 5 ),K(KTn,18 ),K(KTn,20 ),K(KTn,25 ),K(KTn,21 ),K(KTn, 9 ),K(KTn,15 ), - K(KTn,16 ),KIGNORE ,KIGNORE ,KIGNORE ,K(KTf,22 ),K(KTf,23 ),K(KTf,25 ),KPAD_7 , - KPAD_8 ,KPAD_9 ,KPAD_MI ,KCTRL ,K(KTn, 1 ),K(KTn,19 ),K(KTn, 4 ),K(KTn, 6 ), - K(KTn, 7 ),K(KTn, 8 ),K(KTn,10 ),K(KTn,11 ),K(KTn,12 ),KIGNORE ,K(KTn, 7 ),KENTER , - KPAD_4 ,KPAD_5 ,KPAD_6 ,KPAD_PL ,KSHIFT ,KIGNORE ,K(KTn,26 ),K(KTn,24 ), - K(KTn, 3 ),K(KTn,22 ),K(KTn, 2 ),K(KTn,14 ),K(KTn,13 ),KIGNORE ,KIGNORE ,KIGNORE , - KSHIFT ,K(KTc,Kcu),KPAD_1 ,KPAD_2 ,KPAD_3 ,KCAPSLK ,KALT ,K(KTn, 0 ), - KALTGR ,KCTRL ,K(KTc,Kcl),K(KTc,Kcd ),K(KTc,Kcr),KPAD_0 ,KPAD_DT ,KPAD_EN , - KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , - KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , - KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , -}; - -u_short alt_map[NR_KEYS]= -{ - K(KMt,27 ),K(KCn, 0 ),K(KCn, 1 ),K(KCn, 2 ),K(KCn, 3 ),K(KCn, 4 ),K(KCn, 5 ),K(KCn, 6 ), - K(KCn, 7 ),K(KCn, 8 ),K(KCn, 9 ),K(KCn,10 ),K(KCn,11 ),KIGNORE ,KSCRLLK ,KINTR , - K(KMt,'`'),K(KMt,'1'),K(KMt,'2'),K(KMt,'3' ),K(KMt,'4'),K(KMt,'5'),K(KMt,'6' ),K(KMt,'7'), - K(KMt,'8'),K(KMt,'9'),K(KMt,'0'),K(KMt,'-' ),K(KMt,'='),K(KMt,'£'),K(KMt,127 ),K(KTf,21 ), - K(KTf,20 ),K(KTf,24 ),KNUMLK ,KPAD_DV ,KPAD_ML ,KPAD_HS ,K(KMt, 9 ),K(KMt,'q'), - K(KMt,'w'),K(KMt,'e'),K(KMt,'r'),K(KMt,'t' ),K(KMt,'y'),K(KMt,'u'),K(KMt,'i' ),K(KMt,'o'), - K(KMt,'p'),K(KMt,'['),K(KMt,']'),K(KMt,'\\'),K(KTf,22 ),K(KTf,23 ),K(KTf,25 ),KPADA_7 , - KPADA_8 ,KPADA_9 ,KPAD_MI ,KCTRL ,K(KMt,'a'),K(KMt,'s'),K(KMt,'d' ),K(KMt,'f'), - K(KMt,'g'),K(KMt,'h'),K(KMt,'j'),K(KMt,'k' ),K(KMt,'l'),K(KMt,';'),K(KMt,'\''),K(KMt,13 ), - KPADA_4 ,KPADA_5 ,KPADA_6 ,KPAD_PL ,KSHIFT ,KIGNORE ,K(KMt,'z' ),K(KMt,'x'), - K(KMt,'c'),K(KMt,'v'),K(KMt,'b'),K(KMt,'n' ),K(KMt,'m'),K(KMt,','),K(KMt,'.' ),KIGNORE , - KSHIFT ,K(KTc,Kcu),KPADA_1 ,KPADA_2 ,KPADA_3 ,KCAPSLK ,KALT ,K(KMt,' '), - KALTGR ,KCTRL ,CONS_DEC ,K(KTc,Kcd ),CONS_INC ,KPADA_0 ,KPAD_DT ,KPAD_EN , - KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , - KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , - KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , -}; - -u_short ctrl_alt_map[NR_KEYS]= -{ - KIGNORE ,K(KCn, 0 ),K(KCn, 1 ),K(KCn, 2 ),K(KCn, 3 ),K(KCn, 4 ),K(KCn, 5 ),K(KCn, 6 ), - K(KCn, 7 ),K(KCn, 8 ),K(KCn, 9 ),K(KCn,10 ),K(KCn,11 ),KIGNORE ,KIGNORE ,KINTR , - KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , - KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,K(KTf,21 ), - K(KTf,20 ),K(KTf,24 ),KNUMLK ,KPAD_DV ,KPAD_ML ,KPAD_HS ,KIGNORE ,K(KMt,17 ), - K(KMt,23 ),K(KMt, 5 ),K(KMt,18 ),K(KMt,20 ),K(KMt,25 ),K(KMt,21 ),K(KMt, 9 ),K(KMt,15 ), - K(KMt,16 ),KIGNORE ,KIGNORE ,KIGNORE ,KREBOOT ,K(KTf,23 ),K(KTf,25 ),KPAD_7 , - KPAD_8 ,KPAD_9 ,KPAD_MI ,KCTRL ,K(KMt, 1 ),K(KMt,19 ),K(KMt, 4 ),K(KMt, 6 ), - K(KMt, 7 ),K(KMt, 8 ),K(KMt,10 ),K(KMt,11 ),K(KMt,12 ),KIGNORE ,KIGNORE ,KENTER , - KPAD_4 ,KPAD_5 ,KPAD_6 ,KPAD_PL ,KSHIFT ,KIGNORE ,K(KMt,26 ),K(KMt,24 ), - K(KMt, 3 ),K(KMt,22 ),K(KMt, 2 ),K(KMt,14 ),K(KMt,13 ),KIGNORE ,KIGNORE ,KIGNORE , - KSHIFT ,K(KTc,Kcu),KPAD_1 ,KPAD_2 ,KPAD_3 ,KCAPSLK ,KALT ,KIGNORE , - KALTGR ,KCTRL ,K(KTc,Kcl),K(KTc,Kcd ),K(KTc,Kcr),KPAD_0 ,KREBOOT ,KPAD_EN , - KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , - KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , - KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , -}; - -ushort *key_maps[MAX_NR_KEYMAPS] = { - plain_map, shift_map, altgr_map, 0, - ctrl_map, shift_ctrl_map, 0, 0, - alt_map, 0, 0, 0, - ctrl_alt_map, 0 -}; - -unsigned int keymap_count = 7; - -/* - * Philosophy: most people do not define more strings, but they who do - * often want quite a lot of string space. So, we statically allocate - * the default and allocate dynamically in chunks of 512 bytes. - */ - -char func_buf[] = { - '\033', '[', '[', 'A', 0, - '\033', '[', '[', 'B', 0, - '\033', '[', '[', 'C', 0, - '\033', '[', '[', 'D', 0, - '\033', '[', '[', 'E', 0, - '\033', '[', '1', '7', '~', 0, - '\033', '[', '1', '8', '~', 0, - '\033', '[', '1', '9', '~', 0, - '\033', '[', '2', '0', '~', 0, - '\033', '[', '2', '1', '~', 0, - '\033', '[', '2', '3', '~', 0, - '\033', '[', '2', '4', '~', 0, - '\033', '[', '2', '5', '~', 0, - '\033', '[', '2', '6', '~', 0, - '\033', '[', '2', '8', '~', 0, - '\033', '[', '2', '9', '~', 0, - '\033', '[', '3', '1', '~', 0, - '\033', '[', '3', '2', '~', 0, - '\033', '[', '3', '3', '~', 0, - '\033', '[', '3', '4', '~', 0, - '\033', '[', '1', '~', 0, - '\033', '[', '2', '~', 0, - '\033', '[', '3', '~', 0, - '\033', '[', '4', '~', 0, - '\033', '[', '5', '~', 0, - '\033', '[', '6', '~', 0, - '\033', '[', 'M', 0, - '\033', '[', 'P', 0, -}; - -char *funcbufptr = func_buf; -int funcbufsize = sizeof(func_buf); -int funcbufleft = 0; /* space left */ - -char *func_table[MAX_NR_FUNC] = { - func_buf + 0, - func_buf + 5, - func_buf + 10, - func_buf + 15, - func_buf + 20, - func_buf + 25, - func_buf + 31, - func_buf + 37, - func_buf + 43, - func_buf + 49, - func_buf + 55, - func_buf + 61, - func_buf + 67, - func_buf + 73, - func_buf + 79, - func_buf + 85, - func_buf + 91, - func_buf + 97, - func_buf + 103, - func_buf + 109, - func_buf + 115, - func_buf + 120, - func_buf + 125, - func_buf + 130, - func_buf + 135, - func_buf + 140, - func_buf + 145, - 0, - 0, - func_buf + 149, - 0, -}; - -struct kbdiacruc accent_table[MAX_DIACR] = { - {'`', 'A', 0300}, {'`', 'a', 0340}, - {'\'', 'A', 0301}, {'\'', 'a', 0341}, - {'^', 'A', 0302}, {'^', 'a', 0342}, - {'~', 'A', 0303}, {'~', 'a', 0343}, - {'"', 'A', 0304}, {'"', 'a', 0344}, - {'O', 'A', 0305}, {'o', 'a', 0345}, - {'0', 'A', 0305}, {'0', 'a', 0345}, - {'A', 'A', 0305}, {'a', 'a', 0345}, - {'A', 'E', 0306}, {'a', 'e', 0346}, - {',', 'C', 0307}, {',', 'c', 0347}, - {'`', 'E', 0310}, {'`', 'e', 0350}, - {'\'', 'E', 0311}, {'\'', 'e', 0351}, - {'^', 'E', 0312}, {'^', 'e', 0352}, - {'"', 'E', 0313}, {'"', 'e', 0353}, - {'`', 'I', 0314}, {'`', 'i', 0354}, - {'\'', 'I', 0315}, {'\'', 'i', 0355}, - {'^', 'I', 0316}, {'^', 'i', 0356}, - {'"', 'I', 0317}, {'"', 'i', 0357}, - {'-', 'D', 0320}, {'-', 'd', 0360}, - {'~', 'N', 0321}, {'~', 'n', 0361}, - {'`', 'O', 0322}, {'`', 'o', 0362}, - {'\'', 'O', 0323}, {'\'', 'o', 0363}, - {'^', 'O', 0324}, {'^', 'o', 0364}, - {'~', 'O', 0325}, {'~', 'o', 0365}, - {'"', 'O', 0326}, {'"', 'o', 0366}, - {'/', 'O', 0330}, {'/', 'o', 0370}, - {'`', 'U', 0331}, {'`', 'u', 0371}, - {'\'', 'U', 0332}, {'\'', 'u', 0372}, - {'^', 'U', 0333}, {'^', 'u', 0373}, - {'"', 'U', 0334}, {'"', 'u', 0374}, - {'\'', 'Y', 0335}, {'\'', 'y', 0375}, - {'T', 'H', 0336}, {'t', 'h', 0376}, - {'s', 's', 0337}, {'"', 'y', 0377}, - {'s', 'z', 0337}, {'i', 'j', 0377}, -}; - -unsigned int accent_table_size = 68; diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index eb69fbadc9c..dde6ce963a1 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c @@ -39,7 +39,6 @@ #include <asm/io.h> #include <asm/arch/i2c.h> #include <asm/arch/pxa-regs.h> -#include <asm/arch/pxa2xx-gpio.h> struct pxa_i2c { spinlock_t lock; @@ -945,32 +944,6 @@ static const struct i2c_algorithm i2c_pxa_pio_algorithm = { .functionality = i2c_pxa_functionality, }; -static void i2c_pxa_enable(struct platform_device *dev) -{ - if (cpu_is_pxa27x()) { - switch (dev->id) { - case 0: - pxa_gpio_mode(GPIO117_I2CSCL_MD); - pxa_gpio_mode(GPIO118_I2CSDA_MD); - break; - case 1: - local_irq_disable(); - PCFR |= PCFR_PI2CEN; - local_irq_enable(); - break; - } - } -} - -static void i2c_pxa_disable(struct platform_device *dev) -{ - if (cpu_is_pxa27x() && dev->id == 1) { - local_irq_disable(); - PCFR &= ~PCFR_PI2CEN; - local_irq_enable(); - } -} - #define res_len(r) ((r)->end - (r)->start + 1) static int i2c_pxa_probe(struct platform_device *dev) { @@ -1036,7 +1009,6 @@ static int i2c_pxa_probe(struct platform_device *dev) #endif clk_enable(i2c->clk); - i2c_pxa_enable(dev); if (plat) { i2c->adap.class = plat->class; @@ -1080,7 +1052,6 @@ eadapt: free_irq(irq, i2c); ereqirq: clk_disable(i2c->clk); - i2c_pxa_disable(dev); iounmap(i2c->reg_base); eremap: clk_put(i2c->clk); @@ -1103,7 +1074,6 @@ static int __exit i2c_pxa_remove(struct platform_device *dev) clk_disable(i2c->clk); clk_put(i2c->clk); - i2c_pxa_disable(dev); iounmap(i2c->reg_base); release_mem_region(i2c->iobase, i2c->iosize); diff --git a/drivers/i2c/chips/isp1301_omap.c b/drivers/i2c/chips/isp1301_omap.c index b1b45dddb17..03a33f1b9cd 100644 --- a/drivers/i2c/chips/isp1301_omap.c +++ b/drivers/i2c/chips/isp1301_omap.c @@ -72,7 +72,7 @@ struct isp1301 { }; -/* bits in OTG_CTRL_REG */ +/* bits in OTG_CTRL */ #define OTG_XCEIV_OUTPUTS \ (OTG_ASESSVLD|OTG_BSESSEND|OTG_BSESSVLD|OTG_VBUSVLD|OTG_ID) @@ -186,8 +186,8 @@ isp1301_clear_bits(struct isp1301 *isp, u8 reg, u8 bits) /* operational registers */ #define ISP1301_MODE_CONTROL_1 0x04 /* u8 read, set, +1 clear */ -# define MC1_SPEED_REG (1 << 0) -# define MC1_SUSPEND_REG (1 << 1) +# define MC1_SPEED (1 << 0) +# define MC1_SUSPEND (1 << 1) # define MC1_DAT_SE0 (1 << 2) # define MC1_TRANSPARENT (1 << 3) # define MC1_BDIS_ACON_EN (1 << 4) @@ -274,7 +274,7 @@ static void power_down(struct isp1301 *isp) isp->otg.state = OTG_STATE_UNDEFINED; // isp1301_set_bits(isp, ISP1301_MODE_CONTROL_2, MC2_GLOBAL_PWR_DN); - isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_SUSPEND_REG); + isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_SUSPEND); isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_ID_PULLDOWN); isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_1, MC1_DAT_SE0); @@ -283,7 +283,7 @@ static void power_down(struct isp1301 *isp) static void power_up(struct isp1301 *isp) { // isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_2, MC2_GLOBAL_PWR_DN); - isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_1, MC1_SUSPEND_REG); + isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_1, MC1_SUSPEND); /* do this only when cpu is driving transceiver, * so host won't see a low speed device... @@ -360,6 +360,8 @@ isp1301_defer_work(struct isp1301 *isp, int work) /* called from irq handlers */ static void a_idle(struct isp1301 *isp, const char *tag) { + u32 l; + if (isp->otg.state == OTG_STATE_A_IDLE) return; @@ -373,13 +375,17 @@ static void a_idle(struct isp1301 *isp, const char *tag) gadget_suspend(isp); } isp->otg.state = OTG_STATE_A_IDLE; - isp->last_otg_ctrl = OTG_CTRL_REG = OTG_CTRL_REG & OTG_XCEIV_OUTPUTS; + l = omap_readl(OTG_CTRL) & OTG_XCEIV_OUTPUTS; + omap_writel(l, OTG_CTRL); + isp->last_otg_ctrl = l; pr_debug(" --> %s/%s\n", state_name(isp), tag); } /* called from irq handlers */ static void b_idle(struct isp1301 *isp, const char *tag) { + u32 l; + if (isp->otg.state == OTG_STATE_B_IDLE) return; @@ -393,7 +399,9 @@ static void b_idle(struct isp1301 *isp, const char *tag) gadget_suspend(isp); } isp->otg.state = OTG_STATE_B_IDLE; - isp->last_otg_ctrl = OTG_CTRL_REG = OTG_CTRL_REG & OTG_XCEIV_OUTPUTS; + l = omap_readl(OTG_CTRL) & OTG_XCEIV_OUTPUTS; + omap_writel(l, OTG_CTRL); + isp->last_otg_ctrl = l; pr_debug(" --> %s/%s\n", state_name(isp), tag); } @@ -406,7 +414,7 @@ dump_regs(struct isp1301 *isp, const char *label) u8 src = isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE); pr_debug("otg: %06x, %s %s, otg/%02x stat/%02x.%02x\n", - OTG_CTRL_REG, label, state_name(isp), + omap_readl(OTG_CTRL), label, state_name(isp), ctrl, status, src); /* mode control and irq enables don't change much */ #endif @@ -429,7 +437,7 @@ dump_regs(struct isp1301 *isp, const char *label) static void check_state(struct isp1301 *isp, const char *tag) { enum usb_otg_state state = OTG_STATE_UNDEFINED; - u8 fsm = OTG_TEST_REG & 0x0ff; + u8 fsm = omap_readw(OTG_TEST) & 0x0ff; unsigned extra = 0; switch (fsm) { @@ -494,7 +502,8 @@ static void check_state(struct isp1301 *isp, const char *tag) if (isp->otg.state == state && !extra) return; pr_debug("otg: %s FSM %s/%02x, %s, %06x\n", tag, - state_string(state), fsm, state_name(isp), OTG_CTRL_REG); + state_string(state), fsm, state_name(isp), + omap_readl(OTG_CTRL)); } #else @@ -508,10 +517,11 @@ static void update_otg1(struct isp1301 *isp, u8 int_src) { u32 otg_ctrl; - otg_ctrl = OTG_CTRL_REG - & OTG_CTRL_MASK - & ~OTG_XCEIV_INPUTS - & ~(OTG_ID|OTG_ASESSVLD|OTG_VBUSVLD); + otg_ctrl = omap_readl(OTG_CTRL) & OTG_CTRL_MASK; + otg_ctrl &= ~OTG_XCEIV_INPUTS; + otg_ctrl &= ~(OTG_ID|OTG_ASESSVLD|OTG_VBUSVLD); + + if (int_src & INTR_SESS_VLD) otg_ctrl |= OTG_ASESSVLD; else if (isp->otg.state == OTG_STATE_A_WAIT_VFALL) { @@ -534,7 +544,7 @@ static void update_otg1(struct isp1301 *isp, u8 int_src) return; } } - OTG_CTRL_REG = otg_ctrl; + omap_writel(otg_ctrl, OTG_CTRL); } /* outputs from ISP1301_OTG_STATUS */ @@ -542,15 +552,14 @@ static void update_otg2(struct isp1301 *isp, u8 otg_status) { u32 otg_ctrl; - otg_ctrl = OTG_CTRL_REG - & OTG_CTRL_MASK - & ~OTG_XCEIV_INPUTS - & ~(OTG_BSESSVLD|OTG_BSESSEND); + otg_ctrl = omap_readl(OTG_CTRL) & OTG_CTRL_MASK; + otg_ctrl &= ~OTG_XCEIV_INPUTS; + otg_ctrl &= ~(OTG_BSESSVLD | OTG_BSESSEND); if (otg_status & OTG_B_SESS_VLD) otg_ctrl |= OTG_BSESSVLD; else if (otg_status & OTG_B_SESS_END) otg_ctrl |= OTG_BSESSEND; - OTG_CTRL_REG = otg_ctrl; + omap_writel(otg_ctrl, OTG_CTRL); } /* inputs going to ISP1301 */ @@ -559,7 +568,7 @@ static void otg_update_isp(struct isp1301 *isp) u32 otg_ctrl, otg_change; u8 set = OTG1_DM_PULLDOWN, clr = OTG1_DM_PULLUP; - otg_ctrl = OTG_CTRL_REG; + otg_ctrl = omap_readl(OTG_CTRL); otg_change = otg_ctrl ^ isp->last_otg_ctrl; isp->last_otg_ctrl = otg_ctrl; otg_ctrl = otg_ctrl & OTG_XCEIV_INPUTS; @@ -639,6 +648,8 @@ pulldown: /* HNP switch to host or peripheral; and SRP */ if (otg_change & OTG_PULLUP) { + u32 l; + switch (isp->otg.state) { case OTG_STATE_B_IDLE: if (clr & OTG1_DP_PULLUP) @@ -655,7 +666,9 @@ pulldown: default: break; } - OTG_CTRL_REG |= OTG_PULLUP; + l = omap_readl(OTG_CTRL); + l |= OTG_PULLUP; + omap_writel(l, OTG_CTRL); } check_state(isp, __func__); @@ -664,20 +677,20 @@ pulldown: static irqreturn_t omap_otg_irq(int irq, void *_isp) { - u16 otg_irq = OTG_IRQ_SRC_REG; + u16 otg_irq = omap_readw(OTG_IRQ_SRC); u32 otg_ctrl; int ret = IRQ_NONE; struct isp1301 *isp = _isp; /* update ISP1301 transciever from OTG controller */ if (otg_irq & OPRT_CHG) { - OTG_IRQ_SRC_REG = OPRT_CHG; + omap_writew(OPRT_CHG, OTG_IRQ_SRC); isp1301_defer_work(isp, WORK_UPDATE_ISP); ret = IRQ_HANDLED; /* SRP to become b_peripheral failed */ } else if (otg_irq & B_SRP_TMROUT) { - pr_debug("otg: B_SRP_TIMEOUT, %06x\n", OTG_CTRL_REG); + pr_debug("otg: B_SRP_TIMEOUT, %06x\n", omap_readl(OTG_CTRL)); notresponding(isp); /* gadget drivers that care should monitor all kinds of @@ -687,31 +700,31 @@ static irqreturn_t omap_otg_irq(int irq, void *_isp) if (isp->otg.state == OTG_STATE_B_SRP_INIT) b_idle(isp, "srp_timeout"); - OTG_IRQ_SRC_REG = B_SRP_TMROUT; + omap_writew(B_SRP_TMROUT, OTG_IRQ_SRC); ret = IRQ_HANDLED; /* HNP to become b_host failed */ } else if (otg_irq & B_HNP_FAIL) { pr_debug("otg: %s B_HNP_FAIL, %06x\n", - state_name(isp), OTG_CTRL_REG); + state_name(isp), omap_readl(OTG_CTRL)); notresponding(isp); - otg_ctrl = OTG_CTRL_REG; + otg_ctrl = omap_readl(OTG_CTRL); otg_ctrl |= OTG_BUSDROP; otg_ctrl &= OTG_CTRL_MASK & ~OTG_XCEIV_INPUTS; - OTG_CTRL_REG = otg_ctrl; + omap_writel(otg_ctrl, OTG_CTRL); /* subset of b_peripheral()... */ isp->otg.state = OTG_STATE_B_PERIPHERAL; pr_debug(" --> b_peripheral\n"); - OTG_IRQ_SRC_REG = B_HNP_FAIL; + omap_writew(B_HNP_FAIL, OTG_IRQ_SRC); ret = IRQ_HANDLED; /* detect SRP from B-device ... */ } else if (otg_irq & A_SRP_DETECT) { pr_debug("otg: %s SRP_DETECT, %06x\n", - state_name(isp), OTG_CTRL_REG); + state_name(isp), omap_readl(OTG_CTRL)); isp1301_defer_work(isp, WORK_UPDATE_OTG); switch (isp->otg.state) { @@ -719,49 +732,49 @@ static irqreturn_t omap_otg_irq(int irq, void *_isp) if (!isp->otg.host) break; isp1301_defer_work(isp, WORK_HOST_RESUME); - otg_ctrl = OTG_CTRL_REG; + otg_ctrl = omap_readl(OTG_CTRL); otg_ctrl |= OTG_A_BUSREQ; otg_ctrl &= ~(OTG_BUSDROP|OTG_B_BUSREQ) & ~OTG_XCEIV_INPUTS & OTG_CTRL_MASK; - OTG_CTRL_REG = otg_ctrl; + omap_writel(otg_ctrl, OTG_CTRL); break; default: break; } - OTG_IRQ_SRC_REG = A_SRP_DETECT; + omap_writew(A_SRP_DETECT, OTG_IRQ_SRC); ret = IRQ_HANDLED; /* timer expired: T(a_wait_bcon) and maybe T(a_wait_vrise) * we don't track them separately */ } else if (otg_irq & A_REQ_TMROUT) { - otg_ctrl = OTG_CTRL_REG; + otg_ctrl = omap_readl(OTG_CTRL); pr_info("otg: BCON_TMOUT from %s, %06x\n", state_name(isp), otg_ctrl); notresponding(isp); otg_ctrl |= OTG_BUSDROP; otg_ctrl &= ~OTG_A_BUSREQ & OTG_CTRL_MASK & ~OTG_XCEIV_INPUTS; - OTG_CTRL_REG = otg_ctrl; + omap_writel(otg_ctrl, OTG_CTRL); isp->otg.state = OTG_STATE_A_WAIT_VFALL; - OTG_IRQ_SRC_REG = A_REQ_TMROUT; + omap_writew(A_REQ_TMROUT, OTG_IRQ_SRC); ret = IRQ_HANDLED; /* A-supplied voltage fell too low; overcurrent */ } else if (otg_irq & A_VBUS_ERR) { - otg_ctrl = OTG_CTRL_REG; + otg_ctrl = omap_readl(OTG_CTRL); printk(KERN_ERR "otg: %s, VBUS_ERR %04x ctrl %06x\n", state_name(isp), otg_irq, otg_ctrl); otg_ctrl |= OTG_BUSDROP; otg_ctrl &= ~OTG_A_BUSREQ & OTG_CTRL_MASK & ~OTG_XCEIV_INPUTS; - OTG_CTRL_REG = otg_ctrl; + omap_writel(otg_ctrl, OTG_CTRL); isp->otg.state = OTG_STATE_A_VBUS_ERR; - OTG_IRQ_SRC_REG = A_VBUS_ERR; + omap_writew(A_VBUS_ERR, OTG_IRQ_SRC); ret = IRQ_HANDLED; /* switch driver; the transciever code activates it, @@ -770,7 +783,7 @@ static irqreturn_t omap_otg_irq(int irq, void *_isp) } else if (otg_irq & DRIVER_SWITCH) { int kick = 0; - otg_ctrl = OTG_CTRL_REG; + otg_ctrl = omap_readl(OTG_CTRL); printk(KERN_NOTICE "otg: %s, SWITCH to %s, ctrl %06x\n", state_name(isp), (otg_ctrl & OTG_DRIVER_SEL) @@ -793,7 +806,7 @@ static irqreturn_t omap_otg_irq(int irq, void *_isp) } else { if (!(otg_ctrl & OTG_ID)) { otg_ctrl &= OTG_CTRL_MASK & ~OTG_XCEIV_INPUTS; - OTG_CTRL_REG = otg_ctrl | OTG_A_BUSREQ; + omap_writel(otg_ctrl | OTG_A_BUSREQ, OTG_CTRL); } if (isp->otg.host) { @@ -818,7 +831,7 @@ static irqreturn_t omap_otg_irq(int irq, void *_isp) } } - OTG_IRQ_SRC_REG = DRIVER_SWITCH; + omap_writew(DRIVER_SWITCH, OTG_IRQ_SRC); ret = IRQ_HANDLED; if (kick) @@ -834,12 +847,15 @@ static struct platform_device *otg_dev; static int otg_init(struct isp1301 *isp) { + u32 l; + if (!otg_dev) return -ENODEV; dump_regs(isp, __func__); /* some of these values are board-specific... */ - OTG_SYSCON_2_REG |= OTG_EN + l = omap_readl(OTG_SYSCON_2); + l |= OTG_EN /* for B-device: */ | SRP_GPDATA /* 9msec Bdev D+ pulse */ | SRP_GPDVBUS /* discharge after VBUS pulse */ @@ -849,18 +865,22 @@ static int otg_init(struct isp1301 *isp) | SRP_DPW /* detect 167+ns SRP pulses */ | SRP_DATA | SRP_VBUS /* accept both kinds of SRP pulse */ ; + omap_writel(l, OTG_SYSCON_2); update_otg1(isp, isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE)); update_otg2(isp, isp1301_get_u8(isp, ISP1301_OTG_STATUS)); check_state(isp, __func__); pr_debug("otg: %s, %s %06x\n", - state_name(isp), __func__, OTG_CTRL_REG); + state_name(isp), __func__, omap_readl(OTG_CTRL)); - OTG_IRQ_EN_REG = DRIVER_SWITCH | OPRT_CHG + omap_writew(DRIVER_SWITCH | OPRT_CHG | B_SRP_TMROUT | B_HNP_FAIL - | A_VBUS_ERR | A_SRP_DETECT | A_REQ_TMROUT; - OTG_SYSCON_2_REG |= OTG_EN; + | A_VBUS_ERR | A_SRP_DETECT | A_REQ_TMROUT, OTG_IRQ_EN); + + l = omap_readl(OTG_SYSCON_2); + l |= OTG_EN; + omap_writel(l, OTG_SYSCON_2); return 0; } @@ -927,7 +947,11 @@ static void otg_unbind(struct isp1301 *isp) static void b_peripheral(struct isp1301 *isp) { - OTG_CTRL_REG = OTG_CTRL_REG & OTG_XCEIV_OUTPUTS; + u32 l; + + l = omap_readl(OTG_CTRL) & OTG_XCEIV_OUTPUTS; + omap_writel(l, OTG_CTRL); + usb_gadget_vbus_connect(isp->otg.gadget); #ifdef CONFIG_USB_OTG @@ -999,6 +1023,8 @@ static void isp_update_otg(struct isp1301 *isp, u8 stat) isp_bstat = 0; } } else { + u32 l; + /* if user unplugged mini-A end of cable, * don't bypass A_WAIT_VFALL. */ @@ -1019,8 +1045,9 @@ static void isp_update_otg(struct isp1301 *isp, u8 stat) isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_1, MC1_BDIS_ACON_EN); isp->otg.state = OTG_STATE_B_IDLE; - OTG_CTRL_REG &= OTG_CTRL_REG & OTG_CTRL_MASK - & ~OTG_CTRL_BITS; + l = omap_readl(OTG_CTRL) & OTG_CTRL_MASK; + l &= ~OTG_CTRL_BITS; + omap_writel(l, OTG_CTRL); break; case OTG_STATE_B_IDLE: break; @@ -1046,7 +1073,8 @@ static void isp_update_otg(struct isp1301 *isp, u8 stat) /* FALLTHROUGH */ case OTG_STATE_B_SRP_INIT: b_idle(isp, __func__); - OTG_CTRL_REG &= OTG_CTRL_REG & OTG_XCEIV_OUTPUTS; + l = omap_readl(OTG_CTRL) & OTG_XCEIV_OUTPUTS; + omap_writel(l, OTG_CTRL); /* FALLTHROUGH */ case OTG_STATE_B_IDLE: if (isp->otg.gadget && (isp_bstat & OTG_B_SESS_VLD)) { @@ -1130,11 +1158,11 @@ isp1301_work(struct work_struct *work) case OTG_STATE_A_WAIT_VRISE: isp->otg.state = OTG_STATE_A_HOST; pr_debug(" --> a_host\n"); - otg_ctrl = OTG_CTRL_REG; + otg_ctrl = omap_readl(OTG_CTRL); otg_ctrl |= OTG_A_BUSREQ; otg_ctrl &= ~(OTG_BUSDROP|OTG_B_BUSREQ) & OTG_CTRL_MASK; - OTG_CTRL_REG = otg_ctrl; + omap_writel(otg_ctrl, OTG_CTRL); break; case OTG_STATE_B_WAIT_ACON: isp->otg.state = OTG_STATE_B_HOST; @@ -1274,7 +1302,7 @@ isp1301_set_host(struct otg_transceiver *otg, struct usb_bus *host) return -ENODEV; if (!host) { - OTG_IRQ_EN_REG = 0; + omap_writew(0, OTG_IRQ_EN); power_down(isp); isp->otg.host = 0; return 0; @@ -1325,12 +1353,13 @@ static int isp1301_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *gadget) { struct isp1301 *isp = container_of(otg, struct isp1301, otg); + u32 l; if (!otg || isp != the_transceiver) return -ENODEV; if (!gadget) { - OTG_IRQ_EN_REG = 0; + omap_writew(0, OTG_IRQ_EN); if (!isp->otg.default_a) enable_vbus_draw(isp, 0); usb_gadget_vbus_disconnect(isp->otg.gadget); @@ -1351,9 +1380,11 @@ isp1301_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *gadget) isp->otg.gadget = gadget; // FIXME update its refcount - OTG_CTRL_REG = (OTG_CTRL_REG & OTG_CTRL_MASK - & ~(OTG_XCEIV_OUTPUTS|OTG_CTRL_BITS)) - | OTG_ID; + l = omap_readl(OTG_CTRL) & OTG_CTRL_MASK; + l &= ~(OTG_XCEIV_OUTPUTS|OTG_CTRL_BITS); + l |= OTG_ID; + omap_writel(l, OTG_CTRL); + power_up(isp); isp->otg.state = OTG_STATE_B_IDLE; @@ -1405,16 +1436,17 @@ isp1301_start_srp(struct otg_transceiver *dev) || isp->otg.state != OTG_STATE_B_IDLE) return -ENODEV; - otg_ctrl = OTG_CTRL_REG; + otg_ctrl = omap_readl(OTG_CTRL); if (!(otg_ctrl & OTG_BSESSEND)) return -EINVAL; otg_ctrl |= OTG_B_BUSREQ; otg_ctrl &= ~OTG_A_BUSREQ & OTG_CTRL_MASK; - OTG_CTRL_REG = otg_ctrl; + omap_writel(otg_ctrl, OTG_CTRL); isp->otg.state = OTG_STATE_B_SRP_INIT; - pr_debug("otg: SRP, %s ... %06x\n", state_name(isp), OTG_CTRL_REG); + pr_debug("otg: SRP, %s ... %06x\n", state_name(isp), + omap_readl(OTG_CTRL)); #ifdef CONFIG_USB_OTG check_state(isp, __func__); #endif @@ -1426,6 +1458,7 @@ isp1301_start_hnp(struct otg_transceiver *dev) { #ifdef CONFIG_USB_OTG struct isp1301 *isp = container_of(dev, struct isp1301, otg); + u32 l; if (!dev || isp != the_transceiver) return -ENODEV; @@ -1452,7 +1485,9 @@ isp1301_start_hnp(struct otg_transceiver *dev) #endif /* caller must suspend then clear A_BUSREQ */ usb_gadget_vbus_connect(isp->otg.gadget); - OTG_CTRL_REG |= OTG_A_SETB_HNPEN; + l = omap_readl(OTG_CTRL); + l |= OTG_A_SETB_HNPEN; + omap_writel(l, OTG_CTRL); break; case OTG_STATE_A_PERIPHERAL: @@ -1462,7 +1497,7 @@ isp1301_start_hnp(struct otg_transceiver *dev) return -EILSEQ; } pr_debug("otg: HNP %s, %06x ...\n", - state_name(isp), OTG_CTRL_REG); + state_name(isp), omap_readl(OTG_CTRL)); check_state(isp, __func__); return 0; #else diff --git a/drivers/mmc/host/imxmmc.c b/drivers/mmc/host/imxmmc.c index 95f33e87a99..eed211b2ac7 100644 --- a/drivers/mmc/host/imxmmc.c +++ b/drivers/mmc/host/imxmmc.c @@ -42,6 +42,7 @@ #include <linux/mmc/host.h> #include <linux/mmc/card.h> #include <linux/delay.h> +#include <linux/clk.h> #include <asm/dma.h> #include <asm/io.h> @@ -92,6 +93,8 @@ struct imxmci_host { unsigned char actual_bus_width; int prev_cmd_code; + + struct clk *clk; }; #define IMXMCI_PEND_IRQ_b 0 @@ -841,7 +844,7 @@ static void imxmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) /* The prescaler is 5 for PERCLK2 equal to 96MHz * then 96MHz / 5 = 19.2 MHz */ - clk=imx_get_perclk2(); + clk = clk_get_rate(host->clk); prescaler=(clk+(CLK_RATE*7)/8)/CLK_RATE; switch(prescaler) { case 0: @@ -994,6 +997,13 @@ static int imxmci_probe(struct platform_device *pdev) host->res = r; host->irq = irq; + host->clk = clk_get(&pdev->dev, "perclk2"); + if (IS_ERR(host->clk)) { + ret = PTR_ERR(host->clk); + goto out; + } + clk_enable(host->clk); + imx_gpio_mode(PB8_PF_SD_DAT0); imx_gpio_mode(PB9_PF_SD_DAT1); imx_gpio_mode(PB10_PF_SD_DAT2); @@ -1017,8 +1027,8 @@ static int imxmci_probe(struct platform_device *pdev) host->imask = IMXMCI_INT_MASK_DEFAULT; MMC_INT_MASK = host->imask; - - if(imx_dma_request_by_prio(&host->dma, DRIVER_NAME, DMA_PRIO_LOW)<0){ + host->dma = imx_dma_request_by_prio(DRIVER_NAME, DMA_PRIO_LOW); + if(host->dma < 0) { dev_err(mmc_dev(host->mmc), "imx_dma_request_by_prio failed\n"); ret = -EBUSY; goto out; @@ -1053,6 +1063,10 @@ out: imx_dma_free(host->dma); host->dma_allocated=0; } + if (host->clk) { + clk_disable(host->clk); + clk_put(host->clk); + } } if (mmc) mmc_free_host(mmc); @@ -1082,6 +1096,9 @@ static int imxmci_remove(struct platform_device *pdev) tasklet_kill(&host->tasklet); + clk_disable(host->clk); + clk_put(host->clk); + release_resource(host->res); mmc_free_host(mmc); diff --git a/drivers/mtd/maps/omap_nor.c b/drivers/mtd/maps/omap_nor.c index c12d8056beb..68eec6c6c51 100644 --- a/drivers/mtd/maps/omap_nor.c +++ b/drivers/mtd/maps/omap_nor.c @@ -60,13 +60,22 @@ struct omapflash_info { static void omap_set_vpp(struct map_info *map, int enable) { static int count; - - if (enable) { - if (count++ == 0) - OMAP_EMIFS_CONFIG_REG |= OMAP_EMIFS_CONFIG_WP; - } else { - if (count && (--count == 0)) - OMAP_EMIFS_CONFIG_REG &= ~OMAP_EMIFS_CONFIG_WP; + u32 l; + + if (cpu_class_is_omap1()) { + if (enable) { + if (count++ == 0) { + l = omap_readl(EMIFS_CONFIG); + l |= OMAP_EMIFS_CONFIG_WP; + omap_writel(l, EMIFS_CONFIG); + } + } else { + if (count && (--count == 0)) { + l = omap_readl(EMIFS_CONFIG); + l &= ~OMAP_EMIFS_CONFIG_WP; + omap_writel(l, EMIFS_CONFIG); + } + } } } diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c index 59e05a1c50c..ee2ac3948cd 100644 --- a/drivers/mtd/nand/orion_nand.c +++ b/drivers/mtd/nand/orion_nand.c @@ -85,6 +85,9 @@ static int __init orion_nand_probe(struct platform_device *pdev) nc->cmd_ctrl = orion_nand_cmd_ctrl; nc->ecc.mode = NAND_ECC_SOFT; + if (board->chip_delay) + nc->chip_delay = board->chip_delay; + if (board->width == 16) nc->options |= NAND_BUSWIDTH_16; diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index f4182cfffe9..45a41b597da 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -217,7 +217,7 @@ config MII config MACB tristate "Atmel MACB support" - depends on AVR32 || ARCH_AT91SAM9260 || ARCH_AT91SAM9263 || ARCH_AT91CAP9 + depends on AVR32 || ARCH_AT91SAM9260 || ARCH_AT91SAM9263 || ARCH_AT91SAM9G20 || ARCH_AT91CAP9 select PHYLIB help The Atmel MACB ethernet interface is found on many AT32 and AT91 diff --git a/drivers/net/arm/etherh.c b/drivers/net/arm/etherh.c index 00081d2b9cd..e9d15eccad0 100644 --- a/drivers/net/arm/etherh.c +++ b/drivers/net/arm/etherh.c @@ -647,7 +647,7 @@ etherh_probe(struct expansion_card *ec, const struct ecard_id *id) struct ei_device *ei_local; struct net_device *dev; struct etherh_priv *eh; - int i, ret; + int ret; DECLARE_MAC_BUF(mac); etherh_banner(); diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c index d5c2d27f3ea..f76b0b6c277 100644 --- a/drivers/net/irda/pxaficp_ir.c +++ b/drivers/net/irda/pxaficp_ir.c @@ -13,16 +13,8 @@ * */ #include <linux/module.h> -#include <linux/types.h> -#include <linux/init.h> -#include <linux/errno.h> #include <linux/netdevice.h> -#include <linux/slab.h> -#include <linux/rtnetlink.h> -#include <linux/interrupt.h> -#include <linux/dma-mapping.h> #include <linux/platform_device.h> -#include <linux/pm.h> #include <linux/clk.h> #include <net/irda/irda.h> @@ -30,17 +22,9 @@ #include <net/irda/wrapper.h> #include <net/irda/irda_device.h> -#include <asm/irq.h> #include <asm/dma.h> -#include <asm/delay.h> -#include <asm/hardware.h> #include <asm/arch/irda.h> #include <asm/arch/pxa-regs.h> -#include <asm/arch/pxa2xx-gpio.h> - -#ifdef CONFIG_MACH_MAINSTONE -#include <asm/arch/mainstone.h> -#endif #define IrSR_RXPL_NEG_IS_ZERO (1<<4) #define IrSR_RXPL_POS_IS_ZERO 0x0 @@ -163,10 +147,6 @@ static int pxa_irda_set_speed(struct pxa_irda *si, int speed) /* set board transceiver to SIR mode */ si->pdata->transceiver_mode(si->dev, IR_SIRMODE); - /* configure GPIO46/47 */ - pxa_gpio_mode(GPIO46_STRXD_MD); - pxa_gpio_mode(GPIO47_STTXD_MD); - /* enable the STUART clock */ pxa_irda_enable_sirclk(si); } @@ -201,10 +181,6 @@ static int pxa_irda_set_speed(struct pxa_irda *si, int speed) /* set board transceiver to FIR mode */ si->pdata->transceiver_mode(si->dev, IR_FIRMODE); - /* configure GPIO46/47 */ - pxa_gpio_mode(GPIO46_ICPRXD_MD); - pxa_gpio_mode(GPIO47_ICPTXD_MD); - /* enable the FICP clock */ pxa_irda_enable_firclk(si); diff --git a/drivers/pcmcia/omap_cf.c b/drivers/pcmcia/omap_cf.c index 46314b42076..569b746b573 100644 --- a/drivers/pcmcia/omap_cf.c +++ b/drivers/pcmcia/omap_cf.c @@ -38,19 +38,19 @@ #define CF_BASE 0xfffe2800 /* status; read after IRQ */ -#define CF_STATUS_REG __REG16(CF_BASE + 0x00) +#define CF_STATUS (CF_BASE + 0x00) # define CF_STATUS_BAD_READ (1 << 2) # define CF_STATUS_BAD_WRITE (1 << 1) # define CF_STATUS_CARD_DETECT (1 << 0) /* which chipselect (CS0..CS3) is used for CF (active low) */ -#define CF_CFG_REG __REG16(CF_BASE + 0x02) +#define CF_CFG (CF_BASE + 0x02) /* card reset */ -#define CF_CONTROL_REG __REG16(CF_BASE + 0x04) +#define CF_CONTROL (CF_BASE + 0x04) # define CF_CONTROL_RESET (1 << 0) -#define omap_cf_present() (!(CF_STATUS_REG & CF_STATUS_CARD_DETECT)) +#define omap_cf_present() (!(omap_readw(CF_STATUS) & CF_STATUS_CARD_DETECT)) /*--------------------------------------------------------------------------*/ @@ -139,11 +139,11 @@ omap_cf_set_socket(struct pcmcia_socket *sock, struct socket_state_t *s) return -EINVAL; } - control = CF_CONTROL_REG; + control = omap_readw(CF_CONTROL); if (s->flags & SS_RESET) - CF_CONTROL_REG = CF_CONTROL_RESET; + omap_writew(CF_CONTROL_RESET, CF_CONTROL); else - CF_CONTROL_REG = 0; + omap_writew(0, CF_CONTROL); pr_debug("%s: Vcc %d, io_irq %d, flags %04x csc %04x\n", driver_name, s->Vcc, s->io_irq, s->flags, s->csc_mask); @@ -270,7 +270,7 @@ static int __init omap_cf_probe(struct platform_device *pdev) omap_cfg_reg(V10_1610_CF_IREQ); omap_cfg_reg(W10_1610_CF_RESET); - CF_CFG_REG = ~(1 << seg); + omap_writew(~(1 << seg), CF_CFG); pr_info("%s: cs%d on irq %d\n", driver_name, seg, irq); @@ -279,14 +279,15 @@ static int __init omap_cf_probe(struct platform_device *pdev) * CF/PCMCIA variants... */ pr_debug("%s: cs%d, previous ccs %08x acs %08x\n", driver_name, - seg, EMIFS_CCS(seg), EMIFS_ACS(seg)); - EMIFS_CCS(seg) = 0x0004a1b3; /* synch mode 4 etc */ - EMIFS_ACS(seg) = 0x00000000; /* OE hold/setup */ + seg, omap_readl(EMIFS_CCS(seg)), omap_readl(EMIFS_ACS(seg))); + omap_writel(0x0004a1b3, EMIFS_CCS(seg)); /* synch mode 4 etc */ + omap_writel(0x00000000, EMIFS_ACS(seg)); /* OE hold/setup */ /* CF uses armxor_ck, which is "always" available */ pr_debug("%s: sts %04x cfg %04x control %04x %s\n", driver_name, - CF_STATUS_REG, CF_CFG_REG, CF_CONTROL_REG, + omap_readw(CF_STATUS), omap_readw(CF_CFG), + omap_readw(CF_CONTROL), omap_cf_present() ? "present" : "(not present)"); cf->socket.owner = THIS_MODULE; diff --git a/drivers/pcmcia/pxa2xx_cm_x270.c b/drivers/pcmcia/pxa2xx_cm_x270.c index e7ab060ff11..f123fce65f2 100644 --- a/drivers/pcmcia/pxa2xx_cm_x270.c +++ b/drivers/pcmcia/pxa2xx_cm_x270.c @@ -18,6 +18,7 @@ #include <pcmcia/ss.h> #include <asm/hardware.h> +#include <asm/mach-types.h> #include <asm/arch/pxa-regs.h> #include <asm/arch/pxa2xx-gpio.h> @@ -130,7 +131,7 @@ static void cmx270_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) } -static struct pcmcia_low_level cmx270_pcmcia_ops = { +static struct pcmcia_low_level cmx270_pcmcia_ops __initdata = { .owner = THIS_MODULE, .hw_init = cmx270_pcmcia_hw_init, .hw_shutdown = cmx270_pcmcia_shutdown, @@ -147,15 +148,21 @@ static int __init cmx270_pcmcia_init(void) { int ret; + if (!machine_is_armcore()) + return -ENODEV; + cmx270_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1); if (!cmx270_pcmcia_device) return -ENOMEM; - cmx270_pcmcia_device->dev.platform_data = &cmx270_pcmcia_ops; + ret = platform_device_add_data(cmx270_pcmcia_device, &cmx270_pcmcia_ops, + sizeof(cmx270_pcmcia_ops)); - printk(KERN_INFO "Registering cm-x270 PCMCIA interface.\n"); - ret = platform_device_add(cmx270_pcmcia_device); + if (ret == 0) { + printk(KERN_INFO "Registering cm-x270 PCMCIA interface.\n"); + ret = platform_device_add(cmx270_pcmcia_device); + } if (ret) platform_device_put(cmx270_pcmcia_device); diff --git a/drivers/pcmcia/pxa2xx_mainstone.c b/drivers/pcmcia/pxa2xx_mainstone.c index 145b85e0f02..92d1cc33808 100644 --- a/drivers/pcmcia/pxa2xx_mainstone.c +++ b/drivers/pcmcia/pxa2xx_mainstone.c @@ -22,6 +22,7 @@ #include <pcmcia/ss.h> #include <asm/hardware.h> +#include <asm/mach-types.h> #include <asm/irq.h> #include <asm/arch/pxa-regs.h> @@ -136,7 +137,7 @@ static void mst_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) { } -static struct pcmcia_low_level mst_pcmcia_ops = { +static struct pcmcia_low_level mst_pcmcia_ops __initdata = { .owner = THIS_MODULE, .hw_init = mst_pcmcia_hw_init, .hw_shutdown = mst_pcmcia_hw_shutdown, @@ -153,13 +154,17 @@ static int __init mst_pcmcia_init(void) { int ret; + if (!machine_is_mainstone()) + return -ENODEV; + mst_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1); if (!mst_pcmcia_device) return -ENOMEM; - mst_pcmcia_device->dev.platform_data = &mst_pcmcia_ops; - - ret = platform_device_add(mst_pcmcia_device); + ret = platform_device_add_data(mst_pcmcia_device, &mst_pcmcia_ops, + sizeof(mst_pcmcia_ops)); + if (ret == 0) + ret = platform_device_add(mst_pcmcia_device); if (ret) platform_device_put(mst_pcmcia_device); diff --git a/drivers/pcmcia/pxa2xx_sharpsl.c b/drivers/pcmcia/pxa2xx_sharpsl.c index d5c33bd78d6..d71f93d4583 100644 --- a/drivers/pcmcia/pxa2xx_sharpsl.c +++ b/drivers/pcmcia/pxa2xx_sharpsl.c @@ -222,7 +222,7 @@ static void sharpsl_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) sharpsl_pcmcia_init_reset(skt); } -static struct pcmcia_low_level sharpsl_pcmcia_ops = { +static struct pcmcia_low_level sharpsl_pcmcia_ops __initdata = { .owner = THIS_MODULE, .hw_init = sharpsl_pcmcia_hw_init, .hw_shutdown = sharpsl_pcmcia_hw_shutdown, @@ -261,10 +261,12 @@ static int __init sharpsl_pcmcia_init(void) if (!sharpsl_pcmcia_device) return -ENOMEM; - sharpsl_pcmcia_device->dev.platform_data = &sharpsl_pcmcia_ops; - sharpsl_pcmcia_device->dev.parent = platform_scoop_config->devs[0].dev; - - ret = platform_device_add(sharpsl_pcmcia_device); + ret = platform_device_add_data(sharpsl_pcmcia_device, + &sharpsl_pcmcia_ops, sizeof(sharpsl_pcmcia_ops)); + if (ret == 0) { + sharpsl_pcmcia_device->dev.parent = platform_scoop_config->devs[0].dev; + ret = platform_device_add(sharpsl_pcmcia_device); + } if (ret) platform_device_put(sharpsl_pcmcia_device); diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 4949dc4859b..fc85bf2e4a9 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -469,6 +469,16 @@ config RTC_DRV_VR41XX To compile this driver as a module, choose M here: the module will be called rtc-vr41xx. +config RTC_DRV_PL030 + tristate "ARM AMBA PL030 RTC" + depends on ARM_AMBA + help + If you say Y here you will get access to ARM AMBA + PrimeCell PL030 RTC found on certain ARM SOCs. + + To compile this driver as a module, choose M here: the + module will be called rtc-pl030. + config RTC_DRV_PL031 tristate "ARM AMBA PL031 RTC" depends on ARM_AMBA @@ -495,12 +505,13 @@ config RTC_DRV_AT91RM9200 this is powered by the backup power supply. config RTC_DRV_AT91SAM9 - tristate "AT91SAM9x" + tristate "AT91SAM9x/AT91CAP9" depends on ARCH_AT91 && !(ARCH_AT91RM9200 || ARCH_AT91X40) help - RTC driver for the Atmel AT91SAM9x internal RTT (Real Time Timer). - These timers are powered by the backup power supply (such as a - small coin cell battery), but do not need to be used as RTCs. + RTC driver for the Atmel AT91SAM9x and AT91CAP9 internal RTT + (Real Time Timer). These timers are powered by the backup power + supply (such as a small coin cell battery), but do not need to + be used as RTCs. (On AT91SAM9rl chips you probably want to use the dedicated RTC module and leave the RTT available for other uses.) diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index b6e14d51670..b5d9d67df88 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -41,6 +41,7 @@ obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o +obj-$(CONFIG_RTC_DRV_PL030) += rtc-pl030.o obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o obj-$(CONFIG_RTC_DRV_PPC) += rtc-ppc.o obj-$(CONFIG_RTC_DRV_R9701) += rtc-r9701.o diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c index 39e64ab1ecb..9c3db934cc2 100644 --- a/drivers/rtc/rtc-at91rm9200.c +++ b/drivers/rtc/rtc-at91rm9200.c @@ -29,10 +29,6 @@ #include <linux/completion.h> #include <asm/uaccess.h> -#include <asm/rtc.h> - -#include <asm/mach/time.h> - #include <asm/arch/at91_rtc.h> diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c index 38d8742a4bd..f0246ef413a 100644 --- a/drivers/rtc/rtc-at91sam9.c +++ b/drivers/rtc/rtc-at91sam9.c @@ -19,7 +19,6 @@ #include <linux/interrupt.h> #include <linux/ioctl.h> -#include <asm/mach/time.h> #include <asm/arch/board.h> #include <asm/arch/at91_rtt.h> diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index 58f81c77494..eb23d8423f4 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c @@ -22,7 +22,6 @@ #include <linux/platform_device.h> #include <asm/io.h> -#include <asm/mach/time.h> /* The OMAP1 RTC is a year/month/day/hours/minutes/seconds BCD clock diff --git a/drivers/rtc/rtc-pl030.c b/drivers/rtc/rtc-pl030.c new file mode 100644 index 00000000000..8448eeb9d67 --- /dev/null +++ b/drivers/rtc/rtc-pl030.c @@ -0,0 +1,217 @@ +/* + * linux/drivers/rtc/rtc-pl030.c + * + * Copyright (C) 2000-2001 Deep Blue Solutions Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include <linux/module.h> +#include <linux/rtc.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/amba/bus.h> +#include <linux/io.h> + +#define RTC_DR (0) +#define RTC_MR (4) +#define RTC_STAT (8) +#define RTC_EOI (8) +#define RTC_LR (12) +#define RTC_CR (16) +#define RTC_CR_MIE (1 << 0) + +struct pl030_rtc { + struct rtc_device *rtc; + void __iomem *base; +}; + +static irqreturn_t pl030_interrupt(int irq, void *dev_id) +{ + struct pl030_rtc *rtc = dev_id; + writel(0, rtc->base + RTC_EOI); + return IRQ_HANDLED; +} + +static int pl030_open(struct device *dev) +{ + return 0; +} + +static void pl030_release(struct device *dev) +{ +} + +static int pl030_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) +{ + return -ENOIOCTLCMD; +} + +static int pl030_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + struct pl030_rtc *rtc = dev_get_drvdata(dev); + + rtc_time_to_tm(readl(rtc->base + RTC_MR), &alrm->time); + return 0; +} + +static int pl030_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + struct pl030_rtc *rtc = dev_get_drvdata(dev); + unsigned long time; + int ret; + + /* + * At the moment, we can only deal with non-wildcarded alarm times. + */ + ret = rtc_valid_tm(&alrm->time); + if (ret == 0) + ret = rtc_tm_to_time(&alrm->time, &time); + if (ret == 0) + writel(time, rtc->base + RTC_MR); + return ret; +} + +static int pl030_read_time(struct device *dev, struct rtc_time *tm) +{ + struct pl030_rtc *rtc = dev_get_drvdata(dev); + + rtc_time_to_tm(readl(rtc->base + RTC_DR), tm); + + return 0; +} + +/* + * Set the RTC time. Unfortunately, we can't accurately set + * the point at which the counter updates. + * + * Also, since RTC_LR is transferred to RTC_CR on next rising + * edge of the 1Hz clock, we must write the time one second + * in advance. + */ +static int pl030_set_time(struct device *dev, struct rtc_time *tm) +{ + struct pl030_rtc *rtc = dev_get_drvdata(dev); + unsigned long time; + int ret; + + ret = rtc_tm_to_time(tm, &time); + if (ret == 0) + writel(time + 1, rtc->base + RTC_LR); + + return ret; +} + +static const struct rtc_class_ops pl030_ops = { + .open = pl030_open, + .release = pl030_release, + .ioctl = pl030_ioctl, + .read_time = pl030_read_time, + .set_time = pl030_set_time, + .read_alarm = pl030_read_alarm, + .set_alarm = pl030_set_alarm, +}; + +static int pl030_probe(struct amba_device *dev, void *id) +{ + struct pl030_rtc *rtc; + int ret; + + ret = amba_request_regions(dev, NULL); + if (ret) + goto err_req; + + rtc = kmalloc(sizeof(*rtc), GFP_KERNEL); + if (!rtc) { + ret = -ENOMEM; + goto err_rtc; + } + + rtc->base = ioremap(dev->res.start, SZ_4K); + if (!rtc->base) { + ret = -ENOMEM; + goto err_map; + } + + __raw_writel(0, rtc->base + RTC_CR); + __raw_writel(0, rtc->base + RTC_EOI); + + amba_set_drvdata(dev, rtc); + + ret = request_irq(dev->irq[0], pl030_interrupt, IRQF_DISABLED, + "rtc-pl030", rtc); + if (ret) + goto err_irq; + + rtc->rtc = rtc_device_register("pl030", &dev->dev, &pl030_ops, + THIS_MODULE); + if (IS_ERR(rtc->rtc)) { + ret = PTR_ERR(rtc->rtc); + goto err_reg; + } + + return 0; + + err_reg: + free_irq(dev->irq[0], rtc); + err_irq: + iounmap(rtc->base); + err_map: + kfree(rtc); + err_rtc: + amba_release_regions(dev); + err_req: + return ret; +} + +static int pl030_remove(struct amba_device *dev) +{ + struct pl030_rtc *rtc = amba_get_drvdata(dev); + + amba_set_drvdata(dev, NULL); + + writel(0, rtc->base + RTC_CR); + + free_irq(dev->irq[0], rtc); + rtc_device_unregister(rtc->rtc); + iounmap(rtc->base); + kfree(rtc); + amba_release_regions(dev); + + return 0; +} + +static struct amba_id pl030_ids[] = { + { + .id = 0x00041030, + .mask = 0x000fffff, + }, + { 0, 0 }, +}; + +static struct amba_driver pl030_driver = { + .drv = { + .name = "rtc-pl030", + }, + .probe = pl030_probe, + .remove = pl030_remove, + .id_table = pl030_ids, +}; + +static int __init pl030_init(void) +{ + return amba_driver_register(&pl030_driver); +} + +static void __exit pl030_exit(void) +{ + amba_driver_unregister(&pl030_driver); +} + +module_init(pl030_init); +module_exit(pl030_exit); + +MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>"); +MODULE_DESCRIPTION("ARM AMBA PL030 RTC Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c index 2fd49edcc71..08b4610ec5a 100644 --- a/drivers/rtc/rtc-pl031.c +++ b/drivers/rtc/rtc-pl031.c @@ -12,23 +12,12 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ - -#include <linux/platform_device.h> #include <linux/module.h> #include <linux/rtc.h> #include <linux/init.h> -#include <linux/fs.h> #include <linux/interrupt.h> -#include <linux/string.h> -#include <linux/pm.h> -#include <linux/bitops.h> - #include <linux/amba/bus.h> - -#include <asm/io.h> -#include <asm/hardware.h> -#include <asm/irq.h> -#include <asm/rtc.h> +#include <linux/io.h> /* * Register definitions @@ -142,13 +131,12 @@ static int pl031_remove(struct amba_device *adev) { struct pl031_local *ldata = dev_get_drvdata(&adev->dev); - if (ldata) { - dev_set_drvdata(&adev->dev, NULL); - free_irq(adev->irq[0], ldata->rtc); - rtc_device_unregister(ldata->rtc); - iounmap(ldata->base); - kfree(ldata); - } + amba_set_drvdata(adev, NULL); + free_irq(adev->irq[0], ldata->rtc); + rtc_device_unregister(ldata->rtc); + iounmap(ldata->base); + kfree(ldata); + amba_release_regions(adev); return 0; } @@ -158,13 +146,15 @@ static int pl031_probe(struct amba_device *adev, void *id) int ret; struct pl031_local *ldata; + ret = amba_request_regions(adev, NULL); + if (ret) + goto err_req; ldata = kmalloc(sizeof(struct pl031_local), GFP_KERNEL); if (!ldata) { ret = -ENOMEM; goto out; } - dev_set_drvdata(&adev->dev, ldata); ldata->base = ioremap(adev->res.start, adev->res.end - adev->res.start + 1); @@ -173,6 +163,8 @@ static int pl031_probe(struct amba_device *adev, void *id) goto out_no_remap; } + amba_set_drvdata(adev, ldata); + if (request_irq(adev->irq[0], pl031_interrupt, IRQF_DISABLED, "rtc-pl031", ldata->rtc)) { ret = -EIO; @@ -192,10 +184,12 @@ out_no_rtc: free_irq(adev->irq[0], ldata->rtc); out_no_irq: iounmap(ldata->base); + amba_set_drvdata(adev, NULL); out_no_remap: - dev_set_drvdata(&adev->dev, NULL); kfree(ldata); out: + amba_release_regions(adev); +err_req: return ret; } diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index f26e0cad8f1..fed86e507fd 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c @@ -26,10 +26,6 @@ #include <asm/uaccess.h> #include <asm/io.h> #include <asm/irq.h> -#include <asm/rtc.h> - -#include <asm/mach/time.h> - #include <asm/plat-s3c/regs-rtc.h> /* I have yet to find an S3C implementation with more than one diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c index 67421b0d3a7..f47294c6014 100644 --- a/drivers/rtc/rtc-sa1100.c +++ b/drivers/rtc/rtc-sa1100.c @@ -33,7 +33,6 @@ #include <asm/hardware.h> #include <asm/irq.h> -#include <asm/rtc.h> #ifdef CONFIG_ARCH_PXA #include <asm/arch/pxa-regs.h> @@ -47,6 +46,42 @@ static unsigned long rtc_freq = 1024; static struct rtc_time rtc_alarm; static DEFINE_SPINLOCK(sa1100_rtc_lock); +static inline int rtc_periodic_alarm(struct rtc_time *tm) +{ + return (tm->tm_year == -1) || + ((unsigned)tm->tm_mon >= 12) || + ((unsigned)(tm->tm_mday - 1) >= 31) || + ((unsigned)tm->tm_hour > 23) || + ((unsigned)tm->tm_min > 59) || + ((unsigned)tm->tm_sec > 59); +} + +/* + * Calculate the next alarm time given the requested alarm time mask + * and the current time. + */ +static void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now, struct rtc_time *alrm) +{ + unsigned long next_time; + unsigned long now_time; + + next->tm_year = now->tm_year; + next->tm_mon = now->tm_mon; + next->tm_mday = now->tm_mday; + next->tm_hour = alrm->tm_hour; + next->tm_min = alrm->tm_min; + next->tm_sec = alrm->tm_sec; + + rtc_tm_to_time(now, &now_time); + rtc_tm_to_time(next, &next_time); + + if (next_time < now_time) { + /* Advance one day */ + next_time += 60 * 60 * 24; + rtc_time_to_tm(next_time, next); + } +} + static int rtc_update_alarm(struct rtc_time *alrm) { struct rtc_time alarm_tm, now_tm; diff --git a/drivers/scsi/arm/Kconfig b/drivers/scsi/arm/Kconfig index 7236143941f..a8587f1f5e7 100644 --- a/drivers/scsi/arm/Kconfig +++ b/drivers/scsi/arm/Kconfig @@ -3,7 +3,7 @@ # config SCSI_ACORNSCSI_3 tristate "Acorn SCSI card (aka30) support" - depends on ARCH_ACORN && SCSI && BROKEN + depends on ARCH_ACORN && SCSI select SCSI_SPI_ATTRS help This enables support for the Acorn SCSI card (aka30). If you have an diff --git a/drivers/scsi/arm/acornscsi-io.S b/drivers/scsi/arm/acornscsi-io.S index 93467e6ac92..5cebe310526 100644 --- a/drivers/scsi/arm/acornscsi-io.S +++ b/drivers/scsi/arm/acornscsi-io.S @@ -10,17 +10,10 @@ #include <asm/assembler.h> #include <asm/hardware.h> -#if (IO_BASE == (PCIO_BASE & 0xff000000)) -#define ADDR(off,reg) \ - tst off, $0x80000000 ;\ - mov reg, $IO_BASE ;\ - orreq reg, reg, $(PCIO_BASE & 0x00ff0000) -#else -#define ADDR(off,reg) \ - tst off, $0x80000000 ;\ - movne reg, $IO_BASE ;\ - moveq reg, $(PCIO_BASE & 0xff000000) ;\ - orreq reg, reg, $(PCIO_BASE & 0x00ff0000) +#if defined(__APCS_32__) +#define LOADREGS(t,r,l...) ldm##t r, l +#elif defined(__APCS_26__) +#define LOADREGS(t,r,l...) ldm##t r, l##^ #endif @ Purpose: transfer a block of data from the acorn scsi card to memory diff --git a/drivers/scsi/arm/acornscsi.c b/drivers/scsi/arm/acornscsi.c index 8e53f02cc31..918ccf81875 100644 --- a/drivers/scsi/arm/acornscsi.c +++ b/drivers/scsi/arm/acornscsi.c @@ -123,12 +123,6 @@ #define DBG(cmd,xxx...) xxx #endif -#ifndef STRINGIFY -#define STRINGIFY(x) #x -#endif -#define STRx(x) STRINGIFY(x) -#define NO_WRITE_STR STRx(NO_WRITE) - #include <linux/module.h> #include <linux/kernel.h> #include <linux/string.h> @@ -141,9 +135,10 @@ #include <linux/interrupt.h> #include <linux/init.h> #include <linux/bitops.h> +#include <linux/stringify.h> +#include <linux/io.h> #include <asm/system.h> -#include <asm/io.h> #include <asm/ecard.h> #include "../scsi.h" @@ -203,44 +198,46 @@ static void acornscsi_abortcmd(AS_Host *host, unsigned char tag); * Miscellaneous */ -static inline void -sbic_arm_write(unsigned int io_port, int reg, int value) +/* Offsets from MEMC base */ +#define SBIC_REGIDX 0x2000 +#define SBIC_REGVAL 0x2004 +#define DMAC_OFFSET 0x3000 + +/* Offsets from FAST IOC base */ +#define INT_REG 0x2000 +#define PAGE_REG 0x3000 + +static inline void sbic_arm_write(AS_Host *host, unsigned int reg, unsigned int value) { - __raw_writeb(reg, io_port); - __raw_writeb(value, io_port + 4); + writeb(reg, host->base + SBIC_REGIDX); + writeb(value, host->base + SBIC_REGVAL); } -#define sbic_arm_writenext(io,val) \ - __raw_writeb((val), (io) + 4) - -static inline -int sbic_arm_read(unsigned int io_port, int reg) +static inline int sbic_arm_read(AS_Host *host, unsigned int reg) { if(reg == SBIC_ASR) - return __raw_readl(io_port) & 255; - __raw_writeb(reg, io_port); - return __raw_readl(io_port + 4) & 255; + return readl(host->base + SBIC_REGIDX) & 255; + writeb(reg, host->base + SBIC_REGIDX); + return readl(host->base + SBIC_REGVAL) & 255; } -#define sbic_arm_readnext(io) \ - __raw_readb((io) + 4) +#define sbic_arm_writenext(host, val) writeb((val), (host)->base + SBIC_REGVAL) +#define sbic_arm_readnext(host) readb((host)->base + SBIC_REGVAL) #ifdef USE_DMAC -#define dmac_read(io_port,reg) \ - inb((io_port) + (reg)) +#define dmac_read(host,reg) \ + readb((host)->base + DMAC_OFFSET + ((reg) << 2)) -#define dmac_write(io_port,reg,value) \ - ({ outb((value), (io_port) + (reg)); }) +#define dmac_write(host,reg,value) \ + ({ writeb((value), (host)->base + DMAC_OFFSET + ((reg) << 2)); }) -#define dmac_clearintr(io_port) \ - ({ outb(0, (io_port)); }) +#define dmac_clearintr(host) writeb(0, (host)->fast + INT_REG) -static inline -unsigned int dmac_address(unsigned int io_port) +static inline unsigned int dmac_address(AS_Host *host) { - return dmac_read(io_port, DMAC_TXADRHI) << 16 | - dmac_read(io_port, DMAC_TXADRMD) << 8 | - dmac_read(io_port, DMAC_TXADRLO); + return dmac_read(host, DMAC_TXADRHI) << 16 | + dmac_read(host, DMAC_TXADRMD) << 8 | + dmac_read(host, DMAC_TXADRLO); } static @@ -248,15 +245,15 @@ void acornscsi_dumpdma(AS_Host *host, char *where) { unsigned int mode, addr, len; - mode = dmac_read(host->dma.io_port, DMAC_MODECON); - addr = dmac_address(host->dma.io_port); - len = dmac_read(host->dma.io_port, DMAC_TXCNTHI) << 8 | - dmac_read(host->dma.io_port, DMAC_TXCNTLO); + mode = dmac_read(host, DMAC_MODECON); + addr = dmac_address(host); + len = dmac_read(host, DMAC_TXCNTHI) << 8 | + dmac_read(host, DMAC_TXCNTLO); printk("scsi%d: %s: DMAC %02x @%06x+%04x msk %02x, ", host->host->host_no, where, mode, addr, (len + 1) & 0xffff, - dmac_read(host->dma.io_port, DMAC_MASKREG)); + dmac_read(host, DMAC_MASKREG)); printk("DMA @%06x, ", host->dma.start_addr); printk("BH @%p +%04x, ", host->scsi.SCp.ptr, @@ -272,9 +269,9 @@ unsigned long acornscsi_sbic_xfcount(AS_Host *host) { unsigned long length; - length = sbic_arm_read(host->scsi.io_port, SBIC_TRANSCNTH) << 16; - length |= sbic_arm_readnext(host->scsi.io_port) << 8; - length |= sbic_arm_readnext(host->scsi.io_port); + length = sbic_arm_read(host, SBIC_TRANSCNTH) << 16; + length |= sbic_arm_readnext(host) << 8; + length |= sbic_arm_readnext(host); return length; } @@ -285,7 +282,7 @@ acornscsi_sbic_wait(AS_Host *host, int stat_mask, int stat, int timeout, char *m int asr; do { - asr = sbic_arm_read(host->scsi.io_port, SBIC_ASR); + asr = sbic_arm_read(host, SBIC_ASR); if ((asr & stat_mask) == stat) return 0; @@ -304,7 +301,7 @@ int acornscsi_sbic_issuecmd(AS_Host *host, int command) if (acornscsi_sbic_wait(host, ASR_CIP, 0, 1000, "issuing command")) return -1; - sbic_arm_write(host->scsi.io_port, SBIC_CMND, command); + sbic_arm_write(host, SBIC_CMND, command); return 0; } @@ -331,20 +328,20 @@ void acornscsi_resetcard(AS_Host *host) /* assert reset line */ host->card.page_reg = 0x80; - outb(host->card.page_reg, host->card.io_page); + writeb(host->card.page_reg, host->fast + PAGE_REG); /* wait 3 cs. SCSI standard says 25ms. */ acornscsi_csdelay(3); host->card.page_reg = 0; - outb(host->card.page_reg, host->card.io_page); + writeb(host->card.page_reg, host->fast + PAGE_REG); /* * Should get a reset from the card */ timeout = 1000; do { - if (inb(host->card.io_intr) & 8) + if (readb(host->fast + INT_REG) & 8) break; udelay(1); } while (--timeout); @@ -353,19 +350,19 @@ void acornscsi_resetcard(AS_Host *host) printk("scsi%d: timeout while resetting card\n", host->host->host_no); - sbic_arm_read(host->scsi.io_port, SBIC_ASR); - sbic_arm_read(host->scsi.io_port, SBIC_SSR); + sbic_arm_read(host, SBIC_ASR); + sbic_arm_read(host, SBIC_SSR); /* setup sbic - WD33C93A */ - sbic_arm_write(host->scsi.io_port, SBIC_OWNID, OWNID_EAF | host->host->this_id); - sbic_arm_write(host->scsi.io_port, SBIC_CMND, CMND_RESET); + sbic_arm_write(host, SBIC_OWNID, OWNID_EAF | host->host->this_id); + sbic_arm_write(host, SBIC_CMND, CMND_RESET); /* * Command should cause a reset interrupt */ timeout = 1000; do { - if (inb(host->card.io_intr) & 8) + if (readb(host->fast + INT_REG) & 8) break; udelay(1); } while (--timeout); @@ -374,26 +371,26 @@ void acornscsi_resetcard(AS_Host *host) printk("scsi%d: timeout while resetting card\n", host->host->host_no); - sbic_arm_read(host->scsi.io_port, SBIC_ASR); - if (sbic_arm_read(host->scsi.io_port, SBIC_SSR) != 0x01) + sbic_arm_read(host, SBIC_ASR); + if (sbic_arm_read(host, SBIC_SSR) != 0x01) printk(KERN_CRIT "scsi%d: WD33C93A didn't give enhanced reset interrupt\n", host->host->host_no); - sbic_arm_write(host->scsi.io_port, SBIC_CTRL, INIT_SBICDMA | CTRL_IDI); - sbic_arm_write(host->scsi.io_port, SBIC_TIMEOUT, TIMEOUT_TIME); - sbic_arm_write(host->scsi.io_port, SBIC_SYNCHTRANSFER, SYNCHTRANSFER_2DBA); - sbic_arm_write(host->scsi.io_port, SBIC_SOURCEID, SOURCEID_ER | SOURCEID_DSP); + sbic_arm_write(host, SBIC_CTRL, INIT_SBICDMA | CTRL_IDI); + sbic_arm_write(host, SBIC_TIMEOUT, TIMEOUT_TIME); + sbic_arm_write(host, SBIC_SYNCHTRANSFER, SYNCHTRANSFER_2DBA); + sbic_arm_write(host, SBIC_SOURCEID, SOURCEID_ER | SOURCEID_DSP); host->card.page_reg = 0x40; - outb(host->card.page_reg, host->card.io_page); + writeb(host->card.page_reg, host->fast + PAGE_REG); /* setup dmac - uPC71071 */ - dmac_write(host->dma.io_port, DMAC_INIT, 0); + dmac_write(host, DMAC_INIT, 0); #ifdef USE_DMAC - dmac_write(host->dma.io_port, DMAC_INIT, INIT_8BIT); - dmac_write(host->dma.io_port, DMAC_CHANNEL, CHANNEL_0); - dmac_write(host->dma.io_port, DMAC_DEVCON0, INIT_DEVCON0); - dmac_write(host->dma.io_port, DMAC_DEVCON1, INIT_DEVCON1); + dmac_write(host, DMAC_INIT, INIT_8BIT); + dmac_write(host, DMAC_CHANNEL, CHANNEL_0); + dmac_write(host, DMAC_DEVCON0, INIT_DEVCON0); + dmac_write(host, DMAC_DEVCON1, INIT_DEVCON1); #endif host->SCpnt = NULL; @@ -741,9 +738,9 @@ intr_ret_t acornscsi_kick(AS_Host *host) * If we have an interrupt pending, then we may have been reselected. * In this case, we don't want to write to the registers */ - if (!(sbic_arm_read(host->scsi.io_port, SBIC_ASR) & (ASR_INT|ASR_BSY|ASR_CIP))) { - sbic_arm_write(host->scsi.io_port, SBIC_DESTID, SCpnt->device->id); - sbic_arm_write(host->scsi.io_port, SBIC_CMND, CMND_SELWITHATN); + if (!(sbic_arm_read(host, SBIC_ASR) & (ASR_INT|ASR_BSY|ASR_CIP))) { + sbic_arm_write(host, SBIC_DESTID, SCpnt->device->id); + sbic_arm_write(host, SBIC_CMND, CMND_SELWITHATN); } /* @@ -807,7 +804,7 @@ static void acornscsi_done(AS_Host *host, struct scsi_cmnd **SCpntp, struct scsi_cmnd *SCpnt = *SCpntp; /* clean up */ - sbic_arm_write(host->scsi.io_port, SBIC_SOURCEID, SOURCEID_ER | SOURCEID_DSP); + sbic_arm_write(host, SBIC_SOURCEID, SOURCEID_ER | SOURCEID_DSP); host->stats.fins += 1; @@ -918,13 +915,13 @@ static void acornscsi_data_read(AS_Host *host, char *ptr, unsigned int start_addr, unsigned int length) { - extern void __acornscsi_in(int port, char *buf, int len); + extern void __acornscsi_in(void __iomem *, char *buf, int len); unsigned int page, offset, len = length; page = (start_addr >> 12); offset = start_addr & ((1 << 12) - 1); - outb((page & 0x3f) | host->card.page_reg, host->card.io_page); + writeb((page & 0x3f) | host->card.page_reg, host->fast + PAGE_REG); while (len > 0) { unsigned int this_len; @@ -934,7 +931,7 @@ void acornscsi_data_read(AS_Host *host, char *ptr, else this_len = len; - __acornscsi_in(host->card.io_ram + (offset << 1), ptr, this_len); + __acornscsi_in(host->base + (offset << 1), ptr, this_len); offset += this_len; ptr += this_len; @@ -943,10 +940,10 @@ void acornscsi_data_read(AS_Host *host, char *ptr, if (offset == (1 << 12)) { offset = 0; page ++; - outb((page & 0x3f) | host->card.page_reg, host->card.io_page); + writeb((page & 0x3f) | host->card.page_reg, host->fast + PAGE_REG); } } - outb(host->card.page_reg, host->card.io_page); + writeb(host->card.page_reg, host->fast + PAGE_REG); } /* @@ -963,13 +960,13 @@ static void acornscsi_data_write(AS_Host *host, char *ptr, unsigned int start_addr, unsigned int length) { - extern void __acornscsi_out(int port, char *buf, int len); + extern void __acornscsi_out(void __iomem *, char *buf, int len); unsigned int page, offset, len = length; page = (start_addr >> 12); offset = start_addr & ((1 << 12) - 1); - outb((page & 0x3f) | host->card.page_reg, host->card.io_page); + writeb((page & 0x3f) | host->card.page_reg, host->fast + PAGE_REG); while (len > 0) { unsigned int this_len; @@ -979,7 +976,7 @@ void acornscsi_data_write(AS_Host *host, char *ptr, else this_len = len; - __acornscsi_out(host->card.io_ram + (offset << 1), ptr, this_len); + __acornscsi_out(host->base + (offset << 1), ptr, this_len); offset += this_len; ptr += this_len; @@ -988,10 +985,10 @@ void acornscsi_data_write(AS_Host *host, char *ptr, if (offset == (1 << 12)) { offset = 0; page ++; - outb((page & 0x3f) | host->card.page_reg, host->card.io_page); + writeb((page & 0x3f) | host->card.page_reg, host->fast + PAGE_REG); } } - outb(host->card.page_reg, host->card.io_page); + writeb(host->card.page_reg, host->fast + PAGE_REG); } /* ========================================================================================= @@ -1008,8 +1005,8 @@ void acornscsi_data_write(AS_Host *host, char *ptr, static inline void acornscsi_dma_stop(AS_Host *host) { - dmac_write(host->dma.io_port, DMAC_MASKREG, MASK_ON); - dmac_clearintr(host->dma.io_intr_clear); + dmac_write(host, DMAC_MASKREG, MASK_ON); + dmac_clearintr(host); #if (DEBUG & DEBUG_DMA) DBG(host->SCpnt, acornscsi_dumpdma(host, "stop")); @@ -1031,7 +1028,7 @@ void acornscsi_dma_setup(AS_Host *host, dmadir_t direction) host->dma.direction = direction; - dmac_write(host->dma.io_port, DMAC_MASKREG, MASK_ON); + dmac_write(host, DMAC_MASKREG, MASK_ON); if (direction == DMA_OUT) { #if (DEBUG & DEBUG_NO_WRITE) @@ -1062,13 +1059,13 @@ void acornscsi_dma_setup(AS_Host *host, dmadir_t direction) length); length -= 1; - dmac_write(host->dma.io_port, DMAC_TXCNTLO, length); - dmac_write(host->dma.io_port, DMAC_TXCNTHI, length >> 8); - dmac_write(host->dma.io_port, DMAC_TXADRLO, address); - dmac_write(host->dma.io_port, DMAC_TXADRMD, address >> 8); - dmac_write(host->dma.io_port, DMAC_TXADRHI, 0); - dmac_write(host->dma.io_port, DMAC_MODECON, mode); - dmac_write(host->dma.io_port, DMAC_MASKREG, MASK_OFF); + dmac_write(host, DMAC_TXCNTLO, length); + dmac_write(host, DMAC_TXCNTHI, length >> 8); + dmac_write(host, DMAC_TXADRLO, address); + dmac_write(host, DMAC_TXADRMD, address >> 8); + dmac_write(host, DMAC_TXADRHI, 0); + dmac_write(host, DMAC_MODECON, mode); + dmac_write(host, DMAC_MASKREG, MASK_OFF); #if (DEBUG & DEBUG_DMA) DBG(host->SCpnt, acornscsi_dumpdma(host, "strt")); @@ -1088,8 +1085,8 @@ void acornscsi_dma_setup(AS_Host *host, dmadir_t direction) static void acornscsi_dma_cleanup(AS_Host *host) { - dmac_write(host->dma.io_port, DMAC_MASKREG, MASK_ON); - dmac_clearintr(host->dma.io_intr_clear); + dmac_write(host, DMAC_MASKREG, MASK_ON); + dmac_clearintr(host); /* * Check for a pending transfer @@ -1116,7 +1113,7 @@ void acornscsi_dma_cleanup(AS_Host *host) /* * Calculate number of bytes transferred from DMA. */ - transferred = dmac_address(host->dma.io_port) - host->dma.start_addr; + transferred = dmac_address(host) - host->dma.start_addr; host->dma.transferred += transferred; if (host->dma.direction == DMA_IN) @@ -1152,13 +1149,13 @@ void acornscsi_dma_intr(AS_Host *host) DBG(host->SCpnt, acornscsi_dumpdma(host, "inti")); #endif - dmac_write(host->dma.io_port, DMAC_MASKREG, MASK_ON); - dmac_clearintr(host->dma.io_intr_clear); + dmac_write(host, DMAC_MASKREG, MASK_ON); + dmac_clearintr(host); /* * Calculate amount transferred via DMA */ - transferred = dmac_address(host->dma.io_port) - host->dma.start_addr; + transferred = dmac_address(host) - host->dma.start_addr; host->dma.transferred += transferred; /* @@ -1190,12 +1187,12 @@ void acornscsi_dma_intr(AS_Host *host) length); length -= 1; - dmac_write(host->dma.io_port, DMAC_TXCNTLO, length); - dmac_write(host->dma.io_port, DMAC_TXCNTHI, length >> 8); - dmac_write(host->dma.io_port, DMAC_TXADRLO, address); - dmac_write(host->dma.io_port, DMAC_TXADRMD, address >> 8); - dmac_write(host->dma.io_port, DMAC_TXADRHI, 0); - dmac_write(host->dma.io_port, DMAC_MASKREG, MASK_OFF); + dmac_write(host, DMAC_TXCNTLO, length); + dmac_write(host, DMAC_TXCNTHI, length >> 8); + dmac_write(host, DMAC_TXADRLO, address); + dmac_write(host, DMAC_TXADRMD, address >> 8); + dmac_write(host, DMAC_TXADRHI, 0); + dmac_write(host, DMAC_MASKREG, MASK_OFF); #if (DEBUG & DEBUG_DMA) DBG(host->SCpnt, acornscsi_dumpdma(host, "into")); @@ -1209,15 +1206,15 @@ void acornscsi_dma_intr(AS_Host *host) * attention condition. We continue giving one byte until * the device recognises the attention. */ - if (dmac_read(host->dma.io_port, DMAC_STATUS) & STATUS_RQ0) { + if (dmac_read(host, DMAC_STATUS) & STATUS_RQ0) { acornscsi_abortcmd(host, host->SCpnt->tag); - dmac_write(host->dma.io_port, DMAC_TXCNTLO, 0); - dmac_write(host->dma.io_port, DMAC_TXCNTHI, 0); - dmac_write(host->dma.io_port, DMAC_TXADRLO, 0); - dmac_write(host->dma.io_port, DMAC_TXADRMD, 0); - dmac_write(host->dma.io_port, DMAC_TXADRHI, 0); - dmac_write(host->dma.io_port, DMAC_MASKREG, MASK_OFF); + dmac_write(host, DMAC_TXCNTLO, 0); + dmac_write(host, DMAC_TXCNTHI, 0); + dmac_write(host, DMAC_TXADRLO, 0); + dmac_write(host, DMAC_TXADRMD, 0); + dmac_write(host, DMAC_TXADRHI, 0); + dmac_write(host, DMAC_MASKREG, MASK_OFF); } #endif } @@ -1271,9 +1268,9 @@ void acornscsi_dma_adjust(AS_Host *host) host->dma.xfer_setup = 0; else { transferred += host->dma.start_addr; - dmac_write(host->dma.io_port, DMAC_TXADRLO, transferred); - dmac_write(host->dma.io_port, DMAC_TXADRMD, transferred >> 8); - dmac_write(host->dma.io_port, DMAC_TXADRHI, transferred >> 16); + dmac_write(host, DMAC_TXADRLO, transferred); + dmac_write(host, DMAC_TXADRMD, transferred >> 8); + dmac_write(host, DMAC_TXADRHI, transferred >> 16); #if (DEBUG & (DEBUG_DMA|DEBUG_WRITE)) DBG(host->SCpnt, acornscsi_dumpdma(host, "adjo")); #endif @@ -1292,12 +1289,12 @@ acornscsi_write_pio(AS_Host *host, char *bytes, int *ptr, int len, unsigned int int my_ptr = *ptr; while (my_ptr < len) { - asr = sbic_arm_read(host->scsi.io_port, SBIC_ASR); + asr = sbic_arm_read(host, SBIC_ASR); if (asr & ASR_DBR) { timeout = max_timeout; - sbic_arm_write(host->scsi.io_port, SBIC_DATA, bytes[my_ptr++]); + sbic_arm_write(host, SBIC_DATA, bytes[my_ptr++]); } else if (asr & ASR_INT) break; else if (--timeout == 0) @@ -1320,9 +1317,9 @@ acornscsi_sendcommand(AS_Host *host) { struct scsi_cmnd *SCpnt = host->SCpnt; - sbic_arm_write(host->scsi.io_port, SBIC_TRANSCNTH, 0); - sbic_arm_writenext(host->scsi.io_port, 0); - sbic_arm_writenext(host->scsi.io_port, SCpnt->cmd_len - host->scsi.SCp.sent_command); + sbic_arm_write(host, SBIC_TRANSCNTH, 0); + sbic_arm_writenext(host, 0); + sbic_arm_writenext(host, SCpnt->cmd_len - host->scsi.SCp.sent_command); acornscsi_sbic_issuecmd(host, CMND_XFERINFO); @@ -1351,7 +1348,7 @@ void acornscsi_sendmessage(AS_Host *host) acornscsi_sbic_wait(host, ASR_DBR, ASR_DBR, 1000, "sending message 1"); - sbic_arm_write(host->scsi.io_port, SBIC_DATA, NOP); + sbic_arm_write(host, SBIC_DATA, NOP); host->scsi.last_message = NOP; #if (DEBUG & DEBUG_MESSAGES) @@ -1365,7 +1362,7 @@ void acornscsi_sendmessage(AS_Host *host) acornscsi_sbic_wait(host, ASR_DBR, ASR_DBR, 1000, "sending message 2"); - sbic_arm_write(host->scsi.io_port, SBIC_DATA, msg->msg[0]); + sbic_arm_write(host, SBIC_DATA, msg->msg[0]); host->scsi.last_message = msg->msg[0]; #if (DEBUG & DEBUG_MESSAGES) @@ -1382,9 +1379,9 @@ void acornscsi_sendmessage(AS_Host *host) * initiator. This provides an interlock so that the * initiator can determine which message byte is rejected. */ - sbic_arm_write(host->scsi.io_port, SBIC_TRANSCNTH, 0); - sbic_arm_writenext(host->scsi.io_port, 0); - sbic_arm_writenext(host->scsi.io_port, message_length); + sbic_arm_write(host, SBIC_TRANSCNTH, 0); + sbic_arm_writenext(host, 0); + sbic_arm_writenext(host, message_length); acornscsi_sbic_issuecmd(host, CMND_XFERINFO); msgnr = 0; @@ -1421,7 +1418,7 @@ void acornscsi_readstatusbyte(AS_Host *host) { acornscsi_sbic_issuecmd(host, CMND_XFERINFO|CMND_SBT); acornscsi_sbic_wait(host, ASR_DBR, ASR_DBR, 1000, "reading status byte"); - host->scsi.SCp.Status = sbic_arm_read(host->scsi.io_port, SBIC_DATA); + host->scsi.SCp.Status = sbic_arm_read(host, SBIC_DATA); } /* @@ -1438,12 +1435,12 @@ unsigned char acornscsi_readmessagebyte(AS_Host *host) acornscsi_sbic_wait(host, ASR_DBR, ASR_DBR, 1000, "for message byte"); - message = sbic_arm_read(host->scsi.io_port, SBIC_DATA); + message = sbic_arm_read(host, SBIC_DATA); /* wait for MSGIN-XFER-PAUSED */ acornscsi_sbic_wait(host, ASR_INT, ASR_INT, 1000, "for interrupt after message byte"); - sbic_arm_read(host->scsi.io_port, SBIC_SSR); + sbic_arm_read(host, SBIC_SSR); return message; } @@ -1480,7 +1477,7 @@ void acornscsi_message(AS_Host *host) /* wait for next msg-in */ acornscsi_sbic_wait(host, ASR_INT, ASR_INT, 1000, "for interrupt after negate ack"); - sbic_arm_read(host->scsi.io_port, SBIC_SSR); + sbic_arm_read(host, SBIC_SSR); } } while (msgidx < msglen); @@ -1602,7 +1599,7 @@ void acornscsi_message(AS_Host *host) host->host->host_no, acornscsi_target(host)); host->device[host->SCpnt->device->id].sync_xfer = SYNCHTRANSFER_2DBA; host->device[host->SCpnt->device->id].sync_state = SYNC_ASYNCHRONOUS; - sbic_arm_write(host->scsi.io_port, SBIC_SYNCHTRANSFER, host->device[host->SCpnt->device->id].sync_xfer); + sbic_arm_write(host, SBIC_SYNCHTRANSFER, host->device[host->SCpnt->device->id].sync_xfer); break; default: @@ -1652,7 +1649,7 @@ void acornscsi_message(AS_Host *host) host->device[host->SCpnt->device->id].sync_xfer = calc_sync_xfer(period * 4, length); } - sbic_arm_write(host->scsi.io_port, SBIC_SYNCHTRANSFER, host->device[host->SCpnt->device->id].sync_xfer); + sbic_arm_write(host, SBIC_SYNCHTRANSFER, host->device[host->SCpnt->device->id].sync_xfer); break; #else /* We do not accept synchronous transfers. Respond with a @@ -1792,10 +1789,10 @@ int acornscsi_starttransfer(AS_Host *host) residual = scsi_bufflen(host->SCpnt) - host->scsi.SCp.scsi_xferred; - sbic_arm_write(host->scsi.io_port, SBIC_SYNCHTRANSFER, host->device[host->SCpnt->device->id].sync_xfer); - sbic_arm_writenext(host->scsi.io_port, residual >> 16); - sbic_arm_writenext(host->scsi.io_port, residual >> 8); - sbic_arm_writenext(host->scsi.io_port, residual); + sbic_arm_write(host, SBIC_SYNCHTRANSFER, host->device[host->SCpnt->device->id].sync_xfer); + sbic_arm_writenext(host, residual >> 16); + sbic_arm_writenext(host, residual >> 8); + sbic_arm_writenext(host, residual); acornscsi_sbic_issuecmd(host, CMND_XFERINFO); return 1; } @@ -1816,7 +1813,7 @@ int acornscsi_reconnect(AS_Host *host) { unsigned int target, lun, ok = 0; - target = sbic_arm_read(host->scsi.io_port, SBIC_SOURCEID); + target = sbic_arm_read(host, SBIC_SOURCEID); if (!(target & 8)) printk(KERN_ERR "scsi%d: invalid source id after reselection " @@ -1832,7 +1829,7 @@ int acornscsi_reconnect(AS_Host *host) host->SCpnt = NULL; } - lun = sbic_arm_read(host->scsi.io_port, SBIC_DATA) & 7; + lun = sbic_arm_read(host, SBIC_DATA) & 7; host->scsi.reconnected.target = target; host->scsi.reconnected.lun = lun; @@ -1952,7 +1949,7 @@ static void acornscsi_abortcmd(AS_Host *host, unsigned char tag) { host->scsi.phase = PHASE_ABORTED; - sbic_arm_write(host->scsi.io_port, SBIC_CMND, CMND_ASSERTATN); + sbic_arm_write(host, SBIC_CMND, CMND_ASSERTATN); msgqueue_flush(&host->scsi.msgs); #ifdef CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE @@ -1979,11 +1976,11 @@ intr_ret_t acornscsi_sbicintr(AS_Host *host, int in_irq) { unsigned int asr, ssr; - asr = sbic_arm_read(host->scsi.io_port, SBIC_ASR); + asr = sbic_arm_read(host, SBIC_ASR); if (!(asr & ASR_INT)) return INTR_IDLE; - ssr = sbic_arm_read(host->scsi.io_port, SBIC_SSR); + ssr = sbic_arm_read(host, SBIC_SSR); #if (DEBUG & DEBUG_PHASES) print_sbic_status(asr, ssr, host->scsi.phase); @@ -1999,15 +1996,15 @@ intr_ret_t acornscsi_sbicintr(AS_Host *host, int in_irq) printk(KERN_ERR "scsi%d: reset in standard mode but wanted advanced mode.\n", host->host->host_no); /* setup sbic - WD33C93A */ - sbic_arm_write(host->scsi.io_port, SBIC_OWNID, OWNID_EAF | host->host->this_id); - sbic_arm_write(host->scsi.io_port, SBIC_CMND, CMND_RESET); + sbic_arm_write(host, SBIC_OWNID, OWNID_EAF | host->host->this_id); + sbic_arm_write(host, SBIC_CMND, CMND_RESET); return INTR_IDLE; case 0x01: /* reset state - advanced */ - sbic_arm_write(host->scsi.io_port, SBIC_CTRL, INIT_SBICDMA | CTRL_IDI); - sbic_arm_write(host->scsi.io_port, SBIC_TIMEOUT, TIMEOUT_TIME); - sbic_arm_write(host->scsi.io_port, SBIC_SYNCHTRANSFER, SYNCHTRANSFER_2DBA); - sbic_arm_write(host->scsi.io_port, SBIC_SOURCEID, SOURCEID_ER | SOURCEID_DSP); + sbic_arm_write(host, SBIC_CTRL, INIT_SBICDMA | CTRL_IDI); + sbic_arm_write(host, SBIC_TIMEOUT, TIMEOUT_TIME); + sbic_arm_write(host, SBIC_SYNCHTRANSFER, SYNCHTRANSFER_2DBA); + sbic_arm_write(host, SBIC_SOURCEID, SOURCEID_ER | SOURCEID_DSP); msgqueue_flush(&host->scsi.msgs); return INTR_IDLE; @@ -2025,10 +2022,10 @@ intr_ret_t acornscsi_sbicintr(AS_Host *host, int in_irq) msgqueue_flush(&host->scsi.msgs); host->dma.transferred = host->scsi.SCp.scsi_xferred; /* 33C93 gives next interrupt indicating bus phase */ - asr = sbic_arm_read(host->scsi.io_port, SBIC_ASR); + asr = sbic_arm_read(host, SBIC_ASR); if (!(asr & ASR_INT)) break; - ssr = sbic_arm_read(host->scsi.io_port, SBIC_SSR); + ssr = sbic_arm_read(host, SBIC_SSR); ADD_STATUS(8, ssr, host->scsi.phase, 1); ADD_STATUS(host->SCpnt->device->id, ssr, host->scsi.phase, 1); goto connected; @@ -2476,11 +2473,11 @@ acornscsi_intr(int irq, void *dev_id) do { ret = INTR_IDLE; - iostatus = inb(host->card.io_intr); + iostatus = readb(host->fast + INT_REG); if (iostatus & 2) { acornscsi_dma_intr(host); - iostatus = inb(host->card.io_intr); + iostatus = readb(host->fast + INT_REG); } if (iostatus & 8) @@ -2655,7 +2652,7 @@ static enum res_abort acornscsi_do_abort(AS_Host *host, struct scsi_cmnd *SCpnt) * busylun bit. */ case PHASE_CONNECTED: - sbic_arm_write(host->scsi.io_port, SBIC_CMND, CMND_DISCONNECT); + sbic_arm_write(host, SBIC_CMND, CMND_DISCONNECT); host->SCpnt = NULL; res = res_success_clear; break; @@ -2699,8 +2696,8 @@ int acornscsi_abort(struct scsi_cmnd *SCpnt) #if (DEBUG & DEBUG_ABORT) { int asr, ssr; - asr = sbic_arm_read(host->scsi.io_port, SBIC_ASR); - ssr = sbic_arm_read(host->scsi.io_port, SBIC_SSR); + asr = sbic_arm_read(host, SBIC_ASR); + ssr = sbic_arm_read(host, SBIC_SSR); printk(KERN_WARNING "acornscsi_abort: "); print_sbic_status(asr, ssr, host->scsi.phase); @@ -2731,9 +2728,7 @@ int acornscsi_abort(struct scsi_cmnd *SCpnt) //#if (DEBUG & DEBUG_ABORT) printk("success\n"); //#endif - SCpnt->result = DID_ABORT << 16; - SCpnt->scsi_done(SCpnt); - result = SCSI_ABORT_SUCCESS; + result = SUCCESS; break; /* @@ -2745,7 +2740,7 @@ int acornscsi_abort(struct scsi_cmnd *SCpnt) //#if (DEBUG & DEBUG_ABORT) printk("snooze\n"); //#endif - result = SCSI_ABORT_SNOOZE; + result = FAILED; break; /* @@ -2755,11 +2750,7 @@ int acornscsi_abort(struct scsi_cmnd *SCpnt) default: case res_not_running: acornscsi_dumplog(host, SCpnt->device->id); -#if (DEBUG & DEBUG_ABORT) - result = SCSI_ABORT_SNOOZE; -#else - result = SCSI_ABORT_NOT_RUNNING; -#endif + result = FAILED; //#if (DEBUG & DEBUG_ABORT) printk("not running\n"); //#endif @@ -2770,13 +2761,12 @@ int acornscsi_abort(struct scsi_cmnd *SCpnt) } /* - * Prototype: int acornscsi_reset(struct scsi_cmnd *SCpnt, unsigned int reset_flags) + * Prototype: int acornscsi_reset(struct scsi_cmnd *SCpnt) * Purpose : reset a command on this host/reset this host * Params : SCpnt - command causing reset - * result - what type of reset to perform * Returns : one of SCSI_RESET_ macros */ -int acornscsi_reset(struct scsi_cmnd *SCpnt, unsigned int reset_flags) +int acornscsi_bus_reset(struct scsi_cmnd *SCpnt) { AS_Host *host = (AS_Host *)SCpnt->device->host->hostdata; struct scsi_cmnd *SCptr; @@ -2787,8 +2777,8 @@ int acornscsi_reset(struct scsi_cmnd *SCpnt, unsigned int reset_flags) { int asr, ssr; - asr = sbic_arm_read(host->scsi.io_port, SBIC_ASR); - ssr = sbic_arm_read(host->scsi.io_port, SBIC_SSR); + asr = sbic_arm_read(host, SBIC_ASR); + ssr = sbic_arm_read(host, SBIC_SSR); printk(KERN_WARNING "acornscsi_reset: "); print_sbic_status(asr, ssr, host->scsi.phase); @@ -2798,28 +2788,16 @@ int acornscsi_reset(struct scsi_cmnd *SCpnt, unsigned int reset_flags) acornscsi_dma_stop(host); - SCptr = host->SCpnt; - /* * do hard reset. This resets all devices on this host, and so we * must set the reset status on all commands. */ acornscsi_resetcard(host); - /* - * report reset on commands current connected/disconnected - */ - acornscsi_reportstatus(&host->SCpnt, &SCptr, DID_RESET); - while ((SCptr = queue_remove(&host->queues.disconnected)) != NULL) - acornscsi_reportstatus(&SCptr, &SCpnt, DID_RESET); - - if (SCpnt) { - SCpnt->result = DID_RESET << 16; - SCpnt->scsi_done(SCpnt); - } + ; - return SCSI_RESET_BUS_RESET | SCSI_RESET_HOST_RESET | SCSI_RESET_SUCCESS; + return SUCCESS; } /*============================================================================================== @@ -2850,7 +2828,7 @@ char *acornscsi_info(struct Scsi_Host *host) " LINK" #endif #if (DEBUG & DEBUG_NO_WRITE) - " NOWRITE ("NO_WRITE_STR")" + " NOWRITE (" __stringify(NO_WRITE) ")" #endif , host->hostt->name, host->io_port, host->irq, VER_MAJOR, VER_MINOR, VER_PATCH); @@ -2881,15 +2859,15 @@ int acornscsi_proc_info(struct Scsi_Host *instance, char *buffer, char **start, " LINK" #endif #if (DEBUG & DEBUG_NO_WRITE) - " NOWRITE ("NO_WRITE_STR")" + " NOWRITE (" __stringify(NO_WRITE) ")" #endif "\n\n", VER_MAJOR, VER_MINOR, VER_PATCH); - p += sprintf(p, "SBIC: WD33C93A Address: %08X IRQ : %d\n", - host->scsi.io_port, host->scsi.irq); + p += sprintf(p, "SBIC: WD33C93A Address: %p IRQ : %d\n", + host->base + SBIC_REGIDX, host->scsi.irq); #ifdef USE_DMAC - p += sprintf(p, "DMAC: uPC71071 Address: %08X IRQ : %d\n\n", - host->dma.io_port, host->scsi.irq); + p += sprintf(p, "DMAC: uPC71071 Address: %p IRQ : %d\n\n", + host->base + DMAC_OFFSET, host->scsi.irq); #endif p += sprintf(p, "Statistics:\n" @@ -2976,9 +2954,8 @@ static struct scsi_host_template acornscsi_template = { .name = "AcornSCSI", .info = acornscsi_info, .queuecommand = acornscsi_queuecmd, -#warning fixme - .abort = acornscsi_abort, - .reset = acornscsi_reset, + .eh_abort_handler = acornscsi_abort, + .eh_bus_reset_handler = acornscsi_bus_reset, .can_queue = 16, .this_id = 7, .sg_tablesize = SG_ALL, @@ -2992,48 +2969,37 @@ acornscsi_probe(struct expansion_card *ec, const struct ecard_id *id) { struct Scsi_Host *host; AS_Host *ashost; - int ret = -ENOMEM; + int ret; - host = scsi_host_alloc(&acornscsi_template, sizeof(AS_Host)); - if (!host) + ret = ecard_request_resources(ec); + if (ret) goto out; + host = scsi_host_alloc(&acornscsi_template, sizeof(AS_Host)); + if (!host) { + ret = -ENOMEM; + goto out_release; + } + ashost = (AS_Host *)host->hostdata; - host->io_port = ecard_address(ec, ECARD_MEMC, 0); - host->irq = ec->irq; + ashost->base = ecardm_iomap(ec, ECARD_RES_MEMC, 0, 0); + ashost->fast = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0); + if (!ashost->base || !ashost->fast) + goto out_put; - ashost->host = host; - ashost->scsi.io_port = ioaddr(host->io_port + 0x800); - ashost->scsi.irq = host->irq; - ashost->card.io_intr = POD_SPACE(host->io_port) + 0x800; - ashost->card.io_page = POD_SPACE(host->io_port) + 0xc00; - ashost->card.io_ram = ioaddr(host->io_port); - ashost->dma.io_port = host->io_port + 0xc00; - ashost->dma.io_intr_clear = POD_SPACE(host->io_port) + 0x800; + host->irq = ec->irq; + ashost->host = host; + ashost->scsi.irq = host->irq; - ec->irqaddr = (char *)ioaddr(ashost->card.io_intr); + ec->irqaddr = ashost->fast + INT_REG; ec->irqmask = 0x0a; - ret = -EBUSY; - if (!request_region(host->io_port + 0x800, 2, "acornscsi(sbic)")) - goto err_1; - if (!request_region(ashost->card.io_intr, 1, "acornscsi(intr)")) - goto err_2; - if (!request_region(ashost->card.io_page, 1, "acornscsi(page)")) - goto err_3; -#ifdef USE_DMAC - if (!request_region(ashost->dma.io_port, 256, "acornscsi(dmac)")) - goto err_4; -#endif - if (!request_region(host->io_port, 2048, "acornscsi(ram)")) - goto err_5; - ret = request_irq(host->irq, acornscsi_intr, IRQF_DISABLED, "acornscsi", ashost); if (ret) { printk(KERN_CRIT "scsi%d: IRQ%d not free: %d\n", host->host_no, ashost->scsi.irq, ret); - goto err_6; + goto out_put; } memset(&ashost->stats, 0, sizeof (ashost->stats)); @@ -3045,27 +3011,22 @@ acornscsi_probe(struct expansion_card *ec, const struct ecard_id *id) ret = scsi_add_host(host, &ec->dev); if (ret) - goto err_7; + goto out_irq; scsi_scan_host(host); goto out; - err_7: + out_irq: free_irq(host->irq, ashost); - err_6: - release_region(host->io_port, 2048); - err_5: -#ifdef USE_DMAC - release_region(ashost->dma.io_port, 256); -#endif - err_4: - release_region(ashost->card.io_page, 1); - err_3: - release_region(ashost->card.io_intr, 1); - err_2: - release_region(host->io_port + 0x800, 2); - err_1: + msgqueue_free(&ashost->scsi.msgs); + queue_free(&ashost->queues.disconnected); + queue_free(&ashost->queues.issue); + out_put: + ecardm_iounmap(ec, ashost->fast); + ecardm_iounmap(ec, ashost->base); scsi_host_put(host); + out_release: + ecard_release_resources(ec); out: return ret; } @@ -3081,20 +3042,17 @@ static void __devexit acornscsi_remove(struct expansion_card *ec) /* * Put card into RESET state */ - outb(0x80, ashost->card.io_page); + writeb(0x80, ashost->fast + PAGE_REG); free_irq(host->irq, ashost); - release_region(host->io_port + 0x800, 2); - release_region(ashost->card.io_intr, 1); - release_region(ashost->card.io_page, 1); - release_region(ashost->dma.io_port, 256); - release_region(host->io_port, 2048); - msgqueue_free(&ashost->scsi.msgs); queue_free(&ashost->queues.disconnected); queue_free(&ashost->queues.issue); + ecardm_iounmap(ec, ashost->fast); + ecardm_iounmap(ec, ashost->base); scsi_host_put(host); + ecard_release_resources(ec); } static const struct ecard_id acornscsi_cids[] = { diff --git a/drivers/scsi/arm/acornscsi.h b/drivers/scsi/arm/acornscsi.h index d11424b89f4..8d2172a0b35 100644 --- a/drivers/scsi/arm/acornscsi.h +++ b/drivers/scsi/arm/acornscsi.h @@ -179,7 +179,6 @@ /* miscellaneous internal variables */ -#define POD_SPACE(x) ((x) + 0xd0000) #define MASK_ON (MASKREG_M3|MASKREG_M2|MASKREG_M1|MASKREG_M0) #define MASK_OFF (MASKREG_M3|MASKREG_M2|MASKREG_M1) @@ -279,10 +278,11 @@ typedef struct acornscsi_hostdata { struct Scsi_Host *host; /* host */ struct scsi_cmnd *SCpnt; /* currently processing command */ struct scsi_cmnd *origSCpnt; /* original connecting command */ + void __iomem *base; /* memc base address */ + void __iomem *fast; /* fast ioc base address */ /* driver information */ struct { - unsigned int io_port; /* base address of WD33C93 */ unsigned int irq; /* interrupt */ phase_t phase; /* current phase */ @@ -329,8 +329,6 @@ typedef struct acornscsi_hostdata { /* DMA info */ struct { - unsigned int io_port; /* base address of DMA controller */ - unsigned int io_intr_clear; /* address of DMA interrupt clear */ unsigned int free_addr; /* next free address */ unsigned int start_addr; /* start address of current transfer */ dmadir_t direction; /* dma direction */ @@ -345,9 +343,6 @@ typedef struct acornscsi_hostdata { /* card info */ struct { - unsigned int io_intr; /* base address of interrupt id reg */ - unsigned int io_page; /* base address of page reg */ - unsigned int io_ram; /* base address of RAM access */ unsigned char page_reg; /* current setting of page reg */ } card; diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 9bc42763623..18ca9075e13 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -448,22 +448,27 @@ config SERIAL_CLPS711X_CONSOLE your boot loader (lilo or loadlin) about how to pass options to the kernel at boot time.) -config SERIAL_S3C2410 - tristate "Samsung S3C2410/S3C2440/S3C2442/S3C2412 Serial port support" - depends on ARM && ARCH_S3C2410 - select SERIAL_CORE +config SERIAL_SAMSUNG + tristate "Samsung SoC serial support" + depends on ARM && PLAT_S3C24XX help Support for the on-chip UARTs on the Samsung S3C24XX series CPUs, providing /dev/ttySAC0, 1 and 2 (note, some machines may not provide all of these ports, depending on how the serial port pins are configured. - Currently this driver supports the UARTS on the S3C2410, S3C2440, - S3C2442, S3C2412 and S3C2413 CPUs. +config SERIAL_SAMSUNG_DEBUG + bool "Samsung SoC serial debug" + depends on SERIAL_SAMSUNG + help + Add support for debugging the serial driver. Since this is + generally being used as a console, we use our own output + routines that go via the low-level debug printascii() + function. -config SERIAL_S3C2410_CONSOLE - bool "Support for console on S3C2410 serial port" - depends on SERIAL_S3C2410=y +config SERIAL_SAMSUNG_CONSOLE + bool "Support for console on Samsung SoC serial port" + depends on SERIAL_SAMSUNG=y select SERIAL_CORE_CONSOLE help Allow selection of the S3C24XX on-board serial ports for use as @@ -476,6 +481,37 @@ config SERIAL_S3C2410_CONSOLE your boot loader about how to pass options to the kernel at boot time.) +config SERIAL_S3C2400 + tristate "Samsung S3C2410 Serial port support" + depends on ARM && SERIAL_SAMSUNG && CPU_S3C2400 + default y if CPU_S3C2400 + help + Serial port support for the Samsung S3C2400 SoC + +config SERIAL_S3C2410 + tristate "Samsung S3C2410 Serial port support" + depends on SERIAL_SAMSUNG && CPU_S3C2410 + default y if CPU_S3C2410 + help + Serial port support for the Samsung S3C2410 SoC + +config SERIAL_S3C2412 + tristate "Samsung S3C2412/S3C2413 Serial port support" + depends on SERIAL_SAMSUNG && CPU_S3C2412 + default y if CPU_S3C2412 + help + Serial port support for the Samsung S3C2412 and S3C2413 SoC + +config SERIAL_S3C2440 + tristate "Samsung S3C2440/S3C2442 Serial port support" + depends on SERIAL_SAMSUNG && (CPU_S3C2440 || CPU_S3C2442) + default y if CPU_S3C2440 + default y if CPU_S3C2442 + help + Serial port support for the Samsung S3C2440 and S3C2442 SoC + + + config SERIAL_DZ bool "DECstation DZ serial driver" depends on MACH_DECSTATION && 32BIT @@ -753,7 +789,7 @@ config BFIN_UART3_CTSRTS config SERIAL_IMX bool "IMX serial port support" - depends on ARM && ARCH_IMX + depends on ARM && (ARCH_IMX || ARCH_MXC) select SERIAL_CORE help If you have a machine based on a Motorola IMX CPU you diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 0d9c09b1e83..7d85c1fbe7e 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -28,7 +28,11 @@ obj-$(CONFIG_SERIAL_PNX8XXX) += pnx8xxx_uart.o obj-$(CONFIG_SERIAL_SA1100) += sa1100.o obj-$(CONFIG_SERIAL_BFIN) += bfin_5xx.o obj-$(CONFIG_SERIAL_BFIN_SPORT) += bfin_sport_uart.o +obj-$(CONFIG_SERIAL_SAMSUNG) += samsung.o +obj-$(CONFIG_SERIAL_S3C2400) += s3c2400.o obj-$(CONFIG_SERIAL_S3C2410) += s3c2410.o +obj-$(CONFIG_SERIAL_S3C2412) += s3c2412.o +obj-$(CONFIG_SERIAL_S3C2440) += s3c2440.o obj-$(CONFIG_SERIAL_SUNCORE) += suncore.o obj-$(CONFIG_SERIAL_SUNHV) += sunhv.o obj-$(CONFIG_SERIAL_SUNZILOG) += sunzilog.o diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index 5a375bf0ebf..64acb39a51b 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c @@ -40,6 +40,7 @@ #include <linux/tty_flip.h> #include <linux/serial_core.h> #include <linux/serial.h> +#include <linux/clk.h> #include <asm/io.h> #include <asm/irq.h> @@ -61,6 +62,11 @@ #define UBIR 0xa4 /* BRM Incremental Register */ #define UBMR 0xa8 /* BRM Modulator Register */ #define UBRC 0xac /* Baud Rate Count Register */ +#if defined CONFIG_ARCH_MX3 || defined CONFIG_ARCH_MX2 +#define ONEMS 0xb0 /* One Millisecond register */ +#define UTS 0xb4 /* UART Test Register */ +#endif +#ifdef CONFIG_ARCH_IMX #define BIPR1 0xb0 /* Incremental Preset Register 1 */ #define BIPR2 0xb4 /* Incremental Preset Register 2 */ #define BIPR3 0xb8 /* Incremental Preset Register 3 */ @@ -70,6 +76,7 @@ #define BMPR3 0xc8 /* BRM Modulator Register 3 */ #define BMPR4 0xcc /* BRM Modulator Register 4 */ #define UTS 0xd0 /* UART Test Register */ +#endif /* UART Control Register Bit Fields.*/ #define URXD_CHARRDY (1<<15) @@ -89,7 +96,12 @@ #define UCR1_RTSDEN (1<<5) /* RTS delta interrupt enable */ #define UCR1_SNDBRK (1<<4) /* Send break */ #define UCR1_TDMAEN (1<<3) /* Transmitter ready DMA enable */ +#ifdef CONFIG_ARCH_IMX #define UCR1_UARTCLKEN (1<<2) /* UART clock enabled */ +#endif +#if defined CONFIG_ARCH_MX3 || defined CONFIG_ARCH_MX2 +#define UCR1_UARTCLKEN (0) /* not present on mx2/mx3 */ +#endif #define UCR1_DOZE (1<<1) /* Doze */ #define UCR1_UARTEN (1<<0) /* UART enabled */ #define UCR2_ESCI (1<<15) /* Escape seq interrupt enable */ @@ -163,8 +175,19 @@ #define UTS_SOFTRST (1<<0) /* Software reset */ /* We've been assigned a range on the "Low-density serial ports" major */ +#ifdef CONFIG_ARCH_IMX #define SERIAL_IMX_MAJOR 204 #define MINOR_START 41 +#define DEV_NAME "ttySMX" +#define MAX_INTERNAL_IRQ IMX_IRQS +#endif + +#if defined CONFIG_ARCH_MX3 || defined CONFIG_ARCH_MX2 +#define SERIAL_IMX_MAJOR 207 +#define MINOR_START 16 +#define DEV_NAME "ttymxc" +#define MAX_INTERNAL_IRQ MXC_MAX_INT_LINES +#endif /* * This determines how often we check the modem status signals @@ -176,12 +199,15 @@ #define DRIVER_NAME "IMX-uart" +#define UART_NR 8 + struct imx_port { struct uart_port port; struct timer_list timer; unsigned int old_status; int txirq,rxirq,rtsirq; int have_rtscts:1; + struct clk *clk; }; /* @@ -405,6 +431,26 @@ out: return IRQ_HANDLED; } +static irqreturn_t imx_int(int irq, void *dev_id) +{ + struct imx_port *sport = dev_id; + unsigned int sts; + + sts = readl(sport->port.membase + USR1); + + if (sts & USR1_RRDY) + imx_rxint(irq, dev_id); + + if (sts & USR1_TRDY && + readl(sport->port.membase + UCR1) & UCR1_TXMPTYEN) + imx_txint(irq, dev_id); + + if (sts & USR1_RTSS) + imx_rtsint(irq, dev_id); + + return IRQ_HANDLED; +} + /* * Return TIOCSER_TEMT when transmitter is not busy. */ @@ -477,7 +523,8 @@ static int imx_setup_ufcr(struct imx_port *sport, unsigned int mode) * RFDIV is set such way to satisfy requested uartclk value */ val = TXTL << 10 | RXTL; - ufcr_rfdiv = (imx_get_perclk1() + sport->port.uartclk / 2) / sport->port.uartclk; + ufcr_rfdiv = (clk_get_rate(sport->clk) + sport->port.uartclk / 2) + / sport->port.uartclk; if(!ufcr_rfdiv) ufcr_rfdiv = 1; @@ -509,21 +556,34 @@ static int imx_startup(struct uart_port *port) writel(temp & ~UCR4_DREN, sport->port.membase + UCR4); /* - * Allocate the IRQ + * Allocate the IRQ(s) i.MX1 has three interrupts whereas later + * chips only have one interrupt. */ - retval = request_irq(sport->rxirq, imx_rxint, 0, - DRIVER_NAME, sport); - if (retval) goto error_out1; - - retval = request_irq(sport->txirq, imx_txint, 0, - DRIVER_NAME, sport); - if (retval) goto error_out2; - - retval = request_irq(sport->rtsirq, imx_rtsint, - (sport->rtsirq < IMX_IRQS) ? 0 : + if (sport->txirq > 0) { + retval = request_irq(sport->rxirq, imx_rxint, 0, + DRIVER_NAME, sport); + if (retval) + goto error_out1; + + retval = request_irq(sport->txirq, imx_txint, 0, + DRIVER_NAME, sport); + if (retval) + goto error_out2; + + retval = request_irq(sport->rtsirq, imx_rtsint, + (sport->rtsirq < MAX_INTERNAL_IRQ) ? 0 : IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, - DRIVER_NAME, sport); - if (retval) goto error_out3; + DRIVER_NAME, sport); + if (retval) + goto error_out3; + } else { + retval = request_irq(sport->port.irq, imx_int, 0, + DRIVER_NAME, sport); + if (retval) { + free_irq(sport->port.irq, sport); + goto error_out1; + } + } /* * Finally, clear and enable interrupts @@ -548,9 +608,11 @@ static int imx_startup(struct uart_port *port) return 0; error_out3: - free_irq(sport->txirq, sport); + if (sport->txirq) + free_irq(sport->txirq, sport); error_out2: - free_irq(sport->rxirq, sport); + if (sport->rxirq) + free_irq(sport->rxirq, sport); error_out1: return retval; } @@ -568,9 +630,12 @@ static void imx_shutdown(struct uart_port *port) /* * Free the interrupts */ - free_irq(sport->rtsirq, sport); - free_irq(sport->txirq, sport); - free_irq(sport->rxirq, sport); + if (sport->txirq > 0) { + free_irq(sport->rtsirq, sport); + free_irq(sport->txirq, sport); + free_irq(sport->rxirq, sport); + } else + free_irq(sport->port.irq, sport); /* * Disable all interrupts, port and break condition. @@ -589,6 +654,7 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios, unsigned long flags; unsigned int ucr2, old_ucr1, old_txrxen, baud, quot; unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8; + unsigned int div, num, denom, ufcr; /* * If we don't support modem control lines, don't allow @@ -634,7 +700,7 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios, /* * Ask the core to calculate the divisor for us. */ - baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); + baud = uart_get_baud_rate(port, termios, old, 50, port->uartclk / 16); quot = uart_get_divisor(port, baud); spin_lock_irqsave(&sport->port.lock, flags); @@ -684,14 +750,41 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios, sport->port.membase + UCR2); old_txrxen &= (UCR2_TXEN | UCR2_RXEN); - /* set the baud rate. We assume uartclk = 16 MHz - * - * baud * 16 UBIR - 1 - * --------- = -------- - * uartclk UBMR - 1 - */ - writel((baud / 100) - 1, sport->port.membase + UBIR); - writel(10000 - 1, sport->port.membase + UBMR); + div = sport->port.uartclk / (baud * 16); + if (div > 7) + div = 7; + if (!div) + div = 1; + + num = baud; + denom = port->uartclk / div / 16; + + /* shift num and denom right until they fit into 16 bits */ + while (num > 0x10000 || denom > 0x10000) { + num >>= 1; + denom >>= 1; + } + if (num > 0) + num -= 1; + if (denom > 0) + denom -= 1; + + writel(num, sport->port.membase + UBIR); + writel(denom, sport->port.membase + UBMR); + + if (div == 7) + div = 6; /* 6 in RFDIV means divide by 7 */ + else + div = 6 - div; + + ufcr = readl(sport->port.membase + UFCR); + ufcr = (ufcr & (~UFCR_RFDIV)) | + (div << 7); + writel(ufcr, sport->port.membase + UFCR); + +#ifdef ONEMS + writel(sport->port.uartclk / div / 1000, sport->port.membase + ONEMS); +#endif writel(old_ucr1, sport->port.membase + UCR1); @@ -801,65 +894,7 @@ static struct uart_ops imx_pops = { .verify_port = imx_verify_port, }; -static struct imx_port imx_ports[] = { - { - .txirq = UART1_MINT_TX, - .rxirq = UART1_MINT_RX, - .rtsirq = UART1_MINT_RTS, - .port = { - .type = PORT_IMX, - .iotype = UPIO_MEM, - .membase = (void *)IMX_UART1_BASE, - .mapbase = 0x00206000, - .irq = UART1_MINT_RX, - .uartclk = 16000000, - .fifosize = 32, - .flags = UPF_BOOT_AUTOCONF, - .ops = &imx_pops, - .line = 0, - }, - }, { - .txirq = UART2_MINT_TX, - .rxirq = UART2_MINT_RX, - .rtsirq = UART2_MINT_RTS, - .port = { - .type = PORT_IMX, - .iotype = UPIO_MEM, - .membase = (void *)IMX_UART2_BASE, - .mapbase = 0x00207000, - .irq = UART2_MINT_RX, - .uartclk = 16000000, - .fifosize = 32, - .flags = UPF_BOOT_AUTOCONF, - .ops = &imx_pops, - .line = 1, - }, - } -}; - -/* - * Setup the IMX serial ports. - * Note also that we support "console=ttySMXx" where "x" is either 0 or 1. - * Which serial port this ends up being depends on the machine you're - * running this kernel on. I'm not convinced that this is a good idea, - * but that's the way it traditionally works. - * - */ -static void __init imx_init_ports(void) -{ - static int first = 1; - int i; - - if (!first) - return; - first = 0; - - for (i = 0; i < ARRAY_SIZE(imx_ports); i++) { - init_timer(&imx_ports[i].timer); - imx_ports[i].timer.function = imx_timeout; - imx_ports[i].timer.data = (unsigned long)&imx_ports[i]; - } -} +static struct imx_port *imx_ports[UART_NR]; #ifdef CONFIG_SERIAL_IMX_CONSOLE static void imx_console_putchar(struct uart_port *port, int ch) @@ -878,7 +913,7 @@ static void imx_console_putchar(struct uart_port *port, int ch) static void imx_console_write(struct console *co, const char *s, unsigned int count) { - struct imx_port *sport = &imx_ports[co->index]; + struct imx_port *sport = imx_ports[co->index]; unsigned int old_ucr1, old_ucr2; /* @@ -944,7 +979,7 @@ imx_console_get_options(struct imx_port *sport, int *baud, else ucfr_rfdiv = 6 - ucfr_rfdiv; - uartclk = imx_get_perclk1(); + uartclk = clk_get_rate(sport->clk); uartclk /= ucfr_rfdiv; { /* @@ -984,7 +1019,7 @@ imx_console_setup(struct console *co, char *options) */ if (co->index == -1 || co->index >= ARRAY_SIZE(imx_ports)) co->index = 0; - sport = &imx_ports[co->index]; + sport = imx_ports[co->index]; if (options) uart_parse_options(options, &baud, &parity, &bits, &flow); @@ -998,7 +1033,7 @@ imx_console_setup(struct console *co, char *options) static struct uart_driver imx_reg; static struct console imx_console = { - .name = "ttySMX", + .name = DEV_NAME, .write = imx_console_write, .device = uart_console_device, .setup = imx_console_setup, @@ -1007,14 +1042,6 @@ static struct console imx_console = { .data = &imx_reg, }; -static int __init imx_rs_console_init(void) -{ - imx_init_ports(); - register_console(&imx_console); - return 0; -} -console_initcall(imx_rs_console_init); - #define IMX_CONSOLE &imx_console #else #define IMX_CONSOLE NULL @@ -1023,7 +1050,7 @@ console_initcall(imx_rs_console_init); static struct uart_driver imx_reg = { .owner = THIS_MODULE, .driver_name = DRIVER_NAME, - .dev_name = "ttySMX", + .dev_name = DEV_NAME, .major = SERIAL_IMX_MAJOR, .minor = MINOR_START, .nr = ARRAY_SIZE(imx_ports), @@ -1050,29 +1077,98 @@ static int serial_imx_resume(struct platform_device *dev) return 0; } -static int serial_imx_probe(struct platform_device *dev) +static int serial_imx_probe(struct platform_device *pdev) { + struct imx_port *sport; struct imxuart_platform_data *pdata; + void __iomem *base; + int ret = 0; + struct resource *res; + + sport = kzalloc(sizeof(*sport), GFP_KERNEL); + if (!sport) + return -ENOMEM; - imx_ports[dev->id].port.dev = &dev->dev; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + ret = -ENODEV; + goto free; + } + + base = ioremap(res->start, PAGE_SIZE); + if (!base) { + ret = -ENOMEM; + goto free; + } + + sport->port.dev = &pdev->dev; + sport->port.mapbase = res->start; + sport->port.membase = base; + sport->port.type = PORT_IMX, + sport->port.iotype = UPIO_MEM; + sport->port.irq = platform_get_irq(pdev, 0); + sport->rxirq = platform_get_irq(pdev, 0); + sport->txirq = platform_get_irq(pdev, 1); + sport->rtsirq = platform_get_irq(pdev, 2); + sport->port.fifosize = 32; + sport->port.ops = &imx_pops; + sport->port.flags = UPF_BOOT_AUTOCONF; + sport->port.line = pdev->id; + init_timer(&sport->timer); + sport->timer.function = imx_timeout; + sport->timer.data = (unsigned long)sport; + + sport->clk = clk_get(&pdev->dev, "uart_clk"); + if (IS_ERR(sport->clk)) { + ret = PTR_ERR(sport->clk); + goto unmap; + } + clk_enable(sport->clk); - pdata = (struct imxuart_platform_data *)dev->dev.platform_data; + sport->port.uartclk = clk_get_rate(sport->clk); + + imx_ports[pdev->id] = sport; + + pdata = pdev->dev.platform_data; if(pdata && (pdata->flags & IMXUART_HAVE_RTSCTS)) - imx_ports[dev->id].have_rtscts = 1; + sport->have_rtscts = 1; + + if (pdata->init) + pdata->init(pdev); + + uart_add_one_port(&imx_reg, &sport->port); + platform_set_drvdata(pdev, &sport->port); - uart_add_one_port(&imx_reg, &imx_ports[dev->id].port); - platform_set_drvdata(dev, &imx_ports[dev->id]); return 0; +unmap: + iounmap(sport->port.membase); +free: + kfree(sport); + + return ret; } -static int serial_imx_remove(struct platform_device *dev) +static int serial_imx_remove(struct platform_device *pdev) { - struct imx_port *sport = platform_get_drvdata(dev); + struct imxuart_platform_data *pdata; + struct imx_port *sport = platform_get_drvdata(pdev); - platform_set_drvdata(dev, NULL); + pdata = pdev->dev.platform_data; - if (sport) + platform_set_drvdata(pdev, NULL); + + if (sport) { uart_remove_one_port(&imx_reg, &sport->port); + clk_put(sport->clk); + } + + clk_disable(sport->clk); + + if (pdata->exit) + pdata->exit(pdev); + + iounmap(sport->port.membase); + kfree(sport); return 0; } @@ -1095,8 +1191,6 @@ static int __init imx_serial_init(void) printk(KERN_INFO "Serial: IMX driver\n"); - imx_init_ports(); - ret = uart_register_driver(&imx_reg); if (ret) return ret; diff --git a/drivers/serial/s3c2400.c b/drivers/serial/s3c2400.c new file mode 100644 index 00000000000..a1102053e55 --- /dev/null +++ b/drivers/serial/s3c2400.c @@ -0,0 +1,106 @@ +/* linux/drivers/serial/s3c240.c + * + * Driver for Samsung SoC onboard UARTs. + * + * Ben Dooks, Copyright (c) 2003-2005 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/module.h> +#include <linux/ioport.h> +#include <linux/io.h> +#include <linux/platform_device.h> + +#include <asm/irq.h> + +#include <asm/hardware.h> + +#include <asm/plat-s3c/regs-serial.h> +#include <asm/arch/regs-gpio.h> + +#include "samsung.h" + +static int s3c2400_serial_getsource(struct uart_port *port, + struct s3c24xx_uart_clksrc *clk) +{ + clk->divisor = 1; + clk->name = "pclk"; + + return 0; +} + +static int s3c2400_serial_setsource(struct uart_port *port, + struct s3c24xx_uart_clksrc *clk) +{ + return 0; +} + +static int s3c2400_serial_resetport(struct uart_port *port, + struct s3c2410_uartcfg *cfg) +{ + dbg("s3c2400_serial_resetport: port=%p (%08lx), cfg=%p\n", + port, port->mapbase, cfg); + + wr_regl(port, S3C2410_UCON, cfg->ucon); + wr_regl(port, S3C2410_ULCON, cfg->ulcon); + + /* reset both fifos */ + + wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH); + wr_regl(port, S3C2410_UFCON, cfg->ufcon); + + return 0; +} + +static struct s3c24xx_uart_info s3c2400_uart_inf = { + .name = "Samsung S3C2400 UART", + .type = PORT_S3C2400, + .fifosize = 16, + .rx_fifomask = S3C2410_UFSTAT_RXMASK, + .rx_fifoshift = S3C2410_UFSTAT_RXSHIFT, + .rx_fifofull = S3C2410_UFSTAT_RXFULL, + .tx_fifofull = S3C2410_UFSTAT_TXFULL, + .tx_fifomask = S3C2410_UFSTAT_TXMASK, + .tx_fifoshift = S3C2410_UFSTAT_TXSHIFT, + .get_clksrc = s3c2400_serial_getsource, + .set_clksrc = s3c2400_serial_setsource, + .reset_port = s3c2400_serial_resetport, +}; + +static int s3c2400_serial_probe(struct platform_device *dev) +{ + return s3c24xx_serial_probe(dev, &s3c2400_uart_inf); +} + +static struct platform_driver s3c2400_serial_drv = { + .probe = s3c2400_serial_probe, + .remove = s3c24xx_serial_remove, + .driver = { + .name = "s3c2400-uart", + .owner = THIS_MODULE, + }, +}; + +s3c24xx_console_init(&s3c2400_serial_drv, &s3c2400_uart_inf); + +static inline int s3c2400_serial_init(void) +{ + return s3c24xx_serial_init(&s3c2400_serial_drv, &s3c2400_uart_inf); +} + +static inline void s3c2400_serial_exit(void) +{ + platform_driver_unregister(&s3c2400_serial_drv); +} + +module_init(s3c2400_serial_init); +module_exit(s3c2400_serial_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); +MODULE_DESCRIPTION("Samsung S3C2400 SoC Serial port driver"); +MODULE_ALIAS("platform:s3c2400-uart"); diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c index 2b6a013639e..c5f03f41686 100644 --- a/drivers/serial/s3c2410.c +++ b/drivers/serial/s3c2410.c @@ -1,1270 +1,30 @@ -/* - * linux/drivers/serial/s3c2410.c +/* linux/drivers/serial/s3c2410.c * - * Driver for onboard UARTs on the Samsung S3C24XX + * Driver for Samsung S3C2410 SoC onboard UARTs. * - * Based on drivers/char/serial.c and drivers/char/21285.c + * Ben Dooks, Copyright (c) 2003-2005,2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ * - * Ben Dooks, (c) 2003-2005 Simtec Electronics - * http://www.simtec.co.uk/products/SWLINUX/ - * - * Changelog: - * - * 22-Jul-2004 BJD Finished off device rewrite - * - * 21-Jul-2004 BJD Thanks to <herbet@13thfloor.at> for pointing out - * problems with baud rate and loss of IR settings. Update - * to add configuration via platform_device structure - * - * 28-Sep-2004 BJD Re-write for the following items - * - S3C2410 and S3C2440 serial support - * - Power Management support - * - Fix console via IrDA devices - * - SysReq (Herbert Pötzl) - * - Break character handling (Herbert Pötzl) - * - spin-lock initialisation (Dimitry Andric) - * - added clock control - * - updated init code to use platform_device info - * - * 06-Mar-2005 BJD Add s3c2440 fclk clock source - * - * 09-Mar-2005 BJD Add s3c2400 support - * - * 10-Mar-2005 LCVR Changed S3C2410_VA_UART to S3C24XX_VA_UART -*/ - -/* Note on 2440 fclk clock source handling - * - * Whilst it is possible to use the fclk as clock source, the method - * of properly switching too/from this is currently un-implemented, so - * whichever way is configured at startup is the one that will be used. -*/ - -/* Hote on 2410 error handling - * - * The s3c2410 manual has a love/hate affair with the contents of the - * UERSTAT register in the UART blocks, and keeps marking some of the - * error bits as reserved. Having checked with the s3c2410x01, - * it copes with BREAKs properly, so I am happy to ignore the RESERVED - * feature from the latter versions of the manual. - * - * If it becomes aparrent that latter versions of the 2410 remove these - * bits, then action will have to be taken to differentiate the versions - * and change the policy on BREAK - * - * BJD, 04-Nov-2004 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. */ - -#if defined(CONFIG_SERIAL_S3C2410_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #include <linux/module.h> #include <linux/ioport.h> +#include <linux/io.h> #include <linux/platform_device.h> #include <linux/init.h> -#include <linux/sysrq.h> -#include <linux/console.h> -#include <linux/tty.h> -#include <linux/tty_flip.h> #include <linux/serial_core.h> #include <linux/serial.h> -#include <linux/delay.h> -#include <linux/clk.h> -#include <asm/io.h> #include <asm/irq.h> - #include <asm/hardware.h> #include <asm/plat-s3c/regs-serial.h> #include <asm/arch/regs-gpio.h> -/* structures */ - -struct s3c24xx_uart_info { - char *name; - unsigned int type; - unsigned int fifosize; - unsigned long rx_fifomask; - unsigned long rx_fifoshift; - unsigned long rx_fifofull; - unsigned long tx_fifomask; - unsigned long tx_fifoshift; - unsigned long tx_fifofull; - - /* clock source control */ - - int (*get_clksrc)(struct uart_port *, struct s3c24xx_uart_clksrc *clk); - int (*set_clksrc)(struct uart_port *, struct s3c24xx_uart_clksrc *clk); - - /* uart controls */ - int (*reset_port)(struct uart_port *, struct s3c2410_uartcfg *); -}; - -struct s3c24xx_uart_port { - unsigned char rx_claimed; - unsigned char tx_claimed; - - struct s3c24xx_uart_info *info; - struct s3c24xx_uart_clksrc *clksrc; - struct clk *clk; - struct clk *baudclk; - struct uart_port port; -}; - - -/* configuration defines */ - -#if 0 -#if 1 -/* send debug to the low-level output routines */ - -extern void printascii(const char *); - -static void -s3c24xx_serial_dbg(const char *fmt, ...) -{ - va_list va; - char buff[256]; - - va_start(va, fmt); - vsprintf(buff, fmt, va); - va_end(va); - - printascii(buff); -} - -#define dbg(x...) s3c24xx_serial_dbg(x) - -#else -#define dbg(x...) printk(KERN_DEBUG "s3c24xx: "); -#endif -#else /* no debug */ -#define dbg(x...) do {} while(0) -#endif - -/* UART name and device definitions */ - -#define S3C24XX_SERIAL_NAME "ttySAC" -#define S3C24XX_SERIAL_MAJOR 204 -#define S3C24XX_SERIAL_MINOR 64 - - -/* conversion functions */ - -#define s3c24xx_dev_to_port(__dev) (struct uart_port *)dev_get_drvdata(__dev) -#define s3c24xx_dev_to_cfg(__dev) (struct s3c2410_uartcfg *)((__dev)->platform_data) - -/* we can support 3 uarts, but not always use them */ - -#ifdef CONFIG_CPU_S3C2400 -#define NR_PORTS (2) -#else -#define NR_PORTS (3) -#endif - -/* port irq numbers */ - -#define TX_IRQ(port) ((port)->irq + 1) -#define RX_IRQ(port) ((port)->irq) - -/* register access controls */ - -#define portaddr(port, reg) ((port)->membase + (reg)) - -#define rd_regb(port, reg) (__raw_readb(portaddr(port, reg))) -#define rd_regl(port, reg) (__raw_readl(portaddr(port, reg))) - -#define wr_regb(port, reg, val) \ - do { __raw_writeb(val, portaddr(port, reg)); } while(0) - -#define wr_regl(port, reg, val) \ - do { __raw_writel(val, portaddr(port, reg)); } while(0) - -/* macros to change one thing to another */ - -#define tx_enabled(port) ((port)->unused[0]) -#define rx_enabled(port) ((port)->unused[1]) - -/* flag to ignore all characters comming in */ -#define RXSTAT_DUMMY_READ (0x10000000) - -static inline struct s3c24xx_uart_port *to_ourport(struct uart_port *port) -{ - return container_of(port, struct s3c24xx_uart_port, port); -} - -/* translate a port to the device name */ - -static inline const char *s3c24xx_serial_portname(struct uart_port *port) -{ - return to_platform_device(port->dev)->name; -} - -static int s3c24xx_serial_txempty_nofifo(struct uart_port *port) -{ - return (rd_regl(port, S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE); -} - -static void s3c24xx_serial_rx_enable(struct uart_port *port) -{ - unsigned long flags; - unsigned int ucon, ufcon; - int count = 10000; - - spin_lock_irqsave(&port->lock, flags); - - while (--count && !s3c24xx_serial_txempty_nofifo(port)) - udelay(100); - - ufcon = rd_regl(port, S3C2410_UFCON); - ufcon |= S3C2410_UFCON_RESETRX; - wr_regl(port, S3C2410_UFCON, ufcon); - - ucon = rd_regl(port, S3C2410_UCON); - ucon |= S3C2410_UCON_RXIRQMODE; - wr_regl(port, S3C2410_UCON, ucon); - - rx_enabled(port) = 1; - spin_unlock_irqrestore(&port->lock, flags); -} - -static void s3c24xx_serial_rx_disable(struct uart_port *port) -{ - unsigned long flags; - unsigned int ucon; - - spin_lock_irqsave(&port->lock, flags); - - ucon = rd_regl(port, S3C2410_UCON); - ucon &= ~S3C2410_UCON_RXIRQMODE; - wr_regl(port, S3C2410_UCON, ucon); - - rx_enabled(port) = 0; - spin_unlock_irqrestore(&port->lock, flags); -} - -static void s3c24xx_serial_stop_tx(struct uart_port *port) -{ - if (tx_enabled(port)) { - disable_irq(TX_IRQ(port)); - tx_enabled(port) = 0; - if (port->flags & UPF_CONS_FLOW) - s3c24xx_serial_rx_enable(port); - } -} - -static void s3c24xx_serial_start_tx(struct uart_port *port) -{ - if (!tx_enabled(port)) { - if (port->flags & UPF_CONS_FLOW) - s3c24xx_serial_rx_disable(port); - - enable_irq(TX_IRQ(port)); - tx_enabled(port) = 1; - } -} - - -static void s3c24xx_serial_stop_rx(struct uart_port *port) -{ - if (rx_enabled(port)) { - dbg("s3c24xx_serial_stop_rx: port=%p\n", port); - disable_irq(RX_IRQ(port)); - rx_enabled(port) = 0; - } -} - -static void s3c24xx_serial_enable_ms(struct uart_port *port) -{ -} - -static inline struct s3c24xx_uart_info *s3c24xx_port_to_info(struct uart_port *port) -{ - return to_ourport(port)->info; -} - -static inline struct s3c2410_uartcfg *s3c24xx_port_to_cfg(struct uart_port *port) -{ - if (port->dev == NULL) - return NULL; - - return (struct s3c2410_uartcfg *)port->dev->platform_data; -} - -static int s3c24xx_serial_rx_fifocnt(struct s3c24xx_uart_port *ourport, - unsigned long ufstat) -{ - struct s3c24xx_uart_info *info = ourport->info; - - if (ufstat & info->rx_fifofull) - return info->fifosize; - - return (ufstat & info->rx_fifomask) >> info->rx_fifoshift; -} - - -/* ? - where has parity gone?? */ -#define S3C2410_UERSTAT_PARITY (0x1000) - -static irqreturn_t -s3c24xx_serial_rx_chars(int irq, void *dev_id) -{ - struct s3c24xx_uart_port *ourport = dev_id; - struct uart_port *port = &ourport->port; - struct tty_struct *tty = port->info->tty; - unsigned int ufcon, ch, flag, ufstat, uerstat; - int max_count = 64; - - while (max_count-- > 0) { - ufcon = rd_regl(port, S3C2410_UFCON); - ufstat = rd_regl(port, S3C2410_UFSTAT); - - if (s3c24xx_serial_rx_fifocnt(ourport, ufstat) == 0) - break; - - uerstat = rd_regl(port, S3C2410_UERSTAT); - ch = rd_regb(port, S3C2410_URXH); - - if (port->flags & UPF_CONS_FLOW) { - int txe = s3c24xx_serial_txempty_nofifo(port); - - if (rx_enabled(port)) { - if (!txe) { - rx_enabled(port) = 0; - continue; - } - } else { - if (txe) { - ufcon |= S3C2410_UFCON_RESETRX; - wr_regl(port, S3C2410_UFCON, ufcon); - rx_enabled(port) = 1; - goto out; - } - continue; - } - } - - /* insert the character into the buffer */ - - flag = TTY_NORMAL; - port->icount.rx++; - - if (unlikely(uerstat & S3C2410_UERSTAT_ANY)) { - dbg("rxerr: port ch=0x%02x, rxs=0x%08x\n", - ch, uerstat); - - /* check for break */ - if (uerstat & S3C2410_UERSTAT_BREAK) { - dbg("break!\n"); - port->icount.brk++; - if (uart_handle_break(port)) - goto ignore_char; - } - - if (uerstat & S3C2410_UERSTAT_FRAME) - port->icount.frame++; - if (uerstat & S3C2410_UERSTAT_OVERRUN) - port->icount.overrun++; - - uerstat &= port->read_status_mask; - - if (uerstat & S3C2410_UERSTAT_BREAK) - flag = TTY_BREAK; - else if (uerstat & S3C2410_UERSTAT_PARITY) - flag = TTY_PARITY; - else if (uerstat & ( S3C2410_UERSTAT_FRAME | S3C2410_UERSTAT_OVERRUN)) - flag = TTY_FRAME; - } - - if (uart_handle_sysrq_char(port, ch)) - goto ignore_char; - - uart_insert_char(port, uerstat, S3C2410_UERSTAT_OVERRUN, ch, flag); - - ignore_char: - continue; - } - tty_flip_buffer_push(tty); - - out: - return IRQ_HANDLED; -} - -static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id) -{ - struct s3c24xx_uart_port *ourport = id; - struct uart_port *port = &ourport->port; - struct circ_buf *xmit = &port->info->xmit; - int count = 256; - - if (port->x_char) { - wr_regb(port, S3C2410_UTXH, port->x_char); - port->icount.tx++; - port->x_char = 0; - goto out; - } - - /* if there isnt anything more to transmit, or the uart is now - * stopped, disable the uart and exit - */ - - if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { - s3c24xx_serial_stop_tx(port); - goto out; - } - - /* try and drain the buffer... */ - - while (!uart_circ_empty(xmit) && count-- > 0) { - if (rd_regl(port, S3C2410_UFSTAT) & ourport->info->tx_fifofull) - break; - - wr_regb(port, S3C2410_UTXH, xmit->buf[xmit->tail]); - xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); - port->icount.tx++; - } - - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) - uart_write_wakeup(port); - - if (uart_circ_empty(xmit)) - s3c24xx_serial_stop_tx(port); - - out: - return IRQ_HANDLED; -} - -static unsigned int s3c24xx_serial_tx_empty(struct uart_port *port) -{ - struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); - unsigned long ufstat = rd_regl(port, S3C2410_UFSTAT); - unsigned long ufcon = rd_regl(port, S3C2410_UFCON); - - if (ufcon & S3C2410_UFCON_FIFOMODE) { - if ((ufstat & info->tx_fifomask) != 0 || - (ufstat & info->tx_fifofull)) - return 0; - - return 1; - } - - return s3c24xx_serial_txempty_nofifo(port); -} - -/* no modem control lines */ -static unsigned int s3c24xx_serial_get_mctrl(struct uart_port *port) -{ - unsigned int umstat = rd_regb(port,S3C2410_UMSTAT); - - if (umstat & S3C2410_UMSTAT_CTS) - return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS; - else - return TIOCM_CAR | TIOCM_DSR; -} - -static void s3c24xx_serial_set_mctrl(struct uart_port *port, unsigned int mctrl) -{ - /* todo - possibly remove AFC and do manual CTS */ -} - -static void s3c24xx_serial_break_ctl(struct uart_port *port, int break_state) -{ - unsigned long flags; - unsigned int ucon; - - spin_lock_irqsave(&port->lock, flags); - - ucon = rd_regl(port, S3C2410_UCON); - - if (break_state) - ucon |= S3C2410_UCON_SBREAK; - else - ucon &= ~S3C2410_UCON_SBREAK; - - wr_regl(port, S3C2410_UCON, ucon); - - spin_unlock_irqrestore(&port->lock, flags); -} - -static void s3c24xx_serial_shutdown(struct uart_port *port) -{ - struct s3c24xx_uart_port *ourport = to_ourport(port); - - if (ourport->tx_claimed) { - free_irq(TX_IRQ(port), ourport); - tx_enabled(port) = 0; - ourport->tx_claimed = 0; - } - - if (ourport->rx_claimed) { - free_irq(RX_IRQ(port), ourport); - ourport->rx_claimed = 0; - rx_enabled(port) = 0; - } -} - - -static int s3c24xx_serial_startup(struct uart_port *port) -{ - struct s3c24xx_uart_port *ourport = to_ourport(port); - int ret; - - dbg("s3c24xx_serial_startup: port=%p (%08lx,%p)\n", - port->mapbase, port->membase); - - rx_enabled(port) = 1; - - ret = request_irq(RX_IRQ(port), - s3c24xx_serial_rx_chars, 0, - s3c24xx_serial_portname(port), ourport); - - if (ret != 0) { - printk(KERN_ERR "cannot get irq %d\n", RX_IRQ(port)); - return ret; - } - - ourport->rx_claimed = 1; - - dbg("requesting tx irq...\n"); - - tx_enabled(port) = 1; - - ret = request_irq(TX_IRQ(port), - s3c24xx_serial_tx_chars, 0, - s3c24xx_serial_portname(port), ourport); - - if (ret) { - printk(KERN_ERR "cannot get irq %d\n", TX_IRQ(port)); - goto err; - } - - ourport->tx_claimed = 1; - - dbg("s3c24xx_serial_startup ok\n"); - - /* the port reset code should have done the correct - * register setup for the port controls */ - - return ret; - - err: - s3c24xx_serial_shutdown(port); - return ret; -} - -/* power power management control */ - -static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level, - unsigned int old) -{ - struct s3c24xx_uart_port *ourport = to_ourport(port); - - switch (level) { - case 3: - if (!IS_ERR(ourport->baudclk) && ourport->baudclk != NULL) - clk_disable(ourport->baudclk); - - clk_disable(ourport->clk); - break; - - case 0: - clk_enable(ourport->clk); - - if (!IS_ERR(ourport->baudclk) && ourport->baudclk != NULL) - clk_enable(ourport->baudclk); - - break; - default: - printk(KERN_ERR "s3c24xx_serial: unknown pm %d\n", level); - } -} - -/* baud rate calculation - * - * The UARTs on the S3C2410/S3C2440 can take their clocks from a number - * of different sources, including the peripheral clock ("pclk") and an - * external clock ("uclk"). The S3C2440 also adds the core clock ("fclk") - * with a programmable extra divisor. - * - * The following code goes through the clock sources, and calculates the - * baud clocks (and the resultant actual baud rates) and then tries to - * pick the closest one and select that. - * -*/ - - -#define MAX_CLKS (8) - -static struct s3c24xx_uart_clksrc tmp_clksrc = { - .name = "pclk", - .min_baud = 0, - .max_baud = 0, - .divisor = 1, -}; - -static inline int -s3c24xx_serial_getsource(struct uart_port *port, struct s3c24xx_uart_clksrc *c) -{ - struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); - - return (info->get_clksrc)(port, c); -} - -static inline int -s3c24xx_serial_setsource(struct uart_port *port, struct s3c24xx_uart_clksrc *c) -{ - struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); - - return (info->set_clksrc)(port, c); -} - -struct baud_calc { - struct s3c24xx_uart_clksrc *clksrc; - unsigned int calc; - unsigned int quot; - struct clk *src; -}; - -static int s3c24xx_serial_calcbaud(struct baud_calc *calc, - struct uart_port *port, - struct s3c24xx_uart_clksrc *clksrc, - unsigned int baud) -{ - unsigned long rate; - - calc->src = clk_get(port->dev, clksrc->name); - if (calc->src == NULL || IS_ERR(calc->src)) - return 0; - - rate = clk_get_rate(calc->src); - rate /= clksrc->divisor; - - calc->clksrc = clksrc; - calc->quot = (rate + (8 * baud)) / (16 * baud); - calc->calc = (rate / (calc->quot * 16)); - - calc->quot--; - return 1; -} - -static unsigned int s3c24xx_serial_getclk(struct uart_port *port, - struct s3c24xx_uart_clksrc **clksrc, - struct clk **clk, - unsigned int baud) -{ - struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port); - struct s3c24xx_uart_clksrc *clkp; - struct baud_calc res[MAX_CLKS]; - struct baud_calc *resptr, *best, *sptr; - int i; - - clkp = cfg->clocks; - best = NULL; - - if (cfg->clocks_size < 2) { - if (cfg->clocks_size == 0) - clkp = &tmp_clksrc; - - /* check to see if we're sourcing fclk, and if so we're - * going to have to update the clock source - */ - - if (strcmp(clkp->name, "fclk") == 0) { - struct s3c24xx_uart_clksrc src; - - s3c24xx_serial_getsource(port, &src); - - /* check that the port already using fclk, and if - * not, then re-select fclk - */ - - if (strcmp(src.name, clkp->name) == 0) { - s3c24xx_serial_setsource(port, clkp); - s3c24xx_serial_getsource(port, &src); - } - - clkp->divisor = src.divisor; - } - - s3c24xx_serial_calcbaud(res, port, clkp, baud); - best = res; - resptr = best + 1; - } else { - resptr = res; - - for (i = 0; i < cfg->clocks_size; i++, clkp++) { - if (s3c24xx_serial_calcbaud(resptr, port, clkp, baud)) - resptr++; - } - } - - /* ok, we now need to select the best clock we found */ - - if (!best) { - unsigned int deviation = (1<<30)|((1<<30)-1); - int calc_deviation; - - for (sptr = res; sptr < resptr; sptr++) { - printk(KERN_DEBUG - "found clk %p (%s) quot %d, calc %d\n", - sptr->clksrc, sptr->clksrc->name, - sptr->quot, sptr->calc); - - calc_deviation = baud - sptr->calc; - if (calc_deviation < 0) - calc_deviation = -calc_deviation; - - if (calc_deviation < deviation) { - best = sptr; - deviation = calc_deviation; - } - } - - printk(KERN_DEBUG "best %p (deviation %d)\n", best, deviation); - } - - printk(KERN_DEBUG "selected clock %p (%s) quot %d, calc %d\n", - best->clksrc, best->clksrc->name, best->quot, best->calc); - - /* store results to pass back */ - - *clksrc = best->clksrc; - *clk = best->src; - - return best->quot; -} - -static void s3c24xx_serial_set_termios(struct uart_port *port, - struct ktermios *termios, - struct ktermios *old) -{ - struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port); - struct s3c24xx_uart_port *ourport = to_ourport(port); - struct s3c24xx_uart_clksrc *clksrc = NULL; - struct clk *clk = NULL; - unsigned long flags; - unsigned int baud, quot; - unsigned int ulcon; - unsigned int umcon; - - /* - * We don't support modem control lines. - */ - termios->c_cflag &= ~(HUPCL | CMSPAR); - termios->c_cflag |= CLOCAL; - - /* - * Ask the core to calculate the divisor for us. - */ - - baud = uart_get_baud_rate(port, termios, old, 0, 115200*8); - - if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST) - quot = port->custom_divisor; - else - quot = s3c24xx_serial_getclk(port, &clksrc, &clk, baud); - - /* check to see if we need to change clock source */ - - if (ourport->clksrc != clksrc || ourport->baudclk != clk) { - s3c24xx_serial_setsource(port, clksrc); - - if (ourport->baudclk != NULL && !IS_ERR(ourport->baudclk)) { - clk_disable(ourport->baudclk); - ourport->baudclk = NULL; - } - - clk_enable(clk); - - ourport->clksrc = clksrc; - ourport->baudclk = clk; - } - - switch (termios->c_cflag & CSIZE) { - case CS5: - dbg("config: 5bits/char\n"); - ulcon = S3C2410_LCON_CS5; - break; - case CS6: - dbg("config: 6bits/char\n"); - ulcon = S3C2410_LCON_CS6; - break; - case CS7: - dbg("config: 7bits/char\n"); - ulcon = S3C2410_LCON_CS7; - break; - case CS8: - default: - dbg("config: 8bits/char\n"); - ulcon = S3C2410_LCON_CS8; - break; - } - - /* preserve original lcon IR settings */ - ulcon |= (cfg->ulcon & S3C2410_LCON_IRM); - - if (termios->c_cflag & CSTOPB) - ulcon |= S3C2410_LCON_STOPB; - - umcon = (termios->c_cflag & CRTSCTS) ? S3C2410_UMCOM_AFC : 0; - - if (termios->c_cflag & PARENB) { - if (termios->c_cflag & PARODD) - ulcon |= S3C2410_LCON_PODD; - else - ulcon |= S3C2410_LCON_PEVEN; - } else { - ulcon |= S3C2410_LCON_PNONE; - } - - spin_lock_irqsave(&port->lock, flags); - - dbg("setting ulcon to %08x, brddiv to %d\n", ulcon, quot); - - wr_regl(port, S3C2410_ULCON, ulcon); - wr_regl(port, S3C2410_UBRDIV, quot); - wr_regl(port, S3C2410_UMCON, umcon); - - dbg("uart: ulcon = 0x%08x, ucon = 0x%08x, ufcon = 0x%08x\n", - rd_regl(port, S3C2410_ULCON), - rd_regl(port, S3C2410_UCON), - rd_regl(port, S3C2410_UFCON)); - - /* - * Update the per-port timeout. - */ - uart_update_timeout(port, termios->c_cflag, baud); - - /* - * Which character status flags are we interested in? - */ - port->read_status_mask = S3C2410_UERSTAT_OVERRUN; - if (termios->c_iflag & INPCK) - port->read_status_mask |= S3C2410_UERSTAT_FRAME | S3C2410_UERSTAT_PARITY; - - /* - * Which character status flags should we ignore? - */ - port->ignore_status_mask = 0; - if (termios->c_iflag & IGNPAR) - port->ignore_status_mask |= S3C2410_UERSTAT_OVERRUN; - if (termios->c_iflag & IGNBRK && termios->c_iflag & IGNPAR) - port->ignore_status_mask |= S3C2410_UERSTAT_FRAME; - - /* - * Ignore all characters if CREAD is not set. - */ - if ((termios->c_cflag & CREAD) == 0) - port->ignore_status_mask |= RXSTAT_DUMMY_READ; - - spin_unlock_irqrestore(&port->lock, flags); -} - -static const char *s3c24xx_serial_type(struct uart_port *port) -{ - switch (port->type) { - case PORT_S3C2410: - return "S3C2410"; - case PORT_S3C2440: - return "S3C2440"; - case PORT_S3C2412: - return "S3C2412"; - default: - return NULL; - } -} - -#define MAP_SIZE (0x100) - -static void s3c24xx_serial_release_port(struct uart_port *port) -{ - release_mem_region(port->mapbase, MAP_SIZE); -} - -static int s3c24xx_serial_request_port(struct uart_port *port) -{ - const char *name = s3c24xx_serial_portname(port); - return request_mem_region(port->mapbase, MAP_SIZE, name) ? 0 : -EBUSY; -} - -static void s3c24xx_serial_config_port(struct uart_port *port, int flags) -{ - struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); - - if (flags & UART_CONFIG_TYPE && - s3c24xx_serial_request_port(port) == 0) - port->type = info->type; -} - -/* - * verify the new serial_struct (for TIOCSSERIAL). - */ -static int -s3c24xx_serial_verify_port(struct uart_port *port, struct serial_struct *ser) -{ - struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); - - if (ser->type != PORT_UNKNOWN && ser->type != info->type) - return -EINVAL; - - return 0; -} - - -#ifdef CONFIG_SERIAL_S3C2410_CONSOLE - -static struct console s3c24xx_serial_console; - -#define S3C24XX_SERIAL_CONSOLE &s3c24xx_serial_console -#else -#define S3C24XX_SERIAL_CONSOLE NULL -#endif - -static struct uart_ops s3c24xx_serial_ops = { - .pm = s3c24xx_serial_pm, - .tx_empty = s3c24xx_serial_tx_empty, - .get_mctrl = s3c24xx_serial_get_mctrl, - .set_mctrl = s3c24xx_serial_set_mctrl, - .stop_tx = s3c24xx_serial_stop_tx, - .start_tx = s3c24xx_serial_start_tx, - .stop_rx = s3c24xx_serial_stop_rx, - .enable_ms = s3c24xx_serial_enable_ms, - .break_ctl = s3c24xx_serial_break_ctl, - .startup = s3c24xx_serial_startup, - .shutdown = s3c24xx_serial_shutdown, - .set_termios = s3c24xx_serial_set_termios, - .type = s3c24xx_serial_type, - .release_port = s3c24xx_serial_release_port, - .request_port = s3c24xx_serial_request_port, - .config_port = s3c24xx_serial_config_port, - .verify_port = s3c24xx_serial_verify_port, -}; - - -static struct uart_driver s3c24xx_uart_drv = { - .owner = THIS_MODULE, - .dev_name = "s3c2410_serial", - .nr = 3, - .cons = S3C24XX_SERIAL_CONSOLE, - .driver_name = S3C24XX_SERIAL_NAME, - .major = S3C24XX_SERIAL_MAJOR, - .minor = S3C24XX_SERIAL_MINOR, -}; - -static struct s3c24xx_uart_port s3c24xx_serial_ports[NR_PORTS] = { - [0] = { - .port = { - .lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[0].port.lock), - .iotype = UPIO_MEM, - .irq = IRQ_S3CUART_RX0, - .uartclk = 0, - .fifosize = 16, - .ops = &s3c24xx_serial_ops, - .flags = UPF_BOOT_AUTOCONF, - .line = 0, - } - }, - [1] = { - .port = { - .lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[1].port.lock), - .iotype = UPIO_MEM, - .irq = IRQ_S3CUART_RX1, - .uartclk = 0, - .fifosize = 16, - .ops = &s3c24xx_serial_ops, - .flags = UPF_BOOT_AUTOCONF, - .line = 1, - } - }, -#if NR_PORTS > 2 - - [2] = { - .port = { - .lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[2].port.lock), - .iotype = UPIO_MEM, - .irq = IRQ_S3CUART_RX2, - .uartclk = 0, - .fifosize = 16, - .ops = &s3c24xx_serial_ops, - .flags = UPF_BOOT_AUTOCONF, - .line = 2, - } - } -#endif -}; - -/* s3c24xx_serial_resetport - * - * wrapper to call the specific reset for this port (reset the fifos - * and the settings) -*/ - -static inline int s3c24xx_serial_resetport(struct uart_port * port, - struct s3c2410_uartcfg *cfg) -{ - struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); - - return (info->reset_port)(port, cfg); -} - -/* s3c24xx_serial_init_port - * - * initialise a single serial port from the platform device given - */ - -static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport, - struct s3c24xx_uart_info *info, - struct platform_device *platdev) -{ - struct uart_port *port = &ourport->port; - struct s3c2410_uartcfg *cfg; - struct resource *res; - int ret; - - dbg("s3c24xx_serial_init_port: port=%p, platdev=%p\n", port, platdev); - - if (platdev == NULL) - return -ENODEV; - - cfg = s3c24xx_dev_to_cfg(&platdev->dev); - - if (port->mapbase != 0) - return 0; - - if (cfg->hwport > 3) - return -EINVAL; - - /* setup info for port */ - port->dev = &platdev->dev; - ourport->info = info; - - /* copy the info in from provided structure */ - ourport->port.fifosize = info->fifosize; - - dbg("s3c24xx_serial_init_port: %p (hw %d)...\n", port, cfg->hwport); - - port->uartclk = 1; - - if (cfg->uart_flags & UPF_CONS_FLOW) { - dbg("s3c24xx_serial_init_port: enabling flow control\n"); - port->flags |= UPF_CONS_FLOW; - } - - /* sort our the physical and virtual addresses for each UART */ - - res = platform_get_resource(platdev, IORESOURCE_MEM, 0); - if (res == NULL) { - printk(KERN_ERR "failed to find memory resource for uart\n"); - return -EINVAL; - } - - dbg("resource %p (%lx..%lx)\n", res, res->start, res->end); - - port->mapbase = res->start; - port->membase = S3C24XX_VA_UART + (res->start - S3C24XX_PA_UART); - ret = platform_get_irq(platdev, 0); - if (ret < 0) - port->irq = 0; - else - port->irq = ret; - - ourport->clk = clk_get(&platdev->dev, "uart"); - - dbg("port: map=%08x, mem=%08x, irq=%d, clock=%ld\n", - port->mapbase, port->membase, port->irq, port->uartclk); - - /* reset the fifos (and setup the uart) */ - s3c24xx_serial_resetport(port, cfg); - return 0; -} - -/* Device driver serial port probe */ - -static int probe_index = 0; - -static int s3c24xx_serial_probe(struct platform_device *dev, - struct s3c24xx_uart_info *info) -{ - struct s3c24xx_uart_port *ourport; - int ret; - - dbg("s3c24xx_serial_probe(%p, %p) %d\n", dev, info, probe_index); - - ourport = &s3c24xx_serial_ports[probe_index]; - probe_index++; - - dbg("%s: initialising port %p...\n", __func__, ourport); - - ret = s3c24xx_serial_init_port(ourport, info, dev); - if (ret < 0) - goto probe_err; - - dbg("%s: adding port\n", __func__); - uart_add_one_port(&s3c24xx_uart_drv, &ourport->port); - platform_set_drvdata(dev, &ourport->port); - - return 0; - - probe_err: - return ret; -} - -static int s3c24xx_serial_remove(struct platform_device *dev) -{ - struct uart_port *port = s3c24xx_dev_to_port(&dev->dev); - - if (port) - uart_remove_one_port(&s3c24xx_uart_drv, port); - - return 0; -} - -/* UART power management code */ - -#ifdef CONFIG_PM - -static int s3c24xx_serial_suspend(struct platform_device *dev, pm_message_t state) -{ - struct uart_port *port = s3c24xx_dev_to_port(&dev->dev); - - if (port) - uart_suspend_port(&s3c24xx_uart_drv, port); - - return 0; -} - -static int s3c24xx_serial_resume(struct platform_device *dev) -{ - struct uart_port *port = s3c24xx_dev_to_port(&dev->dev); - struct s3c24xx_uart_port *ourport = to_ourport(port); - - if (port) { - clk_enable(ourport->clk); - s3c24xx_serial_resetport(port, s3c24xx_port_to_cfg(port)); - clk_disable(ourport->clk); - - uart_resume_port(&s3c24xx_uart_drv, port); - } - - return 0; -} - -#else -#define s3c24xx_serial_suspend NULL -#define s3c24xx_serial_resume NULL -#endif - -static int s3c24xx_serial_init(struct platform_driver *drv, - struct s3c24xx_uart_info *info) -{ - dbg("s3c24xx_serial_init(%p,%p)\n", drv, info); - return platform_driver_register(drv); -} - - -/* now comes the code to initialise either the s3c2410 or s3c2440 serial - * port information -*/ - -/* cpu specific variations on the serial port support */ - -#ifdef CONFIG_CPU_S3C2400 - -static int s3c2400_serial_getsource(struct uart_port *port, - struct s3c24xx_uart_clksrc *clk) -{ - clk->divisor = 1; - clk->name = "pclk"; - - return 0; -} - -static int s3c2400_serial_setsource(struct uart_port *port, - struct s3c24xx_uart_clksrc *clk) -{ - return 0; -} - -static int s3c2400_serial_resetport(struct uart_port *port, - struct s3c2410_uartcfg *cfg) -{ - dbg("s3c2400_serial_resetport: port=%p (%08lx), cfg=%p\n", - port, port->mapbase, cfg); - - wr_regl(port, S3C2410_UCON, cfg->ucon); - wr_regl(port, S3C2410_ULCON, cfg->ulcon); - - /* reset both fifos */ - - wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH); - wr_regl(port, S3C2410_UFCON, cfg->ufcon); - - return 0; -} - -static struct s3c24xx_uart_info s3c2400_uart_inf = { - .name = "Samsung S3C2400 UART", - .type = PORT_S3C2400, - .fifosize = 16, - .rx_fifomask = S3C2410_UFSTAT_RXMASK, - .rx_fifoshift = S3C2410_UFSTAT_RXSHIFT, - .rx_fifofull = S3C2410_UFSTAT_RXFULL, - .tx_fifofull = S3C2410_UFSTAT_TXFULL, - .tx_fifomask = S3C2410_UFSTAT_TXMASK, - .tx_fifoshift = S3C2410_UFSTAT_TXSHIFT, - .get_clksrc = s3c2400_serial_getsource, - .set_clksrc = s3c2400_serial_setsource, - .reset_port = s3c2400_serial_resetport, -}; - -static int s3c2400_serial_probe(struct platform_device *dev) -{ - return s3c24xx_serial_probe(dev, &s3c2400_uart_inf); -} - -static struct platform_driver s3c2400_serial_drv = { - .probe = s3c2400_serial_probe, - .remove = s3c24xx_serial_remove, - .suspend = s3c24xx_serial_suspend, - .resume = s3c24xx_serial_resume, - .driver = { - .name = "s3c2400-uart", - .owner = THIS_MODULE, - }, -}; - -static inline int s3c2400_serial_init(void) -{ - return s3c24xx_serial_init(&s3c2400_serial_drv, &s3c2400_uart_inf); -} - -static inline void s3c2400_serial_exit(void) -{ - platform_driver_unregister(&s3c2400_serial_drv); -} - -#define s3c2400_uart_inf_at &s3c2400_uart_inf -#else - -static inline int s3c2400_serial_init(void) -{ - return 0; -} - -static inline void s3c2400_serial_exit(void) -{ -} - -#define s3c2400_uart_inf_at NULL - -#endif /* CONFIG_CPU_S3C2400 */ - -/* S3C2410 support */ - -#ifdef CONFIG_CPU_S3C2410 +#include "samsung.h" static int s3c2410_serial_setsource(struct uart_port *port, struct s3c24xx_uart_clksrc *clk) @@ -1323,8 +83,6 @@ static struct s3c24xx_uart_info s3c2410_uart_inf = { .reset_port = s3c2410_serial_resetport, }; -/* device management */ - static int s3c2410_serial_probe(struct platform_device *dev) { return s3c24xx_serial_probe(dev, &s3c2410_uart_inf); @@ -1333,612 +91,28 @@ static int s3c2410_serial_probe(struct platform_device *dev) static struct platform_driver s3c2410_serial_drv = { .probe = s3c2410_serial_probe, .remove = s3c24xx_serial_remove, - .suspend = s3c24xx_serial_suspend, - .resume = s3c24xx_serial_resume, .driver = { .name = "s3c2410-uart", .owner = THIS_MODULE, }, }; -static inline int s3c2410_serial_init(void) +s3c24xx_console_init(&s3c2410_serial_drv, &s3c2410_uart_inf); + +static int __init s3c2410_serial_init(void) { return s3c24xx_serial_init(&s3c2410_serial_drv, &s3c2410_uart_inf); } -static inline void s3c2410_serial_exit(void) +static void __exit s3c2410_serial_exit(void) { platform_driver_unregister(&s3c2410_serial_drv); } -#define s3c2410_uart_inf_at &s3c2410_uart_inf -#else - -static inline int s3c2410_serial_init(void) -{ - return 0; -} - -static inline void s3c2410_serial_exit(void) -{ -} - -#define s3c2410_uart_inf_at NULL - -#endif /* CONFIG_CPU_S3C2410 */ - -#if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2442) - -static int s3c2440_serial_setsource(struct uart_port *port, - struct s3c24xx_uart_clksrc *clk) -{ - unsigned long ucon = rd_regl(port, S3C2410_UCON); - - // todo - proper fclk<>nonfclk switch // - - ucon &= ~S3C2440_UCON_CLKMASK; - - if (strcmp(clk->name, "uclk") == 0) - ucon |= S3C2440_UCON_UCLK; - else if (strcmp(clk->name, "pclk") == 0) - ucon |= S3C2440_UCON_PCLK; - else if (strcmp(clk->name, "fclk") == 0) - ucon |= S3C2440_UCON_FCLK; - else { - printk(KERN_ERR "unknown clock source %s\n", clk->name); - return -EINVAL; - } - - wr_regl(port, S3C2410_UCON, ucon); - return 0; -} - - -static int s3c2440_serial_getsource(struct uart_port *port, - struct s3c24xx_uart_clksrc *clk) -{ - unsigned long ucon = rd_regl(port, S3C2410_UCON); - unsigned long ucon0, ucon1, ucon2; - - switch (ucon & S3C2440_UCON_CLKMASK) { - case S3C2440_UCON_UCLK: - clk->divisor = 1; - clk->name = "uclk"; - break; - - case S3C2440_UCON_PCLK: - case S3C2440_UCON_PCLK2: - clk->divisor = 1; - clk->name = "pclk"; - break; - - case S3C2440_UCON_FCLK: - /* the fun of calculating the uart divisors on - * the s3c2440 */ - - ucon0 = __raw_readl(S3C24XX_VA_UART0 + S3C2410_UCON); - ucon1 = __raw_readl(S3C24XX_VA_UART1 + S3C2410_UCON); - ucon2 = __raw_readl(S3C24XX_VA_UART2 + S3C2410_UCON); - - printk("ucons: %08lx, %08lx, %08lx\n", ucon0, ucon1, ucon2); - - ucon0 &= S3C2440_UCON0_DIVMASK; - ucon1 &= S3C2440_UCON1_DIVMASK; - ucon2 &= S3C2440_UCON2_DIVMASK; - - if (ucon0 != 0) { - clk->divisor = ucon0 >> S3C2440_UCON_DIVSHIFT; - clk->divisor += 6; - } else if (ucon1 != 0) { - clk->divisor = ucon1 >> S3C2440_UCON_DIVSHIFT; - clk->divisor += 21; - } else if (ucon2 != 0) { - clk->divisor = ucon2 >> S3C2440_UCON_DIVSHIFT; - clk->divisor += 36; - } else { - /* manual calims 44, seems to be 9 */ - clk->divisor = 9; - } - - clk->name = "fclk"; - break; - } - - return 0; -} - -static int s3c2440_serial_resetport(struct uart_port *port, - struct s3c2410_uartcfg *cfg) -{ - unsigned long ucon = rd_regl(port, S3C2410_UCON); - - dbg("s3c2440_serial_resetport: port=%p (%08lx), cfg=%p\n", - port, port->mapbase, cfg); - - /* ensure we don't change the clock settings... */ - - ucon &= (S3C2440_UCON0_DIVMASK | (3<<10)); - - wr_regl(port, S3C2410_UCON, ucon | cfg->ucon); - wr_regl(port, S3C2410_ULCON, cfg->ulcon); - - /* reset both fifos */ - - wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH); - wr_regl(port, S3C2410_UFCON, cfg->ufcon); - - return 0; -} - -static struct s3c24xx_uart_info s3c2440_uart_inf = { - .name = "Samsung S3C2440 UART", - .type = PORT_S3C2440, - .fifosize = 64, - .rx_fifomask = S3C2440_UFSTAT_RXMASK, - .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT, - .rx_fifofull = S3C2440_UFSTAT_RXFULL, - .tx_fifofull = S3C2440_UFSTAT_TXFULL, - .tx_fifomask = S3C2440_UFSTAT_TXMASK, - .tx_fifoshift = S3C2440_UFSTAT_TXSHIFT, - .get_clksrc = s3c2440_serial_getsource, - .set_clksrc = s3c2440_serial_setsource, - .reset_port = s3c2440_serial_resetport, -}; - -/* device management */ - -static int s3c2440_serial_probe(struct platform_device *dev) -{ - dbg("s3c2440_serial_probe: dev=%p\n", dev); - return s3c24xx_serial_probe(dev, &s3c2440_uart_inf); -} - -static struct platform_driver s3c2440_serial_drv = { - .probe = s3c2440_serial_probe, - .remove = s3c24xx_serial_remove, - .suspend = s3c24xx_serial_suspend, - .resume = s3c24xx_serial_resume, - .driver = { - .name = "s3c2440-uart", - .owner = THIS_MODULE, - }, -}; - - -static inline int s3c2440_serial_init(void) -{ - return s3c24xx_serial_init(&s3c2440_serial_drv, &s3c2440_uart_inf); -} - -static inline void s3c2440_serial_exit(void) -{ - platform_driver_unregister(&s3c2440_serial_drv); -} - -#define s3c2440_uart_inf_at &s3c2440_uart_inf -#else - -static inline int s3c2440_serial_init(void) -{ - return 0; -} - -static inline void s3c2440_serial_exit(void) -{ -} - -#define s3c2440_uart_inf_at NULL -#endif /* CONFIG_CPU_S3C2440 */ - -#if defined(CONFIG_CPU_S3C2412) - -static int s3c2412_serial_setsource(struct uart_port *port, - struct s3c24xx_uart_clksrc *clk) -{ - unsigned long ucon = rd_regl(port, S3C2410_UCON); - - ucon &= ~S3C2412_UCON_CLKMASK; - - if (strcmp(clk->name, "uclk") == 0) - ucon |= S3C2440_UCON_UCLK; - else if (strcmp(clk->name, "pclk") == 0) - ucon |= S3C2440_UCON_PCLK; - else if (strcmp(clk->name, "usysclk") == 0) - ucon |= S3C2412_UCON_USYSCLK; - else { - printk(KERN_ERR "unknown clock source %s\n", clk->name); - return -EINVAL; - } - - wr_regl(port, S3C2410_UCON, ucon); - return 0; -} - - -static int s3c2412_serial_getsource(struct uart_port *port, - struct s3c24xx_uart_clksrc *clk) -{ - unsigned long ucon = rd_regl(port, S3C2410_UCON); - - switch (ucon & S3C2412_UCON_CLKMASK) { - case S3C2412_UCON_UCLK: - clk->divisor = 1; - clk->name = "uclk"; - break; - - case S3C2412_UCON_PCLK: - case S3C2412_UCON_PCLK2: - clk->divisor = 1; - clk->name = "pclk"; - break; - - case S3C2412_UCON_USYSCLK: - clk->divisor = 1; - clk->name = "usysclk"; - break; - } - - return 0; -} - -static int s3c2412_serial_resetport(struct uart_port *port, - struct s3c2410_uartcfg *cfg) -{ - unsigned long ucon = rd_regl(port, S3C2410_UCON); - - dbg("%s: port=%p (%08lx), cfg=%p\n", - __func__, port, port->mapbase, cfg); - - /* ensure we don't change the clock settings... */ - - ucon &= S3C2412_UCON_CLKMASK; - - wr_regl(port, S3C2410_UCON, ucon | cfg->ucon); - wr_regl(port, S3C2410_ULCON, cfg->ulcon); - - /* reset both fifos */ - - wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH); - wr_regl(port, S3C2410_UFCON, cfg->ufcon); - - return 0; -} - -static struct s3c24xx_uart_info s3c2412_uart_inf = { - .name = "Samsung S3C2412 UART", - .type = PORT_S3C2412, - .fifosize = 64, - .rx_fifomask = S3C2440_UFSTAT_RXMASK, - .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT, - .rx_fifofull = S3C2440_UFSTAT_RXFULL, - .tx_fifofull = S3C2440_UFSTAT_TXFULL, - .tx_fifomask = S3C2440_UFSTAT_TXMASK, - .tx_fifoshift = S3C2440_UFSTAT_TXSHIFT, - .get_clksrc = s3c2412_serial_getsource, - .set_clksrc = s3c2412_serial_setsource, - .reset_port = s3c2412_serial_resetport, -}; - -/* device management */ - -static int s3c2412_serial_probe(struct platform_device *dev) -{ - dbg("s3c2440_serial_probe: dev=%p\n", dev); - return s3c24xx_serial_probe(dev, &s3c2412_uart_inf); -} - -static struct platform_driver s3c2412_serial_drv = { - .probe = s3c2412_serial_probe, - .remove = s3c24xx_serial_remove, - .suspend = s3c24xx_serial_suspend, - .resume = s3c24xx_serial_resume, - .driver = { - .name = "s3c2412-uart", - .owner = THIS_MODULE, - }, -}; - - -static inline int s3c2412_serial_init(void) -{ - return s3c24xx_serial_init(&s3c2412_serial_drv, &s3c2412_uart_inf); -} - -static inline void s3c2412_serial_exit(void) -{ - platform_driver_unregister(&s3c2412_serial_drv); -} - -#define s3c2412_uart_inf_at &s3c2412_uart_inf -#else - -static inline int s3c2412_serial_init(void) -{ - return 0; -} - -static inline void s3c2412_serial_exit(void) -{ -} - -#define s3c2412_uart_inf_at NULL -#endif /* CONFIG_CPU_S3C2440 */ - - -/* module initialisation code */ - -static int __init s3c24xx_serial_modinit(void) -{ - int ret; - - ret = uart_register_driver(&s3c24xx_uart_drv); - if (ret < 0) { - printk(KERN_ERR "failed to register UART driver\n"); - return -1; - } - - s3c2400_serial_init(); - s3c2410_serial_init(); - s3c2412_serial_init(); - s3c2440_serial_init(); - - return 0; -} - -static void __exit s3c24xx_serial_modexit(void) -{ - s3c2400_serial_exit(); - s3c2410_serial_exit(); - s3c2412_serial_exit(); - s3c2440_serial_exit(); - - uart_unregister_driver(&s3c24xx_uart_drv); -} - - -module_init(s3c24xx_serial_modinit); -module_exit(s3c24xx_serial_modexit); - -/* Console code */ - -#ifdef CONFIG_SERIAL_S3C2410_CONSOLE - -static struct uart_port *cons_uart; - -static int -s3c24xx_serial_console_txrdy(struct uart_port *port, unsigned int ufcon) -{ - struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); - unsigned long ufstat, utrstat; - - if (ufcon & S3C2410_UFCON_FIFOMODE) { - /* fifo mode - check ammount of data in fifo registers... */ - - ufstat = rd_regl(port, S3C2410_UFSTAT); - return (ufstat & info->tx_fifofull) ? 0 : 1; - } - - /* in non-fifo mode, we go and use the tx buffer empty */ - - utrstat = rd_regl(port, S3C2410_UTRSTAT); - return (utrstat & S3C2410_UTRSTAT_TXE) ? 1 : 0; -} - -static void -s3c24xx_serial_console_putchar(struct uart_port *port, int ch) -{ - unsigned int ufcon = rd_regl(cons_uart, S3C2410_UFCON); - while (!s3c24xx_serial_console_txrdy(port, ufcon)) - barrier(); - wr_regb(cons_uart, S3C2410_UTXH, ch); -} - -static void -s3c24xx_serial_console_write(struct console *co, const char *s, - unsigned int count) -{ - uart_console_write(cons_uart, s, count, s3c24xx_serial_console_putchar); -} - -static void __init -s3c24xx_serial_get_options(struct uart_port *port, int *baud, - int *parity, int *bits) -{ - struct s3c24xx_uart_clksrc clksrc; - struct clk *clk; - unsigned int ulcon; - unsigned int ucon; - unsigned int ubrdiv; - unsigned long rate; - - ulcon = rd_regl(port, S3C2410_ULCON); - ucon = rd_regl(port, S3C2410_UCON); - ubrdiv = rd_regl(port, S3C2410_UBRDIV); - - dbg("s3c24xx_serial_get_options: port=%p\n" - "registers: ulcon=%08x, ucon=%08x, ubdriv=%08x\n", - port, ulcon, ucon, ubrdiv); - - if ((ucon & 0xf) != 0) { - /* consider the serial port configured if the tx/rx mode set */ - - switch (ulcon & S3C2410_LCON_CSMASK) { - case S3C2410_LCON_CS5: - *bits = 5; - break; - case S3C2410_LCON_CS6: - *bits = 6; - break; - case S3C2410_LCON_CS7: - *bits = 7; - break; - default: - case S3C2410_LCON_CS8: - *bits = 8; - break; - } - - switch (ulcon & S3C2410_LCON_PMASK) { - case S3C2410_LCON_PEVEN: - *parity = 'e'; - break; - - case S3C2410_LCON_PODD: - *parity = 'o'; - break; - - case S3C2410_LCON_PNONE: - default: - *parity = 'n'; - } - - /* now calculate the baud rate */ - - s3c24xx_serial_getsource(port, &clksrc); - - clk = clk_get(port->dev, clksrc.name); - if (!IS_ERR(clk) && clk != NULL) - rate = clk_get_rate(clk) / clksrc.divisor; - else - rate = 1; - - - *baud = rate / ( 16 * (ubrdiv + 1)); - dbg("calculated baud %d\n", *baud); - } - -} - -/* s3c24xx_serial_init_ports - * - * initialise the serial ports from the machine provided initialisation - * data. -*/ - -static int s3c24xx_serial_init_ports(struct s3c24xx_uart_info *info) -{ - struct s3c24xx_uart_port *ptr = s3c24xx_serial_ports; - struct platform_device **platdev_ptr; - int i; - - dbg("s3c24xx_serial_init_ports: initialising ports...\n"); - - platdev_ptr = s3c24xx_uart_devs; - - for (i = 0; i < NR_PORTS; i++, ptr++, platdev_ptr++) { - s3c24xx_serial_init_port(ptr, info, *platdev_ptr); - } - - return 0; -} - -static int __init -s3c24xx_serial_console_setup(struct console *co, char *options) -{ - struct uart_port *port; - int baud = 9600; - int bits = 8; - int parity = 'n'; - int flow = 'n'; - - dbg("s3c24xx_serial_console_setup: co=%p (%d), %s\n", - co, co->index, options); - - /* is this a valid port */ - - if (co->index == -1 || co->index >= NR_PORTS) - co->index = 0; - - port = &s3c24xx_serial_ports[co->index].port; - - /* is the port configured? */ - - if (port->mapbase == 0x0) { - co->index = 0; - port = &s3c24xx_serial_ports[co->index].port; - } - - cons_uart = port; - - dbg("s3c24xx_serial_console_setup: port=%p (%d)\n", port, co->index); - - /* - * Check whether an invalid uart number has been specified, and - * if so, search for the first available port that does have - * console support. - */ - if (options) - uart_parse_options(options, &baud, &parity, &bits, &flow); - else - s3c24xx_serial_get_options(port, &baud, &parity, &bits); - - dbg("s3c24xx_serial_console_setup: baud %d\n", baud); - - return uart_set_options(port, co, baud, parity, bits, flow); -} - -/* s3c24xx_serial_initconsole - * - * initialise the console from one of the uart drivers -*/ - -static struct console s3c24xx_serial_console = -{ - .name = S3C24XX_SERIAL_NAME, - .device = uart_console_device, - .flags = CON_PRINTBUFFER, - .index = -1, - .write = s3c24xx_serial_console_write, - .setup = s3c24xx_serial_console_setup -}; - -static int s3c24xx_serial_initconsole(void) -{ - struct s3c24xx_uart_info *info; - struct platform_device *dev = s3c24xx_uart_devs[0]; - - dbg("s3c24xx_serial_initconsole\n"); - - /* select driver based on the cpu */ - - if (dev == NULL) { - printk(KERN_ERR "s3c24xx: no devices for console init\n"); - return 0; - } - - if (strcmp(dev->name, "s3c2400-uart") == 0) { - info = s3c2400_uart_inf_at; - } else if (strcmp(dev->name, "s3c2410-uart") == 0) { - info = s3c2410_uart_inf_at; - } else if (strcmp(dev->name, "s3c2440-uart") == 0) { - info = s3c2440_uart_inf_at; - } else if (strcmp(dev->name, "s3c2412-uart") == 0) { - info = s3c2412_uart_inf_at; - } else { - printk(KERN_ERR "s3c24xx: no driver for %s\n", dev->name); - return 0; - } - - if (info == NULL) { - printk(KERN_ERR "s3c24xx: no driver for console\n"); - return 0; - } - - s3c24xx_serial_console.data = &s3c24xx_uart_drv; - s3c24xx_serial_init_ports(info); - - register_console(&s3c24xx_serial_console); - return 0; -} - -console_initcall(s3c24xx_serial_initconsole); - -#endif /* CONFIG_SERIAL_S3C2410_CONSOLE */ +module_init(s3c2410_serial_init); +module_exit(s3c2410_serial_exit); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); -MODULE_DESCRIPTION("Samsung S3C2410/S3C2440/S3C2412 Serial port driver"); -MODULE_ALIAS("platform:s3c2400-uart"); +MODULE_DESCRIPTION("Samsung S3C2410 SoC Serial port driver"); MODULE_ALIAS("platform:s3c2410-uart"); -MODULE_ALIAS("platform:s3c2412-uart"); -MODULE_ALIAS("platform:s3c2440-uart"); diff --git a/drivers/serial/s3c2412.c b/drivers/serial/s3c2412.c new file mode 100644 index 00000000000..ce0c220e3e9 --- /dev/null +++ b/drivers/serial/s3c2412.c @@ -0,0 +1,151 @@ +/* linux/drivers/serial/s3c2412.c + * + * Driver for Samsung S3C2412 and S3C2413 SoC onboard UARTs. + * + * Ben Dooks, Copyright (c) 2003-2005,2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/module.h> +#include <linux/ioport.h> +#include <linux/io.h> +#include <linux/platform_device.h> +#include <linux/init.h> +#include <linux/serial_core.h> +#include <linux/serial.h> + +#include <asm/irq.h> +#include <asm/hardware.h> + +#include <asm/plat-s3c/regs-serial.h> +#include <asm/arch/regs-gpio.h> + +#include "samsung.h" + +static int s3c2412_serial_setsource(struct uart_port *port, + struct s3c24xx_uart_clksrc *clk) +{ + unsigned long ucon = rd_regl(port, S3C2410_UCON); + + ucon &= ~S3C2412_UCON_CLKMASK; + + if (strcmp(clk->name, "uclk") == 0) + ucon |= S3C2440_UCON_UCLK; + else if (strcmp(clk->name, "pclk") == 0) + ucon |= S3C2440_UCON_PCLK; + else if (strcmp(clk->name, "usysclk") == 0) + ucon |= S3C2412_UCON_USYSCLK; + else { + printk(KERN_ERR "unknown clock source %s\n", clk->name); + return -EINVAL; + } + + wr_regl(port, S3C2410_UCON, ucon); + return 0; +} + + +static int s3c2412_serial_getsource(struct uart_port *port, + struct s3c24xx_uart_clksrc *clk) +{ + unsigned long ucon = rd_regl(port, S3C2410_UCON); + + switch (ucon & S3C2412_UCON_CLKMASK) { + case S3C2412_UCON_UCLK: + clk->divisor = 1; + clk->name = "uclk"; + break; + + case S3C2412_UCON_PCLK: + case S3C2412_UCON_PCLK2: + clk->divisor = 1; + clk->name = "pclk"; + break; + + case S3C2412_UCON_USYSCLK: + clk->divisor = 1; + clk->name = "usysclk"; + break; + } + + return 0; +} + +static int s3c2412_serial_resetport(struct uart_port *port, + struct s3c2410_uartcfg *cfg) +{ + unsigned long ucon = rd_regl(port, S3C2410_UCON); + + dbg("%s: port=%p (%08lx), cfg=%p\n", + __func__, port, port->mapbase, cfg); + + /* ensure we don't change the clock settings... */ + + ucon &= S3C2412_UCON_CLKMASK; + + wr_regl(port, S3C2410_UCON, ucon | cfg->ucon); + wr_regl(port, S3C2410_ULCON, cfg->ulcon); + + /* reset both fifos */ + + wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH); + wr_regl(port, S3C2410_UFCON, cfg->ufcon); + + return 0; +} + +static struct s3c24xx_uart_info s3c2412_uart_inf = { + .name = "Samsung S3C2412 UART", + .type = PORT_S3C2412, + .fifosize = 64, + .rx_fifomask = S3C2440_UFSTAT_RXMASK, + .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT, + .rx_fifofull = S3C2440_UFSTAT_RXFULL, + .tx_fifofull = S3C2440_UFSTAT_TXFULL, + .tx_fifomask = S3C2440_UFSTAT_TXMASK, + .tx_fifoshift = S3C2440_UFSTAT_TXSHIFT, + .get_clksrc = s3c2412_serial_getsource, + .set_clksrc = s3c2412_serial_setsource, + .reset_port = s3c2412_serial_resetport, +}; + +/* device management */ + +static int s3c2412_serial_probe(struct platform_device *dev) +{ + dbg("s3c2440_serial_probe: dev=%p\n", dev); + return s3c24xx_serial_probe(dev, &s3c2412_uart_inf); +} + +static struct platform_driver s3c2412_serial_drv = { + .probe = s3c2412_serial_probe, + .remove = s3c24xx_serial_remove, + .driver = { + .name = "s3c2412-uart", + .owner = THIS_MODULE, + }, +}; + +s3c24xx_console_init(&s3c2412_serial_drv, &s3c2412_uart_inf); + +static inline int s3c2412_serial_init(void) +{ + return s3c24xx_serial_init(&s3c2412_serial_drv, &s3c2412_uart_inf); +} + +static inline void s3c2412_serial_exit(void) +{ + platform_driver_unregister(&s3c2412_serial_drv); +} + +module_init(s3c2412_serial_init); +module_exit(s3c2412_serial_exit); + +MODULE_DESCRIPTION("Samsung S3C2412,S3C2413 SoC Serial port driver"); +MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:s3c2412-uart"); diff --git a/drivers/serial/s3c2440.c b/drivers/serial/s3c2440.c new file mode 100644 index 00000000000..38f954bd39c --- /dev/null +++ b/drivers/serial/s3c2440.c @@ -0,0 +1,181 @@ +/* linux/drivers/serial/s3c2440.c + * + * Driver for Samsung S3C2440 and S3C2442 SoC onboard UARTs. + * + * Ben Dooks, Copyright (c) 2003-2005,2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/module.h> +#include <linux/ioport.h> +#include <linux/io.h> +#include <linux/platform_device.h> +#include <linux/init.h> +#include <linux/serial_core.h> +#include <linux/serial.h> + +#include <asm/irq.h> +#include <asm/hardware.h> + +#include <asm/plat-s3c/regs-serial.h> +#include <asm/arch/regs-gpio.h> + +#include "samsung.h" + + +static int s3c2440_serial_setsource(struct uart_port *port, + struct s3c24xx_uart_clksrc *clk) +{ + unsigned long ucon = rd_regl(port, S3C2410_UCON); + + /* todo - proper fclk<>nonfclk switch. */ + + ucon &= ~S3C2440_UCON_CLKMASK; + + if (strcmp(clk->name, "uclk") == 0) + ucon |= S3C2440_UCON_UCLK; + else if (strcmp(clk->name, "pclk") == 0) + ucon |= S3C2440_UCON_PCLK; + else if (strcmp(clk->name, "fclk") == 0) + ucon |= S3C2440_UCON_FCLK; + else { + printk(KERN_ERR "unknown clock source %s\n", clk->name); + return -EINVAL; + } + + wr_regl(port, S3C2410_UCON, ucon); + return 0; +} + + +static int s3c2440_serial_getsource(struct uart_port *port, + struct s3c24xx_uart_clksrc *clk) +{ + unsigned long ucon = rd_regl(port, S3C2410_UCON); + unsigned long ucon0, ucon1, ucon2; + + switch (ucon & S3C2440_UCON_CLKMASK) { + case S3C2440_UCON_UCLK: + clk->divisor = 1; + clk->name = "uclk"; + break; + + case S3C2440_UCON_PCLK: + case S3C2440_UCON_PCLK2: + clk->divisor = 1; + clk->name = "pclk"; + break; + + case S3C2440_UCON_FCLK: + /* the fun of calculating the uart divisors on + * the s3c2440 */ + + ucon0 = __raw_readl(S3C24XX_VA_UART0 + S3C2410_UCON); + ucon1 = __raw_readl(S3C24XX_VA_UART1 + S3C2410_UCON); + ucon2 = __raw_readl(S3C24XX_VA_UART2 + S3C2410_UCON); + + printk("ucons: %08lx, %08lx, %08lx\n", ucon0, ucon1, ucon2); + + ucon0 &= S3C2440_UCON0_DIVMASK; + ucon1 &= S3C2440_UCON1_DIVMASK; + ucon2 &= S3C2440_UCON2_DIVMASK; + + if (ucon0 != 0) { + clk->divisor = ucon0 >> S3C2440_UCON_DIVSHIFT; + clk->divisor += 6; + } else if (ucon1 != 0) { + clk->divisor = ucon1 >> S3C2440_UCON_DIVSHIFT; + clk->divisor += 21; + } else if (ucon2 != 0) { + clk->divisor = ucon2 >> S3C2440_UCON_DIVSHIFT; + clk->divisor += 36; + } else { + /* manual calims 44, seems to be 9 */ + clk->divisor = 9; + } + + clk->name = "fclk"; + break; + } + + return 0; +} + +static int s3c2440_serial_resetport(struct uart_port *port, + struct s3c2410_uartcfg *cfg) +{ + unsigned long ucon = rd_regl(port, S3C2410_UCON); + + dbg("s3c2440_serial_resetport: port=%p (%08lx), cfg=%p\n", + port, port->mapbase, cfg); + + /* ensure we don't change the clock settings... */ + + ucon &= (S3C2440_UCON0_DIVMASK | (3<<10)); + + wr_regl(port, S3C2410_UCON, ucon | cfg->ucon); + wr_regl(port, S3C2410_ULCON, cfg->ulcon); + + /* reset both fifos */ + + wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH); + wr_regl(port, S3C2410_UFCON, cfg->ufcon); + + return 0; +} + +static struct s3c24xx_uart_info s3c2440_uart_inf = { + .name = "Samsung S3C2440 UART", + .type = PORT_S3C2440, + .fifosize = 64, + .rx_fifomask = S3C2440_UFSTAT_RXMASK, + .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT, + .rx_fifofull = S3C2440_UFSTAT_RXFULL, + .tx_fifofull = S3C2440_UFSTAT_TXFULL, + .tx_fifomask = S3C2440_UFSTAT_TXMASK, + .tx_fifoshift = S3C2440_UFSTAT_TXSHIFT, + .get_clksrc = s3c2440_serial_getsource, + .set_clksrc = s3c2440_serial_setsource, + .reset_port = s3c2440_serial_resetport, +}; + +/* device management */ + +static int s3c2440_serial_probe(struct platform_device *dev) +{ + dbg("s3c2440_serial_probe: dev=%p\n", dev); + return s3c24xx_serial_probe(dev, &s3c2440_uart_inf); +} + +static struct platform_driver s3c2440_serial_drv = { + .probe = s3c2440_serial_probe, + .remove = s3c24xx_serial_remove, + .driver = { + .name = "s3c2440-uart", + .owner = THIS_MODULE, + }, +}; + +s3c24xx_console_init(&s3c2440_serial_drv, &s3c2440_uart_inf); + +static int __init s3c2440_serial_init(void) +{ + return s3c24xx_serial_init(&s3c2440_serial_drv, &s3c2440_uart_inf); +} + +static void __exit s3c2440_serial_exit(void) +{ + platform_driver_unregister(&s3c2440_serial_drv); +} + +module_init(s3c2440_serial_init); +module_exit(s3c2440_serial_exit); + +MODULE_DESCRIPTION("Samsung S3C2440,S3C2442 SoC Serial port driver"); +MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); +MODULE_LICENSE("GPLi v2"); +MODULE_ALIAS("platform:s3c2440-uart"); diff --git a/drivers/serial/samsung.c b/drivers/serial/samsung.c new file mode 100644 index 00000000000..4a3ecaa629e --- /dev/null +++ b/drivers/serial/samsung.c @@ -0,0 +1,1317 @@ +/* linux/drivers/serial/samsuing.c + * + * Driver core for Samsung SoC onboard UARTs. + * + * Ben Dooks, Copyright (c) 2003-2005,2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +/* Hote on 2410 error handling + * + * The s3c2410 manual has a love/hate affair with the contents of the + * UERSTAT register in the UART blocks, and keeps marking some of the + * error bits as reserved. Having checked with the s3c2410x01, + * it copes with BREAKs properly, so I am happy to ignore the RESERVED + * feature from the latter versions of the manual. + * + * If it becomes aparrent that latter versions of the 2410 remove these + * bits, then action will have to be taken to differentiate the versions + * and change the policy on BREAK + * + * BJD, 04-Nov-2004 +*/ + +#if defined(CONFIG_SERIAL_SAMSUNG_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +#define SUPPORT_SYSRQ +#endif + +#include <linux/module.h> +#include <linux/ioport.h> +#include <linux/io.h> +#include <linux/platform_device.h> +#include <linux/init.h> +#include <linux/sysrq.h> +#include <linux/console.h> +#include <linux/tty.h> +#include <linux/tty_flip.h> +#include <linux/serial_core.h> +#include <linux/serial.h> +#include <linux/delay.h> +#include <linux/clk.h> + +#include <asm/irq.h> + +#include <asm/hardware.h> + +#include <asm/plat-s3c/regs-serial.h> +#include <asm/arch/regs-gpio.h> + +#include "samsung.h" + +/* UART name and device definitions */ + +#define S3C24XX_SERIAL_NAME "ttySAC" +#define S3C24XX_SERIAL_MAJOR 204 +#define S3C24XX_SERIAL_MINOR 64 + +/* we can support 3 uarts, but not always use them */ + +#ifdef CONFIG_CPU_S3C2400 +#define NR_PORTS (2) +#else +#define NR_PORTS (3) +#endif + +/* port irq numbers */ + +#define TX_IRQ(port) ((port)->irq + 1) +#define RX_IRQ(port) ((port)->irq) + +/* macros to change one thing to another */ + +#define tx_enabled(port) ((port)->unused[0]) +#define rx_enabled(port) ((port)->unused[1]) + +/* flag to ignore all characters comming in */ +#define RXSTAT_DUMMY_READ (0x10000000) + +static inline struct s3c24xx_uart_port *to_ourport(struct uart_port *port) +{ + return container_of(port, struct s3c24xx_uart_port, port); +} + +/* translate a port to the device name */ + +static inline const char *s3c24xx_serial_portname(struct uart_port *port) +{ + return to_platform_device(port->dev)->name; +} + +static int s3c24xx_serial_txempty_nofifo(struct uart_port *port) +{ + return (rd_regl(port, S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE); +} + +static void s3c24xx_serial_rx_enable(struct uart_port *port) +{ + unsigned long flags; + unsigned int ucon, ufcon; + int count = 10000; + + spin_lock_irqsave(&port->lock, flags); + + while (--count && !s3c24xx_serial_txempty_nofifo(port)) + udelay(100); + + ufcon = rd_regl(port, S3C2410_UFCON); + ufcon |= S3C2410_UFCON_RESETRX; + wr_regl(port, S3C2410_UFCON, ufcon); + + ucon = rd_regl(port, S3C2410_UCON); + ucon |= S3C2410_UCON_RXIRQMODE; + wr_regl(port, S3C2410_UCON, ucon); + + rx_enabled(port) = 1; + spin_unlock_irqrestore(&port->lock, flags); +} + +static void s3c24xx_serial_rx_disable(struct uart_port *port) +{ + unsigned long flags; + unsigned int ucon; + + spin_lock_irqsave(&port->lock, flags); + + ucon = rd_regl(port, S3C2410_UCON); + ucon &= ~S3C2410_UCON_RXIRQMODE; + wr_regl(port, S3C2410_UCON, ucon); + + rx_enabled(port) = 0; + spin_unlock_irqrestore(&port->lock, flags); +} + +static void s3c24xx_serial_stop_tx(struct uart_port *port) +{ + if (tx_enabled(port)) { + disable_irq(TX_IRQ(port)); + tx_enabled(port) = 0; + if (port->flags & UPF_CONS_FLOW) + s3c24xx_serial_rx_enable(port); + } +} + +static void s3c24xx_serial_start_tx(struct uart_port *port) +{ + if (!tx_enabled(port)) { + if (port->flags & UPF_CONS_FLOW) + s3c24xx_serial_rx_disable(port); + + enable_irq(TX_IRQ(port)); + tx_enabled(port) = 1; + } +} + + +static void s3c24xx_serial_stop_rx(struct uart_port *port) +{ + if (rx_enabled(port)) { + dbg("s3c24xx_serial_stop_rx: port=%p\n", port); + disable_irq(RX_IRQ(port)); + rx_enabled(port) = 0; + } +} + +static void s3c24xx_serial_enable_ms(struct uart_port *port) +{ +} + +static inline struct s3c24xx_uart_info *s3c24xx_port_to_info(struct uart_port *port) +{ + return to_ourport(port)->info; +} + +static inline struct s3c2410_uartcfg *s3c24xx_port_to_cfg(struct uart_port *port) +{ + if (port->dev == NULL) + return NULL; + + return (struct s3c2410_uartcfg *)port->dev->platform_data; +} + +static int s3c24xx_serial_rx_fifocnt(struct s3c24xx_uart_port *ourport, + unsigned long ufstat) +{ + struct s3c24xx_uart_info *info = ourport->info; + + if (ufstat & info->rx_fifofull) + return info->fifosize; + + return (ufstat & info->rx_fifomask) >> info->rx_fifoshift; +} + + +/* ? - where has parity gone?? */ +#define S3C2410_UERSTAT_PARITY (0x1000) + +static irqreturn_t +s3c24xx_serial_rx_chars(int irq, void *dev_id) +{ + struct s3c24xx_uart_port *ourport = dev_id; + struct uart_port *port = &ourport->port; + struct tty_struct *tty = port->info->tty; + unsigned int ufcon, ch, flag, ufstat, uerstat; + int max_count = 64; + + while (max_count-- > 0) { + ufcon = rd_regl(port, S3C2410_UFCON); + ufstat = rd_regl(port, S3C2410_UFSTAT); + + if (s3c24xx_serial_rx_fifocnt(ourport, ufstat) == 0) + break; + + uerstat = rd_regl(port, S3C2410_UERSTAT); + ch = rd_regb(port, S3C2410_URXH); + + if (port->flags & UPF_CONS_FLOW) { + int txe = s3c24xx_serial_txempty_nofifo(port); + + if (rx_enabled(port)) { + if (!txe) { + rx_enabled(port) = 0; + continue; + } + } else { + if (txe) { + ufcon |= S3C2410_UFCON_RESETRX; + wr_regl(port, S3C2410_UFCON, ufcon); + rx_enabled(port) = 1; + goto out; + } + continue; + } + } + + /* insert the character into the buffer */ + + flag = TTY_NORMAL; + port->icount.rx++; + + if (unlikely(uerstat & S3C2410_UERSTAT_ANY)) { + dbg("rxerr: port ch=0x%02x, rxs=0x%08x\n", + ch, uerstat); + + /* check for break */ + if (uerstat & S3C2410_UERSTAT_BREAK) { + dbg("break!\n"); + port->icount.brk++; + if (uart_handle_break(port)) + goto ignore_char; + } + + if (uerstat & S3C2410_UERSTAT_FRAME) + port->icount.frame++; + if (uerstat & S3C2410_UERSTAT_OVERRUN) + port->icount.overrun++; + + uerstat &= port->read_status_mask; + + if (uerstat & S3C2410_UERSTAT_BREAK) + flag = TTY_BREAK; + else if (uerstat & S3C2410_UERSTAT_PARITY) + flag = TTY_PARITY; + else if (uerstat & (S3C2410_UERSTAT_FRAME | + S3C2410_UERSTAT_OVERRUN)) + flag = TTY_FRAME; + } + + if (uart_handle_sysrq_char(port, ch)) + goto ignore_char; + + uart_insert_char(port, uerstat, S3C2410_UERSTAT_OVERRUN, + ch, flag); + + ignore_char: + continue; + } + tty_flip_buffer_push(tty); + + out: + return IRQ_HANDLED; +} + +static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id) +{ + struct s3c24xx_uart_port *ourport = id; + struct uart_port *port = &ourport->port; + struct circ_buf *xmit = &port->info->xmit; + int count = 256; + + if (port->x_char) { + wr_regb(port, S3C2410_UTXH, port->x_char); + port->icount.tx++; + port->x_char = 0; + goto out; + } + + /* if there isnt anything more to transmit, or the uart is now + * stopped, disable the uart and exit + */ + + if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { + s3c24xx_serial_stop_tx(port); + goto out; + } + + /* try and drain the buffer... */ + + while (!uart_circ_empty(xmit) && count-- > 0) { + if (rd_regl(port, S3C2410_UFSTAT) & ourport->info->tx_fifofull) + break; + + wr_regb(port, S3C2410_UTXH, xmit->buf[xmit->tail]); + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); + port->icount.tx++; + } + + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_write_wakeup(port); + + if (uart_circ_empty(xmit)) + s3c24xx_serial_stop_tx(port); + + out: + return IRQ_HANDLED; +} + +static unsigned int s3c24xx_serial_tx_empty(struct uart_port *port) +{ + struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); + unsigned long ufstat = rd_regl(port, S3C2410_UFSTAT); + unsigned long ufcon = rd_regl(port, S3C2410_UFCON); + + if (ufcon & S3C2410_UFCON_FIFOMODE) { + if ((ufstat & info->tx_fifomask) != 0 || + (ufstat & info->tx_fifofull)) + return 0; + + return 1; + } + + return s3c24xx_serial_txempty_nofifo(port); +} + +/* no modem control lines */ +static unsigned int s3c24xx_serial_get_mctrl(struct uart_port *port) +{ + unsigned int umstat = rd_regb(port, S3C2410_UMSTAT); + + if (umstat & S3C2410_UMSTAT_CTS) + return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS; + else + return TIOCM_CAR | TIOCM_DSR; +} + +static void s3c24xx_serial_set_mctrl(struct uart_port *port, unsigned int mctrl) +{ + /* todo - possibly remove AFC and do manual CTS */ +} + +static void s3c24xx_serial_break_ctl(struct uart_port *port, int break_state) +{ + unsigned long flags; + unsigned int ucon; + + spin_lock_irqsave(&port->lock, flags); + + ucon = rd_regl(port, S3C2410_UCON); + + if (break_state) + ucon |= S3C2410_UCON_SBREAK; + else + ucon &= ~S3C2410_UCON_SBREAK; + + wr_regl(port, S3C2410_UCON, ucon); + + spin_unlock_irqrestore(&port->lock, flags); +} + +static void s3c24xx_serial_shutdown(struct uart_port *port) +{ + struct s3c24xx_uart_port *ourport = to_ourport(port); + + if (ourport->tx_claimed) { + free_irq(TX_IRQ(port), ourport); + tx_enabled(port) = 0; + ourport->tx_claimed = 0; + } + + if (ourport->rx_claimed) { + free_irq(RX_IRQ(port), ourport); + ourport->rx_claimed = 0; + rx_enabled(port) = 0; + } +} + + +static int s3c24xx_serial_startup(struct uart_port *port) +{ + struct s3c24xx_uart_port *ourport = to_ourport(port); + int ret; + + dbg("s3c24xx_serial_startup: port=%p (%08lx,%p)\n", + port->mapbase, port->membase); + + rx_enabled(port) = 1; + + ret = request_irq(RX_IRQ(port), + s3c24xx_serial_rx_chars, 0, + s3c24xx_serial_portname(port), ourport); + + if (ret != 0) { + printk(KERN_ERR "cannot get irq %d\n", RX_IRQ(port)); + return ret; + } + + ourport->rx_claimed = 1; + + dbg("requesting tx irq...\n"); + + tx_enabled(port) = 1; + + ret = request_irq(TX_IRQ(port), + s3c24xx_serial_tx_chars, 0, + s3c24xx_serial_portname(port), ourport); + + if (ret) { + printk(KERN_ERR "cannot get irq %d\n", TX_IRQ(port)); + goto err; + } + + ourport->tx_claimed = 1; + + dbg("s3c24xx_serial_startup ok\n"); + + /* the port reset code should have done the correct + * register setup for the port controls */ + + return ret; + + err: + s3c24xx_serial_shutdown(port); + return ret; +} + +/* power power management control */ + +static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level, + unsigned int old) +{ + struct s3c24xx_uart_port *ourport = to_ourport(port); + + switch (level) { + case 3: + if (!IS_ERR(ourport->baudclk) && ourport->baudclk != NULL) + clk_disable(ourport->baudclk); + + clk_disable(ourport->clk); + break; + + case 0: + clk_enable(ourport->clk); + + if (!IS_ERR(ourport->baudclk) && ourport->baudclk != NULL) + clk_enable(ourport->baudclk); + + break; + default: + printk(KERN_ERR "s3c24xx_serial: unknown pm %d\n", level); + } +} + +/* baud rate calculation + * + * The UARTs on the S3C2410/S3C2440 can take their clocks from a number + * of different sources, including the peripheral clock ("pclk") and an + * external clock ("uclk"). The S3C2440 also adds the core clock ("fclk") + * with a programmable extra divisor. + * + * The following code goes through the clock sources, and calculates the + * baud clocks (and the resultant actual baud rates) and then tries to + * pick the closest one and select that. + * +*/ + + +#define MAX_CLKS (8) + +static struct s3c24xx_uart_clksrc tmp_clksrc = { + .name = "pclk", + .min_baud = 0, + .max_baud = 0, + .divisor = 1, +}; + +static inline int +s3c24xx_serial_getsource(struct uart_port *port, struct s3c24xx_uart_clksrc *c) +{ + struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); + + return (info->get_clksrc)(port, c); +} + +static inline int +s3c24xx_serial_setsource(struct uart_port *port, struct s3c24xx_uart_clksrc *c) +{ + struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); + + return (info->set_clksrc)(port, c); +} + +struct baud_calc { + struct s3c24xx_uart_clksrc *clksrc; + unsigned int calc; + unsigned int quot; + struct clk *src; +}; + +static int s3c24xx_serial_calcbaud(struct baud_calc *calc, + struct uart_port *port, + struct s3c24xx_uart_clksrc *clksrc, + unsigned int baud) +{ + unsigned long rate; + + calc->src = clk_get(port->dev, clksrc->name); + if (calc->src == NULL || IS_ERR(calc->src)) + return 0; + + rate = clk_get_rate(calc->src); + rate /= clksrc->divisor; + + calc->clksrc = clksrc; + calc->quot = (rate + (8 * baud)) / (16 * baud); + calc->calc = (rate / (calc->quot * 16)); + + calc->quot--; + return 1; +} + +static unsigned int s3c24xx_serial_getclk(struct uart_port *port, + struct s3c24xx_uart_clksrc **clksrc, + struct clk **clk, + unsigned int baud) +{ + struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port); + struct s3c24xx_uart_clksrc *clkp; + struct baud_calc res[MAX_CLKS]; + struct baud_calc *resptr, *best, *sptr; + int i; + + clkp = cfg->clocks; + best = NULL; + + if (cfg->clocks_size < 2) { + if (cfg->clocks_size == 0) + clkp = &tmp_clksrc; + + /* check to see if we're sourcing fclk, and if so we're + * going to have to update the clock source + */ + + if (strcmp(clkp->name, "fclk") == 0) { + struct s3c24xx_uart_clksrc src; + + s3c24xx_serial_getsource(port, &src); + + /* check that the port already using fclk, and if + * not, then re-select fclk + */ + + if (strcmp(src.name, clkp->name) == 0) { + s3c24xx_serial_setsource(port, clkp); + s3c24xx_serial_getsource(port, &src); + } + + clkp->divisor = src.divisor; + } + + s3c24xx_serial_calcbaud(res, port, clkp, baud); + best = res; + resptr = best + 1; + } else { + resptr = res; + + for (i = 0; i < cfg->clocks_size; i++, clkp++) { + if (s3c24xx_serial_calcbaud(resptr, port, clkp, baud)) + resptr++; + } + } + + /* ok, we now need to select the best clock we found */ + + if (!best) { + unsigned int deviation = (1<<30)|((1<<30)-1); + int calc_deviation; + + for (sptr = res; sptr < resptr; sptr++) { + calc_deviation = baud - sptr->calc; + if (calc_deviation < 0) + calc_deviation = -calc_deviation; + + if (calc_deviation < deviation) { + best = sptr; + deviation = calc_deviation; + } + } + } + + /* store results to pass back */ + + *clksrc = best->clksrc; + *clk = best->src; + + return best->quot; +} + +static void s3c24xx_serial_set_termios(struct uart_port *port, + struct ktermios *termios, + struct ktermios *old) +{ + struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port); + struct s3c24xx_uart_port *ourport = to_ourport(port); + struct s3c24xx_uart_clksrc *clksrc = NULL; + struct clk *clk = NULL; + unsigned long flags; + unsigned int baud, quot; + unsigned int ulcon; + unsigned int umcon; + + /* + * We don't support modem control lines. + */ + termios->c_cflag &= ~(HUPCL | CMSPAR); + termios->c_cflag |= CLOCAL; + + /* + * Ask the core to calculate the divisor for us. + */ + + baud = uart_get_baud_rate(port, termios, old, 0, 115200*8); + + if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST) + quot = port->custom_divisor; + else + quot = s3c24xx_serial_getclk(port, &clksrc, &clk, baud); + + /* check to see if we need to change clock source */ + + if (ourport->clksrc != clksrc || ourport->baudclk != clk) { + s3c24xx_serial_setsource(port, clksrc); + + if (ourport->baudclk != NULL && !IS_ERR(ourport->baudclk)) { + clk_disable(ourport->baudclk); + ourport->baudclk = NULL; + } + + clk_enable(clk); + + ourport->clksrc = clksrc; + ourport->baudclk = clk; + } + + switch (termios->c_cflag & CSIZE) { + case CS5: + dbg("config: 5bits/char\n"); + ulcon = S3C2410_LCON_CS5; + break; + case CS6: + dbg("config: 6bits/char\n"); + ulcon = S3C2410_LCON_CS6; + break; + case CS7: + dbg("config: 7bits/char\n"); + ulcon = S3C2410_LCON_CS7; + break; + case CS8: + default: + dbg("config: 8bits/char\n"); + ulcon = S3C2410_LCON_CS8; + break; + } + + /* preserve original lcon IR settings */ + ulcon |= (cfg->ulcon & S3C2410_LCON_IRM); + + if (termios->c_cflag & CSTOPB) + ulcon |= S3C2410_LCON_STOPB; + + umcon = (termios->c_cflag & CRTSCTS) ? S3C2410_UMCOM_AFC : 0; + + if (termios->c_cflag & PARENB) { + if (termios->c_cflag & PARODD) + ulcon |= S3C2410_LCON_PODD; + else + ulcon |= S3C2410_LCON_PEVEN; + } else { + ulcon |= S3C2410_LCON_PNONE; + } + + spin_lock_irqsave(&port->lock, flags); + + dbg("setting ulcon to %08x, brddiv to %d\n", ulcon, quot); + + wr_regl(port, S3C2410_ULCON, ulcon); + wr_regl(port, S3C2410_UBRDIV, quot); + wr_regl(port, S3C2410_UMCON, umcon); + + dbg("uart: ulcon = 0x%08x, ucon = 0x%08x, ufcon = 0x%08x\n", + rd_regl(port, S3C2410_ULCON), + rd_regl(port, S3C2410_UCON), + rd_regl(port, S3C2410_UFCON)); + + /* + * Update the per-port timeout. + */ + uart_update_timeout(port, termios->c_cflag, baud); + + /* + * Which character status flags are we interested in? + */ + port->read_status_mask = S3C2410_UERSTAT_OVERRUN; + if (termios->c_iflag & INPCK) + port->read_status_mask |= S3C2410_UERSTAT_FRAME | S3C2410_UERSTAT_PARITY; + + /* + * Which character status flags should we ignore? + */ + port->ignore_status_mask = 0; + if (termios->c_iflag & IGNPAR) + port->ignore_status_mask |= S3C2410_UERSTAT_OVERRUN; + if (termios->c_iflag & IGNBRK && termios->c_iflag & IGNPAR) + port->ignore_status_mask |= S3C2410_UERSTAT_FRAME; + + /* + * Ignore all characters if CREAD is not set. + */ + if ((termios->c_cflag & CREAD) == 0) + port->ignore_status_mask |= RXSTAT_DUMMY_READ; + + spin_unlock_irqrestore(&port->lock, flags); +} + +static const char *s3c24xx_serial_type(struct uart_port *port) +{ + switch (port->type) { + case PORT_S3C2410: + return "S3C2410"; + case PORT_S3C2440: + return "S3C2440"; + case PORT_S3C2412: + return "S3C2412"; + default: + return NULL; + } +} + +#define MAP_SIZE (0x100) + +static void s3c24xx_serial_release_port(struct uart_port *port) +{ + release_mem_region(port->mapbase, MAP_SIZE); +} + +static int s3c24xx_serial_request_port(struct uart_port *port) +{ + const char *name = s3c24xx_serial_portname(port); + return request_mem_region(port->mapbase, MAP_SIZE, name) ? 0 : -EBUSY; +} + +static void s3c24xx_serial_config_port(struct uart_port *port, int flags) +{ + struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); + + if (flags & UART_CONFIG_TYPE && + s3c24xx_serial_request_port(port) == 0) + port->type = info->type; +} + +/* + * verify the new serial_struct (for TIOCSSERIAL). + */ +static int +s3c24xx_serial_verify_port(struct uart_port *port, struct serial_struct *ser) +{ + struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); + + if (ser->type != PORT_UNKNOWN && ser->type != info->type) + return -EINVAL; + + return 0; +} + + +#ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE + +static struct console s3c24xx_serial_console; + +#define S3C24XX_SERIAL_CONSOLE &s3c24xx_serial_console +#else +#define S3C24XX_SERIAL_CONSOLE NULL +#endif + +static struct uart_ops s3c24xx_serial_ops = { + .pm = s3c24xx_serial_pm, + .tx_empty = s3c24xx_serial_tx_empty, + .get_mctrl = s3c24xx_serial_get_mctrl, + .set_mctrl = s3c24xx_serial_set_mctrl, + .stop_tx = s3c24xx_serial_stop_tx, + .start_tx = s3c24xx_serial_start_tx, + .stop_rx = s3c24xx_serial_stop_rx, + .enable_ms = s3c24xx_serial_enable_ms, + .break_ctl = s3c24xx_serial_break_ctl, + .startup = s3c24xx_serial_startup, + .shutdown = s3c24xx_serial_shutdown, + .set_termios = s3c24xx_serial_set_termios, + .type = s3c24xx_serial_type, + .release_port = s3c24xx_serial_release_port, + .request_port = s3c24xx_serial_request_port, + .config_port = s3c24xx_serial_config_port, + .verify_port = s3c24xx_serial_verify_port, +}; + + +static struct uart_driver s3c24xx_uart_drv = { + .owner = THIS_MODULE, + .dev_name = "s3c2410_serial", + .nr = 3, + .cons = S3C24XX_SERIAL_CONSOLE, + .driver_name = S3C24XX_SERIAL_NAME, + .major = S3C24XX_SERIAL_MAJOR, + .minor = S3C24XX_SERIAL_MINOR, +}; + +static struct s3c24xx_uart_port s3c24xx_serial_ports[NR_PORTS] = { + [0] = { + .port = { + .lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[0].port.lock), + .iotype = UPIO_MEM, + .irq = IRQ_S3CUART_RX0, + .uartclk = 0, + .fifosize = 16, + .ops = &s3c24xx_serial_ops, + .flags = UPF_BOOT_AUTOCONF, + .line = 0, + } + }, + [1] = { + .port = { + .lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[1].port.lock), + .iotype = UPIO_MEM, + .irq = IRQ_S3CUART_RX1, + .uartclk = 0, + .fifosize = 16, + .ops = &s3c24xx_serial_ops, + .flags = UPF_BOOT_AUTOCONF, + .line = 1, + } + }, +#if NR_PORTS > 2 + + [2] = { + .port = { + .lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[2].port.lock), + .iotype = UPIO_MEM, + .irq = IRQ_S3CUART_RX2, + .uartclk = 0, + .fifosize = 16, + .ops = &s3c24xx_serial_ops, + .flags = UPF_BOOT_AUTOCONF, + .line = 2, + } + } +#endif +}; + +/* s3c24xx_serial_resetport + * + * wrapper to call the specific reset for this port (reset the fifos + * and the settings) +*/ + +static inline int s3c24xx_serial_resetport(struct uart_port *port, + struct s3c2410_uartcfg *cfg) +{ + struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); + + return (info->reset_port)(port, cfg); +} + +/* s3c24xx_serial_init_port + * + * initialise a single serial port from the platform device given + */ + +static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport, + struct s3c24xx_uart_info *info, + struct platform_device *platdev) +{ + struct uart_port *port = &ourport->port; + struct s3c2410_uartcfg *cfg; + struct resource *res; + int ret; + + dbg("s3c24xx_serial_init_port: port=%p, platdev=%p\n", port, platdev); + + if (platdev == NULL) + return -ENODEV; + + cfg = s3c24xx_dev_to_cfg(&platdev->dev); + + if (port->mapbase != 0) + return 0; + + if (cfg->hwport > 3) + return -EINVAL; + + /* setup info for port */ + port->dev = &platdev->dev; + ourport->info = info; + + /* copy the info in from provided structure */ + ourport->port.fifosize = info->fifosize; + + dbg("s3c24xx_serial_init_port: %p (hw %d)...\n", port, cfg->hwport); + + port->uartclk = 1; + + if (cfg->uart_flags & UPF_CONS_FLOW) { + dbg("s3c24xx_serial_init_port: enabling flow control\n"); + port->flags |= UPF_CONS_FLOW; + } + + /* sort our the physical and virtual addresses for each UART */ + + res = platform_get_resource(platdev, IORESOURCE_MEM, 0); + if (res == NULL) { + printk(KERN_ERR "failed to find memory resource for uart\n"); + return -EINVAL; + } + + dbg("resource %p (%lx..%lx)\n", res, res->start, res->end); + + port->mapbase = res->start; + port->membase = S3C24XX_VA_UART + (res->start - S3C24XX_PA_UART); + ret = platform_get_irq(platdev, 0); + if (ret < 0) + port->irq = 0; + else + port->irq = ret; + + ourport->clk = clk_get(&platdev->dev, "uart"); + + dbg("port: map=%08x, mem=%08x, irq=%d, clock=%ld\n", + port->mapbase, port->membase, port->irq, port->uartclk); + + /* reset the fifos (and setup the uart) */ + s3c24xx_serial_resetport(port, cfg); + return 0; +} + +static ssize_t s3c24xx_serial_show_clksrc(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct uart_port *port = s3c24xx_dev_to_port(dev); + struct s3c24xx_uart_port *ourport = to_ourport(port); + + return snprintf(buf, PAGE_SIZE, "* %s\n", ourport->clksrc->name); +} + +static DEVICE_ATTR(clock_source, S_IRUGO, s3c24xx_serial_show_clksrc, NULL); + +/* Device driver serial port probe */ + +static int probe_index; + +int s3c24xx_serial_probe(struct platform_device *dev, + struct s3c24xx_uart_info *info) +{ + struct s3c24xx_uart_port *ourport; + int ret; + + dbg("s3c24xx_serial_probe(%p, %p) %d\n", dev, info, probe_index); + + ourport = &s3c24xx_serial_ports[probe_index]; + probe_index++; + + dbg("%s: initialising port %p...\n", __func__, ourport); + + ret = s3c24xx_serial_init_port(ourport, info, dev); + if (ret < 0) + goto probe_err; + + dbg("%s: adding port\n", __func__); + uart_add_one_port(&s3c24xx_uart_drv, &ourport->port); + platform_set_drvdata(dev, &ourport->port); + + ret = device_create_file(&dev->dev, &dev_attr_clock_source); + if (ret < 0) + printk(KERN_ERR "%s: failed to add clksrc attr.\n", __func__); + + return 0; + + probe_err: + return ret; +} + +EXPORT_SYMBOL_GPL(s3c24xx_serial_probe); + +int s3c24xx_serial_remove(struct platform_device *dev) +{ + struct uart_port *port = s3c24xx_dev_to_port(&dev->dev); + + if (port) { + device_remove_file(&dev->dev, &dev_attr_clock_source); + uart_remove_one_port(&s3c24xx_uart_drv, port); + } + + return 0; +} + +EXPORT_SYMBOL_GPL(s3c24xx_serial_remove); + +/* UART power management code */ + +#ifdef CONFIG_PM + +static int s3c24xx_serial_suspend(struct platform_device *dev, pm_message_t state) +{ + struct uart_port *port = s3c24xx_dev_to_port(&dev->dev); + + if (port) + uart_suspend_port(&s3c24xx_uart_drv, port); + + return 0; +} + +static int s3c24xx_serial_resume(struct platform_device *dev) +{ + struct uart_port *port = s3c24xx_dev_to_port(&dev->dev); + struct s3c24xx_uart_port *ourport = to_ourport(port); + + if (port) { + clk_enable(ourport->clk); + s3c24xx_serial_resetport(port, s3c24xx_port_to_cfg(port)); + clk_disable(ourport->clk); + + uart_resume_port(&s3c24xx_uart_drv, port); + } + + return 0; +} +#endif + +int s3c24xx_serial_init(struct platform_driver *drv, + struct s3c24xx_uart_info *info) +{ + dbg("s3c24xx_serial_init(%p,%p)\n", drv, info); + +#ifdef CONFIG_PM + drv->suspend = s3c24xx_serial_suspend; + drv->resume = s3c24xx_serial_resume; +#endif + + return platform_driver_register(drv); +} + +EXPORT_SYMBOL_GPL(s3c24xx_serial_init); + +/* module initialisation code */ + +static int __init s3c24xx_serial_modinit(void) +{ + int ret; + + ret = uart_register_driver(&s3c24xx_uart_drv); + if (ret < 0) { + printk(KERN_ERR "failed to register UART driver\n"); + return -1; + } + + return 0; +} + +static void __exit s3c24xx_serial_modexit(void) +{ + uart_unregister_driver(&s3c24xx_uart_drv); +} + +module_init(s3c24xx_serial_modinit); +module_exit(s3c24xx_serial_modexit); + +/* Console code */ + +#ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE + +static struct uart_port *cons_uart; + +static int +s3c24xx_serial_console_txrdy(struct uart_port *port, unsigned int ufcon) +{ + struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); + unsigned long ufstat, utrstat; + + if (ufcon & S3C2410_UFCON_FIFOMODE) { + /* fifo mode - check ammount of data in fifo registers... */ + + ufstat = rd_regl(port, S3C2410_UFSTAT); + return (ufstat & info->tx_fifofull) ? 0 : 1; + } + + /* in non-fifo mode, we go and use the tx buffer empty */ + + utrstat = rd_regl(port, S3C2410_UTRSTAT); + return (utrstat & S3C2410_UTRSTAT_TXE) ? 1 : 0; +} + +static void +s3c24xx_serial_console_putchar(struct uart_port *port, int ch) +{ + unsigned int ufcon = rd_regl(cons_uart, S3C2410_UFCON); + while (!s3c24xx_serial_console_txrdy(port, ufcon)) + barrier(); + wr_regb(cons_uart, S3C2410_UTXH, ch); +} + +static void +s3c24xx_serial_console_write(struct console *co, const char *s, + unsigned int count) +{ + uart_console_write(cons_uart, s, count, s3c24xx_serial_console_putchar); +} + +static void __init +s3c24xx_serial_get_options(struct uart_port *port, int *baud, + int *parity, int *bits) +{ + struct s3c24xx_uart_clksrc clksrc; + struct clk *clk; + unsigned int ulcon; + unsigned int ucon; + unsigned int ubrdiv; + unsigned long rate; + + ulcon = rd_regl(port, S3C2410_ULCON); + ucon = rd_regl(port, S3C2410_UCON); + ubrdiv = rd_regl(port, S3C2410_UBRDIV); + + dbg("s3c24xx_serial_get_options: port=%p\n" + "registers: ulcon=%08x, ucon=%08x, ubdriv=%08x\n", + port, ulcon, ucon, ubrdiv); + + if ((ucon & 0xf) != 0) { + /* consider the serial port configured if the tx/rx mode set */ + + switch (ulcon & S3C2410_LCON_CSMASK) { + case S3C2410_LCON_CS5: + *bits = 5; + break; + case S3C2410_LCON_CS6: + *bits = 6; + break; + case S3C2410_LCON_CS7: + *bits = 7; + break; + default: + case S3C2410_LCON_CS8: + *bits = 8; + break; + } + + switch (ulcon & S3C2410_LCON_PMASK) { + case S3C2410_LCON_PEVEN: + *parity = 'e'; + break; + + case S3C2410_LCON_PODD: + *parity = 'o'; + break; + + case S3C2410_LCON_PNONE: + default: + *parity = 'n'; + } + + /* now calculate the baud rate */ + + s3c24xx_serial_getsource(port, &clksrc); + + clk = clk_get(port->dev, clksrc.name); + if (!IS_ERR(clk) && clk != NULL) + rate = clk_get_rate(clk) / clksrc.divisor; + else + rate = 1; + + + *baud = rate / (16 * (ubrdiv + 1)); + dbg("calculated baud %d\n", *baud); + } + +} + +/* s3c24xx_serial_init_ports + * + * initialise the serial ports from the machine provided initialisation + * data. +*/ + +static int s3c24xx_serial_init_ports(struct s3c24xx_uart_info *info) +{ + struct s3c24xx_uart_port *ptr = s3c24xx_serial_ports; + struct platform_device **platdev_ptr; + int i; + + dbg("s3c24xx_serial_init_ports: initialising ports...\n"); + + platdev_ptr = s3c24xx_uart_devs; + + for (i = 0; i < NR_PORTS; i++, ptr++, platdev_ptr++) { + s3c24xx_serial_init_port(ptr, info, *platdev_ptr); + } + + return 0; +} + +static int __init +s3c24xx_serial_console_setup(struct console *co, char *options) +{ + struct uart_port *port; + int baud = 9600; + int bits = 8; + int parity = 'n'; + int flow = 'n'; + + dbg("s3c24xx_serial_console_setup: co=%p (%d), %s\n", + co, co->index, options); + + /* is this a valid port */ + + if (co->index == -1 || co->index >= NR_PORTS) + co->index = 0; + + port = &s3c24xx_serial_ports[co->index].port; + + /* is the port configured? */ + + if (port->mapbase == 0x0) { + co->index = 0; + port = &s3c24xx_serial_ports[co->index].port; + } + + cons_uart = port; + + dbg("s3c24xx_serial_console_setup: port=%p (%d)\n", port, co->index); + + /* + * Check whether an invalid uart number has been specified, and + * if so, search for the first available port that does have + * console support. + */ + if (options) + uart_parse_options(options, &baud, &parity, &bits, &flow); + else + s3c24xx_serial_get_options(port, &baud, &parity, &bits); + + dbg("s3c24xx_serial_console_setup: baud %d\n", baud); + + return uart_set_options(port, co, baud, parity, bits, flow); +} + +/* s3c24xx_serial_initconsole + * + * initialise the console from one of the uart drivers +*/ + +static struct console s3c24xx_serial_console = { + .name = S3C24XX_SERIAL_NAME, + .device = uart_console_device, + .flags = CON_PRINTBUFFER, + .index = -1, + .write = s3c24xx_serial_console_write, + .setup = s3c24xx_serial_console_setup +}; + +int s3c24xx_serial_initconsole(struct platform_driver *drv, + struct s3c24xx_uart_info *info) + +{ + struct platform_device *dev = s3c24xx_uart_devs[0]; + + dbg("s3c24xx_serial_initconsole\n"); + + /* select driver based on the cpu */ + + if (dev == NULL) { + printk(KERN_ERR "s3c24xx: no devices for console init\n"); + return 0; + } + + if (strcmp(dev->name, drv->driver.name) != 0) + return 0; + + s3c24xx_serial_console.data = &s3c24xx_uart_drv; + s3c24xx_serial_init_ports(info); + + register_console(&s3c24xx_serial_console); + return 0; +} + +#endif /* CONFIG_SERIAL_SAMSUNG_CONSOLE */ + +MODULE_DESCRIPTION("Samsung SoC Serial port driver"); +MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/serial/samsung.h b/drivers/serial/samsung.h new file mode 100644 index 00000000000..5c92ebbe7d9 --- /dev/null +++ b/drivers/serial/samsung.h @@ -0,0 +1,102 @@ +/* linux/drivers/serial/samsung.h + * + * Driver for Samsung SoC onboard UARTs. + * + * Ben Dooks, Copyright (c) 2003-2005,2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +struct s3c24xx_uart_info { + char *name; + unsigned int type; + unsigned int fifosize; + unsigned long rx_fifomask; + unsigned long rx_fifoshift; + unsigned long rx_fifofull; + unsigned long tx_fifomask; + unsigned long tx_fifoshift; + unsigned long tx_fifofull; + + /* clock source control */ + + int (*get_clksrc)(struct uart_port *, struct s3c24xx_uart_clksrc *clk); + int (*set_clksrc)(struct uart_port *, struct s3c24xx_uart_clksrc *clk); + + /* uart controls */ + int (*reset_port)(struct uart_port *, struct s3c2410_uartcfg *); +}; + +struct s3c24xx_uart_port { + unsigned char rx_claimed; + unsigned char tx_claimed; + + struct s3c24xx_uart_info *info; + struct s3c24xx_uart_clksrc *clksrc; + struct clk *clk; + struct clk *baudclk; + struct uart_port port; +}; + +/* conversion functions */ + +#define s3c24xx_dev_to_port(__dev) (struct uart_port *)dev_get_drvdata(__dev) +#define s3c24xx_dev_to_cfg(__dev) (struct s3c2410_uartcfg *)((__dev)->platform_data) + +/* register access controls */ + +#define portaddr(port, reg) ((port)->membase + (reg)) + +#define rd_regb(port, reg) (__raw_readb(portaddr(port, reg))) +#define rd_regl(port, reg) (__raw_readl(portaddr(port, reg))) + +#define wr_regb(port, reg, val) __raw_writeb(val, portaddr(port, reg)) +#define wr_regl(port, reg, val) __raw_writel(val, portaddr(port, reg)) + +extern int s3c24xx_serial_probe(struct platform_device *dev, + struct s3c24xx_uart_info *uart); + +extern int s3c24xx_serial_remove(struct platform_device *dev); + +extern int s3c24xx_serial_initconsole(struct platform_driver *drv, + struct s3c24xx_uart_info *uart); + +extern int s3c24xx_serial_init(struct platform_driver *drv, + struct s3c24xx_uart_info *info); + +#ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE + +#define s3c24xx_console_init(__drv, __inf) \ +static int __init s3c_serial_console_init(void) \ +{ \ + return s3c24xx_serial_initconsole(__drv, __inf); \ +} \ + \ +console_initcall(s3c_serial_console_init) + +#else +#define s3c24xx_console_init(drv, inf) extern void no_console(void) +#endif + +#ifdef CONFIG_SERIAL_SAMSUNG_DEBUG + +extern void printascii(const char *); + +static void dbg(const char *fmt, ...) +{ + va_list va; + char buff[256]; + + va_start(va, fmt); + vsprintf(buff, fmt, va); + va_end(va); + + printascii(buff); +} + +#else +#define dbg(x...) do { } while (0) +#endif diff --git a/drivers/spi/spi_imx.c b/drivers/spi/spi_imx.c index c730d05bfeb..54ac7bea5f8 100644 --- a/drivers/spi/spi_imx.c +++ b/drivers/spi/spi_imx.c @@ -29,6 +29,7 @@ #include <linux/spi/spi.h> #include <linux/workqueue.h> #include <linux/delay.h> +#include <linux/clk.h> #include <asm/io.h> #include <asm/irq.h> @@ -250,6 +251,8 @@ struct driver_data { int tx_dma_needs_unmap; size_t tx_map_len; u32 dummy_dma_buf ____cacheline_aligned; + + struct clk *clk; }; /* Runtime state */ @@ -855,15 +858,15 @@ static irqreturn_t spi_int(int irq, void *dev_id) return drv_data->transfer_handler(drv_data); } -static inline u32 spi_speed_hz(u32 data_rate) +static inline u32 spi_speed_hz(struct driver_data *drv_data, u32 data_rate) { - return imx_get_perclk2() / (4 << ((data_rate) >> 13)); + return clk_get_rate(drv_data->clk) / (4 << ((data_rate) >> 13)); } -static u32 spi_data_rate(u32 speed_hz) +static u32 spi_data_rate(struct driver_data *drv_data, u32 speed_hz) { u32 div; - u32 quantized_hz = imx_get_perclk2() >> 2; + u32 quantized_hz = clk_get_rate(drv_data->clk) >> 2; for (div = SPI_PERCLK2_DIV_MIN; div <= SPI_PERCLK2_DIV_MAX; @@ -947,7 +950,7 @@ static void pump_transfers(unsigned long data) tmp = transfer->speed_hz; if (tmp == 0) tmp = chip->max_speed_hz; - tmp = spi_data_rate(tmp); + tmp = spi_data_rate(drv_data, tmp); u32_EDIT(control, SPI_CONTROL_DATARATE, tmp); writel(control, regs + SPI_CONTROL); @@ -1109,7 +1112,7 @@ static int transfer(struct spi_device *spi, struct spi_message *msg) msg->actual_length = 0; /* Per transfer setup check */ - min_speed_hz = spi_speed_hz(SPI_CONTROL_DATARATE_MIN); + min_speed_hz = spi_speed_hz(drv_data, SPI_CONTROL_DATARATE_MIN); max_speed_hz = spi->max_speed_hz; list_for_each_entry(trans, &msg->transfers, transfer_list) { tmp = trans->bits_per_word; @@ -1176,6 +1179,7 @@ msg_rejected: applied and notified to the calling driver. */ static int setup(struct spi_device *spi) { + struct driver_data *drv_data = spi_master_get_devdata(spi->master); struct spi_imx_chip *chip_info; struct chip_data *chip; int first_setup = 0; @@ -1304,14 +1308,14 @@ static int setup(struct spi_device *spi) chip->n_bytes = (tmp <= 8) ? 1 : 2; /* SPI datarate */ - tmp = spi_data_rate(spi->max_speed_hz); + tmp = spi_data_rate(drv_data, spi->max_speed_hz); if (tmp == SPI_CONTROL_DATARATE_BAD) { status = -EINVAL; dev_err(&spi->dev, "setup - " "HW min speed (%d Hz) exceeds required " "max speed (%d Hz)\n", - spi_speed_hz(SPI_CONTROL_DATARATE_MIN), + spi_speed_hz(drv_data, SPI_CONTROL_DATARATE_MIN), spi->max_speed_hz); if (first_setup) goto err_first_setup; @@ -1321,7 +1325,7 @@ static int setup(struct spi_device *spi) } else { u32_EDIT(chip->control, SPI_CONTROL_DATARATE, tmp); /* Actual rounded max_speed_hz */ - tmp = spi_speed_hz(tmp); + tmp = spi_speed_hz(drv_data, tmp); spi->max_speed_hz = tmp; chip->max_speed_hz = tmp; } @@ -1352,7 +1356,7 @@ static int setup(struct spi_device *spi) chip->period & SPI_PERIOD_WAIT, spi->mode, spi->bits_per_word, - spi_speed_hz(SPI_CONTROL_DATARATE_MIN), + spi_speed_hz(drv_data, SPI_CONTROL_DATARATE_MIN), spi->max_speed_hz); return status; @@ -1465,6 +1469,14 @@ static int __init spi_imx_probe(struct platform_device *pdev) goto err_no_pdata; } + drv_data->clk = clk_get(&pdev->dev, "perclk2"); + if (IS_ERR(drv_data->clk)) { + dev_err(&pdev->dev, "probe - cannot get get\n"); + status = PTR_ERR(drv_data->clk); + goto err_no_clk; + } + clk_enable(drv_data->clk); + /* Allocate master with space for drv_data */ master = spi_alloc_master(dev, sizeof(struct driver_data)); if (!master) { @@ -1526,24 +1538,24 @@ static int __init spi_imx_probe(struct platform_device *pdev) drv_data->rx_channel = -1; if (platform_info->enable_dma) { /* Get rx DMA channel */ - status = imx_dma_request_by_prio(&drv_data->rx_channel, - "spi_imx_rx", DMA_PRIO_HIGH); - if (status < 0) { + drv_data->rx_channel = imx_dma_request_by_prio("spi_imx_rx", + DMA_PRIO_HIGH); + if (drv_data->rx_channel < 0) { dev_err(dev, "probe - problem (%d) requesting rx channel\n", - status); + drv_data->rx_channel); goto err_no_rxdma; } else imx_dma_setup_handlers(drv_data->rx_channel, NULL, dma_err_handler, drv_data); /* Get tx DMA channel */ - status = imx_dma_request_by_prio(&drv_data->tx_channel, - "spi_imx_tx", DMA_PRIO_MEDIUM); - if (status < 0) { + drv_data->tx_channel = imx_dma_request_by_prio("spi_imx_tx", + DMA_PRIO_MEDIUM); + if (drv_data->tx_channel < 0) { dev_err(dev, "probe - problem (%d) requesting tx channel\n", - status); + drv_data->tx_channel); imx_dma_free(drv_data->rx_channel); goto err_no_txdma; } else @@ -1623,6 +1635,9 @@ err_no_iores: spi_master_put(master); err_no_pdata: + clk_disable(drv_data->clk); + clk_put(drv_data->clk); +err_no_clk: err_no_mem: return status; } @@ -1662,6 +1677,9 @@ static int __exit spi_imx_remove(struct platform_device *pdev) if (irq >= 0) free_irq(irq, drv_data); + clk_disable(drv_data->clk); + clk_put(drv_data->clk); + /* Release map resources */ iounmap(drv_data->regs); release_resource(drv_data->ioarea); diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 6e784d2db42..d6bab0d5f45 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -118,10 +118,10 @@ config USB_AMD5536UDC config USB_GADGET_ATMEL_USBA boolean "Atmel USBA" select USB_GADGET_DUALSPEED - depends on AVR32 || ARCH_AT91CAP9 + depends on AVR32 || ARCH_AT91CAP9 || ARCH_AT91SAM9RL help USBA is the integrated high-speed USB Device controller on - the AT32AP700x and AT91CAP9 processors from Atmel. + the AT32AP700x, some AT91SAM9 and AT91CAP9 processors from Atmel. config USB_ATMEL_USBA tristate @@ -172,7 +172,7 @@ config USB_NET2280 default USB_GADGET select USB_GADGET_SELECTED -config USB_GADGET_PXA2XX +config USB_GADGET_PXA25X boolean "PXA 25x or IXP 4xx" depends on (ARCH_PXA && PXA25x) || ARCH_IXP4XX help @@ -184,19 +184,19 @@ config USB_GADGET_PXA2XX zero (for control transfers). Say "y" to link the driver statically, or "m" to build a - dynamically linked module called "pxa2xx_udc" and force all + dynamically linked module called "pxa25x_udc" and force all gadget drivers to also be dynamically linked. -config USB_PXA2XX +config USB_PXA25X tristate - depends on USB_GADGET_PXA2XX + depends on USB_GADGET_PXA25X default USB_GADGET select USB_GADGET_SELECTED # if there's only one gadget driver, using only two bulk endpoints, # don't waste memory for the other endpoints -config USB_PXA2XX_SMALL - depends on USB_GADGET_PXA2XX +config USB_PXA25X_SMALL + depends on USB_GADGET_PXA25X bool default n if USB_ETH_RNDIS default y if USB_ZERO diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index 12357255d74..e258afd25fa 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -8,7 +8,7 @@ endif obj-$(CONFIG_USB_DUMMY_HCD) += dummy_hcd.o obj-$(CONFIG_USB_NET2280) += net2280.o obj-$(CONFIG_USB_AMD5536UDC) += amd5536udc.o -obj-$(CONFIG_USB_PXA2XX) += pxa2xx_udc.o +obj-$(CONFIG_USB_PXA25X) += pxa25x_udc.o obj-$(CONFIG_USB_PXA27X) += pxa27x_udc.o obj-$(CONFIG_USB_GOKU) += goku_udc.o obj-$(CONFIG_USB_OMAP) += omap_udc.o diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index 274c60a970c..b6b2a0a5ba3 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -888,7 +888,7 @@ static void pullup(struct at91_udc *udc, int is_on) at91_udp_write(udc, AT91_UDP_TXVC, 0); if (cpu_is_at91rm9200()) gpio_set_value(udc->board.pullup_pin, active); - else if (cpu_is_at91sam9260() || cpu_is_at91sam9263()) { + else if (cpu_is_at91sam9260() || cpu_is_at91sam9263() || cpu_is_at91sam9g20()) { u32 txvc = at91_udp_read(udc, AT91_UDP_TXVC); txvc |= AT91_UDP_TXVC_PUON; @@ -906,7 +906,7 @@ static void pullup(struct at91_udc *udc, int is_on) at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS); if (cpu_is_at91rm9200()) gpio_set_value(udc->board.pullup_pin, !active); - else if (cpu_is_at91sam9260() || cpu_is_at91sam9263()) { + else if (cpu_is_at91sam9260() || cpu_is_at91sam9263() || cpu_is_at91sam9g20()) { u32 txvc = at91_udp_read(udc, AT91_UDP_TXVC); txvc &= ~AT91_UDP_TXVC_PUON; diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 8d61ea67a81..4ce3950b997 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -262,7 +262,7 @@ MODULE_PARM_DESC(host_addr, "Host Ethernet Address"); /* For CDC-incapable hardware, choose the simple cdc subset. * Anything that talks bulk (without notable bugs) can do this. */ -#ifdef CONFIG_USB_GADGET_PXA2XX +#ifdef CONFIG_USB_GADGET_PXA25X #define DEV_CONFIG_SUBSET #endif diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h index f7f159c1002..ca5149ea731 100644 --- a/drivers/usb/gadget/gadget_chips.h +++ b/drivers/usb/gadget/gadget_chips.h @@ -29,8 +29,8 @@ #define gadget_is_dummy(g) 0 #endif -#ifdef CONFIG_USB_GADGET_PXA2XX -#define gadget_is_pxa(g) !strcmp("pxa2xx_udc", (g)->name) +#ifdef CONFIG_USB_GADGET_PXA25X +#define gadget_is_pxa(g) !strcmp("pxa25x_udc", (g)->name) #else #define gadget_is_pxa(g) 0 #endif diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index 69b0a2754f2..f132a9219e1 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c @@ -1501,7 +1501,7 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) } break; -#ifndef CONFIG_USB_GADGET_PXA2XX +#ifndef CONFIG_USB_GADGET_PXA25X /* PXA automagically handles this request too */ case USB_REQ_GET_CONFIGURATION: if (ctrl->bRequestType != 0x80) diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index 881d74c3d96..03a7f49d207 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c @@ -135,13 +135,17 @@ static void use_ep(struct omap_ep *ep, u16 select) if (ep->bEndpointAddress & USB_DIR_IN) num |= UDC_EP_DIR; - UDC_EP_NUM_REG = num | select; + omap_writew(num | select, UDC_EP_NUM); /* when select, MUST deselect later !! */ } static inline void deselect_ep(void) { - UDC_EP_NUM_REG &= ~UDC_EP_SEL; + u16 w; + + w = omap_readw(UDC_EP_NUM); + w &= ~UDC_EP_SEL; + omap_writew(w, UDC_EP_NUM); /* 6 wait states before TX will happen */ } @@ -216,7 +220,7 @@ static int omap_ep_enable(struct usb_ep *_ep, ep->has_dma = 0; ep->lch = -1; use_ep(ep, UDC_EP_SEL); - UDC_CTRL_REG = udc->clr_halt; + omap_writew(udc->clr_halt, UDC_CTRL); ep->ackwait = 0; deselect_ep(); @@ -232,7 +236,7 @@ static int omap_ep_enable(struct usb_ep *_ep, if (desc->bmAttributes != USB_ENDPOINT_XFER_ISOC && !ep->has_dma && !(ep->bEndpointAddress & USB_DIR_IN)) { - UDC_CTRL_REG = UDC_SET_FIFO_EN; + omap_writew(UDC_SET_FIFO_EN, UDC_CTRL); ep->ackwait = 1 + ep->double_buf; } @@ -259,7 +263,7 @@ static int omap_ep_disable(struct usb_ep *_ep) nuke (ep, -ESHUTDOWN); ep->ep.maxpacket = ep->maxpacket; ep->has_dma = 0; - UDC_CTRL_REG = UDC_SET_HALT; + omap_writew(UDC_SET_HALT, UDC_CTRL); list_del_init(&ep->iso); del_timer(&ep->timer); @@ -360,13 +364,13 @@ write_packet(u8 *buf, struct omap_req *req, unsigned max) if (likely((((int)buf) & 1) == 0)) { wp = (u16 *)buf; while (max >= 2) { - UDC_DATA_REG = *wp++; + omap_writew(*wp++, UDC_DATA); max -= 2; } buf = (u8 *)wp; } while (max--) - *(volatile u8 *)&UDC_DATA_REG = *buf++; + omap_writeb(*buf++, UDC_DATA); return len; } @@ -385,13 +389,13 @@ static int write_fifo(struct omap_ep *ep, struct omap_req *req) prefetch(buf); /* PIO-IN isn't double buffered except for iso */ - ep_stat = UDC_STAT_FLG_REG; + ep_stat = omap_readw(UDC_STAT_FLG); if (ep_stat & UDC_FIFO_UNWRITABLE) return 0; count = ep->ep.maxpacket; count = write_packet(buf, req, count); - UDC_CTRL_REG = UDC_SET_FIFO_EN; + omap_writew(UDC_SET_FIFO_EN, UDC_CTRL); ep->ackwait = 1; /* last packet is often short (sometimes a zlp) */ @@ -425,13 +429,13 @@ read_packet(u8 *buf, struct omap_req *req, unsigned avail) if (likely((((int)buf) & 1) == 0)) { wp = (u16 *)buf; while (avail >= 2) { - *wp++ = UDC_DATA_REG; + *wp++ = omap_readw(UDC_DATA); avail -= 2; } buf = (u8 *)wp; } while (avail--) - *buf++ = *(volatile u8 *)&UDC_DATA_REG; + *buf++ = omap_readb(UDC_DATA); return len; } @@ -446,7 +450,7 @@ static int read_fifo(struct omap_ep *ep, struct omap_req *req) prefetchw(buf); for (;;) { - u16 ep_stat = UDC_STAT_FLG_REG; + u16 ep_stat = omap_readw(UDC_STAT_FLG); is_last = 0; if (ep_stat & FIFO_EMPTY) { @@ -460,7 +464,7 @@ static int read_fifo(struct omap_ep *ep, struct omap_req *req) if (ep_stat & UDC_FIFO_FULL) avail = ep->ep.maxpacket; else { - avail = UDC_RXFSTAT_REG; + avail = omap_readw(UDC_RXFSTAT); ep->fnf = ep->double_buf; } count = read_packet(buf, req, avail); @@ -473,7 +477,7 @@ static int read_fifo(struct omap_ep *ep, struct omap_req *req) req->req.status = -EOVERFLOW; avail -= count; while (avail--) - (void) *(volatile u8 *)&UDC_DATA_REG; + omap_readw(UDC_DATA); } } else if (req->req.length == req->req.actual) is_last = 1; @@ -491,32 +495,6 @@ static int read_fifo(struct omap_ep *ep, struct omap_req *req) /*-------------------------------------------------------------------------*/ -static inline dma_addr_t dma_csac(unsigned lch) -{ - dma_addr_t csac; - - /* omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is - * read before the DMA controller finished disabling the channel. - */ - csac = OMAP_DMA_CSAC_REG(lch); - if (csac == 0) - csac = OMAP_DMA_CSAC_REG(lch); - return csac; -} - -static inline dma_addr_t dma_cdac(unsigned lch) -{ - dma_addr_t cdac; - - /* omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is - * read before the DMA controller finished disabling the channel. - */ - cdac = OMAP_DMA_CDAC_REG(lch); - if (cdac == 0) - cdac = OMAP_DMA_CDAC_REG(lch); - return cdac; -} - static u16 dma_src_len(struct omap_ep *ep, dma_addr_t start) { dma_addr_t end; @@ -527,7 +505,7 @@ static u16 dma_src_len(struct omap_ep *ep, dma_addr_t start) if (cpu_is_omap15xx()) return 0; - end = dma_csac(ep->lch); + end = omap_get_dma_src_pos(ep->lch); if (end == ep->dma_counter) return 0; @@ -537,15 +515,11 @@ static u16 dma_src_len(struct omap_ep *ep, dma_addr_t start) return end - start; } -#define DMA_DEST_LAST(x) (cpu_is_omap15xx() \ - ? OMAP_DMA_CSAC_REG(x) /* really: CPC */ \ - : dma_cdac(x)) - static u16 dma_dest_len(struct omap_ep *ep, dma_addr_t start) { dma_addr_t end; - end = DMA_DEST_LAST(ep->lch); + end = omap_get_dma_dst_pos(ep->lch); if (end == ep->dma_counter) return 0; @@ -565,7 +539,7 @@ static u16 dma_dest_len(struct omap_ep *ep, dma_addr_t start) static void next_in_dma(struct omap_ep *ep, struct omap_req *req) { - u16 txdma_ctrl; + u16 txdma_ctrl, w; unsigned length = req->req.length - req->req.actual; const int sync_mode = cpu_is_omap15xx() ? OMAP_DMA_SYNC_FRAME @@ -596,14 +570,18 @@ static void next_in_dma(struct omap_ep *ep, struct omap_req *req) 0, 0); omap_start_dma(ep->lch); - ep->dma_counter = dma_csac(ep->lch); - UDC_DMA_IRQ_EN_REG |= UDC_TX_DONE_IE(ep->dma_channel); - UDC_TXDMA_REG(ep->dma_channel) = UDC_TXN_START | txdma_ctrl; + ep->dma_counter = omap_get_dma_src_pos(ep->lch); + w = omap_readw(UDC_DMA_IRQ_EN); + w |= UDC_TX_DONE_IE(ep->dma_channel); + omap_writew(w, UDC_DMA_IRQ_EN); + omap_writew(UDC_TXN_START | txdma_ctrl, UDC_TXDMA(ep->dma_channel)); req->dma_bytes = length; } static void finish_in_dma(struct omap_ep *ep, struct omap_req *req, int status) { + u16 w; + if (status == 0) { req->req.actual += req->dma_bytes; @@ -620,7 +598,9 @@ static void finish_in_dma(struct omap_ep *ep, struct omap_req *req, int status) /* tx completion */ omap_stop_dma(ep->lch); - UDC_DMA_IRQ_EN_REG &= ~UDC_TX_DONE_IE(ep->dma_channel); + w = omap_readw(UDC_DMA_IRQ_EN); + w &= ~UDC_TX_DONE_IE(ep->dma_channel); + omap_writew(w, UDC_DMA_IRQ_EN); done(ep, req, status); } @@ -628,6 +608,7 @@ static void next_out_dma(struct omap_ep *ep, struct omap_req *req) { unsigned packets = req->req.length - req->req.actual; int dma_trigger = 0; + u16 w; if (cpu_is_omap24xx()) dma_trigger = OMAP24XX_DMA(USB_W2FC_RX0, ep->dma_channel); @@ -654,12 +635,14 @@ static void next_out_dma(struct omap_ep *ep, struct omap_req *req) omap_set_dma_dest_params(ep->lch, OMAP_DMA_PORT_EMIFF, OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual, 0, 0); - ep->dma_counter = DMA_DEST_LAST(ep->lch); + ep->dma_counter = omap_get_dma_dst_pos(ep->lch); - UDC_RXDMA_REG(ep->dma_channel) = UDC_RXN_STOP | (packets - 1); - UDC_DMA_IRQ_EN_REG |= UDC_RX_EOT_IE(ep->dma_channel); - UDC_EP_NUM_REG = (ep->bEndpointAddress & 0xf); - UDC_CTRL_REG = UDC_SET_FIFO_EN; + omap_writew(UDC_RXN_STOP | (packets - 1), UDC_RXDMA(ep->dma_channel)); + w = omap_readw(UDC_DMA_IRQ_EN); + w |= UDC_RX_EOT_IE(ep->dma_channel); + omap_writew(w, UDC_DMA_IRQ_EN); + omap_writew(ep->bEndpointAddress & 0xf, UDC_EP_NUM); + omap_writew(UDC_SET_FIFO_EN, UDC_CTRL); omap_start_dma(ep->lch); } @@ -667,7 +650,7 @@ static void next_out_dma(struct omap_ep *ep, struct omap_req *req) static void finish_out_dma(struct omap_ep *ep, struct omap_req *req, int status, int one) { - u16 count; + u16 count, w; if (status == 0) ep->dma_counter = (u16) (req->req.dma + req->req.actual); @@ -686,13 +669,15 @@ finish_out_dma(struct omap_ep *ep, struct omap_req *req, int status, int one) return; /* rx completion */ - UDC_DMA_IRQ_EN_REG &= ~UDC_RX_EOT_IE(ep->dma_channel); + w = omap_readw(UDC_DMA_IRQ_EN); + w &= ~UDC_RX_EOT_IE(ep->dma_channel); + omap_writew(w, UDC_DMA_IRQ_EN); done(ep, req, status); } static void dma_irq(struct omap_udc *udc, u16 irq_src) { - u16 dman_stat = UDC_DMAN_STAT_REG; + u16 dman_stat = omap_readw(UDC_DMAN_STAT); struct omap_ep *ep; struct omap_req *req; @@ -706,7 +691,7 @@ static void dma_irq(struct omap_udc *udc, u16 irq_src) struct omap_req, queue); finish_in_dma(ep, req, 0); } - UDC_IRQ_SRC_REG = UDC_TXN_DONE; + omap_writew(UDC_TXN_DONE, UDC_IRQ_SRC); if (!list_empty (&ep->queue)) { req = container_of(ep->queue.next, @@ -725,7 +710,7 @@ static void dma_irq(struct omap_udc *udc, u16 irq_src) struct omap_req, queue); finish_out_dma(ep, req, 0, dman_stat & UDC_DMA_RX_SB); } - UDC_IRQ_SRC_REG = UDC_RXN_EOT; + omap_writew(UDC_RXN_EOT, UDC_IRQ_SRC); if (!list_empty (&ep->queue)) { req = container_of(ep->queue.next, @@ -739,7 +724,7 @@ static void dma_irq(struct omap_udc *udc, u16 irq_src) ep->irqs++; /* omap15xx does this unasked... */ VDBG("%s, RX_CNT irq?\n", ep->ep.name); - UDC_IRQ_SRC_REG = UDC_RXN_CNT; + omap_writew(UDC_RXN_CNT, UDC_IRQ_SRC); } } @@ -762,9 +747,9 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel) is_in = ep->bEndpointAddress & USB_DIR_IN; if (is_in) - reg = UDC_TXDMA_CFG_REG; + reg = omap_readw(UDC_TXDMA_CFG); else - reg = UDC_RXDMA_CFG_REG; + reg = omap_readw(UDC_RXDMA_CFG); reg |= UDC_DMA_REQ; /* "pulse" activated */ ep->dma_channel = 0; @@ -792,7 +777,7 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel) status = omap_request_dma(dma_channel, ep->ep.name, dma_error, ep, &ep->lch); if (status == 0) { - UDC_TXDMA_CFG_REG = reg; + omap_writew(reg, UDC_TXDMA_CFG); /* EMIFF or SDRC */ omap_set_dma_src_burst_mode(ep->lch, OMAP_DMA_DATA_BURST_4); @@ -801,7 +786,7 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel) omap_set_dma_dest_params(ep->lch, OMAP_DMA_PORT_TIPB, OMAP_DMA_AMODE_CONSTANT, - (unsigned long) io_v2p((u32)&UDC_DATA_DMA_REG), + (unsigned long) io_v2p(UDC_DATA_DMA), 0, 0); } } else { @@ -813,12 +798,12 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel) status = omap_request_dma(dma_channel, ep->ep.name, dma_error, ep, &ep->lch); if (status == 0) { - UDC_RXDMA_CFG_REG = reg; + omap_writew(reg, UDC_RXDMA_CFG); /* TIPB */ omap_set_dma_src_params(ep->lch, OMAP_DMA_PORT_TIPB, OMAP_DMA_AMODE_CONSTANT, - (unsigned long) io_v2p((u32)&UDC_DATA_DMA_REG), + (unsigned long) io_v2p(UDC_DATA_DMA), 0, 0); /* EMIFF or SDRC */ omap_set_dma_dest_burst_mode(ep->lch, @@ -834,7 +819,7 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel) /* channel type P: hw synch (fifo) */ if (cpu_class_is_omap1() && !cpu_is_omap15xx()) - OMAP1_DMA_LCH_CTRL_REG(ep->lch) = 2; + omap_set_dma_channel_mode(ep->lch, OMAP_DMA_LCH_P); } just_restart: @@ -860,7 +845,7 @@ just_restart: (is_in ? write_fifo : read_fifo)(ep, req); deselect_ep(); if (!is_in) { - UDC_CTRL_REG = UDC_SET_FIFO_EN; + omap_writew(UDC_SET_FIFO_EN, UDC_CTRL); ep->ackwait = 1 + ep->double_buf; } /* IN: 6 wait states before it'll tx */ @@ -881,7 +866,7 @@ static void dma_channel_release(struct omap_ep *ep) else req = NULL; - active = ((1 << 7) & OMAP_DMA_CCR_REG(ep->lch)) != 0; + active = omap_get_dma_active_status(ep->lch); DBG("%s release %s %cxdma%d %p\n", ep->ep.name, active ? "active" : "idle", @@ -894,23 +879,25 @@ static void dma_channel_release(struct omap_ep *ep) /* wait till current packet DMA finishes, and fifo empties */ if (ep->bEndpointAddress & USB_DIR_IN) { - UDC_TXDMA_CFG_REG = (UDC_TXDMA_CFG_REG & ~mask) | UDC_DMA_REQ; + omap_writew((omap_readw(UDC_TXDMA_CFG) & ~mask) | UDC_DMA_REQ, + UDC_TXDMA_CFG); if (req) { finish_in_dma(ep, req, -ECONNRESET); /* clear FIFO; hosts probably won't empty it */ use_ep(ep, UDC_EP_SEL); - UDC_CTRL_REG = UDC_CLR_EP; + omap_writew(UDC_CLR_EP, UDC_CTRL); deselect_ep(); } - while (UDC_TXDMA_CFG_REG & mask) + while (omap_readw(UDC_TXDMA_CFG) & mask) udelay(10); } else { - UDC_RXDMA_CFG_REG = (UDC_RXDMA_CFG_REG & ~mask) | UDC_DMA_REQ; + omap_writew((omap_readw(UDC_RXDMA_CFG) & ~mask) | UDC_DMA_REQ, + UDC_RXDMA_CFG); /* dma empties the fifo */ - while (UDC_RXDMA_CFG_REG & mask) + while (omap_readw(UDC_RXDMA_CFG) & mask) udelay(10); if (req) finish_out_dma(ep, req, -ECONNRESET, 0); @@ -997,9 +984,13 @@ omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) req->req.actual = 0; /* maybe kickstart non-iso i/o queues */ - if (is_iso) - UDC_IRQ_EN_REG |= UDC_SOF_IE; - else if (list_empty(&ep->queue) && !ep->stopped && !ep->ackwait) { + if (is_iso) { + u16 w; + + w = omap_readw(UDC_IRQ_EN); + w |= UDC_SOF_IE; + omap_writew(w, UDC_IRQ_EN); + } else if (list_empty(&ep->queue) && !ep->stopped && !ep->ackwait) { int is_in; if (ep->bEndpointAddress == 0) { @@ -1017,23 +1008,23 @@ omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) * requests to non-control endpoints */ if (udc->ep0_set_config) { - u16 irq_en = UDC_IRQ_EN_REG; + u16 irq_en = omap_readw(UDC_IRQ_EN); irq_en |= UDC_DS_CHG_IE | UDC_EP0_IE; if (!udc->ep0_reset_config) irq_en |= UDC_EPN_RX_IE | UDC_EPN_TX_IE; - UDC_IRQ_EN_REG = irq_en; + omap_writew(irq_en, UDC_IRQ_EN); } /* STATUS for zero length DATA stages is * always an IN ... even for IN transfers, * a weird case which seem to stall OMAP. */ - UDC_EP_NUM_REG = (UDC_EP_SEL|UDC_EP_DIR); - UDC_CTRL_REG = UDC_CLR_EP; - UDC_CTRL_REG = UDC_SET_FIFO_EN; - UDC_EP_NUM_REG = UDC_EP_DIR; + omap_writew(UDC_EP_SEL | UDC_EP_DIR, UDC_EP_NUM); + omap_writew(UDC_CLR_EP, UDC_CTRL); + omap_writew(UDC_SET_FIFO_EN, UDC_CTRL); + omap_writew(UDC_EP_DIR, UDC_EP_NUM); /* cleanup */ udc->ep0_pending = 0; @@ -1042,11 +1033,11 @@ omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) /* non-empty DATA stage */ } else if (is_in) { - UDC_EP_NUM_REG = UDC_EP_SEL|UDC_EP_DIR; + omap_writew(UDC_EP_SEL | UDC_EP_DIR, UDC_EP_NUM); } else { if (udc->ep0_setup) goto irq_wait; - UDC_EP_NUM_REG = UDC_EP_SEL; + omap_writew(UDC_EP_SEL, UDC_EP_NUM); } } else { is_in = ep->bEndpointAddress & USB_DIR_IN; @@ -1062,7 +1053,7 @@ omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) req = NULL; deselect_ep(); if (!is_in) { - UDC_CTRL_REG = UDC_SET_FIFO_EN; + omap_writew(UDC_SET_FIFO_EN, UDC_CTRL); ep->ackwait = 1 + ep->double_buf; } /* IN: 6 wait states before it'll tx */ @@ -1130,9 +1121,9 @@ static int omap_ep_set_halt(struct usb_ep *_ep, int value) else if (value) { if (ep->udc->ep0_set_config) { WARN("error changing config?\n"); - UDC_SYSCON2_REG = UDC_CLR_CFG; + omap_writew(UDC_CLR_CFG, UDC_SYSCON2); } - UDC_SYSCON2_REG = UDC_STALL_CMD; + omap_writew(UDC_STALL_CMD, UDC_SYSCON2); ep->udc->ep0_pending = 0; status = 0; } else /* NOP */ @@ -1159,8 +1150,8 @@ static int omap_ep_set_halt(struct usb_ep *_ep, int value) channel = 0; use_ep(ep, UDC_EP_SEL); - if (UDC_STAT_FLG_REG & UDC_NON_ISO_FIFO_EMPTY) { - UDC_CTRL_REG = UDC_SET_HALT; + if (omap_readw(UDC_STAT_FLG) & UDC_NON_ISO_FIFO_EMPTY) { + omap_writew(UDC_SET_HALT, UDC_CTRL); status = 0; } else status = -EAGAIN; @@ -1170,10 +1161,10 @@ static int omap_ep_set_halt(struct usb_ep *_ep, int value) dma_channel_claim(ep, channel); } else { use_ep(ep, 0); - UDC_CTRL_REG = ep->udc->clr_halt; + omap_writew(ep->udc->clr_halt, UDC_CTRL); ep->ackwait = 0; if (!(ep->bEndpointAddress & USB_DIR_IN)) { - UDC_CTRL_REG = UDC_SET_FIFO_EN; + omap_writew(UDC_SET_FIFO_EN, UDC_CTRL); ep->ackwait = 1 + ep->double_buf; } } @@ -1205,7 +1196,7 @@ static struct usb_ep_ops omap_ep_ops = { static int omap_get_frame(struct usb_gadget *gadget) { - u16 sof = UDC_SOF_REG; + u16 sof = omap_readw(UDC_SOF); return (sof & UDC_TS_OK) ? (sof & UDC_TS) : -EL2NSYNC; } @@ -1224,7 +1215,7 @@ static int omap_wakeup(struct usb_gadget *gadget) */ if (udc->devstat & (UDC_B_HNP_ENABLE|UDC_R_WK_OK)) { DBG("remote wakeup...\n"); - UDC_SYSCON2_REG = UDC_RMT_WKP; + omap_writew(UDC_RMT_WKP, UDC_SYSCON2); retval = 0; } @@ -1247,12 +1238,12 @@ omap_set_selfpowered(struct usb_gadget *gadget, int is_selfpowered) udc = container_of(gadget, struct omap_udc, gadget); spin_lock_irqsave(&udc->lock, flags); - syscon1 = UDC_SYSCON1_REG; + syscon1 = omap_readw(UDC_SYSCON1); if (is_selfpowered) syscon1 |= UDC_SELF_PWR; else syscon1 &= ~UDC_SELF_PWR; - UDC_SYSCON1_REG = syscon1; + omap_writew(syscon1, UDC_SYSCON1); spin_unlock_irqrestore(&udc->lock, flags); return 0; @@ -1265,18 +1256,36 @@ static int can_pullup(struct omap_udc *udc) static void pullup_enable(struct omap_udc *udc) { - UDC_SYSCON1_REG |= UDC_PULLUP_EN; - if (!gadget_is_otg(&udc->gadget) && !cpu_is_omap15xx()) - OTG_CTRL_REG |= OTG_BSESSVLD; - UDC_IRQ_EN_REG = UDC_DS_CHG_IE; + u16 w; + + w = omap_readw(UDC_SYSCON1); + w |= UDC_PULLUP_EN; + omap_writew(w, UDC_SYSCON1); + if (!gadget_is_otg(&udc->gadget) && !cpu_is_omap15xx()) { + u32 l; + + l = omap_readl(OTG_CTRL); + l |= OTG_BSESSVLD; + omap_writel(l, OTG_CTRL); + } + omap_writew(UDC_DS_CHG_IE, UDC_IRQ_EN); } static void pullup_disable(struct omap_udc *udc) { - if (!gadget_is_otg(&udc->gadget) && !cpu_is_omap15xx()) - OTG_CTRL_REG &= ~OTG_BSESSVLD; - UDC_IRQ_EN_REG = UDC_DS_CHG_IE; - UDC_SYSCON1_REG &= ~UDC_PULLUP_EN; + u16 w; + + if (!gadget_is_otg(&udc->gadget) && !cpu_is_omap15xx()) { + u32 l; + + l = omap_readl(OTG_CTRL); + l &= ~OTG_BSESSVLD; + omap_writel(l, OTG_CTRL); + } + omap_writew(UDC_DS_CHG_IE, UDC_IRQ_EN); + w = omap_readw(UDC_SYSCON1); + w &= ~UDC_PULLUP_EN; + omap_writew(w, UDC_SYSCON1); } static struct omap_udc *udc; @@ -1304,6 +1313,7 @@ static int omap_vbus_session(struct usb_gadget *gadget, int is_active) { struct omap_udc *udc; unsigned long flags; + u32 l; udc = container_of(gadget, struct omap_udc, gadget); spin_lock_irqsave(&udc->lock, flags); @@ -1311,10 +1321,12 @@ static int omap_vbus_session(struct usb_gadget *gadget, int is_active) udc->vbus_active = (is_active != 0); if (cpu_is_omap15xx()) { /* "software" detect, ignored if !VBUS_MODE_1510 */ + l = omap_readl(FUNC_MUX_CTRL_0); if (is_active) - FUNC_MUX_CTRL_0_REG |= VBUS_CTRL_1510; + l |= VBUS_CTRL_1510; else - FUNC_MUX_CTRL_0_REG &= ~VBUS_CTRL_1510; + l &= ~VBUS_CTRL_1510; + omap_writel(l, FUNC_MUX_CTRL_0); } if (udc->dc_clk != NULL && is_active) { if (!udc->clk_requested) { @@ -1384,9 +1396,9 @@ static void nuke(struct omap_ep *ep, int status) dma_channel_release(ep); use_ep(ep, 0); - UDC_CTRL_REG = UDC_CLR_EP; + omap_writew(UDC_CLR_EP, UDC_CTRL); if (ep->bEndpointAddress && ep->bmAttributes != USB_ENDPOINT_XFER_ISOC) - UDC_CTRL_REG = UDC_SET_HALT; + omap_writew(UDC_SET_HALT, UDC_CTRL); while (!list_empty(&ep->queue)) { req = list_entry(ep->queue.next, struct omap_req, queue); @@ -1414,8 +1426,8 @@ static void update_otg(struct omap_udc *udc) if (!gadget_is_otg(&udc->gadget)) return; - if (OTG_CTRL_REG & OTG_ID) - devstat = UDC_DEVSTAT_REG; + if (omap_readl(OTG_CTRL) & OTG_ID) + devstat = omap_readw(UDC_DEVSTAT); else devstat = 0; @@ -1426,9 +1438,14 @@ static void update_otg(struct omap_udc *udc) /* Enable HNP early, avoiding races on suspend irq path. * ASSUMES OTG state machine B_BUS_REQ input is true. */ - if (udc->gadget.b_hnp_enable) - OTG_CTRL_REG = (OTG_CTRL_REG | OTG_B_HNPEN | OTG_B_BUSREQ) - & ~OTG_PULLUP; + if (udc->gadget.b_hnp_enable) { + u32 l; + + l = omap_readl(OTG_CTRL); + l |= OTG_B_HNPEN | OTG_B_BUSREQ; + l &= ~OTG_PULLUP; + omap_writel(l, OTG_CTRL); + } } static void ep0_irq(struct omap_udc *udc, u16 irq_src) @@ -1446,7 +1463,7 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src) nuke(ep0, 0); if (ack) { - UDC_IRQ_SRC_REG = ack; + omap_writew(ack, UDC_IRQ_SRC); irq_src = UDC_SETUP; } } @@ -1466,9 +1483,9 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src) if (irq_src & UDC_EP0_TX) { int stat; - UDC_IRQ_SRC_REG = UDC_EP0_TX; - UDC_EP_NUM_REG = UDC_EP_SEL|UDC_EP_DIR; - stat = UDC_STAT_FLG_REG; + omap_writew(UDC_EP0_TX, UDC_IRQ_SRC); + omap_writew(UDC_EP_SEL|UDC_EP_DIR, UDC_EP_NUM); + stat = omap_readw(UDC_STAT_FLG); if (stat & UDC_ACK) { if (udc->ep0_in) { /* write next IN packet from response, @@ -1476,26 +1493,26 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src) */ if (req) stat = write_fifo(ep0, req); - UDC_EP_NUM_REG = UDC_EP_DIR; + omap_writew(UDC_EP_DIR, UDC_EP_NUM); if (!req && udc->ep0_pending) { - UDC_EP_NUM_REG = UDC_EP_SEL; - UDC_CTRL_REG = UDC_CLR_EP; - UDC_CTRL_REG = UDC_SET_FIFO_EN; - UDC_EP_NUM_REG = 0; + omap_writew(UDC_EP_SEL, UDC_EP_NUM); + omap_writew(UDC_CLR_EP, UDC_CTRL); + omap_writew(UDC_SET_FIFO_EN, UDC_CTRL); + omap_writew(0, UDC_EP_NUM); udc->ep0_pending = 0; } /* else: 6 wait states before it'll tx */ } else { /* ack status stage of OUT transfer */ - UDC_EP_NUM_REG = UDC_EP_DIR; + omap_writew(UDC_EP_DIR, UDC_EP_NUM); if (req) done(ep0, req, 0); } req = NULL; } else if (stat & UDC_STALL) { - UDC_CTRL_REG = UDC_CLR_HALT; - UDC_EP_NUM_REG = UDC_EP_DIR; + omap_writew(UDC_CLR_HALT, UDC_CTRL); + omap_writew(UDC_EP_DIR, UDC_EP_NUM); } else { - UDC_EP_NUM_REG = UDC_EP_DIR; + omap_writew(UDC_EP_DIR, UDC_EP_NUM); } } @@ -1503,9 +1520,9 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src) if (irq_src & UDC_EP0_RX) { int stat; - UDC_IRQ_SRC_REG = UDC_EP0_RX; - UDC_EP_NUM_REG = UDC_EP_SEL; - stat = UDC_STAT_FLG_REG; + omap_writew(UDC_EP0_RX, UDC_IRQ_SRC); + omap_writew(UDC_EP_SEL, UDC_EP_NUM); + stat = omap_readw(UDC_STAT_FLG); if (stat & UDC_ACK) { if (!udc->ep0_in) { stat = 0; @@ -1513,34 +1530,35 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src) * reactiviting the fifo; stall on errors. */ if (!req || (stat = read_fifo(ep0, req)) < 0) { - UDC_SYSCON2_REG = UDC_STALL_CMD; + omap_writew(UDC_STALL_CMD, UDC_SYSCON2); udc->ep0_pending = 0; stat = 0; } else if (stat == 0) - UDC_CTRL_REG = UDC_SET_FIFO_EN; - UDC_EP_NUM_REG = 0; + omap_writew(UDC_SET_FIFO_EN, UDC_CTRL); + omap_writew(0, UDC_EP_NUM); /* activate status stage */ if (stat == 1) { done(ep0, req, 0); /* that may have STALLed ep0... */ - UDC_EP_NUM_REG = UDC_EP_SEL|UDC_EP_DIR; - UDC_CTRL_REG = UDC_CLR_EP; - UDC_CTRL_REG = UDC_SET_FIFO_EN; - UDC_EP_NUM_REG = UDC_EP_DIR; + omap_writew(UDC_EP_SEL | UDC_EP_DIR, + UDC_EP_NUM); + omap_writew(UDC_CLR_EP, UDC_CTRL); + omap_writew(UDC_SET_FIFO_EN, UDC_CTRL); + omap_writew(UDC_EP_DIR, UDC_EP_NUM); udc->ep0_pending = 0; } } else { /* ack status stage of IN transfer */ - UDC_EP_NUM_REG = 0; + omap_writew(0, UDC_EP_NUM); if (req) done(ep0, req, 0); } } else if (stat & UDC_STALL) { - UDC_CTRL_REG = UDC_CLR_HALT; - UDC_EP_NUM_REG = 0; + omap_writew(UDC_CLR_HALT, UDC_CTRL); + omap_writew(0, UDC_EP_NUM); } else { - UDC_EP_NUM_REG = 0; + omap_writew(0, UDC_EP_NUM); } } @@ -1555,14 +1573,14 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src) /* read the (latest) SETUP message */ do { - UDC_EP_NUM_REG = UDC_SETUP_SEL; + omap_writew(UDC_SETUP_SEL, UDC_EP_NUM); /* two bytes at a time */ - u.word[0] = UDC_DATA_REG; - u.word[1] = UDC_DATA_REG; - u.word[2] = UDC_DATA_REG; - u.word[3] = UDC_DATA_REG; - UDC_EP_NUM_REG = 0; - } while (UDC_IRQ_SRC_REG & UDC_SETUP); + u.word[0] = omap_readw(UDC_DATA); + u.word[1] = omap_readw(UDC_DATA); + u.word[2] = omap_readw(UDC_DATA); + u.word[3] = omap_readw(UDC_DATA); + omap_writew(0, UDC_EP_NUM); + } while (omap_readw(UDC_IRQ_SRC) & UDC_SETUP); #define w_value le16_to_cpu(u.r.wValue) #define w_index le16_to_cpu(u.r.wIndex) @@ -1593,9 +1611,9 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src) * later if it fails the request. */ if (udc->ep0_reset_config) - UDC_SYSCON2_REG = UDC_CLR_CFG; + omap_writew(UDC_CLR_CFG, UDC_SYSCON2); else - UDC_SYSCON2_REG = UDC_DEV_CFG; + omap_writew(UDC_DEV_CFG, UDC_SYSCON2); update_otg(udc); goto delegate; case USB_REQ_CLEAR_FEATURE: @@ -1613,10 +1631,10 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src) || !ep->desc) goto do_stall; use_ep(ep, 0); - UDC_CTRL_REG = udc->clr_halt; + omap_writew(udc->clr_halt, UDC_CTRL); ep->ackwait = 0; if (!(ep->bEndpointAddress & USB_DIR_IN)) { - UDC_CTRL_REG = UDC_SET_FIFO_EN; + omap_writew(UDC_SET_FIFO_EN, UDC_CTRL); ep->ackwait = 1 + ep->double_buf; } /* NOTE: assumes the host behaves sanely, @@ -1649,15 +1667,15 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src) } use_ep(ep, 0); /* can't halt if fifo isn't empty... */ - UDC_CTRL_REG = UDC_CLR_EP; - UDC_CTRL_REG = UDC_SET_HALT; + omap_writew(UDC_CLR_EP, UDC_CTRL); + omap_writew(UDC_SET_HALT, UDC_CTRL); VDBG("%s halted by host\n", ep->name); ep0out_status_stage: status = 0; - UDC_EP_NUM_REG = UDC_EP_SEL|UDC_EP_DIR; - UDC_CTRL_REG = UDC_CLR_EP; - UDC_CTRL_REG = UDC_SET_FIFO_EN; - UDC_EP_NUM_REG = UDC_EP_DIR; + omap_writew(UDC_EP_SEL|UDC_EP_DIR, UDC_EP_NUM); + omap_writew(UDC_CLR_EP, UDC_CTRL); + omap_writew(UDC_SET_FIFO_EN, UDC_CTRL); + omap_writew(UDC_EP_DIR, UDC_EP_NUM); udc->ep0_pending = 0; break; case USB_REQ_GET_STATUS: @@ -1694,10 +1712,10 @@ intf_status: zero_status: /* return two zero bytes */ - UDC_EP_NUM_REG = UDC_EP_SEL|UDC_EP_DIR; - UDC_DATA_REG = 0; - UDC_CTRL_REG = UDC_SET_FIFO_EN; - UDC_EP_NUM_REG = UDC_EP_DIR; + omap_writew(UDC_EP_SEL|UDC_EP_DIR, UDC_EP_NUM); + omap_writew(0, UDC_DATA); + omap_writew(UDC_SET_FIFO_EN, UDC_CTRL); + omap_writew(UDC_EP_DIR, UDC_EP_NUM); status = 0; VDBG("GET_STATUS, interface %d\n", w_index); /* next, status stage */ @@ -1706,8 +1724,8 @@ zero_status: delegate: /* activate the ep0out fifo right away */ if (!udc->ep0_in && w_length) { - UDC_EP_NUM_REG = 0; - UDC_CTRL_REG = UDC_SET_FIFO_EN; + omap_writew(0, UDC_EP_NUM); + omap_writew(UDC_SET_FIFO_EN, UDC_CTRL); } /* gadget drivers see class/vendor specific requests, @@ -1748,9 +1766,9 @@ do_stall: if (udc->ep0_reset_config) WARN("error resetting config?\n"); else - UDC_SYSCON2_REG = UDC_CLR_CFG; + omap_writew(UDC_CLR_CFG, UDC_SYSCON2); } - UDC_SYSCON2_REG = UDC_STALL_CMD; + omap_writew(UDC_STALL_CMD, UDC_SYSCON2); udc->ep0_pending = 0; } } @@ -1764,7 +1782,7 @@ static void devstate_irq(struct omap_udc *udc, u16 irq_src) { u16 devstat, change; - devstat = UDC_DEVSTAT_REG; + devstat = omap_readw(UDC_DEVSTAT); change = devstat ^ udc->devstat; udc->devstat = devstat; @@ -1804,7 +1822,8 @@ static void devstate_irq(struct omap_udc *udc, u16 irq_src) INFO("USB reset done, gadget %s\n", udc->driver->driver.name); /* ep0 traffic is legal from now on */ - UDC_IRQ_EN_REG = UDC_DS_CHG_IE | UDC_EP0_IE; + omap_writew(UDC_DS_CHG_IE | UDC_EP0_IE, + UDC_IRQ_EN); } change &= ~UDC_USB_RESET; } @@ -1848,7 +1867,7 @@ static void devstate_irq(struct omap_udc *udc, u16 irq_src) VDBG("devstat %03x, ignore change %03x\n", devstat, change); - UDC_IRQ_SRC_REG = UDC_DS_CHG; + omap_writew(UDC_DS_CHG, UDC_IRQ_SRC); } static irqreturn_t omap_udc_irq(int irq, void *_udc) @@ -1859,7 +1878,7 @@ static irqreturn_t omap_udc_irq(int irq, void *_udc) unsigned long flags; spin_lock_irqsave(&udc->lock, flags); - irq_src = UDC_IRQ_SRC_REG; + irq_src = omap_readw(UDC_IRQ_SRC); /* Device state change (usb ch9 stuff) */ if (irq_src & UDC_DS_CHG) { @@ -1882,7 +1901,7 @@ static irqreturn_t omap_udc_irq(int irq, void *_udc) irq_src &= ~(UDC_TXN_DONE|UDC_RXN_CNT|UDC_RXN_EOT); } - irq_src &= ~(UDC_SOF|UDC_EPN_TX|UDC_EPN_RX); + irq_src &= ~(UDC_IRQ_SOF | UDC_EPN_TX|UDC_EPN_RX); if (irq_src) DBG("udc_irq, unhandled %03x\n", irq_src); spin_unlock_irqrestore(&udc->lock, flags); @@ -1903,7 +1922,7 @@ static void pio_out_timer(unsigned long _ep) spin_lock_irqsave(&ep->udc->lock, flags); if (!list_empty(&ep->queue) && ep->ackwait) { use_ep(ep, UDC_EP_SEL); - stat_flg = UDC_STAT_FLG_REG; + stat_flg = omap_readw(UDC_STAT_FLG); if ((stat_flg & UDC_ACK) && (!(stat_flg & UDC_FIFO_EN) || (ep->double_buf && HALF_FULL(stat_flg)))) { @@ -1913,8 +1932,8 @@ static void pio_out_timer(unsigned long _ep) req = container_of(ep->queue.next, struct omap_req, queue); (void) read_fifo(ep, req); - UDC_EP_NUM_REG = ep->bEndpointAddress; - UDC_CTRL_REG = UDC_SET_FIFO_EN; + omap_writew(ep->bEndpointAddress, UDC_EP_NUM); + omap_writew(UDC_SET_FIFO_EN, UDC_CTRL); ep->ackwait = 1 + ep->double_buf; } else deselect_ep(); @@ -1934,20 +1953,20 @@ static irqreturn_t omap_udc_pio_irq(int irq, void *_dev) unsigned long flags; spin_lock_irqsave(&udc->lock, flags); - epn_stat = UDC_EPN_STAT_REG; - irq_src = UDC_IRQ_SRC_REG; + epn_stat = omap_readw(UDC_EPN_STAT); + irq_src = omap_readw(UDC_IRQ_SRC); /* handle OUT first, to avoid some wasteful NAKs */ if (irq_src & UDC_EPN_RX) { epnum = (epn_stat >> 8) & 0x0f; - UDC_IRQ_SRC_REG = UDC_EPN_RX; + omap_writew(UDC_EPN_RX, UDC_IRQ_SRC); status = IRQ_HANDLED; ep = &udc->ep[epnum]; ep->irqs++; - UDC_EP_NUM_REG = epnum | UDC_EP_SEL; + omap_writew(epnum | UDC_EP_SEL, UDC_EP_NUM); ep->fnf = 0; - if ((UDC_STAT_FLG_REG & UDC_ACK)) { + if (omap_readw(UDC_STAT_FLG) & UDC_ACK) { ep->ackwait--; if (!list_empty(&ep->queue)) { int stat; @@ -1959,15 +1978,15 @@ static irqreturn_t omap_udc_pio_irq(int irq, void *_dev) } } /* min 6 clock delay before clearing EP_SEL ... */ - epn_stat = UDC_EPN_STAT_REG; - epn_stat = UDC_EPN_STAT_REG; - UDC_EP_NUM_REG = epnum; + epn_stat = omap_readw(UDC_EPN_STAT); + epn_stat = omap_readw(UDC_EPN_STAT); + omap_writew(epnum, UDC_EP_NUM); /* enabling fifo _after_ clearing ACK, contrary to docs, * reduces lossage; timer still needed though (sigh). */ if (ep->fnf) { - UDC_CTRL_REG = UDC_SET_FIFO_EN; + omap_writew(UDC_SET_FIFO_EN, UDC_CTRL); ep->ackwait = 1 + ep->double_buf; } mod_timer(&ep->timer, PIO_OUT_TIMEOUT); @@ -1976,13 +1995,13 @@ static irqreturn_t omap_udc_pio_irq(int irq, void *_dev) /* then IN transfers */ else if (irq_src & UDC_EPN_TX) { epnum = epn_stat & 0x0f; - UDC_IRQ_SRC_REG = UDC_EPN_TX; + omap_writew(UDC_EPN_TX, UDC_IRQ_SRC); status = IRQ_HANDLED; ep = &udc->ep[16 + epnum]; ep->irqs++; - UDC_EP_NUM_REG = epnum | UDC_EP_DIR | UDC_EP_SEL; - if ((UDC_STAT_FLG_REG & UDC_ACK)) { + omap_writew(epnum | UDC_EP_DIR | UDC_EP_SEL, UDC_EP_NUM); + if (omap_readw(UDC_STAT_FLG) & UDC_ACK) { ep->ackwait = 0; if (!list_empty(&ep->queue)) { req = container_of(ep->queue.next, @@ -1991,9 +2010,9 @@ static irqreturn_t omap_udc_pio_irq(int irq, void *_dev) } } /* min 6 clock delay before clearing EP_SEL ... */ - epn_stat = UDC_EPN_STAT_REG; - epn_stat = UDC_EPN_STAT_REG; - UDC_EP_NUM_REG = epnum | UDC_EP_DIR; + epn_stat = omap_readw(UDC_EPN_STAT); + epn_stat = omap_readw(UDC_EPN_STAT); + omap_writew(epnum | UDC_EP_DIR, UDC_EP_NUM); /* then 6 clocks before it'd tx */ } @@ -2021,7 +2040,7 @@ static irqreturn_t omap_udc_iso_irq(int irq, void *_dev) req = list_entry(ep->queue.next, struct omap_req, queue); use_ep(ep, UDC_EP_SEL); - stat = UDC_STAT_FLG_REG; + stat = omap_readw(UDC_STAT_FLG); /* NOTE: like the other controller drivers, this isn't * currently reporting lost or damaged frames. @@ -2053,9 +2072,14 @@ static irqreturn_t omap_udc_iso_irq(int irq, void *_dev) if (!list_empty(&ep->queue)) pending = 1; } - if (!pending) - UDC_IRQ_EN_REG &= ~UDC_SOF_IE; - UDC_IRQ_SRC_REG = UDC_SOF; + if (!pending) { + u16 w; + + w = omap_readw(UDC_IRQ_EN); + w &= ~UDC_SOF_IE; + omap_writew(w, UDC_IRQ_EN); + } + omap_writew(UDC_IRQ_SOF, UDC_IRQ_SRC); spin_unlock_irqrestore(&udc->lock, flags); return IRQ_HANDLED; @@ -2104,7 +2128,7 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver) if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC) continue; use_ep(ep, 0); - UDC_CTRL_REG = UDC_SET_HALT; + omap_writew(UDC_SET_HALT, UDC_CTRL); } udc->ep0_pending = 0; udc->ep[0].irqs = 0; @@ -2128,7 +2152,7 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver) } DBG("bound to driver %s\n", driver->driver.name); - UDC_IRQ_SRC_REG = UDC_IRQ_SRC_MASK; + omap_writew(UDC_IRQ_SRC_MASK, UDC_IRQ_SRC); /* connect to bus through transceiver */ if (udc->transceiver) { @@ -2225,7 +2249,7 @@ static void proc_ep_show(struct seq_file *s, struct omap_ep *ep) else buf[0] = 0; - stat_flg = UDC_STAT_FLG_REG; + stat_flg = omap_readw(UDC_STAT_FLG); seq_printf(s, "\n%s %s%s%sirqs %ld stat %04x " EIGHTBITS FOURBITS "%s\n", ep->name, buf, @@ -2292,11 +2316,11 @@ static int proc_otg_show(struct seq_file *s) trans = CONTROL_DEVCONF_REG; } else { ctrl_name = "tranceiver_ctrl"; - trans = USB_TRANSCEIVER_CTRL_REG; + trans = omap_readw(USB_TRANSCEIVER_CTRL); } seq_printf(s, "\nOTG rev %d.%d, %s %05x\n", tmp >> 4, tmp & 0xf, ctrl_name, trans); - tmp = OTG_SYSCON_1_REG; + tmp = omap_readw(OTG_SYSCON_1); seq_printf(s, "otg_syscon1 %08x usb2 %s, usb1 %s, usb0 %s," FOURBITS "\n", tmp, trx_mode(USB2_TRX_MODE(tmp), trans & CONF_USB2_UNI_R), @@ -2308,7 +2332,7 @@ static int proc_otg_show(struct seq_file *s) (tmp & HST_IDLE_EN) ? " !host" : "", (tmp & DEV_IDLE_EN) ? " !dev" : "", (tmp & OTG_RESET_DONE) ? " reset_done" : " reset_active"); - tmp = OTG_SYSCON_2_REG; + tmp = omap_readl(OTG_SYSCON_2); seq_printf(s, "otg_syscon2 %08x%s" EIGHTBITS " b_ase_brst=%d hmc=%d\n", tmp, (tmp & OTG_EN) ? " otg_en" : "", @@ -2323,7 +2347,7 @@ static int proc_otg_show(struct seq_file *s) (tmp & HMC_TLLATTACH) ? " tllattach" : "", B_ASE_BRST(tmp), OTG_HMC(tmp)); - tmp = OTG_CTRL_REG; + tmp = omap_readl(OTG_CTRL); seq_printf(s, "otg_ctrl %06x" EIGHTBITS EIGHTBITS "%s\n", tmp, (tmp & OTG_ASESSVLD) ? " asess" : "", (tmp & OTG_BSESSEND) ? " bsess_end" : "", @@ -2343,13 +2367,13 @@ static int proc_otg_show(struct seq_file *s) (tmp & OTG_PU_VBUS) ? " pu_vb" : "", (tmp & OTG_PU_ID) ? " pu_id" : "" ); - tmp = OTG_IRQ_EN_REG; + tmp = omap_readw(OTG_IRQ_EN); seq_printf(s, "otg_irq_en %04x" "\n", tmp); - tmp = OTG_IRQ_SRC_REG; + tmp = omap_readw(OTG_IRQ_SRC); seq_printf(s, "otg_irq_src %04x" "\n", tmp); - tmp = OTG_OUTCTRL_REG; + tmp = omap_readw(OTG_OUTCTRL); seq_printf(s, "otg_outctrl %04x" "\n", tmp); - tmp = OTG_TEST_REG; + tmp = omap_readw(OTG_TEST); seq_printf(s, "otg_test %04x" "\n", tmp); return 0; } @@ -2370,7 +2394,7 @@ static int proc_udc_show(struct seq_file *s, void *_) driver_desc, use_dma ? " (dma)" : ""); - tmp = UDC_REV_REG & 0xff; + tmp = omap_readw(UDC_REV) & 0xff; seq_printf(s, "UDC rev %d.%d, fifo mode %d, gadget %s\n" "hmc %d, transceiver %s\n", @@ -2384,16 +2408,16 @@ static int proc_udc_show(struct seq_file *s, void *_) ? "external" : "(none)")); if (cpu_class_is_omap1()) { seq_printf(s, "ULPD control %04x req %04x status %04x\n", - __REG16(ULPD_CLOCK_CTRL), - __REG16(ULPD_SOFT_REQ), - __REG16(ULPD_STATUS_REQ)); + omap_readw(ULPD_CLOCK_CTRL), + omap_readw(ULPD_SOFT_REQ), + omap_readw(ULPD_STATUS_REQ)); } /* OTG controller registers */ if (!cpu_is_omap15xx()) proc_otg_show(s); - tmp = UDC_SYSCON1_REG; + tmp = omap_readw(UDC_SYSCON1); seq_printf(s, "\nsyscon1 %04x" EIGHTBITS "\n", tmp, (tmp & UDC_CFG_LOCK) ? " cfg_lock" : "", (tmp & UDC_DATA_ENDIAN) ? " data_endian" : "", @@ -2412,7 +2436,7 @@ static int proc_udc_show(struct seq_file *s, void *_) return 0; } - tmp = UDC_DEVSTAT_REG; + tmp = omap_readw(UDC_DEVSTAT); seq_printf(s, "devstat %04x" EIGHTBITS "%s%s\n", tmp, (tmp & UDC_B_HNP_ENABLE) ? " b_hnp" : "", (tmp & UDC_A_HNP_SUPPORT) ? " a_hnp" : "", @@ -2424,20 +2448,20 @@ static int proc_udc_show(struct seq_file *s, void *_) (tmp & UDC_ADD) ? " ADD" : "", (tmp & UDC_DEF) ? " DEF" : "", (tmp & UDC_ATT) ? " ATT" : ""); - seq_printf(s, "sof %04x\n", UDC_SOF_REG); - tmp = UDC_IRQ_EN_REG; + seq_printf(s, "sof %04x\n", omap_readw(UDC_SOF)); + tmp = omap_readw(UDC_IRQ_EN); seq_printf(s, "irq_en %04x" FOURBITS "%s\n", tmp, (tmp & UDC_SOF_IE) ? " sof" : "", (tmp & UDC_EPN_RX_IE) ? " epn_rx" : "", (tmp & UDC_EPN_TX_IE) ? " epn_tx" : "", (tmp & UDC_DS_CHG_IE) ? " ds_chg" : "", (tmp & UDC_EP0_IE) ? " ep0" : ""); - tmp = UDC_IRQ_SRC_REG; + tmp = omap_readw(UDC_IRQ_SRC); seq_printf(s, "irq_src %04x" EIGHTBITS "%s%s\n", tmp, (tmp & UDC_TXN_DONE) ? " txn_done" : "", (tmp & UDC_RXN_CNT) ? " rxn_cnt" : "", (tmp & UDC_RXN_EOT) ? " rxn_eot" : "", - (tmp & UDC_SOF) ? " sof" : "", + (tmp & UDC_IRQ_SOF) ? " sof" : "", (tmp & UDC_EPN_RX) ? " epn_rx" : "", (tmp & UDC_EPN_TX) ? " epn_tx" : "", (tmp & UDC_DS_CHG) ? " ds_chg" : "", @@ -2447,7 +2471,7 @@ static int proc_udc_show(struct seq_file *s, void *_) if (use_dma) { unsigned i; - tmp = UDC_DMA_IRQ_EN_REG; + tmp = omap_readw(UDC_DMA_IRQ_EN); seq_printf(s, "dma_irq_en %04x%s" EIGHTBITS "\n", tmp, (tmp & UDC_TX_DONE_IE(3)) ? " tx2_done" : "", (tmp & UDC_RX_CNT_IE(3)) ? " rx2_cnt" : "", @@ -2461,29 +2485,29 @@ static int proc_udc_show(struct seq_file *s, void *_) (tmp & UDC_RX_CNT_IE(1)) ? " rx0_cnt" : "", (tmp & UDC_RX_EOT_IE(1)) ? " rx0_eot" : ""); - tmp = UDC_RXDMA_CFG_REG; + tmp = omap_readw(UDC_RXDMA_CFG); seq_printf(s, "rxdma_cfg %04x\n", tmp); if (tmp) { for (i = 0; i < 3; i++) { if ((tmp & (0x0f << (i * 4))) == 0) continue; seq_printf(s, "rxdma[%d] %04x\n", i, - UDC_RXDMA_REG(i + 1)); + omap_readw(UDC_RXDMA(i + 1))); } } - tmp = UDC_TXDMA_CFG_REG; + tmp = omap_readw(UDC_TXDMA_CFG); seq_printf(s, "txdma_cfg %04x\n", tmp); if (tmp) { for (i = 0; i < 3; i++) { if (!(tmp & (0x0f << (i * 4)))) continue; seq_printf(s, "txdma[%d] %04x\n", i, - UDC_TXDMA_REG(i + 1)); + omap_readw(UDC_TXDMA(i + 1))); } } } - tmp = UDC_DEVSTAT_REG; + tmp = omap_readw(UDC_DEVSTAT); if (tmp & UDC_ATT) { proc_ep_show(s, &udc->ep[0]); if (tmp & UDC_ADD) { @@ -2535,7 +2559,7 @@ static inline void remove_proc_file(void) {} * buffer space among the endpoints we'll be operating. * * NOTE: as of OMAP 1710 ES2.0, writing a new endpoint config when - * UDC_SYSCON_1_REG.CFG_LOCK is set can now work. We won't use that + * UDC_SYSCON_1.CFG_LOCK is set can now work. We won't use that * capability yet though. */ static unsigned __init @@ -2597,9 +2621,9 @@ omap_ep_setup(char *name, u8 addr, u8 type, name, addr, epn_rxtx, maxp, dbuf ? "x2" : "", buf); if (addr & USB_DIR_IN) - UDC_EP_TX_REG(addr & 0xf) = epn_rxtx; + omap_writew(epn_rxtx, UDC_EP_TX(addr & 0xf)); else - UDC_EP_RX_REG(addr) = epn_rxtx; + omap_writew(epn_rxtx, UDC_EP_RX(addr)); /* next endpoint's buffer starts after this one's */ buf += maxp; @@ -2638,15 +2662,15 @@ omap_udc_setup(struct platform_device *odev, struct otg_transceiver *xceiv) unsigned tmp, buf; /* abolish any previous hardware state */ - UDC_SYSCON1_REG = 0; - UDC_IRQ_EN_REG = 0; - UDC_IRQ_SRC_REG = UDC_IRQ_SRC_MASK; - UDC_DMA_IRQ_EN_REG = 0; - UDC_RXDMA_CFG_REG = 0; - UDC_TXDMA_CFG_REG = 0; + omap_writew(0, UDC_SYSCON1); + omap_writew(0, UDC_IRQ_EN); + omap_writew(UDC_IRQ_SRC_MASK, UDC_IRQ_SRC); + omap_writew(0, UDC_DMA_IRQ_EN); + omap_writew(0, UDC_RXDMA_CFG); + omap_writew(0, UDC_TXDMA_CFG); /* UDC_PULLUP_EN gates the chip clock */ - // OTG_SYSCON_1_REG |= DEV_IDLE_EN; + // OTG_SYSCON_1 |= DEV_IDLE_EN; udc = kzalloc(sizeof(*udc), GFP_KERNEL); if (!udc) @@ -2677,8 +2701,8 @@ omap_udc_setup(struct platform_device *odev, struct otg_transceiver *xceiv) /* initially disable all non-ep0 endpoints */ for (tmp = 1; tmp < 15; tmp++) { - UDC_EP_RX_REG(tmp) = 0; - UDC_EP_TX_REG(tmp) = 0; + omap_writew(0, UDC_EP_RX(tmp)); + omap_writew(0, UDC_EP_TX(tmp)); } #define OMAP_BULK_EP(name,addr) \ @@ -2763,7 +2787,7 @@ omap_udc_setup(struct platform_device *odev, struct otg_transceiver *xceiv) ERR("unsupported fifo_mode #%d\n", fifo_mode); return -ENODEV; } - UDC_SYSCON1_REG = UDC_CFG_LOCK|UDC_SELF_PWR; + omap_writew(UDC_CFG_LOCK|UDC_SELF_PWR, UDC_SYSCON1); INFO("fifo mode %d, %d bytes not used\n", fifo_mode, 2048 - buf); return 0; } @@ -2807,7 +2831,7 @@ static int __init omap_udc_probe(struct platform_device *pdev) } INFO("OMAP UDC rev %d.%d%s\n", - UDC_REV_REG >> 4, UDC_REV_REG & 0xf, + omap_readw(UDC_REV) >> 4, omap_readw(UDC_REV) & 0xf, config->otg ? ", Mini-AB" : ""); /* use the mode given to us by board init code */ @@ -2822,12 +2846,12 @@ static int __init omap_udc_probe(struct platform_device *pdev) * know when to turn PULLUP_EN on/off; and that * means we always "need" the 48MHz clock. */ - u32 tmp = FUNC_MUX_CTRL_0_REG; - - FUNC_MUX_CTRL_0_REG &= ~VBUS_CTRL_1510; + u32 tmp = omap_readl(FUNC_MUX_CTRL_0); + tmp &= ~VBUS_CTRL_1510; + omap_writel(tmp, FUNC_MUX_CTRL_0); tmp |= VBUS_MODE_1510; tmp &= ~VBUS_CTRL_1510; - FUNC_MUX_CTRL_0_REG = tmp; + omap_writel(tmp, FUNC_MUX_CTRL_0); } } else { /* The transceiver may package some GPIO logic or handle @@ -2907,7 +2931,7 @@ known: #endif /* starting with omap1710 es2.0, clear toggle is a separate bit */ - if (UDC_REV_REG >= 0x61) + if (omap_readw(UDC_REV) >= 0x61) udc->clr_halt = UDC_RESET_EP | UDC_CLRDATA_TOGGLE; else udc->clr_halt = UDC_RESET_EP; @@ -3005,7 +3029,7 @@ static int __exit omap_udc_remove(struct platform_device *pdev) put_device(udc->transceiver->dev); udc->transceiver = NULL; } - UDC_SYSCON1_REG = 0; + omap_writew(0, UDC_SYSCON1); remove_proc_file(); @@ -3036,7 +3060,7 @@ static int __exit omap_udc_remove(struct platform_device *pdev) * * REVISIT we should probably reject suspend requests when there's a host * session active, rather than disconnecting, at least on boards that can - * report VBUS irqs (UDC_DEVSTAT_REG.UDC_ATT). And in any case, we need to + * report VBUS irqs (UDC_DEVSTAT.UDC_ATT). And in any case, we need to * make host resumes and VBUS detection trigger OMAP wakeup events; that * may involve talking to an external transceiver (e.g. isp1301). */ @@ -3045,7 +3069,7 @@ static int omap_udc_suspend(struct platform_device *dev, pm_message_t message) { u32 devstat; - devstat = UDC_DEVSTAT_REG; + devstat = omap_readw(UDC_DEVSTAT); /* we're requesting 48 MHz clock if the pullup is enabled * (== we're attached to the host) and we're not suspended, diff --git a/drivers/usb/gadget/omap_udc.h b/drivers/usb/gadget/omap_udc.h index c6b9cbc7230..8522bbb1227 100644 --- a/drivers/usb/gadget/omap_udc.h +++ b/drivers/usb/gadget/omap_udc.h @@ -8,23 +8,22 @@ /* * USB device/endpoint management registers */ -#define UDC_REG(offset) __REG16(UDC_BASE + (offset)) -#define UDC_REV_REG UDC_REG(0x0) /* Revision */ -#define UDC_EP_NUM_REG UDC_REG(0x4) /* Which endpoint */ +#define UDC_REV (UDC_BASE + 0x0) /* Revision */ +#define UDC_EP_NUM (UDC_BASE + 0x4) /* Which endpoint */ # define UDC_SETUP_SEL (1 << 6) # define UDC_EP_SEL (1 << 5) # define UDC_EP_DIR (1 << 4) /* low 4 bits for endpoint number */ -#define UDC_DATA_REG UDC_REG(0x08) /* Endpoint FIFO */ -#define UDC_CTRL_REG UDC_REG(0x0C) /* Endpoint control */ +#define UDC_DATA (UDC_BASE + 0x08) /* Endpoint FIFO */ +#define UDC_CTRL (UDC_BASE + 0x0C) /* Endpoint control */ # define UDC_CLR_HALT (1 << 7) # define UDC_SET_HALT (1 << 6) # define UDC_CLRDATA_TOGGLE (1 << 3) # define UDC_SET_FIFO_EN (1 << 2) # define UDC_CLR_EP (1 << 1) # define UDC_RESET_EP (1 << 0) -#define UDC_STAT_FLG_REG UDC_REG(0x10) /* Endpoint status */ +#define UDC_STAT_FLG (UDC_BASE + 0x10) /* Endpoint status */ # define UDC_NO_RXPACKET (1 << 15) # define UDC_MISS_IN (1 << 14) # define UDC_DATA_FLUSH (1 << 13) @@ -38,8 +37,8 @@ # define UDC_FIFO_EN (1 << 2) # define UDC_NON_ISO_FIFO_EMPTY (1 << 1) # define UDC_NON_ISO_FIFO_FULL (1 << 0) -#define UDC_RXFSTAT_REG UDC_REG(0x14) /* OUT bytecount */ -#define UDC_SYSCON1_REG UDC_REG(0x18) /* System config 1 */ +#define UDC_RXFSTAT (UDC_BASE + 0x14) /* OUT bytecount */ +#define UDC_SYSCON1 (UDC_BASE + 0x18) /* System config 1 */ # define UDC_CFG_LOCK (1 << 8) # define UDC_DATA_ENDIAN (1 << 7) # define UDC_DMA_ENDIAN (1 << 6) @@ -48,12 +47,12 @@ # define UDC_SELF_PWR (1 << 2) # define UDC_SOFF_DIS (1 << 1) # define UDC_PULLUP_EN (1 << 0) -#define UDC_SYSCON2_REG UDC_REG(0x1C) /* System config 2 */ +#define UDC_SYSCON2 (UDC_BASE + 0x1C) /* System config 2 */ # define UDC_RMT_WKP (1 << 6) # define UDC_STALL_CMD (1 << 5) # define UDC_DEV_CFG (1 << 3) # define UDC_CLR_CFG (1 << 2) -#define UDC_DEVSTAT_REG UDC_REG(0x20) /* Device status */ +#define UDC_DEVSTAT (UDC_BASE + 0x20) /* Device status */ # define UDC_B_HNP_ENABLE (1 << 9) # define UDC_A_HNP_SUPPORT (1 << 8) # define UDC_A_ALT_HNP_SUPPORT (1 << 7) @@ -64,26 +63,26 @@ # define UDC_ADD (1 << 2) # define UDC_DEF (1 << 1) # define UDC_ATT (1 << 0) -#define UDC_SOF_REG UDC_REG(0x24) /* Start of frame */ +#define UDC_SOF (UDC_BASE + 0x24) /* Start of frame */ # define UDC_FT_LOCK (1 << 12) # define UDC_TS_OK (1 << 11) # define UDC_TS 0x03ff -#define UDC_IRQ_EN_REG UDC_REG(0x28) /* Interrupt enable */ +#define UDC_IRQ_EN (UDC_BASE + 0x28) /* Interrupt enable */ # define UDC_SOF_IE (1 << 7) # define UDC_EPN_RX_IE (1 << 5) # define UDC_EPN_TX_IE (1 << 4) # define UDC_DS_CHG_IE (1 << 3) # define UDC_EP0_IE (1 << 0) -#define UDC_DMA_IRQ_EN_REG UDC_REG(0x2C) /* DMA irq enable */ +#define UDC_DMA_IRQ_EN (UDC_BASE + 0x2C) /* DMA irq enable */ /* rx/tx dma channels numbered 1-3 not 0-2 */ # define UDC_TX_DONE_IE(n) (1 << (4 * (n) - 2)) # define UDC_RX_CNT_IE(n) (1 << (4 * (n) - 3)) # define UDC_RX_EOT_IE(n) (1 << (4 * (n) - 4)) -#define UDC_IRQ_SRC_REG UDC_REG(0x30) /* Interrupt source */ +#define UDC_IRQ_SRC (UDC_BASE + 0x30) /* Interrupt source */ # define UDC_TXN_DONE (1 << 10) # define UDC_RXN_CNT (1 << 9) # define UDC_RXN_EOT (1 << 8) -# define UDC_SOF (1 << 7) +# define UDC_IRQ_SOF (1 << 7) # define UDC_EPN_RX (1 << 5) # define UDC_EPN_TX (1 << 4) # define UDC_DS_CHG (1 << 3) @@ -91,41 +90,41 @@ # define UDC_EP0_RX (1 << 1) # define UDC_EP0_TX (1 << 0) # define UDC_IRQ_SRC_MASK 0x7bf -#define UDC_EPN_STAT_REG UDC_REG(0x34) /* EP irq status */ -#define UDC_DMAN_STAT_REG UDC_REG(0x38) /* DMA irq status */ +#define UDC_EPN_STAT (UDC_BASE + 0x34) /* EP irq status */ +#define UDC_DMAN_STAT (UDC_BASE + 0x38) /* DMA irq status */ # define UDC_DMA_RX_SB (1 << 12) # define UDC_DMA_RX_SRC(x) (((x)>>8) & 0xf) # define UDC_DMA_TX_SRC(x) (((x)>>0) & 0xf) /* DMA configuration registers: up to three channels in each direction. */ -#define UDC_RXDMA_CFG_REG UDC_REG(0x40) /* 3 eps for RX DMA */ +#define UDC_RXDMA_CFG (UDC_BASE + 0x40) /* 3 eps for RX DMA */ # define UDC_DMA_REQ (1 << 12) -#define UDC_TXDMA_CFG_REG UDC_REG(0x44) /* 3 eps for TX DMA */ -#define UDC_DATA_DMA_REG UDC_REG(0x48) /* rx/tx fifo addr */ +#define UDC_TXDMA_CFG (UDC_BASE + 0x44) /* 3 eps for TX DMA */ +#define UDC_DATA_DMA (UDC_BASE + 0x48) /* rx/tx fifo addr */ /* rx/tx dma control, numbering channels 1-3 not 0-2 */ -#define UDC_TXDMA_REG(chan) UDC_REG(0x50 - 4 + 4 * (chan)) +#define UDC_TXDMA(chan) (UDC_BASE + 0x50 - 4 + 4 * (chan)) # define UDC_TXN_EOT (1 << 15) /* bytes vs packets */ # define UDC_TXN_START (1 << 14) /* start transfer */ # define UDC_TXN_TSC 0x03ff /* units in xfer */ -#define UDC_RXDMA_REG(chan) UDC_REG(0x60 - 4 + 4 * (chan)) +#define UDC_RXDMA(chan) (UDC_BASE + 0x60 - 4 + 4 * (chan)) # define UDC_RXN_STOP (1 << 15) /* enable EOT irq */ # define UDC_RXN_TC 0x00ff /* packets in xfer */ /* * Endpoint configuration registers (used before CFG_LOCK is set) - * UDC_EP_TX_REG(0) is unused + * UDC_EP_TX(0) is unused */ -#define UDC_EP_RX_REG(endpoint) UDC_REG(0x80 + (endpoint)*4) +#define UDC_EP_RX(endpoint) (UDC_BASE + 0x80 + (endpoint)*4) # define UDC_EPN_RX_VALID (1 << 15) # define UDC_EPN_RX_DB (1 << 14) /* buffer size in bits 13, 12 */ # define UDC_EPN_RX_ISO (1 << 11) /* buffer pointer in low 11 bits */ -#define UDC_EP_TX_REG(endpoint) UDC_REG(0xc0 + (endpoint)*4) - /* same bitfields as in RX_REG */ +#define UDC_EP_TX(endpoint) (UDC_BASE + 0xc0 + (endpoint)*4) + /* same bitfields as in RX */ /*-------------------------------------------------------------------------*/ @@ -195,14 +194,14 @@ struct omap_udc { /*-------------------------------------------------------------------------*/ -#define MOD_CONF_CTRL_0_REG __REG32(MOD_CONF_CTRL_0) -#define VBUS_W2FC_1510 (1 << 17) /* 0 gpio0, 1 dvdd2 pin */ +/* MOD_CONF_CTRL_0 */ +#define VBUS_W2FC_1510 (1 << 17) /* 0 gpio0, 1 dvdd2 pin */ -#define FUNC_MUX_CTRL_0_REG __REG32(FUNC_MUX_CTRL_0) +/* FUNC_MUX_CTRL_0 */ #define VBUS_CTRL_1510 (1 << 19) /* 1 connected (software) */ #define VBUS_MODE_1510 (1 << 18) /* 0 hardware, 1 software */ -#define HMC_1510 ((MOD_CONF_CTRL_0_REG >> 1) & 0x3f) -#define HMC_1610 (OTG_SYSCON_2_REG & 0x3f) +#define HMC_1510 ((omap_readl(MOD_CONF_CTRL_0) >> 1) & 0x3f) +#define HMC_1610 (omap_readl(OTG_SYSCON_2) & 0x3f) #define HMC (cpu_is_omap15xx() ? HMC_1510 : HMC_1610) diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa25x_udc.c index 08f699b1fc5..031dceb9302 100644 --- a/drivers/usb/gadget/pxa2xx_udc.c +++ b/drivers/usb/gadget/pxa25x_udc.c @@ -1,5 +1,4 @@ /* - * linux/drivers/usb/gadget/pxa2xx_udc.c * Intel PXA25x and IXP4xx on-chip full speed USB device controllers * * Copyright (C) 2002 Intrinsyc, Inc. (Frank Becker) @@ -46,19 +45,25 @@ #include <linux/err.h> #include <linux/seq_file.h> #include <linux/debugfs.h> +#include <linux/io.h> #include <asm/byteorder.h> #include <asm/dma.h> #include <asm/gpio.h> -#include <asm/io.h> #include <asm/system.h> #include <asm/mach-types.h> #include <asm/unaligned.h> -#include <asm/hardware.h> #include <linux/usb/ch9.h> #include <linux/usb/gadget.h> +/* + * This driver is PXA25x only. Grab the right register definitions. + */ +#ifdef CONFIG_ARCH_PXA +#include <asm/arch/pxa25x-udc.h> +#endif + #include <asm/mach/udc_pxa2xx.h> @@ -91,7 +96,7 @@ #define DRIVER_DESC "PXA 25x USB Device Controller driver" -static const char driver_name [] = "pxa2xx_udc"; +static const char driver_name [] = "pxa25x_udc"; static const char ep0name [] = "ep0"; @@ -111,10 +116,10 @@ static const char ep0name [] = "ep0"; #endif -#include "pxa2xx_udc.h" +#include "pxa25x_udc.h" -#ifdef CONFIG_USB_PXA2XX_SMALL +#ifdef CONFIG_USB_PXA25X_SMALL #define SIZE_STR " (small)" #else #define SIZE_STR "" @@ -126,8 +131,8 @@ static const char ep0name [] = "ep0"; * --------------------------------------------------------------------------- */ -static void pxa2xx_ep_fifo_flush (struct usb_ep *ep); -static void nuke (struct pxa2xx_ep *, int status); +static void pxa25x_ep_fifo_flush (struct usb_ep *ep); +static void nuke (struct pxa25x_ep *, int status); /* one GPIO should be used to detect VBUS from the host */ static int is_vbus_present(void) @@ -212,24 +217,24 @@ static inline void udc_ack_int_UDCCR(int mask) /* * endpoint enable/disable * - * we need to verify the descriptors used to enable endpoints. since pxa2xx + * we need to verify the descriptors used to enable endpoints. since pxa25x * endpoint configurations are fixed, and are pretty much always enabled, * there's not a lot to manage here. * - * because pxa2xx can't selectively initialize bulk (or interrupt) endpoints, + * because pxa25x can't selectively initialize bulk (or interrupt) endpoints, * (resetting endpoint halt and toggle), SET_INTERFACE is unusable except * for a single interface (with only the default altsetting) and for gadget * drivers that don't halt endpoints (not reset by set_interface). that also * means that if you use ISO, you must violate the USB spec rule that all * iso endpoints must be in non-default altsettings. */ -static int pxa2xx_ep_enable (struct usb_ep *_ep, +static int pxa25x_ep_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) { - struct pxa2xx_ep *ep; - struct pxa2xx_udc *dev; + struct pxa25x_ep *ep; + struct pxa25x_udc *dev; - ep = container_of (_ep, struct pxa2xx_ep, ep); + ep = container_of (_ep, struct pxa25x_ep, ep); if (!_ep || !desc || ep->desc || _ep->name == ep0name || desc->bDescriptorType != USB_DT_ENDPOINT || ep->bEndpointAddress != desc->bEndpointAddress @@ -268,7 +273,7 @@ static int pxa2xx_ep_enable (struct usb_ep *_ep, ep->ep.maxpacket = le16_to_cpu (desc->wMaxPacketSize); /* flush fifo (mostly for OUT buffers) */ - pxa2xx_ep_fifo_flush (_ep); + pxa25x_ep_fifo_flush (_ep); /* ... reset halt state too, if we could ... */ @@ -276,12 +281,12 @@ static int pxa2xx_ep_enable (struct usb_ep *_ep, return 0; } -static int pxa2xx_ep_disable (struct usb_ep *_ep) +static int pxa25x_ep_disable (struct usb_ep *_ep) { - struct pxa2xx_ep *ep; + struct pxa25x_ep *ep; unsigned long flags; - ep = container_of (_ep, struct pxa2xx_ep, ep); + ep = container_of (_ep, struct pxa25x_ep, ep); if (!_ep || !ep->desc) { DMSG("%s, %s not enabled\n", __func__, _ep ? ep->ep.name : NULL); @@ -292,7 +297,7 @@ static int pxa2xx_ep_disable (struct usb_ep *_ep) nuke (ep, -ESHUTDOWN); /* flush fifo (mostly for IN buffers) */ - pxa2xx_ep_fifo_flush (_ep); + pxa25x_ep_fifo_flush (_ep); ep->desc = NULL; ep->stopped = 1; @@ -304,18 +309,18 @@ static int pxa2xx_ep_disable (struct usb_ep *_ep) /*-------------------------------------------------------------------------*/ -/* for the pxa2xx, these can just wrap kmalloc/kfree. gadget drivers +/* for the pxa25x, these can just wrap kmalloc/kfree. gadget drivers * must still pass correctly initialized endpoints, since other controller * drivers may care about how it's currently set up (dma issues etc). */ /* - * pxa2xx_ep_alloc_request - allocate a request data structure + * pxa25x_ep_alloc_request - allocate a request data structure */ static struct usb_request * -pxa2xx_ep_alloc_request (struct usb_ep *_ep, gfp_t gfp_flags) +pxa25x_ep_alloc_request (struct usb_ep *_ep, gfp_t gfp_flags) { - struct pxa2xx_request *req; + struct pxa25x_request *req; req = kzalloc(sizeof(*req), gfp_flags); if (!req) @@ -327,14 +332,14 @@ pxa2xx_ep_alloc_request (struct usb_ep *_ep, gfp_t gfp_flags) /* - * pxa2xx_ep_free_request - deallocate a request data structure + * pxa25x_ep_free_request - deallocate a request data structure */ static void -pxa2xx_ep_free_request (struct usb_ep *_ep, struct usb_request *_req) +pxa25x_ep_free_request (struct usb_ep *_ep, struct usb_request *_req) { - struct pxa2xx_request *req; + struct pxa25x_request *req; - req = container_of (_req, struct pxa2xx_request, req); + req = container_of (_req, struct pxa25x_request, req); WARN_ON (!list_empty (&req->queue)); kfree(req); } @@ -344,7 +349,7 @@ pxa2xx_ep_free_request (struct usb_ep *_ep, struct usb_request *_req) /* * done - retire a request; caller blocked irqs */ -static void done(struct pxa2xx_ep *ep, struct pxa2xx_request *req, int status) +static void done(struct pxa25x_ep *ep, struct pxa25x_request *req, int status) { unsigned stopped = ep->stopped; @@ -367,13 +372,13 @@ static void done(struct pxa2xx_ep *ep, struct pxa2xx_request *req, int status) } -static inline void ep0_idle (struct pxa2xx_udc *dev) +static inline void ep0_idle (struct pxa25x_udc *dev) { dev->ep0state = EP0_IDLE; } static int -write_packet(volatile u32 *uddr, struct pxa2xx_request *req, unsigned max) +write_packet(volatile u32 *uddr, struct pxa25x_request *req, unsigned max) { u8 *buf; unsigned length, count; @@ -398,7 +403,7 @@ write_packet(volatile u32 *uddr, struct pxa2xx_request *req, unsigned max) * caller guarantees at least one packet buffer is ready (or a zlp). */ static int -write_fifo (struct pxa2xx_ep *ep, struct pxa2xx_request *req) +write_fifo (struct pxa25x_ep *ep, struct pxa25x_request *req) { unsigned max; @@ -455,7 +460,7 @@ write_fifo (struct pxa2xx_ep *ep, struct pxa2xx_request *req) * ep0 data stage. these chips want very simple state transitions. */ static inline -void ep0start(struct pxa2xx_udc *dev, u32 flags, const char *tag) +void ep0start(struct pxa25x_udc *dev, u32 flags, const char *tag) { UDCCS0 = flags|UDCCS0_SA|UDCCS0_OPR; USIR0 = USIR0_IR0; @@ -465,7 +470,7 @@ void ep0start(struct pxa2xx_udc *dev, u32 flags, const char *tag) } static int -write_ep0_fifo (struct pxa2xx_ep *ep, struct pxa2xx_request *req) +write_ep0_fifo (struct pxa25x_ep *ep, struct pxa25x_request *req) { unsigned count; int is_short; @@ -525,7 +530,7 @@ write_ep0_fifo (struct pxa2xx_ep *ep, struct pxa2xx_request *req) * request buffer having filled (and maybe overran till end-of-packet). */ static int -read_fifo (struct pxa2xx_ep *ep, struct pxa2xx_request *req) +read_fifo (struct pxa25x_ep *ep, struct pxa25x_request *req) { for (;;) { u32 udccs; @@ -602,7 +607,7 @@ read_fifo (struct pxa2xx_ep *ep, struct pxa2xx_request *req) * protocols do use them. */ static int -read_ep0_fifo (struct pxa2xx_ep *ep, struct pxa2xx_request *req) +read_ep0_fifo (struct pxa25x_ep *ep, struct pxa25x_request *req) { u8 *buf, byte; unsigned bufferspace; @@ -641,21 +646,21 @@ read_ep0_fifo (struct pxa2xx_ep *ep, struct pxa2xx_request *req) /*-------------------------------------------------------------------------*/ static int -pxa2xx_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) +pxa25x_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) { - struct pxa2xx_request *req; - struct pxa2xx_ep *ep; - struct pxa2xx_udc *dev; + struct pxa25x_request *req; + struct pxa25x_ep *ep; + struct pxa25x_udc *dev; unsigned long flags; - req = container_of(_req, struct pxa2xx_request, req); + req = container_of(_req, struct pxa25x_request, req); if (unlikely (!_req || !_req->complete || !_req->buf || !list_empty(&req->queue))) { DMSG("%s, bad params\n", __func__); return -EINVAL; } - ep = container_of(_ep, struct pxa2xx_ep, ep); + ep = container_of(_ep, struct pxa25x_ep, ep); if (unlikely (!_ep || (!ep->desc && ep->ep.name != ep0name))) { DMSG("%s, bad ep\n", __func__); return -EINVAL; @@ -751,14 +756,14 @@ pxa2xx_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) /* * nuke - dequeue ALL requests */ -static void nuke(struct pxa2xx_ep *ep, int status) +static void nuke(struct pxa25x_ep *ep, int status) { - struct pxa2xx_request *req; + struct pxa25x_request *req; /* called with irqs blocked */ while (!list_empty(&ep->queue)) { req = list_entry(ep->queue.next, - struct pxa2xx_request, + struct pxa25x_request, queue); done(ep, req, status); } @@ -768,13 +773,13 @@ static void nuke(struct pxa2xx_ep *ep, int status) /* dequeue JUST ONE request */ -static int pxa2xx_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req) +static int pxa25x_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req) { - struct pxa2xx_ep *ep; - struct pxa2xx_request *req; + struct pxa25x_ep *ep; + struct pxa25x_request *req; unsigned long flags; - ep = container_of(_ep, struct pxa2xx_ep, ep); + ep = container_of(_ep, struct pxa25x_ep, ep); if (!_ep || ep->ep.name == ep0name) return -EINVAL; @@ -798,12 +803,12 @@ static int pxa2xx_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req) /*-------------------------------------------------------------------------*/ -static int pxa2xx_ep_set_halt(struct usb_ep *_ep, int value) +static int pxa25x_ep_set_halt(struct usb_ep *_ep, int value) { - struct pxa2xx_ep *ep; + struct pxa25x_ep *ep; unsigned long flags; - ep = container_of(_ep, struct pxa2xx_ep, ep); + ep = container_of(_ep, struct pxa25x_ep, ep); if (unlikely (!_ep || (!ep->desc && ep->ep.name != ep0name)) || ep->bmAttributes == USB_ENDPOINT_XFER_ISOC) { @@ -853,11 +858,11 @@ static int pxa2xx_ep_set_halt(struct usb_ep *_ep, int value) return 0; } -static int pxa2xx_ep_fifo_status(struct usb_ep *_ep) +static int pxa25x_ep_fifo_status(struct usb_ep *_ep) { - struct pxa2xx_ep *ep; + struct pxa25x_ep *ep; - ep = container_of(_ep, struct pxa2xx_ep, ep); + ep = container_of(_ep, struct pxa25x_ep, ep); if (!_ep) { DMSG("%s, bad ep\n", __func__); return -ENODEV; @@ -872,11 +877,11 @@ static int pxa2xx_ep_fifo_status(struct usb_ep *_ep) return (*ep->reg_ubcr & 0xfff) + 1; } -static void pxa2xx_ep_fifo_flush(struct usb_ep *_ep) +static void pxa25x_ep_fifo_flush(struct usb_ep *_ep) { - struct pxa2xx_ep *ep; + struct pxa25x_ep *ep; - ep = container_of(_ep, struct pxa2xx_ep, ep); + ep = container_of(_ep, struct pxa25x_ep, ep); if (!_ep || ep->ep.name == ep0name || !list_empty(&ep->queue)) { DMSG("%s, bad ep\n", __func__); return; @@ -898,19 +903,19 @@ static void pxa2xx_ep_fifo_flush(struct usb_ep *_ep) } -static struct usb_ep_ops pxa2xx_ep_ops = { - .enable = pxa2xx_ep_enable, - .disable = pxa2xx_ep_disable, +static struct usb_ep_ops pxa25x_ep_ops = { + .enable = pxa25x_ep_enable, + .disable = pxa25x_ep_disable, - .alloc_request = pxa2xx_ep_alloc_request, - .free_request = pxa2xx_ep_free_request, + .alloc_request = pxa25x_ep_alloc_request, + .free_request = pxa25x_ep_free_request, - .queue = pxa2xx_ep_queue, - .dequeue = pxa2xx_ep_dequeue, + .queue = pxa25x_ep_queue, + .dequeue = pxa25x_ep_dequeue, - .set_halt = pxa2xx_ep_set_halt, - .fifo_status = pxa2xx_ep_fifo_status, - .fifo_flush = pxa2xx_ep_fifo_flush, + .set_halt = pxa25x_ep_set_halt, + .fifo_status = pxa25x_ep_fifo_status, + .fifo_flush = pxa25x_ep_fifo_flush, }; @@ -919,12 +924,12 @@ static struct usb_ep_ops pxa2xx_ep_ops = { * --------------------------------------------------------------------------- */ -static int pxa2xx_udc_get_frame(struct usb_gadget *_gadget) +static int pxa25x_udc_get_frame(struct usb_gadget *_gadget) { return ((UFNRH & 0x07) << 8) | (UFNRL & 0xff); } -static int pxa2xx_udc_wakeup(struct usb_gadget *_gadget) +static int pxa25x_udc_wakeup(struct usb_gadget *_gadget) { /* host may not have enabled remote wakeup */ if ((UDCCS0 & UDCCS0_DRWF) == 0) @@ -933,14 +938,14 @@ static int pxa2xx_udc_wakeup(struct usb_gadget *_gadget) return 0; } -static void stop_activity(struct pxa2xx_udc *, struct usb_gadget_driver *); -static void udc_enable (struct pxa2xx_udc *); -static void udc_disable(struct pxa2xx_udc *); +static void stop_activity(struct pxa25x_udc *, struct usb_gadget_driver *); +static void udc_enable (struct pxa25x_udc *); +static void udc_disable(struct pxa25x_udc *); /* We disable the UDC -- and its 48 MHz clock -- whenever it's not * in active use. */ -static int pullup(struct pxa2xx_udc *udc) +static int pullup(struct pxa25x_udc *udc) { int is_active = udc->vbus && udc->pullup && !udc->suspended; DMSG("%s\n", is_active ? "active" : "inactive"); @@ -970,11 +975,11 @@ static int pullup(struct pxa2xx_udc *udc) } /* VBUS reporting logically comes from a transceiver */ -static int pxa2xx_udc_vbus_session(struct usb_gadget *_gadget, int is_active) +static int pxa25x_udc_vbus_session(struct usb_gadget *_gadget, int is_active) { - struct pxa2xx_udc *udc; + struct pxa25x_udc *udc; - udc = container_of(_gadget, struct pxa2xx_udc, gadget); + udc = container_of(_gadget, struct pxa25x_udc, gadget); udc->vbus = (is_active != 0); DMSG("vbus %s\n", is_active ? "supplied" : "inactive"); pullup(udc); @@ -982,11 +987,11 @@ static int pxa2xx_udc_vbus_session(struct usb_gadget *_gadget, int is_active) } /* drivers may have software control over D+ pullup */ -static int pxa2xx_udc_pullup(struct usb_gadget *_gadget, int is_active) +static int pxa25x_udc_pullup(struct usb_gadget *_gadget, int is_active) { - struct pxa2xx_udc *udc; + struct pxa25x_udc *udc; - udc = container_of(_gadget, struct pxa2xx_udc, gadget); + udc = container_of(_gadget, struct pxa25x_udc, gadget); /* not all boards support pullup control */ if (!udc->mach->gpio_pullup && !udc->mach->udc_command) @@ -997,11 +1002,11 @@ static int pxa2xx_udc_pullup(struct usb_gadget *_gadget, int is_active) return 0; } -static const struct usb_gadget_ops pxa2xx_udc_ops = { - .get_frame = pxa2xx_udc_get_frame, - .wakeup = pxa2xx_udc_wakeup, - .vbus_session = pxa2xx_udc_vbus_session, - .pullup = pxa2xx_udc_pullup, +static const struct usb_gadget_ops pxa25x_udc_ops = { + .get_frame = pxa25x_udc_get_frame, + .wakeup = pxa25x_udc_wakeup, + .vbus_session = pxa25x_udc_vbus_session, + .pullup = pxa25x_udc_pullup, // .vbus_draw ... boards may consume current from VBUS, up to // 100-500mA based on config. the 500uA suspend ceiling means @@ -1015,7 +1020,7 @@ static const struct usb_gadget_ops pxa2xx_udc_ops = { static int udc_seq_show(struct seq_file *m, void *_d) { - struct pxa2xx_udc *dev = m->private; + struct pxa25x_udc *dev = m->private; unsigned long flags; int i; u32 tmp; @@ -1076,8 +1081,8 @@ udc_seq_show(struct seq_file *m, void *_d) /* dump endpoint queues */ for (i = 0; i < PXA_UDC_NUM_ENDPOINTS; i++) { - struct pxa2xx_ep *ep = &dev->ep [i]; - struct pxa2xx_request *req; + struct pxa25x_ep *ep = &dev->ep [i]; + struct pxa25x_request *req; if (i != 0) { const struct usb_endpoint_descriptor *desc; @@ -1150,7 +1155,7 @@ static const struct file_operations debug_fops = { /* * udc_disable - disable USB device controller */ -static void udc_disable(struct pxa2xx_udc *dev) +static void udc_disable(struct pxa25x_udc *dev) { /* block all irqs */ udc_set_mask_UDCCR(UDCCR_SRM|UDCCR_REM); @@ -1170,7 +1175,7 @@ static void udc_disable(struct pxa2xx_udc *dev) /* * udc_reinit - initialize software state */ -static void udc_reinit(struct pxa2xx_udc *dev) +static void udc_reinit(struct pxa25x_udc *dev) { u32 i; @@ -1181,7 +1186,7 @@ static void udc_reinit(struct pxa2xx_udc *dev) /* basic endpoint records init */ for (i = 0; i < PXA_UDC_NUM_ENDPOINTS; i++) { - struct pxa2xx_ep *ep = &dev->ep[i]; + struct pxa25x_ep *ep = &dev->ep[i]; if (i != 0) list_add_tail (&ep->ep.ep_list, &dev->gadget.ep_list); @@ -1198,7 +1203,7 @@ static void udc_reinit(struct pxa2xx_udc *dev) /* until it's enabled, this UDC should be completely invisible * to any USB host. */ -static void udc_enable (struct pxa2xx_udc *dev) +static void udc_enable (struct pxa25x_udc *dev) { udc_clear_mask_UDCCR(UDCCR_UDE); @@ -1254,7 +1259,7 @@ static void udc_enable (struct pxa2xx_udc *dev) */ int usb_gadget_register_driver(struct usb_gadget_driver *driver) { - struct pxa2xx_udc *dev = the_controller; + struct pxa25x_udc *dev = the_controller; int retval; if (!driver @@ -1299,7 +1304,7 @@ fail: EXPORT_SYMBOL(usb_gadget_register_driver); static void -stop_activity(struct pxa2xx_udc *dev, struct usb_gadget_driver *driver) +stop_activity(struct pxa25x_udc *dev, struct usb_gadget_driver *driver) { int i; @@ -1310,7 +1315,7 @@ stop_activity(struct pxa2xx_udc *dev, struct usb_gadget_driver *driver) /* prevent new request submissions, kill any outstanding requests */ for (i = 0; i < PXA_UDC_NUM_ENDPOINTS; i++) { - struct pxa2xx_ep *ep = &dev->ep[i]; + struct pxa25x_ep *ep = &dev->ep[i]; ep->stopped = 1; nuke(ep, -ESHUTDOWN); @@ -1327,7 +1332,7 @@ stop_activity(struct pxa2xx_udc *dev, struct usb_gadget_driver *driver) int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) { - struct pxa2xx_udc *dev = the_controller; + struct pxa25x_udc *dev = the_controller; if (!dev) return -ENODEV; @@ -1364,7 +1369,7 @@ EXPORT_SYMBOL(usb_gadget_unregister_driver); static irqreturn_t lubbock_vbus_irq(int irq, void *_dev) { - struct pxa2xx_udc *dev = _dev; + struct pxa25x_udc *dev = _dev; int vbus; dev->stats.irqs++; @@ -1383,7 +1388,7 @@ lubbock_vbus_irq(int irq, void *_dev) return IRQ_NONE; } - pxa2xx_udc_vbus_session(&dev->gadget, vbus); + pxa25x_udc_vbus_session(&dev->gadget, vbus); return IRQ_HANDLED; } @@ -1391,20 +1396,20 @@ lubbock_vbus_irq(int irq, void *_dev) static irqreturn_t udc_vbus_irq(int irq, void *_dev) { - struct pxa2xx_udc *dev = _dev; + struct pxa25x_udc *dev = _dev; int vbus = gpio_get_value(dev->mach->gpio_vbus); if (dev->mach->gpio_vbus_inverted) vbus = !vbus; - pxa2xx_udc_vbus_session(&dev->gadget, vbus); + pxa25x_udc_vbus_session(&dev->gadget, vbus); return IRQ_HANDLED; } /*-------------------------------------------------------------------------*/ -static inline void clear_ep_state (struct pxa2xx_udc *dev) +static inline void clear_ep_state (struct pxa25x_udc *dev) { unsigned i; @@ -1417,7 +1422,7 @@ static inline void clear_ep_state (struct pxa2xx_udc *dev) static void udc_watchdog(unsigned long _dev) { - struct pxa2xx_udc *dev = (void *)_dev; + struct pxa25x_udc *dev = (void *)_dev; local_irq_disable(); if (dev->ep0state == EP0_STALL @@ -1430,11 +1435,11 @@ static void udc_watchdog(unsigned long _dev) local_irq_enable(); } -static void handle_ep0 (struct pxa2xx_udc *dev) +static void handle_ep0 (struct pxa25x_udc *dev) { u32 udccs0 = UDCCS0; - struct pxa2xx_ep *ep = &dev->ep [0]; - struct pxa2xx_request *req; + struct pxa25x_ep *ep = &dev->ep [0]; + struct pxa25x_request *req; union { struct usb_ctrlrequest r; u8 raw [8]; @@ -1444,7 +1449,7 @@ static void handle_ep0 (struct pxa2xx_udc *dev) if (list_empty(&ep->queue)) req = NULL; else - req = list_entry(ep->queue.next, struct pxa2xx_request, queue); + req = list_entry(ep->queue.next, struct pxa25x_request, queue); /* clear stall status */ if (udccs0 & UDCCS0_SST) { @@ -1654,9 +1659,9 @@ stall: USIR0 = USIR0_IR0; } -static void handle_ep(struct pxa2xx_ep *ep) +static void handle_ep(struct pxa25x_ep *ep) { - struct pxa2xx_request *req; + struct pxa25x_request *req; int is_in = ep->bEndpointAddress & USB_DIR_IN; int completed; u32 udccs, tmp; @@ -1665,7 +1670,7 @@ static void handle_ep(struct pxa2xx_ep *ep) completed = 0; if (likely (!list_empty(&ep->queue))) req = list_entry(ep->queue.next, - struct pxa2xx_request, queue); + struct pxa25x_request, queue); else req = NULL; @@ -1702,16 +1707,16 @@ static void handle_ep(struct pxa2xx_ep *ep) } /* - * pxa2xx_udc_irq - interrupt handler + * pxa25x_udc_irq - interrupt handler * * avoid delays in ep0 processing. the control handshaking isn't always * under software control (pxa250c0 and the pxa255 are better), and delays * could cause usb protocol errors. */ static irqreturn_t -pxa2xx_udc_irq(int irq, void *_dev) +pxa25x_udc_irq(int irq, void *_dev) { - struct pxa2xx_udc *dev = _dev; + struct pxa25x_udc *dev = _dev; int handled; dev->stats.irqs++; @@ -1820,9 +1825,9 @@ static void nop_release (struct device *dev) * doing it at run-time) to save code, eliminate fault paths, and * be more obviously correct. */ -static struct pxa2xx_udc memory = { +static struct pxa25x_udc memory = { .gadget = { - .ops = &pxa2xx_udc_ops, + .ops = &pxa25x_udc_ops, .ep0 = &memory.ep[0].ep, .name = driver_name, .dev = { @@ -1835,7 +1840,7 @@ static struct pxa2xx_udc memory = { .ep[0] = { .ep = { .name = ep0name, - .ops = &pxa2xx_ep_ops, + .ops = &pxa25x_ep_ops, .maxpacket = EP0_FIFO_SIZE, }, .dev = &memory, @@ -1847,7 +1852,7 @@ static struct pxa2xx_udc memory = { .ep[1] = { .ep = { .name = "ep1in-bulk", - .ops = &pxa2xx_ep_ops, + .ops = &pxa25x_ep_ops, .maxpacket = BULK_FIFO_SIZE, }, .dev = &memory, @@ -1860,7 +1865,7 @@ static struct pxa2xx_udc memory = { .ep[2] = { .ep = { .name = "ep2out-bulk", - .ops = &pxa2xx_ep_ops, + .ops = &pxa25x_ep_ops, .maxpacket = BULK_FIFO_SIZE, }, .dev = &memory, @@ -1871,11 +1876,11 @@ static struct pxa2xx_udc memory = { .reg_ubcr = &UBCR2, .reg_uddr = &UDDR2, }, -#ifndef CONFIG_USB_PXA2XX_SMALL +#ifndef CONFIG_USB_PXA25X_SMALL .ep[3] = { .ep = { .name = "ep3in-iso", - .ops = &pxa2xx_ep_ops, + .ops = &pxa25x_ep_ops, .maxpacket = ISO_FIFO_SIZE, }, .dev = &memory, @@ -1888,7 +1893,7 @@ static struct pxa2xx_udc memory = { .ep[4] = { .ep = { .name = "ep4out-iso", - .ops = &pxa2xx_ep_ops, + .ops = &pxa25x_ep_ops, .maxpacket = ISO_FIFO_SIZE, }, .dev = &memory, @@ -1902,7 +1907,7 @@ static struct pxa2xx_udc memory = { .ep[5] = { .ep = { .name = "ep5in-int", - .ops = &pxa2xx_ep_ops, + .ops = &pxa25x_ep_ops, .maxpacket = INT_FIFO_SIZE, }, .dev = &memory, @@ -1917,7 +1922,7 @@ static struct pxa2xx_udc memory = { .ep[6] = { .ep = { .name = "ep6in-bulk", - .ops = &pxa2xx_ep_ops, + .ops = &pxa25x_ep_ops, .maxpacket = BULK_FIFO_SIZE, }, .dev = &memory, @@ -1930,7 +1935,7 @@ static struct pxa2xx_udc memory = { .ep[7] = { .ep = { .name = "ep7out-bulk", - .ops = &pxa2xx_ep_ops, + .ops = &pxa25x_ep_ops, .maxpacket = BULK_FIFO_SIZE, }, .dev = &memory, @@ -1944,7 +1949,7 @@ static struct pxa2xx_udc memory = { .ep[8] = { .ep = { .name = "ep8in-iso", - .ops = &pxa2xx_ep_ops, + .ops = &pxa25x_ep_ops, .maxpacket = ISO_FIFO_SIZE, }, .dev = &memory, @@ -1957,7 +1962,7 @@ static struct pxa2xx_udc memory = { .ep[9] = { .ep = { .name = "ep9out-iso", - .ops = &pxa2xx_ep_ops, + .ops = &pxa25x_ep_ops, .maxpacket = ISO_FIFO_SIZE, }, .dev = &memory, @@ -1971,7 +1976,7 @@ static struct pxa2xx_udc memory = { .ep[10] = { .ep = { .name = "ep10in-int", - .ops = &pxa2xx_ep_ops, + .ops = &pxa25x_ep_ops, .maxpacket = INT_FIFO_SIZE, }, .dev = &memory, @@ -1986,7 +1991,7 @@ static struct pxa2xx_udc memory = { .ep[11] = { .ep = { .name = "ep11in-bulk", - .ops = &pxa2xx_ep_ops, + .ops = &pxa25x_ep_ops, .maxpacket = BULK_FIFO_SIZE, }, .dev = &memory, @@ -1999,7 +2004,7 @@ static struct pxa2xx_udc memory = { .ep[12] = { .ep = { .name = "ep12out-bulk", - .ops = &pxa2xx_ep_ops, + .ops = &pxa25x_ep_ops, .maxpacket = BULK_FIFO_SIZE, }, .dev = &memory, @@ -2013,7 +2018,7 @@ static struct pxa2xx_udc memory = { .ep[13] = { .ep = { .name = "ep13in-iso", - .ops = &pxa2xx_ep_ops, + .ops = &pxa25x_ep_ops, .maxpacket = ISO_FIFO_SIZE, }, .dev = &memory, @@ -2026,7 +2031,7 @@ static struct pxa2xx_udc memory = { .ep[14] = { .ep = { .name = "ep14out-iso", - .ops = &pxa2xx_ep_ops, + .ops = &pxa25x_ep_ops, .maxpacket = ISO_FIFO_SIZE, }, .dev = &memory, @@ -2040,7 +2045,7 @@ static struct pxa2xx_udc memory = { .ep[15] = { .ep = { .name = "ep15in-int", - .ops = &pxa2xx_ep_ops, + .ops = &pxa25x_ep_ops, .maxpacket = INT_FIFO_SIZE, }, .dev = &memory, @@ -2050,7 +2055,7 @@ static struct pxa2xx_udc memory = { .reg_udccs = &UDCCS15, .reg_uddr = &UDDR15, }, -#endif /* !CONFIG_USB_PXA2XX_SMALL */ +#endif /* !CONFIG_USB_PXA25X_SMALL */ }; #define CP15R0_VENDOR_MASK 0xffffe000 @@ -2090,9 +2095,9 @@ static struct pxa2xx_udc memory = { /* * probe - binds to the platform device */ -static int __init pxa2xx_udc_probe(struct platform_device *pdev) +static int __init pxa25x_udc_probe(struct platform_device *pdev) { - struct pxa2xx_udc *dev = &memory; + struct pxa25x_udc *dev = &memory; int retval, vbus_irq, irq; u32 chiprev; @@ -2155,7 +2160,7 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev) if (dev->mach->gpio_vbus) { if ((retval = gpio_request(dev->mach->gpio_vbus, - "pxa2xx_udc GPIO VBUS"))) { + "pxa25x_udc GPIO VBUS"))) { dev_dbg(&pdev->dev, "can't get vbus gpio %d, err: %d\n", dev->mach->gpio_vbus, retval); @@ -2168,7 +2173,7 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev) if (dev->mach->gpio_pullup) { if ((retval = gpio_request(dev->mach->gpio_pullup, - "pca2xx_udc GPIO PULLUP"))) { + "pca25x_udc GPIO PULLUP"))) { dev_dbg(&pdev->dev, "can't get pullup gpio %d, err: %d\n", dev->mach->gpio_pullup, retval); @@ -2194,7 +2199,7 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev) dev->vbus = is_vbus_present(); /* irq setup after old hardware state is cleaned up */ - retval = request_irq(irq, pxa2xx_udc_irq, + retval = request_irq(irq, pxa25x_udc_irq, IRQF_DISABLED, driver_name, dev); if (retval != 0) { pr_err("%s: can't get irq %d, err %d\n", @@ -2260,14 +2265,14 @@ lubbock_fail0: return retval; } -static void pxa2xx_udc_shutdown(struct platform_device *_dev) +static void pxa25x_udc_shutdown(struct platform_device *_dev) { pullup_off(); } -static int __exit pxa2xx_udc_remove(struct platform_device *pdev) +static int __exit pxa25x_udc_remove(struct platform_device *pdev) { - struct pxa2xx_udc *dev = platform_get_drvdata(pdev); + struct pxa25x_udc *dev = platform_get_drvdata(pdev); if (dev->driver) return -EBUSY; @@ -2317,9 +2322,9 @@ static int __exit pxa2xx_udc_remove(struct platform_device *pdev) * VBUS IRQs should probably be ignored so that the PXA device just acts * "dead" to USB hosts until system resume. */ -static int pxa2xx_udc_suspend(struct platform_device *dev, pm_message_t state) +static int pxa25x_udc_suspend(struct platform_device *dev, pm_message_t state) { - struct pxa2xx_udc *udc = platform_get_drvdata(dev); + struct pxa25x_udc *udc = platform_get_drvdata(dev); unsigned long flags; if (!udc->mach->gpio_pullup && !udc->mach->udc_command) @@ -2333,9 +2338,9 @@ static int pxa2xx_udc_suspend(struct platform_device *dev, pm_message_t state) return 0; } -static int pxa2xx_udc_resume(struct platform_device *dev) +static int pxa25x_udc_resume(struct platform_device *dev) { - struct pxa2xx_udc *udc = platform_get_drvdata(dev); + struct pxa25x_udc *udc = platform_get_drvdata(dev); unsigned long flags; udc->suspended = 0; @@ -2347,27 +2352,27 @@ static int pxa2xx_udc_resume(struct platform_device *dev) } #else -#define pxa2xx_udc_suspend NULL -#define pxa2xx_udc_resume NULL +#define pxa25x_udc_suspend NULL +#define pxa25x_udc_resume NULL #endif /*-------------------------------------------------------------------------*/ static struct platform_driver udc_driver = { - .shutdown = pxa2xx_udc_shutdown, - .remove = __exit_p(pxa2xx_udc_remove), - .suspend = pxa2xx_udc_suspend, - .resume = pxa2xx_udc_resume, + .shutdown = pxa25x_udc_shutdown, + .remove = __exit_p(pxa25x_udc_remove), + .suspend = pxa25x_udc_suspend, + .resume = pxa25x_udc_resume, .driver = { .owner = THIS_MODULE, - .name = "pxa2xx-udc", + .name = "pxa25x-udc", }, }; static int __init udc_init(void) { pr_info("%s: version %s\n", driver_name, DRIVER_VERSION); - return platform_driver_probe(&udc_driver, pxa2xx_udc_probe); + return platform_driver_probe(&udc_driver, pxa25x_udc_probe); } module_init(udc_init); @@ -2380,4 +2385,4 @@ module_exit(udc_exit); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_AUTHOR("Frank Becker, Robert Schwebel, David Brownell"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:pxa2xx-udc"); +MODULE_ALIAS("platform:pxa25x-udc"); diff --git a/drivers/usb/gadget/pxa2xx_udc.h b/drivers/usb/gadget/pxa25x_udc.h index e2c19e88c87..4d11ece7c95 100644 --- a/drivers/usb/gadget/pxa2xx_udc.h +++ b/drivers/usb/gadget/pxa25x_udc.h @@ -1,6 +1,5 @@ /* - * linux/drivers/usb/gadget/pxa2xx_udc.h - * Intel PXA2xx on-chip full speed USB device controller + * Intel PXA25x on-chip full speed USB device controller * * Copyright (C) 2003 Robert Schwebel <r.schwebel@pengutronix.de>, Pengutronix * Copyright (C) 2003 David Brownell @@ -21,14 +20,14 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef __LINUX_USB_GADGET_PXA2XX_H -#define __LINUX_USB_GADGET_PXA2XX_H +#ifndef __LINUX_USB_GADGET_PXA25X_H +#define __LINUX_USB_GADGET_PXA25X_H #include <linux/types.h> /*-------------------------------------------------------------------------*/ -/* pxa2xx has this (move to include/asm-arm/arch-pxa/pxa-regs.h) */ +/* pxa25x has this (move to include/asm-arm/arch-pxa/pxa-regs.h) */ #define UFNRH_SIR (1 << 7) /* SOF interrupt request */ #define UFNRH_SIM (1 << 6) /* SOF interrupt mask */ #define UFNRH_IPE14 (1 << 5) /* ISO packet error, ep14 */ @@ -45,11 +44,11 @@ /*-------------------------------------------------------------------------*/ -struct pxa2xx_udc; +struct pxa25x_udc; -struct pxa2xx_ep { +struct pxa25x_ep { struct usb_ep ep; - struct pxa2xx_udc *dev; + struct pxa25x_udc *dev; const struct usb_endpoint_descriptor *desc; struct list_head queue; @@ -72,7 +71,7 @@ struct pxa2xx_ep { volatile u32 *reg_uddr; }; -struct pxa2xx_request { +struct pxa25x_request { struct usb_request req; struct list_head queue; }; @@ -98,7 +97,7 @@ struct udc_stats { unsigned long irqs; }; -#ifdef CONFIG_USB_PXA2XX_SMALL +#ifdef CONFIG_USB_PXA25X_SMALL /* when memory's tight, SMALL config saves code+data. */ #define PXA_UDC_NUM_ENDPOINTS 3 #endif @@ -107,7 +106,7 @@ struct udc_stats { #define PXA_UDC_NUM_ENDPOINTS 16 #endif -struct pxa2xx_udc { +struct pxa25x_udc { struct usb_gadget gadget; struct usb_gadget_driver *driver; @@ -130,7 +129,7 @@ struct pxa2xx_udc { struct clk *clk; struct pxa2xx_udc_mach_info *mach; u64 dma_mask; - struct pxa2xx_ep ep [PXA_UDC_NUM_ENDPOINTS]; + struct pxa25x_ep ep [PXA_UDC_NUM_ENDPOINTS]; #ifdef CONFIG_USB_GADGET_DEBUG_FS struct dentry *debugfs_udc; @@ -144,7 +143,7 @@ struct pxa2xx_udc { /* lubbock can also report usb connect/disconnect irqs */ #endif -static struct pxa2xx_udc *the_controller; +static struct pxa25x_udc *the_controller; /*-------------------------------------------------------------------------*/ @@ -209,7 +208,7 @@ dump_udccs0(const char *label) } static void __maybe_unused -dump_state(struct pxa2xx_udc *dev) +dump_state(struct pxa25x_udc *dev) { u32 tmp; unsigned i; @@ -264,4 +263,4 @@ dump_state(struct pxa2xx_udc *dev) #define INFO(stuff...) pr_info("udc: " stuff) -#endif /* __LINUX_USB_GADGET_PXA2XX_H */ +#endif /* __LINUX_USB_GADGET_PXA25X_H */ diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c index e02bfd4df3a..9c0e82ec5c4 100644 --- a/drivers/usb/gadget/pxa27x_udc.c +++ b/drivers/usb/gadget/pxa27x_udc.c @@ -38,7 +38,7 @@ #include <linux/usb.h> #include <linux/usb/ch9.h> #include <linux/usb/gadget.h> - +#include <asm/arch/pxa2xx-regs.h> /* FIXME: for PSSR */ #include <asm/arch/udc.h> #include "pxa27x_udc.h" @@ -2360,18 +2360,19 @@ static int pxa_udc_resume(struct platform_device *_dev) * Software must configure the USB OTG pad, UDC, and UHC * to the state they were in before entering sleep mode. */ - PSSR |= PSSR_OTGPH; + if (cpu_is_pxa27x()) + PSSR |= PSSR_OTGPH; return 0; } #endif /* work with hotplug and coldplug */ -MODULE_ALIAS("platform:pxa2xx-udc"); +MODULE_ALIAS("platform:pxa27x-udc"); static struct platform_driver udc_driver = { .driver = { - .name = "pxa2xx-udc", + .name = "pxa27x-udc", .owner = THIS_MODULE, }, .remove = __exit_p(pxa_udc_remove), diff --git a/drivers/usb/gadget/pxa27x_udc.h b/drivers/usb/gadget/pxa27x_udc.h index 97453db924f..1d1b7936ee1 100644 --- a/drivers/usb/gadget/pxa27x_udc.h +++ b/drivers/usb/gadget/pxa27x_udc.h @@ -484,12 +484,4 @@ static inline struct pxa_udc *to_gadget_udc(struct usb_gadget *gadget) #define ep_warn(ep, fmt, arg...) \ dev_warn(ep->dev->dev, "%s:%s:" fmt, EPNAME(ep), __func__, ## arg) -/* - * Cannot include pxa-regs.h, as register names are similar. - * So PSSR is redefined here. This should be removed once UDC registers will - * be gone from pxa-regs.h. - */ -#define PSSR __REG(0x40F00004) /* Power Manager Sleep Status */ -#define PSSR_OTGPH (1 << 6) /* OTG Peripheral Hold */ - #endif /* __LINUX_USB_GADGET_PXA27X_H */ diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c index 3a7c24c0367..a19a4f80a6e 100644 --- a/drivers/usb/host/ohci-omap.c +++ b/drivers/usb/host/ohci-omap.c @@ -169,13 +169,16 @@ static void start_hnp(struct ohci_hcd *ohci) { const unsigned port = ohci_to_hcd(ohci)->self.otg_port - 1; unsigned long flags; + u32 l; otg_start_hnp(ohci->transceiver); local_irq_save(flags); ohci->transceiver->state = OTG_STATE_A_SUSPEND; writel (RH_PS_PSS, &ohci->regs->roothub.portstatus [port]); - OTG_CTRL_REG &= ~OTG_A_BUSREQ; + l = omap_readl(OTG_CTRL); + l &= ~OTG_A_BUSREQ; + omap_writel(l, OTG_CTRL); local_irq_restore(flags); } diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c index d4ee27d92be..127b1579902 100644 --- a/drivers/usb/host/ohci-pxa27x.c +++ b/drivers/usb/host/ohci-pxa27x.c @@ -27,6 +27,7 @@ #include <asm/mach-types.h> #include <asm/hardware.h> #include <asm/arch/pxa-regs.h> +#include <asm/arch/pxa2xx-regs.h> /* FIXME: for PSSR */ #include <asm/arch/ohci.h> #define PXA_UHC_MAX_PORTNUM 3 @@ -104,7 +105,7 @@ static int pxa27x_start_hc(struct device *dev) UHCHIE = (UHCHIE_UPRIE | UHCHIE_RWIE); /* Clear any OTG Pin Hold */ - if (PSSR & PSSR_OTGPH) + if (cpu_is_pxa27x() && (PSSR & PSSR_OTGPH)) PSSR |= PSSR_OTGPH; return 0; diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index dcd8073c236..30bf7f2f163 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig @@ -112,3 +112,10 @@ config BACKLIGHT_CARILLO_RANCH help If you have a Intel LE80578 (Carillo Ranch) say Y to enable the backlight driver. + +config BACKLIGHT_PWM + tristate "Generic PWM based Backlight Driver" + depends on BACKLIGHT_CLASS_DEVICE && HAVE_PWM + help + If you have a LCD backlight adjustable by PWM, say Y to enable + this driver. diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile index 33f6c7cecc7..b51a7cd1250 100644 --- a/drivers/video/backlight/Makefile +++ b/drivers/video/backlight/Makefile @@ -10,3 +10,4 @@ obj-$(CONFIG_BACKLIGHT_LOCOMO) += locomolcd.o obj-$(CONFIG_BACKLIGHT_OMAP1) += omap1_bl.o obj-$(CONFIG_BACKLIGHT_PROGEAR) += progear_bl.o obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o +obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c new file mode 100644 index 00000000000..6338d0e2fe0 --- /dev/null +++ b/drivers/video/backlight/pwm_bl.c @@ -0,0 +1,185 @@ +/* + * linux/drivers/video/backlight/pwm_bl.c + * + * simple PWM based backlight control, board code has to setup + * 1) pin configuration so PWM waveforms can output + * 2) platform_data casts to the PWM id (0/1/2/3 on PXA) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/fb.h> +#include <linux/backlight.h> +#include <linux/err.h> +#include <linux/pwm.h> +#include <linux/pwm_backlight.h> + +struct pwm_bl_data { + struct pwm_device *pwm; + unsigned int period; + int (*notify)(int brightness); +}; + +static int pwm_backlight_update_status(struct backlight_device *bl) +{ + struct pwm_bl_data *pb = dev_get_drvdata(&bl->dev); + int brightness = bl->props.brightness; + int max = bl->props.max_brightness; + + if (bl->props.power != FB_BLANK_UNBLANK) + brightness = 0; + + if (bl->props.fb_blank != FB_BLANK_UNBLANK) + brightness = 0; + + if (pb->notify) + brightness = pb->notify(brightness); + + if (brightness == 0) { + pwm_config(pb->pwm, 0, pb->period); + pwm_disable(pb->pwm); + } else { + pwm_config(pb->pwm, brightness * pb->period / max, pb->period); + pwm_enable(pb->pwm); + } + return 0; +} + +static int pwm_backlight_get_brightness(struct backlight_device *bl) +{ + return bl->props.brightness; +} + +static struct backlight_ops pwm_backlight_ops = { + .update_status = pwm_backlight_update_status, + .get_brightness = pwm_backlight_get_brightness, +}; + +static int pwm_backlight_probe(struct platform_device *pdev) +{ + struct platform_pwm_backlight_data *data = pdev->dev.platform_data; + struct backlight_device *bl; + struct pwm_bl_data *pb; + int ret; + + if (!data) + return -EINVAL; + + if (data->init) { + ret = data->init(&pdev->dev); + if (ret < 0) + return ret; + } + + pb = kzalloc(sizeof(*pb), GFP_KERNEL); + if (!pb) { + ret = -ENOMEM; + goto err_alloc; + } + + pb->period = data->pwm_period_ns; + pb->notify = data->notify; + + pb->pwm = pwm_request(data->pwm_id, "backlight"); + if (IS_ERR(pb->pwm)) { + dev_err(&pdev->dev, "unable to request PWM for backlight\n"); + ret = PTR_ERR(pb->pwm); + goto err_pwm; + } + + bl = backlight_device_register(pdev->name, &pdev->dev, + pb, &pwm_backlight_ops); + if (IS_ERR(bl)) { + dev_err(&pdev->dev, "failed to register backlight\n"); + ret = PTR_ERR(bl); + goto err_bl; + } + + bl->props.max_brightness = data->max_brightness; + bl->props.brightness = data->dft_brightness; + backlight_update_status(bl); + + platform_set_drvdata(pdev, bl); + return 0; + +err_bl: + pwm_free(pb->pwm); +err_pwm: + kfree(pb); +err_alloc: + if (data->exit) + data->exit(&pdev->dev); + return ret; +} + +static int pwm_backlight_remove(struct platform_device *pdev) +{ + struct platform_pwm_backlight_data *data = pdev->dev.platform_data; + struct backlight_device *bl = platform_get_drvdata(pdev); + struct pwm_bl_data *pb = dev_get_drvdata(&bl->dev); + + backlight_device_unregister(bl); + pwm_config(pb->pwm, 0, pb->period); + pwm_disable(pb->pwm); + pwm_free(pb->pwm); + kfree(pb); + if (data->exit) + data->exit(&pdev->dev); + return 0; +} + +#ifdef CONFIG_PM +static int pwm_backlight_suspend(struct platform_device *pdev, + pm_message_t state) +{ + struct backlight_device *bl = platform_get_drvdata(pdev); + struct pwm_bl_data *pb = dev_get_drvdata(&bl->dev); + + pwm_config(pb->pwm, 0, pb->period); + pwm_disable(pb->pwm); + return 0; +} + +static int pwm_backlight_resume(struct platform_device *pdev) +{ + struct backlight_device *bl = platform_get_drvdata(pdev); + + backlight_update_status(bl); + return 0; +} +#else +#define pwm_backlight_suspend NULL +#define pwm_backlight_resume NULL +#endif + +static struct platform_driver pwm_backlight_driver = { + .driver = { + .name = "pwm-backlight", + .owner = THIS_MODULE, + }, + .probe = pwm_backlight_probe, + .remove = pwm_backlight_remove, + .suspend = pwm_backlight_suspend, + .resume = pwm_backlight_resume, +}; + +static int __init pwm_backlight_init(void) +{ + return platform_driver_register(&pwm_backlight_driver); +} +module_init(pwm_backlight_init); + +static void __exit pwm_backlight_exit(void) +{ + platform_driver_unregister(&pwm_backlight_driver); +} +module_exit(pwm_backlight_exit); + +MODULE_DESCRIPTION("PWM based Backlight Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c index fafe7db20d6..d0746261c95 100644 --- a/drivers/video/pxafb.c +++ b/drivers/video/pxafb.c @@ -1792,11 +1792,49 @@ failed: return ret; } +static int __devexit pxafb_remove(struct platform_device *dev) +{ + struct pxafb_info *fbi = platform_get_drvdata(dev); + struct resource *r; + int irq; + struct fb_info *info; + + if (!fbi) + return 0; + + info = &fbi->fb; + + unregister_framebuffer(info); + + pxafb_disable_controller(fbi); + + if (fbi->fb.cmap.len) + fb_dealloc_cmap(&fbi->fb.cmap); + + irq = platform_get_irq(dev, 0); + free_irq(irq, fbi); + + dma_free_writecombine(&dev->dev, fbi->map_size, + fbi->map_cpu, fbi->map_dma); + + iounmap(fbi->mmio_base); + + r = platform_get_resource(dev, IORESOURCE_MEM, 0); + release_mem_region(r->start, r->end - r->start + 1); + + clk_put(fbi->clk); + kfree(fbi); + + return 0; +} + static struct platform_driver pxafb_driver = { .probe = pxafb_probe, + .remove = pxafb_remove, .suspend = pxafb_suspend, .resume = pxafb_resume, .driver = { + .owner = THIS_MODULE, .name = "pxa2xx-fb", }, }; @@ -1809,7 +1847,13 @@ static int __init pxafb_init(void) return platform_driver_register(&pxafb_driver); } +static void __exit pxafb_exit(void) +{ + platform_driver_unregister(&pxafb_driver); +} + module_init(pxafb_init); +module_exit(pxafb_exit); MODULE_DESCRIPTION("loadable framebuffer driver for PXA"); MODULE_LICENSE("GPL"); |