On Mon, Nov 30, 2009 at 10:09:58PM +0100, ext Tony Lindgren wrote:
> * Peter Barada <[email protected]> [091130 12:30]:
> > On Mon, 2009-11-30 at 11:40 -0800, Tony Lindgren wrote:
> > > * Grant Likely <[email protected]> [091130 09:01]:
> > > > On Mon, Nov 30, 2009 at 9:36 AM, Peter Barada <[email protected]> 
> > > > wrote:
> > > > > On Mon, 2009-11-30 at 10:46 +0200, Mika Westerberg wrote:
> > > > >> Hi Tony,
> > > > >>
> > > > >> Current omap serial driver takes control of all 3 (4 on OMAP3640)
> > > > >> UARTS. However, we have such a setup where UART2 for example is used
> > > > >> by bluetooth driver. It uses the UART as non-standard way (there are
> > > > >> some Nokia extensions to H4 protocol) so we cannot use the standard
> > > > >> driver for driving the UART but have written special one for that
> > > > >> purpose.
> > > > >>
> > > > >> Question is: Is there any, upstreamable, way of preventing omap 
> > > > >> serial
> > > > >> driver to do this? Currently this is done with custom #ifdef hackery 
> > > > >> to
> > > > >> mach-omap2/serial.c. Alternative solution that comes into mind is to
> > > > >> specify UART configuration in board files and let serial driver to 
> > > > >> use
> > > > >> that instead of hard-coded one. Or do you have some nice 
> > > > >> alternatives?
> > > > >
> > > > > Previously (back around 2.6.28-rc8) in the board file, the
> > > > > omap_uart_config struct controlled which serial ports were enabled on
> > > > > startup.  It was used in omap_serial_init, and it looks like that code
> > > > > went away with the following commit:
> > > > > http://git.kernel.org/?p=linux/kernel/git/tmlind/linux-omap-2.6.git;a=blobdiff;f=arch/arm/mach-omap2/serial.c;h=2e17b57f5b23bb6703a2d621103585af1d8d729b;hp=555e735524381cbf8ef9f20d778ad81f9438e24e;hb=4355c41a635943d30e9396b95185314343dcb551;hpb=7e9ccf7776bb68b5367eb0bb35e519df62bea35c
> > > > >
> > > > > I'm kinda in the same boat as I want to use some of the unused serial
> > > > > port pins for GPIO, but they are setup as serial ports....
> > > 
> > > Sounds like we need something back to specify the ports to use
> > > from board-*.c files. Kevin, got any comments? 
> > >  
> > > > Not in mainlined yet, but I'm working on porting flattened device tree
> > > > support to OMAP to solve exactly this sort of problem.  Basically,
> > > > instead of hard coding or #ifdeffing things, a data blob gets handed
> > > > to the kernel at boot time telling it exactly what hardware is present
> > > > in a consistent, parsable format.  Device drivers then get probed
> > > > based on data in the device tree.  Here's some info on the approach:
> > > > 
> > > > http://www.elinux.org/Device_Trees
> > > > 
> > > > I expect to have my prototype ready for review mid-January, and most
> > > > of the common code should be either merged or queued up in linux-next
> > > > by that time.
> > > 
> > > While device tree is a nice solution to some of the problems, it still
> > > leaves all the issues we already have with buggy and and outdated
> > > bootloaders. So we still need to properly initialize the devices in
> > > the kernel.
> > > 
> > > Just for reference, most of the omap bootloader bugs seem to be
> > > related to not muxing the pins right or using wrong timings for GPMC.
> > > 
> > > And then things that mostly change during the board development are
> > > the GPIO pins, but those can be easily rewritten in the board-*.c
> > > files based on the omap_rev.
> > > 
> > > But at least the device tree is a standard model, while the earlier
> > > omap tag approach was non-standard.
> > > 
> > > Peter, maybe you've already thought through all this.. But would it be
> > > possible to do lightweight device tree that we just use to populate
> > > the platform data?
> > 
> > One possibility is to pass to omap_serial_init() the omap_uart_config
> > struct pointer to specify which parts are enabled.  If a NULL is passed
> > in, then enable all the ports available.  Since omap_serial_early_init()
> > was already called, the muxing would have to be cleaned up, but since
> > the kernel should mux all the pins it uses, that shouldn't be a problem.
> > omap_serial_init would now look something like(warning, coding on the
> > fly - don't know if it will work as is):
> > 
> > void __init omap_serial_init(struct omap_uart_config *confptr)
> > {
> >     int i;
> > 
> >     for (i = 0; i < ARRAY_SIZE(omap_uart); i++) {
> >             struct omap_uart_state *uart = &omap_uart[i];
> >             struct platform_device *pdev = &uart->pdev;
> >             struct device *dev = &pdev->dev;
> > 
> >             /* Only enable
> >             if (!confptr || confptr->port_enabled & (1<<i)) {
> >                     omap_uart_reset(uart);
> >                     omap_uart_idle_init(uart);
> > 
> >                     if (WARN_ON(platform_device_register(pdev)))
> >                             continue;
> >                     if ((cpu_is_omap34xx() && uart->padconf) ||
> >                         (uart->wk_en && uart->wk_mask)) {
> >                             device_init_wakeup(dev, true);
> >                             DEV_CREATE_FILE(dev, &dev_attr_sleep_timeout);
> >                     }
> >             }
> >     }
> > }
> 
> Yeah, I guess something like that would be good. We may want to
> specify the optional other pins there too, typically it's just
> RX and TX pins.
> 
> It could also be directly struct plat_serial8250_port array we
> pass? Or does that make things more complicated to use the upcoming
> omap serial driver?

How about something like in the patch attached?

Then for example we would do in board-rx51.c:
        ...
        omap_serial_init_port(2);

(we only use UART3 as serial port).

I quickly tested this with RX-51 and seems to work.

Thanks,
MW

---

From: Mika Westerberg <[email protected]>
Date: Tue, 1 Dec 2009 12:54:21 +0200
Subject: [PATCH] OMAP3: serial - allow platforms specify which UARTs to 
initialize

This patch adds new function: omap_serial_init_port(port) that can be
used to initialize only selected UARTs as serial ports. Platforms can
then in their board files call this function instead of omap_serial_init()
if they don't want to use all UARTs as serial ports.

Signed-off-by: Mika Westerberg <[email protected]>
---
 arch/arm/mach-omap2/serial.c             |   59 +++++++++++++++++++++++-------
 arch/arm/plat-omap/include/plat/serial.h |    1 +
 2 files changed, 46 insertions(+), 14 deletions(-)

diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 2e17b57..fe46560 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -631,24 +631,55 @@ void __init omap_serial_early_init(void)
        }
 }
 
+/**
+ * omap_serial_init_port() - initialize single serial port
+ * @port: serial port number (0-3)
+ *
+ * This function initialies serial driver for given @port only.
+ * Platforms can call this function instead of omap_serial_init()
+ * if they don't plan to use all available UARTs as serial ports.
+ *
+ * Don't mix calls to omap_serial_init_port() and omap_serial_init(),
+ * use only one of the two.
+ */
+void __init omap_serial_init_port(int port)
+{
+       struct omap_uart_state *uart;
+       struct platform_device *pdev;
+       struct device *dev;
+
+       BUG_ON(port < 0);
+       BUG_ON(port >= ARRAY_SIZE(omap_uart));
+
+       uart = &omap_uart[port];
+       pdev = &uart->pdev;
+       dev = &pdev->dev;
+
+       omap_uart_reset(uart);
+       omap_uart_idle_init(uart);
+
+       if (WARN_ON(platform_device_register(pdev)))
+               return;
+
+       if ((cpu_is_omap34xx() && uart->padconf) ||
+           (uart->wk_en && uart->wk_mask)) {
+               device_init_wakeup(dev, true);
+               DEV_CREATE_FILE(dev, &dev_attr_sleep_timeout);
+       }
+}
+
+/**
+ * omap_serial_init() - intialize all supported serial ports
+ *
+ * Initializes all available UARTs as serial ports. Platforms
+ * can call this function when they want to have default behaviour
+ * for serial ports (e.g initialize them all as serial ports).
+ */
 void __init omap_serial_init(void)
 {
        int i;
 
        for (i = 0; i < ARRAY_SIZE(omap_uart); i++) {
-               struct omap_uart_state *uart = &omap_uart[i];
-               struct platform_device *pdev = &uart->pdev;
-               struct device *dev = &pdev->dev;
-
-               omap_uart_reset(uart);
-               omap_uart_idle_init(uart);
-
-               if (WARN_ON(platform_device_register(pdev)))
-                       continue;
-               if ((cpu_is_omap34xx() && uart->padconf) ||
-                   (uart->wk_en && uart->wk_mask)) {
-                       device_init_wakeup(dev, true);
-                       DEV_CREATE_FILE(dev, &dev_attr_sleep_timeout);
-               }
+               omap_serial_init_port(i);
        }
 }
diff --git a/arch/arm/plat-omap/include/plat/serial.h 
b/arch/arm/plat-omap/include/plat/serial.h
index 9951345..f5a4a92 100644
--- a/arch/arm/plat-omap/include/plat/serial.h
+++ b/arch/arm/plat-omap/include/plat/serial.h
@@ -53,6 +53,7 @@
 #ifndef __ASSEMBLER__
 extern void __init omap_serial_early_init(void);
 extern void omap_serial_init(void);
+extern void omap_serial_init_port(int port);
 extern int omap_uart_can_sleep(void);
 extern void omap_uart_check_wakeup(void);
 extern void omap_uart_prepare_suspend(void);
-- 
1.5.6.5

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to