diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/acorn/char |
Linux-2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/acorn/char')
-rw-r--r-- | drivers/acorn/char/Makefile | 6 | ||||
-rw-r--r-- | drivers/acorn/char/defkeymap-l7200.c | 386 | ||||
-rw-r--r-- | drivers/acorn/char/i2c.c | 369 | ||||
-rw-r--r-- | drivers/acorn/char/pcf8583.c | 239 | ||||
-rw-r--r-- | drivers/acorn/char/pcf8583.h | 41 |
5 files changed, 1041 insertions, 0 deletions
diff --git a/drivers/acorn/char/Makefile b/drivers/acorn/char/Makefile new file mode 100644 index 00000000000..2fa9a8bf48a --- /dev/null +++ b/drivers/acorn/char/Makefile | |||
@@ -0,0 +1,6 @@ | |||
1 | # | ||
2 | # Makefile for the acorn character device drivers. | ||
3 | # | ||
4 | |||
5 | obj-$(CONFIG_ARCH_ACORN) += i2c.o pcf8583.o | ||
6 | 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 new file mode 100644 index 00000000000..9e18ce742e3 --- /dev/null +++ b/drivers/acorn/char/defkeymap-l7200.c | |||
@@ -0,0 +1,386 @@ | |||
1 | /* | ||
2 | * linux/drivers/acorn/char/defkeymap-l7200.c | ||
3 | * | ||
4 | * Default keyboard maps for LinkUp Systems L7200 board | ||
5 | * | ||
6 | * Copyright (C) 2000 Steve Hill (sjhill@cotw.com) | ||
7 | * | ||
8 | * Changelog: | ||
9 | * 08-04-2000 SJH Created file | ||
10 | */ | ||
11 | |||
12 | #include <linux/types.h> | ||
13 | #include <linux/keyboard.h> | ||
14 | #include <linux/kd.h> | ||
15 | |||
16 | /* Normal (maps 1:1 with no processing) */ | ||
17 | #define KTn 0xF0 | ||
18 | /* Function keys */ | ||
19 | #define KTf 0xF1 | ||
20 | /* Special (Performs special house-keeping funcs) */ | ||
21 | #define KTs 0xF2 | ||
22 | #define KIGNORE K(KTs, 0) /* Ignore */ | ||
23 | #define KENTER K(KTs, 1) /* Enter */ | ||
24 | #define KREGS K(KTs, 2) /* Regs */ | ||
25 | #define KMEM K(KTs, 3) /* Mem */ | ||
26 | #define KSTAT K(KTs, 4) /* State */ | ||
27 | #define KINTR K(KTs, 5) /* Intr */ | ||
28 | #define Ksl 6 /* Last console */ | ||
29 | #define KCAPSLK K(KTs, 7) /* Caps lock */ | ||
30 | #define KNUMLK K(KTs, 8) /* Num-lock */ | ||
31 | #define KSCRLLK K(KTs, 9) /* Scroll-lock */ | ||
32 | #define KSCRLFOR K(KTs,10) /* Scroll forward */ | ||
33 | #define KSCRLBAK K(KTs,11) /* Scroll back */ | ||
34 | #define KREBOOT K(KTs,12) /* Reboot */ | ||
35 | #define KCAPSON K(KTs,13) /* Caps on */ | ||
36 | #define KCOMPOSE K(KTs,14) /* Compose */ | ||
37 | #define KSAK K(KTs,15) /* SAK */ | ||
38 | #define CONS_DEC K(KTs,16) /* Dec console */ | ||
39 | #define CONS_INC K(KTs,17) /* Incr console */ | ||
40 | #define KFLOPPY K(KTs,18) /* Floppy */ | ||
41 | /* Key pad (0-9 = digits, 10=+, 11=-, 12=*, 13=/, 14=enter, 16=., 17=# */ | ||
42 | #define KTp 0xF3 | ||
43 | #define KPAD_0 K(KTp, 0 ) | ||
44 | #define KPAD_1 K(KTp, 1 ) | ||
45 | #define KPAD_2 K(KTp, 2 ) | ||
46 | #define KPAD_3 K(KTp, 3 ) | ||
47 | #define KPAD_4 K(KTp, 4 ) | ||
48 | #define KPAD_5 K(KTp, 5 ) | ||
49 | #define KPAD_6 K(KTp, 6 ) | ||
50 | #define KPAD_7 K(KTp, 7 ) | ||
51 | #define KPAD_8 K(KTp, 8 ) | ||
52 | #define KPAD_9 K(KTp, 9 ) | ||
53 | #define KPAD_PL K(KTp,10 ) | ||
54 | #define KPAD_MI K(KTp,11 ) | ||
55 | #define KPAD_ML K(KTp,12 ) | ||
56 | #define KPAD_DV K(KTp,13 ) | ||
57 | #define KPAD_EN K(KTp,14 ) | ||
58 | #define KPAD_DT K(KTp,16 ) | ||
59 | #define KPAD_HS K(KTp,20 ) | ||
60 | /* Console switching */ | ||
61 | #define KCn 0xF5 | ||
62 | /* Cursor */ | ||
63 | #define KTc 0xF6 | ||
64 | #define Kcd 0 /* Cursor down */ | ||
65 | #define Kcl 1 /* Cursor left */ | ||
66 | #define Kcr 2 /* Cursor right */ | ||
67 | #define Kcu 3 /* Cursor up */ | ||
68 | /* Shift/alt modifiers etc */ | ||
69 | #define KMd 0xF7 | ||
70 | #define KSHIFT K(KMd, 0 ) | ||
71 | #define KALTGR K(KMd, 1 ) | ||
72 | #define KCTRL K(KMd, 2 ) | ||
73 | #define KALT K(KMd, 3 ) | ||
74 | /* Meta */ | ||
75 | #define KMt 0xF8 | ||
76 | #define KAs 0xF9 | ||
77 | #define KPADA_0 K(KAs, 0 ) | ||
78 | #define KPADA_1 K(KAs, 1 ) | ||
79 | #define KPADA_2 K(KAs, 2 ) | ||
80 | #define KPADA_3 K(KAs, 3 ) | ||
81 | #define KPADA_4 K(KAs, 4 ) | ||
82 | #define KPADA_5 K(KAs, 5 ) | ||
83 | #define KPADA_6 K(KAs, 6 ) | ||
84 | #define KPADA_7 K(KAs, 7 ) | ||
85 | #define KPADA_8 K(KAs, 8 ) | ||
86 | #define KPADA_9 K(KAs, 9 ) | ||
87 | #define KPADB_0 K(KAs,10 ) | ||
88 | #define KPADB_1 K(KAs,11 ) | ||
89 | #define KPADB_2 K(KAs,12 ) | ||
90 | #define KPADB_3 K(KAs,13 ) | ||
91 | #define KPADB_4 K(KAs,14 ) | ||
92 | #define KPADB_5 K(KAs,15 ) | ||
93 | #define KPADB_6 K(KAs,16 ) | ||
94 | #define KPADB_7 K(KAs,17 ) | ||
95 | #define KPADB_8 K(KAs,18 ) | ||
96 | #define KPADB_9 K(KAs,19 ) | ||
97 | /* Locking keys */ | ||
98 | #define KLk 0xFA | ||
99 | /* Letters */ | ||
100 | #define KTl 0xFB | ||
101 | |||
102 | /* | ||
103 | * Here is the layout of the keys for the Fujitsu QWERTY | ||
104 | * style keyboard: | ||
105 | * | ||
106 | * static char Fujitsu_Key_Table[] = | ||
107 | * { | ||
108 | * KALT, '`' , KNUL, KCTL, KFUN, KESC, '1' , '2' , | ||
109 | * '9' , '0' , '-' , '=' , KNUL, KBSP, KNUL, KNUL, | ||
110 | * KNUL, KBSL, KSHF, KNUL, KNUL, KDEL, KNUL, 't' , | ||
111 | * 'y' , 'u' , 'i' , KRET, KSHF, KPGD, KNUL, KNUL, | ||
112 | * KNUL, KTAB, KNUL, KNUL, KNUL, 'q' , 'w' , 'e' , | ||
113 | * 'r' , 'o' , 'p' , '[' , KNUL, ']' , KNUL, KNUL, | ||
114 | * KNUL, 'z' , KNUL, KNUL, KNUL, KSHL, KNUL, KNUL, | ||
115 | * 'k' , 'l' , ';' , KSQT, KNUL, KPGU, KNUL, KNUL, | ||
116 | * KNUL, 'a' , KNUL, KNUL, KNUL, 's' , 'd' , 'f' , | ||
117 | * 'g' , 'h' , 'j' , '/' , KNUL, KHME, KNUL, KNUL, | ||
118 | * KNUL, 'x' , KNUL, KNUL, KNUL, 'c' , 'v' , 'b' , | ||
119 | * 'n' , 'm' , ',' , '.' , KNUL, ' ' , KNUL, KNUL, | ||
120 | * KNUL, KNUL, KNUL, KNUL, KNUL, '3' , '4' , '5' , | ||
121 | * '6' , '7' , '8' , KNUL, KPRG, KNUL, KEND, KNUL, | ||
122 | * }; | ||
123 | */ | ||
124 | |||
125 | u_short plain_map[NR_KEYS]= | ||
126 | { | ||
127 | 0xf703, 0xf060, 0xf200, 0xf702, 0xf200, 0xf01b, 0xf031, 0xf032, | ||
128 | 0xf039, 0xf030, 0xf02d, 0xf03d, 0xf200, 0xf07f, 0xf200, 0xf200, | ||
129 | 0xf200, 0xf05c, 0xf700, 0xf200, 0xf200, 0xf116, 0xf000, 0xfb74, | ||
130 | 0xfb79, 0xfb75, 0xfb69, 0xf201, 0xf700, 0xf600, 0xf200, 0xf200, | ||
131 | 0xf200, 0xf009, 0xf200, 0xf200, 0xf200, 0xfb71, 0xfb77, 0xfb65, | ||
132 | 0xfb72, 0xfb6f, 0xfb70, 0xf05b, 0xf200, 0xf05d, 0xf200, 0xf200, | ||
133 | 0xf200, 0xfb7a, 0xf200, 0xf200, 0xf200, 0xf207, 0xf200, 0xf200, | ||
134 | 0xfb6b, 0xfb6c, 0xf03b, 0xf027, 0xf200, 0xf603, 0xf200, 0xf200, | ||
135 | 0xf200, 0xfb61, 0xf200, 0xf200, 0xf200, 0xfb73, 0xfb64, 0xfb66, | ||
136 | 0xfb67, 0xfb68, 0xfb6a, 0xf02f, 0xf200, 0xf601, 0xf200, 0xf200, | ||
137 | 0xf200, 0xfb78, 0xf200, 0xf200, 0xf200, 0xfb63, 0xfb76, 0xfb62, | ||
138 | 0xfb6e, 0xfb6d, 0xf02c, 0xf02e, 0xf200, 0xf020, 0xf200, 0xf200, | ||
139 | 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf033, 0xf034, 0xf035, | ||
140 | 0xf036, 0xf037, 0xf038, 0xf200, 0xf200, 0xf200, 0xf602, 0xf200, | ||
141 | 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, | ||
142 | 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, | ||
143 | }; | ||
144 | |||
145 | u_short shift_map[NR_KEYS]= | ||
146 | { | ||
147 | 0xf703, 0xf07e, 0xf200, 0xf702, 0xf200, 0xf01b, 0xf021, 0xf040, | ||
148 | 0xf028, 0xf029, 0xf05f, 0xf02b, 0xf200, 0xf07f, 0xf200, 0xf200, | ||
149 | 0xf200, 0xf07c, 0xf700, 0xf200, 0xf200, 0xf116, 0xf000, 0xfb54, | ||
150 | 0xfb59, 0xfb55, 0xfb49, 0xf201, 0xf700, 0xf600, 0xf200, 0xf200, | ||
151 | 0xf200, 0xf009, 0xf200, 0xf200, 0xf200, 0xfb51, 0xfb57, 0xfb45, | ||
152 | 0xfb52, 0xfb4f, 0xfb50, 0xf07b, 0xf200, 0xf07d, 0xf200, 0xf200, | ||
153 | 0xf200, 0xfb5a, 0xf200, 0xf200, 0xf200, 0xf207, 0xf200, 0xf200, | ||
154 | 0xfb4b, 0xfb4c, 0xf03a, 0xf022, 0xf200, 0xf603, 0xf200, 0xf200, | ||
155 | 0xf200, 0xfb41, 0xf200, 0xf200, 0xf200, 0xfb53, 0xfb44, 0xfb46, | ||
156 | 0xfb47, 0xfb48, 0xfb4a, 0xf03f, 0xf200, 0xf601, 0xf200, 0xf200, | ||
157 | 0xf200, 0xfb58, 0xf200, 0xf200, 0xf200, 0xfb43, 0xfb56, 0xfb42, | ||
158 | 0xfb4e, 0xfb4d, 0xf03c, 0xf03e, 0xf200, 0xf020, 0xf200, 0xf200, | ||
159 | 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf023, 0xf024, 0xf025, | ||
160 | 0xf05e, 0xf026, 0xf02a, 0xf200, 0xf200, 0xf200, 0xf602, 0xf200, | ||
161 | 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, | ||
162 | 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, | ||
163 | }; | ||
164 | |||
165 | u_short altgr_map[NR_KEYS]= | ||
166 | { | ||
167 | KIGNORE ,K(KCn,12 ),K(KCn,13 ),K(KCn,14 ),K(KCn,15 ),K(KCn,16 ),K(KCn,17 ),K(KCn, 18), | ||
168 | K(KCn, 19),K(KCn,20 ),K(KCn,21 ),K(KCn,22 ),K(KCn,23 ),KIGNORE ,KREGS ,KINTR , | ||
169 | KIGNORE ,KIGNORE ,K(KTn,'@'),KIGNORE ,K(KTn,'$'),KIGNORE ,KIGNORE ,K(KTn,'{'), | ||
170 | K(KTn,'['),K(KTn,']'),K(KTn,'}'),K(KTn,'\\'),KIGNORE ,KIGNORE ,KIGNORE ,K(KTf,21 ), | ||
171 | K(KTf,20 ),K(KTf,24 ),KNUMLK ,KPAD_DV ,KPAD_ML ,KPAD_HS ,KIGNORE ,K(KTl,'q'), | ||
172 | K(KTl,'w'),K(KTl,'e'),K(KTl,'r'),K(KTl,'t' ),K(KTl,'y'),K(KTl,'u'),K(KTl,'i' ),K(KTl,'o'), | ||
173 | K(KTl,'p'),KIGNORE ,K(KTn,'~'),KIGNORE ,K(KTf,22 ),K(KTf,23 ),K(KTf,25 ),KPADB_7 , | ||
174 | KPADB_8 ,KPADB_9 ,KPAD_MI ,KCTRL ,K(KAs,20 ),K(KTl,'s'),K(KAs,23 ),K(KAs,25 ), | ||
175 | K(KTl,'g'),K(KTl,'h'),K(KTl,'j'),K(KTl,'k' ),K(KTl,'l'),KIGNORE ,KIGNORE ,KENTER , | ||
176 | KPADB_4 ,KPADB_5 ,KPADB_6 ,KPAD_PL ,KSHIFT ,KIGNORE ,K(KTl,'z' ),K(KTl,'x'), | ||
177 | K(KAs,22 ),K(KTl,'v'),K(KTl,21 ),K(KTl,'n' ),K(KTl,'m'),KIGNORE ,KIGNORE ,KIGNORE , | ||
178 | KSHIFT ,K(KTc,Kcu),KPADB_1 ,KPADB_2 ,KPADB_3 ,KCAPSLK ,KALT ,KIGNORE , | ||
179 | KALTGR ,KCTRL ,K(KTc,Kcl),K(KTc,Kcd ),K(KTc,Kcr),KPADB_0 ,KPAD_DT ,KPAD_EN , | ||
180 | KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , | ||
181 | KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , | ||
182 | KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , | ||
183 | }; | ||
184 | |||
185 | u_short ctrl_map[NR_KEYS]= | ||
186 | { | ||
187 | 0xf703, 0xf200, 0xf200, 0xf702, 0xf200, 0xf200, 0xf001, 0xf002, | ||
188 | 0xf009, 0xf000, 0xf031, 0xf200, 0xf200, 0xf07f, 0xf200, 0xf200, | ||
189 | 0xf200, 0xf01c, 0xf700, 0xf200, 0xf200, 0xf116, 0xf000, 0xf020, | ||
190 | 0xf019, 0xf015, 0xf009, 0xf201, 0xf700, 0xf600, 0xf200, 0xf200, | ||
191 | 0xf200, 0xf009, 0xf200, 0xf200, 0xf200, 0xf011, 0xf017, 0xf005, | ||
192 | 0xf012, 0xf00f, 0xf010, 0xf01b, 0xf200, 0xf01d, 0xf200, 0xf200, | ||
193 | 0xf200, 0xf01a, 0xf200, 0xf200, 0xf200, 0xf207, 0xf200, 0xf200, | ||
194 | 0xf00b, 0xf00c, 0xf200, 0xf007, 0xf200, 0xf603, 0xf200, 0xf200, | ||
195 | 0xf200, 0xf001, 0xf200, 0xf200, 0xf200, 0xf001, 0xf013, 0xf006, | ||
196 | 0xf007, 0xf008, 0xf00a, 0xf07f, 0xf200, 0xf601, 0xf200, 0xf200, | ||
197 | 0xf200, 0xf018, 0xf200, 0xf200, 0xf200, 0xf003, 0xf016, 0xf002, | ||
198 | 0xf00e, 0xf00d, 0xf200, 0xf200, 0xf200, 0xf000, 0xf200, 0xf200, | ||
199 | 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf01b, 0xf01c, 0xf01d, | ||
200 | 0xf036, 0xf037, 0xf038, 0xf200, 0xf200, 0xf200, 0xf602, 0xf200, | ||
201 | 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, | ||
202 | 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf602, 0xf200, | ||
203 | }; | ||
204 | |||
205 | u_short shift_ctrl_map[NR_KEYS]= | ||
206 | { | ||
207 | KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , | ||
208 | KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KFLOPPY ,KINTR , | ||
209 | KIGNORE ,KIGNORE ,K(KTn, 0 ),KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , | ||
210 | KIGNORE ,KIGNORE ,KIGNORE ,K(KTn,31 ),KIGNORE ,KIGNORE ,KIGNORE ,K(KTf,21 ), | ||
211 | K(KTf,20 ),K(KTf,24 ),KNUMLK ,KPAD_DV ,KPAD_ML ,KPAD_HS ,KIGNORE ,K(KTn,17 ), | ||
212 | K(KTn,23 ),K(KTn, 5 ),K(KTn,18 ),K(KTn,20 ),K(KTn,25 ),K(KTn,21 ),K(KTn, 9 ),K(KTn,15 ), | ||
213 | K(KTn,16 ),KIGNORE ,KIGNORE ,KIGNORE ,K(KTf,22 ),K(KTf,23 ),K(KTf,25 ),KPAD_7 , | ||
214 | KPAD_8 ,KPAD_9 ,KPAD_MI ,KCTRL ,K(KTn, 1 ),K(KTn,19 ),K(KTn, 4 ),K(KTn, 6 ), | ||
215 | K(KTn, 7 ),K(KTn, 8 ),K(KTn,10 ),K(KTn,11 ),K(KTn,12 ),KIGNORE ,K(KTn, 7 ),KENTER , | ||
216 | KPAD_4 ,KPAD_5 ,KPAD_6 ,KPAD_PL ,KSHIFT ,KIGNORE ,K(KTn,26 ),K(KTn,24 ), | ||
217 | K(KTn, 3 ),K(KTn,22 ),K(KTn, 2 ),K(KTn,14 ),K(KTn,13 ),KIGNORE ,KIGNORE ,KIGNORE , | ||
218 | KSHIFT ,K(KTc,Kcu),KPAD_1 ,KPAD_2 ,KPAD_3 ,KCAPSLK ,KALT ,K(KTn, 0 ), | ||
219 | KALTGR ,KCTRL ,K(KTc,Kcl),K(KTc,Kcd ),K(KTc,Kcr),KPAD_0 ,KPAD_DT ,KPAD_EN , | ||
220 | KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , | ||
221 | KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , | ||
222 | KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , | ||
223 | }; | ||
224 | |||
225 | u_short alt_map[NR_KEYS]= | ||
226 | { | ||
227 | K(KMt,27 ),K(KCn, 0 ),K(KCn, 1 ),K(KCn, 2 ),K(KCn, 3 ),K(KCn, 4 ),K(KCn, 5 ),K(KCn, 6 ), | ||
228 | K(KCn, 7 ),K(KCn, 8 ),K(KCn, 9 ),K(KCn,10 ),K(KCn,11 ),KIGNORE ,KSCRLLK ,KINTR , | ||
229 | K(KMt,'`'),K(KMt,'1'),K(KMt,'2'),K(KMt,'3' ),K(KMt,'4'),K(KMt,'5'),K(KMt,'6' ),K(KMt,'7'), | ||
230 | K(KMt,'8'),K(KMt,'9'),K(KMt,'0'),K(KMt,'-' ),K(KMt,'='),K(KMt,'£'),K(KMt,127 ),K(KTf,21 ), | ||
231 | K(KTf,20 ),K(KTf,24 ),KNUMLK ,KPAD_DV ,KPAD_ML ,KPAD_HS ,K(KMt, 9 ),K(KMt,'q'), | ||
232 | K(KMt,'w'),K(KMt,'e'),K(KMt,'r'),K(KMt,'t' ),K(KMt,'y'),K(KMt,'u'),K(KMt,'i' ),K(KMt,'o'), | ||
233 | K(KMt,'p'),K(KMt,'['),K(KMt,']'),K(KMt,'\\'),K(KTf,22 ),K(KTf,23 ),K(KTf,25 ),KPADA_7 , | ||
234 | KPADA_8 ,KPADA_9 ,KPAD_MI ,KCTRL ,K(KMt,'a'),K(KMt,'s'),K(KMt,'d' ),K(KMt,'f'), | ||
235 | K(KMt,'g'),K(KMt,'h'),K(KMt,'j'),K(KMt,'k' ),K(KMt,'l'),K(KMt,';'),K(KMt,'\''),K(KMt,13 ), | ||
236 | KPADA_4 ,KPADA_5 ,KPADA_6 ,KPAD_PL ,KSHIFT ,KIGNORE ,K(KMt,'z' ),K(KMt,'x'), | ||
237 | K(KMt,'c'),K(KMt,'v'),K(KMt,'b'),K(KMt,'n' ),K(KMt,'m'),K(KMt,','),K(KMt,'.' ),KIGNORE , | ||
238 | KSHIFT ,K(KTc,Kcu),KPADA_1 ,KPADA_2 ,KPADA_3 ,KCAPSLK ,KALT ,K(KMt,' '), | ||
239 | KALTGR ,KCTRL ,CONS_DEC ,K(KTc,Kcd ),CONS_INC ,KPADA_0 ,KPAD_DT ,KPAD_EN , | ||
240 | KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , | ||
241 | KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , | ||
242 | KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , | ||
243 | }; | ||
244 | |||
245 | u_short ctrl_alt_map[NR_KEYS]= | ||
246 | { | ||
247 | KIGNORE ,K(KCn, 0 ),K(KCn, 1 ),K(KCn, 2 ),K(KCn, 3 ),K(KCn, 4 ),K(KCn, 5 ),K(KCn, 6 ), | ||
248 | K(KCn, 7 ),K(KCn, 8 ),K(KCn, 9 ),K(KCn,10 ),K(KCn,11 ),KIGNORE ,KIGNORE ,KINTR , | ||
249 | KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , | ||
250 | KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,K(KTf,21 ), | ||
251 | K(KTf,20 ),K(KTf,24 ),KNUMLK ,KPAD_DV ,KPAD_ML ,KPAD_HS ,KIGNORE ,K(KMt,17 ), | ||
252 | K(KMt,23 ),K(KMt, 5 ),K(KMt,18 ),K(KMt,20 ),K(KMt,25 ),K(KMt,21 ),K(KMt, 9 ),K(KMt,15 ), | ||
253 | K(KMt,16 ),KIGNORE ,KIGNORE ,KIGNORE ,KREBOOT ,K(KTf,23 ),K(KTf,25 ),KPAD_7 , | ||
254 | KPAD_8 ,KPAD_9 ,KPAD_MI ,KCTRL ,K(KMt, 1 ),K(KMt,19 ),K(KMt, 4 ),K(KMt, 6 ), | ||
255 | K(KMt, 7 ),K(KMt, 8 ),K(KMt,10 ),K(KMt,11 ),K(KMt,12 ),KIGNORE ,KIGNORE ,KENTER , | ||
256 | KPAD_4 ,KPAD_5 ,KPAD_6 ,KPAD_PL ,KSHIFT ,KIGNORE ,K(KMt,26 ),K(KMt,24 ), | ||
257 | K(KMt, 3 ),K(KMt,22 ),K(KMt, 2 ),K(KMt,14 ),K(KMt,13 ),KIGNORE ,KIGNORE ,KIGNORE , | ||
258 | KSHIFT ,K(KTc,Kcu),KPAD_1 ,KPAD_2 ,KPAD_3 ,KCAPSLK ,KALT ,KIGNORE , | ||
259 | KALTGR ,KCTRL ,K(KTc,Kcl),K(KTc,Kcd ),K(KTc,Kcr),KPAD_0 ,KREBOOT ,KPAD_EN , | ||
260 | KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , | ||
261 | KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , | ||
262 | KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE ,KIGNORE , | ||
263 | }; | ||
264 | |||
265 | ushort *key_maps[MAX_NR_KEYMAPS] = { | ||
266 | plain_map, shift_map, altgr_map, 0, | ||
267 | ctrl_map, shift_ctrl_map, 0, 0, | ||
268 | alt_map, 0, 0, 0, | ||
269 | ctrl_alt_map, 0 | ||
270 | }; | ||
271 | |||
272 | unsigned int keymap_count = 7; | ||
273 | |||
274 | /* | ||
275 | * Philosophy: most people do not define more strings, but they who do | ||
276 | * often want quite a lot of string space. So, we statically allocate | ||
277 | * the default and allocate dynamically in chunks of 512 bytes. | ||
278 | */ | ||
279 | |||
280 | char func_buf[] = { | ||
281 | '\033', '[', '[', 'A', 0, | ||
282 | '\033', '[', '[', 'B', 0, | ||
283 | '\033', '[', '[', 'C', 0, | ||
284 | '\033', '[', '[', 'D', 0, | ||
285 | '\033', '[', '[', 'E', 0, | ||
286 | '\033', '[', '1', '7', '~', 0, | ||
287 | '\033', '[', '1', '8', '~', 0, | ||
288 | '\033', '[', '1', '9', '~', 0, | ||
289 | '\033', '[', '2', '0', '~', 0, | ||
290 | '\033', '[', '2', '1', '~', 0, | ||
291 | '\033', '[', '2', '3', '~', 0, | ||
292 | '\033', '[', '2', '4', '~', 0, | ||
293 | '\033', '[', '2', '5', '~', 0, | ||
294 | '\033', '[', '2', '6', '~', 0, | ||
295 | '\033', '[', '2', '8', '~', 0, | ||
296 | '\033', '[', '2', '9', '~', 0, | ||
297 | '\033', '[', '3', '1', '~', 0, | ||
298 | '\033', '[', '3', '2', '~', 0, | ||
299 | '\033', '[', '3', '3', '~', 0, | ||
300 | '\033', '[', '3', '4', '~', 0, | ||
301 | '\033', '[', '1', '~', 0, | ||
302 | '\033', '[', '2', '~', 0, | ||
303 | '\033', '[', '3', '~', 0, | ||
304 | '\033', '[', '4', '~', 0, | ||
305 | '\033', '[', '5', '~', 0, | ||
306 | '\033', '[', '6', '~', 0, | ||
307 | '\033', '[', 'M', 0, | ||
308 | '\033', '[', 'P', 0, | ||
309 | }; | ||
310 | |||
311 | char *funcbufptr = func_buf; | ||
312 | int funcbufsize = sizeof(func_buf); | ||
313 | int funcbufleft = 0; /* space left */ | ||
314 | |||
315 | char *func_table[MAX_NR_FUNC] = { | ||
316 | func_buf + 0, | ||
317 | func_buf + 5, | ||
318 | func_buf + 10, | ||
319 | func_buf + 15, | ||
320 | func_buf + 20, | ||
321 | func_buf + 25, | ||
322 | func_buf + 31, | ||
323 | func_buf + 37, | ||
324 | func_buf + 43, | ||
325 | func_buf + 49, | ||
326 | func_buf + 55, | ||
327 | func_buf + 61, | ||
328 | func_buf + 67, | ||
329 | func_buf + 73, | ||
330 | func_buf + 79, | ||
331 | func_buf + 85, | ||
332 | func_buf + 91, | ||
333 | func_buf + 97, | ||
334 | func_buf + 103, | ||
335 | func_buf + 109, | ||
336 | func_buf + 115, | ||
337 | func_buf + 120, | ||
338 | func_buf + 125, | ||
339 | func_buf + 130, | ||
340 | func_buf + 135, | ||
341 | func_buf + 140, | ||
342 | func_buf + 145, | ||
343 | 0, | ||
344 | 0, | ||
345 | func_buf + 149, | ||
346 | 0, | ||
347 | }; | ||
348 | |||
349 | struct kbdiacr accent_table[MAX_DIACR] = { | ||
350 | {'`', 'A', '\300'}, {'`', 'a', '\340'}, | ||
351 | {'\'', 'A', '\301'}, {'\'', 'a', '\341'}, | ||
352 | {'^', 'A', '\302'}, {'^', 'a', '\342'}, | ||
353 | {'~', 'A', '\303'}, {'~', 'a', '\343'}, | ||
354 | {'"', 'A', '\304'}, {'"', 'a', '\344'}, | ||
355 | {'O', 'A', '\305'}, {'o', 'a', '\345'}, | ||
356 | {'0', 'A', '\305'}, {'0', 'a', '\345'}, | ||
357 | {'A', 'A', '\305'}, {'a', 'a', '\345'}, | ||
358 | {'A', 'E', '\306'}, {'a', 'e', '\346'}, | ||
359 | {',', 'C', '\307'}, {',', 'c', '\347'}, | ||
360 | {'`', 'E', '\310'}, {'`', 'e', '\350'}, | ||
361 | {'\'', 'E', '\311'}, {'\'', 'e', '\351'}, | ||
362 | {'^', 'E', '\312'}, {'^', 'e', '\352'}, | ||
363 | {'"', 'E', '\313'}, {'"', 'e', '\353'}, | ||
364 | {'`', 'I', '\314'}, {'`', 'i', '\354'}, | ||
365 | {'\'', 'I', '\315'}, {'\'', 'i', '\355'}, | ||
366 | {'^', 'I', '\316'}, {'^', 'i', '\356'}, | ||
367 | {'"', 'I', '\317'}, {'"', 'i', '\357'}, | ||
368 | {'-', 'D', '\320'}, {'-', 'd', '\360'}, | ||
369 | {'~', 'N', '\321'}, {'~', 'n', '\361'}, | ||
370 | {'`', 'O', '\322'}, {'`', 'o', '\362'}, | ||
371 | {'\'', 'O', '\323'}, {'\'', 'o', '\363'}, | ||
372 | {'^', 'O', '\324'}, {'^', 'o', '\364'}, | ||
373 | {'~', 'O', '\325'}, {'~', 'o', '\365'}, | ||
374 | {'"', 'O', '\326'}, {'"', 'o', '\366'}, | ||
375 | {'/', 'O', '\330'}, {'/', 'o', '\370'}, | ||
376 | {'`', 'U', '\331'}, {'`', 'u', '\371'}, | ||
377 | {'\'', 'U', '\332'}, {'\'', 'u', '\372'}, | ||
378 | {'^', 'U', '\333'}, {'^', 'u', '\373'}, | ||
379 | {'"', 'U', '\334'}, {'"', 'u', '\374'}, | ||
380 | {'\'', 'Y', '\335'}, {'\'', 'y', '\375'}, | ||
381 | {'T', 'H', '\336'}, {'t', 'h', '\376'}, | ||
382 | {'s', 's', '\337'}, {'"', 'y', '\377'}, | ||
383 | {'s', 'z', '\337'}, {'i', 'j', '\377'}, | ||
384 | }; | ||
385 | |||
386 | unsigned int accent_table_size = 68; | ||
diff --git a/drivers/acorn/char/i2c.c b/drivers/acorn/char/i2c.c new file mode 100644 index 00000000000..c22bb9dca1e --- /dev/null +++ b/drivers/acorn/char/i2c.c | |||
@@ -0,0 +1,369 @@ | |||
1 | /* | ||
2 | * linux/drivers/acorn/char/i2c.c | ||
3 | * | ||
4 | * Copyright (C) 2000 Russell King | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * ARM IOC/IOMD i2c driver. | ||
11 | * | ||
12 | * On Acorn machines, the following i2c devices are on the bus: | ||
13 | * - PCF8583 real time clock & static RAM | ||
14 | */ | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/sched.h> | ||
17 | #include <linux/time.h> | ||
18 | #include <linux/miscdevice.h> | ||
19 | #include <linux/rtc.h> | ||
20 | #include <linux/i2c.h> | ||
21 | #include <linux/i2c-algo-bit.h> | ||
22 | #include <linux/fs.h> | ||
23 | |||
24 | #include <asm/hardware.h> | ||
25 | #include <asm/io.h> | ||
26 | #include <asm/hardware/ioc.h> | ||
27 | #include <asm/system.h> | ||
28 | #include <asm/uaccess.h> | ||
29 | |||
30 | #include "pcf8583.h" | ||
31 | |||
32 | extern int (*set_rtc)(void); | ||
33 | |||
34 | static struct i2c_client *rtc_client; | ||
35 | static const unsigned char days_in_mon[] = | ||
36 | { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; | ||
37 | |||
38 | #define CMOS_CHECKSUM (63) | ||
39 | |||
40 | /* | ||
41 | * Acorn machines store the year in the static RAM at | ||
42 | * location 128. | ||
43 | */ | ||
44 | #define CMOS_YEAR (64 + 128) | ||
45 | |||
46 | static inline int rtc_command(int cmd, void *data) | ||
47 | { | ||
48 | int ret = -EIO; | ||
49 | |||
50 | if (rtc_client) | ||
51 | ret = rtc_client->driver->command(rtc_client, cmd, data); | ||
52 | |||
53 | return ret; | ||
54 | } | ||
55 | |||
56 | /* | ||
57 | * Update the century + year bytes in the CMOS RAM, ensuring | ||
58 | * that the check byte is correctly adjusted for the change. | ||
59 | */ | ||
60 | static int rtc_update_year(unsigned int new_year) | ||
61 | { | ||
62 | unsigned char yr[2], chk; | ||
63 | struct mem cmos_year = { CMOS_YEAR, sizeof(yr), yr }; | ||
64 | struct mem cmos_check = { CMOS_CHECKSUM, 1, &chk }; | ||
65 | int ret; | ||
66 | |||
67 | ret = rtc_command(MEM_READ, &cmos_check); | ||
68 | if (ret) | ||
69 | goto out; | ||
70 | ret = rtc_command(MEM_READ, &cmos_year); | ||
71 | if (ret) | ||
72 | goto out; | ||
73 | |||
74 | chk -= yr[1] + yr[0]; | ||
75 | |||
76 | yr[1] = new_year / 100; | ||
77 | yr[0] = new_year % 100; | ||
78 | |||
79 | chk += yr[1] + yr[0]; | ||
80 | |||
81 | ret = rtc_command(MEM_WRITE, &cmos_year); | ||
82 | if (ret == 0) | ||
83 | ret = rtc_command(MEM_WRITE, &cmos_check); | ||
84 | out: | ||
85 | return ret; | ||
86 | } | ||
87 | |||
88 | /* | ||
89 | * Read the current RTC time and date, and update xtime. | ||
90 | */ | ||
91 | static void get_rtc_time(struct rtc_tm *rtctm, unsigned int *year) | ||
92 | { | ||
93 | unsigned char ctrl, yr[2]; | ||
94 | struct mem rtcmem = { CMOS_YEAR, sizeof(yr), yr }; | ||
95 | int real_year, year_offset; | ||
96 | |||
97 | /* | ||
98 | * Ensure that the RTC is running. | ||
99 | */ | ||
100 | rtc_command(RTC_GETCTRL, &ctrl); | ||
101 | if (ctrl & 0xc0) { | ||
102 | unsigned char new_ctrl = ctrl & ~0xc0; | ||
103 | |||
104 | printk(KERN_WARNING "RTC: resetting control %02x -> %02x\n", | ||
105 | ctrl, new_ctrl); | ||
106 | |||
107 | rtc_command(RTC_SETCTRL, &new_ctrl); | ||
108 | } | ||
109 | |||
110 | if (rtc_command(RTC_GETDATETIME, rtctm) || | ||
111 | rtc_command(MEM_READ, &rtcmem)) | ||
112 | return; | ||
113 | |||
114 | real_year = yr[0]; | ||
115 | |||
116 | /* | ||
117 | * The RTC year holds the LSB two bits of the current | ||
118 | * year, which should reflect the LSB two bits of the | ||
119 | * CMOS copy of the year. Any difference indicates | ||
120 | * that we have to correct the CMOS version. | ||
121 | */ | ||
122 | year_offset = rtctm->year_off - (real_year & 3); | ||
123 | if (year_offset < 0) | ||
124 | /* | ||
125 | * RTC year wrapped. Adjust it appropriately. | ||
126 | */ | ||
127 | year_offset += 4; | ||
128 | |||
129 | *year = real_year + year_offset + yr[1] * 100; | ||
130 | } | ||
131 | |||
132 | static int set_rtc_time(struct rtc_tm *rtctm, unsigned int year) | ||
133 | { | ||
134 | unsigned char leap; | ||
135 | int ret; | ||
136 | |||
137 | leap = (!(year % 4) && (year % 100)) || !(year % 400); | ||
138 | |||
139 | if (rtctm->mon > 12 || rtctm->mon == 0 || rtctm->mday == 0) | ||
140 | return -EINVAL; | ||
141 | |||
142 | if (rtctm->mday > (days_in_mon[rtctm->mon] + (rtctm->mon == 2 && leap))) | ||
143 | return -EINVAL; | ||
144 | |||
145 | if (rtctm->hours >= 24 || rtctm->mins >= 60 || rtctm->secs >= 60) | ||
146 | return -EINVAL; | ||
147 | |||
148 | /* | ||
149 | * The RTC's own 2-bit year must reflect the least | ||
150 | * significant two bits of the CMOS year. | ||
151 | */ | ||
152 | rtctm->year_off = (year % 100) & 3; | ||
153 | |||
154 | ret = rtc_command(RTC_SETDATETIME, rtctm); | ||
155 | if (ret == 0) | ||
156 | ret = rtc_update_year(year); | ||
157 | |||
158 | return ret; | ||
159 | } | ||
160 | |||
161 | /* | ||
162 | * Set the RTC time only. Note that | ||
163 | * we do not touch the date. | ||
164 | */ | ||
165 | static int k_set_rtc_time(void) | ||
166 | { | ||
167 | struct rtc_tm new_rtctm, old_rtctm; | ||
168 | unsigned long nowtime = xtime.tv_sec; | ||
169 | |||
170 | if (rtc_command(RTC_GETDATETIME, &old_rtctm)) | ||
171 | return 0; | ||
172 | |||
173 | new_rtctm.cs = xtime.tv_nsec / 10000000; | ||
174 | new_rtctm.secs = nowtime % 60; nowtime /= 60; | ||
175 | new_rtctm.mins = nowtime % 60; nowtime /= 60; | ||
176 | new_rtctm.hours = nowtime % 24; | ||
177 | |||
178 | /* | ||
179 | * avoid writing when we're going to change the day | ||
180 | * of the month. We will retry in the next minute. | ||
181 | * This basically means that if the RTC must not drift | ||
182 | * by more than 1 minute in 11 minutes. | ||
183 | * | ||
184 | * [ rtc: 1/1/2000 23:58:00, real 2/1/2000 00:01:00, | ||
185 | * rtc gets set to 1/1/2000 00:01:00 ] | ||
186 | */ | ||
187 | if ((old_rtctm.hours == 23 && old_rtctm.mins == 59) || | ||
188 | (new_rtctm.hours == 23 && new_rtctm.mins == 59)) | ||
189 | return 1; | ||
190 | |||
191 | return rtc_command(RTC_SETTIME, &new_rtctm); | ||
192 | } | ||
193 | |||
194 | static int rtc_ioctl(struct inode *inode, struct file *file, | ||
195 | unsigned int cmd, unsigned long arg) | ||
196 | { | ||
197 | unsigned int year; | ||
198 | struct rtc_time rtctm; | ||
199 | struct rtc_tm rtc_raw; | ||
200 | |||
201 | switch (cmd) { | ||
202 | case RTC_ALM_READ: | ||
203 | case RTC_ALM_SET: | ||
204 | break; | ||
205 | |||
206 | case RTC_RD_TIME: | ||
207 | memset(&rtctm, 0, sizeof(struct rtc_time)); | ||
208 | get_rtc_time(&rtc_raw, &year); | ||
209 | rtctm.tm_sec = rtc_raw.secs; | ||
210 | rtctm.tm_min = rtc_raw.mins; | ||
211 | rtctm.tm_hour = rtc_raw.hours; | ||
212 | rtctm.tm_mday = rtc_raw.mday; | ||
213 | rtctm.tm_mon = rtc_raw.mon - 1; /* month starts at 0 */ | ||
214 | rtctm.tm_year = year - 1900; /* starts at 1900 */ | ||
215 | return copy_to_user((void *)arg, &rtctm, sizeof(rtctm)) | ||
216 | ? -EFAULT : 0; | ||
217 | |||
218 | case RTC_SET_TIME: | ||
219 | if (!capable(CAP_SYS_TIME)) | ||
220 | return -EACCES; | ||
221 | |||
222 | if (copy_from_user(&rtctm, (void *)arg, sizeof(rtctm))) | ||
223 | return -EFAULT; | ||
224 | rtc_raw.secs = rtctm.tm_sec; | ||
225 | rtc_raw.mins = rtctm.tm_min; | ||
226 | rtc_raw.hours = rtctm.tm_hour; | ||
227 | rtc_raw.mday = rtctm.tm_mday; | ||
228 | rtc_raw.mon = rtctm.tm_mon + 1; | ||
229 | year = rtctm.tm_year + 1900; | ||
230 | return set_rtc_time(&rtc_raw, year); | ||
231 | break; | ||
232 | |||
233 | case RTC_EPOCH_READ: | ||
234 | return put_user(1900, (unsigned long *)arg); | ||
235 | |||
236 | } | ||
237 | return -EINVAL; | ||
238 | } | ||
239 | |||
240 | static struct file_operations rtc_fops = { | ||
241 | .ioctl = rtc_ioctl, | ||
242 | }; | ||
243 | |||
244 | static struct miscdevice rtc_dev = { | ||
245 | .minor = RTC_MINOR, | ||
246 | .name = "rtc", | ||
247 | .fops = &rtc_fops, | ||
248 | }; | ||
249 | |||
250 | /* IOC / IOMD i2c driver */ | ||
251 | |||
252 | #define FORCE_ONES 0xdc | ||
253 | #define SCL 0x02 | ||
254 | #define SDA 0x01 | ||
255 | |||
256 | /* | ||
257 | * We must preserve all non-i2c output bits in IOC_CONTROL. | ||
258 | * Note also that we need to preserve the value of SCL and | ||
259 | * SDA outputs as well (which may be different from the | ||
260 | * values read back from IOC_CONTROL). | ||
261 | */ | ||
262 | static u_int force_ones; | ||
263 | |||
264 | static void ioc_setscl(void *data, int state) | ||
265 | { | ||
266 | u_int ioc_control = ioc_readb(IOC_CONTROL) & ~(SCL | SDA); | ||
267 | u_int ones = force_ones; | ||
268 | |||
269 | if (state) | ||
270 | ones |= SCL; | ||
271 | else | ||
272 | ones &= ~SCL; | ||
273 | |||
274 | force_ones = ones; | ||
275 | |||
276 | ioc_writeb(ioc_control | ones, IOC_CONTROL); | ||
277 | } | ||
278 | |||
279 | static void ioc_setsda(void *data, int state) | ||
280 | { | ||
281 | u_int ioc_control = ioc_readb(IOC_CONTROL) & ~(SCL | SDA); | ||
282 | u_int ones = force_ones; | ||
283 | |||
284 | if (state) | ||
285 | ones |= SDA; | ||
286 | else | ||
287 | ones &= ~SDA; | ||
288 | |||
289 | force_ones = ones; | ||
290 | |||
291 | ioc_writeb(ioc_control | ones, IOC_CONTROL); | ||
292 | } | ||
293 | |||
294 | static int ioc_getscl(void *data) | ||
295 | { | ||
296 | return (ioc_readb(IOC_CONTROL) & SCL) != 0; | ||
297 | } | ||
298 | |||
299 | static int ioc_getsda(void *data) | ||
300 | { | ||
301 | return (ioc_readb(IOC_CONTROL) & SDA) != 0; | ||
302 | } | ||
303 | |||
304 | static struct i2c_algo_bit_data ioc_data = { | ||
305 | .setsda = ioc_setsda, | ||
306 | .setscl = ioc_setscl, | ||
307 | .getsda = ioc_getsda, | ||
308 | .getscl = ioc_getscl, | ||
309 | .udelay = 80, | ||
310 | .mdelay = 80, | ||
311 | .timeout = 100 | ||
312 | }; | ||
313 | |||
314 | static int ioc_client_reg(struct i2c_client *client) | ||
315 | { | ||
316 | if (client->driver->id == I2C_DRIVERID_PCF8583 && | ||
317 | client->addr == 0x50) { | ||
318 | struct rtc_tm rtctm; | ||
319 | unsigned int year; | ||
320 | struct timespec tv; | ||
321 | |||
322 | rtc_client = client; | ||
323 | get_rtc_time(&rtctm, &year); | ||
324 | |||
325 | tv.tv_nsec = rtctm.cs * 10000000; | ||
326 | tv.tv_sec = mktime(year, rtctm.mon, rtctm.mday, | ||
327 | rtctm.hours, rtctm.mins, rtctm.secs); | ||
328 | do_settimeofday(&tv); | ||
329 | set_rtc = k_set_rtc_time; | ||
330 | } | ||
331 | |||
332 | return 0; | ||
333 | } | ||
334 | |||
335 | static int ioc_client_unreg(struct i2c_client *client) | ||
336 | { | ||
337 | if (client == rtc_client) { | ||
338 | set_rtc = NULL; | ||
339 | rtc_client = NULL; | ||
340 | } | ||
341 | |||
342 | return 0; | ||
343 | } | ||
344 | |||
345 | static struct i2c_adapter ioc_ops = { | ||
346 | .id = I2C_HW_B_IOC, | ||
347 | .algo_data = &ioc_data, | ||
348 | .client_register = ioc_client_reg, | ||
349 | .client_unregister = ioc_client_unreg, | ||
350 | }; | ||
351 | |||
352 | static int __init i2c_ioc_init(void) | ||
353 | { | ||
354 | int ret; | ||
355 | |||
356 | force_ones = FORCE_ONES | SCL | SDA; | ||
357 | |||
358 | ret = i2c_bit_add_bus(&ioc_ops); | ||
359 | |||
360 | if (ret >= 0){ | ||
361 | ret = misc_register(&rtc_dev); | ||
362 | if(ret < 0) | ||
363 | i2c_bit_del_bus(&ioc_ops); | ||
364 | } | ||
365 | |||
366 | return ret; | ||
367 | } | ||
368 | |||
369 | __initcall(i2c_ioc_init); | ||
diff --git a/drivers/acorn/char/pcf8583.c b/drivers/acorn/char/pcf8583.c new file mode 100644 index 00000000000..ad7ae7ab892 --- /dev/null +++ b/drivers/acorn/char/pcf8583.c | |||
@@ -0,0 +1,239 @@ | |||
1 | /* | ||
2 | * linux/drivers/acorn/char/pcf8583.c | ||
3 | * | ||
4 | * Copyright (C) 2000 Russell King | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * Driver for PCF8583 RTC & RAM chip | ||
11 | */ | ||
12 | #include <linux/i2c.h> | ||
13 | #include <linux/slab.h> | ||
14 | #include <linux/string.h> | ||
15 | #include <linux/mc146818rtc.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/errno.h> | ||
18 | #include <linux/bcd.h> | ||
19 | |||
20 | #include "pcf8583.h" | ||
21 | |||
22 | static struct i2c_driver pcf8583_driver; | ||
23 | |||
24 | static unsigned short ignore[] = { I2C_CLIENT_END }; | ||
25 | static unsigned short normal_addr[] = { 0x50, I2C_CLIENT_END }; | ||
26 | |||
27 | static struct i2c_client_address_data addr_data = { | ||
28 | .normal_i2c = normal_addr, | ||
29 | .normal_i2c_range = ignore, | ||
30 | .probe = ignore, | ||
31 | .probe_range = ignore, | ||
32 | .ignore = ignore, | ||
33 | .ignore_range = ignore, | ||
34 | .force = ignore, | ||
35 | }; | ||
36 | |||
37 | #define DAT(x) ((unsigned int)(x->dev.driver_data)) | ||
38 | |||
39 | static int | ||
40 | pcf8583_attach(struct i2c_adapter *adap, int addr, int kind) | ||
41 | { | ||
42 | struct i2c_client *c; | ||
43 | unsigned char buf[1], ad[1] = { 0 }; | ||
44 | struct i2c_msg msgs[2] = { | ||
45 | { addr, 0, 1, ad }, | ||
46 | { addr, I2C_M_RD, 1, buf } | ||
47 | }; | ||
48 | |||
49 | c = kmalloc(sizeof(*c), GFP_KERNEL); | ||
50 | if (!c) | ||
51 | return -ENOMEM; | ||
52 | |||
53 | memset(c, 0, sizeof(*c)); | ||
54 | c->addr = addr; | ||
55 | c->adapter = adap; | ||
56 | c->driver = &pcf8583_driver; | ||
57 | |||
58 | if (i2c_transfer(c->adapter, msgs, 2) == 2) | ||
59 | DAT(c) = buf[0]; | ||
60 | |||
61 | return i2c_attach_client(c); | ||
62 | } | ||
63 | |||
64 | static int | ||
65 | pcf8583_probe(struct i2c_adapter *adap) | ||
66 | { | ||
67 | return i2c_probe(adap, &addr_data, pcf8583_attach); | ||
68 | } | ||
69 | |||
70 | static int | ||
71 | pcf8583_detach(struct i2c_client *client) | ||
72 | { | ||
73 | i2c_detach_client(client); | ||
74 | kfree(client); | ||
75 | return 0; | ||
76 | } | ||
77 | |||
78 | static int | ||
79 | pcf8583_get_datetime(struct i2c_client *client, struct rtc_tm *dt) | ||
80 | { | ||
81 | unsigned char buf[8], addr[1] = { 1 }; | ||
82 | struct i2c_msg msgs[2] = { | ||
83 | { client->addr, 0, 1, addr }, | ||
84 | { client->addr, I2C_M_RD, 6, buf } | ||
85 | }; | ||
86 | int ret = -EIO; | ||
87 | |||
88 | memset(buf, 0, sizeof(buf)); | ||
89 | |||
90 | ret = i2c_transfer(client->adapter, msgs, 2); | ||
91 | if (ret == 2) { | ||
92 | dt->year_off = buf[4] >> 6; | ||
93 | dt->wday = buf[5] >> 5; | ||
94 | |||
95 | buf[4] &= 0x3f; | ||
96 | buf[5] &= 0x1f; | ||
97 | |||
98 | dt->cs = BCD_TO_BIN(buf[0]); | ||
99 | dt->secs = BCD_TO_BIN(buf[1]); | ||
100 | dt->mins = BCD_TO_BIN(buf[2]); | ||
101 | dt->hours = BCD_TO_BIN(buf[3]); | ||
102 | dt->mday = BCD_TO_BIN(buf[4]); | ||
103 | dt->mon = BCD_TO_BIN(buf[5]); | ||
104 | |||
105 | ret = 0; | ||
106 | } | ||
107 | |||
108 | return ret; | ||
109 | } | ||
110 | |||
111 | static int | ||
112 | pcf8583_set_datetime(struct i2c_client *client, struct rtc_tm *dt, int datetoo) | ||
113 | { | ||
114 | unsigned char buf[8]; | ||
115 | int ret, len = 6; | ||
116 | |||
117 | buf[0] = 0; | ||
118 | buf[1] = DAT(client) | 0x80; | ||
119 | buf[2] = BIN_TO_BCD(dt->cs); | ||
120 | buf[3] = BIN_TO_BCD(dt->secs); | ||
121 | buf[4] = BIN_TO_BCD(dt->mins); | ||
122 | buf[5] = BIN_TO_BCD(dt->hours); | ||
123 | |||
124 | if (datetoo) { | ||
125 | len = 8; | ||
126 | buf[6] = BIN_TO_BCD(dt->mday) | (dt->year_off << 6); | ||
127 | buf[7] = BIN_TO_BCD(dt->mon) | (dt->wday << 5); | ||
128 | } | ||
129 | |||
130 | ret = i2c_master_send(client, (char *)buf, len); | ||
131 | if (ret == len) | ||
132 | ret = 0; | ||
133 | |||
134 | buf[1] = DAT(client); | ||
135 | i2c_master_send(client, (char *)buf, 2); | ||
136 | |||
137 | return ret; | ||
138 | } | ||
139 | |||
140 | static int | ||
141 | pcf8583_get_ctrl(struct i2c_client *client, unsigned char *ctrl) | ||
142 | { | ||
143 | *ctrl = DAT(client); | ||
144 | return 0; | ||
145 | } | ||
146 | |||
147 | static int | ||
148 | pcf8583_set_ctrl(struct i2c_client *client, unsigned char *ctrl) | ||
149 | { | ||
150 | unsigned char buf[2]; | ||
151 | |||
152 | buf[0] = 0; | ||
153 | buf[1] = *ctrl; | ||
154 | DAT(client) = *ctrl; | ||
155 | |||
156 | return i2c_master_send(client, (char *)buf, 2); | ||
157 | } | ||
158 | |||
159 | static int | ||
160 | pcf8583_read_mem(struct i2c_client *client, struct mem *mem) | ||
161 | { | ||
162 | unsigned char addr[1]; | ||
163 | struct i2c_msg msgs[2] = { | ||
164 | { client->addr, 0, 1, addr }, | ||
165 | { client->addr, I2C_M_RD, 0, mem->data } | ||
166 | }; | ||
167 | |||
168 | if (mem->loc < 8) | ||
169 | return -EINVAL; | ||
170 | |||
171 | addr[0] = mem->loc; | ||
172 | msgs[1].len = mem->nr; | ||
173 | |||
174 | return i2c_transfer(client->adapter, msgs, 2) == 2 ? 0 : -EIO; | ||
175 | } | ||
176 | |||
177 | static int | ||
178 | pcf8583_write_mem(struct i2c_client *client, struct mem *mem) | ||
179 | { | ||
180 | unsigned char addr[1]; | ||
181 | struct i2c_msg msgs[2] = { | ||
182 | { client->addr, 0, 1, addr }, | ||
183 | { client->addr, 0, 0, mem->data } | ||
184 | }; | ||
185 | |||
186 | if (mem->loc < 8) | ||
187 | return -EINVAL; | ||
188 | |||
189 | addr[0] = mem->loc; | ||
190 | msgs[1].len = mem->nr; | ||
191 | |||
192 | return i2c_transfer(client->adapter, msgs, 2) == 2 ? 0 : -EIO; | ||
193 | } | ||
194 | |||
195 | static int | ||
196 | pcf8583_command(struct i2c_client *client, unsigned int cmd, void *arg) | ||
197 | { | ||
198 | switch (cmd) { | ||
199 | case RTC_GETDATETIME: | ||
200 | return pcf8583_get_datetime(client, arg); | ||
201 | |||
202 | case RTC_SETTIME: | ||
203 | return pcf8583_set_datetime(client, arg, 0); | ||
204 | |||
205 | case RTC_SETDATETIME: | ||
206 | return pcf8583_set_datetime(client, arg, 1); | ||
207 | |||
208 | case RTC_GETCTRL: | ||
209 | return pcf8583_get_ctrl(client, arg); | ||
210 | |||
211 | case RTC_SETCTRL: | ||
212 | return pcf8583_set_ctrl(client, arg); | ||
213 | |||
214 | case MEM_READ: | ||
215 | return pcf8583_read_mem(client, arg); | ||
216 | |||
217 | case MEM_WRITE: | ||
218 | return pcf8583_write_mem(client, arg); | ||
219 | |||
220 | default: | ||
221 | return -EINVAL; | ||
222 | } | ||
223 | } | ||
224 | |||
225 | static struct i2c_driver pcf8583_driver = { | ||
226 | .name = "PCF8583", | ||
227 | .id = I2C_DRIVERID_PCF8583, | ||
228 | .flags = I2C_DF_NOTIFY, | ||
229 | .attach_adapter = pcf8583_probe, | ||
230 | .detach_client = pcf8583_detach, | ||
231 | .command = pcf8583_command | ||
232 | }; | ||
233 | |||
234 | static __init int pcf8583_init(void) | ||
235 | { | ||
236 | return i2c_add_driver(&pcf8583_driver); | ||
237 | } | ||
238 | |||
239 | __initcall(pcf8583_init); | ||
diff --git a/drivers/acorn/char/pcf8583.h b/drivers/acorn/char/pcf8583.h new file mode 100644 index 00000000000..847f7fdb876 --- /dev/null +++ b/drivers/acorn/char/pcf8583.h | |||
@@ -0,0 +1,41 @@ | |||
1 | /* | ||
2 | * linux/drivers/acorn/char/pcf8583.h | ||
3 | * | ||
4 | * Copyright (C) 2000 Russell King | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | struct rtc_tm { | ||
11 | unsigned char cs; | ||
12 | unsigned char secs; | ||
13 | unsigned char mins; | ||
14 | unsigned char hours; | ||
15 | unsigned char mday; | ||
16 | unsigned char mon; | ||
17 | unsigned char year_off; | ||
18 | unsigned char wday; | ||
19 | }; | ||
20 | |||
21 | struct mem { | ||
22 | unsigned int loc; | ||
23 | unsigned int nr; | ||
24 | unsigned char *data; | ||
25 | }; | ||
26 | |||
27 | #define RTC_GETDATETIME 0 | ||
28 | #define RTC_SETTIME 1 | ||
29 | #define RTC_SETDATETIME 2 | ||
30 | #define RTC_GETCTRL 3 | ||
31 | #define RTC_SETCTRL 4 | ||
32 | #define MEM_READ 5 | ||
33 | #define MEM_WRITE 6 | ||
34 | |||
35 | #define CTRL_STOP 0x80 | ||
36 | #define CTRL_HOLD 0x40 | ||
37 | #define CTRL_32KHZ 0x00 | ||
38 | #define CTRL_MASK 0x08 | ||
39 | #define CTRL_ALARMEN 0x04 | ||
40 | #define CTRL_ALARM 0x02 | ||
41 | #define CTRL_TIMER 0x01 | ||