[U-Boot-Users] [Patch 09/17] U-Boot-V2:Serial: Add support for NS16550 Driver.`

Sascha Hauer s.hauer at pengutronix.de
Tue Jun 3 10:09:10 CEST 2008


On Wed, May 21, 2008 at 11:28:29AM -0500, Menon, Nishanth wrote:
> This introduces support for NS16550 and related OMAP support. This driver is a port from Uboot v1 driver from OMAP's Uboot tree.
> OMAP U-Boot V1 source is available here: http://linux.omap.com/pub/bootloader/3430sdp/u-boot-v1.tar.gz
> 
> Signed-off-by: Nishanth Menon<x0nishan at ti.com>
> 
> ---
>  drivers/serial/Kconfig          |   42 ++++++
>  drivers/serial/Makefile         |    1 
>  drivers/serial/serial_ns16550.c |  248 ++++++++++++++++++++++++++++++++++++++++
>  drivers/serial/serial_ns16550.h |  183 +++++++++++++++++++++++++++++
>  include/ns16550.h               |   46 +++++++
>  5 files changed, 520 insertions(+)
> 
> Index: u-boot-v2.git/drivers/serial/Kconfig
> ===================================================================
> --- u-boot-v2.git.orig/drivers/serial/Kconfig	2008-05-20 17:59:26.000000000 -0500
> +++ u-boot-v2.git/drivers/serial/Kconfig	2008-05-20 18:02:28.000000000 -0500
> @@ -24,4 +24,46 @@
>  	depends on BLACKFIN
>  	default y
>  	bool "Blackfin serial driver"
> +
> +config DRIVER_SERIAL_NS16550
> +	default n
> +	bool "NS16550 serial driver"
> +	help
> +	  Enable this to get support for NS16550 based serial devices
> +choice
> +	prompt "NS16550 register size"
> +	depends on DRIVER_SERIAL_NS16550
> +
> +config DRIVER_SERIAL_NS16550_REG_SIZE_8_BITS
> +	bool "8 bit register"
> +	help
> +	  Say Y here if you are using a 8 bit register for NS16550
> +
> +config DRIVER_SERIAL_NS16550_REG_SIZE_16_BITS
> +	bool "16 bit register"
> +	help
> +	  Say Y here if you are using a 16 bit register for NS16550
> +
> +config DRIVER_SERIAL_NS16550_REG_SIZE_32_BITS
> +	bool "32 bit register"
> +	help
> +	  Say Y here if you are using a 32 bit register for NS16550
> +
> +config DRIVER_SERIAL_NS16550_REG_SIZE_8_BITS_PAD_TO_32
> +	bool "8 bit register Padded to 32 bit"
> +	help
> +	  Say Y here if you are using a 8 bit register padded to 32 bits for NS16550
> +
> +config DRIVER_SERIAL_NS16550_REG_SIZE_8_BITS_PAD_TO_64
> +	bool "8 bit register Padded to 64 bit"
> +	help
> +	  Say Y here if you are using a 8 bit register padded to 64 bits for NS16550
> +endchoice

Please have a look at drivers/net/dm9000.c for an example on how to pass
data between the board and a driver via platform_data. The kconfig approach
for this has several disadvantages. The user is presented a couple of
options which he better does not change because it would break the driver.
Another problem is that you cannot connect two ns16550 with different
register widths on one board (though that's an unlikely case).

> +
> +config DRIVER_SERIAL_NS16550_OMAP_EXTENSIONS
> +	bool "OMAP Extensions for NS16550"
> +	depends on DRIVER_SERIAL_NS16550
> +	depends on ARCH_OMAP
> +	help
> +	  Say Y here if you are using OMAP extensions to NS16550
>  endmenu
> Index: u-boot-v2.git/drivers/serial/Makefile
> ===================================================================
> --- u-boot-v2.git.orig/drivers/serial/Makefile	2008-05-20 17:59:25.000000000 -0500
> +++ u-boot-v2.git/drivers/serial/Makefile	2008-05-20 18:02:28.000000000 -0500
> @@ -10,3 +10,4 @@
>  obj-$(CONFIG_DRIVER_SERIAL_LINUX_COMSOLE)	+= linux_console.o
>  obj-$(CONFIG_DRIVER_SERIAL_MPC5XXX)		+= serial_mpc5xxx.o
>  obj-$(CONFIG_DRIVER_SERIAL_BLACKFIN)		+= serial_blackfin.o
> +obj-$(CONFIG_DRIVER_SERIAL_NS16550)		+= serial_ns16550.o
> Index: u-boot-v2.git/drivers/serial/serial_ns16550.c
> ===================================================================
> --- /dev/null	1970-01-01 00:00:00.000000000 +0000
> +++ u-boot-v2.git/drivers/serial/serial_ns16550.c	2008-05-20 18:04:13.000000000 -0500
> @@ -0,0 +1,248 @@
> +/**
> + * @file
> + * @brief NS16550 Driver implementation
> + *
> + * FileName: drivers/serial/serial_ns16550.c
> + *
> + * NS16550 support
> + * Modified from U-Boot V1 drivers/serial.c and drivers/ns16550.c
> + * originally from linux source (arch/ppc/boot/ns16550.c)
> + * modified to use CFG_ISA_MEM and new defines
> + */
> +/*
> + * (C) Copyright 2008
> + * Texas Instruments, <www.ti.com>
> + * Nishanth Menon <x0nishan at ti.com>
> + *
> + * (C) Copyright 2000
> + * Rob Taylor, Flying Pig Systems. robt at flyingpig.com.
> + *
> + * See file CREDITS for list of people who contributed to this
> + * project.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
> + * MA 02111-1307 USA
> + */
> +
> +
> +#include <common.h>
> +#include <driver.h>
> +#include <init.h>
> +#include <errno.h>
> +#include <malloc.h>
> +#include <asm/io.h>
> +
> +#include "serial_ns16550.h"
> +#include <ns16550.h>
> +
> +/* Forward declaration */
> +static unsigned int ns16550_calc_divisor(struct console_device *cdev,
> +					 unsigned int baudrate);
> +static void ns16550_serial_init_port(struct console_device *cdev);
> +static void ns16550_putc(struct console_device *cdev, char c);
> +static int ns16550_getc(struct console_device *cdev);
> +static int ns16550_tstc(struct console_device *cdev);
> +static int ns16550_setbaudrate(struct console_device *cdev, int baud_rate);
> +static int ns16550_probe(struct device_d *dev);
> +static int ns16550_serial_init(void);

Please reorder the functions to get rid of these declarations. It helps
reading the code when you know that a functions definition is before
its usage.

> +
> +/*********** Private Functions **********************************/
> +
> +/**
> + * @brief ns16550_calc_divisor - compute the divisor for a baud rate
> + *
> + * @param[in] cdev - pointer to console device
> + * @param[in] baudrate - baud rate
> + *
> + * @return divisor to be set
> + */
> +static unsigned int ns16550_calc_divisor(struct console_device *cdev,
> +					 unsigned int baudrate)
> +{
> +	unsigned int clk = ((struct NS16550_plat *)
> +			(cdev->dev->platform_data))->clock;
> +#ifdef CONFIG_DRIVER_SERIAL_NS16550_OMAP_EXTENSIONS
> +	/* FIXME: Legacy Code copied from U-Boot V1 implementation
> +	 */
> +#ifdef CONFIG_ARCH_OMAP1510
> +	NS16550_t com_port = (NS16550_t) (cdev->dev->map_base);
> +	/* If can't cleanly clock 115200 set div to 1 */
> +	if ((clk == 12000000) && (baudrate == 115200)) {
> +		/* enable 6.5 * divisor */
> +		com_port->osc_12m_sel = OSC_12M_SEL;
> +		return (1);	/* return 1 for base divisor */
> +	}
> +	com_port->osc_12m_sel = 0;	/* clear if previsouly set */
> +#elif defined(CONFIG_ARCH_OMAP1610)
> +	/* If can't cleanly clock 115200 set div to 1 */
> +	if ((clk == 48000000) && (baudrate == 115200))
> +		return (26);	/* return 26 for base divisor */
> +#endif
> +
> +#endif				/* End of OMAP specific handling */
> +	return (clk / MODE_X_DIV / baudrate);
> +
> +}
> +
> +/**
> + * @brief ns16550_serial_init_port - initialize the device
> + *
> + * @param cdev[in] - pointer to console device
> + */
> +static void ns16550_serial_init_port(struct console_device *cdev)
> +{
> +	unsigned int baud_divisor;
> +	NS16550_t com_port = (NS16550_t) (cdev->dev->map_base);
> +
> +	/* Setup the serial port with the defaults first */
> +	baud_divisor = ns16550_calc_divisor(cdev, CONFIG_BAUDRATE);
> +
> +	/* initializing the device for the first time */
> +	com_port->ier = 0x00;
> +#ifdef CONFIG_DRIVER_SERIAL_NS16550_OMAP_EXTENSIONS
> +	com_port->mdr1 = 0x7;	/* Disable */
> +#endif
> +	com_port->lcr = LCR_BKSE | LCRVAL;
> +	com_port->dll = baud_divisor & 0xff;
> +	com_port->dlm = (baud_divisor >> 8) & 0xff;
> +	com_port->lcr = LCRVAL;
> +	com_port->mcr = MCRVAL;
> +	com_port->fcr = FCRVAL;
> +#ifdef CONFIG_DRIVER_SERIAL_NS16550_OMAP_EXTENSIONS
> +	com_port->mdr1 = 0;	/* enable uart mode */
> +#endif
> +}
> +
> +/*********** Exposed Functions **********************************/
> +
> +/**
> + * @brief ns16550_putc- put a character to the serial port
> + *
> + * @param cdev[in] - pointer to console device
> + * @param c[in] - character to put
> + */
> +static void ns16550_putc(struct console_device *cdev, char c)
> +{
> +	NS16550_t com_port = (NS16550_t) (cdev->dev->map_base);
> +	/* Loop Doing Nothing */
> +	while ((com_port->lsr & LSR_THRE) == 0) ;
> +	com_port->thr = c;
> +}
> +
> +/**
> + * @brief ns16550_getc - retrieve a character from serial port
> + *
> + * @param cdev[in] - pointer to console device
> + *
> + * @return return the character read
> + */
> +static int ns16550_getc(struct console_device *cdev)
> +{
> +	NS16550_t com_port = (NS16550_t) (cdev->dev->map_base);
> +	/* Loop Doing Nothing */
> +	while ((com_port->lsr & LSR_DR) == 0) ;
> +	return (com_port->rbr);
> +}
> +
> +/**
> + * @brief ns16550_tstc - test if character is available
> + *
> + * @param cdev[in] -pointer to console device
> + *
> + * @return  - status based on data availability
> + */
> +static int ns16550_tstc(struct console_device *cdev)
> +{
> +	NS16550_t com_port = (NS16550_t) (cdev->dev->map_base);
> +	return ((com_port->lsr & LSR_DR) != 0);
> +}
> +
> +/**
> + * @brief ns16550_setbaudrate - set the baudrate for the uart port
> + *
> + * @param cdev[in] - console device
> + * @param baud_rate[in] - baud rate to set
> + *
> + * @return  0-implied to support the baudrate
> + */
> +static int ns16550_setbaudrate(struct console_device *cdev, int baud_rate)
> +{
> +	NS16550_t com_port = (NS16550_t) (cdev->dev->map_base);
> +	unsigned int baud_divisor = ns16550_calc_divisor(cdev, baud_rate);
> +	com_port->ier = 0x00;
> +	com_port->lcr = LCR_BKSE;
> +	com_port->dll = baud_divisor & 0xff;
> +	com_port->dlm = (baud_divisor >> 8) & 0xff;
> +	com_port->lcr = LCRVAL;
> +	com_port->mcr = MCRVAL;
> +	com_port->fcr = FCRVAL;
> +	return 0;
> +}
> +
> +/**
> + * @brief ns16550_probe - Probe entry point -called on the first
> + *			  match for device
> + *
> + * @param dev[in]  - matched device
> + *
> + * @return EINVAL if platform_data is not populated,
> + *	   ENOMEM if calloc failed
> + *	   else return result of console_register
> + */
> +static int ns16550_probe(struct device_d *dev)
> +{
> +	struct console_device *cdev;
> +	struct NS16550_plat *plat = (struct NS16550_plat *)dev->platform_data;
> +
> +	/* we do expect platform specific data */
> +	if (plat == NULL)
> +		return -EINVAL;
> +	cdev = calloc(1, sizeof(struct console_device));
> +	if (cdev == NULL)
> +		return -ENOMEM;
> +
> +	dev->type_data = cdev;
> +	cdev->dev = dev;
> +	cdev->f_caps = plat->f_caps;

Ok, you know about platform_data ;). I suggest that you put the register
access functions there.

> +	cdev->tstc = ns16550_tstc;
> +	cdev->putc = ns16550_putc;
> +	cdev->getc = ns16550_getc;
> +	cdev->setbrg = ns16550_setbaudrate;
> +
> +	ns16550_serial_init_port(cdev);
> +
> +	return console_register(cdev);
> +}
> +
> +/**
> + * @brief Driver registration structure
> + */
> +static struct driver_d ns16550_serial_driver = {
> +	.name = "serial_ns16550",
> +	.probe = ns16550_probe,
> +	.type = DEVICE_TYPE_CONSOLE,
> +};
> +
> +/**
> + * @brief ns16550_serial_init - driver initialization function
> + *
> + * @return result of register_driver
> + */
> +static int ns16550_serial_init(void)
> +{
> +	return register_driver(&ns16550_serial_driver);
> +}
> +
> +console_initcall(ns16550_serial_init);
> Index: u-boot-v2.git/drivers/serial/serial_ns16550.h
> ===================================================================
> --- /dev/null	1970-01-01 00:00:00.000000000 +0000
> +++ u-boot-v2.git/drivers/serial/serial_ns16550.h	2008-05-20 18:02:28.000000000 -0500
> @@ -0,0 +1,183 @@
> +/**
> + * @file
> + * @brief Serial NS16550 header
> + *
> + * FileName: drivers/serial/serial_ns16550.h
> + *
> + * @code struct NS16550 @endcode
> + * Register definitions for NS16550 device
> + */
> +/*
> + * This file is licensed under
> + * the terms of the GNU General Public License version 2.  This program
> + * is licensed "as is" without any warranty of any kind, whether express
> + * or implied.
> + *
> + * NS16550 Serial Port
> + * originally from linux source (arch/ppc/boot/ns16550.h)
> + * modified slightly to
> + * have addresses as offsets from CFG_ISA_BASE
> + * added a few more definitions
> + * added prototypes for ns16550.c
> + * reduced no of com ports to 2
> + * modifications (c) Rob Taylor, Flying Pig Systems. 2000.
> + *
> + * added support for port on 64-bit bus
> + * by Richard Danter (richard.danter at windriver.com), (C) 2005 Wind River Systems
> + */
> +
> +
> +#ifndef __SERIAL_NS16550__H
> +#define  __SERIAL_NS16550__H
> +#ifdef CONFIG_DRIVER_SERIAL_NS16550_REG_SIZE_8_BITS
> +struct NS16550 {
> +	/** RBR register */
> +	unsigned char rbr;	/* 0 */
> +	unsigned char ier;	/* 1 */
> +	unsigned char fcr;	/* 2 */
> +	unsigned char lcr;	/* 3 */
> +	unsigned char mcr;	/* 4 */
> +	unsigned char lsr;	/* 5 */
> +	unsigned char msr;	/* 6 */
> +	unsigned char scr;	/* 7 */
> +#ifdef CONFIG_DRIVER_SERIAL_NS16550_OMAP_EXTENSIONS
> +	unsigned char mdr1;	/* 8 */
> +	unsigned char reg9;	/* 9 */
> +	unsigned char regA;	/* A */
> +	unsigned char regB;	/* B */
> +	unsigned char regC;	/* C */
> +	unsigned char regD;	/* D */
> +	unsigned char regE;	/* E */
> +	unsigned char regF;	/* F */
> +	unsigned char reg10;	/* 10 */
> +	unsigned char ssr;	/* 11 */
> +#endif
> +} __attribute__ ((packed));
> +#elif defined(DRIVER_SERIAL_NS16550_REG_SIZE_16_BITS)
> +struct NS16550 {
> +	unsigned short rbr;	/* 0 */
> +	unsigned short ier;	/* 1 */
> +	unsigned short fcr;	/* 2 */
> +	unsigned short lcr;	/* 3 */
> +	unsigned short mcr;	/* 4 */
> +	unsigned short lsr;	/* 5 */
> +	unsigned short msr;	/* 6 */
> +	unsigned short scr;	/* 7 */
> +} __attribute__ ((packed));
> +#elif defined(DRIVER_SERIAL_NS16550_REG_SIZE_32_BITS)
> +struct NS16550 {
> +	unsigned long rbr;	/* 0 r  */
> +	unsigned long ier;	/* 1 rw */
> +	unsigned long fcr;	/* 2 w  */
> +	unsigned long lcr;	/* 3 rw */
> +	unsigned long mcr;	/* 4 rw */
> +	unsigned long lsr;	/* 5 r  */
> +	unsigned long msr;	/* 6 r  */
> +	unsigned long scr;	/* 7 rw */
> +};				/* No need to pack an already aligned struct */
> +#elif defined(CONFIG_DRIVER_SERIAL_NS16550_REG_SIZE_8_BITS_PAD_TO_32)
> +struct NS16550 {
> +	unsigned char rbr;	/* 0 */
> +	unsigned int pad1:24;
> +	unsigned char ier;	/* 1 */
> +	unsigned int pad2:24;
> +	unsigned char fcr;	/* 2 */
> +	unsigned int pad3:24;
> +	unsigned char lcr;	/* 3 */
> +	unsigned int pad4:24;
> +	unsigned char mcr;	/* 4 */
> +	unsigned int pad5:24;
> +	unsigned char lsr;	/* 5 */
> +	unsigned int pad6:24;
> +	unsigned char msr;	/* 6 */
> +	unsigned int pad7:24;
> +	unsigned char scr;	/* 7 */
> +	unsigned int pad8:24;
> +#ifdef CONFIG_DRIVER_SERIAL_NS16550_OMAP_EXTENSIONS
> +	unsigned char mdr1;	/* mode select reset TL16C750 */
> +#ifdef CONFIG_ARCH_OMAP1510
> +	unsigned int pad9:24;
> +	unsigned long pad[10];
> +	unsigned char osc_12m_sel;
> +	unsigned int pad10:24;
> +#endif				/* CONFIG_ARCH_OMAP1510 */
> +#endif			/* CONFIG_DRIVER_SERIAL_NS16550_OMAP_EXTENSIONS */
> +} __attribute__ ((packed));
> +
> +#elif defined(DRIVER_SERIAL_NS16550_REG_SIZE_8_BITS_PAD_TO_64)
> +struct NS16550 {
> +	unsigned char rbr;	/* 0 */
> +	unsigned char pad0[7];
> +	unsigned char ier;	/* 1 */
> +	unsigned char pad1[7];
> +	unsigned char fcr;	/* 2 */
> +	unsigned char pad2[7];
> +	unsigned char lcr;	/* 3 */
> +	unsigned char pad3[7];
> +	unsigned char mcr;	/* 4 */
> +	unsigned char pad4[7];
> +	unsigned char lsr;	/* 5 */
> +	unsigned char pad5[7];
> +	unsigned char msr;	/* 6 */
> +	unsigned char pad6[7];
> +	unsigned char scr;	/* 7 */
> +	unsigned char pad7[7];
> +} __attribute__ ((packed));
> +#else
> +#error "Please define NS16550 registers size."
> +#endif
> +
> +#define thr rbr
> +#define iir fcr
> +#define dll rbr
> +#define dlm ier
> +
> +/** @brief typedef for register access */
> +typedef volatile struct NS16550 *NS16550_t;
> +
> +#define FCR_FIFO_EN     0x01	/* Fifo enable */
> +#define FCR_RXSR        0x02	/* Receiver soft reset */
> +#define FCR_TXSR        0x04	/* Transmitter soft reset */
> +
> +#define MCR_DTR         0x01
> +#define MCR_RTS         0x02
> +#define MCR_DMA_EN      0x04
> +#define MCR_TX_DFR      0x08
> +
> +#define LCR_WLS_MSK	0x03	/* character length select mask */
> +#define LCR_WLS_5	0x00	/* 5 bit character length */
> +#define LCR_WLS_6	0x01	/* 6 bit character length */
> +#define LCR_WLS_7	0x02	/* 7 bit character length */
> +#define LCR_WLS_8	0x03	/* 8 bit character length */
> +/* Number of stop Bits, off = 1, on = 1.5 or 2) */
> +#define LCR_STB		0x04
> +#define LCR_PEN		0x08	/* Parity eneble */
> +#define LCR_EPS		0x10	/* Even Parity Select */
> +#define LCR_STKP	0x20	/* Stick Parity */
> +#define LCR_SBRK	0x40	/* Set Break */
> +#define LCR_BKSE	0x80	/* Bank select enable */
> +
> +#define LSR_DR		0x01	/* Data ready */
> +#define LSR_OE		0x02	/* Overrun */
> +#define LSR_PE		0x04	/* Parity error */
> +#define LSR_FE		0x08	/* Framing error */
> +#define LSR_BI		0x10	/* Break */
> +#define LSR_THRE	0x20	/* Xmit holding register empty */
> +#define LSR_TEMT	0x40	/* Xmitter empty */
> +#define LSR_ERR		0x80	/* Error */
> +
> +#ifdef CONFIG_ARCH_OMAP1510
> +#define OSC_12M_SEL	0x01	/* selects 6.5 * current clk div */
> +#endif
> +
> +/* useful defaults for LCR */
> +#define LCR_8N1		0x03
> +
> +#define LCRVAL		LCR_8N1	/* 8 data, 1 stop, no parity */
> +#define MCRVAL		(MCR_DTR | MCR_RTS) /* RTS/DTR */
> +/* Clear & enable FIFOs */
> +#define FCRVAL		(FCR_FIFO_EN | FCR_RXSR | FCR_TXSR)
> +
> +#define MODE_X_DIV	16
> +
> +#endif				/*  __SERIAL_NS16550__H */
> Index: u-boot-v2.git/include/ns16550.h
> ===================================================================
> --- /dev/null	1970-01-01 00:00:00.000000000 +0000
> +++ u-boot-v2.git/include/ns16550.h	2008-05-20 18:02:28.000000000 -0500
> @@ -0,0 +1,46 @@
> +/**
> + * @file
> + * @brief Serial NS16550 platform specific header
> + *
> + * FileName: include/ns16550.h
> + * @code struct NS16550_plat @endcode
> + * represents The specifics of the device present in the system.
> + */
> +/*
> + * (C) Copyright 2008
> + * Texas Instruments, <www.ti.com>
> + * Nishanth Menon <x0nishan at ti.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
> + * MA 02111-1307 USA
> + */
> +
> +#ifndef __NS16650_PLATFORM_H_
> +#define __NS16650_PLATFORM_H_
> +
> +/**
> + * @brief Platform dependent feature:
> + * Pass pointer to this structure as part of device_d -> platform_data
> + */
> +struct NS16550_plat {
> +	/** Clock speed */
> +	unsigned int clock;
> +	/** Console capabilities:
> +	 * CONSOLE_STDIN | CONSOLE_STDOUT | CONSOLE_STDERR @see console.h
> +	 */
> +	unsigned char f_caps;
> +};
> +
> +#endif /* __NS16650_PLATFORM_H_ */
> 

-- 
Pengutronix e.K. - Linux Solutions for Science and Industry
-----------------------------------------------------------
Kontakt-Informationen finden Sie im Header dieser Mail oder
auf der Webseite -> http://www.pengutronix.de/impressum/ <-




More information about the U-Boot mailing list