Merge branch 'master' of http://git.denx.de/u-boot-sunxi
authorTom Rini <trini@konsulko.com>
Fri, 11 Sep 2015 17:05:05 +0000 (13:05 -0400)
committerTom Rini <trini@konsulko.com>
Fri, 11 Sep 2015 17:05:05 +0000 (13:05 -0400)
52 files changed:
arch/sandbox/dts/test.dts
arch/x86/cpu/coreboot/coreboot.c
arch/x86/cpu/quark/Makefile
arch/x86/cpu/quark/msg_port.c
arch/x86/cpu/quark/pci.c [deleted file]
arch/x86/cpu/quark/quark.c
arch/x86/dts/chromebox_panther.dts
arch/x86/dts/galileo.dts
arch/x86/include/asm/arch-quark/quark.h
board/intel/bayleybay/bayleybay.c
board/intel/crownbay/crownbay.c
board/intel/galileo/galileo.c
board/siemens/corvus/board.c
board/siemens/smartweb/smartweb.c
board/siemens/taurus/taurus.c
configs/bayleybay_defconfig
configs/coreboot-x86_defconfig
configs/crownbay_defconfig
configs/galileo_defconfig
doc/README.x86
drivers/net/Kconfig
drivers/net/designware.c
drivers/net/pch_gbe.c
drivers/net/pch_gbe.h
drivers/pci/pci-uclass.c
drivers/usb/gadget/Makefile
drivers/usb/gadget/at91_udc.c [new file with mode: 0644]
drivers/usb/gadget/at91_udc.h [new file with mode: 0644]
include/configs/at91-sama5_common.h
include/configs/at91sam9260ek.h
include/configs/at91sam9261ek.h
include/configs/at91sam9263ek.h
include/configs/at91sam9m10g45ek.h
include/configs/at91sam9n12ek.h
include/configs/at91sam9rlek.h
include/configs/at91sam9x5ek.h
include/configs/chromebox_panther.h
include/configs/corvus.h
include/configs/crownbay.h
include/configs/galileo.h
include/configs/meesc.h
include/configs/sandbox.h
include/configs/smartweb.h
include/configs/taurus.h
include/linux/usb/at91_udc.h [new file with mode: 0644]
include/netdev.h
net/eth.c
net/tftp.c
test/dm/eth.c
tools/buildman/builder.py
tools/ifdtool.c
tools/patman/gitutil.py

index c948df8c864bc3fae1fa6b30fd5f9658fb2064bf..f5217fb87778614f783483ef7b0ee774b64ca2c3 100644 (file)
@@ -9,6 +9,7 @@
        aliases {
                console = &uart0;
                eth0 = "/eth@10002000";
+               eth3 = &eth_3;
                eth5 = &eth_5;
                i2c0 = "/i2c@0";
                pci0 = &pci;
                fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x11>;
        };
 
+       eth_3: sbe5 {
+               compatible = "sandbox,eth";
+               reg = <0x10005000 0x1000>;
+               fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x33>;
+       };
+
        eth@10004000 {
                compatible = "sandbox,eth";
                reg = <0x10004000 0x1000>;
index 0e9f15fef68a7eec36421645e2af511280cd05fb..845f86a1766c15afd9da5c0630978dcd3930b40d 100644 (file)
@@ -8,7 +8,6 @@
 
 #include <common.h>
 #include <fdtdec.h>
-#include <netdev.h>
 #include <asm/io.h>
 #include <asm/msr.h>
 #include <asm/mtrr.h>
@@ -48,11 +47,6 @@ int last_stage_init(void)
        return 0;
 }
 
-int board_eth_init(bd_t *bis)
-{
-       return pci_eth_init(bis);
-}
-
 void board_final_cleanup(void)
 {
        /*
index e87b4248e69b56fb8e97323f6ebe5c4b104b6631..8f1d018fb60841d700939a42d5f46298be443fa9 100644 (file)
@@ -6,4 +6,3 @@
 
 obj-y += car.o dram.o msg_port.o quark.o
 obj-y += mrc.o mrc_util.o hte.o smc.o
-obj-$(CONFIG_PCI) += pci.o
index 31713e321f2cf6c02e8b80f2458c38491d642fed..cf828f21c0104f9acf8fbb6cdbe3c11c54c23bde 100644 (file)
@@ -5,34 +5,34 @@
  */
 
 #include <common.h>
-#include <pci.h>
 #include <asm/arch/device.h>
 #include <asm/arch/msg_port.h>
+#include <asm/arch/quark.h>
 
 void msg_port_setup(int op, int port, int reg)
 {
-       pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_REG,
-                              (((op) << 24) | ((port) << 16) |
-                              (((reg) << 8) & 0xff00) | MSG_BYTE_ENABLE));
+       qrk_pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_REG,
+                                  (((op) << 24) | ((port) << 16) |
+                                  (((reg) << 8) & 0xff00) | MSG_BYTE_ENABLE));
 }
 
 u32 msg_port_read(u8 port, u32 reg)
 {
        u32 value;
 
-       pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG,
-                              reg & 0xffffff00);
+       qrk_pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG,
+                                  reg & 0xffffff00);
        msg_port_setup(MSG_OP_READ, port, reg);
-       pci_read_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, &value);
+       qrk_pci_read_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, &value);
 
        return value;
 }
 
 void msg_port_write(u8 port, u32 reg, u32 value)
 {
-       pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, value);
-       pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG,
-                              reg & 0xffffff00);
+       qrk_pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, value);
+       qrk_pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG,
+                                  reg & 0xffffff00);
        msg_port_setup(MSG_OP_WRITE, port, reg);
 }
 
@@ -40,19 +40,19 @@ u32 msg_port_alt_read(u8 port, u32 reg)
 {
        u32 value;
 
-       pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG,
-                              reg & 0xffffff00);
+       qrk_pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG,
+                                  reg & 0xffffff00);
        msg_port_setup(MSG_OP_ALT_READ, port, reg);
-       pci_read_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, &value);
+       qrk_pci_read_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, &value);
 
        return value;
 }
 
 void msg_port_alt_write(u8 port, u32 reg, u32 value)
 {
-       pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, value);
-       pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG,
-                              reg & 0xffffff00);
+       qrk_pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, value);
+       qrk_pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG,
+                                  reg & 0xffffff00);
        msg_port_setup(MSG_OP_ALT_WRITE, port, reg);
 }
 
@@ -60,18 +60,18 @@ u32 msg_port_io_read(u8 port, u32 reg)
 {
        u32 value;
 
-       pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG,
-                              reg & 0xffffff00);
+       qrk_pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG,
+                                  reg & 0xffffff00);
        msg_port_setup(MSG_OP_IO_READ, port, reg);
-       pci_read_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, &value);
+       qrk_pci_read_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, &value);
 
        return value;
 }
 
 void msg_port_io_write(u8 port, u32 reg, u32 value)
 {
-       pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, value);
-       pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG,
-                              reg & 0xffffff00);
+       qrk_pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, value);
+       qrk_pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG,
+                                  reg & 0xffffff00);
        msg_port_setup(MSG_OP_IO_WRITE, port, reg);
 }
