diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-13 17:52:21 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-13 17:52:21 -0400 |
commit | d1447464789918db1e1a3d0aaf50d3d0f6487a4f (patch) | |
tree | 490bd5c493cdba742dc90d3731962226838e5f33 /drivers/tty/serial/8250 | |
parent | 833e68340d108d88f4cb79b7d7223f6859d362ca (diff) | |
parent | 6ac5310e649df5fcd240d764503bf16a1317ea39 (diff) |
Merge branch 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus
Pull MIPS updates from Ralf Baechle:
"MIPS updates:
- All the things that didn't make 3.10.
- Removes the Windriver PPMC platform. Nobody will miss it.
- Remove a workaround from kernel/irq/irqdomain.c which was there
exclusivly for MIPS. Patch by Grant Likely.
- More small improvments for the SEAD 3 platform
- Improvments on the BMIPS / SMP support for the BCM63xx series.
- Various cleanups of dead leftovers.
- Platform support for the Cavium Octeon-based EdgeRouter Lite.
Two large KVM patchsets didn't make it for this pull request because
their respective authors are vacationing"
* 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus: (124 commits)
MIPS: Kconfig: Add missing MODULES dependency to VPE_LOADER
MIPS: BCM63xx: CLK: Add dummy clk_{set,round}_rate() functions
MIPS: SEAD3: Disable L2 cache on SEAD-3.
MIPS: BCM63xx: Enable second core SMP on BCM6328 if available
MIPS: BCM63xx: Add SMP support to prom.c
MIPS: define write{b,w,l,q}_relaxed
MIPS: Expose missing pci_io{map,unmap} declarations
MIPS: Malta: Update GCMP detection.
Revert "MIPS: make CAC_ADDR and UNCAC_ADDR account for PHYS_OFFSET"
MIPS: APSP: Remove <asm/kspd.h>
SSB: Kconfig: Amend SSB_EMBEDDED dependencies
MIPS: microMIPS: Fix improper definition of ISA exception bit.
MIPS: Don't try to decode microMIPS branch instructions where they cannot exist.
MIPS: Declare emulate_load_store_microMIPS as a static function.
MIPS: Fix typos and cleanup comment
MIPS: Cleanup indentation and whitespace
MIPS: BMIPS: support booting from physical CPU other than 0
MIPS: Only set cpu_has_mmips if SYS_SUPPORTS_MICROMIPS
MIPS: GIC: Fix gic_set_affinity infinite loop
MIPS: Don't save/restore OCTEON wide multiplier state on syscalls.
...
Diffstat (limited to 'drivers/tty/serial/8250')
-rw-r--r-- | drivers/tty/serial/8250/8250_dw.c | 108 |
1 files changed, 69 insertions, 39 deletions
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index d07b6af3a937..76a8daadff47 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c | |||
@@ -29,6 +29,8 @@ | |||
29 | #include <linux/clk.h> | 29 | #include <linux/clk.h> |
30 | #include <linux/pm_runtime.h> | 30 | #include <linux/pm_runtime.h> |
31 | 31 | ||
32 | #include <asm/byteorder.h> | ||
33 | |||
32 | #include "8250.h" | 34 | #include "8250.h" |
33 | 35 | ||
34 | /* Offsets for the DesignWare specific registers */ | 36 | /* Offsets for the DesignWare specific registers */ |
@@ -57,6 +59,7 @@ struct dw8250_data { | |||
57 | int last_lcr; | 59 | int last_lcr; |
58 | int line; | 60 | int line; |
59 | struct clk *clk; | 61 | struct clk *clk; |
62 | u8 usr_reg; | ||
60 | }; | 63 | }; |
61 | 64 | ||
62 | static void dw8250_serial_out(struct uart_port *p, int offset, int value) | 65 | static void dw8250_serial_out(struct uart_port *p, int offset, int value) |
@@ -77,6 +80,13 @@ static unsigned int dw8250_serial_in(struct uart_port *p, int offset) | |||
77 | return readb(p->membase + offset); | 80 | return readb(p->membase + offset); |
78 | } | 81 | } |
79 | 82 | ||
83 | /* Read Back (rb) version to ensure register access ording. */ | ||
84 | static void dw8250_serial_out_rb(struct uart_port *p, int offset, int value) | ||
85 | { | ||
86 | dw8250_serial_out(p, offset, value); | ||
87 | dw8250_serial_in(p, UART_LCR); | ||
88 | } | ||
89 | |||
80 | static void dw8250_serial_out32(struct uart_port *p, int offset, int value) | 90 | static void dw8250_serial_out32(struct uart_port *p, int offset, int value) |
81 | { | 91 | { |
82 | struct dw8250_data *d = p->private_data; | 92 | struct dw8250_data *d = p->private_data; |
@@ -104,7 +114,7 @@ static int dw8250_handle_irq(struct uart_port *p) | |||
104 | return 1; | 114 | return 1; |
105 | } else if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) { | 115 | } else if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) { |
106 | /* Clear the USR and write the LCR again. */ | 116 | /* Clear the USR and write the LCR again. */ |
107 | (void)p->serial_in(p, DW_UART_USR); | 117 | (void)p->serial_in(p, d->usr_reg); |
108 | p->serial_out(p, UART_LCR, d->last_lcr); | 118 | p->serial_out(p, UART_LCR, d->last_lcr); |
109 | 119 | ||
110 | return 1; | 120 | return 1; |
@@ -125,12 +135,60 @@ dw8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old) | |||
125 | pm_runtime_put_sync_suspend(port->dev); | 135 | pm_runtime_put_sync_suspend(port->dev); |
126 | } | 136 | } |
127 | 137 | ||
128 | static int dw8250_probe_of(struct uart_port *p) | 138 | static void dw8250_setup_port(struct uart_8250_port *up) |
139 | { | ||
140 | struct uart_port *p = &up->port; | ||
141 | u32 reg = readl(p->membase + DW_UART_UCV); | ||
142 | |||
143 | /* | ||
144 | * If the Component Version Register returns zero, we know that | ||
145 | * ADDITIONAL_FEATURES are not enabled. No need to go any further. | ||
146 | */ | ||
147 | if (!reg) | ||
148 | return; | ||
149 | |||
150 | dev_dbg_ratelimited(p->dev, "Designware UART version %c.%c%c\n", | ||
151 | (reg >> 24) & 0xff, (reg >> 16) & 0xff, (reg >> 8) & 0xff); | ||
152 | |||
153 | reg = readl(p->membase + DW_UART_CPR); | ||
154 | if (!reg) | ||
155 | return; | ||
156 | |||
157 | /* Select the type based on fifo */ | ||
158 | if (reg & DW_UART_CPR_FIFO_MODE) { | ||
159 | p->type = PORT_16550A; | ||
160 | p->flags |= UPF_FIXED_TYPE; | ||
161 | p->fifosize = DW_UART_CPR_FIFO_SIZE(reg); | ||
162 | up->tx_loadsz = p->fifosize; | ||
163 | up->capabilities = UART_CAP_FIFO; | ||
164 | } | ||
165 | |||
166 | if (reg & DW_UART_CPR_AFCE_MODE) | ||
167 | up->capabilities |= UART_CAP_AFE; | ||
168 | } | ||
169 | |||
170 | static int dw8250_probe_of(struct uart_port *p, | ||
171 | struct dw8250_data *data) | ||
129 | { | 172 | { |
130 | struct device_node *np = p->dev->of_node; | 173 | struct device_node *np = p->dev->of_node; |
131 | u32 val; | 174 | u32 val; |
132 | 175 | bool has_ucv = true; | |
133 | if (!of_property_read_u32(np, "reg-io-width", &val)) { | 176 | |
177 | if (of_device_is_compatible(np, "cavium,octeon-3860-uart")) { | ||
178 | #ifdef __BIG_ENDIAN | ||
179 | /* | ||
180 | * Low order bits of these 64-bit registers, when | ||
181 | * accessed as a byte, are 7 bytes further down in the | ||
182 | * address space in big endian mode. | ||
183 | */ | ||
184 | p->membase += 7; | ||
185 | #endif | ||
186 | p->serial_out = dw8250_serial_out_rb; | ||
187 | p->flags = ASYNC_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE; | ||
188 | p->type = PORT_OCTEON; | ||
189 | data->usr_reg = 0x27; | ||
190 | has_ucv = false; | ||
191 | } else if (!of_property_read_u32(np, "reg-io-width", &val)) { | ||
134 | switch (val) { | 192 | switch (val) { |
135 | case 1: | 193 | case 1: |
136 | break; | 194 | break; |
@@ -144,6 +202,8 @@ static int dw8250_probe_of(struct uart_port *p) | |||
144 | return -EINVAL; | 202 | return -EINVAL; |
145 | } | 203 | } |
146 | } | 204 | } |
205 | if (has_ucv) | ||
206 | dw8250_setup_port(container_of(p, struct uart_8250_port, port)); | ||
147 | 207 | ||
148 | if (!of_property_read_u32(np, "reg-shift", &val)) | 208 | if (!of_property_read_u32(np, "reg-shift", &val)) |
149 | p->regshift = val; | 209 | p->regshift = val; |
@@ -168,6 +228,8 @@ static int dw8250_probe_acpi(struct uart_8250_port *up) | |||
168 | const struct acpi_device_id *id; | 228 | const struct acpi_device_id *id; |
169 | struct uart_port *p = &up->port; | 229 | struct uart_port *p = &up->port; |
170 | 230 | ||
231 | dw8250_setup_port(up); | ||
232 | |||
171 | id = acpi_match_device(p->dev->driver->acpi_match_table, p->dev); | 233 | id = acpi_match_device(p->dev->driver->acpi_match_table, p->dev); |
172 | if (!id) | 234 | if (!id) |
173 | return -ENODEV; | 235 | return -ENODEV; |
@@ -196,38 +258,6 @@ static inline int dw8250_probe_acpi(struct uart_8250_port *up) | |||
196 | } | 258 | } |
197 | #endif /* CONFIG_ACPI */ | 259 | #endif /* CONFIG_ACPI */ |
198 | 260 | ||
199 | static void dw8250_setup_port(struct uart_8250_port *up) | ||
200 | { | ||
201 | struct uart_port *p = &up->port; | ||
202 | u32 reg = readl(p->membase + DW_UART_UCV); | ||
203 | |||
204 | /* | ||
205 | * If the Component Version Register returns zero, we know that | ||
206 | * ADDITIONAL_FEATURES are not enabled. No need to go any further. | ||
207 | */ | ||
208 | if (!reg) | ||
209 | return; | ||
210 | |||
211 | dev_dbg_ratelimited(p->dev, "Designware UART version %c.%c%c\n", | ||
212 | (reg >> 24) & 0xff, (reg >> 16) & 0xff, (reg >> 8) & 0xff); | ||
213 | |||
214 | reg = readl(p->membase + DW_UART_CPR); | ||
215 | if (!reg) | ||
216 | return; | ||
217 | |||
218 | /* Select the type based on fifo */ | ||
219 | if (reg & DW_UART_CPR_FIFO_MODE) { | ||
220 | p->type = PORT_16550A; | ||
221 | p->flags |= UPF_FIXED_TYPE; | ||
222 | p->fifosize = DW_UART_CPR_FIFO_SIZE(reg); | ||
223 | up->tx_loadsz = p->fifosize; | ||
224 | up->capabilities = UART_CAP_FIFO; | ||
225 | } | ||
226 | |||
227 | if (reg & DW_UART_CPR_AFCE_MODE) | ||
228 | up->capabilities |= UART_CAP_AFE; | ||
229 | } | ||
230 | |||
231 | static int dw8250_probe(struct platform_device *pdev) | 261 | static int dw8250_probe(struct platform_device *pdev) |
232 | { | 262 | { |
233 | struct uart_8250_port uart = {}; | 263 | struct uart_8250_port uart = {}; |
@@ -259,6 +289,7 @@ static int dw8250_probe(struct platform_device *pdev) | |||
259 | if (!data) | 289 | if (!data) |
260 | return -ENOMEM; | 290 | return -ENOMEM; |
261 | 291 | ||
292 | data->usr_reg = DW_UART_USR; | ||
262 | data->clk = devm_clk_get(&pdev->dev, NULL); | 293 | data->clk = devm_clk_get(&pdev->dev, NULL); |
263 | if (!IS_ERR(data->clk)) { | 294 | if (!IS_ERR(data->clk)) { |
264 | clk_prepare_enable(data->clk); | 295 | clk_prepare_enable(data->clk); |
@@ -270,10 +301,8 @@ static int dw8250_probe(struct platform_device *pdev) | |||
270 | uart.port.serial_out = dw8250_serial_out; | 301 | uart.port.serial_out = dw8250_serial_out; |
271 | uart.port.private_data = data; | 302 | uart.port.private_data = data; |
272 | 303 | ||
273 | dw8250_setup_port(&uart); | ||
274 | |||
275 | if (pdev->dev.of_node) { | 304 | if (pdev->dev.of_node) { |
276 | err = dw8250_probe_of(&uart.port); | 305 | err = dw8250_probe_of(&uart.port, data); |
277 | if (err) | 306 | if (err) |
278 | return err; | 307 | return err; |
279 | } else if (ACPI_HANDLE(&pdev->dev)) { | 308 | } else if (ACPI_HANDLE(&pdev->dev)) { |
@@ -362,6 +391,7 @@ static const struct dev_pm_ops dw8250_pm_ops = { | |||
362 | 391 | ||
363 | static const struct of_device_id dw8250_of_match[] = { | 392 | static const struct of_device_id dw8250_of_match[] = { |
364 | { .compatible = "snps,dw-apb-uart" }, | 393 | { .compatible = "snps,dw-apb-uart" }, |
394 | { .compatible = "cavium,octeon-3860-uart" }, | ||
365 | { /* Sentinel */ } | 395 | { /* Sentinel */ } |
366 | }; | 396 | }; |
367 | MODULE_DEVICE_TABLE(of, dw8250_of_match); | 397 | MODULE_DEVICE_TABLE(of, dw8250_of_match); |