diff options
264 files changed, 15463 insertions, 2602 deletions
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile index 7d87dd73cbe4..5a2882d275ba 100644 --- a/Documentation/DocBook/Makefile +++ b/Documentation/DocBook/Makefile | |||
@@ -2,7 +2,7 @@ | |||
2 | # This makefile is used to generate the kernel documentation, | 2 | # This makefile is used to generate the kernel documentation, |
3 | # primarily based on in-line comments in various source files. | 3 | # primarily based on in-line comments in various source files. |
4 | # See Documentation/kernel-doc-nano-HOWTO.txt for instruction in how | 4 | # See Documentation/kernel-doc-nano-HOWTO.txt for instruction in how |
5 | # to ducument the SRC - and how to read it. | 5 | # to document the SRC - and how to read it. |
6 | # To add a new book the only step required is to add the book to the | 6 | # To add a new book the only step required is to add the book to the |
7 | # list of DOCBOOKS. | 7 | # list of DOCBOOKS. |
8 | 8 | ||
diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl index 8c9c6704e85b..ca02e04a906c 100644 --- a/Documentation/DocBook/kernel-api.tmpl +++ b/Documentation/DocBook/kernel-api.tmpl | |||
@@ -322,7 +322,6 @@ X!Earch/i386/kernel/mca.c | |||
322 | <chapter id="sysfs"> | 322 | <chapter id="sysfs"> |
323 | <title>The Filesystem for Exporting Kernel Objects</title> | 323 | <title>The Filesystem for Exporting Kernel Objects</title> |
324 | !Efs/sysfs/file.c | 324 | !Efs/sysfs/file.c |
325 | !Efs/sysfs/dir.c | ||
326 | !Efs/sysfs/symlink.c | 325 | !Efs/sysfs/symlink.c |
327 | !Efs/sysfs/bin.c | 326 | !Efs/sysfs/bin.c |
328 | </chapter> | 327 | </chapter> |
diff --git a/Documentation/acpi-hotkey.txt b/Documentation/acpi-hotkey.txt index 744f1aec6553..38040fa37649 100644 --- a/Documentation/acpi-hotkey.txt +++ b/Documentation/acpi-hotkey.txt | |||
@@ -30,7 +30,7 @@ specific hotkey(event)) | |||
30 | echo "event_num:event_type:event_argument" > | 30 | echo "event_num:event_type:event_argument" > |
31 | /proc/acpi/hotkey/action. | 31 | /proc/acpi/hotkey/action. |
32 | The result of the execution of this aml method is | 32 | The result of the execution of this aml method is |
33 | attached to /proc/acpi/hotkey/poll_method, which is dnyamically | 33 | attached to /proc/acpi/hotkey/poll_method, which is dynamically |
34 | created. Please use command "cat /proc/acpi/hotkey/polling_method" | 34 | created. Please use command "cat /proc/acpi/hotkey/polling_method" |
35 | to retrieve it. | 35 | to retrieve it. |
36 | 36 | ||
diff --git a/Documentation/fujitsu/frv/kernel-ABI.txt b/Documentation/fujitsu/frv/kernel-ABI.txt index 0ed9b0a779bc..8b0a5fc8bfd9 100644 --- a/Documentation/fujitsu/frv/kernel-ABI.txt +++ b/Documentation/fujitsu/frv/kernel-ABI.txt | |||
@@ -1,17 +1,19 @@ | |||
1 | ================================= | 1 | ================================= |
2 | INTERNAL KERNEL ABI FOR FR-V ARCH | 2 | INTERNAL KERNEL ABI FOR FR-V ARCH |
3 | ================================= | 3 | ================================= |
4 | 4 | ||
5 | The internal FRV kernel ABI is not quite the same as the userspace ABI. A number of the registers | 5 | The internal FRV kernel ABI is not quite the same as the userspace ABI. A |
6 | are used for special purposed, and the ABI is not consistent between modules vs core, and MMU vs | 6 | number of the registers are used for special purposed, and the ABI is not |
7 | no-MMU. | 7 | consistent between modules vs core, and MMU vs no-MMU. |
8 | 8 | ||
9 | This partly stems from the fact that FRV CPUs do not have a separate supervisor stack pointer, and | 9 | This partly stems from the fact that FRV CPUs do not have a separate |
10 | most of them do not have any scratch registers, thus requiring at least one general purpose | 10 | supervisor stack pointer, and most of them do not have any scratch |
11 | register to be clobbered in such an event. Also, within the kernel core, it is possible to simply | 11 | registers, thus requiring at least one general purpose register to be |
12 | jump or call directly between functions using a relative offset. This cannot be extended to modules | 12 | clobbered in such an event. Also, within the kernel core, it is possible to |
13 | for the displacement is likely to be too far. Thus in modules the address of a function to call | 13 | simply jump or call directly between functions using a relative offset. |
14 | must be calculated in a register and then used, requiring two extra instructions. | 14 | This cannot be extended to modules for the displacement is likely to be too |
15 | far. Thus in modules the address of a function to call must be calculated | ||
16 | in a register and then used, requiring two extra instructions. | ||
15 | 17 | ||
16 | This document has the following sections: | 18 | This document has the following sections: |
17 | 19 | ||
@@ -39,7 +41,8 @@ When a system call is made, the following registers are effective: | |||
39 | CPU OPERATING MODES | 41 | CPU OPERATING MODES |
40 | =================== | 42 | =================== |
41 | 43 | ||
42 | The FR-V CPU has three basic operating modes. In order of increasing capability: | 44 | The FR-V CPU has three basic operating modes. In order of increasing |
45 | capability: | ||
43 | 46 | ||
44 | (1) User mode. | 47 | (1) User mode. |
45 | 48 | ||
@@ -47,42 +50,46 @@ The FR-V CPU has three basic operating modes. In order of increasing capability: | |||
47 | 50 | ||
48 | (2) Kernel mode. | 51 | (2) Kernel mode. |
49 | 52 | ||
50 | Normal kernel mode. There are many additional control registers available that may be | 53 | Normal kernel mode. There are many additional control registers |
51 | accessed in this mode, in addition to all the stuff available to user mode. This has two | 54 | available that may be accessed in this mode, in addition to all the |
52 | submodes: | 55 | stuff available to user mode. This has two submodes: |
53 | 56 | ||
54 | (a) Exceptions enabled (PSR.T == 1). | 57 | (a) Exceptions enabled (PSR.T == 1). |
55 | 58 | ||
56 | Exceptions will invoke the appropriate normal kernel mode handler. On entry to the | 59 | Exceptions will invoke the appropriate normal kernel mode |
57 | handler, the PSR.T bit will be cleared. | 60 | handler. On entry to the handler, the PSR.T bit will be cleared. |
58 | 61 | ||
59 | (b) Exceptions disabled (PSR.T == 0). | 62 | (b) Exceptions disabled (PSR.T == 0). |
60 | 63 | ||
61 | No exceptions or interrupts may happen. Any mandatory exceptions will cause the CPU to | 64 | No exceptions or interrupts may happen. Any mandatory exceptions |
62 | halt unless the CPU is told to jump into debug mode instead. | 65 | will cause the CPU to halt unless the CPU is told to jump into |
66 | debug mode instead. | ||
63 | 67 | ||
64 | (3) Debug mode. | 68 | (3) Debug mode. |
65 | 69 | ||
66 | No exceptions may happen in this mode. Memory protection and management exceptions will be | 70 | No exceptions may happen in this mode. Memory protection and |
67 | flagged for later consideration, but the exception handler won't be invoked. Debugging traps | 71 | management exceptions will be flagged for later consideration, but |
68 | such as hardware breakpoints and watchpoints will be ignored. This mode is entered only by | 72 | the exception handler won't be invoked. Debugging traps such as |
69 | debugging events obtained from the other two modes. | 73 | hardware breakpoints and watchpoints will be ignored. This mode is |
74 | entered only by debugging events obtained from the other two modes. | ||
70 | 75 | ||
71 | All kernel mode registers may be accessed, plus a few extra debugging specific registers. | 76 | All kernel mode registers may be accessed, plus a few extra debugging |
77 | specific registers. | ||
72 | 78 | ||
73 | 79 | ||
74 | ================================= | 80 | ================================= |
75 | INTERNAL KERNEL-MODE REGISTER ABI | 81 | INTERNAL KERNEL-MODE REGISTER ABI |
76 | ================================= | 82 | ================================= |
77 | 83 | ||
78 | There are a number of permanent register assignments that are set up by entry.S in the exception | 84 | There are a number of permanent register assignments that are set up by |
79 | prologue. Note that there is a complete set of exception prologues for each of user->kernel | 85 | entry.S in the exception prologue. Note that there is a complete set of |
80 | transition and kernel->kernel transition. There are also user->debug and kernel->debug mode | 86 | exception prologues for each of user->kernel transition and kernel->kernel |
81 | transition prologues. | 87 | transition. There are also user->debug and kernel->debug mode transition |
88 | prologues. | ||
82 | 89 | ||
83 | 90 | ||
84 | REGISTER FLAVOUR USE | 91 | REGISTER FLAVOUR USE |
85 | =============== ======= ==================================================== | 92 | =============== ======= ============================================== |
86 | GR1 Supervisor stack pointer | 93 | GR1 Supervisor stack pointer |
87 | GR15 Current thread info pointer | 94 | GR15 Current thread info pointer |
88 | GR16 GP-Rel base register for small data | 95 | GR16 GP-Rel base register for small data |
@@ -92,10 +99,12 @@ transition prologues. | |||
92 | GR31 NOMMU Destroyed by debug mode entry | 99 | GR31 NOMMU Destroyed by debug mode entry |
93 | GR31 MMU Destroyed by TLB miss kernel mode entry | 100 | GR31 MMU Destroyed by TLB miss kernel mode entry |
94 | CCR.ICC2 Virtual interrupt disablement tracking | 101 | CCR.ICC2 Virtual interrupt disablement tracking |
95 | CCCR.CC3 Cleared by exception prologue (atomic op emulation) | 102 | CCCR.CC3 Cleared by exception prologue |
103 | (atomic op emulation) | ||
96 | SCR0 MMU See mmu-layout.txt. | 104 | SCR0 MMU See mmu-layout.txt. |
97 | SCR1 MMU See mmu-layout.txt. | 105 | SCR1 MMU See mmu-layout.txt. |
98 | SCR2 MMU Save for EAR0 (destroyed by icache insns in debug mode) | 106 | SCR2 MMU Save for EAR0 (destroyed by icache insns |
107 | in debug mode) | ||
99 | SCR3 MMU Save for GR31 during debug exceptions | 108 | SCR3 MMU Save for GR31 during debug exceptions |
100 | DAMR/IAMR NOMMU Fixed memory protection layout. | 109 | DAMR/IAMR NOMMU Fixed memory protection layout. |
101 | DAMR/IAMR MMU See mmu-layout.txt. | 110 | DAMR/IAMR MMU See mmu-layout.txt. |
@@ -104,18 +113,21 @@ transition prologues. | |||
104 | Certain registers are also used or modified across function calls: | 113 | Certain registers are also used or modified across function calls: |
105 | 114 | ||
106 | REGISTER CALL RETURN | 115 | REGISTER CALL RETURN |
107 | =============== =============================== =============================== | 116 | =============== =============================== ====================== |
108 | GR0 Fixed Zero - | 117 | GR0 Fixed Zero - |
109 | GR2 Function call frame pointer | 118 | GR2 Function call frame pointer |
110 | GR3 Special Preserved | 119 | GR3 Special Preserved |
111 | GR3-GR7 - Clobbered | 120 | GR3-GR7 - Clobbered |
112 | GR8 Function call arg #1 Return value (or clobbered) | 121 | GR8 Function call arg #1 Return value |
113 | GR9 Function call arg #2 Return value MSW (or clobbered) | 122 | (or clobbered) |
123 | GR9 Function call arg #2 Return value MSW | ||
124 | (or clobbered) | ||
114 | GR10-GR13 Function call arg #3-#6 Clobbered | 125 | GR10-GR13 Function call arg #3-#6 Clobbered |
115 | GR14 - Clobbered | 126 | GR14 - Clobbered |
116 | GR15-GR16 Special Preserved | 127 | GR15-GR16 Special Preserved |
117 | GR17-GR27 - Preserved | 128 | GR17-GR27 - Preserved |
118 | GR28-GR31 Special Only accessed explicitly | 129 | GR28-GR31 Special Only accessed |
130 | explicitly | ||
119 | LR Return address after CALL Clobbered | 131 | LR Return address after CALL Clobbered |
120 | CCR/CCCR - Mostly Clobbered | 132 | CCR/CCCR - Mostly Clobbered |
121 | 133 | ||
@@ -124,46 +136,53 @@ Certain registers are also used or modified across function calls: | |||
124 | INTERNAL DEBUG-MODE REGISTER ABI | 136 | INTERNAL DEBUG-MODE REGISTER ABI |
125 | ================================ | 137 | ================================ |
126 | 138 | ||
127 | This is the same as the kernel-mode register ABI for functions calls. The difference is that in | 139 | This is the same as the kernel-mode register ABI for functions calls. The |
128 | debug-mode there's a different stack and a different exception frame. Almost all the global | 140 | difference is that in debug-mode there's a different stack and a different |
129 | registers from kernel-mode (including the stack pointer) may be changed. | 141 | exception frame. Almost all the global registers from kernel-mode |
142 | (including the stack pointer) may be changed. | ||
130 | 143 | ||
131 | REGISTER FLAVOUR USE | 144 | REGISTER FLAVOUR USE |
132 | =============== ======= ==================================================== | 145 | =============== ======= ============================================== |
133 | GR1 Debug stack pointer | 146 | GR1 Debug stack pointer |
134 | GR16 GP-Rel base register for small data | 147 | GR16 GP-Rel base register for small data |
135 | GR31 Current debug exception frame pointer (__debug_frame) | 148 | GR31 Current debug exception frame pointer |
149 | (__debug_frame) | ||
136 | SCR3 MMU Saved value of GR31 | 150 | SCR3 MMU Saved value of GR31 |
137 | 151 | ||
138 | 152 | ||
139 | Note that debug mode is able to interfere with the kernel's emulated atomic ops, so it must be | 153 | Note that debug mode is able to interfere with the kernel's emulated atomic |
140 | exceedingly careful not to do any that would interact with the main kernel in this regard. Hence | 154 | ops, so it must be exceedingly careful not to do any that would interact |
141 | the debug mode code (gdbstub) is almost completely self-contained. The only external code used is | 155 | with the main kernel in this regard. Hence the debug mode code (gdbstub) is |
142 | the sprintf family of functions. | 156 | almost completely self-contained. The only external code used is the |
157 | sprintf family of functions. | ||
143 | 158 | ||
144 | Futhermore, break.S is so complicated because single-step mode does not switch off on entry to an | 159 | Futhermore, break.S is so complicated because single-step mode does not |
145 | exception. That means unless manually disabled, single-stepping will blithely go on stepping into | 160 | switch off on entry to an exception. That means unless manually disabled, |
146 | things like interrupts. See gdbstub.txt for more information. | 161 | single-stepping will blithely go on stepping into things like interrupts. |
162 | See gdbstub.txt for more information. | ||
147 | 163 | ||
148 | 164 | ||
149 | ========================== | 165 | ========================== |
150 | VIRTUAL INTERRUPT HANDLING | 166 | VIRTUAL INTERRUPT HANDLING |
151 | ========================== | 167 | ========================== |
152 | 168 | ||
153 | Because accesses to the PSR is so slow, and to disable interrupts we have to access it twice (once | 169 | Because accesses to the PSR is so slow, and to disable interrupts we have |
154 | to read and once to write), we don't actually disable interrupts at all if we don't have to. What | 170 | to access it twice (once to read and once to write), we don't actually |
155 | we do instead is use the ICC2 condition code flags to note virtual disablement, such that if we | 171 | disable interrupts at all if we don't have to. What we do instead is use |
156 | then do take an interrupt, we note the flag, really disable interrupts, set another flag and resume | 172 | the ICC2 condition code flags to note virtual disablement, such that if we |
157 | execution at the point the interrupt happened. Setting condition flags as a side effect of an | 173 | then do take an interrupt, we note the flag, really disable interrupts, set |
158 | arithmetic or logical instruction is really fast. This use of the ICC2 only occurs within the | 174 | another flag and resume execution at the point the interrupt happened. |
175 | Setting condition flags as a side effect of an arithmetic or logical | ||
176 | instruction is really fast. This use of the ICC2 only occurs within the | ||
159 | kernel - it does not affect userspace. | 177 | kernel - it does not affect userspace. |
160 | 178 | ||
161 | The flags we use are: | 179 | The flags we use are: |
162 | 180 | ||
163 | (*) CCR.ICC2.Z [Zero flag] | 181 | (*) CCR.ICC2.Z [Zero flag] |
164 | 182 | ||
165 | Set to virtually disable interrupts, clear when interrupts are virtually enabled. Can be | 183 | Set to virtually disable interrupts, clear when interrupts are |
166 | modified by logical instructions without affecting the Carry flag. | 184 | virtually enabled. Can be modified by logical instructions without |
185 | affecting the Carry flag. | ||
167 | 186 | ||
168 | (*) CCR.ICC2.C [Carry flag] | 187 | (*) CCR.ICC2.C [Carry flag] |
169 | 188 | ||
@@ -176,8 +195,9 @@ What happens is this: | |||
176 | 195 | ||
177 | ICC2.Z is 0, ICC2.C is 1. | 196 | ICC2.Z is 0, ICC2.C is 1. |
178 | 197 | ||
179 | (2) An interrupt occurs. The exception prologue examines ICC2.Z and determines that nothing needs | 198 | (2) An interrupt occurs. The exception prologue examines ICC2.Z and |
180 | doing. This is done simply with an unlikely BEQ instruction. | 199 | determines that nothing needs doing. This is done simply with an |
200 | unlikely BEQ instruction. | ||
181 | 201 | ||
182 | (3) The interrupts are disabled (local_irq_disable) | 202 | (3) The interrupts are disabled (local_irq_disable) |
183 | 203 | ||
@@ -187,48 +207,56 @@ What happens is this: | |||
187 | 207 | ||
188 | ICC2.Z would be set to 0. | 208 | ICC2.Z would be set to 0. |
189 | 209 | ||
190 | A TIHI #2 instruction (trap #2 if condition HI - Z==0 && C==0) would be used to trap if | 210 | A TIHI #2 instruction (trap #2 if condition HI - Z==0 && C==0) would |
191 | interrupts were now virtually enabled, but physically disabled - which they're not, so the | 211 | be used to trap if interrupts were now virtually enabled, but |
192 | trap isn't taken. The kernel would then be back to state (1). | 212 | physically disabled - which they're not, so the trap isn't taken. The |
213 | kernel would then be back to state (1). | ||
193 | 214 | ||
194 | (5) An interrupt occurs. The exception prologue examines ICC2.Z and determines that the interrupt | 215 | (5) An interrupt occurs. The exception prologue examines ICC2.Z and |
195 | shouldn't actually have happened. It jumps aside, and there disabled interrupts by setting | 216 | determines that the interrupt shouldn't actually have happened. It |
196 | PSR.PIL to 14 and then it clears ICC2.C. | 217 | jumps aside, and there disabled interrupts by setting PSR.PIL to 14 |
218 | and then it clears ICC2.C. | ||
197 | 219 | ||
198 | (6) If interrupts were then saved and disabled again (local_irq_save): | 220 | (6) If interrupts were then saved and disabled again (local_irq_save): |
199 | 221 | ||
200 | ICC2.Z would be shifted into the save variable and masked off (giving a 1). | 222 | ICC2.Z would be shifted into the save variable and masked off |
223 | (giving a 1). | ||
201 | 224 | ||
202 | ICC2.Z would then be set to 1 (thus unchanged), and ICC2.C would be unaffected (ie: 0). | 225 | ICC2.Z would then be set to 1 (thus unchanged), and ICC2.C would be |
226 | unaffected (ie: 0). | ||
203 | 227 | ||
204 | (7) If interrupts were then restored from state (6) (local_irq_restore): | 228 | (7) If interrupts were then restored from state (6) (local_irq_restore): |
205 | 229 | ||
206 | ICC2.Z would be set to indicate the result of XOR'ing the saved value (ie: 1) with 1, which | 230 | ICC2.Z would be set to indicate the result of XOR'ing the saved |
207 | gives a result of 0 - thus leaving ICC2.Z set. | 231 | value (ie: 1) with 1, which gives a result of 0 - thus leaving |
232 | ICC2.Z set. | ||
208 | 233 | ||
209 | ICC2.C would remain unaffected (ie: 0). | 234 | ICC2.C would remain unaffected (ie: 0). |
210 | 235 | ||
211 | A TIHI #2 instruction would be used to again assay the current state, but this would do | 236 | A TIHI #2 instruction would be used to again assay the current state, |
212 | nothing as Z==1. | 237 | but this would do nothing as Z==1. |
213 | 238 | ||
214 | (8) If interrupts were then enabled (local_irq_enable): | 239 | (8) If interrupts were then enabled (local_irq_enable): |
215 | 240 | ||
216 | ICC2.Z would be cleared. ICC2.C would be left unaffected. Both flags would now be 0. | 241 | ICC2.Z would be cleared. ICC2.C would be left unaffected. Both |
242 | flags would now be 0. | ||
217 | 243 | ||
218 | A TIHI #2 instruction again issued to assay the current state would then trap as both Z==0 | 244 | A TIHI #2 instruction again issued to assay the current state would |
219 | [interrupts virtually enabled] and C==0 [interrupts really disabled] would then be true. | 245 | then trap as both Z==0 [interrupts virtually enabled] and C==0 |
246 | [interrupts really disabled] would then be true. | ||
220 | 247 | ||
221 | (9) The trap #2 handler would simply enable hardware interrupts (set PSR.PIL to 0), set ICC2.C to | 248 | (9) The trap #2 handler would simply enable hardware interrupts |
222 | 1 and return. | 249 | (set PSR.PIL to 0), set ICC2.C to 1 and return. |
223 | 250 | ||
224 | (10) Immediately upon returning, the pending interrupt would be taken. | 251 | (10) Immediately upon returning, the pending interrupt would be taken. |
225 | 252 | ||
226 | (11) The interrupt handler would take the path of actually processing the interrupt (ICC2.Z is | 253 | (11) The interrupt handler would take the path of actually processing the |
227 | clear, BEQ fails as per step (2)). | 254 | interrupt (ICC2.Z is clear, BEQ fails as per step (2)). |
228 | 255 | ||
229 | (12) The interrupt handler would then set ICC2.C to 1 since hardware interrupts are definitely | 256 | (12) The interrupt handler would then set ICC2.C to 1 since hardware |
230 | enabled - or else the kernel wouldn't be here. | 257 | interrupts are definitely enabled - or else the kernel wouldn't be here. |
231 | 258 | ||
232 | (13) On return from the interrupt handler, things would be back to state (1). | 259 | (13) On return from the interrupt handler, things would be back to state (1). |
233 | 260 | ||
234 | This trap (#2) is only available in kernel mode. In user mode it will result in SIGILL. | 261 | This trap (#2) is only available in kernel mode. In user mode it will |
262 | result in SIGILL. | ||
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index f8cb55c30b0f..b3a6187e5305 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
@@ -1,4 +1,4 @@ | |||
1 | February 2003 Kernel Parameters v2.5.59 | 1 | Kernel Parameters |
2 | ~~~~~~~~~~~~~~~~~ | 2 | ~~~~~~~~~~~~~~~~~ |
3 | 3 | ||
4 | The following is a consolidated list of the kernel parameters as implemented | 4 | The following is a consolidated list of the kernel parameters as implemented |
@@ -17,9 +17,17 @@ are specified on the kernel command line with the module name plus | |||
17 | 17 | ||
18 | usbcore.blinkenlights=1 | 18 | usbcore.blinkenlights=1 |
19 | 19 | ||
20 | The text in square brackets at the beginning of the description states the | 20 | This document may not be entirely up to date and comprehensive. The command |
21 | restrictions on the kernel for the said kernel parameter to be valid. The | 21 | "modinfo -p ${modulename}" shows a current list of all parameters of a loadable |
22 | restrictions referred to are that the relevant option is valid if: | 22 | module. Loadable modules, after being loaded into the running kernel, also |
23 | reveal their parameters in /sys/module/${modulename}/parameters/. Some of these | ||
24 | parameters may be changed at runtime by the command | ||
25 | "echo -n ${value} > /sys/module/${modulename}/parameters/${parm}". | ||
26 | |||
27 | The parameters listed below are only valid if certain kernel build options were | ||
28 | enabled and if respective hardware is present. The text in square brackets at | ||
29 | the beginning of each description states the restrictions within which a | ||
30 | parameter is applicable: | ||
23 | 31 | ||
24 | ACPI ACPI support is enabled. | 32 | ACPI ACPI support is enabled. |
25 | ALSA ALSA sound support is enabled. | 33 | ALSA ALSA sound support is enabled. |
@@ -1046,10 +1054,10 @@ running once the system is up. | |||
1046 | noltlbs [PPC] Do not use large page/tlb entries for kernel | 1054 | noltlbs [PPC] Do not use large page/tlb entries for kernel |
1047 | lowmem mapping on PPC40x. | 1055 | lowmem mapping on PPC40x. |
1048 | 1056 | ||
1049 | nomce [IA-32] Machine Check Exception | ||
1050 | |||
1051 | nomca [IA-64] Disable machine check abort handling | 1057 | nomca [IA-64] Disable machine check abort handling |
1052 | 1058 | ||
1059 | nomce [IA-32] Machine Check Exception | ||
1060 | |||
1053 | noresidual [PPC] Don't use residual data on PReP machines. | 1061 | noresidual [PPC] Don't use residual data on PReP machines. |
1054 | 1062 | ||
1055 | noresume [SWSUSP] Disables resume and restores original swap | 1063 | noresume [SWSUSP] Disables resume and restores original swap |
@@ -1682,20 +1690,6 @@ running once the system is up. | |||
1682 | 1690 | ||
1683 | 1691 | ||
1684 | ______________________________________________________________________ | 1692 | ______________________________________________________________________ |
1685 | Changelog: | ||
1686 | |||
1687 | 2000-06-?? Mr. Unknown | ||
1688 | The last known update (for 2.4.0) - the changelog was not kept before. | ||
1689 | |||
1690 | 2002-11-24 Petr Baudis <pasky@ucw.cz> | ||
1691 | Randy Dunlap <randy.dunlap@verizon.net> | ||
1692 | Update for 2.5.49, description for most of the options introduced, | ||
1693 | references to other documentation (C files, READMEs, ..), added S390, | ||
1694 | PPC, SPARC, MTD, ALSA and OSS category. Minor corrections and | ||
1695 | reformatting. | ||
1696 | |||
1697 | 2005-10-19 Randy Dunlap <rdunlap@xenotime.net> | ||
1698 | Lots of typos, whitespace, some reformatting. | ||
1699 | 1693 | ||
1700 | TODO: | 1694 | TODO: |
1701 | 1695 | ||
diff --git a/Documentation/networking/packet_mmap.txt b/Documentation/networking/packet_mmap.txt index 4fc8e9874320..aaf99d5f0dad 100644 --- a/Documentation/networking/packet_mmap.txt +++ b/Documentation/networking/packet_mmap.txt | |||
@@ -254,7 +254,7 @@ and, the number of frames be | |||
254 | 254 | ||
255 | <block number> * <block size> / <frame size> | 255 | <block number> * <block size> / <frame size> |
256 | 256 | ||
257 | Suposse the following parameters, which apply for 2.6 kernel and an | 257 | Suppose the following parameters, which apply for 2.6 kernel and an |
258 | i386 architecture: | 258 | i386 architecture: |
259 | 259 | ||
260 | <size-max> = 131072 bytes | 260 | <size-max> = 131072 bytes |
diff --git a/Documentation/networking/tuntap.txt b/Documentation/networking/tuntap.txt index ec3d109d787a..76750fb9151a 100644 --- a/Documentation/networking/tuntap.txt +++ b/Documentation/networking/tuntap.txt | |||
@@ -138,7 +138,7 @@ This means that you have to read/write IP packets when you are using tun and | |||
138 | ethernet frames when using tap. | 138 | ethernet frames when using tap. |
139 | 139 | ||
140 | 5. What is the difference between BPF and TUN/TAP driver? | 140 | 5. What is the difference between BPF and TUN/TAP driver? |
141 | BFP is an advanced packet filter. It can be attached to existing | 141 | BPF is an advanced packet filter. It can be attached to existing |
142 | network interface. It does not provide a virtual network interface. | 142 | network interface. It does not provide a virtual network interface. |
143 | A TUN/TAP driver does provide a virtual network interface and it is possible | 143 | A TUN/TAP driver does provide a virtual network interface and it is possible |
144 | to attach BPF to this interface. | 144 | to attach BPF to this interface. |
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index 1def6049784c..0ee2c7dfc482 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt | |||
@@ -120,6 +120,34 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. | |||
120 | enable - enable card | 120 | enable - enable card |
121 | - Default: enabled, for PCI and ISA PnP cards | 121 | - Default: enabled, for PCI and ISA PnP cards |
122 | 122 | ||
123 | Module snd-adlib | ||
124 | ---------------- | ||
125 | |||
126 | Module for AdLib FM cards. | ||
127 | |||
128 | port - port # for OPL chip | ||
129 | |||
130 | This module supports multiple cards. It does not support autoprobe, so | ||
131 | the port must be specified. For actual AdLib FM cards it will be 0x388. | ||
132 | Note that this card does not have PCM support and no mixer; only FM | ||
133 | synthesis. | ||
134 | |||
135 | Make sure you have "sbiload" from the alsa-tools package available and, | ||
136 | after loading the module, find out the assigned ALSA sequencer port | ||
137 | number through "sbiload -l". Example output: | ||
138 | |||
139 | Port Client name Port name | ||
140 | 64:0 OPL2 FM synth OPL2 FM Port | ||
141 | |||
142 | Load the std.sb and drums.sb patches also supplied by sbiload: | ||
143 | |||
144 | sbiload -p 64:0 std.sb drums.sb | ||
145 | |||
146 | If you use this driver to drive an OPL3, you can use std.o3 and drums.o3 | ||
147 | instead. To have the card produce sound, use aplaymidi from alsa-utils: | ||
148 | |||
149 | aplaymidi -p 64:0 foo.mid | ||
150 | |||
123 | Module snd-ad1816a | 151 | Module snd-ad1816a |
124 | ------------------ | 152 | ------------------ |
125 | 153 | ||
@@ -190,6 +218,15 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. | |||
190 | 218 | ||
191 | The power-management is supported. | 219 | The power-management is supported. |
192 | 220 | ||
221 | Module snd-als300 | ||
222 | ----------------- | ||
223 | |||
224 | Module for Avance Logic ALS300 and ALS300+ | ||
225 | |||
226 | This module supports multiple cards. | ||
227 | |||
228 | The power-management is supported. | ||
229 | |||
193 | Module snd-als4000 | 230 | Module snd-als4000 |
194 | ------------------ | 231 | ------------------ |
195 | 232 | ||
@@ -701,6 +738,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. | |||
701 | uniwill 3-jack | 738 | uniwill 3-jack |
702 | F1734 2-jack | 739 | F1734 2-jack |
703 | lg LG laptop (m1 express dual) | 740 | lg LG laptop (m1 express dual) |
741 | lg-lw LG LW20 laptop | ||
704 | test for testing/debugging purpose, almost all controls can be | 742 | test for testing/debugging purpose, almost all controls can be |
705 | adjusted. Appearing only when compiled with | 743 | adjusted. Appearing only when compiled with |
706 | $CONFIG_SND_DEBUG=y | 744 | $CONFIG_SND_DEBUG=y |
@@ -1013,6 +1051,23 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. | |||
1013 | 1051 | ||
1014 | The power-management is supported. | 1052 | The power-management is supported. |
1015 | 1053 | ||
1054 | Module snd-miro | ||
1055 | --------------- | ||
1056 | |||
1057 | Module for Miro soundcards: miroSOUND PCM 1 pro, | ||
1058 | miroSOUND PCM 12, | ||
1059 | miroSOUND PCM 20 Radio. | ||
1060 | |||
1061 | port - Port # (0x530,0x604,0xe80,0xf40) | ||
1062 | irq - IRQ # (5,7,9,10,11) | ||
1063 | dma1 - 1st dma # (0,1,3) | ||
1064 | dma2 - 2nd dma # (0,1) | ||
1065 | mpu_port - MPU-401 port # (0x300,0x310,0x320,0x330) | ||
1066 | mpu_irq - MPU-401 irq # (5,7,9,10) | ||
1067 | fm_port - FM Port # (0x388) | ||
1068 | wss - enable WSS mode | ||
1069 | ide - enable onboard ide support | ||
1070 | |||
1016 | Module snd-mixart | 1071 | Module snd-mixart |
1017 | ----------------- | 1072 | ----------------- |
1018 | 1073 | ||
@@ -1202,6 +1257,20 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. | |||
1202 | 1257 | ||
1203 | The power-management is supported. | 1258 | The power-management is supported. |
1204 | 1259 | ||
1260 | Module snd-riptide | ||
1261 | ------------------ | ||
1262 | |||
1263 | Module for Conexant Riptide chip | ||
1264 | |||
1265 | joystick_port - Joystick port # (default: 0x200) | ||
1266 | mpu_port - MPU401 port # (default: 0x330) | ||
1267 | opl3_port - OPL3 port # (default: 0x388) | ||
1268 | |||
1269 | This module supports multiple cards. | ||
1270 | The driver requires the firmware loader support on kernel. | ||
1271 | You need to install the firmware file "riptide.hex" to the standard | ||
1272 | firmware path (e.g. /lib/firmware). | ||
1273 | |||
1205 | Module snd-rme32 | 1274 | Module snd-rme32 |
1206 | ---------------- | 1275 | ---------------- |
1207 | 1276 | ||
diff --git a/arch/arm/configs/at91rm9200dk_defconfig b/arch/arm/configs/at91rm9200dk_defconfig index 1fe73d198888..9e1c1cceb735 100644 --- a/arch/arm/configs/at91rm9200dk_defconfig +++ b/arch/arm/configs/at91rm9200dk_defconfig | |||
@@ -379,7 +379,7 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=2 | |||
379 | # CONFIG_MTD_DOC2001 is not set | 379 | # CONFIG_MTD_DOC2001 is not set |
380 | # CONFIG_MTD_DOC2001PLUS is not set | 380 | # CONFIG_MTD_DOC2001PLUS is not set |
381 | CONFIG_MTD_AT91_DATAFLASH=y | 381 | CONFIG_MTD_AT91_DATAFLASH=y |
382 | CONFIG_MTD_AT91_DATAFLASH_CARD=y | 382 | # CONFIG_MTD_AT91_DATAFLASH_CARD is not set |
383 | 383 | ||
384 | # | 384 | # |
385 | # NAND Flash Device Drivers | 385 | # NAND Flash Device Drivers |
diff --git a/arch/arm/configs/at91rm9200ek_defconfig b/arch/arm/configs/at91rm9200ek_defconfig index b7d934cdb1b7..6e0805a971d7 100644 --- a/arch/arm/configs/at91rm9200ek_defconfig +++ b/arch/arm/configs/at91rm9200ek_defconfig | |||
@@ -370,7 +370,7 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=2 | |||
370 | # CONFIG_MTD_DOC2001 is not set | 370 | # CONFIG_MTD_DOC2001 is not set |
371 | # CONFIG_MTD_DOC2001PLUS is not set | 371 | # CONFIG_MTD_DOC2001PLUS is not set |
372 | CONFIG_MTD_AT91_DATAFLASH=y | 372 | CONFIG_MTD_AT91_DATAFLASH=y |
373 | CONFIG_MTD_AT91_DATAFLASH_CARD=y | 373 | # CONFIG_MTD_AT91_DATAFLASH_CARD is not set |
374 | 374 | ||
375 | # | 375 | # |
376 | # NAND Flash Device Drivers | 376 | # NAND Flash Device Drivers |
diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c index 1574941ebfe1..ee083b3f0522 100644 --- a/arch/arm/kernel/armksyms.c +++ b/arch/arm/kernel/armksyms.c | |||
@@ -100,23 +100,12 @@ EXPORT_SYMBOL(__raw_writesl); | |||
100 | #endif | 100 | #endif |
101 | 101 | ||
102 | /* string / mem functions */ | 102 | /* string / mem functions */ |
103 | EXPORT_SYMBOL(strcpy); | ||
104 | EXPORT_SYMBOL(strncpy); | ||
105 | EXPORT_SYMBOL(strcat); | ||
106 | EXPORT_SYMBOL(strncat); | ||
107 | EXPORT_SYMBOL(strcmp); | ||
108 | EXPORT_SYMBOL(strncmp); | ||
109 | EXPORT_SYMBOL(strchr); | 103 | EXPORT_SYMBOL(strchr); |
110 | EXPORT_SYMBOL(strlen); | ||
111 | EXPORT_SYMBOL(strnlen); | ||
112 | EXPORT_SYMBOL(strpbrk); | 104 | EXPORT_SYMBOL(strpbrk); |
113 | EXPORT_SYMBOL(strrchr); | 105 | EXPORT_SYMBOL(strrchr); |
114 | EXPORT_SYMBOL(strstr); | ||
115 | EXPORT_SYMBOL(memset); | 106 | EXPORT_SYMBOL(memset); |
116 | EXPORT_SYMBOL(memcpy); | 107 | EXPORT_SYMBOL(memcpy); |
117 | EXPORT_SYMBOL(memmove); | 108 | EXPORT_SYMBOL(memmove); |
118 | EXPORT_SYMBOL(memcmp); | ||
119 | EXPORT_SYMBOL(memscan); | ||
120 | EXPORT_SYMBOL(memchr); | 109 | EXPORT_SYMBOL(memchr); |
121 | EXPORT_SYMBOL(__memzero); | 110 | EXPORT_SYMBOL(__memzero); |
122 | 111 | ||
@@ -190,8 +179,6 @@ EXPORT_SYMBOL(_find_next_bit_be); | |||
190 | 179 | ||
191 | /* syscalls */ | 180 | /* syscalls */ |
192 | EXPORT_SYMBOL(sys_write); | 181 | EXPORT_SYMBOL(sys_write); |
193 | EXPORT_SYMBOL(sys_read); | ||
194 | EXPORT_SYMBOL(sys_lseek); | 182 | EXPORT_SYMBOL(sys_lseek); |
195 | EXPORT_SYMBOL(sys_open); | ||
196 | EXPORT_SYMBOL(sys_exit); | 183 | EXPORT_SYMBOL(sys_exit); |
197 | EXPORT_SYMBOL(sys_wait4); | 184 | EXPORT_SYMBOL(sys_wait4); |
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index b7cd280bfd63..437528403959 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c | |||
@@ -252,6 +252,9 @@ static void __init dump_cpu_info(int cpu) | |||
252 | dump_cache("cache", cpu, CACHE_ISIZE(info)); | 252 | dump_cache("cache", cpu, CACHE_ISIZE(info)); |
253 | } | 253 | } |
254 | } | 254 | } |
255 | |||
256 | if (arch_is_coherent()) | ||
257 | printk("Cache coherency enabled\n"); | ||
255 | } | 258 | } |
256 | 259 | ||
257 | int cpu_architecture(void) | 260 | int cpu_architecture(void) |
diff --git a/arch/arm/mach-at91rm9200/Makefile b/arch/arm/mach-at91rm9200/Makefile index 75e6ee318ded..ef88c4128edc 100644 --- a/arch/arm/mach-at91rm9200/Makefile +++ b/arch/arm/mach-at91rm9200/Makefile | |||
@@ -16,11 +16,12 @@ obj-$(CONFIG_MACH_CSB637) += board-csb637.o | |||
16 | #obj-$(CONFIG_MACH_KB9200) += board-kb9202.o | 16 | #obj-$(CONFIG_MACH_KB9200) += board-kb9202.o |
17 | 17 | ||
18 | # LEDs support | 18 | # LEDs support |
19 | #led-$(CONFIG_ARCH_AT91RM9200DK) += leds.o | 19 | led-$(CONFIG_ARCH_AT91RM9200DK) += leds.o |
20 | #led-$(CONFIG_MACH_AT91RM9200EK) += leds.o | 20 | led-$(CONFIG_MACH_AT91RM9200EK) += leds.o |
21 | #led-$(CONFIG_MACH_CSB337) += leds.o | 21 | led-$(CONFIG_MACH_CSB337) += leds.o |
22 | #led-$(CONFIG_MACH_CSB637) += leds.o | 22 | led-$(CONFIG_MACH_CSB637) += leds.o |
23 | #led-$(CONFIG_MACH_KB9200) += leds.o | 23 | #led-$(CONFIG_MACH_KB9200) += leds.o |
24 | #led-$(CONFIG_MACH_KAFA) += leds.o | ||
24 | obj-$(CONFIG_LEDS) += $(led-y) | 25 | obj-$(CONFIG_LEDS) += $(led-y) |
25 | 26 | ||
26 | # VGA support | 27 | # VGA support |
diff --git a/arch/arm/mach-at91rm9200/board-csb337.c b/arch/arm/mach-at91rm9200/board-csb337.c index 54022e58d50d..f45104ceea8f 100644 --- a/arch/arm/mach-at91rm9200/board-csb337.c +++ b/arch/arm/mach-at91rm9200/board-csb337.c | |||
@@ -67,6 +67,9 @@ static void __init csb337_map_io(void) | |||
67 | /* Initialize clocks: 3.6864 MHz crystal */ | 67 | /* Initialize clocks: 3.6864 MHz crystal */ |
68 | at91_clock_init(3686400); | 68 | at91_clock_init(3686400); |
69 | 69 | ||
70 | /* Setup the LEDs */ | ||
71 | at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2); | ||
72 | |||
70 | #ifdef CONFIG_SERIAL_AT91 | 73 | #ifdef CONFIG_SERIAL_AT91 |
71 | at91_console_port = CSB337_SERIAL_CONSOLE; | 74 | at91_console_port = CSB337_SERIAL_CONSOLE; |
72 | memcpy(at91_serial_map, serial, sizeof(serial)); | 75 | memcpy(at91_serial_map, serial, sizeof(serial)); |
diff --git a/arch/arm/mach-at91rm9200/board-csb637.c b/arch/arm/mach-at91rm9200/board-csb637.c index 8195f9d919ea..f2c2d6e79bc6 100644 --- a/arch/arm/mach-at91rm9200/board-csb637.c +++ b/arch/arm/mach-at91rm9200/board-csb637.c | |||
@@ -67,6 +67,9 @@ static void __init csb637_map_io(void) | |||
67 | /* Initialize clocks: 3.6864 MHz crystal */ | 67 | /* Initialize clocks: 3.6864 MHz crystal */ |
68 | at91_clock_init(3686400); | 68 | at91_clock_init(3686400); |
69 | 69 | ||
70 | /* Setup the LEDs */ | ||
71 | at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2); | ||
72 | |||
70 | #ifdef CONFIG_SERIAL_AT91 | 73 | #ifdef CONFIG_SERIAL_AT91 |
71 | at91_console_port = CSB637_SERIAL_CONSOLE; | 74 | at91_console_port = CSB637_SERIAL_CONSOLE; |
72 | memcpy(at91_serial_map, serial, sizeof(serial)); | 75 | memcpy(at91_serial_map, serial, sizeof(serial)); |
diff --git a/arch/arm/mach-at91rm9200/board-dk.c b/arch/arm/mach-at91rm9200/board-dk.c index 8a783368366e..2d7200ed66ed 100644 --- a/arch/arm/mach-at91rm9200/board-dk.c +++ b/arch/arm/mach-at91rm9200/board-dk.c | |||
@@ -70,6 +70,9 @@ static void __init dk_map_io(void) | |||
70 | /* Initialize clocks: 18.432 MHz crystal */ | 70 | /* Initialize clocks: 18.432 MHz crystal */ |
71 | at91_clock_init(18432000); | 71 | at91_clock_init(18432000); |
72 | 72 | ||
73 | /* Setup the LEDs */ | ||
74 | at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2); | ||
75 | |||
73 | #ifdef CONFIG_SERIAL_AT91 | 76 | #ifdef CONFIG_SERIAL_AT91 |
74 | at91_console_port = DK_SERIAL_CONSOLE; | 77 | at91_console_port = DK_SERIAL_CONSOLE; |
75 | memcpy(at91_serial_map, serial, sizeof(serial)); | 78 | memcpy(at91_serial_map, serial, sizeof(serial)); |
@@ -118,9 +121,14 @@ static void __init dk_board_init(void) | |||
118 | at91_add_device_udc(&dk_udc_data); | 121 | at91_add_device_udc(&dk_udc_data); |
119 | /* Compact Flash */ | 122 | /* Compact Flash */ |
120 | at91_add_device_cf(&dk_cf_data); | 123 | at91_add_device_cf(&dk_cf_data); |
124 | #ifdef CONFIG_MTD_AT91_DATAFLASH_CARD | ||
125 | /* DataFlash card */ | ||
126 | at91_set_gpio_output(AT91_PIN_PB7, 0); | ||
127 | #else | ||
121 | /* MMC */ | 128 | /* MMC */ |
122 | at91_set_gpio_output(AT91_PIN_PB7, 1); /* this MMC card slot can optionally use SPI signaling (CS3). default: MMC */ | 129 | at91_set_gpio_output(AT91_PIN_PB7, 1); /* this MMC card slot can optionally use SPI signaling (CS3). */ |
123 | at91_add_device_mmc(&dk_mmc_data); | 130 | at91_add_device_mmc(&dk_mmc_data); |
131 | #endif | ||
124 | /* VGA */ | 132 | /* VGA */ |
125 | // dk_add_device_video(); | 133 | // dk_add_device_video(); |
126 | } | 134 | } |
diff --git a/arch/arm/mach-at91rm9200/board-ek.c b/arch/arm/mach-at91rm9200/board-ek.c index fd0752eba897..80d90f5135a1 100644 --- a/arch/arm/mach-at91rm9200/board-ek.c +++ b/arch/arm/mach-at91rm9200/board-ek.c | |||
@@ -70,6 +70,9 @@ static void __init ek_map_io(void) | |||
70 | /* Initialize clocks: 18.432 MHz crystal */ | 70 | /* Initialize clocks: 18.432 MHz crystal */ |
71 | at91_clock_init(18432000); | 71 | at91_clock_init(18432000); |
72 | 72 | ||
73 | /* Setup the LEDs */ | ||
74 | at91_init_leds(AT91_PIN_PB1, AT91_PIN_PB2); | ||
75 | |||
73 | #ifdef CONFIG_SERIAL_AT91 | 76 | #ifdef CONFIG_SERIAL_AT91 |
74 | at91_console_port = EK_SERIAL_CONSOLE; | 77 | at91_console_port = EK_SERIAL_CONSOLE; |
75 | memcpy(at91_serial_map, serial, sizeof(serial)); | 78 | memcpy(at91_serial_map, serial, sizeof(serial)); |
@@ -111,9 +114,14 @@ static void __init ek_board_init(void) | |||
111 | at91_add_device_usbh(&ek_usbh_data); | 114 | at91_add_device_usbh(&ek_usbh_data); |
112 | /* USB Device */ | 115 | /* USB Device */ |
113 | at91_add_device_udc(&ek_udc_data); | 116 | at91_add_device_udc(&ek_udc_data); |
117 | #ifdef CONFIG_MTD_AT91_DATAFLASH_CARD | ||
118 | /* DataFlash card */ | ||
119 | at91_set_gpio_output(AT91_PIN_PB22, 0); | ||
120 | #else | ||
114 | /* MMC */ | 121 | /* MMC */ |
115 | at91_set_gpio_output(AT91_PIN_PB22, 1); /* this MMC card slot can optionally use SPI signaling (CS3). default: MMC */ | 122 | at91_set_gpio_output(AT91_PIN_PB22, 1); /* this MMC card slot can optionally use SPI signaling (CS3). */ |
116 | at91_add_device_mmc(&ek_mmc_data); | 123 | at91_add_device_mmc(&ek_mmc_data); |
124 | #endif | ||
117 | /* VGA */ | 125 | /* VGA */ |
118 | // ek_add_device_video(); | 126 | // ek_add_device_video(); |
119 | } | 127 | } |
diff --git a/arch/arm/mach-at91rm9200/devices.c b/arch/arm/mach-at91rm9200/devices.c index 57eedd5beaf6..1781b8f342c4 100644 --- a/arch/arm/mach-at91rm9200/devices.c +++ b/arch/arm/mach-at91rm9200/devices.c | |||
@@ -28,10 +28,10 @@ | |||
28 | static u64 ohci_dmamask = 0xffffffffUL; | 28 | static u64 ohci_dmamask = 0xffffffffUL; |
29 | static struct at91_usbh_data usbh_data; | 29 | static struct at91_usbh_data usbh_data; |
30 | 30 | ||
31 | static struct resource at91rm9200_usbh_resource[] = { | 31 | static struct resource at91_usbh_resource[] = { |
32 | [0] = { | 32 | [0] = { |
33 | .start = AT91_UHP_BASE, | 33 | .start = AT91_UHP_BASE, |
34 | .end = AT91_UHP_BASE + SZ_1M -1, | 34 | .end = AT91_UHP_BASE + SZ_1M - 1, |
35 | .flags = IORESOURCE_MEM, | 35 | .flags = IORESOURCE_MEM, |
36 | }, | 36 | }, |
37 | [1] = { | 37 | [1] = { |
@@ -49,8 +49,8 @@ static struct platform_device at91rm9200_usbh_device = { | |||
49 | .coherent_dma_mask = 0xffffffff, | 49 | .coherent_dma_mask = 0xffffffff, |
50 | .platform_data = &usbh_data, | 50 | .platform_data = &usbh_data, |
51 | }, | 51 | }, |
52 | .resource = at91rm9200_usbh_resource, | 52 | .resource = at91_usbh_resource, |
53 | .num_resources = ARRAY_SIZE(at91rm9200_usbh_resource), | 53 | .num_resources = ARRAY_SIZE(at91_usbh_resource), |
54 | }; | 54 | }; |
55 | 55 | ||
56 | void __init at91_add_device_usbh(struct at91_usbh_data *data) | 56 | void __init at91_add_device_usbh(struct at91_usbh_data *data) |
@@ -121,6 +121,19 @@ void __init at91_add_device_udc(struct at91_udc_data *data) {} | |||
121 | static u64 eth_dmamask = 0xffffffffUL; | 121 | static u64 eth_dmamask = 0xffffffffUL; |
122 | static struct at91_eth_data eth_data; | 122 | static struct at91_eth_data eth_data; |
123 | 123 | ||
124 | static struct resource at91_eth_resources[] = { | ||
125 | [0] = { | ||
126 | .start = AT91_BASE_EMAC, | ||
127 | .end = AT91_BASE_EMAC + SZ_16K - 1, | ||
128 | .flags = IORESOURCE_MEM, | ||
129 | }, | ||
130 | [1] = { | ||
131 | .start = AT91_ID_EMAC, | ||
132 | .end = AT91_ID_EMAC, | ||
133 | .flags = IORESOURCE_IRQ, | ||
134 | }, | ||
135 | }; | ||
136 | |||
124 | static struct platform_device at91rm9200_eth_device = { | 137 | static struct platform_device at91rm9200_eth_device = { |
125 | .name = "at91_ether", | 138 | .name = "at91_ether", |
126 | .id = -1, | 139 | .id = -1, |
@@ -129,7 +142,8 @@ static struct platform_device at91rm9200_eth_device = { | |||
129 | .coherent_dma_mask = 0xffffffff, | 142 | .coherent_dma_mask = 0xffffffff, |
130 | .platform_data = ð_data, | 143 | .platform_data = ð_data, |
131 | }, | 144 | }, |
132 | .num_resources = 0, | 145 | .resource = at91_eth_resources, |
146 | .num_resources = ARRAY_SIZE(at91_eth_resources), | ||
133 | }; | 147 | }; |
134 | 148 | ||
135 | void __init at91_add_device_eth(struct at91_eth_data *data) | 149 | void __init at91_add_device_eth(struct at91_eth_data *data) |
@@ -224,15 +238,20 @@ static u64 mmc_dmamask = 0xffffffffUL; | |||
224 | static struct at91_mmc_data mmc_data; | 238 | static struct at91_mmc_data mmc_data; |
225 | 239 | ||
226 | static struct resource at91_mmc_resources[] = { | 240 | static struct resource at91_mmc_resources[] = { |
227 | { | 241 | [0] = { |
228 | .start = AT91_BASE_MCI, | 242 | .start = AT91_BASE_MCI, |
229 | .end = AT91_BASE_MCI + SZ_16K - 1, | 243 | .end = AT91_BASE_MCI + SZ_16K - 1, |
230 | .flags = IORESOURCE_MEM, | 244 | .flags = IORESOURCE_MEM, |
231 | } | 245 | }, |
246 | [1] = { | ||
247 | .start = AT91_ID_MCI, | ||
248 | .end = AT91_ID_MCI, | ||
249 | .flags = IORESOURCE_IRQ, | ||
250 | }, | ||
232 | }; | 251 | }; |
233 | 252 | ||
234 | static struct platform_device at91rm9200_mmc_device = { | 253 | static struct platform_device at91rm9200_mmc_device = { |
235 | .name = "at91rm9200_mci", | 254 | .name = "at91_mci", |
236 | .id = -1, | 255 | .id = -1, |
237 | .dev = { | 256 | .dev = { |
238 | .dma_mask = &mmc_dmamask, | 257 | .dma_mask = &mmc_dmamask, |
@@ -290,4 +309,123 @@ void __init at91_add_device_mmc(struct at91_mmc_data *data) | |||
290 | void __init at91_add_device_mmc(struct at91_mmc_data *data) {} | 309 | void __init at91_add_device_mmc(struct at91_mmc_data *data) {} |
291 | #endif | 310 | #endif |
292 | 311 | ||
312 | /* -------------------------------------------------------------------- | ||
313 | * NAND / SmartMedia | ||
314 | * -------------------------------------------------------------------- */ | ||
315 | |||
316 | #if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE) | ||
317 | static struct at91_nand_data nand_data; | ||
318 | |||
319 | static struct resource at91_nand_resources[] = { | ||
320 | { | ||
321 | .start = AT91_SMARTMEDIA_BASE, | ||
322 | .end = AT91_SMARTMEDIA_BASE + SZ_8M - 1, | ||
323 | .flags = IORESOURCE_MEM, | ||
324 | } | ||
325 | }; | ||
326 | |||
327 | static struct platform_device at91_nand_device = { | ||
328 | .name = "at91_nand", | ||
329 | .id = -1, | ||
330 | .dev = { | ||
331 | .platform_data = &nand_data, | ||
332 | }, | ||
333 | .resource = at91_nand_resources, | ||
334 | .num_resources = ARRAY_SIZE(at91_nand_resources), | ||
335 | }; | ||
336 | |||
337 | void __init at91_add_device_nand(struct at91_nand_data *data) | ||
338 | { | ||
339 | if (!data) | ||
340 | return; | ||
341 | |||
342 | /* enable pin */ | ||
343 | if (data->enable_pin) | ||
344 | at91_set_gpio_output(data->enable_pin, 1); | ||
345 | |||
346 | /* ready/busy pin */ | ||
347 | if (data->rdy_pin) | ||
348 | at91_set_gpio_input(data->rdy_pin, 1); | ||
349 | |||
350 | /* card detect pin */ | ||
351 | if (data->det_pin) | ||
352 | at91_set_gpio_input(data->det_pin, 1); | ||
353 | |||
354 | at91_set_A_periph(AT91_PIN_PC1, 0); /* SMOE */ | ||
355 | at91_set_A_periph(AT91_PIN_PC3, 0); /* SMWE */ | ||
356 | |||
357 | nand_data = *data; | ||
358 | platform_device_register(&at91_nand_device); | ||
359 | } | ||
360 | #else | ||
361 | void __init at91_add_device_nand(struct at91_nand_data *data) {} | ||
362 | #endif | ||
363 | |||
364 | |||
365 | /* -------------------------------------------------------------------- | ||
366 | * TWI (i2c) | ||
367 | * -------------------------------------------------------------------- */ | ||
368 | |||
369 | #if defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE) | ||
370 | static struct platform_device at91rm9200_twi_device = { | ||
371 | .name = "at91_i2c", | ||
372 | .id = -1, | ||
373 | .num_resources = 0, | ||
374 | }; | ||
375 | |||
376 | void __init at91_add_device_i2c(void) | ||
377 | { | ||
378 | /* pins used for TWI interface */ | ||
379 | at91_set_A_periph(AT91_PIN_PA25, 0); /* TWD */ | ||
380 | at91_set_multi_drive(AT91_PIN_PA25, 1); | ||
381 | |||
382 | at91_set_A_periph(AT91_PIN_PA26, 0); /* TWCK */ | ||
383 | at91_set_multi_drive(AT91_PIN_PA26, 1); | ||
384 | |||
385 | platform_device_register(&at91rm9200_twi_device); | ||
386 | } | ||
387 | #else | ||
388 | void __init at91_add_device_i2c(void) {} | ||
389 | #endif | ||
390 | |||
391 | |||
392 | /* -------------------------------------------------------------------- | ||
393 | * RTC | ||
394 | * -------------------------------------------------------------------- */ | ||
395 | |||
396 | #if defined(CONFIG_AT91_RTC) || defined(CONFIG_AT91_RTC_MODULE) | ||
397 | static struct platform_device at91rm9200_rtc_device = { | ||
398 | .name = "at91_rtc", | ||
399 | .id = -1, | ||
400 | .num_resources = 0, | ||
401 | }; | ||
402 | |||
403 | void __init at91_add_device_rtc(void) | ||
404 | { | ||
405 | platform_device_register(&at91rm9200_rtc_device); | ||
406 | } | ||
407 | #else | ||
408 | void __init at91_add_device_rtc(void) {} | ||
409 | #endif | ||
410 | |||
411 | |||
412 | /* -------------------------------------------------------------------- | ||
413 | * LEDs | ||
414 | * -------------------------------------------------------------------- */ | ||
415 | |||
416 | #if defined(CONFIG_LEDS) | ||
417 | u8 at91_leds_cpu; | ||
418 | u8 at91_leds_timer; | ||
419 | |||
420 | void __init at91_init_leds(u8 cpu_led, u8 timer_led) | ||
421 | { | ||
422 | at91_leds_cpu = cpu_led; | ||
423 | at91_leds_timer = timer_led; | ||
424 | } | ||
425 | |||
426 | #else | ||
427 | void __init at91_init_leds(u8 cpu_led, u8 timer_led) {} | ||
428 | #endif | ||
429 | |||
430 | |||
293 | /* -------------------------------------------------------------------- */ | 431 | /* -------------------------------------------------------------------- */ |
diff --git a/arch/arm/mach-at91rm9200/leds.c b/arch/arm/mach-at91rm9200/leds.c new file mode 100644 index 000000000000..28150e8905ba --- /dev/null +++ b/arch/arm/mach-at91rm9200/leds.c | |||
@@ -0,0 +1,100 @@ | |||
1 | /* | ||
2 | * LED driver for Atmel AT91-based boards. | ||
3 | * | ||
4 | * Copyright (C) SAN People (Pty) Ltd | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/config.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/init.h> | ||
16 | |||
17 | #include <asm/mach-types.h> | ||
18 | #include <asm/leds.h> | ||
19 | #include <asm/arch/board.h> | ||
20 | #include <asm/arch/gpio.h> | ||
21 | |||
22 | |||
23 | static inline void at91_led_on(unsigned int led) | ||
24 | { | ||
25 | at91_set_gpio_value(led, 0); | ||
26 | } | ||
27 | |||
28 | static inline void at91_led_off(unsigned int led) | ||
29 | { | ||
30 | at91_set_gpio_value(led, 1); | ||
31 | } | ||
32 | |||
33 | static inline void at91_led_toggle(unsigned int led) | ||
34 | { | ||
35 | unsigned long is_off = at91_get_gpio_value(led); | ||
36 | if (is_off) | ||
37 | at91_led_on(led); | ||
38 | else | ||
39 | at91_led_off(led); | ||
40 | } | ||
41 | |||
42 | |||
43 | /* | ||
44 | * Handle LED events. | ||
45 | */ | ||
46 | static void at91_leds_event(led_event_t evt) | ||
47 | { | ||
48 | unsigned long flags; | ||
49 | |||
50 | local_irq_save(flags); | ||
51 | |||
52 | switch(evt) { | ||
53 | case led_start: /* System startup */ | ||
54 | at91_led_on(at91_leds_cpu); | ||
55 | break; | ||
56 | |||
57 | case led_stop: /* System stop / suspend */ | ||
58 | at91_led_off(at91_leds_cpu); | ||
59 | break; | ||
60 | |||
61 | #ifdef CONFIG_LEDS_TIMER | ||
62 | case led_timer: /* Every 50 timer ticks */ | ||
63 | at91_led_toggle(at91_leds_timer); | ||
64 | break; | ||
65 | #endif | ||
66 | |||
67 | #ifdef CONFIG_LEDS_CPU | ||
68 | case led_idle_start: /* Entering idle state */ | ||
69 | at91_led_off(at91_leds_cpu); | ||
70 | break; | ||
71 | |||
72 | case led_idle_end: /* Exit idle state */ | ||
73 | at91_led_on(at91_leds_cpu); | ||
74 | break; | ||
75 | #endif | ||
76 | |||
77 | default: | ||
78 | break; | ||
79 | } | ||
80 | |||
81 | local_irq_restore(flags); | ||
82 | } | ||
83 | |||
84 | |||
85 | static int __init leds_init(void) | ||
86 | { | ||
87 | if (!at91_leds_timer || !at91_leds_cpu) | ||
88 | return -ENODEV; | ||
89 | |||
90 | /* Enable PIO to access the LEDs */ | ||
91 | at91_set_gpio_output(at91_leds_timer, 1); | ||
92 | at91_set_gpio_output(at91_leds_cpu, 1); | ||
93 | |||
94 | leds_event = at91_leds_event; | ||
95 | |||
96 | leds_event(led_start); | ||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | __initcall(leds_init); | ||
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index 2d892e4daa07..dcd417625389 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c | |||
@@ -424,6 +424,14 @@ static struct amba_device uart3_device = { | |||
424 | .periphid = 0x00041010, | 424 | .periphid = 0x00041010, |
425 | }; | 425 | }; |
426 | 426 | ||
427 | |||
428 | static struct platform_device ep93xx_rtc_device = { | ||
429 | .name = "ep93xx-rtc", | ||
430 | .id = -1, | ||
431 | .num_resources = 0, | ||
432 | }; | ||
433 | |||
434 | |||
427 | void __init ep93xx_init_devices(void) | 435 | void __init ep93xx_init_devices(void) |
428 | { | 436 | { |
429 | unsigned int v; | 437 | unsigned int v; |
@@ -439,4 +447,6 @@ void __init ep93xx_init_devices(void) | |||
439 | amba_device_register(&uart1_device, &iomem_resource); | 447 | amba_device_register(&uart1_device, &iomem_resource); |
440 | amba_device_register(&uart2_device, &iomem_resource); | 448 | amba_device_register(&uart2_device, &iomem_resource); |
441 | amba_device_register(&uart3_device, &iomem_resource); | 449 | amba_device_register(&uart3_device, &iomem_resource); |
450 | |||
451 | platform_device_register(&ep93xx_rtc_device); | ||
442 | } | 452 | } |
diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c index 777e75daa8a5..9be01b0c3f48 100644 --- a/arch/arm/mach-ep93xx/ts72xx.c +++ b/arch/arm/mach-ep93xx/ts72xx.c | |||
@@ -17,6 +17,8 @@ | |||
17 | #include <linux/sched.h> | 17 | #include <linux/sched.h> |
18 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
19 | #include <linux/mtd/physmap.h> | 19 | #include <linux/mtd/physmap.h> |
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/m48t86.h> | ||
20 | #include <asm/io.h> | 22 | #include <asm/io.h> |
21 | #include <asm/hardware.h> | 23 | #include <asm/hardware.h> |
22 | #include <asm/mach-types.h> | 24 | #include <asm/mach-types.h> |
@@ -39,6 +41,16 @@ static struct map_desc ts72xx_io_desc[] __initdata = { | |||
39 | .pfn = __phys_to_pfn(TS72XX_OPTIONS2_PHYS_BASE), | 41 | .pfn = __phys_to_pfn(TS72XX_OPTIONS2_PHYS_BASE), |
40 | .length = TS72XX_OPTIONS2_SIZE, | 42 | .length = TS72XX_OPTIONS2_SIZE, |
41 | .type = MT_DEVICE, | 43 | .type = MT_DEVICE, |
44 | }, { | ||
45 | .virtual = TS72XX_RTC_INDEX_VIRT_BASE, | ||
46 | .pfn = __phys_to_pfn(TS72XX_RTC_INDEX_PHYS_BASE), | ||
47 | .length = TS72XX_RTC_INDEX_SIZE, | ||
48 | .type = MT_DEVICE, | ||
49 | }, { | ||
50 | .virtual = TS72XX_RTC_DATA_VIRT_BASE, | ||
51 | .pfn = __phys_to_pfn(TS72XX_RTC_DATA_PHYS_BASE), | ||
52 | .length = TS72XX_RTC_DATA_SIZE, | ||
53 | .type = MT_DEVICE, | ||
42 | } | 54 | } |
43 | }; | 55 | }; |
44 | 56 | ||
@@ -99,11 +111,38 @@ static void __init ts72xx_map_io(void) | |||
99 | } | 111 | } |
100 | } | 112 | } |
101 | 113 | ||
114 | static unsigned char ts72xx_rtc_readb(unsigned long addr) | ||
115 | { | ||
116 | __raw_writeb(addr, TS72XX_RTC_INDEX_VIRT_BASE); | ||
117 | return __raw_readb(TS72XX_RTC_DATA_VIRT_BASE); | ||
118 | } | ||
119 | |||
120 | static void ts72xx_rtc_writeb(unsigned char value, unsigned long addr) | ||
121 | { | ||
122 | __raw_writeb(addr, TS72XX_RTC_INDEX_VIRT_BASE); | ||
123 | __raw_writeb(value, TS72XX_RTC_DATA_VIRT_BASE); | ||
124 | } | ||
125 | |||
126 | static struct m48t86_ops ts72xx_rtc_ops = { | ||
127 | .readb = ts72xx_rtc_readb, | ||
128 | .writeb = ts72xx_rtc_writeb, | ||
129 | }; | ||
130 | |||
131 | static struct platform_device ts72xx_rtc_device = { | ||
132 | .name = "rtc-m48t86", | ||
133 | .id = -1, | ||
134 | .dev = { | ||
135 | .platform_data = &ts72xx_rtc_ops, | ||
136 | }, | ||
137 | .num_resources = 0, | ||
138 | }; | ||
139 | |||
102 | static void __init ts72xx_init_machine(void) | 140 | static void __init ts72xx_init_machine(void) |
103 | { | 141 | { |
104 | ep93xx_init_devices(); | 142 | ep93xx_init_devices(); |
105 | if (board_is_ts7200()) | 143 | if (board_is_ts7200()) |
106 | physmap_configure(TS72XX_NOR_PHYS_BASE, 0x01000000, 1, NULL); | 144 | physmap_configure(TS72XX_NOR_PHYS_BASE, 0x01000000, 1, NULL); |
145 | platform_device_register(&ts72xx_rtc_device); | ||
107 | } | 146 | } |
108 | 147 | ||
109 | MACHINE_START(TS72XX, "Technologic Systems TS-72xx SBC") | 148 | MACHINE_START(TS72XX, "Technologic Systems TS-72xx SBC") |
diff --git a/arch/arm/mach-imx/dma.c b/arch/arm/mach-imx/dma.c index 71a59e196166..4ca51dcf13ac 100644 --- a/arch/arm/mach-imx/dma.c +++ b/arch/arm/mach-imx/dma.c | |||
@@ -7,11 +7,18 @@ | |||
7 | * it under the terms of the GNU General Public License version 2 as | 7 | * it under the terms of the GNU General Public License version 2 as |
8 | * published by the Free Software Foundation. | 8 | * published by the Free Software Foundation. |
9 | * | 9 | * |
10 | * 03/03/2004 Sascha Hauer <sascha@saschahauer.de> | 10 | * 2004-03-03 Sascha Hauer <sascha@saschahauer.de> |
11 | * initial version heavily inspired by | 11 | * initial version heavily inspired by |
12 | * linux/arch/arm/mach-pxa/dma.c | 12 | * linux/arch/arm/mach-pxa/dma.c |
13 | * | ||
14 | * 2005-04-17 Pavel Pisa <pisa@cmp.felk.cvut.cz> | ||
15 | * Changed to support scatter gather DMA | ||
16 | * by taking Russell's code from RiscPC | ||
17 | * | ||
13 | */ | 18 | */ |
14 | 19 | ||
20 | #undef DEBUG | ||
21 | |||
15 | #include <linux/module.h> | 22 | #include <linux/module.h> |
16 | #include <linux/init.h> | 23 | #include <linux/init.h> |
17 | #include <linux/kernel.h> | 24 | #include <linux/kernel.h> |
@@ -22,69 +29,368 @@ | |||
22 | #include <asm/irq.h> | 29 | #include <asm/irq.h> |
23 | #include <asm/hardware.h> | 30 | #include <asm/hardware.h> |
24 | #include <asm/dma.h> | 31 | #include <asm/dma.h> |
32 | #include <asm/arch/imx-dma.h> | ||
33 | |||
34 | struct imx_dma_channel imx_dma_channels[IMX_DMA_CHANNELS]; | ||
35 | |||
36 | /* | ||
37 | * imx_dma_sg_next - prepare next chunk for scatter-gather DMA emulation | ||
38 | * @dma_ch: i.MX DMA channel number | ||
39 | * @lastcount: number of bytes transferred during last transfer | ||
40 | * | ||
41 | * Functions prepares DMA controller for next sg data chunk transfer. | ||
42 | * The @lastcount argument informs function about number of bytes transferred | ||
43 | * during last block. Zero value can be used for @lastcount to setup DMA | ||
44 | * for the first chunk. | ||
45 | */ | ||
46 | static inline int imx_dma_sg_next(imx_dmach_t dma_ch, unsigned int lastcount) | ||
47 | { | ||
48 | struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch]; | ||
49 | unsigned int nextcount; | ||
50 | unsigned int nextaddr; | ||
51 | |||
52 | if (!imxdma->name) { | ||
53 | printk(KERN_CRIT "%s: called for not allocated channel %d\n", | ||
54 | __FUNCTION__, dma_ch); | ||
55 | return 0; | ||
56 | } | ||
57 | |||
58 | imxdma->resbytes -= lastcount; | ||
59 | |||
60 | if (!imxdma->sg) { | ||
61 | pr_debug("imxdma%d: no sg data\n", dma_ch); | ||
62 | return 0; | ||
63 | } | ||
64 | |||
65 | imxdma->sgbc += lastcount; | ||
66 | if ((imxdma->sgbc >= imxdma->sg->length) || !imxdma->resbytes) { | ||
67 | if ((imxdma->sgcount <= 1) || !imxdma->resbytes) { | ||
68 | pr_debug("imxdma%d: sg transfer limit reached\n", | ||
69 | dma_ch); | ||
70 | imxdma->sgcount=0; | ||
71 | imxdma->sg = NULL; | ||
72 | return 0; | ||
73 | } else { | ||
74 | imxdma->sgcount--; | ||
75 | imxdma->sg++; | ||
76 | imxdma->sgbc = 0; | ||
77 | } | ||
78 | } | ||
79 | nextcount = imxdma->sg->length - imxdma->sgbc; | ||
80 | nextaddr = imxdma->sg->dma_address + imxdma->sgbc; | ||
25 | 81 | ||
26 | static struct dma_channel { | 82 | if(imxdma->resbytes < nextcount) |
27 | char *name; | 83 | nextcount = imxdma->resbytes; |
28 | void (*irq_handler) (int, void *, struct pt_regs *); | ||
29 | void (*err_handler) (int, void *, struct pt_regs *); | ||
30 | void *data; | ||
31 | } dma_channels[11]; | ||
32 | 84 | ||
33 | /* set err_handler to NULL to have the standard info-only error handler */ | 85 | if ((imxdma->dma_mode & DMA_MODE_MASK) == DMA_MODE_READ) |
86 | DAR(dma_ch) = nextaddr; | ||
87 | else | ||
88 | SAR(dma_ch) = nextaddr; | ||
89 | |||
90 | CNTR(dma_ch) = nextcount; | ||
91 | pr_debug("imxdma%d: next sg chunk dst 0x%08x, src 0x%08x, size 0x%08x\n", | ||
92 | dma_ch, DAR(dma_ch), SAR(dma_ch), CNTR(dma_ch)); | ||
93 | |||
94 | return nextcount; | ||
95 | } | ||
96 | |||
97 | /* | ||
98 | * imx_dma_setup_sg_base - scatter-gather DMA emulation | ||
99 | * @dma_ch: i.MX DMA channel number | ||
100 | * @sg: pointer to the scatter-gather list/vector | ||
101 | * @sgcount: scatter-gather list hungs count | ||
102 | * | ||
103 | * Functions sets up i.MX DMA state for emulated scatter-gather transfer | ||
104 | * and sets up channel registers to be ready for the first chunk | ||
105 | */ | ||
106 | static int | ||
107 | imx_dma_setup_sg_base(imx_dmach_t dma_ch, | ||
108 | struct scatterlist *sg, unsigned int sgcount) | ||
109 | { | ||
110 | struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch]; | ||
111 | |||
112 | imxdma->sg = sg; | ||
113 | imxdma->sgcount = sgcount; | ||
114 | imxdma->sgbc = 0; | ||
115 | return imx_dma_sg_next(dma_ch, 0); | ||
116 | } | ||
117 | |||
118 | /** | ||
119 | * imx_dma_setup_single - setup i.MX DMA channel for linear memory to/from device transfer | ||
120 | * @dma_ch: i.MX DMA channel number | ||
121 | * @dma_address: the DMA/physical memory address of the linear data block | ||
122 | * to transfer | ||
123 | * @dma_length: length of the data block in bytes | ||
124 | * @dev_addr: physical device port address | ||
125 | * @dmamode: DMA transfer mode, %DMA_MODE_READ from the device to the memory | ||
126 | * or %DMA_MODE_WRITE from memory to the device | ||
127 | * | ||
128 | * The function setups DMA channel source and destination addresses for transfer | ||
129 | * specified by provided parameters. The scatter-gather emulation is disabled, | ||
130 | * because linear data block | ||
131 | * form the physical address range is transfered. | ||
132 | * Return value: if incorrect parameters are provided -%EINVAL. | ||
133 | * Zero indicates success. | ||
134 | */ | ||
34 | int | 135 | int |
35 | imx_request_dma(char *name, imx_dma_prio prio, | 136 | imx_dma_setup_single(imx_dmach_t dma_ch, dma_addr_t dma_address, |
36 | void (*irq_handler) (int, void *, struct pt_regs *), | 137 | unsigned int dma_length, unsigned int dev_addr, |
37 | void (*err_handler) (int, void *, struct pt_regs *), void *data) | 138 | dmamode_t dmamode) |
38 | { | 139 | { |
39 | unsigned long flags; | 140 | struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch]; |
40 | int i, found = 0; | ||
41 | 141 | ||
42 | /* basic sanity checks */ | 142 | imxdma->sg = NULL; |
43 | if (!name || !irq_handler) | 143 | imxdma->sgcount = 0; |
144 | imxdma->dma_mode = dmamode; | ||
145 | imxdma->resbytes = dma_length; | ||
146 | |||
147 | if (!dma_address) { | ||
148 | printk(KERN_ERR "imxdma%d: imx_dma_setup_single null address\n", | ||
149 | dma_ch); | ||
44 | return -EINVAL; | 150 | return -EINVAL; |
151 | } | ||
45 | 152 | ||
46 | local_irq_save(flags); | 153 | if (!dma_length) { |
154 | printk(KERN_ERR "imxdma%d: imx_dma_setup_single zero length\n", | ||
155 | dma_ch); | ||
156 | return -EINVAL; | ||
157 | } | ||
47 | 158 | ||
48 | /* try grabbing a DMA channel with the requested priority */ | 159 | if ((dmamode & DMA_MODE_MASK) == DMA_MODE_READ) { |
49 | for (i = prio; i < prio + (prio == DMA_PRIO_LOW) ? 8 : 4; i++) { | 160 | pr_debug("imxdma%d: mx_dma_setup_single2dev dma_addressg=0x%08x dma_length=%d dev_addr=0x%08x for read\n", |
50 | if (!dma_channels[i].name) { | 161 | dma_ch, (unsigned int)dma_address, dma_length, |
51 | found = 1; | 162 | dev_addr); |
52 | break; | 163 | SAR(dma_ch) = dev_addr; |
53 | } | 164 | DAR(dma_ch) = (unsigned int)dma_address; |
165 | } else if ((dmamode & DMA_MODE_MASK) == DMA_MODE_WRITE) { | ||
166 | pr_debug("imxdma%d: mx_dma_setup_single2dev dma_addressg=0x%08x dma_length=%d dev_addr=0x%08x for write\n", | ||
167 | dma_ch, (unsigned int)dma_address, dma_length, | ||
168 | dev_addr); | ||
169 | SAR(dma_ch) = (unsigned int)dma_address; | ||
170 | DAR(dma_ch) = dev_addr; | ||
171 | } else { | ||
172 | printk(KERN_ERR "imxdma%d: imx_dma_setup_single bad dmamode\n", | ||
173 | dma_ch); | ||
174 | return -EINVAL; | ||
54 | } | 175 | } |
55 | 176 | ||
56 | if (!found) { | 177 | CNTR(dma_ch) = dma_length; |
57 | /* requested prio group is full, try hier priorities */ | 178 | |
58 | for (i = prio - 1; i >= 0; i--) { | 179 | return 0; |
59 | if (!dma_channels[i].name) { | 180 | } |
60 | found = 1; | 181 | |
61 | break; | 182 | /** |
62 | } | 183 | * imx_dma_setup_sg - setup i.MX DMA channel SG list to/from device transfer |
63 | } | 184 | * @dma_ch: i.MX DMA channel number |
185 | * @sg: pointer to the scatter-gather list/vector | ||
186 | * @sgcount: scatter-gather list hungs count | ||
187 | * @dma_length: total length of the transfer request in bytes | ||
188 | * @dev_addr: physical device port address | ||
189 | * @dmamode: DMA transfer mode, %DMA_MODE_READ from the device to the memory | ||
190 | * or %DMA_MODE_WRITE from memory to the device | ||
191 | * | ||
192 | * The function setups DMA channel state and registers to be ready for transfer | ||
193 | * specified by provided parameters. The scatter-gather emulation is set up | ||
194 | * according to the parameters. | ||
195 | * | ||
196 | * The full preparation of the transfer requires setup of more register | ||
197 | * by the caller before imx_dma_enable() can be called. | ||
198 | * | ||
199 | * %BLR(dma_ch) holds transfer burst length in bytes, 0 means 64 bytes | ||
200 | * | ||
201 | * %RSSR(dma_ch) has to be set to the DMA request line source %DMA_REQ_xxx | ||
202 | * | ||
203 | * %CCR(dma_ch) has to specify transfer parameters, the next settings is typical | ||
204 | * for linear or simple scatter-gather transfers if %DMA_MODE_READ is specified | ||
205 | * | ||
206 | * %CCR_DMOD_LINEAR | %CCR_DSIZ_32 | %CCR_SMOD_FIFO | %CCR_SSIZ_x | ||
207 | * | ||
208 | * The typical setup for %DMA_MODE_WRITE is specified by next options combination | ||
209 | * | ||
210 | * %CCR_SMOD_LINEAR | %CCR_SSIZ_32 | %CCR_DMOD_FIFO | %CCR_DSIZ_x | ||
211 | * | ||
212 | * Be carefull there and do not mistakenly mix source and target device | ||
213 | * port sizes constants, they are really different: | ||
214 | * %CCR_SSIZ_8, %CCR_SSIZ_16, %CCR_SSIZ_32, | ||
215 | * %CCR_DSIZ_8, %CCR_DSIZ_16, %CCR_DSIZ_32 | ||
216 | * | ||
217 | * Return value: if incorrect parameters are provided -%EINVAL. | ||
218 | * Zero indicates success. | ||
219 | */ | ||
220 | int | ||
221 | imx_dma_setup_sg(imx_dmach_t dma_ch, | ||
222 | struct scatterlist *sg, unsigned int sgcount, unsigned int dma_length, | ||
223 | unsigned int dev_addr, dmamode_t dmamode) | ||
224 | { | ||
225 | int res; | ||
226 | struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch]; | ||
227 | |||
228 | imxdma->sg = NULL; | ||
229 | imxdma->sgcount = 0; | ||
230 | imxdma->dma_mode = dmamode; | ||
231 | imxdma->resbytes = dma_length; | ||
232 | |||
233 | if (!sg || !sgcount) { | ||
234 | printk(KERN_ERR "imxdma%d: imx_dma_setup_sg epty sg list\n", | ||
235 | dma_ch); | ||
236 | return -EINVAL; | ||
237 | } | ||
238 | |||
239 | if (!sg->length) { | ||
240 | printk(KERN_ERR "imxdma%d: imx_dma_setup_sg zero length\n", | ||
241 | dma_ch); | ||
242 | return -EINVAL; | ||
64 | } | 243 | } |
65 | 244 | ||
66 | if (found) { | 245 | if ((dmamode & DMA_MODE_MASK) == DMA_MODE_READ) { |
67 | DIMR &= ~(1 << i); | 246 | pr_debug("imxdma%d: mx_dma_setup_sg2dev sg=%p sgcount=%d total length=%d dev_addr=0x%08x for read\n", |
68 | dma_channels[i].name = name; | 247 | dma_ch, sg, sgcount, dma_length, dev_addr); |
69 | dma_channels[i].irq_handler = irq_handler; | 248 | SAR(dma_ch) = dev_addr; |
70 | dma_channels[i].err_handler = err_handler; | 249 | } else if ((dmamode & DMA_MODE_MASK) == DMA_MODE_WRITE) { |
71 | dma_channels[i].data = data; | 250 | pr_debug("imxdma%d: mx_dma_setup_sg2dev sg=%p sgcount=%d total length=%d dev_addr=0x%08x for write\n", |
251 | dma_ch, sg, sgcount, dma_length, dev_addr); | ||
252 | DAR(dma_ch) = dev_addr; | ||
72 | } else { | 253 | } else { |
73 | printk(KERN_WARNING "No more available DMA channels for %s\n", | 254 | printk(KERN_ERR "imxdma%d: imx_dma_setup_sg bad dmamode\n", |
74 | name); | 255 | dma_ch); |
75 | i = -ENODEV; | 256 | return -EINVAL; |
257 | } | ||
258 | |||
259 | res = imx_dma_setup_sg_base(dma_ch, sg, sgcount); | ||
260 | if (res <= 0) { | ||
261 | printk(KERN_ERR "imxdma%d: no sg chunk ready\n", dma_ch); | ||
262 | return -EINVAL; | ||
263 | } | ||
264 | |||
265 | return 0; | ||
266 | } | ||
267 | |||
268 | /** | ||
269 | * imx_dma_setup_handlers - setup i.MX DMA channel end and error notification handlers | ||
270 | * @dma_ch: i.MX DMA channel number | ||
271 | * @irq_handler: the pointer to the function called if the transfer | ||
272 | * ends successfully | ||
273 | * @err_handler: the pointer to the function called if the premature | ||
274 | * end caused by error occurs | ||
275 | * @data: user specified value to be passed to the handlers | ||
276 | */ | ||
277 | int | ||
278 | imx_dma_setup_handlers(imx_dmach_t dma_ch, | ||
279 | void (*irq_handler) (int, void *, struct pt_regs *), | ||
280 | void (*err_handler) (int, void *, struct pt_regs *), | ||
281 | void *data) | ||
282 | { | ||
283 | struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch]; | ||
284 | unsigned long flags; | ||
285 | |||
286 | if (!imxdma->name) { | ||
287 | printk(KERN_CRIT "%s: called for not allocated channel %d\n", | ||
288 | __FUNCTION__, dma_ch); | ||
289 | return -ENODEV; | ||
290 | } | ||
291 | |||
292 | local_irq_save(flags); | ||
293 | DISR = (1 << dma_ch); | ||
294 | imxdma->irq_handler = irq_handler; | ||
295 | imxdma->err_handler = err_handler; | ||
296 | imxdma->data = data; | ||
297 | local_irq_restore(flags); | ||
298 | return 0; | ||
299 | } | ||
300 | |||
301 | /** | ||
302 | * imx_dma_enable - function to start i.MX DMA channel operation | ||
303 | * @dma_ch: i.MX DMA channel number | ||
304 | * | ||
305 | * The channel has to be allocated by driver through imx_dma_request() | ||
306 | * or imx_dma_request_by_prio() function. | ||
307 | * The transfer parameters has to be set to the channel registers through | ||
308 | * call of the imx_dma_setup_single() or imx_dma_setup_sg() function | ||
309 | * and registers %BLR(dma_ch), %RSSR(dma_ch) and %CCR(dma_ch) has to | ||
310 | * be set prior this function call by the channel user. | ||
311 | */ | ||
312 | void imx_dma_enable(imx_dmach_t dma_ch) | ||
313 | { | ||
314 | struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch]; | ||
315 | unsigned long flags; | ||
316 | |||
317 | pr_debug("imxdma%d: imx_dma_enable\n", dma_ch); | ||
318 | |||
319 | if (!imxdma->name) { | ||
320 | printk(KERN_CRIT "%s: called for not allocated channel %d\n", | ||
321 | __FUNCTION__, dma_ch); | ||
322 | return; | ||
323 | } | ||
324 | |||
325 | local_irq_save(flags); | ||
326 | DISR = (1 << dma_ch); | ||
327 | DIMR &= ~(1 << dma_ch); | ||
328 | CCR(dma_ch) |= CCR_CEN; | ||
329 | local_irq_restore(flags); | ||
330 | } | ||
331 | |||
332 | /** | ||
333 | * imx_dma_disable - stop, finish i.MX DMA channel operatin | ||
334 | * @dma_ch: i.MX DMA channel number | ||
335 | */ | ||
336 | void imx_dma_disable(imx_dmach_t dma_ch) | ||
337 | { | ||
338 | unsigned long flags; | ||
339 | |||
340 | pr_debug("imxdma%d: imx_dma_disable\n", dma_ch); | ||
341 | |||
342 | local_irq_save(flags); | ||
343 | DIMR |= (1 << dma_ch); | ||
344 | CCR(dma_ch) &= ~CCR_CEN; | ||
345 | DISR = (1 << dma_ch); | ||
346 | local_irq_restore(flags); | ||
347 | } | ||
348 | |||
349 | /** | ||
350 | * imx_dma_request - request/allocate specified channel number | ||
351 | * @dma_ch: i.MX DMA channel number | ||
352 | * @name: the driver/caller own non-%NULL identification | ||
353 | */ | ||
354 | int imx_dma_request(imx_dmach_t dma_ch, const char *name) | ||
355 | { | ||
356 | struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch]; | ||
357 | unsigned long flags; | ||
358 | |||
359 | /* basic sanity checks */ | ||
360 | if (!name) | ||
361 | return -EINVAL; | ||
362 | |||
363 | if (dma_ch >= IMX_DMA_CHANNELS) { | ||
364 | printk(KERN_CRIT "%s: called for non-existed channel %d\n", | ||
365 | __FUNCTION__, dma_ch); | ||
366 | return -EINVAL; | ||
76 | } | 367 | } |
77 | 368 | ||
369 | local_irq_save(flags); | ||
370 | if (imxdma->name) { | ||
371 | local_irq_restore(flags); | ||
372 | return -ENODEV; | ||
373 | } | ||
374 | |||
375 | imxdma->name = name; | ||
376 | imxdma->irq_handler = NULL; | ||
377 | imxdma->err_handler = NULL; | ||
378 | imxdma->data = NULL; | ||
379 | imxdma->sg = NULL; | ||
78 | local_irq_restore(flags); | 380 | local_irq_restore(flags); |
79 | return i; | 381 | return 0; |
80 | } | 382 | } |
81 | 383 | ||
82 | void | 384 | /** |
83 | imx_free_dma(int dma_ch) | 385 | * imx_dma_free - release previously acquired channel |
386 | * @dma_ch: i.MX DMA channel number | ||
387 | */ | ||
388 | void imx_dma_free(imx_dmach_t dma_ch) | ||
84 | { | 389 | { |
85 | unsigned long flags; | 390 | unsigned long flags; |
391 | struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch]; | ||
86 | 392 | ||
87 | if (!dma_channels[dma_ch].name) { | 393 | if (!imxdma->name) { |
88 | printk(KERN_CRIT | 394 | printk(KERN_CRIT |
89 | "%s: trying to free channel %d which is already freed\n", | 395 | "%s: trying to free channel %d which is already freed\n", |
90 | __FUNCTION__, dma_ch); | 396 | __FUNCTION__, dma_ch); |
@@ -92,27 +398,84 @@ imx_free_dma(int dma_ch) | |||
92 | } | 398 | } |
93 | 399 | ||
94 | local_irq_save(flags); | 400 | local_irq_save(flags); |
95 | DIMR &= ~(1 << dma_ch); | 401 | /* Disable interrupts */ |
96 | dma_channels[dma_ch].name = NULL; | 402 | DIMR |= (1 << dma_ch); |
403 | CCR(dma_ch) &= ~CCR_CEN; | ||
404 | imxdma->name = NULL; | ||
97 | local_irq_restore(flags); | 405 | local_irq_restore(flags); |
98 | } | 406 | } |
99 | 407 | ||
100 | static irqreturn_t | 408 | /** |
101 | dma_err_handler(int irq, void *dev_id, struct pt_regs *regs) | 409 | * imx_dma_request_by_prio - find and request some of free channels best suiting requested priority |
410 | * @dma_ch: i.MX DMA channel number | ||
411 | * @name: the driver/caller own non-%NULL identification | ||
412 | * @prio: one of the hardware distinguished priority level: | ||
413 | * %DMA_PRIO_HIGH, %DMA_PRIO_MEDIUM, %DMA_PRIO_LOW | ||
414 | * | ||
415 | * This function tries to find free channel in the specified priority group | ||
416 | * if the priority cannot be achieved it tries to look for free channel | ||
417 | * in the higher and then even lower priority groups. | ||
418 | * | ||
419 | * Return value: If there is no free channel to allocate, -%ENODEV is returned. | ||
420 | * Zero value indicates successful channel allocation. | ||
421 | */ | ||
422 | int | ||
423 | imx_dma_request_by_prio(imx_dmach_t * pdma_ch, const char *name, | ||
424 | imx_dma_prio prio) | ||
425 | { | ||
426 | int i; | ||
427 | int best; | ||
428 | |||
429 | switch (prio) { | ||
430 | case (DMA_PRIO_HIGH): | ||
431 | best = 8; | ||
432 | break; | ||
433 | case (DMA_PRIO_MEDIUM): | ||
434 | best = 4; | ||
435 | break; | ||
436 | case (DMA_PRIO_LOW): | ||
437 | default: | ||
438 | best = 0; | ||
439 | break; | ||
440 | } | ||
441 | |||
442 | for (i = best; i < IMX_DMA_CHANNELS; i++) { | ||
443 | if (!imx_dma_request(i, name)) { | ||
444 | *pdma_ch = i; | ||
445 | return 0; | ||
446 | } | ||
447 | } | ||
448 | |||
449 | for (i = best - 1; i >= 0; i--) { | ||
450 | if (!imx_dma_request(i, name)) { | ||
451 | *pdma_ch = i; | ||
452 | return 0; | ||
453 | } | ||
454 | } | ||
455 | |||
456 | printk(KERN_ERR "%s: no free DMA channel found\n", __FUNCTION__); | ||
457 | |||
458 | return -ENODEV; | ||
459 | } | ||
460 | |||
461 | static irqreturn_t dma_err_handler(int irq, void *dev_id, struct pt_regs *regs) | ||
102 | { | 462 | { |
103 | int i, disr = DISR; | 463 | int i, disr = DISR; |
104 | struct dma_channel *channel; | 464 | struct imx_dma_channel *channel; |
105 | unsigned int err_mask = DBTOSR | DRTOSR | DSESR | DBOSR; | 465 | unsigned int err_mask = DBTOSR | DRTOSR | DSESR | DBOSR; |
106 | 466 | ||
107 | DISR = disr; | 467 | DISR = disr; |
108 | for (i = 0; i < 11; i++) { | 468 | for (i = 0; i < IMX_DMA_CHANNELS; i++) { |
109 | channel = &dma_channels[i]; | 469 | channel = &imx_dma_channels[i]; |
110 | 470 | ||
111 | if ( (err_mask & 1<<i) && channel->name && channel->err_handler) { | 471 | if ((err_mask & 1 << i) && channel->name |
472 | && channel->err_handler) { | ||
112 | channel->err_handler(i, channel->data, regs); | 473 | channel->err_handler(i, channel->data, regs); |
113 | continue; | 474 | continue; |
114 | } | 475 | } |
115 | 476 | ||
477 | imx_dma_channels[i].sg = NULL; | ||
478 | |||
116 | if (DBTOSR & (1 << i)) { | 479 | if (DBTOSR & (1 << i)) { |
117 | printk(KERN_WARNING | 480 | printk(KERN_WARNING |
118 | "Burst timeout on channel %d (%s)\n", | 481 | "Burst timeout on channel %d (%s)\n", |
@@ -141,17 +504,27 @@ dma_err_handler(int irq, void *dev_id, struct pt_regs *regs) | |||
141 | return IRQ_HANDLED; | 504 | return IRQ_HANDLED; |
142 | } | 505 | } |
143 | 506 | ||
144 | static irqreturn_t | 507 | static irqreturn_t dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs) |
145 | dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs) | ||
146 | { | 508 | { |
147 | int i, disr = DISR; | 509 | int i, disr = DISR; |
148 | 510 | ||
511 | pr_debug("imxdma: dma_irq_handler called, disr=0x%08x\n", | ||
512 | disr); | ||
513 | |||
149 | DISR = disr; | 514 | DISR = disr; |
150 | for (i = 0; i < 11; i++) { | 515 | for (i = 0; i < IMX_DMA_CHANNELS; i++) { |
151 | if (disr & (1 << i)) { | 516 | if (disr & (1 << i)) { |
152 | struct dma_channel *channel = &dma_channels[i]; | 517 | struct imx_dma_channel *channel = &imx_dma_channels[i]; |
153 | if (channel->name && channel->irq_handler) { | 518 | if (channel->name) { |
154 | channel->irq_handler(i, channel->data, regs); | 519 | if (imx_dma_sg_next(i, CNTR(i))) { |
520 | CCR(i) &= ~CCR_CEN; | ||
521 | mb(); | ||
522 | CCR(i) |= CCR_CEN; | ||
523 | } else { | ||
524 | if (channel->irq_handler) | ||
525 | channel->irq_handler(i, | ||
526 | channel->data, regs); | ||
527 | } | ||
155 | } else { | 528 | } else { |
156 | /* | 529 | /* |
157 | * IRQ for an unregistered DMA channel: | 530 | * IRQ for an unregistered DMA channel: |
@@ -165,10 +538,10 @@ dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs) | |||
165 | return IRQ_HANDLED; | 538 | return IRQ_HANDLED; |
166 | } | 539 | } |
167 | 540 | ||
168 | static int __init | 541 | static int __init imx_dma_init(void) |
169 | imx_dma_init(void) | ||
170 | { | 542 | { |
171 | int ret; | 543 | int ret; |
544 | int i; | ||
172 | 545 | ||
173 | /* reset DMA module */ | 546 | /* reset DMA module */ |
174 | DCR = DCR_DRST; | 547 | DCR = DCR_DRST; |
@@ -189,15 +562,27 @@ imx_dma_init(void) | |||
189 | DCR = DCR_DEN; | 562 | DCR = DCR_DEN; |
190 | 563 | ||
191 | /* clear all interrupts */ | 564 | /* clear all interrupts */ |
192 | DISR = 0x3ff; | 565 | DISR = (1 << IMX_DMA_CHANNELS) - 1; |
193 | 566 | ||
194 | /* enable interrupts */ | 567 | /* enable interrupts */ |
195 | DIMR = 0; | 568 | DIMR = (1 << IMX_DMA_CHANNELS) - 1; |
569 | |||
570 | for (i = 0; i < IMX_DMA_CHANNELS; i++) { | ||
571 | imx_dma_channels[i].sg = NULL; | ||
572 | imx_dma_channels[i].dma_num = i; | ||
573 | } | ||
196 | 574 | ||
197 | return ret; | 575 | return ret; |
198 | } | 576 | } |
199 | 577 | ||
200 | arch_initcall(imx_dma_init); | 578 | arch_initcall(imx_dma_init); |
201 | 579 | ||
202 | EXPORT_SYMBOL(imx_request_dma); | 580 | EXPORT_SYMBOL(imx_dma_setup_single); |
203 | EXPORT_SYMBOL(imx_free_dma); | 581 | EXPORT_SYMBOL(imx_dma_setup_sg); |
582 | EXPORT_SYMBOL(imx_dma_setup_handlers); | ||
583 | EXPORT_SYMBOL(imx_dma_enable); | ||
584 | EXPORT_SYMBOL(imx_dma_disable); | ||
585 | EXPORT_SYMBOL(imx_dma_request); | ||
586 | EXPORT_SYMBOL(imx_dma_free); | ||
587 | EXPORT_SYMBOL(imx_dma_request_by_prio); | ||
588 | EXPORT_SYMBOL(imx_dma_channels); | ||
diff --git a/arch/arm/mach-imx/generic.c b/arch/arm/mach-imx/generic.c index 37613ad68366..9d8331be2b58 100644 --- a/arch/arm/mach-imx/generic.c +++ b/arch/arm/mach-imx/generic.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <asm/arch/imx-regs.h> | 33 | #include <asm/arch/imx-regs.h> |
34 | 34 | ||
35 | #include <asm/mach/map.h> | 35 | #include <asm/mach/map.h> |
36 | #include <asm/arch/mmc.h> | ||
36 | 37 | ||
37 | void imx_gpio_mode(int gpio_mode) | 38 | void imx_gpio_mode(int gpio_mode) |
38 | { | 39 | { |
@@ -175,13 +176,25 @@ static struct resource imx_mmc_resources[] = { | |||
175 | }, | 176 | }, |
176 | }; | 177 | }; |
177 | 178 | ||
179 | static u64 imxmmmc_dmamask = 0xffffffffUL; | ||
180 | |||
178 | static struct platform_device imx_mmc_device = { | 181 | static struct platform_device imx_mmc_device = { |
179 | .name = "imx-mmc", | 182 | .name = "imx-mmc", |
180 | .id = 0, | 183 | .id = 0, |
184 | .dev = { | ||
185 | .dma_mask = &imxmmmc_dmamask, | ||
186 | .coherent_dma_mask = 0xffffffff, | ||
187 | }, | ||
181 | .num_resources = ARRAY_SIZE(imx_mmc_resources), | 188 | .num_resources = ARRAY_SIZE(imx_mmc_resources), |
182 | .resource = imx_mmc_resources, | 189 | .resource = imx_mmc_resources, |
183 | }; | 190 | }; |
184 | 191 | ||
192 | void __init imx_set_mmc_info(struct imxmmc_platform_data *info) | ||
193 | { | ||
194 | imx_mmc_device.dev.platform_data = info; | ||
195 | } | ||
196 | EXPORT_SYMBOL(imx_set_mmc_info); | ||
197 | |||
185 | static struct resource imx_uart1_resources[] = { | 198 | static struct resource imx_uart1_resources[] = { |
186 | [0] = { | 199 | [0] = { |
187 | .start = 0x00206000, | 200 | .start = 0x00206000, |
diff --git a/arch/arm/mach-imx/mx1ads.c b/arch/arm/mach-imx/mx1ads.c index 8ab1b040288c..e34d0df90aed 100644 --- a/arch/arm/mach-imx/mx1ads.c +++ b/arch/arm/mach-imx/mx1ads.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <asm/mach-types.h> | 25 | #include <asm/mach-types.h> |
26 | 26 | ||
27 | #include <asm/mach/arch.h> | 27 | #include <asm/mach/arch.h> |
28 | #include <asm/arch/mmc.h> | ||
28 | #include <linux/interrupt.h> | 29 | #include <linux/interrupt.h> |
29 | #include "generic.h" | 30 | #include "generic.h" |
30 | 31 | ||
@@ -51,12 +52,29 @@ static struct platform_device *devices[] __initdata = { | |||
51 | &cs89x0_device, | 52 | &cs89x0_device, |
52 | }; | 53 | }; |
53 | 54 | ||
55 | #ifdef CONFIG_MMC_IMX | ||
56 | static int mx1ads_mmc_card_present(void) | ||
57 | { | ||
58 | /* MMC/SD Card Detect is PB 20 on MX1ADS V1.0.7 */ | ||
59 | return (SSR(1) & (1 << 20) ? 0 : 1); | ||
60 | } | ||
61 | |||
62 | static struct imxmmc_platform_data mx1ads_mmc_info = { | ||
63 | .card_present = mx1ads_mmc_card_present, | ||
64 | }; | ||
65 | #endif | ||
66 | |||
54 | static void __init | 67 | static void __init |
55 | mx1ads_init(void) | 68 | mx1ads_init(void) |
56 | { | 69 | { |
57 | #ifdef CONFIG_LEDS | 70 | #ifdef CONFIG_LEDS |
58 | imx_gpio_mode(GPIO_PORTA | GPIO_OUT | 2); | 71 | imx_gpio_mode(GPIO_PORTA | GPIO_OUT | 2); |
59 | #endif | 72 | #endif |
73 | #ifdef CONFIG_MMC_IMX | ||
74 | /* SD/MMC card detect */ | ||
75 | imx_gpio_mode(GPIO_PORTB | GPIO_GIUS | GPIO_IN | 20); | ||
76 | imx_set_mmc_info(&mx1ads_mmc_info); | ||
77 | #endif | ||
60 | platform_add_devices(devices, ARRAY_SIZE(devices)); | 78 | platform_add_devices(devices, ARRAY_SIZE(devices)); |
61 | } | 79 | } |
62 | 80 | ||
diff --git a/arch/arm/mach-ixp23xx/espresso.c b/arch/arm/mach-ixp23xx/espresso.c index 2327c9790416..bf688c128630 100644 --- a/arch/arm/mach-ixp23xx/espresso.c +++ b/arch/arm/mach-ixp23xx/espresso.c | |||
@@ -44,6 +44,15 @@ | |||
44 | #include <asm/mach/irq.h> | 44 | #include <asm/mach/irq.h> |
45 | #include <asm/mach/pci.h> | 45 | #include <asm/mach/pci.h> |
46 | 46 | ||
47 | static int __init espresso_pci_init(void) | ||
48 | { | ||
49 | if (machine_is_espresso()) | ||
50 | ixp23xx_pci_slave_init(); | ||
51 | |||
52 | return 0; | ||
53 | }; | ||
54 | subsys_initcall(espresso_pci_init); | ||
55 | |||
47 | static void __init espresso_init(void) | 56 | static void __init espresso_init(void) |
48 | { | 57 | { |
49 | physmap_configure(0x90000000, 0x02000000, 2, NULL); | 58 | physmap_configure(0x90000000, 0x02000000, 2, NULL); |
diff --git a/arch/arm/mach-ixp23xx/pci.c b/arch/arm/mach-ixp23xx/pci.c index 5330ad78c1bb..ac72f94c5b4d 100644 --- a/arch/arm/mach-ixp23xx/pci.c +++ b/arch/arm/mach-ixp23xx/pci.c | |||
@@ -201,7 +201,7 @@ int clear_master_aborts(void) | |||
201 | return 0; | 201 | return 0; |
202 | } | 202 | } |
203 | 203 | ||
204 | void __init ixp23xx_pci_preinit(void) | 204 | static void __init ixp23xx_pci_common_init(void) |
205 | { | 205 | { |
206 | #ifdef __ARMEB__ | 206 | #ifdef __ARMEB__ |
207 | *IXP23XX_PCI_CONTROL |= 0x20000; /* set I/O swapping */ | 207 | *IXP23XX_PCI_CONTROL |= 0x20000; /* set I/O swapping */ |
@@ -219,7 +219,18 @@ void __init ixp23xx_pci_preinit(void) | |||
219 | *IXP23XX_PCI_CPP_ADDR_BITS &= ~(1 << 1); | 219 | *IXP23XX_PCI_CPP_ADDR_BITS &= ~(1 << 1); |
220 | } else { | 220 | } else { |
221 | *IXP23XX_PCI_CPP_ADDR_BITS |= (1 << 1); | 221 | *IXP23XX_PCI_CPP_ADDR_BITS |= (1 << 1); |
222 | |||
223 | /* | ||
224 | * Enable coherency on A2 silicon. | ||
225 | */ | ||
226 | if (arch_is_coherent()) | ||
227 | *IXP23XX_CPP2XSI_CURR_XFER_REG3 &= ~IXP23XX_CPP2XSI_COH_OFF; | ||
222 | } | 228 | } |
229 | } | ||
230 | |||
231 | void __init ixp23xx_pci_preinit(void) | ||
232 | { | ||
233 | ixp23xx_pci_common_init(); | ||
223 | 234 | ||
224 | hook_fault_code(16+6, ixp23xx_pci_abort_handler, SIGBUS, | 235 | hook_fault_code(16+6, ixp23xx_pci_abort_handler, SIGBUS, |
225 | "PCI config cycle to non-existent device"); | 236 | "PCI config cycle to non-existent device"); |
@@ -273,3 +284,8 @@ int ixp23xx_pci_setup(int nr, struct pci_sys_data *sys) | |||
273 | 284 | ||
274 | return 1; | 285 | return 1; |
275 | } | 286 | } |
287 | |||
288 | void ixp23xx_pci_slave_init(void) | ||
289 | { | ||
290 | ixp23xx_pci_common_init(); | ||
291 | } | ||
diff --git a/arch/arm/mach-omap1/Kconfig b/arch/arm/mach-omap1/Kconfig index 86a0f0d14345..f8d716ccc1df 100644 --- a/arch/arm/mach-omap1/Kconfig +++ b/arch/arm/mach-omap1/Kconfig | |||
@@ -69,12 +69,6 @@ config MACH_VOICEBLUE | |||
69 | Support for Voiceblue GSM/VoIP gateway. Say Y here if you have | 69 | Support for Voiceblue GSM/VoIP gateway. Say Y here if you have |
70 | such a board. | 70 | such a board. |
71 | 71 | ||
72 | config MACH_NETSTAR | ||
73 | bool "NetStar" | ||
74 | depends on ARCH_OMAP1 && ARCH_OMAP15XX | ||
75 | help | ||
76 | Support for NetStar PBX. Say Y here if you have such a board. | ||
77 | |||
78 | config MACH_OMAP_PALMTE | 72 | config MACH_OMAP_PALMTE |
79 | bool "Palm Tungsten E" | 73 | bool "Palm Tungsten E" |
80 | depends on ARCH_OMAP1 && ARCH_OMAP15XX | 74 | depends on ARCH_OMAP1 && ARCH_OMAP15XX |
@@ -85,6 +79,20 @@ config MACH_OMAP_PALMTE | |||
85 | informations. | 79 | informations. |
86 | Say Y here if you have such a PDA, say NO otherwise. | 80 | Say Y here if you have such a PDA, say NO otherwise. |
87 | 81 | ||
82 | config MACH_NOKIA770 | ||
83 | bool "Nokia 770" | ||
84 | depends on ARCH_OMAP1 && ARCH_OMAP16XX | ||
85 | help | ||
86 | Support for the Nokia 770 Internet Tablet. Say Y here if you | ||
87 | have such a device. | ||
88 | |||
89 | config MACH_AMS_DELTA | ||
90 | bool "Amstrad E3 (Delta)" | ||
91 | depends on ARCH_OMAP1 && ARCH_OMAP15XX | ||
92 | help | ||
93 | Support for the Amstrad E3 (codename Delta) videophone. Say Y here | ||
94 | if you have such a device. | ||
95 | |||
88 | config MACH_OMAP_GENERIC | 96 | config MACH_OMAP_GENERIC |
89 | bool "Generic OMAP board" | 97 | bool "Generic OMAP board" |
90 | depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX) | 98 | depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX) |
diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile index b0b00156faae..9ea719550ad3 100644 --- a/arch/arm/mach-omap1/Makefile +++ b/arch/arm/mach-omap1/Makefile | |||
@@ -3,7 +3,13 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | # Common support | 5 | # Common support |
6 | obj-y := io.o id.o clock.o irq.o time.o mux.o serial.o devices.o | 6 | obj-y := io.o id.o clock.o irq.o mux.o serial.o devices.o |
7 | |||
8 | obj-$(CONFIG_OMAP_MPU_TIMER) += time.o | ||
9 | |||
10 | # Power Management | ||
11 | obj-$(CONFIG_PM) += pm.o sleep.o | ||
12 | |||
7 | led-y := leds.o | 13 | led-y := leds.o |
8 | 14 | ||
9 | # Specific board support | 15 | # Specific board support |
@@ -14,8 +20,9 @@ obj-$(CONFIG_MACH_OMAP_PERSEUS2) += board-perseus2.o | |||
14 | obj-$(CONFIG_MACH_OMAP_OSK) += board-osk.o | 20 | obj-$(CONFIG_MACH_OMAP_OSK) += board-osk.o |
15 | obj-$(CONFIG_MACH_OMAP_H3) += board-h3.o | 21 | obj-$(CONFIG_MACH_OMAP_H3) += board-h3.o |
16 | obj-$(CONFIG_MACH_VOICEBLUE) += board-voiceblue.o | 22 | obj-$(CONFIG_MACH_VOICEBLUE) += board-voiceblue.o |
17 | obj-$(CONFIG_MACH_NETSTAR) += board-netstar.o | ||
18 | obj-$(CONFIG_MACH_OMAP_PALMTE) += board-palmte.o | 23 | obj-$(CONFIG_MACH_OMAP_PALMTE) += board-palmte.o |
24 | obj-$(CONFIG_MACH_NOKIA770) += board-nokia770.o | ||
25 | obj-$(CONFIG_MACH_AMS_DELTA) += board-ams-delta.o | ||
19 | 26 | ||
20 | ifeq ($(CONFIG_ARCH_OMAP15XX),y) | 27 | ifeq ($(CONFIG_ARCH_OMAP15XX),y) |
21 | # Innovator-1510 FPGA | 28 | # Innovator-1510 FPGA |
diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c new file mode 100644 index 000000000000..6178f046f128 --- /dev/null +++ b/arch/arm/mach-omap1/board-ams-delta.c | |||
@@ -0,0 +1,116 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-omap1/board-ams-delta.c | ||
3 | * | ||
4 | * Modified from board-generic.c | ||
5 | * | ||
6 | * Board specific inits for the Amstrad E3 (codename Delta) videophone | ||
7 | * | ||
8 | * Copyright (C) 2006 Jonathan McDowell <noodles@earth.li> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | |||
19 | #include <asm/hardware.h> | ||
20 | #include <asm/mach-types.h> | ||
21 | #include <asm/mach/arch.h> | ||
22 | #include <asm/mach/map.h> | ||
23 | |||
24 | #include <asm/arch/board-ams-delta.h> | ||
25 | #include <asm/arch/gpio.h> | ||
26 | #include <asm/arch/mux.h> | ||
27 | #include <asm/arch/usb.h> | ||
28 | #include <asm/arch/board.h> | ||
29 | #include <asm/arch/common.h> | ||
30 | |||
31 | static u8 ams_delta_latch1_reg; | ||
32 | static u16 ams_delta_latch2_reg; | ||
33 | |||
34 | void ams_delta_latch1_write(u8 mask, u8 value) | ||
35 | { | ||
36 | ams_delta_latch1_reg &= ~mask; | ||
37 | ams_delta_latch1_reg |= value; | ||
38 | *(volatile __u8 *) AMS_DELTA_LATCH1_VIRT = ams_delta_latch1_reg; | ||
39 | } | ||
40 | |||
41 | void ams_delta_latch2_write(u16 mask, u16 value) | ||
42 | { | ||
43 | ams_delta_latch2_reg &= ~mask; | ||
44 | ams_delta_latch2_reg |= value; | ||
45 | *(volatile __u16 *) AMS_DELTA_LATCH2_VIRT = ams_delta_latch2_reg; | ||
46 | } | ||
47 | |||
48 | static void __init ams_delta_init_irq(void) | ||
49 | { | ||
50 | omap1_init_common_hw(); | ||
51 | omap_init_irq(); | ||
52 | omap_gpio_init(); | ||
53 | } | ||
54 | |||
55 | static struct map_desc ams_delta_io_desc[] __initdata = { | ||
56 | // AMS_DELTA_LATCH1 | ||
57 | { | ||
58 | .virtual = AMS_DELTA_LATCH1_VIRT, | ||
59 | .pfn = __phys_to_pfn(AMS_DELTA_LATCH1_PHYS), | ||
60 | .length = 0x01000000, | ||
61 | .type = MT_DEVICE | ||
62 | }, | ||
63 | // AMS_DELTA_LATCH2 | ||
64 | { | ||
65 | .virtual = AMS_DELTA_LATCH2_VIRT, | ||
66 | .pfn = __phys_to_pfn(AMS_DELTA_LATCH2_PHYS), | ||
67 | .length = 0x01000000, | ||
68 | .type = MT_DEVICE | ||
69 | }, | ||
70 | // AMS_DELTA_MODEM | ||
71 | { | ||
72 | .virtual = AMS_DELTA_MODEM_VIRT, | ||
73 | .pfn = __phys_to_pfn(AMS_DELTA_MODEM_PHYS), | ||
74 | .length = 0x01000000, | ||
75 | .type = MT_DEVICE | ||
76 | } | ||
77 | }; | ||
78 | |||
79 | static struct omap_uart_config ams_delta_uart_config __initdata = { | ||
80 | .enabled_uarts = 1, | ||
81 | }; | ||
82 | |||
83 | static struct omap_board_config_kernel ams_delta_config[] = { | ||
84 | { OMAP_TAG_UART, &ams_delta_uart_config }, | ||
85 | }; | ||
86 | |||
87 | static void __init ams_delta_init(void) | ||
88 | { | ||
89 | iotable_init(ams_delta_io_desc, ARRAY_SIZE(ams_delta_io_desc)); | ||
90 | |||
91 | omap_board_config = ams_delta_config; | ||
92 | omap_board_config_size = ARRAY_SIZE(ams_delta_config); | ||
93 | omap_serial_init(); | ||
94 | |||
95 | /* Clear latch2 (NAND, LCD, modem enable) */ | ||
96 | ams_delta_latch2_write(~0, 0); | ||
97 | } | ||
98 | |||
99 | static void __init ams_delta_map_io(void) | ||
100 | { | ||
101 | omap1_map_common_io(); | ||
102 | } | ||
103 | |||
104 | MACHINE_START(AMS_DELTA, "Amstrad E3 (Delta)") | ||
105 | /* Maintainer: Jonathan McDowell <noodles@earth.li> */ | ||
106 | .phys_io = 0xfff00000, | ||
107 | .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc, | ||
108 | .boot_params = 0x10000100, | ||
109 | .map_io = ams_delta_map_io, | ||
110 | .init_irq = ams_delta_init_irq, | ||
111 | .init_machine = ams_delta_init, | ||
112 | .timer = &omap_timer, | ||
113 | MACHINE_END | ||
114 | |||
115 | EXPORT_SYMBOL(ams_delta_latch1_write); | ||
116 | EXPORT_SYMBOL(ams_delta_latch2_write); | ||
diff --git a/arch/arm/mach-omap1/board-generic.c b/arch/arm/mach-omap1/board-generic.c index a177e78b2b87..33d01adab1ed 100644 --- a/arch/arm/mach-omap1/board-generic.c +++ b/arch/arm/mach-omap1/board-generic.c | |||
@@ -88,7 +88,7 @@ static struct omap_board_config_kernel generic_config[] = { | |||
88 | static void __init omap_generic_init(void) | 88 | static void __init omap_generic_init(void) |
89 | { | 89 | { |
90 | #ifdef CONFIG_ARCH_OMAP15XX | 90 | #ifdef CONFIG_ARCH_OMAP15XX |
91 | if (cpu_is_omap1510()) { | 91 | if (cpu_is_omap15xx()) { |
92 | generic_config[0].data = &generic1510_usb_config; | 92 | generic_config[0].data = &generic1510_usb_config; |
93 | } | 93 | } |
94 | #endif | 94 | #endif |
diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c index 89f0cc74a519..cd3a06dfc0a8 100644 --- a/arch/arm/mach-omap1/board-h2.c +++ b/arch/arm/mach-omap1/board-h2.c | |||
@@ -24,7 +24,9 @@ | |||
24 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
25 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
26 | #include <linux/mtd/mtd.h> | 26 | #include <linux/mtd/mtd.h> |
27 | #include <linux/mtd/nand.h> | ||
27 | #include <linux/mtd/partitions.h> | 28 | #include <linux/mtd/partitions.h> |
29 | #include <linux/input.h> | ||
28 | 30 | ||
29 | #include <asm/hardware.h> | 31 | #include <asm/hardware.h> |
30 | #include <asm/mach-types.h> | 32 | #include <asm/mach-types.h> |
@@ -35,12 +37,55 @@ | |||
35 | #include <asm/arch/gpio.h> | 37 | #include <asm/arch/gpio.h> |
36 | #include <asm/arch/mux.h> | 38 | #include <asm/arch/mux.h> |
37 | #include <asm/arch/tc.h> | 39 | #include <asm/arch/tc.h> |
40 | #include <asm/arch/irda.h> | ||
38 | #include <asm/arch/usb.h> | 41 | #include <asm/arch/usb.h> |
42 | #include <asm/arch/keypad.h> | ||
39 | #include <asm/arch/common.h> | 43 | #include <asm/arch/common.h> |
44 | #include <asm/arch/mcbsp.h> | ||
45 | #include <asm/arch/omap-alsa.h> | ||
40 | 46 | ||
41 | extern int omap_gpio_init(void); | 47 | extern int omap_gpio_init(void); |
42 | 48 | ||
43 | static struct mtd_partition h2_partitions[] = { | 49 | static int h2_keymap[] = { |
50 | KEY(0, 0, KEY_LEFT), | ||
51 | KEY(0, 1, KEY_RIGHT), | ||
52 | KEY(0, 2, KEY_3), | ||
53 | KEY(0, 3, KEY_F10), | ||
54 | KEY(0, 4, KEY_F5), | ||
55 | KEY(0, 5, KEY_9), | ||
56 | KEY(1, 0, KEY_DOWN), | ||
57 | KEY(1, 1, KEY_UP), | ||
58 | KEY(1, 2, KEY_2), | ||
59 | KEY(1, 3, KEY_F9), | ||
60 | KEY(1, 4, KEY_F7), | ||
61 | KEY(1, 5, KEY_0), | ||
62 | KEY(2, 0, KEY_ENTER), | ||
63 | KEY(2, 1, KEY_6), | ||
64 | KEY(2, 2, KEY_1), | ||
65 | KEY(2, 3, KEY_F2), | ||
66 | KEY(2, 4, KEY_F6), | ||
67 | KEY(2, 5, KEY_HOME), | ||
68 | KEY(3, 0, KEY_8), | ||
69 | KEY(3, 1, KEY_5), | ||
70 | KEY(3, 2, KEY_F12), | ||
71 | KEY(3, 3, KEY_F3), | ||
72 | KEY(3, 4, KEY_F8), | ||
73 | KEY(3, 5, KEY_END), | ||
74 | KEY(4, 0, KEY_7), | ||
75 | KEY(4, 1, KEY_4), | ||
76 | KEY(4, 2, KEY_F11), | ||
77 | KEY(4, 3, KEY_F1), | ||
78 | KEY(4, 4, KEY_F4), | ||
79 | KEY(4, 5, KEY_ESC), | ||
80 | KEY(5, 0, KEY_F13), | ||
81 | KEY(5, 1, KEY_F14), | ||
82 | KEY(5, 2, KEY_F15), | ||
83 | KEY(5, 3, KEY_F16), | ||
84 | KEY(5, 4, KEY_SLEEP), | ||
85 | 0 | ||
86 | }; | ||
87 | |||
88 | static struct mtd_partition h2_nor_partitions[] = { | ||
44 | /* bootloader (U-Boot, etc) in first sector */ | 89 | /* bootloader (U-Boot, etc) in first sector */ |
45 | { | 90 | { |
46 | .name = "bootloader", | 91 | .name = "bootloader", |
@@ -71,26 +116,26 @@ static struct mtd_partition h2_partitions[] = { | |||
71 | } | 116 | } |
72 | }; | 117 | }; |
73 | 118 | ||
74 | static struct flash_platform_data h2_flash_data = { | 119 | static struct flash_platform_data h2_nor_data = { |
75 | .map_name = "cfi_probe", | 120 | .map_name = "cfi_probe", |
76 | .width = 2, | 121 | .width = 2, |
77 | .parts = h2_partitions, | 122 | .parts = h2_nor_partitions, |
78 | .nr_parts = ARRAY_SIZE(h2_partitions), | 123 | .nr_parts = ARRAY_SIZE(h2_nor_partitions), |
79 | }; | 124 | }; |
80 | 125 | ||
81 | static struct resource h2_flash_resource = { | 126 | static struct resource h2_nor_resource = { |
82 | /* This is on CS3, wherever it's mapped */ | 127 | /* This is on CS3, wherever it's mapped */ |
83 | .flags = IORESOURCE_MEM, | 128 | .flags = IORESOURCE_MEM, |
84 | }; | 129 | }; |
85 | 130 | ||
86 | static struct platform_device h2_flash_device = { | 131 | static struct platform_device h2_nor_device = { |
87 | .name = "omapflash", | 132 | .name = "omapflash", |
88 | .id = 0, | 133 | .id = 0, |
89 | .dev = { | 134 | .dev = { |
90 | .platform_data = &h2_flash_data, | 135 | .platform_data = &h2_nor_data, |
91 | }, | 136 | }, |
92 | .num_resources = 1, | 137 | .num_resources = 1, |
93 | .resource = &h2_flash_resource, | 138 | .resource = &h2_nor_resource, |
94 | }; | 139 | }; |
95 | 140 | ||
96 | static struct resource h2_smc91x_resources[] = { | 141 | static struct resource h2_smc91x_resources[] = { |
@@ -113,9 +158,119 @@ static struct platform_device h2_smc91x_device = { | |||
113 | .resource = h2_smc91x_resources, | 158 | .resource = h2_smc91x_resources, |
114 | }; | 159 | }; |
115 | 160 | ||
161 | static struct resource h2_kp_resources[] = { | ||
162 | [0] = { | ||
163 | .start = INT_KEYBOARD, | ||
164 | .end = INT_KEYBOARD, | ||
165 | .flags = IORESOURCE_IRQ, | ||
166 | }, | ||
167 | }; | ||
168 | |||
169 | static struct omap_kp_platform_data h2_kp_data = { | ||
170 | .rows = 8, | ||
171 | .cols = 8, | ||
172 | .keymap = h2_keymap, | ||
173 | .rep = 1, | ||
174 | }; | ||
175 | |||
176 | static struct platform_device h2_kp_device = { | ||
177 | .name = "omap-keypad", | ||
178 | .id = -1, | ||
179 | .dev = { | ||
180 | .platform_data = &h2_kp_data, | ||
181 | }, | ||
182 | .num_resources = ARRAY_SIZE(h2_kp_resources), | ||
183 | .resource = h2_kp_resources, | ||
184 | }; | ||
185 | |||
186 | #define H2_IRDA_FIRSEL_GPIO_PIN 17 | ||
187 | |||
188 | #if defined(CONFIG_OMAP_IR) || defined(CONFIG_OMAP_IR_MODULE) | ||
189 | static int h2_transceiver_mode(struct device *dev, int state) | ||
190 | { | ||
191 | if (state & IR_SIRMODE) | ||
192 | omap_set_gpio_dataout(H2_IRDA_FIRSEL_GPIO_PIN, 0); | ||
193 | else /* MIR/FIR */ | ||
194 | omap_set_gpio_dataout(H2_IRDA_FIRSEL_GPIO_PIN, 1); | ||
195 | |||
196 | return 0; | ||
197 | } | ||
198 | #endif | ||
199 | |||
200 | static struct omap_irda_config h2_irda_data = { | ||
201 | .transceiver_cap = IR_SIRMODE | IR_MIRMODE | IR_FIRMODE, | ||
202 | .rx_channel = OMAP_DMA_UART3_RX, | ||
203 | .tx_channel = OMAP_DMA_UART3_TX, | ||
204 | .dest_start = UART3_THR, | ||
205 | .src_start = UART3_RHR, | ||
206 | .tx_trigger = 0, | ||
207 | .rx_trigger = 0, | ||
208 | }; | ||
209 | |||
210 | static struct resource h2_irda_resources[] = { | ||
211 | [0] = { | ||
212 | .start = INT_UART3, | ||
213 | .end = INT_UART3, | ||
214 | .flags = IORESOURCE_IRQ, | ||
215 | }, | ||
216 | }; | ||
217 | static struct platform_device h2_irda_device = { | ||
218 | .name = "omapirda", | ||
219 | .id = 0, | ||
220 | .dev = { | ||
221 | .platform_data = &h2_irda_data, | ||
222 | }, | ||
223 | .num_resources = ARRAY_SIZE(h2_irda_resources), | ||
224 | .resource = h2_irda_resources, | ||
225 | }; | ||
226 | |||
227 | static struct platform_device h2_lcd_device = { | ||
228 | .name = "lcd_h2", | ||
229 | .id = -1, | ||
230 | }; | ||
231 | |||
232 | static struct omap_mcbsp_reg_cfg mcbsp_regs = { | ||
233 | .spcr2 = FREE | FRST | GRST | XRST | XINTM(3), | ||
234 | .spcr1 = RINTM(3) | RRST, | ||
235 | .rcr2 = RPHASE | RFRLEN2(OMAP_MCBSP_WORD_8) | | ||
236 | RWDLEN2(OMAP_MCBSP_WORD_16) | RDATDLY(1), | ||
237 | .rcr1 = RFRLEN1(OMAP_MCBSP_WORD_8) | RWDLEN1(OMAP_MCBSP_WORD_16), | ||
238 | .xcr2 = XPHASE | XFRLEN2(OMAP_MCBSP_WORD_8) | | ||
239 | XWDLEN2(OMAP_MCBSP_WORD_16) | XDATDLY(1) | XFIG, | ||
240 | .xcr1 = XFRLEN1(OMAP_MCBSP_WORD_8) | XWDLEN1(OMAP_MCBSP_WORD_16), | ||
241 | .srgr1 = FWID(15), | ||
242 | .srgr2 = GSYNC | CLKSP | FSGM | FPER(31), | ||
243 | |||
244 | .pcr0 = CLKXM | CLKRM | FSXP | FSRP | CLKXP | CLKRP, | ||
245 | //.pcr0 = CLKXP | CLKRP, /* mcbsp: slave */ | ||
246 | }; | ||
247 | |||
248 | static struct omap_alsa_codec_config alsa_config = { | ||
249 | .name = "H2 TSC2101", | ||
250 | .mcbsp_regs_alsa = &mcbsp_regs, | ||
251 | .codec_configure_dev = NULL, // tsc2101_configure, | ||
252 | .codec_set_samplerate = NULL, // tsc2101_set_samplerate, | ||
253 | .codec_clock_setup = NULL, // tsc2101_clock_setup, | ||
254 | .codec_clock_on = NULL, // tsc2101_clock_on, | ||
255 | .codec_clock_off = NULL, // tsc2101_clock_off, | ||
256 | .get_default_samplerate = NULL, // tsc2101_get_default_samplerate, | ||
257 | }; | ||
258 | |||
259 | static struct platform_device h2_mcbsp1_device = { | ||
260 | .name = "omap_alsa_mcbsp", | ||
261 | .id = 1, | ||
262 | .dev = { | ||
263 | .platform_data = &alsa_config, | ||
264 | }, | ||
265 | }; | ||
266 | |||
116 | static struct platform_device *h2_devices[] __initdata = { | 267 | static struct platform_device *h2_devices[] __initdata = { |
117 | &h2_flash_device, | 268 | &h2_nor_device, |
118 | &h2_smc91x_device, | 269 | &h2_smc91x_device, |
270 | &h2_irda_device, | ||
271 | &h2_kp_device, | ||
272 | &h2_lcd_device, | ||
273 | &h2_mcbsp1_device, | ||
119 | }; | 274 | }; |
120 | 275 | ||
121 | static void __init h2_init_smc91x(void) | 276 | static void __init h2_init_smc91x(void) |
@@ -164,7 +319,6 @@ static struct omap_uart_config h2_uart_config __initdata = { | |||
164 | }; | 319 | }; |
165 | 320 | ||
166 | static struct omap_lcd_config h2_lcd_config __initdata = { | 321 | static struct omap_lcd_config h2_lcd_config __initdata = { |
167 | .panel_name = "h2", | ||
168 | .ctrl_name = "internal", | 322 | .ctrl_name = "internal", |
169 | }; | 323 | }; |
170 | 324 | ||
@@ -177,16 +331,34 @@ static struct omap_board_config_kernel h2_config[] = { | |||
177 | 331 | ||
178 | static void __init h2_init(void) | 332 | static void __init h2_init(void) |
179 | { | 333 | { |
180 | /* NOTE: revC boards support NAND-boot, which can put NOR on CS2B | 334 | /* Here we assume the NOR boot config: NOR on CS3 (possibly swapped |
181 | * and NAND (either 16bit or 8bit) on CS3. | 335 | * to address 0 by a dip switch), NAND on CS2B. The NAND driver will |
336 | * notice whether a NAND chip is enabled at probe time. | ||
337 | * | ||
338 | * FIXME revC boards (and H3) support NAND-boot, with a dip switch to | ||
339 | * put NOR on CS2B and NAND (which on H2 may be 16bit) on CS3. Try | ||
340 | * detecting that in code here, to avoid probing every possible flash | ||
341 | * configuration... | ||
182 | */ | 342 | */ |
183 | h2_flash_resource.end = h2_flash_resource.start = omap_cs3_phys(); | 343 | h2_nor_resource.end = h2_nor_resource.start = omap_cs3_phys(); |
184 | h2_flash_resource.end += SZ_32M - 1; | 344 | h2_nor_resource.end += SZ_32M - 1; |
345 | |||
346 | omap_cfg_reg(L3_1610_FLASH_CS2B_OE); | ||
347 | omap_cfg_reg(M8_1610_FLASH_CS2B_WE); | ||
185 | 348 | ||
186 | /* MMC: card detect and WP */ | 349 | /* MMC: card detect and WP */ |
187 | // omap_cfg_reg(U19_ARMIO1); /* CD */ | 350 | // omap_cfg_reg(U19_ARMIO1); /* CD */ |
188 | omap_cfg_reg(BALLOUT_V8_ARMIO3); /* WP */ | 351 | omap_cfg_reg(BALLOUT_V8_ARMIO3); /* WP */ |
189 | 352 | ||
353 | /* Irda */ | ||
354 | #if defined(CONFIG_OMAP_IR) || defined(CONFIG_OMAP_IR_MODULE) | ||
355 | omap_writel(omap_readl(FUNC_MUX_CTRL_A) | 7, FUNC_MUX_CTRL_A); | ||
356 | if (!(omap_request_gpio(H2_IRDA_FIRSEL_GPIO_PIN))) { | ||
357 | omap_set_gpio_direction(H2_IRDA_FIRSEL_GPIO_PIN, 0); | ||
358 | h2_irda_data.transceiver_mode = h2_transceiver_mode; | ||
359 | } | ||
360 | #endif | ||
361 | |||
190 | platform_add_devices(h2_devices, ARRAY_SIZE(h2_devices)); | 362 | platform_add_devices(h2_devices, ARRAY_SIZE(h2_devices)); |
191 | omap_board_config = h2_config; | 363 | omap_board_config = h2_config; |
192 | omap_board_config_size = ARRAY_SIZE(h2_config); | 364 | omap_board_config_size = ARRAY_SIZE(h2_config); |
diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c index d9f386265996..4b8d0ec73cb7 100644 --- a/arch/arm/mach-omap1/board-h3.c +++ b/arch/arm/mach-omap1/board-h3.c | |||
@@ -21,8 +21,11 @@ | |||
21 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
22 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
23 | #include <linux/errno.h> | 23 | #include <linux/errno.h> |
24 | #include <linux/workqueue.h> | ||
24 | #include <linux/mtd/mtd.h> | 25 | #include <linux/mtd/mtd.h> |
26 | #include <linux/mtd/nand.h> | ||
25 | #include <linux/mtd/partitions.h> | 27 | #include <linux/mtd/partitions.h> |
28 | #include <linux/input.h> | ||
26 | 29 | ||
27 | #include <asm/setup.h> | 30 | #include <asm/setup.h> |
28 | #include <asm/page.h> | 31 | #include <asm/page.h> |
@@ -33,15 +36,59 @@ | |||
33 | #include <asm/mach/map.h> | 36 | #include <asm/mach/map.h> |
34 | 37 | ||
35 | #include <asm/arch/gpio.h> | 38 | #include <asm/arch/gpio.h> |
39 | #include <asm/arch/gpioexpander.h> | ||
36 | #include <asm/arch/irqs.h> | 40 | #include <asm/arch/irqs.h> |
37 | #include <asm/arch/mux.h> | 41 | #include <asm/arch/mux.h> |
38 | #include <asm/arch/tc.h> | 42 | #include <asm/arch/tc.h> |
43 | #include <asm/arch/irda.h> | ||
39 | #include <asm/arch/usb.h> | 44 | #include <asm/arch/usb.h> |
45 | #include <asm/arch/keypad.h> | ||
46 | #include <asm/arch/dma.h> | ||
40 | #include <asm/arch/common.h> | 47 | #include <asm/arch/common.h> |
41 | 48 | ||
42 | extern int omap_gpio_init(void); | 49 | extern int omap_gpio_init(void); |
43 | 50 | ||
44 | static struct mtd_partition h3_partitions[] = { | 51 | static int h3_keymap[] = { |
52 | KEY(0, 0, KEY_LEFT), | ||
53 | KEY(0, 1, KEY_RIGHT), | ||
54 | KEY(0, 2, KEY_3), | ||
55 | KEY(0, 3, KEY_F10), | ||
56 | KEY(0, 4, KEY_F5), | ||
57 | KEY(0, 5, KEY_9), | ||
58 | KEY(1, 0, KEY_DOWN), | ||
59 | KEY(1, 1, KEY_UP), | ||
60 | KEY(1, 2, KEY_2), | ||
61 | KEY(1, 3, KEY_F9), | ||
62 | KEY(1, 4, KEY_F7), | ||
63 | KEY(1, 5, KEY_0), | ||
64 | KEY(2, 0, KEY_ENTER), | ||
65 | KEY(2, 1, KEY_6), | ||
66 | KEY(2, 2, KEY_1), | ||
67 | KEY(2, 3, KEY_F2), | ||
68 | KEY(2, 4, KEY_F6), | ||
69 | KEY(2, 5, KEY_HOME), | ||
70 | KEY(3, 0, KEY_8), | ||
71 | KEY(3, 1, KEY_5), | ||
72 | KEY(3, 2, KEY_F12), | ||
73 | KEY(3, 3, KEY_F3), | ||
74 | KEY(3, 4, KEY_F8), | ||
75 | KEY(3, 5, KEY_END), | ||
76 | KEY(4, 0, KEY_7), | ||
77 | KEY(4, 1, KEY_4), | ||
78 | KEY(4, 2, KEY_F11), | ||
79 | KEY(4, 3, KEY_F1), | ||
80 | KEY(4, 4, KEY_F4), | ||
81 | KEY(4, 5, KEY_ESC), | ||
82 | KEY(5, 0, KEY_F13), | ||
83 | KEY(5, 1, KEY_F14), | ||
84 | KEY(5, 2, KEY_F15), | ||
85 | KEY(5, 3, KEY_F16), | ||
86 | KEY(5, 4, KEY_SLEEP), | ||
87 | 0 | ||
88 | }; | ||
89 | |||
90 | |||
91 | static struct mtd_partition nor_partitions[] = { | ||
45 | /* bootloader (U-Boot, etc) in first sector */ | 92 | /* bootloader (U-Boot, etc) in first sector */ |
46 | { | 93 | { |
47 | .name = "bootloader", | 94 | .name = "bootloader", |
@@ -72,26 +119,80 @@ static struct mtd_partition h3_partitions[] = { | |||
72 | } | 119 | } |
73 | }; | 120 | }; |
74 | 121 | ||
75 | static struct flash_platform_data h3_flash_data = { | 122 | static struct flash_platform_data nor_data = { |
76 | .map_name = "cfi_probe", | 123 | .map_name = "cfi_probe", |
77 | .width = 2, | 124 | .width = 2, |
78 | .parts = h3_partitions, | 125 | .parts = nor_partitions, |
79 | .nr_parts = ARRAY_SIZE(h3_partitions), | 126 | .nr_parts = ARRAY_SIZE(nor_partitions), |
80 | }; | 127 | }; |
81 | 128 | ||
82 | static struct resource h3_flash_resource = { | 129 | static struct resource nor_resource = { |
83 | /* This is on CS3, wherever it's mapped */ | 130 | /* This is on CS3, wherever it's mapped */ |
84 | .flags = IORESOURCE_MEM, | 131 | .flags = IORESOURCE_MEM, |
85 | }; | 132 | }; |
86 | 133 | ||
87 | static struct platform_device flash_device = { | 134 | static struct platform_device nor_device = { |
88 | .name = "omapflash", | 135 | .name = "omapflash", |
89 | .id = 0, | 136 | .id = 0, |
90 | .dev = { | 137 | .dev = { |
91 | .platform_data = &h3_flash_data, | 138 | .platform_data = &nor_data, |
139 | }, | ||
140 | .num_resources = 1, | ||
141 | .resource = &nor_resource, | ||
142 | }; | ||
143 | |||
144 | static struct mtd_partition nand_partitions[] = { | ||
145 | #if 0 | ||
146 | /* REVISIT: enable these partitions if you make NAND BOOT work */ | ||
147 | { | ||
148 | .name = "xloader", | ||
149 | .offset = 0, | ||
150 | .size = 64 * 1024, | ||
151 | .mask_flags = MTD_WRITEABLE, /* force read-only */ | ||
152 | }, | ||
153 | { | ||
154 | .name = "bootloader", | ||
155 | .offset = MTDPART_OFS_APPEND, | ||
156 | .size = 256 * 1024, | ||
157 | .mask_flags = MTD_WRITEABLE, /* force read-only */ | ||
158 | }, | ||
159 | { | ||
160 | .name = "params", | ||
161 | .offset = MTDPART_OFS_APPEND, | ||
162 | .size = 192 * 1024, | ||
163 | }, | ||
164 | { | ||
165 | .name = "kernel", | ||
166 | .offset = MTDPART_OFS_APPEND, | ||
167 | .size = 2 * SZ_1M, | ||
168 | }, | ||
169 | #endif | ||
170 | { | ||
171 | .name = "filesystem", | ||
172 | .size = MTDPART_SIZ_FULL, | ||
173 | .offset = MTDPART_OFS_APPEND, | ||
174 | }, | ||
175 | }; | ||
176 | |||
177 | /* dip switches control NAND chip access: 8 bit, 16 bit, or neither */ | ||
178 | static struct nand_platform_data nand_data = { | ||
179 | .options = NAND_SAMSUNG_LP_OPTIONS, | ||
180 | .parts = nand_partitions, | ||
181 | .nr_parts = ARRAY_SIZE(nand_partitions), | ||
182 | }; | ||
183 | |||
184 | static struct resource nand_resource = { | ||
185 | .flags = IORESOURCE_MEM, | ||
186 | }; | ||
187 | |||
188 | static struct platform_device nand_device = { | ||
189 | .name = "omapnand", | ||
190 | .id = 0, | ||
191 | .dev = { | ||
192 | .platform_data = &nand_data, | ||
92 | }, | 193 | }, |
93 | .num_resources = 1, | 194 | .num_resources = 1, |
94 | .resource = &h3_flash_resource, | 195 | .resource = &nand_resource, |
95 | }; | 196 | }; |
96 | 197 | ||
97 | static struct resource smc91x_resources[] = { | 198 | static struct resource smc91x_resources[] = { |
@@ -138,10 +239,136 @@ static struct platform_device intlat_device = { | |||
138 | .resource = intlat_resources, | 239 | .resource = intlat_resources, |
139 | }; | 240 | }; |
140 | 241 | ||
242 | static struct resource h3_kp_resources[] = { | ||
243 | [0] = { | ||
244 | .start = INT_KEYBOARD, | ||
245 | .end = INT_KEYBOARD, | ||
246 | .flags = IORESOURCE_IRQ, | ||
247 | }, | ||
248 | }; | ||
249 | |||
250 | static struct omap_kp_platform_data h3_kp_data = { | ||
251 | .rows = 8, | ||
252 | .cols = 8, | ||
253 | .keymap = h3_keymap, | ||
254 | .rep = 1, | ||
255 | }; | ||
256 | |||
257 | static struct platform_device h3_kp_device = { | ||
258 | .name = "omap-keypad", | ||
259 | .id = -1, | ||
260 | .dev = { | ||
261 | .platform_data = &h3_kp_data, | ||
262 | }, | ||
263 | .num_resources = ARRAY_SIZE(h3_kp_resources), | ||
264 | .resource = h3_kp_resources, | ||
265 | }; | ||
266 | |||
267 | |||
268 | /* Select between the IrDA and aGPS module | ||
269 | */ | ||
270 | static int h3_select_irda(struct device *dev, int state) | ||
271 | { | ||
272 | unsigned char expa; | ||
273 | int err = 0; | ||
274 | |||
275 | if ((err = read_gpio_expa(&expa, 0x26))) { | ||
276 | printk(KERN_ERR "Error reading from I/O EXPANDER \n"); | ||
277 | return err; | ||
278 | } | ||
279 | |||
280 | /* 'P6' enable/disable IRDA_TX and IRDA_RX */ | ||
281 | if (state & IR_SEL) { /* IrDA */ | ||
282 | if ((err = write_gpio_expa(expa | 0x40, 0x26))) { | ||
283 | printk(KERN_ERR "Error writing to I/O EXPANDER \n"); | ||
284 | return err; | ||
285 | } | ||
286 | } else { | ||
287 | if ((err = write_gpio_expa(expa & ~0x40, 0x26))) { | ||
288 | printk(KERN_ERR "Error writing to I/O EXPANDER \n"); | ||
289 | return err; | ||
290 | } | ||
291 | } | ||
292 | return err; | ||
293 | } | ||
294 | |||
295 | static void set_trans_mode(void *data) | ||
296 | { | ||
297 | int *mode = data; | ||
298 | unsigned char expa; | ||
299 | int err = 0; | ||
300 | |||
301 | if ((err = read_gpio_expa(&expa, 0x27)) != 0) { | ||
302 | printk(KERN_ERR "Error reading from I/O expander\n"); | ||
303 | } | ||
304 | |||
305 | expa &= ~0x03; | ||
306 | |||
307 | if (*mode & IR_SIRMODE) { | ||
308 | expa |= 0x01; | ||
309 | } else { /* MIR/FIR */ | ||
310 | expa |= 0x03; | ||
311 | } | ||
312 | |||
313 | if ((err = write_gpio_expa(expa, 0x27)) != 0) { | ||
314 | printk(KERN_ERR "Error writing to I/O expander\n"); | ||
315 | } | ||
316 | } | ||
317 | |||
318 | static int h3_transceiver_mode(struct device *dev, int mode) | ||
319 | { | ||
320 | struct omap_irda_config *irda_config = dev->platform_data; | ||
321 | |||
322 | cancel_delayed_work(&irda_config->gpio_expa); | ||
323 | PREPARE_WORK(&irda_config->gpio_expa, set_trans_mode, &mode); | ||
324 | schedule_work(&irda_config->gpio_expa); | ||
325 | |||
326 | return 0; | ||
327 | } | ||
328 | |||
329 | static struct omap_irda_config h3_irda_data = { | ||
330 | .transceiver_cap = IR_SIRMODE | IR_MIRMODE | IR_FIRMODE, | ||
331 | .transceiver_mode = h3_transceiver_mode, | ||
332 | .select_irda = h3_select_irda, | ||
333 | .rx_channel = OMAP_DMA_UART3_RX, | ||
334 | .tx_channel = OMAP_DMA_UART3_TX, | ||
335 | .dest_start = UART3_THR, | ||
336 | .src_start = UART3_RHR, | ||
337 | .tx_trigger = 0, | ||
338 | .rx_trigger = 0, | ||
339 | }; | ||
340 | |||
341 | static struct resource h3_irda_resources[] = { | ||
342 | [0] = { | ||
343 | .start = INT_UART3, | ||
344 | .end = INT_UART3, | ||
345 | .flags = IORESOURCE_IRQ, | ||
346 | }, | ||
347 | }; | ||
348 | |||
349 | static struct platform_device h3_irda_device = { | ||
350 | .name = "omapirda", | ||
351 | .id = 0, | ||
352 | .dev = { | ||
353 | .platform_data = &h3_irda_data, | ||
354 | }, | ||
355 | .num_resources = ARRAY_SIZE(h3_irda_resources), | ||
356 | .resource = h3_irda_resources, | ||
357 | }; | ||
358 | |||
359 | static struct platform_device h3_lcd_device = { | ||
360 | .name = "lcd_h3", | ||
361 | .id = -1, | ||
362 | }; | ||
363 | |||
141 | static struct platform_device *devices[] __initdata = { | 364 | static struct platform_device *devices[] __initdata = { |
142 | &flash_device, | 365 | &nor_device, |
366 | &nand_device, | ||
143 | &smc91x_device, | 367 | &smc91x_device, |
144 | &intlat_device, | 368 | &intlat_device, |
369 | &h3_irda_device, | ||
370 | &h3_kp_device, | ||
371 | &h3_lcd_device, | ||
145 | }; | 372 | }; |
146 | 373 | ||
147 | static struct omap_usb_config h3_usb_config __initdata = { | 374 | static struct omap_usb_config h3_usb_config __initdata = { |
@@ -171,7 +398,6 @@ static struct omap_uart_config h3_uart_config __initdata = { | |||
171 | }; | 398 | }; |
172 | 399 | ||
173 | static struct omap_lcd_config h3_lcd_config __initdata = { | 400 | static struct omap_lcd_config h3_lcd_config __initdata = { |
174 | .panel_name = "h3", | ||
175 | .ctrl_name = "internal", | 401 | .ctrl_name = "internal", |
176 | }; | 402 | }; |
177 | 403 | ||
@@ -182,11 +408,36 @@ static struct omap_board_config_kernel h3_config[] = { | |||
182 | { OMAP_TAG_LCD, &h3_lcd_config }, | 408 | { OMAP_TAG_LCD, &h3_lcd_config }, |
183 | }; | 409 | }; |
184 | 410 | ||
411 | #define H3_NAND_RB_GPIO_PIN 10 | ||
412 | |||
413 | static int nand_dev_ready(struct nand_platform_data *data) | ||
414 | { | ||
415 | return omap_get_gpio_datain(H3_NAND_RB_GPIO_PIN); | ||
416 | } | ||
417 | |||
185 | static void __init h3_init(void) | 418 | static void __init h3_init(void) |
186 | { | 419 | { |
187 | h3_flash_resource.end = h3_flash_resource.start = omap_cs3_phys(); | 420 | /* Here we assume the NOR boot config: NOR on CS3 (possibly swapped |
188 | h3_flash_resource.end += OMAP_CS3_SIZE - 1; | 421 | * to address 0 by a dip switch), NAND on CS2B. The NAND driver will |
189 | (void) platform_add_devices(devices, ARRAY_SIZE(devices)); | 422 | * notice whether a NAND chip is enabled at probe time. |
423 | * | ||
424 | * H3 support NAND-boot, with a dip switch to put NOR on CS2B and NAND | ||
425 | * (which on H2 may be 16bit) on CS3. Try detecting that in code here, | ||
426 | * to avoid probing every possible flash configuration... | ||
427 | */ | ||
428 | nor_resource.end = nor_resource.start = omap_cs3_phys(); | ||
429 | nor_resource.end += SZ_32M - 1; | ||
430 | |||
431 | nand_resource.end = nand_resource.start = OMAP_CS2B_PHYS; | ||
432 | nand_resource.end += SZ_4K - 1; | ||
433 | if (!(omap_request_gpio(H3_NAND_RB_GPIO_PIN))) | ||
434 | nand_data.dev_ready = nand_dev_ready; | ||
435 | |||
436 | /* GPIO10 Func_MUX_CTRL reg bit 29:27, Configure V2 to mode1 as GPIO */ | ||
437 | /* GPIO10 pullup/down register, Enable pullup on GPIO10 */ | ||
438 | omap_cfg_reg(V2_1710_GPIO10); | ||
439 | |||
440 | platform_add_devices(devices, ARRAY_SIZE(devices)); | ||
190 | omap_board_config = h3_config; | 441 | omap_board_config = h3_config; |
191 | omap_board_config_size = ARRAY_SIZE(h3_config); | 442 | omap_board_config_size = ARRAY_SIZE(h3_config); |
192 | omap_serial_init(); | 443 | omap_serial_init(); |
diff --git a/arch/arm/mach-omap1/board-innovator.c b/arch/arm/mach-omap1/board-innovator.c index a04e4332915e..e90c137a4cf3 100644 --- a/arch/arm/mach-omap1/board-innovator.c +++ b/arch/arm/mach-omap1/board-innovator.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
23 | #include <linux/mtd/mtd.h> | 23 | #include <linux/mtd/mtd.h> |
24 | #include <linux/mtd/partitions.h> | 24 | #include <linux/mtd/partitions.h> |
25 | #include <linux/input.h> | ||
25 | 26 | ||
26 | #include <asm/hardware.h> | 27 | #include <asm/hardware.h> |
27 | #include <asm/mach-types.h> | 28 | #include <asm/mach-types.h> |
@@ -34,8 +35,22 @@ | |||
34 | #include <asm/arch/gpio.h> | 35 | #include <asm/arch/gpio.h> |
35 | #include <asm/arch/tc.h> | 36 | #include <asm/arch/tc.h> |
36 | #include <asm/arch/usb.h> | 37 | #include <asm/arch/usb.h> |
38 | #include <asm/arch/keypad.h> | ||
37 | #include <asm/arch/common.h> | 39 | #include <asm/arch/common.h> |
38 | 40 | ||
41 | static int innovator_keymap[] = { | ||
42 | KEY(0, 0, KEY_F1), | ||
43 | KEY(0, 3, KEY_DOWN), | ||
44 | KEY(1, 1, KEY_F2), | ||
45 | KEY(1, 2, KEY_RIGHT), | ||
46 | KEY(2, 0, KEY_F3), | ||
47 | KEY(2, 1, KEY_F4), | ||
48 | KEY(2, 2, KEY_UP), | ||
49 | KEY(3, 2, KEY_ENTER), | ||
50 | KEY(3, 3, KEY_LEFT), | ||
51 | 0 | ||
52 | }; | ||
53 | |||
39 | static struct mtd_partition innovator_partitions[] = { | 54 | static struct mtd_partition innovator_partitions[] = { |
40 | /* bootloader (U-Boot, etc) in first sector */ | 55 | /* bootloader (U-Boot, etc) in first sector */ |
41 | { | 56 | { |
@@ -97,6 +112,31 @@ static struct platform_device innovator_flash_device = { | |||
97 | .resource = &innovator_flash_resource, | 112 | .resource = &innovator_flash_resource, |
98 | }; | 113 | }; |
99 | 114 | ||
115 | static struct resource innovator_kp_resources[] = { | ||
116 | [0] = { | ||
117 | .start = INT_KEYBOARD, | ||
118 | .end = INT_KEYBOARD, | ||
119 | .flags = IORESOURCE_IRQ, | ||
120 | }, | ||
121 | }; | ||
122 | |||
123 | static struct omap_kp_platform_data innovator_kp_data = { | ||
124 | .rows = 8, | ||
125 | .cols = 8, | ||
126 | .keymap = innovator_keymap, | ||
127 | }; | ||
128 | |||
129 | static struct platform_device innovator_kp_device = { | ||
130 | .name = "omap-keypad", | ||
131 | .id = -1, | ||
132 | .dev = { | ||
133 | .platform_data = &innovator_kp_data, | ||
134 | }, | ||
135 | .num_resources = ARRAY_SIZE(innovator_kp_resources), | ||
136 | .resource = innovator_kp_resources, | ||
137 | }; | ||
138 | |||
139 | |||
100 | #ifdef CONFIG_ARCH_OMAP15XX | 140 | #ifdef CONFIG_ARCH_OMAP15XX |
101 | 141 | ||
102 | /* Only FPGA needs to be mapped here. All others are done with ioremap */ | 142 | /* Only FPGA needs to be mapped here. All others are done with ioremap */ |
@@ -129,9 +169,16 @@ static struct platform_device innovator1510_smc91x_device = { | |||
129 | .resource = innovator1510_smc91x_resources, | 169 | .resource = innovator1510_smc91x_resources, |
130 | }; | 170 | }; |
131 | 171 | ||
172 | static struct platform_device innovator1510_lcd_device = { | ||
173 | .name = "lcd_inn1510", | ||
174 | .id = -1, | ||
175 | }; | ||
176 | |||
132 | static struct platform_device *innovator1510_devices[] __initdata = { | 177 | static struct platform_device *innovator1510_devices[] __initdata = { |
133 | &innovator_flash_device, | 178 | &innovator_flash_device, |
134 | &innovator1510_smc91x_device, | 179 | &innovator1510_smc91x_device, |
180 | &innovator_kp_device, | ||
181 | &innovator1510_lcd_device, | ||
135 | }; | 182 | }; |
136 | 183 | ||
137 | #endif /* CONFIG_ARCH_OMAP15XX */ | 184 | #endif /* CONFIG_ARCH_OMAP15XX */ |
@@ -158,9 +205,16 @@ static struct platform_device innovator1610_smc91x_device = { | |||
158 | .resource = innovator1610_smc91x_resources, | 205 | .resource = innovator1610_smc91x_resources, |
159 | }; | 206 | }; |
160 | 207 | ||
208 | static struct platform_device innovator1610_lcd_device = { | ||
209 | .name = "inn1610_lcd", | ||
210 | .id = -1, | ||
211 | }; | ||
212 | |||
161 | static struct platform_device *innovator1610_devices[] __initdata = { | 213 | static struct platform_device *innovator1610_devices[] __initdata = { |
162 | &innovator_flash_device, | 214 | &innovator_flash_device, |
163 | &innovator1610_smc91x_device, | 215 | &innovator1610_smc91x_device, |
216 | &innovator_kp_device, | ||
217 | &innovator1610_lcd_device, | ||
164 | }; | 218 | }; |
165 | 219 | ||
166 | #endif /* CONFIG_ARCH_OMAP16XX */ | 220 | #endif /* CONFIG_ARCH_OMAP16XX */ |
@@ -206,7 +260,6 @@ static struct omap_usb_config innovator1510_usb_config __initdata = { | |||
206 | }; | 260 | }; |
207 | 261 | ||
208 | static struct omap_lcd_config innovator1510_lcd_config __initdata = { | 262 | static struct omap_lcd_config innovator1510_lcd_config __initdata = { |
209 | .panel_name = "inn1510", | ||
210 | .ctrl_name = "internal", | 263 | .ctrl_name = "internal", |
211 | }; | 264 | }; |
212 | #endif | 265 | #endif |
@@ -228,7 +281,6 @@ static struct omap_usb_config h2_usb_config __initdata = { | |||
228 | }; | 281 | }; |
229 | 282 | ||
230 | static struct omap_lcd_config innovator1610_lcd_config __initdata = { | 283 | static struct omap_lcd_config innovator1610_lcd_config __initdata = { |
231 | .panel_name = "inn1610", | ||
232 | .ctrl_name = "internal", | 284 | .ctrl_name = "internal", |
233 | }; | 285 | }; |
234 | #endif | 286 | #endif |
diff --git a/arch/arm/mach-omap1/board-netstar.c b/arch/arm/mach-omap1/board-netstar.c deleted file mode 100644 index 7520e602d7a2..000000000000 --- a/arch/arm/mach-omap1/board-netstar.c +++ /dev/null | |||
@@ -1,160 +0,0 @@ | |||
1 | /* | ||
2 | * Modified from board-generic.c | ||
3 | * | ||
4 | * Copyright (C) 2004 2N Telekomunikace, Ladislav Michl <michl@2n.cz> | ||
5 | * | ||
6 | * Code for Netstar OMAP board. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/delay.h> | ||
14 | #include <linux/platform_device.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/notifier.h> | ||
19 | #include <linux/reboot.h> | ||
20 | |||
21 | #include <asm/hardware.h> | ||
22 | #include <asm/mach-types.h> | ||
23 | #include <asm/mach/arch.h> | ||
24 | #include <asm/mach/map.h> | ||
25 | |||
26 | #include <asm/arch/gpio.h> | ||
27 | #include <asm/arch/mux.h> | ||
28 | #include <asm/arch/usb.h> | ||
29 | #include <asm/arch/common.h> | ||
30 | |||
31 | extern void __init omap_init_time(void); | ||
32 | extern int omap_gpio_init(void); | ||
33 | |||
34 | static struct resource netstar_smc91x_resources[] = { | ||
35 | [0] = { | ||
36 | .start = OMAP_CS1_PHYS + 0x300, | ||
37 | .end = OMAP_CS1_PHYS + 0x300 + 16, | ||
38 | .flags = IORESOURCE_MEM, | ||
39 | }, | ||
40 | [1] = { | ||
41 | .start = OMAP_GPIO_IRQ(8), | ||
42 | .end = OMAP_GPIO_IRQ(8), | ||
43 | .flags = IORESOURCE_IRQ, | ||
44 | }, | ||
45 | }; | ||
46 | |||
47 | static struct platform_device netstar_smc91x_device = { | ||
48 | .name = "smc91x", | ||
49 | .id = 0, | ||
50 | .num_resources = ARRAY_SIZE(netstar_smc91x_resources), | ||
51 | .resource = netstar_smc91x_resources, | ||
52 | }; | ||
53 | |||
54 | static struct platform_device *netstar_devices[] __initdata = { | ||
55 | &netstar_smc91x_device, | ||
56 | }; | ||
57 | |||
58 | static struct omap_uart_config netstar_uart_config __initdata = { | ||
59 | .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)), | ||
60 | }; | ||
61 | |||
62 | static struct omap_board_config_kernel netstar_config[] = { | ||
63 | { OMAP_TAG_UART, &netstar_uart_config }, | ||
64 | }; | ||
65 | |||
66 | static void __init netstar_init_irq(void) | ||
67 | { | ||
68 | omap1_init_common_hw(); | ||
69 | omap_init_irq(); | ||
70 | omap_gpio_init(); | ||
71 | } | ||
72 | |||
73 | static void __init netstar_init(void) | ||
74 | { | ||
75 | /* green LED */ | ||
76 | omap_request_gpio(4); | ||
77 | omap_set_gpio_direction(4, 0); | ||
78 | /* smc91x reset */ | ||
79 | omap_request_gpio(7); | ||
80 | omap_set_gpio_direction(7, 0); | ||
81 | omap_set_gpio_dataout(7, 1); | ||
82 | udelay(2); /* wait at least 100ns */ | ||
83 | omap_set_gpio_dataout(7, 0); | ||
84 | mdelay(50); /* 50ms until PHY ready */ | ||
85 | /* smc91x interrupt pin */ | ||
86 | omap_request_gpio(8); | ||
87 | |||
88 | omap_request_gpio(12); | ||
89 | omap_request_gpio(13); | ||
90 | omap_request_gpio(14); | ||
91 | omap_request_gpio(15); | ||
92 | set_irq_type(OMAP_GPIO_IRQ(12), IRQT_FALLING); | ||
93 | set_irq_type(OMAP_GPIO_IRQ(13), IRQT_FALLING); | ||
94 | set_irq_type(OMAP_GPIO_IRQ(14), IRQT_FALLING); | ||
95 | set_irq_type(OMAP_GPIO_IRQ(15), IRQT_FALLING); | ||
96 | |||
97 | platform_add_devices(netstar_devices, ARRAY_SIZE(netstar_devices)); | ||
98 | |||
99 | /* Switch on green LED */ | ||
100 | omap_set_gpio_dataout(4, 0); | ||
101 | /* Switch off red LED */ | ||
102 | omap_writeb(0x00, OMAP_LPG1_PMR); /* Disable clock */ | ||
103 | omap_writeb(0x80, OMAP_LPG1_LCR); | ||
104 | |||
105 | omap_board_config = netstar_config; | ||
106 | omap_board_config_size = ARRAY_SIZE(netstar_config); | ||
107 | omap_serial_init(); | ||
108 | } | ||
109 | |||
110 | static void __init netstar_map_io(void) | ||
111 | { | ||
112 | omap1_map_common_io(); | ||
113 | } | ||
114 | |||
115 | #define MACHINE_PANICED 1 | ||
116 | #define MACHINE_REBOOTING 2 | ||
117 | #define MACHINE_REBOOT 4 | ||
118 | static unsigned long machine_state; | ||
119 | |||
120 | static int panic_event(struct notifier_block *this, unsigned long event, | ||
121 | void *ptr) | ||
122 | { | ||
123 | if (test_and_set_bit(MACHINE_PANICED, &machine_state)) | ||
124 | return NOTIFY_DONE; | ||
125 | |||
126 | /* Switch off green LED */ | ||
127 | omap_set_gpio_dataout(4, 1); | ||
128 | /* Flash red LED */ | ||
129 | omap_writeb(0x78, OMAP_LPG1_LCR); | ||
130 | omap_writeb(0x01, OMAP_LPG1_PMR); /* Enable clock */ | ||
131 | |||
132 | return NOTIFY_DONE; | ||
133 | } | ||
134 | |||
135 | static struct notifier_block panic_block = { | ||
136 | .notifier_call = panic_event, | ||
137 | }; | ||
138 | |||
139 | static int __init netstar_late_init(void) | ||
140 | { | ||
141 | /* TODO: Setup front panel switch here */ | ||
142 | |||
143 | /* Setup panic notifier */ | ||
144 | atomic_notifier_chain_register(&panic_notifier_list, &panic_block); | ||
145 | |||
146 | return 0; | ||
147 | } | ||
148 | |||
149 | postcore_initcall(netstar_late_init); | ||
150 | |||
151 | MACHINE_START(NETSTAR, "NetStar OMAP5910") | ||
152 | /* Maintainer: Ladislav Michl <michl@2n.cz> */ | ||
153 | .phys_io = 0xfff00000, | ||
154 | .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc, | ||
155 | .boot_params = 0x10000100, | ||
156 | .map_io = netstar_map_io, | ||
157 | .init_irq = netstar_init_irq, | ||
158 | .init_machine = netstar_init, | ||
159 | .timer = &omap_timer, | ||
160 | MACHINE_END | ||
diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c new file mode 100644 index 000000000000..02b980d77b12 --- /dev/null +++ b/arch/arm/mach-omap1/board-nokia770.c | |||
@@ -0,0 +1,268 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-omap1/board-nokia770.c | ||
3 | * | ||
4 | * Modified from board-generic.c | ||
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 | |||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/platform_device.h> | ||
14 | #include <linux/input.h> | ||
15 | #include <linux/clk.h> | ||
16 | |||
17 | #include <linux/spi/spi.h> | ||
18 | #include <linux/spi/ads7846.h> | ||
19 | |||
20 | #include <asm/hardware.h> | ||
21 | #include <asm/mach-types.h> | ||
22 | #include <asm/mach/arch.h> | ||
23 | #include <asm/mach/map.h> | ||
24 | |||
25 | #include <asm/arch/gpio.h> | ||
26 | #include <asm/arch/mux.h> | ||
27 | #include <asm/arch/usb.h> | ||
28 | #include <asm/arch/board.h> | ||
29 | #include <asm/arch/keypad.h> | ||
30 | #include <asm/arch/common.h> | ||
31 | #include <asm/arch/dsp_common.h> | ||
32 | #include <asm/arch/aic23.h> | ||
33 | #include <asm/arch/gpio.h> | ||
34 | |||
35 | static void __init omap_nokia770_init_irq(void) | ||
36 | { | ||
37 | /* On Nokia 770, the SleepX signal is masked with an | ||
38 | * MPUIO line by default. It has to be unmasked for it | ||
39 | * to become functional */ | ||
40 | |||
41 | /* SleepX mask direction */ | ||
42 | omap_writew((omap_readw(0xfffb5008) & ~2), 0xfffb5008); | ||
43 | /* Unmask SleepX signal */ | ||
44 | omap_writew((omap_readw(0xfffb5004) & ~2), 0xfffb5004); | ||
45 | |||
46 | omap1_init_common_hw(); | ||
47 | omap_init_irq(); | ||
48 | } | ||
49 | |||
50 | static int nokia770_keymap[] = { | ||
51 | KEY(0, 1, GROUP_0 | KEY_UP), | ||
52 | KEY(0, 2, GROUP_1 | KEY_F5), | ||
53 | KEY(1, 0, GROUP_0 | KEY_LEFT), | ||
54 | KEY(1, 1, GROUP_0 | KEY_ENTER), | ||
55 | KEY(1, 2, GROUP_0 | KEY_RIGHT), | ||
56 | KEY(2, 0, GROUP_1 | KEY_ESC), | ||
57 | KEY(2, 1, GROUP_0 | KEY_DOWN), | ||
58 | KEY(2, 2, GROUP_1 | KEY_F4), | ||
59 | KEY(3, 0, GROUP_2 | KEY_F7), | ||
60 | KEY(3, 1, GROUP_2 | KEY_F8), | ||
61 | KEY(3, 2, GROUP_2 | KEY_F6), | ||
62 | 0 | ||
63 | }; | ||
64 | |||
65 | static struct resource nokia770_kp_resources[] = { | ||
66 | [0] = { | ||
67 | .start = INT_KEYBOARD, | ||
68 | .end = INT_KEYBOARD, | ||
69 | .flags = IORESOURCE_IRQ, | ||
70 | }, | ||
71 | }; | ||
72 | |||
73 | static struct omap_kp_platform_data nokia770_kp_data = { | ||
74 | .rows = 8, | ||
75 | .cols = 8, | ||
76 | .keymap = nokia770_keymap | ||
77 | }; | ||
78 | |||
79 | static struct platform_device nokia770_kp_device = { | ||
80 | .name = "omap-keypad", | ||
81 | .id = -1, | ||
82 | .dev = { | ||
83 | .platform_data = &nokia770_kp_data, | ||
84 | }, | ||
85 | .num_resources = ARRAY_SIZE(nokia770_kp_resources), | ||
86 | .resource = nokia770_kp_resources, | ||
87 | }; | ||
88 | |||
89 | static struct platform_device *nokia770_devices[] __initdata = { | ||
90 | &nokia770_kp_device, | ||
91 | }; | ||
92 | |||
93 | static struct ads7846_platform_data nokia770_ads7846_platform_data __initdata = { | ||
94 | .x_max = 0x0fff, | ||
95 | .y_max = 0x0fff, | ||
96 | .x_plate_ohms = 180, | ||
97 | .pressure_max = 255, | ||
98 | .debounce_max = 10, | ||
99 | .debounce_tol = 3, | ||
100 | }; | ||
101 | |||
102 | static struct spi_board_info nokia770_spi_board_info[] __initdata = { | ||
103 | [0] = { | ||
104 | .modalias = "lcd_lph8923", | ||
105 | .bus_num = 2, | ||
106 | .chip_select = 3, | ||
107 | .max_speed_hz = 12000000, | ||
108 | }, | ||
109 | [1] = { | ||
110 | .modalias = "ads7846", | ||
111 | .bus_num = 2, | ||
112 | .chip_select = 0, | ||
113 | .max_speed_hz = 2500000, | ||
114 | .irq = OMAP_GPIO_IRQ(15), | ||
115 | .platform_data = &nokia770_ads7846_platform_data, | ||
116 | }, | ||
117 | }; | ||
118 | |||
119 | |||
120 | /* assume no Mini-AB port */ | ||
121 | |||
122 | static struct omap_usb_config nokia770_usb_config __initdata = { | ||
123 | .otg = 1, | ||
124 | .register_host = 1, | ||
125 | .register_dev = 1, | ||
126 | .hmc_mode = 16, | ||
127 | .pins[0] = 6, | ||
128 | }; | ||
129 | |||
130 | static struct omap_mmc_config nokia770_mmc_config __initdata = { | ||
131 | .mmc[0] = { | ||
132 | .enabled = 0, | ||
133 | .wire4 = 0, | ||
134 | .wp_pin = -1, | ||
135 | .power_pin = -1, | ||
136 | .switch_pin = -1, | ||
137 | }, | ||
138 | .mmc[1] = { | ||
139 | .enabled = 0, | ||
140 | .wire4 = 0, | ||
141 | .wp_pin = -1, | ||
142 | .power_pin = -1, | ||
143 | .switch_pin = -1, | ||
144 | }, | ||
145 | }; | ||
146 | |||
147 | static struct omap_board_config_kernel nokia770_config[] = { | ||
148 | { OMAP_TAG_USB, NULL }, | ||
149 | { OMAP_TAG_MMC, &nokia770_mmc_config }, | ||
150 | }; | ||
151 | |||
152 | /* | ||
153 | * audio power control | ||
154 | */ | ||
155 | #define HEADPHONE_GPIO 14 | ||
156 | #define AMPLIFIER_CTRL_GPIO 58 | ||
157 | |||
158 | static struct clk *dspxor_ck; | ||
159 | static DECLARE_MUTEX(audio_pwr_sem); | ||
160 | /* | ||
161 | * audio_pwr_state | ||
162 | * +--+-------------------------+---------------------------------------+ | ||
163 | * |-1|down |power-up request -> 0 | | ||
164 | * +--+-------------------------+---------------------------------------+ | ||
165 | * | 0|up |power-down(1) request -> 1 | | ||
166 | * | | |power-down(2) request -> (ignore) | | ||
167 | * +--+-------------------------+---------------------------------------+ | ||
168 | * | 1|up, |power-up request -> 0 | | ||
169 | * | |received down(1) request |power-down(2) request -> -1 | | ||
170 | * +--+-------------------------+---------------------------------------+ | ||
171 | */ | ||
172 | static int audio_pwr_state = -1; | ||
173 | |||
174 | /* | ||
175 | * audio_pwr_up / down should be called under audio_pwr_sem | ||
176 | */ | ||
177 | static void nokia770_audio_pwr_up(void) | ||
178 | { | ||
179 | clk_enable(dspxor_ck); | ||
180 | |||
181 | /* Turn on codec */ | ||
182 | tlv320aic23_power_up(); | ||
183 | |||
184 | if (omap_get_gpio_datain(HEADPHONE_GPIO)) | ||
185 | /* HP not connected, turn on amplifier */ | ||
186 | omap_set_gpio_dataout(AMPLIFIER_CTRL_GPIO, 1); | ||
187 | else | ||
188 | /* HP connected, do not turn on amplifier */ | ||
189 | printk("HP connected\n"); | ||
190 | } | ||
191 | |||
192 | static void codec_delayed_power_down(void *arg) | ||
193 | { | ||
194 | down(&audio_pwr_sem); | ||
195 | if (audio_pwr_state == -1) | ||
196 | tlv320aic23_power_down(); | ||
197 | clk_disable(dspxor_ck); | ||
198 | up(&audio_pwr_sem); | ||
199 | } | ||
200 | |||
201 | static DECLARE_WORK(codec_power_down_work, codec_delayed_power_down, NULL); | ||
202 | |||
203 | static void nokia770_audio_pwr_down(void) | ||
204 | { | ||
205 | /* Turn off amplifier */ | ||
206 | omap_set_gpio_dataout(AMPLIFIER_CTRL_GPIO, 0); | ||
207 | |||
208 | /* Turn off codec: schedule delayed work */ | ||
209 | schedule_delayed_work(&codec_power_down_work, HZ / 20); /* 50ms */ | ||
210 | } | ||
211 | |||
212 | void nokia770_audio_pwr_up_request(int stage) | ||
213 | { | ||
214 | down(&audio_pwr_sem); | ||
215 | if (audio_pwr_state == -1) | ||
216 | nokia770_audio_pwr_up(); | ||
217 | /* force audio_pwr_state = 0, even if it was 1. */ | ||
218 | audio_pwr_state = 0; | ||
219 | up(&audio_pwr_sem); | ||
220 | } | ||
221 | |||
222 | void nokia770_audio_pwr_down_request(int stage) | ||
223 | { | ||
224 | down(&audio_pwr_sem); | ||
225 | switch (stage) { | ||
226 | case 1: | ||
227 | if (audio_pwr_state == 0) | ||
228 | audio_pwr_state = 1; | ||
229 | break; | ||
230 | case 2: | ||
231 | if (audio_pwr_state == 1) { | ||
232 | nokia770_audio_pwr_down(); | ||
233 | audio_pwr_state = -1; | ||
234 | } | ||
235 | break; | ||
236 | } | ||
237 | up(&audio_pwr_sem); | ||
238 | } | ||
239 | |||
240 | static void __init omap_nokia770_init(void) | ||
241 | { | ||
242 | nokia770_config[0].data = &nokia770_usb_config; | ||
243 | |||
244 | platform_add_devices(nokia770_devices, ARRAY_SIZE(nokia770_devices)); | ||
245 | spi_register_board_info(nokia770_spi_board_info, | ||
246 | ARRAY_SIZE(nokia770_spi_board_info)); | ||
247 | omap_board_config = nokia770_config; | ||
248 | omap_board_config_size = ARRAY_SIZE(nokia770_config); | ||
249 | omap_serial_init(); | ||
250 | omap_dsp_audio_pwr_up_request = nokia770_audio_pwr_up_request; | ||
251 | omap_dsp_audio_pwr_down_request = nokia770_audio_pwr_down_request; | ||
252 | dspxor_ck = clk_get(0, "dspxor_ck"); | ||
253 | } | ||
254 | |||
255 | static void __init omap_nokia770_map_io(void) | ||
256 | { | ||
257 | omap1_map_common_io(); | ||
258 | } | ||
259 | |||
260 | MACHINE_START(NOKIA770, "Nokia 770") | ||
261 | .phys_io = 0xfff00000, | ||
262 | .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc, | ||
263 | .boot_params = 0x10000100, | ||
264 | .map_io = omap_nokia770_map_io, | ||
265 | .init_irq = omap_nokia770_init_irq, | ||
266 | .init_machine = omap_nokia770_init, | ||
267 | .timer = &omap_timer, | ||
268 | MACHINE_END | ||
diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c index 543fa136106d..1160093e8ef6 100644 --- a/arch/arm/mach-omap1/board-osk.c +++ b/arch/arm/mach-omap1/board-osk.c | |||
@@ -33,6 +33,7 @@ | |||
33 | 33 | ||
34 | #include <linux/mtd/mtd.h> | 34 | #include <linux/mtd/mtd.h> |
35 | #include <linux/mtd/partitions.h> | 35 | #include <linux/mtd/partitions.h> |
36 | #include <linux/input.h> | ||
36 | 37 | ||
37 | #include <asm/hardware.h> | 38 | #include <asm/hardware.h> |
38 | #include <asm/mach-types.h> | 39 | #include <asm/mach-types.h> |
@@ -44,7 +45,24 @@ | |||
44 | #include <asm/arch/usb.h> | 45 | #include <asm/arch/usb.h> |
45 | #include <asm/arch/mux.h> | 46 | #include <asm/arch/mux.h> |
46 | #include <asm/arch/tc.h> | 47 | #include <asm/arch/tc.h> |
48 | #include <asm/arch/keypad.h> | ||
47 | #include <asm/arch/common.h> | 49 | #include <asm/arch/common.h> |
50 | #include <asm/arch/mcbsp.h> | ||
51 | #include <asm/arch/omap-alsa.h> | ||
52 | |||
53 | static int osk_keymap[] = { | ||
54 | KEY(0, 0, KEY_F1), | ||
55 | KEY(0, 3, KEY_UP), | ||
56 | KEY(1, 1, KEY_LEFTCTRL), | ||
57 | KEY(1, 2, KEY_LEFT), | ||
58 | KEY(2, 0, KEY_SPACE), | ||
59 | KEY(2, 1, KEY_ESC), | ||
60 | KEY(2, 2, KEY_DOWN), | ||
61 | KEY(3, 2, KEY_ENTER), | ||
62 | KEY(3, 3, KEY_RIGHT), | ||
63 | 0 | ||
64 | }; | ||
65 | |||
48 | 66 | ||
49 | static struct mtd_partition osk_partitions[] = { | 67 | static struct mtd_partition osk_partitions[] = { |
50 | /* bootloader (U-Boot, etc) in first sector */ | 68 | /* bootloader (U-Boot, etc) in first sector */ |
@@ -133,9 +151,69 @@ static struct platform_device osk5912_cf_device = { | |||
133 | .resource = osk5912_cf_resources, | 151 | .resource = osk5912_cf_resources, |
134 | }; | 152 | }; |
135 | 153 | ||
154 | #define DEFAULT_BITPERSAMPLE 16 | ||
155 | |||
156 | static struct omap_mcbsp_reg_cfg mcbsp_regs = { | ||
157 | .spcr2 = FREE | FRST | GRST | XRST | XINTM(3), | ||
158 | .spcr1 = RINTM(3) | RRST, | ||
159 | .rcr2 = RPHASE | RFRLEN2(OMAP_MCBSP_WORD_8) | | ||
160 | RWDLEN2(OMAP_MCBSP_WORD_16) | RDATDLY(0), | ||
161 | .rcr1 = RFRLEN1(OMAP_MCBSP_WORD_8) | RWDLEN1(OMAP_MCBSP_WORD_16), | ||
162 | .xcr2 = XPHASE | XFRLEN2(OMAP_MCBSP_WORD_8) | | ||
163 | XWDLEN2(OMAP_MCBSP_WORD_16) | XDATDLY(0) | XFIG, | ||
164 | .xcr1 = XFRLEN1(OMAP_MCBSP_WORD_8) | XWDLEN1(OMAP_MCBSP_WORD_16), | ||
165 | .srgr1 = FWID(DEFAULT_BITPERSAMPLE - 1), | ||
166 | .srgr2 = GSYNC | CLKSP | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1), | ||
167 | /*.pcr0 = FSXM | FSRM | CLKXM | CLKRM | CLKXP | CLKRP,*/ /* mcbsp: master */ | ||
168 | .pcr0 = CLKXP | CLKRP, /* mcbsp: slave */ | ||
169 | }; | ||
170 | |||
171 | static struct omap_alsa_codec_config alsa_config = { | ||
172 | .name = "OSK AIC23", | ||
173 | .mcbsp_regs_alsa = &mcbsp_regs, | ||
174 | .codec_configure_dev = NULL, // aic23_configure, | ||
175 | .codec_set_samplerate = NULL, // aic23_set_samplerate, | ||
176 | .codec_clock_setup = NULL, // aic23_clock_setup, | ||
177 | .codec_clock_on = NULL, // aic23_clock_on, | ||
178 | .codec_clock_off = NULL, // aic23_clock_off, | ||
179 | .get_default_samplerate = NULL, // aic23_get_default_samplerate, | ||
180 | }; | ||
181 | |||
136 | static struct platform_device osk5912_mcbsp1_device = { | 182 | static struct platform_device osk5912_mcbsp1_device = { |
137 | .name = "omap_mcbsp", | 183 | .name = "omap_alsa_mcbsp", |
138 | .id = 1, | 184 | .id = 1, |
185 | .dev = { | ||
186 | .platform_data = &alsa_config, | ||
187 | }, | ||
188 | }; | ||
189 | |||
190 | static struct resource osk5912_kp_resources[] = { | ||
191 | [0] = { | ||
192 | .start = INT_KEYBOARD, | ||
193 | .end = INT_KEYBOARD, | ||
194 | .flags = IORESOURCE_IRQ, | ||
195 | }, | ||
196 | }; | ||
197 | |||
198 | static struct omap_kp_platform_data osk_kp_data = { | ||
199 | .rows = 8, | ||
200 | .cols = 8, | ||
201 | .keymap = osk_keymap, | ||
202 | }; | ||
203 | |||
204 | static struct platform_device osk5912_kp_device = { | ||
205 | .name = "omap-keypad", | ||
206 | .id = -1, | ||
207 | .dev = { | ||
208 | .platform_data = &osk_kp_data, | ||
209 | }, | ||
210 | .num_resources = ARRAY_SIZE(osk5912_kp_resources), | ||
211 | .resource = osk5912_kp_resources, | ||
212 | }; | ||
213 | |||
214 | static struct platform_device osk5912_lcd_device = { | ||
215 | .name = "lcd_osk", | ||
216 | .id = -1, | ||
139 | }; | 217 | }; |
140 | 218 | ||
141 | static struct platform_device *osk5912_devices[] __initdata = { | 219 | static struct platform_device *osk5912_devices[] __initdata = { |
@@ -143,6 +221,8 @@ static struct platform_device *osk5912_devices[] __initdata = { | |||
143 | &osk5912_smc91x_device, | 221 | &osk5912_smc91x_device, |
144 | &osk5912_cf_device, | 222 | &osk5912_cf_device, |
145 | &osk5912_mcbsp1_device, | 223 | &osk5912_mcbsp1_device, |
224 | &osk5912_kp_device, | ||
225 | &osk5912_lcd_device, | ||
146 | }; | 226 | }; |
147 | 227 | ||
148 | static void __init osk_init_smc91x(void) | 228 | static void __init osk_init_smc91x(void) |
@@ -197,7 +277,6 @@ static struct omap_uart_config osk_uart_config __initdata = { | |||
197 | }; | 277 | }; |
198 | 278 | ||
199 | static struct omap_lcd_config osk_lcd_config __initdata = { | 279 | static struct omap_lcd_config osk_lcd_config __initdata = { |
200 | .panel_name = "osk", | ||
201 | .ctrl_name = "internal", | 280 | .ctrl_name = "internal", |
202 | }; | 281 | }; |
203 | 282 | ||
@@ -255,8 +334,18 @@ static void __init osk_mistral_init(void) | |||
255 | static void __init osk_mistral_init(void) { } | 334 | static void __init osk_mistral_init(void) { } |
256 | #endif | 335 | #endif |
257 | 336 | ||
337 | #define EMIFS_CS3_VAL (0x88013141) | ||
338 | |||
258 | static void __init osk_init(void) | 339 | static void __init osk_init(void) |
259 | { | 340 | { |
341 | /* Workaround for wrong CS3 (NOR flash) timing | ||
342 | * There are some U-Boot versions out there which configure | ||
343 | * wrong CS3 memory timings. This mainly leads to CRC | ||
344 | * or similiar errors if you use NOR flash (e.g. with JFFS2) | ||
345 | */ | ||
346 | if (EMIFS_CCS(3) != EMIFS_CS3_VAL) | ||
347 | EMIFS_CCS(3) = EMIFS_CS3_VAL; | ||
348 | |||
260 | osk_flash_resource.end = osk_flash_resource.start = omap_cs3_phys(); | 349 | osk_flash_resource.end = osk_flash_resource.start = omap_cs3_phys(); |
261 | osk_flash_resource.end += SZ_32M - 1; | 350 | osk_flash_resource.end += SZ_32M - 1; |
262 | platform_add_devices(osk5912_devices, ARRAY_SIZE(osk5912_devices)); | 351 | platform_add_devices(osk5912_devices, ARRAY_SIZE(osk5912_devices)); |
diff --git a/arch/arm/mach-omap1/board-palmte.c b/arch/arm/mach-omap1/board-palmte.c index e488f7236775..4bc8a62909b9 100644 --- a/arch/arm/mach-omap1/board-palmte.c +++ b/arch/arm/mach-omap1/board-palmte.c | |||
@@ -38,6 +38,15 @@ static void __init omap_generic_init_irq(void) | |||
38 | omap_init_irq(); | 38 | omap_init_irq(); |
39 | } | 39 | } |
40 | 40 | ||
41 | static struct platform_device palmte_lcd_device = { | ||
42 | .name = "lcd_palmte", | ||
43 | .id = -1, | ||
44 | }; | ||
45 | |||
46 | static struct platform_device *devices[] __initdata = { | ||
47 | &palmte_lcd_device, | ||
48 | }; | ||
49 | |||
41 | static struct omap_usb_config palmte_usb_config __initdata = { | 50 | static struct omap_usb_config palmte_usb_config __initdata = { |
42 | .register_dev = 1, | 51 | .register_dev = 1, |
43 | .hmc_mode = 0, | 52 | .hmc_mode = 0, |
@@ -55,7 +64,6 @@ static struct omap_mmc_config palmte_mmc_config __initdata = { | |||
55 | }; | 64 | }; |
56 | 65 | ||
57 | static struct omap_lcd_config palmte_lcd_config __initdata = { | 66 | static struct omap_lcd_config palmte_lcd_config __initdata = { |
58 | .panel_name = "palmte", | ||
59 | .ctrl_name = "internal", | 67 | .ctrl_name = "internal", |
60 | }; | 68 | }; |
61 | 69 | ||
@@ -69,6 +77,8 @@ static void __init omap_generic_init(void) | |||
69 | { | 77 | { |
70 | omap_board_config = palmte_config; | 78 | omap_board_config = palmte_config; |
71 | omap_board_config_size = ARRAY_SIZE(palmte_config); | 79 | omap_board_config_size = ARRAY_SIZE(palmte_config); |
80 | |||
81 | platform_add_devices(devices, ARRAY_SIZE(devices)); | ||
72 | } | 82 | } |
73 | 83 | ||
74 | static void __init omap_generic_map_io(void) | 84 | static void __init omap_generic_map_io(void) |
diff --git a/arch/arm/mach-omap1/board-perseus2.c b/arch/arm/mach-omap1/board-perseus2.c index 3913a3cc0ce6..64b45d8ae357 100644 --- a/arch/arm/mach-omap1/board-perseus2.c +++ b/arch/arm/mach-omap1/board-perseus2.c | |||
@@ -16,7 +16,9 @@ | |||
16 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
17 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
18 | #include <linux/mtd/mtd.h> | 18 | #include <linux/mtd/mtd.h> |
19 | #include <linux/mtd/nand.h> | ||
19 | #include <linux/mtd/partitions.h> | 20 | #include <linux/mtd/partitions.h> |
21 | #include <linux/input.h> | ||
20 | 22 | ||
21 | #include <asm/hardware.h> | 23 | #include <asm/hardware.h> |
22 | #include <asm/mach-types.h> | 24 | #include <asm/mach-types.h> |
@@ -28,9 +30,44 @@ | |||
28 | #include <asm/arch/gpio.h> | 30 | #include <asm/arch/gpio.h> |
29 | #include <asm/arch/mux.h> | 31 | #include <asm/arch/mux.h> |
30 | #include <asm/arch/fpga.h> | 32 | #include <asm/arch/fpga.h> |
33 | #include <asm/arch/keypad.h> | ||
31 | #include <asm/arch/common.h> | 34 | #include <asm/arch/common.h> |
32 | #include <asm/arch/board.h> | 35 | #include <asm/arch/board.h> |
33 | 36 | ||
37 | static int p2_keymap[] = { | ||
38 | KEY(0,0,KEY_UP), | ||
39 | KEY(0,1,KEY_RIGHT), | ||
40 | KEY(0,2,KEY_LEFT), | ||
41 | KEY(0,3,KEY_DOWN), | ||
42 | KEY(0,4,KEY_CENTER), | ||
43 | KEY(0,5,KEY_0_5), | ||
44 | KEY(1,0,KEY_SOFT2), | ||
45 | KEY(1,1,KEY_SEND), | ||
46 | KEY(1,2,KEY_END), | ||
47 | KEY(1,3,KEY_VOLUMEDOWN), | ||
48 | KEY(1,4,KEY_VOLUMEUP), | ||
49 | KEY(1,5,KEY_RECORD), | ||
50 | KEY(2,0,KEY_SOFT1), | ||
51 | KEY(2,1,KEY_3), | ||
52 | KEY(2,2,KEY_6), | ||
53 | KEY(2,3,KEY_9), | ||
54 | KEY(2,4,KEY_SHARP), | ||
55 | KEY(2,5,KEY_2_5), | ||
56 | KEY(3,0,KEY_BACK), | ||
57 | KEY(3,1,KEY_2), | ||
58 | KEY(3,2,KEY_5), | ||
59 | KEY(3,3,KEY_8), | ||
60 | KEY(3,4,KEY_0), | ||
61 | KEY(3,5,KEY_HEADSETHOOK), | ||
62 | KEY(4,0,KEY_HOME), | ||
63 | KEY(4,1,KEY_1), | ||
64 | KEY(4,2,KEY_4), | ||
65 | KEY(4,3,KEY_7), | ||
66 | KEY(4,4,KEY_STAR), | ||
67 | KEY(4,5,KEY_POWER), | ||
68 | 0 | ||
69 | }; | ||
70 | |||
34 | static struct resource smc91x_resources[] = { | 71 | static struct resource smc91x_resources[] = { |
35 | [0] = { | 72 | [0] = { |
36 | .start = H2P2_DBG_FPGA_ETHR_START, /* Physical */ | 73 | .start = H2P2_DBG_FPGA_ETHR_START, /* Physical */ |
@@ -44,7 +81,7 @@ static struct resource smc91x_resources[] = { | |||
44 | }, | 81 | }, |
45 | }; | 82 | }; |
46 | 83 | ||
47 | static struct mtd_partition p2_partitions[] = { | 84 | static struct mtd_partition nor_partitions[] = { |
48 | /* bootloader (U-Boot, etc) in first sector */ | 85 | /* bootloader (U-Boot, etc) in first sector */ |
49 | { | 86 | { |
50 | .name = "bootloader", | 87 | .name = "bootloader", |
@@ -75,27 +112,47 @@ static struct mtd_partition p2_partitions[] = { | |||
75 | }, | 112 | }, |
76 | }; | 113 | }; |
77 | 114 | ||
78 | static struct flash_platform_data p2_flash_data = { | 115 | static struct flash_platform_data nor_data = { |
79 | .map_name = "cfi_probe", | 116 | .map_name = "cfi_probe", |
80 | .width = 2, | 117 | .width = 2, |
81 | .parts = p2_partitions, | 118 | .parts = nor_partitions, |
82 | .nr_parts = ARRAY_SIZE(p2_partitions), | 119 | .nr_parts = ARRAY_SIZE(nor_partitions), |
83 | }; | 120 | }; |
84 | 121 | ||
85 | static struct resource p2_flash_resource = { | 122 | static struct resource nor_resource = { |
86 | .start = OMAP_CS0_PHYS, | 123 | .start = OMAP_CS0_PHYS, |
87 | .end = OMAP_CS0_PHYS + SZ_32M - 1, | 124 | .end = OMAP_CS0_PHYS + SZ_32M - 1, |
88 | .flags = IORESOURCE_MEM, | 125 | .flags = IORESOURCE_MEM, |
89 | }; | 126 | }; |
90 | 127 | ||
91 | static struct platform_device p2_flash_device = { | 128 | static struct platform_device nor_device = { |
92 | .name = "omapflash", | 129 | .name = "omapflash", |
93 | .id = 0, | 130 | .id = 0, |
94 | .dev = { | 131 | .dev = { |
95 | .platform_data = &p2_flash_data, | 132 | .platform_data = &nor_data, |
133 | }, | ||
134 | .num_resources = 1, | ||
135 | .resource = &nor_resource, | ||
136 | }; | ||
137 | |||
138 | static struct nand_platform_data nand_data = { | ||
139 | .options = NAND_SAMSUNG_LP_OPTIONS, | ||
140 | }; | ||
141 | |||
142 | static struct resource nand_resource = { | ||
143 | .start = OMAP_CS3_PHYS, | ||
144 | .end = OMAP_CS3_PHYS + SZ_4K - 1, | ||
145 | .flags = IORESOURCE_MEM, | ||
146 | }; | ||
147 | |||
148 | static struct platform_device nand_device = { | ||
149 | .name = "omapnand", | ||
150 | .id = 0, | ||
151 | .dev = { | ||
152 | .platform_data = &nand_data, | ||
96 | }, | 153 | }, |
97 | .num_resources = 1, | 154 | .num_resources = 1, |
98 | .resource = &p2_flash_resource, | 155 | .resource = &nand_resource, |
99 | }; | 156 | }; |
100 | 157 | ||
101 | static struct platform_device smc91x_device = { | 158 | static struct platform_device smc91x_device = { |
@@ -105,17 +162,55 @@ static struct platform_device smc91x_device = { | |||
105 | .resource = smc91x_resources, | 162 | .resource = smc91x_resources, |
106 | }; | 163 | }; |
107 | 164 | ||
165 | static struct resource kp_resources[] = { | ||
166 | [0] = { | ||
167 | .start = INT_730_MPUIO_KEYPAD, | ||
168 | .end = INT_730_MPUIO_KEYPAD, | ||
169 | .flags = IORESOURCE_IRQ, | ||
170 | }, | ||
171 | }; | ||
172 | |||
173 | static struct omap_kp_platform_data kp_data = { | ||
174 | .rows = 8, | ||
175 | .cols = 8, | ||
176 | .keymap = p2_keymap, | ||
177 | }; | ||
178 | |||
179 | static struct platform_device kp_device = { | ||
180 | .name = "omap-keypad", | ||
181 | .id = -1, | ||
182 | .dev = { | ||
183 | .platform_data = &kp_data, | ||
184 | }, | ||
185 | .num_resources = ARRAY_SIZE(kp_resources), | ||
186 | .resource = kp_resources, | ||
187 | }; | ||
188 | |||
189 | static struct platform_device lcd_device = { | ||
190 | .name = "lcd_p2", | ||
191 | .id = -1, | ||
192 | }; | ||
193 | |||
108 | static struct platform_device *devices[] __initdata = { | 194 | static struct platform_device *devices[] __initdata = { |
109 | &p2_flash_device, | 195 | &nor_device, |
196 | &nand_device, | ||
110 | &smc91x_device, | 197 | &smc91x_device, |
198 | &kp_device, | ||
199 | &lcd_device, | ||
111 | }; | 200 | }; |
112 | 201 | ||
202 | #define P2_NAND_RB_GPIO_PIN 62 | ||
203 | |||
204 | static int nand_dev_ready(struct nand_platform_data *data) | ||
205 | { | ||
206 | return omap_get_gpio_datain(P2_NAND_RB_GPIO_PIN); | ||
207 | } | ||
208 | |||
113 | static struct omap_uart_config perseus2_uart_config __initdata = { | 209 | static struct omap_uart_config perseus2_uart_config __initdata = { |
114 | .enabled_uarts = ((1 << 0) | (1 << 1)), | 210 | .enabled_uarts = ((1 << 0) | (1 << 1)), |
115 | }; | 211 | }; |
116 | 212 | ||
117 | static struct omap_lcd_config perseus2_lcd_config __initdata = { | 213 | static struct omap_lcd_config perseus2_lcd_config __initdata = { |
118 | .panel_name = "p2", | ||
119 | .ctrl_name = "internal", | 214 | .ctrl_name = "internal", |
120 | }; | 215 | }; |
121 | 216 | ||
@@ -126,7 +221,13 @@ static struct omap_board_config_kernel perseus2_config[] = { | |||
126 | 221 | ||
127 | static void __init omap_perseus2_init(void) | 222 | static void __init omap_perseus2_init(void) |
128 | { | 223 | { |
129 | (void) platform_add_devices(devices, ARRAY_SIZE(devices)); | 224 | if (!(omap_request_gpio(P2_NAND_RB_GPIO_PIN))) |
225 | nand_data.dev_ready = nand_dev_ready; | ||
226 | |||
227 | omap_cfg_reg(L3_1610_FLASH_CS2B_OE); | ||
228 | omap_cfg_reg(M8_1610_FLASH_CS2B_WE); | ||
229 | |||
230 | platform_add_devices(devices, ARRAY_SIZE(devices)); | ||
130 | 231 | ||
131 | omap_board_config = perseus2_config; | 232 | omap_board_config = perseus2_config; |
132 | omap_board_config_size = ARRAY_SIZE(perseus2_config); | 233 | omap_board_config_size = ARRAY_SIZE(perseus2_config); |
diff --git a/arch/arm/mach-omap1/board-voiceblue.c b/arch/arm/mach-omap1/board-voiceblue.c index 52e4a9d69642..447a586eb334 100644 --- a/arch/arm/mach-omap1/board-voiceblue.c +++ b/arch/arm/mach-omap1/board-voiceblue.c | |||
@@ -155,9 +155,9 @@ static struct omap_uart_config voiceblue_uart_config __initdata = { | |||
155 | }; | 155 | }; |
156 | 156 | ||
157 | static struct omap_board_config_kernel voiceblue_config[] = { | 157 | static struct omap_board_config_kernel voiceblue_config[] = { |
158 | { OMAP_TAG_USB, &voiceblue_usb_config }, | 158 | { OMAP_TAG_USB, &voiceblue_usb_config }, |
159 | { OMAP_TAG_MMC, &voiceblue_mmc_config }, | 159 | { OMAP_TAG_MMC, &voiceblue_mmc_config }, |
160 | { OMAP_TAG_UART, &voiceblue_uart_config }, | 160 | { OMAP_TAG_UART, &voiceblue_uart_config }, |
161 | }; | 161 | }; |
162 | 162 | ||
163 | static void __init voiceblue_init_irq(void) | 163 | static void __init voiceblue_init_irq(void) |
@@ -235,7 +235,7 @@ static struct notifier_block panic_block = { | |||
235 | static int __init voiceblue_setup(void) | 235 | static int __init voiceblue_setup(void) |
236 | { | 236 | { |
237 | /* Setup panic notifier */ | 237 | /* Setup panic notifier */ |
238 | atomic_notifier_chain_register(&panic_notifier_list, &panic_block); | 238 | notifier_chain_register(&panic_notifier_list, &panic_block); |
239 | 239 | ||
240 | return 0; | 240 | return 0; |
241 | } | 241 | } |
diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c index 75110ba10424..619db18144ea 100644 --- a/arch/arm/mach-omap1/clock.c +++ b/arch/arm/mach-omap1/clock.c | |||
@@ -345,7 +345,7 @@ static unsigned calc_ext_dsor(unsigned long rate) | |||
345 | */ | 345 | */ |
346 | for (dsor = 2; dsor < 96; ++dsor) { | 346 | for (dsor = 2; dsor < 96; ++dsor) { |
347 | if ((dsor & 1) && dsor > 8) | 347 | if ((dsor & 1) && dsor > 8) |
348 | continue; | 348 | continue; |
349 | if (rate >= 96000000 / dsor) | 349 | if (rate >= 96000000 / dsor) |
350 | break; | 350 | break; |
351 | } | 351 | } |
@@ -687,6 +687,11 @@ int __init omap1_clk_init(void) | |||
687 | clk_register(*clkp); | 687 | clk_register(*clkp); |
688 | continue; | 688 | continue; |
689 | } | 689 | } |
690 | |||
691 | if (((*clkp)->flags &CLOCK_IN_OMAP310) && cpu_is_omap310()) { | ||
692 | clk_register(*clkp); | ||
693 | continue; | ||
694 | } | ||
690 | } | 695 | } |
691 | 696 | ||
692 | info = omap_get_config(OMAP_TAG_CLOCK, struct omap_clock_config); | 697 | info = omap_get_config(OMAP_TAG_CLOCK, struct omap_clock_config); |
@@ -784,7 +789,7 @@ int __init omap1_clk_init(void) | |||
784 | clk_enable(&armxor_ck.clk); | 789 | clk_enable(&armxor_ck.clk); |
785 | clk_enable(&armtim_ck.clk); /* This should be done by timer code */ | 790 | clk_enable(&armtim_ck.clk); /* This should be done by timer code */ |
786 | 791 | ||
787 | if (cpu_is_omap1510()) | 792 | if (cpu_is_omap15xx()) |
788 | clk_enable(&arm_gpio_ck); | 793 | clk_enable(&arm_gpio_ck); |
789 | 794 | ||
790 | return 0; | 795 | return 0; |
diff --git a/arch/arm/mach-omap1/clock.h b/arch/arm/mach-omap1/clock.h index 4f18d1b94449..b7c68819c4e7 100644 --- a/arch/arm/mach-omap1/clock.h +++ b/arch/arm/mach-omap1/clock.h | |||
@@ -151,7 +151,7 @@ static struct clk ck_ref = { | |||
151 | .name = "ck_ref", | 151 | .name = "ck_ref", |
152 | .rate = 12000000, | 152 | .rate = 12000000, |
153 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | 153 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | |
154 | ALWAYS_ENABLED, | 154 | CLOCK_IN_OMAP310 | ALWAYS_ENABLED, |
155 | .enable = &omap1_clk_enable_generic, | 155 | .enable = &omap1_clk_enable_generic, |
156 | .disable = &omap1_clk_disable_generic, | 156 | .disable = &omap1_clk_disable_generic, |
157 | }; | 157 | }; |
@@ -160,7 +160,7 @@ static struct clk ck_dpll1 = { | |||
160 | .name = "ck_dpll1", | 160 | .name = "ck_dpll1", |
161 | .parent = &ck_ref, | 161 | .parent = &ck_ref, |
162 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | 162 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | |
163 | RATE_PROPAGATES | ALWAYS_ENABLED, | 163 | CLOCK_IN_OMAP310 | RATE_PROPAGATES | ALWAYS_ENABLED, |
164 | .enable = &omap1_clk_enable_generic, | 164 | .enable = &omap1_clk_enable_generic, |
165 | .disable = &omap1_clk_disable_generic, | 165 | .disable = &omap1_clk_disable_generic, |
166 | }; | 166 | }; |
@@ -183,7 +183,8 @@ static struct clk arm_ck = { | |||
183 | .name = "arm_ck", | 183 | .name = "arm_ck", |
184 | .parent = &ck_dpll1, | 184 | .parent = &ck_dpll1, |
185 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | 185 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | |
186 | RATE_CKCTL | RATE_PROPAGATES | ALWAYS_ENABLED, | 186 | CLOCK_IN_OMAP310 | RATE_CKCTL | RATE_PROPAGATES | |
187 | ALWAYS_ENABLED, | ||
187 | .rate_offset = CKCTL_ARMDIV_OFFSET, | 188 | .rate_offset = CKCTL_ARMDIV_OFFSET, |
188 | .recalc = &omap1_ckctl_recalc, | 189 | .recalc = &omap1_ckctl_recalc, |
189 | .enable = &omap1_clk_enable_generic, | 190 | .enable = &omap1_clk_enable_generic, |
@@ -195,7 +196,8 @@ static struct arm_idlect1_clk armper_ck = { | |||
195 | .name = "armper_ck", | 196 | .name = "armper_ck", |
196 | .parent = &ck_dpll1, | 197 | .parent = &ck_dpll1, |
197 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | 198 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | |
198 | RATE_CKCTL | CLOCK_IDLE_CONTROL, | 199 | CLOCK_IN_OMAP310 | RATE_CKCTL | |
200 | CLOCK_IDLE_CONTROL, | ||
199 | .enable_reg = (void __iomem *)ARM_IDLECT2, | 201 | .enable_reg = (void __iomem *)ARM_IDLECT2, |
200 | .enable_bit = EN_PERCK, | 202 | .enable_bit = EN_PERCK, |
201 | .rate_offset = CKCTL_PERDIV_OFFSET, | 203 | .rate_offset = CKCTL_PERDIV_OFFSET, |
@@ -209,7 +211,7 @@ static struct arm_idlect1_clk armper_ck = { | |||
209 | static struct clk arm_gpio_ck = { | 211 | static struct clk arm_gpio_ck = { |
210 | .name = "arm_gpio_ck", | 212 | .name = "arm_gpio_ck", |
211 | .parent = &ck_dpll1, | 213 | .parent = &ck_dpll1, |
212 | .flags = CLOCK_IN_OMAP1510, | 214 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310, |
213 | .enable_reg = (void __iomem *)ARM_IDLECT2, | 215 | .enable_reg = (void __iomem *)ARM_IDLECT2, |
214 | .enable_bit = EN_GPIOCK, | 216 | .enable_bit = EN_GPIOCK, |
215 | .recalc = &followparent_recalc, | 217 | .recalc = &followparent_recalc, |
@@ -222,7 +224,7 @@ static struct arm_idlect1_clk armxor_ck = { | |||
222 | .name = "armxor_ck", | 224 | .name = "armxor_ck", |
223 | .parent = &ck_ref, | 225 | .parent = &ck_ref, |
224 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | 226 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | |
225 | CLOCK_IDLE_CONTROL, | 227 | CLOCK_IN_OMAP310 | CLOCK_IDLE_CONTROL, |
226 | .enable_reg = (void __iomem *)ARM_IDLECT2, | 228 | .enable_reg = (void __iomem *)ARM_IDLECT2, |
227 | .enable_bit = EN_XORPCK, | 229 | .enable_bit = EN_XORPCK, |
228 | .recalc = &followparent_recalc, | 230 | .recalc = &followparent_recalc, |
@@ -237,7 +239,7 @@ static struct arm_idlect1_clk armtim_ck = { | |||
237 | .name = "armtim_ck", | 239 | .name = "armtim_ck", |
238 | .parent = &ck_ref, | 240 | .parent = &ck_ref, |
239 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | 241 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | |
240 | CLOCK_IDLE_CONTROL, | 242 | CLOCK_IN_OMAP310 | CLOCK_IDLE_CONTROL, |
241 | .enable_reg = (void __iomem *)ARM_IDLECT2, | 243 | .enable_reg = (void __iomem *)ARM_IDLECT2, |
242 | .enable_bit = EN_TIMCK, | 244 | .enable_bit = EN_TIMCK, |
243 | .recalc = &followparent_recalc, | 245 | .recalc = &followparent_recalc, |
@@ -252,7 +254,7 @@ static struct arm_idlect1_clk armwdt_ck = { | |||
252 | .name = "armwdt_ck", | 254 | .name = "armwdt_ck", |
253 | .parent = &ck_ref, | 255 | .parent = &ck_ref, |
254 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | 256 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | |
255 | CLOCK_IDLE_CONTROL, | 257 | CLOCK_IN_OMAP310 | CLOCK_IDLE_CONTROL, |
256 | .enable_reg = (void __iomem *)ARM_IDLECT2, | 258 | .enable_reg = (void __iomem *)ARM_IDLECT2, |
257 | .enable_bit = EN_WDTCK, | 259 | .enable_bit = EN_WDTCK, |
258 | .recalc = &omap1_watchdog_recalc, | 260 | .recalc = &omap1_watchdog_recalc, |
@@ -344,9 +346,9 @@ static struct arm_idlect1_clk tc_ck = { | |||
344 | .name = "tc_ck", | 346 | .name = "tc_ck", |
345 | .parent = &ck_dpll1, | 347 | .parent = &ck_dpll1, |
346 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | 348 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | |
347 | CLOCK_IN_OMAP730 | RATE_CKCTL | | 349 | CLOCK_IN_OMAP730 | CLOCK_IN_OMAP310 | |
348 | RATE_PROPAGATES | ALWAYS_ENABLED | | 350 | RATE_CKCTL | RATE_PROPAGATES | |
349 | CLOCK_IDLE_CONTROL, | 351 | ALWAYS_ENABLED | CLOCK_IDLE_CONTROL, |
350 | .rate_offset = CKCTL_TCDIV_OFFSET, | 352 | .rate_offset = CKCTL_TCDIV_OFFSET, |
351 | .recalc = &omap1_ckctl_recalc, | 353 | .recalc = &omap1_ckctl_recalc, |
352 | .enable = &omap1_clk_enable_generic, | 354 | .enable = &omap1_clk_enable_generic, |
@@ -358,7 +360,8 @@ static struct arm_idlect1_clk tc_ck = { | |||
358 | static struct clk arminth_ck1510 = { | 360 | static struct clk arminth_ck1510 = { |
359 | .name = "arminth_ck", | 361 | .name = "arminth_ck", |
360 | .parent = &tc_ck.clk, | 362 | .parent = &tc_ck.clk, |
361 | .flags = CLOCK_IN_OMAP1510 | ALWAYS_ENABLED, | 363 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | |
364 | ALWAYS_ENABLED, | ||
362 | .recalc = &followparent_recalc, | 365 | .recalc = &followparent_recalc, |
363 | /* Note: On 1510 the frequency follows TC_CK | 366 | /* Note: On 1510 the frequency follows TC_CK |
364 | * | 367 | * |
@@ -372,7 +375,8 @@ static struct clk tipb_ck = { | |||
372 | /* No-idle controlled by "tc_ck" */ | 375 | /* No-idle controlled by "tc_ck" */ |
373 | .name = "tibp_ck", | 376 | .name = "tibp_ck", |
374 | .parent = &tc_ck.clk, | 377 | .parent = &tc_ck.clk, |
375 | .flags = CLOCK_IN_OMAP1510 | ALWAYS_ENABLED, | 378 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | |
379 | ALWAYS_ENABLED, | ||
376 | .recalc = &followparent_recalc, | 380 | .recalc = &followparent_recalc, |
377 | .enable = &omap1_clk_enable_generic, | 381 | .enable = &omap1_clk_enable_generic, |
378 | .disable = &omap1_clk_disable_generic, | 382 | .disable = &omap1_clk_disable_generic, |
@@ -417,7 +421,7 @@ static struct clk dma_ck = { | |||
417 | .name = "dma_ck", | 421 | .name = "dma_ck", |
418 | .parent = &tc_ck.clk, | 422 | .parent = &tc_ck.clk, |
419 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | 423 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | |
420 | ALWAYS_ENABLED, | 424 | CLOCK_IN_OMAP310 | ALWAYS_ENABLED, |
421 | .recalc = &followparent_recalc, | 425 | .recalc = &followparent_recalc, |
422 | .enable = &omap1_clk_enable_generic, | 426 | .enable = &omap1_clk_enable_generic, |
423 | .disable = &omap1_clk_disable_generic, | 427 | .disable = &omap1_clk_disable_generic, |
@@ -437,7 +441,7 @@ static struct arm_idlect1_clk api_ck = { | |||
437 | .name = "api_ck", | 441 | .name = "api_ck", |
438 | .parent = &tc_ck.clk, | 442 | .parent = &tc_ck.clk, |
439 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | 443 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | |
440 | CLOCK_IDLE_CONTROL, | 444 | CLOCK_IN_OMAP310 | CLOCK_IDLE_CONTROL, |
441 | .enable_reg = (void __iomem *)ARM_IDLECT2, | 445 | .enable_reg = (void __iomem *)ARM_IDLECT2, |
442 | .enable_bit = EN_APICK, | 446 | .enable_bit = EN_APICK, |
443 | .recalc = &followparent_recalc, | 447 | .recalc = &followparent_recalc, |
@@ -451,7 +455,8 @@ static struct arm_idlect1_clk lb_ck = { | |||
451 | .clk = { | 455 | .clk = { |
452 | .name = "lb_ck", | 456 | .name = "lb_ck", |
453 | .parent = &tc_ck.clk, | 457 | .parent = &tc_ck.clk, |
454 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IDLE_CONTROL, | 458 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | |
459 | CLOCK_IDLE_CONTROL, | ||
455 | .enable_reg = (void __iomem *)ARM_IDLECT2, | 460 | .enable_reg = (void __iomem *)ARM_IDLECT2, |
456 | .enable_bit = EN_LBCK, | 461 | .enable_bit = EN_LBCK, |
457 | .recalc = &followparent_recalc, | 462 | .recalc = &followparent_recalc, |
@@ -495,8 +500,8 @@ static struct arm_idlect1_clk lcd_ck_1510 = { | |||
495 | .clk = { | 500 | .clk = { |
496 | .name = "lcd_ck", | 501 | .name = "lcd_ck", |
497 | .parent = &ck_dpll1, | 502 | .parent = &ck_dpll1, |
498 | .flags = CLOCK_IN_OMAP1510 | RATE_CKCTL | | 503 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | |
499 | CLOCK_IDLE_CONTROL, | 504 | RATE_CKCTL | CLOCK_IDLE_CONTROL, |
500 | .enable_reg = (void __iomem *)ARM_IDLECT2, | 505 | .enable_reg = (void __iomem *)ARM_IDLECT2, |
501 | .enable_bit = EN_LCDCK, | 506 | .enable_bit = EN_LCDCK, |
502 | .rate_offset = CKCTL_LCDDIV_OFFSET, | 507 | .rate_offset = CKCTL_LCDDIV_OFFSET, |
@@ -512,8 +517,9 @@ static struct clk uart1_1510 = { | |||
512 | /* Direct from ULPD, no real parent */ | 517 | /* Direct from ULPD, no real parent */ |
513 | .parent = &armper_ck.clk, | 518 | .parent = &armper_ck.clk, |
514 | .rate = 12000000, | 519 | .rate = 12000000, |
515 | .flags = CLOCK_IN_OMAP1510 | ENABLE_REG_32BIT | | 520 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | |
516 | ALWAYS_ENABLED | CLOCK_NO_IDLE_PARENT, | 521 | ENABLE_REG_32BIT | ALWAYS_ENABLED | |
522 | CLOCK_NO_IDLE_PARENT, | ||
517 | .enable_reg = (void __iomem *)MOD_CONF_CTRL_0, | 523 | .enable_reg = (void __iomem *)MOD_CONF_CTRL_0, |
518 | .enable_bit = 29, /* Chooses between 12MHz and 48MHz */ | 524 | .enable_bit = 29, /* Chooses between 12MHz and 48MHz */ |
519 | .set_rate = &omap1_set_uart_rate, | 525 | .set_rate = &omap1_set_uart_rate, |
@@ -544,8 +550,8 @@ static struct clk uart2_ck = { | |||
544 | .parent = &armper_ck.clk, | 550 | .parent = &armper_ck.clk, |
545 | .rate = 12000000, | 551 | .rate = 12000000, |
546 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | 552 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | |
547 | ENABLE_REG_32BIT | ALWAYS_ENABLED | | 553 | CLOCK_IN_OMAP310 | ENABLE_REG_32BIT | |
548 | CLOCK_NO_IDLE_PARENT, | 554 | ALWAYS_ENABLED | CLOCK_NO_IDLE_PARENT, |
549 | .enable_reg = (void __iomem *)MOD_CONF_CTRL_0, | 555 | .enable_reg = (void __iomem *)MOD_CONF_CTRL_0, |
550 | .enable_bit = 30, /* Chooses between 12MHz and 48MHz */ | 556 | .enable_bit = 30, /* Chooses between 12MHz and 48MHz */ |
551 | .set_rate = &omap1_set_uart_rate, | 557 | .set_rate = &omap1_set_uart_rate, |
@@ -559,8 +565,9 @@ static struct clk uart3_1510 = { | |||
559 | /* Direct from ULPD, no real parent */ | 565 | /* Direct from ULPD, no real parent */ |
560 | .parent = &armper_ck.clk, | 566 | .parent = &armper_ck.clk, |
561 | .rate = 12000000, | 567 | .rate = 12000000, |
562 | .flags = CLOCK_IN_OMAP1510 | ENABLE_REG_32BIT | | 568 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | |
563 | ALWAYS_ENABLED | CLOCK_NO_IDLE_PARENT, | 569 | ENABLE_REG_32BIT | ALWAYS_ENABLED | |
570 | CLOCK_NO_IDLE_PARENT, | ||
564 | .enable_reg = (void __iomem *)MOD_CONF_CTRL_0, | 571 | .enable_reg = (void __iomem *)MOD_CONF_CTRL_0, |
565 | .enable_bit = 31, /* Chooses between 12MHz and 48MHz */ | 572 | .enable_bit = 31, /* Chooses between 12MHz and 48MHz */ |
566 | .set_rate = &omap1_set_uart_rate, | 573 | .set_rate = &omap1_set_uart_rate, |
@@ -590,7 +597,7 @@ static struct clk usb_clko = { /* 6 MHz output on W4_USB_CLKO */ | |||
590 | /* Direct from ULPD, no parent */ | 597 | /* Direct from ULPD, no parent */ |
591 | .rate = 6000000, | 598 | .rate = 6000000, |
592 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | 599 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | |
593 | RATE_FIXED | ENABLE_REG_32BIT, | 600 | CLOCK_IN_OMAP310 | RATE_FIXED | ENABLE_REG_32BIT, |
594 | .enable_reg = (void __iomem *)ULPD_CLOCK_CTRL, | 601 | .enable_reg = (void __iomem *)ULPD_CLOCK_CTRL, |
595 | .enable_bit = USB_MCLK_EN_BIT, | 602 | .enable_bit = USB_MCLK_EN_BIT, |
596 | .enable = &omap1_clk_enable_generic, | 603 | .enable = &omap1_clk_enable_generic, |
@@ -601,7 +608,7 @@ static struct clk usb_hhc_ck1510 = { | |||
601 | .name = "usb_hhc_ck", | 608 | .name = "usb_hhc_ck", |
602 | /* Direct from ULPD, no parent */ | 609 | /* Direct from ULPD, no parent */ |
603 | .rate = 48000000, /* Actually 2 clocks, 12MHz and 48MHz */ | 610 | .rate = 48000000, /* Actually 2 clocks, 12MHz and 48MHz */ |
604 | .flags = CLOCK_IN_OMAP1510 | | 611 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | |
605 | RATE_FIXED | ENABLE_REG_32BIT, | 612 | RATE_FIXED | ENABLE_REG_32BIT, |
606 | .enable_reg = (void __iomem *)MOD_CONF_CTRL_0, | 613 | .enable_reg = (void __iomem *)MOD_CONF_CTRL_0, |
607 | .enable_bit = USB_HOST_HHC_UHOST_EN, | 614 | .enable_bit = USB_HOST_HHC_UHOST_EN, |
@@ -637,7 +644,9 @@ static struct clk mclk_1510 = { | |||
637 | .name = "mclk", | 644 | .name = "mclk", |
638 | /* Direct from ULPD, no parent. May be enabled by ext hardware. */ | 645 | /* Direct from ULPD, no parent. May be enabled by ext hardware. */ |
639 | .rate = 12000000, | 646 | .rate = 12000000, |
640 | .flags = CLOCK_IN_OMAP1510 | RATE_FIXED, | 647 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | RATE_FIXED, |
648 | .enable_reg = (void __iomem *)SOFT_REQ_REG, | ||
649 | .enable_bit = 6, | ||
641 | .enable = &omap1_clk_enable_generic, | 650 | .enable = &omap1_clk_enable_generic, |
642 | .disable = &omap1_clk_disable_generic, | 651 | .disable = &omap1_clk_disable_generic, |
643 | }; | 652 | }; |
@@ -659,7 +668,7 @@ static struct clk bclk_1510 = { | |||
659 | .name = "bclk", | 668 | .name = "bclk", |
660 | /* Direct from ULPD, no parent. May be enabled by ext hardware. */ | 669 | /* Direct from ULPD, no parent. May be enabled by ext hardware. */ |
661 | .rate = 12000000, | 670 | .rate = 12000000, |
662 | .flags = CLOCK_IN_OMAP1510 | RATE_FIXED, | 671 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | RATE_FIXED, |
663 | .enable = &omap1_clk_enable_generic, | 672 | .enable = &omap1_clk_enable_generic, |
664 | .disable = &omap1_clk_disable_generic, | 673 | .disable = &omap1_clk_disable_generic, |
665 | }; | 674 | }; |
@@ -678,12 +687,14 @@ static struct clk bclk_16xx = { | |||
678 | }; | 687 | }; |
679 | 688 | ||
680 | static struct clk mmc1_ck = { | 689 | static struct clk mmc1_ck = { |
681 | .name = "mmc1_ck", | 690 | .name = "mmc_ck", |
691 | .id = 1, | ||
682 | /* Functional clock is direct from ULPD, interface clock is ARMPER */ | 692 | /* Functional clock is direct from ULPD, interface clock is ARMPER */ |
683 | .parent = &armper_ck.clk, | 693 | .parent = &armper_ck.clk, |
684 | .rate = 48000000, | 694 | .rate = 48000000, |
685 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | 695 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | |
686 | RATE_FIXED | ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT, | 696 | CLOCK_IN_OMAP310 | RATE_FIXED | ENABLE_REG_32BIT | |
697 | CLOCK_NO_IDLE_PARENT, | ||
687 | .enable_reg = (void __iomem *)MOD_CONF_CTRL_0, | 698 | .enable_reg = (void __iomem *)MOD_CONF_CTRL_0, |
688 | .enable_bit = 23, | 699 | .enable_bit = 23, |
689 | .enable = &omap1_clk_enable_generic, | 700 | .enable = &omap1_clk_enable_generic, |
@@ -691,7 +702,8 @@ static struct clk mmc1_ck = { | |||
691 | }; | 702 | }; |
692 | 703 | ||
693 | static struct clk mmc2_ck = { | 704 | static struct clk mmc2_ck = { |
694 | .name = "mmc2_ck", | 705 | .name = "mmc_ck", |
706 | .id = 2, | ||
695 | /* Functional clock is direct from ULPD, interface clock is ARMPER */ | 707 | /* Functional clock is direct from ULPD, interface clock is ARMPER */ |
696 | .parent = &armper_ck.clk, | 708 | .parent = &armper_ck.clk, |
697 | .rate = 48000000, | 709 | .rate = 48000000, |
@@ -706,7 +718,7 @@ static struct clk mmc2_ck = { | |||
706 | static struct clk virtual_ck_mpu = { | 718 | static struct clk virtual_ck_mpu = { |
707 | .name = "mpu", | 719 | .name = "mpu", |
708 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | 720 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | |
709 | VIRTUAL_CLOCK | ALWAYS_ENABLED, | 721 | CLOCK_IN_OMAP310 | VIRTUAL_CLOCK | ALWAYS_ENABLED, |
710 | .parent = &arm_ck, /* Is smarter alias for */ | 722 | .parent = &arm_ck, /* Is smarter alias for */ |
711 | .recalc = &followparent_recalc, | 723 | .recalc = &followparent_recalc, |
712 | .set_rate = &omap1_select_table_rate, | 724 | .set_rate = &omap1_select_table_rate, |
@@ -715,6 +727,20 @@ static struct clk virtual_ck_mpu = { | |||
715 | .disable = &omap1_clk_disable_generic, | 727 | .disable = &omap1_clk_disable_generic, |
716 | }; | 728 | }; |
717 | 729 | ||
730 | /* virtual functional clock domain for I2C. Just for making sure that ARMXOR_CK | ||
731 | remains active during MPU idle whenever this is enabled */ | ||
732 | static struct clk i2c_fck = { | ||
733 | .name = "i2c_fck", | ||
734 | .id = 1, | ||
735 | .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | | ||
736 | VIRTUAL_CLOCK | CLOCK_NO_IDLE_PARENT | | ||
737 | ALWAYS_ENABLED, | ||
738 | .parent = &armxor_ck.clk, | ||
739 | .recalc = &followparent_recalc, | ||
740 | .enable = &omap1_clk_enable_generic, | ||
741 | .disable = &omap1_clk_disable_generic, | ||
742 | }; | ||
743 | |||
718 | static struct clk * onchip_clks[] = { | 744 | static struct clk * onchip_clks[] = { |
719 | /* non-ULPD clocks */ | 745 | /* non-ULPD clocks */ |
720 | &ck_ref, | 746 | &ck_ref, |
@@ -763,6 +789,7 @@ static struct clk * onchip_clks[] = { | |||
763 | &mmc2_ck, | 789 | &mmc2_ck, |
764 | /* Virtual clocks */ | 790 | /* Virtual clocks */ |
765 | &virtual_ck_mpu, | 791 | &virtual_ck_mpu, |
792 | &i2c_fck, | ||
766 | }; | 793 | }; |
767 | 794 | ||
768 | #endif | 795 | #endif |
diff --git a/arch/arm/mach-omap1/devices.c b/arch/arm/mach-omap1/devices.c index ecbc47514adc..876c38da14f7 100644 --- a/arch/arm/mach-omap1/devices.c +++ b/arch/arm/mach-omap1/devices.c | |||
@@ -99,6 +99,45 @@ static void omap_init_rtc(void) | |||
99 | static inline void omap_init_rtc(void) {} | 99 | static inline void omap_init_rtc(void) {} |
100 | #endif | 100 | #endif |
101 | 101 | ||
102 | #if defined(CONFIG_OMAP_STI) | ||
103 | |||
104 | #define OMAP1_STI_BASE IO_ADDRESS(0xfffea000) | ||
105 | #define OMAP1_STI_CHANNEL_BASE (OMAP1_STI_BASE + 0x400) | ||
106 | |||
107 | static struct resource sti_resources[] = { | ||
108 | { | ||
109 | .start = OMAP1_STI_BASE, | ||
110 | .end = OMAP1_STI_BASE + SZ_1K - 1, | ||
111 | .flags = IORESOURCE_MEM, | ||
112 | }, | ||
113 | { | ||
114 | .start = OMAP1_STI_CHANNEL_BASE, | ||
115 | .end = OMAP1_STI_CHANNEL_BASE + SZ_1K - 1, | ||
116 | .flags = IORESOURCE_MEM, | ||
117 | }, | ||
118 | { | ||
119 | .start = INT_1610_STI, | ||
120 | .flags = IORESOURCE_IRQ, | ||
121 | } | ||
122 | }; | ||
123 | |||
124 | static struct platform_device sti_device = { | ||
125 | .name = "sti", | ||
126 | .id = -1, | ||
127 | .dev = { | ||
128 | .release = omap_nop_release, | ||
129 | }, | ||
130 | .num_resources = ARRAY_SIZE(sti_resources), | ||
131 | .resource = sti_resources, | ||
132 | }; | ||
133 | |||
134 | static inline void omap_init_sti(void) | ||
135 | { | ||
136 | platform_device_register(&sti_device); | ||
137 | } | ||
138 | #else | ||
139 | static inline void omap_init_sti(void) {} | ||
140 | #endif | ||
102 | 141 | ||
103 | /*-------------------------------------------------------------------------*/ | 142 | /*-------------------------------------------------------------------------*/ |
104 | 143 | ||
@@ -129,6 +168,7 @@ static int __init omap1_init_devices(void) | |||
129 | */ | 168 | */ |
130 | omap_init_irda(); | 169 | omap_init_irda(); |
131 | omap_init_rtc(); | 170 | omap_init_rtc(); |
171 | omap_init_sti(); | ||
132 | 172 | ||
133 | return 0; | 173 | return 0; |
134 | } | 174 | } |
diff --git a/arch/arm/mach-omap1/io.c b/arch/arm/mach-omap1/io.c index 82d556be79c5..be3a2a4ee2b8 100644 --- a/arch/arm/mach-omap1/io.c +++ b/arch/arm/mach-omap1/io.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <asm/io.h> | 18 | #include <asm/io.h> |
19 | #include <asm/arch/mux.h> | 19 | #include <asm/arch/mux.h> |
20 | #include <asm/arch/tc.h> | 20 | #include <asm/arch/tc.h> |
21 | #include <asm/arch/omapfb.h> | ||
21 | 22 | ||
22 | extern int omap1_clk_init(void); | 23 | extern int omap1_clk_init(void); |
23 | extern void omap_check_revision(void); | 24 | extern void omap_check_revision(void); |
@@ -110,7 +111,7 @@ void __init omap1_map_common_io(void) | |||
110 | } | 111 | } |
111 | #endif | 112 | #endif |
112 | #ifdef CONFIG_ARCH_OMAP15XX | 113 | #ifdef CONFIG_ARCH_OMAP15XX |
113 | if (cpu_is_omap1510()) { | 114 | if (cpu_is_omap15xx()) { |
114 | iotable_init(omap1510_io_desc, ARRAY_SIZE(omap1510_io_desc)); | 115 | iotable_init(omap1510_io_desc, ARRAY_SIZE(omap1510_io_desc)); |
115 | } | 116 | } |
116 | #endif | 117 | #endif |
@@ -121,6 +122,7 @@ void __init omap1_map_common_io(void) | |||
121 | #endif | 122 | #endif |
122 | 123 | ||
123 | omap_sram_init(); | 124 | omap_sram_init(); |
125 | omapfb_reserve_mem(); | ||
124 | } | 126 | } |
125 | 127 | ||
126 | /* | 128 | /* |
diff --git a/arch/arm/mach-omap1/irq.c b/arch/arm/mach-omap1/irq.c index ed65a7d2e941..a0431c00fa81 100644 --- a/arch/arm/mach-omap1/irq.c +++ b/arch/arm/mach-omap1/irq.c | |||
@@ -60,7 +60,7 @@ struct omap_irq_bank { | |||
60 | unsigned long wake_enable; | 60 | unsigned long wake_enable; |
61 | }; | 61 | }; |
62 | 62 | ||
63 | static unsigned int irq_bank_count = 0; | 63 | static unsigned int irq_bank_count; |
64 | static struct omap_irq_bank *irq_banks; | 64 | static struct omap_irq_bank *irq_banks; |
65 | 65 | ||
66 | static inline unsigned int irq_bank_readl(int bank, int offset) | 66 | static inline unsigned int irq_bank_readl(int bank, int offset) |
@@ -142,28 +142,28 @@ static void omap_irq_set_cfg(int irq, int fiq, int priority, int trigger) | |||
142 | 142 | ||
143 | #ifdef CONFIG_ARCH_OMAP730 | 143 | #ifdef CONFIG_ARCH_OMAP730 |
144 | static struct omap_irq_bank omap730_irq_banks[] = { | 144 | static struct omap_irq_bank omap730_irq_banks[] = { |
145 | { .base_reg = OMAP_IH1_BASE, .trigger_map = 0xb3f8e22f }, | 145 | { .base_reg = OMAP_IH1_BASE, .trigger_map = 0xb3f8e22f }, |
146 | { .base_reg = OMAP_IH2_BASE, .trigger_map = 0xfdb9c1f2 }, | 146 | { .base_reg = OMAP_IH2_BASE, .trigger_map = 0xfdb9c1f2 }, |
147 | { .base_reg = OMAP_IH2_BASE + 0x100, .trigger_map = 0x800040f3 }, | 147 | { .base_reg = OMAP_IH2_BASE + 0x100, .trigger_map = 0x800040f3 }, |
148 | }; | 148 | }; |
149 | #endif | 149 | #endif |
150 | 150 | ||
151 | #ifdef CONFIG_ARCH_OMAP15XX | 151 | #ifdef CONFIG_ARCH_OMAP15XX |
152 | static struct omap_irq_bank omap1510_irq_banks[] = { | 152 | static struct omap_irq_bank omap1510_irq_banks[] = { |
153 | { .base_reg = OMAP_IH1_BASE, .trigger_map = 0xb3febfff }, | 153 | { .base_reg = OMAP_IH1_BASE, .trigger_map = 0xb3febfff }, |
154 | { .base_reg = OMAP_IH2_BASE, .trigger_map = 0xffbfffed }, | 154 | { .base_reg = OMAP_IH2_BASE, .trigger_map = 0xffbfffed }, |
155 | }; | 155 | }; |
156 | static struct omap_irq_bank omap310_irq_banks[] = { | 156 | static struct omap_irq_bank omap310_irq_banks[] = { |
157 | { .base_reg = OMAP_IH1_BASE, .trigger_map = 0xb3faefc3 }, | 157 | { .base_reg = OMAP_IH1_BASE, .trigger_map = 0xb3faefc3 }, |
158 | { .base_reg = OMAP_IH2_BASE, .trigger_map = 0x65b3c061 }, | 158 | { .base_reg = OMAP_IH2_BASE, .trigger_map = 0x65b3c061 }, |
159 | }; | 159 | }; |
160 | #endif | 160 | #endif |
161 | 161 | ||
162 | #if defined(CONFIG_ARCH_OMAP16XX) | 162 | #if defined(CONFIG_ARCH_OMAP16XX) |
163 | 163 | ||
164 | static struct omap_irq_bank omap1610_irq_banks[] = { | 164 | static struct omap_irq_bank omap1610_irq_banks[] = { |
165 | { .base_reg = OMAP_IH1_BASE, .trigger_map = 0xb3fefe8f }, | 165 | { .base_reg = OMAP_IH1_BASE, .trigger_map = 0xb3fefe8f }, |
166 | { .base_reg = OMAP_IH2_BASE, .trigger_map = 0xfdb7c1fd }, | 166 | { .base_reg = OMAP_IH2_BASE, .trigger_map = 0xfdb7c1fd }, |
167 | { .base_reg = OMAP_IH2_BASE + 0x100, .trigger_map = 0xffffb7ff }, | 167 | { .base_reg = OMAP_IH2_BASE + 0x100, .trigger_map = 0xffffb7ff }, |
168 | { .base_reg = OMAP_IH2_BASE + 0x200, .trigger_map = 0xffffffff }, | 168 | { .base_reg = OMAP_IH2_BASE + 0x200, .trigger_map = 0xffffffff }, |
169 | }; | 169 | }; |
diff --git a/arch/arm/mach-omap1/mux.c b/arch/arm/mach-omap1/mux.c index d4b8d624e742..10fe0b3efcac 100644 --- a/arch/arm/mach-omap1/mux.c +++ b/arch/arm/mach-omap1/mux.c | |||
@@ -35,16 +35,20 @@ | |||
35 | 35 | ||
36 | #ifdef CONFIG_ARCH_OMAP730 | 36 | #ifdef CONFIG_ARCH_OMAP730 |
37 | struct pin_config __initdata_or_module omap730_pins[] = { | 37 | struct pin_config __initdata_or_module omap730_pins[] = { |
38 | MUX_CFG_730("E2_730_KBR0", 12, 21, 0, 0, 20, 1, NA, 0, 0) | 38 | MUX_CFG_730("E2_730_KBR0", 12, 21, 0, 20, 1, 0) |
39 | MUX_CFG_730("J7_730_KBR1", 12, 25, 0, 0, 24, 1, NA, 0, 0) | 39 | MUX_CFG_730("J7_730_KBR1", 12, 25, 0, 24, 1, 0) |
40 | MUX_CFG_730("E1_730_KBR2", 12, 29, 0, 0, 28, 1, NA, 0, 0) | 40 | MUX_CFG_730("E1_730_KBR2", 12, 29, 0, 28, 1, 0) |
41 | MUX_CFG_730("F3_730_KBR3", 13, 1, 0, 0, 0, 1, NA, 0, 0) | 41 | MUX_CFG_730("F3_730_KBR3", 13, 1, 0, 0, 1, 0) |
42 | MUX_CFG_730("D2_730_KBR4", 13, 5, 0, 0, 4, 1, NA, 0, 0) | 42 | MUX_CFG_730("D2_730_KBR4", 13, 5, 0, 4, 1, 0) |
43 | MUX_CFG_730("C2_730_KBC0", 13, 9, 0, 0, 8, 1, NA, 0, 0) | 43 | MUX_CFG_730("C2_730_KBC0", 13, 9, 0, 8, 1, 0) |
44 | MUX_CFG_730("D3_730_KBC1", 13, 13, 0, 0, 12, 1, NA, 0, 0) | 44 | MUX_CFG_730("D3_730_KBC1", 13, 13, 0, 12, 1, 0) |
45 | MUX_CFG_730("E4_730_KBC2", 13, 17, 0, 0, 16, 1, NA, 0, 0) | 45 | MUX_CFG_730("E4_730_KBC2", 13, 17, 0, 16, 1, 0) |
46 | MUX_CFG_730("F4_730_KBC3", 13, 21, 0, 0, 20, 1, NA, 0, 0) | 46 | MUX_CFG_730("F4_730_KBC3", 13, 21, 0, 20, 1, 0) |
47 | MUX_CFG_730("E3_730_KBC4", 13, 25, 0, 0, 24, 1, NA, 0, 0) | 47 | MUX_CFG_730("E3_730_KBC4", 13, 25, 0, 24, 1, 0) |
48 | |||
49 | MUX_CFG_730("AA17_730_USB_DM", 2, 21, 0, 20, 0, 0) | ||
50 | MUX_CFG_730("W16_730_USB_PU_EN", 2, 25, 0, 24, 0, 0) | ||
51 | MUX_CFG_730("W17_730_USB_VBUSI", 2, 29, 0, 28, 0, 0) | ||
48 | }; | 52 | }; |
49 | #endif | 53 | #endif |
50 | 54 | ||
@@ -73,8 +77,8 @@ MUX_CFG("UART3_BCLK", A, 0, 0, 2, 6, 0, NA, 0, 0) | |||
73 | MUX_CFG("Y15_1610_UART3_RTS", A, 0, 1, 2, 6, 0, NA, 0, 0) | 77 | MUX_CFG("Y15_1610_UART3_RTS", A, 0, 1, 2, 6, 0, NA, 0, 0) |
74 | 78 | ||
75 | /* PWT & PWL, conflicts with UART3 */ | 79 | /* PWT & PWL, conflicts with UART3 */ |
76 | MUX_CFG("PWT", 6, 0, 2, 0, 30, 0, NA, 0, 0) | 80 | MUX_CFG("PWT", 6, 0, 2, 0, 30, 0, NA, 0, 0) |
77 | MUX_CFG("PWL", 6, 3, 1, 0, 31, 1, NA, 0, 0) | 81 | MUX_CFG("PWL", 6, 3, 1, 0, 31, 1, NA, 0, 0) |
78 | 82 | ||
79 | /* USB internal master generic */ | 83 | /* USB internal master generic */ |
80 | MUX_CFG("R18_USB_VBUS", 7, 9, 2, 1, 11, 0, NA, 0, 1) | 84 | MUX_CFG("R18_USB_VBUS", 7, 9, 2, 1, 11, 0, NA, 0, 1) |
@@ -151,7 +155,7 @@ MUX_CFG("MCBSP3_CLKX", 9, 3, 1, 1, 29, 0, NA, 0, 1) | |||
151 | 155 | ||
152 | /* Misc ballouts */ | 156 | /* Misc ballouts */ |
153 | MUX_CFG("BALLOUT_V8_ARMIO3", B, 18, 0, 2, 25, 1, NA, 0, 1) | 157 | MUX_CFG("BALLOUT_V8_ARMIO3", B, 18, 0, 2, 25, 1, NA, 0, 1) |
154 | MUX_CFG("N20_HDQ", 6, 18, 1, 1, 4, 0, 1, 4, 0) | 158 | MUX_CFG("N20_HDQ", 6, 18, 1, 1, 4, 0, 1, 4, 0) |
155 | 159 | ||
156 | /* OMAP-1610 MMC2 */ | 160 | /* OMAP-1610 MMC2 */ |
157 | MUX_CFG("W8_1610_MMC2_DAT0", B, 21, 6, 2, 23, 1, 2, 1, 1) | 161 | MUX_CFG("W8_1610_MMC2_DAT0", B, 21, 6, 2, 23, 1, 2, 1, 1) |
diff --git a/arch/arm/mach-omap1/pm.c b/arch/arm/mach-omap1/pm.c new file mode 100644 index 000000000000..ddf6b07dc9c7 --- /dev/null +++ b/arch/arm/mach-omap1/pm.c | |||
@@ -0,0 +1,770 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-omap1/pm.c | ||
3 | * | ||
4 | * OMAP Power Management Routines | ||
5 | * | ||
6 | * Original code for the SA11x0: | ||
7 | * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com> | ||
8 | * | ||
9 | * Modified for the PXA250 by Nicolas Pitre: | ||
10 | * Copyright (c) 2002 Monta Vista Software, Inc. | ||
11 | * | ||
12 | * Modified for the OMAP1510 by David Singleton: | ||
13 | * Copyright (c) 2002 Monta Vista Software, Inc. | ||
14 | * | ||
15 | * Cleanup 2004 for OMAP1510/1610 by Dirk Behme <dirk.behme@de.bosch.com> | ||
16 | * | ||
17 | * This program is free software; you can redistribute it and/or modify it | ||
18 | * under the terms of the GNU General Public License as published by the | ||
19 | * Free Software Foundation; either version 2 of the License, or (at your | ||
20 | * option) any later version. | ||
21 | * | ||
22 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
23 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
24 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | ||
25 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
26 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
27 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
28 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
29 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
31 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
32 | * | ||
33 | * You should have received a copy of the GNU General Public License along | ||
34 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
35 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
36 | */ | ||
37 | |||
38 | #include <linux/pm.h> | ||
39 | #include <linux/sched.h> | ||
40 | #include <linux/proc_fs.h> | ||
41 | #include <linux/pm.h> | ||
42 | #include <linux/interrupt.h> | ||
43 | #include <linux/sysfs.h> | ||
44 | #include <linux/module.h> | ||
45 | |||
46 | #include <asm/io.h> | ||
47 | #include <asm/irq.h> | ||
48 | #include <asm/atomic.h> | ||
49 | #include <asm/mach/time.h> | ||
50 | #include <asm/mach/irq.h> | ||
51 | #include <asm/mach-types.h> | ||
52 | |||
53 | #include <asm/arch/irqs.h> | ||
54 | #include <asm/arch/clock.h> | ||
55 | #include <asm/arch/sram.h> | ||
56 | #include <asm/arch/tc.h> | ||
57 | #include <asm/arch/pm.h> | ||
58 | #include <asm/arch/mux.h> | ||
59 | #include <asm/arch/tps65010.h> | ||
60 | #include <asm/arch/dma.h> | ||
61 | #include <asm/arch/dsp_common.h> | ||
62 | #include <asm/arch/dmtimer.h> | ||
63 | |||
64 | static unsigned int arm_sleep_save[ARM_SLEEP_SAVE_SIZE]; | ||
65 | static unsigned short dsp_sleep_save[DSP_SLEEP_SAVE_SIZE]; | ||
66 | static unsigned short ulpd_sleep_save[ULPD_SLEEP_SAVE_SIZE]; | ||
67 | static unsigned int mpui730_sleep_save[MPUI730_SLEEP_SAVE_SIZE]; | ||
68 | static unsigned int mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_SIZE]; | ||
69 | static unsigned int mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_SIZE]; | ||
70 | |||
71 | static unsigned short enable_dyn_sleep = 1; | ||
72 | |||
73 | static ssize_t omap_pm_sleep_while_idle_show(struct subsystem * subsys, char *buf) | ||
74 | { | ||
75 | return sprintf(buf, "%hu\n", enable_dyn_sleep); | ||
76 | } | ||
77 | |||
78 | static ssize_t omap_pm_sleep_while_idle_store(struct subsystem * subsys, | ||
79 | const char * buf, | ||
80 | size_t n) | ||
81 | { | ||
82 | unsigned short value; | ||
83 | if (sscanf(buf, "%hu", &value) != 1 || | ||
84 | (value != 0 && value != 1)) { | ||
85 | printk(KERN_ERR "idle_sleep_store: Invalid value\n"); | ||
86 | return -EINVAL; | ||
87 | } | ||
88 | enable_dyn_sleep = value; | ||
89 | return n; | ||
90 | } | ||
91 | |||
92 | static struct subsys_attribute sleep_while_idle_attr = { | ||
93 | .attr = { | ||
94 | .name = __stringify(sleep_while_idle), | ||
95 | .mode = 0644, | ||
96 | }, | ||
97 | .show = omap_pm_sleep_while_idle_show, | ||
98 | .store = omap_pm_sleep_while_idle_store, | ||
99 | }; | ||
100 | |||
101 | extern struct subsystem power_subsys; | ||
102 | static void (*omap_sram_idle)(void) = NULL; | ||
103 | static void (*omap_sram_suspend)(unsigned long r0, unsigned long r1) = NULL; | ||
104 | |||
105 | /* | ||
106 | * Let's power down on idle, but only if we are really | ||
107 | * idle, because once we start down the path of | ||
108 | * going idle we continue to do idle even if we get | ||
109 | * a clock tick interrupt . . | ||
110 | */ | ||
111 | void omap_pm_idle(void) | ||
112 | { | ||
113 | extern __u32 arm_idlect1_mask; | ||
114 | __u32 use_idlect1 = arm_idlect1_mask; | ||
115 | #ifndef CONFIG_OMAP_MPU_TIMER | ||
116 | int do_sleep; | ||
117 | #endif | ||
118 | |||
119 | local_irq_disable(); | ||
120 | local_fiq_disable(); | ||
121 | if (need_resched()) { | ||
122 | local_fiq_enable(); | ||
123 | local_irq_enable(); | ||
124 | return; | ||
125 | } | ||
126 | |||
127 | /* | ||
128 | * Since an interrupt may set up a timer, we don't want to | ||
129 | * reprogram the hardware timer with interrupts enabled. | ||
130 | * Re-enable interrupts only after returning from idle. | ||
131 | */ | ||
132 | timer_dyn_reprogram(); | ||
133 | |||
134 | #ifdef CONFIG_OMAP_MPU_TIMER | ||
135 | #warning Enable 32kHz OS timer in order to allow sleep states in idle | ||
136 | use_idlect1 = use_idlect1 & ~(1 << 9); | ||
137 | #else | ||
138 | |||
139 | do_sleep = 0; | ||
140 | while (enable_dyn_sleep) { | ||
141 | |||
142 | #ifdef CONFIG_CBUS_TAHVO_USB | ||
143 | extern int vbus_active; | ||
144 | /* Clock requirements? */ | ||
145 | if (vbus_active) | ||
146 | break; | ||
147 | #endif | ||
148 | do_sleep = 1; | ||
149 | break; | ||
150 | } | ||
151 | |||
152 | #ifdef CONFIG_OMAP_DM_TIMER | ||
153 | use_idlect1 = omap_dm_timer_modify_idlect_mask(use_idlect1); | ||
154 | #endif | ||
155 | |||
156 | if (omap_dma_running()) { | ||
157 | use_idlect1 &= ~(1 << 6); | ||
158 | if (omap_lcd_dma_ext_running()) | ||
159 | use_idlect1 &= ~(1 << 12); | ||
160 | } | ||
161 | |||
162 | /* We should be able to remove the do_sleep variable and multiple | ||
163 | * tests above as soon as drivers, timer and DMA code have been fixed. | ||
164 | * Even the sleep block count should become obsolete. */ | ||
165 | if ((use_idlect1 != ~0) || !do_sleep) { | ||
166 | |||
167 | __u32 saved_idlect1 = omap_readl(ARM_IDLECT1); | ||
168 | if (cpu_is_omap15xx()) | ||
169 | use_idlect1 &= OMAP1510_BIG_SLEEP_REQUEST; | ||
170 | else | ||
171 | use_idlect1 &= OMAP1610_IDLECT1_SLEEP_VAL; | ||
172 | omap_writel(use_idlect1, ARM_IDLECT1); | ||
173 | __asm__ volatile ("mcr p15, 0, r0, c7, c0, 4"); | ||
174 | omap_writel(saved_idlect1, ARM_IDLECT1); | ||
175 | |||
176 | local_fiq_enable(); | ||
177 | local_irq_enable(); | ||
178 | return; | ||
179 | } | ||
180 | omap_sram_suspend(omap_readl(ARM_IDLECT1), | ||
181 | omap_readl(ARM_IDLECT2)); | ||
182 | #endif | ||
183 | |||
184 | local_fiq_enable(); | ||
185 | local_irq_enable(); | ||
186 | } | ||
187 | |||
188 | /* | ||
189 | * Configuration of the wakeup event is board specific. For the | ||
190 | * moment we put it into this helper function. Later it may move | ||
191 | * to board specific files. | ||
192 | */ | ||
193 | static void omap_pm_wakeup_setup(void) | ||
194 | { | ||
195 | u32 level1_wake = 0; | ||
196 | u32 level2_wake = OMAP_IRQ_BIT(INT_UART2); | ||
197 | |||
198 | /* | ||
199 | * Turn off all interrupts except GPIO bank 1, L1-2nd level cascade, | ||
200 | * and the L2 wakeup interrupts: keypad and UART2. Note that the | ||
201 | * drivers must still separately call omap_set_gpio_wakeup() to | ||
202 | * wake up to a GPIO interrupt. | ||
203 | */ | ||
204 | if (cpu_is_omap730()) | ||
205 | level1_wake = OMAP_IRQ_BIT(INT_730_GPIO_BANK1) | | ||
206 | OMAP_IRQ_BIT(INT_730_IH2_IRQ); | ||
207 | else if (cpu_is_omap15xx()) | ||
208 | level1_wake = OMAP_IRQ_BIT(INT_GPIO_BANK1) | | ||
209 | OMAP_IRQ_BIT(INT_1510_IH2_IRQ); | ||
210 | else if (cpu_is_omap16xx()) | ||
211 | level1_wake = OMAP_IRQ_BIT(INT_GPIO_BANK1) | | ||
212 | OMAP_IRQ_BIT(INT_1610_IH2_IRQ); | ||
213 | |||
214 | omap_writel(~level1_wake, OMAP_IH1_MIR); | ||
215 | |||
216 | if (cpu_is_omap730()) { | ||
217 | omap_writel(~level2_wake, OMAP_IH2_0_MIR); | ||
218 | omap_writel(~(OMAP_IRQ_BIT(INT_730_WAKE_UP_REQ) | | ||
219 | OMAP_IRQ_BIT(INT_730_MPUIO_KEYPAD)), | ||
220 | OMAP_IH2_1_MIR); | ||
221 | } else if (cpu_is_omap15xx()) { | ||
222 | level2_wake |= OMAP_IRQ_BIT(INT_KEYBOARD); | ||
223 | omap_writel(~level2_wake, OMAP_IH2_MIR); | ||
224 | } else if (cpu_is_omap16xx()) { | ||
225 | level2_wake |= OMAP_IRQ_BIT(INT_KEYBOARD); | ||
226 | omap_writel(~level2_wake, OMAP_IH2_0_MIR); | ||
227 | |||
228 | /* INT_1610_WAKE_UP_REQ is needed for GPIO wakeup... */ | ||
229 | omap_writel(~OMAP_IRQ_BIT(INT_1610_WAKE_UP_REQ), | ||
230 | OMAP_IH2_1_MIR); | ||
231 | omap_writel(~0x0, OMAP_IH2_2_MIR); | ||
232 | omap_writel(~0x0, OMAP_IH2_3_MIR); | ||
233 | } | ||
234 | |||
235 | /* New IRQ agreement, recalculate in cascade order */ | ||
236 | omap_writel(1, OMAP_IH2_CONTROL); | ||
237 | omap_writel(1, OMAP_IH1_CONTROL); | ||
238 | } | ||
239 | |||
240 | #define EN_DSPCK 13 /* ARM_CKCTL */ | ||
241 | #define EN_APICK 6 /* ARM_IDLECT2 */ | ||
242 | #define DSP_EN 1 /* ARM_RSTCT1 */ | ||
243 | |||
244 | void omap_pm_suspend(void) | ||
245 | { | ||
246 | unsigned long arg0 = 0, arg1 = 0; | ||
247 | |||
248 | printk("PM: OMAP%x is trying to enter deep sleep...\n", system_rev); | ||
249 | |||
250 | omap_serial_wake_trigger(1); | ||
251 | |||
252 | if (machine_is_omap_osk()) { | ||
253 | /* Stop LED1 (D9) blink */ | ||
254 | tps65010_set_led(LED1, OFF); | ||
255 | } | ||
256 | |||
257 | omap_writew(0xffff, ULPD_SOFT_DISABLE_REQ_REG); | ||
258 | |||
259 | /* | ||
260 | * Step 1: turn off interrupts (FIXME: NOTE: already disabled) | ||
261 | */ | ||
262 | |||
263 | local_irq_disable(); | ||
264 | local_fiq_disable(); | ||
265 | |||
266 | /* | ||
267 | * Step 2: save registers | ||
268 | * | ||
269 | * The omap is a strange/beautiful device. The caches, memory | ||
270 | * and register state are preserved across power saves. | ||
271 | * We have to save and restore very little register state to | ||
272 | * idle the omap. | ||
273 | * | ||
274 | * Save interrupt, MPUI, ARM and UPLD control registers. | ||
275 | */ | ||
276 | |||
277 | if (cpu_is_omap730()) { | ||
278 | MPUI730_SAVE(OMAP_IH1_MIR); | ||
279 | MPUI730_SAVE(OMAP_IH2_0_MIR); | ||
280 | MPUI730_SAVE(OMAP_IH2_1_MIR); | ||
281 | MPUI730_SAVE(MPUI_CTRL); | ||
282 | MPUI730_SAVE(MPUI_DSP_BOOT_CONFIG); | ||
283 | MPUI730_SAVE(MPUI_DSP_API_CONFIG); | ||
284 | MPUI730_SAVE(EMIFS_CONFIG); | ||
285 | MPUI730_SAVE(EMIFF_SDRAM_CONFIG); | ||
286 | |||
287 | } else if (cpu_is_omap15xx()) { | ||
288 | MPUI1510_SAVE(OMAP_IH1_MIR); | ||
289 | MPUI1510_SAVE(OMAP_IH2_MIR); | ||
290 | MPUI1510_SAVE(MPUI_CTRL); | ||
291 | MPUI1510_SAVE(MPUI_DSP_BOOT_CONFIG); | ||
292 | MPUI1510_SAVE(MPUI_DSP_API_CONFIG); | ||
293 | MPUI1510_SAVE(EMIFS_CONFIG); | ||
294 | MPUI1510_SAVE(EMIFF_SDRAM_CONFIG); | ||
295 | } else if (cpu_is_omap16xx()) { | ||
296 | MPUI1610_SAVE(OMAP_IH1_MIR); | ||
297 | MPUI1610_SAVE(OMAP_IH2_0_MIR); | ||
298 | MPUI1610_SAVE(OMAP_IH2_1_MIR); | ||
299 | MPUI1610_SAVE(OMAP_IH2_2_MIR); | ||
300 | MPUI1610_SAVE(OMAP_IH2_3_MIR); | ||
301 | MPUI1610_SAVE(MPUI_CTRL); | ||
302 | MPUI1610_SAVE(MPUI_DSP_BOOT_CONFIG); | ||
303 | MPUI1610_SAVE(MPUI_DSP_API_CONFIG); | ||
304 | MPUI1610_SAVE(EMIFS_CONFIG); | ||
305 | MPUI1610_SAVE(EMIFF_SDRAM_CONFIG); | ||
306 | } | ||
307 | |||
308 | ARM_SAVE(ARM_CKCTL); | ||
309 | ARM_SAVE(ARM_IDLECT1); | ||
310 | ARM_SAVE(ARM_IDLECT2); | ||
311 | if (!(cpu_is_omap15xx())) | ||
312 | ARM_SAVE(ARM_IDLECT3); | ||
313 | ARM_SAVE(ARM_EWUPCT); | ||
314 | ARM_SAVE(ARM_RSTCT1); | ||
315 | ARM_SAVE(ARM_RSTCT2); | ||
316 | ARM_SAVE(ARM_SYSST); | ||
317 | ULPD_SAVE(ULPD_CLOCK_CTRL); | ||
318 | ULPD_SAVE(ULPD_STATUS_REQ); | ||
319 | |||
320 | /* (Step 3 removed - we now allow deep sleep by default) */ | ||
321 | |||
322 | /* | ||
323 | * Step 4: OMAP DSP Shutdown | ||
324 | */ | ||
325 | |||
326 | /* stop DSP */ | ||
327 | omap_writew(omap_readw(ARM_RSTCT1) & ~(1 << DSP_EN), ARM_RSTCT1); | ||
328 | |||
329 | /* shut down dsp_ck */ | ||
330 | omap_writew(omap_readw(ARM_CKCTL) & ~(1 << EN_DSPCK), ARM_CKCTL); | ||
331 | |||
332 | /* temporarily enabling api_ck to access DSP registers */ | ||
333 | omap_writew(omap_readw(ARM_IDLECT2) | 1 << EN_APICK, ARM_IDLECT2); | ||
334 | |||
335 | /* save DSP registers */ | ||
336 | DSP_SAVE(DSP_IDLECT2); | ||
337 | |||
338 | /* Stop all DSP domain clocks */ | ||
339 | __raw_writew(0, DSP_IDLECT2); | ||
340 | |||
341 | /* | ||
342 | * Step 5: Wakeup Event Setup | ||
343 | */ | ||
344 | |||
345 | omap_pm_wakeup_setup(); | ||
346 | |||
347 | /* | ||
348 | * Step 6: ARM and Traffic controller shutdown | ||
349 | */ | ||
350 | |||
351 | /* disable ARM watchdog */ | ||
352 | omap_writel(0x00F5, OMAP_WDT_TIMER_MODE); | ||
353 | omap_writel(0x00A0, OMAP_WDT_TIMER_MODE); | ||
354 | |||
355 | /* | ||
356 | * Step 6b: ARM and Traffic controller shutdown | ||
357 | * | ||
358 | * Step 6 continues here. Prepare jump to power management | ||
359 | * assembly code in internal SRAM. | ||
360 | * | ||
361 | * Since the omap_cpu_suspend routine has been copied to | ||
362 | * SRAM, we'll do an indirect procedure call to it and pass the | ||
363 | * contents of arm_idlect1 and arm_idlect2 so it can restore | ||
364 | * them when it wakes up and it will return. | ||
365 | */ | ||
366 | |||
367 | arg0 = arm_sleep_save[ARM_SLEEP_SAVE_ARM_IDLECT1]; | ||
368 | arg1 = arm_sleep_save[ARM_SLEEP_SAVE_ARM_IDLECT2]; | ||
369 | |||
370 | /* | ||
371 | * Step 6c: ARM and Traffic controller shutdown | ||
372 | * | ||
373 | * Jump to assembly code. The processor will stay there | ||
374 | * until wake up. | ||
375 | */ | ||
376 | omap_sram_suspend(arg0, arg1); | ||
377 | |||
378 | /* | ||
379 | * If we are here, processor is woken up! | ||
380 | */ | ||
381 | |||
382 | /* | ||
383 | * Restore DSP clocks | ||
384 | */ | ||
385 | |||
386 | /* again temporarily enabling api_ck to access DSP registers */ | ||
387 | omap_writew(omap_readw(ARM_IDLECT2) | 1 << EN_APICK, ARM_IDLECT2); | ||
388 | |||
389 | /* Restore DSP domain clocks */ | ||
390 | DSP_RESTORE(DSP_IDLECT2); | ||
391 | |||
392 | /* | ||
393 | * Restore ARM state, except ARM_IDLECT1/2 which omap_cpu_suspend did | ||
394 | */ | ||
395 | |||
396 | if (!(cpu_is_omap15xx())) | ||
397 | ARM_RESTORE(ARM_IDLECT3); | ||
398 | ARM_RESTORE(ARM_CKCTL); | ||
399 | ARM_RESTORE(ARM_EWUPCT); | ||
400 | ARM_RESTORE(ARM_RSTCT1); | ||
401 | ARM_RESTORE(ARM_RSTCT2); | ||
402 | ARM_RESTORE(ARM_SYSST); | ||
403 | ULPD_RESTORE(ULPD_CLOCK_CTRL); | ||
404 | ULPD_RESTORE(ULPD_STATUS_REQ); | ||
405 | |||
406 | if (cpu_is_omap730()) { | ||
407 | MPUI730_RESTORE(EMIFS_CONFIG); | ||
408 | MPUI730_RESTORE(EMIFF_SDRAM_CONFIG); | ||
409 | MPUI730_RESTORE(OMAP_IH1_MIR); | ||
410 | MPUI730_RESTORE(OMAP_IH2_0_MIR); | ||
411 | MPUI730_RESTORE(OMAP_IH2_1_MIR); | ||
412 | } else if (cpu_is_omap15xx()) { | ||
413 | MPUI1510_RESTORE(MPUI_CTRL); | ||
414 | MPUI1510_RESTORE(MPUI_DSP_BOOT_CONFIG); | ||
415 | MPUI1510_RESTORE(MPUI_DSP_API_CONFIG); | ||
416 | MPUI1510_RESTORE(EMIFS_CONFIG); | ||
417 | MPUI1510_RESTORE(EMIFF_SDRAM_CONFIG); | ||
418 | MPUI1510_RESTORE(OMAP_IH1_MIR); | ||
419 | MPUI1510_RESTORE(OMAP_IH2_MIR); | ||
420 | } else if (cpu_is_omap16xx()) { | ||
421 | MPUI1610_RESTORE(MPUI_CTRL); | ||
422 | MPUI1610_RESTORE(MPUI_DSP_BOOT_CONFIG); | ||
423 | MPUI1610_RESTORE(MPUI_DSP_API_CONFIG); | ||
424 | MPUI1610_RESTORE(EMIFS_CONFIG); | ||
425 | MPUI1610_RESTORE(EMIFF_SDRAM_CONFIG); | ||
426 | |||
427 | MPUI1610_RESTORE(OMAP_IH1_MIR); | ||
428 | MPUI1610_RESTORE(OMAP_IH2_0_MIR); | ||
429 | MPUI1610_RESTORE(OMAP_IH2_1_MIR); | ||
430 | MPUI1610_RESTORE(OMAP_IH2_2_MIR); | ||
431 | MPUI1610_RESTORE(OMAP_IH2_3_MIR); | ||
432 | } | ||
433 | |||
434 | omap_writew(0, ULPD_SOFT_DISABLE_REQ_REG); | ||
435 | |||
436 | /* | ||
437 | * Reenable interrupts | ||
438 | */ | ||
439 | |||
440 | local_irq_enable(); | ||
441 | local_fiq_enable(); | ||
442 | |||
443 | omap_serial_wake_trigger(0); | ||
444 | |||
445 | printk("PM: OMAP%x is re-starting from deep sleep...\n", system_rev); | ||
446 | |||
447 | if (machine_is_omap_osk()) { | ||
448 | /* Let LED1 (D9) blink again */ | ||
449 | tps65010_set_led(LED1, BLINK); | ||
450 | } | ||
451 | } | ||
452 | |||
453 | #if defined(DEBUG) && defined(CONFIG_PROC_FS) | ||
454 | static int g_read_completed; | ||
455 | |||
456 | /* | ||
457 | * Read system PM registers for debugging | ||
458 | */ | ||
459 | static int omap_pm_read_proc( | ||
460 | char *page_buffer, | ||
461 | char **my_first_byte, | ||
462 | off_t virtual_start, | ||
463 | int length, | ||
464 | int *eof, | ||
465 | void *data) | ||
466 | { | ||
467 | int my_buffer_offset = 0; | ||
468 | char * const my_base = page_buffer; | ||
469 | |||
470 | ARM_SAVE(ARM_CKCTL); | ||
471 | ARM_SAVE(ARM_IDLECT1); | ||
472 | ARM_SAVE(ARM_IDLECT2); | ||
473 | if (!(cpu_is_omap15xx())) | ||
474 | ARM_SAVE(ARM_IDLECT3); | ||
475 | ARM_SAVE(ARM_EWUPCT); | ||
476 | ARM_SAVE(ARM_RSTCT1); | ||
477 | ARM_SAVE(ARM_RSTCT2); | ||
478 | ARM_SAVE(ARM_SYSST); | ||
479 | |||
480 | ULPD_SAVE(ULPD_IT_STATUS); | ||
481 | ULPD_SAVE(ULPD_CLOCK_CTRL); | ||
482 | ULPD_SAVE(ULPD_SOFT_REQ); | ||
483 | ULPD_SAVE(ULPD_STATUS_REQ); | ||
484 | ULPD_SAVE(ULPD_DPLL_CTRL); | ||
485 | ULPD_SAVE(ULPD_POWER_CTRL); | ||
486 | |||
487 | if (cpu_is_omap730()) { | ||
488 | MPUI730_SAVE(MPUI_CTRL); | ||
489 | MPUI730_SAVE(MPUI_DSP_STATUS); | ||
490 | MPUI730_SAVE(MPUI_DSP_BOOT_CONFIG); | ||
491 | MPUI730_SAVE(MPUI_DSP_API_CONFIG); | ||
492 | MPUI730_SAVE(EMIFF_SDRAM_CONFIG); | ||
493 | MPUI730_SAVE(EMIFS_CONFIG); | ||
494 | } else if (cpu_is_omap15xx()) { | ||
495 | MPUI1510_SAVE(MPUI_CTRL); | ||
496 | MPUI1510_SAVE(MPUI_DSP_STATUS); | ||
497 | MPUI1510_SAVE(MPUI_DSP_BOOT_CONFIG); | ||
498 | MPUI1510_SAVE(MPUI_DSP_API_CONFIG); | ||
499 | MPUI1510_SAVE(EMIFF_SDRAM_CONFIG); | ||
500 | MPUI1510_SAVE(EMIFS_CONFIG); | ||
501 | } else if (cpu_is_omap16xx()) { | ||
502 | MPUI1610_SAVE(MPUI_CTRL); | ||
503 | MPUI1610_SAVE(MPUI_DSP_STATUS); | ||
504 | MPUI1610_SAVE(MPUI_DSP_BOOT_CONFIG); | ||
505 | MPUI1610_SAVE(MPUI_DSP_API_CONFIG); | ||
506 | MPUI1610_SAVE(EMIFF_SDRAM_CONFIG); | ||
507 | MPUI1610_SAVE(EMIFS_CONFIG); | ||
508 | } | ||
509 | |||
510 | if (virtual_start == 0) { | ||
511 | g_read_completed = 0; | ||
512 | |||
513 | my_buffer_offset += sprintf(my_base + my_buffer_offset, | ||
514 | "ARM_CKCTL_REG: 0x%-8x \n" | ||
515 | "ARM_IDLECT1_REG: 0x%-8x \n" | ||
516 | "ARM_IDLECT2_REG: 0x%-8x \n" | ||
517 | "ARM_IDLECT3_REG: 0x%-8x \n" | ||
518 | "ARM_EWUPCT_REG: 0x%-8x \n" | ||
519 | "ARM_RSTCT1_REG: 0x%-8x \n" | ||
520 | "ARM_RSTCT2_REG: 0x%-8x \n" | ||
521 | "ARM_SYSST_REG: 0x%-8x \n" | ||
522 | "ULPD_IT_STATUS_REG: 0x%-4x \n" | ||
523 | "ULPD_CLOCK_CTRL_REG: 0x%-4x \n" | ||
524 | "ULPD_SOFT_REQ_REG: 0x%-4x \n" | ||
525 | "ULPD_DPLL_CTRL_REG: 0x%-4x \n" | ||
526 | "ULPD_STATUS_REQ_REG: 0x%-4x \n" | ||
527 | "ULPD_POWER_CTRL_REG: 0x%-4x \n", | ||
528 | ARM_SHOW(ARM_CKCTL), | ||
529 | ARM_SHOW(ARM_IDLECT1), | ||
530 | ARM_SHOW(ARM_IDLECT2), | ||
531 | ARM_SHOW(ARM_IDLECT3), | ||
532 | ARM_SHOW(ARM_EWUPCT), | ||
533 | ARM_SHOW(ARM_RSTCT1), | ||
534 | ARM_SHOW(ARM_RSTCT2), | ||
535 | ARM_SHOW(ARM_SYSST), | ||
536 | ULPD_SHOW(ULPD_IT_STATUS), | ||
537 | ULPD_SHOW(ULPD_CLOCK_CTRL), | ||
538 | ULPD_SHOW(ULPD_SOFT_REQ), | ||
539 | ULPD_SHOW(ULPD_DPLL_CTRL), | ||
540 | ULPD_SHOW(ULPD_STATUS_REQ), | ||
541 | ULPD_SHOW(ULPD_POWER_CTRL)); | ||
542 | |||
543 | if (cpu_is_omap730()) { | ||
544 | my_buffer_offset += sprintf(my_base + my_buffer_offset, | ||
545 | "MPUI730_CTRL_REG 0x%-8x \n" | ||
546 | "MPUI730_DSP_STATUS_REG: 0x%-8x \n" | ||
547 | "MPUI730_DSP_BOOT_CONFIG_REG: 0x%-8x \n" | ||
548 | "MPUI730_DSP_API_CONFIG_REG: 0x%-8x \n" | ||
549 | "MPUI730_SDRAM_CONFIG_REG: 0x%-8x \n" | ||
550 | "MPUI730_EMIFS_CONFIG_REG: 0x%-8x \n", | ||
551 | MPUI730_SHOW(MPUI_CTRL), | ||
552 | MPUI730_SHOW(MPUI_DSP_STATUS), | ||
553 | MPUI730_SHOW(MPUI_DSP_BOOT_CONFIG), | ||
554 | MPUI730_SHOW(MPUI_DSP_API_CONFIG), | ||
555 | MPUI730_SHOW(EMIFF_SDRAM_CONFIG), | ||
556 | MPUI730_SHOW(EMIFS_CONFIG)); | ||
557 | } else if (cpu_is_omap15xx()) { | ||
558 | my_buffer_offset += sprintf(my_base + my_buffer_offset, | ||
559 | "MPUI1510_CTRL_REG 0x%-8x \n" | ||
560 | "MPUI1510_DSP_STATUS_REG: 0x%-8x \n" | ||
561 | "MPUI1510_DSP_BOOT_CONFIG_REG: 0x%-8x \n" | ||
562 | "MPUI1510_DSP_API_CONFIG_REG: 0x%-8x \n" | ||
563 | "MPUI1510_SDRAM_CONFIG_REG: 0x%-8x \n" | ||
564 | "MPUI1510_EMIFS_CONFIG_REG: 0x%-8x \n", | ||
565 | MPUI1510_SHOW(MPUI_CTRL), | ||
566 | MPUI1510_SHOW(MPUI_DSP_STATUS), | ||
567 | MPUI1510_SHOW(MPUI_DSP_BOOT_CONFIG), | ||
568 | MPUI1510_SHOW(MPUI_DSP_API_CONFIG), | ||
569 | MPUI1510_SHOW(EMIFF_SDRAM_CONFIG), | ||
570 | MPUI1510_SHOW(EMIFS_CONFIG)); | ||
571 | } else if (cpu_is_omap16xx()) { | ||
572 | my_buffer_offset += sprintf(my_base + my_buffer_offset, | ||
573 | "MPUI1610_CTRL_REG 0x%-8x \n" | ||
574 | "MPUI1610_DSP_STATUS_REG: 0x%-8x \n" | ||
575 | "MPUI1610_DSP_BOOT_CONFIG_REG: 0x%-8x \n" | ||
576 | "MPUI1610_DSP_API_CONFIG_REG: 0x%-8x \n" | ||
577 | "MPUI1610_SDRAM_CONFIG_REG: 0x%-8x \n" | ||
578 | "MPUI1610_EMIFS_CONFIG_REG: 0x%-8x \n", | ||
579 | MPUI1610_SHOW(MPUI_CTRL), | ||
580 | MPUI1610_SHOW(MPUI_DSP_STATUS), | ||
581 | MPUI1610_SHOW(MPUI_DSP_BOOT_CONFIG), | ||
582 | MPUI1610_SHOW(MPUI_DSP_API_CONFIG), | ||
583 | MPUI1610_SHOW(EMIFF_SDRAM_CONFIG), | ||
584 | MPUI1610_SHOW(EMIFS_CONFIG)); | ||
585 | } | ||
586 | |||
587 | g_read_completed++; | ||
588 | } else if (g_read_completed >= 1) { | ||
589 | *eof = 1; | ||
590 | return 0; | ||
591 | } | ||
592 | g_read_completed++; | ||
593 | |||
594 | *my_first_byte = page_buffer; | ||
595 | return my_buffer_offset; | ||
596 | } | ||
597 | |||
598 | static void omap_pm_init_proc(void) | ||
599 | { | ||
600 | struct proc_dir_entry *entry; | ||
601 | |||
602 | entry = create_proc_read_entry("driver/omap_pm", | ||
603 | S_IWUSR | S_IRUGO, NULL, | ||
604 | omap_pm_read_proc, NULL); | ||
605 | } | ||
606 | |||
607 | #endif /* DEBUG && CONFIG_PROC_FS */ | ||
608 | |||
609 | static void (*saved_idle)(void) = NULL; | ||
610 | |||
611 | /* | ||
612 | * omap_pm_prepare - Do preliminary suspend work. | ||
613 | * @state: suspend state we're entering. | ||
614 | * | ||
615 | */ | ||
616 | static int omap_pm_prepare(suspend_state_t state) | ||
617 | { | ||
618 | int error = 0; | ||
619 | |||
620 | /* We cannot sleep in idle until we have resumed */ | ||
621 | saved_idle = pm_idle; | ||
622 | pm_idle = NULL; | ||
623 | |||
624 | switch (state) | ||
625 | { | ||
626 | case PM_SUSPEND_STANDBY: | ||
627 | case PM_SUSPEND_MEM: | ||
628 | break; | ||
629 | |||
630 | case PM_SUSPEND_DISK: | ||
631 | return -ENOTSUPP; | ||
632 | |||
633 | default: | ||
634 | return -EINVAL; | ||
635 | } | ||
636 | |||
637 | return error; | ||
638 | } | ||
639 | |||
640 | |||
641 | /* | ||
642 | * omap_pm_enter - Actually enter a sleep state. | ||
643 | * @state: State we're entering. | ||
644 | * | ||
645 | */ | ||
646 | |||
647 | static int omap_pm_enter(suspend_state_t state) | ||
648 | { | ||
649 | switch (state) | ||
650 | { | ||
651 | case PM_SUSPEND_STANDBY: | ||
652 | case PM_SUSPEND_MEM: | ||
653 | omap_pm_suspend(); | ||
654 | break; | ||
655 | |||
656 | case PM_SUSPEND_DISK: | ||
657 | return -ENOTSUPP; | ||
658 | |||
659 | default: | ||
660 | return -EINVAL; | ||
661 | } | ||
662 | |||
663 | return 0; | ||
664 | } | ||
665 | |||
666 | |||
667 | /** | ||
668 | * omap_pm_finish - Finish up suspend sequence. | ||
669 | * @state: State we're coming out of. | ||
670 | * | ||
671 | * This is called after we wake back up (or if entering the sleep state | ||
672 | * failed). | ||
673 | */ | ||
674 | |||
675 | static int omap_pm_finish(suspend_state_t state) | ||
676 | { | ||
677 | pm_idle = saved_idle; | ||
678 | return 0; | ||
679 | } | ||
680 | |||
681 | |||
682 | static irqreturn_t omap_wakeup_interrupt(int irq, void * dev, | ||
683 | struct pt_regs * regs) | ||
684 | { | ||
685 | return IRQ_HANDLED; | ||
686 | } | ||
687 | |||
688 | static struct irqaction omap_wakeup_irq = { | ||
689 | .name = "peripheral wakeup", | ||
690 | .flags = SA_INTERRUPT, | ||
691 | .handler = omap_wakeup_interrupt | ||
692 | }; | ||
693 | |||
694 | |||
695 | |||
696 | static struct pm_ops omap_pm_ops ={ | ||
697 | .pm_disk_mode = 0, | ||
698 | .prepare = omap_pm_prepare, | ||
699 | .enter = omap_pm_enter, | ||
700 | .finish = omap_pm_finish, | ||
701 | }; | ||
702 | |||
703 | static int __init omap_pm_init(void) | ||
704 | { | ||
705 | printk("Power Management for TI OMAP.\n"); | ||
706 | |||
707 | /* | ||
708 | * We copy the assembler sleep/wakeup routines to SRAM. | ||
709 | * These routines need to be in SRAM as that's the only | ||
710 | * memory the MPU can see when it wakes up. | ||
711 | */ | ||
712 | if (cpu_is_omap730()) { | ||
713 | omap_sram_idle = omap_sram_push(omap730_idle_loop_suspend, | ||
714 | omap730_idle_loop_suspend_sz); | ||
715 | omap_sram_suspend = omap_sram_push(omap730_cpu_suspend, | ||
716 | omap730_cpu_suspend_sz); | ||
717 | } else if (cpu_is_omap15xx()) { | ||
718 | omap_sram_idle = omap_sram_push(omap1510_idle_loop_suspend, | ||
719 | omap1510_idle_loop_suspend_sz); | ||
720 | omap_sram_suspend = omap_sram_push(omap1510_cpu_suspend, | ||
721 | omap1510_cpu_suspend_sz); | ||
722 | } else if (cpu_is_omap16xx()) { | ||
723 | omap_sram_idle = omap_sram_push(omap1610_idle_loop_suspend, | ||
724 | omap1610_idle_loop_suspend_sz); | ||
725 | omap_sram_suspend = omap_sram_push(omap1610_cpu_suspend, | ||
726 | omap1610_cpu_suspend_sz); | ||
727 | } | ||
728 | |||
729 | if (omap_sram_idle == NULL || omap_sram_suspend == NULL) { | ||
730 | printk(KERN_ERR "PM not initialized: Missing SRAM support\n"); | ||
731 | return -ENODEV; | ||
732 | } | ||
733 | |||
734 | pm_idle = omap_pm_idle; | ||
735 | |||
736 | if (cpu_is_omap730()) | ||
737 | setup_irq(INT_730_WAKE_UP_REQ, &omap_wakeup_irq); | ||
738 | else if (cpu_is_omap16xx()) | ||
739 | setup_irq(INT_1610_WAKE_UP_REQ, &omap_wakeup_irq); | ||
740 | |||
741 | /* Program new power ramp-up time | ||
742 | * (0 for most boards since we don't lower voltage when in deep sleep) | ||
743 | */ | ||
744 | omap_writew(ULPD_SETUP_ANALOG_CELL_3_VAL, ULPD_SETUP_ANALOG_CELL_3); | ||
745 | |||
746 | /* Setup ULPD POWER_CTRL_REG - enter deep sleep whenever possible */ | ||
747 | omap_writew(ULPD_POWER_CTRL_REG_VAL, ULPD_POWER_CTRL); | ||
748 | |||
749 | /* Configure IDLECT3 */ | ||
750 | if (cpu_is_omap730()) | ||
751 | omap_writel(OMAP730_IDLECT3_VAL, OMAP730_IDLECT3); | ||
752 | else if (cpu_is_omap16xx()) | ||
753 | omap_writel(OMAP1610_IDLECT3_VAL, OMAP1610_IDLECT3); | ||
754 | |||
755 | pm_set_ops(&omap_pm_ops); | ||
756 | |||
757 | #if defined(DEBUG) && defined(CONFIG_PROC_FS) | ||
758 | omap_pm_init_proc(); | ||
759 | #endif | ||
760 | |||
761 | subsys_create_file(&power_subsys, &sleep_while_idle_attr); | ||
762 | |||
763 | if (cpu_is_omap16xx()) { | ||
764 | /* configure LOW_PWR pin */ | ||
765 | omap_cfg_reg(T20_1610_LOW_PWR); | ||
766 | } | ||
767 | |||
768 | return 0; | ||
769 | } | ||
770 | __initcall(omap_pm_init); | ||
diff --git a/arch/arm/mach-omap1/serial.c b/arch/arm/mach-omap1/serial.c index e924e0c6a4ce..9b4cd698bec8 100644 --- a/arch/arm/mach-omap1/serial.c +++ b/arch/arm/mach-omap1/serial.c | |||
@@ -30,9 +30,9 @@ | |||
30 | #include <asm/arch/pm.h> | 30 | #include <asm/arch/pm.h> |
31 | #endif | 31 | #endif |
32 | 32 | ||
33 | static struct clk * uart1_ck = NULL; | 33 | static struct clk * uart1_ck; |
34 | static struct clk * uart2_ck = NULL; | 34 | static struct clk * uart2_ck; |
35 | static struct clk * uart3_ck = NULL; | 35 | static struct clk * uart3_ck; |
36 | 36 | ||
37 | static inline unsigned int omap_serial_in(struct plat_serial8250_port *up, | 37 | static inline unsigned int omap_serial_in(struct plat_serial8250_port *up, |
38 | int offset) | 38 | int offset) |
diff --git a/arch/arm/plat-omap/sleep.S b/arch/arm/mach-omap1/sleep.S index 4cd7d292f854..e58295e2d3b2 100644 --- a/arch/arm/plat-omap/sleep.S +++ b/arch/arm/mach-omap1/sleep.S | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/arm/plat-omap/sleep.S | 2 | * linux/arch/arm/mach-omap1/sleep.S |
3 | * | 3 | * |
4 | * Low-level OMAP730/1510/1610 sleep/wakeUp support | 4 | * Low-level OMAP730/1510/1610 sleep/wakeUp support |
5 | * | 5 | * |
@@ -383,60 +383,133 @@ ENTRY(omap1610_cpu_suspend) | |||
383 | mcr p15, 0, r0, c7, c10, 4 | 383 | mcr p15, 0, r0, c7, c10, 4 |
384 | nop | 384 | nop |
385 | 385 | ||
386 | @ load base address of Traffic Controller | 386 | @ Load base address of Traffic Controller |
387 | mov r6, #TCMIF_ASM_BASE & 0xff000000 | 387 | mov r6, #TCMIF_ASM_BASE & 0xff000000 |
388 | orr r6, r6, #TCMIF_ASM_BASE & 0x00ff0000 | 388 | orr r6, r6, #TCMIF_ASM_BASE & 0x00ff0000 |
389 | orr r6, r6, #TCMIF_ASM_BASE & 0x0000ff00 | 389 | orr r6, r6, #TCMIF_ASM_BASE & 0x0000ff00 |
390 | 390 | ||
391 | @ prepare to put SDRAM into self-refresh manually | 391 | @ Prepare to put SDRAM into self-refresh manually |
392 | ldr r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] | 392 | ldr r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] |
393 | orr r9, r7, #SELF_REFRESH_MODE & 0xff000000 | 393 | orr r9, r7, #SELF_REFRESH_MODE & 0xff000000 |
394 | orr r9, r9, #SELF_REFRESH_MODE & 0x000000ff | 394 | orr r9, r9, #SELF_REFRESH_MODE & 0x000000ff |
395 | str r9, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] | 395 | str r9, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] |
396 | 396 | ||
397 | @ prepare to put EMIFS to Sleep | 397 | @ Prepare to put EMIFS to Sleep |
398 | ldr r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff] | 398 | ldr r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff] |
399 | orr r9, r8, #IDLE_EMIFS_REQUEST & 0xff | 399 | orr r9, r8, #IDLE_EMIFS_REQUEST & 0xff |
400 | str r9, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff] | 400 | str r9, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff] |
401 | 401 | ||
402 | @ load base address of ARM_IDLECT1 and ARM_IDLECT2 | 402 | @ Load base address of ARM_IDLECT1 and ARM_IDLECT2 |
403 | mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000 | 403 | mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000 |
404 | orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000 | 404 | orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000 |
405 | orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00 | 405 | orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00 |
406 | 406 | ||
407 | @ turn off clock domains | 407 | @ Turn off clock domains |
408 | @ do not disable PERCK (0x04) | 408 | @ Do not disable PERCK (0x04) |
409 | mov r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff | 409 | mov r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff |
410 | orr r5, r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff00 | 410 | orr r5, r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff00 |
411 | strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] | 411 | strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] |
412 | 412 | ||
413 | @ request ARM idle | 413 | @ Request ARM idle |
414 | mov r3, #OMAP1610_IDLECT1_SLEEP_VAL & 0xff | 414 | mov r3, #OMAP1610_IDLECT1_SLEEP_VAL & 0xff |
415 | orr r3, r3, #OMAP1610_IDLECT1_SLEEP_VAL & 0xff00 | 415 | orr r3, r3, #OMAP1610_IDLECT1_SLEEP_VAL & 0xff00 |
416 | strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] | 416 | strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] |
417 | 417 | ||
418 | @ disable instruction cache | ||
419 | mrc p15, 0, r9, c1, c0, 0 | ||
420 | bic r2, r9, #0x1000 | ||
421 | mcr p15, 0, r2, c1, c0, 0 | ||
422 | nop | ||
423 | |||
424 | /* | 418 | /* |
425 | * Let's wait for the next wake up event to wake us up. r0 can't be | 419 | * Let's wait for the next wake up event to wake us up. r0 can't be |
426 | * used here because r0 holds ARM_IDLECT1 | 420 | * used here because r0 holds ARM_IDLECT1 |
427 | */ | 421 | */ |
428 | mov r2, #0 | 422 | mov r2, #0 |
429 | mcr p15, 0, r2, c7, c0, 4 @ wait for interrupt | 423 | mcr p15, 0, r2, c7, c0, 4 @ wait for interrupt |
424 | |||
425 | @ Errata (HEL3SU467, section 1.4.4) specifies nop-instructions | ||
426 | @ according to this formula: | ||
427 | @ 2 + (4*DPLL_MULT)/DPLL_DIV/ARMDIV | ||
428 | @ Max DPLL_MULT = 18 | ||
429 | @ DPLL_DIV = 1 | ||
430 | @ ARMDIV = 1 | ||
431 | @ => 74 nop-instructions | ||
432 | nop | ||
433 | nop | ||
434 | nop | ||
435 | nop | ||
436 | nop | ||
437 | nop | ||
438 | nop | ||
439 | nop | ||
440 | nop | ||
441 | nop @10 | ||
442 | nop | ||
443 | nop | ||
444 | nop | ||
445 | nop | ||
446 | nop | ||
447 | nop | ||
448 | nop | ||
449 | nop | ||
450 | nop | ||
451 | nop @20 | ||
452 | nop | ||
453 | nop | ||
454 | nop | ||
455 | nop | ||
456 | nop | ||
457 | nop | ||
458 | nop | ||
459 | nop | ||
460 | nop | ||
461 | nop @30 | ||
462 | nop | ||
463 | nop | ||
464 | nop | ||
465 | nop | ||
466 | nop | ||
467 | nop | ||
468 | nop | ||
469 | nop | ||
470 | nop | ||
471 | nop @40 | ||
472 | nop | ||
473 | nop | ||
474 | nop | ||
475 | nop | ||
476 | nop | ||
477 | nop | ||
478 | nop | ||
479 | nop | ||
480 | nop | ||
481 | nop @50 | ||
482 | nop | ||
483 | nop | ||
484 | nop | ||
485 | nop | ||
486 | nop | ||
487 | nop | ||
488 | nop | ||
489 | nop | ||
490 | nop | ||
491 | nop @60 | ||
492 | nop | ||
493 | nop | ||
494 | nop | ||
495 | nop | ||
496 | nop | ||
497 | nop | ||
498 | nop | ||
499 | nop | ||
500 | nop | ||
501 | nop @70 | ||
502 | nop | ||
503 | nop | ||
504 | nop | ||
505 | nop @74 | ||
430 | /* | 506 | /* |
431 | * omap1610_cpu_suspend()'s resume point. | 507 | * omap1610_cpu_suspend()'s resume point. |
432 | * | 508 | * |
433 | * It will just start executing here, so we'll restore stuff from the | 509 | * It will just start executing here, so we'll restore stuff from the |
434 | * stack. | 510 | * stack. |
435 | */ | 511 | */ |
436 | @ re-enable Icache | 512 | @ Restore the ARM_IDLECT1 and ARM_IDLECT2. |
437 | mcr p15, 0, r9, c1, c0, 0 | ||
438 | |||
439 | @ reset the ARM_IDLECT1 and ARM_IDLECT2. | ||
440 | strh r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] | 513 | strh r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] |
441 | strh r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] | 514 | strh r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] |
442 | 515 | ||
@@ -444,7 +517,7 @@ ENTRY(omap1610_cpu_suspend) | |||
444 | str r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] | 517 | str r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] |
445 | str r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff] | 518 | str r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff] |
446 | 519 | ||
447 | @ restore regs and return | 520 | @ Restore regs and return |
448 | ldmfd sp!, {r0 - r12, pc} | 521 | ldmfd sp!, {r0 - r12, pc} |
449 | 522 | ||
450 | ENTRY(omap1610_cpu_suspend_sz) | 523 | ENTRY(omap1610_cpu_suspend_sz) |
diff --git a/arch/arm/mach-omap1/time.c b/arch/arm/mach-omap1/time.c index cdbf4d7620c6..a85fe6066bc4 100644 --- a/arch/arm/mach-omap1/time.c +++ b/arch/arm/mach-omap1/time.c | |||
@@ -51,8 +51,6 @@ | |||
51 | 51 | ||
52 | struct sys_timer omap_timer; | 52 | struct sys_timer omap_timer; |
53 | 53 | ||
54 | #ifdef CONFIG_OMAP_MPU_TIMER | ||
55 | |||
56 | /* | 54 | /* |
57 | * --------------------------------------------------------------------------- | 55 | * --------------------------------------------------------------------------- |
58 | * MPU timer | 56 | * MPU timer |
@@ -222,195 +220,6 @@ unsigned long long sched_clock(void) | |||
222 | 220 | ||
223 | return cycles_2_ns(ticks64); | 221 | return cycles_2_ns(ticks64); |
224 | } | 222 | } |
225 | #endif /* CONFIG_OMAP_MPU_TIMER */ | ||
226 | |||
227 | #ifdef CONFIG_OMAP_32K_TIMER | ||
228 | |||
229 | #ifdef CONFIG_ARCH_OMAP15XX | ||
230 | #error OMAP 32KHz timer does not currently work on 15XX! | ||
231 | #endif | ||
232 | |||
233 | /* | ||
234 | * --------------------------------------------------------------------------- | ||
235 | * 32KHz OS timer | ||
236 | * | ||
237 | * This currently works only on 16xx, as 1510 does not have the continuous | ||
238 | * 32KHz synchronous timer. The 32KHz synchronous timer is used to keep track | ||
239 | * of time in addition to the 32KHz OS timer. Using only the 32KHz OS timer | ||
240 | * on 1510 would be possible, but the timer would not be as accurate as | ||
241 | * with the 32KHz synchronized timer. | ||
242 | * --------------------------------------------------------------------------- | ||
243 | */ | ||
244 | #define OMAP_32K_TIMER_BASE 0xfffb9000 | ||
245 | #define OMAP_32K_TIMER_CR 0x08 | ||
246 | #define OMAP_32K_TIMER_TVR 0x00 | ||
247 | #define OMAP_32K_TIMER_TCR 0x04 | ||
248 | |||
249 | #define OMAP_32K_TICKS_PER_HZ (32768 / HZ) | ||
250 | |||
251 | /* | ||
252 | * TRM says 1 / HZ = ( TVR + 1) / 32768, so TRV = (32768 / HZ) - 1 | ||
253 | * so with HZ = 100, TVR = 327.68. | ||
254 | */ | ||
255 | #define OMAP_32K_TIMER_TICK_PERIOD ((32768 / HZ) - 1) | ||
256 | #define TIMER_32K_SYNCHRONIZED 0xfffbc410 | ||
257 | |||
258 | #define JIFFIES_TO_HW_TICKS(nr_jiffies, clock_rate) \ | ||
259 | (((nr_jiffies) * (clock_rate)) / HZ) | ||
260 | |||
261 | static inline void omap_32k_timer_write(int val, int reg) | ||
262 | { | ||
263 | omap_writew(val, reg + OMAP_32K_TIMER_BASE); | ||
264 | } | ||
265 | |||
266 | static inline unsigned long omap_32k_timer_read(int reg) | ||
267 | { | ||
268 | return omap_readl(reg + OMAP_32K_TIMER_BASE) & 0xffffff; | ||
269 | } | ||
270 | |||
271 | /* | ||
272 | * The 32KHz synchronized timer is an additional timer on 16xx. | ||
273 | * It is always running. | ||
274 | */ | ||
275 | static inline unsigned long omap_32k_sync_timer_read(void) | ||
276 | { | ||
277 | return omap_readl(TIMER_32K_SYNCHRONIZED); | ||
278 | } | ||
279 | |||
280 | static inline void omap_32k_timer_start(unsigned long load_val) | ||
281 | { | ||
282 | omap_32k_timer_write(load_val, OMAP_32K_TIMER_TVR); | ||
283 | omap_32k_timer_write(0x0f, OMAP_32K_TIMER_CR); | ||
284 | } | ||
285 | |||
286 | static inline void omap_32k_timer_stop(void) | ||
287 | { | ||
288 | omap_32k_timer_write(0x0, OMAP_32K_TIMER_CR); | ||
289 | } | ||
290 | |||
291 | /* | ||
292 | * Rounds down to nearest usec. Note that this will overflow for larger values. | ||
293 | */ | ||
294 | static inline unsigned long omap_32k_ticks_to_usecs(unsigned long ticks_32k) | ||
295 | { | ||
296 | return (ticks_32k * 5*5*5*5*5*5) >> 9; | ||
297 | } | ||
298 | |||
299 | /* | ||
300 | * Rounds down to nearest nsec. | ||
301 | */ | ||
302 | static inline unsigned long long | ||
303 | omap_32k_ticks_to_nsecs(unsigned long ticks_32k) | ||
304 | { | ||
305 | return (unsigned long long) ticks_32k * 1000 * 5*5*5*5*5*5 >> 9; | ||
306 | } | ||
307 | |||
308 | static unsigned long omap_32k_last_tick = 0; | ||
309 | |||
310 | /* | ||
311 | * Returns elapsed usecs since last 32k timer interrupt | ||
312 | */ | ||
313 | static unsigned long omap_32k_timer_gettimeoffset(void) | ||
314 | { | ||
315 | unsigned long now = omap_32k_sync_timer_read(); | ||
316 | return omap_32k_ticks_to_usecs(now - omap_32k_last_tick); | ||
317 | } | ||
318 | |||
319 | /* | ||
320 | * Returns current time from boot in nsecs. It's OK for this to wrap | ||
321 | * around for now, as it's just a relative time stamp. | ||
322 | */ | ||
323 | unsigned long long sched_clock(void) | ||
324 | { | ||
325 | return omap_32k_ticks_to_nsecs(omap_32k_sync_timer_read()); | ||
326 | } | ||
327 | |||
328 | /* | ||
329 | * Timer interrupt for 32KHz timer. When dynamic tick is enabled, this | ||
330 | * function is also called from other interrupts to remove latency | ||
331 | * issues with dynamic tick. In the dynamic tick case, we need to lock | ||
332 | * with irqsave. | ||
333 | */ | ||
334 | static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id, | ||
335 | struct pt_regs *regs) | ||
336 | { | ||
337 | unsigned long flags; | ||
338 | unsigned long now; | ||
339 | |||
340 | write_seqlock_irqsave(&xtime_lock, flags); | ||
341 | now = omap_32k_sync_timer_read(); | ||
342 | |||
343 | while (now - omap_32k_last_tick >= OMAP_32K_TICKS_PER_HZ) { | ||
344 | omap_32k_last_tick += OMAP_32K_TICKS_PER_HZ; | ||
345 | timer_tick(regs); | ||
346 | } | ||
347 | |||
348 | /* Restart timer so we don't drift off due to modulo or dynamic tick. | ||
349 | * By default we program the next timer to be continuous to avoid | ||
350 | * latencies during high system load. During dynamic tick operation the | ||
351 | * continuous timer can be overridden from pm_idle to be longer. | ||
352 | */ | ||
353 | omap_32k_timer_start(omap_32k_last_tick + OMAP_32K_TICKS_PER_HZ - now); | ||
354 | write_sequnlock_irqrestore(&xtime_lock, flags); | ||
355 | |||
356 | return IRQ_HANDLED; | ||
357 | } | ||
358 | |||
359 | #ifdef CONFIG_NO_IDLE_HZ | ||
360 | /* | ||
361 | * Programs the next timer interrupt needed. Called when dynamic tick is | ||
362 | * enabled, and to reprogram the ticks to skip from pm_idle. Note that | ||
363 | * we can keep the timer continuous, and don't need to set it to run in | ||
364 | * one-shot mode. This is because the timer will get reprogrammed again | ||
365 | * after next interrupt. | ||
366 | */ | ||
367 | void omap_32k_timer_reprogram(unsigned long next_tick) | ||
368 | { | ||
369 | omap_32k_timer_start(JIFFIES_TO_HW_TICKS(next_tick, 32768) + 1); | ||
370 | } | ||
371 | |||
372 | static struct irqaction omap_32k_timer_irq; | ||
373 | extern struct timer_update_handler timer_update; | ||
374 | |||
375 | static int omap_32k_timer_enable_dyn_tick(void) | ||
376 | { | ||
377 | /* No need to reprogram timer, just use the next interrupt */ | ||
378 | return 0; | ||
379 | } | ||
380 | |||
381 | static int omap_32k_timer_disable_dyn_tick(void) | ||
382 | { | ||
383 | omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD); | ||
384 | return 0; | ||
385 | } | ||
386 | |||
387 | static struct dyn_tick_timer omap_dyn_tick_timer = { | ||
388 | .enable = omap_32k_timer_enable_dyn_tick, | ||
389 | .disable = omap_32k_timer_disable_dyn_tick, | ||
390 | .reprogram = omap_32k_timer_reprogram, | ||
391 | .handler = omap_32k_timer_interrupt, | ||
392 | }; | ||
393 | #endif /* CONFIG_NO_IDLE_HZ */ | ||
394 | |||
395 | static struct irqaction omap_32k_timer_irq = { | ||
396 | .name = "32KHz timer", | ||
397 | .flags = SA_INTERRUPT | SA_TIMER, | ||
398 | .handler = omap_32k_timer_interrupt, | ||
399 | }; | ||
400 | |||
401 | static __init void omap_init_32k_timer(void) | ||
402 | { | ||
403 | |||
404 | #ifdef CONFIG_NO_IDLE_HZ | ||
405 | omap_timer.dyn_tick = &omap_dyn_tick_timer; | ||
406 | #endif | ||
407 | |||
408 | setup_irq(INT_OS_TIMER, &omap_32k_timer_irq); | ||
409 | omap_timer.offset = omap_32k_timer_gettimeoffset; | ||
410 | omap_32k_last_tick = omap_32k_sync_timer_read(); | ||
411 | omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD); | ||
412 | } | ||
413 | #endif /* CONFIG_OMAP_32K_TIMER */ | ||
414 | 223 | ||
415 | /* | 224 | /* |
416 | * --------------------------------------------------------------------------- | 225 | * --------------------------------------------------------------------------- |
@@ -419,13 +228,7 @@ static __init void omap_init_32k_timer(void) | |||
419 | */ | 228 | */ |
420 | static void __init omap_timer_init(void) | 229 | static void __init omap_timer_init(void) |
421 | { | 230 | { |
422 | #if defined(CONFIG_OMAP_MPU_TIMER) | ||
423 | omap_init_mpu_timer(); | 231 | omap_init_mpu_timer(); |
424 | #elif defined(CONFIG_OMAP_32K_TIMER) | ||
425 | omap_init_32k_timer(); | ||
426 | #else | ||
427 | #error No system timer selected in Kconfig! | ||
428 | #endif | ||
429 | } | 232 | } |
430 | 233 | ||
431 | struct sys_timer omap_timer = { | 234 | struct sys_timer omap_timer = { |
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index 578880943cf2..537dd2e6d380 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig | |||
@@ -20,3 +20,6 @@ config MACH_OMAP_H4 | |||
20 | bool "OMAP 2420 H4 board" | 20 | bool "OMAP 2420 H4 board" |
21 | depends on ARCH_OMAP2 && ARCH_OMAP24XX | 21 | depends on ARCH_OMAP2 && ARCH_OMAP24XX |
22 | 22 | ||
23 | config MACH_OMAP_APOLLON | ||
24 | bool "OMAP 2420 Apollon board" | ||
25 | depends on ARCH_OMAP2 && ARCH_OMAP24XX | ||
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 42041166435c..111eaa64258f 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile | |||
@@ -3,11 +3,15 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | # Common support | 5 | # Common support |
6 | obj-y := irq.o id.o io.o sram-fn.o clock.o mux.o devices.o serial.o | 6 | obj-y := irq.o id.o io.o sram-fn.o memory.o prcm.o clock.o mux.o devices.o serial.o |
7 | 7 | ||
8 | obj-$(CONFIG_OMAP_MPU_TIMER) += timer-gp.o | 8 | obj-$(CONFIG_OMAP_MPU_TIMER) += timer-gp.o |
9 | 9 | ||
10 | # Power Management | ||
11 | obj-$(CONFIG_PM) += pm.o sleep.o | ||
12 | |||
10 | # Specific board support | 13 | # Specific board support |
11 | obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o | 14 | obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o |
12 | obj-$(CONFIG_MACH_OMAP_H4) += board-h4.o | 15 | obj-$(CONFIG_MACH_OMAP_H4) += board-h4.o |
16 | obj-$(CONFIG_MACH_OMAP_APOLLON) += board-apollon.o | ||
13 | 17 | ||
diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c new file mode 100644 index 000000000000..6c6ba172cdf6 --- /dev/null +++ b/arch/arm/mach-omap2/board-apollon.c | |||
@@ -0,0 +1,285 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-omap/omap2/board-apollon.c | ||
3 | * | ||
4 | * Copyright (C) 2005,2006 Samsung Electronics | ||
5 | * Author: Kyungmin Park <kyungmin.park@samsung.com> | ||
6 | * | ||
7 | * Modified from mach-omap/omap2/board-h4.c | ||
8 | * | ||
9 | * Code for apollon OMAP2 board. Should work on many OMAP2 systems where | ||
10 | * the bootloader passes the board-specific data to the kernel. | ||
11 | * Do not put any board specific code to this file; create a new machine | ||
12 | * type if you need custom low-level initializations. | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify | ||
15 | * it under the terms of the GNU General Public License version 2 as | ||
16 | * published by the Free Software Foundation. | ||
17 | */ | ||
18 | |||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | #include <linux/mtd/mtd.h> | ||
23 | #include <linux/mtd/partitions.h> | ||
24 | #include <linux/mtd/onenand.h> | ||
25 | #include <linux/interrupt.h> | ||
26 | #include <linux/delay.h> | ||
27 | |||
28 | #include <asm/hardware.h> | ||
29 | #include <asm/mach-types.h> | ||
30 | #include <asm/mach/arch.h> | ||
31 | #include <asm/mach/flash.h> | ||
32 | |||
33 | #include <asm/arch/gpio.h> | ||
34 | #include <asm/arch/mux.h> | ||
35 | #include <asm/arch/usb.h> | ||
36 | #include <asm/arch/board.h> | ||
37 | #include <asm/arch/common.h> | ||
38 | #include "prcm-regs.h" | ||
39 | |||
40 | /* LED & Switch macros */ | ||
41 | #define LED0_GPIO13 13 | ||
42 | #define LED1_GPIO14 14 | ||
43 | #define LED2_GPIO15 15 | ||
44 | #define SW_ENTER_GPIO16 16 | ||
45 | #define SW_UP_GPIO17 17 | ||
46 | #define SW_DOWN_GPIO58 58 | ||
47 | |||
48 | static struct mtd_partition apollon_partitions[] = { | ||
49 | { | ||
50 | .name = "X-Loader + U-Boot", | ||
51 | .offset = 0, | ||
52 | .size = SZ_128K, | ||
53 | .mask_flags = MTD_WRITEABLE, | ||
54 | }, | ||
55 | { | ||
56 | .name = "params", | ||
57 | .offset = MTDPART_OFS_APPEND, | ||
58 | .size = SZ_128K, | ||
59 | }, | ||
60 | { | ||
61 | .name = "kernel", | ||
62 | .offset = MTDPART_OFS_APPEND, | ||
63 | .size = SZ_2M, | ||
64 | }, | ||
65 | { | ||
66 | .name = "rootfs", | ||
67 | .offset = MTDPART_OFS_APPEND, | ||
68 | .size = SZ_16M, | ||
69 | }, | ||
70 | { | ||
71 | .name = "filesystem00", | ||
72 | .offset = MTDPART_OFS_APPEND, | ||
73 | .size = SZ_32M, | ||
74 | }, | ||
75 | { | ||
76 | .name = "filesystem01", | ||
77 | .offset = MTDPART_OFS_APPEND, | ||
78 | .size = MTDPART_SIZ_FULL, | ||
79 | }, | ||
80 | }; | ||
81 | |||
82 | static struct flash_platform_data apollon_flash_data = { | ||
83 | .parts = apollon_partitions, | ||
84 | .nr_parts = ARRAY_SIZE(apollon_partitions), | ||
85 | }; | ||
86 | |||
87 | static struct resource apollon_flash_resource = { | ||
88 | .start = APOLLON_CS0_BASE, | ||
89 | .end = APOLLON_CS0_BASE + SZ_128K, | ||
90 | .flags = IORESOURCE_MEM, | ||
91 | }; | ||
92 | |||
93 | static struct platform_device apollon_onenand_device = { | ||
94 | .name = "onenand", | ||
95 | .id = -1, | ||
96 | .dev = { | ||
97 | .platform_data = &apollon_flash_data, | ||
98 | }, | ||
99 | .num_resources = ARRAY_SIZE(&apollon_flash_resource), | ||
100 | .resource = &apollon_flash_resource, | ||
101 | }; | ||
102 | |||
103 | static struct resource apollon_smc91x_resources[] = { | ||
104 | [0] = { | ||
105 | .start = APOLLON_ETHR_START, /* Physical */ | ||
106 | .end = APOLLON_ETHR_START + 0xf, | ||
107 | .flags = IORESOURCE_MEM, | ||
108 | }, | ||
109 | [1] = { | ||
110 | .start = OMAP_GPIO_IRQ(APOLLON_ETHR_GPIO_IRQ), | ||
111 | .end = OMAP_GPIO_IRQ(APOLLON_ETHR_GPIO_IRQ), | ||
112 | .flags = IORESOURCE_IRQ, | ||
113 | }, | ||
114 | }; | ||
115 | |||
116 | static struct platform_device apollon_smc91x_device = { | ||
117 | .name = "smc91x", | ||
118 | .id = -1, | ||
119 | .num_resources = ARRAY_SIZE(apollon_smc91x_resources), | ||
120 | .resource = apollon_smc91x_resources, | ||
121 | }; | ||
122 | |||
123 | static struct platform_device apollon_lcd_device = { | ||
124 | .name = "apollon_lcd", | ||
125 | .id = -1, | ||
126 | }; | ||
127 | |||
128 | static struct platform_device *apollon_devices[] __initdata = { | ||
129 | &apollon_onenand_device, | ||
130 | &apollon_smc91x_device, | ||
131 | &apollon_lcd_device, | ||
132 | }; | ||
133 | |||
134 | static inline void __init apollon_init_smc91x(void) | ||
135 | { | ||
136 | /* Make sure CS1 timings are correct */ | ||
137 | GPMC_CONFIG1_1 = 0x00011203; | ||
138 | GPMC_CONFIG2_1 = 0x001f1f01; | ||
139 | GPMC_CONFIG3_1 = 0x00080803; | ||
140 | GPMC_CONFIG4_1 = 0x1c091c09; | ||
141 | GPMC_CONFIG5_1 = 0x041f1f1f; | ||
142 | GPMC_CONFIG6_1 = 0x000004c4; | ||
143 | GPMC_CONFIG7_1 = 0x00000f40 | (APOLLON_CS1_BASE >> 24); | ||
144 | udelay(100); | ||
145 | |||
146 | omap_cfg_reg(W4__24XX_GPIO74); | ||
147 | if (omap_request_gpio(APOLLON_ETHR_GPIO_IRQ) < 0) { | ||
148 | printk(KERN_ERR "Failed to request GPIO%d for smc91x IRQ\n", | ||
149 | APOLLON_ETHR_GPIO_IRQ); | ||
150 | return; | ||
151 | } | ||
152 | omap_set_gpio_direction(APOLLON_ETHR_GPIO_IRQ, 1); | ||
153 | } | ||
154 | |||
155 | static void __init omap_apollon_init_irq(void) | ||
156 | { | ||
157 | omap2_init_common_hw(); | ||
158 | omap_init_irq(); | ||
159 | omap_gpio_init(); | ||
160 | apollon_init_smc91x(); | ||
161 | } | ||
162 | |||
163 | static struct omap_uart_config apollon_uart_config __initdata = { | ||
164 | .enabled_uarts = (1 << 0) | (0 << 1) | (0 << 2), | ||
165 | }; | ||
166 | |||
167 | static struct omap_mmc_config apollon_mmc_config __initdata = { | ||
168 | .mmc [0] = { | ||
169 | .enabled = 0, | ||
170 | .wire4 = 0, | ||
171 | .wp_pin = -1, | ||
172 | .power_pin = -1, | ||
173 | .switch_pin = -1, | ||
174 | }, | ||
175 | }; | ||
176 | |||
177 | static struct omap_lcd_config apollon_lcd_config __initdata = { | ||
178 | .ctrl_name = "internal", | ||
179 | }; | ||
180 | |||
181 | static struct omap_board_config_kernel apollon_config[] = { | ||
182 | { OMAP_TAG_UART, &apollon_uart_config }, | ||
183 | { OMAP_TAG_MMC, &apollon_mmc_config }, | ||
184 | { OMAP_TAG_LCD, &apollon_lcd_config }, | ||
185 | }; | ||
186 | |||
187 | static void __init apollon_led_init(void) | ||
188 | { | ||
189 | /* LED0 - AA10 */ | ||
190 | omap_cfg_reg(AA10_242X_GPIO13); | ||
191 | omap_request_gpio(LED0_GPIO13); | ||
192 | omap_set_gpio_direction(LED0_GPIO13, 0); | ||
193 | omap_set_gpio_dataout(LED0_GPIO13, 0); | ||
194 | /* LED1 - AA6 */ | ||
195 | omap_cfg_reg(AA6_242X_GPIO14); | ||
196 | omap_request_gpio(LED1_GPIO14); | ||
197 | omap_set_gpio_direction(LED1_GPIO14, 0); | ||
198 | omap_set_gpio_dataout(LED1_GPIO14, 0); | ||
199 | /* LED2 - AA4 */ | ||
200 | omap_cfg_reg(AA4_242X_GPIO15); | ||
201 | omap_request_gpio(LED2_GPIO15); | ||
202 | omap_set_gpio_direction(LED2_GPIO15, 0); | ||
203 | omap_set_gpio_dataout(LED2_GPIO15, 0); | ||
204 | } | ||
205 | |||
206 | static irqreturn_t apollon_sw_interrupt(int irq, void *ignored, struct pt_regs *regs) | ||
207 | { | ||
208 | static unsigned int led0, led1, led2; | ||
209 | |||
210 | if (irq == OMAP_GPIO_IRQ(SW_ENTER_GPIO16)) | ||
211 | omap_set_gpio_dataout(LED0_GPIO13, led0 ^= 1); | ||
212 | else if (irq == OMAP_GPIO_IRQ(SW_UP_GPIO17)) | ||
213 | omap_set_gpio_dataout(LED1_GPIO14, led1 ^= 1); | ||
214 | else if (irq == OMAP_GPIO_IRQ(SW_DOWN_GPIO58)) | ||
215 | omap_set_gpio_dataout(LED2_GPIO15, led2 ^= 1); | ||
216 | |||
217 | return IRQ_HANDLED; | ||
218 | } | ||
219 | |||
220 | static void __init apollon_sw_init(void) | ||
221 | { | ||
222 | /* Enter SW - Y11 */ | ||
223 | omap_cfg_reg(Y11_242X_GPIO16); | ||
224 | omap_request_gpio(SW_ENTER_GPIO16); | ||
225 | omap_set_gpio_direction(SW_ENTER_GPIO16, 1); | ||
226 | /* Up SW - AA12 */ | ||
227 | omap_cfg_reg(AA12_242X_GPIO17); | ||
228 | omap_request_gpio(SW_UP_GPIO17); | ||
229 | omap_set_gpio_direction(SW_UP_GPIO17, 1); | ||
230 | /* Down SW - AA8 */ | ||
231 | omap_cfg_reg(AA8_242X_GPIO58); | ||
232 | omap_request_gpio(SW_DOWN_GPIO58); | ||
233 | omap_set_gpio_direction(SW_DOWN_GPIO58, 1); | ||
234 | |||
235 | set_irq_type(OMAP_GPIO_IRQ(SW_ENTER_GPIO16), IRQT_RISING); | ||
236 | if (request_irq(OMAP_GPIO_IRQ(SW_ENTER_GPIO16), &apollon_sw_interrupt, | ||
237 | SA_SHIRQ, "enter sw", | ||
238 | &apollon_sw_interrupt)) | ||
239 | return; | ||
240 | set_irq_type(OMAP_GPIO_IRQ(SW_UP_GPIO17), IRQT_RISING); | ||
241 | if (request_irq(OMAP_GPIO_IRQ(SW_UP_GPIO17), &apollon_sw_interrupt, | ||
242 | SA_SHIRQ, "up sw", | ||
243 | &apollon_sw_interrupt)) | ||
244 | return; | ||
245 | set_irq_type(OMAP_GPIO_IRQ(SW_DOWN_GPIO58), IRQT_RISING); | ||
246 | if (request_irq(OMAP_GPIO_IRQ(SW_DOWN_GPIO58), &apollon_sw_interrupt, | ||
247 | SA_SHIRQ, "down sw", | ||
248 | &apollon_sw_interrupt)) | ||
249 | return; | ||
250 | } | ||
251 | |||
252 | static void __init omap_apollon_init(void) | ||
253 | { | ||
254 | apollon_led_init(); | ||
255 | apollon_sw_init(); | ||
256 | |||
257 | /* REVISIT: where's the correct place */ | ||
258 | omap_cfg_reg(W19_24XX_SYS_NIRQ); | ||
259 | |||
260 | /* | ||
261 | * Make sure the serial ports are muxed on at this point. | ||
262 | * You have to mux them off in device drivers later on | ||
263 | * if not needed. | ||
264 | */ | ||
265 | platform_add_devices(apollon_devices, ARRAY_SIZE(apollon_devices)); | ||
266 | omap_board_config = apollon_config; | ||
267 | omap_board_config_size = ARRAY_SIZE(apollon_config); | ||
268 | omap_serial_init(); | ||
269 | } | ||
270 | |||
271 | static void __init omap_apollon_map_io(void) | ||
272 | { | ||
273 | omap2_map_common_io(); | ||
274 | } | ||
275 | |||
276 | MACHINE_START(OMAP_APOLLON, "OMAP24xx Apollon") | ||
277 | /* Maintainer: Kyungmin Park <kyungmin.park@samsung.com> */ | ||
278 | .phys_io = 0x48000000, | ||
279 | .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc, | ||
280 | .boot_params = 0x80000100, | ||
281 | .map_io = omap_apollon_map_io, | ||
282 | .init_irq = omap_apollon_init_irq, | ||
283 | .init_machine = omap_apollon_init, | ||
284 | .timer = &omap_timer, | ||
285 | MACHINE_END | ||
diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c index a300d634d8a5..4933fce766c8 100644 --- a/arch/arm/mach-omap2/board-h4.c +++ b/arch/arm/mach-omap2/board-h4.c | |||
@@ -17,6 +17,8 @@ | |||
17 | #include <linux/mtd/mtd.h> | 17 | #include <linux/mtd/mtd.h> |
18 | #include <linux/mtd/partitions.h> | 18 | #include <linux/mtd/partitions.h> |
19 | #include <linux/delay.h> | 19 | #include <linux/delay.h> |
20 | #include <linux/workqueue.h> | ||
21 | #include <linux/input.h> | ||
20 | 22 | ||
21 | #include <asm/hardware.h> | 23 | #include <asm/hardware.h> |
22 | #include <asm/mach-types.h> | 24 | #include <asm/mach-types.h> |
@@ -25,15 +27,57 @@ | |||
25 | #include <asm/mach/flash.h> | 27 | #include <asm/mach/flash.h> |
26 | 28 | ||
27 | #include <asm/arch/gpio.h> | 29 | #include <asm/arch/gpio.h> |
30 | #include <asm/arch/gpioexpander.h> | ||
28 | #include <asm/arch/mux.h> | 31 | #include <asm/arch/mux.h> |
29 | #include <asm/arch/usb.h> | 32 | #include <asm/arch/usb.h> |
33 | #include <asm/arch/irda.h> | ||
30 | #include <asm/arch/board.h> | 34 | #include <asm/arch/board.h> |
31 | #include <asm/arch/common.h> | 35 | #include <asm/arch/common.h> |
32 | #include <asm/arch/prcm.h> | 36 | #include <asm/arch/keypad.h> |
37 | #include <asm/arch/menelaus.h> | ||
38 | #include <asm/arch/dma.h> | ||
39 | #include "prcm-regs.h" | ||
33 | 40 | ||
34 | #include <asm/io.h> | 41 | #include <asm/io.h> |
35 | #include <asm/delay.h> | 42 | #include <asm/delay.h> |
36 | 43 | ||
44 | static unsigned int row_gpios[6] = { 88, 89, 124, 11, 6, 96 }; | ||
45 | static unsigned int col_gpios[7] = { 90, 91, 100, 36, 12, 97, 98 }; | ||
46 | |||
47 | static int h4_keymap[] = { | ||
48 | KEY(0, 0, KEY_LEFT), | ||
49 | KEY(0, 1, KEY_RIGHT), | ||
50 | KEY(0, 2, KEY_A), | ||
51 | KEY(0, 3, KEY_B), | ||
52 | KEY(0, 4, KEY_C), | ||
53 | KEY(1, 0, KEY_DOWN), | ||
54 | KEY(1, 1, KEY_UP), | ||
55 | KEY(1, 2, KEY_E), | ||
56 | KEY(1, 3, KEY_F), | ||
57 | KEY(1, 4, KEY_G), | ||
58 | KEY(2, 0, KEY_ENTER), | ||
59 | KEY(2, 1, KEY_I), | ||
60 | KEY(2, 2, KEY_J), | ||
61 | KEY(2, 3, KEY_K), | ||
62 | KEY(2, 4, KEY_3), | ||
63 | KEY(3, 0, KEY_M), | ||
64 | KEY(3, 1, KEY_N), | ||
65 | KEY(3, 2, KEY_O), | ||
66 | KEY(3, 3, KEY_P), | ||
67 | KEY(3, 4, KEY_Q), | ||
68 | KEY(4, 0, KEY_R), | ||
69 | KEY(4, 1, KEY_4), | ||
70 | KEY(4, 2, KEY_T), | ||
71 | KEY(4, 3, KEY_U), | ||
72 | KEY(4, 4, KEY_ENTER), | ||
73 | KEY(5, 0, KEY_V), | ||
74 | KEY(5, 1, KEY_W), | ||
75 | KEY(5, 2, KEY_L), | ||
76 | KEY(5, 3, KEY_S), | ||
77 | KEY(5, 4, KEY_ENTER), | ||
78 | 0 | ||
79 | }; | ||
80 | |||
37 | static struct mtd_partition h4_partitions[] = { | 81 | static struct mtd_partition h4_partitions[] = { |
38 | /* bootloader (U-Boot, etc) in first sector */ | 82 | /* bootloader (U-Boot, etc) in first sector */ |
39 | { | 83 | { |
@@ -108,9 +152,123 @@ static struct platform_device h4_smc91x_device = { | |||
108 | .resource = h4_smc91x_resources, | 152 | .resource = h4_smc91x_resources, |
109 | }; | 153 | }; |
110 | 154 | ||
155 | /* Select between the IrDA and aGPS module | ||
156 | */ | ||
157 | static int h4_select_irda(struct device *dev, int state) | ||
158 | { | ||
159 | unsigned char expa; | ||
160 | int err = 0; | ||
161 | |||
162 | if ((err = read_gpio_expa(&expa, 0x21))) { | ||
163 | printk(KERN_ERR "Error reading from I/O expander\n"); | ||
164 | return err; | ||
165 | } | ||
166 | |||
167 | /* 'P6' enable/disable IRDA_TX and IRDA_RX */ | ||
168 | if (state & IR_SEL) { /* IrDa */ | ||
169 | if ((err = write_gpio_expa(expa | 0x01, 0x21))) { | ||
170 | printk(KERN_ERR "Error writing to I/O expander\n"); | ||
171 | return err; | ||
172 | } | ||
173 | } else { | ||
174 | if ((err = write_gpio_expa(expa & ~0x01, 0x21))) { | ||
175 | printk(KERN_ERR "Error writing to I/O expander\n"); | ||
176 | return err; | ||
177 | } | ||
178 | } | ||
179 | return err; | ||
180 | } | ||
181 | |||
182 | static void set_trans_mode(void *data) | ||
183 | { | ||
184 | int *mode = data; | ||
185 | unsigned char expa; | ||
186 | int err = 0; | ||
187 | |||
188 | if ((err = read_gpio_expa(&expa, 0x20)) != 0) { | ||
189 | printk(KERN_ERR "Error reading from I/O expander\n"); | ||
190 | } | ||
191 | |||
192 | expa &= ~0x01; | ||
193 | |||
194 | if (!(*mode & IR_SIRMODE)) { /* MIR/FIR */ | ||
195 | expa |= 0x01; | ||
196 | } | ||
197 | |||
198 | if ((err = write_gpio_expa(expa, 0x20)) != 0) { | ||
199 | printk(KERN_ERR "Error writing to I/O expander\n"); | ||
200 | } | ||
201 | } | ||
202 | |||
203 | static int h4_transceiver_mode(struct device *dev, int mode) | ||
204 | { | ||
205 | struct omap_irda_config *irda_config = dev->platform_data; | ||
206 | |||
207 | cancel_delayed_work(&irda_config->gpio_expa); | ||
208 | PREPARE_WORK(&irda_config->gpio_expa, set_trans_mode, &mode); | ||
209 | schedule_work(&irda_config->gpio_expa); | ||
210 | |||
211 | return 0; | ||
212 | } | ||
213 | |||
214 | static struct omap_irda_config h4_irda_data = { | ||
215 | .transceiver_cap = IR_SIRMODE | IR_MIRMODE | IR_FIRMODE, | ||
216 | .transceiver_mode = h4_transceiver_mode, | ||
217 | .select_irda = h4_select_irda, | ||
218 | .rx_channel = OMAP24XX_DMA_UART3_RX, | ||
219 | .tx_channel = OMAP24XX_DMA_UART3_TX, | ||
220 | .dest_start = OMAP_UART3_BASE, | ||
221 | .src_start = OMAP_UART3_BASE, | ||
222 | .tx_trigger = OMAP24XX_DMA_UART3_TX, | ||
223 | .rx_trigger = OMAP24XX_DMA_UART3_RX, | ||
224 | }; | ||
225 | |||
226 | static struct resource h4_irda_resources[] = { | ||
227 | [0] = { | ||
228 | .start = INT_24XX_UART3_IRQ, | ||
229 | .end = INT_24XX_UART3_IRQ, | ||
230 | .flags = IORESOURCE_IRQ, | ||
231 | }, | ||
232 | }; | ||
233 | |||
234 | static struct platform_device h4_irda_device = { | ||
235 | .name = "omapirda", | ||
236 | .id = -1, | ||
237 | .dev = { | ||
238 | .platform_data = &h4_irda_data, | ||
239 | }, | ||
240 | .num_resources = 1, | ||
241 | .resource = h4_irda_resources, | ||
242 | }; | ||
243 | |||
244 | static struct omap_kp_platform_data h4_kp_data = { | ||
245 | .rows = 6, | ||
246 | .cols = 7, | ||
247 | .keymap = h4_keymap, | ||
248 | .rep = 1, | ||
249 | .row_gpios = row_gpios, | ||
250 | .col_gpios = col_gpios, | ||
251 | }; | ||
252 | |||
253 | static struct platform_device h4_kp_device = { | ||
254 | .name = "omap-keypad", | ||
255 | .id = -1, | ||
256 | .dev = { | ||
257 | .platform_data = &h4_kp_data, | ||
258 | }, | ||
259 | }; | ||
260 | |||
261 | static struct platform_device h4_lcd_device = { | ||
262 | .name = "lcd_h4", | ||
263 | .id = -1, | ||
264 | }; | ||
265 | |||
111 | static struct platform_device *h4_devices[] __initdata = { | 266 | static struct platform_device *h4_devices[] __initdata = { |
112 | &h4_smc91x_device, | 267 | &h4_smc91x_device, |
113 | &h4_flash_device, | 268 | &h4_flash_device, |
269 | &h4_irda_device, | ||
270 | &h4_kp_device, | ||
271 | &h4_lcd_device, | ||
114 | }; | 272 | }; |
115 | 273 | ||
116 | static inline void __init h4_init_smc91x(void) | 274 | static inline void __init h4_init_smc91x(void) |
@@ -157,7 +315,6 @@ static struct omap_mmc_config h4_mmc_config __initdata = { | |||
157 | }; | 315 | }; |
158 | 316 | ||
159 | static struct omap_lcd_config h4_lcd_config __initdata = { | 317 | static struct omap_lcd_config h4_lcd_config __initdata = { |
160 | .panel_name = "h4", | ||
161 | .ctrl_name = "internal", | 318 | .ctrl_name = "internal", |
162 | }; | 319 | }; |
163 | 320 | ||
@@ -174,6 +331,19 @@ static void __init omap_h4_init(void) | |||
174 | * You have to mux them off in device drivers later on | 331 | * You have to mux them off in device drivers later on |
175 | * if not needed. | 332 | * if not needed. |
176 | */ | 333 | */ |
334 | #if defined(CONFIG_OMAP_IR) || defined(CONFIG_OMAP_IR_MODULE) | ||
335 | omap_cfg_reg(K15_24XX_UART3_TX); | ||
336 | omap_cfg_reg(K14_24XX_UART3_RX); | ||
337 | #endif | ||
338 | |||
339 | #if defined(CONFIG_KEYBOARD_OMAP) || defined(CONFIG_KEYBOARD_OMAP_MODULE) | ||
340 | if (omap_has_menelaus()) { | ||
341 | row_gpios[5] = 0; | ||
342 | col_gpios[2] = 15; | ||
343 | col_gpios[6] = 18; | ||
344 | } | ||
345 | #endif | ||
346 | |||
177 | platform_add_devices(h4_devices, ARRAY_SIZE(h4_devices)); | 347 | platform_add_devices(h4_devices, ARRAY_SIZE(h4_devices)); |
178 | omap_board_config = h4_config; | 348 | omap_board_config = h4_config; |
179 | omap_board_config_size = ARRAY_SIZE(h4_config); | 349 | omap_board_config_size = ARRAY_SIZE(h4_config); |
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index 180f675c9064..72eb4bf571ac 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c | |||
@@ -28,14 +28,14 @@ | |||
28 | 28 | ||
29 | #include <asm/arch/clock.h> | 29 | #include <asm/arch/clock.h> |
30 | #include <asm/arch/sram.h> | 30 | #include <asm/arch/sram.h> |
31 | #include <asm/arch/prcm.h> | ||
32 | 31 | ||
32 | #include "prcm-regs.h" | ||
33 | #include "memory.h" | ||
33 | #include "clock.h" | 34 | #include "clock.h" |
34 | 35 | ||
35 | //#define DOWN_VARIABLE_DPLL 1 /* Experimental */ | 36 | //#define DOWN_VARIABLE_DPLL 1 /* Experimental */ |
36 | 37 | ||
37 | static struct prcm_config *curr_prcm_set; | 38 | static struct prcm_config *curr_prcm_set; |
38 | static struct memory_timings mem_timings; | ||
39 | static u32 curr_perf_level = PRCM_FULL_SPEED; | 39 | static u32 curr_perf_level = PRCM_FULL_SPEED; |
40 | 40 | ||
41 | /*------------------------------------------------------------------------- | 41 | /*------------------------------------------------------------------------- |
@@ -54,11 +54,13 @@ static void omap2_sys_clk_recalc(struct clk * clk) | |||
54 | 54 | ||
55 | static u32 omap2_get_dpll_rate(struct clk * tclk) | 55 | static u32 omap2_get_dpll_rate(struct clk * tclk) |
56 | { | 56 | { |
57 | int dpll_clk, dpll_mult, dpll_div, amult; | 57 | long long dpll_clk; |
58 | int dpll_mult, dpll_div, amult; | ||
58 | 59 | ||
59 | dpll_mult = (CM_CLKSEL1_PLL >> 12) & 0x03ff; /* 10 bits */ | 60 | dpll_mult = (CM_CLKSEL1_PLL >> 12) & 0x03ff; /* 10 bits */ |
60 | dpll_div = (CM_CLKSEL1_PLL >> 8) & 0x0f; /* 4 bits */ | 61 | dpll_div = (CM_CLKSEL1_PLL >> 8) & 0x0f; /* 4 bits */ |
61 | dpll_clk = (tclk->parent->rate * dpll_mult) / (dpll_div + 1); | 62 | dpll_clk = (long long)tclk->parent->rate * dpll_mult; |
63 | do_div(dpll_clk, dpll_div + 1); | ||
62 | amult = CM_CLKSEL2_PLL & 0x3; | 64 | amult = CM_CLKSEL2_PLL & 0x3; |
63 | dpll_clk *= amult; | 65 | dpll_clk *= amult; |
64 | 66 | ||
@@ -385,75 +387,23 @@ static u32 omap2_dll_force_needed(void) | |||
385 | return 0; | 387 | return 0; |
386 | } | 388 | } |
387 | 389 | ||
388 | static void omap2_init_memory_params(u32 force_lock_to_unlock_mode) | ||
389 | { | ||
390 | unsigned long dll_cnt; | ||
391 | u32 fast_dll = 0; | ||
392 | |||
393 | mem_timings.m_type = !((SDRC_MR_0 & 0x3) == 0x1); /* DDR = 1, SDR = 0 */ | ||
394 | |||
395 | /* 2422 es2.05 and beyond has a single SIP DDR instead of 2 like others. | ||
396 | * In the case of 2422, its ok to use CS1 instead of CS0. | ||
397 | */ | ||
398 | |||
399 | #if 0 /* FIXME: Enable after 24xx cpu detection works */ | ||
400 | ctype = get_cpu_type(); | ||
401 | if (cpu_is_omap2422()) | ||
402 | mem_timings.base_cs = 1; | ||
403 | else | ||
404 | #endif | ||
405 | mem_timings.base_cs = 0; | ||
406 | |||
407 | if (mem_timings.m_type != M_DDR) | ||
408 | return; | ||
409 | |||
410 | /* With DDR we need to determine the low frequency DLL value */ | ||
411 | if (((mem_timings.fast_dll_ctrl & (1 << 2)) == M_LOCK_CTRL)) | ||
412 | mem_timings.dll_mode = M_UNLOCK; | ||
413 | else | ||
414 | mem_timings.dll_mode = M_LOCK; | ||
415 | |||
416 | if (mem_timings.base_cs == 0) { | ||
417 | fast_dll = SDRC_DLLA_CTRL; | ||
418 | dll_cnt = SDRC_DLLA_STATUS & 0xff00; | ||
419 | } else { | ||
420 | fast_dll = SDRC_DLLB_CTRL; | ||
421 | dll_cnt = SDRC_DLLB_STATUS & 0xff00; | ||
422 | } | ||
423 | if (force_lock_to_unlock_mode) { | ||
424 | fast_dll &= ~0xff00; | ||
425 | fast_dll |= dll_cnt; /* Current lock mode */ | ||
426 | } | ||
427 | mem_timings.fast_dll_ctrl = fast_dll; | ||
428 | |||
429 | /* No disruptions, DDR will be offline & C-ABI not followed */ | ||
430 | omap2_sram_ddr_init(&mem_timings.slow_dll_ctrl, | ||
431 | mem_timings.fast_dll_ctrl, | ||
432 | mem_timings.base_cs, | ||
433 | force_lock_to_unlock_mode); | ||
434 | mem_timings.slow_dll_ctrl &= 0xff00; /* Keep lock value */ | ||
435 | |||
436 | /* Turn status into unlock ctrl */ | ||
437 | mem_timings.slow_dll_ctrl |= | ||
438 | ((mem_timings.fast_dll_ctrl & 0xF) | (1 << 2)); | ||
439 | |||
440 | /* 90 degree phase for anything below 133Mhz */ | ||
441 | mem_timings.slow_dll_ctrl |= (1 << 1); | ||
442 | } | ||
443 | |||
444 | static u32 omap2_reprogram_sdrc(u32 level, u32 force) | 390 | static u32 omap2_reprogram_sdrc(u32 level, u32 force) |
445 | { | 391 | { |
392 | u32 slow_dll_ctrl, fast_dll_ctrl, m_type; | ||
446 | u32 prev = curr_perf_level, flags; | 393 | u32 prev = curr_perf_level, flags; |
447 | 394 | ||
448 | if ((curr_perf_level == level) && !force) | 395 | if ((curr_perf_level == level) && !force) |
449 | return prev; | 396 | return prev; |
450 | 397 | ||
398 | m_type = omap2_memory_get_type(); | ||
399 | slow_dll_ctrl = omap2_memory_get_slow_dll_ctrl(); | ||
400 | fast_dll_ctrl = omap2_memory_get_fast_dll_ctrl(); | ||
401 | |||
451 | if (level == PRCM_HALF_SPEED) { | 402 | if (level == PRCM_HALF_SPEED) { |
452 | local_irq_save(flags); | 403 | local_irq_save(flags); |
453 | PRCM_VOLTSETUP = 0xffff; | 404 | PRCM_VOLTSETUP = 0xffff; |
454 | omap2_sram_reprogram_sdrc(PRCM_HALF_SPEED, | 405 | omap2_sram_reprogram_sdrc(PRCM_HALF_SPEED, |
455 | mem_timings.slow_dll_ctrl, | 406 | slow_dll_ctrl, m_type); |
456 | mem_timings.m_type); | ||
457 | curr_perf_level = PRCM_HALF_SPEED; | 407 | curr_perf_level = PRCM_HALF_SPEED; |
458 | local_irq_restore(flags); | 408 | local_irq_restore(flags); |
459 | } | 409 | } |
@@ -461,8 +411,7 @@ static u32 omap2_reprogram_sdrc(u32 level, u32 force) | |||
461 | local_irq_save(flags); | 411 | local_irq_save(flags); |
462 | PRCM_VOLTSETUP = 0xffff; | 412 | PRCM_VOLTSETUP = 0xffff; |
463 | omap2_sram_reprogram_sdrc(PRCM_FULL_SPEED, | 413 | omap2_sram_reprogram_sdrc(PRCM_FULL_SPEED, |
464 | mem_timings.fast_dll_ctrl, | 414 | fast_dll_ctrl, m_type); |
465 | mem_timings.m_type); | ||
466 | curr_perf_level = PRCM_FULL_SPEED; | 415 | curr_perf_level = PRCM_FULL_SPEED; |
467 | local_irq_restore(flags); | 416 | local_irq_restore(flags); |
468 | } | 417 | } |
@@ -650,7 +599,7 @@ static u32 omap2_get_clksel(u32 *div_sel, u32 *field_mask, | |||
650 | case 13: /* dss2 */ | 599 | case 13: /* dss2 */ |
651 | mask = 0x1; break; | 600 | mask = 0x1; break; |
652 | case 25: /* usb */ | 601 | case 25: /* usb */ |
653 | mask = 0xf; break; | 602 | mask = 0x7; break; |
654 | } | 603 | } |
655 | } | 604 | } |
656 | 605 | ||
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h index 6cab20b1d3c1..6c78d471fab7 100644 --- a/arch/arm/mach-omap2/clock.h +++ b/arch/arm/mach-omap2/clock.h | |||
@@ -33,20 +33,6 @@ static u32 omap2_clksel_get_divisor(struct clk *clk); | |||
33 | #define RATE_IN_242X (1 << 0) | 33 | #define RATE_IN_242X (1 << 0) |
34 | #define RATE_IN_243X (1 << 1) | 34 | #define RATE_IN_243X (1 << 1) |
35 | 35 | ||
36 | /* Memory timings */ | ||
37 | #define M_DDR 1 | ||
38 | #define M_LOCK_CTRL (1 << 2) | ||
39 | #define M_UNLOCK 0 | ||
40 | #define M_LOCK 1 | ||
41 | |||
42 | struct memory_timings { | ||
43 | u32 m_type; /* ddr = 1, sdr = 0 */ | ||
44 | u32 dll_mode; /* use lock mode = 1, unlock mode = 0 */ | ||
45 | u32 slow_dll_ctrl; /* unlock mode, dll value for slow speed */ | ||
46 | u32 fast_dll_ctrl; /* unlock mode, dll value for fast speed */ | ||
47 | u32 base_cs; /* base chip select to use for calculations */ | ||
48 | }; | ||
49 | |||
50 | /* Key dividers which make up a PRCM set. Ratio's for a PRCM are mandated. | 36 | /* Key dividers which make up a PRCM set. Ratio's for a PRCM are mandated. |
51 | * xtal_speed, dpll_speed, mpu_speed, CM_CLKSEL_MPU,CM_CLKSEL_DSP | 37 | * xtal_speed, dpll_speed, mpu_speed, CM_CLKSEL_MPU,CM_CLKSEL_DSP |
52 | * CM_CLKSEL_GFX, CM_CLKSEL1_CORE, CM_CLKSEL1_PLL CM_CLKSEL2_PLL, CM_CLKSEL_MDM | 38 | * CM_CLKSEL_GFX, CM_CLKSEL1_CORE, CM_CLKSEL1_PLL CM_CLKSEL2_PLL, CM_CLKSEL_MDM |
@@ -731,6 +717,16 @@ static struct clk sys_clkout2 = { | |||
731 | .recalc = &omap2_clksel_recalc, | 717 | .recalc = &omap2_clksel_recalc, |
732 | }; | 718 | }; |
733 | 719 | ||
720 | static struct clk emul_ck = { | ||
721 | .name = "emul_ck", | ||
722 | .parent = &func_54m_ck, | ||
723 | .flags = CLOCK_IN_OMAP242X, | ||
724 | .enable_reg = (void __iomem *)&PRCM_CLKEMUL_CTRL, | ||
725 | .enable_bit = 0, | ||
726 | .recalc = &omap2_propagate_rate, | ||
727 | |||
728 | }; | ||
729 | |||
734 | /* | 730 | /* |
735 | * MPU clock domain | 731 | * MPU clock domain |
736 | * Clocks: | 732 | * Clocks: |
@@ -1702,7 +1698,8 @@ static struct clk hdq_fck = { | |||
1702 | }; | 1698 | }; |
1703 | 1699 | ||
1704 | static struct clk i2c2_ick = { | 1700 | static struct clk i2c2_ick = { |
1705 | .name = "i2c2_ick", | 1701 | .name = "i2c_ick", |
1702 | .id = 2, | ||
1706 | .parent = &l4_ck, | 1703 | .parent = &l4_ck, |
1707 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | 1704 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, |
1708 | .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, | 1705 | .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, |
@@ -1711,7 +1708,8 @@ static struct clk i2c2_ick = { | |||
1711 | }; | 1708 | }; |
1712 | 1709 | ||
1713 | static struct clk i2c2_fck = { | 1710 | static struct clk i2c2_fck = { |
1714 | .name = "i2c2_fck", | 1711 | .name = "i2c_fck", |
1712 | .id = 2, | ||
1715 | .parent = &func_12m_ck, | 1713 | .parent = &func_12m_ck, |
1716 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | 1714 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, |
1717 | .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE, | 1715 | .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE, |
@@ -1729,7 +1727,8 @@ static struct clk i2chs2_fck = { | |||
1729 | }; | 1727 | }; |
1730 | 1728 | ||
1731 | static struct clk i2c1_ick = { | 1729 | static struct clk i2c1_ick = { |
1732 | .name = "i2c1_ick", | 1730 | .name = "i2c_ick", |
1731 | .id = 1, | ||
1733 | .parent = &l4_ck, | 1732 | .parent = &l4_ck, |
1734 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | 1733 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, |
1735 | .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, | 1734 | .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, |
@@ -1738,7 +1737,8 @@ static struct clk i2c1_ick = { | |||
1738 | }; | 1737 | }; |
1739 | 1738 | ||
1740 | static struct clk i2c1_fck = { | 1739 | static struct clk i2c1_fck = { |
1741 | .name = "i2c1_fck", | 1740 | .name = "i2c_fck", |
1741 | .id = 1, | ||
1742 | .parent = &func_12m_ck, | 1742 | .parent = &func_12m_ck, |
1743 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | 1743 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, |
1744 | .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE, | 1744 | .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE, |
@@ -1971,6 +1971,7 @@ static struct clk *onchip_clks[] = { | |||
1971 | &wdt1_osc_ck, | 1971 | &wdt1_osc_ck, |
1972 | &sys_clkout, | 1972 | &sys_clkout, |
1973 | &sys_clkout2, | 1973 | &sys_clkout2, |
1974 | &emul_ck, | ||
1974 | /* mpu domain clocks */ | 1975 | /* mpu domain clocks */ |
1975 | &mpu_ck, | 1976 | &mpu_ck, |
1976 | /* dsp domain clocks */ | 1977 | /* dsp domain clocks */ |
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index 7181edb89352..def9e5370edf 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c | |||
@@ -74,6 +74,47 @@ static void omap_init_i2c(void) {} | |||
74 | 74 | ||
75 | #endif | 75 | #endif |
76 | 76 | ||
77 | #if defined(CONFIG_OMAP_STI) | ||
78 | |||
79 | #define OMAP2_STI_BASE IO_ADDRESS(0x48068000) | ||
80 | #define OMAP2_STI_CHANNEL_BASE 0x54000000 | ||
81 | #define OMAP2_STI_IRQ 4 | ||
82 | |||
83 | static struct resource sti_resources[] = { | ||
84 | { | ||
85 | .start = OMAP2_STI_BASE, | ||
86 | .end = OMAP2_STI_BASE + 0x7ff, | ||
87 | .flags = IORESOURCE_MEM, | ||
88 | }, | ||
89 | { | ||
90 | .start = OMAP2_STI_CHANNEL_BASE, | ||
91 | .end = OMAP2_STI_CHANNEL_BASE + SZ_64K - 1, | ||
92 | .flags = IORESOURCE_MEM, | ||
93 | }, | ||
94 | { | ||
95 | .start = OMAP2_STI_IRQ, | ||
96 | .flags = IORESOURCE_IRQ, | ||
97 | } | ||
98 | }; | ||
99 | |||
100 | static struct platform_device sti_device = { | ||
101 | .name = "sti", | ||
102 | .id = -1, | ||
103 | .dev = { | ||
104 | .release = omap_nop_release, | ||
105 | }, | ||
106 | .num_resources = ARRAY_SIZE(sti_resources), | ||
107 | .resource = sti_resources, | ||
108 | }; | ||
109 | |||
110 | static inline void omap_init_sti(void) | ||
111 | { | ||
112 | platform_device_register(&sti_device); | ||
113 | } | ||
114 | #else | ||
115 | static inline void omap_init_sti(void) {} | ||
116 | #endif | ||
117 | |||
77 | /*-------------------------------------------------------------------------*/ | 118 | /*-------------------------------------------------------------------------*/ |
78 | 119 | ||
79 | static int __init omap2_init_devices(void) | 120 | static int __init omap2_init_devices(void) |
@@ -82,6 +123,7 @@ static int __init omap2_init_devices(void) | |||
82 | * in alphabetical order so they're easier to sort through. | 123 | * in alphabetical order so they're easier to sort through. |
83 | */ | 124 | */ |
84 | omap_init_i2c(); | 125 | omap_init_i2c(); |
126 | omap_init_sti(); | ||
85 | 127 | ||
86 | return 0; | 128 | return 0; |
87 | } | 129 | } |
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c index 8ea67bf196a5..7d5711611f2f 100644 --- a/arch/arm/mach-omap2/io.c +++ b/arch/arm/mach-omap2/io.c | |||
@@ -16,9 +16,13 @@ | |||
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
18 | 18 | ||
19 | #include <asm/mach/map.h> | 19 | #include <asm/tlb.h> |
20 | #include <asm/io.h> | 20 | #include <asm/io.h> |
21 | |||
22 | #include <asm/mach/map.h> | ||
23 | |||
21 | #include <asm/arch/mux.h> | 24 | #include <asm/arch/mux.h> |
25 | #include <asm/arch/omapfb.h> | ||
22 | 26 | ||
23 | extern void omap_sram_init(void); | 27 | extern void omap_sram_init(void); |
24 | extern int omap2_clk_init(void); | 28 | extern int omap2_clk_init(void); |
@@ -43,11 +47,24 @@ static struct map_desc omap2_io_desc[] __initdata = { | |||
43 | } | 47 | } |
44 | }; | 48 | }; |
45 | 49 | ||
46 | void __init omap_map_common_io(void) | 50 | void __init omap2_map_common_io(void) |
47 | { | 51 | { |
48 | iotable_init(omap2_io_desc, ARRAY_SIZE(omap2_io_desc)); | 52 | iotable_init(omap2_io_desc, ARRAY_SIZE(omap2_io_desc)); |
53 | |||
54 | /* Normally devicemaps_init() would flush caches and tlb after | ||
55 | * mdesc->map_io(), but we must also do it here because of the CPU | ||
56 | * revision check below. | ||
57 | */ | ||
58 | local_flush_tlb_all(); | ||
59 | flush_cache_all(); | ||
60 | |||
49 | omap2_check_revision(); | 61 | omap2_check_revision(); |
50 | omap_sram_init(); | 62 | omap_sram_init(); |
63 | omapfb_reserve_mem(); | ||
64 | } | ||
65 | |||
66 | void __init omap2_init_common_hw(void) | ||
67 | { | ||
51 | omap2_mux_init(); | 68 | omap2_mux_init(); |
52 | omap2_clk_init(); | 69 | omap2_clk_init(); |
53 | } | 70 | } |
diff --git a/arch/arm/mach-omap2/memory.c b/arch/arm/mach-omap2/memory.c new file mode 100644 index 000000000000..1d925d69fc35 --- /dev/null +++ b/arch/arm/mach-omap2/memory.c | |||
@@ -0,0 +1,102 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-omap2/memory.c | ||
3 | * | ||
4 | * Memory timing related functions for OMAP24XX | ||
5 | * | ||
6 | * Copyright (C) 2005 Texas Instruments Inc. | ||
7 | * Richard Woodruff <r-woodruff2@ti.com> | ||
8 | * | ||
9 | * Copyright (C) 2005 Nokia Corporation | ||
10 | * Tony Lindgren <tony@atomide.com> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License version 2 as | ||
14 | * published by the Free Software Foundation. | ||
15 | */ | ||
16 | |||
17 | #include <linux/config.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/device.h> | ||
21 | #include <linux/list.h> | ||
22 | #include <linux/errno.h> | ||
23 | #include <linux/delay.h> | ||
24 | #include <linux/clk.h> | ||
25 | |||
26 | #include <asm/io.h> | ||
27 | |||
28 | #include <asm/arch/clock.h> | ||
29 | #include <asm/arch/sram.h> | ||
30 | |||
31 | #include "prcm-regs.h" | ||
32 | #include "memory.h" | ||
33 | |||
34 | static struct memory_timings mem_timings; | ||
35 | |||
36 | u32 omap2_memory_get_slow_dll_ctrl(void) | ||
37 | { | ||
38 | return mem_timings.slow_dll_ctrl; | ||
39 | } | ||
40 | |||
41 | u32 omap2_memory_get_fast_dll_ctrl(void) | ||
42 | { | ||
43 | return mem_timings.fast_dll_ctrl; | ||
44 | } | ||
45 | |||
46 | u32 omap2_memory_get_type(void) | ||
47 | { | ||
48 | return mem_timings.m_type; | ||
49 | } | ||
50 | |||
51 | void omap2_init_memory_params(u32 force_lock_to_unlock_mode) | ||
52 | { | ||
53 | unsigned long dll_cnt; | ||
54 | u32 fast_dll = 0; | ||
55 | |||
56 | mem_timings.m_type = !((SDRC_MR_0 & 0x3) == 0x1); /* DDR = 1, SDR = 0 */ | ||
57 | |||
58 | /* 2422 es2.05 and beyond has a single SIP DDR instead of 2 like others. | ||
59 | * In the case of 2422, its ok to use CS1 instead of CS0. | ||
60 | */ | ||
61 | if (cpu_is_omap2422()) | ||
62 | mem_timings.base_cs = 1; | ||
63 | else | ||
64 | mem_timings.base_cs = 0; | ||
65 | |||
66 | if (mem_timings.m_type != M_DDR) | ||
67 | return; | ||
68 | |||
69 | /* With DDR we need to determine the low frequency DLL value */ | ||
70 | if (((mem_timings.fast_dll_ctrl & (1 << 2)) == M_LOCK_CTRL)) | ||
71 | mem_timings.dll_mode = M_UNLOCK; | ||
72 | else | ||
73 | mem_timings.dll_mode = M_LOCK; | ||
74 | |||
75 | if (mem_timings.base_cs == 0) { | ||
76 | fast_dll = SDRC_DLLA_CTRL; | ||
77 | dll_cnt = SDRC_DLLA_STATUS & 0xff00; | ||
78 | } else { | ||
79 | fast_dll = SDRC_DLLB_CTRL; | ||
80 | dll_cnt = SDRC_DLLB_STATUS & 0xff00; | ||
81 | } | ||
82 | if (force_lock_to_unlock_mode) { | ||
83 | fast_dll &= ~0xff00; | ||
84 | fast_dll |= dll_cnt; /* Current lock mode */ | ||
85 | } | ||
86 | /* set fast timings with DLL filter disabled */ | ||
87 | mem_timings.fast_dll_ctrl = (fast_dll | (3 << 8)); | ||
88 | |||
89 | /* No disruptions, DDR will be offline & C-ABI not followed */ | ||
90 | omap2_sram_ddr_init(&mem_timings.slow_dll_ctrl, | ||
91 | mem_timings.fast_dll_ctrl, | ||
92 | mem_timings.base_cs, | ||
93 | force_lock_to_unlock_mode); | ||
94 | mem_timings.slow_dll_ctrl &= 0xff00; /* Keep lock value */ | ||
95 | |||
96 | /* Turn status into unlock ctrl */ | ||
97 | mem_timings.slow_dll_ctrl |= | ||
98 | ((mem_timings.fast_dll_ctrl & 0xF) | (1 << 2)); | ||
99 | |||
100 | /* 90 degree phase for anything below 133Mhz + disable DLL filter */ | ||
101 | mem_timings.slow_dll_ctrl |= ((1 << 1) | (3 << 8)); | ||
102 | } | ||
diff --git a/arch/arm/mach-omap2/memory.h b/arch/arm/mach-omap2/memory.h new file mode 100644 index 000000000000..d212eea83a05 --- /dev/null +++ b/arch/arm/mach-omap2/memory.h | |||
@@ -0,0 +1,34 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-omap2/memory.h | ||
3 | * | ||
4 | * Interface for memory timing related functions for OMAP24XX | ||
5 | * | ||
6 | * Copyright (C) 2005 Texas Instruments Inc. | ||
7 | * Richard Woodruff <r-woodruff2@ti.com> | ||
8 | * | ||
9 | * Copyright (C) 2005 Nokia Corporation | ||
10 | * Tony Lindgren <tony@atomide.com> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License version 2 as | ||
14 | * published by the Free Software Foundation. | ||
15 | */ | ||
16 | |||
17 | /* Memory timings */ | ||
18 | #define M_DDR 1 | ||
19 | #define M_LOCK_CTRL (1 << 2) | ||
20 | #define M_UNLOCK 0 | ||
21 | #define M_LOCK 1 | ||
22 | |||
23 | struct memory_timings { | ||
24 | u32 m_type; /* ddr = 1, sdr = 0 */ | ||
25 | u32 dll_mode; /* use lock mode = 1, unlock mode = 0 */ | ||
26 | u32 slow_dll_ctrl; /* unlock mode, dll value for slow speed */ | ||
27 | u32 fast_dll_ctrl; /* unlock mode, dll value for fast speed */ | ||
28 | u32 base_cs; /* base chip select to use for calculations */ | ||
29 | }; | ||
30 | |||
31 | extern void omap2_init_memory_params(u32 force_lock_to_unlock_mode); | ||
32 | extern u32 omap2_memory_get_slow_dll_ctrl(void); | ||
33 | extern u32 omap2_memory_get_fast_dll_ctrl(void); | ||
34 | extern u32 omap2_memory_get_type(void); | ||
diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c index ea4654815dd1..1197dc38c20a 100644 --- a/arch/arm/mach-omap2/mux.c +++ b/arch/arm/mach-omap2/mux.c | |||
@@ -50,9 +50,54 @@ MUX_CFG_24XX("H19_24XX_I2C2_SDA", 0x114, 0, 0, 0, 1) | |||
50 | /* Menelaus interrupt */ | 50 | /* Menelaus interrupt */ |
51 | MUX_CFG_24XX("W19_24XX_SYS_NIRQ", 0x12c, 0, 1, 1, 1) | 51 | MUX_CFG_24XX("W19_24XX_SYS_NIRQ", 0x12c, 0, 1, 1, 1) |
52 | 52 | ||
53 | /* 24xx clocks */ | ||
54 | MUX_CFG_24XX("W14_24XX_SYS_CLKOUT", 0x137, 0, 1, 1, 1) | ||
55 | |||
56 | /* 24xx McBSP */ | ||
57 | MUX_CFG_24XX("Y15_24XX_MCBSP2_CLKX", 0x124, 1, 1, 0, 1) | ||
58 | MUX_CFG_24XX("R14_24XX_MCBSP2_FSX", 0x125, 1, 1, 0, 1) | ||
59 | MUX_CFG_24XX("W15_24XX_MCBSP2_DR", 0x126, 1, 1, 0, 1) | ||
60 | MUX_CFG_24XX("V15_24XX_MCBSP2_DX", 0x127, 1, 1, 0, 1) | ||
61 | |||
53 | /* 24xx GPIO */ | 62 | /* 24xx GPIO */ |
63 | MUX_CFG_24XX("M21_242X_GPIO11", 0x0c9, 3, 1, 1, 1) | ||
64 | MUX_CFG_24XX("AA10_242X_GPIO13", 0x0e5, 3, 0, 0, 1) | ||
65 | MUX_CFG_24XX("AA6_242X_GPIO14", 0x0e6, 3, 0, 0, 1) | ||
66 | MUX_CFG_24XX("AA4_242X_GPIO15", 0x0e7, 3, 0, 0, 1) | ||
67 | MUX_CFG_24XX("Y11_242X_GPIO16", 0x0e8, 3, 0, 0, 1) | ||
68 | MUX_CFG_24XX("AA12_242X_GPIO17", 0x0e9, 3, 0, 0, 1) | ||
69 | MUX_CFG_24XX("AA8_242X_GPIO58", 0x0ea, 3, 0, 0, 1) | ||
54 | MUX_CFG_24XX("Y20_24XX_GPIO60", 0x12c, 3, 0, 0, 1) | 70 | MUX_CFG_24XX("Y20_24XX_GPIO60", 0x12c, 3, 0, 0, 1) |
71 | MUX_CFG_24XX("W4__24XX_GPIO74", 0x0f2, 3, 0, 0, 1) | ||
55 | MUX_CFG_24XX("M15_24XX_GPIO92", 0x10a, 3, 0, 0, 1) | 72 | MUX_CFG_24XX("M15_24XX_GPIO92", 0x10a, 3, 0, 0, 1) |
73 | MUX_CFG_24XX("V14_24XX_GPIO117", 0x128, 3, 1, 0, 1) | ||
74 | |||
75 | /* TSC IRQ */ | ||
76 | MUX_CFG_24XX("P20_24XX_TSC_IRQ", 0x108, 0, 0, 0, 1) | ||
77 | |||
78 | /* UART3 */ | ||
79 | MUX_CFG_24XX("K15_24XX_UART3_TX", 0x118, 0, 0, 0, 1) | ||
80 | MUX_CFG_24XX("K14_24XX_UART3_RX", 0x119, 0, 0, 0, 1) | ||
81 | |||
82 | /* Keypad GPIO*/ | ||
83 | MUX_CFG_24XX("T19_24XX_KBR0", 0x106, 3, 1, 1, 1) | ||
84 | MUX_CFG_24XX("R19_24XX_KBR1", 0x107, 3, 1, 1, 1) | ||
85 | MUX_CFG_24XX("V18_24XX_KBR2", 0x139, 3, 1, 1, 1) | ||
86 | MUX_CFG_24XX("M21_24XX_KBR3", 0xc9, 3, 1, 1, 1) | ||
87 | MUX_CFG_24XX("E5__24XX_KBR4", 0x138, 3, 1, 1, 1) | ||
88 | MUX_CFG_24XX("M18_24XX_KBR5", 0x10e, 3, 1, 1, 1) | ||
89 | MUX_CFG_24XX("R20_24XX_KBC0", 0x108, 3, 0, 0, 1) | ||
90 | MUX_CFG_24XX("M14_24XX_KBC1", 0x109, 3, 0, 0, 1) | ||
91 | MUX_CFG_24XX("H19_24XX_KBC2", 0x114, 3, 0, 0, 1) | ||
92 | MUX_CFG_24XX("V17_24XX_KBC3", 0x135, 3, 0, 0, 1) | ||
93 | MUX_CFG_24XX("P21_24XX_KBC4", 0xca, 3, 0, 0, 1) | ||
94 | MUX_CFG_24XX("L14_24XX_KBC5", 0x10f, 3, 0, 0, 1) | ||
95 | MUX_CFG_24XX("N19_24XX_KBC6", 0x110, 3, 0, 0, 1) | ||
96 | |||
97 | /* 24xx Menelaus Keypad GPIO */ | ||
98 | MUX_CFG_24XX("B3__24XX_KBR5", 0x30, 3, 1, 1, 1) | ||
99 | MUX_CFG_24XX("AA4_24XX_KBC2", 0xe7, 3, 0, 0, 1) | ||
100 | MUX_CFG_24XX("B13_24XX_KBC6", 0x110, 3, 0, 0, 1) | ||
56 | 101 | ||
57 | }; | 102 | }; |
58 | 103 | ||
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c new file mode 100644 index 000000000000..562168fa2b16 --- /dev/null +++ b/arch/arm/mach-omap2/pm.c | |||
@@ -0,0 +1,149 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-omap2/pm.c | ||
3 | * | ||
4 | * OMAP2 Power Management Routines | ||
5 | * | ||
6 | * Copyright (C) 2006 Nokia Corporation | ||
7 | * Tony Lindgren <tony@atomide.com> | ||
8 | * | ||
9 | * Copyright (C) 2005 Texas Instruments, Inc. | ||
10 | * Richard Woodruff <r-woodruff2@ti.com> | ||
11 | * | ||
12 | * Based on pm.c for omap1 | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify | ||
15 | * it under the terms of the GNU General Public License version 2 as | ||
16 | * published by the Free Software Foundation. | ||
17 | */ | ||
18 | |||
19 | #include <linux/pm.h> | ||
20 | #include <linux/sched.h> | ||
21 | #include <linux/proc_fs.h> | ||
22 | #include <linux/pm.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/sysfs.h> | ||
25 | #include <linux/module.h> | ||
26 | |||
27 | #include <asm/io.h> | ||
28 | #include <asm/irq.h> | ||
29 | #include <asm/atomic.h> | ||
30 | #include <asm/mach/time.h> | ||
31 | #include <asm/mach/irq.h> | ||
32 | #include <asm/mach-types.h> | ||
33 | |||
34 | #include <asm/arch/irqs.h> | ||
35 | #include <asm/arch/clock.h> | ||
36 | #include <asm/arch/sram.h> | ||
37 | #include <asm/arch/pm.h> | ||
38 | |||
39 | static struct clk *vclk; | ||
40 | static void (*omap2_sram_idle)(void); | ||
41 | static void (*omap2_sram_suspend)(int dllctrl, int cpu_rev); | ||
42 | static void (*saved_idle)(void); | ||
43 | |||
44 | void omap2_pm_idle(void) | ||
45 | { | ||
46 | local_irq_disable(); | ||
47 | local_fiq_disable(); | ||
48 | if (need_resched()) { | ||
49 | local_fiq_enable(); | ||
50 | local_irq_enable(); | ||
51 | return; | ||
52 | } | ||
53 | |||
54 | /* | ||
55 | * Since an interrupt may set up a timer, we don't want to | ||
56 | * reprogram the hardware timer with interrupts enabled. | ||
57 | * Re-enable interrupts only after returning from idle. | ||
58 | */ | ||
59 | timer_dyn_reprogram(); | ||
60 | |||
61 | omap2_sram_idle(); | ||
62 | local_fiq_enable(); | ||
63 | local_irq_enable(); | ||
64 | } | ||
65 | |||
66 | static int omap2_pm_prepare(suspend_state_t state) | ||
67 | { | ||
68 | int error = 0; | ||
69 | |||
70 | /* We cannot sleep in idle until we have resumed */ | ||
71 | saved_idle = pm_idle; | ||
72 | pm_idle = NULL; | ||
73 | |||
74 | switch (state) | ||
75 | { | ||
76 | case PM_SUSPEND_STANDBY: | ||
77 | case PM_SUSPEND_MEM: | ||
78 | break; | ||
79 | |||
80 | case PM_SUSPEND_DISK: | ||
81 | return -ENOTSUPP; | ||
82 | |||
83 | default: | ||
84 | return -EINVAL; | ||
85 | } | ||
86 | |||
87 | return error; | ||
88 | } | ||
89 | |||
90 | static int omap2_pm_enter(suspend_state_t state) | ||
91 | { | ||
92 | switch (state) | ||
93 | { | ||
94 | case PM_SUSPEND_STANDBY: | ||
95 | case PM_SUSPEND_MEM: | ||
96 | /* FIXME: Add suspend */ | ||
97 | break; | ||
98 | |||
99 | case PM_SUSPEND_DISK: | ||
100 | return -ENOTSUPP; | ||
101 | |||
102 | default: | ||
103 | return -EINVAL; | ||
104 | } | ||
105 | |||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | static int omap2_pm_finish(suspend_state_t state) | ||
110 | { | ||
111 | pm_idle = saved_idle; | ||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | static struct pm_ops omap_pm_ops = { | ||
116 | .pm_disk_mode = 0, | ||
117 | .prepare = omap2_pm_prepare, | ||
118 | .enter = omap2_pm_enter, | ||
119 | .finish = omap2_pm_finish, | ||
120 | }; | ||
121 | |||
122 | int __init omap2_pm_init(void) | ||
123 | { | ||
124 | printk("Power Management for TI OMAP.\n"); | ||
125 | |||
126 | vclk = clk_get(NULL, "virt_prcm_set"); | ||
127 | if (IS_ERR(vclk)) { | ||
128 | printk(KERN_ERR "Could not get PM vclk\n"); | ||
129 | return -ENODEV; | ||
130 | } | ||
131 | |||
132 | /* | ||
133 | * We copy the assembler sleep/wakeup routines to SRAM. | ||
134 | * These routines need to be in SRAM as that's the only | ||
135 | * memory the MPU can see when it wakes up. | ||
136 | */ | ||
137 | omap2_sram_idle = omap_sram_push(omap24xx_idle_loop_suspend, | ||
138 | omap24xx_idle_loop_suspend_sz); | ||
139 | |||
140 | omap2_sram_suspend = omap_sram_push(omap24xx_cpu_suspend, | ||
141 | omap24xx_cpu_suspend_sz); | ||
142 | |||
143 | pm_set_ops(&omap_pm_ops); | ||
144 | pm_idle = omap2_pm_idle; | ||
145 | |||
146 | return 0; | ||
147 | } | ||
148 | |||
149 | __initcall(omap2_pm_init); | ||
diff --git a/arch/arm/mach-omap2/prcm.h b/arch/arm/mach-omap2/prcm-regs.h index 2eb89b936c83..22ac7be4f782 100644 --- a/arch/arm/mach-omap2/prcm.h +++ b/arch/arm/mach-omap2/prcm-regs.h | |||
@@ -1,5 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * prcm.h - Access definations for use in OMAP24XX clock and power management | 2 | * linux/arch/arm/mach-omap2/prcm-reg.h |
3 | * | ||
4 | * OMAP24XX Power Reset and Clock Management (PRCM) registers | ||
3 | * | 5 | * |
4 | * Copyright (C) 2005 Texas Instruments, Inc. | 6 | * Copyright (C) 2005 Texas Instruments, Inc. |
5 | * | 7 | * |
@@ -18,8 +20,8 @@ | |||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 | */ | 21 | */ |
20 | 22 | ||
21 | #ifndef __ASM_ARM_ARCH_DPM_PRCM_H | 23 | #ifndef __ARCH_ARM_MACH_OMAP2_PRCM_H |
22 | #define __ASM_ARM_ARCH_DPM_PRCM_H | 24 | #define __ARCH_ARM_MACH_OMAP2_PRCM_H |
23 | 25 | ||
24 | /* SET_PERFORMANCE_LEVEL PARAMETERS */ | 26 | /* SET_PERFORMANCE_LEVEL PARAMETERS */ |
25 | #define PRCM_HALF_SPEED 1 | 27 | #define PRCM_HALF_SPEED 1 |
@@ -159,54 +161,63 @@ | |||
159 | #define CM_FCLKEN_MDM PRCM_REG32(0xC00) | 161 | #define CM_FCLKEN_MDM PRCM_REG32(0xC00) |
160 | #define CM_ICLKEN_MDM PRCM_REG32(0xC10) | 162 | #define CM_ICLKEN_MDM PRCM_REG32(0xC10) |
161 | #define CM_IDLEST_MDM PRCM_REG32(0xC20) | 163 | #define CM_IDLEST_MDM PRCM_REG32(0xC20) |
164 | #define CM_AUTOIDLE_MDM PRCM_REG32(0xC30) | ||
162 | #define CM_CLKSEL_MDM PRCM_REG32(0xC40) | 165 | #define CM_CLKSEL_MDM PRCM_REG32(0xC40) |
163 | 166 | #define CM_CLKSTCTRL_MDM PRCM_REG32(0xC48) | |
164 | /* FIXME: Move to header for 2430 */ | 167 | #define RM_RSTCTRL_MDM PRCM_REG32(0xC50) |
165 | #define DISP_BASE (OMAP24XX_L4_IO_BASE+0x50000) | 168 | #define RM_RSTST_MDM PRCM_REG32(0xC58) |
169 | #define PM_WKEN_MDM PRCM_REG32(0xCA0) | ||
170 | #define PM_WKST_MDM PRCM_REG32(0xCB0) | ||
171 | #define PM_WKDEP_MDM PRCM_REG32(0xCC8) | ||
172 | #define PM_PWSTCTRL_MDM PRCM_REG32(0xCE0) | ||
173 | #define PM_PWSTST_MDM PRCM_REG32(0xCE4) | ||
174 | |||
175 | #define OMAP24XX_L4_IO_BASE 0x48000000 | ||
176 | |||
177 | #define DISP_BASE (OMAP24XX_L4_IO_BASE + 0x50000) | ||
166 | #define DISP_REG32(offset) __REG32(DISP_BASE + (offset)) | 178 | #define DISP_REG32(offset) __REG32(DISP_BASE + (offset)) |
167 | 179 | ||
168 | #define GPMC_BASE (OMAP24XX_GPMC_BASE) | 180 | #define OMAP24XX_GPMC_BASE (L3_24XX_BASE + 0xa000) |
169 | #define GPMC_REG32(offset) __REG32(GPMC_BASE + (offset)) | 181 | #define GPMC_REG32(offset) __REG32(OMAP24XX_GPMC_BASE + (offset)) |
170 | 182 | ||
171 | #define GPT1_BASE (OMAP24XX_GPT1) | 183 | /* FIXME: Move these to timer code */ |
184 | #define GPT1_BASE (0x48028000) | ||
172 | #define GPT1_REG32(offset) __REG32(GPT1_BASE + (offset)) | 185 | #define GPT1_REG32(offset) __REG32(GPT1_BASE + (offset)) |
173 | 186 | ||
174 | /* Misc sysconfig */ | 187 | /* Misc sysconfig */ |
175 | #define DISPC_SYSCONFIG DISP_REG32(0x410) | 188 | #define DISPC_SYSCONFIG DISP_REG32(0x410) |
176 | #define SPI_BASE (OMAP24XX_L4_IO_BASE+0x98000) | 189 | #define SPI_BASE (OMAP24XX_L4_IO_BASE + 0x98000) |
177 | #define MCSPI1_SYSCONFIG __REG32(SPI_BASE + 0x10) | 190 | #define MCSPI1_SYSCONFIG __REG32(SPI_BASE + 0x10) |
178 | #define MCSPI2_SYSCONFIG __REG32(SPI_BASE+0x2000 + 0x10) | 191 | #define MCSPI2_SYSCONFIG __REG32(SPI_BASE + 0x2000 + 0x10) |
179 | 192 | #define MCSPI3_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE + 0xb8010) | |
180 | //#define DSP_MMU_SYSCONFIG 0x5A000010 | 193 | |
181 | #define CAMERA_MMU_SYSCONFIG __REG32(DISP_BASE+0x2C10) | 194 | #define CAMERA_MMU_SYSCONFIG __REG32(DISP_BASE + 0x2C10) |
182 | //#define IVA_MMU_SYSCONFIG 0x5D000010 | 195 | #define CAMERA_DMA_SYSCONFIG __REG32(DISP_BASE + 0x282C) |
183 | //#define DSP_DMA_SYSCONFIG 0x00FCC02C | 196 | #define SYSTEM_DMA_SYSCONFIG __REG32(DISP_BASE + 0x602C) |
184 | #define CAMERA_DMA_SYSCONFIG __REG32(DISP_BASE+0x282C) | ||
185 | #define SYSTEM_DMA_SYSCONFIG __REG32(DISP_BASE+0x602C) | ||
186 | #define GPMC_SYSCONFIG GPMC_REG32(0x010) | 197 | #define GPMC_SYSCONFIG GPMC_REG32(0x010) |
187 | #define MAILBOXES_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE+0x94010) | 198 | #define MAILBOXES_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE + 0x94010) |
188 | #define UART1_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE+0x6A054) | 199 | #define UART1_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE + 0x6A054) |
189 | #define UART2_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE+0x6C054) | 200 | #define UART2_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE + 0x6C054) |
190 | #define UART3_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE+0x6E054) | 201 | #define UART3_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE + 0x6E054) |
191 | //#define IVA_SYSCONFIG 0x5C060010 | 202 | #define SDRC_SYSCONFIG __REG32(OMAP24XX_SDRC_BASE + 0x10) |
192 | #define SDRC_SYSCONFIG __REG32(OMAP24XX_SDRC_BASE+0x10) | 203 | #define OMAP24XX_SMS_BASE (L3_24XX_BASE + 0x8000) |
193 | #define SMS_SYSCONFIG __REG32(OMAP24XX_SMS_BASE+0x10) | 204 | #define SMS_SYSCONFIG __REG32(OMAP24XX_SMS_BASE + 0x10) |
194 | #define SSI_SYSCONFIG __REG32(DISP_BASE+0x8010) | 205 | #define SSI_SYSCONFIG __REG32(DISP_BASE + 0x8010) |
195 | //#define VLYNQ_SYSCONFIG 0x67FFFE10 | ||
196 | 206 | ||
197 | /* rkw - good cannidates for PM_ to start what nm was trying */ | 207 | /* rkw - good cannidates for PM_ to start what nm was trying */ |
198 | #define OMAP24XX_GPT2 (OMAP24XX_L4_IO_BASE+0x2A000) | 208 | #define OMAP24XX_GPT2 (OMAP24XX_L4_IO_BASE + 0x2A000) |
199 | #define OMAP24XX_GPT3 (OMAP24XX_L4_IO_BASE+0x78000) | 209 | #define OMAP24XX_GPT3 (OMAP24XX_L4_IO_BASE + 0x78000) |
200 | #define OMAP24XX_GPT4 (OMAP24XX_L4_IO_BASE+0x7A000) | 210 | #define OMAP24XX_GPT4 (OMAP24XX_L4_IO_BASE + 0x7A000) |
201 | #define OMAP24XX_GPT5 (OMAP24XX_L4_IO_BASE+0x7C000) | 211 | #define OMAP24XX_GPT5 (OMAP24XX_L4_IO_BASE + 0x7C000) |
202 | #define OMAP24XX_GPT6 (OMAP24XX_L4_IO_BASE+0x7E000) | 212 | #define OMAP24XX_GPT6 (OMAP24XX_L4_IO_BASE + 0x7E000) |
203 | #define OMAP24XX_GPT7 (OMAP24XX_L4_IO_BASE+0x80000) | 213 | #define OMAP24XX_GPT7 (OMAP24XX_L4_IO_BASE + 0x80000) |
204 | #define OMAP24XX_GPT8 (OMAP24XX_L4_IO_BASE+0x82000) | 214 | #define OMAP24XX_GPT8 (OMAP24XX_L4_IO_BASE + 0x82000) |
205 | #define OMAP24XX_GPT9 (OMAP24XX_L4_IO_BASE+0x84000) | 215 | #define OMAP24XX_GPT9 (OMAP24XX_L4_IO_BASE + 0x84000) |
206 | #define OMAP24XX_GPT10 (OMAP24XX_L4_IO_BASE+0x86000) | 216 | #define OMAP24XX_GPT10 (OMAP24XX_L4_IO_BASE + 0x86000) |
207 | #define OMAP24XX_GPT11 (OMAP24XX_L4_IO_BASE+0x88000) | 217 | #define OMAP24XX_GPT11 (OMAP24XX_L4_IO_BASE + 0x88000) |
208 | #define OMAP24XX_GPT12 (OMAP24XX_L4_IO_BASE+0x8A000) | 218 | #define OMAP24XX_GPT12 (OMAP24XX_L4_IO_BASE + 0x8A000) |
209 | 219 | ||
220 | /* FIXME: Move these to timer code */ | ||
210 | #define GPTIMER1_SYSCONFIG GPT1_REG32(0x010) | 221 | #define GPTIMER1_SYSCONFIG GPT1_REG32(0x010) |
211 | #define GPTIMER2_SYSCONFIG __REG32(OMAP24XX_GPT2 + 0x10) | 222 | #define GPTIMER2_SYSCONFIG __REG32(OMAP24XX_GPT2 + 0x10) |
212 | #define GPTIMER3_SYSCONFIG __REG32(OMAP24XX_GPT3 + 0x10) | 223 | #define GPTIMER3_SYSCONFIG __REG32(OMAP24XX_GPT3 + 0x10) |
@@ -220,12 +231,18 @@ | |||
220 | #define GPTIMER11_SYSCONFIG __REG32(OMAP24XX_GPT11 + 0x10) | 231 | #define GPTIMER11_SYSCONFIG __REG32(OMAP24XX_GPT11 + 0x10) |
221 | #define GPTIMER12_SYSCONFIG __REG32(OMAP24XX_GPT12 + 0x10) | 232 | #define GPTIMER12_SYSCONFIG __REG32(OMAP24XX_GPT12 + 0x10) |
222 | 233 | ||
223 | #define GPIOX_BASE(X) (OMAP24XX_GPIO_BASE+(0x2000*((X)-1))) | 234 | /* FIXME: Move these to gpio code */ |
235 | #define OMAP24XX_GPIO_BASE 0x48018000 | ||
236 | #define GPIOX_BASE(X) (OMAP24XX_GPIO_BASE + (0x2000 * ((X) - 1))) | ||
237 | |||
238 | #define GPIO1_SYSCONFIG __REG32((GPIOX_BASE(1) + 0x10)) | ||
239 | #define GPIO2_SYSCONFIG __REG32((GPIOX_BASE(2) + 0x10)) | ||
240 | #define GPIO3_SYSCONFIG __REG32((GPIOX_BASE(3) + 0x10)) | ||
241 | #define GPIO4_SYSCONFIG __REG32((GPIOX_BASE(4) + 0x10)) | ||
224 | 242 | ||
225 | #define GPIO1_SYSCONFIG __REG32((GPIOX_BASE(1)+0x10)) | 243 | #if defined(CONFIG_ARCH_OMAP243X) |
226 | #define GPIO2_SYSCONFIG __REG32((GPIOX_BASE(2)+0x10)) | 244 | #define GPIO5_SYSCONFIG __REG32((OMAP24XX_GPIO5_BASE + 0x10)) |
227 | #define GPIO3_SYSCONFIG __REG32((GPIOX_BASE(3)+0x10)) | 245 | #endif |
228 | #define GPIO4_SYSCONFIG __REG32((GPIOX_BASE(4)+0x10)) | ||
229 | 246 | ||
230 | /* GP TIMER 1 */ | 247 | /* GP TIMER 1 */ |
231 | #define GPTIMER1_TISTAT GPT1_REG32(0x014) | 248 | #define GPTIMER1_TISTAT GPT1_REG32(0x014) |
@@ -243,15 +260,15 @@ | |||
243 | #define GPTIMER1_TCAR2 GPT1_REG32(0x044) | 260 | #define GPTIMER1_TCAR2 GPT1_REG32(0x044) |
244 | 261 | ||
245 | /* rkw -- base fix up please... */ | 262 | /* rkw -- base fix up please... */ |
246 | #define GPTIMER3_TISR __REG32(OMAP24XX_L4_IO_BASE+0x78018) | 263 | #define GPTIMER3_TISR __REG32(OMAP24XX_L4_IO_BASE + 0x78018) |
247 | 264 | ||
248 | /* SDRC */ | 265 | /* SDRC */ |
249 | #define SDRC_DLLA_CTRL __REG32(OMAP24XX_SDRC_BASE+0x060) | 266 | #define SDRC_DLLA_CTRL __REG32(OMAP24XX_SDRC_BASE + 0x060) |
250 | #define SDRC_DLLA_STATUS __REG32(OMAP24XX_SDRC_BASE+0x064) | 267 | #define SDRC_DLLA_STATUS __REG32(OMAP24XX_SDRC_BASE + 0x064) |
251 | #define SDRC_DLLB_CTRL __REG32(OMAP24XX_SDRC_BASE+0x068) | 268 | #define SDRC_DLLB_CTRL __REG32(OMAP24XX_SDRC_BASE + 0x068) |
252 | #define SDRC_DLLB_STATUS __REG32(OMAP24XX_SDRC_BASE+0x06C) | 269 | #define SDRC_DLLB_STATUS __REG32(OMAP24XX_SDRC_BASE + 0x06C) |
253 | #define SDRC_POWER __REG32(OMAP24XX_SDRC_BASE+0x070) | 270 | #define SDRC_POWER __REG32(OMAP24XX_SDRC_BASE + 0x070) |
254 | #define SDRC_MR_0 __REG32(OMAP24XX_SDRC_BASE+0x084) | 271 | #define SDRC_MR_0 __REG32(OMAP24XX_SDRC_BASE + 0x084) |
255 | 272 | ||
256 | /* GPIO 1 */ | 273 | /* GPIO 1 */ |
257 | #define GPIO1_BASE GPIOX_BASE(1) | 274 | #define GPIO1_BASE GPIOX_BASE(1) |
@@ -278,6 +295,8 @@ | |||
278 | #define GPIO2_DATAIN GPIO2_REG32(0x038) | 295 | #define GPIO2_DATAIN GPIO2_REG32(0x038) |
279 | #define GPIO2_OE GPIO2_REG32(0x034) | 296 | #define GPIO2_OE GPIO2_REG32(0x034) |
280 | #define GPIO2_DATAOUT GPIO2_REG32(0x03C) | 297 | #define GPIO2_DATAOUT GPIO2_REG32(0x03C) |
298 | #define GPIO2_DEBOUNCENABLE GPIO2_REG32(0x050) | ||
299 | #define GPIO2_DEBOUNCINGTIME GPIO2_REG32(0x054) | ||
281 | 300 | ||
282 | /* GPIO 3 */ | 301 | /* GPIO 3 */ |
283 | #define GPIO3_BASE GPIOX_BASE(3) | 302 | #define GPIO3_BASE GPIOX_BASE(3) |
@@ -294,6 +313,8 @@ | |||
294 | #define GPIO3_DATAOUT GPIO3_REG32(0x03C) | 313 | #define GPIO3_DATAOUT GPIO3_REG32(0x03C) |
295 | #define GPIO3_DEBOUNCENABLE GPIO3_REG32(0x050) | 314 | #define GPIO3_DEBOUNCENABLE GPIO3_REG32(0x050) |
296 | #define GPIO3_DEBOUNCINGTIME GPIO3_REG32(0x054) | 315 | #define GPIO3_DEBOUNCINGTIME GPIO3_REG32(0x054) |
316 | #define GPIO3_DEBOUNCENABLE GPIO3_REG32(0x050) | ||
317 | #define GPIO3_DEBOUNCINGTIME GPIO3_REG32(0x054) | ||
297 | 318 | ||
298 | /* GPIO 4 */ | 319 | /* GPIO 4 */ |
299 | #define GPIO4_BASE GPIOX_BASE(4) | 320 | #define GPIO4_BASE GPIOX_BASE(4) |
@@ -311,10 +332,26 @@ | |||
311 | #define GPIO4_DEBOUNCENABLE GPIO4_REG32(0x050) | 332 | #define GPIO4_DEBOUNCENABLE GPIO4_REG32(0x050) |
312 | #define GPIO4_DEBOUNCINGTIME GPIO4_REG32(0x054) | 333 | #define GPIO4_DEBOUNCINGTIME GPIO4_REG32(0x054) |
313 | 334 | ||
335 | #if defined(CONFIG_ARCH_OMAP243X) | ||
336 | /* GPIO 5 */ | ||
337 | #define GPIO5_REG32(offset) __REG32((OMAP24XX_GPIO5_BASE + (offset))) | ||
338 | #define GPIO5_IRQENABLE1 GPIO5_REG32(0x01C) | ||
339 | #define GPIO5_IRQSTATUS1 GPIO5_REG32(0x018) | ||
340 | #define GPIO5_IRQENABLE2 GPIO5_REG32(0x02C) | ||
341 | #define GPIO5_IRQSTATUS2 GPIO5_REG32(0x028) | ||
342 | #define GPIO5_WAKEUPENABLE GPIO5_REG32(0x020) | ||
343 | #define GPIO5_RISINGDETECT GPIO5_REG32(0x048) | ||
344 | #define GPIO5_FALLINGDETECT GPIO5_REG32(0x04C) | ||
345 | #define GPIO5_DATAIN GPIO5_REG32(0x038) | ||
346 | #define GPIO5_OE GPIO5_REG32(0x034) | ||
347 | #define GPIO5_DATAOUT GPIO5_REG32(0x03C) | ||
348 | #define GPIO5_DEBOUNCENABLE GPIO5_REG32(0x050) | ||
349 | #define GPIO5_DEBOUNCINGTIME GPIO5_REG32(0x054) | ||
350 | #endif | ||
314 | 351 | ||
315 | /* IO CONFIG */ | 352 | /* IO CONFIG */ |
316 | #define CONTROL_BASE (OMAP24XX_CTRL_BASE) | 353 | #define OMAP24XX_CTRL_BASE (L4_24XX_BASE) |
317 | #define CONTROL_REG32(offset) __REG32(CONTROL_BASE + (offset)) | 354 | #define CONTROL_REG32(offset) __REG32(OMAP24XX_CTRL_BASE + (offset)) |
318 | 355 | ||
319 | #define CONTROL_PADCONF_SPI1_NCS2 CONTROL_REG32(0x104) | 356 | #define CONTROL_PADCONF_SPI1_NCS2 CONTROL_REG32(0x104) |
320 | #define CONTROL_PADCONF_SYS_XTALOUT CONTROL_REG32(0x134) | 357 | #define CONTROL_PADCONF_SYS_XTALOUT CONTROL_REG32(0x134) |
@@ -322,15 +359,18 @@ | |||
322 | #define CONTROL_PADCONF_MCBSP1_DX CONTROL_REG32(0x10C) | 359 | #define CONTROL_PADCONF_MCBSP1_DX CONTROL_REG32(0x10C) |
323 | #define CONTROL_PADCONF_GPMC_NCS4 CONTROL_REG32(0x090) | 360 | #define CONTROL_PADCONF_GPMC_NCS4 CONTROL_REG32(0x090) |
324 | #define CONTROL_PADCONF_DSS_D5 CONTROL_REG32(0x0B8) | 361 | #define CONTROL_PADCONF_DSS_D5 CONTROL_REG32(0x0B8) |
325 | #define CONTROL_PADCONF_DSS_D9 CONTROL_REG32(0x0BC) | 362 | #define CONTROL_PADCONF_DSS_D9 CONTROL_REG32(0x0BC) /* 2420 */ |
326 | #define CONTROL_PADCONF_DSS_D13 CONTROL_REG32(0x0C0) | 363 | #define CONTROL_PADCONF_DSS_D13 CONTROL_REG32(0x0C0) |
327 | #define CONTROL_PADCONF_DSS_VSYNC CONTROL_REG32(0x0CC) | 364 | #define CONTROL_PADCONF_DSS_VSYNC CONTROL_REG32(0x0CC) |
365 | #define CONTROL_PADCONF_SYS_NIRQW0 CONTROL_REG32(0x0BC) /* 2430 */ | ||
366 | #define CONTROL_PADCONF_SSI1_FLAG_TX CONTROL_REG32(0x108) /* 2430 */ | ||
328 | 367 | ||
329 | /* CONTROL */ | 368 | /* CONTROL */ |
330 | #define CONTROL_DEVCONF CONTROL_REG32(0x274) | 369 | #define CONTROL_DEVCONF CONTROL_REG32(0x274) |
370 | #define CONTROL_DEVCONF1 CONTROL_REG32(0x2E8) | ||
331 | 371 | ||
332 | /* INTERRUPT CONTROLLER */ | 372 | /* INTERRUPT CONTROLLER */ |
333 | #define INTC_BASE (OMAP24XX_L4_IO_BASE+0xfe000) | 373 | #define INTC_BASE ((L4_24XX_BASE) + 0xfe000) |
334 | #define INTC_REG32(offset) __REG32(INTC_BASE + (offset)) | 374 | #define INTC_REG32(offset) __REG32(INTC_BASE + (offset)) |
335 | 375 | ||
336 | #define INTC1_U_BASE INTC_REG32(0x000) | 376 | #define INTC1_U_BASE INTC_REG32(0x000) |
@@ -348,10 +388,12 @@ | |||
348 | #define INTC_ISR_CLEAR2 INTC_REG32(0x0D4) | 388 | #define INTC_ISR_CLEAR2 INTC_REG32(0x0D4) |
349 | #define INTC_SIR_IRQ INTC_REG32(0x040) | 389 | #define INTC_SIR_IRQ INTC_REG32(0x040) |
350 | #define INTC_CONTROL INTC_REG32(0x048) | 390 | #define INTC_CONTROL INTC_REG32(0x048) |
351 | #define INTC_ILR11 INTC_REG32(0x12C) | 391 | #define INTC_ILR11 INTC_REG32(0x12C) /* PRCM on MPU PIC */ |
392 | #define INTC_ILR30 INTC_REG32(0x178) | ||
393 | #define INTC_ILR31 INTC_REG32(0x17C) | ||
352 | #define INTC_ILR32 INTC_REG32(0x180) | 394 | #define INTC_ILR32 INTC_REG32(0x180) |
353 | #define INTC_ILR37 INTC_REG32(0x194) | 395 | #define INTC_ILR37 INTC_REG32(0x194) /* GPIO4 on MPU PIC */ |
354 | #define INTC_SYSCONFIG INTC_REG32(0x010) | 396 | #define INTC_SYSCONFIG INTC_REG32(0x010) /* GPT1 on MPU PIC */ |
355 | 397 | ||
356 | /* RAM FIREWALL */ | 398 | /* RAM FIREWALL */ |
357 | #define RAMFW_BASE (0x68005000) | 399 | #define RAMFW_BASE (0x68005000) |
@@ -373,6 +415,24 @@ | |||
373 | #define GPMC_CONFIG6_0 GPMC_REG32(0x074) | 415 | #define GPMC_CONFIG6_0 GPMC_REG32(0x074) |
374 | #define GPMC_CONFIG7_0 GPMC_REG32(0x078) | 416 | #define GPMC_CONFIG7_0 GPMC_REG32(0x078) |
375 | 417 | ||
418 | /* GPMC CS1 */ | ||
419 | #define GPMC_CONFIG1_1 GPMC_REG32(0x090) | ||
420 | #define GPMC_CONFIG2_1 GPMC_REG32(0x094) | ||
421 | #define GPMC_CONFIG3_1 GPMC_REG32(0x098) | ||
422 | #define GPMC_CONFIG4_1 GPMC_REG32(0x09C) | ||
423 | #define GPMC_CONFIG5_1 GPMC_REG32(0x0a0) | ||
424 | #define GPMC_CONFIG6_1 GPMC_REG32(0x0a4) | ||
425 | #define GPMC_CONFIG7_1 GPMC_REG32(0x0a8) | ||
426 | |||
427 | /* GPMC CS3 */ | ||
428 | #define GPMC_CONFIG1_3 GPMC_REG32(0x0F0) | ||
429 | #define GPMC_CONFIG2_3 GPMC_REG32(0x0F4) | ||
430 | #define GPMC_CONFIG3_3 GPMC_REG32(0x0F8) | ||
431 | #define GPMC_CONFIG4_3 GPMC_REG32(0x0FC) | ||
432 | #define GPMC_CONFIG5_3 GPMC_REG32(0x100) | ||
433 | #define GPMC_CONFIG6_3 GPMC_REG32(0x104) | ||
434 | #define GPMC_CONFIG7_3 GPMC_REG32(0x108) | ||
435 | |||
376 | /* DSS */ | 436 | /* DSS */ |
377 | #define DSS_CONTROL DISP_REG32(0x040) | 437 | #define DSS_CONTROL DISP_REG32(0x040) |
378 | #define DISPC_CONTROL DISP_REG32(0x440) | 438 | #define DISPC_CONTROL DISP_REG32(0x440) |
@@ -405,11 +465,15 @@ | |||
405 | #define DISPC_DATA_CYCLE2 DISP_REG32(0x5D8) | 465 | #define DISPC_DATA_CYCLE2 DISP_REG32(0x5D8) |
406 | #define DISPC_DATA_CYCLE3 DISP_REG32(0x5DC) | 466 | #define DISPC_DATA_CYCLE3 DISP_REG32(0x5DC) |
407 | 467 | ||
408 | /* Wake up define for board */ | 468 | /* HSUSB Suspend */ |
409 | #define GPIO97 (1 << 1) | 469 | #define HSUSB_CTRL __REG8(0x480AC001) |
410 | #define GPIO88 (1 << 24) | 470 | #define USBOTG_POWER __REG32(0x480AC000) |
471 | |||
472 | /* HS MMC */ | ||
473 | #define MMCHS1_SYSCONFIG __REG32(0x4809C010) | ||
474 | #define MMCHS2_SYSCONFIG __REG32(0x480b4010) | ||
411 | 475 | ||
412 | #endif /* __ASSEMBLER__ */ | 476 | #endif /* __ASSEMBLER__ */ |
413 | 477 | ||
414 | #endif | 478 | #endif |
415 | 479 | ||
diff --git a/arch/arm/mach-omap2/prcm.c b/arch/arm/mach-omap2/prcm.c new file mode 100644 index 000000000000..8893479dc7e0 --- /dev/null +++ b/arch/arm/mach-omap2/prcm.c | |||
@@ -0,0 +1,40 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-omap2/prcm.c | ||
3 | * | ||
4 | * OMAP 24xx Power Reset and Clock Management (PRCM) functions | ||
5 | * | ||
6 | * Copyright (C) 2005 Nokia Corporation | ||
7 | * | ||
8 | * Written by Tony Lindgren <tony.lindgren@nokia.com> | ||
9 | * | ||
10 | * Some pieces of code Copyright (C) 2005 Texas Instruments, Inc. | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License version 2 as | ||
14 | * published by the Free Software Foundation. | ||
15 | */ | ||
16 | #include <linux/config.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/clk.h> | ||
20 | |||
21 | #include "prcm-regs.h" | ||
22 | |||
23 | u32 omap_prcm_get_reset_sources(void) | ||
24 | { | ||
25 | return RM_RSTST_WKUP & 0x7f; | ||
26 | } | ||
27 | EXPORT_SYMBOL(omap_prcm_get_reset_sources); | ||
28 | |||
29 | /* Resets clock rates and reboots the system. Only called from system.h */ | ||
30 | void omap_prcm_arch_reset(char mode) | ||
31 | { | ||
32 | u32 rate; | ||
33 | struct clk *vclk, *sclk; | ||
34 | |||
35 | vclk = clk_get(NULL, "virt_prcm_set"); | ||
36 | sclk = clk_get(NULL, "sys_ck"); | ||
37 | rate = clk_get_rate(sclk); | ||
38 | clk_set_rate(vclk, rate); /* go to bypass for OMAP limitation */ | ||
39 | RM_RSTCTRL_WKUP |= 2; | ||
40 | } | ||
diff --git a/arch/arm/mach-omap2/sleep.S b/arch/arm/mach-omap2/sleep.S new file mode 100644 index 000000000000..00299cbeb911 --- /dev/null +++ b/arch/arm/mach-omap2/sleep.S | |||
@@ -0,0 +1,144 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-omap2/sleep.S | ||
3 | * | ||
4 | * (C) Copyright 2004 | ||
5 | * Texas Instruments, <www.ti.com> | ||
6 | * Richard Woodruff <r-woodruff2@ti.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License as | ||
10 | * published by the Free Software Foundation; either version 2 of | ||
11 | * the License, or (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR /PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | ||
21 | * MA 02111-1307 USA | ||
22 | */ | ||
23 | |||
24 | #include <linux/config.h> | ||
25 | #include <linux/linkage.h> | ||
26 | #include <asm/assembler.h> | ||
27 | #include <asm/arch/io.h> | ||
28 | #include <asm/arch/pm.h> | ||
29 | |||
30 | #define A_32KSYNC_CR_V IO_ADDRESS(OMAP_TIMER32K_BASE+0x10) | ||
31 | #define A_PRCM_VOLTCTRL_V IO_ADDRESS(OMAP24XX_PRCM_BASE+0x50) | ||
32 | #define A_PRCM_CLKCFG_CTRL_V IO_ADDRESS(OMAP24XX_PRCM_BASE+0x80) | ||
33 | #define A_CM_CLKEN_PLL_V IO_ADDRESS(OMAP24XX_PRCM_BASE+0x500) | ||
34 | #define A_CM_IDLEST_CKGEN_V IO_ADDRESS(OMAP24XX_PRCM_BASE+0x520) | ||
35 | #define A_CM_CLKSEL1_PLL_V IO_ADDRESS(OMAP24XX_PRCM_BASE+0x540) | ||
36 | #define A_CM_CLKSEL2_PLL_V IO_ADDRESS(OMAP24XX_PRCM_BASE+0x544) | ||
37 | |||
38 | #define A_SDRC_DLLA_CTRL_V IO_ADDRESS(OMAP24XX_SDRC_BASE+0x60) | ||
39 | #define A_SDRC_POWER_V IO_ADDRESS(OMAP24XX_SDRC_BASE+0x70) | ||
40 | #define A_SDRC_RFR_CTRL_V IO_ADDRESS(OMAP24XX_SDRC_BASE+0xA4) | ||
41 | #define A_SDRC0_V (0xC0000000) | ||
42 | #define A_SDRC_MANUAL_V IO_ADDRESS(OMAP24XX_SDRC_BASE+0xA8) | ||
43 | |||
44 | .text | ||
45 | |||
46 | /* | ||
47 | * Forces OMAP into idle state | ||
48 | * | ||
49 | * omap24xx_idle_loop_suspend() - This bit of code just executes the WFI | ||
50 | * for normal idles. | ||
51 | * | ||
52 | * Note: This code get's copied to internal SRAM at boot. When the OMAP | ||
53 | * wakes up it continues execution at the point it went to sleep. | ||
54 | */ | ||
55 | ENTRY(omap24xx_idle_loop_suspend) | ||
56 | stmfd sp!, {r0, lr} @ save registers on stack | ||
57 | mov r0, #0 @ clear for mcr setup | ||
58 | mcr p15, 0, r0, c7, c0, 4 @ wait for interrupt | ||
59 | ldmfd sp!, {r0, pc} @ restore regs and return | ||
60 | |||
61 | ENTRY(omap24xx_idle_loop_suspend_sz) | ||
62 | .word . - omap24xx_idle_loop_suspend | ||
63 | |||
64 | /* | ||
65 | * omap242x_cpu_suspend() - Forces OMAP into deep sleep state by completing | ||
66 | * SDRC shutdown then ARM shutdown. Upon wake MPU is back on so just restore | ||
67 | * SDRC. | ||
68 | * | ||
69 | * Input: | ||
70 | * R0 : DLL ctrl value pre-Sleep | ||
71 | * R1 : Processor+Revision | ||
72 | * 2420: 0x21 = 242xES1, 0x26 = 242xES2.2 | ||
73 | * 2430: 0x31 = 2430ES1, 0x32 = 2430ES2 | ||
74 | * | ||
75 | * The if the DPLL is going to AutoIdle. It seems like the DPLL may be back on | ||
76 | * when we get called, but the DLL probably isn't. We will wait a bit more in | ||
77 | * case the DPLL isn't quite there yet. The code will wait on DLL for DDR even | ||
78 | * if in unlocked mode. | ||
79 | * | ||
80 | * For less than 242x-ES2.2 upon wake from a sleep mode where the external | ||
81 | * oscillator was stopped, a timing bug exists where a non-stabilized 12MHz | ||
82 | * clock can pass into the PRCM can cause problems at DSP and IVA. | ||
83 | * To work around this the code will switch to the 32kHz source prior to sleep. | ||
84 | * Post sleep we will shift back to using the DPLL. Apparently, | ||
85 | * CM_IDLEST_CLKGEN does not reflect the full clock change so you need to wait | ||
86 | * 3x12MHz + 3x32kHz clocks for a full switch. | ||
87 | * | ||
88 | * The DLL load value is not kept in RETENTION or OFF. It needs to be restored | ||
89 | * at wake | ||
90 | */ | ||
91 | ENTRY(omap24xx_cpu_suspend) | ||
92 | stmfd sp!, {r0 - r12, lr} @ save registers on stack | ||
93 | mov r3, #0x0 @ clear for mrc call | ||
94 | mcr p15, 0, r3, c7, c10, 4 @ memory barrier, hope SDR/DDR finished | ||
95 | nop | ||
96 | nop | ||
97 | ldr r3, A_SDRC_POWER @ addr of sdrc power | ||
98 | ldr r4, [r3] @ value of sdrc power | ||
99 | orr r4, r4, #0x40 @ enable self refresh on idle req | ||
100 | mov r5, #0x2000 @ set delay (DPLL relock + DLL relock) | ||
101 | str r4, [r3] @ make it so | ||
102 | mov r2, #0 | ||
103 | nop | ||
104 | mcr p15, 0, r2, c7, c0, 4 @ wait for interrupt | ||
105 | nop | ||
106 | loop: | ||
107 | subs r5, r5, #0x1 @ awake, wait just a bit | ||
108 | bne loop | ||
109 | |||
110 | /* The DPLL has on before we take the DDR out of self refresh */ | ||
111 | bic r4, r4, #0x40 @ now clear self refresh bit. | ||
112 | str r4, [r3] @ put vlaue back. | ||
113 | ldr r4, A_SDRC0 @ make a clock happen | ||
114 | ldr r4, [r4] | ||
115 | nop @ start auto refresh only after clk ok | ||
116 | movs r0, r0 @ see if DDR or SDR | ||
117 | ldrne r1, A_SDRC_DLLA_CTRL_S @ get addr of DLL ctrl | ||
118 | strne r0, [r1] @ rewrite DLLA to force DLL reload | ||
119 | addne r1, r1, #0x8 @ move to DLLB | ||
120 | strne r0, [r1] @ rewrite DLLB to force DLL reload | ||
121 | |||
122 | mov r5, #0x1000 | ||
123 | loop2: | ||
124 | subs r5, r5, #0x1 | ||
125 | bne loop2 | ||
126 | /* resume*/ | ||
127 | ldmfd sp!, {r0 - r12, pc} @ restore regs and return | ||
128 | |||
129 | A_SDRC_POWER: | ||
130 | .word A_SDRC_POWER_V | ||
131 | A_SDRC0: | ||
132 | .word A_SDRC0_V | ||
133 | A_CM_CLKSEL2_PLL_S: | ||
134 | .word A_CM_CLKSEL2_PLL_V | ||
135 | A_CM_CLKEN_PLL: | ||
136 | .word A_CM_CLKEN_PLL_V | ||
137 | A_SDRC_DLLA_CTRL_S: | ||
138 | .word A_SDRC_DLLA_CTRL_V | ||
139 | A_SDRC_MANUAL_S: | ||
140 | .word A_SDRC_MANUAL_V | ||
141 | |||
142 | ENTRY(omap24xx_cpu_suspend_sz) | ||
143 | .word . - omap24xx_cpu_suspend | ||
144 | |||
diff --git a/arch/arm/mach-omap2/sram-fn.S b/arch/arm/mach-omap2/sram-fn.S index 2a869e203342..d261e4ff4d9b 100644 --- a/arch/arm/mach-omap2/sram-fn.S +++ b/arch/arm/mach-omap2/sram-fn.S | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/arm/mach-omap1/sram.S | 2 | * linux/arch/arm/mach-omap2/sram.S |
3 | * | 3 | * |
4 | * Omap2 specific functions that need to be run in internal SRAM | 4 | * Omap2 specific functions that need to be run in internal SRAM |
5 | * | 5 | * |
@@ -28,7 +28,7 @@ | |||
28 | #include <asm/arch/io.h> | 28 | #include <asm/arch/io.h> |
29 | #include <asm/hardware.h> | 29 | #include <asm/hardware.h> |
30 | 30 | ||
31 | #include <asm/arch/prcm.h> | 31 | #include "prcm-regs.h" |
32 | 32 | ||
33 | #define TIMER_32KSYNCT_CR_V IO_ADDRESS(OMAP24XX_32KSYNCT_BASE + 0x010) | 33 | #define TIMER_32KSYNCT_CR_V IO_ADDRESS(OMAP24XX_32KSYNCT_BASE + 0x010) |
34 | 34 | ||
diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c index b45560a8f6c4..a042473deedd 100644 --- a/arch/arm/mach-pxa/poodle.c +++ b/arch/arm/mach-pxa/poodle.c | |||
@@ -307,6 +307,10 @@ static void __init fixup_poodle(struct machine_desc *desc, | |||
307 | struct tag *tags, char **cmdline, struct meminfo *mi) | 307 | struct tag *tags, char **cmdline, struct meminfo *mi) |
308 | { | 308 | { |
309 | sharpsl_save_param(); | 309 | sharpsl_save_param(); |
310 | mi->nr_banks=1; | ||
311 | mi->bank[0].start = 0xa0000000; | ||
312 | mi->bank[0].node = 0; | ||
313 | mi->bank[0].size = (32*1024*1024); | ||
310 | } | 314 | } |
311 | 315 | ||
312 | MACHINE_START(POODLE, "SHARP Poodle") | 316 | MACHINE_START(POODLE, "SHARP Poodle") |
diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig index ed07c4149d82..ce7d81000695 100644 --- a/arch/arm/mach-s3c2410/Kconfig +++ b/arch/arm/mach-s3c2410/Kconfig | |||
@@ -50,9 +50,15 @@ config MACH_N30 | |||
50 | 50 | ||
51 | <http://zoo.weinigel.se/n30>. | 51 | <http://zoo.weinigel.se/n30>. |
52 | 52 | ||
53 | config MACH_SMDK | ||
54 | bool | ||
55 | help | ||
56 | Common machine code for SMDK2410 and SMDK2440 | ||
57 | |||
53 | config ARCH_SMDK2410 | 58 | config ARCH_SMDK2410 |
54 | bool "SMDK2410/A9M2410" | 59 | bool "SMDK2410/A9M2410" |
55 | select CPU_S3C2410 | 60 | select CPU_S3C2410 |
61 | select MACH_SMDK | ||
56 | help | 62 | help |
57 | Say Y here if you are using the SMDK2410 or the derived module A9M2410 | 63 | Say Y here if you are using the SMDK2410 or the derived module A9M2410 |
58 | <http://www.fsforth.de> | 64 | <http://www.fsforth.de> |
@@ -60,6 +66,7 @@ config ARCH_SMDK2410 | |||
60 | config ARCH_S3C2440 | 66 | config ARCH_S3C2440 |
61 | bool "SMDK2440" | 67 | bool "SMDK2440" |
62 | select CPU_S3C2440 | 68 | select CPU_S3C2440 |
69 | select MACH_SMDK | ||
63 | help | 70 | help |
64 | Say Y here if you are using the SMDK2440. | 71 | Say Y here if you are using the SMDK2440. |
65 | 72 | ||
diff --git a/arch/arm/mach-s3c2410/Makefile b/arch/arm/mach-s3c2410/Makefile index 1b3b476e5637..3e5712db6b52 100644 --- a/arch/arm/mach-s3c2410/Makefile +++ b/arch/arm/mach-s3c2410/Makefile | |||
@@ -48,3 +48,5 @@ obj-$(CONFIG_MACH_VR1000) += mach-vr1000.o usb-simtec.o | |||
48 | obj-$(CONFIG_MACH_RX3715) += mach-rx3715.o | 48 | obj-$(CONFIG_MACH_RX3715) += mach-rx3715.o |
49 | obj-$(CONFIG_MACH_OTOM) += mach-otom.o | 49 | obj-$(CONFIG_MACH_OTOM) += mach-otom.o |
50 | obj-$(CONFIG_MACH_NEXCODER_2440) += mach-nexcoder.o | 50 | obj-$(CONFIG_MACH_NEXCODER_2440) += mach-nexcoder.o |
51 | |||
52 | obj-$(CONFIG_MACH_SMDK) += common-smdk.o \ No newline at end of file | ||
diff --git a/arch/arm/mach-s3c2410/clock.c b/arch/arm/mach-s3c2410/clock.c index fec02c92f95f..b7f85e6d6b76 100644 --- a/arch/arm/mach-s3c2410/clock.c +++ b/arch/arm/mach-s3c2410/clock.c | |||
@@ -249,7 +249,7 @@ static int s3c24xx_upll_enable(struct clk *clk, int enable) | |||
249 | 249 | ||
250 | /* if we started the UPLL, then allow to settle */ | 250 | /* if we started the UPLL, then allow to settle */ |
251 | 251 | ||
252 | if (enable && !(orig & S3C2410_CLKSLOW_UCLK_OFF)) | 252 | if (enable && (orig & S3C2410_CLKSLOW_UCLK_OFF)) |
253 | udelay(200); | 253 | udelay(200); |
254 | 254 | ||
255 | return 0; | 255 | return 0; |
diff --git a/arch/arm/mach-s3c2410/common-smdk.c b/arch/arm/mach-s3c2410/common-smdk.c new file mode 100644 index 000000000000..36b8291b5e03 --- /dev/null +++ b/arch/arm/mach-s3c2410/common-smdk.c | |||
@@ -0,0 +1,134 @@ | |||
1 | /* linux/arch/arm/mach-s3c2410/common-smdk.c | ||
2 | * | ||
3 | * Copyright (c) 2006 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * | ||
6 | * Common code for SMDK2410 and SMDK2440 boards | ||
7 | * | ||
8 | * http://www.fluff.org/ben/smdk2440/ | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/types.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/list.h> | ||
19 | #include <linux/timer.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | |||
23 | #include <linux/mtd/mtd.h> | ||
24 | #include <linux/mtd/nand.h> | ||
25 | #include <linux/mtd/nand_ecc.h> | ||
26 | #include <linux/mtd/partitions.h> | ||
27 | |||
28 | #include <asm/mach/arch.h> | ||
29 | #include <asm/mach/map.h> | ||
30 | #include <asm/mach/irq.h> | ||
31 | |||
32 | #include <asm/hardware.h> | ||
33 | #include <asm/io.h> | ||
34 | #include <asm/irq.h> | ||
35 | |||
36 | #include <asm/arch/regs-gpio.h> | ||
37 | |||
38 | #include <asm/arch/nand.h> | ||
39 | |||
40 | #include "devs.h" | ||
41 | #include "pm.h" | ||
42 | |||
43 | /* NAND parititon from 2.4.18-swl5 */ | ||
44 | |||
45 | static struct mtd_partition smdk_default_nand_part[] = { | ||
46 | [0] = { | ||
47 | .name = "Boot Agent", | ||
48 | .size = SZ_16K, | ||
49 | .offset = 0, | ||
50 | }, | ||
51 | [1] = { | ||
52 | .name = "S3C2410 flash parition 1", | ||
53 | .offset = 0, | ||
54 | .size = SZ_2M, | ||
55 | }, | ||
56 | [2] = { | ||
57 | .name = "S3C2410 flash partition 2", | ||
58 | .offset = SZ_4M, | ||
59 | .size = SZ_4M, | ||
60 | }, | ||
61 | [3] = { | ||
62 | .name = "S3C2410 flash partition 3", | ||
63 | .offset = SZ_8M, | ||
64 | .size = SZ_2M, | ||
65 | }, | ||
66 | [4] = { | ||
67 | .name = "S3C2410 flash partition 4", | ||
68 | .offset = SZ_1M * 10, | ||
69 | .size = SZ_4M, | ||
70 | }, | ||
71 | [5] = { | ||
72 | .name = "S3C2410 flash partition 5", | ||
73 | .offset = SZ_1M * 14, | ||
74 | .size = SZ_1M * 10, | ||
75 | }, | ||
76 | [6] = { | ||
77 | .name = "S3C2410 flash partition 6", | ||
78 | .offset = SZ_1M * 24, | ||
79 | .size = SZ_1M * 24, | ||
80 | }, | ||
81 | [7] = { | ||
82 | .name = "S3C2410 flash partition 7", | ||
83 | .offset = SZ_1M * 48, | ||
84 | .size = SZ_16M, | ||
85 | } | ||
86 | }; | ||
87 | |||
88 | static struct s3c2410_nand_set smdk_nand_sets[] = { | ||
89 | [0] = { | ||
90 | .name = "NAND", | ||
91 | .nr_chips = 1, | ||
92 | .nr_partitions = ARRAY_SIZE(smdk_default_nand_part), | ||
93 | .partitions = smdk_default_nand_part, | ||
94 | }, | ||
95 | }; | ||
96 | |||
97 | /* choose a set of timings which should suit most 512Mbit | ||
98 | * chips and beyond. | ||
99 | */ | ||
100 | |||
101 | static struct s3c2410_platform_nand smdk_nand_info = { | ||
102 | .tacls = 20, | ||
103 | .twrph0 = 60, | ||
104 | .twrph1 = 20, | ||
105 | .nr_sets = ARRAY_SIZE(smdk_nand_sets), | ||
106 | .sets = smdk_nand_sets, | ||
107 | }; | ||
108 | |||
109 | /* devices we initialise */ | ||
110 | |||
111 | static struct platform_device __initdata *smdk_devs[] = { | ||
112 | &s3c_device_nand, | ||
113 | }; | ||
114 | |||
115 | void __init smdk_machine_init(void) | ||
116 | { | ||
117 | /* Configure the LEDs (even if we have no LED support)*/ | ||
118 | |||
119 | s3c2410_gpio_cfgpin(S3C2410_GPF4, S3C2410_GPF4_OUTP); | ||
120 | s3c2410_gpio_cfgpin(S3C2410_GPF5, S3C2410_GPF5_OUTP); | ||
121 | s3c2410_gpio_cfgpin(S3C2410_GPF6, S3C2410_GPF6_OUTP); | ||
122 | s3c2410_gpio_cfgpin(S3C2410_GPF7, S3C2410_GPF7_OUTP); | ||
123 | |||
124 | s3c2410_gpio_setpin(S3C2410_GPF4, 1); | ||
125 | s3c2410_gpio_setpin(S3C2410_GPF5, 1); | ||
126 | s3c2410_gpio_setpin(S3C2410_GPF6, 1); | ||
127 | s3c2410_gpio_setpin(S3C2410_GPF7, 1); | ||
128 | |||
129 | s3c_device_nand.dev.platform_data = &smdk_nand_info; | ||
130 | |||
131 | platform_add_devices(smdk_devs, ARRAY_SIZE(smdk_devs)); | ||
132 | |||
133 | s3c2410_pm_init(); | ||
134 | } | ||
diff --git a/arch/arm/mach-s3c2410/common-smdk.h b/arch/arm/mach-s3c2410/common-smdk.h new file mode 100644 index 000000000000..0e3a3be330a3 --- /dev/null +++ b/arch/arm/mach-s3c2410/common-smdk.h | |||
@@ -0,0 +1,15 @@ | |||
1 | /* linux/arch/arm/mach-s3c2410/common-smdk.h | ||
2 | * | ||
3 | * Copyright (c) 2006 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * | ||
6 | * Common code for SMDK2410 and SMDK2440 boards | ||
7 | * | ||
8 | * http://www.fluff.org/ben/smdk2440/ | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | extern void smdk_machine_init(void); | ||
diff --git a/arch/arm/mach-s3c2410/mach-anubis.c b/arch/arm/mach-s3c2410/mach-anubis.c index 3e327b8e46be..cc97fbf66291 100644 --- a/arch/arm/mach-s3c2410/mach-anubis.c +++ b/arch/arm/mach-s3c2410/mach-anubis.c | |||
@@ -232,8 +232,8 @@ static void anubis_nand_select(struct s3c2410_nand_set *set, int slot) | |||
232 | 232 | ||
233 | static struct s3c2410_platform_nand anubis_nand_info = { | 233 | static struct s3c2410_platform_nand anubis_nand_info = { |
234 | .tacls = 25, | 234 | .tacls = 25, |
235 | .twrph0 = 80, | 235 | .twrph0 = 55, |
236 | .twrph1 = 80, | 236 | .twrph1 = 40, |
237 | .nr_sets = ARRAY_SIZE(anubis_nand_sets), | 237 | .nr_sets = ARRAY_SIZE(anubis_nand_sets), |
238 | .sets = anubis_nand_sets, | 238 | .sets = anubis_nand_sets, |
239 | .select_chip = anubis_nand_select, | 239 | .select_chip = anubis_nand_select, |
diff --git a/arch/arm/mach-s3c2410/mach-rx3715.c b/arch/arm/mach-s3c2410/mach-rx3715.c index 0260ed5ab946..306afc1d7cd3 100644 --- a/arch/arm/mach-s3c2410/mach-rx3715.c +++ b/arch/arm/mach-s3c2410/mach-rx3715.c | |||
@@ -32,6 +32,11 @@ | |||
32 | #include <linux/serial_core.h> | 32 | #include <linux/serial_core.h> |
33 | #include <linux/serial.h> | 33 | #include <linux/serial.h> |
34 | 34 | ||
35 | #include <linux/mtd/mtd.h> | ||
36 | #include <linux/mtd/nand.h> | ||
37 | #include <linux/mtd/nand_ecc.h> | ||
38 | #include <linux/mtd/partitions.h> | ||
39 | |||
35 | #include <asm/mach/arch.h> | 40 | #include <asm/mach/arch.h> |
36 | #include <asm/mach/map.h> | 41 | #include <asm/mach/map.h> |
37 | #include <asm/mach/irq.h> | 42 | #include <asm/mach/irq.h> |
@@ -46,6 +51,7 @@ | |||
46 | #include <asm/arch/regs-gpio.h> | 51 | #include <asm/arch/regs-gpio.h> |
47 | #include <asm/arch/regs-lcd.h> | 52 | #include <asm/arch/regs-lcd.h> |
48 | 53 | ||
54 | #include <asm/arch/nand.h> | ||
49 | #include <asm/arch/fb.h> | 55 | #include <asm/arch/fb.h> |
50 | 56 | ||
51 | #include "clock.h" | 57 | #include "clock.h" |
@@ -170,12 +176,39 @@ static struct s3c2410fb_mach_info rx3715_lcdcfg __initdata = { | |||
170 | }, | 176 | }, |
171 | }; | 177 | }; |
172 | 178 | ||
179 | static struct mtd_partition rx3715_nand_part[] = { | ||
180 | [0] = { | ||
181 | .name = "Whole Flash", | ||
182 | .offset = 0, | ||
183 | .size = MTDPART_SIZ_FULL, | ||
184 | .mask_flags = MTD_WRITEABLE, | ||
185 | } | ||
186 | }; | ||
187 | |||
188 | static struct s3c2410_nand_set rx3715_nand_sets[] = { | ||
189 | [0] = { | ||
190 | .name = "Internal", | ||
191 | .nr_chips = 1, | ||
192 | .nr_partitions = ARRAY_SIZE(rx3715_nand_part), | ||
193 | .partitions = rx3715_nand_part, | ||
194 | }, | ||
195 | }; | ||
196 | |||
197 | static struct s3c2410_platform_nand rx3715_nand_info = { | ||
198 | .tacls = 25, | ||
199 | .twrph0 = 50, | ||
200 | .twrph1 = 15, | ||
201 | .nr_sets = ARRAY_SIZE(rx3715_nand_sets), | ||
202 | .sets = rx3715_nand_sets, | ||
203 | }; | ||
204 | |||
173 | static struct platform_device *rx3715_devices[] __initdata = { | 205 | static struct platform_device *rx3715_devices[] __initdata = { |
174 | &s3c_device_usb, | 206 | &s3c_device_usb, |
175 | &s3c_device_lcd, | 207 | &s3c_device_lcd, |
176 | &s3c_device_wdt, | 208 | &s3c_device_wdt, |
177 | &s3c_device_i2c, | 209 | &s3c_device_i2c, |
178 | &s3c_device_iis, | 210 | &s3c_device_iis, |
211 | &s3c_device_nand, | ||
179 | }; | 212 | }; |
180 | 213 | ||
181 | static struct s3c24xx_board rx3715_board __initdata = { | 214 | static struct s3c24xx_board rx3715_board __initdata = { |
@@ -185,6 +218,8 @@ static struct s3c24xx_board rx3715_board __initdata = { | |||
185 | 218 | ||
186 | static void __init rx3715_map_io(void) | 219 | static void __init rx3715_map_io(void) |
187 | { | 220 | { |
221 | s3c_device_nand.dev.platform_data = &rx3715_nand_info; | ||
222 | |||
188 | s3c24xx_init_io(rx3715_iodesc, ARRAY_SIZE(rx3715_iodesc)); | 223 | s3c24xx_init_io(rx3715_iodesc, ARRAY_SIZE(rx3715_iodesc)); |
189 | s3c24xx_init_clocks(16934000); | 224 | s3c24xx_init_clocks(16934000); |
190 | s3c24xx_init_uarts(rx3715_uartcfgs, ARRAY_SIZE(rx3715_uartcfgs)); | 225 | s3c24xx_init_uarts(rx3715_uartcfgs, ARRAY_SIZE(rx3715_uartcfgs)); |
diff --git a/arch/arm/mach-s3c2410/mach-smdk2410.c b/arch/arm/mach-s3c2410/mach-smdk2410.c index 1e76e1fdfcea..2db932d72c5a 100644 --- a/arch/arm/mach-s3c2410/mach-smdk2410.c +++ b/arch/arm/mach-s3c2410/mach-smdk2410.c | |||
@@ -28,7 +28,8 @@ | |||
28 | * Ben Dooks <ben@simtec.co.uk> | 28 | * Ben Dooks <ben@simtec.co.uk> |
29 | * | 29 | * |
30 | * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA | 30 | * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA |
31 | * 20-Sep-2005 BJD Added static to non-exported items | 31 | * 20-Sep-2005 BJD Added static to non-exported items |
32 | * 01-Apr-2006 BJD Moved init code to common smdk | ||
32 | * | 33 | * |
33 | ***********************************************************************/ | 34 | ***********************************************************************/ |
34 | 35 | ||
@@ -54,6 +55,8 @@ | |||
54 | #include "devs.h" | 55 | #include "devs.h" |
55 | #include "cpu.h" | 56 | #include "cpu.h" |
56 | 57 | ||
58 | #include "common-smdk.h" | ||
59 | |||
57 | static struct map_desc smdk2410_iodesc[] __initdata = { | 60 | static struct map_desc smdk2410_iodesc[] __initdata = { |
58 | /* nothing here yet */ | 61 | /* nothing here yet */ |
59 | }; | 62 | }; |
@@ -107,11 +110,6 @@ static void __init smdk2410_map_io(void) | |||
107 | s3c24xx_set_board(&smdk2410_board); | 110 | s3c24xx_set_board(&smdk2410_board); |
108 | } | 111 | } |
109 | 112 | ||
110 | static void __init smdk2410_init_irq(void) | ||
111 | { | ||
112 | s3c24xx_init_irq(); | ||
113 | } | ||
114 | |||
115 | MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switch | 113 | MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switch |
116 | * to SMDK2410 */ | 114 | * to SMDK2410 */ |
117 | /* Maintainer: Jonas Dietsche */ | 115 | /* Maintainer: Jonas Dietsche */ |
@@ -119,7 +117,8 @@ MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switc | |||
119 | .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, | 117 | .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, |
120 | .boot_params = S3C2410_SDRAM_PA + 0x100, | 118 | .boot_params = S3C2410_SDRAM_PA + 0x100, |
121 | .map_io = smdk2410_map_io, | 119 | .map_io = smdk2410_map_io, |
122 | .init_irq = smdk2410_init_irq, | 120 | .init_irq = s3c24xx_init_irq, |
121 | .init_machine = smdk_machine_init, | ||
123 | .timer = &s3c24xx_timer, | 122 | .timer = &s3c24xx_timer, |
124 | MACHINE_END | 123 | MACHINE_END |
125 | 124 | ||
diff --git a/arch/arm/mach-s3c2410/mach-smdk2440.c b/arch/arm/mach-s3c2410/mach-smdk2440.c index f4315721c3b8..5fffd1d51047 100644 --- a/arch/arm/mach-s3c2410/mach-smdk2440.c +++ b/arch/arm/mach-s3c2410/mach-smdk2440.c | |||
@@ -53,7 +53,8 @@ | |||
53 | #include "clock.h" | 53 | #include "clock.h" |
54 | #include "devs.h" | 54 | #include "devs.h" |
55 | #include "cpu.h" | 55 | #include "cpu.h" |
56 | #include "pm.h" | 56 | |
57 | #include "common-smdk.h" | ||
57 | 58 | ||
58 | static struct map_desc smdk2440_iodesc[] __initdata = { | 59 | static struct map_desc smdk2440_iodesc[] __initdata = { |
59 | /* ISA IO Space map (memory space selected by A24) */ | 60 | /* ISA IO Space map (memory space selected by A24) */ |
@@ -197,21 +198,9 @@ static void __init smdk2440_map_io(void) | |||
197 | 198 | ||
198 | static void __init smdk2440_machine_init(void) | 199 | static void __init smdk2440_machine_init(void) |
199 | { | 200 | { |
200 | /* Configure the LEDs (even if we have no LED support)*/ | ||
201 | |||
202 | s3c2410_gpio_cfgpin(S3C2410_GPF4, S3C2410_GPF4_OUTP); | ||
203 | s3c2410_gpio_cfgpin(S3C2410_GPF5, S3C2410_GPF5_OUTP); | ||
204 | s3c2410_gpio_cfgpin(S3C2410_GPF6, S3C2410_GPF6_OUTP); | ||
205 | s3c2410_gpio_cfgpin(S3C2410_GPF7, S3C2410_GPF7_OUTP); | ||
206 | |||
207 | s3c2410_gpio_setpin(S3C2410_GPF4, 0); | ||
208 | s3c2410_gpio_setpin(S3C2410_GPF5, 0); | ||
209 | s3c2410_gpio_setpin(S3C2410_GPF6, 0); | ||
210 | s3c2410_gpio_setpin(S3C2410_GPF7, 0); | ||
211 | |||
212 | s3c24xx_fb_set_platdata(&smdk2440_lcd_cfg); | 201 | s3c24xx_fb_set_platdata(&smdk2440_lcd_cfg); |
213 | 202 | ||
214 | s3c2410_pm_init(); | 203 | smdk_machine_init(); |
215 | } | 204 | } |
216 | 205 | ||
217 | MACHINE_START(S3C2440, "SMDK2440") | 206 | MACHINE_START(S3C2440, "SMDK2440") |
diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c index 102454082474..676b5c5b75bb 100644 --- a/arch/arm/mach-sa1100/collie.c +++ b/arch/arm/mach-sa1100/collie.c | |||
@@ -11,7 +11,8 @@ | |||
11 | * published by the Free Software Foundation. | 11 | * published by the Free Software Foundation. |
12 | * | 12 | * |
13 | * ChangeLog: | 13 | * ChangeLog: |
14 | * 03-06-2004 John Lenz <jelenz@wisc.edu> | 14 | * 2006 Pavel Machek <pavel@suse.cz> |
15 | * 03-06-2004 John Lenz <lenz@cs.wisc.edu> | ||
15 | * 06-04-2002 Chris Larson <kergoth@digitalnemesis.net> | 16 | * 06-04-2002 Chris Larson <kergoth@digitalnemesis.net> |
16 | * 04-16-2001 Lineo Japan,Inc. ... | 17 | * 04-16-2001 Lineo Japan,Inc. ... |
17 | */ | 18 | */ |
@@ -87,12 +88,75 @@ static struct mcp_plat_data collie_mcp_data = { | |||
87 | .sclk_rate = 11981000, | 88 | .sclk_rate = 11981000, |
88 | }; | 89 | }; |
89 | 90 | ||
91 | #ifdef CONFIG_SHARP_LOCOMO | ||
92 | /* | ||
93 | * low-level UART features. | ||
94 | */ | ||
95 | static struct locomo_dev *uart_dev = NULL; | ||
96 | |||
97 | static void collie_uart_set_mctrl(struct uart_port *port, u_int mctrl) | ||
98 | { | ||
99 | if (!uart_dev) return; | ||
100 | |||
101 | if (mctrl & TIOCM_RTS) | ||
102 | locomo_gpio_write(uart_dev, LOCOMO_GPIO_RTS, 0); | ||
103 | else | ||
104 | locomo_gpio_write(uart_dev, LOCOMO_GPIO_RTS, 1); | ||
105 | |||
106 | if (mctrl & TIOCM_DTR) | ||
107 | locomo_gpio_write(uart_dev, LOCOMO_GPIO_DTR, 0); | ||
108 | else | ||
109 | locomo_gpio_write(uart_dev, LOCOMO_GPIO_DTR, 1); | ||
110 | } | ||
111 | |||
112 | static u_int collie_uart_get_mctrl(struct uart_port *port) | ||
113 | { | ||
114 | int ret = TIOCM_CD; | ||
115 | unsigned int r; | ||
116 | if (!uart_dev) return ret; | ||
117 | |||
118 | r = locomo_gpio_read_output(uart_dev, LOCOMO_GPIO_CTS & LOCOMO_GPIO_DSR); | ||
119 | if (r & LOCOMO_GPIO_CTS) | ||
120 | ret |= TIOCM_CTS; | ||
121 | if (r & LOCOMO_GPIO_DSR) | ||
122 | ret |= TIOCM_DSR; | ||
123 | |||
124 | return ret; | ||
125 | } | ||
90 | 126 | ||
91 | static struct sa1100_port_fns collie_port_fns __initdata = { | 127 | static struct sa1100_port_fns collie_port_fns __initdata = { |
92 | .set_mctrl = collie_uart_set_mctrl, | 128 | .set_mctrl = collie_uart_set_mctrl, |
93 | .get_mctrl = collie_uart_get_mctrl, | 129 | .get_mctrl = collie_uart_get_mctrl, |
94 | }; | 130 | }; |
95 | 131 | ||
132 | static int collie_uart_probe(struct locomo_dev *dev) | ||
133 | { | ||
134 | uart_dev = dev; | ||
135 | return 0; | ||
136 | } | ||
137 | |||
138 | static int collie_uart_remove(struct locomo_dev *dev) | ||
139 | { | ||
140 | uart_dev = NULL; | ||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | static struct locomo_driver collie_uart_driver = { | ||
145 | .drv = { | ||
146 | .name = "collie_uart", | ||
147 | }, | ||
148 | .devid = LOCOMO_DEVID_UART, | ||
149 | .probe = collie_uart_probe, | ||
150 | .remove = collie_uart_remove, | ||
151 | }; | ||
152 | |||
153 | static int __init collie_uart_init(void) { | ||
154 | return locomo_driver_register(&collie_uart_driver); | ||
155 | } | ||
156 | device_initcall(collie_uart_init); | ||
157 | |||
158 | #endif | ||
159 | |||
96 | 160 | ||
97 | static struct resource locomo_resources[] = { | 161 | static struct resource locomo_resources[] = { |
98 | [0] = { | 162 | [0] = { |
@@ -218,6 +282,12 @@ static void __init collie_map_io(void) | |||
218 | { | 282 | { |
219 | sa1100_map_io(); | 283 | sa1100_map_io(); |
220 | iotable_init(collie_io_desc, ARRAY_SIZE(collie_io_desc)); | 284 | iotable_init(collie_io_desc, ARRAY_SIZE(collie_io_desc)); |
285 | |||
286 | #ifdef CONFIG_SHARP_LOCOMO | ||
287 | sa1100_register_uart_fns(&collie_port_fns); | ||
288 | #endif | ||
289 | sa1100_register_uart(0, 3); | ||
290 | sa1100_register_uart(1, 1); | ||
221 | } | 291 | } |
222 | 292 | ||
223 | MACHINE_START(COLLIE, "Sharp-Collie") | 293 | MACHINE_START(COLLIE, "Sharp-Collie") |
diff --git a/arch/arm/mm/consistent.c b/arch/arm/mm/consistent.c index 8a1bfcd50087..50e6b6bfb2e2 100644 --- a/arch/arm/mm/consistent.c +++ b/arch/arm/mm/consistent.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/device.h> | 18 | #include <linux/device.h> |
19 | #include <linux/dma-mapping.h> | 19 | #include <linux/dma-mapping.h> |
20 | 20 | ||
21 | #include <asm/memory.h> | ||
21 | #include <asm/cacheflush.h> | 22 | #include <asm/cacheflush.h> |
22 | #include <asm/tlbflush.h> | 23 | #include <asm/tlbflush.h> |
23 | #include <asm/sizes.h> | 24 | #include <asm/sizes.h> |
@@ -272,6 +273,17 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp, | |||
272 | void * | 273 | void * |
273 | dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp) | 274 | dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp) |
274 | { | 275 | { |
276 | if (arch_is_coherent()) { | ||
277 | void *virt; | ||
278 | |||
279 | virt = kmalloc(size, gfp); | ||
280 | if (!virt) | ||
281 | return NULL; | ||
282 | *handle = virt_to_dma(dev, virt); | ||
283 | |||
284 | return virt; | ||
285 | } | ||
286 | |||
275 | return __dma_alloc(dev, size, handle, gfp, | 287 | return __dma_alloc(dev, size, handle, gfp, |
276 | pgprot_noncached(pgprot_kernel)); | 288 | pgprot_noncached(pgprot_kernel)); |
277 | } | 289 | } |
@@ -350,6 +362,11 @@ void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr | |||
350 | 362 | ||
351 | WARN_ON(irqs_disabled()); | 363 | WARN_ON(irqs_disabled()); |
352 | 364 | ||
365 | if (arch_is_coherent()) { | ||
366 | kfree(cpu_addr); | ||
367 | return; | ||
368 | } | ||
369 | |||
353 | size = PAGE_ALIGN(size); | 370 | size = PAGE_ALIGN(size); |
354 | 371 | ||
355 | spin_lock_irqsave(&consistent_lock, flags); | 372 | spin_lock_irqsave(&consistent_lock, flags); |
diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c index 5e5d05bcad50..f14b2d0f3690 100644 --- a/arch/arm/mm/mm-armv.c +++ b/arch/arm/mm/mm-armv.c | |||
@@ -389,6 +389,17 @@ void __init build_mem_type_table(void) | |||
389 | kern_pgprot = user_pgprot = cp->pte; | 389 | kern_pgprot = user_pgprot = cp->pte; |
390 | 390 | ||
391 | /* | 391 | /* |
392 | * Enable CPU-specific coherency if supported. | ||
393 | * (Only available on XSC3 at the moment.) | ||
394 | */ | ||
395 | if (arch_is_coherent()) { | ||
396 | if (cpu_is_xsc3()) { | ||
397 | mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S; | ||
398 | mem_types[MT_MEMORY].prot_pte |= L_PTE_COHERENT; | ||
399 | } | ||
400 | } | ||
401 | |||
402 | /* | ||
392 | * ARMv6 and above have extended page tables. | 403 | * ARMv6 and above have extended page tables. |
393 | */ | 404 | */ |
394 | if (cpu_arch >= CPU_ARCH_ARMv6 && (cr & CR_XP)) { | 405 | if (cpu_arch >= CPU_ARCH_ARMv6 && (cr & CR_XP)) { |
diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S index b9dfce57c272..80873b36c3f7 100644 --- a/arch/arm/mm/proc-xsc3.S +++ b/arch/arm/mm/proc-xsc3.S | |||
@@ -371,7 +371,7 @@ ENTRY(cpu_xsc3_switch_mm) | |||
371 | ENTRY(cpu_xsc3_set_pte) | 371 | ENTRY(cpu_xsc3_set_pte) |
372 | str r1, [r0], #-2048 @ linux version | 372 | str r1, [r0], #-2048 @ linux version |
373 | 373 | ||
374 | bic r2, r1, #0xff0 | 374 | bic r2, r1, #0xdf0 @ Keep C, B, coherency bits |
375 | orr r2, r2, #PTE_TYPE_EXT @ extended page | 375 | orr r2, r2, #PTE_TYPE_EXT @ extended page |
376 | 376 | ||
377 | eor r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY | 377 | eor r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY |
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index 0887bb2a2551..ec49495e651e 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig | |||
@@ -70,13 +70,13 @@ config OMAP_MPU_TIMER | |||
70 | 70 | ||
71 | config OMAP_32K_TIMER | 71 | config OMAP_32K_TIMER |
72 | bool "Use 32KHz timer" | 72 | bool "Use 32KHz timer" |
73 | depends on ARCH_OMAP16XX | 73 | depends on ARCH_OMAP16XX || ARCH_OMAP24XX |
74 | help | 74 | help |
75 | Select this option if you want to enable the OMAP 32KHz timer. | 75 | Select this option if you want to enable the OMAP 32KHz timer. |
76 | This timer saves power compared to the OMAP_MPU_TIMER, and has | 76 | This timer saves power compared to the OMAP_MPU_TIMER, and has |
77 | support for no tick during idle. The 32KHz timer provides less | 77 | support for no tick during idle. The 32KHz timer provides less |
78 | intra-tick resolution than OMAP_MPU_TIMER. The 32KHz timer is | 78 | intra-tick resolution than OMAP_MPU_TIMER. The 32KHz timer is |
79 | currently only available for OMAP-16xx. | 79 | currently only available for OMAP16XX and 24XX. |
80 | 80 | ||
81 | endchoice | 81 | endchoice |
82 | 82 | ||
diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile index 9ccf1943fc94..2896b4546411 100644 --- a/arch/arm/plat-omap/Makefile +++ b/arch/arm/plat-omap/Makefile | |||
@@ -3,16 +3,16 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | # Common support | 5 | # Common support |
6 | obj-y := common.o sram.o sram-fn.o clock.o devices.o dma.o mux.o gpio.o mcbsp.o usb.o | 6 | obj-y := common.o sram.o sram-fn.o clock.o devices.o dma.o mux.o gpio.o mcbsp.o usb.o fb.o |
7 | obj-m := | 7 | obj-m := |
8 | obj-n := | 8 | obj-n := |
9 | obj- := | 9 | obj- := |
10 | 10 | ||
11 | obj-$(CONFIG_OMAP_32K_TIMER) += timer32k.o | ||
12 | |||
11 | # OCPI interconnect support for 1710, 1610 and 5912 | 13 | # OCPI interconnect support for 1710, 1610 and 5912 |
12 | obj-$(CONFIG_ARCH_OMAP16XX) += ocpi.o | 14 | obj-$(CONFIG_ARCH_OMAP16XX) += ocpi.o |
13 | 15 | ||
14 | # Power Management | ||
15 | obj-$(CONFIG_PM) += pm.o sleep.o | ||
16 | 16 | ||
17 | obj-$(CONFIG_CPU_FREQ) += cpu-omap.o | 17 | obj-$(CONFIG_CPU_FREQ) += cpu-omap.o |
18 | obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o | 18 | obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o |
diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index 3c2bfc0efdaf..06485c193ee3 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/string.h> | 21 | #include <linux/string.h> |
22 | #include <linux/clk.h> | 22 | #include <linux/clk.h> |
23 | #include <linux/mutex.h> | 23 | #include <linux/mutex.h> |
24 | #include <linux/platform_device.h> | ||
24 | 25 | ||
25 | #include <asm/io.h> | 26 | #include <asm/io.h> |
26 | #include <asm/semaphore.h> | 27 | #include <asm/semaphore.h> |
@@ -37,17 +38,37 @@ static struct clk_functions *arch_clock; | |||
37 | * Standard clock functions defined in include/linux/clk.h | 38 | * Standard clock functions defined in include/linux/clk.h |
38 | *-------------------------------------------------------------------------*/ | 39 | *-------------------------------------------------------------------------*/ |
39 | 40 | ||
41 | /* | ||
42 | * Returns a clock. Note that we first try to use device id on the bus | ||
43 | * and clock name. If this fails, we try to use clock name only. | ||
44 | */ | ||
40 | struct clk * clk_get(struct device *dev, const char *id) | 45 | struct clk * clk_get(struct device *dev, const char *id) |
41 | { | 46 | { |
42 | struct clk *p, *clk = ERR_PTR(-ENOENT); | 47 | struct clk *p, *clk = ERR_PTR(-ENOENT); |
48 | int idno; | ||
49 | |||
50 | if (dev == NULL || dev->bus != &platform_bus_type) | ||
51 | idno = -1; | ||
52 | else | ||
53 | idno = to_platform_device(dev)->id; | ||
43 | 54 | ||
44 | mutex_lock(&clocks_mutex); | 55 | mutex_lock(&clocks_mutex); |
56 | |||
57 | list_for_each_entry(p, &clocks, node) { | ||
58 | if (p->id == idno && | ||
59 | strcmp(id, p->name) == 0 && try_module_get(p->owner)) { | ||
60 | clk = p; | ||
61 | break; | ||
62 | } | ||
63 | } | ||
64 | |||
45 | list_for_each_entry(p, &clocks, node) { | 65 | list_for_each_entry(p, &clocks, node) { |
46 | if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) { | 66 | if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) { |
47 | clk = p; | 67 | clk = p; |
48 | break; | 68 | break; |
49 | } | 69 | } |
50 | } | 70 | } |
71 | |||
51 | mutex_unlock(&clocks_mutex); | 72 | mutex_unlock(&clocks_mutex); |
52 | 73 | ||
53 | return clk; | 74 | return clk; |
@@ -59,6 +80,9 @@ int clk_enable(struct clk *clk) | |||
59 | unsigned long flags; | 80 | unsigned long flags; |
60 | int ret = 0; | 81 | int ret = 0; |
61 | 82 | ||
83 | if (clk == NULL || IS_ERR(clk)) | ||
84 | return -EINVAL; | ||
85 | |||
62 | spin_lock_irqsave(&clockfw_lock, flags); | 86 | spin_lock_irqsave(&clockfw_lock, flags); |
63 | if (arch_clock->clk_enable) | 87 | if (arch_clock->clk_enable) |
64 | ret = arch_clock->clk_enable(clk); | 88 | ret = arch_clock->clk_enable(clk); |
@@ -72,6 +96,9 @@ void clk_disable(struct clk *clk) | |||
72 | { | 96 | { |
73 | unsigned long flags; | 97 | unsigned long flags; |
74 | 98 | ||
99 | if (clk == NULL || IS_ERR(clk)) | ||
100 | return; | ||
101 | |||
75 | spin_lock_irqsave(&clockfw_lock, flags); | 102 | spin_lock_irqsave(&clockfw_lock, flags); |
76 | if (arch_clock->clk_disable) | 103 | if (arch_clock->clk_disable) |
77 | arch_clock->clk_disable(clk); | 104 | arch_clock->clk_disable(clk); |
@@ -84,6 +111,9 @@ int clk_get_usecount(struct clk *clk) | |||
84 | unsigned long flags; | 111 | unsigned long flags; |
85 | int ret = 0; | 112 | int ret = 0; |
86 | 113 | ||
114 | if (clk == NULL || IS_ERR(clk)) | ||
115 | return 0; | ||
116 | |||
87 | spin_lock_irqsave(&clockfw_lock, flags); | 117 | spin_lock_irqsave(&clockfw_lock, flags); |
88 | ret = clk->usecount; | 118 | ret = clk->usecount; |
89 | spin_unlock_irqrestore(&clockfw_lock, flags); | 119 | spin_unlock_irqrestore(&clockfw_lock, flags); |
@@ -97,6 +127,9 @@ unsigned long clk_get_rate(struct clk *clk) | |||
97 | unsigned long flags; | 127 | unsigned long flags; |
98 | unsigned long ret = 0; | 128 | unsigned long ret = 0; |
99 | 129 | ||
130 | if (clk == NULL || IS_ERR(clk)) | ||
131 | return 0; | ||
132 | |||
100 | spin_lock_irqsave(&clockfw_lock, flags); | 133 | spin_lock_irqsave(&clockfw_lock, flags); |
101 | ret = clk->rate; | 134 | ret = clk->rate; |
102 | spin_unlock_irqrestore(&clockfw_lock, flags); | 135 | spin_unlock_irqrestore(&clockfw_lock, flags); |
@@ -121,6 +154,9 @@ long clk_round_rate(struct clk *clk, unsigned long rate) | |||
121 | unsigned long flags; | 154 | unsigned long flags; |
122 | long ret = 0; | 155 | long ret = 0; |
123 | 156 | ||
157 | if (clk == NULL || IS_ERR(clk)) | ||
158 | return ret; | ||
159 | |||
124 | spin_lock_irqsave(&clockfw_lock, flags); | 160 | spin_lock_irqsave(&clockfw_lock, flags); |
125 | if (arch_clock->clk_round_rate) | 161 | if (arch_clock->clk_round_rate) |
126 | ret = arch_clock->clk_round_rate(clk, rate); | 162 | ret = arch_clock->clk_round_rate(clk, rate); |
@@ -133,7 +169,10 @@ EXPORT_SYMBOL(clk_round_rate); | |||
133 | int clk_set_rate(struct clk *clk, unsigned long rate) | 169 | int clk_set_rate(struct clk *clk, unsigned long rate) |
134 | { | 170 | { |
135 | unsigned long flags; | 171 | unsigned long flags; |
136 | int ret = 0; | 172 | int ret = -EINVAL; |
173 | |||
174 | if (clk == NULL || IS_ERR(clk)) | ||
175 | return ret; | ||
137 | 176 | ||
138 | spin_lock_irqsave(&clockfw_lock, flags); | 177 | spin_lock_irqsave(&clockfw_lock, flags); |
139 | if (arch_clock->clk_set_rate) | 178 | if (arch_clock->clk_set_rate) |
@@ -147,7 +186,10 @@ EXPORT_SYMBOL(clk_set_rate); | |||
147 | int clk_set_parent(struct clk *clk, struct clk *parent) | 186 | int clk_set_parent(struct clk *clk, struct clk *parent) |
148 | { | 187 | { |
149 | unsigned long flags; | 188 | unsigned long flags; |
150 | int ret = 0; | 189 | int ret = -EINVAL; |
190 | |||
191 | if (clk == NULL || IS_ERR(clk) || parent == NULL || IS_ERR(parent)) | ||
192 | return ret; | ||
151 | 193 | ||
152 | spin_lock_irqsave(&clockfw_lock, flags); | 194 | spin_lock_irqsave(&clockfw_lock, flags); |
153 | if (arch_clock->clk_set_parent) | 195 | if (arch_clock->clk_set_parent) |
@@ -163,6 +205,9 @@ struct clk *clk_get_parent(struct clk *clk) | |||
163 | unsigned long flags; | 205 | unsigned long flags; |
164 | struct clk * ret = NULL; | 206 | struct clk * ret = NULL; |
165 | 207 | ||
208 | if (clk == NULL || IS_ERR(clk)) | ||
209 | return ret; | ||
210 | |||
166 | spin_lock_irqsave(&clockfw_lock, flags); | 211 | spin_lock_irqsave(&clockfw_lock, flags); |
167 | if (arch_clock->clk_get_parent) | 212 | if (arch_clock->clk_get_parent) |
168 | ret = arch_clock->clk_get_parent(clk); | 213 | ret = arch_clock->clk_get_parent(clk); |
@@ -199,6 +244,9 @@ __setup("mpurate=", omap_clk_setup); | |||
199 | /* Used for clocks that always have same value as the parent clock */ | 244 | /* Used for clocks that always have same value as the parent clock */ |
200 | void followparent_recalc(struct clk *clk) | 245 | void followparent_recalc(struct clk *clk) |
201 | { | 246 | { |
247 | if (clk == NULL || IS_ERR(clk)) | ||
248 | return; | ||
249 | |||
202 | clk->rate = clk->parent->rate; | 250 | clk->rate = clk->parent->rate; |
203 | } | 251 | } |
204 | 252 | ||
@@ -207,6 +255,9 @@ void propagate_rate(struct clk * tclk) | |||
207 | { | 255 | { |
208 | struct clk *clkp; | 256 | struct clk *clkp; |
209 | 257 | ||
258 | if (tclk == NULL || IS_ERR(tclk)) | ||
259 | return; | ||
260 | |||
210 | list_for_each_entry(clkp, &clocks, node) { | 261 | list_for_each_entry(clkp, &clocks, node) { |
211 | if (likely(clkp->parent != tclk)) | 262 | if (likely(clkp->parent != tclk)) |
212 | continue; | 263 | continue; |
@@ -217,6 +268,9 @@ void propagate_rate(struct clk * tclk) | |||
217 | 268 | ||
218 | int clk_register(struct clk *clk) | 269 | int clk_register(struct clk *clk) |
219 | { | 270 | { |
271 | if (clk == NULL || IS_ERR(clk)) | ||
272 | return -EINVAL; | ||
273 | |||
220 | mutex_lock(&clocks_mutex); | 274 | mutex_lock(&clocks_mutex); |
221 | list_add(&clk->node, &clocks); | 275 | list_add(&clk->node, &clocks); |
222 | if (clk->init) | 276 | if (clk->init) |
@@ -229,6 +283,9 @@ EXPORT_SYMBOL(clk_register); | |||
229 | 283 | ||
230 | void clk_unregister(struct clk *clk) | 284 | void clk_unregister(struct clk *clk) |
231 | { | 285 | { |
286 | if (clk == NULL || IS_ERR(clk)) | ||
287 | return; | ||
288 | |||
232 | mutex_lock(&clocks_mutex); | 289 | mutex_lock(&clocks_mutex); |
233 | list_del(&clk->node); | 290 | list_del(&clk->node); |
234 | mutex_unlock(&clocks_mutex); | 291 | mutex_unlock(&clocks_mutex); |
@@ -239,6 +296,9 @@ void clk_deny_idle(struct clk *clk) | |||
239 | { | 296 | { |
240 | unsigned long flags; | 297 | unsigned long flags; |
241 | 298 | ||
299 | if (clk == NULL || IS_ERR(clk)) | ||
300 | return; | ||
301 | |||
242 | spin_lock_irqsave(&clockfw_lock, flags); | 302 | spin_lock_irqsave(&clockfw_lock, flags); |
243 | if (arch_clock->clk_deny_idle) | 303 | if (arch_clock->clk_deny_idle) |
244 | arch_clock->clk_deny_idle(clk); | 304 | arch_clock->clk_deny_idle(clk); |
@@ -250,6 +310,9 @@ void clk_allow_idle(struct clk *clk) | |||
250 | { | 310 | { |
251 | unsigned long flags; | 311 | unsigned long flags; |
252 | 312 | ||
313 | if (clk == NULL || IS_ERR(clk)) | ||
314 | return; | ||
315 | |||
253 | spin_lock_irqsave(&clockfw_lock, flags); | 316 | spin_lock_irqsave(&clockfw_lock, flags); |
254 | if (arch_clock->clk_allow_idle) | 317 | if (arch_clock->clk_allow_idle) |
255 | arch_clock->clk_allow_idle(clk); | 318 | arch_clock->clk_allow_idle(clk); |
diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c index 9dcce904b608..079b67deac0f 100644 --- a/arch/arm/plat-omap/devices.c +++ b/arch/arm/plat-omap/devices.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <asm/arch/board.h> | 24 | #include <asm/arch/board.h> |
25 | #include <asm/arch/mux.h> | 25 | #include <asm/arch/mux.h> |
26 | #include <asm/arch/gpio.h> | 26 | #include <asm/arch/gpio.h> |
27 | #include <asm/arch/menelaus.h> | ||
27 | 28 | ||
28 | 29 | ||
29 | void omap_nop_release(struct device *dev) | 30 | void omap_nop_release(struct device *dev) |
@@ -98,6 +99,62 @@ static inline void omap_init_i2c(void) {} | |||
98 | #endif | 99 | #endif |
99 | 100 | ||
100 | /*-------------------------------------------------------------------------*/ | 101 | /*-------------------------------------------------------------------------*/ |
102 | #if defined(CONFIG_KEYBOARD_OMAP) || defined(CONFIG_KEYBOARD_OMAP_MODULE) | ||
103 | |||
104 | static void omap_init_kp(void) | ||
105 | { | ||
106 | if (machine_is_omap_h2() || machine_is_omap_h3()) { | ||
107 | omap_cfg_reg(F18_1610_KBC0); | ||
108 | omap_cfg_reg(D20_1610_KBC1); | ||
109 | omap_cfg_reg(D19_1610_KBC2); | ||
110 | omap_cfg_reg(E18_1610_KBC3); | ||
111 | omap_cfg_reg(C21_1610_KBC4); | ||
112 | |||
113 | omap_cfg_reg(G18_1610_KBR0); | ||
114 | omap_cfg_reg(F19_1610_KBR1); | ||
115 | omap_cfg_reg(H14_1610_KBR2); | ||
116 | omap_cfg_reg(E20_1610_KBR3); | ||
117 | omap_cfg_reg(E19_1610_KBR4); | ||
118 | omap_cfg_reg(N19_1610_KBR5); | ||
119 | } else if (machine_is_omap_perseus2()) { | ||
120 | omap_cfg_reg(E2_730_KBR0); | ||
121 | omap_cfg_reg(J7_730_KBR1); | ||
122 | omap_cfg_reg(E1_730_KBR2); | ||
123 | omap_cfg_reg(F3_730_KBR3); | ||
124 | omap_cfg_reg(D2_730_KBR4); | ||
125 | |||
126 | omap_cfg_reg(C2_730_KBC0); | ||
127 | omap_cfg_reg(D3_730_KBC1); | ||
128 | omap_cfg_reg(E4_730_KBC2); | ||
129 | omap_cfg_reg(F4_730_KBC3); | ||
130 | omap_cfg_reg(E3_730_KBC4); | ||
131 | } else if (machine_is_omap_h4()) { | ||
132 | omap_cfg_reg(T19_24XX_KBR0); | ||
133 | omap_cfg_reg(R19_24XX_KBR1); | ||
134 | omap_cfg_reg(V18_24XX_KBR2); | ||
135 | omap_cfg_reg(M21_24XX_KBR3); | ||
136 | omap_cfg_reg(E5__24XX_KBR4); | ||
137 | if (omap_has_menelaus()) { | ||
138 | omap_cfg_reg(B3__24XX_KBR5); | ||
139 | omap_cfg_reg(AA4_24XX_KBC2); | ||
140 | omap_cfg_reg(B13_24XX_KBC6); | ||
141 | } else { | ||
142 | omap_cfg_reg(M18_24XX_KBR5); | ||
143 | omap_cfg_reg(H19_24XX_KBC2); | ||
144 | omap_cfg_reg(N19_24XX_KBC6); | ||
145 | } | ||
146 | omap_cfg_reg(R20_24XX_KBC0); | ||
147 | omap_cfg_reg(M14_24XX_KBC1); | ||
148 | omap_cfg_reg(V17_24XX_KBC3); | ||
149 | omap_cfg_reg(P21_24XX_KBC4); | ||
150 | omap_cfg_reg(L14_24XX_KBC5); | ||
151 | } | ||
152 | } | ||
153 | #else | ||
154 | static inline void omap_init_kp(void) {} | ||
155 | #endif | ||
156 | |||
157 | /*-------------------------------------------------------------------------*/ | ||
101 | 158 | ||
102 | #if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) | 159 | #if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) |
103 | 160 | ||
@@ -240,6 +297,55 @@ static void __init omap_init_mmc(void) | |||
240 | static inline void omap_init_mmc(void) {} | 297 | static inline void omap_init_mmc(void) {} |
241 | #endif | 298 | #endif |
242 | 299 | ||
300 | /*-------------------------------------------------------------------------*/ | ||
301 | |||
302 | /* Numbering for the SPI-capable controllers when used for SPI: | ||
303 | * spi = 1 | ||
304 | * uwire = 2 | ||
305 | * mmc1..2 = 3..4 | ||
306 | * mcbsp1..3 = 5..7 | ||
307 | */ | ||
308 | |||
309 | #if defined(CONFIG_SPI_OMAP_UWIRE) || defined(CONFIG_SPI_OMAP_UWIRE_MODULE) | ||
310 | |||
311 | #define OMAP_UWIRE_BASE 0xfffb3000 | ||
312 | |||
313 | static struct resource uwire_resources[] = { | ||
314 | { | ||
315 | .start = OMAP_UWIRE_BASE, | ||
316 | .end = OMAP_UWIRE_BASE + 0x20, | ||
317 | .flags = IORESOURCE_MEM, | ||
318 | }, | ||
319 | }; | ||
320 | |||
321 | static struct platform_device omap_uwire_device = { | ||
322 | .name = "omap_uwire", | ||
323 | .id = -1, | ||
324 | .dev = { | ||
325 | .release = omap_nop_release, | ||
326 | }, | ||
327 | .num_resources = ARRAY_SIZE(uwire_resources), | ||
328 | .resource = uwire_resources, | ||
329 | }; | ||
330 | |||
331 | static void omap_init_uwire(void) | ||
332 | { | ||
333 | /* FIXME define and use a boot tag; not all boards will be hooking | ||
334 | * up devices to the microwire controller, and multi-board configs | ||
335 | * mean that CONFIG_SPI_OMAP_UWIRE may be configured anyway... | ||
336 | */ | ||
337 | |||
338 | /* board-specific code must configure chipselects (only a few | ||
339 | * are normally used) and SCLK/SDI/SDO (each has two choices). | ||
340 | */ | ||
341 | (void) platform_device_register(&omap_uwire_device); | ||
342 | } | ||
343 | #else | ||
344 | static inline void omap_init_uwire(void) {} | ||
345 | #endif | ||
346 | |||
347 | /*-------------------------------------------------------------------------*/ | ||
348 | |||
243 | #if defined(CONFIG_OMAP_WATCHDOG) || defined(CONFIG_OMAP_WATCHDOG_MODULE) | 349 | #if defined(CONFIG_OMAP_WATCHDOG) || defined(CONFIG_OMAP_WATCHDOG_MODULE) |
244 | 350 | ||
245 | #ifdef CONFIG_ARCH_OMAP24XX | 351 | #ifdef CONFIG_ARCH_OMAP24XX |
@@ -310,40 +416,6 @@ static void omap_init_rng(void) | |||
310 | static inline void omap_init_rng(void) {} | 416 | static inline void omap_init_rng(void) {} |
311 | #endif | 417 | #endif |
312 | 418 | ||
313 | #if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE) | ||
314 | |||
315 | static struct omap_lcd_config omap_fb_conf; | ||
316 | |||
317 | static u64 omap_fb_dma_mask = ~(u32)0; | ||
318 | |||
319 | static struct platform_device omap_fb_device = { | ||
320 | .name = "omapfb", | ||
321 | .id = -1, | ||
322 | .dev = { | ||
323 | .release = omap_nop_release, | ||
324 | .dma_mask = &omap_fb_dma_mask, | ||
325 | .coherent_dma_mask = ~(u32)0, | ||
326 | .platform_data = &omap_fb_conf, | ||
327 | }, | ||
328 | .num_resources = 0, | ||
329 | }; | ||
330 | |||
331 | static inline void omap_init_fb(void) | ||
332 | { | ||
333 | const struct omap_lcd_config *conf; | ||
334 | |||
335 | conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config); | ||
336 | if (conf != NULL) | ||
337 | omap_fb_conf = *conf; | ||
338 | platform_device_register(&omap_fb_device); | ||
339 | } | ||
340 | |||
341 | #else | ||
342 | |||
343 | static inline void omap_init_fb(void) {} | ||
344 | |||
345 | #endif | ||
346 | |||
347 | /* | 419 | /* |
348 | * This gets called after board-specific INIT_MACHINE, and initializes most | 420 | * This gets called after board-specific INIT_MACHINE, and initializes most |
349 | * on-chip peripherals accessible on this board (except for few like USB): | 421 | * on-chip peripherals accessible on this board (except for few like USB): |
@@ -369,9 +441,10 @@ static int __init omap_init_devices(void) | |||
369 | /* please keep these calls, and their implementations above, | 441 | /* please keep these calls, and their implementations above, |
370 | * in alphabetical order so they're easier to sort through. | 442 | * in alphabetical order so they're easier to sort through. |
371 | */ | 443 | */ |
372 | omap_init_fb(); | ||
373 | omap_init_i2c(); | 444 | omap_init_i2c(); |
445 | omap_init_kp(); | ||
374 | omap_init_mmc(); | 446 | omap_init_mmc(); |
447 | omap_init_uwire(); | ||
375 | omap_init_wdt(); | 448 | omap_init_wdt(); |
376 | omap_init_rng(); | 449 | omap_init_rng(); |
377 | 450 | ||
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index a4e5ac77f6df..5dac4230360d 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c | |||
@@ -1258,6 +1258,11 @@ void omap_stop_lcd_dma(void) | |||
1258 | omap_writew(w, OMAP1610_DMA_LCD_CTRL); | 1258 | omap_writew(w, OMAP1610_DMA_LCD_CTRL); |
1259 | } | 1259 | } |
1260 | 1260 | ||
1261 | int omap_lcd_dma_ext_running(void) | ||
1262 | { | ||
1263 | return lcd_dma.ext_ctrl && lcd_dma.active; | ||
1264 | } | ||
1265 | |||
1261 | /*----------------------------------------------------------------------------*/ | 1266 | /*----------------------------------------------------------------------------*/ |
1262 | 1267 | ||
1263 | static int __init omap_init_dma(void) | 1268 | static int __init omap_init_dma(void) |
@@ -1389,6 +1394,7 @@ EXPORT_SYMBOL(omap_free_lcd_dma); | |||
1389 | EXPORT_SYMBOL(omap_enable_lcd_dma); | 1394 | EXPORT_SYMBOL(omap_enable_lcd_dma); |
1390 | EXPORT_SYMBOL(omap_setup_lcd_dma); | 1395 | EXPORT_SYMBOL(omap_setup_lcd_dma); |
1391 | EXPORT_SYMBOL(omap_stop_lcd_dma); | 1396 | EXPORT_SYMBOL(omap_stop_lcd_dma); |
1397 | EXPORT_SYMBOL(omap_lcd_dma_ext_running); | ||
1392 | EXPORT_SYMBOL(omap_set_lcd_dma_b1); | 1398 | EXPORT_SYMBOL(omap_set_lcd_dma_b1); |
1393 | EXPORT_SYMBOL(omap_set_lcd_dma_single_transfer); | 1399 | EXPORT_SYMBOL(omap_set_lcd_dma_single_transfer); |
1394 | EXPORT_SYMBOL(omap_set_lcd_dma_ext_controller); | 1400 | EXPORT_SYMBOL(omap_set_lcd_dma_ext_controller); |
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index 38d7ebf87920..eba3cb52ad87 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c | |||
@@ -97,6 +97,32 @@ int omap_dm_timers_active(void) | |||
97 | } | 97 | } |
98 | 98 | ||
99 | 99 | ||
100 | /** | ||
101 | * omap_dm_timer_modify_idlect_mask - Check if any running timers use ARMXOR | ||
102 | * @inputmask: current value of idlect mask | ||
103 | */ | ||
104 | __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask) | ||
105 | { | ||
106 | int n; | ||
107 | |||
108 | /* If ARMXOR cannot be idled this function call is unnecessary */ | ||
109 | if (!(inputmask & (1 << 1))) | ||
110 | return inputmask; | ||
111 | |||
112 | /* If any active timer is using ARMXOR return modified mask */ | ||
113 | for (n = 0; dm_timers[n].base; ++n) | ||
114 | if (omap_dm_timer_read_reg(&dm_timers[n], OMAP_TIMER_CTRL_REG)& | ||
115 | OMAP_TIMER_CTRL_ST) { | ||
116 | if (((omap_readl(MOD_CONF_CTRL_1)>>(n*2)) & 0x03) == 0) | ||
117 | inputmask &= ~(1 << 1); | ||
118 | else | ||
119 | inputmask &= ~(1 << 2); | ||
120 | } | ||
121 | |||
122 | return inputmask; | ||
123 | } | ||
124 | |||
125 | |||
100 | void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source) | 126 | void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source) |
101 | { | 127 | { |
102 | int n = (timer - dm_timers) << 1; | 128 | int n = (timer - dm_timers) << 1; |
diff --git a/arch/arm/plat-omap/fb.c b/arch/arm/plat-omap/fb.c new file mode 100644 index 000000000000..305e9b990b71 --- /dev/null +++ b/arch/arm/plat-omap/fb.c | |||
@@ -0,0 +1,80 @@ | |||
1 | #include <linux/config.h> | ||
2 | #include <linux/module.h> | ||
3 | #include <linux/kernel.h> | ||
4 | #include <linux/init.h> | ||
5 | #include <linux/platform_device.h> | ||
6 | #include <linux/bootmem.h> | ||
7 | |||
8 | #include <asm/hardware.h> | ||
9 | #include <asm/io.h> | ||
10 | #include <asm/mach-types.h> | ||
11 | #include <asm/mach/map.h> | ||
12 | |||
13 | #include <asm/arch/board.h> | ||
14 | #include <asm/arch/sram.h> | ||
15 | #include <asm/arch/omapfb.h> | ||
16 | |||
17 | #if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE) | ||
18 | |||
19 | static struct omapfb_platform_data omapfb_config; | ||
20 | |||
21 | static u64 omap_fb_dma_mask = ~(u32)0; | ||
22 | |||
23 | static struct platform_device omap_fb_device = { | ||
24 | .name = "omapfb", | ||
25 | .id = -1, | ||
26 | .dev = { | ||
27 | .dma_mask = &omap_fb_dma_mask, | ||
28 | .coherent_dma_mask = ~(u32)0, | ||
29 | .platform_data = &omapfb_config, | ||
30 | }, | ||
31 | .num_resources = 0, | ||
32 | }; | ||
33 | |||
34 | /* called from map_io */ | ||
35 | void omapfb_reserve_mem(void) | ||
36 | { | ||
37 | const struct omap_fbmem_config *fbmem_conf; | ||
38 | |||
39 | omapfb_config.fbmem.fb_sram_start = omap_fb_sram_start; | ||
40 | omapfb_config.fbmem.fb_sram_size = omap_fb_sram_size; | ||
41 | |||
42 | fbmem_conf = omap_get_config(OMAP_TAG_FBMEM, struct omap_fbmem_config); | ||
43 | |||
44 | if (fbmem_conf != NULL) { | ||
45 | /* indicate that the bootloader already initialized the | ||
46 | * fb device, so we'll skip that part in the fb driver | ||
47 | */ | ||
48 | omapfb_config.fbmem.fb_sdram_start = fbmem_conf->fb_sdram_start; | ||
49 | omapfb_config.fbmem.fb_sdram_size = fbmem_conf->fb_sdram_size; | ||
50 | if (fbmem_conf->fb_sdram_size) { | ||
51 | pr_info("Reserving %u bytes SDRAM for frame buffer\n", | ||
52 | fbmem_conf->fb_sdram_size); | ||
53 | reserve_bootmem(fbmem_conf->fb_sdram_start, | ||
54 | fbmem_conf->fb_sdram_size); | ||
55 | } | ||
56 | } | ||
57 | } | ||
58 | |||
59 | static inline int omap_init_fb(void) | ||
60 | { | ||
61 | const struct omap_lcd_config *conf; | ||
62 | |||
63 | conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config); | ||
64 | if (conf == NULL) | ||
65 | return 0; | ||
66 | |||
67 | omapfb_config.lcd = *conf; | ||
68 | |||
69 | return platform_device_register(&omap_fb_device); | ||
70 | } | ||
71 | |||
72 | arch_initcall(omap_init_fb); | ||
73 | |||
74 | #else | ||
75 | |||
76 | void omapfb_reserve_mem(void) {} | ||
77 | |||
78 | #endif | ||
79 | |||
80 | |||
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c index b4d5b9e4bfce..d3c8ea7eecfd 100644 --- a/arch/arm/plat-omap/gpio.c +++ b/arch/arm/plat-omap/gpio.c | |||
@@ -174,7 +174,7 @@ static int gpio_bank_count; | |||
174 | static inline struct gpio_bank *get_gpio_bank(int gpio) | 174 | static inline struct gpio_bank *get_gpio_bank(int gpio) |
175 | { | 175 | { |
176 | #ifdef CONFIG_ARCH_OMAP15XX | 176 | #ifdef CONFIG_ARCH_OMAP15XX |
177 | if (cpu_is_omap1510()) { | 177 | if (cpu_is_omap15xx()) { |
178 | if (OMAP_GPIO_IS_MPUIO(gpio)) | 178 | if (OMAP_GPIO_IS_MPUIO(gpio)) |
179 | return &gpio_bank[0]; | 179 | return &gpio_bank[0]; |
180 | return &gpio_bank[1]; | 180 | return &gpio_bank[1]; |
@@ -223,7 +223,7 @@ static inline int gpio_valid(int gpio) | |||
223 | return 0; | 223 | return 0; |
224 | } | 224 | } |
225 | #ifdef CONFIG_ARCH_OMAP15XX | 225 | #ifdef CONFIG_ARCH_OMAP15XX |
226 | if (cpu_is_omap1510() && gpio < 16) | 226 | if (cpu_is_omap15xx() && gpio < 16) |
227 | return 0; | 227 | return 0; |
228 | #endif | 228 | #endif |
229 | #if defined(CONFIG_ARCH_OMAP16XX) | 229 | #if defined(CONFIG_ARCH_OMAP16XX) |
@@ -402,13 +402,13 @@ static inline void set_24xx_gpio_triggering(void __iomem *base, int gpio, int tr | |||
402 | u32 gpio_bit = 1 << gpio; | 402 | u32 gpio_bit = 1 << gpio; |
403 | 403 | ||
404 | MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT0, gpio_bit, | 404 | MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT0, gpio_bit, |
405 | trigger & IRQT_LOW); | 405 | trigger & __IRQT_LOWLVL); |
406 | MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT1, gpio_bit, | 406 | MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT1, gpio_bit, |
407 | trigger & IRQT_HIGH); | 407 | trigger & __IRQT_HIGHLVL); |
408 | MOD_REG_BIT(OMAP24XX_GPIO_RISINGDETECT, gpio_bit, | 408 | MOD_REG_BIT(OMAP24XX_GPIO_RISINGDETECT, gpio_bit, |
409 | trigger & IRQT_RISING); | 409 | trigger & __IRQT_RISEDGE); |
410 | MOD_REG_BIT(OMAP24XX_GPIO_FALLINGDETECT, gpio_bit, | 410 | MOD_REG_BIT(OMAP24XX_GPIO_FALLINGDETECT, gpio_bit, |
411 | trigger & IRQT_FALLING); | 411 | trigger & __IRQT_FALEDGE); |
412 | /* FIXME: Possibly do 'set_irq_handler(j, do_level_IRQ)' if only level | 412 | /* FIXME: Possibly do 'set_irq_handler(j, do_level_IRQ)' if only level |
413 | * triggering requested. */ | 413 | * triggering requested. */ |
414 | } | 414 | } |
@@ -422,9 +422,9 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger) | |||
422 | case METHOD_MPUIO: | 422 | case METHOD_MPUIO: |
423 | reg += OMAP_MPUIO_GPIO_INT_EDGE; | 423 | reg += OMAP_MPUIO_GPIO_INT_EDGE; |
424 | l = __raw_readl(reg); | 424 | l = __raw_readl(reg); |
425 | if (trigger == IRQT_RISING) | 425 | if (trigger & __IRQT_RISEDGE) |
426 | l |= 1 << gpio; | 426 | l |= 1 << gpio; |
427 | else if (trigger == IRQT_FALLING) | 427 | else if (trigger & __IRQT_FALEDGE) |
428 | l &= ~(1 << gpio); | 428 | l &= ~(1 << gpio); |
429 | else | 429 | else |
430 | goto bad; | 430 | goto bad; |
@@ -432,9 +432,9 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger) | |||
432 | case METHOD_GPIO_1510: | 432 | case METHOD_GPIO_1510: |
433 | reg += OMAP1510_GPIO_INT_CONTROL; | 433 | reg += OMAP1510_GPIO_INT_CONTROL; |
434 | l = __raw_readl(reg); | 434 | l = __raw_readl(reg); |
435 | if (trigger == IRQT_RISING) | 435 | if (trigger & __IRQT_RISEDGE) |
436 | l |= 1 << gpio; | 436 | l |= 1 << gpio; |
437 | else if (trigger == IRQT_FALLING) | 437 | else if (trigger & __IRQT_FALEDGE) |
438 | l &= ~(1 << gpio); | 438 | l &= ~(1 << gpio); |
439 | else | 439 | else |
440 | goto bad; | 440 | goto bad; |
@@ -446,20 +446,21 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger) | |||
446 | reg += OMAP1610_GPIO_EDGE_CTRL1; | 446 | reg += OMAP1610_GPIO_EDGE_CTRL1; |
447 | gpio &= 0x07; | 447 | gpio &= 0x07; |
448 | /* We allow only edge triggering, i.e. two lowest bits */ | 448 | /* We allow only edge triggering, i.e. two lowest bits */ |
449 | if (trigger & ~IRQT_BOTHEDGE) | 449 | if (trigger & (__IRQT_LOWLVL | __IRQT_HIGHLVL)) |
450 | BUG(); | 450 | BUG(); |
451 | /* NOTE: knows __IRQT_{FAL,RIS}EDGE match OMAP hardware */ | ||
452 | trigger &= 0x03; | ||
453 | l = __raw_readl(reg); | 451 | l = __raw_readl(reg); |
454 | l &= ~(3 << (gpio << 1)); | 452 | l &= ~(3 << (gpio << 1)); |
455 | l |= trigger << (gpio << 1); | 453 | if (trigger & __IRQT_RISEDGE) |
454 | l |= 2 << (gpio << 1); | ||
455 | if (trigger & __IRQT_FALEDGE) | ||
456 | l |= 1 << (gpio << 1); | ||
456 | break; | 457 | break; |
457 | case METHOD_GPIO_730: | 458 | case METHOD_GPIO_730: |
458 | reg += OMAP730_GPIO_INT_CONTROL; | 459 | reg += OMAP730_GPIO_INT_CONTROL; |
459 | l = __raw_readl(reg); | 460 | l = __raw_readl(reg); |
460 | if (trigger == IRQT_RISING) | 461 | if (trigger & __IRQT_RISEDGE) |
461 | l |= 1 << gpio; | 462 | l |= 1 << gpio; |
462 | else if (trigger == IRQT_FALLING) | 463 | else if (trigger & __IRQT_FALEDGE) |
463 | l &= ~(1 << gpio); | 464 | l &= ~(1 << gpio); |
464 | else | 465 | else |
465 | goto bad; | 466 | goto bad; |
@@ -491,7 +492,9 @@ static int gpio_irq_type(unsigned irq, unsigned type) | |||
491 | if (check_gpio(gpio) < 0) | 492 | if (check_gpio(gpio) < 0) |
492 | return -EINVAL; | 493 | return -EINVAL; |
493 | 494 | ||
494 | if (type & (__IRQT_LOWLVL|__IRQT_HIGHLVL|IRQT_PROBE)) | 495 | if (type & IRQT_PROBE) |
496 | return -EINVAL; | ||
497 | if (!cpu_is_omap24xx() && (type & (__IRQT_LOWLVL|__IRQT_HIGHLVL))) | ||
495 | return -EINVAL; | 498 | return -EINVAL; |
496 | 499 | ||
497 | bank = get_gpio_bank(gpio); | 500 | bank = get_gpio_bank(gpio); |
@@ -755,13 +758,32 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc, | |||
755 | if (bank->method == METHOD_GPIO_24XX) | 758 | if (bank->method == METHOD_GPIO_24XX) |
756 | isr_reg = bank->base + OMAP24XX_GPIO_IRQSTATUS1; | 759 | isr_reg = bank->base + OMAP24XX_GPIO_IRQSTATUS1; |
757 | #endif | 760 | #endif |
758 | |||
759 | while(1) { | 761 | while(1) { |
760 | isr = __raw_readl(isr_reg); | 762 | u32 isr_saved, level_mask = 0; |
761 | _enable_gpio_irqbank(bank, isr, 0); | 763 | |
762 | _clear_gpio_irqbank(bank, isr); | 764 | isr_saved = isr = __raw_readl(isr_reg); |
763 | _enable_gpio_irqbank(bank, isr, 1); | 765 | |
764 | desc->chip->unmask(irq); | 766 | if (cpu_is_omap15xx() && (bank->method == METHOD_MPUIO)) |
767 | isr &= 0x0000ffff; | ||
768 | |||
769 | if (cpu_is_omap24xx()) | ||
770 | level_mask = | ||
771 | __raw_readl(bank->base + | ||
772 | OMAP24XX_GPIO_LEVELDETECT0) | | ||
773 | __raw_readl(bank->base + | ||
774 | OMAP24XX_GPIO_LEVELDETECT1); | ||
775 | |||
776 | /* clear edge sensitive interrupts before handler(s) are | ||
777 | called so that we don't miss any interrupt occurred while | ||
778 | executing them */ | ||
779 | _enable_gpio_irqbank(bank, isr_saved & ~level_mask, 0); | ||
780 | _clear_gpio_irqbank(bank, isr_saved & ~level_mask); | ||
781 | _enable_gpio_irqbank(bank, isr_saved & ~level_mask, 1); | ||
782 | |||
783 | /* if there is only edge sensitive GPIO pin interrupts | ||
784 | configured, we could unmask GPIO bank interrupt immediately */ | ||
785 | if (!level_mask) | ||
786 | desc->chip->unmask(irq); | ||
765 | 787 | ||
766 | if (!isr) | 788 | if (!isr) |
767 | break; | 789 | break; |
@@ -774,6 +796,20 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc, | |||
774 | d = irq_desc + gpio_irq; | 796 | d = irq_desc + gpio_irq; |
775 | desc_handle_irq(gpio_irq, d, regs); | 797 | desc_handle_irq(gpio_irq, d, regs); |
776 | } | 798 | } |
799 | |||
800 | if (cpu_is_omap24xx()) { | ||
801 | /* clear level sensitive interrupts after handler(s) */ | ||
802 | _enable_gpio_irqbank(bank, isr_saved & level_mask, 0); | ||
803 | _clear_gpio_irqbank(bank, isr_saved & level_mask); | ||
804 | _enable_gpio_irqbank(bank, isr_saved & level_mask, 1); | ||
805 | } | ||
806 | |||
807 | /* if bank has any level sensitive GPIO pin interrupt | ||
808 | configured, we must unmask the bank interrupt only after | ||
809 | handler(s) are executed in order to avoid spurious bank | ||
810 | interrupt */ | ||
811 | if (level_mask) | ||
812 | desc->chip->unmask(irq); | ||
777 | } | 813 | } |
778 | } | 814 | } |
779 | 815 | ||
@@ -848,7 +884,7 @@ static int __init _omap_gpio_init(void) | |||
848 | 884 | ||
849 | initialized = 1; | 885 | initialized = 1; |
850 | 886 | ||
851 | if (cpu_is_omap1510()) { | 887 | if (cpu_is_omap15xx()) { |
852 | gpio_ick = clk_get(NULL, "arm_gpio_ck"); | 888 | gpio_ick = clk_get(NULL, "arm_gpio_ck"); |
853 | if (IS_ERR(gpio_ick)) | 889 | if (IS_ERR(gpio_ick)) |
854 | printk("Could not get arm_gpio_ck\n"); | 890 | printk("Could not get arm_gpio_ck\n"); |
@@ -869,7 +905,7 @@ static int __init _omap_gpio_init(void) | |||
869 | } | 905 | } |
870 | 906 | ||
871 | #ifdef CONFIG_ARCH_OMAP15XX | 907 | #ifdef CONFIG_ARCH_OMAP15XX |
872 | if (cpu_is_omap1510()) { | 908 | if (cpu_is_omap15xx()) { |
873 | printk(KERN_INFO "OMAP1510 GPIO hardware\n"); | 909 | printk(KERN_INFO "OMAP1510 GPIO hardware\n"); |
874 | gpio_bank_count = 2; | 910 | gpio_bank_count = 2; |
875 | gpio_bank = gpio_bank_1510; | 911 | gpio_bank = gpio_bank_1510; |
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c index 1cd2cace7e1b..196aac3ac329 100644 --- a/arch/arm/plat-omap/mcbsp.c +++ b/arch/arm/plat-omap/mcbsp.c | |||
@@ -34,7 +34,7 @@ | |||
34 | #ifdef CONFIG_MCBSP_DEBUG | 34 | #ifdef CONFIG_MCBSP_DEBUG |
35 | #define DBG(x...) printk(x) | 35 | #define DBG(x...) printk(x) |
36 | #else | 36 | #else |
37 | #define DBG(x...) do { } while (0) | 37 | #define DBG(x...) do { } while (0) |
38 | #endif | 38 | #endif |
39 | 39 | ||
40 | struct omap_mcbsp { | 40 | struct omap_mcbsp { |
@@ -44,6 +44,7 @@ struct omap_mcbsp { | |||
44 | omap_mcbsp_word_length rx_word_length; | 44 | omap_mcbsp_word_length rx_word_length; |
45 | omap_mcbsp_word_length tx_word_length; | 45 | omap_mcbsp_word_length tx_word_length; |
46 | 46 | ||
47 | omap_mcbsp_io_type_t io_type; /* IRQ or poll */ | ||
47 | /* IRQ based TX/RX */ | 48 | /* IRQ based TX/RX */ |
48 | int rx_irq; | 49 | int rx_irq; |
49 | int tx_irq; | 50 | int tx_irq; |
@@ -64,10 +65,19 @@ struct omap_mcbsp { | |||
64 | }; | 65 | }; |
65 | 66 | ||
66 | static struct omap_mcbsp mcbsp[OMAP_MAX_MCBSP_COUNT]; | 67 | static struct omap_mcbsp mcbsp[OMAP_MAX_MCBSP_COUNT]; |
68 | #ifdef CONFIG_ARCH_OMAP1 | ||
67 | static struct clk *mcbsp_dsp_ck = 0; | 69 | static struct clk *mcbsp_dsp_ck = 0; |
68 | static struct clk *mcbsp_api_ck = 0; | 70 | static struct clk *mcbsp_api_ck = 0; |
69 | static struct clk *mcbsp_dspxor_ck = 0; | 71 | static struct clk *mcbsp_dspxor_ck = 0; |
70 | 72 | #endif | |
73 | #ifdef CONFIG_ARCH_OMAP2 | ||
74 | static struct clk *mcbsp1_ick = 0; | ||
75 | static struct clk *mcbsp1_fck = 0; | ||
76 | static struct clk *mcbsp2_ick = 0; | ||
77 | static struct clk *mcbsp2_fck = 0; | ||
78 | static struct clk *sys_ck = 0; | ||
79 | static struct clk *sys_clkout = 0; | ||
80 | #endif | ||
71 | 81 | ||
72 | static void omap_mcbsp_dump_reg(u8 id) | 82 | static void omap_mcbsp_dump_reg(u8 id) |
73 | { | 83 | { |
@@ -88,7 +98,6 @@ static void omap_mcbsp_dump_reg(u8 id) | |||
88 | DBG("***********************\n"); | 98 | DBG("***********************\n"); |
89 | } | 99 | } |
90 | 100 | ||
91 | |||
92 | static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *dev_id, struct pt_regs *regs) | 101 | static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *dev_id, struct pt_regs *regs) |
93 | { | 102 | { |
94 | struct omap_mcbsp * mcbsp_tx = (struct omap_mcbsp *)(dev_id); | 103 | struct omap_mcbsp * mcbsp_tx = (struct omap_mcbsp *)(dev_id); |
@@ -109,7 +118,6 @@ static irqreturn_t omap_mcbsp_rx_irq_handler(int irq, void *dev_id, struct pt_re | |||
109 | return IRQ_HANDLED; | 118 | return IRQ_HANDLED; |
110 | } | 119 | } |
111 | 120 | ||
112 | |||
113 | static void omap_mcbsp_tx_dma_callback(int lch, u16 ch_status, void *data) | 121 | static void omap_mcbsp_tx_dma_callback(int lch, u16 ch_status, void *data) |
114 | { | 122 | { |
115 | struct omap_mcbsp * mcbsp_dma_tx = (struct omap_mcbsp *)(data); | 123 | struct omap_mcbsp * mcbsp_dma_tx = (struct omap_mcbsp *)(data); |
@@ -176,7 +184,7 @@ static int omap_mcbsp_check(unsigned int id) | |||
176 | return 0; | 184 | return 0; |
177 | } | 185 | } |
178 | 186 | ||
179 | if (cpu_is_omap1510() || cpu_is_omap16xx()) { | 187 | if (cpu_is_omap15xx() || cpu_is_omap16xx() || cpu_is_omap24xx()) { |
180 | if (id > OMAP_MAX_MCBSP_COUNT) { | 188 | if (id > OMAP_MAX_MCBSP_COUNT) { |
181 | printk(KERN_ERR "OMAP-McBSP: McBSP%d doesn't exist\n", id + 1); | 189 | printk(KERN_ERR "OMAP-McBSP: McBSP%d doesn't exist\n", id + 1); |
182 | return -1; | 190 | return -1; |
@@ -187,9 +195,10 @@ static int omap_mcbsp_check(unsigned int id) | |||
187 | return -1; | 195 | return -1; |
188 | } | 196 | } |
189 | 197 | ||
198 | #ifdef CONFIG_ARCH_OMAP1 | ||
190 | static void omap_mcbsp_dsp_request(void) | 199 | static void omap_mcbsp_dsp_request(void) |
191 | { | 200 | { |
192 | if (cpu_is_omap1510() || cpu_is_omap16xx()) { | 201 | if (cpu_is_omap15xx() || cpu_is_omap16xx()) { |
193 | clk_enable(mcbsp_dsp_ck); | 202 | clk_enable(mcbsp_dsp_ck); |
194 | clk_enable(mcbsp_api_ck); | 203 | clk_enable(mcbsp_api_ck); |
195 | 204 | ||
@@ -207,12 +216,49 @@ static void omap_mcbsp_dsp_request(void) | |||
207 | 216 | ||
208 | static void omap_mcbsp_dsp_free(void) | 217 | static void omap_mcbsp_dsp_free(void) |
209 | { | 218 | { |
210 | if (cpu_is_omap1510() || cpu_is_omap16xx()) { | 219 | if (cpu_is_omap15xx() || cpu_is_omap16xx()) { |
211 | clk_disable(mcbsp_dspxor_ck); | 220 | clk_disable(mcbsp_dspxor_ck); |
212 | clk_disable(mcbsp_dsp_ck); | 221 | clk_disable(mcbsp_dsp_ck); |
213 | clk_disable(mcbsp_api_ck); | 222 | clk_disable(mcbsp_api_ck); |
214 | } | 223 | } |
215 | } | 224 | } |
225 | #endif | ||
226 | |||
227 | #ifdef CONFIG_ARCH_OMAP2 | ||
228 | static void omap2_mcbsp2_mux_setup(void) | ||
229 | { | ||
230 | omap_cfg_reg(Y15_24XX_MCBSP2_CLKX); | ||
231 | omap_cfg_reg(R14_24XX_MCBSP2_FSX); | ||
232 | omap_cfg_reg(W15_24XX_MCBSP2_DR); | ||
233 | omap_cfg_reg(V15_24XX_MCBSP2_DX); | ||
234 | omap_cfg_reg(V14_24XX_GPIO117); | ||
235 | omap_cfg_reg(W14_24XX_SYS_CLKOUT); | ||
236 | } | ||
237 | #endif | ||
238 | |||
239 | /* | ||
240 | * We can choose between IRQ based or polled IO. | ||
241 | * This needs to be called before omap_mcbsp_request(). | ||
242 | */ | ||
243 | int omap_mcbsp_set_io_type(unsigned int id, omap_mcbsp_io_type_t io_type) | ||
244 | { | ||
245 | if (omap_mcbsp_check(id) < 0) | ||
246 | return -EINVAL; | ||
247 | |||
248 | spin_lock(&mcbsp[id].lock); | ||
249 | |||
250 | if (!mcbsp[id].free) { | ||
251 | printk (KERN_ERR "OMAP-McBSP: McBSP%d is currently in use\n", id + 1); | ||
252 | spin_unlock(&mcbsp[id].lock); | ||
253 | return -EINVAL; | ||
254 | } | ||
255 | |||
256 | mcbsp[id].io_type = io_type; | ||
257 | |||
258 | spin_unlock(&mcbsp[id].lock); | ||
259 | |||
260 | return 0; | ||
261 | } | ||
216 | 262 | ||
217 | int omap_mcbsp_request(unsigned int id) | 263 | int omap_mcbsp_request(unsigned int id) |
218 | { | 264 | { |
@@ -221,12 +267,26 @@ int omap_mcbsp_request(unsigned int id) | |||
221 | if (omap_mcbsp_check(id) < 0) | 267 | if (omap_mcbsp_check(id) < 0) |
222 | return -EINVAL; | 268 | return -EINVAL; |
223 | 269 | ||
270 | #ifdef CONFIG_ARCH_OMAP1 | ||
224 | /* | 271 | /* |
225 | * On 1510, 1610 and 1710, McBSP1 and McBSP3 | 272 | * On 1510, 1610 and 1710, McBSP1 and McBSP3 |
226 | * are DSP public peripherals. | 273 | * are DSP public peripherals. |
227 | */ | 274 | */ |
228 | if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3) | 275 | if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3) |
229 | omap_mcbsp_dsp_request(); | 276 | omap_mcbsp_dsp_request(); |
277 | #endif | ||
278 | |||
279 | #ifdef CONFIG_ARCH_OMAP2 | ||
280 | if (cpu_is_omap24xx()) { | ||
281 | if (id == OMAP_MCBSP1) { | ||
282 | clk_enable(mcbsp1_ick); | ||
283 | clk_enable(mcbsp1_fck); | ||
284 | } else { | ||
285 | clk_enable(mcbsp2_ick); | ||
286 | clk_enable(mcbsp2_fck); | ||
287 | } | ||
288 | } | ||
289 | #endif | ||
230 | 290 | ||
231 | spin_lock(&mcbsp[id].lock); | 291 | spin_lock(&mcbsp[id].lock); |
232 | if (!mcbsp[id].free) { | 292 | if (!mcbsp[id].free) { |
@@ -238,30 +298,33 @@ int omap_mcbsp_request(unsigned int id) | |||
238 | mcbsp[id].free = 0; | 298 | mcbsp[id].free = 0; |
239 | spin_unlock(&mcbsp[id].lock); | 299 | spin_unlock(&mcbsp[id].lock); |
240 | 300 | ||
241 | /* We need to get IRQs here */ | 301 | if (mcbsp[id].io_type == OMAP_MCBSP_IRQ_IO) { |
242 | err = request_irq(mcbsp[id].tx_irq, omap_mcbsp_tx_irq_handler, 0, | 302 | /* We need to get IRQs here */ |
243 | "McBSP", | 303 | err = request_irq(mcbsp[id].tx_irq, omap_mcbsp_tx_irq_handler, 0, |
244 | (void *) (&mcbsp[id])); | 304 | "McBSP", |
245 | if (err != 0) { | 305 | (void *) (&mcbsp[id])); |
246 | printk(KERN_ERR "OMAP-McBSP: Unable to request TX IRQ %d for McBSP%d\n", | 306 | if (err != 0) { |
247 | mcbsp[id].tx_irq, mcbsp[id].id); | 307 | printk(KERN_ERR "OMAP-McBSP: Unable to request TX IRQ %d for McBSP%d\n", |
248 | return err; | 308 | mcbsp[id].tx_irq, mcbsp[id].id); |
249 | } | 309 | return err; |
310 | } | ||
250 | 311 | ||
251 | init_completion(&(mcbsp[id].tx_irq_completion)); | 312 | init_completion(&(mcbsp[id].tx_irq_completion)); |
252 | 313 | ||
253 | 314 | ||
254 | err = request_irq(mcbsp[id].rx_irq, omap_mcbsp_rx_irq_handler, 0, | 315 | err = request_irq(mcbsp[id].rx_irq, omap_mcbsp_rx_irq_handler, 0, |
255 | "McBSP", | 316 | "McBSP", |
256 | (void *) (&mcbsp[id])); | 317 | (void *) (&mcbsp[id])); |
257 | if (err != 0) { | 318 | if (err != 0) { |
258 | printk(KERN_ERR "OMAP-McBSP: Unable to request RX IRQ %d for McBSP%d\n", | 319 | printk(KERN_ERR "OMAP-McBSP: Unable to request RX IRQ %d for McBSP%d\n", |
259 | mcbsp[id].rx_irq, mcbsp[id].id); | 320 | mcbsp[id].rx_irq, mcbsp[id].id); |
260 | free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id])); | 321 | free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id])); |
261 | return err; | 322 | return err; |
323 | } | ||
324 | |||
325 | init_completion(&(mcbsp[id].rx_irq_completion)); | ||
262 | } | 326 | } |
263 | 327 | ||
264 | init_completion(&(mcbsp[id].rx_irq_completion)); | ||
265 | return 0; | 328 | return 0; |
266 | 329 | ||
267 | } | 330 | } |
@@ -271,8 +334,24 @@ void omap_mcbsp_free(unsigned int id) | |||
271 | if (omap_mcbsp_check(id) < 0) | 334 | if (omap_mcbsp_check(id) < 0) |
272 | return; | 335 | return; |
273 | 336 | ||
274 | if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3) | 337 | #ifdef CONFIG_ARCH_OMAP1 |
275 | omap_mcbsp_dsp_free(); | 338 | if (cpu_class_is_omap1()) { |
339 | if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3) | ||
340 | omap_mcbsp_dsp_free(); | ||
341 | } | ||
342 | #endif | ||
343 | |||
344 | #ifdef CONFIG_ARCH_OMAP2 | ||
345 | if (cpu_is_omap24xx()) { | ||
346 | if (id == OMAP_MCBSP1) { | ||
347 | clk_disable(mcbsp1_ick); | ||
348 | clk_disable(mcbsp1_fck); | ||
349 | } else { | ||
350 | clk_disable(mcbsp2_ick); | ||
351 | clk_disable(mcbsp2_fck); | ||
352 | } | ||
353 | } | ||
354 | #endif | ||
276 | 355 | ||
277 | spin_lock(&mcbsp[id].lock); | 356 | spin_lock(&mcbsp[id].lock); |
278 | if (mcbsp[id].free) { | 357 | if (mcbsp[id].free) { |
@@ -284,9 +363,11 @@ void omap_mcbsp_free(unsigned int id) | |||
284 | mcbsp[id].free = 1; | 363 | mcbsp[id].free = 1; |
285 | spin_unlock(&mcbsp[id].lock); | 364 | spin_unlock(&mcbsp[id].lock); |
286 | 365 | ||
287 | /* Free IRQs */ | 366 | if (mcbsp[id].io_type == OMAP_MCBSP_IRQ_IO) { |
288 | free_irq(mcbsp[id].rx_irq, (void *) (&mcbsp[id])); | 367 | /* Free IRQs */ |
289 | free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id])); | 368 | free_irq(mcbsp[id].rx_irq, (void *) (&mcbsp[id])); |
369 | free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id])); | ||
370 | } | ||
290 | } | 371 | } |
291 | 372 | ||
292 | /* | 373 | /* |
@@ -461,6 +542,115 @@ u32 omap_mcbsp_recv_word(unsigned int id) | |||
461 | } | 542 | } |
462 | 543 | ||
463 | 544 | ||
545 | int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word) | ||
546 | { | ||
547 | u32 io_base = mcbsp[id].io_base; | ||
548 | omap_mcbsp_word_length tx_word_length = mcbsp[id].tx_word_length; | ||
549 | omap_mcbsp_word_length rx_word_length = mcbsp[id].rx_word_length; | ||
550 | u16 spcr2, spcr1, attempts = 0, word_lsb, word_msb = 0; | ||
551 | |||
552 | if (tx_word_length != rx_word_length) | ||
553 | return -EINVAL; | ||
554 | |||
555 | /* First we wait for the transmitter to be ready */ | ||
556 | spcr2 = OMAP_MCBSP_READ(io_base, SPCR2); | ||
557 | while (!(spcr2 & XRDY)) { | ||
558 | spcr2 = OMAP_MCBSP_READ(io_base, SPCR2); | ||
559 | if (attempts++ > 1000) { | ||
560 | /* We must reset the transmitter */ | ||
561 | OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 & (~XRST)); | ||
562 | udelay(10); | ||
563 | OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 | XRST); | ||
564 | udelay(10); | ||
565 | printk("McBSP transmitter not ready\n"); | ||
566 | return -EAGAIN; | ||
567 | } | ||
568 | } | ||
569 | |||
570 | /* Now we can push the data */ | ||
571 | if (tx_word_length > OMAP_MCBSP_WORD_16) | ||
572 | OMAP_MCBSP_WRITE(io_base, DXR2, word >> 16); | ||
573 | OMAP_MCBSP_WRITE(io_base, DXR1, word & 0xffff); | ||
574 | |||
575 | /* We wait for the receiver to be ready */ | ||
576 | spcr1 = OMAP_MCBSP_READ(io_base, SPCR1); | ||
577 | while (!(spcr1 & RRDY)) { | ||
578 | spcr1 = OMAP_MCBSP_READ(io_base, SPCR1); | ||
579 | if (attempts++ > 1000) { | ||
580 | /* We must reset the receiver */ | ||
581 | OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 & (~RRST)); | ||
582 | udelay(10); | ||
583 | OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 | RRST); | ||
584 | udelay(10); | ||
585 | printk("McBSP receiver not ready\n"); | ||
586 | return -EAGAIN; | ||
587 | } | ||
588 | } | ||
589 | |||
590 | /* Receiver is ready, let's read the dummy data */ | ||
591 | if (rx_word_length > OMAP_MCBSP_WORD_16) | ||
592 | word_msb = OMAP_MCBSP_READ(io_base, DRR2); | ||
593 | word_lsb = OMAP_MCBSP_READ(io_base, DRR1); | ||
594 | |||
595 | return 0; | ||
596 | } | ||
597 | |||
598 | int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 * word) | ||
599 | { | ||
600 | u32 io_base = mcbsp[id].io_base, clock_word = 0; | ||
601 | omap_mcbsp_word_length tx_word_length = mcbsp[id].tx_word_length; | ||
602 | omap_mcbsp_word_length rx_word_length = mcbsp[id].rx_word_length; | ||
603 | u16 spcr2, spcr1, attempts = 0, word_lsb, word_msb = 0; | ||
604 | |||
605 | if (tx_word_length != rx_word_length) | ||
606 | return -EINVAL; | ||
607 | |||
608 | /* First we wait for the transmitter to be ready */ | ||
609 | spcr2 = OMAP_MCBSP_READ(io_base, SPCR2); | ||
610 | while (!(spcr2 & XRDY)) { | ||
611 | spcr2 = OMAP_MCBSP_READ(io_base, SPCR2); | ||
612 | if (attempts++ > 1000) { | ||
613 | /* We must reset the transmitter */ | ||
614 | OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 & (~XRST)); | ||
615 | udelay(10); | ||
616 | OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 | XRST); | ||
617 | udelay(10); | ||
618 | printk("McBSP transmitter not ready\n"); | ||
619 | return -EAGAIN; | ||
620 | } | ||
621 | } | ||
622 | |||
623 | /* We first need to enable the bus clock */ | ||
624 | if (tx_word_length > OMAP_MCBSP_WORD_16) | ||
625 | OMAP_MCBSP_WRITE(io_base, DXR2, clock_word >> 16); | ||
626 | OMAP_MCBSP_WRITE(io_base, DXR1, clock_word & 0xffff); | ||
627 | |||
628 | /* We wait for the receiver to be ready */ | ||
629 | spcr1 = OMAP_MCBSP_READ(io_base, SPCR1); | ||
630 | while (!(spcr1 & RRDY)) { | ||
631 | spcr1 = OMAP_MCBSP_READ(io_base, SPCR1); | ||
632 | if (attempts++ > 1000) { | ||
633 | /* We must reset the receiver */ | ||
634 | OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 & (~RRST)); | ||
635 | udelay(10); | ||
636 | OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 | RRST); | ||
637 | udelay(10); | ||
638 | printk("McBSP receiver not ready\n"); | ||
639 | return -EAGAIN; | ||
640 | } | ||
641 | } | ||
642 | |||
643 | /* Receiver is ready, there is something for us */ | ||
644 | if (rx_word_length > OMAP_MCBSP_WORD_16) | ||
645 | word_msb = OMAP_MCBSP_READ(io_base, DRR2); | ||
646 | word_lsb = OMAP_MCBSP_READ(io_base, DRR1); | ||
647 | |||
648 | word[0] = (word_lsb | (word_msb << 16)); | ||
649 | |||
650 | return 0; | ||
651 | } | ||
652 | |||
653 | |||
464 | /* | 654 | /* |
465 | * Simple DMA based buffer rx/tx routines. | 655 | * Simple DMA based buffer rx/tx routines. |
466 | * Nothing fancy, just a single buffer tx/rx through DMA. | 656 | * Nothing fancy, just a single buffer tx/rx through DMA. |
@@ -471,6 +661,9 @@ u32 omap_mcbsp_recv_word(unsigned int id) | |||
471 | int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, unsigned int length) | 661 | int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, unsigned int length) |
472 | { | 662 | { |
473 | int dma_tx_ch; | 663 | int dma_tx_ch; |
664 | int src_port = 0; | ||
665 | int dest_port = 0; | ||
666 | int sync_dev = 0; | ||
474 | 667 | ||
475 | if (omap_mcbsp_check(id) < 0) | 668 | if (omap_mcbsp_check(id) < 0) |
476 | return -EINVAL; | 669 | return -EINVAL; |
@@ -487,20 +680,27 @@ int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, unsigned int leng | |||
487 | 680 | ||
488 | init_completion(&(mcbsp[id].tx_dma_completion)); | 681 | init_completion(&(mcbsp[id].tx_dma_completion)); |
489 | 682 | ||
683 | if (cpu_class_is_omap1()) { | ||
684 | src_port = OMAP_DMA_PORT_TIPB; | ||
685 | dest_port = OMAP_DMA_PORT_EMIFF; | ||
686 | } | ||
687 | if (cpu_is_omap24xx()) | ||
688 | sync_dev = mcbsp[id].dma_tx_sync; | ||
689 | |||
490 | omap_set_dma_transfer_params(mcbsp[id].dma_tx_lch, | 690 | omap_set_dma_transfer_params(mcbsp[id].dma_tx_lch, |
491 | OMAP_DMA_DATA_TYPE_S16, | 691 | OMAP_DMA_DATA_TYPE_S16, |
492 | length >> 1, 1, | 692 | length >> 1, 1, |
493 | OMAP_DMA_SYNC_ELEMENT, | 693 | OMAP_DMA_SYNC_ELEMENT, |
494 | 0, 0); | 694 | sync_dev, 0); |
495 | 695 | ||
496 | omap_set_dma_dest_params(mcbsp[id].dma_tx_lch, | 696 | omap_set_dma_dest_params(mcbsp[id].dma_tx_lch, |
497 | OMAP_DMA_PORT_TIPB, | 697 | src_port, |
498 | OMAP_DMA_AMODE_CONSTANT, | 698 | OMAP_DMA_AMODE_CONSTANT, |
499 | mcbsp[id].io_base + OMAP_MCBSP_REG_DXR1, | 699 | mcbsp[id].io_base + OMAP_MCBSP_REG_DXR1, |
500 | 0, 0); | 700 | 0, 0); |
501 | 701 | ||
502 | omap_set_dma_src_params(mcbsp[id].dma_tx_lch, | 702 | omap_set_dma_src_params(mcbsp[id].dma_tx_lch, |
503 | OMAP_DMA_PORT_EMIFF, | 703 | dest_port, |
504 | OMAP_DMA_AMODE_POST_INC, | 704 | OMAP_DMA_AMODE_POST_INC, |
505 | buffer, | 705 | buffer, |
506 | 0, 0); | 706 | 0, 0); |
@@ -514,6 +714,9 @@ int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, unsigned int leng | |||
514 | int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, unsigned int length) | 714 | int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, unsigned int length) |
515 | { | 715 | { |
516 | int dma_rx_ch; | 716 | int dma_rx_ch; |
717 | int src_port = 0; | ||
718 | int dest_port = 0; | ||
719 | int sync_dev = 0; | ||
517 | 720 | ||
518 | if (omap_mcbsp_check(id) < 0) | 721 | if (omap_mcbsp_check(id) < 0) |
519 | return -EINVAL; | 722 | return -EINVAL; |
@@ -530,20 +733,27 @@ int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, unsigned int leng | |||
530 | 733 | ||
531 | init_completion(&(mcbsp[id].rx_dma_completion)); | 734 | init_completion(&(mcbsp[id].rx_dma_completion)); |
532 | 735 | ||
736 | if (cpu_class_is_omap1()) { | ||
737 | src_port = OMAP_DMA_PORT_TIPB; | ||
738 | dest_port = OMAP_DMA_PORT_EMIFF; | ||
739 | } | ||
740 | if (cpu_is_omap24xx()) | ||
741 | sync_dev = mcbsp[id].dma_rx_sync; | ||
742 | |||
533 | omap_set_dma_transfer_params(mcbsp[id].dma_rx_lch, | 743 | omap_set_dma_transfer_params(mcbsp[id].dma_rx_lch, |
534 | OMAP_DMA_DATA_TYPE_S16, | 744 | OMAP_DMA_DATA_TYPE_S16, |
535 | length >> 1, 1, | 745 | length >> 1, 1, |
536 | OMAP_DMA_SYNC_ELEMENT, | 746 | OMAP_DMA_SYNC_ELEMENT, |
537 | 0, 0); | 747 | sync_dev, 0); |
538 | 748 | ||
539 | omap_set_dma_src_params(mcbsp[id].dma_rx_lch, | 749 | omap_set_dma_src_params(mcbsp[id].dma_rx_lch, |
540 | OMAP_DMA_PORT_TIPB, | 750 | src_port, |
541 | OMAP_DMA_AMODE_CONSTANT, | 751 | OMAP_DMA_AMODE_CONSTANT, |
542 | mcbsp[id].io_base + OMAP_MCBSP_REG_DRR1, | 752 | mcbsp[id].io_base + OMAP_MCBSP_REG_DRR1, |
543 | 0, 0); | 753 | 0, 0); |
544 | 754 | ||
545 | omap_set_dma_dest_params(mcbsp[id].dma_rx_lch, | 755 | omap_set_dma_dest_params(mcbsp[id].dma_rx_lch, |
546 | OMAP_DMA_PORT_EMIFF, | 756 | dest_port, |
547 | OMAP_DMA_AMODE_POST_INC, | 757 | OMAP_DMA_AMODE_POST_INC, |
548 | buffer, | 758 | buffer, |
549 | 0, 0); | 759 | 0, 0); |
@@ -688,6 +898,23 @@ static const struct omap_mcbsp_info mcbsp_1610[] = { | |||
688 | }; | 898 | }; |
689 | #endif | 899 | #endif |
690 | 900 | ||
901 | #if defined(CONFIG_ARCH_OMAP24XX) | ||
902 | static const struct omap_mcbsp_info mcbsp_24xx[] = { | ||
903 | [0] = { .virt_base = IO_ADDRESS(OMAP24XX_MCBSP1_BASE), | ||
904 | .dma_rx_sync = OMAP24XX_DMA_MCBSP1_RX, | ||
905 | .dma_tx_sync = OMAP24XX_DMA_MCBSP1_TX, | ||
906 | .rx_irq = INT_24XX_MCBSP1_IRQ_RX, | ||
907 | .tx_irq = INT_24XX_MCBSP1_IRQ_TX, | ||
908 | }, | ||
909 | [1] = { .virt_base = IO_ADDRESS(OMAP24XX_MCBSP2_BASE), | ||
910 | .dma_rx_sync = OMAP24XX_DMA_MCBSP2_RX, | ||
911 | .dma_tx_sync = OMAP24XX_DMA_MCBSP2_TX, | ||
912 | .rx_irq = INT_24XX_MCBSP2_IRQ_RX, | ||
913 | .tx_irq = INT_24XX_MCBSP2_IRQ_TX, | ||
914 | }, | ||
915 | }; | ||
916 | #endif | ||
917 | |||
691 | static int __init omap_mcbsp_init(void) | 918 | static int __init omap_mcbsp_init(void) |
692 | { | 919 | { |
693 | int mcbsp_count = 0, i; | 920 | int mcbsp_count = 0, i; |
@@ -695,6 +922,7 @@ static int __init omap_mcbsp_init(void) | |||
695 | 922 | ||
696 | printk("Initializing OMAP McBSP system\n"); | 923 | printk("Initializing OMAP McBSP system\n"); |
697 | 924 | ||
925 | #ifdef CONFIG_ARCH_OMAP1 | ||
698 | mcbsp_dsp_ck = clk_get(0, "dsp_ck"); | 926 | mcbsp_dsp_ck = clk_get(0, "dsp_ck"); |
699 | if (IS_ERR(mcbsp_dsp_ck)) { | 927 | if (IS_ERR(mcbsp_dsp_ck)) { |
700 | printk(KERN_ERR "mcbsp: could not acquire dsp_ck handle.\n"); | 928 | printk(KERN_ERR "mcbsp: could not acquire dsp_ck handle.\n"); |
@@ -710,6 +938,29 @@ static int __init omap_mcbsp_init(void) | |||
710 | printk(KERN_ERR "mcbsp: could not acquire dspxor_ck handle.\n"); | 938 | printk(KERN_ERR "mcbsp: could not acquire dspxor_ck handle.\n"); |
711 | return PTR_ERR(mcbsp_dspxor_ck); | 939 | return PTR_ERR(mcbsp_dspxor_ck); |
712 | } | 940 | } |
941 | #endif | ||
942 | #ifdef CONFIG_ARCH_OMAP2 | ||
943 | mcbsp1_ick = clk_get(0, "mcbsp1_ick"); | ||
944 | if (IS_ERR(mcbsp1_ick)) { | ||
945 | printk(KERN_ERR "mcbsp: could not acquire mcbsp1_ick handle.\n"); | ||
946 | return PTR_ERR(mcbsp1_ick); | ||
947 | } | ||
948 | mcbsp1_fck = clk_get(0, "mcbsp1_fck"); | ||
949 | if (IS_ERR(mcbsp1_fck)) { | ||
950 | printk(KERN_ERR "mcbsp: could not acquire mcbsp1_fck handle.\n"); | ||
951 | return PTR_ERR(mcbsp1_fck); | ||
952 | } | ||
953 | mcbsp2_ick = clk_get(0, "mcbsp2_ick"); | ||
954 | if (IS_ERR(mcbsp2_ick)) { | ||
955 | printk(KERN_ERR "mcbsp: could not acquire mcbsp2_ick handle.\n"); | ||
956 | return PTR_ERR(mcbsp2_ick); | ||
957 | } | ||
958 | mcbsp2_fck = clk_get(0, "mcbsp2_fck"); | ||
959 | if (IS_ERR(mcbsp2_fck)) { | ||
960 | printk(KERN_ERR "mcbsp: could not acquire mcbsp2_fck handle.\n"); | ||
961 | return PTR_ERR(mcbsp2_fck); | ||
962 | } | ||
963 | #endif | ||
713 | 964 | ||
714 | #ifdef CONFIG_ARCH_OMAP730 | 965 | #ifdef CONFIG_ARCH_OMAP730 |
715 | if (cpu_is_omap730()) { | 966 | if (cpu_is_omap730()) { |
@@ -718,7 +969,7 @@ static int __init omap_mcbsp_init(void) | |||
718 | } | 969 | } |
719 | #endif | 970 | #endif |
720 | #ifdef CONFIG_ARCH_OMAP15XX | 971 | #ifdef CONFIG_ARCH_OMAP15XX |
721 | if (cpu_is_omap1510()) { | 972 | if (cpu_is_omap15xx()) { |
722 | mcbsp_info = mcbsp_1510; | 973 | mcbsp_info = mcbsp_1510; |
723 | mcbsp_count = ARRAY_SIZE(mcbsp_1510); | 974 | mcbsp_count = ARRAY_SIZE(mcbsp_1510); |
724 | } | 975 | } |
@@ -729,6 +980,19 @@ static int __init omap_mcbsp_init(void) | |||
729 | mcbsp_count = ARRAY_SIZE(mcbsp_1610); | 980 | mcbsp_count = ARRAY_SIZE(mcbsp_1610); |
730 | } | 981 | } |
731 | #endif | 982 | #endif |
983 | #if defined(CONFIG_ARCH_OMAP24XX) | ||
984 | if (cpu_is_omap24xx()) { | ||
985 | mcbsp_info = mcbsp_24xx; | ||
986 | mcbsp_count = ARRAY_SIZE(mcbsp_24xx); | ||
987 | |||
988 | /* REVISIT: where's the right place? */ | ||
989 | omap2_mcbsp2_mux_setup(); | ||
990 | sys_ck = clk_get(0, "sys_ck"); | ||
991 | sys_clkout = clk_get(0, "sys_clkout"); | ||
992 | clk_set_parent(sys_clkout, sys_ck); | ||
993 | clk_enable(sys_clkout); | ||
994 | } | ||
995 | #endif | ||
732 | for (i = 0; i < OMAP_MAX_MCBSP_COUNT ; i++) { | 996 | for (i = 0; i < OMAP_MAX_MCBSP_COUNT ; i++) { |
733 | if (i >= mcbsp_count) { | 997 | if (i >= mcbsp_count) { |
734 | mcbsp[i].io_base = 0; | 998 | mcbsp[i].io_base = 0; |
@@ -741,6 +1005,7 @@ static int __init omap_mcbsp_init(void) | |||
741 | mcbsp[i].dma_rx_lch = -1; | 1005 | mcbsp[i].dma_rx_lch = -1; |
742 | 1006 | ||
743 | mcbsp[i].io_base = mcbsp_info[i].virt_base; | 1007 | mcbsp[i].io_base = mcbsp_info[i].virt_base; |
1008 | mcbsp[i].io_type = OMAP_MCBSP_IRQ_IO; /* Default I/O is IRQ based */ | ||
744 | mcbsp[i].tx_irq = mcbsp_info[i].tx_irq; | 1009 | mcbsp[i].tx_irq = mcbsp_info[i].tx_irq; |
745 | mcbsp[i].rx_irq = mcbsp_info[i].rx_irq; | 1010 | mcbsp[i].rx_irq = mcbsp_info[i].rx_irq; |
746 | mcbsp[i].dma_rx_sync = mcbsp_info[i].dma_rx_sync; | 1011 | mcbsp[i].dma_rx_sync = mcbsp_info[i].dma_rx_sync; |
@@ -751,11 +1016,11 @@ static int __init omap_mcbsp_init(void) | |||
751 | return 0; | 1016 | return 0; |
752 | } | 1017 | } |
753 | 1018 | ||
754 | |||
755 | arch_initcall(omap_mcbsp_init); | 1019 | arch_initcall(omap_mcbsp_init); |
756 | 1020 | ||
757 | EXPORT_SYMBOL(omap_mcbsp_config); | 1021 | EXPORT_SYMBOL(omap_mcbsp_config); |
758 | EXPORT_SYMBOL(omap_mcbsp_request); | 1022 | EXPORT_SYMBOL(omap_mcbsp_request); |
1023 | EXPORT_SYMBOL(omap_mcbsp_set_io_type); | ||
759 | EXPORT_SYMBOL(omap_mcbsp_free); | 1024 | EXPORT_SYMBOL(omap_mcbsp_free); |
760 | EXPORT_SYMBOL(omap_mcbsp_start); | 1025 | EXPORT_SYMBOL(omap_mcbsp_start); |
761 | EXPORT_SYMBOL(omap_mcbsp_stop); | 1026 | EXPORT_SYMBOL(omap_mcbsp_stop); |
@@ -763,4 +1028,6 @@ EXPORT_SYMBOL(omap_mcbsp_xmit_word); | |||
763 | EXPORT_SYMBOL(omap_mcbsp_recv_word); | 1028 | EXPORT_SYMBOL(omap_mcbsp_recv_word); |
764 | EXPORT_SYMBOL(omap_mcbsp_xmit_buffer); | 1029 | EXPORT_SYMBOL(omap_mcbsp_xmit_buffer); |
765 | EXPORT_SYMBOL(omap_mcbsp_recv_buffer); | 1030 | EXPORT_SYMBOL(omap_mcbsp_recv_buffer); |
1031 | EXPORT_SYMBOL(omap_mcbsp_spi_master_xmit_word_poll); | ||
1032 | EXPORT_SYMBOL(omap_mcbsp_spi_master_recv_word_poll); | ||
766 | EXPORT_SYMBOL(omap_mcbsp_set_spi_mode); | 1033 | EXPORT_SYMBOL(omap_mcbsp_set_spi_mode); |
diff --git a/arch/arm/plat-omap/ocpi.c b/arch/arm/plat-omap/ocpi.c index 5cc6775c789c..37792d43738b 100644 --- a/arch/arm/plat-omap/ocpi.c +++ b/arch/arm/plat-omap/ocpi.c | |||
@@ -62,9 +62,6 @@ int ocpi_enable(void) | |||
62 | if (!cpu_is_omap16xx()) | 62 | if (!cpu_is_omap16xx()) |
63 | return -ENODEV; | 63 | return -ENODEV; |
64 | 64 | ||
65 | /* Make sure there's clock for OCPI */ | ||
66 | clk_enable(ocpi_ck); | ||
67 | |||
68 | /* Enable access for OHCI in OCPI */ | 65 | /* Enable access for OHCI in OCPI */ |
69 | val = omap_readl(OCPI_PROT); | 66 | val = omap_readl(OCPI_PROT); |
70 | val &= ~0xff; | 67 | val &= ~0xff; |
diff --git a/arch/arm/plat-omap/pm.c b/arch/arm/plat-omap/pm.c index 093efd786f21..1a24e2c10714 100644 --- a/arch/arm/plat-omap/pm.c +++ b/arch/arm/plat-omap/pm.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/pm.h> | 38 | #include <linux/pm.h> |
39 | #include <linux/sched.h> | 39 | #include <linux/sched.h> |
40 | #include <linux/proc_fs.h> | 40 | #include <linux/proc_fs.h> |
41 | #include <linux/pm.h> | ||
41 | #include <linux/interrupt.h> | 42 | #include <linux/interrupt.h> |
42 | 43 | ||
43 | #include <asm/io.h> | 44 | #include <asm/io.h> |
diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c index ee82763b02b8..b7bf09b1b412 100644 --- a/arch/arm/plat-omap/sram.c +++ b/arch/arm/plat-omap/sram.c | |||
@@ -16,24 +16,94 @@ | |||
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
18 | 18 | ||
19 | #include <asm/mach/map.h> | ||
20 | #include <asm/tlb.h> | 19 | #include <asm/tlb.h> |
21 | #include <asm/io.h> | 20 | #include <asm/io.h> |
22 | #include <asm/cacheflush.h> | 21 | #include <asm/cacheflush.h> |
23 | 22 | ||
23 | #include <asm/mach/map.h> | ||
24 | |||
24 | #include <asm/arch/sram.h> | 25 | #include <asm/arch/sram.h> |
26 | #include <asm/arch/board.h> | ||
25 | 27 | ||
26 | #define OMAP1_SRAM_PA 0x20000000 | 28 | #define OMAP1_SRAM_PA 0x20000000 |
27 | #define OMAP1_SRAM_VA 0xd0000000 | 29 | #define OMAP1_SRAM_VA 0xd0000000 |
28 | #define OMAP2_SRAM_PA 0x40200000 | 30 | #define OMAP2_SRAM_PA 0x40200000 |
31 | #define OMAP2_SRAM_PUB_PA 0x4020f800 | ||
29 | #define OMAP2_SRAM_VA 0xd0000000 | 32 | #define OMAP2_SRAM_VA 0xd0000000 |
33 | #define OMAP2_SRAM_PUB_VA 0xd0000800 | ||
30 | 34 | ||
35 | #if defined(CONFIG_ARCH_OMAP24XX) | ||
36 | #define SRAM_BOOTLOADER_SZ 0x00 | ||
37 | #else | ||
31 | #define SRAM_BOOTLOADER_SZ 0x80 | 38 | #define SRAM_BOOTLOADER_SZ 0x80 |
39 | #endif | ||
40 | |||
41 | #define VA_REQINFOPERM0 IO_ADDRESS(0x68005048) | ||
42 | #define VA_READPERM0 IO_ADDRESS(0x68005050) | ||
43 | #define VA_WRITEPERM0 IO_ADDRESS(0x68005058) | ||
44 | #define VA_CONTROL_STAT IO_ADDRESS(0x480002F8) | ||
45 | #define GP_DEVICE 0x300 | ||
46 | #define TYPE_MASK 0x700 | ||
47 | |||
48 | #define ROUND_DOWN(value,boundary) ((value) & (~((boundary)-1))) | ||
32 | 49 | ||
33 | static unsigned long omap_sram_base; | 50 | static unsigned long omap_sram_base; |
34 | static unsigned long omap_sram_size; | 51 | static unsigned long omap_sram_size; |
35 | static unsigned long omap_sram_ceil; | 52 | static unsigned long omap_sram_ceil; |
36 | 53 | ||
54 | unsigned long omap_fb_sram_start; | ||
55 | unsigned long omap_fb_sram_size; | ||
56 | |||
57 | /* Depending on the target RAMFS firewall setup, the public usable amount of | ||
58 | * SRAM varies. The default accessable size for all device types is 2k. A GP | ||
59 | * device allows ARM11 but not other initators for full size. This | ||
60 | * functionality seems ok until some nice security API happens. | ||
61 | */ | ||
62 | static int is_sram_locked(void) | ||
63 | { | ||
64 | int type = 0; | ||
65 | |||
66 | if (cpu_is_omap242x()) | ||
67 | type = __raw_readl(VA_CONTROL_STAT) & TYPE_MASK; | ||
68 | |||
69 | if (type == GP_DEVICE) { | ||
70 | /* RAMFW: R/W access to all initators for all qualifier sets */ | ||
71 | if (cpu_is_omap242x()) { | ||
72 | __raw_writel(0xFF, VA_REQINFOPERM0); /* all q-vects */ | ||
73 | __raw_writel(0xCFDE, VA_READPERM0); /* all i-read */ | ||
74 | __raw_writel(0xCFDE, VA_WRITEPERM0); /* all i-write */ | ||
75 | } | ||
76 | return 0; | ||
77 | } else | ||
78 | return 1; /* assume locked with no PPA or security driver */ | ||
79 | } | ||
80 | |||
81 | void get_fb_sram_conf(unsigned long start_avail, unsigned size_avail, | ||
82 | unsigned long *start, unsigned long *size) | ||
83 | { | ||
84 | const struct omap_fbmem_config *fbmem_conf; | ||
85 | |||
86 | fbmem_conf = omap_get_config(OMAP_TAG_FBMEM, struct omap_fbmem_config); | ||
87 | if (fbmem_conf != NULL) { | ||
88 | *start = fbmem_conf->fb_sram_start; | ||
89 | *size = fbmem_conf->fb_sram_size; | ||
90 | } else { | ||
91 | *size = 0; | ||
92 | *start = 0; | ||
93 | } | ||
94 | |||
95 | if (*size && ( | ||
96 | *start < start_avail || | ||
97 | *start + *size > start_avail + size_avail)) { | ||
98 | printk(KERN_ERR "invalid FB SRAM configuration\n"); | ||
99 | *start = start_avail; | ||
100 | *size = size_avail; | ||
101 | } | ||
102 | |||
103 | if (*size) | ||
104 | pr_info("Reserving %lu bytes SRAM for frame buffer\n", *size); | ||
105 | } | ||
106 | |||
37 | /* | 107 | /* |
38 | * The amount of SRAM depends on the core type. | 108 | * The amount of SRAM depends on the core type. |
39 | * Note that we cannot try to test for SRAM here because writes | 109 | * Note that we cannot try to test for SRAM here because writes |
@@ -42,26 +112,45 @@ static unsigned long omap_sram_ceil; | |||
42 | */ | 112 | */ |
43 | void __init omap_detect_sram(void) | 113 | void __init omap_detect_sram(void) |
44 | { | 114 | { |
45 | if (!cpu_is_omap24xx()) | 115 | unsigned long sram_start; |
116 | |||
117 | if (cpu_is_omap24xx()) { | ||
118 | if (is_sram_locked()) { | ||
119 | omap_sram_base = OMAP2_SRAM_PUB_VA; | ||
120 | sram_start = OMAP2_SRAM_PUB_PA; | ||
121 | omap_sram_size = 0x800; /* 2K */ | ||
122 | } else { | ||
123 | omap_sram_base = OMAP2_SRAM_VA; | ||
124 | sram_start = OMAP2_SRAM_PA; | ||
125 | if (cpu_is_omap242x()) | ||
126 | omap_sram_size = 0xa0000; /* 640K */ | ||
127 | else if (cpu_is_omap243x()) | ||
128 | omap_sram_size = 0x10000; /* 64K */ | ||
129 | } | ||
130 | } else { | ||
46 | omap_sram_base = OMAP1_SRAM_VA; | 131 | omap_sram_base = OMAP1_SRAM_VA; |
47 | else | 132 | sram_start = OMAP1_SRAM_PA; |
48 | omap_sram_base = OMAP2_SRAM_VA; | 133 | |
49 | 134 | if (cpu_is_omap730()) | |
50 | if (cpu_is_omap730()) | 135 | omap_sram_size = 0x32000; /* 200K */ |
51 | omap_sram_size = 0x32000; /* 200K */ | 136 | else if (cpu_is_omap15xx()) |
52 | else if (cpu_is_omap15xx()) | 137 | omap_sram_size = 0x30000; /* 192K */ |
53 | omap_sram_size = 0x30000; /* 192K */ | 138 | else if (cpu_is_omap1610() || cpu_is_omap1621() || |
54 | else if (cpu_is_omap1610() || cpu_is_omap1621() || cpu_is_omap1710()) | 139 | cpu_is_omap1710()) |
55 | omap_sram_size = 0x4000; /* 16K */ | 140 | omap_sram_size = 0x4000; /* 16K */ |
56 | else if (cpu_is_omap1611()) | 141 | else if (cpu_is_omap1611()) |
57 | omap_sram_size = 0x3e800; /* 250K */ | 142 | omap_sram_size = 0x3e800; /* 250K */ |
58 | else if (cpu_is_omap2420()) | 143 | else { |
59 | omap_sram_size = 0xa0014; /* 640K */ | 144 | printk(KERN_ERR "Could not detect SRAM size\n"); |
60 | else { | 145 | omap_sram_size = 0x4000; |
61 | printk(KERN_ERR "Could not detect SRAM size\n"); | 146 | } |
62 | omap_sram_size = 0x4000; | ||
63 | } | 147 | } |
64 | 148 | get_fb_sram_conf(sram_start + SRAM_BOOTLOADER_SZ, | |
149 | omap_sram_size - SRAM_BOOTLOADER_SZ, | ||
150 | &omap_fb_sram_start, &omap_fb_sram_size); | ||
151 | if (omap_fb_sram_size) | ||
152 | omap_sram_size -= sram_start + omap_sram_size - | ||
153 | omap_fb_sram_start; | ||
65 | omap_sram_ceil = omap_sram_base + omap_sram_size; | 154 | omap_sram_ceil = omap_sram_base + omap_sram_size; |
66 | } | 155 | } |
67 | 156 | ||
@@ -80,12 +169,20 @@ static struct map_desc omap_sram_io_desc[] __initdata = { | |||
80 | */ | 169 | */ |
81 | void __init omap_map_sram(void) | 170 | void __init omap_map_sram(void) |
82 | { | 171 | { |
172 | unsigned long base; | ||
173 | |||
83 | if (omap_sram_size == 0) | 174 | if (omap_sram_size == 0) |
84 | return; | 175 | return; |
85 | 176 | ||
86 | if (cpu_is_omap24xx()) { | 177 | if (cpu_is_omap24xx()) { |
87 | omap_sram_io_desc[0].virtual = OMAP2_SRAM_VA; | 178 | omap_sram_io_desc[0].virtual = OMAP2_SRAM_VA; |
88 | omap_sram_io_desc[0].pfn = __phys_to_pfn(OMAP2_SRAM_PA); | 179 | |
180 | if (is_sram_locked()) | ||
181 | base = OMAP2_SRAM_PUB_PA; | ||
182 | else | ||
183 | base = OMAP2_SRAM_PA; | ||
184 | base = ROUND_DOWN(base, PAGE_SIZE); | ||
185 | omap_sram_io_desc[0].pfn = __phys_to_pfn(base); | ||
89 | } | 186 | } |
90 | 187 | ||
91 | omap_sram_io_desc[0].length = (omap_sram_size + PAGE_SIZE-1)/PAGE_SIZE; | 188 | omap_sram_io_desc[0].length = (omap_sram_size + PAGE_SIZE-1)/PAGE_SIZE; |
@@ -93,7 +190,8 @@ void __init omap_map_sram(void) | |||
93 | iotable_init(omap_sram_io_desc, ARRAY_SIZE(omap_sram_io_desc)); | 190 | iotable_init(omap_sram_io_desc, ARRAY_SIZE(omap_sram_io_desc)); |
94 | 191 | ||
95 | printk(KERN_INFO "SRAM: Mapped pa 0x%08lx to va 0x%08lx size: 0x%lx\n", | 192 | printk(KERN_INFO "SRAM: Mapped pa 0x%08lx to va 0x%08lx size: 0x%lx\n", |
96 | omap_sram_io_desc[0].pfn, omap_sram_io_desc[0].virtual, | 193 | __pfn_to_phys(omap_sram_io_desc[0].pfn), |
194 | omap_sram_io_desc[0].virtual, | ||
97 | omap_sram_io_desc[0].length); | 195 | omap_sram_io_desc[0].length); |
98 | 196 | ||
99 | /* | 197 | /* |
@@ -118,8 +216,9 @@ void * omap_sram_push(void * start, unsigned long size) | |||
118 | printk(KERN_ERR "Not enough space in SRAM\n"); | 216 | printk(KERN_ERR "Not enough space in SRAM\n"); |
119 | return NULL; | 217 | return NULL; |
120 | } | 218 | } |
219 | |||
121 | omap_sram_ceil -= size; | 220 | omap_sram_ceil -= size; |
122 | omap_sram_ceil &= ~0x3; | 221 | omap_sram_ceil = ROUND_DOWN(omap_sram_ceil, sizeof(void *)); |
123 | memcpy((void *)omap_sram_ceil, start, size); | 222 | memcpy((void *)omap_sram_ceil, start, size); |
124 | 223 | ||
125 | return (void *)omap_sram_ceil; | 224 | return (void *)omap_sram_ceil; |
diff --git a/arch/arm/plat-omap/timer32k.c b/arch/arm/plat-omap/timer32k.c new file mode 100644 index 000000000000..b2a943bf11ef --- /dev/null +++ b/arch/arm/plat-omap/timer32k.c | |||
@@ -0,0 +1,325 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/plat-omap/timer32k.c | ||
3 | * | ||
4 | * OMAP 32K Timer | ||
5 | * | ||
6 | * Copyright (C) 2004 - 2005 Nokia Corporation | ||
7 | * Partial timer rewrite and additional dynamic tick timer support by | ||
8 | * Tony Lindgen <tony@atomide.com> and | ||
9 | * Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com> | ||
10 | * | ||
11 | * MPU timer code based on the older MPU timer code for OMAP | ||
12 | * Copyright (C) 2000 RidgeRun, Inc. | ||
13 | * Author: Greg Lonnon <glonnon@ridgerun.com> | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or modify it | ||
16 | * under the terms of the GNU General Public License as published by the | ||
17 | * Free Software Foundation; either version 2 of the License, or (at your | ||
18 | * option) any later version. | ||
19 | * | ||
20 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
21 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
22 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | ||
23 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
24 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
25 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
26 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
27 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
29 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
30 | * | ||
31 | * You should have received a copy of the GNU General Public License along | ||
32 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
33 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
34 | */ | ||
35 | |||
36 | #include <linux/config.h> | ||
37 | #include <linux/kernel.h> | ||
38 | #include <linux/init.h> | ||
39 | #include <linux/delay.h> | ||
40 | #include <linux/interrupt.h> | ||
41 | #include <linux/sched.h> | ||
42 | #include <linux/spinlock.h> | ||
43 | #include <linux/err.h> | ||
44 | #include <linux/clk.h> | ||
45 | |||
46 | #include <asm/system.h> | ||
47 | #include <asm/hardware.h> | ||
48 | #include <asm/io.h> | ||
49 | #include <asm/leds.h> | ||
50 | #include <asm/irq.h> | ||
51 | #include <asm/mach/irq.h> | ||
52 | #include <asm/mach/time.h> | ||
53 | |||
54 | struct sys_timer omap_timer; | ||
55 | |||
56 | /* | ||
57 | * --------------------------------------------------------------------------- | ||
58 | * 32KHz OS timer | ||
59 | * | ||
60 | * This currently works only on 16xx, as 1510 does not have the continuous | ||
61 | * 32KHz synchronous timer. The 32KHz synchronous timer is used to keep track | ||
62 | * of time in addition to the 32KHz OS timer. Using only the 32KHz OS timer | ||
63 | * on 1510 would be possible, but the timer would not be as accurate as | ||
64 | * with the 32KHz synchronized timer. | ||
65 | * --------------------------------------------------------------------------- | ||
66 | */ | ||
67 | |||
68 | #if defined(CONFIG_ARCH_OMAP16XX) | ||
69 | #define TIMER_32K_SYNCHRONIZED 0xfffbc410 | ||
70 | #elif defined(CONFIG_ARCH_OMAP24XX) | ||
71 | #define TIMER_32K_SYNCHRONIZED 0x48004010 | ||
72 | #else | ||
73 | #error OMAP 32KHz timer does not currently work on 15XX! | ||
74 | #endif | ||
75 | |||
76 | /* 16xx specific defines */ | ||
77 | #define OMAP1_32K_TIMER_BASE 0xfffb9000 | ||
78 | #define OMAP1_32K_TIMER_CR 0x08 | ||
79 | #define OMAP1_32K_TIMER_TVR 0x00 | ||
80 | #define OMAP1_32K_TIMER_TCR 0x04 | ||
81 | |||
82 | /* 24xx specific defines */ | ||
83 | #define OMAP2_GP_TIMER_BASE 0x48028000 | ||
84 | #define CM_CLKSEL_WKUP 0x48008440 | ||
85 | #define GP_TIMER_TIDR 0x00 | ||
86 | #define GP_TIMER_TISR 0x18 | ||
87 | #define GP_TIMER_TIER 0x1c | ||
88 | #define GP_TIMER_TCLR 0x24 | ||
89 | #define GP_TIMER_TCRR 0x28 | ||
90 | #define GP_TIMER_TLDR 0x2c | ||
91 | #define GP_TIMER_TTGR 0x30 | ||
92 | #define GP_TIMER_TSICR 0x40 | ||
93 | |||
94 | #define OMAP_32K_TICKS_PER_HZ (32768 / HZ) | ||
95 | |||
96 | /* | ||
97 | * TRM says 1 / HZ = ( TVR + 1) / 32768, so TRV = (32768 / HZ) - 1 | ||
98 | * so with HZ = 128, TVR = 255. | ||
99 | */ | ||
100 | #define OMAP_32K_TIMER_TICK_PERIOD ((32768 / HZ) - 1) | ||
101 | |||
102 | #define JIFFIES_TO_HW_TICKS(nr_jiffies, clock_rate) \ | ||
103 | (((nr_jiffies) * (clock_rate)) / HZ) | ||
104 | |||
105 | static inline void omap_32k_timer_write(int val, int reg) | ||
106 | { | ||
107 | if (cpu_class_is_omap1()) | ||
108 | omap_writew(val, OMAP1_32K_TIMER_BASE + reg); | ||
109 | |||
110 | if (cpu_is_omap24xx()) | ||
111 | omap_writel(val, OMAP2_GP_TIMER_BASE + reg); | ||
112 | } | ||
113 | |||
114 | static inline unsigned long omap_32k_timer_read(int reg) | ||
115 | { | ||
116 | if (cpu_class_is_omap1()) | ||
117 | return omap_readl(OMAP1_32K_TIMER_BASE + reg) & 0xffffff; | ||
118 | |||
119 | if (cpu_is_omap24xx()) | ||
120 | return omap_readl(OMAP2_GP_TIMER_BASE + reg); | ||
121 | } | ||
122 | |||
123 | /* | ||
124 | * The 32KHz synchronized timer is an additional timer on 16xx. | ||
125 | * It is always running. | ||
126 | */ | ||
127 | static inline unsigned long omap_32k_sync_timer_read(void) | ||
128 | { | ||
129 | return omap_readl(TIMER_32K_SYNCHRONIZED); | ||
130 | } | ||
131 | |||
132 | static inline void omap_32k_timer_start(unsigned long load_val) | ||
133 | { | ||
134 | if (cpu_class_is_omap1()) { | ||
135 | omap_32k_timer_write(load_val, OMAP1_32K_TIMER_TVR); | ||
136 | omap_32k_timer_write(0x0f, OMAP1_32K_TIMER_CR); | ||
137 | } | ||
138 | |||
139 | if (cpu_is_omap24xx()) { | ||
140 | omap_32k_timer_write(0xffffffff - load_val, GP_TIMER_TCRR); | ||
141 | omap_32k_timer_write((1 << 1), GP_TIMER_TIER); | ||
142 | omap_32k_timer_write((1 << 1) | 1, GP_TIMER_TCLR); | ||
143 | } | ||
144 | } | ||
145 | |||
146 | static inline void omap_32k_timer_stop(void) | ||
147 | { | ||
148 | if (cpu_class_is_omap1()) | ||
149 | omap_32k_timer_write(0x0, OMAP1_32K_TIMER_CR); | ||
150 | |||
151 | if (cpu_is_omap24xx()) | ||
152 | omap_32k_timer_write(0x0, GP_TIMER_TCLR); | ||
153 | } | ||
154 | |||
155 | /* | ||
156 | * Rounds down to nearest usec. Note that this will overflow for larger values. | ||
157 | */ | ||
158 | static inline unsigned long omap_32k_ticks_to_usecs(unsigned long ticks_32k) | ||
159 | { | ||
160 | return (ticks_32k * 5*5*5*5*5*5) >> 9; | ||
161 | } | ||
162 | |||
163 | /* | ||
164 | * Rounds down to nearest nsec. | ||
165 | */ | ||
166 | static inline unsigned long long | ||
167 | omap_32k_ticks_to_nsecs(unsigned long ticks_32k) | ||
168 | { | ||
169 | return (unsigned long long) ticks_32k * 1000 * 5*5*5*5*5*5 >> 9; | ||
170 | } | ||
171 | |||
172 | static unsigned long omap_32k_last_tick = 0; | ||
173 | |||
174 | /* | ||
175 | * Returns elapsed usecs since last 32k timer interrupt | ||
176 | */ | ||
177 | static unsigned long omap_32k_timer_gettimeoffset(void) | ||
178 | { | ||
179 | unsigned long now = omap_32k_sync_timer_read(); | ||
180 | return omap_32k_ticks_to_usecs(now - omap_32k_last_tick); | ||
181 | } | ||
182 | |||
183 | /* | ||
184 | * Returns current time from boot in nsecs. It's OK for this to wrap | ||
185 | * around for now, as it's just a relative time stamp. | ||
186 | */ | ||
187 | unsigned long long sched_clock(void) | ||
188 | { | ||
189 | return omap_32k_ticks_to_nsecs(omap_32k_sync_timer_read()); | ||
190 | } | ||
191 | |||
192 | /* | ||
193 | * Timer interrupt for 32KHz timer. When dynamic tick is enabled, this | ||
194 | * function is also called from other interrupts to remove latency | ||
195 | * issues with dynamic tick. In the dynamic tick case, we need to lock | ||
196 | * with irqsave. | ||
197 | */ | ||
198 | static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id, | ||
199 | struct pt_regs *regs) | ||
200 | { | ||
201 | unsigned long flags; | ||
202 | unsigned long now; | ||
203 | |||
204 | write_seqlock_irqsave(&xtime_lock, flags); | ||
205 | |||
206 | if (cpu_is_omap24xx()) { | ||
207 | u32 status = omap_32k_timer_read(GP_TIMER_TISR); | ||
208 | omap_32k_timer_write(status, GP_TIMER_TISR); | ||
209 | } | ||
210 | |||
211 | now = omap_32k_sync_timer_read(); | ||
212 | |||
213 | while (now - omap_32k_last_tick >= OMAP_32K_TICKS_PER_HZ) { | ||
214 | omap_32k_last_tick += OMAP_32K_TICKS_PER_HZ; | ||
215 | timer_tick(regs); | ||
216 | } | ||
217 | |||
218 | /* Restart timer so we don't drift off due to modulo or dynamic tick. | ||
219 | * By default we program the next timer to be continuous to avoid | ||
220 | * latencies during high system load. During dynamic tick operation the | ||
221 | * continuous timer can be overridden from pm_idle to be longer. | ||
222 | */ | ||
223 | omap_32k_timer_start(omap_32k_last_tick + OMAP_32K_TICKS_PER_HZ - now); | ||
224 | write_sequnlock_irqrestore(&xtime_lock, flags); | ||
225 | |||
226 | return IRQ_HANDLED; | ||
227 | } | ||
228 | |||
229 | #ifdef CONFIG_NO_IDLE_HZ | ||
230 | /* | ||
231 | * Programs the next timer interrupt needed. Called when dynamic tick is | ||
232 | * enabled, and to reprogram the ticks to skip from pm_idle. Note that | ||
233 | * we can keep the timer continuous, and don't need to set it to run in | ||
234 | * one-shot mode. This is because the timer will get reprogrammed again | ||
235 | * after next interrupt. | ||
236 | */ | ||
237 | void omap_32k_timer_reprogram(unsigned long next_tick) | ||
238 | { | ||
239 | omap_32k_timer_start(JIFFIES_TO_HW_TICKS(next_tick, 32768) + 1); | ||
240 | } | ||
241 | |||
242 | static struct irqaction omap_32k_timer_irq; | ||
243 | extern struct timer_update_handler timer_update; | ||
244 | |||
245 | static int omap_32k_timer_enable_dyn_tick(void) | ||
246 | { | ||
247 | /* No need to reprogram timer, just use the next interrupt */ | ||
248 | return 0; | ||
249 | } | ||
250 | |||
251 | static int omap_32k_timer_disable_dyn_tick(void) | ||
252 | { | ||
253 | omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD); | ||
254 | return 0; | ||
255 | } | ||
256 | |||
257 | static struct dyn_tick_timer omap_dyn_tick_timer = { | ||
258 | .enable = omap_32k_timer_enable_dyn_tick, | ||
259 | .disable = omap_32k_timer_disable_dyn_tick, | ||
260 | .reprogram = omap_32k_timer_reprogram, | ||
261 | .handler = omap_32k_timer_interrupt, | ||
262 | }; | ||
263 | #endif /* CONFIG_NO_IDLE_HZ */ | ||
264 | |||
265 | static struct irqaction omap_32k_timer_irq = { | ||
266 | .name = "32KHz timer", | ||
267 | .flags = SA_INTERRUPT | SA_TIMER, | ||
268 | .handler = omap_32k_timer_interrupt, | ||
269 | }; | ||
270 | |||
271 | static struct clk * gpt1_ick; | ||
272 | static struct clk * gpt1_fck; | ||
273 | |||
274 | static __init void omap_init_32k_timer(void) | ||
275 | { | ||
276 | #ifdef CONFIG_NO_IDLE_HZ | ||
277 | omap_timer.dyn_tick = &omap_dyn_tick_timer; | ||
278 | #endif | ||
279 | |||
280 | if (cpu_class_is_omap1()) | ||
281 | setup_irq(INT_OS_TIMER, &omap_32k_timer_irq); | ||
282 | if (cpu_is_omap24xx()) | ||
283 | setup_irq(37, &omap_32k_timer_irq); | ||
284 | omap_timer.offset = omap_32k_timer_gettimeoffset; | ||
285 | omap_32k_last_tick = omap_32k_sync_timer_read(); | ||
286 | |||
287 | /* REVISIT: Check 24xx TIOCP_CFG settings after idle works */ | ||
288 | if (cpu_is_omap24xx()) { | ||
289 | omap_32k_timer_write(0, GP_TIMER_TCLR); | ||
290 | omap_writel(0, CM_CLKSEL_WKUP); /* 32KHz clock source */ | ||
291 | |||
292 | gpt1_ick = clk_get(NULL, "gpt1_ick"); | ||
293 | if (IS_ERR(gpt1_ick)) | ||
294 | printk(KERN_ERR "Could not get gpt1_ick\n"); | ||
295 | else | ||
296 | clk_enable(gpt1_ick); | ||
297 | |||
298 | gpt1_fck = clk_get(NULL, "gpt1_fck"); | ||
299 | if (IS_ERR(gpt1_fck)) | ||
300 | printk(KERN_ERR "Could not get gpt1_fck\n"); | ||
301 | else | ||
302 | clk_enable(gpt1_fck); | ||
303 | |||
304 | mdelay(100); /* Wait for clocks to stabilize */ | ||
305 | |||
306 | omap_32k_timer_write(0x7, GP_TIMER_TISR); | ||
307 | } | ||
308 | |||
309 | omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD); | ||
310 | } | ||
311 | |||
312 | /* | ||
313 | * --------------------------------------------------------------------------- | ||
314 | * Timer initialization | ||
315 | * --------------------------------------------------------------------------- | ||
316 | */ | ||
317 | static void __init omap_timer_init(void) | ||
318 | { | ||
319 | omap_init_32k_timer(); | ||
320 | } | ||
321 | |||
322 | struct sys_timer omap_timer = { | ||
323 | .init = omap_timer_init, | ||
324 | .offset = NULL, /* Initialized later */ | ||
325 | }; | ||
diff --git a/arch/i386/kernel/crash.c b/arch/i386/kernel/crash.c index e3c5fca0aa8a..2b0cfce24a61 100644 --- a/arch/i386/kernel/crash.c +++ b/arch/i386/kernel/crash.c | |||
@@ -69,7 +69,7 @@ static void crash_save_this_cpu(struct pt_regs *regs, int cpu) | |||
69 | * for the data I pass, and I need tags | 69 | * for the data I pass, and I need tags |
70 | * on the data to indicate what information I have | 70 | * on the data to indicate what information I have |
71 | * squirrelled away. ELF notes happen to provide | 71 | * squirrelled away. ELF notes happen to provide |
72 | * all of that that no need to invent something new. | 72 | * all of that, so there is no need to invent something new. |
73 | */ | 73 | */ |
74 | buf = (u32*)per_cpu_ptr(crash_notes, cpu); | 74 | buf = (u32*)per_cpu_ptr(crash_notes, cpu); |
75 | if (!buf) | 75 | if (!buf) |
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index 5b26af8597f3..e112d1a5dab6 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c | |||
@@ -1740,7 +1740,7 @@ EXPORT_SYMBOL(blk_run_queue); | |||
1740 | 1740 | ||
1741 | /** | 1741 | /** |
1742 | * blk_cleanup_queue: - release a &request_queue_t when it is no longer needed | 1742 | * blk_cleanup_queue: - release a &request_queue_t when it is no longer needed |
1743 | * @q: the request queue to be released | 1743 | * @kobj: the kobj belonging of the request queue to be released |
1744 | * | 1744 | * |
1745 | * Description: | 1745 | * Description: |
1746 | * blk_cleanup_queue is the pair to blk_init_queue() or | 1746 | * blk_cleanup_queue is the pair to blk_init_queue() or |
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig index 16e99db2e12d..d53f664a4dd8 100644 --- a/drivers/char/watchdog/Kconfig +++ b/drivers/char/watchdog/Kconfig | |||
@@ -60,6 +60,13 @@ config SOFT_WATCHDOG | |||
60 | 60 | ||
61 | # ARM Architecture | 61 | # ARM Architecture |
62 | 62 | ||
63 | config AT91_WATCHDOG | ||
64 | tristate "AT91RM9200 watchdog" | ||
65 | depends on WATCHDOG && ARCH_AT91RM9200 | ||
66 | help | ||
67 | Watchdog timer embedded into AT91RM9200 chips. This will reboot your | ||
68 | system when the timeout is reached. | ||
69 | |||
63 | config 21285_WATCHDOG | 70 | config 21285_WATCHDOG |
64 | tristate "DC21285 watchdog" | 71 | tristate "DC21285 watchdog" |
65 | depends on WATCHDOG && FOOTBRIDGE | 72 | depends on WATCHDOG && FOOTBRIDGE |
diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile index d6f27fde9905..6ab77b61a643 100644 --- a/drivers/char/watchdog/Makefile +++ b/drivers/char/watchdog/Makefile | |||
@@ -23,6 +23,7 @@ obj-$(CONFIG_WDTPCI) += wdt_pci.o | |||
23 | obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o | 23 | obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o |
24 | 24 | ||
25 | # ARM Architecture | 25 | # ARM Architecture |
26 | obj-$(CONFIG_AT91_WATCHDOG) += at91_wdt.o | ||
26 | obj-$(CONFIG_21285_WATCHDOG) += wdt285.o | 27 | obj-$(CONFIG_21285_WATCHDOG) += wdt285.o |
27 | obj-$(CONFIG_977_WATCHDOG) += wdt977.o | 28 | obj-$(CONFIG_977_WATCHDOG) += wdt977.o |
28 | obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o | 29 | obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o |
diff --git a/drivers/char/watchdog/at91_wdt.c b/drivers/char/watchdog/at91_wdt.c new file mode 100644 index 000000000000..ac83bc4b019a --- /dev/null +++ b/drivers/char/watchdog/at91_wdt.c | |||
@@ -0,0 +1,228 @@ | |||
1 | /* | ||
2 | * Watchdog driver for Atmel AT91RM9200 (Thunder) | ||
3 | * | ||
4 | * Copyright (C) 2003 SAN People (Pty) Ltd | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/config.h> | ||
13 | #include <linux/errno.h> | ||
14 | #include <linux/fs.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/miscdevice.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/moduleparam.h> | ||
20 | #include <linux/types.h> | ||
21 | #include <linux/watchdog.h> | ||
22 | #include <asm/bitops.h> | ||
23 | #include <asm/uaccess.h> | ||
24 | |||
25 | |||
26 | #define WDT_DEFAULT_TIME 5 /* 5 seconds */ | ||
27 | #define WDT_MAX_TIME 256 /* 256 seconds */ | ||
28 | |||
29 | static int wdt_time = WDT_DEFAULT_TIME; | ||
30 | static int nowayout = WATCHDOG_NOWAYOUT; | ||
31 | |||
32 | module_param(wdt_time, int, 0); | ||
33 | MODULE_PARM_DESC(wdt_time, "Watchdog time in seconds. (default="__MODULE_STRING(WDT_DEFAULT_TIME) ")"); | ||
34 | |||
35 | module_param(nowayout, int, 0); | ||
36 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
37 | |||
38 | |||
39 | static unsigned long at91wdt_busy; | ||
40 | |||
41 | /* ......................................................................... */ | ||
42 | |||
43 | /* | ||
44 | * Disable the watchdog. | ||
45 | */ | ||
46 | static void inline at91_wdt_stop(void) | ||
47 | { | ||
48 | at91_sys_write(AT91_ST_WDMR, AT91_ST_EXTEN); | ||
49 | } | ||
50 | |||
51 | /* | ||
52 | * Enable and reset the watchdog. | ||
53 | */ | ||
54 | static void inline at91_wdt_start(void) | ||
55 | { | ||
56 | at91_sys_write(AT91_ST_WDMR, AT91_ST_EXTEN | AT91_ST_RSTEN | (((65536 * wdt_time) >> 8) & AT91_ST_WDV)); | ||
57 | at91_sys_write(AT91_ST_CR, AT91_ST_WDRST); | ||
58 | } | ||
59 | |||
60 | /* | ||
61 | * Reload the watchdog timer. (ie, pat the watchdog) | ||
62 | */ | ||
63 | static void inline at91_wdt_reload(void) | ||
64 | { | ||
65 | at91_sys_write(AT91_ST_CR, AT91_ST_WDRST); | ||
66 | } | ||
67 | |||
68 | /* ......................................................................... */ | ||
69 | |||
70 | /* | ||
71 | * Watchdog device is opened, and watchdog starts running. | ||
72 | */ | ||
73 | static int at91_wdt_open(struct inode *inode, struct file *file) | ||
74 | { | ||
75 | if (test_and_set_bit(0, &at91wdt_busy)) | ||
76 | return -EBUSY; | ||
77 | |||
78 | at91_wdt_start(); | ||
79 | return nonseekable_open(inode, file); | ||
80 | } | ||
81 | |||
82 | /* | ||
83 | * Close the watchdog device. | ||
84 | * If CONFIG_WATCHDOG_NOWAYOUT is NOT defined then the watchdog is also | ||
85 | * disabled. | ||
86 | */ | ||
87 | static int at91_wdt_close(struct inode *inode, struct file *file) | ||
88 | { | ||
89 | if (!nowayout) | ||
90 | at91_wdt_stop(); /* Disable the watchdog when file is closed */ | ||
91 | |||
92 | clear_bit(0, &at91wdt_busy); | ||
93 | return 0; | ||
94 | } | ||
95 | |||
96 | /* | ||
97 | * Change the watchdog time interval. | ||
98 | */ | ||
99 | static int at91_wdt_settimeout(int new_time) | ||
100 | { | ||
101 | /* | ||
102 | * All counting occurs at SLOW_CLOCK / 128 = 0.256 Hz | ||
103 | * | ||
104 | * Since WDV is a 16-bit counter, the maximum period is | ||
105 | * 65536 / 0.256 = 256 seconds. | ||
106 | */ | ||
107 | if ((new_time <= 0) || (new_time > WDT_MAX_TIME)) | ||
108 | return -EINVAL; | ||
109 | |||
110 | /* Set new watchdog time. It will be used when at91_wdt_start() is called. */ | ||
111 | wdt_time = new_time; | ||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | static struct watchdog_info at91_wdt_info = { | ||
116 | .identity = "at91 watchdog", | ||
117 | .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, | ||
118 | }; | ||
119 | |||
120 | /* | ||
121 | * Handle commands from user-space. | ||
122 | */ | ||
123 | static int at91_wdt_ioctl(struct inode *inode, struct file *file, | ||
124 | unsigned int cmd, unsigned long arg) | ||
125 | { | ||
126 | void __user *argp = (void __user *)arg; | ||
127 | int __user *p = argp; | ||
128 | int new_value; | ||
129 | |||
130 | switch(cmd) { | ||
131 | case WDIOC_KEEPALIVE: | ||
132 | at91_wdt_reload(); /* pat the watchdog */ | ||
133 | return 0; | ||
134 | |||
135 | case WDIOC_GETSUPPORT: | ||
136 | return copy_to_user(argp, &at91_wdt_info, sizeof(at91_wdt_info)) ? -EFAULT : 0; | ||
137 | |||
138 | case WDIOC_SETTIMEOUT: | ||
139 | if (get_user(new_value, p)) | ||
140 | return -EFAULT; | ||
141 | |||
142 | if (at91_wdt_settimeout(new_value)) | ||
143 | return -EINVAL; | ||
144 | |||
145 | /* Enable new time value */ | ||
146 | at91_wdt_start(); | ||
147 | |||
148 | /* Return current value */ | ||
149 | return put_user(wdt_time, p); | ||
150 | |||
151 | case WDIOC_GETTIMEOUT: | ||
152 | return put_user(wdt_time, p); | ||
153 | |||
154 | case WDIOC_GETSTATUS: | ||
155 | case WDIOC_GETBOOTSTATUS: | ||
156 | return put_user(0, p); | ||
157 | |||
158 | case WDIOC_SETOPTIONS: | ||
159 | if (get_user(new_value, p)) | ||
160 | return -EFAULT; | ||
161 | |||
162 | if (new_value & WDIOS_DISABLECARD) | ||
163 | at91_wdt_stop(); | ||
164 | if (new_value & WDIOS_ENABLECARD) | ||
165 | at91_wdt_start(); | ||
166 | return 0; | ||
167 | |||
168 | default: | ||
169 | return -ENOIOCTLCMD; | ||
170 | } | ||
171 | } | ||
172 | |||
173 | /* | ||
174 | * Pat the watchdog whenever device is written to. | ||
175 | */ | ||
176 | static ssize_t at91_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos) | ||
177 | { | ||
178 | at91_wdt_reload(); /* pat the watchdog */ | ||
179 | return len; | ||
180 | } | ||
181 | |||
182 | /* ......................................................................... */ | ||
183 | |||
184 | static struct file_operations at91wdt_fops = { | ||
185 | .owner = THIS_MODULE, | ||
186 | .llseek = no_llseek, | ||
187 | .ioctl = at91_wdt_ioctl, | ||
188 | .open = at91_wdt_open, | ||
189 | .release = at91_wdt_close, | ||
190 | .write = at91_wdt_write, | ||
191 | }; | ||
192 | |||
193 | static struct miscdevice at91wdt_miscdev = { | ||
194 | .minor = WATCHDOG_MINOR, | ||
195 | .name = "watchdog", | ||
196 | .fops = &at91wdt_fops, | ||
197 | }; | ||
198 | |||
199 | static int __init at91_wdt_init(void) | ||
200 | { | ||
201 | int res; | ||
202 | |||
203 | /* Check that the heartbeat value is within range; if not reset to the default */ | ||
204 | if (at91_wdt_settimeout(wdt_time)) { | ||
205 | at91_wdt_settimeout(WDT_DEFAULT_TIME); | ||
206 | printk(KERN_INFO "at91_wdt: wdt_time value must be 1 <= wdt_time <= 256, using %d\n", wdt_time); | ||
207 | } | ||
208 | |||
209 | res = misc_register(&at91wdt_miscdev); | ||
210 | if (res) | ||
211 | return res; | ||
212 | |||
213 | printk("AT91 Watchdog Timer enabled (%d seconds, nowayout=%d)\n", wdt_time, nowayout); | ||
214 | return 0; | ||
215 | } | ||
216 | |||
217 | static void __exit at91_wdt_exit(void) | ||
218 | { | ||
219 | misc_deregister(&at91wdt_miscdev); | ||
220 | } | ||
221 | |||
222 | module_init(at91_wdt_init); | ||
223 | module_exit(at91_wdt_exit); | ||
224 | |||
225 | MODULE_AUTHOR("Andrew Victor"); | ||
226 | MODULE_DESCRIPTION("Watchdog driver for Atmel AT91RM9200"); | ||
227 | MODULE_LICENSE("GPL"); | ||
228 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | ||
diff --git a/drivers/char/watchdog/pcwd.c b/drivers/char/watchdog/pcwd.c index 8d6b249ad66b..6d44ca68312d 100644 --- a/drivers/char/watchdog/pcwd.c +++ b/drivers/char/watchdog/pcwd.c | |||
@@ -66,15 +66,13 @@ | |||
66 | #include <linux/fs.h> /* For file operations */ | 66 | #include <linux/fs.h> /* For file operations */ |
67 | #include <linux/ioport.h> /* For io-port access */ | 67 | #include <linux/ioport.h> /* For io-port access */ |
68 | #include <linux/spinlock.h> /* For spin_lock/spin_unlock/... */ | 68 | #include <linux/spinlock.h> /* For spin_lock/spin_unlock/... */ |
69 | #include <linux/sched.h> /* TASK_INTERRUPTIBLE, set_current_state() and friends */ | ||
70 | #include <linux/slab.h> /* For kmalloc */ | ||
71 | 69 | ||
72 | #include <asm/uaccess.h> /* For copy_to_user/put_user/... */ | 70 | #include <asm/uaccess.h> /* For copy_to_user/put_user/... */ |
73 | #include <asm/io.h> /* For inb/outb/... */ | 71 | #include <asm/io.h> /* For inb/outb/... */ |
74 | 72 | ||
75 | /* Module and version information */ | 73 | /* Module and version information */ |
76 | #define WATCHDOG_VERSION "1.16" | 74 | #define WATCHDOG_VERSION "1.17" |
77 | #define WATCHDOG_DATE "03 Jan 2006" | 75 | #define WATCHDOG_DATE "12 Feb 2006" |
78 | #define WATCHDOG_DRIVER_NAME "ISA-PC Watchdog" | 76 | #define WATCHDOG_DRIVER_NAME "ISA-PC Watchdog" |
79 | #define WATCHDOG_NAME "pcwd" | 77 | #define WATCHDOG_NAME "pcwd" |
80 | #define PFX WATCHDOG_NAME ": " | 78 | #define PFX WATCHDOG_NAME ": " |
@@ -96,15 +94,19 @@ | |||
96 | * PCI-PC Watchdog card. | 94 | * PCI-PC Watchdog card. |
97 | */ | 95 | */ |
98 | /* Port 1 : Control Status #1 for the PC Watchdog card, revision A. */ | 96 | /* Port 1 : Control Status #1 for the PC Watchdog card, revision A. */ |
99 | #define WD_WDRST 0x01 /* Previously reset state */ | 97 | #define WD_WDRST 0x01 /* Previously reset state */ |
100 | #define WD_T110 0x02 /* Temperature overheat sense */ | 98 | #define WD_T110 0x02 /* Temperature overheat sense */ |
101 | #define WD_HRTBT 0x04 /* Heartbeat sense */ | 99 | #define WD_HRTBT 0x04 /* Heartbeat sense */ |
102 | #define WD_RLY2 0x08 /* External relay triggered */ | 100 | #define WD_RLY2 0x08 /* External relay triggered */ |
103 | #define WD_SRLY2 0x80 /* Software external relay triggered */ | 101 | #define WD_SRLY2 0x80 /* Software external relay triggered */ |
104 | /* Port 1 : Control Status #1 for the PC Watchdog card, revision C. */ | 102 | /* Port 1 : Control Status #1 for the PC Watchdog card, revision C. */ |
105 | #define WD_REVC_WTRP 0x01 /* Watchdog Trip status */ | 103 | #define WD_REVC_WTRP 0x01 /* Watchdog Trip status */ |
106 | #define WD_REVC_HRBT 0x02 /* Watchdog Heartbeat */ | 104 | #define WD_REVC_HRBT 0x02 /* Watchdog Heartbeat */ |
107 | #define WD_REVC_TTRP 0x04 /* Temperature Trip status */ | 105 | #define WD_REVC_TTRP 0x04 /* Temperature Trip status */ |
106 | #define WD_REVC_RL2A 0x08 /* Relay 2 activated by on-board processor */ | ||
107 | #define WD_REVC_RL1A 0x10 /* Relay 1 active */ | ||
108 | #define WD_REVC_R2DS 0x40 /* Relay 2 disable */ | ||
109 | #define WD_REVC_RLY2 0x80 /* Relay 2 activated? */ | ||
108 | /* Port 2 : Control Status #2 */ | 110 | /* Port 2 : Control Status #2 */ |
109 | #define WD_WDIS 0x10 /* Watchdog Disabled */ | 111 | #define WD_WDIS 0x10 /* Watchdog Disabled */ |
110 | #define WD_ENTP 0x20 /* Watchdog Enable Temperature Trip */ | 112 | #define WD_ENTP 0x20 /* Watchdog Enable Temperature Trip */ |
@@ -122,9 +124,14 @@ | |||
122 | #define CMD_ISA_VERSION_HUNDRETH 0x03 | 124 | #define CMD_ISA_VERSION_HUNDRETH 0x03 |
123 | #define CMD_ISA_VERSION_MINOR 0x04 | 125 | #define CMD_ISA_VERSION_MINOR 0x04 |
124 | #define CMD_ISA_SWITCH_SETTINGS 0x05 | 126 | #define CMD_ISA_SWITCH_SETTINGS 0x05 |
127 | #define CMD_ISA_RESET_PC 0x06 | ||
128 | #define CMD_ISA_ARM_0 0x07 | ||
129 | #define CMD_ISA_ARM_30 0x08 | ||
130 | #define CMD_ISA_ARM_60 0x09 | ||
125 | #define CMD_ISA_DELAY_TIME_2SECS 0x0A | 131 | #define CMD_ISA_DELAY_TIME_2SECS 0x0A |
126 | #define CMD_ISA_DELAY_TIME_4SECS 0x0B | 132 | #define CMD_ISA_DELAY_TIME_4SECS 0x0B |
127 | #define CMD_ISA_DELAY_TIME_8SECS 0x0C | 133 | #define CMD_ISA_DELAY_TIME_8SECS 0x0C |
134 | #define CMD_ISA_RESET_RELAYS 0x0D | ||
128 | 135 | ||
129 | /* | 136 | /* |
130 | * We are using an kernel timer to do the pinging of the watchdog | 137 | * We are using an kernel timer to do the pinging of the watchdog |
@@ -142,6 +149,7 @@ static atomic_t open_allowed = ATOMIC_INIT(1); | |||
142 | static char expect_close; | 149 | static char expect_close; |
143 | static int temp_panic; | 150 | static int temp_panic; |
144 | static struct { /* this is private data for each ISA-PC watchdog card */ | 151 | static struct { /* this is private data for each ISA-PC watchdog card */ |
152 | char fw_ver_str[6]; /* The cards firmware version */ | ||
145 | int revision; /* The card's revision */ | 153 | int revision; /* The card's revision */ |
146 | int supports_temp; /* Wether or not the card has a temperature device */ | 154 | int supports_temp; /* Wether or not the card has a temperature device */ |
147 | int command_mode; /* Wether or not the card is in command mode */ | 155 | int command_mode; /* Wether or not the card is in command mode */ |
@@ -153,6 +161,13 @@ static struct { /* this is private data for each ISA-PC watchdog card */ | |||
153 | } pcwd_private; | 161 | } pcwd_private; |
154 | 162 | ||
155 | /* module parameters */ | 163 | /* module parameters */ |
164 | #define QUIET 0 /* Default */ | ||
165 | #define VERBOSE 1 /* Verbose */ | ||
166 | #define DEBUG 2 /* print fancy stuff too */ | ||
167 | static int debug = QUIET; | ||
168 | module_param(debug, int, 0); | ||
169 | MODULE_PARM_DESC(debug, "Debug level: 0=Quiet, 1=Verbose, 2=Debug (default=0)"); | ||
170 | |||
156 | #define WATCHDOG_HEARTBEAT 60 /* 60 sec default heartbeat */ | 171 | #define WATCHDOG_HEARTBEAT 60 /* 60 sec default heartbeat */ |
157 | static int heartbeat = WATCHDOG_HEARTBEAT; | 172 | static int heartbeat = WATCHDOG_HEARTBEAT; |
158 | module_param(heartbeat, int, 0); | 173 | module_param(heartbeat, int, 0); |
@@ -172,6 +187,10 @@ static int send_isa_command(int cmd) | |||
172 | int control_status; | 187 | int control_status; |
173 | int port0, last_port0; /* Double read for stabilising */ | 188 | int port0, last_port0; /* Double read for stabilising */ |
174 | 189 | ||
190 | if (debug >= DEBUG) | ||
191 | printk(KERN_DEBUG PFX "sending following data cmd=0x%02x\n", | ||
192 | cmd); | ||
193 | |||
175 | /* The WCMD bit must be 1 and the command is only 4 bits in size */ | 194 | /* The WCMD bit must be 1 and the command is only 4 bits in size */ |
176 | control_status = (cmd & 0x0F) | WD_WCMD; | 195 | control_status = (cmd & 0x0F) | WD_WCMD; |
177 | outb_p(control_status, pcwd_private.io_addr + 2); | 196 | outb_p(control_status, pcwd_private.io_addr + 2); |
@@ -188,6 +207,10 @@ static int send_isa_command(int cmd) | |||
188 | udelay (250); | 207 | udelay (250); |
189 | } | 208 | } |
190 | 209 | ||
210 | if (debug >= DEBUG) | ||
211 | printk(KERN_DEBUG PFX "received following data for cmd=0x%02x: port0=0x%02x last_port0=0x%02x\n", | ||
212 | cmd, port0, last_port0); | ||
213 | |||
191 | return port0; | 214 | return port0; |
192 | } | 215 | } |
193 | 216 | ||
@@ -214,6 +237,10 @@ static int set_command_mode(void) | |||
214 | spin_unlock(&pcwd_private.io_lock); | 237 | spin_unlock(&pcwd_private.io_lock); |
215 | pcwd_private.command_mode = found; | 238 | pcwd_private.command_mode = found; |
216 | 239 | ||
240 | if (debug >= DEBUG) | ||
241 | printk(KERN_DEBUG PFX "command_mode=%d\n", | ||
242 | pcwd_private.command_mode); | ||
243 | |||
217 | return(found); | 244 | return(found); |
218 | } | 245 | } |
219 | 246 | ||
@@ -226,6 +253,10 @@ static void unset_command_mode(void) | |||
226 | spin_unlock(&pcwd_private.io_lock); | 253 | spin_unlock(&pcwd_private.io_lock); |
227 | 254 | ||
228 | pcwd_private.command_mode = 0; | 255 | pcwd_private.command_mode = 0; |
256 | |||
257 | if (debug >= DEBUG) | ||
258 | printk(KERN_DEBUG PFX "command_mode=%d\n", | ||
259 | pcwd_private.command_mode); | ||
229 | } | 260 | } |
230 | 261 | ||
231 | static inline void pcwd_check_temperature_support(void) | 262 | static inline void pcwd_check_temperature_support(void) |
@@ -234,27 +265,22 @@ static inline void pcwd_check_temperature_support(void) | |||
234 | pcwd_private.supports_temp = 1; | 265 | pcwd_private.supports_temp = 1; |
235 | } | 266 | } |
236 | 267 | ||
237 | static inline char *get_firmware(void) | 268 | static inline void pcwd_get_firmware(void) |
238 | { | 269 | { |
239 | int one, ten, hund, minor; | 270 | int one, ten, hund, minor; |
240 | char *ret; | ||
241 | 271 | ||
242 | ret = kmalloc(6, GFP_KERNEL); | 272 | strcpy(pcwd_private.fw_ver_str, "ERROR"); |
243 | if(ret == NULL) | ||
244 | return NULL; | ||
245 | 273 | ||
246 | if (set_command_mode()) { | 274 | if (set_command_mode()) { |
247 | one = send_isa_command(CMD_ISA_VERSION_INTEGER); | 275 | one = send_isa_command(CMD_ISA_VERSION_INTEGER); |
248 | ten = send_isa_command(CMD_ISA_VERSION_TENTH); | 276 | ten = send_isa_command(CMD_ISA_VERSION_TENTH); |
249 | hund = send_isa_command(CMD_ISA_VERSION_HUNDRETH); | 277 | hund = send_isa_command(CMD_ISA_VERSION_HUNDRETH); |
250 | minor = send_isa_command(CMD_ISA_VERSION_MINOR); | 278 | minor = send_isa_command(CMD_ISA_VERSION_MINOR); |
251 | sprintf(ret, "%c.%c%c%c", one, ten, hund, minor); | 279 | sprintf(pcwd_private.fw_ver_str, "%c.%c%c%c", one, ten, hund, minor); |
252 | } | 280 | } |
253 | else | ||
254 | sprintf(ret, "ERROR"); | ||
255 | |||
256 | unset_command_mode(); | 281 | unset_command_mode(); |
257 | return(ret); | 282 | |
283 | return; | ||
258 | } | 284 | } |
259 | 285 | ||
260 | static inline int pcwd_get_option_switches(void) | 286 | static inline int pcwd_get_option_switches(void) |
@@ -272,17 +298,15 @@ static inline int pcwd_get_option_switches(void) | |||
272 | 298 | ||
273 | static void pcwd_show_card_info(void) | 299 | static void pcwd_show_card_info(void) |
274 | { | 300 | { |
275 | char *firmware; | ||
276 | int option_switches; | 301 | int option_switches; |
277 | 302 | ||
278 | /* Get some extra info from the hardware (in command/debug/diag mode) */ | 303 | /* Get some extra info from the hardware (in command/debug/diag mode) */ |
279 | if (pcwd_private.revision == PCWD_REVISION_A) | 304 | if (pcwd_private.revision == PCWD_REVISION_A) |
280 | printk(KERN_INFO PFX "ISA-PC Watchdog (REV.A) detected at port 0x%04x\n", pcwd_private.io_addr); | 305 | printk(KERN_INFO PFX "ISA-PC Watchdog (REV.A) detected at port 0x%04x\n", pcwd_private.io_addr); |
281 | else if (pcwd_private.revision == PCWD_REVISION_C) { | 306 | else if (pcwd_private.revision == PCWD_REVISION_C) { |
282 | firmware = get_firmware(); | 307 | pcwd_get_firmware(); |
283 | printk(KERN_INFO PFX "ISA-PC Watchdog (REV.C) detected at port 0x%04x (Firmware version: %s)\n", | 308 | printk(KERN_INFO PFX "ISA-PC Watchdog (REV.C) detected at port 0x%04x (Firmware version: %s)\n", |
284 | pcwd_private.io_addr, firmware); | 309 | pcwd_private.io_addr, pcwd_private.fw_ver_str); |
285 | kfree(firmware); | ||
286 | option_switches = pcwd_get_option_switches(); | 310 | option_switches = pcwd_get_option_switches(); |
287 | printk(KERN_INFO PFX "Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n", | 311 | printk(KERN_INFO PFX "Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n", |
288 | option_switches, | 312 | option_switches, |
@@ -362,6 +386,10 @@ static int pcwd_start(void) | |||
362 | return -EIO; | 386 | return -EIO; |
363 | } | 387 | } |
364 | } | 388 | } |
389 | |||
390 | if (debug >= VERBOSE) | ||
391 | printk(KERN_DEBUG PFX "Watchdog started\n"); | ||
392 | |||
365 | return 0; | 393 | return 0; |
366 | } | 394 | } |
367 | 395 | ||
@@ -386,6 +414,10 @@ static int pcwd_stop(void) | |||
386 | return -EIO; | 414 | return -EIO; |
387 | } | 415 | } |
388 | } | 416 | } |
417 | |||
418 | if (debug >= VERBOSE) | ||
419 | printk(KERN_DEBUG PFX "Watchdog stopped\n"); | ||
420 | |||
389 | return 0; | 421 | return 0; |
390 | } | 422 | } |
391 | 423 | ||
@@ -393,6 +425,10 @@ static int pcwd_keepalive(void) | |||
393 | { | 425 | { |
394 | /* user land ping */ | 426 | /* user land ping */ |
395 | pcwd_private.next_heartbeat = jiffies + (heartbeat * HZ); | 427 | pcwd_private.next_heartbeat = jiffies + (heartbeat * HZ); |
428 | |||
429 | if (debug >= DEBUG) | ||
430 | printk(KERN_DEBUG PFX "Watchdog keepalive signal send\n"); | ||
431 | |||
396 | return 0; | 432 | return 0; |
397 | } | 433 | } |
398 | 434 | ||
@@ -402,12 +438,17 @@ static int pcwd_set_heartbeat(int t) | |||
402 | return -EINVAL; | 438 | return -EINVAL; |
403 | 439 | ||
404 | heartbeat = t; | 440 | heartbeat = t; |
441 | |||
442 | if (debug >= VERBOSE) | ||
443 | printk(KERN_DEBUG PFX "New heartbeat: %d\n", | ||
444 | heartbeat); | ||
445 | |||
405 | return 0; | 446 | return 0; |
406 | } | 447 | } |
407 | 448 | ||
408 | static int pcwd_get_status(int *status) | 449 | static int pcwd_get_status(int *status) |
409 | { | 450 | { |
410 | int card_status; | 451 | int control_status; |
411 | 452 | ||
412 | *status=0; | 453 | *status=0; |
413 | spin_lock(&pcwd_private.io_lock); | 454 | spin_lock(&pcwd_private.io_lock); |
@@ -415,37 +456,39 @@ static int pcwd_get_status(int *status) | |||
415 | /* Rev A cards return status information from | 456 | /* Rev A cards return status information from |
416 | * the base register, which is used for the | 457 | * the base register, which is used for the |
417 | * temperature in other cards. */ | 458 | * temperature in other cards. */ |
418 | card_status = inb(pcwd_private.io_addr); | 459 | control_status = inb(pcwd_private.io_addr); |
419 | else { | 460 | else { |
420 | /* Rev C cards return card status in the base | 461 | /* Rev C cards return card status in the base |
421 | * address + 1 register. And use different bits | 462 | * address + 1 register. And use different bits |
422 | * to indicate a card initiated reset, and an | 463 | * to indicate a card initiated reset, and an |
423 | * over-temperature condition. And the reboot | 464 | * over-temperature condition. And the reboot |
424 | * status can be reset. */ | 465 | * status can be reset. */ |
425 | card_status = inb(pcwd_private.io_addr + 1); | 466 | control_status = inb(pcwd_private.io_addr + 1); |
426 | } | 467 | } |
427 | spin_unlock(&pcwd_private.io_lock); | 468 | spin_unlock(&pcwd_private.io_lock); |
428 | 469 | ||
429 | if (pcwd_private.revision == PCWD_REVISION_A) { | 470 | if (pcwd_private.revision == PCWD_REVISION_A) { |
430 | if (card_status & WD_WDRST) | 471 | if (control_status & WD_WDRST) |
431 | *status |= WDIOF_CARDRESET; | 472 | *status |= WDIOF_CARDRESET; |
432 | 473 | ||
433 | if (card_status & WD_T110) { | 474 | if (control_status & WD_T110) { |
434 | *status |= WDIOF_OVERHEAT; | 475 | *status |= WDIOF_OVERHEAT; |
435 | if (temp_panic) { | 476 | if (temp_panic) { |
436 | printk (KERN_INFO PFX "Temperature overheat trip!\n"); | 477 | printk (KERN_INFO PFX "Temperature overheat trip!\n"); |
437 | kernel_power_off(); | 478 | kernel_power_off(); |
479 | /* or should we just do a: panic(PFX "Temperature overheat trip!\n"); */ | ||
438 | } | 480 | } |
439 | } | 481 | } |
440 | } else { | 482 | } else { |
441 | if (card_status & WD_REVC_WTRP) | 483 | if (control_status & WD_REVC_WTRP) |
442 | *status |= WDIOF_CARDRESET; | 484 | *status |= WDIOF_CARDRESET; |
443 | 485 | ||
444 | if (card_status & WD_REVC_TTRP) { | 486 | if (control_status & WD_REVC_TTRP) { |
445 | *status |= WDIOF_OVERHEAT; | 487 | *status |= WDIOF_OVERHEAT; |
446 | if (temp_panic) { | 488 | if (temp_panic) { |
447 | printk (KERN_INFO PFX "Temperature overheat trip!\n"); | 489 | printk (KERN_INFO PFX "Temperature overheat trip!\n"); |
448 | kernel_power_off(); | 490 | kernel_power_off(); |
491 | /* or should we just do a: panic(PFX "Temperature overheat trip!\n"); */ | ||
449 | } | 492 | } |
450 | } | 493 | } |
451 | } | 494 | } |
@@ -455,9 +498,25 @@ static int pcwd_get_status(int *status) | |||
455 | 498 | ||
456 | static int pcwd_clear_status(void) | 499 | static int pcwd_clear_status(void) |
457 | { | 500 | { |
501 | int control_status; | ||
502 | |||
458 | if (pcwd_private.revision == PCWD_REVISION_C) { | 503 | if (pcwd_private.revision == PCWD_REVISION_C) { |
459 | spin_lock(&pcwd_private.io_lock); | 504 | spin_lock(&pcwd_private.io_lock); |
460 | outb_p(0x00, pcwd_private.io_addr + 1); /* clear reset status */ | 505 | |
506 | if (debug >= VERBOSE) | ||
507 | printk(KERN_INFO PFX "clearing watchdog trip status\n"); | ||
508 | |||
509 | control_status = inb_p(pcwd_private.io_addr + 1); | ||
510 | |||
511 | if (debug >= DEBUG) { | ||
512 | printk(KERN_DEBUG PFX "status was: 0x%02x\n", control_status); | ||
513 | printk(KERN_DEBUG PFX "sending: 0x%02x\n", | ||
514 | (control_status & WD_REVC_R2DS)); | ||
515 | } | ||
516 | |||
517 | /* clear reset status & Keep Relay 2 disable state as it is */ | ||
518 | outb_p((control_status & WD_REVC_R2DS), pcwd_private.io_addr + 1); | ||
519 | |||
461 | spin_unlock(&pcwd_private.io_lock); | 520 | spin_unlock(&pcwd_private.io_lock); |
462 | } | 521 | } |
463 | return 0; | 522 | return 0; |
@@ -481,6 +540,11 @@ static int pcwd_get_temperature(int *temperature) | |||
481 | *temperature = ((inb(pcwd_private.io_addr)) * 9 / 5) + 32; | 540 | *temperature = ((inb(pcwd_private.io_addr)) * 9 / 5) + 32; |
482 | spin_unlock(&pcwd_private.io_lock); | 541 | spin_unlock(&pcwd_private.io_lock); |
483 | 542 | ||
543 | if (debug >= DEBUG) { | ||
544 | printk(KERN_DEBUG PFX "temperature is: %d F\n", | ||
545 | *temperature); | ||
546 | } | ||
547 | |||
484 | return 0; | 548 | return 0; |
485 | } | 549 | } |
486 | 550 | ||
@@ -599,6 +663,8 @@ static ssize_t pcwd_write(struct file *file, const char __user *buf, size_t len, | |||
599 | static int pcwd_open(struct inode *inode, struct file *file) | 663 | static int pcwd_open(struct inode *inode, struct file *file) |
600 | { | 664 | { |
601 | if (!atomic_dec_and_test(&open_allowed) ) { | 665 | if (!atomic_dec_and_test(&open_allowed) ) { |
666 | if (debug >= VERBOSE) | ||
667 | printk(KERN_ERR PFX "Attempt to open already opened device.\n"); | ||
602 | atomic_inc( &open_allowed ); | 668 | atomic_inc( &open_allowed ); |
603 | return -EBUSY; | 669 | return -EBUSY; |
604 | } | 670 | } |
@@ -922,7 +988,8 @@ static void __exit pcwd_cleanup_module(void) | |||
922 | { | 988 | { |
923 | if (pcwd_private.io_addr) | 989 | if (pcwd_private.io_addr) |
924 | pcwatchdog_exit(); | 990 | pcwatchdog_exit(); |
925 | return; | 991 | |
992 | printk(KERN_INFO PFX "Watchdog Module Unloaded.\n"); | ||
926 | } | 993 | } |
927 | 994 | ||
928 | module_init(pcwd_init_module); | 995 | module_init(pcwd_init_module); |
diff --git a/drivers/char/watchdog/pcwd_usb.c b/drivers/char/watchdog/pcwd_usb.c index 2700c5c45b8a..3fdfda9324fa 100644 --- a/drivers/char/watchdog/pcwd_usb.c +++ b/drivers/char/watchdog/pcwd_usb.c | |||
@@ -705,7 +705,8 @@ err_out_misc_deregister: | |||
705 | err_out_unregister_reboot: | 705 | err_out_unregister_reboot: |
706 | unregister_reboot_notifier(&usb_pcwd_notifier); | 706 | unregister_reboot_notifier(&usb_pcwd_notifier); |
707 | error: | 707 | error: |
708 | usb_pcwd_delete (usb_pcwd); | 708 | if (usb_pcwd) |
709 | usb_pcwd_delete(usb_pcwd); | ||
709 | usb_pcwd_device = NULL; | 710 | usb_pcwd_device = NULL; |
710 | return retval; | 711 | return retval; |
711 | } | 712 | } |
diff --git a/drivers/hwmon/hdaps.c b/drivers/hwmon/hdaps.c index 7636c1a58f9c..23a9e1ea8e32 100644 --- a/drivers/hwmon/hdaps.c +++ b/drivers/hwmon/hdaps.c | |||
@@ -33,7 +33,6 @@ | |||
33 | #include <linux/module.h> | 33 | #include <linux/module.h> |
34 | #include <linux/timer.h> | 34 | #include <linux/timer.h> |
35 | #include <linux/dmi.h> | 35 | #include <linux/dmi.h> |
36 | #include <linux/mutex.h> | ||
37 | #include <asm/io.h> | 36 | #include <asm/io.h> |
38 | 37 | ||
39 | #define HDAPS_LOW_PORT 0x1600 /* first port used by hdaps */ | 38 | #define HDAPS_LOW_PORT 0x1600 /* first port used by hdaps */ |
@@ -71,10 +70,10 @@ static u8 km_activity; | |||
71 | static int rest_x; | 70 | static int rest_x; |
72 | static int rest_y; | 71 | static int rest_y; |
73 | 72 | ||
74 | static DEFINE_MUTEX(hdaps_mutex); | 73 | static DECLARE_MUTEX(hdaps_sem); |
75 | 74 | ||
76 | /* | 75 | /* |
77 | * __get_latch - Get the value from a given port. Callers must hold hdaps_mutex. | 76 | * __get_latch - Get the value from a given port. Callers must hold hdaps_sem. |
78 | */ | 77 | */ |
79 | static inline u8 __get_latch(u16 port) | 78 | static inline u8 __get_latch(u16 port) |
80 | { | 79 | { |
@@ -83,7 +82,7 @@ static inline u8 __get_latch(u16 port) | |||
83 | 82 | ||
84 | /* | 83 | /* |
85 | * __check_latch - Check a port latch for a given value. Returns zero if the | 84 | * __check_latch - Check a port latch for a given value. Returns zero if the |
86 | * port contains the given value. Callers must hold hdaps_mutex. | 85 | * port contains the given value. Callers must hold hdaps_sem. |
87 | */ | 86 | */ |
88 | static inline int __check_latch(u16 port, u8 val) | 87 | static inline int __check_latch(u16 port, u8 val) |
89 | { | 88 | { |
@@ -94,7 +93,7 @@ static inline int __check_latch(u16 port, u8 val) | |||
94 | 93 | ||
95 | /* | 94 | /* |
96 | * __wait_latch - Wait up to 100us for a port latch to get a certain value, | 95 | * __wait_latch - Wait up to 100us for a port latch to get a certain value, |
97 | * returning zero if the value is obtained. Callers must hold hdaps_mutex. | 96 | * returning zero if the value is obtained. Callers must hold hdaps_sem. |
98 | */ | 97 | */ |
99 | static int __wait_latch(u16 port, u8 val) | 98 | static int __wait_latch(u16 port, u8 val) |
100 | { | 99 | { |
@@ -111,7 +110,7 @@ static int __wait_latch(u16 port, u8 val) | |||
111 | 110 | ||
112 | /* | 111 | /* |
113 | * __device_refresh - request a refresh from the accelerometer. Does not wait | 112 | * __device_refresh - request a refresh from the accelerometer. Does not wait |
114 | * for refresh to complete. Callers must hold hdaps_mutex. | 113 | * for refresh to complete. Callers must hold hdaps_sem. |
115 | */ | 114 | */ |
116 | static void __device_refresh(void) | 115 | static void __device_refresh(void) |
117 | { | 116 | { |
@@ -125,7 +124,7 @@ static void __device_refresh(void) | |||
125 | /* | 124 | /* |
126 | * __device_refresh_sync - request a synchronous refresh from the | 125 | * __device_refresh_sync - request a synchronous refresh from the |
127 | * accelerometer. We wait for the refresh to complete. Returns zero if | 126 | * accelerometer. We wait for the refresh to complete. Returns zero if |
128 | * successful and nonzero on error. Callers must hold hdaps_mutex. | 127 | * successful and nonzero on error. Callers must hold hdaps_sem. |
129 | */ | 128 | */ |
130 | static int __device_refresh_sync(void) | 129 | static int __device_refresh_sync(void) |
131 | { | 130 | { |
@@ -135,7 +134,7 @@ static int __device_refresh_sync(void) | |||
135 | 134 | ||
136 | /* | 135 | /* |
137 | * __device_complete - indicate to the accelerometer that we are done reading | 136 | * __device_complete - indicate to the accelerometer that we are done reading |
138 | * data, and then initiate an async refresh. Callers must hold hdaps_mutex. | 137 | * data, and then initiate an async refresh. Callers must hold hdaps_sem. |
139 | */ | 138 | */ |
140 | static inline void __device_complete(void) | 139 | static inline void __device_complete(void) |
141 | { | 140 | { |
@@ -153,7 +152,7 @@ static int hdaps_readb_one(unsigned int port, u8 *val) | |||
153 | { | 152 | { |
154 | int ret; | 153 | int ret; |
155 | 154 | ||
156 | mutex_lock(&hdaps_mutex); | 155 | down(&hdaps_sem); |
157 | 156 | ||
158 | /* do a sync refresh -- we need to be sure that we read fresh data */ | 157 | /* do a sync refresh -- we need to be sure that we read fresh data */ |
159 | ret = __device_refresh_sync(); | 158 | ret = __device_refresh_sync(); |
@@ -164,7 +163,7 @@ static int hdaps_readb_one(unsigned int port, u8 *val) | |||
164 | __device_complete(); | 163 | __device_complete(); |
165 | 164 | ||
166 | out: | 165 | out: |
167 | mutex_unlock(&hdaps_mutex); | 166 | up(&hdaps_sem); |
168 | return ret; | 167 | return ret; |
169 | } | 168 | } |
170 | 169 | ||
@@ -199,9 +198,9 @@ static int hdaps_read_pair(unsigned int port1, unsigned int port2, | |||
199 | { | 198 | { |
200 | int ret; | 199 | int ret; |
201 | 200 | ||
202 | mutex_lock(&hdaps_mutex); | 201 | down(&hdaps_sem); |
203 | ret = __hdaps_read_pair(port1, port2, val1, val2); | 202 | ret = __hdaps_read_pair(port1, port2, val1, val2); |
204 | mutex_unlock(&hdaps_mutex); | 203 | up(&hdaps_sem); |
205 | 204 | ||
206 | return ret; | 205 | return ret; |
207 | } | 206 | } |
@@ -214,7 +213,7 @@ static int hdaps_device_init(void) | |||
214 | { | 213 | { |
215 | int total, ret = -ENXIO; | 214 | int total, ret = -ENXIO; |
216 | 215 | ||
217 | mutex_lock(&hdaps_mutex); | 216 | down(&hdaps_sem); |
218 | 217 | ||
219 | outb(0x13, 0x1610); | 218 | outb(0x13, 0x1610); |
220 | outb(0x01, 0x161f); | 219 | outb(0x01, 0x161f); |
@@ -280,7 +279,7 @@ static int hdaps_device_init(void) | |||
280 | } | 279 | } |
281 | 280 | ||
282 | out: | 281 | out: |
283 | mutex_unlock(&hdaps_mutex); | 282 | up(&hdaps_sem); |
284 | return ret; | 283 | return ret; |
285 | } | 284 | } |
286 | 285 | ||
@@ -314,7 +313,7 @@ static struct platform_driver hdaps_driver = { | |||
314 | }; | 313 | }; |
315 | 314 | ||
316 | /* | 315 | /* |
317 | * hdaps_calibrate - Set our "resting" values. Callers must hold hdaps_mutex. | 316 | * hdaps_calibrate - Set our "resting" values. Callers must hold hdaps_sem. |
318 | */ | 317 | */ |
319 | static void hdaps_calibrate(void) | 318 | static void hdaps_calibrate(void) |
320 | { | 319 | { |
@@ -326,7 +325,7 @@ static void hdaps_mousedev_poll(unsigned long unused) | |||
326 | int x, y; | 325 | int x, y; |
327 | 326 | ||
328 | /* Cannot sleep. Try nonblockingly. If we fail, try again later. */ | 327 | /* Cannot sleep. Try nonblockingly. If we fail, try again later. */ |
329 | if (!mutex_trylock(&hdaps_mutex)) { | 328 | if (down_trylock(&hdaps_sem)) { |
330 | mod_timer(&hdaps_timer,jiffies + HDAPS_POLL_PERIOD); | 329 | mod_timer(&hdaps_timer,jiffies + HDAPS_POLL_PERIOD); |
331 | return; | 330 | return; |
332 | } | 331 | } |
@@ -341,7 +340,7 @@ static void hdaps_mousedev_poll(unsigned long unused) | |||
341 | mod_timer(&hdaps_timer, jiffies + HDAPS_POLL_PERIOD); | 340 | mod_timer(&hdaps_timer, jiffies + HDAPS_POLL_PERIOD); |
342 | 341 | ||
343 | out: | 342 | out: |
344 | mutex_unlock(&hdaps_mutex); | 343 | up(&hdaps_sem); |
345 | } | 344 | } |
346 | 345 | ||
347 | 346 | ||
@@ -421,9 +420,9 @@ static ssize_t hdaps_calibrate_store(struct device *dev, | |||
421 | struct device_attribute *attr, | 420 | struct device_attribute *attr, |
422 | const char *buf, size_t count) | 421 | const char *buf, size_t count) |
423 | { | 422 | { |
424 | mutex_lock(&hdaps_mutex); | 423 | down(&hdaps_sem); |
425 | hdaps_calibrate(); | 424 | hdaps_calibrate(); |
426 | mutex_unlock(&hdaps_mutex); | 425 | up(&hdaps_sem); |
427 | 426 | ||
428 | return count; | 427 | return count; |
429 | } | 428 | } |
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index 2c765ca5aa50..f4206604db03 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c | |||
@@ -496,22 +496,17 @@ static struct sbp2_command_info *sbp2util_find_command_for_orb( | |||
496 | /* | 496 | /* |
497 | * This function finds the sbp2_command for a given outstanding SCpnt. | 497 | * This function finds the sbp2_command for a given outstanding SCpnt. |
498 | * Only looks at the inuse list. | 498 | * Only looks at the inuse list. |
499 | * Must be called with scsi_id->sbp2_command_orb_lock held. | ||
499 | */ | 500 | */ |
500 | static struct sbp2_command_info *sbp2util_find_command_for_SCpnt(struct scsi_id_instance_data *scsi_id, void *SCpnt) | 501 | static struct sbp2_command_info *sbp2util_find_command_for_SCpnt( |
502 | struct scsi_id_instance_data *scsi_id, void *SCpnt) | ||
501 | { | 503 | { |
502 | struct sbp2_command_info *command; | 504 | struct sbp2_command_info *command; |
503 | unsigned long flags; | ||
504 | 505 | ||
505 | spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags); | 506 | if (!list_empty(&scsi_id->sbp2_command_orb_inuse)) |
506 | if (!list_empty(&scsi_id->sbp2_command_orb_inuse)) { | 507 | list_for_each_entry(command, &scsi_id->sbp2_command_orb_inuse, list) |
507 | list_for_each_entry(command, &scsi_id->sbp2_command_orb_inuse, list) { | 508 | if (command->Current_SCpnt == SCpnt) |
508 | if (command->Current_SCpnt == SCpnt) { | ||
509 | spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); | ||
510 | return command; | 509 | return command; |
511 | } | ||
512 | } | ||
513 | } | ||
514 | spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); | ||
515 | return NULL; | 510 | return NULL; |
516 | } | 511 | } |
517 | 512 | ||
@@ -580,17 +575,15 @@ static void sbp2util_free_command_dma(struct sbp2_command_info *command) | |||
580 | 575 | ||
581 | /* | 576 | /* |
582 | * This function moves a command to the completed orb list. | 577 | * This function moves a command to the completed orb list. |
578 | * Must be called with scsi_id->sbp2_command_orb_lock held. | ||
583 | */ | 579 | */ |
584 | static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_id, | 580 | static void sbp2util_mark_command_completed( |
585 | struct sbp2_command_info *command) | 581 | struct scsi_id_instance_data *scsi_id, |
582 | struct sbp2_command_info *command) | ||
586 | { | 583 | { |
587 | unsigned long flags; | ||
588 | |||
589 | spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags); | ||
590 | list_del(&command->list); | 584 | list_del(&command->list); |
591 | sbp2util_free_command_dma(command); | 585 | sbp2util_free_command_dma(command); |
592 | list_add_tail(&command->list, &scsi_id->sbp2_command_orb_completed); | 586 | list_add_tail(&command->list, &scsi_id->sbp2_command_orb_completed); |
593 | spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); | ||
594 | } | 587 | } |
595 | 588 | ||
596 | /* | 589 | /* |
@@ -2148,7 +2141,9 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest | |||
2148 | * Matched status with command, now grab scsi command pointers and check status | 2141 | * Matched status with command, now grab scsi command pointers and check status |
2149 | */ | 2142 | */ |
2150 | SCpnt = command->Current_SCpnt; | 2143 | SCpnt = command->Current_SCpnt; |
2144 | spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags); | ||
2151 | sbp2util_mark_command_completed(scsi_id, command); | 2145 | sbp2util_mark_command_completed(scsi_id, command); |
2146 | spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); | ||
2152 | 2147 | ||
2153 | if (SCpnt) { | 2148 | if (SCpnt) { |
2154 | 2149 | ||
@@ -2484,6 +2479,7 @@ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt) | |||
2484 | (struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0]; | 2479 | (struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0]; |
2485 | struct sbp2scsi_host_info *hi = scsi_id->hi; | 2480 | struct sbp2scsi_host_info *hi = scsi_id->hi; |
2486 | struct sbp2_command_info *command; | 2481 | struct sbp2_command_info *command; |
2482 | unsigned long flags; | ||
2487 | 2483 | ||
2488 | SBP2_ERR("aborting sbp2 command"); | 2484 | SBP2_ERR("aborting sbp2 command"); |
2489 | scsi_print_command(SCpnt); | 2485 | scsi_print_command(SCpnt); |
@@ -2494,6 +2490,7 @@ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt) | |||
2494 | * Right now, just return any matching command structures | 2490 | * Right now, just return any matching command structures |
2495 | * to the free pool. | 2491 | * to the free pool. |
2496 | */ | 2492 | */ |
2493 | spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags); | ||
2497 | command = sbp2util_find_command_for_SCpnt(scsi_id, SCpnt); | 2494 | command = sbp2util_find_command_for_SCpnt(scsi_id, SCpnt); |
2498 | if (command) { | 2495 | if (command) { |
2499 | SBP2_DEBUG("Found command to abort"); | 2496 | SBP2_DEBUG("Found command to abort"); |
@@ -2511,6 +2508,7 @@ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt) | |||
2511 | command->Current_done(command->Current_SCpnt); | 2508 | command->Current_done(command->Current_SCpnt); |
2512 | } | 2509 | } |
2513 | } | 2510 | } |
2511 | spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); | ||
2514 | 2512 | ||
2515 | /* | 2513 | /* |
2516 | * Initiate a fetch agent reset. | 2514 | * Initiate a fetch agent reset. |
diff --git a/drivers/md/dm-target.c b/drivers/md/dm-target.c index aecd9e0c2616..64fd8e79ea4c 100644 --- a/drivers/md/dm-target.c +++ b/drivers/md/dm-target.c | |||
@@ -78,8 +78,7 @@ void dm_put_target_type(struct target_type *t) | |||
78 | if (--ti->use == 0) | 78 | if (--ti->use == 0) |
79 | module_put(ti->tt.module); | 79 | module_put(ti->tt.module); |
80 | 80 | ||
81 | if (ti->use < 0) | 81 | BUG_ON(ti->use < 0); |
82 | BUG(); | ||
83 | up_read(&_lock); | 82 | up_read(&_lock); |
84 | 83 | ||
85 | return; | 84 | return; |
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 9b374c91db66..6081941de1b3 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c | |||
@@ -1558,8 +1558,7 @@ static int init_resync(conf_t *conf) | |||
1558 | int buffs; | 1558 | int buffs; |
1559 | 1559 | ||
1560 | buffs = RESYNC_WINDOW / RESYNC_BLOCK_SIZE; | 1560 | buffs = RESYNC_WINDOW / RESYNC_BLOCK_SIZE; |
1561 | if (conf->r1buf_pool) | 1561 | BUG_ON(conf->r1buf_pool); |
1562 | BUG(); | ||
1563 | conf->r1buf_pool = mempool_create(buffs, r1buf_pool_alloc, r1buf_pool_free, | 1562 | conf->r1buf_pool = mempool_create(buffs, r1buf_pool_alloc, r1buf_pool_free, |
1564 | conf->poolinfo); | 1563 | conf->poolinfo); |
1565 | if (!conf->r1buf_pool) | 1564 | if (!conf->r1buf_pool) |
@@ -1732,8 +1731,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i | |||
1732 | !conf->fullsync && | 1731 | !conf->fullsync && |
1733 | !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) | 1732 | !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) |
1734 | break; | 1733 | break; |
1735 | if (sync_blocks < (PAGE_SIZE>>9)) | 1734 | BUG_ON(sync_blocks < (PAGE_SIZE>>9)); |
1736 | BUG(); | ||
1737 | if (len > (sync_blocks<<9)) | 1735 | if (len > (sync_blocks<<9)) |
1738 | len = sync_blocks<<9; | 1736 | len = sync_blocks<<9; |
1739 | } | 1737 | } |
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index ab90a6d12020..617012bc107a 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c | |||
@@ -1117,8 +1117,7 @@ static int end_sync_read(struct bio *bio, unsigned int bytes_done, int error) | |||
1117 | for (i=0; i<conf->copies; i++) | 1117 | for (i=0; i<conf->copies; i++) |
1118 | if (r10_bio->devs[i].bio == bio) | 1118 | if (r10_bio->devs[i].bio == bio) |
1119 | break; | 1119 | break; |
1120 | if (i == conf->copies) | 1120 | BUG_ON(i == conf->copies); |
1121 | BUG(); | ||
1122 | update_head_pos(i, r10_bio); | 1121 | update_head_pos(i, r10_bio); |
1123 | d = r10_bio->devs[i].devnum; | 1122 | d = r10_bio->devs[i].devnum; |
1124 | 1123 | ||
@@ -1518,8 +1517,7 @@ static int init_resync(conf_t *conf) | |||
1518 | int buffs; | 1517 | int buffs; |
1519 | 1518 | ||
1520 | buffs = RESYNC_WINDOW / RESYNC_BLOCK_SIZE; | 1519 | buffs = RESYNC_WINDOW / RESYNC_BLOCK_SIZE; |
1521 | if (conf->r10buf_pool) | 1520 | BUG_ON(conf->r10buf_pool); |
1522 | BUG(); | ||
1523 | conf->r10buf_pool = mempool_create(buffs, r10buf_pool_alloc, r10buf_pool_free, conf); | 1521 | conf->r10buf_pool = mempool_create(buffs, r10buf_pool_alloc, r10buf_pool_free, conf); |
1524 | if (!conf->r10buf_pool) | 1522 | if (!conf->r10buf_pool) |
1525 | return -ENOMEM; | 1523 | return -ENOMEM; |
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index dae740adaf65..31843604049c 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
@@ -73,10 +73,8 @@ static void print_raid5_conf (raid5_conf_t *conf); | |||
73 | static void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh) | 73 | static void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh) |
74 | { | 74 | { |
75 | if (atomic_dec_and_test(&sh->count)) { | 75 | if (atomic_dec_and_test(&sh->count)) { |
76 | if (!list_empty(&sh->lru)) | 76 | BUG_ON(!list_empty(&sh->lru)); |
77 | BUG(); | 77 | BUG_ON(atomic_read(&conf->active_stripes)==0); |
78 | if (atomic_read(&conf->active_stripes)==0) | ||
79 | BUG(); | ||
80 | if (test_bit(STRIPE_HANDLE, &sh->state)) { | 78 | if (test_bit(STRIPE_HANDLE, &sh->state)) { |
81 | if (test_bit(STRIPE_DELAYED, &sh->state)) | 79 | if (test_bit(STRIPE_DELAYED, &sh->state)) |
82 | list_add_tail(&sh->lru, &conf->delayed_list); | 80 | list_add_tail(&sh->lru, &conf->delayed_list); |
@@ -184,10 +182,8 @@ static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx, int | |||
184 | raid5_conf_t *conf = sh->raid_conf; | 182 | raid5_conf_t *conf = sh->raid_conf; |
185 | int i; | 183 | int i; |
186 | 184 | ||
187 | if (atomic_read(&sh->count) != 0) | 185 | BUG_ON(atomic_read(&sh->count) != 0); |
188 | BUG(); | 186 | BUG_ON(test_bit(STRIPE_HANDLE, &sh->state)); |
189 | if (test_bit(STRIPE_HANDLE, &sh->state)) | ||
190 | BUG(); | ||
191 | 187 | ||
192 | CHECK_DEVLOCK(); | 188 | CHECK_DEVLOCK(); |
193 | PRINTK("init_stripe called, stripe %llu\n", | 189 | PRINTK("init_stripe called, stripe %llu\n", |
@@ -269,8 +265,7 @@ static struct stripe_head *get_active_stripe(raid5_conf_t *conf, sector_t sector | |||
269 | init_stripe(sh, sector, pd_idx, disks); | 265 | init_stripe(sh, sector, pd_idx, disks); |
270 | } else { | 266 | } else { |
271 | if (atomic_read(&sh->count)) { | 267 | if (atomic_read(&sh->count)) { |
272 | if (!list_empty(&sh->lru)) | 268 | BUG_ON(!list_empty(&sh->lru)); |
273 | BUG(); | ||
274 | } else { | 269 | } else { |
275 | if (!test_bit(STRIPE_HANDLE, &sh->state)) | 270 | if (!test_bit(STRIPE_HANDLE, &sh->state)) |
276 | atomic_inc(&conf->active_stripes); | 271 | atomic_inc(&conf->active_stripes); |
@@ -465,8 +460,7 @@ static int drop_one_stripe(raid5_conf_t *conf) | |||
465 | spin_unlock_irq(&conf->device_lock); | 460 | spin_unlock_irq(&conf->device_lock); |
466 | if (!sh) | 461 | if (!sh) |
467 | return 0; | 462 | return 0; |
468 | if (atomic_read(&sh->count)) | 463 | BUG_ON(atomic_read(&sh->count)); |
469 | BUG(); | ||
470 | shrink_buffers(sh, conf->pool_size); | 464 | shrink_buffers(sh, conf->pool_size); |
471 | kmem_cache_free(conf->slab_cache, sh); | 465 | kmem_cache_free(conf->slab_cache, sh); |
472 | atomic_dec(&conf->active_stripes); | 466 | atomic_dec(&conf->active_stripes); |
@@ -882,8 +876,7 @@ static void compute_parity(struct stripe_head *sh, int method) | |||
882 | ptr[0] = page_address(sh->dev[pd_idx].page); | 876 | ptr[0] = page_address(sh->dev[pd_idx].page); |
883 | switch(method) { | 877 | switch(method) { |
884 | case READ_MODIFY_WRITE: | 878 | case READ_MODIFY_WRITE: |
885 | if (!test_bit(R5_UPTODATE, &sh->dev[pd_idx].flags)) | 879 | BUG_ON(!test_bit(R5_UPTODATE, &sh->dev[pd_idx].flags)); |
886 | BUG(); | ||
887 | for (i=disks ; i-- ;) { | 880 | for (i=disks ; i-- ;) { |
888 | if (i==pd_idx) | 881 | if (i==pd_idx) |
889 | continue; | 882 | continue; |
@@ -896,7 +889,7 @@ static void compute_parity(struct stripe_head *sh, int method) | |||
896 | if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags)) | 889 | if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags)) |
897 | wake_up(&conf->wait_for_overlap); | 890 | wake_up(&conf->wait_for_overlap); |
898 | 891 | ||
899 | if (sh->dev[i].written) BUG(); | 892 | BUG_ON(sh->dev[i].written); |
900 | sh->dev[i].written = chosen; | 893 | sh->dev[i].written = chosen; |
901 | check_xor(); | 894 | check_xor(); |
902 | } | 895 | } |
@@ -912,7 +905,7 @@ static void compute_parity(struct stripe_head *sh, int method) | |||
912 | if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags)) | 905 | if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags)) |
913 | wake_up(&conf->wait_for_overlap); | 906 | wake_up(&conf->wait_for_overlap); |
914 | 907 | ||
915 | if (sh->dev[i].written) BUG(); | 908 | BUG_ON(sh->dev[i].written); |
916 | sh->dev[i].written = chosen; | 909 | sh->dev[i].written = chosen; |
917 | } | 910 | } |
918 | break; | 911 | break; |
@@ -995,8 +988,7 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in | |||
995 | if (*bip && (*bip)->bi_sector < bi->bi_sector + ((bi->bi_size)>>9)) | 988 | if (*bip && (*bip)->bi_sector < bi->bi_sector + ((bi->bi_size)>>9)) |
996 | goto overlap; | 989 | goto overlap; |
997 | 990 | ||
998 | if (*bip && bi->bi_next && (*bip) != bi->bi_next) | 991 | BUG_ON(*bip && bi->bi_next && (*bip) != bi->bi_next); |
999 | BUG(); | ||
1000 | if (*bip) | 992 | if (*bip) |
1001 | bi->bi_next = *bip; | 993 | bi->bi_next = *bip; |
1002 | *bip = bi; | 994 | *bip = bi; |
@@ -1430,8 +1422,7 @@ static void handle_stripe(struct stripe_head *sh) | |||
1430 | set_bit(STRIPE_HANDLE, &sh->state); | 1422 | set_bit(STRIPE_HANDLE, &sh->state); |
1431 | if (failed == 0) { | 1423 | if (failed == 0) { |
1432 | char *pagea; | 1424 | char *pagea; |
1433 | if (uptodate != disks) | 1425 | BUG_ON(uptodate != disks); |
1434 | BUG(); | ||
1435 | compute_parity(sh, CHECK_PARITY); | 1426 | compute_parity(sh, CHECK_PARITY); |
1436 | uptodate--; | 1427 | uptodate--; |
1437 | pagea = page_address(sh->dev[sh->pd_idx].page); | 1428 | pagea = page_address(sh->dev[sh->pd_idx].page); |
@@ -2096,8 +2087,7 @@ static void raid5d (mddev_t *mddev) | |||
2096 | 2087 | ||
2097 | list_del_init(first); | 2088 | list_del_init(first); |
2098 | atomic_inc(&sh->count); | 2089 | atomic_inc(&sh->count); |
2099 | if (atomic_read(&sh->count)!= 1) | 2090 | BUG_ON(atomic_read(&sh->count)!= 1); |
2100 | BUG(); | ||
2101 | spin_unlock_irq(&conf->device_lock); | 2091 | spin_unlock_irq(&conf->device_lock); |
2102 | 2092 | ||
2103 | handled++; | 2093 | handled++; |
diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c index ab64b37e4996..bc69355e0100 100644 --- a/drivers/md/raid6main.c +++ b/drivers/md/raid6main.c | |||
@@ -91,10 +91,8 @@ static void print_raid6_conf (raid6_conf_t *conf); | |||
91 | static void __release_stripe(raid6_conf_t *conf, struct stripe_head *sh) | 91 | static void __release_stripe(raid6_conf_t *conf, struct stripe_head *sh) |
92 | { | 92 | { |
93 | if (atomic_dec_and_test(&sh->count)) { | 93 | if (atomic_dec_and_test(&sh->count)) { |
94 | if (!list_empty(&sh->lru)) | 94 | BUG_ON(!list_empty(&sh->lru)); |
95 | BUG(); | 95 | BUG_ON(atomic_read(&conf->active_stripes)==0); |
96 | if (atomic_read(&conf->active_stripes)==0) | ||
97 | BUG(); | ||
98 | if (test_bit(STRIPE_HANDLE, &sh->state)) { | 96 | if (test_bit(STRIPE_HANDLE, &sh->state)) { |
99 | if (test_bit(STRIPE_DELAYED, &sh->state)) | 97 | if (test_bit(STRIPE_DELAYED, &sh->state)) |
100 | list_add_tail(&sh->lru, &conf->delayed_list); | 98 | list_add_tail(&sh->lru, &conf->delayed_list); |
@@ -202,10 +200,8 @@ static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx) | |||
202 | raid6_conf_t *conf = sh->raid_conf; | 200 | raid6_conf_t *conf = sh->raid_conf; |
203 | int disks = conf->raid_disks, i; | 201 | int disks = conf->raid_disks, i; |
204 | 202 | ||
205 | if (atomic_read(&sh->count) != 0) | 203 | BUG_ON(atomic_read(&sh->count) != 0); |
206 | BUG(); | 204 | BUG_ON(test_bit(STRIPE_HANDLE, &sh->state)); |
207 | if (test_bit(STRIPE_HANDLE, &sh->state)) | ||
208 | BUG(); | ||
209 | 205 | ||
210 | CHECK_DEVLOCK(); | 206 | CHECK_DEVLOCK(); |
211 | PRINTK("init_stripe called, stripe %llu\n", | 207 | PRINTK("init_stripe called, stripe %llu\n", |
@@ -284,13 +280,11 @@ static struct stripe_head *get_active_stripe(raid6_conf_t *conf, sector_t sector | |||
284 | init_stripe(sh, sector, pd_idx); | 280 | init_stripe(sh, sector, pd_idx); |
285 | } else { | 281 | } else { |
286 | if (atomic_read(&sh->count)) { | 282 | if (atomic_read(&sh->count)) { |
287 | if (!list_empty(&sh->lru)) | 283 | BUG_ON(!list_empty(&sh->lru)); |
288 | BUG(); | ||
289 | } else { | 284 | } else { |
290 | if (!test_bit(STRIPE_HANDLE, &sh->state)) | 285 | if (!test_bit(STRIPE_HANDLE, &sh->state)) |
291 | atomic_inc(&conf->active_stripes); | 286 | atomic_inc(&conf->active_stripes); |
292 | if (list_empty(&sh->lru)) | 287 | BUG_ON(list_empty(&sh->lru)); |
293 | BUG(); | ||
294 | list_del_init(&sh->lru); | 288 | list_del_init(&sh->lru); |
295 | } | 289 | } |
296 | } | 290 | } |
@@ -353,8 +347,7 @@ static int drop_one_stripe(raid6_conf_t *conf) | |||
353 | spin_unlock_irq(&conf->device_lock); | 347 | spin_unlock_irq(&conf->device_lock); |
354 | if (!sh) | 348 | if (!sh) |
355 | return 0; | 349 | return 0; |
356 | if (atomic_read(&sh->count)) | 350 | BUG_ON(atomic_read(&sh->count)); |
357 | BUG(); | ||
358 | shrink_buffers(sh, conf->raid_disks); | 351 | shrink_buffers(sh, conf->raid_disks); |
359 | kmem_cache_free(conf->slab_cache, sh); | 352 | kmem_cache_free(conf->slab_cache, sh); |
360 | atomic_dec(&conf->active_stripes); | 353 | atomic_dec(&conf->active_stripes); |
@@ -780,7 +773,7 @@ static void compute_parity(struct stripe_head *sh, int method) | |||
780 | if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags)) | 773 | if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags)) |
781 | wake_up(&conf->wait_for_overlap); | 774 | wake_up(&conf->wait_for_overlap); |
782 | 775 | ||
783 | if (sh->dev[i].written) BUG(); | 776 | BUG_ON(sh->dev[i].written); |
784 | sh->dev[i].written = chosen; | 777 | sh->dev[i].written = chosen; |
785 | } | 778 | } |
786 | break; | 779 | break; |
@@ -970,8 +963,7 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in | |||
970 | if (*bip && (*bip)->bi_sector < bi->bi_sector + ((bi->bi_size)>>9)) | 963 | if (*bip && (*bip)->bi_sector < bi->bi_sector + ((bi->bi_size)>>9)) |
971 | goto overlap; | 964 | goto overlap; |
972 | 965 | ||
973 | if (*bip && bi->bi_next && (*bip) != bi->bi_next) | 966 | BUG_ON(*bip && bi->bi_next && (*bip) != bi->bi_next); |
974 | BUG(); | ||
975 | if (*bip) | 967 | if (*bip) |
976 | bi->bi_next = *bip; | 968 | bi->bi_next = *bip; |
977 | *bip = bi; | 969 | *bip = bi; |
@@ -1906,8 +1898,7 @@ static void raid6d (mddev_t *mddev) | |||
1906 | 1898 | ||
1907 | list_del_init(first); | 1899 | list_del_init(first); |
1908 | atomic_inc(&sh->count); | 1900 | atomic_inc(&sh->count); |
1909 | if (atomic_read(&sh->count)!= 1) | 1901 | BUG_ON(atomic_read(&sh->count)!= 1); |
1910 | BUG(); | ||
1911 | spin_unlock_irq(&conf->device_lock); | 1902 | spin_unlock_irq(&conf->device_lock); |
1912 | 1903 | ||
1913 | handled++; | 1904 | handled++; |
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index 7cc162e8978b..003b077c2324 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig | |||
@@ -91,4 +91,22 @@ config MMC_AU1X | |||
91 | 91 | ||
92 | If unsure, say N. | 92 | If unsure, say N. |
93 | 93 | ||
94 | config MMC_AT91RM9200 | ||
95 | tristate "AT91RM9200 SD/MMC Card Interface support" | ||
96 | depends on ARCH_AT91RM9200 && MMC | ||
97 | help | ||
98 | This selects the AT91RM9200 MCI controller. | ||
99 | |||
100 | If unsure, say N. | ||
101 | |||
102 | config MMC_IMX | ||
103 | tristate "Motorola i.MX Multimedia Card Interface support" | ||
104 | depends on ARCH_IMX && MMC | ||
105 | help | ||
106 | This selects the Motorola i.MX Multimedia card Interface. | ||
107 | If you have a i.MX platform with a Multimedia Card slot, | ||
108 | say Y or M here. | ||
109 | |||
110 | If unsure, say N. | ||
111 | |||
94 | endmenu | 112 | endmenu |
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index c7c34aadfc92..d2957e35cc6f 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile | |||
@@ -17,10 +17,12 @@ obj-$(CONFIG_MMC_BLOCK) += mmc_block.o | |||
17 | # | 17 | # |
18 | obj-$(CONFIG_MMC_ARMMMCI) += mmci.o | 18 | obj-$(CONFIG_MMC_ARMMMCI) += mmci.o |
19 | obj-$(CONFIG_MMC_PXA) += pxamci.o | 19 | obj-$(CONFIG_MMC_PXA) += pxamci.o |
20 | obj-$(CONFIG_MMC_IMX) += imxmmc.o | ||
20 | obj-$(CONFIG_MMC_SDHCI) += sdhci.o | 21 | obj-$(CONFIG_MMC_SDHCI) += sdhci.o |
21 | obj-$(CONFIG_MMC_WBSD) += wbsd.o | 22 | obj-$(CONFIG_MMC_WBSD) += wbsd.o |
22 | obj-$(CONFIG_MMC_AU1X) += au1xmmc.o | 23 | obj-$(CONFIG_MMC_AU1X) += au1xmmc.o |
23 | obj-$(CONFIG_MMC_OMAP) += omap.o | 24 | obj-$(CONFIG_MMC_OMAP) += omap.o |
25 | obj-$(CONFIG_MMC_AT91RM9200) += at91_mci.o | ||
24 | 26 | ||
25 | mmc_core-y := mmc.o mmc_queue.o mmc_sysfs.o | 27 | mmc_core-y := mmc.o mmc_queue.o mmc_sysfs.o |
26 | 28 | ||
diff --git a/drivers/mmc/at91_mci.c b/drivers/mmc/at91_mci.c new file mode 100644 index 000000000000..6061c2d101a0 --- /dev/null +++ b/drivers/mmc/at91_mci.c | |||
@@ -0,0 +1,988 @@ | |||
1 | /* | ||
2 | * linux/drivers/mmc/at91_mci.c - ATMEL AT91RM9200 MCI Driver | ||
3 | * | ||
4 | * Copyright (C) 2005 Cougar Creek Computing Devices Ltd, All Rights Reserved | ||
5 | * | ||
6 | * Copyright (C) 2006 Malcolm Noyes | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | /* | ||
14 | This is the AT91RM9200 MCI driver that has been tested with both MMC cards | ||
15 | and SD-cards. Boards that support write protect are now supported. | ||
16 | The CCAT91SBC001 board does not support SD cards. | ||
17 | |||
18 | The three entry points are at91_mci_request, at91_mci_set_ios | ||
19 | and at91_mci_get_ro. | ||
20 | |||
21 | SET IOS | ||
22 | This configures the device to put it into the correct mode and clock speed | ||
23 | required. | ||
24 | |||
25 | MCI REQUEST | ||
26 | MCI request processes the commands sent in the mmc_request structure. This | ||
27 | can consist of a processing command and a stop command in the case of | ||
28 | multiple block transfers. | ||
29 | |||
30 | There are three main types of request, commands, reads and writes. | ||
31 | |||
32 | Commands are straight forward. The command is submitted to the controller and | ||
33 | the request function returns. When the controller generates an interrupt to indicate | ||
34 | the command is finished, the response to the command are read and the mmc_request_done | ||
35 | function called to end the request. | ||
36 | |||
37 | Reads and writes work in a similar manner to normal commands but involve the PDC (DMA) | ||
38 | controller to manage the transfers. | ||
39 | |||
40 | A read is done from the controller directly to the scatterlist passed in from the request. | ||
41 | Due to a bug in the controller, when a read is completed, all the words are byte | ||
42 | swapped in the scatterlist buffers. | ||
43 | |||
44 | The sequence of read interrupts is: ENDRX, RXBUFF, CMDRDY | ||
45 | |||
46 | A write is slightly different in that the bytes to write are read from the scatterlist | ||
47 | into a dma memory buffer (this is in case the source buffer should be read only). The | ||
48 | entire write buffer is then done from this single dma memory buffer. | ||
49 | |||
50 | The sequence of write interrupts is: ENDTX, TXBUFE, NOTBUSY, CMDRDY | ||
51 | |||
52 | GET RO | ||
53 | Gets the status of the write protect pin, if available. | ||
54 | */ | ||
55 | |||
56 | #include <linux/config.h> | ||
57 | #include <linux/module.h> | ||
58 | #include <linux/moduleparam.h> | ||
59 | #include <linux/init.h> | ||
60 | #include <linux/ioport.h> | ||
61 | #include <linux/platform_device.h> | ||
62 | #include <linux/interrupt.h> | ||
63 | #include <linux/blkdev.h> | ||
64 | #include <linux/delay.h> | ||
65 | #include <linux/err.h> | ||
66 | #include <linux/dma-mapping.h> | ||
67 | #include <linux/clk.h> | ||
68 | |||
69 | #include <linux/mmc/host.h> | ||
70 | #include <linux/mmc/protocol.h> | ||
71 | |||
72 | #include <asm/io.h> | ||
73 | #include <asm/irq.h> | ||
74 | #include <asm/mach/mmc.h> | ||
75 | #include <asm/arch/board.h> | ||
76 | #include <asm/arch/gpio.h> | ||
77 | #include <asm/arch/at91rm9200_mci.h> | ||
78 | #include <asm/arch/at91rm9200_pdc.h> | ||
79 | |||
80 | #define DRIVER_NAME "at91_mci" | ||
81 | |||
82 | #undef SUPPORT_4WIRE | ||
83 | |||
84 | #ifdef CONFIG_MMC_DEBUG | ||
85 | #define DBG(fmt...) \ | ||
86 | printk(fmt) | ||
87 | #else | ||
88 | #define DBG(fmt...) do { } while (0) | ||
89 | #endif | ||
90 | |||
91 | static struct clk *mci_clk; | ||
92 | |||
93 | #define FL_SENT_COMMAND (1 << 0) | ||
94 | #define FL_SENT_STOP (1 << 1) | ||
95 | |||
96 | |||
97 | |||
98 | /* | ||
99 | * Read from a MCI register. | ||
100 | */ | ||
101 | static inline unsigned long at91_mci_read(unsigned int reg) | ||
102 | { | ||
103 | void __iomem *mci_base = (void __iomem *)AT91_VA_BASE_MCI; | ||
104 | |||
105 | return __raw_readl(mci_base + reg); | ||
106 | } | ||
107 | |||
108 | /* | ||
109 | * Write to a MCI register. | ||
110 | */ | ||
111 | static inline void at91_mci_write(unsigned int reg, unsigned long value) | ||
112 | { | ||
113 | void __iomem *mci_base = (void __iomem *)AT91_VA_BASE_MCI; | ||
114 | |||
115 | __raw_writel(value, mci_base + reg); | ||
116 | } | ||
117 | |||
118 | /* | ||
119 | * Low level type for this driver | ||
120 | */ | ||
121 | struct at91mci_host | ||
122 | { | ||
123 | struct mmc_host *mmc; | ||
124 | struct mmc_command *cmd; | ||
125 | struct mmc_request *request; | ||
126 | |||
127 | struct at91_mmc_data *board; | ||
128 | int present; | ||
129 | |||
130 | /* | ||
131 | * Flag indicating when the command has been sent. This is used to | ||
132 | * work out whether or not to send the stop | ||
133 | */ | ||
134 | unsigned int flags; | ||
135 | /* flag for current bus settings */ | ||
136 | u32 bus_mode; | ||
137 | |||
138 | /* DMA buffer used for transmitting */ | ||
139 | unsigned int* buffer; | ||
140 | dma_addr_t physical_address; | ||
141 | unsigned int total_length; | ||
142 | |||
143 | /* Latest in the scatterlist that has been enabled for transfer, but not freed */ | ||
144 | int in_use_index; | ||
145 | |||
146 | /* Latest in the scatterlist that has been enabled for transfer */ | ||
147 | int transfer_index; | ||
148 | }; | ||
149 | |||
150 | /* | ||
151 | * Copy from sg to a dma block - used for transfers | ||
152 | */ | ||
153 | static inline void at91mci_sg_to_dma(struct at91mci_host *host, struct mmc_data *data) | ||
154 | { | ||
155 | unsigned int len, i, size; | ||
156 | unsigned *dmabuf = host->buffer; | ||
157 | |||
158 | size = host->total_length; | ||
159 | len = data->sg_len; | ||
160 | |||
161 | /* | ||
162 | * Just loop through all entries. Size might not | ||
163 | * be the entire list though so make sure that | ||
164 | * we do not transfer too much. | ||
165 | */ | ||
166 | for (i = 0; i < len; i++) { | ||
167 | struct scatterlist *sg; | ||
168 | int amount; | ||
169 | int index; | ||
170 | unsigned int *sgbuffer; | ||
171 | |||
172 | sg = &data->sg[i]; | ||
173 | |||
174 | sgbuffer = kmap_atomic(sg->page, KM_BIO_SRC_IRQ) + sg->offset; | ||
175 | amount = min(size, sg->length); | ||
176 | size -= amount; | ||
177 | amount /= 4; | ||
178 | |||
179 | for (index = 0; index < amount; index++) | ||
180 | *dmabuf++ = swab32(sgbuffer[index]); | ||
181 | |||
182 | kunmap_atomic(sgbuffer, KM_BIO_SRC_IRQ); | ||
183 | |||
184 | if (size == 0) | ||
185 | break; | ||
186 | } | ||
187 | |||
188 | /* | ||
189 | * Check that we didn't get a request to transfer | ||
190 | * more data than can fit into the SG list. | ||
191 | */ | ||
192 | BUG_ON(size != 0); | ||
193 | } | ||
194 | |||
195 | /* | ||
196 | * Prepare a dma read | ||
197 | */ | ||
198 | static void at91mci_pre_dma_read(struct at91mci_host *host) | ||
199 | { | ||
200 | int i; | ||
201 | struct scatterlist *sg; | ||
202 | struct mmc_command *cmd; | ||
203 | struct mmc_data *data; | ||
204 | |||
205 | DBG("pre dma read\n"); | ||
206 | |||
207 | cmd = host->cmd; | ||
208 | if (!cmd) { | ||
209 | DBG("no command\n"); | ||
210 | return; | ||
211 | } | ||
212 | |||
213 | data = cmd->data; | ||
214 | if (!data) { | ||
215 | DBG("no data\n"); | ||
216 | return; | ||
217 | } | ||
218 | |||
219 | for (i = 0; i < 2; i++) { | ||
220 | /* nothing left to transfer */ | ||
221 | if (host->transfer_index >= data->sg_len) { | ||
222 | DBG("Nothing left to transfer (index = %d)\n", host->transfer_index); | ||
223 | break; | ||
224 | } | ||
225 | |||
226 | /* Check to see if this needs filling */ | ||
227 | if (i == 0) { | ||
228 | if (at91_mci_read(AT91_PDC_RCR) != 0) { | ||
229 | DBG("Transfer active in current\n"); | ||
230 | continue; | ||
231 | } | ||
232 | } | ||
233 | else { | ||
234 | if (at91_mci_read(AT91_PDC_RNCR) != 0) { | ||
235 | DBG("Transfer active in next\n"); | ||
236 | continue; | ||
237 | } | ||
238 | } | ||
239 | |||
240 | /* Setup the next transfer */ | ||
241 | DBG("Using transfer index %d\n", host->transfer_index); | ||
242 | |||
243 | sg = &data->sg[host->transfer_index++]; | ||
244 | DBG("sg = %p\n", sg); | ||
245 | |||
246 | sg->dma_address = dma_map_page(NULL, sg->page, sg->offset, sg->length, DMA_FROM_DEVICE); | ||
247 | |||
248 | DBG("dma address = %08X, length = %d\n", sg->dma_address, sg->length); | ||
249 | |||
250 | if (i == 0) { | ||
251 | at91_mci_write(AT91_PDC_RPR, sg->dma_address); | ||
252 | at91_mci_write(AT91_PDC_RCR, sg->length / 4); | ||
253 | } | ||
254 | else { | ||
255 | at91_mci_write(AT91_PDC_RNPR, sg->dma_address); | ||
256 | at91_mci_write(AT91_PDC_RNCR, sg->length / 4); | ||
257 | } | ||
258 | } | ||
259 | |||
260 | DBG("pre dma read done\n"); | ||
261 | } | ||
262 | |||
263 | /* | ||
264 | * Handle after a dma read | ||
265 | */ | ||
266 | static void at91mci_post_dma_read(struct at91mci_host *host) | ||
267 | { | ||
268 | struct mmc_command *cmd; | ||
269 | struct mmc_data *data; | ||
270 | |||
271 | DBG("post dma read\n"); | ||
272 | |||
273 | cmd = host->cmd; | ||
274 | if (!cmd) { | ||
275 | DBG("no command\n"); | ||
276 | return; | ||
277 | } | ||
278 | |||
279 | data = cmd->data; | ||
280 | if (!data) { | ||
281 | DBG("no data\n"); | ||
282 | return; | ||
283 | } | ||
284 | |||
285 | while (host->in_use_index < host->transfer_index) { | ||
286 | unsigned int *buffer; | ||
287 | int index; | ||
288 | int len; | ||
289 | |||
290 | struct scatterlist *sg; | ||
291 | |||
292 | DBG("finishing index %d\n", host->in_use_index); | ||
293 | |||
294 | sg = &data->sg[host->in_use_index++]; | ||
295 | |||
296 | DBG("Unmapping page %08X\n", sg->dma_address); | ||
297 | |||
298 | dma_unmap_page(NULL, sg->dma_address, sg->length, DMA_FROM_DEVICE); | ||
299 | |||
300 | /* Swap the contents of the buffer */ | ||
301 | buffer = kmap_atomic(sg->page, KM_BIO_SRC_IRQ) + sg->offset; | ||
302 | DBG("buffer = %p, length = %d\n", buffer, sg->length); | ||
303 | |||
304 | data->bytes_xfered += sg->length; | ||
305 | |||
306 | len = sg->length / 4; | ||
307 | |||
308 | for (index = 0; index < len; index++) { | ||
309 | buffer[index] = swab32(buffer[index]); | ||
310 | } | ||
311 | kunmap_atomic(buffer, KM_BIO_SRC_IRQ); | ||
312 | flush_dcache_page(sg->page); | ||
313 | } | ||
314 | |||
315 | /* Is there another transfer to trigger? */ | ||
316 | if (host->transfer_index < data->sg_len) | ||
317 | at91mci_pre_dma_read(host); | ||
318 | else { | ||
319 | at91_mci_write(AT91_MCI_IER, AT91_MCI_RXBUFF); | ||
320 | at91_mci_write(AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS); | ||
321 | } | ||
322 | |||
323 | DBG("post dma read done\n"); | ||
324 | } | ||
325 | |||
326 | /* | ||
327 | * Handle transmitted data | ||
328 | */ | ||
329 | static void at91_mci_handle_transmitted(struct at91mci_host *host) | ||
330 | { | ||
331 | struct mmc_command *cmd; | ||
332 | struct mmc_data *data; | ||
333 | |||
334 | DBG("Handling the transmit\n"); | ||
335 | |||
336 | /* Disable the transfer */ | ||
337 | at91_mci_write(AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS); | ||
338 | |||
339 | /* Now wait for cmd ready */ | ||
340 | at91_mci_write(AT91_MCI_IDR, AT91_MCI_TXBUFE); | ||
341 | at91_mci_write(AT91_MCI_IER, AT91_MCI_NOTBUSY); | ||
342 | |||
343 | cmd = host->cmd; | ||
344 | if (!cmd) return; | ||
345 | |||
346 | data = cmd->data; | ||
347 | if (!data) return; | ||
348 | |||
349 | data->bytes_xfered = host->total_length; | ||
350 | } | ||
351 | |||
352 | /* | ||
353 | * Enable the controller | ||
354 | */ | ||
355 | static void at91_mci_enable(void) | ||
356 | { | ||
357 | at91_mci_write(AT91_MCI_CR, AT91_MCI_MCIEN); | ||
358 | at91_mci_write(AT91_MCI_IDR, 0xFFFFFFFF); | ||
359 | at91_mci_write(AT91_MCI_DTOR, AT91_MCI_DTOMUL_1M | AT91_MCI_DTOCYC); | ||
360 | at91_mci_write(AT91_MCI_MR, 0x834A); | ||
361 | at91_mci_write(AT91_MCI_SDCR, 0x0); | ||
362 | } | ||
363 | |||
364 | /* | ||
365 | * Disable the controller | ||
366 | */ | ||
367 | static void at91_mci_disable(void) | ||
368 | { | ||
369 | at91_mci_write(AT91_MCI_CR, AT91_MCI_MCIDIS | AT91_MCI_SWRST); | ||
370 | } | ||
371 | |||
372 | /* | ||
373 | * Send a command | ||
374 | * return the interrupts to enable | ||
375 | */ | ||
376 | static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_command *cmd) | ||
377 | { | ||
378 | unsigned int cmdr, mr; | ||
379 | unsigned int block_length; | ||
380 | struct mmc_data *data = cmd->data; | ||
381 | |||
382 | unsigned int blocks; | ||
383 | unsigned int ier = 0; | ||
384 | |||
385 | host->cmd = cmd; | ||
386 | |||
387 | /* Not sure if this is needed */ | ||
388 | #if 0 | ||
389 | if ((at91_mci_read(AT91_MCI_SR) & AT91_MCI_RTOE) && (cmd->opcode == 1)) { | ||
390 | DBG("Clearing timeout\n"); | ||
391 | at91_mci_write(AT91_MCI_ARGR, 0); | ||
392 | at91_mci_write(AT91_MCI_CMDR, AT91_MCI_OPDCMD); | ||
393 | while (!(at91_mci_read(AT91_MCI_SR) & AT91_MCI_CMDRDY)) { | ||
394 | /* spin */ | ||
395 | DBG("Clearing: SR = %08X\n", at91_mci_read(AT91_MCI_SR)); | ||
396 | } | ||
397 | } | ||
398 | #endif | ||
399 | cmdr = cmd->opcode; | ||
400 | |||
401 | if (mmc_resp_type(cmd) == MMC_RSP_NONE) | ||
402 | cmdr |= AT91_MCI_RSPTYP_NONE; | ||
403 | else { | ||
404 | /* if a response is expected then allow maximum response latancy */ | ||
405 | cmdr |= AT91_MCI_MAXLAT; | ||
406 | /* set 136 bit response for R2, 48 bit response otherwise */ | ||
407 | if (mmc_resp_type(cmd) == MMC_RSP_R2) | ||
408 | cmdr |= AT91_MCI_RSPTYP_136; | ||
409 | else | ||
410 | cmdr |= AT91_MCI_RSPTYP_48; | ||
411 | } | ||
412 | |||
413 | if (data) { | ||
414 | block_length = 1 << data->blksz_bits; | ||
415 | blocks = data->blocks; | ||
416 | |||
417 | /* always set data start - also set direction flag for read */ | ||
418 | if (data->flags & MMC_DATA_READ) | ||
419 | cmdr |= (AT91_MCI_TRDIR | AT91_MCI_TRCMD_START); | ||
420 | else if (data->flags & MMC_DATA_WRITE) | ||
421 | cmdr |= AT91_MCI_TRCMD_START; | ||
422 | |||
423 | if (data->flags & MMC_DATA_STREAM) | ||
424 | cmdr |= AT91_MCI_TRTYP_STREAM; | ||
425 | if (data->flags & MMC_DATA_MULTI) | ||
426 | cmdr |= AT91_MCI_TRTYP_MULTIPLE; | ||
427 | } | ||
428 | else { | ||
429 | block_length = 0; | ||
430 | blocks = 0; | ||
431 | } | ||
432 | |||
433 | if (cmd->opcode == MMC_STOP_TRANSMISSION) | ||
434 | cmdr |= AT91_MCI_TRCMD_STOP; | ||
435 | |||
436 | if (host->bus_mode == MMC_BUSMODE_OPENDRAIN) | ||
437 | cmdr |= AT91_MCI_OPDCMD; | ||
438 | |||
439 | /* | ||
440 | * Set the arguments and send the command | ||
441 | */ | ||
442 | DBG("Sending command %d as %08X, arg = %08X, blocks = %d, length = %d (MR = %08lX)\n", | ||
443 | cmd->opcode, cmdr, cmd->arg, blocks, block_length, at91_mci_read(AT91_MCI_MR)); | ||
444 | |||
445 | if (!data) { | ||
446 | at91_mci_write(AT91_PDC_PTCR, AT91_PDC_TXTDIS | AT91_PDC_RXTDIS); | ||
447 | at91_mci_write(AT91_PDC_RPR, 0); | ||
448 | at91_mci_write(AT91_PDC_RCR, 0); | ||
449 | at91_mci_write(AT91_PDC_RNPR, 0); | ||
450 | at91_mci_write(AT91_PDC_RNCR, 0); | ||
451 | at91_mci_write(AT91_PDC_TPR, 0); | ||
452 | at91_mci_write(AT91_PDC_TCR, 0); | ||
453 | at91_mci_write(AT91_PDC_TNPR, 0); | ||
454 | at91_mci_write(AT91_PDC_TNCR, 0); | ||
455 | |||
456 | at91_mci_write(AT91_MCI_ARGR, cmd->arg); | ||
457 | at91_mci_write(AT91_MCI_CMDR, cmdr); | ||
458 | return AT91_MCI_CMDRDY; | ||
459 | } | ||
460 | |||
461 | mr = at91_mci_read(AT91_MCI_MR) & 0x7fff; /* zero block length and PDC mode */ | ||
462 | at91_mci_write(AT91_MCI_MR, mr | (block_length << 16) | AT91_MCI_PDCMODE); | ||
463 | |||
464 | /* | ||
465 | * Disable the PDC controller | ||
466 | */ | ||
467 | at91_mci_write(AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS); | ||
468 | |||
469 | if (cmdr & AT91_MCI_TRCMD_START) { | ||
470 | data->bytes_xfered = 0; | ||
471 | host->transfer_index = 0; | ||
472 | host->in_use_index = 0; | ||
473 | if (cmdr & AT91_MCI_TRDIR) { | ||
474 | /* | ||
475 | * Handle a read | ||
476 | */ | ||
477 | host->buffer = NULL; | ||
478 | host->total_length = 0; | ||
479 | |||
480 | at91mci_pre_dma_read(host); | ||
481 | ier = AT91_MCI_ENDRX /* | AT91_MCI_RXBUFF */; | ||
482 | } | ||
483 | else { | ||
484 | /* | ||
485 | * Handle a write | ||
486 | */ | ||
487 | host->total_length = block_length * blocks; | ||
488 | host->buffer = dma_alloc_coherent(NULL, | ||
489 | host->total_length, | ||
490 | &host->physical_address, GFP_KERNEL); | ||
491 | |||
492 | at91mci_sg_to_dma(host, data); | ||
493 | |||
494 | DBG("Transmitting %d bytes\n", host->total_length); | ||
495 | |||
496 | at91_mci_write(AT91_PDC_TPR, host->physical_address); | ||
497 | at91_mci_write(AT91_PDC_TCR, host->total_length / 4); | ||
498 | ier = AT91_MCI_TXBUFE; | ||
499 | } | ||
500 | } | ||
501 | |||
502 | /* | ||
503 | * Send the command and then enable the PDC - not the other way round as | ||
504 | * the data sheet says | ||
505 | */ | ||
506 | |||
507 | at91_mci_write(AT91_MCI_ARGR, cmd->arg); | ||
508 | at91_mci_write(AT91_MCI_CMDR, cmdr); | ||
509 | |||
510 | if (cmdr & AT91_MCI_TRCMD_START) { | ||
511 | if (cmdr & AT91_MCI_TRDIR) | ||
512 | at91_mci_write(AT91_PDC_PTCR, AT91_PDC_RXTEN); | ||
513 | else | ||
514 | at91_mci_write(AT91_PDC_PTCR, AT91_PDC_TXTEN); | ||
515 | } | ||
516 | return ier; | ||
517 | } | ||
518 | |||
519 | /* | ||
520 | * Wait for a command to complete | ||
521 | */ | ||
522 | static void at91mci_process_command(struct at91mci_host *host, struct mmc_command *cmd) | ||
523 | { | ||
524 | unsigned int ier; | ||
525 | |||
526 | ier = at91_mci_send_command(host, cmd); | ||
527 | |||
528 | DBG("setting ier to %08X\n", ier); | ||
529 | |||
530 | /* Stop on errors or the required value */ | ||
531 | at91_mci_write(AT91_MCI_IER, 0xffff0000 | ier); | ||
532 | } | ||
533 | |||
534 | /* | ||
535 | * Process the next step in the request | ||
536 | */ | ||
537 | static void at91mci_process_next(struct at91mci_host *host) | ||
538 | { | ||
539 | if (!(host->flags & FL_SENT_COMMAND)) { | ||
540 | host->flags |= FL_SENT_COMMAND; | ||
541 | at91mci_process_command(host, host->request->cmd); | ||
542 | } | ||
543 | else if ((!(host->flags & FL_SENT_STOP)) && host->request->stop) { | ||
544 | host->flags |= FL_SENT_STOP; | ||
545 | at91mci_process_command(host, host->request->stop); | ||
546 | } | ||
547 | else | ||
548 | mmc_request_done(host->mmc, host->request); | ||
549 | } | ||
550 | |||
551 | /* | ||
552 | * Handle a command that has been completed | ||
553 | */ | ||
554 | static void at91mci_completed_command(struct at91mci_host *host) | ||
555 | { | ||
556 | struct mmc_command *cmd = host->cmd; | ||
557 | unsigned int status; | ||
558 | |||
559 | at91_mci_write(AT91_MCI_IDR, 0xffffffff); | ||
560 | |||
561 | cmd->resp[0] = at91_mci_read(AT91_MCI_RSPR(0)); | ||
562 | cmd->resp[1] = at91_mci_read(AT91_MCI_RSPR(1)); | ||
563 | cmd->resp[2] = at91_mci_read(AT91_MCI_RSPR(2)); | ||
564 | cmd->resp[3] = at91_mci_read(AT91_MCI_RSPR(3)); | ||
565 | |||
566 | if (host->buffer) { | ||
567 | dma_free_coherent(NULL, host->total_length, host->buffer, host->physical_address); | ||
568 | host->buffer = NULL; | ||
569 | } | ||
570 | |||
571 | status = at91_mci_read(AT91_MCI_SR); | ||
572 | |||
573 | DBG("Status = %08X [%08X %08X %08X %08X]\n", | ||
574 | status, cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]); | ||
575 | |||
576 | if (status & (AT91_MCI_RINDE | AT91_MCI_RDIRE | AT91_MCI_RCRCE | | ||
577 | AT91_MCI_RENDE | AT91_MCI_RTOE | AT91_MCI_DCRCE | | ||
578 | AT91_MCI_DTOE | AT91_MCI_OVRE | AT91_MCI_UNRE)) { | ||
579 | if ((status & AT91_MCI_RCRCE) && | ||
580 | ((cmd->opcode == MMC_SEND_OP_COND) || (cmd->opcode == SD_APP_OP_COND))) { | ||
581 | cmd->error = MMC_ERR_NONE; | ||
582 | } | ||
583 | else { | ||
584 | if (status & (AT91_MCI_RTOE | AT91_MCI_DTOE)) | ||
585 | cmd->error = MMC_ERR_TIMEOUT; | ||
586 | else if (status & (AT91_MCI_RCRCE | AT91_MCI_DCRCE)) | ||
587 | cmd->error = MMC_ERR_BADCRC; | ||
588 | else if (status & (AT91_MCI_OVRE | AT91_MCI_UNRE)) | ||
589 | cmd->error = MMC_ERR_FIFO; | ||
590 | else | ||
591 | cmd->error = MMC_ERR_FAILED; | ||
592 | |||
593 | DBG("Error detected and set to %d (cmd = %d, retries = %d)\n", | ||
594 | cmd->error, cmd->opcode, cmd->retries); | ||
595 | } | ||
596 | } | ||
597 | else | ||
598 | cmd->error = MMC_ERR_NONE; | ||
599 | |||
600 | at91mci_process_next(host); | ||
601 | } | ||
602 | |||
603 | /* | ||
604 | * Handle an MMC request | ||
605 | */ | ||
606 | static void at91_mci_request(struct mmc_host *mmc, struct mmc_request *mrq) | ||
607 | { | ||
608 | struct at91mci_host *host = mmc_priv(mmc); | ||
609 | host->request = mrq; | ||
610 | host->flags = 0; | ||
611 | |||
612 | at91mci_process_next(host); | ||
613 | } | ||
614 | |||
615 | /* | ||
616 | * Set the IOS | ||
617 | */ | ||
618 | static void at91_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | ||
619 | { | ||
620 | int clkdiv; | ||
621 | struct at91mci_host *host = mmc_priv(mmc); | ||
622 | unsigned long at91_master_clock = clk_get_rate(mci_clk); | ||
623 | |||
624 | DBG("Clock %uHz, busmode %u, powermode %u, Vdd %u\n", | ||
625 | ios->clock, ios->bus_mode, ios->power_mode, ios->vdd); | ||
626 | |||
627 | if (host) | ||
628 | host->bus_mode = ios->bus_mode; | ||
629 | else | ||
630 | printk("MMC: No host for bus_mode\n"); | ||
631 | |||
632 | if (ios->clock == 0) { | ||
633 | /* Disable the MCI controller */ | ||
634 | at91_mci_write(AT91_MCI_CR, AT91_MCI_MCIDIS); | ||
635 | clkdiv = 0; | ||
636 | } | ||
637 | else { | ||
638 | /* Enable the MCI controller */ | ||
639 | at91_mci_write(AT91_MCI_CR, AT91_MCI_MCIEN); | ||
640 | |||
641 | if ((at91_master_clock % (ios->clock * 2)) == 0) | ||
642 | clkdiv = ((at91_master_clock / ios->clock) / 2) - 1; | ||
643 | else | ||
644 | clkdiv = (at91_master_clock / ios->clock) / 2; | ||
645 | |||
646 | DBG("clkdiv = %d. mcck = %ld\n", clkdiv, | ||
647 | at91_master_clock / (2 * (clkdiv + 1))); | ||
648 | } | ||
649 | if (ios->bus_width == MMC_BUS_WIDTH_4 && host->board->wire4) { | ||
650 | DBG("MMC: Setting controller bus width to 4\n"); | ||
651 | at91_mci_write(AT91_MCI_SDCR, at91_mci_read(AT91_MCI_SDCR) | AT91_MCI_SDCBUS); | ||
652 | } | ||
653 | else { | ||
654 | DBG("MMC: Setting controller bus width to 1\n"); | ||
655 | at91_mci_write(AT91_MCI_SDCR, at91_mci_read(AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS); | ||
656 | } | ||
657 | |||
658 | /* Set the clock divider */ | ||
659 | at91_mci_write(AT91_MCI_MR, (at91_mci_read(AT91_MCI_MR) & ~AT91_MCI_CLKDIV) | clkdiv); | ||
660 | |||
661 | /* maybe switch power to the card */ | ||
662 | if (host && host->board->vcc_pin) { | ||
663 | switch (ios->power_mode) { | ||
664 | case MMC_POWER_OFF: | ||
665 | at91_set_gpio_output(host->board->vcc_pin, 0); | ||
666 | break; | ||
667 | case MMC_POWER_UP: | ||
668 | case MMC_POWER_ON: | ||
669 | at91_set_gpio_output(host->board->vcc_pin, 1); | ||
670 | break; | ||
671 | } | ||
672 | } | ||
673 | } | ||
674 | |||
675 | /* | ||
676 | * Handle an interrupt | ||
677 | */ | ||
678 | static irqreturn_t at91_mci_irq(int irq, void *devid, struct pt_regs *regs) | ||
679 | { | ||
680 | struct at91mci_host *host = devid; | ||
681 | int completed = 0; | ||
682 | |||
683 | unsigned int int_status; | ||
684 | |||
685 | if (host == NULL) | ||
686 | return IRQ_HANDLED; | ||
687 | |||
688 | int_status = at91_mci_read(AT91_MCI_SR); | ||
689 | DBG("MCI irq: status = %08X, %08lX, %08lX\n", int_status, at91_mci_read(AT91_MCI_IMR), | ||
690 | int_status & at91_mci_read(AT91_MCI_IMR)); | ||
691 | |||
692 | if ((int_status & at91_mci_read(AT91_MCI_IMR)) & 0xffff0000) | ||
693 | completed = 1; | ||
694 | |||
695 | int_status &= at91_mci_read(AT91_MCI_IMR); | ||
696 | |||
697 | if (int_status & AT91_MCI_UNRE) | ||
698 | DBG("MMC: Underrun error\n"); | ||
699 | if (int_status & AT91_MCI_OVRE) | ||
700 | DBG("MMC: Overrun error\n"); | ||
701 | if (int_status & AT91_MCI_DTOE) | ||
702 | DBG("MMC: Data timeout\n"); | ||
703 | if (int_status & AT91_MCI_DCRCE) | ||
704 | DBG("MMC: CRC error in data\n"); | ||
705 | if (int_status & AT91_MCI_RTOE) | ||
706 | DBG("MMC: Response timeout\n"); | ||
707 | if (int_status & AT91_MCI_RENDE) | ||
708 | DBG("MMC: Response end bit error\n"); | ||
709 | if (int_status & AT91_MCI_RCRCE) | ||
710 | DBG("MMC: Response CRC error\n"); | ||
711 | if (int_status & AT91_MCI_RDIRE) | ||
712 | DBG("MMC: Response direction error\n"); | ||
713 | if (int_status & AT91_MCI_RINDE) | ||
714 | DBG("MMC: Response index error\n"); | ||
715 | |||
716 | /* Only continue processing if no errors */ | ||
717 | if (!completed) { | ||
718 | if (int_status & AT91_MCI_TXBUFE) { | ||
719 | DBG("TX buffer empty\n"); | ||
720 | at91_mci_handle_transmitted(host); | ||
721 | } | ||
722 | |||
723 | if (int_status & AT91_MCI_RXBUFF) { | ||
724 | DBG("RX buffer full\n"); | ||
725 | at91_mci_write(AT91_MCI_IER, AT91_MCI_CMDRDY); | ||
726 | } | ||
727 | |||
728 | if (int_status & AT91_MCI_ENDTX) { | ||
729 | DBG("Transmit has ended\n"); | ||
730 | } | ||
731 | |||
732 | if (int_status & AT91_MCI_ENDRX) { | ||
733 | DBG("Receive has ended\n"); | ||
734 | at91mci_post_dma_read(host); | ||
735 | } | ||
736 | |||
737 | if (int_status & AT91_MCI_NOTBUSY) { | ||
738 | DBG("Card is ready\n"); | ||
739 | at91_mci_write(AT91_MCI_IER, AT91_MCI_CMDRDY); | ||
740 | } | ||
741 | |||
742 | if (int_status & AT91_MCI_DTIP) { | ||
743 | DBG("Data transfer in progress\n"); | ||
744 | } | ||
745 | |||
746 | if (int_status & AT91_MCI_BLKE) { | ||
747 | DBG("Block transfer has ended\n"); | ||
748 | } | ||
749 | |||
750 | if (int_status & AT91_MCI_TXRDY) { | ||
751 | DBG("Ready to transmit\n"); | ||
752 | } | ||
753 | |||
754 | if (int_status & AT91_MCI_RXRDY) { | ||
755 | DBG("Ready to receive\n"); | ||
756 | } | ||
757 | |||
758 | if (int_status & AT91_MCI_CMDRDY) { | ||
759 | DBG("Command ready\n"); | ||
760 | completed = 1; | ||
761 | } | ||
762 | } | ||
763 | at91_mci_write(AT91_MCI_IDR, int_status); | ||
764 | |||
765 | if (completed) { | ||
766 | DBG("Completed command\n"); | ||
767 | at91_mci_write(AT91_MCI_IDR, 0xffffffff); | ||
768 | at91mci_completed_command(host); | ||
769 | } | ||
770 | |||
771 | return IRQ_HANDLED; | ||
772 | } | ||
773 | |||
774 | static irqreturn_t at91_mmc_det_irq(int irq, void *_host, struct pt_regs *regs) | ||
775 | { | ||
776 | struct at91mci_host *host = _host; | ||
777 | int present = !at91_get_gpio_value(irq); | ||
778 | |||
779 | /* | ||
780 | * we expect this irq on both insert and remove, | ||
781 | * and use a short delay to debounce. | ||
782 | */ | ||
783 | if (present != host->present) { | ||
784 | host->present = present; | ||
785 | DBG("%s: card %s\n", mmc_hostname(host->mmc), | ||
786 | present ? "insert" : "remove"); | ||
787 | if (!present) { | ||
788 | DBG("****** Resetting SD-card bus width ******\n"); | ||
789 | at91_mci_write(AT91_MCI_SDCR, 0); | ||
790 | } | ||
791 | mmc_detect_change(host->mmc, msecs_to_jiffies(100)); | ||
792 | } | ||
793 | return IRQ_HANDLED; | ||
794 | } | ||
795 | |||
796 | int at91_mci_get_ro(struct mmc_host *mmc) | ||
797 | { | ||
798 | int read_only = 0; | ||
799 | struct at91mci_host *host = mmc_priv(mmc); | ||
800 | |||
801 | if (host->board->wp_pin) { | ||
802 | read_only = at91_get_gpio_value(host->board->wp_pin); | ||
803 | printk(KERN_WARNING "%s: card is %s\n", mmc_hostname(mmc), | ||
804 | (read_only ? "read-only" : "read-write") ); | ||
805 | } | ||
806 | else { | ||
807 | printk(KERN_WARNING "%s: host does not support reading read-only " | ||
808 | "switch. Assuming write-enable.\n", mmc_hostname(mmc)); | ||
809 | } | ||
810 | return read_only; | ||
811 | } | ||
812 | |||
813 | static struct mmc_host_ops at91_mci_ops = { | ||
814 | .request = at91_mci_request, | ||
815 | .set_ios = at91_mci_set_ios, | ||
816 | .get_ro = at91_mci_get_ro, | ||
817 | }; | ||
818 | |||
819 | /* | ||
820 | * Probe for the device | ||
821 | */ | ||
822 | static int at91_mci_probe(struct platform_device *pdev) | ||
823 | { | ||
824 | struct mmc_host *mmc; | ||
825 | struct at91mci_host *host; | ||
826 | int ret; | ||
827 | |||
828 | DBG("Probe MCI devices\n"); | ||
829 | at91_mci_disable(); | ||
830 | at91_mci_enable(); | ||
831 | |||
832 | mmc = mmc_alloc_host(sizeof(struct at91mci_host), &pdev->dev); | ||
833 | if (!mmc) { | ||
834 | DBG("Failed to allocate mmc host\n"); | ||
835 | return -ENOMEM; | ||
836 | } | ||
837 | |||
838 | mmc->ops = &at91_mci_ops; | ||
839 | mmc->f_min = 375000; | ||
840 | mmc->f_max = 25000000; | ||
841 | mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; | ||
842 | |||
843 | host = mmc_priv(mmc); | ||
844 | host->mmc = mmc; | ||
845 | host->buffer = NULL; | ||
846 | host->bus_mode = 0; | ||
847 | host->board = pdev->dev.platform_data; | ||
848 | if (host->board->wire4) { | ||
849 | #ifdef SUPPORT_4WIRE | ||
850 | mmc->caps |= MMC_CAP_4_BIT_DATA; | ||
851 | #else | ||
852 | printk("MMC: 4 wire bus mode not supported by this driver - using 1 wire\n"); | ||
853 | #endif | ||
854 | } | ||
855 | |||
856 | /* | ||
857 | * Get Clock | ||
858 | */ | ||
859 | mci_clk = clk_get(&pdev->dev, "mci_clk"); | ||
860 | if (!mci_clk) { | ||
861 | printk(KERN_ERR "AT91 MMC: no clock defined.\n"); | ||
862 | return -ENODEV; | ||
863 | } | ||
864 | clk_enable(mci_clk); /* Enable the peripheral clock */ | ||
865 | |||
866 | /* | ||
867 | * Allocate the MCI interrupt | ||
868 | */ | ||
869 | ret = request_irq(AT91_ID_MCI, at91_mci_irq, SA_SHIRQ, DRIVER_NAME, host); | ||
870 | if (ret) { | ||
871 | DBG("Failed to request MCI interrupt\n"); | ||
872 | return ret; | ||
873 | } | ||
874 | |||
875 | platform_set_drvdata(pdev, mmc); | ||
876 | |||
877 | /* | ||
878 | * Add host to MMC layer | ||
879 | */ | ||
880 | if (host->board->det_pin) | ||
881 | host->present = !at91_get_gpio_value(host->board->det_pin); | ||
882 | else | ||
883 | host->present = -1; | ||
884 | |||
885 | mmc_add_host(mmc); | ||
886 | |||
887 | /* | ||
888 | * monitor card insertion/removal if we can | ||
889 | */ | ||
890 | if (host->board->det_pin) { | ||
891 | ret = request_irq(host->board->det_pin, at91_mmc_det_irq, | ||
892 | SA_SAMPLE_RANDOM, DRIVER_NAME, host); | ||
893 | if (ret) | ||
894 | DBG("couldn't allocate MMC detect irq\n"); | ||
895 | } | ||
896 | |||
897 | DBG(KERN_INFO "Added MCI driver\n"); | ||
898 | |||
899 | return 0; | ||
900 | } | ||
901 | |||
902 | /* | ||
903 | * Remove a device | ||
904 | */ | ||
905 | static int at91_mci_remove(struct platform_device *pdev) | ||
906 | { | ||
907 | struct mmc_host *mmc = platform_get_drvdata(pdev); | ||
908 | struct at91mci_host *host; | ||
909 | |||
910 | if (!mmc) | ||
911 | return -1; | ||
912 | |||
913 | host = mmc_priv(mmc); | ||
914 | |||
915 | if (host->present != -1) { | ||
916 | free_irq(host->board->det_pin, host); | ||
917 | cancel_delayed_work(&host->mmc->detect); | ||
918 | } | ||
919 | |||
920 | mmc_remove_host(mmc); | ||
921 | at91_mci_disable(); | ||
922 | free_irq(AT91_ID_MCI, host); | ||
923 | mmc_free_host(mmc); | ||
924 | |||
925 | clk_disable(mci_clk); /* Disable the peripheral clock */ | ||
926 | clk_put(mci_clk); | ||
927 | |||
928 | platform_set_drvdata(pdev, NULL); | ||
929 | |||
930 | DBG("Removed\n"); | ||
931 | |||
932 | return 0; | ||
933 | } | ||
934 | |||
935 | #ifdef CONFIG_PM | ||
936 | static int at91_mci_suspend(struct platform_device *pdev, pm_message_t state) | ||
937 | { | ||
938 | struct mmc_host *mmc = platform_get_drvdata(pdev); | ||
939 | int ret = 0; | ||
940 | |||
941 | if (mmc) | ||
942 | ret = mmc_suspend_host(mmc, state); | ||
943 | |||
944 | return ret; | ||
945 | } | ||
946 | |||
947 | static int at91_mci_resume(struct platform_device *pdev) | ||
948 | { | ||
949 | struct mmc_host *mmc = platform_get_drvdata(pdev); | ||
950 | int ret = 0; | ||
951 | |||
952 | if (mmc) | ||
953 | ret = mmc_resume_host(mmc); | ||
954 | |||
955 | return ret; | ||
956 | } | ||
957 | #else | ||
958 | #define at91_mci_suspend NULL | ||
959 | #define at91_mci_resume NULL | ||
960 | #endif | ||
961 | |||
962 | static struct platform_driver at91_mci_driver = { | ||
963 | .probe = at91_mci_probe, | ||
964 | .remove = at91_mci_remove, | ||
965 | .suspend = at91_mci_suspend, | ||
966 | .resume = at91_mci_resume, | ||
967 | .driver = { | ||
968 | .name = DRIVER_NAME, | ||
969 | .owner = THIS_MODULE, | ||
970 | }, | ||
971 | }; | ||
972 | |||
973 | static int __init at91_mci_init(void) | ||
974 | { | ||
975 | return platform_driver_register(&at91_mci_driver); | ||
976 | } | ||
977 | |||
978 | static void __exit at91_mci_exit(void) | ||
979 | { | ||
980 | platform_driver_unregister(&at91_mci_driver); | ||
981 | } | ||
982 | |||
983 | module_init(at91_mci_init); | ||
984 | module_exit(at91_mci_exit); | ||
985 | |||
986 | MODULE_DESCRIPTION("AT91 Multimedia Card Interface driver"); | ||
987 | MODULE_AUTHOR("Nick Randell"); | ||
988 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/mmc/imxmmc.c b/drivers/mmc/imxmmc.c new file mode 100644 index 000000000000..ffb7f55d3467 --- /dev/null +++ b/drivers/mmc/imxmmc.c | |||
@@ -0,0 +1,1096 @@ | |||
1 | /* | ||
2 | * linux/drivers/mmc/imxmmc.c - Motorola i.MX MMCI driver | ||
3 | * | ||
4 | * Copyright (C) 2004 Sascha Hauer, Pengutronix <sascha@saschahauer.de> | ||
5 | * Copyright (C) 2006 Pavel Pisa, PiKRON <ppisa@pikron.com> | ||
6 | * | ||
7 | * derived from pxamci.c by Russell King | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * 2005-04-17 Pavel Pisa <pisa@cmp.felk.cvut.cz> | ||
14 | * Changed to conform redesigned i.MX scatter gather DMA interface | ||
15 | * | ||
16 | * 2005-11-04 Pavel Pisa <pisa@cmp.felk.cvut.cz> | ||
17 | * Updated for 2.6.14 kernel | ||
18 | * | ||
19 | * 2005-12-13 Jay Monkman <jtm@smoothsmoothie.com> | ||
20 | * Found and corrected problems in the write path | ||
21 | * | ||
22 | * 2005-12-30 Pavel Pisa <pisa@cmp.felk.cvut.cz> | ||
23 | * The event handling rewritten right way in softirq. | ||
24 | * Added many ugly hacks and delays to overcome SDHC | ||
25 | * deficiencies | ||
26 | * | ||
27 | */ | ||
28 | #include <linux/config.h> | ||
29 | |||
30 | #ifdef CONFIG_MMC_DEBUG | ||
31 | #define DEBUG | ||
32 | #else | ||
33 | #undef DEBUG | ||
34 | #endif | ||
35 | |||
36 | #include <linux/module.h> | ||
37 | #include <linux/init.h> | ||
38 | #include <linux/ioport.h> | ||
39 | #include <linux/platform_device.h> | ||
40 | #include <linux/interrupt.h> | ||
41 | #include <linux/blkdev.h> | ||
42 | #include <linux/dma-mapping.h> | ||
43 | #include <linux/mmc/host.h> | ||
44 | #include <linux/mmc/card.h> | ||
45 | #include <linux/mmc/protocol.h> | ||
46 | #include <linux/delay.h> | ||
47 | |||
48 | #include <asm/dma.h> | ||
49 | #include <asm/io.h> | ||
50 | #include <asm/irq.h> | ||
51 | #include <asm/sizes.h> | ||
52 | #include <asm/arch/mmc.h> | ||
53 | #include <asm/arch/imx-dma.h> | ||
54 | |||
55 | #include "imxmmc.h" | ||
56 | |||
57 | #define DRIVER_NAME "imx-mmc" | ||
58 | |||
59 | #define IMXMCI_INT_MASK_DEFAULT (INT_MASK_BUF_READY | INT_MASK_DATA_TRAN | \ | ||
60 | INT_MASK_WRITE_OP_DONE | INT_MASK_END_CMD_RES | \ | ||
61 | INT_MASK_AUTO_CARD_DETECT | INT_MASK_DAT0_EN | INT_MASK_SDIO) | ||
62 | |||
63 | struct imxmci_host { | ||
64 | struct mmc_host *mmc; | ||
65 | spinlock_t lock; | ||
66 | struct resource *res; | ||
67 | int irq; | ||
68 | imx_dmach_t dma; | ||
69 | unsigned int clkrt; | ||
70 | unsigned int cmdat; | ||
71 | volatile unsigned int imask; | ||
72 | unsigned int power_mode; | ||
73 | unsigned int present; | ||
74 | struct imxmmc_platform_data *pdata; | ||
75 | |||
76 | struct mmc_request *req; | ||
77 | struct mmc_command *cmd; | ||
78 | struct mmc_data *data; | ||
79 | |||
80 | struct timer_list timer; | ||
81 | struct tasklet_struct tasklet; | ||
82 | unsigned int status_reg; | ||
83 | unsigned long pending_events; | ||
84 | /* Next to fields are there for CPU driven transfers to overcome SDHC deficiencies */ | ||
85 | u16 *data_ptr; | ||
86 | unsigned int data_cnt; | ||
87 | atomic_t stuck_timeout; | ||
88 | |||
89 | unsigned int dma_nents; | ||
90 | unsigned int dma_size; | ||
91 | unsigned int dma_dir; | ||
92 | int dma_allocated; | ||
93 | |||
94 | unsigned char actual_bus_width; | ||
95 | }; | ||
96 | |||
97 | #define IMXMCI_PEND_IRQ_b 0 | ||
98 | #define IMXMCI_PEND_DMA_END_b 1 | ||
99 | #define IMXMCI_PEND_DMA_ERR_b 2 | ||
100 | #define IMXMCI_PEND_WAIT_RESP_b 3 | ||
101 | #define IMXMCI_PEND_DMA_DATA_b 4 | ||
102 | #define IMXMCI_PEND_CPU_DATA_b 5 | ||
103 | #define IMXMCI_PEND_CARD_XCHG_b 6 | ||
104 | #define IMXMCI_PEND_SET_INIT_b 7 | ||
105 | |||
106 | #define IMXMCI_PEND_IRQ_m (1 << IMXMCI_PEND_IRQ_b) | ||
107 | #define IMXMCI_PEND_DMA_END_m (1 << IMXMCI_PEND_DMA_END_b) | ||
108 | #define IMXMCI_PEND_DMA_ERR_m (1 << IMXMCI_PEND_DMA_ERR_b) | ||
109 | #define IMXMCI_PEND_WAIT_RESP_m (1 << IMXMCI_PEND_WAIT_RESP_b) | ||
110 | #define IMXMCI_PEND_DMA_DATA_m (1 << IMXMCI_PEND_DMA_DATA_b) | ||
111 | #define IMXMCI_PEND_CPU_DATA_m (1 << IMXMCI_PEND_CPU_DATA_b) | ||
112 | #define IMXMCI_PEND_CARD_XCHG_m (1 << IMXMCI_PEND_CARD_XCHG_b) | ||
113 | #define IMXMCI_PEND_SET_INIT_m (1 << IMXMCI_PEND_SET_INIT_b) | ||
114 | |||
115 | static void imxmci_stop_clock(struct imxmci_host *host) | ||
116 | { | ||
117 | int i = 0; | ||
118 | MMC_STR_STP_CLK &= ~STR_STP_CLK_START_CLK; | ||
119 | while(i < 0x1000) { | ||
120 | if(!(i & 0x7f)) | ||
121 | MMC_STR_STP_CLK |= STR_STP_CLK_STOP_CLK; | ||
122 | |||
123 | if(!(MMC_STATUS & STATUS_CARD_BUS_CLK_RUN)) { | ||
124 | /* Check twice before cut */ | ||
125 | if(!(MMC_STATUS & STATUS_CARD_BUS_CLK_RUN)) | ||
126 | return; | ||
127 | } | ||
128 | |||
129 | i++; | ||
130 | } | ||
131 | dev_dbg(mmc_dev(host->mmc), "imxmci_stop_clock blocked, no luck\n"); | ||
132 | } | ||
133 | |||
134 | static void imxmci_start_clock(struct imxmci_host *host) | ||
135 | { | ||
136 | int i = 0; | ||
137 | MMC_STR_STP_CLK &= ~STR_STP_CLK_STOP_CLK; | ||
138 | while(i < 0x1000) { | ||
139 | if(!(i & 0x7f)) | ||
140 | MMC_STR_STP_CLK |= STR_STP_CLK_START_CLK; | ||
141 | |||
142 | if(MMC_STATUS & STATUS_CARD_BUS_CLK_RUN) { | ||
143 | /* Check twice before cut */ | ||
144 | if(MMC_STATUS & STATUS_CARD_BUS_CLK_RUN) | ||
145 | return; | ||
146 | } | ||
147 | |||
148 | i++; | ||
149 | } | ||
150 | dev_dbg(mmc_dev(host->mmc), "imxmci_start_clock blocked, no luck\n"); | ||
151 | } | ||
152 | |||
153 | static void imxmci_softreset(void) | ||
154 | { | ||
155 | /* reset sequence */ | ||
156 | MMC_STR_STP_CLK = 0x8; | ||
157 | MMC_STR_STP_CLK = 0xD; | ||
158 | MMC_STR_STP_CLK = 0x5; | ||
159 | MMC_STR_STP_CLK = 0x5; | ||
160 | MMC_STR_STP_CLK = 0x5; | ||
161 | MMC_STR_STP_CLK = 0x5; | ||
162 | MMC_STR_STP_CLK = 0x5; | ||
163 | MMC_STR_STP_CLK = 0x5; | ||
164 | MMC_STR_STP_CLK = 0x5; | ||
165 | MMC_STR_STP_CLK = 0x5; | ||
166 | |||
167 | MMC_RES_TO = 0xff; | ||
168 | MMC_BLK_LEN = 512; | ||
169 | MMC_NOB = 1; | ||
170 | } | ||
171 | |||
172 | static int imxmci_busy_wait_for_status(struct imxmci_host *host, | ||
173 | unsigned int *pstat, unsigned int stat_mask, | ||
174 | int timeout, const char *where) | ||
175 | { | ||
176 | int loops=0; | ||
177 | while(!(*pstat & stat_mask)) { | ||
178 | loops+=2; | ||
179 | if(loops >= timeout) { | ||
180 | dev_dbg(mmc_dev(host->mmc), "busy wait timeout in %s, STATUS = 0x%x (0x%x)\n", | ||
181 | where, *pstat, stat_mask); | ||
182 | return -1; | ||
183 | } | ||
184 | udelay(2); | ||
185 | *pstat |= MMC_STATUS; | ||
186 | } | ||
187 | if(!loops) | ||
188 | return 0; | ||
189 | |||
190 | dev_info(mmc_dev(host->mmc), "busy wait for %d usec in %s, STATUS = 0x%x (0x%x)\n", | ||
191 | loops, where, *pstat, stat_mask); | ||
192 | return loops; | ||
193 | } | ||
194 | |||
195 | static void imxmci_setup_data(struct imxmci_host *host, struct mmc_data *data) | ||
196 | { | ||
197 | unsigned int nob = data->blocks; | ||
198 | unsigned int blksz = 1 << data->blksz_bits; | ||
199 | unsigned int datasz = nob * blksz; | ||
200 | int i; | ||
201 | |||
202 | if (data->flags & MMC_DATA_STREAM) | ||
203 | nob = 0xffff; | ||
204 | |||
205 | host->data = data; | ||
206 | data->bytes_xfered = 0; | ||
207 | |||
208 | MMC_NOB = nob; | ||
209 | MMC_BLK_LEN = blksz; | ||
210 | |||
211 | /* | ||
212 | * DMA cannot be used for small block sizes, we have to use CPU driven transfers otherwise. | ||
213 | * We are in big troubles for non-512 byte transfers according to note in the paragraph | ||
214 | * 20.6.7 of User Manual anyway, but we need to be able to transfer SCR at least. | ||
215 | * The situation is even more complex in reality. The SDHC in not able to handle wll | ||
216 | * partial FIFO fills and reads. The length has to be rounded up to burst size multiple. | ||
217 | * This is required for SCR read at least. | ||
218 | */ | ||
219 | if (datasz < 64) { | ||
220 | host->dma_size = datasz; | ||
221 | if (data->flags & MMC_DATA_READ) { | ||
222 | host->dma_dir = DMA_FROM_DEVICE; | ||
223 | |||
224 | /* Hack to enable read SCR */ | ||
225 | if(datasz < 16) { | ||
226 | MMC_NOB = 1; | ||
227 | MMC_BLK_LEN = 16; | ||
228 | } | ||
229 | } else { | ||
230 | host->dma_dir = DMA_TO_DEVICE; | ||
231 | } | ||
232 | |||
233 | /* Convert back to virtual address */ | ||
234 | host->data_ptr = (u16*)(page_address(data->sg->page) + data->sg->offset); | ||
235 | host->data_cnt = 0; | ||
236 | |||
237 | clear_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events); | ||
238 | set_bit(IMXMCI_PEND_CPU_DATA_b, &host->pending_events); | ||
239 | |||
240 | return; | ||
241 | } | ||
242 | |||
243 | if (data->flags & MMC_DATA_READ) { | ||
244 | host->dma_dir = DMA_FROM_DEVICE; | ||
245 | host->dma_nents = dma_map_sg(mmc_dev(host->mmc), data->sg, | ||
246 | data->sg_len, host->dma_dir); | ||
247 | |||
248 | imx_dma_setup_sg(host->dma, data->sg, data->sg_len, datasz, | ||
249 | host->res->start + MMC_BUFFER_ACCESS_OFS, DMA_MODE_READ); | ||
250 | |||
251 | /*imx_dma_setup_mem2dev_ccr(host->dma, DMA_MODE_READ, IMX_DMA_WIDTH_16, CCR_REN);*/ | ||
252 | CCR(host->dma) = CCR_DMOD_LINEAR | CCR_DSIZ_32 | CCR_SMOD_FIFO | CCR_SSIZ_16 | CCR_REN; | ||
253 | } else { | ||
254 | host->dma_dir = DMA_TO_DEVICE; | ||
255 | |||
256 | host->dma_nents = dma_map_sg(mmc_dev(host->mmc), data->sg, | ||
257 | data->sg_len, host->dma_dir); | ||
258 | |||
259 | imx_dma_setup_sg(host->dma, data->sg, data->sg_len, datasz, | ||
260 | host->res->start + MMC_BUFFER_ACCESS_OFS, DMA_MODE_WRITE); | ||
261 | |||
262 | /*imx_dma_setup_mem2dev_ccr(host->dma, DMA_MODE_WRITE, IMX_DMA_WIDTH_16, CCR_REN);*/ | ||
263 | CCR(host->dma) = CCR_SMOD_LINEAR | CCR_SSIZ_32 | CCR_DMOD_FIFO | CCR_DSIZ_16 | CCR_REN; | ||
264 | } | ||
265 | |||
266 | #if 1 /* This code is there only for consistency checking and can be disabled in future */ | ||
267 | host->dma_size = 0; | ||
268 | for(i=0; i<host->dma_nents; i++) | ||
269 | host->dma_size+=data->sg[i].length; | ||
270 | |||
271 | if (datasz > host->dma_size) { | ||
272 | dev_err(mmc_dev(host->mmc), "imxmci_setup_data datasz 0x%x > 0x%x dm_size\n", | ||
273 | datasz, host->dma_size); | ||
274 | } | ||
275 | #endif | ||
276 | |||
277 | host->dma_size = datasz; | ||
278 | |||
279 | wmb(); | ||
280 | |||
281 | if(host->actual_bus_width == MMC_BUS_WIDTH_4) | ||
282 | BLR(host->dma) = 0; /* burst 64 byte read / 64 bytes write */ | ||
283 | else | ||
284 | BLR(host->dma) = 16; /* burst 16 byte read / 16 bytes write */ | ||
285 | |||
286 | RSSR(host->dma) = DMA_REQ_SDHC; | ||
287 | |||
288 | set_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events); | ||
289 | clear_bit(IMXMCI_PEND_CPU_DATA_b, &host->pending_events); | ||
290 | |||
291 | /* start DMA engine for read, write is delayed after initial response */ | ||
292 | if (host->dma_dir == DMA_FROM_DEVICE) { | ||
293 | imx_dma_enable(host->dma); | ||
294 | } | ||
295 | } | ||
296 | |||
297 | static void imxmci_start_cmd(struct imxmci_host *host, struct mmc_command *cmd, unsigned int cmdat) | ||
298 | { | ||
299 | unsigned long flags; | ||
300 | u32 imask; | ||
301 | |||
302 | WARN_ON(host->cmd != NULL); | ||
303 | host->cmd = cmd; | ||
304 | |||
305 | if (cmd->flags & MMC_RSP_BUSY) | ||
306 | cmdat |= CMD_DAT_CONT_BUSY; | ||
307 | |||
308 | switch (mmc_resp_type(cmd)) { | ||
309 | case MMC_RSP_R1: /* short CRC, OPCODE */ | ||
310 | case MMC_RSP_R1B:/* short CRC, OPCODE, BUSY */ | ||
311 | cmdat |= CMD_DAT_CONT_RESPONSE_FORMAT_R1; | ||
312 | break; | ||
313 | case MMC_RSP_R2: /* long 136 bit + CRC */ | ||
314 | cmdat |= CMD_DAT_CONT_RESPONSE_FORMAT_R2; | ||
315 | break; | ||
316 | case MMC_RSP_R3: /* short */ | ||
317 | cmdat |= CMD_DAT_CONT_RESPONSE_FORMAT_R3; | ||
318 | break; | ||
319 | case MMC_RSP_R6: /* short CRC */ | ||
320 | cmdat |= CMD_DAT_CONT_RESPONSE_FORMAT_R6; | ||
321 | break; | ||
322 | default: | ||
323 | break; | ||
324 | } | ||
325 | |||
326 | if ( test_and_clear_bit(IMXMCI_PEND_SET_INIT_b, &host->pending_events) ) | ||
327 | cmdat |= CMD_DAT_CONT_INIT; /* This command needs init */ | ||
328 | |||
329 | if ( host->actual_bus_width == MMC_BUS_WIDTH_4 ) | ||
330 | cmdat |= CMD_DAT_CONT_BUS_WIDTH_4; | ||
331 | |||
332 | MMC_CMD = cmd->opcode; | ||
333 | MMC_ARGH = cmd->arg >> 16; | ||
334 | MMC_ARGL = cmd->arg & 0xffff; | ||
335 | MMC_CMD_DAT_CONT = cmdat; | ||
336 | |||
337 | atomic_set(&host->stuck_timeout, 0); | ||
338 | set_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events); | ||
339 | |||
340 | |||
341 | imask = IMXMCI_INT_MASK_DEFAULT; | ||
342 | imask &= ~INT_MASK_END_CMD_RES; | ||
343 | if ( cmdat & CMD_DAT_CONT_DATA_ENABLE ) { | ||
344 | /*imask &= ~INT_MASK_BUF_READY;*/ | ||
345 | imask &= ~INT_MASK_DATA_TRAN; | ||
346 | if ( cmdat & CMD_DAT_CONT_WRITE ) | ||
347 | imask &= ~INT_MASK_WRITE_OP_DONE; | ||
348 | if(test_bit(IMXMCI_PEND_CPU_DATA_b, &host->pending_events)) | ||
349 | imask &= ~INT_MASK_BUF_READY; | ||
350 | } | ||
351 | |||
352 | spin_lock_irqsave(&host->lock, flags); | ||
353 | host->imask = imask; | ||
354 | MMC_INT_MASK = host->imask; | ||
355 | spin_unlock_irqrestore(&host->lock, flags); | ||
356 | |||
357 | dev_dbg(mmc_dev(host->mmc), "CMD%02d (0x%02x) mask set to 0x%04x\n", | ||
358 | cmd->opcode, cmd->opcode, imask); | ||
359 | |||
360 | imxmci_start_clock(host); | ||
361 | } | ||
362 | |||
363 | static void imxmci_finish_request(struct imxmci_host *host, struct mmc_request *req) | ||
364 | { | ||
365 | unsigned long flags; | ||
366 | |||
367 | spin_lock_irqsave(&host->lock, flags); | ||
368 | |||
369 | host->pending_events &= ~(IMXMCI_PEND_WAIT_RESP_m | IMXMCI_PEND_DMA_END_m | | ||
370 | IMXMCI_PEND_DMA_DATA_m | IMXMCI_PEND_CPU_DATA_m); | ||
371 | |||
372 | host->imask = IMXMCI_INT_MASK_DEFAULT; | ||
373 | MMC_INT_MASK = host->imask; | ||
374 | |||
375 | spin_unlock_irqrestore(&host->lock, flags); | ||
376 | |||
377 | host->req = NULL; | ||
378 | host->cmd = NULL; | ||
379 | host->data = NULL; | ||
380 | mmc_request_done(host->mmc, req); | ||
381 | } | ||
382 | |||
383 | static int imxmci_finish_data(struct imxmci_host *host, unsigned int stat) | ||
384 | { | ||
385 | struct mmc_data *data = host->data; | ||
386 | int data_error; | ||
387 | |||
388 | if(test_and_clear_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events)){ | ||
389 | imx_dma_disable(host->dma); | ||
390 | dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_nents, | ||
391 | host->dma_dir); | ||
392 | } | ||
393 | |||
394 | if ( stat & STATUS_ERR_MASK ) { | ||
395 | dev_dbg(mmc_dev(host->mmc), "request failed. status: 0x%08x\n",stat); | ||
396 | if(stat & (STATUS_CRC_READ_ERR | STATUS_CRC_WRITE_ERR)) | ||
397 | data->error = MMC_ERR_BADCRC; | ||
398 | else if(stat & STATUS_TIME_OUT_READ) | ||
399 | data->error = MMC_ERR_TIMEOUT; | ||
400 | else | ||
401 | data->error = MMC_ERR_FAILED; | ||
402 | } else { | ||
403 | data->bytes_xfered = host->dma_size; | ||
404 | } | ||
405 | |||
406 | data_error = data->error; | ||
407 | |||
408 | host->data = NULL; | ||
409 | |||
410 | return data_error; | ||
411 | } | ||
412 | |||
413 | static int imxmci_cmd_done(struct imxmci_host *host, unsigned int stat) | ||
414 | { | ||
415 | struct mmc_command *cmd = host->cmd; | ||
416 | int i; | ||
417 | u32 a,b,c; | ||
418 | struct mmc_data *data = host->data; | ||
419 | |||
420 | if (!cmd) | ||
421 | return 0; | ||
422 | |||
423 | host->cmd = NULL; | ||
424 | |||
425 | if (stat & STATUS_TIME_OUT_RESP) { | ||
426 | dev_dbg(mmc_dev(host->mmc), "CMD TIMEOUT\n"); | ||
427 | cmd->error = MMC_ERR_TIMEOUT; | ||
428 | } else if (stat & STATUS_RESP_CRC_ERR && cmd->flags & MMC_RSP_CRC) { | ||
429 | dev_dbg(mmc_dev(host->mmc), "cmd crc error\n"); | ||
430 | cmd->error = MMC_ERR_BADCRC; | ||
431 | } | ||
432 | |||
433 | if(cmd->flags & MMC_RSP_PRESENT) { | ||
434 | if(cmd->flags & MMC_RSP_136) { | ||
435 | for (i = 0; i < 4; i++) { | ||
436 | u32 a = MMC_RES_FIFO & 0xffff; | ||
437 | u32 b = MMC_RES_FIFO & 0xffff; | ||
438 | cmd->resp[i] = a<<16 | b; | ||
439 | } | ||
440 | } else { | ||
441 | a = MMC_RES_FIFO & 0xffff; | ||
442 | b = MMC_RES_FIFO & 0xffff; | ||
443 | c = MMC_RES_FIFO & 0xffff; | ||
444 | cmd->resp[0] = a<<24 | b<<8 | c>>8; | ||
445 | } | ||
446 | } | ||
447 | |||
448 | dev_dbg(mmc_dev(host->mmc), "RESP 0x%08x, 0x%08x, 0x%08x, 0x%08x, error %d\n", | ||
449 | cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3], cmd->error); | ||
450 | |||
451 | if (data && (cmd->error == MMC_ERR_NONE) && !(stat & STATUS_ERR_MASK)) { | ||
452 | if (host->req->data->flags & MMC_DATA_WRITE) { | ||
453 | |||
454 | /* Wait for FIFO to be empty before starting DMA write */ | ||
455 | |||
456 | stat = MMC_STATUS; | ||
457 | if(imxmci_busy_wait_for_status(host, &stat, | ||
458 | STATUS_APPL_BUFF_FE, | ||
459 | 40, "imxmci_cmd_done DMA WR") < 0) { | ||
460 | cmd->error = MMC_ERR_FIFO; | ||
461 | imxmci_finish_data(host, stat); | ||
462 | if(host->req) | ||
463 | imxmci_finish_request(host, host->req); | ||
464 | dev_warn(mmc_dev(host->mmc), "STATUS = 0x%04x\n", | ||
465 | stat); | ||
466 | return 0; | ||
467 | } | ||
468 | |||
469 | if(test_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events)) { | ||
470 | imx_dma_enable(host->dma); | ||
471 | } | ||
472 | } | ||
473 | } else { | ||
474 | struct mmc_request *req; | ||
475 | imxmci_stop_clock(host); | ||
476 | req = host->req; | ||
477 | |||
478 | if(data) | ||
479 | imxmci_finish_data(host, stat); | ||
480 | |||
481 | if( req ) { | ||
482 | imxmci_finish_request(host, req); | ||
483 | } else { | ||
484 | dev_warn(mmc_dev(host->mmc), "imxmci_cmd_done: no request to finish\n"); | ||
485 | } | ||
486 | } | ||
487 | |||
488 | return 1; | ||
489 | } | ||
490 | |||
491 | static int imxmci_data_done(struct imxmci_host *host, unsigned int stat) | ||
492 | { | ||
493 | struct mmc_data *data = host->data; | ||
494 | int data_error; | ||
495 | |||
496 | if (!data) | ||
497 | return 0; | ||
498 | |||
499 | data_error = imxmci_finish_data(host, stat); | ||
500 | |||
501 | if (host->req->stop && (data_error == MMC_ERR_NONE)) { | ||
502 | imxmci_stop_clock(host); | ||
503 | imxmci_start_cmd(host, host->req->stop, 0); | ||
504 | } else { | ||
505 | struct mmc_request *req; | ||
506 | req = host->req; | ||
507 | if( req ) { | ||
508 | imxmci_finish_request(host, req); | ||
509 | } else { | ||
510 | dev_warn(mmc_dev(host->mmc), "imxmci_data_done: no request to finish\n"); | ||
511 | } | ||
512 | } | ||
513 | |||
514 | return 1; | ||
515 | } | ||
516 | |||
517 | static int imxmci_cpu_driven_data(struct imxmci_host *host, unsigned int *pstat) | ||
518 | { | ||
519 | int i; | ||
520 | int burst_len; | ||
521 | int flush_len; | ||
522 | int trans_done = 0; | ||
523 | unsigned int stat = *pstat; | ||
524 | |||
525 | if(host->actual_bus_width == MMC_BUS_WIDTH_4) | ||
526 | burst_len = 16; | ||
527 | else | ||
528 | burst_len = 64; | ||
529 | |||
530 | /* This is unfortunately required */ | ||
531 | dev_dbg(mmc_dev(host->mmc), "imxmci_cpu_driven_data running STATUS = 0x%x\n", | ||
532 | stat); | ||
533 | |||
534 | if(host->dma_dir == DMA_FROM_DEVICE) { | ||
535 | imxmci_busy_wait_for_status(host, &stat, | ||
536 | STATUS_APPL_BUFF_FF | STATUS_DATA_TRANS_DONE, | ||
537 | 20, "imxmci_cpu_driven_data read"); | ||
538 | |||
539 | while((stat & (STATUS_APPL_BUFF_FF | STATUS_DATA_TRANS_DONE)) && | ||
540 | (host->data_cnt < host->dma_size)) { | ||
541 | if(burst_len >= host->dma_size - host->data_cnt) { | ||
542 | flush_len = burst_len; | ||
543 | burst_len = host->dma_size - host->data_cnt; | ||
544 | flush_len -= burst_len; | ||
545 | host->data_cnt = host->dma_size; | ||
546 | trans_done = 1; | ||
547 | } else { | ||
548 | flush_len = 0; | ||
549 | host->data_cnt += burst_len; | ||
550 | } | ||
551 | |||
552 | for(i = burst_len; i>=2 ; i-=2) { | ||
553 | *(host->data_ptr++) = MMC_BUFFER_ACCESS; | ||
554 | udelay(20); /* required for clocks < 8MHz*/ | ||
555 | } | ||
556 | |||
557 | if(i == 1) | ||
558 | *(u8*)(host->data_ptr) = MMC_BUFFER_ACCESS; | ||
559 | |||
560 | stat = MMC_STATUS; | ||
561 | |||
562 | /* Flush extra bytes from FIFO */ | ||
563 | while(flush_len >= 2){ | ||
564 | flush_len -= 2; | ||
565 | i = MMC_BUFFER_ACCESS; | ||
566 | stat = MMC_STATUS; | ||
567 | stat &= ~STATUS_CRC_READ_ERR; /* Stupid but required there */ | ||
568 | } | ||
569 | |||
570 | dev_dbg(mmc_dev(host->mmc), "imxmci_cpu_driven_data read burst %d STATUS = 0x%x\n", | ||
571 | burst_len, stat); | ||
572 | } | ||
573 | } else { | ||
574 | imxmci_busy_wait_for_status(host, &stat, | ||
575 | STATUS_APPL_BUFF_FE, | ||
576 | 20, "imxmci_cpu_driven_data write"); | ||
577 | |||
578 | while((stat & STATUS_APPL_BUFF_FE) && | ||
579 | (host->data_cnt < host->dma_size)) { | ||
580 | if(burst_len >= host->dma_size - host->data_cnt) { | ||
581 | burst_len = host->dma_size - host->data_cnt; | ||
582 | host->data_cnt = host->dma_size; | ||
583 | trans_done = 1; | ||
584 | } else { | ||
585 | host->data_cnt += burst_len; | ||
586 | } | ||
587 | |||
588 | for(i = burst_len; i>0 ; i-=2) | ||
589 | MMC_BUFFER_ACCESS = *(host->data_ptr++); | ||
590 | |||
591 | stat = MMC_STATUS; | ||
592 | |||
593 | dev_dbg(mmc_dev(host->mmc), "imxmci_cpu_driven_data write burst %d STATUS = 0x%x\n", | ||
594 | burst_len, stat); | ||
595 | } | ||
596 | } | ||
597 | |||
598 | *pstat = stat; | ||
599 | |||
600 | return trans_done; | ||
601 | } | ||
602 | |||
603 | static void imxmci_dma_irq(int dma, void *devid, struct pt_regs *regs) | ||
604 | { | ||
605 | struct imxmci_host *host = devid; | ||
606 | uint32_t stat = MMC_STATUS; | ||
607 | |||
608 | atomic_set(&host->stuck_timeout, 0); | ||
609 | host->status_reg = stat; | ||
610 | set_bit(IMXMCI_PEND_DMA_END_b, &host->pending_events); | ||
611 | tasklet_schedule(&host->tasklet); | ||
612 | } | ||
613 | |||
614 | static irqreturn_t imxmci_irq(int irq, void *devid, struct pt_regs *regs) | ||
615 | { | ||
616 | struct imxmci_host *host = devid; | ||
617 | uint32_t stat = MMC_STATUS; | ||
618 | int handled = 1; | ||
619 | |||
620 | MMC_INT_MASK = host->imask | INT_MASK_SDIO | INT_MASK_AUTO_CARD_DETECT; | ||
621 | |||
622 | atomic_set(&host->stuck_timeout, 0); | ||
623 | host->status_reg = stat; | ||
624 | set_bit(IMXMCI_PEND_IRQ_b, &host->pending_events); | ||
625 | tasklet_schedule(&host->tasklet); | ||
626 | |||
627 | return IRQ_RETVAL(handled);; | ||
628 | } | ||
629 | |||
630 | static void imxmci_tasklet_fnc(unsigned long data) | ||
631 | { | ||
632 | struct imxmci_host *host = (struct imxmci_host *)data; | ||
633 | u32 stat; | ||
634 | unsigned int data_dir_mask = 0; /* STATUS_WR_CRC_ERROR_CODE_MASK */ | ||
635 | int timeout = 0; | ||
636 | |||
637 | if(atomic_read(&host->stuck_timeout) > 4) { | ||
638 | char *what; | ||
639 | timeout = 1; | ||
640 | stat = MMC_STATUS; | ||
641 | host->status_reg = stat; | ||
642 | if (test_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events)) | ||
643 | if (test_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events)) | ||
644 | what = "RESP+DMA"; | ||
645 | else | ||
646 | what = "RESP"; | ||
647 | else | ||
648 | if (test_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events)) | ||
649 | if(test_bit(IMXMCI_PEND_DMA_END_b, &host->pending_events)) | ||
650 | what = "DATA"; | ||
651 | else | ||
652 | what = "DMA"; | ||
653 | else | ||
654 | what = "???"; | ||
655 | |||
656 | dev_err(mmc_dev(host->mmc), "%s TIMEOUT, hardware stucked STATUS = 0x%04x IMASK = 0x%04x\n", | ||
657 | what, stat, MMC_INT_MASK); | ||
658 | dev_err(mmc_dev(host->mmc), "CMD_DAT_CONT = 0x%04x, MMC_BLK_LEN = 0x%04x, MMC_NOB = 0x%04x, DMA_CCR = 0x%08x\n", | ||
659 | MMC_CMD_DAT_CONT, MMC_BLK_LEN, MMC_NOB, CCR(host->dma)); | ||
660 | dev_err(mmc_dev(host->mmc), "CMD%d, bus %d-bit, dma_size = 0x%x\n", | ||
661 | host->cmd?host->cmd->opcode:0, 1<<host->actual_bus_width, host->dma_size); | ||
662 | } | ||
663 | |||
664 | if(!host->present || timeout) | ||
665 | host->status_reg = STATUS_TIME_OUT_RESP | STATUS_TIME_OUT_READ | | ||
666 | STATUS_CRC_READ_ERR | STATUS_CRC_WRITE_ERR; | ||
667 | |||
668 | if(test_bit(IMXMCI_PEND_IRQ_b, &host->pending_events) || timeout) { | ||
669 | clear_bit(IMXMCI_PEND_IRQ_b, &host->pending_events); | ||
670 | |||
671 | stat = MMC_STATUS; | ||
672 | /* | ||
673 | * This is not required in theory, but there is chance to miss some flag | ||
674 | * which clears automatically by mask write, FreeScale original code keeps | ||
675 | * stat from IRQ time so do I | ||
676 | */ | ||
677 | stat |= host->status_reg; | ||
678 | |||
679 | if(test_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events)) { | ||
680 | imxmci_busy_wait_for_status(host, &stat, | ||
681 | STATUS_END_CMD_RESP | STATUS_ERR_MASK, | ||
682 | 20, "imxmci_tasklet_fnc resp (ERRATUM #4)"); | ||
683 | } | ||
684 | |||
685 | if(stat & (STATUS_END_CMD_RESP | STATUS_ERR_MASK)) { | ||
686 | if(test_and_clear_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events)) | ||
687 | imxmci_cmd_done(host, stat); | ||
688 | if(host->data && (stat & STATUS_ERR_MASK)) | ||
689 | imxmci_data_done(host, stat); | ||
690 | } | ||
691 | |||
692 | if(test_bit(IMXMCI_PEND_CPU_DATA_b, &host->pending_events)) { | ||
693 | stat |= MMC_STATUS; | ||
694 | if(imxmci_cpu_driven_data(host, &stat)){ | ||
695 | if(test_and_clear_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events)) | ||
696 | imxmci_cmd_done(host, stat); | ||
697 | atomic_clear_mask(IMXMCI_PEND_IRQ_m|IMXMCI_PEND_CPU_DATA_m, | ||
698 | &host->pending_events); | ||
699 | imxmci_data_done(host, stat); | ||
700 | } | ||
701 | } | ||
702 | } | ||
703 | |||
704 | if(test_bit(IMXMCI_PEND_DMA_END_b, &host->pending_events) && | ||
705 | !test_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events)) { | ||
706 | |||
707 | stat = MMC_STATUS; | ||
708 | /* Same as above */ | ||
709 | stat |= host->status_reg; | ||
710 | |||
711 | if(host->dma_dir == DMA_TO_DEVICE) { | ||
712 | data_dir_mask = STATUS_WRITE_OP_DONE; | ||
713 | } else { | ||
714 | data_dir_mask = STATUS_DATA_TRANS_DONE; | ||
715 | } | ||
716 | |||
717 | imxmci_busy_wait_for_status(host, &stat, | ||
718 | data_dir_mask, | ||
719 | 50, "imxmci_tasklet_fnc data"); | ||
720 | |||
721 | if(stat & data_dir_mask) { | ||
722 | clear_bit(IMXMCI_PEND_DMA_END_b, &host->pending_events); | ||
723 | imxmci_data_done(host, stat); | ||
724 | } | ||
725 | } | ||
726 | |||
727 | if(test_and_clear_bit(IMXMCI_PEND_CARD_XCHG_b, &host->pending_events)) { | ||
728 | |||
729 | if(host->cmd) | ||
730 | imxmci_cmd_done(host, STATUS_TIME_OUT_RESP); | ||
731 | |||
732 | if(host->data) | ||
733 | imxmci_data_done(host, STATUS_TIME_OUT_READ | | ||
734 | STATUS_CRC_READ_ERR | STATUS_CRC_WRITE_ERR); | ||
735 | |||
736 | if(host->req) | ||
737 | imxmci_finish_request(host, host->req); | ||
738 | |||
739 | mmc_detect_change(host->mmc, msecs_to_jiffies(100)); | ||
740 | |||
741 | } | ||
742 | } | ||
743 | |||
744 | static void imxmci_request(struct mmc_host *mmc, struct mmc_request *req) | ||
745 | { | ||
746 | struct imxmci_host *host = mmc_priv(mmc); | ||
747 | unsigned int cmdat; | ||
748 | |||
749 | WARN_ON(host->req != NULL); | ||
750 | |||
751 | host->req = req; | ||
752 | |||
753 | cmdat = 0; | ||
754 | |||
755 | if (req->data) { | ||
756 | imxmci_setup_data(host, req->data); | ||
757 | |||
758 | cmdat |= CMD_DAT_CONT_DATA_ENABLE; | ||
759 | |||
760 | if (req->data->flags & MMC_DATA_WRITE) | ||
761 | cmdat |= CMD_DAT_CONT_WRITE; | ||
762 | |||
763 | if (req->data->flags & MMC_DATA_STREAM) { | ||
764 | cmdat |= CMD_DAT_CONT_STREAM_BLOCK; | ||
765 | } | ||
766 | } | ||
767 | |||
768 | imxmci_start_cmd(host, req->cmd, cmdat); | ||
769 | } | ||
770 | |||
771 | #define CLK_RATE 19200000 | ||
772 | |||
773 | static void imxmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | ||
774 | { | ||
775 | struct imxmci_host *host = mmc_priv(mmc); | ||
776 | int prescaler; | ||
777 | |||
778 | dev_dbg(mmc_dev(host->mmc), "clock %u power %u vdd %u width %u\n", | ||
779 | ios->clock, ios->power_mode, ios->vdd, | ||
780 | (ios->bus_width==MMC_BUS_WIDTH_4)?4:1); | ||
781 | |||
782 | if( ios->bus_width==MMC_BUS_WIDTH_4 ) { | ||
783 | host->actual_bus_width = MMC_BUS_WIDTH_4; | ||
784 | imx_gpio_mode(PB11_PF_SD_DAT3); | ||
785 | }else{ | ||
786 | host->actual_bus_width = MMC_BUS_WIDTH_1; | ||
787 | imx_gpio_mode(GPIO_PORTB | GPIO_IN | GPIO_PUEN | 11); | ||
788 | } | ||
789 | |||
790 | if ( host->power_mode != ios->power_mode ) { | ||
791 | switch (ios->power_mode) { | ||
792 | case MMC_POWER_OFF: | ||
793 | break; | ||
794 | case MMC_POWER_UP: | ||
795 | set_bit(IMXMCI_PEND_SET_INIT_b, &host->pending_events); | ||
796 | break; | ||
797 | case MMC_POWER_ON: | ||
798 | break; | ||
799 | } | ||
800 | host->power_mode = ios->power_mode; | ||
801 | } | ||
802 | |||
803 | if ( ios->clock ) { | ||
804 | unsigned int clk; | ||
805 | |||
806 | /* The prescaler is 5 for PERCLK2 equal to 96MHz | ||
807 | * then 96MHz / 5 = 19.2 MHz | ||
808 | */ | ||
809 | clk=imx_get_perclk2(); | ||
810 | prescaler=(clk+(CLK_RATE*7)/8)/CLK_RATE; | ||
811 | switch(prescaler) { | ||
812 | case 0: | ||
813 | case 1: prescaler = 0; | ||
814 | break; | ||
815 | case 2: prescaler = 1; | ||
816 | break; | ||
817 | case 3: prescaler = 2; | ||
818 | break; | ||
819 | case 4: prescaler = 4; | ||
820 | break; | ||
821 | default: | ||
822 | case 5: prescaler = 5; | ||
823 | break; | ||
824 | } | ||
825 | |||
826 | dev_dbg(mmc_dev(host->mmc), "PERCLK2 %d MHz -> prescaler %d\n", | ||
827 | clk, prescaler); | ||
828 | |||
829 | for(clk=0; clk<8; clk++) { | ||
830 | int x; | ||
831 | x = CLK_RATE / (1<<clk); | ||
832 | if( x <= ios->clock) | ||
833 | break; | ||
834 | } | ||
835 | |||
836 | MMC_STR_STP_CLK |= STR_STP_CLK_ENABLE; /* enable controller */ | ||
837 | |||
838 | imxmci_stop_clock(host); | ||
839 | MMC_CLK_RATE = (prescaler<<3) | clk; | ||
840 | imxmci_start_clock(host); | ||
841 | |||
842 | dev_dbg(mmc_dev(host->mmc), "MMC_CLK_RATE: 0x%08x\n", MMC_CLK_RATE); | ||
843 | } else { | ||
844 | imxmci_stop_clock(host); | ||
845 | } | ||
846 | } | ||
847 | |||
848 | static struct mmc_host_ops imxmci_ops = { | ||
849 | .request = imxmci_request, | ||
850 | .set_ios = imxmci_set_ios, | ||
851 | }; | ||
852 | |||
853 | static struct resource *platform_device_resource(struct platform_device *dev, unsigned int mask, int nr) | ||
854 | { | ||
855 | int i; | ||
856 | |||
857 | for (i = 0; i < dev->num_resources; i++) | ||
858 | if (dev->resource[i].flags == mask && nr-- == 0) | ||
859 | return &dev->resource[i]; | ||
860 | return NULL; | ||
861 | } | ||
862 | |||
863 | static int platform_device_irq(struct platform_device *dev, int nr) | ||
864 | { | ||
865 | int i; | ||
866 | |||
867 | for (i = 0; i < dev->num_resources; i++) | ||
868 | if (dev->resource[i].flags == IORESOURCE_IRQ && nr-- == 0) | ||
869 | return dev->resource[i].start; | ||
870 | return NO_IRQ; | ||
871 | } | ||
872 | |||
873 | static void imxmci_check_status(unsigned long data) | ||
874 | { | ||
875 | struct imxmci_host *host = (struct imxmci_host *)data; | ||
876 | |||
877 | if( host->pdata->card_present() != host->present ) { | ||
878 | host->present ^= 1; | ||
879 | dev_info(mmc_dev(host->mmc), "card %s\n", | ||
880 | host->present ? "inserted" : "removed"); | ||
881 | |||
882 | set_bit(IMXMCI_PEND_CARD_XCHG_b, &host->pending_events); | ||
883 | tasklet_schedule(&host->tasklet); | ||
884 | } | ||
885 | |||
886 | if(test_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events) || | ||
887 | test_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events)) { | ||
888 | atomic_inc(&host->stuck_timeout); | ||
889 | if(atomic_read(&host->stuck_timeout) > 4) | ||
890 | tasklet_schedule(&host->tasklet); | ||
891 | } else { | ||
892 | atomic_set(&host->stuck_timeout, 0); | ||
893 | |||
894 | } | ||
895 | |||
896 | mod_timer(&host->timer, jiffies + (HZ>>1)); | ||
897 | } | ||
898 | |||
899 | static int imxmci_probe(struct platform_device *pdev) | ||
900 | { | ||
901 | struct mmc_host *mmc; | ||
902 | struct imxmci_host *host = NULL; | ||
903 | struct resource *r; | ||
904 | int ret = 0, irq; | ||
905 | |||
906 | printk(KERN_INFO "i.MX mmc driver\n"); | ||
907 | |||
908 | r = platform_device_resource(pdev, IORESOURCE_MEM, 0); | ||
909 | irq = platform_device_irq(pdev, 0); | ||
910 | if (!r || irq == NO_IRQ) | ||
911 | return -ENXIO; | ||
912 | |||
913 | r = request_mem_region(r->start, 0x100, "IMXMCI"); | ||
914 | if (!r) | ||
915 | return -EBUSY; | ||
916 | |||
917 | mmc = mmc_alloc_host(sizeof(struct imxmci_host), &pdev->dev); | ||
918 | if (!mmc) { | ||
919 | ret = -ENOMEM; | ||
920 | goto out; | ||
921 | } | ||
922 | |||
923 | mmc->ops = &imxmci_ops; | ||
924 | mmc->f_min = 150000; | ||
925 | mmc->f_max = CLK_RATE/2; | ||
926 | mmc->ocr_avail = MMC_VDD_32_33; | ||
927 | mmc->caps |= MMC_CAP_4_BIT_DATA; | ||
928 | |||
929 | /* MMC core transfer sizes tunable parameters */ | ||
930 | mmc->max_hw_segs = 64; | ||
931 | mmc->max_phys_segs = 64; | ||
932 | mmc->max_sectors = 64; /* default 1 << (PAGE_CACHE_SHIFT - 9) */ | ||
933 | mmc->max_seg_size = 64*512; /* default PAGE_CACHE_SIZE */ | ||
934 | |||
935 | host = mmc_priv(mmc); | ||
936 | host->mmc = mmc; | ||
937 | host->dma_allocated = 0; | ||
938 | host->pdata = pdev->dev.platform_data; | ||
939 | |||
940 | spin_lock_init(&host->lock); | ||
941 | host->res = r; | ||
942 | host->irq = irq; | ||
943 | |||
944 | imx_gpio_mode(PB8_PF_SD_DAT0); | ||
945 | imx_gpio_mode(PB9_PF_SD_DAT1); | ||
946 | imx_gpio_mode(PB10_PF_SD_DAT2); | ||
947 | /* Configured as GPIO with pull-up to ensure right MCC card mode */ | ||
948 | /* Switched to PB11_PF_SD_DAT3 if 4 bit bus is configured */ | ||
949 | imx_gpio_mode(GPIO_PORTB | GPIO_IN | GPIO_PUEN | 11); | ||
950 | /* imx_gpio_mode(PB11_PF_SD_DAT3); */ | ||
951 | imx_gpio_mode(PB12_PF_SD_CLK); | ||
952 | imx_gpio_mode(PB13_PF_SD_CMD); | ||
953 | |||
954 | imxmci_softreset(); | ||
955 | |||
956 | if ( MMC_REV_NO != 0x390 ) { | ||
957 | dev_err(mmc_dev(host->mmc), "wrong rev.no. 0x%08x. aborting.\n", | ||
958 | MMC_REV_NO); | ||
959 | goto out; | ||
960 | } | ||
961 | |||
962 | MMC_READ_TO = 0x2db4; /* recommended in data sheet */ | ||
963 | |||
964 | host->imask = IMXMCI_INT_MASK_DEFAULT; | ||
965 | MMC_INT_MASK = host->imask; | ||
966 | |||
967 | |||
968 | if(imx_dma_request_by_prio(&host->dma, DRIVER_NAME, DMA_PRIO_LOW)<0){ | ||
969 | dev_err(mmc_dev(host->mmc), "imx_dma_request_by_prio failed\n"); | ||
970 | ret = -EBUSY; | ||
971 | goto out; | ||
972 | } | ||
973 | host->dma_allocated=1; | ||
974 | imx_dma_setup_handlers(host->dma, imxmci_dma_irq, NULL, host); | ||
975 | |||
976 | tasklet_init(&host->tasklet, imxmci_tasklet_fnc, (unsigned long)host); | ||
977 | host->status_reg=0; | ||
978 | host->pending_events=0; | ||
979 | |||
980 | ret = request_irq(host->irq, imxmci_irq, 0, DRIVER_NAME, host); | ||
981 | if (ret) | ||
982 | goto out; | ||
983 | |||
984 | host->present = host->pdata->card_present(); | ||
985 | init_timer(&host->timer); | ||
986 | host->timer.data = (unsigned long)host; | ||
987 | host->timer.function = imxmci_check_status; | ||
988 | add_timer(&host->timer); | ||
989 | mod_timer(&host->timer, jiffies + (HZ>>1)); | ||
990 | |||
991 | platform_set_drvdata(pdev, mmc); | ||
992 | |||
993 | mmc_add_host(mmc); | ||
994 | |||
995 | return 0; | ||
996 | |||
997 | out: | ||
998 | if (host) { | ||
999 | if(host->dma_allocated){ | ||
1000 | imx_dma_free(host->dma); | ||
1001 | host->dma_allocated=0; | ||
1002 | } | ||
1003 | } | ||
1004 | if (mmc) | ||
1005 | mmc_free_host(mmc); | ||
1006 | release_resource(r); | ||
1007 | return ret; | ||
1008 | } | ||
1009 | |||
1010 | static int imxmci_remove(struct platform_device *pdev) | ||
1011 | { | ||
1012 | struct mmc_host *mmc = platform_get_drvdata(pdev); | ||
1013 | |||
1014 | platform_set_drvdata(pdev, NULL); | ||
1015 | |||
1016 | if (mmc) { | ||
1017 | struct imxmci_host *host = mmc_priv(mmc); | ||
1018 | |||
1019 | tasklet_disable(&host->tasklet); | ||
1020 | |||
1021 | del_timer_sync(&host->timer); | ||
1022 | mmc_remove_host(mmc); | ||
1023 | |||
1024 | free_irq(host->irq, host); | ||
1025 | if(host->dma_allocated){ | ||
1026 | imx_dma_free(host->dma); | ||
1027 | host->dma_allocated=0; | ||
1028 | } | ||
1029 | |||
1030 | tasklet_kill(&host->tasklet); | ||
1031 | |||
1032 | release_resource(host->res); | ||
1033 | |||
1034 | mmc_free_host(mmc); | ||
1035 | } | ||
1036 | return 0; | ||
1037 | } | ||
1038 | |||
1039 | #ifdef CONFIG_PM | ||
1040 | static int imxmci_suspend(struct platform_device *dev, pm_message_t state) | ||
1041 | { | ||
1042 | struct mmc_host *mmc = platform_get_drvdata(dev); | ||
1043 | int ret = 0; | ||
1044 | |||
1045 | if (mmc) | ||
1046 | ret = mmc_suspend_host(mmc, state); | ||
1047 | |||
1048 | return ret; | ||
1049 | } | ||
1050 | |||
1051 | static int imxmci_resume(struct platform_device *dev) | ||
1052 | { | ||
1053 | struct mmc_host *mmc = platform_get_drvdata(dev); | ||
1054 | struct imxmci_host *host; | ||
1055 | int ret = 0; | ||
1056 | |||
1057 | if (mmc) { | ||
1058 | host = mmc_priv(mmc); | ||
1059 | if(host) | ||
1060 | set_bit(IMXMCI_PEND_SET_INIT_b, &host->pending_events); | ||
1061 | ret = mmc_resume_host(mmc); | ||
1062 | } | ||
1063 | |||
1064 | return ret; | ||
1065 | } | ||
1066 | #else | ||
1067 | #define imxmci_suspend NULL | ||
1068 | #define imxmci_resume NULL | ||
1069 | #endif /* CONFIG_PM */ | ||
1070 | |||
1071 | static struct platform_driver imxmci_driver = { | ||
1072 | .probe = imxmci_probe, | ||
1073 | .remove = imxmci_remove, | ||
1074 | .suspend = imxmci_suspend, | ||
1075 | .resume = imxmci_resume, | ||
1076 | .driver = { | ||
1077 | .name = DRIVER_NAME, | ||
1078 | } | ||
1079 | }; | ||
1080 | |||
1081 | static int __init imxmci_init(void) | ||
1082 | { | ||
1083 | return platform_driver_register(&imxmci_driver); | ||
1084 | } | ||
1085 | |||
1086 | static void __exit imxmci_exit(void) | ||
1087 | { | ||
1088 | platform_driver_unregister(&imxmci_driver); | ||
1089 | } | ||
1090 | |||
1091 | module_init(imxmci_init); | ||
1092 | module_exit(imxmci_exit); | ||
1093 | |||
1094 | MODULE_DESCRIPTION("i.MX Multimedia Card Interface Driver"); | ||
1095 | MODULE_AUTHOR("Sascha Hauer, Pengutronix"); | ||
1096 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/mmc/imxmmc.h b/drivers/mmc/imxmmc.h new file mode 100644 index 000000000000..e5339e334dbb --- /dev/null +++ b/drivers/mmc/imxmmc.h | |||
@@ -0,0 +1,67 @@ | |||
1 | |||
2 | # define __REG16(x) (*((volatile u16 *)IO_ADDRESS(x))) | ||
3 | |||
4 | #define MMC_STR_STP_CLK __REG16(IMX_MMC_BASE + 0x00) | ||
5 | #define MMC_STATUS __REG16(IMX_MMC_BASE + 0x04) | ||
6 | #define MMC_CLK_RATE __REG16(IMX_MMC_BASE + 0x08) | ||
7 | #define MMC_CMD_DAT_CONT __REG16(IMX_MMC_BASE + 0x0C) | ||
8 | #define MMC_RES_TO __REG16(IMX_MMC_BASE + 0x10) | ||
9 | #define MMC_READ_TO __REG16(IMX_MMC_BASE + 0x14) | ||
10 | #define MMC_BLK_LEN __REG16(IMX_MMC_BASE + 0x18) | ||
11 | #define MMC_NOB __REG16(IMX_MMC_BASE + 0x1C) | ||
12 | #define MMC_REV_NO __REG16(IMX_MMC_BASE + 0x20) | ||
13 | #define MMC_INT_MASK __REG16(IMX_MMC_BASE + 0x24) | ||
14 | #define MMC_CMD __REG16(IMX_MMC_BASE + 0x28) | ||
15 | #define MMC_ARGH __REG16(IMX_MMC_BASE + 0x2C) | ||
16 | #define MMC_ARGL __REG16(IMX_MMC_BASE + 0x30) | ||
17 | #define MMC_RES_FIFO __REG16(IMX_MMC_BASE + 0x34) | ||
18 | #define MMC_BUFFER_ACCESS __REG16(IMX_MMC_BASE + 0x38) | ||
19 | #define MMC_BUFFER_ACCESS_OFS 0x38 | ||
20 | |||
21 | |||
22 | #define STR_STP_CLK_ENDIAN (1<<5) | ||
23 | #define STR_STP_CLK_RESET (1<<3) | ||
24 | #define STR_STP_CLK_ENABLE (1<<2) | ||
25 | #define STR_STP_CLK_START_CLK (1<<1) | ||
26 | #define STR_STP_CLK_STOP_CLK (1<<0) | ||
27 | #define STATUS_CARD_PRESENCE (1<<15) | ||
28 | #define STATUS_SDIO_INT_ACTIVE (1<<14) | ||
29 | #define STATUS_END_CMD_RESP (1<<13) | ||
30 | #define STATUS_WRITE_OP_DONE (1<<12) | ||
31 | #define STATUS_DATA_TRANS_DONE (1<<11) | ||
32 | #define STATUS_WR_CRC_ERROR_CODE_MASK (3<<10) | ||
33 | #define STATUS_CARD_BUS_CLK_RUN (1<<8) | ||
34 | #define STATUS_APPL_BUFF_FF (1<<7) | ||
35 | #define STATUS_APPL_BUFF_FE (1<<6) | ||
36 | #define STATUS_RESP_CRC_ERR (1<<5) | ||
37 | #define STATUS_CRC_READ_ERR (1<<3) | ||
38 | #define STATUS_CRC_WRITE_ERR (1<<2) | ||
39 | #define STATUS_TIME_OUT_RESP (1<<1) | ||
40 | #define STATUS_TIME_OUT_READ (1<<0) | ||
41 | #define STATUS_ERR_MASK 0x2f | ||
42 | #define CLK_RATE_PRESCALER(x) ((x) & 0x7) | ||
43 | #define CLK_RATE_CLK_RATE(x) (((x) & 0x7) << 3) | ||
44 | #define CMD_DAT_CONT_CMD_RESP_LONG_OFF (1<<12) | ||
45 | #define CMD_DAT_CONT_STOP_READWAIT (1<<11) | ||
46 | #define CMD_DAT_CONT_START_READWAIT (1<<10) | ||
47 | #define CMD_DAT_CONT_BUS_WIDTH_1 (0<<8) | ||
48 | #define CMD_DAT_CONT_BUS_WIDTH_4 (2<<8) | ||
49 | #define CMD_DAT_CONT_INIT (1<<7) | ||
50 | #define CMD_DAT_CONT_BUSY (1<<6) | ||
51 | #define CMD_DAT_CONT_STREAM_BLOCK (1<<5) | ||
52 | #define CMD_DAT_CONT_WRITE (1<<4) | ||
53 | #define CMD_DAT_CONT_DATA_ENABLE (1<<3) | ||
54 | #define CMD_DAT_CONT_RESPONSE_FORMAT_R1 (1) | ||
55 | #define CMD_DAT_CONT_RESPONSE_FORMAT_R2 (2) | ||
56 | #define CMD_DAT_CONT_RESPONSE_FORMAT_R3 (3) | ||
57 | #define CMD_DAT_CONT_RESPONSE_FORMAT_R4 (4) | ||
58 | #define CMD_DAT_CONT_RESPONSE_FORMAT_R5 (5) | ||
59 | #define CMD_DAT_CONT_RESPONSE_FORMAT_R6 (6) | ||
60 | #define INT_MASK_AUTO_CARD_DETECT (1<<6) | ||
61 | #define INT_MASK_DAT0_EN (1<<5) | ||
62 | #define INT_MASK_SDIO (1<<4) | ||
63 | #define INT_MASK_BUF_READY (1<<3) | ||
64 | #define INT_MASK_END_CMD_RES (1<<2) | ||
65 | #define INT_MASK_WRITE_OP_DONE (1<<1) | ||
66 | #define INT_MASK_DATA_TRAN (1<<0) | ||
67 | #define INT_ALL (0x7f) | ||
diff --git a/drivers/mtd/chips/Kconfig b/drivers/mtd/chips/Kconfig index 0f6bb2e625d8..a7ec5954caf5 100644 --- a/drivers/mtd/chips/Kconfig +++ b/drivers/mtd/chips/Kconfig | |||
@@ -200,27 +200,6 @@ config MTD_CFI_AMDSTD | |||
200 | provides support for one of those command sets, used on chips | 200 | provides support for one of those command sets, used on chips |
201 | including the AMD Am29LV320. | 201 | including the AMD Am29LV320. |
202 | 202 | ||
203 | config MTD_CFI_AMDSTD_RETRY | ||
204 | int "Retry failed commands (erase/program)" | ||
205 | depends on MTD_CFI_AMDSTD | ||
206 | default "0" | ||
207 | help | ||
208 | Some chips, when attached to a shared bus, don't properly filter | ||
209 | bus traffic that is destined to other devices. This broken | ||
210 | behavior causes erase and program sequences to be aborted when | ||
211 | the sequences are mixed with traffic for other devices. | ||
212 | |||
213 | SST49LF040 (and related) chips are know to be broken. | ||
214 | |||
215 | config MTD_CFI_AMDSTD_RETRY_MAX | ||
216 | int "Max retries of failed commands (erase/program)" | ||
217 | depends on MTD_CFI_AMDSTD_RETRY | ||
218 | default "0" | ||
219 | help | ||
220 | If you have an SST49LF040 (or related chip) then this value should | ||
221 | be set to at least 1. This can also be adjusted at driver load | ||
222 | time with the retry_cmd_max module parameter. | ||
223 | |||
224 | config MTD_CFI_STAA | 203 | config MTD_CFI_STAA |
225 | tristate "Support for ST (Advanced Architecture) flash chips" | 204 | tristate "Support for ST (Advanced Architecture) flash chips" |
226 | depends on MTD_GEN_PROBE | 205 | depends on MTD_GEN_PROBE |
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c index ce99845d8266..066e22b01a94 100644 --- a/drivers/net/8139cp.c +++ b/drivers/net/8139cp.c | |||
@@ -539,8 +539,7 @@ rx_status_loop: | |||
539 | unsigned buflen; | 539 | unsigned buflen; |
540 | 540 | ||
541 | skb = cp->rx_skb[rx_tail].skb; | 541 | skb = cp->rx_skb[rx_tail].skb; |
542 | if (!skb) | 542 | BUG_ON(!skb); |
543 | BUG(); | ||
544 | 543 | ||
545 | desc = &cp->rx_ring[rx_tail]; | 544 | desc = &cp->rx_ring[rx_tail]; |
546 | status = le32_to_cpu(desc->opts1); | 545 | status = le32_to_cpu(desc->opts1); |
@@ -723,8 +722,7 @@ static void cp_tx (struct cp_private *cp) | |||
723 | break; | 722 | break; |
724 | 723 | ||
725 | skb = cp->tx_skb[tx_tail].skb; | 724 | skb = cp->tx_skb[tx_tail].skb; |
726 | if (!skb) | 725 | BUG_ON(!skb); |
727 | BUG(); | ||
728 | 726 | ||
729 | pci_unmap_single(cp->pdev, cp->tx_skb[tx_tail].mapping, | 727 | pci_unmap_single(cp->pdev, cp->tx_skb[tx_tail].mapping, |
730 | cp->tx_skb[tx_tail].len, PCI_DMA_TODEVICE); | 728 | cp->tx_skb[tx_tail].len, PCI_DMA_TODEVICE); |
@@ -1550,8 +1548,7 @@ static void cp_get_ethtool_stats (struct net_device *dev, | |||
1550 | tmp_stats[i++] = le16_to_cpu(nic_stats->tx_abort); | 1548 | tmp_stats[i++] = le16_to_cpu(nic_stats->tx_abort); |
1551 | tmp_stats[i++] = le16_to_cpu(nic_stats->tx_underrun); | 1549 | tmp_stats[i++] = le16_to_cpu(nic_stats->tx_underrun); |
1552 | tmp_stats[i++] = cp->cp_stats.rx_frags; | 1550 | tmp_stats[i++] = cp->cp_stats.rx_frags; |
1553 | if (i != CP_NUM_STATS) | 1551 | BUG_ON(i != CP_NUM_STATS); |
1554 | BUG(); | ||
1555 | 1552 | ||
1556 | pci_free_consistent(cp->pdev, sizeof(*nic_stats), nic_stats, dma); | 1553 | pci_free_consistent(cp->pdev, sizeof(*nic_stats), nic_stats, dma); |
1557 | } | 1554 | } |
@@ -1856,8 +1853,7 @@ static void cp_remove_one (struct pci_dev *pdev) | |||
1856 | struct net_device *dev = pci_get_drvdata(pdev); | 1853 | struct net_device *dev = pci_get_drvdata(pdev); |
1857 | struct cp_private *cp = netdev_priv(dev); | 1854 | struct cp_private *cp = netdev_priv(dev); |
1858 | 1855 | ||
1859 | if (!dev) | 1856 | BUG_ON(!dev); |
1860 | BUG(); | ||
1861 | unregister_netdev(dev); | 1857 | unregister_netdev(dev); |
1862 | iounmap(cp->regs); | 1858 | iounmap(cp->regs); |
1863 | if (cp->wol_enabled) pci_set_power_state (pdev, PCI_D0); | 1859 | if (cp->wol_enabled) pci_set_power_state (pdev, PCI_D0); |
diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c index 64e2caf3083d..fabc0607b0f1 100644 --- a/drivers/net/arcnet/arcnet.c +++ b/drivers/net/arcnet/arcnet.c | |||
@@ -765,8 +765,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
765 | BUGMSG(D_DURING, "in arcnet_interrupt\n"); | 765 | BUGMSG(D_DURING, "in arcnet_interrupt\n"); |
766 | 766 | ||
767 | lp = dev->priv; | 767 | lp = dev->priv; |
768 | if (!lp) | 768 | BUG_ON(!lp); |
769 | BUG(); | ||
770 | 769 | ||
771 | spin_lock(&lp->lock); | 770 | spin_lock(&lp->lock); |
772 | 771 | ||
diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 15032f2c7817..c4e12b5cbb92 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c | |||
@@ -608,8 +608,7 @@ static void b44_tx(struct b44 *bp) | |||
608 | struct ring_info *rp = &bp->tx_buffers[cons]; | 608 | struct ring_info *rp = &bp->tx_buffers[cons]; |
609 | struct sk_buff *skb = rp->skb; | 609 | struct sk_buff *skb = rp->skb; |
610 | 610 | ||
611 | if (unlikely(skb == NULL)) | 611 | BUG_ON(skb == NULL); |
612 | BUG(); | ||
613 | 612 | ||
614 | pci_unmap_single(bp->pdev, | 613 | pci_unmap_single(bp->pdev, |
615 | pci_unmap_addr(rp, mapping), | 614 | pci_unmap_addr(rp, mapping), |
diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c index 30ff8ea1a402..4391bf4bf573 100644 --- a/drivers/net/chelsio/sge.c +++ b/drivers/net/chelsio/sge.c | |||
@@ -1093,8 +1093,7 @@ static int process_responses(struct adapter *adapter, int budget) | |||
1093 | if (likely(e->DataValid)) { | 1093 | if (likely(e->DataValid)) { |
1094 | struct freelQ *fl = &sge->freelQ[e->FreelistQid]; | 1094 | struct freelQ *fl = &sge->freelQ[e->FreelistQid]; |
1095 | 1095 | ||
1096 | if (unlikely(!e->Sop || !e->Eop)) | 1096 | BUG_ON(!e->Sop || !e->Eop); |
1097 | BUG(); | ||
1098 | if (unlikely(e->Offload)) | 1097 | if (unlikely(e->Offload)) |
1099 | unexpected_offload(adapter, fl); | 1098 | unexpected_offload(adapter, fl); |
1100 | else | 1099 | else |
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 49cd096a3c3d..add8dc4aa7b0 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c | |||
@@ -3308,8 +3308,7 @@ e1000_clean(struct net_device *poll_dev, int *budget) | |||
3308 | 3308 | ||
3309 | while (poll_dev != &adapter->polling_netdev[i]) { | 3309 | while (poll_dev != &adapter->polling_netdev[i]) { |
3310 | i++; | 3310 | i++; |
3311 | if (unlikely(i == adapter->num_rx_queues)) | 3311 | BUG_ON(i == adapter->num_rx_queues); |
3312 | BUG(); | ||
3313 | } | 3312 | } |
3314 | 3313 | ||
3315 | if (likely(adapter->num_tx_queues == 1)) { | 3314 | if (likely(adapter->num_tx_queues == 1)) { |
diff --git a/drivers/net/eql.c b/drivers/net/eql.c index aa1569182fd6..815436c6170f 100644 --- a/drivers/net/eql.c +++ b/drivers/net/eql.c | |||
@@ -203,8 +203,7 @@ static int eql_open(struct net_device *dev) | |||
203 | printk(KERN_INFO "%s: remember to turn off Van-Jacobson compression on " | 203 | printk(KERN_INFO "%s: remember to turn off Van-Jacobson compression on " |
204 | "your slave devices.\n", dev->name); | 204 | "your slave devices.\n", dev->name); |
205 | 205 | ||
206 | if (!list_empty(&eql->queue.all_slaves)) | 206 | BUG_ON(!list_empty(&eql->queue.all_slaves)); |
207 | BUG(); | ||
208 | 207 | ||
209 | eql->min_slaves = 1; | 208 | eql->min_slaves = 1; |
210 | eql->max_slaves = EQL_DEFAULT_MAX_SLAVES; /* 4 usually... */ | 209 | eql->max_slaves = EQL_DEFAULT_MAX_SLAVES; /* 4 usually... */ |
diff --git a/drivers/net/irda/sa1100_ir.c b/drivers/net/irda/sa1100_ir.c index 63d38fbbd04e..f530686bd09f 100644 --- a/drivers/net/irda/sa1100_ir.c +++ b/drivers/net/irda/sa1100_ir.c | |||
@@ -695,8 +695,7 @@ static int sa1100_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev) | |||
695 | /* | 695 | /* |
696 | * We must not be transmitting... | 696 | * We must not be transmitting... |
697 | */ | 697 | */ |
698 | if (si->txskb) | 698 | BUG_ON(si->txskb); |
699 | BUG(); | ||
700 | 699 | ||
701 | netif_stop_queue(dev); | 700 | netif_stop_queue(dev); |
702 | 701 | ||
diff --git a/drivers/net/ne2k-pci.c b/drivers/net/ne2k-pci.c index d11821dd86ed..ced9fdb8335c 100644 --- a/drivers/net/ne2k-pci.c +++ b/drivers/net/ne2k-pci.c | |||
@@ -645,9 +645,7 @@ static void __devexit ne2k_pci_remove_one (struct pci_dev *pdev) | |||
645 | { | 645 | { |
646 | struct net_device *dev = pci_get_drvdata(pdev); | 646 | struct net_device *dev = pci_get_drvdata(pdev); |
647 | 647 | ||
648 | if (!dev) | 648 | BUG_ON(!dev); |
649 | BUG(); | ||
650 | |||
651 | unregister_netdev(dev); | 649 | unregister_netdev(dev); |
652 | release_region(dev->base_addr, NE_IO_EXTENT); | 650 | release_region(dev->base_addr, NE_IO_EXTENT); |
653 | free_netdev(dev); | 651 | free_netdev(dev); |
diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c index 8e9b1a537dee..706aed7d717f 100644 --- a/drivers/net/ns83820.c +++ b/drivers/net/ns83820.c | |||
@@ -568,8 +568,7 @@ static inline int ns83820_add_rx_skb(struct ns83820 *dev, struct sk_buff *skb) | |||
568 | #endif | 568 | #endif |
569 | 569 | ||
570 | sg = dev->rx_info.descs + (next_empty * DESC_SIZE); | 570 | sg = dev->rx_info.descs + (next_empty * DESC_SIZE); |
571 | if (unlikely(NULL != dev->rx_info.skbs[next_empty])) | 571 | BUG_ON(NULL != dev->rx_info.skbs[next_empty]); |
572 | BUG(); | ||
573 | dev->rx_info.skbs[next_empty] = skb; | 572 | dev->rx_info.skbs[next_empty] = skb; |
574 | 573 | ||
575 | dev->rx_info.next_empty = (next_empty + 1) % NR_RX_DESC; | 574 | dev->rx_info.next_empty = (next_empty + 1) % NR_RX_DESC; |
diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c index 35b18057fbdd..45ad036733e2 100644 --- a/drivers/net/starfire.c +++ b/drivers/net/starfire.c | |||
@@ -2122,8 +2122,7 @@ static void __devexit starfire_remove_one (struct pci_dev *pdev) | |||
2122 | struct net_device *dev = pci_get_drvdata(pdev); | 2122 | struct net_device *dev = pci_get_drvdata(pdev); |
2123 | struct netdev_private *np = netdev_priv(dev); | 2123 | struct netdev_private *np = netdev_priv(dev); |
2124 | 2124 | ||
2125 | if (!dev) | 2125 | BUG_ON(!dev); |
2126 | BUG(); | ||
2127 | 2126 | ||
2128 | unregister_netdev(dev); | 2127 | unregister_netdev(dev); |
2129 | 2128 | ||
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 770e6b6cec60..0b5358072172 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
@@ -2959,9 +2959,7 @@ static void tg3_tx(struct tg3 *tp) | |||
2959 | struct sk_buff *skb = ri->skb; | 2959 | struct sk_buff *skb = ri->skb; |
2960 | int i; | 2960 | int i; |
2961 | 2961 | ||
2962 | if (unlikely(skb == NULL)) | 2962 | BUG_ON(skb == NULL); |
2963 | BUG(); | ||
2964 | |||
2965 | pci_unmap_single(tp->pdev, | 2963 | pci_unmap_single(tp->pdev, |
2966 | pci_unmap_addr(ri, mapping), | 2964 | pci_unmap_addr(ri, mapping), |
2967 | skb_headlen(skb), | 2965 | skb_headlen(skb), |
@@ -2972,12 +2970,10 @@ static void tg3_tx(struct tg3 *tp) | |||
2972 | sw_idx = NEXT_TX(sw_idx); | 2970 | sw_idx = NEXT_TX(sw_idx); |
2973 | 2971 | ||
2974 | for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { | 2972 | for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { |
2975 | if (unlikely(sw_idx == hw_idx)) | 2973 | BUG_ON(sw_idx == hw_idx); |
2976 | BUG(); | ||
2977 | 2974 | ||
2978 | ri = &tp->tx_buffers[sw_idx]; | 2975 | ri = &tp->tx_buffers[sw_idx]; |
2979 | if (unlikely(ri->skb != NULL)) | 2976 | BUG_ON(ri->skb != NULL); |
2980 | BUG(); | ||
2981 | 2977 | ||
2982 | pci_unmap_page(tp->pdev, | 2978 | pci_unmap_page(tp->pdev, |
2983 | pci_unmap_addr(ri, mapping), | 2979 | pci_unmap_addr(ri, mapping), |
@@ -4928,9 +4924,8 @@ static int tg3_halt_cpu(struct tg3 *tp, u32 offset) | |||
4928 | { | 4924 | { |
4929 | int i; | 4925 | int i; |
4930 | 4926 | ||
4931 | if (offset == TX_CPU_BASE && | 4927 | BUG_ON(offset == TX_CPU_BASE && |
4932 | (tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) | 4928 | (tp->tg3_flags2 & TG3_FLG2_5705_PLUS)); |
4933 | BUG(); | ||
4934 | 4929 | ||
4935 | if (offset == RX_CPU_BASE) { | 4930 | if (offset == RX_CPU_BASE) { |
4936 | for (i = 0; i < 10000; i++) { | 4931 | for (i = 0; i < 10000; i++) { |
diff --git a/drivers/net/tokenring/abyss.c b/drivers/net/tokenring/abyss.c index 9345e68c451e..649d8ea354f5 100644 --- a/drivers/net/tokenring/abyss.c +++ b/drivers/net/tokenring/abyss.c | |||
@@ -438,8 +438,7 @@ static void __devexit abyss_detach (struct pci_dev *pdev) | |||
438 | { | 438 | { |
439 | struct net_device *dev = pci_get_drvdata(pdev); | 439 | struct net_device *dev = pci_get_drvdata(pdev); |
440 | 440 | ||
441 | if (!dev) | 441 | BUG_ON(!dev); |
442 | BUG(); | ||
443 | unregister_netdev(dev); | 442 | unregister_netdev(dev); |
444 | release_region(dev->base_addr-0x10, ABYSS_IO_EXTENT); | 443 | release_region(dev->base_addr-0x10, ABYSS_IO_EXTENT); |
445 | free_irq(dev->irq, dev); | 444 | free_irq(dev->irq, dev); |
diff --git a/drivers/net/tokenring/madgemc.c b/drivers/net/tokenring/madgemc.c index 3a25d191ea4a..19e6f4dfd69c 100644 --- a/drivers/net/tokenring/madgemc.c +++ b/drivers/net/tokenring/madgemc.c | |||
@@ -735,8 +735,7 @@ static int __devexit madgemc_remove(struct device *device) | |||
735 | struct net_local *tp; | 735 | struct net_local *tp; |
736 | struct card_info *card; | 736 | struct card_info *card; |
737 | 737 | ||
738 | if (!dev) | 738 | BUG_ON(!dev); |
739 | BUG(); | ||
740 | 739 | ||
741 | tp = dev->priv; | 740 | tp = dev->priv; |
742 | card = tp->tmspriv; | 741 | card = tp->tmspriv; |
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 9dce522526c5..bca89cff85a6 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c | |||
@@ -5573,8 +5573,7 @@ static void ipw_adhoc_create(struct ipw_priv *priv, | |||
5573 | case IEEE80211_52GHZ_BAND: | 5573 | case IEEE80211_52GHZ_BAND: |
5574 | network->mode = IEEE_A; | 5574 | network->mode = IEEE_A; |
5575 | i = ieee80211_channel_to_index(priv->ieee, priv->channel); | 5575 | i = ieee80211_channel_to_index(priv->ieee, priv->channel); |
5576 | if (i == -1) | 5576 | BUG_ON(i == -1); |
5577 | BUG(); | ||
5578 | if (geo->a[i].flags & IEEE80211_CH_PASSIVE_ONLY) { | 5577 | if (geo->a[i].flags & IEEE80211_CH_PASSIVE_ONLY) { |
5579 | IPW_WARNING("Overriding invalid channel\n"); | 5578 | IPW_WARNING("Overriding invalid channel\n"); |
5580 | priv->channel = geo->a[0].channel; | 5579 | priv->channel = geo->a[0].channel; |
@@ -5587,8 +5586,7 @@ static void ipw_adhoc_create(struct ipw_priv *priv, | |||
5587 | else | 5586 | else |
5588 | network->mode = IEEE_B; | 5587 | network->mode = IEEE_B; |
5589 | i = ieee80211_channel_to_index(priv->ieee, priv->channel); | 5588 | i = ieee80211_channel_to_index(priv->ieee, priv->channel); |
5590 | if (i == -1) | 5589 | BUG_ON(i == -1); |
5591 | BUG(); | ||
5592 | if (geo->bg[i].flags & IEEE80211_CH_PASSIVE_ONLY) { | 5590 | if (geo->bg[i].flags & IEEE80211_CH_PASSIVE_ONLY) { |
5593 | IPW_WARNING("Overriding invalid channel\n"); | 5591 | IPW_WARNING("Overriding invalid channel\n"); |
5594 | priv->channel = geo->bg[0].channel; | 5592 | priv->channel = geo->bg[0].channel; |
@@ -6715,8 +6713,7 @@ static int ipw_qos_association(struct ipw_priv *priv, | |||
6715 | 6713 | ||
6716 | switch (priv->ieee->iw_mode) { | 6714 | switch (priv->ieee->iw_mode) { |
6717 | case IW_MODE_ADHOC: | 6715 | case IW_MODE_ADHOC: |
6718 | if (!(network->capability & WLAN_CAPABILITY_IBSS)) | 6716 | BUG_ON(!(network->capability & WLAN_CAPABILITY_IBSS)); |
6719 | BUG(); | ||
6720 | 6717 | ||
6721 | qos_data = &ibss_data; | 6718 | qos_data = &ibss_data; |
6722 | break; | 6719 | break; |
diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c index 75d56bfef0ee..fd0f43b7db5b 100644 --- a/drivers/net/yellowfin.c +++ b/drivers/net/yellowfin.c | |||
@@ -1441,8 +1441,7 @@ static void __devexit yellowfin_remove_one (struct pci_dev *pdev) | |||
1441 | struct net_device *dev = pci_get_drvdata(pdev); | 1441 | struct net_device *dev = pci_get_drvdata(pdev); |
1442 | struct yellowfin_private *np; | 1442 | struct yellowfin_private *np; |
1443 | 1443 | ||
1444 | if (!dev) | 1444 | BUG_ON(!dev); |
1445 | BUG(); | ||
1446 | np = netdev_priv(dev); | 1445 | np = netdev_priv(dev); |
1447 | 1446 | ||
1448 | pci_free_consistent(pdev, STATUS_TOTAL_SIZE, np->tx_status, | 1447 | pci_free_consistent(pdev, STATUS_TOTAL_SIZE, np->tx_status, |
diff --git a/drivers/s390/block/dasd_erp.c b/drivers/s390/block/dasd_erp.c index 8fd71ab02ef0..b842377cb0c6 100644 --- a/drivers/s390/block/dasd_erp.c +++ b/drivers/s390/block/dasd_erp.c | |||
@@ -32,9 +32,8 @@ dasd_alloc_erp_request(char *magic, int cplength, int datasize, | |||
32 | int size; | 32 | int size; |
33 | 33 | ||
34 | /* Sanity checks */ | 34 | /* Sanity checks */ |
35 | if ( magic == NULL || datasize > PAGE_SIZE || | 35 | BUG_ON( magic == NULL || datasize > PAGE_SIZE || |
36 | (cplength*sizeof(struct ccw1)) > PAGE_SIZE) | 36 | (cplength*sizeof(struct ccw1)) > PAGE_SIZE); |
37 | BUG(); | ||
38 | 37 | ||
39 | size = (sizeof(struct dasd_ccw_req) + 7L) & -8L; | 38 | size = (sizeof(struct dasd_ccw_req) + 7L) & -8L; |
40 | if (cplength > 0) | 39 | if (cplength > 0) |
@@ -125,8 +124,7 @@ dasd_default_erp_postaction(struct dasd_ccw_req * cqr) | |||
125 | struct dasd_device *device; | 124 | struct dasd_device *device; |
126 | int success; | 125 | int success; |
127 | 126 | ||
128 | if (cqr->refers == NULL || cqr->function == NULL) | 127 | BUG_ON(cqr->refers == NULL || cqr->function == NULL); |
129 | BUG(); | ||
130 | 128 | ||
131 | device = cqr->device; | 129 | device = cqr->device; |
132 | success = cqr->status == DASD_CQR_DONE; | 130 | success = cqr->status == DASD_CQR_DONE; |
diff --git a/drivers/s390/char/sclp_rw.c b/drivers/s390/char/sclp_rw.c index ac10dfb20a62..91e93c78f57a 100644 --- a/drivers/s390/char/sclp_rw.c +++ b/drivers/s390/char/sclp_rw.c | |||
@@ -24,7 +24,7 @@ | |||
24 | 24 | ||
25 | /* | 25 | /* |
26 | * The room for the SCCB (only for writing) is not equal to a pages size | 26 | * The room for the SCCB (only for writing) is not equal to a pages size |
27 | * (as it is specified as the maximum size in the the SCLP ducumentation) | 27 | * (as it is specified as the maximum size in the the SCLP documentation) |
28 | * because of the additional data structure described above. | 28 | * because of the additional data structure described above. |
29 | */ | 29 | */ |
30 | #define MAX_SCCB_ROOM (PAGE_SIZE - sizeof(struct sclp_buffer)) | 30 | #define MAX_SCCB_ROOM (PAGE_SIZE - sizeof(struct sclp_buffer)) |
diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c index 5ced2725d6c7..5c65cf3e5cc0 100644 --- a/drivers/s390/char/tape_block.c +++ b/drivers/s390/char/tape_block.c | |||
@@ -198,9 +198,7 @@ tapeblock_request_fn(request_queue_t *queue) | |||
198 | 198 | ||
199 | device = (struct tape_device *) queue->queuedata; | 199 | device = (struct tape_device *) queue->queuedata; |
200 | DBF_LH(6, "tapeblock_request_fn(device=%p)\n", device); | 200 | DBF_LH(6, "tapeblock_request_fn(device=%p)\n", device); |
201 | if (device == NULL) | 201 | BUG_ON(device == NULL); |
202 | BUG(); | ||
203 | |||
204 | tapeblock_trigger_requeue(device); | 202 | tapeblock_trigger_requeue(device); |
205 | } | 203 | } |
206 | 204 | ||
@@ -307,8 +305,7 @@ tapeblock_revalidate_disk(struct gendisk *disk) | |||
307 | int rc; | 305 | int rc; |
308 | 306 | ||
309 | device = (struct tape_device *) disk->private_data; | 307 | device = (struct tape_device *) disk->private_data; |
310 | if (!device) | 308 | BUG_ON(!device); |
311 | BUG(); | ||
312 | 309 | ||
313 | if (!device->blk_data.medium_changed) | 310 | if (!device->blk_data.medium_changed) |
314 | return 0; | 311 | return 0; |
@@ -440,11 +437,9 @@ tapeblock_ioctl( | |||
440 | 437 | ||
441 | rc = 0; | 438 | rc = 0; |
442 | disk = inode->i_bdev->bd_disk; | 439 | disk = inode->i_bdev->bd_disk; |
443 | if (!disk) | 440 | BUG_ON(!disk); |
444 | BUG(); | ||
445 | device = disk->private_data; | 441 | device = disk->private_data; |
446 | if (!device) | 442 | BUG_ON(!device); |
447 | BUG(); | ||
448 | minor = iminor(inode); | 443 | minor = iminor(inode); |
449 | 444 | ||
450 | DBF_LH(6, "tapeblock_ioctl(0x%0x)\n", command); | 445 | DBF_LH(6, "tapeblock_ioctl(0x%0x)\n", command); |
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c index edcf05d5d568..5d6b7a57b02f 100644 --- a/drivers/s390/net/lcs.c +++ b/drivers/s390/net/lcs.c | |||
@@ -675,9 +675,8 @@ lcs_ready_buffer(struct lcs_channel *channel, struct lcs_buffer *buffer) | |||
675 | int index, rc; | 675 | int index, rc; |
676 | 676 | ||
677 | LCS_DBF_TEXT(5, trace, "rdybuff"); | 677 | LCS_DBF_TEXT(5, trace, "rdybuff"); |
678 | if (buffer->state != BUF_STATE_LOCKED && | 678 | BUG_ON(buffer->state != BUF_STATE_LOCKED && |
679 | buffer->state != BUF_STATE_PROCESSED) | 679 | buffer->state != BUF_STATE_PROCESSED); |
680 | BUG(); | ||
681 | spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags); | 680 | spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags); |
682 | buffer->state = BUF_STATE_READY; | 681 | buffer->state = BUF_STATE_READY; |
683 | index = buffer - channel->iob; | 682 | index = buffer - channel->iob; |
@@ -701,8 +700,7 @@ __lcs_processed_buffer(struct lcs_channel *channel, struct lcs_buffer *buffer) | |||
701 | int index, prev, next; | 700 | int index, prev, next; |
702 | 701 | ||
703 | LCS_DBF_TEXT(5, trace, "prcsbuff"); | 702 | LCS_DBF_TEXT(5, trace, "prcsbuff"); |
704 | if (buffer->state != BUF_STATE_READY) | 703 | BUG_ON(buffer->state != BUF_STATE_READY); |
705 | BUG(); | ||
706 | buffer->state = BUF_STATE_PROCESSED; | 704 | buffer->state = BUF_STATE_PROCESSED; |
707 | index = buffer - channel->iob; | 705 | index = buffer - channel->iob; |
708 | prev = (index - 1) & (LCS_NUM_BUFFS - 1); | 706 | prev = (index - 1) & (LCS_NUM_BUFFS - 1); |
@@ -734,9 +732,8 @@ lcs_release_buffer(struct lcs_channel *channel, struct lcs_buffer *buffer) | |||
734 | unsigned long flags; | 732 | unsigned long flags; |
735 | 733 | ||
736 | LCS_DBF_TEXT(5, trace, "relbuff"); | 734 | LCS_DBF_TEXT(5, trace, "relbuff"); |
737 | if (buffer->state != BUF_STATE_LOCKED && | 735 | BUG_ON(buffer->state != BUF_STATE_LOCKED && |
738 | buffer->state != BUF_STATE_PROCESSED) | 736 | buffer->state != BUF_STATE_PROCESSED); |
739 | BUG(); | ||
740 | spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags); | 737 | spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags); |
741 | buffer->state = BUF_STATE_EMPTY; | 738 | buffer->state = BUF_STATE_EMPTY; |
742 | spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags); | 739 | spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags); |
diff --git a/drivers/scsi/aic7xxx/Kconfig.aic7xxx b/drivers/scsi/aic7xxx/Kconfig.aic7xxx index 6c2c395554ff..5517da5855f0 100644 --- a/drivers/scsi/aic7xxx/Kconfig.aic7xxx +++ b/drivers/scsi/aic7xxx/Kconfig.aic7xxx | |||
@@ -86,7 +86,7 @@ config AIC7XXX_DEBUG_MASK | |||
86 | default "0" | 86 | default "0" |
87 | help | 87 | help |
88 | Bit mask of debug options that is only valid if the | 88 | Bit mask of debug options that is only valid if the |
89 | CONFIG_AIC7XXX_DEBUG_ENBLE option is enabled. The bits in this mask | 89 | CONFIG_AIC7XXX_DEBUG_ENABLE option is enabled. The bits in this mask |
90 | are defined in the drivers/scsi/aic7xxx/aic7xxx.h - search for the | 90 | are defined in the drivers/scsi/aic7xxx/aic7xxx.h - search for the |
91 | variable ahc_debug in that file to find them. | 91 | variable ahc_debug in that file to find them. |
92 | 92 | ||
diff --git a/drivers/serial/jsm/jsm.h b/drivers/serial/jsm/jsm.h index dfc1e86d3aa1..043f50b1d10c 100644 --- a/drivers/serial/jsm/jsm.h +++ b/drivers/serial/jsm/jsm.h | |||
@@ -20,7 +20,7 @@ | |||
20 | * | 20 | * |
21 | * Contact Information: | 21 | * Contact Information: |
22 | * Scott H Kilau <Scott_Kilau@digi.com> | 22 | * Scott H Kilau <Scott_Kilau@digi.com> |
23 | * Wendy Xiong <wendyx@us.ltcfwd.linux.ibm.com> | 23 | * Wendy Xiong <wendyx@us.ibm.com> |
24 | * | 24 | * |
25 | ***********************************************************************/ | 25 | ***********************************************************************/ |
26 | 26 | ||
diff --git a/drivers/serial/jsm/jsm_driver.c b/drivers/serial/jsm/jsm_driver.c index b1b66e71d281..b3e1f71be4da 100644 --- a/drivers/serial/jsm/jsm_driver.c +++ b/drivers/serial/jsm/jsm_driver.c | |||
@@ -20,7 +20,7 @@ | |||
20 | * | 20 | * |
21 | * Contact Information: | 21 | * Contact Information: |
22 | * Scott H Kilau <Scott_Kilau@digi.com> | 22 | * Scott H Kilau <Scott_Kilau@digi.com> |
23 | * Wendy Xiong <wendyx@us.ltcfwd.linux.ibm.com> | 23 | * Wendy Xiong <wendyx@us.ibm.com> |
24 | * | 24 | * |
25 | * | 25 | * |
26 | ***********************************************************************/ | 26 | ***********************************************************************/ |
diff --git a/drivers/serial/jsm/jsm_neo.c b/drivers/serial/jsm/jsm_neo.c index 87e4e2cf8ce7..a5fc589d6ef5 100644 --- a/drivers/serial/jsm/jsm_neo.c +++ b/drivers/serial/jsm/jsm_neo.c | |||
@@ -20,7 +20,7 @@ | |||
20 | * | 20 | * |
21 | * Contact Information: | 21 | * Contact Information: |
22 | * Scott H Kilau <Scott_Kilau@digi.com> | 22 | * Scott H Kilau <Scott_Kilau@digi.com> |
23 | * Wendy Xiong <wendyx@us.ltcfwd.linux.ibm.com> | 23 | * Wendy Xiong <wendyx@us.ibm.com> |
24 | * | 24 | * |
25 | ***********************************************************************/ | 25 | ***********************************************************************/ |
26 | #include <linux/delay.h> /* For udelay */ | 26 | #include <linux/delay.h> /* For udelay */ |
diff --git a/fs/direct-io.c b/fs/direct-io.c index 910a8ed74b5d..b05d1b218776 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c | |||
@@ -929,8 +929,7 @@ do_holes: | |||
929 | block_in_page += this_chunk_blocks; | 929 | block_in_page += this_chunk_blocks; |
930 | dio->blocks_available -= this_chunk_blocks; | 930 | dio->blocks_available -= this_chunk_blocks; |
931 | next_block: | 931 | next_block: |
932 | if (dio->block_in_file > dio->final_block_in_request) | 932 | BUG_ON(dio->block_in_file > dio->final_block_in_request); |
933 | BUG(); | ||
934 | if (dio->block_in_file == dio->final_block_in_request) | 933 | if (dio->block_in_file == dio->final_block_in_request) |
935 | break; | 934 | break; |
936 | } | 935 | } |
diff --git a/fs/dquot.c b/fs/dquot.c index 6b3886920939..81d87a413c68 100644 --- a/fs/dquot.c +++ b/fs/dquot.c | |||
@@ -590,8 +590,7 @@ we_slept: | |||
590 | atomic_dec(&dquot->dq_count); | 590 | atomic_dec(&dquot->dq_count); |
591 | #ifdef __DQUOT_PARANOIA | 591 | #ifdef __DQUOT_PARANOIA |
592 | /* sanity check */ | 592 | /* sanity check */ |
593 | if (!list_empty(&dquot->dq_free)) | 593 | BUG_ON(!list_empty(&dquot->dq_free)); |
594 | BUG(); | ||
595 | #endif | 594 | #endif |
596 | put_dquot_last(dquot); | 595 | put_dquot_last(dquot); |
597 | spin_unlock(&dq_list_lock); | 596 | spin_unlock(&dq_list_lock); |
@@ -666,8 +665,7 @@ we_slept: | |||
666 | return NODQUOT; | 665 | return NODQUOT; |
667 | } | 666 | } |
668 | #ifdef __DQUOT_PARANOIA | 667 | #ifdef __DQUOT_PARANOIA |
669 | if (!dquot->dq_sb) /* Has somebody invalidated entry under us? */ | 668 | BUG_ON(!dquot->dq_sb); /* Has somebody invalidated entry under us? */ |
670 | BUG(); | ||
671 | #endif | 669 | #endif |
672 | 670 | ||
673 | return dquot; | 671 | return dquot; |
@@ -561,7 +561,7 @@ static int exec_mmap(struct mm_struct *mm) | |||
561 | arch_pick_mmap_layout(mm); | 561 | arch_pick_mmap_layout(mm); |
562 | if (old_mm) { | 562 | if (old_mm) { |
563 | up_read(&old_mm->mmap_sem); | 563 | up_read(&old_mm->mmap_sem); |
564 | if (active_mm != old_mm) BUG(); | 564 | BUG_ON(active_mm != old_mm); |
565 | mmput(old_mm); | 565 | mmput(old_mm); |
566 | return 0; | 566 | return 0; |
567 | } | 567 | } |
diff --git a/fs/fcntl.c b/fs/fcntl.c index 2a2479196f96..d35cbc6bc112 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c | |||
@@ -453,8 +453,7 @@ static void send_sigio_to_task(struct task_struct *p, | |||
453 | /* Make sure we are called with one of the POLL_* | 453 | /* Make sure we are called with one of the POLL_* |
454 | reasons, otherwise we could leak kernel stack into | 454 | reasons, otherwise we could leak kernel stack into |
455 | userspace. */ | 455 | userspace. */ |
456 | if ((reason & __SI_MASK) != __SI_POLL) | 456 | BUG_ON((reason & __SI_MASK) != __SI_POLL); |
457 | BUG(); | ||
458 | if (reason - POLL_IN >= NSIGPOLL) | 457 | if (reason - POLL_IN >= NSIGPOLL) |
459 | si.si_band = ~0L; | 458 | si.si_band = ~0L; |
460 | else | 459 | else |
diff --git a/fs/freevxfs/vxfs_olt.c b/fs/freevxfs/vxfs_olt.c index 76a0708ae978..049500847903 100644 --- a/fs/freevxfs/vxfs_olt.c +++ b/fs/freevxfs/vxfs_olt.c | |||
@@ -42,24 +42,21 @@ | |||
42 | static inline void | 42 | static inline void |
43 | vxfs_get_fshead(struct vxfs_oltfshead *fshp, struct vxfs_sb_info *infp) | 43 | vxfs_get_fshead(struct vxfs_oltfshead *fshp, struct vxfs_sb_info *infp) |
44 | { | 44 | { |
45 | if (infp->vsi_fshino) | 45 | BUG_ON(infp->vsi_fshino); |
46 | BUG(); | ||
47 | infp->vsi_fshino = fshp->olt_fsino[0]; | 46 | infp->vsi_fshino = fshp->olt_fsino[0]; |
48 | } | 47 | } |
49 | 48 | ||
50 | static inline void | 49 | static inline void |
51 | vxfs_get_ilist(struct vxfs_oltilist *ilistp, struct vxfs_sb_info *infp) | 50 | vxfs_get_ilist(struct vxfs_oltilist *ilistp, struct vxfs_sb_info *infp) |
52 | { | 51 | { |
53 | if (infp->vsi_iext) | 52 | BUG_ON(infp->vsi_iext); |
54 | BUG(); | ||
55 | infp->vsi_iext = ilistp->olt_iext[0]; | 53 | infp->vsi_iext = ilistp->olt_iext[0]; |
56 | } | 54 | } |
57 | 55 | ||
58 | static inline u_long | 56 | static inline u_long |
59 | vxfs_oblock(struct super_block *sbp, daddr_t block, u_long bsize) | 57 | vxfs_oblock(struct super_block *sbp, daddr_t block, u_long bsize) |
60 | { | 58 | { |
61 | if (sbp->s_blocksize % bsize) | 59 | BUG_ON(sbp->s_blocksize % bsize); |
62 | BUG(); | ||
63 | return (block * (sbp->s_blocksize / bsize)); | 60 | return (block * (sbp->s_blocksize / bsize)); |
64 | } | 61 | } |
65 | 62 | ||
diff --git a/fs/hfsplus/bnode.c b/fs/hfsplus/bnode.c index 8f07e8fbd03d..746abc9ecf70 100644 --- a/fs/hfsplus/bnode.c +++ b/fs/hfsplus/bnode.c | |||
@@ -466,8 +466,7 @@ void hfs_bnode_unhash(struct hfs_bnode *node) | |||
466 | for (p = &node->tree->node_hash[hfs_bnode_hash(node->this)]; | 466 | for (p = &node->tree->node_hash[hfs_bnode_hash(node->this)]; |
467 | *p && *p != node; p = &(*p)->next_hash) | 467 | *p && *p != node; p = &(*p)->next_hash) |
468 | ; | 468 | ; |
469 | if (!*p) | 469 | BUG_ON(!*p); |
470 | BUG(); | ||
471 | *p = node->next_hash; | 470 | *p = node->next_hash; |
472 | node->tree->node_hash_cnt--; | 471 | node->tree->node_hash_cnt--; |
473 | } | 472 | } |
@@ -622,8 +621,7 @@ void hfs_bnode_put(struct hfs_bnode *node) | |||
622 | 621 | ||
623 | dprint(DBG_BNODE_REFS, "put_node(%d:%d): %d\n", | 622 | dprint(DBG_BNODE_REFS, "put_node(%d:%d): %d\n", |
624 | node->tree->cnid, node->this, atomic_read(&node->refcnt)); | 623 | node->tree->cnid, node->this, atomic_read(&node->refcnt)); |
625 | if (!atomic_read(&node->refcnt)) | 624 | BUG_ON(!atomic_read(&node->refcnt)); |
626 | BUG(); | ||
627 | if (!atomic_dec_and_lock(&node->refcnt, &tree->hash_lock)) | 625 | if (!atomic_dec_and_lock(&node->refcnt, &tree->hash_lock)) |
628 | return; | 626 | return; |
629 | for (i = 0; i < tree->pages_per_bnode; i++) { | 627 | for (i = 0; i < tree->pages_per_bnode; i++) { |
diff --git a/fs/hfsplus/btree.c b/fs/hfsplus/btree.c index a67edfa34e9e..effa8991999c 100644 --- a/fs/hfsplus/btree.c +++ b/fs/hfsplus/btree.c | |||
@@ -269,8 +269,7 @@ void hfs_bmap_free(struct hfs_bnode *node) | |||
269 | u8 *data, byte, m; | 269 | u8 *data, byte, m; |
270 | 270 | ||
271 | dprint(DBG_BNODE_MOD, "btree_free_node: %u\n", node->this); | 271 | dprint(DBG_BNODE_MOD, "btree_free_node: %u\n", node->this); |
272 | if (!node->this) | 272 | BUG_ON(!node->this); |
273 | BUG(); | ||
274 | tree = node->tree; | 273 | tree = node->tree; |
275 | nidx = node->this; | 274 | nidx = node->this; |
276 | node = hfs_bnode_find(tree, 0); | 275 | node = hfs_bnode_find(tree, 0); |
diff --git a/fs/inode.c b/fs/inode.c index 32b7c3375021..3a2446a27d2c 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
@@ -172,8 +172,7 @@ static struct inode *alloc_inode(struct super_block *sb) | |||
172 | 172 | ||
173 | void destroy_inode(struct inode *inode) | 173 | void destroy_inode(struct inode *inode) |
174 | { | 174 | { |
175 | if (inode_has_buffers(inode)) | 175 | BUG_ON(inode_has_buffers(inode)); |
176 | BUG(); | ||
177 | security_inode_free(inode); | 176 | security_inode_free(inode); |
178 | if (inode->i_sb->s_op->destroy_inode) | 177 | if (inode->i_sb->s_op->destroy_inode) |
179 | inode->i_sb->s_op->destroy_inode(inode); | 178 | inode->i_sb->s_op->destroy_inode(inode); |
@@ -249,12 +248,9 @@ void clear_inode(struct inode *inode) | |||
249 | might_sleep(); | 248 | might_sleep(); |
250 | invalidate_inode_buffers(inode); | 249 | invalidate_inode_buffers(inode); |
251 | 250 | ||
252 | if (inode->i_data.nrpages) | 251 | BUG_ON(inode->i_data.nrpages); |
253 | BUG(); | 252 | BUG_ON(!(inode->i_state & I_FREEING)); |
254 | if (!(inode->i_state & I_FREEING)) | 253 | BUG_ON(inode->i_state & I_CLEAR); |
255 | BUG(); | ||
256 | if (inode->i_state & I_CLEAR) | ||
257 | BUG(); | ||
258 | wait_on_inode(inode); | 254 | wait_on_inode(inode); |
259 | DQUOT_DROP(inode); | 255 | DQUOT_DROP(inode); |
260 | if (inode->i_sb && inode->i_sb->s_op->clear_inode) | 256 | if (inode->i_sb && inode->i_sb->s_op->clear_inode) |
@@ -1054,8 +1050,7 @@ void generic_delete_inode(struct inode *inode) | |||
1054 | hlist_del_init(&inode->i_hash); | 1050 | hlist_del_init(&inode->i_hash); |
1055 | spin_unlock(&inode_lock); | 1051 | spin_unlock(&inode_lock); |
1056 | wake_up_inode(inode); | 1052 | wake_up_inode(inode); |
1057 | if (inode->i_state != I_CLEAR) | 1053 | BUG_ON(inode->i_state != I_CLEAR); |
1058 | BUG(); | ||
1059 | destroy_inode(inode); | 1054 | destroy_inode(inode); |
1060 | } | 1055 | } |
1061 | 1056 | ||
diff --git a/fs/jffs2/background.c b/fs/jffs2/background.c index 7b77a9541125..ff2a872e80e7 100644 --- a/fs/jffs2/background.c +++ b/fs/jffs2/background.c | |||
@@ -35,8 +35,7 @@ int jffs2_start_garbage_collect_thread(struct jffs2_sb_info *c) | |||
35 | pid_t pid; | 35 | pid_t pid; |
36 | int ret = 0; | 36 | int ret = 0; |
37 | 37 | ||
38 | if (c->gc_task) | 38 | BUG_ON(c->gc_task); |
39 | BUG(); | ||
40 | 39 | ||
41 | init_completion(&c->gc_thread_start); | 40 | init_completion(&c->gc_thread_start); |
42 | init_completion(&c->gc_thread_exit); | 41 | init_completion(&c->gc_thread_exit); |
diff --git a/fs/smbfs/file.c b/fs/smbfs/file.c index c56bd99a9701..ed9a24d19d7d 100644 --- a/fs/smbfs/file.c +++ b/fs/smbfs/file.c | |||
@@ -178,11 +178,9 @@ smb_writepage(struct page *page, struct writeback_control *wbc) | |||
178 | unsigned offset = PAGE_CACHE_SIZE; | 178 | unsigned offset = PAGE_CACHE_SIZE; |
179 | int err; | 179 | int err; |
180 | 180 | ||
181 | if (!mapping) | 181 | BUG_ON(!mapping); |
182 | BUG(); | ||
183 | inode = mapping->host; | 182 | inode = mapping->host; |
184 | if (!inode) | 183 | BUG_ON(!inode); |
185 | BUG(); | ||
186 | 184 | ||
187 | end_index = inode->i_size >> PAGE_CACHE_SHIFT; | 185 | end_index = inode->i_size >> PAGE_CACHE_SHIFT; |
188 | 186 | ||
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index f26880a4785e..6cfdc9a87772 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c | |||
@@ -50,7 +50,7 @@ static struct sysfs_dirent * sysfs_new_dirent(struct sysfs_dirent * parent_sd, | |||
50 | return sd; | 50 | return sd; |
51 | } | 51 | } |
52 | 52 | ||
53 | /** | 53 | /* |
54 | * | 54 | * |
55 | * Return -EEXIST if there is already a sysfs element with the same name for | 55 | * Return -EEXIST if there is already a sysfs element with the same name for |
56 | * the same parent. | 56 | * the same parent. |
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 830f76fa098c..f1cb1ddde511 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c | |||
@@ -183,7 +183,7 @@ fill_write_buffer(struct sysfs_buffer * buffer, const char __user * buf, size_t | |||
183 | return -ENOMEM; | 183 | return -ENOMEM; |
184 | 184 | ||
185 | if (count >= PAGE_SIZE) | 185 | if (count >= PAGE_SIZE) |
186 | count = PAGE_SIZE; | 186 | count = PAGE_SIZE - 1; |
187 | error = copy_from_user(buffer->page,buf,count); | 187 | error = copy_from_user(buffer->page,buf,count); |
188 | buffer->needs_read_fill = 1; | 188 | buffer->needs_read_fill = 1; |
189 | return error ? -EFAULT : count; | 189 | return error ? -EFAULT : count; |
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index 4c29ac41ac3e..f0b347bd12ca 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c | |||
@@ -175,8 +175,7 @@ const unsigned char * sysfs_get_name(struct sysfs_dirent *sd) | |||
175 | struct bin_attribute * bin_attr; | 175 | struct bin_attribute * bin_attr; |
176 | struct sysfs_symlink * sl; | 176 | struct sysfs_symlink * sl; |
177 | 177 | ||
178 | if (!sd || !sd->s_element) | 178 | BUG_ON(!sd || !sd->s_element); |
179 | BUG(); | ||
180 | 179 | ||
181 | switch (sd->s_type) { | 180 | switch (sd->s_type) { |
182 | case SYSFS_DIR: | 181 | case SYSFS_DIR: |
diff --git a/fs/sysv/dir.c b/fs/sysv/dir.c index 8c66e9270dd6..d7074341ee87 100644 --- a/fs/sysv/dir.c +++ b/fs/sysv/dir.c | |||
@@ -253,8 +253,7 @@ int sysv_delete_entry(struct sysv_dir_entry *de, struct page *page) | |||
253 | 253 | ||
254 | lock_page(page); | 254 | lock_page(page); |
255 | err = mapping->a_ops->prepare_write(NULL, page, from, to); | 255 | err = mapping->a_ops->prepare_write(NULL, page, from, to); |
256 | if (err) | 256 | BUG_ON(err); |
257 | BUG(); | ||
258 | de->inode = 0; | 257 | de->inode = 0; |
259 | err = dir_commit_chunk(page, from, to); | 258 | err = dir_commit_chunk(page, from, to); |
260 | dir_put_page(page); | 259 | dir_put_page(page); |
@@ -353,8 +352,7 @@ void sysv_set_link(struct sysv_dir_entry *de, struct page *page, | |||
353 | 352 | ||
354 | lock_page(page); | 353 | lock_page(page); |
355 | err = page->mapping->a_ops->prepare_write(NULL, page, from, to); | 354 | err = page->mapping->a_ops->prepare_write(NULL, page, from, to); |
356 | if (err) | 355 | BUG_ON(err); |
357 | BUG(); | ||
358 | de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), inode->i_ino); | 356 | de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), inode->i_ino); |
359 | err = dir_commit_chunk(page, from, to); | 357 | err = dir_commit_chunk(page, from, to); |
360 | dir_put_page(page); | 358 | dir_put_page(page); |
diff --git a/fs/udf/inode.c b/fs/udf/inode.c index 81e0e8459af1..2983afd5e7fd 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c | |||
@@ -312,12 +312,10 @@ static int udf_get_block(struct inode *inode, sector_t block, struct buffer_head | |||
312 | err = 0; | 312 | err = 0; |
313 | 313 | ||
314 | bh = inode_getblk(inode, block, &err, &phys, &new); | 314 | bh = inode_getblk(inode, block, &err, &phys, &new); |
315 | if (bh) | 315 | BUG_ON(bh); |
316 | BUG(); | ||
317 | if (err) | 316 | if (err) |
318 | goto abort; | 317 | goto abort; |
319 | if (!phys) | 318 | BUG_ON(!phys); |
320 | BUG(); | ||
321 | 319 | ||
322 | if (new) | 320 | if (new) |
323 | set_buffer_new(bh_result); | 321 | set_buffer_new(bh_result); |
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c index 85997b1205f5..ae4c4754ed31 100644 --- a/fs/xfs/linux-2.6/xfs_file.c +++ b/fs/xfs/linux-2.6/xfs_file.c | |||
@@ -69,7 +69,6 @@ __xfs_file_read( | |||
69 | return rval; | 69 | return rval; |
70 | } | 70 | } |
71 | 71 | ||
72 | |||
73 | STATIC ssize_t | 72 | STATIC ssize_t |
74 | xfs_file_aio_read( | 73 | xfs_file_aio_read( |
75 | struct kiocb *iocb, | 74 | struct kiocb *iocb, |
@@ -90,7 +89,6 @@ xfs_file_aio_read_invis( | |||
90 | return __xfs_file_read(iocb, buf, IO_ISAIO|IO_INVIS, count, pos); | 89 | return __xfs_file_read(iocb, buf, IO_ISAIO|IO_INVIS, count, pos); |
91 | } | 90 | } |
92 | 91 | ||
93 | |||
94 | STATIC inline ssize_t | 92 | STATIC inline ssize_t |
95 | __xfs_file_write( | 93 | __xfs_file_write( |
96 | struct kiocb *iocb, | 94 | struct kiocb *iocb, |
@@ -113,7 +111,6 @@ __xfs_file_write( | |||
113 | return rval; | 111 | return rval; |
114 | } | 112 | } |
115 | 113 | ||
116 | |||
117 | STATIC ssize_t | 114 | STATIC ssize_t |
118 | xfs_file_aio_write( | 115 | xfs_file_aio_write( |
119 | struct kiocb *iocb, | 116 | struct kiocb *iocb, |
@@ -134,7 +131,6 @@ xfs_file_aio_write_invis( | |||
134 | return __xfs_file_write(iocb, buf, IO_ISAIO|IO_INVIS, count, pos); | 131 | return __xfs_file_write(iocb, buf, IO_ISAIO|IO_INVIS, count, pos); |
135 | } | 132 | } |
136 | 133 | ||
137 | |||
138 | STATIC inline ssize_t | 134 | STATIC inline ssize_t |
139 | __xfs_file_readv( | 135 | __xfs_file_readv( |
140 | struct file *file, | 136 | struct file *file, |
@@ -179,7 +175,6 @@ xfs_file_readv_invis( | |||
179 | return __xfs_file_readv(file, iov, IO_INVIS, nr_segs, ppos); | 175 | return __xfs_file_readv(file, iov, IO_INVIS, nr_segs, ppos); |
180 | } | 176 | } |
181 | 177 | ||
182 | |||
183 | STATIC inline ssize_t | 178 | STATIC inline ssize_t |
184 | __xfs_file_writev( | 179 | __xfs_file_writev( |
185 | struct file *file, | 180 | struct file *file, |
@@ -204,7 +199,6 @@ __xfs_file_writev( | |||
204 | return rval; | 199 | return rval; |
205 | } | 200 | } |
206 | 201 | ||
207 | |||
208 | STATIC ssize_t | 202 | STATIC ssize_t |
209 | xfs_file_writev( | 203 | xfs_file_writev( |
210 | struct file *file, | 204 | struct file *file, |
@@ -228,7 +222,7 @@ xfs_file_writev_invis( | |||
228 | STATIC ssize_t | 222 | STATIC ssize_t |
229 | xfs_file_sendfile( | 223 | xfs_file_sendfile( |
230 | struct file *filp, | 224 | struct file *filp, |
231 | loff_t *ppos, | 225 | loff_t *pos, |
232 | size_t count, | 226 | size_t count, |
233 | read_actor_t actor, | 227 | read_actor_t actor, |
234 | void *target) | 228 | void *target) |
@@ -236,10 +230,80 @@ xfs_file_sendfile( | |||
236 | vnode_t *vp = vn_from_inode(filp->f_dentry->d_inode); | 230 | vnode_t *vp = vn_from_inode(filp->f_dentry->d_inode); |
237 | ssize_t rval; | 231 | ssize_t rval; |
238 | 232 | ||
239 | VOP_SENDFILE(vp, filp, ppos, 0, count, actor, target, NULL, rval); | 233 | VOP_SENDFILE(vp, filp, pos, 0, count, actor, target, NULL, rval); |
240 | return rval; | 234 | return rval; |
241 | } | 235 | } |
242 | 236 | ||
237 | STATIC ssize_t | ||
238 | xfs_file_sendfile_invis( | ||
239 | struct file *filp, | ||
240 | loff_t *pos, | ||
241 | size_t count, | ||
242 | read_actor_t actor, | ||
243 | void *target) | ||
244 | { | ||
245 | vnode_t *vp = vn_from_inode(filp->f_dentry->d_inode); | ||
246 | ssize_t rval; | ||
247 | |||
248 | VOP_SENDFILE(vp, filp, pos, IO_INVIS, count, actor, target, NULL, rval); | ||
249 | return rval; | ||
250 | } | ||
251 | |||
252 | STATIC ssize_t | ||
253 | xfs_file_splice_read( | ||
254 | struct file *infilp, | ||
255 | struct inode *pipe, | ||
256 | size_t len, | ||
257 | unsigned int flags) | ||
258 | { | ||
259 | vnode_t *vp = vn_from_inode(infilp->f_dentry->d_inode); | ||
260 | ssize_t rval; | ||
261 | |||
262 | VOP_SPLICE_READ(vp, infilp, pipe, len, flags, 0, NULL, rval); | ||
263 | return rval; | ||
264 | } | ||
265 | |||
266 | STATIC ssize_t | ||
267 | xfs_file_splice_read_invis( | ||
268 | struct file *infilp, | ||
269 | struct inode *pipe, | ||
270 | size_t len, | ||
271 | unsigned int flags) | ||
272 | { | ||
273 | vnode_t *vp = vn_from_inode(infilp->f_dentry->d_inode); | ||
274 | ssize_t rval; | ||
275 | |||
276 | VOP_SPLICE_READ(vp, infilp, pipe, len, flags, IO_INVIS, NULL, rval); | ||
277 | return rval; | ||
278 | } | ||
279 | |||
280 | STATIC ssize_t | ||
281 | xfs_file_splice_write( | ||
282 | struct inode *pipe, | ||
283 | struct file *outfilp, | ||
284 | size_t len, | ||
285 | unsigned int flags) | ||
286 | { | ||
287 | vnode_t *vp = vn_from_inode(outfilp->f_dentry->d_inode); | ||
288 | ssize_t rval; | ||
289 | |||
290 | VOP_SPLICE_WRITE(vp, pipe, outfilp, len, flags, 0, NULL, rval); | ||
291 | return rval; | ||
292 | } | ||
293 | |||
294 | STATIC ssize_t | ||
295 | xfs_file_splice_write_invis( | ||
296 | struct inode *pipe, | ||
297 | struct file *outfilp, | ||
298 | size_t len, | ||
299 | unsigned int flags) | ||
300 | { | ||
301 | vnode_t *vp = vn_from_inode(outfilp->f_dentry->d_inode); | ||
302 | ssize_t rval; | ||
303 | |||
304 | VOP_SPLICE_WRITE(vp, pipe, outfilp, len, flags, IO_INVIS, NULL, rval); | ||
305 | return rval; | ||
306 | } | ||
243 | 307 | ||
244 | STATIC int | 308 | STATIC int |
245 | xfs_file_open( | 309 | xfs_file_open( |
@@ -251,13 +315,10 @@ xfs_file_open( | |||
251 | 315 | ||
252 | if (!(filp->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS) | 316 | if (!(filp->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS) |
253 | return -EFBIG; | 317 | return -EFBIG; |
254 | |||
255 | ASSERT(vp); | ||
256 | VOP_OPEN(vp, NULL, error); | 318 | VOP_OPEN(vp, NULL, error); |
257 | return -error; | 319 | return -error; |
258 | } | 320 | } |
259 | 321 | ||
260 | |||
261 | STATIC int | 322 | STATIC int |
262 | xfs_file_release( | 323 | xfs_file_release( |
263 | struct inode *inode, | 324 | struct inode *inode, |
@@ -271,7 +332,6 @@ xfs_file_release( | |||
271 | return -error; | 332 | return -error; |
272 | } | 333 | } |
273 | 334 | ||
274 | |||
275 | STATIC int | 335 | STATIC int |
276 | xfs_file_fsync( | 336 | xfs_file_fsync( |
277 | struct file *filp, | 337 | struct file *filp, |
@@ -285,21 +345,11 @@ xfs_file_fsync( | |||
285 | 345 | ||
286 | if (datasync) | 346 | if (datasync) |
287 | flags |= FSYNC_DATA; | 347 | flags |= FSYNC_DATA; |
288 | |||
289 | ASSERT(vp); | ||
290 | VOP_FSYNC(vp, flags, NULL, (xfs_off_t)0, (xfs_off_t)-1, error); | 348 | VOP_FSYNC(vp, flags, NULL, (xfs_off_t)0, (xfs_off_t)-1, error); |
291 | return -error; | 349 | return -error; |
292 | } | 350 | } |
293 | 351 | ||
294 | /* | ||
295 | * xfs_file_readdir maps to VOP_READDIR(). | ||
296 | * We need to build a uio, cred, ... | ||
297 | */ | ||
298 | |||
299 | #define nextdp(dp) ((struct xfs_dirent *)((char *)(dp) + (dp)->d_reclen)) | ||
300 | |||
301 | #ifdef CONFIG_XFS_DMAPI | 352 | #ifdef CONFIG_XFS_DMAPI |
302 | |||
303 | STATIC struct page * | 353 | STATIC struct page * |
304 | xfs_vm_nopage( | 354 | xfs_vm_nopage( |
305 | struct vm_area_struct *area, | 355 | struct vm_area_struct *area, |
@@ -319,10 +369,8 @@ xfs_vm_nopage( | |||
319 | 369 | ||
320 | return filemap_nopage(area, address, type); | 370 | return filemap_nopage(area, address, type); |
321 | } | 371 | } |
322 | |||
323 | #endif /* CONFIG_XFS_DMAPI */ | 372 | #endif /* CONFIG_XFS_DMAPI */ |
324 | 373 | ||
325 | |||
326 | STATIC int | 374 | STATIC int |
327 | xfs_file_readdir( | 375 | xfs_file_readdir( |
328 | struct file *filp, | 376 | struct file *filp, |
@@ -330,7 +378,7 @@ xfs_file_readdir( | |||
330 | filldir_t filldir) | 378 | filldir_t filldir) |
331 | { | 379 | { |
332 | int error = 0; | 380 | int error = 0; |
333 | vnode_t *vp; | 381 | vnode_t *vp = vn_from_inode(filp->f_dentry->d_inode); |
334 | uio_t uio; | 382 | uio_t uio; |
335 | iovec_t iov; | 383 | iovec_t iov; |
336 | int eof = 0; | 384 | int eof = 0; |
@@ -340,9 +388,6 @@ xfs_file_readdir( | |||
340 | xfs_off_t start_offset, curr_offset; | 388 | xfs_off_t start_offset, curr_offset; |
341 | xfs_dirent_t *dbp = NULL; | 389 | xfs_dirent_t *dbp = NULL; |
342 | 390 | ||
343 | vp = vn_from_inode(filp->f_dentry->d_inode); | ||
344 | ASSERT(vp); | ||
345 | |||
346 | /* Try fairly hard to get memory */ | 391 | /* Try fairly hard to get memory */ |
347 | do { | 392 | do { |
348 | if ((read_buf = (caddr_t)kmalloc(rlen, GFP_KERNEL))) | 393 | if ((read_buf = (caddr_t)kmalloc(rlen, GFP_KERNEL))) |
@@ -387,7 +432,7 @@ xfs_file_readdir( | |||
387 | } | 432 | } |
388 | size -= dbp->d_reclen; | 433 | size -= dbp->d_reclen; |
389 | curr_offset = (loff_t)dbp->d_off /* & 0x7fffffff */; | 434 | curr_offset = (loff_t)dbp->d_off /* & 0x7fffffff */; |
390 | dbp = nextdp(dbp); | 435 | dbp = (xfs_dirent_t *)((char *)dbp + dbp->d_reclen); |
391 | } | 436 | } |
392 | } | 437 | } |
393 | done: | 438 | done: |
@@ -402,7 +447,6 @@ done: | |||
402 | return -error; | 447 | return -error; |
403 | } | 448 | } |
404 | 449 | ||
405 | |||
406 | STATIC int | 450 | STATIC int |
407 | xfs_file_mmap( | 451 | xfs_file_mmap( |
408 | struct file *filp, | 452 | struct file *filp, |
@@ -457,11 +501,10 @@ xfs_file_ioctl_invis( | |||
457 | unsigned int cmd, | 501 | unsigned int cmd, |
458 | unsigned long arg) | 502 | unsigned long arg) |
459 | { | 503 | { |
460 | int error; | ||
461 | struct inode *inode = filp->f_dentry->d_inode; | 504 | struct inode *inode = filp->f_dentry->d_inode; |
462 | vnode_t *vp = vn_from_inode(inode); | 505 | vnode_t *vp = vn_from_inode(inode); |
506 | int error; | ||
463 | 507 | ||
464 | ASSERT(vp); | ||
465 | VOP_IOCTL(vp, inode, filp, IO_INVIS, cmd, (void __user *)arg, error); | 508 | VOP_IOCTL(vp, inode, filp, IO_INVIS, cmd, (void __user *)arg, error); |
466 | VMODIFY(vp); | 509 | VMODIFY(vp); |
467 | 510 | ||
@@ -537,6 +580,8 @@ const struct file_operations xfs_file_operations = { | |||
537 | .aio_read = xfs_file_aio_read, | 580 | .aio_read = xfs_file_aio_read, |
538 | .aio_write = xfs_file_aio_write, | 581 | .aio_write = xfs_file_aio_write, |
539 | .sendfile = xfs_file_sendfile, | 582 | .sendfile = xfs_file_sendfile, |
583 | .splice_read = xfs_file_splice_read, | ||
584 | .splice_write = xfs_file_splice_write, | ||
540 | .unlocked_ioctl = xfs_file_ioctl, | 585 | .unlocked_ioctl = xfs_file_ioctl, |
541 | #ifdef CONFIG_COMPAT | 586 | #ifdef CONFIG_COMPAT |
542 | .compat_ioctl = xfs_file_compat_ioctl, | 587 | .compat_ioctl = xfs_file_compat_ioctl, |
@@ -558,7 +603,9 @@ const struct file_operations xfs_invis_file_operations = { | |||
558 | .writev = xfs_file_writev_invis, | 603 | .writev = xfs_file_writev_invis, |
559 | .aio_read = xfs_file_aio_read_invis, | 604 | .aio_read = xfs_file_aio_read_invis, |
560 | .aio_write = xfs_file_aio_write_invis, | 605 | .aio_write = xfs_file_aio_write_invis, |
561 | .sendfile = xfs_file_sendfile, | 606 | .sendfile = xfs_file_sendfile_invis, |
607 | .splice_read = xfs_file_splice_read_invis, | ||
608 | .splice_write = xfs_file_splice_write_invis, | ||
562 | .unlocked_ioctl = xfs_file_ioctl_invis, | 609 | .unlocked_ioctl = xfs_file_ioctl_invis, |
563 | #ifdef CONFIG_COMPAT | 610 | #ifdef CONFIG_COMPAT |
564 | .compat_ioctl = xfs_file_compat_invis_ioctl, | 611 | .compat_ioctl = xfs_file_compat_invis_ioctl, |
diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h index 1fe09f2d6519..e9fe43d74768 100644 --- a/fs/xfs/linux-2.6/xfs_linux.h +++ b/fs/xfs/linux-2.6/xfs_linux.h | |||
@@ -103,6 +103,7 @@ | |||
103 | */ | 103 | */ |
104 | #undef HAVE_REFCACHE /* reference cache not needed for NFS in 2.6 */ | 104 | #undef HAVE_REFCACHE /* reference cache not needed for NFS in 2.6 */ |
105 | #define HAVE_SENDFILE /* sendfile(2) exists in 2.6, but not in 2.4 */ | 105 | #define HAVE_SENDFILE /* sendfile(2) exists in 2.6, but not in 2.4 */ |
106 | #define HAVE_SPLICE /* a splice(2) exists in 2.6, but not in 2.4 */ | ||
106 | #ifdef CONFIG_SMP | 107 | #ifdef CONFIG_SMP |
107 | #define HAVE_PERCPU_SB /* per cpu superblock counters are a 2.6 feature */ | 108 | #define HAVE_PERCPU_SB /* per cpu superblock counters are a 2.6 feature */ |
108 | #else | 109 | #else |
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c index 84ddf1893894..90cd314acbaa 100644 --- a/fs/xfs/linux-2.6/xfs_lrw.c +++ b/fs/xfs/linux-2.6/xfs_lrw.c | |||
@@ -301,36 +301,23 @@ xfs_sendfile( | |||
301 | void *target, | 301 | void *target, |
302 | cred_t *credp) | 302 | cred_t *credp) |
303 | { | 303 | { |
304 | xfs_inode_t *ip = XFS_BHVTOI(bdp); | ||
305 | xfs_mount_t *mp = ip->i_mount; | ||
304 | ssize_t ret; | 306 | ssize_t ret; |
305 | xfs_fsize_t n; | ||
306 | xfs_inode_t *ip; | ||
307 | xfs_mount_t *mp; | ||
308 | vnode_t *vp; | ||
309 | |||
310 | ip = XFS_BHVTOI(bdp); | ||
311 | vp = BHV_TO_VNODE(bdp); | ||
312 | mp = ip->i_mount; | ||
313 | 307 | ||
314 | XFS_STATS_INC(xs_read_calls); | 308 | XFS_STATS_INC(xs_read_calls); |
315 | 309 | if (XFS_FORCED_SHUTDOWN(mp)) | |
316 | n = XFS_MAXIOFFSET(mp) - *offset; | ||
317 | if ((n <= 0) || (count == 0)) | ||
318 | return 0; | ||
319 | |||
320 | if (n < count) | ||
321 | count = n; | ||
322 | |||
323 | if (XFS_FORCED_SHUTDOWN(ip->i_mount)) | ||
324 | return -EIO; | 310 | return -EIO; |
325 | 311 | ||
326 | xfs_ilock(ip, XFS_IOLOCK_SHARED); | 312 | xfs_ilock(ip, XFS_IOLOCK_SHARED); |
327 | 313 | ||
328 | if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ) && | 314 | if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_READ) && |
329 | (!(ioflags & IO_INVIS))) { | 315 | (!(ioflags & IO_INVIS))) { |
330 | vrwlock_t locktype = VRWLOCK_READ; | 316 | vrwlock_t locktype = VRWLOCK_READ; |
331 | int error; | 317 | int error; |
332 | 318 | ||
333 | error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp), *offset, count, | 319 | error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp), |
320 | *offset, count, | ||
334 | FILP_DELAY_FLAG(filp), &locktype); | 321 | FILP_DELAY_FLAG(filp), &locktype); |
335 | if (error) { | 322 | if (error) { |
336 | xfs_iunlock(ip, XFS_IOLOCK_SHARED); | 323 | xfs_iunlock(ip, XFS_IOLOCK_SHARED); |
@@ -340,12 +327,96 @@ xfs_sendfile( | |||
340 | xfs_rw_enter_trace(XFS_SENDFILE_ENTER, &ip->i_iocore, | 327 | xfs_rw_enter_trace(XFS_SENDFILE_ENTER, &ip->i_iocore, |
341 | (void *)(unsigned long)target, count, *offset, ioflags); | 328 | (void *)(unsigned long)target, count, *offset, ioflags); |
342 | ret = generic_file_sendfile(filp, offset, count, actor, target); | 329 | ret = generic_file_sendfile(filp, offset, count, actor, target); |
330 | if (ret > 0) | ||
331 | XFS_STATS_ADD(xs_read_bytes, ret); | ||
343 | 332 | ||
344 | xfs_iunlock(ip, XFS_IOLOCK_SHARED); | 333 | xfs_iunlock(ip, XFS_IOLOCK_SHARED); |
334 | return ret; | ||
335 | } | ||
345 | 336 | ||
337 | ssize_t | ||
338 | xfs_splice_read( | ||
339 | bhv_desc_t *bdp, | ||
340 | struct file *infilp, | ||
341 | struct inode *pipe, | ||
342 | size_t count, | ||
343 | int flags, | ||
344 | int ioflags, | ||
345 | cred_t *credp) | ||
346 | { | ||
347 | xfs_inode_t *ip = XFS_BHVTOI(bdp); | ||
348 | xfs_mount_t *mp = ip->i_mount; | ||
349 | ssize_t ret; | ||
350 | |||
351 | XFS_STATS_INC(xs_read_calls); | ||
352 | if (XFS_FORCED_SHUTDOWN(ip->i_mount)) | ||
353 | return -EIO; | ||
354 | |||
355 | xfs_ilock(ip, XFS_IOLOCK_SHARED); | ||
356 | |||
357 | if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_READ) && | ||
358 | (!(ioflags & IO_INVIS))) { | ||
359 | vrwlock_t locktype = VRWLOCK_READ; | ||
360 | int error; | ||
361 | |||
362 | error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp), | ||
363 | infilp->f_pos, count, | ||
364 | FILP_DELAY_FLAG(infilp), &locktype); | ||
365 | if (error) { | ||
366 | xfs_iunlock(ip, XFS_IOLOCK_SHARED); | ||
367 | return -error; | ||
368 | } | ||
369 | } | ||
370 | xfs_rw_enter_trace(XFS_SPLICE_READ_ENTER, &ip->i_iocore, | ||
371 | pipe, count, infilp->f_pos, ioflags); | ||
372 | ret = generic_file_splice_read(infilp, pipe, count, flags); | ||
346 | if (ret > 0) | 373 | if (ret > 0) |
347 | XFS_STATS_ADD(xs_read_bytes, ret); | 374 | XFS_STATS_ADD(xs_read_bytes, ret); |
348 | 375 | ||
376 | xfs_iunlock(ip, XFS_IOLOCK_SHARED); | ||
377 | return ret; | ||
378 | } | ||
379 | |||
380 | ssize_t | ||
381 | xfs_splice_write( | ||
382 | bhv_desc_t *bdp, | ||
383 | struct inode *pipe, | ||
384 | struct file *outfilp, | ||
385 | size_t count, | ||
386 | int flags, | ||
387 | int ioflags, | ||
388 | cred_t *credp) | ||
389 | { | ||
390 | xfs_inode_t *ip = XFS_BHVTOI(bdp); | ||
391 | xfs_mount_t *mp = ip->i_mount; | ||
392 | ssize_t ret; | ||
393 | |||
394 | XFS_STATS_INC(xs_write_calls); | ||
395 | if (XFS_FORCED_SHUTDOWN(ip->i_mount)) | ||
396 | return -EIO; | ||
397 | |||
398 | xfs_ilock(ip, XFS_IOLOCK_EXCL); | ||
399 | |||
400 | if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_WRITE) && | ||
401 | (!(ioflags & IO_INVIS))) { | ||
402 | vrwlock_t locktype = VRWLOCK_WRITE; | ||
403 | int error; | ||
404 | |||
405 | error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, BHV_TO_VNODE(bdp), | ||
406 | outfilp->f_pos, count, | ||
407 | FILP_DELAY_FLAG(outfilp), &locktype); | ||
408 | if (error) { | ||
409 | xfs_iunlock(ip, XFS_IOLOCK_EXCL); | ||
410 | return -error; | ||
411 | } | ||
412 | } | ||
413 | xfs_rw_enter_trace(XFS_SPLICE_WRITE_ENTER, &ip->i_iocore, | ||
414 | pipe, count, outfilp->f_pos, ioflags); | ||
415 | ret = generic_file_splice_write(pipe, outfilp, count, flags); | ||
416 | if (ret > 0) | ||
417 | XFS_STATS_ADD(xs_write_bytes, ret); | ||
418 | |||
419 | xfs_iunlock(ip, XFS_IOLOCK_EXCL); | ||
349 | return ret; | 420 | return ret; |
350 | } | 421 | } |
351 | 422 | ||
@@ -363,7 +434,7 @@ xfs_zero_last_block( | |||
363 | xfs_fsize_t end_size) | 434 | xfs_fsize_t end_size) |
364 | { | 435 | { |
365 | xfs_fileoff_t last_fsb; | 436 | xfs_fileoff_t last_fsb; |
366 | xfs_mount_t *mp; | 437 | xfs_mount_t *mp = io->io_mount; |
367 | int nimaps; | 438 | int nimaps; |
368 | int zero_offset; | 439 | int zero_offset; |
369 | int zero_len; | 440 | int zero_len; |
@@ -373,8 +444,6 @@ xfs_zero_last_block( | |||
373 | 444 | ||
374 | ASSERT(ismrlocked(io->io_lock, MR_UPDATE) != 0); | 445 | ASSERT(ismrlocked(io->io_lock, MR_UPDATE) != 0); |
375 | 446 | ||
376 | mp = io->io_mount; | ||
377 | |||
378 | zero_offset = XFS_B_FSB_OFFSET(mp, isize); | 447 | zero_offset = XFS_B_FSB_OFFSET(mp, isize); |
379 | if (zero_offset == 0) { | 448 | if (zero_offset == 0) { |
380 | /* | 449 | /* |
@@ -405,10 +474,9 @@ xfs_zero_last_block( | |||
405 | * don't deadlock when the buffer cache calls back to us. | 474 | * don't deadlock when the buffer cache calls back to us. |
406 | */ | 475 | */ |
407 | XFS_IUNLOCK(mp, io, XFS_ILOCK_EXCL| XFS_EXTSIZE_RD); | 476 | XFS_IUNLOCK(mp, io, XFS_ILOCK_EXCL| XFS_EXTSIZE_RD); |
408 | loff = XFS_FSB_TO_B(mp, last_fsb); | ||
409 | 477 | ||
478 | loff = XFS_FSB_TO_B(mp, last_fsb); | ||
410 | zero_len = mp->m_sb.sb_blocksize - zero_offset; | 479 | zero_len = mp->m_sb.sb_blocksize - zero_offset; |
411 | |||
412 | error = xfs_iozero(ip, loff + zero_offset, zero_len, end_size); | 480 | error = xfs_iozero(ip, loff + zero_offset, zero_len, end_size); |
413 | 481 | ||
414 | XFS_ILOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD); | 482 | XFS_ILOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD); |
@@ -441,7 +509,7 @@ xfs_zero_eof( | |||
441 | xfs_fileoff_t zero_count_fsb; | 509 | xfs_fileoff_t zero_count_fsb; |
442 | xfs_fileoff_t last_fsb; | 510 | xfs_fileoff_t last_fsb; |
443 | xfs_extlen_t buf_len_fsb; | 511 | xfs_extlen_t buf_len_fsb; |
444 | xfs_mount_t *mp; | 512 | xfs_mount_t *mp = io->io_mount; |
445 | int nimaps; | 513 | int nimaps; |
446 | int error = 0; | 514 | int error = 0; |
447 | xfs_bmbt_irec_t imap; | 515 | xfs_bmbt_irec_t imap; |
@@ -450,8 +518,6 @@ xfs_zero_eof( | |||
450 | ASSERT(ismrlocked(io->io_iolock, MR_UPDATE)); | 518 | ASSERT(ismrlocked(io->io_iolock, MR_UPDATE)); |
451 | ASSERT(offset > isize); | 519 | ASSERT(offset > isize); |
452 | 520 | ||
453 | mp = io->io_mount; | ||
454 | |||
455 | /* | 521 | /* |
456 | * First handle zeroing the block on which isize resides. | 522 | * First handle zeroing the block on which isize resides. |
457 | * We only zero a part of that block so it is handled specially. | 523 | * We only zero a part of that block so it is handled specially. |
diff --git a/fs/xfs/linux-2.6/xfs_lrw.h b/fs/xfs/linux-2.6/xfs_lrw.h index 38864a88d42d..eaa5659713fb 100644 --- a/fs/xfs/linux-2.6/xfs_lrw.h +++ b/fs/xfs/linux-2.6/xfs_lrw.h | |||
@@ -60,6 +60,8 @@ struct xfs_iomap; | |||
60 | #define XFS_IOMAP_ALLOC_ENTER 25 | 60 | #define XFS_IOMAP_ALLOC_ENTER 25 |
61 | #define XFS_IOMAP_ALLOC_MAP 26 | 61 | #define XFS_IOMAP_ALLOC_MAP 26 |
62 | #define XFS_IOMAP_UNWRITTEN 27 | 62 | #define XFS_IOMAP_UNWRITTEN 27 |
63 | #define XFS_SPLICE_READ_ENTER 28 | ||
64 | #define XFS_SPLICE_WRITE_ENTER 29 | ||
63 | extern void xfs_rw_enter_trace(int, struct xfs_iocore *, | 65 | extern void xfs_rw_enter_trace(int, struct xfs_iocore *, |
64 | void *, size_t, loff_t, int); | 66 | void *, size_t, loff_t, int); |
65 | extern void xfs_inval_cached_trace(struct xfs_iocore *, | 67 | extern void xfs_inval_cached_trace(struct xfs_iocore *, |
@@ -78,6 +80,7 @@ extern int xfs_bmap(struct bhv_desc *, xfs_off_t, ssize_t, int, | |||
78 | struct xfs_iomap *, int *); | 80 | struct xfs_iomap *, int *); |
79 | extern int xfsbdstrat(struct xfs_mount *, struct xfs_buf *); | 81 | extern int xfsbdstrat(struct xfs_mount *, struct xfs_buf *); |
80 | extern int xfs_bdstrat_cb(struct xfs_buf *); | 82 | extern int xfs_bdstrat_cb(struct xfs_buf *); |
83 | extern int xfs_dev_is_read_only(struct xfs_mount *, char *); | ||
81 | 84 | ||
82 | extern int xfs_zero_eof(struct vnode *, struct xfs_iocore *, xfs_off_t, | 85 | extern int xfs_zero_eof(struct vnode *, struct xfs_iocore *, xfs_off_t, |
83 | xfs_fsize_t, xfs_fsize_t); | 86 | xfs_fsize_t, xfs_fsize_t); |
@@ -90,7 +93,11 @@ extern ssize_t xfs_write(struct bhv_desc *, struct kiocb *, | |||
90 | extern ssize_t xfs_sendfile(struct bhv_desc *, struct file *, | 93 | extern ssize_t xfs_sendfile(struct bhv_desc *, struct file *, |
91 | loff_t *, int, size_t, read_actor_t, | 94 | loff_t *, int, size_t, read_actor_t, |
92 | void *, struct cred *); | 95 | void *, struct cred *); |
93 | 96 | extern ssize_t xfs_splice_read(struct bhv_desc *, struct file *, | |
94 | extern int xfs_dev_is_read_only(struct xfs_mount *, char *); | 97 | struct inode *, size_t, int, int, |
98 | struct cred *); | ||
99 | extern ssize_t xfs_splice_write(struct bhv_desc *, struct inode *, | ||
100 | struct file *, size_t, int, int, | ||
101 | struct cred *); | ||
95 | 102 | ||
96 | #endif /* __XFS_LRW_H__ */ | 103 | #endif /* __XFS_LRW_H__ */ |
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 1884300417e3..68f4793e8a11 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c | |||
@@ -67,7 +67,8 @@ mempool_t *xfs_ioend_pool; | |||
67 | 67 | ||
68 | STATIC struct xfs_mount_args * | 68 | STATIC struct xfs_mount_args * |
69 | xfs_args_allocate( | 69 | xfs_args_allocate( |
70 | struct super_block *sb) | 70 | struct super_block *sb, |
71 | int silent) | ||
71 | { | 72 | { |
72 | struct xfs_mount_args *args; | 73 | struct xfs_mount_args *args; |
73 | 74 | ||
@@ -80,8 +81,8 @@ xfs_args_allocate( | |||
80 | args->flags |= XFSMNT_DIRSYNC; | 81 | args->flags |= XFSMNT_DIRSYNC; |
81 | if (sb->s_flags & MS_SYNCHRONOUS) | 82 | if (sb->s_flags & MS_SYNCHRONOUS) |
82 | args->flags |= XFSMNT_WSYNC; | 83 | args->flags |= XFSMNT_WSYNC; |
83 | 84 | if (silent) | |
84 | /* Default to 32 bit inodes on Linux all the time */ | 85 | args->flags |= XFSMNT_QUIET; |
85 | args->flags |= XFSMNT_32BITINODES; | 86 | args->flags |= XFSMNT_32BITINODES; |
86 | 87 | ||
87 | return args; | 88 | return args; |
@@ -719,7 +720,7 @@ xfs_fs_remount( | |||
719 | char *options) | 720 | char *options) |
720 | { | 721 | { |
721 | vfs_t *vfsp = vfs_from_sb(sb); | 722 | vfs_t *vfsp = vfs_from_sb(sb); |
722 | struct xfs_mount_args *args = xfs_args_allocate(sb); | 723 | struct xfs_mount_args *args = xfs_args_allocate(sb, 0); |
723 | int error; | 724 | int error; |
724 | 725 | ||
725 | VFS_PARSEARGS(vfsp, options, args, 1, error); | 726 | VFS_PARSEARGS(vfsp, options, args, 1, error); |
@@ -825,7 +826,7 @@ xfs_fs_fill_super( | |||
825 | { | 826 | { |
826 | vnode_t *rootvp; | 827 | vnode_t *rootvp; |
827 | struct vfs *vfsp = vfs_allocate(sb); | 828 | struct vfs *vfsp = vfs_allocate(sb); |
828 | struct xfs_mount_args *args = xfs_args_allocate(sb); | 829 | struct xfs_mount_args *args = xfs_args_allocate(sb, silent); |
829 | struct kstatfs statvfs; | 830 | struct kstatfs statvfs; |
830 | int error, error2; | 831 | int error, error2; |
831 | 832 | ||
diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h index 06f5845e9568..6f1c79a28f8b 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.h +++ b/fs/xfs/linux-2.6/xfs_vnode.h | |||
@@ -173,6 +173,12 @@ typedef ssize_t (*vop_write_t)(bhv_desc_t *, struct kiocb *, | |||
173 | typedef ssize_t (*vop_sendfile_t)(bhv_desc_t *, struct file *, | 173 | typedef ssize_t (*vop_sendfile_t)(bhv_desc_t *, struct file *, |
174 | loff_t *, int, size_t, read_actor_t, | 174 | loff_t *, int, size_t, read_actor_t, |
175 | void *, struct cred *); | 175 | void *, struct cred *); |
176 | typedef ssize_t (*vop_splice_read_t)(bhv_desc_t *, struct file *, | ||
177 | struct inode *, size_t, int, int, | ||
178 | struct cred *); | ||
179 | typedef ssize_t (*vop_splice_write_t)(bhv_desc_t *, struct inode *, | ||
180 | struct file *, size_t, int, int, | ||
181 | struct cred *); | ||
176 | typedef int (*vop_ioctl_t)(bhv_desc_t *, struct inode *, struct file *, | 182 | typedef int (*vop_ioctl_t)(bhv_desc_t *, struct inode *, struct file *, |
177 | int, unsigned int, void __user *); | 183 | int, unsigned int, void __user *); |
178 | typedef int (*vop_getattr_t)(bhv_desc_t *, struct vattr *, int, | 184 | typedef int (*vop_getattr_t)(bhv_desc_t *, struct vattr *, int, |
@@ -231,6 +237,8 @@ typedef struct vnodeops { | |||
231 | vop_read_t vop_read; | 237 | vop_read_t vop_read; |
232 | vop_write_t vop_write; | 238 | vop_write_t vop_write; |
233 | vop_sendfile_t vop_sendfile; | 239 | vop_sendfile_t vop_sendfile; |
240 | vop_splice_read_t vop_splice_read; | ||
241 | vop_splice_write_t vop_splice_write; | ||
234 | vop_ioctl_t vop_ioctl; | 242 | vop_ioctl_t vop_ioctl; |
235 | vop_getattr_t vop_getattr; | 243 | vop_getattr_t vop_getattr; |
236 | vop_setattr_t vop_setattr; | 244 | vop_setattr_t vop_setattr; |
@@ -276,6 +284,10 @@ typedef struct vnodeops { | |||
276 | rv = _VOP_(vop_write, vp)((vp)->v_fbhv,file,iov,segs,offset,ioflags,cr) | 284 | rv = _VOP_(vop_write, vp)((vp)->v_fbhv,file,iov,segs,offset,ioflags,cr) |
277 | #define VOP_SENDFILE(vp,f,off,ioflags,cnt,act,targ,cr,rv) \ | 285 | #define VOP_SENDFILE(vp,f,off,ioflags,cnt,act,targ,cr,rv) \ |
278 | rv = _VOP_(vop_sendfile, vp)((vp)->v_fbhv,f,off,ioflags,cnt,act,targ,cr) | 286 | rv = _VOP_(vop_sendfile, vp)((vp)->v_fbhv,f,off,ioflags,cnt,act,targ,cr) |
287 | #define VOP_SPLICE_READ(vp,f,pipe,cnt,fl,iofl,cr,rv) \ | ||
288 | rv = _VOP_(vop_splice_read, vp)((vp)->v_fbhv,f,pipe,cnt,fl,iofl,cr) | ||
289 | #define VOP_SPLICE_WRITE(vp,f,pipe,cnt,fl,iofl,cr,rv) \ | ||
290 | rv = _VOP_(vop_splice_write, vp)((vp)->v_fbhv,f,pipe,cnt,fl,iofl,cr) | ||
279 | #define VOP_BMAP(vp,of,sz,rw,b,n,rv) \ | 291 | #define VOP_BMAP(vp,of,sz,rw,b,n,rv) \ |
280 | rv = _VOP_(vop_bmap, vp)((vp)->v_fbhv,of,sz,rw,b,n) | 292 | rv = _VOP_(vop_bmap, vp)((vp)->v_fbhv,of,sz,rw,b,n) |
281 | #define VOP_OPEN(vp, cr, rv) \ | 293 | #define VOP_OPEN(vp, cr, rv) \ |
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c index 73c1e5e80c07..7fb5eca9bd50 100644 --- a/fs/xfs/quota/xfs_qm.c +++ b/fs/xfs/quota/xfs_qm.c | |||
@@ -2624,7 +2624,7 @@ xfs_qm_vop_chown_reserve( | |||
2624 | { | 2624 | { |
2625 | int error; | 2625 | int error; |
2626 | xfs_mount_t *mp; | 2626 | xfs_mount_t *mp; |
2627 | uint delblks, blkflags; | 2627 | uint delblks, blkflags, prjflags = 0; |
2628 | xfs_dquot_t *unresudq, *unresgdq, *delblksudq, *delblksgdq; | 2628 | xfs_dquot_t *unresudq, *unresgdq, *delblksudq, *delblksgdq; |
2629 | 2629 | ||
2630 | ASSERT(XFS_ISLOCKED_INODE(ip)); | 2630 | ASSERT(XFS_ISLOCKED_INODE(ip)); |
@@ -2650,10 +2650,13 @@ xfs_qm_vop_chown_reserve( | |||
2650 | } | 2650 | } |
2651 | } | 2651 | } |
2652 | if (XFS_IS_OQUOTA_ON(ip->i_mount) && gdqp) { | 2652 | if (XFS_IS_OQUOTA_ON(ip->i_mount) && gdqp) { |
2653 | if ((XFS_IS_GQUOTA_ON(ip->i_mount) && | 2653 | if (XFS_IS_PQUOTA_ON(ip->i_mount) && |
2654 | ip->i_d.di_gid != be32_to_cpu(gdqp->q_core.d_id)) || | 2654 | ip->i_d.di_projid != be32_to_cpu(gdqp->q_core.d_id)) |
2655 | (XFS_IS_PQUOTA_ON(ip->i_mount) && | 2655 | prjflags = XFS_QMOPT_ENOSPC; |
2656 | ip->i_d.di_projid != be32_to_cpu(gdqp->q_core.d_id))) { | 2656 | |
2657 | if (prjflags || | ||
2658 | (XFS_IS_GQUOTA_ON(ip->i_mount) && | ||
2659 | ip->i_d.di_gid != be32_to_cpu(gdqp->q_core.d_id))) { | ||
2657 | delblksgdq = gdqp; | 2660 | delblksgdq = gdqp; |
2658 | if (delblks) { | 2661 | if (delblks) { |
2659 | ASSERT(ip->i_gdquot); | 2662 | ASSERT(ip->i_gdquot); |
@@ -2664,7 +2667,7 @@ xfs_qm_vop_chown_reserve( | |||
2664 | 2667 | ||
2665 | if ((error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount, | 2668 | if ((error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount, |
2666 | delblksudq, delblksgdq, ip->i_d.di_nblocks, 1, | 2669 | delblksudq, delblksgdq, ip->i_d.di_nblocks, 1, |
2667 | flags | blkflags))) | 2670 | flags | blkflags | prjflags))) |
2668 | return (error); | 2671 | return (error); |
2669 | 2672 | ||
2670 | /* | 2673 | /* |
@@ -2681,7 +2684,7 @@ xfs_qm_vop_chown_reserve( | |||
2681 | ASSERT(unresudq || unresgdq); | 2684 | ASSERT(unresudq || unresgdq); |
2682 | if ((error = xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount, | 2685 | if ((error = xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount, |
2683 | delblksudq, delblksgdq, (xfs_qcnt_t)delblks, 0, | 2686 | delblksudq, delblksgdq, (xfs_qcnt_t)delblks, 0, |
2684 | flags | blkflags))) | 2687 | flags | blkflags | prjflags))) |
2685 | return (error); | 2688 | return (error); |
2686 | xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount, | 2689 | xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount, |
2687 | unresudq, unresgdq, -((xfs_qcnt_t)delblks), 0, | 2690 | unresudq, unresgdq, -((xfs_qcnt_t)delblks), 0, |
diff --git a/fs/xfs/quota/xfs_trans_dquot.c b/fs/xfs/quota/xfs_trans_dquot.c index d8e131ec0aa8..9168918db252 100644 --- a/fs/xfs/quota/xfs_trans_dquot.c +++ b/fs/xfs/quota/xfs_trans_dquot.c | |||
@@ -595,12 +595,19 @@ xfs_trans_unreserve_and_mod_dquots( | |||
595 | } | 595 | } |
596 | } | 596 | } |
597 | 597 | ||
598 | STATIC int | ||
599 | xfs_quota_error(uint flags) | ||
600 | { | ||
601 | if (flags & XFS_QMOPT_ENOSPC) | ||
602 | return ENOSPC; | ||
603 | return EDQUOT; | ||
604 | } | ||
605 | |||
598 | /* | 606 | /* |
599 | * This reserves disk blocks and inodes against a dquot. | 607 | * This reserves disk blocks and inodes against a dquot. |
600 | * Flags indicate if the dquot is to be locked here and also | 608 | * Flags indicate if the dquot is to be locked here and also |
601 | * if the blk reservation is for RT or regular blocks. | 609 | * if the blk reservation is for RT or regular blocks. |
602 | * Sending in XFS_QMOPT_FORCE_RES flag skips the quota check. | 610 | * Sending in XFS_QMOPT_FORCE_RES flag skips the quota check. |
603 | * Returns EDQUOT if quota is exceeded. | ||
604 | */ | 611 | */ |
605 | STATIC int | 612 | STATIC int |
606 | xfs_trans_dqresv( | 613 | xfs_trans_dqresv( |
@@ -666,19 +673,15 @@ xfs_trans_dqresv( | |||
666 | */ | 673 | */ |
667 | if (hardlimit > 0ULL && | 674 | if (hardlimit > 0ULL && |
668 | (hardlimit <= nblks + *resbcountp)) { | 675 | (hardlimit <= nblks + *resbcountp)) { |
669 | error = EDQUOT; | 676 | error = xfs_quota_error(flags); |
670 | goto error_return; | 677 | goto error_return; |
671 | } | 678 | } |
672 | 679 | ||
673 | if (softlimit > 0ULL && | 680 | if (softlimit > 0ULL && |
674 | (softlimit <= nblks + *resbcountp)) { | 681 | (softlimit <= nblks + *resbcountp)) { |
675 | /* | ||
676 | * If timer or warnings has expired, | ||
677 | * return EDQUOT | ||
678 | */ | ||
679 | if ((timer != 0 && get_seconds() > timer) || | 682 | if ((timer != 0 && get_seconds() > timer) || |
680 | (warns != 0 && warns >= warnlimit)) { | 683 | (warns != 0 && warns >= warnlimit)) { |
681 | error = EDQUOT; | 684 | error = xfs_quota_error(flags); |
682 | goto error_return; | 685 | goto error_return; |
683 | } | 686 | } |
684 | } | 687 | } |
@@ -695,16 +698,12 @@ xfs_trans_dqresv( | |||
695 | if (!softlimit) | 698 | if (!softlimit) |
696 | softlimit = q->qi_isoftlimit; | 699 | softlimit = q->qi_isoftlimit; |
697 | if (hardlimit > 0ULL && count >= hardlimit) { | 700 | if (hardlimit > 0ULL && count >= hardlimit) { |
698 | error = EDQUOT; | 701 | error = xfs_quota_error(flags); |
699 | goto error_return; | 702 | goto error_return; |
700 | } else if (softlimit > 0ULL && count >= softlimit) { | 703 | } else if (softlimit > 0ULL && count >= softlimit) { |
701 | /* | ||
702 | * If timer or warnings has expired, | ||
703 | * return EDQUOT | ||
704 | */ | ||
705 | if ((timer != 0 && get_seconds() > timer) || | 704 | if ((timer != 0 && get_seconds() > timer) || |
706 | (warns != 0 && warns >= warnlimit)) { | 705 | (warns != 0 && warns >= warnlimit)) { |
707 | error = EDQUOT; | 706 | error = xfs_quota_error(flags); |
708 | goto error_return; | 707 | goto error_return; |
709 | } | 708 | } |
710 | } | 709 | } |
@@ -751,13 +750,14 @@ error_return: | |||
751 | 750 | ||
752 | 751 | ||
753 | /* | 752 | /* |
754 | * Given a dquot(s), make disk block and/or inode reservations against them. | 753 | * Given dquot(s), make disk block and/or inode reservations against them. |
755 | * The fact that this does the reservation against both the usr and | 754 | * The fact that this does the reservation against both the usr and |
756 | * grp quotas is important, because this follows a both-or-nothing | 755 | * grp/prj quotas is important, because this follows a both-or-nothing |
757 | * approach. | 756 | * approach. |
758 | * | 757 | * |
759 | * flags = XFS_QMOPT_DQLOCK indicate if dquot(s) need to be locked. | 758 | * flags = XFS_QMOPT_DQLOCK indicate if dquot(s) need to be locked. |
760 | * XFS_QMOPT_FORCE_RES evades limit enforcement. Used by chown. | 759 | * XFS_QMOPT_FORCE_RES evades limit enforcement. Used by chown. |
760 | * XFS_QMOPT_ENOSPC returns ENOSPC not EDQUOT. Used by pquota. | ||
761 | * XFS_TRANS_DQ_RES_BLKS reserves regular disk blocks | 761 | * XFS_TRANS_DQ_RES_BLKS reserves regular disk blocks |
762 | * XFS_TRANS_DQ_RES_RTBLKS reserves realtime disk blocks | 762 | * XFS_TRANS_DQ_RES_RTBLKS reserves realtime disk blocks |
763 | * dquots are unlocked on return, if they were not locked by caller. | 763 | * dquots are unlocked on return, if they were not locked by caller. |
@@ -772,25 +772,27 @@ xfs_trans_reserve_quota_bydquots( | |||
772 | long ninos, | 772 | long ninos, |
773 | uint flags) | 773 | uint flags) |
774 | { | 774 | { |
775 | int resvd; | 775 | int resvd = 0, error; |
776 | 776 | ||
777 | if (! XFS_IS_QUOTA_ON(mp)) | 777 | if (!XFS_IS_QUOTA_ON(mp)) |
778 | return (0); | 778 | return 0; |
779 | 779 | ||
780 | if (tp && tp->t_dqinfo == NULL) | 780 | if (tp && tp->t_dqinfo == NULL) |
781 | xfs_trans_alloc_dqinfo(tp); | 781 | xfs_trans_alloc_dqinfo(tp); |
782 | 782 | ||
783 | ASSERT(flags & XFS_QMOPT_RESBLK_MASK); | 783 | ASSERT(flags & XFS_QMOPT_RESBLK_MASK); |
784 | resvd = 0; | ||
785 | 784 | ||
786 | if (udqp) { | 785 | if (udqp) { |
787 | if (xfs_trans_dqresv(tp, mp, udqp, nblks, ninos, flags)) | 786 | error = xfs_trans_dqresv(tp, mp, udqp, nblks, ninos, |
788 | return (EDQUOT); | 787 | (flags & ~XFS_QMOPT_ENOSPC)); |
788 | if (error) | ||
789 | return error; | ||
789 | resvd = 1; | 790 | resvd = 1; |
790 | } | 791 | } |
791 | 792 | ||
792 | if (gdqp) { | 793 | if (gdqp) { |
793 | if (xfs_trans_dqresv(tp, mp, gdqp, nblks, ninos, flags)) { | 794 | error = xfs_trans_dqresv(tp, mp, gdqp, nblks, ninos, flags); |
795 | if (error) { | ||
794 | /* | 796 | /* |
795 | * can't do it, so backout previous reservation | 797 | * can't do it, so backout previous reservation |
796 | */ | 798 | */ |
@@ -799,14 +801,14 @@ xfs_trans_reserve_quota_bydquots( | |||
799 | xfs_trans_dqresv(tp, mp, udqp, | 801 | xfs_trans_dqresv(tp, mp, udqp, |
800 | -nblks, -ninos, flags); | 802 | -nblks, -ninos, flags); |
801 | } | 803 | } |
802 | return (EDQUOT); | 804 | return error; |
803 | } | 805 | } |
804 | } | 806 | } |
805 | 807 | ||
806 | /* | 808 | /* |
807 | * Didn't change anything critical, so, no need to log | 809 | * Didn't change anything critical, so, no need to log |
808 | */ | 810 | */ |
809 | return (0); | 811 | return 0; |
810 | } | 812 | } |
811 | 813 | ||
812 | 814 | ||
@@ -814,8 +816,6 @@ xfs_trans_reserve_quota_bydquots( | |||
814 | * Lock the dquot and change the reservation if we can. | 816 | * Lock the dquot and change the reservation if we can. |
815 | * This doesn't change the actual usage, just the reservation. | 817 | * This doesn't change the actual usage, just the reservation. |
816 | * The inode sent in is locked. | 818 | * The inode sent in is locked. |
817 | * | ||
818 | * Returns 0 on success, EDQUOT or other errors otherwise | ||
819 | */ | 819 | */ |
820 | STATIC int | 820 | STATIC int |
821 | xfs_trans_reserve_quota_nblks( | 821 | xfs_trans_reserve_quota_nblks( |
@@ -824,20 +824,24 @@ xfs_trans_reserve_quota_nblks( | |||
824 | xfs_inode_t *ip, | 824 | xfs_inode_t *ip, |
825 | long nblks, | 825 | long nblks, |
826 | long ninos, | 826 | long ninos, |
827 | uint type) | 827 | uint flags) |
828 | { | 828 | { |
829 | int error; | 829 | int error; |
830 | 830 | ||
831 | if (!XFS_IS_QUOTA_ON(mp)) | 831 | if (!XFS_IS_QUOTA_ON(mp)) |
832 | return (0); | 832 | return 0; |
833 | if (XFS_IS_PQUOTA_ON(mp)) | ||
834 | flags |= XFS_QMOPT_ENOSPC; | ||
833 | 835 | ||
834 | ASSERT(ip->i_ino != mp->m_sb.sb_uquotino); | 836 | ASSERT(ip->i_ino != mp->m_sb.sb_uquotino); |
835 | ASSERT(ip->i_ino != mp->m_sb.sb_gquotino); | 837 | ASSERT(ip->i_ino != mp->m_sb.sb_gquotino); |
836 | 838 | ||
837 | ASSERT(XFS_ISLOCKED_INODE_EXCL(ip)); | 839 | ASSERT(XFS_ISLOCKED_INODE_EXCL(ip)); |
838 | ASSERT(XFS_IS_QUOTA_RUNNING(ip->i_mount)); | 840 | ASSERT(XFS_IS_QUOTA_RUNNING(ip->i_mount)); |
839 | ASSERT((type & ~XFS_QMOPT_FORCE_RES) == XFS_TRANS_DQ_RES_RTBLKS || | 841 | ASSERT((flags & ~(XFS_QMOPT_FORCE_RES | XFS_QMOPT_ENOSPC)) == |
840 | (type & ~XFS_QMOPT_FORCE_RES) == XFS_TRANS_DQ_RES_BLKS); | 842 | XFS_TRANS_DQ_RES_RTBLKS || |
843 | (flags & ~(XFS_QMOPT_FORCE_RES | XFS_QMOPT_ENOSPC)) == | ||
844 | XFS_TRANS_DQ_RES_BLKS); | ||
841 | 845 | ||
842 | /* | 846 | /* |
843 | * Reserve nblks against these dquots, with trans as the mediator. | 847 | * Reserve nblks against these dquots, with trans as the mediator. |
@@ -845,8 +849,8 @@ xfs_trans_reserve_quota_nblks( | |||
845 | error = xfs_trans_reserve_quota_bydquots(tp, mp, | 849 | error = xfs_trans_reserve_quota_bydquots(tp, mp, |
846 | ip->i_udquot, ip->i_gdquot, | 850 | ip->i_udquot, ip->i_gdquot, |
847 | nblks, ninos, | 851 | nblks, ninos, |
848 | type); | 852 | flags); |
849 | return (error); | 853 | return error; |
850 | } | 854 | } |
851 | 855 | ||
852 | /* | 856 | /* |
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index d384e489705f..26939d364bc4 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c | |||
@@ -4719,18 +4719,17 @@ xfs_bmapi( | |||
4719 | /* | 4719 | /* |
4720 | * Make a transaction-less quota reservation for | 4720 | * Make a transaction-less quota reservation for |
4721 | * delayed allocation blocks. This number gets | 4721 | * delayed allocation blocks. This number gets |
4722 | * adjusted later. | 4722 | * adjusted later. We return if we haven't |
4723 | * We return EDQUOT if we haven't allocated | 4723 | * allocated blocks already inside this loop. |
4724 | * blks already inside this loop; | ||
4725 | */ | 4724 | */ |
4726 | if (XFS_TRANS_RESERVE_QUOTA_NBLKS( | 4725 | if ((error = XFS_TRANS_RESERVE_QUOTA_NBLKS( |
4727 | mp, NULL, ip, (long)alen, 0, | 4726 | mp, NULL, ip, (long)alen, 0, |
4728 | rt ? XFS_QMOPT_RES_RTBLKS : | 4727 | rt ? XFS_QMOPT_RES_RTBLKS : |
4729 | XFS_QMOPT_RES_REGBLKS)) { | 4728 | XFS_QMOPT_RES_REGBLKS))) { |
4730 | if (n == 0) { | 4729 | if (n == 0) { |
4731 | *nmap = 0; | 4730 | *nmap = 0; |
4732 | ASSERT(cur == NULL); | 4731 | ASSERT(cur == NULL); |
4733 | return XFS_ERROR(EDQUOT); | 4732 | return error; |
4734 | } | 4733 | } |
4735 | break; | 4734 | break; |
4736 | } | 4735 | } |
diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h index f83399c89ce3..8e0d73d9ccc4 100644 --- a/fs/xfs/xfs_bmap.h +++ b/fs/xfs/xfs_bmap.h | |||
@@ -353,10 +353,11 @@ xfs_check_nostate_extents( | |||
353 | xfs_extnum_t num); | 353 | xfs_extnum_t num); |
354 | 354 | ||
355 | /* | 355 | /* |
356 | * Call xfs_bmap_do_search_extents() to search for the extent | 356 | * Search the extent records for the entry containing block bno. |
357 | * record containing block bno. If in multi-level in-core extent | 357 | * If bno lies in a hole, point to the next entry. If bno lies |
358 | * allocation mode, find and extract the target extent buffer, | 358 | * past eof, *eofp will be set, and *prevp will contain the last |
359 | * otherwise just use the direct extent list. | 359 | * entry (null if none). Else, *lastxp will be set to the index |
360 | * of the found entry; *gotp will contain the entry. | ||
360 | */ | 361 | */ |
361 | xfs_bmbt_rec_t * | 362 | xfs_bmbt_rec_t * |
362 | xfs_bmap_search_multi_extents(struct xfs_ifork *, xfs_fileoff_t, int *, | 363 | xfs_bmap_search_multi_extents(struct xfs_ifork *, xfs_fileoff_t, int *, |
diff --git a/fs/xfs/xfs_clnt.h b/fs/xfs/xfs_clnt.h index 022fff62085b..5b7eb81453be 100644 --- a/fs/xfs/xfs_clnt.h +++ b/fs/xfs/xfs_clnt.h | |||
@@ -68,6 +68,7 @@ struct xfs_mount_args { | |||
68 | * enforcement */ | 68 | * enforcement */ |
69 | #define XFSMNT_PQUOTAENF 0x00000040 /* IRIX project quota limit | 69 | #define XFSMNT_PQUOTAENF 0x00000040 /* IRIX project quota limit |
70 | * enforcement */ | 70 | * enforcement */ |
71 | #define XFSMNT_QUIET 0x00000080 /* don't report mount errors */ | ||
71 | #define XFSMNT_NOALIGN 0x00000200 /* don't allocate at | 72 | #define XFSMNT_NOALIGN 0x00000200 /* don't allocate at |
72 | * stripe boundaries*/ | 73 | * stripe boundaries*/ |
73 | #define XFSMNT_RETERR 0x00000400 /* return error to user */ | 74 | #define XFSMNT_RETERR 0x00000400 /* return error to user */ |
diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h index 26b8e709a569..bc43163456ef 100644 --- a/fs/xfs/xfs_error.h +++ b/fs/xfs/xfs_error.h | |||
@@ -186,4 +186,7 @@ extern void xfs_fs_cmn_err(int level, struct xfs_mount *mp, char *fmt, ...); | |||
186 | #define xfs_fs_repair_cmn_err(level, mp, fmt, args...) \ | 186 | #define xfs_fs_repair_cmn_err(level, mp, fmt, args...) \ |
187 | xfs_fs_cmn_err(level, mp, fmt " Unmount and run xfs_repair.", ## args) | 187 | xfs_fs_cmn_err(level, mp, fmt " Unmount and run xfs_repair.", ## args) |
188 | 188 | ||
189 | #define xfs_fs_mount_cmn_err(f, fmt, args...) \ | ||
190 | ((f & XFS_MFSI_QUIET)? cmn_err(CE_WARN, "XFS: " fmt, ## args) : (void)0) | ||
191 | |||
189 | #endif /* __XFS_ERROR_H__ */ | 192 | #endif /* __XFS_ERROR_H__ */ |
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 72e7e78bfff8..049fabb7f7e0 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c | |||
@@ -213,7 +213,8 @@ xfs_mount_free( | |||
213 | STATIC int | 213 | STATIC int |
214 | xfs_mount_validate_sb( | 214 | xfs_mount_validate_sb( |
215 | xfs_mount_t *mp, | 215 | xfs_mount_t *mp, |
216 | xfs_sb_t *sbp) | 216 | xfs_sb_t *sbp, |
217 | int flags) | ||
217 | { | 218 | { |
218 | /* | 219 | /* |
219 | * If the log device and data device have the | 220 | * If the log device and data device have the |
@@ -223,33 +224,29 @@ xfs_mount_validate_sb( | |||
223 | * a volume filesystem in a non-volume manner. | 224 | * a volume filesystem in a non-volume manner. |
224 | */ | 225 | */ |
225 | if (sbp->sb_magicnum != XFS_SB_MAGIC) { | 226 | if (sbp->sb_magicnum != XFS_SB_MAGIC) { |
226 | cmn_err(CE_WARN, "XFS: bad magic number"); | 227 | xfs_fs_mount_cmn_err(flags, "bad magic number"); |
227 | return XFS_ERROR(EWRONGFS); | 228 | return XFS_ERROR(EWRONGFS); |
228 | } | 229 | } |
229 | 230 | ||
230 | if (!XFS_SB_GOOD_VERSION(sbp)) { | 231 | if (!XFS_SB_GOOD_VERSION(sbp)) { |
231 | cmn_err(CE_WARN, "XFS: bad version"); | 232 | xfs_fs_mount_cmn_err(flags, "bad version"); |
232 | return XFS_ERROR(EWRONGFS); | 233 | return XFS_ERROR(EWRONGFS); |
233 | } | 234 | } |
234 | 235 | ||
235 | if (unlikely( | 236 | if (unlikely( |
236 | sbp->sb_logstart == 0 && mp->m_logdev_targp == mp->m_ddev_targp)) { | 237 | sbp->sb_logstart == 0 && mp->m_logdev_targp == mp->m_ddev_targp)) { |
237 | cmn_err(CE_WARN, | 238 | xfs_fs_mount_cmn_err(flags, |
238 | "XFS: filesystem is marked as having an external log; " | 239 | "filesystem is marked as having an external log; " |
239 | "specify logdev on the\nmount command line."); | 240 | "specify logdev on the\nmount command line."); |
240 | XFS_CORRUPTION_ERROR("xfs_mount_validate_sb(1)", | 241 | return XFS_ERROR(EINVAL); |
241 | XFS_ERRLEVEL_HIGH, mp, sbp); | ||
242 | return XFS_ERROR(EFSCORRUPTED); | ||
243 | } | 242 | } |
244 | 243 | ||
245 | if (unlikely( | 244 | if (unlikely( |
246 | sbp->sb_logstart != 0 && mp->m_logdev_targp != mp->m_ddev_targp)) { | 245 | sbp->sb_logstart != 0 && mp->m_logdev_targp != mp->m_ddev_targp)) { |
247 | cmn_err(CE_WARN, | 246 | xfs_fs_mount_cmn_err(flags, |
248 | "XFS: filesystem is marked as having an internal log; " | 247 | "filesystem is marked as having an internal log; " |
249 | "don't specify logdev on\nthe mount command line."); | 248 | "do not specify logdev on\nthe mount command line."); |
250 | XFS_CORRUPTION_ERROR("xfs_mount_validate_sb(2)", | 249 | return XFS_ERROR(EINVAL); |
251 | XFS_ERRLEVEL_HIGH, mp, sbp); | ||
252 | return XFS_ERROR(EFSCORRUPTED); | ||
253 | } | 250 | } |
254 | 251 | ||
255 | /* | 252 | /* |
@@ -274,9 +271,7 @@ xfs_mount_validate_sb( | |||
274 | (sbp->sb_rextsize * sbp->sb_blocksize > XFS_MAX_RTEXTSIZE) || | 271 | (sbp->sb_rextsize * sbp->sb_blocksize > XFS_MAX_RTEXTSIZE) || |
275 | (sbp->sb_rextsize * sbp->sb_blocksize < XFS_MIN_RTEXTSIZE) || | 272 | (sbp->sb_rextsize * sbp->sb_blocksize < XFS_MIN_RTEXTSIZE) || |
276 | (sbp->sb_imax_pct > 100 || sbp->sb_imax_pct < 1))) { | 273 | (sbp->sb_imax_pct > 100 || sbp->sb_imax_pct < 1))) { |
277 | cmn_err(CE_WARN, "XFS: SB sanity check 1 failed"); | 274 | xfs_fs_mount_cmn_err(flags, "SB sanity check 1 failed"); |
278 | XFS_CORRUPTION_ERROR("xfs_mount_validate_sb(3)", | ||
279 | XFS_ERRLEVEL_LOW, mp, sbp); | ||
280 | return XFS_ERROR(EFSCORRUPTED); | 275 | return XFS_ERROR(EFSCORRUPTED); |
281 | } | 276 | } |
282 | 277 | ||
@@ -289,9 +284,7 @@ xfs_mount_validate_sb( | |||
289 | (xfs_drfsbno_t)sbp->sb_agcount * sbp->sb_agblocks || | 284 | (xfs_drfsbno_t)sbp->sb_agcount * sbp->sb_agblocks || |
290 | sbp->sb_dblocks < (xfs_drfsbno_t)(sbp->sb_agcount - 1) * | 285 | sbp->sb_dblocks < (xfs_drfsbno_t)(sbp->sb_agcount - 1) * |
291 | sbp->sb_agblocks + XFS_MIN_AG_BLOCKS)) { | 286 | sbp->sb_agblocks + XFS_MIN_AG_BLOCKS)) { |
292 | cmn_err(CE_WARN, "XFS: SB sanity check 2 failed"); | 287 | xfs_fs_mount_cmn_err(flags, "SB sanity check 2 failed"); |
293 | XFS_ERROR_REPORT("xfs_mount_validate_sb(4)", | ||
294 | XFS_ERRLEVEL_LOW, mp); | ||
295 | return XFS_ERROR(EFSCORRUPTED); | 288 | return XFS_ERROR(EFSCORRUPTED); |
296 | } | 289 | } |
297 | 290 | ||
@@ -307,15 +300,13 @@ xfs_mount_validate_sb( | |||
307 | (sbp->sb_dblocks << (sbp->sb_blocklog - BBSHIFT)) > UINT_MAX || | 300 | (sbp->sb_dblocks << (sbp->sb_blocklog - BBSHIFT)) > UINT_MAX || |
308 | (sbp->sb_rblocks << (sbp->sb_blocklog - BBSHIFT)) > UINT_MAX)) { | 301 | (sbp->sb_rblocks << (sbp->sb_blocklog - BBSHIFT)) > UINT_MAX)) { |
309 | #endif | 302 | #endif |
310 | cmn_err(CE_WARN, | 303 | xfs_fs_mount_cmn_err(flags, |
311 | "XFS: File system is too large to be mounted on this system."); | 304 | "file system too large to be mounted on this system."); |
312 | return XFS_ERROR(E2BIG); | 305 | return XFS_ERROR(E2BIG); |
313 | } | 306 | } |
314 | 307 | ||
315 | if (unlikely(sbp->sb_inprogress)) { | 308 | if (unlikely(sbp->sb_inprogress)) { |
316 | cmn_err(CE_WARN, "XFS: file system busy"); | 309 | xfs_fs_mount_cmn_err(flags, "file system busy"); |
317 | XFS_ERROR_REPORT("xfs_mount_validate_sb(5)", | ||
318 | XFS_ERRLEVEL_LOW, mp); | ||
319 | return XFS_ERROR(EFSCORRUPTED); | 310 | return XFS_ERROR(EFSCORRUPTED); |
320 | } | 311 | } |
321 | 312 | ||
@@ -323,8 +314,8 @@ xfs_mount_validate_sb( | |||
323 | * Version 1 directory format has never worked on Linux. | 314 | * Version 1 directory format has never worked on Linux. |
324 | */ | 315 | */ |
325 | if (unlikely(!XFS_SB_VERSION_HASDIRV2(sbp))) { | 316 | if (unlikely(!XFS_SB_VERSION_HASDIRV2(sbp))) { |
326 | cmn_err(CE_WARN, | 317 | xfs_fs_mount_cmn_err(flags, |
327 | "XFS: Attempted to mount file system using version 1 directory format"); | 318 | "file system using version 1 directory format"); |
328 | return XFS_ERROR(ENOSYS); | 319 | return XFS_ERROR(ENOSYS); |
329 | } | 320 | } |
330 | 321 | ||
@@ -332,11 +323,11 @@ xfs_mount_validate_sb( | |||
332 | * Until this is fixed only page-sized or smaller data blocks work. | 323 | * Until this is fixed only page-sized or smaller data blocks work. |
333 | */ | 324 | */ |
334 | if (unlikely(sbp->sb_blocksize > PAGE_SIZE)) { | 325 | if (unlikely(sbp->sb_blocksize > PAGE_SIZE)) { |
335 | cmn_err(CE_WARN, | 326 | xfs_fs_mount_cmn_err(flags, |
336 | "XFS: Attempted to mount file system with blocksize %d bytes", | 327 | "file system with blocksize %d bytes", |
337 | sbp->sb_blocksize); | 328 | sbp->sb_blocksize); |
338 | cmn_err(CE_WARN, | 329 | xfs_fs_mount_cmn_err(flags, |
339 | "XFS: Only page-sized (%ld) or less blocksizes currently work.", | 330 | "only pagesize (%ld) or less will currently work.", |
340 | PAGE_SIZE); | 331 | PAGE_SIZE); |
341 | return XFS_ERROR(ENOSYS); | 332 | return XFS_ERROR(ENOSYS); |
342 | } | 333 | } |
@@ -484,7 +475,7 @@ xfs_xlatesb( | |||
484 | * Does the initial read of the superblock. | 475 | * Does the initial read of the superblock. |
485 | */ | 476 | */ |
486 | int | 477 | int |
487 | xfs_readsb(xfs_mount_t *mp) | 478 | xfs_readsb(xfs_mount_t *mp, int flags) |
488 | { | 479 | { |
489 | unsigned int sector_size; | 480 | unsigned int sector_size; |
490 | unsigned int extra_flags; | 481 | unsigned int extra_flags; |
@@ -506,7 +497,7 @@ xfs_readsb(xfs_mount_t *mp) | |||
506 | bp = xfs_buf_read_flags(mp->m_ddev_targp, XFS_SB_DADDR, | 497 | bp = xfs_buf_read_flags(mp->m_ddev_targp, XFS_SB_DADDR, |
507 | BTOBB(sector_size), extra_flags); | 498 | BTOBB(sector_size), extra_flags); |
508 | if (!bp || XFS_BUF_ISERROR(bp)) { | 499 | if (!bp || XFS_BUF_ISERROR(bp)) { |
509 | cmn_err(CE_WARN, "XFS: SB read failed"); | 500 | xfs_fs_mount_cmn_err(flags, "SB read failed"); |
510 | error = bp ? XFS_BUF_GETERROR(bp) : ENOMEM; | 501 | error = bp ? XFS_BUF_GETERROR(bp) : ENOMEM; |
511 | goto fail; | 502 | goto fail; |
512 | } | 503 | } |
@@ -520,9 +511,9 @@ xfs_readsb(xfs_mount_t *mp) | |||
520 | sbp = XFS_BUF_TO_SBP(bp); | 511 | sbp = XFS_BUF_TO_SBP(bp); |
521 | xfs_xlatesb(XFS_BUF_PTR(bp), &(mp->m_sb), 1, XFS_SB_ALL_BITS); | 512 | xfs_xlatesb(XFS_BUF_PTR(bp), &(mp->m_sb), 1, XFS_SB_ALL_BITS); |
522 | 513 | ||
523 | error = xfs_mount_validate_sb(mp, &(mp->m_sb)); | 514 | error = xfs_mount_validate_sb(mp, &(mp->m_sb), flags); |
524 | if (error) { | 515 | if (error) { |
525 | cmn_err(CE_WARN, "XFS: SB validate failed"); | 516 | xfs_fs_mount_cmn_err(flags, "SB validate failed"); |
526 | goto fail; | 517 | goto fail; |
527 | } | 518 | } |
528 | 519 | ||
@@ -530,8 +521,8 @@ xfs_readsb(xfs_mount_t *mp) | |||
530 | * We must be able to do sector-sized and sector-aligned IO. | 521 | * We must be able to do sector-sized and sector-aligned IO. |
531 | */ | 522 | */ |
532 | if (sector_size > mp->m_sb.sb_sectsize) { | 523 | if (sector_size > mp->m_sb.sb_sectsize) { |
533 | cmn_err(CE_WARN, | 524 | xfs_fs_mount_cmn_err(flags, |
534 | "XFS: device supports only %u byte sectors (not %u)", | 525 | "device supports only %u byte sectors (not %u)", |
535 | sector_size, mp->m_sb.sb_sectsize); | 526 | sector_size, mp->m_sb.sb_sectsize); |
536 | error = ENOSYS; | 527 | error = ENOSYS; |
537 | goto fail; | 528 | goto fail; |
@@ -548,7 +539,7 @@ xfs_readsb(xfs_mount_t *mp) | |||
548 | bp = xfs_buf_read_flags(mp->m_ddev_targp, XFS_SB_DADDR, | 539 | bp = xfs_buf_read_flags(mp->m_ddev_targp, XFS_SB_DADDR, |
549 | BTOBB(sector_size), extra_flags); | 540 | BTOBB(sector_size), extra_flags); |
550 | if (!bp || XFS_BUF_ISERROR(bp)) { | 541 | if (!bp || XFS_BUF_ISERROR(bp)) { |
551 | cmn_err(CE_WARN, "XFS: SB re-read failed"); | 542 | xfs_fs_mount_cmn_err(flags, "SB re-read failed"); |
552 | error = bp ? XFS_BUF_GETERROR(bp) : ENOMEM; | 543 | error = bp ? XFS_BUF_GETERROR(bp) : ENOMEM; |
553 | goto fail; | 544 | goto fail; |
554 | } | 545 | } |
@@ -678,7 +669,7 @@ xfs_mountfs( | |||
678 | int error = 0; | 669 | int error = 0; |
679 | 670 | ||
680 | if (mp->m_sb_bp == NULL) { | 671 | if (mp->m_sb_bp == NULL) { |
681 | if ((error = xfs_readsb(mp))) { | 672 | if ((error = xfs_readsb(mp, mfsi_flags))) { |
682 | return error; | 673 | return error; |
683 | } | 674 | } |
684 | } | 675 | } |
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 66cbee79864e..668ad23fd37c 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h | |||
@@ -510,9 +510,12 @@ xfs_preferred_iosize(xfs_mount_t *mp) | |||
510 | */ | 510 | */ |
511 | #define XFS_MFSI_SECOND 0x01 /* Secondary mount -- skip stuff */ | 511 | #define XFS_MFSI_SECOND 0x01 /* Secondary mount -- skip stuff */ |
512 | #define XFS_MFSI_CLIENT 0x02 /* Is a client -- skip lots of stuff */ | 512 | #define XFS_MFSI_CLIENT 0x02 /* Is a client -- skip lots of stuff */ |
513 | /* XFS_MFSI_RRINODES */ | ||
513 | #define XFS_MFSI_NOUNLINK 0x08 /* Skip unlinked inode processing in */ | 514 | #define XFS_MFSI_NOUNLINK 0x08 /* Skip unlinked inode processing in */ |
514 | /* log recovery */ | 515 | /* log recovery */ |
515 | #define XFS_MFSI_NO_QUOTACHECK 0x10 /* Skip quotacheck processing */ | 516 | #define XFS_MFSI_NO_QUOTACHECK 0x10 /* Skip quotacheck processing */ |
517 | /* XFS_MFSI_CONVERT_SUNIT */ | ||
518 | #define XFS_MFSI_QUIET 0x40 /* Be silent if mount errors found */ | ||
516 | 519 | ||
517 | /* | 520 | /* |
518 | * Macros for getting from mount to vfs and back. | 521 | * Macros for getting from mount to vfs and back. |
@@ -581,7 +584,7 @@ extern int xfs_mod_incore_sb_unlocked(xfs_mount_t *, xfs_sb_field_t, | |||
581 | extern int xfs_mod_incore_sb_batch(xfs_mount_t *, xfs_mod_sb_t *, | 584 | extern int xfs_mod_incore_sb_batch(xfs_mount_t *, xfs_mod_sb_t *, |
582 | uint, int); | 585 | uint, int); |
583 | extern struct xfs_buf *xfs_getsb(xfs_mount_t *, int); | 586 | extern struct xfs_buf *xfs_getsb(xfs_mount_t *, int); |
584 | extern int xfs_readsb(xfs_mount_t *mp); | 587 | extern int xfs_readsb(xfs_mount_t *, int); |
585 | extern void xfs_freesb(xfs_mount_t *); | 588 | extern void xfs_freesb(xfs_mount_t *); |
586 | extern void xfs_do_force_shutdown(bhv_desc_t *, int, char *, int); | 589 | extern void xfs_do_force_shutdown(bhv_desc_t *, int, char *, int); |
587 | extern int xfs_syncsub(xfs_mount_t *, int, int, int *); | 590 | extern int xfs_syncsub(xfs_mount_t *, int, int, int *); |
diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h index 4f6a034de7f7..7fbef974bce6 100644 --- a/fs/xfs/xfs_quota.h +++ b/fs/xfs/xfs_quota.h | |||
@@ -196,10 +196,11 @@ typedef struct xfs_qoff_logformat { | |||
196 | #define XFS_QMOPT_QUOTAOFF 0x0000080 /* quotas are being turned off */ | 196 | #define XFS_QMOPT_QUOTAOFF 0x0000080 /* quotas are being turned off */ |
197 | #define XFS_QMOPT_UMOUNTING 0x0000100 /* filesys is being unmounted */ | 197 | #define XFS_QMOPT_UMOUNTING 0x0000100 /* filesys is being unmounted */ |
198 | #define XFS_QMOPT_DOLOG 0x0000200 /* log buf changes (in quotacheck) */ | 198 | #define XFS_QMOPT_DOLOG 0x0000200 /* log buf changes (in quotacheck) */ |
199 | #define XFS_QMOPT_DOWARN 0x0000400 /* increase warning cnt if necessary */ | 199 | #define XFS_QMOPT_DOWARN 0x0000400 /* increase warning cnt if needed */ |
200 | #define XFS_QMOPT_ILOCKED 0x0000800 /* inode is already locked (excl) */ | 200 | #define XFS_QMOPT_ILOCKED 0x0000800 /* inode is already locked (excl) */ |
201 | #define XFS_QMOPT_DQREPAIR 0x0001000 /* repair dquot, if damaged. */ | 201 | #define XFS_QMOPT_DQREPAIR 0x0001000 /* repair dquot if damaged */ |
202 | #define XFS_QMOPT_GQUOTA 0x0002000 /* group dquot requested */ | 202 | #define XFS_QMOPT_GQUOTA 0x0002000 /* group dquot requested */ |
203 | #define XFS_QMOPT_ENOSPC 0x0004000 /* enospc instead of edquot (prj) */ | ||
203 | 204 | ||
204 | /* | 205 | /* |
205 | * flags to xfs_trans_mod_dquot to indicate which field needs to be | 206 | * flags to xfs_trans_mod_dquot to indicate which field needs to be |
diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c index 504d2a80747a..f0e09ca14139 100644 --- a/fs/xfs/xfs_vfsops.c +++ b/fs/xfs/xfs_vfsops.c | |||
@@ -442,6 +442,9 @@ xfs_mount( | |||
442 | p = vfs_bhv_lookup(vfsp, VFS_POSITION_IO); | 442 | p = vfs_bhv_lookup(vfsp, VFS_POSITION_IO); |
443 | mp->m_io_ops = p ? *(xfs_ioops_t *) vfs_bhv_custom(p) : xfs_iocore_xfs; | 443 | mp->m_io_ops = p ? *(xfs_ioops_t *) vfs_bhv_custom(p) : xfs_iocore_xfs; |
444 | 444 | ||
445 | if (args->flags & XFSMNT_QUIET) | ||
446 | flags |= XFS_MFSI_QUIET; | ||
447 | |||
445 | /* | 448 | /* |
446 | * Open real time and log devices - order is important. | 449 | * Open real time and log devices - order is important. |
447 | */ | 450 | */ |
@@ -492,7 +495,7 @@ xfs_mount( | |||
492 | error = xfs_start_flags(vfsp, args, mp); | 495 | error = xfs_start_flags(vfsp, args, mp); |
493 | if (error) | 496 | if (error) |
494 | goto error1; | 497 | goto error1; |
495 | error = xfs_readsb(mp); | 498 | error = xfs_readsb(mp, flags); |
496 | if (error) | 499 | if (error) |
497 | goto error1; | 500 | goto error1; |
498 | error = xfs_finish_flags(vfsp, args, mp); | 501 | error = xfs_finish_flags(vfsp, args, mp); |
@@ -1697,8 +1700,9 @@ xfs_parseargs( | |||
1697 | int dsunit, dswidth, vol_dsunit, vol_dswidth; | 1700 | int dsunit, dswidth, vol_dsunit, vol_dswidth; |
1698 | int iosize; | 1701 | int iosize; |
1699 | 1702 | ||
1700 | args->flags2 |= XFSMNT2_COMPAT_IOSIZE; | ||
1701 | args->flags |= XFSMNT_IDELETE; | 1703 | args->flags |= XFSMNT_IDELETE; |
1704 | args->flags |= XFSMNT_BARRIER; | ||
1705 | args->flags2 |= XFSMNT2_COMPAT_IOSIZE; | ||
1702 | 1706 | ||
1703 | if (!options) | 1707 | if (!options) |
1704 | goto done; | 1708 | goto done; |
@@ -1947,8 +1951,6 @@ xfs_showargs( | |||
1947 | seq_printf(m, "," MNTOPT_IKEEP); | 1951 | seq_printf(m, "," MNTOPT_IKEEP); |
1948 | if (!(mp->m_flags & XFS_MOUNT_COMPAT_IOSIZE)) | 1952 | if (!(mp->m_flags & XFS_MOUNT_COMPAT_IOSIZE)) |
1949 | seq_printf(m, "," MNTOPT_LARGEIO); | 1953 | seq_printf(m, "," MNTOPT_LARGEIO); |
1950 | if (mp->m_flags & XFS_MOUNT_BARRIER) | ||
1951 | seq_printf(m, "," MNTOPT_BARRIER); | ||
1952 | 1954 | ||
1953 | if (!(vfsp->vfs_flag & VFS_32BITINODES)) | 1955 | if (!(vfsp->vfs_flag & VFS_32BITINODES)) |
1954 | seq_printf(m, "," MNTOPT_64BITINODE); | 1956 | seq_printf(m, "," MNTOPT_64BITINODE); |
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index de49601919c1..fa71b305ba5c 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c | |||
@@ -4649,6 +4649,10 @@ vnodeops_t xfs_vnodeops = { | |||
4649 | #ifdef HAVE_SENDFILE | 4649 | #ifdef HAVE_SENDFILE |
4650 | .vop_sendfile = xfs_sendfile, | 4650 | .vop_sendfile = xfs_sendfile, |
4651 | #endif | 4651 | #endif |
4652 | #ifdef HAVE_SPLICE | ||
4653 | .vop_splice_read = xfs_splice_read, | ||
4654 | .vop_splice_write = xfs_splice_write, | ||
4655 | #endif | ||
4652 | .vop_write = xfs_write, | 4656 | .vop_write = xfs_write, |
4653 | .vop_ioctl = xfs_ioctl, | 4657 | .vop_ioctl = xfs_ioctl, |
4654 | .vop_getattr = xfs_getattr, | 4658 | .vop_getattr = xfs_getattr, |
diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200_mci.h b/include/asm-arm/arch-at91rm9200/at91rm9200_mci.h new file mode 100644 index 000000000000..f28636d61e39 --- /dev/null +++ b/include/asm-arm/arch-at91rm9200/at91rm9200_mci.h | |||
@@ -0,0 +1,104 @@ | |||
1 | /* | ||
2 | * include/asm-arm/arch-at91rm9200/at91rm9200_mci.h | ||
3 | * | ||
4 | * Copyright (C) 2005 Ivan Kokshaysky | ||
5 | * Copyright (C) SAN People | ||
6 | * | ||
7 | * MultiMedia Card Interface (MCI) registers. | ||
8 | * Based on AT91RM9200 datasheet revision E. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | */ | ||
15 | |||
16 | #ifndef AT91RM9200_MCI_H | ||
17 | #define AT91RM9200_MCI_H | ||
18 | |||
19 | #define AT91_MCI_CR 0x00 /* Control Register */ | ||
20 | #define AT91_MCI_MCIEN (1 << 0) /* Multi-Media Interface Enable */ | ||
21 | #define AT91_MCI_MCIDIS (1 << 1) /* Multi-Media Interface Disable */ | ||
22 | #define AT91_MCI_PWSEN (1 << 2) /* Power Save Mode Enable */ | ||
23 | #define AT91_MCI_PWSDIS (1 << 3) /* Power Save Mode Disable */ | ||
24 | #define AT91_MCI_SWRST (1 << 7) /* Software Reset */ | ||
25 | |||
26 | #define AT91_MCI_MR 0x04 /* Mode Register */ | ||
27 | #define AT91_MCI_CLKDIV (0xff << 0) /* Clock Divider */ | ||
28 | #define AT91_MCI_PWSDIV (3 << 8) /* Power Saving Divider */ | ||
29 | #define AT91_MCI_PDCPADV (1 << 14) /* PDC Padding Value */ | ||
30 | #define AT91_MCI_PDCMODE (1 << 15) /* PDC-orientated Mode */ | ||
31 | #define AT91_MCI_BLKLEN (0xfff << 18) /* Data Block Length */ | ||
32 | |||
33 | #define AT91_MCI_DTOR 0x08 /* Data Timeout Register */ | ||
34 | #define AT91_MCI_DTOCYC (0xf << 0) /* Data Timeout Cycle Number */ | ||
35 | #define AT91_MCI_DTOMUL (7 << 4) /* Data Timeout Multiplier */ | ||
36 | #define AT91_MCI_DTOMUL_1 (0 << 4) | ||
37 | #define AT91_MCI_DTOMUL_16 (1 << 4) | ||
38 | #define AT91_MCI_DTOMUL_128 (2 << 4) | ||
39 | #define AT91_MCI_DTOMUL_256 (3 << 4) | ||
40 | #define AT91_MCI_DTOMUL_1K (4 << 4) | ||
41 | #define AT91_MCI_DTOMUL_4K (5 << 4) | ||
42 | #define AT91_MCI_DTOMUL_64K (6 << 4) | ||
43 | #define AT91_MCI_DTOMUL_1M (7 << 4) | ||
44 | |||
45 | #define AT91_MCI_SDCR 0x0c /* SD Card Register */ | ||
46 | #define AT91_MCI_SDCSEL (0xf << 0) /* SD Card Selector */ | ||
47 | #define AT91_MCI_SDCBUS (1 << 7) /* 1-bit or 4-bit bus */ | ||
48 | |||
49 | #define AT91_MCI_ARGR 0x10 /* Argument Register */ | ||
50 | |||
51 | #define AT91_MCI_CMDR 0x14 /* Command Register */ | ||
52 | #define AT91_MCI_CMDNB (0x3f << 0) /* Command Number */ | ||
53 | #define AT91_MCI_RSPTYP (3 << 6) /* Response Type */ | ||
54 | #define AT91_MCI_RSPTYP_NONE (0 << 6) | ||
55 | #define AT91_MCI_RSPTYP_48 (1 << 6) | ||
56 | #define AT91_MCI_RSPTYP_136 (2 << 6) | ||
57 | #define AT91_MCI_SPCMD (7 << 8) /* Special Command */ | ||
58 | #define AT91_MCI_SPCMD_NONE (0 << 8) | ||
59 | #define AT91_MCI_SPCMD_INIT (1 << 8) | ||
60 | #define AT91_MCI_SPCMD_SYNC (2 << 8) | ||
61 | #define AT91_MCI_SPCMD_ICMD (4 << 8) | ||
62 | #define AT91_MCI_SPCMD_IRESP (5 << 8) | ||
63 | #define AT91_MCI_OPDCMD (1 << 11) /* Open Drain Command */ | ||
64 | #define AT91_MCI_MAXLAT (1 << 12) /* Max Latency for Command to Response */ | ||
65 | #define AT91_MCI_TRCMD (3 << 16) /* Transfer Command */ | ||
66 | #define AT91_MCI_TRCMD_NONE (0 << 16) | ||
67 | #define AT91_MCI_TRCMD_START (1 << 16) | ||
68 | #define AT91_MCI_TRCMD_STOP (2 << 16) | ||
69 | #define AT91_MCI_TRDIR (1 << 18) /* Transfer Direction */ | ||
70 | #define AT91_MCI_TRTYP (3 << 19) /* Transfer Type */ | ||
71 | #define AT91_MCI_TRTYP_BLOCK (0 << 19) | ||
72 | #define AT91_MCI_TRTYP_MULTIPLE (1 << 19) | ||
73 | #define AT91_MCI_TRTYP_STREAM (2 << 19) | ||
74 | |||
75 | #define AT91_MCI_RSPR(n) (0x20 + ((n) * 4)) /* Response Registers 0-3 */ | ||
76 | #define AT91_MCR_RDR 0x30 /* Receive Data Register */ | ||
77 | #define AT91_MCR_TDR 0x34 /* Transmit Data Register */ | ||
78 | |||
79 | #define AT91_MCI_SR 0x40 /* Status Register */ | ||
80 | #define AT91_MCI_CMDRDY (1 << 0) /* Command Ready */ | ||
81 | #define AT91_MCI_RXRDY (1 << 1) /* Receiver Ready */ | ||
82 | #define AT91_MCI_TXRDY (1 << 2) /* Transmit Ready */ | ||
83 | #define AT91_MCI_BLKE (1 << 3) /* Data Block Ended */ | ||
84 | #define AT91_MCI_DTIP (1 << 4) /* Data Transfer in Progress */ | ||
85 | #define AT91_MCI_NOTBUSY (1 << 5) /* Data Not Busy */ | ||
86 | #define AT91_MCI_ENDRX (1 << 6) /* End of RX Buffer */ | ||
87 | #define AT91_MCI_ENDTX (1 << 7) /* End fo TX Buffer */ | ||
88 | #define AT91_MCI_RXBUFF (1 << 14) /* RX Buffer Full */ | ||
89 | #define AT91_MCI_TXBUFE (1 << 15) /* TX Buffer Empty */ | ||
90 | #define AT91_MCI_RINDE (1 << 16) /* Response Index Error */ | ||
91 | #define AT91_MCI_RDIRE (1 << 17) /* Response Direction Error */ | ||
92 | #define AT91_MCI_RCRCE (1 << 18) /* Response CRC Error */ | ||
93 | #define AT91_MCI_RENDE (1 << 19) /* Response End Bit Error */ | ||
94 | #define AT91_MCI_RTOE (1 << 20) /* Reponse Time-out Error */ | ||
95 | #define AT91_MCI_DCRCE (1 << 21) /* Data CRC Error */ | ||
96 | #define AT91_MCI_DTOE (1 << 22) /* Data Time-out Error */ | ||
97 | #define AT91_MCI_OVRE (1 << 30) /* Overrun */ | ||
98 | #define AT91_MCI_UNRE (1 << 31) /* Underrun */ | ||
99 | |||
100 | #define AT91_MCI_IER 0x44 /* Interrupt Enable Register */ | ||
101 | #define AT91_MCI_IDR 0x48 /* Interrupt Disable Register */ | ||
102 | #define AT91_MCI_IMR 0x4c /* Interrupt Mask Register */ | ||
103 | |||
104 | #endif | ||
diff --git a/include/asm-arm/arch-at91rm9200/board.h b/include/asm-arm/arch-at91rm9200/board.h index 2e7d1139a799..4fdef13d01d4 100644 --- a/include/asm-arm/arch-at91rm9200/board.h +++ b/include/asm-arm/arch-at91rm9200/board.h | |||
@@ -38,6 +38,8 @@ extern unsigned long at91_master_clock; | |||
38 | extern int at91_serial_map[AT91_NR_UART]; | 38 | extern int at91_serial_map[AT91_NR_UART]; |
39 | extern int at91_console_port; | 39 | extern int at91_console_port; |
40 | 40 | ||
41 | #include <linux/mtd/partitions.h> | ||
42 | |||
41 | /* USB Device */ | 43 | /* USB Device */ |
42 | struct at91_udc_data { | 44 | struct at91_udc_data { |
43 | u8 vbus_pin; /* high == host powering us */ | 45 | u8 vbus_pin; /* high == host powering us */ |
@@ -77,4 +79,26 @@ struct at91_usbh_data { | |||
77 | }; | 79 | }; |
78 | extern void __init at91_add_device_usbh(struct at91_usbh_data *data); | 80 | extern void __init at91_add_device_usbh(struct at91_usbh_data *data); |
79 | 81 | ||
82 | /* NAND / SmartMedia */ | ||
83 | struct at91_nand_data { | ||
84 | u8 enable_pin; /* chip enable */ | ||
85 | u8 det_pin; /* card detect */ | ||
86 | u8 rdy_pin; /* ready/busy */ | ||
87 | u8 ale; /* address line number connected to ALE */ | ||
88 | u8 cle; /* address line number connected to CLE */ | ||
89 | struct mtd_partition* (*partition_info)(int, int*); | ||
90 | }; | ||
91 | extern void __init at91_add_device_nand(struct at91_nand_data *data); | ||
92 | |||
93 | /* I2C*/ | ||
94 | void __init at91_add_device_i2c(void); | ||
95 | |||
96 | /* RTC */ | ||
97 | void __init at91_add_device_rtc(void); | ||
98 | |||
99 | /* LEDs */ | ||
100 | extern u8 at91_leds_cpu; | ||
101 | extern u8 at91_leds_timer; | ||
102 | extern void __init at91_init_leds(u8 cpu_led, u8 timer_led); | ||
103 | |||
80 | #endif | 104 | #endif |
diff --git a/include/asm-arm/arch-ep93xx/ts72xx.h b/include/asm-arm/arch-ep93xx/ts72xx.h index 412215e77f44..a94f63ff0535 100644 --- a/include/asm-arm/arch-ep93xx/ts72xx.h +++ b/include/asm-arm/arch-ep93xx/ts72xx.h | |||
@@ -12,6 +12,8 @@ | |||
12 | * febfc000 [67]0000000 4K NAND data register | 12 | * febfc000 [67]0000000 4K NAND data register |
13 | * febfb000 [67]0400000 4K NAND control register | 13 | * febfb000 [67]0400000 4K NAND control register |
14 | * febfa000 [67]0800000 4K NAND busy register | 14 | * febfa000 [67]0800000 4K NAND busy register |
15 | * febf9000 10800000 4K TS-5620 RTC index register | ||
16 | * febf8000 11700000 4K TS-5620 RTC data register | ||
15 | */ | 17 | */ |
16 | 18 | ||
17 | #define TS72XX_MODEL_PHYS_BASE 0x22000000 | 19 | #define TS72XX_MODEL_PHYS_BASE 0x22000000 |
@@ -58,6 +60,15 @@ | |||
58 | #define TS72XX_NAND_BUSY_SIZE 0x00001000 | 60 | #define TS72XX_NAND_BUSY_SIZE 0x00001000 |
59 | 61 | ||
60 | 62 | ||
63 | #define TS72XX_RTC_INDEX_VIRT_BASE 0xfebf9000 | ||
64 | #define TS72XX_RTC_INDEX_PHYS_BASE 0x10800000 | ||
65 | #define TS72XX_RTC_INDEX_SIZE 0x00001000 | ||
66 | |||
67 | #define TS72XX_RTC_DATA_VIRT_BASE 0xfebf8000 | ||
68 | #define TS72XX_RTC_DATA_PHYS_BASE 0x11700000 | ||
69 | #define TS72XX_RTC_DATA_SIZE 0x00001000 | ||
70 | |||
71 | |||
61 | #ifndef __ASSEMBLY__ | 72 | #ifndef __ASSEMBLY__ |
62 | #include <asm/io.h> | 73 | #include <asm/io.h> |
63 | 74 | ||
diff --git a/include/asm-arm/arch-imx/dma.h b/include/asm-arm/arch-imx/dma.h index b45fa367d71e..621ff2c730f2 100644 --- a/include/asm-arm/arch-imx/dma.h +++ b/include/asm-arm/arch-imx/dma.h | |||
@@ -17,27 +17,16 @@ | |||
17 | * along with this program; if not, write to the Free Software | 17 | * along with this program; if not, write to the Free Software |
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 | */ | 19 | */ |
20 | |||
20 | #ifndef __ASM_ARCH_DMA_H | 21 | #ifndef __ASM_ARCH_DMA_H |
21 | #define __ASM_ARCH_DMA_H | 22 | #define __ASM_ARCH_DMA_H |
22 | 23 | ||
23 | /* | ||
24 | * DMA registration | ||
25 | */ | ||
26 | |||
27 | typedef enum { | 24 | typedef enum { |
28 | DMA_PRIO_HIGH = 0, | 25 | DMA_PRIO_HIGH = 0, |
29 | DMA_PRIO_MEDIUM = 3, | 26 | DMA_PRIO_MEDIUM = 1, |
30 | DMA_PRIO_LOW = 6 | 27 | DMA_PRIO_LOW = 2 |
31 | } imx_dma_prio; | 28 | } imx_dma_prio; |
32 | 29 | ||
33 | int imx_request_dma(char *name, imx_dma_prio prio, | ||
34 | void (*irq_handler) (int, void *, struct pt_regs *), | ||
35 | void (*err_handler) (int, void *, struct pt_regs *), | ||
36 | void *data); | ||
37 | |||
38 | void imx_free_dma(int dma_ch); | ||
39 | |||
40 | |||
41 | #define DMA_REQ_UART3_T 2 | 30 | #define DMA_REQ_UART3_T 2 |
42 | #define DMA_REQ_UART3_R 3 | 31 | #define DMA_REQ_UART3_R 3 |
43 | #define DMA_REQ_SSI2_T 4 | 32 | #define DMA_REQ_SSI2_T 4 |
diff --git a/include/asm-arm/arch-imx/imx-dma.h b/include/asm-arm/arch-imx/imx-dma.h new file mode 100644 index 000000000000..f2063c1d610d --- /dev/null +++ b/include/asm-arm/arch-imx/imx-dma.h | |||
@@ -0,0 +1,90 @@ | |||
1 | /* | ||
2 | * linux/include/asm-arm/imxads/dma.h | ||
3 | * | ||
4 | * Copyright (C) 1997,1998 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 as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #include <asm/dma.h> | ||
22 | |||
23 | #ifndef __ASM_ARCH_IMX_DMA_H | ||
24 | #define __ASM_ARCH_IMX_DMA_H | ||
25 | |||
26 | #define IMX_DMA_CHANNELS 11 | ||
27 | |||
28 | /* | ||
29 | * struct imx_dma_channel - i.MX specific DMA extension | ||
30 | * @name: name specified by DMA client | ||
31 | * @irq_handler: client callback for end of transfer | ||
32 | * @err_handler: client callback for error condition | ||
33 | * @data: clients context data for callbacks | ||
34 | * @dma_mode: direction of the transfer %DMA_MODE_READ or %DMA_MODE_WRITE | ||
35 | * @sg: pointer to the actual read/written chunk for scatter-gather emulation | ||
36 | * @sgbc: counter of processed bytes in the actual read/written chunk | ||
37 | * @resbytes: total residual number of bytes to transfer | ||
38 | * (it can be lower or same as sum of SG mapped chunk sizes) | ||
39 | * @sgcount: number of chunks to be read/written | ||
40 | * | ||
41 | * Structure is used for IMX DMA processing. It would be probably good | ||
42 | * @struct dma_struct in the future for external interfacing and use | ||
43 | * @struct imx_dma_channel only as extension to it. | ||
44 | */ | ||
45 | |||
46 | struct imx_dma_channel { | ||
47 | const char *name; | ||
48 | void (*irq_handler) (int, void *, struct pt_regs *); | ||
49 | void (*err_handler) (int, void *, struct pt_regs *); | ||
50 | void *data; | ||
51 | dmamode_t dma_mode; | ||
52 | struct scatterlist *sg; | ||
53 | unsigned int sgbc; | ||
54 | unsigned int sgcount; | ||
55 | unsigned int resbytes; | ||
56 | int dma_num; | ||
57 | }; | ||
58 | |||
59 | extern struct imx_dma_channel imx_dma_channels[IMX_DMA_CHANNELS]; | ||
60 | |||
61 | |||
62 | /* The type to distinguish channel numbers parameter from ordinal int type */ | ||
63 | typedef int imx_dmach_t; | ||
64 | |||
65 | int | ||
66 | imx_dma_setup_single(imx_dmach_t dma_ch, dma_addr_t dma_address, | ||
67 | unsigned int dma_length, unsigned int dev_addr, dmamode_t dmamode); | ||
68 | |||
69 | int | ||
70 | imx_dma_setup_sg(imx_dmach_t dma_ch, | ||
71 | struct scatterlist *sg, unsigned int sgcount, unsigned int dma_length, | ||
72 | unsigned int dev_addr, dmamode_t dmamode); | ||
73 | |||
74 | int | ||
75 | imx_dma_setup_handlers(imx_dmach_t dma_ch, | ||
76 | void (*irq_handler) (int, void *, struct pt_regs *), | ||
77 | void (*err_handler) (int, void *, struct pt_regs *), void *data); | ||
78 | |||
79 | void imx_dma_enable(imx_dmach_t dma_ch); | ||
80 | |||
81 | void imx_dma_disable(imx_dmach_t dma_ch); | ||
82 | |||
83 | int imx_dma_request(imx_dmach_t dma_ch, const char *name); | ||
84 | |||
85 | void imx_dma_free(imx_dmach_t dma_ch); | ||
86 | |||
87 | int imx_dma_request_by_prio(imx_dmach_t *pdma_ch, const char *name, imx_dma_prio prio); | ||
88 | |||
89 | |||
90 | #endif /* _ASM_ARCH_IMX_DMA_H */ | ||
diff --git a/include/asm-arm/arch-imx/mmc.h b/include/asm-arm/arch-imx/mmc.h new file mode 100644 index 000000000000..1937151665c7 --- /dev/null +++ b/include/asm-arm/arch-imx/mmc.h | |||
@@ -0,0 +1,12 @@ | |||
1 | #ifndef ASMARM_ARCH_MMC_H | ||
2 | #define ASMARM_ARCH_MMC_H | ||
3 | |||
4 | #include <linux/mmc/protocol.h> | ||
5 | |||
6 | struct imxmmc_platform_data { | ||
7 | int (*card_present)(void); | ||
8 | }; | ||
9 | |||
10 | extern void imx_set_mmc_info(struct imxmmc_platform_data *info); | ||
11 | |||
12 | #endif | ||
diff --git a/include/asm-arm/arch-ixp23xx/memory.h b/include/asm-arm/arch-ixp23xx/memory.h index bebcf0aa0d72..6e19f46d54d1 100644 --- a/include/asm-arm/arch-ixp23xx/memory.h +++ b/include/asm-arm/arch-ixp23xx/memory.h | |||
@@ -28,6 +28,7 @@ | |||
28 | * to an address that the kernel can use. | 28 | * to an address that the kernel can use. |
29 | */ | 29 | */ |
30 | #ifndef __ASSEMBLY__ | 30 | #ifndef __ASSEMBLY__ |
31 | #include <asm/mach-types.h> | ||
31 | 32 | ||
32 | #define __virt_to_bus(v) \ | 33 | #define __virt_to_bus(v) \ |
33 | ({ unsigned int ret; \ | 34 | ({ unsigned int ret; \ |
@@ -40,6 +41,22 @@ | |||
40 | data = *((volatile int *)IXP23XX_PCI_SDRAM_BAR); \ | 41 | data = *((volatile int *)IXP23XX_PCI_SDRAM_BAR); \ |
41 | __phys_to_virt((((b - (data & 0xfffffff0)) + 0x00000000))); }) | 42 | __phys_to_virt((((b - (data & 0xfffffff0)) + 0x00000000))); }) |
42 | 43 | ||
44 | /* | ||
45 | * Coherency support. Only supported on A2 CPUs or on A1 | ||
46 | * systems that have the cache coherency workaround. | ||
47 | */ | ||
48 | static inline int __ixp23xx_arch_is_coherent(void) | ||
49 | { | ||
50 | extern unsigned int processor_id; | ||
51 | |||
52 | if (((processor_id & 15) >= 2) || machine_is_roadrunner()) | ||
53 | return 1; | ||
54 | |||
55 | return 0; | ||
56 | } | ||
57 | |||
58 | #define arch_is_coherent() __ixp23xx_arch_is_coherent() | ||
59 | |||
43 | #endif | 60 | #endif |
44 | 61 | ||
45 | 62 | ||
diff --git a/include/asm-arm/arch-ixp23xx/platform.h b/include/asm-arm/arch-ixp23xx/platform.h index f85b4685a491..e4d99060a049 100644 --- a/include/asm-arm/arch-ixp23xx/platform.h +++ b/include/asm-arm/arch-ixp23xx/platform.h | |||
@@ -22,6 +22,7 @@ void ixp23xx_sys_init(void); | |||
22 | int ixp23xx_pci_setup(int, struct pci_sys_data *); | 22 | int ixp23xx_pci_setup(int, struct pci_sys_data *); |
23 | void ixp23xx_pci_preinit(void); | 23 | void ixp23xx_pci_preinit(void); |
24 | struct pci_bus *ixp23xx_pci_scan_bus(int, struct pci_sys_data*); | 24 | struct pci_bus *ixp23xx_pci_scan_bus(int, struct pci_sys_data*); |
25 | void ixp23xx_pci_slave_init(void); | ||
25 | 26 | ||
26 | extern struct sys_timer ixp23xx_timer; | 27 | extern struct sys_timer ixp23xx_timer; |
27 | 28 | ||
diff --git a/include/asm-arm/arch-omap/aic23.h b/include/asm-arm/arch-omap/aic23.h index 590bac25b7c4..6513065941d0 100644 --- a/include/asm-arm/arch-omap/aic23.h +++ b/include/asm-arm/arch-omap/aic23.h | |||
@@ -57,6 +57,7 @@ | |||
57 | #define LHV_MIN 0x0000 | 57 | #define LHV_MIN 0x0000 |
58 | 58 | ||
59 | // Analog audio path control register | 59 | // Analog audio path control register |
60 | #define STA_REG(x) ((x)<<6) | ||
60 | #define STE_ENABLED 0x0020 | 61 | #define STE_ENABLED 0x0020 |
61 | #define DAC_SELECTED 0x0010 | 62 | #define DAC_SELECTED 0x0010 |
62 | #define BYPASS_ON 0x0008 | 63 | #define BYPASS_ON 0x0008 |
@@ -109,4 +110,7 @@ | |||
109 | #define TLV320AIC23ID1 (0x1a) // cs low | 110 | #define TLV320AIC23ID1 (0x1a) // cs low |
110 | #define TLV320AIC23ID2 (0x1b) // cs high | 111 | #define TLV320AIC23ID2 (0x1b) // cs high |
111 | 112 | ||
113 | void tlv320aic23_power_up(void); | ||
114 | void tlv320aic23_power_down(void); | ||
115 | |||
112 | #endif /* __ASM_ARCH_AIC23_H */ | 116 | #endif /* __ASM_ARCH_AIC23_H */ |
diff --git a/include/asm-arm/arch-omap/board-ams-delta.h b/include/asm-arm/arch-omap/board-ams-delta.h new file mode 100644 index 000000000000..0070f6d3b75c --- /dev/null +++ b/include/asm-arm/arch-omap/board-ams-delta.h | |||
@@ -0,0 +1,65 @@ | |||
1 | /* | ||
2 | * linux/include/asm-arm/arch-omap/board-ams-delta.h | ||
3 | * | ||
4 | * Copyright (C) 2006 Jonathan McDowell <noodles@earth.li> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | * | ||
11 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
12 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
13 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | ||
14 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
15 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
16 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
17 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
18 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
19 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
20 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License along | ||
23 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
24 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | #ifndef __ASM_ARCH_OMAP_AMS_DELTA_H | ||
27 | #define __ASM_ARCH_OMAP_AMS_DELTA_H | ||
28 | |||
29 | #if defined (CONFIG_MACH_AMS_DELTA) | ||
30 | |||
31 | #define AMS_DELTA_LATCH1_PHYS 0x01000000 | ||
32 | #define AMS_DELTA_LATCH1_VIRT 0xEA000000 | ||
33 | #define AMS_DELTA_MODEM_PHYS 0x04000000 | ||
34 | #define AMS_DELTA_MODEM_VIRT 0xEB000000 | ||
35 | #define AMS_DELTA_LATCH2_PHYS 0x08000000 | ||
36 | #define AMS_DELTA_LATCH2_VIRT 0xEC000000 | ||
37 | |||
38 | #define AMS_DELTA_LATCH1_LED_CAMERA 0x01 | ||
39 | #define AMS_DELTA_LATCH1_LED_ADVERT 0x02 | ||
40 | #define AMS_DELTA_LATCH1_LED_EMAIL 0x04 | ||
41 | #define AMS_DELTA_LATCH1_LED_HANDSFREE 0x08 | ||
42 | #define AMS_DELTA_LATCH1_LED_VOICEMAIL 0x10 | ||
43 | #define AMS_DELTA_LATCH1_LED_VOICE 0x20 | ||
44 | |||
45 | #define AMS_DELTA_LATCH2_LCD_VBLEN 0x0001 | ||
46 | #define AMS_DELTA_LATCH2_LCD_NDISP 0x0002 | ||
47 | #define AMS_DELTA_LATCH2_NAND_NCE 0x0004 | ||
48 | #define AMS_DELTA_LATCH2_NAND_NRE 0x0008 | ||
49 | #define AMS_DELTA_LATCH2_NAND_NWP 0x0010 | ||
50 | #define AMS_DELTA_LATCH2_NAND_NWE 0x0020 | ||
51 | #define AMS_DELTA_LATCH2_NAND_ALE 0x0040 | ||
52 | #define AMS_DELTA_LATCH2_NAND_CLE 0x0080 | ||
53 | #define AMS_DELTA_LATCH2_MODEM_NRESET 0x1000 | ||
54 | #define AMS_DELTA_LATCH2_MODEM_CODEC 0x2000 | ||
55 | |||
56 | #define AMS_DELTA_GPIO_PIN_NAND_RB 12 | ||
57 | |||
58 | #ifndef __ASSEMBLY__ | ||
59 | void ams_delta_latch1_write(u8 mask, u8 value); | ||
60 | void ams_delta_latch2_write(u16 mask, u16 value); | ||
61 | #endif | ||
62 | |||
63 | #endif /* CONFIG_MACH_AMS_DELTA */ | ||
64 | |||
65 | #endif /* __ASM_ARCH_OMAP_AMS_DELTA_H */ | ||
diff --git a/include/asm-arm/arch-omap/board-apollon.h b/include/asm-arm/arch-omap/board-apollon.h new file mode 100644 index 000000000000..de0c5b792c58 --- /dev/null +++ b/include/asm-arm/arch-omap/board-apollon.h | |||
@@ -0,0 +1,45 @@ | |||
1 | /* | ||
2 | * linux/include/asm-arm/arch-omap/board-apollon.h | ||
3 | * | ||
4 | * Hardware definitions for Samsung OMAP24XX Apollon board. | ||
5 | * | ||
6 | * Initial creation by Kyungmin Park <kyungmin.park@samsung.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
14 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
15 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | ||
16 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
17 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
18 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
19 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
20 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
21 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
22 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
23 | * | ||
24 | * You should have received a copy of the GNU General Public License along | ||
25 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
26 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
27 | */ | ||
28 | |||
29 | #ifndef __ASM_ARCH_OMAP_APOLLON_H | ||
30 | #define __ASM_ARCH_OMAP_APOLLON_H | ||
31 | |||
32 | /* Placeholder for APOLLON specific defines */ | ||
33 | /* GPMC CS0 */ | ||
34 | #define APOLLON_CS0_BASE 0x00000000 | ||
35 | /* GPMC CS1 */ | ||
36 | #define APOLLON_CS1_BASE 0x08000000 | ||
37 | #define APOLLON_ETHR_START (APOLLON_CS1_BASE + 0x300) | ||
38 | #define APOLLON_ETHR_GPIO_IRQ 74 | ||
39 | /* GPMC CS2 - reserved for OneNAND */ | ||
40 | #define APOLLON_CS2_BASE 0x10000000 | ||
41 | /* GPMC CS3 - reserved for NOR or NAND */ | ||
42 | #define APOLLON_CS3_BASE 0x18000000 | ||
43 | |||
44 | #endif /* __ASM_ARCH_OMAP_APOLLON_H */ | ||
45 | |||
diff --git a/include/asm-arm/arch-omap/board-h2.h b/include/asm-arm/arch-omap/board-h2.h index 39ca5a31aeea..b2888ef9e9b4 100644 --- a/include/asm-arm/arch-omap/board-h2.h +++ b/include/asm-arm/arch-omap/board-h2.h | |||
@@ -34,9 +34,5 @@ | |||
34 | /* At OMAP1610 Innovator the Ethernet is directly connected to CS1 */ | 34 | /* At OMAP1610 Innovator the Ethernet is directly connected to CS1 */ |
35 | #define OMAP1610_ETHR_START 0x04000300 | 35 | #define OMAP1610_ETHR_START 0x04000300 |
36 | 36 | ||
37 | /* Samsung NAND flash at CS2B or CS3(NAND Boot) */ | ||
38 | #define OMAP_NAND_FLASH_START1 0x0A000000 /* CS2B */ | ||
39 | #define OMAP_NAND_FLASH_START2 0x0C000000 /* CS3 */ | ||
40 | |||
41 | #endif /* __ASM_ARCH_OMAP_H2_H */ | 37 | #endif /* __ASM_ARCH_OMAP_H2_H */ |
42 | 38 | ||
diff --git a/include/asm-arm/arch-omap/board-h3.h b/include/asm-arm/arch-omap/board-h3.h index 1b12c1dcc2fa..761ea0a17897 100644 --- a/include/asm-arm/arch-omap/board-h3.h +++ b/include/asm-arm/arch-omap/board-h3.h | |||
@@ -30,10 +30,6 @@ | |||
30 | /* In OMAP1710 H3 the Ethernet is directly connected to CS1 */ | 30 | /* In OMAP1710 H3 the Ethernet is directly connected to CS1 */ |
31 | #define OMAP1710_ETHR_START 0x04000300 | 31 | #define OMAP1710_ETHR_START 0x04000300 |
32 | 32 | ||
33 | /* Samsung NAND flash at CS2B or CS3(NAND Boot) */ | ||
34 | #define OMAP_NAND_FLASH_START1 0x0A000000 /* CS2B */ | ||
35 | #define OMAP_NAND_FLASH_START2 0x0C000000 /* CS3 */ | ||
36 | |||
37 | #define MAXIRQNUM (IH_BOARD_BASE) | 33 | #define MAXIRQNUM (IH_BOARD_BASE) |
38 | #define MAXFIQNUM MAXIRQNUM | 34 | #define MAXFIQNUM MAXIRQNUM |
39 | #define MAXSWINUM MAXIRQNUM | 35 | #define MAXSWINUM MAXIRQNUM |
diff --git a/include/asm-arm/arch-omap/board-h4.h b/include/asm-arm/arch-omap/board-h4.h index 33ea29a41654..7ef664bc9e33 100644 --- a/include/asm-arm/arch-omap/board-h4.h +++ b/include/asm-arm/arch-omap/board-h4.h | |||
@@ -33,12 +33,6 @@ | |||
33 | /* GPMC CS1 */ | 33 | /* GPMC CS1 */ |
34 | #define OMAP24XX_ETHR_START 0x08000300 | 34 | #define OMAP24XX_ETHR_START 0x08000300 |
35 | #define OMAP24XX_ETHR_GPIO_IRQ 92 | 35 | #define OMAP24XX_ETHR_GPIO_IRQ 92 |
36 | 36 | #define H4_CS0_BASE 0x04000000 | |
37 | #define H4_CS0_BASE 0x04000000 | ||
38 | |||
39 | #define H4_CS0_BASE 0x04000000 | ||
40 | |||
41 | #define H4_CS0_BASE 0x04000000 | ||
42 | |||
43 | #endif /* __ASM_ARCH_OMAP_H4_H */ | 37 | #endif /* __ASM_ARCH_OMAP_H4_H */ |
44 | 38 | ||
diff --git a/include/asm-arm/arch-omap/board-netstar.h b/include/asm-arm/arch-omap/board-netstar.h deleted file mode 100644 index 77cc0fb54d54..000000000000 --- a/include/asm-arm/arch-omap/board-netstar.h +++ /dev/null | |||
@@ -1,19 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2004 2N Telekomunikace, Ladislav Michl <michl@2n.cz> | ||
3 | * | ||
4 | * Hardware definitions for OMAP5910 based NetStar board. | ||
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 | |||
11 | #ifndef __ASM_ARCH_NETSTAR_H | ||
12 | #define __ASM_ARCH_NETSTAR_H | ||
13 | |||
14 | #include <asm/arch/tc.h> | ||
15 | |||
16 | #define OMAP_NAND_FLASH_START1 OMAP_CS1_PHYS + (1 << 23) | ||
17 | #define OMAP_NAND_FLASH_START2 OMAP_CS1_PHYS + (2 << 23) | ||
18 | |||
19 | #endif /* __ASM_ARCH_NETSTAR_H */ | ||
diff --git a/include/asm-arm/arch-omap/board-nokia.h b/include/asm-arm/arch-omap/board-nokia.h new file mode 100644 index 000000000000..72deea203493 --- /dev/null +++ b/include/asm-arm/arch-omap/board-nokia.h | |||
@@ -0,0 +1,54 @@ | |||
1 | /* | ||
2 | * linux/include/asm-arm/arch-omap/board-nokia.h | ||
3 | * | ||
4 | * Information structures for Nokia-specific board config data | ||
5 | * | ||
6 | * Copyright (C) 2005 Nokia Corporation | ||
7 | */ | ||
8 | |||
9 | #ifndef _OMAP_BOARD_NOKIA_H | ||
10 | #define _OMAP_BOARD_NOKIA_H | ||
11 | |||
12 | #include <linux/types.h> | ||
13 | |||
14 | #define OMAP_TAG_NOKIA_BT 0x4e01 | ||
15 | #define OMAP_TAG_WLAN_CX3110X 0x4e02 | ||
16 | #define OMAP_TAG_CBUS 0x4e03 | ||
17 | #define OMAP_TAG_EM_ASIC_BB5 0x4e04 | ||
18 | |||
19 | |||
20 | #define BT_CHIP_CSR 1 | ||
21 | #define BT_CHIP_TI 2 | ||
22 | |||
23 | #define BT_SYSCLK_12 1 | ||
24 | #define BT_SYSCLK_38_4 2 | ||
25 | |||
26 | struct omap_bluetooth_config { | ||
27 | u8 chip_type; | ||
28 | u8 bt_wakeup_gpio; | ||
29 | u8 host_wakeup_gpio; | ||
30 | u8 reset_gpio; | ||
31 | u8 bt_uart; | ||
32 | u8 bd_addr[6]; | ||
33 | u8 bt_sysclk; | ||
34 | }; | ||
35 | |||
36 | struct omap_wlan_cx3110x_config { | ||
37 | u8 chip_type; | ||
38 | s16 power_gpio; | ||
39 | s16 irq_gpio; | ||
40 | s16 spi_cs_gpio; | ||
41 | }; | ||
42 | |||
43 | struct omap_cbus_config { | ||
44 | s16 clk_gpio; | ||
45 | s16 dat_gpio; | ||
46 | s16 sel_gpio; | ||
47 | }; | ||
48 | |||
49 | struct omap_em_asic_bb5_config { | ||
50 | s16 retu_irq_gpio; | ||
51 | s16 tahvo_irq_gpio; | ||
52 | }; | ||
53 | |||
54 | #endif | ||
diff --git a/include/asm-arm/arch-omap/board-perseus2.h b/include/asm-arm/arch-omap/board-perseus2.h index 691e52a52b43..eb74420cb439 100644 --- a/include/asm-arm/arch-omap/board-perseus2.h +++ b/include/asm-arm/arch-omap/board-perseus2.h | |||
@@ -42,8 +42,4 @@ | |||
42 | 42 | ||
43 | #define NR_IRQS (MAXIRQNUM + 1) | 43 | #define NR_IRQS (MAXIRQNUM + 1) |
44 | 44 | ||
45 | /* Samsung NAND flash at CS2B or CS3(NAND Boot) */ | ||
46 | #define OMAP_NAND_FLASH_START1 0x0A000000 /* CS2B */ | ||
47 | #define OMAP_NAND_FLASH_START2 0x0C000000 /* CS3 */ | ||
48 | |||
49 | #endif | 45 | #endif |
diff --git a/include/asm-arm/arch-omap/board.h b/include/asm-arm/arch-omap/board.h index a0040cd86639..6d6240a4681c 100644 --- a/include/asm-arm/arch-omap/board.h +++ b/include/asm-arm/arch-omap/board.h | |||
@@ -21,9 +21,12 @@ | |||
21 | #define OMAP_TAG_LCD 0x4f05 | 21 | #define OMAP_TAG_LCD 0x4f05 |
22 | #define OMAP_TAG_GPIO_SWITCH 0x4f06 | 22 | #define OMAP_TAG_GPIO_SWITCH 0x4f06 |
23 | #define OMAP_TAG_UART 0x4f07 | 23 | #define OMAP_TAG_UART 0x4f07 |
24 | #define OMAP_TAG_FBMEM 0x4f08 | ||
25 | #define OMAP_TAG_STI_CONSOLE 0x4f09 | ||
24 | 26 | ||
25 | #define OMAP_TAG_BOOT_REASON 0x4f80 | 27 | #define OMAP_TAG_BOOT_REASON 0x4f80 |
26 | #define OMAP_TAG_FLASH_PART 0x4f81 | 28 | #define OMAP_TAG_FLASH_PART 0x4f81 |
29 | #define OMAP_TAG_VERSION_STR 0x4f82 | ||
27 | 30 | ||
28 | struct omap_clock_config { | 31 | struct omap_clock_config { |
29 | /* 0 for 12 MHz, 1 for 13 MHz and 2 for 19.2 MHz */ | 32 | /* 0 for 12 MHz, 1 for 13 MHz and 2 for 19.2 MHz */ |
@@ -54,6 +57,11 @@ struct omap_serial_console_config { | |||
54 | u32 console_speed; | 57 | u32 console_speed; |
55 | }; | 58 | }; |
56 | 59 | ||
60 | struct omap_sti_console_config { | ||
61 | unsigned enable:1; | ||
62 | u8 channel; | ||
63 | }; | ||
64 | |||
57 | struct omap_usb_config { | 65 | struct omap_usb_config { |
58 | /* Configure drivers according to the connectors on your board: | 66 | /* Configure drivers according to the connectors on your board: |
59 | * - "A" connector (rectagular) | 67 | * - "A" connector (rectagular) |
@@ -87,6 +95,13 @@ struct omap_lcd_config { | |||
87 | char ctrl_name[16]; | 95 | char ctrl_name[16]; |
88 | }; | 96 | }; |
89 | 97 | ||
98 | struct omap_fbmem_config { | ||
99 | u32 fb_sram_start; | ||
100 | u32 fb_sram_size; | ||
101 | u32 fb_sdram_start; | ||
102 | u32 fb_sdram_size; | ||
103 | }; | ||
104 | |||
90 | /* Cover: | 105 | /* Cover: |
91 | * high -> closed | 106 | * high -> closed |
92 | * low -> open | 107 | * low -> open |
@@ -106,6 +121,12 @@ struct omap_gpio_switch_config { | |||
106 | int key_code:24; /* Linux key code */ | 121 | int key_code:24; /* Linux key code */ |
107 | }; | 122 | }; |
108 | 123 | ||
124 | struct omap_uart_config { | ||
125 | /* Bit field of UARTs present; bit 0 --> UART1 */ | ||
126 | unsigned int enabled_uarts; | ||
127 | }; | ||
128 | |||
129 | |||
109 | struct omap_flash_part_config { | 130 | struct omap_flash_part_config { |
110 | char part_table[0]; | 131 | char part_table[0]; |
111 | }; | 132 | }; |
@@ -114,11 +135,14 @@ struct omap_boot_reason_config { | |||
114 | char reason_str[12]; | 135 | char reason_str[12]; |
115 | }; | 136 | }; |
116 | 137 | ||
117 | struct omap_uart_config { | 138 | struct omap_version_config { |
118 | /* Bit field of UARTs present; bit 0 --> UART1 */ | 139 | char component[12]; |
119 | unsigned int enabled_uarts; | 140 | char version[12]; |
120 | }; | 141 | }; |
121 | 142 | ||
143 | |||
144 | #include <asm-arm/arch-omap/board-nokia.h> | ||
145 | |||
122 | struct omap_board_config_entry { | 146 | struct omap_board_config_entry { |
123 | u16 tag; | 147 | u16 tag; |
124 | u16 len; | 148 | u16 len; |
diff --git a/include/asm-arm/arch-omap/clock.h b/include/asm-arm/arch-omap/clock.h index 46a0402696de..3c4eb9fbe48a 100644 --- a/include/asm-arm/arch-omap/clock.h +++ b/include/asm-arm/arch-omap/clock.h | |||
@@ -19,6 +19,7 @@ struct clk { | |||
19 | struct list_head node; | 19 | struct list_head node; |
20 | struct module *owner; | 20 | struct module *owner; |
21 | const char *name; | 21 | const char *name; |
22 | int id; | ||
22 | struct clk *parent; | 23 | struct clk *parent; |
23 | unsigned long rate; | 24 | unsigned long rate; |
24 | __u32 flags; | 25 | __u32 flags; |
@@ -57,6 +58,7 @@ extern void propagate_rate(struct clk *clk); | |||
57 | extern void followparent_recalc(struct clk * clk); | 58 | extern void followparent_recalc(struct clk * clk); |
58 | extern void clk_allow_idle(struct clk *clk); | 59 | extern void clk_allow_idle(struct clk *clk); |
59 | extern void clk_deny_idle(struct clk *clk); | 60 | extern void clk_deny_idle(struct clk *clk); |
61 | extern int clk_get_usecount(struct clk *clk); | ||
60 | 62 | ||
61 | /* Clock flags */ | 63 | /* Clock flags */ |
62 | #define RATE_CKCTL (1 << 0) /* Main fixed ratio clocks */ | 64 | #define RATE_CKCTL (1 << 0) /* Main fixed ratio clocks */ |
@@ -80,10 +82,11 @@ extern void clk_deny_idle(struct clk *clk); | |||
80 | #define CM_PLL_SEL1 (1 << 18) | 82 | #define CM_PLL_SEL1 (1 << 18) |
81 | #define CM_PLL_SEL2 (1 << 19) | 83 | #define CM_PLL_SEL2 (1 << 19) |
82 | #define CM_SYSCLKOUT_SEL1 (1 << 20) | 84 | #define CM_SYSCLKOUT_SEL1 (1 << 20) |
83 | #define CLOCK_IN_OMAP730 (1 << 21) | 85 | #define CLOCK_IN_OMAP310 (1 << 21) |
84 | #define CLOCK_IN_OMAP1510 (1 << 22) | 86 | #define CLOCK_IN_OMAP730 (1 << 22) |
85 | #define CLOCK_IN_OMAP16XX (1 << 23) | 87 | #define CLOCK_IN_OMAP1510 (1 << 23) |
86 | #define CLOCK_IN_OMAP242X (1 << 24) | 88 | #define CLOCK_IN_OMAP16XX (1 << 24) |
87 | #define CLOCK_IN_OMAP243X (1 << 25) | 89 | #define CLOCK_IN_OMAP242X (1 << 25) |
90 | #define CLOCK_IN_OMAP243X (1 << 26) | ||
88 | 91 | ||
89 | #endif | 92 | #endif |
diff --git a/include/asm-arm/arch-omap/dma.h b/include/asm-arm/arch-omap/dma.h index d4e73efcb816..ca1202312a45 100644 --- a/include/asm-arm/arch-omap/dma.h +++ b/include/asm-arm/arch-omap/dma.h | |||
@@ -404,6 +404,7 @@ extern void omap_free_lcd_dma(void); | |||
404 | extern void omap_setup_lcd_dma(void); | 404 | extern void omap_setup_lcd_dma(void); |
405 | extern void omap_enable_lcd_dma(void); | 405 | extern void omap_enable_lcd_dma(void); |
406 | extern void omap_stop_lcd_dma(void); | 406 | extern void omap_stop_lcd_dma(void); |
407 | extern int omap_lcd_dma_ext_running(void); | ||
407 | extern void omap_set_lcd_dma_ext_controller(int external); | 408 | extern void omap_set_lcd_dma_ext_controller(int external); |
408 | extern void omap_set_lcd_dma_single_transfer(int single); | 409 | extern void omap_set_lcd_dma_single_transfer(int single); |
409 | extern void omap_set_lcd_dma_b1(unsigned long addr, u16 fb_xres, u16 fb_yres, | 410 | extern void omap_set_lcd_dma_b1(unsigned long addr, u16 fb_xres, u16 fb_yres, |
diff --git a/include/asm-arm/arch-omap/dmtimer.h b/include/asm-arm/arch-omap/dmtimer.h index 11772c792f3e..e6522e6a3834 100644 --- a/include/asm-arm/arch-omap/dmtimer.h +++ b/include/asm-arm/arch-omap/dmtimer.h | |||
@@ -88,5 +88,6 @@ unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer); | |||
88 | void omap_dm_timer_reset_counter(struct omap_dm_timer *timer); | 88 | void omap_dm_timer_reset_counter(struct omap_dm_timer *timer); |
89 | 89 | ||
90 | int omap_dm_timers_active(void); | 90 | int omap_dm_timers_active(void); |
91 | u32 omap_dm_timer_modify_idlect_mask(u32 inputmask); | ||
91 | 92 | ||
92 | #endif /* __ASM_ARCH_TIMER_H */ | 93 | #endif /* __ASM_ARCH_TIMER_H */ |
diff --git a/include/asm-arm/arch-omap/dsp.h b/include/asm-arm/arch-omap/dsp.h index 57bf4f39ca58..06dad83dd41f 100644 --- a/include/asm-arm/arch-omap/dsp.h +++ b/include/asm-arm/arch-omap/dsp.h | |||
@@ -181,10 +181,16 @@ struct omap_dsp_varinfo { | |||
181 | #define OMAP_DSP_MBCMD_PM_ENABLE 0x01 | 181 | #define OMAP_DSP_MBCMD_PM_ENABLE 0x01 |
182 | 182 | ||
183 | #define OMAP_DSP_MBCMD_KFUNC_FBCTL 0x00 | 183 | #define OMAP_DSP_MBCMD_KFUNC_FBCTL 0x00 |
184 | #define OMAP_DSP_MBCMD_KFUNC_AUDIO_PWR 0x01 | ||
184 | 185 | ||
186 | #define OMAP_DSP_MBCMD_FBCTL_UPD 0x0000 | ||
185 | #define OMAP_DSP_MBCMD_FBCTL_ENABLE 0x0002 | 187 | #define OMAP_DSP_MBCMD_FBCTL_ENABLE 0x0002 |
186 | #define OMAP_DSP_MBCMD_FBCTL_DISABLE 0x0003 | 188 | #define OMAP_DSP_MBCMD_FBCTL_DISABLE 0x0003 |
187 | 189 | ||
190 | #define OMAP_DSP_MBCMD_AUDIO_PWR_UP 0x0000 | ||
191 | #define OMAP_DSP_MBCMD_AUDIO_PWR_DOWN1 0x0001 | ||
192 | #define OMAP_DSP_MBCMD_AUDIO_PWR_DOWN2 0x0002 | ||
193 | |||
188 | #define OMAP_DSP_MBCMD_TDEL_SAFE 0x0000 | 194 | #define OMAP_DSP_MBCMD_TDEL_SAFE 0x0000 |
189 | #define OMAP_DSP_MBCMD_TDEL_KILL 0x0001 | 195 | #define OMAP_DSP_MBCMD_TDEL_KILL 0x0001 |
190 | 196 | ||
diff --git a/include/asm-arm/arch-omap/dsp_common.h b/include/asm-arm/arch-omap/dsp_common.h index 4fcce6944056..16a459dfa714 100644 --- a/include/asm-arm/arch-omap/dsp_common.h +++ b/include/asm-arm/arch-omap/dsp_common.h | |||
@@ -27,11 +27,12 @@ | |||
27 | #ifndef ASM_ARCH_DSP_COMMON_H | 27 | #ifndef ASM_ARCH_DSP_COMMON_H |
28 | #define ASM_ARCH_DSP_COMMON_H | 28 | #define ASM_ARCH_DSP_COMMON_H |
29 | 29 | ||
30 | void omap_dsp_pm_suspend(void); | 30 | extern void omap_dsp_request_mpui(void); |
31 | void omap_dsp_pm_resume(void); | 31 | extern void omap_dsp_release_mpui(void); |
32 | void omap_dsp_request_mpui(void); | 32 | extern int omap_dsp_request_mem(void); |
33 | void omap_dsp_release_mpui(void); | 33 | extern int omap_dsp_release_mem(void); |
34 | int omap_dsp_request_mem(void); | 34 | |
35 | int omap_dsp_release_mem(void); | 35 | extern void (*omap_dsp_audio_pwr_up_request)(int stage); |
36 | extern void (*omap_dsp_audio_pwr_down_request)(int stage); | ||
36 | 37 | ||
37 | #endif /* ASM_ARCH_DSP_COMMON_H */ | 38 | #endif /* ASM_ARCH_DSP_COMMON_H */ |
diff --git a/include/asm-arm/arch-omap/gpioexpander.h b/include/asm-arm/arch-omap/gpioexpander.h new file mode 100644 index 000000000000..7a43b0a912e4 --- /dev/null +++ b/include/asm-arm/arch-omap/gpioexpander.h | |||
@@ -0,0 +1,24 @@ | |||
1 | /* | ||
2 | * linux/include/asm-arm/arch-omap/gpioexpander.h | ||
3 | * | ||
4 | * | ||
5 | * Copyright (C) 2004 Texas Instruments, Inc. | ||
6 | * | ||
7 | * This package is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR | ||
12 | * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED | ||
13 | * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. | ||
14 | */ | ||
15 | |||
16 | #ifndef __ASM_ARCH_OMAP_GPIOEXPANDER_H | ||
17 | #define __ASM_ARCH_OMAP_GPIOEXPANDER_H | ||
18 | |||
19 | /* Function Prototypes for GPIO Expander functions */ | ||
20 | |||
21 | int read_gpio_expa(u8 *, int); | ||
22 | int write_gpio_expa(u8 , int); | ||
23 | |||
24 | #endif /* __ASM_ARCH_OMAP_GPIOEXPANDER_H */ | ||
diff --git a/include/asm-arm/arch-omap/hardware.h b/include/asm-arm/arch-omap/hardware.h index 5406b875c422..7909b729826c 100644 --- a/include/asm-arm/arch-omap/hardware.h +++ b/include/asm-arm/arch-omap/hardware.h | |||
@@ -306,6 +306,10 @@ | |||
306 | #include "board-h4.h" | 306 | #include "board-h4.h" |
307 | #endif | 307 | #endif |
308 | 308 | ||
309 | #ifdef CONFIG_MACH_OMAP_APOLLON | ||
310 | #include "board-apollon.h" | ||
311 | #endif | ||
312 | |||
309 | #ifdef CONFIG_MACH_OMAP_OSK | 313 | #ifdef CONFIG_MACH_OMAP_OSK |
310 | #include "board-osk.h" | 314 | #include "board-osk.h" |
311 | #endif | 315 | #endif |
@@ -314,10 +318,6 @@ | |||
314 | #include "board-voiceblue.h" | 318 | #include "board-voiceblue.h" |
315 | #endif | 319 | #endif |
316 | 320 | ||
317 | #ifdef CONFIG_MACH_NETSTAR | ||
318 | #include "board-netstar.h" | ||
319 | #endif | ||
320 | |||
321 | #endif /* !__ASSEMBLER__ */ | 321 | #endif /* !__ASSEMBLER__ */ |
322 | 322 | ||
323 | #endif /* __ASM_ARCH_OMAP_HARDWARE_H */ | 323 | #endif /* __ASM_ARCH_OMAP_HARDWARE_H */ |
diff --git a/include/asm-arm/arch-omap/irda.h b/include/asm-arm/arch-omap/irda.h new file mode 100644 index 000000000000..805ae3575e44 --- /dev/null +++ b/include/asm-arm/arch-omap/irda.h | |||
@@ -0,0 +1,36 @@ | |||
1 | /* | ||
2 | * linux/include/asm-arm/arch-omap/irda.h | ||
3 | * | ||
4 | * Copyright (C) 2005-2006 Komal Shah <komal_shah802003@yahoo.com> | ||
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 | #ifndef ASMARM_ARCH_IRDA_H | ||
11 | #define ASMARM_ARCH_IRDA_H | ||
12 | |||
13 | /* board specific transceiver capabilities */ | ||
14 | |||
15 | #define IR_SEL 1 /* Selects IrDA */ | ||
16 | #define IR_SIRMODE 2 | ||
17 | #define IR_FIRMODE 4 | ||
18 | #define IR_MIRMODE 8 | ||
19 | |||
20 | struct omap_irda_config { | ||
21 | int transceiver_cap; | ||
22 | int (*transceiver_mode)(struct device *dev, int mode); | ||
23 | int (*select_irda)(struct device *dev, int state); | ||
24 | /* Very specific to the needs of some platforms (h3,h4) | ||
25 | * having calls which can sleep in irda_set_speed. | ||
26 | */ | ||
27 | struct work_struct gpio_expa; | ||
28 | int rx_channel; | ||
29 | int tx_channel; | ||
30 | unsigned long dest_start; | ||
31 | unsigned long src_start; | ||
32 | int tx_trigger; | ||
33 | int rx_trigger; | ||
34 | }; | ||
35 | |||
36 | #endif | ||
diff --git a/include/asm-arm/arch-omap/irqs.h b/include/asm-arm/arch-omap/irqs.h index 4ffce1d77759..42098d99f302 100644 --- a/include/asm-arm/arch-omap/irqs.h +++ b/include/asm-arm/arch-omap/irqs.h | |||
@@ -242,6 +242,11 @@ | |||
242 | #define INT_24XX_GPIO_BANK2 30 | 242 | #define INT_24XX_GPIO_BANK2 30 |
243 | #define INT_24XX_GPIO_BANK3 31 | 243 | #define INT_24XX_GPIO_BANK3 31 |
244 | #define INT_24XX_GPIO_BANK4 32 | 244 | #define INT_24XX_GPIO_BANK4 32 |
245 | #define INT_24XX_MCBSP1_IRQ_TX 59 | ||
246 | #define INT_24XX_MCBSP1_IRQ_RX 60 | ||
247 | #define INT_24XX_MCBSP2_IRQ_TX 62 | ||
248 | #define INT_24XX_MCBSP2_IRQ_RX 63 | ||
249 | #define INT_24XX_UART3_IRQ 74 | ||
245 | 250 | ||
246 | /* Max. 128 level 2 IRQs (OMAP1610), 192 GPIOs (OMAP730) and | 251 | /* Max. 128 level 2 IRQs (OMAP1610), 192 GPIOs (OMAP730) and |
247 | * 16 MPUIO lines */ | 252 | * 16 MPUIO lines */ |
diff --git a/include/asm-arm/arch-omap/keypad.h b/include/asm-arm/arch-omap/keypad.h new file mode 100644 index 000000000000..8a023a984acb --- /dev/null +++ b/include/asm-arm/arch-omap/keypad.h | |||
@@ -0,0 +1,36 @@ | |||
1 | /* | ||
2 | * linux/include/asm-arm/arch-omap/keypad.h | ||
3 | * | ||
4 | * Copyright (C) 2006 Komal Shah <komal_shah802003@yahoo.com> | ||
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 | #ifndef ASMARM_ARCH_KEYPAD_H | ||
11 | #define ASMARM_ARCH_KEYPAD_H | ||
12 | |||
13 | struct omap_kp_platform_data { | ||
14 | int rows; | ||
15 | int cols; | ||
16 | int *keymap; | ||
17 | unsigned int rep:1; | ||
18 | /* specific to OMAP242x*/ | ||
19 | unsigned int *row_gpios; | ||
20 | unsigned int *col_gpios; | ||
21 | }; | ||
22 | |||
23 | /* Group (0..3) -- when multiple keys are pressed, only the | ||
24 | * keys pressed in the same group are considered as pressed. This is | ||
25 | * in order to workaround certain crappy HW designs that produce ghost | ||
26 | * keypresses. */ | ||
27 | #define GROUP_0 (0 << 16) | ||
28 | #define GROUP_1 (1 << 16) | ||
29 | #define GROUP_2 (2 << 16) | ||
30 | #define GROUP_3 (3 << 16) | ||
31 | #define GROUP_MASK GROUP_3 | ||
32 | |||
33 | #define KEY(col, row, val) (((col) << 28) | ((row) << 24) | (val)) | ||
34 | |||
35 | #endif | ||
36 | |||
diff --git a/include/asm-arm/arch-omap/lcd_lph8923.h b/include/asm-arm/arch-omap/lcd_lph8923.h new file mode 100644 index 000000000000..004e67e22ca7 --- /dev/null +++ b/include/asm-arm/arch-omap/lcd_lph8923.h | |||
@@ -0,0 +1,14 @@ | |||
1 | #ifndef __LCD_LPH8923_H | ||
2 | #define __LCD_LPH8923_H | ||
3 | |||
4 | enum lcd_lph8923_test_num { | ||
5 | LCD_LPH8923_TEST_RGB_LINES, | ||
6 | }; | ||
7 | |||
8 | enum lcd_lph8923_test_result { | ||
9 | LCD_LPH8923_TEST_SUCCESS, | ||
10 | LCD_LPH8923_TEST_INVALID, | ||
11 | LCD_LPH8923_TEST_FAILED, | ||
12 | }; | ||
13 | |||
14 | #endif | ||
diff --git a/include/asm-arm/arch-omap/mcbsp.h b/include/asm-arm/arch-omap/mcbsp.h index e79d98ab2ab6..ed0dde4f7219 100644 --- a/include/asm-arm/arch-omap/mcbsp.h +++ b/include/asm-arm/arch-omap/mcbsp.h | |||
@@ -37,6 +37,11 @@ | |||
37 | #define OMAP1610_MCBSP2_BASE 0xfffb1000 | 37 | #define OMAP1610_MCBSP2_BASE 0xfffb1000 |
38 | #define OMAP1610_MCBSP3_BASE 0xe1017000 | 38 | #define OMAP1610_MCBSP3_BASE 0xe1017000 |
39 | 39 | ||
40 | #define OMAP24XX_MCBSP1_BASE 0x48074000 | ||
41 | #define OMAP24XX_MCBSP2_BASE 0x48076000 | ||
42 | |||
43 | #if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP730) | ||
44 | |||
40 | #define OMAP_MCBSP_REG_DRR2 0x00 | 45 | #define OMAP_MCBSP_REG_DRR2 0x00 |
41 | #define OMAP_MCBSP_REG_DRR1 0x02 | 46 | #define OMAP_MCBSP_REG_DRR1 0x02 |
42 | #define OMAP_MCBSP_REG_DXR2 0x04 | 47 | #define OMAP_MCBSP_REG_DXR2 0x04 |
@@ -71,9 +76,62 @@ | |||
71 | 76 | ||
72 | #define OMAP_MAX_MCBSP_COUNT 3 | 77 | #define OMAP_MAX_MCBSP_COUNT 3 |
73 | 78 | ||
79 | #define AUDIO_MCBSP_DATAWRITE (OMAP1510_MCBSP1_BASE + OMAP_MCBSP_REG_DXR1) | ||
80 | #define AUDIO_MCBSP_DATAREAD (OMAP1510_MCBSP1_BASE + OMAP_MCBSP_REG_DRR1) | ||
81 | |||
82 | #define AUDIO_MCBSP OMAP_MCBSP1 | ||
83 | #define AUDIO_DMA_TX OMAP_DMA_MCBSP1_TX | ||
84 | #define AUDIO_DMA_RX OMAP_DMA_MCBSP1_RX | ||
85 | |||
86 | #elif defined(CONFIG_ARCH_OMAP24XX) | ||
87 | |||
88 | #define OMAP_MCBSP_REG_DRR2 0x00 | ||
89 | #define OMAP_MCBSP_REG_DRR1 0x04 | ||
90 | #define OMAP_MCBSP_REG_DXR2 0x08 | ||
91 | #define OMAP_MCBSP_REG_DXR1 0x0C | ||
92 | #define OMAP_MCBSP_REG_SPCR2 0x10 | ||
93 | #define OMAP_MCBSP_REG_SPCR1 0x14 | ||
94 | #define OMAP_MCBSP_REG_RCR2 0x18 | ||
95 | #define OMAP_MCBSP_REG_RCR1 0x1C | ||
96 | #define OMAP_MCBSP_REG_XCR2 0x20 | ||
97 | #define OMAP_MCBSP_REG_XCR1 0x24 | ||
98 | #define OMAP_MCBSP_REG_SRGR2 0x28 | ||
99 | #define OMAP_MCBSP_REG_SRGR1 0x2C | ||
100 | #define OMAP_MCBSP_REG_MCR2 0x30 | ||
101 | #define OMAP_MCBSP_REG_MCR1 0x34 | ||
102 | #define OMAP_MCBSP_REG_RCERA 0x38 | ||
103 | #define OMAP_MCBSP_REG_RCERB 0x3C | ||
104 | #define OMAP_MCBSP_REG_XCERA 0x40 | ||
105 | #define OMAP_MCBSP_REG_XCERB 0x44 | ||
106 | #define OMAP_MCBSP_REG_PCR0 0x48 | ||
107 | #define OMAP_MCBSP_REG_RCERC 0x4C | ||
108 | #define OMAP_MCBSP_REG_RCERD 0x50 | ||
109 | #define OMAP_MCBSP_REG_XCERC 0x54 | ||
110 | #define OMAP_MCBSP_REG_XCERD 0x58 | ||
111 | #define OMAP_MCBSP_REG_RCERE 0x5C | ||
112 | #define OMAP_MCBSP_REG_RCERF 0x60 | ||
113 | #define OMAP_MCBSP_REG_XCERE 0x64 | ||
114 | #define OMAP_MCBSP_REG_XCERF 0x68 | ||
115 | #define OMAP_MCBSP_REG_RCERG 0x6C | ||
116 | #define OMAP_MCBSP_REG_RCERH 0x70 | ||
117 | #define OMAP_MCBSP_REG_XCERG 0x74 | ||
118 | #define OMAP_MCBSP_REG_XCERH 0x78 | ||
119 | |||
120 | #define OMAP_MAX_MCBSP_COUNT 2 | ||
121 | |||
122 | #define AUDIO_MCBSP_DATAWRITE (OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DXR1) | ||
123 | #define AUDIO_MCBSP_DATAREAD (OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DRR1) | ||
124 | |||
125 | #define AUDIO_MCBSP OMAP_MCBSP2 | ||
126 | #define AUDIO_DMA_TX OMAP24XX_DMA_MCBSP2_TX | ||
127 | #define AUDIO_DMA_RX OMAP24XX_DMA_MCBSP2_RX | ||
128 | |||
129 | #endif | ||
130 | |||
74 | #define OMAP_MCBSP_READ(base, reg) __raw_readw((base) + OMAP_MCBSP_REG_##reg) | 131 | #define OMAP_MCBSP_READ(base, reg) __raw_readw((base) + OMAP_MCBSP_REG_##reg) |
75 | #define OMAP_MCBSP_WRITE(base, reg, val) __raw_writew((val), (base) + OMAP_MCBSP_REG_##reg) | 132 | #define OMAP_MCBSP_WRITE(base, reg, val) __raw_writew((val), (base) + OMAP_MCBSP_REG_##reg) |
76 | 133 | ||
134 | |||
77 | /************************** McBSP SPCR1 bit definitions ***********************/ | 135 | /************************** McBSP SPCR1 bit definitions ***********************/ |
78 | #define RRST 0x0001 | 136 | #define RRST 0x0001 |
79 | #define RRDY 0x0002 | 137 | #define RRDY 0x0002 |
@@ -195,6 +253,10 @@ typedef enum { | |||
195 | OMAP_MCBSP3, | 253 | OMAP_MCBSP3, |
196 | } omap_mcbsp_id; | 254 | } omap_mcbsp_id; |
197 | 255 | ||
256 | typedef int __bitwise omap_mcbsp_io_type_t; | ||
257 | #define OMAP_MCBSP_IRQ_IO ((__force omap_mcbsp_io_type_t) 1) | ||
258 | #define OMAP_MCBSP_POLL_IO ((__force omap_mcbsp_io_type_t) 2) | ||
259 | |||
198 | typedef enum { | 260 | typedef enum { |
199 | OMAP_MCBSP_WORD_8 = 0, | 261 | OMAP_MCBSP_WORD_8 = 0, |
200 | OMAP_MCBSP_WORD_12, | 262 | OMAP_MCBSP_WORD_12, |
@@ -246,6 +308,9 @@ u32 omap_mcbsp_recv_word(unsigned int id); | |||
246 | 308 | ||
247 | int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, unsigned int length); | 309 | int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, unsigned int length); |
248 | int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, unsigned int length); | 310 | int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, unsigned int length); |
311 | int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word); | ||
312 | int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 * word); | ||
313 | |||
249 | 314 | ||
250 | /* SPI specific API */ | 315 | /* SPI specific API */ |
251 | void omap_mcbsp_set_spi_mode(unsigned int id, const struct omap_mcbsp_spi_cfg * spi_cfg); | 316 | void omap_mcbsp_set_spi_mode(unsigned int id, const struct omap_mcbsp_spi_cfg * spi_cfg); |
diff --git a/include/asm-arm/arch-omap/mcspi.h b/include/asm-arm/arch-omap/mcspi.h new file mode 100644 index 000000000000..9e7f40a88e1b --- /dev/null +++ b/include/asm-arm/arch-omap/mcspi.h | |||
@@ -0,0 +1,16 @@ | |||
1 | #ifndef _OMAP2_MCSPI_H | ||
2 | #define _OMAP2_MCSPI_H | ||
3 | |||
4 | struct omap2_mcspi_platform_config { | ||
5 | unsigned long base; | ||
6 | unsigned short num_cs; | ||
7 | }; | ||
8 | |||
9 | struct omap2_mcspi_device_config { | ||
10 | unsigned turbo_mode:1; | ||
11 | |||
12 | /* Do we want one channel enabled at the same time? */ | ||
13 | unsigned single_channel:1; | ||
14 | }; | ||
15 | |||
16 | #endif | ||
diff --git a/include/asm-arm/arch-omap/menelaus.h b/include/asm-arm/arch-omap/menelaus.h index 46be8b8d6346..88cd4c87f0de 100644 --- a/include/asm-arm/arch-omap/menelaus.h +++ b/include/asm-arm/arch-omap/menelaus.h | |||
@@ -7,7 +7,7 @@ | |||
7 | #ifndef __ASM_ARCH_MENELAUS_H | 7 | #ifndef __ASM_ARCH_MENELAUS_H |
8 | #define __ASM_ARCH_MENELAUS_H | 8 | #define __ASM_ARCH_MENELAUS_H |
9 | 9 | ||
10 | extern void menelaus_mmc_register(void (*callback)(u8 card_mask), | 10 | extern void menelaus_mmc_register(void (*callback)(unsigned long data, u8 card_mask), |
11 | unsigned long data); | 11 | unsigned long data); |
12 | extern void menelaus_mmc_remove(void); | 12 | extern void menelaus_mmc_remove(void); |
13 | extern void menelaus_mmc_opendrain(int enable); | 13 | extern void menelaus_mmc_opendrain(int enable); |
diff --git a/include/asm-arm/arch-omap/mux.h b/include/asm-arm/arch-omap/mux.h index 13415a9aab06..0dc24d4ba59c 100644 --- a/include/asm-arm/arch-omap/mux.h +++ b/include/asm-arm/arch-omap/mux.h | |||
@@ -112,14 +112,13 @@ | |||
112 | * as mux config | 112 | * as mux config |
113 | */ | 113 | */ |
114 | #define MUX_CFG_730(desc, mux_reg, mode_offset, mode, \ | 114 | #define MUX_CFG_730(desc, mux_reg, mode_offset, mode, \ |
115 | pull_reg, pull_bit, pull_status, \ | 115 | pull_bit, pull_status, debug_status)\ |
116 | pu_pd_reg, pu_pd_status, debug_status)\ | ||
117 | { \ | 116 | { \ |
118 | .name = desc, \ | 117 | .name = desc, \ |
119 | .debug = debug_status, \ | 118 | .debug = debug_status, \ |
120 | MUX_REG_730(mux_reg, mode_offset, mode) \ | 119 | MUX_REG_730(mux_reg, mode_offset, mode) \ |
121 | PULL_REG_730(mux_reg, pull_bit, pull_status) \ | 120 | PULL_REG_730(mux_reg, pull_bit, pull_status) \ |
122 | PU_PD_REG(pu_pd_reg, pu_pd_status) \ | 121 | PU_PD_REG(NA, 0) \ |
123 | }, | 122 | }, |
124 | 123 | ||
125 | #define MUX_CFG_24XX(desc, reg_offset, mode, \ | 124 | #define MUX_CFG_24XX(desc, reg_offset, mode, \ |
@@ -172,6 +171,11 @@ enum omap730_index { | |||
172 | E4_730_KBC2, | 171 | E4_730_KBC2, |
173 | F4_730_KBC3, | 172 | F4_730_KBC3, |
174 | E3_730_KBC4, | 173 | E3_730_KBC4, |
174 | |||
175 | /* USB */ | ||
176 | AA17_730_USB_DM, | ||
177 | W16_730_USB_PU_EN, | ||
178 | W17_730_USB_VBUSI, | ||
175 | }; | 179 | }; |
176 | 180 | ||
177 | enum omap1xxx_index { | 181 | enum omap1xxx_index { |
@@ -403,9 +407,53 @@ enum omap24xx_index { | |||
403 | /* 24xx Menelaus interrupt */ | 407 | /* 24xx Menelaus interrupt */ |
404 | W19_24XX_SYS_NIRQ, | 408 | W19_24XX_SYS_NIRQ, |
405 | 409 | ||
410 | /* 24xx clock */ | ||
411 | W14_24XX_SYS_CLKOUT, | ||
412 | |||
413 | /* 242X McBSP */ | ||
414 | Y15_24XX_MCBSP2_CLKX, | ||
415 | R14_24XX_MCBSP2_FSX, | ||
416 | W15_24XX_MCBSP2_DR, | ||
417 | V15_24XX_MCBSP2_DX, | ||
418 | |||
406 | /* 24xx GPIO */ | 419 | /* 24xx GPIO */ |
420 | M21_242X_GPIO11, | ||
421 | AA10_242X_GPIO13, | ||
422 | AA6_242X_GPIO14, | ||
423 | AA4_242X_GPIO15, | ||
424 | Y11_242X_GPIO16, | ||
425 | AA12_242X_GPIO17, | ||
426 | AA8_242X_GPIO58, | ||
407 | Y20_24XX_GPIO60, | 427 | Y20_24XX_GPIO60, |
428 | W4__24XX_GPIO74, | ||
408 | M15_24XX_GPIO92, | 429 | M15_24XX_GPIO92, |
430 | V14_24XX_GPIO117, | ||
431 | |||
432 | P20_24XX_TSC_IRQ, | ||
433 | |||
434 | /* UART3 */ | ||
435 | K15_24XX_UART3_TX, | ||
436 | K14_24XX_UART3_RX, | ||
437 | |||
438 | /* Keypad GPIO*/ | ||
439 | T19_24XX_KBR0, | ||
440 | R19_24XX_KBR1, | ||
441 | V18_24XX_KBR2, | ||
442 | M21_24XX_KBR3, | ||
443 | E5__24XX_KBR4, | ||
444 | M18_24XX_KBR5, | ||
445 | R20_24XX_KBC0, | ||
446 | M14_24XX_KBC1, | ||
447 | H19_24XX_KBC2, | ||
448 | V17_24XX_KBC3, | ||
449 | P21_24XX_KBC4, | ||
450 | L14_24XX_KBC5, | ||
451 | N19_24XX_KBC6, | ||
452 | |||
453 | /* 24xx Menelaus Keypad GPIO */ | ||
454 | B3__24XX_KBR5, | ||
455 | AA4_24XX_KBC2, | ||
456 | B13_24XX_KBC6, | ||
409 | }; | 457 | }; |
410 | 458 | ||
411 | #ifdef CONFIG_OMAP_MUX | 459 | #ifdef CONFIG_OMAP_MUX |
diff --git a/include/asm-arm/arch-omap/omap-alsa.h b/include/asm-arm/arch-omap/omap-alsa.h new file mode 100644 index 000000000000..df4695474e3d --- /dev/null +++ b/include/asm-arm/arch-omap/omap-alsa.h | |||
@@ -0,0 +1,124 @@ | |||
1 | /* | ||
2 | * linux/include/asm-arm/arch-omap/omap-alsa.h | ||
3 | * | ||
4 | * Alsa Driver for AIC23 and TSC2101 codecs on OMAP platform boards. | ||
5 | * | ||
6 | * Copyright (C) 2006 Mika Laitio <lamikr@cc.jyu.fi> | ||
7 | * | ||
8 | * Copyright (C) 2005 Instituto Nokia de Tecnologia - INdT - Manaus Brazil | ||
9 | * Written by Daniel Petrini, David Cohen, Anderson Briglia | ||
10 | * {daniel.petrini, david.cohen, anderson.briglia}@indt.org.br | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify it | ||
13 | * under the terms of the GNU General Public License as published by the | ||
14 | * Free Software Foundation; either version 2 of the License, or (at your | ||
15 | * option) any later version. | ||
16 | * | ||
17 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
19 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | ||
20 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
23 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
24 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
27 | * | ||
28 | * You should have received a copy of the GNU General Public License along | ||
29 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
30 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
31 | * | ||
32 | * History | ||
33 | * ------- | ||
34 | * | ||
35 | * 2005/07/25 INdT-10LE Kernel Team - Alsa driver for omap osk, | ||
36 | * original version based in sa1100 driver | ||
37 | * and omap oss driver. | ||
38 | */ | ||
39 | |||
40 | #ifndef __OMAP_ALSA_H | ||
41 | #define __OMAP_ALSA_H | ||
42 | |||
43 | #include <sound/driver.h> | ||
44 | #include <asm/arch/dma.h> | ||
45 | #include <sound/core.h> | ||
46 | #include <sound/pcm.h> | ||
47 | #include <asm/arch/mcbsp.h> | ||
48 | #include <linux/platform_device.h> | ||
49 | |||
50 | #define DMA_BUF_SIZE (1024 * 8) | ||
51 | |||
52 | /* | ||
53 | * Buffer management for alsa and dma | ||
54 | */ | ||
55 | struct audio_stream { | ||
56 | char *id; /* identification string */ | ||
57 | int stream_id; /* numeric identification */ | ||
58 | int dma_dev; /* dma number of that device */ | ||
59 | int *lch; /* Chain of channels this stream is linked to */ | ||
60 | char started; /* to store if the chain was started or not */ | ||
61 | int dma_q_head; /* DMA Channel Q Head */ | ||
62 | int dma_q_tail; /* DMA Channel Q Tail */ | ||
63 | char dma_q_count; /* DMA Channel Q Count */ | ||
64 | int active:1; /* we are using this stream for transfer now */ | ||
65 | int period; /* current transfer period */ | ||
66 | int periods; /* current count of periods registerd in the DMA engine */ | ||
67 | spinlock_t dma_lock; /* for locking in DMA operations */ | ||
68 | snd_pcm_substream_t *stream; /* the pcm stream */ | ||
69 | unsigned linked:1; /* dma channels linked */ | ||
70 | int offset; /* store start position of the last period in the alsa buffer */ | ||
71 | int (*hw_start)(void); /* interface to start HW interface, e.g. McBSP */ | ||
72 | int (*hw_stop)(void); /* interface to stop HW interface, e.g. McBSP */ | ||
73 | }; | ||
74 | |||
75 | /* | ||
76 | * Alsa card structure for aic23 | ||
77 | */ | ||
78 | struct snd_card_omap_codec { | ||
79 | snd_card_t *card; | ||
80 | snd_pcm_t *pcm; | ||
81 | long samplerate; | ||
82 | struct audio_stream s[2]; /* playback & capture */ | ||
83 | }; | ||
84 | |||
85 | /* Codec specific information and function pointers. | ||
86 | * Codec (omap-alsa-aic23.c and omap-alsa-tsc2101.c) | ||
87 | * are responsible for defining the function pointers. | ||
88 | */ | ||
89 | struct omap_alsa_codec_config { | ||
90 | char *name; | ||
91 | struct omap_mcbsp_reg_cfg *mcbsp_regs_alsa; | ||
92 | snd_pcm_hw_constraint_list_t *hw_constraints_rates; | ||
93 | snd_pcm_hardware_t *snd_omap_alsa_playback; | ||
94 | snd_pcm_hardware_t *snd_omap_alsa_capture; | ||
95 | void (*codec_configure_dev)(void); | ||
96 | void (*codec_set_samplerate)(long); | ||
97 | void (*codec_clock_setup)(void); | ||
98 | int (*codec_clock_on)(void); | ||
99 | int (*codec_clock_off)(void); | ||
100 | int (*get_default_samplerate)(void); | ||
101 | }; | ||
102 | |||
103 | /*********** Mixer function prototypes *************************/ | ||
104 | int snd_omap_mixer(struct snd_card_omap_codec *); | ||
105 | void snd_omap_init_mixer(void); | ||
106 | |||
107 | #ifdef CONFIG_PM | ||
108 | void snd_omap_suspend_mixer(void); | ||
109 | void snd_omap_resume_mixer(void); | ||
110 | #endif | ||
111 | |||
112 | int snd_omap_alsa_post_probe(struct platform_device *pdev, struct omap_alsa_codec_config *config); | ||
113 | int snd_omap_alsa_remove(struct platform_device *pdev); | ||
114 | #ifdef CONFIG_PM | ||
115 | int snd_omap_alsa_suspend(struct platform_device *pdev, pm_message_t state); | ||
116 | int snd_omap_alsa_resume(struct platform_device *pdev); | ||
117 | #else | ||
118 | #define snd_omap_alsa_suspend NULL | ||
119 | #define snd_omap_alsa_resume NULL | ||
120 | #endif | ||
121 | |||
122 | void callback_omap_alsa_sound_dma(void *); | ||
123 | |||
124 | #endif | ||
diff --git a/include/asm-arm/arch-omap/omapfb.h b/include/asm-arm/arch-omap/omapfb.h index 4ba2622cc142..fccdb3db025f 100644 --- a/include/asm-arm/arch-omap/omapfb.h +++ b/include/asm-arm/arch-omap/omapfb.h | |||
@@ -34,9 +34,10 @@ | |||
34 | #define OMAPFB_MIRROR OMAP_IOW(31, int) | 34 | #define OMAPFB_MIRROR OMAP_IOW(31, int) |
35 | #define OMAPFB_SYNC_GFX OMAP_IO(37) | 35 | #define OMAPFB_SYNC_GFX OMAP_IO(37) |
36 | #define OMAPFB_VSYNC OMAP_IO(38) | 36 | #define OMAPFB_VSYNC OMAP_IO(38) |
37 | #define OMAPFB_SET_UPDATE_MODE OMAP_IOW(40, enum omapfb_update_mode) | 37 | #define OMAPFB_SET_UPDATE_MODE OMAP_IOW(40, int) |
38 | #define OMAPFB_UPDATE_WINDOW_OLD OMAP_IOW(41, struct omapfb_update_window_old) | ||
38 | #define OMAPFB_GET_CAPS OMAP_IOR(42, unsigned long) | 39 | #define OMAPFB_GET_CAPS OMAP_IOR(42, unsigned long) |
39 | #define OMAPFB_GET_UPDATE_MODE OMAP_IOW(43, enum omapfb_update_mode) | 40 | #define OMAPFB_GET_UPDATE_MODE OMAP_IOW(43, int) |
40 | #define OMAPFB_LCD_TEST OMAP_IOW(45, int) | 41 | #define OMAPFB_LCD_TEST OMAP_IOW(45, int) |
41 | #define OMAPFB_CTRL_TEST OMAP_IOW(46, int) | 42 | #define OMAPFB_CTRL_TEST OMAP_IOW(46, int) |
42 | #define OMAPFB_UPDATE_WINDOW OMAP_IOW(47, struct omapfb_update_window) | 43 | #define OMAPFB_UPDATE_WINDOW OMAP_IOW(47, struct omapfb_update_window) |
@@ -66,9 +67,14 @@ enum omapfb_color_format { | |||
66 | }; | 67 | }; |
67 | 68 | ||
68 | struct omapfb_update_window { | 69 | struct omapfb_update_window { |
69 | u32 x, y; | 70 | __u32 x, y; |
70 | u32 width, height; | 71 | __u32 width, height; |
71 | u32 format; | 72 | __u32 format; |
73 | }; | ||
74 | |||
75 | struct omapfb_update_window_old { | ||
76 | __u32 x, y; | ||
77 | __u32 width, height; | ||
72 | }; | 78 | }; |
73 | 79 | ||
74 | enum omapfb_plane { | 80 | enum omapfb_plane { |
@@ -83,17 +89,17 @@ enum omapfb_channel_out { | |||
83 | }; | 89 | }; |
84 | 90 | ||
85 | struct omapfb_setup_plane { | 91 | struct omapfb_setup_plane { |
86 | u8 plane; | 92 | __u8 plane; |
87 | u8 channel_out; | 93 | __u8 channel_out; |
88 | u32 offset; | 94 | __u32 offset; |
89 | u32 pos_x, pos_y; | 95 | __u32 pos_x, pos_y; |
90 | u32 width, height; | 96 | __u32 width, height; |
91 | u32 color_mode; | 97 | __u32 color_mode; |
92 | }; | 98 | }; |
93 | 99 | ||
94 | struct omapfb_enable_plane { | 100 | struct omapfb_enable_plane { |
95 | u8 plane; | 101 | __u8 plane; |
96 | u8 enable; | 102 | __u8 enable; |
97 | }; | 103 | }; |
98 | 104 | ||
99 | enum omapfb_color_key_type { | 105 | enum omapfb_color_key_type { |
@@ -103,10 +109,10 @@ enum omapfb_color_key_type { | |||
103 | }; | 109 | }; |
104 | 110 | ||
105 | struct omapfb_color_key { | 111 | struct omapfb_color_key { |
106 | u8 channel_out; | 112 | __u8 channel_out; |
107 | u32 background; | 113 | __u32 background; |
108 | u32 trans_key; | 114 | __u32 trans_key; |
109 | u8 key_type; | 115 | __u8 key_type; |
110 | }; | 116 | }; |
111 | 117 | ||
112 | enum omapfb_update_mode { | 118 | enum omapfb_update_mode { |
@@ -120,6 +126,9 @@ enum omapfb_update_mode { | |||
120 | #include <linux/completion.h> | 126 | #include <linux/completion.h> |
121 | #include <linux/interrupt.h> | 127 | #include <linux/interrupt.h> |
122 | #include <linux/fb.h> | 128 | #include <linux/fb.h> |
129 | #include <linux/mutex.h> | ||
130 | |||
131 | #include <asm/arch/board.h> | ||
123 | 132 | ||
124 | #define OMAP_LCDC_INV_VSYNC 0x0001 | 133 | #define OMAP_LCDC_INV_VSYNC 0x0001 |
125 | #define OMAP_LCDC_INV_HSYNC 0x0002 | 134 | #define OMAP_LCDC_INV_HSYNC 0x0002 |
@@ -184,19 +193,38 @@ struct extif_timings { | |||
184 | int re_cycle_time; | 193 | int re_cycle_time; |
185 | int cs_pulse_width; | 194 | int cs_pulse_width; |
186 | int access_time; | 195 | int access_time; |
196 | |||
197 | int clk_div; | ||
198 | |||
199 | u32 tim[5]; /* set by extif->convert_timings */ | ||
200 | |||
201 | int converted; | ||
187 | }; | 202 | }; |
188 | 203 | ||
189 | struct lcd_ctrl_extif { | 204 | struct lcd_ctrl_extif { |
190 | int (*init) (void); | 205 | int (*init) (void); |
191 | void (*cleanup) (void); | 206 | void (*cleanup) (void); |
207 | void (*get_clk_info) (u32 *clk_period, u32 *max_clk_div); | ||
208 | int (*convert_timings) (struct extif_timings *timings); | ||
192 | void (*set_timings) (const struct extif_timings *timings); | 209 | void (*set_timings) (const struct extif_timings *timings); |
193 | void (*write_command) (u32 cmd); | 210 | void (*set_bits_per_cycle)(int bpc); |
194 | u32 (*read_data) (void); | 211 | void (*write_command) (const void *buf, unsigned int len); |
195 | void (*write_data) (u32 data); | 212 | void (*read_data) (void *buf, unsigned int len); |
213 | void (*write_data) (const void *buf, unsigned int len); | ||
196 | void (*transfer_area) (int width, int height, | 214 | void (*transfer_area) (int width, int height, |
197 | void (callback)(void * data), void *data); | 215 | void (callback)(void * data), void *data); |
216 | unsigned long max_transmit_size; | ||
198 | }; | 217 | }; |
199 | 218 | ||
219 | struct omapfb_notifier_block { | ||
220 | struct notifier_block nb; | ||
221 | void *data; | ||
222 | }; | ||
223 | |||
224 | typedef int (*omapfb_notifier_callback_t)(struct omapfb_notifier_block *, | ||
225 | unsigned long event, | ||
226 | struct omapfb_device *fbdev); | ||
227 | |||
200 | struct lcd_ctrl { | 228 | struct lcd_ctrl { |
201 | const char *name; | 229 | const char *name; |
202 | void *data; | 230 | void *data; |
@@ -204,9 +232,11 @@ struct lcd_ctrl { | |||
204 | int (*init) (struct omapfb_device *fbdev, | 232 | int (*init) (struct omapfb_device *fbdev, |
205 | int ext_mode, int req_vram_size); | 233 | int ext_mode, int req_vram_size); |
206 | void (*cleanup) (void); | 234 | void (*cleanup) (void); |
235 | void (*bind_client) (struct omapfb_notifier_block *nb); | ||
207 | void (*get_vram_layout)(unsigned long *size, | 236 | void (*get_vram_layout)(unsigned long *size, |
208 | void **virt_base, | 237 | void **virt_base, |
209 | dma_addr_t *phys_base); | 238 | dma_addr_t *phys_base); |
239 | int (*mmap) (struct vm_area_struct *vma); | ||
210 | unsigned long (*get_caps) (void); | 240 | unsigned long (*get_caps) (void); |
211 | int (*set_update_mode)(enum omapfb_update_mode mode); | 241 | int (*set_update_mode)(enum omapfb_update_mode mode); |
212 | enum omapfb_update_mode (*get_update_mode)(void); | 242 | enum omapfb_update_mode (*get_update_mode)(void); |
@@ -240,7 +270,7 @@ struct omapfb_device { | |||
240 | int state; | 270 | int state; |
241 | int ext_lcdc; /* Using external | 271 | int ext_lcdc; /* Using external |
242 | LCD controller */ | 272 | LCD controller */ |
243 | struct semaphore rqueue_sema; | 273 | struct mutex rqueue_mutex; |
244 | 274 | ||
245 | void *vram_virt_base; | 275 | void *vram_virt_base; |
246 | dma_addr_t vram_phys_base; | 276 | dma_addr_t vram_phys_base; |
@@ -261,12 +291,13 @@ struct omapfb_device { | |||
261 | struct device *dev; | 291 | struct device *dev; |
262 | }; | 292 | }; |
263 | 293 | ||
264 | extern struct lcd_panel h3_panel; | 294 | struct omapfb_platform_data { |
265 | extern struct lcd_panel h2_panel; | 295 | struct omap_lcd_config lcd; |
266 | extern struct lcd_panel p2_panel; | 296 | struct omap_fbmem_config fbmem; |
267 | extern struct lcd_panel osk_panel; | 297 | }; |
268 | extern struct lcd_panel innovator1610_panel; | 298 | |
269 | extern struct lcd_panel innovator1510_panel; | 299 | #define OMAPFB_EVENT_READY 1 |
300 | #define OMAPFB_EVENT_DISABLED 2 | ||
270 | 301 | ||
271 | #ifdef CONFIG_ARCH_OMAP1 | 302 | #ifdef CONFIG_ARCH_OMAP1 |
272 | extern struct lcd_ctrl omap1_lcd_ctrl; | 303 | extern struct lcd_ctrl omap1_lcd_ctrl; |
@@ -274,7 +305,20 @@ extern struct lcd_ctrl omap1_lcd_ctrl; | |||
274 | extern struct lcd_ctrl omap2_disp_ctrl; | 305 | extern struct lcd_ctrl omap2_disp_ctrl; |
275 | #endif | 306 | #endif |
276 | 307 | ||
308 | extern void omapfb_register_panel(struct lcd_panel *panel); | ||
277 | extern void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval); | 309 | extern void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval); |
310 | extern void omapfb_notify_clients(struct omapfb_device *fbdev, | ||
311 | unsigned long event); | ||
312 | extern int omapfb_register_client(struct omapfb_notifier_block *nb, | ||
313 | omapfb_notifier_callback_t callback, | ||
314 | void *callback_data); | ||
315 | extern int omapfb_unregister_client(struct omapfb_notifier_block *nb); | ||
316 | extern int omapfb_update_window_async(struct omapfb_update_window *win, | ||
317 | void (*callback)(void *), | ||
318 | void *callback_data); | ||
319 | |||
320 | /* in arch/arm/plat-omap/devices.c */ | ||
321 | extern void omapfb_reserve_mem(void); | ||
278 | 322 | ||
279 | #endif /* __KERNEL__ */ | 323 | #endif /* __KERNEL__ */ |
280 | 324 | ||
diff --git a/include/asm-arm/arch-omap/param.h b/include/asm-arm/arch-omap/param.h new file mode 100644 index 000000000000..face9ad41e97 --- /dev/null +++ b/include/asm-arm/arch-omap/param.h | |||
@@ -0,0 +1,8 @@ | |||
1 | /* | ||
2 | * linux/include/asm-arm/arch-omap/param.h | ||
3 | * | ||
4 | */ | ||
5 | |||
6 | #ifdef CONFIG_OMAP_32K_TIMER_HZ | ||
7 | #define HZ CONFIG_OMAP_32K_TIMER_HZ | ||
8 | #endif | ||
diff --git a/include/asm-arm/arch-omap/pm.h b/include/asm-arm/arch-omap/pm.h index 7c790425e363..05b003f3a94c 100644 --- a/include/asm-arm/arch-omap/pm.h +++ b/include/asm-arm/arch-omap/pm.h | |||
@@ -49,7 +49,7 @@ | |||
49 | 49 | ||
50 | /* | 50 | /* |
51 | * ---------------------------------------------------------------------------- | 51 | * ---------------------------------------------------------------------------- |
52 | * Powermanagement bitmasks | 52 | * Power management bitmasks |
53 | * ---------------------------------------------------------------------------- | 53 | * ---------------------------------------------------------------------------- |
54 | */ | 54 | */ |
55 | #define IDLE_WAIT_CYCLES 0x00000fff | 55 | #define IDLE_WAIT_CYCLES 0x00000fff |
@@ -112,32 +112,59 @@ | |||
112 | #endif | 112 | #endif |
113 | 113 | ||
114 | #ifndef __ASSEMBLER__ | 114 | #ifndef __ASSEMBLER__ |
115 | |||
116 | #include <linux/clk.h> | ||
117 | |||
118 | extern void prevent_idle_sleep(void); | ||
119 | extern void allow_idle_sleep(void); | ||
120 | |||
121 | /** | ||
122 | * clk_deny_idle - Prevents the clock from being idled during MPU idle | ||
123 | * @clk: clock signal handle | ||
124 | */ | ||
125 | void clk_deny_idle(struct clk *clk); | ||
126 | |||
127 | /** | ||
128 | * clk_allow_idle - Counters previous clk_deny_idle | ||
129 | * @clk: clock signal handle | ||
130 | */ | ||
131 | void clk_deny_idle(struct clk *clk); | ||
132 | |||
115 | extern void omap_pm_idle(void); | 133 | extern void omap_pm_idle(void); |
116 | extern void omap_pm_suspend(void); | 134 | extern void omap_pm_suspend(void); |
117 | extern void omap730_cpu_suspend(unsigned short, unsigned short); | 135 | extern void omap730_cpu_suspend(unsigned short, unsigned short); |
118 | extern void omap1510_cpu_suspend(unsigned short, unsigned short); | 136 | extern void omap1510_cpu_suspend(unsigned short, unsigned short); |
119 | extern void omap1610_cpu_suspend(unsigned short, unsigned short); | 137 | extern void omap1610_cpu_suspend(unsigned short, unsigned short); |
138 | extern void omap24xx_cpu_suspend(u32 dll_ctrl, u32 cpu_revision); | ||
120 | extern void omap730_idle_loop_suspend(void); | 139 | extern void omap730_idle_loop_suspend(void); |
121 | extern void omap1510_idle_loop_suspend(void); | 140 | extern void omap1510_idle_loop_suspend(void); |
122 | extern void omap1610_idle_loop_suspend(void); | 141 | extern void omap1610_idle_loop_suspend(void); |
142 | extern void omap24xx_idle_loop_suspend(void); | ||
143 | |||
144 | extern unsigned int omap730_cpu_suspend_sz; | ||
145 | extern unsigned int omap1510_cpu_suspend_sz; | ||
146 | extern unsigned int omap1610_cpu_suspend_sz; | ||
147 | extern unsigned int omap24xx_cpu_suspend_sz; | ||
148 | extern unsigned int omap730_idle_loop_suspend_sz; | ||
149 | extern unsigned int omap1510_idle_loop_suspend_sz; | ||
150 | extern unsigned int omap1610_idle_loop_suspend_sz; | ||
151 | extern unsigned int omap24xx_idle_loop_suspend_sz; | ||
123 | 152 | ||
124 | #ifdef CONFIG_OMAP_SERIAL_WAKE | 153 | #ifdef CONFIG_OMAP_SERIAL_WAKE |
125 | extern void omap_serial_wake_trigger(int enable); | 154 | extern void omap_serial_wake_trigger(int enable); |
126 | #else | 155 | #else |
156 | #define omap_serial_wakeup_init() {} | ||
127 | #define omap_serial_wake_trigger(x) {} | 157 | #define omap_serial_wake_trigger(x) {} |
128 | #endif /* CONFIG_OMAP_SERIAL_WAKE */ | 158 | #endif /* CONFIG_OMAP_SERIAL_WAKE */ |
129 | 159 | ||
130 | extern unsigned int omap730_cpu_suspend_sz; | ||
131 | extern unsigned int omap730_idle_loop_suspend_sz; | ||
132 | extern unsigned int omap1510_cpu_suspend_sz; | ||
133 | extern unsigned int omap1510_idle_loop_suspend_sz; | ||
134 | extern unsigned int omap1610_cpu_suspend_sz; | ||
135 | extern unsigned int omap1610_idle_loop_suspend_sz; | ||
136 | |||
137 | #define ARM_SAVE(x) arm_sleep_save[ARM_SLEEP_SAVE_##x] = omap_readl(x) | 160 | #define ARM_SAVE(x) arm_sleep_save[ARM_SLEEP_SAVE_##x] = omap_readl(x) |
138 | #define ARM_RESTORE(x) omap_writel((arm_sleep_save[ARM_SLEEP_SAVE_##x]), (x)) | 161 | #define ARM_RESTORE(x) omap_writel((arm_sleep_save[ARM_SLEEP_SAVE_##x]), (x)) |
139 | #define ARM_SHOW(x) arm_sleep_save[ARM_SLEEP_SAVE_##x] | 162 | #define ARM_SHOW(x) arm_sleep_save[ARM_SLEEP_SAVE_##x] |
140 | 163 | ||
164 | #define DSP_SAVE(x) dsp_sleep_save[DSP_SLEEP_SAVE_##x] = __raw_readw(x) | ||
165 | #define DSP_RESTORE(x) __raw_writew((dsp_sleep_save[DSP_SLEEP_SAVE_##x]), (x)) | ||
166 | #define DSP_SHOW(x) dsp_sleep_save[DSP_SLEEP_SAVE_##x] | ||
167 | |||
141 | #define ULPD_SAVE(x) ulpd_sleep_save[ULPD_SLEEP_SAVE_##x] = omap_readw(x) | 168 | #define ULPD_SAVE(x) ulpd_sleep_save[ULPD_SLEEP_SAVE_##x] = omap_readw(x) |
142 | #define ULPD_RESTORE(x) omap_writew((ulpd_sleep_save[ULPD_SLEEP_SAVE_##x]), (x)) | 169 | #define ULPD_RESTORE(x) omap_writew((ulpd_sleep_save[ULPD_SLEEP_SAVE_##x]), (x)) |
143 | #define ULPD_SHOW(x) ulpd_sleep_save[ULPD_SLEEP_SAVE_##x] | 170 | #define ULPD_SHOW(x) ulpd_sleep_save[ULPD_SLEEP_SAVE_##x] |
@@ -154,6 +181,10 @@ extern unsigned int omap1610_idle_loop_suspend_sz; | |||
154 | #define MPUI1610_RESTORE(x) omap_writel((mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_##x]), (x)) | 181 | #define MPUI1610_RESTORE(x) omap_writel((mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_##x]), (x)) |
155 | #define MPUI1610_SHOW(x) mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_##x] | 182 | #define MPUI1610_SHOW(x) mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_##x] |
156 | 183 | ||
184 | #define OMAP24XX_SAVE(x) omap24xx_sleep_save[OMAP24XX_SLEEP_SAVE_##x] = x | ||
185 | #define OMAP24XX_RESTORE(x) x = omap24xx_sleep_save[OMAP24XX_SLEEP_SAVE_##x] | ||
186 | #define OMAP24XX_SHOW(x) omap24xx_sleep_save[OMAP24XX_SLEEP_SAVE_##x] | ||
187 | |||
157 | /* | 188 | /* |
158 | * List of global OMAP registers to preserve. | 189 | * List of global OMAP registers to preserve. |
159 | * More ones like CP and general purpose register values are preserved | 190 | * More ones like CP and general purpose register values are preserved |
@@ -176,6 +207,15 @@ enum arm_save_state { | |||
176 | ARM_SLEEP_SAVE_SIZE | 207 | ARM_SLEEP_SAVE_SIZE |
177 | }; | 208 | }; |
178 | 209 | ||
210 | enum dsp_save_state { | ||
211 | DSP_SLEEP_SAVE_START = 0, | ||
212 | /* | ||
213 | * DSP registers 16 bits | ||
214 | */ | ||
215 | DSP_SLEEP_SAVE_DSP_IDLECT2, | ||
216 | DSP_SLEEP_SAVE_SIZE | ||
217 | }; | ||
218 | |||
179 | enum ulpd_save_state { | 219 | enum ulpd_save_state { |
180 | ULPD_SLEEP_SAVE_START = 0, | 220 | ULPD_SLEEP_SAVE_START = 0, |
181 | /* | 221 | /* |
@@ -254,5 +294,30 @@ enum mpui1610_save_state { | |||
254 | #endif | 294 | #endif |
255 | }; | 295 | }; |
256 | 296 | ||
297 | enum omap24xx_save_state { | ||
298 | OMAP24XX_SLEEP_SAVE_START = 0, | ||
299 | OMAP24XX_SLEEP_SAVE_INTC_MIR0, | ||
300 | OMAP24XX_SLEEP_SAVE_INTC_MIR1, | ||
301 | OMAP24XX_SLEEP_SAVE_INTC_MIR2, | ||
302 | OMAP24XX_SLEEP_SAVE_CM_FCLKEN1_CORE, | ||
303 | OMAP24XX_SLEEP_SAVE_CM_FCLKEN2_CORE, | ||
304 | OMAP24XX_SLEEP_SAVE_CM_ICLKEN1_CORE, | ||
305 | OMAP24XX_SLEEP_SAVE_CM_ICLKEN2_CORE, | ||
306 | OMAP24XX_SLEEP_SAVE_CM_ICLKEN4_CORE, | ||
307 | OMAP24XX_SLEEP_SAVE_GPIO1_IRQENABLE1, | ||
308 | OMAP24XX_SLEEP_SAVE_GPIO2_IRQENABLE1, | ||
309 | OMAP24XX_SLEEP_SAVE_GPIO3_IRQENABLE1, | ||
310 | OMAP24XX_SLEEP_SAVE_GPIO4_IRQENABLE1, | ||
311 | OMAP24XX_SLEEP_SAVE_GPIO3_OE, | ||
312 | OMAP24XX_SLEEP_SAVE_GPIO4_OE, | ||
313 | OMAP24XX_SLEEP_SAVE_GPIO3_RISINGDETECT, | ||
314 | OMAP24XX_SLEEP_SAVE_GPIO3_FALLINGDETECT, | ||
315 | OMAP24XX_SLEEP_SAVE_CONTROL_PADCONF_SPI1_NCS2, | ||
316 | OMAP24XX_SLEEP_SAVE_CONTROL_PADCONF_MCBSP1_DX, | ||
317 | OMAP24XX_SLEEP_SAVE_CONTROL_PADCONF_SSI1_FLAG_TX, | ||
318 | OMAP24XX_SLEEP_SAVE_CONTROL_PADCONF_SYS_NIRQW0, | ||
319 | OMAP24XX_SLEEP_SAVE_SIZE | ||
320 | }; | ||
321 | |||
257 | #endif /* ASSEMBLER */ | 322 | #endif /* ASSEMBLER */ |
258 | #endif /* __ASM_ARCH_OMAP_PM_H */ | 323 | #endif /* __ASM_ARCH_OMAP_PM_H */ |
diff --git a/include/asm-arm/arch-omap/prcm.h b/include/asm-arm/arch-omap/prcm.h index 7b48a5cbb15f..7bcaf94bde9f 100644 --- a/include/asm-arm/arch-omap/prcm.h +++ b/include/asm-arm/arch-omap/prcm.h | |||
@@ -1,5 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * prcm.h - Access definations for use in OMAP24XX clock and power management | 2 | * linux/include/asm-arm/arch-omap/prcm.h |
3 | * | ||
4 | * Access definations for use in OMAP24XX clock and power management | ||
3 | * | 5 | * |
4 | * Copyright (C) 2005 Texas Instruments, Inc. | 6 | * Copyright (C) 2005 Texas Instruments, Inc. |
5 | * | 7 | * |
@@ -21,405 +23,7 @@ | |||
21 | #ifndef __ASM_ARM_ARCH_DPM_PRCM_H | 23 | #ifndef __ASM_ARM_ARCH_DPM_PRCM_H |
22 | #define __ASM_ARM_ARCH_DPM_PRCM_H | 24 | #define __ASM_ARM_ARCH_DPM_PRCM_H |
23 | 25 | ||
24 | /* SET_PERFORMANCE_LEVEL PARAMETERS */ | 26 | u32 omap_prcm_get_reset_sources(void); |
25 | #define PRCM_HALF_SPEED 1 | ||
26 | #define PRCM_FULL_SPEED 2 | ||
27 | |||
28 | #ifndef __ASSEMBLER__ | ||
29 | |||
30 | #define PRCM_REG32(offset) __REG32(OMAP24XX_PRCM_BASE + (offset)) | ||
31 | |||
32 | #define PRCM_REVISION PRCM_REG32(0x000) | ||
33 | #define PRCM_SYSCONFIG PRCM_REG32(0x010) | ||
34 | #define PRCM_IRQSTATUS_MPU PRCM_REG32(0x018) | ||
35 | #define PRCM_IRQENABLE_MPU PRCM_REG32(0x01C) | ||
36 | #define PRCM_VOLTCTRL PRCM_REG32(0x050) | ||
37 | #define PRCM_VOLTST PRCM_REG32(0x054) | ||
38 | #define PRCM_CLKSRC_CTRL PRCM_REG32(0x060) | ||
39 | #define PRCM_CLKOUT_CTRL PRCM_REG32(0x070) | ||
40 | #define PRCM_CLKEMUL_CTRL PRCM_REG32(0x078) | ||
41 | #define PRCM_CLKCFG_CTRL PRCM_REG32(0x080) | ||
42 | #define PRCM_CLKCFG_STATUS PRCM_REG32(0x084) | ||
43 | #define PRCM_VOLTSETUP PRCM_REG32(0x090) | ||
44 | #define PRCM_CLKSSETUP PRCM_REG32(0x094) | ||
45 | #define PRCM_POLCTRL PRCM_REG32(0x098) | ||
46 | |||
47 | /* GENERAL PURPOSE */ | ||
48 | #define GENERAL_PURPOSE1 PRCM_REG32(0x0B0) | ||
49 | #define GENERAL_PURPOSE2 PRCM_REG32(0x0B4) | ||
50 | #define GENERAL_PURPOSE3 PRCM_REG32(0x0B8) | ||
51 | #define GENERAL_PURPOSE4 PRCM_REG32(0x0BC) | ||
52 | #define GENERAL_PURPOSE5 PRCM_REG32(0x0C0) | ||
53 | #define GENERAL_PURPOSE6 PRCM_REG32(0x0C4) | ||
54 | #define GENERAL_PURPOSE7 PRCM_REG32(0x0C8) | ||
55 | #define GENERAL_PURPOSE8 PRCM_REG32(0x0CC) | ||
56 | #define GENERAL_PURPOSE9 PRCM_REG32(0x0D0) | ||
57 | #define GENERAL_PURPOSE10 PRCM_REG32(0x0D4) | ||
58 | #define GENERAL_PURPOSE11 PRCM_REG32(0x0D8) | ||
59 | #define GENERAL_PURPOSE12 PRCM_REG32(0x0DC) | ||
60 | #define GENERAL_PURPOSE13 PRCM_REG32(0x0E0) | ||
61 | #define GENERAL_PURPOSE14 PRCM_REG32(0x0E4) | ||
62 | #define GENERAL_PURPOSE15 PRCM_REG32(0x0E8) | ||
63 | #define GENERAL_PURPOSE16 PRCM_REG32(0x0EC) | ||
64 | #define GENERAL_PURPOSE17 PRCM_REG32(0x0F0) | ||
65 | #define GENERAL_PURPOSE18 PRCM_REG32(0x0F4) | ||
66 | #define GENERAL_PURPOSE19 PRCM_REG32(0x0F8) | ||
67 | #define GENERAL_PURPOSE20 PRCM_REG32(0x0FC) | ||
68 | |||
69 | /* MPU */ | ||
70 | #define CM_CLKSEL_MPU PRCM_REG32(0x140) | ||
71 | #define CM_CLKSTCTRL_MPU PRCM_REG32(0x148) | ||
72 | #define RM_RSTST_MPU PRCM_REG32(0x158) | ||
73 | #define PM_WKDEP_MPU PRCM_REG32(0x1C8) | ||
74 | #define PM_EVGENCTRL_MPU PRCM_REG32(0x1D4) | ||
75 | #define PM_EVEGENONTIM_MPU PRCM_REG32(0x1D8) | ||
76 | #define PM_EVEGENOFFTIM_MPU PRCM_REG32(0x1DC) | ||
77 | #define PM_PWSTCTRL_MPU PRCM_REG32(0x1E0) | ||
78 | #define PM_PWSTST_MPU PRCM_REG32(0x1E4) | ||
79 | |||
80 | /* CORE */ | ||
81 | #define CM_FCLKEN1_CORE PRCM_REG32(0x200) | ||
82 | #define CM_FCLKEN2_CORE PRCM_REG32(0x204) | ||
83 | #define CM_FCLKEN3_CORE PRCM_REG32(0x208) | ||
84 | #define CM_ICLKEN1_CORE PRCM_REG32(0x210) | ||
85 | #define CM_ICLKEN2_CORE PRCM_REG32(0x214) | ||
86 | #define CM_ICLKEN3_CORE PRCM_REG32(0x218) | ||
87 | #define CM_ICLKEN4_CORE PRCM_REG32(0x21C) | ||
88 | #define CM_IDLEST1_CORE PRCM_REG32(0x220) | ||
89 | #define CM_IDLEST2_CORE PRCM_REG32(0x224) | ||
90 | #define CM_IDLEST3_CORE PRCM_REG32(0x228) | ||
91 | #define CM_IDLEST4_CORE PRCM_REG32(0x22C) | ||
92 | #define CM_AUTOIDLE1_CORE PRCM_REG32(0x230) | ||
93 | #define CM_AUTOIDLE2_CORE PRCM_REG32(0x234) | ||
94 | #define CM_AUTOIDLE3_CORE PRCM_REG32(0x238) | ||
95 | #define CM_AUTOIDLE4_CORE PRCM_REG32(0x23C) | ||
96 | #define CM_CLKSEL1_CORE PRCM_REG32(0x240) | ||
97 | #define CM_CLKSEL2_CORE PRCM_REG32(0x244) | ||
98 | #define CM_CLKSTCTRL_CORE PRCM_REG32(0x248) | ||
99 | #define PM_WKEN1_CORE PRCM_REG32(0x2A0) | ||
100 | #define PM_WKEN2_CORE PRCM_REG32(0x2A4) | ||
101 | #define PM_WKST1_CORE PRCM_REG32(0x2B0) | ||
102 | #define PM_WKST2_CORE PRCM_REG32(0x2B4) | ||
103 | #define PM_WKDEP_CORE PRCM_REG32(0x2C8) | ||
104 | #define PM_PWSTCTRL_CORE PRCM_REG32(0x2E0) | ||
105 | #define PM_PWSTST_CORE PRCM_REG32(0x2E4) | ||
106 | |||
107 | /* GFX */ | ||
108 | #define CM_FCLKEN_GFX PRCM_REG32(0x300) | ||
109 | #define CM_ICLKEN_GFX PRCM_REG32(0x310) | ||
110 | #define CM_IDLEST_GFX PRCM_REG32(0x320) | ||
111 | #define CM_CLKSEL_GFX PRCM_REG32(0x340) | ||
112 | #define CM_CLKSTCTRL_GFX PRCM_REG32(0x348) | ||
113 | #define RM_RSTCTRL_GFX PRCM_REG32(0x350) | ||
114 | #define RM_RSTST_GFX PRCM_REG32(0x358) | ||
115 | #define PM_WKDEP_GFX PRCM_REG32(0x3C8) | ||
116 | #define PM_PWSTCTRL_GFX PRCM_REG32(0x3E0) | ||
117 | #define PM_PWSTST_GFX PRCM_REG32(0x3E4) | ||
118 | |||
119 | /* WAKE-UP */ | ||
120 | #define CM_FCLKEN_WKUP PRCM_REG32(0x400) | ||
121 | #define CM_ICLKEN_WKUP PRCM_REG32(0x410) | ||
122 | #define CM_IDLEST_WKUP PRCM_REG32(0x420) | ||
123 | #define CM_AUTOIDLE_WKUP PRCM_REG32(0x430) | ||
124 | #define CM_CLKSEL_WKUP PRCM_REG32(0x440) | ||
125 | #define RM_RSTCTRL_WKUP PRCM_REG32(0x450) | ||
126 | #define RM_RSTTIME_WKUP PRCM_REG32(0x454) | ||
127 | #define RM_RSTST_WKUP PRCM_REG32(0x458) | ||
128 | #define PM_WKEN_WKUP PRCM_REG32(0x4A0) | ||
129 | #define PM_WKST_WKUP PRCM_REG32(0x4B0) | ||
130 | |||
131 | /* CLOCKS */ | ||
132 | #define CM_CLKEN_PLL PRCM_REG32(0x500) | ||
133 | #define CM_IDLEST_CKGEN PRCM_REG32(0x520) | ||
134 | #define CM_AUTOIDLE_PLL PRCM_REG32(0x530) | ||
135 | #define CM_CLKSEL1_PLL PRCM_REG32(0x540) | ||
136 | #define CM_CLKSEL2_PLL PRCM_REG32(0x544) | ||
137 | |||
138 | /* DSP */ | ||
139 | #define CM_FCLKEN_DSP PRCM_REG32(0x800) | ||
140 | #define CM_ICLKEN_DSP PRCM_REG32(0x810) | ||
141 | #define CM_IDLEST_DSP PRCM_REG32(0x820) | ||
142 | #define CM_AUTOIDLE_DSP PRCM_REG32(0x830) | ||
143 | #define CM_CLKSEL_DSP PRCM_REG32(0x840) | ||
144 | #define CM_CLKSTCTRL_DSP PRCM_REG32(0x848) | ||
145 | #define RM_RSTCTRL_DSP PRCM_REG32(0x850) | ||
146 | #define RM_RSTST_DSP PRCM_REG32(0x858) | ||
147 | #define PM_WKEN_DSP PRCM_REG32(0x8A0) | ||
148 | #define PM_WKDEP_DSP PRCM_REG32(0x8C8) | ||
149 | #define PM_PWSTCTRL_DSP PRCM_REG32(0x8E0) | ||
150 | #define PM_PWSTST_DSP PRCM_REG32(0x8E4) | ||
151 | #define PRCM_IRQSTATUS_DSP PRCM_REG32(0x8F0) | ||
152 | #define PRCM_IRQENABLE_DSP PRCM_REG32(0x8F4) | ||
153 | |||
154 | /* IVA */ | ||
155 | #define PRCM_IRQSTATUS_IVA PRCM_REG32(0x8F8) | ||
156 | #define PRCM_IRQENABLE_IVA PRCM_REG32(0x8FC) | ||
157 | |||
158 | /* Modem on 2430 */ | ||
159 | #define CM_FCLKEN_MDM PRCM_REG32(0xC00) | ||
160 | #define CM_ICLKEN_MDM PRCM_REG32(0xC10) | ||
161 | #define CM_IDLEST_MDM PRCM_REG32(0xC20) | ||
162 | #define CM_CLKSEL_MDM PRCM_REG32(0xC40) | ||
163 | |||
164 | /* FIXME: Move to header for 2430 */ | ||
165 | #define DISP_BASE (OMAP24XX_L4_IO_BASE+0x50000) | ||
166 | #define DISP_REG32(offset) __REG32(DISP_BASE + (offset)) | ||
167 | |||
168 | #define OMAP24XX_GPMC_BASE (L3_24XX_BASE + 0xa000) | ||
169 | #define GPMC_BASE (OMAP24XX_GPMC_BASE) | ||
170 | #define GPMC_REG32(offset) __REG32(GPMC_BASE + (offset)) | ||
171 | |||
172 | #define GPT1_BASE (OMAP24XX_GPT1) | ||
173 | #define GPT1_REG32(offset) __REG32(GPT1_BASE + (offset)) | ||
174 | |||
175 | /* Misc sysconfig */ | ||
176 | #define DISPC_SYSCONFIG DISP_REG32(0x410) | ||
177 | #define SPI_BASE (OMAP24XX_L4_IO_BASE+0x98000) | ||
178 | #define MCSPI1_SYSCONFIG __REG32(SPI_BASE + 0x10) | ||
179 | #define MCSPI2_SYSCONFIG __REG32(SPI_BASE+0x2000 + 0x10) | ||
180 | |||
181 | //#define DSP_MMU_SYSCONFIG 0x5A000010 | ||
182 | #define CAMERA_MMU_SYSCONFIG __REG32(DISP_BASE+0x2C10) | ||
183 | //#define IVA_MMU_SYSCONFIG 0x5D000010 | ||
184 | //#define DSP_DMA_SYSCONFIG 0x00FCC02C | ||
185 | #define CAMERA_DMA_SYSCONFIG __REG32(DISP_BASE+0x282C) | ||
186 | #define SYSTEM_DMA_SYSCONFIG __REG32(DISP_BASE+0x602C) | ||
187 | #define GPMC_SYSCONFIG GPMC_REG32(0x010) | ||
188 | #define MAILBOXES_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE+0x94010) | ||
189 | #define UART1_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE+0x6A054) | ||
190 | #define UART2_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE+0x6C054) | ||
191 | #define UART3_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE+0x6E054) | ||
192 | //#define IVA_SYSCONFIG 0x5C060010 | ||
193 | #define SDRC_SYSCONFIG __REG32(OMAP24XX_SDRC_BASE+0x10) | ||
194 | #define SMS_SYSCONFIG __REG32(OMAP24XX_SMS_BASE+0x10) | ||
195 | #define SSI_SYSCONFIG __REG32(DISP_BASE+0x8010) | ||
196 | //#define VLYNQ_SYSCONFIG 0x67FFFE10 | ||
197 | |||
198 | /* rkw - good cannidates for PM_ to start what nm was trying */ | ||
199 | #define OMAP24XX_GPT2 (OMAP24XX_L4_IO_BASE+0x2A000) | ||
200 | #define OMAP24XX_GPT3 (OMAP24XX_L4_IO_BASE+0x78000) | ||
201 | #define OMAP24XX_GPT4 (OMAP24XX_L4_IO_BASE+0x7A000) | ||
202 | #define OMAP24XX_GPT5 (OMAP24XX_L4_IO_BASE+0x7C000) | ||
203 | #define OMAP24XX_GPT6 (OMAP24XX_L4_IO_BASE+0x7E000) | ||
204 | #define OMAP24XX_GPT7 (OMAP24XX_L4_IO_BASE+0x80000) | ||
205 | #define OMAP24XX_GPT8 (OMAP24XX_L4_IO_BASE+0x82000) | ||
206 | #define OMAP24XX_GPT9 (OMAP24XX_L4_IO_BASE+0x84000) | ||
207 | #define OMAP24XX_GPT10 (OMAP24XX_L4_IO_BASE+0x86000) | ||
208 | #define OMAP24XX_GPT11 (OMAP24XX_L4_IO_BASE+0x88000) | ||
209 | #define OMAP24XX_GPT12 (OMAP24XX_L4_IO_BASE+0x8A000) | ||
210 | |||
211 | #define GPTIMER1_SYSCONFIG GPT1_REG32(0x010) | ||
212 | #define GPTIMER2_SYSCONFIG __REG32(OMAP24XX_GPT2 + 0x10) | ||
213 | #define GPTIMER3_SYSCONFIG __REG32(OMAP24XX_GPT3 + 0x10) | ||
214 | #define GPTIMER4_SYSCONFIG __REG32(OMAP24XX_GPT4 + 0x10) | ||
215 | #define GPTIMER5_SYSCONFIG __REG32(OMAP24XX_GPT5 + 0x10) | ||
216 | #define GPTIMER6_SYSCONFIG __REG32(OMAP24XX_GPT6 + 0x10) | ||
217 | #define GPTIMER7_SYSCONFIG __REG32(OMAP24XX_GPT7 + 0x10) | ||
218 | #define GPTIMER8_SYSCONFIG __REG32(OMAP24XX_GPT8 + 0x10) | ||
219 | #define GPTIMER9_SYSCONFIG __REG32(OMAP24XX_GPT9 + 0x10) | ||
220 | #define GPTIMER10_SYSCONFIG __REG32(OMAP24XX_GPT10 + 0x10) | ||
221 | #define GPTIMER11_SYSCONFIG __REG32(OMAP24XX_GPT11 + 0x10) | ||
222 | #define GPTIMER12_SYSCONFIG __REG32(OMAP24XX_GPT12 + 0x10) | ||
223 | |||
224 | #define GPIOX_BASE(X) (OMAP24XX_GPIO_BASE+(0x2000*((X)-1))) | ||
225 | |||
226 | #define GPIO1_SYSCONFIG __REG32((GPIOX_BASE(1)+0x10)) | ||
227 | #define GPIO2_SYSCONFIG __REG32((GPIOX_BASE(2)+0x10)) | ||
228 | #define GPIO3_SYSCONFIG __REG32((GPIOX_BASE(3)+0x10)) | ||
229 | #define GPIO4_SYSCONFIG __REG32((GPIOX_BASE(4)+0x10)) | ||
230 | |||
231 | /* GP TIMER 1 */ | ||
232 | #define GPTIMER1_TISTAT GPT1_REG32(0x014) | ||
233 | #define GPTIMER1_TISR GPT1_REG32(0x018) | ||
234 | #define GPTIMER1_TIER GPT1_REG32(0x01C) | ||
235 | #define GPTIMER1_TWER GPT1_REG32(0x020) | ||
236 | #define GPTIMER1_TCLR GPT1_REG32(0x024) | ||
237 | #define GPTIMER1_TCRR GPT1_REG32(0x028) | ||
238 | #define GPTIMER1_TLDR GPT1_REG32(0x02C) | ||
239 | #define GPTIMER1_TTGR GPT1_REG32(0x030) | ||
240 | #define GPTIMER1_TWPS GPT1_REG32(0x034) | ||
241 | #define GPTIMER1_TMAR GPT1_REG32(0x038) | ||
242 | #define GPTIMER1_TCAR1 GPT1_REG32(0x03C) | ||
243 | #define GPTIMER1_TSICR GPT1_REG32(0x040) | ||
244 | #define GPTIMER1_TCAR2 GPT1_REG32(0x044) | ||
245 | |||
246 | /* rkw -- base fix up please... */ | ||
247 | #define GPTIMER3_TISR __REG32(OMAP24XX_L4_IO_BASE+0x78018) | ||
248 | |||
249 | /* SDRC */ | ||
250 | #define SDRC_DLLA_CTRL __REG32(OMAP24XX_SDRC_BASE+0x060) | ||
251 | #define SDRC_DLLA_STATUS __REG32(OMAP24XX_SDRC_BASE+0x064) | ||
252 | #define SDRC_DLLB_CTRL __REG32(OMAP24XX_SDRC_BASE+0x068) | ||
253 | #define SDRC_DLLB_STATUS __REG32(OMAP24XX_SDRC_BASE+0x06C) | ||
254 | #define SDRC_POWER __REG32(OMAP24XX_SDRC_BASE+0x070) | ||
255 | #define SDRC_MR_0 __REG32(OMAP24XX_SDRC_BASE+0x084) | ||
256 | |||
257 | /* GPIO 1 */ | ||
258 | #define GPIO1_BASE GPIOX_BASE(1) | ||
259 | #define GPIO1_REG32(offset) __REG32(GPIO1_BASE + (offset)) | ||
260 | #define GPIO1_IRQENABLE1 GPIO1_REG32(0x01C) | ||
261 | #define GPIO1_IRQSTATUS1 GPIO1_REG32(0x018) | ||
262 | #define GPIO1_IRQENABLE2 GPIO1_REG32(0x02C) | ||
263 | #define GPIO1_IRQSTATUS2 GPIO1_REG32(0x028) | ||
264 | #define GPIO1_WAKEUPENABLE GPIO1_REG32(0x020) | ||
265 | #define GPIO1_RISINGDETECT GPIO1_REG32(0x048) | ||
266 | #define GPIO1_DATAIN GPIO1_REG32(0x038) | ||
267 | #define GPIO1_OE GPIO1_REG32(0x034) | ||
268 | #define GPIO1_DATAOUT GPIO1_REG32(0x03C) | ||
269 | |||
270 | /* GPIO2 */ | ||
271 | #define GPIO2_BASE GPIOX_BASE(2) | ||
272 | #define GPIO2_REG32(offset) __REG32(GPIO2_BASE + (offset)) | ||
273 | #define GPIO2_IRQENABLE1 GPIO2_REG32(0x01C) | ||
274 | #define GPIO2_IRQSTATUS1 GPIO2_REG32(0x018) | ||
275 | #define GPIO2_IRQENABLE2 GPIO2_REG32(0x02C) | ||
276 | #define GPIO2_IRQSTATUS2 GPIO2_REG32(0x028) | ||
277 | #define GPIO2_WAKEUPENABLE GPIO2_REG32(0x020) | ||
278 | #define GPIO2_RISINGDETECT GPIO2_REG32(0x048) | ||
279 | #define GPIO2_DATAIN GPIO2_REG32(0x038) | ||
280 | #define GPIO2_OE GPIO2_REG32(0x034) | ||
281 | #define GPIO2_DATAOUT GPIO2_REG32(0x03C) | ||
282 | |||
283 | /* GPIO 3 */ | ||
284 | #define GPIO3_BASE GPIOX_BASE(3) | ||
285 | #define GPIO3_REG32(offset) __REG32(GPIO3_BASE + (offset)) | ||
286 | #define GPIO3_IRQENABLE1 GPIO3_REG32(0x01C) | ||
287 | #define GPIO3_IRQSTATUS1 GPIO3_REG32(0x018) | ||
288 | #define GPIO3_IRQENABLE2 GPIO3_REG32(0x02C) | ||
289 | #define GPIO3_IRQSTATUS2 GPIO3_REG32(0x028) | ||
290 | #define GPIO3_WAKEUPENABLE GPIO3_REG32(0x020) | ||
291 | #define GPIO3_RISINGDETECT GPIO3_REG32(0x048) | ||
292 | #define GPIO3_FALLINGDETECT GPIO3_REG32(0x04C) | ||
293 | #define GPIO3_DATAIN GPIO3_REG32(0x038) | ||
294 | #define GPIO3_OE GPIO3_REG32(0x034) | ||
295 | #define GPIO3_DATAOUT GPIO3_REG32(0x03C) | ||
296 | #define GPIO3_DEBOUNCENABLE GPIO3_REG32(0x050) | ||
297 | #define GPIO3_DEBOUNCINGTIME GPIO3_REG32(0x054) | ||
298 | |||
299 | /* GPIO 4 */ | ||
300 | #define GPIO4_BASE GPIOX_BASE(4) | ||
301 | #define GPIO4_REG32(offset) __REG32(GPIO4_BASE + (offset)) | ||
302 | #define GPIO4_IRQENABLE1 GPIO4_REG32(0x01C) | ||
303 | #define GPIO4_IRQSTATUS1 GPIO4_REG32(0x018) | ||
304 | #define GPIO4_IRQENABLE2 GPIO4_REG32(0x02C) | ||
305 | #define GPIO4_IRQSTATUS2 GPIO4_REG32(0x028) | ||
306 | #define GPIO4_WAKEUPENABLE GPIO4_REG32(0x020) | ||
307 | #define GPIO4_RISINGDETECT GPIO4_REG32(0x048) | ||
308 | #define GPIO4_FALLINGDETECT GPIO4_REG32(0x04C) | ||
309 | #define GPIO4_DATAIN GPIO4_REG32(0x038) | ||
310 | #define GPIO4_OE GPIO4_REG32(0x034) | ||
311 | #define GPIO4_DATAOUT GPIO4_REG32(0x03C) | ||
312 | #define GPIO4_DEBOUNCENABLE GPIO4_REG32(0x050) | ||
313 | #define GPIO4_DEBOUNCINGTIME GPIO4_REG32(0x054) | ||
314 | |||
315 | |||
316 | /* IO CONFIG */ | ||
317 | #define CONTROL_BASE (OMAP24XX_CTRL_BASE) | ||
318 | #define CONTROL_REG32(offset) __REG32(CONTROL_BASE + (offset)) | ||
319 | |||
320 | #define CONTROL_PADCONF_SPI1_NCS2 CONTROL_REG32(0x104) | ||
321 | #define CONTROL_PADCONF_SYS_XTALOUT CONTROL_REG32(0x134) | ||
322 | #define CONTROL_PADCONF_UART1_RX CONTROL_REG32(0x0C8) | ||
323 | #define CONTROL_PADCONF_MCBSP1_DX CONTROL_REG32(0x10C) | ||
324 | #define CONTROL_PADCONF_GPMC_NCS4 CONTROL_REG32(0x090) | ||
325 | #define CONTROL_PADCONF_DSS_D5 CONTROL_REG32(0x0B8) | ||
326 | #define CONTROL_PADCONF_DSS_D9 CONTROL_REG32(0x0BC) | ||
327 | #define CONTROL_PADCONF_DSS_D13 CONTROL_REG32(0x0C0) | ||
328 | #define CONTROL_PADCONF_DSS_VSYNC CONTROL_REG32(0x0CC) | ||
329 | |||
330 | /* CONTROL */ | ||
331 | #define CONTROL_DEVCONF CONTROL_REG32(0x274) | ||
332 | |||
333 | /* INTERRUPT CONTROLLER */ | ||
334 | #define INTC_BASE (OMAP24XX_L4_IO_BASE+0xfe000) | ||
335 | #define INTC_REG32(offset) __REG32(INTC_BASE + (offset)) | ||
336 | |||
337 | #define INTC1_U_BASE INTC_REG32(0x000) | ||
338 | #define INTC_MIR0 INTC_REG32(0x084) | ||
339 | #define INTC_MIR_SET0 INTC_REG32(0x08C) | ||
340 | #define INTC_MIR_CLEAR0 INTC_REG32(0x088) | ||
341 | #define INTC_ISR_CLEAR0 INTC_REG32(0x094) | ||
342 | #define INTC_MIR1 INTC_REG32(0x0A4) | ||
343 | #define INTC_MIR_SET1 INTC_REG32(0x0AC) | ||
344 | #define INTC_MIR_CLEAR1 INTC_REG32(0x0A8) | ||
345 | #define INTC_ISR_CLEAR1 INTC_REG32(0x0B4) | ||
346 | #define INTC_MIR2 INTC_REG32(0x0C4) | ||
347 | #define INTC_MIR_SET2 INTC_REG32(0x0CC) | ||
348 | #define INTC_MIR_CLEAR2 INTC_REG32(0x0C8) | ||
349 | #define INTC_ISR_CLEAR2 INTC_REG32(0x0D4) | ||
350 | #define INTC_SIR_IRQ INTC_REG32(0x040) | ||
351 | #define INTC_CONTROL INTC_REG32(0x048) | ||
352 | #define INTC_ILR11 INTC_REG32(0x12C) | ||
353 | #define INTC_ILR32 INTC_REG32(0x180) | ||
354 | #define INTC_ILR37 INTC_REG32(0x194) | ||
355 | #define INTC_SYSCONFIG INTC_REG32(0x010) | ||
356 | |||
357 | /* RAM FIREWALL */ | ||
358 | #define RAMFW_BASE (0x68005000) | ||
359 | #define RAMFW_REG32(offset) __REG32(RAMFW_BASE + (offset)) | ||
360 | |||
361 | #define RAMFW_REQINFOPERM0 RAMFW_REG32(0x048) | ||
362 | #define RAMFW_READPERM0 RAMFW_REG32(0x050) | ||
363 | #define RAMFW_WRITEPERM0 RAMFW_REG32(0x058) | ||
364 | |||
365 | /* GPMC CS1 FPGA ON USER INTERFACE MODULE */ | ||
366 | //#define DEBUG_BOARD_LED_REGISTER 0x04000014 | ||
367 | |||
368 | /* GPMC CS0 */ | ||
369 | #define GPMC_CONFIG1_0 GPMC_REG32(0x060) | ||
370 | #define GPMC_CONFIG2_0 GPMC_REG32(0x064) | ||
371 | #define GPMC_CONFIG3_0 GPMC_REG32(0x068) | ||
372 | #define GPMC_CONFIG4_0 GPMC_REG32(0x06C) | ||
373 | #define GPMC_CONFIG5_0 GPMC_REG32(0x070) | ||
374 | #define GPMC_CONFIG6_0 GPMC_REG32(0x074) | ||
375 | #define GPMC_CONFIG7_0 GPMC_REG32(0x078) | ||
376 | |||
377 | /* GPMC CS1 */ | ||
378 | #define GPMC_CONFIG1_1 GPMC_REG32(0x090) | ||
379 | #define GPMC_CONFIG2_1 GPMC_REG32(0x094) | ||
380 | #define GPMC_CONFIG3_1 GPMC_REG32(0x098) | ||
381 | #define GPMC_CONFIG4_1 GPMC_REG32(0x09C) | ||
382 | #define GPMC_CONFIG5_1 GPMC_REG32(0x0a0) | ||
383 | #define GPMC_CONFIG6_1 GPMC_REG32(0x0a4) | ||
384 | #define GPMC_CONFIG7_1 GPMC_REG32(0x0a8) | ||
385 | |||
386 | /* DSS */ | ||
387 | #define DSS_CONTROL DISP_REG32(0x040) | ||
388 | #define DISPC_CONTROL DISP_REG32(0x440) | ||
389 | #define DISPC_SYSSTATUS DISP_REG32(0x414) | ||
390 | #define DISPC_IRQSTATUS DISP_REG32(0x418) | ||
391 | #define DISPC_IRQENABLE DISP_REG32(0x41C) | ||
392 | #define DISPC_CONFIG DISP_REG32(0x444) | ||
393 | #define DISPC_DEFAULT_COLOR0 DISP_REG32(0x44C) | ||
394 | #define DISPC_DEFAULT_COLOR1 DISP_REG32(0x450) | ||
395 | #define DISPC_TRANS_COLOR0 DISP_REG32(0x454) | ||
396 | #define DISPC_TRANS_COLOR1 DISP_REG32(0x458) | ||
397 | #define DISPC_LINE_NUMBER DISP_REG32(0x460) | ||
398 | #define DISPC_TIMING_H DISP_REG32(0x464) | ||
399 | #define DISPC_TIMING_V DISP_REG32(0x468) | ||
400 | #define DISPC_POL_FREQ DISP_REG32(0x46C) | ||
401 | #define DISPC_DIVISOR DISP_REG32(0x470) | ||
402 | #define DISPC_SIZE_DIG DISP_REG32(0x478) | ||
403 | #define DISPC_SIZE_LCD DISP_REG32(0x47C) | ||
404 | #define DISPC_GFX_BA0 DISP_REG32(0x480) | ||
405 | #define DISPC_GFX_BA1 DISP_REG32(0x484) | ||
406 | #define DISPC_GFX_POSITION DISP_REG32(0x488) | ||
407 | #define DISPC_GFX_SIZE DISP_REG32(0x48C) | ||
408 | #define DISPC_GFX_ATTRIBUTES DISP_REG32(0x4A0) | ||
409 | #define DISPC_GFX_FIFO_THRESHOLD DISP_REG32(0x4A4) | ||
410 | #define DISPC_GFX_ROW_INC DISP_REG32(0x4AC) | ||
411 | #define DISPC_GFX_PIXEL_INC DISP_REG32(0x4B0) | ||
412 | #define DISPC_GFX_WINDOW_SKIP DISP_REG32(0x4B4) | ||
413 | #define DISPC_GFX_TABLE_BA DISP_REG32(0x4B8) | ||
414 | #define DISPC_DATA_CYCLE1 DISP_REG32(0x5D4) | ||
415 | #define DISPC_DATA_CYCLE2 DISP_REG32(0x5D8) | ||
416 | #define DISPC_DATA_CYCLE3 DISP_REG32(0x5DC) | ||
417 | |||
418 | /* Wake up define for board */ | ||
419 | #define GPIO97 (1 << 1) | ||
420 | #define GPIO88 (1 << 24) | ||
421 | |||
422 | #endif /* __ASSEMBLER__ */ | ||
423 | 27 | ||
424 | #endif | 28 | #endif |
425 | 29 | ||
diff --git a/include/asm-arm/arch-omap/sram.h b/include/asm-arm/arch-omap/sram.h index e72ccbf0fe06..6fc0dd57b7c3 100644 --- a/include/asm-arm/arch-omap/sram.h +++ b/include/asm-arm/arch-omap/sram.h | |||
@@ -20,6 +20,8 @@ extern void omap2_sram_reprogram_sdrc(u32 perf_level, u32 dll_val, | |||
20 | u32 mem_type); | 20 | u32 mem_type); |
21 | extern u32 omap2_set_prcm(u32 dpll_ctrl_val, u32 sdrc_rfr_val, int bypass); | 21 | extern u32 omap2_set_prcm(u32 dpll_ctrl_val, u32 sdrc_rfr_val, int bypass); |
22 | 22 | ||
23 | extern unsigned long omap_fb_sram_start; | ||
24 | extern unsigned long omap_fb_sram_size; | ||
23 | 25 | ||
24 | /* Do not use these */ | 26 | /* Do not use these */ |
25 | extern void sram_reprogram_clock(u32 ckctl, u32 dpllctl); | 27 | extern void sram_reprogram_clock(u32 ckctl, u32 dpllctl); |
diff --git a/include/asm-arm/arch-omap/system.h b/include/asm-arm/arch-omap/system.h index 6724a81bd10b..67970d1a2020 100644 --- a/include/asm-arm/arch-omap/system.h +++ b/include/asm-arm/arch-omap/system.h | |||
@@ -9,12 +9,13 @@ | |||
9 | 9 | ||
10 | #include <asm/mach-types.h> | 10 | #include <asm/mach-types.h> |
11 | #include <asm/hardware.h> | 11 | #include <asm/hardware.h> |
12 | #include <asm/arch/prcm.h> | ||
13 | 12 | ||
14 | #ifndef CONFIG_MACH_VOICEBLUE | 13 | #ifndef CONFIG_MACH_VOICEBLUE |
15 | #define voiceblue_reset() do {} while (0) | 14 | #define voiceblue_reset() do {} while (0) |
16 | #endif | 15 | #endif |
17 | 16 | ||
17 | extern void omap_prcm_arch_reset(char mode); | ||
18 | |||
18 | static inline void arch_idle(void) | 19 | static inline void arch_idle(void) |
19 | { | 20 | { |
20 | cpu_do_idle(); | 21 | cpu_do_idle(); |
@@ -38,24 +39,12 @@ static inline void omap1_arch_reset(char mode) | |||
38 | omap_writew(1, ARM_RSTCT1); | 39 | omap_writew(1, ARM_RSTCT1); |
39 | } | 40 | } |
40 | 41 | ||
41 | static inline void omap2_arch_reset(char mode) | ||
42 | { | ||
43 | u32 rate; | ||
44 | struct clk *vclk, *sclk; | ||
45 | |||
46 | vclk = clk_get(NULL, "virt_prcm_set"); | ||
47 | sclk = clk_get(NULL, "sys_ck"); | ||
48 | rate = clk_get_rate(sclk); | ||
49 | clk_set_rate(vclk, rate); /* go to bypass for OMAP limitation */ | ||
50 | RM_RSTCTRL_WKUP |= 2; | ||
51 | } | ||
52 | |||
53 | static inline void arch_reset(char mode) | 42 | static inline void arch_reset(char mode) |
54 | { | 43 | { |
55 | if (!cpu_is_omap24xx()) | 44 | if (!cpu_is_omap24xx()) |
56 | omap1_arch_reset(mode); | 45 | omap1_arch_reset(mode); |
57 | else | 46 | else |
58 | omap2_arch_reset(mode); | 47 | omap_prcm_arch_reset(mode); |
59 | } | 48 | } |
60 | 49 | ||
61 | #endif | 50 | #endif |
diff --git a/include/asm-arm/arch-s3c2410/entry-macro.S b/include/asm-arm/arch-s3c2410/entry-macro.S index cc06b1bd37b2..894c35cf3b1e 100644 --- a/include/asm-arm/arch-s3c2410/entry-macro.S +++ b/include/asm-arm/arch-s3c2410/entry-macro.S | |||
@@ -6,116 +6,83 @@ | |||
6 | * This file is licensed under the terms of the GNU General Public | 6 | * This file is licensed under the terms of the GNU General Public |
7 | * License version 2. This program is licensed "as is" without any | 7 | * License version 2. This program is licensed "as is" without any |
8 | * warranty of any kind, whether express or implied. | 8 | * warranty of any kind, whether express or implied. |
9 | */ | ||
10 | |||
11 | /* We have a problem that the INTOFFSET register does not always | ||
12 | * show one interrupt. Occasionally we get two interrupts through | ||
13 | * the prioritiser, and this causes the INTOFFSET register to show | ||
14 | * what looks like the logical-or of the two interrupt numbers. | ||
15 | * | ||
16 | * Thanks to Klaus, Shannon, et al for helping to debug this problem | ||
17 | */ | ||
18 | |||
19 | #define INTPND (0x10) | ||
20 | #define INTOFFSET (0x14) | ||
21 | #define EXTINTPEND (0xa8) | ||
22 | #define EXTINTMASK (0xa4) | ||
9 | 23 | ||
10 | * Modifications: | ||
11 | * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA | ||
12 | */ | ||
13 | #include <asm/hardware.h> | 24 | #include <asm/hardware.h> |
14 | #include <asm/arch/irqs.h> | 25 | #include <asm/arch/irqs.h> |
15 | 26 | ||
16 | |||
17 | .macro get_irqnr_and_base, irqnr, irqstat, base, tmp | 27 | .macro get_irqnr_and_base, irqnr, irqstat, base, tmp |
18 | 28 | ||
19 | mov \tmp, #S3C24XX_VA_IRQ | 29 | mov \base, #S3C24XX_VA_IRQ |
20 | ldr \irqnr, [ \tmp, #0x14 ] @ get irq no | 30 | |
21 | 30000: | 31 | ldr \irqstat, [ \base, #INTPND] |
22 | teq \irqnr, #4 | 32 | bics \irqnr, \irqstat, #3<<4 @@ only an GPIO IRQ |
23 | teqne \irqnr, #5 | 33 | beq 2000f |
24 | beq 1002f @ external irq reg | 34 | |
25 | 35 | @@ try the interrupt offset register, since it is there | |
26 | @ debug check to see if interrupt reported is the same | 36 | |
27 | @ as the offset.... | 37 | ldr \irqnr, [ \base, #INTOFFSET ] |
28 | 38 | mov \tmp, #1 | |
29 | teq \irqnr, #0 | 39 | tst \irqstat, \tmp, lsl \irqnr |
30 | beq 20002f | 40 | addne \irqnr, \irqnr, #IRQ_EINT0 |
31 | ldr \irqstat, [ \tmp, #0x10 ] @ INTPND | 41 | bne 1001f |
32 | mov \irqstat, \irqstat, lsr \irqnr | 42 | |
33 | tst \irqstat, #1 | 43 | @@ the number specified is not a valid irq, so try |
34 | bne 20002f | 44 | @@ and work it out for ourselves |
35 | 45 | ||
36 | /* debug/warning if we get an invalud response from the | 46 | mov \irqnr, #IRQ_EINT0 @@ start here |
37 | * INTOFFSET register */ | 47 | b 3000f |
38 | #if 1 | 48 | |
39 | stmfd r13!, { r0 - r4 , r8-r12, r14 } | 49 | 2000: |
40 | ldr r1, [ \tmp, #0x14 ] @ INTOFFSET | 50 | @@ load the GPIO interrupt register, and check it |
41 | ldr r2, [ \tmp, #0x10 ] @ INTPND | 51 | |
42 | ldr r3, [ \tmp, #0x00 ] @ SRCPND | 52 | add \tmp, \base, #S3C24XX_VA_GPIO - S3C24XX_VA_IRQ |
43 | adr r0, 20003f | 53 | ldr \irqstat, [ \tmp, # EXTINTPEND ] |
44 | bl printk | 54 | ldr \irqnr, [ \tmp, # EXTINTMASK ] |
45 | b 20004f | 55 | bics \irqstat, \irqstat, \irqnr |
46 | 56 | beq 1001f | |
47 | 20003: | 57 | |
48 | .ascii "<7>irq: err - bad offset %d, intpnd=%08x, srcpnd=%08x\n" | 58 | mov \irqnr, #(IRQ_EINT4 - 4) |
49 | .byte 0 | 59 | |
50 | .align 4 | 60 | @@ work out which irq (if any) we got |
51 | 20004: | 61 | 3000: |
52 | mov r1, #1 | 62 | movs \tmp, \irqstat, lsl#16 |
53 | mov \tmp, #S3C24XX_VA_IRQ | 63 | addeq \irqnr, \irqnr, #16 |
54 | ldmfd r13!, { r0 - r4 , r8-r12, r14 } | 64 | moveq \irqstat, \irqstat, lsr#16 |
55 | #endif | 65 | tst \irqstat, #0xff |
56 | 66 | addeq \irqnr, \irqnr, #8 | |
57 | @ try working out interrupt number for ourselves | 67 | moveq \irqstat, \irqstat, lsr#8 |
58 | mov \irqnr, #0 | 68 | tst \irqstat, #0xf |
59 | ldr \irqstat, [ \tmp, #0x10 ] @ INTPND | 69 | addeq \irqnr, \irqnr, #4 |
60 | 10021: | 70 | moveq \irqstat, \irqstat, lsr#4 |
61 | movs \irqstat, \irqstat, lsr#1 | 71 | tst \irqstat, #0x3 |
62 | bcs 30000b @ try and re-start the proccess | 72 | addeq \irqnr, \irqnr, #2 |
63 | add \irqnr, \irqnr, #1 | 73 | moveq \irqstat, \irqstat, lsr#2 |
64 | cmp \irqnr, #32 | 74 | tst \irqstat, #0x1 |
65 | ble 10021b | 75 | addeq \irqnr, \irqnr, #1 |
66 | 76 | ||
67 | @ found no interrupt, set Z flag and leave | 77 | @@ we have the value |
68 | movs \irqnr, #0 | 78 | movs \irqnr, \irqnr |
69 | b 1001f | 79 | |
70 | |||
71 | 20005: | ||
72 | 20002: @ exit | ||
73 | @ we base the s3c2410x interrupts at 16 and above to allow | ||
74 | @ isa peripherals to have their standard interrupts, also | ||
75 | @ ensure that Z flag is un-set on exit | ||
76 | |||
77 | @ note, we cannot be sure if we get IRQ_EINT0 (0) that | ||
78 | @ there is simply no interrupt pending, so in all other | ||
79 | @ cases we jump to say we have found something, otherwise | ||
80 | @ we check to see if the interrupt really is assrted | ||
81 | adds \irqnr, \irqnr, #IRQ_EINT0 | ||
82 | teq \irqnr, #IRQ_EINT0 | ||
83 | bne 1001f @ exit | ||
84 | ldr \irqstat, [ \tmp, #0x10 ] @ INTPND | ||
85 | teq \irqstat, #0 | ||
86 | moveq \irqnr, #0 | ||
87 | b 1001f | ||
88 | |||
89 | @ we get here from no main or external interrupts pending | ||
90 | 1002: | ||
91 | add \tmp, \tmp, #S3C24XX_VA_GPIO - S3C24XX_VA_IRQ | ||
92 | ldr \irqstat, [ \tmp, # 0xa8 ] @ EXTINTPEND | ||
93 | ldr \irqnr, [ \tmp, # 0xa4 ] @ EXTINTMASK | ||
94 | |||
95 | bic \irqstat, \irqstat, \irqnr @ clear masked irqs | ||
96 | |||
97 | mov \irqnr, #IRQ_EINT4 @ start extint nos | ||
98 | mov \irqstat, \irqstat, lsr#4 @ ignore bottom 4 bits | ||
99 | 10021: | ||
100 | movs \irqstat, \irqstat, lsr#1 | ||
101 | bcs 1004f | ||
102 | add \irqnr, \irqnr, #1 | ||
103 | cmp \irqnr, #IRQ_EINT23 | ||
104 | ble 10021b | ||
105 | |||
106 | @ found no interrupt, set Z flag and leave | ||
107 | movs \irqnr, #0 | ||
108 | |||
109 | 1004: @ ensure Z flag clear in case our MOVS shifted out the last bit | ||
110 | teq \irqnr, #0 | ||
111 | 1001: | 80 | 1001: |
112 | @ exit irq routine | 81 | @@ exit here, Z flag unset if IRQ |
113 | .endm | ||
114 | 82 | ||
83 | .endm | ||
115 | 84 | ||
116 | /* currently don't need an disable_fiq macro */ | 85 | /* currently don't need an disable_fiq macro */ |
117 | 86 | ||
118 | .macro disable_fiq | 87 | .macro disable_fiq |
119 | .endm | 88 | .endm |
120 | |||
121 | |||
diff --git a/include/asm-arm/dma-mapping.h b/include/asm-arm/dma-mapping.h index e3e8541ee63b..63ca7412a462 100644 --- a/include/asm-arm/dma-mapping.h +++ b/include/asm-arm/dma-mapping.h | |||
@@ -47,7 +47,7 @@ static inline int dma_get_cache_alignment(void) | |||
47 | 47 | ||
48 | static inline int dma_is_consistent(dma_addr_t handle) | 48 | static inline int dma_is_consistent(dma_addr_t handle) |
49 | { | 49 | { |
50 | return 0; | 50 | return !!arch_is_coherent(); |
51 | } | 51 | } |
52 | 52 | ||
53 | /* | 53 | /* |
@@ -145,7 +145,9 @@ static inline dma_addr_t | |||
145 | dma_map_single(struct device *dev, void *cpu_addr, size_t size, | 145 | dma_map_single(struct device *dev, void *cpu_addr, size_t size, |
146 | enum dma_data_direction dir) | 146 | enum dma_data_direction dir) |
147 | { | 147 | { |
148 | consistent_sync(cpu_addr, size, dir); | 148 | if (!arch_is_coherent()) |
149 | consistent_sync(cpu_addr, size, dir); | ||
150 | |||
149 | return virt_to_dma(dev, (unsigned long)cpu_addr); | 151 | return virt_to_dma(dev, (unsigned long)cpu_addr); |
150 | } | 152 | } |
151 | #else | 153 | #else |
@@ -255,7 +257,9 @@ dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, | |||
255 | 257 | ||
256 | sg->dma_address = page_to_dma(dev, sg->page) + sg->offset; | 258 | sg->dma_address = page_to_dma(dev, sg->page) + sg->offset; |
257 | virt = page_address(sg->page) + sg->offset; | 259 | virt = page_address(sg->page) + sg->offset; |
258 | consistent_sync(virt, sg->length, dir); | 260 | |
261 | if (!arch_is_coherent()) | ||
262 | consistent_sync(virt, sg->length, dir); | ||
259 | } | 263 | } |
260 | 264 | ||
261 | return nents; | 265 | return nents; |
@@ -310,14 +314,16 @@ static inline void | |||
310 | dma_sync_single_for_cpu(struct device *dev, dma_addr_t handle, size_t size, | 314 | dma_sync_single_for_cpu(struct device *dev, dma_addr_t handle, size_t size, |
311 | enum dma_data_direction dir) | 315 | enum dma_data_direction dir) |
312 | { | 316 | { |
313 | consistent_sync((void *)dma_to_virt(dev, handle), size, dir); | 317 | if (!arch_is_coherent()) |
318 | consistent_sync((void *)dma_to_virt(dev, handle), size, dir); | ||
314 | } | 319 | } |
315 | 320 | ||
316 | static inline void | 321 | static inline void |
317 | dma_sync_single_for_device(struct device *dev, dma_addr_t handle, size_t size, | 322 | dma_sync_single_for_device(struct device *dev, dma_addr_t handle, size_t size, |
318 | enum dma_data_direction dir) | 323 | enum dma_data_direction dir) |
319 | { | 324 | { |
320 | consistent_sync((void *)dma_to_virt(dev, handle), size, dir); | 325 | if (!arch_is_coherent()) |
326 | consistent_sync((void *)dma_to_virt(dev, handle), size, dir); | ||
321 | } | 327 | } |
322 | #else | 328 | #else |
323 | extern void dma_sync_single_for_cpu(struct device*, dma_addr_t, size_t, enum dma_data_direction); | 329 | extern void dma_sync_single_for_cpu(struct device*, dma_addr_t, size_t, enum dma_data_direction); |
@@ -347,7 +353,8 @@ dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nents, | |||
347 | 353 | ||
348 | for (i = 0; i < nents; i++, sg++) { | 354 | for (i = 0; i < nents; i++, sg++) { |
349 | char *virt = page_address(sg->page) + sg->offset; | 355 | char *virt = page_address(sg->page) + sg->offset; |
350 | consistent_sync(virt, sg->length, dir); | 356 | if (!arch_is_coherent()) |
357 | consistent_sync(virt, sg->length, dir); | ||
351 | } | 358 | } |
352 | } | 359 | } |
353 | 360 | ||
@@ -359,7 +366,8 @@ dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nents, | |||
359 | 366 | ||
360 | for (i = 0; i < nents; i++, sg++) { | 367 | for (i = 0; i < nents; i++, sg++) { |
361 | char *virt = page_address(sg->page) + sg->offset; | 368 | char *virt = page_address(sg->page) + sg->offset; |
362 | consistent_sync(virt, sg->length, dir); | 369 | if (!arch_is_coherent()) |
370 | consistent_sync(virt, sg->length, dir); | ||
363 | } | 371 | } |
364 | } | 372 | } |
365 | #else | 373 | #else |
diff --git a/include/asm-arm/memory.h b/include/asm-arm/memory.h index afa5c3ea077c..2b3cf69b3ed9 100644 --- a/include/asm-arm/memory.h +++ b/include/asm-arm/memory.h | |||
@@ -234,6 +234,14 @@ static inline __deprecated void *bus_to_virt(unsigned long x) | |||
234 | #define virt_to_dma(dev, addr) (__arch_virt_to_dma(dev, addr)) | 234 | #define virt_to_dma(dev, addr) (__arch_virt_to_dma(dev, addr)) |
235 | #endif | 235 | #endif |
236 | 236 | ||
237 | /* | ||
238 | * Optional coherency support. Currently used only by selected | ||
239 | * Intel XSC3-based systems. | ||
240 | */ | ||
241 | #ifndef arch_is_coherent | ||
242 | #define arch_is_coherent() 0 | ||
243 | #endif | ||
244 | |||
237 | #endif | 245 | #endif |
238 | 246 | ||
239 | #include <asm-generic/memory_model.h> | 247 | #include <asm-generic/memory_model.h> |
diff --git a/include/asm-arm/pgtable-hwdef.h b/include/asm-arm/pgtable-hwdef.h index 1d033495cc75..1bc1f997bda2 100644 --- a/include/asm-arm/pgtable-hwdef.h +++ b/include/asm-arm/pgtable-hwdef.h | |||
@@ -73,6 +73,7 @@ | |||
73 | #define PTE_EXT_AP_URW_SRW (PTE_EXT_AP1|PTE_EXT_AP0) | 73 | #define PTE_EXT_AP_URW_SRW (PTE_EXT_AP1|PTE_EXT_AP0) |
74 | #define PTE_EXT_TEX(x) ((x) << 6) /* v5 */ | 74 | #define PTE_EXT_TEX(x) ((x) << 6) /* v5 */ |
75 | #define PTE_EXT_APX (1 << 9) /* v6 */ | 75 | #define PTE_EXT_APX (1 << 9) /* v6 */ |
76 | #define PTE_EXT_COHERENT (1 << 9) /* XScale3 */ | ||
76 | #define PTE_EXT_SHARED (1 << 10) /* v6 */ | 77 | #define PTE_EXT_SHARED (1 << 10) /* v6 */ |
77 | #define PTE_EXT_NG (1 << 11) /* v6 */ | 78 | #define PTE_EXT_NG (1 << 11) /* v6 */ |
78 | 79 | ||
diff --git a/include/asm-arm/pgtable.h b/include/asm-arm/pgtable.h index e595ae24efe2..e85c08d78dda 100644 --- a/include/asm-arm/pgtable.h +++ b/include/asm-arm/pgtable.h | |||
@@ -156,6 +156,7 @@ extern void __pgd_error(const char *file, int line, unsigned long val); | |||
156 | #define L_PTE_WRITE (1 << 5) | 156 | #define L_PTE_WRITE (1 << 5) |
157 | #define L_PTE_EXEC (1 << 6) | 157 | #define L_PTE_EXEC (1 << 6) |
158 | #define L_PTE_DIRTY (1 << 7) | 158 | #define L_PTE_DIRTY (1 << 7) |
159 | #define L_PTE_COHERENT (1 << 9) /* I/O coherent (xsc3) */ | ||
159 | #define L_PTE_SHARED (1 << 10) /* shared between CPUs (v6) */ | 160 | #define L_PTE_SHARED (1 << 10) /* shared between CPUs (v6) */ |
160 | #define L_PTE_ASID (1 << 11) /* non-global (use ASID, v6) */ | 161 | #define L_PTE_ASID (1 << 11) /* non-global (use ASID, v6) */ |
161 | 162 | ||
diff --git a/include/linux/fs.h b/include/linux/fs.h index 4ed7e602d703..1e9ebaba07b7 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -864,7 +864,7 @@ struct super_block { | |||
864 | */ | 864 | */ |
865 | struct mutex s_vfs_rename_mutex; /* Kludge */ | 865 | struct mutex s_vfs_rename_mutex; /* Kludge */ |
866 | 866 | ||
867 | /* Granuality of c/m/atime in ns. | 867 | /* Granularity of c/m/atime in ns. |
868 | Cannot be worse than a second */ | 868 | Cannot be worse than a second */ |
869 | u32 s_time_gran; | 869 | u32 s_time_gran; |
870 | }; | 870 | }; |
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h index b20939287613..306acf1dc6d5 100644 --- a/include/linux/hrtimer.h +++ b/include/linux/hrtimer.h | |||
@@ -80,7 +80,7 @@ struct hrtimer_sleeper { | |||
80 | * @first: pointer to the timer node which expires first | 80 | * @first: pointer to the timer node which expires first |
81 | * @resolution: the resolution of the clock, in nanoseconds | 81 | * @resolution: the resolution of the clock, in nanoseconds |
82 | * @get_time: function to retrieve the current time of the clock | 82 | * @get_time: function to retrieve the current time of the clock |
83 | * @get_sofirq_time: function to retrieve the current time from the softirq | 83 | * @get_softirq_time: function to retrieve the current time from the softirq |
84 | * @curr_timer: the timer which is executing a callback right now | 84 | * @curr_timer: the timer which is executing a callback right now |
85 | * @softirq_time: the time when running the hrtimer queue in the softirq | 85 | * @softirq_time: the time when running the hrtimer queue in the softirq |
86 | */ | 86 | */ |
diff --git a/include/sound/core.h b/include/sound/core.h index 7f32c12b4a0a..d1d043f6cb80 100644 --- a/include/sound/core.h +++ b/include/sound/core.h | |||
@@ -170,7 +170,7 @@ static inline void snd_power_change_state(struct snd_card *card, unsigned int st | |||
170 | } | 170 | } |
171 | 171 | ||
172 | /* init.c */ | 172 | /* init.c */ |
173 | int snd_power_wait(struct snd_card *card, unsigned int power_state, struct file *file); | 173 | int snd_power_wait(struct snd_card *card, unsigned int power_state); |
174 | 174 | ||
175 | #else /* ! CONFIG_PM */ | 175 | #else /* ! CONFIG_PM */ |
176 | 176 | ||
diff --git a/include/sound/pcm.h b/include/sound/pcm.h index 15b885660bf0..66b1f08b42b9 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h | |||
@@ -369,6 +369,7 @@ struct snd_pcm_substream { | |||
369 | /* -- assigned files -- */ | 369 | /* -- assigned files -- */ |
370 | struct snd_pcm_file *file; | 370 | struct snd_pcm_file *file; |
371 | struct file *ffile; | 371 | struct file *ffile; |
372 | void (*pcm_release)(struct snd_pcm_substream *); | ||
372 | #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) | 373 | #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) |
373 | /* -- OSS things -- */ | 374 | /* -- OSS things -- */ |
374 | struct snd_pcm_oss_substream oss; | 375 | struct snd_pcm_oss_substream oss; |
@@ -381,13 +382,10 @@ struct snd_pcm_substream { | |||
381 | struct snd_info_entry *proc_prealloc_entry; | 382 | struct snd_info_entry *proc_prealloc_entry; |
382 | /* misc flags */ | 383 | /* misc flags */ |
383 | unsigned int no_mmap_ctrl: 1; | 384 | unsigned int no_mmap_ctrl: 1; |
385 | unsigned int hw_opened: 1; | ||
384 | }; | 386 | }; |
385 | 387 | ||
386 | #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) | ||
387 | #define SUBSTREAM_BUSY(substream) ((substream)->file != NULL || ((substream)->oss.file != NULL)) | ||
388 | #else | ||
389 | #define SUBSTREAM_BUSY(substream) ((substream)->file != NULL) | 388 | #define SUBSTREAM_BUSY(substream) ((substream)->file != NULL) |
390 | #endif | ||
391 | 389 | ||
392 | 390 | ||
393 | struct snd_pcm_str { | 391 | struct snd_pcm_str { |
@@ -460,7 +458,6 @@ int snd_pcm_info_user(struct snd_pcm_substream *substream, | |||
460 | struct snd_pcm_info __user *info); | 458 | struct snd_pcm_info __user *info); |
461 | int snd_pcm_status(struct snd_pcm_substream *substream, | 459 | int snd_pcm_status(struct snd_pcm_substream *substream, |
462 | struct snd_pcm_status *status); | 460 | struct snd_pcm_status *status); |
463 | int snd_pcm_prepare(struct snd_pcm_substream *substream); | ||
464 | int snd_pcm_start(struct snd_pcm_substream *substream); | 461 | int snd_pcm_start(struct snd_pcm_substream *substream); |
465 | int snd_pcm_stop(struct snd_pcm_substream *substream, int status); | 462 | int snd_pcm_stop(struct snd_pcm_substream *substream, int status); |
466 | int snd_pcm_drain_done(struct snd_pcm_substream *substream); | 463 | int snd_pcm_drain_done(struct snd_pcm_substream *substream); |
@@ -468,11 +465,13 @@ int snd_pcm_drain_done(struct snd_pcm_substream *substream); | |||
468 | int snd_pcm_suspend(struct snd_pcm_substream *substream); | 465 | int snd_pcm_suspend(struct snd_pcm_substream *substream); |
469 | int snd_pcm_suspend_all(struct snd_pcm *pcm); | 466 | int snd_pcm_suspend_all(struct snd_pcm *pcm); |
470 | #endif | 467 | #endif |
471 | int snd_pcm_kernel_playback_ioctl(struct snd_pcm_substream *substream, unsigned int cmd, void *arg); | ||
472 | int snd_pcm_kernel_capture_ioctl(struct snd_pcm_substream *substream, unsigned int cmd, void *arg); | ||
473 | int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream, unsigned int cmd, void *arg); | 468 | int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream, unsigned int cmd, void *arg); |
474 | int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, struct snd_pcm_substream **rsubstream); | 469 | int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, struct file *file, |
470 | struct snd_pcm_substream **rsubstream); | ||
475 | void snd_pcm_release_substream(struct snd_pcm_substream *substream); | 471 | void snd_pcm_release_substream(struct snd_pcm_substream *substream); |
472 | int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, struct file *file, | ||
473 | struct snd_pcm_substream **rsubstream); | ||
474 | void snd_pcm_detach_substream(struct snd_pcm_substream *substream); | ||
476 | void snd_pcm_vma_notify_data(void *client, void *data); | 475 | void snd_pcm_vma_notify_data(void *client, void *data); |
477 | int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file, struct vm_area_struct *area); | 476 | int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file, struct vm_area_struct *area); |
478 | 477 | ||
diff --git a/include/sound/pcm_oss.h b/include/sound/pcm_oss.h index bff0778e1969..39df2baca18a 100644 --- a/include/sound/pcm_oss.h +++ b/include/sound/pcm_oss.h | |||
@@ -69,8 +69,7 @@ struct snd_pcm_oss_file { | |||
69 | 69 | ||
70 | struct snd_pcm_oss_substream { | 70 | struct snd_pcm_oss_substream { |
71 | unsigned oss: 1; /* oss mode */ | 71 | unsigned oss: 1; /* oss mode */ |
72 | struct snd_pcm_oss_setup *setup; /* active setup */ | 72 | struct snd_pcm_oss_setup setup; /* active setup */ |
73 | struct snd_pcm_oss_file *file; | ||
74 | }; | 73 | }; |
75 | 74 | ||
76 | struct snd_pcm_oss_stream { | 75 | struct snd_pcm_oss_stream { |
@@ -91,8 +91,8 @@ static inline int shm_addid(struct shmid_kernel *shp) | |||
91 | static inline void shm_inc (int id) { | 91 | static inline void shm_inc (int id) { |
92 | struct shmid_kernel *shp; | 92 | struct shmid_kernel *shp; |
93 | 93 | ||
94 | if(!(shp = shm_lock(id))) | 94 | shp = shm_lock(id); |
95 | BUG(); | 95 | BUG_ON(!shp); |
96 | shp->shm_atim = get_seconds(); | 96 | shp->shm_atim = get_seconds(); |
97 | shp->shm_lprid = current->tgid; | 97 | shp->shm_lprid = current->tgid; |
98 | shp->shm_nattch++; | 98 | shp->shm_nattch++; |
@@ -142,8 +142,8 @@ static void shm_close (struct vm_area_struct *shmd) | |||
142 | 142 | ||
143 | mutex_lock(&shm_ids.mutex); | 143 | mutex_lock(&shm_ids.mutex); |
144 | /* remove from the list of attaches of the shm segment */ | 144 | /* remove from the list of attaches of the shm segment */ |
145 | if(!(shp = shm_lock(id))) | 145 | shp = shm_lock(id); |
146 | BUG(); | 146 | BUG_ON(!shp); |
147 | shp->shm_lprid = current->tgid; | 147 | shp->shm_lprid = current->tgid; |
148 | shp->shm_dtim = get_seconds(); | 148 | shp->shm_dtim = get_seconds(); |
149 | shp->shm_nattch--; | 149 | shp->shm_nattch--; |
@@ -283,8 +283,7 @@ asmlinkage long sys_shmget (key_t key, size_t size, int shmflg) | |||
283 | err = -EEXIST; | 283 | err = -EEXIST; |
284 | } else { | 284 | } else { |
285 | shp = shm_lock(id); | 285 | shp = shm_lock(id); |
286 | if(shp==NULL) | 286 | BUG_ON(shp==NULL); |
287 | BUG(); | ||
288 | if (shp->shm_segsz < size) | 287 | if (shp->shm_segsz < size) |
289 | err = -EINVAL; | 288 | err = -EINVAL; |
290 | else if (ipcperms(&shp->shm_perm, shmflg)) | 289 | else if (ipcperms(&shp->shm_perm, shmflg)) |
@@ -774,8 +773,8 @@ invalid: | |||
774 | up_write(¤t->mm->mmap_sem); | 773 | up_write(¤t->mm->mmap_sem); |
775 | 774 | ||
776 | mutex_lock(&shm_ids.mutex); | 775 | mutex_lock(&shm_ids.mutex); |
777 | if(!(shp = shm_lock(shmid))) | 776 | shp = shm_lock(shmid); |
778 | BUG(); | 777 | BUG_ON(!shp); |
779 | shp->shm_nattch--; | 778 | shp->shm_nattch--; |
780 | if(shp->shm_nattch == 0 && | 779 | if(shp->shm_nattch == 0 && |
781 | shp->shm_perm.mode & SHM_DEST) | 780 | shp->shm_perm.mode & SHM_DEST) |
diff --git a/ipc/util.c b/ipc/util.c index 23151ef32590..5e785a29e1e6 100644 --- a/ipc/util.c +++ b/ipc/util.c | |||
@@ -266,8 +266,7 @@ struct kern_ipc_perm* ipc_rmid(struct ipc_ids* ids, int id) | |||
266 | { | 266 | { |
267 | struct kern_ipc_perm* p; | 267 | struct kern_ipc_perm* p; |
268 | int lid = id % SEQ_MULTIPLIER; | 268 | int lid = id % SEQ_MULTIPLIER; |
269 | if(lid >= ids->entries->size) | 269 | BUG_ON(lid >= ids->entries->size); |
270 | BUG(); | ||
271 | 270 | ||
272 | /* | 271 | /* |
273 | * do not need a rcu_dereference()() here to force ordering | 272 | * do not need a rcu_dereference()() here to force ordering |
@@ -275,8 +274,7 @@ struct kern_ipc_perm* ipc_rmid(struct ipc_ids* ids, int id) | |||
275 | */ | 274 | */ |
276 | p = ids->entries->p[lid]; | 275 | p = ids->entries->p[lid]; |
277 | ids->entries->p[lid] = NULL; | 276 | ids->entries->p[lid] = NULL; |
278 | if(p==NULL) | 277 | BUG_ON(p==NULL); |
279 | BUG(); | ||
280 | ids->in_use--; | 278 | ids->in_use--; |
281 | 279 | ||
282 | if (lid == ids->max_id) { | 280 | if (lid == ids->max_id) { |
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig index 9fd8d4f03595..ce0dfb8f4a4e 100644 --- a/kernel/power/Kconfig +++ b/kernel/power/Kconfig | |||
@@ -41,7 +41,7 @@ config SOFTWARE_SUSPEND | |||
41 | depends on PM && SWAP && (X86 && (!SMP || SUSPEND_SMP)) || ((FRV || PPC32) && !SMP) | 41 | depends on PM && SWAP && (X86 && (!SMP || SUSPEND_SMP)) || ((FRV || PPC32) && !SMP) |
42 | ---help--- | 42 | ---help--- |
43 | Enable the possibility of suspending the machine. | 43 | Enable the possibility of suspending the machine. |
44 | It doesn't need APM. | 44 | It doesn't need ACPI or APM. |
45 | You may suspend your machine by 'swsusp' or 'shutdown -z <time>' | 45 | You may suspend your machine by 'swsusp' or 'shutdown -z <time>' |
46 | (patch for sysvinit needed). | 46 | (patch for sysvinit needed). |
47 | 47 | ||
diff --git a/kernel/printk.c b/kernel/printk.c index 8cc19431e74b..c056f3324432 100644 --- a/kernel/printk.c +++ b/kernel/printk.c | |||
@@ -360,8 +360,7 @@ static void call_console_drivers(unsigned long start, unsigned long end) | |||
360 | unsigned long cur_index, start_print; | 360 | unsigned long cur_index, start_print; |
361 | static int msg_level = -1; | 361 | static int msg_level = -1; |
362 | 362 | ||
363 | if (((long)(start - end)) > 0) | 363 | BUG_ON(((long)(start - end)) > 0); |
364 | BUG(); | ||
365 | 364 | ||
366 | cur_index = start; | 365 | cur_index = start; |
367 | start_print = start; | 366 | start_print = start; |
@@ -708,8 +707,7 @@ int __init add_preferred_console(char *name, int idx, char *options) | |||
708 | */ | 707 | */ |
709 | void acquire_console_sem(void) | 708 | void acquire_console_sem(void) |
710 | { | 709 | { |
711 | if (in_interrupt()) | 710 | BUG_ON(in_interrupt()); |
712 | BUG(); | ||
713 | down(&console_sem); | 711 | down(&console_sem); |
714 | console_locked = 1; | 712 | console_locked = 1; |
715 | console_may_schedule = 1; | 713 | console_may_schedule = 1; |
diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 86a7f6c60cb2..0eeb7e66722c 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c | |||
@@ -30,8 +30,7 @@ | |||
30 | */ | 30 | */ |
31 | void __ptrace_link(task_t *child, task_t *new_parent) | 31 | void __ptrace_link(task_t *child, task_t *new_parent) |
32 | { | 32 | { |
33 | if (!list_empty(&child->ptrace_list)) | 33 | BUG_ON(!list_empty(&child->ptrace_list)); |
34 | BUG(); | ||
35 | if (child->parent == new_parent) | 34 | if (child->parent == new_parent) |
36 | return; | 35 | return; |
37 | list_add(&child->ptrace_list, &child->parent->ptrace_children); | 36 | list_add(&child->ptrace_list, &child->parent->ptrace_children); |
diff --git a/kernel/signal.c b/kernel/signal.c index 92025b108791..5ccaac505e8d 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -769,8 +769,7 @@ specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t) | |||
769 | { | 769 | { |
770 | int ret = 0; | 770 | int ret = 0; |
771 | 771 | ||
772 | if (!irqs_disabled()) | 772 | BUG_ON(!irqs_disabled()); |
773 | BUG(); | ||
774 | assert_spin_locked(&t->sighand->siglock); | 773 | assert_spin_locked(&t->sighand->siglock); |
775 | 774 | ||
776 | /* Short-circuit ignored signals. */ | 775 | /* Short-circuit ignored signals. */ |
@@ -1384,8 +1383,7 @@ send_group_sigqueue(int sig, struct sigqueue *q, struct task_struct *p) | |||
1384 | * the overrun count. Other uses should not try to | 1383 | * the overrun count. Other uses should not try to |
1385 | * send the signal multiple times. | 1384 | * send the signal multiple times. |
1386 | */ | 1385 | */ |
1387 | if (q->info.si_code != SI_TIMER) | 1386 | BUG_ON(q->info.si_code != SI_TIMER); |
1388 | BUG(); | ||
1389 | q->info.si_overrun++; | 1387 | q->info.si_overrun++; |
1390 | goto out; | 1388 | goto out; |
1391 | } | 1389 | } |
diff --git a/kernel/time.c b/kernel/time.c index ff8e7019c4c4..b00ddc71cedb 100644 --- a/kernel/time.c +++ b/kernel/time.c | |||
@@ -410,7 +410,7 @@ EXPORT_SYMBOL(current_kernel_time); | |||
410 | * current_fs_time - Return FS time | 410 | * current_fs_time - Return FS time |
411 | * @sb: Superblock. | 411 | * @sb: Superblock. |
412 | * | 412 | * |
413 | * Return the current time truncated to the time granuality supported by | 413 | * Return the current time truncated to the time granularity supported by |
414 | * the fs. | 414 | * the fs. |
415 | */ | 415 | */ |
416 | struct timespec current_fs_time(struct super_block *sb) | 416 | struct timespec current_fs_time(struct super_block *sb) |
@@ -421,11 +421,11 @@ struct timespec current_fs_time(struct super_block *sb) | |||
421 | EXPORT_SYMBOL(current_fs_time); | 421 | EXPORT_SYMBOL(current_fs_time); |
422 | 422 | ||
423 | /** | 423 | /** |
424 | * timespec_trunc - Truncate timespec to a granuality | 424 | * timespec_trunc - Truncate timespec to a granularity |
425 | * @t: Timespec | 425 | * @t: Timespec |
426 | * @gran: Granuality in ns. | 426 | * @gran: Granularity in ns. |
427 | * | 427 | * |
428 | * Truncate a timespec to a granuality. gran must be smaller than a second. | 428 | * Truncate a timespec to a granularity. gran must be smaller than a second. |
429 | * Always rounds down. | 429 | * Always rounds down. |
430 | * | 430 | * |
431 | * This function should be only used for timestamps returned by | 431 | * This function should be only used for timestamps returned by |
diff --git a/kernel/timer.c b/kernel/timer.c index 6b812c04737b..c3a874f1393c 100644 --- a/kernel/timer.c +++ b/kernel/timer.c | |||
@@ -1479,8 +1479,7 @@ register_time_interpolator(struct time_interpolator *ti) | |||
1479 | unsigned long flags; | 1479 | unsigned long flags; |
1480 | 1480 | ||
1481 | /* Sanity check */ | 1481 | /* Sanity check */ |
1482 | if (ti->frequency == 0 || ti->mask == 0) | 1482 | BUG_ON(ti->frequency == 0 || ti->mask == 0); |
1483 | BUG(); | ||
1484 | 1483 | ||
1485 | ti->nsec_per_cyc = ((u64)NSEC_PER_SEC << ti->shift) / ti->frequency; | 1484 | ti->nsec_per_cyc = ((u64)NSEC_PER_SEC << ti->shift) / ti->frequency; |
1486 | spin_lock(&time_interpolator_lock); | 1485 | spin_lock(&time_interpolator_lock); |
diff --git a/mm/highmem.c b/mm/highmem.c index 55885f64af40..9b274fdf9d08 100644 --- a/mm/highmem.c +++ b/mm/highmem.c | |||
@@ -74,8 +74,7 @@ static void flush_all_zero_pkmaps(void) | |||
74 | pkmap_count[i] = 0; | 74 | pkmap_count[i] = 0; |
75 | 75 | ||
76 | /* sanity check */ | 76 | /* sanity check */ |
77 | if (pte_none(pkmap_page_table[i])) | 77 | BUG_ON(pte_none(pkmap_page_table[i])); |
78 | BUG(); | ||
79 | 78 | ||
80 | /* | 79 | /* |
81 | * Don't need an atomic fetch-and-clear op here; | 80 | * Don't need an atomic fetch-and-clear op here; |
@@ -158,8 +157,7 @@ void fastcall *kmap_high(struct page *page) | |||
158 | if (!vaddr) | 157 | if (!vaddr) |
159 | vaddr = map_new_virtual(page); | 158 | vaddr = map_new_virtual(page); |
160 | pkmap_count[PKMAP_NR(vaddr)]++; | 159 | pkmap_count[PKMAP_NR(vaddr)]++; |
161 | if (pkmap_count[PKMAP_NR(vaddr)] < 2) | 160 | BUG_ON(pkmap_count[PKMAP_NR(vaddr)] < 2); |
162 | BUG(); | ||
163 | spin_unlock(&kmap_lock); | 161 | spin_unlock(&kmap_lock); |
164 | return (void*) vaddr; | 162 | return (void*) vaddr; |
165 | } | 163 | } |
@@ -174,8 +172,7 @@ void fastcall kunmap_high(struct page *page) | |||
174 | 172 | ||
175 | spin_lock(&kmap_lock); | 173 | spin_lock(&kmap_lock); |
176 | vaddr = (unsigned long)page_address(page); | 174 | vaddr = (unsigned long)page_address(page); |
177 | if (!vaddr) | 175 | BUG_ON(!vaddr); |
178 | BUG(); | ||
179 | nr = PKMAP_NR(vaddr); | 176 | nr = PKMAP_NR(vaddr); |
180 | 177 | ||
181 | /* | 178 | /* |
@@ -220,8 +217,7 @@ static __init int init_emergency_pool(void) | |||
220 | return 0; | 217 | return 0; |
221 | 218 | ||
222 | page_pool = mempool_create_page_pool(POOL_SIZE, 0); | 219 | page_pool = mempool_create_page_pool(POOL_SIZE, 0); |
223 | if (!page_pool) | 220 | BUG_ON(!page_pool); |
224 | BUG(); | ||
225 | printk("highmem bounce pool size: %d pages\n", POOL_SIZE); | 221 | printk("highmem bounce pool size: %d pages\n", POOL_SIZE); |
226 | 222 | ||
227 | return 0; | 223 | return 0; |
@@ -264,8 +260,7 @@ int init_emergency_isa_pool(void) | |||
264 | 260 | ||
265 | isa_page_pool = mempool_create(ISA_POOL_SIZE, mempool_alloc_pages_isa, | 261 | isa_page_pool = mempool_create(ISA_POOL_SIZE, mempool_alloc_pages_isa, |
266 | mempool_free_pages, (void *) 0); | 262 | mempool_free_pages, (void *) 0); |
267 | if (!isa_page_pool) | 263 | BUG_ON(!isa_page_pool); |
268 | BUG(); | ||
269 | 264 | ||
270 | printk("isa bounce pool size: %d pages\n", ISA_POOL_SIZE); | 265 | printk("isa bounce pool size: %d pages\n", ISA_POOL_SIZE); |
271 | return 0; | 266 | return 0; |
@@ -294,8 +294,7 @@ void validate_mm(struct mm_struct *mm) | |||
294 | i = browse_rb(&mm->mm_rb); | 294 | i = browse_rb(&mm->mm_rb); |
295 | if (i != mm->map_count) | 295 | if (i != mm->map_count) |
296 | printk("map_count %d rb %d\n", mm->map_count, i), bug = 1; | 296 | printk("map_count %d rb %d\n", mm->map_count, i), bug = 1; |
297 | if (bug) | 297 | BUG_ON(bug); |
298 | BUG(); | ||
299 | } | 298 | } |
300 | #else | 299 | #else |
301 | #define validate_mm(mm) do { } while (0) | 300 | #define validate_mm(mm) do { } while (0) |
@@ -432,8 +431,7 @@ __insert_vm_struct(struct mm_struct * mm, struct vm_area_struct * vma) | |||
432 | struct rb_node ** rb_link, * rb_parent; | 431 | struct rb_node ** rb_link, * rb_parent; |
433 | 432 | ||
434 | __vma = find_vma_prepare(mm, vma->vm_start,&prev, &rb_link, &rb_parent); | 433 | __vma = find_vma_prepare(mm, vma->vm_start,&prev, &rb_link, &rb_parent); |
435 | if (__vma && __vma->vm_start < vma->vm_end) | 434 | BUG_ON(__vma && __vma->vm_start < vma->vm_end); |
436 | BUG(); | ||
437 | __vma_link(mm, vma, prev, rb_link, rb_parent); | 435 | __vma_link(mm, vma, prev, rb_link, rb_parent); |
438 | mm->map_count++; | 436 | mm->map_count++; |
439 | } | 437 | } |
@@ -813,8 +811,7 @@ try_prev: | |||
813 | * (e.g. stash info in next's anon_vma_node when assigning | 811 | * (e.g. stash info in next's anon_vma_node when assigning |
814 | * an anon_vma, or when trying vma_merge). Another time. | 812 | * an anon_vma, or when trying vma_merge). Another time. |
815 | */ | 813 | */ |
816 | if (find_vma_prev(vma->vm_mm, vma->vm_start, &near) != vma) | 814 | BUG_ON(find_vma_prev(vma->vm_mm, vma->vm_start, &near) != vma); |
817 | BUG(); | ||
818 | if (!near) | 815 | if (!near) |
819 | goto none; | 816 | goto none; |
820 | 817 | ||
diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 893d7677579e..6dcce3a4bbdc 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c | |||
@@ -258,7 +258,7 @@ static void balance_dirty_pages(struct address_space *mapping) | |||
258 | /** | 258 | /** |
259 | * balance_dirty_pages_ratelimited_nr - balance dirty memory state | 259 | * balance_dirty_pages_ratelimited_nr - balance dirty memory state |
260 | * @mapping: address_space which was dirtied | 260 | * @mapping: address_space which was dirtied |
261 | * @nr_pages: number of pages which the caller has just dirtied | 261 | * @nr_pages_dirtied: number of pages which the caller has just dirtied |
262 | * | 262 | * |
263 | * Processes which are dirtying memory should call in here once for each page | 263 | * Processes which are dirtying memory should call in here once for each page |
264 | * which was newly dirtied. The function will periodically check the system's | 264 | * which was newly dirtied. The function will periodically check the system's |
@@ -1297,8 +1297,7 @@ void __init kmem_cache_init(void) | |||
1297 | if (cache_cache.num) | 1297 | if (cache_cache.num) |
1298 | break; | 1298 | break; |
1299 | } | 1299 | } |
1300 | if (!cache_cache.num) | 1300 | BUG_ON(!cache_cache.num); |
1301 | BUG(); | ||
1302 | cache_cache.gfporder = order; | 1301 | cache_cache.gfporder = order; |
1303 | cache_cache.colour = left_over / cache_cache.colour_off; | 1302 | cache_cache.colour = left_over / cache_cache.colour_off; |
1304 | cache_cache.slab_size = ALIGN(cache_cache.num * sizeof(kmem_bufctl_t) + | 1303 | cache_cache.slab_size = ALIGN(cache_cache.num * sizeof(kmem_bufctl_t) + |
@@ -1974,8 +1973,7 @@ kmem_cache_create (const char *name, size_t size, size_t align, | |||
1974 | * Always checks flags, a caller might be expecting debug support which | 1973 | * Always checks flags, a caller might be expecting debug support which |
1975 | * isn't available. | 1974 | * isn't available. |
1976 | */ | 1975 | */ |
1977 | if (flags & ~CREATE_MASK) | 1976 | BUG_ON(flags & ~CREATE_MASK); |
1978 | BUG(); | ||
1979 | 1977 | ||
1980 | /* | 1978 | /* |
1981 | * Check that size is in terms of words. This is needed to avoid | 1979 | * Check that size is in terms of words. This is needed to avoid |
@@ -2206,8 +2204,7 @@ static int __node_shrink(struct kmem_cache *cachep, int node) | |||
2206 | 2204 | ||
2207 | slabp = list_entry(l3->slabs_free.prev, struct slab, list); | 2205 | slabp = list_entry(l3->slabs_free.prev, struct slab, list); |
2208 | #if DEBUG | 2206 | #if DEBUG |
2209 | if (slabp->inuse) | 2207 | BUG_ON(slabp->inuse); |
2210 | BUG(); | ||
2211 | #endif | 2208 | #endif |
2212 | list_del(&slabp->list); | 2209 | list_del(&slabp->list); |
2213 | 2210 | ||
@@ -2248,8 +2245,7 @@ static int __cache_shrink(struct kmem_cache *cachep) | |||
2248 | */ | 2245 | */ |
2249 | int kmem_cache_shrink(struct kmem_cache *cachep) | 2246 | int kmem_cache_shrink(struct kmem_cache *cachep) |
2250 | { | 2247 | { |
2251 | if (!cachep || in_interrupt()) | 2248 | BUG_ON(!cachep || in_interrupt()); |
2252 | BUG(); | ||
2253 | 2249 | ||
2254 | return __cache_shrink(cachep); | 2250 | return __cache_shrink(cachep); |
2255 | } | 2251 | } |
@@ -2277,8 +2273,7 @@ int kmem_cache_destroy(struct kmem_cache *cachep) | |||
2277 | int i; | 2273 | int i; |
2278 | struct kmem_list3 *l3; | 2274 | struct kmem_list3 *l3; |
2279 | 2275 | ||
2280 | if (!cachep || in_interrupt()) | 2276 | BUG_ON(!cachep || in_interrupt()); |
2281 | BUG(); | ||
2282 | 2277 | ||
2283 | /* Don't let CPUs to come and go */ | 2278 | /* Don't let CPUs to come and go */ |
2284 | lock_cpu_hotplug(); | 2279 | lock_cpu_hotplug(); |
@@ -2477,8 +2472,7 @@ static int cache_grow(struct kmem_cache *cachep, gfp_t flags, int nodeid) | |||
2477 | * Be lazy and only check for valid flags here, keeping it out of the | 2472 | * Be lazy and only check for valid flags here, keeping it out of the |
2478 | * critical path in kmem_cache_alloc(). | 2473 | * critical path in kmem_cache_alloc(). |
2479 | */ | 2474 | */ |
2480 | if (flags & ~(SLAB_DMA | SLAB_LEVEL_MASK | SLAB_NO_GROW)) | 2475 | BUG_ON(flags & ~(SLAB_DMA | SLAB_LEVEL_MASK | SLAB_NO_GROW)); |
2481 | BUG(); | ||
2482 | if (flags & SLAB_NO_GROW) | 2476 | if (flags & SLAB_NO_GROW) |
2483 | return 0; | 2477 | return 0; |
2484 | 2478 | ||
diff --git a/mm/swap_state.c b/mm/swap_state.c index d7af296833fc..e0e1583f32c2 100644 --- a/mm/swap_state.c +++ b/mm/swap_state.c | |||
@@ -148,8 +148,7 @@ int add_to_swap(struct page * page, gfp_t gfp_mask) | |||
148 | swp_entry_t entry; | 148 | swp_entry_t entry; |
149 | int err; | 149 | int err; |
150 | 150 | ||
151 | if (!PageLocked(page)) | 151 | BUG_ON(!PageLocked(page)); |
152 | BUG(); | ||
153 | 152 | ||
154 | for (;;) { | 153 | for (;;) { |
155 | entry = get_swap_page(); | 154 | entry = get_swap_page(); |
diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 729eb3eec75f..c0504f1e34eb 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c | |||
@@ -321,8 +321,7 @@ void __vunmap(void *addr, int deallocate_pages) | |||
321 | int i; | 321 | int i; |
322 | 322 | ||
323 | for (i = 0; i < area->nr_pages; i++) { | 323 | for (i = 0; i < area->nr_pages; i++) { |
324 | if (unlikely(!area->pages[i])) | 324 | BUG_ON(!area->pages[i]); |
325 | BUG(); | ||
326 | __free_page(area->pages[i]); | 325 | __free_page(area->pages[i]); |
327 | } | 326 | } |
328 | 327 | ||
diff --git a/sound/core/Kconfig b/sound/core/Kconfig index 9dd121bb5638..8efc1b12f3a8 100644 --- a/sound/core/Kconfig +++ b/sound/core/Kconfig | |||
@@ -92,8 +92,9 @@ config SND_SEQUENCER_OSS | |||
92 | 92 | ||
93 | Many programs still use the OSS API, so say Y. | 93 | Many programs still use the OSS API, so say Y. |
94 | 94 | ||
95 | To compile this driver as a module, choose M here: the module | 95 | If you choose M in "Sequencer support" (SND_SEQUENCER), |
96 | will be called snd-seq-oss. | 96 | this will be compiled as a module. The module will be called |
97 | snd-seq-oss. | ||
97 | 98 | ||
98 | config SND_RTCTIMER | 99 | config SND_RTCTIMER |
99 | tristate "RTC Timer support" | 100 | tristate "RTC Timer support" |
diff --git a/sound/core/control.c b/sound/core/control.c index 574745314e70..22565c9b9603 100644 --- a/sound/core/control.c +++ b/sound/core/control.c | |||
@@ -664,7 +664,7 @@ static int snd_ctl_elem_info_user(struct snd_ctl_file *ctl, | |||
664 | if (copy_from_user(&info, _info, sizeof(info))) | 664 | if (copy_from_user(&info, _info, sizeof(info))) |
665 | return -EFAULT; | 665 | return -EFAULT; |
666 | snd_power_lock(ctl->card); | 666 | snd_power_lock(ctl->card); |
667 | result = snd_power_wait(ctl->card, SNDRV_CTL_POWER_D0, NULL); | 667 | result = snd_power_wait(ctl->card, SNDRV_CTL_POWER_D0); |
668 | if (result >= 0) | 668 | if (result >= 0) |
669 | result = snd_ctl_elem_info(ctl, &info); | 669 | result = snd_ctl_elem_info(ctl, &info); |
670 | snd_power_unlock(ctl->card); | 670 | snd_power_unlock(ctl->card); |
@@ -718,7 +718,7 @@ static int snd_ctl_elem_read_user(struct snd_card *card, | |||
718 | return -EFAULT; | 718 | return -EFAULT; |
719 | } | 719 | } |
720 | snd_power_lock(card); | 720 | snd_power_lock(card); |
721 | result = snd_power_wait(card, SNDRV_CTL_POWER_D0, NULL); | 721 | result = snd_power_wait(card, SNDRV_CTL_POWER_D0); |
722 | if (result >= 0) | 722 | if (result >= 0) |
723 | result = snd_ctl_elem_read(card, control); | 723 | result = snd_ctl_elem_read(card, control); |
724 | snd_power_unlock(card); | 724 | snd_power_unlock(card); |
@@ -783,7 +783,7 @@ static int snd_ctl_elem_write_user(struct snd_ctl_file *file, | |||
783 | } | 783 | } |
784 | card = file->card; | 784 | card = file->card; |
785 | snd_power_lock(card); | 785 | snd_power_lock(card); |
786 | result = snd_power_wait(card, SNDRV_CTL_POWER_D0, NULL); | 786 | result = snd_power_wait(card, SNDRV_CTL_POWER_D0); |
787 | if (result >= 0) | 787 | if (result >= 0) |
788 | result = snd_ctl_elem_write(card, file, control); | 788 | result = snd_ctl_elem_write(card, file, control); |
789 | snd_power_unlock(card); | 789 | snd_power_unlock(card); |
diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c index 84fef5084e17..3c0161bb5ba4 100644 --- a/sound/core/control_compat.c +++ b/sound/core/control_compat.c | |||
@@ -109,7 +109,7 @@ static int snd_ctl_elem_info_compat(struct snd_ctl_file *ctl, | |||
109 | goto error; | 109 | goto error; |
110 | 110 | ||
111 | snd_power_lock(ctl->card); | 111 | snd_power_lock(ctl->card); |
112 | err = snd_power_wait(ctl->card, SNDRV_CTL_POWER_D0, NULL); | 112 | err = snd_power_wait(ctl->card, SNDRV_CTL_POWER_D0); |
113 | if (err >= 0) | 113 | if (err >= 0) |
114 | err = snd_ctl_elem_info(ctl, data); | 114 | err = snd_ctl_elem_info(ctl, data); |
115 | snd_power_unlock(ctl->card); | 115 | snd_power_unlock(ctl->card); |
@@ -294,7 +294,7 @@ static int snd_ctl_elem_read_user_compat(struct snd_card *card, | |||
294 | goto error; | 294 | goto error; |
295 | 295 | ||
296 | snd_power_lock(card); | 296 | snd_power_lock(card); |
297 | err = snd_power_wait(card, SNDRV_CTL_POWER_D0, NULL); | 297 | err = snd_power_wait(card, SNDRV_CTL_POWER_D0); |
298 | if (err >= 0) | 298 | if (err >= 0) |
299 | err = snd_ctl_elem_read(card, data); | 299 | err = snd_ctl_elem_read(card, data); |
300 | snd_power_unlock(card); | 300 | snd_power_unlock(card); |
@@ -320,7 +320,7 @@ static int snd_ctl_elem_write_user_compat(struct snd_ctl_file *file, | |||
320 | goto error; | 320 | goto error; |
321 | 321 | ||
322 | snd_power_lock(card); | 322 | snd_power_lock(card); |
323 | err = snd_power_wait(card, SNDRV_CTL_POWER_D0, NULL); | 323 | err = snd_power_wait(card, SNDRV_CTL_POWER_D0); |
324 | if (err >= 0) | 324 | if (err >= 0) |
325 | err = snd_ctl_elem_write(card, file, data); | 325 | err = snd_ctl_elem_write(card, file, data); |
326 | snd_power_unlock(card); | 326 | snd_power_unlock(card); |
diff --git a/sound/core/init.c b/sound/core/init.c index 5bb8a8b23d51..39ed2e5bb0af 100644 --- a/sound/core/init.c +++ b/sound/core/init.c | |||
@@ -722,13 +722,12 @@ int snd_card_file_remove(struct snd_card *card, struct file *file) | |||
722 | * snd_power_wait - wait until the power-state is changed. | 722 | * snd_power_wait - wait until the power-state is changed. |
723 | * @card: soundcard structure | 723 | * @card: soundcard structure |
724 | * @power_state: expected power state | 724 | * @power_state: expected power state |
725 | * @file: file structure for the O_NONBLOCK check (optional) | ||
726 | * | 725 | * |
727 | * Waits until the power-state is changed. | 726 | * Waits until the power-state is changed. |
728 | * | 727 | * |
729 | * Note: the power lock must be active before call. | 728 | * Note: the power lock must be active before call. |
730 | */ | 729 | */ |
731 | int snd_power_wait(struct snd_card *card, unsigned int power_state, struct file *file) | 730 | int snd_power_wait(struct snd_card *card, unsigned int power_state) |
732 | { | 731 | { |
733 | wait_queue_t wait; | 732 | wait_queue_t wait; |
734 | int result = 0; | 733 | int result = 0; |
@@ -745,12 +744,6 @@ int snd_power_wait(struct snd_card *card, unsigned int power_state, struct file | |||
745 | } | 744 | } |
746 | if (snd_power_get_state(card) == power_state) | 745 | if (snd_power_get_state(card) == power_state) |
747 | break; | 746 | break; |
748 | #if 0 /* block all devices */ | ||
749 | if (file && (file->f_flags & O_NONBLOCK)) { | ||
750 | result = -EAGAIN; | ||
751 | break; | ||
752 | } | ||
753 | #endif | ||
754 | set_current_state(TASK_UNINTERRUPTIBLE); | 747 | set_current_state(TASK_UNINTERRUPTIBLE); |
755 | snd_power_unlock(card); | 748 | snd_power_unlock(card); |
756 | schedule_timeout(30 * HZ); | 749 | schedule_timeout(30 * HZ); |
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index f8302b703a30..91114c7aeff5 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c | |||
@@ -208,9 +208,8 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream, | |||
208 | oss_buffer_size = runtime->oss.mmap_bytes; | 208 | oss_buffer_size = runtime->oss.mmap_bytes; |
209 | } | 209 | } |
210 | 210 | ||
211 | if (substream->oss.setup && | 211 | if (substream->oss.setup.period_size > 16) |
212 | substream->oss.setup->period_size > 16) | 212 | oss_period_size = substream->oss.setup.period_size; |
213 | oss_period_size = substream->oss.setup->period_size; | ||
214 | else if (runtime->oss.fragshift) { | 213 | else if (runtime->oss.fragshift) { |
215 | oss_period_size = 1 << runtime->oss.fragshift; | 214 | oss_period_size = 1 << runtime->oss.fragshift; |
216 | if (oss_period_size > oss_buffer_size / 2) | 215 | if (oss_period_size > oss_buffer_size / 2) |
@@ -252,10 +251,8 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream, | |||
252 | 251 | ||
253 | oss_periods = oss_buffer_size / oss_period_size; | 252 | oss_periods = oss_buffer_size / oss_period_size; |
254 | 253 | ||
255 | if (substream->oss.setup) { | 254 | if (substream->oss.setup.periods > 1) |
256 | if (substream->oss.setup->periods > 1) | 255 | oss_periods = substream->oss.setup.periods; |
257 | oss_periods = substream->oss.setup->periods; | ||
258 | } | ||
259 | 256 | ||
260 | s = snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_PERIODS, NULL); | 257 | s = snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_PERIODS, NULL); |
261 | if (runtime->oss.maxfrags && s > runtime->oss.maxfrags) | 258 | if (runtime->oss.maxfrags && s > runtime->oss.maxfrags) |
@@ -341,12 +338,10 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) | |||
341 | goto failure; | 338 | goto failure; |
342 | } | 339 | } |
343 | 340 | ||
344 | if (atomic_read(&runtime->mmap_count)) { | 341 | if (atomic_read(&runtime->mmap_count)) |
345 | direct = 1; | 342 | direct = 1; |
346 | } else { | 343 | else |
347 | struct snd_pcm_oss_setup *setup = substream->oss.setup; | 344 | direct = substream->oss.setup.direct; |
348 | direct = (setup != NULL && setup->direct); | ||
349 | } | ||
350 | 345 | ||
351 | _snd_pcm_hw_params_any(sparams); | 346 | _snd_pcm_hw_params_any(sparams); |
352 | _snd_pcm_hw_param_setinteger(sparams, SNDRV_PCM_HW_PARAM_PERIODS); | 347 | _snd_pcm_hw_param_setinteger(sparams, SNDRV_PCM_HW_PARAM_PERIODS); |
@@ -482,7 +477,7 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) | |||
482 | 1 : runtime->period_size; | 477 | 1 : runtime->period_size; |
483 | sw_params->xfer_align = 1; | 478 | sw_params->xfer_align = 1; |
484 | if (atomic_read(&runtime->mmap_count) || | 479 | if (atomic_read(&runtime->mmap_count) || |
485 | (substream->oss.setup && substream->oss.setup->nosilence)) { | 480 | substream->oss.setup.nosilence) { |
486 | sw_params->silence_threshold = 0; | 481 | sw_params->silence_threshold = 0; |
487 | sw_params->silence_size = 0; | 482 | sw_params->silence_size = 0; |
488 | } else { | 483 | } else { |
@@ -843,7 +838,7 @@ static ssize_t snd_pcm_oss_write1(struct snd_pcm_substream *substream, const cha | |||
843 | buf += tmp; | 838 | buf += tmp; |
844 | bytes -= tmp; | 839 | bytes -= tmp; |
845 | xfer += tmp; | 840 | xfer += tmp; |
846 | if ((substream->oss.setup != NULL && substream->oss.setup->partialfrag) || | 841 | if (substream->oss.setup.partialfrag || |
847 | runtime->oss.buffer_used == runtime->oss.period_bytes) { | 842 | runtime->oss.buffer_used == runtime->oss.period_bytes) { |
848 | tmp = snd_pcm_oss_write2(substream, runtime->oss.buffer + runtime->oss.period_ptr, | 843 | tmp = snd_pcm_oss_write2(substream, runtime->oss.buffer + runtime->oss.period_ptr, |
849 | runtime->oss.buffer_used - runtime->oss.period_ptr, 1); | 844 | runtime->oss.buffer_used - runtime->oss.period_ptr, 1); |
@@ -959,12 +954,12 @@ static int snd_pcm_oss_reset(struct snd_pcm_oss_file *pcm_oss_file) | |||
959 | 954 | ||
960 | substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; | 955 | substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; |
961 | if (substream != NULL) { | 956 | if (substream != NULL) { |
962 | snd_pcm_kernel_playback_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); | 957 | snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); |
963 | substream->runtime->oss.prepare = 1; | 958 | substream->runtime->oss.prepare = 1; |
964 | } | 959 | } |
965 | substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; | 960 | substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; |
966 | if (substream != NULL) { | 961 | if (substream != NULL) { |
967 | snd_pcm_kernel_capture_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); | 962 | snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); |
968 | substream->runtime->oss.prepare = 1; | 963 | substream->runtime->oss.prepare = 1; |
969 | } | 964 | } |
970 | return 0; | 965 | return 0; |
@@ -979,7 +974,7 @@ static int snd_pcm_oss_post(struct snd_pcm_oss_file *pcm_oss_file) | |||
979 | if (substream != NULL) { | 974 | if (substream != NULL) { |
980 | if ((err = snd_pcm_oss_make_ready(substream)) < 0) | 975 | if ((err = snd_pcm_oss_make_ready(substream)) < 0) |
981 | return err; | 976 | return err; |
982 | snd_pcm_kernel_playback_ioctl(substream, SNDRV_PCM_IOCTL_START, NULL); | 977 | snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_START, NULL); |
983 | } | 978 | } |
984 | /* note: all errors from the start action are ignored */ | 979 | /* note: all errors from the start action are ignored */ |
985 | /* OSS apps do not know, how to handle them */ | 980 | /* OSS apps do not know, how to handle them */ |
@@ -1108,7 +1103,7 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file) | |||
1108 | __direct: | 1103 | __direct: |
1109 | saved_f_flags = substream->ffile->f_flags; | 1104 | saved_f_flags = substream->ffile->f_flags; |
1110 | substream->ffile->f_flags &= ~O_NONBLOCK; | 1105 | substream->ffile->f_flags &= ~O_NONBLOCK; |
1111 | err = snd_pcm_kernel_playback_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL); | 1106 | err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL); |
1112 | substream->ffile->f_flags = saved_f_flags; | 1107 | substream->ffile->f_flags = saved_f_flags; |
1113 | if (err < 0) | 1108 | if (err < 0) |
1114 | return err; | 1109 | return err; |
@@ -1120,7 +1115,7 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file) | |||
1120 | if ((err = snd_pcm_oss_make_ready(substream)) < 0) | 1115 | if ((err = snd_pcm_oss_make_ready(substream)) < 0) |
1121 | return err; | 1116 | return err; |
1122 | runtime = substream->runtime; | 1117 | runtime = substream->runtime; |
1123 | err = snd_pcm_kernel_capture_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); | 1118 | err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); |
1124 | if (err < 0) | 1119 | if (err < 0) |
1125 | return err; | 1120 | return err; |
1126 | runtime->oss.buffer_used = 0; | 1121 | runtime->oss.buffer_used = 0; |
@@ -1214,12 +1209,10 @@ static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file) | |||
1214 | 1209 | ||
1215 | if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) | 1210 | if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) |
1216 | return err; | 1211 | return err; |
1217 | if (atomic_read(&substream->runtime->mmap_count)) { | 1212 | if (atomic_read(&substream->runtime->mmap_count)) |
1218 | direct = 1; | 1213 | direct = 1; |
1219 | } else { | 1214 | else |
1220 | struct snd_pcm_oss_setup *setup = substream->oss.setup; | 1215 | direct = substream->oss.setup.direct; |
1221 | direct = (setup != NULL && setup->direct); | ||
1222 | } | ||
1223 | if (!direct) | 1216 | if (!direct) |
1224 | return AFMT_MU_LAW | AFMT_U8 | | 1217 | return AFMT_MU_LAW | AFMT_U8 | |
1225 | AFMT_S16_LE | AFMT_S16_BE | | 1218 | AFMT_S16_LE | AFMT_S16_BE | |
@@ -1437,7 +1430,7 @@ static int snd_pcm_oss_set_trigger(struct snd_pcm_oss_file *pcm_oss_file, int tr | |||
1437 | cmd = SNDRV_PCM_IOCTL_DROP; | 1430 | cmd = SNDRV_PCM_IOCTL_DROP; |
1438 | runtime->oss.prepare = 1; | 1431 | runtime->oss.prepare = 1; |
1439 | } | 1432 | } |
1440 | err = snd_pcm_kernel_playback_ioctl(psubstream, cmd, NULL); | 1433 | err = snd_pcm_kernel_ioctl(psubstream, cmd, NULL); |
1441 | if (err < 0) | 1434 | if (err < 0) |
1442 | return err; | 1435 | return err; |
1443 | } | 1436 | } |
@@ -1458,7 +1451,7 @@ static int snd_pcm_oss_set_trigger(struct snd_pcm_oss_file *pcm_oss_file, int tr | |||
1458 | cmd = SNDRV_PCM_IOCTL_DROP; | 1451 | cmd = SNDRV_PCM_IOCTL_DROP; |
1459 | runtime->oss.prepare = 1; | 1452 | runtime->oss.prepare = 1; |
1460 | } | 1453 | } |
1461 | err = snd_pcm_kernel_capture_ioctl(csubstream, cmd, NULL); | 1454 | err = snd_pcm_kernel_ioctl(csubstream, cmd, NULL); |
1462 | if (err < 0) | 1455 | if (err < 0) |
1463 | return err; | 1456 | return err; |
1464 | } | 1457 | } |
@@ -1495,7 +1488,7 @@ static int snd_pcm_oss_get_odelay(struct snd_pcm_oss_file *pcm_oss_file) | |||
1495 | runtime = substream->runtime; | 1488 | runtime = substream->runtime; |
1496 | if (runtime->oss.params || runtime->oss.prepare) | 1489 | if (runtime->oss.params || runtime->oss.prepare) |
1497 | return 0; | 1490 | return 0; |
1498 | err = snd_pcm_kernel_playback_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, &delay); | 1491 | err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, &delay); |
1499 | if (err == -EPIPE) | 1492 | if (err == -EPIPE) |
1500 | delay = 0; /* hack for broken OSS applications */ | 1493 | delay = 0; /* hack for broken OSS applications */ |
1501 | else if (err < 0) | 1494 | else if (err < 0) |
@@ -1555,8 +1548,7 @@ static int snd_pcm_oss_get_ptr(struct snd_pcm_oss_file *pcm_oss_file, int stream | |||
1555 | } else { | 1548 | } else { |
1556 | delay = snd_pcm_oss_bytes(substream, delay); | 1549 | delay = snd_pcm_oss_bytes(substream, delay); |
1557 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { | 1550 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { |
1558 | struct snd_pcm_oss_setup *setup = substream->oss.setup; | 1551 | if (substream->oss.setup.buggyptr) |
1559 | if (setup && setup->buggyptr) | ||
1560 | info.blocks = (runtime->oss.buffer_bytes - delay - fixup) / runtime->oss.period_bytes; | 1552 | info.blocks = (runtime->oss.buffer_bytes - delay - fixup) / runtime->oss.period_bytes; |
1561 | else | 1553 | else |
1562 | info.blocks = (delay + fixup) / runtime->oss.period_bytes; | 1554 | info.blocks = (delay + fixup) / runtime->oss.period_bytes; |
@@ -1638,37 +1630,46 @@ static int snd_pcm_oss_get_mapbuf(struct snd_pcm_oss_file *pcm_oss_file, int str | |||
1638 | return -EINVAL; | 1630 | return -EINVAL; |
1639 | } | 1631 | } |
1640 | 1632 | ||
1641 | static struct snd_pcm_oss_setup *snd_pcm_oss_look_for_setup(struct snd_pcm *pcm, int stream, const char *task_name) | 1633 | static const char *strip_task_path(const char *path) |
1642 | { | 1634 | { |
1643 | const char *ptr, *ptrl; | 1635 | const char *ptr, *ptrl = NULL; |
1644 | struct snd_pcm_oss_setup *setup; | 1636 | for (ptr = path; *ptr; ptr++) { |
1645 | |||
1646 | mutex_lock(&pcm->streams[stream].oss.setup_mutex); | ||
1647 | for (setup = pcm->streams[stream].oss.setup_list; setup; setup = setup->next) { | ||
1648 | if (!strcmp(setup->task_name, task_name)) { | ||
1649 | mutex_unlock(&pcm->streams[stream].oss.setup_mutex); | ||
1650 | return setup; | ||
1651 | } | ||
1652 | } | ||
1653 | ptr = ptrl = task_name; | ||
1654 | while (*ptr) { | ||
1655 | if (*ptr == '/') | 1637 | if (*ptr == '/') |
1656 | ptrl = ptr + 1; | 1638 | ptrl = ptr + 1; |
1657 | ptr++; | ||
1658 | } | 1639 | } |
1659 | if (ptrl == task_name) { | 1640 | return ptrl; |
1660 | goto __not_found; | 1641 | } |
1661 | return NULL; | 1642 | |
1662 | } | 1643 | static void snd_pcm_oss_look_for_setup(struct snd_pcm *pcm, int stream, |
1663 | for (setup = pcm->streams[stream].oss.setup_list; setup; setup = setup->next) { | 1644 | const char *task_name, |
1664 | if (!strcmp(setup->task_name, ptrl)) { | 1645 | struct snd_pcm_oss_setup *rsetup) |
1665 | mutex_unlock(&pcm->streams[stream].oss.setup_mutex); | 1646 | { |
1666 | return setup; | 1647 | struct snd_pcm_oss_setup *setup; |
1648 | |||
1649 | mutex_lock(&pcm->streams[stream].oss.setup_mutex); | ||
1650 | do { | ||
1651 | for (setup = pcm->streams[stream].oss.setup_list; setup; | ||
1652 | setup = setup->next) { | ||
1653 | if (!strcmp(setup->task_name, task_name)) | ||
1654 | goto out; | ||
1667 | } | 1655 | } |
1668 | } | 1656 | } while ((task_name = strip_task_path(task_name)) != NULL); |
1669 | __not_found: | 1657 | out: |
1658 | if (setup) | ||
1659 | *rsetup = *setup; | ||
1670 | mutex_unlock(&pcm->streams[stream].oss.setup_mutex); | 1660 | mutex_unlock(&pcm->streams[stream].oss.setup_mutex); |
1671 | return NULL; | 1661 | } |
1662 | |||
1663 | static void snd_pcm_oss_release_substream(struct snd_pcm_substream *substream) | ||
1664 | { | ||
1665 | struct snd_pcm_runtime *runtime; | ||
1666 | runtime = substream->runtime; | ||
1667 | vfree(runtime->oss.buffer); | ||
1668 | runtime->oss.buffer = NULL; | ||
1669 | #ifdef CONFIG_SND_PCM_OSS_PLUGINS | ||
1670 | snd_pcm_oss_plugin_clear(substream); | ||
1671 | #endif | ||
1672 | substream->oss.oss = 0; | ||
1672 | } | 1673 | } |
1673 | 1674 | ||
1674 | static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream, | 1675 | static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream, |
@@ -1678,7 +1679,11 @@ static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream, | |||
1678 | struct snd_pcm_runtime *runtime; | 1679 | struct snd_pcm_runtime *runtime; |
1679 | 1680 | ||
1680 | substream->oss.oss = 1; | 1681 | substream->oss.oss = 1; |
1681 | substream->oss.setup = setup; | 1682 | substream->oss.setup = *setup; |
1683 | if (setup->nonblock) | ||
1684 | substream->ffile->f_flags |= O_NONBLOCK; | ||
1685 | else | ||
1686 | substream->ffile->f_flags &= ~O_NONBLOCK; | ||
1682 | runtime = substream->runtime; | 1687 | runtime = substream->runtime; |
1683 | runtime->oss.params = 1; | 1688 | runtime->oss.params = 1; |
1684 | runtime->oss.trigger = 1; | 1689 | runtime->oss.trigger = 1; |
@@ -1697,18 +1702,7 @@ static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream, | |||
1697 | runtime->oss.fragshift = 0; | 1702 | runtime->oss.fragshift = 0; |
1698 | runtime->oss.maxfrags = 0; | 1703 | runtime->oss.maxfrags = 0; |
1699 | runtime->oss.subdivision = 0; | 1704 | runtime->oss.subdivision = 0; |
1700 | } | 1705 | substream->pcm_release = snd_pcm_oss_release_substream; |
1701 | |||
1702 | static void snd_pcm_oss_release_substream(struct snd_pcm_substream *substream) | ||
1703 | { | ||
1704 | struct snd_pcm_runtime *runtime; | ||
1705 | runtime = substream->runtime; | ||
1706 | vfree(runtime->oss.buffer); | ||
1707 | #ifdef CONFIG_SND_PCM_OSS_PLUGINS | ||
1708 | snd_pcm_oss_plugin_clear(substream); | ||
1709 | #endif | ||
1710 | substream->oss.file = NULL; | ||
1711 | substream->oss.oss = 0; | ||
1712 | } | 1706 | } |
1713 | 1707 | ||
1714 | static int snd_pcm_oss_release_file(struct snd_pcm_oss_file *pcm_oss_file) | 1708 | static int snd_pcm_oss_release_file(struct snd_pcm_oss_file *pcm_oss_file) |
@@ -1717,23 +1711,8 @@ static int snd_pcm_oss_release_file(struct snd_pcm_oss_file *pcm_oss_file) | |||
1717 | snd_assert(pcm_oss_file != NULL, return -ENXIO); | 1711 | snd_assert(pcm_oss_file != NULL, return -ENXIO); |
1718 | for (cidx = 0; cidx < 2; ++cidx) { | 1712 | for (cidx = 0; cidx < 2; ++cidx) { |
1719 | struct snd_pcm_substream *substream = pcm_oss_file->streams[cidx]; | 1713 | struct snd_pcm_substream *substream = pcm_oss_file->streams[cidx]; |
1720 | struct snd_pcm_runtime *runtime; | 1714 | if (substream) |
1721 | if (substream == NULL) | 1715 | snd_pcm_release_substream(substream); |
1722 | continue; | ||
1723 | runtime = substream->runtime; | ||
1724 | |||
1725 | snd_pcm_stream_lock_irq(substream); | ||
1726 | if (snd_pcm_running(substream)) | ||
1727 | snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP); | ||
1728 | snd_pcm_stream_unlock_irq(substream); | ||
1729 | if (substream->ffile != NULL) { | ||
1730 | if (substream->ops->hw_free != NULL) | ||
1731 | substream->ops->hw_free(substream); | ||
1732 | substream->ops->close(substream); | ||
1733 | substream->ffile = NULL; | ||
1734 | } | ||
1735 | snd_pcm_oss_release_substream(substream); | ||
1736 | snd_pcm_release_substream(substream); | ||
1737 | } | 1716 | } |
1738 | kfree(pcm_oss_file); | 1717 | kfree(pcm_oss_file); |
1739 | return 0; | 1718 | return 0; |
@@ -1743,12 +1722,11 @@ static int snd_pcm_oss_open_file(struct file *file, | |||
1743 | struct snd_pcm *pcm, | 1722 | struct snd_pcm *pcm, |
1744 | struct snd_pcm_oss_file **rpcm_oss_file, | 1723 | struct snd_pcm_oss_file **rpcm_oss_file, |
1745 | int minor, | 1724 | int minor, |
1746 | struct snd_pcm_oss_setup *psetup, | 1725 | struct snd_pcm_oss_setup *setup) |
1747 | struct snd_pcm_oss_setup *csetup) | ||
1748 | { | 1726 | { |
1749 | int err = 0; | 1727 | int idx, err; |
1750 | struct snd_pcm_oss_file *pcm_oss_file; | 1728 | struct snd_pcm_oss_file *pcm_oss_file; |
1751 | struct snd_pcm_substream *psubstream = NULL, *csubstream = NULL; | 1729 | struct snd_pcm_substream *substream; |
1752 | unsigned int f_mode = file->f_mode; | 1730 | unsigned int f_mode = file->f_mode; |
1753 | 1731 | ||
1754 | snd_assert(rpcm_oss_file != NULL, return -EINVAL); | 1732 | snd_assert(rpcm_oss_file != NULL, return -EINVAL); |
@@ -1761,73 +1739,31 @@ static int snd_pcm_oss_open_file(struct file *file, | |||
1761 | if ((f_mode & (FMODE_WRITE|FMODE_READ)) == (FMODE_WRITE|FMODE_READ) && | 1739 | if ((f_mode & (FMODE_WRITE|FMODE_READ)) == (FMODE_WRITE|FMODE_READ) && |
1762 | (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX)) | 1740 | (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX)) |
1763 | f_mode = FMODE_WRITE; | 1741 | f_mode = FMODE_WRITE; |
1764 | if ((f_mode & FMODE_WRITE) && !(psetup && psetup->disable)) { | 1742 | |
1765 | if ((err = snd_pcm_open_substream(pcm, SNDRV_PCM_STREAM_PLAYBACK, | 1743 | for (idx = 0; idx < 2; idx++) { |
1766 | &psubstream)) < 0) { | 1744 | if (setup[idx].disable) |
1745 | continue; | ||
1746 | if (idx == SNDRV_PCM_STREAM_PLAYBACK) { | ||
1747 | if (! (f_mode & FMODE_WRITE)) | ||
1748 | continue; | ||
1749 | } else { | ||
1750 | if (! (f_mode & FMODE_READ)) | ||
1751 | continue; | ||
1752 | } | ||
1753 | err = snd_pcm_open_substream(pcm, idx, file, &substream); | ||
1754 | if (err < 0) { | ||
1767 | snd_pcm_oss_release_file(pcm_oss_file); | 1755 | snd_pcm_oss_release_file(pcm_oss_file); |
1768 | return err; | 1756 | return err; |
1769 | } | 1757 | } |
1770 | pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK] = psubstream; | 1758 | |
1771 | } | 1759 | pcm_oss_file->streams[idx] = substream; |
1772 | if ((f_mode & FMODE_READ) && !(csetup && csetup->disable)) { | 1760 | snd_pcm_oss_init_substream(substream, &setup[idx], minor); |
1773 | if ((err = snd_pcm_open_substream(pcm, SNDRV_PCM_STREAM_CAPTURE, | ||
1774 | &csubstream)) < 0) { | ||
1775 | if (!(f_mode & FMODE_WRITE) || err != -ENODEV) { | ||
1776 | snd_pcm_oss_release_file(pcm_oss_file); | ||
1777 | return err; | ||
1778 | } else { | ||
1779 | csubstream = NULL; | ||
1780 | } | ||
1781 | } | ||
1782 | pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE] = csubstream; | ||
1783 | } | 1761 | } |
1784 | 1762 | ||
1785 | if (psubstream == NULL && csubstream == NULL) { | 1763 | if (! pcm_oss_file->streams[0] && pcm_oss_file->streams[1]) { |
1786 | snd_pcm_oss_release_file(pcm_oss_file); | 1764 | snd_pcm_oss_release_file(pcm_oss_file); |
1787 | return -EINVAL; | 1765 | return -EINVAL; |
1788 | } | 1766 | } |
1789 | if (psubstream != NULL) { | ||
1790 | psubstream->oss.file = pcm_oss_file; | ||
1791 | err = snd_pcm_hw_constraints_init(psubstream); | ||
1792 | if (err < 0) { | ||
1793 | snd_printd("snd_pcm_hw_constraint_init failed\n"); | ||
1794 | snd_pcm_oss_release_file(pcm_oss_file); | ||
1795 | return err; | ||
1796 | } | ||
1797 | if ((err = psubstream->ops->open(psubstream)) < 0) { | ||
1798 | snd_pcm_oss_release_file(pcm_oss_file); | ||
1799 | return err; | ||
1800 | } | ||
1801 | psubstream->ffile = file; | ||
1802 | err = snd_pcm_hw_constraints_complete(psubstream); | ||
1803 | if (err < 0) { | ||
1804 | snd_printd("snd_pcm_hw_constraint_complete failed\n"); | ||
1805 | snd_pcm_oss_release_file(pcm_oss_file); | ||
1806 | return err; | ||
1807 | } | ||
1808 | snd_pcm_oss_init_substream(psubstream, psetup, minor); | ||
1809 | } | ||
1810 | if (csubstream != NULL) { | ||
1811 | csubstream->oss.file = pcm_oss_file; | ||
1812 | err = snd_pcm_hw_constraints_init(csubstream); | ||
1813 | if (err < 0) { | ||
1814 | snd_printd("snd_pcm_hw_constraint_init failed\n"); | ||
1815 | snd_pcm_oss_release_file(pcm_oss_file); | ||
1816 | return err; | ||
1817 | } | ||
1818 | if ((err = csubstream->ops->open(csubstream)) < 0) { | ||
1819 | snd_pcm_oss_release_file(pcm_oss_file); | ||
1820 | return err; | ||
1821 | } | ||
1822 | csubstream->ffile = file; | ||
1823 | err = snd_pcm_hw_constraints_complete(csubstream); | ||
1824 | if (err < 0) { | ||
1825 | snd_printd("snd_pcm_hw_constraint_complete failed\n"); | ||
1826 | snd_pcm_oss_release_file(pcm_oss_file); | ||
1827 | return err; | ||
1828 | } | ||
1829 | snd_pcm_oss_init_substream(csubstream, csetup, minor); | ||
1830 | } | ||
1831 | 1767 | ||
1832 | file->private_data = pcm_oss_file; | 1768 | file->private_data = pcm_oss_file; |
1833 | *rpcm_oss_file = pcm_oss_file; | 1769 | *rpcm_oss_file = pcm_oss_file; |
@@ -1852,7 +1788,7 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file) | |||
1852 | char task_name[32]; | 1788 | char task_name[32]; |
1853 | struct snd_pcm *pcm; | 1789 | struct snd_pcm *pcm; |
1854 | struct snd_pcm_oss_file *pcm_oss_file; | 1790 | struct snd_pcm_oss_file *pcm_oss_file; |
1855 | struct snd_pcm_oss_setup *psetup = NULL, *csetup = NULL; | 1791 | struct snd_pcm_oss_setup setup[2]; |
1856 | int nonblock; | 1792 | int nonblock; |
1857 | wait_queue_t wait; | 1793 | wait_queue_t wait; |
1858 | 1794 | ||
@@ -1873,23 +1809,15 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file) | |||
1873 | err = -EFAULT; | 1809 | err = -EFAULT; |
1874 | goto __error; | 1810 | goto __error; |
1875 | } | 1811 | } |
1812 | memset(setup, 0, sizeof(*setup)); | ||
1876 | if (file->f_mode & FMODE_WRITE) | 1813 | if (file->f_mode & FMODE_WRITE) |
1877 | psetup = snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_PLAYBACK, task_name); | 1814 | snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_PLAYBACK, |
1815 | task_name, &setup[0]); | ||
1878 | if (file->f_mode & FMODE_READ) | 1816 | if (file->f_mode & FMODE_READ) |
1879 | csetup = snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_CAPTURE, task_name); | 1817 | snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_CAPTURE, |
1818 | task_name, &setup[1]); | ||
1880 | 1819 | ||
1881 | nonblock = !!(file->f_flags & O_NONBLOCK); | 1820 | nonblock = !!(file->f_flags & O_NONBLOCK); |
1882 | if (psetup && !psetup->disable) { | ||
1883 | if (psetup->nonblock) | ||
1884 | nonblock = 1; | ||
1885 | else if (psetup->block) | ||
1886 | nonblock = 0; | ||
1887 | } else if (csetup && !csetup->disable) { | ||
1888 | if (csetup->nonblock) | ||
1889 | nonblock = 1; | ||
1890 | else if (csetup->block) | ||
1891 | nonblock = 0; | ||
1892 | } | ||
1893 | if (!nonblock) | 1821 | if (!nonblock) |
1894 | nonblock = nonblock_open; | 1822 | nonblock = nonblock_open; |
1895 | 1823 | ||
@@ -1898,7 +1826,7 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file) | |||
1898 | mutex_lock(&pcm->open_mutex); | 1826 | mutex_lock(&pcm->open_mutex); |
1899 | while (1) { | 1827 | while (1) { |
1900 | err = snd_pcm_oss_open_file(file, pcm, &pcm_oss_file, | 1828 | err = snd_pcm_oss_open_file(file, pcm, &pcm_oss_file, |
1901 | iminor(inode), psetup, csetup); | 1829 | iminor(inode), setup); |
1902 | if (err >= 0) | 1830 | if (err >= 0) |
1903 | break; | 1831 | break; |
1904 | if (err == -EAGAIN) { | 1832 | if (err == -EAGAIN) { |
@@ -2312,13 +2240,8 @@ static void snd_pcm_oss_proc_read(struct snd_info_entry *entry, | |||
2312 | 2240 | ||
2313 | static void snd_pcm_oss_proc_free_setup_list(struct snd_pcm_str * pstr) | 2241 | static void snd_pcm_oss_proc_free_setup_list(struct snd_pcm_str * pstr) |
2314 | { | 2242 | { |
2315 | unsigned int idx; | ||
2316 | struct snd_pcm_substream *substream; | ||
2317 | struct snd_pcm_oss_setup *setup, *setupn; | 2243 | struct snd_pcm_oss_setup *setup, *setupn; |
2318 | 2244 | ||
2319 | for (idx = 0, substream = pstr->substream; | ||
2320 | idx < pstr->substream_count; idx++, substream = substream->next) | ||
2321 | substream->oss.setup = NULL; | ||
2322 | for (setup = pstr->oss.setup_list, pstr->oss.setup_list = NULL; | 2245 | for (setup = pstr->oss.setup_list, pstr->oss.setup_list = NULL; |
2323 | setup; setup = setupn) { | 2246 | setup; setup = setupn) { |
2324 | setupn = setup->next; | 2247 | setupn = setup->next; |
@@ -2379,21 +2302,28 @@ static void snd_pcm_oss_proc_write(struct snd_info_entry *entry, | |||
2379 | } | 2302 | } |
2380 | } while (*str); | 2303 | } while (*str); |
2381 | if (setup == NULL) { | 2304 | if (setup == NULL) { |
2382 | setup = kmalloc(sizeof(struct snd_pcm_oss_setup), GFP_KERNEL); | 2305 | setup = kmalloc(sizeof(*setup), GFP_KERNEL); |
2383 | if (setup) { | 2306 | if (! setup) { |
2384 | if (pstr->oss.setup_list == NULL) { | 2307 | buffer->error = -ENOMEM; |
2385 | pstr->oss.setup_list = setup; | 2308 | mutex_lock(&pstr->oss.setup_mutex); |
2386 | } else { | 2309 | return; |
2387 | for (setup1 = pstr->oss.setup_list; setup1->next; setup1 = setup1->next); | 2310 | } |
2388 | setup1->next = setup; | 2311 | if (pstr->oss.setup_list == NULL) |
2389 | } | 2312 | pstr->oss.setup_list = setup; |
2390 | template.task_name = kstrdup(task_name, GFP_KERNEL); | 2313 | else { |
2391 | } else { | 2314 | for (setup1 = pstr->oss.setup_list; |
2315 | setup1->next; setup1 = setup1->next); | ||
2316 | setup1->next = setup; | ||
2317 | } | ||
2318 | template.task_name = kstrdup(task_name, GFP_KERNEL); | ||
2319 | if (! template.task_name) { | ||
2320 | kfree(setup); | ||
2392 | buffer->error = -ENOMEM; | 2321 | buffer->error = -ENOMEM; |
2322 | mutex_lock(&pstr->oss.setup_mutex); | ||
2323 | return; | ||
2393 | } | 2324 | } |
2394 | } | 2325 | } |
2395 | if (setup) | 2326 | *setup = template; |
2396 | *setup = template; | ||
2397 | mutex_unlock(&pstr->oss.setup_mutex); | 2327 | mutex_unlock(&pstr->oss.setup_mutex); |
2398 | } | 2328 | } |
2399 | } | 2329 | } |
diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 3da6a38c2d0f..5d7eb123b999 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c | |||
@@ -777,8 +777,9 @@ static void snd_pcm_tick_timer_func(unsigned long data) | |||
777 | snd_pcm_tick_elapsed(substream); | 777 | snd_pcm_tick_elapsed(substream); |
778 | } | 778 | } |
779 | 779 | ||
780 | int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, | 780 | int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, |
781 | struct snd_pcm_substream **rsubstream) | 781 | struct file *file, |
782 | struct snd_pcm_substream **rsubstream) | ||
782 | { | 783 | { |
783 | struct snd_pcm_str * pstr; | 784 | struct snd_pcm_str * pstr; |
784 | struct snd_pcm_substream *substream; | 785 | struct snd_pcm_substream *substream; |
@@ -793,7 +794,7 @@ int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, | |||
793 | *rsubstream = NULL; | 794 | *rsubstream = NULL; |
794 | snd_assert(pcm != NULL, return -ENXIO); | 795 | snd_assert(pcm != NULL, return -ENXIO); |
795 | pstr = &pcm->streams[stream]; | 796 | pstr = &pcm->streams[stream]; |
796 | if (pstr->substream == NULL) | 797 | if (pstr->substream == NULL || pstr->substream_count == 0) |
797 | return -ENODEV; | 798 | return -ENODEV; |
798 | 799 | ||
799 | card = pcm->card; | 800 | card = pcm->card; |
@@ -807,8 +808,6 @@ int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, | |||
807 | } | 808 | } |
808 | up_read(&card->controls_rwsem); | 809 | up_read(&card->controls_rwsem); |
809 | 810 | ||
810 | if (pstr->substream_count == 0) | ||
811 | return -ENODEV; | ||
812 | switch (stream) { | 811 | switch (stream) { |
813 | case SNDRV_PCM_STREAM_PLAYBACK: | 812 | case SNDRV_PCM_STREAM_PLAYBACK: |
814 | if (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX) { | 813 | if (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX) { |
@@ -874,12 +873,13 @@ int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, | |||
874 | 873 | ||
875 | substream->runtime = runtime; | 874 | substream->runtime = runtime; |
876 | substream->private_data = pcm->private_data; | 875 | substream->private_data = pcm->private_data; |
876 | substream->ffile = file; | ||
877 | pstr->substream_opened++; | 877 | pstr->substream_opened++; |
878 | *rsubstream = substream; | 878 | *rsubstream = substream; |
879 | return 0; | 879 | return 0; |
880 | } | 880 | } |
881 | 881 | ||
882 | void snd_pcm_release_substream(struct snd_pcm_substream *substream) | 882 | void snd_pcm_detach_substream(struct snd_pcm_substream *substream) |
883 | { | 883 | { |
884 | struct snd_pcm_runtime *runtime; | 884 | struct snd_pcm_runtime *runtime; |
885 | substream->file = NULL; | 885 | substream->file = NULL; |
@@ -1111,8 +1111,6 @@ EXPORT_SYMBOL(snd_pcm_link_rwlock); | |||
1111 | EXPORT_SYMBOL(snd_pcm_suspend); | 1111 | EXPORT_SYMBOL(snd_pcm_suspend); |
1112 | EXPORT_SYMBOL(snd_pcm_suspend_all); | 1112 | EXPORT_SYMBOL(snd_pcm_suspend_all); |
1113 | #endif | 1113 | #endif |
1114 | EXPORT_SYMBOL(snd_pcm_kernel_playback_ioctl); | ||
1115 | EXPORT_SYMBOL(snd_pcm_kernel_capture_ioctl); | ||
1116 | EXPORT_SYMBOL(snd_pcm_kernel_ioctl); | 1114 | EXPORT_SYMBOL(snd_pcm_kernel_ioctl); |
1117 | EXPORT_SYMBOL(snd_pcm_mmap_data); | 1115 | EXPORT_SYMBOL(snd_pcm_mmap_data); |
1118 | #if SNDRV_PCM_INFO_MMAP_IOMEM | 1116 | #if SNDRV_PCM_INFO_MMAP_IOMEM |
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index eeba2f060955..230a940d00bd 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c | |||
@@ -2299,19 +2299,7 @@ snd_pcm_sframes_t snd_pcm_lib_write(struct snd_pcm_substream *substream, const v | |||
2299 | if (runtime->status->state == SNDRV_PCM_STATE_OPEN) | 2299 | if (runtime->status->state == SNDRV_PCM_STATE_OPEN) |
2300 | return -EBADFD; | 2300 | return -EBADFD; |
2301 | 2301 | ||
2302 | snd_assert(substream->ffile != NULL, return -ENXIO); | ||
2303 | nonblock = !!(substream->ffile->f_flags & O_NONBLOCK); | 2302 | nonblock = !!(substream->ffile->f_flags & O_NONBLOCK); |
2304 | #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) | ||
2305 | if (substream->oss.oss) { | ||
2306 | struct snd_pcm_oss_setup *setup = substream->oss.setup; | ||
2307 | if (setup != NULL) { | ||
2308 | if (setup->nonblock) | ||
2309 | nonblock = 1; | ||
2310 | else if (setup->block) | ||
2311 | nonblock = 0; | ||
2312 | } | ||
2313 | } | ||
2314 | #endif | ||
2315 | 2303 | ||
2316 | if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED && | 2304 | if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED && |
2317 | runtime->channels > 1) | 2305 | runtime->channels > 1) |
@@ -2374,19 +2362,7 @@ snd_pcm_sframes_t snd_pcm_lib_writev(struct snd_pcm_substream *substream, | |||
2374 | if (runtime->status->state == SNDRV_PCM_STATE_OPEN) | 2362 | if (runtime->status->state == SNDRV_PCM_STATE_OPEN) |
2375 | return -EBADFD; | 2363 | return -EBADFD; |
2376 | 2364 | ||
2377 | snd_assert(substream->ffile != NULL, return -ENXIO); | ||
2378 | nonblock = !!(substream->ffile->f_flags & O_NONBLOCK); | 2365 | nonblock = !!(substream->ffile->f_flags & O_NONBLOCK); |
2379 | #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) | ||
2380 | if (substream->oss.oss) { | ||
2381 | struct snd_pcm_oss_setup *setup = substream->oss.setup; | ||
2382 | if (setup != NULL) { | ||
2383 | if (setup->nonblock) | ||
2384 | nonblock = 1; | ||
2385 | else if (setup->block) | ||
2386 | nonblock = 0; | ||
2387 | } | ||
2388 | } | ||
2389 | #endif | ||
2390 | 2366 | ||
2391 | if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) | 2367 | if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) |
2392 | return -EINVAL; | 2368 | return -EINVAL; |
@@ -2596,19 +2572,7 @@ snd_pcm_sframes_t snd_pcm_lib_read(struct snd_pcm_substream *substream, void __u | |||
2596 | if (runtime->status->state == SNDRV_PCM_STATE_OPEN) | 2572 | if (runtime->status->state == SNDRV_PCM_STATE_OPEN) |
2597 | return -EBADFD; | 2573 | return -EBADFD; |
2598 | 2574 | ||
2599 | snd_assert(substream->ffile != NULL, return -ENXIO); | ||
2600 | nonblock = !!(substream->ffile->f_flags & O_NONBLOCK); | 2575 | nonblock = !!(substream->ffile->f_flags & O_NONBLOCK); |
2601 | #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) | ||
2602 | if (substream->oss.oss) { | ||
2603 | struct snd_pcm_oss_setup *setup = substream->oss.setup; | ||
2604 | if (setup != NULL) { | ||
2605 | if (setup->nonblock) | ||
2606 | nonblock = 1; | ||
2607 | else if (setup->block) | ||
2608 | nonblock = 0; | ||
2609 | } | ||
2610 | } | ||
2611 | #endif | ||
2612 | if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED) | 2576 | if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED) |
2613 | return -EINVAL; | 2577 | return -EINVAL; |
2614 | return snd_pcm_lib_read1(substream, (unsigned long)buf, size, nonblock, snd_pcm_lib_read_transfer); | 2578 | return snd_pcm_lib_read1(substream, (unsigned long)buf, size, nonblock, snd_pcm_lib_read_transfer); |
@@ -2665,20 +2629,7 @@ snd_pcm_sframes_t snd_pcm_lib_readv(struct snd_pcm_substream *substream, | |||
2665 | if (runtime->status->state == SNDRV_PCM_STATE_OPEN) | 2629 | if (runtime->status->state == SNDRV_PCM_STATE_OPEN) |
2666 | return -EBADFD; | 2630 | return -EBADFD; |
2667 | 2631 | ||
2668 | snd_assert(substream->ffile != NULL, return -ENXIO); | ||
2669 | nonblock = !!(substream->ffile->f_flags & O_NONBLOCK); | 2632 | nonblock = !!(substream->ffile->f_flags & O_NONBLOCK); |
2670 | #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) | ||
2671 | if (substream->oss.oss) { | ||
2672 | struct snd_pcm_oss_setup *setup = substream->oss.setup; | ||
2673 | if (setup != NULL) { | ||
2674 | if (setup->nonblock) | ||
2675 | nonblock = 1; | ||
2676 | else if (setup->block) | ||
2677 | nonblock = 0; | ||
2678 | } | ||
2679 | } | ||
2680 | #endif | ||
2681 | |||
2682 | if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) | 2633 | if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) |
2683 | return -EINVAL; | 2634 | return -EINVAL; |
2684 | return snd_pcm_lib_read1(substream, (unsigned long)bufs, frames, nonblock, snd_pcm_lib_readv_transfer); | 2635 | return snd_pcm_lib_read1(substream, (unsigned long)bufs, frames, nonblock, snd_pcm_lib_readv_transfer); |
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 01f150f0990e..964e4c47a7f1 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c | |||
@@ -1170,7 +1170,7 @@ static int snd_pcm_resume(struct snd_pcm_substream *substream) | |||
1170 | int res; | 1170 | int res; |
1171 | 1171 | ||
1172 | snd_power_lock(card); | 1172 | snd_power_lock(card); |
1173 | if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile)) >= 0) | 1173 | if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0)) >= 0) |
1174 | res = snd_pcm_action_lock_irq(&snd_pcm_action_resume, substream, 0); | 1174 | res = snd_pcm_action_lock_irq(&snd_pcm_action_resume, substream, 0); |
1175 | snd_power_unlock(card); | 1175 | snd_power_unlock(card); |
1176 | return res; | 1176 | return res; |
@@ -1198,7 +1198,7 @@ static int snd_pcm_xrun(struct snd_pcm_substream *substream) | |||
1198 | 1198 | ||
1199 | snd_power_lock(card); | 1199 | snd_power_lock(card); |
1200 | if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { | 1200 | if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { |
1201 | result = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile); | 1201 | result = snd_power_wait(card, SNDRV_CTL_POWER_D0); |
1202 | if (result < 0) | 1202 | if (result < 0) |
1203 | goto _unlock; | 1203 | goto _unlock; |
1204 | } | 1204 | } |
@@ -1313,13 +1313,13 @@ static struct action_ops snd_pcm_action_prepare = { | |||
1313 | * | 1313 | * |
1314 | * Prepare the PCM substream to be triggerable. | 1314 | * Prepare the PCM substream to be triggerable. |
1315 | */ | 1315 | */ |
1316 | int snd_pcm_prepare(struct snd_pcm_substream *substream) | 1316 | static int snd_pcm_prepare(struct snd_pcm_substream *substream) |
1317 | { | 1317 | { |
1318 | int res; | 1318 | int res; |
1319 | struct snd_card *card = substream->pcm->card; | 1319 | struct snd_card *card = substream->pcm->card; |
1320 | 1320 | ||
1321 | snd_power_lock(card); | 1321 | snd_power_lock(card); |
1322 | if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile)) >= 0) | 1322 | if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0)) >= 0) |
1323 | res = snd_pcm_action_nonatomic(&snd_pcm_action_prepare, substream, 0); | 1323 | res = snd_pcm_action_nonatomic(&snd_pcm_action_prepare, substream, 0); |
1324 | snd_power_unlock(card); | 1324 | snd_power_unlock(card); |
1325 | return res; | 1325 | return res; |
@@ -1410,7 +1410,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream) | |||
1410 | 1410 | ||
1411 | snd_power_lock(card); | 1411 | snd_power_lock(card); |
1412 | if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { | 1412 | if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { |
1413 | result = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile); | 1413 | result = snd_power_wait(card, SNDRV_CTL_POWER_D0); |
1414 | if (result < 0) { | 1414 | if (result < 0) { |
1415 | snd_power_unlock(card); | 1415 | snd_power_unlock(card); |
1416 | return result; | 1416 | return result; |
@@ -1533,7 +1533,7 @@ static int snd_pcm_drop(struct snd_pcm_substream *substream) | |||
1533 | 1533 | ||
1534 | snd_power_lock(card); | 1534 | snd_power_lock(card); |
1535 | if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { | 1535 | if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { |
1536 | result = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile); | 1536 | result = snd_power_wait(card, SNDRV_CTL_POWER_D0); |
1537 | if (result < 0) | 1537 | if (result < 0) |
1538 | goto _unlock; | 1538 | goto _unlock; |
1539 | } | 1539 | } |
@@ -1995,28 +1995,63 @@ static void snd_pcm_remove_file(struct snd_pcm_str *str, | |||
1995 | } | 1995 | } |
1996 | } | 1996 | } |
1997 | 1997 | ||
1998 | static int snd_pcm_release_file(struct snd_pcm_file * pcm_file) | 1998 | static void pcm_release_private(struct snd_pcm_substream *substream) |
1999 | { | 1999 | { |
2000 | struct snd_pcm_substream *substream; | 2000 | struct snd_pcm_file *pcm_file = substream->file; |
2001 | struct snd_pcm_runtime *runtime; | ||
2002 | struct snd_pcm_str * str; | ||
2003 | 2001 | ||
2004 | snd_assert(pcm_file != NULL, return -ENXIO); | ||
2005 | substream = pcm_file->substream; | ||
2006 | snd_assert(substream != NULL, return -ENXIO); | ||
2007 | runtime = substream->runtime; | ||
2008 | str = substream->pstr; | ||
2009 | snd_pcm_unlink(substream); | 2002 | snd_pcm_unlink(substream); |
2010 | if (substream->ffile != NULL) { | 2003 | snd_pcm_remove_file(substream->pstr, pcm_file); |
2004 | kfree(pcm_file); | ||
2005 | } | ||
2006 | |||
2007 | void snd_pcm_release_substream(struct snd_pcm_substream *substream) | ||
2008 | { | ||
2009 | snd_pcm_drop(substream); | ||
2010 | if (substream->pcm_release) | ||
2011 | substream->pcm_release(substream); | ||
2012 | if (substream->hw_opened) { | ||
2011 | if (substream->ops->hw_free != NULL) | 2013 | if (substream->ops->hw_free != NULL) |
2012 | substream->ops->hw_free(substream); | 2014 | substream->ops->hw_free(substream); |
2013 | substream->ops->close(substream); | 2015 | substream->ops->close(substream); |
2014 | substream->ffile = NULL; | 2016 | substream->hw_opened = 0; |
2015 | } | 2017 | } |
2016 | snd_pcm_remove_file(str, pcm_file); | 2018 | snd_pcm_detach_substream(substream); |
2017 | snd_pcm_release_substream(substream); | 2019 | } |
2018 | kfree(pcm_file); | 2020 | |
2021 | int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, | ||
2022 | struct file *file, | ||
2023 | struct snd_pcm_substream **rsubstream) | ||
2024 | { | ||
2025 | struct snd_pcm_substream *substream; | ||
2026 | int err; | ||
2027 | |||
2028 | err = snd_pcm_attach_substream(pcm, stream, file, &substream); | ||
2029 | if (err < 0) | ||
2030 | return err; | ||
2031 | substream->no_mmap_ctrl = 0; | ||
2032 | err = snd_pcm_hw_constraints_init(substream); | ||
2033 | if (err < 0) { | ||
2034 | snd_printd("snd_pcm_hw_constraints_init failed\n"); | ||
2035 | goto error; | ||
2036 | } | ||
2037 | |||
2038 | if ((err = substream->ops->open(substream)) < 0) | ||
2039 | goto error; | ||
2040 | |||
2041 | substream->hw_opened = 1; | ||
2042 | |||
2043 | err = snd_pcm_hw_constraints_complete(substream); | ||
2044 | if (err < 0) { | ||
2045 | snd_printd("snd_pcm_hw_constraints_complete failed\n"); | ||
2046 | goto error; | ||
2047 | } | ||
2048 | |||
2049 | *rsubstream = substream; | ||
2019 | return 0; | 2050 | return 0; |
2051 | |||
2052 | error: | ||
2053 | snd_pcm_release_substream(substream); | ||
2054 | return err; | ||
2020 | } | 2055 | } |
2021 | 2056 | ||
2022 | static int snd_pcm_open_file(struct file *file, | 2057 | static int snd_pcm_open_file(struct file *file, |
@@ -2024,52 +2059,29 @@ static int snd_pcm_open_file(struct file *file, | |||
2024 | int stream, | 2059 | int stream, |
2025 | struct snd_pcm_file **rpcm_file) | 2060 | struct snd_pcm_file **rpcm_file) |
2026 | { | 2061 | { |
2027 | int err = 0; | ||
2028 | struct snd_pcm_file *pcm_file; | 2062 | struct snd_pcm_file *pcm_file; |
2029 | struct snd_pcm_substream *substream; | 2063 | struct snd_pcm_substream *substream; |
2030 | struct snd_pcm_str *str; | 2064 | struct snd_pcm_str *str; |
2065 | int err; | ||
2031 | 2066 | ||
2032 | snd_assert(rpcm_file != NULL, return -EINVAL); | 2067 | snd_assert(rpcm_file != NULL, return -EINVAL); |
2033 | *rpcm_file = NULL; | 2068 | *rpcm_file = NULL; |
2034 | 2069 | ||
2070 | err = snd_pcm_open_substream(pcm, stream, file, &substream); | ||
2071 | if (err < 0) | ||
2072 | return err; | ||
2073 | |||
2035 | pcm_file = kzalloc(sizeof(*pcm_file), GFP_KERNEL); | 2074 | pcm_file = kzalloc(sizeof(*pcm_file), GFP_KERNEL); |
2036 | if (pcm_file == NULL) { | 2075 | if (pcm_file == NULL) { |
2076 | snd_pcm_release_substream(substream); | ||
2037 | return -ENOMEM; | 2077 | return -ENOMEM; |
2038 | } | 2078 | } |
2039 | |||
2040 | if ((err = snd_pcm_open_substream(pcm, stream, &substream)) < 0) { | ||
2041 | kfree(pcm_file); | ||
2042 | return err; | ||
2043 | } | ||
2044 | |||
2045 | str = substream->pstr; | 2079 | str = substream->pstr; |
2046 | substream->file = pcm_file; | 2080 | substream->file = pcm_file; |
2047 | substream->no_mmap_ctrl = 0; | 2081 | substream->pcm_release = pcm_release_private; |
2048 | |||
2049 | pcm_file->substream = substream; | 2082 | pcm_file->substream = substream; |
2050 | |||
2051 | snd_pcm_add_file(str, pcm_file); | 2083 | snd_pcm_add_file(str, pcm_file); |
2052 | 2084 | ||
2053 | err = snd_pcm_hw_constraints_init(substream); | ||
2054 | if (err < 0) { | ||
2055 | snd_printd("snd_pcm_hw_constraints_init failed\n"); | ||
2056 | snd_pcm_release_file(pcm_file); | ||
2057 | return err; | ||
2058 | } | ||
2059 | |||
2060 | if ((err = substream->ops->open(substream)) < 0) { | ||
2061 | snd_pcm_release_file(pcm_file); | ||
2062 | return err; | ||
2063 | } | ||
2064 | substream->ffile = file; | ||
2065 | |||
2066 | err = snd_pcm_hw_constraints_complete(substream); | ||
2067 | if (err < 0) { | ||
2068 | snd_printd("snd_pcm_hw_constraints_complete failed\n"); | ||
2069 | snd_pcm_release_file(pcm_file); | ||
2070 | return err; | ||
2071 | } | ||
2072 | |||
2073 | file->private_data = pcm_file; | 2085 | file->private_data = pcm_file; |
2074 | *rpcm_file = pcm_file; | 2086 | *rpcm_file = pcm_file; |
2075 | return 0; | 2087 | return 0; |
@@ -2158,10 +2170,9 @@ static int snd_pcm_release(struct inode *inode, struct file *file) | |||
2158 | snd_assert(substream != NULL, return -ENXIO); | 2170 | snd_assert(substream != NULL, return -ENXIO); |
2159 | snd_assert(!atomic_read(&substream->runtime->mmap_count), ); | 2171 | snd_assert(!atomic_read(&substream->runtime->mmap_count), ); |
2160 | pcm = substream->pcm; | 2172 | pcm = substream->pcm; |
2161 | snd_pcm_drop(substream); | ||
2162 | fasync_helper(-1, file, 0, &substream->runtime->fasync); | 2173 | fasync_helper(-1, file, 0, &substream->runtime->fasync); |
2163 | mutex_lock(&pcm->open_mutex); | 2174 | mutex_lock(&pcm->open_mutex); |
2164 | snd_pcm_release_file(pcm_file); | 2175 | snd_pcm_release_substream(substream); |
2165 | mutex_unlock(&pcm->open_mutex); | 2176 | mutex_unlock(&pcm->open_mutex); |
2166 | wake_up(&pcm->open_wait); | 2177 | wake_up(&pcm->open_wait); |
2167 | module_put(pcm->card->module); | 2178 | module_put(pcm->card->module); |
@@ -2480,11 +2491,6 @@ static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream, | |||
2480 | return 0; | 2491 | return 0; |
2481 | } | 2492 | } |
2482 | 2493 | ||
2483 | static int snd_pcm_playback_ioctl1(struct snd_pcm_substream *substream, | ||
2484 | unsigned int cmd, void __user *arg); | ||
2485 | static int snd_pcm_capture_ioctl1(struct snd_pcm_substream *substream, | ||
2486 | unsigned int cmd, void __user *arg); | ||
2487 | |||
2488 | static int snd_pcm_common_ioctl1(struct snd_pcm_substream *substream, | 2494 | static int snd_pcm_common_ioctl1(struct snd_pcm_substream *substream, |
2489 | unsigned int cmd, void __user *arg) | 2495 | unsigned int cmd, void __user *arg) |
2490 | { | 2496 | { |
@@ -2736,41 +2742,28 @@ static long snd_pcm_capture_ioctl(struct file *file, unsigned int cmd, | |||
2736 | return snd_pcm_capture_ioctl1(pcm_file->substream, cmd, (void __user *)arg); | 2742 | return snd_pcm_capture_ioctl1(pcm_file->substream, cmd, (void __user *)arg); |
2737 | } | 2743 | } |
2738 | 2744 | ||
2739 | int snd_pcm_kernel_playback_ioctl(struct snd_pcm_substream *substream, | 2745 | int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream, |
2740 | unsigned int cmd, void *arg) | 2746 | unsigned int cmd, void *arg) |
2741 | { | ||
2742 | mm_segment_t fs; | ||
2743 | int result; | ||
2744 | |||
2745 | fs = snd_enter_user(); | ||
2746 | result = snd_pcm_playback_ioctl1(substream, cmd, (void __user *)arg); | ||
2747 | snd_leave_user(fs); | ||
2748 | return result; | ||
2749 | } | ||
2750 | |||
2751 | int snd_pcm_kernel_capture_ioctl(struct snd_pcm_substream *substream, | ||
2752 | unsigned int cmd, void *arg) | ||
2753 | { | 2747 | { |
2754 | mm_segment_t fs; | 2748 | mm_segment_t fs; |
2755 | int result; | 2749 | int result; |
2756 | 2750 | ||
2757 | fs = snd_enter_user(); | 2751 | fs = snd_enter_user(); |
2758 | result = snd_pcm_capture_ioctl1(substream, cmd, (void __user *)arg); | ||
2759 | snd_leave_user(fs); | ||
2760 | return result; | ||
2761 | } | ||
2762 | |||
2763 | int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream, | ||
2764 | unsigned int cmd, void *arg) | ||
2765 | { | ||
2766 | switch (substream->stream) { | 2752 | switch (substream->stream) { |
2767 | case SNDRV_PCM_STREAM_PLAYBACK: | 2753 | case SNDRV_PCM_STREAM_PLAYBACK: |
2768 | return snd_pcm_kernel_playback_ioctl(substream, cmd, arg); | 2754 | result = snd_pcm_playback_ioctl1(substream, |
2755 | cmd, (void __user *)arg); | ||
2756 | break; | ||
2769 | case SNDRV_PCM_STREAM_CAPTURE: | 2757 | case SNDRV_PCM_STREAM_CAPTURE: |
2770 | return snd_pcm_kernel_capture_ioctl(substream, cmd, arg); | 2758 | result = snd_pcm_capture_ioctl1(substream, |
2759 | cmd, (void __user *)arg); | ||
2760 | break; | ||
2771 | default: | 2761 | default: |
2772 | return -EINVAL; | 2762 | result = -EINVAL; |
2763 | break; | ||
2773 | } | 2764 | } |
2765 | snd_leave_user(fs); | ||
2766 | return result; | ||
2774 | } | 2767 | } |
2775 | 2768 | ||
2776 | static ssize_t snd_pcm_read(struct file *file, char __user *buf, size_t count, | 2769 | static ssize_t snd_pcm_read(struct file *file, char __user *buf, size_t count, |
diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig index ff8fef932786..557c4de22960 100644 --- a/sound/isa/Kconfig +++ b/sound/isa/Kconfig | |||
@@ -11,6 +11,15 @@ config SND_CS4231_LIB | |||
11 | tristate | 11 | tristate |
12 | select SND_PCM | 12 | select SND_PCM |
13 | 13 | ||
14 | config SND_ADLIB | ||
15 | tristate "AdLib FM card" | ||
16 | select SND_OPL3_LIB | ||
17 | help | ||
18 | Say Y here to include support for AdLib FM cards. | ||
19 | |||
20 | To compile this driver as a module, choose M here: the module | ||
21 | will be called snd-adlib. | ||
22 | |||
14 | config SND_AD1816A | 23 | config SND_AD1816A |
15 | tristate "Analog Devices SoundPort AD1816A" | 24 | tristate "Analog Devices SoundPort AD1816A" |
16 | depends on SND && PNP && ISA | 25 | depends on SND && PNP && ISA |
@@ -292,6 +301,20 @@ config SND_OPTI93X | |||
292 | To compile this driver as a module, choose M here: the module | 301 | To compile this driver as a module, choose M here: the module |
293 | will be called snd-opti93x. | 302 | will be called snd-opti93x. |
294 | 303 | ||
304 | config SND_MIRO | ||
305 | tristate "Miro miroSOUND PCM1pro/PCM12/PCM20radio driver" | ||
306 | depends on SND | ||
307 | select SND_OPL4_LIB | ||
308 | select SND_CS4231_LIB | ||
309 | select SND_MPU401_UART | ||
310 | select SND_PCM | ||
311 | help | ||
312 | Say 'Y' or 'M' to include support for Miro miroSOUND PCM1 pro, | ||
313 | miroSOUND PCM12 and miroSOUND PCM20 Radio soundcards. | ||
314 | |||
315 | To compile this driver as a module, choose M here: the module | ||
316 | will be called snd-miro. | ||
317 | |||
295 | config SND_SB8 | 318 | config SND_SB8 |
296 | tristate "Sound Blaster 1.0/2.0/Pro (8-bit)" | 319 | tristate "Sound Blaster 1.0/2.0/Pro (8-bit)" |
297 | depends on SND | 320 | depends on SND |
diff --git a/sound/isa/Makefile b/sound/isa/Makefile index 05724eb7bfe4..bb317ccc170f 100644 --- a/sound/isa/Makefile +++ b/sound/isa/Makefile | |||
@@ -3,6 +3,7 @@ | |||
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-adlib-objs := adlib.o | ||
6 | snd-als100-objs := als100.o | 7 | snd-als100-objs := als100.o |
7 | snd-azt2320-objs := azt2320.o | 8 | snd-azt2320-objs := azt2320.o |
8 | snd-cmi8330-objs := cmi8330.o | 9 | snd-cmi8330-objs := cmi8330.o |
@@ -13,6 +14,7 @@ snd-sgalaxy-objs := sgalaxy.o | |||
13 | snd-sscape-objs := sscape.o | 14 | snd-sscape-objs := sscape.o |
14 | 15 | ||
15 | # Toplevel Module Dependency | 16 | # Toplevel Module Dependency |
17 | obj-$(CONFIG_SND_ADLIB) += snd-adlib.o | ||
16 | obj-$(CONFIG_SND_ALS100) += snd-als100.o | 18 | obj-$(CONFIG_SND_ALS100) += snd-als100.o |
17 | obj-$(CONFIG_SND_AZT2320) += snd-azt2320.o | 19 | obj-$(CONFIG_SND_AZT2320) += snd-azt2320.o |
18 | obj-$(CONFIG_SND_CMI8330) += snd-cmi8330.o | 20 | obj-$(CONFIG_SND_CMI8330) += snd-cmi8330.o |
diff --git a/sound/isa/adlib.c b/sound/isa/adlib.c new file mode 100644 index 000000000000..a253a14e6a45 --- /dev/null +++ b/sound/isa/adlib.c | |||
@@ -0,0 +1,161 @@ | |||
1 | /* | ||
2 | * AdLib FM card driver. | ||
3 | */ | ||
4 | |||
5 | #include <sound/driver.h> | ||
6 | #include <linux/kernel.h> | ||
7 | #include <linux/module.h> | ||
8 | #include <linux/platform_device.h> | ||
9 | #include <sound/core.h> | ||
10 | #include <sound/initval.h> | ||
11 | #include <sound/opl3.h> | ||
12 | |||
13 | #define CRD_NAME "AdLib FM" | ||
14 | #define DRV_NAME "snd_adlib" | ||
15 | |||
16 | MODULE_DESCRIPTION(CRD_NAME); | ||
17 | MODULE_AUTHOR("Rene Herman"); | ||
18 | MODULE_LICENSE("GPL"); | ||
19 | |||
20 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; | ||
21 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; | ||
22 | static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; | ||
23 | static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; | ||
24 | |||
25 | module_param_array(index, int, NULL, 0444); | ||
26 | MODULE_PARM_DESC(index, "Index value for " CRD_NAME " soundcard."); | ||
27 | module_param_array(id, charp, NULL, 0444); | ||
28 | MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard."); | ||
29 | module_param_array(enable, bool, NULL, 0444); | ||
30 | MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard."); | ||
31 | module_param_array(port, long, NULL, 0444); | ||
32 | MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver."); | ||
33 | |||
34 | static struct platform_device *devices[SNDRV_CARDS]; | ||
35 | |||
36 | static void snd_adlib_free(struct snd_card *card) | ||
37 | { | ||
38 | release_and_free_resource(card->private_data); | ||
39 | } | ||
40 | |||
41 | static int __devinit snd_adlib_probe(struct platform_device *device) | ||
42 | { | ||
43 | struct snd_card *card; | ||
44 | struct snd_opl3 *opl3; | ||
45 | |||
46 | int error; | ||
47 | int i = device->id; | ||
48 | |||
49 | if (port[i] == SNDRV_AUTO_PORT) { | ||
50 | snd_printk(KERN_ERR DRV_NAME ": please specify port\n"); | ||
51 | error = -EINVAL; | ||
52 | goto out0; | ||
53 | } | ||
54 | |||
55 | card = snd_card_new(index[i], id[i], THIS_MODULE, 0); | ||
56 | if (!card) { | ||
57 | snd_printk(KERN_ERR DRV_NAME ": could not create card\n"); | ||
58 | error = -EINVAL; | ||
59 | goto out0; | ||
60 | } | ||
61 | |||
62 | card->private_data = request_region(port[i], 4, CRD_NAME); | ||
63 | if (!card->private_data) { | ||
64 | snd_printk(KERN_ERR DRV_NAME ": could not grab ports\n"); | ||
65 | error = -EBUSY; | ||
66 | goto out1; | ||
67 | } | ||
68 | card->private_free = snd_adlib_free; | ||
69 | |||
70 | error = snd_opl3_create(card, port[i], port[i] + 2, OPL3_HW_AUTO, 1, &opl3); | ||
71 | if (error < 0) { | ||
72 | snd_printk(KERN_ERR DRV_NAME ": could not create OPL\n"); | ||
73 | goto out1; | ||
74 | } | ||
75 | |||
76 | error = snd_opl3_hwdep_new(opl3, 0, 0, NULL); | ||
77 | if (error < 0) { | ||
78 | snd_printk(KERN_ERR DRV_NAME ": could not create FM\n"); | ||
79 | goto out1; | ||
80 | } | ||
81 | |||
82 | strcpy(card->driver, DRV_NAME); | ||
83 | strcpy(card->shortname, CRD_NAME); | ||
84 | sprintf(card->longname, CRD_NAME " at %#lx", port[i]); | ||
85 | |||
86 | snd_card_set_dev(card, &device->dev); | ||
87 | |||
88 | error = snd_card_register(card); | ||
89 | if (error < 0) { | ||
90 | snd_printk(KERN_ERR DRV_NAME ": could not register card\n"); | ||
91 | goto out1; | ||
92 | } | ||
93 | |||
94 | platform_set_drvdata(device, card); | ||
95 | return 0; | ||
96 | |||
97 | out1: snd_card_free(card); | ||
98 | out0: error = -EINVAL; /* FIXME: should be the original error code */ | ||
99 | return error; | ||
100 | } | ||
101 | |||
102 | static int __devexit snd_adlib_remove(struct platform_device *device) | ||
103 | { | ||
104 | snd_card_free(platform_get_drvdata(device)); | ||
105 | platform_set_drvdata(device, NULL); | ||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | static struct platform_driver snd_adlib_driver = { | ||
110 | .probe = snd_adlib_probe, | ||
111 | .remove = __devexit_p(snd_adlib_remove), | ||
112 | |||
113 | .driver = { | ||
114 | .name = DRV_NAME | ||
115 | } | ||
116 | }; | ||
117 | |||
118 | static int __init alsa_card_adlib_init(void) | ||
119 | { | ||
120 | int i, cards; | ||
121 | |||
122 | if (platform_driver_register(&snd_adlib_driver) < 0) { | ||
123 | snd_printk(KERN_ERR DRV_NAME ": could not register driver\n"); | ||
124 | return -ENODEV; | ||
125 | } | ||
126 | |||
127 | for (cards = 0, i = 0; i < SNDRV_CARDS; i++) { | ||
128 | struct platform_device *device; | ||
129 | |||
130 | if (!enable[i]) | ||
131 | continue; | ||
132 | |||
133 | device = platform_device_register_simple(DRV_NAME, i, NULL, 0); | ||
134 | if (IS_ERR(device)) | ||
135 | continue; | ||
136 | |||
137 | devices[i] = device; | ||
138 | cards++; | ||
139 | } | ||
140 | |||
141 | if (!cards) { | ||
142 | #ifdef MODULE | ||
143 | printk(KERN_ERR CRD_NAME " soundcard not found or device busy\n"); | ||
144 | #endif | ||
145 | platform_driver_unregister(&snd_adlib_driver); | ||
146 | return -ENODEV; | ||
147 | } | ||
148 | return 0; | ||
149 | } | ||
150 | |||
151 | static void __exit alsa_card_adlib_exit(void) | ||
152 | { | ||
153 | int i; | ||
154 | |||
155 | for (i = 0; i < SNDRV_CARDS; i++) | ||
156 | platform_device_unregister(devices[i]); | ||
157 | platform_driver_unregister(&snd_adlib_driver); | ||
158 | } | ||
159 | |||
160 | module_init(alsa_card_adlib_init); | ||
161 | module_exit(alsa_card_adlib_exit); | ||
diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c index fa63048a8b9d..bc0f5ebf5d3c 100644 --- a/sound/isa/cmi8330.c +++ b/sound/isa/cmi8330.c | |||
@@ -693,9 +693,9 @@ static int __init alsa_card_cmi8330_init(void) | |||
693 | if ((err = platform_driver_register(&snd_cmi8330_driver)) < 0) | 693 | if ((err = platform_driver_register(&snd_cmi8330_driver)) < 0) |
694 | return err; | 694 | return err; |
695 | 695 | ||
696 | for (i = 0; i < SNDRV_CARDS && enable[i]; i++) { | 696 | for (i = 0; i < SNDRV_CARDS; i++) { |
697 | struct platform_device *device; | 697 | struct platform_device *device; |
698 | if (is_isapnp_selected(i)) | 698 | if (! enable[i] || is_isapnp_selected(i)) |
699 | continue; | 699 | continue; |
700 | device = platform_device_register_simple(CMI8330_DRIVER, | 700 | device = platform_device_register_simple(CMI8330_DRIVER, |
701 | i, NULL, 0); | 701 | i, NULL, 0); |
diff --git a/sound/isa/opti9xx/Makefile b/sound/isa/opti9xx/Makefile index 28c64070cd56..0e41bfd5a403 100644 --- a/sound/isa/opti9xx/Makefile +++ b/sound/isa/opti9xx/Makefile | |||
@@ -6,8 +6,10 @@ | |||
6 | snd-opti92x-ad1848-objs := opti92x-ad1848.o | 6 | snd-opti92x-ad1848-objs := opti92x-ad1848.o |
7 | snd-opti92x-cs4231-objs := opti92x-cs4231.o | 7 | snd-opti92x-cs4231-objs := opti92x-cs4231.o |
8 | snd-opti93x-objs := opti93x.o | 8 | snd-opti93x-objs := opti93x.o |
9 | snd-miro-objs := miro.o | ||
9 | 10 | ||
10 | # Toplevel Module Dependency | 11 | # Toplevel Module Dependency |
11 | obj-$(CONFIG_SND_OPTI92X_AD1848) += snd-opti92x-ad1848.o | 12 | obj-$(CONFIG_SND_OPTI92X_AD1848) += snd-opti92x-ad1848.o |
12 | obj-$(CONFIG_SND_OPTI92X_CS4231) += snd-opti92x-cs4231.o | 13 | obj-$(CONFIG_SND_OPTI92X_CS4231) += snd-opti92x-cs4231.o |
13 | obj-$(CONFIG_SND_OPTI93X) += snd-opti93x.o | 14 | obj-$(CONFIG_SND_OPTI93X) += snd-opti93x.o |
15 | obj-$(CONFIG_SND_MIRO) += snd-miro.o | ||
diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c new file mode 100644 index 000000000000..09384d03dc31 --- /dev/null +++ b/sound/isa/opti9xx/miro.c | |||
@@ -0,0 +1,1455 @@ | |||
1 | /* | ||
2 | * ALSA soundcard driver for Miro miroSOUND PCM1 pro | ||
3 | * miroSOUND PCM12 | ||
4 | * miroSOUND PCM20 Radio | ||
5 | * | ||
6 | * Copyright (C) 2004-2005 Martin Langer <martin-langer@gmx.de> | ||
7 | * | ||
8 | * Based on OSS ACI and ALSA OPTi9xx drivers | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
23 | */ | ||
24 | |||
25 | #include <sound/driver.h> | ||
26 | #include <linux/init.h> | ||
27 | #include <linux/err.h> | ||
28 | #include <linux/platform_device.h> | ||
29 | #include <linux/delay.h> | ||
30 | #include <linux/slab.h> | ||
31 | #include <linux/ioport.h> | ||
32 | #include <linux/moduleparam.h> | ||
33 | #include <asm/io.h> | ||
34 | #include <asm/dma.h> | ||
35 | #include <sound/core.h> | ||
36 | #include <sound/cs4231.h> | ||
37 | #include <sound/mpu401.h> | ||
38 | #include <sound/opl4.h> | ||
39 | #include <sound/control.h> | ||
40 | #include <sound/info.h> | ||
41 | #define SNDRV_LEGACY_FIND_FREE_IRQ | ||
42 | #define SNDRV_LEGACY_FIND_FREE_DMA | ||
43 | #include <sound/initval.h> | ||
44 | #include "miro.h" | ||
45 | |||
46 | MODULE_AUTHOR("Martin Langer <martin-langer@gmx.de>"); | ||
47 | MODULE_LICENSE("GPL"); | ||
48 | MODULE_DESCRIPTION("Miro miroSOUND PCM1 pro, PCM12, PCM20 Radio"); | ||
49 | MODULE_SUPPORTED_DEVICE("{{Miro,miroSOUND PCM1 pro}, " | ||
50 | "{Miro,miroSOUND PCM12}, " | ||
51 | "{Miro,miroSOUND PCM20 Radio}}"); | ||
52 | |||
53 | static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */ | ||
54 | static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ | ||
55 | static long port = SNDRV_DEFAULT_PORT1; /* 0x530,0xe80,0xf40,0x604 */ | ||
56 | static long mpu_port = SNDRV_DEFAULT_PORT1; /* 0x300,0x310,0x320,0x330 */ | ||
57 | static long fm_port = SNDRV_DEFAULT_PORT1; /* 0x388 */ | ||
58 | static int irq = SNDRV_DEFAULT_IRQ1; /* 5,7,9,10,11 */ | ||
59 | static int mpu_irq = SNDRV_DEFAULT_IRQ1; /* 5,7,9,10 */ | ||
60 | static int dma1 = SNDRV_DEFAULT_DMA1; /* 0,1,3 */ | ||
61 | static int dma2 = SNDRV_DEFAULT_DMA1; /* 0,1,3 */ | ||
62 | static int wss; | ||
63 | static int ide; | ||
64 | |||
65 | module_param(index, int, 0444); | ||
66 | MODULE_PARM_DESC(index, "Index value for miro soundcard."); | ||
67 | module_param(id, charp, 0444); | ||
68 | MODULE_PARM_DESC(id, "ID string for miro soundcard."); | ||
69 | module_param(port, long, 0444); | ||
70 | MODULE_PARM_DESC(port, "WSS port # for miro driver."); | ||
71 | module_param(mpu_port, long, 0444); | ||
72 | MODULE_PARM_DESC(mpu_port, "MPU-401 port # for miro driver."); | ||
73 | module_param(fm_port, long, 0444); | ||
74 | MODULE_PARM_DESC(fm_port, "FM Port # for miro driver."); | ||
75 | module_param(irq, int, 0444); | ||
76 | MODULE_PARM_DESC(irq, "WSS irq # for miro driver."); | ||
77 | module_param(mpu_irq, int, 0444); | ||
78 | MODULE_PARM_DESC(mpu_irq, "MPU-401 irq # for miro driver."); | ||
79 | module_param(dma1, int, 0444); | ||
80 | MODULE_PARM_DESC(dma1, "1st dma # for miro driver."); | ||
81 | module_param(dma2, int, 0444); | ||
82 | MODULE_PARM_DESC(dma2, "2nd dma # for miro driver."); | ||
83 | module_param(wss, int, 0444); | ||
84 | MODULE_PARM_DESC(wss, "wss mode"); | ||
85 | module_param(ide, int, 0444); | ||
86 | MODULE_PARM_DESC(ide, "enable ide port"); | ||
87 | |||
88 | #define OPTi9XX_HW_DETECT 0 | ||
89 | #define OPTi9XX_HW_82C928 1 | ||
90 | #define OPTi9XX_HW_82C929 2 | ||
91 | #define OPTi9XX_HW_82C924 3 | ||
92 | #define OPTi9XX_HW_82C925 4 | ||
93 | #define OPTi9XX_HW_82C930 5 | ||
94 | #define OPTi9XX_HW_82C931 6 | ||
95 | #define OPTi9XX_HW_82C933 7 | ||
96 | #define OPTi9XX_HW_LAST OPTi9XX_HW_82C933 | ||
97 | |||
98 | #define OPTi9XX_MC_REG(n) n | ||
99 | |||
100 | |||
101 | struct snd_miro { | ||
102 | unsigned short hardware; | ||
103 | unsigned char password; | ||
104 | char name[7]; | ||
105 | |||
106 | struct resource *res_mc_base; | ||
107 | struct resource *res_aci_port; | ||
108 | |||
109 | unsigned long mc_base; | ||
110 | unsigned long mc_base_size; | ||
111 | unsigned long pwd_reg; | ||
112 | |||
113 | spinlock_t lock; | ||
114 | struct snd_card *card; | ||
115 | struct snd_pcm *pcm; | ||
116 | |||
117 | long wss_base; | ||
118 | int irq; | ||
119 | int dma1; | ||
120 | int dma2; | ||
121 | |||
122 | long fm_port; | ||
123 | |||
124 | long mpu_port; | ||
125 | int mpu_irq; | ||
126 | |||
127 | unsigned long aci_port; | ||
128 | int aci_vendor; | ||
129 | int aci_product; | ||
130 | int aci_version; | ||
131 | int aci_amp; | ||
132 | int aci_preamp; | ||
133 | int aci_solomode; | ||
134 | |||
135 | struct mutex aci_mutex; | ||
136 | }; | ||
137 | |||
138 | static void snd_miro_proc_init(struct snd_miro * miro); | ||
139 | |||
140 | #define DRIVER_NAME "snd-miro" | ||
141 | |||
142 | static struct platform_device *device; | ||
143 | |||
144 | static char * snd_opti9xx_names[] = { | ||
145 | "unkown", | ||
146 | "82C928", "82C929", | ||
147 | "82C924", "82C925", | ||
148 | "82C930", "82C931", "82C933" | ||
149 | }; | ||
150 | |||
151 | /* | ||
152 | * ACI control | ||
153 | */ | ||
154 | |||
155 | static int aci_busy_wait(struct snd_miro * miro) | ||
156 | { | ||
157 | long timeout; | ||
158 | unsigned char byte; | ||
159 | |||
160 | for (timeout = 1; timeout <= ACI_MINTIME+30; timeout++) { | ||
161 | if (((byte=inb(miro->aci_port + ACI_REG_BUSY)) & 1) == 0) { | ||
162 | if (timeout >= ACI_MINTIME) | ||
163 | snd_printd("aci ready in round %ld.\n", | ||
164 | timeout-ACI_MINTIME); | ||
165 | return byte; | ||
166 | } | ||
167 | if (timeout >= ACI_MINTIME) { | ||
168 | long out=10*HZ; | ||
169 | switch (timeout-ACI_MINTIME) { | ||
170 | case 0 ... 9: | ||
171 | out /= 10; | ||
172 | case 10 ... 19: | ||
173 | out /= 10; | ||
174 | case 20 ... 30: | ||
175 | out /= 10; | ||
176 | default: | ||
177 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
178 | schedule_timeout(out); | ||
179 | break; | ||
180 | } | ||
181 | } | ||
182 | } | ||
183 | snd_printk(KERN_ERR "aci_busy_wait() time out\n"); | ||
184 | return -EBUSY; | ||
185 | } | ||
186 | |||
187 | static inline int aci_write(struct snd_miro * miro, unsigned char byte) | ||
188 | { | ||
189 | if (aci_busy_wait(miro) >= 0) { | ||
190 | outb(byte, miro->aci_port + ACI_REG_COMMAND); | ||
191 | return 0; | ||
192 | } else { | ||
193 | snd_printk(KERN_ERR "aci busy, aci_write(0x%x) stopped.\n", byte); | ||
194 | return -EBUSY; | ||
195 | } | ||
196 | } | ||
197 | |||
198 | static inline int aci_read(struct snd_miro * miro) | ||
199 | { | ||
200 | unsigned char byte; | ||
201 | |||
202 | if (aci_busy_wait(miro) >= 0) { | ||
203 | byte=inb(miro->aci_port + ACI_REG_STATUS); | ||
204 | return byte; | ||
205 | } else { | ||
206 | snd_printk(KERN_ERR "aci busy, aci_read() stopped.\n"); | ||
207 | return -EBUSY; | ||
208 | } | ||
209 | } | ||
210 | |||
211 | static int aci_cmd(struct snd_miro * miro, int write1, int write2, int write3) | ||
212 | { | ||
213 | int write[] = {write1, write2, write3}; | ||
214 | int value, i; | ||
215 | |||
216 | if (mutex_lock_interruptible(&miro->aci_mutex)) | ||
217 | return -EINTR; | ||
218 | |||
219 | for (i=0; i<3; i++) { | ||
220 | if (write[i]< 0 || write[i] > 255) | ||
221 | break; | ||
222 | else { | ||
223 | value = aci_write(miro, write[i]); | ||
224 | if (value < 0) | ||
225 | goto out; | ||
226 | } | ||
227 | } | ||
228 | |||
229 | value = aci_read(miro); | ||
230 | |||
231 | out: mutex_unlock(&miro->aci_mutex); | ||
232 | return value; | ||
233 | } | ||
234 | |||
235 | static int aci_getvalue(struct snd_miro * miro, unsigned char index) | ||
236 | { | ||
237 | return aci_cmd(miro, ACI_STATUS, index, -1); | ||
238 | } | ||
239 | |||
240 | static int aci_setvalue(struct snd_miro * miro, unsigned char index, int value) | ||
241 | { | ||
242 | return aci_cmd(miro, index, value, -1); | ||
243 | } | ||
244 | |||
245 | /* | ||
246 | * MIXER part | ||
247 | */ | ||
248 | |||
249 | static int snd_miro_info_capture(struct snd_kcontrol *kcontrol, | ||
250 | struct snd_ctl_elem_info *uinfo) | ||
251 | { | ||
252 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
253 | uinfo->count = 1; | ||
254 | |||
255 | return 0; | ||
256 | } | ||
257 | |||
258 | static int snd_miro_get_capture(struct snd_kcontrol *kcontrol, | ||
259 | struct snd_ctl_elem_value *ucontrol) | ||
260 | { | ||
261 | struct snd_miro *miro = snd_kcontrol_chip(kcontrol); | ||
262 | int value; | ||
263 | |||
264 | if ((value = aci_getvalue(miro, ACI_S_GENERAL)) < 0) { | ||
265 | snd_printk(KERN_ERR "snd_miro_get_capture() failed: %d\n", value); | ||
266 | return value; | ||
267 | } | ||
268 | |||
269 | ucontrol->value.integer.value[0] = value & 0x20; | ||
270 | |||
271 | return 0; | ||
272 | } | ||
273 | |||
274 | static int snd_miro_put_capture(struct snd_kcontrol *kcontrol, | ||
275 | struct snd_ctl_elem_value *ucontrol) | ||
276 | { | ||
277 | struct snd_miro *miro = snd_kcontrol_chip(kcontrol); | ||
278 | int change, value, error; | ||
279 | |||
280 | value = !(ucontrol->value.integer.value[0]); | ||
281 | |||
282 | if ((error = aci_setvalue(miro, ACI_SET_SOLOMODE, value)) < 0) { | ||
283 | snd_printk(KERN_ERR "snd_miro_put_capture() failed: %d\n", error); | ||
284 | return error; | ||
285 | } | ||
286 | |||
287 | change = (value != miro->aci_solomode); | ||
288 | miro->aci_solomode = value; | ||
289 | |||
290 | return change; | ||
291 | } | ||
292 | |||
293 | static int snd_miro_info_preamp(struct snd_kcontrol *kcontrol, | ||
294 | struct snd_ctl_elem_info *uinfo) | ||
295 | { | ||
296 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
297 | uinfo->count = 1; | ||
298 | uinfo->value.integer.min = 0; | ||
299 | uinfo->value.integer.max = 3; | ||
300 | |||
301 | return 0; | ||
302 | } | ||
303 | |||
304 | static int snd_miro_get_preamp(struct snd_kcontrol *kcontrol, | ||
305 | struct snd_ctl_elem_value *ucontrol) | ||
306 | { | ||
307 | struct snd_miro *miro = snd_kcontrol_chip(kcontrol); | ||
308 | int value; | ||
309 | |||
310 | if (miro->aci_version <= 176) { | ||
311 | |||
312 | /* | ||
313 | OSS says it's not readable with versions < 176. | ||
314 | But it doesn't work on my card, | ||
315 | which is a PCM12 with aci_version = 176. | ||
316 | */ | ||
317 | |||
318 | ucontrol->value.integer.value[0] = miro->aci_preamp; | ||
319 | return 0; | ||
320 | } | ||
321 | |||
322 | if ((value = aci_getvalue(miro, ACI_GET_PREAMP)) < 0) { | ||
323 | snd_printk(KERN_ERR "snd_miro_get_preamp() failed: %d\n", value); | ||
324 | return value; | ||
325 | } | ||
326 | |||
327 | ucontrol->value.integer.value[0] = value; | ||
328 | |||
329 | return 0; | ||
330 | } | ||
331 | |||
332 | static int snd_miro_put_preamp(struct snd_kcontrol *kcontrol, | ||
333 | struct snd_ctl_elem_value *ucontrol) | ||
334 | { | ||
335 | struct snd_miro *miro = snd_kcontrol_chip(kcontrol); | ||
336 | int error, value, change; | ||
337 | |||
338 | value = ucontrol->value.integer.value[0]; | ||
339 | |||
340 | if ((error = aci_setvalue(miro, ACI_SET_PREAMP, value)) < 0) { | ||
341 | snd_printk(KERN_ERR "snd_miro_put_preamp() failed: %d\n", error); | ||
342 | return error; | ||
343 | } | ||
344 | |||
345 | change = (value != miro->aci_preamp); | ||
346 | miro->aci_preamp = value; | ||
347 | |||
348 | return change; | ||
349 | } | ||
350 | |||
351 | static int snd_miro_info_amp(struct snd_kcontrol *kcontrol, | ||
352 | struct snd_ctl_elem_info *uinfo) | ||
353 | { | ||
354 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
355 | uinfo->count = 1; | ||
356 | |||
357 | return 0; | ||
358 | } | ||
359 | |||
360 | static int snd_miro_get_amp(struct snd_kcontrol *kcontrol, | ||
361 | struct snd_ctl_elem_value *ucontrol) | ||
362 | { | ||
363 | struct snd_miro *miro = snd_kcontrol_chip(kcontrol); | ||
364 | ucontrol->value.integer.value[0] = miro->aci_amp; | ||
365 | |||
366 | return 0; | ||
367 | } | ||
368 | |||
369 | static int snd_miro_put_amp(struct snd_kcontrol *kcontrol, | ||
370 | struct snd_ctl_elem_value *ucontrol) | ||
371 | { | ||
372 | struct snd_miro *miro = snd_kcontrol_chip(kcontrol); | ||
373 | int error, value, change; | ||
374 | |||
375 | value = ucontrol->value.integer.value[0]; | ||
376 | |||
377 | if ((error = aci_setvalue(miro, ACI_SET_POWERAMP, value)) < 0) { | ||
378 | snd_printk(KERN_ERR "snd_miro_put_amp() to %d failed: %d\n", value, error); | ||
379 | return error; | ||
380 | } | ||
381 | |||
382 | change = (value != miro->aci_amp); | ||
383 | miro->aci_amp = value; | ||
384 | |||
385 | return change; | ||
386 | } | ||
387 | |||
388 | #define MIRO_DOUBLE(ctl_name, ctl_index, get_right_reg, set_right_reg) \ | ||
389 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
390 | .name = ctl_name, \ | ||
391 | .index = ctl_index, \ | ||
392 | .info = snd_miro_info_double, \ | ||
393 | .get = snd_miro_get_double, \ | ||
394 | .put = snd_miro_put_double, \ | ||
395 | .private_value = get_right_reg | (set_right_reg << 8) \ | ||
396 | } | ||
397 | |||
398 | static int snd_miro_info_double(struct snd_kcontrol *kcontrol, | ||
399 | struct snd_ctl_elem_info *uinfo) | ||
400 | { | ||
401 | int reg = kcontrol->private_value & 0xff; | ||
402 | |||
403 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
404 | uinfo->count = 2; | ||
405 | |||
406 | if ((reg >= ACI_GET_EQ1) && (reg <= ACI_GET_EQ7)) { | ||
407 | |||
408 | /* equalizer elements */ | ||
409 | |||
410 | uinfo->value.integer.min = - 0x7f; | ||
411 | uinfo->value.integer.max = 0x7f; | ||
412 | } else { | ||
413 | |||
414 | /* non-equalizer elements */ | ||
415 | |||
416 | uinfo->value.integer.min = 0; | ||
417 | uinfo->value.integer.max = 0x20; | ||
418 | } | ||
419 | |||
420 | return 0; | ||
421 | } | ||
422 | |||
423 | static int snd_miro_get_double(struct snd_kcontrol *kcontrol, | ||
424 | struct snd_ctl_elem_value *uinfo) | ||
425 | { | ||
426 | struct snd_miro *miro = snd_kcontrol_chip(kcontrol); | ||
427 | int left_val, right_val; | ||
428 | |||
429 | int right_reg = kcontrol->private_value & 0xff; | ||
430 | int left_reg = right_reg + 1; | ||
431 | |||
432 | if ((right_val = aci_getvalue(miro, right_reg)) < 0) { | ||
433 | snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", right_reg, right_val); | ||
434 | return right_val; | ||
435 | } | ||
436 | |||
437 | if ((left_val = aci_getvalue(miro, left_reg)) < 0) { | ||
438 | snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", left_reg, left_val); | ||
439 | return left_val; | ||
440 | } | ||
441 | |||
442 | if ((right_reg >= ACI_GET_EQ1) && (right_reg <= ACI_GET_EQ7)) { | ||
443 | |||
444 | /* equalizer elements */ | ||
445 | |||
446 | if (left_val < 0x80) { | ||
447 | uinfo->value.integer.value[0] = left_val; | ||
448 | } else { | ||
449 | uinfo->value.integer.value[0] = 0x80 - left_val; | ||
450 | } | ||
451 | |||
452 | if (right_val < 0x80) { | ||
453 | uinfo->value.integer.value[1] = right_val; | ||
454 | } else { | ||
455 | uinfo->value.integer.value[1] = 0x80 - right_val; | ||
456 | } | ||
457 | |||
458 | } else { | ||
459 | |||
460 | /* non-equalizer elements */ | ||
461 | |||
462 | uinfo->value.integer.value[0] = 0x20 - left_val; | ||
463 | uinfo->value.integer.value[1] = 0x20 - right_val; | ||
464 | } | ||
465 | |||
466 | return 0; | ||
467 | } | ||
468 | |||
469 | static int snd_miro_put_double(struct snd_kcontrol *kcontrol, | ||
470 | struct snd_ctl_elem_value *ucontrol) | ||
471 | { | ||
472 | struct snd_miro *miro = snd_kcontrol_chip(kcontrol); | ||
473 | int left, right, left_old, right_old; | ||
474 | int setreg_left, setreg_right, getreg_left, getreg_right; | ||
475 | int change, error; | ||
476 | |||
477 | left = ucontrol->value.integer.value[0]; | ||
478 | right = ucontrol->value.integer.value[1]; | ||
479 | |||
480 | setreg_right = (kcontrol->private_value >> 8) & 0xff; | ||
481 | if (setreg_right == ACI_SET_MASTER) { | ||
482 | setreg_left = setreg_right + 1; | ||
483 | } else { | ||
484 | setreg_left = setreg_right + 8; | ||
485 | } | ||
486 | |||
487 | getreg_right = kcontrol->private_value & 0xff; | ||
488 | getreg_left = getreg_right + 1; | ||
489 | |||
490 | if ((left_old = aci_getvalue(miro, getreg_left)) < 0) { | ||
491 | snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", getreg_left, left_old); | ||
492 | return left_old; | ||
493 | } | ||
494 | |||
495 | if ((right_old = aci_getvalue(miro, getreg_right)) < 0) { | ||
496 | snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", getreg_right, right_old); | ||
497 | return right_old; | ||
498 | } | ||
499 | |||
500 | if ((getreg_right >= ACI_GET_EQ1) && (getreg_right <= ACI_GET_EQ7)) { | ||
501 | |||
502 | /* equalizer elements */ | ||
503 | |||
504 | if (left_old > 0x80) | ||
505 | left_old = 0x80 - left_old; | ||
506 | if (right_old > 0x80) | ||
507 | right_old = 0x80 - right_old; | ||
508 | |||
509 | if (left >= 0) { | ||
510 | if ((error = aci_setvalue(miro, setreg_left, left)) < 0) { | ||
511 | snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", | ||
512 | left, error); | ||
513 | return error; | ||
514 | } | ||
515 | } else { | ||
516 | if ((error = aci_setvalue(miro, setreg_left, 0x80 - left)) < 0) { | ||
517 | snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", | ||
518 | 0x80 - left, error); | ||
519 | return error; | ||
520 | } | ||
521 | } | ||
522 | |||
523 | if (right >= 0) { | ||
524 | if ((error = aci_setvalue(miro, setreg_right, right)) < 0) { | ||
525 | snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", | ||
526 | right, error); | ||
527 | return error; | ||
528 | } | ||
529 | } else { | ||
530 | if ((error = aci_setvalue(miro, setreg_right, 0x80 - right)) < 0) { | ||
531 | snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", | ||
532 | 0x80 - right, error); | ||
533 | return error; | ||
534 | } | ||
535 | } | ||
536 | |||
537 | } else { | ||
538 | |||
539 | /* non-equalizer elements */ | ||
540 | |||
541 | left_old = 0x20 - left_old; | ||
542 | right_old = 0x20 - right_old; | ||
543 | |||
544 | if ((error = aci_setvalue(miro, setreg_left, 0x20 - left)) < 0) { | ||
545 | snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", | ||
546 | 0x20 - left, error); | ||
547 | return error; | ||
548 | } | ||
549 | if ((error = aci_setvalue(miro, setreg_right, 0x20 - right)) < 0) { | ||
550 | snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", | ||
551 | 0x20 - right, error); | ||
552 | return error; | ||
553 | } | ||
554 | } | ||
555 | |||
556 | change = (left != left_old) || (right != right_old); | ||
557 | |||
558 | return change; | ||
559 | } | ||
560 | |||
561 | static struct snd_kcontrol_new snd_miro_controls[] = { | ||
562 | MIRO_DOUBLE("Master Playback Volume", 0, ACI_GET_MASTER, ACI_SET_MASTER), | ||
563 | MIRO_DOUBLE("Mic Playback Volume", 1, ACI_GET_MIC, ACI_SET_MIC), | ||
564 | MIRO_DOUBLE("Line Playback Volume", 1, ACI_GET_LINE, ACI_SET_LINE), | ||
565 | MIRO_DOUBLE("CD Playback Volume", 0, ACI_GET_CD, ACI_SET_CD), | ||
566 | MIRO_DOUBLE("Synth Playback Volume", 0, ACI_GET_SYNTH, ACI_SET_SYNTH), | ||
567 | MIRO_DOUBLE("PCM Playback Volume", 1, ACI_GET_PCM, ACI_SET_PCM), | ||
568 | MIRO_DOUBLE("Aux Playback Volume", 2, ACI_GET_LINE2, ACI_SET_LINE2), | ||
569 | }; | ||
570 | |||
571 | /* Equalizer with seven bands (only PCM20) | ||
572 | from -12dB up to +12dB on each band */ | ||
573 | static struct snd_kcontrol_new snd_miro_eq_controls[] = { | ||
574 | MIRO_DOUBLE("Tone Control - 28 Hz", 0, ACI_GET_EQ1, ACI_SET_EQ1), | ||
575 | MIRO_DOUBLE("Tone Control - 160 Hz", 0, ACI_GET_EQ2, ACI_SET_EQ2), | ||
576 | MIRO_DOUBLE("Tone Control - 400 Hz", 0, ACI_GET_EQ3, ACI_SET_EQ3), | ||
577 | MIRO_DOUBLE("Tone Control - 1 kHz", 0, ACI_GET_EQ4, ACI_SET_EQ4), | ||
578 | MIRO_DOUBLE("Tone Control - 2.5 kHz", 0, ACI_GET_EQ5, ACI_SET_EQ5), | ||
579 | MIRO_DOUBLE("Tone Control - 6.3 kHz", 0, ACI_GET_EQ6, ACI_SET_EQ6), | ||
580 | MIRO_DOUBLE("Tone Control - 16 kHz", 0, ACI_GET_EQ7, ACI_SET_EQ7), | ||
581 | }; | ||
582 | |||
583 | static struct snd_kcontrol_new snd_miro_radio_control[] = { | ||
584 | MIRO_DOUBLE("Radio Playback Volume", 0, ACI_GET_LINE1, ACI_SET_LINE1), | ||
585 | }; | ||
586 | |||
587 | static struct snd_kcontrol_new snd_miro_line_control[] = { | ||
588 | MIRO_DOUBLE("Line Playback Volume", 2, ACI_GET_LINE1, ACI_SET_LINE1), | ||
589 | }; | ||
590 | |||
591 | static struct snd_kcontrol_new snd_miro_preamp_control[] = { | ||
592 | { | ||
593 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
594 | .name = "Mic Boost", | ||
595 | .index = 1, | ||
596 | .info = snd_miro_info_preamp, | ||
597 | .get = snd_miro_get_preamp, | ||
598 | .put = snd_miro_put_preamp, | ||
599 | }}; | ||
600 | |||
601 | static struct snd_kcontrol_new snd_miro_amp_control[] = { | ||
602 | { | ||
603 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
604 | .name = "Line Boost", | ||
605 | .index = 0, | ||
606 | .info = snd_miro_info_amp, | ||
607 | .get = snd_miro_get_amp, | ||
608 | .put = snd_miro_put_amp, | ||
609 | }}; | ||
610 | |||
611 | static struct snd_kcontrol_new snd_miro_capture_control[] = { | ||
612 | { | ||
613 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
614 | .name = "PCM Capture Switch", | ||
615 | .index = 0, | ||
616 | .info = snd_miro_info_capture, | ||
617 | .get = snd_miro_get_capture, | ||
618 | .put = snd_miro_put_capture, | ||
619 | }}; | ||
620 | |||
621 | static unsigned char aci_init_values[][2] __initdata = { | ||
622 | { ACI_SET_MUTE, 0x00 }, | ||
623 | { ACI_SET_POWERAMP, 0x00 }, | ||
624 | { ACI_SET_PREAMP, 0x00 }, | ||
625 | { ACI_SET_SOLOMODE, 0x00 }, | ||
626 | { ACI_SET_MIC + 0, 0x20 }, | ||
627 | { ACI_SET_MIC + 8, 0x20 }, | ||
628 | { ACI_SET_LINE + 0, 0x20 }, | ||
629 | { ACI_SET_LINE + 8, 0x20 }, | ||
630 | { ACI_SET_CD + 0, 0x20 }, | ||
631 | { ACI_SET_CD + 8, 0x20 }, | ||
632 | { ACI_SET_PCM + 0, 0x20 }, | ||
633 | { ACI_SET_PCM + 8, 0x20 }, | ||
634 | { ACI_SET_LINE1 + 0, 0x20 }, | ||
635 | { ACI_SET_LINE1 + 8, 0x20 }, | ||
636 | { ACI_SET_LINE2 + 0, 0x20 }, | ||
637 | { ACI_SET_LINE2 + 8, 0x20 }, | ||
638 | { ACI_SET_SYNTH + 0, 0x20 }, | ||
639 | { ACI_SET_SYNTH + 8, 0x20 }, | ||
640 | { ACI_SET_MASTER + 0, 0x20 }, | ||
641 | { ACI_SET_MASTER + 1, 0x20 }, | ||
642 | }; | ||
643 | |||
644 | static int __init snd_set_aci_init_values(struct snd_miro *miro) | ||
645 | { | ||
646 | int idx, error; | ||
647 | |||
648 | /* enable WSS on PCM1 */ | ||
649 | |||
650 | if ((miro->aci_product == 'A') && wss) { | ||
651 | if ((error = aci_setvalue(miro, ACI_SET_WSS, wss)) < 0) { | ||
652 | snd_printk(KERN_ERR "enabling WSS mode failed\n"); | ||
653 | return error; | ||
654 | } | ||
655 | } | ||
656 | |||
657 | /* enable IDE port */ | ||
658 | |||
659 | if (ide) { | ||
660 | if ((error = aci_setvalue(miro, ACI_SET_IDE, ide)) < 0) { | ||
661 | snd_printk(KERN_ERR "enabling IDE port failed\n"); | ||
662 | return error; | ||
663 | } | ||
664 | } | ||
665 | |||
666 | /* set common aci values */ | ||
667 | |||
668 | for (idx = 0; idx < ARRAY_SIZE(aci_init_values); idx++) | ||
669 | if ((error = aci_setvalue(miro, aci_init_values[idx][0], | ||
670 | aci_init_values[idx][1])) < 0) { | ||
671 | snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", | ||
672 | aci_init_values[idx][0], error); | ||
673 | return error; | ||
674 | } | ||
675 | |||
676 | miro->aci_amp = 0; | ||
677 | miro->aci_preamp = 0; | ||
678 | miro->aci_solomode = 1; | ||
679 | |||
680 | return 0; | ||
681 | } | ||
682 | |||
683 | static int snd_miro_mixer(struct snd_miro *miro) | ||
684 | { | ||
685 | struct snd_card *card; | ||
686 | unsigned int idx; | ||
687 | int err; | ||
688 | |||
689 | snd_assert(miro != NULL && miro->card != NULL, return -EINVAL); | ||
690 | |||
691 | card = miro->card; | ||
692 | |||
693 | switch (miro->hardware) { | ||
694 | case OPTi9XX_HW_82C924: | ||
695 | strcpy(card->mixername, "ACI & OPTi924"); | ||
696 | break; | ||
697 | case OPTi9XX_HW_82C929: | ||
698 | strcpy(card->mixername, "ACI & OPTi929"); | ||
699 | break; | ||
700 | default: | ||
701 | snd_BUG(); | ||
702 | break; | ||
703 | } | ||
704 | |||
705 | for (idx = 0; idx < ARRAY_SIZE(snd_miro_controls); idx++) { | ||
706 | if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_controls[idx], miro))) < 0) | ||
707 | return err; | ||
708 | } | ||
709 | |||
710 | if ((miro->aci_product == 'A') || (miro->aci_product == 'B')) { | ||
711 | /* PCM1/PCM12 with power-amp and Line 2 */ | ||
712 | if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_line_control[0], miro))) < 0) | ||
713 | return err; | ||
714 | if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_amp_control[0], miro))) < 0) | ||
715 | return err; | ||
716 | } | ||
717 | |||
718 | if ((miro->aci_product == 'B') || (miro->aci_product == 'C')) { | ||
719 | /* PCM12/PCM20 with mic-preamp */ | ||
720 | if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_preamp_control[0], miro))) < 0) | ||
721 | return err; | ||
722 | if (miro->aci_version >= 176) | ||
723 | if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_capture_control[0], miro))) < 0) | ||
724 | return err; | ||
725 | } | ||
726 | |||
727 | if (miro->aci_product == 'C') { | ||
728 | /* PCM20 with radio and 7 band equalizer */ | ||
729 | if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_radio_control[0], miro))) < 0) | ||
730 | return err; | ||
731 | for (idx = 0; idx < ARRAY_SIZE(snd_miro_eq_controls); idx++) { | ||
732 | if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_eq_controls[idx], miro))) < 0) | ||
733 | return err; | ||
734 | } | ||
735 | } | ||
736 | |||
737 | return 0; | ||
738 | } | ||
739 | |||
740 | static long snd_legacy_find_free_ioport(long *port_table, long size) | ||
741 | { | ||
742 | while (*port_table != -1) { | ||
743 | struct resource *res; | ||
744 | if ((res = request_region(*port_table, size, | ||
745 | "ALSA test")) != NULL) { | ||
746 | release_and_free_resource(res); | ||
747 | return *port_table; | ||
748 | } | ||
749 | port_table++; | ||
750 | } | ||
751 | return -1; | ||
752 | } | ||
753 | |||
754 | static int __init snd_miro_init(struct snd_miro *chip, unsigned short hardware) | ||
755 | { | ||
756 | static int opti9xx_mc_size[] = {7, 7, 10, 10, 2, 2, 2}; | ||
757 | |||
758 | chip->hardware = hardware; | ||
759 | strcpy(chip->name, snd_opti9xx_names[hardware]); | ||
760 | |||
761 | chip->mc_base_size = opti9xx_mc_size[hardware]; | ||
762 | |||
763 | spin_lock_init(&chip->lock); | ||
764 | |||
765 | chip->wss_base = -1; | ||
766 | chip->irq = -1; | ||
767 | chip->dma1 = -1; | ||
768 | chip->dma2 = -1; | ||
769 | chip->fm_port = -1; | ||
770 | chip->mpu_port = -1; | ||
771 | chip->mpu_irq = -1; | ||
772 | |||
773 | switch (hardware) { | ||
774 | case OPTi9XX_HW_82C929: | ||
775 | chip->mc_base = 0xf8c; | ||
776 | chip->password = 0xe3; | ||
777 | chip->pwd_reg = 3; | ||
778 | break; | ||
779 | |||
780 | case OPTi9XX_HW_82C924: | ||
781 | chip->mc_base = 0xf8c; | ||
782 | chip->password = 0xe5; | ||
783 | chip->pwd_reg = 3; | ||
784 | break; | ||
785 | |||
786 | default: | ||
787 | snd_printk(KERN_ERR "sorry, no support for %d\n", hardware); | ||
788 | return -ENODEV; | ||
789 | } | ||
790 | |||
791 | return 0; | ||
792 | } | ||
793 | |||
794 | static unsigned char snd_miro_read(struct snd_miro *chip, | ||
795 | unsigned char reg) | ||
796 | { | ||
797 | unsigned long flags; | ||
798 | unsigned char retval = 0xff; | ||
799 | |||
800 | spin_lock_irqsave(&chip->lock, flags); | ||
801 | outb(chip->password, chip->mc_base + chip->pwd_reg); | ||
802 | |||
803 | switch (chip->hardware) { | ||
804 | case OPTi9XX_HW_82C924: | ||
805 | if (reg > 7) { | ||
806 | outb(reg, chip->mc_base + 8); | ||
807 | outb(chip->password, chip->mc_base + chip->pwd_reg); | ||
808 | retval = inb(chip->mc_base + 9); | ||
809 | break; | ||
810 | } | ||
811 | |||
812 | case OPTi9XX_HW_82C929: | ||
813 | retval = inb(chip->mc_base + reg); | ||
814 | break; | ||
815 | |||
816 | default: | ||
817 | snd_printk(KERN_ERR "sorry, no support for %d\n", chip->hardware); | ||
818 | } | ||
819 | |||
820 | spin_unlock_irqrestore(&chip->lock, flags); | ||
821 | return retval; | ||
822 | } | ||
823 | |||
824 | static void snd_miro_write(struct snd_miro *chip, unsigned char reg, | ||
825 | unsigned char value) | ||
826 | { | ||
827 | unsigned long flags; | ||
828 | |||
829 | spin_lock_irqsave(&chip->lock, flags); | ||
830 | outb(chip->password, chip->mc_base + chip->pwd_reg); | ||
831 | |||
832 | switch (chip->hardware) { | ||
833 | case OPTi9XX_HW_82C924: | ||
834 | if (reg > 7) { | ||
835 | outb(reg, chip->mc_base + 8); | ||
836 | outb(chip->password, chip->mc_base + chip->pwd_reg); | ||
837 | outb(value, chip->mc_base + 9); | ||
838 | break; | ||
839 | } | ||
840 | |||
841 | case OPTi9XX_HW_82C929: | ||
842 | outb(value, chip->mc_base + reg); | ||
843 | break; | ||
844 | |||
845 | default: | ||
846 | snd_printk(KERN_ERR "sorry, no support for %d\n", chip->hardware); | ||
847 | } | ||
848 | |||
849 | spin_unlock_irqrestore(&chip->lock, flags); | ||
850 | } | ||
851 | |||
852 | |||
853 | #define snd_miro_write_mask(chip, reg, value, mask) \ | ||
854 | snd_miro_write(chip, reg, \ | ||
855 | (snd_miro_read(chip, reg) & ~(mask)) | ((value) & (mask))) | ||
856 | |||
857 | /* | ||
858 | * Proc Interface | ||
859 | */ | ||
860 | |||
861 | static void snd_miro_proc_read(struct snd_info_entry * entry, | ||
862 | struct snd_info_buffer *buffer) | ||
863 | { | ||
864 | struct snd_miro *miro = (struct snd_miro *) entry->private_data; | ||
865 | char* model = "unknown"; | ||
866 | |||
867 | /* miroSOUND PCM1 pro, early PCM12 */ | ||
868 | |||
869 | if ((miro->hardware == OPTi9XX_HW_82C929) && | ||
870 | (miro->aci_vendor == 'm') && | ||
871 | (miro->aci_product == 'A')) { | ||
872 | switch(miro->aci_version) { | ||
873 | case 3: | ||
874 | model = "miroSOUND PCM1 pro"; | ||
875 | break; | ||
876 | default: | ||
877 | model = "miroSOUND PCM1 pro / (early) PCM12"; | ||
878 | break; | ||
879 | } | ||
880 | } | ||
881 | |||
882 | /* miroSOUND PCM12, PCM12 (Rev. E), PCM12 pnp */ | ||
883 | |||
884 | if ((miro->hardware == OPTi9XX_HW_82C924) && | ||
885 | (miro->aci_vendor == 'm') && | ||
886 | (miro->aci_product == 'B')) { | ||
887 | switch(miro->aci_version) { | ||
888 | case 4: | ||
889 | model = "miroSOUND PCM12"; | ||
890 | break; | ||
891 | case 176: | ||
892 | model = "miroSOUND PCM12 (Rev. E)"; | ||
893 | break; | ||
894 | default: | ||
895 | model = "miroSOUND PCM12 / PCM12 pnp"; | ||
896 | break; | ||
897 | } | ||
898 | } | ||
899 | |||
900 | /* miroSOUND PCM20 radio */ | ||
901 | |||
902 | if ((miro->hardware == OPTi9XX_HW_82C924) && | ||
903 | (miro->aci_vendor == 'm') && | ||
904 | (miro->aci_product == 'C')) { | ||
905 | switch(miro->aci_version) { | ||
906 | case 7: | ||
907 | model = "miroSOUND PCM20 radio (Rev. E)"; | ||
908 | break; | ||
909 | default: | ||
910 | model = "miroSOUND PCM20 radio"; | ||
911 | break; | ||
912 | } | ||
913 | } | ||
914 | |||
915 | snd_iprintf(buffer, "\nGeneral information:\n"); | ||
916 | snd_iprintf(buffer, " model : %s\n", model); | ||
917 | snd_iprintf(buffer, " opti : %s\n", miro->name); | ||
918 | snd_iprintf(buffer, " codec : %s\n", miro->pcm->name); | ||
919 | snd_iprintf(buffer, " port : 0x%lx\n", miro->wss_base); | ||
920 | snd_iprintf(buffer, " irq : %d\n", miro->irq); | ||
921 | snd_iprintf(buffer, " dma : %d,%d\n\n", miro->dma1, miro->dma2); | ||
922 | |||
923 | snd_iprintf(buffer, "MPU-401:\n"); | ||
924 | snd_iprintf(buffer, " port : 0x%lx\n", miro->mpu_port); | ||
925 | snd_iprintf(buffer, " irq : %d\n\n", miro->mpu_irq); | ||
926 | |||
927 | snd_iprintf(buffer, "ACI information:\n"); | ||
928 | snd_iprintf(buffer, " vendor : "); | ||
929 | switch(miro->aci_vendor) { | ||
930 | case 'm': | ||
931 | snd_iprintf(buffer, "Miro\n"); | ||
932 | break; | ||
933 | default: | ||
934 | snd_iprintf(buffer, "unknown (0x%x)\n", miro->aci_vendor); | ||
935 | break; | ||
936 | } | ||
937 | |||
938 | snd_iprintf(buffer, " product : "); | ||
939 | switch(miro->aci_product) { | ||
940 | case 'A': | ||
941 | snd_iprintf(buffer, "miroSOUND PCM1 pro / (early) PCM12\n"); | ||
942 | break; | ||
943 | case 'B': | ||
944 | snd_iprintf(buffer, "miroSOUND PCM12\n"); | ||
945 | break; | ||
946 | case 'C': | ||
947 | snd_iprintf(buffer, "miroSOUND PCM20 radio\n"); | ||
948 | break; | ||
949 | default: | ||
950 | snd_iprintf(buffer, "unknown (0x%x)\n", miro->aci_product); | ||
951 | break; | ||
952 | } | ||
953 | |||
954 | snd_iprintf(buffer, " firmware: %d (0x%x)\n", | ||
955 | miro->aci_version, miro->aci_version); | ||
956 | snd_iprintf(buffer, " port : 0x%lx-0x%lx\n", | ||
957 | miro->aci_port, miro->aci_port+2); | ||
958 | snd_iprintf(buffer, " wss : 0x%x\n", wss); | ||
959 | snd_iprintf(buffer, " ide : 0x%x\n", ide); | ||
960 | snd_iprintf(buffer, " solomode: 0x%x\n", miro->aci_solomode); | ||
961 | snd_iprintf(buffer, " amp : 0x%x\n", miro->aci_amp); | ||
962 | snd_iprintf(buffer, " preamp : 0x%x\n", miro->aci_preamp); | ||
963 | } | ||
964 | |||
965 | static void __init snd_miro_proc_init(struct snd_miro * miro) | ||
966 | { | ||
967 | struct snd_info_entry *entry; | ||
968 | |||
969 | if (! snd_card_proc_new(miro->card, "miro", &entry)) | ||
970 | snd_info_set_text_ops(entry, miro, 1024, snd_miro_proc_read); | ||
971 | } | ||
972 | |||
973 | /* | ||
974 | * Init | ||
975 | */ | ||
976 | |||
977 | static int __init snd_miro_configure(struct snd_miro *chip) | ||
978 | { | ||
979 | unsigned char wss_base_bits; | ||
980 | unsigned char irq_bits; | ||
981 | unsigned char dma_bits; | ||
982 | unsigned char mpu_port_bits = 0; | ||
983 | unsigned char mpu_irq_bits; | ||
984 | unsigned long flags; | ||
985 | |||
986 | switch (chip->hardware) { | ||
987 | case OPTi9XX_HW_82C924: | ||
988 | snd_miro_write_mask(chip, OPTi9XX_MC_REG(6), 0x02, 0x02); | ||
989 | snd_miro_write_mask(chip, OPTi9XX_MC_REG(1), 0x80, 0x80); | ||
990 | snd_miro_write_mask(chip, OPTi9XX_MC_REG(2), 0x20, 0x20); /* OPL4 */ | ||
991 | snd_miro_write_mask(chip, OPTi9XX_MC_REG(3), 0xf0, 0xff); | ||
992 | snd_miro_write_mask(chip, OPTi9XX_MC_REG(5), 0x02, 0x02); | ||
993 | break; | ||
994 | case OPTi9XX_HW_82C929: | ||
995 | /* untested init commands for OPTi929 */ | ||
996 | snd_miro_write_mask(chip, OPTi9XX_MC_REG(1), 0x80, 0x80); | ||
997 | snd_miro_write_mask(chip, OPTi9XX_MC_REG(2), 0x20, 0x20); /* OPL4 */ | ||
998 | snd_miro_write_mask(chip, OPTi9XX_MC_REG(4), 0x00, 0x0c); | ||
999 | snd_miro_write_mask(chip, OPTi9XX_MC_REG(5), 0x02, 0x02); | ||
1000 | break; | ||
1001 | default: | ||
1002 | snd_printk(KERN_ERR "chip %d not supported\n", chip->hardware); | ||
1003 | return -EINVAL; | ||
1004 | } | ||
1005 | |||
1006 | switch (chip->wss_base) { | ||
1007 | case 0x530: | ||
1008 | wss_base_bits = 0x00; | ||
1009 | break; | ||
1010 | case 0x604: | ||
1011 | wss_base_bits = 0x03; | ||
1012 | break; | ||
1013 | case 0xe80: | ||
1014 | wss_base_bits = 0x01; | ||
1015 | break; | ||
1016 | case 0xf40: | ||
1017 | wss_base_bits = 0x02; | ||
1018 | break; | ||
1019 | default: | ||
1020 | snd_printk(KERN_ERR "WSS port 0x%lx not valid\n", chip->wss_base); | ||
1021 | goto __skip_base; | ||
1022 | } | ||
1023 | snd_miro_write_mask(chip, OPTi9XX_MC_REG(1), wss_base_bits << 4, 0x30); | ||
1024 | |||
1025 | __skip_base: | ||
1026 | switch (chip->irq) { | ||
1027 | case 5: | ||
1028 | irq_bits = 0x05; | ||
1029 | break; | ||
1030 | case 7: | ||
1031 | irq_bits = 0x01; | ||
1032 | break; | ||
1033 | case 9: | ||
1034 | irq_bits = 0x02; | ||
1035 | break; | ||
1036 | case 10: | ||
1037 | irq_bits = 0x03; | ||
1038 | break; | ||
1039 | case 11: | ||
1040 | irq_bits = 0x04; | ||
1041 | break; | ||
1042 | default: | ||
1043 | snd_printk(KERN_ERR "WSS irq # %d not valid\n", chip->irq); | ||
1044 | goto __skip_resources; | ||
1045 | } | ||
1046 | |||
1047 | switch (chip->dma1) { | ||
1048 | case 0: | ||
1049 | dma_bits = 0x01; | ||
1050 | break; | ||
1051 | case 1: | ||
1052 | dma_bits = 0x02; | ||
1053 | break; | ||
1054 | case 3: | ||
1055 | dma_bits = 0x03; | ||
1056 | break; | ||
1057 | default: | ||
1058 | snd_printk(KERN_ERR "WSS dma1 # %d not valid\n", chip->dma1); | ||
1059 | goto __skip_resources; | ||
1060 | } | ||
1061 | |||
1062 | if (chip->dma1 == chip->dma2) { | ||
1063 | snd_printk(KERN_ERR "don't want to share dmas\n"); | ||
1064 | return -EBUSY; | ||
1065 | } | ||
1066 | |||
1067 | switch (chip->dma2) { | ||
1068 | case 0: | ||
1069 | case 1: | ||
1070 | break; | ||
1071 | default: | ||
1072 | snd_printk(KERN_ERR "WSS dma2 # %d not valid\n", chip->dma2); | ||
1073 | goto __skip_resources; | ||
1074 | } | ||
1075 | dma_bits |= 0x04; | ||
1076 | |||
1077 | spin_lock_irqsave(&chip->lock, flags); | ||
1078 | outb(irq_bits << 3 | dma_bits, chip->wss_base); | ||
1079 | spin_unlock_irqrestore(&chip->lock, flags); | ||
1080 | |||
1081 | __skip_resources: | ||
1082 | if (chip->hardware > OPTi9XX_HW_82C928) { | ||
1083 | switch (chip->mpu_port) { | ||
1084 | case 0: | ||
1085 | case -1: | ||
1086 | break; | ||
1087 | case 0x300: | ||
1088 | mpu_port_bits = 0x03; | ||
1089 | break; | ||
1090 | case 0x310: | ||
1091 | mpu_port_bits = 0x02; | ||
1092 | break; | ||
1093 | case 0x320: | ||
1094 | mpu_port_bits = 0x01; | ||
1095 | break; | ||
1096 | case 0x330: | ||
1097 | mpu_port_bits = 0x00; | ||
1098 | break; | ||
1099 | default: | ||
1100 | snd_printk(KERN_ERR "MPU-401 port 0x%lx not valid\n", | ||
1101 | chip->mpu_port); | ||
1102 | goto __skip_mpu; | ||
1103 | } | ||
1104 | |||
1105 | switch (chip->mpu_irq) { | ||
1106 | case 5: | ||
1107 | mpu_irq_bits = 0x02; | ||
1108 | break; | ||
1109 | case 7: | ||
1110 | mpu_irq_bits = 0x03; | ||
1111 | break; | ||
1112 | case 9: | ||
1113 | mpu_irq_bits = 0x00; | ||
1114 | break; | ||
1115 | case 10: | ||
1116 | mpu_irq_bits = 0x01; | ||
1117 | break; | ||
1118 | default: | ||
1119 | snd_printk(KERN_ERR "MPU-401 irq # %d not valid\n", | ||
1120 | chip->mpu_irq); | ||
1121 | goto __skip_mpu; | ||
1122 | } | ||
1123 | |||
1124 | snd_miro_write_mask(chip, OPTi9XX_MC_REG(6), | ||
1125 | (chip->mpu_port <= 0) ? 0x00 : | ||
1126 | 0x80 | mpu_port_bits << 5 | mpu_irq_bits << 3, | ||
1127 | 0xf8); | ||
1128 | } | ||
1129 | __skip_mpu: | ||
1130 | |||
1131 | return 0; | ||
1132 | } | ||
1133 | |||
1134 | static int __init snd_card_miro_detect(struct snd_card *card, struct snd_miro *chip) | ||
1135 | { | ||
1136 | int i, err; | ||
1137 | unsigned char value; | ||
1138 | |||
1139 | for (i = OPTi9XX_HW_82C929; i <= OPTi9XX_HW_82C924; i++) { | ||
1140 | |||
1141 | if ((err = snd_miro_init(chip, i)) < 0) | ||
1142 | return err; | ||
1143 | |||
1144 | if ((chip->res_mc_base = request_region(chip->mc_base, chip->mc_base_size, "OPTi9xx MC")) == NULL) | ||
1145 | continue; | ||
1146 | |||
1147 | value = snd_miro_read(chip, OPTi9XX_MC_REG(1)); | ||
1148 | if ((value != 0xff) && (value != inb(chip->mc_base + 1))) | ||
1149 | if (value == snd_miro_read(chip, OPTi9XX_MC_REG(1))) | ||
1150 | return 1; | ||
1151 | |||
1152 | release_and_free_resource(chip->res_mc_base); | ||
1153 | chip->res_mc_base = NULL; | ||
1154 | |||
1155 | } | ||
1156 | |||
1157 | return -ENODEV; | ||
1158 | } | ||
1159 | |||
1160 | static int __init snd_card_miro_aci_detect(struct snd_card *card, struct snd_miro * miro) | ||
1161 | { | ||
1162 | unsigned char regval; | ||
1163 | int i; | ||
1164 | |||
1165 | mutex_init(&miro->aci_mutex); | ||
1166 | |||
1167 | /* get ACI port from OPTi9xx MC 4 */ | ||
1168 | |||
1169 | miro->mc_base = 0xf8c; | ||
1170 | regval=inb(miro->mc_base + 4); | ||
1171 | miro->aci_port = (regval & 0x10) ? 0x344: 0x354; | ||
1172 | |||
1173 | if ((miro->res_aci_port = request_region(miro->aci_port, 3, "miro aci")) == NULL) { | ||
1174 | snd_printk(KERN_ERR "aci i/o area 0x%lx-0x%lx already used.\n", | ||
1175 | miro->aci_port, miro->aci_port+2); | ||
1176 | return -ENOMEM; | ||
1177 | } | ||
1178 | |||
1179 | /* force ACI into a known state */ | ||
1180 | for (i = 0; i < 3; i++) | ||
1181 | if (aci_cmd(miro, ACI_ERROR_OP, -1, -1) < 0) { | ||
1182 | snd_card_free(card); | ||
1183 | snd_printk(KERN_ERR "can't force aci into known state.\n"); | ||
1184 | return -ENXIO; | ||
1185 | } | ||
1186 | |||
1187 | if ((miro->aci_vendor=aci_cmd(miro, ACI_READ_IDCODE, -1, -1)) < 0 || | ||
1188 | (miro->aci_product=aci_cmd(miro, ACI_READ_IDCODE, -1, -1)) < 0) { | ||
1189 | snd_card_free(card); | ||
1190 | snd_printk(KERN_ERR "can't read aci id on 0x%lx.\n", miro->aci_port); | ||
1191 | return -ENXIO; | ||
1192 | } | ||
1193 | |||
1194 | if ((miro->aci_version=aci_cmd(miro, ACI_READ_VERSION, -1, -1)) < 0) { | ||
1195 | snd_card_free(card); | ||
1196 | snd_printk(KERN_ERR "can't read aci version on 0x%lx.\n", | ||
1197 | miro->aci_port); | ||
1198 | return -ENXIO; | ||
1199 | } | ||
1200 | |||
1201 | if (aci_cmd(miro, ACI_INIT, -1, -1) < 0 || | ||
1202 | aci_cmd(miro, ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP) < 0 || | ||
1203 | aci_cmd(miro, ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP) < 0) { | ||
1204 | snd_printk(KERN_ERR "can't initialize aci.\n"); | ||
1205 | return -ENXIO; | ||
1206 | } | ||
1207 | |||
1208 | return 0; | ||
1209 | } | ||
1210 | |||
1211 | static void snd_card_miro_free(struct snd_card *card) | ||
1212 | { | ||
1213 | struct snd_miro *miro = card->private_data; | ||
1214 | |||
1215 | release_and_free_resource(miro->res_aci_port); | ||
1216 | release_and_free_resource(miro->res_mc_base); | ||
1217 | } | ||
1218 | |||
1219 | static int __init snd_miro_probe(struct platform_device *devptr) | ||
1220 | { | ||
1221 | static long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1}; | ||
1222 | static long possible_mpu_ports[] = {0x330, 0x300, 0x310, 0x320, -1}; | ||
1223 | static int possible_irqs[] = {11, 9, 10, 7, -1}; | ||
1224 | static int possible_mpu_irqs[] = {10, 5, 9, 7, -1}; | ||
1225 | static int possible_dma1s[] = {3, 1, 0, -1}; | ||
1226 | static int possible_dma2s[][2] = {{1,-1}, {0,-1}, {-1,-1}, {0,-1}}; | ||
1227 | |||
1228 | int error; | ||
1229 | struct snd_miro *miro; | ||
1230 | struct snd_cs4231 *codec; | ||
1231 | struct snd_timer *timer; | ||
1232 | struct snd_card *card; | ||
1233 | struct snd_pcm *pcm; | ||
1234 | struct snd_rawmidi *rmidi; | ||
1235 | |||
1236 | if (!(card = snd_card_new(index, id, THIS_MODULE, | ||
1237 | sizeof(struct snd_miro)))) | ||
1238 | return -ENOMEM; | ||
1239 | |||
1240 | card->private_free = snd_card_miro_free; | ||
1241 | miro = card->private_data; | ||
1242 | miro->card = card; | ||
1243 | |||
1244 | if ((error = snd_card_miro_aci_detect(card, miro)) < 0) { | ||
1245 | snd_card_free(card); | ||
1246 | snd_printk(KERN_ERR "unable to detect aci chip\n"); | ||
1247 | return -ENODEV; | ||
1248 | } | ||
1249 | |||
1250 | /* init proc interface */ | ||
1251 | snd_miro_proc_init(miro); | ||
1252 | |||
1253 | if ((error = snd_card_miro_detect(card, miro)) < 0) { | ||
1254 | snd_card_free(card); | ||
1255 | snd_printk(KERN_ERR "unable to detect OPTi9xx chip\n"); | ||
1256 | return -ENODEV; | ||
1257 | } | ||
1258 | |||
1259 | if (! miro->res_mc_base && | ||
1260 | (miro->res_mc_base = request_region(miro->mc_base, miro->mc_base_size, | ||
1261 | "miro (OPTi9xx MC)")) == NULL) { | ||
1262 | snd_card_free(card); | ||
1263 | snd_printk(KERN_ERR "request for OPTI9xx MC failed\n"); | ||
1264 | return -ENOMEM; | ||
1265 | } | ||
1266 | |||
1267 | miro->wss_base = port; | ||
1268 | miro->fm_port = fm_port; | ||
1269 | miro->mpu_port = mpu_port; | ||
1270 | miro->irq = irq; | ||
1271 | miro->mpu_irq = mpu_irq; | ||
1272 | miro->dma1 = dma1; | ||
1273 | miro->dma2 = dma2; | ||
1274 | |||
1275 | if (miro->wss_base == SNDRV_AUTO_PORT) { | ||
1276 | if ((miro->wss_base = snd_legacy_find_free_ioport(possible_ports, 4)) < 0) { | ||
1277 | snd_card_free(card); | ||
1278 | snd_printk(KERN_ERR "unable to find a free WSS port\n"); | ||
1279 | return -EBUSY; | ||
1280 | } | ||
1281 | } | ||
1282 | |||
1283 | if (miro->mpu_port == SNDRV_AUTO_PORT) { | ||
1284 | if ((miro->mpu_port = snd_legacy_find_free_ioport(possible_mpu_ports, 2)) < 0) { | ||
1285 | snd_card_free(card); | ||
1286 | snd_printk(KERN_ERR "unable to find a free MPU401 port\n"); | ||
1287 | return -EBUSY; | ||
1288 | } | ||
1289 | } | ||
1290 | if (miro->irq == SNDRV_AUTO_IRQ) { | ||
1291 | if ((miro->irq = snd_legacy_find_free_irq(possible_irqs)) < 0) { | ||
1292 | snd_card_free(card); | ||
1293 | snd_printk(KERN_ERR "unable to find a free IRQ\n"); | ||
1294 | return -EBUSY; | ||
1295 | } | ||
1296 | } | ||
1297 | if (miro->mpu_irq == SNDRV_AUTO_IRQ) { | ||
1298 | if ((miro->mpu_irq = snd_legacy_find_free_irq(possible_mpu_irqs)) < 0) { | ||
1299 | snd_card_free(card); | ||
1300 | snd_printk(KERN_ERR "unable to find a free MPU401 IRQ\n"); | ||
1301 | return -EBUSY; | ||
1302 | } | ||
1303 | } | ||
1304 | if (miro->dma1 == SNDRV_AUTO_DMA) { | ||
1305 | if ((miro->dma1 = snd_legacy_find_free_dma(possible_dma1s)) < 0) { | ||
1306 | snd_card_free(card); | ||
1307 | snd_printk(KERN_ERR "unable to find a free DMA1\n"); | ||
1308 | return -EBUSY; | ||
1309 | } | ||
1310 | } | ||
1311 | if (miro->dma2 == SNDRV_AUTO_DMA) { | ||
1312 | if ((miro->dma2 = snd_legacy_find_free_dma(possible_dma2s[miro->dma1 % 4])) < 0) { | ||
1313 | snd_card_free(card); | ||
1314 | snd_printk(KERN_ERR "unable to find a free DMA2\n"); | ||
1315 | return -EBUSY; | ||
1316 | } | ||
1317 | } | ||
1318 | |||
1319 | if ((error = snd_miro_configure(miro))) { | ||
1320 | snd_card_free(card); | ||
1321 | return error; | ||
1322 | } | ||
1323 | |||
1324 | if ((error = snd_cs4231_create(card, miro->wss_base + 4, -1, | ||
1325 | miro->irq, miro->dma1, miro->dma2, | ||
1326 | CS4231_HW_AD1845, | ||
1327 | 0, | ||
1328 | &codec)) < 0) { | ||
1329 | snd_card_free(card); | ||
1330 | return error; | ||
1331 | } | ||
1332 | |||
1333 | if ((error = snd_cs4231_pcm(codec, 0, &pcm)) < 0) { | ||
1334 | snd_card_free(card); | ||
1335 | return error; | ||
1336 | } | ||
1337 | if ((error = snd_cs4231_mixer(codec)) < 0) { | ||
1338 | snd_card_free(card); | ||
1339 | return error; | ||
1340 | } | ||
1341 | if ((error = snd_cs4231_timer(codec, 0, &timer)) < 0) { | ||
1342 | snd_card_free(card); | ||
1343 | return error; | ||
1344 | } | ||
1345 | |||
1346 | miro->pcm = pcm; | ||
1347 | |||
1348 | if ((error = snd_miro_mixer(miro)) < 0) { | ||
1349 | snd_card_free(card); | ||
1350 | return error; | ||
1351 | } | ||
1352 | |||
1353 | if (miro->aci_vendor == 'm') { | ||
1354 | /* It looks like a miro sound card. */ | ||
1355 | switch (miro->aci_product) { | ||
1356 | case 'A': | ||
1357 | sprintf(card->shortname, | ||
1358 | "miroSOUND PCM1 pro / PCM12"); | ||
1359 | break; | ||
1360 | case 'B': | ||
1361 | sprintf(card->shortname, | ||
1362 | "miroSOUND PCM12"); | ||
1363 | break; | ||
1364 | case 'C': | ||
1365 | sprintf(card->shortname, | ||
1366 | "miroSOUND PCM20 radio"); | ||
1367 | break; | ||
1368 | default: | ||
1369 | sprintf(card->shortname, | ||
1370 | "unknown miro"); | ||
1371 | snd_printk(KERN_INFO "unknown miro aci id\n"); | ||
1372 | break; | ||
1373 | } | ||
1374 | } else { | ||
1375 | snd_printk(KERN_INFO "found unsupported aci card\n"); | ||
1376 | sprintf(card->shortname, "unknown Cardinal Technologies"); | ||
1377 | } | ||
1378 | |||
1379 | strcpy(card->driver, "miro"); | ||
1380 | sprintf(card->longname, "%s: OPTi%s, %s at 0x%lx, irq %d, dma %d&%d", | ||
1381 | card->shortname, miro->name, pcm->name, miro->wss_base + 4, | ||
1382 | miro->irq, miro->dma1, miro->dma2); | ||
1383 | |||
1384 | if (miro->mpu_port <= 0 || miro->mpu_port == SNDRV_AUTO_PORT) | ||
1385 | rmidi = NULL; | ||
1386 | else | ||
1387 | if ((error = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, | ||
1388 | miro->mpu_port, 0, miro->mpu_irq, SA_INTERRUPT, | ||
1389 | &rmidi))) | ||
1390 | snd_printk(KERN_WARNING "no MPU-401 device at 0x%lx?\n", miro->mpu_port); | ||
1391 | |||
1392 | if (miro->fm_port > 0 && miro->fm_port != SNDRV_AUTO_PORT) { | ||
1393 | struct snd_opl3 *opl3 = NULL; | ||
1394 | struct snd_opl4 *opl4; | ||
1395 | if (snd_opl4_create(card, miro->fm_port, miro->fm_port - 8, | ||
1396 | 2, &opl3, &opl4) < 0) | ||
1397 | snd_printk(KERN_WARNING "no OPL4 device at 0x%lx\n", miro->fm_port); | ||
1398 | } | ||
1399 | |||
1400 | if ((error = snd_set_aci_init_values(miro)) < 0) { | ||
1401 | snd_card_free(card); | ||
1402 | return error; | ||
1403 | } | ||
1404 | |||
1405 | snd_card_set_dev(card, &devptr->dev); | ||
1406 | |||
1407 | if ((error = snd_card_register(card))) { | ||
1408 | snd_card_free(card); | ||
1409 | return error; | ||
1410 | } | ||
1411 | |||
1412 | platform_set_drvdata(devptr, card); | ||
1413 | return 0; | ||
1414 | } | ||
1415 | |||
1416 | static int __devexit snd_miro_remove(struct platform_device *devptr) | ||
1417 | { | ||
1418 | snd_card_free(platform_get_drvdata(devptr)); | ||
1419 | platform_set_drvdata(devptr, NULL); | ||
1420 | return 0; | ||
1421 | } | ||
1422 | |||
1423 | static struct platform_driver snd_miro_driver = { | ||
1424 | .probe = snd_miro_probe, | ||
1425 | .remove = __devexit_p(snd_miro_remove), | ||
1426 | /* FIXME: suspend/resume */ | ||
1427 | .driver = { | ||
1428 | .name = DRIVER_NAME | ||
1429 | }, | ||
1430 | }; | ||
1431 | |||
1432 | static int __init alsa_card_miro_init(void) | ||
1433 | { | ||
1434 | int error; | ||
1435 | |||
1436 | if ((error = platform_driver_register(&snd_miro_driver)) < 0) | ||
1437 | return error; | ||
1438 | device = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0); | ||
1439 | if (! IS_ERR(device)) | ||
1440 | return 0; | ||
1441 | #ifdef MODULE | ||
1442 | printk(KERN_ERR "no miro soundcard found\n"); | ||
1443 | #endif | ||
1444 | platform_driver_unregister(&snd_miro_driver); | ||
1445 | return PTR_ERR(device); | ||
1446 | } | ||
1447 | |||
1448 | static void __exit alsa_card_miro_exit(void) | ||
1449 | { | ||
1450 | platform_device_unregister(device); | ||
1451 | platform_driver_unregister(&snd_miro_driver); | ||
1452 | } | ||
1453 | |||
1454 | module_init(alsa_card_miro_init) | ||
1455 | module_exit(alsa_card_miro_exit) | ||
diff --git a/sound/isa/opti9xx/miro.h b/sound/isa/opti9xx/miro.h new file mode 100644 index 000000000000..6e1385b8e07e --- /dev/null +++ b/sound/isa/opti9xx/miro.h | |||
@@ -0,0 +1,73 @@ | |||
1 | #ifndef _MIRO_H_ | ||
2 | #define _MIRO_H_ | ||
3 | |||
4 | #define ACI_REG_COMMAND 0 /* write register offset */ | ||
5 | #define ACI_REG_STATUS 1 /* read register offset */ | ||
6 | #define ACI_REG_BUSY 2 /* busy register offset */ | ||
7 | #define ACI_REG_RDS 2 /* PCM20: RDS register offset */ | ||
8 | #define ACI_MINTIME 500 /* ACI time out limit */ | ||
9 | |||
10 | #define ACI_SET_MUTE 0x0d | ||
11 | #define ACI_SET_POWERAMP 0x0f | ||
12 | #define ACI_SET_TUNERMUTE 0xa3 | ||
13 | #define ACI_SET_TUNERMONO 0xa4 | ||
14 | #define ACI_SET_IDE 0xd0 | ||
15 | #define ACI_SET_WSS 0xd1 | ||
16 | #define ACI_SET_SOLOMODE 0xd2 | ||
17 | #define ACI_SET_PREAMP 0x03 | ||
18 | #define ACI_GET_PREAMP 0x21 | ||
19 | #define ACI_WRITE_TUNE 0xa7 | ||
20 | #define ACI_READ_TUNERSTEREO 0xa8 | ||
21 | #define ACI_READ_TUNERSTATION 0xa9 | ||
22 | #define ACI_READ_VERSION 0xf1 | ||
23 | #define ACI_READ_IDCODE 0xf2 | ||
24 | #define ACI_INIT 0xff | ||
25 | #define ACI_STATUS 0xf0 | ||
26 | #define ACI_S_GENERAL 0x00 | ||
27 | #define ACI_ERROR_OP 0xdf | ||
28 | |||
29 | /* ACI Mixer */ | ||
30 | |||
31 | /* These are the values for the right channel GET registers. | ||
32 | Add an offset of 0x01 for the left channel register. | ||
33 | (left=right+0x01) */ | ||
34 | |||
35 | #define ACI_GET_MASTER 0x03 | ||
36 | #define ACI_GET_MIC 0x05 | ||
37 | #define ACI_GET_LINE 0x07 | ||
38 | #define ACI_GET_CD 0x09 | ||
39 | #define ACI_GET_SYNTH 0x0b | ||
40 | #define ACI_GET_PCM 0x0d | ||
41 | #define ACI_GET_LINE1 0x10 /* Radio on PCM20 */ | ||
42 | #define ACI_GET_LINE2 0x12 | ||
43 | |||
44 | #define ACI_GET_EQ1 0x22 /* from Bass ... */ | ||
45 | #define ACI_GET_EQ2 0x24 | ||
46 | #define ACI_GET_EQ3 0x26 | ||
47 | #define ACI_GET_EQ4 0x28 | ||
48 | #define ACI_GET_EQ5 0x2a | ||
49 | #define ACI_GET_EQ6 0x2c | ||
50 | #define ACI_GET_EQ7 0x2e /* ... to Treble */ | ||
51 | |||
52 | /* And these are the values for the right channel SET registers. | ||
53 | For left channel access you have to add an offset of 0x08. | ||
54 | MASTER is an exception, which needs an offset of 0x01 */ | ||
55 | |||
56 | #define ACI_SET_MASTER 0x00 | ||
57 | #define ACI_SET_MIC 0x30 | ||
58 | #define ACI_SET_LINE 0x31 | ||
59 | #define ACI_SET_CD 0x34 | ||
60 | #define ACI_SET_SYNTH 0x33 | ||
61 | #define ACI_SET_PCM 0x32 | ||
62 | #define ACI_SET_LINE1 0x35 /* Radio on PCM20 */ | ||
63 | #define ACI_SET_LINE2 0x36 | ||
64 | |||
65 | #define ACI_SET_EQ1 0x40 /* from Bass ... */ | ||
66 | #define ACI_SET_EQ2 0x41 | ||
67 | #define ACI_SET_EQ3 0x42 | ||
68 | #define ACI_SET_EQ4 0x43 | ||
69 | #define ACI_SET_EQ5 0x44 | ||
70 | #define ACI_SET_EQ6 0x45 | ||
71 | #define ACI_SET_EQ7 0x46 /* ... to Treble */ | ||
72 | |||
73 | #endif /* _MIRO_H_ */ | ||
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig index 1e2e19305e38..a2081803a827 100644 --- a/sound/pci/Kconfig +++ b/sound/pci/Kconfig | |||
@@ -15,6 +15,18 @@ config SND_AD1889 | |||
15 | To compile this as a module, choose M here: the module | 15 | To compile this as a module, choose M here: the module |
16 | will be called snd-ad1889. | 16 | will be called snd-ad1889. |
17 | 17 | ||
18 | config SND_ALS300 | ||
19 | tristate "Avance Logic ALS300/ALS300+" | ||
20 | depends on SND | ||
21 | select SND_PCM | ||
22 | select SND_AC97_CODEC | ||
23 | select SND_OPL3_LIB | ||
24 | help | ||
25 | Say 'Y' or 'M' to include support for Avance Logic ALS300/ALS300+ | ||
26 | |||
27 | To compile this driver as a module, choose M here: the module | ||
28 | will be called snd-als300 | ||
29 | |||
18 | config SND_ALS4000 | 30 | config SND_ALS4000 |
19 | tristate "Avance Logic ALS4000" | 31 | tristate "Avance Logic ALS4000" |
20 | depends on SND && ISA_DMA_API | 32 | depends on SND && ISA_DMA_API |
@@ -195,8 +207,9 @@ config SND_CS46XX | |||
195 | will be called snd-cs46xx. | 207 | will be called snd-cs46xx. |
196 | 208 | ||
197 | config SND_CS46XX_NEW_DSP | 209 | config SND_CS46XX_NEW_DSP |
198 | bool "Cirrus Logic (Sound Fusion) New DSP support (EXPERIMENTAL)" | 210 | bool "Cirrus Logic (Sound Fusion) New DSP support" |
199 | depends on SND_CS46XX && EXPERIMENTAL | 211 | depends on SND_CS46XX |
212 | default y | ||
200 | help | 213 | help |
201 | Say Y here to use a new DSP image for SPDIF and dual codecs. | 214 | Say Y here to use a new DSP image for SPDIF and dual codecs. |
202 | 215 | ||
@@ -466,6 +479,19 @@ config SND_PCXHR | |||
466 | To compile this driver as a module, choose M here: the module | 479 | To compile this driver as a module, choose M here: the module |
467 | will be called snd-pcxhr. | 480 | will be called snd-pcxhr. |
468 | 481 | ||
482 | config SND_RIPTIDE | ||
483 | tristate "Conexant Riptide" | ||
484 | depends on SND | ||
485 | depends on FW_LOADER | ||
486 | select SND_OPL3_LIB | ||
487 | select SND_MPU401_UART | ||
488 | select SND_AC97_CODEC | ||
489 | help | ||
490 | Say 'Y' or 'M' to include support for Conexant Riptide chip. | ||
491 | |||
492 | To compile this driver as a module, choose M here: the module | ||
493 | will be called snd-riptide | ||
494 | |||
469 | config SND_RME32 | 495 | config SND_RME32 |
470 | tristate "RME Digi32, 32/8, 32 PRO" | 496 | tristate "RME Digi32, 32/8, 32 PRO" |
471 | depends on SND | 497 | depends on SND |
diff --git a/sound/pci/Makefile b/sound/pci/Makefile index a6c3cd58fe94..cba5105aafea 100644 --- a/sound/pci/Makefile +++ b/sound/pci/Makefile | |||
@@ -4,6 +4,7 @@ | |||
4 | # | 4 | # |
5 | 5 | ||
6 | snd-ad1889-objs := ad1889.o | 6 | snd-ad1889-objs := ad1889.o |
7 | snd-als300-objs := als300.o | ||
7 | snd-als4000-objs := als4000.o | 8 | snd-als4000-objs := als4000.o |
8 | snd-atiixp-objs := atiixp.o | 9 | snd-atiixp-objs := atiixp.o |
9 | snd-atiixp-modem-objs := atiixp_modem.o | 10 | snd-atiixp-modem-objs := atiixp_modem.o |
@@ -27,6 +28,7 @@ snd-via82xx-modem-objs := via82xx_modem.o | |||
27 | 28 | ||
28 | # Toplevel Module Dependency | 29 | # Toplevel Module Dependency |
29 | obj-$(CONFIG_SND_AD1889) += snd-ad1889.o | 30 | obj-$(CONFIG_SND_AD1889) += snd-ad1889.o |
31 | obj-$(CONFIG_SND_ALS300) += snd-als300.o | ||
30 | obj-$(CONFIG_SND_ALS4000) += snd-als4000.o | 32 | obj-$(CONFIG_SND_ALS4000) += snd-als4000.o |
31 | obj-$(CONFIG_SND_ATIIXP) += snd-atiixp.o | 33 | obj-$(CONFIG_SND_ATIIXP) += snd-atiixp.o |
32 | obj-$(CONFIG_SND_ATIIXP_MODEM) += snd-atiixp-modem.o | 34 | obj-$(CONFIG_SND_ATIIXP_MODEM) += snd-atiixp-modem.o |
@@ -62,6 +64,7 @@ obj-$(CONFIG_SND) += \ | |||
62 | mixart/ \ | 64 | mixart/ \ |
63 | nm256/ \ | 65 | nm256/ \ |
64 | pcxhr/ \ | 66 | pcxhr/ \ |
67 | riptide/ \ | ||
65 | rme9652/ \ | 68 | rme9652/ \ |
66 | trident/ \ | 69 | trident/ \ |
67 | ymfpci/ \ | 70 | ymfpci/ \ |
diff --git a/sound/pci/als300.c b/sound/pci/als300.c new file mode 100644 index 000000000000..37b80570a5c6 --- /dev/null +++ b/sound/pci/als300.c | |||
@@ -0,0 +1,866 @@ | |||
1 | /* | ||
2 | * als300.c - driver for Avance Logic ALS300/ALS300+ soundcards. | ||
3 | * Copyright (C) 2005 by Ash Willis <ashwillis@programmer.net> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | * | ||
19 | * TODO | ||
20 | * 4 channel playback for ALS300+ | ||
21 | * gameport | ||
22 | * mpu401 | ||
23 | * opl3 | ||
24 | * | ||
25 | * NOTES | ||
26 | * The BLOCK_COUNTER registers for the ALS300(+) return a figure related to | ||
27 | * the position in the current period, NOT the whole buffer. It is important | ||
28 | * to know which period we are in so we can calculate the correct pointer. | ||
29 | * This is why we always use 2 periods. We can then use a flip-flop variable | ||
30 | * to keep track of what period we are in. | ||
31 | */ | ||
32 | |||
33 | #include <sound/driver.h> | ||
34 | #include <linux/delay.h> | ||
35 | #include <linux/init.h> | ||
36 | #include <linux/moduleparam.h> | ||
37 | #include <linux/pci.h> | ||
38 | #include <linux/interrupt.h> | ||
39 | #include <linux/slab.h> | ||
40 | |||
41 | #include <asm/io.h> | ||
42 | |||
43 | #include <sound/core.h> | ||
44 | #include <sound/control.h> | ||
45 | #include <sound/initval.h> | ||
46 | #include <sound/pcm.h> | ||
47 | #include <sound/pcm_params.h> | ||
48 | #include <sound/ac97_codec.h> | ||
49 | #include <sound/opl3.h> | ||
50 | |||
51 | /* snd_als300_set_irq_flag */ | ||
52 | #define IRQ_DISABLE 0 | ||
53 | #define IRQ_ENABLE 1 | ||
54 | |||
55 | /* I/O port layout */ | ||
56 | #define AC97_ACCESS 0x00 | ||
57 | #define AC97_READ 0x04 | ||
58 | #define AC97_STATUS 0x06 | ||
59 | #define AC97_DATA_AVAIL (1<<6) | ||
60 | #define AC97_BUSY (1<<7) | ||
61 | #define ALS300_IRQ_STATUS 0x07 /* ALS300 Only */ | ||
62 | #define IRQ_PLAYBACK (1<<3) | ||
63 | #define IRQ_CAPTURE (1<<2) | ||
64 | #define GCR_DATA 0x08 | ||
65 | #define GCR_INDEX 0x0C | ||
66 | #define ALS300P_DRAM_IRQ_STATUS 0x0D /* ALS300+ Only */ | ||
67 | #define MPU_IRQ_STATUS 0x0E /* ALS300 Rev. E+, ALS300+ */ | ||
68 | #define ALS300P_IRQ_STATUS 0x0F /* ALS300+ Only */ | ||
69 | |||
70 | /* General Control Registers */ | ||
71 | #define PLAYBACK_START 0x80 | ||
72 | #define PLAYBACK_END 0x81 | ||
73 | #define PLAYBACK_CONTROL 0x82 | ||
74 | #define TRANSFER_START (1<<16) | ||
75 | #define FIFO_PAUSE (1<<17) | ||
76 | #define RECORD_START 0x83 | ||
77 | #define RECORD_END 0x84 | ||
78 | #define RECORD_CONTROL 0x85 | ||
79 | #define DRAM_WRITE_CONTROL 0x8B | ||
80 | #define WRITE_TRANS_START (1<<16) | ||
81 | #define DRAM_MODE_2 (1<<17) | ||
82 | #define MISC_CONTROL 0x8C | ||
83 | #define IRQ_SET_BIT (1<<15) | ||
84 | #define VMUTE_NORMAL (1<<20) | ||
85 | #define MMUTE_NORMAL (1<<21) | ||
86 | #define MUS_VOC_VOL 0x8E | ||
87 | #define PLAYBACK_BLOCK_COUNTER 0x9A | ||
88 | #define RECORD_BLOCK_COUNTER 0x9B | ||
89 | |||
90 | #define DEBUG_CALLS 1 | ||
91 | #define DEBUG_PLAY_REC 1 | ||
92 | |||
93 | #if DEBUG_CALLS | ||
94 | #define snd_als300_dbgcalls(format, args...) printk(format, ##args) | ||
95 | #define snd_als300_dbgcallenter() printk(KERN_ERR "--> %s\n", __FUNCTION__) | ||
96 | #define snd_als300_dbgcallleave() printk(KERN_ERR "<-- %s\n", __FUNCTION__) | ||
97 | #else | ||
98 | #define snd_als300_dbgcalls(format, args...) | ||
99 | #define snd_als300_dbgcallenter() | ||
100 | #define snd_als300_dbgcallleave() | ||
101 | #endif | ||
102 | |||
103 | #if DEBUG_PLAY_REC | ||
104 | #define snd_als300_dbgplay(format, args...) printk(KERN_ERR format, ##args) | ||
105 | #else | ||
106 | #define snd_als300_dbgplay(format, args...) | ||
107 | #endif | ||
108 | |||
109 | enum {DEVICE_ALS300, DEVICE_ALS300_PLUS}; | ||
110 | |||
111 | MODULE_AUTHOR("Ash Willis <ashwillis@programmer.net>"); | ||
112 | MODULE_DESCRIPTION("Avance Logic ALS300"); | ||
113 | MODULE_LICENSE("GPL"); | ||
114 | MODULE_SUPPORTED_DEVICE("{{Avance Logic,ALS300},{Avance Logic,ALS300+}}"); | ||
115 | |||
116 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; | ||
117 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; | ||
118 | static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; | ||
119 | |||
120 | struct snd_als300 { | ||
121 | unsigned long port; | ||
122 | spinlock_t reg_lock; | ||
123 | struct snd_card *card; | ||
124 | struct pci_dev *pci; | ||
125 | |||
126 | struct snd_pcm *pcm; | ||
127 | struct snd_pcm_substream *playback_substream; | ||
128 | struct snd_pcm_substream *capture_substream; | ||
129 | |||
130 | struct snd_ac97 *ac97; | ||
131 | struct snd_opl3 *opl3; | ||
132 | |||
133 | struct resource *res_port; | ||
134 | |||
135 | int irq; | ||
136 | |||
137 | int chip_type; /* ALS300 or ALS300+ */ | ||
138 | |||
139 | char revision; | ||
140 | }; | ||
141 | |||
142 | struct snd_als300_substream_data { | ||
143 | int period_flipflop; | ||
144 | int control_register; | ||
145 | int block_counter_register; | ||
146 | }; | ||
147 | |||
148 | static struct pci_device_id snd_als300_ids[] = { | ||
149 | { 0x4005, 0x0300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_ALS300 }, | ||
150 | { 0x4005, 0x0308, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_ALS300_PLUS }, | ||
151 | { 0, } | ||
152 | }; | ||
153 | |||
154 | MODULE_DEVICE_TABLE(pci, snd_als300_ids); | ||
155 | |||
156 | static inline u32 snd_als300_gcr_read(unsigned long port, unsigned short reg) | ||
157 | { | ||
158 | outb(reg, port+GCR_INDEX); | ||
159 | return inl(port+GCR_DATA); | ||
160 | } | ||
161 | |||
162 | static inline void snd_als300_gcr_write(unsigned long port, | ||
163 | unsigned short reg, u32 val) | ||
164 | { | ||
165 | outb(reg, port+GCR_INDEX); | ||
166 | outl(val, port+GCR_DATA); | ||
167 | } | ||
168 | |||
169 | /* Enable/Disable Interrupts */ | ||
170 | static void snd_als300_set_irq_flag(struct snd_als300 *chip, int cmd) | ||
171 | { | ||
172 | u32 tmp = snd_als300_gcr_read(chip->port, MISC_CONTROL); | ||
173 | snd_als300_dbgcallenter(); | ||
174 | |||
175 | /* boolean XOR check, since old vs. new hardware have | ||
176 | directly reversed bit setting for ENABLE and DISABLE. | ||
177 | ALS300+ acts like newer versions of ALS300 */ | ||
178 | if (((chip->revision > 5 || chip->chip_type == DEVICE_ALS300_PLUS) ^ | ||
179 | (cmd == IRQ_ENABLE)) == 0) | ||
180 | tmp |= IRQ_SET_BIT; | ||
181 | else | ||
182 | tmp &= ~IRQ_SET_BIT; | ||
183 | snd_als300_gcr_write(chip->port, MISC_CONTROL, tmp); | ||
184 | snd_als300_dbgcallleave(); | ||
185 | } | ||
186 | |||
187 | static int snd_als300_free(struct snd_als300 *chip) | ||
188 | { | ||
189 | snd_als300_dbgcallenter(); | ||
190 | snd_als300_set_irq_flag(chip, IRQ_DISABLE); | ||
191 | if (chip->irq >= 0) | ||
192 | free_irq(chip->irq, (void *)chip); | ||
193 | pci_release_regions(chip->pci); | ||
194 | pci_disable_device(chip->pci); | ||
195 | kfree(chip); | ||
196 | snd_als300_dbgcallleave(); | ||
197 | return 0; | ||
198 | } | ||
199 | |||
200 | static int snd_als300_dev_free(struct snd_device *device) | ||
201 | { | ||
202 | struct snd_als300 *chip = device->device_data; | ||
203 | return snd_als300_free(chip); | ||
204 | } | ||
205 | |||
206 | static irqreturn_t snd_als300_interrupt(int irq, void *dev_id, | ||
207 | struct pt_regs *regs) | ||
208 | { | ||
209 | u8 status; | ||
210 | struct snd_als300 *chip = dev_id; | ||
211 | struct snd_als300_substream_data *data; | ||
212 | |||
213 | status = inb(chip->port+ALS300_IRQ_STATUS); | ||
214 | if (!status) /* shared IRQ, for different device?? Exit ASAP! */ | ||
215 | return IRQ_NONE; | ||
216 | |||
217 | /* ACK everything ASAP */ | ||
218 | outb(status, chip->port+ALS300_IRQ_STATUS); | ||
219 | if (status & IRQ_PLAYBACK) { | ||
220 | if (chip->pcm && chip->playback_substream) { | ||
221 | data = chip->playback_substream->runtime->private_data; | ||
222 | data->period_flipflop ^= 1; | ||
223 | snd_pcm_period_elapsed(chip->playback_substream); | ||
224 | snd_als300_dbgplay("IRQ_PLAYBACK\n"); | ||
225 | } | ||
226 | } | ||
227 | if (status & IRQ_CAPTURE) { | ||
228 | if (chip->pcm && chip->capture_substream) { | ||
229 | data = chip->capture_substream->runtime->private_data; | ||
230 | data->period_flipflop ^= 1; | ||
231 | snd_pcm_period_elapsed(chip->capture_substream); | ||
232 | snd_als300_dbgplay("IRQ_CAPTURE\n"); | ||
233 | } | ||
234 | } | ||
235 | return IRQ_HANDLED; | ||
236 | } | ||
237 | |||
238 | static irqreturn_t snd_als300plus_interrupt(int irq, void *dev_id, | ||
239 | struct pt_regs *regs) | ||
240 | { | ||
241 | u8 general, mpu, dram; | ||
242 | struct snd_als300 *chip = dev_id; | ||
243 | struct snd_als300_substream_data *data; | ||
244 | |||
245 | general = inb(chip->port+ALS300P_IRQ_STATUS); | ||
246 | mpu = inb(chip->port+MPU_IRQ_STATUS); | ||
247 | dram = inb(chip->port+ALS300P_DRAM_IRQ_STATUS); | ||
248 | |||
249 | /* shared IRQ, for different device?? Exit ASAP! */ | ||
250 | if ((general == 0) && ((mpu & 0x80) == 0) && ((dram & 0x01) == 0)) | ||
251 | return IRQ_NONE; | ||
252 | |||
253 | if (general & IRQ_PLAYBACK) { | ||
254 | if (chip->pcm && chip->playback_substream) { | ||
255 | outb(IRQ_PLAYBACK, chip->port+ALS300P_IRQ_STATUS); | ||
256 | data = chip->playback_substream->runtime->private_data; | ||
257 | data->period_flipflop ^= 1; | ||
258 | snd_pcm_period_elapsed(chip->playback_substream); | ||
259 | snd_als300_dbgplay("IRQ_PLAYBACK\n"); | ||
260 | } | ||
261 | } | ||
262 | if (general & IRQ_CAPTURE) { | ||
263 | if (chip->pcm && chip->capture_substream) { | ||
264 | outb(IRQ_CAPTURE, chip->port+ALS300P_IRQ_STATUS); | ||
265 | data = chip->capture_substream->runtime->private_data; | ||
266 | data->period_flipflop ^= 1; | ||
267 | snd_pcm_period_elapsed(chip->capture_substream); | ||
268 | snd_als300_dbgplay("IRQ_CAPTURE\n"); | ||
269 | } | ||
270 | } | ||
271 | /* FIXME: Ack other interrupt types. Not important right now as | ||
272 | * those other devices aren't enabled. */ | ||
273 | return IRQ_HANDLED; | ||
274 | } | ||
275 | |||
276 | static void __devexit snd_als300_remove(struct pci_dev *pci) | ||
277 | { | ||
278 | snd_als300_dbgcallenter(); | ||
279 | snd_card_free(pci_get_drvdata(pci)); | ||
280 | pci_set_drvdata(pci, NULL); | ||
281 | snd_als300_dbgcallleave(); | ||
282 | } | ||
283 | |||
284 | static unsigned short snd_als300_ac97_read(struct snd_ac97 *ac97, | ||
285 | unsigned short reg) | ||
286 | { | ||
287 | int i; | ||
288 | struct snd_als300 *chip = ac97->private_data; | ||
289 | |||
290 | for (i = 0; i < 1000; i++) { | ||
291 | if ((inb(chip->port+AC97_STATUS) & (AC97_BUSY)) == 0) | ||
292 | break; | ||
293 | udelay(10); | ||
294 | } | ||
295 | outl((reg << 24) | (1 << 31), chip->port+AC97_ACCESS); | ||
296 | |||
297 | for (i = 0; i < 1000; i++) { | ||
298 | if ((inb(chip->port+AC97_STATUS) & (AC97_DATA_AVAIL)) != 0) | ||
299 | break; | ||
300 | udelay(10); | ||
301 | } | ||
302 | return inw(chip->port+AC97_READ); | ||
303 | } | ||
304 | |||
305 | static void snd_als300_ac97_write(struct snd_ac97 *ac97, | ||
306 | unsigned short reg, unsigned short val) | ||
307 | { | ||
308 | int i; | ||
309 | struct snd_als300 *chip = ac97->private_data; | ||
310 | |||
311 | for (i = 0; i < 1000; i++) { | ||
312 | if ((inb(chip->port+AC97_STATUS) & (AC97_BUSY)) == 0) | ||
313 | break; | ||
314 | udelay(10); | ||
315 | } | ||
316 | outl((reg << 24) | val, chip->port+AC97_ACCESS); | ||
317 | } | ||
318 | |||
319 | static int snd_als300_ac97(struct snd_als300 *chip) | ||
320 | { | ||
321 | struct snd_ac97_bus *bus; | ||
322 | struct snd_ac97_template ac97; | ||
323 | int err; | ||
324 | static struct snd_ac97_bus_ops ops = { | ||
325 | .write = snd_als300_ac97_write, | ||
326 | .read = snd_als300_ac97_read, | ||
327 | }; | ||
328 | |||
329 | snd_als300_dbgcallenter(); | ||
330 | if ((err = snd_ac97_bus(chip->card, 0, &ops, NULL, &bus)) < 0) | ||
331 | return err; | ||
332 | |||
333 | memset(&ac97, 0, sizeof(ac97)); | ||
334 | ac97.private_data = chip; | ||
335 | |||
336 | snd_als300_dbgcallleave(); | ||
337 | return snd_ac97_mixer(bus, &ac97, &chip->ac97); | ||
338 | } | ||
339 | |||
340 | /* hardware definition | ||
341 | * | ||
342 | * In AC97 mode, we always use 48k/16bit/stereo. | ||
343 | * Any request to change data type is ignored by | ||
344 | * the card when it is running outside of legacy | ||
345 | * mode. | ||
346 | */ | ||
347 | static struct snd_pcm_hardware snd_als300_playback_hw = | ||
348 | { | ||
349 | .info = (SNDRV_PCM_INFO_MMAP | | ||
350 | SNDRV_PCM_INFO_INTERLEAVED | | ||
351 | SNDRV_PCM_INFO_PAUSE | | ||
352 | SNDRV_PCM_INFO_MMAP_VALID), | ||
353 | .formats = SNDRV_PCM_FMTBIT_S16, | ||
354 | .rates = SNDRV_PCM_RATE_48000, | ||
355 | .rate_min = 48000, | ||
356 | .rate_max = 48000, | ||
357 | .channels_min = 2, | ||
358 | .channels_max = 2, | ||
359 | .buffer_bytes_max = 64 * 1024, | ||
360 | .period_bytes_min = 64, | ||
361 | .period_bytes_max = 32 * 1024, | ||
362 | .periods_min = 2, | ||
363 | .periods_max = 2, | ||
364 | }; | ||
365 | |||
366 | static struct snd_pcm_hardware snd_als300_capture_hw = | ||
367 | { | ||
368 | .info = (SNDRV_PCM_INFO_MMAP | | ||
369 | SNDRV_PCM_INFO_INTERLEAVED | | ||
370 | SNDRV_PCM_INFO_PAUSE | | ||
371 | SNDRV_PCM_INFO_MMAP_VALID), | ||
372 | .formats = SNDRV_PCM_FMTBIT_S16, | ||
373 | .rates = SNDRV_PCM_RATE_48000, | ||
374 | .rate_min = 48000, | ||
375 | .rate_max = 48000, | ||
376 | .channels_min = 2, | ||
377 | .channels_max = 2, | ||
378 | .buffer_bytes_max = 64 * 1024, | ||
379 | .period_bytes_min = 64, | ||
380 | .period_bytes_max = 32 * 1024, | ||
381 | .periods_min = 2, | ||
382 | .periods_max = 2, | ||
383 | }; | ||
384 | |||
385 | static int snd_als300_playback_open(struct snd_pcm_substream *substream) | ||
386 | { | ||
387 | struct snd_als300 *chip = snd_pcm_substream_chip(substream); | ||
388 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
389 | struct snd_als300_substream_data *data = kzalloc(sizeof(*data), | ||
390 | GFP_KERNEL); | ||
391 | |||
392 | snd_als300_dbgcallenter(); | ||
393 | chip->playback_substream = substream; | ||
394 | runtime->hw = snd_als300_playback_hw; | ||
395 | runtime->private_data = data; | ||
396 | data->control_register = PLAYBACK_CONTROL; | ||
397 | data->block_counter_register = PLAYBACK_BLOCK_COUNTER; | ||
398 | snd_als300_dbgcallleave(); | ||
399 | return 0; | ||
400 | } | ||
401 | |||
402 | static int snd_als300_playback_close(struct snd_pcm_substream *substream) | ||
403 | { | ||
404 | struct snd_als300 *chip = snd_pcm_substream_chip(substream); | ||
405 | struct snd_als300_substream_data *data; | ||
406 | |||
407 | data = substream->runtime->private_data; | ||
408 | snd_als300_dbgcallenter(); | ||
409 | kfree(data); | ||
410 | chip->playback_substream = NULL; | ||
411 | snd_pcm_lib_free_pages(substream); | ||
412 | snd_als300_dbgcallleave(); | ||
413 | return 0; | ||
414 | } | ||
415 | |||
416 | static int snd_als300_capture_open(struct snd_pcm_substream *substream) | ||
417 | { | ||
418 | struct snd_als300 *chip = snd_pcm_substream_chip(substream); | ||
419 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
420 | struct snd_als300_substream_data *data = kzalloc(sizeof(*data), | ||
421 | GFP_KERNEL); | ||
422 | |||
423 | snd_als300_dbgcallenter(); | ||
424 | chip->capture_substream = substream; | ||
425 | runtime->hw = snd_als300_capture_hw; | ||
426 | runtime->private_data = data; | ||
427 | data->control_register = RECORD_CONTROL; | ||
428 | data->block_counter_register = RECORD_BLOCK_COUNTER; | ||
429 | snd_als300_dbgcallleave(); | ||
430 | return 0; | ||
431 | } | ||
432 | |||
433 | static int snd_als300_capture_close(struct snd_pcm_substream *substream) | ||
434 | { | ||
435 | struct snd_als300 *chip = snd_pcm_substream_chip(substream); | ||
436 | struct snd_als300_substream_data *data; | ||
437 | |||
438 | data = substream->runtime->private_data; | ||
439 | snd_als300_dbgcallenter(); | ||
440 | kfree(data); | ||
441 | chip->capture_substream = NULL; | ||
442 | snd_pcm_lib_free_pages(substream); | ||
443 | snd_als300_dbgcallleave(); | ||
444 | return 0; | ||
445 | } | ||
446 | |||
447 | static int snd_als300_pcm_hw_params(struct snd_pcm_substream *substream, | ||
448 | snd_pcm_hw_params_t * hw_params) | ||
449 | { | ||
450 | return snd_pcm_lib_malloc_pages(substream, | ||
451 | params_buffer_bytes(hw_params)); | ||
452 | } | ||
453 | |||
454 | static int snd_als300_pcm_hw_free(struct snd_pcm_substream *substream) | ||
455 | { | ||
456 | return snd_pcm_lib_free_pages(substream); | ||
457 | } | ||
458 | |||
459 | static int snd_als300_playback_prepare(struct snd_pcm_substream *substream) | ||
460 | { | ||
461 | u32 tmp; | ||
462 | struct snd_als300 *chip = snd_pcm_substream_chip(substream); | ||
463 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
464 | unsigned short period_bytes = snd_pcm_lib_period_bytes(substream); | ||
465 | unsigned short buffer_bytes = snd_pcm_lib_buffer_bytes(substream); | ||
466 | |||
467 | snd_als300_dbgcallenter(); | ||
468 | spin_lock_irq(&chip->reg_lock); | ||
469 | tmp = snd_als300_gcr_read(chip->port, PLAYBACK_CONTROL); | ||
470 | tmp &= ~TRANSFER_START; | ||
471 | |||
472 | snd_als300_dbgplay("Period bytes: %d Buffer bytes %d\n", | ||
473 | period_bytes, buffer_bytes); | ||
474 | |||
475 | /* set block size */ | ||
476 | tmp &= 0xffff0000; | ||
477 | tmp |= period_bytes - 1; | ||
478 | snd_als300_gcr_write(chip->port, PLAYBACK_CONTROL, tmp); | ||
479 | |||
480 | /* set dma area */ | ||
481 | snd_als300_gcr_write(chip->port, PLAYBACK_START, | ||
482 | runtime->dma_addr); | ||
483 | snd_als300_gcr_write(chip->port, PLAYBACK_END, | ||
484 | runtime->dma_addr + buffer_bytes - 1); | ||
485 | spin_unlock_irq(&chip->reg_lock); | ||
486 | snd_als300_dbgcallleave(); | ||
487 | return 0; | ||
488 | } | ||
489 | |||
490 | static int snd_als300_capture_prepare(struct snd_pcm_substream *substream) | ||
491 | { | ||
492 | u32 tmp; | ||
493 | struct snd_als300 *chip = snd_pcm_substream_chip(substream); | ||
494 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
495 | unsigned short period_bytes = snd_pcm_lib_period_bytes(substream); | ||
496 | unsigned short buffer_bytes = snd_pcm_lib_buffer_bytes(substream); | ||
497 | |||
498 | snd_als300_dbgcallenter(); | ||
499 | spin_lock_irq(&chip->reg_lock); | ||
500 | tmp = snd_als300_gcr_read(chip->port, RECORD_CONTROL); | ||
501 | tmp &= ~TRANSFER_START; | ||
502 | |||
503 | snd_als300_dbgplay("Period bytes: %d Buffer bytes %d\n", period_bytes, | ||
504 | buffer_bytes); | ||
505 | |||
506 | /* set block size */ | ||
507 | tmp &= 0xffff0000; | ||
508 | tmp |= period_bytes - 1; | ||
509 | |||
510 | /* set dma area */ | ||
511 | snd_als300_gcr_write(chip->port, RECORD_CONTROL, tmp); | ||
512 | snd_als300_gcr_write(chip->port, RECORD_START, | ||
513 | runtime->dma_addr); | ||
514 | snd_als300_gcr_write(chip->port, RECORD_END, | ||
515 | runtime->dma_addr + buffer_bytes - 1); | ||
516 | spin_unlock_irq(&chip->reg_lock); | ||
517 | snd_als300_dbgcallleave(); | ||
518 | return 0; | ||
519 | } | ||
520 | |||
521 | static int snd_als300_trigger(struct snd_pcm_substream *substream, int cmd) | ||
522 | { | ||
523 | struct snd_als300 *chip = snd_pcm_substream_chip(substream); | ||
524 | u32 tmp; | ||
525 | struct snd_als300_substream_data *data; | ||
526 | unsigned short reg; | ||
527 | int ret = 0; | ||
528 | |||
529 | data = substream->runtime->private_data; | ||
530 | reg = data->control_register; | ||
531 | |||
532 | snd_als300_dbgcallenter(); | ||
533 | spin_lock(&chip->reg_lock); | ||
534 | switch (cmd) { | ||
535 | case SNDRV_PCM_TRIGGER_START: | ||
536 | case SNDRV_PCM_TRIGGER_RESUME: | ||
537 | tmp = snd_als300_gcr_read(chip->port, reg); | ||
538 | data->period_flipflop = 1; | ||
539 | snd_als300_gcr_write(chip->port, reg, tmp | TRANSFER_START); | ||
540 | snd_als300_dbgplay("TRIGGER START\n"); | ||
541 | break; | ||
542 | case SNDRV_PCM_TRIGGER_STOP: | ||
543 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
544 | tmp = snd_als300_gcr_read(chip->port, reg); | ||
545 | snd_als300_gcr_write(chip->port, reg, tmp & ~TRANSFER_START); | ||
546 | snd_als300_dbgplay("TRIGGER STOP\n"); | ||
547 | break; | ||
548 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
549 | tmp = snd_als300_gcr_read(chip->port, reg); | ||
550 | snd_als300_gcr_write(chip->port, reg, tmp | FIFO_PAUSE); | ||
551 | snd_als300_dbgplay("TRIGGER PAUSE\n"); | ||
552 | break; | ||
553 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
554 | tmp = snd_als300_gcr_read(chip->port, reg); | ||
555 | snd_als300_gcr_write(chip->port, reg, tmp & ~FIFO_PAUSE); | ||
556 | snd_als300_dbgplay("TRIGGER RELEASE\n"); | ||
557 | break; | ||
558 | default: | ||
559 | snd_als300_dbgplay("TRIGGER INVALID\n"); | ||
560 | ret = -EINVAL; | ||
561 | } | ||
562 | spin_unlock(&chip->reg_lock); | ||
563 | snd_als300_dbgcallleave(); | ||
564 | return ret; | ||
565 | } | ||
566 | |||
567 | static snd_pcm_uframes_t snd_als300_pointer(struct snd_pcm_substream *substream) | ||
568 | { | ||
569 | u16 current_ptr; | ||
570 | struct snd_als300 *chip = snd_pcm_substream_chip(substream); | ||
571 | struct snd_als300_substream_data *data; | ||
572 | unsigned short period_bytes; | ||
573 | |||
574 | data = substream->runtime->private_data; | ||
575 | period_bytes = snd_pcm_lib_period_bytes(substream); | ||
576 | |||
577 | snd_als300_dbgcallenter(); | ||
578 | spin_lock(&chip->reg_lock); | ||
579 | current_ptr = (u16) snd_als300_gcr_read(chip->port, | ||
580 | data->block_counter_register) + 4; | ||
581 | spin_unlock(&chip->reg_lock); | ||
582 | if (current_ptr > period_bytes) | ||
583 | current_ptr = 0; | ||
584 | else | ||
585 | current_ptr = period_bytes - current_ptr; | ||
586 | |||
587 | if (data->period_flipflop == 0) | ||
588 | current_ptr += period_bytes; | ||
589 | snd_als300_dbgplay("Pointer (bytes): %d\n", current_ptr); | ||
590 | snd_als300_dbgcallleave(); | ||
591 | return bytes_to_frames(substream->runtime, current_ptr); | ||
592 | } | ||
593 | |||
594 | static struct snd_pcm_ops snd_als300_playback_ops = { | ||
595 | .open = snd_als300_playback_open, | ||
596 | .close = snd_als300_playback_close, | ||
597 | .ioctl = snd_pcm_lib_ioctl, | ||
598 | .hw_params = snd_als300_pcm_hw_params, | ||
599 | .hw_free = snd_als300_pcm_hw_free, | ||
600 | .prepare = snd_als300_playback_prepare, | ||
601 | .trigger = snd_als300_trigger, | ||
602 | .pointer = snd_als300_pointer, | ||
603 | }; | ||
604 | |||
605 | static struct snd_pcm_ops snd_als300_capture_ops = { | ||
606 | .open = snd_als300_capture_open, | ||
607 | .close = snd_als300_capture_close, | ||
608 | .ioctl = snd_pcm_lib_ioctl, | ||
609 | .hw_params = snd_als300_pcm_hw_params, | ||
610 | .hw_free = snd_als300_pcm_hw_free, | ||
611 | .prepare = snd_als300_capture_prepare, | ||
612 | .trigger = snd_als300_trigger, | ||
613 | .pointer = snd_als300_pointer, | ||
614 | }; | ||
615 | |||
616 | static int __devinit snd_als300_new_pcm(struct snd_als300 *chip) | ||
617 | { | ||
618 | struct snd_pcm *pcm; | ||
619 | int err; | ||
620 | |||
621 | snd_als300_dbgcallenter(); | ||
622 | err = snd_pcm_new(chip->card, "ALS300", 0, 1, 1, &pcm); | ||
623 | if (err < 0) | ||
624 | return err; | ||
625 | pcm->private_data = chip; | ||
626 | strcpy(pcm->name, "ALS300"); | ||
627 | chip->pcm = pcm; | ||
628 | |||
629 | /* set operators */ | ||
630 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, | ||
631 | &snd_als300_playback_ops); | ||
632 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, | ||
633 | &snd_als300_capture_ops); | ||
634 | |||
635 | /* pre-allocation of buffers */ | ||
636 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, | ||
637 | snd_dma_pci_data(chip->pci), 64*1024, 64*1024); | ||
638 | snd_als300_dbgcallleave(); | ||
639 | return 0; | ||
640 | } | ||
641 | |||
642 | static void snd_als300_init(struct snd_als300 *chip) | ||
643 | { | ||
644 | unsigned long flags; | ||
645 | u32 tmp; | ||
646 | |||
647 | snd_als300_dbgcallenter(); | ||
648 | spin_lock_irqsave(&chip->reg_lock, flags); | ||
649 | chip->revision = (snd_als300_gcr_read(chip->port, MISC_CONTROL) >> 16) | ||
650 | & 0x0000000F; | ||
651 | /* Setup DRAM */ | ||
652 | tmp = snd_als300_gcr_read(chip->port, DRAM_WRITE_CONTROL); | ||
653 | snd_als300_gcr_write(chip->port, DRAM_WRITE_CONTROL, | ||
654 | (tmp | DRAM_MODE_2) | ||
655 | & ~WRITE_TRANS_START); | ||
656 | |||
657 | /* Enable IRQ output */ | ||
658 | snd_als300_set_irq_flag(chip, IRQ_ENABLE); | ||
659 | |||
660 | /* Unmute hardware devices so their outputs get routed to | ||
661 | * the onboard mixer */ | ||
662 | tmp = snd_als300_gcr_read(chip->port, MISC_CONTROL); | ||
663 | snd_als300_gcr_write(chip->port, MISC_CONTROL, | ||
664 | tmp | VMUTE_NORMAL | MMUTE_NORMAL); | ||
665 | |||
666 | /* Reset volumes */ | ||
667 | snd_als300_gcr_write(chip->port, MUS_VOC_VOL, 0); | ||
668 | |||
669 | /* Make sure playback transfer is stopped */ | ||
670 | tmp = snd_als300_gcr_read(chip->port, PLAYBACK_CONTROL); | ||
671 | snd_als300_gcr_write(chip->port, PLAYBACK_CONTROL, | ||
672 | tmp & ~TRANSFER_START); | ||
673 | spin_unlock_irqrestore(&chip->reg_lock, flags); | ||
674 | snd_als300_dbgcallleave(); | ||
675 | } | ||
676 | |||
677 | static int __devinit snd_als300_create(snd_card_t *card, | ||
678 | struct pci_dev *pci, int chip_type, | ||
679 | struct snd_als300 **rchip) | ||
680 | { | ||
681 | struct snd_als300 *chip; | ||
682 | void *irq_handler; | ||
683 | int err; | ||
684 | |||
685 | static snd_device_ops_t ops = { | ||
686 | .dev_free = snd_als300_dev_free, | ||
687 | }; | ||
688 | *rchip = NULL; | ||
689 | |||
690 | snd_als300_dbgcallenter(); | ||
691 | if ((err = pci_enable_device(pci)) < 0) | ||
692 | return err; | ||
693 | |||
694 | if (pci_set_dma_mask(pci, 0x0fffffff) < 0 || | ||
695 | pci_set_consistent_dma_mask(pci, 0x0fffffff) < 0) { | ||
696 | printk(KERN_ERR "error setting 28bit DMA mask\n"); | ||
697 | pci_disable_device(pci); | ||
698 | return -ENXIO; | ||
699 | } | ||
700 | pci_set_master(pci); | ||
701 | |||
702 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); | ||
703 | if (chip == NULL) { | ||
704 | pci_disable_device(pci); | ||
705 | return -ENOMEM; | ||
706 | } | ||
707 | |||
708 | chip->card = card; | ||
709 | chip->pci = pci; | ||
710 | chip->irq = -1; | ||
711 | chip->chip_type = chip_type; | ||
712 | spin_lock_init(&chip->reg_lock); | ||
713 | |||
714 | if ((err = pci_request_regions(pci, "ALS300")) < 0) { | ||
715 | kfree(chip); | ||
716 | pci_disable_device(pci); | ||
717 | return err; | ||
718 | } | ||
719 | chip->port = pci_resource_start(pci, 0); | ||
720 | |||
721 | if (chip->chip_type == DEVICE_ALS300_PLUS) | ||
722 | irq_handler = snd_als300plus_interrupt; | ||
723 | else | ||
724 | irq_handler = snd_als300_interrupt; | ||
725 | |||
726 | if (request_irq(pci->irq, irq_handler, SA_INTERRUPT|SA_SHIRQ, | ||
727 | card->shortname, (void *)chip)) { | ||
728 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); | ||
729 | snd_als300_free(chip); | ||
730 | return -EBUSY; | ||
731 | } | ||
732 | chip->irq = pci->irq; | ||
733 | |||
734 | |||
735 | snd_als300_init(chip); | ||
736 | |||
737 | if (snd_als300_ac97(chip) < 0) { | ||
738 | snd_printk(KERN_WARNING "Could not create ac97\n"); | ||
739 | snd_als300_free(chip); | ||
740 | return err; | ||
741 | } | ||
742 | |||
743 | if ((err = snd_als300_new_pcm(chip)) < 0) { | ||
744 | snd_printk(KERN_WARNING "Could not create PCM\n"); | ||
745 | snd_als300_free(chip); | ||
746 | return err; | ||
747 | } | ||
748 | |||
749 | if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, | ||
750 | chip, &ops)) < 0) { | ||
751 | snd_als300_free(chip); | ||
752 | return err; | ||
753 | } | ||
754 | |||
755 | snd_card_set_dev(card, &pci->dev); | ||
756 | |||
757 | *rchip = chip; | ||
758 | snd_als300_dbgcallleave(); | ||
759 | return 0; | ||
760 | } | ||
761 | |||
762 | #ifdef CONFIG_PM | ||
763 | static int snd_als300_suspend(struct pci_dev *pci, pm_message_t state) | ||
764 | { | ||
765 | struct snd_card *card = pci_get_drvdata(pci); | ||
766 | struct snd_als300 *chip = card->private_data; | ||
767 | |||
768 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); | ||
769 | snd_pcm_suspend_all(chip->pcm); | ||
770 | snd_ac97_suspend(chip->ac97); | ||
771 | |||
772 | pci_set_power_state(pci, PCI_D3hot); | ||
773 | pci_disable_device(pci); | ||
774 | pci_save_state(pci); | ||
775 | return 0; | ||
776 | } | ||
777 | |||
778 | static int snd_als300_resume(struct pci_dev *pci) | ||
779 | { | ||
780 | struct snd_card *card = pci_get_drvdata(pci); | ||
781 | struct snd_als300 *chip = card->private_data; | ||
782 | |||
783 | pci_restore_state(pci); | ||
784 | pci_enable_device(pci); | ||
785 | pci_set_power_state(pci, PCI_D0); | ||
786 | pci_set_master(pci); | ||
787 | |||
788 | snd_als300_init(chip); | ||
789 | snd_ac97_resume(chip->ac97); | ||
790 | |||
791 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | ||
792 | return 0; | ||
793 | } | ||
794 | #endif | ||
795 | |||
796 | static int __devinit snd_als300_probe(struct pci_dev *pci, | ||
797 | const struct pci_device_id *pci_id) | ||
798 | { | ||
799 | static int dev; | ||
800 | struct snd_card *card; | ||
801 | struct snd_als300 *chip; | ||
802 | int err, chip_type; | ||
803 | |||
804 | if (dev >= SNDRV_CARDS) | ||
805 | return -ENODEV; | ||
806 | if (!enable[dev]) { | ||
807 | dev++; | ||
808 | return -ENOENT; | ||
809 | } | ||
810 | |||
811 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | ||
812 | |||
813 | if (card == NULL) | ||
814 | return -ENOMEM; | ||
815 | |||
816 | chip_type = pci_id->driver_data; | ||
817 | |||
818 | if ((err = snd_als300_create(card, pci, chip_type, &chip)) < 0) { | ||
819 | snd_card_free(card); | ||
820 | return err; | ||
821 | } | ||
822 | card->private_data = chip; | ||
823 | |||
824 | strcpy(card->driver, "ALS300"); | ||
825 | if (chip->chip_type == DEVICE_ALS300_PLUS) | ||
826 | /* don't know much about ALS300+ yet | ||
827 | * print revision number for now */ | ||
828 | sprintf(card->shortname, "ALS300+ (Rev. %d)", chip->revision); | ||
829 | else | ||
830 | sprintf(card->shortname, "ALS300 (Rev. %c)", 'A' + | ||
831 | chip->revision - 1); | ||
832 | sprintf(card->longname, "%s at 0x%lx irq %i", | ||
833 | card->shortname, chip->port, chip->irq); | ||
834 | |||
835 | if ((err = snd_card_register(card)) < 0) { | ||
836 | snd_card_free(card); | ||
837 | return err; | ||
838 | } | ||
839 | pci_set_drvdata(pci, card); | ||
840 | dev++; | ||
841 | return 0; | ||
842 | } | ||
843 | |||
844 | static struct pci_driver driver = { | ||
845 | .name = "ALS300", | ||
846 | .id_table = snd_als300_ids, | ||
847 | .probe = snd_als300_probe, | ||
848 | .remove = __devexit_p(snd_als300_remove), | ||
849 | #ifdef CONFIG_PM | ||
850 | .suspend = snd_als300_suspend, | ||
851 | .resume = snd_als300_resume, | ||
852 | #endif | ||
853 | }; | ||
854 | |||
855 | static int __init alsa_card_als300_init(void) | ||
856 | { | ||
857 | return pci_register_driver(&driver); | ||
858 | } | ||
859 | |||
860 | static void __exit alsa_card_als300_exit(void) | ||
861 | { | ||
862 | pci_unregister_driver(&driver); | ||
863 | } | ||
864 | |||
865 | module_init(alsa_card_als300_init) | ||
866 | module_exit(alsa_card_als300_exit) | ||
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c index 4f65ec56bf35..ac4e73f69c1d 100644 --- a/sound/pci/cs4281.c +++ b/sound/pci/cs4281.c | |||
@@ -1046,7 +1046,7 @@ static int snd_cs4281_put_volume(struct snd_kcontrol *kcontrol, | |||
1046 | snd_cs4281_pokeBA0(chip, regL, volL); | 1046 | snd_cs4281_pokeBA0(chip, regL, volL); |
1047 | change = 1; | 1047 | change = 1; |
1048 | } | 1048 | } |
1049 | if (ucontrol->value.integer.value[0] != volL) { | 1049 | if (ucontrol->value.integer.value[1] != volR) { |
1050 | volR = CS_VOL_MASK - (ucontrol->value.integer.value[1] & CS_VOL_MASK); | 1050 | volR = CS_VOL_MASK - (ucontrol->value.integer.value[1] & CS_VOL_MASK); |
1051 | snd_cs4281_pokeBA0(chip, regR, volR); | 1051 | snd_cs4281_pokeBA0(chip, regR, volR); |
1052 | change = 1; | 1052 | change = 1; |
@@ -1416,7 +1416,7 @@ static int __devinit snd_cs4281_create(struct snd_card *card, | |||
1416 | static int snd_cs4281_chip_init(struct cs4281 *chip) | 1416 | static int snd_cs4281_chip_init(struct cs4281 *chip) |
1417 | { | 1417 | { |
1418 | unsigned int tmp; | 1418 | unsigned int tmp; |
1419 | int timeout; | 1419 | unsigned long end_time; |
1420 | int retry_count = 2; | 1420 | int retry_count = 2; |
1421 | 1421 | ||
1422 | /* Having EPPMC.FPDN=1 prevent proper chip initialisation */ | 1422 | /* Having EPPMC.FPDN=1 prevent proper chip initialisation */ |
@@ -1496,7 +1496,7 @@ static int snd_cs4281_chip_init(struct cs4281 *chip) | |||
1496 | /* | 1496 | /* |
1497 | * Wait for the DLL ready signal from the clock logic. | 1497 | * Wait for the DLL ready signal from the clock logic. |
1498 | */ | 1498 | */ |
1499 | timeout = 100; | 1499 | end_time = jiffies + HZ; |
1500 | do { | 1500 | do { |
1501 | /* | 1501 | /* |
1502 | * Read the AC97 status register to see if we've seen a CODEC | 1502 | * Read the AC97 status register to see if we've seen a CODEC |
@@ -1504,8 +1504,8 @@ static int snd_cs4281_chip_init(struct cs4281 *chip) | |||
1504 | */ | 1504 | */ |
1505 | if (snd_cs4281_peekBA0(chip, BA0_CLKCR1) & BA0_CLKCR1_DLLRDY) | 1505 | if (snd_cs4281_peekBA0(chip, BA0_CLKCR1) & BA0_CLKCR1_DLLRDY) |
1506 | goto __ok0; | 1506 | goto __ok0; |
1507 | msleep(1); | 1507 | schedule_timeout_uninterruptible(1); |
1508 | } while (timeout-- > 0); | 1508 | } while (time_after_eq(end_time, jiffies)); |
1509 | 1509 | ||
1510 | snd_printk(KERN_ERR "DLLRDY not seen\n"); | 1510 | snd_printk(KERN_ERR "DLLRDY not seen\n"); |
1511 | return -EIO; | 1511 | return -EIO; |
@@ -1522,7 +1522,7 @@ static int snd_cs4281_chip_init(struct cs4281 *chip) | |||
1522 | /* | 1522 | /* |
1523 | * Wait for the codec ready signal from the AC97 codec. | 1523 | * Wait for the codec ready signal from the AC97 codec. |
1524 | */ | 1524 | */ |
1525 | timeout = 100; | 1525 | end_time = jiffies + HZ; |
1526 | do { | 1526 | do { |
1527 | /* | 1527 | /* |
1528 | * Read the AC97 status register to see if we've seen a CODEC | 1528 | * Read the AC97 status register to see if we've seen a CODEC |
@@ -1530,20 +1530,20 @@ static int snd_cs4281_chip_init(struct cs4281 *chip) | |||
1530 | */ | 1530 | */ |
1531 | if (snd_cs4281_peekBA0(chip, BA0_ACSTS) & BA0_ACSTS_CRDY) | 1531 | if (snd_cs4281_peekBA0(chip, BA0_ACSTS) & BA0_ACSTS_CRDY) |
1532 | goto __ok1; | 1532 | goto __ok1; |
1533 | msleep(1); | 1533 | schedule_timeout_uninterruptible(1); |
1534 | } while (timeout-- > 0); | 1534 | } while (time_after_eq(end_time, jiffies)); |
1535 | 1535 | ||
1536 | snd_printk(KERN_ERR "never read codec ready from AC'97 (0x%x)\n", snd_cs4281_peekBA0(chip, BA0_ACSTS)); | 1536 | snd_printk(KERN_ERR "never read codec ready from AC'97 (0x%x)\n", snd_cs4281_peekBA0(chip, BA0_ACSTS)); |
1537 | return -EIO; | 1537 | return -EIO; |
1538 | 1538 | ||
1539 | __ok1: | 1539 | __ok1: |
1540 | if (chip->dual_codec) { | 1540 | if (chip->dual_codec) { |
1541 | timeout = 100; | 1541 | end_time = jiffies + HZ; |
1542 | do { | 1542 | do { |
1543 | if (snd_cs4281_peekBA0(chip, BA0_ACSTS2) & BA0_ACSTS_CRDY) | 1543 | if (snd_cs4281_peekBA0(chip, BA0_ACSTS2) & BA0_ACSTS_CRDY) |
1544 | goto __codec2_ok; | 1544 | goto __codec2_ok; |
1545 | msleep(1); | 1545 | schedule_timeout_uninterruptible(1); |
1546 | } while (timeout-- > 0); | 1546 | } while (time_after_eq(end_time, jiffies)); |
1547 | snd_printk(KERN_INFO "secondary codec doesn't respond. disable it...\n"); | 1547 | snd_printk(KERN_INFO "secondary codec doesn't respond. disable it...\n"); |
1548 | chip->dual_codec = 0; | 1548 | chip->dual_codec = 0; |
1549 | __codec2_ok: ; | 1549 | __codec2_ok: ; |
@@ -1561,7 +1561,7 @@ static int snd_cs4281_chip_init(struct cs4281 *chip) | |||
1561 | * the codec is pumping ADC data across the AC-link. | 1561 | * the codec is pumping ADC data across the AC-link. |
1562 | */ | 1562 | */ |
1563 | 1563 | ||
1564 | timeout = 100; | 1564 | end_time = jiffies + HZ; |
1565 | do { | 1565 | do { |
1566 | /* | 1566 | /* |
1567 | * Read the input slot valid register and see if input slots 3 | 1567 | * Read the input slot valid register and see if input slots 3 |
@@ -1569,8 +1569,8 @@ static int snd_cs4281_chip_init(struct cs4281 *chip) | |||
1569 | */ | 1569 | */ |
1570 | if ((snd_cs4281_peekBA0(chip, BA0_ACISV) & (BA0_ACISV_SLV(3) | BA0_ACISV_SLV(4))) == (BA0_ACISV_SLV(3) | BA0_ACISV_SLV(4))) | 1570 | if ((snd_cs4281_peekBA0(chip, BA0_ACISV) & (BA0_ACISV_SLV(3) | BA0_ACISV_SLV(4))) == (BA0_ACISV_SLV(3) | BA0_ACISV_SLV(4))) |
1571 | goto __ok2; | 1571 | goto __ok2; |
1572 | msleep(1); | 1572 | schedule_timeout_uninterruptible(1); |
1573 | } while (timeout-- > 0); | 1573 | } while (time_after_eq(end_time, jiffies)); |
1574 | 1574 | ||
1575 | if (--retry_count > 0) | 1575 | if (--retry_count > 0) |
1576 | goto __retry; | 1576 | goto __retry; |
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index b42dff7ceed0..5bee3b536478 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -295,7 +295,7 @@ static int init_unsol_queue(struct hda_bus *bus) | |||
295 | snd_printk(KERN_ERR "hda_codec: can't allocate unsolicited queue\n"); | 295 | snd_printk(KERN_ERR "hda_codec: can't allocate unsolicited queue\n"); |
296 | return -ENOMEM; | 296 | return -ENOMEM; |
297 | } | 297 | } |
298 | unsol->workq = create_workqueue("hda_codec"); | 298 | unsol->workq = create_singlethread_workqueue("hda_codec"); |
299 | if (! unsol->workq) { | 299 | if (! unsol->workq) { |
300 | snd_printk(KERN_ERR "hda_codec: can't create workqueue\n"); | 300 | snd_printk(KERN_ERR "hda_codec: can't create workqueue\n"); |
301 | kfree(unsol); | 301 | kfree(unsol); |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index c096606970ff..0ad60ae29011 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -81,6 +81,7 @@ MODULE_SUPPORTED_DEVICE("{{Intel, ICH6}," | |||
81 | "{Intel, ESB2}," | 81 | "{Intel, ESB2}," |
82 | "{Intel, ICH8}," | 82 | "{Intel, ICH8}," |
83 | "{ATI, SB450}," | 83 | "{ATI, SB450}," |
84 | "{ATI, SB600}," | ||
84 | "{VIA, VT8251}," | 85 | "{VIA, VT8251}," |
85 | "{VIA, VT8237A}," | 86 | "{VIA, VT8237A}," |
86 | "{SiS, SIS966}," | 87 | "{SiS, SIS966}," |
@@ -1619,6 +1620,7 @@ static struct pci_device_id azx_ids[] = { | |||
1619 | { 0x8086, 0x269a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ESB2 */ | 1620 | { 0x8086, 0x269a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ESB2 */ |
1620 | { 0x8086, 0x284b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH8 */ | 1621 | { 0x8086, 0x284b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH8 */ |
1621 | { 0x1002, 0x437b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB450 */ | 1622 | { 0x1002, 0x437b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB450 */ |
1623 | { 0x1002, 0x4383, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB600 */ | ||
1622 | { 0x1106, 0x3288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_VIA }, /* VIA VT8251/VT8237A */ | 1624 | { 0x1106, 0x3288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_VIA }, /* VIA VT8251/VT8237A */ |
1623 | { 0x1039, 0x7502, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_SIS }, /* SIS966 */ | 1625 | { 0x1039, 0x7502, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_SIS }, /* SIS966 */ |
1624 | { 0x10b9, 0x5461, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ULI }, /* ULI M5461 */ | 1626 | { 0x10b9, 0x5461, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ULI }, /* ULI M5461 */ |
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 32401bd8c229..2bfe37e8543c 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c | |||
@@ -44,6 +44,7 @@ struct ad198x_spec { | |||
44 | * dig_out_nid and hp_nid are optional | 44 | * dig_out_nid and hp_nid are optional |
45 | */ | 45 | */ |
46 | unsigned int cur_eapd; | 46 | unsigned int cur_eapd; |
47 | unsigned int need_dac_fix; | ||
47 | 48 | ||
48 | /* capture */ | 49 | /* capture */ |
49 | unsigned int num_adc_nids; | 50 | unsigned int num_adc_nids; |
@@ -836,10 +837,14 @@ static int patch_ad1986a(struct hda_codec *codec) | |||
836 | case AD1986A_3STACK: | 837 | case AD1986A_3STACK: |
837 | spec->num_mixers = 2; | 838 | spec->num_mixers = 2; |
838 | spec->mixers[1] = ad1986a_3st_mixers; | 839 | spec->mixers[1] = ad1986a_3st_mixers; |
839 | spec->num_init_verbs = 2; | 840 | spec->num_init_verbs = 3; |
840 | spec->init_verbs[1] = ad1986a_3st_init_verbs; | 841 | spec->init_verbs[1] = ad1986a_3st_init_verbs; |
842 | spec->init_verbs[2] = ad1986a_ch2_init; | ||
841 | spec->channel_mode = ad1986a_modes; | 843 | spec->channel_mode = ad1986a_modes; |
842 | spec->num_channel_mode = ARRAY_SIZE(ad1986a_modes); | 844 | spec->num_channel_mode = ARRAY_SIZE(ad1986a_modes); |
845 | spec->need_dac_fix = 1; | ||
846 | spec->multiout.max_channels = 2; | ||
847 | spec->multiout.num_dacs = 1; | ||
843 | break; | 848 | break; |
844 | case AD1986A_LAPTOP: | 849 | case AD1986A_LAPTOP: |
845 | spec->mixers[0] = ad1986a_laptop_mixers; | 850 | spec->mixers[0] = ad1986a_laptop_mixers; |
@@ -1555,6 +1560,8 @@ static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol, | |||
1555 | { | 1560 | { |
1556 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 1561 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
1557 | struct ad198x_spec *spec = codec->spec; | 1562 | struct ad198x_spec *spec = codec->spec; |
1563 | if (spec->need_dac_fix) | ||
1564 | spec->multiout.num_dacs = spec->multiout.max_channels / 2; | ||
1558 | return snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode, | 1565 | return snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode, |
1559 | spec->num_channel_mode, &spec->multiout.max_channels); | 1566 | spec->num_channel_mode, &spec->multiout.max_channels); |
1560 | } | 1567 | } |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 4c6c9ec8ea5b..66bbdb60f50b 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -52,6 +52,7 @@ enum { | |||
52 | ALC880_CLEVO, | 52 | ALC880_CLEVO, |
53 | ALC880_TCL_S700, | 53 | ALC880_TCL_S700, |
54 | ALC880_LG, | 54 | ALC880_LG, |
55 | ALC880_LG_LW, | ||
55 | #ifdef CONFIG_SND_DEBUG | 56 | #ifdef CONFIG_SND_DEBUG |
56 | ALC880_TEST, | 57 | ALC880_TEST, |
57 | #endif | 58 | #endif |
@@ -131,6 +132,7 @@ struct alc_spec { | |||
131 | hda_nid_t dig_in_nid; /* digital-in NID; optional */ | 132 | hda_nid_t dig_in_nid; /* digital-in NID; optional */ |
132 | 133 | ||
133 | /* capture source */ | 134 | /* capture source */ |
135 | unsigned int num_mux_defs; | ||
134 | const struct hda_input_mux *input_mux; | 136 | const struct hda_input_mux *input_mux; |
135 | unsigned int cur_mux[3]; | 137 | unsigned int cur_mux[3]; |
136 | 138 | ||
@@ -172,6 +174,7 @@ struct alc_config_preset { | |||
172 | hda_nid_t dig_in_nid; | 174 | hda_nid_t dig_in_nid; |
173 | unsigned int num_channel_mode; | 175 | unsigned int num_channel_mode; |
174 | const struct hda_channel_mode *channel_mode; | 176 | const struct hda_channel_mode *channel_mode; |
177 | unsigned int num_mux_defs; | ||
175 | const struct hda_input_mux *input_mux; | 178 | const struct hda_input_mux *input_mux; |
176 | void (*unsol_event)(struct hda_codec *, unsigned int); | 179 | void (*unsol_event)(struct hda_codec *, unsigned int); |
177 | void (*init_hook)(struct hda_codec *); | 180 | void (*init_hook)(struct hda_codec *); |
@@ -185,7 +188,10 @@ static int alc_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ | |||
185 | { | 188 | { |
186 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 189 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
187 | struct alc_spec *spec = codec->spec; | 190 | struct alc_spec *spec = codec->spec; |
188 | return snd_hda_input_mux_info(spec->input_mux, uinfo); | 191 | unsigned int mux_idx = snd_ctl_get_ioffidx(kcontrol, &uinfo->id); |
192 | if (mux_idx >= spec->num_mux_defs) | ||
193 | mux_idx = 0; | ||
194 | return snd_hda_input_mux_info(&spec->input_mux[mux_idx], uinfo); | ||
189 | } | 195 | } |
190 | 196 | ||
191 | static int alc_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 197 | static int alc_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
@@ -203,7 +209,8 @@ static int alc_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v | |||
203 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 209 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
204 | struct alc_spec *spec = codec->spec; | 210 | struct alc_spec *spec = codec->spec; |
205 | unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | 211 | unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); |
206 | return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol, | 212 | unsigned int mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx; |
213 | return snd_hda_input_mux_put(codec, &spec->input_mux[mux_idx], ucontrol, | ||
207 | spec->adc_nids[adc_idx], &spec->cur_mux[adc_idx]); | 214 | spec->adc_nids[adc_idx], &spec->cur_mux[adc_idx]); |
208 | } | 215 | } |
209 | 216 | ||
@@ -245,7 +252,8 @@ static int alc_ch_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_va | |||
245 | * states other than HiZ (eg: PIN_VREFxx) and revert to HiZ if any of these | 252 | * states other than HiZ (eg: PIN_VREFxx) and revert to HiZ if any of these |
246 | * are requested. Therefore order this list so that this behaviour will not | 253 | * are requested. Therefore order this list so that this behaviour will not |
247 | * cause problems when mixer clients move through the enum sequentially. | 254 | * cause problems when mixer clients move through the enum sequentially. |
248 | * NIDs 0x0f and 0x10 have been observed to have this behaviour. | 255 | * NIDs 0x0f and 0x10 have been observed to have this behaviour as of |
256 | * March 2006. | ||
249 | */ | 257 | */ |
250 | static char *alc_pin_mode_names[] = { | 258 | static char *alc_pin_mode_names[] = { |
251 | "Mic 50pc bias", "Mic 80pc bias", | 259 | "Mic 50pc bias", "Mic 80pc bias", |
@@ -255,19 +263,27 @@ static unsigned char alc_pin_mode_values[] = { | |||
255 | PIN_VREF50, PIN_VREF80, PIN_IN, PIN_OUT, PIN_HP, | 263 | PIN_VREF50, PIN_VREF80, PIN_IN, PIN_OUT, PIN_HP, |
256 | }; | 264 | }; |
257 | /* The control can present all 5 options, or it can limit the options based | 265 | /* The control can present all 5 options, or it can limit the options based |
258 | * in the pin being assumed to be exclusively an input or an output pin. | 266 | * in the pin being assumed to be exclusively an input or an output pin. In |
267 | * addition, "input" pins may or may not process the mic bias option | ||
268 | * depending on actual widget capability (NIDs 0x0f and 0x10 don't seem to | ||
269 | * accept requests for bias as of chip versions up to March 2006) and/or | ||
270 | * wiring in the computer. | ||
259 | */ | 271 | */ |
260 | #define ALC_PIN_DIR_IN 0x00 | 272 | #define ALC_PIN_DIR_IN 0x00 |
261 | #define ALC_PIN_DIR_OUT 0x01 | 273 | #define ALC_PIN_DIR_OUT 0x01 |
262 | #define ALC_PIN_DIR_INOUT 0x02 | 274 | #define ALC_PIN_DIR_INOUT 0x02 |
275 | #define ALC_PIN_DIR_IN_NOMICBIAS 0x03 | ||
276 | #define ALC_PIN_DIR_INOUT_NOMICBIAS 0x04 | ||
263 | 277 | ||
264 | /* Info about the pin modes supported by the three different pin directions. | 278 | /* Info about the pin modes supported by the different pin direction modes. |
265 | * For each direction the minimum and maximum values are given. | 279 | * For each direction the minimum and maximum values are given. |
266 | */ | 280 | */ |
267 | static signed char alc_pin_mode_dir_info[3][2] = { | 281 | static signed char alc_pin_mode_dir_info[5][2] = { |
268 | { 0, 2 }, /* ALC_PIN_DIR_IN */ | 282 | { 0, 2 }, /* ALC_PIN_DIR_IN */ |
269 | { 3, 4 }, /* ALC_PIN_DIR_OUT */ | 283 | { 3, 4 }, /* ALC_PIN_DIR_OUT */ |
270 | { 0, 4 }, /* ALC_PIN_DIR_INOUT */ | 284 | { 0, 4 }, /* ALC_PIN_DIR_INOUT */ |
285 | { 2, 2 }, /* ALC_PIN_DIR_IN_NOMICBIAS */ | ||
286 | { 2, 4 }, /* ALC_PIN_DIR_INOUT_NOMICBIAS */ | ||
271 | }; | 287 | }; |
272 | #define alc_pin_mode_min(_dir) (alc_pin_mode_dir_info[_dir][0]) | 288 | #define alc_pin_mode_min(_dir) (alc_pin_mode_dir_info[_dir][0]) |
273 | #define alc_pin_mode_max(_dir) (alc_pin_mode_dir_info[_dir][1]) | 289 | #define alc_pin_mode_max(_dir) (alc_pin_mode_dir_info[_dir][1]) |
@@ -329,9 +345,10 @@ static int alc_pin_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v | |||
329 | * input modes. | 345 | * input modes. |
330 | * | 346 | * |
331 | * Dynamically switching the input/output buffers probably | 347 | * Dynamically switching the input/output buffers probably |
332 | * reduces noise slightly, particularly on input. However, | 348 | * reduces noise slightly (particularly on input) so we'll |
333 | * havingboth input and output buffers enabled | 349 | * do it. However, having both input and output buffers |
334 | * simultaneously doesn't seem to be problematic. | 350 | * enabled simultaneously doesn't seem to be problematic if |
351 | * this turns out to be necessary in the future. | ||
335 | */ | 352 | */ |
336 | if (val <= 2) { | 353 | if (val <= 2) { |
337 | snd_hda_codec_write(codec,nid,0,AC_VERB_SET_AMP_GAIN_MUTE, | 354 | snd_hda_codec_write(codec,nid,0,AC_VERB_SET_AMP_GAIN_MUTE, |
@@ -483,6 +500,9 @@ static void setup_preset(struct alc_spec *spec, const struct alc_config_preset * | |||
483 | spec->multiout.dig_out_nid = preset->dig_out_nid; | 500 | spec->multiout.dig_out_nid = preset->dig_out_nid; |
484 | spec->multiout.hp_nid = preset->hp_nid; | 501 | spec->multiout.hp_nid = preset->hp_nid; |
485 | 502 | ||
503 | spec->num_mux_defs = preset->num_mux_defs; | ||
504 | if (! spec->num_mux_defs) | ||
505 | spec->num_mux_defs = 1; | ||
486 | spec->input_mux = preset->input_mux; | 506 | spec->input_mux = preset->input_mux; |
487 | 507 | ||
488 | spec->num_adc_nids = preset->num_adc_nids; | 508 | spec->num_adc_nids = preset->num_adc_nids; |
@@ -1427,6 +1447,82 @@ static void alc880_lg_unsol_event(struct hda_codec *codec, unsigned int res) | |||
1427 | } | 1447 | } |
1428 | 1448 | ||
1429 | /* | 1449 | /* |
1450 | * LG LW20 | ||
1451 | * | ||
1452 | * Pin assignment: | ||
1453 | * Speaker-out: 0x14 | ||
1454 | * Mic-In: 0x18 | ||
1455 | * Built-in Mic-In: 0x19 (?) | ||
1456 | * HP-Out: 0x1b | ||
1457 | * SPDIF-Out: 0x1e | ||
1458 | */ | ||
1459 | |||
1460 | /* seems analog CD is not working */ | ||
1461 | static struct hda_input_mux alc880_lg_lw_capture_source = { | ||
1462 | .num_items = 2, | ||
1463 | .items = { | ||
1464 | { "Mic", 0x0 }, | ||
1465 | { "Internal Mic", 0x1 }, | ||
1466 | }, | ||
1467 | }; | ||
1468 | |||
1469 | static struct snd_kcontrol_new alc880_lg_lw_mixer[] = { | ||
1470 | HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
1471 | HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT), | ||
1472 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
1473 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
1474 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), | ||
1475 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), | ||
1476 | { } /* end */ | ||
1477 | }; | ||
1478 | |||
1479 | static struct hda_verb alc880_lg_lw_init_verbs[] = { | ||
1480 | /* set capture source to mic-in */ | ||
1481 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
1482 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
1483 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
1484 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(7)}, | ||
1485 | /* speaker-out */ | ||
1486 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
1487 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1488 | /* HP-out */ | ||
1489 | {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1490 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
1491 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1492 | /* mic-in to input */ | ||
1493 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
1494 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1495 | /* built-in mic */ | ||
1496 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
1497 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1498 | /* jack sense */ | ||
1499 | {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | 0x1}, | ||
1500 | { } | ||
1501 | }; | ||
1502 | |||
1503 | /* toggle speaker-output according to the hp-jack state */ | ||
1504 | static void alc880_lg_lw_automute(struct hda_codec *codec) | ||
1505 | { | ||
1506 | unsigned int present; | ||
1507 | |||
1508 | present = snd_hda_codec_read(codec, 0x1b, 0, | ||
1509 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | ||
1510 | snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, | ||
1511 | 0x80, present ? 0x80 : 0); | ||
1512 | snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, | ||
1513 | 0x80, present ? 0x80 : 0); | ||
1514 | } | ||
1515 | |||
1516 | static void alc880_lg_lw_unsol_event(struct hda_codec *codec, unsigned int res) | ||
1517 | { | ||
1518 | /* Looks like the unsol event is incompatible with the standard | ||
1519 | * definition. 4bit tag is placed at 28 bit! | ||
1520 | */ | ||
1521 | if ((res >> 28) == 0x01) | ||
1522 | alc880_lg_lw_automute(codec); | ||
1523 | } | ||
1524 | |||
1525 | /* | ||
1430 | * Common callbacks | 1526 | * Common callbacks |
1431 | */ | 1527 | */ |
1432 | 1528 | ||
@@ -2078,6 +2174,9 @@ static struct hda_board_config alc880_cfg_tbl[] = { | |||
2078 | { .modelname = "lg", .config = ALC880_LG }, | 2174 | { .modelname = "lg", .config = ALC880_LG }, |
2079 | { .pci_subvendor = 0x1854, .pci_subdevice = 0x003b, .config = ALC880_LG }, | 2175 | { .pci_subvendor = 0x1854, .pci_subdevice = 0x003b, .config = ALC880_LG }, |
2080 | 2176 | ||
2177 | { .modelname = "lg-lw", .config = ALC880_LG_LW }, | ||
2178 | { .pci_subvendor = 0x1854, .pci_subdevice = 0x0018, .config = ALC880_LG_LW }, | ||
2179 | |||
2081 | #ifdef CONFIG_SND_DEBUG | 2180 | #ifdef CONFIG_SND_DEBUG |
2082 | { .modelname = "test", .config = ALC880_TEST }, | 2181 | { .modelname = "test", .config = ALC880_TEST }, |
2083 | #endif | 2182 | #endif |
@@ -2268,6 +2367,19 @@ static struct alc_config_preset alc880_presets[] = { | |||
2268 | .unsol_event = alc880_lg_unsol_event, | 2367 | .unsol_event = alc880_lg_unsol_event, |
2269 | .init_hook = alc880_lg_automute, | 2368 | .init_hook = alc880_lg_automute, |
2270 | }, | 2369 | }, |
2370 | [ALC880_LG_LW] = { | ||
2371 | .mixers = { alc880_lg_lw_mixer }, | ||
2372 | .init_verbs = { alc880_volume_init_verbs, | ||
2373 | alc880_lg_lw_init_verbs }, | ||
2374 | .num_dacs = 1, | ||
2375 | .dac_nids = alc880_dac_nids, | ||
2376 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
2377 | .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes), | ||
2378 | .channel_mode = alc880_2_jack_modes, | ||
2379 | .input_mux = &alc880_lg_lw_capture_source, | ||
2380 | .unsol_event = alc880_lg_lw_unsol_event, | ||
2381 | .init_hook = alc880_lg_lw_automute, | ||
2382 | }, | ||
2271 | #ifdef CONFIG_SND_DEBUG | 2383 | #ifdef CONFIG_SND_DEBUG |
2272 | [ALC880_TEST] = { | 2384 | [ALC880_TEST] = { |
2273 | .mixers = { alc880_test_mixer }, | 2385 | .mixers = { alc880_test_mixer }, |
@@ -2593,6 +2705,7 @@ static int alc880_parse_auto_config(struct hda_codec *codec) | |||
2593 | 2705 | ||
2594 | spec->init_verbs[spec->num_init_verbs++] = alc880_volume_init_verbs; | 2706 | spec->init_verbs[spec->num_init_verbs++] = alc880_volume_init_verbs; |
2595 | 2707 | ||
2708 | spec->num_mux_defs = 1; | ||
2596 | spec->input_mux = &spec->private_imux; | 2709 | spec->input_mux = &spec->private_imux; |
2597 | 2710 | ||
2598 | return 1; | 2711 | return 1; |
@@ -2722,30 +2835,56 @@ static struct hda_input_mux alc260_capture_source = { | |||
2722 | }; | 2835 | }; |
2723 | 2836 | ||
2724 | /* On Fujitsu S702x laptops capture only makes sense from Mic/LineIn jack, | 2837 | /* On Fujitsu S702x laptops capture only makes sense from Mic/LineIn jack, |
2725 | * headphone jack and the internal CD lines. | 2838 | * headphone jack and the internal CD lines since these are the only pins at |
2839 | * which audio can appear. For flexibility, also allow the option of | ||
2840 | * recording the mixer output on the second ADC (ADC0 doesn't have a | ||
2841 | * connection to the mixer output). | ||
2726 | */ | 2842 | */ |
2727 | static struct hda_input_mux alc260_fujitsu_capture_source = { | 2843 | static struct hda_input_mux alc260_fujitsu_capture_sources[2] = { |
2728 | .num_items = 3, | 2844 | { |
2729 | .items = { | 2845 | .num_items = 3, |
2730 | { "Mic/Line", 0x0 }, | 2846 | .items = { |
2731 | { "CD", 0x4 }, | 2847 | { "Mic/Line", 0x0 }, |
2732 | { "Headphone", 0x2 }, | 2848 | { "CD", 0x4 }, |
2849 | { "Headphone", 0x2 }, | ||
2850 | }, | ||
2733 | }, | 2851 | }, |
2852 | { | ||
2853 | .num_items = 4, | ||
2854 | .items = { | ||
2855 | { "Mic/Line", 0x0 }, | ||
2856 | { "CD", 0x4 }, | ||
2857 | { "Headphone", 0x2 }, | ||
2858 | { "Mixer", 0x5 }, | ||
2859 | }, | ||
2860 | }, | ||
2861 | |||
2734 | }; | 2862 | }; |
2735 | 2863 | ||
2736 | /* Acer TravelMate(/Extensa/Aspire) notebooks have similar configutation to | 2864 | /* Acer TravelMate(/Extensa/Aspire) notebooks have similar configuration to |
2737 | * the Fujitsu S702x, but jacks are marked differently. We won't allow | 2865 | * the Fujitsu S702x, but jacks are marked differently. |
2738 | * retasking the Headphone jack, so it won't be available here. | ||
2739 | */ | 2866 | */ |
2740 | static struct hda_input_mux alc260_acer_capture_source = { | 2867 | static struct hda_input_mux alc260_acer_capture_sources[2] = { |
2741 | .num_items = 3, | 2868 | { |
2742 | .items = { | 2869 | .num_items = 4, |
2743 | { "Mic", 0x0 }, | 2870 | .items = { |
2744 | { "Line", 0x2 }, | 2871 | { "Mic", 0x0 }, |
2745 | { "CD", 0x4 }, | 2872 | { "Line", 0x2 }, |
2873 | { "CD", 0x4 }, | ||
2874 | { "Headphone", 0x5 }, | ||
2875 | }, | ||
2876 | }, | ||
2877 | { | ||
2878 | .num_items = 5, | ||
2879 | .items = { | ||
2880 | { "Mic", 0x0 }, | ||
2881 | { "Line", 0x2 }, | ||
2882 | { "CD", 0x4 }, | ||
2883 | { "Headphone", 0x6 }, | ||
2884 | { "Mixer", 0x5 }, | ||
2885 | }, | ||
2746 | }, | 2886 | }, |
2747 | }; | 2887 | }; |
2748 | |||
2749 | /* | 2888 | /* |
2750 | * This is just place-holder, so there's something for alc_build_pcms to look | 2889 | * This is just place-holder, so there's something for alc_build_pcms to look |
2751 | * at when it calculates the maximum number of channels. ALC260 has no mixer | 2890 | * at when it calculates the maximum number of channels. ALC260 has no mixer |
@@ -2806,6 +2945,9 @@ static struct snd_kcontrol_new alc260_hp_3013_mixer[] = { | |||
2806 | { } /* end */ | 2945 | { } /* end */ |
2807 | }; | 2946 | }; |
2808 | 2947 | ||
2948 | /* Fujitsu S702x series laptops. ALC260 pin usage: Mic/Line jack = 0x12, | ||
2949 | * HP jack = 0x14, CD audio = 0x16, internal speaker = 0x10. | ||
2950 | */ | ||
2809 | static struct snd_kcontrol_new alc260_fujitsu_mixer[] = { | 2951 | static struct snd_kcontrol_new alc260_fujitsu_mixer[] = { |
2810 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT), | 2952 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT), |
2811 | HDA_BIND_MUTE("Headphone Playback Switch", 0x08, 2, HDA_INPUT), | 2953 | HDA_BIND_MUTE("Headphone Playback Switch", 0x08, 2, HDA_INPUT), |
@@ -2822,9 +2964,28 @@ static struct snd_kcontrol_new alc260_fujitsu_mixer[] = { | |||
2822 | { } /* end */ | 2964 | { } /* end */ |
2823 | }; | 2965 | }; |
2824 | 2966 | ||
2967 | /* Mixer for Acer TravelMate(/Extensa/Aspire) notebooks. Note that current | ||
2968 | * versions of the ALC260 don't act on requests to enable mic bias from NID | ||
2969 | * 0x0f (used to drive the headphone jack in these laptops). The ALC260 | ||
2970 | * datasheet doesn't mention this restriction. At this stage it's not clear | ||
2971 | * whether this behaviour is intentional or is a hardware bug in chip | ||
2972 | * revisions available in early 2006. Therefore for now allow the | ||
2973 | * "Headphone Jack Mode" control to span all choices, but if it turns out | ||
2974 | * that the lack of mic bias for this NID is intentional we could change the | ||
2975 | * mode from ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS. | ||
2976 | * | ||
2977 | * In addition, Acer TravelMate(/Extensa/Aspire) notebooks in early 2006 | ||
2978 | * don't appear to make the mic bias available from the "line" jack, even | ||
2979 | * though the NID used for this jack (0x14) can supply it. The theory is | ||
2980 | * that perhaps Acer have included blocking capacitors between the ALC260 | ||
2981 | * and the output jack. If this turns out to be the case for all such | ||
2982 | * models the "Line Jack Mode" mode could be changed from ALC_PIN_DIR_INOUT | ||
2983 | * to ALC_PIN_DIR_INOUT_NOMICBIAS. | ||
2984 | */ | ||
2825 | static struct snd_kcontrol_new alc260_acer_mixer[] = { | 2985 | static struct snd_kcontrol_new alc260_acer_mixer[] = { |
2826 | HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT), | 2986 | HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT), |
2827 | HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT), | 2987 | HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT), |
2988 | ALC_PIN_MODE("Headphone Jack Mode", 0x0f, ALC_PIN_DIR_INOUT), | ||
2828 | HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), | 2989 | HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), |
2829 | HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), | 2990 | HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), |
2830 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT), | 2991 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT), |
@@ -3038,7 +3199,8 @@ static struct hda_verb alc260_hp_3013_init_verbs[] = { | |||
3038 | }; | 3199 | }; |
3039 | 3200 | ||
3040 | /* Initialisation sequence for ALC260 as configured in Fujitsu S702x | 3201 | /* Initialisation sequence for ALC260 as configured in Fujitsu S702x |
3041 | * laptops. | 3202 | * laptops. ALC260 pin usage: Mic/Line jack = 0x12, HP jack = 0x14, CD |
3203 | * audio = 0x16, internal speaker = 0x10. | ||
3042 | */ | 3204 | */ |
3043 | static struct hda_verb alc260_fujitsu_init_verbs[] = { | 3205 | static struct hda_verb alc260_fujitsu_init_verbs[] = { |
3044 | /* Disable all GPIOs */ | 3206 | /* Disable all GPIOs */ |
@@ -3185,10 +3347,10 @@ static struct hda_verb alc260_acer_init_verbs[] = { | |||
3185 | {0x04, AC_VERB_SET_CONNECT_SEL, 0x00}, | 3347 | {0x04, AC_VERB_SET_CONNECT_SEL, 0x00}, |
3186 | 3348 | ||
3187 | /* Do similar with the second ADC: mute capture input amp and | 3349 | /* Do similar with the second ADC: mute capture input amp and |
3188 | * set ADC connection to line (on line1 pin) | 3350 | * set ADC connection to mic to match ALSA's default state. |
3189 | */ | 3351 | */ |
3190 | {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | 3352 | {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
3191 | {0x05, AC_VERB_SET_CONNECT_SEL, 0x02}, | 3353 | {0x05, AC_VERB_SET_CONNECT_SEL, 0x00}, |
3192 | 3354 | ||
3193 | /* Mute all inputs to mixer widget (even unconnected ones) */ | 3355 | /* Mute all inputs to mixer widget (even unconnected ones) */ |
3194 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */ | 3356 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */ |
@@ -3213,26 +3375,35 @@ static hda_nid_t alc260_test_dac_nids[1] = { | |||
3213 | static hda_nid_t alc260_test_adc_nids[2] = { | 3375 | static hda_nid_t alc260_test_adc_nids[2] = { |
3214 | 0x04, 0x05, | 3376 | 0x04, 0x05, |
3215 | }; | 3377 | }; |
3216 | /* This is a bit messy since the two input muxes in the ALC260 have slight | 3378 | /* For testing the ALC260, each input MUX needs its own definition since |
3217 | * variations in their signal assignments. The ideal way to deal with this | 3379 | * the signal assignments are different. This assumes that the first ADC |
3218 | * is to extend alc_spec.input_mux to allow a different input MUX for each | 3380 | * is NID 0x04. |
3219 | * ADC. For the purposes of the test model it's sufficient to just list | ||
3220 | * both options for affected signal indices. The separate input mux | ||
3221 | * functionality only needs to be considered if a model comes along which | ||
3222 | * actually uses signals 0x5, 0x6 and 0x7 for something which makes sense to | ||
3223 | * record. | ||
3224 | */ | 3381 | */ |
3225 | static struct hda_input_mux alc260_test_capture_source = { | 3382 | static struct hda_input_mux alc260_test_capture_sources[2] = { |
3226 | .num_items = 8, | 3383 | { |
3227 | .items = { | 3384 | .num_items = 7, |
3228 | { "MIC1 pin", 0x0 }, | 3385 | .items = { |
3229 | { "MIC2 pin", 0x1 }, | 3386 | { "MIC1 pin", 0x0 }, |
3230 | { "LINE1 pin", 0x2 }, | 3387 | { "MIC2 pin", 0x1 }, |
3231 | { "LINE2 pin", 0x3 }, | 3388 | { "LINE1 pin", 0x2 }, |
3232 | { "CD pin", 0x4 }, | 3389 | { "LINE2 pin", 0x3 }, |
3233 | { "LINE-OUT pin (cap1), Mixer (cap2)", 0x5 }, | 3390 | { "CD pin", 0x4 }, |
3234 | { "HP-OUT pin (cap1), LINE-OUT pin (cap2)", 0x6 }, | 3391 | { "LINE-OUT pin", 0x5 }, |
3235 | { "HP-OUT pin (cap2 only)", 0x7 }, | 3392 | { "HP-OUT pin", 0x6 }, |
3393 | }, | ||
3394 | }, | ||
3395 | { | ||
3396 | .num_items = 8, | ||
3397 | .items = { | ||
3398 | { "MIC1 pin", 0x0 }, | ||
3399 | { "MIC2 pin", 0x1 }, | ||
3400 | { "LINE1 pin", 0x2 }, | ||
3401 | { "LINE2 pin", 0x3 }, | ||
3402 | { "CD pin", 0x4 }, | ||
3403 | { "Mixer", 0x5 }, | ||
3404 | { "LINE-OUT pin", 0x6 }, | ||
3405 | { "HP-OUT pin", 0x7 }, | ||
3406 | }, | ||
3236 | }, | 3407 | }, |
3237 | }; | 3408 | }; |
3238 | static struct snd_kcontrol_new alc260_test_mixer[] = { | 3409 | static struct snd_kcontrol_new alc260_test_mixer[] = { |
@@ -3244,7 +3415,17 @@ static struct snd_kcontrol_new alc260_test_mixer[] = { | |||
3244 | HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x08, 0x0, HDA_OUTPUT), | 3415 | HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x08, 0x0, HDA_OUTPUT), |
3245 | HDA_BIND_MUTE("LOUT1 Playback Switch", 0x08, 2, HDA_INPUT), | 3416 | HDA_BIND_MUTE("LOUT1 Playback Switch", 0x08, 2, HDA_INPUT), |
3246 | 3417 | ||
3247 | /* Modes for retasking pin widgets */ | 3418 | /* Modes for retasking pin widgets |
3419 | * Note: the ALC260 doesn't seem to act on requests to enable mic | ||
3420 | * bias from NIDs 0x0f and 0x10. The ALC260 datasheet doesn't | ||
3421 | * mention this restriction. At this stage it's not clear whether | ||
3422 | * this behaviour is intentional or is a hardware bug in chip | ||
3423 | * revisions available at least up until early 2006. Therefore for | ||
3424 | * now allow the "HP-OUT" and "LINE-OUT" Mode controls to span all | ||
3425 | * choices, but if it turns out that the lack of mic bias for these | ||
3426 | * NIDs is intentional we could change their modes from | ||
3427 | * ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS. | ||
3428 | */ | ||
3248 | ALC_PIN_MODE("HP-OUT pin mode", 0x10, ALC_PIN_DIR_INOUT), | 3429 | ALC_PIN_MODE("HP-OUT pin mode", 0x10, ALC_PIN_DIR_INOUT), |
3249 | ALC_PIN_MODE("LINE-OUT pin mode", 0x0f, ALC_PIN_DIR_INOUT), | 3430 | ALC_PIN_MODE("LINE-OUT pin mode", 0x0f, ALC_PIN_DIR_INOUT), |
3250 | ALC_PIN_MODE("LINE2 pin mode", 0x15, ALC_PIN_DIR_INOUT), | 3431 | ALC_PIN_MODE("LINE2 pin mode", 0x15, ALC_PIN_DIR_INOUT), |
@@ -3606,6 +3787,7 @@ static int alc260_parse_auto_config(struct hda_codec *codec) | |||
3606 | 3787 | ||
3607 | spec->init_verbs[spec->num_init_verbs++] = alc260_volume_init_verbs; | 3788 | spec->init_verbs[spec->num_init_verbs++] = alc260_volume_init_verbs; |
3608 | 3789 | ||
3790 | spec->num_mux_defs = 1; | ||
3609 | spec->input_mux = &spec->private_imux; | 3791 | spec->input_mux = &spec->private_imux; |
3610 | 3792 | ||
3611 | /* check whether NID 0x04 is valid */ | 3793 | /* check whether NID 0x04 is valid */ |
@@ -3711,7 +3893,8 @@ static struct alc_config_preset alc260_presets[] = { | |||
3711 | .adc_nids = alc260_dual_adc_nids, | 3893 | .adc_nids = alc260_dual_adc_nids, |
3712 | .num_channel_mode = ARRAY_SIZE(alc260_modes), | 3894 | .num_channel_mode = ARRAY_SIZE(alc260_modes), |
3713 | .channel_mode = alc260_modes, | 3895 | .channel_mode = alc260_modes, |
3714 | .input_mux = &alc260_fujitsu_capture_source, | 3896 | .num_mux_defs = ARRAY_SIZE(alc260_fujitsu_capture_sources), |
3897 | .input_mux = alc260_fujitsu_capture_sources, | ||
3715 | }, | 3898 | }, |
3716 | [ALC260_ACER] = { | 3899 | [ALC260_ACER] = { |
3717 | .mixers = { alc260_acer_mixer, | 3900 | .mixers = { alc260_acer_mixer, |
@@ -3723,7 +3906,8 @@ static struct alc_config_preset alc260_presets[] = { | |||
3723 | .adc_nids = alc260_dual_adc_nids, | 3906 | .adc_nids = alc260_dual_adc_nids, |
3724 | .num_channel_mode = ARRAY_SIZE(alc260_modes), | 3907 | .num_channel_mode = ARRAY_SIZE(alc260_modes), |
3725 | .channel_mode = alc260_modes, | 3908 | .channel_mode = alc260_modes, |
3726 | .input_mux = &alc260_acer_capture_source, | 3909 | .num_mux_defs = ARRAY_SIZE(alc260_acer_capture_sources), |
3910 | .input_mux = alc260_acer_capture_sources, | ||
3727 | }, | 3911 | }, |
3728 | #ifdef CONFIG_SND_DEBUG | 3912 | #ifdef CONFIG_SND_DEBUG |
3729 | [ALC260_TEST] = { | 3913 | [ALC260_TEST] = { |
@@ -3736,7 +3920,8 @@ static struct alc_config_preset alc260_presets[] = { | |||
3736 | .adc_nids = alc260_test_adc_nids, | 3920 | .adc_nids = alc260_test_adc_nids, |
3737 | .num_channel_mode = ARRAY_SIZE(alc260_modes), | 3921 | .num_channel_mode = ARRAY_SIZE(alc260_modes), |
3738 | .channel_mode = alc260_modes, | 3922 | .channel_mode = alc260_modes, |
3739 | .input_mux = &alc260_test_capture_source, | 3923 | .num_mux_defs = ARRAY_SIZE(alc260_test_capture_sources), |
3924 | .input_mux = alc260_test_capture_sources, | ||
3740 | }, | 3925 | }, |
3741 | #endif | 3926 | #endif |
3742 | }; | 3927 | }; |
@@ -3828,7 +4013,6 @@ static struct hda_input_mux alc882_capture_source = { | |||
3828 | { "CD", 0x4 }, | 4013 | { "CD", 0x4 }, |
3829 | }, | 4014 | }, |
3830 | }; | 4015 | }; |
3831 | |||
3832 | #define alc882_mux_enum_info alc_mux_enum_info | 4016 | #define alc882_mux_enum_info alc_mux_enum_info |
3833 | #define alc882_mux_enum_get alc_mux_enum_get | 4017 | #define alc882_mux_enum_get alc_mux_enum_get |
3834 | 4018 | ||
@@ -4730,6 +4914,7 @@ static int alc262_parse_auto_config(struct hda_codec *codec) | |||
4730 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 4914 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; |
4731 | 4915 | ||
4732 | spec->init_verbs[spec->num_init_verbs++] = alc262_volume_init_verbs; | 4916 | spec->init_verbs[spec->num_init_verbs++] = alc262_volume_init_verbs; |
4917 | spec->num_mux_defs = 1; | ||
4733 | spec->input_mux = &spec->private_imux; | 4918 | spec->input_mux = &spec->private_imux; |
4734 | 4919 | ||
4735 | return 1; | 4920 | return 1; |
@@ -5406,6 +5591,7 @@ static int alc861_parse_auto_config(struct hda_codec *codec) | |||
5406 | 5591 | ||
5407 | spec->init_verbs[spec->num_init_verbs++] = alc861_auto_init_verbs; | 5592 | spec->init_verbs[spec->num_init_verbs++] = alc861_auto_init_verbs; |
5408 | 5593 | ||
5594 | spec->num_mux_defs = 1; | ||
5409 | spec->input_mux = &spec->private_imux; | 5595 | spec->input_mux = &spec->private_imux; |
5410 | 5596 | ||
5411 | spec->adc_nids = alc861_adc_nids; | 5597 | spec->adc_nids = alc861_adc_nids; |
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index b56ca4019392..abe9493f0a2c 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -534,6 +534,22 @@ static int stac92xx_build_pcms(struct hda_codec *codec) | |||
534 | return 0; | 534 | return 0; |
535 | } | 535 | } |
536 | 536 | ||
537 | static unsigned int stac92xx_get_vref(struct hda_codec *codec, hda_nid_t nid) | ||
538 | { | ||
539 | unsigned int pincap = snd_hda_param_read(codec, nid, | ||
540 | AC_PAR_PIN_CAP); | ||
541 | pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT; | ||
542 | if (pincap & AC_PINCAP_VREF_100) | ||
543 | return AC_PINCTL_VREF_100; | ||
544 | if (pincap & AC_PINCAP_VREF_80) | ||
545 | return AC_PINCTL_VREF_80; | ||
546 | if (pincap & AC_PINCAP_VREF_50) | ||
547 | return AC_PINCTL_VREF_50; | ||
548 | if (pincap & AC_PINCAP_VREF_GRD) | ||
549 | return AC_PINCTL_VREF_GRD; | ||
550 | return 0; | ||
551 | } | ||
552 | |||
537 | static void stac92xx_auto_set_pinctl(struct hda_codec *codec, hda_nid_t nid, int pin_type) | 553 | static void stac92xx_auto_set_pinctl(struct hda_codec *codec, hda_nid_t nid, int pin_type) |
538 | 554 | ||
539 | { | 555 | { |
@@ -571,9 +587,12 @@ static int stac92xx_io_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ | |||
571 | 587 | ||
572 | if (val) | 588 | if (val) |
573 | stac92xx_auto_set_pinctl(codec, nid, AC_PINCTL_OUT_EN); | 589 | stac92xx_auto_set_pinctl(codec, nid, AC_PINCTL_OUT_EN); |
574 | else | 590 | else { |
575 | stac92xx_auto_set_pinctl(codec, nid, AC_PINCTL_IN_EN); | 591 | unsigned int pinctl = AC_PINCTL_IN_EN; |
576 | 592 | if (io_idx) /* set VREF for mic */ | |
593 | pinctl |= stac92xx_get_vref(codec, nid); | ||
594 | stac92xx_auto_set_pinctl(codec, nid, pinctl); | ||
595 | } | ||
577 | return 1; | 596 | return 1; |
578 | } | 597 | } |
579 | 598 | ||
@@ -767,13 +786,8 @@ static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec, struct auto_pin | |||
767 | return 0; | 786 | return 0; |
768 | 787 | ||
769 | wid_caps = get_wcaps(codec, pin); | 788 | wid_caps = get_wcaps(codec, pin); |
770 | if (wid_caps & AC_WCAP_UNSOL_CAP) { | 789 | if (wid_caps & AC_WCAP_UNSOL_CAP) |
771 | /* Enable unsolicited responses on the HP widget */ | ||
772 | snd_hda_codec_write(codec, pin, 0, | ||
773 | AC_VERB_SET_UNSOLICITED_ENABLE, | ||
774 | STAC_UNSOL_ENABLE); | ||
775 | spec->hp_detect = 1; | 790 | spec->hp_detect = 1; |
776 | } | ||
777 | 791 | ||
778 | nid = snd_hda_codec_read(codec, pin, 0, AC_VERB_GET_CONNECT_LIST, 0) & 0xff; | 792 | nid = snd_hda_codec_read(codec, pin, 0, AC_VERB_GET_CONNECT_LIST, 0) & 0xff; |
779 | for (i = 0; i < cfg->line_outs; i++) { | 793 | for (i = 0; i < cfg->line_outs; i++) { |
@@ -896,13 +910,8 @@ static int stac9200_auto_create_hp_ctls(struct hda_codec *codec, | |||
896 | return 0; | 910 | return 0; |
897 | 911 | ||
898 | wid_caps = get_wcaps(codec, pin); | 912 | wid_caps = get_wcaps(codec, pin); |
899 | if (wid_caps & AC_WCAP_UNSOL_CAP) { | 913 | if (wid_caps & AC_WCAP_UNSOL_CAP) |
900 | /* Enable unsolicited responses on the HP widget */ | ||
901 | snd_hda_codec_write(codec, pin, 0, | ||
902 | AC_VERB_SET_UNSOLICITED_ENABLE, | ||
903 | STAC_UNSOL_ENABLE); | ||
904 | spec->hp_detect = 1; | 914 | spec->hp_detect = 1; |
905 | } | ||
906 | 915 | ||
907 | return 0; | 916 | return 0; |
908 | } | 917 | } |
@@ -944,6 +953,10 @@ static int stac92xx_init(struct hda_codec *codec) | |||
944 | 953 | ||
945 | /* set up pins */ | 954 | /* set up pins */ |
946 | if (spec->hp_detect) { | 955 | if (spec->hp_detect) { |
956 | /* Enable unsolicited responses on the HP widget */ | ||
957 | snd_hda_codec_write(codec, cfg->hp_pin, 0, | ||
958 | AC_VERB_SET_UNSOLICITED_ENABLE, | ||
959 | STAC_UNSOL_ENABLE); | ||
947 | /* fake event to set up pins */ | 960 | /* fake event to set up pins */ |
948 | codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26); | 961 | codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26); |
949 | } else { | 962 | } else { |
@@ -951,9 +964,13 @@ static int stac92xx_init(struct hda_codec *codec) | |||
951 | stac92xx_auto_init_hp_out(codec); | 964 | stac92xx_auto_init_hp_out(codec); |
952 | } | 965 | } |
953 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 966 | for (i = 0; i < AUTO_PIN_LAST; i++) { |
954 | if (cfg->input_pins[i]) | 967 | hda_nid_t nid = cfg->input_pins[i]; |
955 | stac92xx_auto_set_pinctl(codec, cfg->input_pins[i], | 968 | if (nid) { |
956 | AC_PINCTL_IN_EN); | 969 | unsigned int pinctl = AC_PINCTL_IN_EN; |
970 | if (i == AUTO_PIN_MIC || i == AUTO_PIN_FRONT_MIC) | ||
971 | pinctl |= stac92xx_get_vref(codec, nid); | ||
972 | stac92xx_auto_set_pinctl(codec, nid, pinctl); | ||
973 | } | ||
957 | } | 974 | } |
958 | if (cfg->dig_out_pin) | 975 | if (cfg->dig_out_pin) |
959 | stac92xx_auto_set_pinctl(codec, cfg->dig_out_pin, | 976 | stac92xx_auto_set_pinctl(codec, cfg->dig_out_pin, |
diff --git a/sound/pci/ice1712/aureon.c b/sound/pci/ice1712/aureon.c index 7e6608b14abc..336dc489aee1 100644 --- a/sound/pci/ice1712/aureon.c +++ b/sound/pci/ice1712/aureon.c | |||
@@ -87,7 +87,151 @@ | |||
87 | #define CS8415_C_BUFFER 0x20 | 87 | #define CS8415_C_BUFFER 0x20 |
88 | #define CS8415_ID 0x7F | 88 | #define CS8415_ID 0x7F |
89 | 89 | ||
90 | static void aureon_ac97_write(struct snd_ice1712 *ice, unsigned short reg, unsigned short val) { | 90 | /* PCA9554 registers */ |
91 | #define PCA9554_DEV 0x40 /* I2C device address */ | ||
92 | #define PCA9554_IN 0x00 /* input port */ | ||
93 | #define PCA9554_OUT 0x01 /* output port */ | ||
94 | #define PCA9554_INVERT 0x02 /* input invert */ | ||
95 | #define PCA9554_DIR 0x03 /* port directions */ | ||
96 | |||
97 | /* | ||
98 | * Aureon Universe additional controls using PCA9554 | ||
99 | */ | ||
100 | |||
101 | /* | ||
102 | * Send data to pca9554 | ||
103 | */ | ||
104 | static void aureon_pca9554_write(struct snd_ice1712 *ice, unsigned char reg, | ||
105 | unsigned char data) | ||
106 | { | ||
107 | unsigned int tmp; | ||
108 | int i, j; | ||
109 | unsigned char dev = PCA9554_DEV; /* ID 0100000, write */ | ||
110 | unsigned char val = 0; | ||
111 | |||
112 | tmp = snd_ice1712_gpio_read(ice); | ||
113 | |||
114 | snd_ice1712_gpio_set_mask(ice, ~(AUREON_SPI_MOSI|AUREON_SPI_CLK| | ||
115 | AUREON_WM_RW|AUREON_WM_CS| | ||
116 | AUREON_CS8415_CS)); | ||
117 | tmp |= AUREON_WM_RW; | ||
118 | tmp |= AUREON_CS8415_CS | AUREON_WM_CS; /* disable SPI devices */ | ||
119 | |||
120 | tmp &= ~AUREON_SPI_MOSI; | ||
121 | tmp &= ~AUREON_SPI_CLK; | ||
122 | snd_ice1712_gpio_write(ice, tmp); | ||
123 | udelay(50); | ||
124 | |||
125 | /* | ||
126 | * send i2c stop condition and start condition | ||
127 | * to obtain sane state | ||
128 | */ | ||
129 | tmp |= AUREON_SPI_CLK; | ||
130 | snd_ice1712_gpio_write(ice, tmp); | ||
131 | udelay(50); | ||
132 | tmp |= AUREON_SPI_MOSI; | ||
133 | snd_ice1712_gpio_write(ice, tmp); | ||
134 | udelay(100); | ||
135 | tmp &= ~AUREON_SPI_MOSI; | ||
136 | snd_ice1712_gpio_write(ice, tmp); | ||
137 | udelay(50); | ||
138 | tmp &= ~AUREON_SPI_CLK; | ||
139 | snd_ice1712_gpio_write(ice, tmp); | ||
140 | udelay(100); | ||
141 | /* | ||
142 | * send device address, command and value, | ||
143 | * skipping ack cycles inbetween | ||
144 | */ | ||
145 | for (j = 0; j < 3; j++) { | ||
146 | switch(j) { | ||
147 | case 0: val = dev; break; | ||
148 | case 1: val = reg; break; | ||
149 | case 2: val = data; break; | ||
150 | } | ||
151 | for (i = 7; i >= 0; i--) { | ||
152 | tmp &= ~AUREON_SPI_CLK; | ||
153 | snd_ice1712_gpio_write(ice, tmp); | ||
154 | udelay(40); | ||
155 | if (val & (1 << i)) | ||
156 | tmp |= AUREON_SPI_MOSI; | ||
157 | else | ||
158 | tmp &= ~AUREON_SPI_MOSI; | ||
159 | snd_ice1712_gpio_write(ice, tmp); | ||
160 | udelay(40); | ||
161 | tmp |= AUREON_SPI_CLK; | ||
162 | snd_ice1712_gpio_write(ice, tmp); | ||
163 | udelay(40); | ||
164 | } | ||
165 | tmp &= ~AUREON_SPI_CLK; | ||
166 | snd_ice1712_gpio_write(ice, tmp); | ||
167 | udelay(40); | ||
168 | tmp |= AUREON_SPI_CLK; | ||
169 | snd_ice1712_gpio_write(ice, tmp); | ||
170 | udelay(40); | ||
171 | tmp &= ~AUREON_SPI_CLK; | ||
172 | snd_ice1712_gpio_write(ice, tmp); | ||
173 | udelay(40); | ||
174 | } | ||
175 | tmp &= ~AUREON_SPI_CLK; | ||
176 | snd_ice1712_gpio_write(ice, tmp); | ||
177 | udelay(40); | ||
178 | tmp &= ~AUREON_SPI_MOSI; | ||
179 | snd_ice1712_gpio_write(ice, tmp); | ||
180 | udelay(40); | ||
181 | tmp |= AUREON_SPI_CLK; | ||
182 | snd_ice1712_gpio_write(ice, tmp); | ||
183 | udelay(50); | ||
184 | tmp |= AUREON_SPI_MOSI; | ||
185 | snd_ice1712_gpio_write(ice, tmp); | ||
186 | udelay(100); | ||
187 | } | ||
188 | |||
189 | static int aureon_universe_inmux_info(struct snd_kcontrol *kcontrol, | ||
190 | struct snd_ctl_elem_info *uinfo) | ||
191 | { | ||
192 | char *texts[3] = {"Internal Aux", "Wavetable", "Rear Line-In"}; | ||
193 | |||
194 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
195 | uinfo->count = 1; | ||
196 | uinfo->value.enumerated.items = 3; | ||
197 | if(uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
198 | uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; | ||
199 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); | ||
200 | return 0; | ||
201 | } | ||
202 | |||
203 | static int aureon_universe_inmux_get(struct snd_kcontrol *kcontrol, | ||
204 | struct snd_ctl_elem_value *ucontrol) | ||
205 | { | ||
206 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
207 | ucontrol->value.integer.value[0] = ice->spec.aureon.pca9554_out; | ||
208 | return 0; | ||
209 | } | ||
210 | |||
211 | static int aureon_universe_inmux_put(struct snd_kcontrol *kcontrol, | ||
212 | struct snd_ctl_elem_value *ucontrol) | ||
213 | { | ||
214 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
215 | unsigned char oval, nval; | ||
216 | int change; | ||
217 | |||
218 | snd_ice1712_save_gpio_status(ice); | ||
219 | |||
220 | oval = ice->spec.aureon.pca9554_out; | ||
221 | nval = ucontrol->value.integer.value[0]; | ||
222 | if ((change = (oval != nval))) { | ||
223 | aureon_pca9554_write(ice, PCA9554_OUT, nval); | ||
224 | ice->spec.aureon.pca9554_out = nval; | ||
225 | } | ||
226 | snd_ice1712_restore_gpio_status(ice); | ||
227 | |||
228 | return change; | ||
229 | } | ||
230 | |||
231 | |||
232 | static void aureon_ac97_write(struct snd_ice1712 *ice, unsigned short reg, | ||
233 | unsigned short val) | ||
234 | { | ||
91 | unsigned int tmp; | 235 | unsigned int tmp; |
92 | 236 | ||
93 | /* Send address to XILINX chip */ | 237 | /* Send address to XILINX chip */ |
@@ -146,7 +290,8 @@ static unsigned short aureon_ac97_read(struct snd_ice1712 *ice, unsigned short r | |||
146 | /* | 290 | /* |
147 | * Initialize STAC9744 chip | 291 | * Initialize STAC9744 chip |
148 | */ | 292 | */ |
149 | static int aureon_ac97_init (struct snd_ice1712 *ice) { | 293 | static int aureon_ac97_init (struct snd_ice1712 *ice) |
294 | { | ||
150 | int i; | 295 | int i; |
151 | static unsigned short ac97_defaults[] = { | 296 | static unsigned short ac97_defaults[] = { |
152 | 0x00, 0x9640, | 297 | 0x00, 0x9640, |
@@ -1598,7 +1743,15 @@ static struct snd_kcontrol_new universe_ac97_controls[] __devinitdata = { | |||
1598 | .get = aureon_ac97_vol_get, | 1743 | .get = aureon_ac97_vol_get, |
1599 | .put = aureon_ac97_vol_put, | 1744 | .put = aureon_ac97_vol_put, |
1600 | .private_value = AC97_VIDEO|AUREON_AC97_STEREO | 1745 | .private_value = AC97_VIDEO|AUREON_AC97_STEREO |
1601 | } | 1746 | }, |
1747 | { | ||
1748 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1749 | .name = "Aux Source", | ||
1750 | .info = aureon_universe_inmux_info, | ||
1751 | .get = aureon_universe_inmux_get, | ||
1752 | .put = aureon_universe_inmux_put | ||
1753 | } | ||
1754 | |||
1602 | }; | 1755 | }; |
1603 | 1756 | ||
1604 | 1757 | ||
@@ -1856,6 +2009,10 @@ static int __devinit aureon_init(struct snd_ice1712 *ice) | |||
1856 | } | 2009 | } |
1857 | 2010 | ||
1858 | snd_ice1712_restore_gpio_status(ice); | 2011 | snd_ice1712_restore_gpio_status(ice); |
2012 | |||
2013 | /* initialize PCA9554 pin directions & set default input*/ | ||
2014 | aureon_pca9554_write(ice, PCA9554_DIR, 0x00); | ||
2015 | aureon_pca9554_write(ice, PCA9554_OUT, 0x00); /* internal AUX */ | ||
1859 | 2016 | ||
1860 | ice->spec.aureon.master[0] = WM_VOL_MUTE; | 2017 | ice->spec.aureon.master[0] = WM_VOL_MUTE; |
1861 | ice->spec.aureon.master[1] = WM_VOL_MUTE; | 2018 | ice->spec.aureon.master[1] = WM_VOL_MUTE; |
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index b88eeba2f5d1..32f8415558a5 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c | |||
@@ -2402,7 +2402,7 @@ static int __devinit snd_ice1712_chip_init(struct snd_ice1712 *ice) | |||
2402 | if (ice->eeprom.subvendor == ICE1712_SUBDEVICE_DMX6FIRE && !ice->dxr_enable) { | 2402 | if (ice->eeprom.subvendor == ICE1712_SUBDEVICE_DMX6FIRE && !ice->dxr_enable) { |
2403 | /* Limit active ADCs and DACs to 6; */ | 2403 | /* Limit active ADCs and DACs to 6; */ |
2404 | /* Note: DXR extension not supported */ | 2404 | /* Note: DXR extension not supported */ |
2405 | pci_write_config_byte(ice->pci, 0x60, 0x0a); | 2405 | pci_write_config_byte(ice->pci, 0x60, 0x2a); |
2406 | } else { | 2406 | } else { |
2407 | pci_write_config_byte(ice->pci, 0x60, ice->eeprom.data[ICE_EEP1_CODEC]); | 2407 | pci_write_config_byte(ice->pci, 0x60, ice->eeprom.data[ICE_EEP1_CODEC]); |
2408 | } | 2408 | } |
diff --git a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h index f9b22d4a3932..053f8e56fd68 100644 --- a/sound/pci/ice1712/ice1712.h +++ b/sound/pci/ice1712/ice1712.h | |||
@@ -373,6 +373,7 @@ struct snd_ice1712 { | |||
373 | unsigned int cs8415_mux; | 373 | unsigned int cs8415_mux; |
374 | unsigned short master[2]; | 374 | unsigned short master[2]; |
375 | unsigned short vol[8]; | 375 | unsigned short vol[8]; |
376 | unsigned char pca9554_out; | ||
376 | } aureon; | 377 | } aureon; |
377 | /* AC97 register cache for Phase28 */ | 378 | /* AC97 register cache for Phase28 */ |
378 | struct phase28_spec { | 379 | struct phase28_spec { |
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index 44393e190929..9c90d901e6b9 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c | |||
@@ -831,8 +831,8 @@ struct snd_m3 { | |||
831 | struct snd_pcm *pcm; | 831 | struct snd_pcm *pcm; |
832 | 832 | ||
833 | struct pci_dev *pci; | 833 | struct pci_dev *pci; |
834 | struct m3_quirk *quirk; | 834 | const struct m3_quirk *quirk; |
835 | struct m3_hv_quirk *hv_quirk; | 835 | const struct m3_hv_quirk *hv_quirk; |
836 | 836 | ||
837 | int dacs_active; | 837 | int dacs_active; |
838 | int timer_users; | 838 | int timer_users; |
@@ -892,7 +892,7 @@ static struct pci_device_id snd_m3_ids[] = { | |||
892 | 892 | ||
893 | MODULE_DEVICE_TABLE(pci, snd_m3_ids); | 893 | MODULE_DEVICE_TABLE(pci, snd_m3_ids); |
894 | 894 | ||
895 | static struct m3_quirk m3_quirk_list[] = { | 895 | static const struct m3_quirk m3_quirk_list[] = { |
896 | /* panasonic CF-28 "toughbook" */ | 896 | /* panasonic CF-28 "toughbook" */ |
897 | { | 897 | { |
898 | .name = "Panasonic CF-28", | 898 | .name = "Panasonic CF-28", |
@@ -950,7 +950,7 @@ static struct m3_quirk m3_quirk_list[] = { | |||
950 | }; | 950 | }; |
951 | 951 | ||
952 | /* These values came from the Windows driver. */ | 952 | /* These values came from the Windows driver. */ |
953 | static struct m3_hv_quirk m3_hv_quirk_list[] = { | 953 | static const struct m3_hv_quirk m3_hv_quirk_list[] = { |
954 | /* Allegro chips */ | 954 | /* Allegro chips */ |
955 | { 0x125D, 0x1988, 0x0E11, 0x002E, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, | 955 | { 0x125D, 0x1988, 0x0E11, 0x002E, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, |
956 | { 0x125D, 0x1988, 0x0E11, 0x0094, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, | 956 | { 0x125D, 0x1988, 0x0E11, 0x0094, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, |
@@ -1361,7 +1361,7 @@ static void snd_m3_pcm_setup2(struct snd_m3 *chip, struct m3_dma *s, | |||
1361 | } | 1361 | } |
1362 | 1362 | ||
1363 | 1363 | ||
1364 | static struct play_vals { | 1364 | static const struct play_vals { |
1365 | u16 addr, val; | 1365 | u16 addr, val; |
1366 | } pv[] = { | 1366 | } pv[] = { |
1367 | {CDATA_LEFT_VOLUME, ARB_VOLUME}, | 1367 | {CDATA_LEFT_VOLUME, ARB_VOLUME}, |
@@ -1428,7 +1428,7 @@ snd_m3_playback_setup(struct snd_m3 *chip, struct m3_dma *s, | |||
1428 | /* | 1428 | /* |
1429 | * Native record driver | 1429 | * Native record driver |
1430 | */ | 1430 | */ |
1431 | static struct rec_vals { | 1431 | static const struct rec_vals { |
1432 | u16 addr, val; | 1432 | u16 addr, val; |
1433 | } rv[] = { | 1433 | } rv[] = { |
1434 | {CDATA_LEFT_VOLUME, ARB_VOLUME}, | 1434 | {CDATA_LEFT_VOLUME, ARB_VOLUME}, |
@@ -1598,12 +1598,26 @@ static void snd_m3_update_ptr(struct snd_m3 *chip, struct m3_dma *s) | |||
1598 | if (! s->running) | 1598 | if (! s->running) |
1599 | return; | 1599 | return; |
1600 | 1600 | ||
1601 | hwptr = snd_m3_get_pointer(chip, s, subs) % s->dma_size; | 1601 | hwptr = snd_m3_get_pointer(chip, s, subs); |
1602 | diff = (s->dma_size + hwptr - s->hwptr) % s->dma_size; | 1602 | |
1603 | /* try to avoid expensive modulo divisions */ | ||
1604 | if (hwptr >= s->dma_size) | ||
1605 | hwptr %= s->dma_size; | ||
1606 | |||
1607 | diff = s->dma_size + hwptr - s->hwptr; | ||
1608 | if (diff >= s->dma_size) | ||
1609 | diff %= s->dma_size; | ||
1610 | |||
1603 | s->hwptr = hwptr; | 1611 | s->hwptr = hwptr; |
1604 | s->count += diff; | 1612 | s->count += diff; |
1613 | |||
1605 | if (s->count >= (signed)s->period_size) { | 1614 | if (s->count >= (signed)s->period_size) { |
1606 | s->count %= s->period_size; | 1615 | |
1616 | if (s->count < 2 * (signed)s->period_size) | ||
1617 | s->count -= (signed)s->period_size; | ||
1618 | else | ||
1619 | s->count %= s->period_size; | ||
1620 | |||
1607 | spin_unlock(&chip->reg_lock); | 1621 | spin_unlock(&chip->reg_lock); |
1608 | snd_pcm_period_elapsed(subs); | 1622 | snd_pcm_period_elapsed(subs); |
1609 | spin_lock(&chip->reg_lock); | 1623 | spin_lock(&chip->reg_lock); |
@@ -1942,6 +1956,7 @@ static int snd_m3_ac97_wait(struct snd_m3 *chip) | |||
1942 | do { | 1956 | do { |
1943 | if (! (snd_m3_inb(chip, 0x30) & 1)) | 1957 | if (! (snd_m3_inb(chip, 0x30) & 1)) |
1944 | return 0; | 1958 | return 0; |
1959 | cpu_relax(); | ||
1945 | } while (i-- > 0); | 1960 | } while (i-- > 0); |
1946 | 1961 | ||
1947 | snd_printk(KERN_ERR "ac97 serial bus busy\n"); | 1962 | snd_printk(KERN_ERR "ac97 serial bus busy\n"); |
@@ -1953,16 +1968,18 @@ snd_m3_ac97_read(struct snd_ac97 *ac97, unsigned short reg) | |||
1953 | { | 1968 | { |
1954 | struct snd_m3 *chip = ac97->private_data; | 1969 | struct snd_m3 *chip = ac97->private_data; |
1955 | unsigned long flags; | 1970 | unsigned long flags; |
1956 | unsigned short data; | 1971 | unsigned short data = 0xffff; |
1957 | 1972 | ||
1958 | if (snd_m3_ac97_wait(chip)) | 1973 | if (snd_m3_ac97_wait(chip)) |
1959 | return 0xffff; | 1974 | goto fail; |
1960 | spin_lock_irqsave(&chip->ac97_lock, flags); | 1975 | spin_lock_irqsave(&chip->ac97_lock, flags); |
1961 | snd_m3_outb(chip, 0x80 | (reg & 0x7f), CODEC_COMMAND); | 1976 | snd_m3_outb(chip, 0x80 | (reg & 0x7f), CODEC_COMMAND); |
1962 | if (snd_m3_ac97_wait(chip)) | 1977 | if (snd_m3_ac97_wait(chip)) |
1963 | return 0xffff; | 1978 | goto fail_unlock; |
1964 | data = snd_m3_inw(chip, CODEC_DATA); | 1979 | data = snd_m3_inw(chip, CODEC_DATA); |
1980 | fail_unlock: | ||
1965 | spin_unlock_irqrestore(&chip->ac97_lock, flags); | 1981 | spin_unlock_irqrestore(&chip->ac97_lock, flags); |
1982 | fail: | ||
1966 | return data; | 1983 | return data; |
1967 | } | 1984 | } |
1968 | 1985 | ||
@@ -2121,7 +2138,7 @@ static int __devinit snd_m3_mixer(struct snd_m3 *chip) | |||
2121 | * DSP Code images | 2138 | * DSP Code images |
2122 | */ | 2139 | */ |
2123 | 2140 | ||
2124 | static u16 assp_kernel_image[] __devinitdata = { | 2141 | static const u16 assp_kernel_image[] __devinitdata = { |
2125 | 0x7980, 0x0030, 0x7980, 0x03B4, 0x7980, 0x03B4, 0x7980, 0x00FB, 0x7980, 0x00DD, 0x7980, 0x03B4, | 2142 | 0x7980, 0x0030, 0x7980, 0x03B4, 0x7980, 0x03B4, 0x7980, 0x00FB, 0x7980, 0x00DD, 0x7980, 0x03B4, |
2126 | 0x7980, 0x0332, 0x7980, 0x0287, 0x7980, 0x03B4, 0x7980, 0x03B4, 0x7980, 0x03B4, 0x7980, 0x03B4, | 2143 | 0x7980, 0x0332, 0x7980, 0x0287, 0x7980, 0x03B4, 0x7980, 0x03B4, 0x7980, 0x03B4, 0x7980, 0x03B4, |
2127 | 0x7980, 0x031A, 0x7980, 0x03B4, 0x7980, 0x022F, 0x7980, 0x03B4, 0x7980, 0x03B4, 0x7980, 0x03B4, | 2144 | 0x7980, 0x031A, 0x7980, 0x03B4, 0x7980, 0x022F, 0x7980, 0x03B4, 0x7980, 0x03B4, 0x7980, 0x03B4, |
@@ -2208,7 +2225,7 @@ static u16 assp_kernel_image[] __devinitdata = { | |||
2208 | * Mini sample rate converter code image | 2225 | * Mini sample rate converter code image |
2209 | * that is to be loaded at 0x400 on the DSP. | 2226 | * that is to be loaded at 0x400 on the DSP. |
2210 | */ | 2227 | */ |
2211 | static u16 assp_minisrc_image[] __devinitdata = { | 2228 | static const u16 assp_minisrc_image[] __devinitdata = { |
2212 | 2229 | ||
2213 | 0xBF80, 0x101E, 0x906E, 0x006E, 0x8B88, 0x6980, 0xEF88, 0x906F, 0x0D6F, 0x6900, 0xEB08, 0x0412, | 2230 | 0xBF80, 0x101E, 0x906E, 0x006E, 0x8B88, 0x6980, 0xEF88, 0x906F, 0x0D6F, 0x6900, 0xEB08, 0x0412, |
2214 | 0xBC20, 0x696E, 0xB801, 0x906E, 0x7980, 0x0403, 0xB90E, 0x8807, 0xBE43, 0xBF01, 0xBE47, 0xBE41, | 2231 | 0xBC20, 0x696E, 0xB801, 0x906E, 0x7980, 0x0403, 0xB90E, 0x8807, 0xBE43, 0xBF01, 0xBE47, 0xBE41, |
@@ -2251,7 +2268,7 @@ static u16 assp_minisrc_image[] __devinitdata = { | |||
2251 | */ | 2268 | */ |
2252 | 2269 | ||
2253 | #define MINISRC_LPF_LEN 10 | 2270 | #define MINISRC_LPF_LEN 10 |
2254 | static u16 minisrc_lpf[MINISRC_LPF_LEN] __devinitdata = { | 2271 | static const u16 minisrc_lpf[MINISRC_LPF_LEN] __devinitdata = { |
2255 | 0X0743, 0X1104, 0X0A4C, 0XF88D, 0X242C, | 2272 | 0X0743, 0X1104, 0X0A4C, 0XF88D, 0X242C, |
2256 | 0X1023, 0X1AA9, 0X0B60, 0XEFDD, 0X186F | 2273 | 0X1023, 0X1AA9, 0X0B60, 0XEFDD, 0X186F |
2257 | }; | 2274 | }; |
@@ -2358,7 +2375,7 @@ static int __devinit snd_m3_assp_client_init(struct snd_m3 *chip, struct m3_dma | |||
2358 | */ | 2375 | */ |
2359 | 2376 | ||
2360 | /* | 2377 | /* |
2361 | * align instance address to 256 bytes so that it's | 2378 | * align instance address to 256 bytes so that its |
2362 | * shifted list address is aligned. | 2379 | * shifted list address is aligned. |
2363 | * list address = (mem address >> 1) >> 7; | 2380 | * list address = (mem address >> 1) >> 7; |
2364 | */ | 2381 | */ |
@@ -2647,8 +2664,8 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci, | |||
2647 | { | 2664 | { |
2648 | struct snd_m3 *chip; | 2665 | struct snd_m3 *chip; |
2649 | int i, err; | 2666 | int i, err; |
2650 | struct m3_quirk *quirk; | 2667 | const struct m3_quirk *quirk; |
2651 | struct m3_hv_quirk *hv_quirk; | 2668 | const struct m3_hv_quirk *hv_quirk; |
2652 | static struct snd_device_ops ops = { | 2669 | static struct snd_device_ops ops = { |
2653 | .dev_free = snd_m3_dev_free, | 2670 | .dev_free = snd_m3_dev_free, |
2654 | }; | 2671 | }; |
@@ -2843,12 +2860,12 @@ snd_m3_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) | |||
2843 | } | 2860 | } |
2844 | 2861 | ||
2845 | #if 0 /* TODO: not supported yet */ | 2862 | #if 0 /* TODO: not supported yet */ |
2846 | /* TODO enable midi irq and i/o */ | 2863 | /* TODO enable MIDI IRQ and I/O */ |
2847 | err = snd_mpu401_uart_new(chip->card, 0, MPU401_HW_MPU401, | 2864 | err = snd_mpu401_uart_new(chip->card, 0, MPU401_HW_MPU401, |
2848 | chip->iobase + MPU401_DATA_PORT, 1, | 2865 | chip->iobase + MPU401_DATA_PORT, 1, |
2849 | chip->irq, 0, &chip->rmidi); | 2866 | chip->irq, 0, &chip->rmidi); |
2850 | if (err < 0) | 2867 | if (err < 0) |
2851 | printk(KERN_WARNING "maestro3: no midi support.\n"); | 2868 | printk(KERN_WARNING "maestro3: no MIDI support.\n"); |
2852 | #endif | 2869 | #endif |
2853 | 2870 | ||
2854 | pci_set_drvdata(pci, card); | 2871 | pci_set_drvdata(pci, card); |
diff --git a/sound/pci/pcxhr/pcxhr_core.c b/sound/pci/pcxhr/pcxhr_core.c index fdc652c6992d..c40f59062684 100644 --- a/sound/pci/pcxhr/pcxhr_core.c +++ b/sound/pci/pcxhr/pcxhr_core.c | |||
@@ -274,12 +274,9 @@ int pcxhr_load_xilinx_binary(struct pcxhr_mgr *mgr, const struct firmware *xilin | |||
274 | 274 | ||
275 | /* test first xilinx */ | 275 | /* test first xilinx */ |
276 | chipsc = PCXHR_INPL(mgr, PCXHR_PLX_CHIPSC); | 276 | chipsc = PCXHR_INPL(mgr, PCXHR_PLX_CHIPSC); |
277 | if (!second) { | 277 | /* REV01 cards do not support the PCXHR_CHIPSC_GPI_USERI bit anymore */ |
278 | if (chipsc & PCXHR_CHIPSC_GPI_USERI) { | 278 | /* this bit will always be 1; no possibility to test presence of first xilinx */ |
279 | snd_printdd("no need to load first xilinx\n"); | 279 | if(second) { |
280 | return 0; /* first xilinx is already present and cannot be reset */ | ||
281 | } | ||
282 | } else { | ||
283 | if ((chipsc & PCXHR_CHIPSC_GPI_USERI) == 0) { | 280 | if ((chipsc & PCXHR_CHIPSC_GPI_USERI) == 0) { |
284 | snd_printk(KERN_ERR "error loading first xilinx\n"); | 281 | snd_printk(KERN_ERR "error loading first xilinx\n"); |
285 | return -EINVAL; | 282 | return -EINVAL; |
diff --git a/sound/pci/riptide/Makefile b/sound/pci/riptide/Makefile new file mode 100644 index 000000000000..dcd2e64e4818 --- /dev/null +++ b/sound/pci/riptide/Makefile | |||
@@ -0,0 +1,3 @@ | |||
1 | snd-riptide-objs := riptide.o | ||
2 | |||
3 | obj-$(CONFIG_SND_RIPTIDE) += snd-riptide.o | ||
diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c new file mode 100644 index 000000000000..f148ee434a6b --- /dev/null +++ b/sound/pci/riptide/riptide.c | |||
@@ -0,0 +1,2223 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant Riptide Soundchip | ||
3 | * | ||
4 | * Copyright (c) 2004 Peter Gruber <nokos@gmx.net> | ||
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 as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | * | ||
20 | */ | ||
21 | /* | ||
22 | History: | ||
23 | - 02/15/2004 first release | ||
24 | |||
25 | This Driver is based on the OSS Driver version from Linuxant (riptide-0.6lnxtbeta03111100) | ||
26 | credits from the original files: | ||
27 | |||
28 | MODULE NAME: cnxt_rt.h | ||
29 | AUTHOR: K. Lazarev (Transcribed by KNL) | ||
30 | HISTORY: Major Revision Date By | ||
31 | ----------------------------- -------- ----- | ||
32 | Created 02/1/2000 KNL | ||
33 | |||
34 | MODULE NAME: int_mdl.c | ||
35 | AUTHOR: Konstantin Lazarev (Transcribed by KNL) | ||
36 | HISTORY: Major Revision Date By | ||
37 | ----------------------------- -------- ----- | ||
38 | Created 10/01/99 KNL | ||
39 | |||
40 | MODULE NAME: riptide.h | ||
41 | AUTHOR: O. Druzhinin (Transcribed by OLD) | ||
42 | HISTORY: Major Revision Date By | ||
43 | ----------------------------- -------- ----- | ||
44 | Created 10/16/97 OLD | ||
45 | |||
46 | MODULE NAME: Rp_Cmdif.cpp | ||
47 | AUTHOR: O. Druzhinin (Transcribed by OLD) | ||
48 | K. Lazarev (Transcribed by KNL) | ||
49 | HISTORY: Major Revision Date By | ||
50 | ----------------------------- -------- ----- | ||
51 | Adopted from NT4 driver 6/22/99 OLD | ||
52 | Ported to Linux 9/01/99 KNL | ||
53 | |||
54 | MODULE NAME: rt_hw.c | ||
55 | AUTHOR: O. Druzhinin (Transcribed by OLD) | ||
56 | C. Lazarev (Transcribed by CNL) | ||
57 | HISTORY: Major Revision Date By | ||
58 | ----------------------------- -------- ----- | ||
59 | Created 11/18/97 OLD | ||
60 | Hardware functions for RipTide 11/24/97 CNL | ||
61 | (ES1) are coded | ||
62 | Hardware functions for RipTide 12/24/97 CNL | ||
63 | (A0) are coded | ||
64 | Hardware functions for RipTide 03/20/98 CNL | ||
65 | (A1) are coded | ||
66 | Boot loader is included 05/07/98 CNL | ||
67 | Redesigned for WDM 07/27/98 CNL | ||
68 | Redesigned for Linux 09/01/99 CNL | ||
69 | |||
70 | MODULE NAME: rt_hw.h | ||
71 | AUTHOR: C. Lazarev (Transcribed by CNL) | ||
72 | HISTORY: Major Revision Date By | ||
73 | ----------------------------- -------- ----- | ||
74 | Created 11/18/97 CNL | ||
75 | |||
76 | MODULE NAME: rt_mdl.c | ||
77 | AUTHOR: Konstantin Lazarev (Transcribed by KNL) | ||
78 | HISTORY: Major Revision Date By | ||
79 | ----------------------------- -------- ----- | ||
80 | Created 10/01/99 KNL | ||
81 | |||
82 | MODULE NAME: mixer.h | ||
83 | AUTHOR: K. Kenney | ||
84 | HISTORY: Major Revision Date By | ||
85 | ----------------------------- -------- ----- | ||
86 | Created from MS W95 Sample 11/28/95 KRS | ||
87 | RipTide 10/15/97 KRS | ||
88 | Adopted for Windows NT driver 01/20/98 CNL | ||
89 | */ | ||
90 | |||
91 | #include <sound/driver.h> | ||
92 | #include <linux/delay.h> | ||
93 | #include <linux/init.h> | ||
94 | #include <linux/interrupt.h> | ||
95 | #include <linux/pci.h> | ||
96 | #include <linux/slab.h> | ||
97 | #include <linux/wait.h> | ||
98 | #include <linux/gameport.h> | ||
99 | #include <linux/device.h> | ||
100 | #include <linux/firmware.h> | ||
101 | #include <asm/io.h> | ||
102 | #include <sound/core.h> | ||
103 | #include <sound/info.h> | ||
104 | #include <sound/control.h> | ||
105 | #include <sound/pcm.h> | ||
106 | #include <sound/pcm_params.h> | ||
107 | #include <sound/ac97_codec.h> | ||
108 | #include <sound/mpu401.h> | ||
109 | #include <sound/opl3.h> | ||
110 | #include <sound/initval.h> | ||
111 | |||
112 | #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) | ||
113 | #define SUPPORT_JOYSTICK 1 | ||
114 | #endif | ||
115 | |||
116 | MODULE_AUTHOR("Peter Gruber <nokos@gmx.net>"); | ||
117 | MODULE_DESCRIPTION("riptide"); | ||
118 | MODULE_LICENSE("GPL"); | ||
119 | MODULE_SUPPORTED_DEVICE("{{Conexant,Riptide}}"); | ||
120 | |||
121 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; | ||
122 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; | ||
123 | static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; | ||
124 | |||
125 | #ifdef SUPPORT_JOYSTICK | ||
126 | static int joystick_port[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS - 1)] = 0x200 }; | ||
127 | #endif | ||
128 | static int mpu_port[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS - 1)] = 0x330 }; | ||
129 | static int opl3_port[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS - 1)] = 0x388 }; | ||
130 | |||
131 | module_param_array(index, int, NULL, 0444); | ||
132 | MODULE_PARM_DESC(index, "Index value for Riptide soundcard."); | ||
133 | module_param_array(id, charp, NULL, 0444); | ||
134 | MODULE_PARM_DESC(id, "ID string for Riptide soundcard."); | ||
135 | module_param_array(enable, bool, NULL, 0444); | ||
136 | MODULE_PARM_DESC(enable, "Enable Riptide soundcard."); | ||
137 | #ifdef SUPPORT_JOYSTICK | ||
138 | module_param_array(joystick_port, int, NULL, 0444); | ||
139 | MODULE_PARM_DESC(joystick_port, "Joystick port # for Riptide soundcard."); | ||
140 | #endif | ||
141 | module_param_array(mpu_port, int, NULL, 0444); | ||
142 | MODULE_PARM_DESC(mpu_port, "MPU401 port # for Riptide driver."); | ||
143 | module_param_array(opl3_port, int, NULL, 0444); | ||
144 | MODULE_PARM_DESC(opl3_port, "OPL3 port # for Riptide driver."); | ||
145 | |||
146 | /* | ||
147 | */ | ||
148 | |||
149 | #define MPU401_HW_RIPTIDE MPU401_HW_MPU401 | ||
150 | #define OPL3_HW_RIPTIDE OPL3_HW_OPL3 | ||
151 | |||
152 | #define PCI_EXT_CapId 0x40 | ||
153 | #define PCI_EXT_NextCapPrt 0x41 | ||
154 | #define PCI_EXT_PWMC 0x42 | ||
155 | #define PCI_EXT_PWSCR 0x44 | ||
156 | #define PCI_EXT_Data00 0x46 | ||
157 | #define PCI_EXT_PMSCR_BSE 0x47 | ||
158 | #define PCI_EXT_SB_Base 0x48 | ||
159 | #define PCI_EXT_FM_Base 0x4a | ||
160 | #define PCI_EXT_MPU_Base 0x4C | ||
161 | #define PCI_EXT_Game_Base 0x4E | ||
162 | #define PCI_EXT_Legacy_Mask 0x50 | ||
163 | #define PCI_EXT_AsicRev 0x52 | ||
164 | #define PCI_EXT_Reserved3 0x53 | ||
165 | |||
166 | #define LEGACY_ENABLE_ALL 0x8000 /* legacy device options */ | ||
167 | #define LEGACY_ENABLE_SB 0x4000 | ||
168 | #define LEGACY_ENABLE_FM 0x2000 | ||
169 | #define LEGACY_ENABLE_MPU_INT 0x1000 | ||
170 | #define LEGACY_ENABLE_MPU 0x0800 | ||
171 | #define LEGACY_ENABLE_GAMEPORT 0x0400 | ||
172 | |||
173 | #define MAX_WRITE_RETRY 10 /* cmd interface limits */ | ||
174 | #define MAX_ERROR_COUNT 10 | ||
175 | #define CMDIF_TIMEOUT 500000 | ||
176 | #define RESET_TRIES 5 | ||
177 | |||
178 | #define READ_PORT_ULONG(p) inl((unsigned long)&(p)) | ||
179 | #define WRITE_PORT_ULONG(p,x) outl(x,(unsigned long)&(p)) | ||
180 | |||
181 | #define READ_AUDIO_CONTROL(p) READ_PORT_ULONG(p->audio_control) | ||
182 | #define WRITE_AUDIO_CONTROL(p,x) WRITE_PORT_ULONG(p->audio_control,x) | ||
183 | #define UMASK_AUDIO_CONTROL(p,x) WRITE_PORT_ULONG(p->audio_control,READ_PORT_ULONG(p->audio_control)|x) | ||
184 | #define MASK_AUDIO_CONTROL(p,x) WRITE_PORT_ULONG(p->audio_control,READ_PORT_ULONG(p->audio_control)&x) | ||
185 | #define READ_AUDIO_STATUS(p) READ_PORT_ULONG(p->audio_status) | ||
186 | |||
187 | #define SET_GRESET(p) UMASK_AUDIO_CONTROL(p,0x0001) /* global reset switch */ | ||
188 | #define UNSET_GRESET(p) MASK_AUDIO_CONTROL(p,~0x0001) | ||
189 | #define SET_AIE(p) UMASK_AUDIO_CONTROL(p,0x0004) /* interrupt enable */ | ||
190 | #define UNSET_AIE(p) MASK_AUDIO_CONTROL(p,~0x0004) | ||
191 | #define SET_AIACK(p) UMASK_AUDIO_CONTROL(p,0x0008) /* interrupt acknowledge */ | ||
192 | #define UNSET_AIACKT(p) MASKAUDIO_CONTROL(p,~0x0008) | ||
193 | #define SET_ECMDAE(p) UMASK_AUDIO_CONTROL(p,0x0010) | ||
194 | #define UNSET_ECMDAE(p) MASK_AUDIO_CONTROL(p,~0x0010) | ||
195 | #define SET_ECMDBE(p) UMASK_AUDIO_CONTROL(p,0x0020) | ||
196 | #define UNSET_ECMDBE(p) MASK_AUDIO_CONTROL(p,~0x0020) | ||
197 | #define SET_EDATAF(p) UMASK_AUDIO_CONTROL(p,0x0040) | ||
198 | #define UNSET_EDATAF(p) MASK_AUDIO_CONTROL(p,~0x0040) | ||
199 | #define SET_EDATBF(p) UMASK_AUDIO_CONTROL(p,0x0080) | ||
200 | #define UNSET_EDATBF(p) MASK_AUDIO_CONTROL(p,~0x0080) | ||
201 | #define SET_ESBIRQON(p) UMASK_AUDIO_CONTROL(p,0x0100) | ||
202 | #define UNSET_ESBIRQON(p) MASK_AUDIO_CONTROL(p,~0x0100) | ||
203 | #define SET_EMPUIRQ(p) UMASK_AUDIO_CONTROL(p,0x0200) | ||
204 | #define UNSET_EMPUIRQ(p) MASK_AUDIO_CONTROL(p,~0x0200) | ||
205 | #define IS_CMDE(a) (READ_PORT_ULONG(a->stat)&0x1) /* cmd empty */ | ||
206 | #define IS_DATF(a) (READ_PORT_ULONG(a->stat)&0x2) /* data filled */ | ||
207 | #define IS_READY(p) (READ_AUDIO_STATUS(p)&0x0001) | ||
208 | #define IS_DLREADY(p) (READ_AUDIO_STATUS(p)&0x0002) | ||
209 | #define IS_DLERR(p) (READ_AUDIO_STATUS(p)&0x0004) | ||
210 | #define IS_GERR(p) (READ_AUDIO_STATUS(p)&0x0008) /* error ! */ | ||
211 | #define IS_CMDAEIRQ(p) (READ_AUDIO_STATUS(p)&0x0010) | ||
212 | #define IS_CMDBEIRQ(p) (READ_AUDIO_STATUS(p)&0x0020) | ||
213 | #define IS_DATAFIRQ(p) (READ_AUDIO_STATUS(p)&0x0040) | ||
214 | #define IS_DATBFIRQ(p) (READ_AUDIO_STATUS(p)&0x0080) | ||
215 | #define IS_EOBIRQ(p) (READ_AUDIO_STATUS(p)&0x0100) /* interrupt status */ | ||
216 | #define IS_EOSIRQ(p) (READ_AUDIO_STATUS(p)&0x0200) | ||
217 | #define IS_EOCIRQ(p) (READ_AUDIO_STATUS(p)&0x0400) | ||
218 | #define IS_UNSLIRQ(p) (READ_AUDIO_STATUS(p)&0x0800) | ||
219 | #define IS_SBIRQ(p) (READ_AUDIO_STATUS(p)&0x1000) | ||
220 | #define IS_MPUIRQ(p) (READ_AUDIO_STATUS(p)&0x2000) | ||
221 | |||
222 | #define RESP 0x00000001 /* command flags */ | ||
223 | #define PARM 0x00000002 | ||
224 | #define CMDA 0x00000004 | ||
225 | #define CMDB 0x00000008 | ||
226 | #define NILL 0x00000000 | ||
227 | |||
228 | #define LONG0(a) ((u32)a) /* shifts and masks */ | ||
229 | #define BYTE0(a) (LONG0(a)&0xff) | ||
230 | #define BYTE1(a) (BYTE0(a)<<8) | ||
231 | #define BYTE2(a) (BYTE0(a)<<16) | ||
232 | #define BYTE3(a) (BYTE0(a)<<24) | ||
233 | #define WORD0(a) (LONG0(a)&0xffff) | ||
234 | #define WORD1(a) (WORD0(a)<<8) | ||
235 | #define WORD2(a) (WORD0(a)<<16) | ||
236 | #define TRINIB0(a) (LONG0(a)&0xffffff) | ||
237 | #define TRINIB1(a) (TRINIB0(a)<<8) | ||
238 | |||
239 | #define RET(a) ((union cmdret *)(a)) | ||
240 | |||
241 | #define SEND_GETV(p,b) sendcmd(p,RESP,GETV,0,RET(b)) /* get version */ | ||
242 | #define SEND_GETC(p,b,c) sendcmd(p,PARM|RESP,GETC,c,RET(b)) | ||
243 | #define SEND_GUNS(p,b) sendcmd(p,RESP,GUNS,0,RET(b)) | ||
244 | #define SEND_SCID(p,b) sendcmd(p,RESP,SCID,0,RET(b)) | ||
245 | #define SEND_RMEM(p,b,c,d) sendcmd(p,PARM|RESP,RMEM|BYTE1(b),LONG0(c),RET(d)) /* memory access for firmware write */ | ||
246 | #define SEND_SMEM(p,b,c) sendcmd(p,PARM,SMEM|BYTE1(b),LONG0(c),RET(0)) /* memory access for firmware write */ | ||
247 | #define SEND_WMEM(p,b,c) sendcmd(p,PARM,WMEM|BYTE1(b),LONG0(c),RET(0)) /* memory access for firmware write */ | ||
248 | #define SEND_SDTM(p,b,c) sendcmd(p,PARM|RESP,SDTM|TRINIB1(b),0,RET(c)) /* memory access for firmware write */ | ||
249 | #define SEND_GOTO(p,b) sendcmd(p,PARM,GOTO,LONG0(b),RET(0)) /* memory access for firmware write */ | ||
250 | #define SEND_SETDPLL(p) sendcmd(p,0,ARM_SETDPLL,0,RET(0)) | ||
251 | #define SEND_SSTR(p,b,c) sendcmd(p,PARM,SSTR|BYTE3(b),LONG0(c),RET(0)) /* start stream */ | ||
252 | #define SEND_PSTR(p,b) sendcmd(p,PARM,PSTR,BYTE3(b),RET(0)) /* pause stream */ | ||
253 | #define SEND_KSTR(p,b) sendcmd(p,PARM,KSTR,BYTE3(b),RET(0)) /* stop stream */ | ||
254 | #define SEND_KDMA(p) sendcmd(p,0,KDMA,0,RET(0)) /* stop all dma */ | ||
255 | #define SEND_GPOS(p,b,c,d) sendcmd(p,PARM|RESP,GPOS,BYTE3(c)|BYTE2(b),RET(d)) /* get position in dma */ | ||
256 | #define SEND_SETF(p,b,c,d,e,f,g) sendcmd(p,PARM,SETF|WORD1(b)|BYTE3(c),d|BYTE1(e)|BYTE2(f)|BYTE3(g),RET(0)) /* set sample format at mixer */ | ||
257 | #define SEND_GSTS(p,b,c,d) sendcmd(p,PARM|RESP,GSTS,BYTE3(c)|BYTE2(b),RET(d)) | ||
258 | #define SEND_NGPOS(p,b,c,d) sendcmd(p,PARM|RESP,NGPOS,BYTE3(c)|BYTE2(b),RET(d)) | ||
259 | #define SEND_PSEL(p,b,c) sendcmd(p,PARM,PSEL,BYTE2(b)|BYTE3(c),RET(0)) /* activate lbus path */ | ||
260 | #define SEND_PCLR(p,b,c) sendcmd(p,PARM,PCLR,BYTE2(b)|BYTE3(c),RET(0)) /* deactivate lbus path */ | ||
261 | #define SEND_PLST(p,b) sendcmd(p,PARM,PLST,BYTE3(b),RET(0)) | ||
262 | #define SEND_RSSV(p,b,c,d) sendcmd(p,PARM|RESP,RSSV,BYTE2(b)|BYTE3(c),RET(d)) | ||
263 | #define SEND_LSEL(p,b,c,d,e,f,g,h) sendcmd(p,PARM,LSEL|BYTE1(b)|BYTE2(c)|BYTE3(d),BYTE0(e)|BYTE1(f)|BYTE2(g)|BYTE3(h),RET(0)) /* select paths for internal connections */ | ||
264 | #define SEND_SSRC(p,b,c,d,e) sendcmd(p,PARM,SSRC|BYTE1(b)|WORD2(c),WORD0(d)|WORD2(e),RET(0)) /* configure source */ | ||
265 | #define SEND_SLST(p,b) sendcmd(p,PARM,SLST,BYTE3(b),RET(0)) | ||
266 | #define SEND_RSRC(p,b,c) sendcmd(p,RESP,RSRC|BYTE1(b),0,RET(c)) /* read source config */ | ||
267 | #define SEND_SSRB(p,b,c) sendcmd(p,PARM,SSRB|BYTE1(b),WORD2(c),RET(0)) | ||
268 | #define SEND_SDGV(p,b,c,d,e) sendcmd(p,PARM,SDGV|BYTE2(b)|BYTE3(c),WORD0(d)|WORD2(e),RET(0)) /* set digital mixer */ | ||
269 | #define SEND_RDGV(p,b,c,d) sendcmd(p,PARM|RESP,RDGV|BYTE2(b)|BYTE3(c),0,RET(d)) /* read digital mixer */ | ||
270 | #define SEND_DLST(p,b) sendcmd(p,PARM,DLST,BYTE3(b),RET(0)) | ||
271 | #define SEND_SACR(p,b,c) sendcmd(p,PARM,SACR,WORD0(b)|WORD2(c),RET(0)) /* set AC97 register */ | ||
272 | #define SEND_RACR(p,b,c) sendcmd(p,PARM|RESP,RACR,WORD2(b),RET(c)) /* get AC97 register */ | ||
273 | #define SEND_ALST(p,b) sendcmd(p,PARM,ALST,BYTE3(b),RET(0)) | ||
274 | #define SEND_TXAC(p,b,c,d,e,f) sendcmd(p,PARM,TXAC|BYTE1(b)|WORD2(c),WORD0(d)|BYTE2(e)|BYTE3(f),RET(0)) | ||
275 | #define SEND_RXAC(p,b,c,d) sendcmd(p,PARM|RESP,RXAC,BYTE2(b)|BYTE3(c),RET(d)) | ||
276 | #define SEND_SI2S(p,b) sendcmd(p,PARM,SI2S,WORD2(b),RET(0)) | ||
277 | |||
278 | #define EOB_STATUS 0x80000000 /* status flags : block boundary */ | ||
279 | #define EOS_STATUS 0x40000000 /* : stoppped */ | ||
280 | #define EOC_STATUS 0x20000000 /* : stream end */ | ||
281 | #define ERR_STATUS 0x10000000 | ||
282 | #define EMPTY_STATUS 0x08000000 | ||
283 | |||
284 | #define IEOB_ENABLE 0x1 /* enable interrupts for status notification above */ | ||
285 | #define IEOS_ENABLE 0x2 | ||
286 | #define IEOC_ENABLE 0x4 | ||
287 | #define RDONCE 0x8 | ||
288 | #define DESC_MAX_MASK 0xff | ||
289 | |||
290 | #define ST_PLAY 0x1 /* stream states */ | ||
291 | #define ST_STOP 0x2 | ||
292 | #define ST_PAUSE 0x4 | ||
293 | |||
294 | #define I2S_INTDEC 3 /* config for I2S link */ | ||
295 | #define I2S_MERGER 0 | ||
296 | #define I2S_SPLITTER 0 | ||
297 | #define I2S_MIXER 7 | ||
298 | #define I2S_RATE 44100 | ||
299 | |||
300 | #define MODEM_INTDEC 4 /* config for modem link */ | ||
301 | #define MODEM_MERGER 3 | ||
302 | #define MODEM_SPLITTER 0 | ||
303 | #define MODEM_MIXER 11 | ||
304 | |||
305 | #define FM_INTDEC 3 /* config for FM/OPL3 link */ | ||
306 | #define FM_MERGER 0 | ||
307 | #define FM_SPLITTER 0 | ||
308 | #define FM_MIXER 9 | ||
309 | |||
310 | #define SPLIT_PATH 0x80 /* path splitting flag */ | ||
311 | |||
312 | enum FIRMWARE { | ||
313 | DATA_REC = 0, EXT_END_OF_FILE, EXT_SEG_ADDR_REC, EXT_GOTO_CMD_REC, | ||
314 | EXT_LIN_ADDR_REC, | ||
315 | }; | ||
316 | |||
317 | enum CMDS { | ||
318 | GETV = 0x00, GETC, GUNS, SCID, RMEM = | ||
319 | 0x10, SMEM, WMEM, SDTM, GOTO, SSTR = | ||
320 | 0x20, PSTR, KSTR, KDMA, GPOS, SETF, GSTS, NGPOS, PSEL = | ||
321 | 0x30, PCLR, PLST, RSSV, LSEL, SSRC = 0x40, SLST, RSRC, SSRB, SDGV = | ||
322 | 0x50, RDGV, DLST, SACR = 0x60, RACR, ALST, TXAC, RXAC, SI2S = | ||
323 | 0x70, ARM_SETDPLL = 0x72, | ||
324 | }; | ||
325 | |||
326 | enum E1SOURCE { | ||
327 | ARM2LBUS_FIFO0 = 0, ARM2LBUS_FIFO1, ARM2LBUS_FIFO2, ARM2LBUS_FIFO3, | ||
328 | ARM2LBUS_FIFO4, ARM2LBUS_FIFO5, ARM2LBUS_FIFO6, ARM2LBUS_FIFO7, | ||
329 | ARM2LBUS_FIFO8, ARM2LBUS_FIFO9, ARM2LBUS_FIFO10, ARM2LBUS_FIFO11, | ||
330 | ARM2LBUS_FIFO12, ARM2LBUS_FIFO13, ARM2LBUS_FIFO14, ARM2LBUS_FIFO15, | ||
331 | INTER0_OUT, INTER1_OUT, INTER2_OUT, INTER3_OUT, INTER4_OUT, | ||
332 | INTERM0_OUT, INTERM1_OUT, INTERM2_OUT, INTERM3_OUT, INTERM4_OUT, | ||
333 | INTERM5_OUT, INTERM6_OUT, DECIMM0_OUT, DECIMM1_OUT, DECIMM2_OUT, | ||
334 | DECIMM3_OUT, DECIM0_OUT, SR3_4_OUT, OPL3_SAMPLE, ASRC0, ASRC1, | ||
335 | ACLNK2PADC, ACLNK2MODEM0RX, ACLNK2MIC, ACLNK2MODEM1RX, ACLNK2HNDMIC, | ||
336 | DIGITAL_MIXER_OUT0, GAINFUNC0_OUT, GAINFUNC1_OUT, GAINFUNC2_OUT, | ||
337 | GAINFUNC3_OUT, GAINFUNC4_OUT, SOFTMODEMTX, SPLITTER0_OUTL, | ||
338 | SPLITTER0_OUTR, SPLITTER1_OUTL, SPLITTER1_OUTR, SPLITTER2_OUTL, | ||
339 | SPLITTER2_OUTR, SPLITTER3_OUTL, SPLITTER3_OUTR, MERGER0_OUT, | ||
340 | MERGER1_OUT, MERGER2_OUT, MERGER3_OUT, ARM2LBUS_FIFO_DIRECT, NO_OUT | ||
341 | }; | ||
342 | |||
343 | enum E2SINK { | ||
344 | LBUS2ARM_FIFO0 = 0, LBUS2ARM_FIFO1, LBUS2ARM_FIFO2, LBUS2ARM_FIFO3, | ||
345 | LBUS2ARM_FIFO4, LBUS2ARM_FIFO5, LBUS2ARM_FIFO6, LBUS2ARM_FIFO7, | ||
346 | INTER0_IN, INTER1_IN, INTER2_IN, INTER3_IN, INTER4_IN, INTERM0_IN, | ||
347 | INTERM1_IN, INTERM2_IN, INTERM3_IN, INTERM4_IN, INTERM5_IN, INTERM6_IN, | ||
348 | DECIMM0_IN, DECIMM1_IN, DECIMM2_IN, DECIMM3_IN, DECIM0_IN, SR3_4_IN, | ||
349 | PDAC2ACLNK, MODEM0TX2ACLNK, MODEM1TX2ACLNK, HNDSPK2ACLNK, | ||
350 | DIGITAL_MIXER_IN0, DIGITAL_MIXER_IN1, DIGITAL_MIXER_IN2, | ||
351 | DIGITAL_MIXER_IN3, DIGITAL_MIXER_IN4, DIGITAL_MIXER_IN5, | ||
352 | DIGITAL_MIXER_IN6, DIGITAL_MIXER_IN7, DIGITAL_MIXER_IN8, | ||
353 | DIGITAL_MIXER_IN9, DIGITAL_MIXER_IN10, DIGITAL_MIXER_IN11, | ||
354 | GAINFUNC0_IN, GAINFUNC1_IN, GAINFUNC2_IN, GAINFUNC3_IN, GAINFUNC4_IN, | ||
355 | SOFTMODEMRX, SPLITTER0_IN, SPLITTER1_IN, SPLITTER2_IN, SPLITTER3_IN, | ||
356 | MERGER0_INL, MERGER0_INR, MERGER1_INL, MERGER1_INR, MERGER2_INL, | ||
357 | MERGER2_INR, MERGER3_INL, MERGER3_INR, E2SINK_MAX | ||
358 | }; | ||
359 | |||
360 | enum LBUS_SINK { | ||
361 | LS_SRC_INTERPOLATOR = 0, LS_SRC_INTERPOLATORM, LS_SRC_DECIMATOR, | ||
362 | LS_SRC_DECIMATORM, LS_MIXER_IN, LS_MIXER_GAIN_FUNCTION, | ||
363 | LS_SRC_SPLITTER, LS_SRC_MERGER, LS_NONE1, LS_NONE2, | ||
364 | }; | ||
365 | |||
366 | enum RT_CHANNEL_IDS { | ||
367 | M0TX = 0, M1TX, TAMTX, HSSPKR, PDAC, DSNDTX0, DSNDTX1, DSNDTX2, | ||
368 | DSNDTX3, DSNDTX4, DSNDTX5, DSNDTX6, DSNDTX7, WVSTRTX, COP3DTX, SPARE, | ||
369 | M0RX, HSMIC, M1RX, CLEANRX, MICADC, PADC, COPRX1, COPRX2, | ||
370 | CHANNEL_ID_COUNTER | ||
371 | }; | ||
372 | |||
373 | enum { SB_CMD = 0, MODEM_CMD, I2S_CMD0, I2S_CMD1, FM_CMD, MAX_CMD }; | ||
374 | |||
375 | struct lbuspath { | ||
376 | unsigned char *noconv; | ||
377 | unsigned char *stereo; | ||
378 | unsigned char *mono; | ||
379 | }; | ||
380 | |||
381 | struct cmdport { | ||
382 | u32 data1; /* cmd,param */ | ||
383 | u32 data2; /* param */ | ||
384 | u32 stat; /* status */ | ||
385 | u32 pad[5]; | ||
386 | }; | ||
387 | |||
388 | struct riptideport { | ||
389 | u32 audio_control; /* status registers */ | ||
390 | u32 audio_status; | ||
391 | u32 pad[2]; | ||
392 | struct cmdport port[2]; /* command ports */ | ||
393 | }; | ||
394 | |||
395 | struct cmdif { | ||
396 | struct riptideport *hwport; | ||
397 | spinlock_t lock; | ||
398 | unsigned int cmdcnt; /* cmd statistics */ | ||
399 | unsigned int cmdtime; | ||
400 | unsigned int cmdtimemax; | ||
401 | unsigned int cmdtimemin; | ||
402 | unsigned int errcnt; | ||
403 | int is_reset; | ||
404 | }; | ||
405 | |||
406 | struct riptide_firmware { | ||
407 | u16 ASIC; | ||
408 | u16 CODEC; | ||
409 | u16 AUXDSP; | ||
410 | u16 PROG; | ||
411 | }; | ||
412 | |||
413 | union cmdret { | ||
414 | u8 retbytes[8]; | ||
415 | u16 retwords[4]; | ||
416 | u32 retlongs[2]; | ||
417 | }; | ||
418 | |||
419 | union firmware_version { | ||
420 | union cmdret ret; | ||
421 | struct riptide_firmware firmware; | ||
422 | }; | ||
423 | |||
424 | #define get_pcmhwdev(substream) (struct pcmhw *)(substream->runtime->private_data) | ||
425 | |||
426 | #define PLAYBACK_SUBSTREAMS 3 | ||
427 | struct snd_riptide { | ||
428 | struct snd_card *card; | ||
429 | struct pci_dev *pci; | ||
430 | const struct firmware *fw_entry; | ||
431 | |||
432 | struct cmdif *cif; | ||
433 | |||
434 | struct snd_pcm *pcm; | ||
435 | struct snd_pcm *pcm_i2s; | ||
436 | struct snd_rawmidi *rmidi; | ||
437 | struct snd_opl3 *opl3; | ||
438 | struct snd_ac97 *ac97; | ||
439 | struct snd_ac97_bus *ac97_bus; | ||
440 | |||
441 | struct snd_pcm_substream *playback_substream[PLAYBACK_SUBSTREAMS]; | ||
442 | struct snd_pcm_substream *capture_substream; | ||
443 | |||
444 | int openstreams; | ||
445 | |||
446 | int irq; | ||
447 | unsigned long port; | ||
448 | unsigned short mpuaddr; | ||
449 | unsigned short opladdr; | ||
450 | #ifdef SUPPORT_JOYSTICK | ||
451 | unsigned short gameaddr; | ||
452 | #endif | ||
453 | struct resource *res_port; | ||
454 | |||
455 | unsigned short device_id; | ||
456 | |||
457 | union firmware_version firmware; | ||
458 | |||
459 | spinlock_t lock; | ||
460 | struct tasklet_struct riptide_tq; | ||
461 | struct snd_info_entry *proc_entry; | ||
462 | |||
463 | unsigned long received_irqs; | ||
464 | unsigned long handled_irqs; | ||
465 | #ifdef CONFIG_PM | ||
466 | int in_suspend; | ||
467 | #endif | ||
468 | }; | ||
469 | |||
470 | struct sgd { /* scatter gather desriptor */ | ||
471 | u32 dwNextLink; | ||
472 | u32 dwSegPtrPhys; | ||
473 | u32 dwSegLen; | ||
474 | u32 dwStat_Ctl; | ||
475 | }; | ||
476 | |||
477 | struct pcmhw { /* pcm descriptor */ | ||
478 | struct lbuspath paths; | ||
479 | unsigned char *lbuspath; | ||
480 | unsigned char source; | ||
481 | unsigned char intdec[2]; | ||
482 | unsigned char mixer; | ||
483 | unsigned char id; | ||
484 | unsigned char state; | ||
485 | unsigned int rate; | ||
486 | unsigned int channels; | ||
487 | snd_pcm_format_t format; | ||
488 | struct snd_dma_buffer sgdlist; | ||
489 | struct sgd *sgdbuf; | ||
490 | unsigned int size; | ||
491 | unsigned int pages; | ||
492 | unsigned int oldpos; | ||
493 | unsigned int pointer; | ||
494 | }; | ||
495 | |||
496 | #define CMDRET_ZERO (union cmdret){{(u32)0, (u32) 0}} | ||
497 | |||
498 | static int sendcmd(struct cmdif *cif, u32 flags, u32 cmd, u32 parm, | ||
499 | union cmdret *ret); | ||
500 | static int getsourcesink(struct cmdif *cif, unsigned char source, | ||
501 | unsigned char sink, unsigned char *a, | ||
502 | unsigned char *b); | ||
503 | static int snd_riptide_initialize(struct snd_riptide *chip); | ||
504 | static int riptide_reset(struct cmdif *cif, struct snd_riptide *chip); | ||
505 | |||
506 | /* | ||
507 | */ | ||
508 | |||
509 | static struct pci_device_id snd_riptide_ids[] = { | ||
510 | { | ||
511 | .vendor = 0x127a,.device = 0x4310, | ||
512 | .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID, | ||
513 | }, | ||
514 | { | ||
515 | .vendor = 0x127a,.device = 0x4320, | ||
516 | .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID, | ||
517 | }, | ||
518 | { | ||
519 | .vendor = 0x127a,.device = 0x4330, | ||
520 | .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID, | ||
521 | }, | ||
522 | { | ||
523 | .vendor = 0x127a,.device = 0x4340, | ||
524 | .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID, | ||
525 | }, | ||
526 | {0,}, | ||
527 | }; | ||
528 | |||
529 | #ifdef SUPPORT_JOYSTICK | ||
530 | static struct pci_device_id snd_riptide_joystick_ids[] = { | ||
531 | { | ||
532 | .vendor = 0x127a,.device = 0x4312, | ||
533 | .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID, | ||
534 | }, | ||
535 | { | ||
536 | .vendor = 0x127a,.device = 0x4322, | ||
537 | .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID, | ||
538 | }, | ||
539 | {.vendor = 0x127a,.device = 0x4332, | ||
540 | .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID, | ||
541 | }, | ||
542 | {.vendor = 0x127a,.device = 0x4342, | ||
543 | .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID, | ||
544 | }, | ||
545 | {0,}, | ||
546 | }; | ||
547 | #endif | ||
548 | |||
549 | MODULE_DEVICE_TABLE(pci, snd_riptide_ids); | ||
550 | |||
551 | /* | ||
552 | */ | ||
553 | |||
554 | static unsigned char lbusin2out[E2SINK_MAX + 1][2] = { | ||
555 | {NO_OUT, LS_NONE1}, {NO_OUT, LS_NONE2}, {NO_OUT, LS_NONE1}, {NO_OUT, | ||
556 | LS_NONE2}, | ||
557 | {NO_OUT, LS_NONE1}, {NO_OUT, LS_NONE2}, {NO_OUT, LS_NONE1}, {NO_OUT, | ||
558 | LS_NONE2}, | ||
559 | {INTER0_OUT, LS_SRC_INTERPOLATOR}, {INTER1_OUT, LS_SRC_INTERPOLATOR}, | ||
560 | {INTER2_OUT, LS_SRC_INTERPOLATOR}, {INTER3_OUT, LS_SRC_INTERPOLATOR}, | ||
561 | {INTER4_OUT, LS_SRC_INTERPOLATOR}, {INTERM0_OUT, LS_SRC_INTERPOLATORM}, | ||
562 | {INTERM1_OUT, LS_SRC_INTERPOLATORM}, {INTERM2_OUT, | ||
563 | LS_SRC_INTERPOLATORM}, | ||
564 | {INTERM3_OUT, LS_SRC_INTERPOLATORM}, {INTERM4_OUT, | ||
565 | LS_SRC_INTERPOLATORM}, | ||
566 | {INTERM5_OUT, LS_SRC_INTERPOLATORM}, {INTERM6_OUT, | ||
567 | LS_SRC_INTERPOLATORM}, | ||
568 | {DECIMM0_OUT, LS_SRC_DECIMATORM}, {DECIMM1_OUT, LS_SRC_DECIMATORM}, | ||
569 | {DECIMM2_OUT, LS_SRC_DECIMATORM}, {DECIMM3_OUT, LS_SRC_DECIMATORM}, | ||
570 | {DECIM0_OUT, LS_SRC_DECIMATOR}, {SR3_4_OUT, LS_NONE1}, {NO_OUT, | ||
571 | LS_NONE2}, | ||
572 | {NO_OUT, LS_NONE1}, {NO_OUT, LS_NONE2}, {NO_OUT, LS_NONE1}, | ||
573 | {DIGITAL_MIXER_OUT0, LS_MIXER_IN}, {DIGITAL_MIXER_OUT0, LS_MIXER_IN}, | ||
574 | {DIGITAL_MIXER_OUT0, LS_MIXER_IN}, {DIGITAL_MIXER_OUT0, LS_MIXER_IN}, | ||
575 | {DIGITAL_MIXER_OUT0, LS_MIXER_IN}, {DIGITAL_MIXER_OUT0, LS_MIXER_IN}, | ||
576 | {DIGITAL_MIXER_OUT0, LS_MIXER_IN}, {DIGITAL_MIXER_OUT0, LS_MIXER_IN}, | ||
577 | {DIGITAL_MIXER_OUT0, LS_MIXER_IN}, {DIGITAL_MIXER_OUT0, LS_MIXER_IN}, | ||
578 | {DIGITAL_MIXER_OUT0, LS_MIXER_IN}, {DIGITAL_MIXER_OUT0, LS_MIXER_IN}, | ||
579 | {GAINFUNC0_OUT, LS_MIXER_GAIN_FUNCTION}, {GAINFUNC1_OUT, | ||
580 | LS_MIXER_GAIN_FUNCTION}, | ||
581 | {GAINFUNC2_OUT, LS_MIXER_GAIN_FUNCTION}, {GAINFUNC3_OUT, | ||
582 | LS_MIXER_GAIN_FUNCTION}, | ||
583 | {GAINFUNC4_OUT, LS_MIXER_GAIN_FUNCTION}, {SOFTMODEMTX, LS_NONE1}, | ||
584 | {SPLITTER0_OUTL, LS_SRC_SPLITTER}, {SPLITTER1_OUTL, LS_SRC_SPLITTER}, | ||
585 | {SPLITTER2_OUTL, LS_SRC_SPLITTER}, {SPLITTER3_OUTL, LS_SRC_SPLITTER}, | ||
586 | {MERGER0_OUT, LS_SRC_MERGER}, {MERGER0_OUT, LS_SRC_MERGER}, | ||
587 | {MERGER1_OUT, LS_SRC_MERGER}, | ||
588 | {MERGER1_OUT, LS_SRC_MERGER}, {MERGER2_OUT, LS_SRC_MERGER}, | ||
589 | {MERGER2_OUT, LS_SRC_MERGER}, | ||
590 | {MERGER3_OUT, LS_SRC_MERGER}, {MERGER3_OUT, LS_SRC_MERGER}, {NO_OUT, | ||
591 | LS_NONE2}, | ||
592 | }; | ||
593 | |||
594 | static unsigned char lbus_play_opl3[] = { | ||
595 | DIGITAL_MIXER_IN0 + FM_MIXER, 0xff | ||
596 | }; | ||
597 | static unsigned char lbus_play_modem[] = { | ||
598 | DIGITAL_MIXER_IN0 + MODEM_MIXER, 0xff | ||
599 | }; | ||
600 | static unsigned char lbus_play_i2s[] = { | ||
601 | INTER0_IN + I2S_INTDEC, DIGITAL_MIXER_IN0 + I2S_MIXER, 0xff | ||
602 | }; | ||
603 | static unsigned char lbus_play_out[] = { | ||
604 | PDAC2ACLNK, 0xff | ||
605 | }; | ||
606 | static unsigned char lbus_play_outhp[] = { | ||
607 | HNDSPK2ACLNK, 0xff | ||
608 | }; | ||
609 | static unsigned char lbus_play_noconv1[] = { | ||
610 | DIGITAL_MIXER_IN0, 0xff | ||
611 | }; | ||
612 | static unsigned char lbus_play_stereo1[] = { | ||
613 | INTER0_IN, DIGITAL_MIXER_IN0, 0xff | ||
614 | }; | ||
615 | static unsigned char lbus_play_mono1[] = { | ||
616 | INTERM0_IN, DIGITAL_MIXER_IN0, 0xff | ||
617 | }; | ||
618 | static unsigned char lbus_play_noconv2[] = { | ||
619 | DIGITAL_MIXER_IN1, 0xff | ||
620 | }; | ||
621 | static unsigned char lbus_play_stereo2[] = { | ||
622 | INTER1_IN, DIGITAL_MIXER_IN1, 0xff | ||
623 | }; | ||
624 | static unsigned char lbus_play_mono2[] = { | ||
625 | INTERM1_IN, DIGITAL_MIXER_IN1, 0xff | ||
626 | }; | ||
627 | static unsigned char lbus_play_noconv3[] = { | ||
628 | DIGITAL_MIXER_IN2, 0xff | ||
629 | }; | ||
630 | static unsigned char lbus_play_stereo3[] = { | ||
631 | INTER2_IN, DIGITAL_MIXER_IN2, 0xff | ||
632 | }; | ||
633 | static unsigned char lbus_play_mono3[] = { | ||
634 | INTERM2_IN, DIGITAL_MIXER_IN2, 0xff | ||
635 | }; | ||
636 | static unsigned char lbus_rec_noconv1[] = { | ||
637 | LBUS2ARM_FIFO5, 0xff | ||
638 | }; | ||
639 | static unsigned char lbus_rec_stereo1[] = { | ||
640 | DECIM0_IN, LBUS2ARM_FIFO5, 0xff | ||
641 | }; | ||
642 | static unsigned char lbus_rec_mono1[] = { | ||
643 | DECIMM3_IN, LBUS2ARM_FIFO5, 0xff | ||
644 | }; | ||
645 | |||
646 | static unsigned char play_ids[] = { 4, 1, 2, }; | ||
647 | static unsigned char play_sources[] = { | ||
648 | ARM2LBUS_FIFO4, ARM2LBUS_FIFO1, ARM2LBUS_FIFO2, | ||
649 | }; | ||
650 | static struct lbuspath lbus_play_paths[] = { | ||
651 | { | ||
652 | .noconv = lbus_play_noconv1, | ||
653 | .stereo = lbus_play_stereo1, | ||
654 | .mono = lbus_play_mono1, | ||
655 | }, | ||
656 | { | ||
657 | .noconv = lbus_play_noconv2, | ||
658 | .stereo = lbus_play_stereo2, | ||
659 | .mono = lbus_play_mono2, | ||
660 | }, | ||
661 | { | ||
662 | .noconv = lbus_play_noconv3, | ||
663 | .stereo = lbus_play_stereo3, | ||
664 | .mono = lbus_play_mono3, | ||
665 | }, | ||
666 | }; | ||
667 | static struct lbuspath lbus_rec_path = { | ||
668 | .noconv = lbus_rec_noconv1, | ||
669 | .stereo = lbus_rec_stereo1, | ||
670 | .mono = lbus_rec_mono1, | ||
671 | }; | ||
672 | |||
673 | #define FIRMWARE_VERSIONS 1 | ||
674 | static union firmware_version firmware_versions[] = { | ||
675 | { | ||
676 | .firmware.ASIC = 3,.firmware.CODEC = 2, | ||
677 | .firmware.AUXDSP = 3,.firmware.PROG = 773, | ||
678 | }, | ||
679 | }; | ||
680 | |||
681 | static u32 atoh(unsigned char *in, unsigned int len) | ||
682 | { | ||
683 | u32 sum = 0; | ||
684 | unsigned int mult = 1; | ||
685 | unsigned char c; | ||
686 | |||
687 | while (len) { | ||
688 | c = in[len - 1]; | ||
689 | if ((c >= '0') && (c <= '9')) | ||
690 | sum += mult * (c - '0'); | ||
691 | else if ((c >= 'A') && (c <= 'F')) | ||
692 | sum += mult * (c - ('A' - 10)); | ||
693 | else if ((c >= 'a') && (c <= 'f')) | ||
694 | sum += mult * (c - ('a' - 10)); | ||
695 | mult *= 16; | ||
696 | --len; | ||
697 | } | ||
698 | return sum; | ||
699 | } | ||
700 | |||
701 | static int senddata(struct cmdif *cif, unsigned char *in, u32 offset) | ||
702 | { | ||
703 | u32 addr; | ||
704 | u32 data; | ||
705 | u32 i; | ||
706 | unsigned char *p; | ||
707 | |||
708 | i = atoh(&in[1], 2); | ||
709 | addr = offset + atoh(&in[3], 4); | ||
710 | if (SEND_SMEM(cif, 0, addr) != 0) | ||
711 | return -EACCES; | ||
712 | p = in + 9; | ||
713 | while (i) { | ||
714 | data = atoh(p, 8); | ||
715 | if (SEND_WMEM(cif, 2, | ||
716 | ((data & 0x0f0f0f0f) << 4) | ((data & 0xf0f0f0f0) | ||
717 | >> 4))) | ||
718 | return -EACCES; | ||
719 | i -= 4; | ||
720 | p += 8; | ||
721 | } | ||
722 | return 0; | ||
723 | } | ||
724 | |||
725 | static int loadfirmware(struct cmdif *cif, unsigned char *img, | ||
726 | unsigned int size) | ||
727 | { | ||
728 | unsigned char *in; | ||
729 | u32 laddr, saddr, t, val; | ||
730 | int err = 0; | ||
731 | |||
732 | laddr = saddr = 0; | ||
733 | while (size > 0 && err == 0) { | ||
734 | in = img; | ||
735 | if (in[0] == ':') { | ||
736 | t = atoh(&in[7], 2); | ||
737 | switch (t) { | ||
738 | case DATA_REC: | ||
739 | err = senddata(cif, in, laddr + saddr); | ||
740 | break; | ||
741 | case EXT_SEG_ADDR_REC: | ||
742 | saddr = atoh(&in[9], 4) << 4; | ||
743 | break; | ||
744 | case EXT_LIN_ADDR_REC: | ||
745 | laddr = atoh(&in[9], 4) << 16; | ||
746 | break; | ||
747 | case EXT_GOTO_CMD_REC: | ||
748 | val = atoh(&in[9], 8); | ||
749 | if (SEND_GOTO(cif, val) != 0) | ||
750 | err = -EACCES; | ||
751 | break; | ||
752 | case EXT_END_OF_FILE: | ||
753 | size = 0; | ||
754 | break; | ||
755 | default: | ||
756 | break; | ||
757 | } | ||
758 | while (size > 0) { | ||
759 | size--; | ||
760 | if (*img++ == '\n') | ||
761 | break; | ||
762 | } | ||
763 | } | ||
764 | } | ||
765 | snd_printdd("load firmware return %d\n", err); | ||
766 | return err; | ||
767 | } | ||
768 | |||
769 | static void | ||
770 | alloclbuspath(struct cmdif *cif, unsigned char source, | ||
771 | unsigned char *path, unsigned char *mixer, unsigned char *s) | ||
772 | { | ||
773 | while (*path != 0xff) { | ||
774 | unsigned char sink, type; | ||
775 | |||
776 | sink = *path & (~SPLIT_PATH); | ||
777 | if (sink != E2SINK_MAX) { | ||
778 | snd_printdd("alloc path 0x%x->0x%x\n", source, sink); | ||
779 | SEND_PSEL(cif, source, sink); | ||
780 | source = lbusin2out[sink][0]; | ||
781 | type = lbusin2out[sink][1]; | ||
782 | if (type == LS_MIXER_IN) { | ||
783 | if (mixer) | ||
784 | *mixer = sink - DIGITAL_MIXER_IN0; | ||
785 | } | ||
786 | if (type == LS_SRC_DECIMATORM || | ||
787 | type == LS_SRC_DECIMATOR || | ||
788 | type == LS_SRC_INTERPOLATORM || | ||
789 | type == LS_SRC_INTERPOLATOR) { | ||
790 | if (s) { | ||
791 | if (s[0] != 0xff) | ||
792 | s[1] = sink; | ||
793 | else | ||
794 | s[0] = sink; | ||
795 | } | ||
796 | } | ||
797 | } | ||
798 | if (*path++ & SPLIT_PATH) { | ||
799 | unsigned char *npath = path; | ||
800 | |||
801 | while (*npath != 0xff) | ||
802 | npath++; | ||
803 | alloclbuspath(cif, source + 1, ++npath, mixer, s); | ||
804 | } | ||
805 | } | ||
806 | } | ||
807 | |||
808 | static void | ||
809 | freelbuspath(struct cmdif *cif, unsigned char source, unsigned char *path) | ||
810 | { | ||
811 | while (*path != 0xff) { | ||
812 | unsigned char sink; | ||
813 | |||
814 | sink = *path & (~SPLIT_PATH); | ||
815 | if (sink != E2SINK_MAX) { | ||
816 | snd_printdd("free path 0x%x->0x%x\n", source, sink); | ||
817 | SEND_PCLR(cif, source, sink); | ||
818 | source = lbusin2out[sink][0]; | ||
819 | } | ||
820 | if (*path++ & SPLIT_PATH) { | ||
821 | unsigned char *npath = path; | ||
822 | |||
823 | while (*npath != 0xff) | ||
824 | npath++; | ||
825 | freelbuspath(cif, source + 1, ++npath); | ||
826 | } | ||
827 | } | ||
828 | } | ||
829 | |||
830 | static int writearm(struct cmdif *cif, u32 addr, u32 data, u32 mask) | ||
831 | { | ||
832 | union cmdret rptr = CMDRET_ZERO; | ||
833 | unsigned int i = MAX_WRITE_RETRY; | ||
834 | int flag = 1; | ||
835 | |||
836 | SEND_RMEM(cif, 0x02, addr, &rptr); | ||
837 | rptr.retlongs[0] &= (~mask); | ||
838 | |||
839 | while (--i) { | ||
840 | SEND_SMEM(cif, 0x01, addr); | ||
841 | SEND_WMEM(cif, 0x02, (rptr.retlongs[0] | data)); | ||
842 | SEND_RMEM(cif, 0x02, addr, &rptr); | ||
843 | if ((rptr.retlongs[0] & data) == data) { | ||
844 | flag = 0; | ||
845 | break; | ||
846 | } else | ||
847 | rptr.retlongs[0] &= ~mask; | ||
848 | } | ||
849 | snd_printdd("send arm 0x%x 0x%x 0x%x return %d\n", addr, data, mask, | ||
850 | flag); | ||
851 | return flag; | ||
852 | } | ||
853 | |||
854 | static int sendcmd(struct cmdif *cif, u32 flags, u32 cmd, u32 parm, | ||
855 | union cmdret *ret) | ||
856 | { | ||
857 | int i, j; | ||
858 | int err; | ||
859 | unsigned int time = 0; | ||
860 | unsigned long irqflags; | ||
861 | struct riptideport *hwport; | ||
862 | struct cmdport *cmdport = NULL; | ||
863 | |||
864 | snd_assert(cif, return -EINVAL); | ||
865 | |||
866 | hwport = cif->hwport; | ||
867 | if (cif->errcnt > MAX_ERROR_COUNT) { | ||
868 | if (cif->is_reset) { | ||
869 | snd_printk(KERN_ERR | ||
870 | "Riptide: Too many failed cmds, reinitializing\n"); | ||
871 | if (riptide_reset(cif, NULL) == 0) { | ||
872 | cif->errcnt = 0; | ||
873 | return -EIO; | ||
874 | } | ||
875 | } | ||
876 | snd_printk(KERN_ERR "Riptide: Initialization failed.\n"); | ||
877 | return -EINVAL; | ||
878 | } | ||
879 | if (ret) { | ||
880 | ret->retlongs[0] = 0; | ||
881 | ret->retlongs[1] = 0; | ||
882 | } | ||
883 | i = 0; | ||
884 | spin_lock_irqsave(&cif->lock, irqflags); | ||
885 | while (i++ < CMDIF_TIMEOUT && !IS_READY(cif->hwport)) | ||
886 | udelay(10); | ||
887 | if (i >= CMDIF_TIMEOUT) { | ||
888 | err = -EBUSY; | ||
889 | goto errout; | ||
890 | } | ||
891 | |||
892 | err = 0; | ||
893 | for (j = 0, time = 0; time < CMDIF_TIMEOUT; j++, time += 2) { | ||
894 | cmdport = &(hwport->port[j % 2]); | ||
895 | if (IS_DATF(cmdport)) { /* free pending data */ | ||
896 | READ_PORT_ULONG(cmdport->data1); | ||
897 | READ_PORT_ULONG(cmdport->data2); | ||
898 | } | ||
899 | if (IS_CMDE(cmdport)) { | ||
900 | if (flags & PARM) /* put data */ | ||
901 | WRITE_PORT_ULONG(cmdport->data2, parm); | ||
902 | WRITE_PORT_ULONG(cmdport->data1, cmd); /* write cmd */ | ||
903 | if ((flags & RESP) && ret) { | ||
904 | while (!IS_DATF(cmdport) && | ||
905 | time++ < CMDIF_TIMEOUT) | ||
906 | udelay(10); | ||
907 | if (time < CMDIF_TIMEOUT) { /* read response */ | ||
908 | ret->retlongs[0] = | ||
909 | READ_PORT_ULONG(cmdport->data1); | ||
910 | ret->retlongs[1] = | ||
911 | READ_PORT_ULONG(cmdport->data2); | ||
912 | } else { | ||
913 | err = -ENOSYS; | ||
914 | goto errout; | ||
915 | } | ||
916 | } | ||
917 | break; | ||
918 | } | ||
919 | udelay(20); | ||
920 | } | ||
921 | if (time == CMDIF_TIMEOUT) { | ||
922 | err = -ENODATA; | ||
923 | goto errout; | ||
924 | } | ||
925 | spin_unlock_irqrestore(&cif->lock, irqflags); | ||
926 | |||
927 | cif->cmdcnt++; /* update command statistics */ | ||
928 | cif->cmdtime += time; | ||
929 | if (time > cif->cmdtimemax) | ||
930 | cif->cmdtimemax = time; | ||
931 | if (time < cif->cmdtimemin) | ||
932 | cif->cmdtimemin = time; | ||
933 | if ((cif->cmdcnt) % 1000 == 0) | ||
934 | snd_printdd | ||
935 | ("send cmd %d time: %d mintime: %d maxtime %d err: %d\n", | ||
936 | cif->cmdcnt, cif->cmdtime, cif->cmdtimemin, | ||
937 | cif->cmdtimemax, cif->errcnt); | ||
938 | return 0; | ||
939 | |||
940 | errout: | ||
941 | cif->errcnt++; | ||
942 | spin_unlock_irqrestore(&cif->lock, irqflags); | ||
943 | snd_printdd | ||
944 | ("send cmd %d hw: 0x%x flag: 0x%x cmd: 0x%x parm: 0x%x ret: 0x%x 0x%x CMDE: %d DATF: %d failed %d\n", | ||
945 | cif->cmdcnt, (int)((void *)&(cmdport->stat) - (void *)hwport), | ||
946 | flags, cmd, parm, ret ? ret->retlongs[0] : 0, | ||
947 | ret ? ret->retlongs[1] : 0, IS_CMDE(cmdport), IS_DATF(cmdport), | ||
948 | err); | ||
949 | return err; | ||
950 | } | ||
951 | |||
952 | static int | ||
953 | setmixer(struct cmdif *cif, short num, unsigned short rval, unsigned short lval) | ||
954 | { | ||
955 | union cmdret rptr = CMDRET_ZERO; | ||
956 | int i = 0; | ||
957 | |||
958 | snd_printdd("sent mixer %d: 0x%d 0x%d\n", num, rval, lval); | ||
959 | do { | ||
960 | SEND_SDGV(cif, num, num, rval, lval); | ||
961 | SEND_RDGV(cif, num, num, &rptr); | ||
962 | if (rptr.retwords[0] == lval && rptr.retwords[1] == rval) | ||
963 | return 0; | ||
964 | } while (i++ < MAX_WRITE_RETRY); | ||
965 | snd_printdd("sent mixer failed\n"); | ||
966 | return -EIO; | ||
967 | } | ||
968 | |||
969 | static int getpaths(struct cmdif *cif, unsigned char *o) | ||
970 | { | ||
971 | unsigned char src[E2SINK_MAX]; | ||
972 | unsigned char sink[E2SINK_MAX]; | ||
973 | int i, j = 0; | ||
974 | |||
975 | for (i = 0; i < E2SINK_MAX; i++) { | ||
976 | getsourcesink(cif, i, i, &src[i], &sink[i]); | ||
977 | if (sink[i] < E2SINK_MAX) { | ||
978 | o[j++] = sink[i]; | ||
979 | o[j++] = i; | ||
980 | } | ||
981 | } | ||
982 | return j; | ||
983 | } | ||
984 | |||
985 | static int | ||
986 | getsourcesink(struct cmdif *cif, unsigned char source, unsigned char sink, | ||
987 | unsigned char *a, unsigned char *b) | ||
988 | { | ||
989 | union cmdret rptr = CMDRET_ZERO; | ||
990 | |||
991 | if (SEND_RSSV(cif, source, sink, &rptr) && | ||
992 | SEND_RSSV(cif, source, sink, &rptr)) | ||
993 | return -EIO; | ||
994 | *a = rptr.retbytes[0]; | ||
995 | *b = rptr.retbytes[1]; | ||
996 | snd_printdd("getsourcesink 0x%x 0x%x\n", *a, *b); | ||
997 | return 0; | ||
998 | } | ||
999 | |||
1000 | static int | ||
1001 | getsamplerate(struct cmdif *cif, unsigned char *intdec, unsigned int *rate) | ||
1002 | { | ||
1003 | unsigned char *s; | ||
1004 | unsigned int p[2] = { 0, 0 }; | ||
1005 | int i; | ||
1006 | union cmdret rptr = CMDRET_ZERO; | ||
1007 | |||
1008 | s = intdec; | ||
1009 | for (i = 0; i < 2; i++) { | ||
1010 | if (*s != 0xff) { | ||
1011 | if (SEND_RSRC(cif, *s, &rptr) && | ||
1012 | SEND_RSRC(cif, *s, &rptr)) | ||
1013 | return -EIO; | ||
1014 | p[i] += rptr.retwords[1]; | ||
1015 | p[i] *= rptr.retwords[2]; | ||
1016 | p[i] += rptr.retwords[3]; | ||
1017 | p[i] /= 65536; | ||
1018 | } | ||
1019 | s++; | ||
1020 | } | ||
1021 | if (p[0]) { | ||
1022 | if (p[1] != p[0]) | ||
1023 | snd_printdd("rates differ %d %d\n", p[0], p[1]); | ||
1024 | *rate = (unsigned int)p[0]; | ||
1025 | } else | ||
1026 | *rate = (unsigned int)p[1]; | ||
1027 | snd_printdd("getsampleformat %d %d %d\n", intdec[0], intdec[1], *rate); | ||
1028 | return 0; | ||
1029 | } | ||
1030 | |||
1031 | static int | ||
1032 | setsampleformat(struct cmdif *cif, | ||
1033 | unsigned char mixer, unsigned char id, | ||
1034 | unsigned char channels, unsigned char format) | ||
1035 | { | ||
1036 | unsigned char w, ch, sig, order; | ||
1037 | |||
1038 | snd_printdd | ||
1039 | ("setsampleformat mixer: %d id: %d channels: %d format: %d\n", | ||
1040 | mixer, id, channels, format); | ||
1041 | ch = channels == 1; | ||
1042 | w = snd_pcm_format_width(format) == 8; | ||
1043 | sig = snd_pcm_format_unsigned(format) != 0; | ||
1044 | order = snd_pcm_format_big_endian(format) != 0; | ||
1045 | |||
1046 | if (SEND_SETF(cif, mixer, w, ch, order, sig, id) && | ||
1047 | SEND_SETF(cif, mixer, w, ch, order, sig, id)) { | ||
1048 | snd_printdd("setsampleformat failed\n"); | ||
1049 | return -EIO; | ||
1050 | } | ||
1051 | return 0; | ||
1052 | } | ||
1053 | |||
1054 | static int | ||
1055 | setsamplerate(struct cmdif *cif, unsigned char *intdec, unsigned int rate) | ||
1056 | { | ||
1057 | u32 D, M, N; | ||
1058 | union cmdret rptr = CMDRET_ZERO; | ||
1059 | int i; | ||
1060 | |||
1061 | snd_printdd("setsamplerate intdec: %d,%d rate: %d\n", intdec[0], | ||
1062 | intdec[1], rate); | ||
1063 | D = 48000; | ||
1064 | M = ((rate == 48000) ? 47999 : rate) * 65536; | ||
1065 | N = M % D; | ||
1066 | M /= D; | ||
1067 | for (i = 0; i < 2; i++) { | ||
1068 | if (*intdec != 0xff) { | ||
1069 | do { | ||
1070 | SEND_SSRC(cif, *intdec, D, M, N); | ||
1071 | SEND_RSRC(cif, *intdec, &rptr); | ||
1072 | } while (rptr.retwords[1] != D && | ||
1073 | rptr.retwords[2] != M && | ||
1074 | rptr.retwords[3] != N && | ||
1075 | i++ < MAX_WRITE_RETRY); | ||
1076 | if (i == MAX_WRITE_RETRY) { | ||
1077 | snd_printdd("sent samplerate %d: %d failed\n", | ||
1078 | *intdec, rate); | ||
1079 | return -EIO; | ||
1080 | } | ||
1081 | } | ||
1082 | intdec++; | ||
1083 | } | ||
1084 | return 0; | ||
1085 | } | ||
1086 | |||
1087 | static int | ||
1088 | getmixer(struct cmdif *cif, short num, unsigned short *rval, | ||
1089 | unsigned short *lval) | ||
1090 | { | ||
1091 | union cmdret rptr = CMDRET_ZERO; | ||
1092 | |||
1093 | if (SEND_RDGV(cif, num, num, &rptr) && SEND_RDGV(cif, num, num, &rptr)) | ||
1094 | return -EIO; | ||
1095 | *rval = rptr.retwords[0]; | ||
1096 | *lval = rptr.retwords[1]; | ||
1097 | snd_printdd("got mixer %d: 0x%d 0x%d\n", num, *rval, *lval); | ||
1098 | return 0; | ||
1099 | } | ||
1100 | |||
1101 | static void riptide_handleirq(unsigned long dev_id) | ||
1102 | { | ||
1103 | struct snd_riptide *chip = (void *)dev_id; | ||
1104 | struct cmdif *cif = chip->cif; | ||
1105 | struct snd_pcm_substream *substream[PLAYBACK_SUBSTREAMS + 1]; | ||
1106 | struct snd_pcm_runtime *runtime; | ||
1107 | struct pcmhw *data = NULL; | ||
1108 | unsigned int pos, period_bytes; | ||
1109 | struct sgd *c; | ||
1110 | int i, j; | ||
1111 | unsigned int flag; | ||
1112 | |||
1113 | if (!cif) | ||
1114 | return; | ||
1115 | |||
1116 | for (i = 0; i < PLAYBACK_SUBSTREAMS; i++) | ||
1117 | substream[i] = chip->playback_substream[i]; | ||
1118 | substream[i] = chip->capture_substream; | ||
1119 | for (i = 0; i < PLAYBACK_SUBSTREAMS + 1; i++) { | ||
1120 | if (substream[i] && | ||
1121 | (runtime = substream[i]->runtime) && | ||
1122 | (data = runtime->private_data) && data->state != ST_STOP) { | ||
1123 | pos = 0; | ||
1124 | for (j = 0; j < data->pages; j++) { | ||
1125 | c = &data->sgdbuf[j]; | ||
1126 | flag = le32_to_cpu(c->dwStat_Ctl); | ||
1127 | if (flag & EOB_STATUS) | ||
1128 | pos += le32_to_cpu(c->dwSegLen); | ||
1129 | if (flag & EOC_STATUS) | ||
1130 | pos += le32_to_cpu(c->dwSegLen); | ||
1131 | if ((flag & EOS_STATUS) | ||
1132 | && (data->state == ST_PLAY)) { | ||
1133 | data->state = ST_STOP; | ||
1134 | snd_printk(KERN_ERR | ||
1135 | "Riptide: DMA stopped unexpectedly\n"); | ||
1136 | } | ||
1137 | c->dwStat_Ctl = | ||
1138 | cpu_to_le32(flag & | ||
1139 | ~(EOS_STATUS | EOB_STATUS | | ||
1140 | EOC_STATUS)); | ||
1141 | } | ||
1142 | data->pointer += pos; | ||
1143 | pos += data->oldpos; | ||
1144 | if (data->state != ST_STOP) { | ||
1145 | period_bytes = | ||
1146 | frames_to_bytes(runtime, | ||
1147 | runtime->period_size); | ||
1148 | snd_printdd | ||
1149 | ("interrupt 0x%x after 0x%lx of 0x%lx frames in period\n", | ||
1150 | READ_AUDIO_STATUS(cif->hwport), | ||
1151 | bytes_to_frames(runtime, pos), | ||
1152 | runtime->period_size); | ||
1153 | j = 0; | ||
1154 | if (pos >= period_bytes) { | ||
1155 | j++; | ||
1156 | while (pos >= period_bytes) | ||
1157 | pos -= period_bytes; | ||
1158 | } | ||
1159 | data->oldpos = pos; | ||
1160 | if (j > 0) | ||
1161 | snd_pcm_period_elapsed(substream[i]); | ||
1162 | } | ||
1163 | } | ||
1164 | } | ||
1165 | } | ||
1166 | |||
1167 | #ifdef CONFIG_PM | ||
1168 | static int riptide_suspend(struct pci_dev *pci, pm_message_t state) | ||
1169 | { | ||
1170 | struct snd_card *card = pci_get_drvdata(pci); | ||
1171 | struct snd_riptide *chip = card->private_data; | ||
1172 | |||
1173 | chip->in_suspend = 1; | ||
1174 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); | ||
1175 | snd_pcm_suspend_all(chip->pcm); | ||
1176 | snd_ac97_suspend(chip->ac97); | ||
1177 | pci_set_power_state(pci, PCI_D3hot); | ||
1178 | pci_disable_device(pci); | ||
1179 | pci_save_state(pci); | ||
1180 | return 0; | ||
1181 | } | ||
1182 | |||
1183 | static int riptide_resume(struct pci_dev *pci) | ||
1184 | { | ||
1185 | struct snd_card *card = pci_get_drvdata(pci); | ||
1186 | struct snd_riptide *chip = card->private_data; | ||
1187 | |||
1188 | pci_restore_state(pci); | ||
1189 | pci_enable_device(pci); | ||
1190 | pci_set_power_state(pci, PCI_D0); | ||
1191 | pci_set_master(pci); | ||
1192 | snd_riptide_initialize(chip); | ||
1193 | snd_ac97_resume(chip->ac97); | ||
1194 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | ||
1195 | chip->in_suspend = 0; | ||
1196 | return 0; | ||
1197 | } | ||
1198 | #endif | ||
1199 | |||
1200 | static int riptide_reset(struct cmdif *cif, struct snd_riptide *chip) | ||
1201 | { | ||
1202 | int timeout, tries; | ||
1203 | union cmdret rptr = CMDRET_ZERO; | ||
1204 | union firmware_version firmware; | ||
1205 | int i, j, err, has_firmware; | ||
1206 | |||
1207 | if (!cif) | ||
1208 | return -EINVAL; | ||
1209 | |||
1210 | cif->cmdcnt = 0; | ||
1211 | cif->cmdtime = 0; | ||
1212 | cif->cmdtimemax = 0; | ||
1213 | cif->cmdtimemin = 0xffffffff; | ||
1214 | cif->errcnt = 0; | ||
1215 | cif->is_reset = 0; | ||
1216 | |||
1217 | tries = RESET_TRIES; | ||
1218 | has_firmware = 0; | ||
1219 | while (has_firmware == 0 && tries-- > 0) { | ||
1220 | for (i = 0; i < 2; i++) { | ||
1221 | WRITE_PORT_ULONG(cif->hwport->port[i].data1, 0); | ||
1222 | WRITE_PORT_ULONG(cif->hwport->port[i].data2, 0); | ||
1223 | } | ||
1224 | SET_GRESET(cif->hwport); | ||
1225 | udelay(100); | ||
1226 | UNSET_GRESET(cif->hwport); | ||
1227 | udelay(100); | ||
1228 | |||
1229 | for (timeout = 100000; --timeout; udelay(10)) { | ||
1230 | if (IS_READY(cif->hwport) && !IS_GERR(cif->hwport)) | ||
1231 | break; | ||
1232 | } | ||
1233 | if (timeout == 0) { | ||
1234 | snd_printk(KERN_ERR | ||
1235 | "Riptide: device not ready, audio status: 0x%x ready: %d gerr: %d\n", | ||
1236 | READ_AUDIO_STATUS(cif->hwport), | ||
1237 | IS_READY(cif->hwport), IS_GERR(cif->hwport)); | ||
1238 | return -EIO; | ||
1239 | } else { | ||
1240 | snd_printdd | ||
1241 | ("Riptide: audio status: 0x%x ready: %d gerr: %d\n", | ||
1242 | READ_AUDIO_STATUS(cif->hwport), | ||
1243 | IS_READY(cif->hwport), IS_GERR(cif->hwport)); | ||
1244 | } | ||
1245 | |||
1246 | SEND_GETV(cif, &rptr); | ||
1247 | for (i = 0; i < 4; i++) | ||
1248 | firmware.ret.retwords[i] = rptr.retwords[i]; | ||
1249 | |||
1250 | snd_printdd | ||
1251 | ("Firmware version: ASIC: %d CODEC %d AUXDSP %d PROG %d\n", | ||
1252 | firmware.firmware.ASIC, firmware.firmware.CODEC, | ||
1253 | firmware.firmware.AUXDSP, firmware.firmware.PROG); | ||
1254 | |||
1255 | for (j = 0; j < FIRMWARE_VERSIONS; j++) { | ||
1256 | has_firmware = 1; | ||
1257 | for (i = 0; i < 4; i++) { | ||
1258 | if (firmware_versions[j].ret.retwords[i] != | ||
1259 | firmware.ret.retwords[i]) | ||
1260 | has_firmware = 0; | ||
1261 | } | ||
1262 | if (has_firmware) | ||
1263 | break; | ||
1264 | } | ||
1265 | |||
1266 | if (chip != NULL && has_firmware == 0) { | ||
1267 | snd_printdd("Writing Firmware\n"); | ||
1268 | if (!chip->fw_entry) { | ||
1269 | if ((err = | ||
1270 | request_firmware(&chip->fw_entry, | ||
1271 | "riptide.hex", | ||
1272 | &chip->pci->dev)) != 0) { | ||
1273 | snd_printk(KERN_ERR | ||
1274 | "Riptide: Firmware not available %d\n", | ||
1275 | err); | ||
1276 | return -EIO; | ||
1277 | } | ||
1278 | } | ||
1279 | err = loadfirmware(cif, chip->fw_entry->data, | ||
1280 | chip->fw_entry->size); | ||
1281 | if (err) | ||
1282 | snd_printk(KERN_ERR | ||
1283 | "Riptide: Could not load firmware %d\n", | ||
1284 | err); | ||
1285 | } | ||
1286 | } | ||
1287 | |||
1288 | SEND_SACR(cif, 0, AC97_RESET); | ||
1289 | SEND_RACR(cif, AC97_RESET, &rptr); | ||
1290 | snd_printdd("AC97: 0x%x 0x%x\n", rptr.retlongs[0], rptr.retlongs[1]); | ||
1291 | |||
1292 | SEND_PLST(cif, 0); | ||
1293 | SEND_SLST(cif, 0); | ||
1294 | SEND_DLST(cif, 0); | ||
1295 | SEND_ALST(cif, 0); | ||
1296 | SEND_KDMA(cif); | ||
1297 | |||
1298 | writearm(cif, 0x301F8, 1, 1); | ||
1299 | writearm(cif, 0x301F4, 1, 1); | ||
1300 | |||
1301 | SEND_LSEL(cif, MODEM_CMD, 0, 0, MODEM_INTDEC, MODEM_MERGER, | ||
1302 | MODEM_SPLITTER, MODEM_MIXER); | ||
1303 | setmixer(cif, MODEM_MIXER, 0x7fff, 0x7fff); | ||
1304 | alloclbuspath(cif, ARM2LBUS_FIFO13, lbus_play_modem, NULL, NULL); | ||
1305 | |||
1306 | SEND_LSEL(cif, FM_CMD, 0, 0, FM_INTDEC, FM_MERGER, FM_SPLITTER, | ||
1307 | FM_MIXER); | ||
1308 | setmixer(cif, FM_MIXER, 0x7fff, 0x7fff); | ||
1309 | writearm(cif, 0x30648 + FM_MIXER * 4, 0x01, 0x00000005); | ||
1310 | writearm(cif, 0x301A8, 0x02, 0x00000002); | ||
1311 | writearm(cif, 0x30264, 0x08, 0xffffffff); | ||
1312 | alloclbuspath(cif, OPL3_SAMPLE, lbus_play_opl3, NULL, NULL); | ||
1313 | |||
1314 | SEND_SSRC(cif, I2S_INTDEC, 48000, | ||
1315 | ((u32) I2S_RATE * 65536) / 48000, | ||
1316 | ((u32) I2S_RATE * 65536) % 48000); | ||
1317 | SEND_LSEL(cif, I2S_CMD0, 0, 0, I2S_INTDEC, I2S_MERGER, I2S_SPLITTER, | ||
1318 | I2S_MIXER); | ||
1319 | SEND_SI2S(cif, 1); | ||
1320 | alloclbuspath(cif, ARM2LBUS_FIFO0, lbus_play_i2s, NULL, NULL); | ||
1321 | alloclbuspath(cif, DIGITAL_MIXER_OUT0, lbus_play_out, NULL, NULL); | ||
1322 | alloclbuspath(cif, DIGITAL_MIXER_OUT0, lbus_play_outhp, NULL, NULL); | ||
1323 | |||
1324 | SET_AIACK(cif->hwport); | ||
1325 | SET_AIE(cif->hwport); | ||
1326 | SET_AIACK(cif->hwport); | ||
1327 | cif->is_reset = 1; | ||
1328 | if (chip) { | ||
1329 | for (i = 0; i < 4; i++) | ||
1330 | chip->firmware.ret.retwords[i] = | ||
1331 | firmware.ret.retwords[i]; | ||
1332 | } | ||
1333 | |||
1334 | return 0; | ||
1335 | } | ||
1336 | |||
1337 | static struct snd_pcm_hardware snd_riptide_playback = { | ||
1338 | .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | | ||
1339 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
1340 | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_MMAP_VALID), | ||
1341 | .formats = | ||
1342 | SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | ||
1343 | | SNDRV_PCM_FMTBIT_U16_LE, | ||
1344 | .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000, | ||
1345 | .rate_min = 5500, | ||
1346 | .rate_max = 48000, | ||
1347 | .channels_min = 1, | ||
1348 | .channels_max = 2, | ||
1349 | .buffer_bytes_max = (64 * 1024), | ||
1350 | .period_bytes_min = PAGE_SIZE >> 1, | ||
1351 | .period_bytes_max = PAGE_SIZE << 8, | ||
1352 | .periods_min = 2, | ||
1353 | .periods_max = 64, | ||
1354 | .fifo_size = 0, | ||
1355 | }; | ||
1356 | static struct snd_pcm_hardware snd_riptide_capture = { | ||
1357 | .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | | ||
1358 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
1359 | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_MMAP_VALID), | ||
1360 | .formats = | ||
1361 | SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | ||
1362 | | SNDRV_PCM_FMTBIT_U16_LE, | ||
1363 | .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000, | ||
1364 | .rate_min = 5500, | ||
1365 | .rate_max = 48000, | ||
1366 | .channels_min = 1, | ||
1367 | .channels_max = 2, | ||
1368 | .buffer_bytes_max = (64 * 1024), | ||
1369 | .period_bytes_min = PAGE_SIZE >> 1, | ||
1370 | .period_bytes_max = PAGE_SIZE << 3, | ||
1371 | .periods_min = 2, | ||
1372 | .periods_max = 64, | ||
1373 | .fifo_size = 0, | ||
1374 | }; | ||
1375 | |||
1376 | static snd_pcm_uframes_t snd_riptide_pointer(struct snd_pcm_substream | ||
1377 | *substream) | ||
1378 | { | ||
1379 | struct snd_riptide *chip = snd_pcm_substream_chip(substream); | ||
1380 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
1381 | struct pcmhw *data = get_pcmhwdev(substream); | ||
1382 | struct cmdif *cif = chip->cif; | ||
1383 | union cmdret rptr = CMDRET_ZERO; | ||
1384 | snd_pcm_uframes_t ret; | ||
1385 | |||
1386 | SEND_GPOS(cif, 0, data->id, &rptr); | ||
1387 | if (data->size && runtime->period_size) { | ||
1388 | snd_printdd | ||
1389 | ("pointer stream %d position 0x%x(0x%x in buffer) bytes 0x%lx(0x%lx in period) frames\n", | ||
1390 | data->id, rptr.retlongs[1], rptr.retlongs[1] % data->size, | ||
1391 | bytes_to_frames(runtime, rptr.retlongs[1]), | ||
1392 | bytes_to_frames(runtime, | ||
1393 | rptr.retlongs[1]) % runtime->period_size); | ||
1394 | if (rptr.retlongs[1] > data->pointer) | ||
1395 | ret = | ||
1396 | bytes_to_frames(runtime, | ||
1397 | rptr.retlongs[1] % data->size); | ||
1398 | else | ||
1399 | ret = | ||
1400 | bytes_to_frames(runtime, | ||
1401 | data->pointer % data->size); | ||
1402 | } else { | ||
1403 | snd_printdd("stream not started or strange parms (%d %ld)\n", | ||
1404 | data->size, runtime->period_size); | ||
1405 | ret = bytes_to_frames(runtime, 0); | ||
1406 | } | ||
1407 | return ret; | ||
1408 | } | ||
1409 | |||
1410 | static int snd_riptide_trigger(struct snd_pcm_substream *substream, int cmd) | ||
1411 | { | ||
1412 | int i, j; | ||
1413 | struct snd_riptide *chip = snd_pcm_substream_chip(substream); | ||
1414 | struct pcmhw *data = get_pcmhwdev(substream); | ||
1415 | struct cmdif *cif = chip->cif; | ||
1416 | union cmdret rptr = CMDRET_ZERO; | ||
1417 | |||
1418 | spin_lock(&chip->lock); | ||
1419 | switch (cmd) { | ||
1420 | case SNDRV_PCM_TRIGGER_START: | ||
1421 | case SNDRV_PCM_TRIGGER_RESUME: | ||
1422 | if (!(data->state & ST_PLAY)) { | ||
1423 | SEND_SSTR(cif, data->id, data->sgdlist.addr); | ||
1424 | SET_AIE(cif->hwport); | ||
1425 | data->state = ST_PLAY; | ||
1426 | if (data->mixer != 0xff) | ||
1427 | setmixer(cif, data->mixer, 0x7fff, 0x7fff); | ||
1428 | chip->openstreams++; | ||
1429 | data->oldpos = 0; | ||
1430 | data->pointer = 0; | ||
1431 | } | ||
1432 | break; | ||
1433 | case SNDRV_PCM_TRIGGER_STOP: | ||
1434 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
1435 | if (data->mixer != 0xff) | ||
1436 | setmixer(cif, data->mixer, 0, 0); | ||
1437 | setmixer(cif, data->mixer, 0, 0); | ||
1438 | SEND_KSTR(cif, data->id); | ||
1439 | data->state = ST_STOP; | ||
1440 | chip->openstreams--; | ||
1441 | j = 0; | ||
1442 | do { | ||
1443 | i = rptr.retlongs[1]; | ||
1444 | SEND_GPOS(cif, 0, data->id, &rptr); | ||
1445 | udelay(1); | ||
1446 | } while (i != rptr.retlongs[1] && j++ < MAX_WRITE_RETRY); | ||
1447 | if (j >= MAX_WRITE_RETRY) | ||
1448 | snd_printk(KERN_ERR "Riptide: Could not stop stream!"); | ||
1449 | break; | ||
1450 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
1451 | if (!(data->state & ST_PAUSE)) { | ||
1452 | SEND_PSTR(cif, data->id); | ||
1453 | data->state |= ST_PAUSE; | ||
1454 | chip->openstreams--; | ||
1455 | } | ||
1456 | break; | ||
1457 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
1458 | if (data->state & ST_PAUSE) { | ||
1459 | SEND_SSTR(cif, data->id, data->sgdlist.addr); | ||
1460 | data->state &= ~ST_PAUSE; | ||
1461 | chip->openstreams++; | ||
1462 | } | ||
1463 | break; | ||
1464 | default: | ||
1465 | spin_unlock(&chip->lock); | ||
1466 | return -EINVAL; | ||
1467 | } | ||
1468 | spin_unlock(&chip->lock); | ||
1469 | return 0; | ||
1470 | } | ||
1471 | |||
1472 | static int snd_riptide_prepare(struct snd_pcm_substream *substream) | ||
1473 | { | ||
1474 | struct snd_riptide *chip = snd_pcm_substream_chip(substream); | ||
1475 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
1476 | struct snd_sg_buf *sgbuf = snd_pcm_substream_sgbuf(substream); | ||
1477 | struct pcmhw *data = get_pcmhwdev(substream); | ||
1478 | struct cmdif *cif = chip->cif; | ||
1479 | unsigned char *lbuspath = NULL; | ||
1480 | unsigned int rate, channels; | ||
1481 | int err = 0; | ||
1482 | snd_pcm_format_t format; | ||
1483 | |||
1484 | snd_assert(cif && data, return -EINVAL); | ||
1485 | |||
1486 | snd_printdd("prepare id %d ch: %d f:0x%x r:%d\n", data->id, | ||
1487 | runtime->channels, runtime->format, runtime->rate); | ||
1488 | |||
1489 | spin_lock_irq(&chip->lock); | ||
1490 | channels = runtime->channels; | ||
1491 | format = runtime->format; | ||
1492 | rate = runtime->rate; | ||
1493 | switch (channels) { | ||
1494 | case 1: | ||
1495 | if (rate == 48000 && format == SNDRV_PCM_FORMAT_S16_LE) | ||
1496 | lbuspath = data->paths.noconv; | ||
1497 | else | ||
1498 | lbuspath = data->paths.mono; | ||
1499 | break; | ||
1500 | case 2: | ||
1501 | if (rate == 48000 && format == SNDRV_PCM_FORMAT_S16_LE) | ||
1502 | lbuspath = data->paths.noconv; | ||
1503 | else | ||
1504 | lbuspath = data->paths.stereo; | ||
1505 | break; | ||
1506 | } | ||
1507 | snd_printdd("use sgdlist at 0x%p and buffer at 0x%p\n", | ||
1508 | data->sgdlist.area, sgbuf); | ||
1509 | if (data->sgdlist.area && sgbuf) { | ||
1510 | unsigned int i, j, size, pages, f, pt, period; | ||
1511 | struct sgd *c, *p = NULL; | ||
1512 | |||
1513 | size = frames_to_bytes(runtime, runtime->buffer_size); | ||
1514 | period = frames_to_bytes(runtime, runtime->period_size); | ||
1515 | f = PAGE_SIZE; | ||
1516 | while ((size + (f >> 1) - 1) <= (f << 7) && (f << 1) > period) | ||
1517 | f = f >> 1; | ||
1518 | pages = (size + f - 1) / f; | ||
1519 | data->size = size; | ||
1520 | data->pages = pages; | ||
1521 | snd_printdd | ||
1522 | ("create sgd size: 0x%x pages %d of size 0x%x for period 0x%x\n", | ||
1523 | size, pages, f, period); | ||
1524 | pt = 0; | ||
1525 | j = 0; | ||
1526 | for (i = 0; i < pages; i++) { | ||
1527 | c = &data->sgdbuf[i]; | ||
1528 | if (p) | ||
1529 | p->dwNextLink = cpu_to_le32(data->sgdlist.addr + | ||
1530 | (i * | ||
1531 | sizeof(struct | ||
1532 | sgd))); | ||
1533 | c->dwNextLink = cpu_to_le32(data->sgdlist.addr); | ||
1534 | c->dwSegPtrPhys = | ||
1535 | cpu_to_le32(sgbuf->table[j].addr + pt); | ||
1536 | pt = (pt + f) % PAGE_SIZE; | ||
1537 | if (pt == 0) | ||
1538 | j++; | ||
1539 | c->dwSegLen = cpu_to_le32(f); | ||
1540 | c->dwStat_Ctl = | ||
1541 | cpu_to_le32(IEOB_ENABLE | IEOS_ENABLE | | ||
1542 | IEOC_ENABLE); | ||
1543 | p = c; | ||
1544 | size -= f; | ||
1545 | } | ||
1546 | data->sgdbuf[i].dwSegLen = cpu_to_le32(size); | ||
1547 | } | ||
1548 | if (lbuspath && lbuspath != data->lbuspath) { | ||
1549 | if (data->lbuspath) | ||
1550 | freelbuspath(cif, data->source, data->lbuspath); | ||
1551 | alloclbuspath(cif, data->source, lbuspath, | ||
1552 | &data->mixer, data->intdec); | ||
1553 | data->lbuspath = lbuspath; | ||
1554 | data->rate = 0; | ||
1555 | } | ||
1556 | if (data->rate != rate || data->format != format || | ||
1557 | data->channels != channels) { | ||
1558 | data->rate = rate; | ||
1559 | data->format = format; | ||
1560 | data->channels = channels; | ||
1561 | if (setsampleformat | ||
1562 | (cif, data->mixer, data->id, channels, format) | ||
1563 | || setsamplerate(cif, data->intdec, rate)) | ||
1564 | err = -EIO; | ||
1565 | } | ||
1566 | spin_unlock_irq(&chip->lock); | ||
1567 | return err; | ||
1568 | } | ||
1569 | |||
1570 | static int | ||
1571 | snd_riptide_hw_params(struct snd_pcm_substream *substream, | ||
1572 | struct snd_pcm_hw_params *hw_params) | ||
1573 | { | ||
1574 | struct snd_riptide *chip = snd_pcm_substream_chip(substream); | ||
1575 | struct pcmhw *data = get_pcmhwdev(substream); | ||
1576 | struct snd_dma_buffer *sgdlist = &data->sgdlist; | ||
1577 | int err; | ||
1578 | |||
1579 | snd_printdd("hw params id %d (sgdlist: 0x%p 0x%lx %d)\n", data->id, | ||
1580 | sgdlist->area, (unsigned long)sgdlist->addr, | ||
1581 | (int)sgdlist->bytes); | ||
1582 | if (sgdlist->area) | ||
1583 | snd_dma_free_pages(sgdlist); | ||
1584 | if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, | ||
1585 | snd_dma_pci_data(chip->pci), | ||
1586 | sizeof(struct sgd) * (DESC_MAX_MASK + 1), | ||
1587 | sgdlist)) < 0) { | ||
1588 | snd_printk(KERN_ERR "Riptide: failed to alloc %d dma bytes\n", | ||
1589 | (int)sizeof(struct sgd) * (DESC_MAX_MASK + 1)); | ||
1590 | return err; | ||
1591 | } | ||
1592 | data->sgdbuf = (struct sgd *)sgdlist->area; | ||
1593 | return snd_pcm_lib_malloc_pages(substream, | ||
1594 | params_buffer_bytes(hw_params)); | ||
1595 | } | ||
1596 | |||
1597 | static int snd_riptide_hw_free(struct snd_pcm_substream *substream) | ||
1598 | { | ||
1599 | struct snd_riptide *chip = snd_pcm_substream_chip(substream); | ||
1600 | struct pcmhw *data = get_pcmhwdev(substream); | ||
1601 | struct cmdif *cif = chip->cif; | ||
1602 | |||
1603 | if (cif && data) { | ||
1604 | if (data->lbuspath) | ||
1605 | freelbuspath(cif, data->source, data->lbuspath); | ||
1606 | data->lbuspath = NULL; | ||
1607 | data->source = 0xff; | ||
1608 | data->intdec[0] = 0xff; | ||
1609 | data->intdec[1] = 0xff; | ||
1610 | |||
1611 | if (data->sgdlist.area) { | ||
1612 | snd_dma_free_pages(&data->sgdlist); | ||
1613 | data->sgdlist.area = NULL; | ||
1614 | } | ||
1615 | } | ||
1616 | return snd_pcm_lib_free_pages(substream); | ||
1617 | } | ||
1618 | |||
1619 | static int snd_riptide_playback_open(struct snd_pcm_substream *substream) | ||
1620 | { | ||
1621 | struct snd_riptide *chip = snd_pcm_substream_chip(substream); | ||
1622 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
1623 | struct pcmhw *data; | ||
1624 | int index = substream->number; | ||
1625 | |||
1626 | chip->playback_substream[index] = substream; | ||
1627 | runtime->hw = snd_riptide_playback; | ||
1628 | data = kzalloc(sizeof(struct pcmhw), GFP_KERNEL); | ||
1629 | data->paths = lbus_play_paths[index]; | ||
1630 | data->id = play_ids[index]; | ||
1631 | data->source = play_sources[index]; | ||
1632 | data->intdec[0] = 0xff; | ||
1633 | data->intdec[1] = 0xff; | ||
1634 | data->state = ST_STOP; | ||
1635 | runtime->private_data = data; | ||
1636 | return snd_pcm_hw_constraint_integer(runtime, | ||
1637 | SNDRV_PCM_HW_PARAM_PERIODS); | ||
1638 | } | ||
1639 | |||
1640 | static int snd_riptide_capture_open(struct snd_pcm_substream *substream) | ||
1641 | { | ||
1642 | struct snd_riptide *chip = snd_pcm_substream_chip(substream); | ||
1643 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
1644 | struct pcmhw *data; | ||
1645 | |||
1646 | chip->capture_substream = substream; | ||
1647 | runtime->hw = snd_riptide_capture; | ||
1648 | data = kzalloc(sizeof(struct pcmhw), GFP_KERNEL); | ||
1649 | data->paths = lbus_rec_path; | ||
1650 | data->id = PADC; | ||
1651 | data->source = ACLNK2PADC; | ||
1652 | data->intdec[0] = 0xff; | ||
1653 | data->intdec[1] = 0xff; | ||
1654 | data->state = ST_STOP; | ||
1655 | runtime->private_data = data; | ||
1656 | return snd_pcm_hw_constraint_integer(runtime, | ||
1657 | SNDRV_PCM_HW_PARAM_PERIODS); | ||
1658 | } | ||
1659 | |||
1660 | static int snd_riptide_playback_close(struct snd_pcm_substream *substream) | ||
1661 | { | ||
1662 | struct snd_riptide *chip = snd_pcm_substream_chip(substream); | ||
1663 | struct pcmhw *data = get_pcmhwdev(substream); | ||
1664 | int index = substream->number; | ||
1665 | |||
1666 | substream->runtime->private_data = NULL; | ||
1667 | chip->playback_substream[index] = NULL; | ||
1668 | kfree(data); | ||
1669 | return 0; | ||
1670 | } | ||
1671 | |||
1672 | static int snd_riptide_capture_close(struct snd_pcm_substream *substream) | ||
1673 | { | ||
1674 | struct snd_riptide *chip = snd_pcm_substream_chip(substream); | ||
1675 | struct pcmhw *data = get_pcmhwdev(substream); | ||
1676 | |||
1677 | substream->runtime->private_data = NULL; | ||
1678 | chip->capture_substream = NULL; | ||
1679 | kfree(data); | ||
1680 | return 0; | ||
1681 | } | ||
1682 | |||
1683 | static struct snd_pcm_ops snd_riptide_playback_ops = { | ||
1684 | .open = snd_riptide_playback_open, | ||
1685 | .close = snd_riptide_playback_close, | ||
1686 | .ioctl = snd_pcm_lib_ioctl, | ||
1687 | .hw_params = snd_riptide_hw_params, | ||
1688 | .hw_free = snd_riptide_hw_free, | ||
1689 | .prepare = snd_riptide_prepare, | ||
1690 | .page = snd_pcm_sgbuf_ops_page, | ||
1691 | .trigger = snd_riptide_trigger, | ||
1692 | .pointer = snd_riptide_pointer, | ||
1693 | }; | ||
1694 | static struct snd_pcm_ops snd_riptide_capture_ops = { | ||
1695 | .open = snd_riptide_capture_open, | ||
1696 | .close = snd_riptide_capture_close, | ||
1697 | .ioctl = snd_pcm_lib_ioctl, | ||
1698 | .hw_params = snd_riptide_hw_params, | ||
1699 | .hw_free = snd_riptide_hw_free, | ||
1700 | .prepare = snd_riptide_prepare, | ||
1701 | .page = snd_pcm_sgbuf_ops_page, | ||
1702 | .trigger = snd_riptide_trigger, | ||
1703 | .pointer = snd_riptide_pointer, | ||
1704 | }; | ||
1705 | |||
1706 | static int __devinit | ||
1707 | snd_riptide_pcm(struct snd_riptide *chip, int device, struct snd_pcm **rpcm) | ||
1708 | { | ||
1709 | struct snd_pcm *pcm; | ||
1710 | int err; | ||
1711 | |||
1712 | if (rpcm) | ||
1713 | *rpcm = NULL; | ||
1714 | if ((err = | ||
1715 | snd_pcm_new(chip->card, "RIPTIDE", device, PLAYBACK_SUBSTREAMS, 1, | ||
1716 | &pcm)) < 0) | ||
1717 | return err; | ||
1718 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, | ||
1719 | &snd_riptide_playback_ops); | ||
1720 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, | ||
1721 | &snd_riptide_capture_ops); | ||
1722 | pcm->private_data = chip; | ||
1723 | pcm->info_flags = 0; | ||
1724 | strcpy(pcm->name, "RIPTIDE"); | ||
1725 | chip->pcm = pcm; | ||
1726 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, | ||
1727 | snd_dma_pci_data(chip->pci), | ||
1728 | 64 * 1024, 128 * 1024); | ||
1729 | if (rpcm) | ||
1730 | *rpcm = pcm; | ||
1731 | return 0; | ||
1732 | } | ||
1733 | |||
1734 | static irqreturn_t | ||
1735 | snd_riptide_interrupt(int irq, void *dev_id, struct pt_regs *regs) | ||
1736 | { | ||
1737 | struct snd_riptide *chip = dev_id; | ||
1738 | struct cmdif *cif = chip->cif; | ||
1739 | |||
1740 | if (cif) { | ||
1741 | chip->received_irqs++; | ||
1742 | if (IS_EOBIRQ(cif->hwport) || IS_EOSIRQ(cif->hwport) || | ||
1743 | IS_EOCIRQ(cif->hwport)) { | ||
1744 | chip->handled_irqs++; | ||
1745 | tasklet_hi_schedule(&chip->riptide_tq); | ||
1746 | } | ||
1747 | if (chip->rmidi && IS_MPUIRQ(cif->hwport)) { | ||
1748 | chip->handled_irqs++; | ||
1749 | snd_mpu401_uart_interrupt(irq, | ||
1750 | chip->rmidi->private_data, | ||
1751 | regs); | ||
1752 | } | ||
1753 | SET_AIACK(cif->hwport); | ||
1754 | } | ||
1755 | return IRQ_HANDLED; | ||
1756 | } | ||
1757 | |||
1758 | static void | ||
1759 | snd_riptide_codec_write(struct snd_ac97 *ac97, unsigned short reg, | ||
1760 | unsigned short val) | ||
1761 | { | ||
1762 | struct snd_riptide *chip = ac97->private_data; | ||
1763 | struct cmdif *cif = chip->cif; | ||
1764 | union cmdret rptr = CMDRET_ZERO; | ||
1765 | int i = 0; | ||
1766 | |||
1767 | snd_assert(cif, return); | ||
1768 | |||
1769 | snd_printdd("Write AC97 reg 0x%x 0x%x\n", reg, val); | ||
1770 | do { | ||
1771 | SEND_SACR(cif, val, reg); | ||
1772 | SEND_RACR(cif, reg, &rptr); | ||
1773 | } while (rptr.retwords[1] != val && i++ < MAX_WRITE_RETRY); | ||
1774 | if (i == MAX_WRITE_RETRY) | ||
1775 | snd_printdd("Write AC97 reg failed\n"); | ||
1776 | } | ||
1777 | |||
1778 | static unsigned short snd_riptide_codec_read(struct snd_ac97 *ac97, | ||
1779 | unsigned short reg) | ||
1780 | { | ||
1781 | struct snd_riptide *chip = ac97->private_data; | ||
1782 | struct cmdif *cif = chip->cif; | ||
1783 | union cmdret rptr = CMDRET_ZERO; | ||
1784 | |||
1785 | snd_assert(cif, return 0); | ||
1786 | |||
1787 | if (SEND_RACR(cif, reg, &rptr) != 0) | ||
1788 | SEND_RACR(cif, reg, &rptr); | ||
1789 | snd_printdd("Read AC97 reg 0x%x got 0x%x\n", reg, rptr.retwords[1]); | ||
1790 | return rptr.retwords[1]; | ||
1791 | } | ||
1792 | |||
1793 | static int snd_riptide_initialize(struct snd_riptide *chip) | ||
1794 | { | ||
1795 | struct cmdif *cif; | ||
1796 | unsigned int device_id; | ||
1797 | int err; | ||
1798 | |||
1799 | snd_assert(chip, return -EINVAL); | ||
1800 | |||
1801 | cif = chip->cif; | ||
1802 | if (!cif) { | ||
1803 | if ((cif = kzalloc(sizeof(struct cmdif), GFP_KERNEL)) == NULL) | ||
1804 | return -ENOMEM; | ||
1805 | cif->hwport = (struct riptideport *)chip->port; | ||
1806 | spin_lock_init(&cif->lock); | ||
1807 | chip->cif = cif; | ||
1808 | } | ||
1809 | cif->is_reset = 0; | ||
1810 | if ((err = riptide_reset(cif, chip)) != 0) | ||
1811 | return err; | ||
1812 | device_id = chip->device_id; | ||
1813 | switch (device_id) { | ||
1814 | case 0x4310: | ||
1815 | case 0x4320: | ||
1816 | case 0x4330: | ||
1817 | snd_printdd("Modem enable?\n"); | ||
1818 | SEND_SETDPLL(cif); | ||
1819 | break; | ||
1820 | } | ||
1821 | snd_printdd("Enabling MPU IRQs\n"); | ||
1822 | if (chip->rmidi) | ||
1823 | SET_EMPUIRQ(cif->hwport); | ||
1824 | return err; | ||
1825 | } | ||
1826 | |||
1827 | static int snd_riptide_free(struct snd_riptide *chip) | ||
1828 | { | ||
1829 | struct cmdif *cif; | ||
1830 | |||
1831 | snd_assert(chip, return 0); | ||
1832 | |||
1833 | if ((cif = chip->cif)) { | ||
1834 | SET_GRESET(cif->hwport); | ||
1835 | udelay(100); | ||
1836 | UNSET_GRESET(cif->hwport); | ||
1837 | kfree(chip->cif); | ||
1838 | } | ||
1839 | if (chip->fw_entry) | ||
1840 | release_firmware(chip->fw_entry); | ||
1841 | release_and_free_resource(chip->res_port); | ||
1842 | if (chip->irq >= 0) | ||
1843 | free_irq(chip->irq, chip); | ||
1844 | kfree(chip); | ||
1845 | return 0; | ||
1846 | } | ||
1847 | |||
1848 | static int snd_riptide_dev_free(struct snd_device *device) | ||
1849 | { | ||
1850 | struct snd_riptide *chip = device->device_data; | ||
1851 | |||
1852 | return snd_riptide_free(chip); | ||
1853 | } | ||
1854 | |||
1855 | static int __devinit | ||
1856 | snd_riptide_create(struct snd_card *card, struct pci_dev *pci, | ||
1857 | struct snd_riptide **rchip) | ||
1858 | { | ||
1859 | struct snd_riptide *chip; | ||
1860 | struct riptideport *hwport; | ||
1861 | int err; | ||
1862 | static struct snd_device_ops ops = { | ||
1863 | .dev_free = snd_riptide_dev_free, | ||
1864 | }; | ||
1865 | |||
1866 | *rchip = NULL; | ||
1867 | if ((err = pci_enable_device(pci)) < 0) | ||
1868 | return err; | ||
1869 | if (!(chip = kzalloc(sizeof(struct snd_riptide), GFP_KERNEL))) | ||
1870 | return -ENOMEM; | ||
1871 | |||
1872 | spin_lock_init(&chip->lock); | ||
1873 | chip->card = card; | ||
1874 | chip->pci = pci; | ||
1875 | chip->irq = -1; | ||
1876 | chip->openstreams = 0; | ||
1877 | chip->port = pci_resource_start(pci, 0); | ||
1878 | chip->received_irqs = 0; | ||
1879 | chip->handled_irqs = 0; | ||
1880 | chip->cif = NULL; | ||
1881 | tasklet_init(&chip->riptide_tq, riptide_handleirq, (unsigned long)chip); | ||
1882 | |||
1883 | if ((chip->res_port = | ||
1884 | request_region(chip->port, 64, "RIPTIDE")) == NULL) { | ||
1885 | snd_printk(KERN_ERR | ||
1886 | "Riptide: unable to grab region 0x%lx-0x%lx\n", | ||
1887 | chip->port, chip->port + 64 - 1); | ||
1888 | snd_riptide_free(chip); | ||
1889 | return -EBUSY; | ||
1890 | } | ||
1891 | hwport = (struct riptideport *)chip->port; | ||
1892 | UNSET_AIE(hwport); | ||
1893 | |||
1894 | if (request_irq | ||
1895 | (pci->irq, snd_riptide_interrupt, SA_INTERRUPT | SA_SHIRQ, | ||
1896 | "RIPTIDE", chip)) { | ||
1897 | snd_printk(KERN_ERR "Riptide: unable to grab IRQ %d\n", | ||
1898 | pci->irq); | ||
1899 | snd_riptide_free(chip); | ||
1900 | return -EBUSY; | ||
1901 | } | ||
1902 | chip->irq = pci->irq; | ||
1903 | chip->device_id = pci->device; | ||
1904 | pci_set_master(pci); | ||
1905 | if ((err = snd_riptide_initialize(chip)) < 0) { | ||
1906 | snd_riptide_free(chip); | ||
1907 | return err; | ||
1908 | } | ||
1909 | |||
1910 | if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { | ||
1911 | snd_riptide_free(chip); | ||
1912 | return err; | ||
1913 | } | ||
1914 | |||
1915 | *rchip = chip; | ||
1916 | return 0; | ||
1917 | } | ||
1918 | |||
1919 | static void | ||
1920 | snd_riptide_proc_read(struct snd_info_entry *entry, | ||
1921 | struct snd_info_buffer *buffer) | ||
1922 | { | ||
1923 | struct snd_riptide *chip = entry->private_data; | ||
1924 | struct pcmhw *data; | ||
1925 | int i; | ||
1926 | struct cmdif *cif = NULL; | ||
1927 | unsigned char p[256]; | ||
1928 | unsigned short rval = 0, lval = 0; | ||
1929 | unsigned int rate; | ||
1930 | |||
1931 | if (!chip) | ||
1932 | return; | ||
1933 | |||
1934 | snd_iprintf(buffer, "%s\n\n", chip->card->longname); | ||
1935 | snd_iprintf(buffer, "Device ID: 0x%x\nReceived IRQs: (%ld)%ld\nPorts:", | ||
1936 | chip->device_id, chip->handled_irqs, chip->received_irqs); | ||
1937 | for (i = 0; i < 64; i += 4) | ||
1938 | snd_iprintf(buffer, "%c%02x: %08x", | ||
1939 | (i % 16) ? ' ' : '\n', i, inl(chip->port + i)); | ||
1940 | if ((cif = chip->cif)) { | ||
1941 | snd_iprintf(buffer, | ||
1942 | "\nVersion: ASIC: %d CODEC: %d AUXDSP: %d PROG: %d", | ||
1943 | chip->firmware.firmware.ASIC, | ||
1944 | chip->firmware.firmware.CODEC, | ||
1945 | chip->firmware.firmware.AUXDSP, | ||
1946 | chip->firmware.firmware.PROG); | ||
1947 | snd_iprintf(buffer, "\nDigital mixer:"); | ||
1948 | for (i = 0; i < 12; i++) { | ||
1949 | getmixer(cif, i, &rval, &lval); | ||
1950 | snd_iprintf(buffer, "\n %d: %d %d", i, rval, lval); | ||
1951 | } | ||
1952 | snd_iprintf(buffer, | ||
1953 | "\nARM Commands num: %d failed: %d time: %d max: %d min: %d", | ||
1954 | cif->cmdcnt, cif->errcnt, | ||
1955 | cif->cmdtime, cif->cmdtimemax, cif->cmdtimemin); | ||
1956 | } | ||
1957 | snd_iprintf(buffer, "\nOpen streams %d:\n", chip->openstreams); | ||
1958 | for (i = 0; i < PLAYBACK_SUBSTREAMS; i++) { | ||
1959 | if (chip->playback_substream[i] | ||
1960 | && chip->playback_substream[i]->runtime | ||
1961 | && (data = | ||
1962 | chip->playback_substream[i]->runtime->private_data)) { | ||
1963 | snd_iprintf(buffer, | ||
1964 | "stream: %d mixer: %d source: %d (%d,%d)\n", | ||
1965 | data->id, data->mixer, data->source, | ||
1966 | data->intdec[0], data->intdec[1]); | ||
1967 | if (!(getsamplerate(cif, data->intdec, &rate))) | ||
1968 | snd_iprintf(buffer, "rate: %d\n", rate); | ||
1969 | } | ||
1970 | } | ||
1971 | if (chip->capture_substream | ||
1972 | && chip->capture_substream->runtime | ||
1973 | && (data = chip->capture_substream->runtime->private_data)) { | ||
1974 | snd_iprintf(buffer, | ||
1975 | "stream: %d mixer: %d source: %d (%d,%d)\n", | ||
1976 | data->id, data->mixer, | ||
1977 | data->source, data->intdec[0], data->intdec[1]); | ||
1978 | if (!(getsamplerate(cif, data->intdec, &rate))) | ||
1979 | snd_iprintf(buffer, "rate: %d\n", rate); | ||
1980 | } | ||
1981 | snd_iprintf(buffer, "Paths:\n"); | ||
1982 | i = getpaths(cif, p); | ||
1983 | while (i--) { | ||
1984 | snd_iprintf(buffer, "%x->%x ", p[i - 1], p[i]); | ||
1985 | i--; | ||
1986 | } | ||
1987 | snd_iprintf(buffer, "\n"); | ||
1988 | } | ||
1989 | |||
1990 | static void __devinit snd_riptide_proc_init(struct snd_riptide *chip) | ||
1991 | { | ||
1992 | struct snd_info_entry *entry; | ||
1993 | |||
1994 | if (!snd_card_proc_new(chip->card, "riptide", &entry)) | ||
1995 | snd_info_set_text_ops(entry, chip, 4096, snd_riptide_proc_read); | ||
1996 | } | ||
1997 | |||
1998 | static int __devinit snd_riptide_mixer(struct snd_riptide *chip) | ||
1999 | { | ||
2000 | struct snd_ac97_bus *pbus; | ||
2001 | struct snd_ac97_template ac97; | ||
2002 | int err = 0; | ||
2003 | static struct snd_ac97_bus_ops ops = { | ||
2004 | .write = snd_riptide_codec_write, | ||
2005 | .read = snd_riptide_codec_read, | ||
2006 | }; | ||
2007 | |||
2008 | memset(&ac97, 0, sizeof(ac97)); | ||
2009 | ac97.private_data = chip; | ||
2010 | ac97.scaps = AC97_SCAP_SKIP_MODEM; | ||
2011 | |||
2012 | if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &pbus)) < 0) | ||
2013 | return err; | ||
2014 | |||
2015 | chip->ac97_bus = pbus; | ||
2016 | ac97.pci = chip->pci; | ||
2017 | if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97)) < 0) | ||
2018 | return err; | ||
2019 | return err; | ||
2020 | } | ||
2021 | |||
2022 | #ifdef SUPPORT_JOYSTICK | ||
2023 | static int have_joystick; | ||
2024 | static struct pci_dev *riptide_gameport_pci; | ||
2025 | static struct gameport *riptide_gameport; | ||
2026 | |||
2027 | static int __devinit | ||
2028 | snd_riptide_joystick_probe(struct pci_dev *pci, const struct pci_device_id *id) | ||
2029 | { | ||
2030 | static int dev; | ||
2031 | |||
2032 | if (dev >= SNDRV_CARDS) | ||
2033 | return -ENODEV; | ||
2034 | if (!enable[dev]) { | ||
2035 | dev++; | ||
2036 | return -ENOENT; | ||
2037 | } | ||
2038 | |||
2039 | if (joystick_port[dev]) { | ||
2040 | riptide_gameport = gameport_allocate_port(); | ||
2041 | if (riptide_gameport) { | ||
2042 | if (!request_region | ||
2043 | (joystick_port[dev], 8, "Riptide gameport")) { | ||
2044 | snd_printk(KERN_WARNING | ||
2045 | "Riptide: cannot grab gameport 0x%x\n", | ||
2046 | joystick_port[dev]); | ||
2047 | gameport_free_port(riptide_gameport); | ||
2048 | riptide_gameport = NULL; | ||
2049 | } else { | ||
2050 | riptide_gameport_pci = pci; | ||
2051 | riptide_gameport->io = joystick_port[dev]; | ||
2052 | gameport_register_port(riptide_gameport); | ||
2053 | } | ||
2054 | } | ||
2055 | } | ||
2056 | dev++; | ||
2057 | return 0; | ||
2058 | } | ||
2059 | |||
2060 | static void __devexit snd_riptide_joystick_remove(struct pci_dev *pci) | ||
2061 | { | ||
2062 | if (riptide_gameport) { | ||
2063 | if (riptide_gameport_pci == pci) { | ||
2064 | release_region(riptide_gameport->io, 8); | ||
2065 | riptide_gameport_pci = NULL; | ||
2066 | gameport_unregister_port(riptide_gameport); | ||
2067 | riptide_gameport = NULL; | ||
2068 | } | ||
2069 | } | ||
2070 | } | ||
2071 | #endif | ||
2072 | |||
2073 | static int __devinit | ||
2074 | snd_card_riptide_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) | ||
2075 | { | ||
2076 | static int dev; | ||
2077 | struct snd_card *card; | ||
2078 | struct snd_riptide *chip; | ||
2079 | unsigned short addr; | ||
2080 | int err = 0; | ||
2081 | |||
2082 | if (dev >= SNDRV_CARDS) | ||
2083 | return -ENODEV; | ||
2084 | if (!enable[dev]) { | ||
2085 | dev++; | ||
2086 | return -ENOENT; | ||
2087 | } | ||
2088 | |||
2089 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | ||
2090 | if (card == NULL) | ||
2091 | return -ENOMEM; | ||
2092 | if ((err = snd_riptide_create(card, pci, &chip)) < 0) { | ||
2093 | snd_card_free(card); | ||
2094 | return err; | ||
2095 | } | ||
2096 | card->private_data = chip; | ||
2097 | if ((err = snd_riptide_pcm(chip, 0, NULL)) < 0) { | ||
2098 | snd_card_free(card); | ||
2099 | return err; | ||
2100 | } | ||
2101 | if ((err = snd_riptide_mixer(chip)) < 0) { | ||
2102 | snd_card_free(card); | ||
2103 | return err; | ||
2104 | } | ||
2105 | pci_write_config_word(chip->pci, PCI_EXT_Legacy_Mask, LEGACY_ENABLE_ALL | ||
2106 | | (opl3_port[dev] ? LEGACY_ENABLE_FM : 0) | ||
2107 | #ifdef SUPPORT_JOYSTICK | ||
2108 | | (joystick_port[dev] ? LEGACY_ENABLE_GAMEPORT : | ||
2109 | 0) | ||
2110 | #endif | ||
2111 | | (mpu_port[dev] | ||
2112 | ? (LEGACY_ENABLE_MPU_INT | LEGACY_ENABLE_MPU) : | ||
2113 | 0) | ||
2114 | | ((chip->irq << 4) & 0xF0)); | ||
2115 | if ((addr = mpu_port[dev]) != 0) { | ||
2116 | pci_write_config_word(chip->pci, PCI_EXT_MPU_Base, addr); | ||
2117 | if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_RIPTIDE, | ||
2118 | addr, 0, chip->irq, 0, | ||
2119 | &chip->rmidi)) < 0) | ||
2120 | snd_printk(KERN_WARNING | ||
2121 | "Riptide: Can't Allocate MPU at 0x%x\n", | ||
2122 | addr); | ||
2123 | else | ||
2124 | chip->mpuaddr = addr; | ||
2125 | } | ||
2126 | if ((addr = opl3_port[dev]) != 0) { | ||
2127 | pci_write_config_word(chip->pci, PCI_EXT_FM_Base, addr); | ||
2128 | if ((err = snd_opl3_create(card, addr, addr + 2, | ||
2129 | OPL3_HW_RIPTIDE, 0, | ||
2130 | &chip->opl3)) < 0) | ||
2131 | snd_printk(KERN_WARNING | ||
2132 | "Riptide: Can't Allocate OPL3 at 0x%x\n", | ||
2133 | addr); | ||
2134 | else { | ||
2135 | chip->opladdr = addr; | ||
2136 | if ((err = | ||
2137 | snd_opl3_hwdep_new(chip->opl3, 0, 1, NULL)) < 0) | ||
2138 | snd_printk(KERN_WARNING | ||
2139 | "Riptide: Can't Allocate OPL3-HWDEP\n"); | ||
2140 | } | ||
2141 | } | ||
2142 | #ifdef SUPPORT_JOYSTICK | ||
2143 | if ((addr = joystick_port[dev]) != 0) { | ||
2144 | pci_write_config_word(chip->pci, PCI_EXT_Game_Base, addr); | ||
2145 | chip->gameaddr = addr; | ||
2146 | } | ||
2147 | #endif | ||
2148 | |||
2149 | strcpy(card->driver, "RIPTIDE"); | ||
2150 | strcpy(card->shortname, "Riptide"); | ||
2151 | #ifdef SUPPORT_JOYSTICK | ||
2152 | snprintf(card->longname, sizeof(card->longname), | ||
2153 | "%s at 0x%lx, irq %i mpu 0x%x opl3 0x%x gameport 0x%x", | ||
2154 | card->shortname, chip->port, chip->irq, chip->mpuaddr, | ||
2155 | chip->opladdr, chip->gameaddr); | ||
2156 | #else | ||
2157 | snprintf(card->longname, sizeof(card->longname), | ||
2158 | "%s at 0x%lx, irq %i mpu 0x%x opl3 0x%x", | ||
2159 | card->shortname, chip->port, chip->irq, chip->mpuaddr, | ||
2160 | chip->opladdr); | ||
2161 | #endif | ||
2162 | snd_riptide_proc_init(chip); | ||
2163 | if ((err = snd_card_register(card)) < 0) { | ||
2164 | snd_card_free(card); | ||
2165 | return err; | ||
2166 | } | ||
2167 | pci_set_drvdata(pci, card); | ||
2168 | dev++; | ||
2169 | return 0; | ||
2170 | } | ||
2171 | |||
2172 | static void __devexit snd_card_riptide_remove(struct pci_dev *pci) | ||
2173 | { | ||
2174 | snd_card_free(pci_get_drvdata(pci)); | ||
2175 | pci_set_drvdata(pci, NULL); | ||
2176 | } | ||
2177 | |||
2178 | static struct pci_driver driver = { | ||
2179 | .name = "RIPTIDE", | ||
2180 | .id_table = snd_riptide_ids, | ||
2181 | .probe = snd_card_riptide_probe, | ||
2182 | .remove = __devexit_p(snd_card_riptide_remove), | ||
2183 | #ifdef CONFIG_PM | ||
2184 | .suspend = riptide_suspend, | ||
2185 | .resume = riptide_resume, | ||
2186 | #endif | ||
2187 | }; | ||
2188 | |||
2189 | #ifdef SUPPORT_JOYSTICK | ||
2190 | static struct pci_driver joystick_driver = { | ||
2191 | .name = "Riptide Joystick", | ||
2192 | .id_table = snd_riptide_joystick_ids, | ||
2193 | .probe = snd_riptide_joystick_probe, | ||
2194 | .remove = __devexit_p(snd_riptide_joystick_remove), | ||
2195 | }; | ||
2196 | #endif | ||
2197 | |||
2198 | static int __init alsa_card_riptide_init(void) | ||
2199 | { | ||
2200 | int err; | ||
2201 | if ((err = pci_register_driver(&driver)) < 0) | ||
2202 | return err; | ||
2203 | #if defined(SUPPORT_JOYSTICK) | ||
2204 | if (pci_register_driver(&joystick_driver) < 0) { | ||
2205 | have_joystick = 0; | ||
2206 | snd_printk(KERN_INFO "no joystick found\n"); | ||
2207 | } else | ||
2208 | have_joystick = 1; | ||
2209 | #endif | ||
2210 | return 0; | ||
2211 | } | ||
2212 | |||
2213 | static void __exit alsa_card_riptide_exit(void) | ||
2214 | { | ||
2215 | pci_unregister_driver(&driver); | ||
2216 | #if defined(SUPPORT_JOYSTICK) | ||
2217 | if (have_joystick) | ||
2218 | pci_unregister_driver(&joystick_driver); | ||
2219 | #endif | ||
2220 | } | ||
2221 | |||
2222 | module_init(alsa_card_riptide_init); | ||
2223 | module_exit(alsa_card_riptide_exit); | ||
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index 1957d29c119e..1e7398de2865 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c | |||
@@ -2373,6 +2373,7 @@ static int __devinit check_dxs_list(struct pci_dev *pci) | |||
2373 | { .subvendor = 0x161f, .subdevice = 0x2032, .action = VIA_DXS_48K }, /* m680x machines */ | 2373 | { .subvendor = 0x161f, .subdevice = 0x2032, .action = VIA_DXS_48K }, /* m680x machines */ |
2374 | { .subvendor = 0x1631, .subdevice = 0xe004, .action = VIA_DXS_ENABLE }, /* Easy Note 3174, Packard Bell */ | 2374 | { .subvendor = 0x1631, .subdevice = 0xe004, .action = VIA_DXS_ENABLE }, /* Easy Note 3174, Packard Bell */ |
2375 | { .subvendor = 0x1695, .subdevice = 0x3005, .action = VIA_DXS_ENABLE }, /* EPoX EP-8K9A */ | 2375 | { .subvendor = 0x1695, .subdevice = 0x3005, .action = VIA_DXS_ENABLE }, /* EPoX EP-8K9A */ |
2376 | { .subvendor = 0x1695, .subdevice = 0x300c, .action = VIA_DXS_SRC }, /* EPoX EP-8KRAI */ | ||
2376 | { .subvendor = 0x1695, .subdevice = 0x300e, .action = VIA_DXS_SRC }, /* EPoX 9HEAI */ | 2377 | { .subvendor = 0x1695, .subdevice = 0x300e, .action = VIA_DXS_SRC }, /* EPoX 9HEAI */ |
2377 | { .subvendor = 0x16f3, .subdevice = 0x6405, .action = VIA_DXS_SRC }, /* Jetway K8M8MS */ | 2378 | { .subvendor = 0x16f3, .subdevice = 0x6405, .action = VIA_DXS_SRC }, /* Jetway K8M8MS */ |
2378 | { .subvendor = 0x1734, .subdevice = 0x1078, .action = VIA_DXS_SRC }, /* FSC Amilo L7300 */ | 2379 | { .subvendor = 0x1734, .subdevice = 0x1078, .action = VIA_DXS_SRC }, /* FSC Amilo L7300 */ |
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c index 8d08b34a1cb5..ce86283ee0fa 100644 --- a/sound/usb/usbmixer.c +++ b/sound/usb/usbmixer.c | |||
@@ -306,8 +306,8 @@ static int get_relative_value(struct usb_mixer_elem_info *cval, int val) | |||
306 | cval->res = 1; | 306 | cval->res = 1; |
307 | if (val < cval->min) | 307 | if (val < cval->min) |
308 | return 0; | 308 | return 0; |
309 | else if (val > cval->max) | 309 | else if (val >= cval->max) |
310 | return (cval->max - cval->min) / cval->res; | 310 | return (cval->max - cval->min + cval->res - 1) / cval->res; |
311 | else | 311 | else |
312 | return (val - cval->min) / cval->res; | 312 | return (val - cval->min) / cval->res; |
313 | } | 313 | } |
@@ -670,6 +670,36 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min) | |||
670 | } | 670 | } |
671 | if (cval->res == 0) | 671 | if (cval->res == 0) |
672 | cval->res = 1; | 672 | cval->res = 1; |
673 | |||
674 | /* Additional checks for the proper resolution | ||
675 | * | ||
676 | * Some devices report smaller resolutions than actually | ||
677 | * reacting. They don't return errors but simply clip | ||
678 | * to the lower aligned value. | ||
679 | */ | ||
680 | if (cval->min + cval->res < cval->max) { | ||
681 | int last_valid_res = cval->res; | ||
682 | int saved, test, check; | ||
683 | get_cur_mix_value(cval, minchn, &saved); | ||
684 | for (;;) { | ||
685 | test = saved; | ||
686 | if (test < cval->max) | ||
687 | test += cval->res; | ||
688 | else | ||
689 | test -= cval->res; | ||
690 | if (test < cval->min || test > cval->max || | ||
691 | set_cur_mix_value(cval, minchn, test) || | ||
692 | get_cur_mix_value(cval, minchn, &check)) { | ||
693 | cval->res = last_valid_res; | ||
694 | break; | ||
695 | } | ||
696 | if (test == check) | ||
697 | break; | ||
698 | cval->res *= 2; | ||
699 | } | ||
700 | set_cur_mix_value(cval, minchn, saved); | ||
701 | } | ||
702 | |||
673 | cval->initialized = 1; | 703 | cval->initialized = 1; |
674 | } | 704 | } |
675 | return 0; | 705 | return 0; |
@@ -695,7 +725,8 @@ static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol, struct snd_ctl_ | |||
695 | if (! cval->initialized) | 725 | if (! cval->initialized) |
696 | get_min_max(cval, 0); | 726 | get_min_max(cval, 0); |
697 | uinfo->value.integer.min = 0; | 727 | uinfo->value.integer.min = 0; |
698 | uinfo->value.integer.max = (cval->max - cval->min) / cval->res; | 728 | uinfo->value.integer.max = |
729 | (cval->max - cval->min + cval->res - 1) / cval->res; | ||
699 | } | 730 | } |
700 | return 0; | 731 | return 0; |
701 | } | 732 | } |