hi Ira Snyder,
Thanks for the respone. The solution mentioned looks feasible..
Could you please send the U-boot patch in the current shape .. Shall test the
same patch with modifications as required to support our board.
Thanks again .
Rajeev S
Ira Snyder <[EMAIL PROTECTED]> wrote: On Fri, Oct 31, 2008 at 01:25:14PM +0100,
Jean-Christophe PLAGNIOL-VILLARD wrote:
> On 08:06 Fri 31 Oct , Jerry Van Baren wrote:
> > Wolfgang Denk wrote:
> > > Dear rajeev s,
> > >
> > > In message <[EMAIL PROTECTED]> you wrote:
> > >> We have a custom board based on coldfire (MCF5484) Similar to MCF5484
> > >> Kitlite
> > >> The board runs Coldfire as PCI agent , 64MB of SDRAM, 4 MB of Bootflash
> > >> and the PCI bus as a slave (no serial
> > >> port->no console)
> > >> I can flash U-boot using the JTAG . Can you let know how can i pass the
> > >> Commands over PCI .
> > >> I do not have a Console to do that ?
[snip]
> >
> > I have not googled, I'm sure many people have done this before. Maybe
> > you will get lucky and someone will have published source under a GPL
> > (compatible) license.
> IIRC I've seen this in the Prism54 driver
>
I'm currently working on a custom board based on MPC8349EMDS. It works
in PCI agent mode.
I have written a Linux driver that implements both ethernet and a uart
over the PCI bus. I don't think it would be hard to port to your board.
Search the linuxppc-dev or LKML archives for the patch. The subject is
"net: add PCINet driver".
I'm currently trying to get the driver merged into Linux. I have also
written U-Boot drivers that offer the same functionality. I can "see"
the U-Boot prompt over PCI, and tftp + nfs boot over PCI. It is very
convenient.
I was going to post up the U-Boot drivers after I get the Linux driver
merged, just in case there are changes. I've inlined the patches below.
The first adds ethernet, the second adds a serial port.
Please note that they are MPC8349EMDS specific right now, but they might
provide inspiration. Showing your support of the PCINet driver on LKML
might help get it reviewed. Noone has taken much interest.
Ira
>From 356297a295bb2a5ee7c0bc736b838f144939376d Mon Sep 17 00:00:00 2001
From: Ira W. Snyder
Date: Mon, 18 Aug 2008 15:40:40 -0700
Subject: [PATCH] Add PCINet Driver
This adds a virtual network interface that uses the PCI bus for
communication. This is extremely useful for boards in PCISLAVE mode, so you
do not need extra cables to communicate with them.
There is a corresponding Linux driver to be run on the host system.
Signed-off-by: Ira W. Snyder
---
cpu/mpc83xx/cpu.c | 4 +-
drivers/net/Makefile | 1 +
drivers/net/pcinet.c | 503 ++++++++++++++++++++++++++++++++++++++++++++++++++
drivers/net/pcinet.h | 73 ++++++++
4 files changed, 580 insertions(+), 1 deletions(-)
create mode 100644 drivers/net/pcinet.c
create mode 100644 drivers/net/pcinet.h
diff --git a/cpu/mpc83xx/cpu.c b/cpu/mpc83xx/cpu.c
index aa9b18d..79c0363 100644
--- a/cpu/mpc83xx/cpu.c
+++ b/cpu/mpc83xx/cpu.c
@@ -364,6 +364,8 @@ int cpu_eth_init(bd_t *bis)
#if defined(CONFIG_TSEC_ENET)
tsec_standard_init(bis);
#endif
-
+#ifdef CONFIG_PCINET_ETHERNET
+ pcinet_initialize(bis, 0, "PCINET");
+#endif
return 0;
}
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 439c354..2435e63 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -52,6 +52,7 @@ COBJS-$(CONFIG_NETCONSOLE) += netconsole.o
COBJS-$(CONFIG_DRIVER_NS7520_ETHERNET) += ns7520_eth.o
COBJS-$(CONFIG_NS8382X) += ns8382x.o
COBJS-$(CONFIG_DRIVER_NS9750_ETHERNET) += ns9750_eth.o
+COBJS-$(CONFIG_PCINET_ETHERNET) += pcinet.o
COBJS-$(CONFIG_PCNET) += pcnet.o
COBJS-$(CONFIG_PLB2800_ETHER) += plb2800_eth.o
COBJS-$(CONFIG_DRIVER_RTL8019) += rtl8019.o
diff --git a/drivers/net/pcinet.c b/drivers/net/pcinet.c
new file mode 100644
index 0000000..b86383f
--- /dev/null
+++ b/drivers/net/pcinet.c
@@ -0,0 +1,503 @@
+/*
+ * PCINet Virtual Ethernet over PCI driver
+ *
+ * This software may be used and distributed according to the
+ * terms of the GNU General Public License, Version 2, incorporated
+ * herein by reference.
+ *
+ * Copyright (c) 2008, Ira W. Snyder
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include "pcinet.h"
+
+struct wqt_dev;
+typedef void (*wqt_irqhandler_t)(struct wqt_dev *);
+
+struct wqt_dev {
+ wqt_irqhandler_t net_rx_packet_handler;
+ wqt_irqhandler_t net_tx_complete_handler;
+ int state;
+
+ void *netregs;
+
+ cbd_t *rx_base;
+ cbd_t *tx_base;
+
+ cbd_t *cur_rx;
+ cbd_t *cur_tx;
+ cbd_t *dirty_tx;
+ int tx_free;
+};
+
+#define W32(addr, b) out_le32((volatile u32 *)(addr), (b))
+#define R32(addr) in_le32((volatile u32 *)(addr))
+
+#define W32BE(addr, b) out_be32((volatile u32 *)(addr), (b))
+#define R32BE(addr) in_be32((volatile u32 *)(addr))
+
+/*----------------------------------------------------------------------------*/
+/* Status Bits
*/
+/*----------------------------------------------------------------------------*/
+
+static void status_setbit(u32 bit)
+{
+ volatile immap_t *immr = (volatile immap_t *)CONFIG_SYS_IMMR;
+ volatile dma83xx_t *dma = &immr->dma;
+
+ W32(&dma->omr1, R32(&dma->omr1) | bit);
+}
+
+static void status_clrbit(u32 bit)
+{
+ volatile immap_t *immr = (volatile immap_t *)CONFIG_SYS_IMMR;
+ volatile dma83xx_t *dma = &immr->dma;
+
+ W32(&dma->omr1, R32(&dma->omr1) & ~bit);
+}
+
+static u32 status_remote_testbit(u32 bit)
+{
+ volatile immap_t *immr = (volatile immap_t *)CONFIG_SYS_IMMR;
+ volatile dma83xx_t *dma = &immr->dma;
+
+ return R32(&dma->imr1) & bit;
+}
+
+/*----------------------------------------------------------------------------*/
+/* Doorbell
*/
+/*----------------------------------------------------------------------------*/
+
+static void doorbell_set(u32 bit)
+{
+ volatile immap_t *immr = (volatile immap_t *)CONFIG_SYS_IMMR;
+ volatile dma83xx_t *dma = &immr->dma;
+
+ W32(&dma->odr, bit);
+}
+
+/*----------------------------------------------------------------------------*/
+/* DMA
*/
+/*----------------------------------------------------------------------------*/
+
+/*
+ * Set up a 1GB outbound window starting at PCI address 0x0
+ */
+static void setup_outbound_window(void)
+{
+ volatile immap_t *immr = (volatile immap_t *)CONFIG_SYS_IMMR;
+ volatile law83xx_t *pci_law = immr->sysconf.pcilaw;
+ volatile pot83xx_t *pci_pot = immr->ios.pot;
+
+ W32BE(&pci_law[0].ar, LAWAR_EN | LAWAR_SIZE_1G);
+ W32BE(&pci_pot[0].pocmr, POCMR_EN | POCMR_PREFETCH_EN
+ | (POCMR_CM_1G & POCMR_CM_MASK));
+ W32BE(&pci_pot[0].potar, 0x0);
+}
+
+static void dma_pci_to_buf(u32 dst, u32 src, size_t len)
+{
+ volatile immap_t *immr = (volatile immap_t *)CONFIG_SYS_IMMR;
+ volatile dma83xx_t *dma = &immr->dma;
+
+ /* Wait for the DMA controller to become free */
+ while (R32(&dma->dmasr0) & DMA_CHANNEL_BUSY)
+ udelay(100);
+
+ /* Program the DMA controller */
+ W32(&dma->dmasar0, 0x80000000 + src);
+ W32(&dma->dmadar0, dst);
+ W32(&dma->dmabcr0, len);
+
+ /* Start the transfer */
+ W32(&dma->dmamr0, DMA_CHANNEL_TRANSFER_MODE_DIRECT | DMA_CHANNEL_SNOOP);
+ W32(&dma->dmamr0, DMA_CHANNEL_TRANSFER_MODE_DIRECT | DMA_CHANNEL_SNOOP
+ | DMA_CHANNEL_START);
+
+ while (R32(&dma->dmasr0) & DMA_CHANNEL_BUSY)
+ udelay(100);
+}
+
+static void dma_buf_to_pci(u32 dst, u32 src, size_t len)
+{
+ volatile immap_t *immr = (volatile immap_t *)CONFIG_SYS_IMMR;
+ volatile dma83xx_t *dma = &immr->dma;
+
+ /* Wait for the DMA controller to become free */
+ while (R32(&dma->dmasr0) & DMA_CHANNEL_BUSY)
+ udelay(100);
+
+ /* Program the DMA controller */
+ W32(&dma->dmasar0, src);
+ W32(&dma->dmadar0, 0x80000000 + dst);
+ W32(&dma->dmabcr0, len);
+
+ /* Start the transfer */
+ W32(&dma->dmamr0, DMA_CHANNEL_TRANSFER_MODE_DIRECT | DMA_CHANNEL_SNOOP);
+ W32(&dma->dmamr0, DMA_CHANNEL_TRANSFER_MODE_DIRECT | DMA_CHANNEL_SNOOP
+ | DMA_CHANNEL_START);
+
+ while (R32(&dma->dmasr0) & DMA_CHANNEL_BUSY)
+ udelay(100);
+}
+
+/*----------------------------------------------------------------------------*/
+/* Helper Functions
*/
+/*----------------------------------------------------------------------------*/
+
+static int pcinet_init_netregs(struct wqt_dev *priv)
+{
+ volatile immap_t *immr = (volatile immap_t *)CONFIG_SYS_IMMR;
+ volatile pcictrl83xx_t *pci_ctrl = &immr->pci_ctrl[0];
+ u32 val;
+
+ /* Check the PCI Inbound Window Attributes Register 0 for a 4k window
+ * This is PCI BAR1, and will be used as network device registers */
+ val = R32BE(&pci_ctrl->piwar0) & (PIWAR_EN | PIWAR_IWS_4K);
+
+ if (val != (PIWAR_EN | PIWAR_IWS_4K)) {
+ printf("PIWAR0 set up incorrectly (was %x should be %x)\n",
+ val, (PIWAR_EN | PIWAR_IWS_4K));
+ return -ENODEV;
+ }
+
+ /* Allocate the 4k of registers, 4k aligned */
+ priv->netregs = memalign(4096, 4096);
+
+ if (!priv->netregs)
+ return -ENOMEM;
+
+ memset(priv->netregs, 0, 4096);
+
+ /* Write the address into the inbound window address register */
+ W32BE(&pci_ctrl->pitar0, (u32)priv->netregs >> 12);
+
+ return 0;
+}
+
+/*----------------------------------------------------------------------------*/
+/* Interrupt Handling
*/
+/*----------------------------------------------------------------------------*/
+
+static void net_rx_packet_handler(struct wqt_dev *priv);
+static void net_tx_complete_handler(struct wqt_dev *priv);
+static void empty_handler(struct wqt_dev *priv);
+
+static void do_reinitialize_ring_pointers(struct wqt_dev *priv)
+{
+ priv->cur_rx = priv->rx_base;
+ priv->cur_tx = priv->tx_base;
+ priv->dirty_tx = priv->tx_base;
+ priv->tx_free = PH_RING_SIZE;
+}
+
+static void do_start_queues(struct wqt_dev *priv)
+{
+ priv->net_rx_packet_handler = net_rx_packet_handler;
+ priv->net_tx_complete_handler = net_tx_complete_handler;
+}
+
+static void do_stop_queues(struct wqt_dev *priv)
+{
+ priv->net_rx_packet_handler = empty_handler;
+ priv->net_tx_complete_handler = empty_handler;
+}
+
+static void empty_handler(struct wqt_dev *priv)
+{
+}
+
+static void net_start_handler(struct wqt_dev *priv)
+{
+ if (priv->state == NET_STATE_RUNNING)
+ return;
+
+ do_reinitialize_ring_pointers(priv);
+ do_start_queues(priv);
+
+ priv->state = NET_STATE_RUNNING;
+}
+
+static void net_stop_handler(struct wqt_dev *priv)
+{
+ if (priv->state == NET_STATE_STOPPED)
+ return;
+
+ do_stop_queues(priv);
+
+ priv->state = NET_STATE_STOPPED;
+}
+
+static void net_rx_packet_handler(struct wqt_dev *priv)
+{
+ cbd_t *bdp;
+ int dirty_idx;
+ u32 pkt_len, src_addr;
+ uchar *pkt;
+
+ bdp = priv->cur_rx;
+
+ while (CBDR_SC(bdp) == BD_MEM_DIRTY) {
+ dirty_idx = bdp - priv->rx_base;
+
+ pkt_len = CBDR_LEN(bdp);
+ src_addr = CBDR_ADDR(bdp);
+
+ pkt = malloc(pkt_len);
+
+ if (pkt != NULL) {
+ dma_pci_to_buf((u32)pkt, src_addr, pkt_len);
+ NetReceive(pkt, pkt_len);
+ free(pkt);
+ }
+
+ CBDW_SC(bdp, BD_MEM_FREE);
+
+ if (dirty_idx == PH_RING_SIZE - 1)
+ bdp = priv->rx_base;
+ else
+ bdp++;
+ }
+
+ priv->cur_rx = bdp;
+
+ doorbell_set(NET_TX_COMPLETE_DBELL);
+}
+
+static void net_tx_complete_handler(struct wqt_dev *priv)
+{
+ cbd_t *bdp;
+ int dirty_idx;
+
+ bdp = priv->dirty_tx;
+
+ while (CBDR_SC(bdp) == BD_MEM_FREE) {
+ dirty_idx = bdp - priv->tx_base;
+
+ priv->tx_free++;
+ CBDW_SC(bdp, BD_MEM_READY);
+
+ if (dirty_idx == PH_RING_SIZE - 1)
+ bdp = priv->tx_base;
+ else
+ bdp++;
+ }
+
+ priv->dirty_tx = bdp;
+}
+
+static void pcinet_interrupt(struct wqt_dev *priv)
+{
+ volatile immap_t *immr = (volatile immap_t *)CONFIG_SYS_IMMR;
+ volatile dma83xx_t *dma = &immr->dma;
+ u32 idr;
+
+ idr = R32(&dma->idr);
+
+ /* Clear all of the network doorbells */
+ W32(&dma->idr, NET_START_REQ_DBELL | NET_START_ACK_DBELL
+ | NET_STOP_REQ_DBELL | NET_STOP_ACK_DBELL
+ | NET_RX_PACKET_DBELL | NET_TX_COMPLETE_DBELL);
+
+ if (idr & NET_START_REQ_DBELL) {
+ net_start_handler(priv);
+ doorbell_set(NET_START_ACK_DBELL);
+ }
+
+ if (idr & NET_START_ACK_DBELL)
+ net_start_handler(priv);
+
+ if (idr & NET_STOP_REQ_DBELL) {
+ net_stop_handler(priv);
+ doorbell_set(NET_STOP_ACK_DBELL);
+ }
+
+ if (idr & NET_STOP_ACK_DBELL)
+ net_stop_handler(priv);
+
+ if (idr & NET_RX_PACKET_DBELL)
+ priv->net_rx_packet_handler(priv);
+
+ if (idr & NET_TX_COMPLETE_DBELL)
+ priv->net_tx_complete_handler(priv);
+
+ /* This slows down the interrupt routine a bit, since we don't need
+ * to be running it as absolutely fast as the CPU can handle */
+ udelay(250);
+}
+
+/*----------------------------------------------------------------------------*/
+/* Ethernet Device Functions
*/
+/*----------------------------------------------------------------------------*/
+
+/* Initializes data structures and registers for the controller,
+ * and brings the interface up. Returns the link status, meaning:
+ * SUCCESS if the link is up
+ * FAILURE otherwise
+ *
+ * This allows u-boot to find the first active controller
+ */
+static int pcinet_open(struct eth_device *dev, bd_t *bd)
+{
+ struct wqt_dev *priv = dev->priv;
+ int i;
+
+ status_setbit(PCINET_NET_STATUS_RUNNING);
+ do_stop_queues(priv);
+
+ /* If the other side is not running, there isn't much we can do. It's not
like we
+ * can just magically start it */
+ if (!status_remote_testbit(PCINET_NET_STATUS_RUNNING))
+ return 0;
+
+ /* Notify the other side to start */
+ doorbell_set(NET_START_REQ_DBELL);
+
+ /* Wait for 5 seconds to start */
+ for (i=0; priv->state == NET_STATE_STOPPED && i<5000; ++i) {
+ pcinet_interrupt(priv);
+ udelay(1000);
+ }
+
+ if (priv->state == NET_STATE_RUNNING)
+ return 1;
+
+ return 0;
+}
+
+/* Stop the interface completely */
+static void pcinet_stop(struct eth_device *dev)
+{
+ struct wqt_dev *priv = dev->priv;
+ int i;
+
+ status_clrbit(PCINET_NET_STATUS_RUNNING);
+ do_stop_queues(priv);
+
+ if (priv->state == NET_STATE_RUNNING) {
+ doorbell_set(NET_STOP_REQ_DBELL);
+
+ /* Wait 5 seconds to stop */
+ for (i=0; priv->state == NET_STATE_RUNNING && i<5000; ++i) {
+ pcinet_interrupt(priv);
+ udelay(1000);
+ }
+ }
+}
+
+static int pcinet_xmit(struct eth_device *dev, volatile void *packet, int
length)
+{
+ struct wqt_dev *priv = dev->priv;
+ u32 dst_addr;
+ int dirty_idx;
+ cbd_t *bdp;
+
+ bdp = priv->cur_tx;
+ dirty_idx = bdp - priv->tx_base;
+
+ if (priv->state == NET_STATE_STOPPED)
+ return 1;
+
+ /* Check for no free TX slots */
+ if (priv->tx_free == 0 || CBDR_SC(bdp) != BD_MEM_READY)
+ return 1;
+
+ dst_addr = CBDR_ADDR(bdp);
+
+ /* DMA the packet into the remote memory */
+ dma_buf_to_pci(dst_addr, (u32)packet, length);
+
+ CBDW_LEN(bdp, length);
+ CBDW_SC(bdp, BD_MEM_DIRTY);
+
+ if (dirty_idx == PH_RING_SIZE - 1)
+ bdp = priv->tx_base;
+ else
+ bdp++;
+
+ priv->cur_tx = bdp;
+ priv->tx_free--;
+
+ if (!status_remote_testbit(PCINET_NET_RXINT_OFF))
+ doorbell_set(NET_RX_PACKET_DBELL);
+
+ return 0;
+}
+
+static int pcinet_recv(struct eth_device *dev)
+{
+ struct wqt_dev *priv = dev->priv;
+ pcinet_interrupt(priv);
+ return -1;
+}
+
+/* Called from net/eth.c to start the ethernet controller */
+int pcinet_initialize(bd_t *bis, int index, char *devname)
+{
+ struct eth_device *dev;
+ struct wqt_dev *priv;
+ int ret;
+
+ /* Allocate the ethernet device and driver-private data */
+ dev = malloc(sizeof(*dev));
+
+ if (!dev)
+ goto out_alloc_eth_device;
+
+ priv = malloc(sizeof(*priv));
+
+ if (!priv)
+ goto out_alloc_priv;
+
+ memset(dev, 0, sizeof(*dev));
+ memset(priv, 0, sizeof(*priv));
+
+ /* Allocate and setup network registers */
+ ret = pcinet_init_netregs(priv);
+
+ if (ret)
+ goto out_init_netregs;
+
+ status_setbit(PCINET_NET_REGISTERS_VALID);
+ priv->rx_base = priv->netregs + PCINET_TXBD_BASE;
+ priv->tx_base = priv->netregs + PCINET_RXBD_BASE;
+
+ /* Set up the outbound window */
+ setup_outbound_window();
+
+ /* Setup ethernet device */
+ sprintf (dev->name, devname);
+ dev->iobase = 0;
+ dev->priv = priv;
+ dev->init = pcinet_open;
+ dev->halt = pcinet_stop;
+ dev->send = pcinet_xmit;
+ dev->recv = pcinet_recv;
+
+ /* Tell u-boot to get the addr from the env */
+ memset(dev->enetaddr, 0, 6);
+
+ eth_register (dev);
+
+ return 1;
+
+out_init_netregs:
+ free(priv);
+out_alloc_priv:
+ free(dev);
+out_alloc_eth_device:
+ return 0;
+}
+
+/* vim: set ts=8 sts=8 sw=8 noet tw=92: */
diff --git a/drivers/net/pcinet.h b/drivers/net/pcinet.h
new file mode 100644
index 0000000..b1851fe
--- /dev/null
+++ b/drivers/net/pcinet.h
@@ -0,0 +1,73 @@
+/*
+ * ONE-LINE DESCRIPTION
+ *
+ * Copyright (c) 2008 Ira W. Snyder
+ *
+ * Heavily inspired by the drivers/net/fs_enet driver
+ *
+ * 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.
+ */
+
+#ifndef PCINET_H
+#define PCINET_H
+
+//#define PH_MAX_MTU (1508)
+//#define PH_MAX_MTU (4082)
+//#define PH_MAX_MTU (8178)
+//#define PH_MAX_MTU (16370)
+//#define PH_MAX_MTU (32754)
+#define PH_MAX_MTU (65522)
+//#define PH_MAX_MTU (131058)
+#define PH_MAX_FRSIZE (PH_MAX_MTU+ETHER_HDR_SIZE)
+
+#define PH_RING_SIZE 64
+
+struct circ_buf_desc {
+ u32 sc;
+ u32 len;
+ u32 addr;
+} __attribute__((__packed__));
+typedef struct circ_buf_desc cbd_t;
+
+/* Buffer Descriptor Accessors */
+#define CBDW_SC(_cbd, _sc) out_le32((volatile u32 *)&(_cbd)->sc, (_sc))
+#define CBDW_LEN(_cbd, _len) out_le32((volatile u32 *)&(_cbd)->len, (_len))
+#define CBDW_ADDR(_cbd, _addr) out_le32((volatile u32 *)&(_cbd)->addr, (_addr))
+
+#define CBDR_SC(_cbd) in_le32((volatile u32 *)&(_cbd)->sc)
+#define CBDR_LEN(_cbd) in_le32((volatile u32 *)&(_cbd)->len)
+#define CBDR_ADDR(_cbd) in_le32((volatile u32 *)&(_cbd)->addr)
+
+/* Buffer Descriptor Registers */
+#define PCINET_TXBD_BASE 0x400
+#define PCINET_RXBD_BASE 0x800
+
+/* Buffer Descriptor Status */
+#define BD_MEM_READY 0x1
+#define BD_MEM_DIRTY 0x2
+#define BD_MEM_FREE 0x3
+
+#define PCINET_UART_RX_ENABLED (1<<0)
+#define PCINET_NET_STATUS_RUNNING (1<<1)
+#define PCINET_NET_RXINT_OFF (1<<2)
+#define PCINET_NET_REGISTERS_VALID (1<<3)
+
+/* Driver State Bits */
+#define NET_STATE_STOPPED 0
+#define NET_STATE_RUNNING 1
+
+/* Doorbell Registers */
+#define UART_RX_READY_DBELL (1<<0)
+#define UART_TX_EMPTY_DBELL (1<<1)
+#define NET_RX_PACKET_DBELL (1<<2)
+#define NET_TX_COMPLETE_DBELL (1<<3)
+#define NET_START_REQ_DBELL (1<<4)
+#define NET_START_ACK_DBELL (1<<5)
+#define NET_STOP_REQ_DBELL (1<<6)
+#define NET_STOP_ACK_DBELL (1<<7)
+
+#endif /* PCINET_H */
+
+/* vim: set ts=8 sts=8 sw=8 noet tw=92: */
--
1.5.4.3
>From 343a1511912ddd998c25f549a8ae67522601e762 Mon Sep 17 00:00:00 2001
From: Ira W. Snyder
Date: Mon, 18 Aug 2008 10:56:33 -0700
Subject: [PATCH] Add PCISerial Driver
This adds a very simple driver which emulates a serial port over the PCI
bus. This is extremely useful for boards in PCISLAVE mode, so you do not
need extra cables to communicate with them.
There is a corresponding Linux driver.
Signed-off-by: Ira W. Snyder
---
drivers/serial/Makefile | 3 +-
drivers/serial/pciserial.c | 230 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 232 insertions(+), 1 deletions(-)
create mode 100644 drivers/serial/pciserial.c
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index eafe543..652371d 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -31,13 +31,14 @@ COBJS-$(CONFIG_NS9750_UART) += ns9750_serial.o
COBJS-y += ns16550.o
COBJS-$(CONFIG_DRIVER_S3C4510_UART) += s3c4510b_uart.o
COBJS-$(CONFIG_S3C64XX) += s3c64xx.o
-COBJS-y += serial.o
+COBJS-$(CFG_NS16550_SERIAL) += serial.o
COBJS-$(CONFIG_MAX3100_SERIAL) += serial_max3100.o
COBJS-$(CONFIG_PL010_SERIAL) += serial_pl01x.o
COBJS-$(CONFIG_PL011_SERIAL) += serial_pl01x.o
COBJS-$(CONFIG_XILINX_UARTLITE) += serial_xuartlite.o
COBJS-$(CONFIG_SCIF_CONSOLE) += serial_sh.o
COBJS-$(CONFIG_USB_TTY) += usbtty.o
+COBJS-$(CONFIG_PCISERIAL) += pciserial.o
COBJS := $(sort $(COBJS-y))
SRCS := $(COBJS:.o=.c)
diff --git a/drivers/serial/pciserial.c b/drivers/serial/pciserial.c
new file mode 100644
index 0000000..ae5b8c4
--- /dev/null
+++ b/drivers/serial/pciserial.c
@@ -0,0 +1,230 @@
+/*
+ * ONE-LINE DESCRIPTION
+ *
+ * Copyright (c) 2008 Ira W. Snyder
=== message truncated ===
_______________________________________________
U-Boot mailing list
[email protected]
http://lists.denx.de/mailman/listinfo/u-boot