From 4e76c0774a12873243b078a118d716928b884349 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Wed, 16 Aug 2017 11:00:50 -0700 Subject: imx: move imximage header to common location MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the imximage.h header file to a common location so we can make use of it from U-Boot too. Signed-off-by: Stefan Agner Reviewed-by: Łukasz Majewski diff --git a/include/imximage.h b/include/imximage.h new file mode 100644 index 0000000..de1ea8f --- /dev/null +++ b/include/imximage.h @@ -0,0 +1,200 @@ +/* + * (C) Copyright 2009 + * Stefano Babic, DENX Software Engineering, sbabic@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _IMXIMAGE_H_ +#define _IMXIMAGE_H_ + +#define MAX_HW_CFG_SIZE_V2 220 /* Max number of registers imx can set for v2 */ +#define MAX_PLUGIN_CODE_SIZE (64 * 1024) +#define MAX_HW_CFG_SIZE_V1 60 /* Max number of registers imx can set for v1 */ +#define APP_CODE_BARKER 0xB1 +#define DCD_BARKER 0xB17219E9 + +/* + * NOTE: This file must be kept in sync with arch/arm/include/asm/\ + * mach-imx/imximage.cfg because tools/imximage.c can not + * cross-include headers from arch/arm/ and vice-versa. + */ +#define CMD_DATA_STR "DATA" + +/* Initial Vector Table Offset */ +#define FLASH_OFFSET_UNDEFINED 0xFFFFFFFF +#define FLASH_OFFSET_STANDARD 0x400 +#define FLASH_OFFSET_NAND FLASH_OFFSET_STANDARD +#define FLASH_OFFSET_SD FLASH_OFFSET_STANDARD +#define FLASH_OFFSET_SPI FLASH_OFFSET_STANDARD +#define FLASH_OFFSET_ONENAND 0x100 +#define FLASH_OFFSET_NOR 0x1000 +#define FLASH_OFFSET_SATA FLASH_OFFSET_STANDARD +#define FLASH_OFFSET_QSPI 0x1000 + +/* Initial Load Region Size */ +#define FLASH_LOADSIZE_UNDEFINED 0xFFFFFFFF +#define FLASH_LOADSIZE_STANDARD 0x1000 +#define FLASH_LOADSIZE_NAND FLASH_LOADSIZE_STANDARD +#define FLASH_LOADSIZE_SD FLASH_LOADSIZE_STANDARD +#define FLASH_LOADSIZE_SPI FLASH_LOADSIZE_STANDARD +#define FLASH_LOADSIZE_ONENAND 0x400 +#define FLASH_LOADSIZE_NOR 0x0 /* entire image */ +#define FLASH_LOADSIZE_SATA FLASH_LOADSIZE_STANDARD +#define FLASH_LOADSIZE_QSPI 0x0 /* entire image */ + +/* Command tags and parameters */ +#define IVT_HEADER_TAG 0xD1 +#define IVT_VERSION 0x40 +#define DCD_HEADER_TAG 0xD2 +#define DCD_VERSION 0x40 +#define DCD_WRITE_DATA_COMMAND_TAG 0xCC +#define DCD_WRITE_DATA_PARAM 0x4 +#define DCD_WRITE_CLR_BIT_PARAM 0xC +#define DCD_WRITE_SET_BIT_PARAM 0x1C +#define DCD_CHECK_DATA_COMMAND_TAG 0xCF +#define DCD_CHECK_BITS_SET_PARAM 0x14 +#define DCD_CHECK_BITS_CLR_PARAM 0x04 + +enum imximage_cmd { + CMD_INVALID, + CMD_IMAGE_VERSION, + CMD_BOOT_FROM, + CMD_BOOT_OFFSET, + CMD_WRITE_DATA, + CMD_WRITE_CLR_BIT, + CMD_WRITE_SET_BIT, + CMD_CHECK_BITS_SET, + CMD_CHECK_BITS_CLR, + CMD_CSF, + CMD_PLUGIN, +}; + +enum imximage_fld_types { + CFG_INVALID = -1, + CFG_COMMAND, + CFG_REG_SIZE, + CFG_REG_ADDRESS, + CFG_REG_VALUE +}; + +enum imximage_version { + IMXIMAGE_VER_INVALID = -1, + IMXIMAGE_V1 = 1, + IMXIMAGE_V2 +}; + +typedef struct { + uint32_t type; /* Type of pointer (byte, halfword, word, wait/read) */ + uint32_t addr; /* Address to write to */ + uint32_t value; /* Data to write */ +} dcd_type_addr_data_t; + +typedef struct { + uint32_t barker; /* Barker for sanity check */ + uint32_t length; /* Device configuration length (without preamble) */ +} dcd_preamble_t; + +typedef struct { + dcd_preamble_t preamble; + dcd_type_addr_data_t addr_data[MAX_HW_CFG_SIZE_V1]; +} dcd_v1_t; + +typedef struct { + uint32_t app_code_jump_vector; + uint32_t app_code_barker; + uint32_t app_code_csf; + uint32_t dcd_ptr_ptr; + uint32_t super_root_key; + uint32_t dcd_ptr; + uint32_t app_dest_ptr; +} flash_header_v1_t; + +typedef struct { + uint32_t length; /* Length of data to be read from flash */ +} flash_cfg_parms_t; + +typedef struct { + flash_header_v1_t fhdr; + dcd_v1_t dcd_table; + flash_cfg_parms_t ext_header; +} imx_header_v1_t; + +typedef struct { + uint32_t addr; + uint32_t value; +} dcd_addr_data_t; + +typedef struct { + uint8_t tag; + uint16_t length; + uint8_t version; +} __attribute__((packed)) ivt_header_t; + +typedef struct { + uint8_t tag; + uint16_t length; + uint8_t param; +} __attribute__((packed)) write_dcd_command_t; + +struct dcd_v2_cmd { + write_dcd_command_t write_dcd_command; + dcd_addr_data_t addr_data[MAX_HW_CFG_SIZE_V2]; +}; + +typedef struct { + ivt_header_t header; + struct dcd_v2_cmd dcd_cmd; + uint32_t padding[1]; /* end up on an 8-byte boundary */ +} dcd_v2_t; + +typedef struct { + uint32_t start; + uint32_t size; + uint32_t plugin; +} boot_data_t; + +typedef struct { + ivt_header_t header; + uint32_t entry; + uint32_t reserved1; + uint32_t dcd_ptr; + uint32_t boot_data_ptr; + uint32_t self; + uint32_t csf; + uint32_t reserved2; +} flash_header_v2_t; + +typedef struct { + flash_header_v2_t fhdr; + boot_data_t boot_data; + union { + dcd_v2_t dcd_table; + char plugin_code[MAX_PLUGIN_CODE_SIZE]; + } data; +} imx_header_v2_t; + +/* The header must be aligned to 4k on MX53 for NAND boot */ +struct imx_header { + union { + imx_header_v1_t hdr_v1; + imx_header_v2_t hdr_v2; + } header; +}; + +typedef void (*set_dcd_val_t)(struct imx_header *imxhdr, + char *name, int lineno, + int fld, uint32_t value, + uint32_t off); + +typedef void (*set_dcd_param_t)(struct imx_header *imxhdr, uint32_t dcd_len, + int32_t cmd); + +typedef void (*set_dcd_rst_t)(struct imx_header *imxhdr, + uint32_t dcd_len, + char *name, int lineno); + +typedef void (*set_imx_hdr_t)(struct imx_header *imxhdr, uint32_t dcd_len, + uint32_t entry_point, uint32_t flash_offset); + +#endif /* _IMXIMAGE_H_ */ diff --git a/tools/imximage.h b/tools/imximage.h deleted file mode 100644 index de1ea8f..0000000 --- a/tools/imximage.h +++ /dev/null @@ -1,200 +0,0 @@ -/* - * (C) Copyright 2009 - * Stefano Babic, DENX Software Engineering, sbabic@denx.de. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifndef _IMXIMAGE_H_ -#define _IMXIMAGE_H_ - -#define MAX_HW_CFG_SIZE_V2 220 /* Max number of registers imx can set for v2 */ -#define MAX_PLUGIN_CODE_SIZE (64 * 1024) -#define MAX_HW_CFG_SIZE_V1 60 /* Max number of registers imx can set for v1 */ -#define APP_CODE_BARKER 0xB1 -#define DCD_BARKER 0xB17219E9 - -/* - * NOTE: This file must be kept in sync with arch/arm/include/asm/\ - * mach-imx/imximage.cfg because tools/imximage.c can not - * cross-include headers from arch/arm/ and vice-versa. - */ -#define CMD_DATA_STR "DATA" - -/* Initial Vector Table Offset */ -#define FLASH_OFFSET_UNDEFINED 0xFFFFFFFF -#define FLASH_OFFSET_STANDARD 0x400 -#define FLASH_OFFSET_NAND FLASH_OFFSET_STANDARD -#define FLASH_OFFSET_SD FLASH_OFFSET_STANDARD -#define FLASH_OFFSET_SPI FLASH_OFFSET_STANDARD -#define FLASH_OFFSET_ONENAND 0x100 -#define FLASH_OFFSET_NOR 0x1000 -#define FLASH_OFFSET_SATA FLASH_OFFSET_STANDARD -#define FLASH_OFFSET_QSPI 0x1000 - -/* Initial Load Region Size */ -#define FLASH_LOADSIZE_UNDEFINED 0xFFFFFFFF -#define FLASH_LOADSIZE_STANDARD 0x1000 -#define FLASH_LOADSIZE_NAND FLASH_LOADSIZE_STANDARD -#define FLASH_LOADSIZE_SD FLASH_LOADSIZE_STANDARD -#define FLASH_LOADSIZE_SPI FLASH_LOADSIZE_STANDARD -#define FLASH_LOADSIZE_ONENAND 0x400 -#define FLASH_LOADSIZE_NOR 0x0 /* entire image */ -#define FLASH_LOADSIZE_SATA FLASH_LOADSIZE_STANDARD -#define FLASH_LOADSIZE_QSPI 0x0 /* entire image */ - -/* Command tags and parameters */ -#define IVT_HEADER_TAG 0xD1 -#define IVT_VERSION 0x40 -#define DCD_HEADER_TAG 0xD2 -#define DCD_VERSION 0x40 -#define DCD_WRITE_DATA_COMMAND_TAG 0xCC -#define DCD_WRITE_DATA_PARAM 0x4 -#define DCD_WRITE_CLR_BIT_PARAM 0xC -#define DCD_WRITE_SET_BIT_PARAM 0x1C -#define DCD_CHECK_DATA_COMMAND_TAG 0xCF -#define DCD_CHECK_BITS_SET_PARAM 0x14 -#define DCD_CHECK_BITS_CLR_PARAM 0x04 - -enum imximage_cmd { - CMD_INVALID, - CMD_IMAGE_VERSION, - CMD_BOOT_FROM, - CMD_BOOT_OFFSET, - CMD_WRITE_DATA, - CMD_WRITE_CLR_BIT, - CMD_WRITE_SET_BIT, - CMD_CHECK_BITS_SET, - CMD_CHECK_BITS_CLR, - CMD_CSF, - CMD_PLUGIN, -}; - -enum imximage_fld_types { - CFG_INVALID = -1, - CFG_COMMAND, - CFG_REG_SIZE, - CFG_REG_ADDRESS, - CFG_REG_VALUE -}; - -enum imximage_version { - IMXIMAGE_VER_INVALID = -1, - IMXIMAGE_V1 = 1, - IMXIMAGE_V2 -}; - -typedef struct { - uint32_t type; /* Type of pointer (byte, halfword, word, wait/read) */ - uint32_t addr; /* Address to write to */ - uint32_t value; /* Data to write */ -} dcd_type_addr_data_t; - -typedef struct { - uint32_t barker; /* Barker for sanity check */ - uint32_t length; /* Device configuration length (without preamble) */ -} dcd_preamble_t; - -typedef struct { - dcd_preamble_t preamble; - dcd_type_addr_data_t addr_data[MAX_HW_CFG_SIZE_V1]; -} dcd_v1_t; - -typedef struct { - uint32_t app_code_jump_vector; - uint32_t app_code_barker; - uint32_t app_code_csf; - uint32_t dcd_ptr_ptr; - uint32_t super_root_key; - uint32_t dcd_ptr; - uint32_t app_dest_ptr; -} flash_header_v1_t; - -typedef struct { - uint32_t length; /* Length of data to be read from flash */ -} flash_cfg_parms_t; - -typedef struct { - flash_header_v1_t fhdr; - dcd_v1_t dcd_table; - flash_cfg_parms_t ext_header; -} imx_header_v1_t; - -typedef struct { - uint32_t addr; - uint32_t value; -} dcd_addr_data_t; - -typedef struct { - uint8_t tag; - uint16_t length; - uint8_t version; -} __attribute__((packed)) ivt_header_t; - -typedef struct { - uint8_t tag; - uint16_t length; - uint8_t param; -} __attribute__((packed)) write_dcd_command_t; - -struct dcd_v2_cmd { - write_dcd_command_t write_dcd_command; - dcd_addr_data_t addr_data[MAX_HW_CFG_SIZE_V2]; -}; - -typedef struct { - ivt_header_t header; - struct dcd_v2_cmd dcd_cmd; - uint32_t padding[1]; /* end up on an 8-byte boundary */ -} dcd_v2_t; - -typedef struct { - uint32_t start; - uint32_t size; - uint32_t plugin; -} boot_data_t; - -typedef struct { - ivt_header_t header; - uint32_t entry; - uint32_t reserved1; - uint32_t dcd_ptr; - uint32_t boot_data_ptr; - uint32_t self; - uint32_t csf; - uint32_t reserved2; -} flash_header_v2_t; - -typedef struct { - flash_header_v2_t fhdr; - boot_data_t boot_data; - union { - dcd_v2_t dcd_table; - char plugin_code[MAX_PLUGIN_CODE_SIZE]; - } data; -} imx_header_v2_t; - -/* The header must be aligned to 4k on MX53 for NAND boot */ -struct imx_header { - union { - imx_header_v1_t hdr_v1; - imx_header_v2_t hdr_v2; - } header; -}; - -typedef void (*set_dcd_val_t)(struct imx_header *imxhdr, - char *name, int lineno, - int fld, uint32_t value, - uint32_t off); - -typedef void (*set_dcd_param_t)(struct imx_header *imxhdr, uint32_t dcd_len, - int32_t cmd); - -typedef void (*set_dcd_rst_t)(struct imx_header *imxhdr, - uint32_t dcd_len, - char *name, int lineno); - -typedef void (*set_imx_hdr_t)(struct imx_header *imxhdr, uint32_t dcd_len, - uint32_t entry_point, uint32_t flash_offset); - -#endif /* _IMXIMAGE_H_ */ -- cgit v0.10.2 From 5661f08a71446ab0ffb5bcf595709027e68f10fa Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Wed, 16 Aug 2017 11:00:51 -0700 Subject: usb: gadget: add SDP driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add SDP (Serial Downloader Protocol) implementation for U-Boot. The protocol is used in NXP SoC's boot ROM and allows to download program images. Beside that, it can also be used to read/write registers and download complete Device Configuration Data (DCD) sets. This basic implementation supports downloading images with the imx header format reading and writing registers. Signed-off-by: Stefan Agner Reviewed-by: Łukasz Majewski diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 261ed12..225b66b 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -103,6 +103,13 @@ config USB_GADGET_DOWNLOAD if USB_GADGET_DOWNLOAD +config USB_FUNCTION_SDP + bool "Enable USB SDP (Serial Download Protocol)" + help + Enable Serial Download Protocol (SDP) device support in U-Boot. This + allows to download images into memory and execute (jump to) them + using the same protocol as implemented by the i.MX family's boot ROM. + config G_DNL_MANUFACTURER string "Vendor name of USB device" diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index 5e316a7..6a007d1 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -28,6 +28,7 @@ obj-$(CONFIG_USB_FUNCTION_THOR) += f_thor.o obj-$(CONFIG_USB_FUNCTION_DFU) += f_dfu.o obj-$(CONFIG_USB_FUNCTION_MASS_STORAGE) += f_mass_storage.o obj-$(CONFIG_USB_FUNCTION_FASTBOOT) += f_fastboot.o +obj-$(CONFIG_USB_FUNCTION_SDP) += f_sdp.o endif endif ifdef CONFIG_USB_ETHER diff --git a/drivers/usb/gadget/f_sdp.c b/drivers/usb/gadget/f_sdp.c new file mode 100644 index 0000000..9d82abc --- /dev/null +++ b/drivers/usb/gadget/f_sdp.c @@ -0,0 +1,721 @@ +/* + * f_sdp.c -- USB HID Serial Download Protocol + * + * Copyright (C) 2017 Toradex + * Author: Stefan Agner + * + * This file implements the Serial Download Protocol (SDP) as specified in + * the i.MX 6 Reference Manual. The SDP is a USB HID based protocol and + * allows to download images directly to memory. The implementation + * works with the imx_loader (imx_usb) USB client software on host side. + * + * Not all commands are implemented, e.g. WRITE_REGISTER, DCD_WRITE and + * SKIP_DCD_HEADER are only stubs. + * + * Parts of the implementation are based on f_dfu and f_thor. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#define HID_REPORT_ID_MASK 0x000000ff + +/* + * HID class requests + */ +#define HID_REQ_GET_REPORT 0x01 +#define HID_REQ_GET_IDLE 0x02 +#define HID_REQ_GET_PROTOCOL 0x03 +#define HID_REQ_SET_REPORT 0x09 +#define HID_REQ_SET_IDLE 0x0A +#define HID_REQ_SET_PROTOCOL 0x0B + +#define HID_USAGE_PAGE_LEN 76 + +struct hid_report { + u8 usage_page[HID_USAGE_PAGE_LEN]; +} __packed; + +#define SDP_READ_REGISTER 0x0101 +#define SDP_WRITE_REGISTER 0x0202 +#define SDP_WRITE_FILE 0x0404 +#define SDP_ERROR_STATUS 0x0505 +#define SDP_DCD_WRITE 0x0a0a +#define SDP_JUMP_ADDRESS 0x0b0b +#define SDP_SKIP_DCD_HEADER 0x0c0c + +#define SDP_SECURITY_CLOSED 0x12343412 +#define SDP_SECURITY_OPEN 0x56787856 + +#define SDP_WRITE_FILE_COMPLETE 0x88888888 +#define SDP_WRITE_REGISTER_COMPLETE 0x128A8A12 +#define SDP_SKIP_DCD_HEADER_COMPLETE 0x900DD009 +#define SDP_ERROR_IMXHEADER 0x000a0533 + +#define SDP_COMMAND_LEN 16 + +struct sdp_command { + u16 cmd; + u32 addr; + u8 format; + u32 cnt; + u32 data; + u8 rsvd; +} __packed; + +enum sdp_state { + SDP_STATE_IDLE, + SDP_STATE_RX_DCD_DATA, + SDP_STATE_RX_FILE_DATA, + SDP_STATE_TX_SEC_CONF, + SDP_STATE_TX_SEC_CONF_BUSY, + SDP_STATE_TX_REGISTER, + SDP_STATE_TX_REGISTER_BUSY, + SDP_STATE_TX_STATUS, + SDP_STATE_TX_STATUS_BUSY, + SDP_STATE_JUMP, +}; + +struct f_sdp { + struct usb_function usb_function; + + struct usb_descriptor_header **function; + + u8 altsetting; + enum sdp_state state; + enum sdp_state next_state; + u32 dnl_address; + u32 dnl_bytes_remaining; + u32 jmp_address; + bool always_send_status; + u32 error_status; + + /* EP0 request */ + struct usb_request *req; + + /* EP1 IN */ + struct usb_ep *in_ep; + struct usb_request *in_req; + + bool configuration_done; +}; + +static struct f_sdp *sdp_func; + +static inline struct f_sdp *func_to_sdp(struct usb_function *f) +{ + return container_of(f, struct f_sdp, usb_function); +} + +static struct usb_interface_descriptor sdp_intf_runtime = { + .bLength = sizeof(sdp_intf_runtime), + .bDescriptorType = USB_DT_INTERFACE, + .bAlternateSetting = 0, + .bNumEndpoints = 1, + .bInterfaceClass = USB_CLASS_HID, + .bInterfaceSubClass = 0, + .bInterfaceProtocol = 0, + /* .iInterface = DYNAMIC */ +}; + +/* HID configuration */ +static struct usb_class_hid_descriptor sdp_hid_desc = { + .bLength = sizeof(sdp_hid_desc), + .bDescriptorType = USB_DT_CS_DEVICE, + + .bcdCDC = __constant_cpu_to_le16(0x0110), + .bCountryCode = 0, + .bNumDescriptors = 1, + + .bDescriptorType0 = USB_DT_HID_REPORT, + .wDescriptorLength0 = HID_USAGE_PAGE_LEN, +}; + +static struct usb_endpoint_descriptor in_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, /*USB_DT_CS_ENDPOINT*/ + + .bEndpointAddress = 1 | USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_INT, + .wMaxPacketSize = 64, + .bInterval = 1, +}; + +static struct usb_descriptor_header *sdp_runtime_descs[] = { + (struct usb_descriptor_header *)&sdp_intf_runtime, + (struct usb_descriptor_header *)&sdp_hid_desc, + (struct usb_descriptor_header *)&in_desc, + NULL, +}; + +/* This is synchronized with what the SoC implementation reports */ +static struct hid_report sdp_hid_report = { + .usage_page = { + 0x06, 0x00, 0xff, /* Usage Page */ + 0x09, 0x01, /* Usage (Pointer?) */ + 0xa1, 0x01, /* Collection */ + + 0x85, 0x01, /* Report ID */ + 0x19, 0x01, /* Usage Minimum */ + 0x29, 0x01, /* Usage Maximum */ + 0x15, 0x00, /* Local Minimum */ + 0x26, 0xFF, 0x00, /* Local Maximum? */ + 0x75, 0x08, /* Report Size */ + 0x95, 0x10, /* Report Count */ + 0x91, 0x02, /* Output Data */ + + 0x85, 0x02, /* Report ID */ + 0x19, 0x01, /* Usage Minimum */ + 0x29, 0x01, /* Usage Maximum */ + 0x15, 0x00, /* Local Minimum */ + 0x26, 0xFF, 0x00, /* Local Maximum? */ + 0x75, 0x80, /* Report Size 128 */ + 0x95, 0x40, /* Report Count */ + 0x91, 0x02, /* Output Data */ + + 0x85, 0x03, /* Report ID */ + 0x19, 0x01, /* Usage Minimum */ + 0x29, 0x01, /* Usage Maximum */ + 0x15, 0x00, /* Local Minimum */ + 0x26, 0xFF, 0x00, /* Local Maximum? */ + 0x75, 0x08, /* Report Size 8 */ + 0x95, 0x04, /* Report Count */ + 0x81, 0x02, /* Input Data */ + + 0x85, 0x04, /* Report ID */ + 0x19, 0x01, /* Usage Minimum */ + 0x29, 0x01, /* Usage Maximum */ + 0x15, 0x00, /* Local Minimum */ + 0x26, 0xFF, 0x00, /* Local Maximum? */ + 0x75, 0x08, /* Report Size 8 */ + 0x95, 0x40, /* Report Count */ + 0x81, 0x02, /* Input Data */ + 0xc0 + }, +}; + +static const char sdp_name[] = "Serial Downloader Protocol"; + +/* + * static strings, in UTF-8 + */ +static struct usb_string strings_sdp_generic[] = { + [0].s = sdp_name, + { } /* end of list */ +}; + +static struct usb_gadget_strings stringtab_sdp_generic = { + .language = 0x0409, /* en-us */ + .strings = strings_sdp_generic, +}; + +static struct usb_gadget_strings *sdp_generic_strings[] = { + &stringtab_sdp_generic, + NULL, +}; + +static void sdp_rx_command_complete(struct usb_ep *ep, struct usb_request *req) +{ + struct f_sdp *sdp = req->context; + int status = req->status; + u8 *data = req->buf; + u8 report = data[0]; + + if (status != 0) { + error("Status: %d", status); + return; + } + + if (report != 1) { + error("Unexpected report %d", report); + return; + } + + struct sdp_command *cmd = req->buf + 1; + + debug("%s: command: %04x, addr: %08x, cnt: %u\n", + __func__, be16_to_cpu(cmd->cmd), + be32_to_cpu(cmd->addr), be32_to_cpu(cmd->cnt)); + + switch (be16_to_cpu(cmd->cmd)) { + case SDP_READ_REGISTER: + sdp->always_send_status = false; + sdp->error_status = 0x0; + + sdp->state = SDP_STATE_TX_SEC_CONF; + sdp->dnl_address = be32_to_cpu(cmd->addr); + sdp->dnl_bytes_remaining = be32_to_cpu(cmd->cnt); + sdp->next_state = SDP_STATE_TX_REGISTER; + printf("Reading %d registers at 0x%08x... ", + sdp->dnl_bytes_remaining, sdp->dnl_address); + break; + case SDP_WRITE_FILE: + sdp->always_send_status = true; + sdp->error_status = SDP_WRITE_FILE_COMPLETE; + + sdp->state = SDP_STATE_RX_FILE_DATA; + sdp->dnl_address = be32_to_cpu(cmd->addr); + sdp->dnl_bytes_remaining = be32_to_cpu(cmd->cnt); + sdp->next_state = SDP_STATE_IDLE; + + printf("Downloading file of size %d to 0x%08x... ", + sdp->dnl_bytes_remaining, sdp->dnl_address); + + break; + case SDP_ERROR_STATUS: + sdp->always_send_status = true; + sdp->error_status = 0; + + sdp->state = SDP_STATE_TX_SEC_CONF; + sdp->next_state = SDP_STATE_IDLE; + break; + case SDP_DCD_WRITE: + sdp->always_send_status = true; + sdp->error_status = SDP_WRITE_REGISTER_COMPLETE; + + sdp->state = SDP_STATE_RX_DCD_DATA; + sdp->dnl_bytes_remaining = be32_to_cpu(cmd->cnt); + sdp->next_state = SDP_STATE_IDLE; + break; + case SDP_JUMP_ADDRESS: + sdp->always_send_status = false; + sdp->error_status = 0; + + sdp->jmp_address = be32_to_cpu(cmd->addr); + sdp->state = SDP_STATE_TX_SEC_CONF; + sdp->next_state = SDP_STATE_JUMP; + break; + case SDP_SKIP_DCD_HEADER: + sdp->always_send_status = true; + sdp->error_status = SDP_SKIP_DCD_HEADER_COMPLETE; + + /* Ignore command, DCD not supported anyway */ + sdp->state = SDP_STATE_TX_SEC_CONF; + sdp->next_state = SDP_STATE_IDLE; + break; + default: + error("Unknown command: %04x\n", be16_to_cpu(cmd->cmd)); + } +} + +static void sdp_rx_data_complete(struct usb_ep *ep, struct usb_request *req) +{ + struct f_sdp *sdp = req->context; + int status = req->status; + u8 *data = req->buf; + u8 report = data[0]; + int datalen = req->length - 1; + + if (status != 0) { + error("Status: %d", status); + return; + } + + if (report != 2) { + error("Unexpected report %d", report); + return; + } + + if (sdp->dnl_bytes_remaining < datalen) { + /* + * Some USB stacks require to send a complete buffer as + * specified in the HID descriptor. This leads to longer + * transfers than the file length, no problem for us. + */ + sdp->dnl_bytes_remaining = 0; + } else { + sdp->dnl_bytes_remaining -= datalen; + } + + if (sdp->state == SDP_STATE_RX_FILE_DATA) { + memcpy((void *)sdp->dnl_address, req->buf + 1, datalen); + sdp->dnl_address += datalen; + } + + if (sdp->dnl_bytes_remaining) + return; + + printf("done\n"); + + switch (sdp->state) { + case SDP_STATE_RX_FILE_DATA: + sdp->state = SDP_STATE_TX_SEC_CONF; + break; + case SDP_STATE_RX_DCD_DATA: + sdp->state = SDP_STATE_TX_SEC_CONF; + break; + default: + error("Invalid state: %d", sdp->state); + } +} + +static void sdp_tx_complete(struct usb_ep *ep, struct usb_request *req) +{ + struct f_sdp *sdp = req->context; + int status = req->status; + + if (status != 0) { + error("Status: %d", status); + return; + } + + switch (sdp->state) { + case SDP_STATE_TX_SEC_CONF_BUSY: + /* Not all commands require status report */ + if (sdp->always_send_status || sdp->error_status) + sdp->state = SDP_STATE_TX_STATUS; + else + sdp->state = sdp->next_state; + + break; + case SDP_STATE_TX_STATUS_BUSY: + sdp->state = sdp->next_state; + break; + case SDP_STATE_TX_REGISTER_BUSY: + if (sdp->dnl_bytes_remaining) + sdp->state = SDP_STATE_TX_REGISTER; + else + sdp->state = SDP_STATE_IDLE; + break; + default: + error("Wrong State: %d", sdp->state); + sdp->state = SDP_STATE_IDLE; + break; + } + debug("%s complete --> %d, %d/%d\n", ep->name, + status, req->actual, req->length); +} + +static int sdp_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) +{ + struct usb_gadget *gadget = f->config->cdev->gadget; + struct usb_request *req = f->config->cdev->req; + struct f_sdp *sdp = f->config->cdev->req->context; + u16 len = le16_to_cpu(ctrl->wLength); + u16 w_value = le16_to_cpu(ctrl->wValue); + int value = 0; + u8 req_type = ctrl->bRequestType & USB_TYPE_MASK; + + debug("w_value: 0x%04x len: 0x%04x\n", w_value, len); + debug("req_type: 0x%02x ctrl->bRequest: 0x%02x sdp->state: %d\n", + req_type, ctrl->bRequest, sdp->state); + + if (req_type == USB_TYPE_STANDARD) { + if (ctrl->bRequest == USB_REQ_GET_DESCRIPTOR) { + /* Send HID report descriptor */ + value = min(len, (u16) sizeof(sdp_hid_report)); + memcpy(req->buf, &sdp_hid_report, value); + sdp->configuration_done = true; + } + } + + if (req_type == USB_TYPE_CLASS) { + int report = w_value & HID_REPORT_ID_MASK; + + /* HID (SDP) request */ + switch (ctrl->bRequest) { + case HID_REQ_SET_REPORT: + switch (report) { + case 1: + value = SDP_COMMAND_LEN + 1; + req->complete = sdp_rx_command_complete; + break; + case 2: + value = len; + req->complete = sdp_rx_data_complete; + break; + } + } + } + + if (value >= 0) { + req->length = value; + req->zero = value < len; + value = usb_ep_queue(gadget->ep0, req, 0); + if (value < 0) { + debug("ep_queue --> %d\n", value); + req->status = 0; + } + } + + return value; +} + +static int sdp_bind(struct usb_configuration *c, struct usb_function *f) +{ + struct usb_gadget *gadget = c->cdev->gadget; + struct usb_composite_dev *cdev = c->cdev; + struct f_sdp *sdp = func_to_sdp(f); + int rv = 0, id; + + id = usb_interface_id(c, f); + if (id < 0) + return id; + sdp_intf_runtime.bInterfaceNumber = id; + + struct usb_ep *ep; + + /* allocate instance-specific endpoints */ + ep = usb_ep_autoconfig(gadget, &in_desc); + if (!ep) { + rv = -ENODEV; + goto error; + } + + sdp->in_ep = ep; /* Store IN EP for enabling @ setup */ + + cdev->req->context = sdp; + +error: + return rv; +} + +static void sdp_unbind(struct usb_configuration *c, struct usb_function *f) +{ + free(sdp_func); + sdp_func = NULL; +} + +static struct usb_request *alloc_ep_req(struct usb_ep *ep, unsigned length) +{ + struct usb_request *req; + + req = usb_ep_alloc_request(ep, 0); + if (!req) + return req; + + req->length = length; + req->buf = memalign(CONFIG_SYS_CACHELINE_SIZE, length); + if (!req->buf) { + usb_ep_free_request(ep, req); + req = NULL; + } + + return req; +} + + +static struct usb_request *sdp_start_ep(struct usb_ep *ep) +{ + struct usb_request *req; + + req = alloc_ep_req(ep, 64); + debug("%s: ep:%p req:%p\n", __func__, ep, req); + + if (!req) + return NULL; + + memset(req->buf, 0, req->length); + req->complete = sdp_tx_complete; + + return req; +} +static int sdp_set_alt(struct usb_function *f, unsigned intf, unsigned alt) +{ + struct f_sdp *sdp = func_to_sdp(f); + struct usb_composite_dev *cdev = f->config->cdev; + int result; + + debug("%s: intf: %d alt: %d\n", __func__, intf, alt); + + result = usb_ep_enable(sdp->in_ep, &in_desc); + if (result) + return result; + sdp->in_req = sdp_start_ep(sdp->in_ep); + sdp->in_req->context = sdp; + + sdp->in_ep->driver_data = cdev; /* claim */ + + sdp->altsetting = alt; + sdp->state = SDP_STATE_IDLE; + + return 0; +} + +static int sdp_get_alt(struct usb_function *f, unsigned intf) +{ + struct f_sdp *sdp = func_to_sdp(f); + + return sdp->altsetting; +} + +static void sdp_disable(struct usb_function *f) +{ + struct f_sdp *sdp = func_to_sdp(f); + + usb_ep_disable(sdp->in_ep); + + if (sdp->in_req) { + free(sdp->in_req); + sdp->in_req = NULL; + } +} + +static int sdp_bind_config(struct usb_configuration *c) +{ + int status; + + if (!sdp_func) { + sdp_func = memalign(CONFIG_SYS_CACHELINE_SIZE, sizeof(*sdp_func)); + if (!sdp_func) + return -ENOMEM; + } + + memset(sdp_func, 0, sizeof(*sdp_func)); + + sdp_func->usb_function.name = "sdp"; + sdp_func->usb_function.hs_descriptors = sdp_runtime_descs; + sdp_func->usb_function.descriptors = sdp_runtime_descs; + sdp_func->usb_function.bind = sdp_bind; + sdp_func->usb_function.unbind = sdp_unbind; + sdp_func->usb_function.set_alt = sdp_set_alt; + sdp_func->usb_function.get_alt = sdp_get_alt; + sdp_func->usb_function.disable = sdp_disable; + sdp_func->usb_function.strings = sdp_generic_strings; + sdp_func->usb_function.setup = sdp_setup; + + status = usb_add_function(c, &sdp_func->usb_function); + + return status; +} + +int sdp_init(int controller_index) +{ + printf("SDP: initialize...\n"); + while (!sdp_func->configuration_done) { + if (ctrlc()) { + puts("\rCTRL+C - Operation aborted.\n"); + return 1; + } + usb_gadget_handle_interrupts(controller_index); + } + + return 0; +} + +static u32 sdp_jump_imxheader(void *address) +{ + flash_header_v2_t *headerv2 = address; + ulong (*entry)(void); + + if (headerv2->header.tag != IVT_HEADER_TAG) { + printf("Header Tag is not an IMX image\n"); + return SDP_ERROR_IMXHEADER; + } + + printf("Jumping to 0x%08x\n", headerv2->entry); + entry = (void *)headerv2->entry; + entry(); + + /* The image probably never returns hence we won't reach that point */ + return 0; +} + +static void sdp_handle_in_ep(void) +{ + u8 *data = sdp_func->in_req->buf; + u32 status; + int datalen; + + switch (sdp_func->state) { + case SDP_STATE_TX_SEC_CONF: + debug("Report 3: HAB security\n"); + data[0] = 3; + + status = SDP_SECURITY_OPEN; + memcpy(&data[1], &status, 4); + sdp_func->in_req->length = 5; + usb_ep_queue(sdp_func->in_ep, sdp_func->in_req, 0); + sdp_func->state = SDP_STATE_TX_SEC_CONF_BUSY; + break; + + case SDP_STATE_TX_STATUS: + debug("Report 4: Status\n"); + data[0] = 4; + + memcpy(&data[1], &sdp_func->error_status, 4); + sdp_func->in_req->length = 65; + usb_ep_queue(sdp_func->in_ep, sdp_func->in_req, 0); + sdp_func->state = SDP_STATE_TX_STATUS_BUSY; + break; + case SDP_STATE_TX_REGISTER: + debug("Report 4: Register Values\n"); + data[0] = 4; + + datalen = sdp_func->dnl_bytes_remaining; + + if (datalen > 64) + datalen = 64; + + memcpy(&data[1], (void *)sdp_func->dnl_address, datalen); + sdp_func->in_req->length = 65; + + sdp_func->dnl_bytes_remaining -= datalen; + sdp_func->dnl_address += datalen; + + usb_ep_queue(sdp_func->in_ep, sdp_func->in_req, 0); + sdp_func->state = SDP_STATE_TX_REGISTER_BUSY; + break; + case SDP_STATE_JUMP: + printf("Checking imxheader at 0x%08x\n", f_sdp->jmp_address); + status = sdp_jump_imxheader((void *)f_sdp->jmp_address); + + sdp_func->next_state = SDP_STATE_IDLE; + sdp_func->error_status = status; + + /* Only send Report 4 if there was an error */ + if (status) + sdp_func->state = SDP_STATE_TX_STATUS; + else + sdp_func->state = SDP_STATE_IDLE; + break; + default: + break; + }; +} + +void sdp_handle(int controller_index) +{ + printf("SDP: handle requests...\n"); + while (1) { + if (ctrlc()) { + puts("\rCTRL+C - Operation aborted.\n"); + return; + } + + usb_gadget_handle_interrupts(controller_index); + + sdp_handle_in_ep(); + } +} + +int sdp_add(struct usb_configuration *c) +{ + int id; + + id = usb_string_id(c->cdev); + if (id < 0) + return id; + strings_sdp_generic[0].id = id; + sdp_intf_runtime.iInterface = id; + + debug("%s: cdev: %p gadget: %p gadget->ep0: %p\n", __func__, + c->cdev, c->cdev->gadget, c->cdev->gadget->ep0); + + return sdp_bind_config(c); +} + +DECLARE_GADGET_BIND_CALLBACK(usb_dnl_sdp, sdp_add); diff --git a/include/sdp.h b/include/sdp.h new file mode 100644 index 0000000..f476bab --- /dev/null +++ b/include/sdp.h @@ -0,0 +1,16 @@ +/* + * sdp.h - Serial Download Protocol + * + * Copyright (C) 2017 Toradex + * Author: Stefan Agner + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __SDP_H_ +#define __SDP_H_ + +int sdp_init(int controller_index); +void sdp_handle(int controller_index); + +#endif /* __SDP_H_ */ -- cgit v0.10.2 From ccd7a4d2f42df7ebc8fd0fbbd31d5e6534cb590c Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Wed, 16 Aug 2017 11:00:52 -0700 Subject: usb: gadget: sdp: extend images compatible for jumps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Support U-Boot images in SPL so that u-boot.img files can be directly downloaded and executed. Furthermore support U-Boot scripts download and execution in full U-Boot so that custom recovery actions can be downloaded from the host in a third step. Signed-off-by: Stefan Agner Reviewed-by: Łukasz Majewski Reviewed-by: Stefano Babic diff --git a/drivers/usb/gadget/f_sdp.c b/drivers/usb/gadget/f_sdp.c index 9d82abc..0fae66b 100644 --- a/drivers/usb/gadget/f_sdp.c +++ b/drivers/usb/gadget/f_sdp.c @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include #define HID_REPORT_ID_MASK 0x000000ff @@ -670,8 +672,22 @@ static void sdp_handle_in_ep(void) sdp_func->state = SDP_STATE_TX_REGISTER_BUSY; break; case SDP_STATE_JUMP: - printf("Checking imxheader at 0x%08x\n", f_sdp->jmp_address); - status = sdp_jump_imxheader((void *)f_sdp->jmp_address); + printf("Jumping to header at 0x%08x\n", sdp_func->jmp_address); + status = sdp_jump_imxheader((void *)sdp_func->jmp_address); + + /* If imx header fails, try some U-Boot specific headers */ + if (status) { +#ifdef CONFIG_SPL_BUILD + /* In SPL, allow jumps to U-Boot images */ + struct spl_image_info spl_image = {}; + spl_parse_image_header(&spl_image, + (struct image_header *)sdp_func->jmp_address); + jump_to_image_no_args(&spl_image); +#else + /* In U-Boot, allow jumps to scripts */ + source(sdp_func->jmp_address, "script@1"); +#endif + } sdp_func->next_state = SDP_STATE_IDLE; sdp_func->error_status = status; -- cgit v0.10.2 From 2f005695df7b03d25a367f6bedc41c015088ee29 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Wed, 16 Aug 2017 11:00:53 -0700 Subject: cmd: add sdp command MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a new command to start USB Serial Download Protocol (SDP) state machine. Signed-off-by: Stefan Agner Reviewed-by: Łukasz Majewski Reviewed-by: Stefano Babic diff --git a/cmd/Kconfig b/cmd/Kconfig index 42d955c..d6d130e 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -895,6 +895,13 @@ config CMD_USB help USB support. +config CMD_USB_SDP + bool "sdp" + select USB_FUNCTION_SDP + help + Enables the command "sdp" which is used to have U-Boot emulating the + Serial Download Protocol (SDP) via USB. + config CMD_USB_MASS_STORAGE bool "UMS usb mass storage" help diff --git a/cmd/Makefile b/cmd/Makefile index 4a865bd..2a5b8ce 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -132,6 +132,7 @@ obj-$(CONFIG_CMD_FASTBOOT) += fastboot.o obj-$(CONFIG_CMD_FS_UUID) += fs_uuid.o obj-$(CONFIG_CMD_USB_MASS_STORAGE) += usb_mass_storage.o +obj-$(CONFIG_CMD_USB_SDP) += usb_gadget_sdp.o obj-$(CONFIG_CMD_THOR_DOWNLOAD) += thordown.o obj-$(CONFIG_CMD_XIMG) += ximg.o obj-$(CONFIG_CMD_YAFFS2) += yaffs2.o diff --git a/cmd/usb_gadget_sdp.c b/cmd/usb_gadget_sdp.c new file mode 100644 index 0000000..b1d8b28 --- /dev/null +++ b/cmd/usb_gadget_sdp.c @@ -0,0 +1,50 @@ +/* + * cmd_sdp.c -- sdp command + * + * Copyright (C) 2016 Toradex + * Author: Stefan Agner + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include + +static int do_sdp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + int ret = CMD_RET_FAILURE; + + if (argc < 2) + return CMD_RET_USAGE; + + char *usb_controller = argv[1]; + int controller_index = simple_strtoul(usb_controller, NULL, 0); + board_usb_init(controller_index, USB_INIT_DEVICE); + + g_dnl_clear_detach(); + g_dnl_register("usb_dnl_sdp"); + + ret = sdp_init(controller_index); + if (ret) { + error("SDP init failed: %d", ret); + goto exit; + } + + /* This command typically does not return but jumps to an image */ + sdp_handle(controller_index); + error("SDP ended"); + +exit: + g_dnl_unregister(); + board_usb_cleanup(controller_index, USB_INIT_DEVICE); + + return ret; +} + +U_BOOT_CMD(sdp, 2, 1, do_sdp, + "Serial Downloader Protocol", + "\n" + " - serial downloader protocol via \n" +); -- cgit v0.10.2 From a3774c1c3c28e4ed89a36383ca73970b809bae94 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Wed, 16 Aug 2017 11:00:54 -0700 Subject: spl: add serial download protocol (SDP) support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add USB serial download protocol support to SPL. If the SoC started in recovery mode the SPL will immediately switch to SDP and wait for further downloads/commands from the host side. Signed-off-by: Stefan Agner Reviewed-by: Stefano Babic Reviewed-by: Łukasz Majewski diff --git a/common/spl/Kconfig b/common/spl/Kconfig index 582b685..9446cd9 100644 --- a/common/spl/Kconfig +++ b/common/spl/Kconfig @@ -668,6 +668,12 @@ config SPL_DFU_RAM endchoice +config SPL_USB_SDP_SUPPORT + bool "Support SDP (Serial Download Protocol)" + help + Enable Serial Download Protocol (SDP) device support in SPL. This + allows to download images into memory and execute (jump to) them + using the same protocol as implemented by the i.MX family's boot ROM. endif config SPL_WATCHDOG_SUPPORT diff --git a/common/spl/Makefile b/common/spl/Makefile index fde0d09..e229947 100644 --- a/common/spl/Makefile +++ b/common/spl/Makefile @@ -30,4 +30,5 @@ obj-$(CONFIG_$(SPL_TPL_)SATA_SUPPORT) += spl_sata.o obj-$(CONFIG_$(SPL_TPL_)DFU_SUPPORT) += spl_dfu.o obj-$(CONFIG_$(SPL_TPL_)SPI_LOAD) += spl_spi.o obj-$(CONFIG_$(SPL_TPL_)RAM_SUPPORT) += spl_ram.o +obj-$(CONFIG_$(SPL_TPL_)USB_SDP_SUPPORT) += spl_sdp.o endif diff --git a/common/spl/spl_sdp.c b/common/spl/spl_sdp.c new file mode 100644 index 0000000..350bcdb --- /dev/null +++ b/common/spl/spl_sdp.c @@ -0,0 +1,37 @@ +/* + * (C) Copyright 2016 Toradex + * Author: Stefan Agner + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +static int spl_sdp_load_image(struct spl_image_info *spl_image, + struct spl_boot_device *bootdev) +{ + int ret; + const int controller_index = 0; + + g_dnl_clear_detach(); + g_dnl_register("usb_dnl_sdp"); + + ret = sdp_init(controller_index); + if (ret) { + error("SDP init failed: %d", ret); + return -ENODEV; + } + + /* This command typically does not return but jumps to an image */ + sdp_handle(controller_index); + error("SDP ended"); + + return -EINVAL; +} +SPL_LOAD_IMAGE_METHOD("USB SDP", 0, BOOT_DEVICE_BOARD, spl_sdp_load_image); diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index 6a007d1..7258099 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_USB_ETHER) += epautoconf.o config.o usbstring.o ifdef CONFIG_SPL_BUILD obj-$(CONFIG_SPL_USB_GADGET_SUPPORT) += g_dnl.o obj-$(CONFIG_SPL_DFU_SUPPORT) += f_dfu.o +obj-$(CONFIG_SPL_USB_SDP_SUPPORT) += f_sdp.o endif # new USB gadget layer dependencies -- cgit v0.10.2 From f9c39d95f16e62a39d751d9b886f673c6d1e90b8 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Wed, 16 Aug 2017 11:00:55 -0700 Subject: doc: add Serial Download Protocol documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Document the U-Boot Serial Download Protocol implementation and some typical use cases. Signed-off-by: Stefan Agner Reviewed-by: Łukasz Majewski diff --git a/doc/README.sdp b/doc/README.sdp new file mode 100644 index 0000000..9b438c0 --- /dev/null +++ b/doc/README.sdp @@ -0,0 +1,100 @@ +------------- +SDP in U-Boot +------------- + +SDP stands for serial download protocol. It is the protocol used in NXP's +i.MX SoCs ROM Serial Downloader and provides means to download a program +image to the chip over USB and UART serial connection. + +The implementation in U-Boot uses the USB Downloader Gadget (g_dnl) to +provide a SDP implementation over USB. This allows to download program +images to the target in SPL/U-Boot using the same protocol/tooling the +SoC's recovery mechanism is using. + +The SDP protocol over USB is a USB HID class protocol. USB HID class +protocols allow to access a USB device without OS specific drivers. The +U-Boot implementation has primarly been tested using the open source +imx_loader utility (https://github.com/toradex/imx_loader). + +The host side utilities are typically capable to interpret the i.MX +specific image header (see doc/README.imximage). There are extensions +for imx_loader's imx_usb utility which allow to interpret the U-Boot +specific legacy image format (see mkimage(1)). Also the U-Boot side +support beside the i.MX specific header the U-Boot legacy header. + +Usage +----- + +This implementation can be started in U-Boot using the sdp command +(CONFIG_CMD_USB_SDP) or in SPL if Serial Downloader boot mode has been +detected (CONFIG_SPL_USB_SDP_SUPPORT). + +A typical use case is downloading full U-Boot after SPL has been +downloaded through the boot ROM's Serial Downloader. Using boot mode +detection the SPL will run the SDP implementation automatically in +this case: + + # imx_usb SPL + +Targets Serial Console: + + Trying to boot from USB SDP + SDP: initialize... + SDP: handle requests... + +At this point the SPL reenumerated as a new HID device and emulating +the boot ROM's SDP protocol. The USB VID/PID will depend on standard +U-Boot configurations CONFIG_G_DNL_(VENDOR|PRODUCT)_NUM. Make sure +imx_usb is aware of the USB VID/PID for your device by adding a +configuration entry in imx_usb.conf: + + 0x1b67:0x4fff, mx6_usb_sdp_spl.conf + +And the device specific configuration file mx6_usb_sdp_spl.conf: + + mx6_spl_sdp + hid,uboot_header,1024,0x910000,0x10000000,1G,0x00900000,0x40000 + +This allows to download the regular U-Boot with legacy image headers +(u-boot.img) using a second invocation of imx_usb: + + # imx_usb u-boot.img + +Furthermore, when U-Boot is running the sdp command can be used to +download and run scripts: + + # imx_usb script.scr + +imx_usb configuration files can be also used to download multiple +files and of arbitrary types, e.g. + + mx6_usb_sdp_uboot + hid,1024,0x10000000,1G,0x00907000,0x31000 + full.itb:load 0x12100000 + boot.scr:load 0x12000000,jump 0x12000000 + +There is also a batch mode which allows imx_usb to handle multiple +consecutive reenumerations by adding multiple VID/PID specifications +in imx_usb.conf: + + 0x15a2:0x0061, mx6_usb_rom.conf, 0x1b67:0x4fff, mx6_usb_sdp_spl.conf + +In this mode the file to download (imx_usb job) needs to be specified +in the configuration files. + +mx6_usb_rom.conf: + + mx6_qsb + hid,1024,0x910000,0x10000000,1G,0x00900000,0x40000 + SPL:jump header2 + +mx6_usb_sdp_spl.conf: + + mx6_spl_sdp + hid,uboot_header,1024,0x10000000,1G,0x00907000,0x31000 + u-boot.img:jump header2 + +With that SPL and U-Boot can be downloaded with a single invocation +of imx_usb without arguments: + + # imx_usb -- cgit v0.10.2 From 2b2f6782805dddc2060f7436e1c911eb98ab86e4 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Wed, 16 Aug 2017 11:00:56 -0700 Subject: apalis/colibri_imx6: use independent USB PID for SPL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use a completely independent USB Product ID for SPL. This allows to differentiate a SDP running in SPL and SDP running in a U-Boot which could not read the config block successfully. Signed-off-by: Stefan Agner Acked-by: Max Krummenacher Reviewed-by: Łukasz Majewski diff --git a/board/toradex/apalis_imx6/apalis_imx6.c b/board/toradex/apalis_imx6/apalis_imx6.c index 7a3e493..2fd9623 100644 --- a/board/toradex/apalis_imx6/apalis_imx6.c +++ b/board/toradex/apalis_imx6/apalis_imx6.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -1234,6 +1235,18 @@ void reset_cpu(ulong addr) { } +#ifdef CONFIG_SPL_USB_GADGET_SUPPORT +int g_dnl_bind_fixup(struct usb_device_descriptor *dev, const char *name) +{ + unsigned short usb_pid; + + usb_pid = TORADEX_USB_PRODUCT_NUM_OFFSET + 0xfff; + put_unaligned(usb_pid, &dev->idProduct); + + return 0; +} +#endif + #endif static struct mxc_serial_platdata mxc_serial_plat = { diff --git a/board/toradex/colibri_imx6/colibri_imx6.c b/board/toradex/colibri_imx6/colibri_imx6.c index dbcd233..d30391f 100644 --- a/board/toradex/colibri_imx6/colibri_imx6.c +++ b/board/toradex/colibri_imx6/colibri_imx6.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -1118,6 +1119,18 @@ void reset_cpu(ulong addr) { } +#ifdef CONFIG_SPL_USB_GADGET_SUPPORT +int g_dnl_bind_fixup(struct usb_device_descriptor *dev, const char *name) +{ + unsigned short usb_pid; + + usb_pid = TORADEX_USB_PRODUCT_NUM_OFFSET + 0xfff; + put_unaligned(usb_pid, &dev->idProduct); + + return 0; +} +#endif + #endif static struct mxc_serial_platdata mxc_serial_plat = { -- cgit v0.10.2 From f0e0698cee4a6410a26bdb2fbee82cfd30f31785 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Wed, 16 Aug 2017 11:00:57 -0700 Subject: apalis/colibri_imx6: enable SDP by default Enable Serial Download Protocol (SDP) in SPL and U-Boot. This is useful to make use of imx_usb to download the complete U-Boot (u-boot.img) after SPL has been downloaded. The U-Boot command sdp allows to enumerate as SDP capable device again, e.g. to download a Linux kernel and/or U-Boot script. Signed-off-by: Stefan Agner Acked-by: Max Krummenacher diff --git a/configs/apalis_imx6_defconfig b/configs/apalis_imx6_defconfig index 468a1fc..8f87f1d 100644 --- a/configs/apalis_imx6_defconfig +++ b/configs/apalis_imx6_defconfig @@ -17,6 +17,9 @@ CONFIG_BOARD_EARLY_INIT_F=y CONFIG_SPL=y CONFIG_SPL_DMA_SUPPORT=y CONFIG_SPL_I2C_SUPPORT=y +CONFIG_SPL_USB_HOST_SUPPORT=y +CONFIG_SPL_USB_GADGET_SUPPORT=y +CONFIG_SPL_USB_SDP_SUPPORT=y CONFIG_HUSH_PARSER=y CONFIG_SYS_PROMPT="Apalis iMX6 # " CONFIG_CMD_BOOTZ=y @@ -33,6 +36,7 @@ CONFIG_CMD_GPIO=y CONFIG_CMD_I2C=y CONFIG_CMD_MMC=y CONFIG_CMD_USB=y +CONFIG_CMD_USB_SDP=y CONFIG_CMD_USB_MASS_STORAGE=y CONFIG_CMD_DHCP=y CONFIG_CMD_MII=y diff --git a/configs/colibri_imx6_defconfig b/configs/colibri_imx6_defconfig index edbd87f..beb74b5 100644 --- a/configs/colibri_imx6_defconfig +++ b/configs/colibri_imx6_defconfig @@ -17,6 +17,9 @@ CONFIG_BOARD_EARLY_INIT_F=y CONFIG_SPL=y CONFIG_SPL_DMA_SUPPORT=y CONFIG_SPL_I2C_SUPPORT=y +CONFIG_SPL_USB_HOST_SUPPORT=y +CONFIG_SPL_USB_GADGET_SUPPORT=y +CONFIG_SPL_USB_SDP_SUPPORT=y CONFIG_HUSH_PARSER=y CONFIG_SYS_PROMPT="Colibri iMX6 # " CONFIG_CMD_BOOTZ=y @@ -33,6 +36,7 @@ CONFIG_CMD_GPIO=y CONFIG_CMD_I2C=y CONFIG_CMD_MMC=y CONFIG_CMD_USB=y +CONFIG_CMD_USB_SDP=y CONFIG_CMD_USB_MASS_STORAGE=y CONFIG_CMD_DHCP=y CONFIG_CMD_MII=y -- cgit v0.10.2 From fa85b0217db0ceb024e5018db979d78f97651ff6 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Thu, 17 Aug 2017 17:48:50 +0800 Subject: imx: mx7: psci: add copyright and license Add copyright and license header. Signed-off-by: Peng Fan Cc: Stefano Babic diff --git a/arch/arm/mach-imx/mx7/psci-mx7.c b/arch/arm/mach-imx/mx7/psci-mx7.c index 502552d..7f429b0 100644 --- a/arch/arm/mach-imx/mx7/psci-mx7.c +++ b/arch/arm/mach-imx/mx7/psci-mx7.c @@ -1,3 +1,10 @@ +/* + * Copyright (C) 2015-2016 Freescale Semiconductor, Inc. + * Copyright 2017 NXP + * + * SPDX-License-Identifier: GPL-2.0+ + */ + #include #include #include diff --git a/arch/arm/mach-imx/mx7/psci.S b/arch/arm/mach-imx/mx7/psci.S index 96e88d6..fc5eb34 100644 --- a/arch/arm/mach-imx/mx7/psci.S +++ b/arch/arm/mach-imx/mx7/psci.S @@ -1,3 +1,10 @@ +/* + * Copyright (C) 2015-2016 Freescale Semiconductor, Inc. + * Copyright 2017 NXP + * + * SPDX-License-Identifier: GPL-2.0+ + */ + #include #include -- cgit v0.10.2 From 7c09cbf68bd1881450dbac13f38486aab5640090 Mon Sep 17 00:00:00 2001 From: Stefano Babic Date: Thu, 17 Aug 2017 13:55:20 +0200 Subject: imx: fix licensing in i.MX files Some files for i.MX do not yet have the SPDX ID to reference the correct license. Signed-off-by: Stefano Babic Reviewed-by: Wolfgang Denk diff --git a/arch/arm/include/asm/arch-mx35/mmc_host_def.h b/arch/arm/include/asm/arch-mx35/mmc_host_def.h index 775b955..0775511 100644 --- a/arch/arm/include/asm/arch-mx35/mmc_host_def.h +++ b/arch/arm/include/asm/arch-mx35/mmc_host_def.h @@ -3,23 +3,7 @@ * Texas Instruments, * Syed Mohammed Khasim * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation's version 2 of - * the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA + * SPDX-License-Identifier: GPL-2.0 */ #ifndef MMC_HOST_DEF_H diff --git a/arch/arm/include/asm/arch-mx5/iomux-mx51.h b/arch/arm/include/asm/arch-mx5/iomux-mx51.h index 5c636ac..522512e 100644 --- a/arch/arm/include/asm/arch-mx5/iomux-mx51.h +++ b/arch/arm/include/asm/arch-mx5/iomux-mx51.h @@ -3,12 +3,7 @@ * Copyright (C) 2010 Freescale Semiconductor, Inc. * Copyright (C) 2009-2012 Genesi USA, Inc. * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html + * SPDX-License-Identifier: GPL-2.0+ */ /* diff --git a/arch/arm/include/asm/arch-mxs/iomux-mx23.h b/arch/arm/include/asm/arch-mxs/iomux-mx23.h index 7cb5e71..690929c 100644 --- a/arch/arm/include/asm/arch-mxs/iomux-mx23.h +++ b/arch/arm/include/asm/arch-mxs/iomux-mx23.h @@ -2,12 +2,7 @@ * Copyright (C) 2009-2010 Amit Kucheria * Copyright (C) 2010 Freescale Semiconductor, Inc. * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html + * SPDX-License-Identifier: GPL-2.0+ */ #ifndef __MACH_IOMUX_MX23_H__ diff --git a/arch/arm/include/asm/arch-mxs/iomux-mx28.h b/arch/arm/include/asm/arch-mxs/iomux-mx28.h index b42820d..39ea74b 100644 --- a/arch/arm/include/asm/arch-mxs/iomux-mx28.h +++ b/arch/arm/include/asm/arch-mxs/iomux-mx28.h @@ -2,12 +2,7 @@ * Copyright (C) 2009-2010 Amit Kucheria * Copyright (C) 2010 Freescale Semiconductor, Inc. * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html + * SPDX-License-Identifier: GPL-2.0+ */ #ifndef __MACH_IOMUX_MX28_H__ -- cgit v0.10.2 From 63fbc59b4f14e6c19b203cca894226874fe68998 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Mon, 14 Aug 2017 18:09:16 +0800 Subject: pinctrl: imx: Fix mask when SHARE_MUX_CONF_REG is set when using SHARE_MUX_CONF_REG, wrong mask is used for writing config value, which causes mux value is cleared. Signed-off-by: Peng Fan Cc: Simon Glass Cc: Stefano Babic diff --git a/drivers/pinctrl/nxp/pinctrl-imx.c b/drivers/pinctrl/nxp/pinctrl-imx.c index 1b6107f..32cbac9 100644 --- a/drivers/pinctrl/nxp/pinctrl-imx.c +++ b/drivers/pinctrl/nxp/pinctrl-imx.c @@ -158,7 +158,7 @@ static int imx_pinctrl_set_state(struct udevice *dev, struct udevice *config) if (!(config_val & IMX_NO_PAD_CTL)) { if (info->flags & SHARE_MUX_CONF_REG) { clrsetbits_le32(info->base + conf_reg, - info->mux_mask, config_val); + ~info->mux_mask, config_val); } else { writel(config_val, info->base + conf_reg); } -- cgit v0.10.2 From 7a7bfec39ea8a800c6cce21c3f44544943ea0a8e Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Mon, 14 Aug 2017 18:09:17 +0800 Subject: pinctrl: imx7ulp: Add new info instance for iomuxc1 To i.MX7ULP, we need to create two info instances for iomux0 and iomux1 respectively, otherwise iomuxc0/1 will share one info instance and use one base, because imx_pinctrl_probe will use info to store base address and etc. But iomuxc0/1 actually have different base address. Signed-off-by: Peng Fan Cc: Simon Glass Cc: Stefano Babic diff --git a/drivers/pinctrl/nxp/pinctrl-imx7ulp.c b/drivers/pinctrl/nxp/pinctrl-imx7ulp.c index 4a893e5..618ce6a 100644 --- a/drivers/pinctrl/nxp/pinctrl-imx7ulp.c +++ b/drivers/pinctrl/nxp/pinctrl-imx7ulp.c @@ -12,7 +12,11 @@ #include "pinctrl-imx.h" -static struct imx_pinctrl_soc_info imx7ulp_pinctrl_soc_info = { +static struct imx_pinctrl_soc_info imx7ulp_pinctrl_soc_info0 = { + .flags = ZERO_OFFSET_VALID | SHARE_MUX_CONF_REG | CONFIG_IBE_OBE, +}; + +static struct imx_pinctrl_soc_info imx7ulp_pinctrl_soc_info1 = { .flags = ZERO_OFFSET_VALID | SHARE_MUX_CONF_REG | CONFIG_IBE_OBE, }; @@ -25,8 +29,8 @@ static int imx7ulp_pinctrl_probe(struct udevice *dev) } static const struct udevice_id imx7ulp_pinctrl_match[] = { - { .compatible = "fsl,imx7ulp-iomuxc-0", .data = (ulong)&imx7ulp_pinctrl_soc_info }, - { .compatible = "fsl,imx7ulp-iomuxc-1", .data = (ulong)&imx7ulp_pinctrl_soc_info }, + { .compatible = "fsl,imx7ulp-iomuxc-0", .data = (ulong)&imx7ulp_pinctrl_soc_info0 }, + { .compatible = "fsl,imx7ulp-iomuxc-1", .data = (ulong)&imx7ulp_pinctrl_soc_info1 }, { /* sentinel */ } }; -- cgit v0.10.2 From 3bd1642d4d50171291cb18bbae0cb3c8bf7fa5f7 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Tue, 15 Aug 2017 17:49:42 -0700 Subject: imx: fix USB boot mode detection for i.MX 6UL and 6ULL Add the reserved boot mode used in the bmode command for i.MX 6UL and 6ULL as introduced in commit 3fd9579085fa ("imx: mx6ull: fix USB bmode for i.MX 6UL and 6ULL"). Also replace BMODE_UART with BMODE_RESERVED, which is more appropriate. Commit 96aac843b68d ("imx: Use IMX6_BMODE_* macros instead of numericals") added macros for boot modes, in the process the reserved boot mode got named BMODE_UART. We use the reserved boot mode in the bmode command to let the boot ROM enter serial downloader recovery mode. But this is only a side effect, the actual boot mode is reserved... Signed-off-by: Stefan Agner diff --git a/arch/arm/include/asm/mach-imx/sys_proto.h b/arch/arm/include/asm/mach-imx/sys_proto.h index 046df62..d94c095 100644 --- a/arch/arm/include/asm/mach-imx/sys_proto.h +++ b/arch/arm/include/asm/mach-imx/sys_proto.h @@ -69,8 +69,13 @@ enum imx6_bmode_emi { enum imx6_bmode { IMX6_BMODE_EMI, - IMX6_BMODE_UART, +#if defined(CONFIG_MX6UL) || defined(CONFIG_MX6ULL) + IMX6_BMODE_QSPI, + IMX6_BMODE_RESERVED, +#else + IMX6_BMODE_RESERVED, IMX6_BMODE_SATA, +#endif IMX6_BMODE_SERIAL_ROM, IMX6_BMODE_SD, IMX6_BMODE_ESD, diff --git a/arch/arm/mach-imx/spl.c b/arch/arm/mach-imx/spl.c index 75698c4..836b334 100644 --- a/arch/arm/mach-imx/spl.c +++ b/arch/arm/mach-imx/spl.c @@ -42,7 +42,7 @@ u32 spl_boot_device(void) break; } /* Reserved: Used to force Serial Downloader */ - case IMX6_BMODE_UART: + case IMX6_BMODE_RESERVED: return BOOT_DEVICE_UART; /* SATA: See 8.5.4, Table 8-20 */ case IMX6_BMODE_SATA: -- cgit v0.10.2 From 962c78b1dfa6cd69333cad52c9298a3e1f85f606 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Tue, 15 Aug 2017 17:49:43 -0700 Subject: imx: use BOOT_DEVICE_BOARD instead of UART i.MX 6 serial downloader is not necessarily booting via UART but can also boot from USB. In fact only some i.MX chips have serial downloader support via UART (e.g. 6UL/ULL and Vybrid) but all of them have serial downloader support via USB. Use the more appropriate BOOT_DEVICE_BOARD define which is used for ROM provided recovery mechanisms in general. Signed-off-by: Stefan Agner diff --git a/arch/arm/mach-imx/spl.c b/arch/arm/mach-imx/spl.c index 836b334..bcd1033 100644 --- a/arch/arm/mach-imx/spl.c +++ b/arch/arm/mach-imx/spl.c @@ -27,7 +27,7 @@ u32 spl_boot_device(void) * BOOT_MODE - see IMX6DQRM Table 8-1 */ if (((bmode >> 24) & 0x03) == 0x01) /* Serial Downloader */ - return BOOT_DEVICE_UART; + return BOOT_DEVICE_BOARD; /* BOOT_CFG1[7:4] - see IMX6DQRM Table 8-8 */ switch ((reg & IMX6_BMODE_MASK) >> IMX6_BMODE_SHIFT) { @@ -43,7 +43,7 @@ u32 spl_boot_device(void) } /* Reserved: Used to force Serial Downloader */ case IMX6_BMODE_RESERVED: - return BOOT_DEVICE_UART; + return BOOT_DEVICE_BOARD; /* SATA: See 8.5.4, Table 8-20 */ case IMX6_BMODE_SATA: return BOOT_DEVICE_SATA; -- cgit v0.10.2 From 3aa4b703b483f165dd2eb5c3324b44b60fbb1672 Mon Sep 17 00:00:00 2001 From: Breno Lima Date: Thu, 24 Aug 2017 10:00:16 -0300 Subject: imx: imx6: Move gpr_init() function to soc.c Since the gpr_init() function is common for boards using MX6S, MX6DL, MX6D, MX6Q and MX6QP processors move it to the soc.c file. Signed-off-by: Breno Lima Acked-by: Stefano Babic Reviewed-by: Lukasz Majewski Reviewed-by: Fabio Estevam diff --git a/arch/arm/include/asm/mach-imx/sys_proto.h b/arch/arm/include/asm/mach-imx/sys_proto.h index d94c095..970c4ca 100644 --- a/arch/arm/include/asm/mach-imx/sys_proto.h +++ b/arch/arm/include/asm/mach-imx/sys_proto.h @@ -90,6 +90,8 @@ static inline u8 imx6_is_bmode_from_gpr9(void) } u32 imx6_src_get_boot_mode(void); +void gpr_init(void); + #endif /* CONFIG_MX6 */ u32 get_nr_cpus(void); diff --git a/arch/arm/mach-imx/mx6/soc.c b/arch/arm/mach-imx/mx6/soc.c index 9ede1f5..f8bc05e 100644 --- a/arch/arm/mach-imx/mx6/soc.c +++ b/arch/arm/mach-imx/mx6/soc.c @@ -681,6 +681,23 @@ void imx_setup_hdmi(void) } #endif +void gpr_init(void) +{ + struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR; + + /* enable AXI cache for VDOA/VPU/IPU */ + writel(0xF00000CF, &iomux->gpr[4]); + if (is_mx6dqp()) { + /* set IPU AXI-id1 Qos=0x1 AXI-id0/2/3 Qos=0x7 */ + writel(0x77177717, &iomux->gpr[6]); + writel(0x77177717, &iomux->gpr[7]); + } else { + /* set IPU AXI-id0 Qos=0xf(bypass) AXI-id1 Qos=0x7 */ + writel(0x007F007F, &iomux->gpr[6]); + writel(0x007F007F, &iomux->gpr[7]); + } +} + #ifdef CONFIG_IMX_BOOTAUX int arch_auxiliary_core_up(u32 core_id, u32 boot_private_data) { diff --git a/board/bachmann/ot1200/ot1200.c b/board/bachmann/ot1200/ot1200.c index df10d6a..9465cea 100644 --- a/board/bachmann/ot1200/ot1200.c +++ b/board/bachmann/ot1200/ot1200.c @@ -169,17 +169,6 @@ static void ccgr_init(void) writel(0x000003FF, &ccm->CCGR6); } -static void gpr_init(void) -{ - struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR; - - /* enable AXI cache for VDOA/VPU/IPU */ - writel(0xF00000CF, &iomux->gpr[4]); - /* set IPU AXI-id0 Qos=0xf(bypass) AXI-id1 Qos=0x7 */ - writel(0x007F007F, &iomux->gpr[6]); - writel(0x007F007F, &iomux->gpr[7]); -} - int board_early_init_f(void) { ccgr_init(); diff --git a/board/barco/platinum/platinum.h b/board/barco/platinum/platinum.h index d3ea8bd..3013ed9 100644 --- a/board/barco/platinum/platinum.h +++ b/board/barco/platinum/platinum.h @@ -75,15 +75,4 @@ static inline void ccgr_init(void) writel(0x000003FF, &ccm->CCGR6); } -static inline void gpr_init(void) -{ - struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR; - - /* enable AXI cache for VDOA/VPU/IPU */ - writel(0xF00000CF, &iomux->gpr[4]); - /* set IPU AXI-id0 Qos=0xf(bypass) AXI-id1 Qos=0x7 */ - writel(0x007F007F, &iomux->gpr[6]); - writel(0x007F007F, &iomux->gpr[7]); -} - #endif /* _PLATINUM_H_ */ diff --git a/board/congatec/cgtqmx6eval/cgtqmx6eval.c b/board/congatec/cgtqmx6eval/cgtqmx6eval.c index 8cd0090..2ed66d3 100644 --- a/board/congatec/cgtqmx6eval/cgtqmx6eval.c +++ b/board/congatec/cgtqmx6eval/cgtqmx6eval.c @@ -955,17 +955,6 @@ static void ccgr_init(void) writel(0x000003FF, &ccm->CCGR6); } -static void gpr_init(void) -{ - struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR; - - /* enable AXI cache for VDOA/VPU/IPU */ - writel(0xF00000CF, &iomux->gpr[4]); - /* set IPU AXI-id0 Qos=0xf(bypass) AXI-id1 Qos=0x7 */ - writel(0x007F007F, &iomux->gpr[6]); - writel(0x007F007F, &iomux->gpr[7]); -} - /* Define a minimal structure so that the part number can be read via SPL */ struct mfgdata { unsigned char tsize; diff --git a/board/el/el6x/el6x.c b/board/el/el6x/el6x.c index 6b98b5c..fb128f5 100644 --- a/board/el/el6x/el6x.c +++ b/board/el/el6x/el6x.c @@ -570,17 +570,6 @@ static void ccgr_init(void) writel(0x000003FF, &ccm->CCGR6); } -static void gpr_init(void) -{ - struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR; - - /* enable AXI cache for VDOA/VPU/IPU */ - writel(0xF00000CF, &iomux->gpr[4]); - /* set IPU AXI-id0 Qos=0xf(bypass) AXI-id1 Qos=0x7 */ - writel(0x007F007F, &iomux->gpr[6]); - writel(0x007F007F, &iomux->gpr[7]); -} - /* * This section requires the differentiation between iMX6 Sabre boards, but * for now, it will configure only for the mx6q variant. diff --git a/board/engicam/common/spl.c b/board/engicam/common/spl.c index a8a7cf3..29a27ce 100644 --- a/board/engicam/common/spl.c +++ b/board/engicam/common/spl.c @@ -332,17 +332,6 @@ static void ccgr_init(void) #endif } -static void gpr_init(void) -{ - struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR; - - /* enable AXI cache for VDOA/VPU/IPU */ - writel(0xF00000CF, &iomux->gpr[4]); - /* set IPU AXI-id0 Qos=0xf(bypass) AXI-id1 Qos=0x7 */ - writel(0x007F007F, &iomux->gpr[6]); - writel(0x007F007F, &iomux->gpr[7]); -} - static void spl_dram_init(void) { #ifdef CONFIG_MX6QDL diff --git a/board/freescale/mx6sabreauto/mx6sabreauto.c b/board/freescale/mx6sabreauto/mx6sabreauto.c index f8f77f6..15ca029 100644 --- a/board/freescale/mx6sabreauto/mx6sabreauto.c +++ b/board/freescale/mx6sabreauto/mx6sabreauto.c @@ -798,23 +798,6 @@ static void ccgr_init(void) writel(0x000003FF, &ccm->CCGR6); } -static void gpr_init(void) -{ - struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR; - - /* enable AXI cache for VDOA/VPU/IPU */ - writel(0xF00000CF, &iomux->gpr[4]); - if (is_mx6dqp()) { - /* set IPU AXI-id1 Qos=0x1 AXI-id0/2/3 Qos=0x7 */ - writel(0x77177717, &iomux->gpr[6]); - writel(0x77177717, &iomux->gpr[7]); - } else { - /* set IPU AXI-id0 Qos=0xf(bypass) AXI-id1 Qos=0x7 */ - writel(0x007F007F, &iomux->gpr[6]); - writel(0x007F007F, &iomux->gpr[7]); - } -} - static int mx6q_dcd_table[] = { 0x020e0798, 0x000C0000, 0x020e0758, 0x00000000, diff --git a/board/freescale/mx6sabresd/mx6sabresd.c b/board/freescale/mx6sabresd/mx6sabresd.c index 9a562b3..5b50bc8 100644 --- a/board/freescale/mx6sabresd/mx6sabresd.c +++ b/board/freescale/mx6sabresd/mx6sabresd.c @@ -747,23 +747,6 @@ static void ccgr_init(void) writel(0x000003FF, &ccm->CCGR6); } -static void gpr_init(void) -{ - struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR; - - /* enable AXI cache for VDOA/VPU/IPU */ - writel(0xF00000CF, &iomux->gpr[4]); - if (is_mx6dqp()) { - /* set IPU AXI-id1 Qos=0x1 AXI-id0/2/3 Qos=0x7 */ - writel(0x77177717, &iomux->gpr[6]); - writel(0x77177717, &iomux->gpr[7]); - } else { - /* set IPU AXI-id0 Qos=0xf(bypass) AXI-id1 Qos=0x7 */ - writel(0x007F007F, &iomux->gpr[6]); - writel(0x007F007F, &iomux->gpr[7]); - } -} - static int mx6q_dcd_table[] = { 0x020e0798, 0x000C0000, 0x020e0758, 0x00000000, diff --git a/board/gateworks/gw_ventana/gw_ventana_spl.c b/board/gateworks/gw_ventana/gw_ventana_spl.c index 9524da7..c2e370b 100644 --- a/board/gateworks/gw_ventana/gw_ventana_spl.c +++ b/board/gateworks/gw_ventana/gw_ventana_spl.c @@ -583,17 +583,6 @@ static void ccgr_init(void) writel(0x000003FF, &ccm->CCGR6); } -static void gpr_init(void) -{ - struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR; - - /* enable AXI cache for VDOA/VPU/IPU */ - writel(0xF00000CF, &iomux->gpr[4]); - /* set IPU AXI-id0 Qos=0xf(bypass) AXI-id1 Qos=0x7 */ - writel(0x007F007F, &iomux->gpr[6]); - writel(0x007F007F, &iomux->gpr[7]); -} - /* * called from C runtime startup code (arch/arm/lib/crt0.S:_main) * - we have a stack and a place to store GD, both in SRAM diff --git a/board/kosagi/novena/novena_spl.c b/board/kosagi/novena/novena_spl.c index 3645b75..512f06d 100644 --- a/board/kosagi/novena/novena_spl.c +++ b/board/kosagi/novena/novena_spl.c @@ -550,17 +550,6 @@ static void ccgr_init(void) writel(0x000003FF, &ccm->CCGR6); } -static void gpr_init(void) -{ - struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR; - - /* enable AXI cache for VDOA/VPU/IPU */ - writel(0xF00000CF, &iomux->gpr[4]); - /* set IPU AXI-id0 Qos=0xf(bypass) AXI-id1 Qos=0x7 */ - writel(0x007F007F, &iomux->gpr[6]); - writel(0x007F007F, &iomux->gpr[7]); -} - /* * called from C runtime startup code (arch/arm/lib/crt0.S:_main) * - we have a stack and a place to store GD, both in SRAM diff --git a/board/liebherr/mccmon6/spl.c b/board/liebherr/mccmon6/spl.c index 15844ef..a2f804d 100644 --- a/board/liebherr/mccmon6/spl.c +++ b/board/liebherr/mccmon6/spl.c @@ -260,17 +260,6 @@ static void ccgr_init(void) writel(0x000003FF, &ccm->CCGR6); } -static void gpr_init(void) -{ - struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR; - - /* enable AXI cache for VDOA/VPU/IPU */ - writel(0xF00000CF, &iomux->gpr[4]); - /* set IPU AXI-id0 Qos=0xf(bypass) AXI-id1 Qos=0x7 */ - writel(0x007F007F, &iomux->gpr[6]); - writel(0x007F007F, &iomux->gpr[7]); -} - static void spl_dram_init(void) { if (is_cpu_type(MXC_CPU_MX6SOLO)) { diff --git a/board/phytec/pcm058/pcm058.c b/board/phytec/pcm058/pcm058.c index 4257fbc..1538158 100644 --- a/board/phytec/pcm058/pcm058.c +++ b/board/phytec/pcm058/pcm058.c @@ -487,18 +487,6 @@ static void ccgr_init(void) writel(0x000003FF, &ccm->CCGR6); } -static void gpr_init(void) -{ - struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR; - - /* enable AXI cache for VDOA/VPU/IPU */ - writel(0xF00000CF, &iomux->gpr[4]); - /* set IPU AXI-id0 Qos=0xf(bypass) AXI-id1 Qos=0x7 */ - writel(0x007F007F, &iomux->gpr[6]); - writel(0x007F007F, &iomux->gpr[7]); -} - - static void spl_dram_init(void) { struct mx6_ddr_sysinfo sysinfo = { diff --git a/board/phytec/pfla02/pfla02.c b/board/phytec/pfla02/pfla02.c index 8d2ce63..ec9264d 100644 --- a/board/phytec/pfla02/pfla02.c +++ b/board/phytec/pfla02/pfla02.c @@ -550,17 +550,6 @@ static void ccgr_init(void) writel(0x000003FF, &ccm->CCGR6); } -static void gpr_init(void) -{ - struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR; - - /* enable AXI cache for VDOA/VPU/IPU */ - writel(0xF00000CF, &iomux->gpr[4]); - /* set IPU AXI-id0 Qos=0xf(bypass) AXI-id1 Qos=0x7 */ - writel(0x007F007F, &iomux->gpr[6]); - writel(0x007F007F, &iomux->gpr[7]); -} - static void spl_dram_init(struct mx6_ddr3_cfg *mem_ddr) { struct mx6_ddr_sysinfo sysinfo = { diff --git a/board/solidrun/mx6cuboxi/mx6cuboxi.c b/board/solidrun/mx6cuboxi/mx6cuboxi.c index 7e59fb2..986abc5 100644 --- a/board/solidrun/mx6cuboxi/mx6cuboxi.c +++ b/board/solidrun/mx6cuboxi/mx6cuboxi.c @@ -581,17 +581,6 @@ static void ccgr_init(void) writel(0x000003FF, &ccm->CCGR6); } -static void gpr_init(void) -{ - struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR; - - /* enable AXI cache for VDOA/VPU/IPU */ - writel(0xF00000CF, &iomux->gpr[4]); - /* set IPU AXI-id0 Qos=0xf(bypass) AXI-id1 Qos=0x7 */ - writel(0x007F007F, &iomux->gpr[6]); - writel(0x007F007F, &iomux->gpr[7]); -} - static void spl_dram_init(int width) { struct mx6_ddr_sysinfo sysinfo = { diff --git a/board/toradex/apalis_imx6/apalis_imx6.c b/board/toradex/apalis_imx6/apalis_imx6.c index 2fd9623..ebc6c12 100644 --- a/board/toradex/apalis_imx6/apalis_imx6.c +++ b/board/toradex/apalis_imx6/apalis_imx6.c @@ -1160,17 +1160,6 @@ static void ccgr_init(void) writel(0x000000FB, &ccm->ccosr); } -static void gpr_init(void) -{ - struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR; - - /* enable AXI cache for VDOA/VPU/IPU */ - writel(0xF00000CF, &iomux->gpr[4]); - /* set IPU AXI-id0 Qos=0xf(bypass) AXI-id1 Qos=0x7 */ - writel(0x007F007F, &iomux->gpr[6]); - writel(0x007F007F, &iomux->gpr[7]); -} - static void ddr_init(int *table, int size) { int i; diff --git a/board/toradex/colibri_imx6/colibri_imx6.c b/board/toradex/colibri_imx6/colibri_imx6.c index d30391f..669d912 100644 --- a/board/toradex/colibri_imx6/colibri_imx6.c +++ b/board/toradex/colibri_imx6/colibri_imx6.c @@ -1037,17 +1037,6 @@ static void ccgr_init(void) writel(0x000000FB, &ccm->ccosr); } -static void gpr_init(void) -{ - struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR; - - /* enable AXI cache for VDOA/VPU/IPU */ - writel(0xF00000CF, &iomux->gpr[4]); - /* set IPU AXI-id0 Qos=0xf(bypass) AXI-id1 Qos=0x7 */ - writel(0x007F007F, &iomux->gpr[6]); - writel(0x007F007F, &iomux->gpr[7]); -} - static void ddr_init(int *table, int size) { int i; diff --git a/board/udoo/udoo_spl.c b/board/udoo/udoo_spl.c index e83e7c3..3645969 100644 --- a/board/udoo/udoo_spl.c +++ b/board/udoo/udoo_spl.c @@ -211,17 +211,6 @@ static void ccgr_init(void) writel(0x000003FF, &ccm->CCGR6); } -static void gpr_init(void) -{ - struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR; - - /* enable AXI cache for VDOA/VPU/IPU */ - writel(0xF00000FF, &iomux->gpr[4]); - /* set IPU AXI-id0 Qos=0xf(bypass) AXI-id1 Qos=0x7 */ - writel(0x007F007F, &iomux->gpr[6]); - writel(0x007F007F, &iomux->gpr[7]); -} - static void spl_dram_init(void) { if (is_cpu_type(MXC_CPU_MX6DL)) { diff --git a/board/wandboard/spl.c b/board/wandboard/spl.c index 47082a8..99a0286 100644 --- a/board/wandboard/spl.c +++ b/board/wandboard/spl.c @@ -266,17 +266,6 @@ static void ccgr_init(void) writel(0x000003FF, &ccm->CCGR6); } -static void gpr_init(void) -{ - struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR; - - /* enable AXI cache for VDOA/VPU/IPU */ - writel(0xF00000CF, &iomux->gpr[4]); - /* set IPU AXI-id0 Qos=0xf(bypass) AXI-id1 Qos=0x7 */ - writel(0x007F007F, &iomux->gpr[6]); - writel(0x007F007F, &iomux->gpr[7]); -} - static void spl_dram_init(void) { if (is_cpu_type(MXC_CPU_MX6SOLO)) { -- cgit v0.10.2 From cb40adff8fd5335c0f623562c57bf8505c32b16f Mon Sep 17 00:00:00 2001 From: Stefano Babic Date: Fri, 25 Aug 2017 13:02:53 +0200 Subject: pfla02: Fix RAM detection and support 1 bank SOM In case of 2 banks, the address space of the first CS must be defined and not let to the higher value. Add support for SOM with a single bank of RAM. It was tested with i.MX6Q modules in the following configurations: - 2 Banks, 4 GB - 2 Banks, 1 GB - 1 Bank, 1 GB Signed-off-by: Stefano Babic diff --git a/board/phytec/pfla02/Kconfig b/board/phytec/pfla02/Kconfig index 142a122..f4da68b 100644 --- a/board/phytec/pfla02/Kconfig +++ b/board/phytec/pfla02/Kconfig @@ -9,4 +9,10 @@ config SYS_VENDOR config SYS_CONFIG_NAME default "pfla02" +config SPL_DRAM_1_BANK + bool "DRAM on just one bank" + help + activate, if the module has just one bank + of RAM + endif diff --git a/board/phytec/pfla02/pfla02.c b/board/phytec/pfla02/pfla02.c index ec9264d..136f1d5 100644 --- a/board/phytec/pfla02/pfla02.c +++ b/board/phytec/pfla02/pfla02.c @@ -485,9 +485,9 @@ static const struct mx6_mmdc_calibration mx6_mmcd_calib = { /* Index in RAM Chip array */ enum { - RAM_1GB, - RAM_2GB, - RAM_4GB + RAM_MT64K, + RAM_MT128K, + RAM_MT256K }; static struct mx6_ddr3_cfg mt41k_xx[] = { @@ -550,31 +550,11 @@ static void ccgr_init(void) writel(0x000003FF, &ccm->CCGR6); } -static void spl_dram_init(struct mx6_ddr3_cfg *mem_ddr) +static void spl_dram_init(struct mx6_ddr_sysinfo *sysinfo, + struct mx6_ddr3_cfg *mem_ddr) { - struct mx6_ddr_sysinfo sysinfo = { - /* width of data bus:0=16,1=32,2=64 */ - .dsize = 2, - /* config for full 4GB range so that get_mem_size() works */ - .cs_density = 32, /* 32Gb per CS */ - /* single chip select */ - .ncs = 2, - .cs1_mirror = 0, - .rtt_wr = 1 /*DDR3_RTT_60_OHM*/, /* RTT_Wr = RZQ/4 */ - .rtt_nom = 1 /*DDR3_RTT_60_OHM*/, /* RTT_Nom = RZQ/4 */ - .walat = 1, /* Write additional latency */ - .ralat = 5, /* Read additional latency */ - .mif3_mode = 3, /* Command prediction working mode */ - .bi_on = 1, /* Bank interleaving enabled */ - .sde_to_rst = 0x10, /* 14 cycles, 200us (JEDEC default) */ - .rst_to_cke = 0x23, /* 33 cycles, 500us (JEDEC default) */ - .ddr_type = DDR_TYPE_DDR3, - .refsel = 1, /* Refresh cycles at 32KHz */ - .refr = 7, /* 8 refresh commands per refresh cycle */ - }; - mx6dq_dram_iocfg(64, &mx6_ddr_ioregs, &mx6_grp_ioregs); - mx6_dram_cfg(&sysinfo, &mx6_mmcd_calib, mem_ddr); + mx6_dram_cfg(sysinfo, &mx6_mmcd_calib, mem_ddr); } int board_mmc_init(bd_t *bis) @@ -616,10 +596,12 @@ void board_boot_order(u32 *spl_boot_list) * Function checks for mirrors in the first CS */ #define RAM_TEST_PATTERN 0xaa5555aa -static unsigned int pfla02_detect_ramsize(void) +#define MIN_BANK_SIZE (512 * 1024 * 1024) + +static unsigned int pfla02_detect_chiptype(void) { u32 *p, *p1; - unsigned int offset = 512 * 1024 * 1024; + unsigned int offset = MIN_BANK_SIZE; int i; for (i = 0; i < 2; i++) { @@ -638,12 +620,38 @@ static unsigned int pfla02_detect_ramsize(void) if (*p == *p1) return i; } - return RAM_4GB; + return RAM_MT256K; } void board_init_f(ulong dummy) { unsigned int ramchip; + + struct mx6_ddr_sysinfo sysinfo = { + /* width of data bus:0=16,1=32,2=64 */ + .dsize = 2, + /* config for full 4GB range so that get_mem_size() works */ + .cs_density = 32, /* 512 MB */ + /* single chip select */ +#if IS_ENABLED(CONFIG_SPL_DRAM_1_BANK) + .ncs = 1, +#else + .ncs = 2, +#endif + .cs1_mirror = 1, + .rtt_wr = 1 /*DDR3_RTT_60_OHM*/, /* RTT_Wr = RZQ/4 */ + .rtt_nom = 1 /*DDR3_RTT_60_OHM*/, /* RTT_Nom = RZQ/4 */ + .walat = 1, /* Write additional latency */ + .ralat = 5, /* Read additional latency */ + .mif3_mode = 3, /* Command prediction working mode */ + .bi_on = 1, /* Bank interleaving enabled */ + .sde_to_rst = 0x10, /* 14 cycles, 200us (JEDEC default) */ + .rst_to_cke = 0x23, /* 33 cycles, 500us (JEDEC default) */ + .ddr_type = DDR_TYPE_DDR3, + .refsel = 1, /* Refresh cycles at 32KHz */ + .refr = 7, /* 8 refresh commands per refresh cycle */ + }; + #ifdef CONFIG_CMD_NAND /* Enable NAND */ setup_gpmi_nand(); @@ -671,10 +679,23 @@ void board_init_f(ulong dummy) setup_gpios(); /* DDR initialization */ - spl_dram_init(&mt41k_xx[RAM_4GB]); - ramchip = pfla02_detect_ramsize(); - if (ramchip != RAM_4GB) - spl_dram_init(&mt41k_xx[ramchip]); + spl_dram_init(&sysinfo, &mt41k_xx[RAM_MT256K]); + ramchip = pfla02_detect_chiptype(); + debug("Detected chip %d\n", ramchip); +#if !IS_ENABLED(CONFIG_SPL_DRAM_1_BANK) + switch (ramchip) { + case RAM_MT64K: + sysinfo.cs_density = 6; + break; + case RAM_MT128K: + sysinfo.cs_density = 10; + break; + case RAM_MT256K: + sysinfo.cs_density = 18; + break; + } +#endif + spl_dram_init(&sysinfo, &mt41k_xx[ramchip]); /* Clear the BSS. */ memset(__bss_start, 0, __bss_end - __bss_start); -- cgit v0.10.2 From ae64226dbec2a50a2d88027018c9bd25b20c4ae0 Mon Sep 17 00:00:00 2001 From: Anatolij Gustschin Date: Mon, 28 Aug 2017 17:46:32 +0200 Subject: imx: timer: don't clear the GPT control register multiple times There is no need to clear the control register 100 times in a loop, a single zero write clears the register. I didn't find any justification why clearing this register in a loop is needed (no info in i.MX6 errata or GPT timer linux driver, linux driver uses single write to clear this control register). Signed-off-by: Anatolij Gustschin Acked-by: Stefano Babic diff --git a/arch/arm/mach-imx/timer.c b/arch/arm/mach-imx/timer.c index 9b01114..69dbf3c 100644 --- a/arch/arm/mach-imx/timer.c +++ b/arch/arm/mach-imx/timer.c @@ -74,8 +74,7 @@ int timer_init(void) __raw_writel(GPTCR_SWR, &cur_gpt->control); /* We have no udelay by now */ - for (i = 0; i < 100; i++) - __raw_writel(0, &cur_gpt->control); + __raw_writel(0, &cur_gpt->control); i = __raw_readl(&cur_gpt->control); i &= ~GPTCR_CLKSOURCE_MASK; -- cgit v0.10.2 From f9d42d821c49e0a12c77c100857b914717b9bc0a Mon Sep 17 00:00:00 2001 From: Anatolij Gustschin Date: Mon, 28 Aug 2017 17:46:33 +0200 Subject: spl: do not repeat timer init on i.MX6 The GPT timer was already initialised in board_init_f() as it is needed in dram init. Do not repeat timer init in board_init_r(). Signed-off-by: Anatolij Gustschin Acked-by: Stefano Babic diff --git a/common/spl/spl.c b/common/spl/spl.c index d245cfc..8b219ba 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -379,7 +379,7 @@ void board_init_r(gd_t *dummy1, ulong dummy2) if (spl_init()) hang(); } -#ifndef CONFIG_PPC +#if !defined(CONFIG_PPC) && !defined(CONFIG_ARCH_MX6) /* * timer_init() does not exist on PPC systems. The timer is initialized * and enabled (decrementer) in interrupt_init() here. -- cgit v0.10.2 From ffc36f57bc769bc111b157e2f27791756f8d4057 Mon Sep 17 00:00:00 2001 From: Anatolij Gustschin Date: Mon, 28 Aug 2017 17:51:33 +0200 Subject: imx6: don't include unneeded boot_mode array in SPL The soc_boot_modes array is only used by bmode command and not needed in SPL. Don't include it into SPL. Signed-off-by: Anatolij Gustschin Reviewed-by: Stefano Babic diff --git a/arch/arm/mach-imx/mx6/soc.c b/arch/arm/mach-imx/mx6/soc.c index f8bc05e..b724668 100644 --- a/arch/arm/mach-imx/mx6/soc.c +++ b/arch/arm/mach-imx/mx6/soc.c @@ -551,6 +551,7 @@ void imx_get_mac_from_fuse(int dev_id, unsigned char *mac) } #endif +#ifndef CONFIG_SPL_BUILD /* * cfg_val will be used for * Boot_cfg4[7:0]:Boot_cfg3[7:0]:Boot_cfg2[7:0]:Boot_cfg1[7:0] @@ -577,6 +578,7 @@ const struct boot_mode soc_boot_modes[] = { {"esdhc4", MAKE_CFGVAL(0x40, 0x38, 0x00, 0x00)}, {NULL, 0}, }; +#endif void reset_misc(void) { -- cgit v0.10.2 From a2b137b38d925df91afef52f5122927de024f81a Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Fri, 25 Aug 2017 20:20:44 +0530 Subject: icorem6: Fix to find MMC devices U-Boot proper is using DM_MMC so, enable CONFIG_BLK otherwise find_mmc_device failed to detect MMC device. Signed-off-by: Jagan Teki Reviewed-by: Stefano Babic diff --git a/configs/imx6qdl_icore_mmc_defconfig b/configs/imx6qdl_icore_mmc_defconfig index ec39d09..9d61c48 100644 --- a/configs/imx6qdl_icore_mmc_defconfig +++ b/configs/imx6qdl_icore_mmc_defconfig @@ -36,7 +36,6 @@ CONFIG_CMD_EXT4_WRITE=y CONFIG_CMD_FAT=y CONFIG_CMD_FS_GENERIC=y CONFIG_OF_LIST="imx6q-icore imx6dl-icore" -# CONFIG_BLK is not set CONFIG_SYS_I2C_MXC=y CONFIG_PHYLIB=y CONFIG_PHY_SMSC=y diff --git a/configs/imx6qdl_icore_rqs_defconfig b/configs/imx6qdl_icore_rqs_defconfig index ba3ac1b..319a88d 100644 --- a/configs/imx6qdl_icore_rqs_defconfig +++ b/configs/imx6qdl_icore_rqs_defconfig @@ -34,7 +34,6 @@ CONFIG_CMD_EXT4_WRITE=y CONFIG_CMD_FAT=y CONFIG_CMD_FS_GENERIC=y CONFIG_OF_LIST="imx6q-icore-rqs imx6dl-icore-rqs" -# CONFIG_BLK is not set CONFIG_SYS_I2C_MXC=y CONFIG_PHYLIB=y CONFIG_PHY_MICREL=y -- cgit v0.10.2 From 624da53ca8a8196985a48bc32d788b434ae0f788 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Tue, 29 Aug 2017 09:10:11 -0700 Subject: imx: remove SATA boot mode for i.MX 6UL and 6ULL The NXP i.MX 6UL and 6ULL do not support SATA and have no SATA boot mode, hence remove it from the boot device detecion. This fixes a build error introduced with 3bd1642d4d50 ("imx: fix USB boot mode detection for i.MX 6UL and 6ULL") Fixes: 3bd1642d4d50 ("imx: fix USB boot mode detection for i.MX 6UL and 6ULL") Signed-off-by: Stefan Agner Reviewed-by: Stefano Babic Reviewed-by: Jagan Teki diff --git a/arch/arm/mach-imx/spl.c b/arch/arm/mach-imx/spl.c index bcd1033..3853e77 100644 --- a/arch/arm/mach-imx/spl.c +++ b/arch/arm/mach-imx/spl.c @@ -45,8 +45,10 @@ u32 spl_boot_device(void) case IMX6_BMODE_RESERVED: return BOOT_DEVICE_BOARD; /* SATA: See 8.5.4, Table 8-20 */ +#if !defined(CONFIG_MX6UL) && !defined(CONFIG_MX6ULL) case IMX6_BMODE_SATA: return BOOT_DEVICE_SATA; +#endif /* Serial ROM: See 8.5.5.1, Table 8-22 */ case IMX6_BMODE_SERIAL_ROM: /* BOOT_CFG4[2:0] */ -- cgit v0.10.2 From 46668df5d0a94c6f546bcd31bd56c0ded7b4193f Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Mon, 28 Aug 2017 16:45:47 +0530 Subject: i.MX6Q: spl: Fix falcon to use dram_init_banksize Memory dt node update introduced by spl_fixup_fdt() in below commit was making DDR configuration in-appropriate to boot falcon mode. Hence added dram_init_banksize for explicit assignment of proper base and size of DDR. "boot: fdt: Perform arch_fixup_fdt() on the given device tree for falcon boot" (sha1: 6e7585bb64b12f632681c80c4b193349e1985d92) Signed-off-by: Jagan Teki diff --git a/arch/arm/mach-imx/spl.c b/arch/arm/mach-imx/spl.c index 3853e77..258578a 100644 --- a/arch/arm/mach-imx/spl.c +++ b/arch/arm/mach-imx/spl.c @@ -15,6 +15,8 @@ #include #include +DECLARE_GLOBAL_DATA_PTR; + #if defined(CONFIG_MX6) /* determine boot device from SRC_SBMR1 (BOOT_CFG[4:1]) or SRC_GPR9 register */ u32 spl_boot_device(void) @@ -128,3 +130,13 @@ __weak void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image) } #endif + +#if defined(CONFIG_MX6) && defined(CONFIG_SPL_OS_BOOT) +int dram_init_banksize(void) +{ + gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE; + gd->bd->bi_dram[0].size = imx_ddr_size(); + + return 0; +} +#endif -- cgit v0.10.2 From 63af4b0ad0666e0797306593813b6272e1995bde Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Mon, 28 Aug 2017 16:45:48 +0530 Subject: i.MX6Q: icorem6: Add falcon mode Add Falcon mode support in Engicam i.CoreM6 board. Signed-off-by: Jagan Teki diff --git a/board/engicam/common/spl.c b/board/engicam/common/spl.c index 29a27ce..6964c13 100644 --- a/board/engicam/common/spl.c +++ b/board/engicam/common/spl.c @@ -39,6 +39,17 @@ static iomux_v3_cfg_t const uart_pads[] = { #endif }; +#ifdef CONFIG_SPL_OS_BOOT +int spl_start_uboot(void) +{ + /* break into full u-boot on 'c' */ + if (serial_tstc() && serial_getc() == 'c') + return 1; + + return 0; +} +#endif + #ifdef CONFIG_MX6QDL /* * Driving strength: diff --git a/configs/imx6qdl_icore_mmc_defconfig b/configs/imx6qdl_icore_mmc_defconfig index 9d61c48..4baed1c 100644 --- a/configs/imx6qdl_icore_mmc_defconfig +++ b/configs/imx6qdl_icore_mmc_defconfig @@ -48,3 +48,4 @@ CONFIG_DEBUG_UART_CLOCK=24000000 CONFIG_MXC_UART=y CONFIG_IMX_THERMAL=y CONFIG_VIDEO_IPUV3=y +CONFIG_SPL_OS_BOOT=y diff --git a/include/configs/imx6-engicam.h b/include/configs/imx6-engicam.h index e0bdb656..a1b7036 100644 --- a/include/configs/imx6-engicam.h +++ b/include/configs/imx6-engicam.h @@ -183,6 +183,20 @@ # define CONFIG_MII #endif +/* Falcon Mode */ +#ifdef CONFIG_SPL_OS_BOOT +# define CONFIG_SPL_FS_LOAD_ARGS_NAME "args" +# define CONFIG_SPL_FS_LOAD_KERNEL_NAME "uImage" +# define CONFIG_CMD_SPL +# define CONFIG_SYS_SPL_ARGS_ADDR 0x18000000 +# define CONFIG_CMD_SPL_WRITE_SIZE (128 * SZ_1K) + +/* MMC support: args@1MB kernel@2MB */ +# define CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTOR 0x800 /* 1MB */ +# define CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTORS (CONFIG_CMD_SPL_WRITE_SIZE / 512) +# define CONFIG_SYS_MMCSD_RAW_MODE_KERNEL_SECTOR 0x1000 /* 2MB */ +#endif + /* Framebuffer */ #ifdef CONFIG_VIDEO_IPUV3 # define CONFIG_IPUV3_CLK 260000000 -- cgit v0.10.2