summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/sandbox/dts/test.dts7
-rw-r--r--arch/x86/cpu/coreboot/coreboot.c6
-rw-r--r--arch/x86/cpu/quark/Makefile1
-rw-r--r--arch/x86/cpu/quark/msg_port.c44
-rw-r--r--arch/x86/cpu/quark/pci.c70
-rw-r--r--arch/x86/cpu/quark/quark.c139
-rw-r--r--arch/x86/dts/chromebox_panther.dts10
-rw-r--r--arch/x86/dts/galileo.dts8
-rw-r--r--arch/x86/include/asm/arch-quark/quark.h85
-rw-r--r--board/intel/bayleybay/bayleybay.c6
-rw-r--r--board/intel/crownbay/crownbay.c6
-rw-r--r--board/intel/galileo/galileo.c56
-rw-r--r--board/siemens/corvus/board.c23
-rw-r--r--board/siemens/smartweb/smartweb.c29
-rw-r--r--board/siemens/taurus/taurus.c229
-rw-r--r--configs/bayleybay_defconfig5
-rw-r--r--configs/coreboot-x86_defconfig5
-rw-r--r--configs/crownbay_defconfig5
-rw-r--r--configs/galileo_defconfig3
-rw-r--r--doc/README.x862
-rw-r--r--drivers/net/Kconfig13
-rw-r--r--drivers/net/designware.c8
-rw-r--r--drivers/net/pch_gbe.c133
-rw-r--r--drivers/net/pch_gbe.h2
-rw-r--r--drivers/pci/pci-uclass.c28
-rw-r--r--drivers/usb/gadget/Makefile1
-rw-r--r--drivers/usb/gadget/at91_udc.c1625
-rw-r--r--drivers/usb/gadget/at91_udc.h171
-rw-r--r--include/configs/at91-sama5_common.h2
-rw-r--r--include/configs/at91sam9260ek.h1
-rw-r--r--include/configs/at91sam9261ek.h1
-rw-r--r--include/configs/at91sam9263ek.h1
-rw-r--r--include/configs/at91sam9m10g45ek.h1
-rw-r--r--include/configs/at91sam9n12ek.h2
-rw-r--r--include/configs/at91sam9rlek.h1
-rw-r--r--include/configs/at91sam9x5ek.h2
-rw-r--r--include/configs/chromebox_panther.h2
-rw-r--r--include/configs/corvus.h44
-rw-r--r--include/configs/crownbay.h4
-rw-r--r--include/configs/galileo.h12
-rw-r--r--include/configs/meesc.h2
-rw-r--r--include/configs/sandbox.h3
-rw-r--r--include/configs/smartweb.h53
-rw-r--r--include/configs/taurus.h120
-rw-r--r--include/linux/usb/at91_udc.h20
-rw-r--r--include/netdev.h4
-rw-r--r--net/eth.c7
-rw-r--r--net/tftp.c10
-rw-r--r--test/dm/eth.c5
-rw-r--r--tools/buildman/builder.py186
-rw-r--r--tools/ifdtool.c66
-rw-r--r--tools/patman/gitutil.py2
52 files changed, 2905 insertions, 366 deletions
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index c948df8c86..f5217fb877 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -9,6 +9,7 @@
aliases {
console = &uart0;
eth0 = "/eth@10002000";
+ eth3 = &eth_3;
eth5 = &eth_5;
i2c0 = "/i2c@0";
pci0 = &pci;
@@ -121,6 +122,12 @@
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>;
diff --git a/arch/x86/cpu/coreboot/coreboot.c b/arch/x86/cpu/coreboot/coreboot.c
index 0e9f15fef6..845f86a176 100644
--- a/arch/x86/cpu/coreboot/coreboot.c
+++ b/arch/x86/cpu/coreboot/coreboot.c
@@ -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)
{
/*
diff --git a/arch/x86/cpu/quark/Makefile b/arch/x86/cpu/quark/Makefile
index e87b4248e6..8f1d018fb6 100644
--- a/arch/x86/cpu/quark/Makefile
+++ b/arch/x86/cpu/quark/Makefile
@@ -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
diff --git a/arch/x86/cpu/quark/msg_port.c b/arch/x86/cpu/quark/msg_port.c
index 31713e321f..cf828f21c0 100644
--- a/arch/x86/cpu/quark/msg_port.c
+++ b/arch/x86/cpu/quark/msg_port.c
@@ -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
index 354e15a990..0000000000
--- a/arch/x86/cpu/quark/pci.c
+++ /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;
-}
diff --git a/arch/x86/cpu/quark/quark.c b/arch/x86/cpu/quark/quark.c
index 12ac3761d2..637c370e81 100644
--- a/arch/x86/cpu/quark/quark.c
+++ b/arch/x86/cpu/quark/quark.c
@@ -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;
diff --git a/arch/x86/dts/chromebox_panther.dts b/arch/x86/dts/chromebox_panther.dts
index 36feb96a94..c60ab710d2 100644
--- a/arch/x86/dts/chromebox_panther.dts
+++ b/arch/x86/dts/chromebox_panther.dts
@@ -42,6 +42,16 @@
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>;
diff --git a/arch/x86/dts/galileo.dts b/arch/x86/dts/galileo.dts
index d77ff8ad55..f119bf7f42 100644
--- a/arch/x86/dts/galileo.dts
+++ b/arch/x86/dts/galileo.dts
@@ -54,8 +54,11 @@
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>;
diff --git a/arch/x86/include/asm/arch-quark/quark.h b/arch/x86/include/asm/arch-quark/quark.h
index c9979280b6..5d81976998 100644
--- a/arch/x86/include/asm/arch-quark/quark.h
+++ b/arch/x86/include/asm/arch-quark/quark.h
@@ -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 */
@@ -48,6 +50,28 @@
#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_ */
diff --git a/board/intel/bayleybay/bayleybay.c b/board/intel/bayleybay/bayleybay.c
index 78447965b9..ccbe860b14 100644
--- a/board/intel/bayleybay/bayleybay.c
+++ b/board/intel/bayleybay/bayleybay.c
@@ -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);
-}
diff --git a/board/intel/crownbay/crownbay.c b/board/intel/crownbay/crownbay.c
index d6de9fabc0..3a79e69112 100644
--- a/board/intel/crownbay/crownbay.c
+++ b/board/intel/crownbay/crownbay.c
@@ -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);
-}
diff --git a/board/intel/galileo/galileo.c b/board/intel/galileo/galileo.c
index 746ab277cb..c1087acb69 100644
--- a/board/intel/galileo/galileo.c
+++ b/board/intel/galileo/galileo.c
@@ -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;
diff --git a/board/siemens/corvus/board.c b/board/siemens/corvus/board.c
index 3294203b71..28985b8b08 100644
--- a/board/siemens/corvus/board.c
+++ b/board/siemens/corvus/board.c
@@ -29,6 +29,10 @@
#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 */
@@ -222,6 +239,10 @@ int board_init(void)
#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;
}
diff --git a/board/siemens/smartweb/smartweb.c b/board/siemens/smartweb/smartweb.c
index cf8a7f5b06..2d424882a9 100644
--- a/board/siemens/smartweb/smartweb.c
+++ b/board/siemens/smartweb/smartweb.c
@@ -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;
}
diff --git a/board/siemens/taurus/taurus.c b/board/siemens/taurus/taurus.c
index 013dac2e2f..72c5e6083d 100644
--- a/board/siemens/taurus/taurus.c
+++ b/board/siemens/taurus/taurus.c
@@ -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
diff --git a/configs/bayleybay_defconfig b/configs/bayleybay_defconfig
index 13bd282024..2ea30c8227 100644
--- a/configs/bayleybay_defconfig
+++ b/configs/bayleybay_defconfig
@@ -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
diff --git a/configs/coreboot-x86_defconfig b/configs/coreboot-x86_defconfig
index ebaf86bc7f..e95f96d779 100644
--- a/configs/coreboot-x86_defconfig
+++ b/configs/coreboot-x86_defconfig
@@ -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
diff --git a/configs/crownbay_defconfig b/configs/crownbay_defconfig
index 4fc1827482..f328159051 100644
--- a/configs/crownbay_defconfig
+++ b/configs/crownbay_defconfig
@@ -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
diff --git a/configs/galileo_defconfig b/configs/galileo_defconfig
index 6ef1090e1e..d05154ee0a 100644
--- a/configs/galileo_defconfig
+++ b/configs/galileo_defconfig
@@ -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
diff --git a/doc/README.x86 b/doc/README.x86
index 3bab5cf64e..5f9c46f05d 100644
--- a/doc/README.x86
+++ b/doc/README.x86
@@ -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
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 7367d9e5ac..bbec6a60e0 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -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
diff --git a/drivers/net/designware.c b/drivers/net/designware.c
index d9cb507695..ae78d21db6 100644
--- a/drivers/net/designware.c
+++ b/drivers/net/designware.c
@@ -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);
diff --git a/drivers/net/pch_gbe.c b/drivers/net/pch_gbe.c
index a03bdc0630..004fcf88c2 100644
--- a/drivers/net/pch_gbe.c
+++ b/drivers/net/pch_gbe.c
@@ -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);
diff --git a/drivers/net/pch_gbe.h b/drivers/net/pch_gbe.h
index 11329d4834..afcb03dd36 100644
--- a/drivers/net/pch_gbe.h
+++ b/drivers/net/pch_gbe.h
@@ -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;
};
diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c
index b25298fb5e..ea70853da2 100644
--- a/drivers/pci/pci-uclass.c
+++ b/drivers/pci/pci-uclass.c
@@ -20,16 +20,36 @@
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;
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 4c11a7e326..6288ecf09f 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -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
index 0000000000..4070803b65
--- /dev/null
+++ b/drivers/usb/gadget/at91_udc.c
@@ -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
index 0000000000..3d8752e106
--- /dev/null
+++ b/drivers/usb/gadget/at91_udc.h
@@ -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
+
diff --git a/include/configs/at91-sama5_common.h b/include/configs/at91-sama5_common.h
index de5f12ebb0..3d6b0ae0c3 100644
--- a/include/configs/at91-sama5_common.h
+++ b/include/configs/at91-sama5_common.h
@@ -105,8 +105,6 @@
#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
diff --git a/include/configs/at91sam9260ek.h b/include/configs/at91sam9260ek.h
index 459b8f97e0..619f5dab17 100644
--- a/include/configs/at91sam9260ek.h
+++ b/include/configs/at91sam9260ek.h
@@ -256,7 +256,6 @@
#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
diff --git a/include/configs/at91sam9261ek.h b/include/configs/at91sam9261ek.h
index 9c595f2867..4d260e9fa8 100644
--- a/include/configs/at91sam9261ek.h
+++ b/include/configs/at91sam9261ek.h
@@ -203,7 +203,6 @@
#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
diff --git a/include/configs/at91sam9263ek.h b/include/configs/at91sam9263ek.h
index 3eb0154c06..2f251db1ae 100644
--- a/include/configs/at91sam9263ek.h
+++ b/include/configs/at91sam9263ek.h
@@ -332,7 +332,6 @@
#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
diff --git a/include/configs/at91sam9m10g45ek.h b/include/configs/at91sam9m10g45ek.h
index 2f6a3a57b4..70eaf1d602 100644
--- a/include/configs/at91sam9m10g45ek.h
+++ b/include/configs/at91sam9m10g45ek.h
@@ -183,7 +183,6 @@
#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
diff --git a/include/configs/at91sam9n12ek.h b/include/configs/at91sam9n12ek.h
index acdd63e758..44f821be05 100644
--- a/include/configs/at91sam9n12ek.h
+++ b/include/configs/at91sam9n12ek.h
@@ -223,8 +223,6 @@
#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
diff --git a/include/configs/at91sam9rlek.h b/include/configs/at91sam9rlek.h
index f7a174edbf..cba927acb4 100644
--- a/include/configs/at91sam9rlek.h
+++ b/include/configs/at91sam9rlek.h
@@ -186,7 +186,6 @@
#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
diff --git a/include/configs/at91sam9x5ek.h b/include/configs/at91sam9x5ek.h
index fbb584d9bf..2068e0de04 100644
--- a/include/configs/at91sam9x5ek.h
+++ b/include/configs/at91sam9x5ek.h
@@ -225,8 +225,6 @@
#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
diff --git a/include/configs/chromebox_panther.h b/include/configs/chromebox_panther.h
index 00fe26da29..dc732b810f 100644
--- a/include/configs/chromebox_panther.h
+++ b/include/configs/chromebox_panther.h
@@ -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 */
diff --git a/include/configs/corvus.h b/include/configs/corvus.h
index c91e289da8..68056125e9 100644
--- a/include/configs/corvus.h
+++ b/include/configs/corvus.h
@@ -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
@@ -113,13 +114,37 @@
#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;" \
@@ -146,15 +171,16 @@
* 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
@@ -174,8 +200,8 @@
#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
diff --git a/include/configs/crownbay.h b/include/configs/crownbay.h
index 998da78842..3153a74d3b 100644
--- a/include/configs/crownbay.h
+++ b/include/configs/crownbay.h
@@ -49,10 +49,6 @@
#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
diff --git a/include/configs/galileo.h b/include/configs/galileo.h
index 3c3c6e9d54..b7ec2792bb 100644
--- a/include/configs/galileo.h
+++ b/include/configs/galileo.h
@@ -20,18 +20,6 @@
/* 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
diff --git a/include/configs/meesc.h b/include/configs/meesc.h
index e5bb87302c..ab6c910dee 100644
--- a/include/configs/meesc.h
+++ b/include/configs/meesc.h
@@ -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
*/
diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
index 6965d921d9..32e3a9ba55 100644
--- a/include/configs/sandbox.h
+++ b/include/configs/sandbox.h
@@ -187,7 +187,8 @@
#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 \
diff --git a/include/configs/smartweb.h b/include/configs/smartweb.h
index d696d4bece..d189c3fde9 100644
--- a/include/configs/smartweb.h
+++ b/include/configs/smartweb.h
@@ -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
@@ -140,15 +141,42 @@
#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 */
@@ -173,8 +201,8 @@
#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.
@@ -193,7 +221,6 @@
#undef CONFIG_CMD_LOADS
#define CONFIG_CMD_NAND
-#define CONFIG_CMD_USB
#define CONFIG_CMD_FAT
#ifdef CONFIG_MACB
@@ -230,10 +257,10 @@
/* 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
@@ -253,14 +280,14 @@
#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
diff --git a/include/configs/taurus.h b/include/configs/taurus.h
index 2c9f5da55a..12994c8065 100644
--- a/include/configs/taurus.h
+++ b/include/configs/taurus.h
@@ -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
@@ -80,14 +81,14 @@
*/
#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 */
@@ -111,6 +112,7 @@
#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
@@ -119,12 +121,38 @@
/* 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 */
@@ -145,8 +173,8 @@
#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 */
@@ -156,14 +184,77 @@
#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
@@ -177,19 +268,19 @@
* 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
@@ -206,14 +297,14 @@
#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
@@ -232,4 +323,5 @@
#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
index 0000000000..cd0d00f5a5
--- /dev/null
+++ b/include/linux/usb/at91_udc.h
@@ -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__ */
diff --git a/include/netdev.h b/include/netdev.h
index 662d1735db..3d5a54f2ab 100644
--- a/include/netdev.h
+++ b/include/netdev.h
@@ -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
diff --git a/net/eth.c b/net/eth.c
index d3ec8d64d5..26520d3038 100644
--- 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);
}
diff --git a/net/tftp.c b/net/tftp.c
index 181f0f363e..1a5113179a 100644
--- a/net/tftp.c
+++ b/net/tftp.c
@@ -19,10 +19,10 @@
/* 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",
diff --git a/test/dm/eth.c b/test/dm/eth.c
index 700abdddbd..fcfb3e1ece 100644
--- a/test/dm/eth.c
+++ b/test/dm/eth.c
@@ -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;
}
diff --git a/tools/buildman/builder.py b/tools/buildman/builder.py
index c7d3c86968..141bf64691 100644
--- a/tools/buildman/builder.py
+++ b/tools/buildman/builder.py
@@ -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
diff --git a/tools/ifdtool.c b/tools/ifdtool.c
index 1f95203eea..48059c02b5 100644
--- a/tools/ifdtool.c
+++ b/tools/ifdtool.c
@@ -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;
diff --git a/tools/patman/gitutil.py b/tools/patman/gitutil.py
index 67b086bd69..9e739d89b6 100644
--- a/tools/patman/gitutil.py
+++ b/tools/patman/gitutil.py
@@ -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()