diff --git a/arch/x86/cpu/quark/pci.c b/arch/x86/cpu/quark/pci.c
deleted file mode 100644 (file)
index 354e15a..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
- *
- * SPDX-License-Identifier:    GPL-2.0+
- */
-
-#include <common.h>
-#include <pci.h>
-#include <asm/pci.h>
-#include <asm/arch/device.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-void board_pci_setup_hose(struct pci_controller *hose)
-{
-       hose->first_busno = 0;
-       hose->last_busno = 0;
-
-       /* PCI memory space */
-       pci_set_region(hose->regions + 0,
-                      CONFIG_PCI_MEM_BUS,
-                      CONFIG_PCI_MEM_PHYS,
-                      CONFIG_PCI_MEM_SIZE,
-                      PCI_REGION_MEM);
-
-       /* PCI IO space */
-       pci_set_region(hose->regions + 1,
-                      CONFIG_PCI_IO_BUS,
-                      CONFIG_PCI_IO_PHYS,
-                      CONFIG_PCI_IO_SIZE,
-                      PCI_REGION_IO);
-
-       pci_set_region(hose->regions + 2,
-                      CONFIG_PCI_PREF_BUS,
-                      CONFIG_PCI_PREF_PHYS,
-                      CONFIG_PCI_PREF_SIZE,
-                      PCI_REGION_PREFETCH);
-
-       pci_set_region(hose->regions + 3,
-                      0,
-                      0,
-                      gd->ram_size,
-                      PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
-
-       hose->region_count = 4;
-}
-
-int board_pci_post_scan(struct pci_controller *hose)
-{
-       return 0;
-}
-
-int pci_skip_dev(struct pci_controller *hose, pci_dev_t dev)
-{
-       /*
-        * TODO:
-        *
-        * For some unknown reason, the PCI enumeration process hangs
-        * when it scans to the PCIe root port 0 (D23:F0) & 1 (D23:F1).
-        *
-        * For now we just skip these two devices, and this needs to
-        * be revisited later.
-        */
-       if (dev == QUARK_HOST_BRIDGE ||
-           dev == QUARK_PCIE0 || dev == QUARK_PCIE1) {
-               return 1;
-       }
-
-       return 0;
-}
index 12ac3761d2565ec5e4ffb3435ec56d81ecb14410..637c370e818acfd68a571c126273d2dbc16b4e78 100644 (file)
@@ -31,32 +31,32 @@ static void unprotect_spi_flash(void)
 {
        u32 bc;
 
-       bc = x86_pci_read_config32(QUARK_LEGACY_BRIDGE, 0xd8);
+       qrk_pci_read_config_dword(QUARK_LEGACY_BRIDGE, 0xd8, &bc);
        bc |= 0x1;      /* unprotect the flash */
-       x86_pci_write_config32(QUARK_LEGACY_BRIDGE, 0xd8, bc);
+       qrk_pci_write_config_dword(QUARK_LEGACY_BRIDGE, 0xd8, bc);
 }
 
 static void quark_setup_bars(void)
 {
        /* GPIO - D31:F0:R44h */
-       pci_write_config_dword(QUARK_LEGACY_BRIDGE, LB_GBA,
-                              CONFIG_GPIO_BASE | IO_BAR_EN);
+       qrk_pci_write_config_dword(QUARK_LEGACY_BRIDGE, LB_GBA,
+                                  CONFIG_GPIO_BASE | IO_BAR_EN);
 
        /* ACPI PM1 Block - D31:F0:R48h */
-       pci_write_config_dword(QUARK_LEGACY_BRIDGE, LB_PM1BLK,
-                              CONFIG_ACPI_PM1_BASE | IO_BAR_EN);
+       qrk_pci_write_config_dword(QUARK_LEGACY_BRIDGE, LB_PM1BLK,
+                                  CONFIG_ACPI_PM1_BASE | IO_BAR_EN);
 
        /* GPE0 - D31:F0:R4Ch */
-       pci_write_config_dword(QUARK_LEGACY_BRIDGE, LB_GPE0BLK,
-                              CONFIG_ACPI_GPE0_BASE | IO_BAR_EN);
+       qrk_pci_write_config_dword(QUARK_LEGACY_BRIDGE, LB_GPE0BLK,
+                                  CONFIG_ACPI_GPE0_BASE | IO_BAR_EN);
 
        /* WDT - D31:F0:R84h */
-       pci_write_config_dword(QUARK_LEGACY_BRIDGE, LB_WDTBA,
-                              CONFIG_WDT_BASE | IO_BAR_EN);
+       qrk_pci_write_config_dword(QUARK_LEGACY_BRIDGE, LB_WDTBA,
+                                  CONFIG_WDT_BASE | IO_BAR_EN);
 
        /* RCBA - D31:F0:RF0h */
-       pci_write_config_dword(QUARK_LEGACY_BRIDGE, LB_RCBA,
-                              CONFIG_RCBA_BASE | MEM_BAR_EN);
+       qrk_pci_write_config_dword(QUARK_LEGACY_BRIDGE, LB_RCBA,
+                                  CONFIG_RCBA_BASE | MEM_BAR_EN);
 
        /* ACPI P Block - Msg Port 04:R70h */
        msg_port_write(MSG_PORT_RMU, PBLK_BA,
@@ -73,6 +73,96 @@ static void quark_setup_bars(void)
                       CONFIG_PCIE_ECAM_BASE | MEM_BAR_EN);
 }
 
+static void quark_pcie_early_init(void)
+{
+       u32 pcie_cfg;
+
+       /*
+        * Step1: Assert PCIe signal PERST#
+        *
+        * The CPU interface to the PERST# signal is platform dependent.
+        * Call the board-specific codes to perform this task.
+        */
+       board_assert_perst();
+
+       /* Step2: PHY common lane reset */
+       pcie_cfg = msg_port_alt_read(MSG_PORT_SOC_UNIT, PCIE_CFG);
+       pcie_cfg |= PCIE_PHY_LANE_RST;
+       msg_port_alt_write(MSG_PORT_SOC_UNIT, PCIE_CFG, pcie_cfg);
+       /* wait 1 ms for PHY common lane reset */
+       mdelay(1);
+
+       /* Step3: PHY sideband interface reset and controller main reset */
+       pcie_cfg = msg_port_alt_read(MSG_PORT_SOC_UNIT, PCIE_CFG);
+       pcie_cfg |= (PCIE_PHY_SB_RST | PCIE_CTLR_MAIN_RST);
+       msg_port_alt_write(MSG_PORT_SOC_UNIT, PCIE_CFG, pcie_cfg);
+       /* wait 80ms for PLL to lock */
+       mdelay(80);
+
+       /* Step4: Controller sideband interface reset */
+       pcie_cfg = msg_port_alt_read(MSG_PORT_SOC_UNIT, PCIE_CFG);
+       pcie_cfg |= PCIE_CTLR_SB_RST;
+       msg_port_alt_write(MSG_PORT_SOC_UNIT, PCIE_CFG, pcie_cfg);
+       /* wait 20ms for controller sideband interface reset */
+       mdelay(20);
+
+       /* Step5: De-assert PERST# */
+       board_deassert_perst();
+
+       /* Step6: Controller primary interface reset */
+       pcie_cfg = msg_port_alt_read(MSG_PORT_SOC_UNIT, PCIE_CFG);
+       pcie_cfg |= PCIE_CTLR_PRI_RST;
+       msg_port_alt_write(MSG_PORT_SOC_UNIT, PCIE_CFG, pcie_cfg);
+
+       /* Mixer Load Lane 0 */
+       pcie_cfg = msg_port_io_read(MSG_PORT_PCIE_AFE, PCIE_RXPICTRL0_L0);
+       pcie_cfg &= ~((1 << 6) | (1 << 7));
+       msg_port_io_write(MSG_PORT_PCIE_AFE, PCIE_RXPICTRL0_L0, pcie_cfg);
+
+       /* Mixer Load Lane 1 */
+       pcie_cfg = msg_port_io_read(MSG_PORT_PCIE_AFE, PCIE_RXPICTRL0_L1);
+       pcie_cfg &= ~((1 << 6) | (1 << 7));
+       msg_port_io_write(MSG_PORT_PCIE_AFE, PCIE_RXPICTRL0_L1, pcie_cfg);
+}
+
+static void quark_usb_early_init(void)
+{
+       u32 usb;
+
+       /* The sequence below comes from Quark firmware writer guide */
+
+       usb = msg_port_alt_read(MSG_PORT_USB_AFE, USB2_GLOBAL_PORT);
+       usb &= ~(1 << 1);
+       usb |= ((1 << 6) | (1 << 7));
+       msg_port_alt_write(MSG_PORT_USB_AFE, USB2_GLOBAL_PORT, usb);
+
+       usb = msg_port_alt_read(MSG_PORT_USB_AFE, USB2_COMPBG);
+       usb &= ~((1 << 8) | (1 << 9));
+       usb |= ((1 << 7) | (1 << 10));
+       msg_port_alt_write(MSG_PORT_USB_AFE, USB2_COMPBG, usb);
+
+       usb = msg_port_alt_read(MSG_PORT_USB_AFE, USB2_PLL2);
+       usb |= (1 << 29);
+       msg_port_alt_write(MSG_PORT_USB_AFE, USB2_PLL2, usb);
+
+       usb = msg_port_alt_read(MSG_PORT_USB_AFE, USB2_PLL1);
+       usb |= (1 << 1);
+       msg_port_alt_write(MSG_PORT_USB_AFE, USB2_PLL1, usb);
+
+       usb = msg_port_alt_read(MSG_PORT_USB_AFE, USB2_PLL1);
+       usb &= ~((1 << 3) | (1 << 4) | (1 << 5));
+       usb |= (1 << 6);
+       msg_port_alt_write(MSG_PORT_USB_AFE, USB2_PLL1, usb);
+
+       usb = msg_port_alt_read(MSG_PORT_USB_AFE, USB2_PLL2);
+       usb &= ~(1 << 29);
+       msg_port_alt_write(MSG_PORT_USB_AFE, USB2_PLL2, usb);
+
+       usb = msg_port_alt_read(MSG_PORT_USB_AFE, USB2_PLL2);
+       usb |= (1 << 24);
+       msg_port_alt_write(MSG_PORT_USB_AFE, USB2_PLL2, usb);
+}
+
 static void quark_enable_legacy_seg(void)
 {
        u32 hmisc2;
@@ -84,7 +174,6 @@ static void quark_enable_legacy_seg(void)
 
 int arch_cpu_init(void)
 {
-       struct pci_controller *hose;
        int ret;
 
        post_code(POST_CPU_INIT);
@@ -96,16 +185,26 @@ int arch_cpu_init(void)
        if (ret)
                return ret;
 
-       ret = pci_early_init_hose(&hose);
-       if (ret)
-               return ret;
-
        /*
         * Quark SoC has some non-standard BARs (excluding PCI standard BARs)
         * which need be initialized with suggested values
         */
        quark_setup_bars();
 
+       /*
+        * Initialize PCIe controller
+        *
+        * Quark SoC holds the PCIe controller in reset following a power on.
+        * U-Boot needs to release the PCIe controller from reset. The PCIe
+        * controller (D23:F0/F1) will not be visible in PCI configuration
+        * space and any access to its PCI configuration registers will cause
+        * system hang while it is held in reset.
+        */
+       quark_pcie_early_init();
+
+       /* Initialize USB2 PHY */
+       quark_usb_early_init();
+
        /* Turn on legacy segments (A/B/E/F) decode to system RAM */
        quark_enable_legacy_seg();
 
@@ -137,10 +236,10 @@ int cpu_eth_init(bd_t *bis)
        u32 base;
        int ret0, ret1;
 
-       pci_read_config_dword(QUARK_EMAC0, PCI_BASE_ADDRESS_0, &base);
+       qrk_pci_read_config_dword(QUARK_EMAC0, PCI_BASE_ADDRESS_0, &base);
        ret0 = designware_initialize(base, PHY_INTERFACE_MODE_RMII);
 
-       pci_read_config_dword(QUARK_EMAC1, PCI_BASE_ADDRESS_0, &base);
+       qrk_pci_read_config_dword(QUARK_EMAC1, PCI_BASE_ADDRESS_0, &base);
        ret1 = designware_initialize(base, PHY_INTERFACE_MODE_RMII);
 
        if (ret0 < 0 && ret1 < 0)
@@ -154,7 +253,7 @@ void cpu_irq_init(void)
        struct quark_rcba *rcba;
        u32 base;
 
-       base = x86_pci_read_config32(QUARK_LEGACY_BRIDGE, LB_RCBA);
+       qrk_pci_read_config_dword(QUARK_LEGACY_BRIDGE, LB_RCBA, &base);
        base &= ~MEM_BAR_EN;
        rcba = (struct quark_rcba *)base;
 
index 36feb96a94d09ee2fcabe315be1f59ca3feba95b..c60ab710d2fdef390c049a406131ab17e49d7054 100644 (file)
                stdout-path = "/serial";
        };
 
+       pci {
+               compatible = "pci-x86";
+               #address-cells = <3>;
+               #size-cells = <2>;
+               u-boot,dm-pre-reloc;
+               ranges = <0x02000000 0x0 0xe0000000 0xe0000000 0 0x10000000
+                       0x42000000 0x0 0xd0000000 0xd0000000 0 0x10000000
+                       0x01000000 0x0 0x1000 0x1000 0 0xf000>;
+       };
+
        spi {
                #address-cells = <1>;
                #size-cells = <0>;
index d77ff8ad5558c30e06de3fb69866ee68859567b0..f119bf7f42c9e7d1f156dbb2f4e1790c195b1319 100644 (file)
        pci {
                #address-cells = <3>;
                #size-cells = <2>;
-               compatible = "intel,pci";
-               device_type = "pci";
+               compatible = "pci-x86";
+               u-boot,dm-pre-reloc;
+               ranges = <0x02000000 0x0 0x90000000 0x90000000 0 0x20000000
+                         0x42000000 0x0 0xb0000000 0xb0000000 0 0x20000000
+                         0x01000000 0x0 0x2000 0x2000 0 0xe000>;
 
                pciuart0: uart@14,5 {
                        compatible = "pci8086,0936.00",
@@ -63,6 +66,7 @@
                                        "pciclass,070002",
                                        "pciclass,0700",
                                        "x86-uart";
+                       u-boot,dm-pre-reloc;
                        reg = <0x0000a500 0x0 0x0 0x0 0x0
                               0x0200a510 0x0 0x0 0x0 0x0>;
                        reg-shift = <2>;
index c9979280b625a9ebe3ff5c7236a332dc352c0b10..5d81976998d36a0013ecbc4f7fec86bd0e71e55f 100644 (file)
@@ -12,6 +12,8 @@
 #define MSG_PORT_HOST_BRIDGE   0x03
 #define MSG_PORT_RMU           0x04
 #define MSG_PORT_MEM_MGR       0x05
+#define MSG_PORT_USB_AFE       0x14
+#define MSG_PORT_PCIE_AFE      0x16
 #define MSG_PORT_SOC_UNIT      0x31
 
 /* Port 0x00: Memory Arbiter Message Port Registers */
 #define ESRAM_BLK_CTRL         0x82
 #define ESRAM_BLOCK_MODE       0x10000000
 
+/* Port 0x14: USB2 AFE Unit Port Registers */
+
+#define USB2_GLOBAL_PORT       0x4001
+#define USB2_PLL1              0x7f02
+#define USB2_PLL2              0x7f03
+#define USB2_COMPBG            0x7f04
+
+/* Port 0x16: PCIe AFE Unit Port Registers */
+
+#define PCIE_RXPICTRL0_L0      0x2080
+#define PCIE_RXPICTRL0_L1      0x2180
+
+/* Port 0x31: SoC Unit Port Registers */
+
+/* PCIe Controller Config */
+#define PCIE_CFG               0x36
+#define PCIE_CTLR_PRI_RST      0x00010000
+#define PCIE_PHY_SB_RST                0x00020000
+#define PCIE_CTLR_SB_RST       0x00040000
+#define PCIE_PHY_LANE_RST      0x00090000
+#define PCIE_CTLR_MAIN_RST     0x00100000
+
 /* DRAM */
 #define DRAM_BASE              0x00000000
 #define DRAM_MAX_SIZE          0x80000000
@@ -89,6 +113,67 @@ struct quark_rcba {
        u16     d20d21_ir;
 };
 
+#include <asm/io.h>
+#include <asm/pci.h>
+
+/**
+ * qrk_pci_read_config_dword() - Read a configuration value
+ *
+ * @dev:       PCI device address: bus, device and function
+ * @offset:    Dword offset within the device's configuration space
+ * @valuep:    Place to put the returned value
+ *
+ * Note: This routine is inlined to provide better performance on Quark
+ */
+static inline void qrk_pci_read_config_dword(pci_dev_t dev, int offset,
+                                            u32 *valuep)
+{
+       outl(dev | offset | PCI_CFG_EN, PCI_REG_ADDR);
+       *valuep = inl(PCI_REG_DATA);
+}
+
+/**
+ * qrk_pci_write_config_dword() - Write a PCI configuration value
+ *
+ * @dev:       PCI device address: bus, device and function
+ * @offset:    Dword offset within the device's configuration space
+ * @value:     Value to write
+ *
+ * Note: This routine is inlined to provide better performance on Quark
+ */
+static inline void qrk_pci_write_config_dword(pci_dev_t dev, int offset,
+                                             u32 value)
+{
+       outl(dev | offset | PCI_CFG_EN, PCI_REG_ADDR);
+       outl(value, PCI_REG_DATA);
+}
+
+/**
+ * board_assert_perst() - Assert the PERST# pin
+ *
+ * The CPU interface to the PERST# signal on Quark is platform dependent.
+ * Board-specific codes need supply this routine to assert PCIe slot reset.
+ *
+ * The tricky part in this routine is that any APIs that may trigger PCI
+ * enumeration process are strictly forbidden, as any access to PCIe root
+ * port's configuration registers will cause system hang while it is held
+ * in reset.
+ */
+void board_assert_perst(void);
+
+/**
+ * board_deassert_perst() - De-assert the PERST# pin
+ *
+ * The CPU interface to the PERST# signal on Quark is platform dependent.
+ * Board-specific codes need supply this routine to de-assert PCIe slot reset.
+ *
+ * The tricky part in this routine is that any APIs that may trigger PCI
+ * enumeration process are strictly forbidden, as any access to PCIe root
+ * port's configuration registers will cause system hang while it is held
+ * in reset.
+ */
+void board_deassert_perst(void);
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* _QUARK_H_ */
index 78447965b9287a459f40c59784a996c1dc37f644..ccbe860b147ad4bbec98fa7ce2d8f281e509b55f 100644 (file)
@@ -6,14 +6,8 @@
 
 #include <common.h>
 #include <asm/gpio.h>
-#include <netdev.h>
 
 void setup_pch_gpios(u16 gpiobase, const struct pch_gpio_map *gpio)
 {
        return;
 }
-
-int board_eth_init(bd_t *bis)
-{
-       return pci_eth_init(bis);
-}
index d6de9fabc03ca07377774c6b30e5558ce9cbd750..3a79e69112101d5b72fba749992f75150fe17501 100644 (file)
@@ -7,7 +7,6 @@
 #include <common.h>
 #include <asm/ibmpc.h>
 #include <asm/pnp_def.h>
-#include <netdev.h>
 #include <smsc_lpc47m.h>
 
 int board_early_init_f(void)
@@ -24,8 +23,3 @@ void setup_pch_gpios(u16 gpiobase, const struct pch_gpio_map *gpio)
 {
        return;
 }
-
-int board_eth_init(bd_t *bis)
-{
-       return pci_eth_init(bis);
-}
index 746ab277cb35c67645b8d454ce79a86afcc5e4fa..c1087acb690a0b1bfe7cedae51e723f19c242b6c 100644 (file)
@@ -5,12 +5,68 @@
  */
 
 #include <common.h>
+#include <asm/io.h>
+#include <asm/arch/device.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/quark.h>
 
 int board_early_init_f(void)
 {
        return 0;
 }
 
+/*
+ * Intel Galileo gen2 board uses GPIO Resume Well bank pin0 as the PERST# pin.
+ *
+ * We cannot use any public GPIO APIs in <asm-generic/gpio.h> to control this
+ * pin, as these APIs will eventually call into gpio_ich6_ofdata_to_platdata()
+ * in the Intel ICH6 GPIO driver where it calls PCI configuration space access
+ * APIs which will trigger PCI enumeration process.
+ *
+ * Check <asm/arch-quark/quark.h> for more details.
+ */
+void board_assert_perst(void)
+{
+       u32 base, port, val;
+
+       /* retrieve the GPIO IO base */
+       qrk_pci_read_config_dword(QUARK_LEGACY_BRIDGE, PCI_CFG_GPIOBASE, &base);
+       base = (base & 0xffff) & ~0x7f;
+
+       /* enable the pin */
+       port = base + 0x20;
+       val = inl(port);
+       val |= (1 << 0);
+       outl(val, port);
+
+       /* configure the pin as output */
+       port = base + 0x24;
+       val = inl(port);
+       val &= ~(1 << 0);
+       outl(val, port);
+
+       /* pull it down (assert) */
+       port = base + 0x28;
+       val = inl(port);
+       val &= ~(1 << 0);
+       outl(val, port);
+}
+
+void board_deassert_perst(void)
+{
+       u32 base, port, val;
+
+       /* retrieve the GPIO IO base */
+       qrk_pci_read_config_dword(QUARK_LEGACY_BRIDGE, PCI_CFG_GPIOBASE, &base);
+       base = (base & 0xffff) & ~0x7f;
+
+       /* pull it up (de-assert) */
+       port = base + 0x28;
+       val = inl(port);
+       val |= (1 << 0);
+       outl(val, port);
+}
+
 void setup_pch_gpios(u16 gpiobase, const struct pch_gpio_map *gpio)
 {
        return;
index 3294203b716b09fb146dbde65acb9daa59b95358..28985b8b08c5fd34009a2975ce6837b33cf16c1a 100644 (file)
 #include <netdev.h>
 #include <spi.h>
 
+#ifdef CONFIG_USB_GADGET_ATMEL_USBA
+#include <asm/arch/atmel_usba_udc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 static void corvus_nand_hw_init(void)
@@ -73,7 +77,7 @@ static void corvus_nand_hw_init(void)
 #include <spl.h>
 #include <nand.h>
 
-void at91_spl_board_init(void)
+void spl_board_init(void)
 {
        /*
         * For on the sam9m10g45ek board, the chip wm9711 stay in the test
@@ -202,6 +206,19 @@ int board_early_init_f(void)
        return 0;
 }
 
+#ifdef CONFIG_USB_GADGET_ATMEL_USBA
+/* from ./arch/arm/mach-at91/armv7/sama5d3_devices.c */
+void at91_udp_hw_init(void)
+{
+       struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+
+       /* Enable UPLL clock */
+       writel(AT91_PMC_UPLLEN | AT91_PMC_BIASEN, &pmc->uckr);
+       /* Enable UDPHS clock */
+       at91_periph_clk_enable(ATMEL_ID_UDPHS);
+}
+#endif
+
 int board_init(void)
 {
        /* address of boot parameters */
@@ -221,6 +238,10 @@ int board_init(void)
 #endif
 #ifdef CONFIG_CMD_USB
        taurus_usb_hw_init();
+#endif
+#ifdef CONFIG_USB_GADGET_ATMEL_USBA
+       at91_udp_hw_init();
+       usba_udc_probe(&pdata);
 #endif
        return 0;
 }
index cf8a7f5b06186c28c82e869503be45e94ad659e2..2d424882a9c9b8404f767c90c6a751bfb091fd8e 100644 (file)
@@ -25,6 +25,7 @@
 #include <asm/arch/at91_pmc.h>
 #include <asm/arch/at91_spi.h>
 #include <spi.h>
+#include <asm/arch/clk.h>
 #include <asm/arch/gpio.h>
 #include <watchdog.h>
 #ifdef CONFIG_MACB
@@ -108,6 +109,29 @@ static void smartweb_macb_hw_init(void)
 }
 #endif /* CONFIG_MACB */
 
+#ifdef CONFIG_USB_GADGET_AT91
+#include <linux/usb/at91_udc.h>
+
+void at91_udp_hw_init(void)
+{
+       at91_pmc_t *pmc = (at91_pmc_t *)ATMEL_BASE_PMC;
+
+       /* Enable PLLB */
+       writel(get_pllb_init(), &pmc->pllbr);
+       while ((readl(&pmc->sr) & AT91_PMC_LOCKB) != AT91_PMC_LOCKB)
+               ;
+
+       /* Enable UDPCK clock, MCK is enabled in at91_clock_init() */
+       at91_periph_clk_enable(ATMEL_ID_UDP);
+
+       writel(AT91SAM926x_PMC_UDP, &pmc->scer);
+}
+
+struct at91_udc_data board_udc_data  = {
+       .baseaddr = ATMEL_BASE_UDP0,
+};
+#endif
+
 int board_early_init_f(void)
 {
        /* enable this here, as we have SPL without serial support */
@@ -134,6 +158,11 @@ int board_init(void)
        at91_set_gpio_output(AT91_PIN_PC10, 0);
        at91_set_gpio_output(AT91_PIN_PC11, 1);
 
+#ifdef CONFIG_USB_GADGET_AT91
+       at91_udp_hw_init();
+       at91_udc_probe(&board_udc_data);
+#endif
+
        return 0;
 }
 
index 013dac2e2fb131baa83ae883c1eb514c26f55ef1..72c5e6083d53fec4cee1cd53da5cd6642131ffda 100644 (file)
@@ -12,6 +12,7 @@
  * SPDX-License-Identifier:    GPL-2.0+
  */
 
+#include <command.h>
 #include <common.h>
 #include <asm/io.h>
 #include <asm/arch/at91sam9260_matrix.h>
@@ -79,25 +80,57 @@ void matrix_init(void)
                        &mat->scfg[3]);
 }
 
-void at91_spl_board_init(void)
+#if defined(CONFIG_BOARD_AXM)
+static int at91_is_recovery(void)
+{
+       if ((at91_get_gpio_value(AT91_PIN_PA26) == 0) &&
+           (at91_get_gpio_value(AT91_PIN_PA27) == 0))
+               return 1;
+
+       return 0;
+}
+#elif defined(CONFIG_BOARD_TAURUS)
+static int at91_is_recovery(void)
+{
+       if (at91_get_gpio_value(AT91_PIN_PA31) == 0)
+               return 1;
+
+       return 0;
+}
+#endif
+
+void spl_board_init(void)
 {
        taurus_nand_hw_init();
        at91_spi0_hw_init(TAURUS_SPI_MASK);
 
+#if defined(CONFIG_BOARD_AXM)
+       /* Configure LED PINs */
+       at91_set_gpio_output(AT91_PIN_PA6, 0);
+       at91_set_gpio_output(AT91_PIN_PA8, 0);
+       at91_set_gpio_output(AT91_PIN_PA9, 0);
+       at91_set_gpio_output(AT91_PIN_PA10, 0);
+       at91_set_gpio_output(AT91_PIN_PA11, 0);
+       at91_set_gpio_output(AT91_PIN_PA12, 0);
+
        /* Configure recovery button PINs */
+       at91_set_gpio_input(AT91_PIN_PA26, 1);
+       at91_set_gpio_input(AT91_PIN_PA27, 1);
+#elif defined(CONFIG_BOARD_TAURUS)
        at91_set_gpio_input(AT91_PIN_PA31, 1);
+#endif
 
-       /* check if button is pressed */
-       if (at91_get_gpio_value(AT91_PIN_PA31) == 0) {
+       /* check for recovery mode */
+       if (at91_is_recovery() == 1) {
                struct spi_flash *flash;
 
-               debug("Recovery button pressed\n");
+               puts("Recovery button pressed\n");
                nand_init();
                spl_nand_erase_one(0, 0);
                flash = spi_flash_probe(CONFIG_SF_DEFAULT_BUS,
                                        0,
                                        CONFIG_SF_DEFAULT_SPEED,
-                                       SPI_MODE_3);
+                                       CONFIG_SF_DEFAULT_MODE);
                if (!flash) {
                        puts("no flash\n");
                } else {
@@ -108,35 +141,72 @@ void at91_spl_board_init(void)
        }
 }
 
-void mem_init(void)
+#define SDRAM_BASE_CONF        (AT91_SDRAMC_NR_13 | AT91_SDRAMC_CAS_3 \
+                        |AT91_SDRAMC_NB_4 | AT91_SDRAMC_DBW_32 \
+                        | AT91_SDRAMC_TWR_VAL(3) | AT91_SDRAMC_TRC_VAL(9) \
+                        | AT91_SDRAMC_TRP_VAL(3) | AT91_SDRAMC_TRCD_VAL(3) \
+                        | AT91_SDRAMC_TRAS_VAL(6) | AT91_SDRAMC_TXSR_VAL(10))
+
+void sdramc_configure(unsigned int mask)
 {
        struct at91_matrix *ma = (struct at91_matrix *)ATMEL_BASE_MATRIX;
        struct sdramc_reg setting;
 
        at91_sdram_hw_init();
-       setting.cr = (AT91_SDRAMC_NC_9 |
-                     AT91_SDRAMC_NR_13 |
-                     AT91_SDRAMC_CAS_3 |
-                     AT91_SDRAMC_NB_4 |
-                     AT91_SDRAMC_DBW_32 |
-                     AT91_SDRAMC_TWR_VAL(3) |
-                     AT91_SDRAMC_TRC_VAL(9) |
-                     AT91_SDRAMC_TRP_VAL(3) |
-                     AT91_SDRAMC_TRCD_VAL(3) |
-                     AT91_SDRAMC_TRAS_VAL(6) |
-                     AT91_SDRAMC_TXSR_VAL(10));
+       setting.cr = SDRAM_BASE_CONF | mask;
        setting.mdr = AT91_SDRAMC_MD_SDRAM;
        setting.tr = (CONFIG_SYS_MASTER_CLOCK * 7) / 1000000;
 
-
        writel(readl(&ma->ebicsa) | AT91_MATRIX_CS1A_SDRAMC |
                AT91_MATRIX_VDDIOMSEL_3_3V | AT91_MATRIX_EBI_IOSR_SEL,
                &ma->ebicsa);
+
        sdramc_initialize(ATMEL_BASE_CS1, &setting);
 }
+
+void mem_init(void)
+{
+       unsigned int ram_size = 0;
+
+       /* Configure SDRAM for 128MB */
+       sdramc_configure(AT91_SDRAMC_NC_10);
+
+       /* Do memtest for 128MB */
+       ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE,
+                               CONFIG_SYS_SDRAM_SIZE);
+
+       /*
+        * If 32MB or 16MB should be supported check also for
+        * expected mirroring at A16 and A17
+        * To find mirror addresses depends how the collumns are connected
+        * at RAM (internaly or externaly)
+        * If the collumns are not in inverted order the mirror size effect
+        * behaves like normal SRAM with A0,A1,A2,etc. connected incremantal
+        */
+
+       /* Mirrors at A15 on ATMEL G20 SDRAM Controller with 64MB*/
+       if (ram_size == 0x800) {
+               printf("\n\r 64MB");
+               sdramc_configure(AT91_SDRAMC_NC_9);
+       } else {
+               /* Size already initialized */
+               printf("\n\r 128MB");
+       }
+}
 #endif
 
 #ifdef CONFIG_MACB
+static void siemens_phy_reset(void)
+{
+       /*
+        * we need to reset PHY for 200us
+        * because of bug in ATMEL G20 CPU (undefined initial state of GPIO)
+        */
+       if ((readl(AT91_ASM_RSTC_SR) & AT91_RSTC_RSTTYP) ==
+           AT91_RSTC_RSTTYP_GENERAL)
+               at91_set_gpio_value(AT91_PIN_PA25, 0); /* reset eth switch */
+}
+
 static void taurus_macb_hw_init(void)
 {
        /* Enable EMAC clock */
@@ -160,6 +230,8 @@ static void taurus_macb_hw_init(void)
        at91_set_pio_pullup(AT91_PIO_PORTA, 26, 0);
        at91_set_pio_pullup(AT91_PIO_PORTA, 28, 0);
 
+       siemens_phy_reset();
+
        at91_phy_reset();
 
        at91_set_gpio_input(AT91_PIN_PA25, 1);   /* ERST tri-state */
@@ -213,6 +285,29 @@ void spi_cs_deactivate(struct spi_slave *slave)
        at91_set_gpio_value(TAURUS_SPI_CS_PIN, 1);
 }
 
+#ifdef CONFIG_USB_GADGET_AT91
+#include <linux/usb/at91_udc.h>
+
+void at91_udp_hw_init(void)
+{
+       at91_pmc_t *pmc = (at91_pmc_t *)ATMEL_BASE_PMC;
+
+       /* Enable PLLB */
+       writel(get_pllb_init(), &pmc->pllbr);
+       while ((readl(&pmc->sr) & AT91_PMC_LOCKB) != AT91_PMC_LOCKB)
+               ;
+
+       /* Enable UDPCK clock, MCK is enabled in at91_clock_init() */
+       at91_periph_clk_enable(ATMEL_ID_UDP);
+
+       writel(AT91SAM926x_PMC_UDP, &pmc->scer);
+}
+
+struct at91_udc_data board_udc_data  = {
+       .baseaddr = ATMEL_BASE_UDP0,
+};
+#endif
+
 int board_init(void)
 {
        /* adress of boot parameters */
@@ -225,6 +320,10 @@ int board_init(void)
        taurus_macb_hw_init();
 #endif
        at91_spi0_hw_init(TAURUS_SPI_MASK);
+#ifdef CONFIG_USB_GADGET_AT91
+       at91_udp_hw_init();
+       at91_udc_probe(&board_udc_data);
+#endif
 
        return 0;
 }
@@ -244,3 +343,97 @@ int board_eth_init(bd_t *bis)
 #endif
        return rc;
 }
+
+#if !defined(CONFIG_SPL_BUILD)
+#if defined(CONFIG_BOARD_AXM)
+/*
+ * Booting the Fallback Image.
+ *
+ *  The function is used to provide and
+ *  boot the image with the fallback
+ *  parameters, incase if the faulty image
+ *  in upgraded over the base firmware.
+ *
+ */
+static int upgrade_failure_fallback(void)
+{
+       char *partitionset_active = NULL;
+       char *rootfs = NULL;
+       char *rootfs_fallback = NULL;
+       char *kern_off;
+       char *kern_off_fb;
+       char *kern_size;
+       char *kern_size_fb;
+
+       partitionset_active = getenv("partitionset_active");
+       if (partitionset_active) {
+               if (partitionset_active[0] == 'A')
+                       setenv("partitionset_active", "B");
+               else
+                       setenv("partitionset_active", "A");
+       } else {
+               printf("partitionset_active missing.\n");
+               return -ENOENT;
+       }
+
+       rootfs = getenv("rootfs");
+       rootfs_fallback = getenv("rootfs_fallback");
+       setenv("rootfs", rootfs_fallback);
+       setenv("rootfs_fallback", rootfs);
+
+       kern_size = getenv("kernel_size");
+       kern_size_fb = getenv("kernel_size_fallback");
+       setenv("kernel_size", kern_size_fb);
+       setenv("kernel_size_fallback", kern_size);
+
+       kern_off = getenv("kernel_Off");
+       kern_off_fb = getenv("kernel_Off_fallback");
+       setenv("kernel_Off", kern_off_fb);
+       setenv("kernel_Off_fallback", kern_off);
+
+       setenv("bootargs", '\0');
+       setenv("upgrade_available", '\0');
+       setenv("boot_retries", '\0');
+       saveenv();
+
+       return 0;
+}
+
+static int do_upgrade_available(cmd_tbl_t *cmdtp, int flag, int argc,
+                       char * const argv[])
+{
+       unsigned long upgrade_available = 0;
+       unsigned long boot_retry = 0;
+       char boot_buf[10];
+
+       upgrade_available = simple_strtoul(getenv("upgrade_available"), NULL,
+                                          10);
+       if (upgrade_available) {
+               boot_retry = simple_strtoul(getenv("boot_retries"), NULL, 10);
+               boot_retry++;
+               sprintf(boot_buf, "%lx", boot_retry);
+               setenv("boot_retries", boot_buf);
+               saveenv();
+
+               /*
+                * Here the boot_retries count is checked, and if the
+                * count becomes greater than 2 switch back to the
+                * fallback, and reset the board.
+                */
+
+               if (boot_retry > 2) {
+                       if (upgrade_failure_fallback() == 0)
+                               do_reset(NULL, 0, 0, NULL);
+                       return -1;
+               }
+       }
+       return 0;
+}
+
+U_BOOT_CMD(
+       upgrade_available,      1,      1,      do_upgrade_available,
+       "check Siemens update",
+       "no parameters"
+);
+#endif
+#endif
index 13bd282024b7c24ea8ae55cdc89968defca5d979..2ea30c82275f3d62b2017b0db2d6b4a7842523c4 100644 (file)
@@ -5,6 +5,7 @@ CONFIG_TARGET_BAYLEYBAY=y
 CONFIG_HAVE_INTEL_ME=y
 CONFIG_SMP=y
 CONFIG_HAVE_VGA_BIOS=y
+CONFIG_VGA_BIOS_ADDR=0xfffa0000
 CONFIG_GENERATE_PIRQ_TABLE=y
 CONFIG_GENERATE_MP_TABLE=y
 CONFIG_CMD_CPU=y
@@ -19,11 +20,13 @@ CONFIG_OF_CONTROL=y
 CONFIG_CPU=y
 CONFIG_DM_PCI=y
 CONFIG_SPI_FLASH=y
-CONFIG_NETDEVICES=y
+CONFIG_DM_ETH=y
 CONFIG_E1000=y
 CONFIG_VIDEO_VESA=y
 CONFIG_FRAMEBUFFER_SET_VESA_MODE=y
 CONFIG_FRAMEBUFFER_VESA_MODE_11A=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
 CONFIG_DM_RTC=y
 CONFIG_USE_PRIVATE_LIBGCC=y
 CONFIG_SYS_VSNPRINTF=y
index ebaf86bc7fb80a5a9e4dea3bfa47b169ad64e87b..e95f96d77953d4084a59d547f802cbbaebb91888 100644 (file)
@@ -14,10 +14,13 @@ CONFIG_CMD_TPM_TEST=y
 CONFIG_OF_CONTROL=y
 CONFIG_DM_PCI=y
 CONFIG_SPI_FLASH=y
-CONFIG_NETDEVICES=y
+CONFIG_DM_ETH=y
 CONFIG_E1000=y
 CONFIG_DM_TPM=y
 CONFIG_TPM_TIS_LPC=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_DM_RTC=y
 CONFIG_USE_PRIVATE_LIBGCC=y
 CONFIG_SYS_VSNPRINTF=y
 CONFIG_TPM=y
index 4fc182748261ec6f77e146309a284a5162125b09..f328159051e19d7e5b0b616f1ab6c92431a0643a 100644 (file)
@@ -19,10 +19,13 @@ CONFIG_OF_CONTROL=y
 CONFIG_CPU=y
 CONFIG_DM_PCI=y
 CONFIG_SPI_FLASH=y
-CONFIG_NETDEVICES=y
+CONFIG_DM_ETH=y
 CONFIG_E1000=y
+CONFIG_PCH_GBE=y
 CONFIG_VIDEO_VESA=y
 CONFIG_FRAMEBUFFER_SET_VESA_MODE=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
 CONFIG_DM_RTC=y
 CONFIG_USE_PRIVATE_LIBGCC=y
 CONFIG_SYS_VSNPRINTF=y
index 6ef1090e1ee965a56b4305315ec3f18b3d1d33c7..d05154ee0a61d554d41aad4e355ea82538450218 100644 (file)
@@ -14,6 +14,9 @@ CONFIG_OF_CONTROL=y
 CONFIG_SPI_FLASH=y
 CONFIG_NETDEVICES=y
 CONFIG_ETH_DESIGNWARE=y
+CONFIG_DM_PCI=y
 CONFIG_DM_RTC=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
 CONFIG_USE_PRIVATE_LIBGCC=y
 CONFIG_SYS_VSNPRINTF=y
index 3bab5cf64e62902240a705e32aa3290205cd596f..5f9c46f05d98eb8d30fa5757e47b4253f2da98a4 100644 (file)
@@ -189,7 +189,7 @@ Offset   Description         Controlling config
 001000   me.bin              Set by the descriptor
 500000   <spare>
 700000   u-boot-dtb.bin      CONFIG_SYS_TEXT_BASE
-790000   vga.bin             CONFIG_X86_OPTION_ROM_ADDR
+790000   vga.bin             CONFIG_VGA_BIOS_ADDR
 7c0000   fsp.bin             CONFIG_FSP_ADDR
 7f8000   <spare>             (depends on size of fsp.bin)
 7fe000   Environment         CONFIG_ENV_OFFSET
index 7367d9e5ac911bf91343ee345a2a7f16f5cc953c..bbec6a60e01a42b4411bd6b75d0d5d8fc6ab93ac 100644 (file)
@@ -8,6 +8,11 @@ config DM_ETH
          This is currently implemented in net/eth.c
          Look in include/net.h for details.
 
+config PHYLIB
+       bool "Ethernet PHY (physical media interface) support"
+       help
+         Enable Ethernet PHY (physical media interface) support.
+
 menuconfig NETDEVICES
        bool "Network device support"
        depends on NET
@@ -79,4 +84,12 @@ config ETH_DESIGNWARE
          100Mbit and 1 Gbit operation. You must enable CONFIG_PHYLIB to
          provide the PHY (physical media interface).
 
+config PCH_GBE
+       bool "Intel Platform Controller Hub EG20T GMAC driver"
+       depends on DM_ETH && DM_PCI
+       select PHYLIB
+       help
+         This MAC is present in Intel Platform Controller Hub EG20T. It
+         supports 10/100/1000 Mbps operation.
+
 endif # NETDEVICES
index d9cb5076951a9a5c5576c434a734e45bf7976c46..ae78d21db6d95a5d2b63552d7ef7d9d1d3fb7937 100644 (file)
@@ -562,12 +562,12 @@ static int designware_eth_probe(struct udevice *dev)
 {
        struct eth_pdata *pdata = dev_get_platdata(dev);
        struct dw_eth_dev *priv = dev_get_priv(dev);
+       u32 iobase = pdata->iobase;
        int ret;
 
-       debug("%s, iobase=%lx, priv=%p\n", __func__, pdata->iobase, priv);
-       priv->mac_regs_p = (struct eth_mac_regs *)pdata->iobase;
-       priv->dma_regs_p = (struct eth_dma_regs *)(pdata->iobase +
-                       DW_DMA_BASE_OFFSET);
+       debug("%s, iobase=%x, priv=%p\n", __func__, iobase, priv);
+       priv->mac_regs_p = (struct eth_mac_regs *)iobase;
+       priv->dma_regs_p = (struct eth_dma_regs *)(iobase + DW_DMA_BASE_OFFSET);
        priv->interface = pdata->phy_interface;
 
        dw_mdio_init(dev->name, priv->mac_regs_p);
index a03bdc06300fde51293a30baa930c0697306f28b..004fcf88c207066b3b6aa03e3d9010c38561e07f 100644 (file)
@@ -7,10 +7,10 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <errno.h>
 #include <asm/io.h>
 #include <pci.h>
-#include <malloc.h>
 #include <miiphy.h>
 #include "pch_gbe.h"
 
@@ -19,7 +19,7 @@
 #endif
 
 static struct pci_device_id supported[] = {
-       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TCF_GBE },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TCF_GBE) },
        { }
 };
 
