diff options
57 files changed, 2144 insertions, 797 deletions
diff --git a/Documentation/console/console.txt b/Documentation/console/console.txt index 926cf1b5e63e..f93810d599ad 100644 --- a/Documentation/console/console.txt +++ b/Documentation/console/console.txt | |||
@@ -12,20 +12,20 @@ The second type has to be explicitly loaded and unloaded. This will be called | |||
12 | any time with each driver sharing the console with other drivers including | 12 | any time with each driver sharing the console with other drivers including |
13 | the system driver. However, modular drivers cannot take over the console | 13 | the system driver. However, modular drivers cannot take over the console |
14 | that is currently occupied by another modular driver. (Exception: Drivers that | 14 | that is currently occupied by another modular driver. (Exception: Drivers that |
15 | call take_over_console() will succeed in the takeover regardless of the type | 15 | call do_take_over_console() will succeed in the takeover regardless of the type |
16 | of driver occupying the consoles.) They can only take over the console that is | 16 | of driver occupying the consoles.) They can only take over the console that is |
17 | occupied by the system driver. In the same token, if the modular driver is | 17 | occupied by the system driver. In the same token, if the modular driver is |
18 | released by the console, the system driver will take over. | 18 | released by the console, the system driver will take over. |
19 | 19 | ||
20 | Modular drivers, from the programmer's point of view, has to call: | 20 | Modular drivers, from the programmer's point of view, has to call: |
21 | 21 | ||
22 | take_over_console() - load and bind driver to console layer | 22 | do_take_over_console() - load and bind driver to console layer |
23 | give_up_console() - unbind and unload driver | 23 | give_up_console() - unload driver, it will only work if driver is fully unbond |
24 | 24 | ||
25 | In newer kernels, the following are also available: | 25 | In newer kernels, the following are also available: |
26 | 26 | ||
27 | register_con_driver() | 27 | do_register_con_driver() |
28 | unregister_con_driver() | 28 | do_unregister_con_driver() |
29 | 29 | ||
30 | If sysfs is enabled, the contents of /sys/class/vtconsole can be | 30 | If sysfs is enabled, the contents of /sys/class/vtconsole can be |
31 | examined. This shows the console backends currently registered by the | 31 | examined. This shows the console backends currently registered by the |
@@ -94,12 +94,12 @@ for more details). | |||
94 | Notes for developers: | 94 | Notes for developers: |
95 | ===================== | 95 | ===================== |
96 | 96 | ||
97 | take_over_console() is now broken up into: | 97 | do_take_over_console() is now broken up into: |
98 | 98 | ||
99 | register_con_driver() | 99 | do_register_con_driver() |
100 | bind_con_driver() - private function | 100 | do_bind_con_driver() - private function |
101 | 101 | ||
102 | give_up_console() is a wrapper to unregister_con_driver(), and a driver must | 102 | give_up_console() is a wrapper to do_unregister_con_driver(), and a driver must |
103 | be fully unbound for this call to succeed. con_is_bound() will check if the | 103 | be fully unbound for this call to succeed. con_is_bound() will check if the |
104 | driver is bound or not. | 104 | driver is bound or not. |
105 | 105 | ||
@@ -109,10 +109,10 @@ Guidelines for console driver writers: | |||
109 | In order for binding to and unbinding from the console to properly work, | 109 | In order for binding to and unbinding from the console to properly work, |
110 | console drivers must follow these guidelines: | 110 | console drivers must follow these guidelines: |
111 | 111 | ||
112 | 1. All drivers, except system drivers, must call either register_con_driver() | 112 | 1. All drivers, except system drivers, must call either do_register_con_driver() |
113 | or take_over_console(). register_con_driver() will just add the driver to | 113 | or do_take_over_console(). do_register_con_driver() will just add the driver to |
114 | the console's internal list. It won't take over the | 114 | the console's internal list. It won't take over the |
115 | console. take_over_console(), as it name implies, will also take over (or | 115 | console. do_take_over_console(), as it name implies, will also take over (or |
116 | bind to) the console. | 116 | bind to) the console. |
117 | 117 | ||
118 | 2. All resources allocated during con->con_init() must be released in | 118 | 2. All resources allocated during con->con_init() must be released in |
@@ -128,10 +128,10 @@ console drivers must follow these guidelines: | |||
128 | rebind the driver to the console arrives. | 128 | rebind the driver to the console arrives. |
129 | 129 | ||
130 | 4. Upon exit of the driver, ensure that the driver is totally unbound. If the | 130 | 4. Upon exit of the driver, ensure that the driver is totally unbound. If the |
131 | condition is satisfied, then the driver must call unregister_con_driver() | 131 | condition is satisfied, then the driver must call do_unregister_con_driver() |
132 | or give_up_console(). | 132 | or give_up_console(). |
133 | 133 | ||
134 | 5. unregister_con_driver() can also be called on conditions which make it | 134 | 5. do_unregister_con_driver() can also be called on conditions which make it |
135 | impossible for the driver to service console requests. This can happen | 135 | impossible for the driver to service console requests. This can happen |
136 | with the framebuffer console that suddenly lost all of its drivers. | 136 | with the framebuffer console that suddenly lost all of its drivers. |
137 | 137 | ||
diff --git a/Documentation/devicetree/bindings/tty/serial/fsl-imx-uart.txt b/Documentation/devicetree/bindings/tty/serial/fsl-imx-uart.txt index b462d0c54823..c662eb36be29 100644 --- a/Documentation/devicetree/bindings/tty/serial/fsl-imx-uart.txt +++ b/Documentation/devicetree/bindings/tty/serial/fsl-imx-uart.txt | |||
@@ -8,6 +8,8 @@ Required properties: | |||
8 | Optional properties: | 8 | Optional properties: |
9 | - fsl,uart-has-rtscts : Indicate the uart has rts and cts | 9 | - fsl,uart-has-rtscts : Indicate the uart has rts and cts |
10 | - fsl,irda-mode : Indicate the uart supports irda mode | 10 | - fsl,irda-mode : Indicate the uart supports irda mode |
11 | - fsl,dte-mode : Indicate the uart works in DTE mode. The uart works | ||
12 | is DCE mode by default. | ||
11 | 13 | ||
12 | Example: | 14 | Example: |
13 | 15 | ||
@@ -16,4 +18,5 @@ serial@73fbc000 { | |||
16 | reg = <0x73fbc000 0x4000>; | 18 | reg = <0x73fbc000 0x4000>; |
17 | interrupts = <31>; | 19 | interrupts = <31>; |
18 | fsl,uart-has-rtscts; | 20 | fsl,uart-has-rtscts; |
21 | fsl,dte-mode; | ||
19 | }; | 22 | }; |
diff --git a/Documentation/devicetree/bindings/tty/serial/fsl-lpuart.txt b/Documentation/devicetree/bindings/tty/serial/fsl-lpuart.txt new file mode 100644 index 000000000000..6fd1dd1638dd --- /dev/null +++ b/Documentation/devicetree/bindings/tty/serial/fsl-lpuart.txt | |||
@@ -0,0 +1,14 @@ | |||
1 | * Freescale low power universal asynchronous receiver/transmitter (lpuart) | ||
2 | |||
3 | Required properties: | ||
4 | - compatible : Should be "fsl,<soc>-lpuart" | ||
5 | - reg : Address and length of the register set for the device | ||
6 | - interrupts : Should contain uart interrupt | ||
7 | |||
8 | Example: | ||
9 | |||
10 | uart0: serial@40027000 { | ||
11 | compatible = "fsl,vf610-lpuart"; | ||
12 | reg = <0x40027000 0x1000>; | ||
13 | interrupts = <0 61 0x00>; | ||
14 | }; | ||
diff --git a/Documentation/serial/00-INDEX b/Documentation/serial/00-INDEX index f7b0c7dc25ef..1f1b22fbd739 100644 --- a/Documentation/serial/00-INDEX +++ b/Documentation/serial/00-INDEX | |||
@@ -16,8 +16,6 @@ serial-rs485.txt | |||
16 | - info about RS485 structures and support in the kernel. | 16 | - info about RS485 structures and support in the kernel. |
17 | specialix.txt | 17 | specialix.txt |
18 | - info on hardware/driver for specialix IO8+ multiport serial card. | 18 | - info on hardware/driver for specialix IO8+ multiport serial card. |
19 | stallion.txt | ||
20 | - info on using the Stallion multiport serial driver. | ||
21 | sx.txt | 19 | sx.txt |
22 | - info on the Specialix SX/SI multiport serial driver. | 20 | - info on the Specialix SX/SI multiport serial driver. |
23 | tty.txt | 21 | tty.txt |
diff --git a/Documentation/serial/stallion.txt b/Documentation/serial/stallion.txt deleted file mode 100644 index 4d798c0cb5cb..000000000000 --- a/Documentation/serial/stallion.txt +++ /dev/null | |||
@@ -1,392 +0,0 @@ | |||
1 | * NOTE - This is an unmaintained driver. Lantronix, which bought Stallion | ||
2 | technologies, is not active in driver maintenance, and they have no information | ||
3 | on when or if they will have a 2.6 driver. | ||
4 | |||
5 | James Nelson <james4765@gmail.com> - 12-12-2004 | ||
6 | |||
7 | Stallion Multiport Serial Driver Readme | ||
8 | --------------------------------------- | ||
9 | |||
10 | Copyright (C) 1994-1999, Stallion Technologies. | ||
11 | |||
12 | Version: 5.5.1 | ||
13 | Date: 28MAR99 | ||
14 | |||
15 | |||
16 | |||
17 | 1. INTRODUCTION | ||
18 | |||
19 | There are two drivers that work with the different families of Stallion | ||
20 | multiport serial boards. One is for the Stallion smart boards - that is | ||
21 | EasyIO, EasyConnection 8/32 and EasyConnection 8/64-PCI, the other for | ||
22 | the true Stallion intelligent multiport boards - EasyConnection 8/64 | ||
23 | (ISA, EISA), EasyConnection/RA-PCI, ONboard and Brumby. | ||
24 | |||
25 | If you are using any of the Stallion intelligent multiport boards (Brumby, | ||
26 | ONboard, EasyConnection 8/64 (ISA, EISA), EasyConnection/RA-PCI) with | ||
27 | Linux you will need to get the driver utility package. This contains a | ||
28 | firmware loader and the firmware images necessary to make the devices operate. | ||
29 | |||
30 | The Stallion Technologies ftp site, ftp.stallion.com, will always have | ||
31 | the latest version of the driver utility package. | ||
32 | |||
33 | ftp://ftp.stallion.com/drivers/ata5/Linux/ata-linux-550.tar.gz | ||
34 | |||
35 | As of the printing of this document the latest version of the driver | ||
36 | utility package is 5.5.0. If a later version is now available then you | ||
37 | should use the latest version. | ||
38 | |||
39 | If you are using the EasyIO, EasyConnection 8/32 or EasyConnection 8/64-PCI | ||
40 | boards then you don't need this package, although it does have a serial stats | ||
41 | display program. | ||
42 | |||
43 | If you require DIP switch settings, or EISA configuration files, or any | ||
44 | other information related to Stallion boards then have a look at Stallion's | ||
45 | web pages at http://www.stallion.com. | ||
46 | |||
47 | |||
48 | |||
49 | 2. INSTALLATION | ||
50 | |||
51 | The drivers can be used as loadable modules or compiled into the kernel. | ||
52 | You can choose which when doing a "config" on the kernel. | ||
53 | |||
54 | All ISA, and EISA boards that you want to use need to be configured into | ||
55 | the driver(s). All PCI boards will be automatically detected when you load | ||
56 | the driver - so they do not need to be entered into the driver(s) | ||
57 | configuration structure. Note that kernel PCI support is required to use PCI | ||
58 | boards. | ||
59 | |||
60 | There are two methods of configuring ISA and EISA boards into the drivers. | ||
61 | If using the driver as a loadable module then the simplest method is to pass | ||
62 | the driver configuration as module arguments. The other method is to modify | ||
63 | the driver source to add configuration lines for each board in use. | ||
64 | |||
65 | If you have pre-built Stallion driver modules then the module argument | ||
66 | configuration method should be used. A lot of Linux distributions come with | ||
67 | pre-built driver modules in /lib/modules/X.Y.Z/misc for the kernel in use. | ||
68 | That makes things pretty simple to get going. | ||
69 | |||
70 | |||
71 | 2.1 MODULE DRIVER CONFIGURATION: | ||
72 | |||
73 | The simplest configuration for modules is to use the module load arguments | ||
74 | to configure any ISA or EISA boards. PCI boards are automatically | ||
75 | detected, so do not need any additional configuration at all. | ||
76 | |||
77 | If using EasyIO, EasyConnection 8/32 ISA, or EasyConnection 8/63-PCI | ||
78 | boards then use the "stallion" driver module, Otherwise if you are using | ||
79 | an EasyConnection 8/64 ISA or EISA, EasyConnection/RA-PCI, ONboard, | ||
80 | Brumby or original Stallion board then use the "istallion" driver module. | ||
81 | |||
82 | Typically to load up the smart board driver use: | ||
83 | |||
84 | modprobe stallion | ||
85 | |||
86 | This will load the EasyIO and EasyConnection 8/32 driver. It will output a | ||
87 | message to say that it loaded and print the driver version number. It will | ||
88 | also print out whether it found the configured boards or not. These messages | ||
89 | may not appear on the console, but typically are always logged to | ||
90 | /var/adm/messages or /var/log/syslog files - depending on how the klogd and | ||
91 | syslogd daemons are setup on your system. | ||
92 | |||
93 | To load the intelligent board driver use: | ||
94 | |||
95 | modprobe istallion | ||
96 | |||
97 | It will output similar messages to the smart board driver. | ||
98 | |||
99 | If not using an auto-detectable board type (that is a PCI board) then you | ||
100 | will also need to supply command line arguments to the modprobe command | ||
101 | when loading the driver. The general form of the configuration argument is | ||
102 | |||
103 | board?=<name>[,<ioaddr>[,<addr>][,<irq>]] | ||
104 | |||
105 | where: | ||
106 | |||
107 | board? -- specifies the arbitrary board number of this board, | ||
108 | can be in the range 0 to 3. | ||
109 | |||
110 | name -- textual name of this board. The board name is the common | ||
111 | board name, or any "shortened" version of that. The board | ||
112 | type number may also be used here. | ||
113 | |||
114 | ioaddr -- specifies the I/O address of this board. This argument is | ||
115 | optional, but should generally be specified. | ||
116 | |||
117 | addr -- optional second address argument. Some board types require | ||
118 | a second I/O address, some require a memory address. The | ||
119 | exact meaning of this argument depends on the board type. | ||
120 | |||
121 | irq -- optional IRQ line used by this board. | ||
122 | |||
123 | Up to 4 board configuration arguments can be specified on the load line. | ||
124 | Here is some examples: | ||
125 | |||
126 | modprobe stallion board0=easyio,0x2a0,5 | ||
127 | |||
128 | This configures an EasyIO board as board 0 at I/O address 0x2a0 and IRQ 5. | ||
129 | |||
130 | modprobe istallion board3=ec8/64,0x2c0,0xcc000 | ||
131 | |||
132 | This configures an EasyConnection 8/64 ISA as board 3 at I/O address 0x2c0 at | ||
133 | memory address 0xcc000. | ||
134 | |||
135 | modprobe stallion board1=ec8/32-at,0x2a0,0x280,10 | ||
136 | |||
137 | This configures an EasyConnection 8/32 ISA board at primary I/O address 0x2a0, | ||
138 | secondary address 0x280 and IRQ 10. | ||
139 | |||
140 | You will probably want to enter this module load and configuration information | ||
141 | into your system startup scripts so that the drivers are loaded and configured | ||
142 | on each system boot. Typically configuration files are put in the | ||
143 | /etc/modprobe.d/ directory. | ||
144 | |||
145 | |||
146 | 2.2 STATIC DRIVER CONFIGURATION: | ||
147 | |||
148 | For static driver configuration you need to modify the driver source code. | ||
149 | Entering ISA and EISA boards into the driver(s) configuration structure | ||
150 | involves editing the driver(s) source file. It's pretty easy if you follow | ||
151 | the instructions below. Both drivers can support up to 4 boards. The smart | ||
152 | card driver (the stallion.c driver) supports any combination of EasyIO and | ||
153 | EasyConnection 8/32 boards (up to a total of 4). The intelligent driver | ||
154 | supports any combination of ONboards, Brumbys, Stallions and EasyConnection | ||
155 | 8/64 (ISA and EISA) boards (up to a total of 4). | ||
156 | |||
157 | To set up the driver(s) for the boards that you want to use you need to | ||
158 | edit the appropriate driver file and add configuration entries. | ||
159 | |||
160 | If using EasyIO or EasyConnection 8/32 ISA boards, | ||
161 | In drivers/char/stallion.c: | ||
162 | - find the definition of the stl_brdconf array (of structures) | ||
163 | near the top of the file | ||
164 | - modify this to match the boards you are going to install | ||
165 | (the comments before this structure should help) | ||
166 | - save and exit | ||
167 | |||
168 | If using ONboard, Brumby, Stallion or EasyConnection 8/64 (ISA or EISA) | ||
169 | boards, | ||
170 | In drivers/char/istallion.c: | ||
171 | - find the definition of the stli_brdconf array (of structures) | ||
172 | near the top of the file | ||
173 | - modify this to match the boards you are going to install | ||
174 | (the comments before this structure should help) | ||
175 | - save and exit | ||
176 | |||
177 | Once you have set up the board configurations then you are ready to build | ||
178 | the kernel or modules. | ||
179 | |||
180 | When the new kernel is booted, or the loadable module loaded then the | ||
181 | driver will emit some kernel trace messages about whether the configured | ||
182 | boards were detected or not. Depending on how your system logger is set | ||
183 | up these may come out on the console, or just be logged to | ||
184 | /var/adm/messages or /var/log/syslog. You should check the messages to | ||
185 | confirm that all is well. | ||
186 | |||
187 | |||
188 | 2.3 SHARING INTERRUPTS | ||
189 | |||
190 | It is possible to share interrupts between multiple EasyIO and | ||
191 | EasyConnection 8/32 boards in an EISA system. To do this you must be using | ||
192 | static driver configuration, modifying the driver source code to add driver | ||
193 | configuration. Then a couple of extra things are required: | ||
194 | |||
195 | 1. When entering the board resources into the stallion.c file you need to | ||
196 | mark the boards as using level triggered interrupts. Do this by replacing | ||
197 | the "0" entry at field position 6 (the last field) in the board | ||
198 | configuration structure with a "1". (This is the structure that defines | ||
199 | the board type, I/O locations, etc. for each board). All boards that are | ||
200 | sharing an interrupt must be set this way, and each board should have the | ||
201 | same interrupt number specified here as well. Now build the module or | ||
202 | kernel as you would normally. | ||
203 | |||
204 | 2. When physically installing the boards into the system you must enter | ||
205 | the system EISA configuration utility. You will need to install the EISA | ||
206 | configuration files for *all* the EasyIO and EasyConnection 8/32 boards | ||
207 | that are sharing interrupts. The Stallion EasyIO and EasyConnection 8/32 | ||
208 | EISA configuration files required are supplied by Stallion Technologies | ||
209 | on the EASY Utilities floppy diskette (usually supplied in the box with | ||
210 | the board when purchased. If not, you can pick it up from Stallion's FTP | ||
211 | site, ftp.stallion.com). You will need to edit the board resources to | ||
212 | choose level triggered interrupts, and make sure to set each board's | ||
213 | interrupt to the same IRQ number. | ||
214 | |||
215 | You must complete both the above steps for this to work. When you reboot | ||
216 | or load the driver your EasyIO and EasyConnection 8/32 boards will be | ||
217 | sharing interrupts. | ||
218 | |||
219 | |||
220 | 2.4 USING HIGH SHARED MEMORY | ||
221 | |||
222 | The EasyConnection 8/64-EI, ONboard and Stallion boards are capable of | ||
223 | using shared memory addresses above the usual 640K - 1Mb range. The ONboard | ||
224 | ISA and the Stallion boards can be programmed to use memory addresses up to | ||
225 | 16Mb (the ISA bus addressing limit), and the EasyConnection 8/64-EI and | ||
226 | ONboard/E can be programmed for memory addresses up to 4Gb (the EISA bus | ||
227 | addressing limit). | ||
228 | |||
229 | The higher than 1Mb memory addresses are fully supported by this driver. | ||
230 | Just enter the address as you normally would for a lower than 1Mb address | ||
231 | (in the driver's board configuration structure). | ||
232 | |||
233 | |||
234 | |||
235 | 2.5 TROUBLE SHOOTING | ||
236 | |||
237 | If a board is not found by the driver but is actually in the system then the | ||
238 | most likely problem is that the I/O address is wrong. Change the module load | ||
239 | argument for the loadable module form. Or change it in the driver stallion.c | ||
240 | or istallion.c configuration structure and rebuild the kernel or modules, or | ||
241 | change it on the board. | ||
242 | |||
243 | On EasyIO and EasyConnection 8/32 boards the IRQ is software programmable, so | ||
244 | if there is a conflict you may need to change the IRQ used for a board. There | ||
245 | are no interrupts to worry about for ONboard, Brumby or EasyConnection 8/64 | ||
246 | (ISA and EISA) boards. The memory region on EasyConnection 8/64 and | ||
247 | ONboard boards is software programmable, but not on the Brumby boards. | ||
248 | |||
249 | |||
250 | |||
251 | 3. USING THE DRIVERS | ||
252 | |||
253 | 3.1 INTELLIGENT DRIVER OPERATION | ||
254 | |||
255 | The intelligent boards also need to have their "firmware" code downloaded | ||
256 | to them. This is done via a user level application supplied in the driver | ||
257 | utility package called "stlload". Compile this program wherever you dropped | ||
258 | the package files, by typing "make". In its simplest form you can then type | ||
259 | |||
260 | ./stlload -i cdk.sys | ||
261 | |||
262 | in this directory and that will download board 0 (assuming board 0 is an | ||
263 | EasyConnection 8/64 or EasyConnection/RA board). To download to an | ||
264 | ONboard, Brumby or Stallion do: | ||
265 | |||
266 | ./stlload -i 2681.sys | ||
267 | |||
268 | Normally you would want all boards to be downloaded as part of the standard | ||
269 | system startup. To achieve this, add one of the lines above into the | ||
270 | /etc/rc.d/rc.S or /etc/rc.d/rc.serial file. To download each board just add | ||
271 | the "-b <brd-number>" option to the line. You will need to download code for | ||
272 | every board. You should probably move the stlload program into a system | ||
273 | directory, such as /usr/sbin. Also, the default location of the cdk.sys image | ||
274 | file in the stlload down-loader is /usr/lib/stallion. Create that directory | ||
275 | and put the cdk.sys and 2681.sys files in it. (It's a convenient place to put | ||
276 | them anyway). As an example your /etc/rc.d/rc.S file might have the | ||
277 | following lines added to it (if you had 3 boards): | ||
278 | |||
279 | /usr/sbin/stlload -b 0 -i /usr/lib/stallion/cdk.sys | ||
280 | /usr/sbin/stlload -b 1 -i /usr/lib/stallion/2681.sys | ||
281 | /usr/sbin/stlload -b 2 -i /usr/lib/stallion/2681.sys | ||
282 | |||
283 | The image files cdk.sys and 2681.sys are specific to the board types. The | ||
284 | cdk.sys will only function correctly on an EasyConnection 8/64 board. Similarly | ||
285 | the 2681.sys image fill only operate on ONboard, Brumby and Stallion boards. | ||
286 | If you load the wrong image file into a board it will fail to start up, and | ||
287 | of course the ports will not be operational! | ||
288 | |||
289 | If you are using the modularized version of the driver you might want to put | ||
290 | the modprobe calls in the startup script as well (before the download lines | ||
291 | obviously). | ||
292 | |||
293 | |||
294 | 3.2 USING THE SERIAL PORTS | ||
295 | |||
296 | Once the driver is installed you will need to setup some device nodes to | ||
297 | access the serial ports. The simplest method is to use the /dev/MAKEDEV program. | ||
298 | It will automatically create device entries for Stallion boards. This will | ||
299 | create the normal serial port devices as /dev/ttyE# where# is the port number | ||
300 | starting from 0. A bank of 64 minor device numbers is allocated to each board, | ||
301 | so the first port on the second board is port 64,etc. A set of callout type | ||
302 | devices may also be created. They are created as the devices /dev/cue# where # | ||
303 | is the same as for the ttyE devices. | ||
304 | |||
305 | For the most part the Stallion driver tries to emulate the standard PC system | ||
306 | COM ports and the standard Linux serial driver. The idea is that you should | ||
307 | be able to use Stallion board ports and COM ports interchangeably without | ||
308 | modifying anything but the device name. Anything that doesn't work like that | ||
309 | should be considered a bug in this driver! | ||
310 | |||
311 | If you look at the driver code you will notice that it is fairly closely | ||
312 | based on the Linux serial driver (linux/drivers/char/serial.c). This is | ||
313 | intentional, obviously this is the easiest way to emulate its behavior! | ||
314 | |||
315 | Since this driver tries to emulate the standard serial ports as much as | ||
316 | possible, most system utilities should work as they do for the standard | ||
317 | COM ports. Most importantly "stty" works as expected and "setserial" can | ||
318 | also be used (excepting the ability to auto-configure the I/O and IRQ | ||
319 | addresses of boards). Higher baud rates are supported in the usual fashion | ||
320 | through setserial or using the CBAUDEX extensions. Note that the EasyIO and | ||
321 | EasyConnection (all types) support at least 57600 and 115200 baud. The newer | ||
322 | EasyConnection XP modules and new EasyIO boards support 230400 and 460800 | ||
323 | baud as well. The older boards including ONboard and Brumby support a | ||
324 | maximum baud rate of 38400. | ||
325 | |||
326 | If you are unfamiliar with how to use serial ports, then get the Serial-HOWTO | ||
327 | by Greg Hankins. It will explain everything you need to know! | ||
328 | |||
329 | |||
330 | |||
331 | 4. NOTES | ||
332 | |||
333 | You can use both drivers at once if you have a mix of board types installed | ||
334 | in a system. However to do this you will need to change the major numbers | ||
335 | used by one of the drivers. Currently both drivers use major numbers 24, 25 | ||
336 | and 28 for their devices. Change one driver to use some other major numbers, | ||
337 | and then modify the mkdevnods script to make device nodes based on those new | ||
338 | major numbers. For example, you could change the istallion.c driver to use | ||
339 | major numbers 60, 61 and 62. You will also need to create device nodes with | ||
340 | different names for the ports, for example ttyF# and cuf#. | ||
341 | |||
342 | The original Stallion board is no longer supported by Stallion Technologies. | ||
343 | Although it is known to work with the istallion driver. | ||
344 | |||
345 | Finding a free physical memory address range can be a problem. The older | ||
346 | boards like the Stallion and ONboard need large areas (64K or even 128K), so | ||
347 | they can be very difficult to get into a system. If you have 16 Mb of RAM | ||
348 | then you have no choice but to put them somewhere in the 640K -> 1Mb range. | ||
349 | ONboards require 64K, so typically 0xd0000 is good, or 0xe0000 on some | ||
350 | systems. If you have an original Stallion board, "V4.0" or Rev.O, then you | ||
351 | need a 64K memory address space, so again 0xd0000 and 0xe0000 are good. | ||
352 | Older Stallion boards are a much bigger problem. They need 128K of address | ||
353 | space and must be on a 128K boundary. If you don't have a VGA card then | ||
354 | 0xc0000 might be usable - there is really no other place you can put them | ||
355 | below 1Mb. | ||
356 | |||
357 | Both the ONboard and old Stallion boards can use higher memory addresses as | ||
358 | well, but you must have less than 16Mb of RAM to be able to use them. Usual | ||
359 | high memory addresses used include 0xec0000 and 0xf00000. | ||
360 | |||
361 | The Brumby boards only require 16Kb of address space, so you can usually | ||
362 | squeeze them in somewhere. Common addresses are 0xc8000, 0xcc000, or in | ||
363 | the 0xd0000 range. EasyConnection 8/64 boards are even better, they only | ||
364 | require 4Kb of address space, again usually 0xc8000, 0xcc000 or 0xd0000 | ||
365 | are good. | ||
366 | |||
367 | If you are using an EasyConnection 8/64-EI or ONboard/E then usually the | ||
368 | 0xd0000 or 0xe0000 ranges are the best options below 1Mb. If neither of | ||
369 | them can be used then the high memory support to use the really high address | ||
370 | ranges is the best option. Typically the 2Gb range is convenient for them, | ||
371 | and gets them well out of the way. | ||
372 | |||
373 | The ports of the EasyIO-8M board do not have DCD or DTR signals. So these | ||
374 | ports cannot be used as real modem devices. Generally, when using these | ||
375 | ports you should only use the cueX devices. | ||
376 | |||
377 | The driver utility package contains a couple of very useful programs. One | ||
378 | is a serial port statistics collection and display program - very handy | ||
379 | for solving serial port problems. The other is an extended option setting | ||
380 | program that works with the intelligent boards. | ||
381 | |||
382 | |||
383 | |||
384 | 5. DISCLAIMER | ||
385 | |||
386 | The information contained in this document is believed to be accurate and | ||
387 | reliable. However, no responsibility is assumed by Stallion Technologies | ||
388 | Pty. Ltd. for its use, nor any infringements of patents or other rights | ||
389 | of third parties resulting from its use. Stallion Technologies reserves | ||
390 | the right to modify the design of its products and will endeavour to change | ||
391 | the information in manuals and accompanying documentation accordingly. | ||
392 | |||
diff --git a/MAINTAINERS b/MAINTAINERS index ad7e322ad17b..a996ab582211 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -4577,7 +4577,7 @@ F: fs/jbd2/ | |||
4577 | F: include/linux/jbd2.h | 4577 | F: include/linux/jbd2.h |
4578 | 4578 | ||
4579 | JSM Neo PCI based serial card | 4579 | JSM Neo PCI based serial card |
4580 | M: Lucas Tavares <lucaskt@linux.vnet.ibm.com> | 4580 | M: Thadeu Lima de Souza Cascardo <cascardo@linux.vnet.ibm.com> |
4581 | L: linux-serial@vger.kernel.org | 4581 | L: linux-serial@vger.kernel.org |
4582 | S: Maintained | 4582 | S: Maintained |
4583 | F: drivers/tty/serial/jsm/ | 4583 | F: drivers/tty/serial/jsm/ |
diff --git a/arch/alpha/kernel/console.c b/arch/alpha/kernel/console.c index da711e37fc97..6a61deed4a85 100644 --- a/arch/alpha/kernel/console.c +++ b/arch/alpha/kernel/console.c | |||
@@ -61,7 +61,9 @@ locate_and_init_vga(void *(*sel_func)(void *, void *)) | |||
61 | 61 | ||
62 | /* Set the VGA hose and init the new console. */ | 62 | /* Set the VGA hose and init the new console. */ |
63 | pci_vga_hose = hose; | 63 | pci_vga_hose = hose; |
64 | take_over_console(&vga_con, 0, MAX_NR_CONSOLES-1, 1); | 64 | console_lock(); |
65 | do_take_over_console(&vga_con, 0, MAX_NR_CONSOLES-1, 1); | ||
66 | console_unlock(); | ||
65 | } | 67 | } |
66 | 68 | ||
67 | void __init | 69 | void __init |
diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c index ab80a80d38a2..f2360a74e5d5 100644 --- a/arch/alpha/kernel/process.c +++ b/arch/alpha/kernel/process.c | |||
@@ -117,7 +117,9 @@ common_shutdown_1(void *generic_ptr) | |||
117 | if (in_interrupt()) | 117 | if (in_interrupt()) |
118 | irq_exit(); | 118 | irq_exit(); |
119 | /* This has the effect of resetting the VGA video origin. */ | 119 | /* This has the effect of resetting the VGA video origin. */ |
120 | take_over_console(&dummy_con, 0, MAX_NR_CONSOLES-1, 1); | 120 | console_lock(); |
121 | do_take_over_console(&dummy_con, 0, MAX_NR_CONSOLES-1, 1); | ||
122 | console_unlock(); | ||
121 | #endif | 123 | #endif |
122 | pci_restore_srm_config(); | 124 | pci_restore_srm_config(); |
123 | set_hae(srm_hae); | 125 | set_hae(srm_hae); |
diff --git a/arch/mips/pci/pci-bcm1480.c b/arch/mips/pci/pci-bcm1480.c index e2e69e1e9fe1..44dd5aa2e36f 100644 --- a/arch/mips/pci/pci-bcm1480.c +++ b/arch/mips/pci/pci-bcm1480.c | |||
@@ -257,7 +257,9 @@ static int __init bcm1480_pcibios_init(void) | |||
257 | register_pci_controller(&bcm1480_controller); | 257 | register_pci_controller(&bcm1480_controller); |
258 | 258 | ||
259 | #ifdef CONFIG_VGA_CONSOLE | 259 | #ifdef CONFIG_VGA_CONSOLE |
260 | take_over_console(&vga_con, 0, MAX_NR_CONSOLES-1, 1); | 260 | console_lock(); |
261 | do_take_over_console(&vga_con, 0, MAX_NR_CONSOLES-1, 1); | ||
262 | console_unlock(); | ||
261 | #endif | 263 | #endif |
262 | return 0; | 264 | return 0; |
263 | } | 265 | } |
diff --git a/arch/mips/pci/pci-sb1250.c b/arch/mips/pci/pci-sb1250.c index cdefcc4cb8d4..fc634aeda4a5 100644 --- a/arch/mips/pci/pci-sb1250.c +++ b/arch/mips/pci/pci-sb1250.c | |||
@@ -283,7 +283,9 @@ static int __init sb1250_pcibios_init(void) | |||
283 | register_pci_controller(&sb1250_controller); | 283 | register_pci_controller(&sb1250_controller); |
284 | 284 | ||
285 | #ifdef CONFIG_VGA_CONSOLE | 285 | #ifdef CONFIG_VGA_CONSOLE |
286 | take_over_console(&vga_con, 0, MAX_NR_CONSOLES - 1, 1); | 286 | console_lock(); |
287 | do_take_over_console(&vga_con, 0, MAX_NR_CONSOLES - 1, 1); | ||
288 | console_unlock(); | ||
287 | #endif | 289 | #endif |
288 | return 0; | 290 | return 0; |
289 | } | 291 | } |
diff --git a/arch/parisc/kernel/setup.c b/arch/parisc/kernel/setup.c index 1e95b2000ce8..7349a3fedfc7 100644 --- a/arch/parisc/kernel/setup.c +++ b/arch/parisc/kernel/setup.c | |||
@@ -156,7 +156,7 @@ void __init setup_arch(char **cmdline_p) | |||
156 | #endif | 156 | #endif |
157 | 157 | ||
158 | #if defined(CONFIG_VT) && defined(CONFIG_DUMMY_CONSOLE) | 158 | #if defined(CONFIG_VT) && defined(CONFIG_DUMMY_CONSOLE) |
159 | conswitchp = &dummy_con; /* we use take_over_console() later ! */ | 159 | conswitchp = &dummy_con; /* we use do_take_over_console() later ! */ |
160 | #endif | 160 | #endif |
161 | 161 | ||
162 | } | 162 | } |
diff --git a/arch/powerpc/include/asm/mpc52xx_psc.h b/arch/powerpc/include/asm/mpc52xx_psc.h index 2966df604221..d0ece257d310 100644 --- a/arch/powerpc/include/asm/mpc52xx_psc.h +++ b/arch/powerpc/include/asm/mpc52xx_psc.h | |||
@@ -299,4 +299,53 @@ struct mpc512x_psc_fifo { | |||
299 | #define rxdata_32 rxdata.rxdata_32 | 299 | #define rxdata_32 rxdata.rxdata_32 |
300 | }; | 300 | }; |
301 | 301 | ||
302 | struct mpc5125_psc { | ||
303 | u8 mr1; /* PSC + 0x00 */ | ||
304 | u8 reserved0[3]; | ||
305 | u8 mr2; /* PSC + 0x04 */ | ||
306 | u8 reserved1[3]; | ||
307 | struct { | ||
308 | u16 status; /* PSC + 0x08 */ | ||
309 | u8 reserved2[2]; | ||
310 | u8 clock_select; /* PSC + 0x0c */ | ||
311 | u8 reserved3[3]; | ||
312 | } sr_csr; | ||
313 | u8 command; /* PSC + 0x10 */ | ||
314 | u8 reserved4[3]; | ||
315 | union { /* PSC + 0x14 */ | ||
316 | u8 buffer_8; | ||
317 | u16 buffer_16; | ||
318 | u32 buffer_32; | ||
319 | } buffer; | ||
320 | struct { | ||
321 | u8 ipcr; /* PSC + 0x18 */ | ||
322 | u8 reserved5[3]; | ||
323 | u8 acr; /* PSC + 0x1c */ | ||
324 | u8 reserved6[3]; | ||
325 | } ipcr_acr; | ||
326 | struct { | ||
327 | u16 isr; /* PSC + 0x20 */ | ||
328 | u8 reserved7[2]; | ||
329 | u16 imr; /* PSC + 0x24 */ | ||
330 | u8 reserved8[2]; | ||
331 | } isr_imr; | ||
332 | u8 ctur; /* PSC + 0x28 */ | ||
333 | u8 reserved9[3]; | ||
334 | u8 ctlr; /* PSC + 0x2c */ | ||
335 | u8 reserved10[3]; | ||
336 | u32 ccr; /* PSC + 0x30 */ | ||
337 | u32 ac97slots; /* PSC + 0x34 */ | ||
338 | u32 ac97cmd; /* PSC + 0x38 */ | ||
339 | u32 ac97data; /* PSC + 0x3c */ | ||
340 | u8 reserved11[4]; | ||
341 | u8 ip; /* PSC + 0x44 */ | ||
342 | u8 reserved12[3]; | ||
343 | u8 op1; /* PSC + 0x48 */ | ||
344 | u8 reserved13[3]; | ||
345 | u8 op0; /* PSC + 0x4c */ | ||
346 | u8 reserved14[3]; | ||
347 | u32 sicr; /* PSC + 0x50 */ | ||
348 | u8 reserved15[4]; /* make eq. sizeof(mpc52xx_psc) */ | ||
349 | }; | ||
350 | |||
302 | #endif /* __ASM_MPC52xx_PSC_H__ */ | 351 | #endif /* __ASM_MPC52xx_PSC_H__ */ |
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 3bb6fa3930be..14219972c745 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig | |||
@@ -15,18 +15,6 @@ config DEVKMEM | |||
15 | kind of kernel debugging operations. | 15 | kind of kernel debugging operations. |
16 | When in doubt, say "N". | 16 | When in doubt, say "N". |
17 | 17 | ||
18 | config STALDRV | ||
19 | bool "Stallion multiport serial support" | ||
20 | depends on SERIAL_NONSTANDARD | ||
21 | help | ||
22 | Stallion cards give you many serial ports. You would need something | ||
23 | like this to connect more than two modems to your Linux box, for | ||
24 | instance in order to become a dial-in server. If you say Y here, | ||
25 | you will be asked for your specific card model in the next | ||
26 | questions. Make sure to read <file:Documentation/serial/stallion.txt> | ||
27 | in this case. If you have never heard about all this, it's safe to | ||
28 | say N. | ||
29 | |||
30 | config SGI_SNSC | 18 | config SGI_SNSC |
31 | bool "SGI Altix system controller communication support" | 19 | bool "SGI Altix system controller communication support" |
32 | depends on (IA64_SGI_SN2 || IA64_GENERIC) | 20 | depends on (IA64_SGI_SN2 || IA64_GENERIC) |
diff --git a/drivers/tty/Makefile b/drivers/tty/Makefile index 6b78399bc7c9..58ad1c05b7f8 100644 --- a/drivers/tty/Makefile +++ b/drivers/tty/Makefile | |||
@@ -1,5 +1,5 @@ | |||
1 | obj-$(CONFIG_TTY) += tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o \ | 1 | obj-$(CONFIG_TTY) += tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o \ |
2 | tty_buffer.o tty_port.o tty_mutex.o | 2 | tty_buffer.o tty_port.o tty_mutex.o tty_ldsem.o |
3 | obj-$(CONFIG_LEGACY_PTYS) += pty.o | 3 | obj-$(CONFIG_LEGACY_PTYS) += pty.o |
4 | obj-$(CONFIG_UNIX98_PTYS) += pty.o | 4 | obj-$(CONFIG_UNIX98_PTYS) += pty.o |
5 | obj-$(CONFIG_AUDIT) += tty_audit.o | 5 | obj-$(CONFIG_AUDIT) += tty_audit.o |
diff --git a/drivers/tty/hvc/hvc_iucv.c b/drivers/tty/hvc/hvc_iucv.c index b6f7d52f7c35..9d47f50c2755 100644 --- a/drivers/tty/hvc/hvc_iucv.c +++ b/drivers/tty/hvc/hvc_iucv.c | |||
@@ -1328,7 +1328,7 @@ out_error: | |||
1328 | */ | 1328 | */ |
1329 | static int __init hvc_iucv_config(char *val) | 1329 | static int __init hvc_iucv_config(char *val) |
1330 | { | 1330 | { |
1331 | return strict_strtoul(val, 10, &hvc_iucv_devices); | 1331 | return kstrtoul(val, 10, &hvc_iucv_devices); |
1332 | } | 1332 | } |
1333 | 1333 | ||
1334 | 1334 | ||
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 6c7fe90ad72d..4bf0fc0843d7 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c | |||
@@ -89,6 +89,7 @@ struct n_tty_data { | |||
89 | int read_head; | 89 | int read_head; |
90 | int read_tail; | 90 | int read_tail; |
91 | int read_cnt; | 91 | int read_cnt; |
92 | int minimum_to_wake; | ||
92 | 93 | ||
93 | unsigned char *echo_buf; | 94 | unsigned char *echo_buf; |
94 | unsigned int echo_pos; | 95 | unsigned int echo_pos; |
@@ -114,22 +115,25 @@ static inline int tty_put_user(struct tty_struct *tty, unsigned char x, | |||
114 | } | 115 | } |
115 | 116 | ||
116 | /** | 117 | /** |
117 | * n_tty_set__room - receive space | 118 | * n_tty_set_room - receive space |
118 | * @tty: terminal | 119 | * @tty: terminal |
119 | * | 120 | * |
120 | * Called by the driver to find out how much data it is | 121 | * Updates tty->receive_room to reflect the currently available space |
121 | * permitted to feed to the line discipline without any being lost | 122 | * in the input buffer, and re-schedules the flip buffer work if space |
122 | * and thus to manage flow control. Not serialized. Answers for the | 123 | * just became available. |
123 | * "instant". | 124 | * |
125 | * Locks: Concurrent update is protected with read_lock | ||
124 | */ | 126 | */ |
125 | 127 | ||
126 | static void n_tty_set_room(struct tty_struct *tty) | 128 | static int set_room(struct tty_struct *tty) |
127 | { | 129 | { |
128 | struct n_tty_data *ldata = tty->disc_data; | 130 | struct n_tty_data *ldata = tty->disc_data; |
129 | int left; | 131 | int left; |
130 | int old_left; | 132 | int old_left; |
133 | unsigned long flags; | ||
134 | |||
135 | raw_spin_lock_irqsave(&ldata->read_lock, flags); | ||
131 | 136 | ||
132 | /* ldata->read_cnt is not read locked ? */ | ||
133 | if (I_PARMRK(tty)) { | 137 | if (I_PARMRK(tty)) { |
134 | /* Multiply read_cnt by 3, since each byte might take up to | 138 | /* Multiply read_cnt by 3, since each byte might take up to |
135 | * three times as many spaces when PARMRK is set (depending on | 139 | * three times as many spaces when PARMRK is set (depending on |
@@ -149,8 +153,15 @@ static void n_tty_set_room(struct tty_struct *tty) | |||
149 | old_left = tty->receive_room; | 153 | old_left = tty->receive_room; |
150 | tty->receive_room = left; | 154 | tty->receive_room = left; |
151 | 155 | ||
156 | raw_spin_unlock_irqrestore(&ldata->read_lock, flags); | ||
157 | |||
158 | return left && !old_left; | ||
159 | } | ||
160 | |||
161 | static void n_tty_set_room(struct tty_struct *tty) | ||
162 | { | ||
152 | /* Did this open up the receive buffer? We may need to flip */ | 163 | /* Did this open up the receive buffer? We may need to flip */ |
153 | if (left && !old_left) { | 164 | if (set_room(tty)) { |
154 | WARN_RATELIMIT(tty->port->itty == NULL, | 165 | WARN_RATELIMIT(tty->port->itty == NULL, |
155 | "scheduling with invalid itty\n"); | 166 | "scheduling with invalid itty\n"); |
156 | /* see if ldisc has been killed - if so, this means that | 167 | /* see if ldisc has been killed - if so, this means that |
@@ -647,8 +658,7 @@ static void process_echoes(struct tty_struct *tty) | |||
647 | if (no_space_left) | 658 | if (no_space_left) |
648 | break; | 659 | break; |
649 | } else { | 660 | } else { |
650 | if (O_OPOST(tty) && | 661 | if (O_OPOST(tty)) { |
651 | !(test_bit(TTY_HW_COOK_OUT, &tty->flags))) { | ||
652 | int retval = do_output_char(c, tty, space); | 662 | int retval = do_output_char(c, tty, space); |
653 | if (retval < 0) | 663 | if (retval < 0) |
654 | break; | 664 | break; |
@@ -1454,9 +1464,9 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp, | |||
1454 | tty->ops->flush_chars(tty); | 1464 | tty->ops->flush_chars(tty); |
1455 | } | 1465 | } |
1456 | 1466 | ||
1457 | n_tty_set_room(tty); | 1467 | set_room(tty); |
1458 | 1468 | ||
1459 | if ((!ldata->icanon && (ldata->read_cnt >= tty->minimum_to_wake)) || | 1469 | if ((!ldata->icanon && (ldata->read_cnt >= ldata->minimum_to_wake)) || |
1460 | L_EXTPROC(tty)) { | 1470 | L_EXTPROC(tty)) { |
1461 | kill_fasync(&tty->fasync, SIGIO, POLL_IN); | 1471 | kill_fasync(&tty->fasync, SIGIO, POLL_IN); |
1462 | if (waitqueue_active(&tty->read_wait)) | 1472 | if (waitqueue_active(&tty->read_wait)) |
@@ -1516,12 +1526,7 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old) | |||
1516 | wake_up_interruptible(&tty->read_wait); | 1526 | wake_up_interruptible(&tty->read_wait); |
1517 | 1527 | ||
1518 | ldata->icanon = (L_ICANON(tty) != 0); | 1528 | ldata->icanon = (L_ICANON(tty) != 0); |
1519 | if (test_bit(TTY_HW_COOK_IN, &tty->flags)) { | 1529 | |
1520 | ldata->raw = 1; | ||
1521 | ldata->real_raw = 1; | ||
1522 | n_tty_set_room(tty); | ||
1523 | return; | ||
1524 | } | ||
1525 | if (I_ISTRIP(tty) || I_IUCLC(tty) || I_IGNCR(tty) || | 1530 | if (I_ISTRIP(tty) || I_IUCLC(tty) || I_IGNCR(tty) || |
1526 | I_ICRNL(tty) || I_INLCR(tty) || L_ICANON(tty) || | 1531 | I_ICRNL(tty) || I_INLCR(tty) || L_ICANON(tty) || |
1527 | I_IXON(tty) || L_ISIG(tty) || L_ECHO(tty) || | 1532 | I_IXON(tty) || L_ISIG(tty) || L_ECHO(tty) || |
@@ -1642,7 +1647,7 @@ static int n_tty_open(struct tty_struct *tty) | |||
1642 | tty->disc_data = ldata; | 1647 | tty->disc_data = ldata; |
1643 | reset_buffer_flags(tty->disc_data); | 1648 | reset_buffer_flags(tty->disc_data); |
1644 | ldata->column = 0; | 1649 | ldata->column = 0; |
1645 | tty->minimum_to_wake = 1; | 1650 | ldata->minimum_to_wake = 1; |
1646 | tty->closing = 0; | 1651 | tty->closing = 0; |
1647 | /* indicate buffer work may resume */ | 1652 | /* indicate buffer work may resume */ |
1648 | clear_bit(TTY_LDISC_HALTED, &tty->flags); | 1653 | clear_bit(TTY_LDISC_HALTED, &tty->flags); |
@@ -1806,21 +1811,17 @@ do_it_again: | |||
1806 | minimum = time = 0; | 1811 | minimum = time = 0; |
1807 | timeout = MAX_SCHEDULE_TIMEOUT; | 1812 | timeout = MAX_SCHEDULE_TIMEOUT; |
1808 | if (!ldata->icanon) { | 1813 | if (!ldata->icanon) { |
1809 | time = (HZ / 10) * TIME_CHAR(tty); | ||
1810 | minimum = MIN_CHAR(tty); | 1814 | minimum = MIN_CHAR(tty); |
1811 | if (minimum) { | 1815 | if (minimum) { |
1816 | time = (HZ / 10) * TIME_CHAR(tty); | ||
1812 | if (time) | 1817 | if (time) |
1813 | tty->minimum_to_wake = 1; | 1818 | ldata->minimum_to_wake = 1; |
1814 | else if (!waitqueue_active(&tty->read_wait) || | 1819 | else if (!waitqueue_active(&tty->read_wait) || |
1815 | (tty->minimum_to_wake > minimum)) | 1820 | (ldata->minimum_to_wake > minimum)) |
1816 | tty->minimum_to_wake = minimum; | 1821 | ldata->minimum_to_wake = minimum; |
1817 | } else { | 1822 | } else { |
1818 | timeout = 0; | 1823 | timeout = (HZ / 10) * TIME_CHAR(tty); |
1819 | if (time) { | 1824 | ldata->minimum_to_wake = minimum = 1; |
1820 | timeout = time; | ||
1821 | time = 0; | ||
1822 | } | ||
1823 | tty->minimum_to_wake = minimum = 1; | ||
1824 | } | 1825 | } |
1825 | } | 1826 | } |
1826 | 1827 | ||
@@ -1860,9 +1861,9 @@ do_it_again: | |||
1860 | TASK_RUNNING. */ | 1861 | TASK_RUNNING. */ |
1861 | set_current_state(TASK_INTERRUPTIBLE); | 1862 | set_current_state(TASK_INTERRUPTIBLE); |
1862 | 1863 | ||
1863 | if (((minimum - (b - buf)) < tty->minimum_to_wake) && | 1864 | if (((minimum - (b - buf)) < ldata->minimum_to_wake) && |
1864 | ((minimum - (b - buf)) >= 1)) | 1865 | ((minimum - (b - buf)) >= 1)) |
1865 | tty->minimum_to_wake = (minimum - (b - buf)); | 1866 | ldata->minimum_to_wake = (minimum - (b - buf)); |
1866 | 1867 | ||
1867 | if (!input_available_p(tty, 0)) { | 1868 | if (!input_available_p(tty, 0)) { |
1868 | if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) { | 1869 | if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) { |
@@ -1881,7 +1882,6 @@ do_it_again: | |||
1881 | retval = -ERESTARTSYS; | 1882 | retval = -ERESTARTSYS; |
1882 | break; | 1883 | break; |
1883 | } | 1884 | } |
1884 | /* FIXME: does n_tty_set_room need locking ? */ | ||
1885 | n_tty_set_room(tty); | 1885 | n_tty_set_room(tty); |
1886 | timeout = schedule_timeout(timeout); | 1886 | timeout = schedule_timeout(timeout); |
1887 | continue; | 1887 | continue; |
@@ -1979,7 +1979,7 @@ do_it_again: | |||
1979 | remove_wait_queue(&tty->read_wait, &wait); | 1979 | remove_wait_queue(&tty->read_wait, &wait); |
1980 | 1980 | ||
1981 | if (!waitqueue_active(&tty->read_wait)) | 1981 | if (!waitqueue_active(&tty->read_wait)) |
1982 | tty->minimum_to_wake = minimum; | 1982 | ldata->minimum_to_wake = minimum; |
1983 | 1983 | ||
1984 | __set_current_state(TASK_RUNNING); | 1984 | __set_current_state(TASK_RUNNING); |
1985 | size = b - buf; | 1985 | size = b - buf; |
@@ -2045,7 +2045,7 @@ static ssize_t n_tty_write(struct tty_struct *tty, struct file *file, | |||
2045 | retval = -EIO; | 2045 | retval = -EIO; |
2046 | break; | 2046 | break; |
2047 | } | 2047 | } |
2048 | if (O_OPOST(tty) && !(test_bit(TTY_HW_COOK_OUT, &tty->flags))) { | 2048 | if (O_OPOST(tty)) { |
2049 | while (nr > 0) { | 2049 | while (nr > 0) { |
2050 | ssize_t num = process_output_block(tty, b, nr); | 2050 | ssize_t num = process_output_block(tty, b, nr); |
2051 | if (num < 0) { | 2051 | if (num < 0) { |
@@ -2111,6 +2111,7 @@ break_out: | |||
2111 | static unsigned int n_tty_poll(struct tty_struct *tty, struct file *file, | 2111 | static unsigned int n_tty_poll(struct tty_struct *tty, struct file *file, |
2112 | poll_table *wait) | 2112 | poll_table *wait) |
2113 | { | 2113 | { |
2114 | struct n_tty_data *ldata = tty->disc_data; | ||
2114 | unsigned int mask = 0; | 2115 | unsigned int mask = 0; |
2115 | 2116 | ||
2116 | poll_wait(file, &tty->read_wait, wait); | 2117 | poll_wait(file, &tty->read_wait, wait); |
@@ -2125,9 +2126,9 @@ static unsigned int n_tty_poll(struct tty_struct *tty, struct file *file, | |||
2125 | mask |= POLLHUP; | 2126 | mask |= POLLHUP; |
2126 | if (!(mask & (POLLHUP | POLLIN | POLLRDNORM))) { | 2127 | if (!(mask & (POLLHUP | POLLIN | POLLRDNORM))) { |
2127 | if (MIN_CHAR(tty) && !TIME_CHAR(tty)) | 2128 | if (MIN_CHAR(tty) && !TIME_CHAR(tty)) |
2128 | tty->minimum_to_wake = MIN_CHAR(tty); | 2129 | ldata->minimum_to_wake = MIN_CHAR(tty); |
2129 | else | 2130 | else |
2130 | tty->minimum_to_wake = 1; | 2131 | ldata->minimum_to_wake = 1; |
2131 | } | 2132 | } |
2132 | if (tty->ops->write && !tty_is_writelocked(tty) && | 2133 | if (tty->ops->write && !tty_is_writelocked(tty) && |
2133 | tty_chars_in_buffer(tty) < WAKEUP_CHARS && | 2134 | tty_chars_in_buffer(tty) < WAKEUP_CHARS && |
@@ -2175,6 +2176,18 @@ static int n_tty_ioctl(struct tty_struct *tty, struct file *file, | |||
2175 | } | 2176 | } |
2176 | } | 2177 | } |
2177 | 2178 | ||
2179 | static void n_tty_fasync(struct tty_struct *tty, int on) | ||
2180 | { | ||
2181 | struct n_tty_data *ldata = tty->disc_data; | ||
2182 | |||
2183 | if (!waitqueue_active(&tty->read_wait)) { | ||
2184 | if (on) | ||
2185 | ldata->minimum_to_wake = 1; | ||
2186 | else if (!tty->fasync) | ||
2187 | ldata->minimum_to_wake = N_TTY_BUF_SIZE; | ||
2188 | } | ||
2189 | } | ||
2190 | |||
2178 | struct tty_ldisc_ops tty_ldisc_N_TTY = { | 2191 | struct tty_ldisc_ops tty_ldisc_N_TTY = { |
2179 | .magic = TTY_LDISC_MAGIC, | 2192 | .magic = TTY_LDISC_MAGIC, |
2180 | .name = "n_tty", | 2193 | .name = "n_tty", |
@@ -2188,7 +2201,8 @@ struct tty_ldisc_ops tty_ldisc_N_TTY = { | |||
2188 | .set_termios = n_tty_set_termios, | 2201 | .set_termios = n_tty_set_termios, |
2189 | .poll = n_tty_poll, | 2202 | .poll = n_tty_poll, |
2190 | .receive_buf = n_tty_receive_buf, | 2203 | .receive_buf = n_tty_receive_buf, |
2191 | .write_wakeup = n_tty_write_wakeup | 2204 | .write_wakeup = n_tty_write_wakeup, |
2205 | .fasync = n_tty_fasync, | ||
2192 | }; | 2206 | }; |
2193 | 2207 | ||
2194 | /** | 2208 | /** |
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 26e3a97ab157..c52948b368d8 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c | |||
@@ -4797,10 +4797,6 @@ static struct pci_device_id serial_pci_tbl[] = { | |||
4797 | PCI_VENDOR_ID_IBM, 0x0299, | 4797 | PCI_VENDOR_ID_IBM, 0x0299, |
4798 | 0, 0, pbn_b0_bt_2_115200 }, | 4798 | 0, 0, pbn_b0_bt_2_115200 }, |
4799 | 4799 | ||
4800 | { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9835, | ||
4801 | 0x1000, 0x0012, | ||
4802 | 0, 0, pbn_b0_bt_2_115200 }, | ||
4803 | |||
4804 | { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9901, | 4800 | { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9901, |
4805 | 0xA000, 0x1000, | 4801 | 0xA000, 0x1000, |
4806 | 0, 0, pbn_b0_1_115200 }, | 4802 | 0, 0, pbn_b0_1_115200 }, |
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index 80fe91e64a52..a1ba94d64885 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig | |||
@@ -12,9 +12,8 @@ config SERIAL_8250 | |||
12 | here are those that are setting up dedicated Ethernet WWW/FTP | 12 | here are those that are setting up dedicated Ethernet WWW/FTP |
13 | servers, or users that have one of the various bus mice instead of a | 13 | servers, or users that have one of the various bus mice instead of a |
14 | serial mouse and don't intend to use their machine's standard serial | 14 | serial mouse and don't intend to use their machine's standard serial |
15 | port for anything. (Note that the Cyclades and Stallion multi | 15 | port for anything. (Note that the Cyclades multi serial port driver |
16 | serial port drivers do not need this driver built in for them to | 16 | does not need this driver built in for it to work.) |
17 | work.) | ||
18 | 17 | ||
19 | To compile this driver as a module, choose M here: the | 18 | To compile this driver as a module, choose M here: the |
20 | module will be called 8250. | 19 | module will be called 8250. |
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 7e7006fd404e..46dd1c72feda 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig | |||
@@ -551,7 +551,7 @@ config BFIN_UART3_CTSRTS | |||
551 | Enable hardware flow control in the driver. | 551 | Enable hardware flow control in the driver. |
552 | 552 | ||
553 | config SERIAL_IMX | 553 | config SERIAL_IMX |
554 | bool "IMX serial port support" | 554 | tristate "IMX serial port support" |
555 | depends on ARCH_MXC | 555 | depends on ARCH_MXC |
556 | select SERIAL_CORE | 556 | select SERIAL_CORE |
557 | select RATIONAL | 557 | select RATIONAL |
@@ -561,22 +561,21 @@ config SERIAL_IMX | |||
561 | 561 | ||
562 | config SERIAL_IMX_CONSOLE | 562 | config SERIAL_IMX_CONSOLE |
563 | bool "Console on IMX serial port" | 563 | bool "Console on IMX serial port" |
564 | depends on SERIAL_IMX | 564 | depends on SERIAL_IMX=y |
565 | select SERIAL_CORE_CONSOLE | 565 | select SERIAL_CORE_CONSOLE |
566 | help | 566 | help |
567 | If you have enabled the serial port on the Motorola IMX | 567 | If you have enabled the serial port on the Freescale IMX |
568 | CPU you can make it the console by answering Y to this option. | 568 | CPU you can make it the console by answering Y to this option. |
569 | 569 | ||
570 | Even if you say Y here, the currently visible virtual console | 570 | Even if you say Y here, the currently visible virtual console |
571 | (/dev/tty0) will still be used as the system console by default, but | 571 | (/dev/tty0) will still be used as the system console by default, but |
572 | you can alter that using a kernel command line option such as | 572 | you can alter that using a kernel command line option such as |
573 | "console=ttySA0". (Try "man bootparam" or see the documentation of | 573 | "console=ttymxc0". (Try "man bootparam" or see the documentation of |
574 | your boot loader (lilo or loadlin) about how to pass options to the | 574 | your bootloader about how to pass options to the kernel at boot time.) |
575 | kernel at boot time.) | ||
576 | 575 | ||
577 | config SERIAL_UARTLITE | 576 | config SERIAL_UARTLITE |
578 | tristate "Xilinx uartlite serial port support" | 577 | tristate "Xilinx uartlite serial port support" |
579 | depends on PPC32 || MICROBLAZE || MFD_TIMBERDALE | 578 | depends on PPC32 || MICROBLAZE || MFD_TIMBERDALE || ARCH_ZYNQ |
580 | select SERIAL_CORE | 579 | select SERIAL_CORE |
581 | help | 580 | help |
582 | Say Y here if you want to use the Xilinx uartlite serial controller. | 581 | Say Y here if you want to use the Xilinx uartlite serial controller. |
@@ -1484,6 +1483,20 @@ config SERIAL_RP2_NR_UARTS | |||
1484 | If multiple cards are present, the default limit of 32 ports may | 1483 | If multiple cards are present, the default limit of 32 ports may |
1485 | need to be increased. | 1484 | need to be increased. |
1486 | 1485 | ||
1486 | config SERIAL_FSL_LPUART | ||
1487 | tristate "Freescale lpuart serial port support" | ||
1488 | select SERIAL_CORE | ||
1489 | help | ||
1490 | Support for the on-chip lpuart on some Freescale SOCs. | ||
1491 | |||
1492 | config SERIAL_FSL_LPUART_CONSOLE | ||
1493 | bool "Console on Freescale lpuart serial port" | ||
1494 | depends on SERIAL_FSL_LPUART=y | ||
1495 | select SERIAL_CORE_CONSOLE | ||
1496 | help | ||
1497 | If you have enabled the lpuart serial port on the Freescale SoCs, | ||
1498 | you can make it the console by answering Y to this option. | ||
1499 | |||
1487 | endmenu | 1500 | endmenu |
1488 | 1501 | ||
1489 | endif # TTY | 1502 | endif # TTY |
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile index eedfec40e3dd..cf650f0cd6e4 100644 --- a/drivers/tty/serial/Makefile +++ b/drivers/tty/serial/Makefile | |||
@@ -85,3 +85,4 @@ obj-$(CONFIG_SERIAL_AR933X) += ar933x_uart.o | |||
85 | obj-$(CONFIG_SERIAL_EFM32_UART) += efm32-uart.o | 85 | obj-$(CONFIG_SERIAL_EFM32_UART) += efm32-uart.o |
86 | obj-$(CONFIG_SERIAL_ARC) += arc_uart.o | 86 | obj-$(CONFIG_SERIAL_ARC) += arc_uart.o |
87 | obj-$(CONFIG_SERIAL_RP2) += rp2.o | 87 | obj-$(CONFIG_SERIAL_RP2) += rp2.o |
88 | obj-$(CONFIG_SERIAL_FSL_LPUART) += fsl_lpuart.o | ||
diff --git a/drivers/tty/serial/altera_uart.c b/drivers/tty/serial/altera_uart.c index 13471dd95793..1d46966e2a65 100644 --- a/drivers/tty/serial/altera_uart.c +++ b/drivers/tty/serial/altera_uart.c | |||
@@ -604,7 +604,6 @@ static int altera_uart_remove(struct platform_device *pdev) | |||
604 | 604 | ||
605 | if (port) { | 605 | if (port) { |
606 | uart_remove_one_port(&altera_uart_driver, port); | 606 | uart_remove_one_port(&altera_uart_driver, port); |
607 | platform_set_drvdata(pdev, NULL); | ||
608 | port->mapbase = 0; | 607 | port->mapbase = 0; |
609 | } | 608 | } |
610 | 609 | ||
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index e2774f9ecd59..ad41319d1d9b 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c | |||
@@ -79,13 +79,12 @@ struct vendor_data { | |||
79 | bool dma_threshold; | 79 | bool dma_threshold; |
80 | bool cts_event_workaround; | 80 | bool cts_event_workaround; |
81 | 81 | ||
82 | unsigned int (*get_fifosize)(unsigned int periphid); | 82 | unsigned int (*get_fifosize)(struct amba_device *dev); |
83 | }; | 83 | }; |
84 | 84 | ||
85 | static unsigned int get_fifosize_arm(unsigned int periphid) | 85 | static unsigned int get_fifosize_arm(struct amba_device *dev) |
86 | { | 86 | { |
87 | unsigned int rev = (periphid >> 20) & 0xf; | 87 | return amba_rev(dev) < 3 ? 16 : 32; |
88 | return rev < 3 ? 16 : 32; | ||
89 | } | 88 | } |
90 | 89 | ||
91 | static struct vendor_data vendor_arm = { | 90 | static struct vendor_data vendor_arm = { |
@@ -98,7 +97,7 @@ static struct vendor_data vendor_arm = { | |||
98 | .get_fifosize = get_fifosize_arm, | 97 | .get_fifosize = get_fifosize_arm, |
99 | }; | 98 | }; |
100 | 99 | ||
101 | static unsigned int get_fifosize_st(unsigned int periphid) | 100 | static unsigned int get_fifosize_st(struct amba_device *dev) |
102 | { | 101 | { |
103 | return 64; | 102 | return 64; |
104 | } | 103 | } |
@@ -2157,7 +2156,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) | |||
2157 | uap->lcrh_rx = vendor->lcrh_rx; | 2156 | uap->lcrh_rx = vendor->lcrh_rx; |
2158 | uap->lcrh_tx = vendor->lcrh_tx; | 2157 | uap->lcrh_tx = vendor->lcrh_tx; |
2159 | uap->old_cr = 0; | 2158 | uap->old_cr = 0; |
2160 | uap->fifosize = vendor->get_fifosize(dev->periphid); | 2159 | uap->fifosize = vendor->get_fifosize(dev); |
2161 | uap->port.dev = &dev->dev; | 2160 | uap->port.dev = &dev->dev; |
2162 | uap->port.mapbase = dev->res.start; | 2161 | uap->port.mapbase = dev->res.start; |
2163 | uap->port.membase = base; | 2162 | uap->port.membase = base; |
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 3467462869ce..691265faebbe 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c | |||
@@ -1100,7 +1100,7 @@ static void atmel_serial_pm(struct uart_port *port, unsigned int state, | |||
1100 | * Enable the peripheral clock for this serial port. | 1100 | * Enable the peripheral clock for this serial port. |
1101 | * This is called on uart_open() or a resume event. | 1101 | * This is called on uart_open() or a resume event. |
1102 | */ | 1102 | */ |
1103 | clk_enable(atmel_port->clk); | 1103 | clk_prepare_enable(atmel_port->clk); |
1104 | 1104 | ||
1105 | /* re-enable interrupts if we disabled some on suspend */ | 1105 | /* re-enable interrupts if we disabled some on suspend */ |
1106 | UART_PUT_IER(port, atmel_port->backup_imr); | 1106 | UART_PUT_IER(port, atmel_port->backup_imr); |
@@ -1114,7 +1114,7 @@ static void atmel_serial_pm(struct uart_port *port, unsigned int state, | |||
1114 | * Disable the peripheral clock for this serial port. | 1114 | * Disable the peripheral clock for this serial port. |
1115 | * This is called on uart_close() or a suspend event. | 1115 | * This is called on uart_close() or a suspend event. |
1116 | */ | 1116 | */ |
1117 | clk_disable(atmel_port->clk); | 1117 | clk_disable_unprepare(atmel_port->clk); |
1118 | break; | 1118 | break; |
1119 | default: | 1119 | default: |
1120 | printk(KERN_ERR "atmel_serial: unknown pm %d\n", state); | 1120 | printk(KERN_ERR "atmel_serial: unknown pm %d\n", state); |
@@ -1458,9 +1458,10 @@ static void atmel_of_init_port(struct atmel_uart_port *atmel_port, | |||
1458 | /* | 1458 | /* |
1459 | * Configure the port from the platform device resource info. | 1459 | * Configure the port from the platform device resource info. |
1460 | */ | 1460 | */ |
1461 | static void atmel_init_port(struct atmel_uart_port *atmel_port, | 1461 | static int atmel_init_port(struct atmel_uart_port *atmel_port, |
1462 | struct platform_device *pdev) | 1462 | struct platform_device *pdev) |
1463 | { | 1463 | { |
1464 | int ret; | ||
1464 | struct uart_port *port = &atmel_port->uart; | 1465 | struct uart_port *port = &atmel_port->uart; |
1465 | struct atmel_uart_data *pdata = pdev->dev.platform_data; | 1466 | struct atmel_uart_data *pdata = pdev->dev.platform_data; |
1466 | 1467 | ||
@@ -1496,9 +1497,19 @@ static void atmel_init_port(struct atmel_uart_port *atmel_port, | |||
1496 | /* for console, the clock could already be configured */ | 1497 | /* for console, the clock could already be configured */ |
1497 | if (!atmel_port->clk) { | 1498 | if (!atmel_port->clk) { |
1498 | atmel_port->clk = clk_get(&pdev->dev, "usart"); | 1499 | atmel_port->clk = clk_get(&pdev->dev, "usart"); |
1499 | clk_enable(atmel_port->clk); | 1500 | if (IS_ERR(atmel_port->clk)) { |
1501 | ret = PTR_ERR(atmel_port->clk); | ||
1502 | atmel_port->clk = NULL; | ||
1503 | return ret; | ||
1504 | } | ||
1505 | ret = clk_prepare_enable(atmel_port->clk); | ||
1506 | if (ret) { | ||
1507 | clk_put(atmel_port->clk); | ||
1508 | atmel_port->clk = NULL; | ||
1509 | return ret; | ||
1510 | } | ||
1500 | port->uartclk = clk_get_rate(atmel_port->clk); | 1511 | port->uartclk = clk_get_rate(atmel_port->clk); |
1501 | clk_disable(atmel_port->clk); | 1512 | clk_disable_unprepare(atmel_port->clk); |
1502 | /* only enable clock when USART is in use */ | 1513 | /* only enable clock when USART is in use */ |
1503 | } | 1514 | } |
1504 | 1515 | ||
@@ -1511,6 +1522,8 @@ static void atmel_init_port(struct atmel_uart_port *atmel_port, | |||
1511 | } else { | 1522 | } else { |
1512 | atmel_port->tx_done_mask = ATMEL_US_TXRDY; | 1523 | atmel_port->tx_done_mask = ATMEL_US_TXRDY; |
1513 | } | 1524 | } |
1525 | |||
1526 | return 0; | ||
1514 | } | 1527 | } |
1515 | 1528 | ||
1516 | struct platform_device *atmel_default_console_device; /* the serial console device */ | 1529 | struct platform_device *atmel_default_console_device; /* the serial console device */ |
@@ -1601,6 +1614,7 @@ static void __init atmel_console_get_options(struct uart_port *port, int *baud, | |||
1601 | 1614 | ||
1602 | static int __init atmel_console_setup(struct console *co, char *options) | 1615 | static int __init atmel_console_setup(struct console *co, char *options) |
1603 | { | 1616 | { |
1617 | int ret; | ||
1604 | struct uart_port *port = &atmel_ports[co->index].uart; | 1618 | struct uart_port *port = &atmel_ports[co->index].uart; |
1605 | int baud = 115200; | 1619 | int baud = 115200; |
1606 | int bits = 8; | 1620 | int bits = 8; |
@@ -1612,7 +1626,9 @@ static int __init atmel_console_setup(struct console *co, char *options) | |||
1612 | return -ENODEV; | 1626 | return -ENODEV; |
1613 | } | 1627 | } |
1614 | 1628 | ||
1615 | clk_enable(atmel_ports[co->index].clk); | 1629 | ret = clk_prepare_enable(atmel_ports[co->index].clk); |
1630 | if (ret) | ||
1631 | return ret; | ||
1616 | 1632 | ||
1617 | UART_PUT_IDR(port, -1); | 1633 | UART_PUT_IDR(port, -1); |
1618 | UART_PUT_CR(port, ATMEL_US_RSTSTA | ATMEL_US_RSTRX); | 1634 | UART_PUT_CR(port, ATMEL_US_RSTSTA | ATMEL_US_RSTRX); |
@@ -1645,6 +1661,7 @@ static struct console atmel_console = { | |||
1645 | */ | 1661 | */ |
1646 | static int __init atmel_console_init(void) | 1662 | static int __init atmel_console_init(void) |
1647 | { | 1663 | { |
1664 | int ret; | ||
1648 | if (atmel_default_console_device) { | 1665 | if (atmel_default_console_device) { |
1649 | struct atmel_uart_data *pdata = | 1666 | struct atmel_uart_data *pdata = |
1650 | atmel_default_console_device->dev.platform_data; | 1667 | atmel_default_console_device->dev.platform_data; |
@@ -1655,7 +1672,9 @@ static int __init atmel_console_init(void) | |||
1655 | port->uart.line = id; | 1672 | port->uart.line = id; |
1656 | 1673 | ||
1657 | add_preferred_console(ATMEL_DEVICENAME, id, NULL); | 1674 | add_preferred_console(ATMEL_DEVICENAME, id, NULL); |
1658 | atmel_init_port(port, atmel_default_console_device); | 1675 | ret = atmel_init_port(port, atmel_default_console_device); |
1676 | if (ret) | ||
1677 | return ret; | ||
1659 | register_console(&atmel_console); | 1678 | register_console(&atmel_console); |
1660 | } | 1679 | } |
1661 | 1680 | ||
@@ -1786,7 +1805,9 @@ static int atmel_serial_probe(struct platform_device *pdev) | |||
1786 | port->backup_imr = 0; | 1805 | port->backup_imr = 0; |
1787 | port->uart.line = ret; | 1806 | port->uart.line = ret; |
1788 | 1807 | ||
1789 | atmel_init_port(port, pdev); | 1808 | ret = atmel_init_port(port, pdev); |
1809 | if (ret) | ||
1810 | goto err; | ||
1790 | 1811 | ||
1791 | pinctrl = devm_pinctrl_get_select_default(&pdev->dev); | 1812 | pinctrl = devm_pinctrl_get_select_default(&pdev->dev); |
1792 | if (IS_ERR(pinctrl)) { | 1813 | if (IS_ERR(pinctrl)) { |
@@ -1812,9 +1833,9 @@ static int atmel_serial_probe(struct platform_device *pdev) | |||
1812 | && ATMEL_CONSOLE_DEVICE->flags & CON_ENABLED) { | 1833 | && ATMEL_CONSOLE_DEVICE->flags & CON_ENABLED) { |
1813 | /* | 1834 | /* |
1814 | * The serial core enabled the clock for us, so undo | 1835 | * The serial core enabled the clock for us, so undo |
1815 | * the clk_enable() in atmel_console_setup() | 1836 | * the clk_prepare_enable() in atmel_console_setup() |
1816 | */ | 1837 | */ |
1817 | clk_disable(port->clk); | 1838 | clk_disable_unprepare(port->clk); |
1818 | } | 1839 | } |
1819 | #endif | 1840 | #endif |
1820 | 1841 | ||
diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_core.c b/drivers/tty/serial/cpm_uart/cpm_uart_core.c index 97f4e1858649..f7672cae5321 100644 --- a/drivers/tty/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/tty/serial/cpm_uart/cpm_uart_core.c | |||
@@ -1384,7 +1384,7 @@ static int cpm_uart_probe(struct platform_device *ofdev) | |||
1384 | if (index >= UART_NR) | 1384 | if (index >= UART_NR) |
1385 | return -ENODEV; | 1385 | return -ENODEV; |
1386 | 1386 | ||
1387 | dev_set_drvdata(&ofdev->dev, pinfo); | 1387 | platform_set_drvdata(ofdev, pinfo); |
1388 | 1388 | ||
1389 | /* initialize the device pointer for the port */ | 1389 | /* initialize the device pointer for the port */ |
1390 | pinfo->port.dev = &ofdev->dev; | 1390 | pinfo->port.dev = &ofdev->dev; |
@@ -1398,7 +1398,7 @@ static int cpm_uart_probe(struct platform_device *ofdev) | |||
1398 | 1398 | ||
1399 | static int cpm_uart_remove(struct platform_device *ofdev) | 1399 | static int cpm_uart_remove(struct platform_device *ofdev) |
1400 | { | 1400 | { |
1401 | struct uart_cpm_port *pinfo = dev_get_drvdata(&ofdev->dev); | 1401 | struct uart_cpm_port *pinfo = platform_get_drvdata(ofdev); |
1402 | return uart_remove_one_port(&cpm_reg, &pinfo->port); | 1402 | return uart_remove_one_port(&cpm_reg, &pinfo->port); |
1403 | } | 1403 | } |
1404 | 1404 | ||
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c new file mode 100644 index 000000000000..263cfaabe9e2 --- /dev/null +++ b/drivers/tty/serial/fsl_lpuart.c | |||
@@ -0,0 +1,874 @@ | |||
1 | /* | ||
2 | * Freescale lpuart serial port driver | ||
3 | * | ||
4 | * Copyright 2012-2013 Freescale Semiconductor, Inc. | ||
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 | |||
12 | #if defined(CONFIG_SERIAL_FSL_LPUART_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) | ||
13 | #define SUPPORT_SYSRQ | ||
14 | #endif | ||
15 | |||
16 | #include <linux/module.h> | ||
17 | #include <linux/io.h> | ||
18 | #include <linux/irq.h> | ||
19 | #include <linux/clk.h> | ||
20 | #include <linux/of.h> | ||
21 | #include <linux/of_device.h> | ||
22 | #include <linux/console.h> | ||
23 | #include <linux/serial_core.h> | ||
24 | #include <linux/tty_flip.h> | ||
25 | |||
26 | /* All registers are 8-bit width */ | ||
27 | #define UARTBDH 0x00 | ||
28 | #define UARTBDL 0x01 | ||
29 | #define UARTCR1 0x02 | ||
30 | #define UARTCR2 0x03 | ||
31 | #define UARTSR1 0x04 | ||
32 | #define UARTCR3 0x06 | ||
33 | #define UARTDR 0x07 | ||
34 | #define UARTCR4 0x0a | ||
35 | #define UARTCR5 0x0b | ||
36 | #define UARTMODEM 0x0d | ||
37 | #define UARTPFIFO 0x10 | ||
38 | #define UARTCFIFO 0x11 | ||
39 | #define UARTSFIFO 0x12 | ||
40 | #define UARTTWFIFO 0x13 | ||
41 | #define UARTTCFIFO 0x14 | ||
42 | #define UARTRWFIFO 0x15 | ||
43 | |||
44 | #define UARTBDH_LBKDIE 0x80 | ||
45 | #define UARTBDH_RXEDGIE 0x40 | ||
46 | #define UARTBDH_SBR_MASK 0x1f | ||
47 | |||
48 | #define UARTCR1_LOOPS 0x80 | ||
49 | #define UARTCR1_RSRC 0x20 | ||
50 | #define UARTCR1_M 0x10 | ||
51 | #define UARTCR1_WAKE 0x08 | ||
52 | #define UARTCR1_ILT 0x04 | ||
53 | #define UARTCR1_PE 0x02 | ||
54 | #define UARTCR1_PT 0x01 | ||
55 | |||
56 | #define UARTCR2_TIE 0x80 | ||
57 | #define UARTCR2_TCIE 0x40 | ||
58 | #define UARTCR2_RIE 0x20 | ||
59 | #define UARTCR2_ILIE 0x10 | ||
60 | #define UARTCR2_TE 0x08 | ||
61 | #define UARTCR2_RE 0x04 | ||
62 | #define UARTCR2_RWU 0x02 | ||
63 | #define UARTCR2_SBK 0x01 | ||
64 | |||
65 | #define UARTSR1_TDRE 0x80 | ||
66 | #define UARTSR1_TC 0x40 | ||
67 | #define UARTSR1_RDRF 0x20 | ||
68 | #define UARTSR1_IDLE 0x10 | ||
69 | #define UARTSR1_OR 0x08 | ||
70 | #define UARTSR1_NF 0x04 | ||
71 | #define UARTSR1_FE 0x02 | ||
72 | #define UARTSR1_PE 0x01 | ||
73 | |||
74 | #define UARTCR3_R8 0x80 | ||
75 | #define UARTCR3_T8 0x40 | ||
76 | #define UARTCR3_TXDIR 0x20 | ||
77 | #define UARTCR3_TXINV 0x10 | ||
78 | #define UARTCR3_ORIE 0x08 | ||
79 | #define UARTCR3_NEIE 0x04 | ||
80 | #define UARTCR3_FEIE 0x02 | ||
81 | #define UARTCR3_PEIE 0x01 | ||
82 | |||
83 | #define UARTCR4_MAEN1 0x80 | ||
84 | #define UARTCR4_MAEN2 0x40 | ||
85 | #define UARTCR4_M10 0x20 | ||
86 | #define UARTCR4_BRFA_MASK 0x1f | ||
87 | #define UARTCR4_BRFA_OFF 0 | ||
88 | |||
89 | #define UARTCR5_TDMAS 0x80 | ||
90 | #define UARTCR5_RDMAS 0x20 | ||
91 | |||
92 | #define UARTMODEM_RXRTSE 0x08 | ||
93 | #define UARTMODEM_TXRTSPOL 0x04 | ||
94 | #define UARTMODEM_TXRTSE 0x02 | ||
95 | #define UARTMODEM_TXCTSE 0x01 | ||
96 | |||
97 | #define UARTPFIFO_TXFE 0x80 | ||
98 | #define UARTPFIFO_FIFOSIZE_MASK 0x7 | ||
99 | #define UARTPFIFO_TXSIZE_OFF 4 | ||
100 | #define UARTPFIFO_RXFE 0x08 | ||
101 | #define UARTPFIFO_RXSIZE_OFF 0 | ||
102 | |||
103 | #define UARTCFIFO_TXFLUSH 0x80 | ||
104 | #define UARTCFIFO_RXFLUSH 0x40 | ||
105 | #define UARTCFIFO_RXOFE 0x04 | ||
106 | #define UARTCFIFO_TXOFE 0x02 | ||
107 | #define UARTCFIFO_RXUFE 0x01 | ||
108 | |||
109 | #define UARTSFIFO_TXEMPT 0x80 | ||
110 | #define UARTSFIFO_RXEMPT 0x40 | ||
111 | #define UARTSFIFO_RXOF 0x04 | ||
112 | #define UARTSFIFO_TXOF 0x02 | ||
113 | #define UARTSFIFO_RXUF 0x01 | ||
114 | |||
115 | #define DRIVER_NAME "fsl-lpuart" | ||
116 | #define DEV_NAME "ttyLP" | ||
117 | #define UART_NR 6 | ||
118 | |||
119 | struct lpuart_port { | ||
120 | struct uart_port port; | ||
121 | struct clk *clk; | ||
122 | unsigned int txfifo_size; | ||
123 | unsigned int rxfifo_size; | ||
124 | }; | ||
125 | |||
126 | static struct of_device_id lpuart_dt_ids[] = { | ||
127 | { | ||
128 | .compatible = "fsl,vf610-lpuart", | ||
129 | }, | ||
130 | { /* sentinel */ } | ||
131 | }; | ||
132 | MODULE_DEVICE_TABLE(of, lpuart_dt_ids); | ||
133 | |||
134 | static void lpuart_stop_tx(struct uart_port *port) | ||
135 | { | ||
136 | unsigned char temp; | ||
137 | |||
138 | temp = readb(port->membase + UARTCR2); | ||
139 | temp &= ~(UARTCR2_TIE | UARTCR2_TCIE); | ||
140 | writeb(temp, port->membase + UARTCR2); | ||
141 | } | ||
142 | |||
143 | static void lpuart_stop_rx(struct uart_port *port) | ||
144 | { | ||
145 | unsigned char temp; | ||
146 | |||
147 | temp = readb(port->membase + UARTCR2); | ||
148 | writeb(temp & ~UARTCR2_RE, port->membase + UARTCR2); | ||
149 | } | ||
150 | |||
151 | static void lpuart_enable_ms(struct uart_port *port) | ||
152 | { | ||
153 | } | ||
154 | |||
155 | static inline void lpuart_transmit_buffer(struct lpuart_port *sport) | ||
156 | { | ||
157 | struct circ_buf *xmit = &sport->port.state->xmit; | ||
158 | |||
159 | while (!uart_circ_empty(xmit) && | ||
160 | (readb(sport->port.membase + UARTTCFIFO) < sport->txfifo_size)) { | ||
161 | writeb(xmit->buf[xmit->tail], sport->port.membase + UARTDR); | ||
162 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | ||
163 | sport->port.icount.tx++; | ||
164 | } | ||
165 | |||
166 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | ||
167 | uart_write_wakeup(&sport->port); | ||
168 | |||
169 | if (uart_circ_empty(xmit)) | ||
170 | lpuart_stop_tx(&sport->port); | ||
171 | } | ||
172 | |||
173 | static void lpuart_start_tx(struct uart_port *port) | ||
174 | { | ||
175 | struct lpuart_port *sport = container_of(port, struct lpuart_port, port); | ||
176 | unsigned char temp; | ||
177 | |||
178 | temp = readb(port->membase + UARTCR2); | ||
179 | writeb(temp | UARTCR2_TIE, port->membase + UARTCR2); | ||
180 | |||
181 | if (readb(port->membase + UARTSR1) & UARTSR1_TDRE) | ||
182 | lpuart_transmit_buffer(sport); | ||
183 | } | ||
184 | |||
185 | static irqreturn_t lpuart_txint(int irq, void *dev_id) | ||
186 | { | ||
187 | struct lpuart_port *sport = dev_id; | ||
188 | struct circ_buf *xmit = &sport->port.state->xmit; | ||
189 | unsigned long flags; | ||
190 | |||
191 | spin_lock_irqsave(&sport->port.lock, flags); | ||
192 | if (sport->port.x_char) { | ||
193 | writeb(sport->port.x_char, sport->port.membase + UARTDR); | ||
194 | goto out; | ||
195 | } | ||
196 | |||
197 | if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) { | ||
198 | lpuart_stop_tx(&sport->port); | ||
199 | goto out; | ||
200 | } | ||
201 | |||
202 | lpuart_transmit_buffer(sport); | ||
203 | |||
204 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | ||
205 | uart_write_wakeup(&sport->port); | ||
206 | |||
207 | out: | ||
208 | spin_unlock_irqrestore(&sport->port.lock, flags); | ||
209 | return IRQ_HANDLED; | ||
210 | } | ||
211 | |||
212 | static irqreturn_t lpuart_rxint(int irq, void *dev_id) | ||
213 | { | ||
214 | struct lpuart_port *sport = dev_id; | ||
215 | unsigned int flg, ignored = 0; | ||
216 | struct tty_port *port = &sport->port.state->port; | ||
217 | unsigned long flags; | ||
218 | unsigned char rx, sr; | ||
219 | |||
220 | spin_lock_irqsave(&sport->port.lock, flags); | ||
221 | |||
222 | while (!(readb(sport->port.membase + UARTSFIFO) & UARTSFIFO_RXEMPT)) { | ||
223 | flg = TTY_NORMAL; | ||
224 | sport->port.icount.rx++; | ||
225 | /* | ||
226 | * to clear the FE, OR, NF, FE, PE flags, | ||
227 | * read SR1 then read DR | ||
228 | */ | ||
229 | sr = readb(sport->port.membase + UARTSR1); | ||
230 | rx = readb(sport->port.membase + UARTDR); | ||
231 | |||
232 | if (uart_handle_sysrq_char(&sport->port, (unsigned char)rx)) | ||
233 | continue; | ||
234 | |||
235 | if (sr & (UARTSR1_PE | UARTSR1_OR | UARTSR1_FE)) { | ||
236 | if (sr & UARTSR1_PE) | ||
237 | sport->port.icount.parity++; | ||
238 | else if (sr & UARTSR1_FE) | ||
239 | sport->port.icount.frame++; | ||
240 | |||
241 | if (sr & UARTSR1_OR) | ||
242 | sport->port.icount.overrun++; | ||
243 | |||
244 | if (sr & sport->port.ignore_status_mask) { | ||
245 | if (++ignored > 100) | ||
246 | goto out; | ||
247 | continue; | ||
248 | } | ||
249 | |||
250 | sr &= sport->port.read_status_mask; | ||
251 | |||
252 | if (sr & UARTSR1_PE) | ||
253 | flg = TTY_PARITY; | ||
254 | else if (sr & UARTSR1_FE) | ||
255 | flg = TTY_FRAME; | ||
256 | |||
257 | if (sr & UARTSR1_OR) | ||
258 | flg = TTY_OVERRUN; | ||
259 | |||
260 | #ifdef SUPPORT_SYSRQ | ||
261 | sport->port.sysrq = 0; | ||
262 | #endif | ||
263 | } | ||
264 | |||
265 | tty_insert_flip_char(port, rx, flg); | ||
266 | } | ||
267 | |||
268 | out: | ||
269 | spin_unlock_irqrestore(&sport->port.lock, flags); | ||
270 | |||
271 | tty_flip_buffer_push(port); | ||
272 | return IRQ_HANDLED; | ||
273 | } | ||
274 | |||
275 | static irqreturn_t lpuart_int(int irq, void *dev_id) | ||
276 | { | ||
277 | struct lpuart_port *sport = dev_id; | ||
278 | unsigned char sts; | ||
279 | |||
280 | sts = readb(sport->port.membase + UARTSR1); | ||
281 | |||
282 | if (sts & UARTSR1_RDRF) | ||
283 | lpuart_rxint(irq, dev_id); | ||
284 | |||
285 | if (sts & UARTSR1_TDRE && | ||
286 | !(readb(sport->port.membase + UARTCR5) & UARTCR5_TDMAS)) | ||
287 | lpuart_txint(irq, dev_id); | ||
288 | |||
289 | return IRQ_HANDLED; | ||
290 | } | ||
291 | |||
292 | /* return TIOCSER_TEMT when transmitter is not busy */ | ||
293 | static unsigned int lpuart_tx_empty(struct uart_port *port) | ||
294 | { | ||
295 | return (readb(port->membase + UARTSR1) & UARTSR1_TC) ? | ||
296 | TIOCSER_TEMT : 0; | ||
297 | } | ||
298 | |||
299 | static unsigned int lpuart_get_mctrl(struct uart_port *port) | ||
300 | { | ||
301 | unsigned int temp = 0; | ||
302 | unsigned char reg; | ||
303 | |||
304 | reg = readb(port->membase + UARTMODEM); | ||
305 | if (reg & UARTMODEM_TXCTSE) | ||
306 | temp |= TIOCM_CTS; | ||
307 | |||
308 | if (reg & UARTMODEM_RXRTSE) | ||
309 | temp |= TIOCM_RTS; | ||
310 | |||
311 | return temp; | ||
312 | } | ||
313 | |||
314 | static void lpuart_set_mctrl(struct uart_port *port, unsigned int mctrl) | ||
315 | { | ||
316 | unsigned char temp; | ||
317 | |||
318 | temp = readb(port->membase + UARTMODEM) & | ||
319 | ~(UARTMODEM_RXRTSE | UARTMODEM_TXCTSE); | ||
320 | |||
321 | if (mctrl & TIOCM_RTS) | ||
322 | temp |= UARTMODEM_RXRTSE; | ||
323 | |||
324 | if (mctrl & TIOCM_CTS) | ||
325 | temp |= UARTMODEM_TXCTSE; | ||
326 | |||
327 | writeb(temp, port->membase + UARTMODEM); | ||
328 | } | ||
329 | |||
330 | static void lpuart_break_ctl(struct uart_port *port, int break_state) | ||
331 | { | ||
332 | unsigned char temp; | ||
333 | |||
334 | temp = readb(port->membase + UARTCR2) & ~UARTCR2_SBK; | ||
335 | |||
336 | if (break_state != 0) | ||
337 | temp |= UARTCR2_SBK; | ||
338 | |||
339 | writeb(temp, port->membase + UARTCR2); | ||
340 | } | ||
341 | |||
342 | static void lpuart_setup_watermark(struct lpuart_port *sport) | ||
343 | { | ||
344 | unsigned char val, cr2; | ||
345 | |||
346 | cr2 = readb(sport->port.membase + UARTCR2); | ||
347 | cr2 &= ~(UARTCR2_TIE | UARTCR2_TCIE | UARTCR2_TE | | ||
348 | UARTCR2_RIE | UARTCR2_RE); | ||
349 | writeb(cr2, sport->port.membase + UARTCR2); | ||
350 | |||
351 | /* determine FIFO size and enable FIFO mode */ | ||
352 | val = readb(sport->port.membase + UARTPFIFO); | ||
353 | |||
354 | sport->txfifo_size = 0x1 << (((val >> UARTPFIFO_TXSIZE_OFF) & | ||
355 | UARTPFIFO_FIFOSIZE_MASK) + 1); | ||
356 | |||
357 | sport->rxfifo_size = 0x1 << (((val >> UARTPFIFO_RXSIZE_OFF) & | ||
358 | UARTPFIFO_FIFOSIZE_MASK) + 1); | ||
359 | |||
360 | writeb(val | UARTPFIFO_TXFE | UARTPFIFO_RXFE, | ||
361 | sport->port.membase + UARTPFIFO); | ||
362 | |||
363 | /* flush Tx and Rx FIFO */ | ||
364 | writeb(UARTCFIFO_TXFLUSH | UARTCFIFO_RXFLUSH, | ||
365 | sport->port.membase + UARTCFIFO); | ||
366 | |||
367 | writeb(2, sport->port.membase + UARTTWFIFO); | ||
368 | writeb(1, sport->port.membase + UARTRWFIFO); | ||
369 | } | ||
370 | |||
371 | static int lpuart_startup(struct uart_port *port) | ||
372 | { | ||
373 | struct lpuart_port *sport = container_of(port, struct lpuart_port, port); | ||
374 | int ret; | ||
375 | unsigned long flags; | ||
376 | unsigned char temp; | ||
377 | |||
378 | ret = devm_request_irq(port->dev, port->irq, lpuart_int, 0, | ||
379 | DRIVER_NAME, sport); | ||
380 | if (ret) | ||
381 | return ret; | ||
382 | |||
383 | spin_lock_irqsave(&sport->port.lock, flags); | ||
384 | |||
385 | lpuart_setup_watermark(sport); | ||
386 | |||
387 | temp = readb(sport->port.membase + UARTCR2); | ||
388 | temp |= (UARTCR2_RIE | UARTCR2_TIE | UARTCR2_RE | UARTCR2_TE); | ||
389 | writeb(temp, sport->port.membase + UARTCR2); | ||
390 | |||
391 | spin_unlock_irqrestore(&sport->port.lock, flags); | ||
392 | return 0; | ||
393 | } | ||
394 | |||
395 | static void lpuart_shutdown(struct uart_port *port) | ||
396 | { | ||
397 | struct lpuart_port *sport = container_of(port, struct lpuart_port, port); | ||
398 | unsigned char temp; | ||
399 | unsigned long flags; | ||
400 | |||
401 | spin_lock_irqsave(&port->lock, flags); | ||
402 | |||
403 | /* disable Rx/Tx and interrupts */ | ||
404 | temp = readb(port->membase + UARTCR2); | ||
405 | temp &= ~(UARTCR2_TE | UARTCR2_RE | | ||
406 | UARTCR2_TIE | UARTCR2_TCIE | UARTCR2_RIE); | ||
407 | writeb(temp, port->membase + UARTCR2); | ||
408 | |||
409 | spin_unlock_irqrestore(&port->lock, flags); | ||
410 | |||
411 | devm_free_irq(port->dev, port->irq, sport); | ||
412 | } | ||
413 | |||
414 | static void | ||
415 | lpuart_set_termios(struct uart_port *port, struct ktermios *termios, | ||
416 | struct ktermios *old) | ||
417 | { | ||
418 | struct lpuart_port *sport = container_of(port, struct lpuart_port, port); | ||
419 | unsigned long flags; | ||
420 | unsigned char cr1, old_cr1, old_cr2, cr4, bdh, modem; | ||
421 | unsigned int baud; | ||
422 | unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8; | ||
423 | unsigned int sbr, brfa; | ||
424 | |||
425 | cr1 = old_cr1 = readb(sport->port.membase + UARTCR1); | ||
426 | old_cr2 = readb(sport->port.membase + UARTCR2); | ||
427 | cr4 = readb(sport->port.membase + UARTCR4); | ||
428 | bdh = readb(sport->port.membase + UARTBDH); | ||
429 | modem = readb(sport->port.membase + UARTMODEM); | ||
430 | /* | ||
431 | * only support CS8 and CS7, and for CS7 must enable PE. | ||
432 | * supported mode: | ||
433 | * - (7,e/o,1) | ||
434 | * - (8,n,1) | ||
435 | * - (8,m/s,1) | ||
436 | * - (8,e/o,1) | ||
437 | */ | ||
438 | while ((termios->c_cflag & CSIZE) != CS8 && | ||
439 | (termios->c_cflag & CSIZE) != CS7) { | ||
440 | termios->c_cflag &= ~CSIZE; | ||
441 | termios->c_cflag |= old_csize; | ||
442 | old_csize = CS8; | ||
443 | } | ||
444 | |||
445 | if ((termios->c_cflag & CSIZE) == CS8 || | ||
446 | (termios->c_cflag & CSIZE) == CS7) | ||
447 | cr1 = old_cr1 & ~UARTCR1_M; | ||
448 | |||
449 | if (termios->c_cflag & CMSPAR) { | ||
450 | if ((termios->c_cflag & CSIZE) != CS8) { | ||
451 | termios->c_cflag &= ~CSIZE; | ||
452 | termios->c_cflag |= CS8; | ||
453 | } | ||
454 | cr1 |= UARTCR1_M; | ||
455 | } | ||
456 | |||
457 | if (termios->c_cflag & CRTSCTS) { | ||
458 | modem |= (UARTMODEM_RXRTSE | UARTMODEM_TXCTSE); | ||
459 | } else { | ||
460 | termios->c_cflag &= ~CRTSCTS; | ||
461 | modem &= ~(UARTMODEM_RXRTSE | UARTMODEM_TXCTSE); | ||
462 | } | ||
463 | |||
464 | if (termios->c_cflag & CSTOPB) | ||
465 | termios->c_cflag &= ~CSTOPB; | ||
466 | |||
467 | /* parity must be enabled when CS7 to match 8-bits format */ | ||
468 | if ((termios->c_cflag & CSIZE) == CS7) | ||
469 | termios->c_cflag |= PARENB; | ||
470 | |||
471 | if ((termios->c_cflag & PARENB)) { | ||
472 | if (termios->c_cflag & CMSPAR) { | ||
473 | cr1 &= ~UARTCR1_PE; | ||
474 | cr1 |= UARTCR1_M; | ||
475 | } else { | ||
476 | cr1 |= UARTCR1_PE; | ||
477 | if ((termios->c_cflag & CSIZE) == CS8) | ||
478 | cr1 |= UARTCR1_M; | ||
479 | if (termios->c_cflag & PARODD) | ||
480 | cr1 |= UARTCR1_PT; | ||
481 | else | ||
482 | cr1 &= ~UARTCR1_PT; | ||
483 | } | ||
484 | } | ||
485 | |||
486 | /* ask the core to calculate the divisor */ | ||
487 | baud = uart_get_baud_rate(port, termios, old, 50, port->uartclk / 16); | ||
488 | |||
489 | spin_lock_irqsave(&sport->port.lock, flags); | ||
490 | |||
491 | sport->port.read_status_mask = 0; | ||
492 | if (termios->c_iflag & INPCK) | ||
493 | sport->port.read_status_mask |= (UARTSR1_FE | UARTSR1_PE); | ||
494 | if (termios->c_iflag & (BRKINT | PARMRK)) | ||
495 | sport->port.read_status_mask |= UARTSR1_FE; | ||
496 | |||
497 | /* characters to ignore */ | ||
498 | sport->port.ignore_status_mask = 0; | ||
499 | if (termios->c_iflag & IGNPAR) | ||
500 | sport->port.ignore_status_mask |= UARTSR1_PE; | ||
501 | if (termios->c_iflag & IGNBRK) { | ||
502 | sport->port.ignore_status_mask |= UARTSR1_FE; | ||
503 | /* | ||
504 | * if we're ignoring parity and break indicators, | ||
505 | * ignore overruns too (for real raw support). | ||
506 | */ | ||
507 | if (termios->c_iflag & IGNPAR) | ||
508 | sport->port.ignore_status_mask |= UARTSR1_OR; | ||
509 | } | ||
510 | |||
511 | /* update the per-port timeout */ | ||
512 | uart_update_timeout(port, termios->c_cflag, baud); | ||
513 | |||
514 | /* wait transmit engin complete */ | ||
515 | while (!(readb(sport->port.membase + UARTSR1) & UARTSR1_TC)) | ||
516 | barrier(); | ||
517 | |||
518 | /* disable transmit and receive */ | ||
519 | writeb(old_cr2 & ~(UARTCR2_TE | UARTCR2_RE), | ||
520 | sport->port.membase + UARTCR2); | ||
521 | |||
522 | sbr = sport->port.uartclk / (16 * baud); | ||
523 | brfa = ((sport->port.uartclk - (16 * sbr * baud)) * 2) / baud; | ||
524 | bdh &= ~UARTBDH_SBR_MASK; | ||
525 | bdh |= (sbr >> 8) & 0x1F; | ||
526 | cr4 &= ~UARTCR4_BRFA_MASK; | ||
527 | brfa &= UARTCR4_BRFA_MASK; | ||
528 | writeb(cr4 | brfa, sport->port.membase + UARTCR4); | ||
529 | writeb(bdh, sport->port.membase + UARTBDH); | ||
530 | writeb(sbr & 0xFF, sport->port.membase + UARTBDL); | ||
531 | writeb(cr1, sport->port.membase + UARTCR1); | ||
532 | writeb(modem, sport->port.membase + UARTMODEM); | ||
533 | |||
534 | /* restore control register */ | ||
535 | writeb(old_cr2, sport->port.membase + UARTCR2); | ||
536 | |||
537 | spin_unlock_irqrestore(&sport->port.lock, flags); | ||
538 | } | ||
539 | |||
540 | static const char *lpuart_type(struct uart_port *port) | ||
541 | { | ||
542 | return "FSL_LPUART"; | ||
543 | } | ||
544 | |||
545 | static void lpuart_release_port(struct uart_port *port) | ||
546 | { | ||
547 | /* nothing to do */ | ||
548 | } | ||
549 | |||
550 | static int lpuart_request_port(struct uart_port *port) | ||
551 | { | ||
552 | return 0; | ||
553 | } | ||
554 | |||
555 | /* configure/autoconfigure the port */ | ||
556 | static void lpuart_config_port(struct uart_port *port, int flags) | ||
557 | { | ||
558 | if (flags & UART_CONFIG_TYPE) | ||
559 | port->type = PORT_LPUART; | ||
560 | } | ||
561 | |||
562 | static int lpuart_verify_port(struct uart_port *port, struct serial_struct *ser) | ||
563 | { | ||
564 | int ret = 0; | ||
565 | |||
566 | if (ser->type != PORT_UNKNOWN && ser->type != PORT_LPUART) | ||
567 | ret = -EINVAL; | ||
568 | if (port->irq != ser->irq) | ||
569 | ret = -EINVAL; | ||
570 | if (ser->io_type != UPIO_MEM) | ||
571 | ret = -EINVAL; | ||
572 | if (port->uartclk / 16 != ser->baud_base) | ||
573 | ret = -EINVAL; | ||
574 | if (port->iobase != ser->port) | ||
575 | ret = -EINVAL; | ||
576 | if (ser->hub6 != 0) | ||
577 | ret = -EINVAL; | ||
578 | return ret; | ||
579 | } | ||
580 | |||
581 | static struct uart_ops lpuart_pops = { | ||
582 | .tx_empty = lpuart_tx_empty, | ||
583 | .set_mctrl = lpuart_set_mctrl, | ||
584 | .get_mctrl = lpuart_get_mctrl, | ||
585 | .stop_tx = lpuart_stop_tx, | ||
586 | .start_tx = lpuart_start_tx, | ||
587 | .stop_rx = lpuart_stop_rx, | ||
588 | .enable_ms = lpuart_enable_ms, | ||
589 | .break_ctl = lpuart_break_ctl, | ||
590 | .startup = lpuart_startup, | ||
591 | .shutdown = lpuart_shutdown, | ||
592 | .set_termios = lpuart_set_termios, | ||
593 | .type = lpuart_type, | ||
594 | .request_port = lpuart_request_port, | ||
595 | .release_port = lpuart_release_port, | ||
596 | .config_port = lpuart_config_port, | ||
597 | .verify_port = lpuart_verify_port, | ||
598 | }; | ||
599 | |||
600 | static struct lpuart_port *lpuart_ports[UART_NR]; | ||
601 | |||
602 | #ifdef CONFIG_SERIAL_FSL_LPUART_CONSOLE | ||
603 | static void lpuart_console_putchar(struct uart_port *port, int ch) | ||
604 | { | ||
605 | while (!(readb(port->membase + UARTSR1) & UARTSR1_TDRE)) | ||
606 | barrier(); | ||
607 | |||
608 | writeb(ch, port->membase + UARTDR); | ||
609 | } | ||
610 | |||
611 | static void | ||
612 | lpuart_console_write(struct console *co, const char *s, unsigned int count) | ||
613 | { | ||
614 | struct lpuart_port *sport = lpuart_ports[co->index]; | ||
615 | unsigned char old_cr2, cr2; | ||
616 | |||
617 | /* first save CR2 and then disable interrupts */ | ||
618 | cr2 = old_cr2 = readb(sport->port.membase + UARTCR2); | ||
619 | cr2 |= (UARTCR2_TE | UARTCR2_RE); | ||
620 | cr2 &= ~(UARTCR2_TIE | UARTCR2_TCIE | UARTCR2_RIE); | ||
621 | writeb(cr2, sport->port.membase + UARTCR2); | ||
622 | |||
623 | uart_console_write(&sport->port, s, count, lpuart_console_putchar); | ||
624 | |||
625 | /* wait for transmitter finish complete and restore CR2 */ | ||
626 | while (!(readb(sport->port.membase + UARTSR1) & UARTSR1_TC)) | ||
627 | barrier(); | ||
628 | |||
629 | writeb(old_cr2, sport->port.membase + UARTCR2); | ||
630 | } | ||
631 | |||
632 | /* | ||
633 | * if the port was already initialised (eg, by a boot loader), | ||
634 | * try to determine the current setup. | ||
635 | */ | ||
636 | static void __init | ||
637 | lpuart_console_get_options(struct lpuart_port *sport, int *baud, | ||
638 | int *parity, int *bits) | ||
639 | { | ||
640 | unsigned char cr, bdh, bdl, brfa; | ||
641 | unsigned int sbr, uartclk, baud_raw; | ||
642 | |||
643 | cr = readb(sport->port.membase + UARTCR2); | ||
644 | cr &= UARTCR2_TE | UARTCR2_RE; | ||
645 | if (!cr) | ||
646 | return; | ||
647 | |||
648 | /* ok, the port was enabled */ | ||
649 | |||
650 | cr = readb(sport->port.membase + UARTCR1); | ||
651 | |||
652 | *parity = 'n'; | ||
653 | if (cr & UARTCR1_PE) { | ||
654 | if (cr & UARTCR1_PT) | ||
655 | *parity = 'o'; | ||
656 | else | ||
657 | *parity = 'e'; | ||
658 | } | ||
659 | |||
660 | if (cr & UARTCR1_M) | ||
661 | *bits = 9; | ||
662 | else | ||
663 | *bits = 8; | ||
664 | |||
665 | bdh = readb(sport->port.membase + UARTBDH); | ||
666 | bdh &= UARTBDH_SBR_MASK; | ||
667 | bdl = readb(sport->port.membase + UARTBDL); | ||
668 | sbr = bdh; | ||
669 | sbr <<= 8; | ||
670 | sbr |= bdl; | ||
671 | brfa = readb(sport->port.membase + UARTCR4); | ||
672 | brfa &= UARTCR4_BRFA_MASK; | ||
673 | |||
674 | uartclk = clk_get_rate(sport->clk); | ||
675 | /* | ||
676 | * baud = mod_clk/(16*(sbr[13]+(brfa)/32) | ||
677 | */ | ||
678 | baud_raw = uartclk / (16 * (sbr + brfa / 32)); | ||
679 | |||
680 | if (*baud != baud_raw) | ||
681 | printk(KERN_INFO "Serial: Console lpuart rounded baud rate" | ||
682 | "from %d to %d\n", baud_raw, *baud); | ||
683 | } | ||
684 | |||
685 | static int __init lpuart_console_setup(struct console *co, char *options) | ||
686 | { | ||
687 | struct lpuart_port *sport; | ||
688 | int baud = 115200; | ||
689 | int bits = 8; | ||
690 | int parity = 'n'; | ||
691 | int flow = 'n'; | ||
692 | |||
693 | /* | ||
694 | * check whether an invalid uart number has been specified, and | ||
695 | * if so, search for the first available port that does have | ||
696 | * console support. | ||
697 | */ | ||
698 | if (co->index == -1 || co->index >= ARRAY_SIZE(lpuart_ports)) | ||
699 | co->index = 0; | ||
700 | |||
701 | sport = lpuart_ports[co->index]; | ||
702 | if (sport == NULL) | ||
703 | return -ENODEV; | ||
704 | |||
705 | if (options) | ||
706 | uart_parse_options(options, &baud, &parity, &bits, &flow); | ||
707 | else | ||
708 | lpuart_console_get_options(sport, &baud, &parity, &bits); | ||
709 | |||
710 | lpuart_setup_watermark(sport); | ||
711 | |||
712 | return uart_set_options(&sport->port, co, baud, parity, bits, flow); | ||
713 | } | ||
714 | |||
715 | static struct uart_driver lpuart_reg; | ||
716 | static struct console lpuart_console = { | ||
717 | .name = DEV_NAME, | ||
718 | .write = lpuart_console_write, | ||
719 | .device = uart_console_device, | ||
720 | .setup = lpuart_console_setup, | ||
721 | .flags = CON_PRINTBUFFER, | ||
722 | .index = -1, | ||
723 | .data = &lpuart_reg, | ||
724 | }; | ||
725 | |||
726 | #define LPUART_CONSOLE (&lpuart_console) | ||
727 | #else | ||
728 | #define LPUART_CONSOLE NULL | ||
729 | #endif | ||
730 | |||
731 | static struct uart_driver lpuart_reg = { | ||
732 | .owner = THIS_MODULE, | ||
733 | .driver_name = DRIVER_NAME, | ||
734 | .dev_name = DEV_NAME, | ||
735 | .nr = ARRAY_SIZE(lpuart_ports), | ||
736 | .cons = LPUART_CONSOLE, | ||
737 | }; | ||
738 | |||
739 | static int lpuart_probe(struct platform_device *pdev) | ||
740 | { | ||
741 | struct device_node *np = pdev->dev.of_node; | ||
742 | struct lpuart_port *sport; | ||
743 | struct resource *res; | ||
744 | int ret; | ||
745 | |||
746 | sport = devm_kzalloc(&pdev->dev, sizeof(*sport), GFP_KERNEL); | ||
747 | if (!sport) | ||
748 | return -ENOMEM; | ||
749 | |||
750 | pdev->dev.coherent_dma_mask = 0; | ||
751 | |||
752 | ret = of_alias_get_id(np, "serial"); | ||
753 | if (ret < 0) { | ||
754 | dev_err(&pdev->dev, "failed to get alias id, errno %d\n", ret); | ||
755 | return ret; | ||
756 | } | ||
757 | sport->port.line = ret; | ||
758 | |||
759 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
760 | if (!res) | ||
761 | return -ENODEV; | ||
762 | |||
763 | sport->port.mapbase = res->start; | ||
764 | sport->port.membase = devm_ioremap_resource(&pdev->dev, res); | ||
765 | if (IS_ERR(sport->port.membase)) | ||
766 | return PTR_ERR(sport->port.membase); | ||
767 | |||
768 | sport->port.dev = &pdev->dev; | ||
769 | sport->port.type = PORT_LPUART; | ||
770 | sport->port.iotype = UPIO_MEM; | ||
771 | sport->port.irq = platform_get_irq(pdev, 0); | ||
772 | sport->port.ops = &lpuart_pops; | ||
773 | sport->port.flags = UPF_BOOT_AUTOCONF; | ||
774 | |||
775 | sport->clk = devm_clk_get(&pdev->dev, "ipg"); | ||
776 | if (IS_ERR(sport->clk)) { | ||
777 | ret = PTR_ERR(sport->clk); | ||
778 | dev_err(&pdev->dev, "failed to get uart clk: %d\n", ret); | ||
779 | return ret; | ||
780 | } | ||
781 | |||
782 | ret = clk_prepare_enable(sport->clk); | ||
783 | if (ret) { | ||
784 | dev_err(&pdev->dev, "failed to enable uart clk: %d\n", ret); | ||
785 | return ret; | ||
786 | } | ||
787 | |||
788 | sport->port.uartclk = clk_get_rate(sport->clk); | ||
789 | |||
790 | lpuart_ports[sport->port.line] = sport; | ||
791 | |||
792 | platform_set_drvdata(pdev, &sport->port); | ||
793 | |||
794 | ret = uart_add_one_port(&lpuart_reg, &sport->port); | ||
795 | if (ret) { | ||
796 | clk_disable_unprepare(sport->clk); | ||
797 | return ret; | ||
798 | } | ||
799 | |||
800 | return 0; | ||
801 | } | ||
802 | |||
803 | static int lpuart_remove(struct platform_device *pdev) | ||
804 | { | ||
805 | struct lpuart_port *sport = platform_get_drvdata(pdev); | ||
806 | |||
807 | uart_remove_one_port(&lpuart_reg, &sport->port); | ||
808 | |||
809 | clk_disable_unprepare(sport->clk); | ||
810 | |||
811 | return 0; | ||
812 | } | ||
813 | |||
814 | #ifdef CONFIG_PM_SLEEP | ||
815 | static int lpuart_suspend(struct device *dev) | ||
816 | { | ||
817 | struct lpuart_port *sport = dev_get_drvdata(dev); | ||
818 | |||
819 | uart_suspend_port(&lpuart_reg, &sport->port); | ||
820 | |||
821 | return 0; | ||
822 | } | ||
823 | |||
824 | static int lpuart_resume(struct device *dev) | ||
825 | { | ||
826 | struct lpuart_port *sport = dev_get_drvdata(dev); | ||
827 | |||
828 | uart_resume_port(&lpuart_reg, &sport->port); | ||
829 | |||
830 | return 0; | ||
831 | } | ||
832 | #endif | ||
833 | |||
834 | static SIMPLE_DEV_PM_OPS(lpuart_pm_ops, lpuart_suspend, lpuart_resume); | ||
835 | |||
836 | static struct platform_driver lpuart_driver = { | ||
837 | .probe = lpuart_probe, | ||
838 | .remove = lpuart_remove, | ||
839 | .driver = { | ||
840 | .name = "fsl-lpuart", | ||
841 | .owner = THIS_MODULE, | ||
842 | .of_match_table = lpuart_dt_ids, | ||
843 | .pm = &lpuart_pm_ops, | ||
844 | }, | ||
845 | }; | ||
846 | |||
847 | static int __init lpuart_serial_init(void) | ||
848 | { | ||
849 | int ret; | ||
850 | |||
851 | pr_info("serial: Freescale lpuart driver\n"); | ||
852 | |||
853 | ret = uart_register_driver(&lpuart_reg); | ||
854 | if (ret) | ||
855 | return ret; | ||
856 | |||
857 | ret = platform_driver_register(&lpuart_driver); | ||
858 | if (ret) | ||
859 | uart_unregister_driver(&lpuart_reg); | ||
860 | |||
861 | return 0; | ||
862 | } | ||
863 | |||
864 | static void __exit lpuart_serial_exit(void) | ||
865 | { | ||
866 | platform_driver_unregister(&lpuart_driver); | ||
867 | uart_unregister_driver(&lpuart_reg); | ||
868 | } | ||
869 | |||
870 | module_init(lpuart_serial_init); | ||
871 | module_exit(lpuart_serial_exit); | ||
872 | |||
873 | MODULE_DESCRIPTION("Freescale lpuart serial port driver"); | ||
874 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 8cdfbd365892..415cec62073f 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c | |||
@@ -201,6 +201,7 @@ struct imx_port { | |||
201 | unsigned int old_status; | 201 | unsigned int old_status; |
202 | int txirq, rxirq, rtsirq; | 202 | int txirq, rxirq, rtsirq; |
203 | unsigned int have_rtscts:1; | 203 | unsigned int have_rtscts:1; |
204 | unsigned int dte_mode:1; | ||
204 | unsigned int use_irda:1; | 205 | unsigned int use_irda:1; |
205 | unsigned int irda_inv_rx:1; | 206 | unsigned int irda_inv_rx:1; |
206 | unsigned int irda_inv_tx:1; | 207 | unsigned int irda_inv_tx:1; |
@@ -271,6 +272,7 @@ static inline int is_imx21_uart(struct imx_port *sport) | |||
271 | /* | 272 | /* |
272 | * Save and restore functions for UCR1, UCR2 and UCR3 registers | 273 | * Save and restore functions for UCR1, UCR2 and UCR3 registers |
273 | */ | 274 | */ |
275 | #if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_IMX_CONSOLE) | ||
274 | static void imx_port_ucrs_save(struct uart_port *port, | 276 | static void imx_port_ucrs_save(struct uart_port *port, |
275 | struct imx_port_ucrs *ucr) | 277 | struct imx_port_ucrs *ucr) |
276 | { | 278 | { |
@@ -288,6 +290,7 @@ static void imx_port_ucrs_restore(struct uart_port *port, | |||
288 | writel(ucr->ucr2, port->membase + UCR2); | 290 | writel(ucr->ucr2, port->membase + UCR2); |
289 | writel(ucr->ucr3, port->membase + UCR3); | 291 | writel(ucr->ucr3, port->membase + UCR3); |
290 | } | 292 | } |
293 | #endif | ||
291 | 294 | ||
292 | /* | 295 | /* |
293 | * Handle any change of modem status signal since we were last called. | 296 | * Handle any change of modem status signal since we were last called. |
@@ -449,6 +452,13 @@ static void imx_start_tx(struct uart_port *port) | |||
449 | temp &= ~(UCR1_RRDYEN); | 452 | temp &= ~(UCR1_RRDYEN); |
450 | writel(temp, sport->port.membase + UCR1); | 453 | writel(temp, sport->port.membase + UCR1); |
451 | } | 454 | } |
455 | /* Clear any pending ORE flag before enabling interrupt */ | ||
456 | temp = readl(sport->port.membase + USR2); | ||
457 | writel(temp | USR2_ORE, sport->port.membase + USR2); | ||
458 | |||
459 | temp = readl(sport->port.membase + UCR4); | ||
460 | temp |= UCR4_OREN; | ||
461 | writel(temp, sport->port.membase + UCR4); | ||
452 | 462 | ||
453 | temp = readl(sport->port.membase + UCR1); | 463 | temp = readl(sport->port.membase + UCR1); |
454 | writel(temp | UCR1_TXMPTYEN, sport->port.membase + UCR1); | 464 | writel(temp | UCR1_TXMPTYEN, sport->port.membase + UCR1); |
@@ -582,6 +592,7 @@ static irqreturn_t imx_int(int irq, void *dev_id) | |||
582 | { | 592 | { |
583 | struct imx_port *sport = dev_id; | 593 | struct imx_port *sport = dev_id; |
584 | unsigned int sts; | 594 | unsigned int sts; |
595 | unsigned int sts2; | ||
585 | 596 | ||
586 | sts = readl(sport->port.membase + USR1); | 597 | sts = readl(sport->port.membase + USR1); |
587 | 598 | ||
@@ -598,6 +609,13 @@ static irqreturn_t imx_int(int irq, void *dev_id) | |||
598 | if (sts & USR1_AWAKE) | 609 | if (sts & USR1_AWAKE) |
599 | writel(USR1_AWAKE, sport->port.membase + USR1); | 610 | writel(USR1_AWAKE, sport->port.membase + USR1); |
600 | 611 | ||
612 | sts2 = readl(sport->port.membase + USR2); | ||
613 | if (sts2 & USR2_ORE) { | ||
614 | dev_err(sport->port.dev, "Rx FIFO overrun\n"); | ||
615 | sport->port.icount.overrun++; | ||
616 | writel(sts2 | USR2_ORE, sport->port.membase + USR2); | ||
617 | } | ||
618 | |||
601 | return IRQ_HANDLED; | 619 | return IRQ_HANDLED; |
602 | } | 620 | } |
603 | 621 | ||
@@ -684,6 +702,17 @@ static int imx_startup(struct uart_port *port) | |||
684 | int retval; | 702 | int retval; |
685 | unsigned long flags, temp; | 703 | unsigned long flags, temp; |
686 | 704 | ||
705 | if (!uart_console(port)) { | ||
706 | retval = clk_prepare_enable(sport->clk_per); | ||
707 | if (retval) | ||
708 | goto error_out1; | ||
709 | retval = clk_prepare_enable(sport->clk_ipg); | ||
710 | if (retval) { | ||
711 | clk_disable_unprepare(sport->clk_per); | ||
712 | goto error_out1; | ||
713 | } | ||
714 | } | ||
715 | |||
687 | imx_setup_ufcr(sport, 0); | 716 | imx_setup_ufcr(sport, 0); |
688 | 717 | ||
689 | /* disable the DREN bit (Data Ready interrupt enable) before | 718 | /* disable the DREN bit (Data Ready interrupt enable) before |
@@ -871,6 +900,11 @@ static void imx_shutdown(struct uart_port *port) | |||
871 | 900 | ||
872 | writel(temp, sport->port.membase + UCR1); | 901 | writel(temp, sport->port.membase + UCR1); |
873 | spin_unlock_irqrestore(&sport->port.lock, flags); | 902 | spin_unlock_irqrestore(&sport->port.lock, flags); |
903 | |||
904 | if (!uart_console(&sport->port)) { | ||
905 | clk_disable_unprepare(sport->clk_per); | ||
906 | clk_disable_unprepare(sport->clk_ipg); | ||
907 | } | ||
874 | } | 908 | } |
875 | 909 | ||
876 | static void | 910 | static void |
@@ -1007,6 +1041,8 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios, | |||
1007 | 1041 | ||
1008 | ufcr = readl(sport->port.membase + UFCR); | 1042 | ufcr = readl(sport->port.membase + UFCR); |
1009 | ufcr = (ufcr & (~UFCR_RFDIV)) | UFCR_RFDIV_REG(div); | 1043 | ufcr = (ufcr & (~UFCR_RFDIV)) | UFCR_RFDIV_REG(div); |
1044 | if (sport->dte_mode) | ||
1045 | ufcr |= UFCR_DCEDTE; | ||
1010 | writel(ufcr, sport->port.membase + UFCR); | 1046 | writel(ufcr, sport->port.membase + UFCR); |
1011 | 1047 | ||
1012 | writel(num, sport->port.membase + UBIR); | 1048 | writel(num, sport->port.membase + UBIR); |
@@ -1431,6 +1467,9 @@ static int serial_imx_probe_dt(struct imx_port *sport, | |||
1431 | if (of_get_property(np, "fsl,irda-mode", NULL)) | 1467 | if (of_get_property(np, "fsl,irda-mode", NULL)) |
1432 | sport->use_irda = 1; | 1468 | sport->use_irda = 1; |
1433 | 1469 | ||
1470 | if (of_get_property(np, "fsl,dte-mode", NULL)) | ||
1471 | sport->dte_mode = 1; | ||
1472 | |||
1434 | sport->devdata = of_id->data; | 1473 | sport->devdata = of_id->data; |
1435 | 1474 | ||
1436 | return 0; | 1475 | return 0; |
@@ -1544,6 +1583,11 @@ static int serial_imx_probe(struct platform_device *pdev) | |||
1544 | goto deinit; | 1583 | goto deinit; |
1545 | platform_set_drvdata(pdev, sport); | 1584 | platform_set_drvdata(pdev, sport); |
1546 | 1585 | ||
1586 | if (!uart_console(&sport->port)) { | ||
1587 | clk_disable_unprepare(sport->clk_per); | ||
1588 | clk_disable_unprepare(sport->clk_ipg); | ||
1589 | } | ||
1590 | |||
1547 | return 0; | 1591 | return 0; |
1548 | deinit: | 1592 | deinit: |
1549 | if (pdata && pdata->exit) | 1593 | if (pdata && pdata->exit) |
@@ -1565,9 +1609,6 @@ static int serial_imx_remove(struct platform_device *pdev) | |||
1565 | 1609 | ||
1566 | uart_remove_one_port(&imx_reg, &sport->port); | 1610 | uart_remove_one_port(&imx_reg, &sport->port); |
1567 | 1611 | ||
1568 | clk_disable_unprepare(sport->clk_per); | ||
1569 | clk_disable_unprepare(sport->clk_ipg); | ||
1570 | |||
1571 | if (pdata && pdata->exit) | 1612 | if (pdata && pdata->exit) |
1572 | pdata->exit(pdev); | 1613 | pdata->exit(pdev); |
1573 | 1614 | ||
diff --git a/drivers/tty/serial/mfd.c b/drivers/tty/serial/mfd.c index 5f4765a7a5c5..e266eca0ec76 100644 --- a/drivers/tty/serial/mfd.c +++ b/drivers/tty/serial/mfd.c | |||
@@ -21,6 +21,10 @@ | |||
21 | * be triggered | 21 | * be triggered |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #if defined(CONFIG_SERIAL_MFD_HSU_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) | ||
25 | #define SUPPORT_SYSRQ | ||
26 | #endif | ||
27 | |||
24 | #include <linux/module.h> | 28 | #include <linux/module.h> |
25 | #include <linux/init.h> | 29 | #include <linux/init.h> |
26 | #include <linux/console.h> | 30 | #include <linux/console.h> |
diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c index f51b280f3bf2..e1280a20b7a2 100644 --- a/drivers/tty/serial/mpc52xx_uart.c +++ b/drivers/tty/serial/mpc52xx_uart.c | |||
@@ -84,16 +84,6 @@ static void mpc52xx_uart_of_enumerate(void); | |||
84 | static irqreturn_t mpc52xx_uart_int(int irq, void *dev_id); | 84 | static irqreturn_t mpc52xx_uart_int(int irq, void *dev_id); |
85 | static irqreturn_t mpc5xxx_uart_process_int(struct uart_port *port); | 85 | static irqreturn_t mpc5xxx_uart_process_int(struct uart_port *port); |
86 | 86 | ||
87 | |||
88 | /* Simple macro to test if a port is console or not. This one is taken | ||
89 | * for serial_core.c and maybe should be moved to serial_core.h ? */ | ||
90 | #ifdef CONFIG_SERIAL_CORE_CONSOLE | ||
91 | #define uart_console(port) \ | ||
92 | ((port)->cons && (port)->cons->index == (port)->line) | ||
93 | #else | ||
94 | #define uart_console(port) (0) | ||
95 | #endif | ||
96 | |||
97 | /* ======================================================================== */ | 87 | /* ======================================================================== */ |
98 | /* PSC fifo operations for isolating differences between 52xx and 512x */ | 88 | /* PSC fifo operations for isolating differences between 52xx and 512x */ |
99 | /* ======================================================================== */ | 89 | /* ======================================================================== */ |
@@ -122,6 +112,15 @@ struct psc_ops { | |||
122 | void (*fifoc_uninit)(void); | 112 | void (*fifoc_uninit)(void); |
123 | void (*get_irq)(struct uart_port *, struct device_node *); | 113 | void (*get_irq)(struct uart_port *, struct device_node *); |
124 | irqreturn_t (*handle_irq)(struct uart_port *port); | 114 | irqreturn_t (*handle_irq)(struct uart_port *port); |
115 | u16 (*get_status)(struct uart_port *port); | ||
116 | u8 (*get_ipcr)(struct uart_port *port); | ||
117 | void (*command)(struct uart_port *port, u8 cmd); | ||
118 | void (*set_mode)(struct uart_port *port, u8 mr1, u8 mr2); | ||
119 | void (*set_rts)(struct uart_port *port, int state); | ||
120 | void (*enable_ms)(struct uart_port *port); | ||
121 | void (*set_sicr)(struct uart_port *port, u32 val); | ||
122 | void (*set_imr)(struct uart_port *port, u16 val); | ||
123 | u8 (*get_mr1)(struct uart_port *port); | ||
125 | }; | 124 | }; |
126 | 125 | ||
127 | /* setting the prescaler and divisor reg is common for all chips */ | 126 | /* setting the prescaler and divisor reg is common for all chips */ |
@@ -134,6 +133,65 @@ static inline void mpc52xx_set_divisor(struct mpc52xx_psc __iomem *psc, | |||
134 | out_8(&psc->ctlr, divisor & 0xff); | 133 | out_8(&psc->ctlr, divisor & 0xff); |
135 | } | 134 | } |
136 | 135 | ||
136 | static u16 mpc52xx_psc_get_status(struct uart_port *port) | ||
137 | { | ||
138 | return in_be16(&PSC(port)->mpc52xx_psc_status); | ||
139 | } | ||
140 | |||
141 | static u8 mpc52xx_psc_get_ipcr(struct uart_port *port) | ||
142 | { | ||
143 | return in_8(&PSC(port)->mpc52xx_psc_ipcr); | ||
144 | } | ||
145 | |||
146 | static void mpc52xx_psc_command(struct uart_port *port, u8 cmd) | ||
147 | { | ||
148 | out_8(&PSC(port)->command, cmd); | ||
149 | } | ||
150 | |||
151 | static void mpc52xx_psc_set_mode(struct uart_port *port, u8 mr1, u8 mr2) | ||
152 | { | ||
153 | out_8(&PSC(port)->command, MPC52xx_PSC_SEL_MODE_REG_1); | ||
154 | out_8(&PSC(port)->mode, mr1); | ||
155 | out_8(&PSC(port)->mode, mr2); | ||
156 | } | ||
157 | |||
158 | static void mpc52xx_psc_set_rts(struct uart_port *port, int state) | ||
159 | { | ||
160 | if (state) | ||
161 | out_8(&PSC(port)->op1, MPC52xx_PSC_OP_RTS); | ||
162 | else | ||
163 | out_8(&PSC(port)->op0, MPC52xx_PSC_OP_RTS); | ||
164 | } | ||
165 | |||
166 | static void mpc52xx_psc_enable_ms(struct uart_port *port) | ||
167 | { | ||
168 | struct mpc52xx_psc __iomem *psc = PSC(port); | ||
169 | |||
170 | /* clear D_*-bits by reading them */ | ||
171 | in_8(&psc->mpc52xx_psc_ipcr); | ||
172 | /* enable CTS and DCD as IPC interrupts */ | ||
173 | out_8(&psc->mpc52xx_psc_acr, MPC52xx_PSC_IEC_CTS | MPC52xx_PSC_IEC_DCD); | ||
174 | |||
175 | port->read_status_mask |= MPC52xx_PSC_IMR_IPC; | ||
176 | out_be16(&psc->mpc52xx_psc_imr, port->read_status_mask); | ||
177 | } | ||
178 | |||
179 | static void mpc52xx_psc_set_sicr(struct uart_port *port, u32 val) | ||
180 | { | ||
181 | out_be32(&PSC(port)->sicr, val); | ||
182 | } | ||
183 | |||
184 | static void mpc52xx_psc_set_imr(struct uart_port *port, u16 val) | ||
185 | { | ||
186 | out_be16(&PSC(port)->mpc52xx_psc_imr, val); | ||
187 | } | ||
188 | |||
189 | static u8 mpc52xx_psc_get_mr1(struct uart_port *port) | ||
190 | { | ||
191 | out_8(&PSC(port)->command, MPC52xx_PSC_SEL_MODE_REG_1); | ||
192 | return in_8(&PSC(port)->mode); | ||
193 | } | ||
194 | |||
137 | #ifdef CONFIG_PPC_MPC52xx | 195 | #ifdef CONFIG_PPC_MPC52xx |
138 | #define FIFO_52xx(port) ((struct mpc52xx_psc_fifo __iomem *)(PSC(port)+1)) | 196 | #define FIFO_52xx(port) ((struct mpc52xx_psc_fifo __iomem *)(PSC(port)+1)) |
139 | static void mpc52xx_psc_fifo_init(struct uart_port *port) | 197 | static void mpc52xx_psc_fifo_init(struct uart_port *port) |
@@ -304,6 +362,15 @@ static struct psc_ops mpc52xx_psc_ops = { | |||
304 | .set_baudrate = mpc5200_psc_set_baudrate, | 362 | .set_baudrate = mpc5200_psc_set_baudrate, |
305 | .get_irq = mpc52xx_psc_get_irq, | 363 | .get_irq = mpc52xx_psc_get_irq, |
306 | .handle_irq = mpc52xx_psc_handle_irq, | 364 | .handle_irq = mpc52xx_psc_handle_irq, |
365 | .get_status = mpc52xx_psc_get_status, | ||
366 | .get_ipcr = mpc52xx_psc_get_ipcr, | ||
367 | .command = mpc52xx_psc_command, | ||
368 | .set_mode = mpc52xx_psc_set_mode, | ||
369 | .set_rts = mpc52xx_psc_set_rts, | ||
370 | .enable_ms = mpc52xx_psc_enable_ms, | ||
371 | .set_sicr = mpc52xx_psc_set_sicr, | ||
372 | .set_imr = mpc52xx_psc_set_imr, | ||
373 | .get_mr1 = mpc52xx_psc_get_mr1, | ||
307 | }; | 374 | }; |
308 | 375 | ||
309 | static struct psc_ops mpc5200b_psc_ops = { | 376 | static struct psc_ops mpc5200b_psc_ops = { |
@@ -325,6 +392,15 @@ static struct psc_ops mpc5200b_psc_ops = { | |||
325 | .set_baudrate = mpc5200b_psc_set_baudrate, | 392 | .set_baudrate = mpc5200b_psc_set_baudrate, |
326 | .get_irq = mpc52xx_psc_get_irq, | 393 | .get_irq = mpc52xx_psc_get_irq, |
327 | .handle_irq = mpc52xx_psc_handle_irq, | 394 | .handle_irq = mpc52xx_psc_handle_irq, |
395 | .get_status = mpc52xx_psc_get_status, | ||
396 | .get_ipcr = mpc52xx_psc_get_ipcr, | ||
397 | .command = mpc52xx_psc_command, | ||
398 | .set_mode = mpc52xx_psc_set_mode, | ||
399 | .set_rts = mpc52xx_psc_set_rts, | ||
400 | .enable_ms = mpc52xx_psc_enable_ms, | ||
401 | .set_sicr = mpc52xx_psc_set_sicr, | ||
402 | .set_imr = mpc52xx_psc_set_imr, | ||
403 | .get_mr1 = mpc52xx_psc_get_mr1, | ||
328 | }; | 404 | }; |
329 | 405 | ||
330 | #endif /* CONFIG_MPC52xx */ | 406 | #endif /* CONFIG_MPC52xx */ |
@@ -572,6 +648,246 @@ static void mpc512x_psc_get_irq(struct uart_port *port, struct device_node *np) | |||
572 | port->irqflags = IRQF_SHARED; | 648 | port->irqflags = IRQF_SHARED; |
573 | port->irq = psc_fifoc_irq; | 649 | port->irq = psc_fifoc_irq; |
574 | } | 650 | } |
651 | #endif | ||
652 | |||
653 | #ifdef CONFIG_PPC_MPC512x | ||
654 | |||
655 | #define PSC_5125(port) ((struct mpc5125_psc __iomem *)((port)->membase)) | ||
656 | #define FIFO_5125(port) ((struct mpc512x_psc_fifo __iomem *)(PSC_5125(port)+1)) | ||
657 | |||
658 | static void mpc5125_psc_fifo_init(struct uart_port *port) | ||
659 | { | ||
660 | /* /32 prescaler */ | ||
661 | out_8(&PSC_5125(port)->mpc52xx_psc_clock_select, 0xdd); | ||
662 | |||
663 | out_be32(&FIFO_5125(port)->txcmd, MPC512x_PSC_FIFO_RESET_SLICE); | ||
664 | out_be32(&FIFO_5125(port)->txcmd, MPC512x_PSC_FIFO_ENABLE_SLICE); | ||
665 | out_be32(&FIFO_5125(port)->txalarm, 1); | ||
666 | out_be32(&FIFO_5125(port)->tximr, 0); | ||
667 | |||
668 | out_be32(&FIFO_5125(port)->rxcmd, MPC512x_PSC_FIFO_RESET_SLICE); | ||
669 | out_be32(&FIFO_5125(port)->rxcmd, MPC512x_PSC_FIFO_ENABLE_SLICE); | ||
670 | out_be32(&FIFO_5125(port)->rxalarm, 1); | ||
671 | out_be32(&FIFO_5125(port)->rximr, 0); | ||
672 | |||
673 | out_be32(&FIFO_5125(port)->tximr, MPC512x_PSC_FIFO_ALARM); | ||
674 | out_be32(&FIFO_5125(port)->rximr, MPC512x_PSC_FIFO_ALARM); | ||
675 | } | ||
676 | |||
677 | static int mpc5125_psc_raw_rx_rdy(struct uart_port *port) | ||
678 | { | ||
679 | return !(in_be32(&FIFO_5125(port)->rxsr) & MPC512x_PSC_FIFO_EMPTY); | ||
680 | } | ||
681 | |||
682 | static int mpc5125_psc_raw_tx_rdy(struct uart_port *port) | ||
683 | { | ||
684 | return !(in_be32(&FIFO_5125(port)->txsr) & MPC512x_PSC_FIFO_FULL); | ||
685 | } | ||
686 | |||
687 | static int mpc5125_psc_rx_rdy(struct uart_port *port) | ||
688 | { | ||
689 | return in_be32(&FIFO_5125(port)->rxsr) & | ||
690 | in_be32(&FIFO_5125(port)->rximr) & MPC512x_PSC_FIFO_ALARM; | ||
691 | } | ||
692 | |||
693 | static int mpc5125_psc_tx_rdy(struct uart_port *port) | ||
694 | { | ||
695 | return in_be32(&FIFO_5125(port)->txsr) & | ||
696 | in_be32(&FIFO_5125(port)->tximr) & MPC512x_PSC_FIFO_ALARM; | ||
697 | } | ||
698 | |||
699 | static int mpc5125_psc_tx_empty(struct uart_port *port) | ||
700 | { | ||
701 | return in_be32(&FIFO_5125(port)->txsr) & MPC512x_PSC_FIFO_EMPTY; | ||
702 | } | ||
703 | |||
704 | static void mpc5125_psc_stop_rx(struct uart_port *port) | ||
705 | { | ||
706 | unsigned long rx_fifo_imr; | ||
707 | |||
708 | rx_fifo_imr = in_be32(&FIFO_5125(port)->rximr); | ||
709 | rx_fifo_imr &= ~MPC512x_PSC_FIFO_ALARM; | ||
710 | out_be32(&FIFO_5125(port)->rximr, rx_fifo_imr); | ||
711 | } | ||
712 | |||
713 | static void mpc5125_psc_start_tx(struct uart_port *port) | ||
714 | { | ||
715 | unsigned long tx_fifo_imr; | ||
716 | |||
717 | tx_fifo_imr = in_be32(&FIFO_5125(port)->tximr); | ||
718 | tx_fifo_imr |= MPC512x_PSC_FIFO_ALARM; | ||
719 | out_be32(&FIFO_5125(port)->tximr, tx_fifo_imr); | ||
720 | } | ||
721 | |||
722 | static void mpc5125_psc_stop_tx(struct uart_port *port) | ||
723 | { | ||
724 | unsigned long tx_fifo_imr; | ||
725 | |||
726 | tx_fifo_imr = in_be32(&FIFO_5125(port)->tximr); | ||
727 | tx_fifo_imr &= ~MPC512x_PSC_FIFO_ALARM; | ||
728 | out_be32(&FIFO_5125(port)->tximr, tx_fifo_imr); | ||
729 | } | ||
730 | |||
731 | static void mpc5125_psc_rx_clr_irq(struct uart_port *port) | ||
732 | { | ||
733 | out_be32(&FIFO_5125(port)->rxisr, in_be32(&FIFO_5125(port)->rxisr)); | ||
734 | } | ||
735 | |||
736 | static void mpc5125_psc_tx_clr_irq(struct uart_port *port) | ||
737 | { | ||
738 | out_be32(&FIFO_5125(port)->txisr, in_be32(&FIFO_5125(port)->txisr)); | ||
739 | } | ||
740 | |||
741 | static void mpc5125_psc_write_char(struct uart_port *port, unsigned char c) | ||
742 | { | ||
743 | out_8(&FIFO_5125(port)->txdata_8, c); | ||
744 | } | ||
745 | |||
746 | static unsigned char mpc5125_psc_read_char(struct uart_port *port) | ||
747 | { | ||
748 | return in_8(&FIFO_5125(port)->rxdata_8); | ||
749 | } | ||
750 | |||
751 | static void mpc5125_psc_cw_disable_ints(struct uart_port *port) | ||
752 | { | ||
753 | port->read_status_mask = | ||
754 | in_be32(&FIFO_5125(port)->tximr) << 16 | | ||
755 | in_be32(&FIFO_5125(port)->rximr); | ||
756 | out_be32(&FIFO_5125(port)->tximr, 0); | ||
757 | out_be32(&FIFO_5125(port)->rximr, 0); | ||
758 | } | ||
759 | |||
760 | static void mpc5125_psc_cw_restore_ints(struct uart_port *port) | ||
761 | { | ||
762 | out_be32(&FIFO_5125(port)->tximr, | ||
763 | (port->read_status_mask >> 16) & 0x7f); | ||
764 | out_be32(&FIFO_5125(port)->rximr, port->read_status_mask & 0x7f); | ||
765 | } | ||
766 | |||
767 | static inline void mpc5125_set_divisor(struct mpc5125_psc __iomem *psc, | ||
768 | u8 prescaler, unsigned int divisor) | ||
769 | { | ||
770 | /* select prescaler */ | ||
771 | out_8(&psc->mpc52xx_psc_clock_select, prescaler); | ||
772 | out_8(&psc->ctur, divisor >> 8); | ||
773 | out_8(&psc->ctlr, divisor & 0xff); | ||
774 | } | ||
775 | |||
776 | static unsigned int mpc5125_psc_set_baudrate(struct uart_port *port, | ||
777 | struct ktermios *new, | ||
778 | struct ktermios *old) | ||
779 | { | ||
780 | unsigned int baud; | ||
781 | unsigned int divisor; | ||
782 | |||
783 | /* | ||
784 | * Calculate with a /16 prescaler here. | ||
785 | */ | ||
786 | |||
787 | /* uartclk contains the ips freq */ | ||
788 | baud = uart_get_baud_rate(port, new, old, | ||
789 | port->uartclk / (16 * 0xffff) + 1, | ||
790 | port->uartclk / 16); | ||
791 | divisor = (port->uartclk + 8 * baud) / (16 * baud); | ||
792 | |||
793 | /* enable the /16 prescaler and set the divisor */ | ||
794 | mpc5125_set_divisor(PSC_5125(port), 0xdd, divisor); | ||
795 | return baud; | ||
796 | } | ||
797 | |||
798 | /* | ||
799 | * MPC5125 have compatible PSC FIFO Controller. | ||
800 | * Special init not needed. | ||
801 | */ | ||
802 | static u16 mpc5125_psc_get_status(struct uart_port *port) | ||
803 | { | ||
804 | return in_be16(&PSC_5125(port)->mpc52xx_psc_status); | ||
805 | } | ||
806 | |||
807 | static u8 mpc5125_psc_get_ipcr(struct uart_port *port) | ||
808 | { | ||
809 | return in_8(&PSC_5125(port)->mpc52xx_psc_ipcr); | ||
810 | } | ||
811 | |||
812 | static void mpc5125_psc_command(struct uart_port *port, u8 cmd) | ||
813 | { | ||
814 | out_8(&PSC_5125(port)->command, cmd); | ||
815 | } | ||
816 | |||
817 | static void mpc5125_psc_set_mode(struct uart_port *port, u8 mr1, u8 mr2) | ||
818 | { | ||
819 | out_8(&PSC_5125(port)->mr1, mr1); | ||
820 | out_8(&PSC_5125(port)->mr2, mr2); | ||
821 | } | ||
822 | |||
823 | static void mpc5125_psc_set_rts(struct uart_port *port, int state) | ||
824 | { | ||
825 | if (state & TIOCM_RTS) | ||
826 | out_8(&PSC_5125(port)->op1, MPC52xx_PSC_OP_RTS); | ||
827 | else | ||
828 | out_8(&PSC_5125(port)->op0, MPC52xx_PSC_OP_RTS); | ||
829 | } | ||
830 | |||
831 | static void mpc5125_psc_enable_ms(struct uart_port *port) | ||
832 | { | ||
833 | struct mpc5125_psc __iomem *psc = PSC_5125(port); | ||
834 | |||
835 | /* clear D_*-bits by reading them */ | ||
836 | in_8(&psc->mpc52xx_psc_ipcr); | ||
837 | /* enable CTS and DCD as IPC interrupts */ | ||
838 | out_8(&psc->mpc52xx_psc_acr, MPC52xx_PSC_IEC_CTS | MPC52xx_PSC_IEC_DCD); | ||
839 | |||
840 | port->read_status_mask |= MPC52xx_PSC_IMR_IPC; | ||
841 | out_be16(&psc->mpc52xx_psc_imr, port->read_status_mask); | ||
842 | } | ||
843 | |||
844 | static void mpc5125_psc_set_sicr(struct uart_port *port, u32 val) | ||
845 | { | ||
846 | out_be32(&PSC_5125(port)->sicr, val); | ||
847 | } | ||
848 | |||
849 | static void mpc5125_psc_set_imr(struct uart_port *port, u16 val) | ||
850 | { | ||
851 | out_be16(&PSC_5125(port)->mpc52xx_psc_imr, val); | ||
852 | } | ||
853 | |||
854 | static u8 mpc5125_psc_get_mr1(struct uart_port *port) | ||
855 | { | ||
856 | return in_8(&PSC_5125(port)->mr1); | ||
857 | } | ||
858 | |||
859 | static struct psc_ops mpc5125_psc_ops = { | ||
860 | .fifo_init = mpc5125_psc_fifo_init, | ||
861 | .raw_rx_rdy = mpc5125_psc_raw_rx_rdy, | ||
862 | .raw_tx_rdy = mpc5125_psc_raw_tx_rdy, | ||
863 | .rx_rdy = mpc5125_psc_rx_rdy, | ||
864 | .tx_rdy = mpc5125_psc_tx_rdy, | ||
865 | .tx_empty = mpc5125_psc_tx_empty, | ||
866 | .stop_rx = mpc5125_psc_stop_rx, | ||
867 | .start_tx = mpc5125_psc_start_tx, | ||
868 | .stop_tx = mpc5125_psc_stop_tx, | ||
869 | .rx_clr_irq = mpc5125_psc_rx_clr_irq, | ||
870 | .tx_clr_irq = mpc5125_psc_tx_clr_irq, | ||
871 | .write_char = mpc5125_psc_write_char, | ||
872 | .read_char = mpc5125_psc_read_char, | ||
873 | .cw_disable_ints = mpc5125_psc_cw_disable_ints, | ||
874 | .cw_restore_ints = mpc5125_psc_cw_restore_ints, | ||
875 | .set_baudrate = mpc5125_psc_set_baudrate, | ||
876 | .clock = mpc512x_psc_clock, | ||
877 | .fifoc_init = mpc512x_psc_fifoc_init, | ||
878 | .fifoc_uninit = mpc512x_psc_fifoc_uninit, | ||
879 | .get_irq = mpc512x_psc_get_irq, | ||
880 | .handle_irq = mpc512x_psc_handle_irq, | ||
881 | .get_status = mpc5125_psc_get_status, | ||
882 | .get_ipcr = mpc5125_psc_get_ipcr, | ||
883 | .command = mpc5125_psc_command, | ||
884 | .set_mode = mpc5125_psc_set_mode, | ||
885 | .set_rts = mpc5125_psc_set_rts, | ||
886 | .enable_ms = mpc5125_psc_enable_ms, | ||
887 | .set_sicr = mpc5125_psc_set_sicr, | ||
888 | .set_imr = mpc5125_psc_set_imr, | ||
889 | .get_mr1 = mpc5125_psc_get_mr1, | ||
890 | }; | ||
575 | 891 | ||
576 | static struct psc_ops mpc512x_psc_ops = { | 892 | static struct psc_ops mpc512x_psc_ops = { |
577 | .fifo_init = mpc512x_psc_fifo_init, | 893 | .fifo_init = mpc512x_psc_fifo_init, |
@@ -595,8 +911,18 @@ static struct psc_ops mpc512x_psc_ops = { | |||
595 | .fifoc_uninit = mpc512x_psc_fifoc_uninit, | 911 | .fifoc_uninit = mpc512x_psc_fifoc_uninit, |
596 | .get_irq = mpc512x_psc_get_irq, | 912 | .get_irq = mpc512x_psc_get_irq, |
597 | .handle_irq = mpc512x_psc_handle_irq, | 913 | .handle_irq = mpc512x_psc_handle_irq, |
914 | .get_status = mpc52xx_psc_get_status, | ||
915 | .get_ipcr = mpc52xx_psc_get_ipcr, | ||
916 | .command = mpc52xx_psc_command, | ||
917 | .set_mode = mpc52xx_psc_set_mode, | ||
918 | .set_rts = mpc52xx_psc_set_rts, | ||
919 | .enable_ms = mpc52xx_psc_enable_ms, | ||
920 | .set_sicr = mpc52xx_psc_set_sicr, | ||
921 | .set_imr = mpc52xx_psc_set_imr, | ||
922 | .get_mr1 = mpc52xx_psc_get_mr1, | ||
598 | }; | 923 | }; |
599 | #endif | 924 | #endif /* CONFIG_PPC_MPC512x */ |
925 | |||
600 | 926 | ||
601 | static const struct psc_ops *psc_ops; | 927 | static const struct psc_ops *psc_ops; |
602 | 928 | ||
@@ -613,17 +939,14 @@ mpc52xx_uart_tx_empty(struct uart_port *port) | |||
613 | static void | 939 | static void |
614 | mpc52xx_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) | 940 | mpc52xx_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) |
615 | { | 941 | { |
616 | if (mctrl & TIOCM_RTS) | 942 | psc_ops->set_rts(port, mctrl & TIOCM_RTS); |
617 | out_8(&PSC(port)->op1, MPC52xx_PSC_OP_RTS); | ||
618 | else | ||
619 | out_8(&PSC(port)->op0, MPC52xx_PSC_OP_RTS); | ||
620 | } | 943 | } |
621 | 944 | ||
622 | static unsigned int | 945 | static unsigned int |
623 | mpc52xx_uart_get_mctrl(struct uart_port *port) | 946 | mpc52xx_uart_get_mctrl(struct uart_port *port) |
624 | { | 947 | { |
625 | unsigned int ret = TIOCM_DSR; | 948 | unsigned int ret = TIOCM_DSR; |
626 | u8 status = in_8(&PSC(port)->mpc52xx_psc_ipcr); | 949 | u8 status = psc_ops->get_ipcr(port); |
627 | 950 | ||
628 | if (!(status & MPC52xx_PSC_CTS)) | 951 | if (!(status & MPC52xx_PSC_CTS)) |
629 | ret |= TIOCM_CTS; | 952 | ret |= TIOCM_CTS; |
@@ -673,15 +996,7 @@ mpc52xx_uart_stop_rx(struct uart_port *port) | |||
673 | static void | 996 | static void |
674 | mpc52xx_uart_enable_ms(struct uart_port *port) | 997 | mpc52xx_uart_enable_ms(struct uart_port *port) |
675 | { | 998 | { |
676 | struct mpc52xx_psc __iomem *psc = PSC(port); | 999 | psc_ops->enable_ms(port); |
677 | |||
678 | /* clear D_*-bits by reading them */ | ||
679 | in_8(&psc->mpc52xx_psc_ipcr); | ||
680 | /* enable CTS and DCD as IPC interrupts */ | ||
681 | out_8(&psc->mpc52xx_psc_acr, MPC52xx_PSC_IEC_CTS | MPC52xx_PSC_IEC_DCD); | ||
682 | |||
683 | port->read_status_mask |= MPC52xx_PSC_IMR_IPC; | ||
684 | out_be16(&psc->mpc52xx_psc_imr, port->read_status_mask); | ||
685 | } | 1000 | } |
686 | 1001 | ||
687 | static void | 1002 | static void |
@@ -691,9 +1006,9 @@ mpc52xx_uart_break_ctl(struct uart_port *port, int ctl) | |||
691 | spin_lock_irqsave(&port->lock, flags); | 1006 | spin_lock_irqsave(&port->lock, flags); |
692 | 1007 | ||
693 | if (ctl == -1) | 1008 | if (ctl == -1) |
694 | out_8(&PSC(port)->command, MPC52xx_PSC_START_BRK); | 1009 | psc_ops->command(port, MPC52xx_PSC_START_BRK); |
695 | else | 1010 | else |
696 | out_8(&PSC(port)->command, MPC52xx_PSC_STOP_BRK); | 1011 | psc_ops->command(port, MPC52xx_PSC_STOP_BRK); |
697 | 1012 | ||
698 | spin_unlock_irqrestore(&port->lock, flags); | 1013 | spin_unlock_irqrestore(&port->lock, flags); |
699 | } | 1014 | } |
@@ -701,7 +1016,6 @@ mpc52xx_uart_break_ctl(struct uart_port *port, int ctl) | |||
701 | static int | 1016 | static int |
702 | mpc52xx_uart_startup(struct uart_port *port) | 1017 | mpc52xx_uart_startup(struct uart_port *port) |
703 | { | 1018 | { |
704 | struct mpc52xx_psc __iomem *psc = PSC(port); | ||
705 | int ret; | 1019 | int ret; |
706 | 1020 | ||
707 | if (psc_ops->clock) { | 1021 | if (psc_ops->clock) { |
@@ -717,15 +1031,15 @@ mpc52xx_uart_startup(struct uart_port *port) | |||
717 | return ret; | 1031 | return ret; |
718 | 1032 | ||
719 | /* Reset/activate the port, clear and enable interrupts */ | 1033 | /* Reset/activate the port, clear and enable interrupts */ |
720 | out_8(&psc->command, MPC52xx_PSC_RST_RX); | 1034 | psc_ops->command(port, MPC52xx_PSC_RST_RX); |
721 | out_8(&psc->command, MPC52xx_PSC_RST_TX); | 1035 | psc_ops->command(port, MPC52xx_PSC_RST_TX); |
722 | 1036 | ||
723 | out_be32(&psc->sicr, 0); /* UART mode DCD ignored */ | 1037 | psc_ops->set_sicr(port, 0); /* UART mode DCD ignored */ |
724 | 1038 | ||
725 | psc_ops->fifo_init(port); | 1039 | psc_ops->fifo_init(port); |
726 | 1040 | ||
727 | out_8(&psc->command, MPC52xx_PSC_TX_ENABLE); | 1041 | psc_ops->command(port, MPC52xx_PSC_TX_ENABLE); |
728 | out_8(&psc->command, MPC52xx_PSC_RX_ENABLE); | 1042 | psc_ops->command(port, MPC52xx_PSC_RX_ENABLE); |
729 | 1043 | ||
730 | return 0; | 1044 | return 0; |
731 | } | 1045 | } |
@@ -733,19 +1047,20 @@ mpc52xx_uart_startup(struct uart_port *port) | |||
733 | static void | 1047 | static void |
734 | mpc52xx_uart_shutdown(struct uart_port *port) | 1048 | mpc52xx_uart_shutdown(struct uart_port *port) |
735 | { | 1049 | { |
736 | struct mpc52xx_psc __iomem *psc = PSC(port); | ||
737 | |||
738 | /* Shut down the port. Leave TX active if on a console port */ | 1050 | /* Shut down the port. Leave TX active if on a console port */ |
739 | out_8(&psc->command, MPC52xx_PSC_RST_RX); | 1051 | psc_ops->command(port, MPC52xx_PSC_RST_RX); |
740 | if (!uart_console(port)) | 1052 | if (!uart_console(port)) |
741 | out_8(&psc->command, MPC52xx_PSC_RST_TX); | 1053 | psc_ops->command(port, MPC52xx_PSC_RST_TX); |
742 | 1054 | ||
743 | port->read_status_mask = 0; | 1055 | port->read_status_mask = 0; |
744 | out_be16(&psc->mpc52xx_psc_imr, port->read_status_mask); | 1056 | psc_ops->set_imr(port, port->read_status_mask); |
745 | 1057 | ||
746 | if (psc_ops->clock) | 1058 | if (psc_ops->clock) |
747 | psc_ops->clock(port, 0); | 1059 | psc_ops->clock(port, 0); |
748 | 1060 | ||
1061 | /* Disable interrupt */ | ||
1062 | psc_ops->cw_disable_ints(port); | ||
1063 | |||
749 | /* Release interrupt */ | 1064 | /* Release interrupt */ |
750 | free_irq(port->irq, port); | 1065 | free_irq(port->irq, port); |
751 | } | 1066 | } |
@@ -754,7 +1069,6 @@ static void | |||
754 | mpc52xx_uart_set_termios(struct uart_port *port, struct ktermios *new, | 1069 | mpc52xx_uart_set_termios(struct uart_port *port, struct ktermios *new, |
755 | struct ktermios *old) | 1070 | struct ktermios *old) |
756 | { | 1071 | { |
757 | struct mpc52xx_psc __iomem *psc = PSC(port); | ||
758 | unsigned long flags; | 1072 | unsigned long flags; |
759 | unsigned char mr1, mr2; | 1073 | unsigned char mr1, mr2; |
760 | unsigned int j; | 1074 | unsigned int j; |
@@ -818,13 +1132,11 @@ mpc52xx_uart_set_termios(struct uart_port *port, struct ktermios *new, | |||
818 | "Some chars may have been lost.\n"); | 1132 | "Some chars may have been lost.\n"); |
819 | 1133 | ||
820 | /* Reset the TX & RX */ | 1134 | /* Reset the TX & RX */ |
821 | out_8(&psc->command, MPC52xx_PSC_RST_RX); | 1135 | psc_ops->command(port, MPC52xx_PSC_RST_RX); |
822 | out_8(&psc->command, MPC52xx_PSC_RST_TX); | 1136 | psc_ops->command(port, MPC52xx_PSC_RST_TX); |
823 | 1137 | ||
824 | /* Send new mode settings */ | 1138 | /* Send new mode settings */ |
825 | out_8(&psc->command, MPC52xx_PSC_SEL_MODE_REG_1); | 1139 | psc_ops->set_mode(port, mr1, mr2); |
826 | out_8(&psc->mode, mr1); | ||
827 | out_8(&psc->mode, mr2); | ||
828 | baud = psc_ops->set_baudrate(port, new, old); | 1140 | baud = psc_ops->set_baudrate(port, new, old); |
829 | 1141 | ||
830 | /* Update the per-port timeout */ | 1142 | /* Update the per-port timeout */ |
@@ -834,8 +1146,8 @@ mpc52xx_uart_set_termios(struct uart_port *port, struct ktermios *new, | |||
834 | mpc52xx_uart_enable_ms(port); | 1146 | mpc52xx_uart_enable_ms(port); |
835 | 1147 | ||
836 | /* Reenable TX & RX */ | 1148 | /* Reenable TX & RX */ |
837 | out_8(&psc->command, MPC52xx_PSC_TX_ENABLE); | 1149 | psc_ops->command(port, MPC52xx_PSC_TX_ENABLE); |
838 | out_8(&psc->command, MPC52xx_PSC_RX_ENABLE); | 1150 | psc_ops->command(port, MPC52xx_PSC_RX_ENABLE); |
839 | 1151 | ||
840 | /* We're all set, release the lock */ | 1152 | /* We're all set, release the lock */ |
841 | spin_unlock_irqrestore(&port->lock, flags); | 1153 | spin_unlock_irqrestore(&port->lock, flags); |
@@ -963,7 +1275,7 @@ mpc52xx_uart_int_rx_chars(struct uart_port *port) | |||
963 | flag = TTY_NORMAL; | 1275 | flag = TTY_NORMAL; |
964 | port->icount.rx++; | 1276 | port->icount.rx++; |
965 | 1277 | ||
966 | status = in_be16(&PSC(port)->mpc52xx_psc_status); | 1278 | status = psc_ops->get_status(port); |
967 | 1279 | ||
968 | if (status & (MPC52xx_PSC_SR_PE | | 1280 | if (status & (MPC52xx_PSC_SR_PE | |
969 | MPC52xx_PSC_SR_FE | | 1281 | MPC52xx_PSC_SR_FE | |
@@ -983,7 +1295,7 @@ mpc52xx_uart_int_rx_chars(struct uart_port *port) | |||
983 | } | 1295 | } |
984 | 1296 | ||
985 | /* Clear error condition */ | 1297 | /* Clear error condition */ |
986 | out_8(&PSC(port)->command, MPC52xx_PSC_RST_ERR_STAT); | 1298 | psc_ops->command(port, MPC52xx_PSC_RST_ERR_STAT); |
987 | 1299 | ||
988 | } | 1300 | } |
989 | tty_insert_flip_char(tport, ch, flag); | 1301 | tty_insert_flip_char(tport, ch, flag); |
@@ -1066,7 +1378,7 @@ mpc5xxx_uart_process_int(struct uart_port *port) | |||
1066 | if (psc_ops->tx_rdy(port)) | 1378 | if (psc_ops->tx_rdy(port)) |
1067 | keepgoing |= mpc52xx_uart_int_tx_chars(port); | 1379 | keepgoing |= mpc52xx_uart_int_tx_chars(port); |
1068 | 1380 | ||
1069 | status = in_8(&PSC(port)->mpc52xx_psc_ipcr); | 1381 | status = psc_ops->get_ipcr(port); |
1070 | if (status & MPC52xx_PSC_D_DCD) | 1382 | if (status & MPC52xx_PSC_D_DCD) |
1071 | uart_handle_dcd_change(port, !(status & MPC52xx_PSC_DCD)); | 1383 | uart_handle_dcd_change(port, !(status & MPC52xx_PSC_DCD)); |
1072 | 1384 | ||
@@ -1107,14 +1419,12 @@ static void __init | |||
1107 | mpc52xx_console_get_options(struct uart_port *port, | 1419 | mpc52xx_console_get_options(struct uart_port *port, |
1108 | int *baud, int *parity, int *bits, int *flow) | 1420 | int *baud, int *parity, int *bits, int *flow) |
1109 | { | 1421 | { |
1110 | struct mpc52xx_psc __iomem *psc = PSC(port); | ||
1111 | unsigned char mr1; | 1422 | unsigned char mr1; |
1112 | 1423 | ||
1113 | pr_debug("mpc52xx_console_get_options(port=%p)\n", port); | 1424 | pr_debug("mpc52xx_console_get_options(port=%p)\n", port); |
1114 | 1425 | ||
1115 | /* Read the mode registers */ | 1426 | /* Read the mode registers */ |
1116 | out_8(&psc->command, MPC52xx_PSC_SEL_MODE_REG_1); | 1427 | mr1 = psc_ops->get_mr1(port); |
1117 | mr1 = in_8(&psc->mode); | ||
1118 | 1428 | ||
1119 | /* CT{U,L}R are write-only ! */ | 1429 | /* CT{U,L}R are write-only ! */ |
1120 | *baud = CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD; | 1430 | *baud = CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD; |
@@ -1304,6 +1614,7 @@ static struct of_device_id mpc52xx_uart_of_match[] = { | |||
1304 | #endif | 1614 | #endif |
1305 | #ifdef CONFIG_PPC_MPC512x | 1615 | #ifdef CONFIG_PPC_MPC512x |
1306 | { .compatible = "fsl,mpc5121-psc-uart", .data = &mpc512x_psc_ops, }, | 1616 | { .compatible = "fsl,mpc5121-psc-uart", .data = &mpc512x_psc_ops, }, |
1617 | { .compatible = "fsl,mpc5125-psc-uart", .data = &mpc5125_psc_ops, }, | ||
1307 | #endif | 1618 | #endif |
1308 | {}, | 1619 | {}, |
1309 | }; | 1620 | }; |
@@ -1372,15 +1683,14 @@ static int mpc52xx_uart_of_probe(struct platform_device *op) | |||
1372 | if (ret) | 1683 | if (ret) |
1373 | return ret; | 1684 | return ret; |
1374 | 1685 | ||
1375 | dev_set_drvdata(&op->dev, (void *)port); | 1686 | platform_set_drvdata(op, (void *)port); |
1376 | return 0; | 1687 | return 0; |
1377 | } | 1688 | } |
1378 | 1689 | ||
1379 | static int | 1690 | static int |
1380 | mpc52xx_uart_of_remove(struct platform_device *op) | 1691 | mpc52xx_uart_of_remove(struct platform_device *op) |
1381 | { | 1692 | { |
1382 | struct uart_port *port = dev_get_drvdata(&op->dev); | 1693 | struct uart_port *port = platform_get_drvdata(op); |
1383 | dev_set_drvdata(&op->dev, NULL); | ||
1384 | 1694 | ||
1385 | if (port) | 1695 | if (port) |
1386 | uart_remove_one_port(&mpc52xx_uart_driver, port); | 1696 | uart_remove_one_port(&mpc52xx_uart_driver, port); |
@@ -1392,7 +1702,7 @@ mpc52xx_uart_of_remove(struct platform_device *op) | |||
1392 | static int | 1702 | static int |
1393 | mpc52xx_uart_of_suspend(struct platform_device *op, pm_message_t state) | 1703 | mpc52xx_uart_of_suspend(struct platform_device *op, pm_message_t state) |
1394 | { | 1704 | { |
1395 | struct uart_port *port = (struct uart_port *) dev_get_drvdata(&op->dev); | 1705 | struct uart_port *port = (struct uart_port *) platform_get_drvdata(op); |
1396 | 1706 | ||
1397 | if (port) | 1707 | if (port) |
1398 | uart_suspend_port(&mpc52xx_uart_driver, port); | 1708 | uart_suspend_port(&mpc52xx_uart_driver, port); |
@@ -1403,7 +1713,7 @@ mpc52xx_uart_of_suspend(struct platform_device *op, pm_message_t state) | |||
1403 | static int | 1713 | static int |
1404 | mpc52xx_uart_of_resume(struct platform_device *op) | 1714 | mpc52xx_uart_of_resume(struct platform_device *op) |
1405 | { | 1715 | { |
1406 | struct uart_port *port = (struct uart_port *) dev_get_drvdata(&op->dev); | 1716 | struct uart_port *port = (struct uart_port *) platform_get_drvdata(op); |
1407 | 1717 | ||
1408 | if (port) | 1718 | if (port) |
1409 | uart_resume_port(&mpc52xx_uart_driver, port); | 1719 | uart_resume_port(&mpc52xx_uart_driver, port); |
diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c index 39c7ea4cb14f..2caf9c6f6149 100644 --- a/drivers/tty/serial/of_serial.c +++ b/drivers/tty/serial/of_serial.c | |||
@@ -204,7 +204,7 @@ static int of_platform_serial_probe(struct platform_device *ofdev) | |||
204 | 204 | ||
205 | info->type = port_type; | 205 | info->type = port_type; |
206 | info->line = ret; | 206 | info->line = ret; |
207 | dev_set_drvdata(&ofdev->dev, info); | 207 | platform_set_drvdata(ofdev, info); |
208 | return 0; | 208 | return 0; |
209 | out: | 209 | out: |
210 | kfree(info); | 210 | kfree(info); |
@@ -217,7 +217,7 @@ out: | |||
217 | */ | 217 | */ |
218 | static int of_platform_serial_remove(struct platform_device *ofdev) | 218 | static int of_platform_serial_remove(struct platform_device *ofdev) |
219 | { | 219 | { |
220 | struct of_serial_info *info = dev_get_drvdata(&ofdev->dev); | 220 | struct of_serial_info *info = platform_get_drvdata(ofdev); |
221 | switch (info->type) { | 221 | switch (info->type) { |
222 | #ifdef CONFIG_SERIAL_8250 | 222 | #ifdef CONFIG_SERIAL_8250 |
223 | case PORT_8250 ... PORT_MAX_8250: | 223 | case PORT_8250 ... PORT_MAX_8250: |
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index f0b9f6b52b32..b6d172873076 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c | |||
@@ -161,6 +161,7 @@ struct uart_omap_port { | |||
161 | u32 calc_latency; | 161 | u32 calc_latency; |
162 | struct work_struct qos_work; | 162 | struct work_struct qos_work; |
163 | struct pinctrl *pins; | 163 | struct pinctrl *pins; |
164 | bool is_suspending; | ||
164 | }; | 165 | }; |
165 | 166 | ||
166 | #define to_uart_omap_port(p) ((container_of((p), struct uart_omap_port, port))) | 167 | #define to_uart_omap_port(p) ((container_of((p), struct uart_omap_port, port))) |
@@ -197,7 +198,7 @@ static int serial_omap_get_context_loss_count(struct uart_omap_port *up) | |||
197 | struct omap_uart_port_info *pdata = up->dev->platform_data; | 198 | struct omap_uart_port_info *pdata = up->dev->platform_data; |
198 | 199 | ||
199 | if (!pdata || !pdata->get_context_loss_count) | 200 | if (!pdata || !pdata->get_context_loss_count) |
200 | return 0; | 201 | return -EINVAL; |
201 | 202 | ||
202 | return pdata->get_context_loss_count(up->dev); | 203 | return pdata->get_context_loss_count(up->dev); |
203 | } | 204 | } |
@@ -1289,6 +1290,22 @@ static struct uart_driver serial_omap_reg = { | |||
1289 | }; | 1290 | }; |
1290 | 1291 | ||
1291 | #ifdef CONFIG_PM_SLEEP | 1292 | #ifdef CONFIG_PM_SLEEP |
1293 | static int serial_omap_prepare(struct device *dev) | ||
1294 | { | ||
1295 | struct uart_omap_port *up = dev_get_drvdata(dev); | ||
1296 | |||
1297 | up->is_suspending = true; | ||
1298 | |||
1299 | return 0; | ||
1300 | } | ||
1301 | |||
1302 | static void serial_omap_complete(struct device *dev) | ||
1303 | { | ||
1304 | struct uart_omap_port *up = dev_get_drvdata(dev); | ||
1305 | |||
1306 | up->is_suspending = false; | ||
1307 | } | ||
1308 | |||
1292 | static int serial_omap_suspend(struct device *dev) | 1309 | static int serial_omap_suspend(struct device *dev) |
1293 | { | 1310 | { |
1294 | struct uart_omap_port *up = dev_get_drvdata(dev); | 1311 | struct uart_omap_port *up = dev_get_drvdata(dev); |
@@ -1307,7 +1324,10 @@ static int serial_omap_resume(struct device *dev) | |||
1307 | 1324 | ||
1308 | return 0; | 1325 | return 0; |
1309 | } | 1326 | } |
1310 | #endif | 1327 | #else |
1328 | #define serial_omap_prepare NULL | ||
1329 | #define serial_omap_complete NULL | ||
1330 | #endif /* CONFIG_PM_SLEEP */ | ||
1311 | 1331 | ||
1312 | static void omap_serial_fill_features_erratas(struct uart_omap_port *up) | 1332 | static void omap_serial_fill_features_erratas(struct uart_omap_port *up) |
1313 | { | 1333 | { |
@@ -1482,6 +1502,9 @@ static int serial_omap_probe(struct platform_device *pdev) | |||
1482 | 1502 | ||
1483 | platform_set_drvdata(pdev, up); | 1503 | platform_set_drvdata(pdev, up); |
1484 | pm_runtime_enable(&pdev->dev); | 1504 | pm_runtime_enable(&pdev->dev); |
1505 | if (omap_up_info->autosuspend_timeout == 0) | ||
1506 | omap_up_info->autosuspend_timeout = -1; | ||
1507 | device_init_wakeup(up->dev, true); | ||
1485 | pm_runtime_use_autosuspend(&pdev->dev); | 1508 | pm_runtime_use_autosuspend(&pdev->dev); |
1486 | pm_runtime_set_autosuspend_delay(&pdev->dev, | 1509 | pm_runtime_set_autosuspend_delay(&pdev->dev, |
1487 | omap_up_info->autosuspend_timeout); | 1510 | omap_up_info->autosuspend_timeout); |
@@ -1591,13 +1614,19 @@ static void serial_omap_restore_context(struct uart_omap_port *up) | |||
1591 | static int serial_omap_runtime_suspend(struct device *dev) | 1614 | static int serial_omap_runtime_suspend(struct device *dev) |
1592 | { | 1615 | { |
1593 | struct uart_omap_port *up = dev_get_drvdata(dev); | 1616 | struct uart_omap_port *up = dev_get_drvdata(dev); |
1594 | struct omap_uart_port_info *pdata = dev->platform_data; | ||
1595 | 1617 | ||
1596 | if (!up) | 1618 | if (!up) |
1597 | return -EINVAL; | 1619 | return -EINVAL; |
1598 | 1620 | ||
1599 | if (!pdata) | 1621 | /* |
1600 | return 0; | 1622 | * When using 'no_console_suspend', the console UART must not be |
1623 | * suspended. Since driver suspend is managed by runtime suspend, | ||
1624 | * preventing runtime suspend (by returning error) will keep device | ||
1625 | * active during suspend. | ||
1626 | */ | ||
1627 | if (up->is_suspending && !console_suspend_enabled && | ||
1628 | uart_console(&up->port)) | ||
1629 | return -EBUSY; | ||
1601 | 1630 | ||
1602 | up->context_loss_cnt = serial_omap_get_context_loss_count(up); | 1631 | up->context_loss_cnt = serial_omap_get_context_loss_count(up); |
1603 | 1632 | ||
@@ -1626,7 +1655,7 @@ static int serial_omap_runtime_resume(struct device *dev) | |||
1626 | int loss_cnt = serial_omap_get_context_loss_count(up); | 1655 | int loss_cnt = serial_omap_get_context_loss_count(up); |
1627 | 1656 | ||
1628 | if (loss_cnt < 0) { | 1657 | if (loss_cnt < 0) { |
1629 | dev_err(dev, "serial_omap_get_context_loss_count failed : %d\n", | 1658 | dev_dbg(dev, "serial_omap_get_context_loss_count failed : %d\n", |
1630 | loss_cnt); | 1659 | loss_cnt); |
1631 | serial_omap_restore_context(up); | 1660 | serial_omap_restore_context(up); |
1632 | } else if (up->context_loss_cnt != loss_cnt) { | 1661 | } else if (up->context_loss_cnt != loss_cnt) { |
@@ -1643,6 +1672,8 @@ static const struct dev_pm_ops serial_omap_dev_pm_ops = { | |||
1643 | SET_SYSTEM_SLEEP_PM_OPS(serial_omap_suspend, serial_omap_resume) | 1672 | SET_SYSTEM_SLEEP_PM_OPS(serial_omap_suspend, serial_omap_resume) |
1644 | SET_RUNTIME_PM_OPS(serial_omap_runtime_suspend, | 1673 | SET_RUNTIME_PM_OPS(serial_omap_runtime_suspend, |
1645 | serial_omap_runtime_resume, NULL) | 1674 | serial_omap_runtime_resume, NULL) |
1675 | .prepare = serial_omap_prepare, | ||
1676 | .complete = serial_omap_complete, | ||
1646 | }; | 1677 | }; |
1647 | 1678 | ||
1648 | #if defined(CONFIG_OF) | 1679 | #if defined(CONFIG_OF) |
diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index 21a7e179edf3..572d48189de9 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c | |||
@@ -217,6 +217,7 @@ enum { | |||
217 | #define FRI2_64_UARTCLK 64000000 /* 64.0000 MHz */ | 217 | #define FRI2_64_UARTCLK 64000000 /* 64.0000 MHz */ |
218 | #define FRI2_48_UARTCLK 48000000 /* 48.0000 MHz */ | 218 | #define FRI2_48_UARTCLK 48000000 /* 48.0000 MHz */ |
219 | #define NTC1_UARTCLK 64000000 /* 64.0000 MHz */ | 219 | #define NTC1_UARTCLK 64000000 /* 64.0000 MHz */ |
220 | #define MINNOW_UARTCLK 50000000 /* 50.0000 MHz */ | ||
220 | 221 | ||
221 | struct pch_uart_buffer { | 222 | struct pch_uart_buffer { |
222 | unsigned char *buf; | 223 | unsigned char *buf; |
@@ -398,6 +399,10 @@ static int pch_uart_get_uartclk(void) | |||
398 | strstr(cmp, "nanoETXexpress-TT"))) | 399 | strstr(cmp, "nanoETXexpress-TT"))) |
399 | return NTC1_UARTCLK; | 400 | return NTC1_UARTCLK; |
400 | 401 | ||
402 | cmp = dmi_get_system_info(DMI_BOARD_NAME); | ||
403 | if (cmp && strstr(cmp, "MinnowBoard")) | ||
404 | return MINNOW_UARTCLK; | ||
405 | |||
401 | return DEFAULT_UARTCLK; | 406 | return DEFAULT_UARTCLK; |
402 | } | 407 | } |
403 | 408 | ||
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c index 0c8a9fa2be6c..81ebc86a9e23 100644 --- a/drivers/tty/serial/samsung.c +++ b/drivers/tty/serial/samsung.c | |||
@@ -1811,7 +1811,13 @@ static int __init s3c24xx_serial_modinit(void) | |||
1811 | return ret; | 1811 | return ret; |
1812 | } | 1812 | } |
1813 | 1813 | ||
1814 | return platform_driver_register(&samsung_serial_driver); | 1814 | ret = platform_driver_register(&samsung_serial_driver); |
1815 | if (ret < 0) { | ||
1816 | pr_err("Failed to register platform driver\n"); | ||
1817 | uart_unregister_driver(&s3c24xx_uart_drv); | ||
1818 | } | ||
1819 | |||
1820 | return ret; | ||
1815 | } | 1821 | } |
1816 | 1822 | ||
1817 | static void __exit s3c24xx_serial_modexit(void) | 1823 | static void __exit s3c24xx_serial_modexit(void) |
diff --git a/drivers/tty/serial/sc26xx.c b/drivers/tty/serial/sc26xx.c index c9735680762d..4b1434d53e9d 100644 --- a/drivers/tty/serial/sc26xx.c +++ b/drivers/tty/serial/sc26xx.c | |||
@@ -696,7 +696,7 @@ static int sc26xx_probe(struct platform_device *dev) | |||
696 | if (err) | 696 | if (err) |
697 | goto out_remove_ports; | 697 | goto out_remove_ports; |
698 | 698 | ||
699 | dev_set_drvdata(&dev->dev, up); | 699 | platform_set_drvdata(dev, up); |
700 | return 0; | 700 | return 0; |
701 | 701 | ||
702 | out_remove_ports: | 702 | out_remove_ports: |
@@ -716,7 +716,7 @@ out_free_port: | |||
716 | 716 | ||
717 | static int __exit sc26xx_driver_remove(struct platform_device *dev) | 717 | static int __exit sc26xx_driver_remove(struct platform_device *dev) |
718 | { | 718 | { |
719 | struct uart_sc26xx_port *up = dev_get_drvdata(&dev->dev); | 719 | struct uart_sc26xx_port *up = platform_get_drvdata(dev); |
720 | 720 | ||
721 | free_irq(up->port[0].irq, up); | 721 | free_irq(up->port[0].irq, up); |
722 | 722 | ||
@@ -728,7 +728,6 @@ static int __exit sc26xx_driver_remove(struct platform_device *dev) | |||
728 | kfree(up); | 728 | kfree(up); |
729 | sc26xx_port = NULL; | 729 | sc26xx_port = NULL; |
730 | 730 | ||
731 | dev_set_drvdata(&dev->dev, NULL); | ||
732 | return 0; | 731 | return 0; |
733 | } | 732 | } |
734 | 733 | ||
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index f87dbfd32770..28cdd2829139 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c | |||
@@ -50,12 +50,6 @@ static struct lock_class_key port_lock_key; | |||
50 | 50 | ||
51 | #define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8) | 51 | #define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8) |
52 | 52 | ||
53 | #ifdef CONFIG_SERIAL_CORE_CONSOLE | ||
54 | #define uart_console(port) ((port)->cons && (port)->cons->index == (port)->line) | ||
55 | #else | ||
56 | #define uart_console(port) (0) | ||
57 | #endif | ||
58 | |||
59 | static void uart_change_speed(struct tty_struct *tty, struct uart_state *state, | 53 | static void uart_change_speed(struct tty_struct *tty, struct uart_state *state, |
60 | struct ktermios *old_termios); | 54 | struct ktermios *old_termios); |
61 | static void uart_wait_until_sent(struct tty_struct *tty, int timeout); | 55 | static void uart_wait_until_sent(struct tty_struct *tty, int timeout); |
diff --git a/drivers/tty/serial/sirfsoc_uart.c b/drivers/tty/serial/sirfsoc_uart.c index 03465b673945..1fd564b8194b 100644 --- a/drivers/tty/serial/sirfsoc_uart.c +++ b/drivers/tty/serial/sirfsoc_uart.c | |||
@@ -687,9 +687,10 @@ int sirfsoc_uart_probe(struct platform_device *pdev) | |||
687 | 687 | ||
688 | if (sirfport->hw_flow_ctrl) { | 688 | if (sirfport->hw_flow_ctrl) { |
689 | sirfport->p = pinctrl_get_select_default(&pdev->dev); | 689 | sirfport->p = pinctrl_get_select_default(&pdev->dev); |
690 | ret = IS_ERR(sirfport->p); | 690 | if (IS_ERR(sirfport->p)) { |
691 | if (ret) | 691 | ret = PTR_ERR(sirfport->p); |
692 | goto err; | 692 | goto err; |
693 | } | ||
693 | } | 694 | } |
694 | 695 | ||
695 | sirfport->clk = clk_get(&pdev->dev, NULL); | 696 | sirfport->clk = clk_get(&pdev->dev, NULL); |
diff --git a/drivers/tty/serial/sunhv.c b/drivers/tty/serial/sunhv.c index ba60708053e0..cf86e729532b 100644 --- a/drivers/tty/serial/sunhv.c +++ b/drivers/tty/serial/sunhv.c | |||
@@ -577,7 +577,7 @@ static int hv_probe(struct platform_device *op) | |||
577 | if (err) | 577 | if (err) |
578 | goto out_remove_port; | 578 | goto out_remove_port; |
579 | 579 | ||
580 | dev_set_drvdata(&op->dev, port); | 580 | platform_set_drvdata(op, port); |
581 | 581 | ||
582 | return 0; | 582 | return 0; |
583 | 583 | ||
@@ -601,7 +601,7 @@ out_free_port: | |||
601 | 601 | ||
602 | static int hv_remove(struct platform_device *dev) | 602 | static int hv_remove(struct platform_device *dev) |
603 | { | 603 | { |
604 | struct uart_port *port = dev_get_drvdata(&dev->dev); | 604 | struct uart_port *port = platform_get_drvdata(dev); |
605 | 605 | ||
606 | free_irq(port->irq, port); | 606 | free_irq(port->irq, port); |
607 | 607 | ||
@@ -612,8 +612,6 @@ static int hv_remove(struct platform_device *dev) | |||
612 | kfree(port); | 612 | kfree(port); |
613 | sunhv_port = NULL; | 613 | sunhv_port = NULL; |
614 | 614 | ||
615 | dev_set_drvdata(&dev->dev, NULL); | ||
616 | |||
617 | return 0; | 615 | return 0; |
618 | } | 616 | } |
619 | 617 | ||
diff --git a/drivers/tty/serial/sunsab.c b/drivers/tty/serial/sunsab.c index a422c8b55a47..5d6136b2a04a 100644 --- a/drivers/tty/serial/sunsab.c +++ b/drivers/tty/serial/sunsab.c | |||
@@ -1037,7 +1037,7 @@ static int sab_probe(struct platform_device *op) | |||
1037 | if (err) | 1037 | if (err) |
1038 | goto out3; | 1038 | goto out3; |
1039 | 1039 | ||
1040 | dev_set_drvdata(&op->dev, &up[0]); | 1040 | platform_set_drvdata(op, &up[0]); |
1041 | 1041 | ||
1042 | inst++; | 1042 | inst++; |
1043 | 1043 | ||
@@ -1059,7 +1059,7 @@ out: | |||
1059 | 1059 | ||
1060 | static int sab_remove(struct platform_device *op) | 1060 | static int sab_remove(struct platform_device *op) |
1061 | { | 1061 | { |
1062 | struct uart_sunsab_port *up = dev_get_drvdata(&op->dev); | 1062 | struct uart_sunsab_port *up = platform_get_drvdata(op); |
1063 | 1063 | ||
1064 | uart_remove_one_port(&sunsab_reg, &up[1].port); | 1064 | uart_remove_one_port(&sunsab_reg, &up[1].port); |
1065 | uart_remove_one_port(&sunsab_reg, &up[0].port); | 1065 | uart_remove_one_port(&sunsab_reg, &up[0].port); |
@@ -1070,8 +1070,6 @@ static int sab_remove(struct platform_device *op) | |||
1070 | up[0].port.membase, | 1070 | up[0].port.membase, |
1071 | sizeof(union sab82532_async_regs)); | 1071 | sizeof(union sab82532_async_regs)); |
1072 | 1072 | ||
1073 | dev_set_drvdata(&op->dev, NULL); | ||
1074 | |||
1075 | return 0; | 1073 | return 0; |
1076 | } | 1074 | } |
1077 | 1075 | ||
diff --git a/drivers/tty/serial/sunsu.c b/drivers/tty/serial/sunsu.c index 0d8465728473..699cc1b5f6aa 100644 --- a/drivers/tty/serial/sunsu.c +++ b/drivers/tty/serial/sunsu.c | |||
@@ -1454,7 +1454,7 @@ static int su_probe(struct platform_device *op) | |||
1454 | kfree(up); | 1454 | kfree(up); |
1455 | return err; | 1455 | return err; |
1456 | } | 1456 | } |
1457 | dev_set_drvdata(&op->dev, up); | 1457 | platform_set_drvdata(op, up); |
1458 | 1458 | ||
1459 | nr_inst++; | 1459 | nr_inst++; |
1460 | 1460 | ||
@@ -1483,7 +1483,7 @@ static int su_probe(struct platform_device *op) | |||
1483 | if (err) | 1483 | if (err) |
1484 | goto out_unmap; | 1484 | goto out_unmap; |
1485 | 1485 | ||
1486 | dev_set_drvdata(&op->dev, up); | 1486 | platform_set_drvdata(op, up); |
1487 | 1487 | ||
1488 | nr_inst++; | 1488 | nr_inst++; |
1489 | 1489 | ||
@@ -1496,7 +1496,7 @@ out_unmap: | |||
1496 | 1496 | ||
1497 | static int su_remove(struct platform_device *op) | 1497 | static int su_remove(struct platform_device *op) |
1498 | { | 1498 | { |
1499 | struct uart_sunsu_port *up = dev_get_drvdata(&op->dev); | 1499 | struct uart_sunsu_port *up = platform_get_drvdata(op); |
1500 | bool kbdms = false; | 1500 | bool kbdms = false; |
1501 | 1501 | ||
1502 | if (up->su_type == SU_PORT_MS || | 1502 | if (up->su_type == SU_PORT_MS || |
@@ -1516,8 +1516,6 @@ static int su_remove(struct platform_device *op) | |||
1516 | if (kbdms) | 1516 | if (kbdms) |
1517 | kfree(up); | 1517 | kfree(up); |
1518 | 1518 | ||
1519 | dev_set_drvdata(&op->dev, NULL); | ||
1520 | |||
1521 | return 0; | 1519 | return 0; |
1522 | } | 1520 | } |
1523 | 1521 | ||
diff --git a/drivers/tty/serial/sunzilog.c b/drivers/tty/serial/sunzilog.c index 813ef8eb8eff..135a15203532 100644 --- a/drivers/tty/serial/sunzilog.c +++ b/drivers/tty/serial/sunzilog.c | |||
@@ -1495,7 +1495,7 @@ static int zs_probe(struct platform_device *op) | |||
1495 | kbm_inst++; | 1495 | kbm_inst++; |
1496 | } | 1496 | } |
1497 | 1497 | ||
1498 | dev_set_drvdata(&op->dev, &up[0]); | 1498 | platform_set_drvdata(op, &up[0]); |
1499 | 1499 | ||
1500 | return 0; | 1500 | return 0; |
1501 | } | 1501 | } |
@@ -1512,7 +1512,7 @@ static void zs_remove_one(struct uart_sunzilog_port *up) | |||
1512 | 1512 | ||
1513 | static int zs_remove(struct platform_device *op) | 1513 | static int zs_remove(struct platform_device *op) |
1514 | { | 1514 | { |
1515 | struct uart_sunzilog_port *up = dev_get_drvdata(&op->dev); | 1515 | struct uart_sunzilog_port *up = platform_get_drvdata(op); |
1516 | struct zilog_layout __iomem *regs; | 1516 | struct zilog_layout __iomem *regs; |
1517 | 1517 | ||
1518 | zs_remove_one(&up[0]); | 1518 | zs_remove_one(&up[0]); |
@@ -1521,8 +1521,6 @@ static int zs_remove(struct platform_device *op) | |||
1521 | regs = sunzilog_chip_regs[up[0].port.line / 2]; | 1521 | regs = sunzilog_chip_regs[up[0].port.line / 2]; |
1522 | of_iounmap(&op->resource[0], regs, sizeof(struct zilog_layout)); | 1522 | of_iounmap(&op->resource[0], regs, sizeof(struct zilog_layout)); |
1523 | 1523 | ||
1524 | dev_set_drvdata(&op->dev, NULL); | ||
1525 | |||
1526 | return 0; | 1524 | return 0; |
1527 | } | 1525 | } |
1528 | 1526 | ||
diff --git a/drivers/tty/serial/ucc_uart.c b/drivers/tty/serial/ucc_uart.c index 7355303dad99..88317482b81f 100644 --- a/drivers/tty/serial/ucc_uart.c +++ b/drivers/tty/serial/ucc_uart.c | |||
@@ -1451,7 +1451,7 @@ static int ucc_uart_probe(struct platform_device *ofdev) | |||
1451 | goto out_np; | 1451 | goto out_np; |
1452 | } | 1452 | } |
1453 | 1453 | ||
1454 | dev_set_drvdata(&ofdev->dev, qe_port); | 1454 | platform_set_drvdata(ofdev, qe_port); |
1455 | 1455 | ||
1456 | dev_info(&ofdev->dev, "UCC%u assigned to /dev/ttyQE%u\n", | 1456 | dev_info(&ofdev->dev, "UCC%u assigned to /dev/ttyQE%u\n", |
1457 | qe_port->ucc_num + 1, qe_port->port.line); | 1457 | qe_port->ucc_num + 1, qe_port->port.line); |
@@ -1471,13 +1471,12 @@ out_free: | |||
1471 | 1471 | ||
1472 | static int ucc_uart_remove(struct platform_device *ofdev) | 1472 | static int ucc_uart_remove(struct platform_device *ofdev) |
1473 | { | 1473 | { |
1474 | struct uart_qe_port *qe_port = dev_get_drvdata(&ofdev->dev); | 1474 | struct uart_qe_port *qe_port = platform_get_drvdata(ofdev); |
1475 | 1475 | ||
1476 | dev_info(&ofdev->dev, "removing /dev/ttyQE%u\n", qe_port->port.line); | 1476 | dev_info(&ofdev->dev, "removing /dev/ttyQE%u\n", qe_port->port.line); |
1477 | 1477 | ||
1478 | uart_remove_one_port(&ucc_uart_driver, &qe_port->port); | 1478 | uart_remove_one_port(&ucc_uart_driver, &qe_port->port); |
1479 | 1479 | ||
1480 | dev_set_drvdata(&ofdev->dev, NULL); | ||
1481 | kfree(qe_port); | 1480 | kfree(qe_port); |
1482 | 1481 | ||
1483 | return 0; | 1482 | return 0; |
@@ -1518,9 +1517,11 @@ static int __init ucc_uart_init(void) | |||
1518 | } | 1517 | } |
1519 | 1518 | ||
1520 | ret = platform_driver_register(&ucc_uart_of_driver); | 1519 | ret = platform_driver_register(&ucc_uart_of_driver); |
1521 | if (ret) | 1520 | if (ret) { |
1522 | printk(KERN_ERR | 1521 | printk(KERN_ERR |
1523 | "ucc-uart: could not register platform driver\n"); | 1522 | "ucc-uart: could not register platform driver\n"); |
1523 | uart_unregister_driver(&ucc_uart_driver); | ||
1524 | } | ||
1524 | 1525 | ||
1525 | return ret; | 1526 | return ret; |
1526 | } | 1527 | } |
diff --git a/drivers/tty/serial/vt8500_serial.c b/drivers/tty/serial/vt8500_serial.c index 1a8bc2275ea4..48af43de3467 100644 --- a/drivers/tty/serial/vt8500_serial.c +++ b/drivers/tty/serial/vt8500_serial.c | |||
@@ -648,7 +648,7 @@ static struct platform_driver vt8500_platform_driver = { | |||
648 | .driver = { | 648 | .driver = { |
649 | .name = "vt8500_serial", | 649 | .name = "vt8500_serial", |
650 | .owner = THIS_MODULE, | 650 | .owner = THIS_MODULE, |
651 | .of_match_table = of_match_ptr(wmt_dt_ids), | 651 | .of_match_table = wmt_dt_ids, |
652 | }, | 652 | }, |
653 | }; | 653 | }; |
654 | 654 | ||
diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 4e5c77834c50..6c9174530422 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c | |||
@@ -974,12 +974,11 @@ static int xuartps_probe(struct platform_device *pdev) | |||
974 | port->dev = &pdev->dev; | 974 | port->dev = &pdev->dev; |
975 | port->uartclk = clk_get_rate(clk); | 975 | port->uartclk = clk_get_rate(clk); |
976 | port->private_data = clk; | 976 | port->private_data = clk; |
977 | dev_set_drvdata(&pdev->dev, port); | 977 | platform_set_drvdata(pdev, port); |
978 | rc = uart_add_one_port(&xuartps_uart_driver, port); | 978 | rc = uart_add_one_port(&xuartps_uart_driver, port); |
979 | if (rc) { | 979 | if (rc) { |
980 | dev_err(&pdev->dev, | 980 | dev_err(&pdev->dev, |
981 | "uart_add_one_port() failed; err=%i\n", rc); | 981 | "uart_add_one_port() failed; err=%i\n", rc); |
982 | dev_set_drvdata(&pdev->dev, NULL); | ||
983 | return rc; | 982 | return rc; |
984 | } | 983 | } |
985 | return 0; | 984 | return 0; |
@@ -994,46 +993,17 @@ static int xuartps_probe(struct platform_device *pdev) | |||
994 | **/ | 993 | **/ |
995 | static int xuartps_remove(struct platform_device *pdev) | 994 | static int xuartps_remove(struct platform_device *pdev) |
996 | { | 995 | { |
997 | struct uart_port *port = dev_get_drvdata(&pdev->dev); | 996 | struct uart_port *port = platform_get_drvdata(pdev); |
998 | struct clk *clk = port->private_data; | 997 | struct clk *clk = port->private_data; |
999 | int rc; | 998 | int rc; |
1000 | 999 | ||
1001 | /* Remove the xuartps port from the serial core */ | 1000 | /* Remove the xuartps port from the serial core */ |
1002 | rc = uart_remove_one_port(&xuartps_uart_driver, port); | 1001 | rc = uart_remove_one_port(&xuartps_uart_driver, port); |
1003 | dev_set_drvdata(&pdev->dev, NULL); | ||
1004 | port->mapbase = 0; | 1002 | port->mapbase = 0; |
1005 | clk_disable_unprepare(clk); | 1003 | clk_disable_unprepare(clk); |
1006 | return rc; | 1004 | return rc; |
1007 | } | 1005 | } |
1008 | 1006 | ||
1009 | /** | ||
1010 | * xuartps_suspend - suspend event | ||
1011 | * @pdev: Pointer to the platform device structure | ||
1012 | * @state: State of the device | ||
1013 | * | ||
1014 | * Returns 0 | ||
1015 | **/ | ||
1016 | static int xuartps_suspend(struct platform_device *pdev, pm_message_t state) | ||
1017 | { | ||
1018 | /* Call the API provided in serial_core.c file which handles | ||
1019 | * the suspend. | ||
1020 | */ | ||
1021 | uart_suspend_port(&xuartps_uart_driver, &xuartps_port[pdev->id]); | ||
1022 | return 0; | ||
1023 | } | ||
1024 | |||
1025 | /** | ||
1026 | * xuartps_resume - Resume after a previous suspend | ||
1027 | * @pdev: Pointer to the platform device structure | ||
1028 | * | ||
1029 | * Returns 0 | ||
1030 | **/ | ||
1031 | static int xuartps_resume(struct platform_device *pdev) | ||
1032 | { | ||
1033 | uart_resume_port(&xuartps_uart_driver, &xuartps_port[pdev->id]); | ||
1034 | return 0; | ||
1035 | } | ||
1036 | |||
1037 | /* Match table for of_platform binding */ | 1007 | /* Match table for of_platform binding */ |
1038 | static struct of_device_id xuartps_of_match[] = { | 1008 | static struct of_device_id xuartps_of_match[] = { |
1039 | { .compatible = "xlnx,xuartps", }, | 1009 | { .compatible = "xlnx,xuartps", }, |
@@ -1044,8 +1014,6 @@ MODULE_DEVICE_TABLE(of, xuartps_of_match); | |||
1044 | static struct platform_driver xuartps_platform_driver = { | 1014 | static struct platform_driver xuartps_platform_driver = { |
1045 | .probe = xuartps_probe, /* Probe method */ | 1015 | .probe = xuartps_probe, /* Probe method */ |
1046 | .remove = xuartps_remove, /* Detach method */ | 1016 | .remove = xuartps_remove, /* Detach method */ |
1047 | .suspend = xuartps_suspend, /* Suspend */ | ||
1048 | .resume = xuartps_resume, /* Resume after a suspend */ | ||
1049 | .driver = { | 1017 | .driver = { |
1050 | .owner = THIS_MODULE, | 1018 | .owner = THIS_MODULE, |
1051 | .name = XUARTPS_NAME, /* Driver name */ | 1019 | .name = XUARTPS_NAME, /* Driver name */ |
diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c index b51c15408ff3..5f68f2cfdfd0 100644 --- a/drivers/tty/sysrq.c +++ b/drivers/tty/sysrq.c | |||
@@ -932,7 +932,7 @@ static int sysrq_reset_seq_param_set(const char *buffer, | |||
932 | unsigned long val; | 932 | unsigned long val; |
933 | int error; | 933 | int error; |
934 | 934 | ||
935 | error = strict_strtoul(buffer, 0, &val); | 935 | error = kstrtoul(buffer, 0, &val); |
936 | if (error < 0) | 936 | if (error < 0) |
937 | return error; | 937 | return error; |
938 | 938 | ||
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 6464029e4860..366af832794b 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c | |||
@@ -1618,6 +1618,8 @@ static void release_tty(struct tty_struct *tty, int idx) | |||
1618 | tty_free_termios(tty); | 1618 | tty_free_termios(tty); |
1619 | tty_driver_remove_tty(tty->driver, tty); | 1619 | tty_driver_remove_tty(tty->driver, tty); |
1620 | tty->port->itty = NULL; | 1620 | tty->port->itty = NULL; |
1621 | if (tty->link) | ||
1622 | tty->link->port->itty = NULL; | ||
1621 | cancel_work_sync(&tty->port->buf.work); | 1623 | cancel_work_sync(&tty->port->buf.work); |
1622 | 1624 | ||
1623 | if (tty->link) | 1625 | if (tty->link) |
@@ -2138,6 +2140,7 @@ static unsigned int tty_poll(struct file *filp, poll_table *wait) | |||
2138 | static int __tty_fasync(int fd, struct file *filp, int on) | 2140 | static int __tty_fasync(int fd, struct file *filp, int on) |
2139 | { | 2141 | { |
2140 | struct tty_struct *tty = file_tty(filp); | 2142 | struct tty_struct *tty = file_tty(filp); |
2143 | struct tty_ldisc *ldisc; | ||
2141 | unsigned long flags; | 2144 | unsigned long flags; |
2142 | int retval = 0; | 2145 | int retval = 0; |
2143 | 2146 | ||
@@ -2148,11 +2151,17 @@ static int __tty_fasync(int fd, struct file *filp, int on) | |||
2148 | if (retval <= 0) | 2151 | if (retval <= 0) |
2149 | goto out; | 2152 | goto out; |
2150 | 2153 | ||
2154 | ldisc = tty_ldisc_ref(tty); | ||
2155 | if (ldisc) { | ||
2156 | if (ldisc->ops->fasync) | ||
2157 | ldisc->ops->fasync(tty, on); | ||
2158 | tty_ldisc_deref(ldisc); | ||
2159 | } | ||
2160 | |||
2151 | if (on) { | 2161 | if (on) { |
2152 | enum pid_type type; | 2162 | enum pid_type type; |
2153 | struct pid *pid; | 2163 | struct pid *pid; |
2154 | if (!waitqueue_active(&tty->read_wait)) | 2164 | |
2155 | tty->minimum_to_wake = 1; | ||
2156 | spin_lock_irqsave(&tty->ctrl_lock, flags); | 2165 | spin_lock_irqsave(&tty->ctrl_lock, flags); |
2157 | if (tty->pgrp) { | 2166 | if (tty->pgrp) { |
2158 | pid = tty->pgrp; | 2167 | pid = tty->pgrp; |
@@ -2165,13 +2174,7 @@ static int __tty_fasync(int fd, struct file *filp, int on) | |||
2165 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); | 2174 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); |
2166 | retval = __f_setown(filp, pid, type, 0); | 2175 | retval = __f_setown(filp, pid, type, 0); |
2167 | put_pid(pid); | 2176 | put_pid(pid); |
2168 | if (retval) | ||
2169 | goto out; | ||
2170 | } else { | ||
2171 | if (!tty->fasync && !waitqueue_active(&tty->read_wait)) | ||
2172 | tty->minimum_to_wake = N_TTY_BUF_SIZE; | ||
2173 | } | 2177 | } |
2174 | retval = 0; | ||
2175 | out: | 2178 | out: |
2176 | return retval; | 2179 | return retval; |
2177 | } | 2180 | } |
diff --git a/drivers/tty/tty_ldsem.c b/drivers/tty/tty_ldsem.c new file mode 100644 index 000000000000..22fad8ad5ac2 --- /dev/null +++ b/drivers/tty/tty_ldsem.c | |||
@@ -0,0 +1,453 @@ | |||
1 | /* | ||
2 | * Ldisc rw semaphore | ||
3 | * | ||
4 | * The ldisc semaphore is semantically a rw_semaphore but which enforces | ||
5 | * an alternate policy, namely: | ||
6 | * 1) Supports lock wait timeouts | ||
7 | * 2) Write waiter has priority | ||
8 | * 3) Downgrading is not supported | ||
9 | * | ||
10 | * Implementation notes: | ||
11 | * 1) Upper half of semaphore count is a wait count (differs from rwsem | ||
12 | * in that rwsem normalizes the upper half to the wait bias) | ||
13 | * 2) Lacks overflow checking | ||
14 | * | ||
15 | * The generic counting was copied and modified from include/asm-generic/rwsem.h | ||
16 | * by Paul Mackerras <paulus@samba.org>. | ||
17 | * | ||
18 | * The scheduling policy was copied and modified from lib/rwsem.c | ||
19 | * Written by David Howells (dhowells@redhat.com). | ||
20 | * | ||
21 | * This implementation incorporates the write lock stealing work of | ||
22 | * Michel Lespinasse <walken@google.com>. | ||
23 | * | ||
24 | * Copyright (C) 2013 Peter Hurley <peter@hurleysoftware.com> | ||
25 | * | ||
26 | * This file may be redistributed under the terms of the GNU General Public | ||
27 | * License v2. | ||
28 | */ | ||
29 | |||
30 | #include <linux/list.h> | ||
31 | #include <linux/spinlock.h> | ||
32 | #include <linux/atomic.h> | ||
33 | #include <linux/tty.h> | ||
34 | #include <linux/sched.h> | ||
35 | |||
36 | |||
37 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
38 | # define __acq(l, s, t, r, c, n, i) \ | ||
39 | lock_acquire(&(l)->dep_map, s, t, r, c, n, i) | ||
40 | # define __rel(l, n, i) \ | ||
41 | lock_release(&(l)->dep_map, n, i) | ||
42 | # ifdef CONFIG_PROVE_LOCKING | ||
43 | # define lockdep_acquire(l, s, t, i) __acq(l, s, t, 0, 2, NULL, i) | ||
44 | # define lockdep_acquire_nest(l, s, t, n, i) __acq(l, s, t, 0, 2, n, i) | ||
45 | # define lockdep_acquire_read(l, s, t, i) __acq(l, s, t, 1, 2, NULL, i) | ||
46 | # define lockdep_release(l, n, i) __rel(l, n, i) | ||
47 | # else | ||
48 | # define lockdep_acquire(l, s, t, i) __acq(l, s, t, 0, 1, NULL, i) | ||
49 | # define lockdep_acquire_nest(l, s, t, n, i) __acq(l, s, t, 0, 1, n, i) | ||
50 | # define lockdep_acquire_read(l, s, t, i) __acq(l, s, t, 1, 1, NULL, i) | ||
51 | # define lockdep_release(l, n, i) __rel(l, n, i) | ||
52 | # endif | ||
53 | #else | ||
54 | # define lockdep_acquire(l, s, t, i) do { } while (0) | ||
55 | # define lockdep_acquire_nest(l, s, t, n, i) do { } while (0) | ||
56 | # define lockdep_acquire_read(l, s, t, i) do { } while (0) | ||
57 | # define lockdep_release(l, n, i) do { } while (0) | ||
58 | #endif | ||
59 | |||
60 | #ifdef CONFIG_LOCK_STAT | ||
61 | # define lock_stat(_lock, stat) lock_##stat(&(_lock)->dep_map, _RET_IP_) | ||
62 | #else | ||
63 | # define lock_stat(_lock, stat) do { } while (0) | ||
64 | #endif | ||
65 | |||
66 | |||
67 | #if BITS_PER_LONG == 64 | ||
68 | # define LDSEM_ACTIVE_MASK 0xffffffffL | ||
69 | #else | ||
70 | # define LDSEM_ACTIVE_MASK 0x0000ffffL | ||
71 | #endif | ||
72 | |||
73 | #define LDSEM_UNLOCKED 0L | ||
74 | #define LDSEM_ACTIVE_BIAS 1L | ||
75 | #define LDSEM_WAIT_BIAS (-LDSEM_ACTIVE_MASK-1) | ||
76 | #define LDSEM_READ_BIAS LDSEM_ACTIVE_BIAS | ||
77 | #define LDSEM_WRITE_BIAS (LDSEM_WAIT_BIAS + LDSEM_ACTIVE_BIAS) | ||
78 | |||
79 | struct ldsem_waiter { | ||
80 | struct list_head list; | ||
81 | struct task_struct *task; | ||
82 | }; | ||
83 | |||
84 | static inline long ldsem_atomic_update(long delta, struct ld_semaphore *sem) | ||
85 | { | ||
86 | return atomic_long_add_return(delta, (atomic_long_t *)&sem->count); | ||
87 | } | ||
88 | |||
89 | static inline int ldsem_cmpxchg(long *old, long new, struct ld_semaphore *sem) | ||
90 | { | ||
91 | long tmp = *old; | ||
92 | *old = atomic_long_cmpxchg(&sem->count, *old, new); | ||
93 | return *old == tmp; | ||
94 | } | ||
95 | |||
96 | /* | ||
97 | * Initialize an ldsem: | ||
98 | */ | ||
99 | void __init_ldsem(struct ld_semaphore *sem, const char *name, | ||
100 | struct lock_class_key *key) | ||
101 | { | ||
102 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
103 | /* | ||
104 | * Make sure we are not reinitializing a held semaphore: | ||
105 | */ | ||
106 | debug_check_no_locks_freed((void *)sem, sizeof(*sem)); | ||
107 | lockdep_init_map(&sem->dep_map, name, key, 0); | ||
108 | #endif | ||
109 | sem->count = LDSEM_UNLOCKED; | ||
110 | sem->wait_readers = 0; | ||
111 | raw_spin_lock_init(&sem->wait_lock); | ||
112 | INIT_LIST_HEAD(&sem->read_wait); | ||
113 | INIT_LIST_HEAD(&sem->write_wait); | ||
114 | } | ||
115 | |||
116 | static void __ldsem_wake_readers(struct ld_semaphore *sem) | ||
117 | { | ||
118 | struct ldsem_waiter *waiter, *next; | ||
119 | struct task_struct *tsk; | ||
120 | long adjust, count; | ||
121 | |||
122 | /* Try to grant read locks to all readers on the read wait list. | ||
123 | * Note the 'active part' of the count is incremented by | ||
124 | * the number of readers before waking any processes up. | ||
125 | */ | ||
126 | adjust = sem->wait_readers * (LDSEM_ACTIVE_BIAS - LDSEM_WAIT_BIAS); | ||
127 | count = ldsem_atomic_update(adjust, sem); | ||
128 | do { | ||
129 | if (count > 0) | ||
130 | break; | ||
131 | if (ldsem_cmpxchg(&count, count - adjust, sem)) | ||
132 | return; | ||
133 | } while (1); | ||
134 | |||
135 | list_for_each_entry_safe(waiter, next, &sem->read_wait, list) { | ||
136 | tsk = waiter->task; | ||
137 | smp_mb(); | ||
138 | waiter->task = NULL; | ||
139 | wake_up_process(tsk); | ||
140 | put_task_struct(tsk); | ||
141 | } | ||
142 | INIT_LIST_HEAD(&sem->read_wait); | ||
143 | sem->wait_readers = 0; | ||
144 | } | ||
145 | |||
146 | static inline int writer_trylock(struct ld_semaphore *sem) | ||
147 | { | ||
148 | /* only wake this writer if the active part of the count can be | ||
149 | * transitioned from 0 -> 1 | ||
150 | */ | ||
151 | long count = ldsem_atomic_update(LDSEM_ACTIVE_BIAS, sem); | ||
152 | do { | ||
153 | if ((count & LDSEM_ACTIVE_MASK) == LDSEM_ACTIVE_BIAS) | ||
154 | return 1; | ||
155 | if (ldsem_cmpxchg(&count, count - LDSEM_ACTIVE_BIAS, sem)) | ||
156 | return 0; | ||
157 | } while (1); | ||
158 | } | ||
159 | |||
160 | static void __ldsem_wake_writer(struct ld_semaphore *sem) | ||
161 | { | ||
162 | struct ldsem_waiter *waiter; | ||
163 | |||
164 | waiter = list_entry(sem->write_wait.next, struct ldsem_waiter, list); | ||
165 | wake_up_process(waiter->task); | ||
166 | } | ||
167 | |||
168 | /* | ||
169 | * handle the lock release when processes blocked on it that can now run | ||
170 | * - if we come here from up_xxxx(), then: | ||
171 | * - the 'active part' of count (&0x0000ffff) reached 0 (but may have changed) | ||
172 | * - the 'waiting part' of count (&0xffff0000) is -ve (and will still be so) | ||
173 | * - the spinlock must be held by the caller | ||
174 | * - woken process blocks are discarded from the list after having task zeroed | ||
175 | */ | ||
176 | static void __ldsem_wake(struct ld_semaphore *sem) | ||
177 | { | ||
178 | if (!list_empty(&sem->write_wait)) | ||
179 | __ldsem_wake_writer(sem); | ||
180 | else if (!list_empty(&sem->read_wait)) | ||
181 | __ldsem_wake_readers(sem); | ||
182 | } | ||
183 | |||
184 | static void ldsem_wake(struct ld_semaphore *sem) | ||
185 | { | ||
186 | unsigned long flags; | ||
187 | |||
188 | raw_spin_lock_irqsave(&sem->wait_lock, flags); | ||
189 | __ldsem_wake(sem); | ||
190 | raw_spin_unlock_irqrestore(&sem->wait_lock, flags); | ||
191 | } | ||
192 | |||
193 | /* | ||
194 | * wait for the read lock to be granted | ||
195 | */ | ||
196 | static struct ld_semaphore __sched * | ||
197 | down_read_failed(struct ld_semaphore *sem, long count, long timeout) | ||
198 | { | ||
199 | struct ldsem_waiter waiter; | ||
200 | struct task_struct *tsk = current; | ||
201 | long adjust = -LDSEM_ACTIVE_BIAS + LDSEM_WAIT_BIAS; | ||
202 | |||
203 | /* set up my own style of waitqueue */ | ||
204 | raw_spin_lock_irq(&sem->wait_lock); | ||
205 | |||
206 | /* Try to reverse the lock attempt but if the count has changed | ||
207 | * so that reversing fails, check if there are are no waiters, | ||
208 | * and early-out if not */ | ||
209 | do { | ||
210 | if (ldsem_cmpxchg(&count, count + adjust, sem)) | ||
211 | break; | ||
212 | if (count > 0) { | ||
213 | raw_spin_unlock_irq(&sem->wait_lock); | ||
214 | return sem; | ||
215 | } | ||
216 | } while (1); | ||
217 | |||
218 | list_add_tail(&waiter.list, &sem->read_wait); | ||
219 | sem->wait_readers++; | ||
220 | |||
221 | waiter.task = tsk; | ||
222 | get_task_struct(tsk); | ||
223 | |||
224 | /* if there are no active locks, wake the new lock owner(s) */ | ||
225 | if ((count & LDSEM_ACTIVE_MASK) == 0) | ||
226 | __ldsem_wake(sem); | ||
227 | |||
228 | raw_spin_unlock_irq(&sem->wait_lock); | ||
229 | |||
230 | /* wait to be given the lock */ | ||
231 | for (;;) { | ||
232 | set_task_state(tsk, TASK_UNINTERRUPTIBLE); | ||
233 | |||
234 | if (!waiter.task) | ||
235 | break; | ||
236 | if (!timeout) | ||
237 | break; | ||
238 | timeout = schedule_timeout(timeout); | ||
239 | } | ||
240 | |||
241 | __set_task_state(tsk, TASK_RUNNING); | ||
242 | |||
243 | if (!timeout) { | ||
244 | /* lock timed out but check if this task was just | ||
245 | * granted lock ownership - if so, pretend there | ||
246 | * was no timeout; otherwise, cleanup lock wait */ | ||
247 | raw_spin_lock_irq(&sem->wait_lock); | ||
248 | if (waiter.task) { | ||
249 | ldsem_atomic_update(-LDSEM_WAIT_BIAS, sem); | ||
250 | list_del(&waiter.list); | ||
251 | raw_spin_unlock_irq(&sem->wait_lock); | ||
252 | put_task_struct(waiter.task); | ||
253 | return NULL; | ||
254 | } | ||
255 | raw_spin_unlock_irq(&sem->wait_lock); | ||
256 | } | ||
257 | |||
258 | return sem; | ||
259 | } | ||
260 | |||
261 | /* | ||
262 | * wait for the write lock to be granted | ||
263 | */ | ||
264 | static struct ld_semaphore __sched * | ||
265 | down_write_failed(struct ld_semaphore *sem, long count, long timeout) | ||
266 | { | ||
267 | struct ldsem_waiter waiter; | ||
268 | struct task_struct *tsk = current; | ||
269 | long adjust = -LDSEM_ACTIVE_BIAS; | ||
270 | int locked = 0; | ||
271 | |||
272 | /* set up my own style of waitqueue */ | ||
273 | raw_spin_lock_irq(&sem->wait_lock); | ||
274 | |||
275 | /* Try to reverse the lock attempt but if the count has changed | ||
276 | * so that reversing fails, check if the lock is now owned, | ||
277 | * and early-out if so */ | ||
278 | do { | ||
279 | if (ldsem_cmpxchg(&count, count + adjust, sem)) | ||
280 | break; | ||
281 | if ((count & LDSEM_ACTIVE_MASK) == LDSEM_ACTIVE_BIAS) { | ||
282 | raw_spin_unlock_irq(&sem->wait_lock); | ||
283 | return sem; | ||
284 | } | ||
285 | } while (1); | ||
286 | |||
287 | list_add_tail(&waiter.list, &sem->write_wait); | ||
288 | |||
289 | waiter.task = tsk; | ||
290 | |||
291 | set_task_state(tsk, TASK_UNINTERRUPTIBLE); | ||
292 | for (;;) { | ||
293 | if (!timeout) | ||
294 | break; | ||
295 | raw_spin_unlock_irq(&sem->wait_lock); | ||
296 | timeout = schedule_timeout(timeout); | ||
297 | raw_spin_lock_irq(&sem->wait_lock); | ||
298 | set_task_state(tsk, TASK_UNINTERRUPTIBLE); | ||
299 | if ((locked = writer_trylock(sem))) | ||
300 | break; | ||
301 | } | ||
302 | |||
303 | if (!locked) | ||
304 | ldsem_atomic_update(-LDSEM_WAIT_BIAS, sem); | ||
305 | list_del(&waiter.list); | ||
306 | raw_spin_unlock_irq(&sem->wait_lock); | ||
307 | |||
308 | __set_task_state(tsk, TASK_RUNNING); | ||
309 | |||
310 | /* lock wait may have timed out */ | ||
311 | if (!locked) | ||
312 | return NULL; | ||
313 | return sem; | ||
314 | } | ||
315 | |||
316 | |||
317 | |||
318 | static inline int __ldsem_down_read_nested(struct ld_semaphore *sem, | ||
319 | int subclass, long timeout) | ||
320 | { | ||
321 | long count; | ||
322 | |||
323 | lockdep_acquire_read(sem, subclass, 0, _RET_IP_); | ||
324 | |||
325 | count = ldsem_atomic_update(LDSEM_READ_BIAS, sem); | ||
326 | if (count <= 0) { | ||
327 | lock_stat(sem, contended); | ||
328 | if (!down_read_failed(sem, count, timeout)) { | ||
329 | lockdep_release(sem, 1, _RET_IP_); | ||
330 | return 0; | ||
331 | } | ||
332 | } | ||
333 | lock_stat(sem, acquired); | ||
334 | return 1; | ||
335 | } | ||
336 | |||
337 | static inline int __ldsem_down_write_nested(struct ld_semaphore *sem, | ||
338 | int subclass, long timeout) | ||
339 | { | ||
340 | long count; | ||
341 | |||
342 | lockdep_acquire(sem, subclass, 0, _RET_IP_); | ||
343 | |||
344 | count = ldsem_atomic_update(LDSEM_WRITE_BIAS, sem); | ||
345 | if ((count & LDSEM_ACTIVE_MASK) != LDSEM_ACTIVE_BIAS) { | ||
346 | lock_stat(sem, contended); | ||
347 | if (!down_write_failed(sem, count, timeout)) { | ||
348 | lockdep_release(sem, 1, _RET_IP_); | ||
349 | return 0; | ||
350 | } | ||
351 | } | ||
352 | lock_stat(sem, acquired); | ||
353 | return 1; | ||
354 | } | ||
355 | |||
356 | |||
357 | /* | ||
358 | * lock for reading -- returns 1 if successful, 0 if timed out | ||
359 | */ | ||
360 | int __sched ldsem_down_read(struct ld_semaphore *sem, long timeout) | ||
361 | { | ||
362 | might_sleep(); | ||
363 | return __ldsem_down_read_nested(sem, 0, timeout); | ||
364 | } | ||
365 | |||
366 | /* | ||
367 | * trylock for reading -- returns 1 if successful, 0 if contention | ||
368 | */ | ||
369 | int ldsem_down_read_trylock(struct ld_semaphore *sem) | ||
370 | { | ||
371 | long count = sem->count; | ||
372 | |||
373 | while (count >= 0) { | ||
374 | if (ldsem_cmpxchg(&count, count + LDSEM_READ_BIAS, sem)) { | ||
375 | lockdep_acquire_read(sem, 0, 1, _RET_IP_); | ||
376 | lock_stat(sem, acquired); | ||
377 | return 1; | ||
378 | } | ||
379 | } | ||
380 | return 0; | ||
381 | } | ||
382 | |||
383 | /* | ||
384 | * lock for writing -- returns 1 if successful, 0 if timed out | ||
385 | */ | ||
386 | int __sched ldsem_down_write(struct ld_semaphore *sem, long timeout) | ||
387 | { | ||
388 | might_sleep(); | ||
389 | return __ldsem_down_write_nested(sem, 0, timeout); | ||
390 | } | ||
391 | |||
392 | /* | ||
393 | * trylock for writing -- returns 1 if successful, 0 if contention | ||
394 | */ | ||
395 | int ldsem_down_write_trylock(struct ld_semaphore *sem) | ||
396 | { | ||
397 | long count = sem->count; | ||
398 | |||
399 | while ((count & LDSEM_ACTIVE_MASK) == 0) { | ||
400 | if (ldsem_cmpxchg(&count, count + LDSEM_WRITE_BIAS, sem)) { | ||
401 | lockdep_acquire(sem, 0, 1, _RET_IP_); | ||
402 | lock_stat(sem, acquired); | ||
403 | return 1; | ||
404 | } | ||
405 | } | ||
406 | return 0; | ||
407 | } | ||
408 | |||
409 | /* | ||
410 | * release a read lock | ||
411 | */ | ||
412 | void ldsem_up_read(struct ld_semaphore *sem) | ||
413 | { | ||
414 | long count; | ||
415 | |||
416 | lockdep_release(sem, 1, _RET_IP_); | ||
417 | |||
418 | count = ldsem_atomic_update(-LDSEM_READ_BIAS, sem); | ||
419 | if (count < 0 && (count & LDSEM_ACTIVE_MASK) == 0) | ||
420 | ldsem_wake(sem); | ||
421 | } | ||
422 | |||
423 | /* | ||
424 | * release a write lock | ||
425 | */ | ||
426 | void ldsem_up_write(struct ld_semaphore *sem) | ||
427 | { | ||
428 | long count; | ||
429 | |||
430 | lockdep_release(sem, 1, _RET_IP_); | ||
431 | |||
432 | count = ldsem_atomic_update(-LDSEM_WRITE_BIAS, sem); | ||
433 | if (count < 0) | ||
434 | ldsem_wake(sem); | ||
435 | } | ||
436 | |||
437 | |||
438 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
439 | |||
440 | int ldsem_down_read_nested(struct ld_semaphore *sem, int subclass, long timeout) | ||
441 | { | ||
442 | might_sleep(); | ||
443 | return __ldsem_down_read_nested(sem, subclass, timeout); | ||
444 | } | ||
445 | |||
446 | int ldsem_down_write_nested(struct ld_semaphore *sem, int subclass, | ||
447 | long timeout) | ||
448 | { | ||
449 | might_sleep(); | ||
450 | return __ldsem_down_write_nested(sem, subclass, timeout); | ||
451 | } | ||
452 | |||
453 | #endif | ||
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 740202d8a5c4..c677829baa8b 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c | |||
@@ -3086,17 +3086,6 @@ err: | |||
3086 | }; | 3086 | }; |
3087 | 3087 | ||
3088 | 3088 | ||
3089 | static int bind_con_driver(const struct consw *csw, int first, int last, | ||
3090 | int deflt) | ||
3091 | { | ||
3092 | int ret; | ||
3093 | |||
3094 | console_lock(); | ||
3095 | ret = do_bind_con_driver(csw, first, last, deflt); | ||
3096 | console_unlock(); | ||
3097 | return ret; | ||
3098 | } | ||
3099 | |||
3100 | #ifdef CONFIG_VT_HW_CONSOLE_BINDING | 3089 | #ifdef CONFIG_VT_HW_CONSOLE_BINDING |
3101 | static int con_is_graphics(const struct consw *csw, int first, int last) | 3090 | static int con_is_graphics(const struct consw *csw, int first, int last) |
3102 | { | 3091 | { |
@@ -3114,34 +3103,6 @@ static int con_is_graphics(const struct consw *csw, int first, int last) | |||
3114 | return retval; | 3103 | return retval; |
3115 | } | 3104 | } |
3116 | 3105 | ||
3117 | /** | ||
3118 | * unbind_con_driver - unbind a console driver | ||
3119 | * @csw: pointer to console driver to unregister | ||
3120 | * @first: first in range of consoles that @csw should be unbound from | ||
3121 | * @last: last in range of consoles that @csw should be unbound from | ||
3122 | * @deflt: should next bound console driver be default after @csw is unbound? | ||
3123 | * | ||
3124 | * To unbind a driver from all possible consoles, pass 0 as @first and | ||
3125 | * %MAX_NR_CONSOLES as @last. | ||
3126 | * | ||
3127 | * @deflt controls whether the console that ends up replacing @csw should be | ||
3128 | * the default console. | ||
3129 | * | ||
3130 | * RETURNS: | ||
3131 | * -ENODEV if @csw isn't a registered console driver or can't be unregistered | ||
3132 | * or 0 on success. | ||
3133 | */ | ||
3134 | int unbind_con_driver(const struct consw *csw, int first, int last, int deflt) | ||
3135 | { | ||
3136 | int retval; | ||
3137 | |||
3138 | console_lock(); | ||
3139 | retval = do_unbind_con_driver(csw, first, last, deflt); | ||
3140 | console_unlock(); | ||
3141 | return retval; | ||
3142 | } | ||
3143 | EXPORT_SYMBOL(unbind_con_driver); | ||
3144 | |||
3145 | /* unlocked version of unbind_con_driver() */ | 3106 | /* unlocked version of unbind_con_driver() */ |
3146 | int do_unbind_con_driver(const struct consw *csw, int first, int last, int deflt) | 3107 | int do_unbind_con_driver(const struct consw *csw, int first, int last, int deflt) |
3147 | { | 3108 | { |
@@ -3262,8 +3223,11 @@ static int vt_bind(struct con_driver *con) | |||
3262 | if (first == 0 && last == MAX_NR_CONSOLES -1) | 3223 | if (first == 0 && last == MAX_NR_CONSOLES -1) |
3263 | deflt = 1; | 3224 | deflt = 1; |
3264 | 3225 | ||
3265 | if (first != -1) | 3226 | if (first != -1) { |
3266 | bind_con_driver(csw, first, last, deflt); | 3227 | console_lock(); |
3228 | do_bind_con_driver(csw, first, last, deflt); | ||
3229 | console_unlock(); | ||
3230 | } | ||
3267 | 3231 | ||
3268 | first = -1; | 3232 | first = -1; |
3269 | last = -1; | 3233 | last = -1; |
@@ -3301,8 +3265,11 @@ static int vt_unbind(struct con_driver *con) | |||
3301 | if (first == 0 && last == MAX_NR_CONSOLES -1) | 3265 | if (first == 0 && last == MAX_NR_CONSOLES -1) |
3302 | deflt = 1; | 3266 | deflt = 1; |
3303 | 3267 | ||
3304 | if (first != -1) | 3268 | if (first != -1) { |
3305 | unbind_con_driver(csw, first, last, deflt); | 3269 | console_lock(); |
3270 | do_unbind_con_driver(csw, first, last, deflt); | ||
3271 | console_unlock(); | ||
3272 | } | ||
3306 | 3273 | ||
3307 | first = -1; | 3274 | first = -1; |
3308 | last = -1; | 3275 | last = -1; |
@@ -3574,29 +3541,9 @@ err: | |||
3574 | return retval; | 3541 | return retval; |
3575 | } | 3542 | } |
3576 | 3543 | ||
3577 | /** | ||
3578 | * register_con_driver - register console driver to console layer | ||
3579 | * @csw: console driver | ||
3580 | * @first: the first console to take over, minimum value is 0 | ||
3581 | * @last: the last console to take over, maximum value is MAX_NR_CONSOLES -1 | ||
3582 | * | ||
3583 | * DESCRIPTION: This function registers a console driver which can later | ||
3584 | * bind to a range of consoles specified by @first and @last. It will | ||
3585 | * also initialize the console driver by calling con_startup(). | ||
3586 | */ | ||
3587 | int register_con_driver(const struct consw *csw, int first, int last) | ||
3588 | { | ||
3589 | int retval; | ||
3590 | |||
3591 | console_lock(); | ||
3592 | retval = do_register_con_driver(csw, first, last); | ||
3593 | console_unlock(); | ||
3594 | return retval; | ||
3595 | } | ||
3596 | EXPORT_SYMBOL(register_con_driver); | ||
3597 | 3544 | ||
3598 | /** | 3545 | /** |
3599 | * unregister_con_driver - unregister console driver from console layer | 3546 | * do_unregister_con_driver - unregister console driver from console layer |
3600 | * @csw: console driver | 3547 | * @csw: console driver |
3601 | * | 3548 | * |
3602 | * DESCRIPTION: All drivers that registers to the console layer must | 3549 | * DESCRIPTION: All drivers that registers to the console layer must |
@@ -3606,17 +3553,6 @@ EXPORT_SYMBOL(register_con_driver); | |||
3606 | * | 3553 | * |
3607 | * The driver must unbind first prior to unregistration. | 3554 | * The driver must unbind first prior to unregistration. |
3608 | */ | 3555 | */ |
3609 | int unregister_con_driver(const struct consw *csw) | ||
3610 | { | ||
3611 | int retval; | ||
3612 | |||
3613 | console_lock(); | ||
3614 | retval = do_unregister_con_driver(csw); | ||
3615 | console_unlock(); | ||
3616 | return retval; | ||
3617 | } | ||
3618 | EXPORT_SYMBOL(unregister_con_driver); | ||
3619 | |||
3620 | int do_unregister_con_driver(const struct consw *csw) | 3556 | int do_unregister_con_driver(const struct consw *csw) |
3621 | { | 3557 | { |
3622 | int i, retval = -ENODEV; | 3558 | int i, retval = -ENODEV; |
@@ -3654,7 +3590,7 @@ EXPORT_SYMBOL_GPL(do_unregister_con_driver); | |||
3654 | * when a driver wants to take over some existing consoles | 3590 | * when a driver wants to take over some existing consoles |
3655 | * and become default driver for newly opened ones. | 3591 | * and become default driver for newly opened ones. |
3656 | * | 3592 | * |
3657 | * take_over_console is basically a register followed by unbind | 3593 | * do_take_over_console is basically a register followed by unbind |
3658 | */ | 3594 | */ |
3659 | int do_take_over_console(const struct consw *csw, int first, int last, int deflt) | 3595 | int do_take_over_console(const struct consw *csw, int first, int last, int deflt) |
3660 | { | 3596 | { |
@@ -3675,30 +3611,6 @@ int do_take_over_console(const struct consw *csw, int first, int last, int deflt | |||
3675 | } | 3611 | } |
3676 | EXPORT_SYMBOL_GPL(do_take_over_console); | 3612 | EXPORT_SYMBOL_GPL(do_take_over_console); |
3677 | 3613 | ||
3678 | /* | ||
3679 | * If we support more console drivers, this function is used | ||
3680 | * when a driver wants to take over some existing consoles | ||
3681 | * and become default driver for newly opened ones. | ||
3682 | * | ||
3683 | * take_over_console is basically a register followed by unbind | ||
3684 | */ | ||
3685 | int take_over_console(const struct consw *csw, int first, int last, int deflt) | ||
3686 | { | ||
3687 | int err; | ||
3688 | |||
3689 | err = register_con_driver(csw, first, last); | ||
3690 | /* | ||
3691 | * If we get an busy error we still want to bind the console driver | ||
3692 | * and return success, as we may have unbound the console driver | ||
3693 | * but not unregistered it. | ||
3694 | */ | ||
3695 | if (err == -EBUSY) | ||
3696 | err = 0; | ||
3697 | if (!err) | ||
3698 | bind_con_driver(csw, first, last, deflt); | ||
3699 | |||
3700 | return err; | ||
3701 | } | ||
3702 | 3614 | ||
3703 | /* | 3615 | /* |
3704 | * give_up_console is a wrapper to unregister_con_driver. It will only | 3616 | * give_up_console is a wrapper to unregister_con_driver. It will only |
@@ -3706,7 +3618,9 @@ int take_over_console(const struct consw *csw, int first, int last, int deflt) | |||
3706 | */ | 3618 | */ |
3707 | void give_up_console(const struct consw *csw) | 3619 | void give_up_console(const struct consw *csw) |
3708 | { | 3620 | { |
3709 | unregister_con_driver(csw); | 3621 | console_lock(); |
3622 | do_unregister_con_driver(csw); | ||
3623 | console_unlock(); | ||
3710 | } | 3624 | } |
3711 | 3625 | ||
3712 | static int __init vtconsole_class_init(void) | 3626 | static int __init vtconsole_class_init(void) |
@@ -4262,6 +4176,5 @@ EXPORT_SYMBOL(console_blanked); | |||
4262 | EXPORT_SYMBOL(vc_cons); | 4176 | EXPORT_SYMBOL(vc_cons); |
4263 | EXPORT_SYMBOL(global_cursor_default); | 4177 | EXPORT_SYMBOL(global_cursor_default); |
4264 | #ifndef VT_SINGLE_DRIVER | 4178 | #ifndef VT_SINGLE_DRIVER |
4265 | EXPORT_SYMBOL(take_over_console); | ||
4266 | EXPORT_SYMBOL(give_up_console); | 4179 | EXPORT_SYMBOL(give_up_console); |
4267 | #endif | 4180 | #endif |
diff --git a/drivers/usb/misc/sisusbvga/sisusb_con.c b/drivers/usb/misc/sisusbvga/sisusb_con.c index 411e605f448a..a638c4e9a947 100644 --- a/drivers/usb/misc/sisusbvga/sisusb_con.c +++ b/drivers/usb/misc/sisusbvga/sisusb_con.c | |||
@@ -208,7 +208,7 @@ sisusbcon_init(struct vc_data *c, int init) | |||
208 | struct sisusb_usb_data *sisusb; | 208 | struct sisusb_usb_data *sisusb; |
209 | int cols, rows; | 209 | int cols, rows; |
210 | 210 | ||
211 | /* This is called by take_over_console(), | 211 | /* This is called by do_take_over_console(), |
212 | * ie by us/under our control. It is | 212 | * ie by us/under our control. It is |
213 | * only called after text mode and fonts | 213 | * only called after text mode and fonts |
214 | * are set up/restored. | 214 | * are set up/restored. |
@@ -273,7 +273,7 @@ sisusbcon_deinit(struct vc_data *c) | |||
273 | struct sisusb_usb_data *sisusb; | 273 | struct sisusb_usb_data *sisusb; |
274 | int i; | 274 | int i; |
275 | 275 | ||
276 | /* This is called by take_over_console() | 276 | /* This is called by do_take_over_console() |
277 | * and others, ie not under our control. | 277 | * and others, ie not under our control. |
278 | */ | 278 | */ |
279 | 279 | ||
@@ -1490,8 +1490,9 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last) | |||
1490 | mutex_unlock(&sisusb->lock); | 1490 | mutex_unlock(&sisusb->lock); |
1491 | 1491 | ||
1492 | /* Now grab the desired console(s) */ | 1492 | /* Now grab the desired console(s) */ |
1493 | ret = take_over_console(&sisusb_con, first - 1, last - 1, 0); | 1493 | console_lock(); |
1494 | 1494 | ret = do_take_over_console(&sisusb_con, first - 1, last - 1, 0); | |
1495 | console_unlock(); | ||
1495 | if (!ret) | 1496 | if (!ret) |
1496 | sisusb->haveconsole = 1; | 1497 | sisusb->haveconsole = 1; |
1497 | else { | 1498 | else { |
@@ -1535,11 +1536,14 @@ sisusb_console_exit(struct sisusb_usb_data *sisusb) | |||
1535 | 1536 | ||
1536 | if (sisusb->haveconsole) { | 1537 | if (sisusb->haveconsole) { |
1537 | for (i = 0; i < MAX_NR_CONSOLES; i++) | 1538 | for (i = 0; i < MAX_NR_CONSOLES; i++) |
1538 | if (sisusb->havethisconsole[i]) | 1539 | if (sisusb->havethisconsole[i]) { |
1539 | take_over_console(&sisusb_dummy_con, i, i, 0); | 1540 | console_lock(); |
1541 | do_take_over_console(&sisusb_dummy_con, i, i, 0); | ||
1542 | console_unlock(); | ||
1540 | /* At this point, con_deinit for all our | 1543 | /* At this point, con_deinit for all our |
1541 | * consoles is executed by take_over_console(). | 1544 | * consoles is executed by do_take_over_console(). |
1542 | */ | 1545 | */ |
1546 | } | ||
1543 | sisusb->haveconsole = 0; | 1547 | sisusb->haveconsole = 0; |
1544 | } | 1548 | } |
1545 | 1549 | ||
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index a92783e480e6..d55b33757465 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c | |||
@@ -556,34 +556,6 @@ static int do_fbcon_takeover(int show_logo) | |||
556 | return err; | 556 | return err; |
557 | } | 557 | } |
558 | 558 | ||
559 | static int fbcon_takeover(int show_logo) | ||
560 | { | ||
561 | int err, i; | ||
562 | |||
563 | if (!num_registered_fb) | ||
564 | return -ENODEV; | ||
565 | |||
566 | if (!show_logo) | ||
567 | logo_shown = FBCON_LOGO_DONTSHOW; | ||
568 | |||
569 | for (i = first_fb_vc; i <= last_fb_vc; i++) | ||
570 | con2fb_map[i] = info_idx; | ||
571 | |||
572 | err = take_over_console(&fb_con, first_fb_vc, last_fb_vc, | ||
573 | fbcon_is_default); | ||
574 | |||
575 | if (err) { | ||
576 | for (i = first_fb_vc; i <= last_fb_vc; i++) { | ||
577 | con2fb_map[i] = -1; | ||
578 | } | ||
579 | info_idx = -1; | ||
580 | } else { | ||
581 | fbcon_has_console_bind = 1; | ||
582 | } | ||
583 | |||
584 | return err; | ||
585 | } | ||
586 | |||
587 | #ifdef MODULE | 559 | #ifdef MODULE |
588 | static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info, | 560 | static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info, |
589 | int cols, int rows, int new_cols, int new_rows) | 561 | int cols, int rows, int new_cols, int new_rows) |
@@ -901,7 +873,7 @@ static int set_con2fb_map(int unit, int newidx, int user) | |||
901 | /* | 873 | /* |
902 | * Low Level Operations | 874 | * Low Level Operations |
903 | */ | 875 | */ |
904 | /* NOTE: fbcon cannot be __init: it may be called from take_over_console later */ | 876 | /* NOTE: fbcon cannot be __init: it may be called from do_take_over_console later */ |
905 | static int var_to_display(struct display *disp, | 877 | static int var_to_display(struct display *disp, |
906 | struct fb_var_screeninfo *var, | 878 | struct fb_var_screeninfo *var, |
907 | struct fb_info *info) | 879 | struct fb_info *info) |
@@ -3543,8 +3515,9 @@ static void fbcon_start(void) | |||
3543 | } | 3515 | } |
3544 | } | 3516 | } |
3545 | 3517 | ||
3518 | do_fbcon_takeover(0); | ||
3546 | console_unlock(); | 3519 | console_unlock(); |
3547 | fbcon_takeover(0); | 3520 | |
3548 | } | 3521 | } |
3549 | } | 3522 | } |
3550 | 3523 | ||
@@ -3648,8 +3621,8 @@ static void __exit fb_console_exit(void) | |||
3648 | fbcon_deinit_device(); | 3621 | fbcon_deinit_device(); |
3649 | device_destroy(fb_class, MKDEV(0, 0)); | 3622 | device_destroy(fb_class, MKDEV(0, 0)); |
3650 | fbcon_exit(); | 3623 | fbcon_exit(); |
3624 | do_unregister_con_driver(&fb_con); | ||
3651 | console_unlock(); | 3625 | console_unlock(); |
3652 | unregister_con_driver(&fb_con); | ||
3653 | } | 3626 | } |
3654 | 3627 | ||
3655 | module_exit(fb_console_exit); | 3628 | module_exit(fb_console_exit); |
diff --git a/drivers/video/console/mdacon.c b/drivers/video/console/mdacon.c index 0b67866cae10..296e94561556 100644 --- a/drivers/video/console/mdacon.c +++ b/drivers/video/console/mdacon.c | |||
@@ -585,10 +585,14 @@ static const struct consw mda_con = { | |||
585 | 585 | ||
586 | int __init mda_console_init(void) | 586 | int __init mda_console_init(void) |
587 | { | 587 | { |
588 | int err; | ||
589 | |||
588 | if (mda_first_vc > mda_last_vc) | 590 | if (mda_first_vc > mda_last_vc) |
589 | return 1; | 591 | return 1; |
590 | 592 | console_lock(); | |
591 | return take_over_console(&mda_con, mda_first_vc-1, mda_last_vc-1, 0); | 593 | err = do_take_over_console(&mda_con, mda_first_vc-1, mda_last_vc-1, 0); |
594 | console_unlock(); | ||
595 | return err; | ||
592 | } | 596 | } |
593 | 597 | ||
594 | static void __exit mda_console_exit(void) | 598 | static void __exit mda_console_exit(void) |
diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c index b05afd03729e..a6ab9299813c 100644 --- a/drivers/video/console/newport_con.c +++ b/drivers/video/console/newport_con.c | |||
@@ -297,7 +297,7 @@ static void newport_exit(void) | |||
297 | newport_set_def_font(i, NULL); | 297 | newport_set_def_font(i, NULL); |
298 | } | 298 | } |
299 | 299 | ||
300 | /* Can't be __init, take_over_console may call it later */ | 300 | /* Can't be __init, do_take_over_console may call it later */ |
301 | static const char *newport_startup(void) | 301 | static const char *newport_startup(void) |
302 | { | 302 | { |
303 | int i; | 303 | int i; |
@@ -746,6 +746,7 @@ static int newport_probe(struct gio_device *dev, | |||
746 | const struct gio_device_id *id) | 746 | const struct gio_device_id *id) |
747 | { | 747 | { |
748 | unsigned long newport_addr; | 748 | unsigned long newport_addr; |
749 | int err; | ||
749 | 750 | ||
750 | if (!dev->resource.start) | 751 | if (!dev->resource.start) |
751 | return -EINVAL; | 752 | return -EINVAL; |
@@ -759,8 +760,10 @@ static int newport_probe(struct gio_device *dev, | |||
759 | 760 | ||
760 | npregs = (struct newport_regs *)/* ioremap cannot fail */ | 761 | npregs = (struct newport_regs *)/* ioremap cannot fail */ |
761 | ioremap(newport_addr, sizeof(struct newport_regs)); | 762 | ioremap(newport_addr, sizeof(struct newport_regs)); |
762 | 763 | console_lock(); | |
763 | return take_over_console(&newport_con, 0, MAX_NR_CONSOLES - 1, 1); | 764 | err = do_take_over_console(&newport_con, 0, MAX_NR_CONSOLES - 1, 1); |
765 | console_unlock(); | ||
766 | return err; | ||
764 | } | 767 | } |
765 | 768 | ||
766 | static void newport_remove(struct gio_device *dev) | 769 | static void newport_remove(struct gio_device *dev) |
diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c index 491c1c1baf4c..5f65ca3d8564 100644 --- a/drivers/video/console/sticon.c +++ b/drivers/video/console/sticon.c | |||
@@ -372,6 +372,7 @@ static const struct consw sti_con = { | |||
372 | 372 | ||
373 | static int __init sticonsole_init(void) | 373 | static int __init sticonsole_init(void) |
374 | { | 374 | { |
375 | int err; | ||
375 | /* already initialized ? */ | 376 | /* already initialized ? */ |
376 | if (sticon_sti) | 377 | if (sticon_sti) |
377 | return 0; | 378 | return 0; |
@@ -382,7 +383,10 @@ static int __init sticonsole_init(void) | |||
382 | 383 | ||
383 | if (conswitchp == &dummy_con) { | 384 | if (conswitchp == &dummy_con) { |
384 | printk(KERN_INFO "sticon: Initializing STI text console.\n"); | 385 | printk(KERN_INFO "sticon: Initializing STI text console.\n"); |
385 | return take_over_console(&sti_con, 0, MAX_NR_CONSOLES - 1, 1); | 386 | console_lock(); |
387 | err = do_take_over_console(&sti_con, 0, MAX_NR_CONSOLES - 1, 1); | ||
388 | console_unlock(); | ||
389 | return err; | ||
386 | } | 390 | } |
387 | return 0; | 391 | return 0; |
388 | } | 392 | } |
diff --git a/include/linux/console.h b/include/linux/console.h index 73bab0f58af5..7571a16bd653 100644 --- a/include/linux/console.h +++ b/include/linux/console.h | |||
@@ -75,10 +75,7 @@ extern const struct consw newport_con; /* SGI Newport console */ | |||
75 | extern const struct consw prom_con; /* SPARC PROM console */ | 75 | extern const struct consw prom_con; /* SPARC PROM console */ |
76 | 76 | ||
77 | int con_is_bound(const struct consw *csw); | 77 | int con_is_bound(const struct consw *csw); |
78 | int register_con_driver(const struct consw *csw, int first, int last); | ||
79 | int unregister_con_driver(const struct consw *csw); | ||
80 | int do_unregister_con_driver(const struct consw *csw); | 78 | int do_unregister_con_driver(const struct consw *csw); |
81 | int take_over_console(const struct consw *sw, int first, int last, int deflt); | ||
82 | int do_take_over_console(const struct consw *sw, int first, int last, int deflt); | 79 | int do_take_over_console(const struct consw *sw, int first, int last, int deflt); |
83 | void give_up_console(const struct consw *sw); | 80 | void give_up_console(const struct consw *sw); |
84 | #ifdef CONFIG_HW_CONSOLE | 81 | #ifdef CONFIG_HW_CONSOLE |
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 87d4bbc773fc..b98291ac7f14 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h | |||
@@ -31,6 +31,13 @@ | |||
31 | #include <linux/sysrq.h> | 31 | #include <linux/sysrq.h> |
32 | #include <uapi/linux/serial_core.h> | 32 | #include <uapi/linux/serial_core.h> |
33 | 33 | ||
34 | #ifdef CONFIG_SERIAL_CORE_CONSOLE | ||
35 | #define uart_console(port) \ | ||
36 | ((port)->cons && (port)->cons->index == (port)->line) | ||
37 | #else | ||
38 | #define uart_console(port) (0) | ||
39 | #endif | ||
40 | |||
34 | struct uart_port; | 41 | struct uart_port; |
35 | struct serial_struct; | 42 | struct serial_struct; |
36 | struct device; | 43 | struct device; |
diff --git a/include/linux/tty.h b/include/linux/tty.h index 8780bd2a272a..01ac30efd6a6 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h | |||
@@ -272,7 +272,6 @@ struct tty_struct { | |||
272 | #define N_TTY_BUF_SIZE 4096 | 272 | #define N_TTY_BUF_SIZE 4096 |
273 | 273 | ||
274 | unsigned char closing:1; | 274 | unsigned char closing:1; |
275 | unsigned short minimum_to_wake; | ||
276 | unsigned char *write_buf; | 275 | unsigned char *write_buf; |
277 | int write_cnt; | 276 | int write_cnt; |
278 | /* If the tty has a pending do_SAK, queue it here - akpm */ | 277 | /* If the tty has a pending do_SAK, queue it here - akpm */ |
@@ -309,8 +308,6 @@ struct tty_file_private { | |||
309 | #define TTY_LDISC 9 /* Line discipline attached */ | 308 | #define TTY_LDISC 9 /* Line discipline attached */ |
310 | #define TTY_LDISC_CHANGING 10 /* Line discipline changing */ | 309 | #define TTY_LDISC_CHANGING 10 /* Line discipline changing */ |
311 | #define TTY_LDISC_OPEN 11 /* Line discipline is open */ | 310 | #define TTY_LDISC_OPEN 11 /* Line discipline is open */ |
312 | #define TTY_HW_COOK_OUT 14 /* Hardware can do output cooking */ | ||
313 | #define TTY_HW_COOK_IN 15 /* Hardware can do input cooking */ | ||
314 | #define TTY_PTY_LOCK 16 /* pty private */ | 311 | #define TTY_PTY_LOCK 16 /* pty private */ |
315 | #define TTY_NO_WRITE_SPLIT 17 /* Preserve write boundaries to driver */ | 312 | #define TTY_NO_WRITE_SPLIT 17 /* Preserve write boundaries to driver */ |
316 | #define TTY_HUPPED 18 /* Post driver->hangup() */ | 313 | #define TTY_HUPPED 18 /* Post driver->hangup() */ |
diff --git a/include/linux/tty_ldisc.h b/include/linux/tty_ldisc.h index 58390c73df8b..a1b048999821 100644 --- a/include/linux/tty_ldisc.h +++ b/include/linux/tty_ldisc.h | |||
@@ -100,6 +100,11 @@ | |||
100 | * seek to perform this action quickly but should wait until | 100 | * seek to perform this action quickly but should wait until |
101 | * any pending driver I/O is completed. | 101 | * any pending driver I/O is completed. |
102 | * | 102 | * |
103 | * void (*fasync)(struct tty_struct *, int on) | ||
104 | * | ||
105 | * Notify line discipline when signal-driven I/O is enabled or | ||
106 | * disabled. | ||
107 | * | ||
103 | * void (*dcd_change)(struct tty_struct *tty, unsigned int status) | 108 | * void (*dcd_change)(struct tty_struct *tty, unsigned int status) |
104 | * | 109 | * |
105 | * Tells the discipline that the DCD pin has changed its status. | 110 | * Tells the discipline that the DCD pin has changed its status. |
@@ -110,6 +115,52 @@ | |||
110 | #include <linux/wait.h> | 115 | #include <linux/wait.h> |
111 | #include <linux/wait.h> | 116 | #include <linux/wait.h> |
112 | 117 | ||
118 | |||
119 | /* | ||
120 | * the semaphore definition | ||
121 | */ | ||
122 | struct ld_semaphore { | ||
123 | long count; | ||
124 | raw_spinlock_t wait_lock; | ||
125 | unsigned int wait_readers; | ||
126 | struct list_head read_wait; | ||
127 | struct list_head write_wait; | ||
128 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
129 | struct lockdep_map dep_map; | ||
130 | #endif | ||
131 | }; | ||
132 | |||
133 | extern void __init_ldsem(struct ld_semaphore *sem, const char *name, | ||
134 | struct lock_class_key *key); | ||
135 | |||
136 | #define init_ldsem(sem) \ | ||
137 | do { \ | ||
138 | static struct lock_class_key __key; \ | ||
139 | \ | ||
140 | __init_ldsem((sem), #sem, &__key); \ | ||
141 | } while (0) | ||
142 | |||
143 | |||
144 | extern int ldsem_down_read(struct ld_semaphore *sem, long timeout); | ||
145 | extern int ldsem_down_read_trylock(struct ld_semaphore *sem); | ||
146 | extern int ldsem_down_write(struct ld_semaphore *sem, long timeout); | ||
147 | extern int ldsem_down_write_trylock(struct ld_semaphore *sem); | ||
148 | extern void ldsem_up_read(struct ld_semaphore *sem); | ||
149 | extern void ldsem_up_write(struct ld_semaphore *sem); | ||
150 | |||
151 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
152 | extern int ldsem_down_read_nested(struct ld_semaphore *sem, int subclass, | ||
153 | long timeout); | ||
154 | extern int ldsem_down_write_nested(struct ld_semaphore *sem, int subclass, | ||
155 | long timeout); | ||
156 | #else | ||
157 | # define ldsem_down_read_nested(sem, subclass, timeout) \ | ||
158 | ldsem_down_read(sem, timeout) | ||
159 | # define ldsem_down_write_nested(sem, subclass, timeout) \ | ||
160 | ldsem_down_write(sem, timeout) | ||
161 | #endif | ||
162 | |||
163 | |||
113 | struct tty_ldisc_ops { | 164 | struct tty_ldisc_ops { |
114 | int magic; | 165 | int magic; |
115 | char *name; | 166 | char *name; |
@@ -143,6 +194,7 @@ struct tty_ldisc_ops { | |||
143 | char *fp, int count); | 194 | char *fp, int count); |
144 | void (*write_wakeup)(struct tty_struct *); | 195 | void (*write_wakeup)(struct tty_struct *); |
145 | void (*dcd_change)(struct tty_struct *, unsigned int); | 196 | void (*dcd_change)(struct tty_struct *, unsigned int); |
197 | void (*fasync)(struct tty_struct *tty, int on); | ||
146 | 198 | ||
147 | struct module *owner; | 199 | struct module *owner; |
148 | 200 | ||
diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h index 0d33fca48774..8d7634247fb4 100644 --- a/include/linux/vt_kern.h +++ b/include/linux/vt_kern.h | |||
@@ -133,8 +133,6 @@ void change_console(struct vc_data *new_vc); | |||
133 | void reset_vc(struct vc_data *vc); | 133 | void reset_vc(struct vc_data *vc); |
134 | extern int do_unbind_con_driver(const struct consw *csw, int first, int last, | 134 | extern int do_unbind_con_driver(const struct consw *csw, int first, int last, |
135 | int deflt); | 135 | int deflt); |
136 | extern int unbind_con_driver(const struct consw *csw, int first, int last, | ||
137 | int deflt); | ||
138 | int vty_init(const struct file_operations *console_fops); | 136 | int vty_init(const struct file_operations *console_fops); |
139 | 137 | ||
140 | static inline bool vt_force_oops_output(struct vc_data *vc) | 138 | static inline bool vt_force_oops_output(struct vc_data *vc) |
diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h index 74c2bf7211f8..c8eaeb5465ef 100644 --- a/include/uapi/linux/serial_core.h +++ b/include/uapi/linux/serial_core.h | |||
@@ -226,4 +226,7 @@ | |||
226 | /* Rocketport EXPRESS/INFINITY */ | 226 | /* Rocketport EXPRESS/INFINITY */ |
227 | #define PORT_RP2 102 | 227 | #define PORT_RP2 102 |
228 | 228 | ||
229 | /* Freescale lpuart */ | ||
230 | #define PORT_LPUART 103 | ||
231 | |||
229 | #endif /* _UAPILINUX_SERIAL_CORE_H */ | 232 | #endif /* _UAPILINUX_SERIAL_CORE_H */ |