Merge remote-tracking branches 'regulator/fix/88pm800', 'regulator/fix/max8973',...
[linux-drm-fsl-dcu.git] / arch / s390 / kernel / sclp.S
1 /*
2  * Mini SCLP driver.
3  *
4  * Copyright IBM Corp. 2004, 2009
5  *
6  *   Author(s): Peter Oberparleiter <Peter.Oberparleiter@de.ibm.com>,
7  *              Heiko Carstens <heiko.carstens@de.ibm.com>,
8  *
9  */
10
11 #include <linux/linkage.h>
12 #include <asm/irq.h>
13
14 LC_EXT_NEW_PSW          = 0x58                  # addr of ext int handler
15 LC_EXT_NEW_PSW_64       = 0x1b0                 # addr of ext int handler 64 bit
16 LC_EXT_INT_PARAM        = 0x80                  # addr of ext int parameter
17 LC_EXT_INT_CODE         = 0x86                  # addr of ext int code
18 LC_AR_MODE_ID           = 0xa3
19
20 #
21 # Subroutine which waits synchronously until either an external interruption
22 # or a timeout occurs.
23 #
24 # Parameters:
25 #   R2  = 0 for no timeout, non-zero for timeout in (approximated) seconds
26 #
27 # Returns:
28 #   R2  = 0 on interrupt, 2 on timeout
29 #   R3  = external interruption parameter if R2=0
30 #
31
32 _sclp_wait_int:
33         stm     %r6,%r15,24(%r15)               # save registers
34         basr    %r13,0                          # get base register
35 .LbaseS1:
36         ahi     %r15,-96                        # create stack frame
37         la      %r8,LC_EXT_NEW_PSW              # register int handler
38         la      %r9,.LextpswS1-.LbaseS1(%r13)
39         tm      LC_AR_MODE_ID,1
40         jno     .Lesa1
41         la      %r8,LC_EXT_NEW_PSW_64           # register int handler 64 bit
42         la      %r9,.LextpswS1_64-.LbaseS1(%r13)
43 .Lesa1:
44         mvc     .LoldpswS1-.LbaseS1(16,%r13),0(%r8)
45         mvc     0(16,%r8),0(%r9)
46         epsw    %r6,%r7                         # set current addressing mode
47         nill    %r6,0x1                         # in new psw (31 or 64 bit mode)
48         nilh    %r7,0x8000
49         stm     %r6,%r7,0(%r8)
50         lhi     %r6,0x0200                      # cr mask for ext int (cr0.54)
51         ltr     %r2,%r2
52         jz      .LsetctS1
53         ahi     %r6,0x0800                      # cr mask for clock int (cr0.52)
54         stck    .LtimeS1-.LbaseS1(%r13)         # initiate timeout
55         al      %r2,.LtimeS1-.LbaseS1(%r13)
56         st      %r2,.LtimeS1-.LbaseS1(%r13)
57         sckc    .LtimeS1-.LbaseS1(%r13)
58
59 .LsetctS1:
60         stctl   %c0,%c0,.LctlS1-.LbaseS1(%r13)  # enable required interrupts
61         l       %r0,.LctlS1-.LbaseS1(%r13)
62         lhi     %r1,~(0x200 | 0x800)            # clear old values
63         nr      %r1,%r0
64         or      %r1,%r6                         # set new value
65         st      %r1,.LctlS1-.LbaseS1(%r13)
66         lctl    %c0,%c0,.LctlS1-.LbaseS1(%r13)
67         st      %r0,.LctlS1-.LbaseS1(%r13)
68         lhi     %r2,2                           # return code for timeout
69 .LloopS1:
70         lpsw    .LwaitpswS1-.LbaseS1(%r13)      # wait until interrupt
71 .LwaitS1:
72         lh      %r7,LC_EXT_INT_CODE
73         chi     %r7,EXT_IRQ_CLK_COMP            # timeout?
74         je      .LtimeoutS1
75         chi     %r7,EXT_IRQ_SERVICE_SIG         # service int?
76         jne     .LloopS1
77         sr      %r2,%r2
78         l       %r3,LC_EXT_INT_PARAM
79 .LtimeoutS1:
80         lctl    %c0,%c0,.LctlS1-.LbaseS1(%r13)  # restore interrupt setting
81         # restore old handler
82         mvc     0(16,%r8),.LoldpswS1-.LbaseS1(%r13)
83         lm      %r6,%r15,120(%r15)              # restore registers
84         br      %r14                            # return to caller
85
86         .align  8
87 .LoldpswS1:
88         .long   0, 0, 0, 0                      # old ext int PSW
89 .LextpswS1:
90         .long   0x00080000, 0x80000000+.LwaitS1 # PSW to handle ext int
91 .LextpswS1_64:
92         .quad   0, .LwaitS1                     # PSW to handle ext int, 64 bit
93 .LwaitpswS1:
94         .long   0x010a0000, 0x00000000+.LloopS1 # PSW to wait for ext int
95 .LtimeS1:
96         .quad   0                               # current time
97 .LctlS1:
98         .long   0                               # CT0 contents
99
100 #
101 # Subroutine to synchronously issue a service call.
102 #
103 # Parameters:
104 #   R2  = command word
105 #   R3  = sccb address
106 #
107 # Returns:
108 #   R2  = 0 on success, 1 on failure
109 #   R3  = sccb response code if R2 = 0
110 #
111
112 _sclp_servc:
113         stm     %r6,%r15,24(%r15)               # save registers
114         ahi     %r15,-96                        # create stack frame
115         lr      %r6,%r2                         # save command word
116         lr      %r7,%r3                         # save sccb address
117 .LretryS2:
118         lhi     %r2,1                           # error return code
119         .insn   rre,0xb2200000,%r6,%r7          # servc
120         brc     1,.LendS2                       # exit if not operational
121         brc     8,.LnotbusyS2                   # go on if not busy
122         sr      %r2,%r2                         # wait until no longer busy
123         bras    %r14,_sclp_wait_int
124         j       .LretryS2                       # retry
125 .LnotbusyS2:
126         sr      %r2,%r2                         # wait until result
127         bras    %r14,_sclp_wait_int
128         sr      %r2,%r2
129         lh      %r3,6(%r7)
130 .LendS2:
131         lm      %r6,%r15,120(%r15)              # restore registers
132         br      %r14
133
134 #
135 # Subroutine to set up the SCLP interface.
136 #
137 # Parameters:
138 #   R2  = 0 to activate, non-zero to deactivate
139 #
140 # Returns:
141 #   R2  = 0 on success, non-zero on failure
142 #
143
144 _sclp_setup:
145         stm     %r6,%r15,24(%r15)               # save registers
146         ahi     %r15,-96                        # create stack frame
147         basr    %r13,0                          # get base register
148 .LbaseS3:
149         l       %r6,.LsccbS0-.LbaseS3(%r13)     # prepare init mask sccb
150         mvc     0(.LinitendS3-.LinitsccbS3,%r6),.LinitsccbS3-.LbaseS3(%r13)
151         ltr     %r2,%r2                         # initialization?
152         jz      .LdoinitS3                      # go ahead
153         # clear masks
154         xc      .LinitmaskS3-.LinitsccbS3(8,%r6),.LinitmaskS3-.LinitsccbS3(%r6)
155 .LdoinitS3:
156         l       %r2,.LwritemaskS3-.LbaseS3(%r13)# get command word
157         lr      %r3,%r6                         # get sccb address
158         bras    %r14,_sclp_servc                # issue service call
159         ltr     %r2,%r2                         # servc successful?
160         jnz     .LerrorS3
161         chi     %r3,0x20                        # write mask successful?
162         jne     .LerrorS3
163         # check masks
164         la      %r2,.LinitmaskS3-.LinitsccbS3(%r6)
165         l       %r1,0(%r2)                      # receive mask ok?
166         n       %r1,12(%r2)
167         cl      %r1,0(%r2)
168         jne     .LerrorS3
169         l       %r1,4(%r2)                      # send mask ok?
170         n       %r1,8(%r2)
171         cl      %r1,4(%r2)
172         sr      %r2,%r2
173         je      .LendS3
174 .LerrorS3:
175         lhi     %r2,1                           # error return code
176 .LendS3:
177         lm      %r6,%r15,120(%r15)              # restore registers
178         br      %r14
179 .LwritemaskS3:
180         .long   0x00780005                      # SCLP command for write mask
181 .LinitsccbS3:
182         .word   .LinitendS3-.LinitsccbS3
183         .byte   0,0,0,0
184         .word   0
185         .word   0
186         .word   4
187 .LinitmaskS3:
188         .long   0x80000000
189         .long   0x40000000
190         .long   0
191         .long   0
192 .LinitendS3:
193
194 #
195 # Subroutine which prints a given text to the SCLP console.
196 #
197 # Parameters:
198 #   R2  = address of nil-terminated ASCII text
199 #
200 # Returns:
201 #   R2  = 0 on success, 1 on failure
202 #
203
204 _sclp_print:
205         stm     %r6,%r15,24(%r15)               # save registers
206         ahi     %r15,-96                        # create stack frame
207         basr    %r13,0                          # get base register
208 .LbaseS4:
209         l       %r8,.LsccbS0-.LbaseS4(%r13)     # prepare write data sccb
210         mvc     0(.LmtoS4-.LwritesccbS4,%r8),.LwritesccbS4-.LbaseS4(%r13)
211         la      %r7,.LmtoS4-.LwritesccbS4(%r8)  # current mto addr
212         sr      %r0,%r0
213         l       %r10,.Lascebc-.LbaseS4(%r13)    # address of translation table
214 .LinitmtoS4:
215         # initialize mto
216         mvc     0(.LmtoendS4-.LmtoS4,%r7),.LmtoS4-.LbaseS4(%r13)
217         lhi     %r6,.LmtoendS4-.LmtoS4          # current mto length
218 .LloopS4:
219         ic      %r0,0(%r2)                      # get character
220         ahi     %r2,1
221         ltr     %r0,%r0                         # end of string?
222         jz      .LfinalizemtoS4
223         chi     %r0,0x0a                        # end of line (NL)?
224         jz      .LfinalizemtoS4
225         stc     %r0,0(%r6,%r7)                  # copy to mto
226         la      %r11,0(%r6,%r7)
227         tr      0(1,%r11),0(%r10)               # translate to EBCDIC
228         ahi     %r6,1
229         j       .LloopS4
230 .LfinalizemtoS4:
231         sth     %r6,0(%r7)                      # update mto length
232         lh      %r9,.LmdbS4-.LwritesccbS4(%r8)  # update mdb length
233         ar      %r9,%r6
234         sth     %r9,.LmdbS4-.LwritesccbS4(%r8)
235         lh      %r9,.LevbufS4-.LwritesccbS4(%r8)# update evbuf length
236         ar      %r9,%r6
237         sth     %r9,.LevbufS4-.LwritesccbS4(%r8)
238         lh      %r9,0(%r8)                      # update sccb length
239         ar      %r9,%r6
240         sth     %r9,0(%r8)
241         ar      %r7,%r6                         # update current mto address
242         ltr     %r0,%r0                         # more characters?
243         jnz     .LinitmtoS4
244         l       %r2,.LwritedataS4-.LbaseS4(%r13)# write data
245         lr      %r3,%r8
246         bras    %r14,_sclp_servc
247         ltr     %r2,%r2                         # servc successful?
248         jnz     .LendS4
249         chi     %r3,0x20                        # write data successful?
250         je      .LendS4
251         lhi     %r2,1                           # error return code
252 .LendS4:
253         lm      %r6,%r15,120(%r15)              # restore registers
254         br      %r14
255
256 #
257 # Function which prints a given text to the SCLP console.
258 #
259 # Parameters:
260 #   R2  = address of nil-terminated ASCII text
261 #
262 # Returns:
263 #   R2  = 0 on success, 1 on failure
264 #
265
266 ENTRY(_sclp_print_early)
267         stm     %r6,%r15,24(%r15)               # save registers
268         ahi     %r15,-96                        # create stack frame
269         tm      LC_AR_MODE_ID,1
270         jno     .Lesa2
271         ahi     %r15,-80
272         stmh    %r6,%r15,96(%r15)               # store upper register halves
273         basr    %r13,0
274         lmh     %r0,%r15,.Lzeroes-.(%r13)       # clear upper register halves
275 .Lesa2:
276         lr      %r10,%r2                        # save string pointer
277         lhi     %r2,0
278         bras    %r14,_sclp_setup                # enable console
279         ltr     %r2,%r2
280         jnz     .LendS5
281         lr      %r2,%r10
282         bras    %r14,_sclp_print                # print string
283         ltr     %r2,%r2
284         jnz     .LendS5
285         lhi     %r2,1
286         bras    %r14,_sclp_setup                # disable console
287 .LendS5:
288         tm      LC_AR_MODE_ID,1
289         jno     .Lesa3
290         lgfr    %r2,%r2                         # sign extend return value
291         lmh     %r6,%r15,96(%r15)               # restore upper register halves
292         ahi     %r15,80
293 .Lesa3:
294         lm      %r6,%r15,120(%r15)              # restore registers
295         br      %r14
296 .Lzeroes:
297         .fill   64,4,0
298
299 .LwritedataS4:
300         .long   0x00760005                      # SCLP command for write data
301 .LwritesccbS4:
302         # sccb
303         .word   .LmtoS4-.LwritesccbS4
304         .byte   0
305         .byte   0,0,0
306         .word   0
307
308         # evbuf
309 .LevbufS4:
310         .word   .LmtoS4-.LevbufS4
311         .byte   0x02
312         .byte   0
313         .word   0
314
315 .LmdbS4:
316         # mdb
317         .word   .LmtoS4-.LmdbS4
318         .word   1
319         .long   0xd4c4c240
320         .long   1
321
322         # go
323 .LgoS4:
324         .word   .LmtoS4-.LgoS4
325         .word   1
326         .long   0
327         .byte   0,0,0,0,0,0,0,0
328         .byte   0,0,0
329         .byte   0
330         .byte   0,0,0,0,0,0,0
331         .byte   0
332         .word   0
333         .byte   0,0,0,0,0,0,0,0,0,0
334         .byte   0,0,0,0,0,0,0,0
335         .byte   0,0,0,0,0,0,0,0
336
337 .LmtoS4:
338         .word   .LmtoendS4-.LmtoS4
339         .word   4
340         .word   0x1000
341         .byte   0
342         .byte   0,0,0
343 .LmtoendS4:
344
345         # Global constants
346 .LsccbS0:
347         .long   _sclp_work_area
348 .Lascebc:
349         .long   _ascebc
350
351 .section .data,"aw",@progbits
352         .balign 4096
353 _sclp_work_area:
354         .fill   4096
355 .previous