@@ -62,9 +62,10 @@ static int pch_gbe_mac_write(struct pch_gbe_regs *mac_regs, u8 *addr)
        return -ETIME;
 }
 
-static int pch_gbe_reset(struct eth_device *dev)
+static int pch_gbe_reset(struct udevice *dev)
 {
-       struct pch_gbe_priv *priv = dev->priv;
+       struct pch_gbe_priv *priv = dev_get_priv(dev);
+       struct eth_pdata *plat = dev_get_platdata(dev);
        struct pch_gbe_regs *mac_regs = priv->mac_regs;
        ulong start;
 
@@ -97,7 +98,7 @@ static int pch_gbe_reset(struct eth_device *dev)
                         * so we have to reload MAC address here in order to
                         * make linux pch_gbe driver happy.
                         */
-                       return pch_gbe_mac_write(mac_regs, dev->enetaddr);
+                       return pch_gbe_mac_write(mac_regs, plat->enetaddr);
                }
 
                udelay(10);
@@ -107,9 +108,9 @@ static int pch_gbe_reset(struct eth_device *dev)
        return -ETIME;
 }
 
-static void pch_gbe_rx_descs_init(struct eth_device *dev)
+static void pch_gbe_rx_descs_init(struct udevice *dev)
 {
-       struct pch_gbe_priv *priv = dev->priv;
+       struct pch_gbe_priv *priv = dev_get_priv(dev);
        struct pch_gbe_regs *mac_regs = priv->mac_regs;
        struct pch_gbe_rx_desc *rx_desc = &priv->rx_desc[0];
        int i;
@@ -128,9 +129,9 @@ static void pch_gbe_rx_descs_init(struct eth_device *dev)
               &mac_regs->rx_dsc_sw_p);
 }
 
