diff mbox

[5/5] serial: 8250_mid: add support for DMA engine handling from UART MMIO

Message ID 1444052484-138915-6-git-send-email-heikki.krogerus@linux.intel.com (mailing list archive)
State Not Applicable
Headers show

Commit Message

Heikki Krogerus Oct. 5, 2015, 1:41 p.m. UTC
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>
---
 drivers/tty/serial/8250/8250_mid.c | 67 ++++++++++++++++++++++++++++++++++++--
 drivers/tty/serial/8250/8250_pci.c |  1 +
 2 files changed, 66 insertions(+), 2 deletions(-)

Comments

Andy Shevchenko Oct. 12, 2015, 1:52 p.m. UTC | #1
On Mon, 2015-10-05 at 16:41 +0300, Heikki Krogerus wrote:
> 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.


One comment below.

> 
> Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> ---
>  drivers/tty/serial/8250/8250_mid.c | 67 
> ++++++++++++++++++++++++++++++++++++--
>  drivers/tty/serial/8250/8250_pci.c |  1 +
>  2 files changed, 66 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/tty/serial/8250/8250_mid.c 
> b/drivers/tty/serial/8250/8250_mid.c
> index 61f604c..06eb10c 100644
> --- a/drivers/tty/serial/8250/8250_mid.c
> +++ b/drivers/tty/serial/8250/8250_mid.c
> @@ -21,6 +21,7 @@
>  #define PCI_DEVICE_ID_INTEL_PNW_UART2	0x081c
>  #define PCI_DEVICE_ID_INTEL_PNW_UART3	0x081d
>  #define PCI_DEVICE_ID_INTEL_TNG_UART	0x1191
> +#define PCI_DEVICE_ID_INTEL_DNV_UART	0x19d8
>  
>  /* Intel MID Specific registers */
>  #define INTEL_MID_UART_PS		0x30
> @@ -33,6 +34,7 @@ struct mid8250_board {
>  	unsigned long freq;
>  	unsigned int base_baud;
>  	int (*setup)(struct mid8250 *, struct uart_port *p);
> +	void (*exit)(struct mid8250 *);
>  };
>  
>  struct mid8250 {
> @@ -41,6 +43,7 @@ struct mid8250 {
>  	struct pci_dev *dma_dev;
>  	struct uart_8250_dma dma;
>  	struct mid8250_board *board;
> +	struct hsu_dma_chip dma_chip;
>  };
>  
>  /*******************************************************************
> **********/
> @@ -82,6 +85,51 @@ static int tng_setup(struct mid8250 *mid, struct 
> uart_port *p)
>  	return 0;
>  }
>  
> +static int dnv_handle_irq(struct uart_port *p)
> +{
> +	struct mid8250 *mid = p->private_data;
> +	int ret;
> +
> +	ret = hsu_dma_irq(&mid->dma_chip, 0);
> +	ret |= hsu_dma_irq(&mid->dma_chip, 1);
> +
> +	/* For now, letting the HW generate separate interrupt for 
> the UART */
> +	if (ret)
> +		return ret;
> +
> +	return serial8250_handle_irq(p, serial_port_in(p, 
> UART_IIR));
> +}
> +
> +#define DNV_DMA_REGS	0x80
> +#define DNV_DMA_OFFSET	0x40
> +
> +static int dnv_setup(struct mid8250 *mid, struct uart_port *p)
> +{
> +	struct hsu_dma_chip *chip = &mid->dma_chip;
> +	struct pci_dev *pdev = to_pci_dev(p->dev);
> +	int ret;
> +
> +	chip->dev = &pdev->dev;
> +	chip->irq = pdev->irq;
> +	chip->regs = p->membase + DNV_DMA_REGS;
> +	chip->length = pci_resource_len(pdev, 0) - DNV_DMA_REGS;
> +	chip->offset = DNV_DMA_OFFSET;

This a bit buggy, since that offset stuff is coming for HSU PCI case
where we have
1) 0x100 bytes for global DMA registers (like interrupt)
2) 0x40 * nr_channels

So, in your case chip->offset should be 0, but _DMA_REGS should be
renamed to something like DMA_REGS_START since it's an offset to UART
register space.

