]> git.ipfire.org Git - people/ms/u-boot.git/commitdiff
Merge branch 'master' of git://git.denx.de/u-boot-rockchip
authorTom Rini <trini@konsulko.com>
Mon, 14 Aug 2017 14:40:01 +0000 (10:40 -0400)
committerTom Rini <trini@konsulko.com>
Mon, 14 Aug 2017 14:40:01 +0000 (10:40 -0400)
122 files changed:
api/api.c
arch/arm/cpu/arm926ejs/spear/spl.c
arch/arm/cpu/armv7/bcm235xx/clk-core.c
arch/arm/cpu/armv7/bcm281xx/clk-core.c
arch/arm/cpu/armv7m/mpu.c
arch/arm/include/asm/arch-omap5/clock.h
arch/arm/include/asm/arch-omap5/omap.h
arch/arm/include/asm/arch-stm32f1/gpio.h [deleted file]
arch/arm/include/asm/arch-stm32f1/stm32.h [deleted file]
arch/arm/mach-mvebu/serdes/axp/high_speed_env_lib.c
arch/arm/mach-omap2/omap3/emif4.c
arch/arm/mach-omap2/omap5/abb.c
arch/arm/mach-omap2/omap5/hw_data.c
arch/arm/mach-stm32/Kconfig
arch/arm/mach-stm32/Makefile
arch/arm/mach-stm32/stm32f1/Kconfig [deleted file]
arch/arm/mach-stm32/stm32f1/Makefile [deleted file]
arch/arm/mach-stm32/stm32f1/clock.c [deleted file]
arch/arm/mach-stm32/stm32f1/flash.c [deleted file]
arch/arm/mach-stm32/stm32f1/soc.c [deleted file]
arch/arm/mach-stm32/stm32f1/timer.c [deleted file]
board/hisilicon/hikey/hikey.c
cmd/Kconfig
cmd/Makefile
cmd/bdinfo.c
cmd/nvme.c [new file with mode: 0644]
common/boot_fit.c
configs/am335x_baltos_defconfig
configs/am335x_boneblack_defconfig
configs/am335x_boneblack_vboot_defconfig
configs/am335x_evm_defconfig
configs/am335x_evm_nor_defconfig
configs/am335x_evm_norboot_defconfig
configs/am335x_evm_spiboot_defconfig
configs/am335x_evm_usbspl_defconfig
configs/am335x_hs_evm_defconfig
configs/am335x_igep003x_defconfig
configs/am335x_shc_defconfig
configs/am335x_shc_ict_defconfig
configs/am335x_shc_netboot_defconfig
configs/am335x_shc_prompt_defconfig
configs/am335x_shc_sdboot_defconfig
configs/am335x_shc_sdboot_prompt_defconfig
configs/am335x_sl50_defconfig
configs/birdland_bav335a_defconfig
configs/birdland_bav335b_defconfig
configs/brppt1_spi_defconfig
configs/cairo_defconfig
configs/chiliboard_defconfig
configs/cm_t3517_defconfig
configs/cm_t35_defconfig
configs/cm_t43_defconfig
configs/cm_t54_defconfig
configs/draco_defconfig
configs/duovero_defconfig
configs/etamin_defconfig
configs/igep0020_defconfig
configs/igep0030_defconfig
configs/igep0032_defconfig
configs/nokia_rx51_defconfig
configs/omap3_beagle_defconfig
configs/omap3_evm_defconfig
configs/omap3_ha_defconfig
configs/omap3_logic_defconfig
configs/omap3_overo_defconfig
configs/omap3_pandora_defconfig
configs/omap3_zoom1_defconfig
configs/omap4_panda_defconfig
configs/omap4_sdp4430_defconfig
configs/omap5_uevm_defconfig
configs/pcm051_rev1_defconfig
configs/pcm051_rev3_defconfig
configs/pengwyn_defconfig
configs/pepper_defconfig
configs/pxm2_defconfig
configs/qemu-x86_defconfig
configs/rastaban_defconfig
configs/rut_defconfig
configs/tao3530_defconfig
configs/thuban_defconfig
configs/ti816x_evm_defconfig
disk/part.c
doc/README.nvme [new file with mode: 0644]
drivers/Kconfig
drivers/Makefile
drivers/block/blk-uclass.c
drivers/ddr/marvell/a38x/ddr3_debug.c
drivers/ddr/marvell/a38x/ddr3_training_centralization.c
drivers/gpio/stm32_gpio.c
drivers/nvme/Kconfig [new file with mode: 0644]
drivers/nvme/Makefile [new file with mode: 0644]
drivers/nvme/nvme-uclass.c [new file with mode: 0644]
drivers/nvme/nvme.c [new file with mode: 0644]
drivers/nvme/nvme.h [new file with mode: 0644]
drivers/nvme/nvme_show.c [new file with mode: 0644]
drivers/spi/Kconfig
drivers/watchdog/wdt-uclass.c
include/blk.h
include/configs/am43xx_evm.h
include/configs/am57xx_evm.h
include/configs/brppt1.h
include/configs/cl-som-am57x.h
include/configs/cm_t335.h
include/configs/cm_t35.h
include/configs/cm_t3517.h
include/configs/devkit8000.h
include/configs/dra7xx_evm.h
include/configs/nokia_rx51.h
include/configs/omap3_beagle.h
include/configs/omap3_cairo.h
include/configs/rut.h
include/configs/siemens-am33x-common.h
include/configs/tao3530.h
include/configs/ti_armv7_omap.h
include/dm/uclass-id.h
include/flash.h
include/nvme.h [new file with mode: 0644]
include/pci_ids.h
include/wdt.h
lib/tpm.c
test/image/test-fit.py [deleted file]
test/py/tests/test_fit.py [new file with mode: 0755]