-static void pch_gbe_tx_descs_init(struct eth_device *dev)
+static void pch_gbe_tx_descs_init(struct udevice *dev)
 {
-       struct pch_gbe_priv *priv = dev->priv;
+       struct pch_gbe_priv *priv = dev_get_priv(dev);
        struct pch_gbe_regs *mac_regs = priv->mac_regs;
        struct pch_gbe_tx_desc *tx_desc = &priv->tx_desc[0];
 
@@ -183,9 +184,9 @@ static void pch_gbe_adjust_link(struct pch_gbe_regs *mac_regs,
        return;
 }
 
-static int pch_gbe_init(struct eth_device *dev, bd_t *bis)
+static int pch_gbe_start(struct udevice *dev)
 {
-       struct pch_gbe_priv *priv = dev->priv;
+       struct pch_gbe_priv *priv = dev_get_priv(dev);
        struct pch_gbe_regs *mac_regs = priv->mac_regs;
 
        if (pch_gbe_reset(dev))
@@ -226,18 +227,18 @@ static int pch_gbe_init(struct eth_device *dev, bd_t *bis)
        return 0;
 }
 
-static void pch_gbe_halt(struct eth_device *dev)
+static void pch_gbe_stop(struct udevice *dev)
 {
-       struct pch_gbe_priv *priv = dev->priv;
+       struct pch_gbe_priv *priv = dev_get_priv(dev);
 
        pch_gbe_reset(dev);
 
        phy_shutdown(priv->phydev);
 }
 
-static int pch_gbe_send(struct eth_device *dev, void *packet, int length)
+static int pch_gbe_send(struct udevice *dev, void *packet, int length)
 {
-       struct pch_gbe_priv *priv = dev->priv;
+       struct pch_gbe_priv *priv = dev_get_priv(dev);
        struct pch_gbe_regs *mac_regs = priv->mac_regs;
        struct pch_gbe_tx_desc *tx_head, *tx_desc;
        u16 frame_ctrl = 0;
@@ -277,15 +278,13 @@ static int pch_gbe_send(struct eth_device *dev, void *packet, int length)
        return -ETIME;
 }
 
-static int pch_gbe_recv(struct eth_device *dev)
+static int pch_gbe_recv(struct udevice *dev, int flags, uchar **packetp)
 {
-       struct pch_gbe_priv *priv = dev->priv;
+       struct pch_gbe_priv *priv = dev_get_priv(dev);
        struct pch_gbe_regs *mac_regs = priv->mac_regs;
-       struct pch_gbe_rx_desc *rx_head, *rx_desc;
+       struct pch_gbe_rx_desc *rx_desc;
        u32 hw_desc, buffer_addr, length;
-       int rx_swp;
 
-       rx_head = &priv->rx_desc[0];
        rx_desc = &priv->rx_desc[priv->rx_idx];
 
        readl(&mac_regs->int_st);
@@ -293,11 +292,21 @@ static int pch_gbe_recv(struct eth_device *dev)
 
        /* Just return if not receiving any packet */
        if ((u32)rx_desc == hw_desc)
-               return 0;
+               return -EAGAIN;
 
        buffer_addr = pci_mem_to_phys(priv->bdf, rx_desc->buffer_addr);
+       *packetp = (uchar *)buffer_addr;
        length = rx_desc->rx_words_eob - 3 - ETH_FCS_LEN;
-       net_process_received_packet((uchar *)buffer_addr, length);
+
+       return length;
+}
+
+static int pch_gbe_free_pkt(struct udevice *dev, uchar *packet, int length)
+{
+       struct pch_gbe_priv *priv = dev_get_priv(dev);
+       struct pch_gbe_regs *mac_regs = priv->mac_regs;
+       struct pch_gbe_rx_desc *rx_head = &priv->rx_desc[0];
+       int rx_swp;
 
        /* Test the wrap-around condition */
        if (++priv->rx_idx >= PCH_GBE_DESC_NUM)
@@ -309,7 +318,7 @@ static int pch_gbe_recv(struct eth_device *dev)
        writel(pci_phys_to_mem(priv->bdf, (u32)(rx_head + rx_swp)),
               &mac_regs->rx_dsc_sw_p);
 
-       return length;
+       return 0;
 }
 
 static int pch_gbe_mdio_ready(struct pch_gbe_regs *mac_regs)
@@ -365,7 +374,7 @@ static int pch_gbe_mdio_write(struct mii_dev *bus, int addr, int devad,
                return 0;
 }
 
-static int pch_gbe_mdio_init(char *name, struct pch_gbe_regs *mac_regs)
+static int pch_gbe_mdio_init(const char *name, struct pch_gbe_regs *mac_regs)
 {
        struct mii_dev *bus;
 
@@ -384,13 +393,14 @@ static int pch_gbe_mdio_init(char *name, struct pch_gbe_regs *mac_regs)
        return mdio_register(bus);
 }
 
-static int pch_gbe_phy_init(struct eth_device *dev)
+static int pch_gbe_phy_init(struct udevice *dev)
 {
-       struct pch_gbe_priv *priv = dev->priv;
+       struct pch_gbe_priv *priv = dev_get_priv(dev);
+       struct eth_pdata *plat = dev_get_platdata(dev);
        struct phy_device *phydev;
        int mask = 0xffffffff;
 
-       phydev = phy_find_by_mask(priv->bus, mask, priv->interface);
+       phydev = phy_find_by_mask(priv->bus, mask, plat->phy_interface);
        if (!phydev) {
                printf("pch_gbe: cannot find the phy\n");
                return -1;
@@ -404,63 +414,66 @@ static int pch_gbe_phy_init(struct eth_device *dev)
        priv->phydev = phydev;
        phy_config(phydev);
 
-       return 1;
+       return 0;
 }
 
-int pch_gbe_register(bd_t *bis)
+int pch_gbe_probe(struct udevice *dev)
 {
-       struct eth_device *dev;
        struct pch_gbe_priv *priv;
+       struct eth_pdata *plat = dev_get_platdata(dev);
        pci_dev_t devno;
        u32 iobase;
 
-       devno = pci_find_devices(supported, 0);
-       if (devno == -1)
-               return -ENODEV;
-
-       dev = (struct eth_device *)malloc(sizeof(*dev));
-       if (!dev)
-               return -ENOMEM;
-       memset(dev, 0, sizeof(*dev));
+       devno = pci_get_bdf(dev);
 
        /*
         * The priv structure contains the descriptors and frame buffers which
-        * need a strict buswidth alignment (64 bytes)
+        * need a strict buswidth alignment (64 bytes). This is guaranteed by
+        * DM_FLAG_ALLOC_PRIV_DMA flag in the U_BOOT_DRIVER.
         */
-       priv = (struct pch_gbe_priv *)memalign(PCH_GBE_ALIGN_SIZE,
-                                              sizeof(*priv));
-       if (!priv) {
-               free(dev);
-               return -ENOMEM;
-       }
-       memset(priv, 0, sizeof(*priv));
+       priv = dev_get_priv(dev);
 
-       dev->priv = priv;
-       priv->dev = dev;
        priv->bdf = devno;
 
        pci_read_config_dword(devno, PCI_BASE_ADDRESS_1, &iobase);
        iobase &= PCI_BASE_ADDRESS_MEM_MASK;
        iobase = pci_mem_to_phys(devno, iobase);
 
-       dev->iobase = iobase;
+       plat->iobase = iobase;
        priv->mac_regs = (struct pch_gbe_regs *)iobase;
 
-       sprintf(dev->name, "pch_gbe");
-
        /* Read MAC address from SROM and initialize dev->enetaddr with it */
-       pch_gbe_mac_read(priv->mac_regs, dev->enetaddr);
-
-       dev->init = pch_gbe_init;
-       dev->halt = pch_gbe_halt;
-       dev->send = pch_gbe_send;
-       dev->recv = pch_gbe_recv;
+       pch_gbe_mac_read(priv->mac_regs, plat->enetaddr);
 
-       eth_register(dev);
-
-       priv->interface = PHY_INTERFACE_MODE_RGMII;
+       plat->phy_interface = PHY_INTERFACE_MODE_RGMII;
        pch_gbe_mdio_init(dev->name, priv->mac_regs);
        priv->bus = miiphy_get_dev_by_name(dev->name);
 
        return pch_gbe_phy_init(dev);
 }
+
+static const struct eth_ops pch_gbe_ops = {
+       .start = pch_gbe_start,
+       .send = pch_gbe_send,
+       .recv = pch_gbe_recv,
+       .free_pkt = pch_gbe_free_pkt,
+       .stop = pch_gbe_stop,
+};
+
+static const struct udevice_id pch_gbe_ids[] = {
+       { .compatible = "intel,pch-gbe" },
+       { }
+};
+
+U_BOOT_DRIVER(eth_pch_gbe) = {
+       .name = "pch_gbe",
+       .id = UCLASS_ETH,
+       .of_match = pch_gbe_ids,
+       .probe = pch_gbe_probe,
+       .ops = &pch_gbe_ops,
+       .priv_auto_alloc_size = sizeof(struct pch_gbe_priv),
+       .platdata_auto_alloc_size = sizeof(struct eth_pdata),
+       .flags = DM_FLAG_ALLOC_PRIV_DMA,
+};
+
+U_BOOT_PCI_DEVICE(eth_pch_gbe, supported);
index 11329d4834d6eec4fe7d4e0fec068907a3ec9c2a..afcb03dd36a1605ca9fd9e35e1a115051e450695 100644 (file)
@@ -287,12 +287,10 @@ struct pch_gbe_priv {
        struct pch_gbe_rx_desc rx_desc[PCH_GBE_DESC_NUM];
        struct pch_gbe_tx_desc tx_desc[PCH_GBE_DESC_NUM];
        char rx_buff[PCH_GBE_DESC_NUM][PCH_GBE_RX_FRAME_LEN];
-       struct eth_device *dev;
        struct phy_device *phydev;
        struct mii_dev *bus;
        struct pch_gbe_regs *mac_regs;
        pci_dev_t bdf;
-       u32 interface;
        int rx_idx;
        int tx_idx;
 };
index b25298fb5e9cec04a8a5e383206521049e8c18c3..ea70853da21fa1e756a342404801148479bcd747 100644 (file)
 
 DECLARE_GLOBAL_DATA_PTR;
 
+static int pci_get_bus(int busnum, struct udevice **busp)
+{
+       int ret;
+
+       ret = uclass_get_device_by_seq(UCLASS_PCI, busnum, busp);
+
+       /* Since buses may not be numbered yet try a little harder with bus 0 */
+       if (ret == -ENODEV) {
+               ret = uclass_first_device(UCLASS_PCI, busp);
+               if (ret)
+                       return ret;
+               else if (!*busp)
+                       return -ENODEV;
+               ret = uclass_get_device_by_seq(UCLASS_PCI, busnum, busp);
+       }
+
+       return ret;
+}
+
 struct pci_controller *pci_bus_to_hose(int busnum)
 {
        struct udevice *bus;
        int ret;
 
-       ret = uclass_get_device_by_seq(UCLASS_PCI, busnum, &bus);
+       ret = pci_get_bus(busnum, &bus);
        if (ret) {
                debug("%s: Cannot get bus %d: ret=%d\n", __func__, busnum, ret);
                return NULL;
        }
+
        return dev_get_uclass_priv(bus);
 }
 
@@ -128,7 +148,7 @@ int pci_bus_find_bdf(pci_dev_t bdf, struct udevice **devp)
        struct udevice *bus;
        int ret;
 
-       ret = uclass_get_device_by_seq(UCLASS_PCI, PCI_BUS(bdf), &bus);
+       ret = pci_get_bus(PCI_BUS(bdf), &bus);
        if (ret)
                return ret;
        return pci_bus_find_devfn(bus, PCI_MASK_BUS(bdf), devp);
@@ -206,7 +226,7 @@ int pci_write_config(pci_dev_t bdf, int offset, unsigned long value,
        struct udevice *bus;
        int ret;
 
-       ret = uclass_get_device_by_seq(UCLASS_PCI, PCI_BUS(bdf), &bus);
+       ret = pci_get_bus(PCI_BUS(bdf), &bus);
        if (ret)
                return ret;
 
@@ -271,7 +291,7 @@ int pci_read_config(pci_dev_t bdf, int offset, unsigned long *valuep,
        struct udevice *bus;
        int ret;
 
-       ret = uclass_get_device_by_seq(UCLASS_PCI, PCI_BUS(bdf), &bus);
+       ret = pci_get_bus(PCI_BUS(bdf), &bus);
        if (ret)
                return ret;
 
index 4c11a7e32677ab4d62aae367cd74f7aafa01b07b..6288ecf09f5316385b17ef2054b518277745a5c8 100644 (file)
@@ -10,6 +10,7 @@ obj-$(CONFIG_USB_ETHER) += epautoconf.o config.o usbstring.o
 
 # new USB gadget layer dependencies
 ifdef CONFIG_USB_GADGET
+obj-$(CONFIG_USB_GADGET_AT91) += at91_udc.o
 obj-$(CONFIG_USB_GADGET_ATMEL_USBA) += atmel_usba_udc.o
 obj-$(CONFIG_USB_GADGET_BCM_UDC_OTG_PHY) += bcm_udc_otg_phy.o
 obj-$(CONFIG_USB_GADGET_S3C_UDC_OTG) += s3c_udc_otg.o
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
new file mode 100644 (file)
index 0000000..4070803
--- /dev/null
@@ -0,0 +1,1625 @@
+/*
+ * from linux:
+ * c94e289f195e: usb: gadget: remove incorrect __init/__exit annotations
+ *
+ * at91_udc -- driver for at91-series USB peripheral controller
+ *
+ * Copyright (C) 2004 by Thomas Rathbone
+ * Copyright (C) 2005 by HP Labs
+ * Copyright (C) 2005 by David Brownell
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#undef VERBOSE_DEBUG
+#undef PACKET_TRACE
+
+#include <common.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/gpio.h>
+#include <asm/hardware.h>
+#include <mach/at91_matrix.h>
+#include <linux/list.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/at91_udc.h>
+#include <malloc.h>
+#include <usb/lin_gadget_compat.h>
+
+#include "at91_udc.h"
+
+/*
+ * This controller is simple and PIO-only.  It's used in many AT91-series
+ * full speed USB controllers, including the at91rm9200 (arm920T, with MMU),
+ * at91sam926x (arm926ejs, with MMU), and several no-mmu versions.
+ *
+ * This driver expects the board has been wired with two GPIOs supporting
+ * a VBUS sensing IRQ, and a D+ pullup.  (They may be omitted, but the
+ * testing hasn't covered such cases.)
+ *
+ * The pullup is most important (so it's integrated on sam926x parts).  It
+ * provides software control over whether the host enumerates the device.
+ *
+ * The VBUS sensing helps during enumeration, and allows both USB clocks
+ * (and the transceiver) to stay gated off until they're necessary, saving
+ * power.  During USB suspend, the 48 MHz clock is gated off in hardware;
+ * it may also be gated off by software during some Linux sleep states.
+ */
+
+#define        DRIVER_VERSION  "3 May 2006"
+
+static const char driver_name [] = "at91_udc";
+static const char * const ep_names[] = {
+       "ep0",
+       "ep1",
+       "ep2",
+       "ep3-int",
+       "ep4",
+       "ep5",
+};
+#define ep0name                ep_names[0]
+
+#define at91_udp_read(udc, reg) \
+       __raw_readl((udc)->udp_baseaddr + (reg))
+#define at91_udp_write(udc, reg, val) \
+       __raw_writel((val), (udc)->udp_baseaddr + (reg))
+
+static struct at91_udc *controller;
+
+/*-------------------------------------------------------------------------*/
+
+static void done(struct at91_ep *ep, struct at91_request *req, int status)
+{
+       unsigned        stopped = ep->stopped;
+       struct at91_udc *udc = ep->udc;
+
+       list_del_init(&req->queue);
+       if (req->req.status == -EINPROGRESS)
+               req->req.status = status;
+       else
+               status = req->req.status;
+       if (status && status != -ESHUTDOWN)
+               VDBG("%s done %p, status %d\n", ep->ep.name, req, status);
+
+       ep->stopped = 1;
+       spin_unlock(&udc->lock);
+       req->req.complete(&ep->ep, &req->req);
+       spin_lock(&udc->lock);
+       ep->stopped = stopped;
+
+       /* ep0 is always ready; other endpoints need a non-empty queue */
+       if (list_empty(&ep->queue) && ep->int_mask != (1 << 0))
+               at91_udp_write(udc, AT91_UDP_IDR, ep->int_mask);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* bits indicating OUT fifo has data ready */
+#define        RX_DATA_READY   (AT91_UDP_RX_DATA_BK0 | AT91_UDP_RX_DATA_BK1)
+
+/*
+ * Endpoint FIFO CSR bits have a mix of bits, making it unsafe to just write
+ * back most of the value you just read (because of side effects, including
+ * bits that may change after reading and before writing).
+ *
+ * Except when changing a specific bit, always write values which:
+ *  - clear SET_FX bits (setting them could change something)
+ *  - set CLR_FX bits (clearing them could change something)
+ *
+ * There are also state bits like FORCESTALL, EPEDS, DIR, and EPTYPE
+ * that shouldn't normally be changed.
+ *
+ * NOTE at91sam9260 docs mention synch between UDPCK and MCK clock domains,
+ * implying a need to wait for one write to complete (test relevant bits)
+ * before starting the next write.  This shouldn't be an issue given how
+ * infrequently we write, except maybe for write-then-read idioms.
+ */
+#define        SET_FX  (AT91_UDP_TXPKTRDY)
+#define        CLR_FX  (RX_DATA_READY | AT91_UDP_RXSETUP \
+               | AT91_UDP_STALLSENT | AT91_UDP_TXCOMP)
+
+/* pull OUT packet data from the endpoint's fifo */
+static int read_fifo (struct at91_ep *ep, struct at91_request *req)
+{
+       u32 __iomem     *creg = ep->creg;
+       u8 __iomem      *dreg = ep->creg + (AT91_UDP_FDR(0) - AT91_UDP_CSR(0));
+       u32             csr;
+       u8              *buf;
+       unsigned int    count, bufferspace, is_done;
+
+       buf = req->req.buf + req->req.actual;
+       bufferspace = req->req.length - req->req.actual;
+
+       /*
+        * there might be nothing to read if ep_queue() calls us,
+        * or if we already emptied both pingpong buffers
+        */
+rescan:
+       csr = __raw_readl(creg);
+       if ((csr & RX_DATA_READY) == 0)
+               return 0;
+
+       count = (csr & AT91_UDP_RXBYTECNT) >> 16;
+       if (count > ep->ep.maxpacket)
+               count = ep->ep.maxpacket;
+       if (count > bufferspace) {
+               DBG("%s buffer overflow\n", ep->ep.name);
+               req->req.status = -EOVERFLOW;
+               count = bufferspace;
+       }
+       __raw_readsb((unsigned long)dreg, buf, count);
+
+       /* release and swap pingpong mem bank */
+       csr |= CLR_FX;
+       if (ep->is_pingpong) {
+               if (ep->fifo_bank == 0) {
+                       csr &= ~(SET_FX | AT91_UDP_RX_DATA_BK0);
+                       ep->fifo_bank = 1;
+               } else {
+                       csr &= ~(SET_FX | AT91_UDP_RX_DATA_BK1);
+                       ep->fifo_bank = 0;
+               }
+       } else
+               csr &= ~(SET_FX | AT91_UDP_RX_DATA_BK0);
+       __raw_writel(csr, creg);
+
+       req->req.actual += count;
+       is_done = (count < ep->ep.maxpacket);
+       if (count == bufferspace)
+               is_done = 1;
+
+       PACKET("%s %p out/%d%s\n", ep->ep.name, &req->req, count,
+                       is_done ? " (done)" : "");
+
+       /*
+        * avoid extra trips through IRQ logic for packets already in
+        * the fifo ... maybe preventing an extra (expensive) OUT-NAK
+        */
+       if (is_done)
+               done(ep, req, 0);
+       else if (ep->is_pingpong) {
+               /*
+                * One dummy read to delay the code because of a HW glitch:
+                * CSR returns bad RXCOUNT when read too soon after updating
+                * RX_DATA_BK flags.
+                */
+               csr = __raw_readl(creg);
+
+               bufferspace -= count;
+               buf += count;
+               goto rescan;
+       }
+
+       return is_done;
+}
+
+/* load fifo for an IN packet */
+static int write_fifo(struct at91_ep *ep, struct at91_request *req)
+{
+       u32 __iomem     *creg = ep->creg;
+       u32             csr = __raw_readl(creg);
+       u8 __iomem      *dreg = ep->creg + (AT91_UDP_FDR(0) - AT91_UDP_CSR(0));
+       unsigned        total, count, is_last;
+       u8              *buf;
+
+       /*
+        * TODO: allow for writing two packets to the fifo ... that'll
+        * reduce the amount of IN-NAKing, but probably won't affect
+        * throughput much.  (Unlike preventing OUT-NAKing!)
+        */
+
+       /*
+        * If ep_queue() calls us, the queue is empty and possibly in
+        * odd states like TXCOMP not yet cleared (we do it, saving at
+        * least one IRQ) or the fifo not yet being free.  Those aren't
+        * issues normally (IRQ handler fast path).
+        */
+       if (unlikely(csr & (AT91_UDP_TXCOMP | AT91_UDP_TXPKTRDY))) {
+               if (csr & AT91_UDP_TXCOMP) {
+                       csr |= CLR_FX;
+                       csr &= ~(SET_FX | AT91_UDP_TXCOMP);
+                       __raw_writel(csr, creg);
+                       csr = __raw_readl(creg);
+               }
+               if (csr & AT91_UDP_TXPKTRDY)
+                       return 0;
+       }
+
+       buf = req->req.buf + req->req.actual;
+       prefetch(buf);
+       total = req->req.length - req->req.actual;
+       if (ep->ep.maxpacket < total) {
+               count = ep->ep.maxpacket;
+               is_last = 0;
+       } else {
+               count = total;
+               is_last = (count < ep->ep.maxpacket) || !req->req.zero;
+       }
+
+       /*
+        * Write the packet, maybe it's a ZLP.
+        *
+        * NOTE:  incrementing req->actual before we receive the ACK means
+        * gadget driver IN bytecounts can be wrong in fault cases.  That's
+        * fixable with PIO drivers like this one (save "count" here, and
+        * do the increment later on TX irq), but not for most DMA hardware.
+        *
+        * So all gadget drivers must accept that potential error.  Some
+        * hardware supports precise fifo status reporting, letting them
+        * recover when the actual bytecount matters (e.g. for USB Test
+        * and Measurement Class devices).
+        */
+       __raw_writesb((unsigned long)dreg, buf, count);
+       csr &= ~SET_FX;
+       csr |= CLR_FX | AT91_UDP_TXPKTRDY;
+       __raw_writel(csr, creg);
+       req->req.actual += count;
+
+       PACKET("%s %p in/%d%s\n", ep->ep.name, &req->req, count,
+                       is_last ? " (done)" : "");
+       if (is_last)
+               done(ep, req, 0);
+       return is_last;
+}
+
+static void nuke(struct at91_ep *ep, int status)
+{
+       struct at91_request *req;
+
+       /* terminate any request in the queue */
+       ep->stopped = 1;
+       if (list_empty(&ep->queue))
+               return;
+
+       VDBG("%s %s\n", __func__, ep->ep.name);
+       while (!list_empty(&ep->queue)) {
+               req = list_entry(ep->queue.next, struct at91_request, queue);
+               done(ep, req, status);
+       }
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int at91_ep_enable(struct usb_ep *_ep,
+                               const struct usb_endpoint_descriptor *desc)
+{
+       struct at91_ep  *ep = container_of(_ep, struct at91_ep, ep);
+       struct at91_udc *udc;
+       u16             maxpacket;
+       u32             tmp;
+       unsigned long   flags;
+
+       if (!_ep || !ep
+                       || !desc || _ep->name == ep0name
+                       || desc->bDescriptorType != USB_DT_ENDPOINT
+                       || (maxpacket = usb_endpoint_maxp(desc)) == 0
+                       || maxpacket > ep->maxpacket) {
+               DBG("bad ep or descriptor\n");
+               return -EINVAL;
+       }
+
+       udc = ep->udc;
+       if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN) {
+               DBG("bogus device state\n");
+               return -ESHUTDOWN;
+       }
+
+       tmp = usb_endpoint_type(desc);
+       switch (tmp) {
+       case USB_ENDPOINT_XFER_CONTROL:
+               DBG("only one control endpoint\n");
+               return -EINVAL;
+       case USB_ENDPOINT_XFER_INT:
+               if (maxpacket > 64)
+                       goto bogus_max;
+               break;
+       case USB_ENDPOINT_XFER_BULK:
+               switch (maxpacket) {
+               case 8:
+               case 16:
+               case 32:
+               case 64:
+                       goto ok;
+               }
+bogus_max:
+               DBG("bogus maxpacket %d\n", maxpacket);
+               return -EINVAL;
+       case USB_ENDPOINT_XFER_ISOC:
+               if (!ep->is_pingpong) {
+                       DBG("iso requires double buffering\n");
+                       return -EINVAL;
+               }
+               break;
+       }
+
+ok:
+       spin_lock_irqsave(&udc->lock, flags);
+
+       /* initialize endpoint to match this descriptor */
+       ep->is_in = usb_endpoint_dir_in(desc);
+       ep->is_iso = (tmp == USB_ENDPOINT_XFER_ISOC);
+       ep->stopped = 0;
+       if (ep->is_in)
+               tmp |= 0x04;
+       tmp <<= 8;
+       tmp |= AT91_UDP_EPEDS;
+       __raw_writel(tmp, ep->creg);
+
+       ep->ep.maxpacket = maxpacket;
+
+       /*
+        * reset/init endpoint fifo.  NOTE:  leaves fifo_bank alone,
+        * since endpoint resets don't reset hw pingpong state.
+        */
+       at91_udp_write(udc, AT91_UDP_RST_EP, ep->int_mask);
+       at91_udp_write(udc, AT91_UDP_RST_EP, 0);
+
+       spin_unlock_irqrestore(&udc->lock, flags);
+       return 0;
+}
+
+static int at91_ep_disable (struct usb_ep * _ep)
+{
+       struct at91_ep  *ep = container_of(_ep, struct at91_ep, ep);
+       struct at91_udc *udc = ep->udc;
+       unsigned long   flags;
+
+       if (ep == &ep->udc->ep[0])
+               return -EINVAL;
+
+       spin_lock_irqsave(&udc->lock, flags);
+
+       nuke(ep, -ESHUTDOWN);
+
+       /* restore the endpoint's pristine config */
+       ep->ep.desc = NULL;
+       ep->ep.maxpacket = ep->maxpacket;
+
+       /* reset fifos and endpoint */
+       if (ep->udc->clocked) {
+               at91_udp_write(udc, AT91_UDP_RST_EP, ep->int_mask);
+               at91_udp_write(udc, AT91_UDP_RST_EP, 0);
+               __raw_writel(0, ep->creg);
+       }
+
+       spin_unlock_irqrestore(&udc->lock, flags);
+       return 0;
+}
+
+/*
+ * this is a PIO-only driver, so there's nothing
+ * interesting for request or buffer allocation.
+ */
+
+static struct usb_request *
+at91_ep_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
+{
+       struct at91_request *req;
+
+       req = kzalloc(sizeof (struct at91_request), gfp_flags);
+       if (!req)
+               return NULL;
+
+       INIT_LIST_HEAD(&req->queue);
+       return &req->req;
+}
+
+static void at91_ep_free_request(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct at91_request *req;
+
+       req = container_of(_req, struct at91_request, req);
+       BUG_ON(!list_empty(&req->queue));
+       kfree(req);
+}
+
+static int at91_ep_queue(struct usb_ep *_ep,
+                       struct usb_request *_req, gfp_t gfp_flags)
+{
+       struct at91_request     *req;
+       struct at91_ep          *ep;
+       struct at91_udc         *udc;
+       int                     status;
+       unsigned long           flags;
+
+       req = container_of(_req, struct at91_request, req);
+       ep = container_of(_ep, struct at91_ep, ep);
+
+       if (!_req || !_req->complete
+                       || !_req->buf || !list_empty(&req->queue)) {
+               DBG("invalid request\n");
+               return -EINVAL;
+       }
+
+       if (!_ep || (!ep->ep.desc && ep->ep.name != ep0name)) {
+               DBG("invalid ep\n");
+               return -EINVAL;
+       }
+
+       udc = ep->udc;
+
+       if (!udc || !udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN) {
+               DBG("invalid device\n");
+               return -EINVAL;
+       }
+
+       _req->status = -EINPROGRESS;
+       _req->actual = 0;
+
+       spin_lock_irqsave(&udc->lock, flags);
+
+       /* try to kickstart any empty and idle queue */
+       if (list_empty(&ep->queue) && !ep->stopped) {
+               int     is_ep0;
+
+               /*
+                * If this control request has a non-empty DATA stage, this
+                * will start that stage.  It works just like a non-control
+                * request (until the status stage starts, maybe early).
+                *
+                * If the data stage is empty, then this starts a successful
+                * IN/STATUS stage.  (Unsuccessful ones use set_halt.)
+                */
+               is_ep0 = (ep->ep.name == ep0name);
+               if (is_ep0) {
+                       u32     tmp;
+
+                       if (!udc->req_pending) {
+                               status = -EINVAL;
+                               goto done;
+                       }
+
+                       /*
+                        * defer changing CONFG until after the gadget driver
+                        * reconfigures the endpoints.
+                        */
+                       if (udc->wait_for_config_ack) {
+                               tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT);
+                               tmp ^= AT91_UDP_CONFG;
+                               VDBG("toggle config\n");
+                               at91_udp_write(udc, AT91_UDP_GLB_STAT, tmp);
+                       }
+                       if (req->req.length == 0) {
+ep0_in_status:
+                               PACKET("ep0 in/status\n");
+                               status = 0;
+                               tmp = __raw_readl(ep->creg);
+                               tmp &= ~SET_FX;
+                               tmp |= CLR_FX | AT91_UDP_TXPKTRDY;
+                               __raw_writel(tmp, ep->creg);
+                               udc->req_pending = 0;
+                               goto done;
+                       }
+               }
+
+               if (ep->is_in)
+                       status = write_fifo(ep, req);
+               else {
+                       status = read_fifo(ep, req);
+
+                       /* IN/STATUS stage is otherwise triggered by irq */
+                       if (status && is_ep0)
+                               goto ep0_in_status;
+               }
+       } else
+               status = 0;
+
+       if (req && !status) {
+               list_add_tail (&req->queue, &ep->queue);
+               at91_udp_write(udc, AT91_UDP_IER, ep->int_mask);
+       }
+done:
+       spin_unlock_irqrestore(&udc->lock, flags);
+       return (status < 0) ? status : 0;
+}
+
+static int at91_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct at91_ep          *ep;
+       struct at91_request     *req;
+       unsigned long           flags;
+
+       ep = container_of(_ep, struct at91_ep, ep);
+       if (!_ep || ep->ep.name == ep0name)
+               return -EINVAL;
+
+       spin_lock_irqsave(&udc->lock, 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) {
+               spin_unlock_irqrestore(&udc->lock, flags);
+               return -EINVAL;
+       }
+
+       done(ep, req, -ECONNRESET);
+       spin_unlock_irqrestore(&udc->lock, flags);
+       return 0;
+}
+
+static int at91_ep_set_halt(struct usb_ep *_ep, int value)
+{
+       struct at91_ep  *ep = container_of(_ep, struct at91_ep, ep);
+       struct at91_udc *udc = ep->udc;
+       u32 __iomem     *creg;
+       u32             csr;
+       unsigned long   flags;
+       int             status = 0;
+
+       if (!_ep || ep->is_iso || !ep->udc->clocked)
+               return -EINVAL;
+
+       creg = ep->creg;
+       spin_lock_irqsave(&udc->lock, flags);
+
+       csr = __raw_readl(creg);
+
+       /*
+        * fail with still-busy IN endpoints, ensuring correct sequencing
+        * of data tx then stall.  note that the fifo rx bytecount isn't
+        * completely accurate as a tx bytecount.
+        */
+       if (ep->is_in && (!list_empty(&ep->queue) || (csr >> 16) != 0))
+               status = -EAGAIN;
+       else {
+               csr |= CLR_FX;
+               csr &= ~SET_FX;
+               if (value) {
+                       csr |= AT91_UDP_FORCESTALL;
+                       VDBG("halt %s\n", ep->ep.name);
+               } else {
+                       at91_udp_write(udc, AT91_UDP_RST_EP, ep->int_mask);
+                       at91_udp_write(udc, AT91_UDP_RST_EP, 0);
+                       csr &= ~AT91_UDP_FORCESTALL;
+               }
+               __raw_writel(csr, creg);
+       }
+
+       spin_unlock_irqrestore(&udc->lock, flags);
+       return status;
+}
+
+static const struct usb_ep_ops at91_ep_ops = {
+       .enable         = at91_ep_enable,
+       .disable        = at91_ep_disable,
+       .alloc_request  = at91_ep_alloc_request,
+       .free_request   = at91_ep_free_request,
+       .queue          = at91_ep_queue,
+       .dequeue        = at91_ep_dequeue,
+       .set_halt       = at91_ep_set_halt,
+       /* there's only imprecise fifo status reporting */
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int at91_get_frame(struct usb_gadget *gadget)
+{
+       struct at91_udc *udc = to_udc(gadget);
+
+       if (!to_udc(gadget)->clocked)
+               return -EINVAL;
+       return at91_udp_read(udc, AT91_UDP_FRM_NUM) & AT91_UDP_NUM;
+}
+
+static int at91_wakeup(struct usb_gadget *gadget)
+{
+       struct at91_udc *udc = to_udc(gadget);
+       u32             glbstate;
+       int             status = -EINVAL;
+       unsigned long   flags;
+
+       DBG("%s\n", __func__ );
+       spin_lock_irqsave(&udc->lock, flags);
+
+       if (!udc->clocked || !udc->suspended)
+               goto done;
+
+       /* NOTE:  some "early versions" handle ESR differently ... */
+
+       glbstate = at91_udp_read(udc, AT91_UDP_GLB_STAT);
+       if (!(glbstate & AT91_UDP_ESR))
+               goto done;
+       glbstate |= AT91_UDP_ESR;
+       at91_udp_write(udc, AT91_UDP_GLB_STAT, glbstate);
+
+done:
+       spin_unlock_irqrestore(&udc->lock, flags);
+       return status;
+}
+
+/* reinit == restore initial software state */
+static void udc_reinit(struct at91_udc *udc)
+{
+       u32 i;
+
+       INIT_LIST_HEAD(&udc->gadget.ep_list);
+       INIT_LIST_HEAD(&udc->gadget.ep0->ep_list);
+
+       for (i = 0; i < NUM_ENDPOINTS; i++) {
+               struct at91_ep *ep = &udc->ep[i];
+
+               if (i != 0)
+                       list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
+               ep->ep.desc = NULL;
+               ep->stopped = 0;
+               ep->fifo_bank = 0;
+               usb_ep_set_maxpacket_limit(&ep->ep, ep->maxpacket);
+               ep->creg = (void __iomem *) udc->udp_baseaddr + AT91_UDP_CSR(i);
+               /* initialize one queue per endpoint */
+               INIT_LIST_HEAD(&ep->queue);
+       }
+}
+
+static void reset_gadget(struct at91_udc *udc)
+{
+       struct usb_gadget_driver *driver = udc->driver;
+       int i;
+
+       if (udc->gadget.speed == USB_SPEED_UNKNOWN)
+               driver = NULL;
+       udc->gadget.speed = USB_SPEED_UNKNOWN;
+       udc->suspended = 0;
+
+       for (i = 0; i < NUM_ENDPOINTS; i++) {
+               struct at91_ep *ep = &udc->ep[i];
+
+               ep->stopped = 1;
+               nuke(ep, -ESHUTDOWN);
+       }
+       if (driver) {
+               spin_unlock(&udc->lock);
+               udc->driver->disconnect(&udc->gadget);
+               spin_lock(&udc->lock);
+       }
+
+       udc_reinit(udc);
+}
+
+static void stop_activity(struct at91_udc *udc)
+{
+       struct usb_gadget_driver *driver = udc->driver;
+       int i;
+
+       if (udc->gadget.speed == USB_SPEED_UNKNOWN)
+               driver = NULL;
+       udc->gadget.speed = USB_SPEED_UNKNOWN;
+       udc->suspended = 0;
+
+       for (i = 0; i < NUM_ENDPOINTS; i++) {
+               struct at91_ep *ep = &udc->ep[i];
+               ep->stopped = 1;
+               nuke(ep, -ESHUTDOWN);
+       }
+       if (driver) {
+               spin_unlock(&udc->lock);
+               driver->disconnect(&udc->gadget);
+               spin_lock(&udc->lock);
+       }
+
+       udc_reinit(udc);
+}
+
+static void clk_on(struct at91_udc *udc)
+{
+       if (udc->clocked)
+               return;
+       udc->clocked = 1;
+}
+
+static void clk_off(struct at91_udc *udc)
+{
+       if (!udc->clocked)
+               return;
+       udc->clocked = 0;
+       udc->gadget.speed = USB_SPEED_UNKNOWN;
+}
+
+/*
+ * activate/deactivate link with host; minimize power usage for
+ * inactive links by cutting clocks and transceiver power.
+ */
+static void pullup(struct at91_udc *udc, int is_on)
+{
+       if (!udc->enabled || !udc->vbus)
+               is_on = 0;
+       DBG("%sactive\n", is_on ? "" : "in");
+
+       if (is_on) {
+               clk_on(udc);
+               at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_RXRSM);
+               at91_udp_write(udc, AT91_UDP_TXVC, 0);
+       } else {
+               stop_activity(udc);
+               at91_udp_write(udc, AT91_UDP_IDR, AT91_UDP_RXRSM);
+               at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
+               clk_off(udc);
+       }
+
+       if (udc->caps && udc->caps->pullup)
+               udc->caps->pullup(udc, is_on);
+}
+
+/* vbus is here!  turn everything on that's ready */
+static int at91_vbus_session(struct usb_gadget *gadget, int is_active)
+{
+       struct at91_udc *udc = to_udc(gadget);
+       unsigned long   flags;
+
+       /* VDBG("vbus %s\n", is_active ? "on" : "off"); */
+       spin_lock_irqsave(&udc->lock, flags);
+       udc->vbus = (is_active != 0);
+       if (udc->driver)
+               pullup(udc, is_active);
+       else
+               pullup(udc, 0);
+       spin_unlock_irqrestore(&udc->lock, flags);
+       return 0;
+}
+
+static int at91_pullup(struct usb_gadget *gadget, int is_on)
+{
+       struct at91_udc *udc = to_udc(gadget);
+       unsigned long   flags;
+
+       spin_lock_irqsave(&udc->lock, flags);
+       udc->enabled = is_on = !!is_on;
+       pullup(udc, is_on);
+       spin_unlock_irqrestore(&udc->lock, flags);
+       return 0;
+}
+
+static int at91_set_selfpowered(struct usb_gadget *gadget, int is_on)
+{
+       struct at91_udc *udc = to_udc(gadget);
+       unsigned long   flags;
+
+       spin_lock_irqsave(&udc->lock, flags);
+       udc->selfpowered = (is_on != 0);
+       spin_unlock_irqrestore(&udc->lock, flags);
+       return 0;
+}
+
+static int at91_start(struct usb_gadget *gadget,
+               struct usb_gadget_driver *driver);
+static int at91_stop(struct usb_gadget *gadget);
+
+static const struct usb_gadget_ops at91_udc_ops = {
+       .get_frame              = at91_get_frame,
+       .wakeup                 = at91_wakeup,
+       .set_selfpowered        = at91_set_selfpowered,
+       .vbus_session           = at91_vbus_session,
+       .pullup                 = at91_pullup,
+       .udc_start              = at91_start,
+       .udc_stop               = at91_stop,
+
+       /*
+        * VBUS-powered devices may also also want to support bigger
+        * power budgets after an appropriate SET_CONFIGURATION.
+        */
+       /* .vbus_power          = at91_vbus_power, */
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int handle_ep(struct at91_ep *ep)
+{
+       struct at91_request     *req;
+       u32 __iomem             *creg = ep->creg;
+       u32                     csr = __raw_readl(creg);
+
+       if (!list_empty(&ep->queue))
+               req = list_entry(ep->queue.next,
+                       struct at91_request, queue);
+       else
+               req = NULL;
+
+       if (ep->is_in) {
+               if (csr & (AT91_UDP_STALLSENT | AT91_UDP_TXCOMP)) {
+                       csr |= CLR_FX;
+                       csr &= ~(SET_FX | AT91_UDP_STALLSENT | AT91_UDP_TXCOMP);
+                       __raw_writel(csr, creg);
+               }
+               if (req)
+                       return write_fifo(ep, req);
+
+       } else {
+               if (csr & AT91_UDP_STALLSENT) {
+                       /* STALLSENT bit == ISOERR */
+                       if (ep->is_iso && req)
+                               req->req.status = -EILSEQ;
+                       csr |= CLR_FX;
+                       csr &= ~(SET_FX | AT91_UDP_STALLSENT);
+                       __raw_writel(csr, creg);
+                       csr = __raw_readl(creg);
+               }
+               if (req && (csr & RX_DATA_READY))
+                       return read_fifo(ep, req);
+       }
+       return 0;
+}
+
+union setup {
+       u8                      raw[8];
+       struct usb_ctrlrequest  r;
+};
+
+static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr)
+{
+       u32 __iomem     *creg = ep->creg;
+       u8 __iomem      *dreg = ep->creg + (AT91_UDP_FDR(0) - AT91_UDP_CSR(0));
+       unsigned        rxcount, i = 0;
+       u32             tmp;
+       union setup     pkt;
+       int             status = 0;
+
+       /* read and ack SETUP; hard-fail for bogus packets */
+       rxcount = (csr & AT91_UDP_RXBYTECNT) >> 16;
+       if (likely(rxcount == 8)) {
+               while (rxcount--)
+                       pkt.raw[i++] = __raw_readb(dreg);
+               if (pkt.r.bRequestType & USB_DIR_IN) {
+                       csr |= AT91_UDP_DIR;
+                       ep->is_in = 1;
+               } else {
+                       csr &= ~AT91_UDP_DIR;
+                       ep->is_in = 0;
+               }
+       } else {
+               /* REVISIT this happens sometimes under load; why?? */
+               ERR("SETUP len %d, csr %08x\n", rxcount, csr);
+               status = -EINVAL;
+       }
+       csr |= CLR_FX;
+       csr &= ~(SET_FX | AT91_UDP_RXSETUP);
+       __raw_writel(csr, creg);
+       udc->wait_for_addr_ack = 0;
+       udc->wait_for_config_ack = 0;
+       ep->stopped = 0;
+       if (unlikely(status != 0))
+               goto stall;
+
+#define w_index                le16_to_cpu(pkt.r.wIndex)
+#define w_value                le16_to_cpu(pkt.r.wValue)
+#define w_length       le16_to_cpu(pkt.r.wLength)
+
+       VDBG("SETUP %02x.%02x v%04x i%04x l%04x\n",
+                       pkt.r.bRequestType, pkt.r.bRequest,
+                       w_value, w_index, w_length);
+
+       /*
+        * A few standard requests get handled here, ones that touch
+        * hardware ... notably for device and endpoint features.
+        */
+       udc->req_pending = 1;
+       csr = __raw_readl(creg);
+       csr |= CLR_FX;
+       csr &= ~SET_FX;
+       switch ((pkt.r.bRequestType << 8) | pkt.r.bRequest) {
+
+       case ((USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8)
+                       | USB_REQ_SET_ADDRESS:
+               __raw_writel(csr | AT91_UDP_TXPKTRDY, creg);
+               udc->addr = w_value;
+               udc->wait_for_addr_ack = 1;
+               udc->req_pending = 0;
+               /* FADDR is set later, when we ack host STATUS */
+               return;
+
+       case ((USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8)
+                       | USB_REQ_SET_CONFIGURATION:
+               tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT) & AT91_UDP_CONFG;
+               if (pkt.r.wValue)
+                       udc->wait_for_config_ack = (tmp == 0);
+               else
+                       udc->wait_for_config_ack = (tmp != 0);
+               if (udc->wait_for_config_ack)
+                       VDBG("wait for config\n");
+               /* CONFG is toggled later, if gadget driver succeeds */
+               break;
+
+       /*
+        * Hosts may set or clear remote wakeup status, and
+        * devices may report they're VBUS powered.
+        */
+       case ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8)
+                       | USB_REQ_GET_STATUS:
+               tmp = (udc->selfpowered << USB_DEVICE_SELF_POWERED);
+               if (at91_udp_read(udc, AT91_UDP_GLB_STAT) & AT91_UDP_ESR)
+                       tmp |= (1 << USB_DEVICE_REMOTE_WAKEUP);
+               PACKET("get device status\n");
+               __raw_writeb(tmp, dreg);
+               __raw_writeb(0, dreg);
+               goto write_in;
+               /* then STATUS starts later, automatically */
+       case ((USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8)
+                       | USB_REQ_SET_FEATURE:
+               if (w_value != USB_DEVICE_REMOTE_WAKEUP)
+                       goto stall;
+               tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT);
+               tmp |= AT91_UDP_ESR;
+               at91_udp_write(udc, AT91_UDP_GLB_STAT, tmp);
+               goto succeed;
+       case ((USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8)
+                       | USB_REQ_CLEAR_FEATURE:
+               if (w_value != USB_DEVICE_REMOTE_WAKEUP)
+                       goto stall;
+               tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT);
+               tmp &= ~AT91_UDP_ESR;
+               at91_udp_write(udc, AT91_UDP_GLB_STAT, tmp);
+               goto succeed;
+
+       /*
+        * Interfaces have no feature settings; this is pretty useless.
+        * we won't even insist the interface exists...
+        */
+       case ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_INTERFACE) << 8)
+                       | USB_REQ_GET_STATUS:
+               PACKET("get interface status\n");
+               __raw_writeb(0, dreg);
+               __raw_writeb(0, dreg);
+               goto write_in;
+               /* then STATUS starts later, automatically */
+       case ((USB_TYPE_STANDARD|USB_RECIP_INTERFACE) << 8)
+                       | USB_REQ_SET_FEATURE:
+       case ((USB_TYPE_STANDARD|USB_RECIP_INTERFACE) << 8)
+                       | USB_REQ_CLEAR_FEATURE:
+               goto stall;
+
+       /*
+        * Hosts may clear bulk/intr endpoint halt after the gadget
+        * driver sets it (not widely used); or set it (for testing)
+        */
+       case ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_ENDPOINT) << 8)
+                       | USB_REQ_GET_STATUS:
+               tmp = w_index & USB_ENDPOINT_NUMBER_MASK;
+               ep = &udc->ep[tmp];
+               if (tmp >= NUM_ENDPOINTS || (tmp && !ep->ep.desc))
+                       goto stall;
+
+               if (tmp) {
+                       if ((w_index & USB_DIR_IN)) {
+                               if (!ep->is_in)
+                                       goto stall;
+                       } else if (ep->is_in)
+                               goto stall;
+               }
+               PACKET("get %s status\n", ep->ep.name);
+               if (__raw_readl(ep->creg) & AT91_UDP_FORCESTALL)
+                       tmp = (1 << USB_ENDPOINT_HALT);
+               else
+                       tmp = 0;
+               __raw_writeb(tmp, dreg);
+               __raw_writeb(0, dreg);
+               goto write_in;
+               /* then STATUS starts later, automatically */
+       case ((USB_TYPE_STANDARD|USB_RECIP_ENDPOINT) << 8)
+                       | USB_REQ_SET_FEATURE:
+               tmp = w_index & USB_ENDPOINT_NUMBER_MASK;
+               ep = &udc->ep[tmp];
+               if (w_value != USB_ENDPOINT_HALT || tmp >= NUM_ENDPOINTS)
+                       goto stall;
+               if (!ep->ep.desc || ep->is_iso)
+                       goto stall;
+               if ((w_index & USB_DIR_IN)) {
+                       if (!ep->is_in)
+                               goto stall;
+               } else if (ep->is_in)
+                       goto stall;
+
+               tmp = __raw_readl(ep->creg);
+               tmp &= ~SET_FX;
+               tmp |= CLR_FX | AT91_UDP_FORCESTALL;
+               __raw_writel(tmp, ep->creg);
+               goto succeed;
+       case ((USB_TYPE_STANDARD|USB_RECIP_ENDPOINT) << 8)
+                       | USB_REQ_CLEAR_FEATURE:
+               tmp = w_index & USB_ENDPOINT_NUMBER_MASK;
+               ep = &udc->ep[tmp];
+               if (w_value != USB_ENDPOINT_HALT || tmp >= NUM_ENDPOINTS)
+                       goto stall;
+               if (tmp == 0)
+                       goto succeed;
+               if (!ep->ep.desc || ep->is_iso)
+                       goto stall;
+               if ((w_index & USB_DIR_IN)) {
+                       if (!ep->is_in)
+                               goto stall;
+               } else if (ep->is_in)
+                       goto stall;
+
+               at91_udp_write(udc, AT91_UDP_RST_EP, ep->int_mask);
+               at91_udp_write(udc, AT91_UDP_RST_EP, 0);
+               tmp = __raw_readl(ep->creg);
+               tmp |= CLR_FX;
+               tmp &= ~(SET_FX | AT91_UDP_FORCESTALL);
+               __raw_writel(tmp, ep->creg);
+               if (!list_empty(&ep->queue))
+                       handle_ep(ep);
+               goto succeed;
+       }
+
+#undef w_value
+#undef w_index
+#undef w_length
+
+       /* pass request up to the gadget driver */
+       if (udc->driver) {
+               spin_unlock(&udc->lock);
+               status = udc->driver->setup(&udc->gadget, &pkt.r);
+               spin_lock(&udc->lock);
+       }
+       else
+               status = -ENODEV;
+       if (status < 0) {
+stall:
+               VDBG("req %02x.%02x protocol STALL; stat %d\n",
+                               pkt.r.bRequestType, pkt.r.bRequest, status);
+               csr |= AT91_UDP_FORCESTALL;
+               __raw_writel(csr, creg);
+               udc->req_pending = 0;
+       }
+       return;
+
+succeed:
+       /* immediate successful (IN) STATUS after zero length DATA */
+       PACKET("ep0 in/status\n");
+write_in:
+       csr |= AT91_UDP_TXPKTRDY;
+       __raw_writel(csr, creg);
+       udc->req_pending = 0;
+}
+
+static void handle_ep0(struct at91_udc *udc)
+{
+       struct at91_ep          *ep0 = &udc->ep[0];
+       u32 __iomem             *creg = ep0->creg;
+       u32                     csr = __raw_readl(creg);
+       struct at91_request     *req;
+
+       if (unlikely(csr & AT91_UDP_STALLSENT)) {
+               nuke(ep0, -EPROTO);
+               udc->req_pending = 0;
+               csr |= CLR_FX;
+               csr &= ~(SET_FX | AT91_UDP_STALLSENT | AT91_UDP_FORCESTALL);
+               __raw_writel(csr, creg);
+               VDBG("ep0 stalled\n");
+               csr = __raw_readl(creg);
+       }
+       if (csr & AT91_UDP_RXSETUP) {
+               nuke(ep0, 0);
+               udc->req_pending = 0;
+               handle_setup(udc, ep0, csr);
+               return;
+       }
+
+       if (list_empty(&ep0->queue))
+               req = NULL;
+       else
+               req = list_entry(ep0->queue.next, struct at91_request, queue);
+
+       /* host ACKed an IN packet that we sent */
+       if (csr & AT91_UDP_TXCOMP) {
+               csr |= CLR_FX;
+               csr &= ~(SET_FX | AT91_UDP_TXCOMP);
+
+               /* write more IN DATA? */
+               if (req && ep0->is_in) {
+                       if (handle_ep(ep0))
+                               udc->req_pending = 0;
+
+               /*
+                * Ack after:
+                *  - last IN DATA packet (including GET_STATUS)
+                *  - IN/STATUS for OUT DATA
+                *  - IN/STATUS for any zero-length DATA stage
+                * except for the IN DATA case, the host should send
+                * an OUT status later, which we'll ack.
+                */
+               } else {
+                       udc->req_pending = 0;
+                       __raw_writel(csr, creg);
+
+                       /*
+                        * SET_ADDRESS takes effect only after the STATUS
+                        * (to the original address) gets acked.
+                        */
+                       if (udc->wait_for_addr_ack) {
+                               u32     tmp;
+
+                               at91_udp_write(udc, AT91_UDP_FADDR,
+                                               AT91_UDP_FEN | udc->addr);
+                               tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT);
+                               tmp &= ~AT91_UDP_FADDEN;
+                               if (udc->addr)
+                                       tmp |= AT91_UDP_FADDEN;
+                               at91_udp_write(udc, AT91_UDP_GLB_STAT, tmp);
+
+                               udc->wait_for_addr_ack = 0;
+                               VDBG("address %d\n", udc->addr);
+                       }
+               }
+       }
+
+       /* OUT packet arrived ... */
+       else if (csr & AT91_UDP_RX_DATA_BK0) {
+               csr |= CLR_FX;
+               csr &= ~(SET_FX | AT91_UDP_RX_DATA_BK0);
+
+               /* OUT DATA stage */
+               if (!ep0->is_in) {
+                       if (req) {
+                               if (handle_ep(ep0)) {
+                                       /* send IN/STATUS */
+                                       PACKET("ep0 in/status\n");
+                                       csr = __raw_readl(creg);
+                                       csr &= ~SET_FX;
+                                       csr |= CLR_FX | AT91_UDP_TXPKTRDY;
+                                       __raw_writel(csr, creg);
+                                       udc->req_pending = 0;
+                               }
+                       } else if (udc->req_pending) {
+                               /*
+                                * AT91 hardware has a hard time with this
+                                * "deferred response" mode for control-OUT
+                                * transfers.  (For control-IN it's fine.)
+                                *
+                                * The normal solution leaves OUT data in the
+                                * fifo until the gadget driver is ready.
+                                * We couldn't do that here without disabling
+                                * the IRQ that tells about SETUP packets,
+                                * e.g. when the host gets impatient...
+                                *
+                                * Working around it by copying into a buffer
+                                * would almost be a non-deferred response,
+                                * except that it wouldn't permit reliable
+                                * stalling of the request.  Instead, demand
+                                * that gadget drivers not use this mode.
+                                */
+                               DBG("no control-OUT deferred responses!\n");
+                               __raw_writel(csr | AT91_UDP_FORCESTALL, creg);
+                               udc->req_pending = 0;
+                       }
+
+               /* STATUS stage for control-IN; ack.  */
+               } else {
+                       PACKET("ep0 out/status ACK\n");
+                       __raw_writel(csr, creg);
+
+                       /* "early" status stage */
+                       if (req)
+                               done(ep0, req, 0);
+               }
+       }
+}
+
+static irqreturn_t at91_udc_irq(struct at91_udc *udc)
+{
+       u32                     rescans = 5;
+       int                     disable_clock = 0;
+       unsigned long           flags;
+
+       spin_lock_irqsave(&udc->lock, flags);
+
+       if (!udc->clocked) {
+               clk_on(udc);
+               disable_clock = 1;
+       }
+
+       while (rescans--) {
+               u32 status;
+
+               status = at91_udp_read(udc, AT91_UDP_ISR)
+                       & at91_udp_read(udc, AT91_UDP_IMR);
+               if (!status)
+                       break;
+
+               /* USB reset irq:  not maskable */
+               if (status & AT91_UDP_ENDBUSRES) {
+                       at91_udp_write(udc, AT91_UDP_IDR, ~MINIMUS_INTERRUPTUS);
+                       at91_udp_write(udc, AT91_UDP_IER, MINIMUS_INTERRUPTUS);
+                       /* Atmel code clears this irq twice */
+                       at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_ENDBUSRES);
+                       at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_ENDBUSRES);
+                       VDBG("end bus reset\n");
+                       udc->addr = 0;
+                       reset_gadget(udc);
+
+                       /* enable ep0 */
+                       at91_udp_write(udc, AT91_UDP_CSR(0),
+                                       AT91_UDP_EPEDS | AT91_UDP_EPTYPE_CTRL);
+                       udc->gadget.speed = USB_SPEED_FULL;
+                       udc->suspended = 0;
+                       at91_udp_write(udc, AT91_UDP_IER, AT91_UDP_EP(0));
+
+                       /*
+                        * NOTE:  this driver keeps clocks off unless the
+                        * USB host is present.  That saves power, but for
+                        * boards that don't support VBUS detection, both
+                        * clocks need to be active most of the time.
+                        */
+
+               /* host initiated suspend (3+ms bus idle) */
+               } else if (status & AT91_UDP_RXSUSP) {
+                       at91_udp_write(udc, AT91_UDP_IDR, AT91_UDP_RXSUSP);
+                       at91_udp_write(udc, AT91_UDP_IER, AT91_UDP_RXRSM);
+                       at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_RXSUSP);
+                       /* VDBG("bus suspend\n"); */
+                       if (udc->suspended)
+                               continue;
+                       udc->suspended = 1;
+
+                       /*
+                        * NOTE:  when suspending a VBUS-powered device, the
+                        * gadget driver should switch into slow clock mode
+                        * and then into standby to avoid drawing more than
+                        * 500uA power (2500uA for some high-power configs).
+                        */
+                       if (udc->driver && udc->driver->suspend) {
+                               spin_unlock(&udc->lock);
+                               udc->driver->suspend(&udc->gadget);
+                               spin_lock(&udc->lock);
+                       }
+
+               /* host initiated resume */
+               } else if (status & AT91_UDP_RXRSM) {
+                       at91_udp_write(udc, AT91_UDP_IDR, AT91_UDP_RXRSM);
+                       at91_udp_write(udc, AT91_UDP_IER, AT91_UDP_RXSUSP);
+                       at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_RXRSM);
+                       /* VDBG("bus resume\n"); */
+                       if (!udc->suspended)
+                               continue;
+                       udc->suspended = 0;
+
+                       /*
+                        * NOTE:  for a VBUS-powered device, the gadget driver
+                        * would normally want to switch out of slow clock
+                        * mode into normal mode.
+                        */
+                       if (udc->driver && udc->driver->resume) {
+                               spin_unlock(&udc->lock);
+                               udc->driver->resume(&udc->gadget);
+                               spin_lock(&udc->lock);
+                       }
+
+               /* endpoint IRQs are cleared by handling them */
+               } else {
+                       int             i;
+                       unsigned        mask = 1;
+                       struct at91_ep  *ep = &udc->ep[1];
+
+                       if (status & mask)
+                               handle_ep0(udc);
+                       for (i = 1; i < NUM_ENDPOINTS; i++) {
+                               mask <<= 1;
+                               if (status & mask)
+                                       handle_ep(ep);
+                               ep++;
+                       }
+               }
+       }
+
+       if (disable_clock)
+               clk_off(udc);
+
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       return IRQ_HANDLED;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int at91_start(struct usb_gadget *gadget,
+               struct usb_gadget_driver *driver)
+{
+       struct at91_udc *udc = controller;
+
+       udc->driver = driver;
+       udc->enabled = 1;
+       udc->selfpowered = 1;
+
+       return 0;
+}
+
+static int at91_stop(struct usb_gadget *gadget)
+{
+       struct at91_udc *udc = controller;
+       unsigned long   flags;
+
+       spin_lock_irqsave(&udc->lock, flags);
+       udc->enabled = 0;
+       at91_udp_write(udc, AT91_UDP_IDR, ~0);
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       udc->driver = NULL;
+
+       return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int at91rm9200_udc_init(struct at91_udc *udc)
+{
+       struct at91_ep *ep;
+       int ret;
+       int i;
+
+       for (i = 0; i < NUM_ENDPOINTS; i++) {
+               ep = &udc->ep[i];
+
+               switch (i) {
+               case 0:
+               case 3:
+                       ep->maxpacket = 8;
+                       break;
+               case 1 ... 2:
+                       ep->maxpacket = 64;
+                       break;
+               case 4 ... 5:
+                       ep->maxpacket = 256;
+                       break;
+               }
+       }
+
+       ret = gpio_request(udc->board.pullup_pin, "udc_pullup");
+       if (ret) {
+               DBG("D+ pullup is busy\n");
+               return ret;
+       }
+
+       gpio_direction_output(udc->board.pullup_pin,
+                             udc->board.pullup_active_low);
+
+       return 0;
+}
+
+static void at91rm9200_udc_pullup(struct at91_udc *udc, int is_on)
+{
+       int active = !udc->board.pullup_active_low;
+
+       if (is_on)
+               gpio_set_value(udc->board.pullup_pin, active);
+       else
+               gpio_set_value(udc->board.pullup_pin, !active);
+}
+
+static const struct at91_udc_caps at91rm9200_udc_caps = {
+       .init = at91rm9200_udc_init,
+       .pullup = at91rm9200_udc_pullup,
+};
+
+static int at91sam9260_udc_init(struct at91_udc *udc)
+{
+       struct at91_ep *ep;
+       int i;
+
+       for (i = 0; i < NUM_ENDPOINTS; i++) {
+               ep = &udc->ep[i];
+
+               switch (i) {
+               case 0 ... 3:
+                       ep->maxpacket = 64;
+                       break;
+               case 4 ... 5:
+                       ep->maxpacket = 512;
+                       break;
+               }
+       }
+
+       return 0;
+}
+
+#if defined(CONFIG_AT91SAM9260) || defined(CONFIG_AT91SAM9G20)
+static void at91sam9260_udc_pullup(struct at91_udc *udc, int is_on)
+{
+       u32 txvc = at91_udp_read(udc, AT91_UDP_TXVC);
+
+       if (is_on)
+               txvc |= AT91_UDP_TXVC_PUON;
+       else
+               txvc &= ~AT91_UDP_TXVC_PUON;
+
+       at91_udp_write(udc, AT91_UDP_TXVC, txvc);
+}
+
+static const struct at91_udc_caps at91sam9260_udc_caps = {
+       .init = at91sam9260_udc_init,
+       .pullup = at91sam9260_udc_pullup,
+};
+#endif
+
+#if defined(CONFIG_AT91SAM9261)
+static int at91sam9261_udc_init(struct at91_udc *udc)
+{
+       struct at91_ep *ep;
+       int i;
+
+       for (i = 0; i < NUM_ENDPOINTS; i++) {
+               ep = &udc->ep[i];
+
+               switch (i) {
+               case 0:
+                       ep->maxpacket = 8;
+                       break;
+               case 1 ... 3:
+                       ep->maxpacket = 64;
+                       break;
+               case 4 ... 5:
+                       ep->maxpacket = 256;
+                       break;
+               }
+       }
+
+       udc->matrix = (struct at91_matrix *)ATMEL_BASE_MATRIX;
+
+       if (IS_ERR(udc->matrix))
+               return PTR_ERR(udc->matrix);
+
+       return 0;
+}
+
+static void at91sam9261_udc_pullup(struct at91_udc *udc, int is_on)
+{
+       u32 usbpucr = 0;
+
+       usbpucr = readl(&udc->matrix->pucr);
+       if (is_on)
+               usbpucr |= AT91_MATRIX_USBPUCR_PUON;
+
+       writel(usbpucr, &udc->matrix->pucr);
+}
+
+static const struct at91_udc_caps at91sam9261_udc_caps = {
+       .init = at91sam9261_udc_init,
+       .pullup = at91sam9261_udc_pullup,
+};
+#endif
+
+static int at91sam9263_udc_init(struct at91_udc *udc)
+{
+       struct at91_ep *ep;
+       int i;
+
+       for (i = 0; i < NUM_ENDPOINTS; i++) {
+               ep = &udc->ep[i];
+
+               switch (i) {
+               case 0:
+               case 1:
+               case 2:
+               case 3:
+                       ep->maxpacket = 64;
+                       break;
+               case 4:
+               case 5:
+                       ep->maxpacket = 256;
+                       break;
+               }
+       }
+
+       return 0;
+}
+
+static const struct at91_udc_caps at91sam9263_udc_caps = {
+       .init = at91sam9263_udc_init,
+       .pullup = at91sam9260_udc_pullup,
+};
+
+int usb_gadget_handle_interrupts(int index)
+{
+       struct at91_udc *udc = controller;
+
+       return at91_udc_irq(udc);
+}
+
+int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+{
+       struct at91_udc *udc = controller;
+       int ret;
+
+       if (!driver || !driver->bind || !driver->setup) {
+               printf("bad paramter\n");
+               return -EINVAL;
+       }
+
+       if (udc->driver) {
+               printf("UDC already has a gadget driver\n");
+               return -EBUSY;
+       }
+
+       at91_start(&udc->gadget, driver);
+
+       udc->driver = driver;
+
+       ret = driver->bind(&udc->gadget);
+       if (ret) {
+               error("driver->bind() returned %d\n", ret);
+               udc->driver = NULL;
+       }
+
+       return ret;
+}
+
+int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+{
+       struct at91_udc *udc = controller;
+
+       if (!driver || !driver->unbind || !driver->disconnect) {
+               error("bad paramter\n");
+               return -EINVAL;
+       }
+
+       driver->disconnect(&udc->gadget);
+       driver->unbind(&udc->gadget);
+       udc->driver = NULL;
+
+       at91_stop(&udc->gadget);
+
+       return 0;
+}
+
+int at91_udc_probe(struct at91_udc_data *pdata)
+{
+       struct at91_udc *udc;
+       int             retval;
+       struct at91_ep  *ep;
+       int             i;
+
+       udc = kzalloc(sizeof(*udc), GFP_KERNEL);
+       if (!udc)
+               return -ENOMEM;
+
+       controller = udc;
+       memcpy(&udc->board, pdata, sizeof(struct at91_udc_data));
+       if (udc->board.vbus_pin) {
+               printf("%s: gpio vbus pin not supported yet.\n", __func__);
+               return -ENXIO;
+       } else {
+               DBG("no VBUS detection, assuming always-on\n");
+               udc->vbus = 1;
+       }
+
+#if defined(CONFIG_AT91SAM9260) || defined(CONFIG_AT91SAM9G20)
+       udc->caps = &at91sam9260_udc_caps;
+#endif
+
+       udc->enabled = 0;
+       spin_lock_init(&udc->lock);
+
+       udc->gadget.ops = &at91_udc_ops;
+       udc->gadget.ep0 = &udc->ep[0].ep;
+       udc->gadget.name = driver_name;
+
+       for (i = 0; i < NUM_ENDPOINTS; i++) {
+               ep = &udc->ep[i];
+               ep->ep.name = ep_names[i];
+               ep->ep.ops = &at91_ep_ops;
+               ep->udc = udc;
+               ep->int_mask = (1 << i);
+               if (i != 0 && i != 3)
+                       ep->is_pingpong = 1;
+       }
+
+       udc->udp_baseaddr = (void *)udc->board.baseaddr;
+       if (IS_ERR(udc->udp_baseaddr))
+               return PTR_ERR(udc->udp_baseaddr);
+
+       if (udc->caps && udc->caps->init) {
+               retval = udc->caps->init(udc);
+               if (retval)
+                       return retval;
+       }
+
+       udc_reinit(udc);
+
+       at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
+       at91_udp_write(udc, AT91_UDP_IDR, 0xffffffff);
+       /* Clear all pending interrupts - UDP may be used by bootloader. */
+       at91_udp_write(udc, AT91_UDP_ICR, 0xffffffff);
+
+       INFO("%s version %s\n", driver_name, DRIVER_VERSION);
+       return 0;
+}
diff --git a/drivers/usb/gadget/at91_udc.h b/drivers/usb/gadget/at91_udc.h
new file mode 100644 (file)
index 0000000..3d8752e
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2004 by Thomas Rathbone, HP Labs
+ * Copyright (C) 2005 by Ivan Kokshaysky
+ * Copyright (C) 2006 by SAN People
+ *
+ * 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.
+ */
+
+#ifndef AT91_UDC_H
+#define AT91_UDC_H
+
+/*
+ * USB Device Port (UDP) registers.
+ * Based on AT91RM9200 datasheet revision E.
+ */
+
+#define AT91_UDP_FRM_NUM       0x00            /* Frame Number Register */
+#define     AT91_UDP_NUM       (0x7ff <<  0)   /* Frame Number */
+#define     AT91_UDP_FRM_ERR   (1     << 16)   /* Frame Error */
+#define     AT91_UDP_FRM_OK    (1     << 17)   /* Frame OK */
+
+#define AT91_UDP_GLB_STAT      0x04            /* Global State Register */
+#define     AT91_UDP_FADDEN    (1 <<  0)       /* Function Address Enable */
+#define     AT91_UDP_CONFG     (1 <<  1)       /* Configured */
+#define     AT91_UDP_ESR       (1 <<  2)       /* Enable Send Resume */
+#define     AT91_UDP_RSMINPR   (1 <<  3)       /* Resume has been sent */
+#define     AT91_UDP_RMWUPE    (1 <<  4)       /* Remote Wake Up Enable */
+
+#define AT91_UDP_FADDR         0x08            /* Function Address Register */
+#define     AT91_UDP_FADD      (0x7f << 0)     /* Function Address Value */
+#define     AT91_UDP_FEN       (1    << 8)     /* Function Enable */
+
+#define AT91_UDP_IER           0x10            /* Interrupt Enable Register */
+#define AT91_UDP_IDR           0x14            /* Interrupt Disable Register */
+#define AT91_UDP_IMR           0x18            /* Interrupt Mask Register */
+
+#define AT91_UDP_ISR           0x1c            /* Interrupt Status Register */
+#define     AT91_UDP_EP(n)     (1 << (n))      /* Endpoint Interrupt Status */
+#define     AT91_UDP_RXSUSP    (1 <<  8)       /* USB Suspend Interrupt Status */
+#define     AT91_UDP_RXRSM     (1 <<  9)       /* USB Resume Interrupt Status */
+#define     AT91_UDP_EXTRSM    (1 << 10)       /* External Resume Interrupt Status [AT91RM9200 only] */
+#define     AT91_UDP_SOFINT    (1 << 11)       /* Start of Frame Interrupt Status */
+#define     AT91_UDP_ENDBUSRES (1 << 12)       /* End of Bus Reset Interrupt Status */
+#define     AT91_UDP_WAKEUP    (1 << 13)       /* USB Wakeup Interrupt Status [AT91RM9200 only] */
+
+#define AT91_UDP_ICR           0x20            /* Interrupt Clear Register */
+#define AT91_UDP_RST_EP                0x28            /* Reset Endpoint Register */
+
+#define AT91_UDP_CSR(n)                (0x30+((n)*4))  /* Endpoint Control/Status Registers 0-7 */
+#define     AT91_UDP_TXCOMP    (1 <<  0)       /* Generates IN packet with data previously written in DPR */
+#define     AT91_UDP_RX_DATA_BK0 (1 <<  1)     /* Receive Data Bank 0 */
+#define     AT91_UDP_RXSETUP   (1 <<  2)       /* Send STALL to the host */
+#define     AT91_UDP_STALLSENT (1 <<  3)       /* Stall Sent / Isochronous error (Isochronous endpoints) */
+#define     AT91_UDP_TXPKTRDY  (1 <<  4)       /* Transmit Packet Ready */
+#define     AT91_UDP_FORCESTALL        (1 <<  5)       /* Force Stall */
+#define     AT91_UDP_RX_DATA_BK1 (1 <<  6)     /* Receive Data Bank 1 */
+#define     AT91_UDP_DIR       (1 <<  7)       /* Transfer Direction */
+#define     AT91_UDP_EPTYPE    (7 <<  8)       /* Endpoint Type */
+#define                AT91_UDP_EPTYPE_CTRL            (0 <<  8)
+#define                AT91_UDP_EPTYPE_ISO_OUT         (1 <<  8)
+#define                AT91_UDP_EPTYPE_BULK_OUT        (2 <<  8)
+#define                AT91_UDP_EPTYPE_INT_OUT         (3 <<  8)
+#define                AT91_UDP_EPTYPE_ISO_IN          (5 <<  8)
+#define                AT91_UDP_EPTYPE_BULK_IN         (6 <<  8)
+#define                AT91_UDP_EPTYPE_INT_IN          (7 <<  8)
+#define     AT91_UDP_DTGLE     (1 << 11)       /* Data Toggle */
+#define     AT91_UDP_EPEDS     (1 << 15)       /* Endpoint Enable/Disable */
+#define     AT91_UDP_RXBYTECNT (0x7ff << 16)   /* Number of bytes in FIFO */
+
+#define AT91_UDP_FDR(n)                (0x50+((n)*4))  /* Endpoint FIFO Data Registers 0-7 */
+
+#define AT91_UDP_TXVC          0x74            /* Transceiver Control Register */
+#define     AT91_UDP_TXVC_TXVDIS (1 << 8)      /* Transceiver Disable */
+#define     AT91_UDP_TXVC_PUON   (1 << 9)      /* PullUp On [AT91SAM9260 only] */
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * controller driver data structures
+ */
+
+#define        NUM_ENDPOINTS   6
+
+/*
+ * hardware won't disable bus reset, or resume while the controller
+ * is suspended ... watching suspend helps keep the logic symmetric.
+ */
+#define        MINIMUS_INTERRUPTUS \
+       (AT91_UDP_ENDBUSRES | AT91_UDP_RXRSM | AT91_UDP_RXSUSP)
+
+struct at91_ep {
+       struct usb_ep                   ep;
+       struct list_head                queue;
+       struct at91_udc                 *udc;
+       void __iomem                    *creg;
+
+       unsigned                        maxpacket:16;
+       u8                              int_mask;
+       unsigned                        is_pingpong:1;
+
+       unsigned                        stopped:1;
+       unsigned                        is_in:1;
+       unsigned                        is_iso:1;
+       unsigned                        fifo_bank:1;
+};
+
+struct at91_udc_caps {
+       int (*init)(struct at91_udc *udc);
+       void (*pullup)(struct at91_udc *udc, int is_on);
+};
+
+/*
+ * driver is non-SMP, and just blocks IRQs whenever it needs
+ * access protection for chip registers or driver state
+ */
+struct at91_udc {
+       struct usb_gadget               gadget;
+       struct at91_ep                  ep[NUM_ENDPOINTS];
+       struct usb_gadget_driver        *driver;
+       const struct at91_udc_caps      *caps;
+       unsigned                        vbus:1;
+       unsigned                        enabled:1;
+       unsigned                        clocked:1;
+       unsigned                        suspended:1;
+       unsigned                        req_pending:1;
+       unsigned                        wait_for_addr_ack:1;
+       unsigned                        wait_for_config_ack:1;
+       unsigned                        selfpowered:1;
+       unsigned                        active_suspend:1;
+       u8                              addr;
+       struct at91_udc_data            board;
+       void __iomem                    *udp_baseaddr;
+       int                             udp_irq;
+       spinlock_t                      lock;
+       struct at91_matrix              *matrix;
+};
+
+static inline struct at91_udc *to_udc(struct usb_gadget *g)
+{
+       return container_of(g, struct at91_udc, gadget);
+}
+
+struct at91_request {
+       struct usb_request              req;
+       struct list_head                queue;
+};
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef VERBOSE_DEBUG
+#    define VDBG               DBG
+#else
+#    define VDBG(stuff...)     do{}while(0)
+#endif
+
+#ifdef PACKET_TRACE
+#    define PACKET             VDBG
+#else
+#    define PACKET(stuff...)   do{}while(0)
+#endif
+
+#define ERR(stuff...)          debug("udc: " stuff)
+#define WARNING(stuff...)      debug("udc: " stuff)
+#define INFO(stuff...)         debug("udc: " stuff)
+#define DBG(stuff...)          debug("udc: " stuff)
+
+#endif
+
index de5f12ebb05a0c2b3b64b9a155ae63157d4150c4..3d6b0ae0c32dae4726e235be71e11bd48216ce8e 100644 (file)
 
 #define CONFIG_SYS_CBSIZE              256
 #define CONFIG_SYS_MAXARGS             16
-#define CONFIG_SYS_PBSIZE              (CONFIG_SYS_CBSIZE + \
-                                       sizeof(CONFIG_SYS_PROMPT) + 16)
 #define CONFIG_SYS_LONGHELP
 #define CONFIG_CMDLINE_EDITING
 #define CONFIG_AUTO_COMPLETE