> +
> +	ret = hsu_dma_probe(chip);
> +	if (ret)
> +		return ret;
> +
> +	mid->dma_dev = pdev;
> +
> +	p->handle_irq = dnv_handle_irq;
> +	return 0;
> +}
> +
> +static void dnv_exit(struct mid8250 *mid)
> +{
> +	hsu_dma_remove(&mid->dma_chip);
> +}
> +
>  /*******************************************************************
> **********/
>  
>  static void mid8250_set_termios(struct uart_port *p,
> @@ -202,22 +250,29 @@ static int mid8250_probe(struct pci_dev *pdev, 
> const struct pci_device_id *id)
>  
>  	ret = mid8250_dma_setup(mid, &uart);
>  	if (ret)
> -		return ret;
> +		goto err;
>  
>  	ret = serial8250_register_8250_port(&uart);
>  	if (ret < 0)
> -		return ret;
> +		goto err;
>  
>  	mid->line = ret;
>  
>  	pci_set_drvdata(pdev, mid);
>  	return 0;
> +err:
> +	if (mid->board->exit)
> +		mid->board->exit(mid);
> +	return ret;
>  }
>  
>  static void mid8250_remove(struct pci_dev *pdev)
>  {
>  	struct mid8250 *mid = pci_get_drvdata(pdev);
>  
> +	if (mid->board->exit)
> +		mid->board->exit(mid);
> +
>  	serial8250_unregister_port(mid->line);
>  }
>  
> @@ -233,6 +288,13 @@ static const struct mid8250_board tng_board = {
>  	.setup = tng_setup,
>  };
>  
> +static const struct mid8250_board dnv_board = {
> +	.freq = 133333333,
> +	.base_baud = 115200,
> +	.setup = dnv_setup,
> +	.exit = dnv_exit,
> +};
> +
>  #define MID_DEVICE(id, board) { PCI_VDEVICE(INTEL, id), 
> (kernel_ulong_t)&board }
>  
>  static const struct pci_device_id pci_ids[] = {
> @@ -240,6 +302,7 @@ static const struct pci_device_id pci_ids[] = {
>  	MID_DEVICE(PCI_DEVICE_ID_INTEL_PNW_UART2, pnw_board),
>  	MID_DEVICE(PCI_DEVICE_ID_INTEL_PNW_UART3, pnw_board),
>  	MID_DEVICE(PCI_DEVICE_ID_INTEL_TNG_UART, tng_board),
> +	MID_DEVICE(PCI_DEVICE_ID_INTEL_DNV_UART, dnv_board),
>  	{ },
>  };
>  MODULE_DEVICE_TABLE(pci, pci_ids);
> diff --git a/drivers/tty/serial/8250/8250_pci.c 
> b/drivers/tty/serial/8250/8250_pci.c
> index 177eaea..4097f3f 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[] = 
> {
>  	{ PCI_VDEVICE(INTEL, 0x081c), },
>  	{ PCI_VDEVICE(INTEL, 0x081d), },
>  	{ PCI_VDEVICE(INTEL, 0x1191), },
> +	{ PCI_VDEVICE(INTEL, 0x19d8), },
>  };
>  
>  /*
Heikki Krogerus Oct. 13, 2015, 6:42 a.m. UTC | #2
> > +#define DNV_DMA_REGS	0x80
> > +#define DNV_DMA_OFFSET	0x40
> > +
> > +static int dnv_setup(struct mid8250 *mid, struct uart_port *p)
> > +{
> > +	struct hsu_dma_chip *chip = &mid->dma_chip;
> > +	struct pci_dev *pdev = to_pci_dev(p->dev);
> > +	int ret;
> > +
> > +	chip->dev = &pdev->dev;
> > +	chip->irq = pdev->irq;
> > +	chip->regs = p->membase + DNV_DMA_REGS;
> > +	chip->length = pci_resource_len(pdev, 0) - DNV_DMA_REGS;
> > +	chip->offset = DNV_DMA_OFFSET;
> 
> This a bit buggy, since that offset stuff is coming for HSU PCI case
> where we have
> 1) 0x100 bytes for global DMA registers (like interrupt)
> 2) 0x40 * nr_channels
> 
> So, in your case chip->offset should be 0, but _DMA_REGS should be
> renamed to something like DMA_REGS_START since it's an offset to UART
> register space.

Good catch! I'll prepare v2 of this series today and fix that.


Thanks Andy,
diff mbox

Patch

diff --git a/drivers/tty/serial/8250/8250_mid.c b/drivers/tty/serial/8250/8250_mid.c
index 61f604c..06eb10c 100644
--- a/drivers/tty/serial/8250/8250_mid.c
+++ b/drivers/tty/serial/8250/8250_mid.c
@@ -21,6 +21,7 @@ 
 #define PCI_DEVICE_ID_INTEL_PNW_UART2	0x081c
 #define PCI_DEVICE_ID_INTEL_PNW_UART3	0x081d
 #define PCI_DEVICE_ID_INTEL_TNG_UART	0x1191
+#define PCI_DEVICE_ID_INTEL_DNV_UART	0x19d8
 
 /* Intel MID Specific registers */
 #define INTEL_MID_UART_PS		0x30
@@ -33,6 +34,7 @@  struct mid8250_board {
 	unsigned long freq;
 	unsigned int base_baud;
 	int (*setup)(struct mid8250 *, struct uart_port *p);
+	void (*exit)(struct mid8250 *);
 };
 
 struct mid8250 {
@@ -41,6 +43,7 @@  struct mid8250 {
 	struct pci_dev *dma_dev;
 	struct uart_8250_dma dma;
 	struct mid8250_board *board;
+	struct hsu_dma_chip dma_chip;
 };
 
 /*****************************************************************************/
@@ -82,6 +85,51 @@  static int tng_setup(struct mid8250 *mid, struct uart_port *p)
 	return 0;
 }
 
+static int dnv_handle_irq(struct uart_port *p)
+{
+	struct mid8250 *mid = p->private_data;
+	int ret;
+
+	ret = hsu_dma_irq(&mid->dma_chip, 0);
+	ret |= hsu_dma_irq(&mid->dma_chip, 1);
+
+	/* For now, letting the HW generate separate interrupt for the UART */
+	if (ret)
+		return ret;
+
+	return serial8250_handle_irq(p, serial_port_in(p, UART_IIR));
+}
+
+#define DNV_DMA_REGS	0x80
+#define DNV_DMA_OFFSET	0x40
+
+static int dnv_setup(struct mid8250 *mid, struct uart_port *p)
+{
+	struct hsu_dma_chip *chip = &mid->dma_chip;
+	struct pci_dev *pdev = to_pci_dev(p->dev);
+	int ret;
+
+	chip->dev = &pdev->dev;
+	chip->irq = pdev->irq;
+	chip->regs = p->membase + DNV_DMA_REGS;
+	chip->length = pci_resource_len(pdev, 0) - DNV_DMA_REGS;
+	chip->offset = DNV_DMA_OFFSET;
+
+	ret = hsu_dma_probe(chip);
+	if (ret)
+		return ret;
+
+	mid->dma_dev = pdev;
+
+	p->handle_irq = dnv_handle_irq;
+	return 0;
+}
+
+static void dnv_exit(struct mid8250 *mid)
+{
+	hsu_dma_remove(&mid->dma_chip);
+}
+
 /*****************************************************************************/
 
 static void mid8250_set_termios(struct uart_port *p,
@@ -202,22 +250,29 @@  static int mid8250_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
 	ret = mid8250_dma_setup(mid, &uart);
 	if (ret)
-		return ret;
+		goto err;
 
 	ret = serial8250_register_8250_port(&uart);
 	if (ret < 0)
-		return ret;
+		goto err;
 
 	mid->line = ret;
 
 	pci_set_drvdata(pdev, mid);
 	return 0;
+err:
+	if (mid->board->exit)
+		mid->board->exit(mid);
+	return ret;
 }
 
 static void mid8250_remove(struct pci_dev *pdev)
 {
 	struct mid8250 *mid = pci_get_drvdata(pdev);
 
+	if (mid->board->exit)
+		mid->board->exit(mid);
+
 	serial8250_unregister_port(mid->line);
 }
 
@@ -233,6 +288,13 @@  static const struct mid8250_board tng_board = {
 	.setup = tng_setup,
 };
 
+static const struct mid8250_board dnv_board = {
+	.freq = 133333333,
+	.base_baud = 115200,
+	.setup = dnv_setup,
+	.exit = dnv_exit,
+};
+
 #define MID_DEVICE(id, board) { PCI_VDEVICE(INTEL, id), (kernel_ulong_t)&board }
 
 static const struct pci_device_id pci_ids[] = {
@@ -240,6 +302,7 @@  static const struct pci_device_id pci_ids[] = {
 	MID_DEVICE(PCI_DEVICE_ID_INTEL_PNW_UART2, pnw_board),
 	MID_DEVICE(PCI_DEVICE_ID_INTEL_PNW_UART3, pnw_board),
 	MID_DEVICE(PCI_DEVICE_ID_INTEL_TNG_UART, tng_board),
+	MID_DEVICE(PCI_DEVICE_ID_INTEL_DNV_UART, dnv_board),
 	{ },
 };
 MODULE_DEVICE_TABLE(pci, pci_ids);
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index 177eaea..4097f3f 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[] = {
 	{ PCI_VDEVICE(INTEL, 0x081c), },
 	{ PCI_VDEVICE(INTEL, 0x081d), },
 	{ PCI_VDEVICE(INTEL, 0x1191), },
+	{ PCI_VDEVICE(INTEL, 0x19d8), },
 };
 
 /*