Message ID | 20241202-m5441x_uart_resource-v1-1-6b28cb295fb5@yoseli.org |
---|---|
State | New |
Headers | show |
Series | m68k: coldfire: Support resources for UART | expand |
Hi JM, On 2/12/24 20:34, Jean-Michel Hautbois wrote: > In order to use the eDMA channels for UART, the mcf_platform_uart needs > to be changed. Instead of adding another custom member for the > structure, use a resource tree in a platform_device per UART. It then > makes it possible to have a device named like "mcfuart.N" with N the > UART number. > > Later, adding the dma channel in the mcf tty driver will also be more > straightfoward. > > Signed-off-by: Jean-Michel Hautbois <jeanmichel.hautbois@yoseli.org> > --- > arch/m68k/coldfire/device.c | 96 ++++++++++++++------------------------------- > drivers/tty/serial/mcf.c | 69 +++++++++++++++++++------------- > 2 files changed, 70 insertions(+), 95 deletions(-) > > diff --git a/arch/m68k/coldfire/device.c b/arch/m68k/coldfire/device.c > index b6958ec2a220cf91a78a14fc7fa18749451412f7..fd7d0b0ce7eb2970cb8ffe33589fe8d7e88c268d 100644 > --- a/arch/m68k/coldfire/device.c > +++ b/arch/m68k/coldfire/device.c > @@ -24,73 +24,35 @@ > #include <linux/platform_data/dma-mcf-edma.h> > #include <linux/platform_data/mmc-esdhc-mcf.h> > > -/* > - * All current ColdFire parts contain from 2, 3, 4 or 10 UARTS. > - */ > -static struct mcf_platform_uart mcf_uart_platform_data[] = { > - { > - .mapbase = MCFUART_BASE0, > - .irq = MCF_IRQ_UART0, > - }, > - { > - .mapbase = MCFUART_BASE1, > - .irq = MCF_IRQ_UART1, > - }, > -#ifdef MCFUART_BASE2 > - { > - .mapbase = MCFUART_BASE2, > - .irq = MCF_IRQ_UART2, > - }, > -#endif > -#ifdef MCFUART_BASE3 > - { > - .mapbase = MCFUART_BASE3, > - .irq = MCF_IRQ_UART3, > - }, > -#endif > -#ifdef MCFUART_BASE4 > - { > - .mapbase = MCFUART_BASE4, > - .irq = MCF_IRQ_UART4, > - }, > -#endif > -#ifdef MCFUART_BASE5 > - { > - .mapbase = MCFUART_BASE5, > - .irq = MCF_IRQ_UART5, > - }, > -#endif > -#ifdef MCFUART_BASE6 > - { > - .mapbase = MCFUART_BASE6, > - .irq = MCF_IRQ_UART6, > - }, > -#endif > -#ifdef MCFUART_BASE7 > - { > - .mapbase = MCFUART_BASE7, > - .irq = MCF_IRQ_UART7, > +static u64 mcf_uart_mask = DMA_BIT_MASK(32); > + > +static struct resource mcf_uart0_resource[] = { > + [0] = { > + .start = MCFUART_BASE0, > + .end = MCFUART_BASE0 + 0x3fff, > + .flags = IORESOURCE_MEM, > }, > -#endif > -#ifdef MCFUART_BASE8 > - { > - .mapbase = MCFUART_BASE8, > - .irq = MCF_IRQ_UART8, > + [1] = { > + .start = 2, > + .end = 3, > + .flags = IORESOURCE_DMA, > }, > -#endif > -#ifdef MCFUART_BASE9 > - { > - .mapbase = MCFUART_BASE9, > - .irq = MCF_IRQ_UART9, > + [2] = { > + .start = MCF_IRQ_UART0, > + .end = MCF_IRQ_UART0, > + .flags = IORESOURCE_IRQ, > }, > -#endif > - { }, > }; > > -static struct platform_device mcf_uart = { > +static struct platform_device mcf_uart0 = { > .name = "mcfuart", > .id = 0, > - .dev.platform_data = mcf_uart_platform_data, > + .num_resources = ARRAY_SIZE(mcf_uart0_resource), > + .resource = mcf_uart0_resource, > + .dev = { > + .dma_mask = &mcf_uart_mask, > + .coherent_dma_mask = DMA_BIT_MASK(32), > + }, > }; > > #ifdef MCFFEC_BASE0 > @@ -485,12 +447,12 @@ static struct platform_device mcf_i2c5 = { > static const struct dma_slave_map mcf_edma_map[] = { > { "dreq0", "rx-tx", MCF_EDMA_FILTER_PARAM(0) }, > { "dreq1", "rx-tx", MCF_EDMA_FILTER_PARAM(1) }, > - { "uart.0", "rx", MCF_EDMA_FILTER_PARAM(2) }, > - { "uart.0", "tx", MCF_EDMA_FILTER_PARAM(3) }, > - { "uart.1", "rx", MCF_EDMA_FILTER_PARAM(4) }, > - { "uart.1", "tx", MCF_EDMA_FILTER_PARAM(5) }, > - { "uart.2", "rx", MCF_EDMA_FILTER_PARAM(6) }, > - { "uart.2", "tx", MCF_EDMA_FILTER_PARAM(7) }, > + { "mcfuart.0", "rx", MCF_EDMA_FILTER_PARAM(2) }, > + { "mcfuart.0", "tx", MCF_EDMA_FILTER_PARAM(3) }, > + { "mcfuart.1", "rx", MCF_EDMA_FILTER_PARAM(4) }, > + { "mcfuart.1", "tx", MCF_EDMA_FILTER_PARAM(5) }, > + { "mcfuart.2", "rx", MCF_EDMA_FILTER_PARAM(6) }, > + { "mcfuart.2", "tx", MCF_EDMA_FILTER_PARAM(7) }, > { "timer0", "rx-tx", MCF_EDMA_FILTER_PARAM(8) }, > { "timer1", "rx-tx", MCF_EDMA_FILTER_PARAM(9) }, > { "timer2", "rx-tx", MCF_EDMA_FILTER_PARAM(10) }, > @@ -623,7 +585,7 @@ static struct platform_device mcf_flexcan0 = { > #endif /* MCFFLEXCAN_SIZE */ > > static struct platform_device *mcf_devices[] __initdata = { > - &mcf_uart, > + &mcf_uart0, > #ifdef MCFFEC_BASE0 > &mcf_fec0, > #endif > diff --git a/drivers/tty/serial/mcf.c b/drivers/tty/serial/mcf.c > index 93e7dda4d39acd23daf8c0d4c29ac8d666f263c5..07b8decfdb6005f0265dd130765e45c3fd1715eb 100644 > --- a/drivers/tty/serial/mcf.c > +++ b/drivers/tty/serial/mcf.c > @@ -570,31 +570,46 @@ static struct uart_driver mcf_driver = { > > static int mcf_probe(struct platform_device *pdev) > { > - struct mcf_platform_uart *platp = dev_get_platdata(&pdev->dev); > struct uart_port *port; > - int i; > - > - for (i = 0; ((i < MCF_MAXPORTS) && (platp[i].mapbase)); i++) { > - port = &mcf_ports[i].port; > - > - port->line = i; > - port->type = PORT_MCF; > - port->mapbase = platp[i].mapbase; > - port->membase = (platp[i].membase) ? platp[i].membase : > - (unsigned char __iomem *) platp[i].mapbase; > - port->dev = &pdev->dev; > - port->iotype = SERIAL_IO_MEM; > - port->irq = platp[i].irq; > - port->uartclk = MCF_BUSCLK; > - port->ops = &mcf_uart_ops; > - port->flags = UPF_BOOT_AUTOCONF; > - port->rs485_config = mcf_config_rs485; > - port->rs485_supported = mcf_rs485_supported; > - port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_MCF_CONSOLE); > - > - uart_add_one_port(&mcf_driver, port); > + struct mcf_uart *pp; > + struct resource *res; > + void __iomem *base; > + int id = pdev->id; > + > + if (id == -1 || id >= MCF_MAXPORTS) { > + dev_err(&pdev->dev, "uart%d out of range\n", > + id); > + return -EINVAL; > } > > + port = &mcf_ports[id].port; > + port->line = id; > + > + base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); > + if (IS_ERR(base)) > + return PTR_ERR(base); > + > + port->mapbase = res->start; > + port->membase = base; > + > + port->irq = platform_get_irq(pdev, 0); > + if (port->irq < 0) > + return port->irq; > + > + port->type = PORT_MCF; > + port->dev = &pdev->dev; > + port->iotype = SERIAL_IO_MEM; > + port->uartclk = MCF_BUSCLK; > + port->ops = &mcf_uart_ops; > + port->flags = UPF_BOOT_AUTOCONF; > + port->rs485_config = mcf_config_rs485; > + port->rs485_supported = mcf_rs485_supported; > + port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_MCF_CONSOLE); > + > + pp = container_of(port, struct mcf_uart, port); > + > + uart_add_one_port(&mcf_driver, port); > + This breaks platforms with more than one UART - which is quite a few of the ColdFire platforms. Numerous boards bring and use more than one UART. Regards Greg > return 0; > } > > @@ -603,13 +618,11 @@ static int mcf_probe(struct platform_device *pdev) > static void mcf_remove(struct platform_device *pdev) > { > struct uart_port *port; > - int i; > + int id = pdev->id; > > - for (i = 0; (i < MCF_MAXPORTS); i++) { > - port = &mcf_ports[i].port; > - if (port) > - uart_remove_one_port(&mcf_driver, port); > - } > + port = &mcf_ports[id].port; > + if (port) > + uart_remove_one_port(&mcf_driver, port); > } > > /****************************************************************************/ > > --- > base-commit: e457f18d7f25288d143c1fe024a620d0b15caec1 > change-id: 20241202-m5441x_uart_resource-729b30c15363 > > Best regards,
Hi Greg, On 04/12/2024 11:54, Greg Ungerer wrote: > Hi JM, > > On 2/12/24 20:34, Jean-Michel Hautbois wrote: >> In order to use the eDMA channels for UART, the mcf_platform_uart needs >> to be changed. Instead of adding another custom member for the >> structure, use a resource tree in a platform_device per UART. It then >> makes it possible to have a device named like "mcfuart.N" with N the >> UART number. >> >> Later, adding the dma channel in the mcf tty driver will also be more >> straightfoward. >> >> Signed-off-by: Jean-Michel Hautbois <jeanmichel.hautbois@yoseli.org> >> --- >> arch/m68k/coldfire/device.c | 96 +++++++++++++ >> +------------------------------- >> drivers/tty/serial/mcf.c | 69 +++++++++++++++++++------------- >> 2 files changed, 70 insertions(+), 95 deletions(-) >> >> diff --git a/arch/m68k/coldfire/device.c b/arch/m68k/coldfire/device.c >> index >> b6958ec2a220cf91a78a14fc7fa18749451412f7..fd7d0b0ce7eb2970cb8ffe33589fe8d7e88c268d 100644 >> --- a/arch/m68k/coldfire/device.c >> +++ b/arch/m68k/coldfire/device.c >> @@ -24,73 +24,35 @@ >> #include <linux/platform_data/dma-mcf-edma.h> >> #include <linux/platform_data/mmc-esdhc-mcf.h> >> -/* >> - * All current ColdFire parts contain from 2, 3, 4 or 10 UARTS. >> - */ >> -static struct mcf_platform_uart mcf_uart_platform_data[] = { >> - { >> - .mapbase = MCFUART_BASE0, >> - .irq = MCF_IRQ_UART0, >> - }, >> - { >> - .mapbase = MCFUART_BASE1, >> - .irq = MCF_IRQ_UART1, >> - }, >> -#ifdef MCFUART_BASE2 >> - { >> - .mapbase = MCFUART_BASE2, >> - .irq = MCF_IRQ_UART2, >> - }, >> -#endif >> -#ifdef MCFUART_BASE3 >> - { >> - .mapbase = MCFUART_BASE3, >> - .irq = MCF_IRQ_UART3, >> - }, >> -#endif >> -#ifdef MCFUART_BASE4 >> - { >> - .mapbase = MCFUART_BASE4, >> - .irq = MCF_IRQ_UART4, >> - }, >> -#endif >> -#ifdef MCFUART_BASE5 >> - { >> - .mapbase = MCFUART_BASE5, >> - .irq = MCF_IRQ_UART5, >> - }, >> -#endif >> -#ifdef MCFUART_BASE6 >> - { >> - .mapbase = MCFUART_BASE6, >> - .irq = MCF_IRQ_UART6, >> - }, >> -#endif >> -#ifdef MCFUART_BASE7 >> - { >> - .mapbase = MCFUART_BASE7, >> - .irq = MCF_IRQ_UART7, >> +static u64 mcf_uart_mask = DMA_BIT_MASK(32); >> + >> +static struct resource mcf_uart0_resource[] = { >> + [0] = { >> + .start = MCFUART_BASE0, >> + .end = MCFUART_BASE0 + 0x3fff, >> + .flags = IORESOURCE_MEM, >> }, >> -#endif >> -#ifdef MCFUART_BASE8 >> - { >> - .mapbase = MCFUART_BASE8, >> - .irq = MCF_IRQ_UART8, >> + [1] = { >> + .start = 2, >> + .end = 3, >> + .flags = IORESOURCE_DMA, >> }, >> -#endif >> -#ifdef MCFUART_BASE9 >> - { >> - .mapbase = MCFUART_BASE9, >> - .irq = MCF_IRQ_UART9, >> + [2] = { >> + .start = MCF_IRQ_UART0, >> + .end = MCF_IRQ_UART0, >> + .flags = IORESOURCE_IRQ, >> }, >> -#endif >> - { }, >> }; >> -static struct platform_device mcf_uart = { >> +static struct platform_device mcf_uart0 = { >> .name = "mcfuart", >> .id = 0, >> - .dev.platform_data = mcf_uart_platform_data, >> + .num_resources = ARRAY_SIZE(mcf_uart0_resource), >> + .resource = mcf_uart0_resource, >> + .dev = { >> + .dma_mask = &mcf_uart_mask, >> + .coherent_dma_mask = DMA_BIT_MASK(32), >> + }, >> }; >> #ifdef MCFFEC_BASE0 >> @@ -485,12 +447,12 @@ static struct platform_device mcf_i2c5 = { >> static const struct dma_slave_map mcf_edma_map[] = { >> { "dreq0", "rx-tx", MCF_EDMA_FILTER_PARAM(0) }, >> { "dreq1", "rx-tx", MCF_EDMA_FILTER_PARAM(1) }, >> - { "uart.0", "rx", MCF_EDMA_FILTER_PARAM(2) }, >> - { "uart.0", "tx", MCF_EDMA_FILTER_PARAM(3) }, >> - { "uart.1", "rx", MCF_EDMA_FILTER_PARAM(4) }, >> - { "uart.1", "tx", MCF_EDMA_FILTER_PARAM(5) }, >> - { "uart.2", "rx", MCF_EDMA_FILTER_PARAM(6) }, >> - { "uart.2", "tx", MCF_EDMA_FILTER_PARAM(7) }, >> + { "mcfuart.0", "rx", MCF_EDMA_FILTER_PARAM(2) }, >> + { "mcfuart.0", "tx", MCF_EDMA_FILTER_PARAM(3) }, >> + { "mcfuart.1", "rx", MCF_EDMA_FILTER_PARAM(4) }, >> + { "mcfuart.1", "tx", MCF_EDMA_FILTER_PARAM(5) }, >> + { "mcfuart.2", "rx", MCF_EDMA_FILTER_PARAM(6) }, >> + { "mcfuart.2", "tx", MCF_EDMA_FILTER_PARAM(7) }, >> { "timer0", "rx-tx", MCF_EDMA_FILTER_PARAM(8) }, >> { "timer1", "rx-tx", MCF_EDMA_FILTER_PARAM(9) }, >> { "timer2", "rx-tx", MCF_EDMA_FILTER_PARAM(10) }, >> @@ -623,7 +585,7 @@ static struct platform_device mcf_flexcan0 = { >> #endif /* MCFFLEXCAN_SIZE */ >> static struct platform_device *mcf_devices[] __initdata = { >> - &mcf_uart, >> + &mcf_uart0, >> #ifdef MCFFEC_BASE0 >> &mcf_fec0, >> #endif >> diff --git a/drivers/tty/serial/mcf.c b/drivers/tty/serial/mcf.c >> index >> 93e7dda4d39acd23daf8c0d4c29ac8d666f263c5..07b8decfdb6005f0265dd130765e45c3fd1715eb 100644 >> --- a/drivers/tty/serial/mcf.c >> +++ b/drivers/tty/serial/mcf.c >> @@ -570,31 +570,46 @@ static struct uart_driver mcf_driver = { >> static int mcf_probe(struct platform_device *pdev) >> { >> - struct mcf_platform_uart *platp = dev_get_platdata(&pdev->dev); >> struct uart_port *port; >> - int i; >> - >> - for (i = 0; ((i < MCF_MAXPORTS) && (platp[i].mapbase)); i++) { >> - port = &mcf_ports[i].port; >> - >> - port->line = i; >> - port->type = PORT_MCF; >> - port->mapbase = platp[i].mapbase; >> - port->membase = (platp[i].membase) ? platp[i].membase : >> - (unsigned char __iomem *) platp[i].mapbase; >> - port->dev = &pdev->dev; >> - port->iotype = SERIAL_IO_MEM; >> - port->irq = platp[i].irq; >> - port->uartclk = MCF_BUSCLK; >> - port->ops = &mcf_uart_ops; >> - port->flags = UPF_BOOT_AUTOCONF; >> - port->rs485_config = mcf_config_rs485; >> - port->rs485_supported = mcf_rs485_supported; >> - port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_MCF_CONSOLE); >> - >> - uart_add_one_port(&mcf_driver, port); >> + struct mcf_uart *pp; >> + struct resource *res; >> + void __iomem *base; >> + int id = pdev->id; >> + >> + if (id == -1 || id >= MCF_MAXPORTS) { >> + dev_err(&pdev->dev, "uart%d out of range\n", >> + id); >> + return -EINVAL; >> } >> + port = &mcf_ports[id].port; >> + port->line = id; >> + >> + base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); >> + if (IS_ERR(base)) >> + return PTR_ERR(base); >> + >> + port->mapbase = res->start; >> + port->membase = base; >> + >> + port->irq = platform_get_irq(pdev, 0); >> + if (port->irq < 0) >> + return port->irq; >> + >> + port->type = PORT_MCF; >> + port->dev = &pdev->dev; >> + port->iotype = SERIAL_IO_MEM; >> + port->uartclk = MCF_BUSCLK; >> + port->ops = &mcf_uart_ops; >> + port->flags = UPF_BOOT_AUTOCONF; >> + port->rs485_config = mcf_config_rs485; >> + port->rs485_supported = mcf_rs485_supported; >> + port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_MCF_CONSOLE); >> + >> + pp = container_of(port, struct mcf_uart, port); >> + >> + uart_add_one_port(&mcf_driver, port); >> + > > This breaks platforms with more than one UART - which is quite a few of > the ColdFire platforms. Numerous boards bring and use more than one UART. I don't get why, as I have two uarts here, and each is detected properly when declaring those in my platform ? I get that it breaks existing detection (we are parsing all uarts even when only one or two is used) but it does not prevent it to work ? static struct resource mcf_uart2_resource[] = { [0] = { .start = MCFUART_BASE2, .end = MCFUART_BASE2 + 0x3fff, .flags = IORESOURCE_MEM, }, [1] = { .start = 6, .end = 7, .flags = IORESOURCE_DMA, }, [2] = { .start = MCF_IRQ_UART2, .end = MCF_IRQ_UART2, .flags = IORESOURCE_IRQ, }, }; static struct platform_device mcf_uart2 = { .name = "mcfuart", .id = 2, .num_resources = ARRAY_SIZE(mcf_uart2_resource), .resource = mcf_uart2_resource, .dev = { .dma_mask = &mcf_uart_mask, .coherent_dma_mask = DMA_BIT_MASK(32), }, }; static struct resource mcf_uart6_resource[] = { [0] = { .start = MCFUART_BASE6, .end = MCFUART_BASE6 + 0x3fff, .flags = IORESOURCE_MEM, }, [1] = { .start = 22, .end = 23, .flags = IORESOURCE_DMA, }, [2] = { .start = MCF_IRQ_UART6, .end = MCF_IRQ_UART6, .flags = IORESOURCE_IRQ, }, }; static struct platform_device mcf_uart6 = { .name = "mcfuart", .id = 6, .num_resources = ARRAY_SIZE(mcf_uart6_resource), .resource = mcf_uart6_resource, .dev = { .dma_mask = &mcf_uart_mask, .coherent_dma_mask = DMA_BIT_MASK(32), }, }; JM > > Regards > Greg > > > >> return 0; >> } >> @@ -603,13 +618,11 @@ static int mcf_probe(struct platform_device *pdev) >> static void mcf_remove(struct platform_device *pdev) >> { >> struct uart_port *port; >> - int i; >> + int id = pdev->id; >> - for (i = 0; (i < MCF_MAXPORTS); i++) { >> - port = &mcf_ports[i].port; >> - if (port) >> - uart_remove_one_port(&mcf_driver, port); >> - } >> + port = &mcf_ports[id].port; >> + if (port) >> + uart_remove_one_port(&mcf_driver, port); >> } >> / >> ****************************************************************************/ >> >> --- >> base-commit: e457f18d7f25288d143c1fe024a620d0b15caec1 >> change-id: 20241202-m5441x_uart_resource-729b30c15363 >> >> Best regards,
Hi JM, On 4/12/24 20:58, Jean-Michel Hautbois wrote: > On 04/12/2024 11:54, Greg Ungerer wrote: >> On 2/12/24 20:34, Jean-Michel Hautbois wrote: >>> In order to use the eDMA channels for UART, the mcf_platform_uart needs >>> to be changed. Instead of adding another custom member for the >>> structure, use a resource tree in a platform_device per UART. It then >>> makes it possible to have a device named like "mcfuart.N" with N the >>> UART number. >>> >>> Later, adding the dma channel in the mcf tty driver will also be more >>> straightfoward. >>> >>> Signed-off-by: Jean-Michel Hautbois <jeanmichel.hautbois@yoseli.org> >>> --- >>> arch/m68k/coldfire/device.c | 96 +++++++++++++ +------------------------------- >>> drivers/tty/serial/mcf.c | 69 +++++++++++++++++++------------- >>> 2 files changed, 70 insertions(+), 95 deletions(-) >>> >>> diff --git a/arch/m68k/coldfire/device.c b/arch/m68k/coldfire/device.c >>> index b6958ec2a220cf91a78a14fc7fa18749451412f7..fd7d0b0ce7eb2970cb8ffe33589fe8d7e88c268d 100644 >>> --- a/arch/m68k/coldfire/device.c >>> +++ b/arch/m68k/coldfire/device.c >>> @@ -24,73 +24,35 @@ >>> #include <linux/platform_data/dma-mcf-edma.h> >>> #include <linux/platform_data/mmc-esdhc-mcf.h> >>> -/* >>> - * All current ColdFire parts contain from 2, 3, 4 or 10 UARTS. >>> - */ >>> -static struct mcf_platform_uart mcf_uart_platform_data[] = { >>> - { >>> - .mapbase = MCFUART_BASE0, >>> - .irq = MCF_IRQ_UART0, >>> - }, >>> - { >>> - .mapbase = MCFUART_BASE1, >>> - .irq = MCF_IRQ_UART1, >>> - }, >>> -#ifdef MCFUART_BASE2 >>> - { >>> - .mapbase = MCFUART_BASE2, >>> - .irq = MCF_IRQ_UART2, >>> - }, >>> -#endif >>> -#ifdef MCFUART_BASE3 >>> - { >>> - .mapbase = MCFUART_BASE3, >>> - .irq = MCF_IRQ_UART3, >>> - }, >>> -#endif >>> -#ifdef MCFUART_BASE4 >>> - { >>> - .mapbase = MCFUART_BASE4, >>> - .irq = MCF_IRQ_UART4, >>> - }, >>> -#endif >>> -#ifdef MCFUART_BASE5 >>> - { >>> - .mapbase = MCFUART_BASE5, >>> - .irq = MCF_IRQ_UART5, >>> - }, >>> -#endif >>> -#ifdef MCFUART_BASE6 >>> - { >>> - .mapbase = MCFUART_BASE6, >>> - .irq = MCF_IRQ_UART6, >>> - }, >>> -#endif >>> -#ifdef MCFUART_BASE7 >>> - { >>> - .mapbase = MCFUART_BASE7, >>> - .irq = MCF_IRQ_UART7, >>> +static u64 mcf_uart_mask = DMA_BIT_MASK(32); >>> + >>> +static struct resource mcf_uart0_resource[] = { >>> + [0] = { >>> + .start = MCFUART_BASE0, >>> + .end = MCFUART_BASE0 + 0x3fff, >>> + .flags = IORESOURCE_MEM, >>> }, >>> -#endif >>> -#ifdef MCFUART_BASE8 >>> - { >>> - .mapbase = MCFUART_BASE8, >>> - .irq = MCF_IRQ_UART8, >>> + [1] = { >>> + .start = 2, >>> + .end = 3, >>> + .flags = IORESOURCE_DMA, >>> }, >>> -#endif >>> -#ifdef MCFUART_BASE9 >>> - { >>> - .mapbase = MCFUART_BASE9, >>> - .irq = MCF_IRQ_UART9, >>> + [2] = { >>> + .start = MCF_IRQ_UART0, >>> + .end = MCF_IRQ_UART0, >>> + .flags = IORESOURCE_IRQ, >>> }, >>> -#endif >>> - { }, >>> }; >>> -static struct platform_device mcf_uart = { >>> +static struct platform_device mcf_uart0 = { >>> .name = "mcfuart", >>> .id = 0, >>> - .dev.platform_data = mcf_uart_platform_data, >>> + .num_resources = ARRAY_SIZE(mcf_uart0_resource), >>> + .resource = mcf_uart0_resource, >>> + .dev = { >>> + .dma_mask = &mcf_uart_mask, >>> + .coherent_dma_mask = DMA_BIT_MASK(32), >>> + }, >>> }; >>> #ifdef MCFFEC_BASE0 >>> @@ -485,12 +447,12 @@ static struct platform_device mcf_i2c5 = { >>> static const struct dma_slave_map mcf_edma_map[] = { >>> { "dreq0", "rx-tx", MCF_EDMA_FILTER_PARAM(0) }, >>> { "dreq1", "rx-tx", MCF_EDMA_FILTER_PARAM(1) }, >>> - { "uart.0", "rx", MCF_EDMA_FILTER_PARAM(2) }, >>> - { "uart.0", "tx", MCF_EDMA_FILTER_PARAM(3) }, >>> - { "uart.1", "rx", MCF_EDMA_FILTER_PARAM(4) }, >>> - { "uart.1", "tx", MCF_EDMA_FILTER_PARAM(5) }, >>> - { "uart.2", "rx", MCF_EDMA_FILTER_PARAM(6) }, >>> - { "uart.2", "tx", MCF_EDMA_FILTER_PARAM(7) }, >>> + { "mcfuart.0", "rx", MCF_EDMA_FILTER_PARAM(2) }, >>> + { "mcfuart.0", "tx", MCF_EDMA_FILTER_PARAM(3) }, >>> + { "mcfuart.1", "rx", MCF_EDMA_FILTER_PARAM(4) }, >>> + { "mcfuart.1", "tx", MCF_EDMA_FILTER_PARAM(5) }, >>> + { "mcfuart.2", "rx", MCF_EDMA_FILTER_PARAM(6) }, >>> + { "mcfuart.2", "tx", MCF_EDMA_FILTER_PARAM(7) }, >>> { "timer0", "rx-tx", MCF_EDMA_FILTER_PARAM(8) }, >>> { "timer1", "rx-tx", MCF_EDMA_FILTER_PARAM(9) }, >>> { "timer2", "rx-tx", MCF_EDMA_FILTER_PARAM(10) }, >>> @@ -623,7 +585,7 @@ static struct platform_device mcf_flexcan0 = { >>> #endif /* MCFFLEXCAN_SIZE */ >>> static struct platform_device *mcf_devices[] __initdata = { >>> - &mcf_uart, >>> + &mcf_uart0, >>> #ifdef MCFFEC_BASE0 >>> &mcf_fec0, >>> #endif >>> diff --git a/drivers/tty/serial/mcf.c b/drivers/tty/serial/mcf.c >>> index 93e7dda4d39acd23daf8c0d4c29ac8d666f263c5..07b8decfdb6005f0265dd130765e45c3fd1715eb 100644 >>> --- a/drivers/tty/serial/mcf.c >>> +++ b/drivers/tty/serial/mcf.c >>> @@ -570,31 +570,46 @@ static struct uart_driver mcf_driver = { >>> static int mcf_probe(struct platform_device *pdev) >>> { >>> - struct mcf_platform_uart *platp = dev_get_platdata(&pdev->dev); >>> struct uart_port *port; >>> - int i; >>> - >>> - for (i = 0; ((i < MCF_MAXPORTS) && (platp[i].mapbase)); i++) { >>> - port = &mcf_ports[i].port; >>> - >>> - port->line = i; >>> - port->type = PORT_MCF; >>> - port->mapbase = platp[i].mapbase; >>> - port->membase = (platp[i].membase) ? platp[i].membase : >>> - (unsigned char __iomem *) platp[i].mapbase; >>> - port->dev = &pdev->dev; >>> - port->iotype = SERIAL_IO_MEM; >>> - port->irq = platp[i].irq; >>> - port->uartclk = MCF_BUSCLK; >>> - port->ops = &mcf_uart_ops; >>> - port->flags = UPF_BOOT_AUTOCONF; >>> - port->rs485_config = mcf_config_rs485; >>> - port->rs485_supported = mcf_rs485_supported; >>> - port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_MCF_CONSOLE); >>> - >>> - uart_add_one_port(&mcf_driver, port); >>> + struct mcf_uart *pp; >>> + struct resource *res; >>> + void __iomem *base; >>> + int id = pdev->id; >>> + >>> + if (id == -1 || id >= MCF_MAXPORTS) { >>> + dev_err(&pdev->dev, "uart%d out of range\n", >>> + id); >>> + return -EINVAL; >>> } >>> + port = &mcf_ports[id].port; >>> + port->line = id; >>> + >>> + base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); >>> + if (IS_ERR(base)) >>> + return PTR_ERR(base); >>> + >>> + port->mapbase = res->start; >>> + port->membase = base; >>> + >>> + port->irq = platform_get_irq(pdev, 0); >>> + if (port->irq < 0) >>> + return port->irq; >>> + >>> + port->type = PORT_MCF; >>> + port->dev = &pdev->dev; >>> + port->iotype = SERIAL_IO_MEM; >>> + port->uartclk = MCF_BUSCLK; >>> + port->ops = &mcf_uart_ops; >>> + port->flags = UPF_BOOT_AUTOCONF; >>> + port->rs485_config = mcf_config_rs485; >>> + port->rs485_supported = mcf_rs485_supported; >>> + port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_MCF_CONSOLE); >>> + >>> + pp = container_of(port, struct mcf_uart, port); >>> + >>> + uart_add_one_port(&mcf_driver, port); >>> + >> >> This breaks platforms with more than one UART - which is quite a few of >> the ColdFire platforms. Numerous boards bring and use more than one UART. > > I don't get why, as I have two uarts here, and each is detected properly when declaring those in my platform ? I get that it breaks existing detection (we are parsing all uarts even when only one or two is used) but it does not prevent it to work ? Building and testing on an M5208EVB platform. With original un-modified code boot console shows: ... [ 0.110000] romfs: ROMFS MTD (C) 2007 Red Hat, Inc. [ 0.110000] ColdFire internal UART serial driver [ 0.110000] mcfuart.0: ttyS0 at MMIO 0xfc060000 (irq = 90, base_baud = 5208333) is a ColdFire UART [ 0.120000] printk: legacy console [ttyS0] enabled [ 0.120000] mcfuart.0: ttyS1 at MMIO 0xfc064000 (irq = 91, base_baud = 5208333) is a ColdFire UART [ 0.120000] mcfuart.0: ttyS2 at MMIO 0xfc068000 (irq = 92, base_baud = 5208333) is a ColdFire UART [ 0.130000] brd: module loaded ... But with this change applied only the first port is probed: ... [ 0.120000] romfs: ROMFS MTD (C) 2007 Red Hat, Inc. [ 0.120000] ColdFire internal UART serial driver [ 0.130000] mcfuart.0: ttyS0 at MMIO 0xfc060000 (irq = 90, base_baud = 5208333) is a ColdFire UART [ 0.130000] printk: legacy console [ttyS0] enabled [ 0.130000] brd: module loaded ... Regards Greg > static struct resource mcf_uart2_resource[] = { > [0] = { > .start = MCFUART_BASE2, > .end = MCFUART_BASE2 + 0x3fff, > .flags = IORESOURCE_MEM, > }, > [1] = { > .start = 6, > .end = 7, > .flags = IORESOURCE_DMA, > }, > [2] = { > .start = MCF_IRQ_UART2, > .end = MCF_IRQ_UART2, > .flags = IORESOURCE_IRQ, > }, > }; > > static struct platform_device mcf_uart2 = { > .name = "mcfuart", > .id = 2, > .num_resources = ARRAY_SIZE(mcf_uart2_resource), > .resource = mcf_uart2_resource, > .dev = { > .dma_mask = &mcf_uart_mask, > .coherent_dma_mask = DMA_BIT_MASK(32), > }, > }; > > static struct resource mcf_uart6_resource[] = { > [0] = { > .start = MCFUART_BASE6, > .end = MCFUART_BASE6 + 0x3fff, > .flags = IORESOURCE_MEM, > }, > [1] = { > .start = 22, > .end = 23, > .flags = IORESOURCE_DMA, > }, > [2] = { > .start = MCF_IRQ_UART6, > .end = MCF_IRQ_UART6, > .flags = IORESOURCE_IRQ, > }, > }; > > static struct platform_device mcf_uart6 = { > .name = "mcfuart", > .id = 6, > .num_resources = ARRAY_SIZE(mcf_uart6_resource), > .resource = mcf_uart6_resource, > .dev = { > .dma_mask = &mcf_uart_mask, > .coherent_dma_mask = DMA_BIT_MASK(32), > }, > }; > > JM > >> >> Regards >> Greg >> >> >> >>> return 0; >>> } >>> @@ -603,13 +618,11 @@ static int mcf_probe(struct platform_device *pdev) >>> static void mcf_remove(struct platform_device *pdev) >>> { >>> struct uart_port *port; >>> - int i; >>> + int id = pdev->id; >>> - for (i = 0; (i < MCF_MAXPORTS); i++) { >>> - port = &mcf_ports[i].port; >>> - if (port) >>> - uart_remove_one_port(&mcf_driver, port); >>> - } >>> + port = &mcf_ports[id].port; >>> + if (port) >>> + uart_remove_one_port(&mcf_driver, port); >>> } >>> / ****************************************************************************/ >>> >>> --- >>> base-commit: e457f18d7f25288d143c1fe024a620d0b15caec1 >>> change-id: 20241202-m5441x_uart_resource-729b30c15363 >>> >>> Best regards, >
Hi Greg, On 04/12/2024 12:15, Greg Ungerer wrote: > Hi JM, > > On 4/12/24 20:58, Jean-Michel Hautbois wrote: >> On 04/12/2024 11:54, Greg Ungerer wrote: >>> On 2/12/24 20:34, Jean-Michel Hautbois wrote: >>>> In order to use the eDMA channels for UART, the mcf_platform_uart needs >>>> to be changed. Instead of adding another custom member for the >>>> structure, use a resource tree in a platform_device per UART. It then >>>> makes it possible to have a device named like "mcfuart.N" with N the >>>> UART number. >>>> >>>> Later, adding the dma channel in the mcf tty driver will also be more >>>> straightfoward. >>>> >>>> Signed-off-by: Jean-Michel Hautbois <jeanmichel.hautbois@yoseli.org> >>>> --- >>>> arch/m68k/coldfire/device.c | 96 +++++++++++++ >>>> +------------------------------- >>>> drivers/tty/serial/mcf.c | 69 +++++++++++++++++++------------- >>>> 2 files changed, 70 insertions(+), 95 deletions(-) >>>> >>>> diff --git a/arch/m68k/coldfire/device.c b/arch/m68k/coldfire/device.c >>>> index >>>> b6958ec2a220cf91a78a14fc7fa18749451412f7..fd7d0b0ce7eb2970cb8ffe33589fe8d7e88c268d 100644 >>>> --- a/arch/m68k/coldfire/device.c >>>> +++ b/arch/m68k/coldfire/device.c >>>> @@ -24,73 +24,35 @@ >>>> #include <linux/platform_data/dma-mcf-edma.h> >>>> #include <linux/platform_data/mmc-esdhc-mcf.h> >>>> -/* >>>> - * All current ColdFire parts contain from 2, 3, 4 or 10 UARTS. >>>> - */ >>>> -static struct mcf_platform_uart mcf_uart_platform_data[] = { >>>> - { >>>> - .mapbase = MCFUART_BASE0, >>>> - .irq = MCF_IRQ_UART0, >>>> - }, >>>> - { >>>> - .mapbase = MCFUART_BASE1, >>>> - .irq = MCF_IRQ_UART1, >>>> - }, >>>> -#ifdef MCFUART_BASE2 >>>> - { >>>> - .mapbase = MCFUART_BASE2, >>>> - .irq = MCF_IRQ_UART2, >>>> - }, >>>> -#endif >>>> -#ifdef MCFUART_BASE3 >>>> - { >>>> - .mapbase = MCFUART_BASE3, >>>> - .irq = MCF_IRQ_UART3, >>>> - }, >>>> -#endif >>>> -#ifdef MCFUART_BASE4 >>>> - { >>>> - .mapbase = MCFUART_BASE4, >>>> - .irq = MCF_IRQ_UART4, >>>> - }, >>>> -#endif >>>> -#ifdef MCFUART_BASE5 >>>> - { >>>> - .mapbase = MCFUART_BASE5, >>>> - .irq = MCF_IRQ_UART5, >>>> - }, >>>> -#endif >>>> -#ifdef MCFUART_BASE6 >>>> - { >>>> - .mapbase = MCFUART_BASE6, >>>> - .irq = MCF_IRQ_UART6, >>>> - }, >>>> -#endif >>>> -#ifdef MCFUART_BASE7 >>>> - { >>>> - .mapbase = MCFUART_BASE7, >>>> - .irq = MCF_IRQ_UART7, >>>> +static u64 mcf_uart_mask = DMA_BIT_MASK(32); >>>> + >>>> +static struct resource mcf_uart0_resource[] = { >>>> + [0] = { >>>> + .start = MCFUART_BASE0, >>>> + .end = MCFUART_BASE0 + 0x3fff, >>>> + .flags = IORESOURCE_MEM, >>>> }, >>>> -#endif >>>> -#ifdef MCFUART_BASE8 >>>> - { >>>> - .mapbase = MCFUART_BASE8, >>>> - .irq = MCF_IRQ_UART8, >>>> + [1] = { >>>> + .start = 2, >>>> + .end = 3, >>>> + .flags = IORESOURCE_DMA, >>>> }, >>>> -#endif >>>> -#ifdef MCFUART_BASE9 >>>> - { >>>> - .mapbase = MCFUART_BASE9, >>>> - .irq = MCF_IRQ_UART9, >>>> + [2] = { >>>> + .start = MCF_IRQ_UART0, >>>> + .end = MCF_IRQ_UART0, >>>> + .flags = IORESOURCE_IRQ, >>>> }, >>>> -#endif >>>> - { }, >>>> }; >>>> -static struct platform_device mcf_uart = { >>>> +static struct platform_device mcf_uart0 = { >>>> .name = "mcfuart", >>>> .id = 0, >>>> - .dev.platform_data = mcf_uart_platform_data, >>>> + .num_resources = ARRAY_SIZE(mcf_uart0_resource), >>>> + .resource = mcf_uart0_resource, >>>> + .dev = { >>>> + .dma_mask = &mcf_uart_mask, >>>> + .coherent_dma_mask = DMA_BIT_MASK(32), >>>> + }, >>>> }; >>>> #ifdef MCFFEC_BASE0 >>>> @@ -485,12 +447,12 @@ static struct platform_device mcf_i2c5 = { >>>> static const struct dma_slave_map mcf_edma_map[] = { >>>> { "dreq0", "rx-tx", MCF_EDMA_FILTER_PARAM(0) }, >>>> { "dreq1", "rx-tx", MCF_EDMA_FILTER_PARAM(1) }, >>>> - { "uart.0", "rx", MCF_EDMA_FILTER_PARAM(2) }, >>>> - { "uart.0", "tx", MCF_EDMA_FILTER_PARAM(3) }, >>>> - { "uart.1", "rx", MCF_EDMA_FILTER_PARAM(4) }, >>>> - { "uart.1", "tx", MCF_EDMA_FILTER_PARAM(5) }, >>>> - { "uart.2", "rx", MCF_EDMA_FILTER_PARAM(6) }, >>>> - { "uart.2", "tx", MCF_EDMA_FILTER_PARAM(7) }, >>>> + { "mcfuart.0", "rx", MCF_EDMA_FILTER_PARAM(2) }, >>>> + { "mcfuart.0", "tx", MCF_EDMA_FILTER_PARAM(3) }, >>>> + { "mcfuart.1", "rx", MCF_EDMA_FILTER_PARAM(4) }, >>>> + { "mcfuart.1", "tx", MCF_EDMA_FILTER_PARAM(5) }, >>>> + { "mcfuart.2", "rx", MCF_EDMA_FILTER_PARAM(6) }, >>>> + { "mcfuart.2", "tx", MCF_EDMA_FILTER_PARAM(7) }, >>>> { "timer0", "rx-tx", MCF_EDMA_FILTER_PARAM(8) }, >>>> { "timer1", "rx-tx", MCF_EDMA_FILTER_PARAM(9) }, >>>> { "timer2", "rx-tx", MCF_EDMA_FILTER_PARAM(10) }, >>>> @@ -623,7 +585,7 @@ static struct platform_device mcf_flexcan0 = { >>>> #endif /* MCFFLEXCAN_SIZE */ >>>> static struct platform_device *mcf_devices[] __initdata = { >>>> - &mcf_uart, >>>> + &mcf_uart0, >>>> #ifdef MCFFEC_BASE0 >>>> &mcf_fec0, >>>> #endif >>>> diff --git a/drivers/tty/serial/mcf.c b/drivers/tty/serial/mcf.c >>>> index >>>> 93e7dda4d39acd23daf8c0d4c29ac8d666f263c5..07b8decfdb6005f0265dd130765e45c3fd1715eb 100644 >>>> --- a/drivers/tty/serial/mcf.c >>>> +++ b/drivers/tty/serial/mcf.c >>>> @@ -570,31 +570,46 @@ static struct uart_driver mcf_driver = { >>>> static int mcf_probe(struct platform_device *pdev) >>>> { >>>> - struct mcf_platform_uart *platp = dev_get_platdata(&pdev->dev); >>>> struct uart_port *port; >>>> - int i; >>>> - >>>> - for (i = 0; ((i < MCF_MAXPORTS) && (platp[i].mapbase)); i++) { >>>> - port = &mcf_ports[i].port; >>>> - >>>> - port->line = i; >>>> - port->type = PORT_MCF; >>>> - port->mapbase = platp[i].mapbase; >>>> - port->membase = (platp[i].membase) ? platp[i].membase : >>>> - (unsigned char __iomem *) platp[i].mapbase; >>>> - port->dev = &pdev->dev; >>>> - port->iotype = SERIAL_IO_MEM; >>>> - port->irq = platp[i].irq; >>>> - port->uartclk = MCF_BUSCLK; >>>> - port->ops = &mcf_uart_ops; >>>> - port->flags = UPF_BOOT_AUTOCONF; >>>> - port->rs485_config = mcf_config_rs485; >>>> - port->rs485_supported = mcf_rs485_supported; >>>> - port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_MCF_CONSOLE); >>>> - >>>> - uart_add_one_port(&mcf_driver, port); >>>> + struct mcf_uart *pp; >>>> + struct resource *res; >>>> + void __iomem *base; >>>> + int id = pdev->id; >>>> + >>>> + if (id == -1 || id >= MCF_MAXPORTS) { >>>> + dev_err(&pdev->dev, "uart%d out of range\n", >>>> + id); >>>> + return -EINVAL; >>>> } >>>> + port = &mcf_ports[id].port; >>>> + port->line = id; >>>> + >>>> + base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); >>>> + if (IS_ERR(base)) >>>> + return PTR_ERR(base); >>>> + >>>> + port->mapbase = res->start; >>>> + port->membase = base; >>>> + >>>> + port->irq = platform_get_irq(pdev, 0); >>>> + if (port->irq < 0) >>>> + return port->irq; >>>> + >>>> + port->type = PORT_MCF; >>>> + port->dev = &pdev->dev; >>>> + port->iotype = SERIAL_IO_MEM; >>>> + port->uartclk = MCF_BUSCLK; >>>> + port->ops = &mcf_uart_ops; >>>> + port->flags = UPF_BOOT_AUTOCONF; >>>> + port->rs485_config = mcf_config_rs485; >>>> + port->rs485_supported = mcf_rs485_supported; >>>> + port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_MCF_CONSOLE); >>>> + >>>> + pp = container_of(port, struct mcf_uart, port); >>>> + >>>> + uart_add_one_port(&mcf_driver, port); >>>> + >>> >>> This breaks platforms with more than one UART - which is quite a few of >>> the ColdFire platforms. Numerous boards bring and use more than one >>> UART. >> >> I don't get why, as I have two uarts here, and each is detected >> properly when declaring those in my platform ? I get that it breaks >> existing detection (we are parsing all uarts even when only one or two >> is used) but it does not prevent it to work ? > > Building and testing on an M5208EVB platform. > With original un-modified code boot console shows: > > ... > [ 0.110000] romfs: ROMFS MTD (C) 2007 Red Hat, Inc. > [ 0.110000] ColdFire internal UART serial driver > [ 0.110000] mcfuart.0: ttyS0 at MMIO 0xfc060000 (irq = 90, base_baud > = 5208333) is a ColdFire UART > [ 0.120000] printk: legacy console [ttyS0] enabled > [ 0.120000] mcfuart.0: ttyS1 at MMIO 0xfc064000 (irq = 91, base_baud > = 5208333) is a ColdFire UART > [ 0.120000] mcfuart.0: ttyS2 at MMIO 0xfc068000 (irq = 92, base_baud > = 5208333) is a ColdFire UART > [ 0.130000] brd: module loaded > ... > > > But with this change applied only the first port is probed: > > ... > [ 0.120000] romfs: ROMFS MTD (C) 2007 Red Hat, Inc. > [ 0.120000] ColdFire internal UART serial driver > [ 0.130000] mcfuart.0: ttyS0 at MMIO 0xfc060000 (irq = 90, base_baud > = 5208333) is a ColdFire UART > [ 0.130000] printk: legacy console [ttyS0] enabled > [ 0.130000] brd: module loaded > ... OK, I see what you mean. Let me try to explain why I did it :-). The idea is to avoid probing a UART device which may exist as such on the core, but not be used as UART at all (on my board, for instance, I have uart2 and uart6, I don't need any other UART to be probed). So, based on what I think is the dts philosophy, you declare the devices you really need to probe ? I can add all the uarts as resources with the ifdefs like before, but on the M54418 it will always probe 10 devices, which sounds like a bit overkill ? Thanks ! JM > > Regards > Greg > > > >> static struct resource mcf_uart2_resource[] = { >> [0] = { >> .start = MCFUART_BASE2, >> .end = MCFUART_BASE2 + 0x3fff, >> .flags = IORESOURCE_MEM, >> }, >> [1] = { >> .start = 6, >> .end = 7, >> .flags = IORESOURCE_DMA, >> }, >> [2] = { >> .start = MCF_IRQ_UART2, >> .end = MCF_IRQ_UART2, >> .flags = IORESOURCE_IRQ, >> }, >> }; >> >> static struct platform_device mcf_uart2 = { >> .name = "mcfuart", >> .id = 2, >> .num_resources = ARRAY_SIZE(mcf_uart2_resource), >> .resource = mcf_uart2_resource, >> .dev = { >> .dma_mask = &mcf_uart_mask, >> .coherent_dma_mask = DMA_BIT_MASK(32), >> }, >> }; >> >> static struct resource mcf_uart6_resource[] = { >> [0] = { >> .start = MCFUART_BASE6, >> .end = MCFUART_BASE6 + 0x3fff, >> .flags = IORESOURCE_MEM, >> }, >> [1] = { >> .start = 22, >> .end = 23, >> .flags = IORESOURCE_DMA, >> }, >> [2] = { >> .start = MCF_IRQ_UART6, >> .end = MCF_IRQ_UART6, >> .flags = IORESOURCE_IRQ, >> }, >> }; >> >> static struct platform_device mcf_uart6 = { >> .name = "mcfuart", >> .id = 6, >> .num_resources = ARRAY_SIZE(mcf_uart6_resource), >> .resource = mcf_uart6_resource, >> .dev = { >> .dma_mask = &mcf_uart_mask, >> .coherent_dma_mask = DMA_BIT_MASK(32), >> }, >> }; >> >> JM >> >>> >>> Regards >>> Greg >>> >>> >>> >>>> return 0; >>>> } >>>> @@ -603,13 +618,11 @@ static int mcf_probe(struct platform_device >>>> *pdev) >>>> static void mcf_remove(struct platform_device *pdev) >>>> { >>>> struct uart_port *port; >>>> - int i; >>>> + int id = pdev->id; >>>> - for (i = 0; (i < MCF_MAXPORTS); i++) { >>>> - port = &mcf_ports[i].port; >>>> - if (port) >>>> - uart_remove_one_port(&mcf_driver, port); >>>> - } >>>> + port = &mcf_ports[id].port; >>>> + if (port) >>>> + uart_remove_one_port(&mcf_driver, port); >>>> } >>>> / >>>> ****************************************************************************/ >>>> >>>> --- >>>> base-commit: e457f18d7f25288d143c1fe024a620d0b15caec1 >>>> change-id: 20241202-m5441x_uart_resource-729b30c15363 >>>> >>>> Best regards, >>
Hi JM, On 4/12/24 21:32, Jean-Michel Hautbois wrote: > On 04/12/2024 12:15, Greg Ungerer wrote: >> On 4/12/24 20:58, Jean-Michel Hautbois wrote: >>> On 04/12/2024 11:54, Greg Ungerer wrote: >>>> On 2/12/24 20:34, Jean-Michel Hautbois wrote: >>>>> In order to use the eDMA channels for UART, the mcf_platform_uart needs >>>>> to be changed. Instead of adding another custom member for the >>>>> structure, use a resource tree in a platform_device per UART. It then >>>>> makes it possible to have a device named like "mcfuart.N" with N the >>>>> UART number. >>>>> >>>>> Later, adding the dma channel in the mcf tty driver will also be more >>>>> straightfoward. >>>>> >>>>> Signed-off-by: Jean-Michel Hautbois <jeanmichel.hautbois@yoseli.org> >>>>> --- >>>>> arch/m68k/coldfire/device.c | 96 +++++++++++++ +------------------------------- >>>>> drivers/tty/serial/mcf.c | 69 +++++++++++++++++++------------- >>>>> 2 files changed, 70 insertions(+), 95 deletions(-) >>>>> >>>>> diff --git a/arch/m68k/coldfire/device.c b/arch/m68k/coldfire/device.c >>>>> index b6958ec2a220cf91a78a14fc7fa18749451412f7..fd7d0b0ce7eb2970cb8ffe33589fe8d7e88c268d 100644 >>>>> --- a/arch/m68k/coldfire/device.c >>>>> +++ b/arch/m68k/coldfire/device.c >>>>> @@ -24,73 +24,35 @@ >>>>> #include <linux/platform_data/dma-mcf-edma.h> >>>>> #include <linux/platform_data/mmc-esdhc-mcf.h> >>>>> -/* >>>>> - * All current ColdFire parts contain from 2, 3, 4 or 10 UARTS. >>>>> - */ >>>>> -static struct mcf_platform_uart mcf_uart_platform_data[] = { >>>>> - { >>>>> - .mapbase = MCFUART_BASE0, >>>>> - .irq = MCF_IRQ_UART0, >>>>> - }, >>>>> - { >>>>> - .mapbase = MCFUART_BASE1, >>>>> - .irq = MCF_IRQ_UART1, >>>>> - }, >>>>> -#ifdef MCFUART_BASE2 >>>>> - { >>>>> - .mapbase = MCFUART_BASE2, >>>>> - .irq = MCF_IRQ_UART2, >>>>> - }, >>>>> -#endif >>>>> -#ifdef MCFUART_BASE3 >>>>> - { >>>>> - .mapbase = MCFUART_BASE3, >>>>> - .irq = MCF_IRQ_UART3, >>>>> - }, >>>>> -#endif >>>>> -#ifdef MCFUART_BASE4 >>>>> - { >>>>> - .mapbase = MCFUART_BASE4, >>>>> - .irq = MCF_IRQ_UART4, >>>>> - }, >>>>> -#endif >>>>> -#ifdef MCFUART_BASE5 >>>>> - { >>>>> - .mapbase = MCFUART_BASE5, >>>>> - .irq = MCF_IRQ_UART5, >>>>> - }, >>>>> -#endif >>>>> -#ifdef MCFUART_BASE6 >>>>> - { >>>>> - .mapbase = MCFUART_BASE6, >>>>> - .irq = MCF_IRQ_UART6, >>>>> - }, >>>>> -#endif >>>>> -#ifdef MCFUART_BASE7 >>>>> - { >>>>> - .mapbase = MCFUART_BASE7, >>>>> - .irq = MCF_IRQ_UART7, >>>>> +static u64 mcf_uart_mask = DMA_BIT_MASK(32); >>>>> + >>>>> +static struct resource mcf_uart0_resource[] = { >>>>> + [0] = { >>>>> + .start = MCFUART_BASE0, >>>>> + .end = MCFUART_BASE0 + 0x3fff, >>>>> + .flags = IORESOURCE_MEM, >>>>> }, >>>>> -#endif >>>>> -#ifdef MCFUART_BASE8 >>>>> - { >>>>> - .mapbase = MCFUART_BASE8, >>>>> - .irq = MCF_IRQ_UART8, >>>>> + [1] = { >>>>> + .start = 2, >>>>> + .end = 3, >>>>> + .flags = IORESOURCE_DMA, >>>>> }, >>>>> -#endif >>>>> -#ifdef MCFUART_BASE9 >>>>> - { >>>>> - .mapbase = MCFUART_BASE9, >>>>> - .irq = MCF_IRQ_UART9, >>>>> + [2] = { >>>>> + .start = MCF_IRQ_UART0, >>>>> + .end = MCF_IRQ_UART0, >>>>> + .flags = IORESOURCE_IRQ, >>>>> }, >>>>> -#endif >>>>> - { }, >>>>> }; >>>>> -static struct platform_device mcf_uart = { >>>>> +static struct platform_device mcf_uart0 = { >>>>> .name = "mcfuart", >>>>> .id = 0, >>>>> - .dev.platform_data = mcf_uart_platform_data, >>>>> + .num_resources = ARRAY_SIZE(mcf_uart0_resource), >>>>> + .resource = mcf_uart0_resource, >>>>> + .dev = { >>>>> + .dma_mask = &mcf_uart_mask, >>>>> + .coherent_dma_mask = DMA_BIT_MASK(32), >>>>> + }, >>>>> }; >>>>> #ifdef MCFFEC_BASE0 >>>>> @@ -485,12 +447,12 @@ static struct platform_device mcf_i2c5 = { >>>>> static const struct dma_slave_map mcf_edma_map[] = { >>>>> { "dreq0", "rx-tx", MCF_EDMA_FILTER_PARAM(0) }, >>>>> { "dreq1", "rx-tx", MCF_EDMA_FILTER_PARAM(1) }, >>>>> - { "uart.0", "rx", MCF_EDMA_FILTER_PARAM(2) }, >>>>> - { "uart.0", "tx", MCF_EDMA_FILTER_PARAM(3) }, >>>>> - { "uart.1", "rx", MCF_EDMA_FILTER_PARAM(4) }, >>>>> - { "uart.1", "tx", MCF_EDMA_FILTER_PARAM(5) }, >>>>> - { "uart.2", "rx", MCF_EDMA_FILTER_PARAM(6) }, >>>>> - { "uart.2", "tx", MCF_EDMA_FILTER_PARAM(7) }, >>>>> + { "mcfuart.0", "rx", MCF_EDMA_FILTER_PARAM(2) }, >>>>> + { "mcfuart.0", "tx", MCF_EDMA_FILTER_PARAM(3) }, >>>>> + { "mcfuart.1", "rx", MCF_EDMA_FILTER_PARAM(4) }, >>>>> + { "mcfuart.1", "tx", MCF_EDMA_FILTER_PARAM(5) }, >>>>> + { "mcfuart.2", "rx", MCF_EDMA_FILTER_PARAM(6) }, >>>>> + { "mcfuart.2", "tx", MCF_EDMA_FILTER_PARAM(7) }, >>>>> { "timer0", "rx-tx", MCF_EDMA_FILTER_PARAM(8) }, >>>>> { "timer1", "rx-tx", MCF_EDMA_FILTER_PARAM(9) }, >>>>> { "timer2", "rx-tx", MCF_EDMA_FILTER_PARAM(10) }, >>>>> @@ -623,7 +585,7 @@ static struct platform_device mcf_flexcan0 = { >>>>> #endif /* MCFFLEXCAN_SIZE */ >>>>> static struct platform_device *mcf_devices[] __initdata = { >>>>> - &mcf_uart, >>>>> + &mcf_uart0, >>>>> #ifdef MCFFEC_BASE0 >>>>> &mcf_fec0, >>>>> #endif >>>>> diff --git a/drivers/tty/serial/mcf.c b/drivers/tty/serial/mcf.c >>>>> index 93e7dda4d39acd23daf8c0d4c29ac8d666f263c5..07b8decfdb6005f0265dd130765e45c3fd1715eb 100644 >>>>> --- a/drivers/tty/serial/mcf.c >>>>> +++ b/drivers/tty/serial/mcf.c >>>>> @@ -570,31 +570,46 @@ static struct uart_driver mcf_driver = { >>>>> static int mcf_probe(struct platform_device *pdev) >>>>> { >>>>> - struct mcf_platform_uart *platp = dev_get_platdata(&pdev->dev); >>>>> struct uart_port *port; >>>>> - int i; >>>>> - >>>>> - for (i = 0; ((i < MCF_MAXPORTS) && (platp[i].mapbase)); i++) { >>>>> - port = &mcf_ports[i].port; >>>>> - >>>>> - port->line = i; >>>>> - port->type = PORT_MCF; >>>>> - port->mapbase = platp[i].mapbase; >>>>> - port->membase = (platp[i].membase) ? platp[i].membase : >>>>> - (unsigned char __iomem *) platp[i].mapbase; >>>>> - port->dev = &pdev->dev; >>>>> - port->iotype = SERIAL_IO_MEM; >>>>> - port->irq = platp[i].irq; >>>>> - port->uartclk = MCF_BUSCLK; >>>>> - port->ops = &mcf_uart_ops; >>>>> - port->flags = UPF_BOOT_AUTOCONF; >>>>> - port->rs485_config = mcf_config_rs485; >>>>> - port->rs485_supported = mcf_rs485_supported; >>>>> - port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_MCF_CONSOLE); >>>>> - >>>>> - uart_add_one_port(&mcf_driver, port); >>>>> + struct mcf_uart *pp; >>>>> + struct resource *res; >>>>> + void __iomem *base; >>>>> + int id = pdev->id; >>>>> + >>>>> + if (id == -1 || id >= MCF_MAXPORTS) { >>>>> + dev_err(&pdev->dev, "uart%d out of range\n", >>>>> + id); >>>>> + return -EINVAL; >>>>> } >>>>> + port = &mcf_ports[id].port; >>>>> + port->line = id; >>>>> + >>>>> + base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); >>>>> + if (IS_ERR(base)) >>>>> + return PTR_ERR(base); >>>>> + >>>>> + port->mapbase = res->start; >>>>> + port->membase = base; >>>>> + >>>>> + port->irq = platform_get_irq(pdev, 0); >>>>> + if (port->irq < 0) >>>>> + return port->irq; >>>>> + >>>>> + port->type = PORT_MCF; >>>>> + port->dev = &pdev->dev; >>>>> + port->iotype = SERIAL_IO_MEM; >>>>> + port->uartclk = MCF_BUSCLK; >>>>> + port->ops = &mcf_uart_ops; >>>>> + port->flags = UPF_BOOT_AUTOCONF; >>>>> + port->rs485_config = mcf_config_rs485; >>>>> + port->rs485_supported = mcf_rs485_supported; >>>>> + port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_MCF_CONSOLE); >>>>> + >>>>> + pp = container_of(port, struct mcf_uart, port); >>>>> + >>>>> + uart_add_one_port(&mcf_driver, port); >>>>> + >>>> >>>> This breaks platforms with more than one UART - which is quite a few of >>>> the ColdFire platforms. Numerous boards bring and use more than one UART. >>> >>> I don't get why, as I have two uarts here, and each is detected properly when declaring those in my platform ? I get that it breaks existing detection (we are parsing all uarts even when only one or two is used) but it does not prevent it to work ? >> >> Building and testing on an M5208EVB platform. >> With original un-modified code boot console shows: >> >> ... >> [ 0.110000] romfs: ROMFS MTD (C) 2007 Red Hat, Inc. >> [ 0.110000] ColdFire internal UART serial driver >> [ 0.110000] mcfuart.0: ttyS0 at MMIO 0xfc060000 (irq = 90, base_baud = 5208333) is a ColdFire UART >> [ 0.120000] printk: legacy console [ttyS0] enabled >> [ 0.120000] mcfuart.0: ttyS1 at MMIO 0xfc064000 (irq = 91, base_baud = 5208333) is a ColdFire UART >> [ 0.120000] mcfuart.0: ttyS2 at MMIO 0xfc068000 (irq = 92, base_baud = 5208333) is a ColdFire UART >> [ 0.130000] brd: module loaded >> ... >> >> >> But with this change applied only the first port is probed: >> >> ... >> [ 0.120000] romfs: ROMFS MTD (C) 2007 Red Hat, Inc. >> [ 0.120000] ColdFire internal UART serial driver >> [ 0.130000] mcfuart.0: ttyS0 at MMIO 0xfc060000 (irq = 90, base_baud = 5208333) is a ColdFire UART >> [ 0.130000] printk: legacy console [ttyS0] enabled >> [ 0.130000] brd: module loaded >> ... > > OK, I see what you mean. Let me try to explain why I did it :-). > > The idea is to avoid probing a UART device which may exist as such on the core, but not be used as UART at all (on my board, for instance, I have uart2 and uart6, I don't need any other UART to be probed). > > So, based on what I think is the dts philosophy, you declare the devices you really need to probe ? You can do this too, with the old style platform setups. What you want is to have a separate board file just for your board. There is a few examples already in arch/m68k/coldfire/ like amcore.c, firebee.c, nettel.c and stmark2.c. None currently specifically extract out UARTS - no one really seemed to have a need for that in the past. Most ColdFire parts have 2 or 3 UARTS, the 5441x family is an out-lier here with 10. Anyway, the device.c entries are really just a catch-all for the most common devices and their most commonly used configurations. Regards Greg > I can add all the uarts as resources with the ifdefs like before, but on the M54418 it will always probe 10 devices, which sounds like a bit overkill ? > > Thanks ! > JM > >> >> Regards >> Greg >> >> >> >>> static struct resource mcf_uart2_resource[] = { >>> [0] = { >>> .start = MCFUART_BASE2, >>> .end = MCFUART_BASE2 + 0x3fff, >>> .flags = IORESOURCE_MEM, >>> }, >>> [1] = { >>> .start = 6, >>> .end = 7, >>> .flags = IORESOURCE_DMA, >>> }, >>> [2] = { >>> .start = MCF_IRQ_UART2, >>> .end = MCF_IRQ_UART2, >>> .flags = IORESOURCE_IRQ, >>> }, >>> }; >>> >>> static struct platform_device mcf_uart2 = { >>> .name = "mcfuart", >>> .id = 2, >>> .num_resources = ARRAY_SIZE(mcf_uart2_resource), >>> .resource = mcf_uart2_resource, >>> .dev = { >>> .dma_mask = &mcf_uart_mask, >>> .coherent_dma_mask = DMA_BIT_MASK(32), >>> }, >>> }; >>> >>> static struct resource mcf_uart6_resource[] = { >>> [0] = { >>> .start = MCFUART_BASE6, >>> .end = MCFUART_BASE6 + 0x3fff, >>> .flags = IORESOURCE_MEM, >>> }, >>> [1] = { >>> .start = 22, >>> .end = 23, >>> .flags = IORESOURCE_DMA, >>> }, >>> [2] = { >>> .start = MCF_IRQ_UART6, >>> .end = MCF_IRQ_UART6, >>> .flags = IORESOURCE_IRQ, >>> }, >>> }; >>> >>> static struct platform_device mcf_uart6 = { >>> .name = "mcfuart", >>> .id = 6, >>> .num_resources = ARRAY_SIZE(mcf_uart6_resource), >>> .resource = mcf_uart6_resource, >>> .dev = { >>> .dma_mask = &mcf_uart_mask, >>> .coherent_dma_mask = DMA_BIT_MASK(32), >>> }, >>> }; >>> >>> JM >>> >>>> >>>> Regards >>>> Greg >>>> >>>> >>>> >>>>> return 0; >>>>> } >>>>> @@ -603,13 +618,11 @@ static int mcf_probe(struct platform_device *pdev) >>>>> static void mcf_remove(struct platform_device *pdev) >>>>> { >>>>> struct uart_port *port; >>>>> - int i; >>>>> + int id = pdev->id; >>>>> - for (i = 0; (i < MCF_MAXPORTS); i++) { >>>>> - port = &mcf_ports[i].port; >>>>> - if (port) >>>>> - uart_remove_one_port(&mcf_driver, port); >>>>> - } >>>>> + port = &mcf_ports[id].port; >>>>> + if (port) >>>>> + uart_remove_one_port(&mcf_driver, port); >>>>> } >>>>> / ****************************************************************************/ >>>>> >>>>> --- >>>>> base-commit: e457f18d7f25288d143c1fe024a620d0b15caec1 >>>>> change-id: 20241202-m5441x_uart_resource-729b30c15363 >>>>> >>>>> Best regards, >>> >
Hi Greg, On 05/12/2024 14:01, Greg Ungerer wrote: > Hi JM, > > On 4/12/24 21:32, Jean-Michel Hautbois wrote: >> On 04/12/2024 12:15, Greg Ungerer wrote: >>> On 4/12/24 20:58, Jean-Michel Hautbois wrote: >>>> On 04/12/2024 11:54, Greg Ungerer wrote: >>>>> On 2/12/24 20:34, Jean-Michel Hautbois wrote: >>>>>> In order to use the eDMA channels for UART, the mcf_platform_uart >>>>>> needs >>>>>> to be changed. Instead of adding another custom member for the >>>>>> structure, use a resource tree in a platform_device per UART. It then >>>>>> makes it possible to have a device named like "mcfuart.N" with N the >>>>>> UART number. >>>>>> >>>>>> Later, adding the dma channel in the mcf tty driver will also be more >>>>>> straightfoward. >>>>>> >>>>>> Signed-off-by: Jean-Michel Hautbois <jeanmichel.hautbois@yoseli.org> >>>>>> --- >>>>>> arch/m68k/coldfire/device.c | 96 +++++++++++++ >>>>>> +------------------------------- >>>>>> drivers/tty/serial/mcf.c | 69 +++++++++++++++++++------------- >>>>>> 2 files changed, 70 insertions(+), 95 deletions(-) >>>>>> >>>>>> diff --git a/arch/m68k/coldfire/device.c b/arch/m68k/coldfire/ >>>>>> device.c >>>>>> index >>>>>> b6958ec2a220cf91a78a14fc7fa18749451412f7..fd7d0b0ce7eb2970cb8ffe33589fe8d7e88c268d 100644 >>>>>> --- a/arch/m68k/coldfire/device.c >>>>>> +++ b/arch/m68k/coldfire/device.c >>>>>> @@ -24,73 +24,35 @@ >>>>>> #include <linux/platform_data/dma-mcf-edma.h> >>>>>> #include <linux/platform_data/mmc-esdhc-mcf.h> >>>>>> -/* >>>>>> - * All current ColdFire parts contain from 2, 3, 4 or 10 UARTS. >>>>>> - */ >>>>>> -static struct mcf_platform_uart mcf_uart_platform_data[] = { >>>>>> - { >>>>>> - .mapbase = MCFUART_BASE0, >>>>>> - .irq = MCF_IRQ_UART0, >>>>>> - }, >>>>>> - { >>>>>> - .mapbase = MCFUART_BASE1, >>>>>> - .irq = MCF_IRQ_UART1, >>>>>> - }, >>>>>> -#ifdef MCFUART_BASE2 >>>>>> - { >>>>>> - .mapbase = MCFUART_BASE2, >>>>>> - .irq = MCF_IRQ_UART2, >>>>>> - }, >>>>>> -#endif >>>>>> -#ifdef MCFUART_BASE3 >>>>>> - { >>>>>> - .mapbase = MCFUART_BASE3, >>>>>> - .irq = MCF_IRQ_UART3, >>>>>> - }, >>>>>> -#endif >>>>>> -#ifdef MCFUART_BASE4 >>>>>> - { >>>>>> - .mapbase = MCFUART_BASE4, >>>>>> - .irq = MCF_IRQ_UART4, >>>>>> - }, >>>>>> -#endif >>>>>> -#ifdef MCFUART_BASE5 >>>>>> - { >>>>>> - .mapbase = MCFUART_BASE5, >>>>>> - .irq = MCF_IRQ_UART5, >>>>>> - }, >>>>>> -#endif >>>>>> -#ifdef MCFUART_BASE6 >>>>>> - { >>>>>> - .mapbase = MCFUART_BASE6, >>>>>> - .irq = MCF_IRQ_UART6, >>>>>> - }, >>>>>> -#endif >>>>>> -#ifdef MCFUART_BASE7 >>>>>> - { >>>>>> - .mapbase = MCFUART_BASE7, >>>>>> - .irq = MCF_IRQ_UART7, >>>>>> +static u64 mcf_uart_mask = DMA_BIT_MASK(32); >>>>>> + >>>>>> +static struct resource mcf_uart0_resource[] = { >>>>>> + [0] = { >>>>>> + .start = MCFUART_BASE0, >>>>>> + .end = MCFUART_BASE0 + 0x3fff, >>>>>> + .flags = IORESOURCE_MEM, >>>>>> }, >>>>>> -#endif >>>>>> -#ifdef MCFUART_BASE8 >>>>>> - { >>>>>> - .mapbase = MCFUART_BASE8, >>>>>> - .irq = MCF_IRQ_UART8, >>>>>> + [1] = { >>>>>> + .start = 2, >>>>>> + .end = 3, >>>>>> + .flags = IORESOURCE_DMA, >>>>>> }, >>>>>> -#endif >>>>>> -#ifdef MCFUART_BASE9 >>>>>> - { >>>>>> - .mapbase = MCFUART_BASE9, >>>>>> - .irq = MCF_IRQ_UART9, >>>>>> + [2] = { >>>>>> + .start = MCF_IRQ_UART0, >>>>>> + .end = MCF_IRQ_UART0, >>>>>> + .flags = IORESOURCE_IRQ, >>>>>> }, >>>>>> -#endif >>>>>> - { }, >>>>>> }; >>>>>> -static struct platform_device mcf_uart = { >>>>>> +static struct platform_device mcf_uart0 = { >>>>>> .name = "mcfuart", >>>>>> .id = 0, >>>>>> - .dev.platform_data = mcf_uart_platform_data, >>>>>> + .num_resources = ARRAY_SIZE(mcf_uart0_resource), >>>>>> + .resource = mcf_uart0_resource, >>>>>> + .dev = { >>>>>> + .dma_mask = &mcf_uart_mask, >>>>>> + .coherent_dma_mask = DMA_BIT_MASK(32), >>>>>> + }, >>>>>> }; >>>>>> #ifdef MCFFEC_BASE0 >>>>>> @@ -485,12 +447,12 @@ static struct platform_device mcf_i2c5 = { >>>>>> static const struct dma_slave_map mcf_edma_map[] = { >>>>>> { "dreq0", "rx-tx", MCF_EDMA_FILTER_PARAM(0) }, >>>>>> { "dreq1", "rx-tx", MCF_EDMA_FILTER_PARAM(1) }, >>>>>> - { "uart.0", "rx", MCF_EDMA_FILTER_PARAM(2) }, >>>>>> - { "uart.0", "tx", MCF_EDMA_FILTER_PARAM(3) }, >>>>>> - { "uart.1", "rx", MCF_EDMA_FILTER_PARAM(4) }, >>>>>> - { "uart.1", "tx", MCF_EDMA_FILTER_PARAM(5) }, >>>>>> - { "uart.2", "rx", MCF_EDMA_FILTER_PARAM(6) }, >>>>>> - { "uart.2", "tx", MCF_EDMA_FILTER_PARAM(7) }, >>>>>> + { "mcfuart.0", "rx", MCF_EDMA_FILTER_PARAM(2) }, >>>>>> + { "mcfuart.0", "tx", MCF_EDMA_FILTER_PARAM(3) }, >>>>>> + { "mcfuart.1", "rx", MCF_EDMA_FILTER_PARAM(4) }, >>>>>> + { "mcfuart.1", "tx", MCF_EDMA_FILTER_PARAM(5) }, >>>>>> + { "mcfuart.2", "rx", MCF_EDMA_FILTER_PARAM(6) }, >>>>>> + { "mcfuart.2", "tx", MCF_EDMA_FILTER_PARAM(7) }, >>>>>> { "timer0", "rx-tx", MCF_EDMA_FILTER_PARAM(8) }, >>>>>> { "timer1", "rx-tx", MCF_EDMA_FILTER_PARAM(9) }, >>>>>> { "timer2", "rx-tx", MCF_EDMA_FILTER_PARAM(10) }, >>>>>> @@ -623,7 +585,7 @@ static struct platform_device mcf_flexcan0 = { >>>>>> #endif /* MCFFLEXCAN_SIZE */ >>>>>> static struct platform_device *mcf_devices[] __initdata = { >>>>>> - &mcf_uart, >>>>>> + &mcf_uart0, >>>>>> #ifdef MCFFEC_BASE0 >>>>>> &mcf_fec0, >>>>>> #endif >>>>>> diff --git a/drivers/tty/serial/mcf.c b/drivers/tty/serial/mcf.c >>>>>> index >>>>>> 93e7dda4d39acd23daf8c0d4c29ac8d666f263c5..07b8decfdb6005f0265dd130765e45c3fd1715eb 100644 >>>>>> --- a/drivers/tty/serial/mcf.c >>>>>> +++ b/drivers/tty/serial/mcf.c >>>>>> @@ -570,31 +570,46 @@ static struct uart_driver mcf_driver = { >>>>>> static int mcf_probe(struct platform_device *pdev) >>>>>> { >>>>>> - struct mcf_platform_uart *platp = dev_get_platdata(&pdev->dev); >>>>>> struct uart_port *port; >>>>>> - int i; >>>>>> - >>>>>> - for (i = 0; ((i < MCF_MAXPORTS) && (platp[i].mapbase)); i++) { >>>>>> - port = &mcf_ports[i].port; >>>>>> - >>>>>> - port->line = i; >>>>>> - port->type = PORT_MCF; >>>>>> - port->mapbase = platp[i].mapbase; >>>>>> - port->membase = (platp[i].membase) ? platp[i].membase : >>>>>> - (unsigned char __iomem *) platp[i].mapbase; >>>>>> - port->dev = &pdev->dev; >>>>>> - port->iotype = SERIAL_IO_MEM; >>>>>> - port->irq = platp[i].irq; >>>>>> - port->uartclk = MCF_BUSCLK; >>>>>> - port->ops = &mcf_uart_ops; >>>>>> - port->flags = UPF_BOOT_AUTOCONF; >>>>>> - port->rs485_config = mcf_config_rs485; >>>>>> - port->rs485_supported = mcf_rs485_supported; >>>>>> - port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_MCF_CONSOLE); >>>>>> - >>>>>> - uart_add_one_port(&mcf_driver, port); >>>>>> + struct mcf_uart *pp; >>>>>> + struct resource *res; >>>>>> + void __iomem *base; >>>>>> + int id = pdev->id; >>>>>> + >>>>>> + if (id == -1 || id >= MCF_MAXPORTS) { >>>>>> + dev_err(&pdev->dev, "uart%d out of range\n", >>>>>> + id); >>>>>> + return -EINVAL; >>>>>> } >>>>>> + port = &mcf_ports[id].port; >>>>>> + port->line = id; >>>>>> + >>>>>> + base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); >>>>>> + if (IS_ERR(base)) >>>>>> + return PTR_ERR(base); >>>>>> + >>>>>> + port->mapbase = res->start; >>>>>> + port->membase = base; >>>>>> + >>>>>> + port->irq = platform_get_irq(pdev, 0); >>>>>> + if (port->irq < 0) >>>>>> + return port->irq; >>>>>> + >>>>>> + port->type = PORT_MCF; >>>>>> + port->dev = &pdev->dev; >>>>>> + port->iotype = SERIAL_IO_MEM; >>>>>> + port->uartclk = MCF_BUSCLK; >>>>>> + port->ops = &mcf_uart_ops; >>>>>> + port->flags = UPF_BOOT_AUTOCONF; >>>>>> + port->rs485_config = mcf_config_rs485; >>>>>> + port->rs485_supported = mcf_rs485_supported; >>>>>> + port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_MCF_CONSOLE); >>>>>> + >>>>>> + pp = container_of(port, struct mcf_uart, port); >>>>>> + >>>>>> + uart_add_one_port(&mcf_driver, port); >>>>>> + >>>>> >>>>> This breaks platforms with more than one UART - which is quite a >>>>> few of >>>>> the ColdFire platforms. Numerous boards bring and use more than one >>>>> UART. >>>> >>>> I don't get why, as I have two uarts here, and each is detected >>>> properly when declaring those in my platform ? I get that it breaks >>>> existing detection (we are parsing all uarts even when only one or >>>> two is used) but it does not prevent it to work ? >>> >>> Building and testing on an M5208EVB platform. >>> With original un-modified code boot console shows: >>> >>> ... >>> [ 0.110000] romfs: ROMFS MTD (C) 2007 Red Hat, Inc. >>> [ 0.110000] ColdFire internal UART serial driver >>> [ 0.110000] mcfuart.0: ttyS0 at MMIO 0xfc060000 (irq = 90, >>> base_baud = 5208333) is a ColdFire UART >>> [ 0.120000] printk: legacy console [ttyS0] enabled >>> [ 0.120000] mcfuart.0: ttyS1 at MMIO 0xfc064000 (irq = 91, >>> base_baud = 5208333) is a ColdFire UART >>> [ 0.120000] mcfuart.0: ttyS2 at MMIO 0xfc068000 (irq = 92, >>> base_baud = 5208333) is a ColdFire UART >>> [ 0.130000] brd: module loaded >>> ... >>> >>> >>> But with this change applied only the first port is probed: >>> >>> ... >>> [ 0.120000] romfs: ROMFS MTD (C) 2007 Red Hat, Inc. >>> [ 0.120000] ColdFire internal UART serial driver >>> [ 0.130000] mcfuart.0: ttyS0 at MMIO 0xfc060000 (irq = 90, >>> base_baud = 5208333) is a ColdFire UART >>> [ 0.130000] printk: legacy console [ttyS0] enabled >>> [ 0.130000] brd: module loaded >>> ... >> >> OK, I see what you mean. Let me try to explain why I did it :-). >> >> The idea is to avoid probing a UART device which may exist as such on >> the core, but not be used as UART at all (on my board, for instance, I >> have uart2 and uart6, I don't need any other UART to be probed). >> >> So, based on what I think is the dts philosophy, you declare the >> devices you really need to probe ? > > You can do this too, with the old style platform setups. > > What you want is to have a separate board file just for your board. > There is a few examples already in arch/m68k/coldfire/ like amcore.c, > firebee.c, nettel.c and stmark2.c. None currently specifically extract > out UARTS - no one really seemed to have a need for that in the past. > Most ColdFire parts have 2 or 3 UARTS, the 5441x family is an out-lier > here with 10. > > Anyway, the device.c entries are really just a catch-all for the most > common devices and their most commonly used configurations. Thanks for answering ! I know I can have a dedicated file for my board (which i have tbh) but device.c is always built when you select CONFIG_COLDFIRE so, I would end up with 10 UARTs probed anyways ? Is there no way for this patch to find a path ? I mean, I can keep the existing behavior, and have everything probed in device.c if the BASE address is declared. But I don't want my board to have all 10 UARTs and I don't want to locally patch the Makefile to remove the device.c from the built-in ? Thanks, JM > > Regards > Greg > > > >> I can add all the uarts as resources with the ifdefs like before, but >> on the M54418 it will always probe 10 devices, which sounds like a bit >> overkill ? >> >> Thanks ! >> JM >> >>> >>> Regards >>> Greg >>> >>> >>> >>>> static struct resource mcf_uart2_resource[] = { >>>> [0] = { >>>> .start = MCFUART_BASE2, >>>> .end = MCFUART_BASE2 + 0x3fff, >>>> .flags = IORESOURCE_MEM, >>>> }, >>>> [1] = { >>>> .start = 6, >>>> .end = 7, >>>> .flags = IORESOURCE_DMA, >>>> }, >>>> [2] = { >>>> .start = MCF_IRQ_UART2, >>>> .end = MCF_IRQ_UART2, >>>> .flags = IORESOURCE_IRQ, >>>> }, >>>> }; >>>> >>>> static struct platform_device mcf_uart2 = { >>>> .name = "mcfuart", >>>> .id = 2, >>>> .num_resources = ARRAY_SIZE(mcf_uart2_resource), >>>> .resource = mcf_uart2_resource, >>>> .dev = { >>>> .dma_mask = &mcf_uart_mask, >>>> .coherent_dma_mask = DMA_BIT_MASK(32), >>>> }, >>>> }; >>>> >>>> static struct resource mcf_uart6_resource[] = { >>>> [0] = { >>>> .start = MCFUART_BASE6, >>>> .end = MCFUART_BASE6 + 0x3fff, >>>> .flags = IORESOURCE_MEM, >>>> }, >>>> [1] = { >>>> .start = 22, >>>> .end = 23, >>>> .flags = IORESOURCE_DMA, >>>> }, >>>> [2] = { >>>> .start = MCF_IRQ_UART6, >>>> .end = MCF_IRQ_UART6, >>>> .flags = IORESOURCE_IRQ, >>>> }, >>>> }; >>>> >>>> static struct platform_device mcf_uart6 = { >>>> .name = "mcfuart", >>>> .id = 6, >>>> .num_resources = ARRAY_SIZE(mcf_uart6_resource), >>>> .resource = mcf_uart6_resource, >>>> .dev = { >>>> .dma_mask = &mcf_uart_mask, >>>> .coherent_dma_mask = DMA_BIT_MASK(32), >>>> }, >>>> }; >>>> >>>> JM >>>> >>>>> >>>>> Regards >>>>> Greg >>>>> >>>>> >>>>> >>>>>> return 0; >>>>>> } >>>>>> @@ -603,13 +618,11 @@ static int mcf_probe(struct platform_device >>>>>> *pdev) >>>>>> static void mcf_remove(struct platform_device *pdev) >>>>>> { >>>>>> struct uart_port *port; >>>>>> - int i; >>>>>> + int id = pdev->id; >>>>>> - for (i = 0; (i < MCF_MAXPORTS); i++) { >>>>>> - port = &mcf_ports[i].port; >>>>>> - if (port) >>>>>> - uart_remove_one_port(&mcf_driver, port); >>>>>> - } >>>>>> + port = &mcf_ports[id].port; >>>>>> + if (port) >>>>>> + uart_remove_one_port(&mcf_driver, port); >>>>>> } >>>>>> / >>>>>> ****************************************************************************/ >>>>>> >>>>>> --- >>>>>> base-commit: e457f18d7f25288d143c1fe024a620d0b15caec1 >>>>>> change-id: 20241202-m5441x_uart_resource-729b30c15363 >>>>>> >>>>>> Best regards, >>>> >>
Hi JM, On 5/12/24 23:06, Jean-Michel Hautbois wrote: > On 05/12/2024 14:01, Greg Ungerer wrote: >> On 4/12/24 21:32, Jean-Michel Hautbois wrote: >>> On 04/12/2024 12:15, Greg Ungerer wrote: >>>> On 4/12/24 20:58, Jean-Michel Hautbois wrote: >>>>> On 04/12/2024 11:54, Greg Ungerer wrote: >>>>>> On 2/12/24 20:34, Jean-Michel Hautbois wrote: >>>>>>> In order to use the eDMA channels for UART, the mcf_platform_uart needs >>>>>>> to be changed. Instead of adding another custom member for the >>>>>>> structure, use a resource tree in a platform_device per UART. It then >>>>>>> makes it possible to have a device named like "mcfuart.N" with N the >>>>>>> UART number. >>>>>>> >>>>>>> Later, adding the dma channel in the mcf tty driver will also be more >>>>>>> straightfoward. >>>>>>> >>>>>>> Signed-off-by: Jean-Michel Hautbois <jeanmichel.hautbois@yoseli.org> >>>>>>> --- >>>>>>> arch/m68k/coldfire/device.c | 96 +++++++++++++ +------------------------------- >>>>>>> drivers/tty/serial/mcf.c | 69 +++++++++++++++++++------------- >>>>>>> 2 files changed, 70 insertions(+), 95 deletions(-) >>>>>>> >>>>>>> diff --git a/arch/m68k/coldfire/device.c b/arch/m68k/coldfire/ device.c >>>>>>> index b6958ec2a220cf91a78a14fc7fa18749451412f7..fd7d0b0ce7eb2970cb8ffe33589fe8d7e88c268d 100644 >>>>>>> --- a/arch/m68k/coldfire/device.c >>>>>>> +++ b/arch/m68k/coldfire/device.c >>>>>>> @@ -24,73 +24,35 @@ >>>>>>> #include <linux/platform_data/dma-mcf-edma.h> >>>>>>> #include <linux/platform_data/mmc-esdhc-mcf.h> >>>>>>> -/* >>>>>>> - * All current ColdFire parts contain from 2, 3, 4 or 10 UARTS. >>>>>>> - */ >>>>>>> -static struct mcf_platform_uart mcf_uart_platform_data[] = { >>>>>>> - { >>>>>>> - .mapbase = MCFUART_BASE0, >>>>>>> - .irq = MCF_IRQ_UART0, >>>>>>> - }, >>>>>>> - { >>>>>>> - .mapbase = MCFUART_BASE1, >>>>>>> - .irq = MCF_IRQ_UART1, >>>>>>> - }, >>>>>>> -#ifdef MCFUART_BASE2 >>>>>>> - { >>>>>>> - .mapbase = MCFUART_BASE2, >>>>>>> - .irq = MCF_IRQ_UART2, >>>>>>> - }, >>>>>>> -#endif >>>>>>> -#ifdef MCFUART_BASE3 >>>>>>> - { >>>>>>> - .mapbase = MCFUART_BASE3, >>>>>>> - .irq = MCF_IRQ_UART3, >>>>>>> - }, >>>>>>> -#endif >>>>>>> -#ifdef MCFUART_BASE4 >>>>>>> - { >>>>>>> - .mapbase = MCFUART_BASE4, >>>>>>> - .irq = MCF_IRQ_UART4, >>>>>>> - }, >>>>>>> -#endif >>>>>>> -#ifdef MCFUART_BASE5 >>>>>>> - { >>>>>>> - .mapbase = MCFUART_BASE5, >>>>>>> - .irq = MCF_IRQ_UART5, >>>>>>> - }, >>>>>>> -#endif >>>>>>> -#ifdef MCFUART_BASE6 >>>>>>> - { >>>>>>> - .mapbase = MCFUART_BASE6, >>>>>>> - .irq = MCF_IRQ_UART6, >>>>>>> - }, >>>>>>> -#endif >>>>>>> -#ifdef MCFUART_BASE7 >>>>>>> - { >>>>>>> - .mapbase = MCFUART_BASE7, >>>>>>> - .irq = MCF_IRQ_UART7, >>>>>>> +static u64 mcf_uart_mask = DMA_BIT_MASK(32); >>>>>>> + >>>>>>> +static struct resource mcf_uart0_resource[] = { >>>>>>> + [0] = { >>>>>>> + .start = MCFUART_BASE0, >>>>>>> + .end = MCFUART_BASE0 + 0x3fff, >>>>>>> + .flags = IORESOURCE_MEM, >>>>>>> }, >>>>>>> -#endif >>>>>>> -#ifdef MCFUART_BASE8 >>>>>>> - { >>>>>>> - .mapbase = MCFUART_BASE8, >>>>>>> - .irq = MCF_IRQ_UART8, >>>>>>> + [1] = { >>>>>>> + .start = 2, >>>>>>> + .end = 3, >>>>>>> + .flags = IORESOURCE_DMA, >>>>>>> }, >>>>>>> -#endif >>>>>>> -#ifdef MCFUART_BASE9 >>>>>>> - { >>>>>>> - .mapbase = MCFUART_BASE9, >>>>>>> - .irq = MCF_IRQ_UART9, >>>>>>> + [2] = { >>>>>>> + .start = MCF_IRQ_UART0, >>>>>>> + .end = MCF_IRQ_UART0, >>>>>>> + .flags = IORESOURCE_IRQ, >>>>>>> }, >>>>>>> -#endif >>>>>>> - { }, >>>>>>> }; >>>>>>> -static struct platform_device mcf_uart = { >>>>>>> +static struct platform_device mcf_uart0 = { >>>>>>> .name = "mcfuart", >>>>>>> .id = 0, >>>>>>> - .dev.platform_data = mcf_uart_platform_data, >>>>>>> + .num_resources = ARRAY_SIZE(mcf_uart0_resource), >>>>>>> + .resource = mcf_uart0_resource, >>>>>>> + .dev = { >>>>>>> + .dma_mask = &mcf_uart_mask, >>>>>>> + .coherent_dma_mask = DMA_BIT_MASK(32), >>>>>>> + }, >>>>>>> }; >>>>>>> #ifdef MCFFEC_BASE0 >>>>>>> @@ -485,12 +447,12 @@ static struct platform_device mcf_i2c5 = { >>>>>>> static const struct dma_slave_map mcf_edma_map[] = { >>>>>>> { "dreq0", "rx-tx", MCF_EDMA_FILTER_PARAM(0) }, >>>>>>> { "dreq1", "rx-tx", MCF_EDMA_FILTER_PARAM(1) }, >>>>>>> - { "uart.0", "rx", MCF_EDMA_FILTER_PARAM(2) }, >>>>>>> - { "uart.0", "tx", MCF_EDMA_FILTER_PARAM(3) }, >>>>>>> - { "uart.1", "rx", MCF_EDMA_FILTER_PARAM(4) }, >>>>>>> - { "uart.1", "tx", MCF_EDMA_FILTER_PARAM(5) }, >>>>>>> - { "uart.2", "rx", MCF_EDMA_FILTER_PARAM(6) }, >>>>>>> - { "uart.2", "tx", MCF_EDMA_FILTER_PARAM(7) }, >>>>>>> + { "mcfuart.0", "rx", MCF_EDMA_FILTER_PARAM(2) }, >>>>>>> + { "mcfuart.0", "tx", MCF_EDMA_FILTER_PARAM(3) }, >>>>>>> + { "mcfuart.1", "rx", MCF_EDMA_FILTER_PARAM(4) }, >>>>>>> + { "mcfuart.1", "tx", MCF_EDMA_FILTER_PARAM(5) }, >>>>>>> + { "mcfuart.2", "rx", MCF_EDMA_FILTER_PARAM(6) }, >>>>>>> + { "mcfuart.2", "tx", MCF_EDMA_FILTER_PARAM(7) }, >>>>>>> { "timer0", "rx-tx", MCF_EDMA_FILTER_PARAM(8) }, >>>>>>> { "timer1", "rx-tx", MCF_EDMA_FILTER_PARAM(9) }, >>>>>>> { "timer2", "rx-tx", MCF_EDMA_FILTER_PARAM(10) }, >>>>>>> @@ -623,7 +585,7 @@ static struct platform_device mcf_flexcan0 = { >>>>>>> #endif /* MCFFLEXCAN_SIZE */ >>>>>>> static struct platform_device *mcf_devices[] __initdata = { >>>>>>> - &mcf_uart, >>>>>>> + &mcf_uart0, >>>>>>> #ifdef MCFFEC_BASE0 >>>>>>> &mcf_fec0, >>>>>>> #endif >>>>>>> diff --git a/drivers/tty/serial/mcf.c b/drivers/tty/serial/mcf.c >>>>>>> index 93e7dda4d39acd23daf8c0d4c29ac8d666f263c5..07b8decfdb6005f0265dd130765e45c3fd1715eb 100644 >>>>>>> --- a/drivers/tty/serial/mcf.c >>>>>>> +++ b/drivers/tty/serial/mcf.c >>>>>>> @@ -570,31 +570,46 @@ static struct uart_driver mcf_driver = { >>>>>>> static int mcf_probe(struct platform_device *pdev) >>>>>>> { >>>>>>> - struct mcf_platform_uart *platp = dev_get_platdata(&pdev->dev); >>>>>>> struct uart_port *port; >>>>>>> - int i; >>>>>>> - >>>>>>> - for (i = 0; ((i < MCF_MAXPORTS) && (platp[i].mapbase)); i++) { >>>>>>> - port = &mcf_ports[i].port; >>>>>>> - >>>>>>> - port->line = i; >>>>>>> - port->type = PORT_MCF; >>>>>>> - port->mapbase = platp[i].mapbase; >>>>>>> - port->membase = (platp[i].membase) ? platp[i].membase : >>>>>>> - (unsigned char __iomem *) platp[i].mapbase; >>>>>>> - port->dev = &pdev->dev; >>>>>>> - port->iotype = SERIAL_IO_MEM; >>>>>>> - port->irq = platp[i].irq; >>>>>>> - port->uartclk = MCF_BUSCLK; >>>>>>> - port->ops = &mcf_uart_ops; >>>>>>> - port->flags = UPF_BOOT_AUTOCONF; >>>>>>> - port->rs485_config = mcf_config_rs485; >>>>>>> - port->rs485_supported = mcf_rs485_supported; >>>>>>> - port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_MCF_CONSOLE); >>>>>>> - >>>>>>> - uart_add_one_port(&mcf_driver, port); >>>>>>> + struct mcf_uart *pp; >>>>>>> + struct resource *res; >>>>>>> + void __iomem *base; >>>>>>> + int id = pdev->id; >>>>>>> + >>>>>>> + if (id == -1 || id >= MCF_MAXPORTS) { >>>>>>> + dev_err(&pdev->dev, "uart%d out of range\n", >>>>>>> + id); >>>>>>> + return -EINVAL; >>>>>>> } >>>>>>> + port = &mcf_ports[id].port; >>>>>>> + port->line = id; >>>>>>> + >>>>>>> + base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); >>>>>>> + if (IS_ERR(base)) >>>>>>> + return PTR_ERR(base); >>>>>>> + >>>>>>> + port->mapbase = res->start; >>>>>>> + port->membase = base; >>>>>>> + >>>>>>> + port->irq = platform_get_irq(pdev, 0); >>>>>>> + if (port->irq < 0) >>>>>>> + return port->irq; >>>>>>> + >>>>>>> + port->type = PORT_MCF; >>>>>>> + port->dev = &pdev->dev; >>>>>>> + port->iotype = SERIAL_IO_MEM; >>>>>>> + port->uartclk = MCF_BUSCLK; >>>>>>> + port->ops = &mcf_uart_ops; >>>>>>> + port->flags = UPF_BOOT_AUTOCONF; >>>>>>> + port->rs485_config = mcf_config_rs485; >>>>>>> + port->rs485_supported = mcf_rs485_supported; >>>>>>> + port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_MCF_CONSOLE); >>>>>>> + >>>>>>> + pp = container_of(port, struct mcf_uart, port); >>>>>>> + >>>>>>> + uart_add_one_port(&mcf_driver, port); >>>>>>> + >>>>>> >>>>>> This breaks platforms with more than one UART - which is quite a few of >>>>>> the ColdFire platforms. Numerous boards bring and use more than one UART. >>>>> >>>>> I don't get why, as I have two uarts here, and each is detected properly when declaring those in my platform ? I get that it breaks existing detection (we are parsing all uarts even when only one or two is used) but it does not prevent it to work ? >>>> >>>> Building and testing on an M5208EVB platform. >>>> With original un-modified code boot console shows: >>>> >>>> ... >>>> [ 0.110000] romfs: ROMFS MTD (C) 2007 Red Hat, Inc. >>>> [ 0.110000] ColdFire internal UART serial driver >>>> [ 0.110000] mcfuart.0: ttyS0 at MMIO 0xfc060000 (irq = 90, base_baud = 5208333) is a ColdFire UART >>>> [ 0.120000] printk: legacy console [ttyS0] enabled >>>> [ 0.120000] mcfuart.0: ttyS1 at MMIO 0xfc064000 (irq = 91, base_baud = 5208333) is a ColdFire UART >>>> [ 0.120000] mcfuart.0: ttyS2 at MMIO 0xfc068000 (irq = 92, base_baud = 5208333) is a ColdFire UART >>>> [ 0.130000] brd: module loaded >>>> ... >>>> >>>> >>>> But with this change applied only the first port is probed: >>>> >>>> ... >>>> [ 0.120000] romfs: ROMFS MTD (C) 2007 Red Hat, Inc. >>>> [ 0.120000] ColdFire internal UART serial driver >>>> [ 0.130000] mcfuart.0: ttyS0 at MMIO 0xfc060000 (irq = 90, base_baud = 5208333) is a ColdFire UART >>>> [ 0.130000] printk: legacy console [ttyS0] enabled >>>> [ 0.130000] brd: module loaded >>>> ... >>> >>> OK, I see what you mean. Let me try to explain why I did it :-). >>> >>> The idea is to avoid probing a UART device which may exist as such on the core, but not be used as UART at all (on my board, for instance, I have uart2 and uart6, I don't need any other UART to be probed). >>> >>> So, based on what I think is the dts philosophy, you declare the devices you really need to probe ? >> >> You can do this too, with the old style platform setups. >> >> What you want is to have a separate board file just for your board. >> There is a few examples already in arch/m68k/coldfire/ like amcore.c, >> firebee.c, nettel.c and stmark2.c. None currently specifically extract >> out UARTS - no one really seemed to have a need for that in the past. >> Most ColdFire parts have 2 or 3 UARTS, the 5441x family is an out-lier >> here with 10. >> >> Anyway, the device.c entries are really just a catch-all for the most >> common devices and their most commonly used configurations. > > Thanks for answering ! > > I know I can have a dedicated file for my board (which i have tbh) but device.c is always built when you select CONFIG_COLDFIRE so, I would end up with 10 UARTs probed anyways ? > > Is there no way for this patch to find a path ? I mean, I can keep the existing behavior, and have everything probed in device.c if the BASE address is declared. But I don't want my board to have all 10 UARTs and I don't want to locally patch the Makefile to remove the device.c from the built-in ? Here is one example way to do it. Compile tested only - but I am sure you get the idea. Regards Greg
Hi Greg, On 12/9/24 13:30, Greg Ungerer wrote: > Hi JM, > > On 5/12/24 23:06, Jean-Michel Hautbois wrote: >> On 05/12/2024 14:01, Greg Ungerer wrote: >>> On 4/12/24 21:32, Jean-Michel Hautbois wrote: >>>> On 04/12/2024 12:15, Greg Ungerer wrote: >>>>> On 4/12/24 20:58, Jean-Michel Hautbois wrote: >>>>>> On 04/12/2024 11:54, Greg Ungerer wrote: >>>>>>> On 2/12/24 20:34, Jean-Michel Hautbois wrote: >>>>>>>> In order to use the eDMA channels for UART, the >>>>>>>> mcf_platform_uart needs >>>>>>>> to be changed. Instead of adding another custom member for the >>>>>>>> structure, use a resource tree in a platform_device per UART. It >>>>>>>> then >>>>>>>> makes it possible to have a device named like "mcfuart.N" with N >>>>>>>> the >>>>>>>> UART number. >>>>>>>> >>>>>>>> Later, adding the dma channel in the mcf tty driver will also be >>>>>>>> more >>>>>>>> straightfoward. >>>>>>>> >>>>>>>> Signed-off-by: Jean-Michel Hautbois >>>>>>>> <jeanmichel.hautbois@yoseli.org> >>>>>>>> --- >>>>>>>> arch/m68k/coldfire/device.c | 96 +++++++++++++ >>>>>>>> +------------------------------- >>>>>>>> drivers/tty/serial/mcf.c | 69 +++++++++++++++++++------------- >>>>>>>> 2 files changed, 70 insertions(+), 95 deletions(-) >>>>>>>> >>>>>>>> diff --git a/arch/m68k/coldfire/device.c b/arch/m68k/coldfire/ >>>>>>>> device.c >>>>>>>> index >>>>>>>> b6958ec2a220cf91a78a14fc7fa18749451412f7..fd7d0b0ce7eb2970cb8ffe33589fe8d7e88c268d 100644 >>>>>>>> --- a/arch/m68k/coldfire/device.c >>>>>>>> +++ b/arch/m68k/coldfire/device.c >>>>>>>> @@ -24,73 +24,35 @@ >>>>>>>> #include <linux/platform_data/dma-mcf-edma.h> >>>>>>>> #include <linux/platform_data/mmc-esdhc-mcf.h> >>>>>>>> -/* >>>>>>>> - * All current ColdFire parts contain from 2, 3, 4 or 10 UARTS. >>>>>>>> - */ >>>>>>>> -static struct mcf_platform_uart mcf_uart_platform_data[] = { >>>>>>>> - { >>>>>>>> - .mapbase = MCFUART_BASE0, >>>>>>>> - .irq = MCF_IRQ_UART0, >>>>>>>> - }, >>>>>>>> - { >>>>>>>> - .mapbase = MCFUART_BASE1, >>>>>>>> - .irq = MCF_IRQ_UART1, >>>>>>>> - }, >>>>>>>> -#ifdef MCFUART_BASE2 >>>>>>>> - { >>>>>>>> - .mapbase = MCFUART_BASE2, >>>>>>>> - .irq = MCF_IRQ_UART2, >>>>>>>> - }, >>>>>>>> -#endif >>>>>>>> -#ifdef MCFUART_BASE3 >>>>>>>> - { >>>>>>>> - .mapbase = MCFUART_BASE3, >>>>>>>> - .irq = MCF_IRQ_UART3, >>>>>>>> - }, >>>>>>>> -#endif >>>>>>>> -#ifdef MCFUART_BASE4 >>>>>>>> - { >>>>>>>> - .mapbase = MCFUART_BASE4, >>>>>>>> - .irq = MCF_IRQ_UART4, >>>>>>>> - }, >>>>>>>> -#endif >>>>>>>> -#ifdef MCFUART_BASE5 >>>>>>>> - { >>>>>>>> - .mapbase = MCFUART_BASE5, >>>>>>>> - .irq = MCF_IRQ_UART5, >>>>>>>> - }, >>>>>>>> -#endif >>>>>>>> -#ifdef MCFUART_BASE6 >>>>>>>> - { >>>>>>>> - .mapbase = MCFUART_BASE6, >>>>>>>> - .irq = MCF_IRQ_UART6, >>>>>>>> - }, >>>>>>>> -#endif >>>>>>>> -#ifdef MCFUART_BASE7 >>>>>>>> - { >>>>>>>> - .mapbase = MCFUART_BASE7, >>>>>>>> - .irq = MCF_IRQ_UART7, >>>>>>>> +static u64 mcf_uart_mask = DMA_BIT_MASK(32); >>>>>>>> + >>>>>>>> +static struct resource mcf_uart0_resource[] = { >>>>>>>> + [0] = { >>>>>>>> + .start = MCFUART_BASE0, >>>>>>>> + .end = MCFUART_BASE0 + 0x3fff, >>>>>>>> + .flags = IORESOURCE_MEM, >>>>>>>> }, >>>>>>>> -#endif >>>>>>>> -#ifdef MCFUART_BASE8 >>>>>>>> - { >>>>>>>> - .mapbase = MCFUART_BASE8, >>>>>>>> - .irq = MCF_IRQ_UART8, >>>>>>>> + [1] = { >>>>>>>> + .start = 2, >>>>>>>> + .end = 3, >>>>>>>> + .flags = IORESOURCE_DMA, >>>>>>>> }, >>>>>>>> -#endif >>>>>>>> -#ifdef MCFUART_BASE9 >>>>>>>> - { >>>>>>>> - .mapbase = MCFUART_BASE9, >>>>>>>> - .irq = MCF_IRQ_UART9, >>>>>>>> + [2] = { >>>>>>>> + .start = MCF_IRQ_UART0, >>>>>>>> + .end = MCF_IRQ_UART0, >>>>>>>> + .flags = IORESOURCE_IRQ, >>>>>>>> }, >>>>>>>> -#endif >>>>>>>> - { }, >>>>>>>> }; >>>>>>>> -static struct platform_device mcf_uart = { >>>>>>>> +static struct platform_device mcf_uart0 = { >>>>>>>> .name = "mcfuart", >>>>>>>> .id = 0, >>>>>>>> - .dev.platform_data = mcf_uart_platform_data, >>>>>>>> + .num_resources = ARRAY_SIZE(mcf_uart0_resource), >>>>>>>> + .resource = mcf_uart0_resource, >>>>>>>> + .dev = { >>>>>>>> + .dma_mask = &mcf_uart_mask, >>>>>>>> + .coherent_dma_mask = DMA_BIT_MASK(32), >>>>>>>> + }, >>>>>>>> }; >>>>>>>> #ifdef MCFFEC_BASE0 >>>>>>>> @@ -485,12 +447,12 @@ static struct platform_device mcf_i2c5 = { >>>>>>>> static const struct dma_slave_map mcf_edma_map[] = { >>>>>>>> { "dreq0", "rx-tx", MCF_EDMA_FILTER_PARAM(0) }, >>>>>>>> { "dreq1", "rx-tx", MCF_EDMA_FILTER_PARAM(1) }, >>>>>>>> - { "uart.0", "rx", MCF_EDMA_FILTER_PARAM(2) }, >>>>>>>> - { "uart.0", "tx", MCF_EDMA_FILTER_PARAM(3) }, >>>>>>>> - { "uart.1", "rx", MCF_EDMA_FILTER_PARAM(4) }, >>>>>>>> - { "uart.1", "tx", MCF_EDMA_FILTER_PARAM(5) }, >>>>>>>> - { "uart.2", "rx", MCF_EDMA_FILTER_PARAM(6) }, >>>>>>>> - { "uart.2", "tx", MCF_EDMA_FILTER_PARAM(7) }, >>>>>>>> + { "mcfuart.0", "rx", MCF_EDMA_FILTER_PARAM(2) }, >>>>>>>> + { "mcfuart.0", "tx", MCF_EDMA_FILTER_PARAM(3) }, >>>>>>>> + { "mcfuart.1", "rx", MCF_EDMA_FILTER_PARAM(4) }, >>>>>>>> + { "mcfuart.1", "tx", MCF_EDMA_FILTER_PARAM(5) }, >>>>>>>> + { "mcfuart.2", "rx", MCF_EDMA_FILTER_PARAM(6) }, >>>>>>>> + { "mcfuart.2", "tx", MCF_EDMA_FILTER_PARAM(7) }, >>>>>>>> { "timer0", "rx-tx", MCF_EDMA_FILTER_PARAM(8) }, >>>>>>>> { "timer1", "rx-tx", MCF_EDMA_FILTER_PARAM(9) }, >>>>>>>> { "timer2", "rx-tx", MCF_EDMA_FILTER_PARAM(10) }, >>>>>>>> @@ -623,7 +585,7 @@ static struct platform_device mcf_flexcan0 = { >>>>>>>> #endif /* MCFFLEXCAN_SIZE */ >>>>>>>> static struct platform_device *mcf_devices[] __initdata = { >>>>>>>> - &mcf_uart, >>>>>>>> + &mcf_uart0, >>>>>>>> #ifdef MCFFEC_BASE0 >>>>>>>> &mcf_fec0, >>>>>>>> #endif >>>>>>>> diff --git a/drivers/tty/serial/mcf.c b/drivers/tty/serial/mcf.c >>>>>>>> index >>>>>>>> 93e7dda4d39acd23daf8c0d4c29ac8d666f263c5..07b8decfdb6005f0265dd130765e45c3fd1715eb 100644 >>>>>>>> --- a/drivers/tty/serial/mcf.c >>>>>>>> +++ b/drivers/tty/serial/mcf.c >>>>>>>> @@ -570,31 +570,46 @@ static struct uart_driver mcf_driver = { >>>>>>>> static int mcf_probe(struct platform_device *pdev) >>>>>>>> { >>>>>>>> - struct mcf_platform_uart *platp = dev_get_platdata(&pdev- >>>>>>>> >dev); >>>>>>>> struct uart_port *port; >>>>>>>> - int i; >>>>>>>> - >>>>>>>> - for (i = 0; ((i < MCF_MAXPORTS) && (platp[i].mapbase)); i++) { >>>>>>>> - port = &mcf_ports[i].port; >>>>>>>> - >>>>>>>> - port->line = i; >>>>>>>> - port->type = PORT_MCF; >>>>>>>> - port->mapbase = platp[i].mapbase; >>>>>>>> - port->membase = (platp[i].membase) ? platp[i].membase : >>>>>>>> - (unsigned char __iomem *) platp[i].mapbase; >>>>>>>> - port->dev = &pdev->dev; >>>>>>>> - port->iotype = SERIAL_IO_MEM; >>>>>>>> - port->irq = platp[i].irq; >>>>>>>> - port->uartclk = MCF_BUSCLK; >>>>>>>> - port->ops = &mcf_uart_ops; >>>>>>>> - port->flags = UPF_BOOT_AUTOCONF; >>>>>>>> - port->rs485_config = mcf_config_rs485; >>>>>>>> - port->rs485_supported = mcf_rs485_supported; >>>>>>>> - port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_MCF_CONSOLE); >>>>>>>> - >>>>>>>> - uart_add_one_port(&mcf_driver, port); >>>>>>>> + struct mcf_uart *pp; >>>>>>>> + struct resource *res; >>>>>>>> + void __iomem *base; >>>>>>>> + int id = pdev->id; >>>>>>>> + >>>>>>>> + if (id == -1 || id >= MCF_MAXPORTS) { >>>>>>>> + dev_err(&pdev->dev, "uart%d out of range\n", >>>>>>>> + id); >>>>>>>> + return -EINVAL; >>>>>>>> } >>>>>>>> + port = &mcf_ports[id].port; >>>>>>>> + port->line = id; >>>>>>>> + >>>>>>>> + base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); >>>>>>>> + if (IS_ERR(base)) >>>>>>>> + return PTR_ERR(base); >>>>>>>> + >>>>>>>> + port->mapbase = res->start; >>>>>>>> + port->membase = base; >>>>>>>> + >>>>>>>> + port->irq = platform_get_irq(pdev, 0); >>>>>>>> + if (port->irq < 0) >>>>>>>> + return port->irq; >>>>>>>> + >>>>>>>> + port->type = PORT_MCF; >>>>>>>> + port->dev = &pdev->dev; >>>>>>>> + port->iotype = SERIAL_IO_MEM; >>>>>>>> + port->uartclk = MCF_BUSCLK; >>>>>>>> + port->ops = &mcf_uart_ops; >>>>>>>> + port->flags = UPF_BOOT_AUTOCONF; >>>>>>>> + port->rs485_config = mcf_config_rs485; >>>>>>>> + port->rs485_supported = mcf_rs485_supported; >>>>>>>> + port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_MCF_CONSOLE); >>>>>>>> + >>>>>>>> + pp = container_of(port, struct mcf_uart, port); >>>>>>>> + >>>>>>>> + uart_add_one_port(&mcf_driver, port); >>>>>>>> + >>>>>>> >>>>>>> This breaks platforms with more than one UART - which is quite a >>>>>>> few of >>>>>>> the ColdFire platforms. Numerous boards bring and use more than >>>>>>> one UART. >>>>>> >>>>>> I don't get why, as I have two uarts here, and each is detected >>>>>> properly when declaring those in my platform ? I get that it >>>>>> breaks existing detection (we are parsing all uarts even when only >>>>>> one or two is used) but it does not prevent it to work ? >>>>> >>>>> Building and testing on an M5208EVB platform. >>>>> With original un-modified code boot console shows: >>>>> >>>>> ... >>>>> [ 0.110000] romfs: ROMFS MTD (C) 2007 Red Hat, Inc. >>>>> [ 0.110000] ColdFire internal UART serial driver >>>>> [ 0.110000] mcfuart.0: ttyS0 at MMIO 0xfc060000 (irq = 90, >>>>> base_baud = 5208333) is a ColdFire UART >>>>> [ 0.120000] printk: legacy console [ttyS0] enabled >>>>> [ 0.120000] mcfuart.0: ttyS1 at MMIO 0xfc064000 (irq = 91, >>>>> base_baud = 5208333) is a ColdFire UART >>>>> [ 0.120000] mcfuart.0: ttyS2 at MMIO 0xfc068000 (irq = 92, >>>>> base_baud = 5208333) is a ColdFire UART >>>>> [ 0.130000] brd: module loaded >>>>> ... >>>>> >>>>> >>>>> But with this change applied only the first port is probed: >>>>> >>>>> ... >>>>> [ 0.120000] romfs: ROMFS MTD (C) 2007 Red Hat, Inc. >>>>> [ 0.120000] ColdFire internal UART serial driver >>>>> [ 0.130000] mcfuart.0: ttyS0 at MMIO 0xfc060000 (irq = 90, >>>>> base_baud = 5208333) is a ColdFire UART >>>>> [ 0.130000] printk: legacy console [ttyS0] enabled >>>>> [ 0.130000] brd: module loaded >>>>> ... >>>> >>>> OK, I see what you mean. Let me try to explain why I did it :-). >>>> >>>> The idea is to avoid probing a UART device which may exist as such >>>> on the core, but not be used as UART at all (on my board, for >>>> instance, I have uart2 and uart6, I don't need any other UART to be >>>> probed). >>>> >>>> So, based on what I think is the dts philosophy, you declare the >>>> devices you really need to probe ? >>> >>> You can do this too, with the old style platform setups. >>> >>> What you want is to have a separate board file just for your board. >>> There is a few examples already in arch/m68k/coldfire/ like amcore.c, >>> firebee.c, nettel.c and stmark2.c. None currently specifically extract >>> out UARTS - no one really seemed to have a need for that in the past. >>> Most ColdFire parts have 2 or 3 UARTS, the 5441x family is an out-lier >>> here with 10. >>> >>> Anyway, the device.c entries are really just a catch-all for the most >>> common devices and their most commonly used configurations. >> >> Thanks for answering ! >> >> I know I can have a dedicated file for my board (which i have tbh) but >> device.c is always built when you select CONFIG_COLDFIRE so, I would >> end up with 10 UARTs probed anyways ? >> >> Is there no way for this patch to find a path ? I mean, I can keep the >> existing behavior, and have everything probed in device.c if the BASE >> address is declared. But I don't want my board to have all 10 UARTs >> and I don't want to locally patch the Makefile to remove the device.c >> from the built-in ? > > Here is one example way to do it. > Compile tested only - but I am sure you get the idea. Thank you, it is clear. Yes, I get the idea :-). I will submit a v2 once I have something (very) inspired ;-). I just have to find a name for this new configuration, and test it. JM
diff --git a/arch/m68k/coldfire/device.c b/arch/m68k/coldfire/device.c index b6958ec2a220cf91a78a14fc7fa18749451412f7..fd7d0b0ce7eb2970cb8ffe33589fe8d7e88c268d 100644 --- a/arch/m68k/coldfire/device.c +++ b/arch/m68k/coldfire/device.c @@ -24,73 +24,35 @@ #include <linux/platform_data/dma-mcf-edma.h> #include <linux/platform_data/mmc-esdhc-mcf.h> -/* - * All current ColdFire parts contain from 2, 3, 4 or 10 UARTS. - */ -static struct mcf_platform_uart mcf_uart_platform_data[] = { - { - .mapbase = MCFUART_BASE0, - .irq = MCF_IRQ_UART0, - }, - { - .mapbase = MCFUART_BASE1, - .irq = MCF_IRQ_UART1, - }, -#ifdef MCFUART_BASE2 - { - .mapbase = MCFUART_BASE2, - .irq = MCF_IRQ_UART2, - }, -#endif -#ifdef MCFUART_BASE3 - { - .mapbase = MCFUART_BASE3, - .irq = MCF_IRQ_UART3, - }, -#endif -#ifdef MCFUART_BASE4 - { - .mapbase = MCFUART_BASE4, - .irq = MCF_IRQ_UART4, - }, -#endif -#ifdef MCFUART_BASE5 - { - .mapbase = MCFUART_BASE5, - .irq = MCF_IRQ_UART5, - }, -#endif -#ifdef MCFUART_BASE6 - { - .mapbase = MCFUART_BASE6, - .irq = MCF_IRQ_UART6, - }, -#endif -#ifdef MCFUART_BASE7 - { - .mapbase = MCFUART_BASE7, - .irq = MCF_IRQ_UART7, +static u64 mcf_uart_mask = DMA_BIT_MASK(32); + +static struct resource mcf_uart0_resource[] = { + [0] = { + .start = MCFUART_BASE0, + .end = MCFUART_BASE0 + 0x3fff, + .flags = IORESOURCE_MEM, }, -#endif -#ifdef MCFUART_BASE8 - { - .mapbase = MCFUART_BASE8, - .irq = MCF_IRQ_UART8, + [1] = { + .start = 2, + .end = 3, + .flags = IORESOURCE_DMA, }, -#endif -#ifdef MCFUART_BASE9 - { - .mapbase = MCFUART_BASE9, - .irq = MCF_IRQ_UART9, + [2] = { + .start = MCF_IRQ_UART0, + .end = MCF_IRQ_UART0, + .flags = IORESOURCE_IRQ, }, -#endif - { }, }; -static struct platform_device mcf_uart = { +static struct platform_device mcf_uart0 = { .name = "mcfuart", .id = 0, - .dev.platform_data = mcf_uart_platform_data, + .num_resources = ARRAY_SIZE(mcf_uart0_resource), + .resource = mcf_uart0_resource, + .dev = { + .dma_mask = &mcf_uart_mask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, }; #ifdef MCFFEC_BASE0 @@ -485,12 +447,12 @@ static struct platform_device mcf_i2c5 = { static const struct dma_slave_map mcf_edma_map[] = { { "dreq0", "rx-tx", MCF_EDMA_FILTER_PARAM(0) }, { "dreq1", "rx-tx", MCF_EDMA_FILTER_PARAM(1) }, - { "uart.0", "rx", MCF_EDMA_FILTER_PARAM(2) }, - { "uart.0", "tx", MCF_EDMA_FILTER_PARAM(3) }, - { "uart.1", "rx", MCF_EDMA_FILTER_PARAM(4) }, - { "uart.1", "tx", MCF_EDMA_FILTER_PARAM(5) }, - { "uart.2", "rx", MCF_EDMA_FILTER_PARAM(6) }, - { "uart.2", "tx", MCF_EDMA_FILTER_PARAM(7) }, + { "mcfuart.0", "rx", MCF_EDMA_FILTER_PARAM(2) }, + { "mcfuart.0", "tx", MCF_EDMA_FILTER_PARAM(3) }, + { "mcfuart.1", "rx", MCF_EDMA_FILTER_PARAM(4) }, + { "mcfuart.1", "tx", MCF_EDMA_FILTER_PARAM(5) }, + { "mcfuart.2", "rx", MCF_EDMA_FILTER_PARAM(6) }, + { "mcfuart.2", "tx", MCF_EDMA_FILTER_PARAM(7) }, { "timer0", "rx-tx", MCF_EDMA_FILTER_PARAM(8) }, { "timer1", "rx-tx", MCF_EDMA_FILTER_PARAM(9) }, { "timer2", "rx-tx", MCF_EDMA_FILTER_PARAM(10) }, @@ -623,7 +585,7 @@ static struct platform_device mcf_flexcan0 = { #endif /* MCFFLEXCAN_SIZE */ static struct platform_device *mcf_devices[] __initdata = { - &mcf_uart, + &mcf_uart0, #ifdef MCFFEC_BASE0 &mcf_fec0, #endif diff --git a/drivers/tty/serial/mcf.c b/drivers/tty/serial/mcf.c index 93e7dda4d39acd23daf8c0d4c29ac8d666f263c5..07b8decfdb6005f0265dd130765e45c3fd1715eb 100644 --- a/drivers/tty/serial/mcf.c +++ b/drivers/tty/serial/mcf.c @@ -570,31 +570,46 @@ static struct uart_driver mcf_driver = { static int mcf_probe(struct platform_device *pdev) { - struct mcf_platform_uart *platp = dev_get_platdata(&pdev->dev); struct uart_port *port; - int i; - - for (i = 0; ((i < MCF_MAXPORTS) && (platp[i].mapbase)); i++) { - port = &mcf_ports[i].port; - - port->line = i; - port->type = PORT_MCF; - port->mapbase = platp[i].mapbase; - port->membase = (platp[i].membase) ? platp[i].membase : - (unsigned char __iomem *) platp[i].mapbase; - port->dev = &pdev->dev; - port->iotype = SERIAL_IO_MEM; - port->irq = platp[i].irq; - port->uartclk = MCF_BUSCLK; - port->ops = &mcf_uart_ops; - port->flags = UPF_BOOT_AUTOCONF; - port->rs485_config = mcf_config_rs485; - port->rs485_supported = mcf_rs485_supported; - port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_MCF_CONSOLE); - - uart_add_one_port(&mcf_driver, port); + struct mcf_uart *pp; + struct resource *res; + void __iomem *base; + int id = pdev->id; + + if (id == -1 || id >= MCF_MAXPORTS) { + dev_err(&pdev->dev, "uart%d out of range\n", + id); + return -EINVAL; } + port = &mcf_ports[id].port; + port->line = id; + + base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); + if (IS_ERR(base)) + return PTR_ERR(base); + + port->mapbase = res->start; + port->membase = base; + + port->irq = platform_get_irq(pdev, 0); + if (port->irq < 0) + return port->irq; + + port->type = PORT_MCF; + port->dev = &pdev->dev; + port->iotype = SERIAL_IO_MEM; + port->uartclk = MCF_BUSCLK; + port->ops = &mcf_uart_ops; + port->flags = UPF_BOOT_AUTOCONF; + port->rs485_config = mcf_config_rs485; + port->rs485_supported = mcf_rs485_supported; + port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_MCF_CONSOLE); + + pp = container_of(port, struct mcf_uart, port); + + uart_add_one_port(&mcf_driver, port); + return 0; } @@ -603,13 +618,11 @@ static int mcf_probe(struct platform_device *pdev) static void mcf_remove(struct platform_device *pdev) { struct uart_port *port; - int i; + int id = pdev->id; - for (i = 0; (i < MCF_MAXPORTS); i++) { - port = &mcf_ports[i].port; - if (port) - uart_remove_one_port(&mcf_driver, port); - } + port = &mcf_ports[id].port; + if (port) + uart_remove_one_port(&mcf_driver, port); } /****************************************************************************/
In order to use the eDMA channels for UART, the mcf_platform_uart needs to be changed. Instead of adding another custom member for the structure, use a resource tree in a platform_device per UART. It then makes it possible to have a device named like "mcfuart.N" with N the UART number. Later, adding the dma channel in the mcf tty driver will also be more straightfoward. Signed-off-by: Jean-Michel Hautbois <jeanmichel.hautbois@yoseli.org> --- arch/m68k/coldfire/device.c | 96 ++++++++++++++------------------------------- drivers/tty/serial/mcf.c | 69 +++++++++++++++++++------------- 2 files changed, 70 insertions(+), 95 deletions(-) --- base-commit: e457f18d7f25288d143c1fe024a620d0b15caec1 change-id: 20241202-m5441x_uart_resource-729b30c15363 Best regards,