aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHeikki Krogerus <heikki.krogerus@linux.intel.com>2015-10-13 06:29:06 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-10-18 00:22:08 -0400
commit6ede6dcd87aa32787f077b6556dce6b0de7d91e6 (patch)
treee616986d6dc65bf124d302b24ac92af7609d3b38
parent4c97ad993d763904fc1c9e0bdc3a6dba062802a2 (diff)
serial: 8250_mid: add support for DMA engine handling from UART MMIO
The platforms that have this UART, but that don't have separate PCI device for the DMA Engine, need to create the HSU DMA Engine device separately. Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com> Acked-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/tty/serial/8250/8250_mid.c72
-rw-r--r--drivers/tty/serial/8250/8250_pci.c1
2 files changed, 71 insertions, 2 deletions
diff --git a/drivers/tty/serial/8250/8250_mid.c b/drivers/tty/serial/8250/8250_mid.c
index 61f604c7aeee..88531a36b69c 100644
--- a/drivers/tty/serial/8250/8250_mid.c
+++ b/drivers/tty/serial/8250/8250_mid.c
@@ -21,6 +21,7 @@
21#define PCI_DEVICE_ID_INTEL_PNW_UART2 0x081c 21#define PCI_DEVICE_ID_INTEL_PNW_UART2 0x081c
22#define PCI_DEVICE_ID_INTEL_PNW_UART3 0x081d 22#define PCI_DEVICE_ID_INTEL_PNW_UART3 0x081d
23#define PCI_DEVICE_ID_INTEL_TNG_UART 0x1191 23#define PCI_DEVICE_ID_INTEL_TNG_UART 0x1191
24#define PCI_DEVICE_ID_INTEL_DNV_UART 0x19d8
24 25
25/* Intel MID Specific registers */ 26/* Intel MID Specific registers */
26#define INTEL_MID_UART_PS 0x30 27#define INTEL_MID_UART_PS 0x30
@@ -33,6 +34,7 @@ struct mid8250_board {
33 unsigned long freq; 34 unsigned long freq;
34 unsigned int base_baud; 35 unsigned int base_baud;
35 int (*setup)(struct mid8250 *, struct uart_port *p); 36 int (*setup)(struct mid8250 *, struct uart_port *p);
37 void (*exit)(struct mid8250 *);
36}; 38};
37 39
38struct mid8250 { 40struct mid8250 {
@@ -41,6 +43,7 @@ struct mid8250 {
41 struct pci_dev *dma_dev; 43 struct pci_dev *dma_dev;
42 struct uart_8250_dma dma; 44 struct uart_8250_dma dma;
43 struct mid8250_board *board; 45 struct mid8250_board *board;
46 struct hsu_dma_chip dma_chip;
44}; 47};
45 48
46/*****************************************************************************/ 49/*****************************************************************************/
@@ -82,6 +85,53 @@ static int tng_setup(struct mid8250 *mid, struct uart_port *p)
82 return 0; 85 return 0;
83} 86}
84 87
88static int dnv_handle_irq(struct uart_port *p)
89{
90 struct mid8250 *mid = p->private_data;
91 int ret;
92
93 ret = hsu_dma_irq(&mid->dma_chip, 0);
94 ret |= hsu_dma_irq(&mid->dma_chip, 1);
95
96 /* For now, letting the HW generate separate interrupt for the UART */
97 if (ret)
98 return ret;
99
100 return serial8250_handle_irq(p, serial_port_in(p, UART_IIR));
101}
102
103#define DNV_DMA_CHAN_OFFSET 0x80
104
105static int dnv_setup(struct mid8250 *mid, struct uart_port *p)
106{
107 struct hsu_dma_chip *chip = &mid->dma_chip;
108 struct pci_dev *pdev = to_pci_dev(p->dev);
109 int ret;
110
111 chip->dev = &pdev->dev;
112 chip->irq = pdev->irq;
113 chip->regs = p->membase;
114 chip->length = pci_resource_len(pdev, 0);
115 chip->offset = DNV_DMA_CHAN_OFFSET;
116
117 /* Falling back to PIO mode if DMA probing fails */
118 ret = hsu_dma_probe(chip);
119 if (ret)
120 return 0;
121
122 mid->dma_dev = pdev;
123
124 p->handle_irq = dnv_handle_irq;
125 return 0;
126}
127
128static void dnv_exit(struct mid8250 *mid)
129{
130 if (!mid->dma_dev)
131 return;
132 hsu_dma_remove(&mid->dma_chip);
133}
134
85/*****************************************************************************/ 135/*****************************************************************************/
86 136
87static void mid8250_set_termios(struct uart_port *p, 137static void mid8250_set_termios(struct uart_port *p,
@@ -135,6 +185,9 @@ static int mid8250_dma_setup(struct mid8250 *mid, struct uart_8250_port *port)
135 struct hsu_dma_slave *rx_param; 185 struct hsu_dma_slave *rx_param;
136 struct hsu_dma_slave *tx_param; 186 struct hsu_dma_slave *tx_param;
137 187
188 if (!mid->dma_dev)
189 return 0;
190
138 rx_param = devm_kzalloc(dev, sizeof(*rx_param), GFP_KERNEL); 191 rx_param = devm_kzalloc(dev, sizeof(*rx_param), GFP_KERNEL);
139 if (!rx_param) 192 if (!rx_param)
140 return -ENOMEM; 193 return -ENOMEM;
@@ -202,22 +255,29 @@ static int mid8250_probe(struct pci_dev *pdev, const struct pci_device_id *id)
202 255
203 ret = mid8250_dma_setup(mid, &uart); 256 ret = mid8250_dma_setup(mid, &uart);
204 if (ret) 257 if (ret)
205 return ret; 258 goto err;
206 259
207 ret = serial8250_register_8250_port(&uart); 260 ret = serial8250_register_8250_port(&uart);
208 if (ret < 0) 261 if (ret < 0)
209 return ret; 262 goto err;
210 263
211 mid->line = ret; 264 mid->line = ret;
212 265
213 pci_set_drvdata(pdev, mid); 266 pci_set_drvdata(pdev, mid);
214 return 0; 267 return 0;
268err:
269 if (mid->board->exit)
270 mid->board->exit(mid);
271 return ret;
215} 272}
216 273
217static void mid8250_remove(struct pci_dev *pdev) 274static void mid8250_remove(struct pci_dev *pdev)
218{ 275{
219 struct mid8250 *mid = pci_get_drvdata(pdev); 276 struct mid8250 *mid = pci_get_drvdata(pdev);
220 277
278 if (mid->board->exit)
279 mid->board->exit(mid);
280
221 serial8250_unregister_port(mid->line); 281 serial8250_unregister_port(mid->line);
222} 282}
223 283
@@ -233,6 +293,13 @@ static const struct mid8250_board tng_board = {
233 .setup = tng_setup, 293 .setup = tng_setup,
234}; 294};
235 295
296static const struct mid8250_board dnv_board = {
297 .freq = 133333333,
298 .base_baud = 115200,
299 .setup = dnv_setup,
300 .exit = dnv_exit,
301};
302
236#define MID_DEVICE(id, board) { PCI_VDEVICE(INTEL, id), (kernel_ulong_t)&board } 303#define MID_DEVICE(id, board) { PCI_VDEVICE(INTEL, id), (kernel_ulong_t)&board }
237 304
238static const struct pci_device_id pci_ids[] = { 305static const struct pci_device_id pci_ids[] = {
@@ -240,6 +307,7 @@ static const struct pci_device_id pci_ids[] = {
240 MID_DEVICE(PCI_DEVICE_ID_INTEL_PNW_UART2, pnw_board), 307 MID_DEVICE(PCI_DEVICE_ID_INTEL_PNW_UART2, pnw_board),
241 MID_DEVICE(PCI_DEVICE_ID_INTEL_PNW_UART3, pnw_board), 308 MID_DEVICE(PCI_DEVICE_ID_INTEL_PNW_UART3, pnw_board),
242 MID_DEVICE(PCI_DEVICE_ID_INTEL_TNG_UART, tng_board), 309 MID_DEVICE(PCI_DEVICE_ID_INTEL_TNG_UART, tng_board),
310 MID_DEVICE(PCI_DEVICE_ID_INTEL_DNV_UART, dnv_board),
243 { }, 311 { },
244}; 312};
245MODULE_DEVICE_TABLE(pci, pci_ids); 313MODULE_DEVICE_TABLE(pci, pci_ids);
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index 177eaeafeb3e..4097f3f65b3b 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -3809,6 +3809,7 @@ static const struct pci_device_id blacklist[] = {
3809 { PCI_VDEVICE(INTEL, 0x081c), }, 3809 { PCI_VDEVICE(INTEL, 0x081c), },
3810 { PCI_VDEVICE(INTEL, 0x081d), }, 3810 { PCI_VDEVICE(INTEL, 0x081d), },
3811 { PCI_VDEVICE(INTEL, 0x1191), }, 3811 { PCI_VDEVICE(INTEL, 0x1191), },
3812 { PCI_VDEVICE(INTEL, 0x19d8), },
3812}; 3813};
3813 3814
3814/* 3815/*