diff --git a/arch/arm/boards/guf-vincell/board.c b/arch/arm/boards/guf-vincell/board.c index ad47ee2..43c1952 100644 --- a/arch/arm/boards/guf-vincell/board.c +++ b/arch/arm/boards/guf-vincell/board.c @@ -40,7 +40,8 @@ static int vincell_devices_init(void) { - if (!of_machine_is_compatible("guf,imx53-vincell")) + if (!of_machine_is_compatible("guf,imx53-vincell") && + !of_machine_is_compatible("guf,imx53-vincell-lt")) return 0; writel(0, MX53_M4IF_BASE_ADDR + 0xc); diff --git a/arch/arm/boards/karo-tx6x/flash-header-tx6qp-2g.imxcfg b/arch/arm/boards/karo-tx6x/flash-header-tx6qp-2g.imxcfg new file mode 100644 index 0000000..455aab9 --- /dev/null +++ b/arch/arm/boards/karo-tx6x/flash-header-tx6qp-2g.imxcfg @@ -0,0 +1,183 @@ +soc imx6 +loadaddr 0x20000000 +dcdofs 0x400 + +wm 32 0x020e00a4 0x00000016 +wm 32 0x020e00c4 0x00000011 +wm 32 0x020e03b8 0x0000f079 +wm 32 0x020e03d8 0x0000f079 +wm 32 0x020e0898 0x00000000 +wm 32 0x020e089c 0x00000000 +wm 32 0x020e0248 0x00000012 +wm 32 0x020e02c8 0x00000015 +wm 32 0x020e06b0 0x000030b0 +wm 32 0x020e00a0 0x00000015 +wm 32 0x020e03b4 0x000030b0 +wm 32 0x020e024c 0x00000005 +wm 32 0x020e061c 0x000030b0 +wm 32 0x020c402c 0x006336c1 +wm 32 0x020c4034 0x00012093 +wm 32 0x020c4038 0x00012090 +wm 32 0x020c80e0 0x00002001 +set_bits 32 0x020c4068 0x00000030 +set_bits 32 0x020c406c 0x00000c00 +set_bits 32 0x020c4070 0x000000c0 +set_bits 32 0x020c4078 0xff000000 +set_bits 32 0x020c407c 0x0f000000 +set_bits 32 0x020c4080 0x000003fc +wm 32 0x020c80a0 0x00082029 +wm 32 0x020c80b0 0x0007a120 +wm 32 0x020c80c0 0x000f4240 +wm 32 0x020e0004 0x48640005 +wm 32 0x020e0010 0xf00000cf +wm 32 0x020e0018 0x77177717 +wm 32 0x020e001c 0x77177717 +wm 32 0x020e02a8 0x00000001 +wm 32 0x020e02ac 0x00000001 +wm 32 0x020e0920 0x00000003 +wm 32 0x020e02c0 0x00000001 +wm 32 0x020e02c4 0x00000001 +wm 32 0x020e091c 0x00000003 +wm 32 0x020e02ec 0x00000000 +wm 32 0x020e05ac 0x00020030 +wm 32 0x020e05b4 0x00020030 +wm 32 0x020e0528 0x00020030 +wm 32 0x020e0520 0x00020030 +wm 32 0x020e0514 0x00020030 +wm 32 0x020e0510 0x00020030 +wm 32 0x020e05bc 0x00020030 +wm 32 0x020e05c4 0x00020030 +wm 32 0x020e052c 0x00020200 +wm 32 0x020e0530 0x00020200 +wm 32 0x020e0534 0x00020200 +wm 32 0x020e0538 0x00020200 +wm 32 0x020e053c 0x00020200 +wm 32 0x020e0540 0x00020200 +wm 32 0x020e0544 0x00020200 +wm 32 0x020e0548 0x00020200 +wm 32 0x020e054c 0x00020200 +wm 32 0x020e0550 0x00020200 +wm 32 0x020e0554 0x00020200 +wm 32 0x020e0558 0x00020200 +wm 32 0x020e055c 0x00020200 +wm 32 0x020e0560 0x00020200 +wm 32 0x020e0564 0x00020200 +wm 32 0x020e0568 0x00020200 +wm 32 0x020e056c 0x00020030 +wm 32 0x020e0578 0x00020030 +wm 32 0x020e0588 0x00020030 +wm 32 0x020e0594 0x00020030 +wm 32 0x020e057c 0x00020030 +wm 32 0x020e0590 0x00003000 +wm 32 0x020e0598 0x00003000 +wm 32 0x020e0580 0x00000000 +wm 32 0x020e0584 0x00000000 +wm 32 0x020e058c 0x00000000 +wm 32 0x020e059c 0x00003030 +wm 32 0x020e05a0 0x00003030 +wm 32 0x020e0784 0x00000030 +wm 32 0x020e0788 0x00000030 +wm 32 0x020e0794 0x00000030 +wm 32 0x020e079c 0x00000030 +wm 32 0x020e07a0 0x00000030 +wm 32 0x020e07a4 0x00000030 +wm 32 0x020e07a8 0x00000030 +wm 32 0x020e0748 0x00000030 +wm 32 0x020e074c 0x00000030 +wm 32 0x020e0750 0x00020000 +wm 32 0x020e0758 0x00000000 +wm 32 0x020e0774 0x00020000 +wm 32 0x020e078c 0x00000030 +wm 32 0x020e0798 0x000c0000 +wm 32 0x020e0768 0x00002000 +wm 32 0x020e0770 0x00000000 +wm 32 0x020e0754 0x00000200 +wm 32 0x020e075c 0x00000200 +wm 32 0x020e0760 0x00000200 +wm 32 0x020e0764 0x00000200 +wm 32 0x020e076c 0x00000200 +wm 32 0x020e0778 0x00000200 +wm 32 0x020e077c 0x00000200 +wm 32 0x020e0780 0x00000200 +wm 32 0x021b001c 0x04008010 +wm 32 0x021b001c 0x04008040 +wm 32 0x021b0800 0xa1390001 +wm 32 0x021b080c 0x001e001e +wm 32 0x021b0810 0x001e001e +wm 32 0x021b480c 0x001e001e +wm 32 0x021b4810 0x001e001e +wm 32 0x021b083c 0x43430349 +wm 32 0x021b0840 0x03330334 +wm 32 0x021b483c 0x434b0351 +wm 32 0x021b4840 0x033d030e +wm 32 0x021b0848 0x40404040 +wm 32 0x021b0850 0x40404040 +wm 32 0x021b4848 0x40404040 +wm 32 0x021b4850 0x40404040 +wm 32 0x021b081c 0x33333333 +wm 32 0x021b0820 0x33333333 +wm 32 0x021b0824 0x33333333 +wm 32 0x021b0828 0x33333333 +wm 32 0x021b481c 0x33333333 +wm 32 0x021b4820 0x33333333 +wm 32 0x021b4824 0x33333333 +wm 32 0x021b4828 0x33333333 +wm 32 0x021b08b8 0x00000800 +wm 32 0x021b48b8 0x00000800 +wm 32 0x021b0018 0x00000742 +check 32 while_all_bits_clear 0x021b0018 0x00000002 +wm 32 0x021b001c 0x00008000 +check 32 while_any_bit_clear 0x021b001c 0x00004000 +wm 32 0x021b0000 0x841a0000 +check 32 while_any_bit_clear 0x021b0018 0x40000000 +wm 32 0x021b000c 0x898f78f4 +wm 32 0x021b0010 0xff328e64 +wm 32 0x021b0014 0x01ff00db +wm 32 0x021b002c 0x000026d2 +wm 32 0x021b0030 0x008f1023 +wm 32 0x021b0008 0x24444040 +wm 32 0x021b0004 0x00020076 +wm 32 0x021b0040 0x00000047 +wm 32 0x021b001c 0x09308030 +wm 32 0x021b001c 0x00048031 +wm 32 0x021b001c 0x00488032 +wm 32 0x021b001c 0x00008033 +wm 32 0x021b0020 0x0000c000 +wm 32 0x021b001c 0x00008020 +wm 32 0x021b0818 0x00022222 +wm 32 0x021b4818 0x00022222 +wm 32 0x021b0890 0x00000003 +set_bits 32 0x021b0400 0x02000000 +wm 32 0x021b0404 0x00000001 +wm 32 0x021b001c 0x04008010 +wm 32 0x021b001c 0x04008040 +wm 32 0x021b0800 0xa1390001 +check 32 while_all_bits_clear 0x021b0800 0x00010000 +wm 32 0x021b0800 0xa1380000 +wm 32 0x021b001c 0x00048033 +wm 32 0x020e05a8 0x00000030 +wm 32 0x020e05b0 0x00000030 +wm 32 0x020e0524 0x00000030 +wm 32 0x020e051c 0x00000030 +wm 32 0x020e0518 0x00000030 +wm 32 0x020e050c 0x00000030 +wm 32 0x020e05b8 0x00000030 +wm 32 0x020e05c0 0x00000030 +wm 32 0x021b001c 0x04008050 +wm 32 0x021b0860 0x00000030 +wm 32 0x021b4860 0x00000030 +check 32 while_all_bits_clear 0x021b0860 0x0000001f +check 32 while_all_bits_clear 0x021b4860 0x0000001f +wm 32 0x021b001c 0x04008050 +wm 32 0x021b0864 0x00000030 +check 32 while_all_bits_clear 0x021b0864 0x0000001f +wm 32 0x021b001c 0x04008050 +wm 32 0x021b4864 0x00000030 +check 32 while_all_bits_clear 0x021b4864 0x0000001f +wm 32 0x021b001c 0x00008033 +wm 32 0x021b0800 0xa138002b +wm 32 0x021b0020 0x00001800 +wm 32 0x021b0404 0x00001000 +wm 32 0x021b0004 0x00025576 +wm 32 0x021b001c 0x00000000 +check 32 while_all_bits_clear 0x021b001c 0x00004000 diff --git a/arch/arm/boards/karo-tx6x/lowlevel.c b/arch/arm/boards/karo-tx6x/lowlevel.c index 1aa24c5..459c44b 100644 --- a/arch/arm/boards/karo-tx6x/lowlevel.c +++ b/arch/arm/boards/karo-tx6x/lowlevel.c @@ -77,3 +77,23 @@ imx6q_barebox_entry(fdt); } + +BAREBOX_IMD_TAG_STRING(tx6x_mx6_memsize_2G, IMD_TYPE_PARAMETER, "memsize=2048", 0); + +ENTRY_FUNCTION(start_imx6q_tx6x_2g, r0, r1, r2) +{ + void *fdt; + + imx6_cpu_lowlevel_init(); + + arm_setup_stack(0x00920000 - 8); + + IMD_USED(tx6x_mx6_memsize_2G); + + if (IS_ENABLED(CONFIG_DEBUG_LL)) + setup_uart(); + + fdt = __dtb_imx6q_tx6q_start - get_runtime_offset(); + + imx6q_barebox_entry(fdt); +} diff --git a/arch/arm/mach-imx/esdctl.c b/arch/arm/mach-imx/esdctl.c index 66ba51c..106e648 100644 --- a/arch/arm/mach-imx/esdctl.c +++ b/arch/arm/mach-imx/esdctl.c @@ -434,7 +434,7 @@ } }; -static struct driver_d imx_serial_driver = { +static struct driver_d imx_esdctl_driver = { .name = "imx-esdctl", .probe = imx_esdctl_probe, .id_table = imx_esdctl_ids, @@ -443,7 +443,7 @@ static int imx_esdctl_init(void) { - return platform_driver_register(&imx_serial_driver); + return platform_driver_register(&imx_esdctl_driver); } mem_initcall(imx_esdctl_init); diff --git a/drivers/mci/imx-esdhc.c b/drivers/mci/imx-esdhc.c index 282887b..2e189fe 100644 --- a/drivers/mci/imx-esdhc.c +++ b/drivers/mci/imx-esdhc.c @@ -41,6 +41,8 @@ #define IMX_SDHCI_WML 0x44 #define IMX_SDHCI_MIXCTRL 0x48 +#define IMX_SDHCI_DLL_CTRL 0x60 +#define IMX_SDHCI_MIX_CTRL_FBCLK_SEL (BIT(25)) struct fsl_esdhc_host { struct mci_host mci; @@ -516,11 +518,23 @@ { void __iomem *regs = host->regs; uint64_t start; + int val; /* reset the controller */ esdhc_write32(regs + SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET, SYSCTL_RSTA); + /* extra register reset for i.MX6 Solo/DualLite */ + if (cpu_is_mx6()) { + /* reset bit FBCLK_SEL */ + val = esdhc_read32(regs + IMX_SDHCI_MIXCTRL); + val &= ~IMX_SDHCI_MIX_CTRL_FBCLK_SEL; + esdhc_write32(regs + IMX_SDHCI_MIXCTRL, val); + + /* reset delay line settings in IMX_SDHCI_DLL_CTRL */ + esdhc_write32(regs + IMX_SDHCI_DLL_CTRL, 0x0); + } + start = get_time_ns(); /* hardware clears the bit when it is done */ while (1) { diff --git a/images/Makefile.imx b/images/Makefile.imx index 6870bce..4caccdb 100644 --- a/images/Makefile.imx +++ b/images/Makefile.imx @@ -293,6 +293,11 @@ FILE_barebox-karo-imx6q-tx6x-1g.img = start_imx6q_tx6x_1g.pblx.imximg image-$(CONFIG_MACH_TX6X) += barebox-karo-imx6q-tx6x-1g.img +pblx-$(CONFIG_MACH_TX6X) += start_imx6q_tx6x_2g +CFG_start_imx6q_tx6x_2g.pblx.imximg = $(board)/karo-tx6x/flash-header-tx6qp-2g.imxcfg +FILE_barebox-karo-imx6qp-tx6x-2g.img = start_imx6q_tx6x_2g.pblx.imximg +image-$(CONFIG_MACH_TX6X) += barebox-karo-imx6qp-tx6x-2g.img + pblx-$(CONFIG_MACH_UDOO) += start_imx6_udoo CFG_start_imx6_udoo.pblx.imximg = $(board)/udoo/flash-header-mx6-udoo.imxcfg FILE_barebox-udoo-imx6q.img = start_imx6_udoo.pblx.imximg diff --git a/scripts/imx/README b/scripts/imx/README index 0d6d0d0..474b387 100644 --- a/scripts/imx/README +++ b/scripts/imx/README @@ -30,6 +30,8 @@ while_all_bits_set, while_any_bit_clear, while_any_bit_set +set_bits set in register +clear_bits clear in register the i.MX SoCs support a wide range of fancy things doing with the flash header. We limit ourselves to a very simple case, that is the flash header has a fixed diff --git a/scripts/imx/imx-image.c b/scripts/imx/imx-image.c index 16f086a..0d315a2 100644 --- a/scripts/imx/imx-image.c +++ b/scripts/imx/imx-image.c @@ -252,8 +252,13 @@ return 0; } -static int write_mem_v1(uint32_t addr, uint32_t val, int width) +static int write_mem_v1(uint32_t addr, uint32_t val, int width, int set_bits, int clear_bits) { + if (set_bits || clear_bits) { + fprintf(stderr, "This SoC does not support setting/clearing bits\n"); + return -EINVAL; + } + if (curdcd > MAX_DCD - 3) { fprintf(stderr, "At maximum %d dcd entried are allowed\n", MAX_DCD); return -ENOMEM; @@ -362,12 +367,20 @@ } } -static int write_mem_v2(uint32_t addr, uint32_t val, int width) +static int write_mem_v2(uint32_t addr, uint32_t val, int width, int set_bits, int clear_bits) { uint32_t cmd; cmd = (TAG_WRITE << 24) | width; + if (set_bits && clear_bits) + return -EINVAL; + + if (set_bits) + cmd |= 3 << 3; + if (clear_bits) + cmd |= 2 << 3; + if (curdcd > MAX_DCD - 3) { fprintf(stderr, "At maximum %d dcd entried are allowed\n", MAX_DCD); return -ENOMEM; @@ -449,13 +462,14 @@ return 0; } -static int write_mem(struct config_data *data, uint32_t addr, uint32_t val, int width) +static int write_mem(struct config_data *data, uint32_t addr, uint32_t val, int width, + int set_bits, int clear_bits) { switch (data->header_version) { case 1: - return write_mem_v1(addr, val, width); + return write_mem_v1(addr, val, width, set_bits, clear_bits); case 2: - return write_mem_v2(addr, val, width); + return write_mem_v2(addr, val, width, set_bits, clear_bits); default: return -EINVAL; } diff --git a/scripts/imx/imx-usb-loader.c b/scripts/imx/imx-usb-loader.c index ed27831..cf9d610 100644 --- a/scripts/imx/imx-usb-loader.c +++ b/scripts/imx/imx-usb-loader.c @@ -412,7 +412,7 @@ #define V(a) (((a) >> 24) & 0xff), (((a) >> 16) & 0xff), (((a) >> 8) & 0xff), ((a) & 0xff) -static int read_memory(unsigned addr, unsigned char *dest, unsigned cnt) +static int read_memory(unsigned addr, void *dest, unsigned cnt) { static unsigned char read_reg_command[] = { 1, @@ -506,6 +506,9 @@ write_reg_command[4] = (unsigned char)(addr >> 8); write_reg_command[5] = (unsigned char)(addr); + if (verbose > 1) + printf("write memory reg: 0x%08x val: 0x%08x width: %d\n", addr, val, width); + switch (width) { case 1: ds = 0x8; @@ -556,6 +559,31 @@ return err; } +static int modify_memory(unsigned addr, unsigned val, int width, int set_bits, int clear_bits) +{ + int err; + + if (set_bits || clear_bits) { + uint32_t r; + + err = read_memory(addr, &r, 4); + if (err < 0) + return err; + + if (verbose > 1) + printf("reg 0x%08x val: 0x%08x %s0x%08x\n", addr, r, + set_bits ? "|= " : "&= ~", val); + + if (set_bits) + r |= val; + if (clear_bits) + r &= ~val; + val = r; + } + + return write_memory(addr, val, 4); +} + static int load_file(void *buf, unsigned len, unsigned dladdr, unsigned char type) { static unsigned char dl_command[] = { @@ -682,15 +710,24 @@ while (dcd < dcd_end) { unsigned s_length = (dcd[1] << 8) + dcd[2]; unsigned char *s_end = dcd + s_length; + int set_bits = 0, clear_bits = 0; - printf("sub dcd length %x\n", s_length); + printf("command: 0x%02x sub dcd length: 0x%04x, flags: 0x%02x\n", dcd[0], s_length, dcd[3]); - if ((dcd[0] != 0xcc) || (dcd[3] != 0x04)) { + if ((dcd[0] != 0xcc)) { printf("Skipping unknown sub tag 0x%02x with len %04x\n", dcd[0], s_length); usleep(50000); dcd += s_length; continue; } + + if (dcd[3] & PARAMETER_FLAG_MASK) { + if (dcd[3] & PARAMETER_FLAG_SET) + set_bits = 1; + else + clear_bits = 1; + } + dcd += 4; if (s_end > dcd_end) { @@ -703,9 +740,8 @@ unsigned val = (dcd[4] << 24) | (dcd[5] << 16) | (dcd[6] << 8) | dcd[7]; dcd += 8; - err = write_memory(addr, val, 4); - if (err < 0) - return err; + + modify_memory(addr, val, 4, set_bits, clear_bits); } } return err; @@ -1203,11 +1239,10 @@ return ret; } -static int write_mem(struct config_data *data, uint32_t addr, uint32_t val, int width) +static int write_mem(struct config_data *data, uint32_t addr, uint32_t val, int width, + int set_bits, int clear_bits) { - printf("wr 0x%08x 0x%08x\n", addr, val); - - return write_memory(addr, val, width); + return modify_memory(addr, val, width, set_bits, clear_bits); } static int parse_initfile(const char *filename) diff --git a/scripts/imx/imx.c b/scripts/imx/imx.c index ca65389..70936ba 100644 --- a/scripts/imx/imx.c +++ b/scripts/imx/imx.c @@ -130,7 +130,8 @@ return data->check(data, cmd, addr, mask); } -static int do_cmd_write_mem(struct config_data *data, int argc, char *argv[]) +static int write_mem(struct config_data *data, int argc, char *argv[], + int set_bits, int clear_bits) { uint32_t addr, val, width; char *end; @@ -170,7 +171,22 @@ return -EINVAL; }; - return data->write_mem(data, addr, val, width); + return data->write_mem(data, addr, val, width, set_bits, clear_bits); +} + +static int do_cmd_write_mem(struct config_data *data, int argc, char *argv[]) +{ + return write_mem(data, argc, argv, 0, 0); +} + +static int do_cmd_set_bits(struct config_data *data, int argc, char *argv[]) +{ + return write_mem(data, argc, argv, 1, 0); +} + +static int do_cmd_clear_bits(struct config_data *data, int argc, char *argv[]) +{ + return write_mem(data, argc, argv, 0, 1); } static int do_loadaddr(struct config_data *data, int argc, char *argv[]) @@ -338,6 +354,12 @@ .name = "wm", .parse = do_cmd_write_mem, }, { + .name = "set_bits", + .parse = do_cmd_set_bits, + }, { + .name = "clear_bits", + .parse = do_cmd_clear_bits, + }, { .name = "check", .parse = do_cmd_check, }, { diff --git a/scripts/imx/imx.h b/scripts/imx/imx.h index 85071b4..a136958 100644 --- a/scripts/imx/imx.h +++ b/scripts/imx/imx.h @@ -31,6 +31,8 @@ #define TAG_DCD_HEADER 0xd2 #define DCD_VERSION 0x40 #define TAG_WRITE 0xcc +#define PARAMETER_FLAG_MASK (1 << 3) +#define PARAMETER_FLAG_SET (1 << 4) #define TAG_CHECK 0xcf struct imx_ivt_header { @@ -64,7 +66,8 @@ int header_version; int cpu_type; int (*check)(struct config_data *data, uint32_t cmd, uint32_t addr, uint32_t mask); - int (*write_mem)(struct config_data *data, uint32_t addr, uint32_t val, int width); + int (*write_mem)(struct config_data *data, uint32_t addr, uint32_t val, int width, + int set_bits, int clear_bits); int csf_space; char *csf; };