index c368511704e5e9877757a49b2e8e9cf2256c2b95..4fae95d2801db2d1d7e304559630500949d405db 100644 (file)
--- a/api/api.c
+++ b/api/api.c
@@ -625,7 +625,7 @@ int syscall(int call, int *retval, ...)
 
 void api_init(void)
 {
-       struct api_signature *sig = NULL;
+       struct api_signature *sig;
 
        /* TODO put this into linker set one day... */
        calls_table[API_RSVD] = NULL;
index a60f5838de418f93df7251f69156b00ee67b3b02..ba1e5591574c7d194e0fe2ca52ef5a4a0c49715b 100644 (file)
@@ -222,7 +222,7 @@ static void snor_init(void)
 
 u32 spl_boot_device(void)
 {
-       u32 mode;
+       u32 mode = 0;
 
        /* Currently only SNOR is supported as the only */
        if (snor_boot_selected()) {
index 79fafa08ed9358f3817658eff65159968ab85022..89e367be822797e1f55d6dae0e1eaa721ec78de2 100644 (file)
@@ -479,9 +479,9 @@ unsigned long clk_get_rate(struct clk *c)
 {
        unsigned long rate;
 
-       debug("%s: %s\n", __func__, c->name);
        if (!c || !c->ops || !c->ops->get_rate)
                return 0;
+       debug("%s: %s\n", __func__, c->name);
 
        rate = c->ops->get_rate(c);
        debug("%s: rate = %ld\n", __func__, rate);
@@ -493,9 +493,9 @@ int clk_set_rate(struct clk *c, unsigned long rate)
 {
        int ret;
 
-       debug("%s: %s rate=%ld\n", __func__, c->name, rate);
        if (!c || !c->ops || !c->ops->set_rate)
                return -EINVAL;
+       debug("%s: %s rate=%ld\n", __func__, c->name, rate);
 
        if (c->use_cnt)
                return -EINVAL;
index cdc1264d7cd5d1c0ab7883220e553d47404aa198..b061c20648b8e2eaf326f89e9ca8aaf892b01cb3 100644 (file)
@@ -479,9 +479,9 @@ unsigned long clk_get_rate(struct clk *c)
 {
        unsigned long rate;
 
-       debug("%s: %s\n", __func__, c->name);
        if (!c || !c->ops || !c->ops->get_rate)
                return 0;
+       debug("%s: %s\n", __func__, c->name);
 
        rate = c->ops->get_rate(c);
        debug("%s: rate = %ld\n", __func__, rate);
@@ -493,9 +493,9 @@ int clk_set_rate(struct clk *c, unsigned long rate)
 {
        int ret;
 
-       debug("%s: %s rate=%ld\n", __func__, c->name, rate);
        if (!c || !c->ops || !c->ops->set_rate)
                return -EINVAL;
+       debug("%s: %s rate=%ld\n", __func__, c->name, rate);
 
        if (c->use_cnt)
                return -EINVAL;
index 31a243b49adde86ff0ab8abe7370f6b6189b599f..4622aa48263f73a49f15fe46a077da39c64d4736 100644 (file)
@@ -68,6 +68,7 @@ void mpu_config(struct mpu_region_config *reg_config)
                break;
        case DEVICE_NON_SHARED:
                attr = (2 << TEX_SHIFT) | BUFFERABLE;
+               break;
        default:
                attr = 0; /* strongly ordered */
                break;
index 0c99bbdc9320326e843099d0d399f305ca903ced..dbe340d23e4fb42e2ae45a4b397ec315fc5cca62 100644 (file)
 #define VDD_MPU_ES2_HIGH 1250
 #define VDD_MM_ES2_OD  1120
 
-#define VDD_MPU_ES2_LOW 880
-#define VDD_MM_ES2_LOW 880
+/* Efuse register offsets for OMAP5 platform */
+#define OMAP5_ES2_EFUSE_BASE   0x4A002000
+#define OMAP5_ES2_PROD_REGBITS 16
+
+/* CONTROL_STD_FUSE_OPP_VDD_CORE_3 */
+#define OMAP5_ES2_PROD_CORE_OPNO_VMIN  (OMAP5_ES2_EFUSE_BASE + 0x1D8)
+
+/* CONTROL_STD_FUSE_OPP_VDD_MM_4 */
+#define OMAP5_ES2_PROD_MM_OPNO_VMIN    (OMAP5_ES2_EFUSE_BASE + 0x1A4)
+/* CONTROL_STD_FUSE_OPP_VDD_MM_5 */
+#define OMAP5_ES2_PROD_MM_OPOD_VMIN    (OMAP5_ES2_EFUSE_BASE + 0x1A8)
+/* CONTROL_STD_FUSE_OPP_VDD_MPU_6 */
+#define OMAP5_ES2_PROD_MPU_OPNO_VMIN   (OMAP5_ES2_EFUSE_BASE + 0x1C4)
+/* CONTROL_STD_FUSE_OPP_VDD_MPU_7 */
+#define OMAP5_ES2_PROD_MPU_OPHI_VMIN   (OMAP5_ES2_EFUSE_BASE + 0x1C8)
 
 /* DRA74x/75x/72x voltage settings in mv for OPP_NOM per DM */
 #define VDD_MPU_DRA7_NOM       1150
index 2f005dd3ad924b55f837fb02ee650eb92e205c89..b047f0d6508159374e42bc738714b2c9931c6cfb 100644 (file)
@@ -224,8 +224,8 @@ struct s32ktimer {
 #define OMAP_ABB_GPU_TXDONE_MASK               (0x1 << 28)
 
 /* ABB efuse masks */
-#define OMAP5_ABB_FUSE_VSET_MASK               (0x1F << 24)
-#define OMAP5_ABB_FUSE_ENABLE_MASK             (0x1 << 29)
+#define OMAP5_PROD_ABB_FUSE_VSET_MASK          (0x1F << 20)
+#define OMAP5_PROD_ABB_FUSE_ENABLE_MASK                (0x1 << 25)
 #define DRA7_ABB_FUSE_VSET_MASK                        (0x1F << 20)
 #define DRA7_ABB_FUSE_ENABLE_MASK              (0x1 << 25)
 #define OMAP5_ABB_LDOVBBMPU_MUX_CTRL_MASK      (0x1 << 10)
diff --git a/arch/arm/include/asm/arch-stm32f1/gpio.h b/arch/arm/include/asm/arch-stm32f1/gpio.h
deleted file mode 100644 (file)
index 8e8712f..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * (C) Copyright 2011
- * Yuri Tikhonov, Emcraft Systems, yur@emcraft.com
- *
- * (C) Copyright 2015
- * Kamil Lulko, <kamil.lulko@gmail.com>
- *
- * Copyright 2015 ATS Advanced Telematics Systems GmbH
- * Copyright 2015 Konsulko Group, Matt Porter <mporter@konsulko.com>
- *
- * SPDX-License-Identifier:    GPL-2.0+
- */
-
-#ifndef _STM32_GPIO_H_
-#define _STM32_GPIO_H_
-
-enum stm32_gpio_port {
-       STM32_GPIO_PORT_A = 0,
-       STM32_GPIO_PORT_B,
-       STM32_GPIO_PORT_C,
-       STM32_GPIO_PORT_D,
-       STM32_GPIO_PORT_E,
-       STM32_GPIO_PORT_F,
-       STM32_GPIO_PORT_G,
-};
-
-enum stm32_gpio_pin {
-       STM32_GPIO_PIN_0 = 0,
-       STM32_GPIO_PIN_1,
-       STM32_GPIO_PIN_2,
-       STM32_GPIO_PIN_3,
-       STM32_GPIO_PIN_4,
-       STM32_GPIO_PIN_5,
-       STM32_GPIO_PIN_6,
-       STM32_GPIO_PIN_7,
-       STM32_GPIO_PIN_8,
-       STM32_GPIO_PIN_9,
-       STM32_GPIO_PIN_10,
-       STM32_GPIO_PIN_11,
-       STM32_GPIO_PIN_12,
-       STM32_GPIO_PIN_13,
-       STM32_GPIO_PIN_14,
-       STM32_GPIO_PIN_15
-};
-
-enum stm32_gpio_icnf {
-       STM32_GPIO_ICNF_AN = 0,
-       STM32_GPIO_ICNF_IN_FLT,
-       STM32_GPIO_ICNF_IN_PUD,
-       STM32_GPIO_ICNF_RSVD
-};
-
-enum stm32_gpio_ocnf {
-       STM32_GPIO_OCNF_GP_PP = 0,
-       STM32_GPIO_OCNF_GP_OD,
-       STM32_GPIO_OCNF_AF_PP,
-       STM32_GPIO_OCNF_AF_OD
-};
-
-enum stm32_gpio_pupd {
-       STM32_GPIO_PUPD_DOWN = 0,
-       STM32_GPIO_PUPD_UP,
-};
-
-enum stm32_gpio_mode {
-       STM32_GPIO_MODE_IN = 0,
-       STM32_GPIO_MODE_OUT_10M,
-       STM32_GPIO_MODE_OUT_2M,
-       STM32_GPIO_MODE_OUT_50M
-};
-
-enum stm32_gpio_af {
-       STM32_GPIO_AF0 = 0,
-       STM32_GPIO_AF1,
-       STM32_GPIO_AF2,
-       STM32_GPIO_AF3,
-       STM32_GPIO_AF4,
-       STM32_GPIO_AF5,
-       STM32_GPIO_AF6,
-       STM32_GPIO_AF7,
-       STM32_GPIO_AF8,
-       STM32_GPIO_AF9,
-       STM32_GPIO_AF10,
-       STM32_GPIO_AF11,
-       STM32_GPIO_AF12,
-       STM32_GPIO_AF13,
-       STM32_GPIO_AF14,
-       STM32_GPIO_AF15
-};
-
-struct stm32_gpio_dsc {
-       enum stm32_gpio_port    port;
-       enum stm32_gpio_pin     pin;
-};
-
-struct stm32_gpio_ctl {
-       enum stm32_gpio_icnf    icnf;
-       enum stm32_gpio_ocnf    ocnf;
-       enum stm32_gpio_mode    mode;
-       enum stm32_gpio_pupd    pupd;
-       enum stm32_gpio_af      af;
-};
-
-static inline unsigned stm32_gpio_to_port(unsigned gpio)
-{
-       return gpio / 16;
-}
-
-static inline unsigned stm32_gpio_to_pin(unsigned gpio)
-{
-       return gpio % 16;
-}
-
-int stm32_gpio_config(const struct stm32_gpio_dsc *gpio_dsc,
-               const struct stm32_gpio_ctl *gpio_ctl);
-int stm32_gpout_set(const struct stm32_gpio_dsc *gpio_dsc, int state);
-
-#endif /* _STM32_GPIO_H_ */
diff --git a/arch/arm/include/asm/arch-stm32f1/stm32.h b/arch/arm/include/asm/arch-stm32f1/stm32.h
deleted file mode 100644 (file)
index 1af73c5..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * (C) Copyright 2011
- * Yuri Tikhonov, Emcraft Systems, yur@emcraft.com
- *
- * (C) Copyright 2015
- * Kamil Lulko, <kamil.lulko@gmail.com>
- *
- * Copyright 2015 ATS Advanced Telematics Systems GmbH
- * Copyright 2015 Konsulko Group, Matt Porter <mporter@konsulko.com>
- *
- * SPDX-License-Identifier:    GPL-2.0+
- */
-
-#ifndef _MACH_STM32_H_
-#define _MACH_STM32_H_
-
-/*
- * Peripheral memory map
- */
-#define STM32_PERIPH_BASE      0x40000000
-#define STM32_APB1PERIPH_BASE  (STM32_PERIPH_BASE + 0x00000000)
-#define STM32_APB2PERIPH_BASE  (STM32_PERIPH_BASE + 0x00010000)
-#define STM32_AHB1PERIPH_BASE  (STM32_PERIPH_BASE + 0x00018000)
-
-#define STM32_BUS_MASK         0xFFFF0000
-
-#define STM32_GPIOA_BASE       (STM32_APB2PERIPH_BASE + 0x0800)
-#define STM32_GPIOB_BASE       (STM32_APB2PERIPH_BASE + 0x0C00)
-#define STM32_GPIOC_BASE       (STM32_APB2PERIPH_BASE + 0x1000)
-#define STM32_GPIOD_BASE       (STM32_APB2PERIPH_BASE + 0x1400)
-#define STM32_GPIOE_BASE       (STM32_APB2PERIPH_BASE + 0x1800)
-#define STM32_GPIOF_BASE       (STM32_APB2PERIPH_BASE + 0x1C00)
-#define STM32_GPIOG_BASE       (STM32_APB2PERIPH_BASE + 0x2000)
-
-/*
- * Register maps
- */
-struct stm32_des_regs {
-       u16 flash_size;
-       u16 pad1;
-       u32 pad2;
-       u32 uid0;
-       u32 uid1;
-       u32 uid2;
-};
-
-struct stm32_rcc_regs {
-       u32 cr;         /* RCC clock control */
-       u32 cfgr;       /* RCC clock configuration */
-       u32 cir;        /* RCC clock interrupt */
-       u32 apb2rstr;   /* RCC APB2 peripheral reset */
-       u32 apb1rstr;   /* RCC APB1 peripheral reset */
-       u32 ahbenr;     /* RCC AHB peripheral clock enable */
-       u32 apb2enr;    /* RCC APB2 peripheral clock enable */
-       u32 apb1enr;    /* RCC APB1 peripheral clock enable */
-       u32 bdcr;       /* RCC Backup domain control */
-       u32 csr;        /* RCC clock control & status */
-};
-
-struct stm32_pwr_regs {
-       u32 cr;
-       u32 csr;
-};
-
-struct stm32_flash_regs {
-       u32 acr;
-       u32 keyr;
-       u32 optkeyr;
-       u32 sr;
-       u32 cr;
-       u32 ar;
-       u32 rsvd1;      /* Reserved */
-       u32 obr;
-       u32 wrpr;
-       u32 rsvd2[8];   /* Reserved */
-       u32 keyr2;
-       u32 rsvd3;
-       u32 sr2;
-       u32 cr2;
-       u32 ar2;
-};
-
-/* Per bank register set for XL devices */
-struct stm32_flash_bank_regs {
-       u32 keyr;
-       u32 rsvd;       /* Reserved */
-       u32 sr;
-       u32 cr;
-       u32 ar;
-};
-
-/*
- * Registers access macros
- */
-#define STM32_DES_BASE         (0x1ffff7e0)
-#define STM32_DES              ((struct stm32_des_regs *)STM32_DES_BASE)
-
-#define STM32_RCC_BASE         (STM32_AHB1PERIPH_BASE + 0x9000)
-#define STM32_RCC              ((struct stm32_rcc_regs *)STM32_RCC_BASE)
-
-#define STM32_PWR_BASE         (STM32_APB1PERIPH_BASE + 0x7000)
-#define STM32_PWR              ((struct stm32_pwr_regs *)STM32_PWR_BASE)
-
-#define STM32_FLASH_BASE       (STM32_AHB1PERIPH_BASE + 0xa000)
-#define STM32_FLASH            ((struct stm32_flash_regs *)STM32_FLASH_BASE)
-
-#define STM32_FLASH_SR_BSY             (1 << 0)
-
-#define STM32_FLASH_CR_PG              (1 << 0)
-#define STM32_FLASH_CR_PER             (1 << 1)
-#define STM32_FLASH_CR_STRT            (1 << 6)
-#define STM32_FLASH_CR_LOCK            (1 << 7)
-
-enum clock {
-       CLOCK_CORE,
-       CLOCK_AHB,
-       CLOCK_APB1,
-       CLOCK_APB2
-};
-
-int configure_clocks(void);
-unsigned long clock_get(enum clock clck);
-
-#endif /* _MACH_STM32_H_ */
index b0e193b78c0d08a3af43a806cf5ee5dd877eca53..525576a4fc8a9173ed65cf1a4d63eb6717a7c6c5 100644 (file)
@@ -354,16 +354,16 @@ int serdes_phy_config(void)
        }
 
        info = board_serdes_cfg_get(PEX_MODE_GET(satr11));
-       DEBUG_INIT_FULL_S("info->line0_7= 0x");
-       DEBUG_INIT_FULL_D(info->line0_7, 8);
-       DEBUG_INIT_FULL_S("   info->line8_15= 0x");
-       DEBUG_INIT_FULL_D(info->line8_15, 8);
-       DEBUG_INIT_FULL_S("\n");
 
        if (info == NULL) {
                DEBUG_INIT_S("Hight speed PHY Error #1\n");
                return MV_ERROR;
        }
+       DEBUG_INIT_FULL_S("info->line0_7= 0x");
+       DEBUG_INIT_FULL_D(info->line0_7, 8);
+       DEBUG_INIT_FULL_S("   info->line8_15= 0x");
+       DEBUG_INIT_FULL_D(info->line8_15, 8);
+       DEBUG_INIT_FULL_S("\n");
 
        if (config_module & ETM_MODULE_DETECT) {        /* step 0.9 ETM */
                DEBUG_INIT_FULL_S("ETM module detect Step 0.9:\n");
index d540cf08d2e710f022ab28d5d9c83df8bc479c15..8197e7b03270dc9c8974d5798b0439bc7245bf40 100644 (file)
@@ -76,7 +76,7 @@ static void do_emif4_init(void)
        regval |= (1<<10);
        writel(regval, &emif4_base->sdram_iodft_tlgc);
        /*Wait till that bit clears*/
-       while ((readl(&emif4_base->sdram_iodft_tlgc) & (1<<10)) == 0x1);
+       while ((readl(&emif4_base->sdram_iodft_tlgc) & (1<<10)) != 0x0);
        /*Re-verify the DDR PHY status*/
        while ((readl(&emif4_base->sdram_sts) & (1<<2)) == 0x0);
 
index 3bf88979e5d62bad3a5565e8cef19e77aada065e..1882c49e7df6c66de583bc8b70de2d67b1c02b76 100644 (file)
@@ -28,8 +28,8 @@
 s8 abb_setup_ldovbb(u32 fuse, u32 ldovbb)
 {
        u32 vset;
-       u32 fuse_enable_mask = OMAP5_ABB_FUSE_ENABLE_MASK;
-       u32 fuse_vset_mask = OMAP5_ABB_FUSE_VSET_MASK;
+       u32 fuse_enable_mask = OMAP5_PROD_ABB_FUSE_ENABLE_MASK;
+       u32 fuse_vset_mask = OMAP5_PROD_ABB_FUSE_VSET_MASK;
 
        if (!is_omap54xx()) {
                /* DRA7 */
index a8a6b8a869e539106a5e5234b37f5567f273b41e..4ad6b530d29cb7b5ba4073dd9495e7fe8450a401 100644 (file)
@@ -329,6 +329,15 @@ struct vcores_data omap5430_volts_es2 = {
        .mm.addr = SMPS_REG_ADDR_45_IVA,
        .mm.pmic = &palmas,
        .mm.abb_tx_done_mask = OMAP_ABB_MM_TXDONE_MASK,
+
+       .mpu.efuse.reg[OPP_NOM] = OMAP5_ES2_PROD_MPU_OPNO_VMIN,
+       .mpu.efuse.reg_bits     = OMAP5_ES2_PROD_REGBITS,
+
+       .core.efuse.reg[OPP_NOM] = OMAP5_ES2_PROD_CORE_OPNO_VMIN,
+       .core.efuse.reg_bits    = OMAP5_ES2_PROD_REGBITS,
+
+       .mm.efuse.reg[OPP_NOM]  = OMAP5_ES2_PROD_MM_OPNO_VMIN,
+       .mm.efuse.reg_bits      = OMAP5_ES2_PROD_REGBITS,
 };
 
 /*
index 8f4371429f60d1ebaf3749dbe0159a5aeffc5f56..f70f5ec9656918b4085f9fc702077d0dc3abc90e 100644 (file)
@@ -3,9 +3,6 @@ if STM32
 config STM32F4
        bool "stm32f4 family"
 
-config STM32F1
-       bool "stm32f1 family"
-
 config STM32F7
        bool "stm32f7 family"
        select SUPPORT_SPL
@@ -29,7 +26,6 @@ config STM32F7
        select SPL_XIP_SUPPORT
 
 source "arch/arm/mach-stm32/stm32f4/Kconfig"
-source "arch/arm/mach-stm32/stm32f1/Kconfig"
 source "arch/arm/mach-stm32/stm32f7/Kconfig"
 
 endif
index ffc537f35b1aaa4899cef8ab4b42b8323046f9c8..6b7694471f878413c8e9715aecaaa5f3a736950a 100644 (file)
@@ -5,6 +5,5 @@
 # SPDX-License-Identifier:     GPL-2.0+
 #
 
-obj-$(CONFIG_STM32F1) += stm32f1/
 obj-$(CONFIG_STM32F4) += stm32f4/
 obj-$(CONFIG_STM32F7) += stm32f7/
diff --git a/arch/arm/mach-stm32/stm32f1/Kconfig b/arch/arm/mach-stm32/stm32f1/Kconfig
deleted file mode 100644 (file)
index f627fd2..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-if STM32F1
-
-endif
diff --git a/arch/arm/mach-stm32/stm32f1/Makefile b/arch/arm/mach-stm32/stm32f1/Makefile
deleted file mode 100644 (file)
index e2081db..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#
-# (C) Copyright 2000-2006
-# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
-#
-# (C) Copyright 2015
-# Kamil Lulko, <kamil.lulko@gmail.com>
-#
-# Copyright 2015 ATS Advanced Telematics Systems GmbH
-# Copyright 2015 Konsulko Group, Matt Porter <mporter@konsulko.com>
-#
-# SPDX-License-Identifier:     GPL-2.0+
-#
-
-obj-y += soc.o clock.o timer.o flash.o
diff --git a/arch/arm/mach-stm32/stm32f1/clock.c b/arch/arm/mach-stm32/stm32f1/clock.c
deleted file mode 100644 (file)
index 2820848..0000000
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * (C) Copyright 2015
- * Kamil Lulko, <kamil.lulko@gmail.com>
- *
- * Copyright 2015 ATS Advanced Telematics Systems GmbH
- * Copyright 2015 Konsulko Group, Matt Porter <mporter@konsulko.com>
- *
- * (C) Copyright 2014
- * STMicroelectronics
- *
- * SPDX-License-Identifier:    GPL-2.0+
- */
-
-#include <common.h>
-#include <asm/io.h>
-#include <asm/arch/stm32.h>
-
-#define RCC_CR_HSION           (1 << 0)
-#define RCC_CR_HSEON           (1 << 16)
-#define RCC_CR_HSERDY          (1 << 17)
-#define RCC_CR_HSEBYP          (1 << 18)
-#define RCC_CR_CSSON           (1 << 19)
-#define RCC_CR_PLLON           (1 << 24)
-#define RCC_CR_PLLRDY          (1 << 25)
-
-#define RCC_CFGR_PLLMUL_MASK   0x3C0000
-#define RCC_CFGR_PLLMUL_SHIFT  18
-#define RCC_CFGR_PLLSRC_HSE    (1 << 16)
-
-#define RCC_CFGR_AHB_PSC_MASK  0xF0
-#define RCC_CFGR_APB1_PSC_MASK 0x700
-#define RCC_CFGR_APB2_PSC_MASK 0x3800
-#define RCC_CFGR_SW0           (1 << 0)
-#define RCC_CFGR_SW1           (1 << 1)
-#define RCC_CFGR_SW_MASK       0x3
-#define RCC_CFGR_SW_HSI                0
-#define RCC_CFGR_SW_HSE                RCC_CFGR_SW0
-#define RCC_CFGR_SW_PLL                RCC_CFGR_SW1
-#define RCC_CFGR_SWS0          (1 << 2)
-#define RCC_CFGR_SWS1          (1 << 3)
-#define RCC_CFGR_SWS_MASK      0xC
-#define RCC_CFGR_SWS_HSI       0
-#define RCC_CFGR_SWS_HSE       RCC_CFGR_SWS0
-#define RCC_CFGR_SWS_PLL       RCC_CFGR_SWS1
-#define RCC_CFGR_HPRE_SHIFT    4
-#define RCC_CFGR_PPRE1_SHIFT   8
-#define RCC_CFGR_PPRE2_SHIFT   11
-
-#define RCC_APB1ENR_PWREN      (1 << 28)
-
-#define PWR_CR_VOS0            (1 << 14)
-#define PWR_CR_VOS1            (1 << 15)
-#define PWR_CR_VOS_MASK                0xC000
-#define PWR_CR_VOS_SCALE_MODE_1        (PWR_CR_VOS0 | PWR_CR_VOS1)
-#define PWR_CR_VOS_SCALE_MODE_2        (PWR_CR_VOS1)
-#define PWR_CR_VOS_SCALE_MODE_3        (PWR_CR_VOS0)
-
-#define FLASH_ACR_WS(n)                n
-#define FLASH_ACR_PRFTEN       (1 << 8)
-#define FLASH_ACR_ICEN         (1 << 9)
-#define FLASH_ACR_DCEN         (1 << 10)
-
-struct psc {
-       u8      ahb_psc;
-       u8      apb1_psc;
-       u8      apb2_psc;
-};
-
-#define AHB_PSC_1              0
-#define AHB_PSC_2              0x8
-#define AHB_PSC_4              0x9
-#define AHB_PSC_8              0xA
-#define AHB_PSC_16             0xB
-#define AHB_PSC_64             0xC
-#define AHB_PSC_128            0xD
-#define AHB_PSC_256            0xE
-#define AHB_PSC_512            0xF
-
-#define APB_PSC_1              0
-#define APB_PSC_2              0x4
-#define APB_PSC_4              0x5
-#define APB_PSC_8              0x6
-#define APB_PSC_16             0x7
-
-#if !defined(CONFIG_STM32_HSE_HZ)
-#error "CONFIG_STM32_HSE_HZ not defined!"
-#else
-#if (CONFIG_STM32_HSE_HZ == 8000000)
-#define RCC_CFGR_PLLMUL_CFG    0x7
-struct psc psc_hse = {
-       .ahb_psc = AHB_PSC_1,
-       .apb1_psc = APB_PSC_2,
-       .apb2_psc = APB_PSC_1
-};
-#else
-#error "No PLL/Prescaler configuration for given CONFIG_STM32_HSE_HZ exists"
-#endif
-#endif
-
-int configure_clocks(void)
-{
-       /* Reset RCC configuration */
-       setbits_le32(&STM32_RCC->cr, RCC_CR_HSION);
-       writel(0, &STM32_RCC->cfgr); /* Reset CFGR */
-       clrbits_le32(&STM32_RCC->cr, (RCC_CR_HSEON | RCC_CR_CSSON
-               | RCC_CR_PLLON));
-       clrbits_le32(&STM32_RCC->cr, RCC_CR_HSEBYP);
-       writel(0, &STM32_RCC->cir); /* Disable all interrupts */
-
-       /* Configure for HSE+PLL operation */
-       setbits_le32(&STM32_RCC->cr, RCC_CR_HSEON);
-       while (!(readl(&STM32_RCC->cr) & RCC_CR_HSERDY))
-               ;
-
-       /* Enable high performance mode, System frequency up to 168 MHz */
-       setbits_le32(&STM32_RCC->apb1enr, RCC_APB1ENR_PWREN);
-       writel(PWR_CR_VOS_SCALE_MODE_1, &STM32_PWR->cr);
-
-       setbits_le32(&STM32_RCC->cfgr,
-                    RCC_CFGR_PLLMUL_CFG << RCC_CFGR_PLLMUL_SHIFT);
-       setbits_le32(&STM32_RCC->cfgr, RCC_CFGR_PLLSRC_HSE);
-       setbits_le32(&STM32_RCC->cfgr, ((
-               psc_hse.ahb_psc << RCC_CFGR_HPRE_SHIFT)
-               | (psc_hse.apb1_psc << RCC_CFGR_PPRE1_SHIFT)
-               | (psc_hse.apb2_psc << RCC_CFGR_PPRE2_SHIFT)));
-
-       setbits_le32(&STM32_RCC->cr, RCC_CR_PLLON);
-
-       while (!(readl(&STM32_RCC->cr) & RCC_CR_PLLRDY))
-               ;
-
-       /* 5 wait states, Prefetch enabled, D-Cache enabled, I-Cache enabled */
-       writel(FLASH_ACR_WS(5) | FLASH_ACR_PRFTEN | FLASH_ACR_ICEN
-               | FLASH_ACR_DCEN, &STM32_FLASH->acr);
-
-       clrbits_le32(&STM32_RCC->cfgr, (RCC_CFGR_SW0 | RCC_CFGR_SW1));
-       setbits_le32(&STM32_RCC->cfgr, RCC_CFGR_SW_PLL);
-
-       while ((readl(&STM32_RCC->cfgr) & RCC_CFGR_SWS_MASK) !=
-                       RCC_CFGR_SWS_PLL)
-               ;
-
-       return 0;
-}
-
-unsigned long clock_get(enum clock clck)
-{
-       u32 sysclk = 0;
-       u32 shift = 0;
-       /* PLL table lookups for clock computation */
-       u8 pll_mul_table[16] = {
-               2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 16
-       };
-       /* Prescaler table lookups for clock computation */
-       u8 ahb_psc_table[16] = {
-               0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9
-       };
-       u8 apb_psc_table[8] = {
-               0, 0, 0, 0, 1, 2, 3, 4
-       };
-
-       if ((readl(&STM32_RCC->cfgr) & RCC_CFGR_SWS_MASK) ==
-                       RCC_CFGR_SWS_PLL) {
-               u16 pll;
-               pll = ((readl(&STM32_RCC->cfgr) & RCC_CFGR_PLLMUL_MASK)
-                       >> RCC_CFGR_PLLMUL_SHIFT);
-               sysclk = CONFIG_STM32_HSE_HZ * pll_mul_table[pll];
-       }
-
-       switch (clck) {
-       case CLOCK_CORE:
-               return sysclk;
-               break;
-       case CLOCK_AHB:
-               shift = ahb_psc_table[(
-                       (readl(&STM32_RCC->cfgr) & RCC_CFGR_AHB_PSC_MASK)
-                       >> RCC_CFGR_HPRE_SHIFT)];
-               return sysclk >>= shift;
-               break;
-       case CLOCK_APB1:
-               shift = apb_psc_table[(
-                       (readl(&STM32_RCC->cfgr) & RCC_CFGR_APB1_PSC_MASK)
-                       >> RCC_CFGR_PPRE1_SHIFT)];
-               return sysclk >>= shift;
-               break;
-       case CLOCK_APB2:
-               shift = apb_psc_table[(
-                       (readl(&STM32_RCC->cfgr) & RCC_CFGR_APB2_PSC_MASK)
-                       >> RCC_CFGR_PPRE2_SHIFT)];
-               return sysclk >>= shift;
-               break;
-       default:
-               return 0;
-               break;
-       }
-}
diff --git a/arch/arm/mach-stm32/stm32f1/flash.c b/arch/arm/mach-stm32/stm32f1/flash.c
deleted file mode 100644 (file)
index 7d41f63..0000000
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * (C) Copyright 2015
- * Kamil Lulko, <kamil.lulko@gmail.com>
- *
- * Copyright 2015 ATS Advanced Telematics Systems GmbH
- * Copyright 2015 Konsulko Group, Matt Porter <mporter@konsulko.com>
- *
- * SPDX-License-Identifier:    GPL-2.0+
- */
-
-#include <common.h>
-#include <asm/io.h>
-#include <asm/arch/stm32.h>
-
-#define STM32_FLASH_KEY1       0x45670123
-#define STM32_FLASH_KEY2       0xcdef89ab
-
-#define STM32_NUM_BANKS        2
-#define STM32_MAX_BANK 0x200
-
-flash_info_t flash_info[STM32_NUM_BANKS];
-static struct stm32_flash_bank_regs *flash_bank[STM32_NUM_BANKS];
-
-static void stm32f1_flash_lock(u8 bank, u8 lock)
-{
-       if (lock) {
-               setbits_le32(&flash_bank[bank]->cr, STM32_FLASH_CR_LOCK);
-       } else {
-               writel(STM32_FLASH_KEY1, &flash_bank[bank]->keyr);
-               writel(STM32_FLASH_KEY2, &flash_bank[bank]->keyr);
-       }
-}
-
-/* Only XL devices are supported (2 KiB sector size) */
-unsigned long flash_init(void)
-{
-       u8 i, banks;
-       u16 j, size;
-
-       /* Set up accessors for XL devices with wonky register layout */
-       flash_bank[0] = (struct stm32_flash_bank_regs *)&STM32_FLASH->keyr;
-       flash_bank[1] = (struct stm32_flash_bank_regs *)&STM32_FLASH->keyr2;
-
-       /*
-        * Get total flash size (in KiB) and configure number of banks
-        * present and sector count per bank.
-        */
-       size = readw(&STM32_DES->flash_size);
-       if (size <= STM32_MAX_BANK) {
-               banks = 1;
-               flash_info[0].sector_count = size >> 1;
-       } else if (size > STM32_MAX_BANK) {
-               banks = 2;
-               flash_info[0].sector_count = STM32_MAX_BANK >> 1;
-               flash_info[1].sector_count = (size - STM32_MAX_BANK) >> 1;
-       }
-
-       /* Configure start/size for all sectors */
-       for (i = 0; i < banks; i++) {
-               flash_info[i].flash_id = FLASH_STM32F1;
-               flash_info[i].start[0] = CONFIG_SYS_FLASH_BASE + (i << 19);
-               flash_info[i].size = 2048;
-               for (j = 1; (j < flash_info[i].sector_count); j++) {
-                       flash_info[i].start[j] = flash_info[i].start[j - 1]
-                               + 2048;
-                       flash_info[i].size += 2048;
-               }
-       }
-
-       return size << 10;
-}
-
-void flash_print_info(flash_info_t *info)
-{
-       int i;
-
-       if (info->flash_id == FLASH_UNKNOWN) {
-               printf("Missing or unknown FLASH type\n");
-               return;
-       } else if (info->flash_id == FLASH_STM32F1) {
-               printf("STM32F1 Embedded Flash\n");
-       }
-
-       printf("  Size: %ld MB in %d Sectors\n",
-              info->size >> 10, info->sector_count);
-
-       printf("  Sector Start Addresses:");
-       for (i = 0; i < info->sector_count; ++i) {
-               if ((i % 5) == 0)
-                       printf("\n   ");
-               printf(" %08lX%s",
-                      info->start[i],
-                       info->protect[i] ? " (RO)" : "     ");
-       }
-       printf("\n");
-       return;
-}
-
-int flash_erase(flash_info_t *info, int first, int last)
-{
-       u8 bank = 0xff;
-       int i;
-
-       for (i = 0; i < STM32_NUM_BANKS; i++) {
-               if (info == &flash_info[i]) {
-                       bank = i;
-                       break;
-               }
-       }
-       if (bank == 0xff)
-               return -1;
-
-       stm32f1_flash_lock(bank, 0);
-
-       for (i = first; i <= last; i++) {
-               while (readl(&flash_bank[bank]->sr) & STM32_FLASH_SR_BSY)
-                       ;
-
-               setbits_le32(&flash_bank[bank]->cr, STM32_FLASH_CR_PER);
-
-               writel(info->start[i], &flash_bank[bank]->ar);
-
-               setbits_le32(&flash_bank[bank]->cr, STM32_FLASH_CR_STRT);
-
-               while (readl(&flash_bank[bank]->sr) & STM32_FLASH_SR_BSY)
-                       ;
-       }
-
-       clrbits_le32(&flash_bank[bank]->cr, STM32_FLASH_CR_PER);
-
-       stm32f1_flash_lock(bank, 1);
-
-       return 0;
-}
-
-int write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt)
-{
-       ulong i;
-       u8 bank = 0xff;
-
-       if (addr & 1) {
-               printf("Flash address must be half word aligned\n");
-               return -1;
-       }
-
-       if (cnt & 1) {
-               printf("Flash length must be half word aligned\n");
-               return -1;
-       }
-
-       for (i = 0; i < 2; i++) {
-               if (info == &flash_info[i]) {
-                       bank = i;
-                       break;
-               }
-       }
-
-       if (bank == 0xff)
-               return -1;
-
-       while (readl(&flash_bank[bank]->sr) & STM32_FLASH_SR_BSY)
-               ;
-
-       stm32f1_flash_lock(bank, 0);
-
-       setbits_le32(&flash_bank[bank]->cr, STM32_FLASH_CR_PG);
-
-       /* STM32F1 requires half word writes */
-       for (i = 0; i < cnt >> 1; i++) {
-               *(u16 *)(addr + i * 2) = ((u16 *)src)[i];
-               while (readl(&flash_bank[bank]->sr) & STM32_FLASH_SR_BSY)
-                       ;
-       }
-
-       clrbits_le32(&flash_bank[bank]->cr, STM32_FLASH_CR_PG);
-
-       stm32f1_flash_lock(bank, 1);
-
-       return 0;
-}
diff --git a/arch/arm/mach-stm32/stm32f1/soc.c b/arch/arm/mach-stm32/stm32f1/soc.c
deleted file mode 100644 (file)
index 4438621..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * (C) Copyright 2015
- * Kamil Lulko, <kamil.lulko@gmail.com>
- *
- * Copyright 2015 ATS Advanced Telematics Systems GmbH
- * Copyright 2015 Konsulko Group, Matt Porter <mporter@konsulko.com>
- *
- * SPDX-License-Identifier:    GPL-2.0+
- */
-
-#include <common.h>
-#include <asm/io.h>
-#include <asm/armv7m.h>
-#include <asm/arch/stm32.h>
-
-u32 get_cpu_rev(void)
-{
-       return 0;
-}
-
-int arch_cpu_init(void)
-{
-       configure_clocks();
-
-       /*
-        * Configure the memory protection unit (MPU) to allow full access to
-        * the whole 4GB address space.
-        */
-       writel(0, &V7M_MPU->rnr);
-       writel(0, &V7M_MPU->rbar);
-       writel((V7M_MPU_RASR_AP_RW_RW | V7M_MPU_RASR_SIZE_4GB
-               | V7M_MPU_RASR_EN), &V7M_MPU->rasr);
-       writel(V7M_MPU_CTRL_ENABLE | V7M_MPU_CTRL_HFNMIENA, &V7M_MPU->ctrl);
-
-       return 0;
-}
diff --git a/arch/arm/mach-stm32/stm32f1/timer.c b/arch/arm/mach-stm32/stm32f1/timer.c
deleted file mode 100644 (file)
index 6a26198..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * (C) Copyright 2015
- * Kamil Lulko, <kamil.lulko@gmail.com>
- *
- * Copyright 2015 ATS Advanced Telematics Systems GmbH
- * Copyright 2015 Konsulko Group, Matt Porter <mporter@konsulko.com>
- *
- * SPDX-License-Identifier:    GPL-2.0+
- */
-
-#include <common.h>
-#include <asm/io.h>
-#include <asm/armv7m.h>
-#include <asm/arch/stm32.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-#define STM32_TIM2_BASE        (STM32_APB1PERIPH_BASE + 0x0000)
-
-#define RCC_APB1ENR_TIM2EN     (1 << 0)
-
-struct stm32_tim2_5 {
-       u32 cr1;
-       u32 cr2;
-       u32 smcr;
-       u32 dier;
-       u32 sr;
-       u32 egr;
-       u32 ccmr1;
-       u32 ccmr2;
-       u32 ccer;
-       u32 cnt;
-       u32 psc;
-       u32 arr;
-       u32 reserved1;
-       u32 ccr1;
-       u32 ccr2;
-       u32 ccr3;
-       u32 ccr4;
-       u32 reserved2;
-       u32 dcr;
-       u32 dmar;
-       u32 or;
-};
-
-#define TIM_CR1_CEN    (1 << 0)
-
-#define TIM_EGR_UG     (1 << 0)
-
-int timer_init(void)
-{
-       struct stm32_tim2_5 *tim = (struct stm32_tim2_5 *)STM32_TIM2_BASE;
-
-       setbits_le32(&STM32_RCC->apb1enr, RCC_APB1ENR_TIM2EN);
-
-       if (clock_get(CLOCK_AHB) == clock_get(CLOCK_APB1))
-               writel((clock_get(CLOCK_APB1) / CONFIG_SYS_HZ_CLOCK) - 1,
-                      &tim->psc);
-       else
-               writel(((clock_get(CLOCK_APB1) * 2) / CONFIG_SYS_HZ_CLOCK) - 1,
-                      &tim->psc);
-
-       writel(0xFFFFFFFF, &tim->arr);
-       writel(TIM_CR1_CEN, &tim->cr1);
-       setbits_le32(&tim->egr, TIM_EGR_UG);
-
-       gd->arch.tbl = 0;
-       gd->arch.tbu = 0;
-       gd->arch.lastinc = 0;
-
-       return 0;
-}
-
-ulong get_timer(ulong base)
-{
-       return (get_ticks() / (CONFIG_SYS_HZ_CLOCK / CONFIG_SYS_HZ)) - base;
-}
-
-unsigned long long get_ticks(void)
-{
-       struct stm32_tim2_5 *tim = (struct stm32_tim2_5 *)STM32_TIM2_BASE;
-       u32 now;
-
-       now = readl(&tim->cnt);
-
-       if (now >= gd->arch.lastinc)
-               gd->arch.tbl += (now - gd->arch.lastinc);
-       else
-               gd->arch.tbl += (0xFFFFFFFF - gd->arch.lastinc) + now;
-
-       gd->arch.lastinc = now;
-
-       return gd->arch.tbl;
-}
-
-void reset_timer(void)
-{
-       struct stm32_tim2_5 *tim = (struct stm32_tim2_5 *)STM32_TIM2_BASE;
-
-       gd->arch.lastinc = readl(&tim->cnt);
-       gd->arch.tbl = 0;
-}
-
-/* delay x useconds */
-void __udelay(ulong usec)
-{
-       unsigned long long start;
-
-       start = get_ticks();            /* get current timestamp */
-       while ((get_ticks() - start) < usec)
-               ;                       /* loop till time has passed */
-}
-
-/*
- * This function is derived from PowerPC code (timebase clock frequency).
- * On ARM it returns the number of timer ticks per second.
- */
-ulong get_tbclk(void)
-{
-       return CONFIG_SYS_HZ_CLOCK;
-}
index 47bce4daa63652382343e05ff94770271e1d7caf..c513d0af10a6059b9256b5f44ad82bdaa031a3a9 100644 (file)
@@ -345,7 +345,7 @@ int board_init(void)
 
 static int init_dwmmc(void)
 {
-       int ret;
+       int ret = 0;
 
 #ifdef CONFIG_MMC_DW
 
index 183f93260d3ea05d7b0f22e3796f7914d70c4173..42d955c96aee9520bd68462b09ed01ff47b03f82 100644 (file)
@@ -773,6 +773,13 @@ config CMD_NAND_TORTURE
 
 endif # CMD_NAND
 
+config CMD_NVME
+       bool "nvme"
+       depends on NVME
+       default y if NVME
+       help
+         NVM Express device support
+
 config CMD_MMC_SPI
        bool "mmc_spi - Set up MMC SPI device"
        help
index 1bf6e3f71182c3a092bcfcecf069d0e86e27126d..13c86f8fccc2dadc24ad9fa0cdc65e46280530c0 100644 (file)
@@ -105,6 +105,7 @@ obj-$(CONFIG_CMD_REISER) += reiser.o
 obj-$(CONFIG_CMD_REMOTEPROC) += remoteproc.o
 obj-$(CONFIG_SANDBOX) += host.o
 obj-$(CONFIG_CMD_SATA) += sata.o
+obj-$(CONFIG_CMD_NVME) += nvme.o
 obj-$(CONFIG_CMD_SF) += sf.o
 obj-$(CONFIG_CMD_SCSI) += scsi.o disk.o
 obj-$(CONFIG_CMD_SHA1SUM) += sha1sum.o
index 81ac78da940ce60726707f26e92dedc11c10f738..96d7b72df2333cc5be9400a350daa860896dc1ca 100644 (file)
@@ -166,7 +166,7 @@ static inline void __maybe_unused print_std_bdinfo(const bd_t *bd)
 #if defined(CONFIG_PPC)
 void __weak board_detail(void)
 {
-       /* Please define boot_detail() for your platform */
+       /* Please define board_detail() for your platform */
 }
 
 int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
diff --git a/cmd/nvme.c b/cmd/nvme.c
new file mode 100644 (file)
index 0000000..e1ef95f
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2017 NXP Semiconductors
+ * Copyright (C) 2017 Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <command.h>
+#include <dm.h>
+#include <nvme.h>
+#include <part.h>
+#include <linux/math64.h>
+
+static int nvme_curr_device;
+
+static int do_nvme_scan(cmd_tbl_t *cmdtp, int flag,
+               int argc, char * const argv[])
+{
+       int ret;
+
+       ret = nvme_scan_namespace();
+       if (ret)
+               return CMD_RET_FAILURE;
+
+       return CMD_RET_SUCCESS;
+}
+
+static int do_nvme_list(cmd_tbl_t *cmdtp, int flag,
+               int argc, char * const argv[])
+{
+       blk_list_devices(IF_TYPE_NVME);
+
+       return CMD_RET_SUCCESS;
+}
+
+static int do_nvme_info(cmd_tbl_t *cmdtp, int flag,
+               int argc, char * const argv[])
+{
+       int devnum;
+       struct udevice *udev;
+       int ret;
+
+       if (argc > 1)
+               devnum = (int)simple_strtoul(argv[1], NULL, 10);
+       else
+               devnum = nvme_curr_device;
+
+       ret = blk_get_device(IF_TYPE_NVME, devnum, &udev);
+       if (ret < 0)
+               return CMD_RET_FAILURE;
+
+       nvme_print_info(udev);
+
+       return CMD_RET_SUCCESS;
+}
+
+static int do_nvme_device(cmd_tbl_t *cmdtp, int flag,
+               int argc, char * const argv[])
+{
+       if (argc > 1) {
+               int devnum = (int)simple_strtoul(argv[1], NULL, 10);
+
+               if (!blk_show_device(IF_TYPE_NVME, devnum)) {
+                       nvme_curr_device = devnum;
+                       printf("... is now current device\n");
+               } else {
+                       return CMD_RET_FAILURE;
+               }
+       } else {
+               blk_show_device(IF_TYPE_NVME, nvme_curr_device);
+       }
+
+       return CMD_RET_SUCCESS;
+}
+
+static int do_nvme_part(cmd_tbl_t *cmdtp, int flag,
+               int argc, char * const argv[])
+{
+       if (argc > 1) {
+               int devnum = (int)simple_strtoul(argv[2], NULL, 10);
+
+               if (blk_print_part_devnum(IF_TYPE_NVME, devnum)) {
+                       printf("\nNVMe device %d not available\n", devnum);
+                       return CMD_RET_FAILURE;
+               }
+       } else {
+               blk_print_part_devnum(IF_TYPE_NVME, nvme_curr_device);
+       }
+
+       return CMD_RET_SUCCESS;
+}
+
+static int do_nvme_read(cmd_tbl_t *cmdtp, int flag, int argc,
+               char * const argv[])
+{
+       unsigned long time;
+       if (argc != 4)
+               return CMD_RET_USAGE;
+
+       ulong addr = simple_strtoul(argv[1], NULL, 16);
+       ulong cnt = simple_strtoul(argv[3], NULL, 16);
+       ulong n;
+       lbaint_t blk = simple_strtoul(argv[2], NULL, 16);
+
+       printf("\nNVMe read: device %d block # " LBAFU " count %ld ... ",
+              nvme_curr_device, blk, cnt);
+
+       time = get_timer(0);
+       n = blk_read_devnum(IF_TYPE_NVME, nvme_curr_device, blk,
+                           cnt, (ulong *)addr);
+       time = get_timer(time);
+
+       printf("read: %s\n", (n == cnt) ? "OK" : "ERROR");
+       printf("%lu bytes read in %lu ms", cnt * 512, time);
+       if (time > 0) {
+               puts(" (");
+               print_size(div_u64(cnt * 512, time) * 1000, "/s");
+               puts(")");
+       }
+       puts("\n");
+
+       return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
+}
+
+static int do_nvme_write(cmd_tbl_t *cmdtp, int flag, int argc,
+               char * const argv[])
+{
+       unsigned long time;
+       if (argc != 4)
+               return CMD_RET_USAGE;
+
+       ulong addr = simple_strtoul(argv[1], NULL, 16);
+       ulong cnt = simple_strtoul(argv[3], NULL, 16);
+       ulong n;
+       lbaint_t blk = simple_strtoul(argv[2], NULL, 16);
+
+       printf("\nNVMe write: device %d block # " LBAFU " count %ld ... ",
+              nvme_curr_device, blk, cnt);
+
+       time = get_timer(0);
+       n = blk_write_devnum(IF_TYPE_NVME, nvme_curr_device, blk,
+                           cnt, (ulong *)addr);
+       time = get_timer(time);
+
+       printf("write: %s\n", (n == cnt) ? "OK" : "ERROR");
+       printf("%lu bytes write in %lu ms", cnt * 512, time);
+       if (time > 0) {
+               puts(" (");
+               print_size(div_u64(cnt * 512, time) * 1000, "/s");
+               puts(")");
+       }
+       puts("\n");
+
+       return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
+}
+
+static cmd_tbl_t cmd_nvme[] = {
+       U_BOOT_CMD_MKENT(scan, 1, 1, do_nvme_scan, "", ""),
+       U_BOOT_CMD_MKENT(list, 1, 1, do_nvme_list, "", ""),
+       U_BOOT_CMD_MKENT(info, 2, 1, do_nvme_info, "", ""),
+       U_BOOT_CMD_MKENT(device, 2, 1, do_nvme_device, "", ""),
+       U_BOOT_CMD_MKENT(part, 2, 1, do_nvme_part, "", ""),
+       U_BOOT_CMD_MKENT(write, 4, 0, do_nvme_write, "", ""),
+       U_BOOT_CMD_MKENT(read, 4, 0, do_nvme_read, "", "")
+};
+
+static int do_nvmecops(cmd_tbl_t *cmdtp, int flag, int argc,
+               char * const argv[])
+{
+       cmd_tbl_t *cp;
+
+       cp = find_cmd_tbl(argv[1], cmd_nvme, ARRAY_SIZE(cmd_nvme));
+
+       argc--;
+       argv++;
+
+       if (cp == NULL || argc > cp->maxargs)
+               return CMD_RET_USAGE;
+
+       if (flag == CMD_FLAG_REPEAT && !cp->repeatable)
+               return CMD_RET_SUCCESS;
+
+       return cp->cmd(cmdtp, flag, argc, argv);
+}
+
+U_BOOT_CMD(
+       nvme, 8, 1, do_nvmecops,
+       "NVM Express sub-system",
+       "\nnvme scan - scan NVMe blk devices\n"
+       "nvme list - show all available NVMe blk devices\n"
+       "nvme info [dev]- show current or a specific NVMe blk device\n"
+       "nvme device [dev] - show or set current device\n"
+       "nvme part [dev] - print partition table\n"
+       "nvme read  addr blk# cnt\n"
+       "nvme write addr blk# cnt"
+);
index 51440a6e6f32ae27793904219367ea825a39ccd9..0a723150b5883f32301cf87ab2ccfede2949db35 100644 (file)
@@ -25,7 +25,7 @@ int fdt_offset(void *fit)
        images = fdt_path_offset(fit, FIT_IMAGES_PATH);
        if (images < 0) {
                debug("%s: Cannot find /images node: %d\n", __func__, images);
-               return FDT_ERROR;
+               return -EINVAL;
        }
 
        fdt_name = fdt_getprop(fit, node, FIT_FDT_PROP, &fdt_len);
index 41ca490759cf998a26a93eb5d81c47a817837971..eadd59e4e76e8aa3d9d83819d806c5b70347849b 100644 (file)
@@ -54,6 +54,7 @@ CONFIG_MMC_OMAP_HS=y
 CONFIG_PHYLIB=y
 CONFIG_NAND=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_USB=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_USB_MUSB_GADGET=y
index bbda9d3e6eb00b66ed59ab36cb0dd6d84d25c606..ecf55d6da6a9150cd8e45e2983a19cd233866fa6 100644 (file)
@@ -35,6 +35,7 @@ CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_PHYLIB=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_USB=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_USB_MUSB_GADGET=y
index 596a083c7c5c39313af4674032bc217af58c6a01..570c668a7fec50afd7134eb8a6e7ddab039f7d48 100644 (file)
@@ -43,6 +43,7 @@ CONFIG_PHYLIB=y
 CONFIG_DM_ETH=y
 CONFIG_PHY_GIGE=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_TIMER=y
 CONFIG_OMAP_TIMER=y
 CONFIG_USB=y
index e05f50efe486c47d1c81e4e30b8bcf2c8e44ea7b..9f88a42cdc980d84b6046d9b5a38b6a124ae15d4 100644 (file)
@@ -42,6 +42,7 @@ CONFIG_PHYLIB=y
 CONFIG_DM_ETH=y
 CONFIG_PHY_GIGE=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_TIMER=y
 CONFIG_OMAP_TIMER=y
 CONFIG_USB=y
index e78bb97ea57ac03ecb73a89a9bb537c59f617421..b61e5168a2919ade675284e0af169457f6eab0e0 100644 (file)
@@ -33,6 +33,7 @@ CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_PHYLIB=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_USB=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_USB_MUSB_GADGET=y
index 9f7247bcb4f17539b99793f40e9660384a7b6255..2aa67b0f2eae0247baf56ba992f13fb43098025e 100644 (file)
@@ -28,6 +28,7 @@ CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_PHYLIB=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_USB=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_USB_MUSB_GADGET=y
index 607ac07196af4ea97ff2d17582612038534bce30..2a55d352218b2bbe3e66f0d3f7364f5936c71b7e 100644 (file)
@@ -32,6 +32,7 @@ CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_PHYLIB=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_USB=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_USB_MUSB_GADGET=y
index 54f8bcd234fa783c4e8dce587aa886ece5e4fcd7..666b6323f034edbc32bd65327a5c506d5479b7e5 100644 (file)
@@ -36,6 +36,7 @@ CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_PHYLIB=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_USB=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_USB_MUSB_GADGET=y
index 7acbf8e76b705b2697eabbbda75a31c7a477969f..dabfcbb9ba5e913480f280a3e6d10a0a53aefcc8 100644 (file)
@@ -43,6 +43,7 @@ CONFIG_PHYLIB=y
 CONFIG_DM_ETH=y
 CONFIG_PHY_GIGE=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_TIMER=y
 CONFIG_OMAP_TIMER=y
 CONFIG_USB=y
index 464f53f9ca0d21af199741a025b27c840c50610b..d26ebd57bb1657bdae8e3e4033ee9095f7efddfc 100644 (file)
@@ -56,6 +56,7 @@ CONFIG_NAND=y
 CONFIG_MTD_UBI_FASTMAP=y
 CONFIG_PHYLIB=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
 CONFIG_FDT_FIXUP_PARTITIONS=y
index 9361824e07885674ccd3e0f2785c75aea65348ec..2508d7fcb9a00b04b640946e7fb28fd1b3a920b9 100644 (file)
@@ -41,6 +41,7 @@ CONFIG_ISO_PARTITION=y
 CONFIG_MMC_OMAP_HS=y
 CONFIG_PHYLIB=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_FAT_WRITE=y
 CONFIG_LZO=y
 CONFIG_OF_LIBFDT=y
index 160e3690e77d0b7cdcb766d2e7e4869bd173dc25..3175b07fc3060b70ae927111b1a6473e2c755702 100644 (file)
@@ -41,6 +41,7 @@ CONFIG_ISO_PARTITION=y
 CONFIG_MMC_OMAP_HS=y
 CONFIG_PHYLIB=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_FAT_WRITE=y
 CONFIG_LZO=y
 CONFIG_OF_LIBFDT=y
index 9eac46d13c5c980523792ec874cce3beeef3e191..aa3837582eeca92002a0642d861480ca21a627f6 100644 (file)
@@ -42,6 +42,7 @@ CONFIG_ISO_PARTITION=y
 CONFIG_MMC_OMAP_HS=y
 CONFIG_PHYLIB=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_FAT_WRITE=y
 CONFIG_LZO=y
 CONFIG_OF_LIBFDT=y
index a6c6c57325e2e53825e902aabc1037ca2f759d8e..36a0e3ca5e1ccb9280b8851924b88ff6f2b8141d 100644 (file)
@@ -39,6 +39,7 @@ CONFIG_ISO_PARTITION=y
 CONFIG_MMC_OMAP_HS=y
 CONFIG_PHYLIB=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_FAT_WRITE=y
 CONFIG_LZO=y
 CONFIG_OF_LIBFDT=y
index 2be46460fbab772df666d0ca937488a62e28bd2e..667cdda9fde8f6869e13e1b32d987e248808026c 100644 (file)
@@ -41,6 +41,7 @@ CONFIG_ISO_PARTITION=y
 CONFIG_MMC_OMAP_HS=y
 CONFIG_PHYLIB=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_FAT_WRITE=y
 CONFIG_LZO=y
 CONFIG_OF_LIBFDT=y
index 2be46460fbab772df666d0ca937488a62e28bd2e..667cdda9fde8f6869e13e1b32d987e248808026c 100644 (file)
@@ -41,6 +41,7 @@ CONFIG_ISO_PARTITION=y
 CONFIG_MMC_OMAP_HS=y
 CONFIG_PHYLIB=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_FAT_WRITE=y
 CONFIG_LZO=y
 CONFIG_OF_LIBFDT=y
index e0956d5b99aef2f61ecbe8a5d51a41bdcfb2d826..1dd315b36a4a38b77c7860224a0ab02317666631 100644 (file)
@@ -43,6 +43,7 @@ CONFIG_CMD_EXT4_WRITE=y
 CONFIG_MMC_OMAP_HS=y
 CONFIG_PHYLIB=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_FAT_WRITE=y
 CONFIG_LZO=y
 CONFIG_OF_LIBFDT=y
index e161037c4c10df6352d8243f6de39fab406c6431..a8b58349a85cb41eb684789767fcee81f0b3f9e7 100644 (file)
@@ -57,6 +57,7 @@ CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_PHYLIB=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_USB=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_USB_MUSB_GADGET=y
index f040aa05886db6c24ba7b41e52af07d7dcb37e1a..40dc0916e8d4430573d052b3f13ca9da33bfd050 100644 (file)
@@ -57,6 +57,7 @@ CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_PHYLIB=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_USB=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_USB_MUSB_GADGET=y
index 2227830802816089d322415e2e56d8778737f912..dfa6deeec039d5c9729867511f72a85927c02e22 100644 (file)
@@ -62,6 +62,7 @@ CONFIG_SPI_FLASH_STMICRO=y
 # CONFIG_SPI_FLASH_USE_4K_SECTORS is not set
 CONFIG_PHYLIB=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_USB=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_USB_STORAGE=y
index afdecc71b53d85f5aa9b0df189196caaeeffc2aa..89541a3429fc96d507b74c218f972ecdb8448d2d 100644 (file)
@@ -41,5 +41,6 @@ CONFIG_EFI_PARTITION=y
 CONFIG_MMC_OMAP_HS=y
 CONFIG_NAND=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
index 8b2895242d61122f47ba031535042d2895995b28..5de8382f1972244e07d25819a5dece82af4f5791 100644 (file)
@@ -43,6 +43,7 @@ CONFIG_MMC_OMAP_HS=y
 CONFIG_PHYLIB=y
 CONFIG_NAND=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_USB=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_USB_STORAGE=y
index d5550feda857674f088d894c06f4b9828b863ca8..f6d832eed8901f1fd01017a2e5f0f65ec262ac23 100644 (file)
@@ -38,6 +38,7 @@ CONFIG_LED_STATUS_BOOT_ENABLE=y
 CONFIG_LED_STATUS_BOOT=0
 CONFIG_MMC_OMAP_HS=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_USB=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_USB_STORAGE=y
index 16f1eab92738865b192819acff6cbf2fab191caf..3a04597aaf3b35a10cadaa736aeb307e6ad1590a 100644 (file)
@@ -40,6 +40,7 @@ CONFIG_LED_STATUS_BOOT_ENABLE=y
 CONFIG_LED_STATUS_BOOT=0
 CONFIG_MMC_OMAP_HS=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
index 7d8d44c6d1b7d373f7318fdc066a003b362eb322..dbccc39438797dbdf2b22a6299a2d0315fd4c735 100644 (file)
@@ -68,6 +68,7 @@ CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_PHYLIB=y
 CONFIG_DM_SERIAL=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
index 4aed572cf6a4c7824c92706d6f181ba52ad196ad..d3297de65794e4de32be4d89d58f2792d0231cc3 100644 (file)
@@ -42,6 +42,8 @@ CONFIG_EFI_PARTITION=y
 CONFIG_MMC_OMAP_HS=y
 CONFIG_SCSI=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
+CONFIG_OMAP3_SPI=y
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
index b6609d949d762bb147bcf28afc96310cf0ffad02..c3b1f3dcfebfe77e9db5a162e6d9200c55b4b5b9 100644 (file)
@@ -60,6 +60,7 @@ CONFIG_MTD_UBI_FASTMAP=y
 CONFIG_MTD_UBI_FASTMAP_AUTOCONVERT=1
 CONFIG_PHYLIB=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_USB=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_USB_MUSB_GADGET=y
index ced8156a73f80a27502aa2e80aa34084b17f8448..d4b89433e79f62f830e694183526512b8e805e49 100644 (file)
@@ -26,6 +26,7 @@ CONFIG_CMD_EXT4_WRITE=y
 CONFIG_SPL_PARTITION_UUIDS=y
 CONFIG_MMC_OMAP_HS=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
index 9ab6058e9176a9e3535c567bb844403b84de3c06..b376dc83be18749ca1064e5cfb088c6e73a38db6 100644 (file)
@@ -60,6 +60,7 @@ CONFIG_MTD_UBI_FASTMAP=y
 CONFIG_MTD_UBI_FASTMAP_AUTOCONVERT=1
 CONFIG_PHYLIB=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_USB=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_USB_MUSB_GADGET=y
index 255b38e7d76429affa4b543932f9a836d9839834..e33f85cfc6d4a629e3f6fe1b2e9289275cf0b40d 100644 (file)
@@ -42,6 +42,7 @@ CONFIG_MMC_OMAP_HS=y
 CONFIG_NAND=y
 CONFIG_MTD_UBI_FASTMAP=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
 CONFIG_FDT_FIXUP_PARTITIONS=y
index bd491812d78aa80dac2b4de207f43e7781a0ca0d..b54954ada5d6a8f4baf64515e026a8b99be1f3ea 100644 (file)
@@ -41,6 +41,7 @@ CONFIG_LED_STATUS_BOOT=0
 CONFIG_MMC_OMAP_HS=y
 CONFIG_NAND=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
 CONFIG_FDT_FIXUP_PARTITIONS=y
index e8c704e99a0678b1439f54e7421d456c60b21e83..5aed8fc71e873c846c7a434b0300f35e277b40b5 100644 (file)
@@ -33,6 +33,7 @@ CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_MMC_OMAP_HS=y
 CONFIG_NAND=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
 CONFIG_FDT_FIXUP_PARTITIONS=y
index 3802bc57d19bc0c23ff19c9488151ddf309692cf..1461c88fd0d61e4d0bdc66224e06f6ce57b74fc6 100644 (file)
@@ -28,5 +28,6 @@ CONFIG_CMD_EXT4=y
 CONFIG_CMD_FAT=y
 CONFIG_MMC_OMAP_HS=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_CFB_CONSOLE_ANSI=y
 # CONFIG_VGA_AS_SINGLE_DEVICE is not set
index 1944c0cdb2d9b8e2648a19cbff8cbcf59fb3a635..9d22ca80a331e8a6723fc07554c5f6532a32363b 100644 (file)
@@ -38,6 +38,7 @@ CONFIG_LED_STATUS_CMD=y
 CONFIG_MMC_OMAP_HS=y
 CONFIG_NAND=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_MUSB_GADGET=y
index 9bbc9803f1220401b8e30717a17189d95aeeab0b..a07ea0fd5528b97c657afcfad6f4872422b29892 100644 (file)
@@ -47,6 +47,7 @@ CONFIG_MMC_OMAP_HS=y
 CONFIG_MTD=y
 CONFIG_DM_SERIAL=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_MUSB_GADGET=y
index f88c2e197ad39f804d1b5c532be92a10b667297d..970f165211a5eeea56fafd24202eeae39456feb6 100644 (file)
@@ -26,6 +26,7 @@ CONFIG_CMD_FAT=y
 CONFIG_CMD_MTDPARTS=y
 CONFIG_MMC_OMAP_HS=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
index 464a41f2f610ab5c0a361817fd3313ffa6cb1597..81b60640071541914d381fc4bdc2f95964ecd7f3 100644 (file)
@@ -37,6 +37,7 @@ CONFIG_MMC_OMAP_HS=y
 CONFIG_MMC_OMAP36XX_PINS=y
 CONFIG_NAND=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_USB=y
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_USB_GADGET=y
index 1fc77520286cb49bff979c75b993655d5545c09a..b18fe365cfada0176b7c429920bf8d5c26e7ff73 100644 (file)
@@ -45,6 +45,7 @@ CONFIG_EFI_PARTITION=y
 CONFIG_MMC_OMAP_HS=y
 CONFIG_NAND=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
index 3a33b7bd18b223cac81d7a8a4f53b2b0cf332e09..97c6cb39228d7cf3c332588156d45c46dca81d1a 100644 (file)
@@ -27,5 +27,6 @@ CONFIG_CMD_UBI=y
 CONFIG_MMC_OMAP_HS=y
 CONFIG_NAND=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
index 1b6eb300c9d479ebcfa2bdeec984a65a19eb293b..03b4f0097abef37a20ce02af46ac233879750cc8 100644 (file)
@@ -34,5 +34,6 @@ CONFIG_EFI_PARTITION=y
 CONFIG_MMC_OMAP_HS=y
 CONFIG_NAND=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
index 3e39e2f0dfc43093e11f9732e2ca4acb7da53807..ce4e2aa743ce973dc2a864fdb4e6d81e86749a70 100644 (file)
@@ -28,6 +28,7 @@ CONFIG_CMD_GPIO=y
 CONFIG_CMD_EXT4_WRITE=y
 CONFIG_MMC_OMAP_HS=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
index 04198e5d8381ecf804c24613e69f2b52035989f7..af519be4518c1c4c6892f2b0962f1c55260cfd05 100644 (file)
@@ -26,5 +26,6 @@ CONFIG_CMD_GPIO=y
 CONFIG_CMD_EXT4_WRITE=y
 CONFIG_MMC_OMAP_HS=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
index 273be581145894e699f665119706428c459a4c3f..90dd62a791141627634424d14f975e959a792123 100644 (file)
@@ -40,6 +40,7 @@ CONFIG_CMD_TCA642X=y
 CONFIG_MMC_OMAP_HS=y
 CONFIG_SCSI=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_DWC3=y
index cd0af42dd247e78bdb35d060ed18303a5a5b3f17..47ca96054903d962fd8a339b5624ccc3d2e699ad 100644 (file)
@@ -55,6 +55,7 @@ CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_PHYLIB=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_USB=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_USB_MUSB_GADGET=y
index b16020a554d0c86db7a85fa600eaff7fca238dd1..7185a9053c322598bbb9bed0a4ca3eb21c67ece6 100644 (file)
@@ -55,6 +55,7 @@ CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_PHYLIB=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_USB=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_USB_MUSB_GADGET=y
index d3235d923a27a8b085c8e60d5f2c4cb6bbdf25c4..a8a435cf29de3210c38df89739b5042a5cc1b06e 100644 (file)
@@ -58,6 +58,7 @@ CONFIG_MMC_OMAP_HS=y
 CONFIG_PHYLIB=y
 CONFIG_NAND=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_USB=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_USB_MUSB_GADGET=y
index a7e057499acb874ec08e3789ed3fa10a03bcf721..05564370317fe8331099fc80c95e8b7016bbef8d 100644 (file)
@@ -45,5 +45,6 @@ CONFIG_PHY_MICREL=y
 CONFIG_PHY_MICREL_KSZ90X1=y
 CONFIG_NETDEVICES=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
index 5bceca7c2f81122ca38798428eb0612f257509dd..2422ed4656e08dedeeb324083163b8d1087cb8e0 100644 (file)
@@ -64,6 +64,7 @@ CONFIG_MTD_UBI_FASTMAP=y
 CONFIG_MTD_UBI_FASTMAP_AUTOCONVERT=1
 CONFIG_PHYLIB=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_USB=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_USB_MUSB_GADGET=y
index 293309c994407f3e606b9b13859fb3776c7e5b1f..fef396076d98830994294cee575e26e31d012bde 100644 (file)
@@ -37,6 +37,7 @@ CONFIG_EFI_PARTITION=y
 CONFIG_REGMAP=y
 CONFIG_SYSCON=y
 CONFIG_CPU=y
+CONFIG_NVME=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_KEYBOARD=y
 CONFIG_FRAMEBUFFER_SET_VESA_MODE=y
index 7bbe4d91eec8be3756a735062b6f1ff0e566c441..2488ed63f322b34bbbdbad3ddd31cd7006ab7a2d 100644 (file)
@@ -60,6 +60,7 @@ CONFIG_MTD_UBI_FASTMAP=y
 CONFIG_MTD_UBI_FASTMAP_AUTOCONVERT=1
 CONFIG_PHYLIB=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_USB=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_USB_MUSB_GADGET=y
index 291d51461c449f1614d241af4014c77aa645b3e3..0a1022fb09951aee4ad68c2456ee84649c65ec2e 100644 (file)
@@ -65,6 +65,7 @@ CONFIG_MTD_UBI_FASTMAP=y
 CONFIG_MTD_UBI_FASTMAP_AUTOCONVERT=1
 CONFIG_PHYLIB=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_USB=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_USB_MUSB_GADGET=y
index e6c7e605974362da197a14d9a2582f12dcad96e0..2489a0f9a12ff38f5886e45d03ad612e30a210dc 100644 (file)
@@ -26,6 +26,7 @@ CONFIG_CMD_FAT=y
 CONFIG_CMD_MTDPARTS=y
 CONFIG_MMC_OMAP_HS=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
index 81b34c6a580d5fbf4f1ffcc3e321b8115d386b62..1ad879b78b5127d361bb6c707f818771a85d1243 100644 (file)
@@ -60,6 +60,7 @@ CONFIG_MTD_UBI_FASTMAP=y
 CONFIG_MTD_UBI_FASTMAP_AUTOCONVERT=1
 CONFIG_PHYLIB=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 CONFIG_USB=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_USB_MUSB_GADGET=y
index bc1f7c8db258d4c503667e2193e3abeb21cafb88..9106a05498e646e266d65214ab5de1ce9a57c51f 100644 (file)
@@ -42,4 +42,5 @@ CONFIG_SYS_I2C_OMAP24XX=y
 CONFIG_MMC_OMAP_HS=y
 CONFIG_NAND=y
 CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
 # CONFIG_USE_PRIVATE_LIBGCC is not set
index e640a55163f2d28f69bb869fd775317199b8154c..d76aa903a8c6deba137d710e6be320fe566056bb 100644 (file)
@@ -132,6 +132,7 @@ void dev_print (struct blk_desc *dev_desc)
        case IF_TYPE_SD:
        case IF_TYPE_MMC:
        case IF_TYPE_USB:
+       case IF_TYPE_NVME:
                printf ("Vendor: %s Rev: %s Prod: %s\n",
                        dev_desc->vendor,
                        dev_desc->revision,
@@ -263,7 +264,10 @@ static void print_part_header(const char *type, struct blk_desc *dev_desc)
                puts ("MMC");
                break;
        case IF_TYPE_HOST:
-               puts("HOST");
+               puts ("HOST");
+               break;
+       case IF_TYPE_NVME:
+               puts ("NVMe");
                break;
        default:
                puts ("UNKNOWN");
diff --git a/doc/README.nvme b/doc/README.nvme
new file mode 100644 (file)
index 0000000..3afa912
--- /dev/null
@@ -0,0 +1,86 @@
+#
+# Copyright (C) 2017 NXP Semiconductors
+# Copyright (C) 2017 Bin Meng <bmeng.cn@gmail.com>
+#
+# SPDX-License-Identifier:     GPL-2.0+
+#
+
+What is NVMe
+============
+
+NVM Express (NVMe) is a register level interface that allows host software to
+communicate with a non-volatile memory subsystem. This interface is optimized
+for enterprise and client solid state drives, typically attached to the PCI
+express interface. It is a scalable host controller interface designed to
+address the needs of enterprise and client systems that utilize PCI express
+based solid state drives (SSD). The interface provides optimized command
+submission and completion paths. It includes support for parallel operation by
+supporting up to 64K I/O queues with up to 64K commands per I/O queue.
+
+The device is comprised of some number of controllers, where each controller
+is comprised of some number of namespaces, where each namespace is comprised
+of some number of logical blocks. A namespace is a quantity of non-volatile
+memory that is formatted into logical blocks. An NVMe namespace is equivalent
+to a SCSI LUN. Each namespace is operated as an independent "device".
+
+How it works
+------------
+There is an NVMe uclass driver (driver name "nvme"), an NVMe host controller
+driver (driver name "nvme") and an NVMe namespace block driver (driver name
+"nvme-blk"). The host controller driver is supposed to probe the hardware and
+do necessary initialization to put the controller into a ready state at which
+it is able to scan all available namespaces attached to it. Scanning namespace
+is triggered by the NVMe uclass driver and the actual work is done in the NVMe
+namespace block driver.
+
+Status
+------
+It only support basic block read/write functions in the NVMe driver.
+
+Config options
+--------------
+CONFIG_NVME    Enable NVMe device support
+CONFIG_CMD_NVME        Enable basic NVMe commands
+
+Usage in U-Boot
+---------------
+To use an NVMe hard disk from U-Boot shell, a 'nvme scan' command needs to
+be executed for all NVMe hard disks attached to the NVMe controller to be
+identified.
+
+To list all of the NVMe hard disks, try:
+
+  => nvme list
+  Device 0: Vendor: 0x8086 Rev: 8DV10131 Prod: CVFT535600LS400BGN
+           Type: Hard Disk
+           Capacity: 381554.0 MB = 372.6 GB (781422768 x 512)
+
+and print out detailed information for controller and namespaces via:
+
+  => nvme info
+
+Raw block read/write to can be done via the 'nvme read/write' commands:
+
+  => nvme read a0000000 0 11000
+
+  => tftp 80000000 /tftpboot/kernel.itb
+  => nvme write 80000000 0 11000
+
+Of course, file system command can be used on the NVMe hard disk as well:
+
+  => fatls nvme 0:1
+       32376967   kernel.itb
+       22929408   100m
+
+       2 file(s), 0 dir(s)
+
+  => fatload nvme 0:1 a0000000 /kernel.itb
+  => bootm a0000000
+
+Testing NVMe with QEMU x86
+--------------------------
+QEMU supports NVMe emulation and we can test NVMe driver with QEMU x86 running
+U-Boot. Please see README.x86 for how to build u-boot.rom image for QEMU x86.
+
+Example command line to call QEMU x86 below with emulated NVMe device:
+$ ./qemu-system-i386 -drive file=nvme.img,if=none,id=drv0 -device nvme,drive=drv0,serial=QEMUNVME0001 -bios u-boot.rom
index 2e03133c4364c31e4d44ec1b99a2de6f887e3865..613e60235dc41b7c2129aebb773e1e073d7e937b 100644 (file)
@@ -50,6 +50,8 @@ source "drivers/mtd/Kconfig"
 
 source "drivers/net/Kconfig"
 
+source "drivers/nvme/Kconfig"
+
 source "drivers/pci/Kconfig"
 
 source "drivers/pcmcia/Kconfig"
index 0e0fdf0208917d327813feaf4b34f40403eb94e7..dab5c182c2c9d6d253a80e0045de96b2f9de75c1 100644 (file)
@@ -74,6 +74,7 @@ obj-y += firmware/
 obj-$(CONFIG_FPGA) += fpga/
 obj-y += misc/
 obj-$(CONFIG_MMC) += mmc/
+obj-$(CONFIG_NVME) += nvme/
 obj-y += pcmcia/
 obj-y += dfu/
 obj-$(CONFIG_X86) += pch/
index 23f131b7ad74b0a363038ef5bcd0b667e871c082..a3737badec6df61ca318cfee975f6f95a6535191 100644 (file)
@@ -22,6 +22,7 @@ static const char *if_typename_str[IF_TYPE_COUNT] = {
        [IF_TYPE_SATA]          = "sata",
        [IF_TYPE_HOST]          = "host",
        [IF_TYPE_SYSTEMACE]     = "ace",
+       [IF_TYPE_NVME]          = "nvme",
 };
 
 static enum uclass_id if_type_uclass_id[IF_TYPE_COUNT] = {
@@ -34,6 +35,7 @@ static enum uclass_id if_type_uclass_id[IF_TYPE_COUNT] = {
        [IF_TYPE_SD]            = UCLASS_INVALID,
        [IF_TYPE_SATA]          = UCLASS_AHCI,
        [IF_TYPE_HOST]          = UCLASS_ROOT,
+       [IF_TYPE_NVME]          = UCLASS_NVME,
        [IF_TYPE_SYSTEMACE]     = UCLASS_INVALID,
 };
 
index 12b5b04109d3e5090121ada7b075a907a6b4e057..a704a3e9d314fe24d57e57a091de006f771fca9d 100644 (file)
@@ -327,8 +327,6 @@ int ddr3_tip_print_log(u32 dev_num, u32 mem_addr)
        u32 if_id = 0;
        struct hws_topology_map *tm = ddr3_get_topology_map();
 
-       mem_addr = mem_addr;
-
 #ifndef EXCLUDE_SWITCH_DEBUG
        if ((is_validate_window_per_if != 0) ||
            (is_validate_window_per_pup != 0)) {
@@ -820,7 +818,6 @@ static int ddr3_tip_access_atr(u32 dev_num, u32 flag_id, u32 value, u32 **ptr)
        u32 tmp_val = 0, if_id = 0, pup_id = 0;
        struct hws_topology_map *tm = ddr3_get_topology_map();
 
-       dev_num = dev_num;
        *ptr = NULL;
 
        switch (flag_id) {
@@ -1169,8 +1166,6 @@ int print_adll(u32 dev_num, u32 adll[MAX_INTERFACE_NUM * MAX_BUS_NUM])
        u32 i, j;
        struct hws_topology_map *tm = ddr3_get_topology_map();
 
-       dev_num = dev_num;
-
        for (j = 0; j < tm->num_of_bus_per_interface; j++) {
                VALIDATE_ACTIVE(tm->bus_act_mask, j);
                for (i = 0; i < MAX_INTERFACE_NUM; i++) {
@@ -1229,8 +1224,6 @@ int ddr3_tip_sweep_test(u32 dev_num, u32 test_type,
        u32 reg_addr = 0;
        struct hws_topology_map *tm = ddr3_get_topology_map();
 
-       mem_addr = mem_addr;
-
        if (test_type == 0) {
                reg_addr = 1;
                ui_mask_bit = 0x3f;
@@ -1301,8 +1294,6 @@ int ddr3_tip_run_sweep_test(int dev_num, u32 repeat_num, u32 direction,
        u32 max_cs = hws_ddr3_tip_max_cs_get();
        struct hws_topology_map *tm = ddr3_get_topology_map();
 
-       repeat_num = repeat_num;
-
        if (mode == 1) {
                /* per pup */
                start_pup = 0;
index 9d216da96dce5de85ff644c7f0942e50f3e8a453..2909ae3c6f9a52df3f08e937a8ac18be28304ea9 100644 (file)
@@ -697,8 +697,6 @@ int ddr3_tip_print_centralization_result(u32 dev_num)
        u32 if_id = 0, bus_id = 0;
        struct hws_topology_map *tm = ddr3_get_topology_map();
 
-       dev_num = dev_num;
-
        printf("Centralization Results\n");
        printf("I/F0 Result[0 - success 1-fail 2 - state_2 3 - state_3] ...\n");
        for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
index ff245db91d5ddffac39a9cee34f2355975a5eed8..c04cef4cb98a091f74d6592c6fa4455dadc37882 100644 (file)
@@ -19,7 +19,6 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-#if defined(CONFIG_STM32F4) || defined(CONFIG_STM32F7)
 static const unsigned long io_base[] = {
        STM32_GPIOA_BASE, STM32_GPIOB_BASE, STM32_GPIOC_BASE,
        STM32_GPIOD_BASE, STM32_GPIOE_BASE, STM32_GPIOF_BASE,
@@ -74,81 +73,6 @@ int stm32_gpio_config(const struct stm32_gpio_dsc *dsc,
 out:
        return rv;
 }
-#elif defined(CONFIG_STM32F1)
-static const unsigned long io_base[] = {
-       STM32_GPIOA_BASE, STM32_GPIOB_BASE, STM32_GPIOC_BASE,
-       STM32_GPIOD_BASE, STM32_GPIOE_BASE, STM32_GPIOF_BASE,
-       STM32_GPIOG_BASE
-};
-
-#define STM32_GPIO_CR_MODE_MASK                0x3
-#define STM32_GPIO_CR_MODE_SHIFT(p)    (p * 4)
-#define STM32_GPIO_CR_CNF_MASK         0x3
-#define STM32_GPIO_CR_CNF_SHIFT(p)     (p * 4 + 2)
-
-struct stm32_gpio_regs {
-       u32 crl;        /* GPIO port configuration low */
-       u32 crh;        /* GPIO port configuration high */
-       u32 idr;        /* GPIO port input data */
-       u32 odr;        /* GPIO port output data */
-       u32 bsrr;       /* GPIO port bit set/reset */
-       u32 brr;        /* GPIO port bit reset */
-       u32 lckr;       /* GPIO port configuration lock */
-};
-
-#define CHECK_DSC(x)   (!x || x->port > 6 || x->pin > 15)
-#define CHECK_CTL(x)   (!x || x->mode > 3 || x->icnf > 3 || x->ocnf > 3 || \
-                        x->pupd > 1)
-
-int stm32_gpio_config(const struct stm32_gpio_dsc *dsc,
-               const struct stm32_gpio_ctl *ctl)
-{
-       struct stm32_gpio_regs *gpio_regs;
-       u32 *cr;
-       int p, crp;
-       int rv;
-
-       if (CHECK_DSC(dsc)) {
-               rv = -EINVAL;
-               goto out;
-       }
-       if (CHECK_CTL(ctl)) {
-               rv = -EINVAL;
-               goto out;
-       }
-
-       p = dsc->pin;
-
-       gpio_regs = (struct stm32_gpio_regs *)io_base[dsc->port];
-
-       if (p < 8) {
-               cr = &gpio_regs->crl;
-               crp = p;
-       } else {
-               cr = &gpio_regs->crh;
-               crp = p - 8;
-       }
-
-       clrbits_le32(cr, 0x3 << STM32_GPIO_CR_MODE_SHIFT(crp));
-       setbits_le32(cr, ctl->mode << STM32_GPIO_CR_MODE_SHIFT(crp));
-
-       clrbits_le32(cr, 0x3 << STM32_GPIO_CR_CNF_SHIFT(crp));
-       /* Inputs set the optional pull up / pull down */
-       if (ctl->mode == STM32_GPIO_MODE_IN) {
-               setbits_le32(cr, ctl->icnf << STM32_GPIO_CR_CNF_SHIFT(crp));
-               clrbits_le32(&gpio_regs->odr, 0x1 << p);
-               setbits_le32(&gpio_regs->odr, ctl->pupd << p);
-       } else {
-               setbits_le32(cr, ctl->ocnf << STM32_GPIO_CR_CNF_SHIFT(crp));
-       }
-
-       rv = 0;
-out:
-       return rv;
-}
-#else
-#error STM32 family not supported
-#endif
 
 int stm32_gpout_set(const struct stm32_gpio_dsc *dsc, int state)
 {
@@ -207,20 +131,11 @@ int gpio_direction_input(unsigned gpio)
 
        dsc.port = stm32_gpio_to_port(gpio);
        dsc.pin = stm32_gpio_to_pin(gpio);
-#if defined(CONFIG_STM32F4) || defined(CONFIG_STM32F7)
        ctl.af = STM32_GPIO_AF0;
        ctl.mode = STM32_GPIO_MODE_IN;
        ctl.otype = STM32_GPIO_OTYPE_PP;
        ctl.pupd = STM32_GPIO_PUPD_NO;
        ctl.speed = STM32_GPIO_SPEED_50M;
-#elif defined(CONFIG_STM32F1)
-       ctl.mode = STM32_GPIO_MODE_IN;
-       ctl.icnf = STM32_GPIO_ICNF_IN_FLT;
-       ctl.ocnf = STM32_GPIO_OCNF_GP_PP;       /* ignored for input */
-       ctl.pupd = STM32_GPIO_PUPD_UP;          /* ignored for floating */
-#else
-#error STM32 family not supported
-#endif
 
        return stm32_gpio_config(&dsc, &ctl);
 }
@@ -233,19 +148,10 @@ int gpio_direction_output(unsigned gpio, int value)
 
        dsc.port = stm32_gpio_to_port(gpio);
        dsc.pin = stm32_gpio_to_pin(gpio);
-#if defined(CONFIG_STM32F4) || defined(CONFIG_STM32F7)
        ctl.af = STM32_GPIO_AF0;
        ctl.mode = STM32_GPIO_MODE_OUT;
        ctl.pupd = STM32_GPIO_PUPD_NO;
        ctl.speed = STM32_GPIO_SPEED_50M;
-#elif defined(CONFIG_STM32F1)
-       ctl.mode = STM32_GPIO_MODE_OUT_50M;
-       ctl.ocnf = STM32_GPIO_OCNF_GP_PP;
-       ctl.icnf = STM32_GPIO_ICNF_IN_FLT;      /* ignored for output */
-       ctl.pupd = STM32_GPIO_PUPD_UP;          /* ignored for output */
-#else
-#error STM32 family not supported
-#endif
 
        res = stm32_gpio_config(&dsc, &ctl);
        if (res < 0)
diff --git a/drivers/nvme/Kconfig b/drivers/nvme/Kconfig
new file mode 100644 (file)
index 0000000..cad8dbc
--- /dev/null
@@ -0,0 +1,12 @@
+#
+# Copyright (C) 2017, Bin Meng <bmeng.cn@gmail.com>
+#
+# SPDX-License-Identifier:     GPL-2.0+
+#
+
+config NVME
+       bool "NVM Express device support"
+       depends on BLK && PCI
+       help
+         This option enables support for NVM Express devices.
+         It supports basic functions of NVMe (read/write).
diff --git a/drivers/nvme/Makefile b/drivers/nvme/Makefile
new file mode 100644 (file)
index 0000000..1f3010a
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# Copyright (C) 2017, Bin Meng <bmeng.cn@gmail.com>
+#
+# SPDX-License-Identifier:     GPL-2.0+
+#
+
+obj-y += nvme-uclass.o nvme.o nvme_show.o
diff --git a/drivers/nvme/nvme-uclass.c b/drivers/nvme/nvme-uclass.c
new file mode 100644 (file)
index 0000000..0895bc9
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2017 NXP Semiconductors
+ * Copyright (C) 2017 Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <dm.h>
+#include <dm/device.h>
+#include "nvme.h"
+
+static int nvme_info_init(struct uclass *uc)
+{
+       struct nvme_info *info = (struct nvme_info *)uc->priv;
+
+       info->ns_num = 0;
+       info->ndev_num = 0;
+       INIT_LIST_HEAD(&info->dev_list);
+       nvme_info = info;
+
+       return 0;
+}
+
+static int nvme_uclass_post_probe(struct udevice *udev)
+{
+       char name[20];
+       char *str;
+       struct udevice *ns_udev;
+       int i, ret;
+       struct nvme_dev *ndev = dev_get_priv(udev);
+
+       /* Create a blk device for each namespace */
+       for (i = 0; i < ndev->nn; i++) {
+               sprintf(name, "nvme-blk#%d", nvme_info->ns_num);
+               str = strdup(name);
+               if (!str)
+                       return -ENOMEM;
+
+               /* The real blksz and size will be set by nvme_blk_probe() */
+               ret = blk_create_device(udev, "nvme-blk", str, IF_TYPE_NVME,
+                                       nvme_info->ns_num++, 512, 0, &ns_udev);
+               if (ret) {
+                       free(str);
+                       nvme_info->ns_num--;
+
+                       return ret;
+               }
+               device_set_name_alloced(ns_udev);
+       }
+
+       return 0;
+}
+
+UCLASS_DRIVER(nvme) = {
+       .name   = "nvme",
+       .id     = UCLASS_NVME,
+       .init   = nvme_info_init,
+       .post_probe = nvme_uclass_post_probe,
+       .priv_auto_alloc_size = sizeof(struct nvme_info),
+};
diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c
new file mode 100644 (file)
index 0000000..151fe92
--- /dev/null
@@ -0,0 +1,860 @@
+/*
+ * Copyright (C) 2017 NXP Semiconductors
+ * Copyright (C) 2017 Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <memalign.h>
+#include <pci.h>
+#include <dm/device-internal.h>
+#include "nvme.h"
+
+struct nvme_info *nvme_info;
+
+#define NVME_Q_DEPTH           2
+#define NVME_AQ_DEPTH          2
+#define NVME_SQ_SIZE(depth)    (depth * sizeof(struct nvme_command))
+#define NVME_CQ_SIZE(depth)    (depth * sizeof(struct nvme_completion))
+#define ADMIN_TIMEOUT          60
+#define IO_TIMEOUT             30
+#define MAX_PRP_POOL           512
+
+/*
+ * An NVM Express queue. Each device has at least two (one for admin
+ * commands and one for I/O commands).
+ */
+struct nvme_queue {
+       struct nvme_dev *dev;
+       struct nvme_command *sq_cmds;
+       struct nvme_completion *cqes;
+       wait_queue_head_t sq_full;
+       u32 __iomem *q_db;
+       u16 q_depth;
+       s16 cq_vector;
+       u16 sq_head;
+       u16 sq_tail;
+       u16 cq_head;
+       u16 qid;
+       u8 cq_phase;
+       u8 cqe_seen;
+       unsigned long cmdid_data[];
+};
+
+static int nvme_wait_ready(struct nvme_dev *dev, bool enabled)
+{
+       u32 bit = enabled ? NVME_CSTS_RDY : 0;
+
+       while ((readl(&dev->bar->csts) & NVME_CSTS_RDY) != bit)
+               udelay(10000);
+
+       return 0;
+}
+
+static int nvme_setup_prps(struct nvme_dev *dev, u64 *prp2,
+                          int total_len, u64 dma_addr)
+{
+       u32 page_size = dev->page_size;
+       int offset = dma_addr & (page_size - 1);
+       u64 *prp_pool;
+       int length = total_len;
+       int i, nprps;
+       length -= (page_size - offset);
+
+       if (length <= 0) {
+               *prp2 = 0;
+               return 0;
+       }
+
+       if (length)
+               dma_addr += (page_size - offset);
+
+       if (length <= page_size) {
+               *prp2 = dma_addr;
+               return 0;
+       }
+
+       nprps = DIV_ROUND_UP(length, page_size);
+
+       if (nprps > dev->prp_entry_num) {
+               free(dev->prp_pool);
+               dev->prp_pool = malloc(nprps << 3);
+               if (!dev->prp_pool) {
+                       printf("Error: malloc prp_pool fail\n");
+                       return -ENOMEM;
+               }
+               dev->prp_entry_num = nprps;
+       }
+
+       prp_pool = dev->prp_pool;
+       i = 0;
+       while (nprps) {
+               if (i == ((page_size >> 3) - 1)) {
+                       *(prp_pool + i) = cpu_to_le64((ulong)prp_pool +
+                                       page_size);
+                       i = 0;
+                       prp_pool += page_size;
+               }
+               *(prp_pool + i++) = cpu_to_le64(dma_addr);
+               dma_addr += page_size;
+               nprps--;
+       }
+       *prp2 = (ulong)dev->prp_pool;
+
+       return 0;
+}
+
+static __le16 nvme_get_cmd_id(void)
+{
+       static unsigned short cmdid;
+
+       return cpu_to_le16((cmdid < USHRT_MAX) ? cmdid++ : 0);
+}
+
+static u16 nvme_read_completion_status(struct nvme_queue *nvmeq, u16 index)
+{
+       u64 start = (ulong)&nvmeq->cqes[index];
+       u64 stop = start + sizeof(struct nvme_completion);
+
+       invalidate_dcache_range(start, stop);
+
+       return le16_to_cpu(readw(&(nvmeq->cqes[index].status)));
+}
+
+/**
+ * nvme_submit_cmd() - copy a command into a queue and ring the doorbell
+ *
+ * @nvmeq:     The queue to use
+ * @cmd:       The command to send
+ */
+static void nvme_submit_cmd(struct nvme_queue *nvmeq, struct nvme_command *cmd)
+{
+       u16 tail = nvmeq->sq_tail;
+
+       memcpy(&nvmeq->sq_cmds[tail], cmd, sizeof(*cmd));
+       flush_dcache_range((ulong)&nvmeq->sq_cmds[tail],
+                          (ulong)&nvmeq->sq_cmds[tail] + sizeof(*cmd));
+
+       if (++tail == nvmeq->q_depth)
+               tail = 0;
+       writel(tail, nvmeq->q_db);
+       nvmeq->sq_tail = tail;
+}
+
+static int nvme_submit_sync_cmd(struct nvme_queue *nvmeq,
+                               struct nvme_command *cmd,
+                               u32 *result, unsigned timeout)
+{
+       u16 head = nvmeq->cq_head;
+       u16 phase = nvmeq->cq_phase;
+       u16 status;
+       ulong start_time;
+       ulong timeout_us = timeout * 100000;
+
+       cmd->common.command_id = nvme_get_cmd_id();
+       nvme_submit_cmd(nvmeq, cmd);
+
+       start_time = timer_get_us();
+
+       for (;;) {
+               status = nvme_read_completion_status(nvmeq, head);
+               if ((status & 0x01) == phase)
+                       break;
+               if (timeout_us > 0 && (timer_get_us() - start_time)
+                   >= timeout_us)
+                       return -ETIMEDOUT;
+       }
+
+       status >>= 1;
+       if (status) {
+               printf("ERROR: status = %x, phase = %d, head = %d\n",
+                      status, phase, head);
+               status = 0;
+               if (++head == nvmeq->q_depth) {
+                       head = 0;
+                       phase = !phase;
+               }
+               writel(head, nvmeq->q_db + nvmeq->dev->db_stride);
+               nvmeq->cq_head = head;
+               nvmeq->cq_phase = phase;
+
+               return -EIO;
+       }
+
+       if (result)
+               *result = le32_to_cpu(readl(&(nvmeq->cqes[head].result)));
+
+       if (++head == nvmeq->q_depth) {
+               head = 0;
+               phase = !phase;
+       }
+       writel(head, nvmeq->q_db + nvmeq->dev->db_stride);
+       nvmeq->cq_head = head;
+       nvmeq->cq_phase = phase;
+
+       return status;
+}
+
+static int nvme_submit_admin_cmd(struct nvme_dev *dev, struct nvme_command *cmd,
+                                u32 *result)
+{
+       return nvme_submit_sync_cmd(dev->queues[0], cmd, result, ADMIN_TIMEOUT);
+}
+
+static struct nvme_queue *nvme_alloc_queue(struct nvme_dev *dev,
+                                          int qid, int depth)
+{
+       struct nvme_queue *nvmeq = malloc(sizeof(*nvmeq));
+       if (!nvmeq)
+               return NULL;
+       memset(nvmeq, 0, sizeof(*nvmeq));
+
+       nvmeq->cqes = (void *)memalign(4096, NVME_CQ_SIZE(depth));
+       if (!nvmeq->cqes)
+               goto free_nvmeq;
+       memset((void *)nvmeq->cqes, 0, NVME_CQ_SIZE(depth));
+
+       nvmeq->sq_cmds = (void *)memalign(4096, NVME_SQ_SIZE(depth));
+       if (!nvmeq->sq_cmds)
+               goto free_queue;
+       memset((void *)nvmeq->sq_cmds, 0, NVME_SQ_SIZE(depth));
+
+       nvmeq->dev = dev;
+
+       nvmeq->cq_head = 0;
+       nvmeq->cq_phase = 1;
+       nvmeq->q_db = &dev->dbs[qid * 2 * dev->db_stride];
+       nvmeq->q_depth = depth;
+       nvmeq->qid = qid;
+       dev->queue_count++;
+       dev->queues[qid] = nvmeq;
+
+       return nvmeq;
+
+ free_queue:
+       free((void *)nvmeq->cqes);
+ free_nvmeq:
+       free(nvmeq);
+
+       return NULL;
+}
+
+static int nvme_delete_queue(struct nvme_dev *dev, u8 opcode, u16 id)
+{
+       struct nvme_command c;
+
+       memset(&c, 0, sizeof(c));
+       c.delete_queue.opcode = opcode;
+       c.delete_queue.qid = cpu_to_le16(id);
+
+       return nvme_submit_admin_cmd(dev, &c, NULL);
+}
+
+static int nvme_delete_sq(struct nvme_dev *dev, u16 sqid)
+{
+       return nvme_delete_queue(dev, nvme_admin_delete_sq, sqid);
+}
+
+static int nvme_delete_cq(struct nvme_dev *dev, u16 cqid)
+{
+       return nvme_delete_queue(dev, nvme_admin_delete_cq, cqid);
+}
+
+static int nvme_enable_ctrl(struct nvme_dev *dev)
+{
+       dev->ctrl_config &= ~NVME_CC_SHN_MASK;
+       dev->ctrl_config |= NVME_CC_ENABLE;
+       writel(cpu_to_le32(dev->ctrl_config), &dev->bar->cc);
+
+       return nvme_wait_ready(dev, true);
+}
+
+static int nvme_disable_ctrl(struct nvme_dev *dev)
+{
+       dev->ctrl_config &= ~NVME_CC_SHN_MASK;
+       dev->ctrl_config &= ~NVME_CC_ENABLE;
+       writel(cpu_to_le32(dev->ctrl_config), &dev->bar->cc);
+
+       return nvme_wait_ready(dev, false);
+}
+
+static void nvme_free_queue(struct nvme_queue *nvmeq)
+{
+       free((void *)nvmeq->cqes);
+       free(nvmeq->sq_cmds);
+       free(nvmeq);
+}
+
+static void nvme_free_queues(struct nvme_dev *dev, int lowest)
+{
+       int i;
+
+       for (i = dev->queue_count - 1; i >= lowest; i--) {
+               struct nvme_queue *nvmeq = dev->queues[i];
+               dev->queue_count--;
+               dev->queues[i] = NULL;
+               nvme_free_queue(nvmeq);
+       }
+}
+
+static void nvme_init_queue(struct nvme_queue *nvmeq, u16 qid)
+{
+       struct nvme_dev *dev = nvmeq->dev;
+
+       nvmeq->sq_tail = 0;
+       nvmeq->cq_head = 0;
+       nvmeq->cq_phase = 1;
+       nvmeq->q_db = &dev->dbs[qid * 2 * dev->db_stride];
+       memset((void *)nvmeq->cqes, 0, NVME_CQ_SIZE(nvmeq->q_depth));
+       flush_dcache_range((ulong)nvmeq->cqes,
+                          (ulong)nvmeq->cqes + NVME_CQ_SIZE(nvmeq->q_depth));
+       dev->online_queues++;
+}
+
+static int nvme_configure_admin_queue(struct nvme_dev *dev)
+{
+       int result;
+       u32 aqa;
+       u64 cap = nvme_readq(&dev->bar->cap);
+       struct nvme_queue *nvmeq;
+       /* most architectures use 4KB as the page size */
+       unsigned page_shift = 12;
+       unsigned dev_page_min = NVME_CAP_MPSMIN(cap) + 12;
+       unsigned dev_page_max = NVME_CAP_MPSMAX(cap) + 12;
+
+       if (page_shift < dev_page_min) {
+               debug("Device minimum page size (%u) too large for host (%u)\n",
+                     1 << dev_page_min, 1 << page_shift);
+               return -ENODEV;
+       }
+
+       if (page_shift > dev_page_max) {
+               debug("Device maximum page size (%u) smaller than host (%u)\n",
+                     1 << dev_page_max, 1 << page_shift);
+               page_shift = dev_page_max;
+       }
+
+       result = nvme_disable_ctrl(dev);
+       if (result < 0)
+               return result;
+
+       nvmeq = dev->queues[0];
+       if (!nvmeq) {
+               nvmeq = nvme_alloc_queue(dev, 0, NVME_AQ_DEPTH);
+               if (!nvmeq)
+                       return -ENOMEM;
+       }
+
+       aqa = nvmeq->q_depth - 1;
+       aqa |= aqa << 16;
+       aqa |= aqa << 16;
+
+       dev->page_size = 1 << page_shift;
+
+       dev->ctrl_config = NVME_CC_CSS_NVM;
+       dev->ctrl_config |= (page_shift - 12) << NVME_CC_MPS_SHIFT;
+       dev->ctrl_config |= NVME_CC_ARB_RR | NVME_CC_SHN_NONE;
+       dev->ctrl_config |= NVME_CC_IOSQES | NVME_CC_IOCQES;
+
+       writel(aqa, &dev->bar->aqa);
+       nvme_writeq((ulong)nvmeq->sq_cmds, &dev->bar->asq);
+       nvme_writeq((ulong)nvmeq->cqes, &dev->bar->acq);
+
+       result = nvme_enable_ctrl(dev);
+       if (result)
+               goto free_nvmeq;
+
+       nvmeq->cq_vector = 0;
+
+       nvme_init_queue(dev->queues[0], 0);
+
+       return result;
+
+ free_nvmeq:
+       nvme_free_queues(dev, 0);
+
+       return result;
+}
+
+static int nvme_alloc_cq(struct nvme_dev *dev, u16 qid,
+                           struct nvme_queue *nvmeq)
+{
+       struct nvme_command c;
+       int flags = NVME_QUEUE_PHYS_CONTIG | NVME_CQ_IRQ_ENABLED;
+
+       memset(&c, 0, sizeof(c));
+       c.create_cq.opcode = nvme_admin_create_cq;
+       c.create_cq.prp1 = cpu_to_le64((ulong)nvmeq->cqes);
+       c.create_cq.cqid = cpu_to_le16(qid);
+       c.create_cq.qsize = cpu_to_le16(nvmeq->q_depth - 1);
+       c.create_cq.cq_flags = cpu_to_le16(flags);
+       c.create_cq.irq_vector = cpu_to_le16(nvmeq->cq_vector);
+
+       return nvme_submit_admin_cmd(dev, &c, NULL);
+}
+
+static int nvme_alloc_sq(struct nvme_dev *dev, u16 qid,
+                           struct nvme_queue *nvmeq)
+{
+       struct nvme_command c;
+       int flags = NVME_QUEUE_PHYS_CONTIG | NVME_SQ_PRIO_MEDIUM;
+
+       memset(&c, 0, sizeof(c));
+       c.create_sq.opcode = nvme_admin_create_sq;
+       c.create_sq.prp1 = cpu_to_le64((ulong)nvmeq->sq_cmds);
+       c.create_sq.sqid = cpu_to_le16(qid);
+       c.create_sq.qsize = cpu_to_le16(nvmeq->q_depth - 1);
+       c.create_sq.sq_flags = cpu_to_le16(flags);
+       c.create_sq.cqid = cpu_to_le16(qid);
+
+       return nvme_submit_admin_cmd(dev, &c, NULL);
+}
+
+int nvme_identify(struct nvme_dev *dev, unsigned nsid,
+                 unsigned cns, dma_addr_t dma_addr)
+{
+       struct nvme_command c;
+       u32 page_size = dev->page_size;
+       int offset = dma_addr & (page_size - 1);
+       int length = sizeof(struct nvme_id_ctrl);
+
+       memset(&c, 0, sizeof(c));
+       c.identify.opcode = nvme_admin_identify;
+       c.identify.nsid = cpu_to_le32(nsid);
+       c.identify.prp1 = cpu_to_le64(dma_addr);
+
+       length -= (page_size - offset);
+       if (length <= 0) {
+               c.identify.prp2 = 0;
+       } else {
+               dma_addr += (page_size - offset);
+               c.identify.prp2 = dma_addr;
+       }
+
+       c.identify.cns = cpu_to_le32(cns);
+
+       return nvme_submit_admin_cmd(dev, &c, NULL);
+}
+
+int nvme_get_features(struct nvme_dev *dev, unsigned fid, unsigned nsid,
+                     dma_addr_t dma_addr, u32 *result)
+{
+       struct nvme_command c;
+
+       memset(&c, 0, sizeof(c));
+       c.features.opcode = nvme_admin_get_features;
+       c.features.nsid = cpu_to_le32(nsid);
+       c.features.prp1 = cpu_to_le64(dma_addr);
+       c.features.fid = cpu_to_le32(fid);
+
+       return nvme_submit_admin_cmd(dev, &c, result);
+}
+
+int nvme_set_features(struct nvme_dev *dev, unsigned fid, unsigned dword11,
+                     dma_addr_t dma_addr, u32 *result)
+{
+       struct nvme_command c;
+
+       memset(&c, 0, sizeof(c));
+       c.features.opcode = nvme_admin_set_features;
+       c.features.prp1 = cpu_to_le64(dma_addr);
+       c.features.fid = cpu_to_le32(fid);
+       c.features.dword11 = cpu_to_le32(dword11);
+
+       return nvme_submit_admin_cmd(dev, &c, result);
+}
+
+static int nvme_create_queue(struct nvme_queue *nvmeq, int qid)
+{
+       struct nvme_dev *dev = nvmeq->dev;
+       int result;
+
+       nvmeq->cq_vector = qid - 1;
+       result = nvme_alloc_cq(dev, qid, nvmeq);
+       if (result < 0)
+               goto release_cq;
+
+       result = nvme_alloc_sq(dev, qid, nvmeq);
+       if (result < 0)
+               goto release_sq;
+
+       nvme_init_queue(nvmeq, qid);
+
+       return result;
+
+ release_sq:
+       nvme_delete_sq(dev, qid);
+ release_cq:
+       nvme_delete_cq(dev, qid);
+
+       return result;
+}
+
+static int nvme_set_queue_count(struct nvme_dev *dev, int count)
+{
+       int status;
+       u32 result;
+       u32 q_count = (count - 1) | ((count - 1) << 16);
+
+       status = nvme_set_features(dev, NVME_FEAT_NUM_QUEUES,
+                       q_count, 0, &result);
+
+       if (status < 0)
+               return status;
+       if (status > 1)
+               return 0;
+
+       return min(result & 0xffff, result >> 16) + 1;
+}
+
+static void nvme_create_io_queues(struct nvme_dev *dev)
+{
+       unsigned int i;
+
+       for (i = dev->queue_count; i <= dev->max_qid; i++)
+               if (!nvme_alloc_queue(dev, i, dev->q_depth))
+                       break;
+
+       for (i = dev->online_queues; i <= dev->queue_count - 1; i++)
+               if (nvme_create_queue(dev->queues[i], i))
+                       break;
+}
+
+static int nvme_setup_io_queues(struct nvme_dev *dev)
+{
+       int nr_io_queues;
+       int result;
+
+       nr_io_queues = 1;
+       result = nvme_set_queue_count(dev, nr_io_queues);
+       if (result <= 0)
+               return result;
+
+       if (result < nr_io_queues)
+               nr_io_queues = result;
+
+       dev->max_qid = nr_io_queues;
+
+       /* Free previously allocated queues */
+       nvme_free_queues(dev, nr_io_queues + 1);
+       nvme_create_io_queues(dev);
+
+       return 0;
+}
+
+static int nvme_get_info_from_identify(struct nvme_dev *dev)
+{
+       u16 vendor, device;
+       struct nvme_id_ctrl buf, *ctrl = &buf;
+       int ret;
+       int shift = NVME_CAP_MPSMIN(nvme_readq(&dev->bar->cap)) + 12;
+
+       ret = nvme_identify(dev, 0, 1, (dma_addr_t)ctrl);
+       if (ret)
+               return -EIO;
+
+       dev->nn = le32_to_cpu(ctrl->nn);
+       dev->vwc = ctrl->vwc;
+       memcpy(dev->serial, ctrl->sn, sizeof(ctrl->sn));
+       memcpy(dev->model, ctrl->mn, sizeof(ctrl->mn));
+       memcpy(dev->firmware_rev, ctrl->fr, sizeof(ctrl->fr));
+       if (ctrl->mdts)
+               dev->max_transfer_shift = (ctrl->mdts + shift);
+       else {
+               /*
+                * Maximum Data Transfer Size (MDTS) field indicates the maximum
+                * data transfer size between the host and the controller. The
+                * host should not submit a command that exceeds this transfer
+                * size. The value is in units of the minimum memory page size
+                * and is reported as a power of two (2^n).
+                *
+                * The spec also says: a value of 0h indicates no restrictions
+                * on transfer size. But in nvme_blk_read/write() below we have
+                * the following algorithm for maximum number of logic blocks
+                * per transfer:
+                *
+                * u16 lbas = 1 << (dev->max_transfer_shift - ns->lba_shift);
+                *
+                * In order for lbas not to overflow, the maximum number is 15
+                * which means dev->max_transfer_shift = 15 + 9 (ns->lba_shift).
+                * Let's use 20 which provides 1MB size.
+                */
+               dev->max_transfer_shift = 20;
+       }
+
+       /* Apply quirk stuff */
+       dm_pci_read_config16(dev->pdev, PCI_VENDOR_ID, &vendor);
+       dm_pci_read_config16(dev->pdev, PCI_DEVICE_ID, &device);
+       if ((vendor == PCI_VENDOR_ID_INTEL) &&
+           (device == 0x0953) && ctrl->vs[3]) {
+               unsigned int max_transfer_shift;
+               dev->stripe_size = (ctrl->vs[3] + shift);
+               max_transfer_shift = (ctrl->vs[3] + 18);
+               if (dev->max_transfer_shift) {
+                       dev->max_transfer_shift = min(max_transfer_shift,
+                                                     dev->max_transfer_shift);
+               } else {
+                       dev->max_transfer_shift = max_transfer_shift;
+               }
+       }
+
+       return 0;
+}
+
+int nvme_scan_namespace(void)
+{
+       struct uclass *uc;
+       struct udevice *dev;
+       int ret;
+
+       ret = uclass_get(UCLASS_NVME, &uc);
+       if (ret)
+               return ret;
+
+       uclass_foreach_dev(dev, uc) {
+               ret = device_probe(dev);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int nvme_blk_probe(struct udevice *udev)
+{
+       struct nvme_dev *ndev = dev_get_priv(udev->parent);
+       struct blk_desc *desc = dev_get_uclass_platdata(udev);
+       struct nvme_ns *ns = dev_get_priv(udev);
+       u8 flbas;
+       u16 vendor;
+       struct nvme_id_ns buf, *id = &buf;
+
+       memset(ns, 0, sizeof(*ns));
+       ns->dev = ndev;
+       ns->ns_id = desc->devnum - ndev->blk_dev_start + 1;
+       if (nvme_identify(ndev, ns->ns_id, 0, (dma_addr_t)id))
+               return -EIO;
+
+       flbas = id->flbas & NVME_NS_FLBAS_LBA_MASK;
+       ns->flbas = flbas;
+       ns->lba_shift = id->lbaf[flbas].ds;
+       ns->mode_select_num_blocks = le64_to_cpu(id->nsze);
+       ns->mode_select_block_len = 1 << ns->lba_shift;
+       list_add(&ns->list, &ndev->namespaces);
+
+       desc->lba = ns->mode_select_num_blocks;
+       desc->log2blksz = ns->lba_shift;
+       desc->blksz = 1 << ns->lba_shift;
+       desc->bdev = udev;
+       dm_pci_read_config16(ndev->pdev, PCI_VENDOR_ID, &vendor);
+       sprintf(desc->vendor, "0x%.4x", vendor);
+       memcpy(desc->product, ndev->serial, sizeof(ndev->serial));
+       memcpy(desc->revision, ndev->firmware_rev, sizeof(ndev->firmware_rev));
+       part_init(desc);
+
+       return 0;
+}
+
+static ulong nvme_blk_read(struct udevice *udev, lbaint_t blknr,
+                          lbaint_t blkcnt, void *buffer)
+{
+       struct nvme_ns *ns = dev_get_priv(udev);
+       struct nvme_dev *dev = ns->dev;
+       struct nvme_command c;
+       struct blk_desc *desc = dev_get_uclass_platdata(udev);
+       int status;
+       u64 prp2;
+       u64 total_len = blkcnt << desc->log2blksz;
+       u64 temp_len = total_len;
+
+       u64 slba = blknr;
+       u16 lbas = 1 << (dev->max_transfer_shift - ns->lba_shift);
+       u64 total_lbas = blkcnt;
+
+       c.rw.opcode = nvme_cmd_read;
+       c.rw.flags = 0;
+       c.rw.nsid = cpu_to_le32(ns->ns_id);
+       c.rw.control = 0;
+       c.rw.dsmgmt = 0;
+       c.rw.reftag = 0;
+       c.rw.apptag = 0;
+       c.rw.appmask = 0;
+       c.rw.metadata = 0;
+
+       while (total_lbas) {
+               if (total_lbas < lbas) {
+                       lbas = (u16)total_lbas;
+                       total_lbas = 0;
+               } else {
+                       total_lbas -= lbas;
+               }
+
+               if (nvme_setup_prps
+                  (dev, &prp2, lbas << ns->lba_shift, (ulong)buffer))
+                       return -EIO;
+               c.rw.slba = cpu_to_le64(slba);
+               slba += lbas;
+               c.rw.length = cpu_to_le16(lbas - 1);
+               c.rw.prp1 = cpu_to_le64((ulong)buffer);
+               c.rw.prp2 = cpu_to_le64(prp2);
+               status = nvme_submit_sync_cmd(dev->queues[1],
+                               &c, NULL, IO_TIMEOUT);
+               if (status)
+                       break;
+               temp_len -= lbas << ns->lba_shift;
+               buffer += lbas << ns->lba_shift;
+       }
+
+       return (total_len - temp_len) >> desc->log2blksz;
+}
+
+static ulong nvme_blk_write(struct udevice *udev, lbaint_t blknr,
+                           lbaint_t blkcnt, const void *buffer)
+{
+       struct nvme_ns *ns = dev_get_priv(udev);
+       struct nvme_dev *dev = ns->dev;
+       struct nvme_command c;
+       struct blk_desc *desc = dev_get_uclass_platdata(udev);
+       int status;
+       u64 prp2;
+       u64 total_len = blkcnt << desc->log2blksz;
+       u64 temp_len = total_len;
+
+       u64 slba = blknr;
+       u16 lbas = 1 << (dev->max_transfer_shift - ns->lba_shift);
+       u64 total_lbas = blkcnt;
+
+       c.rw.opcode = nvme_cmd_write;
+       c.rw.flags = 0;
+       c.rw.nsid = cpu_to_le32(ns->ns_id);
+       c.rw.control = 0;
+       c.rw.dsmgmt = 0;
+       c.rw.reftag = 0;
+       c.rw.apptag = 0;
+       c.rw.appmask = 0;
+       c.rw.metadata = 0;
+
+       while (total_lbas) {
+               if (total_lbas < lbas) {
+                       lbas = (u16)total_lbas;
+                       total_lbas = 0;
+               } else {
+                       total_lbas -= lbas;
+               }
+
+               if (nvme_setup_prps
+                  (dev, &prp2, lbas << ns->lba_shift, (ulong)buffer))
+                       return -EIO;
+               c.rw.slba = cpu_to_le64(slba);
+               slba += lbas;
+               c.rw.length = cpu_to_le16(lbas - 1);
+               c.rw.prp1 = cpu_to_le64((ulong)buffer);
+               c.rw.prp2 = cpu_to_le64(prp2);
+               status = nvme_submit_sync_cmd(dev->queues[1],
+                               &c, NULL, IO_TIMEOUT);
+               if (status)
+                       break;
+               temp_len -= lbas << ns->lba_shift;
+               buffer += lbas << ns->lba_shift;
+       }
+
+       return (total_len - temp_len) >> desc->log2blksz;
+}
+
+static const struct blk_ops nvme_blk_ops = {
+       .read   = nvme_blk_read,
+       .write  = nvme_blk_write,
+};
+
+U_BOOT_DRIVER(nvme_blk) = {
+       .name   = "nvme-blk",
+       .id     = UCLASS_BLK,
+       .probe  = nvme_blk_probe,
+       .ops    = &nvme_blk_ops,
+       .priv_auto_alloc_size = sizeof(struct nvme_ns),
+};
+
+static int nvme_bind(struct udevice *udev)
+{
+       char name[20];
+       sprintf(name, "nvme#%d", nvme_info->ndev_num++);
+
+       return device_set_name(udev, name);
+}
+
+static int nvme_probe(struct udevice *udev)
+{
+       int ret;
+       struct nvme_dev *ndev = dev_get_priv(udev);
+       u64 cap;
+
+       ndev->pdev = pci_get_controller(udev);
+       ndev->instance = trailing_strtol(udev->name);
+
+       INIT_LIST_HEAD(&ndev->namespaces);
+       ndev->bar = dm_pci_map_bar(udev, PCI_BASE_ADDRESS_0,
+                       PCI_REGION_MEM);
+       if (readl(&ndev->bar->csts) == -1) {
+               ret = -ENODEV;
+               printf("Error: %s: Out of memory!\n", udev->name);
+               goto free_nvme;
+       }
+
+       ndev->queues = malloc(2 * sizeof(struct nvme_queue));
+       if (!ndev->queues) {
+               ret = -ENOMEM;
+               printf("Error: %s: Out of memory!\n", udev->name);
+               goto free_nvme;
+       }
+       memset(ndev->queues, 0, sizeof(2 * sizeof(struct nvme_queue)));
+
+       ndev->prp_pool = malloc(MAX_PRP_POOL);
+       if (!ndev->prp_pool) {
+               ret = -ENOMEM;
+               printf("Error: %s: Out of memory!\n", udev->name);
+               goto free_nvme;
+       }
+       ndev->prp_entry_num = MAX_PRP_POOL >> 3;
+
+       cap = nvme_readq(&ndev->bar->cap);
+       ndev->q_depth = min_t(int, NVME_CAP_MQES(cap) + 1, NVME_Q_DEPTH);
+       ndev->db_stride = 1 << NVME_CAP_STRIDE(cap);
+       ndev->dbs = ((void __iomem *)ndev->bar) + 4096;
+
+       ret = nvme_configure_admin_queue(ndev);
+       if (ret)
+               goto free_queue;
+
+       ret = nvme_setup_io_queues(ndev);
+       if (ret)
+               goto free_queue;
+
+       nvme_get_info_from_identify(ndev);
+       ndev->blk_dev_start = nvme_info->ns_num;
+       list_add(&ndev->node, &nvme_info->dev_list);
+
+       return 0;
+
+free_queue:
+       free((void *)ndev->queues);
+free_nvme:
+       return ret;
+}
+
+U_BOOT_DRIVER(nvme) = {
+       .name   = "nvme",
+       .id     = UCLASS_NVME,
+       .bind   = nvme_bind,
+       .probe  = nvme_probe,
+       .priv_auto_alloc_size = sizeof(struct nvme_dev),
+};
+
+struct pci_device_id nvme_supported[] = {
+       { PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_EXPRESS, ~0) },
+       {}
+};
+
+U_BOOT_PCI_DEVICE(nvme, nvme_supported);
diff --git a/drivers/nvme/nvme.h b/drivers/nvme/nvme.h
new file mode 100644 (file)
index 0000000..b7fdd0b
--- /dev/null
@@ -0,0 +1,717 @@
+/*
+ * Copyright (C) 2017 NXP Semiconductors
+ * Copyright (C) 2017 Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef __DRIVER_NVME_H__
+#define __DRIVER_NVME_H__
+
+#include <asm/io.h>
+
+struct nvme_id_power_state {
+       __le16                  max_power;      /* centiwatts */
+       __u8                    rsvd2;
+       __u8                    flags;
+       __le32                  entry_lat;      /* microseconds */
+       __le32                  exit_lat;       /* microseconds */
+       __u8                    read_tput;
+       __u8                    read_lat;
+       __u8                    write_tput;
+       __u8                    write_lat;
+       __le16                  idle_power;
+       __u8                    idle_scale;
+       __u8                    rsvd19;
+       __le16                  active_power;
+       __u8                    active_work_scale;
+       __u8                    rsvd23[9];
+};
+
+enum {
+       NVME_PS_FLAGS_MAX_POWER_SCALE   = 1 << 0,
+       NVME_PS_FLAGS_NON_OP_STATE      = 1 << 1,
+};
+
+struct nvme_id_ctrl {
+       __le16                  vid;
+       __le16                  ssvid;
+       char                    sn[20];
+       char                    mn[40];
+       char                    fr[8];
+       __u8                    rab;
+       __u8                    ieee[3];
+       __u8                    mic;
+       __u8                    mdts;
+       __u16                   cntlid;
+       __u32                   ver;
+       __u8                    rsvd84[172];
+       __le16                  oacs;
+       __u8                    acl;
+       __u8                    aerl;
+       __u8                    frmw;
+       __u8                    lpa;
+       __u8                    elpe;
+       __u8                    npss;
+       __u8                    avscc;
+       __u8                    apsta;
+       __le16                  wctemp;
+       __le16                  cctemp;
+       __u8                    rsvd270[242];
+       __u8                    sqes;
+       __u8                    cqes;
+       __u8                    rsvd514[2];
+       __le32                  nn;
+       __le16                  oncs;
+       __le16                  fuses;
+       __u8                    fna;
+       __u8                    vwc;
+       __le16                  awun;
+       __le16                  awupf;
+       __u8                    nvscc;
+       __u8                    rsvd531;
+       __le16                  acwu;
+       __u8                    rsvd534[2];
+       __le32                  sgls;
+       __u8                    rsvd540[1508];
+       struct nvme_id_power_state      psd[32];
+       __u8                    vs[1024];
+};
+
+enum {
+       NVME_CTRL_ONCS_COMPARE                  = 1 << 0,
+       NVME_CTRL_ONCS_WRITE_UNCORRECTABLE      = 1 << 1,
+       NVME_CTRL_ONCS_DSM                      = 1 << 2,
+       NVME_CTRL_VWC_PRESENT                   = 1 << 0,
+};
+
+struct nvme_lbaf {
+       __le16                  ms;
+       __u8                    ds;
+       __u8                    rp;
+};
+
+struct nvme_id_ns {
+       __le64                  nsze;
+       __le64                  ncap;
+       __le64                  nuse;
+       __u8                    nsfeat;
+       __u8                    nlbaf;
+       __u8                    flbas;
+       __u8                    mc;
+       __u8                    dpc;
+       __u8                    dps;
+       __u8                    nmic;
+       __u8                    rescap;
+       __u8                    fpi;
+       __u8                    rsvd33;
+       __le16                  nawun;
+       __le16                  nawupf;
+       __le16                  nacwu;
+       __le16                  nabsn;
+       __le16                  nabo;
+       __le16                  nabspf;
+       __u16                   rsvd46;
+       __le64                  nvmcap[2];
+       __u8                    rsvd64[40];
+       __u8                    nguid[16];
+       __u8                    eui64[8];
+       struct nvme_lbaf        lbaf[16];
+       __u8                    rsvd192[192];
+       __u8                    vs[3712];
+};
+
+enum {
+       NVME_NS_FEAT_THIN       = 1 << 0,
+       NVME_NS_FLBAS_LBA_MASK  = 0xf,
+       NVME_NS_FLBAS_META_EXT  = 0x10,
+       NVME_LBAF_RP_BEST       = 0,
+       NVME_LBAF_RP_BETTER     = 1,
+       NVME_LBAF_RP_GOOD       = 2,
+       NVME_LBAF_RP_DEGRADED   = 3,
+       NVME_NS_DPC_PI_LAST     = 1 << 4,
+       NVME_NS_DPC_PI_FIRST    = 1 << 3,
+       NVME_NS_DPC_PI_TYPE3    = 1 << 2,
+       NVME_NS_DPC_PI_TYPE2    = 1 << 1,
+       NVME_NS_DPC_PI_TYPE1    = 1 << 0,
+       NVME_NS_DPS_PI_FIRST    = 1 << 3,
+       NVME_NS_DPS_PI_MASK     = 0x7,
+       NVME_NS_DPS_PI_TYPE1    = 1,
+       NVME_NS_DPS_PI_TYPE2    = 2,
+       NVME_NS_DPS_PI_TYPE3    = 3,
+};
+
+struct nvme_smart_log {
+       __u8                    critical_warning;
+       __u8                    temperature[2];
+       __u8                    avail_spare;
+       __u8                    spare_thresh;
+       __u8                    percent_used;
+       __u8                    rsvd6[26];
+       __u8                    data_units_read[16];
+       __u8                    data_units_written[16];
+       __u8                    host_reads[16];
+       __u8                    host_writes[16];
+       __u8                    ctrl_busy_time[16];
+       __u8                    power_cycles[16];
+       __u8                    power_on_hours[16];
+       __u8                    unsafe_shutdowns[16];
+       __u8                    media_errors[16];
+       __u8                    num_err_log_entries[16];
+       __le32                  warning_temp_time;
+       __le32                  critical_comp_time;
+       __le16                  temp_sensor[8];
+       __u8                    rsvd216[296];
+};
+
+enum {
+       NVME_SMART_CRIT_SPARE           = 1 << 0,
+       NVME_SMART_CRIT_TEMPERATURE     = 1 << 1,
+       NVME_SMART_CRIT_RELIABILITY     = 1 << 2,
+       NVME_SMART_CRIT_MEDIA           = 1 << 3,
+       NVME_SMART_CRIT_VOLATILE_MEMORY = 1 << 4,
+};
+
+struct nvme_lba_range_type {
+       __u8                    type;
+       __u8                    attributes;
+       __u8                    rsvd2[14];
+       __u64                   slba;
+       __u64                   nlb;
+       __u8                    guid[16];
+       __u8                    rsvd48[16];
+};
+
+enum {
+       NVME_LBART_TYPE_FS      = 0x01,
+       NVME_LBART_TYPE_RAID    = 0x02,
+       NVME_LBART_TYPE_CACHE   = 0x03,
+       NVME_LBART_TYPE_SWAP    = 0x04,
+
+       NVME_LBART_ATTRIB_TEMP  = 1 << 0,
+       NVME_LBART_ATTRIB_HIDE  = 1 << 1,
+};
+
+struct nvme_reservation_status {
+       __le32  gen;
+       __u8    rtype;
+       __u8    regctl[2];
+       __u8    resv5[2];
+       __u8    ptpls;
+       __u8    resv10[13];
+       struct {
+               __le16  cntlid;
+               __u8    rcsts;
+               __u8    resv3[5];
+               __le64  hostid;
+               __le64  rkey;
+       } regctl_ds[];
+};
+
+/* I/O commands */
+
+enum nvme_opcode {
+       nvme_cmd_flush          = 0x00,
+       nvme_cmd_write          = 0x01,
+       nvme_cmd_read           = 0x02,
+       nvme_cmd_write_uncor    = 0x04,
+       nvme_cmd_compare        = 0x05,
+       nvme_cmd_write_zeroes   = 0x08,
+       nvme_cmd_dsm            = 0x09,
+       nvme_cmd_resv_register  = 0x0d,
+       nvme_cmd_resv_report    = 0x0e,
+       nvme_cmd_resv_acquire   = 0x11,
+       nvme_cmd_resv_release   = 0x15,
+};
+
+struct nvme_common_command {
+       __u8                    opcode;
+       __u8                    flags;
+       __u16                   command_id;
+       __le32                  nsid;
+       __le32                  cdw2[2];
+       __le64                  metadata;
+       __le64                  prp1;
+       __le64                  prp2;
+       __le32                  cdw10[6];
+};
+
+struct nvme_rw_command {
+       __u8                    opcode;
+       __u8                    flags;
+       __u16                   command_id;
+       __le32                  nsid;
+       __u64                   rsvd2;
+       __le64                  metadata;
+       __le64                  prp1;
+       __le64                  prp2;
+       __le64                  slba;
+       __le16                  length;
+       __le16                  control;
+       __le32                  dsmgmt;
+       __le32                  reftag;
+       __le16                  apptag;
+       __le16                  appmask;
+};
+
+enum {
+       NVME_RW_LR                      = 1 << 15,
+       NVME_RW_FUA                     = 1 << 14,
+       NVME_RW_DSM_FREQ_UNSPEC         = 0,
+       NVME_RW_DSM_FREQ_TYPICAL        = 1,
+       NVME_RW_DSM_FREQ_RARE           = 2,
+       NVME_RW_DSM_FREQ_READS          = 3,
+       NVME_RW_DSM_FREQ_WRITES         = 4,
+       NVME_RW_DSM_FREQ_RW             = 5,
+       NVME_RW_DSM_FREQ_ONCE           = 6,
+       NVME_RW_DSM_FREQ_PREFETCH       = 7,
+       NVME_RW_DSM_FREQ_TEMP           = 8,
+       NVME_RW_DSM_LATENCY_NONE        = 0 << 4,
+       NVME_RW_DSM_LATENCY_IDLE        = 1 << 4,
+       NVME_RW_DSM_LATENCY_NORM        = 2 << 4,
+       NVME_RW_DSM_LATENCY_LOW         = 3 << 4,
+       NVME_RW_DSM_SEQ_REQ             = 1 << 6,
+       NVME_RW_DSM_COMPRESSED          = 1 << 7,
+       NVME_RW_PRINFO_PRCHK_REF        = 1 << 10,
+       NVME_RW_PRINFO_PRCHK_APP        = 1 << 11,
+       NVME_RW_PRINFO_PRCHK_GUARD      = 1 << 12,
+       NVME_RW_PRINFO_PRACT            = 1 << 13,
+};
+
+struct nvme_dsm_cmd {
+       __u8                    opcode;
+       __u8                    flags;
+       __u16                   command_id;
+       __le32                  nsid;
+       __u64                   rsvd2[2];
+       __le64                  prp1;
+       __le64                  prp2;
+       __le32                  nr;
+       __le32                  attributes;
+       __u32                   rsvd12[4];
+};
+
+enum {
+       NVME_DSMGMT_IDR         = 1 << 0,
+       NVME_DSMGMT_IDW         = 1 << 1,
+       NVME_DSMGMT_AD          = 1 << 2,
+};
+
+struct nvme_dsm_range {
+       __le32                  cattr;
+       __le32                  nlb;
+       __le64                  slba;
+};
+
+/* Admin commands */
+
+enum nvme_admin_opcode {
+       nvme_admin_delete_sq            = 0x00,
+       nvme_admin_create_sq            = 0x01,
+       nvme_admin_get_log_page         = 0x02,
+       nvme_admin_delete_cq            = 0x04,
+       nvme_admin_create_cq            = 0x05,
+       nvme_admin_identify             = 0x06,
+       nvme_admin_abort_cmd            = 0x08,
+       nvme_admin_set_features         = 0x09,
+       nvme_admin_get_features         = 0x0a,
+       nvme_admin_async_event          = 0x0c,
+       nvme_admin_activate_fw          = 0x10,
+       nvme_admin_download_fw          = 0x11,
+       nvme_admin_format_nvm           = 0x80,
+       nvme_admin_security_send        = 0x81,
+       nvme_admin_security_recv        = 0x82,
+};
+
+enum {
+       NVME_QUEUE_PHYS_CONTIG  = (1 << 0),
+       NVME_CQ_IRQ_ENABLED     = (1 << 1),
+       NVME_SQ_PRIO_URGENT     = (0 << 1),
+       NVME_SQ_PRIO_HIGH       = (1 << 1),
+       NVME_SQ_PRIO_MEDIUM     = (2 << 1),
+       NVME_SQ_PRIO_LOW        = (3 << 1),
+       NVME_FEAT_ARBITRATION   = 0x01,
+       NVME_FEAT_POWER_MGMT    = 0x02,
+       NVME_FEAT_LBA_RANGE     = 0x03,
+       NVME_FEAT_TEMP_THRESH   = 0x04,
+       NVME_FEAT_ERR_RECOVERY  = 0x05,
+       NVME_FEAT_VOLATILE_WC   = 0x06,
+       NVME_FEAT_NUM_QUEUES    = 0x07,
+       NVME_FEAT_IRQ_COALESCE  = 0x08,
+       NVME_FEAT_IRQ_CONFIG    = 0x09,
+       NVME_FEAT_WRITE_ATOMIC  = 0x0a,
+       NVME_FEAT_ASYNC_EVENT   = 0x0b,
+       NVME_FEAT_AUTO_PST      = 0x0c,
+       NVME_FEAT_SW_PROGRESS   = 0x80,
+       NVME_FEAT_HOST_ID       = 0x81,
+       NVME_FEAT_RESV_MASK     = 0x82,
+       NVME_FEAT_RESV_PERSIST  = 0x83,
+       NVME_LOG_ERROR          = 0x01,
+       NVME_LOG_SMART          = 0x02,
+       NVME_LOG_FW_SLOT        = 0x03,
+       NVME_LOG_RESERVATION    = 0x80,
+       NVME_FWACT_REPL         = (0 << 3),
+       NVME_FWACT_REPL_ACTV    = (1 << 3),
+       NVME_FWACT_ACTV         = (2 << 3),
+};
+
+struct nvme_identify {
+       __u8                    opcode;
+       __u8                    flags;
+       __u16                   command_id;
+       __le32                  nsid;
+       __u64                   rsvd2[2];
+       __le64                  prp1;
+       __le64                  prp2;
+       __le32                  cns;
+       __u32                   rsvd11[5];
+};
+
+struct nvme_features {
+       __u8                    opcode;
+       __u8                    flags;
+       __u16                   command_id;
+       __le32                  nsid;
+       __u64                   rsvd2[2];
+       __le64                  prp1;
+       __le64                  prp2;
+       __le32                  fid;
+       __le32                  dword11;
+       __u32                   rsvd12[4];
+};
+
+struct nvme_create_cq {
+       __u8                    opcode;
+       __u8                    flags;
+       __u16                   command_id;
+       __u32                   rsvd1[5];
+       __le64                  prp1;
+       __u64                   rsvd8;
+       __le16                  cqid;
+       __le16                  qsize;
+       __le16                  cq_flags;
+       __le16                  irq_vector;
+       __u32                   rsvd12[4];
+};
+
+struct nvme_create_sq {
+       __u8                    opcode;
+       __u8                    flags;
+       __u16                   command_id;
+       __u32                   rsvd1[5];
+       __le64                  prp1;
+       __u64                   rsvd8;
+       __le16                  sqid;
+       __le16                  qsize;
+       __le16                  sq_flags;
+       __le16                  cqid;
+       __u32                   rsvd12[4];
+};
+
+struct nvme_delete_queue {
+       __u8                    opcode;
+       __u8                    flags;
+       __u16                   command_id;
+       __u32                   rsvd1[9];
+       __le16                  qid;
+       __u16                   rsvd10;
+       __u32                   rsvd11[5];
+};
+
+struct nvme_abort_cmd {
+       __u8                    opcode;
+       __u8                    flags;
+       __u16                   command_id;
+       __u32                   rsvd1[9];
+       __le16                  sqid;
+       __u16                   cid;
+       __u32                   rsvd11[5];
+};
+
+struct nvme_download_firmware {
+       __u8                    opcode;
+       __u8                    flags;
+       __u16                   command_id;
+       __u32                   rsvd1[5];
+       __le64                  prp1;
+       __le64                  prp2;
+       __le32                  numd;
+       __le32                  offset;
+       __u32                   rsvd12[4];
+};
+
+struct nvme_format_cmd {
+       __u8                    opcode;
+       __u8                    flags;
+       __u16                   command_id;
+       __le32                  nsid;
+       __u64                   rsvd2[4];
+       __le32                  cdw10;
+       __u32                   rsvd11[5];
+};
+
+struct nvme_command {
+       union {
+               struct nvme_common_command common;
+               struct nvme_rw_command rw;
+               struct nvme_identify identify;
+               struct nvme_features features;
+               struct nvme_create_cq create_cq;
+               struct nvme_create_sq create_sq;
+               struct nvme_delete_queue delete_queue;
+               struct nvme_download_firmware dlfw;
+               struct nvme_format_cmd format;
+               struct nvme_dsm_cmd dsm;
+               struct nvme_abort_cmd abort;
+       };
+};
+
+enum {
+       NVME_SC_SUCCESS                 = 0x0,
+       NVME_SC_INVALID_OPCODE          = 0x1,
+       NVME_SC_INVALID_FIELD           = 0x2,
+       NVME_SC_CMDID_CONFLICT          = 0x3,
+       NVME_SC_DATA_XFER_ERROR         = 0x4,
+       NVME_SC_POWER_LOSS              = 0x5,
+       NVME_SC_INTERNAL                = 0x6,
+       NVME_SC_ABORT_REQ               = 0x7,
+       NVME_SC_ABORT_QUEUE             = 0x8,
+       NVME_SC_FUSED_FAIL              = 0x9,
+       NVME_SC_FUSED_MISSING           = 0xa,
+       NVME_SC_INVALID_NS              = 0xb,
+       NVME_SC_CMD_SEQ_ERROR           = 0xc,
+       NVME_SC_SGL_INVALID_LAST        = 0xd,
+       NVME_SC_SGL_INVALID_COUNT       = 0xe,
+       NVME_SC_SGL_INVALID_DATA        = 0xf,
+       NVME_SC_SGL_INVALID_METADATA    = 0x10,
+       NVME_SC_SGL_INVALID_TYPE        = 0x11,
+       NVME_SC_LBA_RANGE               = 0x80,
+       NVME_SC_CAP_EXCEEDED            = 0x81,
+       NVME_SC_NS_NOT_READY            = 0x82,
+       NVME_SC_RESERVATION_CONFLICT    = 0x83,
+       NVME_SC_CQ_INVALID              = 0x100,
+       NVME_SC_QID_INVALID             = 0x101,
+       NVME_SC_QUEUE_SIZE              = 0x102,
+       NVME_SC_ABORT_LIMIT             = 0x103,
+       NVME_SC_ABORT_MISSING           = 0x104,
+       NVME_SC_ASYNC_LIMIT             = 0x105,
+       NVME_SC_FIRMWARE_SLOT           = 0x106,
+       NVME_SC_FIRMWARE_IMAGE          = 0x107,
+       NVME_SC_INVALID_VECTOR          = 0x108,
+       NVME_SC_INVALID_LOG_PAGE        = 0x109,
+       NVME_SC_INVALID_FORMAT          = 0x10a,
+       NVME_SC_FIRMWARE_NEEDS_RESET    = 0x10b,
+       NVME_SC_INVALID_QUEUE           = 0x10c,
+       NVME_SC_FEATURE_NOT_SAVEABLE    = 0x10d,
+       NVME_SC_FEATURE_NOT_CHANGEABLE  = 0x10e,
+       NVME_SC_FEATURE_NOT_PER_NS      = 0x10f,
+       NVME_SC_FW_NEEDS_RESET_SUBSYS   = 0x110,
+       NVME_SC_BAD_ATTRIBUTES          = 0x180,
+       NVME_SC_INVALID_PI              = 0x181,
+       NVME_SC_READ_ONLY               = 0x182,
+       NVME_SC_WRITE_FAULT             = 0x280,
+       NVME_SC_READ_ERROR              = 0x281,
+       NVME_SC_GUARD_CHECK             = 0x282,
+       NVME_SC_APPTAG_CHECK            = 0x283,
+       NVME_SC_REFTAG_CHECK            = 0x284,
+       NVME_SC_COMPARE_FAILED          = 0x285,
+       NVME_SC_ACCESS_DENIED           = 0x286,
+       NVME_SC_DNR                     = 0x4000,
+};
+
+struct nvme_completion {
+       __le32  result;         /* Used by admin commands to return data */
+       __u32   rsvd;
+       __le16  sq_head;        /* how much of this queue may be reclaimed */
+       __le16  sq_id;          /* submission queue that generated this entry */
+       __u16   command_id;     /* of the command which completed */
+       __le16  status;         /* did the command fail, and if so, why? */
+};
+
+struct nvme_user_io {
+       __u8    opcode;
+       __u8    flags;
+       __u16   control;
+       __u16   nblocks;
+       __u16   rsvd;
+       __u64   metadata;
+       __u64   addr;
+       __u64   slba;
+       __u32   dsmgmt;
+       __u32   reftag;
+       __u16   apptag;
+       __u16   appmask;
+};
+
+struct nvme_passthru_cmd {
+       __u8    opcode;
+       __u8    flags;
+       __u16   rsvd1;
+       __u32   nsid;
+       __u32   cdw2;
+       __u32   cdw3;
+       __u64   metadata;
+       __u64   addr;
+       __u32   metadata_len;
+       __u32   data_len;
+       __u32   cdw10;
+       __u32   cdw11;
+       __u32   cdw12;
+       __u32   cdw13;
+       __u32   cdw14;
+       __u32   cdw15;
+       __u32   timeout_ms;
+       __u32   result;
+};
+
+/*
+ * Registers should always be accessed with double word or quad word
+ * accesses. Registers with 64-bit address pointers should be written
+ * to with dword accesses by writing the low dword first (ptr[0]),
+ * then the high dword (ptr[1]) second.
+ */
+static inline u64 nvme_readq(__le64 volatile *regs)
+{
+#if BITS_PER_LONG == 64
+       return readq(regs);
+#else
+       __u32 *ptr = (__u32 *)regs;
+       u64 val_lo = readl(ptr);
+       u64 val_hi = readl(ptr + 1);
+
+       return val_lo + (val_hi << 32);
+#endif
+}
+
+static inline void nvme_writeq(const u64 val, __le64 volatile *regs)
+{
+#if BITS_PER_LONG == 64
+       writeq(val, regs);
+#else
+       __u32 *ptr = (__u32 *)regs;
+       u32 val_lo = lower_32_bits(val);
+       u32 val_hi = upper_32_bits(val);
+       writel(val_lo, ptr);
+       writel(val_hi, ptr + 1);
+#endif
+}
+
+struct nvme_bar {
+       __u64 cap;      /* Controller Capabilities */
+       __u32 vs;       /* Version */
+       __u32 intms;    /* Interrupt Mask Set */
+       __u32 intmc;    /* Interrupt Mask Clear */
+       __u32 cc;       /* Controller Configuration */
+       __u32 rsvd1;    /* Reserved */
+       __u32 csts;     /* Controller Status */
+       __u32 rsvd2;    /* Reserved */
+       __u32 aqa;      /* Admin Queue Attributes */
+       __u64 asq;      /* Admin SQ Base Address */
+       __u64 acq;      /* Admin CQ Base Address */
+};
+
+#define NVME_CAP_MQES(cap)     ((cap) & 0xffff)
+#define NVME_CAP_TIMEOUT(cap)  (((cap) >> 24) & 0xff)
+#define NVME_CAP_STRIDE(cap)   (((cap) >> 32) & 0xf)
+#define NVME_CAP_MPSMIN(cap)   (((cap) >> 48) & 0xf)
+#define NVME_CAP_MPSMAX(cap)   (((cap) >> 52) & 0xf)
+
+#define NVME_VS(major, minor)  (((major) << 16) | ((minor) << 8))
+
+enum {
+       NVME_CC_ENABLE          = 1 << 0,
+       NVME_CC_CSS_NVM         = 0 << 4,
+       NVME_CC_MPS_SHIFT       = 7,
+       NVME_CC_ARB_RR          = 0 << 11,
+       NVME_CC_ARB_WRRU        = 1 << 11,
+       NVME_CC_ARB_VS          = 7 << 11,
+       NVME_CC_SHN_NONE        = 0 << 14,
+       NVME_CC_SHN_NORMAL      = 1 << 14,
+       NVME_CC_SHN_ABRUPT      = 2 << 14,
+       NVME_CC_SHN_MASK        = 3 << 14,
+       NVME_CC_IOSQES          = 6 << 16,
+       NVME_CC_IOCQES          = 4 << 20,
+       NVME_CSTS_RDY           = 1 << 0,
+       NVME_CSTS_CFS           = 1 << 1,
+       NVME_CSTS_SHST_NORMAL   = 0 << 2,
+       NVME_CSTS_SHST_OCCUR    = 1 << 2,
+       NVME_CSTS_SHST_CMPLT    = 2 << 2,
+       NVME_CSTS_SHST_MASK     = 3 << 2,
+};
+
+/* Represents an NVM Express device. Each nvme_dev is a PCI function. */
+struct nvme_dev {
+       struct list_head node;
+       struct nvme_queue **queues;
+       u32 __iomem *dbs;
+       unsigned int cardnum;
+       struct udevice *pdev;
+       pci_dev_t pci_dev;
+       int instance;
+       uint8_t *hw_addr;
+       unsigned queue_count;
+       unsigned online_queues;
+       unsigned max_qid;
+       int q_depth;
+       u32 db_stride;
+       u32 ctrl_config;
+       struct nvme_bar __iomem *bar;
+       struct list_head namespaces;
+       const char *name;
+       char serial[20];
+       char model[40];
+       char firmware_rev[8];
+       u32 max_transfer_shift;
+       u32 stripe_size;
+       u32 page_size;
+       u16 oncs;
+       u16 abort_limit;
+       u8 event_limit;
+       u8 vwc;
+       u64 *prp_pool;
+       u32 prp_entry_num;
+       u32 nn;
+       u32 blk_dev_start;
+};
+
+struct nvme_info {
+       int ns_num;     /*the number of nvme namespaces*/
+       int ndev_num;   /*the number of nvme devices*/
+       struct list_head dev_list;
+};
+
+/*
+ * The nvme_iod describes the data in an I/O, including the list of PRP
+ * entries.  You can't see it in this data structure because C doesn't let
+ * me express that.  Use nvme_alloc_iod to ensure there's enough space
+ * allocated to store the PRP list.
+ */
+struct nvme_iod {
+       unsigned long private;  /* For the use of the submitter of the I/O */
+       int npages;             /* In the PRP list. 0 means small pool in use */
+       int offset;             /* Of PRP list */
+       int nents;              /* Used in scatterlist */
+       int length;             /* Of data, in bytes */
+       dma_addr_t first_dma;
+};
+
+/*
+ * An NVM Express namespace is equivalent to a SCSI LUN.
+ * Each namespace is operated as an independent "device".
+ */
+struct nvme_ns {
+       struct list_head list;
+       struct nvme_dev *dev;
+       unsigned ns_id;
+       int devnum;
+       int lba_shift;
+       u16 ms;
+       u8 flbas;
+       u8 pi_type;
+       u64 mode_select_num_blocks;
+       u32 mode_select_block_len;
+};
+
+extern struct nvme_info *nvme_info;
+
+#endif /* __DRIVER_NVME_H__ */
diff --git a/drivers/nvme/nvme_show.c b/drivers/nvme/nvme_show.c
new file mode 100644 (file)
index 0000000..5577e5d
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2017 NXP Semiconductors
+ * Copyright (C) 2017 Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <nvme.h>
+#include "nvme.h"
+
+static void print_optional_admin_cmd(u16 oacs, int devnum)
+{
+       printf("Blk device %d: Optional Admin Command Support:\n",
+              devnum);
+       printf("\tNamespace Management/Attachment: %s\n",
+              oacs & 0x08 ? "yes" : "no");
+       printf("\tFirmware Commit/Image download: %s\n",
+              oacs & 0x04 ? "yes" : "no");
+       printf("\tFormat NVM: %s\n",
+              oacs & 0x02 ? "yes" : "no");
+       printf("\tSecurity Send/Receive: %s\n",
+              oacs & 0x01 ? "yes" : "no");
+}
+
+static void print_optional_nvm_cmd(u16 oncs, int devnum)
+{
+       printf("Blk device %d: Optional NVM Command Support:\n",
+              devnum);
+       printf("\tReservation: %s\n",
+              oncs & 0x10 ? "yes" : "no");
+       printf("\tSave/Select field in the Set/Get features: %s\n",
+              oncs & 0x08 ? "yes" : "no");
+       printf("\tWrite Zeroes: %s\n",
+              oncs & 0x04 ? "yes" : "no");
+       printf("\tDataset Management: %s\n",
+              oncs & 0x02 ? "yes" : "no");
+       printf("\tWrite Uncorrectable: %s\n",
+              oncs & 0x01 ? "yes" : "no");
+}
+
+static void print_format_nvme_attributes(u8 fna, int devnum)
+{
+       printf("Blk device %d: Format NVM Attributes:\n", devnum);
+       printf("\tSupport Cryptographic Erase: %s\n",
+              fna & 0x04 ? "yes" : "No");
+       printf("\tSupport erase a particular namespace: %s\n",
+              fna & 0x02 ? "No" : "Yes");
+       printf("\tSupport format a particular namespace: %s\n",
+              fna & 0x01 ? "No" : "Yes");
+}
+
+static void print_format(struct nvme_lbaf *lbaf)
+{
+       u8 str[][10] = {"Best", "Better", "Good", "Degraded"};
+
+       printf("\t\tMetadata Size: %d\n", le16_to_cpu(lbaf->ms));
+       printf("\t\tLBA Data Size: %d\n", 1 << lbaf->ds);
+       printf("\t\tRelative Performance: %s\n", str[lbaf->rp & 0x03]);
+}
+
+static void print_formats(struct nvme_id_ns *id, struct nvme_ns *ns)
+{
+       int i;
+
+       printf("Blk device %d: LBA Format Support:\n", ns->devnum);
+
+       for (i = 0; i < id->nlbaf; i++) {
+               printf("\tLBA Foramt %d Support: ", i);
+               if (i == ns->flbas)
+                       printf("(current)\n");
+               else
+                       printf("\n");
+               print_format(id->lbaf + i);
+       }
+}
+
+static void print_data_protect_cap(u8 dpc, int devnum)
+{
+       printf("Blk device %d: End-to-End Data", devnum);
+       printf("Protect Capabilities:\n");
+       printf("\tAs last eight bytes: %s\n",
+              dpc & 0x10 ? "yes" : "No");
+       printf("\tAs first eight bytes: %s\n",
+              dpc & 0x08 ? "yes" : "No");
+       printf("\tSupport Type3: %s\n",
+              dpc & 0x04 ? "yes" : "No");
+       printf("\tSupport Type2: %s\n",
+              dpc & 0x02 ? "yes" : "No");
+       printf("\tSupport Type1: %s\n",
+              dpc & 0x01 ? "yes" : "No");
+}
+
+static void print_metadata_cap(u8 mc, int devnum)
+{
+       printf("Blk device %d: Metadata capabilities:\n", devnum);
+       printf("\tAs part of a separate buffer: %s\n",
+              mc & 0x02 ? "yes" : "No");
+       printf("\tAs part of an extended data LBA: %s\n",
+              mc & 0x01 ? "yes" : "No");
+}
+
+int nvme_print_info(struct udevice *udev)
+{
+       struct nvme_ns *ns = dev_get_priv(udev);
+       struct nvme_dev *dev = ns->dev;
+       struct nvme_id_ns buf_ns, *id = &buf_ns;
+       struct nvme_id_ctrl buf_ctrl, *ctrl = &buf_ctrl;
+
+       if (nvme_identify(dev, 0, 1, (dma_addr_t)ctrl))
+               return -EIO;
+
+       print_optional_admin_cmd(le16_to_cpu(ctrl->oacs), ns->devnum);
+       print_optional_nvm_cmd(le16_to_cpu(ctrl->oncs), ns->devnum);
+       print_format_nvme_attributes(ctrl->fna, ns->devnum);
+
+       if (nvme_identify(dev, ns->ns_id, 0, (dma_addr_t)id))
+               return -EIO;
+
+       print_formats(id, ns);
+       print_data_protect_cap(id->dpc, ns->devnum);
+       print_metadata_cap(id->mc, ns->devnum);
+
+       return 0;
+}
index 8a8e8e480f548b2277547e6157859793ff313082..3c5582a9504c8e079c24c14e86da4b7a940afdc7 100644 (file)
@@ -188,13 +188,6 @@ config ZYNQ_QSPI
          Zynq QSPI IP core. This IP is used to connect the flash in
          4-bit qspi, 8-bit dual stacked and shared 4-bit dual parallel.
 
-config OMAP3_SPI
-       bool "McSPI driver for OMAP"
-       help
-         SPI master controller for OMAP24XX and later Multichannel SPI
-         (McSPI). This driver be used to access SPI chips on platforms
-         embedding this OMAP3 McSPI IP core.
-
 endif # if DM_SPI
 
 config SOFT_SPI
@@ -229,4 +222,11 @@ config MPC8XX_SPI
        help
          Enable support for SPI on MPC8XX
 
+config OMAP3_SPI
+       bool "McSPI driver for OMAP"
+       help
+         SPI master controller for OMAP24XX and later Multichannel SPI
+         (McSPI). This driver be used to access SPI chips on platforms
+         embedding this OMAP3 McSPI IP core.
+
 endmenu # menu "SPI Support"
index bb9ae808666f577bef796ab277f1ea8a8e20d6e8..8a30f024fdbf9511785ad206a28e9942953f37e9 100644 (file)
 
 DECLARE_GLOBAL_DATA_PTR;
 
-int wdt_start(struct udevice *dev, u64 timeout, ulong flags)
+int wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags)
 {
        const struct wdt_ops *ops = device_get_ops(dev);
 
        if (!ops->start)
                return -ENOSYS;
 
-       return ops->start(dev, timeout, flags);
+       return ops->start(dev, timeout_ms, flags);
 }
 
 int wdt_stop(struct udevice *dev)
index 1e6239ac9e8676f4b3280a0a8229bea86d14aaab..61b56281b3150cc815a7385969ed6504d8d0d379 100644 (file)
@@ -31,6 +31,7 @@ enum if_type {
        IF_TYPE_SATA,
        IF_TYPE_HOST,
        IF_TYPE_SYSTEMACE,
+       IF_TYPE_NVME,
 
        IF_TYPE_COUNT,                  /* Number of interface types */
 };
index d3fbcb5c76d73391d0a0bb27f6a7f1cced0ccc0d..b84f6e3480cb118d9fbb14f9de249341c9d186b4 100644 (file)
 #endif
 
 /* SPI */
-#undef CONFIG_OMAP3_SPI
 #define CONFIG_TI_SPI_MMAP
 #define CONFIG_QSPI_SEL_GPIO                   48
 #define CONFIG_SF_DEFAULT_SPEED                48000000
index 9f07bba0c8985565a6709f938dd3c069b5fb7360..0c70c5305033e30fa757af80801148b648d507d8 100644 (file)
 #define CONFIG_SYS_SPI_U_BOOT_OFFS     0x40000
 
 /* SPI */
-#undef CONFIG_OMAP3_SPI
 #define CONFIG_TI_SPI_MMAP
 #define CONFIG_SF_DEFAULT_SPEED                76800000
 #define CONFIG_SF_DEFAULT_MODE                 SPI_MODE_0
index f965fc9a1d0fc3ad466efe5b555cda68f5c1fc06..07a173ff14f7c31edddb4e8562e7a30b3d1400ed 100644 (file)
@@ -234,7 +234,6 @@ MMCARGS
 #if defined(CONFIG_SPI_BOOT)
 /* McSPI IP block */
 #define CONFIG_SPI
-#define CONFIG_OMAP3_SPI
 #define CONFIG_SF_DEFAULT_SPEED                24000000
 
 #define CONFIG_SPL_SPI_LOAD
index 49db5a964cbae36fdcc961a8900f87d4ff4fed25..3aaa82ce511dd4b8537b9b67104c6f64ae967ff1 100644 (file)
@@ -29,8 +29,6 @@
 #define CONFIG_SYS_SPD_BUS_NUM 3
 
 /* SPI Flash support */
-#undef  CONFIG_OMAP3_SPI
-
 #define CONFIG_TI_SPI_MMAP
 #define CONFIG_SF_DEFAULT_SPEED                48000000
 #define CONFIG_DEFAULT_SPI_MODE                SPI_MODE_3
index d29859d93ab270457e09feaa027bab25ea277027..2287d5b6e455ec2bd8a6c5d067de362bd584a65d 100644 (file)
@@ -16,7 +16,6 @@
 #include <configs/ti_am335x_common.h>
 
 #undef CONFIG_SPI
-#undef CONFIG_OMAP3_SPI
 #undef CONFIG_BOOTCOUNT_LIMIT
 #undef CONFIG_SPL_AM33XX_ENABLE_RTC32K_OSC
 
index adef6f8b185798a67a98fa6207edf6e48aad274b..a94d55fa3abe5e11eecc90923cd25f24fde332a9 100644 (file)
 #define CONFIG_BMP_16BPP
 #define CONFIG_SCF0403_LCD
 
-#define CONFIG_OMAP3_SPI
-
 /* Defines for SPL */
 #define CONFIG_SPL_FRAMEWORK
 #define CONFIG_SPL_NAND_SIMPLE
index 5821183fc9ca4e9341a93c5368147ef922f50a5a..3a9fd2ac6c550eb4edfe9a057a55f31fb55ea3cf 100644 (file)
 #define CONFIG_BMP_16BPP
 #define CONFIG_SCF0403_LCD
 
-#define CONFIG_OMAP3_SPI
-
 /* EEPROM */
 #define CONFIG_ENV_EEPROM_IS_ON_I2C
 #define CONFIG_SYS_I2C_EEPROM_ADDR_LEN         1
index 5edf0a9bf657453e0e2bd3634334af52dd368eb3..2bf0983e37e35c08eb016882dcd6c633068be297 100644 (file)
@@ -60,7 +60,6 @@
 
 /* SPI */
 #undef CONFIG_SPI
-#undef CONFIG_OMAP3_SPI
 
 /* I2C */
 
index e124bda496b0392536c44b5eda6d12a33f94ddc0..efe63daf269fe843cabf9782d2127b1d323f8199 100644 (file)
 #define CONFIG_PHY_TI
 
 /* SPI */
-#undef CONFIG_OMAP3_SPI
 #define CONFIG_TI_SPI_MMAP
 #define CONFIG_SF_DEFAULT_SPEED                76800000
 #define CONFIG_SF_DEFAULT_MODE                 SPI_MODE_0
index 6d589273aa94e07b80d2f2096fc2efdb728e0cd6..a072708d616ce1ea2af08a8c732edc08164f8b65 100644 (file)
 #define CONFIG_CMDLINE_EDITING         /* add command line history */
 #define CONFIG_AUTO_COMPLETE           /* add autocompletion support */
 
-#define CONFIG_OMAP3_SPI
 #define CONFIG_SYS_I2C
 #define CONFIG_SYS_OMAP24_I2C_SPEED    100000
 #define CONFIG_SYS_OMAP24_I2C_SLAVE    1
index fe83e71b6182ee439e17bce60ba17bf6c7db26b0..33d29b56926d021df36d7aa830ddcfe599a9a904 100644 (file)
 #define CONFIG_ENV_OFFSET              SMNAND_ENV_OFFSET
 #define CONFIG_ENV_ADDR                        SMNAND_ENV_OFFSET
 
-#define CONFIG_OMAP3_SPI
-
 /* Defines for SPL */
 #define CONFIG_SPL_OMAP3_ID_NAND
 
index 729bcc74eb2bbf2abf2cb24495981f913da61367..560e50081f086289f7286d635db86dbe83b98c01 100644 (file)
 #define CONFIG_ENV_OFFSET              SMNAND_ENV_OFFSET
 #define CONFIG_ENV_ADDR                        SMNAND_ENV_OFFSET
 
-#define CONFIG_OMAP3_SPI
-
 /* Defines for SPL */
 #define CONFIG_SPL_OMAP3_ID_NAND
 
index e676a5acd481a81861aef343c5303c864714056e..9f9bc718cd20a6ae6d3aedad97a0fd38244b35bb 100644 (file)
 #define DA8XX_LCD_CNTL_BASE    LCD_CNTL_BASE
 
 #define CONFIG_SPI
-#define CONFIG_OMAP3_SPI
 
 #define BOARD_LCD_RESET                115     /* Bank 3 pin 19 */
 #define CONFIG_FORMIKE
index 83768cd2fb0fde448364cd029f6fdaec9147ce4d..5ed46588dd8cfd655743bfbb3b6b309557870d47 100644 (file)
@@ -72,7 +72,6 @@
 #define CONFIG_SYS_LOAD_ADDR           0x81000000 /* Default load address */
 
 #define CONFIG_SPI
-#define CONFIG_OMAP3_SPI
 #define CONFIG_MTD_DEVICE
 #define CONFIG_SF_DEFAULT_SPEED                (75000000)
 
index b755bb9d9e18b459e97b3019f4b41fab255f165a..d47dc8bba909bc1c137e247599986e4e611da853 100644 (file)
                                         CONFIG_SYS_INIT_RAM_SIZE - \
                                         GENERATED_GBL_DATA_SIZE)
 
-#define CONFIG_OMAP3_SPI
-
 /*
  * USB
  *
index 6834500c172fa937a15b2cbda4444281cf4cd439..306f503d9e9d792163faa780be92012f691501a7 100644 (file)
@@ -16,9 +16,6 @@
 #define CONFIG_SYS_OMAP24_I2C_SPEED    100000
 #define CONFIG_SYS_OMAP24_I2C_SLAVE    1
 
-/* SPI IP Block */
-#define CONFIG_OMAP3_SPI
-
 /*
  * GPMC NAND block.  We support 1 device and the physical address to
  * access CS0 at is 0x8000000.
index 2e6498b7dcd1126444b930b7dae880ae530e6523..1a501992db26b9ed555b712f0b53060d47ed7500 100644 (file)
@@ -52,6 +52,7 @@ enum uclass_id {
        UCLASS_MOD_EXP,         /* RSA Mod Exp device */
        UCLASS_MTD,             /* Memory Technology Device (MTD) device */
        UCLASS_NORTHBRIDGE,     /* Intel Northbridge / SDRAM controller */
+       UCLASS_NVME,            /* NVM Express device */
        UCLASS_PANEL,           /* Display panel, such as an LCD */
        UCLASS_PANEL_BACKLIGHT, /* Backlight controller for panel */
        UCLASS_PCH,             /* x86 platform controller hub */
index 908d7cec6ca8c9fed255754632d3b7237da9c74e..55c5bdd4b12983fde8c70bf49a474a5b0d64e1e1 100644 (file)
@@ -467,7 +467,6 @@ extern flash_info_t *flash_get_info(ulong base);
 #define FLASH_S29GL128N 0x00F1         /* Spansion S29GL128N                   */
 
 #define FLASH_STM32    0x00F2          /* STM32 Embedded Flash */
-#define FLASH_STM32F1  0x00F3          /* STM32F1 Embedded Flash */
 
 #define FLASH_UNKNOWN  0xFFFF          /* unknown flash type                   */
 
diff --git a/include/nvme.h b/include/nvme.h
new file mode 100644 (file)
index 0000000..8375d61
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2017 NXP Semiconductors
+ * Copyright (C) 2017 Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef __NVME_H__
+#define __NVME_H__
+
+struct nvme_dev;
+
+/**
+ * nvme_identify - identify controller or namespace capabilities and status
+ *
+ * This issues an identify command to the NVMe controller to return a data
+ * buffer that describes the controller or namespace capabilities and status.
+ *
+ * @dev:       NVMe controller device
+ * @nsid:      0 for controller, namespace id for namespace to identify
+ * @cns:       1 for controller, 0 for namespace
+ * @dma_addr:  dma buffer address to store the identify result
+ * @return:    0 on success, -ETIMEDOUT on command execution timeout,
+ *             -EIO on command execution fails
+ */
+int nvme_identify(struct nvme_dev *dev, unsigned nsid,
+                 unsigned cns, dma_addr_t dma_addr);
+
+/**
+ * nvme_get_features - retrieve the attributes of the feature specified
+ *
+ * This retrieves the attributes of the feature specified.
+ *
+ * @dev:       NVMe controller device
+ * @fid:       feature id to provide data
+ * @nsid:      namespace id the command applies to
+ * @dma_addr:  data structure used as part of the specified feature
+ * @result:    command-specific result in the completion queue entry
+ * @return:    0 on success, -ETIMEDOUT on command execution timeout,
+ *             -EIO on command execution fails
+ */
+int nvme_get_features(struct nvme_dev *dev, unsigned fid, unsigned nsid,
+                     dma_addr_t dma_addr, u32 *result);
+
+/**
+ * nvme_set_features - specify the attributes of the feature indicated
+ *
+ * This specifies the attributes of the feature indicated.
+ *
+ * @dev:       NVMe controller device
+ * @fid:       feature id to provide data
+ * @dword11:   command-specific input parameter
+ * @dma_addr:  data structure used as part of the specified feature
+ * @result:    command-specific result in the completion queue entry
+ * @return:    0 on success, -ETIMEDOUT on command execution timeout,
+ *             -EIO on command execution fails
+ */
+int nvme_set_features(struct nvme_dev *dev, unsigned fid, unsigned dword11,
+                     dma_addr_t dma_addr, u32 *result);
+
+/**
+ * nvme_scan_namespace - scan all namespaces attached to NVMe controllers
+ *
+ * This probes all registered NVMe uclass device drivers in the system,
+ * and tries to find all namespaces attached to the NVMe controllers.
+ *
+ * @return:    0 on success, -ve on error
+ */
+int nvme_scan_namespace(void);
+
+/**
+ * nvme_print_info - print detailed NVMe controller and namespace information
+ *
+ * This prints out detailed human readable NVMe controller and namespace
+ * information which is very useful for debugging.
+ *
+ * @udev:      NVMe controller device
+ * @return:    0 on success, -EIO if NVMe identify command fails
+ */
+int nvme_print_info(struct udevice *udev);
+
+#endif /* __NVME_H__ */
index ab6aa58adb815b8748bcd0b35f574935468a0987..fdda679cc05a7b1612afed3c3d08efbd64b8c36c 100644 (file)
@@ -21,6 +21,7 @@
 #define PCI_CLASS_STORAGE_SATA         0x0106
 #define PCI_CLASS_STORAGE_SATA_AHCI    0x010601
 #define PCI_CLASS_STORAGE_SAS          0x0107
+#define PCI_CLASS_STORAGE_EXPRESS      0x010802
 #define PCI_CLASS_STORAGE_OTHER                0x0180
 
 #define PCI_BASE_CLASS_NETWORK         0x02
index 0b5f05851a33c0e7527d30958a86e2214a9469e4..9b90fbeeb3a304d44ce1149ffd7d1dc9899cc3c3 100644 (file)
  * Start the timer
  *
  * @dev: WDT Device
- * @timeout: Number of ticks before timer expires
+ * @timeout_ms: Number of ticks (milliseconds) before timer expires
  * @flags: Driver specific flags. This might be used to specify
  * which action needs to be executed when the timer expires
  * @return: 0 if OK, -ve on error
  */
-int wdt_start(struct udevice *dev, u64 timeout, ulong flags);
+int wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags);
 
 /*
  * Stop the timer, thus disabling the Watchdog. Use wdt_start to start it again.
@@ -67,12 +67,12 @@ struct wdt_ops {
         * Start the timer
         *
         * @dev: WDT Device
-        * @timeout: Number of ticks before the timer expires
+        * @timeout_ms: Number of ticks (milliseconds) before the timer expires
         * @flags: Driver specific flags. This might be used to specify
         * which action needs to be executed when the timer expires
         * @return: 0 if OK, -ve on error
         */
-       int (*start)(struct udevice *dev, u64 timeout, ulong flags);
+       int (*start)(struct udevice *dev, u64 timeout_ms, ulong flags);
        /*
         * Stop the timer
         *
index fb520e3d733ca4bfe813efd34827adaae283a2ec..d1cf5a8a1679fa7ab7f828c8b4290bb8aca80fe0 100644 (file)
--- a/lib/tpm.c
+++ b/lib/tpm.c
@@ -95,8 +95,10 @@ int pack_byte_string(uint8_t *str, size_t size, const char *format, ...)
                        return -1;
                }
 
-               if (offset + length > size)
+               if (offset + length > size) {
+                       va_end(args);
                        return -1;
+               }
 
                switch (*format) {
                case 'b':
@@ -163,6 +165,7 @@ int unpack_byte_string(const uint8_t *str, size_t size, const char *format, ...)
                        length = va_arg(args, uint32_t);
                        break;
                default:
+                       va_end(args);
                        debug("Couldn't recognize format string\n");
                        return -1;
                }
diff --git a/test/image/test-fit.py b/test/image/test-fit.py
deleted file mode 100755 (executable)
index b0d0538..0000000
+++ /dev/null
@@ -1,481 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (c) 2013, Google Inc.
-#
-# Sanity check of the FIT handling in U-Boot
-#
-# SPDX-License-Identifier:     GPL-2.0+
-#
-# To run this:
-#
-# make O=sandbox sandbox_config
-# make O=sandbox
-# ./test/image/test-fit.py -u sandbox/u-boot
-#
-# Note: The above testing requires the Python development package, typically
-# called python-devel or something similar.
-
-import doctest
-from optparse import OptionParser
-import os
-import shutil
-import struct
-import sys
-import tempfile
-
-# Enable printing of all U-Boot output
-DEBUG = True
-
-# The 'command' library in patman is convenient for running commands
-base_path = os.path.dirname(sys.argv[0])
-patman = os.path.join(base_path, '../../tools/patman')
-sys.path.append(patman)
-
-import command
-
-# Define a base ITS which we can adjust using % and a dictionary
-base_its = '''
-/dts-v1/;
-
-/ {
-        description = "Chrome OS kernel image with one or more FDT blobs";
-        #address-cells = <1>;
-
-        images {
-                kernel@1 {
-                        data = /incbin/("%(kernel)s");
-                        type = "kernel";
-                        arch = "sandbox";
-                        os = "linux";
-                        compression = "none";
-                        load = <0x40000>;
-                        entry = <0x8>;
-                };
-                kernel@2 {
-                        data = /incbin/("%(loadables1)s");
-                        type = "kernel";
-                        arch = "sandbox";
-                        os = "linux";
-                        compression = "none";
-                        %(loadables1_load)s
-                        entry = <0x0>;
-                };
-                fdt@1 {
-                        description = "snow";
-                        data = /incbin/("u-boot.dtb");
-                        type = "flat_dt";
-                        arch = "sandbox";
-                        %(fdt_load)s
-                        compression = "none";
-                        signature@1 {
-                                algo = "sha1,rsa2048";
-                                key-name-hint = "dev";
-                        };
-                };
-                ramdisk@1 {
-                        description = "snow";
-                        data = /incbin/("%(ramdisk)s");
-                        type = "ramdisk";
-                        arch = "sandbox";
-                        os = "linux";
-                        %(ramdisk_load)s
-                        compression = "none";
-                };
-                ramdisk@2 {
-                        description = "snow";
-                        data = /incbin/("%(loadables2)s");
-                        type = "ramdisk";
-                        arch = "sandbox";
-                        os = "linux";
-                        %(loadables2_load)s
-                        compression = "none";
-                };
-        };
-        configurations {
-                default = "conf@1";
-                conf@1 {
-                        kernel = "kernel@1";
-                        fdt = "fdt@1";
-                        %(ramdisk_config)s
-                        %(loadables_config)s
-                };
-        };
-};
-'''
-
-# Define a base FDT - currently we don't use anything in this
-base_fdt = '''
-/dts-v1/;
-
-/ {
-        model = "Sandbox Verified Boot Test";
-        compatible = "sandbox";
-
-       reset@0 {
-               compatible = "sandbox,reset";
-       };
-
-};
-'''
-
-# This is the U-Boot script that is run for each test. First load the FIT,
-# then run the 'bootm' command, then save out memory from the places where
-# we expect 'bootm' to write things. Then quit.
-base_script = '''
-sb load hostfs 0 %(fit_addr)x %(fit)s
-fdt addr %(fit_addr)x
-bootm start %(fit_addr)x
-bootm loados
-sb save hostfs 0 %(kernel_addr)x %(kernel_out)s %(kernel_size)x
-sb save hostfs 0 %(fdt_addr)x %(fdt_out)s %(fdt_size)x
-sb save hostfs 0 %(ramdisk_addr)x %(ramdisk_out)s %(ramdisk_size)x
-sb save hostfs 0 %(loadables1_addr)x %(loadables1_out)s %(loadables1_size)x
-sb save hostfs 0 %(loadables2_addr)x %(loadables2_out)s %(loadables2_size)x
-reset
-'''
-
-def debug_stdout(stdout):
-    if DEBUG:
-        print stdout
-
-def make_fname(leaf):
-    """Make a temporary filename
-
-    Args:
-        leaf: Leaf name of file to create (within temporary directory)
-    Return:
-        Temporary filename
-    """
-    global base_dir
-
-    return os.path.join(base_dir, leaf)
-
-def filesize(fname):
-    """Get the size of a file
-
-    Args:
-        fname: Filename to check
-    Return:
-        Size of file in bytes
-    """
-    return os.stat(fname).st_size
-
-def read_file(fname):
-    """Read the contents of a file
-
-    Args:
-        fname: Filename to read
-    Returns:
-        Contents of file as a string
-    """
-    with open(fname, 'r') as fd:
-        return fd.read()
-
-def make_dtb():
-    """Make a sample .dts file and compile it to a .dtb
-
-    Returns:
-        Filename of .dtb file created
-    """
-    src = make_fname('u-boot.dts')
-    dtb = make_fname('u-boot.dtb')
-    with open(src, 'w') as fd:
-        print >>fd, base_fdt
-    command.Output('dtc', src, '-O', 'dtb', '-o', dtb)
-    return dtb
-
-def make_its(params):
-    """Make a sample .its file with parameters embedded
-
-    Args:
-        params: Dictionary containing parameters to embed in the %() strings
-    Returns:
-        Filename of .its file created
-    """
-    its = make_fname('test.its')
-    with open(its, 'w') as fd:
-        print >>fd, base_its % params
-    return its
-
-def make_fit(mkimage, params):
-    """Make a sample .fit file ready for loading
-
-    This creates a .its script with the selected parameters and uses mkimage to
-    turn this into a .fit image.
-
-    Args:
-        mkimage: Filename of 'mkimage' utility
-        params: Dictionary containing parameters to embed in the %() strings
-    Return:
-        Filename of .fit file created
-    """
-    fit = make_fname('test.fit')
-    its = make_its(params)
-    command.Output(mkimage, '-f', its, fit)
-    with open(make_fname('u-boot.dts'), 'w') as fd:
-        print >>fd, base_fdt
-    return fit
-
-def make_kernel(filename, text):
-    """Make a sample kernel with test data
-
-    Args:
-        filename: the name of the file you want to create
-    Returns:
-        Full path and filename of the kernel it created
-    """
-    fname = make_fname(filename)
-    data = ''
-    for i in range(100):
-        data += 'this %s %d is unlikely to boot\n' % (text, i)
-    with open(fname, 'w') as fd:
-        print >>fd, data
-    return fname
-
-def make_ramdisk(filename, text):
-    """Make a sample ramdisk with test data
-
-    Returns:
-        Filename of ramdisk created
-    """
-    fname = make_fname(filename)
-    data = ''
-    for i in range(100):
-        data += '%s %d was seldom used in the middle ages\n' % (text, i)
-    with open(fname, 'w') as fd:
-        print >>fd, data
-    return fname
-
-def find_matching(text, match):
-    """Find a match in a line of text, and return the unmatched line portion
-
-    This is used to extract a part of a line from some text. The match string
-    is used to locate the line - we use the first line that contains that
-    match text.
-
-    Once we find a match, we discard the match string itself from the line,
-    and return what remains.
-
-    TODO: If this function becomes more generally useful, we could change it
-    to use regex and return groups.
-
-    Args:
-        text: Text to check (each line separated by \n)
-        match: String to search for
-    Return:
-        String containing unmatched portion of line
-    Exceptions:
-        ValueError: If match is not found
-
-    >>> find_matching('first line:10\\nsecond_line:20', 'first line:')
-    '10'
-    >>> find_matching('first line:10\\nsecond_line:20', 'second line')
-    Traceback (most recent call last):
-      ...
-    ValueError: Test aborted
-    >>> find_matching('first line:10\\nsecond_line:20', 'second_line:')
-    '20'
-    """
-    for line in text.splitlines():
-        pos = line.find(match)
-        if pos != -1:
-            return line[:pos] + line[pos + len(match):]
-
-    print "Expected '%s' but not found in output:"
-    print text
-    raise ValueError('Test aborted')
-
-def set_test(name):
-    """Set the name of the current test and print a message
-
-    Args:
-        name: Name of test
-    """
-    global test_name
-
-    test_name = name
-    print name
-
-def fail(msg, stdout):
-    """Raise an error with a helpful failure message
-
-    Args:
-        msg: Message to display
-    """
-    print stdout
-    raise ValueError("Test '%s' failed: %s" % (test_name, msg))
-
-def run_fit_test(mkimage, u_boot):
-    """Basic sanity check of FIT loading in U-Boot
-
-    TODO: Almost everything:
-       - hash algorithms - invalid hash/contents should be detected
-       - signature algorithms - invalid sig/contents should be detected
-       - compression
-       - checking that errors are detected like:
-            - image overwriting
-            - missing images
-            - invalid configurations
-            - incorrect os/arch/type fields
-            - empty data
-            - images too large/small
-            - invalid FDT (e.g. putting a random binary in instead)
-       - default configuration selection
-       - bootm command line parameters should have desired effect
-       - run code coverage to make sure we are testing all the code
-    """
-    global test_name
-
-    # Set up invariant files
-    control_dtb = make_dtb()
-    kernel = make_kernel('test-kernel.bin', 'kernel')
-    ramdisk = make_ramdisk('test-ramdisk.bin', 'ramdisk')
-    loadables1 = make_kernel('test-loadables1.bin', 'lenrek')
-    loadables2 = make_ramdisk('test-loadables2.bin', 'ksidmar')
-    kernel_out = make_fname('kernel-out.bin')
-    fdt_out = make_fname('fdt-out.dtb')
-    ramdisk_out = make_fname('ramdisk-out.bin')
-    loadables1_out = make_fname('loadables1-out.bin')
-    loadables2_out = make_fname('loadables2-out.bin')
-
-    # Set up basic parameters with default values
-    params = {
-        'fit_addr' : 0x1000,
-
-        'kernel' : kernel,
-        'kernel_out' : kernel_out,
-        'kernel_addr' : 0x40000,
-        'kernel_size' : filesize(kernel),
-
-        'fdt_out' : fdt_out,
-        'fdt_addr' : 0x80000,
-        'fdt_size' : filesize(control_dtb),
-        'fdt_load' : '',
-
-        'ramdisk' : ramdisk,
-        'ramdisk_out' : ramdisk_out,
-        'ramdisk_addr' : 0xc0000,
-        'ramdisk_size' : filesize(ramdisk),
-        'ramdisk_load' : '',
-        'ramdisk_config' : '',
-
-        'loadables1' : loadables1,
-        'loadables1_out' : loadables1_out,
-        'loadables1_addr' : 0x100000,
-        'loadables1_size' : filesize(loadables1),
-        'loadables1_load' : '',
-
-        'loadables2' : loadables2,
-        'loadables2_out' : loadables2_out,
-        'loadables2_addr' : 0x140000,
-        'loadables2_size' : filesize(loadables2),
-        'loadables2_load' : '',
-
-        'loadables_config' : '',
-    }
-
-    # Make a basic FIT and a script to load it
-    fit = make_fit(mkimage, params)
-    params['fit'] = fit
-    cmd = base_script % params
-
-    # First check that we can load a kernel
-    # We could perhaps reduce duplication with some loss of readability
-    set_test('Kernel load')
-    stdout = command.Output(u_boot, '-d', control_dtb, '-c', cmd)
-    debug_stdout(stdout)
-    if read_file(kernel) != read_file(kernel_out):
-        fail('Kernel not loaded', stdout)
-    if read_file(control_dtb) == read_file(fdt_out):
-        fail('FDT loaded but should be ignored', stdout)
-    if read_file(ramdisk) == read_file(ramdisk_out):
-        fail('Ramdisk loaded but should not be', stdout)
-
-    # Find out the offset in the FIT where U-Boot has found the FDT
-    line = find_matching(stdout, 'Booting using the FDT blob at ')
-    fit_offset = int(line, 16) - params['fit_addr']
-    fdt_magic = struct.pack('>L', 0xd00dfeed)
-    data = read_file(fit)
-
-    # Now find where it actually is in the FIT (skip the first word)
-    real_fit_offset = data.find(fdt_magic, 4)
-    if fit_offset != real_fit_offset:
-        fail('U-Boot loaded FDT from offset %#x, FDT is actually at %#x' %
-                (fit_offset, real_fit_offset), stdout)
-
-    # Now a kernel and an FDT
-    set_test('Kernel + FDT load')
-    params['fdt_load'] = 'load = <%#x>;' % params['fdt_addr']
-    fit = make_fit(mkimage, params)
-    stdout = command.Output(u_boot, '-d', control_dtb, '-c', cmd)
-    debug_stdout(stdout)
-    if read_file(kernel) != read_file(kernel_out):
-        fail('Kernel not loaded', stdout)
-    if read_file(control_dtb) != read_file(fdt_out):
-        fail('FDT not loaded', stdout)
-    if read_file(ramdisk) == read_file(ramdisk_out):
-        fail('Ramdisk loaded but should not be', stdout)
-
-    # Try a ramdisk
-    set_test('Kernel + FDT + Ramdisk load')
-    params['ramdisk_config'] = 'ramdisk = "ramdisk@1";'
-    params['ramdisk_load'] = 'load = <%#x>;' % params['ramdisk_addr']
-    fit = make_fit(mkimage, params)
-    stdout = command.Output(u_boot, '-d', control_dtb, '-c', cmd)
-    debug_stdout(stdout)
-    if read_file(ramdisk) != read_file(ramdisk_out):
-        fail('Ramdisk not loaded', stdout)
-
-    # Configuration with some Loadables
-    set_test('Kernel + FDT + Ramdisk load + Loadables')
-    params['loadables_config'] = 'loadables = "kernel@2", "ramdisk@2";'
-    params['loadables1_load'] = 'load = <%#x>;' % params['loadables1_addr']
-    params['loadables2_load'] = 'load = <%#x>;' % params['loadables2_addr']
-    fit = make_fit(mkimage, params)
-    stdout = command.Output(u_boot, '-d', control_dtb, '-c', cmd)
-    debug_stdout(stdout)
-    if read_file(loadables1) != read_file(loadables1_out):
-        fail('Loadables1 (kernel) not loaded', stdout)
-    if read_file(loadables2) != read_file(loadables2_out):
-        fail('Loadables2 (ramdisk) not loaded', stdout)
-
-def run_tests():
-    """Parse options, run the FIT tests and print the result"""
-    global base_path, base_dir
-
-    # Work in a temporary directory
-    base_dir = tempfile.mkdtemp()
-    parser = OptionParser()
-    parser.add_option('-u', '--u-boot',
-            default=os.path.join(base_path, 'u-boot'),
-            help='Select U-Boot sandbox binary')
-    parser.add_option('-k', '--keep', action='store_true',
-            help="Don't delete temporary directory even when tests pass")
-    parser.add_option('-t', '--selftest', action='store_true',
-            help='Run internal self tests')
-    (options, args) = parser.parse_args()
-
-    # Find the path to U-Boot, and assume mkimage is in its tools/mkimage dir
-    base_path = os.path.dirname(options.u_boot)
-    mkimage = os.path.join(base_path, 'tools/mkimage')
-
-    # There are a few doctests - handle these here
-    if options.selftest:
-        doctest.testmod()
-        return
-
-    title = 'FIT Tests'
-    print title, '\n', '=' * len(title)
-
-    run_fit_test(mkimage, options.u_boot)
-
-    print '\nTests passed'
-    print 'Caveat: this is only a sanity check - test coverage is poor'
-
-    # Remove the temporary directory unless we are asked to keep it
-    if options.keep:
-        print "Output files are in '%s'" % base_dir
-    else:
-        shutil.rmtree(base_dir)
-
-run_tests()
diff --git a/test/py/tests/test_fit.py b/test/py/tests/test_fit.py
new file mode 100755 (executable)
index 0000000..7e6b96d
--- /dev/null
@@ -0,0 +1,428 @@
+# Copyright (c) 2013, Google Inc.
+#
+# SPDX-License-Identifier:     GPL-2.0+
+#
+# Sanity check of the FIT handling in U-Boot
+
+import os
+import pytest
+import struct
+import u_boot_utils as util
+
+# Define a base ITS which we can adjust using % and a dictionary
+base_its = '''
+/dts-v1/;
+
+/ {
+        description = "Chrome OS kernel image with one or more FDT blobs";
+        #address-cells = <1>;
+
+        images {
+                kernel@1 {
+                        data = /incbin/("%(kernel)s");
+                        type = "kernel";
+                        arch = "sandbox";
+                        os = "linux";
+                        compression = "none";
+                        load = <0x40000>;
+                        entry = <0x8>;
+                };
+                kernel@2 {
+                        data = /incbin/("%(loadables1)s");
+                        type = "kernel";
+                        arch = "sandbox";
+                        os = "linux";
+                        compression = "none";
+                        %(loadables1_load)s
+                        entry = <0x0>;
+                };
+                fdt@1 {
+                        description = "snow";
+                        data = /incbin/("u-boot.dtb");
+                        type = "flat_dt";
+                        arch = "sandbox";
+                        %(fdt_load)s
+                        compression = "none";
+                        signature@1 {
+                                algo = "sha1,rsa2048";
+                                key-name-hint = "dev";
+                        };
+                };
+                ramdisk@1 {
+                        description = "snow";
+                        data = /incbin/("%(ramdisk)s");
+                        type = "ramdisk";
+                        arch = "sandbox";
+                        os = "linux";
+                        %(ramdisk_load)s
+                        compression = "none";
+                };
+                ramdisk@2 {
+                        description = "snow";
+                        data = /incbin/("%(loadables2)s");
+                        type = "ramdisk";
+                        arch = "sandbox";
+                        os = "linux";
+                        %(loadables2_load)s
+                        compression = "none";
+                };
+        };
+        configurations {
+                default = "conf@1";
+                conf@1 {
+                        kernel = "kernel@1";
+                        fdt = "fdt@1";
+                        %(ramdisk_config)s
+                        %(loadables_config)s
+                };
+        };
+};
+'''
+
+# Define a base FDT - currently we don't use anything in this
+base_fdt = '''
+/dts-v1/;
+
+/ {
+        model = "Sandbox Verified Boot Test";
+        compatible = "sandbox";
+
+       reset@0 {
+               compatible = "sandbox,reset";
+       };
+
+};
+'''
+
+# This is the U-Boot script that is run for each test. First load the FIT,
+# then run the 'bootm' command, then save out memory from the places where
+# we expect 'bootm' to write things. Then quit.
+base_script = '''
+sb load hostfs 0 %(fit_addr)x %(fit)s
+fdt addr %(fit_addr)x
+bootm start %(fit_addr)x
+bootm loados
+sb save hostfs 0 %(kernel_addr)x %(kernel_out)s %(kernel_size)x
+sb save hostfs 0 %(fdt_addr)x %(fdt_out)s %(fdt_size)x
+sb save hostfs 0 %(ramdisk_addr)x %(ramdisk_out)s %(ramdisk_size)x
+sb save hostfs 0 %(loadables1_addr)x %(loadables1_out)s %(loadables1_size)x
+sb save hostfs 0 %(loadables2_addr)x %(loadables2_out)s %(loadables2_size)x
+'''
+
+@pytest.mark.boardspec('sandbox')
+@pytest.mark.buildconfigspec('fit_signature')
+def test_fit(u_boot_console):
+    def make_fname(leaf):
+        """Make a temporary filename
+
+        Args:
+            leaf: Leaf name of file to create (within temporary directory)
+        Return:
+            Temporary filename
+        """
+
+        return os.path.join(cons.config.build_dir, leaf)
+
+    def filesize(fname):
+        """Get the size of a file
+
+        Args:
+            fname: Filename to check
+        Return:
+            Size of file in bytes
+        """
+        return os.stat(fname).st_size
+
+    def read_file(fname):
+        """Read the contents of a file
+
+        Args:
+            fname: Filename to read
+        Returns:
+            Contents of file as a string
+        """
+        with open(fname, 'r') as fd:
+            return fd.read()
+
+    def make_dtb():
+        """Make a sample .dts file and compile it to a .dtb
+
+        Returns:
+            Filename of .dtb file created
+        """
+        src = make_fname('u-boot.dts')
+        dtb = make_fname('u-boot.dtb')
+        with open(src, 'w') as fd:
+            print >> fd, base_fdt
+        util.run_and_log(cons, ['dtc', src, '-O', 'dtb', '-o', dtb])
+        return dtb
+
+    def make_its(params):
+        """Make a sample .its file with parameters embedded
+
+        Args:
+            params: Dictionary containing parameters to embed in the %() strings
+        Returns:
+            Filename of .its file created
+        """
+        its = make_fname('test.its')
+        with open(its, 'w') as fd:
+            print >> fd, base_its % params
+        return its
+
+    def make_fit(mkimage, params):
+        """Make a sample .fit file ready for loading
+
+        This creates a .its script with the selected parameters and uses mkimage to
+        turn this into a .fit image.
+
+        Args:
+            mkimage: Filename of 'mkimage' utility
+            params: Dictionary containing parameters to embed in the %() strings
+        Return:
+            Filename of .fit file created
+        """
+        fit = make_fname('test.fit')
+        its = make_its(params)
+        util.run_and_log(cons, [mkimage, '-f', its, fit])
+        with open(make_fname('u-boot.dts'), 'w') as fd:
+            print >> fd, base_fdt
+        return fit
+
+    def make_kernel(filename, text):
+        """Make a sample kernel with test data
+
+        Args:
+            filename: the name of the file you want to create
+        Returns:
+            Full path and filename of the kernel it created
+        """
+        fname = make_fname(filename)
+        data = ''
+        for i in range(100):
+            data += 'this %s %d is unlikely to boot\n' % (text, i)
+        with open(fname, 'w') as fd:
+            print >> fd, data
+        return fname
+
+    def make_ramdisk(filename, text):
+        """Make a sample ramdisk with test data
+
+        Returns:
+            Filename of ramdisk created
+        """
+        fname = make_fname(filename)
+        data = ''
+        for i in range(100):
+            data += '%s %d was seldom used in the middle ages\n' % (text, i)
+        with open(fname, 'w') as fd:
+            print >> fd, data
+        return fname
+
+    def find_matching(text, match):
+        """Find a match in a line of text, and return the unmatched line portion
+
+        This is used to extract a part of a line from some text. The match string
+        is used to locate the line - we use the first line that contains that
+        match text.
+
+        Once we find a match, we discard the match string itself from the line,
+        and return what remains.
+
+        TODO: If this function becomes more generally useful, we could change it
+        to use regex and return groups.
+
+        Args:
+            text: Text to check (list of strings, one for each command issued)
+            match: String to search for
+        Return:
+            String containing unmatched portion of line
+        Exceptions:
+            ValueError: If match is not found
+
+        >>> find_matching(['first line:10', 'second_line:20'], 'first line:')
+        '10'
+        >>> find_matching(['first line:10', 'second_line:20'], 'second line')
+        Traceback (most recent call last):
+          ...
+        ValueError: Test aborted
+        >>> find_matching('first line:10\', 'second_line:20'], 'second_line:')
+        '20'
+        >>> find_matching('first line:10\', 'second_line:20\nthird_line:30'],
+                          'third_line:')
+        '30'
+        """
+        __tracebackhide__ = True
+        for line in '\n'.join(text).splitlines():
+            pos = line.find(match)
+            if pos != -1:
+                return line[:pos] + line[pos + len(match):]
+
+        pytest.fail("Expected '%s' but not found in output")
+
+    def check_equal(expected_fname, actual_fname, failure_msg):
+        """Check that a file matches its expected contents
+
+        Args:
+            expected_fname: Filename containing expected contents
+            actual_fname: Filename containing actual contents
+            failure_msg: Message to print on failure
+        """
+        expected_data = read_file(expected_fname)
+        actual_data = read_file(actual_fname)
+        assert expected_data == actual_data, failure_msg
+
+    def check_not_equal(expected_fname, actual_fname, failure_msg):
+        """Check that a file does not match its expected contents
+
+        Args:
+            expected_fname: Filename containing expected contents
+            actual_fname: Filename containing actual contents
+            failure_msg: Message to print on failure
+        """
+        expected_data = read_file(expected_fname)
+        actual_data = read_file(actual_fname)
+        assert expected_data != actual_data, failure_msg
+
+    def run_fit_test(mkimage):
+        """Basic sanity check of FIT loading in U-Boot
+
+        TODO: Almost everything:
+          - hash algorithms - invalid hash/contents should be detected
+          - signature algorithms - invalid sig/contents should be detected
+          - compression
+          - checking that errors are detected like:
+                - image overwriting
+                - missing images
+                - invalid configurations
+                - incorrect os/arch/type fields
+                - empty data
+                - images too large/small
+                - invalid FDT (e.g. putting a random binary in instead)
+          - default configuration selection
+          - bootm command line parameters should have desired effect
+          - run code coverage to make sure we are testing all the code
+        """
+        # Set up invariant files
+        control_dtb = make_dtb()
+        kernel = make_kernel('test-kernel.bin', 'kernel')
+        ramdisk = make_ramdisk('test-ramdisk.bin', 'ramdisk')
+        loadables1 = make_kernel('test-loadables1.bin', 'lenrek')
+        loadables2 = make_ramdisk('test-loadables2.bin', 'ksidmar')
+        kernel_out = make_fname('kernel-out.bin')
+        fdt_out = make_fname('fdt-out.dtb')
+        ramdisk_out = make_fname('ramdisk-out.bin')
+        loadables1_out = make_fname('loadables1-out.bin')
+        loadables2_out = make_fname('loadables2-out.bin')
+
+        # Set up basic parameters with default values
+        params = {
+            'fit_addr' : 0x1000,
+
+            'kernel' : kernel,
+            'kernel_out' : kernel_out,
+            'kernel_addr' : 0x40000,
+            'kernel_size' : filesize(kernel),
+
+            'fdt_out' : fdt_out,
+            'fdt_addr' : 0x80000,
+            'fdt_size' : filesize(control_dtb),
+            'fdt_load' : '',
+
+            'ramdisk' : ramdisk,
+            'ramdisk_out' : ramdisk_out,
+            'ramdisk_addr' : 0xc0000,
+            'ramdisk_size' : filesize(ramdisk),
+            'ramdisk_load' : '',
+            'ramdisk_config' : '',
+
+            'loadables1' : loadables1,
+            'loadables1_out' : loadables1_out,
+            'loadables1_addr' : 0x100000,
+            'loadables1_size' : filesize(loadables1),
+            'loadables1_load' : '',
+
+            'loadables2' : loadables2,
+            'loadables2_out' : loadables2_out,
+            'loadables2_addr' : 0x140000,
+            'loadables2_size' : filesize(loadables2),
+            'loadables2_load' : '',
+
+            'loadables_config' : '',
+        }
+
+        # Make a basic FIT and a script to load it
+        fit = make_fit(mkimage, params)
+        params['fit'] = fit
+        cmd = base_script % params
+
+        # First check that we can load a kernel
+        # We could perhaps reduce duplication with some loss of readability
+        cons.config.dtb = control_dtb
+        cons.restart_uboot()
+        with cons.log.section('Kernel load'):
+            output = cons.run_command_list(cmd.splitlines())
+            check_equal(kernel, kernel_out, 'Kernel not loaded')
+            check_not_equal(control_dtb, fdt_out,
+                            'FDT loaded but should be ignored')
+            check_not_equal(ramdisk, ramdisk_out,
+                            'Ramdisk loaded but should not be')
+
+            # Find out the offset in the FIT where U-Boot has found the FDT
+            line = find_matching(output, 'Booting using the fdt blob at ')
+            fit_offset = int(line, 16) - params['fit_addr']
+            fdt_magic = struct.pack('>L', 0xd00dfeed)
+            data = read_file(fit)
+
+            # Now find where it actually is in the FIT (skip the first word)
+            real_fit_offset = data.find(fdt_magic, 4)
+            assert fit_offset == real_fit_offset, (
+                  'U-Boot loaded FDT from offset %#x, FDT is actually at %#x' %
+                  (fit_offset, real_fit_offset))
+
+        # Now a kernel and an FDT
+        with cons.log.section('Kernel + FDT load'):
+            params['fdt_load'] = 'load = <%#x>;' % params['fdt_addr']
+            fit = make_fit(mkimage, params)
+            cons.restart_uboot()
+            output = cons.run_command_list(cmd.splitlines())
+            check_equal(kernel, kernel_out, 'Kernel not loaded')
+            check_equal(control_dtb, fdt_out, 'FDT not loaded')
+            check_not_equal(ramdisk, ramdisk_out,
+                            'Ramdisk loaded but should not be')
+
+        # Try a ramdisk
+        with cons.log.section('Kernel + FDT + Ramdisk load'):
+            params['ramdisk_config'] = 'ramdisk = "ramdisk@1";'
+            params['ramdisk_load'] = 'load = <%#x>;' % params['ramdisk_addr']
+            fit = make_fit(mkimage, params)
+            cons.restart_uboot()
+            output = cons.run_command_list(cmd.splitlines())
+            check_equal(ramdisk, ramdisk_out, 'Ramdisk not loaded')
+
+        # Configuration with some Loadables
+        with cons.log.section('Kernel + FDT + Ramdisk load + Loadables'):
+            params['loadables_config'] = 'loadables = "kernel@2", "ramdisk@2";'
+            params['loadables1_load'] = ('load = <%#x>;' %
+                                         params['loadables1_addr'])
+            params['loadables2_load'] = ('load = <%#x>;' %
+                                         params['loadables2_addr'])
+            fit = make_fit(mkimage, params)
+            cons.restart_uboot()
+            output = cons.run_command_list(cmd.splitlines())
+            check_equal(loadables1, loadables1_out,
+                        'Loadables1 (kernel) not loaded')
+            check_equal(loadables2, loadables2_out,
+                        'Loadables2 (ramdisk) not loaded')
+
+    cons = u_boot_console
+    try:
+        # We need to use our own device tree file. Remember to restore it
+        # afterwards.
+        old_dtb = cons.config.dtb
+        mkimage = cons.config.build_dir + '/tools/mkimage'
+        run_fit_test(mkimage)
+    finally:
+        # Go back to the original U-Boot with the correct dtb.
+        cons.config.dtb = old_dtb
+        cons.restart_uboot()