index 459b8f97e0b80eaae4870f55dff8a01deee10b4f..619f5dab177bdf569c849cde293a6c8db5f21d50 100644 (file)
 
 #define CONFIG_SYS_CBSIZE              256
 #define CONFIG_SYS_MAXARGS             16
-#define CONFIG_SYS_PBSIZE              (CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16)
 #define CONFIG_SYS_LONGHELP            1
 #define CONFIG_CMDLINE_EDITING 1
 #define CONFIG_AUTO_COMPLETE
index 9c595f28674133d705fbdb68070aef12dac624f5..4d260e9fa8972aad2c510d7bf6229751f93c8d4d 100644 (file)
 
 #define CONFIG_SYS_CBSIZE              256
 #define CONFIG_SYS_MAXARGS             16
-#define CONFIG_SYS_PBSIZE              (CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16)
 #define CONFIG_SYS_LONGHELP
 #define CONFIG_CMDLINE_EDITING
 #define CONFIG_AUTO_COMPLETE
index 3eb0154c06cc22f1e64c02ca130e67673e20c5b7..2f251db1aebeb446c4d751b48474ec246acb777b 100644 (file)
 
 #define CONFIG_SYS_CBSIZE              256
 #define CONFIG_SYS_MAXARGS             16
-#define CONFIG_SYS_PBSIZE              (CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16)
 #define CONFIG_SYS_LONGHELP            1
 #define CONFIG_CMDLINE_EDITING         1
 #define CONFIG_AUTO_COMPLETE
