aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/serial/8250/8250_dw.c
diff options
context:
space:
mode:
authorHeikki Krogerus <heikki.krogerus@linux.intel.com>2013-01-10 04:25:12 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-01-16 02:03:00 -0500
commit7277b2a1c687b728a4ec0511d2ae076aed6ed5b4 (patch)
treee7274f6523a7cb4989cbabd338d32f4d2131b739 /drivers/tty/serial/8250/8250_dw.c
parent9ee4b83e51f741a645c43e61b9f3f8075ca0fdf4 (diff)
serial: 8250_dw: Enable DMA support with ACPI
With ACPI 5.0 we can use the FixedDMA Resource Descriptor to extract the needed information for DMA support. Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty/serial/8250/8250_dw.c')
-rw-r--r--drivers/tty/serial/8250/8250_dw.c65
1 files changed, 65 insertions, 0 deletions
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index f6eeff02dced..ceacf5e36f2e 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -27,6 +27,8 @@
27#include <linux/slab.h> 27#include <linux/slab.h>
28#include <linux/acpi.h> 28#include <linux/acpi.h>
29 29
30#include "8250.h"
31
30/* Offsets for the DesignWare specific registers */ 32/* Offsets for the DesignWare specific registers */
31#define DW_UART_USR 0x1f /* UART Status Register */ 33#define DW_UART_USR 0x1f /* UART Status Register */
32#define DW_UART_CPR 0xf4 /* Component Parameter Register */ 34#define DW_UART_CPR 0xf4 /* Component Parameter Register */
@@ -143,9 +145,64 @@ static int dw8250_probe_of(struct uart_port *p)
143 return 0; 145 return 0;
144} 146}
145 147
148static bool dw8250_acpi_dma_filter(struct dma_chan *chan, void *parm)
149{
150 return chan->chan_id == *(int *)parm;
151}
152
153static acpi_status
154dw8250_acpi_walk_resource(struct acpi_resource *res, void *data)
155{
156 struct uart_port *p = data;
157 struct uart_8250_port *port;
158 struct uart_8250_dma *dma;
159 struct acpi_resource_fixed_dma *fixed_dma;
160 struct dma_slave_config *slave;
161
162 port = container_of(p, struct uart_8250_port, port);
163
164 switch (res->type) {
165 case ACPI_RESOURCE_TYPE_FIXED_DMA:
166 fixed_dma = &res->data.fixed_dma;
167
168 /* TX comes first */
169 if (!port->dma) {
170 dma = devm_kzalloc(p->dev, sizeof(*dma), GFP_KERNEL);
171 if (!dma)
172 return AE_NO_MEMORY;
173
174 port->dma = dma;
175 slave = &dma->txconf;
176
177 slave->direction = DMA_MEM_TO_DEV;
178 slave->dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
179 slave->slave_id = fixed_dma->request_lines;
180
181 dma->tx_chan_id = fixed_dma->channels;
182 dma->tx_param = &dma->tx_chan_id;
183 dma->fn = dw8250_acpi_dma_filter;
184 } else {
185 dma = port->dma;
186 slave = &dma->rxconf;
187
188 slave->direction = DMA_DEV_TO_MEM;
189 slave->src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
190 slave->slave_id = fixed_dma->request_lines;
191
192 dma->rx_chan_id = fixed_dma->channels;
193 dma->rx_param = &dma->rx_chan_id;
194 }
195
196 break;
197 }
198
199 return AE_OK;
200}
201
146static int dw8250_probe_acpi(struct uart_port *p) 202static int dw8250_probe_acpi(struct uart_port *p)
147{ 203{
148 const struct acpi_device_id *id; 204 const struct acpi_device_id *id;
205 acpi_status status;
149 u32 reg; 206 u32 reg;
150 207
151 id = acpi_match_device(p->dev->driver->acpi_match_table, p->dev); 208 id = acpi_match_device(p->dev->driver->acpi_match_table, p->dev);
@@ -158,6 +215,14 @@ static int dw8250_probe_acpi(struct uart_port *p)
158 p->regshift = 2; 215 p->regshift = 2;
159 p->uartclk = (unsigned int)id->driver_data; 216 p->uartclk = (unsigned int)id->driver_data;
160 217
218 status = acpi_walk_resources(ACPI_HANDLE(p->dev), METHOD_NAME__CRS,
219 dw8250_acpi_walk_resource, p);
220 if (ACPI_FAILURE(status)) {
221 dev_err_ratelimited(p->dev, "%s failed \"%s\"\n", __func__,
222 acpi_format_exception(status));
223 return -ENODEV;
224 }
225
161 /* Fix Haswell issue where the clocks do not get enabled */ 226 /* Fix Haswell issue where the clocks do not get enabled */
162 if (!strcmp(id->id, "INT33C4") || !strcmp(id->id, "INT33C5")) { 227 if (!strcmp(id->id, "INT33C4") || !strcmp(id->id, "INT33C5")) {
163 reg = readl(p->membase + LPSS_PRV_CLOCK_PARAMS); 228 reg = readl(p->membase + LPSS_PRV_CLOCK_PARAMS);