summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/block/ata_piix.c455
-rw-r--r--drivers/block/ata_piix.h46
-rw-r--r--drivers/block/dwc_ahsata.c9
-rw-r--r--drivers/block/dwc_ahsata.h2
-rw-r--r--drivers/block/fsl_sata.c13
-rw-r--r--drivers/block/pata_bfin.c5
-rw-r--r--drivers/block/pata_bfin.h2
-rw-r--r--drivers/block/sata_dwc.c5
-rw-r--r--drivers/block/sata_sil.c7
-rw-r--r--drivers/block/sata_sil.h2
-rw-r--r--drivers/block/sata_sil3114.c2
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/pca953x.c51
-rw-r--r--drivers/gpio/s3c2440_gpio.c95
-rw-r--r--drivers/gpio/tegra_gpio.c2
-rw-r--r--drivers/i2c/mxc_i2c.c4
-rw-r--r--drivers/i2c/sh_i2c.c16
-rw-r--r--drivers/i2c/tegra_i2c.c4
-rw-r--r--drivers/input/input.c13
-rw-r--r--drivers/input/key_matrix.c22
-rw-r--r--drivers/input/tegra-kbc.c9
-rw-r--r--drivers/mmc/tegra_mmc.c6
-rw-r--r--drivers/mtd/nand/atmel_nand.c5
-rw-r--r--drivers/mtd/nand/fsl_upm.c10
-rw-r--r--drivers/mtd/nand/tegra_nand.c6
-rw-r--r--drivers/mtd/spi/atmel.c17
-rw-r--r--drivers/net/davinci_emac.c3
-rw-r--r--drivers/net/e1000.c42
-rw-r--r--drivers/serial/Makefile5
-rw-r--r--drivers/serial/altera_jtag_uart.c41
-rw-r--r--drivers/serial/altera_uart.c53
-rw-r--r--drivers/serial/atmel_usart.c35
-rw-r--r--drivers/serial/lpc32xx_hsuart.c57
-rw-r--r--drivers/serial/mcfuart.c33
-rw-r--r--drivers/serial/ns16550.c2
-rw-r--r--drivers/serial/ns9750_serial.c33
-rw-r--r--drivers/serial/opencores_yanu.c35
-rw-r--r--drivers/serial/s3c4510b_uart.c33
-rw-r--r--drivers/serial/s3c64xx.c33
-rw-r--r--drivers/serial/sandbox.c35
-rw-r--r--drivers/serial/serial.c552
-rw-r--r--drivers/serial/serial_clps7111.c34
-rw-r--r--drivers/serial/serial_imx.c36
-rw-r--r--drivers/serial/serial_ixp.c36
-rw-r--r--drivers/serial/serial_ks8695.c41
-rw-r--r--drivers/serial/serial_lh7a40x.c34
-rw-r--r--drivers/serial/serial_lpc2292.c34
-rw-r--r--drivers/serial/serial_max3100.c42
-rw-r--r--drivers/serial/serial_mxc.c40
-rw-r--r--drivers/serial/serial_netarm.c33
-rw-r--r--drivers/serial/serial_ns16550.c264
-rw-r--r--drivers/serial/serial_pl01x.c37
-rw-r--r--drivers/serial/serial_pxa.c65
-rw-r--r--drivers/serial/serial_s3c24x0.c78
-rw-r--r--drivers/serial/serial_s3c44b0.c36
-rw-r--r--drivers/serial/serial_s5p.c27
-rw-r--r--drivers/serial/serial_sa1100.c36
-rw-r--r--drivers/serial/serial_sh.c35
-rw-r--r--drivers/serial/serial_xuartlite.c69
-rw-r--r--drivers/serial/serial_zynq.c225
-rw-r--r--drivers/spi/tegra_spi.c7
-rw-r--r--drivers/usb/eth/usb_ether.c2
-rw-r--r--drivers/usb/gadget/Makefile1
-rw-r--r--drivers/usb/gadget/ether.c69
-rw-r--r--drivers/usb/gadget/pxa25x_udc.c2059
-rw-r--r--drivers/usb/gadget/pxa25x_udc.h162
-rw-r--r--drivers/usb/host/ehci-armada100.c15
-rw-r--r--drivers/usb/host/ehci-atmel.c11
-rw-r--r--drivers/usb/host/ehci-core.h29
-rw-r--r--drivers/usb/host/ehci-exynos.c15
-rw-r--r--drivers/usb/host/ehci-fsl.c15
-rw-r--r--drivers/usb/host/ehci-hcd.c126
-rw-r--r--drivers/usb/host/ehci-ixp4xx.c15
-rw-r--r--drivers/usb/host/ehci-marvell.c15
-rw-r--r--drivers/usb/host/ehci-mpc512x.c25
-rw-r--r--drivers/usb/host/ehci-mx5.c14
-rw-r--r--drivers/usb/host/ehci-mx6.c11
-rw-r--r--drivers/usb/host/ehci-mxc.c11
-rw-r--r--drivers/usb/host/ehci-mxs.c20
-rw-r--r--drivers/usb/host/ehci-omap.c10
-rw-r--r--drivers/usb/host/ehci-pci.c15
-rw-r--r--drivers/usb/host/ehci-ppc4xx.c11
-rw-r--r--drivers/usb/host/ehci-tegra.c14
-rw-r--r--drivers/usb/host/ehci-vct.c9
-rw-r--r--drivers/usb/host/ehci.h4
-rw-r--r--drivers/usb/host/isp116x-hcd.c4
-rw-r--r--drivers/usb/host/ohci-hcd.c4
-rw-r--r--drivers/usb/host/r8a66597-hcd.c4
-rw-r--r--drivers/usb/host/sl811-hcd.c4
-rw-r--r--drivers/usb/musb/musb_hcd.c4
-rw-r--r--drivers/usb/ulpi/ulpi.c32
-rw-r--r--drivers/video/cfb_console.c140
-rw-r--r--drivers/video/ipu_common.c12
-rw-r--r--drivers/video/mxc_ipuv3_fb.c20
94 files changed, 4616 insertions, 1296 deletions
diff --git a/drivers/block/ata_piix.c b/drivers/block/ata_piix.c
index 1c3ab8a733..1e33a66c45 100644
--- a/drivers/block/ata_piix.c
+++ b/drivers/block/ata_piix.c
@@ -34,17 +34,15 @@
#include <part.h>
#include <ide.h>
#include <ata.h>
+#include <sata.h>
-extern block_dev_desc_t sata_dev_desc[CONFIG_SYS_SATA_MAX_DEVICE];
-extern int sata_curr_device;
-
-#define DEBUG_SATA 0 /*For debug prints set DEBUG_SATA to 1 */
+#define DEBUG_SATA 0 /* For debug prints set DEBUG_SATA to 1 */
#define SATA_DECL
-#define DRV_DECL /*For file specific declarations */
+#define DRV_DECL /* For file specific declarations */
#include "ata_piix.h"
-/*Macros realted to PCI*/
+/* Macros realted to PCI */
#define PCI_SATA_BUS 0x00
#define PCI_SATA_DEV 0x1f
#define PCI_SATA_FUNC 0x02
@@ -63,35 +61,36 @@ extern int sata_curr_device;
#define PORT_ENABLED (1<<4)
u32 bdf;
-u32 iobase1 = 0; /*Primary cmd block */
-u32 iobase2 = 0; /*Primary ctl block */
-u32 iobase3 = 0; /*Sec cmd block */
-u32 iobase4 = 0; /*sec ctl block */
-u32 iobase5 = 0; /*BMDMA*/
-int
-pci_sata_init (void)
+u32 iobase1; /* Primary cmd block */
+u32 iobase2; /* Primary ctl block */
+u32 iobase3; /* Sec cmd block */
+u32 iobase4; /* sec ctl block */
+u32 iobase5; /* BMDMA*/
+
+int pci_sata_init(void)
{
u32 bus = PCI_SATA_BUS;
u32 dev = PCI_SATA_DEV;
u32 fun = PCI_SATA_FUNC;
u16 cmd = 0;
u8 lat = 0, pcibios_max_latency = 0xff;
- u8 pmr; /*Port mapping reg */
- u8 pi; /*Prgming Interface reg */
+ u8 pmr; /* Port mapping reg */
+ u8 pi; /* Prgming Interface reg */
- bdf = PCI_BDF (bus, dev, fun);
- pci_read_config_dword (bdf, PCI_SATA_BASE1, &iobase1);
- pci_read_config_dword (bdf, PCI_SATA_BASE2, &iobase2);
- pci_read_config_dword (bdf, PCI_SATA_BASE3, &iobase3);
- pci_read_config_dword (bdf, PCI_SATA_BASE4, &iobase4);
- pci_read_config_dword (bdf, PCI_SATA_BASE5, &iobase5);
+ bdf = PCI_BDF(bus, dev, fun);
+ pci_read_config_dword(bdf, PCI_SATA_BASE1, &iobase1);
+ pci_read_config_dword(bdf, PCI_SATA_BASE2, &iobase2);
+ pci_read_config_dword(bdf, PCI_SATA_BASE3, &iobase3);
+ pci_read_config_dword(bdf, PCI_SATA_BASE4, &iobase4);
+ pci_read_config_dword(bdf, PCI_SATA_BASE5, &iobase5);
if ((iobase1 == 0xFFFFFFFF) || (iobase2 == 0xFFFFFFFF) ||
(iobase3 == 0xFFFFFFFF) || (iobase4 == 0xFFFFFFFF) ||
(iobase5 == 0xFFFFFFFF)) {
- printf ("error no base addr for SATA controller\n");
+ /* ERROR */
+ printf("error no base addr for SATA controller\n");
return 1;
- /*ERROR*/}
+ }
iobase1 &= 0xFFFFFFFE;
iobase2 &= 0xFFFFFFFE;
@@ -99,44 +98,42 @@ pci_sata_init (void)
iobase4 &= 0xFFFFFFFE;
iobase5 &= 0xFFFFFFFE;
- /*check for mode */
- pci_read_config_byte (bdf, PCI_PMR, &pmr);
+ /* check for mode */
+ pci_read_config_byte(bdf, PCI_PMR, &pmr);
if (pmr > 1) {
- printf ("combined mode not supported\n");
+ puts("combined mode not supported\n");
return 1;
}
- pci_read_config_byte (bdf, PCI_PI, &pi);
+ pci_read_config_byte(bdf, PCI_PI, &pi);
if ((pi & 0x05) != 0x05) {
- printf ("Sata is in Legacy mode\n");
+ puts("Sata is in Legacy mode\n");
return 1;
- } else {
- printf ("sata is in Native mode\n");
- }
+ } else
+ puts("sata is in Native mode\n");
- /*MASTER CFG AND IO CFG */
- pci_read_config_word (bdf, PCI_COMMAND, &cmd);
+ /* MASTER CFG AND IO CFG */
+ pci_read_config_word(bdf, PCI_COMMAND, &cmd);
cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_IO;
- pci_write_config_word (bdf, PCI_COMMAND, cmd);
- pci_read_config_byte (dev, PCI_LATENCY_TIMER, &lat);
+ pci_write_config_word(bdf, PCI_COMMAND, cmd);
+ pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
if (lat < 16)
lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency;
else if (lat > pcibios_max_latency)
lat = pcibios_max_latency;
- pci_write_config_byte (dev, PCI_LATENCY_TIMER, lat);
+ pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
return 0;
}
-int
-sata_bus_probe (int port_no)
+int sata_bus_probe(int port_no)
{
int orig_mask, mask;
u16 pcs;
mask = (PORT_PRESENT << port_no);
- pci_read_config_word (bdf, PCI_PCS, &pcs);
+ pci_read_config_word(bdf, PCI_PCS, &pcs);
orig_mask = (int) pcs & 0xff;
if ((orig_mask & mask) != mask)
return 0;
@@ -144,10 +141,9 @@ sata_bus_probe (int port_no)
return 1;
}
-int
-init_sata (int dev)
+int init_sata(int dev)
{
- static int done = 0;
+ static int done;
u8 i, rv = 0;
if (!done)
@@ -155,9 +151,9 @@ init_sata (int dev)
else
return 0;
- rv = pci_sata_init ();
+ rv = pci_sata_init();
if (rv == 1) {
- printf ("pci initialization failed\n");
+ puts("pci initialization failed\n");
return 1;
}
@@ -174,19 +170,18 @@ init_sata (int dev)
port[1].ioaddr.bmdma_addr = iobase5 + 0x8;
for (i = 0; i < CONFIG_SYS_SATA_MAXBUS; i++)
- sata_port (&port[i].ioaddr);
+ sata_port(&port[i].ioaddr);
for (i = 0; i < CONFIG_SYS_SATA_MAXBUS; i++) {
- if (!(sata_bus_probe (i))) {
+ if (!(sata_bus_probe(i))) {
port[i].port_state = 0;
- printf ("SATA#%d port is not present \n", i);
+ printf("SATA#%d port is not present\n", i);
} else {
- printf ("SATA#%d port is present\n", i);
- if (sata_bus_softreset (i)) {
+ printf("SATA#%d port is present\n", i);
+ if (sata_bus_softreset(i))
port[i].port_state = 0;
- } else {
+ else
port[i].port_state = 1;
- }
}
}
@@ -196,47 +191,43 @@ init_sata (int dev)
if (port[i].port_state == 0)
continue;
for (j = 0; j < CONFIG_SYS_SATA_DEVS_PER_BUS; j++) {
- sata_identify (i, j);
- set_Feature_cmd (i, j);
+ sata_identify(i, j);
+ set_Feature_cmd(i, j);
devno = i * CONFIG_SYS_SATA_DEVS_PER_BUS + j;
if ((sata_dev_desc[devno].lba > 0) &&
(sata_dev_desc[devno].blksz > 0)) {
- dev_print (&sata_dev_desc[devno]);
+ dev_print(&sata_dev_desc[devno]);
/* initialize partition type */
- init_part (&sata_dev_desc[devno]);
+ init_part(&sata_dev_desc[devno]);
}
}
}
return 0;
}
-static u8 __inline__
-sata_inb (unsigned long ioaddr)
+static inline u8 sata_inb(unsigned long ioaddr)
{
- return inb (ioaddr);
+ return inb(ioaddr);
}
-static void __inline__
-sata_outb (unsigned char val, unsigned long ioaddr)
+static inline void sata_outb(unsigned char val, unsigned long ioaddr)
{
- outb (val, ioaddr);
+ outb(val, ioaddr);
}
-static void
-output_data (struct sata_ioports *ioaddr, ulong * sect_buf, int words)
+static void output_data(struct sata_ioports *ioaddr, ulong * sect_buf,
+ int words)
{
- outsw (ioaddr->data_addr, sect_buf, words << 1);
+ outsw(ioaddr->data_addr, sect_buf, words << 1);
}
-static int
-input_data (struct sata_ioports *ioaddr, ulong * sect_buf, int words)
+static int input_data(struct sata_ioports *ioaddr, ulong * sect_buf, int words)
{
- insw (ioaddr->data_addr, sect_buf, words << 1);
+ insw(ioaddr->data_addr, sect_buf, words << 1);
return 0;
}
-static void
-sata_cpy (unsigned char *dst, unsigned char *src, unsigned int len)
+static void sata_cpy(unsigned char *dst, unsigned char *src, unsigned int len)
{
unsigned char *end, *last;
@@ -257,41 +248,41 @@ sata_cpy (unsigned char *dst, unsigned char *src, unsigned int len)
if (*src++ != ' ')
last = dst;
}
- OUT:
+OUT:
*last = '\0';
}
-int
-sata_bus_softreset (int num)
+int sata_bus_softreset(int num)
{
u8 dev = 0, status = 0, i;
port[num].dev_mask = 0;
for (i = 0; i < CONFIG_SYS_SATA_DEVS_PER_BUS; i++) {
- if (!(sata_devchk (&port[num].ioaddr, i))) {
- PRINTF ("dev_chk failed for dev#%d\n", i);
+ if (!(sata_devchk(&port[num].ioaddr, i))) {
+ debug("dev_chk failed for dev#%d\n", i);
} else {
port[num].dev_mask |= (1 << i);
- PRINTF ("dev_chk passed for dev#%d\n", i);
+ debug("dev_chk passed for dev#%d\n", i);
}
}
if (!(port[num].dev_mask)) {
- printf ("no devices on port%d\n", num);
+ printf("no devices on port%d\n", num);
return 1;
}
- dev_select (&port[num].ioaddr, dev);
+ dev_select(&port[num].ioaddr, dev);
- port[num].ctl_reg = 0x08; /*Default value of control reg */
- sata_outb (port[num].ctl_reg, port[num].ioaddr.ctl_addr);
- udelay (10);
- sata_outb (port[num].ctl_reg | ATA_SRST, port[num].ioaddr.ctl_addr);
- udelay (10);
- sata_outb (port[num].ctl_reg, port[num].ioaddr.ctl_addr);
+ port[num].ctl_reg = 0x08; /* Default value of control reg */
+ sata_outb(port[num].ctl_reg, port[num].ioaddr.ctl_addr);
+ udelay(10);
+ sata_outb(port[num].ctl_reg | ATA_SRST, port[num].ioaddr.ctl_addr);
+ udelay(10);
+ sata_outb(port[num].ctl_reg, port[num].ioaddr.ctl_addr);
- /* spec mandates ">= 2ms" before checking status.
+ /*
+ * spec mandates ">= 2ms" before checking status.
* We wait 150ms, because that was the magic delay used for
* ATAPI devices in Hale Landis's ATADRVR, for the period of time
* between when the ATA command register is written, and then
@@ -299,38 +290,37 @@ sata_bus_softreset (int num)
* checking status is fine, post SRST, we perform this magic
* delay here as well.
*/
- msleep (150);
- status = sata_busy_wait (&port[num].ioaddr, ATA_BUSY, 300);
+ mdelay(150);
+ status = sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 300);
while ((status & ATA_BUSY)) {
- msleep (100);
- status = sata_busy_wait (&port[num].ioaddr, ATA_BUSY, 3);
+ mdelay(100);
+ status = sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 3);
}
if (status & ATA_BUSY)
- printf ("ata%u is slow to respond,plz be patient\n", num);
+ printf("ata%u is slow to respond,plz be patient\n", num);
while ((status & ATA_BUSY)) {
- msleep (100);
- status = sata_chk_status (&port[num].ioaddr);
+ mdelay(100);
+ status = sata_chk_status(&port[num].ioaddr);
}
if (status & ATA_BUSY) {
- printf ("ata%u failed to respond : ", num);
- printf ("bus reset failed\n");
+ printf("ata%u failed to respond : bus reset failed\n", num);
return 1;
}
return 0;
}
-void
-sata_identify (int num, int dev)
+void sata_identify(int num, int dev)
{
- u8 cmd = 0, status = 0, devno = num * CONFIG_SYS_SATA_DEVS_PER_BUS + dev;
+ u8 cmd = 0, status = 0;
+ u8 devno = num * CONFIG_SYS_SATA_DEVS_PER_BUS + dev;
u16 iobuf[ATA_SECT_SIZE];
u64 n_sectors = 0;
u8 mask = 0;
- memset (iobuf, 0, sizeof (iobuf));
+ memset(iobuf, 0, sizeof(iobuf));
hd_driveid_t *iop = (hd_driveid_t *) iobuf;
if (dev == 0)
@@ -339,70 +329,67 @@ sata_identify (int num, int dev)
mask = 0x02;
if (!(port[num].dev_mask & mask)) {
- printf ("dev%d is not present on port#%d\n", dev, num);
+ printf("dev%d is not present on port#%d\n", dev, num);
return;
}
- printf ("port=%d dev=%d\n", num, dev);
+ printf("port=%d dev=%d\n", num, dev);
- dev_select (&port[num].ioaddr, dev);
+ dev_select(&port[num].ioaddr, dev);
status = 0;
- cmd = ATA_CMD_IDENT; /*Device Identify Command */
- sata_outb (cmd, port[num].ioaddr.command_addr);
- sata_inb (port[num].ioaddr.altstatus_addr);
- udelay (10);
+ cmd = ATA_CMD_IDENT; /* Device Identify Command */
+ sata_outb(cmd, port[num].ioaddr.command_addr);
+ sata_inb(port[num].ioaddr.altstatus_addr);
+ udelay(10);
- status = sata_busy_wait (&port[num].ioaddr, ATA_BUSY, 1000);
+ status = sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 1000);
if (status & ATA_ERR) {
- printf ("\ndevice not responding\n");
+ puts("\ndevice not responding\n");
port[num].dev_mask &= ~mask;
return;
}
- input_data (&port[num].ioaddr, (ulong *) iobuf, ATA_SECTORWORDS);
+ input_data(&port[num].ioaddr, (ulong *) iobuf, ATA_SECTORWORDS);
- PRINTF ("\nata%u: dev %u cfg 49:%04x 82:%04x 83:%04x 84:%04x85:%04x"
+ debug("\nata%u: dev %u cfg 49:%04x 82:%04x 83:%04x 84:%04x85:%04x"
"86:%04x" "87:%04x 88:%04x\n", num, dev, iobuf[49],
iobuf[82], iobuf[83], iobuf[84], iobuf[85], iobuf[86],
iobuf[87], iobuf[88]);
/* we require LBA and DMA support (bits 8 & 9 of word 49) */
- if (!ata_id_has_dma (iobuf) || !ata_id_has_lba (iobuf)) {
- PRINTF ("ata%u: no dma/lba\n", num);
- }
- ata_dump_id (iobuf);
+ if (!ata_id_has_dma(iobuf) || !ata_id_has_lba(iobuf))
+ debug("ata%u: no dma/lba\n", num);
+ ata_dump_id(iobuf);
- if (ata_id_has_lba48 (iobuf)) {
- n_sectors = ata_id_u64 (iobuf, 100);
- } else {
- n_sectors = ata_id_u32 (iobuf, 60);
- }
- PRINTF ("no. of sectors %u\n", ata_id_u64 (iobuf, 100));
- PRINTF ("no. of sectors %u\n", ata_id_u32 (iobuf, 60));
+ if (ata_id_has_lba48(iobuf))
+ n_sectors = ata_id_u64(iobuf, 100);
+ else
+ n_sectors = ata_id_u32(iobuf, 60);
+ debug("no. of sectors %u\n", ata_id_u64(iobuf, 100));
+ debug("no. of sectors %u\n", ata_id_u32(iobuf, 60));
if (n_sectors == 0) {
port[num].dev_mask &= ~mask;
return;
}
- sata_cpy ((unsigned char *)sata_dev_desc[devno].revision, iop->fw_rev,
- sizeof (sata_dev_desc[devno].revision));
- sata_cpy ((unsigned char *)sata_dev_desc[devno].vendor, iop->model,
- sizeof (sata_dev_desc[devno].vendor));
- sata_cpy ((unsigned char *)sata_dev_desc[devno].product, iop->serial_no,
- sizeof (sata_dev_desc[devno].product));
- strswab (sata_dev_desc[devno].revision);
- strswab (sata_dev_desc[devno].vendor);
+ sata_cpy((unsigned char *)sata_dev_desc[devno].revision, iop->fw_rev,
+ sizeof(sata_dev_desc[devno].revision));
+ sata_cpy((unsigned char *)sata_dev_desc[devno].vendor, iop->model,
+ sizeof(sata_dev_desc[devno].vendor));
+ sata_cpy((unsigned char *)sata_dev_desc[devno].product, iop->serial_no,
+ sizeof(sata_dev_desc[devno].product));
+ strswab(sata_dev_desc[devno].revision);
+ strswab(sata_dev_desc[devno].vendor);
- if ((iop->config & 0x0080) == 0x0080) {
+ if ((iop->config & 0x0080) == 0x0080)
sata_dev_desc[devno].removable = 1;
- } else {
+ else
sata_dev_desc[devno].removable = 0;
- }
sata_dev_desc[devno].lba = iop->lba_capacity;
- PRINTF ("lba=0x%x", sata_dev_desc[devno].lba);
+ debug("lba=0x%x", sata_dev_desc[devno].lba);
#ifdef CONFIG_LBA48
if (iop->command_set_2 & 0x0400) {
@@ -422,8 +409,7 @@ sata_identify (int num, int dev)
sata_dev_desc[devno].lun = 0; /* just to fill something in... */
}
-void
-set_Feature_cmd (int num, int dev)
+void set_Feature_cmd(int num, int dev)
{
u8 mask = 0x00, status = 0;
@@ -433,33 +419,32 @@ set_Feature_cmd (int num, int dev)
mask = 0x02;
if (!(port[num].dev_mask & mask)) {
- PRINTF ("dev%d is not present on port#%d\n", dev, num);
+ debug("dev%d is not present on port#%d\n", dev, num);
return;
}
- dev_select (&port[num].ioaddr, dev);
+ dev_select(&port[num].ioaddr, dev);
- sata_outb (SETFEATURES_XFER, port[num].ioaddr.feature_addr);
- sata_outb (XFER_PIO_4, port[num].ioaddr.nsect_addr);
- sata_outb (0, port[num].ioaddr.lbal_addr);
- sata_outb (0, port[num].ioaddr.lbam_addr);
- sata_outb (0, port[num].ioaddr.lbah_addr);
+ sata_outb(SETFEATURES_XFER, port[num].ioaddr.feature_addr);
+ sata_outb(XFER_PIO_4, port[num].ioaddr.nsect_addr);
+ sata_outb(0, port[num].ioaddr.lbal_addr);
+ sata_outb(0, port[num].ioaddr.lbam_addr);
+ sata_outb(0, port[num].ioaddr.lbah_addr);
- sata_outb (ATA_DEVICE_OBS, port[num].ioaddr.device_addr);
- sata_outb (ATA_CMD_SETF, port[num].ioaddr.command_addr);
+ sata_outb(ATA_DEVICE_OBS, port[num].ioaddr.device_addr);
+ sata_outb(ATA_CMD_SETF, port[num].ioaddr.command_addr);
- udelay (50);
- msleep (150);
+ udelay(50);
+ mdelay(150);
- status = sata_busy_wait (&port[num].ioaddr, ATA_BUSY, 5000);
+ status = sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 5000);
if ((status & (ATA_STAT_BUSY | ATA_STAT_ERR))) {
- printf ("Error : status 0x%02x\n", status);
+ printf("Error : status 0x%02x\n", status);
port[num].dev_mask &= ~mask;
}
}
-void
-sata_port (struct sata_ioports *ioport)
+void sata_port(struct sata_ioports *ioport)
{
ioport->data_addr = ioport->cmd_addr + ATA_REG_DATA;
ioport->error_addr = ioport->cmd_addr + ATA_REG_ERR;
@@ -473,24 +458,23 @@ sata_port (struct sata_ioports *ioport)
ioport->command_addr = ioport->cmd_addr + ATA_REG_CMD;
}
-int
-sata_devchk (struct sata_ioports *ioaddr, int dev)
+int sata_devchk(struct sata_ioports *ioaddr, int dev)
{
u8 nsect, lbal;
- dev_select (ioaddr, dev);
+ dev_select(ioaddr, dev);
- sata_outb (0x55, ioaddr->nsect_addr);
- sata_outb (0xaa, ioaddr->lbal_addr);
+ sata_outb(0x55, ioaddr->nsect_addr);
+ sata_outb(0xaa, ioaddr->lbal_addr);
- sata_outb (0xaa, ioaddr->nsect_addr);
- sata_outb (0x55, ioaddr->lbal_addr);
+ sata_outb(0xaa, ioaddr->nsect_addr);
+ sata_outb(0x55, ioaddr->lbal_addr);
- sata_outb (0x55, ioaddr->nsect_addr);
- sata_outb (0xaa, ioaddr->lbal_addr);
+ sata_outb(0x55, ioaddr->nsect_addr);
+ sata_outb(0xaa, ioaddr->lbal_addr);
- nsect = sata_inb (ioaddr->nsect_addr);
- lbal = sata_inb (ioaddr->lbal_addr);
+ nsect = sata_inb(ioaddr->nsect_addr);
+ lbal = sata_inb(ioaddr->lbal_addr);
if ((nsect == 0x55) && (lbal == 0xaa))
return 1; /* we found a device */
@@ -498,8 +482,7 @@ sata_devchk (struct sata_ioports *ioaddr, int dev)
return 0; /* nothing found */
}
-void
-dev_select (struct sata_ioports *ioaddr, int dev)
+void dev_select(struct sata_ioports *ioaddr, int dev)
{
u8 tmp = 0;
@@ -508,42 +491,31 @@ dev_select (struct sata_ioports *ioaddr, int dev)
else
tmp = ATA_DEVICE_OBS | ATA_DEV1;
- sata_outb (tmp, ioaddr->device_addr);
- sata_inb (ioaddr->altstatus_addr);
- udelay (5);
+ sata_outb(tmp, ioaddr->device_addr);
+ sata_inb(ioaddr->altstatus_addr);
+ udelay(5);
}
-u8
-sata_busy_wait (struct sata_ioports *ioaddr, int bits, unsigned int max)
+u8 sata_busy_wait(struct sata_ioports *ioaddr, int bits, unsigned int max)
{
u8 status;
do {
- udelay (1000);
- status = sata_chk_status (ioaddr);
+ udelay(1000);
+ status = sata_chk_status(ioaddr);
max--;
} while ((status & bits) && (max > 0));
return status;
}
-u8
-sata_chk_status (struct sata_ioports * ioaddr)
+u8 sata_chk_status(struct sata_ioports *ioaddr)
{
- return sata_inb (ioaddr->status_addr);
+ return sata_inb(ioaddr->status_addr);
}
-void
-msleep (int count)
-{
- int i;
- for (i = 0; i < count; i++)
- udelay (1000);
-}
-
-ulong
-sata_read (int device, ulong blknr,lbaint_t blkcnt, void * buff)
+ulong sata_read(int device, ulong blknr, lbaint_t blkcnt, void *buff)
{
ulong n = 0, *buffer = (ulong *)buff;
u8 dev = 0, num = 0, mask = 0, status = 0;
@@ -553,16 +525,16 @@ sata_read (int device, ulong blknr,lbaint_t blkcnt, void * buff)
if (blknr & 0x0000fffff0000000) {
if (!sata_dev_desc[devno].lba48) {
- printf ("Drive doesn't support 48-bit addressing\n");
+ printf("Drive doesn't support 48-bit addressing\n");
return 0;
}
/* more than 28 bits used, use 48bit mode */
lba48 = 1;
}
#endif
- /*Port Number */
+ /* Port Number */
num = device / CONFIG_SYS_SATA_DEVS_PER_BUS;
- /*dev on the port */
+ /* dev on the port */
if (device >= CONFIG_SYS_SATA_DEVS_PER_BUS)
dev = device - CONFIG_SYS_SATA_DEVS_PER_BUS;
else
@@ -574,73 +546,73 @@ sata_read (int device, ulong blknr,lbaint_t blkcnt, void * buff)
mask = 0x02;
if (!(port[num].dev_mask & mask)) {
- printf ("dev%d is not present on port#%d\n", dev, num);
+ printf("dev%d is not present on port#%d\n", dev, num);
return 0;
}
/* Select device */
- dev_select (&port[num].ioaddr, dev);
+ dev_select(&port[num].ioaddr, dev);
- status = sata_busy_wait (&port[num].ioaddr, ATA_BUSY, 500);
+ status = sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 500);
if (status & ATA_BUSY) {
- printf ("ata%u failed to respond\n", port[num].port_no);
+ printf("ata%u failed to respond\n", port[num].port_no);
return n;
}
while (blkcnt-- > 0) {
- status = sata_busy_wait (&port[num].ioaddr, ATA_BUSY, 500);
+ status = sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 500);
if (status & ATA_BUSY) {
- printf ("ata%u failed to respond\n", 0);
+ printf("ata%u failed to respond\n", 0);
return n;
}
#ifdef CONFIG_LBA48
if (lba48) {
/* write high bits */
- sata_outb (0, port[num].ioaddr.nsect_addr);
- sata_outb ((blknr >> 24) & 0xFF,
+ sata_outb(0, port[num].ioaddr.nsect_addr);
+ sata_outb((blknr >> 24) & 0xFF,
port[num].ioaddr.lbal_addr);
- sata_outb ((blknr >> 32) & 0xFF,
+ sata_outb((blknr >> 32) & 0xFF,
port[num].ioaddr.lbam_addr);
- sata_outb ((blknr >> 40) & 0xFF,
+ sata_outb((blknr >> 40) & 0xFF,
port[num].ioaddr.lbah_addr);
}
#endif
- sata_outb (1, port[num].ioaddr.nsect_addr);
- sata_outb (((blknr) >> 0) & 0xFF,
+ sata_outb(1, port[num].ioaddr.nsect_addr);
+ sata_outb(((blknr) >> 0) & 0xFF,
port[num].ioaddr.lbal_addr);
- sata_outb ((blknr >> 8) & 0xFF, port[num].ioaddr.lbam_addr);
- sata_outb ((blknr >> 16) & 0xFF, port[num].ioaddr.lbah_addr);
+ sata_outb((blknr >> 8) & 0xFF, port[num].ioaddr.lbam_addr);
+ sata_outb((blknr >> 16) & 0xFF, port[num].ioaddr.lbah_addr);
#ifdef CONFIG_LBA48
if (lba48) {
- sata_outb (ATA_LBA, port[num].ioaddr.device_addr);
- sata_outb (ATA_CMD_READ_EXT,
+ sata_outb(ATA_LBA, port[num].ioaddr.device_addr);
+ sata_outb(ATA_CMD_READ_EXT,
port[num].ioaddr.command_addr);
} else
#endif
{
- sata_outb (ATA_LBA | ((blknr >> 24) & 0xF),
+ sata_outb(ATA_LBA | ((blknr >> 24) & 0xF),
port[num].ioaddr.device_addr);
- sata_outb (ATA_CMD_READ,
+ sata_outb(ATA_CMD_READ,
port[num].ioaddr.command_addr);
}
- msleep (50);
- /*may take up to 4 sec */
- status = sata_busy_wait (&port[num].ioaddr, ATA_BUSY, 4000);
+ mdelay(50);
+ /* may take up to 4 sec */
+ status = sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 4000);
if ((status & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR))
!= ATA_STAT_DRQ) {
u8 err = 0;
- printf ("Error no DRQ dev %d blk %ld: sts 0x%02x\n",
+ printf("Error no DRQ dev %d blk %ld: sts 0x%02x\n",
device, (ulong) blknr, status);
- err = sata_inb (port[num].ioaddr.error_addr);
- printf ("Error reg = 0x%x\n", err);
- return (n);
+ err = sata_inb(port[num].ioaddr.error_addr);
+ printf("Error reg = 0x%x\n", err);
+ return n;
}
- input_data (&port[num].ioaddr, buffer, ATA_SECTORWORDS);
- sata_inb (port[num].ioaddr.altstatus_addr);
- udelay (50);
+ input_data(&port[num].ioaddr, buffer, ATA_SECTORWORDS);
+ sata_inb(port[num].ioaddr.altstatus_addr);
+ udelay(50);
++n;
++blknr;
@@ -649,8 +621,7 @@ sata_read (int device, ulong blknr,lbaint_t blkcnt, void * buff)
return n;
}
-ulong
-sata_write (int device, ulong blknr,lbaint_t blkcnt, void * buff)
+ulong sata_write(int device, ulong blknr, lbaint_t blkcnt, const void *buff)
{
ulong n = 0, *buffer = (ulong *)buff;
unsigned char status = 0, num = 0, dev = 0, mask = 0;
@@ -660,16 +631,16 @@ sata_write (int device, ulong blknr,lbaint_t blkcnt, void * buff)
if (blknr & 0x0000fffff0000000) {
if (!sata_dev_desc[devno].lba48) {
- printf ("Drive doesn't support 48-bit addressing\n");
+ printf("Drive doesn't support 48-bit addressing\n");
return 0;
}
/* more than 28 bits used, use 48bit mode */
lba48 = 1;
}
#endif
- /*Port Number */
+ /* Port Number */
num = device / CONFIG_SYS_SATA_DEVS_PER_BUS;
- /*dev on the Port */
+ /* dev on the Port */
if (device >= CONFIG_SYS_SATA_DEVS_PER_BUS)
dev = device - CONFIG_SYS_SATA_DEVS_PER_BUS;
else
@@ -681,64 +652,64 @@ sata_write (int device, ulong blknr,lbaint_t blkcnt, void * buff)
mask = 0x02;
/* Select device */
- dev_select (&port[num].ioaddr, dev);
+ dev_select(&port[num].ioaddr, dev);
- status = sata_busy_wait (&port[num].ioaddr, ATA_BUSY, 500);
+ status = sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 500);
if (status & ATA_BUSY) {
- printf ("ata%u failed to respond\n", port[num].port_no);
+ printf("ata%u failed to respond\n", port[num].port_no);
return n;
}
while (blkcnt-- > 0) {
- status = sata_busy_wait (&port[num].ioaddr, ATA_BUSY, 500);
+ status = sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 500);
if (status & ATA_BUSY) {
- printf ("ata%u failed to respond\n",
+ printf("ata%u failed to respond\n",
port[num].port_no);
return n;
}
#ifdef CONFIG_LBA48
if (lba48) {
/* write high bits */
- sata_outb (0, port[num].ioaddr.nsect_addr);
- sata_outb ((blknr >> 24) & 0xFF,
+ sata_outb(0, port[num].ioaddr.nsect_addr);
+ sata_outb((blknr >> 24) & 0xFF,
port[num].ioaddr.lbal_addr);
- sata_outb ((blknr >> 32) & 0xFF,
+ sata_outb((blknr >> 32) & 0xFF,
port[num].ioaddr.lbam_addr);
- sata_outb ((blknr >> 40) & 0xFF,
+ sata_outb((blknr >> 40) & 0xFF,
port[num].ioaddr.lbah_addr);
}
#endif
- sata_outb (1, port[num].ioaddr.nsect_addr);
- sata_outb ((blknr >> 0) & 0xFF, port[num].ioaddr.lbal_addr);
- sata_outb ((blknr >> 8) & 0xFF, port[num].ioaddr.lbam_addr);
- sata_outb ((blknr >> 16) & 0xFF, port[num].ioaddr.lbah_addr);
+ sata_outb(1, port[num].ioaddr.nsect_addr);
+ sata_outb((blknr >> 0) & 0xFF, port[num].ioaddr.lbal_addr);
+ sata_outb((blknr >> 8) & 0xFF, port[num].ioaddr.lbam_addr);
+ sata_outb((blknr >> 16) & 0xFF, port[num].ioaddr.lbah_addr);
#ifdef CONFIG_LBA48
if (lba48) {
- sata_outb (ATA_LBA, port[num].ioaddr.device_addr);
- sata_outb (ATA_CMD_WRITE_EXT,
+ sata_outb(ATA_LBA, port[num].ioaddr.device_addr);
+ sata_outb(ATA_CMD_WRITE_EXT,
port[num].ioaddr.command_addr);
} else
#endif
{
- sata_outb (ATA_LBA | ((blknr >> 24) & 0xF),
+ sata_outb(ATA_LBA | ((blknr >> 24) & 0xF),
port[num].ioaddr.device_addr);
- sata_outb (ATA_CMD_WRITE,
+ sata_outb(ATA_CMD_WRITE,
port[num].ioaddr.command_addr);
}
- msleep (50);
- /*may take up to 4 sec */
- status = sata_busy_wait (&port[num].ioaddr, ATA_BUSY, 4000);
+ mdelay(50);
+ /* may take up to 4 sec */
+ status = sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 4000);
if ((status & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR))
!= ATA_STAT_DRQ) {
- printf ("Error no DRQ dev %d blk %ld: sts 0x%02x\n",
+ printf("Error no DRQ dev %d blk %ld: sts 0x%02x\n",
device, (ulong) blknr, status);
- return (n);
+ return n;
}
- output_data (&port[num].ioaddr, buffer, ATA_SECTORWORDS);
- sata_inb (port[num].ioaddr.altstatus_addr);
- udelay (50);
+ output_data(&port[num].ioaddr, buffer, ATA_SECTORWORDS);
+ sata_inb(port[num].ioaddr.altstatus_addr);
+ udelay(50);
++n;
++blknr;
diff --git a/drivers/block/ata_piix.h b/drivers/block/ata_piix.h
index 9157cf82c0..6c68ea2f01 100644
--- a/drivers/block/ata_piix.h
+++ b/drivers/block/ata_piix.h
@@ -1,12 +1,6 @@
#ifndef __ATA_PIIX_H__
#define __ATA_PIIX_H__
-#if (DEBUG_SATA)
-#define PRINTF(fmt,args...) printf (fmt ,##args)
-#else
-#define PRINTF(fmt,args...)
-#endif
-
struct sata_ioports {
unsigned long cmd_addr;
unsigned long data_addr;
@@ -36,45 +30,41 @@ struct sata_port {
};
/***********SATA LIBRARY SPECIFIC DEFINITIONS AND DECLARATIONS**************/
-#ifdef SATA_DECL /*SATA library specific declarations */
-inline void
-ata_dump_id (u16 * id)
+#ifdef SATA_DECL /* SATA library specific declarations */
+inline void ata_dump_id(u16 *id)
{
- PRINTF ("49 = 0x%04x "
+ debug("49 = 0x%04x "
"53 = 0x%04x "
"63 = 0x%04x "
"64 = 0x%04x "
- "75 = 0x%04x \n", id[49], id[53], id[63], id[64], id[75]);
- PRINTF ("80 = 0x%04x "
+ "75 = 0x%04x\n", id[49], id[53], id[63], id[64], id[75]);
+ debug("80 = 0x%04x "
"81 = 0x%04x "
"82 = 0x%04x "
"83 = 0x%04x "
- "84 = 0x%04x \n", id[80], id[81], id[82], id[83], id[84]);
- PRINTF ("88 = 0x%04x " "93 = 0x%04x\n", id[88], id[93]);
+ "84 = 0x%04x\n", id[80], id[81], id[82], id[83], id[84]);
+ debug("88 = 0x%04x " "93 = 0x%04x\n", id[88], id[93]);
}
#endif
#ifdef SATA_DECL /*SATA library specific declarations */
-int sata_bus_softreset (int num);
-void sata_identify (int num, int dev);
-void sata_port (struct sata_ioports *ioport);
-void set_Feature_cmd (int num, int dev);
-int sata_devchk (struct sata_ioports *ioaddr, int dev);
-void dev_select (struct sata_ioports *ioaddr, int dev);
-u8 sata_busy_wait (struct sata_ioports *ioaddr, int bits, unsigned int max);
-u8 sata_chk_status (struct sata_ioports *ioaddr);
-ulong sata_read (int device, ulong blknr,lbaint_t blkcnt, void * buffer);
-ulong sata_write (int device,ulong blknr, lbaint_t blkcnt, void * buffer);
-void msleep (int count);
+int sata_bus_softreset(int num);
+void sata_identify(int num, int dev);
+void sata_port(struct sata_ioports *ioport);
+void set_Feature_cmd(int num, int dev);
+int sata_devchk(struct sata_ioports *ioaddr, int dev);
+void dev_select(struct sata_ioports *ioaddr, int dev);
+u8 sata_busy_wait(struct sata_ioports *ioaddr, int bits, unsigned int max);
+u8 sata_chk_status(struct sata_ioports *ioaddr);
#endif
/************DRIVER SPECIFIC DEFINITIONS AND DECLARATIONS**************/
-#ifdef DRV_DECL /*Driver specific declaration */
-int init_sata (int dev);
+#ifdef DRV_DECL /* Driver specific declaration */
+int init_sata(int dev);
#endif
-#ifdef DRV_DECL /*Defines Driver Specific variables */
+#ifdef DRV_DECL /* Defines Driver Specific variables */
struct sata_port port[CONFIG_SYS_SATA_MAXBUS];
#endif
diff --git a/drivers/block/dwc_ahsata.c b/drivers/block/dwc_ahsata.c
index 2703d3dc84..c9b71f7e1f 100644
--- a/drivers/block/dwc_ahsata.c
+++ b/drivers/block/dwc_ahsata.c
@@ -24,6 +24,7 @@
#include <libata.h>
#include <ahci.h>
#include <fis.h>
+#include <sata.h>
#include <common.h>
#include <malloc.h>
@@ -794,7 +795,7 @@ static void dwc_ahsata_init_wcache(int dev, u16 *id)
}
u32 ata_low_level_rw_lba48(int dev, u32 blknr, lbaint_t blkcnt,
- void *buffer, int is_write)
+ const void *buffer, int is_write)
{
u32 start, blks;
u8 *addr;
@@ -828,7 +829,7 @@ u32 ata_low_level_rw_lba48(int dev, u32 blknr, lbaint_t blkcnt,
}
u32 ata_low_level_rw_lba28(int dev, u32 blknr, lbaint_t blkcnt,
- void *buffer, int is_write)
+ const void *buffer, int is_write)
{
u32 start, blks;
u8 *addr;
@@ -863,7 +864,7 @@ u32 ata_low_level_rw_lba28(int dev, u32 blknr, lbaint_t blkcnt,
/*
* SATA interface between low level driver and command layer
*/
-ulong sata_read(int dev, unsigned long blknr, lbaint_t blkcnt, void *buffer)
+ulong sata_read(int dev, ulong blknr, lbaint_t blkcnt, void *buffer)
{
u32 rc;
@@ -876,7 +877,7 @@ ulong sata_read(int dev, unsigned long blknr, lbaint_t blkcnt, void *buffer)
return rc;
}
-ulong sata_write(int dev, unsigned long blknr, lbaint_t blkcnt, void *buffer)
+ulong sata_write(int dev, ulong blknr, lbaint_t blkcnt, const void *buffer)
{
u32 rc;
struct ahci_probe_ent *probe_ent =
diff --git a/drivers/block/dwc_ahsata.h b/drivers/block/dwc_ahsata.h
index 84860ea492..4dac5dcae2 100644
--- a/drivers/block/dwc_ahsata.h
+++ b/drivers/block/dwc_ahsata.h
@@ -330,6 +330,4 @@
#define READ_CMD 0
#define WRITE_CMD 1
-extern block_dev_desc_t sata_dev_desc[CONFIG_SYS_SATA_MAX_DEVICE];
-
#endif /* __FSL_SATA_H__ */
diff --git a/drivers/block/fsl_sata.c b/drivers/block/fsl_sata.c
index 3026adec0d..fda3389e8b 100644
--- a/drivers/block/fsl_sata.c
+++ b/drivers/block/fsl_sata.c
@@ -26,10 +26,9 @@
#include <malloc.h>
#include <libata.h>
#include <fis.h>
+#include <sata.h>
#include "fsl_sata.h"
-extern block_dev_desc_t sata_dev_desc[CONFIG_SYS_SATA_MAX_DEVICE];
-
#ifndef CONFIG_SYS_SATA1_FLAGS
#define CONFIG_SYS_SATA1_FLAGS FLAGS_DMA
#endif
@@ -758,7 +757,8 @@ static int fsl_sata_get_flush_ext(int dev)
return sata->flush_ext;
}
-u32 ata_low_level_rw_lba48(int dev, u32 blknr, u32 blkcnt, void *buffer, int is_write)
+u32 ata_low_level_rw_lba48(int dev, u32 blknr, lbaint_t blkcnt,
+ const void *buffer, int is_write)
{
u32 start, blks;
u8 *addr;
@@ -792,7 +792,8 @@ u32 ata_low_level_rw_lba48(int dev, u32 blknr, u32 blkcnt, void *buffer, int is_
return blkcnt;
}
-u32 ata_low_level_rw_lba28(int dev, u32 blknr, u32 blkcnt, void *buffer, int is_write)
+u32 ata_low_level_rw_lba28(int dev, u32 blknr, u32 blkcnt, const void *buffer,
+ int is_write)
{
u32 start, blks;
u8 *addr;
@@ -823,7 +824,7 @@ u32 ata_low_level_rw_lba28(int dev, u32 blknr, u32 blkcnt, void *buffer, int is_
/*
* SATA interface between low level driver and command layer
*/
-ulong sata_read(int dev, u32 blknr, u32 blkcnt, void *buffer)
+ulong sata_read(int dev, ulong blknr, lbaint_t blkcnt, void *buffer)
{
u32 rc;
fsl_sata_t *sata = (fsl_sata_t *)sata_dev_desc[dev].priv;
@@ -835,7 +836,7 @@ ulong sata_read(int dev, u32 blknr, u32 blkcnt, void *buffer)
return rc;
}
-ulong sata_write(int dev, u32 blknr, u32 blkcnt, void *buffer)
+ulong sata_write(int dev, ulong blknr, lbaint_t blkcnt, const void *buffer)
{
u32 rc;
fsl_sata_t *sata = (fsl_sata_t *)sata_dev_desc[dev].priv;
diff --git a/drivers/block/pata_bfin.c b/drivers/block/pata_bfin.c
index cce21fbc54..b847dd91e7 100644
--- a/drivers/block/pata_bfin.c
+++ b/drivers/block/pata_bfin.c
@@ -17,6 +17,7 @@
#include <asm/portmux.h>
#include <asm/mach-common/bits/pata.h>
#include <ata.h>
+#include <sata.h>
#include <libata.h>
#include "pata_bfin.h"
@@ -1079,7 +1080,7 @@ static u8 do_one_read(struct ata_port *ap, u64 blknr, u8 blkcnt, u16 *buffer,
return sr;
}
-ulong sata_read(int dev, ulong block, ulong blkcnt, void *buff)
+ulong sata_read(int dev, ulong block, lbaint_t blkcnt, void *buff)
{
struct ata_port *ap = &port[dev];
ulong n = 0, sread;
@@ -1121,7 +1122,7 @@ ulong sata_read(int dev, ulong block, ulong blkcnt, void *buff)
return n;
}
-ulong sata_write(int dev, ulong block, ulong blkcnt, const void *buff)
+ulong sata_write(int dev, ulong block, lbaint_t blkcnt, const void *buff)
{
struct ata_port *ap = &port[dev];
void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
diff --git a/drivers/block/pata_bfin.h b/drivers/block/pata_bfin.h
index 2b3425bc95..2093cf06b4 100644
--- a/drivers/block/pata_bfin.h
+++ b/drivers/block/pata_bfin.h
@@ -41,8 +41,6 @@ struct ata_port {
unsigned char dev_mask;
};
-extern block_dev_desc_t sata_dev_desc[CONFIG_SYS_SATA_MAX_DEVICE];
-
#define DRV_NAME "pata-bfin"
#define DRV_VERSION "0.9"
#define __iomem
diff --git a/drivers/block/sata_dwc.c b/drivers/block/sata_dwc.c
index 75101b5d79..28d87f538b 100644
--- a/drivers/block/sata_dwc.c
+++ b/drivers/block/sata_dwc.c
@@ -35,6 +35,7 @@
#include <asm/io.h>
#include <malloc.h>
#include <ata.h>
+#include <sata.h>
#include <linux/ctype.h>
#include "sata_dwc.h"
@@ -268,8 +269,6 @@ static int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
unsigned int flags, u16 *id);
static int check_sata_dev_state(void);
-extern block_dev_desc_t sata_dev_desc[CONFIG_SYS_SATA_MAX_DEVICE];
-
static const struct ata_port_info sata_dwc_port_info[] = {
{
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
@@ -1907,7 +1906,7 @@ err_out:
#define SATA_MAX_WRITE_BLK 0xFFFF
#endif
-ulong sata_write(int device, ulong blknr, lbaint_t blkcnt, void *buffer)
+ulong sata_write(int device, ulong blknr, lbaint_t blkcnt, const void *buffer)
{
ulong start,blks, buf_addr;
unsigned short smallblks;
diff --git a/drivers/block/sata_sil.c b/drivers/block/sata_sil.c
index fb7cd2aae2..245b872f99 100644
--- a/drivers/block/sata_sil.c
+++ b/drivers/block/sata_sil.c
@@ -25,6 +25,7 @@
#include <malloc.h>
#include <asm/io.h>
#include <fis.h>
+#include <sata.h>
#include <libata.h>
#include "sata_sil.h"
@@ -369,7 +370,7 @@ static ulong sil_sata_rw_cmd_ext(int dev, ulong start, ulong blkcnt,
}
ulong sil_sata_rw_lba28(int dev, ulong blknr, lbaint_t blkcnt,
- void *buffer, int is_write)
+ const void *buffer, int is_write)
{
ulong start, blks, max_blks;
u8 *addr;
@@ -397,7 +398,7 @@ ulong sil_sata_rw_lba28(int dev, ulong blknr, lbaint_t blkcnt,
}
ulong sil_sata_rw_lba48(int dev, ulong blknr, lbaint_t blkcnt,
- void *buffer, int is_write)
+ const void *buffer, int is_write)
{
ulong start, blks, max_blks;
u8 *addr;
@@ -502,7 +503,7 @@ ulong sata_read(int dev, ulong blknr, lbaint_t blkcnt, void *buffer)
/*
* SATA interface between low level driver and command layer
*/
-ulong sata_write(int dev, ulong blknr, lbaint_t blkcnt, void *buffer)
+ulong sata_write(int dev, ulong blknr, lbaint_t blkcnt, const void *buffer)
{
struct sil_sata *sata = sata_dev_desc[dev].priv;
ulong rc;
diff --git a/drivers/block/sata_sil.h b/drivers/block/sata_sil.h
index 2dfd4a5e54..9f3a37f508 100644
--- a/drivers/block/sata_sil.h
+++ b/drivers/block/sata_sil.h
@@ -24,8 +24,6 @@
#define READ_CMD 0
#define WRITE_CMD 1
-extern block_dev_desc_t sata_dev_desc[CONFIG_SYS_SATA_MAX_DEVICE];
-
/*
* SATA device driver struct for each dev
*/
diff --git a/drivers/block/sata_sil3114.c b/drivers/block/sata_sil3114.c
index 34fe038608..3a5e0328f5 100644
--- a/drivers/block/sata_sil3114.c
+++ b/drivers/block/sata_sil3114.c
@@ -28,6 +28,7 @@
#include <asm/byteorder.h>
#include <asm/io.h>
#include <ide.h>
+#include <sata.h>
#include <libata.h>
#include "sata_sil3114.h"
@@ -48,7 +49,6 @@ static u8 sata_chk_status (struct sata_ioports *ioaddr, u8 usealtstatus);
static void msleep (int count);
static u32 iobase[6] = { 0, 0, 0, 0, 0, 0}; /* PCI BAR registers for device */
-extern block_dev_desc_t sata_dev_desc[CONFIG_SYS_SATA_MAX_DEVICE];
static struct sata_port port[CONFIG_SYS_SATA_MAX_DEVICE];
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 17f4b739a9..d50ac3bfef 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -44,6 +44,7 @@ COBJS-$(CONFIG_SH_GPIO_PFC) += sh_pfc.o
COBJS-$(CONFIG_OMAP_GPIO) += omap_gpio.o
COBJS-$(CONFIG_DB8500_GPIO) += db8500_gpio.o
COBJS-$(CONFIG_BCM2835_GPIO) += bcm2835_gpio.o
+COBJS-$(CONFIG_S3C2440_GPIO) += s3c2440_gpio.o
COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)
diff --git a/drivers/gpio/pca953x.c b/drivers/gpio/pca953x.c
index 359fdeea23..be13745921 100644
--- a/drivers/gpio/pca953x.c
+++ b/drivers/gpio/pca953x.c
@@ -221,7 +221,7 @@ cmd_tbl_t cmd_pca953x[] = {
int do_pca953x(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
static uint8_t chip = CONFIG_SYS_I2C_PCA953X_ADDR;
- int val;
+ int ret = CMD_RET_USAGE, val;
ulong ul_arg2 = 0;
ulong ul_arg3 = 0;
cmd_tbl_t *c;
@@ -232,7 +232,7 @@ int do_pca953x(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
if (!c || !((argc == (c->maxargs)) ||
(((int)c->cmd == PCA953X_CMD_DEVICE) &&
(argc == (c->maxargs - 1))))) {
- return cmd_usage(cmdtp);
+ return CMD_RET_USAGE;
}
/* arg2 used as chip number or pin number */
@@ -246,32 +246,53 @@ int do_pca953x(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
switch ((int)c->cmd) {
#ifdef CONFIG_CMD_PCA953X_INFO
case PCA953X_CMD_INFO:
- return pca953x_info(chip);
+ ret = pca953x_info(chip);
+ if (ret)
+ ret = CMD_RET_FAILURE;
+ break;
#endif
+
case PCA953X_CMD_DEVICE:
if (argc == 3)
chip = (uint8_t)ul_arg2;
printf("Current device address: 0x%x\n", chip);
- return 0;
+ ret = CMD_RET_SUCCESS;
+ break;
+
case PCA953X_CMD_INPUT:
- pca953x_set_dir(chip, (1 << ul_arg2),
+ ret = pca953x_set_dir(chip, (1 << ul_arg2),
PCA953X_DIR_IN << ul_arg2);
val = (pca953x_get_val(chip) & (1 << ul_arg2)) != 0;
- printf("chip 0x%02x, pin 0x%lx = %d\n", chip, ul_arg2, val);
- return val;
+ if (ret)
+ ret = CMD_RET_FAILURE;
+ else
+ printf("chip 0x%02x, pin 0x%lx = %d\n", chip, ul_arg2,
+ val);
+ break;
+
case PCA953X_CMD_OUTPUT:
- pca953x_set_dir(chip, (1 << ul_arg2),
+ ret = pca953x_set_dir(chip, (1 << ul_arg2),
(PCA953X_DIR_OUT << ul_arg2));
- return pca953x_set_val(chip, (1 << ul_arg2),
- (ul_arg3 << ul_arg2));
+ if (!ret)
+ ret = pca953x_set_val(chip, (1 << ul_arg2),
+ (ul_arg3 << ul_arg2));
+ if (ret)
+ ret = CMD_RET_FAILURE;
+ break;
+
case PCA953X_CMD_INVERT:
- return pca953x_set_pol(chip, (1 << ul_arg2),
+ ret = pca953x_set_pol(chip, (1 << ul_arg2),
(ul_arg3 << ul_arg2));
- default:
- /* We should never get here */
- return 1;
+ if (ret)
+ ret = CMD_RET_FAILURE;
+ break;
}
+
+ if (ret == CMD_RET_FAILURE)
+ eprintf("Error talking to chip at 0x%x\n", chip);
+
+ return ret;
}
U_BOOT_CMD(
@@ -287,7 +308,7 @@ U_BOOT_CMD(
" - set pin as output and drive low or high\n"
"pca953x invert pin 0|1\n"
" - disable/enable polarity inversion for reads\n"
- "pca953x intput pin\n"
+ "pca953x input pin\n"
" - set pin as input and read value"
);
diff --git a/drivers/gpio/s3c2440_gpio.c b/drivers/gpio/s3c2440_gpio.c
new file mode 100644
index 0000000000..43bbf1160c
--- /dev/null
+++ b/drivers/gpio/s3c2440_gpio.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2012
+ * Gabriel Huau <contact@huau-gabriel.fr>
+ *
+ * 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 <asm/arch/s3c2440.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+
+#define GPIO_INPUT 0x0
+#define GPIO_OUTPUT 0x1
+
+/* 0x4 means that we want DAT and not CON register */
+#define GPIO_PORT(x) ((((x) >> 5) & 0x3) + 0x4)
+#define GPIO_BIT(x) ((x) & 0x3f)
+
+/*
+ * It's how we calculate the full port address
+ * We have to get the number of the port + 1 (Port A is at 0x56000001 ...)
+ * We move it at the second digit, and finally we add 0x4 because we want
+ * to modify GPIO DAT and not CON
+ */
+#define GPIO_FULLPORT(x) (S3C24X0_GPIO_BASE | ((GPIO_PORT(gpio) + 1) << 1))
+
+int gpio_set_value(unsigned gpio, int value)
+{
+ unsigned l = readl(GPIO_FULLPORT(gpio));
+ unsigned bit;
+ unsigned port = GPIO_FULLPORT(gpio);
+
+ /*
+ * All GPIO Port have a configuration on
+ * 2 bits excepted the first GPIO (A) which
+ * have only 1 bit of configuration.
+ */
+ if (!GPIO_PORT(gpio))
+ bit = (0x1 << GPIO_BIT(gpio));
+ else
+ bit = (0x3 << GPIO_BIT(gpio));
+
+ if (value)
+ l |= bit;
+ else
+ l &= ~bit;
+
+ return writel(port, l);
+}
+
+int gpio_get_value(unsigned gpio)
+{
+ unsigned l = readl(GPIO_FULLPORT(gpio));
+
+ if (GPIO_PORT(gpio) == 0) /* PORT A */
+ return (l >> GPIO_BIT(gpio)) & 0x1;
+ return (l >> GPIO_BIT(gpio)) & 0x3;
+}
+
+int gpio_request(unsigned gpio, const char *label)
+{
+ return 0;
+}
+
+int gpio_free(unsigned gpio)
+{
+ return 0;
+}
+
+int gpio_direction_input(unsigned gpio)
+{
+ return writel(GPIO_FULLPORT(gpio), GPIO_INPUT << GPIO_BIT(gpio));
+}
+
+int gpio_direction_output(unsigned gpio, int value)
+{
+ writel(GPIO_FULLPORT(gpio), GPIO_OUTPUT << GPIO_BIT(gpio));
+ return gpio_set_value(gpio, value);
+}
diff --git a/drivers/gpio/tegra_gpio.c b/drivers/gpio/tegra_gpio.c
index 747f4cf921..2417968214 100644
--- a/drivers/gpio/tegra_gpio.c
+++ b/drivers/gpio/tegra_gpio.c
@@ -30,7 +30,7 @@
#include <common.h>
#include <asm/io.h>
#include <asm/bitops.h>
-#include <asm/arch/tegra20.h>
+#include <asm/arch/tegra.h>
#include <asm/gpio.h>
enum {
diff --git a/drivers/i2c/mxc_i2c.c b/drivers/i2c/mxc_i2c.c
index 73d8958701..18270b9de6 100644
--- a/drivers/i2c/mxc_i2c.c
+++ b/drivers/i2c/mxc_i2c.c
@@ -98,7 +98,7 @@ static uint8_t i2c_imx_get_clk(unsigned int rate)
#endif
/* Divider value calculation */
- i2c_clk_rate = mxc_get_clock(MXC_IPG_PERCLK);
+ i2c_clk_rate = mxc_get_clock(MXC_I2C_CLK);
div = (i2c_clk_rate + rate - 1) / rate;
if (div < i2c_clk_div[0][0])
clk_div = 0;
@@ -142,7 +142,7 @@ unsigned int bus_i2c_get_bus_speed(void *base)
for (clk_div = 0; i2c_clk_div[clk_div][1] != clk_idx; clk_div++)
;
- return mxc_get_clock(MXC_IPG_PERCLK) / i2c_clk_div[clk_div][0];
+ return mxc_get_clock(MXC_I2C_CLK) / i2c_clk_div[clk_div][0];
}
#define ST_BUS_IDLE (0 | (I2SR_IBB << 8))
diff --git a/drivers/i2c/sh_i2c.c b/drivers/i2c/sh_i2c.c
index fd8cb9285c..3147123bba 100644
--- a/drivers/i2c/sh_i2c.c
+++ b/drivers/i2c/sh_i2c.c
@@ -52,22 +52,6 @@ static u8 iccl, icch;
#define IRQ_WAIT 1000
-static void irq_wait(struct sh_i2c *base)
-{
- int i;
- u8 status;
-
- for (i = 0 ; i < IRQ_WAIT ; i++) {
- status = readb(&base->icsr);
- if (SH_IC_WAIT & status)
- break;
-
- udelay(10);
- }
-
- writeb(status & ~SH_IC_WAIT, &base->icsr);
-}
-
static void irq_dte(struct sh_i2c *base)
{
int i;
diff --git a/drivers/i2c/tegra_i2c.c b/drivers/i2c/tegra_i2c.c
index e3be14e3cf..efc77fa910 100644
--- a/drivers/i2c/tegra_i2c.c
+++ b/drivers/i2c/tegra_i2c.c
@@ -26,12 +26,12 @@
#include <fdtdec.h>
#include <i2c.h>
#include <asm/io.h>
-#include <asm/arch/clk_rst.h>
#include <asm/arch/clock.h>
#include <asm/arch/funcmux.h>
#include <asm/arch/gpio.h>
#include <asm/arch/pinmux.h>
-#include <asm/arch/tegra_i2c.h>
+#include <asm/arch-tegra/clk_rst.h>
+#include <asm/arch-tegra/tegra_i2c.h>
DECLARE_GLOBAL_DATA_PTR;
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 4eadd773b4..5b2b4b0714 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -356,7 +356,8 @@ int input_send_keycodes(struct input_config *config,
* insert another character if we later realise that we
* have missed a repeat slot.
*/
- is_repeat = (int)get_timer(config->next_repeat_ms) >= 0;
+ is_repeat = config->repeat_rate_ms &&
+ (int)get_timer(config->next_repeat_ms) >= 0;
if (!is_repeat)
return 0;
}
@@ -392,13 +393,17 @@ int input_add_table(struct input_config *config, int left_keycode,
return 0;
}
-int input_init(struct input_config *config, int leds, int repeat_delay_ms,
+void input_set_delays(struct input_config *config, int repeat_delay_ms,
int repeat_rate_ms)
{
- memset(config, '\0', sizeof(*config));
- config->leds = leds;
config->repeat_delay_ms = repeat_delay_ms;
config->repeat_rate_ms = repeat_rate_ms;
+}
+
+int input_init(struct input_config *config, int leds)
+{
+ memset(config, '\0', sizeof(*config));
+ config->leds = leds;
if (input_add_table(config, -1, -1,
kbd_plain_xlate, ARRAY_SIZE(kbd_plain_xlate)) ||
input_add_table(config, KEY_LEFTSHIFT, KEY_RIGHTSHIFT,
diff --git a/drivers/input/key_matrix.c b/drivers/input/key_matrix.c
index 715e57a2af..946a186a1f 100644
--- a/drivers/input/key_matrix.c
+++ b/drivers/input/key_matrix.c
@@ -46,6 +46,9 @@ static int has_ghosting(struct key_matrix *config, struct key_matrix_key *keys,
int key_in_same_col = 0, key_in_same_row = 0;
int i, j;
+ if (!config->ghost_filter || valid < 3)
+ return 0;
+
for (i = 0; i < valid; i++) {
/*
* Find 2 keys such that one key is in the same row
@@ -92,7 +95,7 @@ int key_matrix_decode(struct key_matrix *config, struct key_matrix_key keys[],
}
/* For a ghost key config, ignore the keypresses for this iteration. */
- if (valid >= 3 && has_ghosting(config, keys, valid)) {
+ if (has_ghosting(config, keys, valid)) {
valid = 0;
debug(" ghosting detected!\n");
}
@@ -142,6 +145,8 @@ static uchar *create_keymap(struct key_matrix *config, u32 *data, int len,
key_code = tmp & 0xffff;
entry = row * config->num_cols + col;
map[entry] = key_code;
+ debug(" map %d, %d: pos=%d, keycode=%d\n", row, col,
+ entry, key_code);
if (pos && map_keycode == key_code)
*pos = entry;
}
@@ -153,6 +158,8 @@ int key_matrix_decode_fdt(struct key_matrix *config, const void *blob,
int node)
{
const struct fdt_property *prop;
+ const char prefix[] = "linux,";
+ int plen = sizeof(prefix) - 1;
int offset;
/* Check each property name for ones that we understand */
@@ -168,16 +175,17 @@ int key_matrix_decode_fdt(struct key_matrix *config, const void *blob,
/* Name needs to match "1,<type>keymap" */
debug("%s: property '%s'\n", __func__, name);
- if (strncmp(name, "1,", 2) || len < 8 ||
- strcmp(name + len - 6, "keymap"))
+ if (strncmp(name, prefix, plen) ||
+ len < plen + 6 ||
+ strcmp(name + len - 6, "keymap"))
continue;
- len -= 8;
+ len -= plen + 6;
if (len == 0) {
config->plain_keycode = create_keymap(config,
(u32 *)prop->data, fdt32_to_cpu(prop->len),
KEY_FN, &config->fn_pos);
- } else if (0 == strncmp(name + 2, "fn-", len)) {
+ } else if (0 == strncmp(name + plen, "fn-", len)) {
config->fn_keycode = create_keymap(config,
(u32 *)prop->data, fdt32_to_cpu(prop->len),
-1, NULL);
@@ -197,12 +205,14 @@ int key_matrix_decode_fdt(struct key_matrix *config, const void *blob,
return 0;
}
-int key_matrix_init(struct key_matrix *config, int rows, int cols)
+int key_matrix_init(struct key_matrix *config, int rows, int cols,
+ int ghost_filter)
{
memset(config, '\0', sizeof(*config));
config->num_rows = rows;
config->num_cols = cols;
config->key_count = rows * cols;
+ config->ghost_filter = ghost_filter;
assert(config->key_count > 0);
return 0;
diff --git a/drivers/input/tegra-kbc.c b/drivers/input/tegra-kbc.c
index f164791bee..ab7a9e33ee 100644
--- a/drivers/input/tegra-kbc.c
+++ b/drivers/input/tegra-kbc.c
@@ -30,7 +30,7 @@
#include <asm/io.h>
#include <asm/arch/clock.h>
#include <asm/arch/funcmux.h>
-#include <asm/arch/timer.h>
+#include <asm/arch-tegra/timer.h>
#include <linux/input.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -321,9 +321,11 @@ static int init_tegra_keyboard(void)
debug("%s: No keyboard register found\n", __func__);
return -1;
}
+ input_set_delays(&config.input, KBC_REPEAT_DELAY_MS,
+ KBC_REPEAT_RATE_MS);
/* Decode the keyboard matrix information (16 rows, 8 columns) */
- if (key_matrix_init(&config.matrix, 16, 8)) {
+ if (key_matrix_init(&config.matrix, 16, 8, 1)) {
debug("%s: Could not init key matrix\n", __func__);
return -1;
}
@@ -356,8 +358,7 @@ int drv_keyboard_init(void)
{
struct stdio_dev dev;
- if (input_init(&config.input, 0, KBC_REPEAT_DELAY_MS,
- KBC_REPEAT_RATE_MS)) {
+ if (input_init(&config.input, 0)) {
debug("%s: Cannot set up input\n", __func__);
return -1;
}
diff --git a/drivers/mmc/tegra_mmc.c b/drivers/mmc/tegra_mmc.c
index ca8fad8657..8fea6a6bfb 100644
--- a/drivers/mmc/tegra_mmc.c
+++ b/drivers/mmc/tegra_mmc.c
@@ -20,12 +20,12 @@
*/
#include <common.h>
-#include <mmc.h>
#include <asm/gpio.h>
#include <asm/io.h>
-#include <asm/arch/clk_rst.h>
#include <asm/arch/clock.h>
-#include <asm/arch/tegra_mmc.h>
+#include <asm/arch-tegra/clk_rst.h>
+#include <asm/arch-tegra/tegra_mmc.h>
+#include <mmc.h>
/* support 4 mmc hosts */
struct mmc mmc_dev[4];
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index c6aa5db33c..994dd9f095 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -652,8 +652,9 @@ static int atmel_pmecc_nand_init_params(struct nand_chip *nand,
sector_size = host->pmecc_sector_size = CONFIG_PMECC_SECTOR_SIZE;
host->pmecc_index_table_offset = CONFIG_PMECC_INDEX_TABLE_OFFSET;
- printk(KERN_INFO "Initialize PMECC params, cap: %d, sector: %d\n",
- cap, sector_size);
+ MTDDEBUG(MTD_DEBUG_LEVEL1,
+ "Initialize PMECC params, cap: %d, sector: %d\n",
+ cap, sector_size);
host->pmecc = (struct pmecc_regs __iomem *) ATMEL_BASE_PMECC;
host->pmerrloc = (struct pmecc_errloc_regs __iomem *)
diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c
index 31c174bd3b..11eb167e37 100644
--- a/drivers/mtd/nand/fsl_upm.c
+++ b/drivers/mtd/nand/fsl_upm.c
@@ -57,7 +57,7 @@ static void fun_wait(struct fsl_upm_nand *fun)
debug("unexpected busy state\n");
} else {
/*
- * If the R/B pin is not connected, like on the TQM8548,
+ * If the R/B pin is not connected,
* a short delay is necessary.
*/
udelay(1);
@@ -115,10 +115,10 @@ static void fun_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
fsl_upm_run_pattern(&fun->upm, fun->width, io_addr, mar);
/*
- * Some boards/chips needs this. At least the MPC8360E-RDK and
- * TQM8548 need it. Probably weird chip, because I don't see
- * any need for this on MPC8555E + Samsung K9F1G08U0A. Usually
- * here are 0-2 unexpected busy states per block read.
+ * Some boards/chips needs this. At least the MPC8360E-RDK
+ * needs it. Probably weird chip, because I don't see any
+ * need for this on MPC8555E + Samsung K9F1G08U0A. Usually
+ * here are 0-2 unexpected busy states per block read.
*/
if (fun->wait_flags & FSL_UPM_WAIT_RUN_PATTERN)
fun_wait(fun);
diff --git a/drivers/mtd/nand/tegra_nand.c b/drivers/mtd/nand/tegra_nand.c
index 8c1de34455..5408c51ffb 100644
--- a/drivers/mtd/nand/tegra_nand.c
+++ b/drivers/mtd/nand/tegra_nand.c
@@ -26,12 +26,11 @@
#include <common.h>
#include <asm/io.h>
#include <nand.h>
-#include <asm/arch/clk_rst.h>
#include <asm/arch/clock.h>
#include <asm/arch/funcmux.h>
-#include <asm/arch/gpio.h>
+#include <asm/arch-tegra/clk_rst.h>
#include <asm/errno.h>
-#include <asm-generic/gpio.h>
+#include <asm/gpio.h>
#include <fdtdec.h>
#include "tegra_nand.h"
@@ -993,7 +992,6 @@ int tegra_nand_init(struct nand_chip *nand, int devnum)
/* Adjust timing for NAND device */
setup_timing(config->timing, info->reg);
- funcmux_select(PERIPH_ID_NDFLASH, FUNCMUX_DEFAULT);
fdtdec_setup_gpio(&config->wp_gpio);
gpio_direction_output(config->wp_gpio.gpio, 1);
diff --git a/drivers/mtd/spi/atmel.c b/drivers/mtd/spi/atmel.c
index 1ecece0d78..006f6d5d04 100644
--- a/drivers/mtd/spi/atmel.c
+++ b/drivers/mtd/spi/atmel.c
@@ -109,6 +109,14 @@ static const struct atmel_spi_flash_params atmel_spi_flash_table[] = {
.nr_sectors = 32,
.name = "AT45DB642D",
},
+ {
+ .idcode1 = 0x47,
+ .l2_page_size = 8,
+ .pages_per_block = 16,
+ .blocks_per_sector = 16,
+ .nr_sectors = 64,
+ .name = "AT25DF321",
+ },
};
static int at45_wait_ready(struct spi_flash *flash, unsigned long timeout)
@@ -510,11 +518,19 @@ struct spi_flash *spi_flash_probe_atmel(struct spi_slave *spi, u8 *idcode)
asf->flash.erase = dataflash_erase_p2;
}
+ asf->flash.page_size = page_size;
+ asf->flash.sector_size = page_size;
break;
case DF_FAMILY_AT26F:
case DF_FAMILY_AT26DF:
asf->flash.read = spi_flash_cmd_read_fast;
+ asf->flash.write = spi_flash_cmd_write_multi;
+ asf->flash.erase = spi_flash_cmd_erase;
+ asf->flash.page_size = page_size;
+ asf->flash.sector_size = 4096;
+ /* clear SPRL# bit for locked flash */
+ spi_flash_cmd_write_status(&asf->flash, 0);
break;
default:
@@ -522,7 +538,6 @@ struct spi_flash *spi_flash_probe_atmel(struct spi_slave *spi, u8 *idcode)
goto err;
}
- asf->flash.sector_size = page_size;
asf->flash.size = page_size * params->pages_per_block
* params->blocks_per_sector
* params->nr_sectors;
diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c
index b2516d1768..1db586d6b2 100644
--- a/drivers/net/davinci_emac.c
+++ b/drivers/net/davinci_emac.c
@@ -897,7 +897,8 @@ int davinci_emac_initialize(void)
}
#if defined(CONFIG_DRIVER_TI_EMAC_USE_RMII) && \
- defined(CONFIG_MACH_DAVINCI_DA850_EVM)
+ defined(CONFIG_MACH_DAVINCI_DA850_EVM) && \
+ !defined(CONFIG_DRIVER_TI_EMAC_RMII_NO_NEGOTIATE)
for (i = 0; i < num_phy; i++) {
if (phy[i].is_phy_connected(i))
phy[i].auto_negotiate(i);
diff --git a/drivers/net/e1000.c b/drivers/net/e1000.c
index 94b2a41e14..2d4da4b386 100644
--- a/drivers/net/e1000.c
+++ b/drivers/net/e1000.c
@@ -135,7 +135,6 @@ static void e1000_set_media_type(struct e1000_hw *hw);
static int32_t e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask);
static int32_t e1000_check_phy_reset_block(struct e1000_hw *hw);
-#ifndef CONFIG_AP1000 /* remove for warnings */
static int32_t e1000_read_eeprom(struct e1000_hw *hw, uint16_t offset,
uint16_t words,
uint16_t *data);
@@ -942,7 +941,6 @@ e1000_set_phy_mode(struct e1000_hw *hw)
return E1000_SUCCESS;
}
-#endif /* #ifndef CONFIG_AP1000 */
/***************************************************************************
*
@@ -1123,7 +1121,6 @@ static boolean_t e1000_is_second_port(struct e1000_hw *hw)
static int
e1000_read_mac_addr(struct eth_device *nic)
{
-#ifndef CONFIG_AP1000
struct e1000_hw *hw = nic->priv;
uint16_t offset;
uint16_t eeprom_data;
@@ -1152,31 +1149,6 @@ e1000_read_mac_addr(struct eth_device *nic)
memcpy (nic->enetaddr, fb_mac, NODE_ADDRESS_SIZE);
}
#endif
-#else
- /*
- * The AP1000's e1000 has no eeprom; the MAC address is stored in the
- * environment variables. Currently this does not support the addition
- * of a PMC e1000 card, which is certainly a possibility, so this should
- * be updated to properly use the env variable only for the onboard e1000
- */
-
- int ii;
- char *s, *e;
-
- DEBUGFUNC();
-
- s = getenv ("ethaddr");
- if (s == NULL) {
- return -E1000_ERR_EEPROM;
- } else {
- for(ii = 0; ii < 6; ii++) {
- nic->enetaddr[ii] = s ? simple_strtoul (s, &e, 16) : 0;
- if (s){
- s = (*e) ? e + 1 : e;
- }
- }
- }
-#endif
return 0;
}
@@ -1808,7 +1780,6 @@ e1000_setup_link(struct eth_device *nic)
if (e1000_check_phy_reset_block(hw))
return E1000_SUCCESS;
-#ifndef CONFIG_AP1000
/* Read and store word 0x0F of the EEPROM. This word contains bits
* that determine the hardware's default PAUSE (flow control) mode,
* a bit that determines whether the HW defaults to enabling or
@@ -1822,11 +1793,6 @@ e1000_setup_link(struct eth_device *nic)
DEBUGOUT("EEPROM Read Error\n");
return -E1000_ERR_EEPROM;
}
-#else
- /* we have to hardcode the proper value for our hardware. */
- /* this value is for the 82540EM pci card used for prototyping, and it works. */
- eeprom_data = 0xb220;
-#endif
if (hw->fc == e1000_fc_default) {
switch (hw->mac_type) {
@@ -1836,16 +1802,12 @@ e1000_setup_link(struct eth_device *nic)
hw->fc = e1000_fc_full;
break;
default:
-#ifndef CONFIG_AP1000
ret_val = e1000_read_eeprom(hw,
EEPROM_INIT_CONTROL2_REG, 1, &eeprom_data);
if (ret_val) {
DEBUGOUT("EEPROM Read Error\n");
return -E1000_ERR_EEPROM;
}
-#else
- eeprom_data = 0xb220;
-#endif
if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == 0)
hw->fc = e1000_fc_none;
else if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) ==
@@ -2109,12 +2071,10 @@ e1000_copper_link_preconfig(struct e1000_hw *hw)
}
DEBUGOUT("Phy ID = %x \n", hw->phy_id);
-#ifndef CONFIG_AP1000
/* Set PHY to class A mode (if necessary) */
ret_val = e1000_set_phy_mode(hw);
if (ret_val)
return ret_val;
-#endif
if ((hw->mac_type == e1000_82545_rev_3) ||
(hw->mac_type == e1000_82546_rev_3)) {
ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL,
@@ -5242,7 +5202,7 @@ e1000_initialize(bd_t * bis)
list_add_tail(&hw->list_node, &e1000_hw_list);
/* Validate the EEPROM and get chipset information */
-#if !(defined(CONFIG_AP1000) || defined(CONFIG_MVBC_1G))
+#if !defined(CONFIG_MVBC_1G)
if (e1000_init_eeprom_params(hw)) {
E1000_ERR(nic, "EEPROM is invalid!\n");
continue;
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 65d0f234e7..3c32f97abb 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -25,6 +25,8 @@ include $(TOPDIR)/config.mk
LIB := $(obj)libserial.o
+COBJS-y += serial.o
+
COBJS-$(CONFIG_ALTERA_UART) += altera_uart.o
COBJS-$(CONFIG_ALTERA_JTAG_UART) += altera_jtag_uart.o
COBJS-$(CONFIG_ARM_DCC) += arm_dcc.o
@@ -37,7 +39,7 @@ COBJS-$(CONFIG_SYS_NS16550) += ns16550.o
COBJS-$(CONFIG_DRIVER_S3C4510_UART) += s3c4510b_uart.o
COBJS-$(CONFIG_S3C64XX) += s3c64xx.o
COBJS-$(CONFIG_S5P) += serial_s5p.o
-COBJS-$(CONFIG_SYS_NS16550_SERIAL) += serial.o
+COBJS-$(CONFIG_SYS_NS16550_SERIAL) += serial_ns16550.o
COBJS-$(CONFIG_CLPS7111_SERIAL) += serial_clps7111.o
COBJS-$(CONFIG_IMX_SERIAL) += serial_imx.o
COBJS-$(CONFIG_IXP_SERIAL) += serial_ixp.o
@@ -56,6 +58,7 @@ COBJS-$(CONFIG_S3C44B0_SERIAL) += serial_s3c44b0.o
COBJS-$(CONFIG_XILINX_UARTLITE) += serial_xuartlite.o
COBJS-$(CONFIG_SANDBOX_SERIAL) += sandbox.o
COBJS-$(CONFIG_SCIF_CONSOLE) += serial_sh.o
+COBJS-$(CONFIG_ZYNQ_SERIAL) += serial_zynq.o
ifndef CONFIG_SPL_BUILD
COBJS-$(CONFIG_USB_TTY) += usbtty.o
diff --git a/drivers/serial/altera_jtag_uart.c b/drivers/serial/altera_jtag_uart.c
index 2980e4d07c..654b5019eb 100644
--- a/drivers/serial/altera_jtag_uart.c
+++ b/drivers/serial/altera_jtag_uart.c
@@ -25,6 +25,8 @@
#include <watchdog.h>
#include <asm/io.h>
#include <nios2-io.h>
+#include <linux/compiler.h>
+#include <serial.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -33,10 +35,16 @@ DECLARE_GLOBAL_DATA_PTR;
*-----------------------------------------------------------------*/
static nios_jtag_t *jtag = (nios_jtag_t *)CONFIG_SYS_NIOS_CONSOLE;
-void serial_setbrg( void ){ return; }
-int serial_init( void ) { return(0);}
+static void altera_jtag_serial_setbrg(void)
+{
+}
+
+static int altera_jtag_serial_init(void)
+{
+ return 0;
+}
-void serial_putc (char c)
+static void altera_jtag_serial_putc(char c)
{
while (1) {
unsigned st = readl(&jtag->control);
@@ -51,18 +59,18 @@ void serial_putc (char c)
writel ((unsigned char)c, &jtag->data);
}
-void serial_puts (const char *s)
+static void altera_jtag_serial_puts(const char *s)
{
while (*s != 0)
serial_putc (*s++);
}
-int serial_tstc (void)
+static int altera_jtag_serial_tstc(void)
{
return ( readl (&jtag->control) & NIOS_JTAG_RRDY);
}
-int serial_getc (void)
+static int altera_jtag_serial_getc(void)
{
int c;
unsigned val;
@@ -76,3 +84,24 @@ int serial_getc (void)
c = val & 0x0ff;
return (c);
}
+
+static struct serial_device altera_jtag_serial_drv = {
+ .name = "altera_jtag_uart",
+ .start = altera_jtag_serial_init,
+ .stop = NULL,
+ .setbrg = altera_jtag_serial_setbrg,
+ .putc = altera_jtag_serial_putc,
+ .puts = altera_jtag_serial_puts,
+ .getc = altera_jtag_serial_getc,
+ .tstc = altera_jtag_serial_tstc,
+};
+
+void altera_jtag_serial_initialize(void)
+{
+ serial_register(&altera_jtag_serial_drv);
+}
+
+__weak struct serial_device *default_serial_console(void)
+{
+ return &altera_jtag_serial_drv;
+}
diff --git a/drivers/serial/altera_uart.c b/drivers/serial/altera_uart.c
index 045f1197a3..27550ed48d 100644
--- a/drivers/serial/altera_uart.c
+++ b/drivers/serial/altera_uart.c
@@ -26,6 +26,8 @@
#include <watchdog.h>
#include <asm/io.h>
#include <nios2-io.h>
+#include <linux/compiler.h>
+#include <serial.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -37,27 +39,33 @@ static nios_uart_t *uart = (nios_uart_t *) CONFIG_SYS_NIOS_CONSOLE;
#if defined(CONFIG_SYS_NIOS_FIXEDBAUD)
-/* Everything's already setup for fixed-baud PTF
+/*
+ * Everything's already setup for fixed-baud PTF
* assignment
*/
-void serial_setbrg (void){ return; }
-int serial_init (void) { return (0);}
+static void altera_serial_setbrg(void)
+{
+}
+
+static int altera_serial_init(void)
+{
+ return 0;
+}
#else
-void serial_setbrg (void)
+static void altera_serial_setbrg(void)
{
unsigned div;
div = (CONFIG_SYS_CLK_FREQ/gd->baudrate)-1;
writel (div, &uart->divisor);
- return;
}
-int serial_init (void)
+static int altera_serial_init(void)
{
- serial_setbrg ();
- return (0);
+ serial_setbrg();
+ return 0;
}
#endif /* CONFIG_SYS_NIOS_FIXEDBAUD */
@@ -65,7 +73,7 @@ int serial_init (void)
/*-----------------------------------------------------------------------
* UART CONSOLE
*---------------------------------------------------------------------*/
-void serial_putc (char c)
+static void altera_serial_putc(char c)
{
if (c == '\n')
serial_putc ('\r');
@@ -74,21 +82,42 @@ void serial_putc (char c)
writel ((unsigned char)c, &uart->txdata);
}
-void serial_puts (const char *s)
+static void altera_serial_puts(const char *s)
{
while (*s != 0) {
serial_putc (*s++);
}
}
-int serial_tstc (void)
+static int altera_serial_tstc(void)
{
return (readl (&uart->status) & NIOS_UART_RRDY);
}
-int serial_getc (void)
+static int altera_serial_getc(void)
{
while (serial_tstc () == 0)
WATCHDOG_RESET ();
return (readl (&uart->rxdata) & 0x00ff );
}
+
+static struct serial_device altera_serial_drv = {
+ .name = "altera_serial",
+ .start = altera_serial_init,
+ .stop = NULL,
+ .setbrg = altera_serial_setbrg,
+ .putc = altera_serial_putc,
+ .puts = altera_serial_puts,
+ .getc = altera_serial_getc,
+ .tstc = altera_serial_tstc,
+};
+
+void altera_serial_initialize(void)
+{
+ serial_register(&altera_serial_drv);
+}
+
+__weak struct serial_device *default_serial_console(void)
+{
+ return &altera_serial_drv;
+}
diff --git a/drivers/serial/atmel_usart.c b/drivers/serial/atmel_usart.c
index 943ef70fa6..130303129e 100644
--- a/drivers/serial/atmel_usart.c
+++ b/drivers/serial/atmel_usart.c
@@ -20,6 +20,8 @@
*/
#include <common.h>
#include <watchdog.h>
+#include <serial.h>
+#include <linux/compiler.h>
#include <asm/io.h>
#include <asm/arch/clk.h>
@@ -29,7 +31,7 @@
DECLARE_GLOBAL_DATA_PTR;
-void serial_setbrg(void)
+static void atmel_serial_setbrg(void)
{
atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE;
unsigned long divisor;
@@ -45,7 +47,7 @@ void serial_setbrg(void)
writel(USART3_BF(CD, divisor), &usart->brgr);
}
-int serial_init(void)
+static int atmel_serial_init(void)
{
atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE;
@@ -73,7 +75,7 @@ int serial_init(void)
return 0;
}
-void serial_putc(char c)
+static void atmel_serial_putc(char c)
{
atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE;
@@ -84,13 +86,13 @@ void serial_putc(char c)
writel(c, &usart->thr);
}
-void serial_puts(const char *s)
+static void atmel_serial_puts(const char *s)
{
while (*s)
serial_putc(*s++);
}
-int serial_getc(void)
+static int atmel_serial_getc(void)
{
atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE;
@@ -99,8 +101,29 @@ int serial_getc(void)
return readl(&usart->rhr);
}
-int serial_tstc(void)
+static int atmel_serial_tstc(void)
{
atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE;
return (readl(&usart->csr) & USART3_BIT(RXRDY)) != 0;
}
+
+static struct serial_device atmel_serial_drv = {
+ .name = "atmel_serial",
+ .start = atmel_serial_init,
+ .stop = NULL,
+ .setbrg = atmel_serial_setbrg,
+ .putc = atmel_serial_putc,
+ .puts = atmel_serial_puts,
+ .getc = atmel_serial_getc,
+ .tstc = atmel_serial_tstc,
+};
+
+void atmel_serial_initialize(void)
+{
+ serial_register(&atmel_serial_drv);
+}
+
+__weak struct serial_device *default_serial_console(void)
+{
+ return &atmel_serial_drv;
+}
diff --git a/drivers/serial/lpc32xx_hsuart.c b/drivers/serial/lpc32xx_hsuart.c
index 8ce3382d86..02429b5541 100644
--- a/drivers/serial/lpc32xx_hsuart.c
+++ b/drivers/serial/lpc32xx_hsuart.c
@@ -22,12 +22,14 @@
#include <asm/arch/clk.h>
#include <asm/arch/uart.h>
#include <asm/io.h>
+#include <serial.h>
+#include <linux/compiler.h>
DECLARE_GLOBAL_DATA_PTR;
static struct hsuart_regs *hsuart = (struct hsuart_regs *)HS_UART_BASE;
-static void lpc32xx_hsuart_set_baudrate(void)
+static void lpc32xx_serial_setbrg(void)
{
u32 div;
@@ -39,7 +41,7 @@ static void lpc32xx_hsuart_set_baudrate(void)
writel(div, &hsuart->rate);
}
-static int lpc32xx_hsuart_getc(void)
+static int lpc32xx_serial_getc(void)
{
while (!(readl(&hsuart->level) & HSUART_LEVEL_RX))
/* NOP */;
@@ -47,7 +49,7 @@ static int lpc32xx_hsuart_getc(void)
return readl(&hsuart->rx) & HSUART_RX_DATA;
}
-static void lpc32xx_hsuart_putc(const char c)
+static void lpc32xx_serial_putc(const char c)
{
writel(c, &hsuart->tx);
@@ -56,7 +58,7 @@ static void lpc32xx_hsuart_putc(const char c)
/* NOP */;
}
-static int lpc32xx_hsuart_tstc(void)
+static int lpc32xx_serial_tstc(void)
{
if (readl(&hsuart->level) & HSUART_LEVEL_RX)
return 1;
@@ -64,49 +66,40 @@ static int lpc32xx_hsuart_tstc(void)
return 0;
}
-static void lpc32xx_hsuart_init(void)
+static int lpc32xx_serial_init(void)
{
- lpc32xx_hsuart_set_baudrate();
+ lpc32xx_serial_setbrg();
/* Disable hardware RTS and CTS flow control, set up RX and TX FIFO */
writel(HSUART_CTRL_TMO_16 | HSUART_CTRL_HSU_OFFSET(20) |
HSUART_CTRL_HSU_RX_TRIG_32 | HSUART_CTRL_HSU_TX_TRIG_0,
&hsuart->ctrl);
+ return 0;
}
-void serial_setbrg(void)
-{
- return lpc32xx_hsuart_set_baudrate();
-}
-
-void serial_putc(const char c)
-{
- lpc32xx_hsuart_putc(c);
-
- /* If \n, also do \r */
- if (c == '\n')
- lpc32xx_hsuart_putc('\r');
-}
-
-int serial_getc(void)
-{
- return lpc32xx_hsuart_getc();
-}
-
-void serial_puts(const char *s)
+static void lpc32xx_serial_puts(const char *s)
{
while (*s)
serial_putc(*s++);
}
-int serial_tstc(void)
+static struct serial_device lpc32xx_serial_drv = {
+ .name = "lpc32xx_serial",
+ .start = lpc32xx_serial_init,
+ .stop = NULL,
+ .setbrg = lpc32xx_serial_setbrg,
+ .putc = lpc32xx_serial_putc,
+ .puts = lpc32xx_serial_puts,
+ .getc = lpc32xx_serial_getc,
+ .tstc = lpc32xx_serial_tstc,
+};
+
+void lpc32xx_serial_initialize(void)
{
- return lpc32xx_hsuart_tstc();
+ serial_register(&lpc32xx_serial_drv);
}
-int serial_init(void)
+__weak struct serial_device *default_serial_console(void)
{
- lpc32xx_hsuart_init();
-
- return 0;
+ return &lpc32xx_serial_drv;
}
diff --git a/drivers/serial/mcfuart.c b/drivers/serial/mcfuart.c
index d93b24b897..00a7114691 100644
--- a/drivers/serial/mcfuart.c
+++ b/drivers/serial/mcfuart.c
@@ -36,7 +36,7 @@ DECLARE_GLOBAL_DATA_PTR;
extern void uart_port_conf(int port);
-int serial_init(void)
+static int mcf_serial_init(void)
{
volatile uart_t *uart;
u32 counter;
@@ -74,7 +74,7 @@ int serial_init(void)
return (0);
}
-void serial_putc(const char c)
+static void mcf_serial_putc(const char c)
{
volatile uart_t *uart = (volatile uart_t *)(CONFIG_SYS_UART_BASE);
@@ -87,14 +87,14 @@ void serial_putc(const char c)
uart->utb = c;
}
-void serial_puts(const char *s)
+static void mcf_serial_puts(const char *s)
{
while (*s) {
serial_putc(*s++);
}
}
-int serial_getc(void)
+static int mcf_serial_getc(void)
{
volatile uart_t *uart = (volatile uart_t *)(CONFIG_SYS_UART_BASE);
@@ -103,14 +103,14 @@ int serial_getc(void)
return uart->urb;
}
-int serial_tstc(void)
+static int mcf_serial_tstc(void)
{
volatile uart_t *uart = (volatile uart_t *)(CONFIG_SYS_UART_BASE);
return (uart->usr & UART_USR_RXRDY);
}
-void serial_setbrg(void)
+static void mcf_serial_setbrg(void)
{
volatile uart_t *uart = (volatile uart_t *)(CONFIG_SYS_UART_BASE);
u32 counter;
@@ -129,3 +129,24 @@ void serial_setbrg(void)
uart->ucr = UART_UCR_RX_ENABLED | UART_UCR_TX_ENABLED;
}
+
+static struct serial_device mcf_serial_drv = {
+ .name = "mcf_serial",
+ .start = mcf_serial_init,
+ .stop = NULL,
+ .setbrg = mcf_serial_setbrg,
+ .putc = mcf_serial_putc,
+ .puts = mcf_serial_puts,
+ .getc = mcf_serial_getc,
+ .tstc = mcf_serial_tstc,
+};
+
+void mcf_serial_initialize(void)
+{
+ serial_register(&mcf_serial_drv);
+}
+
+__weak struct serial_device *default_serial_console(void)
+{
+ return &mcf_serial_drv;
+}
diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c
index facadd2f5c..9027781445 100644
--- a/drivers/serial/ns16550.c
+++ b/drivers/serial/ns16550.c
@@ -101,7 +101,7 @@ void NS16550_putc(NS16550_t com_port, char c)
char NS16550_getc(NS16550_t com_port)
{
while ((serial_in(&com_port->lsr) & UART_LSR_DR) == 0) {
-#ifdef CONFIG_USB_TTY
+#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_USB_TTY)
extern void usbtty_poll(void);
usbtty_poll();
#endif
diff --git a/drivers/serial/ns9750_serial.c b/drivers/serial/ns9750_serial.c
index e9645a053d..cb545c4065 100644
--- a/drivers/serial/ns9750_serial.c
+++ b/drivers/serial/ns9750_serial.c
@@ -52,7 +52,7 @@ static unsigned int unCharCache; /* unCharCache is only valid if
* @Descr: configures GPIOs and UART. Requires BBUS Master Reset turned off
***********************************************************************/
-int serial_init( void )
+static int ns9750_serial_init(void)
{
unsigned int aunGPIOTxD[] = { 0, 8, 40, 44 };
unsigned int aunGPIORxD[] = { 1, 9, 41, 45 };
@@ -85,7 +85,7 @@ int serial_init( void )
* @Descr: writes one character to the FIFO. Blocks until FIFO is not full
***********************************************************************/
-void serial_putc( const char c )
+static void ns9750_serial_putc(const char c)
{
if (c == '\n')
serial_putc( '\r' );
@@ -105,7 +105,7 @@ void serial_putc( const char c )
* @Descr: writes non-zero string to the FIFO.
***********************************************************************/
-void serial_puts( const char *s )
+static void ns9750_serial_puts(const char *s)
{
while (*s) {
serial_putc( *s++ );
@@ -118,7 +118,7 @@ void serial_puts( const char *s )
* @Descr: performs only 8bit accesses to the FIFO. No error handling
***********************************************************************/
-int serial_getc( void )
+static int ns9750_serial_getc(void)
{
int i;
@@ -142,7 +142,7 @@ int serial_getc( void )
* unCharCache and the numbers of characters in cCharsAvailable
***********************************************************************/
-int serial_tstc( void )
+static int ns9750_serial_tstc(void)
{
unsigned int unRegCache;
@@ -171,7 +171,7 @@ int serial_tstc( void )
return 0;
}
-void serial_setbrg( void )
+static void ns9750_serial_setbrg(void)
{
*get_ser_reg_addr_channel( NS9750_SER_BITRATE, CONSOLE ) =
calcBitrateRegister();
@@ -208,3 +208,24 @@ static unsigned int calcRxCharGapRegister( void )
{
return NS9750_SER_RX_CHAR_TIMER_TRUN;
}
+
+static struct serial_device ns9750_serial_drv = {
+ .name = "ns9750_serial",
+ .start = ns9750_serial_init,
+ .stop = NULL,
+ .setbrg = ns9750_serial_setbrg,
+ .putc = ns9750_serial_putc,
+ .puts = ns9750_serial_puts,
+ .getc = ns9750_serial_getc,
+ .tstc = ns9750_serial_tstc,
+};
+
+void ns9750_serial_initialize(void)
+{
+ serial_register(&ns9750_serial_drv);
+}
+
+__weak struct serial_device *default_serial_console(void)
+{
+ return &ns9750_serial_drv;
+}
diff --git a/drivers/serial/opencores_yanu.c b/drivers/serial/opencores_yanu.c
index f3830112aa..49bccf3a6c 100644
--- a/drivers/serial/opencores_yanu.c
+++ b/drivers/serial/opencores_yanu.c
@@ -37,7 +37,7 @@ static yanu_uart_t *uart = (yanu_uart_t *)CONFIG_SYS_NIOS_CONSOLE;
/* Everything's already setup for fixed-baud PTF assignment*/
-void serial_setbrg (void)
+static void oc_serial_setbrg(void)
{
int n, k;
const unsigned max_uns = 0xFFFFFFFF;
@@ -68,7 +68,7 @@ void serial_setbrg (void)
#else
-void serial_setbrg (void)
+static void oc_serial_setbrg(void)
{
int n, k;
const unsigned max_uns = 0xFFFFFFFF;
@@ -100,7 +100,7 @@ void serial_setbrg (void)
#endif /* CONFIG_SYS_NIOS_FIXEDBAUD */
-int serial_init (void)
+static int oc_serial_init(void)
{
unsigned action,control;
@@ -141,7 +141,7 @@ int serial_init (void)
/*-----------------------------------------------------------------------
* YANU CONSOLE
*---------------------------------------------------------------------*/
-void serial_putc (char c)
+static void oc_serial_putc(char c)
{
int tx_chars;
unsigned status;
@@ -161,7 +161,7 @@ void serial_putc (char c)
writel((unsigned char)c, &uart->data);
}
-void serial_puts (const char *s)
+static void oc_serial_puts(const char *s)
{
while (*s != 0) {
serial_putc (*s++);
@@ -169,7 +169,7 @@ void serial_puts (const char *s)
}
-int serial_tstc(void)
+static int oc_serial_tstc(void)
{
unsigned status ;
@@ -178,7 +178,7 @@ int serial_tstc(void)
((1 << YANU_RFIFO_CHARS_N) - 1)) > 0);
}
-int serial_getc (void)
+statoc int oc_serial_getc(void)
{
while (serial_tstc() == 0)
WATCHDOG_RESET ();
@@ -188,3 +188,24 @@ int serial_getc (void)
return(readl(&uart->data) & YANU_DATA_CHAR_MASK);
}
+
+static struct serial_device oc_serial_drv = {
+ .name = "oc_serial",
+ .start = oc_serial_init,
+ .stop = NULL,
+ .setbrg = oc_serial_setbrg,
+ .putc = oc_serial_putc,
+ .puts = oc_serial_puts,
+ .getc = oc_serial_getc,
+ .tstc = oc_serial_tstc,
+};
+
+void oc_serial_initialize(void)
+{
+ serial_register(&oc_serial_drv);
+}
+
+__weak struct serial_device *default_serial_console(void)
+{
+ return &oc_serial_drv;
+}
diff --git a/drivers/serial/s3c4510b_uart.c b/drivers/serial/s3c4510b_uart.c
index aa378e1ac1..423d26e678 100644
--- a/drivers/serial/s3c4510b_uart.c
+++ b/drivers/serial/s3c4510b_uart.c
@@ -80,7 +80,7 @@ static int serial_flush_output(void)
}
-void serial_setbrg (void)
+static void s3c4510b_serial_setbrg(void)
{
UART_LINE_CTRL ulctrl;
UART_CTRL uctrl;
@@ -135,7 +135,7 @@ void serial_setbrg (void)
* are always 8 data bits, no parity, 1 stop bit, no start bits.
*
*/
-int serial_init (void)
+static int s3c4510b_serial_init(void)
{
#if CONFIG_SERIAL1 == 1
@@ -155,7 +155,7 @@ int serial_init (void)
/*
* Output a single byte to the serial port.
*/
-void serial_putc (const char c)
+static void s3c4510_serial_putc(const char c)
{
/* wait for room in the transmit FIFO */
while( !uart->m_stat.bf.txBufEmpty);
@@ -174,7 +174,7 @@ void serial_putc (const char c)
* Test if an input byte is ready from the serial port. Returns non-zero on
* success, 0 otherwise.
*/
-int serial_tstc (void)
+static int s3c4510b_serial_tstc(void)
{
return uart->m_stat.bf.rxReady;
}
@@ -184,7 +184,7 @@ int serial_tstc (void)
* otherwise. When the function is succesfull, the character read is
* written into its argument c.
*/
-int serial_getc (void)
+static int s3c4510b_serial_getc(void)
{
int rv;
@@ -197,7 +197,7 @@ int serial_getc (void)
}
}
-void serial_puts (const char *s)
+static void s3c4510b_serial_puts(const char *s)
{
while (*s) {
serial_putc (*s++);
@@ -210,3 +210,24 @@ void serial_puts (const char *s)
uart->m_ctrl.bf.sendBreak = 0;
}
+
+static struct serial_device s3c4510b_serial_drv = {
+ .name = "s3c4510b_serial",
+ .start = s3c4510b_serial_init,
+ .stop = NULL,
+ .setbrg = s3c4510b_serial_setbrg,
+ .putc = s3c4510b_serial_putc,
+ .puts = s3c4510b_serial_puts,
+ .getc = s3c4510b_serial_getc,
+ .tstc = s3c4510b_serial_tstc,
+};
+
+void s3c4510b_serial_initialize(void)
+{
+ serial_register(&s3c4510b_serial_drv);
+}
+
+__weak struct serial_device *default_serial_console(void)
+{
+ return &s3c4510b_serial_drv;
+}
diff --git a/drivers/serial/s3c64xx.c b/drivers/serial/s3c64xx.c
index a88e930945..9ab8a28d83 100644
--- a/drivers/serial/s3c64xx.c
+++ b/drivers/serial/s3c64xx.c
@@ -68,7 +68,7 @@ static const int udivslot[] = {
0xffdf,
};
-void serial_setbrg(void)
+static void s3c64xx_serial_setbrg(void)
{
s3c64xx_uart *const uart = s3c64xx_get_base_uart(UART_NR);
u32 pclk = get_PCLK();
@@ -88,7 +88,7 @@ void serial_setbrg(void)
* Initialise the serial port with the given baudrate. The settings
* are always 8 data bits, no parity, 1 stop bit, no start bits.
*/
-int serial_init(void)
+static int s3c64xx_serial_init(void)
{
s3c64xx_uart *const uart = s3c64xx_get_base_uart(UART_NR);
@@ -110,7 +110,7 @@ int serial_init(void)
* otherwise. When the function is succesfull, the character read is
* written into its argument c.
*/
-int serial_getc(void)
+static int s3c64xx_serial_getc(void)
{
s3c64xx_uart *const uart = s3c64xx_get_base_uart(UART_NR);
@@ -137,7 +137,7 @@ void enable_putc(void)
/*
* Output a single byte to the serial port.
*/
-void serial_putc(const char c)
+static void s3c64xx_serial_putc(const char c)
{
s3c64xx_uart *const uart = s3c64xx_get_base_uart(UART_NR);
@@ -159,15 +159,36 @@ void serial_putc(const char c)
/*
* Test whether a character is in the RX buffer
*/
-int serial_tstc(void)
+static int s3c64xx_serial_tstc(void)
{
s3c64xx_uart *const uart = s3c64xx_get_base_uart(UART_NR);
return uart->UTRSTAT & 0x1;
}
-void serial_puts(const char *s)
+static void s3c64xx_serial_puts(const char *s)
{
while (*s)
serial_putc(*s++);
}
+
+static struct serial_device s3c64xx_serial_drv = {
+ .name = "s3c64xx_serial",
+ .start = s3c64xx_serial_init,
+ .stop = NULL,
+ .setbrg = s3c64xx_serial_setbrg,
+ .putc = s3c64xx_serial_putc,
+ .puts = s3c64xx_serial_puts,
+ .getc = s3c64xx_serial_getc,
+ .tstc = s3c64xx_serial_tstc,
+};
+
+void s3c64xx_serial_initialize(void)
+{
+ serial_register(&s3c64xx_serial_drv);
+}
+
+__weak struct serial_device *default_serial_console(void)
+{
+ return &s3c64xx_serial_drv;
+}
diff --git a/drivers/serial/sandbox.c b/drivers/serial/sandbox.c
index 1927c167bb..cb19401df6 100644
--- a/drivers/serial/sandbox.c
+++ b/drivers/serial/sandbox.c
@@ -27,28 +27,30 @@
#include <common.h>
#include <os.h>
+#include <serial.h>
+#include <linux/compiler.h>
-int serial_init(void)
+static int sandbox_serial_init(void)
{
os_tty_raw(0);
return 0;
}
-void serial_setbrg(void)
+static void sandbox_serial_setbrg(void)
{
}
-void serial_putc(const char ch)
+static void sandbox_serial_putc(const char ch)
{
os_write(1, &ch, 1);
}
-void serial_puts(const char *str)
+static void sandbox_serial_puts(const char *str)
{
os_write(1, str, strlen(str));
}
-int serial_getc(void)
+static int sandbox_serial_getc(void)
{
char buf;
ssize_t count;
@@ -57,7 +59,28 @@ int serial_getc(void)
return count == 1 ? buf : 0;
}
-int serial_tstc(void)
+static int sandbox_serial_tstc(void)
{
return 0;
}
+
+static struct serial_device sandbox_serial_drv = {
+ .name = "sandbox_serial",
+ .start = sandbox_serial_init,
+ .stop = NULL,
+ .setbrg = sandbox_serial_setbrg,
+ .putc = sandbox_serial_putc,
+ .puts = sandbox_serial_puts,
+ .getc = sandbox_serial_getc,
+ .tstc = sandbox_serial_tstc,
+};
+
+void sandbox_serial_initialize(void)
+{
+ serial_register(&sandbox_serial_drv);
+}
+
+__weak struct serial_device *default_serial_console(void)
+{
+ return &sandbox_serial_drv;
+}
diff --git a/drivers/serial/serial.c b/drivers/serial/serial.c
index b10bab70d0..5bbf3aeb44 100644
--- a/drivers/serial/serial.c
+++ b/drivers/serial/serial.c
@@ -1,6 +1,6 @@
/*
- * (C) Copyright 2000
- * Rob Taylor, Flying Pig Systems. robt@flyingpig.com.
+ * (C) Copyright 2004
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* See file CREDITS for list of people who contributed to this
* project.
@@ -22,321 +22,341 @@
*/
#include <common.h>
-#include <linux/compiler.h>
-
-#include <ns16550.h>
-#ifdef CONFIG_NS87308
-#include <ns87308.h>
-#endif
-
-#if defined (CONFIG_SERIAL_MULTI)
#include <serial.h>
-#endif
+#include <stdio_dev.h>
+#include <post.h>
+#include <linux/compiler.h>
DECLARE_GLOBAL_DATA_PTR;
-#if !defined(CONFIG_CONS_INDEX)
-#if defined (CONFIG_SERIAL_MULTI)
-/* with CONFIG_SERIAL_MULTI we might have no console
- * on these devices
- */
-#else
-#error "No console index specified."
-#endif /* CONFIG_SERIAL_MULTI */
-#elif (CONFIG_CONS_INDEX < 1) || (CONFIG_CONS_INDEX > 4)
-#error "Invalid console index value."
-#endif
+static struct serial_device *serial_devices;
+static struct serial_device *serial_current;
-#if CONFIG_CONS_INDEX == 1 && !defined(CONFIG_SYS_NS16550_COM1)
-#error "Console port 1 defined but not configured."
-#elif CONFIG_CONS_INDEX == 2 && !defined(CONFIG_SYS_NS16550_COM2)
-#error "Console port 2 defined but not configured."
-#elif CONFIG_CONS_INDEX == 3 && !defined(CONFIG_SYS_NS16550_COM3)
-#error "Console port 3 defined but not configured."
-#elif CONFIG_CONS_INDEX == 4 && !defined(CONFIG_SYS_NS16550_COM4)
-#error "Console port 4 defined but not configured."
-#endif
+static void serial_null(void)
+{
+}
-/* Note: The port number specified in the functions is 1 based.
- * the array is 0 based.
- */
-static NS16550_t serial_ports[4] = {
-#ifdef CONFIG_SYS_NS16550_COM1
- (NS16550_t)CONFIG_SYS_NS16550_COM1,
-#else
- NULL,
-#endif
-#ifdef CONFIG_SYS_NS16550_COM2
- (NS16550_t)CONFIG_SYS_NS16550_COM2,
-#else
- NULL,
-#endif
-#ifdef CONFIG_SYS_NS16550_COM3
- (NS16550_t)CONFIG_SYS_NS16550_COM3,
-#else
- NULL,
-#endif
-#ifdef CONFIG_SYS_NS16550_COM4
- (NS16550_t)CONFIG_SYS_NS16550_COM4
-#else
- NULL
-#endif
-};
-
-#define PORT serial_ports[port-1]
-
-#if defined(CONFIG_SERIAL_MULTI)
-
-/* Multi serial device functions */
-#define DECLARE_ESERIAL_FUNCTIONS(port) \
- int eserial##port##_init (void) {\
- int clock_divisor; \
- clock_divisor = calc_divisor(serial_ports[port-1]); \
- NS16550_init(serial_ports[port-1], clock_divisor); \
- return(0);}\
- void eserial##port##_setbrg (void) {\
- serial_setbrg_dev(port);}\
- int eserial##port##_getc (void) {\
- return serial_getc_dev(port);}\
- int eserial##port##_tstc (void) {\
- return serial_tstc_dev(port);}\
- void eserial##port##_putc (const char c) {\
- serial_putc_dev(port, c);}\
- void eserial##port##_puts (const char *s) {\
- serial_puts_dev(port, s);}
-
-/* Serial device descriptor */
-#define INIT_ESERIAL_STRUCTURE(port, name) {\
- name,\
- eserial##port##_init,\
- NULL,\
- eserial##port##_setbrg,\
- eserial##port##_getc,\
- eserial##port##_tstc,\
- eserial##port##_putc,\
- eserial##port##_puts, }
-
-#endif /* CONFIG_SERIAL_MULTI */
-
-static int calc_divisor (NS16550_t port)
+#define serial_initfunc(name) \
+ void name(void) \
+ __attribute__((weak, alias("serial_null")));
+
+serial_initfunc(mpc8xx_serial_initialize);
+serial_initfunc(ns16550_serial_initialize);
+serial_initfunc(pxa_serial_initialize);
+serial_initfunc(s3c24xx_serial_initialize);
+serial_initfunc(s5p_serial_initialize);
+serial_initfunc(zynq_serial_initalize);
+serial_initfunc(bfin_serial_initialize);
+serial_initfunc(bfin_jtag_initialize);
+serial_initfunc(mpc512x_serial_initialize);
+serial_initfunc(uartlite_serial_initialize);
+serial_initfunc(au1x00_serial_initialize);
+serial_initfunc(asc_serial_initialize);
+serial_initfunc(jz_serial_initialize);
+serial_initfunc(mpc5xx_serial_initialize);
+serial_initfunc(mpc8220_serial_initialize);
+serial_initfunc(mpc8260_scc_serial_initialize);
+serial_initfunc(mpc8260_smc_serial_initialize);
+serial_initfunc(mpc85xx_serial_initialize);
+serial_initfunc(iop480_serial_initialize);
+serial_initfunc(leon2_serial_initialize);
+serial_initfunc(leon3_serial_initialize);
+serial_initfunc(marvell_serial_initialize);
+serial_initfunc(amirix_serial_initialize);
+serial_initfunc(bmw_serial_initialize);
+serial_initfunc(cogent_serial_initialize);
+serial_initfunc(cpci750_serial_initialize);
+serial_initfunc(evb64260_serial_initialize);
+serial_initfunc(ml2_serial_initialize);
+serial_initfunc(sconsole_serial_initialize);
+serial_initfunc(p3mx_serial_initialize);
+serial_initfunc(altera_jtag_serial_initialize);
+serial_initfunc(altera_serial_initialize);
+serial_initfunc(atmel_serial_initialize);
+serial_initfunc(lpc32xx_serial_initialize);
+serial_initfunc(mcf_serial_initialize);
+serial_initfunc(ns9750_serial_initialize);
+serial_initfunc(oc_serial_initialize);
+serial_initfunc(s3c4510b_serial_initialize);
+serial_initfunc(s3c64xx_serial_initialize);
+serial_initfunc(sandbox_serial_initialize);
+serial_initfunc(clps7111_serial_initialize);
+serial_initfunc(imx_serial_initialize);
+serial_initfunc(ixp_serial_initialize);
+serial_initfunc(ks8695_serial_initialize);
+serial_initfunc(lh7a40x_serial_initialize);
+serial_initfunc(lpc2292_serial_initialize);
+serial_initfunc(max3100_serial_initialize);
+serial_initfunc(mxc_serial_initialize);
+serial_initfunc(netarm_serial_initialize);
+serial_initfunc(pl01x_serial_initialize);
+serial_initfunc(s3c44b0_serial_initialize);
+serial_initfunc(sa1100_serial_initialize);
+serial_initfunc(sh_serial_initialize);
+
+void serial_register(struct serial_device *dev)
{
-#ifdef CONFIG_OMAP1510
- /* If can't cleanly clock 115200 set div to 1 */
- if ((CONFIG_SYS_NS16550_CLK == 12000000) && (gd->baudrate == 115200)) {
- port->osc_12m_sel = OSC_12M_SEL; /* enable 6.5 * divisor */
- return (1); /* return 1 for base divisor */
- }
- port->osc_12m_sel = 0; /* clear if previsouly set */
-#endif
-#ifdef CONFIG_OMAP1610
- /* If can't cleanly clock 115200 set div to 1 */
- if ((CONFIG_SYS_NS16550_CLK == 48000000) && (gd->baudrate == 115200)) {
- return (26); /* return 26 for base divisor */
- }
+#ifdef CONFIG_NEEDS_MANUAL_RELOC
+ if (dev->start)
+ dev->start += gd->reloc_off;
+ if (dev->stop)
+ dev->stop += gd->reloc_off;
+ if (dev->setbrg)
+ dev->setbrg += gd->reloc_off;
+ if (dev->getc)
+ dev->getc += gd->reloc_off;
+ if (dev->tstc)
+ dev->tstc += gd->reloc_off;
+ if (dev->putc)
+ dev->putc += gd->reloc_off;
+ if (dev->puts)
+ dev->puts += gd->reloc_off;
#endif
-#ifdef CONFIG_APTIX
-#define MODE_X_DIV 13
-#else
-#define MODE_X_DIV 16
-#endif
+ dev->next = serial_devices;
+ serial_devices = dev;
+}
- /* Compute divisor value. Normally, we should simply return:
- * CONFIG_SYS_NS16550_CLK) / MODE_X_DIV / gd->baudrate
- * but we need to round that value by adding 0.5.
- * Rounding is especially important at high baud rates.
- */
- return (CONFIG_SYS_NS16550_CLK + (gd->baudrate * (MODE_X_DIV / 2))) /
- (MODE_X_DIV * gd->baudrate);
+void serial_initialize(void)
+{
+ mpc8xx_serial_initialize();
+ ns16550_serial_initialize();
+ pxa_serial_initialize();
+ s3c24xx_serial_initialize();
+ s5p_serial_initialize();
+ mpc512x_serial_initialize();
+ bfin_serial_initialize();
+ bfin_jtag_initialize();
+ uartlite_serial_initialize();
+ zynq_serial_initalize();
+ au1x00_serial_initialize();
+ asc_serial_initialize();
+ jz_serial_initialize();
+ mpc5xx_serial_initialize();
+ mpc8220_serial_initialize();
+ mpc8260_scc_serial_initialize();
+ mpc8260_smc_serial_initialize();
+ mpc85xx_serial_initialize();
+ iop480_serial_initialize();
+ leon2_serial_initialize();
+ leon3_serial_initialize();
+ marvell_serial_initialize();
+ amirix_serial_initialize();
+ bmw_serial_initialize();
+ cogent_serial_initialize();
+ cpci750_serial_initialize();
+ evb64260_serial_initialize();
+ ml2_serial_initialize();
+ sconsole_serial_initialize();
+ p3mx_serial_initialize();
+ altera_jtag_serial_initialize();
+ altera_serial_initialize();
+ atmel_serial_initialize();
+ lpc32xx_serial_initialize();
+ mcf_serial_initialize();
+ ns9750_serial_initialize();
+ oc_serial_initialize();
+ s3c4510b_serial_initialize();
+ s3c64xx_serial_initialize();
+ sandbox_serial_initialize();
+ clps7111_serial_initialize();
+ imx_serial_initialize();
+ ixp_serial_initialize();
+ ks8695_serial_initialize();
+ lh7a40x_serial_initialize();
+ lpc2292_serial_initialize();
+ max3100_serial_initialize();
+ mxc_serial_initialize();
+ netarm_serial_initialize();
+ pl01x_serial_initialize();
+ s3c44b0_serial_initialize();
+ sa1100_serial_initialize();
+ sh_serial_initialize();
+
+ serial_assign(default_serial_console()->name);
}
-#if !defined(CONFIG_SERIAL_MULTI)
-int serial_init (void)
+void serial_stdio_init(void)
{
- int clock_divisor;
+ struct stdio_dev dev;
+ struct serial_device *s = serial_devices;
-#ifdef CONFIG_NS87308
- initialise_ns87308();
-#endif
+ while (s) {
+ memset(&dev, 0, sizeof(dev));
-#ifdef CONFIG_SYS_NS16550_COM1
- clock_divisor = calc_divisor(serial_ports[0]);
- NS16550_init(serial_ports[0], clock_divisor);
-#endif
-#ifdef CONFIG_SYS_NS16550_COM2
- clock_divisor = calc_divisor(serial_ports[1]);
- NS16550_init(serial_ports[1], clock_divisor);
-#endif
-#ifdef CONFIG_SYS_NS16550_COM3
- clock_divisor = calc_divisor(serial_ports[2]);
- NS16550_init(serial_ports[2], clock_divisor);
-#endif
-#ifdef CONFIG_SYS_NS16550_COM4
- clock_divisor = calc_divisor(serial_ports[3]);
- NS16550_init(serial_ports[3], clock_divisor);
-#endif
+ strcpy(dev.name, s->name);
+ dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT;
- return (0);
-}
-#endif
+ dev.start = s->start;
+ dev.stop = s->stop;
+ dev.putc = s->putc;
+ dev.puts = s->puts;
+ dev.getc = s->getc;
+ dev.tstc = s->tstc;
-void
-_serial_putc(const char c,const int port)
-{
- if (c == '\n')
- NS16550_putc(PORT, '\r');
+ stdio_register(&dev);
- NS16550_putc(PORT, c);
+ s = s->next;
+ }
}
-void
-_serial_putc_raw(const char c,const int port)
+int serial_assign(const char *name)
{
- NS16550_putc(PORT, c);
-}
+ struct serial_device *s;
-void
-_serial_puts (const char *s,const int port)
-{
- while (*s) {
- _serial_putc (*s++,port);
+ for (s = serial_devices; s; s = s->next) {
+ if (strcmp(s->name, name) == 0) {
+ serial_current = s;
+ return 0;
+ }
}
-}
-
-int
-_serial_getc(const int port)
-{
- return NS16550_getc(PORT);
+ return 1;
}
-int
-_serial_tstc(const int port)
+void serial_reinit_all(void)
{
- return NS16550_tstc(PORT);
+ struct serial_device *s;
+
+ for (s = serial_devices; s; s = s->next)
+ s->start();
}
-void
-_serial_setbrg (const int port)
+static struct serial_device *get_current(void)
{
- int clock_divisor;
+ struct serial_device *dev;
- clock_divisor = calc_divisor(PORT);
- NS16550_reinit(PORT, clock_divisor);
-}
+ if (!(gd->flags & GD_FLG_RELOC) || !serial_current) {
+ dev = default_serial_console();
-#if defined(CONFIG_SERIAL_MULTI)
-static inline void
-serial_putc_dev(unsigned int dev_index,const char c)
-{
- _serial_putc(c,dev_index);
-}
+ /* We must have a console device */
+ if (!dev) {
+#ifdef CONFIG_SPL_BUILD
+ puts("Cannot find console\n");
+ hang();
#else
-void
-serial_putc(const char c)
-{
- _serial_putc(c,CONFIG_CONS_INDEX);
-}
+ panic("Cannot find console\n");
#endif
-
-#if defined(CONFIG_SERIAL_MULTI)
-static inline void
-serial_putc_raw_dev(unsigned int dev_index,const char c)
-{
- _serial_putc_raw(c,dev_index);
-}
-#else
-void
-serial_putc_raw(const char c)
-{
- _serial_putc_raw(c,CONFIG_CONS_INDEX);
+ }
+ } else
+ dev = serial_current;
+ return dev;
}
-#endif
-#if defined(CONFIG_SERIAL_MULTI)
-static inline void
-serial_puts_dev(unsigned int dev_index,const char *s)
-{
- _serial_puts(s,dev_index);
-}
-#else
-void
-serial_puts(const char *s)
+int serial_init(void)
{
- _serial_puts(s,CONFIG_CONS_INDEX);
+ return get_current()->start();
}
-#endif
-#if defined(CONFIG_SERIAL_MULTI)
-static inline int
-serial_getc_dev(unsigned int dev_index)
+void serial_setbrg(void)
{
- return _serial_getc(dev_index);
+ get_current()->setbrg();
}
-#else
-int
-serial_getc(void)
-{
- return _serial_getc(CONFIG_CONS_INDEX);
-}
-#endif
-#if defined(CONFIG_SERIAL_MULTI)
-static inline int
-serial_tstc_dev(unsigned int dev_index)
+int serial_getc(void)
{
- return _serial_tstc(dev_index);
+ return get_current()->getc();
}
-#else
-int
-serial_tstc(void)
+
+int serial_tstc(void)
{
- return _serial_tstc(CONFIG_CONS_INDEX);
+ return get_current()->tstc();
}
-#endif
-#if defined(CONFIG_SERIAL_MULTI)
-static inline void
-serial_setbrg_dev(unsigned int dev_index)
+void serial_putc(const char c)
{
- _serial_setbrg(dev_index);
+ get_current()->putc(c);
}
-#else
-void
-serial_setbrg(void)
+
+void serial_puts(const char *s)
{
- _serial_setbrg(CONFIG_CONS_INDEX);
+ get_current()->puts(s);
}
-#endif
-#if defined(CONFIG_SERIAL_MULTI)
-
-DECLARE_ESERIAL_FUNCTIONS(1);
-struct serial_device eserial1_device =
- INIT_ESERIAL_STRUCTURE(1, "eserial0");
-DECLARE_ESERIAL_FUNCTIONS(2);
-struct serial_device eserial2_device =
- INIT_ESERIAL_STRUCTURE(2, "eserial1");
-DECLARE_ESERIAL_FUNCTIONS(3);
-struct serial_device eserial3_device =
- INIT_ESERIAL_STRUCTURE(3, "eserial2");
-DECLARE_ESERIAL_FUNCTIONS(4);
-struct serial_device eserial4_device =
- INIT_ESERIAL_STRUCTURE(4, "eserial3");
-
-__weak struct serial_device *default_serial_console(void)
+#if CONFIG_POST & CONFIG_SYS_POST_UART
+static const int bauds[] = CONFIG_SYS_BAUDRATE_TABLE;
+
+/* Mark weak until post/cpu/.../uart.c migrate over */
+__weak
+int uart_post_test(int flags)
{
-#if CONFIG_CONS_INDEX == 1
- return &eserial1_device;
-#elif CONFIG_CONS_INDEX == 2
- return &eserial2_device;
-#elif CONFIG_CONS_INDEX == 3
- return &eserial3_device;
-#elif CONFIG_CONS_INDEX == 4
- return &eserial4_device;
-#else
-#error "Bad CONFIG_CONS_INDEX."
-#endif
-}
+ unsigned char c;
+ int ret, saved_baud, b;
+ struct serial_device *saved_dev, *s;
+ bd_t *bd = gd->bd;
+
+ /* Save current serial state */
+ ret = 0;
+ saved_dev = serial_current;
+ saved_baud = bd->bi_baudrate;
+
+ for (s = serial_devices; s; s = s->next) {
+ /* If this driver doesn't support loop back, skip it */
+ if (!s->loop)
+ continue;
+
+ /* Test the next device */
+ serial_current = s;
+
+ ret = serial_init();
+ if (ret)
+ goto done;
+
+ /* Consume anything that happens to be queued */
+ while (serial_tstc())
+ serial_getc();
+
+ /* Enable loop back */
+ s->loop(1);
+
+ /* Test every available baud rate */
+ for (b = 0; b < ARRAY_SIZE(bauds); ++b) {
+ bd->bi_baudrate = bauds[b];
+ serial_setbrg();
+
+ /*
+ * Stick to printable chars to avoid issues:
+ * - terminal corruption
+ * - serial program reacting to sequences and sending
+ * back random extra data
+ * - most serial drivers add in extra chars (like \r\n)
+ */
+ for (c = 0x20; c < 0x7f; ++c) {
+ /* Send it out */
+ serial_putc(c);
+
+ /* Make sure it's the same one */
+ ret = (c != serial_getc());
+ if (ret) {
+ s->loop(0);
+ goto done;
+ }
+
+ /* Clean up the output in case it was sent */
+ serial_putc('\b');
+ ret = ('\b' != serial_getc());
+ if (ret) {
+ s->loop(0);
+ goto done;
+ }
+ }
+ }
+
+ /* Disable loop back */
+ s->loop(0);
+
+ /* XXX: There is no serial_stop() !? */
+ if (s->stop)
+ s->stop();
+ }
+
+ done:
+ /* Restore previous serial state */
+ serial_current = saved_dev;
+ bd->bi_baudrate = saved_baud;
+ serial_reinit_all();
+ serial_setbrg();
-#endif /* CONFIG_SERIAL_MULTI */
+ return ret;
+}
+#endif
diff --git a/drivers/serial/serial_clps7111.c b/drivers/serial/serial_clps7111.c
index a6aecadd13..65473e8608 100644
--- a/drivers/serial/serial_clps7111.c
+++ b/drivers/serial/serial_clps7111.c
@@ -33,7 +33,7 @@
DECLARE_GLOBAL_DATA_PTR;
-void serial_setbrg (void)
+static void clps7111_serial_setbrg(void)
{
unsigned int reg = 0;
@@ -63,7 +63,7 @@ void serial_setbrg (void)
* are always 8 data bits, no parity, 1 stop bit, no start bits.
*
*/
-int serial_init (void)
+static int clps7111_serial_init(void)
{
serial_setbrg ();
@@ -74,7 +74,7 @@ int serial_init (void)
/*
* Output a single byte to the serial port.
*/
-void serial_putc (const char c)
+static void clps7111_serial_putc(const char c)
{
int tmo;
@@ -95,7 +95,7 @@ void serial_putc (const char c)
* otherwise. When the function is succesfull, the character read is
* written into its argument c.
*/
-int serial_tstc (void)
+static int clps7111_serial_tstc(void)
{
return !(IO_SYSFLG1 & SYSFLG1_URXFE);
}
@@ -105,17 +105,37 @@ int serial_tstc (void)
* otherwise. When the function is succesfull, the character read is
* written into its argument c.
*/
-int serial_getc (void)
+static int clps7111_serial_getc(void)
{
while (IO_SYSFLG1 & SYSFLG1_URXFE);
return IO_UARTDR1 & 0xff;
}
-void
-serial_puts (const char *s)
+static void clps7111_serial_puts(const char *s)
{
while (*s) {
serial_putc (*s++);
}
}
+
+static struct serial_device clps7111_serial_drv = {
+ .name = "clps7111_serial",
+ .start = clps7111_serial_init,
+ .stop = NULL,
+ .setbrg = clps7111_serial_setbrg,
+ .putc = clps7111_serial_putc,
+ .puts = clps7111_serial_puts,
+ .getc = clps7111_serial_getc,
+ .tstc = clps7111_serial_tstc,
+};
+
+void clps7111_serial_initialize(void)
+{
+ serial_register(&clps7111_serial_drv);
+}
+
+__weak struct serial_device *default_serial_console(void)
+{
+ return &clps7111_serial_drv;
+}
diff --git a/drivers/serial/serial_imx.c b/drivers/serial/serial_imx.c
index b9ca748f69..6c075b5b91 100644
--- a/drivers/serial/serial_imx.c
+++ b/drivers/serial/serial_imx.c
@@ -19,6 +19,8 @@
#include <common.h>
#include <asm/arch/imx-regs.h>
+#include <serial.h>
+#include <linux/compiler.h>
#if defined CONFIG_IMX_SERIAL1
#define UART_BASE IMX_UART1_BASE
@@ -50,7 +52,7 @@ struct imx_serial {
DECLARE_GLOBAL_DATA_PTR;
-void serial_setbrg (void)
+static void imx_serial_setbrg(void)
{
serial_init();
}
@@ -62,7 +64,7 @@ extern void imx_gpio_mode(int gpio_mode);
* are always 8 data bits, no parity, 1 stop bit, no start bits.
*
*/
-int serial_init (void)
+static int imx_serial_init(void)
{
volatile struct imx_serial* base = (struct imx_serial *)UART_BASE;
unsigned int ufcr_rfdiv;
@@ -163,7 +165,7 @@ int serial_init (void)
* otherwise. When the function is successful, the character read is
* written into its argument c.
*/
-int serial_getc (void)
+static int imx_serial_getc(void)
{
volatile struct imx_serial* base = (struct imx_serial *)UART_BASE;
unsigned char ch;
@@ -185,7 +187,7 @@ int hwflow_onoff(int on)
/*
* Output a single byte to the serial port.
*/
-void serial_putc (const char c)
+static void imx_serial_putc(const char c)
{
volatile struct imx_serial* base = (struct imx_serial *)UART_BASE;
@@ -202,7 +204,7 @@ void serial_putc (const char c)
/*
* Test whether a character is in the RX buffer
*/
-int serial_tstc (void)
+static int imx_serial_tstc(void)
{
volatile struct imx_serial* base = (struct imx_serial *)UART_BASE;
@@ -212,10 +214,30 @@ int serial_tstc (void)
return 1;
}
-void
-serial_puts (const char *s)
+static void imx_serial_puts(const char *s)
{
while (*s) {
serial_putc (*s++);
}
}
+
+static struct serial_device imx_serial_drv = {
+ .name = "imx_serial",
+ .start = imx_serial_init,
+ .stop = NULL,
+ .setbrg = imx_serial_setbrg,
+ .putc = imx_serial_putc,
+ .puts = imx_serial_puts,
+ .getc = imx_serial_getc,
+ .tstc = imx_serial_tstc,
+};
+
+void imx_serial_initialize(void)
+{
+ serial_register(&imx_serial_drv);
+}
+
+__weak struct serial_device *default_serial_console(void)
+{
+ return &imx_serial_drv;
+}
diff --git a/drivers/serial/serial_ixp.c b/drivers/serial/serial_ixp.c
index a9acd476c4..c8b3658d47 100644
--- a/drivers/serial/serial_ixp.c
+++ b/drivers/serial/serial_ixp.c
@@ -31,6 +31,8 @@
#include <common.h>
#include <asm/arch/ixp425.h>
#include <watchdog.h>
+#include <serial.h>
+#include <linux/compiler.h>
/*
* 14.7456 MHz
@@ -41,7 +43,7 @@
DECLARE_GLOBAL_DATA_PTR;
-void serial_setbrg (void)
+static void ixp_serial_setbrg(void)
{
unsigned int quot = 0;
int uart = CONFIG_SYS_IXP425_CONSOLE;
@@ -72,7 +74,7 @@ void serial_setbrg (void)
* are always 8 data bits, no parity, 1 stop bit, no start bits.
*
*/
-int serial_init (void)
+static int ixp_serial_init(void)
{
serial_setbrg ();
@@ -83,7 +85,7 @@ int serial_init (void)
/*
* Output a single byte to the serial port.
*/
-void serial_putc (const char c)
+static void ixp_serial_putc(const char c)
{
/* wait for room in the tx FIFO on UART */
while ((LSR(CONFIG_SYS_IXP425_CONSOLE) & LSR_TEMT) == 0)
@@ -101,7 +103,7 @@ void serial_putc (const char c)
* otherwise. When the function is succesfull, the character read is
* written into its argument c.
*/
-int serial_tstc (void)
+static int ixp_serial_tstc(void)
{
return LSR(CONFIG_SYS_IXP425_CONSOLE) & LSR_DR;
}
@@ -111,7 +113,7 @@ int serial_tstc (void)
* otherwise. When the function is succesfull, the character read is
* written into its argument c.
*/
-int serial_getc (void)
+static int ixp_serial_getc(void)
{
while (!(LSR(CONFIG_SYS_IXP425_CONSOLE) & LSR_DR))
WATCHDOG_RESET(); /* Reset HW Watchdog, if needed */
@@ -119,10 +121,30 @@ int serial_getc (void)
return (char) RBR(CONFIG_SYS_IXP425_CONSOLE) & 0xff;
}
-void
-serial_puts (const char *s)
+static void ixp_serial_puts(const char *s)
{
while (*s) {
serial_putc (*s++);
}
}
+
+static struct serial_device ixp_serial_drv = {
+ .name = "ixp_serial",
+ .start = ixp_serial_init,
+ .stop = NULL,
+ .setbrg = ixp_serial_setbrg,
+ .putc = ixp_serial_putc,
+ .puts = ixp_serial_puts,
+ .getc = ixp_serial_getc,
+ .tstc = ixp_serial_tstc,
+};
+
+void ixp_serial_initialize(void)
+{
+ serial_register(&ixp_serial_drv);
+}
+
+__weak struct serial_device *default_serial_console(void)
+{
+ return &ixp_serial_drv;
+}
diff --git a/drivers/serial/serial_ks8695.c b/drivers/serial/serial_ks8695.c
index aacd1be630..60e8007201 100644
--- a/drivers/serial/serial_ks8695.c
+++ b/drivers/serial/serial_ks8695.c
@@ -20,6 +20,8 @@
#include <common.h>
#include <asm/arch/platform.h>
+#include <serial.h>
+#include <linux/compiler.h>
#ifndef CONFIG_SERIAL1
#error "Bad: you didn't configure serial ..."
@@ -54,7 +56,7 @@ struct ks8695uart {
int serial_console = 1;
-void serial_setbrg(void)
+static void ks8695_serial_setbrg(void)
{
volatile struct ks8695uart *uartp = KS8695_UART_ADDR;
@@ -63,14 +65,14 @@ void serial_setbrg(void)
uartp->LCR = KS8695_UART_LINEC_WLEN8;
}
-int serial_init(void)
+static int ks8695_serial_init(void)
{
serial_console = 1;
serial_setbrg();
return 0;
}
-void serial_raw_putc(const char c)
+static void ks8695_serial_raw_putc(const char c)
{
volatile struct ks8695uart *uartp = KS8695_UART_ADDR;
int i;
@@ -83,16 +85,16 @@ void serial_raw_putc(const char c)
uartp->TX = c;
}
-void serial_putc(const char c)
+static void ks8695_serial_putc(const char c)
{
if (serial_console) {
- serial_raw_putc(c);
+ ks8695_serial_raw_putc(c);
if (c == '\n')
- serial_raw_putc('\r');
+ ks8695_serial_raw_putc('\r');
}
}
-int serial_tstc(void)
+static int ks8695_serial_tstc(void)
{
volatile struct ks8695uart *uartp = KS8695_UART_ADDR;
if (serial_console)
@@ -100,14 +102,14 @@ int serial_tstc(void)
return 0;
}
-void serial_puts(const char *s)
+static void ks8695_serial_puts(const char *s)
{
char c;
while ((c = *s++) != 0)
serial_putc(c);
}
-int serial_getc(void)
+static int ks8695_serial_getc(void)
{
volatile struct ks8695uart *uartp = KS8695_UART_ADDR;
@@ -115,3 +117,24 @@ int serial_getc(void)
;
return (uartp->RX);
}
+
+static struct serial_device ks8695_serial_drv = {
+ .name = "ks8695_serial",
+ .start = ks8695_serial_init,
+ .stop = NULL,
+ .setbrg = ks8695_serial_setbrg,
+ .putc = ks8695_serial_putc,
+ .puts = ks8695_serial_puts,
+ .getc = ks8695_serial_getc,
+ .tstc = ks8695_serial_tstc,
+};
+
+void ks8695_serial_initialize(void)
+{
+ serial_register(&ks8695_serial_drv);
+}
+
+__weak struct serial_device *default_serial_console(void)
+{
+ return &ks8695_serial_drv;
+}
diff --git a/drivers/serial/serial_lh7a40x.c b/drivers/serial/serial_lh7a40x.c
index 4767489aef..6c9628581b 100644
--- a/drivers/serial/serial_lh7a40x.c
+++ b/drivers/serial/serial_lh7a40x.c
@@ -33,7 +33,7 @@ DECLARE_GLOBAL_DATA_PTR;
# error "No console configured ... "
#endif
-void serial_setbrg (void)
+static void lh7a40x_serial_setbrg(void)
{
lh7a40x_uart_t* uart = LH7A40X_UART_PTR(UART_CONSOLE);
int i;
@@ -61,7 +61,7 @@ void serial_setbrg (void)
* are always 8 data bits, no parity, 1 stop bit, no start bits.
*
*/
-int serial_init (void)
+static int lh7a40x_serial_init(void)
{
lh7a40x_uart_t* uart = LH7A40X_UART_PTR(UART_CONSOLE);
@@ -95,7 +95,7 @@ int serial_init (void)
* otherwise. When the function is succesfull, the character read is
* written into its argument c.
*/
-int serial_getc (void)
+static int lh7a40x_serial_getc(void)
{
lh7a40x_uart_t* uart = LH7A40X_UART_PTR(UART_CONSOLE);
@@ -141,7 +141,7 @@ void enable_putc(void)
/*
* Output a single byte to the serial port.
*/
-void serial_putc (const char c)
+static void lh7a40x_serial_putc(const char c)
{
lh7a40x_uart_t* uart = LH7A40X_UART_PTR(UART_CONSOLE);
@@ -168,17 +168,37 @@ void serial_putc (const char c)
/*
* Test whether a character is in the RX buffer
*/
-int serial_tstc (void)
+static int lh7a40x_serial_tstc(void)
{
lh7a40x_uart_t* uart = LH7A40X_UART_PTR(UART_CONSOLE);
return(!(uart->status & UART_RXFE));
}
-void
-serial_puts (const char *s)
+static void lh7a40x_serial_puts(const char *s)
{
while (*s) {
serial_putc (*s++);
}
}
+
+static struct serial_device lh7a40x_serial_drv = {
+ .name = "lh7a40x_serial",
+ .start = lh7a40x_serial_init,
+ .stop = NULL,
+ .setbrg = lh7a40x_serial_setbrg,
+ .putc = lh7a40x_serial_putc,
+ .puts = lh7a40x_serial_puts,
+ .getc = lh7a40x_serial_getc,
+ .tstc = lh7a40x_serial_tstc,
+};
+
+void lh7a40x_serial_initialize(void)
+{
+ serial_register(&lh7a40x_serial_drv);
+}
+
+__weak struct serial_device *default_serial_console(void)
+{
+ return &lh7a40x_serial_drv;
+}
diff --git a/drivers/serial/serial_lpc2292.c b/drivers/serial/serial_lpc2292.c
index e3a60b6cb4..fcab20280e 100644
--- a/drivers/serial/serial_lpc2292.c
+++ b/drivers/serial/serial_lpc2292.c
@@ -33,7 +33,7 @@
DECLARE_GLOBAL_DATA_PTR;
-void serial_setbrg (void)
+static void lpc2292_serial_setbrg(void)
{
unsigned short divisor = 0;
@@ -57,7 +57,7 @@ void serial_setbrg (void)
PUT8(U0FCR, 1); /* Enable RX and TX FIFOs */
}
-int serial_init (void)
+static int lpc2292_serial_init(void)
{
unsigned long pinsel0;
@@ -71,7 +71,7 @@ int serial_init (void)
return (0);
}
-void serial_putc (const char c)
+static void lpc2292_serial_putc(const char c)
{
if (c == '\n')
{
@@ -83,14 +83,13 @@ void serial_putc (const char c)
PUT8(U0THR, c);
}
-int serial_getc (void)
+static int lpc2292_serial_getc(void)
{
while((GET8(U0LSR) & 1) == 0);
return GET8(U0RBR);
}
-void
-serial_puts (const char *s)
+static void lpc2292_serial_puts(const char *s)
{
while (*s) {
serial_putc (*s++);
@@ -98,7 +97,28 @@ serial_puts (const char *s)
}
/* Test if there is a byte to read */
-int serial_tstc (void)
+static int lpc2292_serial_tstc(void)
{
return (GET8(U0LSR) & 1);
}
+
+static struct serial_device lpc2292_serial_drv = {
+ .name = "lpc2292_serial",
+ .start = lpc2292_serial_init,
+ .stop = NULL,
+ .setbrg = lpc2292_serial_setbrg,
+ .putc = lpc2292_serial_putc,
+ .puts = lpc2292_serial_puts,
+ .getc = lpc2292_serial_getc,
+ .tstc = lpc2292_serial_tstc,
+};
+
+void lpc2292_serial_initialize(void)
+{
+ serial_register(&lpc2292_serial_drv);
+}
+
+__weak struct serial_device *default_serial_console(void)
+{
+ return &lpc2292_serial_drv;
+}
diff --git a/drivers/serial/serial_max3100.c b/drivers/serial/serial_max3100.c
index 4abc27109b..3533cfc6d7 100644
--- a/drivers/serial/serial_max3100.c
+++ b/drivers/serial/serial_max3100.c
@@ -25,6 +25,8 @@
#include <common.h>
#include <watchdog.h>
+#include <serial.h>
+#include <linux/compiler.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -149,7 +151,7 @@ static int rxfifo_in;
static int rxfifo_out;
static unsigned char rxfifo_buf[16];
-static void max3100_putc(int c)
+static void max3100_serial_putc_raw(int c)
{
unsigned int rx;
@@ -164,7 +166,7 @@ static void max3100_putc(int c)
}
}
-static int max3100_getc(void)
+static int max3100_serial_getc(void)
{
int c;
unsigned int rx;
@@ -190,7 +192,7 @@ static int max3100_getc(void)
return c;
}
-static int max3100_tstc(void)
+static int max3100_serial_tstc(void)
{
unsigned int rx;
@@ -213,7 +215,7 @@ static int max3100_tstc(void)
return 1;
}
-int serial_init(void)
+static int max3100_serial_init(void)
{
unsigned int wconf, rconf;
int i;
@@ -268,31 +270,41 @@ int serial_init(void)
return (0);
}
-void serial_putc(const char c)
+static void max3100_serial_putc(const char c)
{
if (c == '\n')
- max3100_putc('\r');
+ max3100_serial_putc_raw('\r');
- max3100_putc(c);
+ max3100_serial_putc_raw(c);
}
-void serial_puts(const char *s)
+static void max3100_serial_puts(const char *s)
{
while (*s)
- serial_putc (*s++);
+ max3100_serial_putc_raw(*s++);
}
-int serial_getc(void)
+static void max3100_serial_setbrg(void)
{
- return max3100_getc();
}
-int serial_tstc(void)
+static struct serial_device max3100_serial_drv = {
+ .name = "max3100_serial",
+ .start = max3100_serial_init,
+ .stop = NULL,
+ .setbrg = max3100_serial_setbrg,
+ .putc = max3100_serial_putc,
+ .puts = max3100_serial_puts,
+ .getc = max3100_serial_getc,
+ .tstc = max3100_serial_tstc,
+};
+
+void max3100_serial_initialize(void)
{
- return max3100_tstc();
+ serial_register(&max3100_serial_drv);
}
-/* XXX WTF? */
-void serial_setbrg(void)
+__weak struct serial_device *default_serial_console(void)
{
+ return &max3100_serial_drv;
}
diff --git a/drivers/serial/serial_mxc.c b/drivers/serial/serial_mxc.c
index af00b9c0ec..b0612f5aca 100644
--- a/drivers/serial/serial_mxc.c
+++ b/drivers/serial/serial_mxc.c
@@ -21,6 +21,8 @@
#include <watchdog.h>
#include <asm/arch/imx-regs.h>
#include <asm/arch/clock.h>
+#include <serial.h>
+#include <linux/compiler.h>
#define __REG(x) (*((volatile u32 *)(x)))
@@ -30,10 +32,6 @@
#define UART_PHYS CONFIG_MXC_UART_BASE
-#ifdef CONFIG_SERIAL_MULTI
-#warning "MXC driver does not support MULTI serials."
-#endif
-
/* Register definitions */
#define URXD 0x0 /* Receiver Register */
#define UTXD 0x40 /* Transmitter Register */
@@ -145,7 +143,7 @@
DECLARE_GLOBAL_DATA_PTR;
-void serial_setbrg (void)
+static void mxc_serial_setbrg(void)
{
u32 clk = imx_get_uartclk();
@@ -158,14 +156,14 @@ void serial_setbrg (void)
}
-int serial_getc (void)
+static int mxc_serial_getc(void)
{
while (__REG(UART_PHYS + UTS) & UTS_RXEMPTY)
WATCHDOG_RESET();
return (__REG(UART_PHYS + URXD) & URXD_RX_DATA); /* mask out status from upper word */
}
-void serial_putc (const char c)
+static void mxc_serial_putc(const char c)
{
__REG(UART_PHYS + UTXD) = c;
@@ -181,7 +179,7 @@ void serial_putc (const char c)
/*
* Test whether a character is in the RX buffer
*/
-int serial_tstc (void)
+static int mxc_serial_tstc(void)
{
/* If receive fifo is empty, return false */
if (__REG(UART_PHYS + UTS) & UTS_RXEMPTY)
@@ -189,8 +187,7 @@ int serial_tstc (void)
return 1;
}
-void
-serial_puts (const char *s)
+static void mxc_serial_puts(const char *s)
{
while (*s) {
serial_putc (*s++);
@@ -202,7 +199,7 @@ serial_puts (const char *s)
* are always 8 data bits, no parity, 1 stop bit, no start bits.
*
*/
-int serial_init (void)
+static int mxc_serial_init(void)
{
__REG(UART_PHYS + UCR1) = 0x0;
__REG(UART_PHYS + UCR2) = 0x0;
@@ -224,3 +221,24 @@ int serial_init (void)
return 0;
}
+
+static struct serial_device mxc_serial_drv = {
+ .name = "mxc_serial",
+ .start = mxc_serial_init,
+ .stop = NULL,
+ .setbrg = mxc_serial_setbrg,
+ .putc = mxc_serial_putc,
+ .puts = mxc_serial_puts,
+ .getc = mxc_serial_getc,
+ .tstc = mxc_serial_tstc,
+};
+
+void mxc_serial_initialize(void)
+{
+ serial_register(&mxc_serial_drv);
+}
+
+__weak struct serial_device *default_serial_console(void)
+{
+ return &mxc_serial_drv;
+}
diff --git a/drivers/serial/serial_netarm.c b/drivers/serial/serial_netarm.c
index d04790d270..d30adc3183 100644
--- a/drivers/serial/serial_netarm.c
+++ b/drivers/serial/serial_netarm.c
@@ -59,7 +59,7 @@ extern void _netarm_led_FAIL1(void);
/*
* Setup both serial i/f with given baudrate
*/
-void serial_setbrg (void)
+static void netarm_serial_setbrg(void)
{
/* set 0 ... make sure pins are configured for serial */
#if !defined(CONFIG_NETARM_NS7520)
@@ -108,7 +108,7 @@ void serial_setbrg (void)
* Initialise the serial port with the given baudrate. The settings
* are always 8 data bits, no parity, 1 stop bit, no start bits.
*/
-int serial_init (void)
+static int netarm_serial_init(void)
{
serial_setbrg ();
return 0;
@@ -118,7 +118,7 @@ int serial_init (void)
/*
* Output a single byte to the serial port.
*/
-void serial_putc (const char c)
+static void netarm_serial_putc(const char c)
{
volatile unsigned char *fifo;
@@ -135,7 +135,7 @@ void serial_putc (const char c)
* Test of a single byte from the serial port. Returns 1 on success, 0
* otherwise.
*/
-int serial_tstc(void)
+static int netarm_serial_tstc(void)
{
return serial_reg_ch1->status_a & NETARM_SER_STATA_RX_RDY;
}
@@ -144,7 +144,7 @@ int serial_tstc(void)
* Read a single byte from the serial port. Returns 1 on success, 0
* otherwise.
*/
-int serial_getc (void)
+static int netarm_serial_getc(void)
{
unsigned int ch_uint;
volatile unsigned int *fifo;
@@ -182,9 +182,30 @@ int serial_getc (void)
return ch_uint & 0xff;
}
-void serial_puts (const char *s)
+static void netarm_serial_puts(const char *s)
{
while (*s) {
serial_putc (*s++);
}
}
+
+static struct serial_device netarm_serial_drv = {
+ .name = "netarm_serial",
+ .start = netarm_serial_init,
+ .stop = NULL,
+ .setbrg = netarm_serial_setbrg,
+ .putc = netarm_serial_putc,
+ .puts = netarm_serial_puts,
+ .getc = netarm_serial_getc,
+ .tstc = netarm_serial_tstc,
+};
+
+void netarm_serial_initialize(void)
+{
+ serial_register(&netarm_serial_drv);
+}
+
+__weak struct serial_device *default_serial_console(void)
+{
+ return &netarm_serial_drv;
+}
diff --git a/drivers/serial/serial_ns16550.c b/drivers/serial/serial_ns16550.c
new file mode 100644
index 0000000000..b5d12481ca
--- /dev/null
+++ b/drivers/serial/serial_ns16550.c
@@ -0,0 +1,264 @@
+/*
+ * (C) Copyright 2000
+ * Rob Taylor, Flying Pig Systems. robt@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 <linux/compiler.h>
+
+#include <ns16550.h>
+#ifdef CONFIG_NS87308
+#include <ns87308.h>
+#endif
+
+#include <serial.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if !defined(CONFIG_CONS_INDEX)
+#elif (CONFIG_CONS_INDEX < 1) || (CONFIG_CONS_INDEX > 4)
+#error "Invalid console index value."
+#endif
+
+#if CONFIG_CONS_INDEX == 1 && !defined(CONFIG_SYS_NS16550_COM1)
+#error "Console port 1 defined but not configured."
+#elif CONFIG_CONS_INDEX == 2 && !defined(CONFIG_SYS_NS16550_COM2)
+#error "Console port 2 defined but not configured."
+#elif CONFIG_CONS_INDEX == 3 && !defined(CONFIG_SYS_NS16550_COM3)
+#error "Console port 3 defined but not configured."
+#elif CONFIG_CONS_INDEX == 4 && !defined(CONFIG_SYS_NS16550_COM4)
+#error "Console port 4 defined but not configured."
+#endif
+
+/* Note: The port number specified in the functions is 1 based.
+ * the array is 0 based.
+ */
+static NS16550_t serial_ports[4] = {
+#ifdef CONFIG_SYS_NS16550_COM1
+ (NS16550_t)CONFIG_SYS_NS16550_COM1,
+#else
+ NULL,
+#endif
+#ifdef CONFIG_SYS_NS16550_COM2
+ (NS16550_t)CONFIG_SYS_NS16550_COM2,
+#else
+ NULL,
+#endif
+#ifdef CONFIG_SYS_NS16550_COM3
+ (NS16550_t)CONFIG_SYS_NS16550_COM3,
+#else
+ NULL,
+#endif
+#ifdef CONFIG_SYS_NS16550_COM4
+ (NS16550_t)CONFIG_SYS_NS16550_COM4
+#else
+ NULL
+#endif
+};
+
+#define PORT serial_ports[port-1]
+
+/* Multi serial device functions */
+#define DECLARE_ESERIAL_FUNCTIONS(port) \
+ int eserial##port##_init (void) {\
+ int clock_divisor; \
+ clock_divisor = calc_divisor(serial_ports[port-1]); \
+ NS16550_init(serial_ports[port-1], clock_divisor); \
+ return(0);}\
+ void eserial##port##_setbrg (void) {\
+ serial_setbrg_dev(port);}\
+ int eserial##port##_getc (void) {\
+ return serial_getc_dev(port);}\
+ int eserial##port##_tstc (void) {\
+ return serial_tstc_dev(port);}\
+ void eserial##port##_putc (const char c) {\
+ serial_putc_dev(port, c);}\
+ void eserial##port##_puts (const char *s) {\
+ serial_puts_dev(port, s);}
+
+/* Serial device descriptor */
+#define INIT_ESERIAL_STRUCTURE(port, __name) { \
+ .name = __name, \
+ .start = eserial##port##_init, \
+ .stop = NULL, \
+ .setbrg = eserial##port##_setbrg, \
+ .getc = eserial##port##_getc, \
+ .tstc = eserial##port##_tstc, \
+ .putc = eserial##port##_putc, \
+ .puts = eserial##port##_puts, \
+}
+
+static int calc_divisor (NS16550_t port)
+{
+#ifdef CONFIG_OMAP1510
+ /* If can't cleanly clock 115200 set div to 1 */
+ if ((CONFIG_SYS_NS16550_CLK == 12000000) && (gd->baudrate == 115200)) {
+ port->osc_12m_sel = OSC_12M_SEL; /* enable 6.5 * divisor */
+ return (1); /* return 1 for base divisor */
+ }
+ port->osc_12m_sel = 0; /* clear if previsouly set */
+#endif
+#ifdef CONFIG_OMAP1610
+ /* If can't cleanly clock 115200 set div to 1 */
+ if ((CONFIG_SYS_NS16550_CLK == 48000000) && (gd->baudrate == 115200)) {
+ return (26); /* return 26 for base divisor */
+ }
+#endif
+
+#ifdef CONFIG_APTIX
+#define MODE_X_DIV 13
+#else
+#define MODE_X_DIV 16
+#endif
+
+ /* Compute divisor value. Normally, we should simply return:
+ * CONFIG_SYS_NS16550_CLK) / MODE_X_DIV / gd->baudrate
+ * but we need to round that value by adding 0.5.
+ * Rounding is especially important at high baud rates.
+ */
+ return (CONFIG_SYS_NS16550_CLK + (gd->baudrate * (MODE_X_DIV / 2))) /
+ (MODE_X_DIV * gd->baudrate);
+}
+
+void
+_serial_putc(const char c,const int port)
+{
+ if (c == '\n')
+ NS16550_putc(PORT, '\r');
+
+ NS16550_putc(PORT, c);
+}
+
+void
+_serial_putc_raw(const char c,const int port)
+{
+ NS16550_putc(PORT, c);
+}
+
+void
+_serial_puts (const char *s,const int port)
+{
+ while (*s) {
+ _serial_putc (*s++,port);
+ }
+}
+
+
+int
+_serial_getc(const int port)
+{
+ return NS16550_getc(PORT);
+}
+
+int
+_serial_tstc(const int port)
+{
+ return NS16550_tstc(PORT);
+}
+
+void
+_serial_setbrg (const int port)
+{
+ int clock_divisor;
+
+ clock_divisor = calc_divisor(PORT);
+ NS16550_reinit(PORT, clock_divisor);
+}
+
+static inline void
+serial_putc_dev(unsigned int dev_index,const char c)
+{
+ _serial_putc(c,dev_index);
+}
+
+static inline void
+serial_putc_raw_dev(unsigned int dev_index,const char c)
+{
+ _serial_putc_raw(c,dev_index);
+}
+
+static inline void
+serial_puts_dev(unsigned int dev_index,const char *s)
+{
+ _serial_puts(s,dev_index);
+}
+
+static inline int
+serial_getc_dev(unsigned int dev_index)
+{
+ return _serial_getc(dev_index);
+}
+
+static inline int
+serial_tstc_dev(unsigned int dev_index)
+{
+ return _serial_tstc(dev_index);
+}
+
+static inline void
+serial_setbrg_dev(unsigned int dev_index)
+{
+ _serial_setbrg(dev_index);
+}
+
+DECLARE_ESERIAL_FUNCTIONS(1);
+struct serial_device eserial1_device =
+ INIT_ESERIAL_STRUCTURE(1, "eserial0");
+DECLARE_ESERIAL_FUNCTIONS(2);
+struct serial_device eserial2_device =
+ INIT_ESERIAL_STRUCTURE(2, "eserial1");
+DECLARE_ESERIAL_FUNCTIONS(3);
+struct serial_device eserial3_device =
+ INIT_ESERIAL_STRUCTURE(3, "eserial2");
+DECLARE_ESERIAL_FUNCTIONS(4);
+struct serial_device eserial4_device =
+ INIT_ESERIAL_STRUCTURE(4, "eserial3");
+
+__weak struct serial_device *default_serial_console(void)
+{
+#if CONFIG_CONS_INDEX == 1
+ return &eserial1_device;
+#elif CONFIG_CONS_INDEX == 2
+ return &eserial2_device;
+#elif CONFIG_CONS_INDEX == 3
+ return &eserial3_device;
+#elif CONFIG_CONS_INDEX == 4
+ return &eserial4_device;
+#else
+#error "Bad CONFIG_CONS_INDEX."
+#endif
+}
+
+void ns16550_serial_initialize(void)
+{
+#if defined(CONFIG_SYS_NS16550_COM1)
+ serial_register(&eserial1_device);
+#endif
+#if defined(CONFIG_SYS_NS16550_COM2)
+ serial_register(&eserial2_device);
+#endif
+#if defined(CONFIG_SYS_NS16550_COM3)
+ serial_register(&eserial3_device);
+#endif
+#if defined(CONFIG_SYS_NS16550_COM4)
+ serial_register(&eserial4_device);
+#endif
+}
diff --git a/drivers/serial/serial_pl01x.c b/drivers/serial/serial_pl01x.c
index d4c5137092..7db7b65c3f 100644
--- a/drivers/serial/serial_pl01x.c
+++ b/drivers/serial/serial_pl01x.c
@@ -30,6 +30,8 @@
#include <common.h>
#include <watchdog.h>
#include <asm/io.h>
+#include <serial.h>
+#include <linux/compiler.h>
#include "serial_pl01x.h"
/*
@@ -54,7 +56,7 @@ static struct pl01x_regs *pl01x_get_regs(int portnum)
#ifdef CONFIG_PL010_SERIAL
-int serial_init (void)
+static int pl01x_serial_init(void)
{
struct pl01x_regs *regs = pl01x_get_regs(CONSOLE_PORT);
unsigned int divisor;
@@ -104,7 +106,7 @@ int serial_init (void)
#ifdef CONFIG_PL011_SERIAL
-int serial_init (void)
+static int pl01x_serial_init(void)
{
struct pl01x_regs *regs = pl01x_get_regs(CONSOLE_PORT);
unsigned int temp;
@@ -169,7 +171,7 @@ int serial_init (void)
#endif /* CONFIG_PL011_SERIAL */
-void serial_putc (const char c)
+static void pl01x_serial_putc(const char c)
{
if (c == '\n')
pl01x_putc (CONSOLE_PORT, '\r');
@@ -177,24 +179,24 @@ void serial_putc (const char c)
pl01x_putc (CONSOLE_PORT, c);
}
-void serial_puts (const char *s)
+static void pl01x_serial_puts(const char *s)
{
while (*s) {
serial_putc (*s++);
}
}
-int serial_getc (void)
+static int pl01x_serial_getc(void)
{
return pl01x_getc (CONSOLE_PORT);
}
-int serial_tstc (void)
+static int pl01x_serial_tstc(void)
{
return pl01x_tstc (CONSOLE_PORT);
}
-void serial_setbrg (void)
+static void pl01x_serial_setbrg(void)
{
struct pl01x_regs *regs = pl01x_get_regs(CONSOLE_PORT);
@@ -250,3 +252,24 @@ static int pl01x_tstc (int portnum)
WATCHDOG_RESET();
return !(readl(&regs->fr) & UART_PL01x_FR_RXFE);
}
+
+static struct serial_device pl01x_serial_drv = {
+ .name = "pl01x_serial",
+ .start = pl01x_serial_init,
+ .stop = NULL,
+ .setbrg = pl01x_serial_setbrg,
+ .putc = pl01x_serial_putc,
+ .puts = pl01x_serial_puts,
+ .getc = pl01x_serial_getc,
+ .tstc = pl01x_serial_tstc,
+};
+
+void pl01x_serial_initialize(void)
+{
+ serial_register(&pl01x_serial_drv);
+}
+
+__weak struct serial_device *default_serial_console(void)
+{
+ return &pl01x_serial_drv;
+}
diff --git a/drivers/serial/serial_pxa.c b/drivers/serial/serial_pxa.c
index a9976d709a..ad391004b9 100644
--- a/drivers/serial/serial_pxa.c
+++ b/drivers/serial/serial_pxa.c
@@ -36,6 +36,7 @@
#include <asm/arch/pxa-regs.h>
#include <asm/arch/regs-uart.h>
#include <asm/io.h>
+#include <linux/compiler.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -72,21 +73,7 @@ DECLARE_GLOBAL_DATA_PTR;
#define HWUART_INDEX 0xff
#endif
-#ifndef CONFIG_SERIAL_MULTI
-#if defined(CONFIG_FFUART)
-#define UART_INDEX FFUART_INDEX
-#elif defined(CONFIG_BTUART)
-#define UART_INDEX BTUART_INDEX
-#elif defined(CONFIG_STUART)
-#define UART_INDEX STUART_INDEX
-#elif defined(CONFIG_HWUART)
-#define UART_INDEX HWUART_INDEX
-#else
-#error "Please select CONFIG_(FF|BT|ST|HW)UART in board config file."
-#endif
-#endif
-
-uint32_t pxa_uart_get_baud_divider(void)
+static uint32_t pxa_uart_get_baud_divider(void)
{
if (gd->baudrate == 1200)
return 768;
@@ -104,7 +91,7 @@ uint32_t pxa_uart_get_baud_divider(void)
return 0;
}
-struct pxa_uart_regs *pxa_uart_index_to_regs(uint32_t uart_index)
+static struct pxa_uart_regs *pxa_uart_index_to_regs(uint32_t uart_index)
{
switch (uart_index) {
case FFUART_INDEX: return (struct pxa_uart_regs *)FFUART_BASE;
@@ -116,7 +103,7 @@ struct pxa_uart_regs *pxa_uart_index_to_regs(uint32_t uart_index)
}
}
-void pxa_uart_toggle_clock(uint32_t uart_index, int enable)
+static void pxa_uart_toggle_clock(uint32_t uart_index, int enable)
{
uint32_t clk_reg, clk_offset, reg;
@@ -269,14 +256,14 @@ void pxa_puts_dev(unsigned int uart_index, const char *s)
#define pxa_uart_desc(uart) \
struct serial_device serial_##uart##_device = \
{ \
- "serial_"#uart, \
- uart##_init, \
- NULL, \
- uart##_setbrg, \
- uart##_getc, \
- uart##_tstc, \
- uart##_putc, \
- uart##_puts, \
+ .name = "serial_"#uart, \
+ .start = uart##_init, \
+ .stop = NULL, \
+ .setbrg = uart##_setbrg, \
+ .getc = uart##_getc, \
+ .tstc = uart##_tstc, \
+ .putc = uart##_putc, \
+ .puts = uart##_puts, \
};
#define pxa_uart_multi(uart, UART) \
@@ -296,6 +283,30 @@ void pxa_puts_dev(unsigned int uart_index, const char *s)
pxa_uart_multi(btuart, BTUART)
#endif
-#ifndef CONFIG_SERIAL_MULTI
- pxa_uart(serial, UART)
+__weak struct serial_device *default_serial_console(void)
+{
+#if CONFIG_CONS_INDEX == 1
+ return &serial_hwuart_device;
+#elif CONFIG_CONS_INDEX == 2
+ return &serial_stuart_device;
+#elif CONFIG_CONS_INDEX == 3
+ return &serial_ffuart_device;
+#elif CONFIG_CONS_INDEX == 4
+ return &serial_btuart_device;
+#else
+#error "Bad CONFIG_CONS_INDEX."
#endif
+}
+
+void pxa_serial_initialize(void)
+{
+#if defined(CONFIG_FFUART)
+ serial_register(&serial_ffuart_device);
+#endif
+#if defined(CONFIG_BTUART)
+ serial_register(&serial_btuart_device);
+#endif
+#if defined(CONFIG_STUART)
+ serial_register(&serial_stuart_device);
+#endif
+}
diff --git a/drivers/serial/serial_s3c24x0.c b/drivers/serial/serial_s3c24x0.c
index 12bcdd3dbf..4d214c396f 100644
--- a/drivers/serial/serial_s3c24x0.c
+++ b/drivers/serial/serial_s3c24x0.c
@@ -38,8 +38,6 @@ DECLARE_GLOBAL_DATA_PTR;
#endif
#include <asm/io.h>
-
-#if defined(CONFIG_SERIAL_MULTI)
#include <serial.h>
/* Multi serial device functions */
@@ -69,19 +67,17 @@ DECLARE_GLOBAL_DATA_PTR;
serial_puts_dev(port, s); \
}
-#define INIT_S3C_SERIAL_STRUCTURE(port, name) { \
- name, \
- s3serial##port##_init, \
- NULL,\
- s3serial##port##_setbrg, \
- s3serial##port##_getc, \
- s3serial##port##_tstc, \
- s3serial##port##_putc, \
- s3serial##port##_puts, \
+#define INIT_S3C_SERIAL_STRUCTURE(port, __name) { \
+ .name = __name, \
+ .start = s3serial##port##_init, \
+ .stop = NULL, \
+ .setbrg = s3serial##port##_setbrg, \
+ .getc = s3serial##port##_getc, \
+ .tstc = s3serial##port##_tstc, \
+ .putc = s3serial##port##_putc, \
+ .puts = s3serial##port##_puts, \
}
-#endif /* CONFIG_SERIAL_MULTI */
-
#ifdef CONFIG_HWFLOW
static int hwflow;
#endif
@@ -100,18 +96,10 @@ void _serial_setbrg(const int dev_index)
/* Delay */ ;
}
-#if defined(CONFIG_SERIAL_MULTI)
static inline void serial_setbrg_dev(unsigned int dev_index)
{
_serial_setbrg(dev_index);
}
-#else
-void serial_setbrg(void)
-{
- _serial_setbrg(UART_NR);
-}
-#endif
-
/* Initialise the serial port. The settings are always 8 data bits, no parity,
* 1 stop bit, no start bits.
@@ -151,16 +139,6 @@ static int serial_init_dev(const int dev_index)
return (0);
}
-#if !defined(CONFIG_SERIAL_MULTI)
-/* Initialise the serial port. The settings are always 8 data bits, no parity,
- * 1 stop bit, no start bits.
- */
-int serial_init(void)
-{
- return serial_init_dev(UART_NR);
-}
-#endif
-
/*
* Read a single byte from the serial port. Returns 1 on success, 0
* otherwise. When the function is succesfull, the character read is
@@ -176,17 +154,10 @@ int _serial_getc(const int dev_index)
return readb(&uart->urxh) & 0xff;
}
-#if defined(CONFIG_SERIAL_MULTI)
static inline int serial_getc_dev(unsigned int dev_index)
{
return _serial_getc(dev_index);
}
-#else
-int serial_getc(void)
-{
- return _serial_getc(UART_NR);
-}
-#endif
#ifdef CONFIG_HWFLOW
int hwflow_onoff(int on)
@@ -246,18 +217,10 @@ void _serial_putc(const char c, const int dev_index)
serial_putc('\r');
}
-#if defined(CONFIG_SERIAL_MULTI)
static inline void serial_putc_dev(unsigned int dev_index, const char c)
{
_serial_putc(c, dev_index);
}
-#else
-void serial_putc(const char c)
-{
- _serial_putc(c, UART_NR);
-}
-#endif
-
/*
* Test whether a character is in the RX buffer
@@ -269,17 +232,10 @@ int _serial_tstc(const int dev_index)
return readl(&uart->utrstat) & 0x1;
}
-#if defined(CONFIG_SERIAL_MULTI)
static inline int serial_tstc_dev(unsigned int dev_index)
{
return _serial_tstc(dev_index);
}
-#else
-int serial_tstc(void)
-{
- return _serial_tstc(UART_NR);
-}
-#endif
void _serial_puts(const char *s, const int dev_index)
{
@@ -288,19 +244,11 @@ void _serial_puts(const char *s, const int dev_index)
}
}
-#if defined(CONFIG_SERIAL_MULTI)
static inline void serial_puts_dev(int dev_index, const char *s)
{
_serial_puts(s, dev_index);
}
-#else
-void serial_puts(const char *s)
-{
- _serial_puts(s, UART_NR);
-}
-#endif
-#if defined(CONFIG_SERIAL_MULTI)
DECLARE_S3C_SERIAL_FUNCTIONS(0);
struct serial_device s3c24xx_serial0_device =
INIT_S3C_SERIAL_STRUCTURE(0, "s3ser0");
@@ -323,4 +271,10 @@ __weak struct serial_device *default_serial_console(void)
#error "CONFIG_SERIAL? missing."
#endif
}
-#endif /* CONFIG_SERIAL_MULTI */
+
+void s3c24xx_serial_initialize(void)
+{
+ serial_register(&s3c24xx_serial0_device);
+ serial_register(&s3c24xx_serial1_device);
+ serial_register(&s3c24xx_serial2_device);
+}
diff --git a/drivers/serial/serial_s3c44b0.c b/drivers/serial/serial_s3c44b0.c
index 95d0266c6c..a4428e0f47 100644
--- a/drivers/serial/serial_s3c44b0.c
+++ b/drivers/serial/serial_s3c44b0.c
@@ -68,7 +68,7 @@ static int serial_flush_output(void)
}
-void serial_setbrg (void)
+static void s3c44b0_serial_setbrg(void)
{
u32 divisor = 0;
@@ -156,7 +156,7 @@ void serial_setbrg (void)
* are always 8 data bits, no parity, 1 stop bit, no start bits.
*
*/
-int serial_init (void)
+static int s3c44b0_serial_init(void)
{
serial_setbrg ();
@@ -167,7 +167,7 @@ int serial_init (void)
/*
* Output a single byte to the serial port.
*/
-void serial_putc (const char c)
+static void s3c44b0_serial_putc(const char c)
{
/* wait for room in the transmit FIFO */
while(!(UTRSTAT0 & 0x02));
@@ -187,7 +187,7 @@ void serial_putc (const char c)
* otherwise. When the function is succesfull, the character read is
* written into its argument c.
*/
-int serial_tstc (void)
+static int s3c44b0_serial_tstc(void)
{
return (UTRSTAT0 & 0x01);
}
@@ -197,22 +197,42 @@ int serial_tstc (void)
* otherwise. When the function is succesfull, the character read is
* written into its argument c.
*/
-int serial_getc (void)
+static int s3c44b0_serial_getc(void)
{
int rv;
for(;;) {
- rv = serial_tstc();
+ rv = s3c44b0_serial_tstc();
if(rv > 0)
return URXH0;
}
}
-void
-serial_puts (const char *s)
+static void s3c44b0_serial_puts(const char *s)
{
while (*s) {
serial_putc (*s++);
}
}
+
+static struct serial_device s3c44b0_serial_drv = {
+ .name = "s3c44b0_serial",
+ .start = s3c44b0_serial_init,
+ .stop = NULL,
+ .setbrg = s3c44b0_serial_setbrg,
+ .putc = s3c44b0_serial_putc,
+ .puts = s3c44b0_serial_puts,
+ .getc = s3c44b0_serial_getc,
+ .tstc = s3c44b0_serial_tstc,
+};
+
+void s3c44b0_serial_initialize(void)
+{
+ serial_register(&s3c44b0_serial_drv);
+}
+
+__weak struct serial_device *default_serial_console(void)
+{
+ return &s3c44b0_serial_drv;
+}
diff --git a/drivers/serial/serial_s5p.c b/drivers/serial/serial_s5p.c
index 6819bb07b7..3c41242a8e 100644
--- a/drivers/serial/serial_s5p.c
+++ b/drivers/serial/serial_s5p.c
@@ -183,15 +183,16 @@ int s5p_serial##port##_tstc(void) { return serial_tstc_dev(port); } \
void s5p_serial##port##_putc(const char c) { serial_putc_dev(c, port); } \
void s5p_serial##port##_puts(const char *s) { serial_puts_dev(s, port); }
-#define INIT_S5P_SERIAL_STRUCTURE(port, name) { \
- name, \
- s5p_serial##port##_init, \
- NULL, \
- s5p_serial##port##_setbrg, \
- s5p_serial##port##_getc, \
- s5p_serial##port##_tstc, \
- s5p_serial##port##_putc, \
- s5p_serial##port##_puts, }
+#define INIT_S5P_SERIAL_STRUCTURE(port, __name) { \
+ .name = __name, \
+ .start = s5p_serial##port##_init, \
+ .stop = NULL, \
+ .setbrg = s5p_serial##port##_setbrg, \
+ .getc = s5p_serial##port##_getc, \
+ .tstc = s5p_serial##port##_tstc, \
+ .putc = s5p_serial##port##_putc, \
+ .puts = s5p_serial##port##_puts, \
+}
DECLARE_S5P_SERIAL_FUNCTIONS(0);
struct serial_device s5p_serial0_device =
@@ -220,3 +221,11 @@ __weak struct serial_device *default_serial_console(void)
#error "CONFIG_SERIAL? missing."
#endif
}
+
+void s5p_serial_initialize(void)
+{
+ serial_register(&s5p_serial0_device);
+ serial_register(&s5p_serial1_device);
+ serial_register(&s5p_serial2_device);
+ serial_register(&s5p_serial3_device);
+}
diff --git a/drivers/serial/serial_sa1100.c b/drivers/serial/serial_sa1100.c
index 5d1887580d..c6b34db7c6 100644
--- a/drivers/serial/serial_sa1100.c
+++ b/drivers/serial/serial_sa1100.c
@@ -30,10 +30,12 @@
#include <common.h>
#include <SA-1100.h>
+#include <serial.h>
+#include <linux/compiler.h>
DECLARE_GLOBAL_DATA_PTR;
-void serial_setbrg (void)
+static void sa1100_serial_setbrg(void)
{
unsigned int reg = 0;
@@ -89,7 +91,7 @@ void serial_setbrg (void)
* are always 8 data bits, no parity, 1 stop bit, no start bits.
*
*/
-int serial_init (void)
+static int sa1100_serial_init(void)
{
serial_setbrg ();
@@ -100,7 +102,7 @@ int serial_init (void)
/*
* Output a single byte to the serial port.
*/
-void serial_putc (const char c)
+static void sa1100_serial_putc(const char c)
{
#ifdef CONFIG_SERIAL1
/* wait for room in the tx FIFO on SERIAL1 */
@@ -124,7 +126,7 @@ void serial_putc (const char c)
* otherwise. When the function is succesfull, the character read is
* written into its argument c.
*/
-int serial_tstc (void)
+static int sa1100_serial_tstc(void)
{
#ifdef CONFIG_SERIAL1
return Ser1UTSR1 & UTSR1_RNE;
@@ -138,7 +140,7 @@ int serial_tstc (void)
* otherwise. When the function is succesfull, the character read is
* written into its argument c.
*/
-int serial_getc (void)
+static int sa1100_serial_getc(void)
{
#ifdef CONFIG_SERIAL1
while (!(Ser1UTSR1 & UTSR1_RNE));
@@ -151,10 +153,30 @@ int serial_getc (void)
#endif
}
-void
-serial_puts (const char *s)
+static void sa1100_serial_puts(const char *s)
{
while (*s) {
serial_putc (*s++);
}
}
+
+static struct serial_device sa1100_serial_drv = {
+ .name = "sa1100_serial",
+ .start = sa1100_serial_init,
+ .stop = NULL,
+ .setbrg = sa1100_serial_setbrg,
+ .putc = sa1100_serial_putc,
+ .puts = sa1100_serial_puts,
+ .getc = sa1100_serial_getc,
+ .tstc = sa1100_serial_tstc,
+};
+
+void sa1100_serial_initialize(void)
+{
+ serial_register(&sa1100_serial_drv);
+}
+
+__weak struct serial_device *default_serial_console(void)
+{
+ return &sa1100_serial_drv;
+}
diff --git a/drivers/serial/serial_sh.c b/drivers/serial/serial_sh.c
index 13919c623b..1ddfc7d87f 100644
--- a/drivers/serial/serial_sh.c
+++ b/drivers/serial/serial_sh.c
@@ -22,6 +22,8 @@
#include <asm/io.h>
#include <asm/processor.h>
#include "serial_sh.h"
+#include <serial.h>
+#include <linux/compiler.h>
#if defined(CONFIG_CONS_SCIF0)
# define SCIF_BASE SCIF0_BASE
@@ -55,13 +57,13 @@ static struct uart_port sh_sci = {
.type = SCIF_BASE_PORT,
};
-void serial_setbrg(void)
+static void sh_serial_setbrg(void)
{
DECLARE_GLOBAL_DATA_PTR;
sci_out(&sh_sci, SCBRR, SCBRR_VALUE(gd->baudrate, CONFIG_SYS_CLK_FREQ));
}
-int serial_init(void)
+static int sh_serial_init(void)
{
sci_out(&sh_sci, SCSCR , SCSCR_INIT(&sh_sci));
sci_out(&sh_sci, SCSCR , SCSCR_INIT(&sh_sci));
@@ -127,21 +129,21 @@ void serial_raw_putc(const char c)
sci_out(&sh_sci, SCxSR, sci_in(&sh_sci, SCxSR) & ~SCxSR_TEND(&sh_sci));
}
-void serial_putc(const char c)
+static void sh_serial_putc(const char c)
{
if (c == '\n')
serial_raw_putc('\r');
serial_raw_putc(c);
}
-void serial_puts(const char *s)
+static void sh_serial_puts(const char *s)
{
char c;
while ((c = *s++) != 0)
serial_putc(c);
}
-int serial_tstc(void)
+static int sh_serial_tstc(void)
{
return serial_rx_fifo_level() ? 1 : 0;
}
@@ -167,7 +169,7 @@ int serial_getc_check(void)
return status & (SCIF_DR | SCxSR_RDxF(&sh_sci));
}
-int serial_getc(void)
+static int sh_serial_getc(void)
{
unsigned short status;
char ch;
@@ -187,3 +189,24 @@ int serial_getc(void)
handle_error();
return ch;
}
+
+static struct serial_device sh_serial_drv = {
+ .name = "sh_serial",
+ .start = sh_serial_init,
+ .stop = NULL,
+ .setbrg = sh_serial_setbrg,
+ .putc = sh_serial_putc,
+ .puts = sh_serial_puts,
+ .getc = sh_serial_getc,
+ .tstc = sh_serial_tstc,
+};
+
+void sh_serial_initialize(void)
+{
+ serial_register(&sh_serial_drv);
+}
+
+__weak struct serial_device *default_serial_console(void)
+{
+ return &sh_serial_drv;
+}
diff --git a/drivers/serial/serial_xuartlite.c b/drivers/serial/serial_xuartlite.c
index 2bdb68ba4a..9cc0b7f1d2 100644
--- a/drivers/serial/serial_xuartlite.c
+++ b/drivers/serial/serial_xuartlite.c
@@ -96,39 +96,6 @@ static int uartlite_serial_init(const int port)
return -1;
}
-#if !defined(CONFIG_SERIAL_MULTI)
-int serial_init(void)
-{
- return uartlite_serial_init(0);
-}
-
-void serial_setbrg(void)
-{
- /* FIXME: what's this for? */
-}
-
-void serial_putc(const char c)
-{
- uartlite_serial_putc(c, 0);
-}
-
-void serial_puts(const char *s)
-{
- uartlite_serial_puts(s, 0);
-}
-
-int serial_getc(void)
-{
- return uartlite_serial_getc(0);
-}
-
-int serial_tstc(void)
-{
- return uartlite_serial_tstc(0);
-}
-#endif
-
-#if defined(CONFIG_SERIAL_MULTI)
/* Multi serial device functions */
#define DECLARE_ESERIAL_FUNCTIONS(port) \
int userial##port##_init(void) \
@@ -144,15 +111,16 @@ int serial_tstc(void)
{ uartlite_serial_puts(s, port); }
/* Serial device descriptor */
-#define INIT_ESERIAL_STRUCTURE(port, name) {\
- name,\
- userial##port##_init,\
- NULL,\
- userial##port##_setbrg,\
- userial##port##_getc,\
- userial##port##_tstc,\
- userial##port##_putc,\
- userial##port##_puts, }
+#define INIT_ESERIAL_STRUCTURE(port, __name) { \
+ .name = __name, \
+ .start = userial##port##_init, \
+ .stop = NULL, \
+ .setbrg = userial##port##_setbrg, \
+ .getc = userial##port##_getc, \
+ .tstc = userial##port##_tstc, \
+ .putc = userial##port##_putc, \
+ .puts = userial##port##_puts, \
+}
DECLARE_ESERIAL_FUNCTIONS(0);
struct serial_device uartlite_serial0_device =
@@ -180,4 +148,19 @@ __weak struct serial_device *default_serial_console(void)
return NULL;
}
-#endif /* CONFIG_SERIAL_MULTI */
+
+void uartlite_serial_initialize(void)
+{
+#ifdef XILINX_UARTLITE_BASEADDR
+ serial_register(&uartlite_serial0_device);
+#endif /* XILINX_UARTLITE_BASEADDR */
+#ifdef XILINX_UARTLITE_BASEADDR1
+ serial_register(&uartlite_serial1_device);
+#endif /* XILINX_UARTLITE_BASEADDR1 */
+#ifdef XILINX_UARTLITE_BASEADDR2
+ serial_register(&uartlite_serial2_device);
+#endif /* XILINX_UARTLITE_BASEADDR2 */
+#ifdef XILINX_UARTLITE_BASEADDR3
+ serial_register(&uartlite_serial3_device);
+#endif /* XILINX_UARTLITE_BASEADDR3 */
+}
diff --git a/drivers/serial/serial_zynq.c b/drivers/serial/serial_zynq.c
new file mode 100644
index 0000000000..c09aa271b5
--- /dev/null
+++ b/drivers/serial/serial_zynq.c
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2012 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2011-2012 Xilinx, Inc. All rights reserved.
+ *
+ * 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 <watchdog.h>
+#include <asm/io.h>
+#include <linux/compiler.h>
+#include <serial.h>
+
+#define ZYNQ_UART_SR_TXFULL 0x00000010 /* TX FIFO full */
+#define ZYNQ_UART_SR_RXEMPTY 0x00000002 /* RX FIFO empty */
+
+#define ZYNQ_UART_CR_TX_EN 0x00000010 /* TX enabled */
+#define ZYNQ_UART_CR_RX_EN 0x00000004 /* RX enabled */
+#define ZYNQ_UART_CR_TXRST 0x00000002 /* TX logic reset */
+#define ZYNQ_UART_CR_RXRST 0x00000001 /* RX logic reset */
+
+#define ZYNQ_UART_MR_PARITY_NONE 0x00000020 /* No parity mode */
+
+/* Some clock/baud constants */
+#define ZYNQ_UART_BDIV 15 /* Default/reset BDIV value */
+#define ZYNQ_UART_BASECLK 3125000L /* master / (bdiv + 1) */
+
+struct uart_zynq {
+ u32 control; /* Control Register [8:0] */
+ u32 mode; /* Mode Register [10:0] */
+ u32 reserved1[4];
+ u32 baud_rate_gen; /* Baud Rate Generator [15:0] */
+ u32 reserved2[4];
+ u32 channel_sts; /* Channel Status [11:0] */
+ u32 tx_rx_fifo; /* FIFO [15:0] or [7:0] */
+ u32 baud_rate_divider; /* Baud Rate Divider [7:0] */
+};
+
+static struct uart_zynq *uart_zynq_ports[2] = {
+#ifdef CONFIG_ZYNQ_SERIAL_BASEADDR0
+ [0] = (struct uart_zynq *)CONFIG_ZYNQ_SERIAL_BASEADDR0,
+#endif
+#ifdef CONFIG_ZYNQ_SERIAL_BASEADDR1
+ [1] = (struct uart_zynq *)CONFIG_ZYNQ_SERIAL_BASEADDR1,
+#endif
+};
+
+struct uart_zynq_params {
+ u32 baudrate;
+ u32 clock;
+};
+
+static struct uart_zynq_params uart_zynq_ports_param[2] = {
+#if defined(CONFIG_ZYNQ_SERIAL_BAUDRATE0) && defined(CONFIG_ZYNQ_SERIAL_CLOCK0)
+ [0].baudrate = CONFIG_ZYNQ_SERIAL_BAUDRATE0,
+ [0].clock = CONFIG_ZYNQ_SERIAL_CLOCK0,
+#endif
+#if defined(CONFIG_ZYNQ_SERIAL_BAUDRATE1) && defined(CONFIG_ZYNQ_SERIAL_CLOCK1)
+ [1].baudrate = CONFIG_ZYNQ_SERIAL_BAUDRATE1,
+ [1].clock = CONFIG_ZYNQ_SERIAL_CLOCK1,
+#endif
+};
+
+/* Set up the baud rate in gd struct */
+static void uart_zynq_serial_setbrg(const int port)
+{
+ /* Calculation results. */
+ unsigned int calc_bauderror, bdiv, bgen;
+ unsigned long calc_baud = 0;
+ unsigned long baud = uart_zynq_ports_param[port].baudrate;
+ unsigned long clock = uart_zynq_ports_param[port].clock;
+ struct uart_zynq *regs = uart_zynq_ports[port];
+
+ /* master clock
+ * Baud rate = ------------------
+ * bgen * (bdiv + 1)
+ *
+ * Find acceptable values for baud generation.
+ */
+ for (bdiv = 4; bdiv < 255; bdiv++) {
+ bgen = clock / (baud * (bdiv + 1));
+ if (bgen < 2 || bgen > 65535)
+ continue;
+
+ calc_baud = clock / (bgen * (bdiv + 1));
+
+ /*
+ * Use first calculated baudrate with
+ * an acceptable (<3%) error
+ */
+ if (baud > calc_baud)
+ calc_bauderror = baud - calc_baud;
+ else
+ calc_bauderror = calc_baud - baud;
+ if (((calc_bauderror * 100) / baud) < 3)
+ break;
+ }
+
+ writel(bdiv, &regs->baud_rate_divider);
+ writel(bgen, &regs->baud_rate_gen);
+}
+
+/* Initialize the UART, with...some settings. */
+static int uart_zynq_serial_init(const int port)
+{
+ struct uart_zynq *regs = uart_zynq_ports[port];
+
+ if (!regs)
+ return -1;
+
+ /* RX/TX enabled & reset */
+ writel(ZYNQ_UART_CR_TX_EN | ZYNQ_UART_CR_RX_EN | ZYNQ_UART_CR_TXRST | \
+ ZYNQ_UART_CR_RXRST, &regs->control);
+ writel(ZYNQ_UART_MR_PARITY_NONE, &regs->mode); /* 8 bit, no parity */
+ uart_zynq_serial_setbrg(port);
+
+ return 0;
+}
+
+static void uart_zynq_serial_putc(const char c, const int port)
+{
+ struct uart_zynq *regs = uart_zynq_ports[port];
+
+ while ((readl(&regs->channel_sts) & ZYNQ_UART_SR_TXFULL) != 0)
+ WATCHDOG_RESET();
+
+ if (c == '\n') {
+ writel('\r', &regs->tx_rx_fifo);
+ while ((readl(&regs->channel_sts) & ZYNQ_UART_SR_TXFULL) != 0)
+ WATCHDOG_RESET();
+ }
+ writel(c, &regs->tx_rx_fifo);
+}
+
+static void uart_zynq_serial_puts(const char *s, const int port)
+{
+ while (*s)
+ uart_zynq_serial_putc(*s++, port);
+}
+
+static int uart_zynq_serial_tstc(const int port)
+{
+ struct uart_zynq *regs = uart_zynq_ports[port];
+
+ return (readl(&regs->channel_sts) & ZYNQ_UART_SR_RXEMPTY) == 0;
+}
+
+static int uart_zynq_serial_getc(const int port)
+{
+ struct uart_zynq *regs = uart_zynq_ports[port];
+
+ while (!uart_zynq_serial_tstc(port))
+ WATCHDOG_RESET();
+ return readl(&regs->tx_rx_fifo);
+}
+
+/* Multi serial device functions */
+#define DECLARE_PSSERIAL_FUNCTIONS(port) \
+ int uart_zynq##port##_init(void) \
+ { return uart_zynq_serial_init(port); } \
+ void uart_zynq##port##_setbrg(void) \
+ { return uart_zynq_serial_setbrg(port); } \
+ int uart_zynq##port##_getc(void) \
+ { return uart_zynq_serial_getc(port); } \
+ int uart_zynq##port##_tstc(void) \
+ { return uart_zynq_serial_tstc(port); } \
+ void uart_zynq##port##_putc(const char c) \
+ { uart_zynq_serial_putc(c, port); } \
+ void uart_zynq##port##_puts(const char *s) \
+ { uart_zynq_serial_puts(s, port); }
+
+/* Serial device descriptor */
+#define INIT_PSSERIAL_STRUCTURE(port, __name) { \
+ .name = __name, \
+ .start = uart_zynq##port##_init, \
+ .stop = NULL, \
+ .setbrg = uart_zynq##port##_setbrg, \
+ .getc = uart_zynq##port##_getc, \
+ .tstc = uart_zynq##port##_tstc, \
+ .putc = uart_zynq##port##_putc, \
+ .puts = uart_zynq##port##_puts, \
+}
+
+DECLARE_PSSERIAL_FUNCTIONS(0);
+struct serial_device uart_zynq_serial0_device =
+ INIT_PSSERIAL_STRUCTURE(0, "ttyPS0");
+DECLARE_PSSERIAL_FUNCTIONS(1);
+struct serial_device uart_zynq_serial1_device =
+ INIT_PSSERIAL_STRUCTURE(1, "ttyPS1");
+
+__weak struct serial_device *default_serial_console(void)
+{
+ if (uart_zynq_ports[0])
+ return &uart_zynq_serial0_device;
+ if (uart_zynq_ports[1])
+ return &uart_zynq_serial1_device;
+
+ return NULL;
+}
+
+void zynq_serial_initalize(void)
+{
+#ifdef CONFIG_ZYNQ_SERIAL_BASEADDR0
+ serial_register(&uart_zynq_serial0_device);
+#endif
+#ifdef CONFIG_ZYNQ_SERIAL_BASEADDR1
+ serial_register(&uart_zynq_serial1_device);
+#endif
+}
diff --git a/drivers/spi/tegra_spi.c b/drivers/spi/tegra_spi.c
index 18b00b2cae..9bb34e2938 100644
--- a/drivers/spi/tegra_spi.c
+++ b/drivers/spi/tegra_spi.c
@@ -23,16 +23,15 @@
*/
#include <common.h>
-
#include <malloc.h>
-#include <spi.h>
#include <asm/io.h>
#include <asm/gpio.h>
-#include <asm/arch/clk_rst.h>
#include <asm/arch/clock.h>
#include <asm/arch/pinmux.h>
#include <asm/arch/uart-spi-switch.h>
-#include <asm/arch/tegra_spi.h>
+#include <asm/arch-tegra/clk_rst.h>
+#include <asm/arch-tegra/tegra_spi.h>
+#include <spi.h>
#if defined(CONFIG_SPI_CORRUPTS_UART)
#define corrupt_delay() udelay(CONFIG_SPI_CORRUPTS_UART_DLY);
diff --git a/drivers/usb/eth/usb_ether.c b/drivers/usb/eth/usb_ether.c
index 6cad6c87ca..f361e8b168 100644
--- a/drivers/usb/eth/usb_ether.c
+++ b/drivers/usb/eth/usb_ether.c
@@ -123,7 +123,7 @@ int usb_host_eth_scan(int mode)
if (mode == 1)
- printf(" scanning bus for ethernet devices... ");
+ printf(" scanning usb for ethernet devices... ");
old_async = usb_disable_asynch(1); /* asynch transfer not allowed */
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 5bbdd368f4..040eaba3bc 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -36,6 +36,7 @@ ifdef CONFIG_USB_ETHER
COBJS-y += ether.o epautoconf.o config.o usbstring.o
COBJS-$(CONFIG_USB_ETH_RNDIS) += rndis.o
COBJS-$(CONFIG_MV_UDC) += mv_udc.o
+COBJS-$(CONFIG_CPU_PXA25X) += pxa25x_udc.o
else
# Devices not related to the new gadget layer depend on CONFIG_USB_DEVICE
ifdef CONFIG_USB_DEVICE
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index d975fb680e..1e187e5b52 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -44,7 +44,6 @@ extern struct platform_data brd;
unsigned packet_received, packet_sent;
-#define DEV_CONFIG_CDC 1
#define GFP_ATOMIC ((gfp_t) 0)
#define GFP_KERNEL ((gfp_t) 0)
@@ -160,9 +159,9 @@ static struct usb_gadget_driver eth_driver;
/* "main" config is either CDC, or its simple subset */
static inline int is_cdc(struct eth_dev *dev)
{
-#if !defined(DEV_CONFIG_SUBSET)
+#if !defined(CONFIG_USB_ETH_SUBSET)
return 1; /* only cdc possible */
-#elif !defined(DEV_CONFIG_CDC)
+#elif !defined(CONFIG_USB_ETH_CDC)
return 0; /* only subset possible */
#else
return dev->cdc; /* depends on what hardware we found */
@@ -406,7 +405,7 @@ rndis_config = {
* get those drivers from MCCI, or bundled with various products.
*/
-#ifdef DEV_CONFIG_CDC
+#ifdef CONFIG_USB_ETH_CDC
static struct usb_interface_descriptor
control_intf = {
.bLength = sizeof control_intf,
@@ -445,7 +444,7 @@ static const struct usb_cdc_header_desc header_desc = {
.bcdCDC = __constant_cpu_to_le16(0x0110),
};
-#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
+#if defined(CONFIG_USB_ETH_CDC) || defined(CONFIG_USB_ETH_RNDIS)
static const struct usb_cdc_union_desc union_desc = {
.bLength = sizeof union_desc,
@@ -479,7 +478,7 @@ static const struct usb_cdc_acm_descriptor acm_descriptor = {
#endif
-#ifndef DEV_CONFIG_CDC
+#ifndef CONFIG_USB_ETH_CDC
/*
* "SAFE" loosely follows CDC WMC MDLM, violating the spec in various
@@ -529,7 +528,7 @@ static const struct usb_cdc_ether_desc ether_desc = {
.bNumberPowerFilters = 0,
};
-#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
+#if defined(CONFIG_USB_ETH_CDC) || defined(CONFIG_USB_ETH_RNDIS)
/*
* include the status endpoint if we can, even where it's optional.
@@ -561,7 +560,7 @@ fs_status_desc = {
};
#endif
-#ifdef DEV_CONFIG_CDC
+#ifdef CONFIG_USB_ETH_CDC
/* the default data interface has no endpoints ... */
@@ -616,7 +615,7 @@ rndis_data_intf = {
#endif
-#ifdef DEV_CONFIG_SUBSET
+#ifdef CONFIG_USB_ETH_SUBSET
/*
* "Simple" CDC-subset option is a simple vendor-neutral model that most
@@ -662,7 +661,7 @@ fs_sink_desc = {
static const struct usb_descriptor_header *fs_eth_function[11] = {
(struct usb_descriptor_header *) &otg_descriptor,
-#ifdef DEV_CONFIG_CDC
+#ifdef CONFIG_USB_ETH_CDC
/* "cdc" mode descriptors */
(struct usb_descriptor_header *) &control_intf,
(struct usb_descriptor_header *) &header_desc,
@@ -676,12 +675,12 @@ static const struct usb_descriptor_header *fs_eth_function[11] = {
(struct usb_descriptor_header *) &fs_source_desc,
(struct usb_descriptor_header *) &fs_sink_desc,
NULL,
-#endif /* DEV_CONFIG_CDC */
+#endif /* CONFIG_USB_ETH_CDC */
};
static inline void fs_subset_descriptors(void)
{
-#ifdef DEV_CONFIG_SUBSET
+#ifdef CONFIG_USB_ETH_SUBSET
/* behavior is "CDC Subset"; extra descriptors say "SAFE" */
fs_eth_function[1] = (struct usb_descriptor_header *) &subset_data_intf;
fs_eth_function[2] = (struct usb_descriptor_header *) &header_desc;
@@ -719,7 +718,7 @@ static const struct usb_descriptor_header *fs_rndis_function[] = {
* descriptors, unless they only run at full speed.
*/
-#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
+#if defined(CONFIG_USB_ETH_CDC) || defined(CONFIG_USB_ETH_RNDIS)
static struct usb_endpoint_descriptor
hs_status_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
@@ -729,7 +728,7 @@ hs_status_desc = {
.wMaxPacketSize = __constant_cpu_to_le16(STATUS_BYTECOUNT),
.bInterval = LOG2_STATUS_INTERVAL_MSEC + 4,
};
-#endif /* DEV_CONFIG_CDC */
+#endif /* CONFIG_USB_ETH_CDC */
static struct usb_endpoint_descriptor
hs_source_desc = {
@@ -762,7 +761,7 @@ dev_qualifier = {
static const struct usb_descriptor_header *hs_eth_function[11] = {
(struct usb_descriptor_header *) &otg_descriptor,
-#ifdef DEV_CONFIG_CDC
+#ifdef CONFIG_USB_ETH_CDC
/* "cdc" mode descriptors */
(struct usb_descriptor_header *) &control_intf,
(struct usb_descriptor_header *) &header_desc,
@@ -776,12 +775,12 @@ static const struct usb_descriptor_header *hs_eth_function[11] = {
(struct usb_descriptor_header *) &hs_source_desc,
(struct usb_descriptor_header *) &hs_sink_desc,
NULL,
-#endif /* DEV_CONFIG_CDC */
+#endif /* CONFIG_USB_ETH_CDC */
};
static inline void hs_subset_descriptors(void)
{
-#ifdef DEV_CONFIG_SUBSET
+#ifdef CONFIG_USB_ETH_SUBSET
/* behavior is "CDC Subset"; extra descriptors say "SAFE" */
hs_eth_function[1] = (struct usb_descriptor_header *) &subset_data_intf;
hs_eth_function[2] = (struct usb_descriptor_header *) &header_desc;
@@ -843,11 +842,11 @@ static struct usb_string strings[] = {
{ STRING_SERIALNUMBER, serial_number, },
{ STRING_DATA, "Ethernet Data", },
{ STRING_ETHADDR, ethaddr, },
-#ifdef DEV_CONFIG_CDC
+#ifdef CONFIG_USB_ETH_CDC
{ STRING_CDC, "CDC Ethernet", },
{ STRING_CONTROL, "CDC Communications Control", },
#endif
-#ifdef DEV_CONFIG_SUBSET
+#ifdef CONFIG_USB_ETH_SUBSET
{ STRING_SUBSET, "CDC Ethernet Subset", },
#endif
#ifdef CONFIG_USB_ETH_RNDIS
@@ -864,7 +863,9 @@ static struct usb_gadget_strings stringtab = {
/*============================================================================*/
static u8 control_req[USB_BUFSIZ];
+#if defined(CONFIG_USB_ETH_CDC) || defined(CONFIG_USB_ETH_RNDIS)
static u8 status_req[STATUS_BYTECOUNT] __attribute__ ((aligned(4)));
+#endif
/**
@@ -951,7 +952,7 @@ set_ether_config(struct eth_dev *dev, gfp_t gfp_flags)
int result = 0;
struct usb_gadget *gadget = dev->gadget;
-#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
+#if defined(CONFIG_USB_ETH_CDC) || defined(CONFIG_USB_ETH_RNDIS)
/* status endpoint used for RNDIS and (optionally) CDC */
if (!subset_active(dev) && dev->status_ep) {
dev->status = ep_desc(gadget, &hs_status_desc,
@@ -1132,7 +1133,7 @@ static int eth_set_config(struct eth_dev *dev, unsigned number,
/*-------------------------------------------------------------------------*/
-#ifdef DEV_CONFIG_CDC
+#ifdef CONFIG_USB_ETH_CDC
/*
* The interrupt endpoint is used in CDC networking models (Ethernet, ATM)
@@ -1352,10 +1353,18 @@ eth_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
if (gadget_is_pxa(gadget)) {
value = eth_set_config(dev, DEV_CONFIG_VALUE,
GFP_ATOMIC);
+ /*
+ * PXA25x driver use non-CDC ethernet gadget.
+ * But only _CDC and _RNDIS code can signalize
+ * that network is working. So we signalize it
+ * here.
+ */
+ l_ethdev.network_started = 1;
+ debug("USB network up!\n");
goto done_set_intf;
}
-#ifdef DEV_CONFIG_CDC
+#ifdef CONFIG_USB_ETH_CDC
switch (wIndex) {
case 0: /* control/master intf */
if (wValue != 0)
@@ -1397,7 +1406,7 @@ eth_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
* all non-PXA hardware talks real CDC ...
*/
debug("set_interface ignored!\n");
-#endif /* DEV_CONFIG_CDC */
+#endif /* CONFIG_USB_ETH_CDC */
done_set_intf:
break;
@@ -1420,7 +1429,7 @@ done_set_intf:
value = min(wLength, (u16) 1);
break;
-#ifdef DEV_CONFIG_CDC
+#ifdef CONFIG_USB_ETH_CDC
case USB_CDC_SET_ETHERNET_PACKET_FILTER:
/*
* see 6.2.30: no data, wIndex = interface,
@@ -1444,7 +1453,7 @@ done_set_intf:
* case USB_CDC_GET_ETHERNET_STATISTIC:
*/
-#endif /* DEV_CONFIG_CDC */
+#endif /* CONFIG_USB_ETH_CDC */
#ifdef CONFIG_USB_ETH_RNDIS
/*
@@ -2015,7 +2024,7 @@ static int eth_bind(struct usb_gadget *gadget)
u8 tmp[7];
/* these flags are only ever cleared; compiler take note */
-#ifndef DEV_CONFIG_CDC
+#ifndef CONFIG_USB_ETH_CDC
cdc = 0;
#endif
#ifndef CONFIG_USB_ETH_RNDIS
@@ -2127,7 +2136,7 @@ autoconf_fail:
goto autoconf_fail;
out_ep->driver_data = out_ep; /* claim */
-#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
+#if defined(CONFIG_USB_ETH_CDC) || defined(CONFIG_USB_ETH_RNDIS)
/*
* CDC Ethernet control interface doesn't require a status endpoint.
* Since some hosts expect one, try to allocate one anyway.
@@ -2139,7 +2148,7 @@ autoconf_fail:
} else if (rndis) {
error("can't run RNDIS on %s", gadget->name);
return -ENODEV;
-#ifdef DEV_CONFIG_CDC
+#ifdef CONFIG_USB_ETH_CDC
} else if (cdc) {
control_intf.bNumEndpoints = 0;
/* FIXME remove endpoint from descriptor list */
@@ -2182,7 +2191,7 @@ autoconf_fail:
fs_source_desc.bEndpointAddress;
hs_sink_desc.bEndpointAddress =
fs_sink_desc.bEndpointAddress;
-#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
+#if defined(CONFIG_USB_ETH_CDC) || defined(CONFIG_USB_ETH_RNDIS)
if (status_ep)
hs_status_desc.bEndpointAddress =
fs_status_desc.bEndpointAddress;
@@ -2251,7 +2260,7 @@ autoconf_fail:
dev->req->complete = eth_setup_complete;
/* ... and maybe likewise for status transfer */
-#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
+#if defined(CONFIG_USB_ETH_CDC) || defined(CONFIG_USB_ETH_RNDIS)
if (dev->status_ep) {
dev->stat_req = usb_ep_alloc_request(dev->status_ep,
GFP_KERNEL);
diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c
new file mode 100644
index 0000000000..dd741439ae
--- /dev/null
+++ b/drivers/usb/gadget/pxa25x_udc.c
@@ -0,0 +1,2059 @@
+/*
+ * Intel PXA25x and IXP4xx on-chip full speed USB device controllers
+ *
+ * Copyright (C) 2002 Intrinsyc, Inc. (Frank Becker)
+ * Copyright (C) 2003 Robert Schwebel, Pengutronix
+ * Copyright (C) 2003 Benedikt Spranger, Pengutronix
+ * Copyright (C) 2003 David Brownell
+ * Copyright (C) 2003 Joshua Wise
+ * Copyright (C) 2012 Lukasz Dalek <luk0104@gmail.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
+ *
+ * MODULE_AUTHOR("Frank Becker, Robert Schwebel, David Brownell");
+ */
+
+#define CONFIG_USB_PXA25X_SMALL
+#define DRIVER_NAME "pxa25x_udc_linux"
+#define ARCH_HAS_PREFETCH
+
+#include <common.h>
+#include <errno.h>
+#include <asm/byteorder.h>
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <asm/unaligned.h>
+#include <linux/compat.h>
+#include <malloc.h>
+#include <asm/io.h>
+#include <asm/arch/pxa.h>
+
+#include <usbdescriptors.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <usb/lin_gadget_compat.h>
+#include <asm/arch/pxa-regs.h>
+
+#include "pxa25x_udc.h"
+
+/*
+ * This driver handles the USB Device Controller (UDC) in Intel's PXA 25x
+ * series processors. The UDC for the IXP 4xx series is very similar.
+ * There are fifteen endpoints, in addition to ep0.
+ *
+ * Such controller drivers work with a gadget driver. The gadget driver
+ * returns descriptors, implements configuration and data protocols used
+ * by the host to interact with this device, and allocates endpoints to
+ * the different protocol interfaces. The controller driver virtualizes
+ * usb hardware so that the gadget drivers will be more portable.
+ *
+ * This UDC hardware wants to implement a bit too much USB protocol, so
+ * it constrains the sorts of USB configuration change events that work.
+ * The errata for these chips are misleading; some "fixed" bugs from
+ * pxa250 a0/a1 b0/b1/b2 sure act like they're still there.
+ *
+ * Note that the UDC hardware supports DMA (except on IXP) but that's
+ * not used here. IN-DMA (to host) is simple enough, when the data is
+ * suitably aligned (16 bytes) ... the network stack doesn't do that,
+ * other software can. OUT-DMA is buggy in most chip versions, as well
+ * as poorly designed (data toggle not automatic). So this driver won't
+ * bother using DMA. (Mostly-working IN-DMA support was available in
+ * kernels before 2.6.23, but was never enabled or well tested.)
+ */
+
+#define DRIVER_VERSION "18-August-2012"
+#define DRIVER_DESC "PXA 25x USB Device Controller driver"
+
+static const char driver_name[] = "pxa25x_udc";
+static const char ep0name[] = "ep0";
+
+/* Watchdog */
+static inline void start_watchdog(struct pxa25x_udc *udc)
+{
+ debug("Started watchdog\n");
+ udc->watchdog.base = get_timer(0);
+ udc->watchdog.running = 1;
+}
+
+static inline void stop_watchdog(struct pxa25x_udc *udc)
+{
+ udc->watchdog.running = 0;
+ debug("Stopped watchdog\n");
+}
+
+static inline void test_watchdog(struct pxa25x_udc *udc)
+{
+ if (!udc->watchdog.running)
+ return;
+
+ debug("watchdog %ld %ld\n", get_timer(udc->watchdog.base),
+ udc->watchdog.period);
+
+ if (get_timer(udc->watchdog.base) >= udc->watchdog.period) {
+ stop_watchdog(udc);
+ udc->watchdog.function(udc);
+ }
+}
+
+static void udc_watchdog(struct pxa25x_udc *dev)
+{
+ uint32_t udccs0 = readl(&dev->regs->udccs[0]);
+
+ debug("Fired up udc_watchdog\n");
+
+ local_irq_disable();
+ if (dev->ep0state == EP0_STALL
+ && (udccs0 & UDCCS0_FST) == 0
+ && (udccs0 & UDCCS0_SST) == 0) {
+ writel(UDCCS0_FST|UDCCS0_FTF, &dev->regs->udccs[0]);
+ debug("ep0 re-stall\n");
+ start_watchdog(dev);
+ }
+ local_irq_enable();
+}
+
+#ifdef DEBUG
+
+static const char * const state_name[] = {
+ "EP0_IDLE",
+ "EP0_IN_DATA_PHASE", "EP0_OUT_DATA_PHASE",
+ "EP0_END_XFER", "EP0_STALL"
+};
+
+static void
+dump_udccr(const char *label)
+{
+ u32 udccr = readl(&UDC_REGS->udccr);
+ debug("%s %02X =%s%s%s%s%s%s%s%s\n",
+ label, udccr,
+ (udccr & UDCCR_REM) ? " rem" : "",
+ (udccr & UDCCR_RSTIR) ? " rstir" : "",
+ (udccr & UDCCR_SRM) ? " srm" : "",
+ (udccr & UDCCR_SUSIR) ? " susir" : "",
+ (udccr & UDCCR_RESIR) ? " resir" : "",
+ (udccr & UDCCR_RSM) ? " rsm" : "",
+ (udccr & UDCCR_UDA) ? " uda" : "",
+ (udccr & UDCCR_UDE) ? " ude" : "");
+}
+
+static void
+dump_udccs0(const char *label)
+{
+ u32 udccs0 = readl(&UDC_REGS->udccs[0]);
+
+ debug("%s %s %02X =%s%s%s%s%s%s%s%s\n",
+ label, state_name[the_controller->ep0state], udccs0,
+ (udccs0 & UDCCS0_SA) ? " sa" : "",
+ (udccs0 & UDCCS0_RNE) ? " rne" : "",
+ (udccs0 & UDCCS0_FST) ? " fst" : "",
+ (udccs0 & UDCCS0_SST) ? " sst" : "",
+ (udccs0 & UDCCS0_DRWF) ? " dwrf" : "",
+ (udccs0 & UDCCS0_FTF) ? " ftf" : "",
+ (udccs0 & UDCCS0_IPR) ? " ipr" : "",
+ (udccs0 & UDCCS0_OPR) ? " opr" : "");
+}
+
+static void
+dump_state(struct pxa25x_udc *dev)
+{
+ u32 tmp;
+ unsigned i;
+
+ debug("%s, uicr %02X.%02X, usir %02X.%02x, ufnr %02X.%02X\n",
+ state_name[dev->ep0state],
+ readl(&UDC_REGS->uicr1), readl(&UDC_REGS->uicr0),
+ readl(&UDC_REGS->usir1), readl(&UDC_REGS->usir0),
+ readl(&UDC_REGS->ufnrh), readl(&UDC_REGS->ufnrl));
+ dump_udccr("udccr");
+ if (dev->has_cfr) {
+ tmp = readl(&UDC_REGS->udccfr);
+ debug("udccfr %02X =%s%s\n", tmp,
+ (tmp & UDCCFR_AREN) ? " aren" : "",
+ (tmp & UDCCFR_ACM) ? " acm" : "");
+ }
+
+ if (!dev->driver) {
+ debug("no gadget driver bound\n");
+ return;
+ } else
+ debug("ep0 driver '%s'\n", "ether");
+
+ dump_udccs0("udccs0");
+ debug("ep0 IN %lu/%lu, OUT %lu/%lu\n",
+ dev->stats.write.bytes, dev->stats.write.ops,
+ dev->stats.read.bytes, dev->stats.read.ops);
+
+ for (i = 1; i < PXA_UDC_NUM_ENDPOINTS; i++) {
+ if (dev->ep[i].desc == NULL)
+ continue;
+ debug("udccs%d = %02x\n", i, *dev->ep->reg_udccs);
+ }
+}
+
+#else /* DEBUG */
+
+static inline void dump_udccr(const char *label) { }
+static inline void dump_udccs0(const char *label) { }
+static inline void dump_state(struct pxa25x_udc *dev) { }
+
+#endif /* DEBUG */
+
+/*
+ * ---------------------------------------------------------------------------
+ * endpoint related parts of the api to the usb controller hardware,
+ * used by gadget driver; and the inner talker-to-hardware core.
+ * ---------------------------------------------------------------------------
+ */
+
+static void pxa25x_ep_fifo_flush(struct usb_ep *ep);
+static void nuke(struct pxa25x_ep *, int status);
+
+/* one GPIO should control a D+ pullup, so host sees this device (or not) */
+static void pullup_off(void)
+{
+ struct pxa2xx_udc_mach_info *mach = the_controller->mach;
+
+ if (mach->udc_command)
+ mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT);
+}
+
+static void pullup_on(void)
+{
+ struct pxa2xx_udc_mach_info *mach = the_controller->mach;
+
+ if (mach->udc_command)
+ mach->udc_command(PXA2XX_UDC_CMD_CONNECT);
+}
+
+static void pio_irq_enable(int bEndpointAddress)
+{
+ bEndpointAddress &= 0xf;
+ if (bEndpointAddress < 8) {
+ clrbits_le32(&the_controller->regs->uicr0,
+ 1 << bEndpointAddress);
+ } else {
+ bEndpointAddress -= 8;
+ clrbits_le32(&the_controller->regs->uicr1,
+ 1 << bEndpointAddress);
+ }
+}
+
+static void pio_irq_disable(int bEndpointAddress)
+{
+ bEndpointAddress &= 0xf;
+ if (bEndpointAddress < 8) {
+ setbits_le32(&the_controller->regs->uicr0,
+ 1 << bEndpointAddress);
+ } else {
+ bEndpointAddress -= 8;
+ setbits_le32(&the_controller->regs->uicr1,
+ 1 << bEndpointAddress);
+ }
+}
+
+static inline void udc_set_mask_UDCCR(int mask)
+{
+ /*
+ * The UDCCR reg contains mask and interrupt status bits,
+ * so using '|=' isn't safe as it may ack an interrupt.
+ */
+ const uint32_t mask_bits = UDCCR_REM | UDCCR_SRM | UDCCR_UDE;
+
+ mask &= mask_bits;
+ clrsetbits_le32(&the_controller->regs->udccr, ~mask_bits, mask);
+}
+
+static inline void udc_clear_mask_UDCCR(int mask)
+{
+ const uint32_t mask_bits = UDCCR_REM | UDCCR_SRM | UDCCR_UDE;
+
+ mask = ~mask & mask_bits;
+ clrbits_le32(&the_controller->regs->udccr, ~mask);
+}
+
+static inline void udc_ack_int_UDCCR(int mask)
+{
+ const uint32_t mask_bits = UDCCR_REM | UDCCR_SRM | UDCCR_UDE;
+
+ mask &= ~mask_bits;
+ clrsetbits_le32(&the_controller->regs->udccr, ~mask_bits, mask);
+}
+
+/*
+ * endpoint enable/disable
+ *
+ * we need to verify the descriptors used to enable endpoints. since pxa25x
+ * endpoint configurations are fixed, and are pretty much always enabled,
+ * there's not a lot to manage here.
+ *
+ * because pxa25x can't selectively initialize bulk (or interrupt) endpoints,
+ * (resetting endpoint halt and toggle), SET_INTERFACE is unusable except
+ * for a single interface (with only the default altsetting) and for gadget
+ * drivers that don't halt endpoints (not reset by set_interface). that also
+ * means that if you use ISO, you must violate the USB spec rule that all
+ * iso endpoints must be in non-default altsettings.
+ */
+static int pxa25x_ep_enable(struct usb_ep *_ep,
+ const struct usb_endpoint_descriptor *desc)
+{
+ struct pxa25x_ep *ep;
+ struct pxa25x_udc *dev;
+
+ ep = container_of(_ep, struct pxa25x_ep, ep);
+ if (!_ep || !desc || ep->desc || _ep->name == ep0name
+ || desc->bDescriptorType != USB_DT_ENDPOINT
+ || ep->bEndpointAddress != desc->bEndpointAddress
+ || ep->fifo_size < le16_to_cpu(desc->wMaxPacketSize)) {
+ printf("%s, bad ep or descriptor\n", __func__);
+ return -EINVAL;
+ }
+
+ /* xfer types must match, except that interrupt ~= bulk */
+ if (ep->bmAttributes != desc->bmAttributes
+ && ep->bmAttributes != USB_ENDPOINT_XFER_BULK
+ && desc->bmAttributes != USB_ENDPOINT_XFER_INT) {
+ printf("%s, %s type mismatch\n", __func__, _ep->name);
+ return -EINVAL;
+ }
+
+ /* hardware _could_ do smaller, but driver doesn't */
+ if ((desc->bmAttributes == USB_ENDPOINT_XFER_BULK
+ && le16_to_cpu(desc->wMaxPacketSize)
+ != BULK_FIFO_SIZE)
+ || !desc->wMaxPacketSize) {
+ printf("%s, bad %s maxpacket\n", __func__, _ep->name);
+ return -ERANGE;
+ }
+
+ dev = ep->dev;
+ if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) {
+ printf("%s, bogus device state\n", __func__);
+ return -ESHUTDOWN;
+ }
+
+ ep->desc = desc;
+ ep->stopped = 0;
+ ep->pio_irqs = 0;
+ ep->ep.maxpacket = le16_to_cpu(desc->wMaxPacketSize);
+
+ /* flush fifo (mostly for OUT buffers) */
+ pxa25x_ep_fifo_flush(_ep);
+
+ /* ... reset halt state too, if we could ... */
+
+ debug("enabled %s\n", _ep->name);
+ return 0;
+}
+
+static int pxa25x_ep_disable(struct usb_ep *_ep)
+{
+ struct pxa25x_ep *ep;
+ unsigned long flags;
+
+ ep = container_of(_ep, struct pxa25x_ep, ep);
+ if (!_ep || !ep->desc) {
+ printf("%s, %s not enabled\n", __func__,
+ _ep ? ep->ep.name : NULL);
+ return -EINVAL;
+ }
+ local_irq_save(flags);
+
+ nuke(ep, -ESHUTDOWN);
+
+ /* flush fifo (mostly for IN buffers) */
+ pxa25x_ep_fifo_flush(_ep);
+
+ ep->desc = NULL;
+ ep->stopped = 1;
+
+ local_irq_restore(flags);
+ debug("%s disabled\n", _ep->name);
+ return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * for the pxa25x, these can just wrap kmalloc/kfree. gadget drivers
+ * must still pass correctly initialized endpoints, since other controller
+ * drivers may care about how it's currently set up (dma issues etc).
+ */
+
+/*
+ * pxa25x_ep_alloc_request - allocate a request data structure
+ */
+static struct usb_request *
+pxa25x_ep_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
+{
+ struct pxa25x_request *req;
+
+ req = kzalloc(sizeof(*req), gfp_flags);
+ if (!req)
+ return NULL;
+
+ INIT_LIST_HEAD(&req->queue);
+ return &req->req;
+}
+
+
+/*
+ * pxa25x_ep_free_request - deallocate a request data structure
+ */
+static void
+pxa25x_ep_free_request(struct usb_ep *_ep, struct usb_request *_req)
+{
+ struct pxa25x_request *req;
+
+ req = container_of(_req, struct pxa25x_request, req);
+ WARN_ON(!list_empty(&req->queue));
+ kfree(req);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * done - retire a request; caller blocked irqs
+ */
+static void done(struct pxa25x_ep *ep, struct pxa25x_request *req, int status)
+{
+ unsigned stopped = ep->stopped;
+
+ list_del_init(&req->queue);
+
+ if (likely(req->req.status == -EINPROGRESS))
+ req->req.status = status;
+ else
+ status = req->req.status;
+
+ if (status && status != -ESHUTDOWN)
+ debug("complete %s req %p stat %d len %u/%u\n",
+ ep->ep.name, &req->req, status,
+ req->req.actual, req->req.length);
+
+ /* don't modify queue heads during completion callback */
+ ep->stopped = 1;
+ req->req.complete(&ep->ep, &req->req);
+ ep->stopped = stopped;
+}
+
+
+static inline void ep0_idle(struct pxa25x_udc *dev)
+{
+ dev->ep0state = EP0_IDLE;
+}
+
+static int
+write_packet(u32 *uddr, struct pxa25x_request *req, unsigned max)
+{
+ u8 *buf;
+ unsigned length, count;
+
+ debug("%s(): uddr %p\n", __func__, uddr);
+
+ buf = req->req.buf + req->req.actual;
+ prefetch(buf);
+
+ /* how big will this packet be? */
+ length = min(req->req.length - req->req.actual, max);
+ req->req.actual += length;
+
+ count = length;
+ while (likely(count--))
+ writeb(*buf++, uddr);
+
+ return length;
+}
+
+/*
+ * write to an IN endpoint fifo, as many packets as possible.
+ * irqs will use this to write the rest later.
+ * caller guarantees at least one packet buffer is ready (or a zlp).
+ */
+static int
+write_fifo(struct pxa25x_ep *ep, struct pxa25x_request *req)
+{
+ unsigned max;
+
+ max = le16_to_cpu(ep->desc->wMaxPacketSize);
+ do {
+ unsigned count;
+ int is_last, is_short;
+
+ count = write_packet(ep->reg_uddr, req, max);
+
+ /* last packet is usually short (or a zlp) */
+ if (unlikely(count != max))
+ is_last = is_short = 1;
+ else {
+ if (likely(req->req.length != req->req.actual)
+ || req->req.zero)
+ is_last = 0;
+ else
+ is_last = 1;
+ /* interrupt/iso maxpacket may not fill the fifo */
+ is_short = unlikely(max < ep->fifo_size);
+ }
+
+ debug_cond(NOISY, "wrote %s %d bytes%s%s %d left %p\n",
+ ep->ep.name, count,
+ is_last ? "/L" : "", is_short ? "/S" : "",
+ req->req.length - req->req.actual, req);
+
+ /*
+ * let loose that packet. maybe try writing another one,
+ * double buffering might work. TSP, TPC, and TFS
+ * bit values are the same for all normal IN endpoints.
+ */
+ writel(UDCCS_BI_TPC, ep->reg_udccs);
+ if (is_short)
+ writel(UDCCS_BI_TSP, ep->reg_udccs);
+
+ /* requests complete when all IN data is in the FIFO */
+ if (is_last) {
+ done(ep, req, 0);
+ if (list_empty(&ep->queue))
+ pio_irq_disable(ep->bEndpointAddress);
+ return 1;
+ }
+
+ /*
+ * TODO experiment: how robust can fifo mode tweaking be?
+ * double buffering is off in the default fifo mode, which
+ * prevents TFS from being set here.
+ */
+
+ } while (readl(ep->reg_udccs) & UDCCS_BI_TFS);
+ return 0;
+}
+
+/*
+ * caller asserts req->pending (ep0 irq status nyet cleared); starts
+ * ep0 data stage. these chips want very simple state transitions.
+ */
+static inline
+void ep0start(struct pxa25x_udc *dev, u32 flags, const char *tag)
+{
+ writel(flags|UDCCS0_SA|UDCCS0_OPR, &dev->regs->udccs[0]);
+ writel(USIR0_IR0, &dev->regs->usir0);
+ dev->req_pending = 0;
+ debug_cond(NOISY, "%s() %s, udccs0: %02x/%02x usir: %X.%X\n",
+ __func__, tag, readl(&dev->regs->udccs[0]), flags,
+ readl(&dev->regs->usir1), readl(&dev->regs->usir0));
+}
+
+static int
+write_ep0_fifo(struct pxa25x_ep *ep, struct pxa25x_request *req)
+{
+ unsigned count;
+ int is_short;
+
+ count = write_packet(&ep->dev->regs->uddr0, req, EP0_FIFO_SIZE);
+ ep->dev->stats.write.bytes += count;
+
+ /* last packet "must be" short (or a zlp) */
+ is_short = (count != EP0_FIFO_SIZE);
+
+ debug_cond(NOISY, "ep0in %d bytes %d left %p\n", count,
+ req->req.length - req->req.actual, req);
+
+ if (unlikely(is_short)) {
+ if (ep->dev->req_pending)
+ ep0start(ep->dev, UDCCS0_IPR, "short IN");
+ else
+ writel(UDCCS0_IPR, &ep->dev->regs->udccs[0]);
+
+ count = req->req.length;
+ done(ep, req, 0);
+ ep0_idle(ep->dev);
+
+ /*
+ * This seems to get rid of lost status irqs in some cases:
+ * host responds quickly, or next request involves config
+ * change automagic, or should have been hidden, or ...
+ *
+ * FIXME get rid of all udelays possible...
+ */
+ if (count >= EP0_FIFO_SIZE) {
+ count = 100;
+ do {
+ if ((readl(&ep->dev->regs->udccs[0]) &
+ UDCCS0_OPR) != 0) {
+ /* clear OPR, generate ack */
+ writel(UDCCS0_OPR,
+ &ep->dev->regs->udccs[0]);
+ break;
+ }
+ count--;
+ udelay(1);
+ } while (count);
+ }
+ } else if (ep->dev->req_pending)
+ ep0start(ep->dev, 0, "IN");
+
+ return is_short;
+}
+
+
+/*
+ * read_fifo - unload packet(s) from the fifo we use for usb OUT
+ * transfers and put them into the request. caller should have made
+ * sure there's at least one packet ready.
+ *
+ * returns true if the request completed because of short packet or the
+ * request buffer having filled (and maybe overran till end-of-packet).
+ */
+static int
+read_fifo(struct pxa25x_ep *ep, struct pxa25x_request *req)
+{
+ u32 udccs;
+ u8 *buf;
+ unsigned bufferspace, count, is_short;
+
+ for (;;) {
+ /*
+ * make sure there's a packet in the FIFO.
+ * UDCCS_{BO,IO}_RPC are all the same bit value.
+ * UDCCS_{BO,IO}_RNE are all the same bit value.
+ */
+ udccs = readl(ep->reg_udccs);
+ if (unlikely((udccs & UDCCS_BO_RPC) == 0))
+ break;
+ buf = req->req.buf + req->req.actual;
+ prefetchw(buf);
+ bufferspace = req->req.length - req->req.actual;
+
+ /* read all bytes from this packet */
+ if (likely(udccs & UDCCS_BO_RNE)) {
+ count = 1 + (0x0ff & readl(ep->reg_ubcr));
+ req->req.actual += min(count, bufferspace);
+ } else /* zlp */
+ count = 0;
+ is_short = (count < ep->ep.maxpacket);
+ debug_cond(NOISY, "read %s %02x, %d bytes%s req %p %d/%d\n",
+ ep->ep.name, udccs, count,
+ is_short ? "/S" : "",
+ req, req->req.actual, req->req.length);
+ while (likely(count-- != 0)) {
+ u8 byte = readb(ep->reg_uddr);
+
+ if (unlikely(bufferspace == 0)) {
+ /*
+ * this happens when the driver's buffer
+ * is smaller than what the host sent.
+ * discard the extra data.
+ */
+ if (req->req.status != -EOVERFLOW)
+ printf("%s overflow %d\n",
+ ep->ep.name, count);
+ req->req.status = -EOVERFLOW;
+ } else {
+ *buf++ = byte;
+ bufferspace--;
+ }
+ }
+ writel(UDCCS_BO_RPC, ep->reg_udccs);
+ /* RPC/RSP/RNE could now reflect the other packet buffer */
+
+ /* iso is one request per packet */
+ if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
+ if (udccs & UDCCS_IO_ROF)
+ req->req.status = -EHOSTUNREACH;
+ /* more like "is_done" */
+ is_short = 1;
+ }
+
+ /* completion */
+ if (is_short || req->req.actual == req->req.length) {
+ done(ep, req, 0);
+ if (list_empty(&ep->queue))
+ pio_irq_disable(ep->bEndpointAddress);
+ return 1;
+ }
+
+ /* finished that packet. the next one may be waiting... */
+ }
+ return 0;
+}
+
+/*
+ * special ep0 version of the above. no UBCR0 or double buffering; status
+ * handshaking is magic. most device protocols don't need control-OUT.
+ * CDC vendor commands (and RNDIS), mass storage CB/CBI, and some other
+ * protocols do use them.
+ */
+static int
+read_ep0_fifo(struct pxa25x_ep *ep, struct pxa25x_request *req)
+{
+ u8 *buf, byte;
+ unsigned bufferspace;
+
+ buf = req->req.buf + req->req.actual;
+ bufferspace = req->req.length - req->req.actual;
+
+ while (readl(&ep->dev->regs->udccs[0]) & UDCCS0_RNE) {
+ byte = (u8)readb(&ep->dev->regs->uddr0);
+
+ if (unlikely(bufferspace == 0)) {
+ /*
+ * this happens when the driver's buffer
+ * is smaller than what the host sent.
+ * discard the extra data.
+ */
+ if (req->req.status != -EOVERFLOW)
+ printf("%s overflow\n", ep->ep.name);
+ req->req.status = -EOVERFLOW;
+ } else {
+ *buf++ = byte;
+ req->req.actual++;
+ bufferspace--;
+ }
+ }
+
+ writel(UDCCS0_OPR | UDCCS0_IPR, &ep->dev->regs->udccs[0]);
+
+ /* completion */
+ if (req->req.actual >= req->req.length)
+ return 1;
+
+ /* finished that packet. the next one may be waiting... */
+ return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int
+pxa25x_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
+{
+ struct pxa25x_request *req;
+ struct pxa25x_ep *ep;
+ struct pxa25x_udc *dev;
+ unsigned long flags;
+
+ req = container_of(_req, struct pxa25x_request, req);
+ if (unlikely(!_req || !_req->complete || !_req->buf
+ || !list_empty(&req->queue))) {
+ printf("%s, bad params\n", __func__);
+ return -EINVAL;
+ }
+
+ ep = container_of(_ep, struct pxa25x_ep, ep);
+ if (unlikely(!_ep || (!ep->desc && ep->ep.name != ep0name))) {
+ printf("%s, bad ep\n", __func__);
+ return -EINVAL;
+ }
+
+ dev = ep->dev;
+ if (unlikely(!dev->driver
+ || dev->gadget.speed == USB_SPEED_UNKNOWN)) {
+ printf("%s, bogus device state\n", __func__);
+ return -ESHUTDOWN;
+ }
+
+ /*
+ * iso is always one packet per request, that's the only way
+ * we can report per-packet status. that also helps with dma.
+ */
+ if (unlikely(ep->bmAttributes == USB_ENDPOINT_XFER_ISOC
+ && req->req.length >
+ le16_to_cpu(ep->desc->wMaxPacketSize)))
+ return -EMSGSIZE;
+
+ debug_cond(NOISY, "%s queue req %p, len %d buf %p\n",
+ _ep->name, _req, _req->length, _req->buf);
+
+ local_irq_save(flags);
+
+ _req->status = -EINPROGRESS;
+ _req->actual = 0;
+
+ /* kickstart this i/o queue? */
+ if (list_empty(&ep->queue) && !ep->stopped) {
+ if (ep->desc == NULL/* ep0 */) {
+ unsigned length = _req->length;
+
+ switch (dev->ep0state) {
+ case EP0_IN_DATA_PHASE:
+ dev->stats.write.ops++;
+ if (write_ep0_fifo(ep, req))
+ req = NULL;
+ break;
+
+ case EP0_OUT_DATA_PHASE:
+ dev->stats.read.ops++;
+ /* messy ... */
+ if (dev->req_config) {
+ debug("ep0 config ack%s\n",
+ dev->has_cfr ? "" : " raced");
+ if (dev->has_cfr)
+ writel(UDCCFR_AREN|UDCCFR_ACM
+ |UDCCFR_MB1,
+ &ep->dev->regs->udccfr);
+ done(ep, req, 0);
+ dev->ep0state = EP0_END_XFER;
+ local_irq_restore(flags);
+ return 0;
+ }
+ if (dev->req_pending)
+ ep0start(dev, UDCCS0_IPR, "OUT");
+ if (length == 0 ||
+ ((readl(
+ &ep->dev->regs->udccs[0])
+ & UDCCS0_RNE) != 0
+ && read_ep0_fifo(ep, req))) {
+ ep0_idle(dev);
+ done(ep, req, 0);
+ req = NULL;
+ }
+ break;
+
+ default:
+ printf("ep0 i/o, odd state %d\n",
+ dev->ep0state);
+ local_irq_restore(flags);
+ return -EL2HLT;
+ }
+ /* can the FIFO can satisfy the request immediately? */
+ } else if ((ep->bEndpointAddress & USB_DIR_IN) != 0) {
+ if ((readl(ep->reg_udccs) & UDCCS_BI_TFS) != 0
+ && write_fifo(ep, req))
+ req = NULL;
+ } else if ((readl(ep->reg_udccs) & UDCCS_BO_RFS) != 0
+ && read_fifo(ep, req)) {
+ req = NULL;
+ }
+
+ if (likely(req && ep->desc))
+ pio_irq_enable(ep->bEndpointAddress);
+ }
+
+ /* pio or dma irq handler advances the queue. */
+ if (likely(req != NULL))
+ list_add_tail(&req->queue, &ep->queue);
+ local_irq_restore(flags);
+
+ return 0;
+}
+
+
+/*
+ * nuke - dequeue ALL requests
+ */
+static void nuke(struct pxa25x_ep *ep, int status)
+{
+ struct pxa25x_request *req;
+
+ /* called with irqs blocked */
+ while (!list_empty(&ep->queue)) {
+ req = list_entry(ep->queue.next,
+ struct pxa25x_request,
+ queue);
+ done(ep, req, status);
+ }
+ if (ep->desc)
+ pio_irq_disable(ep->bEndpointAddress);
+}
+
+
+/* dequeue JUST ONE request */
+static int pxa25x_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+ struct pxa25x_ep *ep;
+ struct pxa25x_request *req;
+ unsigned long flags;
+
+ ep = container_of(_ep, struct pxa25x_ep, ep);
+ if (!_ep || ep->ep.name == ep0name)
+ return -EINVAL;
+
+ local_irq_save(flags);
+
+ /* make sure it's actually queued on this endpoint */
+ list_for_each_entry(req, &ep->queue, queue) {
+ if (&req->req == _req)
+ break;
+ }
+ if (&req->req != _req) {
+ local_irq_restore(flags);
+ return -EINVAL;
+ }
+
+ done(ep, req, -ECONNRESET);
+
+ local_irq_restore(flags);
+ return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int pxa25x_ep_set_halt(struct usb_ep *_ep, int value)
+{
+ struct pxa25x_ep *ep;
+ unsigned long flags;
+
+ ep = container_of(_ep, struct pxa25x_ep, ep);
+ if (unlikely(!_ep
+ || (!ep->desc && ep->ep.name != ep0name))
+ || ep->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
+ printf("%s, bad ep\n", __func__);
+ return -EINVAL;
+ }
+ if (value == 0) {
+ /*
+ * this path (reset toggle+halt) is needed to implement
+ * SET_INTERFACE on normal hardware. but it can't be
+ * done from software on the PXA UDC, and the hardware
+ * forgets to do it as part of SET_INTERFACE automagic.
+ */
+ printf("only host can clear %s halt\n", _ep->name);
+ return -EROFS;
+ }
+
+ local_irq_save(flags);
+
+ if ((ep->bEndpointAddress & USB_DIR_IN) != 0
+ && ((readl(ep->reg_udccs) & UDCCS_BI_TFS) == 0
+ || !list_empty(&ep->queue))) {
+ local_irq_restore(flags);
+ return -EAGAIN;
+ }
+
+ /* FST bit is the same for control, bulk in, bulk out, interrupt in */
+ writel(UDCCS_BI_FST|UDCCS_BI_FTF, ep->reg_udccs);
+
+ /* ep0 needs special care */
+ if (!ep->desc) {
+ start_watchdog(ep->dev);
+ ep->dev->req_pending = 0;
+ ep->dev->ep0state = EP0_STALL;
+
+ /* and bulk/intr endpoints like dropping stalls too */
+ } else {
+ unsigned i;
+ for (i = 0; i < 1000; i += 20) {
+ if (readl(ep->reg_udccs) & UDCCS_BI_SST)
+ break;
+ udelay(20);
+ }
+ }
+ local_irq_restore(flags);
+
+ debug("%s halt\n", _ep->name);
+ return 0;
+}
+
+static int pxa25x_ep_fifo_status(struct usb_ep *_ep)
+{
+ struct pxa25x_ep *ep;
+
+ ep = container_of(_ep, struct pxa25x_ep, ep);
+ if (!_ep) {
+ printf("%s, bad ep\n", __func__);
+ return -ENODEV;
+ }
+ /* pxa can't report unclaimed bytes from IN fifos */
+ if ((ep->bEndpointAddress & USB_DIR_IN) != 0)
+ return -EOPNOTSUPP;
+ if (ep->dev->gadget.speed == USB_SPEED_UNKNOWN
+ || (readl(ep->reg_udccs) & UDCCS_BO_RFS) == 0)
+ return 0;
+ else
+ return (readl(ep->reg_ubcr) & 0xfff) + 1;
+}
+
+static void pxa25x_ep_fifo_flush(struct usb_ep *_ep)
+{
+ struct pxa25x_ep *ep;
+
+ ep = container_of(_ep, struct pxa25x_ep, ep);
+ if (!_ep || ep->ep.name == ep0name || !list_empty(&ep->queue)) {
+ printf("%s, bad ep\n", __func__);
+ return;
+ }
+
+ /* toggle and halt bits stay unchanged */
+
+ /* for OUT, just read and discard the FIFO contents. */
+ if ((ep->bEndpointAddress & USB_DIR_IN) == 0) {
+ while (((readl(ep->reg_udccs)) & UDCCS_BO_RNE) != 0)
+ (void)readb(ep->reg_uddr);
+ return;
+ }
+
+ /* most IN status is the same, but ISO can't stall */
+ writel(UDCCS_BI_TPC|UDCCS_BI_FTF|UDCCS_BI_TUR
+ | (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC
+ ? 0 : UDCCS_BI_SST), ep->reg_udccs);
+}
+
+
+static struct usb_ep_ops pxa25x_ep_ops = {
+ .enable = pxa25x_ep_enable,
+ .disable = pxa25x_ep_disable,
+
+ .alloc_request = pxa25x_ep_alloc_request,
+ .free_request = pxa25x_ep_free_request,
+
+ .queue = pxa25x_ep_queue,
+ .dequeue = pxa25x_ep_dequeue,
+
+ .set_halt = pxa25x_ep_set_halt,
+ .fifo_status = pxa25x_ep_fifo_status,
+ .fifo_flush = pxa25x_ep_fifo_flush,
+};
+
+
+/* ---------------------------------------------------------------------------
+ * device-scoped parts of the api to the usb controller hardware
+ * ---------------------------------------------------------------------------
+ */
+
+static int pxa25x_udc_get_frame(struct usb_gadget *_gadget)
+{
+ return ((readl(&the_controller->regs->ufnrh) & 0x07) << 8) |
+ (readl(&the_controller->regs->ufnrl) & 0xff);
+}
+
+static int pxa25x_udc_wakeup(struct usb_gadget *_gadget)
+{
+ /* host may not have enabled remote wakeup */
+ if ((readl(&the_controller->regs->udccs[0]) & UDCCS0_DRWF) == 0)
+ return -EHOSTUNREACH;
+ udc_set_mask_UDCCR(UDCCR_RSM);
+ return 0;
+}
+
+static void stop_activity(struct pxa25x_udc *, struct usb_gadget_driver *);
+static void udc_enable(struct pxa25x_udc *);
+static void udc_disable(struct pxa25x_udc *);
+
+/*
+ * We disable the UDC -- and its 48 MHz clock -- whenever it's not
+ * in active use.
+ */
+static int pullup(struct pxa25x_udc *udc)
+{
+ if (udc->pullup)
+ pullup_on();
+ else
+ pullup_off();
+
+
+ int is_active = udc->pullup;
+ if (is_active) {
+ if (!udc->active) {
+ udc->active = 1;
+ udc_enable(udc);
+ }
+ } else {
+ if (udc->active) {
+ if (udc->gadget.speed != USB_SPEED_UNKNOWN)
+ stop_activity(udc, udc->driver);
+ udc_disable(udc);
+ udc->active = 0;
+ }
+
+ }
+ return 0;
+}
+
+/* VBUS reporting logically comes from a transceiver */
+static int pxa25x_udc_vbus_session(struct usb_gadget *_gadget, int is_active)
+{
+ struct pxa25x_udc *udc;
+
+ udc = container_of(_gadget, struct pxa25x_udc, gadget);
+ printf("vbus %s\n", is_active ? "supplied" : "inactive");
+ pullup(udc);
+ return 0;
+}
+
+/* drivers may have software control over D+ pullup */
+static int pxa25x_udc_pullup(struct usb_gadget *_gadget, int is_active)
+{
+ struct pxa25x_udc *udc;
+
+ udc = container_of(_gadget, struct pxa25x_udc, gadget);
+
+ /* not all boards support pullup control */
+ if (!udc->mach->udc_command)
+ return -EOPNOTSUPP;
+
+ udc->pullup = (is_active != 0);
+ pullup(udc);
+ return 0;
+}
+
+/*
+ * boards may consume current from VBUS, up to 100-500mA based on config.
+ * the 500uA suspend ceiling means that exclusively vbus-powered PXA designs
+ * violate USB specs.
+ */
+static int pxa25x_udc_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
+{
+ return -EOPNOTSUPP;
+}
+
+static const struct usb_gadget_ops pxa25x_udc_ops = {
+ .get_frame = pxa25x_udc_get_frame,
+ .wakeup = pxa25x_udc_wakeup,
+ .vbus_session = pxa25x_udc_vbus_session,
+ .pullup = pxa25x_udc_pullup,
+ .vbus_draw = pxa25x_udc_vbus_draw,
+};
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * udc_disable - disable USB device controller
+ */
+static void udc_disable(struct pxa25x_udc *dev)
+{
+ /* block all irqs */
+ udc_set_mask_UDCCR(UDCCR_SRM|UDCCR_REM);
+ writel(0xff, &dev->regs->uicr0);
+ writel(0xff, &dev->regs->uicr1);
+ writel(UFNRH_SIM, &dev->regs->ufnrh);
+
+ /* if hardware supports it, disconnect from usb */
+ pullup_off();
+
+ udc_clear_mask_UDCCR(UDCCR_UDE);
+
+ ep0_idle(dev);
+ dev->gadget.speed = USB_SPEED_UNKNOWN;
+}
+
+/*
+ * udc_reinit - initialize software state
+ */
+static void udc_reinit(struct pxa25x_udc *dev)
+{
+ u32 i;
+
+ /* device/ep0 records init */
+ INIT_LIST_HEAD(&dev->gadget.ep_list);
+ INIT_LIST_HEAD(&dev->gadget.ep0->ep_list);
+ dev->ep0state = EP0_IDLE;
+
+ /* basic endpoint records init */
+ for (i = 0; i < PXA_UDC_NUM_ENDPOINTS; i++) {
+ struct pxa25x_ep *ep = &dev->ep[i];
+
+ if (i != 0)
+ list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list);
+
+ ep->desc = NULL;
+ ep->stopped = 0;
+ INIT_LIST_HEAD(&ep->queue);
+ ep->pio_irqs = 0;
+ }
+
+ /* the rest was statically initialized, and is read-only */
+}
+
+/*
+ * until it's enabled, this UDC should be completely invisible
+ * to any USB host.
+ */
+static void udc_enable(struct pxa25x_udc *dev)
+{
+ debug("udc: enabling udc\n");
+
+ udc_clear_mask_UDCCR(UDCCR_UDE);
+
+ /*
+ * Try to clear these bits before we enable the udc.
+ * Do not touch reset ack bit, we would take care of it in
+ * interrupt handle routine
+ */
+ udc_ack_int_UDCCR(UDCCR_SUSIR|UDCCR_RESIR);
+
+ ep0_idle(dev);
+ dev->gadget.speed = USB_SPEED_UNKNOWN;
+ dev->stats.irqs = 0;
+
+ /*
+ * sequence taken from chapter 12.5.10, PXA250 AppProcDevManual:
+ * - enable UDC
+ * - if RESET is already in progress, ack interrupt
+ * - unmask reset interrupt
+ */
+ udc_set_mask_UDCCR(UDCCR_UDE);
+ if (!(readl(&dev->regs->udccr) & UDCCR_UDA))
+ udc_ack_int_UDCCR(UDCCR_RSTIR);
+
+ if (dev->has_cfr /* UDC_RES2 is defined */) {
+ /*
+ * pxa255 (a0+) can avoid a set_config race that could
+ * prevent gadget drivers from configuring correctly
+ */
+ writel(UDCCFR_ACM | UDCCFR_MB1, &dev->regs->udccfr);
+ }
+
+ /* enable suspend/resume and reset irqs */
+ udc_clear_mask_UDCCR(UDCCR_SRM | UDCCR_REM);
+
+ /* enable ep0 irqs */
+ clrbits_le32(&dev->regs->uicr0, UICR0_IM0);
+
+ /* if hardware supports it, pullup D+ and wait for reset */
+ pullup_on();
+}
+
+static inline void clear_ep_state(struct pxa25x_udc *dev)
+{
+ unsigned i;
+
+ /*
+ * hardware SET_{CONFIGURATION,INTERFACE} automagic resets endpoint
+ * fifos, and pending transactions mustn't be continued in any case.
+ */
+ for (i = 1; i < PXA_UDC_NUM_ENDPOINTS; i++)
+ nuke(&dev->ep[i], -ECONNABORTED);
+}
+
+static void handle_ep0(struct pxa25x_udc *dev)
+{
+ u32 udccs0 = readl(&dev->regs->udccs[0]);
+ struct pxa25x_ep *ep = &dev->ep[0];
+ struct pxa25x_request *req;
+ union {
+ struct usb_ctrlrequest r;
+ u8 raw[8];
+ u32 word[2];
+ } u;
+
+ if (list_empty(&ep->queue))
+ req = NULL;
+ else
+ req = list_entry(ep->queue.next, struct pxa25x_request, queue);
+
+ /* clear stall status */
+ if (udccs0 & UDCCS0_SST) {
+ nuke(ep, -EPIPE);
+ writel(UDCCS0_SST, &dev->regs->udccs[0]);
+ stop_watchdog(dev);
+ ep0_idle(dev);
+ }
+
+ /* previous request unfinished? non-error iff back-to-back ... */
+ if ((udccs0 & UDCCS0_SA) != 0 && dev->ep0state != EP0_IDLE) {
+ nuke(ep, 0);
+ stop_watchdog(dev);
+ ep0_idle(dev);
+ }
+
+ switch (dev->ep0state) {
+ case EP0_IDLE:
+ /* late-breaking status? */
+ udccs0 = readl(&dev->regs->udccs[0]);
+
+ /* start control request? */
+ if (likely((udccs0 & (UDCCS0_OPR|UDCCS0_SA|UDCCS0_RNE))
+ == (UDCCS0_OPR|UDCCS0_SA|UDCCS0_RNE))) {
+ int i;
+
+ nuke(ep, -EPROTO);
+
+ /* read SETUP packet */
+ for (i = 0; i < 8; i++) {
+ if (unlikely(!(readl(&dev->regs->udccs[0]) &
+ UDCCS0_RNE))) {
+bad_setup:
+ debug("SETUP %d!\n", i);
+ goto stall;
+ }
+ u.raw[i] = (u8)readb(&dev->regs->uddr0);
+ }
+ if (unlikely((readl(&dev->regs->udccs[0]) &
+ UDCCS0_RNE) != 0))
+ goto bad_setup;
+
+got_setup:
+ debug("SETUP %02x.%02x v%04x i%04x l%04x\n",
+ u.r.bRequestType, u.r.bRequest,
+ le16_to_cpu(u.r.wValue),
+ le16_to_cpu(u.r.wIndex),
+ le16_to_cpu(u.r.wLength));
+
+ /* cope with automagic for some standard requests. */
+ dev->req_std = (u.r.bRequestType & USB_TYPE_MASK)
+ == USB_TYPE_STANDARD;
+ dev->req_config = 0;
+ dev->req_pending = 1;
+ switch (u.r.bRequest) {
+ /* hardware restricts gadget drivers here! */
+ case USB_REQ_SET_CONFIGURATION:
+ debug("GOT SET_CONFIGURATION\n");
+ if (u.r.bRequestType == USB_RECIP_DEVICE) {
+ /*
+ * reflect hardware's automagic
+ * up to the gadget driver.
+ */
+config_change:
+ dev->req_config = 1;
+ clear_ep_state(dev);
+ /*
+ * if !has_cfr, there's no synch
+ * else use AREN (later) not SA|OPR
+ * USIR0_IR0 acts edge sensitive
+ */
+ }
+ break;
+ /* ... and here, even more ... */
+ case USB_REQ_SET_INTERFACE:
+ if (u.r.bRequestType == USB_RECIP_INTERFACE) {
+ /*
+ * udc hardware is broken by design:
+ * - altsetting may only be zero;
+ * - hw resets all interfaces' eps;
+ * - ep reset doesn't include halt(?).
+ */
+ printf("broken set_interface (%d/%d)\n",
+ le16_to_cpu(u.r.wIndex),
+ le16_to_cpu(u.r.wValue));
+ goto config_change;
+ }
+ break;
+ /* hardware was supposed to hide this */
+ case USB_REQ_SET_ADDRESS:
+ debug("GOT SET ADDRESS\n");
+ if (u.r.bRequestType == USB_RECIP_DEVICE) {
+ ep0start(dev, 0, "address");
+ return;
+ }
+ break;
+ }
+
+ if (u.r.bRequestType & USB_DIR_IN)
+ dev->ep0state = EP0_IN_DATA_PHASE;
+ else
+ dev->ep0state = EP0_OUT_DATA_PHASE;
+
+ i = dev->driver->setup(&dev->gadget, &u.r);
+ if (i < 0) {
+ /* hardware automagic preventing STALL... */
+ if (dev->req_config) {
+ /*
+ * hardware sometimes neglects to tell
+ * tell us about config change events,
+ * so later ones may fail...
+ */
+ printf("config change %02x fail %d?\n",
+ u.r.bRequest, i);
+ return;
+ /*
+ * TODO experiment: if has_cfr,
+ * hardware didn't ACK; maybe we
+ * could actually STALL!
+ */
+ }
+ if (0) {
+stall:
+ /* uninitialized when goto stall */
+ i = 0;
+ }
+ debug("protocol STALL, "
+ "%02x err %d\n",
+ readl(&dev->regs->udccs[0]), i);
+
+ /*
+ * the watchdog timer helps deal with cases
+ * where udc seems to clear FST wrongly, and
+ * then NAKs instead of STALLing.
+ */
+ ep0start(dev, UDCCS0_FST|UDCCS0_FTF, "stall");
+ start_watchdog(dev);
+ dev->ep0state = EP0_STALL;
+
+ /* deferred i/o == no response yet */
+ } else if (dev->req_pending) {
+ if (likely(dev->ep0state == EP0_IN_DATA_PHASE
+ || dev->req_std || u.r.wLength))
+ ep0start(dev, 0, "defer");
+ else
+ ep0start(dev, UDCCS0_IPR, "defer/IPR");
+ }
+
+ /* expect at least one data or status stage irq */
+ return;
+
+ } else if (likely((udccs0 & (UDCCS0_OPR|UDCCS0_SA))
+ == (UDCCS0_OPR|UDCCS0_SA))) {
+ unsigned i;
+
+ /*
+ * pxa210/250 erratum 131 for B0/B1 says RNE lies.
+ * still observed on a pxa255 a0.
+ */
+ debug("e131\n");
+ nuke(ep, -EPROTO);
+
+ /* read SETUP data, but don't trust it too much */
+ for (i = 0; i < 8; i++)
+ u.raw[i] = (u8)readb(&dev->regs->uddr0);
+ if ((u.r.bRequestType & USB_RECIP_MASK)
+ > USB_RECIP_OTHER)
+ goto stall;
+ if (u.word[0] == 0 && u.word[1] == 0)
+ goto stall;
+ goto got_setup;
+ } else {
+ /*
+ * some random early IRQ:
+ * - we acked FST
+ * - IPR cleared
+ * - OPR got set, without SA (likely status stage)
+ */
+ debug("random IRQ %X %X\n", udccs0,
+ readl(&dev->regs->udccs[0]));
+ writel(udccs0 & (UDCCS0_SA|UDCCS0_OPR),
+ &dev->regs->udccs[0]);
+ }
+ break;
+ case EP0_IN_DATA_PHASE: /* GET_DESCRIPTOR etc */
+ if (udccs0 & UDCCS0_OPR) {
+ debug("ep0in premature status\n");
+ if (req)
+ done(ep, req, 0);
+ ep0_idle(dev);
+ } else /* irq was IPR clearing */ {
+ if (req) {
+ debug("next ep0 in packet\n");
+ /* this IN packet might finish the request */
+ (void) write_ep0_fifo(ep, req);
+ } /* else IN token before response was written */
+ }
+ break;
+ case EP0_OUT_DATA_PHASE: /* SET_DESCRIPTOR etc */
+ if (udccs0 & UDCCS0_OPR) {
+ if (req) {
+ /* this OUT packet might finish the request */
+ if (read_ep0_fifo(ep, req))
+ done(ep, req, 0);
+ /* else more OUT packets expected */
+ } /* else OUT token before read was issued */
+ } else /* irq was IPR clearing */ {
+ debug("ep0out premature status\n");
+ if (req)
+ done(ep, req, 0);
+ ep0_idle(dev);
+ }
+ break;
+ case EP0_END_XFER:
+ if (req)
+ done(ep, req, 0);
+ /*
+ * ack control-IN status (maybe in-zlp was skipped)
+ * also appears after some config change events.
+ */
+ if (udccs0 & UDCCS0_OPR)
+ writel(UDCCS0_OPR, &dev->regs->udccs[0]);
+ ep0_idle(dev);
+ break;
+ case EP0_STALL:
+ writel(UDCCS0_FST, &dev->regs->udccs[0]);
+ break;
+ }
+
+ writel(USIR0_IR0, &dev->regs->usir0);
+}
+
+static void handle_ep(struct pxa25x_ep *ep)
+{
+ struct pxa25x_request *req;
+ int is_in = ep->bEndpointAddress & USB_DIR_IN;
+ int completed;
+ u32 udccs, tmp;
+
+ do {
+ completed = 0;
+ if (likely(!list_empty(&ep->queue)))
+ req = list_entry(ep->queue.next,
+ struct pxa25x_request, queue);
+ else
+ req = NULL;
+
+ /* TODO check FST handling */
+
+ udccs = readl(ep->reg_udccs);
+ if (unlikely(is_in)) { /* irq from TPC, SST, or (ISO) TUR */
+ tmp = UDCCS_BI_TUR;
+ if (likely(ep->bmAttributes == USB_ENDPOINT_XFER_BULK))
+ tmp |= UDCCS_BI_SST;
+ tmp &= udccs;
+ if (likely(tmp))
+ writel(tmp, ep->reg_udccs);
+ if (req && likely((udccs & UDCCS_BI_TFS) != 0))
+ completed = write_fifo(ep, req);
+
+ } else { /* irq from RPC (or for ISO, ROF) */
+ if (likely(ep->bmAttributes == USB_ENDPOINT_XFER_BULK))
+ tmp = UDCCS_BO_SST | UDCCS_BO_DME;
+ else
+ tmp = UDCCS_IO_ROF | UDCCS_IO_DME;
+ tmp &= udccs;
+ if (likely(tmp))
+ writel(tmp, ep->reg_udccs);
+
+ /* fifos can hold packets, ready for reading... */
+ if (likely(req))
+ completed = read_fifo(ep, req);
+ else
+ pio_irq_disable(ep->bEndpointAddress);
+ }
+ ep->pio_irqs++;
+ } while (completed);
+}
+
+/*
+ * pxa25x_udc_irq - interrupt handler
+ *
+ * avoid delays in ep0 processing. the control handshaking isn't always
+ * under software control (pxa250c0 and the pxa255 are better), and delays
+ * could cause usb protocol errors.
+ */
+static struct pxa25x_udc memory;
+static int
+pxa25x_udc_irq(void)
+{
+ struct pxa25x_udc *dev = &memory;
+ int handled;
+
+ test_watchdog(dev);
+
+ dev->stats.irqs++;
+ do {
+ u32 udccr = readl(&dev->regs->udccr);
+
+ handled = 0;
+
+ /* SUSpend Interrupt Request */
+ if (unlikely(udccr & UDCCR_SUSIR)) {
+ udc_ack_int_UDCCR(UDCCR_SUSIR);
+ handled = 1;
+ debug("USB suspend\n");
+
+ if (dev->gadget.speed != USB_SPEED_UNKNOWN
+ && dev->driver
+ && dev->driver->suspend)
+ dev->driver->suspend(&dev->gadget);
+ ep0_idle(dev);
+ }
+
+ /* RESume Interrupt Request */
+ if (unlikely(udccr & UDCCR_RESIR)) {
+ udc_ack_int_UDCCR(UDCCR_RESIR);
+ handled = 1;
+ debug("USB resume\n");
+
+ if (dev->gadget.speed != USB_SPEED_UNKNOWN
+ && dev->driver
+ && dev->driver->resume)
+ dev->driver->resume(&dev->gadget);
+ }
+
+ /* ReSeT Interrupt Request - USB reset */
+ if (unlikely(udccr & UDCCR_RSTIR)) {
+ udc_ack_int_UDCCR(UDCCR_RSTIR);
+ handled = 1;
+
+ if ((readl(&dev->regs->udccr) & UDCCR_UDA) == 0) {
+ debug("USB reset start\n");
+
+ /*
+ * reset driver and endpoints,
+ * in case that's not yet done
+ */
+ stop_activity(dev, dev->driver);
+
+ } else {
+ debug("USB reset end\n");
+ dev->gadget.speed = USB_SPEED_FULL;
+ memset(&dev->stats, 0, sizeof dev->stats);
+ /* driver and endpoints are still reset */
+ }
+
+ } else {
+ u32 uicr0 = readl(&dev->regs->uicr0);
+ u32 uicr1 = readl(&dev->regs->uicr1);
+ u32 usir0 = readl(&dev->regs->usir0);
+ u32 usir1 = readl(&dev->regs->usir1);
+
+ usir0 = usir0 & ~uicr0;
+ usir1 = usir1 & ~uicr1;
+ int i;
+
+ if (unlikely(!usir0 && !usir1))
+ continue;
+
+ debug_cond(NOISY, "irq %02x.%02x\n", usir1, usir0);
+
+ /* control traffic */
+ if (usir0 & USIR0_IR0) {
+ dev->ep[0].pio_irqs++;
+ handle_ep0(dev);
+ handled = 1;
+ }
+
+ /* endpoint data transfers */
+ for (i = 0; i < 8; i++) {
+ u32 tmp = 1 << i;
+
+ if (i && (usir0 & tmp)) {
+ handle_ep(&dev->ep[i]);
+ setbits_le32(&dev->regs->usir0, tmp);
+ handled = 1;
+ }
+#ifndef CONFIG_USB_PXA25X_SMALL
+ if (usir1 & tmp) {
+ handle_ep(&dev->ep[i+8]);
+ setbits_le32(&dev->regs->usir1, tmp);
+ handled = 1;
+ }
+#endif
+ }
+ }
+
+ /* we could also ask for 1 msec SOF (SIR) interrupts */
+
+ } while (handled);
+ return IRQ_HANDLED;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * this uses load-time allocation and initialization (instead of
+ * doing it at run-time) to save code, eliminate fault paths, and
+ * be more obviously correct.
+ */
+static struct pxa25x_udc memory = {
+ .regs = UDC_REGS,
+
+ .gadget = {
+ .ops = &pxa25x_udc_ops,
+ .ep0 = &memory.ep[0].ep,
+ .name = driver_name,
+ },
+
+ /* control endpoint */
+ .ep[0] = {
+ .ep = {
+ .name = ep0name,
+ .ops = &pxa25x_ep_ops,
+ .maxpacket = EP0_FIFO_SIZE,
+ },
+ .dev = &memory,
+ .reg_udccs = &UDC_REGS->udccs[0],
+ .reg_uddr = &UDC_REGS->uddr0,
+ },
+
+ /* first group of endpoints */
+ .ep[1] = {
+ .ep = {
+ .name = "ep1in-bulk",
+ .ops = &pxa25x_ep_ops,
+ .maxpacket = BULK_FIFO_SIZE,
+ },
+ .dev = &memory,
+ .fifo_size = BULK_FIFO_SIZE,
+ .bEndpointAddress = USB_DIR_IN | 1,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .reg_udccs = &UDC_REGS->udccs[1],
+ .reg_uddr = &UDC_REGS->uddr1,
+ },
+ .ep[2] = {
+ .ep = {
+ .name = "ep2out-bulk",
+ .ops = &pxa25x_ep_ops,
+ .maxpacket = BULK_FIFO_SIZE,
+ },
+ .dev = &memory,
+ .fifo_size = BULK_FIFO_SIZE,
+ .bEndpointAddress = 2,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .reg_udccs = &UDC_REGS->udccs[2],
+ .reg_ubcr = &UDC_REGS->ubcr2,
+ .reg_uddr = &UDC_REGS->uddr2,
+ },
+#ifndef CONFIG_USB_PXA25X_SMALL
+ .ep[3] = {
+ .ep = {
+ .name = "ep3in-iso",
+ .ops = &pxa25x_ep_ops,
+ .maxpacket = ISO_FIFO_SIZE,
+ },
+ .dev = &memory,
+ .fifo_size = ISO_FIFO_SIZE,
+ .bEndpointAddress = USB_DIR_IN | 3,
+ .bmAttributes = USB_ENDPOINT_XFER_ISOC,
+ .reg_udccs = &UDC_REGS->udccs[3],
+ .reg_uddr = &UDC_REGS->uddr3,
+ },
+ .ep[4] = {
+ .ep = {
+ .name = "ep4out-iso",
+ .ops = &pxa25x_ep_ops,
+ .maxpacket = ISO_FIFO_SIZE,
+ },
+ .dev = &memory,
+ .fifo_size = ISO_FIFO_SIZE,
+ .bEndpointAddress = 4,
+ .bmAttributes = USB_ENDPOINT_XFER_ISOC,
+ .reg_udccs = &UDC_REGS->udccs[4],
+ .reg_ubcr = &UDC_REGS->ubcr4,
+ .reg_uddr = &UDC_REGS->uddr4,
+ },
+ .ep[5] = {
+ .ep = {
+ .name = "ep5in-int",
+ .ops = &pxa25x_ep_ops,
+ .maxpacket = INT_FIFO_SIZE,
+ },
+ .dev = &memory,
+ .fifo_size = INT_FIFO_SIZE,
+ .bEndpointAddress = USB_DIR_IN | 5,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .reg_udccs = &UDC_REGS->udccs[5],
+ .reg_uddr = &UDC_REGS->uddr5,
+ },
+
+ /* second group of endpoints */
+ .ep[6] = {
+ .ep = {
+ .name = "ep6in-bulk",
+ .ops = &pxa25x_ep_ops,
+ .maxpacket = BULK_FIFO_SIZE,
+ },
+ .dev = &memory,
+ .fifo_size = BULK_FIFO_SIZE,
+ .bEndpointAddress = USB_DIR_IN | 6,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .reg_udccs = &UDC_REGS->udccs[6],
+ .reg_uddr = &UDC_REGS->uddr6,
+ },
+ .ep[7] = {
+ .ep = {
+ .name = "ep7out-bulk",
+ .ops = &pxa25x_ep_ops,
+ .maxpacket = BULK_FIFO_SIZE,
+ },
+ .dev = &memory,
+ .fifo_size = BULK_FIFO_SIZE,
+ .bEndpointAddress = 7,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .reg_udccs = &UDC_REGS->udccs[7],
+ .reg_ubcr = &UDC_REGS->ubcr7,
+ .reg_uddr = &UDC_REGS->uddr7,
+ },
+ .ep[8] = {
+ .ep = {
+ .name = "ep8in-iso",
+ .ops = &pxa25x_ep_ops,
+ .maxpacket = ISO_FIFO_SIZE,
+ },
+ .dev = &memory,
+ .fifo_size = ISO_FIFO_SIZE,
+ .bEndpointAddress = USB_DIR_IN | 8,
+ .bmAttributes = USB_ENDPOINT_XFER_ISOC,
+ .reg_udccs = &UDC_REGS->udccs[8],
+ .reg_uddr = &UDC_REGS->uddr8,
+ },
+ .ep[9] = {
+ .ep = {
+ .name = "ep9out-iso",
+ .ops = &pxa25x_ep_ops,
+ .maxpacket = ISO_FIFO_SIZE,
+ },
+ .dev = &memory,
+ .fifo_size = ISO_FIFO_SIZE,
+ .bEndpointAddress = 9,
+ .bmAttributes = USB_ENDPOINT_XFER_ISOC,
+ .reg_udccs = &UDC_REGS->udccs[9],
+ .reg_ubcr = &UDC_REGS->ubcr9,
+ .reg_uddr = &UDC_REGS->uddr9,
+ },
+ .ep[10] = {
+ .ep = {
+ .name = "ep10in-int",
+ .ops = &pxa25x_ep_ops,
+ .maxpacket = INT_FIFO_SIZE,
+ },
+ .dev = &memory,
+ .fifo_size = INT_FIFO_SIZE,
+ .bEndpointAddress = USB_DIR_IN | 10,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .reg_udccs = &UDC_REGS->udccs[10],
+ .reg_uddr = &UDC_REGS->uddr10,
+ },
+
+ /* third group of endpoints */
+ .ep[11] = {
+ .ep = {
+ .name = "ep11in-bulk",
+ .ops = &pxa25x_ep_ops,
+ .maxpacket = BULK_FIFO_SIZE,
+ },
+ .dev = &memory,
+ .fifo_size = BULK_FIFO_SIZE,
+ .bEndpointAddress = USB_DIR_IN | 11,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .reg_udccs = &UDC_REGS->udccs[11],
+ .reg_uddr = &UDC_REGS->uddr11,
+ },
+ .ep[12] = {
+ .ep = {
+ .name = "ep12out-bulk",
+ .ops = &pxa25x_ep_ops,
+ .maxpacket = BULK_FIFO_SIZE,
+ },
+ .dev = &memory,
+ .fifo_size = BULK_FIFO_SIZE,
+ .bEndpointAddress = 12,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .reg_udccs = &UDC_REGS->udccs[12],
+ .reg_ubcr = &UDC_REGS->ubcr12,
+ .reg_uddr = &UDC_REGS->uddr12,
+ },
+ .ep[13] = {
+ .ep = {
+ .name = "ep13in-iso",
+ .ops = &pxa25x_ep_ops,
+ .maxpacket = ISO_FIFO_SIZE,
+ },
+ .dev = &memory,
+ .fifo_size = ISO_FIFO_SIZE,
+ .bEndpointAddress = USB_DIR_IN | 13,
+ .bmAttributes = USB_ENDPOINT_XFER_ISOC,
+ .reg_udccs = &UDC_REGS->udccs[13],
+ .reg_uddr = &UDC_REGS->uddr13,
+ },
+ .ep[14] = {
+ .ep = {
+ .name = "ep14out-iso",
+ .ops = &pxa25x_ep_ops,
+ .maxpacket = ISO_FIFO_SIZE,
+ },
+ .dev = &memory,
+ .fifo_size = ISO_FIFO_SIZE,
+ .bEndpointAddress = 14,
+ .bmAttributes = USB_ENDPOINT_XFER_ISOC,
+ .reg_udccs = &UDC_REGS->udccs[14],
+ .reg_ubcr = &UDC_REGS->ubcr14,
+ .reg_uddr = &UDC_REGS->uddr14,
+ },
+ .ep[15] = {
+ .ep = {
+ .name = "ep15in-int",
+ .ops = &pxa25x_ep_ops,
+ .maxpacket = INT_FIFO_SIZE,
+ },
+ .dev = &memory,
+ .fifo_size = INT_FIFO_SIZE,
+ .bEndpointAddress = USB_DIR_IN | 15,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .reg_udccs = &UDC_REGS->udccs[15],
+ .reg_uddr = &UDC_REGS->uddr15,
+ },
+#endif /* !CONFIG_USB_PXA25X_SMALL */
+};
+
+static void udc_command(int cmd)
+{
+ switch (cmd) {
+ case PXA2XX_UDC_CMD_CONNECT:
+ setbits_le32(GPDR(CONFIG_USB_DEV_PULLUP_GPIO),
+ GPIO_bit(CONFIG_USB_DEV_PULLUP_GPIO));
+
+ /* enable pullup */
+ writel(GPIO_bit(CONFIG_USB_DEV_PULLUP_GPIO),
+ GPCR(CONFIG_USB_DEV_PULLUP_GPIO));
+
+ debug("Connected to USB\n");
+ break;
+
+ case PXA2XX_UDC_CMD_DISCONNECT:
+ /* disable pullup resistor */
+ writel(GPIO_bit(CONFIG_USB_DEV_PULLUP_GPIO),
+ GPSR(CONFIG_USB_DEV_PULLUP_GPIO));
+
+ /* setup pin as input, line will float */
+ clrbits_le32(GPDR(CONFIG_USB_DEV_PULLUP_GPIO),
+ GPIO_bit(CONFIG_USB_DEV_PULLUP_GPIO));
+
+ debug("Disconnected from USB\n");
+ break;
+ }
+}
+
+static struct pxa2xx_udc_mach_info mach_info = {
+ .udc_command = udc_command,
+};
+
+/*
+ * when a driver is successfully registered, it will receive
+ * control requests including set_configuration(), which enables
+ * non-control requests. then usb traffic follows until a
+ * disconnect is reported. then a host may connect again, or
+ * the driver might get unbound.
+ */
+int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+{
+ struct pxa25x_udc *dev = &memory;
+ int retval;
+ uint32_t chiprev;
+
+ if (!driver
+ || driver->speed < USB_SPEED_FULL
+ || !driver->disconnect
+ || !driver->setup)
+ return -EINVAL;
+ if (!dev)
+ return -ENODEV;
+ if (dev->driver)
+ return -EBUSY;
+
+ /* Enable clock for usb controller */
+ setbits_le32(CKEN, CKEN11_USB);
+
+ /* first hook up the driver ... */
+ dev->driver = driver;
+ dev->pullup = 1;
+
+ /* trigger chiprev-specific logic */
+ switch ((chiprev = pxa_get_cpu_revision())) {
+ case PXA255_A0:
+ dev->has_cfr = 1;
+ break;
+ case PXA250_A0:
+ case PXA250_A1:
+ /* A0/A1 "not released"; ep 13, 15 unusable */
+ /* fall through */
+ case PXA250_B2: case PXA210_B2:
+ case PXA250_B1: case PXA210_B1:
+ case PXA250_B0: case PXA210_B0:
+ /* OUT-DMA is broken ... */
+ /* fall through */
+ case PXA250_C0: case PXA210_C0:
+ break;
+ default:
+ printf("%s: unrecognized processor: %08x\n",
+ DRIVER_NAME, chiprev);
+ return -ENODEV;
+ }
+
+ the_controller = dev;
+
+ /* prepare watchdog timer */
+ dev->watchdog.running = 0;
+ dev->watchdog.period = 5000 * CONFIG_SYS_HZ / 1000000; /* 5 ms */
+ dev->watchdog.function = udc_watchdog;
+
+ udc_disable(dev);
+ udc_reinit(dev);
+
+ dev->mach = &mach_info;
+
+ dev->gadget.name = "pxa2xx_udc";
+ retval = driver->bind(&dev->gadget);
+ if (retval) {
+ printf("bind to driver %s --> error %d\n",
+ DRIVER_NAME, retval);
+ dev->driver = NULL;
+ return retval;
+ }
+
+ /*
+ * ... then enable host detection and ep0; and we're ready
+ * for set_configuration as well as eventual disconnect.
+ */
+ printf("registered gadget driver '%s'\n", DRIVER_NAME);
+
+ pullup(dev);
+ dump_state(dev);
+ return 0;
+}
+
+static void
+stop_activity(struct pxa25x_udc *dev, struct usb_gadget_driver *driver)
+{
+ int i;
+
+ /* don't disconnect drivers more than once */
+ if (dev->gadget.speed == USB_SPEED_UNKNOWN)
+ driver = NULL;
+ dev->gadget.speed = USB_SPEED_UNKNOWN;
+
+ /* prevent new request submissions, kill any outstanding requests */
+ for (i = 0; i < PXA_UDC_NUM_ENDPOINTS; i++) {
+ struct pxa25x_ep *ep = &dev->ep[i];
+
+ ep->stopped = 1;
+ nuke(ep, -ESHUTDOWN);
+ }
+ stop_watchdog(dev);
+
+ /* report disconnect; the driver is already quiesced */
+ if (driver)
+ driver->disconnect(&dev->gadget);
+
+ /* re-init driver-visible data structures */
+ udc_reinit(dev);
+}
+
+int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+{
+ struct pxa25x_udc *dev = the_controller;
+
+ if (!dev)
+ return -ENODEV;
+ if (!driver || driver != dev->driver || !driver->unbind)
+ return -EINVAL;
+
+ local_irq_disable();
+ dev->pullup = 0;
+ pullup(dev);
+ stop_activity(dev, driver);
+ local_irq_enable();
+
+ driver->unbind(&dev->gadget);
+ dev->driver = NULL;
+
+ printf("unregistered gadget driver '%s'\n", DRIVER_NAME);
+ dump_state(dev);
+
+ the_controller = NULL;
+
+ clrbits_le32(CKEN, CKEN11_USB);
+
+ return 0;
+}
+
+extern void udc_disconnect(void)
+{
+ setbits_le32(CKEN, CKEN11_USB);
+ udc_clear_mask_UDCCR(UDCCR_UDE);
+ udc_command(PXA2XX_UDC_CMD_DISCONNECT);
+ clrbits_le32(CKEN, CKEN11_USB);
+}
+
+/*-------------------------------------------------------------------------*/
+
+extern int
+usb_gadget_handle_interrupts(void)
+{
+ return pxa25x_udc_irq();
+}
diff --git a/drivers/usb/gadget/pxa25x_udc.h b/drivers/usb/gadget/pxa25x_udc.h
new file mode 100644
index 0000000000..de28a697f6
--- /dev/null
+++ b/drivers/usb/gadget/pxa25x_udc.h
@@ -0,0 +1,162 @@
+/*
+ * Intel PXA25x on-chip full speed USB device controller
+ *
+ * Copyright (C) 2003 Robert Schwebel <r.schwebel@pengutronix.de>, Pengutronix
+ * Copyright (C) 2003 David Brownell
+ * Copyright (C) 2012 Lukasz Dalek <luk0104@gmail.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 __LINUX_USB_GADGET_PXA25X_H
+#define __LINUX_USB_GADGET_PXA25X_H
+
+#include <linux/types.h>
+#include <asm/arch/regs-usb.h>
+
+/*
+ * Prefetching support - only ARMv5.
+ */
+
+#ifdef ARCH_HAS_PREFETCH
+static inline void prefetch(const void *ptr)
+{
+ __asm__ __volatile__(
+ "pld\t%a0"
+ :
+ : "p" (ptr)
+ : "cc");
+}
+
+#define prefetchw(ptr) prefetch(ptr)
+#endif /* ARCH_HAS_PREFETCH */
+
+/*-------------------------------------------------------------------------*/
+
+#define UDC_REGS ((struct pxa25x_udc_regs *)PXA25X_UDC_BASE)
+
+/*-------------------------------------------------------------------------*/
+
+struct pxa2xx_udc_mach_info {
+ int (*udc_is_connected)(void); /* do we see host? */
+ void (*udc_command)(int cmd);
+#define PXA2XX_UDC_CMD_CONNECT 0 /* let host see us */
+#define PXA2XX_UDC_CMD_DISCONNECT 1 /* so host won't see us */
+};
+
+struct pxa25x_udc;
+
+struct pxa25x_ep {
+ struct usb_ep ep;
+ struct pxa25x_udc *dev;
+
+ const struct usb_endpoint_descriptor *desc;
+ struct list_head queue;
+ unsigned long pio_irqs;
+
+ unsigned short fifo_size;
+ u8 bEndpointAddress;
+ u8 bmAttributes;
+
+ unsigned stopped:1;
+
+ /* UDCCS = UDC Control/Status for this EP
+ * UBCR = UDC Byte Count Remaining (contents of OUT fifo)
+ * UDDR = UDC Endpoint Data Register (the fifo)
+ * DRCM = DMA Request Channel Map
+ */
+ u32 *reg_udccs;
+ u32 *reg_ubcr;
+ u32 *reg_uddr;
+};
+
+struct pxa25x_request {
+ struct usb_request req;
+ struct list_head queue;
+};
+
+enum ep0_state {
+ EP0_IDLE,
+ EP0_IN_DATA_PHASE,
+ EP0_OUT_DATA_PHASE,
+ EP0_END_XFER,
+ EP0_STALL,
+};
+
+#define EP0_FIFO_SIZE 16U
+#define BULK_FIFO_SIZE 64U
+#define ISO_FIFO_SIZE 256U
+#define INT_FIFO_SIZE 8U
+
+struct udc_stats {
+ struct ep0stats {
+ unsigned long ops;
+ unsigned long bytes;
+ } read, write;
+ unsigned long irqs;
+};
+
+#ifdef CONFIG_USB_PXA25X_SMALL
+/* when memory's tight, SMALL config saves code+data. */
+#define PXA_UDC_NUM_ENDPOINTS 3
+#endif
+
+#ifndef PXA_UDC_NUM_ENDPOINTS
+#define PXA_UDC_NUM_ENDPOINTS 16
+#endif
+
+struct pxa25x_watchdog {
+ unsigned running:1;
+ ulong period;
+ ulong base;
+ struct pxa25x_udc *udc;
+
+ void (*function)(struct pxa25x_udc *udc);
+};
+
+struct pxa25x_udc {
+ struct usb_gadget gadget;
+ struct usb_gadget_driver *driver;
+ struct pxa25x_udc_regs *regs;
+
+ enum ep0_state ep0state;
+ struct udc_stats stats;
+ unsigned got_irq:1,
+ pullup:1,
+ has_cfr:1,
+ req_pending:1,
+ req_std:1,
+ req_config:1,
+ active:1;
+
+ struct clk *clk;
+ struct pxa2xx_udc_mach_info *mach;
+ u64 dma_mask;
+ struct pxa25x_ep ep[PXA_UDC_NUM_ENDPOINTS];
+
+ struct pxa25x_watchdog watchdog;
+};
+
+/*-------------------------------------------------------------------------*/
+
+static struct pxa25x_udc *the_controller;
+
+/*-------------------------------------------------------------------------*/
+
+#ifndef DEBUG
+# define NOISY 0
+#endif
+
+#endif /* __LINUX_USB_GADGET_PXA25X_H */
diff --git a/drivers/usb/host/ehci-armada100.c b/drivers/usb/host/ehci-armada100.c
index 7725641487..d24ed3e3f2 100644
--- a/drivers/usb/host/ehci-armada100.c
+++ b/drivers/usb/host/ehci-armada100.c
@@ -31,7 +31,6 @@
#include <asm/io.h>
#include <usb.h>
#include "ehci.h"
-#include "ehci-core.h"
#include <asm/arch/cpu.h>
#include <asm/arch/armada100.h>
#include <asm/arch/utmi-armada100.h>
@@ -39,18 +38,18 @@
/*
* EHCI host controller init
*/
-int ehci_hcd_init(void)
+int ehci_hcd_init(int index, struct ehci_hccr **hccr, struct ehci_hcor **hcor)
{
if (utmi_init() < 0)
return -1;
- hccr = (struct ehci_hccr *)(ARMD1_USB_HOST_BASE + 0x100);
- hcor = (struct ehci_hcor *)((uint32_t) hccr
- + HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
+ *hccr = (struct ehci_hccr *)(ARMD1_USB_HOST_BASE + 0x100);
+ *hcor = (struct ehci_hcor *)((uint32_t) *hccr
+ + HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
debug("armada100-ehci: init hccr %x and hcor %x hc_length %d\n",
- (uint32_t)hccr, (uint32_t)hcor,
- (uint32_t)HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
+ (uint32_t)*hccr, (uint32_t)*hcor,
+ (uint32_t)HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
return 0;
}
@@ -58,7 +57,7 @@ int ehci_hcd_init(void)
/*
* EHCI host controller stop
*/
-int ehci_hcd_stop(void)
+int ehci_hcd_stop(int index)
{
return 0;
}
diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c
index 15b9b60eb4..05058d3e33 100644
--- a/drivers/usb/host/ehci-atmel.c
+++ b/drivers/usb/host/ehci-atmel.c
@@ -31,14 +31,13 @@
#include <asm/arch/clk.h>
#include "ehci.h"
-#include "ehci-core.h"
/* Enable UTMI PLL time out 500us
* 10 times as datasheet specified
*/
#define EN_UPLL_TIMEOUT 500UL
-int ehci_hcd_init(void)
+int ehci_hcd_init(int index, struct ehci_hccr **hccr, struct ehci_hcor **hcor)
{
at91_pmc_t *pmc = (at91_pmc_t *)ATMEL_BASE_PMC;
ulong start_time, tmp_time;
@@ -58,14 +57,14 @@ int ehci_hcd_init(void)
/* Enable USB Host clock */
writel(1 << ATMEL_ID_UHPHS, &pmc->pcer);
- hccr = (struct ehci_hccr *)ATMEL_BASE_EHCI;
- hcor = (struct ehci_hcor *)((uint32_t)hccr +
- HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
+ *hccr = (struct ehci_hccr *)ATMEL_BASE_EHCI;
+ *hcor = (struct ehci_hcor *)((uint32_t)*hccr +
+ HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
return 0;
}
-int ehci_hcd_stop(void)
+int ehci_hcd_stop(int index)
{
at91_pmc_t *pmc = (at91_pmc_t *)ATMEL_BASE_PMC;
ulong start_time, tmp_time;
diff --git a/drivers/usb/host/ehci-core.h b/drivers/usb/host/ehci-core.h
deleted file mode 100644
index 39e5c5e58c..0000000000
--- a/drivers/usb/host/ehci-core.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*-
- * Copyright (c) 2007-2008, Juniper Networks, Inc.
- * Copyright (c) 2008, Excito Elektronik i Skåne AB
- * All rights reserved.
- *
- * 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 version 2 of
- * the License.
- *
- * 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 USB_EHCI_CORE_H
-#define USB_EHCI_CORE_H
-
-extern int rootdev;
-extern struct ehci_hccr *hccr;
-extern volatile struct ehci_hcor *hcor;
-
-#endif
diff --git a/drivers/usb/host/ehci-exynos.c b/drivers/usb/host/ehci-exynos.c
index a71b3977d8..9f0ed06a85 100644
--- a/drivers/usb/host/ehci-exynos.c
+++ b/drivers/usb/host/ehci-exynos.c
@@ -27,7 +27,6 @@
#include <asm/arch/system.h>
#include <asm/arch/power.h>
#include "ehci.h"
-#include "ehci-core.h"
/* Setup the EHCI host controller. */
static void setup_usb_phy(struct exynos_usb_phy *usb)
@@ -85,20 +84,20 @@ static void reset_usb_phy(struct exynos_usb_phy *usb)
* Create the appropriate control structures to manage
* a new EHCI host controller.
*/
-int ehci_hcd_init(void)
+int ehci_hcd_init(int index, struct ehci_hccr **hccr, struct ehci_hcor **hcor)
{
struct exynos_usb_phy *usb;
usb = (struct exynos_usb_phy *)samsung_get_base_usb_phy();
setup_usb_phy(usb);
- hccr = (struct ehci_hccr *)samsung_get_base_usb_ehci();
- hcor = (struct ehci_hcor *)((uint32_t) hccr
- + HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
+ *hccr = (struct ehci_hccr *)samsung_get_base_usb_ehci();
+ *hcor = (struct ehci_hcor *)((uint32_t) *hccr
+ + HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
debug("Exynos5-ehci: init hccr %x and hcor %x hc_length %d\n",
- (uint32_t)hccr, (uint32_t)hcor,
- (uint32_t)HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
+ (uint32_t)*hccr, (uint32_t)*hcor,
+ (uint32_t)HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
return 0;
}
@@ -107,7 +106,7 @@ int ehci_hcd_init(void)
* Destroy the appropriate control structures corresponding
* the EHCI host controller.
*/
-int ehci_hcd_stop()
+int ehci_hcd_stop(int index)
{
struct exynos_usb_phy *usb;
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index b2d294ee88..7b8f033b03 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -29,7 +29,6 @@
#include <hwconfig.h>
#include "ehci.h"
-#include "ehci-core.h"
/*
* Create the appropriate control structures to manage
@@ -37,7 +36,7 @@
*
* Excerpts from linux ehci fsl driver.
*/
-int ehci_hcd_init(void)
+int ehci_hcd_init(int index, struct ehci_hccr **hccr, struct ehci_hcor **hcor)
{
struct usb_ehci *ehci;
const char *phy_type = NULL;
@@ -49,9 +48,9 @@ int ehci_hcd_init(void)
#endif
ehci = (struct usb_ehci *)CONFIG_SYS_FSL_USB_ADDR;
- hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength);
- hcor = (struct ehci_hcor *)((uint32_t) hccr +
- HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
+ *hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength);
+ *hcor = (struct ehci_hcor *)((uint32_t) *hccr +
+ HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
/* Set to Host mode */
setbits_le32(&ehci->usbmode, CM_HOST);
@@ -82,14 +81,14 @@ int ehci_hcd_init(void)
setbits_be32(&ehci->control, UTMI_PHY_EN);
udelay(1000); /* delay required for PHY Clk to appear */
#endif
- out_le32(&(hcor->or_portsc[0]), PORT_PTS_UTMI);
+ out_le32(&(*hcor)->or_portsc[0], PORT_PTS_UTMI);
} else {
#if defined(CONFIG_SYS_FSL_USB_INTERNAL_UTMI_PHY)
clrbits_be32(&ehci->control, UTMI_PHY_EN);
setbits_be32(&ehci->control, PHY_CLK_SEL_ULPI);
udelay(1000); /* delay required for PHY Clk to appear */
#endif
- out_le32(&(hcor->or_portsc[0]), PORT_PTS_ULPI);
+ out_le32(&(*hcor)->or_portsc[0], PORT_PTS_ULPI);
}
/* Enable interface. */
@@ -108,7 +107,7 @@ int ehci_hcd_init(void)
* Destroy the appropriate control structures corresponding
* the the EHCI host controller.
*/
-int ehci_hcd_stop(void)
+int ehci_hcd_stop(int index)
{
return 0;
}
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 392e286224..d90e94d810 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -30,12 +30,17 @@
#include "ehci.h"
-int rootdev;
-struct ehci_hccr *hccr; /* R/O registers, not need for volatile */
-volatile struct ehci_hcor *hcor;
+#ifndef CONFIG_USB_MAX_CONTROLLER_COUNT
+#define CONFIG_USB_MAX_CONTROLLER_COUNT 1
+#endif
-static uint16_t portreset;
-DEFINE_ALIGN_BUFFER(struct QH, qh_list, 1, USB_DMA_MINALIGN);
+static struct ehci_ctrl {
+ struct ehci_hccr *hccr; /* R/O registers, not need for volatile */
+ struct ehci_hcor *hcor;
+ int rootdev;
+ uint16_t portreset;
+ struct QH qh_list __attribute__((aligned(USB_DMA_MINALIGN)));
+} ehcic[CONFIG_USB_MAX_CONTROLLER_COUNT];
#define ALIGN_END_ADDR(type, ptr, size) \
((uint32_t)(ptr) + roundup((size) * sizeof(type), USB_DMA_MINALIGN))
@@ -136,24 +141,25 @@ static int handshake(uint32_t *ptr, uint32_t mask, uint32_t done, int usec)
return -1;
}
-static int ehci_reset(void)
+static int ehci_reset(int index)
{
uint32_t cmd;
uint32_t tmp;
uint32_t *reg_ptr;
int ret = 0;
- cmd = ehci_readl(&hcor->or_usbcmd);
+ cmd = ehci_readl(&ehcic[index].hcor->or_usbcmd);
cmd = (cmd & ~CMD_RUN) | CMD_RESET;
- ehci_writel(&hcor->or_usbcmd, cmd);
- ret = handshake((uint32_t *)&hcor->or_usbcmd, CMD_RESET, 0, 250 * 1000);
+ ehci_writel(&ehcic[index].hcor->or_usbcmd, cmd);
+ ret = handshake((uint32_t *)&ehcic[index].hcor->or_usbcmd,
+ CMD_RESET, 0, 250 * 1000);
if (ret < 0) {
printf("EHCI fail to reset\n");
goto out;
}
if (ehci_is_TDI()) {
- reg_ptr = (uint32_t *)((u8 *)hcor + USBMODE);
+ reg_ptr = (uint32_t *)((u8 *)ehcic[index].hcor + USBMODE);
tmp = ehci_readl(reg_ptr);
tmp |= USBMODE_CM_HC;
#if defined(CONFIG_EHCI_MMIO_BIG_ENDIAN)
@@ -163,10 +169,10 @@ static int ehci_reset(void)
}
#ifdef CONFIG_USB_EHCI_TXFIFO_THRESH
- cmd = ehci_readl(&hcor->or_txfilltuning);
+ cmd = ehci_readl(&ehcic[index].hcor->or_txfilltuning);
cmd &= ~TXFIFO_THRESH_MASK;
cmd |= TXFIFO_THRESH(CONFIG_USB_EHCI_TXFIFO_THRESH);
- ehci_writel(&hcor->or_txfilltuning, cmd);
+ ehci_writel(&ehcic[index].hcor->or_txfilltuning, cmd);
#endif
out:
return ret;
@@ -212,7 +218,6 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
struct qTD *qtd;
int qtd_count = 0;
int qtd_counter = 0;
-
volatile struct qTD *vtd;
unsigned long ts;
uint32_t *tdp;
@@ -221,6 +226,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
uint32_t cmd;
int timeout;
int ret = 0;
+ struct ehci_ctrl *ctrl = dev->controller;
debug("dev=%p, pipe=%lx, buffer=%p, length=%d, req=%p\n", dev, pipe,
buffer, length, req);
@@ -311,7 +317,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
* qh_overlay.qt_next ...... 13-10 H
* - qh_overlay.qt_altnext
*/
- qh->qh_link = cpu_to_hc32((uint32_t)qh_list | QH_LINK_TYPE_QH);
+ qh->qh_link = cpu_to_hc32((uint32_t)&ctrl->qh_list | QH_LINK_TYPE_QH);
c = usb_pipespeed(pipe) != USB_SPEED_HIGH && !usb_pipeendpoint(pipe);
maxpacket = usb_maxpacket(dev, pipe);
endpt = QH_ENDPT1_RL(8) | QH_ENDPT1_C(c) |
@@ -445,27 +451,27 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
tdp = &qtd[qtd_counter++].qt_next;
}
- qh_list->qh_link = cpu_to_hc32((uint32_t)qh | QH_LINK_TYPE_QH);
+ ctrl->qh_list.qh_link = cpu_to_hc32((uint32_t)qh | QH_LINK_TYPE_QH);
/* Flush dcache */
- flush_dcache_range((uint32_t)qh_list,
- ALIGN_END_ADDR(struct QH, qh_list, 1));
+ flush_dcache_range((uint32_t)&ctrl->qh_list,
+ ALIGN_END_ADDR(struct QH, &ctrl->qh_list, 1));
flush_dcache_range((uint32_t)qh, ALIGN_END_ADDR(struct QH, qh, 1));
flush_dcache_range((uint32_t)qtd,
ALIGN_END_ADDR(struct qTD, qtd, qtd_count));
/* Set async. queue head pointer. */
- ehci_writel(&hcor->or_asynclistaddr, (uint32_t)qh_list);
+ ehci_writel(&ctrl->hcor->or_asynclistaddr, (uint32_t)&ctrl->qh_list);
- usbsts = ehci_readl(&hcor->or_usbsts);
- ehci_writel(&hcor->or_usbsts, (usbsts & 0x3f));
+ usbsts = ehci_readl(&ctrl->hcor->or_usbsts);
+ ehci_writel(&ctrl->hcor->or_usbsts, (usbsts & 0x3f));
/* Enable async. schedule. */
- cmd = ehci_readl(&hcor->or_usbcmd);
+ cmd = ehci_readl(&ctrl->hcor->or_usbcmd);
cmd |= CMD_ASE;
- ehci_writel(&hcor->or_usbcmd, cmd);
+ ehci_writel(&ctrl->hcor->or_usbcmd, cmd);
- ret = handshake((uint32_t *)&hcor->or_usbsts, STS_ASS, STS_ASS,
+ ret = handshake((uint32_t *)&ctrl->hcor->or_usbsts, STS_ASS, STS_ASS,
100 * 1000);
if (ret < 0) {
printf("EHCI fail timeout STS_ASS set\n");
@@ -478,8 +484,8 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
timeout = USB_TIMEOUT_MS(pipe);
do {
/* Invalidate dcache */
- invalidate_dcache_range((uint32_t)qh_list,
- ALIGN_END_ADDR(struct QH, qh_list, 1));
+ invalidate_dcache_range((uint32_t)&ctrl->qh_list,
+ ALIGN_END_ADDR(struct QH, &ctrl->qh_list, 1));
invalidate_dcache_range((uint32_t)qh,
ALIGN_END_ADDR(struct QH, qh, 1));
invalidate_dcache_range((uint32_t)qtd,
@@ -508,11 +514,11 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
printf("EHCI timed out on TD - token=%#x\n", token);
/* Disable async schedule. */
- cmd = ehci_readl(&hcor->or_usbcmd);
+ cmd = ehci_readl(&ctrl->hcor->or_usbcmd);
cmd &= ~CMD_ASE;
- ehci_writel(&hcor->or_usbcmd, cmd);
+ ehci_writel(&ctrl->hcor->or_usbcmd, cmd);
- ret = handshake((uint32_t *)&hcor->or_usbsts, STS_ASS, 0,
+ ret = handshake((uint32_t *)&ctrl->hcor->or_usbsts, STS_ASS, 0,
100 * 1000);
if (ret < 0) {
printf("EHCI fail timeout STS_ASS reset\n");
@@ -551,9 +557,9 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
} else {
dev->act_len = 0;
debug("dev=%u, usbsts=%#x, p[1]=%#x, p[2]=%#x\n",
- dev->devnum, ehci_readl(&hcor->or_usbsts),
- ehci_readl(&hcor->or_portsc[0]),
- ehci_readl(&hcor->or_portsc[1]));
+ dev->devnum, ehci_readl(&ctrl->hcor->or_usbsts),
+ ehci_readl(&ctrl->hcor->or_portsc[0]),
+ ehci_readl(&ctrl->hcor->or_portsc[1]));
}
free(qtd);
@@ -584,13 +590,14 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,
int len, srclen;
uint32_t reg;
uint32_t *status_reg;
+ struct ehci_ctrl *ctrl = dev->controller;
if (le16_to_cpu(req->index) > CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS) {
printf("The request port(%d) is not configured\n",
le16_to_cpu(req->index) - 1);
return -1;
}
- status_reg = (uint32_t *)&hcor->or_portsc[
+ status_reg = (uint32_t *)&ctrl->hcor->or_portsc[
le16_to_cpu(req->index) - 1];
srclen = 0;
@@ -658,7 +665,7 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,
break;
case USB_REQ_SET_ADDRESS | (USB_RECIP_DEVICE << 8):
debug("USB_REQ_SET_ADDRESS\n");
- rootdev = le16_to_cpu(req->value);
+ ctrl->rootdev = le16_to_cpu(req->value);
break;
case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
debug("USB_REQ_SET_CONFIGURATION\n");
@@ -708,7 +715,7 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,
tmpbuf[2] |= USB_PORT_STAT_C_ENABLE;
if (reg & EHCI_PS_OCC)
tmpbuf[2] |= USB_PORT_STAT_C_OVERCURRENT;
- if (portreset & (1 << le16_to_cpu(req->index)))
+ if (ctrl->portreset & (1 << le16_to_cpu(req->index)))
tmpbuf[2] |= USB_PORT_STAT_C_RESET;
srcptr = tmpbuf;
@@ -723,7 +730,7 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,
ehci_writel(status_reg, reg);
break;
case USB_PORT_FEAT_POWER:
- if (HCS_PPC(ehci_readl(&hccr->cr_hcsparams))) {
+ if (HCS_PPC(ehci_readl(&ctrl->hccr->cr_hcsparams))) {
reg |= EHCI_PS_PP;
ehci_writel(status_reg, reg);
}
@@ -760,7 +767,7 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,
ret = handshake(status_reg, EHCI_PS_PR, 0,
2 * 1000);
if (!ret)
- portreset |=
+ ctrl->portreset |=
1 << le16_to_cpu(req->index);
else
printf("port(%d) reset error\n",
@@ -772,7 +779,7 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,
goto unknown;
}
/* unblock posted writes */
- (void) ehci_readl(&hcor->or_usbcmd);
+ (void) ehci_readl(&ctrl->hcor->or_usbcmd);
break;
case USB_REQ_CLEAR_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8):
reg = ehci_readl(status_reg);
@@ -784,7 +791,7 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,
reg = (reg & ~EHCI_PS_CLEAR) | EHCI_PS_PE;
break;
case USB_PORT_FEAT_POWER:
- if (HCS_PPC(ehci_readl(&hccr->cr_hcsparams)))
+ if (HCS_PPC(ehci_readl(&ctrl->hccr->cr_hcsparams)))
reg = reg & ~(EHCI_PS_CLEAR | EHCI_PS_PP);
case USB_PORT_FEAT_C_CONNECTION:
reg = (reg & ~EHCI_PS_CLEAR) | EHCI_PS_CSC;
@@ -793,7 +800,7 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,
reg = (reg & ~EHCI_PS_CLEAR) | EHCI_PS_OCC;
break;
case USB_PORT_FEAT_C_RESET:
- portreset &= ~(1 << le16_to_cpu(req->index));
+ ctrl->portreset &= ~(1 << le16_to_cpu(req->index));
break;
default:
debug("unknown feature %x\n", le16_to_cpu(req->value));
@@ -801,7 +808,7 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,
}
ehci_writel(status_reg, reg);
/* unblock posted write */
- (void) ehci_readl(&hcor->or_usbcmd);
+ (void) ehci_readl(&ctrl->hcor->or_usbcmd);
break;
default:
debug("Unknown request\n");
@@ -829,28 +836,31 @@ unknown:
return -1;
}
-int usb_lowlevel_stop(void)
+int usb_lowlevel_stop(int index)
{
- return ehci_hcd_stop();
+ return ehci_hcd_stop(index);
}
-int usb_lowlevel_init(void)
+int usb_lowlevel_init(int index, void **controller)
{
uint32_t reg;
uint32_t cmd;
+ struct QH *qh_list;
- if (ehci_hcd_init())
+ if (ehci_hcd_init(index, &ehcic[index].hccr, &ehcic[index].hcor))
return -1;
/* EHCI spec section 4.1 */
- if (ehci_reset())
+ if (ehci_reset(index))
return -1;
#if defined(CONFIG_EHCI_HCD_INIT_AFTER_RESET)
- if (ehci_hcd_init())
+ if (ehci_hcd_init(index, &ehcic[index].hccr, &ehcic[index].hcor))
return -1;
#endif
+ qh_list = &ehcic[index].qh_list;
+
/* Set head of reclaim list */
memset(qh_list, 0, sizeof(*qh_list));
qh_list->qh_link = cpu_to_hc32((uint32_t)qh_list | QH_LINK_TYPE_QH);
@@ -862,9 +872,9 @@ int usb_lowlevel_init(void)
qh_list->qh_overlay.qt_token =
cpu_to_hc32(QT_TOKEN_STATUS(QT_TOKEN_STATUS_HALTED));
- reg = ehci_readl(&hccr->cr_hcsparams);
+ reg = ehci_readl(&ehcic[index].hccr->cr_hcsparams);
descriptor.hub.bNbrPorts = HCS_N_PORTS(reg);
- printf("Register %x NbrPorts %d\n", reg, descriptor.hub.bNbrPorts);
+ debug("Register %x NbrPorts %d\n", reg, descriptor.hub.bNbrPorts);
/* Port Indicators */
if (HCS_INDICATOR(reg))
put_unaligned(get_unaligned(&descriptor.hub.wHubCharacteristics)
@@ -875,27 +885,28 @@ int usb_lowlevel_init(void)
| 0x01, &descriptor.hub.wHubCharacteristics);
/* Start the host controller. */
- cmd = ehci_readl(&hcor->or_usbcmd);
+ cmd = ehci_readl(&ehcic[index].hcor->or_usbcmd);
/*
* Philips, Intel, and maybe others need CMD_RUN before the
* root hub will detect new devices (why?); NEC doesn't
*/
cmd &= ~(CMD_LRESET|CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET);
cmd |= CMD_RUN;
- ehci_writel(&hcor->or_usbcmd, cmd);
+ ehci_writel(&ehcic[index].hcor->or_usbcmd, cmd);
/* take control over the ports */
- cmd = ehci_readl(&hcor->or_configflag);
+ cmd = ehci_readl(&ehcic[index].hcor->or_configflag);
cmd |= FLAG_CF;
- ehci_writel(&hcor->or_configflag, cmd);
+ ehci_writel(&ehcic[index].hcor->or_configflag, cmd);
/* unblock posted write */
- cmd = ehci_readl(&hcor->or_usbcmd);
+ cmd = ehci_readl(&ehcic[index].hcor->or_usbcmd);
mdelay(5);
- reg = HC_VERSION(ehci_readl(&hccr->cr_capbase));
+ reg = HC_VERSION(ehci_readl(&ehcic[index].hccr->cr_capbase));
printf("USB EHCI %x.%02x\n", reg >> 8, reg & 0xff);
- rootdev = 0;
+ ehcic[index].rootdev = 0;
+ *controller = &ehcic[index];
return 0;
}
@@ -915,14 +926,15 @@ int
submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
int length, struct devrequest *setup)
{
+ struct ehci_ctrl *ctrl = dev->controller;
if (usb_pipetype(pipe) != PIPE_CONTROL) {
debug("non-control pipe (type=%lu)", usb_pipetype(pipe));
return -1;
}
- if (usb_pipedevice(pipe) == rootdev) {
- if (!rootdev)
+ if (usb_pipedevice(pipe) == ctrl->rootdev) {
+ if (!ctrl->rootdev)
dev->speed = USB_SPEED_HIGH;
return ehci_submit_root(dev, pipe, buffer, length, setup);
}
diff --git a/drivers/usb/host/ehci-ixp4xx.c b/drivers/usb/host/ehci-ixp4xx.c
index b8f15ae52a..cf3d5f5fd7 100644
--- a/drivers/usb/host/ehci-ixp4xx.c
+++ b/drivers/usb/host/ehci-ixp4xx.c
@@ -23,20 +23,19 @@
#include <usb.h>
#include "ehci.h"
-#include "ehci-core.h"
/*
* Create the appropriate control structures to manage
* a new EHCI host controller.
*/
-int ehci_hcd_init(void)
+int ehci_hcd_init(int index, struct ehci_hccr **hccr, struct ehci_hcor **hcor)
{
- hccr = (struct ehci_hccr *)(0xcd000100);
- hcor = (struct ehci_hcor *)((uint32_t) hccr
- + HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
+ *hccr = (struct ehci_hccr *)(0xcd000100);
+ *hcor = (struct ehci_hcor *)((uint32_t) *hccr
+ + HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
printf("IXP4XX init hccr %x and hcor %x hc_length %d\n",
- (uint32_t)hccr, (uint32_t)hcor,
- (uint32_t)HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
+ (uint32_t)*hccr, (uint32_t)*hcor,
+ (uint32_t)HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
return 0;
}
@@ -44,7 +43,7 @@ int ehci_hcd_init(void)
* Destroy the appropriate control structures corresponding
* the the EHCI host controller.
*/
-int ehci_hcd_stop(void)
+int ehci_hcd_stop(int index)
{
return 0;
}
diff --git a/drivers/usb/host/ehci-marvell.c b/drivers/usb/host/ehci-marvell.c
index 89c8af7287..2b73e4ad6a 100644
--- a/drivers/usb/host/ehci-marvell.c
+++ b/drivers/usb/host/ehci-marvell.c
@@ -26,7 +26,6 @@
#include <asm/io.h>
#include <usb.h>
#include "ehci.h"
-#include "ehci-core.h"
#include <asm/arch/cpu.h>
#if defined(CONFIG_KIRKWOOD)
@@ -91,17 +90,17 @@ static void usb_brg_adrdec_setup(void)
* Create the appropriate control structures to manage
* a new EHCI host controller.
*/
-int ehci_hcd_init(void)
+int ehci_hcd_init(int index, struct ehci_hccr **hccr, struct ehci_hcor **hcor)
{
usb_brg_adrdec_setup();
- hccr = (struct ehci_hccr *)(MVUSB0_BASE + 0x100);
- hcor = (struct ehci_hcor *)((uint32_t) hccr
- + HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
+ *hccr = (struct ehci_hccr *)(MVUSB0_BASE + 0x100);
+ *hcor = (struct ehci_hcor *)((uint32_t) *hccr
+ + HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
debug("ehci-marvell: init hccr %x and hcor %x hc_length %d\n",
- (uint32_t)hccr, (uint32_t)hcor,
- (uint32_t)HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
+ (uint32_t)*hccr, (uint32_t)*hcor,
+ (uint32_t)HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
return 0;
}
@@ -110,7 +109,7 @@ int ehci_hcd_init(void)
* Destroy the appropriate control structures corresponding
* the the EHCI host controller.
*/
-int ehci_hcd_stop(void)
+int ehci_hcd_stop(int index)
{
return 0;
}
diff --git a/drivers/usb/host/ehci-mpc512x.c b/drivers/usb/host/ehci-mpc512x.c
index d36010826b..e98f79f9cc 100644
--- a/drivers/usb/host/ehci-mpc512x.c
+++ b/drivers/usb/host/ehci-mpc512x.c
@@ -33,7 +33,6 @@
#include <usb/ehci-fsl.h>
#include "ehci.h"
-#include "ehci-core.h"
static void fsl_setup_phy(volatile struct ehci_hcor *);
static void fsl_platform_set_host_mode(volatile struct usb_ehci *ehci);
@@ -46,21 +45,21 @@ static void usb_platform_dr_init(volatile struct usb_ehci *ehci);
* This code is derived from EHCI FSL USB Linux driver for MPC5121
*
*/
-int ehci_hcd_init(void)
+int ehci_hcd_init(int index, struct ehci_hccr **hccr, struct ehci_hcor **hcor)
{
volatile struct usb_ehci *ehci;
/* Hook the memory mapped registers for EHCI-Controller */
ehci = (struct usb_ehci *)CONFIG_SYS_FSL_USB_ADDR;
- hccr = (struct ehci_hccr *)((uint32_t)&(ehci->caplength));
- hcor = (struct ehci_hcor *)((uint32_t) hccr +
- HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
+ *hccr = (struct ehci_hccr *)((uint32_t)&(ehci->caplength));
+ *hcor = (struct ehci_hcor *)((uint32_t) *hccr +
+ HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
/* configure interface for UTMI_WIDE */
usb_platform_dr_init(ehci);
/* Init Phy USB0 to UTMI+ */
- fsl_setup_phy(hcor);
+ fsl_setup_phy(*hcor);
/* Set to host mode */
fsl_platform_set_host_mode(ehci);
@@ -89,20 +88,14 @@ int ehci_hcd_init(void)
* Destroy the appropriate control structures corresponding
* the the EHCI host controller.
*/
-int ehci_hcd_stop(void)
+int ehci_hcd_stop(int index)
{
volatile struct usb_ehci *ehci;
int exit_status = 0;
- if (hcor) {
- /* Unhook struct */
- hccr = NULL;
- hcor = NULL;
-
- /* Reset the USB controller */
- ehci = (struct usb_ehci *)CONFIG_SYS_FSL_USB_ADDR;
- exit_status = reset_usb_controller(ehci);
- }
+ /* Reset the USB controller */
+ ehci = (struct usb_ehci *)CONFIG_SYS_FSL_USB_ADDR;
+ exit_status = reset_usb_controller(ehci);
return exit_status;
}
diff --git a/drivers/usb/host/ehci-mx5.c b/drivers/usb/host/ehci-mx5.c
index 58cdcbedf2..9a2c295ec5 100644
--- a/drivers/usb/host/ehci-mx5.c
+++ b/drivers/usb/host/ehci-mx5.c
@@ -25,7 +25,6 @@
#include <asm/arch/iomux.h>
#include "ehci.h"
-#include "ehci-core.h"
#define MX5_USBOTHER_REGS_OFFSET 0x800
@@ -206,7 +205,7 @@ void __board_ehci_hcd_postinit(struct usb_ehci *ehci, int port)
void board_ehci_hcd_postinit(struct usb_ehci *ehci, int port)
__attribute((weak, alias("__board_ehci_hcd_postinit")));
-int ehci_hcd_init(void)
+int ehci_hcd_init(int index, struct ehci_hccr **hccr, struct ehci_hcor **hcor)
{
struct usb_ehci *ehci;
#ifdef CONFIG_MX53
@@ -221,7 +220,8 @@ int ehci_hcd_init(void)
set_usboh3_clk();
enable_usboh3_clk(1);
- set_usb_phy2_clk();
+ set_usb_phy_clk();
+ enable_usb_phy1_clk(1);
enable_usb_phy2_clk(1);
mdelay(1);
@@ -230,9 +230,9 @@ int ehci_hcd_init(void)
ehci = (struct usb_ehci *)(OTG_BASE_ADDR +
(0x200 * CONFIG_MXC_USB_PORT));
- hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength);
- hcor = (struct ehci_hcor *)((uint32_t)hccr +
- HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
+ *hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength);
+ *hcor = (struct ehci_hcor *)((uint32_t)*hccr +
+ HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
setbits_le32(&ehci->usbmode, CM_HOST);
__raw_writel(CONFIG_MXC_USB_PORTSC, &ehci->portsc);
@@ -247,7 +247,7 @@ int ehci_hcd_init(void)
return 0;
}
-int ehci_hcd_stop(void)
+int ehci_hcd_stop(int index)
{
return 0;
}
diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c
index 028024298d..9ce25da598 100644
--- a/drivers/usb/host/ehci-mx6.c
+++ b/drivers/usb/host/ehci-mx6.c
@@ -25,7 +25,6 @@
#include <asm/imx-common/iomux-v3.h>
#include "ehci.h"
-#include "ehci-core.h"
#define USB_OTGREGS_OFFSET 0x000
#define USB_H1REGS_OFFSET 0x200
@@ -160,7 +159,7 @@ static void usbh1_oc_config(void)
__raw_writel(val, usbother_base + USB_H1_CTRL_OFFSET);
}
-int ehci_hcd_init(void)
+int ehci_hcd_init(int index, struct ehci_hccr **hccr, struct ehci_hcor **hcor)
{
struct usb_ehci *ehci;
@@ -182,9 +181,9 @@ int ehci_hcd_init(void)
ehci = (struct usb_ehci *)(USBOH3_USB_BASE_ADDR +
(0x200 * CONFIG_MXC_USB_PORT));
- hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength);
- hcor = (struct ehci_hcor *)((uint32_t)hccr +
- HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
+ *hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength);
+ *hcor = (struct ehci_hcor *)((uint32_t)*hccr +
+ HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
setbits_le32(&ehci->usbmode, CM_HOST);
__raw_writel(CONFIG_MXC_USB_PORTSC, &ehci->portsc);
@@ -195,7 +194,7 @@ int ehci_hcd_init(void)
return 0;
}
-int ehci_hcd_stop(void)
+int ehci_hcd_stop(int index)
{
return 0;
}
diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c
index 45cbd18a00..a38bc9c1bb 100644
--- a/drivers/usb/host/ehci-mxc.c
+++ b/drivers/usb/host/ehci-mxc.c
@@ -25,7 +25,6 @@
#include <errno.h>
#include "ehci.h"
-#include "ehci-core.h"
#define USBCTRL_OTGBASE_OFFSET 0x600
@@ -106,7 +105,7 @@ static int mxc_set_usbcontrol(int port, unsigned int flags)
return 0;
}
-int ehci_hcd_init(void)
+int ehci_hcd_init(int index, struct ehci_hccr **hccr, struct ehci_hcor **hcor)
{
struct usb_ehci *ehci;
#ifdef CONFIG_MX31
@@ -121,9 +120,9 @@ int ehci_hcd_init(void)
ehci = (struct usb_ehci *)(IMX_USB_BASE +
(0x200 * CONFIG_MXC_USB_PORT));
- hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength);
- hcor = (struct ehci_hcor *)((uint32_t) hccr +
- HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
+ *hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength);
+ *hcor = (struct ehci_hcor *)((uint32_t) *hccr +
+ HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
setbits_le32(&ehci->usbmode, CM_HOST);
__raw_writel(CONFIG_MXC_USB_PORTSC, &ehci->portsc);
mxc_set_usbcontrol(CONFIG_MXC_USB_PORT, CONFIG_MXC_USB_FLAGS);
@@ -137,7 +136,7 @@ int ehci_hcd_init(void)
* Destroy the appropriate control structures corresponding
* the the EHCI host controller.
*/
-int ehci_hcd_stop(void)
+int ehci_hcd_stop(int index)
{
return 0;
}
diff --git a/drivers/usb/host/ehci-mxs.c b/drivers/usb/host/ehci-mxs.c
index 6e21669d5a..5062af5559 100644
--- a/drivers/usb/host/ehci-mxs.c
+++ b/drivers/usb/host/ehci-mxs.c
@@ -27,7 +27,6 @@
#include <asm/arch/regs-usb.h>
#include <asm/arch/regs-usbphy.h>
-#include "ehci-core.h"
#include "ehci.h"
#if (CONFIG_EHCI_MXS_PORT != 0) && (CONFIG_EHCI_MXS_PORT != 1)
@@ -70,7 +69,7 @@ int mxs_ehci_get_port(struct ehci_mxs *mxs_usb, int port)
#define HW_DIGCTL_CTRL_USB0_CLKGATE (1 << 2)
#define HW_DIGCTL_CTRL_USB1_CLKGATE (1 << 16)
-int ehci_hcd_init(void)
+int ehci_hcd_init(int index, struct ehci_hccr **hccr, struct ehci_hcor **hcor)
{
int ret;
@@ -107,28 +106,35 @@ int ehci_hcd_init(void)
&ehci_mxs.phy_regs->hw_usbphy_ctrl_set);
usb_base = ((uint32_t)ehci_mxs.usb_regs) + 0x100;
- hccr = (struct ehci_hccr *)usb_base;
+ *hccr = (struct ehci_hccr *)usb_base;
- cap_base = ehci_readl(&hccr->cr_capbase);
- hcor = (struct ehci_hcor *)(usb_base + HC_LENGTH(cap_base));
+ cap_base = ehci_readl(&(*hccr)->cr_capbase);
+ *hcor = (struct ehci_hcor *)(usb_base + HC_LENGTH(cap_base));
return 0;
}
-int ehci_hcd_stop(void)
+int ehci_hcd_stop(int index)
{
int ret;
- uint32_t tmp;
+ uint32_t usb_base, cap_base, tmp;
struct mxs_register_32 *digctl_ctrl =
(struct mxs_register_32 *)HW_DIGCTL_CTRL;
struct mxs_clkctrl_regs *clkctrl_regs =
(struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
+ struct ehci_hccr *hccr;
+ struct ehci_hcor *hcor;
ret = mxs_ehci_get_port(&ehci_mxs, CONFIG_EHCI_MXS_PORT);
if (ret)
return ret;
/* Stop the USB port */
+ usb_base = ((uint32_t)ehci_mxs.usb_regs) + 0x100;
+ hccr = (struct ehci_hccr *)usb_base;
+ cap_base = ehci_readl(&hccr->cr_capbase);
+ hcor = (struct ehci_hcor *)(usb_base + HC_LENGTH(cap_base));
+
tmp = ehci_readl(&hcor->or_usbcmd);
tmp &= ~CMD_RUN;
ehci_writel(tmp, &hcor->or_usbcmd);
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index 292673bf00..086c6978e1 100644
--- a/drivers/usb/host/ehci-omap.c
+++ b/drivers/usb/host/ehci-omap.c
@@ -33,7 +33,8 @@
#include <asm/gpio.h>
#include <asm/arch/ehci.h>
#include <asm/ehci-omap.h>
-#include "ehci-core.h"
+
+#include "ehci.h"
static struct omap_uhh *const uhh = (struct omap_uhh *)OMAP_UHH_BASE;
static struct omap_usbtll *const usbtll = (struct omap_usbtll *)OMAP_USBTLL_BASE;
@@ -155,7 +156,8 @@ int omap_ehci_hcd_stop(void)
* Based on "drivers/usb/host/ehci-omap.c" from Linux 3.1
* See there for additional Copyrights.
*/
-int omap_ehci_hcd_init(struct omap_usbhs_board_data *usbhs_pdata)
+int omap_ehci_hcd_init(struct omap_usbhs_board_data *usbhs_pdata,
+ struct ehci_hccr **hccr, struct ehci_hcor **hcor)
{
int ret;
unsigned int i, reg = 0, rev = 0;
@@ -246,8 +248,8 @@ int omap_ehci_hcd_init(struct omap_usbhs_board_data *usbhs_pdata)
if (is_ehci_phy_mode(usbhs_pdata->port_mode[i]))
omap_ehci_soft_phy_reset(i);
- hccr = (struct ehci_hccr *)(OMAP_EHCI_BASE);
- hcor = (struct ehci_hcor *)(OMAP_EHCI_BASE + 0x10);
+ *hccr = (struct ehci_hccr *)(OMAP_EHCI_BASE);
+ *hcor = (struct ehci_hcor *)(OMAP_EHCI_BASE + 0x10);
debug("OMAP EHCI init done\n");
return 0;
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 020ab11355..29af02dc5b 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -23,7 +23,6 @@
#include <usb.h>
#include "ehci.h"
-#include "ehci-core.h"
#ifdef CONFIG_PCI_EHCI_DEVICE
static struct pci_device_id ehci_pci_ids[] = {
@@ -39,7 +38,7 @@ static struct pci_device_id ehci_pci_ids[] = {
* Create the appropriate control structures to manage
* a new EHCI host controller.
*/
-int ehci_hcd_init(void)
+int ehci_hcd_init(int index, struct ehci_hccr **hccr, struct ehci_hcor **hcor)
{
pci_dev_t pdev;
@@ -49,14 +48,14 @@ int ehci_hcd_init(void)
return -1;
}
- hccr = (struct ehci_hccr *)pci_map_bar(pdev,
+ *hccr = (struct ehci_hccr *)pci_map_bar(pdev,
PCI_BASE_ADDRESS_0, PCI_REGION_MEM);
- hcor = (struct ehci_hcor *)((uint32_t) hccr +
- HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
+ *hcor = (struct ehci_hcor *)((uint32_t) *hccr +
+ HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
debug("EHCI-PCI init hccr 0x%x and hcor 0x%x hc_length %d\n",
- (uint32_t)hccr, (uint32_t)hcor,
- (uint32_t)HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
+ (uint32_t)*hccr, (uint32_t)*hcor,
+ (uint32_t)HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
return 0;
}
@@ -65,7 +64,7 @@ int ehci_hcd_init(void)
* Destroy the appropriate control structures corresponding
* the the EHCI host controller.
*/
-int ehci_hcd_stop(void)
+int ehci_hcd_stop(int index)
{
return 0;
}
diff --git a/drivers/usb/host/ehci-ppc4xx.c b/drivers/usb/host/ehci-ppc4xx.c
index 1179919987..e389c755e1 100644
--- a/drivers/usb/host/ehci-ppc4xx.c
+++ b/drivers/usb/host/ehci-ppc4xx.c
@@ -23,17 +23,16 @@
#include <usb.h>
#include "ehci.h"
-#include "ehci-core.h"
/*
* Create the appropriate control structures to manage
* a new EHCI host controller.
*/
-int ehci_hcd_init(void)
+int ehci_hcd_init(int index, struct ehci_hccr **hccr, struct ehci_hcor **hcor)
{
- hccr = (struct ehci_hccr *)(CONFIG_SYS_PPC4XX_USB_ADDR);
- hcor = (struct ehci_hcor *)((uint32_t) hccr +
- HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
+ *hccr = (struct ehci_hccr *)(CONFIG_SYS_PPC4XX_USB_ADDR);
+ *hcor = (struct ehci_hcor *)((uint32_t) *hccr +
+ HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
return 0;
}
@@ -41,7 +40,7 @@ int ehci_hcd_init(void)
* Destroy the appropriate control structures corresponding
* the the EHCI host controller.
*/
-int ehci_hcd_stop(void)
+int ehci_hcd_stop(int index)
{
return 0;
}
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index 4646b29508..a1c43f8331 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -24,7 +24,6 @@
#include <usb.h>
#include "ehci.h"
-#include "ehci-core.h"
#include <asm/errno.h>
#include <asm/arch/usb.h>
@@ -50,7 +49,7 @@ void ehci_powerup_fixup(uint32_t *status_reg, uint32_t *reg)
* Create the appropriate control structures to manage
* a new EHCI host controller.
*/
-int ehci_hcd_init(void)
+int ehci_hcd_init(int index, struct ehci_hccr **hccr, struct ehci_hcor **hcor)
{
u32 our_hccr, our_hcor;
@@ -58,11 +57,11 @@ int ehci_hcd_init(void)
* Select the first port, as we don't have a way of selecting others
* yet
*/
- if (tegrausb_start_port(0, &our_hccr, &our_hcor))
+ if (tegrausb_start_port(index, &our_hccr, &our_hcor))
return -1;
- hccr = (struct ehci_hccr *)our_hccr;
- hcor = (struct ehci_hcor *)our_hcor;
+ *hccr = (struct ehci_hccr *)our_hccr;
+ *hcor = (struct ehci_hcor *)our_hcor;
return 0;
}
@@ -71,8 +70,7 @@ int ehci_hcd_init(void)
* Destroy the appropriate control structures corresponding
* the the EHCI host controller.
*/
-int ehci_hcd_stop(void)
+int ehci_hcd_stop(int index)
{
- tegrausb_stop_port();
- return 0;
+ return tegrausb_stop_port(index);
}
diff --git a/drivers/usb/host/ehci-vct.c b/drivers/usb/host/ehci-vct.c
index 3063dd172f..5f8a159e72 100644
--- a/drivers/usb/host/ehci-vct.c
+++ b/drivers/usb/host/ehci-vct.c
@@ -21,7 +21,6 @@
#include <usb.h>
#include "ehci.h"
-#include "ehci-core.h"
int vct_ehci_hcd_init(u32 *hccr, u32 *hcor);
@@ -29,7 +28,7 @@ int vct_ehci_hcd_init(u32 *hccr, u32 *hcor);
* Create the appropriate control structures to manage
* a new EHCI host controller.
*/
-int ehci_hcd_init(void)
+int ehci_hcd_init(int index, struct ehci_hccr **hccr, struct ehci_hcor **hcor)
{
int ret;
u32 vct_hccr;
@@ -42,8 +41,8 @@ int ehci_hcd_init(void)
if (ret)
return ret;
- hccr = (struct ehci_hccr *)vct_hccr;
- hcor = (struct ehci_hcor *)vct_hcor;
+ *hccr = (struct ehci_hccr *)vct_hccr;
+ *hcor = (struct ehci_hcor *)vct_hcor;
return 0;
}
@@ -52,7 +51,7 @@ int ehci_hcd_init(void)
* Destroy the appropriate control structures corresponding
* the the EHCI host controller.
*/
-int ehci_hcd_stop(void)
+int ehci_hcd_stop(int index)
{
return 0;
}
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 39acdf9656..1e3cd793b6 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -249,7 +249,7 @@ struct QH {
};
/* Low level init functions */
-int ehci_hcd_init(void);
-int ehci_hcd_stop(void);
+int ehci_hcd_init(int index, struct ehci_hccr **hccr, struct ehci_hcor **hcor);
+int ehci_hcd_stop(int index);
#endif /* USB_EHCI_H */
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
index 5ef34c30fd..19e16a4a80 100644
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/drivers/usb/host/isp116x-hcd.c
@@ -1391,7 +1391,7 @@ int isp116x_check_id(struct isp116x *isp116x)
return 0;
}
-int usb_lowlevel_init(void)
+int usb_lowlevel_init(int index, void **controller))
{
struct isp116x *isp116x = &isp116x_dev;
@@ -1428,7 +1428,7 @@ int usb_lowlevel_init(void)
return 0;
}
-int usb_lowlevel_stop(void)
+int usb_lowlevel_stop(int index)
{
struct isp116x *isp116x = &isp116x_dev;
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 9f4735167a..c2106adbd3 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -1865,7 +1865,7 @@ static void hc_release_ohci(ohci_t *ohci)
*/
static char ohci_inited = 0;
-int usb_lowlevel_init(void)
+int usb_lowlevel_init(int index, void **controller)
{
#ifdef CONFIG_PCI_OHCI
pci_dev_t pdev;
@@ -1971,7 +1971,7 @@ int usb_lowlevel_init(void)
return 0;
}
-int usb_lowlevel_stop(void)
+int usb_lowlevel_stop(int index)
{
/* this gets called really early - before the controller has */
/* even been initialized! */
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
index ab1b8d0d8b..2a4e7ff4b3 100644
--- a/drivers/usb/host/r8a66597-hcd.c
+++ b/drivers/usb/host/r8a66597-hcd.c
@@ -908,7 +908,7 @@ int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
return 0;
}
-int usb_lowlevel_init(void)
+int usb_lowlevel_init(int index, void **controller))
{
struct r8a66597 *r8a66597 = &gr8a66597;
@@ -931,7 +931,7 @@ int usb_lowlevel_init(void)
return 0;
}
-int usb_lowlevel_stop(void)
+int usb_lowlevel_stop(int index)
{
disable_controller(&gr8a66597);
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
index bb27dd514a..2830616046 100644
--- a/drivers/usb/host/sl811-hcd.c
+++ b/drivers/usb/host/sl811-hcd.c
@@ -210,14 +210,14 @@ static int sl811_hc_reset(void)
return 1;
}
-int usb_lowlevel_init(void)
+int usb_lowlevel_init(int index, void **controller)
{
root_hub_devnum = 0;
sl811_hc_reset();
return 0;
}
-int usb_lowlevel_stop(void)
+int usb_lowlevel_stop(int index)
{
sl811_hc_reset();
return 0;
diff --git a/drivers/usb/musb/musb_hcd.c b/drivers/usb/musb/musb_hcd.c
index 8d44c4657f..06be38d1cf 100644
--- a/drivers/usb/musb/musb_hcd.c
+++ b/drivers/usb/musb/musb_hcd.c
@@ -1092,7 +1092,7 @@ int submit_bulk_msg(struct usb_device *dev, unsigned long pipe,
/*
* This function initializes the usb controller module.
*/
-int usb_lowlevel_init(void)
+int usb_lowlevel_init(int index, void **controller)
{
u8 power;
u32 timeout;
@@ -1144,7 +1144,7 @@ int usb_lowlevel_init(void)
/*
* This function stops the operation of the davinci usb module.
*/
-int usb_lowlevel_stop(void)
+int usb_lowlevel_stop(int index)
{
/* Reset the USB module */
musb_platform_deinit();
diff --git a/drivers/usb/ulpi/ulpi.c b/drivers/usb/ulpi/ulpi.c
index dde2585c58..23b59e740f 100644
--- a/drivers/usb/ulpi/ulpi.c
+++ b/drivers/usb/ulpi/ulpi.c
@@ -106,20 +106,44 @@ int ulpi_select_transceiver(struct ulpi_viewport *ulpi_vp, unsigned speed)
return ulpi_write(ulpi_vp, &ulpi->function_ctrl, val);
}
-int ulpi_set_vbus(struct ulpi_viewport *ulpi_vp, int on, int ext_power,
- int ext_ind)
+int ulpi_set_vbus(struct ulpi_viewport *ulpi_vp, int on, int ext_power)
{
u32 flags = ULPI_OTG_DRVVBUS;
u8 *reg = on ? &ulpi->otg_ctrl_set : &ulpi->otg_ctrl_clear;
if (ext_power)
flags |= ULPI_OTG_DRVVBUS_EXT;
- if (ext_ind)
- flags |= ULPI_OTG_EXTVBUSIND;
return ulpi_write(ulpi_vp, reg, flags);
}
+int ulpi_set_vbus_indicator(struct ulpi_viewport *ulpi_vp, int external,
+ int passthu, int complement)
+{
+ u32 flags, val;
+ u8 *reg;
+
+ reg = external ? &ulpi->otg_ctrl_set : &ulpi->otg_ctrl_clear;
+ val = ulpi_write(ulpi_vp, reg, ULPI_OTG_EXTVBUSIND);
+ if (val)
+ return val;
+
+ flags = passthu ? ULPI_IFACE_PASSTHRU : 0;
+ flags |= complement ? ULPI_IFACE_EXTVBUS_COMPLEMENT : 0;
+
+ val = ulpi_read(ulpi_vp, &ulpi->iface_ctrl);
+ if (val == ULPI_ERROR)
+ return val;
+
+ val = val & ~(ULPI_IFACE_PASSTHRU & ULPI_IFACE_EXTVBUS_COMPLEMENT);
+ val |= flags;
+ val = ulpi_write(ulpi_vp, &ulpi->iface_ctrl, val);
+ if (val)
+ return val;
+
+ return 0;
+}
+
int ulpi_set_pd(struct ulpi_viewport *ulpi_vp, int enable)
{
u32 val = ULPI_OTG_DP_PULLDOWN | ULPI_OTG_DM_PULLDOWN;
diff --git a/drivers/video/cfb_console.c b/drivers/video/cfb_console.c
index 19d061f6cb..9f7794fe53 100644
--- a/drivers/video/cfb_console.c
+++ b/drivers/video/cfb_console.c
@@ -66,7 +66,11 @@
* CONFIG_CONSOLE_TIME - display time/date in upper right
* corner, needs CONFIG_CMD_DATE and
* CONFIG_CONSOLE_CURSOR
- * CONFIG_VIDEO_LOGO - display Linux Logo in upper left corner
+ * CONFIG_VIDEO_LOGO - display Linux Logo in upper left corner.
+ * Use CONFIG_SPLASH_SCREEN_ALIGN with
+ * environment variable "splashpos" to place
+ * the logo on other position. In this case
+ * no CONSOLE_EXTRA_INFO is possible.
* CONFIG_VIDEO_BMP_LOGO - use bmp_logo instead of linux_logo
* CONFIG_CONSOLE_EXTRA_INFO - display additional board information
* strings that normaly goes to serial
@@ -1480,7 +1484,42 @@ int video_display_bitmap(ulong bmp_image, int x, int y)
#ifdef CONFIG_VIDEO_LOGO
-void logo_plot(void *screen, int width, int x, int y)
+static int video_logo_xpos;
+static int video_logo_ypos;
+
+static void plot_logo_or_black(void *screen, int width, int x, int y, \
+ int black);
+
+static void logo_plot(void *screen, int width, int x, int y)
+{
+ plot_logo_or_black(screen, width, x, y, 0);
+}
+
+static void logo_black(void)
+{
+ plot_logo_or_black(video_fb_address, \
+ VIDEO_COLS, \
+ video_logo_xpos, \
+ video_logo_ypos, \
+ 1);
+}
+
+static int do_clrlogo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ if (argc != 1)
+ return cmd_usage(cmdtp);
+
+ logo_black();
+ return 0;
+}
+
+U_BOOT_CMD(
+ clrlogo, 1, 0, do_clrlogo,
+ "fill the boot logo area with black",
+ " "
+ );
+
+static void plot_logo_or_black(void *screen, int width, int x, int y, int black)
{
int xcount, i;
@@ -1488,8 +1527,21 @@ void logo_plot(void *screen, int width, int x, int y)
int ycount = video_logo_height;
unsigned char r, g, b, *logo_red, *logo_blue, *logo_green;
unsigned char *source;
- unsigned char *dest = (unsigned char *) screen +
- ((y * width * VIDEO_PIXEL_SIZE) + x * VIDEO_PIXEL_SIZE);
+ unsigned char *dest;
+
+#ifdef CONFIG_SPLASH_SCREEN_ALIGN
+ if (x == BMP_ALIGN_CENTER)
+ x = max(0, (VIDEO_VISIBLE_COLS - VIDEO_LOGO_WIDTH) / 2);
+ else if (x < 0)
+ x = max(0, VIDEO_VISIBLE_COLS - VIDEO_LOGO_WIDTH + x + 1);
+
+ if (y == BMP_ALIGN_CENTER)
+ y = max(0, (VIDEO_VISIBLE_ROWS - VIDEO_LOGO_HEIGHT) / 2);
+ else if (y < 0)
+ y = max(0, VIDEO_VISIBLE_ROWS - VIDEO_LOGO_HEIGHT + y + 1);
+#endif /* CONFIG_SPLASH_SCREEN_ALIGN */
+
+ dest = (unsigned char *)screen + (y * width + x) * VIDEO_PIXEL_SIZE;
#ifdef CONFIG_VIDEO_BMP_LOGO
source = bmp_logo_bitmap;
@@ -1525,9 +1577,15 @@ void logo_plot(void *screen, int width, int x, int y)
#endif
xcount = VIDEO_LOGO_WIDTH;
while (xcount--) {
- r = logo_red[*source - VIDEO_LOGO_LUT_OFFSET];
- g = logo_green[*source - VIDEO_LOGO_LUT_OFFSET];
- b = logo_blue[*source - VIDEO_LOGO_LUT_OFFSET];
+ if (black) {
+ r = 0x00;
+ g = 0x00;
+ b = 0x00;
+ } else {
+ r = logo_red[*source - VIDEO_LOGO_LUT_OFFSET];
+ g = logo_green[*source - VIDEO_LOGO_LUT_OFFSET];
+ b = logo_blue[*source - VIDEO_LOGO_LUT_OFFSET];
+ }
switch (VIDEO_DATA_FORMAT) {
case GDF__8BIT_INDEX:
@@ -1592,42 +1650,66 @@ static void *video_logo(void)
char info[128];
int space, len;
__maybe_unused int y_off = 0;
+ __maybe_unused ulong addr;
+ __maybe_unused char *s;
-#ifdef CONFIG_SPLASH_SCREEN
- char *s;
- ulong addr;
-
- s = getenv("splashimage");
+#ifdef CONFIG_SPLASH_SCREEN_ALIGN
+ s = getenv("splashpos");
if (s != NULL) {
- int x = 0, y = 0;
+ if (s[0] == 'm')
+ video_logo_xpos = BMP_ALIGN_CENTER;
+ else
+ video_logo_xpos = simple_strtol(s, NULL, 0);
- addr = simple_strtoul(s, NULL, 16);
-#ifdef CONFIG_SPLASH_SCREEN_ALIGN
- s = getenv("splashpos");
+ s = strchr(s + 1, ',');
if (s != NULL) {
- if (s[0] == 'm')
- x = BMP_ALIGN_CENTER;
+ if (s[1] == 'm')
+ video_logo_ypos = BMP_ALIGN_CENTER;
else
- x = simple_strtol(s, NULL, 0);
-
- s = strchr(s + 1, ',');
- if (s != NULL) {
- if (s[1] == 'm')
- y = BMP_ALIGN_CENTER;
- else
- y = simple_strtol(s + 1, NULL, 0);
- }
+ video_logo_ypos = simple_strtol(s + 1, NULL, 0);
}
+ }
#endif /* CONFIG_SPLASH_SCREEN_ALIGN */
- if (video_display_bitmap(addr, x, y) == 0) {
+#ifdef CONFIG_SPLASH_SCREEN
+ s = getenv("splashimage");
+ if (s != NULL) {
+
+ addr = simple_strtoul(s, NULL, 16);
+
+
+ if (video_display_bitmap(addr,
+ video_logo_xpos,
+ video_logo_ypos) == 0) {
video_logo_height = 0;
return ((void *) (video_fb_address));
}
}
#endif /* CONFIG_SPLASH_SCREEN */
- logo_plot(video_fb_address, VIDEO_COLS, 0, 0);
+ logo_plot(video_fb_address, VIDEO_COLS,
+ video_logo_xpos, video_logo_ypos);
+
+#ifdef CONFIG_SPLASH_SCREEN_ALIGN
+ /*
+ * when using splashpos for video_logo, skip any info
+ * output on video console if the logo is not at 0,0
+ */
+ if (video_logo_xpos || video_logo_ypos) {
+ /*
+ * video_logo_height is used in text and cursor offset
+ * calculations. Since the console is below the logo,
+ * we need to adjust the logo height
+ */
+ if (video_logo_ypos == BMP_ALIGN_CENTER)
+ video_logo_height += max(0, (VIDEO_VISIBLE_ROWS - \
+ VIDEO_LOGO_HEIGHT) / 2);
+ else if (video_logo_ypos > 0)
+ video_logo_height += video_logo_ypos;
+
+ return video_fb_address + video_logo_height * VIDEO_LINE_LEN;
+ }
+#endif
sprintf(info, " %s", version_string);
diff --git a/drivers/video/ipu_common.c b/drivers/video/ipu_common.c
index 2020da98d2..0f2d113a6f 100644
--- a/drivers/video/ipu_common.c
+++ b/drivers/video/ipu_common.c
@@ -163,13 +163,13 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
static int clk_ipu_enable(struct clk *clk)
{
-#if defined(CONFIG_MX51) || defined(CONFIG_MX53)
u32 reg;
reg = __raw_readl(clk->enable_reg);
reg |= MXC_CCM_CCGR_CG_MASK << clk->enable_shift;
__raw_writel(reg, clk->enable_reg);
+#if defined(CONFIG_MX51) || defined(CONFIG_MX53)
/* Handshake with IPU when certain clock rates are changed. */
reg = __raw_readl(&mxc_ccm->ccdr);
reg &= ~MXC_CCM_CCDR_IPU_HS_MASK;
@@ -185,13 +185,13 @@ static int clk_ipu_enable(struct clk *clk)
static void clk_ipu_disable(struct clk *clk)
{
-#if defined(CONFIG_MX51) || defined(CONFIG_MX53)
u32 reg;
reg = __raw_readl(clk->enable_reg);
reg &= ~(MXC_CCM_CCGR_CG_MASK << clk->enable_shift);
__raw_writel(reg, clk->enable_reg);
+#if defined(CONFIG_MX51) || defined(CONFIG_MX53)
/*
* No handshake with IPU whe dividers are changed
* as its not enabled.
@@ -211,9 +211,15 @@ static void clk_ipu_disable(struct clk *clk)
static struct clk ipu_clk = {
.name = "ipu_clk",
.rate = CONFIG_IPUV3_CLK,
+#if defined(CONFIG_MX51) || defined(CONFIG_MX53)
.enable_reg = (u32 *)(CCM_BASE_ADDR +
offsetof(struct mxc_ccm_reg, CCGR5)),
- .enable_shift = MXC_CCM_CCGR5_CG5_OFFSET,
+ .enable_shift = MXC_CCM_CCGR5_IPU_OFFSET,
+#else
+ .enable_reg = (u32 *)(CCM_BASE_ADDR +
+ offsetof(struct mxc_ccm_reg, CCGR3)),
+ .enable_shift = MXC_CCM_CCGR3_IPU1_IPU_DI0_OFFSET,
+#endif
.enable = clk_ipu_enable,
.disable = clk_ipu_disable,
.usecount = 0,
diff --git a/drivers/video/mxc_ipuv3_fb.c b/drivers/video/mxc_ipuv3_fb.c
index c38e22de1f..47b336e7aa 100644
--- a/drivers/video/mxc_ipuv3_fb.c
+++ b/drivers/video/mxc_ipuv3_fb.c
@@ -38,6 +38,7 @@
#include "videomodes.h"
#include "ipu.h"
#include "mxcfb.h"
+#include "ipu_regs.h"
static int mxcfb_map_video_memory(struct fb_info *fbi);
static int mxcfb_unmap_video_memory(struct fb_info *fbi);
@@ -576,6 +577,25 @@ err0:
return ret;
}
+void ipuv3_fb_shutdown(void)
+{
+ int i;
+ struct ipu_stat *stat = (struct ipu_stat *)IPU_STAT;
+
+ for (i = 0; i < ARRAY_SIZE(mxcfb_info); i++) {
+ struct fb_info *fbi = mxcfb_info[i];
+ if (fbi) {
+ struct mxcfb_info *mxc_fbi = fbi->par;
+ ipu_disable_channel(mxc_fbi->ipu_ch);
+ ipu_uninit_channel(mxc_fbi->ipu_ch);
+ }
+ }
+ for (i = 0; i < ARRAY_SIZE(stat->int_stat); i++) {
+ __raw_writel(__raw_readl(&stat->int_stat[i]),
+ &stat->int_stat[i]);
+ }
+}
+
void *video_hw_init(void)
{
int ret;