diff options
author | Tom Rini <trini@konsulko.com> | 2017-02-23 10:12:41 -0500 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2017-02-23 10:12:41 -0500 |
commit | d38de7cb03adf88e18c05d840c2528b7a5af2f9b (patch) | |
tree | 35be69932e53e4c58260af58ae841a3d1a2523b6 | |
parent | b24cf8540a85a9bf97975aadd6a7542f166c78a3 (diff) | |
parent | bc647958047cd03193e19cd8c08a6771fea828b7 (diff) |
Merge branch 'master' of git://git.denx.de/u-boot-uniphier
- Fix regressions caused by the previous reworks
- Add pin configuration support
- Re-work SPL code
- Update DRAM and PLL setup code
- Enable needed configs, disable unneeded configs
54 files changed, 948 insertions, 659 deletions
diff --git a/arch/arm/dts/uniphier-ld11-ref.dts b/arch/arm/dts/uniphier-ld11-ref.dts index ea11198976..7693bf2736 100644 --- a/arch/arm/dts/uniphier-ld11-ref.dts +++ b/arch/arm/dts/uniphier-ld11-ref.dts @@ -71,7 +71,3 @@ &pinctrl_uart0 { u-boot,dm-pre-reloc; }; - -&pinctrl_system_bus { - u-boot,dm-pre-reloc; -}; diff --git a/arch/arm/dts/uniphier-ld20-ref.dts b/arch/arm/dts/uniphier-ld20-ref.dts index 044e000749..41ee07ebab 100644 --- a/arch/arm/dts/uniphier-ld20-ref.dts +++ b/arch/arm/dts/uniphier-ld20-ref.dts @@ -59,7 +59,3 @@ &pinctrl_uart0 { u-boot,dm-pre-reloc; }; - -&pinctrl_system_bus { - u-boot,dm-pre-reloc; -}; diff --git a/arch/arm/mach-uniphier/Makefile b/arch/arm/mach-uniphier/Makefile index 166b41f217..124a1c6e98 100644 --- a/arch/arm/mach-uniphier/Makefile +++ b/arch/arm/mach-uniphier/Makefile @@ -8,6 +8,7 @@ obj-y += boards.o obj-y += spl_board_init.o obj-y += memconf.o obj-y += bcu/ +obj-$(CONFIG_SPL_MMC_SUPPORT) += mmc-boot-mode.o else @@ -19,11 +20,12 @@ obj-y += reset.o obj-$(CONFIG_MICRO_SUPPORT_CARD) += sbc/ micro-support-card.o obj-y += pinctrl-glue.o +obj-$(CONFIG_MMC) += mmc-first-dev.o endif obj-y += soc-info.o -obj-y += boot-mode/ +obj-y += boot-device/ obj-y += clk/ obj-y += dram/ diff --git a/arch/arm/mach-uniphier/bcu/bcu-ld4.c b/arch/arm/mach-uniphier/bcu/bcu-ld4.c index 75578806f0..a16b24e7e5 100644 --- a/arch/arm/mach-uniphier/bcu/bcu-ld4.c +++ b/arch/arm/mach-uniphier/bcu/bcu-ld4.c @@ -24,7 +24,7 @@ void uniphier_ld4_bcu_init(const struct uniphier_board_data *bd) writel(0x11111111, BCSCR5); /* 0xe0000000-0Xffffffff: IPPC/IPPD-bus */ /* Specify DDR channel */ - shift = (bd->dram_ch[1].base - bd->dram_ch[0].base) / 0x04000000 * 4; + shift = bd->dram_ch[0].size / 0x04000000 * 4; writel(ch(shift), BCIPPCCHR2); /* 0x80000000-0x9fffffff */ shift -= 32; diff --git a/arch/arm/mach-uniphier/bcu/bcu-sld3.c b/arch/arm/mach-uniphier/bcu/bcu-sld3.c index 64efd37657..99b318fd8f 100644 --- a/arch/arm/mach-uniphier/bcu/bcu-sld3.c +++ b/arch/arm/mach-uniphier/bcu/bcu-sld3.c @@ -28,7 +28,7 @@ void uniphier_sld3_bcu_init(const struct uniphier_board_data *bd) writel(0x24440000, BCSCR5); /* Specify DDR channel */ - shift = (bd->dram_ch[1].base - bd->dram_ch[0].base) / 0x04000000 * 4; + shift = bd->dram_ch[0].size / 0x04000000 * 4; writel(ch(shift), BCIPPCCHR2); /* 0x80000000-0x9fffffff */ shift -= 32; diff --git a/arch/arm/mach-uniphier/board_init.c b/arch/arm/mach-uniphier/board_init.c index e89a4c59e2..2564a02a62 100644 --- a/arch/arm/mach-uniphier/board_init.c +++ b/arch/arm/mach-uniphier/board_init.c @@ -165,6 +165,7 @@ static const struct uniphier_initdata uniphier_initdata[] = { .nand_2cs = false, .sbc_init = uniphier_ld11_sbc_init, .pll_init = uniphier_ld20_pll_init, + .clk_init = uniphier_ld20_clk_init, .misc_init = uniphier_ld20_misc_init, }, #endif diff --git a/arch/arm/mach-uniphier/board_late_init.c b/arch/arm/mach-uniphier/board_late_init.c index ece761fb94..92dd6105e4 100644 --- a/arch/arm/mach-uniphier/board_late_init.c +++ b/arch/arm/mach-uniphier/board_late_init.c @@ -13,7 +13,7 @@ #include <linux/io.h> #include <../drivers/mtd/nand/denali.h> -#include "boot-mode/boot-device.h" +#include "init.h" static void nand_denali_wp_disable(void) { @@ -62,7 +62,7 @@ int board_late_init(void) { puts("MODE: "); - switch (spl_boot_device_raw()) { + switch (uniphier_boot_device_raw()) { case BOOT_DEVICE_MMC1: printf("eMMC Boot\n"); setenv("bootmode", "emmcboot"); diff --git a/arch/arm/mach-uniphier/boards.c b/arch/arm/mach-uniphier/boards.c index 059645171a..db7d192d68 100644 --- a/arch/arm/mach-uniphier/boards.c +++ b/arch/arm/mach-uniphier/boards.c @@ -16,36 +16,30 @@ DECLARE_GLOBAL_DATA_PTR; #if defined(CONFIG_ARCH_UNIPHIER_SLD3) static const struct uniphier_board_data uniphier_sld3_data = { .dram_freq = 1600, - .dram_nr_ch = 3, .dram_ch[0] = { - .base = 0x80000000, .size = 0x20000000, .width = 32, }, .dram_ch[1] = { - .base = 0xc0000000, .size = 0x20000000, .width = 16, }, .dram_ch[2] = { - .base = 0xc0000000, .size = 0x10000000, .width = 16, }, + .flags = UNIPHIER_BD_DRAM_SPARSE, }; #endif #if defined(CONFIG_ARCH_UNIPHIER_LD4) static const struct uniphier_board_data uniphier_ld4_data = { .dram_freq = 1600, - .dram_nr_ch = 2, .dram_ch[0] = { - .base = 0x80000000, .size = 0x10000000, .width = 16, }, .dram_ch[1] = { - .base = 0x90000000, .size = 0x10000000, .width = 16, }, @@ -57,14 +51,11 @@ static const struct uniphier_board_data uniphier_ld4_data = { /* 1GB RAM board */ static const struct uniphier_board_data uniphier_pro4_data = { .dram_freq = 1600, - .dram_nr_ch = 2, .dram_ch[0] = { - .base = 0x80000000, .size = 0x20000000, .width = 32, }, .dram_ch[1] = { - .base = 0xa0000000, .size = 0x20000000, .width = 32, }, @@ -73,14 +64,11 @@ static const struct uniphier_board_data uniphier_pro4_data = { /* 2GB RAM board */ static const struct uniphier_board_data uniphier_pro4_2g_data = { .dram_freq = 1600, - .dram_nr_ch = 2, .dram_ch[0] = { - .base = 0x80000000, .size = 0x40000000, .width = 32, }, .dram_ch[1] = { - .base = 0xc0000000, .size = 0x40000000, .width = 32, }, @@ -90,14 +78,11 @@ static const struct uniphier_board_data uniphier_pro4_2g_data = { #if defined(CONFIG_ARCH_UNIPHIER_SLD8) static const struct uniphier_board_data uniphier_sld8_data = { .dram_freq = 1333, - .dram_nr_ch = 2, .dram_ch[0] = { - .base = 0x80000000, .size = 0x10000000, .width = 16, }, .dram_ch[1] = { - .base = 0x90000000, .size = 0x10000000, .width = 16, }, @@ -108,14 +93,11 @@ static const struct uniphier_board_data uniphier_sld8_data = { #if defined(CONFIG_ARCH_UNIPHIER_PRO5) static const struct uniphier_board_data uniphier_pro5_data = { .dram_freq = 1866, - .dram_nr_ch = 2, .dram_ch[0] = { - .base = 0x80000000, .size = 0x20000000, .width = 32, }, .dram_ch[1] = { - .base = 0xa0000000, .size = 0x20000000, .width = 32, }, @@ -125,19 +107,15 @@ static const struct uniphier_board_data uniphier_pro5_data = { #if defined(CONFIG_ARCH_UNIPHIER_PXS2) static const struct uniphier_board_data uniphier_pxs2_data = { .dram_freq = 2133, - .dram_nr_ch = 3, .dram_ch[0] = { - .base = 0x80000000, .size = 0x40000000, .width = 32, }, .dram_ch[1] = { - .base = 0xc0000000, .size = 0x20000000, .width = 32, }, .dram_ch[2] = { - .base = 0xe0000000, .size = 0x20000000, .width = 16, }, @@ -147,19 +125,15 @@ static const struct uniphier_board_data uniphier_pxs2_data = { #if defined(CONFIG_ARCH_UNIPHIER_LD6B) static const struct uniphier_board_data uniphier_ld6b_data = { .dram_freq = 1866, - .dram_nr_ch = 3, .dram_ch[0] = { - .base = 0x80000000, .size = 0x40000000, .width = 32, }, .dram_ch[1] = { - .base = 0xc0000000, .size = 0x20000000, .width = 32, }, .dram_ch[2] = { - .base = 0xe0000000, .size = 0x20000000, .width = 16, }, @@ -169,14 +143,11 @@ static const struct uniphier_board_data uniphier_ld6b_data = { #if defined(CONFIG_ARCH_UNIPHIER_LD11) static const struct uniphier_board_data uniphier_ld11_data = { .dram_freq = 1600, - .dram_nr_ch = 2, .dram_ch[0] = { - .base = 0x80000000, .size = 0x20000000, .width = 16, }, .dram_ch[1] = { - .base = 0xa0000000, .size = 0x20000000, .width = 16, }, @@ -186,19 +157,15 @@ static const struct uniphier_board_data uniphier_ld11_data = { #if defined(CONFIG_ARCH_UNIPHIER_LD20) static const struct uniphier_board_data uniphier_ld20_ref_data = { .dram_freq = 1866, - .dram_nr_ch = 3, .dram_ch[0] = { - .base = 0x80000000, .size = 0x40000000, .width = 32, }, .dram_ch[1] = { - .base = 0xc0000000, .size = 0x40000000, .width = 32, }, .dram_ch[2] = { - .base = 0x100000000UL, .size = 0x40000000, .width = 32, }, @@ -207,19 +174,15 @@ static const struct uniphier_board_data uniphier_ld20_ref_data = { static const struct uniphier_board_data uniphier_ld20_data = { .dram_freq = 1866, - .dram_nr_ch = 3, .dram_ch[0] = { - .base = 0x80000000, .size = 0x40000000, .width = 32, }, .dram_ch[1] = { - .base = 0xc0000000, .size = 0x40000000, .width = 32, }, .dram_ch[2] = { - .base = 0x100000000UL, .size = 0x40000000, .width = 32, }, @@ -228,14 +191,11 @@ static const struct uniphier_board_data uniphier_ld20_data = { static const struct uniphier_board_data uniphier_ld21_data = { .dram_freq = 1866, - .dram_nr_ch = 2, .dram_ch[0] = { - .base = 0x80000000, .size = 0x20000000, .width = 32, }, .dram_ch[1] = { - .base = 0xc0000000, .size = 0x40000000, .width = 32, }, diff --git a/arch/arm/mach-uniphier/boot-device/Makefile b/arch/arm/mach-uniphier/boot-device/Makefile new file mode 100644 index 0000000000..a54d2acb10 --- /dev/null +++ b/arch/arm/mach-uniphier/boot-device/Makefile @@ -0,0 +1,19 @@ +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += boot-device.o + +obj-$(CONFIG_ARCH_UNIPHIER_SLD3) += boot-device-sld3.o +obj-$(CONFIG_ARCH_UNIPHIER_LD4) += boot-device-ld4.o +obj-$(CONFIG_ARCH_UNIPHIER_PRO4) += boot-device-ld4.o +obj-$(CONFIG_ARCH_UNIPHIER_SLD8) += boot-device-ld4.o +obj-$(CONFIG_ARCH_UNIPHIER_PRO5) += boot-device-pro5.o +obj-$(CONFIG_ARCH_UNIPHIER_PXS2) += boot-device-pxs2.o +obj-$(CONFIG_ARCH_UNIPHIER_LD6B) += boot-device-pxs2.o +obj-$(CONFIG_ARCH_UNIPHIER_LD11) += boot-device-ld11.o +obj-$(CONFIG_ARCH_UNIPHIER_LD20) += boot-device-ld11.o + +ifdef CONFIG_SPL_BUILD +obj-$(CONFIG_SPL_BOARD_LOAD_IMAGE) += spl_board.o +endif diff --git a/arch/arm/mach-uniphier/boot-mode/boot-mode-ld20.c b/arch/arm/mach-uniphier/boot-device/boot-device-ld11.c index 2992fd757f..f1a467c831 100644 --- a/arch/arm/mach-uniphier/boot-mode/boot-mode-ld20.c +++ b/arch/arm/mach-uniphier/boot-device/boot-device-ld11.c @@ -8,12 +8,11 @@ #include <common.h> #include <spl.h> #include <linux/io.h> +#include <linux/kernel.h> -#include "../sg-regs.h" -#include "../soc-info.h" #include "boot-device.h" -static struct boot_device_info boot_device_table[] = { +const struct uniphier_boot_device uniphier_ld11_boot_device_table[] = { {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 8, EraseSize 128KB, Addr 4)"}, {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 16, EraseSize 128KB, Addr 4)"}, {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 8, EraseSize 128KB, Addr 5)"}, @@ -48,48 +47,23 @@ static struct boot_device_info boot_device_table[] = { {BOOT_DEVICE_NOR, "NOR (XECS1)"}, }; -static int get_boot_mode_sel(void) +const unsigned uniphier_ld11_boot_device_count = + ARRAY_SIZE(uniphier_ld11_boot_device_table); + +int uniphier_ld11_boot_device_is_usb(u32 pinmon) { - return (readl(SG_PINMON0) >> 1) & 0x1f; + return !!(~pinmon & 0x00000080); } -u32 uniphier_ld20_boot_device(void) +int uniphier_ld20_boot_device_is_usb(u32 pinmon) { - int boot_mode; - u32 usb_boot_mask; - - switch (uniphier_get_soc_id()) { -#if defined(CONFIG_ARCH_UNIPHIER_LD11) - case UNIPHIER_LD11_ID: - usb_boot_mask = 0x00000080; - break; -#endif -#if defined(CONFIG_ARCH_UNIPHIER_LD20) - case UNIPHIER_LD20_ID: - usb_boot_mask = 0x00000780; - break; -#endif - default: - BUG(); - } - - if (~readl(SG_PINMON0) & usb_boot_mask) - return BOOT_DEVICE_USB; - - boot_mode = get_boot_mode_sel(); - - return boot_device_table[boot_mode].type; + return !!(~pinmon & 0x00000780); } -void uniphier_ld20_boot_mode_show(void) +unsigned int uniphier_ld11_boot_device_fixup(unsigned int mode) { - int mode_sel, i; - - mode_sel = get_boot_mode_sel(); - - puts("Boot Mode Pin:\n"); + if (mode == BOOT_DEVICE_MMC1 || mode == BOOT_DEVICE_USB) + mode = BOOT_DEVICE_BOARD; - for (i = 0; i < ARRAY_SIZE(boot_device_table); i++) - printf(" %c %02x %s\n", i == mode_sel ? '*' : ' ', i, - boot_device_table[i].info); + return mode; } diff --git a/arch/arm/mach-uniphier/boot-mode/boot-mode-ld4.c b/arch/arm/mach-uniphier/boot-device/boot-device-ld4.c index b066ed9c4b..b5d23210b1 100644 --- a/arch/arm/mach-uniphier/boot-mode/boot-mode-ld4.c +++ b/arch/arm/mach-uniphier/boot-device/boot-device-ld4.c @@ -1,5 +1,7 @@ /* - * Copyright (C) 2014-2015 Masahiro Yamada <yamada.masahiro@socionext.com> + * Copyright (C) 2014 Panasonic Corporation + * Copyright (C) 2015-2017 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> * * SPDX-License-Identifier: GPL-2.0+ */ @@ -7,11 +9,11 @@ #include <common.h> #include <spl.h> #include <linux/io.h> +#include <linux/kernel.h> -#include "../sg-regs.h" #include "boot-device.h" -struct boot_device_info boot_device_table[] = { +const struct uniphier_boot_device uniphier_ld4_boot_device_table[] = { {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 8, EraseSize 128KB, Addr 4)"}, {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 8, EraseSize 128KB, Addr 5)"}, {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 16, EraseSize 128KB, Addr 5)"}, @@ -46,29 +48,5 @@ struct boot_device_info boot_device_table[] = { {BOOT_DEVICE_NOR, "NOR (XECS0)"}, }; -static int get_boot_mode_sel(void) -{ - return (readl(SG_PINMON0) >> 1) & 0x1f; -} - -u32 uniphier_ld4_boot_device(void) -{ - int boot_mode; - - boot_mode = get_boot_mode_sel(); - - return boot_device_table[boot_mode].type; -} - -void uniphier_ld4_boot_mode_show(void) -{ - int mode_sel, i; - - mode_sel = get_boot_mode_sel(); - - puts("Boot Mode Pin:\n"); - - for (i = 0; i < ARRAY_SIZE(boot_device_table); i++) - printf(" %c %02x %s\n", i == mode_sel ? '*' : ' ', i, - boot_device_table[i].info); -} +const unsigned uniphier_ld4_boot_device_count = + ARRAY_SIZE(uniphier_ld4_boot_device_table); diff --git a/arch/arm/mach-uniphier/boot-mode/boot-mode-pro5.c b/arch/arm/mach-uniphier/boot-device/boot-device-pro5.c index 450c43bba5..47221ee61d 100644 --- a/arch/arm/mach-uniphier/boot-mode/boot-mode-pro5.c +++ b/arch/arm/mach-uniphier/boot-device/boot-device-pro5.c @@ -1,5 +1,6 @@ /* - * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com> + * Copyright (C) 2015-2017 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> * * SPDX-License-Identifier: GPL-2.0+ */ @@ -7,11 +8,11 @@ #include <common.h> #include <spl.h> #include <linux/io.h> +#include <linux/kernel.h> -#include "../sg-regs.h" #include "boot-device.h" -static struct boot_device_info boot_device_table[] = { +const struct uniphier_boot_device uniphier_pro5_boot_device_table[] = { {BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC 8, EraseSize 128KB, Addr 5)"}, {BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC 16, EraseSize 128KB, Addr 5)"}, {BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC 8, EraseSize 256KB, Addr 5)"}, @@ -44,32 +45,7 @@ static struct boot_device_info boot_device_table[] = { {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 16, EraseSize 128KB, Addr 5)"}, {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 8, EraseSize 256KB, Addr 5)"}, {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 16, EraseSize 256KB, Addr 5)"}, - { /* sentinel */ } }; -static int get_boot_mode_sel(void) -{ - return (readl(SG_PINMON0) >> 1) & 0x1f; -} - -u32 uniphier_pro5_boot_device(void) -{ - int boot_mode; - - boot_mode = get_boot_mode_sel(); - - return boot_device_table[boot_mode].type; -} - -void uniphier_pro5_boot_mode_show(void) -{ - int mode_sel, i; - - mode_sel = get_boot_mode_sel(); - - puts("Boot Mode Pin:\n"); - - for (i = 0; i < ARRAY_SIZE(boot_device_table); i++) - printf(" %c %02x %s\n", i == mode_sel ? '*' : ' ', i, - boot_device_table[i].info); -} +const unsigned uniphier_pro5_boot_device_count = + ARRAY_SIZE(uniphier_pro5_boot_device_table); diff --git a/arch/arm/mach-uniphier/boot-mode/boot-mode-pxs2.c b/arch/arm/mach-uniphier/boot-device/boot-device-pxs2.c index 20ff7731d5..20a9511549 100644 --- a/arch/arm/mach-uniphier/boot-mode/boot-mode-pxs2.c +++ b/arch/arm/mach-uniphier/boot-device/boot-device-pxs2.c @@ -1,5 +1,6 @@ /* - * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com> + * Copyright (C) 2015-2017 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> * * SPDX-License-Identifier: GPL-2.0+ */ @@ -7,11 +8,11 @@ #include <common.h> #include <spl.h> #include <linux/io.h> +#include <linux/kernel.h> -#include "../sg-regs.h" #include "boot-device.h" -static struct boot_device_info boot_device_table[] = { +const struct uniphier_boot_device uniphier_pxs2_boot_device_table[] = { {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 8, EraseSize 128KB, Addr 4)"}, {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 8, EraseSize 128KB, Addr 5)"}, {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 16, EraseSize 128KB, Addr 5)"}, @@ -46,32 +47,18 @@ static struct boot_device_info boot_device_table[] = { {BOOT_DEVICE_NONE, "Reserved"}, }; -static int get_boot_mode_sel(void) -{ - return (readl(SG_PINMON0) >> 1) & 0x1f; -} +const unsigned uniphier_pxs2_boot_device_count = + ARRAY_SIZE(uniphier_pxs2_boot_device_table); -u32 uniphier_pxs2_boot_device(void) +int uniphier_pxs2_boot_device_is_usb(u32 pinmon) { - int boot_mode; - - if (readl(SG_PINMON0) & BIT(6)) - return BOOT_DEVICE_USB; - - boot_mode = get_boot_mode_sel(); - - return boot_device_table[boot_mode].type; + return !!(pinmon & 0x00000040); } -void uniphier_pxs2_boot_mode_show(void) +unsigned int uniphier_pxs2_boot_device_fixup(unsigned int mode) { - int mode_sel, i; - - mode_sel = get_boot_mode_sel(); - - puts("Boot Mode Pin:\n"); + if (mode == BOOT_DEVICE_USB) + return BOOT_DEVICE_NOR; - for (i = 0; i < ARRAY_SIZE(boot_device_table); i++) - printf(" %c %02x %s\n", i == mode_sel ? '*' : ' ', i, - boot_device_table[i].info); + return mode; } diff --git a/arch/arm/mach-uniphier/boot-mode/boot-mode-sld3.c b/arch/arm/mach-uniphier/boot-device/boot-device-sld3.c index ddf8259c2c..2b36494f73 100644 --- a/arch/arm/mach-uniphier/boot-mode/boot-mode-sld3.c +++ b/arch/arm/mach-uniphier/boot-device/boot-device-sld3.c @@ -1,5 +1,7 @@ /* - * Copyright (C) 2014-2015 Masahiro Yamada <yamada.masahiro@socionext.com> + * Copyright (C) 2014 Panasonic Corporation + * Copyright (C) 2015-2017 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> * * SPDX-License-Identifier: GPL-2.0+ */ @@ -7,11 +9,11 @@ #include <common.h> #include <spl.h> #include <linux/io.h> +#include <linux/kernel.h> -#include "../sg-regs.h" #include "boot-device.h" -static struct boot_device_info boot_device_table[] = { +const struct uniphier_boot_device uniphier_sld3_boot_device_table[] = { {BOOT_DEVICE_NOR, "NOR (XECS0)"}, {BOOT_DEVICE_NONE, "External Master"}, {BOOT_DEVICE_NONE, "Reserved"}, @@ -78,29 +80,5 @@ static struct boot_device_info boot_device_table[] = { {BOOT_DEVICE_NONE, "Reserved"}, }; -static int get_boot_mode_sel(void) -{ - return readl(SG_PINMON0) & 0x3f; -} - -u32 uniphier_sld3_boot_device(void) -{ - int boot_mode; - - boot_mode = get_boot_mode_sel(); - - return boot_device_table[boot_mode].type; -} - -void uniphier_sld3_boot_mode_show(void) -{ - int mode_sel, i; - - mode_sel = get_boot_mode_sel(); - - puts("Boot Mode Pin:\n"); - - for (i = 0; i < ARRAY_SIZE(boot_device_table); i++) - printf(" %c %02x %s\n", i == mode_sel ? '*' : ' ', i, - boot_device_table[i].info); -} +const unsigned uniphier_sld3_boot_device_count = + ARRAY_SIZE(uniphier_sld3_boot_device_table); diff --git a/arch/arm/mach-uniphier/boot-device/boot-device.c b/arch/arm/mach-uniphier/boot-device/boot-device.c new file mode 100644 index 0000000000..5ec0b5b87c --- /dev/null +++ b/arch/arm/mach-uniphier/boot-device/boot-device.c @@ -0,0 +1,206 @@ +/* + * Copyright (C) 2015-2017 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <spl.h> +#include <linux/log2.h> + +#include "../init.h" +#include "../sbc/sbc-regs.h" +#include "../sg-regs.h" +#include "../soc-info.h" +#include "boot-device.h" + +struct uniphier_boot_device_info { + unsigned int soc_id; + unsigned int boot_device_sel_shift; + const struct uniphier_boot_device *boot_device_table; + const unsigned int *boot_device_count; + int (*boot_device_is_usb)(u32 pinmon); + unsigned int (*boot_device_fixup)(unsigned int mode); +}; + +static const struct uniphier_boot_device_info uniphier_boot_device_info[] = { +#if defined(CONFIG_ARCH_UNIPHIER_SLD3) + { + .soc_id = UNIPHIER_SLD3_ID, + .boot_device_sel_shift = 0, + .boot_device_table = uniphier_sld3_boot_device_table, + .boot_device_count = &uniphier_sld3_boot_device_count, + }, +#endif +#if defined(CONFIG_ARCH_UNIPHIER_LD4) + { + .soc_id = UNIPHIER_LD4_ID, + .boot_device_sel_shift = 1, + .boot_device_table = uniphier_ld4_boot_device_table, + .boot_device_count = &uniphier_ld4_boot_device_count, + }, +#endif +#if defined(CONFIG_ARCH_UNIPHIER_PRO4) + { + .soc_id = UNIPHIER_PRO4_ID, + .boot_device_sel_shift = 1, + .boot_device_table = uniphier_ld4_boot_device_table, + .boot_device_count = &uniphier_ld4_boot_device_count, + }, +#endif +#if defined(CONFIG_ARCH_UNIPHIER_SLD8) + { + .soc_id = UNIPHIER_SLD8_ID, + .boot_device_sel_shift = 1, + .boot_device_table = uniphier_ld4_boot_device_table, + .boot_device_count = &uniphier_ld4_boot_device_count, + }, +#endif +#if defined(CONFIG_ARCH_UNIPHIER_PRO5) + { + .soc_id = UNIPHIER_PRO5_ID, + .boot_device_sel_shift = 1, + .boot_device_table = uniphier_pro5_boot_device_table, + .boot_device_count = &uniphier_pro5_boot_device_count, + }, +#endif +#if defined(CONFIG_ARCH_UNIPHIER_PXS2) + { + .soc_id = UNIPHIER_PXS2_ID, + .boot_device_sel_shift = 1, + .boot_device_table = uniphier_pxs2_boot_device_table, + .boot_device_count = &uniphier_pxs2_boot_device_count, + .boot_device_is_usb = uniphier_pxs2_boot_device_is_usb, + .boot_device_fixup = uniphier_pxs2_boot_device_fixup, + }, +#endif +#if defined(CONFIG_ARCH_UNIPHIER_LD6B) + { + .soc_id = UNIPHIER_LD6B_ID, + .boot_device_sel_shift = 1, + .boot_device_table = uniphier_pxs2_boot_device_table, + .boot_device_count = &uniphier_pxs2_boot_device_count, + .boot_device_is_usb = uniphier_pxs2_boot_device_is_usb, + .boot_device_fixup = uniphier_pxs2_boot_device_fixup, + }, +#endif +#if defined(CONFIG_ARCH_UNIPHIER_LD11) + { + .soc_id = UNIPHIER_LD11_ID, + .boot_device_sel_shift = 1, + .boot_device_table = uniphier_ld11_boot_device_table, + .boot_device_count = &uniphier_ld11_boot_device_count, + .boot_device_is_usb = uniphier_ld11_boot_device_is_usb, + .boot_device_fixup = uniphier_ld11_boot_device_fixup, + }, +#endif +#if defined(CONFIG_ARCH_UNIPHIER_LD20) + { + .soc_id = UNIPHIER_LD20_ID, + .boot_device_sel_shift = 1, + .boot_device_table = uniphier_ld11_boot_device_table, + .boot_device_count = &uniphier_ld11_boot_device_count, + .boot_device_is_usb = uniphier_ld20_boot_device_is_usb, + .boot_device_fixup = uniphier_ld11_boot_device_fixup, + }, +#endif +}; +UNIPHIER_DEFINE_SOCDATA_FUNC(uniphier_get_boot_device_info, + uniphier_boot_device_info) + +static unsigned int __uniphier_boot_device_raw( + const struct uniphier_boot_device_info *info) +{ + u32 pinmon; + unsigned int boot_sel; + + if (boot_is_swapped()) + return BOOT_DEVICE_NOR; + + pinmon = readl(SG_PINMON0); + + if (info->boot_device_is_usb && info->boot_device_is_usb(pinmon)) + return BOOT_DEVICE_USB; + + boot_sel = pinmon >> info->boot_device_sel_shift; + + BUG_ON(!is_power_of_2(*info->boot_device_count)); + boot_sel &= *info->boot_device_count - 1; + + return info->boot_device_table[boot_sel].boot_device; +} + +unsigned int uniphier_boot_device_raw(void) +{ + const struct uniphier_boot_device_info *info; + + info = uniphier_get_boot_device_info(); + if (!info) { + pr_err("unsupported SoC\n"); + return BOOT_DEVICE_NONE; + } + + return __uniphier_boot_device_raw(info); +} + +u32 spl_boot_device(void) +{ + const struct uniphier_boot_device_info *info; + u32 raw_mode; + + info = uniphier_get_boot_device_info(); + if (!info) { + pr_err("unsupported SoC\n"); + return BOOT_DEVICE_NONE; + } + + raw_mode = __uniphier_boot_device_raw(info); + + return info->boot_device_fixup ? + info->boot_device_fixup(raw_mode) : raw_mode; +} + +#ifndef CONFIG_SPL_BUILD + +static int do_pinmon(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + const struct uniphier_boot_device_info *info; + u32 pinmon; + unsigned int boot_device_count, boot_sel; + int i; + + info = uniphier_get_boot_device_info(); + if (!info) { + pr_err("unsupported SoC\n"); + return CMD_RET_FAILURE; + } + + printf("Boot Swap: %s\n\n", boot_is_swapped() ? "ON" : "OFF"); + + pinmon = readl(SG_PINMON0); + + if (info->boot_device_is_usb) + printf("USB Boot: %s\n\n", + info->boot_device_is_usb(pinmon) ? "ON" : "OFF"); + + boot_device_count = *info->boot_device_count; + + boot_sel = pinmon >> info->boot_device_sel_shift; + boot_sel &= boot_device_count - 1; + + printf("Boot Mode Sel:\n"); + for (i = 0; i < boot_device_count; i++) + printf(" %c %02x %s\n", i == boot_sel ? '*' : ' ', i, + info->boot_device_table[i].desc); + + return CMD_RET_SUCCESS; +} + +U_BOOT_CMD( + pinmon, 1, 1, do_pinmon, + "pin monitor", + "" +); + +#endif /* !CONFIG_SPL_BUILD */ diff --git a/arch/arm/mach-uniphier/boot-device/boot-device.h b/arch/arm/mach-uniphier/boot-device/boot-device.h new file mode 100644 index 0000000000..f3fb2f32a8 --- /dev/null +++ b/arch/arm/mach-uniphier/boot-device/boot-device.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2017 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _UNIPHIER_BOOT_DEVICE_H_ +#define _UNIPHIER_BOOT_DEVICE_H_ + +struct uniphier_boot_device { + unsigned int boot_device; + const char *desc; +}; + +extern const struct uniphier_boot_device uniphier_sld3_boot_device_table[]; +extern const struct uniphier_boot_device uniphier_ld4_boot_device_table[]; +extern const struct uniphier_boot_device uniphier_pro5_boot_device_table[]; +extern const struct uniphier_boot_device uniphier_pxs2_boot_device_table[]; +extern const struct uniphier_boot_device uniphier_ld11_boot_device_table[]; + +extern const unsigned int uniphier_sld3_boot_device_count; +extern const unsigned int uniphier_ld4_boot_device_count; +extern const unsigned int uniphier_pro5_boot_device_count; +extern const unsigned int uniphier_pxs2_boot_device_count; +extern const unsigned int uniphier_ld11_boot_device_count; + +int uniphier_pxs2_boot_device_is_usb(u32 pinmon); +int uniphier_ld11_boot_device_is_usb(u32 pinmon); +int uniphier_ld20_boot_device_is_usb(u32 pinmon); + +unsigned int uniphier_pxs2_boot_device_fixup(unsigned int mode); +unsigned int uniphier_ld11_boot_device_fixup(unsigned int mode); + +#endif /* _UNIPHIER_BOOT_DEVICE_H_ */ diff --git a/arch/arm/mach-uniphier/boot-device/spl_board.c b/arch/arm/mach-uniphier/boot-device/spl_board.c new file mode 100644 index 0000000000..bd47ac874b --- /dev/null +++ b/arch/arm/mach-uniphier/boot-device/spl_board.c @@ -0,0 +1,262 @@ +/* + * Copyright (C) 2017 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <spl.h> +#include <linux/bitops.h> +#include <linux/compat.h> +#include <linux/io.h> +#include <asm/processor.h> + +#include "../soc-info.h" + +#define MMC_CMD_SWITCH 6 +#define MMC_CMD_SELECT_CARD 7 +#define MMC_CMD_SEND_CSD 9 +#define MMC_CMD_READ_MULTIPLE_BLOCK 18 + +#define EXT_CSD_PART_CONF 179 /* R/W */ + +#define MMC_RSP_PRESENT BIT(0) +#define MMC_RSP_136 BIT(1) /* 136 bit response */ +#define MMC_RSP_CRC BIT(2) /* expect valid crc */ +#define MMC_RSP_BUSY BIT(3) /* card may send busy */ +#define MMC_RSP_OPCODE BIT(4) /* response contains opcode */ + +#define MMC_RSP_NONE (0) +#define MMC_RSP_R1 (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE) +#define MMC_RSP_R1b (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE | \ + MMC_RSP_BUSY) +#define MMC_RSP_R2 (MMC_RSP_PRESENT | MMC_RSP_136 | MMC_RSP_CRC) +#define MMC_RSP_R3 (MMC_RSP_PRESENT) +#define MMC_RSP_R4 (MMC_RSP_PRESENT) +#define MMC_RSP_R5 (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE) +#define MMC_RSP_R6 (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE) +#define MMC_RSP_R7 (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE) + +#define SDHCI_DMA_ADDRESS 0x00 +#define SDHCI_BLOCK_SIZE 0x04 +#define SDHCI_MAKE_BLKSZ(dma, blksz) ((((dma) & 0x7) << 12) | ((blksz) & 0xFFF)) +#define SDHCI_BLOCK_COUNT 0x06 +#define SDHCI_ARGUMENT 0x08 +#define SDHCI_TRANSFER_MODE 0x0C +#define SDHCI_TRNS_DMA BIT(0) +#define SDHCI_TRNS_BLK_CNT_EN BIT(1) +#define SDHCI_TRNS_ACMD12 BIT(2) +#define SDHCI_TRNS_READ BIT(4) +#define SDHCI_TRNS_MULTI BIT(5) +#define SDHCI_COMMAND 0x0E +#define SDHCI_CMD_RESP_MASK 0x03 +#define SDHCI_CMD_CRC 0x08 +#define SDHCI_CMD_INDEX 0x10 +#define SDHCI_CMD_DATA 0x20 +#define SDHCI_CMD_ABORTCMD 0xC0 +#define SDHCI_CMD_RESP_NONE 0x00 +#define SDHCI_CMD_RESP_LONG 0x01 +#define SDHCI_CMD_RESP_SHORT 0x02 +#define SDHCI_CMD_RESP_SHORT_BUSY 0x03 +#define SDHCI_MAKE_CMD(c, f) ((((c) & 0xff) << 8) | ((f) & 0xff)) +#define SDHCI_RESPONSE 0x10 +#define SDHCI_HOST_CONTROL 0x28 +#define SDHCI_CTRL_DMA_MASK 0x18 +#define SDHCI_CTRL_SDMA 0x00 +#define SDHCI_BLOCK_GAP_CONTROL 0x2A +#define SDHCI_SOFTWARE_RESET 0x2F +#define SDHCI_RESET_CMD 0x02 +#define SDHCI_RESET_DATA 0x04 +#define SDHCI_INT_STATUS 0x30 +#define SDHCI_INT_RESPONSE BIT(0) +#define SDHCI_INT_DATA_END BIT(1) +#define SDHCI_INT_ERROR BIT(15) +#define SDHCI_SIGNAL_ENABLE 0x38 + +/* RCA assigned by Boot ROM */ +#define UNIPHIER_EMMC_RCA 0x1000 + +struct uniphier_mmc_cmd { + unsigned int cmdidx; + unsigned int resp_type; + unsigned int cmdarg; + unsigned int is_data; +}; + +static int uniphier_emmc_send_cmd(void __iomem *host_base, + struct uniphier_mmc_cmd *cmd) +{ + u32 mode = 0; + u32 mask = SDHCI_INT_RESPONSE; + u32 stat, flags; + + writel(U32_MAX, host_base + SDHCI_INT_STATUS); + writel(0, host_base + SDHCI_SIGNAL_ENABLE); + writel(cmd->cmdarg, host_base + SDHCI_ARGUMENT); + + if (cmd->is_data) + mode = SDHCI_TRNS_DMA | SDHCI_TRNS_BLK_CNT_EN | + SDHCI_TRNS_ACMD12 | SDHCI_TRNS_READ | + SDHCI_TRNS_MULTI; + + writew(mode, host_base + SDHCI_TRANSFER_MODE); + + if (!(cmd->resp_type & MMC_RSP_PRESENT)) + flags = SDHCI_CMD_RESP_NONE; + else if (cmd->resp_type & MMC_RSP_136) + flags = SDHCI_CMD_RESP_LONG; + else if (cmd->resp_type & MMC_RSP_BUSY) + flags = SDHCI_CMD_RESP_SHORT_BUSY; + else + flags = SDHCI_CMD_RESP_SHORT; + + if (cmd->resp_type & MMC_RSP_CRC) + flags |= SDHCI_CMD_CRC; + if (cmd->resp_type & MMC_RSP_OPCODE) + flags |= SDHCI_CMD_INDEX; + if (cmd->is_data) + flags |= SDHCI_CMD_DATA; + + if (cmd->resp_type & MMC_RSP_BUSY || cmd->is_data) + mask |= SDHCI_INT_DATA_END; + + writew(SDHCI_MAKE_CMD(cmd->cmdidx, flags), host_base + SDHCI_COMMAND); + + do { + stat = readl(host_base + SDHCI_INT_STATUS); + if (stat & SDHCI_INT_ERROR) + return -EIO; + + } while ((stat & mask) != mask); + + return 0; +} + +static int uniphier_emmc_switch_part(void __iomem *host_base, int part_num) +{ + struct uniphier_mmc_cmd cmd = {}; + + cmd.cmdidx = MMC_CMD_SWITCH; + cmd.resp_type = MMC_RSP_R1b; + cmd.cmdarg = (EXT_CSD_PART_CONF << 16) | (part_num << 8) | (3 << 24); + + return uniphier_emmc_send_cmd(host_base, &cmd); +} + +static int uniphier_emmc_is_over_2gb(void __iomem *host_base) +{ + struct uniphier_mmc_cmd cmd = {}; + u32 csd40, csd72; /* CSD[71:40], CSD[103:72] */ + int ret; + + cmd.cmdidx = MMC_CMD_SEND_CSD; + cmd.resp_type = MMC_RSP_R2; + cmd.cmdarg = UNIPHIER_EMMC_RCA << 16; + + ret = uniphier_emmc_send_cmd(host_base, &cmd); + if (ret) + return ret; + + csd40 = readl(host_base + SDHCI_RESPONSE + 4); + csd72 = readl(host_base + SDHCI_RESPONSE + 8); + + return !(~csd40 & 0xffc00380) && !(~csd72 & 0x3); +} + +static int uniphier_emmc_load_image(void __iomem *host_base, u32 dev_addr, + unsigned long load_addr, u32 block_cnt) +{ + struct uniphier_mmc_cmd cmd = {}; + u8 tmp; + + WARN_ON(load_addr >> 32); + + writel(load_addr, host_base + SDHCI_DMA_ADDRESS); + writew(SDHCI_MAKE_BLKSZ(7, 512), host_base + SDHCI_BLOCK_SIZE); + writew(block_cnt, host_base + SDHCI_BLOCK_COUNT); + + tmp = readb(host_base + SDHCI_HOST_CONTROL); + tmp &= ~SDHCI_CTRL_DMA_MASK; + tmp |= SDHCI_CTRL_SDMA; + writeb(tmp, host_base + SDHCI_HOST_CONTROL); + + tmp = readb(host_base + SDHCI_BLOCK_GAP_CONTROL); + tmp &= ~1; /* clear Stop At Block Gap Request */ + writeb(tmp, host_base + SDHCI_BLOCK_GAP_CONTROL); + + cmd.cmdidx = MMC_CMD_READ_MULTIPLE_BLOCK; + cmd.resp_type = MMC_RSP_R1; + cmd.cmdarg = dev_addr; + cmd.is_data = 1; + + return uniphier_emmc_send_cmd(host_base, &cmd); +} + +static int spl_board_load_image(struct spl_image_info *spl_image, + struct spl_boot_device *bootdev) +{ + u32 dev_addr = CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR; + void __iomem *host_base = (void __iomem *)0x5a000200; + struct uniphier_mmc_cmd cmd = {}; + int ret; + + /* + * deselect card before SEND_CSD command. + * Do not check the return code. It fails, but it is OK. + */ + cmd.cmdidx = MMC_CMD_SELECT_CARD; + cmd.resp_type = MMC_RSP_R1; + + uniphier_emmc_send_cmd(host_base, &cmd); /* CMD7 (arg=0) */ + + /* reset CMD Line */ + writeb(SDHCI_RESET_CMD | SDHCI_RESET_DATA, + host_base + SDHCI_SOFTWARE_RESET); + while (readb(host_base + SDHCI_SOFTWARE_RESET)) + cpu_relax(); + + ret = uniphier_emmc_is_over_2gb(host_base); + if (ret < 0) + return ret; + if (ret) { + debug("card is block addressing\n"); + } else { + debug("card is byte addressing\n"); + dev_addr *= 512; + } + + cmd.cmdarg = UNIPHIER_EMMC_RCA << 16; + + /* select card again */ + ret = uniphier_emmc_send_cmd(host_base, &cmd); + if (ret) + printf("failed to select card\n"); + + /* Switch to Boot Partition 1 */ + ret = uniphier_emmc_switch_part(host_base, 1); + if (ret) + printf("failed to switch partition\n"); + + ret = uniphier_emmc_load_image(host_base, dev_addr, + CONFIG_SYS_TEXT_BASE, 1); + if (ret) { + printf("failed to load image\n"); + return ret; + } + + ret = spl_parse_image_header(spl_image, (void *)CONFIG_SYS_TEXT_BASE); + if (ret) + return ret; + + ret = uniphier_emmc_load_image(host_base, dev_addr, + spl_image->load_addr, + spl_image->size / 512); + if (ret) { + printf("failed to load image\n"); + return ret; + } + + return 0; +} +SPL_LOAD_IMAGE_METHOD("eMMC", 0, BOOT_DEVICE_BOARD, spl_board_load_image); diff --git a/arch/arm/mach-uniphier/boot-mode/Makefile b/arch/arm/mach-uniphier/boot-mode/Makefile deleted file mode 100644 index a8980210b1..0000000000 --- a/arch/arm/mach-uniphier/boot-mode/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -# -# SPDX-License-Identifier: GPL-2.0+ -# - -obj-y += boot-mode.o - -obj-$(CONFIG_ARCH_UNIPHIER_SLD3) += boot-mode-sld3.o -obj-$(CONFIG_ARCH_UNIPHIER_LD4) += boot-mode-ld4.o -obj-$(CONFIG_ARCH_UNIPHIER_PRO4) += boot-mode-ld4.o -obj-$(CONFIG_ARCH_UNIPHIER_SLD8) += boot-mode-ld4.o -obj-$(CONFIG_ARCH_UNIPHIER_PRO5) += boot-mode-pro5.o -obj-$(CONFIG_ARCH_UNIPHIER_PXS2) += boot-mode-pxs2.o -obj-$(CONFIG_ARCH_UNIPHIER_LD6B) += boot-mode-pxs2.o -obj-$(CONFIG_ARCH_UNIPHIER_LD11) += boot-mode-ld20.o -obj-$(CONFIG_ARCH_UNIPHIER_LD20) += boot-mode-ld20.o - -ifdef CONFIG_SPL_BUILD -obj-$(CONFIG_SPL_BOARD_LOAD_IMAGE) += spl_board.o -else -obj-$(CONFIG_CMD_PINMON) += cmd_pinmon.o -endif diff --git a/arch/arm/mach-uniphier/boot-mode/boot-device.h b/arch/arm/mach-uniphier/boot-mode/boot-device.h deleted file mode 100644 index bd44d73416..0000000000 --- a/arch/arm/mach-uniphier/boot-mode/boot-device.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2011-2015 Masahiro Yamada <yamada.masahiro@socionext.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifndef _ASM_BOOT_DEVICE_H_ -#define _ASM_BOOT_DEVICE_H_ - -struct boot_device_info { - u32 type; - char *info; -}; - -u32 uniphier_sld3_boot_device(void); -u32 uniphier_ld4_boot_device(void); -u32 uniphier_pro5_boot_device(void); -u32 uniphier_pxs2_boot_device(void); -u32 uniphier_ld20_boot_device(void); - -void uniphier_sld3_boot_mode_show(void); -void uniphier_ld4_boot_mode_show(void); -void uniphier_pro5_boot_mode_show(void); -void uniphier_pxs2_boot_mode_show(void); -void uniphier_ld20_boot_mode_show(void); - -u32 spl_boot_device_raw(void); - -#endif /* _ASM_BOOT_DEVICE_H_ */ diff --git a/arch/arm/mach-uniphier/boot-mode/boot-mode.c b/arch/arm/mach-uniphier/boot-mode/boot-mode.c deleted file mode 100644 index a5527704df..0000000000 --- a/arch/arm/mach-uniphier/boot-mode/boot-mode.c +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <mmc.h> -#include <spl.h> -#include <linux/errno.h> - -#include "../sbc/sbc-regs.h" -#include "../soc-info.h" -#include "boot-device.h" - -u32 spl_boot_device_raw(void) -{ - if (boot_is_swapped()) - return BOOT_DEVICE_NOR; - - switch (uniphier_get_soc_id()) { -#if defined(CONFIG_ARCH_UNIPHIER_SLD3) - case UNIPHIER_SLD3_ID: - return uniphier_sld3_boot_device(); -#endif -#if defined(CONFIG_ARCH_UNIPHIER_LD4) || defined(CONFIG_ARCH_UNIPHIER_PRO4) || \ - defined(CONFIG_ARCH_UNIPHIER_SLD8) - case UNIPHIER_LD4_ID: - case UNIPHIER_PRO4_ID: - case UNIPHIER_SLD8_ID: - return uniphier_ld4_boot_device(); -#endif -#if defined(CONFIG_ARCH_UNIPHIER_PRO5) - case UNIPHIER_PRO5_ID: - return uniphier_pro5_boot_device(); -#endif -#if defined(CONFIG_ARCH_UNIPHIER_PXS2) || defined(CONFIG_ARCH_UNIPHIER_LD6B) - case UNIPHIER_PXS2_ID: - case UNIPHIER_LD6B_ID: - return uniphier_pxs2_boot_device(); -#endif -#if defined(CONFIG_ARCH_UNIPHIER_LD11) || defined(CONFIG_ARCH_UNIPHIER_LD20) - case UNIPHIER_LD11_ID: - case UNIPHIER_LD20_ID: - return uniphier_ld20_boot_device(); -#endif - default: - return BOOT_DEVICE_NONE; - } -} - -u32 spl_boot_device(void) -{ - u32 mode; - - mode = spl_boot_device_raw(); - - switch (uniphier_get_soc_id()) { -#if defined(CONFIG_ARCH_UNIPHIER_PXS2) || defined(CONFIG_ARCH_UNIPHIER_LD6B) - case UNIPHIER_PXS2_ID: - case UNIPHIER_LD6B_ID: - if (mode == BOOT_DEVICE_USB) - mode = BOOT_DEVICE_NOR; - break; -#endif -#if defined(CONFIG_ARCH_UNIPHIER_LD11) || defined(CONFIG_ARCH_UNIPHIER_LD20) - case UNIPHIER_LD11_ID: - case UNIPHIER_LD20_ID: - if (mode == BOOT_DEVICE_MMC1 || mode == BOOT_DEVICE_USB) - mode = BOOT_DEVICE_BOARD; - break; -#endif - default: - break; - } - - return mode; -} - -u32 spl_boot_mode(const u32 boot_device) -{ - struct mmc *mmc; - - /* - * work around a bug in the Boot ROM of PH1-sLD3, LD4, Pro4, and sLD8: - * - * The boot ROM in these SoCs breaks the PARTITION_CONFIG [179] of - * Extended CSD register; when switching to the Boot Partition 1, the - * Boot ROM should issue the SWITCH command (CMD6) with Set Bits for - * the Access Bits, but in fact it uses Write Byte for the Access Bits. - * As a result, the BOOT_PARTITION_ENABLE field of the PARTITION_CONFIG - * is lost. This bug was fixed for PH1-Pro5 and later SoCs. - * - * Fixup mmc->part_config here because it is used to determine the - * partition which the U-Boot image is read from. - */ - mmc = find_mmc_device(0); - mmc->part_config &= ~EXT_CSD_BOOT_PART_NUM(PART_ACCESS_MASK); - mmc->part_config |= EXT_CSD_BOOT_PARTITION_ENABLE; - - return MMCSD_MODE_EMMCBOOT; -} - -#if defined(CONFIG_DM_MMC) && !defined(CONFIG_SPL_BUILD) -static int find_first_mmc_device(void) -{ - struct mmc *mmc; - int i; - - for (i = 0; (mmc = find_mmc_device(i)); i++) { - if (!mmc_init(mmc) && IS_MMC(mmc)) - return i; - } - - return -ENODEV; -} - -int mmc_get_env_dev(void) -{ - return find_first_mmc_device(); -} - -static int do_mmcsetn(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - int dev; - - dev = find_first_mmc_device(); - if (dev < 0) - return CMD_RET_FAILURE; - - setenv_ulong("mmc_first_dev", dev); - return CMD_RET_SUCCESS; -} - -U_BOOT_CMD( - mmcsetn, 1, 1, do_mmcsetn, - "Set the first MMC (not SD) dev number to \"mmc_first_dev\" environment", - "" -); -#endif diff --git a/arch/arm/mach-uniphier/boot-mode/cmd_pinmon.c b/arch/arm/mach-uniphier/boot-mode/cmd_pinmon.c deleted file mode 100644 index 670d4f6bff..0000000000 --- a/arch/arm/mach-uniphier/boot-mode/cmd_pinmon.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2014-2015 Masahiro Yamada <yamada.masahiro@socionext.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> - -#include "../sbc/sbc-regs.h" -#include "../soc-info.h" -#include "boot-device.h" - -static int do_pinmon(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - printf("Boot Swap: %s\n\n", boot_is_swapped() ? "ON" : "OFF"); - - switch (uniphier_get_soc_id()) { -#if defined(CONFIG_ARCH_UNIPHIER_SLD3) - case UNIPHIER_SLD3_ID: - uniphier_sld3_boot_mode_show(); - break; -#endif -#if defined(CONFIG_ARCH_UNIPHIER_LD4) || defined(CONFIG_ARCH_UNIPHIER_PRO4) || \ - defined(CONFIG_ARCH_UNIPHIER_SLD8) - case UNIPHIER_LD4_ID: - case UNIPHIER_PRO4_ID: - case UNIPHIER_SLD8_ID: - uniphier_ld4_boot_mode_show(); - break; -#endif -#if defined(CONFIG_ARCH_UNIPHIER_PRO5) - case UNIPHIER_PRO5_ID: - uniphier_pro5_boot_mode_show(); - break; -#endif -#if defined(CONFIG_ARCH_UNIPHIER_PXS2) || defined(CONFIG_ARCH_UNIPHIER_LD6B) - case UNIPHIER_PXS2_ID: - case UNIPHIER_LD6B_ID: - uniphier_pxs2_boot_mode_show(); - break; -#endif -#if defined(CONFIG_ARCH_UNIPHIER_LD11) || defined(CONFIG_ARCH_UNIPHIER_LD20) - case UNIPHIER_LD11_ID: - case UNIPHIER_LD20_ID: - uniphier_ld20_boot_mode_show(); - break; -#endif - default: - break; - } - - return 0; -} - -U_BOOT_CMD( - pinmon, 1, 1, do_pinmon, - "pin monitor", - "" -); diff --git a/arch/arm/mach-uniphier/boot-mode/spl_board.c b/arch/arm/mach-uniphier/boot-mode/spl_board.c deleted file mode 100644 index 0aac9241c3..0000000000 --- a/arch/arm/mach-uniphier/boot-mode/spl_board.c +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (C) 2016 Socionext Inc. - * Author: Masahiro Yamada <yamada.masahiro@socionext.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <spl.h> -#include <linux/io.h> -#include <asm/processor.h> - -#include "../soc-info.h" - -struct uniphier_romfunc_table { - void *mmc_send_cmd; - void *mmc_card_blockaddr; - void *mmc_switch_part; - void *mmc_load_image; -}; - -static const struct uniphier_romfunc_table uniphier_ld11_romfunc_table = { - .mmc_send_cmd = (void *)0x20d8, - .mmc_card_blockaddr = (void *)0x1b68, - .mmc_switch_part = (void *)0x1c38, - .mmc_load_image = (void *)0x2e48, -}; - -static const struct uniphier_romfunc_table uniphier_ld20_romfunc_table = { - .mmc_send_cmd = (void *)0x2130, - .mmc_card_blockaddr = (void *)0x1ba0, - .mmc_switch_part = (void *)0x1c70, - .mmc_load_image = (void *)0x2ef0, -}; - -int uniphier_rom_get_mmc_funcptr(int (**send_cmd)(u32, u32), - int (**card_blockaddr)(u32), - int (**switch_part)(int), - int (**load_image)(u32, uintptr_t, u32)) -{ - const struct uniphier_romfunc_table *table; - - switch (uniphier_get_soc_id()) { - case UNIPHIER_LD11_ID: - table = &uniphier_ld11_romfunc_table; - break; - case UNIPHIER_LD20_ID: - table = &uniphier_ld20_romfunc_table; - break; - default: - printf("unsupported SoC\n"); - return -EINVAL; - } - - *send_cmd = table->mmc_send_cmd; - *card_blockaddr = table->mmc_card_blockaddr; - *switch_part = table->mmc_switch_part; - *load_image = table->mmc_load_image; - - return 0; -} - -static int spl_board_load_image(struct spl_image_info *spl_image, - struct spl_boot_device *bootdev) -{ - int (*send_cmd)(u32 cmd, u32 arg); - int (*card_blockaddr)(u32 rca); - int (*switch_part)(int part); - int (*load_image)(u32 dev_addr, uintptr_t load_addr, u32 block_cnt); - u32 dev_addr = CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR; - const u32 rca = 0x1000; /* RCA assigned by Boot ROM */ - int ret; - - ret = uniphier_rom_get_mmc_funcptr(&send_cmd, &card_blockaddr, - &switch_part, &load_image); - if (ret) - return ret; - - /* - * deselect card before SEND_CSD command. - * Do not check the return code. It fails, but it is OK. - */ - (*send_cmd)(0x071a0000, 0); /* CMD7 (arg=0) */ - - /* reset CMD Line */ - writeb(0x6, 0x5a00022f); - while (readb(0x5a00022f)) - cpu_relax(); - - ret = (*card_blockaddr)(rca); - if (ret) { - debug("card is block addressing\n"); - } else { - debug("card is byte addressing\n"); - dev_addr *= 512; - } - - ret = (*send_cmd)(0x071a0000, rca << 16); /* CMD7: select card again */ - if (ret) - printf("failed to select card\n"); - - ret = (*switch_part)(1); /* Switch to Boot Partition 1 */ - if (ret) - printf("failed to switch partition\n"); - - ret = (*load_image)(dev_addr, CONFIG_SYS_TEXT_BASE, 1); - if (ret) { - printf("failed to load image\n"); - return ret; - } - - ret = spl_parse_image_header(spl_image, (void *)CONFIG_SYS_TEXT_BASE); - if (ret) - return ret; - - ret = (*load_image)(dev_addr, spl_image->load_addr, - spl_image->size / 512); - if (ret) { - printf("failed to load image\n"); - return ret; - } - - return 0; -} -SPL_LOAD_IMAGE_METHOD("eMMC", 0, BOOT_DEVICE_BOARD, spl_board_load_image); diff --git a/arch/arm/mach-uniphier/clk/Makefile b/arch/arm/mach-uniphier/clk/Makefile index 43df670ca0..41341970ec 100644 --- a/arch/arm/mach-uniphier/clk/Makefile +++ b/arch/arm/mach-uniphier/clk/Makefile @@ -24,7 +24,7 @@ obj-$(CONFIG_ARCH_UNIPHIER_PRO5) += clk-pro5.o obj-$(CONFIG_ARCH_UNIPHIER_PXS2) += clk-pxs2.o obj-$(CONFIG_ARCH_UNIPHIER_LD6B) += clk-pxs2.o obj-$(CONFIG_ARCH_UNIPHIER_LD11) += clk-ld11.o pll-ld11.o -obj-$(CONFIG_ARCH_UNIPHIER_LD20) += pll-ld20.o +obj-$(CONFIG_ARCH_UNIPHIER_LD20) += clk-ld20.o pll-ld20.o obj-$(CONFIG_ARCH_UNIPHIER_PXS3) += pll-pxs3.o endif diff --git a/arch/arm/mach-uniphier/clk/clk-ld11.c b/arch/arm/mach-uniphier/clk/clk-ld11.c index 58069cbf15..a4dcde743b 100644 --- a/arch/arm/mach-uniphier/clk/clk-ld11.c +++ b/arch/arm/mach-uniphier/clk/clk-ld11.c @@ -9,16 +9,17 @@ #include <linux/bitops.h> #include <linux/io.h> -#include "../boot-mode/boot-device.h" #include "../init.h" #include "../sc64-regs.h" #include "../sg-regs.h" +#define SDCTRL_EMMC_HW_RESET 0x59810280 + void uniphier_ld11_clk_init(void) { /* if booted from a device other than USB, without stand-by MPU */ if ((readl(SG_PINMON0) & BIT(27)) && - spl_boot_device_raw() != BOOT_DEVICE_USB) { + uniphier_boot_device_raw() != BOOT_DEVICE_USB) { writel(1, SG_ETPHYPSHUT); writel(1, SG_ETPHYCNT); @@ -29,6 +30,9 @@ void uniphier_ld11_clk_init(void) writel(7, SG_ETPHYCNT); } + /* TODO: use "mmc-pwrseq-emmc" */ + writel(1, SDCTRL_EMMC_HW_RESET); + #ifdef CONFIG_USB_EHCI { /* FIXME: the current clk driver can not handle parents */ diff --git a/arch/arm/mach-uniphier/clk/clk-ld20.c b/arch/arm/mach-uniphier/clk/clk-ld20.c new file mode 100644 index 0000000000..5bb560cafe --- /dev/null +++ b/arch/arm/mach-uniphier/clk/clk-ld20.c @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2017 Socionext Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <linux/io.h> + +#include "../init.h" + +#define SDCTRL_EMMC_HW_RESET 0x59810280 + +void uniphier_ld20_clk_init(void) +{ + /* TODO: use "mmc-pwrseq-emmc" */ + writel(1, SDCTRL_EMMC_HW_RESET); +} diff --git a/arch/arm/mach-uniphier/clk/pll-base-ld20.c b/arch/arm/mach-uniphier/clk/pll-base-ld20.c index c66f083fae..697eb7aabf 100644 --- a/arch/arm/mach-uniphier/clk/pll-base-ld20.c +++ b/arch/arm/mach-uniphier/clk/pll-base-ld20.c @@ -18,6 +18,8 @@ #define SC_PLLCTRL_SSC_EN BIT(31) #define SC_PLLCTRL2_NRSTDS BIT(28) #define SC_PLLCTRL2_SSC_JK_MASK GENMASK(26, 0) +#define SC_PLLCTRL3_REGI_SHIFT 16 +#define SC_PLLCTRL3_REGI_MASK GENMASK(19, 16) /* PLL type: VPLL27 */ #define SC_VPLL27CTRL_WP BIT(0) @@ -77,6 +79,25 @@ int uniphier_ld20_sscpll_ssc_en(unsigned long reg_base) return 0; } +int uniphier_ld20_sscpll_set_regi(unsigned long reg_base, unsigned regi) +{ + void __iomem *base; + u32 tmp; + + base = ioremap(reg_base, SZ_16); + if (!base) + return -ENOMEM; + + tmp = readl(base + 8); /* SSCPLLCTRL */ + tmp &= ~SC_PLLCTRL3_REGI_MASK; + tmp |= regi << SC_PLLCTRL3_REGI_SHIFT; + writel(tmp, base + 8); + + iounmap(base); + + return 0; +} + int uniphier_ld20_vpll27_init(unsigned long reg_base) { void __iomem *base; diff --git a/arch/arm/mach-uniphier/clk/pll-ld11.c b/arch/arm/mach-uniphier/clk/pll-ld11.c index 7746deb72d..02befa298b 100644 --- a/arch/arm/mach-uniphier/clk/pll-ld11.c +++ b/arch/arm/mach-uniphier/clk/pll-ld11.c @@ -18,6 +18,8 @@ void uniphier_ld11_pll_init(void) uniphier_ld20_sscpll_init(SC_MPLLCTRL, 1600, 1, 2); /* 1500MHz -> 1600MHz */ uniphier_ld20_sscpll_init(SC_VSPLLCTRL, UNIPHIER_PLL_FREQ_DEFAULT, 0, 2); + uniphier_ld20_sscpll_set_regi(SC_MPLLCTRL, 5); + mdelay(1); uniphier_ld20_sscpll_ssc_en(SC_CPLLCTRL); diff --git a/arch/arm/mach-uniphier/clk/pll.h b/arch/arm/mach-uniphier/clk/pll.h index d7e93037d6..5eefc4ee31 100644 --- a/arch/arm/mach-uniphier/clk/pll.h +++ b/arch/arm/mach-uniphier/clk/pll.h @@ -15,6 +15,7 @@ void uniphier_ld4_dpll_ssc_en(void); int uniphier_ld20_sscpll_init(unsigned long reg_base, unsigned int freq, unsigned int ssc_rate, unsigned int divn); int uniphier_ld20_sscpll_ssc_en(unsigned long reg_base); +int uniphier_ld20_sscpll_set_regi(unsigned long reg_base, unsigned regi); int uniphier_ld20_vpll27_init(unsigned long reg_base); int uniphier_ld20_dspll_init(unsigned long reg_base); diff --git a/arch/arm/mach-uniphier/dram/umc-ld11.c b/arch/arm/mach-uniphier/dram/umc-ld11.c index 97a9fef24c..69aa4f2eeb 100644 --- a/arch/arm/mach-uniphier/dram/umc-ld11.c +++ b/arch/arm/mach-uniphier/dram/umc-ld11.c @@ -471,7 +471,7 @@ int uniphier_ld11_umc_init(const struct uniphier_board_data *bd) ddrphy_init(phy_base, freq); - for (ch = 0; ch < bd->dram_nr_ch; ch++) { + for (ch = 0; ch < DRAM_CH_NR; ch++) { unsigned long size = bd->dram_ch[ch].size; unsigned int width = bd->dram_ch[ch].width; diff --git a/arch/arm/mach-uniphier/dram/umc-ld20.c b/arch/arm/mach-uniphier/dram/umc-ld20.c index 157b915a7b..500c1c11ba 100644 --- a/arch/arm/mach-uniphier/dram/umc-ld20.c +++ b/arch/arm/mach-uniphier/dram/umc-ld20.c @@ -1,7 +1,7 @@ /* * Copyright (C) 2016-2017 Socionext Inc. * - * based on commit e732175d0b0dbc2a3855cb8ac791c538666b6fd4 of Diag + * based on commit 5ffd75ecd4929f22361ef65a35f0331d2fbc0f35 of Diag * * SPDX-License-Identifier: GPL-2.0+ */ @@ -177,12 +177,18 @@ static void ddrphy_select_lane(void __iomem *phy_base, unsigned int lane, phy_base + PHY_LANE_SEL); } +#define DDRPHY_EFUSEMON (void *)0x5f900118 + static void ddrphy_init(void __iomem *phy_base, enum dram_board board, int ch) { writel(0x0C001001, phy_base + PHY_UNIQUIFY_TSMC_IO_1); while (!(readl(phy_base + PHY_UNIQUIFY_TSMC_IO_1) & BIT(1))) cpu_relax(); - writel(0x0C001000, phy_base + PHY_UNIQUIFY_TSMC_IO_1); + + if (readl(DDRPHY_EFUSEMON) & BIT(ch)) + writel(0x00000000, phy_base + PHY_UNIQUIFY_TSMC_IO_1); + else + writel(0x0C001000, phy_base + PHY_UNIQUIFY_TSMC_IO_1); writel(0x00000000, phy_base + PHY_DLL_INCR_TRIM_3); writel(0x00000000, phy_base + PHY_DLL_INCR_TRIM_1); @@ -606,15 +612,18 @@ int uniphier_ld20_umc_init(const struct uniphier_board_data *bd) return -EINVAL; } - for (ch = 0; ch < bd->dram_nr_ch; ch++) { + for (ch = 0; ch < DRAM_CH_NR; ch++) { unsigned long size = bd->dram_ch[ch].size; unsigned int width = bd->dram_ch[ch].width; - ret = umc_ch_init(umc_ch_base, phy_ch_base, board, - bd->dram_freq, size / (width / 16), ch); - if (ret) { - pr_err("failed to initialize UMC ch%d\n", ch); - return ret; + if (size) { + ret = umc_ch_init(umc_ch_base, phy_ch_base, board, + bd->dram_freq, size / (width / 16), + ch); + if (ret) { + pr_err("failed to initialize UMC ch%d\n", ch); + return ret; + } } umc_ch_base += 0x00200000; diff --git a/arch/arm/mach-uniphier/dram/umc-pxs2.c b/arch/arm/mach-uniphier/dram/umc-pxs2.c index 05a62de45a..7fa29f119d 100644 --- a/arch/arm/mach-uniphier/dram/umc-pxs2.c +++ b/arch/arm/mach-uniphier/dram/umc-pxs2.c @@ -619,15 +619,17 @@ int uniphier_pxs2_umc_init(const struct uniphier_board_data *bd) return -EINVAL; } - for (ch = 0; ch < bd->dram_nr_ch; ch++) { + for (ch = 0; ch < DRAM_CH_NR; ch++) { unsigned long size = bd->dram_ch[ch].size; unsigned int width = bd->dram_ch[ch].width; - ret = umc_ch_init(umc_ch_base, freq, size / (width / 16), - width, ch); - if (ret) { - pr_err("failed to initialize UMC ch%d\n", ch); - return ret; + if (size) { + ret = umc_ch_init(umc_ch_base, freq, + size / (width / 16), width, ch); + if (ret) { + pr_err("failed to initialize UMC ch%d\n", ch); + return ret; + } } umc_ch_base += 0x00200000; diff --git a/arch/arm/mach-uniphier/dram_init.c b/arch/arm/mach-uniphier/dram_init.c index 881062d9b6..d9f6c16fdc 100644 --- a/arch/arm/mach-uniphier/dram_init.c +++ b/arch/arm/mach-uniphier/dram_init.c @@ -11,10 +11,12 @@ #include <linux/errno.h> #include <linux/sizes.h> -#include "init.h" #include "sg-regs.h" #include "soc-info.h" +#define pr_warn(fmt, args...) printf(fmt, ##args) +#define pr_err(fmt, args...) printf(fmt, ##args) + DECLARE_GLOBAL_DATA_PTR; struct uniphier_memif_data { @@ -76,7 +78,12 @@ static const struct uniphier_memif_data uniphier_memif_data[] = { }; UNIPHIER_DEFINE_SOCDATA_FUNC(uniphier_get_memif_data, uniphier_memif_data) -static int uniphier_memconf_decode(struct uniphier_dram_ch *dram_ch) +struct uniphier_dram_map { + unsigned long base; + unsigned long size; +}; + +static int uniphier_memconf_decode(struct uniphier_dram_map *dram_map) { const struct uniphier_memif_data *data; unsigned long size; @@ -91,7 +98,7 @@ static int uniphier_memconf_decode(struct uniphier_dram_ch *dram_ch) val = readl(SG_MEMCONF); /* set up ch0 */ - dram_ch[0].base = CONFIG_SYS_SDRAM_BASE; + dram_map[0].base = CONFIG_SYS_SDRAM_BASE; switch (val & SG_MEMCONF_CH0_SZ_MASK) { case SG_MEMCONF_CH0_SZ_64M: @@ -110,27 +117,27 @@ static int uniphier_memconf_decode(struct uniphier_dram_ch *dram_ch) size = SZ_1G; break; default: - pr_err("error: invald value is set to MEMCONF ch0 size\n"); + pr_err("error: invalid value is set to MEMCONF ch0 size\n"); return -EINVAL; } if ((val & SG_MEMCONF_CH0_NUM_MASK) == SG_MEMCONF_CH0_NUM_2) size *= 2; - dram_ch[0].size = size; + dram_map[0].size = size; /* set up ch1 */ - dram_ch[1].base = dram_ch[0].base + size; + dram_map[1].base = dram_map[0].base + size; if (val & SG_MEMCONF_SPARSEMEM) { - if (dram_ch[1].base > data->sparse_ch1_base) { + if (dram_map[1].base > data->sparse_ch1_base) { pr_warn("Sparse mem is enabled, but ch0 and ch1 overlap\n"); pr_warn("Only ch0 is available\n"); - dram_ch[1].base = 0; + dram_map[1].base = 0; return 0; } - dram_ch[1].base = data->sparse_ch1_base; + dram_map[1].base = data->sparse_ch1_base; } switch (val & SG_MEMCONF_CH1_SZ_MASK) { @@ -150,20 +157,20 @@ static int uniphier_memconf_decode(struct uniphier_dram_ch *dram_ch) size = SZ_1G; break; default: - pr_err("error: invald value is set to MEMCONF ch1 size\n"); + pr_err("error: invalid value is set to MEMCONF ch1 size\n"); return -EINVAL; } if ((val & SG_MEMCONF_CH1_NUM_MASK) == SG_MEMCONF_CH1_NUM_2) size *= 2; - dram_ch[1].size = size; + dram_map[1].size = size; - if (!data->have_ch2) + if (!data->have_ch2 || val & SG_MEMCONF_CH2_DISABLE) return 0; /* set up ch2 */ - dram_ch[2].base = dram_ch[1].base + size; + dram_map[2].base = dram_map[1].base + size; switch (val & SG_MEMCONF_CH2_SZ_MASK) { case SG_MEMCONF_CH2_SZ_64M: @@ -182,32 +189,32 @@ static int uniphier_memconf_decode(struct uniphier_dram_ch *dram_ch) size = SZ_1G; break; default: - pr_err("error: invald value is set to MEMCONF ch2 size\n"); + pr_err("error: invalid value is set to MEMCONF ch2 size\n"); return -EINVAL; } if ((val & SG_MEMCONF_CH2_NUM_MASK) == SG_MEMCONF_CH2_NUM_2) size *= 2; - dram_ch[2].size = size; + dram_map[2].size = size; return 0; } int dram_init(void) { - struct uniphier_dram_ch dram_ch[UNIPHIER_MAX_NR_DRAM_CH] = {}; + struct uniphier_dram_map dram_map[3] = {}; int ret, i; gd->ram_size = 0; - ret = uniphier_memconf_decode(dram_ch); + ret = uniphier_memconf_decode(dram_map); if (ret) return ret; - for (i = 0; i < ARRAY_SIZE(dram_ch); i++) { + for (i = 0; i < ARRAY_SIZE(dram_map); i++) { - if (!dram_ch[i].size) + if (!dram_map[i].size) break; /* @@ -215,11 +222,11 @@ int dram_init(void) * but it does not expect sparse memory. We use the first * contiguous chunk here. */ - if (i > 0 && - dram_ch[i - 1].base + dram_ch[i - 1].size < dram_ch[i].base) + if (i > 0 && dram_map[i - 1].base + dram_map[i - 1].size < + dram_map[i].base) break; - gd->ram_size += dram_ch[i].size; + gd->ram_size += dram_map[i].size; } return 0; @@ -227,17 +234,17 @@ int dram_init(void) void dram_init_banksize(void) { - struct uniphier_dram_ch dram_ch[UNIPHIER_MAX_NR_DRAM_CH] = {}; + struct uniphier_dram_map dram_map[3] = {}; int i; - uniphier_memconf_decode(dram_ch); + uniphier_memconf_decode(dram_map); - for (i = 0; i < ARRAY_SIZE(dram_ch); i++) { + for (i = 0; i < ARRAY_SIZE(dram_map); i++) { if (i >= ARRAY_SIZE(gd->bd->bi_dram)) break; - gd->bd->bi_dram[i].start = dram_ch[i].base; - gd->bd->bi_dram[i].size = dram_ch[i].size; + gd->bd->bi_dram[i].start = dram_map[i].base; + gd->bd->bi_dram[i].size = dram_map[i].size; } } @@ -256,6 +263,9 @@ int ft_board_setup(void *fdt, bd_t *bd) return 0; for (i = 0; i < ARRAY_SIZE(gd->bd->bi_dram); i++) { + if (!gd->bd->bi_dram[i].size) + continue; + rsv_addr = gd->bd->bi_dram[i].start + gd->bd->bi_dram[i].size; rsv_addr -= rsv_size; diff --git a/arch/arm/mach-uniphier/init.h b/arch/arm/mach-uniphier/init.h index 453e68a43e..5c45f2d31b 100644 --- a/arch/arm/mach-uniphier/init.h +++ b/arch/arm/mach-uniphier/init.h @@ -13,18 +13,17 @@ #define UNIPHIER_MAX_NR_DRAM_CH 3 struct uniphier_dram_ch { - unsigned long base; unsigned long size; unsigned int width; }; struct uniphier_board_data { unsigned int dram_freq; - unsigned int dram_nr_ch; struct uniphier_dram_ch dram_ch[UNIPHIER_MAX_NR_DRAM_CH]; unsigned int flags; -#define UNIPHIER_BD_DDR3PLUS BIT(2) +#define UNIPHIER_BD_DRAM_SPARSE BIT(9) +#define UNIPHIER_BD_DDR3PLUS BIT(8) #define UNIPHIER_BD_BOARD_GET_TYPE(f) ((f) & 0x7) #define UNIPHIER_BD_BOARD_LD20_REF 0 /* LD20 reference */ @@ -119,12 +118,16 @@ void uniphier_pro4_clk_init(void); void uniphier_pro5_clk_init(void); void uniphier_pxs2_clk_init(void); void uniphier_ld11_clk_init(void); +void uniphier_ld20_clk_init(void); +unsigned int uniphier_boot_device_raw(void); int uniphier_pin_init(const char *pinconfig_name); void uniphier_smp_kick_all_cpus(void); void cci500_init(int nr_slaves); +#undef pr_warn #define pr_warn(fmt, args...) printf(fmt, ##args) +#undef pr_err #define pr_err(fmt, args...) printf(fmt, ##args) #endif /* __MACH_INIT_H */ diff --git a/arch/arm/mach-uniphier/memconf.c b/arch/arm/mach-uniphier/memconf.c index dcfc6455ba..4ced2cbace 100644 --- a/arch/arm/mach-uniphier/memconf.c +++ b/arch/arm/mach-uniphier/memconf.c @@ -93,7 +93,7 @@ static int __uniphier_memconf_init(const struct uniphier_board_data *bd, } /* is sparse mem? */ - if (bd->dram_ch[0].base + bd->dram_ch[0].size < bd->dram_ch[1].base) + if (bd->flags & UNIPHIER_BD_DRAM_SPARSE) val |= SG_MEMCONF_SPARSEMEM; if (!have_ch2) diff --git a/arch/arm/mach-uniphier/micro-support-card.c b/arch/arm/mach-uniphier/micro-support-card.c index 2b231ac187..8a3034114f 100644 --- a/arch/arm/mach-uniphier/micro-support-card.c +++ b/arch/arm/mach-uniphier/micro-support-card.c @@ -43,18 +43,13 @@ static int support_card_show_revision(void) revision &= 0xff; /* revision 3.6.x card changed the revision format */ - printf("(CPLD version %s%d.%d)\n", revision >> 4 == 6 ? "3." : "", + printf("SC: Micro Support Card (CPLD version %s%d.%d)\n", + revision >> 4 == 6 ? "3." : "", revision >> 4, revision & 0xf); return 0; } -int checkboard(void) -{ - printf("SC: Micro Support Card "); - return support_card_show_revision(); -} - void support_card_init(void) { support_card_reset(); @@ -64,6 +59,8 @@ void support_card_init(void) */ udelay(200); support_card_reset_deassert(); + + support_card_show_revision(); } #if defined(CONFIG_SMC911X) diff --git a/arch/arm/mach-uniphier/mmc-boot-mode.c b/arch/arm/mach-uniphier/mmc-boot-mode.c new file mode 100644 index 0000000000..d60c578ce7 --- /dev/null +++ b/arch/arm/mach-uniphier/mmc-boot-mode.c @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2016 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <mmc.h> +#include <spl.h> + +u32 spl_boot_mode(const u32 boot_device) +{ + struct mmc *mmc; + + /* + * work around a bug in the Boot ROM of PH1-sLD3, LD4, Pro4, and sLD8: + * + * The boot ROM in these SoCs breaks the PARTITION_CONFIG [179] of + * Extended CSD register; when switching to the Boot Partition 1, the + * Boot ROM should issue the SWITCH command (CMD6) with Set Bits for + * the Access Bits, but in fact it uses Write Byte for the Access Bits. + * As a result, the BOOT_PARTITION_ENABLE field of the PARTITION_CONFIG + * is lost. This bug was fixed for PH1-Pro5 and later SoCs. + * + * Fixup mmc->part_config here because it is used to determine the + * partition which the U-Boot image is read from. + */ + mmc = find_mmc_device(0); + mmc->part_config &= ~EXT_CSD_BOOT_PART_NUM(PART_ACCESS_MASK); + mmc->part_config |= EXT_CSD_BOOT_PARTITION_ENABLE; + + return MMCSD_MODE_EMMCBOOT; +} diff --git a/arch/arm/mach-uniphier/mmc-first-dev.c b/arch/arm/mach-uniphier/mmc-first-dev.c new file mode 100644 index 0000000000..8c45229a89 --- /dev/null +++ b/arch/arm/mach-uniphier/mmc-first-dev.c @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2016 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <mmc.h> +#include <linux/errno.h> + +static int find_first_mmc_device(void) +{ + struct mmc *mmc; + int i; + + for (i = 0; (mmc = find_mmc_device(i)); i++) { + if (!mmc_init(mmc) && IS_MMC(mmc)) + return i; + } + + return -ENODEV; +} + +int mmc_get_env_dev(void) +{ + return find_first_mmc_device(); +} + +static int do_mmcsetn(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + int dev; + + dev = find_first_mmc_device(); + if (dev < 0) + return CMD_RET_FAILURE; + + setenv_ulong("mmc_first_dev", dev); + return CMD_RET_SUCCESS; +} + +U_BOOT_CMD( + mmcsetn, 1, 1, do_mmcsetn, + "Set the first MMC (not SD) dev number to \"mmc_first_dev\" environment", + "" +); diff --git a/arch/arm/mach-uniphier/spl_board_init.c b/arch/arm/mach-uniphier/spl_board_init.c index da749a3d6d..0079a083e8 100644 --- a/arch/arm/mach-uniphier/spl_board_init.c +++ b/arch/arm/mach-uniphier/spl_board_init.c @@ -168,4 +168,8 @@ void spl_board_init(void) pr_err("failed to init DRAM\n"); hang(); } + +#ifdef CONFIG_ARM64 + dcache_disable(); +#endif } diff --git a/configs/uniphier_ld11_defconfig b/configs/uniphier_ld11_defconfig index f14ae0430b..e5cfab6687 100644 --- a/configs/uniphier_ld11_defconfig +++ b/configs/uniphier_ld11_defconfig @@ -10,8 +10,10 @@ CONFIG_DEFAULT_DEVICE_TREE="uniphier-ld11-ref" CONFIG_SPL=y CONFIG_SPL_NOR_SUPPORT=y CONFIG_HUSH_PARSER=y +CONFIG_CMD_CONFIG=y # CONFIG_CMD_XIMG is not set # CONFIG_CMD_ENV_EXISTS is not set +CONFIG_CMD_GPT=y CONFIG_CMD_MMC=y CONFIG_CMD_I2C=y CONFIG_CMD_USB=y @@ -23,6 +25,8 @@ CONFIG_CMD_CACHE=y CONFIG_CMD_TIME=y # CONFIG_CMD_MISC is not set CONFIG_CMD_FAT=y +# CONFIG_SPL_DOS_PARTITION is not set +# CONFIG_SPL_EFI_PARTITION is not set CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPL_OF_TRANSLATE=y CONFIG_GPIO_UNIPHIER=y @@ -31,7 +35,6 @@ CONFIG_I2C_EEPROM=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_SDMA=y CONFIG_MMC_SDHCI_CADENCE=y -CONFIG_MTD_NOR_FLASH=y CONFIG_USB=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_GENERIC=y diff --git a/configs/uniphier_ld20_defconfig b/configs/uniphier_ld20_defconfig index c065bf28c8..62513597a6 100644 --- a/configs/uniphier_ld20_defconfig +++ b/configs/uniphier_ld20_defconfig @@ -10,8 +10,10 @@ CONFIG_DEFAULT_DEVICE_TREE="uniphier-ld20-ref" CONFIG_SPL=y CONFIG_SPL_NOR_SUPPORT=y CONFIG_HUSH_PARSER=y +CONFIG_CMD_CONFIG=y # CONFIG_CMD_XIMG is not set # CONFIG_CMD_ENV_EXISTS is not set +CONFIG_CMD_GPT=y CONFIG_CMD_MMC=y CONFIG_CMD_I2C=y CONFIG_CMD_USB=y @@ -23,6 +25,8 @@ CONFIG_CMD_CACHE=y CONFIG_CMD_TIME=y # CONFIG_CMD_MISC is not set CONFIG_CMD_FAT=y +# CONFIG_SPL_DOS_PARTITION is not set +# CONFIG_SPL_EFI_PARTITION is not set CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPL_OF_TRANSLATE=y CONFIG_GPIO_UNIPHIER=y @@ -31,7 +35,6 @@ CONFIG_I2C_EEPROM=y CONFIG_MMC_UNIPHIER=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_CADENCE=y -CONFIG_MTD_NOR_FLASH=y CONFIG_USB=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_STORAGE=y diff --git a/configs/uniphier_ld4_sld8_defconfig b/configs/uniphier_ld4_sld8_defconfig index b9a9524f19..68bca1942b 100644 --- a/configs/uniphier_ld4_sld8_defconfig +++ b/configs/uniphier_ld4_sld8_defconfig @@ -12,9 +12,11 @@ CONFIG_DEFAULT_DEVICE_TREE="uniphier-ld4-ref" CONFIG_SPL=y CONFIG_SPL_NOR_SUPPORT=y CONFIG_HUSH_PARSER=y +CONFIG_CMD_CONFIG=y CONFIG_CMD_BOOTZ=y # CONFIG_CMD_XIMG is not set # CONFIG_CMD_ENV_EXISTS is not set +CONFIG_CMD_GPT=y CONFIG_CMD_MMC=y CONFIG_CMD_NAND=y CONFIG_CMD_I2C=y @@ -27,12 +29,13 @@ CONFIG_CMD_CACHE=y CONFIG_CMD_TIME=y # CONFIG_CMD_MISC is not set CONFIG_CMD_FAT=y +# CONFIG_SPL_DOS_PARTITION is not set +# CONFIG_SPL_EFI_PARTITION is not set CONFIG_NET_RANDOM_ETHADDR=y CONFIG_GPIO_UNIPHIER=y CONFIG_MISC=y CONFIG_I2C_EEPROM=y CONFIG_MMC_UNIPHIER=y -CONFIG_MTD_NOR_FLASH=y CONFIG_NAND_DENALI=y CONFIG_SYS_NAND_DENALI_64BIT=y CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8 diff --git a/configs/uniphier_pro4_defconfig b/configs/uniphier_pro4_defconfig index 0b83a1bda5..fc72889dbf 100644 --- a/configs/uniphier_pro4_defconfig +++ b/configs/uniphier_pro4_defconfig @@ -11,9 +11,11 @@ CONFIG_DEFAULT_DEVICE_TREE="uniphier-pro4-ref" CONFIG_SPL=y CONFIG_SPL_NOR_SUPPORT=y CONFIG_HUSH_PARSER=y +CONFIG_CMD_CONFIG=y CONFIG_CMD_BOOTZ=y # CONFIG_CMD_XIMG is not set # CONFIG_CMD_ENV_EXISTS is not set +CONFIG_CMD_GPT=y CONFIG_CMD_MMC=y CONFIG_CMD_NAND=y CONFIG_CMD_I2C=y @@ -26,12 +28,13 @@ CONFIG_CMD_CACHE=y CONFIG_CMD_TIME=y # CONFIG_CMD_MISC is not set CONFIG_CMD_FAT=y +# CONFIG_SPL_DOS_PARTITION is not set +# CONFIG_SPL_EFI_PARTITION is not set CONFIG_NET_RANDOM_ETHADDR=y CONFIG_GPIO_UNIPHIER=y CONFIG_MISC=y CONFIG_I2C_EEPROM=y CONFIG_MMC_UNIPHIER=y -CONFIG_MTD_NOR_FLASH=y CONFIG_NAND_DENALI=y CONFIG_SYS_NAND_DENALI_64BIT=y CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8 diff --git a/configs/uniphier_pxs2_ld6b_defconfig b/configs/uniphier_pxs2_ld6b_defconfig index 7e6f0a0154..7a358e321c 100644 --- a/configs/uniphier_pxs2_ld6b_defconfig +++ b/configs/uniphier_pxs2_ld6b_defconfig @@ -12,9 +12,11 @@ CONFIG_DEFAULT_DEVICE_TREE="uniphier-pxs2-vodka" CONFIG_SPL=y CONFIG_SPL_NOR_SUPPORT=y CONFIG_HUSH_PARSER=y +CONFIG_CMD_CONFIG=y CONFIG_CMD_BOOTZ=y # CONFIG_CMD_XIMG is not set # CONFIG_CMD_ENV_EXISTS is not set +CONFIG_CMD_GPT=y CONFIG_CMD_MMC=y CONFIG_CMD_NAND=y CONFIG_CMD_I2C=y @@ -27,12 +29,13 @@ CONFIG_CMD_CACHE=y CONFIG_CMD_TIME=y # CONFIG_CMD_MISC is not set CONFIG_CMD_FAT=y +# CONFIG_SPL_DOS_PARTITION is not set +# CONFIG_SPL_EFI_PARTITION is not set CONFIG_NET_RANDOM_ETHADDR=y CONFIG_GPIO_UNIPHIER=y CONFIG_MISC=y CONFIG_I2C_EEPROM=y CONFIG_MMC_UNIPHIER=y -CONFIG_MTD_NOR_FLASH=y CONFIG_NAND_DENALI=y CONFIG_SYS_NAND_DENALI_64BIT=y CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8 diff --git a/configs/uniphier_sld3_defconfig b/configs/uniphier_sld3_defconfig index f1f2a3fd65..ef5d1e4190 100644 --- a/configs/uniphier_sld3_defconfig +++ b/configs/uniphier_sld3_defconfig @@ -12,9 +12,11 @@ CONFIG_DEFAULT_DEVICE_TREE="uniphier-sld3-ref" CONFIG_SPL=y CONFIG_SPL_NOR_SUPPORT=y CONFIG_HUSH_PARSER=y +CONFIG_CMD_CONFIG=y CONFIG_CMD_BOOTZ=y # CONFIG_CMD_XIMG is not set # CONFIG_CMD_ENV_EXISTS is not set +CONFIG_CMD_GPT=y CONFIG_CMD_MMC=y CONFIG_CMD_NAND=y CONFIG_CMD_I2C=y @@ -27,12 +29,13 @@ CONFIG_CMD_CACHE=y CONFIG_CMD_TIME=y # CONFIG_CMD_MISC is not set CONFIG_CMD_FAT=y +# CONFIG_SPL_DOS_PARTITION is not set +# CONFIG_SPL_EFI_PARTITION is not set CONFIG_NET_RANDOM_ETHADDR=y CONFIG_GPIO_UNIPHIER=y CONFIG_MISC=y CONFIG_I2C_EEPROM=y CONFIG_MMC_UNIPHIER=y -CONFIG_MTD_NOR_FLASH=y CONFIG_NAND_DENALI=y CONFIG_SYS_NAND_DENALI_64BIT=y CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8 diff --git a/configs/uniphier_v8_defconfig b/configs/uniphier_v8_defconfig index a8f2816f1b..85f8da5a46 100644 --- a/configs/uniphier_v8_defconfig +++ b/configs/uniphier_v8_defconfig @@ -7,8 +7,10 @@ CONFIG_SYS_TEXT_BASE=0x84000000 CONFIG_DEFAULT_DEVICE_TREE="uniphier-ld20-ref" # CONFIG_ARCH_FIXUP_FDT_MEMORY is not set CONFIG_HUSH_PARSER=y +CONFIG_CMD_CONFIG=y # CONFIG_CMD_XIMG is not set # CONFIG_CMD_ENV_EXISTS is not set +CONFIG_CMD_GPT=y CONFIG_CMD_MMC=y CONFIG_CMD_I2C=y CONFIG_CMD_USB=y @@ -27,8 +29,9 @@ CONFIG_I2C_EEPROM=y CONFIG_MMC_UNIPHIER=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_CADENCE=y -CONFIG_MTD_NOR_FLASH=y CONFIG_USB=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_GENERIC=y CONFIG_USB_STORAGE=y diff --git a/doc/README.uniphier b/doc/README.uniphier index 539b1f20a1..f79659c9ca 100644 --- a/doc/README.uniphier +++ b/doc/README.uniphier @@ -75,7 +75,7 @@ Burn U-Boot images to NAND Write the following to the NAND device: - spl/u-boot-spl.bin at the offset address 0x00000000 - - u-boot.bin at the offset address 0x00010000 + - u-boot.bin at the offset address 0x00020000 or @@ -94,7 +94,7 @@ Burn U-Boot images to eMMC Write the following to the Boot partition 1 of the eMMC device: - spl/u-boot-spl.bin at the offset address 0x00000000 - - u-boot.bin at the offset address 0x00010000 + - u-boot.bin at the offset address 0x00020000 or @@ -179,4 +179,4 @@ newer SoCs. Even if it is, EA[25] is not connected on most of the boards. -- Masahiro Yamada <yamada.masahiro@socionext.com> -Oct. 2016 +Jan. 2017 diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c index 51144b8e73..d8e9948ee7 100644 --- a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c +++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c @@ -5,6 +5,7 @@ * SPDX-License-Identifier: GPL-2.0+ */ +#include <common.h> #include <linux/io.h> #include <linux/err.h> #include <linux/sizes.h> @@ -15,6 +16,7 @@ #define UNIPHIER_PINCTRL_PINMUX_BASE 0x1000 #define UNIPHIER_PINCTRL_LOAD_PINMUX 0x1700 +#define UNIPHIER_PINCTRL_PUPDCTRL_BASE 0x1a00 #define UNIPHIER_PINCTRL_IECTRL 0x1d00 static const char *uniphier_pinctrl_dummy_name = "_dummy"; @@ -55,8 +57,8 @@ static const char *uniphier_pinmux_get_function_name(struct udevice *dev, return priv->socdata->functions[selector]; } -static void uniphier_pinconf_input_enable_perpin(struct udevice *dev, - unsigned pin) +static int uniphier_pinconf_input_enable_perpin(struct udevice *dev, + unsigned int pin, int enable) { struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); unsigned reg; @@ -66,18 +68,30 @@ static void uniphier_pinconf_input_enable_perpin(struct udevice *dev, mask = BIT(pin % 32); tmp = readl(priv->base + reg); - tmp |= mask; + if (enable) + tmp |= mask; + else + tmp &= ~mask; writel(tmp, priv->base + reg); + + return 0; } -static void uniphier_pinconf_input_enable_legacy(struct udevice *dev, - unsigned pin) +static int uniphier_pinconf_input_enable_legacy(struct udevice *dev, + unsigned int pin, int enable) { struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); int pins_count = priv->socdata->pins_count; const struct uniphier_pinctrl_pin *pins = priv->socdata->pins; int i; + /* + * Multiple pins share one input enable, per-pin disabling is + * impossible. + */ + if (!enable) + return -EINVAL; + for (i = 0; i < pins_count; i++) { if (pins[i].number == pin) { unsigned int iectrl; @@ -89,18 +103,115 @@ static void uniphier_pinconf_input_enable_legacy(struct udevice *dev, writel(tmp, priv->base + UNIPHIER_PINCTRL_IECTRL); } } + + return 0; } -static void uniphier_pinconf_input_enable(struct udevice *dev, unsigned pin) +static int uniphier_pinconf_input_enable(struct udevice *dev, + unsigned int pin, int enable) { struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); if (priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_PERPIN_IECTRL) - uniphier_pinconf_input_enable_perpin(dev, pin); + return uniphier_pinconf_input_enable_perpin(dev, pin, enable); + else + return uniphier_pinconf_input_enable_legacy(dev, pin, enable); +} + +#if CONFIG_IS_ENABLED(PINCONF) + +static const struct pinconf_param uniphier_pinconf_params[] = { + { "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 }, + { "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 }, + { "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 }, + { "bias-pull-pin-default", PIN_CONFIG_BIAS_PULL_PIN_DEFAULT, 1 }, + { "input-enable", PIN_CONFIG_INPUT_ENABLE, 1 }, + { "input-disable", PIN_CONFIG_INPUT_ENABLE, 0 }, +}; + +static int uniphier_pinconf_bias_set(struct udevice *dev, unsigned int pin, + unsigned int param, unsigned int arg) +{ + struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); + unsigned int enable = 1; + unsigned int reg; + u32 mask, tmp; + + if (!(priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_PUPD_SIMPLE)) + return -ENOTSUPP; + + switch (param) { + case PIN_CONFIG_BIAS_DISABLE: + enable = 0; + break; + case PIN_CONFIG_BIAS_PULL_UP: + case PIN_CONFIG_BIAS_PULL_DOWN: + if (arg == 0) /* total bias is not supported */ + return -EINVAL; + break; + case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT: + if (arg == 0) /* configuration ignored */ + return 0; + default: + BUG(); + } + + reg = UNIPHIER_PINCTRL_PUPDCTRL_BASE + pin / 32 * 4; + mask = BIT(pin % 32); + + tmp = readl(priv->base + reg); + if (enable) + tmp |= mask; else - uniphier_pinconf_input_enable_legacy(dev, pin); + tmp &= ~mask; + writel(tmp, priv->base + reg); + + return 0; +} + +static int uniphier_pinconf_set_one(struct udevice *dev, unsigned int pin, + unsigned int param, unsigned int arg) +{ + int ret; + + switch (param) { + case PIN_CONFIG_BIAS_DISABLE: + case PIN_CONFIG_BIAS_PULL_UP: + case PIN_CONFIG_BIAS_PULL_DOWN: + case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT: + ret = uniphier_pinconf_bias_set(dev, pin, param, arg); + break; + case PIN_CONFIG_INPUT_ENABLE: + ret = uniphier_pinconf_input_enable(dev, pin, arg); + break; + default: + printf("unsupported configuration parameter %u\n", param); + return -EINVAL; + } + + return ret; } +static int uniphier_pinconf_group_set(struct udevice *dev, + unsigned int group_selector, + unsigned int param, unsigned int arg) +{ + struct uniphier_pinctrl_priv *priv = dev_get_priv(dev); + const struct uniphier_pinctrl_group *grp = + &priv->socdata->groups[group_selector]; + int i, ret; + + for (i = 0; i < grp->num_pins; i++) { + ret = uniphier_pinconf_set_one(dev, grp->pins[i], param, arg); + if (ret) + return ret; + } + + return 0; +} + +#endif /* CONFIG_IS_ENABLED(PINCONF) */ + static void uniphier_pinmux_set_one(struct udevice *dev, unsigned pin, int muxval) { @@ -112,7 +223,7 @@ static void uniphier_pinmux_set_one(struct udevice *dev, unsigned pin, u32 tmp; /* some pins need input-enabling */ - uniphier_pinconf_input_enable(dev, pin); + uniphier_pinconf_input_enable(dev, pin, 1); if (muxval < 0) return; /* dedicated pin; nothing to do for pin-mux */ @@ -174,6 +285,11 @@ const struct pinctrl_ops uniphier_pinctrl_ops = { .get_functions_count = uniphier_pinmux_get_functions_count, .get_function_name = uniphier_pinmux_get_function_name, .pinmux_group_set = uniphier_pinmux_group_set, +#if CONFIG_IS_ENABLED(PINCONF) + .pinconf_num_params = ARRAY_SIZE(uniphier_pinconf_params), + .pinconf_params = uniphier_pinconf_params, + .pinconf_group_set = uniphier_pinconf_group_set, +#endif .set_state = pinctrl_generic_set_state, }; diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld11.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld11.c index 1d318d824c..53c37cda7a 100644 --- a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld11.c +++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld11.c @@ -92,7 +92,8 @@ static struct uniphier_pinctrl_socdata uniphier_ld11_pinctrl_socdata = { .groups_count = ARRAY_SIZE(uniphier_ld11_groups), .functions = uniphier_ld11_functions, .functions_count = ARRAY_SIZE(uniphier_ld11_functions), - .caps = UNIPHIER_PINCTRL_CAPS_PERPIN_IECTRL, + .caps = UNIPHIER_PINCTRL_CAPS_PUPD_SIMPLE | + UNIPHIER_PINCTRL_CAPS_PERPIN_IECTRL, }; static int uniphier_ld11_pinctrl_probe(struct udevice *dev) diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld20.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld20.c index 0c46450d36..5a7d142865 100644 --- a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld20.c +++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld20.c @@ -106,7 +106,8 @@ static struct uniphier_pinctrl_socdata uniphier_ld20_pinctrl_socdata = { .groups_count = ARRAY_SIZE(uniphier_ld20_groups), .functions = uniphier_ld20_functions, .functions_count = ARRAY_SIZE(uniphier_ld20_functions), - .caps = UNIPHIER_PINCTRL_CAPS_PERPIN_IECTRL, + .caps = UNIPHIER_PINCTRL_CAPS_PUPD_SIMPLE | + UNIPHIER_PINCTRL_CAPS_PERPIN_IECTRL, }; static int uniphier_ld20_pinctrl_probe(struct udevice *dev) diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c index 80d782c8d6..b25c7ea16e 100644 --- a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c +++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c @@ -140,6 +140,7 @@ static struct uniphier_pinctrl_socdata uniphier_ld6b_pinctrl_socdata = { .groups_count = ARRAY_SIZE(uniphier_ld6b_groups), .functions = uniphier_ld6b_functions, .functions_count = ARRAY_SIZE(uniphier_ld6b_functions), + .caps = UNIPHIER_PINCTRL_CAPS_PUPD_SIMPLE, }; static int uniphier_ld6b_pinctrl_probe(struct udevice *dev) diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c index 9670f254e2..70c90bae54 100644 --- a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c +++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c @@ -147,7 +147,8 @@ static struct uniphier_pinctrl_socdata uniphier_pro5_pinctrl_socdata = { .groups_count = ARRAY_SIZE(uniphier_pro5_groups), .functions = uniphier_pro5_functions, .functions_count = ARRAY_SIZE(uniphier_pro5_functions), - .caps = UNIPHIER_PINCTRL_CAPS_DBGMUX_SEPARATE, + .caps = UNIPHIER_PINCTRL_CAPS_PUPD_SIMPLE | + UNIPHIER_PINCTRL_CAPS_DBGMUX_SEPARATE, }; static int uniphier_pro5_pinctrl_probe(struct udevice *dev) diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c index 1d291703f4..60777c3045 100644 --- a/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c +++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c @@ -140,6 +140,7 @@ static struct uniphier_pinctrl_socdata uniphier_pxs2_pinctrl_socdata = { .groups_count = ARRAY_SIZE(uniphier_pxs2_groups), .functions = uniphier_pxs2_functions, .functions_count = ARRAY_SIZE(uniphier_pxs2_functions), + .caps = UNIPHIER_PINCTRL_CAPS_PUPD_SIMPLE, }; static int uniphier_pxs2_pinctrl_probe(struct udevice *dev) diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier.h b/drivers/pinctrl/uniphier/pinctrl-uniphier.h index 21e2d377b4..a0eccf8d4a 100644 --- a/drivers/pinctrl/uniphier/pinctrl-uniphier.h +++ b/drivers/pinctrl/uniphier/pinctrl-uniphier.h @@ -67,6 +67,7 @@ struct uniphier_pinctrl_socdata { const char * const *functions; int functions_count; unsigned caps; +#define UNIPHIER_PINCTRL_CAPS_PUPD_SIMPLE BIT(3) #define UNIPHIER_PINCTRL_CAPS_PERPIN_IECTRL BIT(2) #define UNIPHIER_PINCTRL_CAPS_DBGMUX_SEPARATE BIT(1) #define UNIPHIER_PINCTRL_CAPS_MUX_4BIT BIT(0) diff --git a/include/configs/uniphier.h b/include/configs/uniphier.h index ab35191d92..2976d6313c 100644 --- a/include/configs/uniphier.h +++ b/include/configs/uniphier.h @@ -142,7 +142,7 @@ #if defined(CONFIG_ARM64) && !defined(CONFIG_ARMV8_MULTIENTRY) /* ARM Trusted Firmware */ #define BOOT_IMAGES \ - "second_image=bl1.bin\0" \ + "second_image=unph_bl.bin\0" \ "third_image=fip.bin\0" #else #define BOOT_IMAGES \ |