index 2f6a3a57b49bb5b24a2806c45a99e960c4db53a5..70eaf1d6024589787523734c5788595c20f4b157 100644 (file)
 
 #define CONFIG_SYS_CBSIZE              256
 #define CONFIG_SYS_MAXARGS             16
-#define CONFIG_SYS_PBSIZE              (CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16)
 #define CONFIG_SYS_LONGHELP
 #define CONFIG_CMDLINE_EDITING
 #define CONFIG_AUTO_COMPLETE
index acdd63e758f7df743d9905fac0e927ebc1da8157..44f821be05ba3c708cd7338d85850fd63ae10ae6 100644 (file)
 
 #define CONFIG_SYS_CBSIZE      256
 #define CONFIG_SYS_MAXARGS     16
-#define CONFIG_SYS_PBSIZE      (CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) \
-                                       + 16)
 #define CONFIG_SYS_LONGHELP
 #define CONFIG_CMDLINE_EDITING
 #define CONFIG_AUTO_COMPLETE
index f7a174edbf3b2b1f2d4cb17c1a60a83e1e96e241..cba927acb40e0175b223b2e43fde496fcac79c0d 100644 (file)
 
 #define CONFIG_SYS_CBSIZE              256
 #define CONFIG_SYS_MAXARGS             16
-#define CONFIG_SYS_PBSIZE              (CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16)
 #define CONFIG_SYS_LONGHELP            1
 #define CONFIG_CMDLINE_EDITING         1
 #define CONFIG_AUTO_COMPLETE
index fbb584d9bf3c047dbfc566cd0cc734902257dc4d..2068e0de04abb4181d9dc1ba521c2defda2166d9 100644 (file)
 
 #define CONFIG_SYS_CBSIZE      256
 #define CONFIG_SYS_MAXARGS     16
-#define CONFIG_SYS_PBSIZE      (CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) \
-                                       + 16)
 #define CONFIG_SYS_LONGHELP
 #define CONFIG_CMDLINE_EDITING
 #define CONFIG_AUTO_COMPLETE
index 00fe26da2965ed48feb9e2b32d7305968084d6b5..dc732b810f9c29a3d47c97a5a2a5ab657186d1d0 100644 (file)
@@ -14,4 +14,6 @@
 /* Avoid a warning in the Realtek Ethernet driver */
 #define CONFIG_SYS_CACHELINE_SIZE 16
 
+#define CONFIG_VGA_AS_SINGLE_DEVICE
+
 #endif /* __CONFIG_H */
index c91e289da8d9b2893bfc7e4ce238e7a100413f33..68056125e9a8649fe399f4dd67edc637ce2503e3 100644 (file)
@@ -15,6 +15,7 @@
 #define __CONFIG_H
 
 #include <asm/hardware.h>
