summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorVicente <vicencb@gmail.com>2012-10-09 00:55:20 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2012-11-16 15:32:31 +0100
commit6b4dc4d4f128bd22df4d022ad37285ce4858e1e8 (patch)
treedd66fc53750274c211dd78994732701de9ad7608 /arch
parent7b8a200154be38bd54ce4fc291a5a7904e5d33f2 (diff)
downloadbarebox-6b4dc4d4f128bd22df4d022ad37285ce4858e1e8.tar.gz
barebox-6b4dc4d4f128bd22df4d022ad37285ce4858e1e8.tar.xz
omap4: add support for booting cpu from usb
Signed-off-by: Vicente <vicencb@gmail.com> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-omap/Kconfig9
-rw-r--r--arch/arm/mach-omap/Makefile1
-rw-r--r--arch/arm/mach-omap/include/mach/omap4_rom_usb.h141
-rw-r--r--arch/arm/mach-omap/omap4_generic.c23
-rw-r--r--arch/arm/mach-omap/omap4_rom_usb.c198
5 files changed, 365 insertions, 7 deletions
diff --git a/arch/arm/mach-omap/Kconfig b/arch/arm/mach-omap/Kconfig
index 3315d1c51d..7efd93d864 100644
--- a/arch/arm/mach-omap/Kconfig
+++ b/arch/arm/mach-omap/Kconfig
@@ -82,6 +82,15 @@ config ARCH_TEXT_BASE
default 0x80e80000 if MACH_OMAP343xSDP
default 0x80e80000 if MACH_BEAGLE
+config OMAP4_USBBOOT
+ bool "enable booting from USB"
+ default n
+ depends on ARCH_OMAP4 && !MMU
+ help
+ Say Y here if you want to be able to boot an OMAP4 cpu from USB.
+ You need the utility program omap4_usbboot to boot from USB.
+ Please read oamp4_usb_booting.txt for more information.
+
config BOARDINFO
default "Texas Instrument's SDP343x" if MACH_OMAP343xSDP
default "Texas Instrument's Beagle" if MACH_BEAGLE
diff --git a/arch/arm/mach-omap/Makefile b/arch/arm/mach-omap/Makefile
index 3a6d50cd81..2ac7fb28a0 100644
--- a/arch/arm/mach-omap/Makefile
+++ b/arch/arm/mach-omap/Makefile
@@ -27,4 +27,5 @@ pbl-$(CONFIG_OMAP3_CLOCK_CONFIG) += omap3_clock.o
obj-$(CONFIG_OMAP_GPMC) += gpmc.o devices-gpmc-nand.o
obj-$(CONFIG_SHELL_NONE) += xload.o
obj-$(CONFIG_I2C_TWL6030) += omap4_twl6030_mmc.o
+obj-$(CONFIG_OMAP4_USBBOOT) += omap4_rom_usb.o
obj-y += gpio.o
diff --git a/arch/arm/mach-omap/include/mach/omap4_rom_usb.h b/arch/arm/mach-omap/include/mach/omap4_rom_usb.h
new file mode 100644
index 0000000000..50c359f474
--- /dev/null
+++ b/arch/arm/mach-omap/include/mach/omap4_rom_usb.h
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _OMAP4_ROM_USB_H_
+#define _OMAP4_ROM_USB_H_
+
+/* public api */
+#define PUBLIC_API_BASE_4430 (0x28400)
+#define PUBLIC_API_BASE_4460 (0x30400)
+
+#define PUBLIC_GET_DRIVER_MEM_OFFSET (0x04)
+#define PUBLIC_GET_DRIVER_PER_OFFSET (0x08)
+#define PUBLIC_GET_DEVICE_MEM_OFFSET (0x80)
+#define PUBLIC_GET_DEVICE_PER_OFFSET (0x84)
+
+#define DEVICE_NULL 0x40
+#define DEVICE_UART1 0x41
+#define DEVICE_UART2 0x42
+#define DEVICE_UART3 0x43
+#define DEVICE_UART4 0x44
+#define DEVICE_USB 0x45
+#define DEVICE_USBEXT 0x46
+
+#define XFER_MODE_CPU 0
+#define XFER_MODE_DMA 1
+
+#define STATUS_OKAY 0
+#define STATUS_FAILED 1
+#define STATUS_TIMEOUT 2
+#define STATUS_BAD_PARAM 3
+#define STATUS_WAITING 4
+#define STATUS_NO_MEMORY 5
+#define STATUS_INVALID_PTR 6
+
+/* Memory ROM interface */
+struct read_desc {
+ u32 sector_start;
+ u32 sector_count;
+ void *destination;
+};
+
+struct mem_device {
+ u32 initialized;
+ u8 device_type;
+ u8 trials_count;
+ u32 xip_device;
+ u16 search_size;
+ u32 base_address;
+ u16 hs_toc_mask;
+ u16 gp_toc_mask;
+ void *device_data;
+ u16 *boot_options;
+};
+
+struct mem_driver {
+ int (*init)(struct mem_device *md);
+ int (*read)(struct mem_device *md, struct read_desc *rd);
+ int (*configure)(struct mem_device *md, void *config);
+};
+
+
+/* Peripheral ROM interface */
+struct per_handle {
+ void *set_to_null;
+ void (*callback)(struct per_handle *rh);
+ void *data;
+ u32 length;
+ u16 *options;
+ u32 xfer_mode;
+ u32 device_type;
+ u32 status;
+ u16 hs_toc_mask;
+ u16 gp_toc_mask;
+ u32 config_timeout;
+};
+
+struct per_driver {
+ int (*init)(struct per_handle *rh);
+ int (*read)(struct per_handle *rh);
+ int (*write)(struct per_handle *rh);
+ int (*close)(struct per_handle *rh);
+ int (*config)(struct per_handle *rh, void *x);
+};
+
+#define USB_SETCONFIGDESC_ATTRIBUTES (0)
+#define USB_SETCONFIGDESC_MAXPOWER (1)
+#define USB_SETSUSPEND_CALLBACK (2)
+struct per_usb_config {
+ u32 configid;
+ u32 value;
+};
+
+#define API(n) ((void *) (*((u32 *) (n))))
+/* ROM API End */
+
+struct omap4_usbboot {
+ struct per_handle dread;
+ struct per_handle dwrite;
+ struct per_driver *io;
+};
+
+void omap4_usbboot_close(void);
+
+void omap4_usbboot_queue_read(void *data, unsigned len);
+int omap4_usbboot_wait_read(void);
+int omap4_usbboot_is_read_waiting(void);
+int omap4_usbboot_is_read_ok(void);
+
+void omap4_usbboot_queue_write(void *data, unsigned len);
+int omap4_usbboot_wait_write(void);
+
+int omap4_usbboot_read(void *data, unsigned len);
+int omap4_usbboot_write(void *data, unsigned len);
+void omap4_usbboot_puts(const char *s);
+
+#endif
diff --git a/arch/arm/mach-omap/omap4_generic.c b/arch/arm/mach-omap/omap4_generic.c
index ea4af68f72..c75666483b 100644
--- a/arch/arm/mach-omap/omap4_generic.c
+++ b/arch/arm/mach-omap/omap4_generic.c
@@ -8,6 +8,7 @@
#include <mach/xload.h>
#include <mach/gpmc.h>
#include <mach/gpio.h>
+#include <mach/omap4_rom_usb.h>
/*
* The following several lines are taken from U-Boot to support
@@ -459,13 +460,21 @@ late_initcall(watchdog_init);
static int omap_vector_init(void)
{
- __asm__ __volatile__ (
- "mov r0, #0;"
- "mcr p15, #0, r0, c12, c0, #0;"
- :
- :
- : "r0"
- );
+ /*
+ * omap4 usbboot interfaces with the omap4 ROM to reuse the USB port
+ * used for booting.
+ * The ROM code uses interrupts for the transfers, so do not modify the
+ * interrupt vectors in this case.
+ */
+ if (omap4_bootsrc() != OMAP_BOOTSRC_USB1) {
+ __asm__ __volatile__ (
+ "mov r0, #0;"
+ "mcr p15, #0, r0, c12, c0, #0;"
+ :
+ :
+ : "r0"
+ );
+ }
return 0;
}
diff --git a/arch/arm/mach-omap/omap4_rom_usb.c b/arch/arm/mach-omap/omap4_rom_usb.c
new file mode 100644
index 0000000000..48d6433757
--- /dev/null
+++ b/arch/arm/mach-omap/omap4_rom_usb.c
@@ -0,0 +1,198 @@
+/*
+ * This code is based on:
+ * git://github.com/swetland/omap4boot.git
+ */
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <common.h>
+#include <mach/omap4-silicon.h>
+#include <mach/omap4_rom_usb.h>
+#include <mach/xload.h>
+#include <init.h>
+
+static struct omap4_usbboot omap4_usbboot_pdata;
+
+static int omap4_usbboot_open(void)
+{
+ int (*rom_get_per_driver)(struct per_driver **io, u32 device_type);
+ int (*rom_get_per_device)(struct per_handle **rh);
+ struct per_handle *boot;
+ int n;
+ u32 base;
+
+ if (omap4_revision() >= OMAP4460_ES1_0)
+ base = PUBLIC_API_BASE_4460;
+ else
+ base = PUBLIC_API_BASE_4430;
+
+ rom_get_per_driver = API(base + PUBLIC_GET_DRIVER_PER_OFFSET);
+ rom_get_per_device = API(base + PUBLIC_GET_DEVICE_PER_OFFSET);
+
+ n = rom_get_per_device(&boot);
+ if (n)
+ return n;
+
+ if ((boot->device_type != DEVICE_USB) &&
+ (boot->device_type != DEVICE_USBEXT))
+ return -1;
+
+ memset(&omap4_usbboot_pdata, 0, sizeof(omap4_usbboot_pdata));
+ n = rom_get_per_driver(&omap4_usbboot_pdata.io, boot->device_type);
+ if (n)
+ return n;
+
+ omap4_usbboot_pdata.dread.status = -1;
+ omap4_usbboot_pdata.dread.xfer_mode = boot->xfer_mode;
+ omap4_usbboot_pdata.dread.options = boot->options;
+ omap4_usbboot_pdata.dread.device_type = boot->device_type;
+
+ omap4_usbboot_pdata.dwrite.status = -1;
+ omap4_usbboot_pdata.dwrite.xfer_mode = boot->xfer_mode;
+ omap4_usbboot_pdata.dwrite.options = boot->options;
+ omap4_usbboot_pdata.dwrite.device_type = boot->device_type;
+ __asm__ __volatile__ ("cpsie i\n");
+ return 0;
+}
+
+
+static void rom_read_callback(struct per_handle *rh)
+{
+ omap4_usbboot_pdata.dread.status = rh->status;
+ return;
+}
+
+void omap4_usbboot_queue_read(void *data, unsigned len)
+{
+ int n;
+ omap4_usbboot_pdata.dread.data = data;
+ omap4_usbboot_pdata.dread.length = len;
+ omap4_usbboot_pdata.dread.status = STATUS_WAITING;
+ omap4_usbboot_pdata.dread.xfer_mode = 1;
+ omap4_usbboot_pdata.dread.callback = rom_read_callback;
+ n = omap4_usbboot_pdata.io->read(&omap4_usbboot_pdata.dread);
+ if (n)
+ omap4_usbboot_pdata.dread.status = n;
+}
+
+int omap4_usbboot_wait_read(void)
+{
+ int ret;
+ while (omap4_usbboot_pdata.dread.status == STATUS_WAITING)
+ /* cpu_relax(); */
+ barrier();
+ ret = omap4_usbboot_pdata.dread.status;
+ omap4_usbboot_pdata.dread.status = -1;
+ return ret;
+}
+int omap4_usbboot_is_read_waiting(void)
+{
+ barrier();
+ return omap4_usbboot_pdata.dread.status == STATUS_WAITING;
+}
+int omap4_usbboot_is_read_ok(void)
+{
+ barrier();
+ return omap4_usbboot_pdata.dread.status == STATUS_OKAY;
+}
+
+static void rom_write_callback(struct per_handle *rh)
+{
+ omap4_usbboot_pdata.dwrite.status = rh->status;
+ return;
+}
+
+void omap4_usbboot_queue_write(void *data, unsigned len)
+{
+ int n;
+ omap4_usbboot_pdata.dwrite.data = data;
+ omap4_usbboot_pdata.dwrite.length = len;
+ omap4_usbboot_pdata.dwrite.status = STATUS_WAITING;
+ omap4_usbboot_pdata.dwrite.xfer_mode = 1;
+ omap4_usbboot_pdata.dwrite.callback = rom_write_callback;
+ n = omap4_usbboot_pdata.io->write(&omap4_usbboot_pdata.dwrite);
+ if (n)
+ omap4_usbboot_pdata.dwrite.status = n;
+}
+
+int omap4_usbboot_wait_write(void)
+{
+ int ret;
+ while (omap4_usbboot_pdata.dwrite.status == STATUS_WAITING)
+ /* cpu_relax(); */
+ barrier();
+ ret = omap4_usbboot_pdata.dwrite.status;
+ omap4_usbboot_pdata.dwrite.status = -1;
+ return ret;
+}
+
+#define USB_MAX_IO 65536
+int omap4_usbboot_read(void *data, unsigned len)
+{
+ unsigned xfer;
+ unsigned char *x = data;
+ int n;
+ while (len > 0) {
+ xfer = (len > USB_MAX_IO) ? USB_MAX_IO : len;
+ omap4_usbboot_queue_read(x, xfer);
+ n = omap4_usbboot_wait_read();
+ if (n)
+ return n;
+ x += xfer;
+ len -= xfer;
+ }
+ return 0;
+}
+
+int omap4_usbboot_write(void *data, unsigned len)
+{
+ omap4_usbboot_queue_write(data, len);
+ return omap4_usbboot_wait_write();
+}
+
+void omap4_usbboot_close(void)
+{
+ omap4_usbboot_pdata.io->close(&omap4_usbboot_pdata.dread);
+}
+
+void omap4_usbboot_puts(const char *s)
+{
+ u32 c;
+ while ((c = *s++))
+ omap4_usbboot_write(&c, 4);
+}
+
+static int omap4_usbboot_init(void)
+{
+ if (omap4_bootsrc() == OMAP_BOOTSRC_USB1) {
+ omap4_usbboot_open();
+ omap4_usbboot_puts("USB communications initialized\n");
+ }
+ return 0;
+}
+core_initcall(omap4_usbboot_init);