diff --git a/Documentation/boards/mxs.rst b/Documentation/boards/mxs.rst index feb0242..53de4c1 100644 --- a/Documentation/boards/mxs.rst +++ b/Documentation/boards/mxs.rst @@ -3,71 +3,83 @@ Freescale i.MXs or MXS are a SoC family which consists of the i.MX23 and the i.MX28. These are quite different from the regular i.MX SoCs -and thus are represented by their own architecture in both the Kernel -and barebox. +and thus are represented by their own architecture in both the kernel +and in barebox. Bootlets -------- -Traditionally These SoCs need the Freescale bootlets source and the -elf2sb2 binary to build a bootable image out of the barebox binary. -Since the bootlets are board specific and the source code is only -hardly customisable each vendor usually has his own slightly different +Traditionally these SoCs need the Freescale bootlets source and the +*elf2sb2* binary to set up the PMIC and SDRAM, and to build a bootable +image out of the barebox binary. +Since the bootlets are board-specific and the source code is only +hardly customisable, each vendor usually has their own slightly different version of the bootlets. Booting with the Freescale bootlets is not -described here, refer to the bootlet sourcecode or your vendors +described here, refer to the bootlet source code or your vendor's documentation instead. -U-Boot and barebox have a port of the bootlets integrated into their -source. The barebox bootlet code is derived from the U-Boot bootlet -code written by Marek Vasut. +Barebox has a port of the bootlets integrated into its source, which is +derived from the U-Boot bootlet code written by Marek Vasut. -Currently only the Karo TX28 is supported by the barebox bootlets, -but we recommend that this approach should be followed for new boards -and existing boards should be ported over. +Most MXS boards in the barebox tree have been ported to use barebox bootlets and +image generation, and we recommend this approach for new boards too. Booting Freescale i.MXs ----------------------- The Freescale MXS SoCs have a multi staged boot process which needs different images composed out of different binaries. The ROM executes -a so called bootstream which contains multiple executables. The first -one is executed in SRAM and the purpose of this binary is to setup -the internal PMIC and the SDRAM. The second image is usually the -bootloader itself. In case of barebox the bootstream is composed -out of the self extracting barebox image (pblx) and the prepare -stage for setting up the SDRAM. +a so called *bootstream* which can contain multiple executables. + +The first executable (the prepare stage) is only a small binary executed in +SRAM, which has a limited size of 128 KB. Its purpose is to setup the internal +PMIC and the SDRAM, and then jump back to the MXS ROM code, which then maps the +second executable (the full bootloader) into SDRAM and executes it. +In case of barebox, the bootstream (``*-bootstream.img``) is composed of the +self extracting barebox image (``*.pblx``) and the prepare stage +(``prep_*.pblb``). The file name of those images reflects the name of the +respective entry points. The bootstream image itself is useful for USB boot, but for booting from SD cards or NAND a BCB header has to be prepended to the image. In case -of SD boot the image has the .mxssd file extension in barebox. +of SD boot the image is named ``*-sd.img``. -Since the bootstream images are encrypted they are not suitable for -2nd stage execution. For this purpose the 2nd stage images are generated. +Bootstream images can be unencrypted or encrypted. Depending on the OCOTP fuses +of your chip, you might need the one or the other to boot the board. + +Since some of the bootstream images are encrypted, they are not suitable for +2nd stage execution. For this purpose a 2nd stage image with the name +``*-2nd.img`` is generated. Booting from USB ---------------- -barebox has the mxs-usb-loader tool (derived from the sbloader tool from -the rockbox project). If the board is connected to the PC and started in -USB Boot mode it should show up in lsusb:: +If enabled in *menuconfig* → *System Type*, barebox builds the *imx-usb-loader* +tool (derived from the *sbloader* tool from the rockbox project), which can +load images onto MXS SoCs over USB. (Refer to the documentation of your board +how to get it into USB boot mode.) + +If the board is connected to the PC and started in USB boot mode, it should +show up in lsusb:: Bus 001 Device 098: ID 15a2:004f Freescale Semiconductor, Inc. i.MX28 SystemOnChip in RecoveryMode -The bootstream images can be directly booted with:: +The bootstream images can then directly be booted with:: - ./scripts/mxs-usb-loader 0 images/barebox-karo-tx28-bootstream.img + ./scripts/imx-usb-loader images/barebox-karo-tx28-bootstream.img -You might require appropriate udev rules or sudo to gain the rights to +You might require appropriate udev rules or *sudo* to gain the rights to access the USB device. Booting from SD cards --------------------- -The SD images are suitable for booting from SD cards. SD cards need a special -partitioning which can be created with the following fdisk sequence (using -/dev/sdg as example):: +The SD images are suitable for booting from SD cards. The MXS SoCs require a +special partition of type 0x53 (OnTrack DM6 Aux) which contains the BCB header. +The partitioning can be created with the following fdisk sequence (using +*/dev/sdg* as an example for the SD card):: - fdisk /dev/sdg + $ fdisk /dev/sdg Welcome to fdisk (util-linux 2.25.1). Changes will remain in memory only, until you decide to write them. @@ -93,24 +105,21 @@ Hex code (type L to list all codes): 53 Changed type of partition 'Linux' to 'OnTrack DM6 Aux3'. - Command (m for help): - Command (m for help): w -After writing the new partition table the image can be written directly to -the partition:: +After writing the new partition table, the image can be written directly to +the first partition:: cat images/barebox-karo-tx28-sd.img > /dev/sdg1 -** NOTE ** +.. note:: -The MXS SoCs require a special partition of type 0x53 (OnTrack DM6 Aux) -which contains the BCB header. For some unknown reason the BCB header is -inside a partition, but contains the sector number of the raw device from -which the rest of the image is read. With standard settings booting from -SD card only works if the partition containing the bootloader starts at -sector 2048 (the standard for fdisk). See the -p parameter to the mxsboot -tool which changes this sector number in the image. + For some unknown reason the BCB header is + inside a partition, but contains the sector number of the raw device from + which the rest of the image is read. With standard settings, booting from + SD card only works if the partition containing the bootloader starts at + sector 2048 (the standard for fdisk). See the *-p* parameter to the + ``scripts/mxsboot`` tool to change this sector number in the image. Booting second stage -------------------- diff --git a/arch/arm/boards/chumby_falconwing/falconwing.c b/arch/arm/boards/chumby_falconwing/falconwing.c index c866043..5554b78 100644 --- a/arch/arm/boards/chumby_falconwing/falconwing.c +++ b/arch/arm/boards/chumby_falconwing/falconwing.c @@ -258,14 +258,6 @@ GPMI_RDY3_GPIO | GPIO_IN | PULLUP(1), }; -static int falconwing_mem_init(void) -{ - arm_add_mem_device("ram0", IMX_MEMORY_BASE, 64 * 1024 * 1024); - - return 0; -} -mem_initcall(falconwing_mem_init); - #define GPIO_USB_HUB_RESET 29 #define GPIO_USB_HUB_POWER 26 diff --git a/arch/arm/boards/crystalfontz-cfa10036/cfa10036.c b/arch/arm/boards/crystalfontz-cfa10036/cfa10036.c index 947db7c..dcf5604 100644 --- a/arch/arm/boards/crystalfontz-cfa10036/cfa10036.c +++ b/arch/arm/boards/crystalfontz-cfa10036/cfa10036.c @@ -89,30 +89,6 @@ .udelay = 5, /* ~100 kHz */ }; -void v5_mmu_cache_flush(void); -long cfa10036_get_ram_size(void) -{ - volatile u32 *base = (void *)IMX_MEMORY_BASE; - volatile u32 *ofs = base + SZ_128M / sizeof(u32); - - *base = *ofs = 0xdeadbeef; - *ofs = 0xbaadcafe; - - v5_mmu_cache_flush(); - if (*base == 0xbaadcafe) - return SZ_128M; - else - return SZ_256M; -} - -static int cfa10036_mem_init(void) -{ - arm_add_mem_device("ram0", IMX_MEMORY_BASE, cfa10036_get_ram_size()); - - return 0; -} -mem_initcall(cfa10036_mem_init); - static int cfa10036_devices_init(void) { int i; diff --git a/arch/arm/boards/duckbill/lowlevel.c b/arch/arm/boards/duckbill/lowlevel.c index 2922e40..22987a6 100644 --- a/arch/arm/boards/duckbill/lowlevel.c +++ b/arch/arm/boards/duckbill/lowlevel.c @@ -51,11 +51,14 @@ pr_debug("initializing power...\n"); - mx28_power_init(0, 0, 1); + mx28_power_init(POWER_USE_5V, &mx28_power_default); pr_debug("initializing SDRAM...\n"); - mx28_mem_init(mx28_dram_vals_default); + /* EMI_CLK of 480 / 2 * (18/21) = 205.7 MHz */ + mxs_mem_init_clock(2, 21); + mx28_mem_init(PINCTRL_EMI_DS_CTRL_DDR_MODE_DDR2, + mx28_dram_vals_default); pr_debug("DONE\n"); } diff --git a/arch/arm/boards/freescale-mx23-evk/mx23-evk.c b/arch/arm/boards/freescale-mx23-evk/mx23-evk.c index dd80488..a3587db 100644 --- a/arch/arm/boards/freescale-mx23-evk/mx23-evk.c +++ b/arch/arm/boards/freescale-mx23-evk/mx23-evk.c @@ -53,14 +53,6 @@ }; #endif -static int mx23_evk_mem_init(void) -{ - arm_add_mem_device("ram0", IMX_MEMORY_BASE, 32 * 1024 * 1024); - - return 0; -} -mem_initcall(mx23_evk_mem_init); - /** * Try to register an environment storage on the attached MCI card * @return 0 on success diff --git a/arch/arm/boards/freescale-mx28-evk/lowlevel.c b/arch/arm/boards/freescale-mx28-evk/lowlevel.c index 4d45a03..22cae13 100644 --- a/arch/arm/boards/freescale-mx28-evk/lowlevel.c +++ b/arch/arm/boards/freescale-mx28-evk/lowlevel.c @@ -43,11 +43,15 @@ pr_debug("initializing power...\n"); - mx28_power_init(0, 1, 0); + mx28_power_init(POWER_USE_BATTERY_INPUT | POWER_ENABLE_4P2, + &mx28_power_default); pr_debug("initializing SDRAM...\n"); - mx28_mem_init(mx28_dram_vals_default); + /* EMI_CLK of 480 / 2 * (18/21) = 205.7 MHz */ + mxs_mem_init_clock(2, 21); + mx28_mem_init(PINCTRL_EMI_DS_CTRL_DDR_MODE_DDR2, + mx28_dram_vals_default); pr_debug("DONE\n"); } diff --git a/arch/arm/boards/freescale-mx28-evk/mx28-evk.c b/arch/arm/boards/freescale-mx28-evk/mx28-evk.c index 9e5d612..06a2c21 100644 --- a/arch/arm/boards/freescale-mx28-evk/mx28-evk.c +++ b/arch/arm/boards/freescale-mx28-evk/mx28-evk.c @@ -232,14 +232,6 @@ .enable = mx28_evk_fb_enable, }; -static int mx28_evk_mem_init(void) -{ - arm_add_mem_device("ram0", IMX_MEMORY_BASE, 128 * 1024 * 1024); - - return 0; -} -mem_initcall(mx28_evk_mem_init); - static const struct spi_board_info mx28evk_spi_board_info[] = { { .name = "m25p80", diff --git a/arch/arm/boards/imx233-olinuxino/imx23-olinuxino.c b/arch/arm/boards/imx233-olinuxino/imx23-olinuxino.c index b87a676..c06779d 100644 --- a/arch/arm/boards/imx233-olinuxino/imx23-olinuxino.c +++ b/arch/arm/boards/imx233-olinuxino/imx23-olinuxino.c @@ -40,14 +40,6 @@ .f_min = 400000, }; -static int imx23_olinuxino_mem_init(void) -{ - arm_add_mem_device("ram0", IMX_MEMORY_BASE, 64 * 1024 * 1024); - - return 0; -} -mem_initcall(imx23_olinuxino_mem_init); - static void olinuxino_init_usb(void) { imx23_usb_phy_enable(); diff --git a/arch/arm/boards/imx233-olinuxino/lowlevel.c b/arch/arm/boards/imx233-olinuxino/lowlevel.c index 63a6523..5f36c17 100644 --- a/arch/arm/boards/imx233-olinuxino/lowlevel.c +++ b/arch/arm/boards/imx233-olinuxino/lowlevel.c @@ -154,11 +154,13 @@ pr_debug("initializing power...\n"); - mx23_power_init(0, 0, 1); + mx23_power_init(POWER_USE_5V, &mx23_power_default); pr_debug("initializing SDRAM...\n"); imx23_olinuxino_adjust_memory_params(mx23_dram_vals); + /* EMI_CLK of 480 / 2 * (18/33) = 130.90 MHz */ + mxs_mem_init_clock(2, 33); mx23_mem_init(); pr_debug("DONE\n"); diff --git a/arch/arm/boards/karo-tx28/lowlevel.c b/arch/arm/boards/karo-tx28/lowlevel.c index d072637..1a93be7 100644 --- a/arch/arm/boards/karo-tx28/lowlevel.c +++ b/arch/arm/boards/karo-tx28/lowlevel.c @@ -43,11 +43,15 @@ pr_debug("initializing power...\n"); - mx28_power_init(0, 1, 0); + mx28_power_init(POWER_USE_BATTERY_INPUT | POWER_ENABLE_4P2, + &mx28_power_default); pr_debug("initializing SDRAM...\n"); - mx28_mem_init(mx28_dram_vals_default); + /* EMI_CLK of 480 / 2 * (18/21) = 205.7 MHz */ + mxs_mem_init_clock(2, 21); + mx28_mem_init(PINCTRL_EMI_DS_CTRL_DDR_MODE_DDR2, + mx28_dram_vals_default); pr_debug("DONE\n"); } diff --git a/arch/arm/boards/karo-tx28/tx28.c b/arch/arm/boards/karo-tx28/tx28.c index 26dbc00..47cac21 100644 --- a/arch/arm/boards/karo-tx28/tx28.c +++ b/arch/arm/boards/karo-tx28/tx28.c @@ -73,14 +73,6 @@ extern void base_board_init(void); -static int tx28_mem_init(void) -{ - arm_add_mem_device("ram0", IMX_MEMORY_BASE, 128 * 1024 * 1024); - - return 0; -} -mem_initcall(tx28_mem_init); - static int tx28_devices_init(void) { int i; diff --git a/arch/arm/mach-mxs/include/mach/imx23.h b/arch/arm/mach-mxs/include/mach/imx23.h new file mode 100644 index 0000000..56e76d5 --- /dev/null +++ b/arch/arm/mach-mxs/include/mach/imx23.h @@ -0,0 +1,29 @@ +#ifndef __MACH_IMX23_H +#define __MACH_IMX23_H + +#include +#include + +#define DRAM_CTL14_CS0_EN BIT(0) +#define DRAM_CTL14_CS1_EN BIT(1) +#define DRAM_CTL11_COLUMNS_DIFF GENMASK(10, 8) +#define DRAM_CTL10_ROWS_DIFF GENMASK(18, 16) + +#define DRAM_CTL(n) (IMX_SDRAMC_BASE + 4 * (n)) + +static inline u32 imx23_get_memsize(void) +{ + u32 ctl10 = readl(DRAM_CTL(10)); + u32 ctl11 = readl(DRAM_CTL(11)); + u32 ctl14 = readl(DRAM_CTL(14)); + int rows, columns, banks = 4, cs0, cs1; + + columns = 12 - FIELD_GET(DRAM_CTL11_COLUMNS_DIFF, ctl11); + rows = 13 - FIELD_GET(DRAM_CTL10_ROWS_DIFF, ctl10); + cs0 = FIELD_GET(DRAM_CTL14_CS0_EN, ctl14); + cs1 = FIELD_GET(DRAM_CTL14_CS1_EN, ctl14); + + return (1 << columns) * (1 << rows) * banks * (cs0 + cs1); +} + +#endif /* __MACH_IMX23_H */ \ No newline at end of file diff --git a/arch/arm/mach-mxs/include/mach/imx28.h b/arch/arm/mach-mxs/include/mach/imx28.h new file mode 100644 index 0000000..5816625 --- /dev/null +++ b/arch/arm/mach-mxs/include/mach/imx28.h @@ -0,0 +1,30 @@ +#ifndef __MACH_IMX28_H +#define __MACH_IMX28_H + +#include +#include + +#define DRAM_CTL29_CS0_EN BIT(24) +#define DRAM_CTL29_CS1_EN BIT(25) +#define DRAM_CTL29_COLUMNS_DIFF GENMASK(18, 16) +#define DRAM_CTL29_ROWS_DIFF GENMASK(10, 8) +#define DRAM_CTL31_EIGHT_BANKS BIT(16) + +#define DRAM_CTL(n) (IMX_SDRAMC_BASE + 4 * (n)) + +static inline u32 imx28_get_memsize(void) +{ + u32 ctl29 = readl(DRAM_CTL(29)); + u32 ctl31 = readl(DRAM_CTL(31)); + int rows, columns, banks, cs0, cs1; + + columns = 12 - FIELD_GET(DRAM_CTL29_COLUMNS_DIFF, ctl29); + rows = 15 - FIELD_GET(DRAM_CTL29_ROWS_DIFF, ctl29); + banks = FIELD_GET(DRAM_CTL31_EIGHT_BANKS, ctl31) ? 8 : 4; + cs0 = FIELD_GET(DRAM_CTL29_CS0_EN, ctl29); + cs1 = FIELD_GET(DRAM_CTL29_CS1_EN, ctl29); + + return (1 << columns) * (1 << rows) * banks * (cs0 + cs1); +} + +#endif /* __MACH_IMX28_H */ \ No newline at end of file diff --git a/arch/arm/mach-mxs/include/mach/init.h b/arch/arm/mach-mxs/include/mach/init.h index 6526d30..53c1e05 100644 --- a/arch/arm/mach-mxs/include/mach/init.h +++ b/arch/arm/mach-mxs/include/mach/init.h @@ -12,20 +12,61 @@ void mxs_early_delay(int delay); -void mx23_power_init(int __has_battery, int __use_battery_input, - int __use_5v_input); -void mx28_power_init(int __has_battery, int __use_battery_input, - int __use_5v_input); +/** + * Power configuration of the system: + * - POWER_USE_5V: use 5V input as power supply + * - POWER_USE_BATTERY: use battery input when the system is supplied by a battery + * - POWER_USE_BATTERY_INPUT: use battery input when the system is supplied by + * a DC source (instead of a real battery) on the battery input + * - POWER_ENABLE_4P2: power up the 4P2 regulator (implied for POWER_USE_5V) + */ +enum mxs_power_config { + POWER_USE_5V = 0b00000000, + POWER_USE_BATTERY = 0b00000001, + POWER_USE_BATTERY_INPUT = 0b00000010, + POWER_ENABLE_4P2 = 0b00000100, +}; +extern int power_config; +static inline enum mxs_power_config mxs_power_config_get_use(void) { + return (power_config & 0b00000011); +} + + +struct mxs_power_ctrl { + uint32_t target; /*< target voltage */ + uint32_t brownout; /*< brownout threshhold */ +}; +struct mxs_power_ctrls { + struct mxs_power_ctrl * vdda; /*< if non-null, set values for VDDA */ + struct mxs_power_ctrl * vddd; /*< if non-null, set values for VDDD */ + struct mxs_power_ctrl * vddio; /*< if non-null, set values for VDDIO */ + struct mxs_power_ctrl * vddmem; /*< if non-null, set values for VDDMEM */ +}; + +extern struct mxs_power_ctrl mxs_vddio_default; +extern struct mxs_power_ctrl mxs_vddd_default; +extern struct mxs_power_ctrl mxs_vdda_default; +extern struct mxs_power_ctrl mx23_vddmem_default; +extern struct mxs_power_ctrls mx23_power_default; +extern struct mxs_power_ctrls mx28_power_default; + +void mx23_power_init(const int config, struct mxs_power_ctrls *ctrls); +void mx28_power_init(const int config, struct mxs_power_ctrls *ctrls); void mxs_power_wait_pswitch(void); extern const uint32_t mx28_dram_vals_default[190]; extern uint32_t mx23_dram_vals[]; +#define PINCTRL_EMI_DS_CTRL_DDR_MODE_LPDDR1 (0b00 << 16) +#define PINCTRL_EMI_DS_CTRL_DDR_MODE_LVDDR2 (0b10 << 16) +#define PINCTRL_EMI_DS_CTRL_DDR_MODE_DDR2 (0b11 << 16) + void mx23_mem_init(void); -void mx28_mem_init(const uint32_t dram_vals[190]); +void mx28_mem_init(const int emi_ds_ctrl_ddr_mode, + const uint32_t dram_vals[190]); void mxs_mem_setup_cpu_and_hbus(void); void mxs_mem_setup_vdda(void); -void mxs_mem_init_clock(unsigned char divider); +void mxs_mem_init_clock(const uint8_t clk_emi_div, const uint8_t clk_emi_frac); void mxs_lradc_init(void); void mxs_lradc_enable_batt_measurement(void); diff --git a/arch/arm/mach-mxs/mem-init.c b/arch/arm/mach-mxs/mem-init.c index ac8bfee..568db81 100644 --- a/arch/arm/mach-mxs/mem-init.c +++ b/arch/arm/mach-mxs/mem-init.c @@ -192,7 +192,12 @@ writel((1 << 24), IMX_SDRAMC_BASE + (4 * 8)); } -void mxs_mem_init_clock(unsigned char divider) +/** + * Set up the EMI clock. + * @clk_emi_div: integer divider (prescaler), the DIV_EMI field in HW_CLKCTRL_EMI + * @clk_emi_frac: fractional divider, the EMIFRAC field in HW_CLKCTRL_FRAC0 + */ +void mxs_mem_init_clock(const uint8_t clk_emi_div, const uint8_t clk_emi_frac) { struct mxs_clkctrl_regs *clkctrl_regs = (struct mxs_clkctrl_regs *)IMX_CCM_BASE; @@ -202,7 +207,7 @@ &clkctrl_regs->hw_clkctrl_frac0_set[CLKCTRL_FRAC0_EMI]); /* Set fractional divider for ref_emi */ - writeb(CLKCTRL_FRAC_CLKGATE | (divider & CLKCTRL_FRAC_FRAC_MASK), + writeb(CLKCTRL_FRAC_CLKGATE | (clk_emi_frac & CLKCTRL_FRAC_FRAC_MASK), &clkctrl_regs->hw_clkctrl_frac0[CLKCTRL_FRAC0_EMI]); /* Ungate EMI clock */ @@ -211,8 +216,8 @@ mxs_early_delay(11000); - /* Set EMI clock divider for EMI clock to 411 / 2 = 205MHz */ - writel((2 << CLKCTRL_EMI_DIV_EMI_OFFSET) | + /* Set EMI clock prescaler */ + writel(((clk_emi_div & CLKCTRL_EMI_DIV_EMI_MASK) << CLKCTRL_EMI_DIV_EMI_OFFSET) | (1 << CLKCTRL_EMI_DIV_XTAL_OFFSET), &clkctrl_regs->hw_clkctrl_emi); @@ -273,9 +278,6 @@ { mxs_early_delay(11000); - /* Fractional divider for ref_emi is 33 ; 480 * 18 / 33 = 266MHz */ - mxs_mem_init_clock(33); - /* * Reset/ungate the EMI block. This is essential, otherwise the system * suffers from memory instability. This thing is mx23 specific and is @@ -318,18 +320,12 @@ mxs_mem_setup_cpu_and_hbus(); } -#define PINCTRL_EMI_DS_CTRL_DDR_MODE_DDR2 (0x3 << 16) - -void mx28_mem_init(const uint32_t dram_vals[190]) +void mx28_mem_init(const int emi_ds_ctrl_ddr_mode, const uint32_t dram_vals[190]) { mxs_early_delay(11000); - /* Fractional divider for ref_emi is 21 ; 480 * 18 / 21 = 411MHz */ - mxs_mem_init_clock(21); - - /* Set DDR2 mode */ - writel(PINCTRL_EMI_DS_CTRL_DDR_MODE_DDR2, - IMX_IOMUXC_BASE + 0x1b80); + /* Set DDR mode */ + writel(emi_ds_ctrl_ddr_mode, IMX_IOMUXC_BASE + 0x1b80); /* * Configure the DRAM registers diff --git a/arch/arm/mach-mxs/power-init.c b/arch/arm/mach-mxs/power-init.c index 595b51c..ca7c349 100644 --- a/arch/arm/mach-mxs/power-init.c +++ b/arch/arm/mach-mxs/power-init.c @@ -24,21 +24,7 @@ #include #include -/* - * has_battery - true when this board has a battery. - */ -static int has_battery; - -/* - * use_battery_input - true when this board is supplied from the - * battery input, but has a DC source instead of a real battery - */ -static int use_battery_input; - -/* - * use_5v_input - true when this board can use the 5V input - */ -static int use_5v_input; +int power_config; static void mxs_power_status(void) { @@ -51,27 +37,30 @@ uint32_t vddd = readl(&power_regs->hw_power_vdddctrl); uint32_t vddmem = readl(&power_regs->hw_power_vddmemctrl); - printf("vddio: %dmV (BO -%dmV), Linreg enabled, Linreg offset: %d, FET %sabled\n", - (vddio & 0x1f) * 50 + 2800, - ((vddio >> 8) & 0x7) * 50, - linregofs[((vdda >> 12) & 0x3)], - (vddio & (1 << 16)) ? "dis" : "en"); - printf("vdda: %dmV (BO -%dmV), Linreg %sabled, Linreg offset: %d, FET %sabled\n", - (vdda & 0x1f) * 25 + 1500, - ((vdda >> 8) & 0x7) * 25, - (vdda & (1 << 17)) ? "en" : "dis", - linregofs[((vdda >> 12) & 0x3)], - (vdda & (1 << 16)) ? "dis" : "en"); - printf("vddd: %dmV (BO -%dmV), Linreg %sabled, Linreg offset: %d, FET %sabled\n", - (vddd & 0x1f) * 25 + 800, - ((vddd >> 8) & 0x7) * 25, - (vddd & (1 << 21)) ? "en" : "dis", - linregofs[((vdda >> 16) & 0x3)], - (vdda & (1 << 20)) ? "dis" : "en"); - printf("vddmem: %dmV (BO -%dmV), Linreg %sabled\n", - (vddmem & 0x1f) * 25 + 1100, - ((vddmem >> 5) & 0x7) * 25, - (vddmem & (1 << 8)) ? "en" : "dis"); +#define __REG_BITS(value, fieldname) (((value) & fieldname##_MASK) >> fieldname##_OFFSET) + + printf("vddio: %4dmV (BO -%3dmV), Linreg enabled, Linreg offset: %1d, FET %sabled\n", + __REG_BITS(vddio, POWER_VDDIOCTRL_TRG) * 50 + 2800, + __REG_BITS(vddio, POWER_VDDIOCTRL_BO_OFFSET) * 50, + linregofs[__REG_BITS(vddio, POWER_VDDIOCTRL_LINREG_OFFSET)], + (vddio & POWER_VDDIOCTRL_DISABLE_FET) ? "dis" : " en"); + printf("vdda: %4dmV (BO -%3dmV), Linreg %sabled, Linreg offset: %1d, FET %sabled\n", + __REG_BITS(vdda, POWER_VDDACTRL_TRG) * 25 + 1500, + __REG_BITS(vdda, POWER_VDDACTRL_BO_OFFSET) * 25, + (vdda & POWER_VDDACTRL_ENABLE_LINREG) ? " en" : "dis", + linregofs[__REG_BITS(vdda, POWER_VDDACTRL_LINREG_OFFSET)], + (vdda & POWER_VDDACTRL_DISABLE_FET) ? "dis" : " en"); + printf("vddd: %4dmV (BO -%3dmV), Linreg %sabled, Linreg offset: %1d, FET %sabled\n", + __REG_BITS(vddd, POWER_VDDDCTRL_TRG) * 25 + 800, + __REG_BITS(vddd, POWER_VDDDCTRL_BO_OFFSET) * 25, + (vddd & POWER_VDDDCTRL_ENABLE_LINREG) ? " en" : "dis", + linregofs[__REG_BITS(vddd, POWER_VDDDCTRL_LINREG_OFFSET)], + (vddd & POWER_VDDDCTRL_DISABLE_FET) ? "dis" : " en"); + printf("vddmem: %4dmV (BO -%3dmV), Linreg %sabled\n", + __REG_BITS(vddmem, POWER_VDDMEMCTRL_TRG) * 25 + 1100, + /* Note: this area is reserved on i.MX23, yielding 0: */ + __REG_BITS(vddmem, MX28_POWER_VDDMEMCTRL_BO_OFFSET) * 25, + (vddmem & POWER_VDDMEMCTRL_ENABLE_LINREG) ? " en" : "dis"); } /* @@ -514,7 +503,8 @@ POWER_5VCTRL_HEADROOM_ADJ_MASK, 0x4 << POWER_5VCTRL_HEADROOM_ADJ_OFFSET); - if (has_battery || use_battery_input) + if (mxs_power_config_get_use() == POWER_USE_BATTERY || + mxs_power_config_get_use() == POWER_USE_BATTERY_INPUT) dropout_ctrl = POWER_DCDC4P2_DROPOUT_CTRL_SRC_SEL; else dropout_ctrl = POWER_DCDC4P2_DROPOUT_CTRL_SRC_4P2; @@ -730,7 +720,8 @@ POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK, 0x8 << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET); - mxs_power_enable_4p2(); + if (power_config & POWER_ENABLE_4P2) + mxs_power_enable_4p2(); } /** @@ -1078,7 +1069,7 @@ { struct mxs_power_regs *power_regs = (struct mxs_power_regs *)IMX_POWER_BASE; - uint32_t cur_target, diff, bo_int = 0; + uint32_t cur_target, diff, prev_bo_enirq = 0; uint32_t powered_by_linreg = 0; int adjust_up, tmp; @@ -1094,9 +1085,11 @@ powered_by_linreg = cfg->powered_by_linreg(); if (adjust_up && cfg->bo_irq) { + /* temporarily disable brownout to prevent it from taking + effect prematurely during the adjustment */ if (powered_by_linreg) { - bo_int = readl(cfg->reg); - clrbits_le32(cfg->reg, cfg->bo_enirq); + prev_bo_enirq = readl(&power_regs->hw_power_ctrl) & cfg->bo_enirq; + writel(cfg->bo_enirq, &power_regs->hw_power_ctrl_clr); } setbits_le32(cfg->reg, cfg->bo_offset_mask); } @@ -1136,9 +1129,11 @@ if (cfg->bo_irq) { if (adjust_up && powered_by_linreg) { + /* clear brownout IRQ flag in case it fired */ writel(cfg->bo_irq, &power_regs->hw_power_ctrl_clr); - if (bo_int & cfg->bo_enirq) - setbits_le32(cfg->reg, cfg->bo_enirq); + if (prev_bo_enirq) + /* re-enable brownout IRQ after adjustment has finished */ + writel(cfg->bo_enirq, &power_regs->hw_power_ctrl_set); } clrsetbits_le32(cfg->reg, cfg->bo_offset_mask, @@ -1177,21 +1172,32 @@ writel(MX23_POWER_CTRL_CLKGATE, &power_regs->hw_power_ctrl_clr); } +struct mxs_power_ctrl mxs_vddd_default = { .target = 1500, .brownout = 1325 }; +struct mxs_power_ctrl mxs_vdda_default = { .target = 1800, .brownout = 1650 }; +struct mxs_power_ctrl mxs_vddio_default = { .target = 3300, .brownout = 3150 }; +struct mxs_power_ctrl mx23_vddmem_default = { .target = 2500, .brownout = 1700 }; +struct mxs_power_ctrls mx23_power_default = { + .vdda = &mxs_vdda_default, + .vddd = &mxs_vddd_default, + .vddio = &mxs_vddio_default, + .vddmem = &mx23_vddmem_default, +}; + /** * mx23_power_init() - The power block init main function * * This function calls all the power block initialization functions in * proper sequence to start the power block. + * + * @config: see enum mxs_power_config for possible options + * @ctrls: a mxs_power_ctrls struct, or use &mx23_power_default for default values */ -void mx23_power_init(int __has_battery, int __use_battery_input, - int __use_5v_input) +void mx23_power_init(const int config, struct mxs_power_ctrls *ctrls) { struct mxs_power_regs *power_regs = (struct mxs_power_regs *)IMX_POWER_BASE; - has_battery = __has_battery; - use_battery_input = __use_battery_input; - use_5v_input = __use_5v_input; + power_config = config; mx23_ungate_power(); @@ -1204,11 +1210,11 @@ mxs_src_power_init(); - if (has_battery) + if (mxs_power_config_get_use() == POWER_USE_BATTERY) mxs_power_configure_power_source(); - else if (use_battery_input) + else if (mxs_power_config_get_use() == POWER_USE_BATTERY_INPUT) mxs_enable_battery_input(); - else if (use_5v_input) + else if (mxs_power_config_get_use() == POWER_USE_5V) mxs_boot_valid_5v(); mxs_power_clock2pll(); @@ -1223,10 +1229,18 @@ mxs_enable_output_rail_protection(); - mxs_power_set_vddx(&mx23_vddio_cfg, 3300, 3150); - mxs_power_set_vddx(&mxs_vddd_cfg, 1500, 1325); - mxs_power_set_vddx(&mxs_vddmem_cfg, 2500, 1700); - mxs_power_set_vddx(&mxs_vdda_cfg, 1800, 1650); + if (ctrls->vddio) + mxs_power_set_vddx(&mx23_vddio_cfg, ctrls->vddio->target, + ctrls->vddio->brownout); + if (ctrls->vddd) + mxs_power_set_vddx(&mxs_vddd_cfg, ctrls->vddd->target, + ctrls->vddd->brownout); + if (ctrls->vddmem) + mxs_power_set_vddx(&mxs_vddmem_cfg, ctrls->vddmem->target, + ctrls->vddmem->brownout); + if (ctrls->vdda) + mxs_power_set_vddx(&mxs_vdda_cfg, ctrls->vdda->target, + ctrls->vdda->brownout); writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ | POWER_CTRL_VDDIO_BO_IRQ | POWER_CTRL_VDD5V_DROOP_IRQ | @@ -1238,21 +1252,28 @@ mxs_early_delay(1000); } +struct mxs_power_ctrls mx28_power_default = { + .vdda = &mxs_vdda_default, + .vddd = &mxs_vddd_default, + .vddio = &mxs_vddio_default, + .vddmem = NULL, +}; + /** * mx28_power_init() - The power block init main function * * This function calls all the power block initialization functions in * proper sequence to start the power block. + * + * @config: see enum mxs_power_config for possible options + * @ctrls: a mxs_power_ctrls struct, or use &mx28_power_default for default values */ -void mx28_power_init(int __has_battery, int __use_battery_input, - int __use_5v_input) +void mx28_power_init(const int config, struct mxs_power_ctrls *ctrls) { struct mxs_power_regs *power_regs = (struct mxs_power_regs *)IMX_POWER_BASE; - has_battery = __has_battery; - use_battery_input = __use_battery_input; - use_5v_input = __use_5v_input; + power_config = config; mxs_power_status(); mxs_power_clock2xtal(); @@ -1264,11 +1285,11 @@ mxs_src_power_init(); - if (has_battery) + if (mxs_power_config_get_use() == POWER_USE_BATTERY) mxs_power_configure_power_source(); - else if (use_battery_input) + else if (mxs_power_config_get_use() == POWER_USE_BATTERY_INPUT) mxs_enable_battery_input(); - else if (use_5v_input) + else if (mxs_power_config_get_use() == POWER_USE_5V) mxs_boot_valid_5v(); mxs_power_clock2pll(); @@ -1279,9 +1300,18 @@ mxs_enable_output_rail_protection(); - mxs_power_set_vddx(&mx28_vddio_cfg, 3300, 3150); - mxs_power_set_vddx(&mxs_vddd_cfg, 1500, 1325); - mxs_power_set_vddx(&mxs_vdda_cfg, 1800, 1650); + if (ctrls->vddio) + mxs_power_set_vddx(&mx28_vddio_cfg, ctrls->vddio->target, + ctrls->vddio->brownout); + if (ctrls->vddd) + mxs_power_set_vddx(&mxs_vddd_cfg, ctrls->vddd->target, + ctrls->vddd->brownout); + if (ctrls->vddmem) + mxs_power_set_vddx(&mxs_vddmem_cfg, ctrls->vddmem->target, + ctrls->vddmem->brownout); + if (ctrls->vdda) + mxs_power_set_vddx(&mxs_vdda_cfg, ctrls->vdda->target, + ctrls->vdda->brownout); writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ | POWER_CTRL_VDDIO_BO_IRQ | POWER_CTRL_VDD5V_DROOP_IRQ | diff --git a/arch/arm/mach-mxs/soc-imx23.c b/arch/arm/mach-mxs/soc-imx23.c index d471c8e..f25fff1 100644 --- a/arch/arm/mach-mxs/soc-imx23.c +++ b/arch/arm/mach-mxs/soc-imx23.c @@ -19,6 +19,8 @@ #include #include #include +#include +#include #define HW_CLKCTRL_RESET 0x120 # define HW_CLKCTRL_RESET_CHIP (1 << 1) @@ -37,6 +39,8 @@ static int imx23_devices_init(void) { + arm_add_mem_device("ram0", IMX_MEMORY_BASE, imx23_get_memsize()); + if (of_get_root_node()) return 0; diff --git a/arch/arm/mach-mxs/soc-imx28.c b/arch/arm/mach-mxs/soc-imx28.c index dc6020a..49f870b 100644 --- a/arch/arm/mach-mxs/soc-imx28.c +++ b/arch/arm/mach-mxs/soc-imx28.c @@ -19,6 +19,8 @@ #include #include #include +#include +#include #define HW_CLKCTRL_RESET 0x1e0 # define HW_CLKCTRL_RESET_CHIP (1 << 1) @@ -51,6 +53,8 @@ restart_handler_register_fn(imx28_restart_soc); + arm_add_mem_device("ram0", IMX_MEMORY_BASE, imx28_get_memsize()); + return 0; } postcore_initcall(imx28_init); diff --git a/images/Makefile.mxs b/images/Makefile.mxs index 93d43b3..aab8832 100644 --- a/images/Makefile.mxs +++ b/images/Makefile.mxs @@ -10,6 +10,14 @@ $(obj)/%.mxsbs: $(obj)/%.pblx $(obj)/prep_%.pblb FORCE $(call if_changed,mxs_bootstream) +# %.mxsbsu - convert into unencrypted MXS BootStream image +# ---------------------------------------------------------------- +quiet_cmd_mxs_bootstream_u = MXS-BOOTSTREAM-U $@ + cmd_mxs_bootstream_u = $(objtree)/scripts/mxsimage -u -c $(CFG_$(@F)) -b $< -o $@ -p $(word 2,$^) + +$(obj)/%.mxsbsu: $(obj)/%.pblx $(obj)/prep_%.pblb FORCE + $(call if_changed,mxs_bootstream_u) + # %.mxssd - convert into MXS SD card image # ---------------------------------------------------------------- quiet_cmd_mxs_sd = MXS-SD $@ diff --git a/scripts/mxsimage.c b/scripts/mxsimage.c index 5c2c307..8a63d76 100644 --- a/scripts/mxsimage.c +++ b/scripts/mxsimage.c @@ -337,6 +337,7 @@ /* Image configuration */ unsigned int verbose_boot:1; unsigned int silent_dump:1; + unsigned int encrypted:1; const char *input_filename; const char *output_filename; const char *cfg_filename; @@ -484,6 +485,12 @@ int ret, outlen; uint8_t *outbuf; + if (!ictx->encrypted) { + if (out_data && in_data != out_data) + memcpy(out_data, in_data, in_len); + return 0; + } + outbuf = malloc(in_len); if (!outbuf) return -ENOMEM; @@ -645,7 +652,8 @@ * Key dictionary. */ sb_aes_reinit(ictx, 1); - sb_encrypt_key_dictionary_key(ictx); + if (ictx->encrypted) + sb_encrypt_key_dictionary_key(ictx); /* * Section tags. @@ -1609,10 +1617,10 @@ hdr->timestamp_us = sb_get_timestamp() * 1000000; /* FIXME -- add proper config option */ - hdr->flags = ictx->verbose_boot ? SB_IMAGE_FLAG_VERBOSE : 0, + hdr->flags = ictx->verbose_boot ? SB_IMAGE_FLAG_VERBOSE : 0; /* FIXME -- We support only default key */ - hdr->key_count = 1; + hdr->key_count = ictx->encrypted ? 1 : 0; return 0; } @@ -2450,7 +2458,7 @@ /* Calculate image size. */ uint32_t size = sizeof(*sb_header) + ictx->sect_count * sizeof(struct sb_sections_header) + - sizeof(*sb_dict_key) + sizeof(ictx->digest); + sizeof(*sb_dict_key) * sb_header->key_count + sizeof(ictx->digest); sctx = ictx->sect_head; while (sctx) { @@ -2473,8 +2481,10 @@ sctx = sctx->sect; }; - memcpy(iptr, sb_dict_key, sizeof(*sb_dict_key)); - iptr += sizeof(*sb_dict_key); + if (ictx->encrypted) { + memcpy(iptr, sb_dict_key, sizeof(*sb_dict_key)); + iptr += sizeof(*sb_dict_key); + } sctx = ictx->sect_head; while (sctx) { @@ -2516,27 +2526,20 @@ return 0; } -static int mxsimage_generate(const char *configfile, const char *imagefile) +static int mxsimage_generate(struct sb_image_ctx *ctx) { int ret; - struct sb_image_ctx ctx; - memset(&ctx, 0, sizeof(ctx)); - - ctx.cfg_filename = configfile; - ctx.output_filename = imagefile; - ctx.verbose_boot = 1; - - ret = sb_build_tree_from_cfg(&ctx); + ret = sb_build_tree_from_cfg(ctx); if (ret) goto fail; - ret = sb_encrypt_image(&ctx); + ret = sb_encrypt_image(ctx); if (!ret) - ret = sb_build_image(&ctx); + ret = sb_build_image(ctx); fail: - sb_free_image(&ctx); + sb_free_image(ctx); return ret; } @@ -2546,8 +2549,12 @@ int ret; int opt; char *configfile = NULL, *outfile = NULL, *verify = NULL; + struct sb_image_ctx ctx = { + .encrypted = 1, + .verbose_boot = 1, + }; - while ((opt = getopt(argc, argv, "p:b:c:o:v:")) != -1) { + while ((opt = getopt(argc, argv, "p:b:c:o:v:u")) != -1) { switch (opt) { case 'p': prepfile = optarg; @@ -2564,6 +2571,9 @@ case 'v': verify = optarg; break; + case 'u': + ctx.encrypted = 0; + break; default: exit(1); } @@ -2587,7 +2597,10 @@ exit(1); } - ret = mxsimage_generate(configfile, outfile); + ctx.cfg_filename = configfile; + ctx.output_filename = outfile; + + ret = mxsimage_generate(&ctx); if (ret) exit(1);