+#include <linux/sizes.h>
 
 #define CONFIG_SYS_GENERIC_BOARD
 /*
@@ -81,7 +82,7 @@
 #define CONFIG_SYS_SDRAM_SIZE          0x08000000
 
 #define CONFIG_SYS_INIT_SP_ADDR \
-       (CONFIG_SYS_SDRAM_BASE + 4 * 1024 - GENERATED_GBL_DATA_SIZE)
+       (CONFIG_SYS_SDRAM_BASE + SZ_4K - GENERATED_GBL_DATA_SIZE)
 
 /* No NOR flash */
 #define CONFIG_SYS_NO_FLASH
 #define CONFIG_DOS_PARTITION
 #define CONFIG_USB_STORAGE
 
-#define CONFIG_SYS_LOAD_ADDR           0x72000000      /* load address */
+/* USB DFU support */
+#define CONFIG_CMD_MTDPARTS
+#define CONFIG_MTD_DEVICE
+#define CONFIG_MTD_PARTITIONS
+
+#define CONFIG_USB_GADGET
+#define CONFIG_USB_GADGET_DUALSPEED
+#define CONFIG_USB_GADGET_ATMEL_USBA
+
+/* DFU class support */
+#define CONFIG_CMD_DFU
+#define CONFIG_USB_FUNCTION_DFU
+#define CONFIG_DFU_NAND
+#define CONFIG_USB_GADGET_DOWNLOAD
+#define CONFIG_USB_GADGET_VBUS_DRAW    2
+#define CONFIG_SYS_DFU_DATA_BUF_SIZE   (SZ_1M)
+#define DFU_MANIFEST_POLL_TIMEOUT      25000
+
+/* USB DFU IDs */
+#define CONFIG_G_DNL_VENDOR_NUM 0x0908
+#define CONFIG_G_DNL_PRODUCT_NUM 0x02d2
+#define CONFIG_G_DNL_MANUFACTURER "Siemens AG"
+
+#define CONFIG_SYS_CACHELINE_SIZE      SZ_8K
+#define CONFIG_SYS_LOAD_ADDR   ATMEL_BASE_CS6
 
 /* bootstrap + u-boot + env in nandflash */
 #define CONFIG_ENV_IS_IN_NAND
 #define CONFIG_ENV_OFFSET              0x100000
 #define CONFIG_ENV_OFFSET_REDUND       0x180000
-#define CONFIG_ENV_SIZE                        0x20000
+#define CONFIG_ENV_SIZE                        SZ_128K
 
 #define CONFIG_BOOTCOMMAND                                             \
        "nand read 0x70000000 0x200000 0x300000;"                       \
  * Size of malloc() pool
  */
 #define CONFIG_SYS_MALLOC_LEN  ROUND(3 * CONFIG_ENV_SIZE + \
-                               128*1024, 0x1000)
+                               SZ_4M, 0x1000)
+
 /* Defines for SPL */
 #define CONFIG_SPL_FRAMEWORK
 #define CONFIG_SPL_TEXT_BASE           0x300000
-#define CONFIG_SPL_MAX_SIZE            (12 * 1024)
-#define CONFIG_SPL_STACK               (16 * 1024)
+#define CONFIG_SPL_MAX_SIZE            (12 * SZ_1K)
+#define CONFIG_SPL_STACK               (SZ_16K)
 
 #define CONFIG_SPL_BSS_START_ADDR      CONFIG_SPL_MAX_SIZE
-#define CONFIG_SPL_BSS_MAX_SIZE                (2 * 1024)
+#define CONFIG_SPL_BSS_MAX_SIZE                (SZ_2K)
 
 #define CONFIG_SPL_LIBCOMMON_SUPPORT
 #define CONFIG_SPL_LIBGENERIC_SUPPORT
 #define CONFIG_SYS_NAND_U_BOOT_DST     CONFIG_SYS_TEXT_BASE
 #define CONFIG_SYS_NAND_5_ADDR_CYCLE
 
-#define CONFIG_SYS_NAND_PAGE_SIZE      2048
-#define CONFIG_SYS_NAND_BLOCK_SIZE     (128*1024)
+#define CONFIG_SYS_NAND_PAGE_SIZE      SZ_2K
+#define CONFIG_SYS_NAND_BLOCK_SIZE     (SZ_128K)
 #define CONFIG_SYS_NAND_PAGE_COUNT     (CONFIG_SYS_NAND_BLOCK_SIZE / \
                                         CONFIG_SYS_NAND_PAGE_SIZE)
 #define CONFIG_SYS_NAND_BAD_BLOCK_POS  NAND_LARGE_BADBLOCK_POS
index 998da78842bf15cde6fbbf539ebf13f056597019..3153a74d3b819ca468e8c802692d7f965aea0963 100644 (file)
 #define CONFIG_MMC_SDMA
 #define CONFIG_CMD_MMC
 
-/* Topcliff Gigabit Ethernet */
-#define CONFIG_PCH_GBE
-#define CONFIG_PHYLIB
-
 /* Environment configuration */
 #define CONFIG_ENV_SECT_SIZE           0x1000
 #define CONFIG_ENV_OFFSET              0
index 3c3c6e9d543e11d1244bd72901d9de598bfe52a9..b7ec2792bbe736fa38f049a261bbfc5054ba8128 100644 (file)
 /* ns16550 UART is memory-mapped in Quark SoC */
 #undef  CONFIG_SYS_NS16550_PORT_MAPPED
 
-#define CONFIG_PCI_MEM_BUS             0x90000000
-#define CONFIG_PCI_MEM_PHYS            CONFIG_PCI_MEM_BUS
-#define CONFIG_PCI_MEM_SIZE            0x20000000
-
-#define CONFIG_PCI_PREF_BUS            0xb0000000
-#define CONFIG_PCI_PREF_PHYS           CONFIG_PCI_PREF_BUS
-#define CONFIG_PCI_PREF_SIZE           0x20000000
-
-#define CONFIG_PCI_IO_BUS              0x2000
-#define CONFIG_PCI_IO_PHYS             CONFIG_PCI_IO_BUS
-#define CONFIG_PCI_IO_SIZE             0xe000
-
 #define CONFIG_SYS_EARLY_PCI_INIT
 #define CONFIG_PCI_PNP
 
index e5bb87302c7b82649d1c96b5bd146ec85833b972..ab6c910dee6604478aec664ef52f975f03562bfc 100644 (file)
@@ -56,6 +56,8 @@
 #define CONFIG_DISPLAY_CPUINFO                 /* display cpu info and speed */
 #define CONFIG_PREBOOT                         /* enable preboot variable */
 
+#define CONFIG_SYS_GENERIC_BOARD
+
 /*
  * Hardware drivers
  */
index 6965d921d9ea3eb1792bfc5a8b928ef533af8610..32e3a9ba559476b5e1bf8f482c9ae0360aaf0182 100644 (file)
 
 #define SANDBOX_ETH_SETTINGS           "ethaddr=00:00:11:22:33:44\0" \
                                        "eth1addr=00:00:11:22:33:45\0" \
-                                       "eth5addr=00:00:11:22:33:46\0" \
+                                       "eth3addr=00:00:11:22:33:46\0" \
+                                       "eth5addr=00:00:11:22:33:47\0" \
                                        "ipaddr=1.2.3.4\0"
 
 #define MEM_LAYOUT_ENV_SETTINGS \
index d696d4becec82dd54eab0213741eaa198ea8615a..d189c3fde97ce1f789023c861517b9d37bd7a98e 100644 (file)
@@ -28,6 +28,7 @@
  * In this case SoC is defined in boards.cfg.
  */
 #include <asm/hardware.h>
+#include <linux/sizes.h>
 
 /*
  * Warning: changing CONFIG_SYS_TEXT_BASE requires adapting the initial boot
@@ -64,7 +65,7 @@
  */
 #define CONFIG_NR_DRAM_BANKS           1
 #define CONFIG_SYS_SDRAM_BASE          ATMEL_BASE_CS1
-#define CONFIG_SYS_SDRAM_SIZE          (64 << 20)
+#define CONFIG_SYS_SDRAM_SIZE          (64 * SZ_1M)
 
 /*
  * Perform a SDRAM Memtest from the start of SDRAM
@@ -75,7 +76,7 @@
 
 /* Size of malloc() pool */
 #define CONFIG_SYS_MALLOC_LEN \
-       ROUND(3 * CONFIG_ENV_SIZE + (128 << 10), 0x1000)
+       ROUND(3 * CONFIG_ENV_SIZE + (4 * SZ_1M), 0x1000)
 
 /* NAND flash settings */
 #define CONFIG_NAND_ATMEL
 
 #if !defined(CONFIG_SPL_BUILD)
 /* USB configuration */
+#define CONFIG_CMD_USB
 #define CONFIG_USB_ATMEL
 #define CONFIG_USB_ATMEL_CLK_SEL_PLLB
 #define CONFIG_USB_OHCI_NEW
-#define CONFIG_USB_STORAGE
-#define CONFIG_DOS_PARTITION
 #define CONFIG_SYS_USB_OHCI_CPU_INIT
 #define CONFIG_SYS_USB_OHCI_REGS_BASE  ATMEL_UHP_BASE
 #define CONFIG_SYS_USB_OHCI_SLOT_NAME  "at91sam9260"
 #define CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS     2
+
+#define CONFIG_USB_HOST_ETHER
+#define CONFIG_USB_ETHER_ASIX
+#define CONFIG_USB_ETHER_MCS7830
+
+/* USB DFU support */
+#define CONFIG_CMD_MTDPARTS
+#define CONFIG_MTD_DEVICE
+#define CONFIG_MTD_PARTITIONS
+
+#define CONFIG_USB_GADGET
+#define CONFIG_USB_GADGET_AT91
+
+/* DFU class support */
+#define CONFIG_CMD_DFU
+#define CONFIG_USB_FUNCTION_DFU
+#define CONFIG_DFU_NAND
+#define CONFIG_USB_GADGET_DOWNLOAD
+#define CONFIG_USB_GADGET_VBUS_DRAW    2
+#define CONFIG_SYS_DFU_DATA_BUF_SIZE   SZ_1M
+#define DFU_MANIFEST_POLL_TIMEOUT      25000
+
+/* USB DFU IDs */
+#define CONFIG_G_DNL_VENDOR_NUM 0x0908
+#define CONFIG_G_DNL_PRODUCT_NUM 0x02d2
+#define CONFIG_G_DNL_MANUFACTURER "Siemens AG"
+
+#define CONFIG_SYS_CACHELINE_SIZE      0x2000
 #endif
 
 /* General Boot Parameter */
 #define CONFIG_ENV_IS_IN_NAND
 #define CONFIG_ENV_OFFSET              (0x100000)
 #define CONFIG_ENV_OFFSET_REDUND       (0x180000)
-#define CONFIG_ENV_RANGE               (0x80000)
-#define CONFIG_ENV_SIZE                        (0x20000)
+#define CONFIG_ENV_RANGE               (SZ_512K)
+#define CONFIG_ENV_SIZE                        (SZ_128K)
 
 /*
  * Predefined environment variables.
 #undef CONFIG_CMD_LOADS
 
 #define CONFIG_CMD_NAND
-#define CONFIG_CMD_USB
 #define CONFIG_CMD_FAT
 
 #ifdef CONFIG_MACB
 /* Defines for SPL */
 #define CONFIG_SPL_FRAMEWORK
 #define CONFIG_SPL_TEXT_BASE           0x0
-#define CONFIG_SPL_MAX_SIZE            (4 * 1024)
+#define CONFIG_SPL_MAX_SIZE            (SZ_4K)
 
 #define CONFIG_SPL_BSS_START_ADDR      CONFIG_SYS_SDRAM_BASE
-#define CONFIG_SPL_BSS_MAX_SIZE                (16 * 1024)
+#define CONFIG_SPL_BSS_MAX_SIZE                (SZ_16K)
 #define CONFIG_SYS_SPL_MALLOC_START     (CONFIG_SPL_BSS_START_ADDR + \
                                        CONFIG_SPL_BSS_MAX_SIZE)
 #define CONFIG_SYS_SPL_MALLOC_SIZE      CONFIG_SYS_MALLOC_LEN
 #define CONFIG_SPL_NAND_RAW_ONLY
 #define CONFIG_SPL_NAND_SOFTECC
 #define CONFIG_SYS_NAND_U_BOOT_OFFS    0x20000
-#define CONFIG_SYS_NAND_U_BOOT_SIZE    0x80000
+#define CONFIG_SYS_NAND_U_BOOT_SIZE    SZ_512K
 #define        CONFIG_SYS_NAND_U_BOOT_START    CONFIG_SYS_TEXT_BASE
 #define CONFIG_SYS_NAND_U_BOOT_DST     CONFIG_SYS_TEXT_BASE
 #define CONFIG_SYS_NAND_5_ADDR_CYCLE
 
-#define CONFIG_SYS_NAND_SIZE           (256*1024*1024)
-#define CONFIG_SYS_NAND_PAGE_SIZE      2048
-#define CONFIG_SYS_NAND_BLOCK_SIZE     (128*1024)
+#define CONFIG_SYS_NAND_SIZE           (SZ_256M)
+#define CONFIG_SYS_NAND_PAGE_SIZE      SZ_2K
+#define CONFIG_SYS_NAND_BLOCK_SIZE     (SZ_128K)
 #define CONFIG_SYS_NAND_PAGE_COUNT     (CONFIG_SYS_NAND_BLOCK_SIZE / \
                                         CONFIG_SYS_NAND_PAGE_SIZE)
 #define CONFIG_SYS_NAND_BAD_BLOCK_POS  NAND_LARGE_BADBLOCK_POS
index 2c9f5da55ad4d9db88ee1ca6091e3ff6c5609e04..12994c8065985e4c8325d92fbad8461093f994ed 100644 (file)
@@ -20,6 +20,7 @@
  * In this case SoC is defined in boards.cfg.
  */
 #include <asm/hardware.h>
+#include <linux/sizes.h>
 
 #define CONFIG_SYS_GENERIC_BOARD
 
  */
 #define CONFIG_NR_DRAM_BANKS           1
 #define CONFIG_SYS_SDRAM_BASE          ATMEL_BASE_CS1
-#define CONFIG_SYS_SDRAM_SIZE          (128 * 1024 * 1024)
+#define CONFIG_SYS_SDRAM_SIZE          (128 * SZ_1M)
 
 /*
  * Initial stack pointer: 4k - GENERATED_GBL_DATA_SIZE in internal SRAM,
  * leaving the correct space for initial global data structure above
  * that address while providing maximum stack area below.
  */
-# define CONFIG_SYS_INIT_SP_ADDR \
+#define CONFIG_SYS_INIT_SP_ADDR \
        (ATMEL_BASE_SRAM1 + 0x1000 - GENERATED_GBL_DATA_SIZE)
 
 /* NAND flash */
 #define CONFIG_AT91_WANTS_COMMON_PHY
 
 #define CONFIG_AT91SAM9_WATCHDOG
+#define CONFIG_AT91_HW_WDT_TIMEOUT     15
 #if !defined(CONFIG_SPL_BUILD)
 /* Enable the watchdog */
 #define CONFIG_HW_WATCHDOG
 /* USB */
 #if defined(CONFIG_BOARD_TAURUS)
 #define CONFIG_USB_ATMEL
+#define CONFIG_USB_ATMEL_CLK_SEL_PLLB
 #define CONFIG_USB_OHCI_NEW
 #define CONFIG_SYS_USB_OHCI_CPU_INIT
 #define CONFIG_SYS_USB_OHCI_REGS_BASE          0x00500000
 #define CONFIG_SYS_USB_OHCI_SLOT_NAME          "at91sam9260"
 #define CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS     2
 #define CONFIG_USB_STORAGE
+
+/* USB DFU support */
+#define CONFIG_CMD_MTDPARTS
+#define CONFIG_MTD_DEVICE
+#define CONFIG_MTD_PARTITIONS
+
+#define CONFIG_USB_GADGET
+#define CONFIG_USB_GADGET_AT91
+
+/* DFU class support */
+#define CONFIG_CMD_USB
+#define CONFIG_CMD_DFU
+#define CONFIG_USB_FUNCTION_DFU
+#define CONFIG_DFU_NAND
+#define CONFIG_USB_GADGET_DOWNLOAD
+#define CONFIG_USB_GADGET_VBUS_DRAW    2
+#define CONFIG_SYS_DFU_DATA_BUF_SIZE   (SZ_1M)
+#define DFU_MANIFEST_POLL_TIMEOUT      25000
+
+/* USB DFU IDs */
+#define CONFIG_G_DNL_VENDOR_NUM 0x0908
+#define CONFIG_G_DNL_PRODUCT_NUM 0x02d2
+#define CONFIG_G_DNL_MANUFACTURER "Siemens AG"
+
+#define CONFIG_SYS_CACHELINE_SIZE      SZ_8K
 #endif
 
 /* SPI EEPROM */
 #define CONFIG_SYS_SPI_U_BOOT_OFFS     0x20000
 
 #define CONFIG_SF_DEFAULT_BUS 0
-#define CONFIG_SF_DEFAULT_SPEED 10000000
-#define CONFIG_SF_DEFAULT_MODE SPI_MODE_0
+#define CONFIG_SF_DEFAULT_SPEED 1000000
+#define CONFIG_SF_DEFAULT_MODE SPI_MODE_3
 #endif
 
 /* load address */
 #define CONFIG_ENV_IS_IN_NAND
 #define CONFIG_ENV_OFFSET              0x100000
 #define CONFIG_ENV_OFFSET_REDUND       0x180000
-#define CONFIG_ENV_SIZE                0x20000         /* 1 sector = 128 kB */
+#define CONFIG_ENV_SIZE                (SZ_128K)       /* 1 sector = 128 kB */
 #define CONFIG_BOOTCOMMAND     "nand read 0x22000000 0x200000 0x300000; bootm"
-#define CONFIG_BOOTARGS                                                        \
+
+#if defined(CONFIG_BOARD_TAURUS)
+#define        CONFIG_BOOTARGS_TAURUS                                          \
        "console=ttyS0,115200 earlyprintk "                             \
        "mtdparts=atmel_nand:256k(bootstrap)ro,512k(uboot)ro,"          \
        "256k(env),256k(env_redundant),256k(spare),"                    \
        "512k(dtb),6M(kernel)ro,-(rootfs) "                             \
        "root=/dev/mtdblock7 rw rootfstype=jffs2"
+#endif
+
+#if defined(CONFIG_BOARD_AXM)
+#define CONFIG_BOOTARGS_AXM                                            \
+       "\0"    \
+       "addip=setenv bootargs ${bootargs} ip=${ipaddr}:${serverip}:"   \
+       "${gatewayip}:${netmask}:${hostname}:${netdev}::off\0"          \
+       "addtest=setenv bootargs ${bootargs} loglevel=4 test\0"         \
+       "baudrate=115200\0"                                             \
+       "boot_file=setenv bootfile /${project_dir}/kernel/uImage\0"     \
+       "boot_retries=0\0"                                              \
+       "bootcmd=run flash_self\0"                                      \
+       "bootdelay=3\0"                                                 \
+       "ethact=macb0\0"                                                \
+       "flash_nfs=run nand_kernel;run nfsargs;run addip;upgrade_available;"\
+       "bootm ${kernel_ram};reset\0"                                   \
+       "flash_self=run nand_kernel;run setbootargs;upgrade_available;" \
+       "bootm ${kernel_ram};reset\0"                                   \
+       "flash_self_test=run nand_kernel;run setbootargs addtest; "     \
+       "upgrade_available;bootm ${kernel_ram};reset\0"                 \
+       "hostname=systemone\0"                                          \
+       "kernel_Off=0x00200000\0"                                       \
+       "kernel_Off_fallback=0x03800000\0"                              \
+       "kernel_ram=0x21500000\0"                                       \
+       "kernel_size=0x00400000\0"                                      \
+       "kernel_size_fallback=0x00400000\0"                             \
+       "loads_echo=1\0"                                                \
+       "nand_kernel=nand read.e ${kernel_ram} ${kernel_Off} "          \
+               "${kernel_size}\0"                                      \
+       "net_nfs=run boot_file;tftp ${kernel_ram} ${bootfile};"         \
+       "run nfsargs;run addip;upgrade_available;bootm "                \
+               "${kernel_ram};reset\0"                                 \
+       "netdev=eth0\0"                                                 \
+       "nfsargs=run root_path;setenv bootargs ${bootargs} "            \
+       "root=/dev/nfs rw nfsroot=${serverip}:${rootpath} "             \
+       "at91sam9_wdt.wdt_timeout=16\0"                                 \
+       "partitionset_active=A\0"                                       \
+       "preboot=echo;echo Type 'run flash_self' to use kernel and root "\
+       "filesystem on memory;echo Type 'run flash_nfs' to use kernel " \
+       "from memory and root filesystem over NFS;echo Type 'run net_nfs' "\
+       "to get Kernel over TFTP and mount root filesystem over NFS;echo\0"\
+       "project_dir=systemone\0"                                       \
+       "root_path=setenv rootpath /home/projects/${project_dir}/rootfs\0"\
+       "rootfs=/dev/mtdblock5\0"                                       \
+       "rootfs_fallback=/dev/mtdblock7\0"                              \
+       "setbootargs=setenv bootargs ${bootargs} console=ttyMTD,mtdoops "\
+               "root=${rootfs} rootfstype=jffs2 panic=7 "              \
+               "at91sam9_wdt.wdt_timeout=16\0"                         \
+       "stderr=serial\0"                                               \
+       "stdin=serial\0"                                                \
+       "stdout=serial\0"                                               \
+       "upgrade_available=0\0"
+#endif
+
+#if defined(CONFIG_BOARD_TAURUS)
+#define CONFIG_BOOTARGS                CONFIG_BOOTARGS_TAURUS
+#endif
+
+#if defined(CONFIG_BOARD_AXM)
+#define CONFIG_BOOTARGS                CONFIG_BOOTARGS_AXM
+#endif
 
 #define CONFIG_SYS_CBSIZE              256
 #define CONFIG_SYS_MAXARGS             16
  * Size of malloc() pool
  */
 #define CONFIG_SYS_MALLOC_LEN \
-       ROUND(3 * CONFIG_ENV_SIZE + 128*1024, 0x1000)
+       ROUND(3 * CONFIG_ENV_SIZE + SZ_4M, 0x1000)
 
 /* Defines for SPL */
 #define CONFIG_SPL_FRAMEWORK
 #define CONFIG_SPL_TEXT_BASE           0x0
-#define CONFIG_SPL_MAX_SIZE            (14 * 1024)
-#define CONFIG_SPL_STACK               (16 * 1024)
+#define CONFIG_SPL_MAX_SIZE            (31 * SZ_512)
+#define        CONFIG_SPL_STACK                (ATMEL_BASE_SRAM1 + SZ_16K)
 #define CONFIG_SYS_SPL_MALLOC_START     (CONFIG_SYS_TEXT_BASE - \
                                        CONFIG_SYS_MALLOC_LEN)
 #define CONFIG_SYS_SPL_MALLOC_SIZE      CONFIG_SYS_MALLOC_LEN
 
 #define CONFIG_SPL_BSS_START_ADDR      CONFIG_SPL_MAX_SIZE
-#define CONFIG_SPL_BSS_MAX_SIZE                (3 * 1024)
+#define CONFIG_SPL_BSS_MAX_SIZE                (3 * SZ_512)
 
 #define CONFIG_SPL_LIBCOMMON_SUPPORT
 #define CONFIG_SPL_LIBGENERIC_SUPPORT
 #define CONFIG_SPL_NAND_RAW_ONLY
 #define CONFIG_SPL_NAND_SOFTECC
 #define CONFIG_SYS_NAND_U_BOOT_OFFS    0x20000
-#define CONFIG_SYS_NAND_U_BOOT_SIZE    0x80000
+#define CONFIG_SYS_NAND_U_BOOT_SIZE    SZ_512K
 #define        CONFIG_SYS_NAND_U_BOOT_START    CONFIG_SYS_TEXT_BASE
 #define CONFIG_SYS_NAND_U_BOOT_DST     CONFIG_SYS_TEXT_BASE
 #define CONFIG_SYS_NAND_5_ADDR_CYCLE
 
-#define CONFIG_SYS_NAND_SIZE           (256*1024*1024)
-#define CONFIG_SYS_NAND_PAGE_SIZE      2048
-#define CONFIG_SYS_NAND_BLOCK_SIZE     (128*1024)
+#define CONFIG_SYS_NAND_SIZE           (256 * SZ_1M)
+#define CONFIG_SYS_NAND_PAGE_SIZE      SZ_2K
+#define CONFIG_SYS_NAND_BLOCK_SIZE     (SZ_128K)
 #define CONFIG_SYS_NAND_PAGE_COUNT     (CONFIG_SYS_NAND_BLOCK_SIZE / \
                                         CONFIG_SYS_NAND_PAGE_SIZE)
 #define CONFIG_SYS_NAND_BAD_BLOCK_POS  NAND_LARGE_BADBLOCK_POS
 #define CONFIG_SYS_MCKR                        0x1300
 #define CONFIG_SYS_MCKR_CSS            (0x02 | CONFIG_SYS_MCKR)
 #define CONFIG_SYS_AT91_PLLB           0x10193F05
+
 #endif
diff --git a/include/linux/usb/at91_udc.h b/include/linux/usb/at91_udc.h
new file mode 100644 (file)
index 0000000..cd0d00f
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Platform data definitions for Atmel USBA gadget driver
+ * pieces copied from linux:include/linux/platform_data/atmel.h
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+#ifndef __LINUX_USB_AT91_UDC_H__
+#define __LINUX_USB_AT91_UDC_H__
+
+struct at91_udc_data {
+       int     vbus_pin;               /* high == host powering us */
+       u8      vbus_active_low;        /* vbus polarity */
+       u8      vbus_polled;            /* Use polling, not interrupt */
+       int     pullup_pin;             /* active == D+ pulled up */
+       u8      pullup_active_low;      /* true == pullup_pin is active low */
+       unsigned long   baseaddr;
+};
+
+int at91_udc_probe(struct at91_udc_data *pdata);
+#endif /* __LINUX_USB_AT91_UDC_H__ */
index 662d1735db0808fb418adbc266524ac58b00f698..3d5a54f2abab06ce9dd46e717ebcd01b32cfc43a 100644 (file)
@@ -70,7 +70,6 @@ int natsemi_initialize(bd_t *bis);
 int ne2k_register(void);
 int npe_initialize(bd_t *bis);
 int ns8382x_initialize(bd_t *bis);
-int pch_gbe_register(bd_t *bis);
 int pcnet_initialize(bd_t *bis);
 int ppc_4xx_eth_initialize (bd_t *bis);
 int rtl8139_initialize(bd_t *bis);
@@ -123,9 +122,6 @@ static inline int pci_eth_init(bd_t *bis)
 #ifdef CONFIG_E1000
        num += e1000_initialize(bis);
 #endif
-#ifdef CONFIG_PCH_GBE
-       num += pch_gbe_register(bis);
-#endif
 #ifdef CONFIG_PCNET
        num += pcnet_initialize(bis);
 #endif
index d3ec8d64d596d3a8e51336617b8de0032c87812b..26520d303885ea1e77e396b7f175d13f0299417b 100644 (file)
--- a/net/eth.c
+++ b/net/eth.c
@@ -107,7 +107,9 @@ static void eth_common_init(void)
                if (cpu_eth_init(gd->bd) < 0)
                        printf("CPU Net Initialization Failed\n");
        } else {
+#ifndef CONFIG_DM_ETH
                printf("Net Initialization Skipped\n");
+#endif
        }
 }
 
@@ -193,10 +195,11 @@ struct udevice *eth_get_dev_by_name(const char *devname)
        const char *startp = NULL;
        struct udevice *it;
        struct uclass *uc;
+       int len = strlen("eth");
 
        /* Must be longer than 3 to be an alias */
-       if (strlen(devname) > strlen("eth")) {
-               startp = devname + strlen("eth");
+       if (!strncmp(devname, "eth", len) && strlen(devname) > len) {
+               startp = devname + len;
                seq = simple_strtoul(startp, &endp, 10);
        }
 
index 181f0f363e70d7ad45044910d1216def34e412a7..1a5113179ac54862b399593ff2419a6745d8ccf9 100644 (file)
 /* Well known TFTP port # */
 #define WELL_KNOWN_PORT        69
 /* Millisecs to timeout for lost pkt */
-#define TIMEOUT                100UL
+#define TIMEOUT                5000UL
 #ifndef        CONFIG_NET_RETRY_COUNT
 /* # of timeouts before giving up */
-# define TIMEOUT_COUNT 1000
+# define TIMEOUT_COUNT 10
 #else
 # define TIMEOUT_COUNT  (CONFIG_NET_RETRY_COUNT * 2)
 #endif
@@ -711,10 +711,10 @@ void tftp_start(enum proto_t protocol)
        if (ep != NULL)
                timeout_ms = simple_strtol(ep, NULL, 10);
 
-       if (timeout_ms < 10) {
-               printf("TFTP timeout (%ld ms) too low, set min = 10 ms\n",
+       if (timeout_ms < 1000) {
+               printf("TFTP timeout (%ld ms) too low, set min = 1000 ms\n",
                       timeout_ms);
-               timeout_ms = 10;
+               timeout_ms = 1000;
        }
 
        debug("TFTP blocksize = %i, timeout = %ld ms\n",
index 700abdddbdd72c953fd5e766818de202737d38db..fcfb3e1ece840a5ed896c10cbeddbce6d69139a9 100644 (file)
@@ -106,6 +106,11 @@ static int _dm_test_eth_rotate2(struct unit_test_state *uts)
        ut_assertok(net_loop(PING));
        ut_asserteq_str("eth@10004000", getenv("ethact"));
 
+       /* Make sure we can handle device name which is not eth# */
+       setenv("ethact", "sbe5");
+       ut_assertok(net_loop(PING));
+       ut_asserteq_str("sbe5", getenv("ethact"));
+
        return 0;
 }
 
index c7d3c869688dd7a99cd4f3893059205f94086272..141bf6469136aa7f5f18bb6e07701dfcfd5d135d 100644 (file)
@@ -103,6 +103,24 @@ CONFIG_FILENAMES = [
     'u-boot.cfg', 'u-boot-spl.cfg', 'u-boot-tpl.cfg'
 ]
 
+class Config:
+    """Holds information about configuration settings for a board."""
+    def __init__(self, target):
+        self.target = target
+        self.config = {}
+        for fname in CONFIG_FILENAMES:
+            self.config[fname] = {}
+
+    def Add(self, fname, key, value):
+        self.config[fname][key] = value
+
+    def __hash__(self):
+        val = 0
+        for fname in self.config:
+            for key, value in self.config[fname].iteritems():
+                print key, value
+                val = val ^ hash(key) & hash(value)
+        return val
 
 class Builder:
     """Class for building U-Boot for a particular commit.
@@ -659,7 +677,8 @@ class Builder:
                 List containing a summary of warning lines
                 Dict keyed by error line, containing a list of the Board
                     objects with that warning
-                Dictionary keyed by filename - e.g. '.config'. Each
+                Dictionary keyed by board.target. Each value is a dictionary:
+                    key: filename - e.g. '.config'
                     value is itself a dictionary:
                         key: config name
                         value: config value
@@ -678,8 +697,6 @@ class Builder:
         warn_lines_summary = []
         warn_lines_boards = {}
         config = {}
-        for fname in CONFIG_FILENAMES:
-            config[fname] = {}
 
         for board in boards_selected.itervalues():
             outcome = self.GetBuildOutcome(commit_upto, board.target,
@@ -709,11 +726,12 @@ class Builder:
                                     line, board)
                         last_was_warning = is_warning
                         last_func = None
+            tconfig = Config(board.target)
             for fname in CONFIG_FILENAMES:
-                config[fname] = {}
                 if outcome.config:
                     for key, value in outcome.config[fname].iteritems():
-                        config[fname][key] = value
+                        tconfig.Add(fname, key, value)
+            config[board.target] = tconfig
 
         return (board_dict, err_lines_summary, err_lines_boards,
                 warn_lines_summary, warn_lines_boards, config)
@@ -774,9 +792,7 @@ class Builder:
         self._base_warn_lines = []
         self._base_err_line_boards = {}
         self._base_warn_line_boards = {}
-        self._base_config = {}
-        for fname in CONFIG_FILENAMES:
-            self._base_config[fname] = {}
+        self._base_config = None
 
     def PrintFuncSizeDetail(self, fname, old, new):
         grow, shrink, add, remove, up, down = 0, 0, 0, 0, 0, 0
@@ -1051,12 +1067,14 @@ class Builder:
             out = ''
             for key in sorted(config.keys()):
                 out += '%s=%s ' % (key, config[key])
-            return '%5s %s: %s' % (delta, name, out)
+            return '%s %s: %s' % (delta, name, out)
 
-        def _ShowConfig(name, config_plus, config_minus, config_change):
-            """Show changes in configuration
+        def _AddConfig(lines, name, config_plus, config_minus, config_change):
+            """Add changes in configuration to a list
 
             Args:
+                lines: list to add to
+                name: config file name
                 config_plus: configurations added, dictionary
                     key: config name
                     value: config value
@@ -1068,14 +1086,24 @@ class Builder:
                     value: config value
             """
             if config_plus:
-                Print(_CalcConfig('+', name, config_plus),
-                      colour=self.col.GREEN)
+                lines.append(_CalcConfig('+', name, config_plus))
             if config_minus:
-                Print(_CalcConfig('-', name, config_minus),
-                      colour=self.col.RED)
+                lines.append(_CalcConfig('-', name, config_minus))
             if config_change:
-                Print(_CalcConfig('+/-', name, config_change),
-                      colour=self.col.YELLOW)
+                lines.append(_CalcConfig('c', name, config_change))
+
+        def _OutputConfigInfo(lines):
+            for line in lines:
+                if not line:
+                    continue
+                if line[0] == '+':
+                    col = self.col.GREEN
+                elif line[0] == '-':
+                    col = self.col.RED
+                elif line[0] == 'c':
+                    col = self.col.YELLOW
+                Print('   ' + line, newline=True, colour=col)
+
 
         better = []     # List of boards fixed since last commit
         worse = []      # List of new broken boards since last commit
@@ -1137,34 +1165,104 @@ class Builder:
             self.PrintSizeSummary(board_selected, board_dict, show_detail,
                                   show_bloat)
 
-        if show_config:
-            all_config_plus = {}
-            all_config_minus = {}
-            all_config_change = {}
-            for name in CONFIG_FILENAMES:
-                if not config[name]:
+        if show_config and self._base_config:
+            summary = {}
+            arch_config_plus = {}
+            arch_config_minus = {}
+            arch_config_change = {}
+            arch_list = []
+
+            for target in board_dict:
+                if target not in board_selected:
+                    continue
+                arch = board_selected[target].arch
+                if arch not in arch_list:
+                    arch_list.append(arch)
+
+            for arch in arch_list:
+                arch_config_plus[arch] = {}
+                arch_config_minus[arch] = {}
+                arch_config_change[arch] = {}
+                for name in CONFIG_FILENAMES:
+                    arch_config_plus[arch][name] = {}
+                    arch_config_minus[arch][name] = {}
+                    arch_config_change[arch][name] = {}
+
+            for target in board_dict:
+                if target not in board_selected:
                     continue
-                config_plus = {}
-                config_minus = {}
-                config_change = {}
-                base = self._base_config[name]
-                for key, value in config[name].iteritems():
-                    if key not in base:
-                        config_plus[key] = value
-                        all_config_plus[key] = value
-                for key, value in base.iteritems():
-                    if key not in config[name]:
-                        config_minus[key] = value
-                        all_config_minus[key] = value
-                for key, value in base.iteritems():
-                    new_value = base[key]
-                    if key in config[name] and value != new_value:
-                        desc = '%s -> %s' % (value, new_value)
-                        config_change[key] = desc
-                        all_config_change[key] = desc
-                _ShowConfig(name, config_plus, config_minus, config_change)
-            _ShowConfig('all', all_config_plus, all_config_minus,
-                        all_config_change)
+
+                arch = board_selected[target].arch
+
+                all_config_plus = {}
+                all_config_minus = {}
+                all_config_change = {}
+                tbase = self._base_config[target]
+                tconfig = config[target]
+                lines = []
+                for name in CONFIG_FILENAMES:
+                    if not tconfig.config[name]:
+                        continue
+                    config_plus = {}
+                    config_minus = {}
+                    config_change = {}
+                    base = tbase.config[name]
+                    for key, value in tconfig.config[name].iteritems():
+                        if key not in base:
+                            config_plus[key] = value
+                            all_config_plus[key] = value
+                    for key, value in base.iteritems():
+                        if key not in tconfig.config[name]:
+                            config_minus[key] = value
+                            all_config_minus[key] = value
+                    for key, value in base.iteritems():
+                        new_value = tconfig.config.get(key)
+                        if new_value and value != new_value:
+                            desc = '%s -> %s' % (value, new_value)
+                            config_change[key] = desc
+                            all_config_change[key] = desc
+
+                    arch_config_plus[arch][name].update(config_plus)
+                    arch_config_minus[arch][name].update(config_minus)
+                    arch_config_change[arch][name].update(config_change)
+
+                    _AddConfig(lines, name, config_plus, config_minus,
+                               config_change)
+                _AddConfig(lines, 'all', all_config_plus, all_config_minus,
+                           all_config_change)
+                summary[target] = '\n'.join(lines)
+
+            lines_by_target = {}
+            for target, lines in summary.iteritems():
+                if lines in lines_by_target:
+                    lines_by_target[lines].append(target)
+                else:
+                    lines_by_target[lines] = [target]
+
+            for arch in arch_list:
+                lines = []
+                all_plus = {}
+                all_minus = {}
+                all_change = {}
+                for name in CONFIG_FILENAMES:
+                    all_plus.update(arch_config_plus[arch][name])
+                    all_minus.update(arch_config_minus[arch][name])
+                    all_change.update(arch_config_change[arch][name])
+                    _AddConfig(lines, name, arch_config_plus[arch][name],
+                               arch_config_minus[arch][name],
+                               arch_config_change[arch][name])
+                _AddConfig(lines, 'all', all_plus, all_minus, all_change)
+                #arch_summary[target] = '\n'.join(lines)
+                if lines:
+                    Print('%s:' % arch)
+                    _OutputConfigInfo(lines)
+
+            for lines, targets in lines_by_target.iteritems():
+                if not lines:
+                    continue
+                Print('%s :' % ' '.join(sorted(targets)))
+                _OutputConfigInfo(lines.split('\n'))
+
 
         # Save our updated information for the next call to this function
         self._base_board_dict = board_dict
index 1f95203eea9ed12c88ccf7af5aee75c5eee1f098..48059c02b550ee8db3cbfc7c9702b152936a0d4e 100644 (file)
@@ -707,10 +707,12 @@ int inject_region(char *image, int size, int region_type, char *region_fname)
  *                     8MB ROM the start address is 0xfff80000.
  * @write_fname:       Filename to add to the image
  * @offset_uboot_top:  Offset of the top of U-Boot
+ * @offset_uboot_start:        Offset of the start of U-Boot
  * @return number of bytes written if OK, -ve on error
  */
 static int write_data(char *image, int size, unsigned int addr,
-                     const char *write_fname, int offset_uboot_top)
+                     const char *write_fname, int offset_uboot_top,
+                     int offset_uboot_start)
 {
        int write_fd, write_size;
        int offset;
@@ -720,13 +722,25 @@ static int write_data(char *image, int size, unsigned int addr,
                return write_fd;
 
        offset = (uint32_t)(addr + size);
-       if (offset_uboot_top && offset_uboot_top >= offset) {
-               fprintf(stderr, "U-Boot image overlaps with region '%s'\n",
-                       write_fname);
-               fprintf(stderr,
-                       "U-Boot finishes at offset %x, file starts at %x\n",
-                       offset_uboot_top, offset);
-               return -EXDEV;
+       if (offset_uboot_top) {
+               if (offset_uboot_start < offset &&
+                   offset_uboot_top >= offset) {
+                       fprintf(stderr, "U-Boot image overlaps with region '%s'\n",
+                               write_fname);
+                       fprintf(stderr,
+                               "U-Boot finishes at offset %x, file starts at %x\n",
+                               offset_uboot_top, offset);
+                       return -EXDEV;
+               }
+               if (offset_uboot_start > offset &&
+                   offset_uboot_start <= offset + write_size) {
+                       fprintf(stderr, "U-Boot image overlaps with region '%s'\n",
+                               write_fname);
+                       fprintf(stderr,
+                               "U-Boot starts at offset %x, file finishes at %x\n",
+                               offset_uboot_start, offset + write_size);
+                       return -EXDEV;
+               }
        }
        debug("Writing %s to offset %#x\n", write_fname, offset);
 
@@ -927,27 +941,36 @@ static int write_ucode(char *image, int size, struct input_file *fdt,
  */
 static int write_uboot(char *image, int size, struct input_file *uboot,
                       struct input_file *fdt, unsigned int ucode_ptr,
-                      int collate_ucode)
+                      int collate_ucode, int *offset_uboot_top,
+                      int *offset_uboot_start)
 {
-       const void *blob;
        int uboot_size, fdt_size;
+       int uboot_top;
 
-       uboot_size = write_data(image, size, uboot->addr, uboot->fname, 0);
+       uboot_size = write_data(image, size, uboot->addr, uboot->fname, 0, 0);
        if (uboot_size < 0)
                return uboot_size;
        fdt->addr = uboot->addr + uboot_size;
        debug("U-Boot size %#x, FDT at %#x\n", uboot_size, fdt->addr);
-       fdt_size = write_data(image, size, fdt->addr, fdt->fname, 0);
+       fdt_size = write_data(image, size, fdt->addr, fdt->fname, 0, 0);
        if (fdt_size < 0)
                return fdt_size;
-       blob = (void *)image + (uint32_t)(fdt->addr + size);
+
+       uboot_top = (uint32_t)(fdt->addr + size) + fdt_size;
 
        if (ucode_ptr) {
-               return write_ucode(image, size, fdt, fdt_size, ucode_ptr,
-                                  collate_ucode);
+               uboot_top = write_ucode(image, size, fdt, fdt_size, ucode_ptr,
+                                       collate_ucode);
+               if (uboot_top < 0)
+                       return uboot_top;
        }
 
-       return ((char *)blob + fdt_size) - image;
+       if (offset_uboot_top && offset_uboot_start) {
+               *offset_uboot_top = uboot_top;
+               *offset_uboot_start = (uint32_t)(uboot->addr + size);
+       }
+
+       return 0;
 }
 
 static void print_version(void)
@@ -1268,13 +1291,14 @@ int main(int argc, char *argv[])
        }
 
        if (mode_write_descriptor)
-               ret = write_data(image, size, -size, desc_fname, 0);
+               ret = write_data(image, size, -size, desc_fname, 0, 0);
 
        if (mode_inject)
                ret = inject_region(image, size, region_type, inject_fname);
 
        if (mode_write) {
                int offset_uboot_top = 0;
+               int offset_uboot_start = 0;
 
                for (wr_idx = 0; wr_idx < wr_num; wr_idx++) {
                        ifile = &input_file[wr_idx];
@@ -1282,11 +1306,13 @@ int main(int argc, char *argv[])
                                continue;
                        } else if (ifile->type == IF_uboot) {
                                ret = write_uboot(image, size, ifile, fdt,
-                                                 ucode_ptr, collate_ucode);
-                               offset_uboot_top = ret;
+                                                 ucode_ptr, collate_ucode,
+                                                 &offset_uboot_top,
+                                                 &offset_uboot_start);
                        } else {
                                ret = write_data(image, size, ifile->addr,
-                                        ifile->fname, offset_uboot_top);
+                                                ifile->fname, offset_uboot_top,
+                                                offset_uboot_start);
                        }
                        if (ret < 0)
                                break;
index 67b086bd69c57d458cb878f407aef278fa4df426..9e739d89b6ff7ac261d6bc96b6c66def4b7d2937 100644 (file)
@@ -264,7 +264,7 @@ def CreatePatches(start, count, series):
     """
     if series.get('version'):
         version = '%s ' % series['version']
-    cmd = ['git', 'format-patch', '-D', '-M', '--signoff']
+    cmd = ['git', 'format-patch', '-M', '--signoff']
     if series.get('cover'):
         cmd.append('--cover-letter')
     prefix = series.GetPatchPrefix()