From 0f5fb8ce408eb790f9fc33c4545757782aaa790b Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 16 Feb 2016 17:00:22 +0900 Subject: [PATCH 01/38] ARM: dts: uniphier: rework System Bus nodes Follow the changes of DTS in Linux. Signed-off-by: Masahiro Yamada --- arch/arm/dts/uniphier-common32.dtsi | 19 ++++++++++--------- arch/arm/dts/uniphier-ph1-sld3.dtsi | 20 ++++++++++---------- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/arch/arm/dts/uniphier-common32.dtsi b/arch/arm/dts/uniphier-common32.dtsi index 59511bde94..7d59112ddd 100644 --- a/arch/arm/dts/uniphier-common32.dtsi +++ b/arch/arm/dts/uniphier-common32.dtsi @@ -23,12 +23,6 @@ ranges; interrupt-parent = <&intc>; - extbus: extbus { - compatible = "simple-bus"; - #address-cells = <2>; - #size-cells = <1>; - }; - serial0: serial@54006800 { compatible = "socionext,uniphier-uart"; status = "disabled"; @@ -69,9 +63,16 @@ clocks = <&uart_clk>; }; - system-bus-controller@58c00000 { - compatible = "socionext,uniphier-system-bus-controller"; - reg = <0x58c00000 0x400>, <0x59800000 0x2000>; + system_bus: system-bus@58c00000 { + compatible = "socionext,uniphier-system-bus"; + reg = <0x58c00000 0x400>; + #address-cells = <2>; + #size-cells = <1>; + }; + + smpctrl@59800000 { + compatible = "socionext,uniphier-smpctrl"; + reg = <0x59801000 0x400>; }; mio: mioctrl@59810000 { diff --git a/arch/arm/dts/uniphier-ph1-sld3.dtsi b/arch/arm/dts/uniphier-ph1-sld3.dtsi index 85dde66f07..e01bd30345 100644 --- a/arch/arm/dts/uniphier-ph1-sld3.dtsi +++ b/arch/arm/dts/uniphier-ph1-sld3.dtsi @@ -62,12 +62,6 @@ ranges; interrupt-parent = <&intc>; - extbus: extbus { - compatible = "simple-bus"; - #address-cells = <2>; - #size-cells = <1>; - }; - timer@20000200 { compatible = "arm,cortex-a9-global-timer"; reg = <0x20000200 0x20>; @@ -172,10 +166,16 @@ clock-frequency = <400000>; }; - system-bus-controller-misc@59800000 { - compatible = "socionext,uniphier-system-bus-controller-misc", - "syscon"; - reg = <0x59800000 0x2000>; + system_bus: system-bus@58c00000 { + compatible = "socionext,uniphier-system-bus"; + reg = <0x58c00000 0x400>; + #address-cells = <2>; + #size-cells = <1>; + }; + + smpctrl@59800000 { + compatible = "socionext,uniphier-smpctrl"; + reg = <0x59801000 0x400>; }; mio: mioctrl@59810000 { From b9a66b63b49ce8ce7a43de68e46ef8c1c0a781fc Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 16 Feb 2016 17:03:48 +0900 Subject: [PATCH 02/38] gpio: uniphier: add driver for UniPhier GPIO controller This GPIO controller device is used on UniPhier SoCs. Signed-off-by: Masahiro Yamada Acked-by: Simon Glass --- doc/README.uniphier | 1 + drivers/gpio/Kconfig | 6 ++ drivers/gpio/Makefile | 1 + drivers/gpio/gpio-uniphier.c | 147 +++++++++++++++++++++++++++++++++++ 4 files changed, 155 insertions(+) create mode 100644 drivers/gpio/gpio-uniphier.c diff --git a/doc/README.uniphier b/doc/README.uniphier index bcf0ac3d4b..f03c20700c 100644 --- a/doc/README.uniphier +++ b/doc/README.uniphier @@ -95,6 +95,7 @@ Supported devices - NAND - USB 2.0 (EHCI) - USB 3.0 (xHCI) + - GPIO - LAN (on-board SMSC9118) - I2C - EEPROM (connected to the on-board I2C bus) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 845dc725c5..94fabb9e18 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -76,6 +76,12 @@ config SANDBOX_GPIO_COUNT of 'anonymous' GPIOs that do not belong to any device or bank. Select a suitable value depending on your needs. +config GPIO_UNIPHIER + bool "UniPhier GPIO" + depends on ARCH_UNIPHIER + help + Say yes here to support UniPhier GPIOs. + config VYBRID_GPIO bool "Vybrid GPIO driver" depends on DM diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 845a6d4493..ca8c4879e4 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -43,6 +43,7 @@ oby-$(CONFIG_SX151X) += sx151x.o obj-$(CONFIG_SUNXI_GPIO) += sunxi_gpio.o obj-$(CONFIG_LPC32XX_GPIO) += lpc32xx_gpio.o obj-$(CONFIG_STM32_GPIO) += stm32_gpio.o +obj-$(CONFIG_GPIO_UNIPHIER) += gpio-uniphier.o obj-$(CONFIG_ZYNQ_GPIO) += zynq_gpio.o obj-$(CONFIG_VYBRID_GPIO) += vybrid_gpio.o obj-$(CONFIG_HIKEY_GPIO) += hi6220_gpio.o diff --git a/drivers/gpio/gpio-uniphier.c b/drivers/gpio/gpio-uniphier.c new file mode 100644 index 0000000000..80bb16ec06 --- /dev/null +++ b/drivers/gpio/gpio-uniphier.c @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2016 Masahiro Yamada + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include + +#define UNIPHIER_GPIO_PORTS_PER_BANK 8 + +#define UNIPHIER_GPIO_REG_DATA 0 /* data */ +#define UNIPHIER_GPIO_REG_DIR 4 /* direction (1:in, 0:out) */ + +struct uniphier_gpio_priv { + void __iomem *base; + char bank_name[16]; +}; + +static void uniphier_gpio_offset_write(struct udevice *dev, unsigned offset, + unsigned reg, int value) +{ + struct uniphier_gpio_priv *priv = dev_get_priv(dev); + u32 tmp; + + tmp = readl(priv->base + reg); + if (value) + tmp |= BIT(offset); + else + tmp &= ~BIT(offset); + writel(tmp, priv->base + reg); +} + +static int uniphier_gpio_offset_read(struct udevice *dev, unsigned offset, + unsigned reg) +{ + struct uniphier_gpio_priv *priv = dev_get_priv(dev); + + return !!(readl(priv->base + reg) & BIT(offset)); +} + +static int uniphier_gpio_direction_input(struct udevice *dev, unsigned offset) +{ + uniphier_gpio_offset_write(dev, offset, UNIPHIER_GPIO_REG_DIR, 1); + + return 0; +} + +static int uniphier_gpio_direction_output(struct udevice *dev, unsigned offset, + int value) +{ + uniphier_gpio_offset_write(dev, offset, UNIPHIER_GPIO_REG_DATA, value); + uniphier_gpio_offset_write(dev, offset, UNIPHIER_GPIO_REG_DIR, 0); + + return 0; +} + +static int uniphier_gpio_get_value(struct udevice *dev, unsigned offset) +{ + return uniphier_gpio_offset_read(dev, offset, UNIPHIER_GPIO_REG_DATA); +} + +static int uniphier_gpio_set_value(struct udevice *dev, unsigned offset, + int value) +{ + uniphier_gpio_offset_write(dev, offset, UNIPHIER_GPIO_REG_DATA, value); + + return 0; +} + +static int uniphier_gpio_get_function(struct udevice *dev, unsigned offset) +{ + return uniphier_gpio_offset_read(dev, offset, UNIPHIER_GPIO_REG_DIR) ? + GPIOF_INPUT : GPIOF_OUTPUT; +} + +static const struct dm_gpio_ops uniphier_gpio_ops = { + .direction_input = uniphier_gpio_direction_input, + .direction_output = uniphier_gpio_direction_output, + .get_value = uniphier_gpio_get_value, + .set_value = uniphier_gpio_set_value, + .get_function = uniphier_gpio_get_function, +}; + +static int uniphier_gpio_probe(struct udevice *dev) +{ + struct uniphier_gpio_priv *priv = dev_get_priv(dev); + struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); + DECLARE_GLOBAL_DATA_PTR; + fdt_addr_t addr; + fdt_size_t size; + unsigned int tmp; + + addr = fdtdec_get_addr_size(gd->fdt_blob, dev->of_offset, "reg", + &size); + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + + priv->base = map_sysmem(addr, size); + if (!priv->base) + return -ENOMEM; + + uc_priv->gpio_count = UNIPHIER_GPIO_PORTS_PER_BANK; + + tmp = (addr & 0xfff); + + /* Unfortunately, there is a register hole at offset 0x90-0x9f. */ + if (tmp > 0x90) + tmp -= 0x10; + + snprintf(priv->bank_name, sizeof(priv->bank_name) - 1, + "port%d-", (tmp - 8) / 8); + + uc_priv->bank_name = priv->bank_name; + + return 0; +} + +static int uniphier_gpio_remove(struct udevice *dev) +{ + struct uniphier_gpio_priv *priv = dev_get_priv(dev); + + unmap_sysmem(priv->base); + + return 0; +} + +/* .data = the number of GPIO banks */ +static const struct udevice_id uniphier_gpio_match[] = { + { .compatible = "socionext,uniphier-gpio" }, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(uniphier_gpio) = { + .name = "uniphier_gpio", + .id = UCLASS_GPIO, + .of_match = uniphier_gpio_match, + .probe = uniphier_gpio_probe, + .remove = uniphier_gpio_remove, + .priv_auto_alloc_size = sizeof(struct uniphier_gpio_priv), + .ops = &uniphier_gpio_ops, +}; From f8facbe71ecb4c9411e3da6e40d90152d066879a Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 16 Feb 2016 17:03:49 +0900 Subject: [PATCH 03/38] gpio: do not include for UniPhier I implemented a GPIO driver based on Driver Model for the UniPhier SoC family, but I could not find any good reason why such SoC specific GPIO headers are needed. Signed-off-by: Masahiro Yamada Acked-by: Simon Glass --- arch/arm/include/asm/gpio.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/include/asm/gpio.h b/arch/arm/include/asm/gpio.h index d49ad080e2..fe4419cae4 100644 --- a/arch/arm/include/asm/gpio.h +++ b/arch/arm/include/asm/gpio.h @@ -1,2 +1,4 @@ +#ifndef CONFIG_ARCH_UNIPHIER #include +#endif #include From b800cbde4fecd26b52aa1736b045ca3c3673fc94 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 16 Feb 2016 17:03:50 +0900 Subject: [PATCH 04/38] ARM: uniphier: enable GPIO command and driver for UniPhier SoCs This allows to use the "gpio" command. Signed-off-by: Masahiro Yamada Acked-by: Simon Glass --- arch/arm/Kconfig | 1 + configs/uniphier_ld4_sld8_defconfig | 2 ++ configs/uniphier_pro4_defconfig | 2 ++ configs/uniphier_pro5_defconfig | 2 ++ configs/uniphier_pxs2_ld6b_defconfig | 2 ++ configs/uniphier_sld3_defconfig | 2 ++ 6 files changed, 11 insertions(+) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index d8b63e9407..94bd7ece09 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -697,6 +697,7 @@ config ARCH_UNIPHIER select SPL_OF_CONTROL select DM select SPL_DM + select DM_GPIO select DM_SERIAL select DM_I2C help diff --git a/configs/uniphier_ld4_sld8_defconfig b/configs/uniphier_ld4_sld8_defconfig index 535f96fb63..dbee08eaf7 100644 --- a/configs/uniphier_ld4_sld8_defconfig +++ b/configs/uniphier_ld4_sld8_defconfig @@ -13,12 +13,14 @@ CONFIG_CMD_NAND=y CONFIG_CMD_I2C=y CONFIG_CMD_USB=y # CONFIG_CMD_FPGA is not set +CONFIG_CMD_GPIO=y CONFIG_CMD_TFTPPUT=y CONFIG_CMD_PING=y CONFIG_CMD_TIME=y # CONFIG_CMD_MISC is not set CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPL_SIMPLE_BUS=y +CONFIG_GPIO_UNIPHIER=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 2361db6ab5..3c2f7b08ef 100644 --- a/configs/uniphier_pro4_defconfig +++ b/configs/uniphier_pro4_defconfig @@ -12,12 +12,14 @@ CONFIG_CMD_NAND=y CONFIG_CMD_I2C=y CONFIG_CMD_USB=y # CONFIG_CMD_FPGA is not set +CONFIG_CMD_GPIO=y CONFIG_CMD_TFTPPUT=y CONFIG_CMD_PING=y CONFIG_CMD_TIME=y # CONFIG_CMD_MISC is not set CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPL_SIMPLE_BUS=y +CONFIG_GPIO_UNIPHIER=y CONFIG_NAND_DENALI=y CONFIG_SYS_NAND_DENALI_64BIT=y CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8 diff --git a/configs/uniphier_pro5_defconfig b/configs/uniphier_pro5_defconfig index be0d7b5390..cf5f1ced29 100644 --- a/configs/uniphier_pro5_defconfig +++ b/configs/uniphier_pro5_defconfig @@ -12,12 +12,14 @@ CONFIG_CMD_NAND=y CONFIG_CMD_I2C=y CONFIG_CMD_USB=y # CONFIG_CMD_FPGA is not set +CONFIG_CMD_GPIO=y CONFIG_CMD_TFTPPUT=y CONFIG_CMD_PING=y CONFIG_CMD_TIME=y # CONFIG_CMD_MISC is not set CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPL_SIMPLE_BUS=y +CONFIG_GPIO_UNIPHIER=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 f8cb794b8f..00a29009fe 100644 --- a/configs/uniphier_pxs2_ld6b_defconfig +++ b/configs/uniphier_pxs2_ld6b_defconfig @@ -13,12 +13,14 @@ CONFIG_CMD_NAND=y CONFIG_CMD_I2C=y CONFIG_CMD_USB=y # CONFIG_CMD_FPGA is not set +CONFIG_CMD_GPIO=y CONFIG_CMD_TFTPPUT=y CONFIG_CMD_PING=y CONFIG_CMD_TIME=y # CONFIG_CMD_MISC is not set CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPL_SIMPLE_BUS=y +CONFIG_GPIO_UNIPHIER=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 e369c45e82..013fc8af2e 100644 --- a/configs/uniphier_sld3_defconfig +++ b/configs/uniphier_sld3_defconfig @@ -11,11 +11,13 @@ CONFIG_CMD_NAND=y CONFIG_CMD_I2C=y CONFIG_CMD_USB=y # CONFIG_CMD_FPGA is not set +CONFIG_CMD_GPIO=y CONFIG_CMD_TFTPPUT=y CONFIG_CMD_PING=y CONFIG_CMD_TIME=y # CONFIG_CMD_MISC is not set CONFIG_NET_RANDOM_ETHADDR=y +CONFIG_GPIO_UNIPHIER=y CONFIG_NAND_DENALI=y CONFIG_SYS_NAND_DENALI_64BIT=y CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8 From 595dc1e162e2d8dce6a97a0199554d59b2589a5f Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 16 Feb 2016 17:03:51 +0900 Subject: [PATCH 05/38] ARM: dts: uniphier: add GPIO controller nodes Make the GPIO driver really active. Signed-off-by: Masahiro Yamada --- arch/arm/dts/uniphier-ph1-ld4.dtsi | 112 ++++++++++++++ arch/arm/dts/uniphier-ph1-pro4.dtsi | 203 +++++++++++++++++++++++++ arch/arm/dts/uniphier-ph1-pro5.dtsi | 203 +++++++++++++++++++++++++ arch/arm/dts/uniphier-ph1-sld3.dtsi | 112 ++++++++++++++ arch/arm/dts/uniphier-ph1-sld8.dtsi | 112 ++++++++++++++ arch/arm/dts/uniphier-proxstream2.dtsi | 196 ++++++++++++++++++++++++ 6 files changed, 938 insertions(+) diff --git a/arch/arm/dts/uniphier-ph1-ld4.dtsi b/arch/arm/dts/uniphier-ph1-ld4.dtsi index 7c8759f929..f13c6db271 100644 --- a/arch/arm/dts/uniphier-ph1-ld4.dtsi +++ b/arch/arm/dts/uniphier-ph1-ld4.dtsi @@ -56,6 +56,118 @@ cache-level = <2>; }; + port0x: gpio@55000008 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000008 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port1x: gpio@55000010 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000010 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port2x: gpio@55000018 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000018 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port3x: gpio@55000020 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000020 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port4: gpio@55000028 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000028 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port5x: gpio@55000030 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000030 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port6x: gpio@55000038 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000038 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port7x: gpio@55000040 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000040 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port8x: gpio@55000048 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000048 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port9x: gpio@55000050 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000050 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port10x: gpio@55000058 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000058 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port11x: gpio@55000060 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000060 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port12x: gpio@55000068 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000068 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port13x: gpio@55000070 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000070 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port14x: gpio@55000078 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000078 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port16x: gpio@55000088 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000088 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + i2c0: i2c@58400000 { compatible = "socionext,uniphier-i2c"; status = "disabled"; diff --git a/arch/arm/dts/uniphier-ph1-pro4.dtsi b/arch/arm/dts/uniphier-ph1-pro4.dtsi index cb5b8f1a86..6637aeaa07 100644 --- a/arch/arm/dts/uniphier-ph1-pro4.dtsi +++ b/arch/arm/dts/uniphier-ph1-pro4.dtsi @@ -64,6 +64,209 @@ cache-level = <2>; }; + port0x: gpio@55000008 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000008 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port1x: gpio@55000010 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000010 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port2x: gpio@55000018 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000018 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port3x: gpio@55000020 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000020 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port4: gpio@55000028 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000028 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port5x: gpio@55000030 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000030 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port6x: gpio@55000038 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000038 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port7x: gpio@55000040 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000040 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port8x: gpio@55000048 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000048 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port9x: gpio@55000050 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000050 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port10x: gpio@55000058 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000058 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port11x: gpio@55000060 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000060 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port12x: gpio@55000068 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000068 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port13x: gpio@55000070 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000070 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port14x: gpio@55000078 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000078 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port17x: gpio@550000a0 { + compatible = "socionext,uniphier-gpio"; + reg = <0x550000a0 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port18x: gpio@550000a8 { + compatible = "socionext,uniphier-gpio"; + reg = <0x550000a8 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port19x: gpio@550000b0 { + compatible = "socionext,uniphier-gpio"; + reg = <0x550000b0 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port20x: gpio@550000b8 { + compatible = "socionext,uniphier-gpio"; + reg = <0x550000b8 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port21x: gpio@550000c0 { + compatible = "socionext,uniphier-gpio"; + reg = <0x550000c0 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port22x: gpio@550000c8 { + compatible = "socionext,uniphier-gpio"; + reg = <0x550000c8 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port23x: gpio@550000d0 { + compatible = "socionext,uniphier-gpio"; + reg = <0x550000d0 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port24x: gpio@550000d8 { + compatible = "socionext,uniphier-gpio"; + reg = <0x550000d8 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port25x: gpio@550000e0 { + compatible = "socionext,uniphier-gpio"; + reg = <0x550000e0 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port26x: gpio@550000e8 { + compatible = "socionext,uniphier-gpio"; + reg = <0x550000e8 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port27x: gpio@550000f0 { + compatible = "socionext,uniphier-gpio"; + reg = <0x550000f0 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port28x: gpio@550000f8 { + compatible = "socionext,uniphier-gpio"; + reg = <0x550000f8 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port29x: gpio@55000100 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000100 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port30x: gpio@55000108 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000108 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + i2c0: i2c@58780000 { compatible = "socionext,uniphier-fi2c"; status = "disabled"; diff --git a/arch/arm/dts/uniphier-ph1-pro5.dtsi b/arch/arm/dts/uniphier-ph1-pro5.dtsi index 087b25a950..67a435e913 100644 --- a/arch/arm/dts/uniphier-ph1-pro5.dtsi +++ b/arch/arm/dts/uniphier-ph1-pro5.dtsi @@ -76,6 +76,209 @@ cache-level = <3>; }; + port0x: gpio@55000008 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000008 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port1x: gpio@55000010 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000010 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port2x: gpio@55000018 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000018 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port3x: gpio@55000020 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000020 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port4: gpio@55000028 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000028 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port5x: gpio@55000030 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000030 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port6x: gpio@55000038 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000038 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port7x: gpio@55000040 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000040 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port8x: gpio@55000048 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000048 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port9x: gpio@55000050 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000050 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port10x: gpio@55000058 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000058 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port11x: gpio@55000060 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000060 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port12x: gpio@55000068 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000068 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port13x: gpio@55000070 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000070 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port14x: gpio@55000078 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000078 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port17x: gpio@550000a0 { + compatible = "socionext,uniphier-gpio"; + reg = <0x550000a0 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port18x: gpio@550000a8 { + compatible = "socionext,uniphier-gpio"; + reg = <0x550000a8 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port19x: gpio@550000b0 { + compatible = "socionext,uniphier-gpio"; + reg = <0x550000b0 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port20x: gpio@550000b8 { + compatible = "socionext,uniphier-gpio"; + reg = <0x550000b8 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port21x: gpio@550000c0 { + compatible = "socionext,uniphier-gpio"; + reg = <0x550000c0 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port22x: gpio@550000c8 { + compatible = "socionext,uniphier-gpio"; + reg = <0x550000c8 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port23x: gpio@550000d0 { + compatible = "socionext,uniphier-gpio"; + reg = <0x550000d0 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port24x: gpio@550000d8 { + compatible = "socionext,uniphier-gpio"; + reg = <0x550000d8 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port25x: gpio@550000e0 { + compatible = "socionext,uniphier-gpio"; + reg = <0x550000e0 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port26x: gpio@550000e8 { + compatible = "socionext,uniphier-gpio"; + reg = <0x550000e8 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port27x: gpio@550000f0 { + compatible = "socionext,uniphier-gpio"; + reg = <0x550000f0 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port28x: gpio@550000f8 { + compatible = "socionext,uniphier-gpio"; + reg = <0x550000f8 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port29x: gpio@55000100 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000100 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port30x: gpio@55000108 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000108 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + i2c0: i2c@58780000 { compatible = "socionext,uniphier-fi2c"; status = "disabled"; diff --git a/arch/arm/dts/uniphier-ph1-sld3.dtsi b/arch/arm/dts/uniphier-ph1-sld3.dtsi index e01bd30345..9a6ca575bd 100644 --- a/arch/arm/dts/uniphier-ph1-sld3.dtsi +++ b/arch/arm/dts/uniphier-ph1-sld3.dtsi @@ -111,6 +111,118 @@ clock-frequency = <36864000>; }; + port0x: gpio@55000008 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000008 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port1x: gpio@55000010 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000010 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port2x: gpio@55000018 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000018 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port3x: gpio@55000020 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000020 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port4: gpio@55000028 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000028 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port5x: gpio@55000030 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000030 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port6x: gpio@55000038 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000038 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port7x: gpio@55000040 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000040 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port8x: gpio@55000048 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000048 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port9x: gpio@55000050 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000050 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port10x: gpio@55000058 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000058 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port11x: gpio@55000060 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000060 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port12x: gpio@55000068 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000068 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port13x: gpio@55000070 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000070 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port14x: gpio@55000078 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000078 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port16x: gpio@55000088 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000088 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + i2c0: i2c@58400000 { compatible = "socionext,uniphier-i2c"; status = "disabled"; diff --git a/arch/arm/dts/uniphier-ph1-sld8.dtsi b/arch/arm/dts/uniphier-ph1-sld8.dtsi index f93db83661..985848a027 100644 --- a/arch/arm/dts/uniphier-ph1-sld8.dtsi +++ b/arch/arm/dts/uniphier-ph1-sld8.dtsi @@ -56,6 +56,118 @@ cache-level = <2>; }; + port0x: gpio@55000008 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000008 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port1x: gpio@55000010 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000010 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port2x: gpio@55000018 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000018 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port3x: gpio@55000020 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000020 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port4: gpio@55000028 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000028 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port5x: gpio@55000030 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000030 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port6x: gpio@55000038 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000038 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port7x: gpio@55000040 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000040 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port8x: gpio@55000048 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000048 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port9x: gpio@55000050 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000050 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port10x: gpio@55000058 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000058 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port11x: gpio@55000060 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000060 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port12x: gpio@55000068 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000068 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port13x: gpio@55000070 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000070 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port14x: gpio@55000078 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000078 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port16x: gpio@55000088 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000088 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + i2c0: i2c@58400000 { compatible = "socionext,uniphier-i2c"; status = "disabled"; diff --git a/arch/arm/dts/uniphier-proxstream2.dtsi b/arch/arm/dts/uniphier-proxstream2.dtsi index 2d324f95a4..21fad0cdee 100644 --- a/arch/arm/dts/uniphier-proxstream2.dtsi +++ b/arch/arm/dts/uniphier-proxstream2.dtsi @@ -78,6 +78,202 @@ cache-level = <2>; }; + port0x: gpio@55000008 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000008 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port1x: gpio@55000010 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000010 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port2x: gpio@55000018 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000018 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port3x: gpio@55000020 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000020 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port4: gpio@55000028 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000028 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port5x: gpio@55000030 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000030 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port6x: gpio@55000038 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000038 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port7x: gpio@55000040 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000040 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port8x: gpio@55000048 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000048 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port9x: gpio@55000050 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000050 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port10x: gpio@55000058 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000058 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port12x: gpio@55000068 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000068 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port13x: gpio@55000070 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000070 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port14x: gpio@55000078 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000078 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port15x: gpio@55000080 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000080 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port16x: gpio@55000088 { + compatible = "socionext,uniphier-gpio"; + reg = <0x55000088 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port17x: gpio@550000a0 { + compatible = "socionext,uniphier-gpio"; + reg = <0x550000a0 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port18x: gpio@550000a8 { + compatible = "socionext,uniphier-gpio"; + reg = <0x550000a8 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port19x: gpio@550000b0 { + compatible = "socionext,uniphier-gpio"; + reg = <0x550000b0 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port20x: gpio@550000b8 { + compatible = "socionext,uniphier-gpio"; + reg = <0x550000b8 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port21x: gpio@550000c0 { + compatible = "socionext,uniphier-gpio"; + reg = <0x550000c0 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port22x: gpio@550000c8 { + compatible = "socionext,uniphier-gpio"; + reg = <0x550000c8 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port23x: gpio@550000d0 { + compatible = "socionext,uniphier-gpio"; + reg = <0x550000d0 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port24x: gpio@550000d8 { + compatible = "socionext,uniphier-gpio"; + reg = <0x550000d8 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port25x: gpio@550000e0 { + compatible = "socionext,uniphier-gpio"; + reg = <0x550000e0 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port26x: gpio@550000e8 { + compatible = "socionext,uniphier-gpio"; + reg = <0x550000e8 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port27x: gpio@550000f0 { + compatible = "socionext,uniphier-gpio"; + reg = <0x550000f0 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + + port28x: gpio@550000f8 { + compatible = "socionext,uniphier-gpio"; + reg = <0x550000f8 0x8>; + gpio-controller; + #gpio-cells = <2>; + }; + i2c0: i2c@58780000 { compatible = "socionext,uniphier-fi2c"; status = "disabled"; From a111bfbfad21dd83aae5a6d96c620c3666e9b654 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 18 Feb 2016 19:52:48 +0900 Subject: [PATCH 06/38] mmc: uniphier: add driver for UniPhier SD/MMC host controller Add a driver for the on-chip SD/eMMC host controller used by UniPhier SoC family. Signed-off-by: Masahiro Yamada --- doc/README.uniphier | 1 + drivers/mmc/Kconfig | 6 + drivers/mmc/Makefile | 1 + drivers/mmc/uniphier-sd.c | 751 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 759 insertions(+) create mode 100644 drivers/mmc/uniphier-sd.c diff --git a/doc/README.uniphier b/doc/README.uniphier index f03c20700c..c270ecb9a5 100644 --- a/doc/README.uniphier +++ b/doc/README.uniphier @@ -93,6 +93,7 @@ Supported devices - UART (on-chip) - NAND + - SD/eMMC - USB 2.0 (EHCI) - USB 3.0 (xHCI) - GPIO diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index 9d3f7e908f..dc8532fe93 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -43,4 +43,10 @@ config ZYNQ_SDHCI help Support for Arasan SDHCI host controller on Zynq/ZynqMP ARM SoCs platform +config MMC_UNIPHIER + bool "UniPhier SD/MMC Host Controller support" + depends on ARCH_UNIPHIER + help + This selects support for the SD/MMC Host Controller on UniPhier SoCs. + endmenu diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index c9c3e3e938..b85e4bfb77 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -41,6 +41,7 @@ obj-$(CONFIG_SH_SDHI) += sh_sdhi.o obj-$(CONFIG_SOCFPGA_DWMMC) += socfpga_dw_mmc.o obj-$(CONFIG_SPEAR_SDHCI) += spear_sdhci.o obj-$(CONFIG_TEGRA_MMC) += tegra_mmc.o +obj-$(CONFIG_MMC_UNIPHIER) += uniphier-sd.o obj-$(CONFIG_ZYNQ_SDHCI) += zynq_sdhci.o ifdef CONFIG_SPL_BUILD diff --git a/drivers/mmc/uniphier-sd.c b/drivers/mmc/uniphier-sd.c new file mode 100644 index 0000000000..3bc4d942a0 --- /dev/null +++ b/drivers/mmc/uniphier-sd.c @@ -0,0 +1,751 @@ +/* + * Copyright (C) 2016 Masahiro Yamada + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +#define UNIPHIER_SD_CMD 0x000 /* command */ +#define UNIPHIER_SD_CMD_NOSTOP BIT(14) /* No automatic CMD12 issue */ +#define UNIPHIER_SD_CMD_MULTI BIT(13) /* multiple block transfer */ +#define UNIPHIER_SD_CMD_RD BIT(12) /* 1: read, 0: write */ +#define UNIPHIER_SD_CMD_DATA BIT(11) /* data transfer */ +#define UNIPHIER_SD_CMD_APP BIT(6) /* ACMD preceded by CMD55 */ +#define UNIPHIER_SD_CMD_NORMAL (0 << 8)/* auto-detect of resp-type */ +#define UNIPHIER_SD_CMD_RSP_NONE (3 << 8)/* response: none */ +#define UNIPHIER_SD_CMD_RSP_R1 (4 << 8)/* response: R1, R5, R6, R7 */ +#define UNIPHIER_SD_CMD_RSP_R1B (5 << 8)/* response: R1b, R5b */ +#define UNIPHIER_SD_CMD_RSP_R2 (6 << 8)/* response: R2 */ +#define UNIPHIER_SD_CMD_RSP_R3 (7 << 8)/* response: R3, R4 */ +#define UNIPHIER_SD_ARG 0x008 /* command argument */ +#define UNIPHIER_SD_STOP 0x010 /* stop action control */ +#define UNIPHIER_SD_STOP_SEC BIT(8) /* use sector count */ +#define UNIPHIER_SD_STOP_STP BIT(0) /* issue CMD12 */ +#define UNIPHIER_SD_SECCNT 0x014 /* sector counter */ +#define UNIPHIER_SD_RSP10 0x018 /* response[39:8] */ +#define UNIPHIER_SD_RSP32 0x020 /* response[71:40] */ +#define UNIPHIER_SD_RSP54 0x028 /* response[103:72] */ +#define UNIPHIER_SD_RSP76 0x030 /* response[127:104] */ +#define UNIPHIER_SD_INFO1 0x038 /* IRQ status 1 */ +#define UNIPHIER_SD_INFO1_CD BIT(5) /* state of card detect */ +#define UNIPHIER_SD_INFO1_INSERT BIT(4) /* card inserted */ +#define UNIPHIER_SD_INFO1_REMOVE BIT(3) /* card removed */ +#define UNIPHIER_SD_INFO1_CMP BIT(2) /* data complete */ +#define UNIPHIER_SD_INFO1_RSP BIT(0) /* response complete */ +#define UNIPHIER_SD_INFO2 0x03c /* IRQ status 2 */ +#define UNIPHIER_SD_INFO2_ERR_ILA BIT(15) /* illegal access err */ +#define UNIPHIER_SD_INFO2_CBSY BIT(14) /* command busy */ +#define UNIPHIER_SD_INFO2_BWE BIT(9) /* write buffer ready */ +#define UNIPHIER_SD_INFO2_BRE BIT(8) /* read buffer ready */ +#define UNIPHIER_SD_INFO2_DAT0 BIT(7) /* SDDAT0 */ +#define UNIPHIER_SD_INFO2_ERR_RTO BIT(6) /* response time out */ +#define UNIPHIER_SD_INFO2_ERR_ILR BIT(5) /* illegal read err */ +#define UNIPHIER_SD_INFO2_ERR_ILW BIT(4) /* illegal write err */ +#define UNIPHIER_SD_INFO2_ERR_TO BIT(3) /* time out error */ +#define UNIPHIER_SD_INFO2_ERR_END BIT(2) /* END bit error */ +#define UNIPHIER_SD_INFO2_ERR_CRC BIT(1) /* CRC error */ +#define UNIPHIER_SD_INFO2_ERR_IDX BIT(0) /* cmd index error */ +#define UNIPHIER_SD_INFO1_MASK 0x040 +#define UNIPHIER_SD_INFO2_MASK 0x044 +#define UNIPHIER_SD_CLKCTL 0x048 /* clock divisor */ +#define UNIPHIER_SD_CLKCTL_DIV_MASK 0x104ff +#define UNIPHIER_SD_CLKCTL_DIV1024 BIT(16) /* SDCLK = CLK / 1024 */ +#define UNIPHIER_SD_CLKCTL_DIV512 BIT(7) /* SDCLK = CLK / 512 */ +#define UNIPHIER_SD_CLKCTL_DIV256 BIT(6) /* SDCLK = CLK / 256 */ +#define UNIPHIER_SD_CLKCTL_DIV128 BIT(5) /* SDCLK = CLK / 128 */ +#define UNIPHIER_SD_CLKCTL_DIV64 BIT(4) /* SDCLK = CLK / 64 */ +#define UNIPHIER_SD_CLKCTL_DIV32 BIT(3) /* SDCLK = CLK / 32 */ +#define UNIPHIER_SD_CLKCTL_DIV16 BIT(2) /* SDCLK = CLK / 16 */ +#define UNIPHIER_SD_CLKCTL_DIV8 BIT(1) /* SDCLK = CLK / 8 */ +#define UNIPHIER_SD_CLKCTL_DIV4 BIT(0) /* SDCLK = CLK / 4 */ +#define UNIPHIER_SD_CLKCTL_DIV2 0 /* SDCLK = CLK / 2 */ +#define UNIPHIER_SD_CLKCTL_DIV1 BIT(10) /* SDCLK = CLK */ +#define UNIPHIER_SD_CLKCTL_OFFEN BIT(9) /* stop SDCLK when unused */ +#define UNIPHIER_SD_CLKCTL_SCLKEN BIT(8) /* SDCLK output enable */ +#define UNIPHIER_SD_SIZE 0x04c /* block size */ +#define UNIPHIER_SD_OPTION 0x050 +#define UNIPHIER_SD_OPTION_WIDTH_MASK (5 << 13) +#define UNIPHIER_SD_OPTION_WIDTH_1 (4 << 13) +#define UNIPHIER_SD_OPTION_WIDTH_4 (0 << 13) +#define UNIPHIER_SD_OPTION_WIDTH_8 (1 << 13) +#define UNIPHIER_SD_BUF 0x060 /* read/write buffer */ +#define UNIPHIER_SD_EXTMODE 0x1b0 +#define UNIPHIER_SD_EXTMODE_DMA_EN BIT(1) /* transfer 1: DMA, 0: pio */ +#define UNIPHIER_SD_SOFT_RST 0x1c0 +#define UNIPHIER_SD_SOFT_RST_RSTX BIT(0) /* reset deassert */ +#define UNIPHIER_SD_VERSION 0x1c4 /* version register */ +#define UNIPHIER_SD_VERSION_IP 0xff /* IP version */ +#define UNIPHIER_SD_HOST_MODE 0x1c8 +#define UNIPHIER_SD_IF_MODE 0x1cc +#define UNIPHIER_SD_IF_MODE_DDR BIT(0) /* DDR mode */ +#define UNIPHIER_SD_VOLT 0x1e4 /* voltage switch */ +#define UNIPHIER_SD_VOLT_MASK (3 << 0) +#define UNIPHIER_SD_VOLT_OFF (0 << 0) +#define UNIPHIER_SD_VOLT_330 (1 << 0)/* 3.3V signal */ +#define UNIPHIER_SD_VOLT_180 (2 << 0)/* 1.8V signal */ +#define UNIPHIER_SD_DMA_MODE 0x410 +#define UNIPHIER_SD_DMA_MODE_DIR_RD BIT(16) /* 1: from device, 0: to dev */ +#define UNIPHIER_SD_DMA_MODE_ADDR_INC BIT(0) /* 1: address inc, 0: fixed */ +#define UNIPHIER_SD_DMA_CTL 0x414 +#define UNIPHIER_SD_DMA_CTL_START BIT(0) /* start DMA (auto cleared) */ +#define UNIPHIER_SD_DMA_RST 0x418 +#define UNIPHIER_SD_DMA_RST_RD BIT(9) +#define UNIPHIER_SD_DMA_RST_WR BIT(8) +#define UNIPHIER_SD_DMA_INFO1 0x420 +#define UNIPHIER_SD_DMA_INFO1_END_RD2 BIT(20) /* DMA from device is complete*/ +#define UNIPHIER_SD_DMA_INFO1_END_RD BIT(17) /* Don't use! Hardware bug */ +#define UNIPHIER_SD_DMA_INFO1_END_WR BIT(16) /* DMA to device is complete */ +#define UNIPHIER_SD_DMA_INFO1_MASK 0x424 +#define UNIPHIER_SD_DMA_INFO2 0x428 +#define UNIPHIER_SD_DMA_INFO2_ERR_RD BIT(17) +#define UNIPHIER_SD_DMA_INFO2_ERR_WR BIT(16) +#define UNIPHIER_SD_DMA_INFO2_MASK 0x42c +#define UNIPHIER_SD_DMA_ADDR_L 0x440 +#define UNIPHIER_SD_DMA_ADDR_H 0x444 + +/* alignment required by the DMA engine of this controller */ +#define UNIPHIER_SD_DMA_MINALIGN 0x10 + +struct uniphier_sd_priv { + struct mmc_config cfg; + struct mmc *mmc; + struct udevice *dev; + void __iomem *regbase; + unsigned long mclk; + unsigned int version; + u32 caps; +#define UNIPHIER_SD_CAP_NONREMOVABLE BIT(0) /* Nonremovable e.g. eMMC */ +#define UNIPHIER_SD_CAP_DMA_INTERNAL BIT(1) /* have internal DMA engine */ +#define UNIPHIER_SD_CAP_DIV1024 BIT(2) /* divisor 1024 is available */ +}; + +static dma_addr_t __dma_map_single(void *ptr, size_t size, + enum dma_data_direction dir) +{ + unsigned long addr = (unsigned long)ptr; + + if (dir == DMA_FROM_DEVICE) + invalidate_dcache_range(addr, addr + size); + else + flush_dcache_range(addr, addr + size); + + return addr; +} + +static void __dma_unmap_single(dma_addr_t addr, size_t size, + enum dma_data_direction dir) +{ + if (dir != DMA_TO_DEVICE) + invalidate_dcache_range(addr, addr + size); +} + +static int uniphier_sd_check_error(struct uniphier_sd_priv *priv) +{ + u32 info2 = readl(priv->regbase + UNIPHIER_SD_INFO2); + + if (info2 & UNIPHIER_SD_INFO2_ERR_RTO) { + /* + * TIMEOUT must be returned for unsupported command. Do not + * display error log since this might be a part of sequence to + * distinguish between SD and MMC. + */ + return TIMEOUT; + } + + if (info2 & UNIPHIER_SD_INFO2_ERR_TO) { + dev_err(priv->dev, "timeout error\n"); + return -ETIMEDOUT; + } + + if (info2 & (UNIPHIER_SD_INFO2_ERR_END | UNIPHIER_SD_INFO2_ERR_CRC | + UNIPHIER_SD_INFO2_ERR_IDX)) { + dev_err(priv->dev, "communication out of sync\n"); + return -EILSEQ; + } + + if (info2 & (UNIPHIER_SD_INFO2_ERR_ILA | UNIPHIER_SD_INFO2_ERR_ILR | + UNIPHIER_SD_INFO2_ERR_ILW)) { + dev_err(priv->dev, "illegal access\n"); + return -EIO; + } + + return 0; +} + +static int uniphier_sd_wait_for_irq(struct uniphier_sd_priv *priv, + unsigned int reg, u32 flag) +{ + long wait = 1000000; + int ret; + + while (!(readl(priv->regbase + reg) & flag)) { + if (wait-- < 0) { + dev_err(priv->dev, "timeout\n"); + return -ETIMEDOUT; + } + + ret = uniphier_sd_check_error(priv); + if (ret) + return ret; + + udelay(1); + } + + return 0; +} + +static int uniphier_sd_pio_read_one_block(struct mmc *mmc, u32 **pbuf, + uint blocksize) +{ + struct uniphier_sd_priv *priv = mmc->priv; + int i, ret; + + /* wait until the buffer is filled with data */ + ret = uniphier_sd_wait_for_irq(priv, UNIPHIER_SD_INFO2, + UNIPHIER_SD_INFO2_BRE); + if (ret) + return ret; + + /* + * Clear the status flag _before_ read the buffer out because + * UNIPHIER_SD_INFO2_BRE is edge-triggered, not level-triggered. + */ + writel(0, priv->regbase + UNIPHIER_SD_INFO2); + + if (likely(IS_ALIGNED((unsigned long)*pbuf, 4))) { + for (i = 0; i < blocksize / 4; i++) + *(*pbuf)++ = readl(priv->regbase + UNIPHIER_SD_BUF); + } else { + for (i = 0; i < blocksize / 4; i++) + put_unaligned(readl(priv->regbase + UNIPHIER_SD_BUF), + (*pbuf)++); + } + + return 0; +} + +static int uniphier_sd_pio_write_one_block(struct mmc *mmc, const u32 **pbuf, + uint blocksize) +{ + struct uniphier_sd_priv *priv = mmc->priv; + int i, ret; + + /* wait until the buffer becomes empty */ + ret = uniphier_sd_wait_for_irq(priv, UNIPHIER_SD_INFO2, + UNIPHIER_SD_INFO2_BWE); + if (ret) + return ret; + + writel(0, priv->regbase + UNIPHIER_SD_INFO2); + + if (likely(IS_ALIGNED((unsigned long)*pbuf, 4))) { + for (i = 0; i < blocksize / 4; i++) + writel(*(*pbuf)++, priv->regbase + UNIPHIER_SD_BUF); + } else { + for (i = 0; i < blocksize / 4; i++) + writel(get_unaligned((*pbuf)++), + priv->regbase + UNIPHIER_SD_BUF); + } + + return 0; +} + +static int uniphier_sd_pio_xfer(struct mmc *mmc, struct mmc_data *data) +{ + u32 *dest = (u32 *)data->dest; + const u32 *src = (const u32 *)data->src; + int i, ret; + + for (i = 0; i < data->blocks; i++) { + if (data->flags & MMC_DATA_READ) + ret = uniphier_sd_pio_read_one_block(mmc, &dest, + data->blocksize); + else + ret = uniphier_sd_pio_write_one_block(mmc, &src, + data->blocksize); + if (ret) + return ret; + } + + return 0; +} + +static void uniphier_sd_dma_start(struct uniphier_sd_priv *priv, + dma_addr_t dma_addr) +{ + u32 tmp; + + writel(0, priv->regbase + UNIPHIER_SD_DMA_INFO1); + writel(0, priv->regbase + UNIPHIER_SD_DMA_INFO2); + + /* enable DMA */ + tmp = readl(priv->regbase + UNIPHIER_SD_EXTMODE); + tmp |= UNIPHIER_SD_EXTMODE_DMA_EN; + writel(tmp, priv->regbase + UNIPHIER_SD_EXTMODE); + + writel(dma_addr & U32_MAX, priv->regbase + UNIPHIER_SD_DMA_ADDR_L); + + /* suppress the warning "right shift count >= width of type" */ + dma_addr >>= min_t(int, 32, 8 * sizeof(dma_addr)); + + writel(dma_addr & U32_MAX, priv->regbase + UNIPHIER_SD_DMA_ADDR_H); + + writel(UNIPHIER_SD_DMA_CTL_START, priv->regbase + UNIPHIER_SD_DMA_CTL); +} + +static int uniphier_sd_dma_wait_for_irq(struct uniphier_sd_priv *priv, u32 flag, + unsigned int blocks) +{ + long wait = 1000000 + 10 * blocks; + + while (!(readl(priv->regbase + UNIPHIER_SD_DMA_INFO1) & flag)) { + if (wait-- < 0) { + dev_err(priv->dev, "timeout during DMA\n"); + return -ETIMEDOUT; + } + + udelay(10); + } + + if (readl(priv->regbase + UNIPHIER_SD_DMA_INFO2)) { + dev_err(priv->dev, "error during DMA\n"); + return -EIO; + } + + return 0; +} + +static int uniphier_sd_dma_xfer(struct mmc *mmc, struct mmc_data *data) +{ + struct uniphier_sd_priv *priv = mmc->priv; + size_t len = data->blocks * data->blocksize; + void *buf; + enum dma_data_direction dir; + dma_addr_t dma_addr; + u32 poll_flag, tmp; + int ret; + + tmp = readl(priv->regbase + UNIPHIER_SD_DMA_MODE); + + if (data->flags & MMC_DATA_READ) { + buf = data->dest; + dir = DMA_FROM_DEVICE; + poll_flag = UNIPHIER_SD_DMA_INFO1_END_RD2; + tmp |= UNIPHIER_SD_DMA_MODE_DIR_RD; + } else { + buf = (void *)data->src; + dir = DMA_TO_DEVICE; + poll_flag = UNIPHIER_SD_DMA_INFO1_END_WR; + tmp &= ~UNIPHIER_SD_DMA_MODE_DIR_RD; + } + + writel(tmp, priv->regbase + UNIPHIER_SD_DMA_MODE); + + dma_addr = __dma_map_single(buf, len, dir); + + uniphier_sd_dma_start(priv, dma_addr); + + ret = uniphier_sd_dma_wait_for_irq(priv, poll_flag, data->blocks); + + __dma_unmap_single(dma_addr, len, dir); + + return ret; +} + +/* check if the address is DMA'able */ +static bool uniphier_sd_addr_is_dmaable(unsigned long addr) +{ + if (!IS_ALIGNED(addr, UNIPHIER_SD_DMA_MINALIGN)) + return false; + +#if defined(CONFIG_ARCH_UNIPHIER) && !defined(CONFIG_ARM64) && \ + defined(CONFIG_SPL_BUILD) + /* + * For UniPhier ARMv7 SoCs, the stack is allocated in the locked ways + * of L2, which is unreachable from the DMA engine. + */ + if (addr < CONFIG_SPL_STACK) + return false; +#endif + + return true; +} + +static int uniphier_sd_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, + struct mmc_data *data) +{ + struct uniphier_sd_priv *priv = mmc->priv; + int ret; + u32 tmp; + + if (readl(priv->regbase + UNIPHIER_SD_INFO2) & UNIPHIER_SD_INFO2_CBSY) { + dev_err(priv->dev, "command busy\n"); + return -EBUSY; + } + + /* clear all status flags */ + writel(0, priv->regbase + UNIPHIER_SD_INFO1); + writel(0, priv->regbase + UNIPHIER_SD_INFO2); + + /* disable DMA once */ + tmp = readl(priv->regbase + UNIPHIER_SD_EXTMODE); + tmp &= ~UNIPHIER_SD_EXTMODE_DMA_EN; + writel(tmp, priv->regbase + UNIPHIER_SD_EXTMODE); + + writel(cmd->cmdarg, priv->regbase + UNIPHIER_SD_ARG); + + tmp = cmd->cmdidx; + + if (data) { + writel(data->blocksize, priv->regbase + UNIPHIER_SD_SIZE); + writel(data->blocks, priv->regbase + UNIPHIER_SD_SECCNT); + + /* Do not send CMD12 automatically */ + tmp |= UNIPHIER_SD_CMD_NOSTOP | UNIPHIER_SD_CMD_DATA; + + if (data->blocks > 1) + tmp |= UNIPHIER_SD_CMD_MULTI; + + if (data->flags & MMC_DATA_READ) + tmp |= UNIPHIER_SD_CMD_RD; + } + + /* + * Do not use the response type auto-detection on this hardware. + * CMD8, for example, has different response types on SD and eMMC, + * while this controller always assumes the response type for SD. + * Set the response type manually. + */ + switch (cmd->resp_type) { + case MMC_RSP_NONE: + tmp |= UNIPHIER_SD_CMD_RSP_NONE; + break; + case MMC_RSP_R1: + tmp |= UNIPHIER_SD_CMD_RSP_R1; + break; + case MMC_RSP_R1b: + tmp |= UNIPHIER_SD_CMD_RSP_R1B; + break; + case MMC_RSP_R2: + tmp |= UNIPHIER_SD_CMD_RSP_R2; + break; + case MMC_RSP_R3: + tmp |= UNIPHIER_SD_CMD_RSP_R3; + break; + default: + dev_err(priv->dev, "unknown response type\n"); + return -EINVAL; + } + + dev_dbg(priv->dev, "sending CMD%d (SD_CMD=%08x, SD_ARG=%08x)\n", + cmd->cmdidx, tmp, cmd->cmdarg); + writel(tmp, priv->regbase + UNIPHIER_SD_CMD); + + ret = uniphier_sd_wait_for_irq(priv, UNIPHIER_SD_INFO1, + UNIPHIER_SD_INFO1_RSP); + if (ret) + return ret; + + if (cmd->resp_type & MMC_RSP_136) { + u32 rsp_127_104 = readl(priv->regbase + UNIPHIER_SD_RSP76); + u32 rsp_103_72 = readl(priv->regbase + UNIPHIER_SD_RSP54); + u32 rsp_71_40 = readl(priv->regbase + UNIPHIER_SD_RSP32); + u32 rsp_39_8 = readl(priv->regbase + UNIPHIER_SD_RSP10); + + cmd->response[0] = (rsp_127_104 & 0xffffff) << 8 | + (rsp_103_72 & 0xff); + cmd->response[1] = (rsp_103_72 & 0xffffff) << 8 | + (rsp_71_40 & 0xff); + cmd->response[2] = (rsp_71_40 & 0xffffff) << 8 | + (rsp_39_8 & 0xff); + cmd->response[3] = (rsp_39_8 & 0xffffff) << 8; + } else { + /* bit 39-8 */ + cmd->response[0] = readl(priv->regbase + UNIPHIER_SD_RSP10); + } + + if (data) { + /* use DMA if the HW supports it and the buffer is aligned */ + if (priv->caps & UNIPHIER_SD_CAP_DMA_INTERNAL && + uniphier_sd_addr_is_dmaable((long)data->src)) + ret = uniphier_sd_dma_xfer(mmc, data); + else + ret = uniphier_sd_pio_xfer(mmc, data); + + ret = uniphier_sd_wait_for_irq(priv, UNIPHIER_SD_INFO1, + UNIPHIER_SD_INFO1_CMP); + if (ret) + return ret; + } + + return ret; +} + +static void uniphier_sd_set_bus_width(struct uniphier_sd_priv *priv, + struct mmc *mmc) +{ + u32 val, tmp; + + switch (mmc->bus_width) { + case 1: + val = UNIPHIER_SD_OPTION_WIDTH_1; + break; + case 4: + val = UNIPHIER_SD_OPTION_WIDTH_4; + break; + case 8: + val = UNIPHIER_SD_OPTION_WIDTH_8; + break; + default: + BUG(); + break; + } + + tmp = readl(priv->regbase + UNIPHIER_SD_OPTION); + tmp &= ~UNIPHIER_SD_OPTION_WIDTH_MASK; + tmp |= val; + writel(tmp, priv->regbase + UNIPHIER_SD_OPTION); +} + +static void uniphier_sd_set_ddr_mode(struct uniphier_sd_priv *priv, + struct mmc *mmc) +{ + u32 tmp; + + tmp = readl(priv->regbase + UNIPHIER_SD_IF_MODE); + if (mmc->ddr_mode) + tmp |= UNIPHIER_SD_IF_MODE_DDR; + else + tmp &= ~UNIPHIER_SD_IF_MODE_DDR; + writel(tmp, priv->regbase + UNIPHIER_SD_IF_MODE); +} + +static void uniphier_sd_set_clk_rate(struct uniphier_sd_priv *priv, + struct mmc *mmc) +{ + unsigned int divisor; + u32 val, tmp; + + if (!mmc->clock) + return; + + divisor = DIV_ROUND_UP(priv->mclk, mmc->clock); + + if (divisor <= 1) + val = UNIPHIER_SD_CLKCTL_DIV1; + else if (divisor <= 2) + val = UNIPHIER_SD_CLKCTL_DIV2; + else if (divisor <= 4) + val = UNIPHIER_SD_CLKCTL_DIV4; + else if (divisor <= 8) + val = UNIPHIER_SD_CLKCTL_DIV8; + else if (divisor <= 16) + val = UNIPHIER_SD_CLKCTL_DIV16; + else if (divisor <= 32) + val = UNIPHIER_SD_CLKCTL_DIV32; + else if (divisor <= 64) + val = UNIPHIER_SD_CLKCTL_DIV64; + else if (divisor <= 128) + val = UNIPHIER_SD_CLKCTL_DIV128; + else if (divisor <= 256) + val = UNIPHIER_SD_CLKCTL_DIV256; + else if (divisor <= 512 || !(priv->caps & UNIPHIER_SD_CAP_DIV1024)) + val = UNIPHIER_SD_CLKCTL_DIV512; + else + val = UNIPHIER_SD_CLKCTL_DIV1024; + + tmp = readl(priv->regbase + UNIPHIER_SD_CLKCTL); + + /* stop the clock before changing its rate to avoid a glitch signal */ + tmp &= ~UNIPHIER_SD_CLKCTL_SCLKEN; + writel(tmp, priv->regbase + UNIPHIER_SD_CLKCTL); + + tmp &= ~UNIPHIER_SD_CLKCTL_DIV_MASK; + tmp |= val | UNIPHIER_SD_CLKCTL_OFFEN; + writel(tmp, priv->regbase + UNIPHIER_SD_CLKCTL); + + tmp |= UNIPHIER_SD_CLKCTL_SCLKEN; + writel(tmp, priv->regbase + UNIPHIER_SD_CLKCTL); +} + +static void uniphier_sd_set_ios(struct mmc *mmc) +{ + struct uniphier_sd_priv *priv = mmc->priv; + + dev_dbg(priv->dev, "clock %uHz, DDRmode %d, width %u\n", + mmc->clock, mmc->ddr_mode, mmc->bus_width); + + uniphier_sd_set_bus_width(priv, mmc); + uniphier_sd_set_ddr_mode(priv, mmc); + uniphier_sd_set_clk_rate(priv, mmc); + + udelay(1000); +} + +static int uniphier_sd_init(struct mmc *mmc) +{ + struct uniphier_sd_priv *priv = mmc->priv; + u32 tmp; + + /* soft reset of the host */ + tmp = readl(priv->regbase + UNIPHIER_SD_SOFT_RST); + tmp &= ~UNIPHIER_SD_SOFT_RST_RSTX; + writel(tmp, priv->regbase + UNIPHIER_SD_SOFT_RST); + tmp |= UNIPHIER_SD_SOFT_RST_RSTX; + writel(tmp, priv->regbase + UNIPHIER_SD_SOFT_RST); + + /* FIXME: implement eMMC hw_reset */ + + writel(UNIPHIER_SD_STOP_SEC, priv->regbase + UNIPHIER_SD_STOP); + + /* + * Connected to 32bit AXI. + * This register dropped backward compatibility at version 0x10. + * Write an appropriate value depending on the IP version. + */ + writel(priv->version >= 0x10 ? 0x00000101 : 0x00000000, + priv->regbase + UNIPHIER_SD_HOST_MODE); + + if (priv->caps & UNIPHIER_SD_CAP_DMA_INTERNAL) { + tmp = readl(priv->regbase + UNIPHIER_SD_DMA_MODE); + tmp |= UNIPHIER_SD_DMA_MODE_ADDR_INC; + writel(tmp, priv->regbase + UNIPHIER_SD_DMA_MODE); + } + + return 0; +} + +static int uniphier_sd_getcd(struct mmc *mmc) +{ + struct uniphier_sd_priv *priv = mmc->priv; + + if (priv->caps & UNIPHIER_SD_CAP_NONREMOVABLE) + return 1; + + return !!(readl(priv->regbase + UNIPHIER_SD_INFO1) & + UNIPHIER_SD_INFO1_CD); +} + +static const struct mmc_ops uniphier_sd_ops = { + .send_cmd = uniphier_sd_send_cmd, + .set_ios = uniphier_sd_set_ios, + .init = uniphier_sd_init, + .getcd = uniphier_sd_getcd, +}; + +int uniphier_sd_probe(struct udevice *dev) +{ + struct uniphier_sd_priv *priv = dev_get_priv(dev); + struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); + fdt_addr_t base; + fdt_size_t size; + struct udevice *clk_dev; + int clk_id; + int ret; + + priv->dev = dev; + + base = fdtdec_get_addr_size(gd->fdt_blob, dev->of_offset, "reg", &size); + priv->regbase = map_sysmem(base, size); + if (!priv->regbase) + return -ENOMEM; + + clk_id = clk_get_by_index(dev, 0, &clk_dev); + if (clk_id < 0) { + dev_err(dev, "failed to get host clock\n"); + return clk_id; + } + + /* set to max rate */ + priv->mclk = clk_set_periph_rate(clk_dev, clk_id, ULONG_MAX); + if (IS_ERR_VALUE(priv->mclk)) { + dev_err(dev, "failed to set rate for host clock\n"); + return priv->mclk; + } + + ret = clk_enable(clk_dev, clk_id); + if (ret) { + dev_err(dev, "failed to enable host clock\n"); + return ret; + } + + priv->cfg.name = dev->name; + priv->cfg.ops = &uniphier_sd_ops; + priv->cfg.host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS; + + switch (fdtdec_get_int(gd->fdt_blob, dev->of_offset, "bus-width", 1)) { + case 8: + priv->cfg.host_caps |= MMC_MODE_8BIT; + break; + case 4: + priv->cfg.host_caps |= MMC_MODE_4BIT; + break; + case 1: + break; + default: + dev_err(dev, "Invalid \"bus-width\" value\n"); + return -EINVAL; + } + + if (fdt_get_property(gd->fdt_blob, dev->of_offset, "non-removable", + NULL)) + priv->caps |= UNIPHIER_SD_CAP_NONREMOVABLE; + + priv->version = readl(priv->regbase + UNIPHIER_SD_VERSION) & + UNIPHIER_SD_VERSION_IP; + dev_dbg(dev, "version %x\n", priv->version); + if (priv->version >= 0x10) { + priv->caps |= UNIPHIER_SD_CAP_DMA_INTERNAL; + priv->caps |= UNIPHIER_SD_CAP_DIV1024; + } + + priv->cfg.voltages = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34; + priv->cfg.f_min = priv->mclk / + (priv->caps & UNIPHIER_SD_CAP_DIV1024 ? 1024 : 512); + priv->cfg.f_max = priv->mclk; + priv->cfg.b_max = U32_MAX; /* max value of UNIPHIER_SD_SECCNT */ + + priv->mmc = mmc_create(&priv->cfg, priv); + if (!priv->mmc) + return -EIO; + + upriv->mmc = priv->mmc; + + return 0; +} + +int uniphier_sd_remove(struct udevice *dev) +{ + struct uniphier_sd_priv *priv = dev_get_priv(dev); + + unmap_sysmem(priv->regbase); + mmc_destroy(priv->mmc); + + return 0; +} + +static const struct udevice_id uniphier_sd_match[] = { + { .compatible = "socionext,uniphier-sdhc" }, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(uniphier_mmc) = { + .name = "uniphier-mmc", + .id = UCLASS_MMC, + .of_match = uniphier_sd_match, + .probe = uniphier_sd_probe, + .remove = uniphier_sd_remove, + .priv_auto_alloc_size = sizeof(struct uniphier_sd_priv), +}; From 4aceb3f8d4bfcafa895ecbc3108e1f35f2b8c091 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 18 Feb 2016 19:52:49 +0900 Subject: [PATCH 07/38] ARM: uniphier: enable UniPhier SD/MMC host driver Enable the driver in all UniPhier defconfig files and add some needed defines to the common files. Signed-off-by: Masahiro Yamada --- arch/arm/Kconfig | 1 + configs/uniphier_ld4_sld8_defconfig | 1 + configs/uniphier_pro4_defconfig | 1 + configs/uniphier_pro5_defconfig | 1 + configs/uniphier_pxs2_ld6b_defconfig | 1 + configs/uniphier_sld3_defconfig | 1 + include/configs/uniphier.h | 4 ++++ 7 files changed, 10 insertions(+) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 94bd7ece09..37b20ff331 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -700,6 +700,7 @@ config ARCH_UNIPHIER select DM_GPIO select DM_SERIAL select DM_I2C + select DM_MMC help Support for UniPhier SoC family developed by Socionext Inc. (formerly, System LSI Business Division of Panasonic Corporation) diff --git a/configs/uniphier_ld4_sld8_defconfig b/configs/uniphier_ld4_sld8_defconfig index dbee08eaf7..892bccc32f 100644 --- a/configs/uniphier_ld4_sld8_defconfig +++ b/configs/uniphier_ld4_sld8_defconfig @@ -21,6 +21,7 @@ CONFIG_CMD_TIME=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPL_SIMPLE_BUS=y CONFIG_GPIO_UNIPHIER=y +CONFIG_MMC_UNIPHIER=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 3c2f7b08ef..45ef8837e2 100644 --- a/configs/uniphier_pro4_defconfig +++ b/configs/uniphier_pro4_defconfig @@ -20,6 +20,7 @@ CONFIG_CMD_TIME=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPL_SIMPLE_BUS=y CONFIG_GPIO_UNIPHIER=y +CONFIG_MMC_UNIPHIER=y CONFIG_NAND_DENALI=y CONFIG_SYS_NAND_DENALI_64BIT=y CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8 diff --git a/configs/uniphier_pro5_defconfig b/configs/uniphier_pro5_defconfig index cf5f1ced29..0029cd3ff9 100644 --- a/configs/uniphier_pro5_defconfig +++ b/configs/uniphier_pro5_defconfig @@ -20,6 +20,7 @@ CONFIG_CMD_TIME=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPL_SIMPLE_BUS=y CONFIG_GPIO_UNIPHIER=y +CONFIG_MMC_UNIPHIER=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 00a29009fe..0115c215f8 100644 --- a/configs/uniphier_pxs2_ld6b_defconfig +++ b/configs/uniphier_pxs2_ld6b_defconfig @@ -21,6 +21,7 @@ CONFIG_CMD_TIME=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPL_SIMPLE_BUS=y CONFIG_GPIO_UNIPHIER=y +CONFIG_MMC_UNIPHIER=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 013fc8af2e..5f0d678c66 100644 --- a/configs/uniphier_sld3_defconfig +++ b/configs/uniphier_sld3_defconfig @@ -18,6 +18,7 @@ CONFIG_CMD_TIME=y # CONFIG_CMD_MISC is not set CONFIG_NET_RANDOM_ETHADDR=y CONFIG_GPIO_UNIPHIER=y +CONFIG_MMC_UNIPHIER=y CONFIG_NAND_DENALI=y CONFIG_SYS_NAND_DENALI_64BIT=y CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8 diff --git a/include/configs/uniphier.h b/include/configs/uniphier.h index fcec0c0ae2..9d14155751 100644 --- a/include/configs/uniphier.h +++ b/include/configs/uniphier.h @@ -146,6 +146,10 @@ #define CONFIG_FAT_WRITE #define CONFIG_DOS_PARTITION +/* SD/MMC */ +#define CONFIG_CMD_MMC +#define CONFIG_GENERIC_MMC + /* memtest works on */ #define CONFIG_SYS_MEMTEST_START CONFIG_SYS_SDRAM_BASE #define CONFIG_SYS_MEMTEST_END (CONFIG_SYS_SDRAM_BASE + 0x01000000) From c7f94eecfd46bb62d173169caa8c6d9493a9859b Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 18 Feb 2016 19:52:50 +0900 Subject: [PATCH 08/38] ARM: dts: uniphier: add SD/MMC host controller nodes This host controller is available for all UniPhier SoCs. Signed-off-by: Masahiro Yamada --- arch/arm/dts/uniphier-ph1-ld4-ref.dts | 4 +++ arch/arm/dts/uniphier-ph1-ld4.dtsi | 25 +++++++++++++ arch/arm/dts/uniphier-ph1-ld6b-ref.dts | 4 +++ arch/arm/dts/uniphier-ph1-pro4-ace.dts | 4 +++ arch/arm/dts/uniphier-ph1-pro4-ref.dts | 8 +++++ arch/arm/dts/uniphier-ph1-pro4-sanji.dts | 4 +++ arch/arm/dts/uniphier-ph1-pro4.dtsi | 37 ++++++++++++++++++++ arch/arm/dts/uniphier-ph1-pro5-4kbox.dts | 8 +++++ arch/arm/dts/uniphier-ph1-pro5.dtsi | 24 +++++++++++++ arch/arm/dts/uniphier-ph1-sld3-ref.dts | 4 +++ arch/arm/dts/uniphier-ph1-sld3.dtsi | 19 ++++++++++ arch/arm/dts/uniphier-ph1-sld8-ref.dts | 4 +++ arch/arm/dts/uniphier-ph1-sld8.dtsi | 25 +++++++++++++ arch/arm/dts/uniphier-pinctrl.dtsi | 15 ++++++++ arch/arm/dts/uniphier-proxstream2-gentil.dts | 4 +++ arch/arm/dts/uniphier-proxstream2-vodka.dts | 4 +++ arch/arm/dts/uniphier-proxstream2.dtsi | 24 +++++++++++++ 17 files changed, 217 insertions(+) diff --git a/arch/arm/dts/uniphier-ph1-ld4-ref.dts b/arch/arm/dts/uniphier-ph1-ld4-ref.dts index f62916da39..d7b000796e 100644 --- a/arch/arm/dts/uniphier-ph1-ld4-ref.dts +++ b/arch/arm/dts/uniphier-ph1-ld4-ref.dts @@ -51,6 +51,10 @@ status = "okay"; }; +&sd { + status = "okay"; +}; + &usb0 { status = "okay"; }; diff --git a/arch/arm/dts/uniphier-ph1-ld4.dtsi b/arch/arm/dts/uniphier-ph1-ld4.dtsi index f13c6db271..5ae029ea97 100644 --- a/arch/arm/dts/uniphier-ph1-ld4.dtsi +++ b/arch/arm/dts/uniphier-ph1-ld4.dtsi @@ -220,6 +220,31 @@ clock-frequency = <100000>; }; + sd: sdhc@5a400000 { + compatible = "socionext,uniphier-sdhc"; + status = "disabled"; + reg = <0x5a400000 0x200>; + interrupts = <0 76 4>; + pinctrl-names = "default", "1.8v"; + pinctrl-0 = <&pinctrl_sd>; + pinctrl-1 = <&pinctrl_sd_1v8>; + clocks = <&mio 0>; + bus-width = <4>; + }; + + emmc: sdhc@5a500000 { + compatible = "socionext,uniphier-sdhc"; + status = "disabled"; + reg = <0x5a500000 0x200>; + interrupts = <0 78 4>; + pinctrl-names = "default", "1.8v"; + pinctrl-0 = <&pinctrl_emmc>; + pinctrl-1 = <&pinctrl_emmc_1v8>; + clocks = <&mio 1>; + bus-width = <8>; + non-removable; + }; + usb0: usb@5a800100 { compatible = "socionext,uniphier-ehci", "generic-ehci"; status = "disabled"; diff --git a/arch/arm/dts/uniphier-ph1-ld6b-ref.dts b/arch/arm/dts/uniphier-ph1-ld6b-ref.dts index dca408bb70..13a29fdfaa 100644 --- a/arch/arm/dts/uniphier-ph1-ld6b-ref.dts +++ b/arch/arm/dts/uniphier-ph1-ld6b-ref.dts @@ -53,6 +53,10 @@ status = "okay"; }; +&sd { + status = "okay"; +}; + &usb0 { status = "okay"; }; diff --git a/arch/arm/dts/uniphier-ph1-pro4-ace.dts b/arch/arm/dts/uniphier-ph1-pro4-ace.dts index 6e741ea45b..37e0853365 100644 --- a/arch/arm/dts/uniphier-ph1-pro4-ace.dts +++ b/arch/arm/dts/uniphier-ph1-pro4-ace.dts @@ -69,6 +69,10 @@ status = "okay"; }; +&sd { + status = "okay"; +}; + &usb0 { status = "okay"; }; diff --git a/arch/arm/dts/uniphier-ph1-pro4-ref.dts b/arch/arm/dts/uniphier-ph1-pro4-ref.dts index 202a642a4d..07a9783357 100644 --- a/arch/arm/dts/uniphier-ph1-pro4-ref.dts +++ b/arch/arm/dts/uniphier-ph1-pro4-ref.dts @@ -54,6 +54,14 @@ status = "okay"; }; +&sd { + status = "okay"; +}; + +&sd1 { + status = "okay"; +}; + &usb0 { status = "okay"; }; diff --git a/arch/arm/dts/uniphier-ph1-pro4-sanji.dts b/arch/arm/dts/uniphier-ph1-pro4-sanji.dts index 91a71ef469..1ca1042128 100644 --- a/arch/arm/dts/uniphier-ph1-pro4-sanji.dts +++ b/arch/arm/dts/uniphier-ph1-pro4-sanji.dts @@ -64,6 +64,10 @@ status = "okay"; }; +&emmc { + status = "okay"; +}; + &usb0 { status = "okay"; }; diff --git a/arch/arm/dts/uniphier-ph1-pro4.dtsi b/arch/arm/dts/uniphier-ph1-pro4.dtsi index 6637aeaa07..d5767b6252 100644 --- a/arch/arm/dts/uniphier-ph1-pro4.dtsi +++ b/arch/arm/dts/uniphier-ph1-pro4.dtsi @@ -343,6 +343,43 @@ clock-frequency = <400000>; }; + sd: sdhc@5a400000 { + compatible = "socionext,uniphier-sdhc"; + status = "disabled"; + reg = <0x5a400000 0x200>; + interrupts = <0 76 4>; + pinctrl-names = "default", "1.8v"; + pinctrl-0 = <&pinctrl_sd>; + pinctrl-1 = <&pinctrl_sd_1v8>; + clocks = <&mio 0>; + bus-width = <4>; + }; + + emmc: sdhc@5a500000 { + compatible = "socionext,uniphier-sdhc"; + status = "disabled"; + reg = <0x5a500000 0x200>; + interrupts = <0 78 4>; + pinctrl-names = "default", "1.8v"; + pinctrl-0 = <&pinctrl_emmc>; + pinctrl-1 = <&pinctrl_emmc_1v8>; + clocks = <&mio 1>; + bus-width = <8>; + non-removable; + }; + + sd1: sdhc@5a600000 { + compatible = "socionext,uniphier-sdhc"; + status = "disabled"; + reg = <0x5a600000 0x200>; + interrupts = <0 85 4>; + pinctrl-names = "default", "1.8v"; + pinctrl-0 = <&pinctrl_sd1>; + pinctrl-1 = <&pinctrl_sd1_1v8>; + clocks = <&mio 2>; + bus-width = <4>; + }; + usb2: usb@5a800100 { compatible = "socionext,uniphier-ehci", "generic-ehci"; status = "disabled"; diff --git a/arch/arm/dts/uniphier-ph1-pro5-4kbox.dts b/arch/arm/dts/uniphier-ph1-pro5-4kbox.dts index 02a3362e74..cbdc3ebbff 100644 --- a/arch/arm/dts/uniphier-ph1-pro5-4kbox.dts +++ b/arch/arm/dts/uniphier-ph1-pro5-4kbox.dts @@ -47,6 +47,14 @@ status = "okay"; }; +&emmc { + status = "okay"; +}; + +&sd { + status = "okay"; +}; + /* for U-Boot only */ / { soc { diff --git a/arch/arm/dts/uniphier-ph1-pro5.dtsi b/arch/arm/dts/uniphier-ph1-pro5.dtsi index 67a435e913..bd1b4b1b66 100644 --- a/arch/arm/dts/uniphier-ph1-pro5.dtsi +++ b/arch/arm/dts/uniphier-ph1-pro5.dtsi @@ -355,6 +355,30 @@ clock-frequency = <400000>; }; + emmc: sdhc@68400000 { + compatible = "socionext,uniphier-sdhc"; + status = "disabled"; + reg = <0x68400000 0x800>; + interrupts = <0 78 4>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_emmc>; + clocks = <&mio 1>; + bus-width = <8>; + non-removable; + }; + + sd: sdhc@68800000 { + compatible = "socionext,uniphier-sdhc"; + status = "disabled"; + reg = <0x68800000 0x800>; + interrupts = <0 76 4>; + pinctrl-names = "default", "1.8v"; + pinctrl-0 = <&pinctrl_sd>; + pinctrl-1 = <&pinctrl_sd_1v8>; + clocks = <&mio 0>; + bus-width = <4>; + }; + usb0: usb@65a00000 { compatible = "socionext,uniphier-xhci", "generic-xhci"; status = "disabled"; diff --git a/arch/arm/dts/uniphier-ph1-sld3-ref.dts b/arch/arm/dts/uniphier-ph1-sld3-ref.dts index ff17945e90..c7213c9ff4 100644 --- a/arch/arm/dts/uniphier-ph1-sld3-ref.dts +++ b/arch/arm/dts/uniphier-ph1-sld3-ref.dts @@ -52,6 +52,10 @@ status = "okay"; }; +&sd { + status = "okay"; +}; + &usb0 { status = "okay"; }; diff --git a/arch/arm/dts/uniphier-ph1-sld3.dtsi b/arch/arm/dts/uniphier-ph1-sld3.dtsi index 9a6ca575bd..789713db12 100644 --- a/arch/arm/dts/uniphier-ph1-sld3.dtsi +++ b/arch/arm/dts/uniphier-ph1-sld3.dtsi @@ -298,6 +298,25 @@ clocks = <&sysctrl 10>, <&sysctrl 18>; }; + emmc: sdhc@5a400000 { + compatible = "socionext,uniphier-sdhc"; + status = "disabled"; + reg = <0x5a400000 0x200>; + interrupts = <0 78 4>; + clocks = <&mio 1>; + bus-width = <8>; + non-removable; + }; + + sd: sdhc@5a500000 { + compatible = "socionext,uniphier-sdhc"; + status = "disabled"; + reg = <0x5a500000 0x200>; + interrupts = <0 76 4>; + clocks = <&mio 0>; + bus-width = <4>; + }; + usb0: usb@5a800100 { compatible = "socionext,uniphier-ehci", "generic-ehci"; status = "disabled"; diff --git a/arch/arm/dts/uniphier-ph1-sld8-ref.dts b/arch/arm/dts/uniphier-ph1-sld8-ref.dts index b5b6f65d36..ec5c5bdadc 100644 --- a/arch/arm/dts/uniphier-ph1-sld8-ref.dts +++ b/arch/arm/dts/uniphier-ph1-sld8-ref.dts @@ -51,6 +51,10 @@ status = "okay"; }; +&sd { + status = "okay"; +}; + &usb0 { status = "okay"; }; diff --git a/arch/arm/dts/uniphier-ph1-sld8.dtsi b/arch/arm/dts/uniphier-ph1-sld8.dtsi index 985848a027..61e0b45781 100644 --- a/arch/arm/dts/uniphier-ph1-sld8.dtsi +++ b/arch/arm/dts/uniphier-ph1-sld8.dtsi @@ -220,6 +220,31 @@ clock-frequency = <100000>; }; + sd: sdhc@5a400000 { + compatible = "socionext,uniphier-sdhc"; + status = "disabled"; + reg = <0x5a400000 0x200>; + interrupts = <0 76 4>; + pinctrl-names = "default", "1.8v"; + pinctrl-0 = <&pinctrl_sd>; + pinctrl-1 = <&pinctrl_sd_1v8>; + clocks = <&mio 0>; + bus-width = <4>; + }; + + emmc: sdhc@5a500000 { + compatible = "socionext,uniphier-sdhc"; + status = "disabled"; + interrupts = <0 78 4>; + reg = <0x5a500000 0x200>; + pinctrl-names = "default", "1.8v"; + pinctrl-0 = <&pinctrl_emmc>; + pinctrl-1 = <&pinctrl_emmc_1v8>; + clocks = <&mio 1>; + bus-width = <8>; + non-removable; + }; + usb0: usb@5a800100 { compatible = "socionext,uniphier-ehci", "generic-ehci"; status = "disabled"; diff --git a/arch/arm/dts/uniphier-pinctrl.dtsi b/arch/arm/dts/uniphier-pinctrl.dtsi index b1691d0679..494139a05d 100644 --- a/arch/arm/dts/uniphier-pinctrl.dtsi +++ b/arch/arm/dts/uniphier-pinctrl.dtsi @@ -12,6 +12,11 @@ function = "emmc"; }; + pinctrl_emmc_1v8: emmc_grp_1v8 { + groups = "emmc", "emmc_dat8"; + function = "emmc"; + }; + pinctrl_i2c0: i2c0_grp { groups = "i2c0"; function = "i2c0"; @@ -37,11 +42,21 @@ function = "sd"; }; + pinctrl_sd_1v8: sd_grp_1v8 { + groups = "sd"; + function = "sd"; + }; + pinctrl_sd1: sd1_grp { groups = "sd1"; function = "sd1"; }; + pinctrl_sd1_1v8: sd1_grp_1v8 { + groups = "sd1"; + function = "sd1"; + }; + pinctrl_uart0: uart0_grp { groups = "uart0"; function = "uart0"; diff --git a/arch/arm/dts/uniphier-proxstream2-gentil.dts b/arch/arm/dts/uniphier-proxstream2-gentil.dts index dc0def30fd..c3551fe7fa 100644 --- a/arch/arm/dts/uniphier-proxstream2-gentil.dts +++ b/arch/arm/dts/uniphier-proxstream2-gentil.dts @@ -52,6 +52,10 @@ status = "okay"; }; +&emmc { + status = "okay"; +}; + &usb0 { status = "okay"; }; diff --git a/arch/arm/dts/uniphier-proxstream2-vodka.dts b/arch/arm/dts/uniphier-proxstream2-vodka.dts index 3703ad36a5..d61e0b6ff9 100644 --- a/arch/arm/dts/uniphier-proxstream2-vodka.dts +++ b/arch/arm/dts/uniphier-proxstream2-vodka.dts @@ -41,6 +41,10 @@ status = "okay"; }; +&emmc { + status = "okay"; +}; + &usb0 { status = "okay"; }; diff --git a/arch/arm/dts/uniphier-proxstream2.dtsi b/arch/arm/dts/uniphier-proxstream2.dtsi index 21fad0cdee..12968bdd17 100644 --- a/arch/arm/dts/uniphier-proxstream2.dtsi +++ b/arch/arm/dts/uniphier-proxstream2.dtsi @@ -359,6 +359,30 @@ clock-frequency = <400000>; }; + emmc: sdhc@5a000000 { + compatible = "socionext,uniphier-sdhc"; + status = "disabled"; + reg = <0x5a000000 0x800>; + interrupts = <0 78 4>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_emmc>; + clocks = <&mio 1>; + bus-width = <8>; + non-removable; + }; + + sd: sdhc@5a400000 { + compatible = "socionext,uniphier-sdhc"; + status = "disabled"; + reg = <0x5a400000 0x800>; + interrupts = <0 76 4>; + pinctrl-names = "default", "1.8v"; + pinctrl-0 = <&pinctrl_sd>; + pinctrl-1 = <&pinctrl_sd_1v8>; + clocks = <&mio 0>; + bus-width = <4>; + }; + usb0: usb@65a00000 { compatible = "socionext,uniphier-xhci", "generic-xhci"; status = "disabled"; From a55d9feeec141bc5ec04cf84c86e270cf0ed0d3c Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 16 Feb 2016 17:08:39 +0900 Subject: [PATCH 09/38] ARM: uniphier: add eMMC boot support Export device nodes needed for eMMC boot (eMMC node, pinctrl, and clock) to the SPL DTB. CONFIG_SUPPORT_EMMC_BOOT is also necessary to use "mmc partconf" command. Signed-off-by: Masahiro Yamada --- arch/arm/dts/uniphier-ph1-pro4-sanji.dts | 12 ++++++++++ arch/arm/dts/uniphier-proxstream2-gentil.dts | 12 ++++++++++ arch/arm/dts/uniphier-proxstream2-vodka.dts | 12 ++++++++++ arch/arm/mach-uniphier/boot-mode/boot-mode.c | 25 ++++++++++++++++++++ include/configs/uniphier.h | 3 +++ 5 files changed, 64 insertions(+) diff --git a/arch/arm/dts/uniphier-ph1-pro4-sanji.dts b/arch/arm/dts/uniphier-ph1-pro4-sanji.dts index 1ca1042128..82e2bd02c7 100644 --- a/arch/arm/dts/uniphier-ph1-pro4-sanji.dts +++ b/arch/arm/dts/uniphier-ph1-pro4-sanji.dts @@ -95,6 +95,14 @@ u-boot,dm-pre-reloc; }; +&mio { + u-boot,dm-pre-reloc; +}; + +&emmc { + u-boot,dm-pre-reloc; +}; + &pinctrl { u-boot,dm-pre-reloc; }; @@ -102,3 +110,7 @@ &pinctrl_uart0 { u-boot,dm-pre-reloc; }; + +&pinctrl_emmc { + u-boot,dm-pre-reloc; +}; diff --git a/arch/arm/dts/uniphier-proxstream2-gentil.dts b/arch/arm/dts/uniphier-proxstream2-gentil.dts index c3551fe7fa..eb1d2bcc63 100644 --- a/arch/arm/dts/uniphier-proxstream2-gentil.dts +++ b/arch/arm/dts/uniphier-proxstream2-gentil.dts @@ -75,6 +75,14 @@ u-boot,dm-pre-reloc; }; +&mio { + u-boot,dm-pre-reloc; +}; + +&emmc { + u-boot,dm-pre-reloc; +}; + &pinctrl { u-boot,dm-pre-reloc; }; @@ -82,3 +90,7 @@ &pinctrl_uart2 { u-boot,dm-pre-reloc; }; + +&pinctrl_emmc { + u-boot,dm-pre-reloc; +}; diff --git a/arch/arm/dts/uniphier-proxstream2-vodka.dts b/arch/arm/dts/uniphier-proxstream2-vodka.dts index d61e0b6ff9..e7d5db8894 100644 --- a/arch/arm/dts/uniphier-proxstream2-vodka.dts +++ b/arch/arm/dts/uniphier-proxstream2-vodka.dts @@ -60,6 +60,14 @@ u-boot,dm-pre-reloc; }; +&mio { + u-boot,dm-pre-reloc; +}; + +&emmc { + u-boot,dm-pre-reloc; +}; + &pinctrl { u-boot,dm-pre-reloc; }; @@ -67,3 +75,7 @@ &pinctrl_uart2 { u-boot,dm-pre-reloc; }; + +&pinctrl_emmc { + u-boot,dm-pre-reloc; +}; diff --git a/arch/arm/mach-uniphier/boot-mode/boot-mode.c b/arch/arm/mach-uniphier/boot-mode/boot-mode.c index 935e551472..2f2e45d2c1 100644 --- a/arch/arm/mach-uniphier/boot-mode/boot-mode.c +++ b/arch/arm/mach-uniphier/boot-mode/boot-mode.c @@ -5,6 +5,7 @@ */ #include +#include #include #include "../sbc/sbc-regs.h" @@ -52,3 +53,27 @@ u32 spl_boot_device(void) return ret == BOOT_DEVICE_USB ? BOOT_DEVICE_NOR : ret; } + +u32 spl_boot_mode(void) +{ + 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/include/configs/uniphier.h b/include/configs/uniphier.h index 9d14155751..19dbfbbfc7 100644 --- a/include/configs/uniphier.h +++ b/include/configs/uniphier.h @@ -148,6 +148,7 @@ /* SD/MMC */ #define CONFIG_CMD_MMC +#define CONFIG_SUPPORT_EMMC_BOOT #define CONFIG_GENERIC_MMC /* memtest works on */ @@ -263,6 +264,7 @@ #define CONFIG_SPL_FRAMEWORK #define CONFIG_SPL_SERIAL_SUPPORT #define CONFIG_SPL_NAND_SUPPORT +#define CONFIG_SPL_MMC_SUPPORT #define CONFIG_SPL_LIBCOMMON_SUPPORT /* for mem_malloc_init */ #define CONFIG_SPL_LIBGENERIC_SUPPORT @@ -270,6 +272,7 @@ #define CONFIG_SPL_BOARD_INIT #define CONFIG_SYS_NAND_U_BOOT_OFFS 0x10000 +#define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR 0x80 #define CONFIG_SPL_MAX_FOOTPRINT 0x10000 From 569e4be172d1bf2041e97c0b65f872a7451b178a Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 16 Feb 2016 17:08:40 +0900 Subject: [PATCH 10/38] ARM: uniphier: add a command to find the first MMC (non-SD) device UniPhier SoC family supports both (e)MMC boot and SD card boot; however, both of them are handled in the same uclass. When booting from the eMMC, we want to know the device number of the (e)MMC, not SD. This command is useful to find the first MMC (non-SD) device. Signed-off-by: Masahiro Yamada --- arch/arm/mach-uniphier/boot-mode/boot-mode.c | 34 ++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/arch/arm/mach-uniphier/boot-mode/boot-mode.c b/arch/arm/mach-uniphier/boot-mode/boot-mode.c index 2f2e45d2c1..05477620a3 100644 --- a/arch/arm/mach-uniphier/boot-mode/boot-mode.c +++ b/arch/arm/mach-uniphier/boot-mode/boot-mode.c @@ -7,6 +7,7 @@ #include #include #include +#include #include "../sbc/sbc-regs.h" #include "../soc-info.h" @@ -77,3 +78,36 @@ u32 spl_boot_mode(void) 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; +} + +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\" enviroment", + "" +); +#endif From c231c4367ace6574e27ff0d1844d163fc471287b Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 16 Feb 2016 17:08:41 +0900 Subject: [PATCH 11/38] ARM: uniphier: add emmcupdate command The Boot ROM expects the boot image (SPL) in the Boot Partition 1. So, updating images involves the hardware partition switch. It might be a bit advanced for some users. To be user-friendly, this commit adds a useful command to update the images; just put SPL and U-Boot proper into the public directory of the TFTP server and execute "run emmcupdate" from the command line. Signed-off-by: Masahiro Yamada --- doc/README.uniphier | 14 ++++++++++++++ include/configs/uniphier.h | 7 +++++++ 2 files changed, 21 insertions(+) diff --git a/doc/README.uniphier b/doc/README.uniphier index c270ecb9a5..5ac52bd41f 100644 --- a/doc/README.uniphier +++ b/doc/README.uniphier @@ -78,6 +78,20 @@ directory, and then run the following command at the U-Boot command line: => run nandupdate +Burn U-Boot images to eMMC +-------------------------- + +Write two files to the Boot partition 1 of the eMMC device as follows: + - spl/u-boot-spl.bin at the offset address 0x00000000 + - u-boot.img at the offset address 0x00010000 + +If a TFTP server is available, the images can be easily updated. +Just copy the u-boot-spl-dtb.bin and u-boot-dtb.img to the TFTP public +directory, and then run the following command at the U-Boot command line: + + => run emmcupdate + + UniPhier specific commands -------------------------- diff --git a/include/configs/uniphier.h b/include/configs/uniphier.h index 19dbfbbfc7..1b28cdc1a9 100644 --- a/include/configs/uniphier.h +++ b/include/configs/uniphier.h @@ -233,6 +233,13 @@ "netdev=eth0\0" \ "verify=n\0" \ "nor_base=0x42000000\0" \ + "emmcupdate=mmcsetn &&" \ + "mmc partconf $mmc_first_dev 0 1 1 &&" \ + "mmc erase 0 800 &&" \ + "tftpboot u-boot-spl.bin &&" \ + "mmc write $loadaddr 0 80 &&" \ + "tftpboot u-boot.img &&" \ + "mmc write $loadaddr 80 780\0" \ "nandupdate=nand erase 0 0x00100000 &&" \ "tftpboot u-boot-spl.bin &&" \ "nand write $loadaddr 0 0x00010000 &&" \ From aa8a93480e072d8d0473e512b66c31f3c4cc3cc7 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 16 Feb 2016 17:08:42 +0900 Subject: [PATCH 12/38] ARM: uniphier: default to environment in eMMC Of the several boot devices supported, it looks like the eMMC is the most commonly used. Enable CONFIG_ENV_IS_IN_MMC by default. Signed-off-by: Masahiro Yamada --- arch/arm/mach-uniphier/boot-mode/boot-mode.c | 5 +++++ include/configs/uniphier.h | 12 ++++++------ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-uniphier/boot-mode/boot-mode.c b/arch/arm/mach-uniphier/boot-mode/boot-mode.c index 05477620a3..cf39bf57e9 100644 --- a/arch/arm/mach-uniphier/boot-mode/boot-mode.c +++ b/arch/arm/mach-uniphier/boot-mode/boot-mode.c @@ -93,6 +93,11 @@ static int find_first_mmc_device(void) 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; diff --git a/include/configs/uniphier.h b/include/configs/uniphier.h index 1b28cdc1a9..b1c8ccb7b9 100644 --- a/include/configs/uniphier.h +++ b/include/configs/uniphier.h @@ -99,16 +99,16 @@ #define CONFIG_CONS_INDEX 1 -/* - * For NAND booting the environment is embedded in the U-Boot image. Please take - * look at the file board/amcc/canyonlands/u-boot-nand.lds for details. - */ +/* #define CONFIG_ENV_IS_NOWHERE */ /* #define CONFIG_ENV_IS_IN_NAND */ -#define CONFIG_ENV_IS_NOWHERE +#define CONFIG_ENV_IS_IN_MMC +#define CONFIG_ENV_OFFSET 0x80000 #define CONFIG_ENV_SIZE 0x2000 -#define CONFIG_ENV_OFFSET 0x0 /* #define CONFIG_ENV_OFFSET_REDUND (CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE) */ +#define CONFIG_SYS_MMC_ENV_DEV 0 +#define CONFIG_SYS_MMC_ENV_PART 1 + /* Time clock 1MHz */ #define CONFIG_SYS_TIMER_RATE 1000000 From 8353266825d7b7d673519bce3a54cdddf2c3d459 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 14:21:33 +0900 Subject: [PATCH 13/38] ARM: uniphier: remove unused umc_polling() This function is unused. Signed-off-by: Masahiro Yamada --- arch/arm/mach-uniphier/dram/umc-regs.h | 9 --------- 1 file changed, 9 deletions(-) diff --git a/arch/arm/mach-uniphier/dram/umc-regs.h b/arch/arm/mach-uniphier/dram/umc-regs.h index a6957a4a51..b33e2da2bd 100644 --- a/arch/arm/mach-uniphier/dram/umc-regs.h +++ b/arch/arm/mach-uniphier/dram/umc-regs.h @@ -120,15 +120,6 @@ #include -static inline void umc_polling(u32 address, u32 expval, u32 mask) -{ - u32 nmask = ~mask; - u32 data; - do { - data = readl(address) & nmask; - } while (data != expval); -} - static inline void umc_dram_init_start(void __iomem *dramcont) { writel(0x00000002, dramcont + UMC_INITSET); From 46abfcc99e04efa75ed293bd871092c31d0f3be3 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 14:21:34 +0900 Subject: [PATCH 14/38] ARM: uniphier: rework struct uniphier_board_data This commit reworks "struct uniphier_board_data" with an array of DRAM channel data in it. It will allow further cleanups by means of "for" statements that iterate over the DDR channels. Signed-off-by: Masahiro Yamada --- arch/arm/mach-uniphier/bcu/bcu-ph1-ld4.c | 2 +- arch/arm/mach-uniphier/bcu/bcu-ph1-sld3.c | 2 +- arch/arm/mach-uniphier/boards.c | 176 +++++++++++------- arch/arm/mach-uniphier/dram/umc-ph1-ld4.c | 10 +- arch/arm/mach-uniphier/dram/umc-ph1-pro4.c | 16 +- arch/arm/mach-uniphier/dram/umc-ph1-sld8.c | 10 +- arch/arm/mach-uniphier/dram/umc-proxstream2.c | 12 +- arch/arm/mach-uniphier/init.h | 21 ++- .../mach-uniphier/memconf/memconf-ph1-sld3.c | 6 +- .../memconf/memconf-proxstream2.c | 6 +- arch/arm/mach-uniphier/memconf/memconf.c | 14 +- 11 files changed, 161 insertions(+), 114 deletions(-) diff --git a/arch/arm/mach-uniphier/bcu/bcu-ph1-ld4.c b/arch/arm/mach-uniphier/bcu/bcu-ph1-ld4.c index f82c7d1f8e..bbe8a74ce3 100644 --- a/arch/arm/mach-uniphier/bcu/bcu-ph1-ld4.c +++ b/arch/arm/mach-uniphier/bcu/bcu-ph1-ld4.c @@ -22,7 +22,7 @@ int ph1_ld4_bcu_init(const struct uniphier_board_data *bd) writel(0x11111111, BCSCR5); /* 0xe0000000-0Xffffffff: IPPC/IPPD-bus */ /* Specify DDR channel */ - shift = (bd->dram_ch1_base - bd->dram_ch0_base) / 0x04000000 * 4; + shift = (bd->dram_ch[1].base - bd->dram_ch[0].base) / 0x04000000 * 4; writel(ch(shift), BCIPPCCHR2); /* 0x80000000-0x9fffffff */ shift -= 32; diff --git a/arch/arm/mach-uniphier/bcu/bcu-ph1-sld3.c b/arch/arm/mach-uniphier/bcu/bcu-ph1-sld3.c index 75ccd155b0..b7497e9e57 100644 --- a/arch/arm/mach-uniphier/bcu/bcu-ph1-sld3.c +++ b/arch/arm/mach-uniphier/bcu/bcu-ph1-sld3.c @@ -26,7 +26,7 @@ int ph1_sld3_bcu_init(const struct uniphier_board_data *bd) writel(0x24440000, BCSCR5); /* Specify DDR channel */ - shift = (bd->dram_ch1_base - bd->dram_ch0_base) / 0x04000000 * 4; + shift = (bd->dram_ch[1].base - bd->dram_ch[0].base) / 0x04000000 * 4; writel(ch(shift), BCIPPCCHR2); /* 0x80000000-0x9fffffff */ shift -= 32; diff --git a/arch/arm/mach-uniphier/boards.c b/arch/arm/mach-uniphier/boards.c index d70c712206..05b7c7612e 100644 --- a/arch/arm/mach-uniphier/boards.c +++ b/arch/arm/mach-uniphier/boards.c @@ -14,106 +14,152 @@ DECLARE_GLOBAL_DATA_PTR; #if defined(CONFIG_ARCH_UNIPHIER_PH1_SLD3) static const struct uniphier_board_data ph1_sld3_data = { - .dram_ch0_base = 0x80000000, - .dram_ch0_size = 0x20000000, - .dram_ch0_width = 32, - .dram_ch1_base = 0xc0000000, - .dram_ch1_size = 0x20000000, - .dram_ch1_width = 16, - .dram_ch2_base = 0xc0000000, - .dram_ch2_size = 0x10000000, - .dram_ch2_width = 16, - .dram_freq = 1600, + .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, + }, }; #endif #if defined(CONFIG_ARCH_UNIPHIER_PH1_LD4) static const struct uniphier_board_data ph1_ld4_data = { - .dram_ch0_base = 0x80000000, - .dram_ch0_size = 0x10000000, - .dram_ch0_width = 16, - .dram_ch1_base = 0x90000000, - .dram_ch1_size = 0x10000000, - .dram_ch1_width = 16, - .dram_freq = 1600, + .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, + }, }; #endif #if defined(CONFIG_ARCH_UNIPHIER_PH1_PRO4) /* 1GB RAM board */ static const struct uniphier_board_data ph1_pro4_data = { - .dram_ch0_base = 0x80000000, - .dram_ch0_size = 0x20000000, - .dram_ch0_width = 32, - .dram_ch1_base = 0xa0000000, - .dram_ch1_size = 0x20000000, - .dram_ch1_width = 32, - .dram_freq = 1600, + .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, + }, }; /* 2GB RAM board */ static const struct uniphier_board_data ph1_pro4_2g_data = { - .dram_ch0_base = 0x80000000, - .dram_ch0_size = 0x40000000, - .dram_ch0_width = 32, - .dram_ch1_base = 0xc0000000, - .dram_ch1_size = 0x40000000, - .dram_ch1_width = 32, - .dram_freq = 1600, + .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, + }, }; #endif #if defined(CONFIG_ARCH_UNIPHIER_PH1_SLD8) static const struct uniphier_board_data ph1_sld8_data = { - .dram_ch0_base = 0x80000000, - .dram_ch0_size = 0x10000000, - .dram_ch0_width = 16, - .dram_ch1_base = 0x90000000, - .dram_ch1_size = 0x10000000, - .dram_ch1_width = 16, - .dram_freq = 1333, + .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, + }, }; #endif #if defined(CONFIG_ARCH_UNIPHIER_PH1_PRO5) static const struct uniphier_board_data ph1_pro5_data = { - .dram_ch0_base = 0x80000000, - .dram_ch0_size = 0x20000000, - .dram_ch0_width = 32, - .dram_ch1_base = 0xa0000000, - .dram_ch1_size = 0x20000000, - .dram_ch1_width = 32, - .dram_freq = 1866, + .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, + }, }; #endif #if defined(CONFIG_ARCH_UNIPHIER_PROXSTREAM2) static const struct uniphier_board_data proxstream2_data = { - .dram_ch0_base = 0x80000000, - .dram_ch0_size = 0x40000000, - .dram_ch0_width = 32, - .dram_ch1_base = 0xc0000000, - .dram_ch1_size = 0x20000000, - .dram_ch1_width = 32, - .dram_ch2_base = 0xe0000000, - .dram_ch2_size = 0x20000000, - .dram_ch2_width = 16, - .dram_freq = 2133, + .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, + }, }; #endif #if defined(CONFIG_ARCH_UNIPHIER_PH1_LD6B) static const struct uniphier_board_data ph1_ld6b_data = { - .dram_ch0_base = 0x80000000, - .dram_ch0_size = 0x40000000, - .dram_ch0_width = 32, - .dram_ch1_base = 0xc0000000, - .dram_ch1_size = 0x20000000, - .dram_ch1_width = 32, - .dram_ch2_base = 0xe0000000, - .dram_ch2_size = 0x20000000, - .dram_ch2_width = 16, - .dram_freq = 1866, + .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, + }, }; #endif diff --git a/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c b/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c index ffd7aa97b2..f2889c0f49 100644 --- a/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c +++ b/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c @@ -162,13 +162,13 @@ static int umc_init_sub(int freq, int size_ch0, int size_ch1) int ph1_ld4_umc_init(const struct uniphier_board_data *bd) { - if ((bd->dram_ch0_size == SZ_128M || bd->dram_ch0_size == SZ_256M) && - (bd->dram_ch1_size == SZ_128M || bd->dram_ch1_size == SZ_256M) && + if ((bd->dram_ch[0].size == SZ_128M || bd->dram_ch[0].size == SZ_256M) && + (bd->dram_ch[1].size == SZ_128M || bd->dram_ch[1].size == SZ_256M) && (bd->dram_freq == 1333 || bd->dram_freq == 1600) && - bd->dram_ch0_width == 16 && bd->dram_ch1_width == 16) { + bd->dram_ch[0].width == 16 && bd->dram_ch[1].width == 16) { return umc_init_sub(bd->dram_freq, - bd->dram_ch0_size / SZ_128M, - bd->dram_ch1_size / SZ_128M); + bd->dram_ch[0].size / SZ_128M, + bd->dram_ch[1].size / SZ_128M); } else { pr_err("Unsupported DDR configuration\n"); return -EINVAL; diff --git a/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c b/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c index 261f7cfce7..16c82645c4 100644 --- a/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c +++ b/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c @@ -146,39 +146,39 @@ int ph1_pro4_umc_init(const struct uniphier_board_data *bd) writel(0x00000101, dramcont0 + UMC_DIOCTLA); - ph1_pro4_ddrphy_init(phy0_0, bd->dram_freq, bd->dram_ch0_size); + ph1_pro4_ddrphy_init(phy0_0, bd->dram_freq, bd->dram_ch[0].size); ddrphy_prepare_training(phy0_0, 0); ddrphy_training(phy0_0); writel(0x00000103, dramcont0 + UMC_DIOCTLA); - ph1_pro4_ddrphy_init(phy0_1, bd->dram_freq, bd->dram_ch0_size); + ph1_pro4_ddrphy_init(phy0_1, bd->dram_freq, bd->dram_ch[0].size); ddrphy_prepare_training(phy0_1, 1); ddrphy_training(phy0_1); writel(0x00000101, dramcont1 + UMC_DIOCTLA); - ph1_pro4_ddrphy_init(phy1_0, bd->dram_freq, bd->dram_ch1_size); + ph1_pro4_ddrphy_init(phy1_0, bd->dram_freq, bd->dram_ch[1].size); ddrphy_prepare_training(phy1_0, 0); ddrphy_training(phy1_0); writel(0x00000103, dramcont1 + UMC_DIOCTLA); - ph1_pro4_ddrphy_init(phy1_1, bd->dram_freq, bd->dram_ch1_size); + ph1_pro4_ddrphy_init(phy1_1, bd->dram_freq, bd->dram_ch[1].size); ddrphy_prepare_training(phy1_1, 1); ddrphy_training(phy1_1); - ret = umc_dramcont_init(dramcont0, ca_base0, bd->dram_ch0_size, - bd->dram_ch0_width); + ret = umc_dramcont_init(dramcont0, ca_base0, bd->dram_ch[0].size, + bd->dram_ch[0].width); if (ret) return ret; - ret = umc_dramcont_init(dramcont1, ca_base1, bd->dram_ch1_size, - bd->dram_ch1_width); + ret = umc_dramcont_init(dramcont1, ca_base1, bd->dram_ch[1].size, + bd->dram_ch[1].width); if (ret) return ret; diff --git a/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c b/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c index 09f9ccfb43..3c2724eb37 100644 --- a/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c +++ b/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c @@ -142,13 +142,13 @@ static int umc_init_sub(int freq, int size_ch0, int size_ch1) int ph1_sld8_umc_init(const struct uniphier_board_data *bd) { - if ((bd->dram_ch0_size == SZ_128M || bd->dram_ch0_size == SZ_256M) && - (bd->dram_ch1_size == SZ_128M || bd->dram_ch1_size == SZ_256M) && + if ((bd->dram_ch[0].size == SZ_128M || bd->dram_ch[0].size == SZ_256M) && + (bd->dram_ch[1].size == SZ_128M || bd->dram_ch[1].size == SZ_256M) && bd->dram_freq == 1333 && - bd->dram_ch0_width == 16 && bd->dram_ch1_width == 16) { + bd->dram_ch[0].width == 16 && bd->dram_ch[1].width == 16) { return umc_init_sub(bd->dram_freq, - bd->dram_ch0_size / SZ_128M, - bd->dram_ch1_size / SZ_128M); + bd->dram_ch[0].size / SZ_128M, + bd->dram_ch[1].size / SZ_128M); } else { pr_err("Unsupported DDR configuration\n"); return -EINVAL; diff --git a/arch/arm/mach-uniphier/dram/umc-proxstream2.c b/arch/arm/mach-uniphier/dram/umc-proxstream2.c index 6e7fa885c4..6e6fff98e8 100644 --- a/arch/arm/mach-uniphier/dram/umc-proxstream2.c +++ b/arch/arm/mach-uniphier/dram/umc-proxstream2.c @@ -603,22 +603,22 @@ int proxstream2_umc_init(const struct uniphier_board_data *bd) return -EINVAL; } - ret = umc_init(umc_ch0_base, freq, 0, bd->dram_ch0_size / SZ_256M, - bd->dram_ch0_width); + ret = umc_init(umc_ch0_base, freq, 0, bd->dram_ch[0].size / SZ_256M, + bd->dram_ch[0].width); if (ret) { printf("failed to initialize UMC ch0\n"); return ret; } - ret = umc_init(umc_ch1_base, freq, 1, bd->dram_ch1_size / SZ_256M, - bd->dram_ch1_width); + ret = umc_init(umc_ch1_base, freq, 1, bd->dram_ch[1].size / SZ_256M, + bd->dram_ch[1].width); if (ret) { printf("failed to initialize UMC ch1\n"); return ret; } - ret = umc_init(umc_ch2_base, freq, 2, bd->dram_ch2_size / SZ_256M, - bd->dram_ch2_width); + ret = umc_init(umc_ch2_base, freq, 2, bd->dram_ch[2].size / SZ_256M, + bd->dram_ch[2].width); if (ret) { printf("failed to initialize UMC ch2\n"); return ret; diff --git a/arch/arm/mach-uniphier/init.h b/arch/arm/mach-uniphier/init.h index 0a47e70dcf..aabd84a8ed 100644 --- a/arch/arm/mach-uniphier/init.h +++ b/arch/arm/mach-uniphier/init.h @@ -7,17 +7,18 @@ #ifndef __MACH_INIT_H #define __MACH_INIT_H +#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 long dram_ch0_base; - unsigned long dram_ch0_size; - unsigned long dram_ch0_width; - unsigned long dram_ch1_base; - unsigned long dram_ch1_size; - unsigned long dram_ch1_width; - unsigned long dram_ch2_base; - unsigned long dram_ch2_size; - unsigned long dram_ch2_width; - unsigned int dram_freq; + unsigned int dram_freq; + unsigned int dram_nr_ch; + struct uniphier_dram_ch dram_ch[UNIPHIER_MAX_NR_DRAM_CH]; }; const struct uniphier_board_data *uniphier_get_board_param(void); diff --git a/arch/arm/mach-uniphier/memconf/memconf-ph1-sld3.c b/arch/arm/mach-uniphier/memconf/memconf-ph1-sld3.c index 9718cc560f..6fdf910895 100644 --- a/arch/arm/mach-uniphier/memconf/memconf-ph1-sld3.c +++ b/arch/arm/mach-uniphier/memconf/memconf-ph1-sld3.c @@ -21,14 +21,14 @@ int ph1_sld3_memconf_init(const struct uniphier_board_data *bd) tmp &= ~(SG_MEMCONF_CH2_SZ_MASK | SG_MEMCONF_CH2_NUM_MASK); - switch (bd->dram_ch2_width) { + switch (bd->dram_ch[2].width) { case 16: tmp |= SG_MEMCONF_CH2_NUM_1; - size_per_word = bd->dram_ch2_size; + size_per_word = bd->dram_ch[2].size; break; case 32: tmp |= SG_MEMCONF_CH2_NUM_2; - size_per_word = bd->dram_ch2_size >> 1; + size_per_word = bd->dram_ch[2].size >> 1; break; default: pr_err("error: unsupported DRAM Ch2 width\n"); diff --git a/arch/arm/mach-uniphier/memconf/memconf-proxstream2.c b/arch/arm/mach-uniphier/memconf/memconf-proxstream2.c index 9a91fb33ef..c47fe0ae53 100644 --- a/arch/arm/mach-uniphier/memconf/memconf-proxstream2.c +++ b/arch/arm/mach-uniphier/memconf/memconf-proxstream2.c @@ -21,14 +21,14 @@ int proxstream2_memconf_init(const struct uniphier_board_data *bd) tmp &= ~(SG_MEMCONF_CH2_SZ_MASK | SG_MEMCONF_CH2_NUM_MASK); - switch (bd->dram_ch2_width) { + switch (bd->dram_ch[2].width) { case 16: tmp |= SG_MEMCONF_CH2_NUM_1; - size_per_word = bd->dram_ch2_size; + size_per_word = bd->dram_ch[2].size; break; case 32: tmp |= SG_MEMCONF_CH2_NUM_2; - size_per_word = bd->dram_ch2_size >> 1; + size_per_word = bd->dram_ch[2].size >> 1; break; default: pr_err("error: unsupported DRAM Ch2 width\n"); diff --git a/arch/arm/mach-uniphier/memconf/memconf.c b/arch/arm/mach-uniphier/memconf/memconf.c index f2a0eaf3f5..3d4b50456b 100644 --- a/arch/arm/mach-uniphier/memconf/memconf.c +++ b/arch/arm/mach-uniphier/memconf/memconf.c @@ -21,14 +21,14 @@ int memconf_init(const struct uniphier_board_data *bd) tmp &= ~(SG_MEMCONF_CH0_SZ_MASK | SG_MEMCONF_CH0_NUM_MASK); - switch (bd->dram_ch0_width) { + switch (bd->dram_ch[0].width) { case 16: tmp |= SG_MEMCONF_CH0_NUM_1; - size_per_word = bd->dram_ch0_size; + size_per_word = bd->dram_ch[0].size; break; case 32: tmp |= SG_MEMCONF_CH0_NUM_2; - size_per_word = bd->dram_ch0_size >> 1; + size_per_word = bd->dram_ch[0].size >> 1; break; default: pr_err("error: unsupported DRAM Ch0 width\n"); @@ -59,14 +59,14 @@ int memconf_init(const struct uniphier_board_data *bd) tmp &= ~(SG_MEMCONF_CH1_SZ_MASK | SG_MEMCONF_CH1_NUM_MASK); - switch (bd->dram_ch1_width) { + switch (bd->dram_ch[1].width) { case 16: tmp |= SG_MEMCONF_CH1_NUM_1; - size_per_word = bd->dram_ch1_size; + size_per_word = bd->dram_ch[1].size; break; case 32: tmp |= SG_MEMCONF_CH1_NUM_2; - size_per_word = bd->dram_ch1_size >> 1; + size_per_word = bd->dram_ch[1].size >> 1; break; default: pr_err("error: unsupported DRAM Ch1 width\n"); @@ -94,7 +94,7 @@ int memconf_init(const struct uniphier_board_data *bd) return -EINVAL; } - if (bd->dram_ch0_base + bd->dram_ch0_size < bd->dram_ch1_base) + if (bd->dram_ch[0].base + bd->dram_ch[0].size < bd->dram_ch[1].base) tmp |= SG_MEMCONF_SPARSEMEM; else tmp &= ~SG_MEMCONF_SPARSEMEM; From 59fe23c2e0bc442c9344852425155f0d683e217c Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 14:21:35 +0900 Subject: [PATCH 15/38] ARM: uniphier: optimize ProXstream2 UMC init code with "for" loop Now this code can be re-written with a "for" statement instead of calling the same function multiple times. Signed-off-by: Masahiro Yamada --- arch/arm/mach-uniphier/dram/umc-proxstream2.c | 33 +++++++------------ 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/arch/arm/mach-uniphier/dram/umc-proxstream2.c b/arch/arm/mach-uniphier/dram/umc-proxstream2.c index 6e6fff98e8..dca34ba78b 100644 --- a/arch/arm/mach-uniphier/dram/umc-proxstream2.c +++ b/arch/arm/mach-uniphier/dram/umc-proxstream2.c @@ -585,11 +585,9 @@ static void um_init(void __iomem *um_base) int proxstream2_umc_init(const struct uniphier_board_data *bd) { void __iomem *um_base = (void __iomem *)0x5b600000; - void __iomem *umc_ch0_base = (void __iomem *)0x5b800000; - void __iomem *umc_ch1_base = (void __iomem *)0x5ba00000; - void __iomem *umc_ch2_base = (void __iomem *)0x5bc00000; + void __iomem *umc_ch_base = (void __iomem *)0x5b800000; enum dram_freq freq; - int ret; + int ch, ret; switch (bd->dram_freq) { case 1866: @@ -603,25 +601,16 @@ int proxstream2_umc_init(const struct uniphier_board_data *bd) return -EINVAL; } - ret = umc_init(umc_ch0_base, freq, 0, bd->dram_ch[0].size / SZ_256M, - bd->dram_ch[0].width); - if (ret) { - printf("failed to initialize UMC ch0\n"); - return ret; - } + for (ch = 0; ch < bd->dram_nr_ch; ch++) { + ret = umc_init(umc_ch_base, freq, ch, + bd->dram_ch[ch].size / SZ_256M, + bd->dram_ch[ch].width); + if (ret) { + printf("failed to initialize UMC ch%d\n", ch); + return ret; + } - ret = umc_init(umc_ch1_base, freq, 1, bd->dram_ch[1].size / SZ_256M, - bd->dram_ch[1].width); - if (ret) { - printf("failed to initialize UMC ch1\n"); - return ret; - } - - ret = umc_init(umc_ch2_base, freq, 2, bd->dram_ch[2].size / SZ_256M, - bd->dram_ch[2].width); - if (ret) { - printf("failed to initialize UMC ch2\n"); - return ret; + umc_ch_base += 0x00200000; } um_init(um_base); From a54c879a423959b475f6f67c4cbf1c744e08849a Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 14:21:36 +0900 Subject: [PATCH 16/38] ARM: uniphier: use pr_err() where possible Signed-off-by: Masahiro Yamada --- arch/arm/mach-uniphier/dram/umc-ph1-pro4.c | 2 +- arch/arm/mach-uniphier/dram/umc-proxstream2.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c b/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c index 16c82645c4..ff988e3540 100644 --- a/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c +++ b/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c @@ -82,7 +82,7 @@ static int umc_dramcont_init(void __iomem *dramcont, void __iomem *ca_base, dram_size = DRAM_SZ_512M; break; default: - printf("unsupported DRAM size\n"); + pr_err("unsupported DRAM size\n"); return -EINVAL; } diff --git a/arch/arm/mach-uniphier/dram/umc-proxstream2.c b/arch/arm/mach-uniphier/dram/umc-proxstream2.c index dca34ba78b..d98765b2ac 100644 --- a/arch/arm/mach-uniphier/dram/umc-proxstream2.c +++ b/arch/arm/mach-uniphier/dram/umc-proxstream2.c @@ -344,7 +344,7 @@ static int __ddrphy_training(void __iomem *phy_base, do { if (--timeout < 0) { - printf("%s: error: timeout during DDR training\n", + pr_err("%s: error: timeout during DDR training\n", __func__); return -ETIMEDOUT; } @@ -354,7 +354,7 @@ static int __ddrphy_training(void __iomem *phy_base, for (s = seq; s->description; s++) { if (pgsr0 & s->err_flag) { - printf("%s: error: %s failed\n", __func__, + pr_err("%s: error: %s failed\n", __func__, s->description); return -EIO; } @@ -597,7 +597,7 @@ int proxstream2_umc_init(const struct uniphier_board_data *bd) freq = FREQ_2133M; break; default: - printf("unsupported DRAM frequency %d MHz\n", bd->dram_freq); + pr_err("unsupported DRAM frequency %d MHz\n", bd->dram_freq); return -EINVAL; } @@ -606,7 +606,7 @@ int proxstream2_umc_init(const struct uniphier_board_data *bd) bd->dram_ch[ch].size / SZ_256M, bd->dram_ch[ch].width); if (ret) { - printf("failed to initialize UMC ch%d\n", ch); + pr_err("failed to initialize UMC ch%d\n", ch); return ret; } From 94b756f3318b5dea3c1aefa670f43ae85d780144 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 14:21:37 +0900 Subject: [PATCH 17/38] ARM: uniphier: refactor UMC init code for ProXstream2 Currently, a dummy value is defined for the UMC_SPCCTLA register when the DRAM size is zero. This seems weird because the controller does not need setting in the first place if the size is zero. Also, redefine enum dram_size to represent the DRAM size per 16-bit unit. This makes things simpler because the channel 0 and 1 are connected with 32-bit width DRAM, while the channel 2 is connected with 16-bit width one. I am renaming SIZE_* into DRAM_SZ_* (and also FREQ_* to DRAM_FREQ_* for consistency) while I am here because SIZE_* might be easily mixed-up with the macros in include/linux/sizes.h. Signed-off-by: Masahiro Yamada --- arch/arm/mach-uniphier/dram/umc-proxstream2.c | 109 ++++++++++-------- 1 file changed, 64 insertions(+), 45 deletions(-) diff --git a/arch/arm/mach-uniphier/dram/umc-proxstream2.c b/arch/arm/mach-uniphier/dram/umc-proxstream2.c index d98765b2ac..86909062b6 100644 --- a/arch/arm/mach-uniphier/dram/umc-proxstream2.c +++ b/arch/arm/mach-uniphier/dram/umc-proxstream2.c @@ -18,46 +18,45 @@ #include "ddrmphy-regs.h" #include "umc-regs.h" -#define CH_NR 3 +#define DRAM_CH_NR 3 enum dram_freq { - FREQ_1866M, - FREQ_2133M, - FREQ_NR, + DRAM_FREQ_1866M, + DRAM_FREQ_2133M, + DRAM_FREQ_NR, }; enum dram_size { - SIZE_0, - SIZE_512M, - SIZE_1G, - SIZE_NR, + DRAM_SZ_256M, + DRAM_SZ_512M, + DRAM_SZ_NR, }; -static u32 ddrphy_pgcr2[FREQ_NR] = {0x00FC7E5D, 0x00FC90AB}; -static u32 ddrphy_ptr0[FREQ_NR] = {0x0EA09205, 0x10C0A6C6}; -static u32 ddrphy_ptr1[FREQ_NR] = {0x0DAC041B, 0x0FA104B1}; -static u32 ddrphy_ptr3[FREQ_NR] = {0x15171e45, 0x18182357}; -static u32 ddrphy_ptr4[FREQ_NR] = {0x0e9ad8e9, 0x10b34157}; -static u32 ddrphy_dtpr0[FREQ_NR] = {0x35a00d88, 0x39e40e88}; -static u32 ddrphy_dtpr1[FREQ_NR] = {0x2288cc2c, 0x228a04d0}; -static u32 ddrphy_dtpr2[FREQ_NR] = {0x50005e00, 0x50006a00}; -static u32 ddrphy_dtpr3[FREQ_NR] = {0x0010cb49, 0x0010ec89}; -static u32 ddrphy_mr0[FREQ_NR] = {0x00000115, 0x00000125}; -static u32 ddrphy_mr2[FREQ_NR] = {0x000002a0, 0x000002a8}; +static u32 ddrphy_pgcr2[DRAM_FREQ_NR] = {0x00FC7E5D, 0x00FC90AB}; +static u32 ddrphy_ptr0[DRAM_FREQ_NR] = {0x0EA09205, 0x10C0A6C6}; +static u32 ddrphy_ptr1[DRAM_FREQ_NR] = {0x0DAC041B, 0x0FA104B1}; +static u32 ddrphy_ptr3[DRAM_FREQ_NR] = {0x15171e45, 0x18182357}; +static u32 ddrphy_ptr4[DRAM_FREQ_NR] = {0x0e9ad8e9, 0x10b34157}; +static u32 ddrphy_dtpr0[DRAM_FREQ_NR] = {0x35a00d88, 0x39e40e88}; +static u32 ddrphy_dtpr1[DRAM_FREQ_NR] = {0x2288cc2c, 0x228a04d0}; +static u32 ddrphy_dtpr2[DRAM_FREQ_NR] = {0x50005e00, 0x50006a00}; +static u32 ddrphy_dtpr3[DRAM_FREQ_NR] = {0x0010cb49, 0x0010ec89}; +static u32 ddrphy_mr0[DRAM_FREQ_NR] = {0x00000115, 0x00000125}; +static u32 ddrphy_mr2[DRAM_FREQ_NR] = {0x000002a0, 0x000002a8}; /* dependent on package and board design */ -static u32 ddrphy_acbdlr0[CH_NR] = {0x0000000c, 0x0000000c, 0x00000009}; +static u32 ddrphy_acbdlr0[DRAM_CH_NR] = {0x0000000c, 0x0000000c, 0x00000009}; -static u32 umc_cmdctla[FREQ_NR] = {0x66DD131D, 0x77EE1722}; +static u32 umc_cmdctla[DRAM_FREQ_NR] = {0x66DD131D, 0x77EE1722}; /* * The ch2 is a different generation UMC core. * The register spec is different, unfortunately. */ -static u32 umc_cmdctlb_ch01[FREQ_NR] = {0x13E87C44, 0x18F88C44}; -static u32 umc_cmdctlb_ch2[FREQ_NR] = {0x19E8DC44, 0x1EF8EC44}; -static u32 umc_spcctla[FREQ_NR][SIZE_NR] = { - {0x00000000, 0x004A071D, 0x0078071D}, - {0x00000000, 0x0055081E, 0x0089081E}, +static u32 umc_cmdctlb_ch01[DRAM_FREQ_NR] = {0x13E87C44, 0x18F88C44}; +static u32 umc_cmdctlb_ch2[DRAM_FREQ_NR] = {0x19E8DC44, 0x1EF8EC44}; +static u32 umc_spcctla[DRAM_FREQ_NR][DRAM_SZ_NR] = { + {0x004A071D, 0x0078071D}, + {0x0055081E, 0x0089081E}, }; static u32 umc_spcctlb[] = {0x00FF000A, 0x00FF000B}; @@ -459,18 +458,34 @@ static void umc_ud_init(void __iomem *umc_base, int ch) writel(0x00000033, umc_base + UMC_PAIR1DOFF_D0); } -static void umc_dc_init(void __iomem *umc_dc_base, enum dram_freq freq, - enum dram_size size, int ch, int width) +static int umc_dc_init(void __iomem *umc_dc_base, enum dram_freq freq, + unsigned long size, int width, int ch) { + enum dram_size size_e; int latency; u32 val; + switch (size) { + case 0: + return 0; + case SZ_256M: + size_e = DRAM_SZ_256M; + break; + case SZ_512M: + size_e = DRAM_SZ_512M; + break; + default: + pr_err("unsupported DRAM size 0x%08lx (per 16bit) for ch%d\n", + size, ch); + return -EINVAL; + } + writel(umc_cmdctla[freq], umc_dc_base + UMC_CMDCTLA); writel(ch == 2 ? umc_cmdctlb_ch2[freq] : umc_cmdctlb_ch01[freq], umc_dc_base + UMC_CMDCTLB); - writel(umc_spcctla[freq][size / (width / 16)], + writel(umc_spcctla[freq][size_e], umc_dc_base + UMC_SPCCTLA); writel(umc_spcctlb[freq], umc_dc_base + UMC_SPCCTLB); @@ -519,13 +534,15 @@ static void umc_dc_init(void __iomem *umc_dc_base, enum dram_freq freq, writel(0x00000000, umc_dc_base + UMC_ERRMASKA); writel(0x00000000, umc_dc_base + UMC_ERRMASKB); + + return 0; } -static int umc_init(void __iomem *umc_base, enum dram_freq freq, int ch, - enum dram_size size, int width) +static int umc_ch_init(void __iomem *umc_ch_base, enum dram_freq freq, + unsigned long size, unsigned int width, int ch) { - void __iomem *umc_dc_base = umc_base + 0x00011000; - void __iomem *phy_base = umc_base + 0x00030000; + void __iomem *umc_dc_base = umc_ch_base + 0x00011000; + void __iomem *phy_base = umc_ch_base + 0x00030000; int ret; writel(0x00000002, umc_dc_base + UMC_INITSET); @@ -546,15 +563,15 @@ static int umc_init(void __iomem *umc_base, enum dram_freq freq, int ch, if (ret) return ret; - umc_dc_init(umc_dc_base, freq, size, ch, width); + ret = umc_dc_init(umc_dc_base, freq, size, width, ch); + if (ret) + return ret; - umc_ud_init(umc_base, ch); + umc_ud_init(umc_ch_base, ch); - if (size) { - ret = ddrphy_training(phy_base); - if (ret) - return ret; - } + ret = ddrphy_training(phy_base); + if (ret) + return ret; udelay(1); @@ -591,10 +608,10 @@ int proxstream2_umc_init(const struct uniphier_board_data *bd) switch (bd->dram_freq) { case 1866: - freq = FREQ_1866M; + freq = DRAM_FREQ_1866M; break; case 2133: - freq = FREQ_2133M; + freq = DRAM_FREQ_2133M; break; default: pr_err("unsupported DRAM frequency %d MHz\n", bd->dram_freq); @@ -602,9 +619,11 @@ int proxstream2_umc_init(const struct uniphier_board_data *bd) } for (ch = 0; ch < bd->dram_nr_ch; ch++) { - ret = umc_init(umc_ch_base, freq, ch, - bd->dram_ch[ch].size / SZ_256M, - bd->dram_ch[ch].width); + 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; From 00dd3f6ab068276f8baa409e9317fbf466187a34 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 14:21:38 +0900 Subject: [PATCH 18/38] ARM: uniphier: remove UMC_INITCTL* and UMC_DRMR* settings These settings were used only for the PH1-sLD3 and older SoCs. The PH1-LD4 and newer one just ignore them because their DDR-PHY take care of such timing parameters instead. Signed-off-by: Masahiro Yamada --- arch/arm/mach-uniphier/dram/umc-ph1-ld4.c | 27 ---------------------- arch/arm/mach-uniphier/dram/umc-ph1-pro4.c | 8 ------- arch/arm/mach-uniphier/dram/umc-ph1-sld8.c | 18 --------------- arch/arm/mach-uniphier/dram/umc-regs.h | 7 ------ 4 files changed, 60 deletions(-) diff --git a/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c b/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c index f2889c0f49..638aa11d0d 100644 --- a/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c +++ b/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c @@ -53,38 +53,11 @@ static void umc_dramcont_init(void __iomem *dramcont, void __iomem *ca_base, if (freq == 1333) { writel(0x45990b11, dramcont + UMC_CMDCTLA); writel(0x16958924, dramcont + UMC_CMDCTLB); - writel(0x5101046A, dramcont + UMC_INITCTLA); - - if (size == 1) - writel(0x27028B0A, dramcont + UMC_INITCTLB); - else if (size == 2) - writel(0x38028B0A, dramcont + UMC_INITCTLB); - - writel(0x000FF0FF, dramcont + UMC_INITCTLC); - writel(0x00000b51, dramcont + UMC_DRMMR0); } else if (freq == 1600) { writel(0x36BB0F17, dramcont + UMC_CMDCTLA); writel(0x18C6AA24, dramcont + UMC_CMDCTLB); - writel(0x5101387F, dramcont + UMC_INITCTLA); - - if (size == 1) - writel(0x2F030D3F, dramcont + UMC_INITCTLB); - else if (size == 2) - writel(0x43030D3F, dramcont + UMC_INITCTLB); - - writel(0x00FF00FF, dramcont + UMC_INITCTLC); - writel(0x00000d71, dramcont + UMC_DRMMR0); } - writel(0x00000006, dramcont + UMC_DRMMR1); - - if (freq == 1333) - writel(0x00000290, dramcont + UMC_DRMMR2); - else if (freq == 1600) - writel(0x00000298, dramcont + UMC_DRMMR2); - - writel(0x00000800, dramcont + UMC_DRMMR3); - if (freq == 1333) { if (size == 1) writel(0x00240512, dramcont + UMC_SPCCTLA); diff --git a/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c b/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c index ff988e3540..c28492c4f1 100644 --- a/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c +++ b/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c @@ -20,7 +20,6 @@ enum dram_size { DRAM_SZ_NR, }; -static u32 umc_initctlb[DRAM_SZ_NR] = {0x43030d3f, 0x43030d3f, 0x7b030d3f}; static u32 umc_spcctla[DRAM_SZ_NR] = {0x002b0617, 0x003f0617, 0x00770617}; static void umc_start_ssif(void __iomem *ssif_base) @@ -88,13 +87,6 @@ static int umc_dramcont_init(void __iomem *dramcont, void __iomem *ca_base, writel(0x66bb0f17, dramcont + UMC_CMDCTLA); writel(0x18c6aa44, dramcont + UMC_CMDCTLB); - writel(0x5101387f, dramcont + UMC_INITCTLA); - writel(umc_initctlb[dram_size], dramcont + UMC_INITCTLB); - writel(0x00ff00ff, dramcont + UMC_INITCTLC); - writel(0x00000d71, dramcont + UMC_DRMMR0); - writel(0x00000006, dramcont + UMC_DRMMR1); - writel(0x00000298, dramcont + UMC_DRMMR2); - writel(0x00000000, dramcont + UMC_DRMMR3); writel(umc_spcctla[dram_size], dramcont + UMC_SPCCTLA); writel(0x00ff0008, dramcont + UMC_SPCCTLB); writel(0x000c00ae, dramcont + UMC_RDATACTL_D0); diff --git a/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c b/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c index 3c2724eb37..fa0619fc72 100644 --- a/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c +++ b/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c @@ -58,24 +58,6 @@ static void umc_dramcont_init(void __iomem *dramcont, void __iomem *ca_base, writel(0x16958924, dramcont + UMC_CMDCTLB); #endif - writel(0x5101046A, dramcont + UMC_INITCTLA); - - if (size == 1) - writel(0x27028B0A, dramcont + UMC_INITCTLB); - else if (size == 2) - writel(0x38028B0A, dramcont + UMC_INITCTLB); - - writel(0x00FF00FF, dramcont + UMC_INITCTLC); - writel(0x00000b51, dramcont + UMC_DRMMR0); - writel(0x00000006, dramcont + UMC_DRMMR1); - writel(0x00000290, dramcont + UMC_DRMMR2); - -#ifdef CONFIG_DDR_STANDARD - writel(0x00000000, dramcont + UMC_DRMMR3); -#else - writel(0x00000800, dramcont + UMC_DRMMR3); -#endif - if (size == 1) writel(0x00240512, dramcont + UMC_SPCCTLA); else if (size == 2) diff --git a/arch/arm/mach-uniphier/dram/umc-regs.h b/arch/arm/mach-uniphier/dram/umc-regs.h index b33e2da2bd..311cf3d352 100644 --- a/arch/arm/mach-uniphier/dram/umc-regs.h +++ b/arch/arm/mach-uniphier/dram/umc-regs.h @@ -56,15 +56,8 @@ #define UMC_CMDCTLA 0x00000000 #define UMC_CMDCTLB 0x00000004 -#define UMC_INITCTLA 0x00000008 -#define UMC_INITCTLB 0x0000000C -#define UMC_INITCTLC 0x00000010 #define UMC_INITSET 0x00000014 #define UMC_INITSTAT 0x00000018 -#define UMC_DRMMR0 0x0000001C -#define UMC_DRMMR1 0x00000020 -#define UMC_DRMMR2 0x00000024 -#define UMC_DRMMR3 0x00000028 #define UMC_SPCCTLA 0x00000030 #define UMC_SPCCTLB 0x00000034 #define UMC_SPCSETA 0x00000038 From 3c963d48995ed4ca4e6d742de3d234cb0bcf699e Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 14:21:39 +0900 Subject: [PATCH 19/38] ARM: uniphier: disable debug circuit clocks for PH1-Pro4 These settings control the clocks around the memory controller. The debug ability is unneeded once it works properly. Signed-off-by: Masahiro Yamada --- arch/arm/mach-uniphier/dram/umc-ph1-pro4.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c b/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c index c28492c4f1..f89b1da26c 100644 --- a/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c +++ b/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c @@ -24,9 +24,9 @@ static u32 umc_spcctla[DRAM_SZ_NR] = {0x002b0617, 0x003f0617, 0x00770617}; static void umc_start_ssif(void __iomem *ssif_base) { - writel(0x00000001, ssif_base + 0x0000b004); + writel(0x00000000, ssif_base + 0x0000b004); writel(0xffffffff, ssif_base + 0x0000c004); - writel(0x07ffffff, ssif_base + 0x0000c008); + writel(0x000fffcf, ssif_base + 0x0000c008); writel(0x00000001, ssif_base + 0x0000b000); writel(0x00000001, ssif_base + 0x0000c000); From 4021b4381d8d3c18a3d8732967eec3ec1624ab7b Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 14:21:40 +0900 Subject: [PATCH 20/38] ARM: uniphier: add a field to specify DDR3+ Add a field to distinguish DDR3+ from (standard) DDR3. It also allows to delete CONFIG_DDR_STANDARD (this is not a software configuration, but a board attribute). Default DDR3 spec for each SoC: PH1-LD4, PH1-sLD8: DDR3+ Others: DDR3 Signed-off-by: Masahiro Yamada --- arch/arm/mach-uniphier/boards.c | 2 ++ arch/arm/mach-uniphier/dram/ddrphy-ph1-ld4.c | 5 ++-- arch/arm/mach-uniphier/dram/ddrphy-ph1-pro4.c | 5 ++-- arch/arm/mach-uniphier/dram/ddrphy-ph1-sld8.c | 9 +++---- arch/arm/mach-uniphier/dram/ddrphy-regs.h | 10 +++++--- arch/arm/mach-uniphier/dram/umc-ph1-ld4.c | 9 +++---- arch/arm/mach-uniphier/dram/umc-ph1-pro4.c | 12 ++++++---- arch/arm/mach-uniphier/dram/umc-ph1-sld8.c | 24 ++++++++----------- arch/arm/mach-uniphier/init.h | 3 +++ 9 files changed, 44 insertions(+), 35 deletions(-) diff --git a/arch/arm/mach-uniphier/boards.c b/arch/arm/mach-uniphier/boards.c index 05b7c7612e..408aff0cd0 100644 --- a/arch/arm/mach-uniphier/boards.c +++ b/arch/arm/mach-uniphier/boards.c @@ -38,6 +38,7 @@ static const struct uniphier_board_data ph1_sld3_data = { static const struct uniphier_board_data ph1_ld4_data = { .dram_freq = 1600, .dram_nr_ch = 2, + .dram_ddr3plus = true, .dram_ch[0] = { .base = 0x80000000, .size = 0x10000000, @@ -89,6 +90,7 @@ static const struct uniphier_board_data ph1_pro4_2g_data = { static const struct uniphier_board_data ph1_sld8_data = { .dram_freq = 1333, .dram_nr_ch = 2, + .dram_ddr3plus = true, .dram_ch[0] = { .base = 0x80000000, .size = 0x10000000, diff --git a/arch/arm/mach-uniphier/dram/ddrphy-ph1-ld4.c b/arch/arm/mach-uniphier/dram/ddrphy-ph1-ld4.c index d2bc5a15d4..3000a284bb 100644 --- a/arch/arm/mach-uniphier/dram/ddrphy-ph1-ld4.c +++ b/arch/arm/mach-uniphier/dram/ddrphy-ph1-ld4.c @@ -9,7 +9,8 @@ #include "ddrphy-regs.h" -int ph1_ld4_ddrphy_init(struct ddrphy __iomem *phy, int freq, int size) +int ph1_ld4_ddrphy_init(struct ddrphy __iomem *phy, int freq, int size, + bool ddr3plus) { u32 tmp; @@ -61,7 +62,7 @@ int ph1_ld4_ddrphy_init(struct ddrphy __iomem *phy, int freq, int size) else writel(0x00000298, &phy->mr2); - writel(0x00000800, &phy->mr3); + writel(ddr3plus ? 0x00000800 : 0x00000000, &phy->mr3); while (!(readl(&phy->pgsr[0]) & PGSR0_IDONE)) ; diff --git a/arch/arm/mach-uniphier/dram/ddrphy-ph1-pro4.c b/arch/arm/mach-uniphier/dram/ddrphy-ph1-pro4.c index 9fb34f79a7..b4dca3596f 100644 --- a/arch/arm/mach-uniphier/dram/ddrphy-ph1-pro4.c +++ b/arch/arm/mach-uniphier/dram/ddrphy-ph1-pro4.c @@ -9,7 +9,8 @@ #include "ddrphy-regs.h" -int ph1_pro4_ddrphy_init(struct ddrphy __iomem *phy, int freq, int size) +int ph1_pro4_ddrphy_init(struct ddrphy __iomem *phy, int freq, int size, + bool ddr3plus) { u32 tmp; @@ -55,7 +56,7 @@ int ph1_pro4_ddrphy_init(struct ddrphy __iomem *phy, int freq, int size) else writel(0x00000298, &phy->mr2); - writel(0x00000000, &phy->mr3); + writel(ddr3plus ? 0x00000800 : 0x00000000, &phy->mr3); while (!(readl(&phy->pgsr[0]) & PGSR0_IDONE)) ; diff --git a/arch/arm/mach-uniphier/dram/ddrphy-ph1-sld8.c b/arch/arm/mach-uniphier/dram/ddrphy-ph1-sld8.c index 651069073c..0d2ae42685 100644 --- a/arch/arm/mach-uniphier/dram/ddrphy-ph1-sld8.c +++ b/arch/arm/mach-uniphier/dram/ddrphy-ph1-sld8.c @@ -10,7 +10,8 @@ #include "ddrphy-regs.h" -int ph1_sld8_ddrphy_init(struct ddrphy __iomem *phy, int freq, int size) +int ph1_sld8_ddrphy_init(struct ddrphy __iomem *phy, int freq, int size, + bool ddr3plus) { u32 tmp; @@ -62,11 +63,7 @@ int ph1_sld8_ddrphy_init(struct ddrphy __iomem *phy, int freq, int size) else writel(0x00000298, &phy->mr2); -#ifdef CONFIG_DDR_STANDARD - writel(0x00000000, &phy->mr3); -#else - writel(0x00000800, &phy->mr3); -#endif + writel(ddr3plus ? 0x00000800 : 0x00000000, &phy->mr3); while (!(readl(&phy->pgsr[0]) & PGSR0_IDONE)) ; diff --git a/arch/arm/mach-uniphier/dram/ddrphy-regs.h b/arch/arm/mach-uniphier/dram/ddrphy-regs.h index 03aedc2e63..206fabdd0b 100644 --- a/arch/arm/mach-uniphier/dram/ddrphy-regs.h +++ b/arch/arm/mach-uniphier/dram/ddrphy-regs.h @@ -11,6 +11,7 @@ #include #include +#include #ifndef __ASSEMBLY__ @@ -169,9 +170,12 @@ struct ddrphy { #define DDRPHY_BASE(ch, phy) (0x5bc01000 + 0x200000 * (ch) + 0x1000 * (phy)) #ifndef __ASSEMBLY__ -int ph1_ld4_ddrphy_init(struct ddrphy __iomem *phy, int freq, int size); -int ph1_pro4_ddrphy_init(struct ddrphy __iomem *phy, int freq, int size); -int ph1_sld8_ddrphy_init(struct ddrphy __iomem *phy, int freq, int size); +int ph1_ld4_ddrphy_init(struct ddrphy __iomem *phy, int freq, int size, + bool ddr3plus); +int ph1_pro4_ddrphy_init(struct ddrphy __iomem *phy, int freq, int size, + bool ddr3plus); +int ph1_sld8_ddrphy_init(struct ddrphy __iomem *phy, int freq, int size, + bool ddr3plus); void ddrphy_prepare_training(struct ddrphy __iomem *phy, int rank); int ddrphy_training(struct ddrphy __iomem *phy); #endif diff --git a/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c b/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c index 638aa11d0d..957a38fec4 100644 --- a/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c +++ b/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c @@ -96,7 +96,7 @@ static void umc_dramcont_init(void __iomem *dramcont, void __iomem *ca_base, writel(0x00000520, dramcont + UMC_DFICUPDCTLA); } -static int umc_init_sub(int freq, int size_ch0, int size_ch1) +static int umc_init_sub(int freq, int size_ch0, int size_ch1, bool ddr3plus) { void __iomem *ssif_base = (void __iomem *)UMC_SSIF_BASE; void __iomem *ca_base0 = (void __iomem *)UMC_CA_BASE(0); @@ -113,14 +113,14 @@ static int umc_init_sub(int freq, int size_ch0, int size_ch1) writel(0x00000101, dramcont0 + UMC_DIOCTLA); - ph1_ld4_ddrphy_init(phy0_0, freq, size_ch0); + ph1_ld4_ddrphy_init(phy0_0, freq, size_ch0, ddr3plus); ddrphy_prepare_training(phy0_0, 0); ddrphy_training(phy0_0); writel(0x00000101, dramcont1 + UMC_DIOCTLA); - ph1_ld4_ddrphy_init(phy1_0, freq, size_ch1); + ph1_ld4_ddrphy_init(phy1_0, freq, size_ch1, ddr3plus); ddrphy_prepare_training(phy1_0, 1); ddrphy_training(phy1_0); @@ -141,7 +141,8 @@ int ph1_ld4_umc_init(const struct uniphier_board_data *bd) bd->dram_ch[0].width == 16 && bd->dram_ch[1].width == 16) { return umc_init_sub(bd->dram_freq, bd->dram_ch[0].size / SZ_128M, - bd->dram_ch[1].size / SZ_128M); + bd->dram_ch[1].size / SZ_128M, + bd->dram_ddr3plus); } else { pr_err("Unsupported DDR configuration\n"); return -EINVAL; diff --git a/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c b/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c index f89b1da26c..38dd338c85 100644 --- a/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c +++ b/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c @@ -138,28 +138,32 @@ int ph1_pro4_umc_init(const struct uniphier_board_data *bd) writel(0x00000101, dramcont0 + UMC_DIOCTLA); - ph1_pro4_ddrphy_init(phy0_0, bd->dram_freq, bd->dram_ch[0].size); + ph1_pro4_ddrphy_init(phy0_0, bd->dram_freq, bd->dram_ch[0].size, + bd->dram_ddr3plus); ddrphy_prepare_training(phy0_0, 0); ddrphy_training(phy0_0); writel(0x00000103, dramcont0 + UMC_DIOCTLA); - ph1_pro4_ddrphy_init(phy0_1, bd->dram_freq, bd->dram_ch[0].size); + ph1_pro4_ddrphy_init(phy0_1, bd->dram_freq, bd->dram_ch[0].size, + bd->dram_ddr3plus); ddrphy_prepare_training(phy0_1, 1); ddrphy_training(phy0_1); writel(0x00000101, dramcont1 + UMC_DIOCTLA); - ph1_pro4_ddrphy_init(phy1_0, bd->dram_freq, bd->dram_ch[1].size); + ph1_pro4_ddrphy_init(phy1_0, bd->dram_freq, bd->dram_ch[1].size, + bd->dram_ddr3plus); ddrphy_prepare_training(phy1_0, 0); ddrphy_training(phy1_0); writel(0x00000103, dramcont1 + UMC_DIOCTLA); - ph1_pro4_ddrphy_init(phy1_1, bd->dram_freq, bd->dram_ch[1].size); + ph1_pro4_ddrphy_init(phy1_1, bd->dram_freq, bd->dram_ch[1].size, + bd->dram_ddr3plus); ddrphy_prepare_training(phy1_1, 1); ddrphy_training(phy1_1); diff --git a/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c b/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c index fa0619fc72..3cbb7ba765 100644 --- a/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c +++ b/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c @@ -48,15 +48,10 @@ static void umc_start_ssif(void __iomem *ssif_base) } static void umc_dramcont_init(void __iomem *dramcont, void __iomem *ca_base, - int size, int freq) + int size, int freq, bool ddr3plus) { -#ifdef CONFIG_DDR_STANDARD - writel(0x55990b11, dramcont + UMC_CMDCTLA); - writel(0x16958944, dramcont + UMC_CMDCTLB); -#else - writel(0x45990b11, dramcont + UMC_CMDCTLA); - writel(0x16958924, dramcont + UMC_CMDCTLB); -#endif + writel(ddr3plus ? 0x45990b11 : 0x55990b11, dramcont + UMC_CMDCTLA); + writel(ddr3plus ? 0x16958924 : 0x16958944, dramcont + UMC_CMDCTLB); if (size == 1) writel(0x00240512, dramcont + UMC_SPCCTLA); @@ -85,7 +80,7 @@ static void umc_dramcont_init(void __iomem *dramcont, void __iomem *ca_base, writel(0x00000520, dramcont + UMC_DFICUPDCTLA); } -static int umc_init_sub(int freq, int size_ch0, int size_ch1) +static int umc_init_sub(int freq, int size_ch0, int size_ch1, bool ddr3plus) { void __iomem *ssif_base = (void __iomem *)UMC_SSIF_BASE; void __iomem *ca_base0 = (void __iomem *)UMC_CA_BASE(0); @@ -102,20 +97,20 @@ static int umc_init_sub(int freq, int size_ch0, int size_ch1) writel(0x00000101, dramcont0 + UMC_DIOCTLA); - ph1_sld8_ddrphy_init(phy0_0, freq, size_ch0); + ph1_sld8_ddrphy_init(phy0_0, freq, size_ch0, ddr3plus); ddrphy_prepare_training(phy0_0, 0); ddrphy_training(phy0_0); writel(0x00000101, dramcont1 + UMC_DIOCTLA); - ph1_sld8_ddrphy_init(phy1_0, freq, size_ch1); + ph1_sld8_ddrphy_init(phy1_0, freq, size_ch1, ddr3plus); ddrphy_prepare_training(phy1_0, 1); ddrphy_training(phy1_0); - umc_dramcont_init(dramcont0, ca_base0, size_ch0, freq); - umc_dramcont_init(dramcont1, ca_base1, size_ch1, freq); + umc_dramcont_init(dramcont0, ca_base0, size_ch0, freq, ddr3plus); + umc_dramcont_init(dramcont1, ca_base1, size_ch1, freq, ddr3plus); umc_start_ssif(ssif_base); @@ -130,7 +125,8 @@ int ph1_sld8_umc_init(const struct uniphier_board_data *bd) bd->dram_ch[0].width == 16 && bd->dram_ch[1].width == 16) { return umc_init_sub(bd->dram_freq, bd->dram_ch[0].size / SZ_128M, - bd->dram_ch[1].size / SZ_128M); + bd->dram_ch[1].size / SZ_128M, + bd->dram_ddr3plus); } else { pr_err("Unsupported DDR configuration\n"); return -EINVAL; diff --git a/arch/arm/mach-uniphier/init.h b/arch/arm/mach-uniphier/init.h index aabd84a8ed..e969fd0c4e 100644 --- a/arch/arm/mach-uniphier/init.h +++ b/arch/arm/mach-uniphier/init.h @@ -7,6 +7,8 @@ #ifndef __MACH_INIT_H #define __MACH_INIT_H +#include + #define UNIPHIER_MAX_NR_DRAM_CH 3 struct uniphier_dram_ch { @@ -18,6 +20,7 @@ struct uniphier_dram_ch { struct uniphier_board_data { unsigned int dram_freq; unsigned int dram_nr_ch; + bool dram_ddr3plus; struct uniphier_dram_ch dram_ch[UNIPHIER_MAX_NR_DRAM_CH]; }; From 4f19f6118478c8bbf4bd435404094b23991ad225 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 14:21:41 +0900 Subject: [PATCH 21/38] ARM: uniphier: merge DDR PHY init code for 3 SoCs Now these three are almost the same. The only difference is the DTPR1 register dependency on the DRAM size, but it can be ignored. (It has already been ignored in PH1-sLD8 and PH1-Pro4.) Signed-off-by: Masahiro Yamada --- arch/arm/mach-uniphier/dram/Makefile | 4 +- arch/arm/mach-uniphier/dram/ddrphy-ph1-ld4.c | 10 +-- arch/arm/mach-uniphier/dram/ddrphy-ph1-pro4.c | 68 ----------------- arch/arm/mach-uniphier/dram/ddrphy-ph1-sld8.c | 75 ------------------- arch/arm/mach-uniphier/dram/ddrphy-regs.h | 4 - arch/arm/mach-uniphier/dram/umc-ph1-pro4.c | 16 ++-- arch/arm/mach-uniphier/dram/umc-ph1-sld8.c | 4 +- 7 files changed, 14 insertions(+), 167 deletions(-) delete mode 100644 arch/arm/mach-uniphier/dram/ddrphy-ph1-pro4.c delete mode 100644 arch/arm/mach-uniphier/dram/ddrphy-ph1-sld8.c diff --git a/arch/arm/mach-uniphier/dram/Makefile b/arch/arm/mach-uniphier/dram/Makefile index a0a6003065..3d1553cbe1 100644 --- a/arch/arm/mach-uniphier/dram/Makefile +++ b/arch/arm/mach-uniphier/dram/Makefile @@ -7,9 +7,9 @@ ifdef CONFIG_SPL_BUILD obj-$(CONFIG_ARCH_UNIPHIER_PH1_LD4) += umc-ph1-ld4.o \ ddrphy-training.o ddrphy-ph1-ld4.o obj-$(CONFIG_ARCH_UNIPHIER_PH1_PRO4) += umc-ph1-pro4.o \ - ddrphy-training.o ddrphy-ph1-pro4.o + ddrphy-training.o ddrphy-ph1-ld4.o obj-$(CONFIG_ARCH_UNIPHIER_PH1_SLD8) += umc-ph1-sld8.o \ - ddrphy-training.o ddrphy-ph1-sld8.o + ddrphy-training.o ddrphy-ph1-ld4.o obj-$(CONFIG_ARCH_UNIPHIER_PROXSTREAM2) += umc-proxstream2.o obj-$(CONFIG_ARCH_UNIPHIER_PH1_LD6B) += umc-proxstream2.o diff --git a/arch/arm/mach-uniphier/dram/ddrphy-ph1-ld4.c b/arch/arm/mach-uniphier/dram/ddrphy-ph1-ld4.c index 3000a284bb..27be1cc21e 100644 --- a/arch/arm/mach-uniphier/dram/ddrphy-ph1-ld4.c +++ b/arch/arm/mach-uniphier/dram/ddrphy-ph1-ld4.c @@ -41,18 +41,12 @@ int ph1_ld4_ddrphy_init(struct ddrphy __iomem *phy, int freq, int size, writel(0x0000040B, &phy->dcr); if (freq == 1333) { writel(0x85589955, &phy->dtpr[0]); - if (size == 1) - writel(0x1a8253c0, &phy->dtpr[1]); - else - writel(0x1a8363c0, &phy->dtpr[1]); + writel(0x1a8363c0, &phy->dtpr[1]); writel(0x5002c200, &phy->dtpr[2]); writel(0x00000b51, &phy->mr0); } else { writel(0x999cbb66, &phy->dtpr[0]); - if (size == 1) - writel(0x1a82dbc0, &phy->dtpr[1]); - else - writel(0x1a878400, &phy->dtpr[1]); + writel(0x1a878400, &phy->dtpr[1]); writel(0xa00214f8, &phy->dtpr[2]); writel(0x00000d71, &phy->mr0); } diff --git a/arch/arm/mach-uniphier/dram/ddrphy-ph1-pro4.c b/arch/arm/mach-uniphier/dram/ddrphy-ph1-pro4.c deleted file mode 100644 index b4dca3596f..0000000000 --- a/arch/arm/mach-uniphier/dram/ddrphy-ph1-pro4.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2014-2015 Masahiro Yamada - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include - -#include "ddrphy-regs.h" - -int ph1_pro4_ddrphy_init(struct ddrphy __iomem *phy, int freq, int size, - bool ddr3plus) -{ - u32 tmp; - - writel(0x0300c473, &phy->pgcr[1]); - if (freq == 1333) { - writel(0x0a806844, &phy->ptr[0]); - writel(0x208e0124, &phy->ptr[1]); - } else { - writel(0x0c807d04, &phy->ptr[0]); - writel(0x2710015E, &phy->ptr[1]); - } - writel(0x00083DEF, &phy->ptr[2]); - if (freq == 1333) { - writel(0x0f051616, &phy->ptr[3]); - writel(0x06ae08d6, &phy->ptr[4]); - } else { - writel(0x12061A80, &phy->ptr[3]); - writel(0x08027100, &phy->ptr[4]); - } - writel(0xF004001A, &phy->dsgcr); - - /* change the value of the on-die pull-up/pull-down registors */ - tmp = readl(&phy->dxccr); - tmp &= ~0x0ee0; - tmp |= DXCCR_DQSNRES_688_OHM | DXCCR_DQSRES_688_OHM; - writel(tmp, &phy->dxccr); - - writel(0x0000040B, &phy->dcr); - if (freq == 1333) { - writel(0x85589955, &phy->dtpr[0]); - writel(0x1a8363c0, &phy->dtpr[1]); - writel(0x5002c200, &phy->dtpr[2]); - writel(0x00000b51, &phy->mr0); - } else { - writel(0x999cbb66, &phy->dtpr[0]); - writel(0x1a878400, &phy->dtpr[1]); - writel(0xa00214f8, &phy->dtpr[2]); - writel(0x00000d71, &phy->mr0); - } - writel(0x00000006, &phy->mr1); - if (freq == 1333) - writel(0x00000290, &phy->mr2); - else - writel(0x00000298, &phy->mr2); - - writel(ddr3plus ? 0x00000800 : 0x00000000, &phy->mr3); - - while (!(readl(&phy->pgsr[0]) & PGSR0_IDONE)) - ; - - writel(0x0300C473, &phy->pgcr[1]); - writel(0x0000005D, &phy->zq[0].cr[1]); - - return 0; -} diff --git a/arch/arm/mach-uniphier/dram/ddrphy-ph1-sld8.c b/arch/arm/mach-uniphier/dram/ddrphy-ph1-sld8.c deleted file mode 100644 index 0d2ae42685..0000000000 --- a/arch/arm/mach-uniphier/dram/ddrphy-ph1-sld8.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2014-2015 Masahiro Yamada - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include - -#include "ddrphy-regs.h" - -int ph1_sld8_ddrphy_init(struct ddrphy __iomem *phy, int freq, int size, - bool ddr3plus) -{ - u32 tmp; - - writel(0x0300c473, &phy->pgcr[1]); - if (freq == 1333) { - writel(0x0a806844, &phy->ptr[0]); - writel(0x208e0124, &phy->ptr[1]); - } else { - writel(0x0c807d04, &phy->ptr[0]); - writel(0x2710015E, &phy->ptr[1]); - } - writel(0x00083DEF, &phy->ptr[2]); - if (freq == 1333) { - writel(0x0f051616, &phy->ptr[3]); - writel(0x06ae08d6, &phy->ptr[4]); - } else { - writel(0x12061A80, &phy->ptr[3]); - writel(0x08027100, &phy->ptr[4]); - } - writel(0xF004001A, &phy->dsgcr); - - /* change the value of the on-die pull-up/pull-down registors */ - tmp = readl(&phy->dxccr); - tmp &= ~0x0ee0; - tmp |= DXCCR_DQSNRES_688_OHM | DXCCR_DQSRES_688_OHM; - writel(tmp, &phy->dxccr); - - writel(0x0000040B, &phy->dcr); - if (freq == 1333) { - writel(0x85589955, &phy->dtpr[0]); - if (size == 1) - writel(0x1a8363c0, &phy->dtpr[1]); - else - writel(0x1a8363c0, &phy->dtpr[1]); - writel(0x5002c200, &phy->dtpr[2]); - writel(0x00000b51, &phy->mr0); - } else { - writel(0x999cbb66, &phy->dtpr[0]); - if (size == 1) - writel(0x1a878400, &phy->dtpr[1]); - else - writel(0x1a878400, &phy->dtpr[1]); - writel(0xa00214f8, &phy->dtpr[2]); - writel(0x00000d71, &phy->mr0); - } - writel(0x00000006, &phy->mr1); - if (freq == 1333) - writel(0x00000290, &phy->mr2); - else - writel(0x00000298, &phy->mr2); - - writel(ddr3plus ? 0x00000800 : 0x00000000, &phy->mr3); - - while (!(readl(&phy->pgsr[0]) & PGSR0_IDONE)) - ; - - writel(0x0300C473, &phy->pgcr[1]); - writel(0x0000005D, &phy->zq[0].cr[1]); - - return 0; -} diff --git a/arch/arm/mach-uniphier/dram/ddrphy-regs.h b/arch/arm/mach-uniphier/dram/ddrphy-regs.h index 206fabdd0b..a466118258 100644 --- a/arch/arm/mach-uniphier/dram/ddrphy-regs.h +++ b/arch/arm/mach-uniphier/dram/ddrphy-regs.h @@ -172,10 +172,6 @@ struct ddrphy { #ifndef __ASSEMBLY__ int ph1_ld4_ddrphy_init(struct ddrphy __iomem *phy, int freq, int size, bool ddr3plus); -int ph1_pro4_ddrphy_init(struct ddrphy __iomem *phy, int freq, int size, - bool ddr3plus); -int ph1_sld8_ddrphy_init(struct ddrphy __iomem *phy, int freq, int size, - bool ddr3plus); void ddrphy_prepare_training(struct ddrphy __iomem *phy, int rank); int ddrphy_training(struct ddrphy __iomem *phy); #endif diff --git a/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c b/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c index 38dd338c85..877f5ef9cc 100644 --- a/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c +++ b/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c @@ -138,32 +138,32 @@ int ph1_pro4_umc_init(const struct uniphier_board_data *bd) writel(0x00000101, dramcont0 + UMC_DIOCTLA); - ph1_pro4_ddrphy_init(phy0_0, bd->dram_freq, bd->dram_ch[0].size, - bd->dram_ddr3plus); + ph1_ld4_ddrphy_init(phy0_0, bd->dram_freq, bd->dram_ch[0].size, + bd->dram_ddr3plus); ddrphy_prepare_training(phy0_0, 0); ddrphy_training(phy0_0); writel(0x00000103, dramcont0 + UMC_DIOCTLA); - ph1_pro4_ddrphy_init(phy0_1, bd->dram_freq, bd->dram_ch[0].size, - bd->dram_ddr3plus); + ph1_ld4_ddrphy_init(phy0_1, bd->dram_freq, bd->dram_ch[0].size, + bd->dram_ddr3plus); ddrphy_prepare_training(phy0_1, 1); ddrphy_training(phy0_1); writel(0x00000101, dramcont1 + UMC_DIOCTLA); - ph1_pro4_ddrphy_init(phy1_0, bd->dram_freq, bd->dram_ch[1].size, - bd->dram_ddr3plus); + ph1_ld4_ddrphy_init(phy1_0, bd->dram_freq, bd->dram_ch[1].size, + bd->dram_ddr3plus); ddrphy_prepare_training(phy1_0, 0); ddrphy_training(phy1_0); writel(0x00000103, dramcont1 + UMC_DIOCTLA); - ph1_pro4_ddrphy_init(phy1_1, bd->dram_freq, bd->dram_ch[1].size, - bd->dram_ddr3plus); + ph1_ld4_ddrphy_init(phy1_1, bd->dram_freq, bd->dram_ch[1].size, + bd->dram_ddr3plus); ddrphy_prepare_training(phy1_1, 1); ddrphy_training(phy1_1); diff --git a/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c b/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c index 3cbb7ba765..a27f91f895 100644 --- a/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c +++ b/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c @@ -97,14 +97,14 @@ static int umc_init_sub(int freq, int size_ch0, int size_ch1, bool ddr3plus) writel(0x00000101, dramcont0 + UMC_DIOCTLA); - ph1_sld8_ddrphy_init(phy0_0, freq, size_ch0, ddr3plus); + ph1_ld4_ddrphy_init(phy0_0, freq, size_ch0, ddr3plus); ddrphy_prepare_training(phy0_0, 0); ddrphy_training(phy0_0); writel(0x00000101, dramcont1 + UMC_DIOCTLA); - ph1_sld8_ddrphy_init(phy1_0, freq, size_ch1, ddr3plus); + ph1_ld4_ddrphy_init(phy1_0, freq, size_ch1, ddr3plus); ddrphy_prepare_training(phy1_0, 1); ddrphy_training(phy1_0); From 78876704984f44e96578f887035aabaec2b776f5 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 14:21:42 +0900 Subject: [PATCH 22/38] ARM: uniphier: remove unused argument of ph1_ld4_ddrphy_init() The DDR PHY settings no longer depend on the DRAM size. Drop the argument from the init function. Signed-off-by: Masahiro Yamada --- arch/arm/mach-uniphier/dram/ddrphy-ph1-ld4.c | 3 +-- arch/arm/mach-uniphier/dram/ddrphy-regs.h | 3 +-- arch/arm/mach-uniphier/dram/umc-ph1-ld4.c | 4 ++-- arch/arm/mach-uniphier/dram/umc-ph1-pro4.c | 12 ++++-------- arch/arm/mach-uniphier/dram/umc-ph1-sld8.c | 4 ++-- 5 files changed, 10 insertions(+), 16 deletions(-) diff --git a/arch/arm/mach-uniphier/dram/ddrphy-ph1-ld4.c b/arch/arm/mach-uniphier/dram/ddrphy-ph1-ld4.c index 27be1cc21e..ef1941e5a6 100644 --- a/arch/arm/mach-uniphier/dram/ddrphy-ph1-ld4.c +++ b/arch/arm/mach-uniphier/dram/ddrphy-ph1-ld4.c @@ -9,8 +9,7 @@ #include "ddrphy-regs.h" -int ph1_ld4_ddrphy_init(struct ddrphy __iomem *phy, int freq, int size, - bool ddr3plus) +int ph1_ld4_ddrphy_init(struct ddrphy __iomem *phy, int freq, bool ddr3plus) { u32 tmp; diff --git a/arch/arm/mach-uniphier/dram/ddrphy-regs.h b/arch/arm/mach-uniphier/dram/ddrphy-regs.h index a466118258..87f6d0d3a2 100644 --- a/arch/arm/mach-uniphier/dram/ddrphy-regs.h +++ b/arch/arm/mach-uniphier/dram/ddrphy-regs.h @@ -170,8 +170,7 @@ struct ddrphy { #define DDRPHY_BASE(ch, phy) (0x5bc01000 + 0x200000 * (ch) + 0x1000 * (phy)) #ifndef __ASSEMBLY__ -int ph1_ld4_ddrphy_init(struct ddrphy __iomem *phy, int freq, int size, - bool ddr3plus); +int ph1_ld4_ddrphy_init(struct ddrphy __iomem *phy, int freq, bool ddr3plus); void ddrphy_prepare_training(struct ddrphy __iomem *phy, int rank); int ddrphy_training(struct ddrphy __iomem *phy); #endif diff --git a/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c b/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c index 957a38fec4..bee3ef4bff 100644 --- a/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c +++ b/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c @@ -113,14 +113,14 @@ static int umc_init_sub(int freq, int size_ch0, int size_ch1, bool ddr3plus) writel(0x00000101, dramcont0 + UMC_DIOCTLA); - ph1_ld4_ddrphy_init(phy0_0, freq, size_ch0, ddr3plus); + ph1_ld4_ddrphy_init(phy0_0, freq, ddr3plus); ddrphy_prepare_training(phy0_0, 0); ddrphy_training(phy0_0); writel(0x00000101, dramcont1 + UMC_DIOCTLA); - ph1_ld4_ddrphy_init(phy1_0, freq, size_ch1, ddr3plus); + ph1_ld4_ddrphy_init(phy1_0, freq, ddr3plus); ddrphy_prepare_training(phy1_0, 1); ddrphy_training(phy1_0); diff --git a/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c b/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c index 877f5ef9cc..0a2485e6ae 100644 --- a/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c +++ b/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c @@ -138,32 +138,28 @@ int ph1_pro4_umc_init(const struct uniphier_board_data *bd) writel(0x00000101, dramcont0 + UMC_DIOCTLA); - ph1_ld4_ddrphy_init(phy0_0, bd->dram_freq, bd->dram_ch[0].size, - bd->dram_ddr3plus); + ph1_ld4_ddrphy_init(phy0_0, bd->dram_freq, bd->dram_ddr3plus); ddrphy_prepare_training(phy0_0, 0); ddrphy_training(phy0_0); writel(0x00000103, dramcont0 + UMC_DIOCTLA); - ph1_ld4_ddrphy_init(phy0_1, bd->dram_freq, bd->dram_ch[0].size, - bd->dram_ddr3plus); + ph1_ld4_ddrphy_init(phy0_1, bd->dram_freq, bd->dram_ddr3plus); ddrphy_prepare_training(phy0_1, 1); ddrphy_training(phy0_1); writel(0x00000101, dramcont1 + UMC_DIOCTLA); - ph1_ld4_ddrphy_init(phy1_0, bd->dram_freq, bd->dram_ch[1].size, - bd->dram_ddr3plus); + ph1_ld4_ddrphy_init(phy1_0, bd->dram_freq, bd->dram_ddr3plus); ddrphy_prepare_training(phy1_0, 0); ddrphy_training(phy1_0); writel(0x00000103, dramcont1 + UMC_DIOCTLA); - ph1_ld4_ddrphy_init(phy1_1, bd->dram_freq, bd->dram_ch[1].size, - bd->dram_ddr3plus); + ph1_ld4_ddrphy_init(phy1_1, bd->dram_freq, bd->dram_ddr3plus); ddrphy_prepare_training(phy1_1, 1); ddrphy_training(phy1_1); diff --git a/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c b/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c index a27f91f895..73ad934cff 100644 --- a/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c +++ b/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c @@ -97,14 +97,14 @@ static int umc_init_sub(int freq, int size_ch0, int size_ch1, bool ddr3plus) writel(0x00000101, dramcont0 + UMC_DIOCTLA); - ph1_ld4_ddrphy_init(phy0_0, freq, size_ch0, ddr3plus); + ph1_ld4_ddrphy_init(phy0_0, freq, ddr3plus); ddrphy_prepare_training(phy0_0, 0); ddrphy_training(phy0_0); writel(0x00000101, dramcont1 + UMC_DIOCTLA); - ph1_ld4_ddrphy_init(phy1_0, freq, size_ch1, ddr3plus); + ph1_ld4_ddrphy_init(phy1_0, freq, ddr3plus); ddrphy_prepare_training(phy1_0, 1); ddrphy_training(phy1_0); From 6257a0b0e9b84fca5853e225e1de8023de5f1668 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 14:21:43 +0900 Subject: [PATCH 23/38] ARM: uniphier: refactor DDR-PHY init code The if-else statements for the frequency-dependent register settings seem clumsy. Moving them to arrays would make it cleaner. Signed-off-by: Masahiro Yamada --- arch/arm/mach-uniphier/dram/ddrphy-ph1-ld4.c | 70 +++++++++++--------- 1 file changed, 40 insertions(+), 30 deletions(-) diff --git a/arch/arm/mach-uniphier/dram/ddrphy-ph1-ld4.c b/arch/arm/mach-uniphier/dram/ddrphy-ph1-ld4.c index ef1941e5a6..eb9bf24da0 100644 --- a/arch/arm/mach-uniphier/dram/ddrphy-ph1-ld4.c +++ b/arch/arm/mach-uniphier/dram/ddrphy-ph1-ld4.c @@ -4,31 +4,52 @@ * SPDX-License-Identifier: GPL-2.0+ */ +#include +#include #include #include #include "ddrphy-regs.h" +enum dram_freq { + DRAM_FREQ_1333M, + DRAM_FREQ_1600M, + DRAM_FREQ_NR, +}; + +static u32 ddrphy_ptr0[DRAM_FREQ_NR] = {0x0a806844, 0x0c807d04}; +static u32 ddrphy_ptr1[DRAM_FREQ_NR] = {0x208e0124, 0x2710015E}; +static u32 ddrphy_ptr3[DRAM_FREQ_NR] = {0x0f051616, 0x12061A80}; +static u32 ddrphy_ptr4[DRAM_FREQ_NR] = {0x06ae08d6, 0x08027100}; +static u32 ddrphy_dtpr0[DRAM_FREQ_NR] = {0x85589955, 0x999cbb66}; +static u32 ddrphy_dtpr1[DRAM_FREQ_NR] = {0x1a8363c0, 0x1a878400}; +static u32 ddrphy_dtpr2[DRAM_FREQ_NR] = {0x5002c200, 0xa00214f8}; +static u32 ddrphy_mr0[DRAM_FREQ_NR] = {0x00000b51, 0x00000d71}; +static u32 ddrphy_mr2[DRAM_FREQ_NR] = {0x00000290, 0x00000298}; + int ph1_ld4_ddrphy_init(struct ddrphy __iomem *phy, int freq, bool ddr3plus) { + enum dram_freq freq_e; u32 tmp; + switch (freq) { + case 1333: + freq_e = DRAM_FREQ_1333M; + break; + case 1600: + freq_e = DRAM_FREQ_1600M; + break; + default: + printf("unsupported DRAM frequency %d MHz\n", freq); + return -EINVAL; + } + writel(0x0300c473, &phy->pgcr[1]); - if (freq == 1333) { - writel(0x0a806844, &phy->ptr[0]); - writel(0x208e0124, &phy->ptr[1]); - } else { - writel(0x0c807d04, &phy->ptr[0]); - writel(0x2710015E, &phy->ptr[1]); - } + writel(ddrphy_ptr0[freq_e], &phy->ptr[0]); + writel(ddrphy_ptr1[freq_e], &phy->ptr[1]); writel(0x00083DEF, &phy->ptr[2]); - if (freq == 1333) { - writel(0x0f051616, &phy->ptr[3]); - writel(0x06ae08d6, &phy->ptr[4]); - } else { - writel(0x12061A80, &phy->ptr[3]); - writel(0x08027100, &phy->ptr[4]); - } + writel(ddrphy_ptr3[freq_e], &phy->ptr[3]); + writel(ddrphy_ptr4[freq_e], &phy->ptr[4]); writel(0xF004001A, &phy->dsgcr); /* change the value of the on-die pull-up/pull-down registors */ @@ -38,23 +59,12 @@ int ph1_ld4_ddrphy_init(struct ddrphy __iomem *phy, int freq, bool ddr3plus) writel(tmp, &phy->dxccr); writel(0x0000040B, &phy->dcr); - if (freq == 1333) { - writel(0x85589955, &phy->dtpr[0]); - writel(0x1a8363c0, &phy->dtpr[1]); - writel(0x5002c200, &phy->dtpr[2]); - writel(0x00000b51, &phy->mr0); - } else { - writel(0x999cbb66, &phy->dtpr[0]); - writel(0x1a878400, &phy->dtpr[1]); - writel(0xa00214f8, &phy->dtpr[2]); - writel(0x00000d71, &phy->mr0); - } + writel(ddrphy_dtpr0[freq_e], &phy->dtpr[0]); + writel(ddrphy_dtpr1[freq_e], &phy->dtpr[1]); + writel(ddrphy_dtpr2[freq_e], &phy->dtpr[2]); + writel(ddrphy_mr0[freq_e], &phy->mr0); writel(0x00000006, &phy->mr1); - if (freq == 1333) - writel(0x00000290, &phy->mr2); - else - writel(0x00000298, &phy->mr2); - + writel(ddrphy_mr2[freq_e], &phy->mr2); writel(ddr3plus ? 0x00000800 : 0x00000000, &phy->mr3); while (!(readl(&phy->pgsr[0]) & PGSR0_IDONE)) From 82e5950802137d8bb5ee389e16c6a9f3b0361faf Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 14:21:44 +0900 Subject: [PATCH 24/38] ARM: uniphier: refactor UMC init code for PH1-sLD8 Move frequency-dependent register settings to arrays for clean-up. Signed-off-by: Masahiro Yamada --- arch/arm/mach-uniphier/dram/umc-ph1-sld8.c | 37 +++++++++++++++++----- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c b/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c index 73ad934cff..5e333e0c96 100644 --- a/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c +++ b/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c @@ -13,6 +13,14 @@ #include "ddrphy-regs.h" #include "umc-regs.h" +enum dram_size { + DRAM_SZ_128M, + DRAM_SZ_256M, + DRAM_SZ_NR, +}; + +static u32 umc_spcctla[DRAM_SZ_NR] = {0x00240512, 0x00350512}; + static void umc_start_ssif(void __iomem *ssif_base) { writel(0x00000000, ssif_base + 0x0000b004); @@ -47,17 +55,28 @@ static void umc_start_ssif(void __iomem *ssif_base) writel(0x00000001, ssif_base + UMC_DMDRST); } -static void umc_dramcont_init(void __iomem *dramcont, void __iomem *ca_base, - int size, int freq, bool ddr3plus) +static int umc_dramcont_init(void __iomem *dramcont, void __iomem *ca_base, + int size, int freq, bool ddr3plus) { + enum dram_size size_e; + + switch (size) { + case 0: + return 0; + case 1: + size_e = DRAM_SZ_128M; + break; + case 2: + size_e = DRAM_SZ_256M; + break; + default: + pr_err("unsupported DRAM size\n"); + return -EINVAL; + } + writel(ddr3plus ? 0x45990b11 : 0x55990b11, dramcont + UMC_CMDCTLA); writel(ddr3plus ? 0x16958924 : 0x16958944, dramcont + UMC_CMDCTLB); - - if (size == 1) - writel(0x00240512, dramcont + UMC_SPCCTLA); - else if (size == 2) - writel(0x00350512, dramcont + UMC_SPCCTLA); - + writel(umc_spcctla[size_e], dramcont + UMC_SPCCTLA); writel(0x00ff0006, dramcont + UMC_SPCCTLB); writel(0x000a00ac, dramcont + UMC_RDATACTL_D0); writel(0x04060806, dramcont + UMC_WDATACTL_D0); @@ -78,6 +97,8 @@ static void umc_dramcont_init(void __iomem *dramcont, void __iomem *ca_base, writel(0x200a0a00, dramcont + UMC_SPCSETB); writel(0x00000000, dramcont + UMC_SPCSETD); writel(0x00000520, dramcont + UMC_DFICUPDCTLA); + + return 0; } static int umc_init_sub(int freq, int size_ch0, int size_ch1, bool ddr3plus) From 380a8cafc09800e4a6573c938e28f1bc1c93793f Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 14:21:45 +0900 Subject: [PATCH 25/38] ARM: uniphier: support more DRAM use cases for PH1-sLD8 Support DDR3-1600 / 512MB DDR size. Signed-off-by: Masahiro Yamada --- arch/arm/mach-uniphier/dram/umc-ph1-sld8.c | 46 +++++++++++++++++++--- 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c b/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c index 5e333e0c96..b8d729c925 100644 --- a/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c +++ b/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c @@ -13,13 +13,29 @@ #include "ddrphy-regs.h" #include "umc-regs.h" +enum dram_freq { + DRAM_FREQ_1333M, + DRAM_FREQ_1600M, + DRAM_FREQ_NR, +}; + enum dram_size { DRAM_SZ_128M, DRAM_SZ_256M, + DRAM_SZ_512M, DRAM_SZ_NR, }; -static u32 umc_spcctla[DRAM_SZ_NR] = {0x00240512, 0x00350512}; +static u32 umc_cmdctla[DRAM_FREQ_NR] = {0x55990b11, 0x66bb0f17}; +static u32 umc_cmdctla_plus[DRAM_FREQ_NR] = {0x45990b11, 0x46bb0f17}; +static u32 umc_cmdctlb[DRAM_FREQ_NR] = {0x16958944, 0x18c6ab44}; +static u32 umc_cmdctlb_plus[DRAM_FREQ_NR] = {0x16958924, 0x18c6ab24}; +static u32 umc_spcctla[DRAM_FREQ_NR][DRAM_SZ_NR] = { + {0x00240512, 0x00350512, 0x00000000}, /* no data for 1333MHz,128MB */ + {0x002b0617, 0x003f0617, 0x00670617}, +}; +static u32 umc_spcctlb[DRAM_FREQ_NR] = {0x00ff0006, 0x00ff0008}; +static u32 umc_rdatactl[DRAM_FREQ_NR] = {0x000a00ac, 0x000c00ac}; static void umc_start_ssif(void __iomem *ssif_base) { @@ -58,8 +74,21 @@ static void umc_start_ssif(void __iomem *ssif_base) static int umc_dramcont_init(void __iomem *dramcont, void __iomem *ca_base, int size, int freq, bool ddr3plus) { + enum dram_freq freq_e; enum dram_size size_e; + switch (freq) { + case 1333: + freq_e = DRAM_FREQ_1333M; + break; + case 1600: + freq_e = DRAM_FREQ_1600M; + break; + default: + pr_err("unsupported DRAM frequency %d MHz\n", freq); + return -EINVAL; + } + switch (size) { case 0: return 0; @@ -69,16 +98,21 @@ static int umc_dramcont_init(void __iomem *dramcont, void __iomem *ca_base, case 2: size_e = DRAM_SZ_256M; break; + case 4: + size_e = DRAM_SZ_512M; + break; default: pr_err("unsupported DRAM size\n"); return -EINVAL; } - writel(ddr3plus ? 0x45990b11 : 0x55990b11, dramcont + UMC_CMDCTLA); - writel(ddr3plus ? 0x16958924 : 0x16958944, dramcont + UMC_CMDCTLB); - writel(umc_spcctla[size_e], dramcont + UMC_SPCCTLA); - writel(0x00ff0006, dramcont + UMC_SPCCTLB); - writel(0x000a00ac, dramcont + UMC_RDATACTL_D0); + writel((ddr3plus ? umc_cmdctla_plus : umc_cmdctla)[freq_e], + dramcont + UMC_CMDCTLA); + writel((ddr3plus ? umc_cmdctlb_plus : umc_cmdctlb)[freq_e], + dramcont + UMC_CMDCTLB); + writel(umc_spcctla[freq_e][size_e], dramcont + UMC_SPCCTLA); + writel(umc_spcctlb[freq_e], dramcont + UMC_SPCCTLB); + writel(umc_rdatactl[freq_e], dramcont + UMC_RDATACTL_D0); writel(0x04060806, dramcont + UMC_WDATACTL_D0); writel(0x04a02000, dramcont + UMC_DATASET); writel(0x00000000, ca_base + 0x2300); From 71d7ef35df49b94797ad6f32c23e23af4728b18d Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 14:21:46 +0900 Subject: [PATCH 26/38] ARM: uniphier: refactor UMC init code for PH1-LD4 Move frequency-dependent register settings to arrays for clean-up. Signed-off-by: Masahiro Yamada --- arch/arm/mach-uniphier/dram/umc-ph1-ld4.c | 79 ++++++++++++++++------- 1 file changed, 55 insertions(+), 24 deletions(-) diff --git a/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c b/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c index bee3ef4bff..353ef6939e 100644 --- a/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c +++ b/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c @@ -13,6 +13,27 @@ #include "ddrphy-regs.h" #include "umc-regs.h" +enum dram_freq { + DRAM_FREQ_1333M, + DRAM_FREQ_1600M, + DRAM_FREQ_NR, +}; + +enum dram_size { + DRAM_SZ_128M, + DRAM_SZ_256M, + DRAM_SZ_NR, +}; + +static u32 umc_cmdctla_plus[DRAM_FREQ_NR] = {0x45990b11, 0x36bb0f17}; +static u32 umc_cmdctlb_plus[DRAM_FREQ_NR] = {0x16958924, 0x18c6aa24}; +static u32 umc_spcctla[DRAM_FREQ_NR][DRAM_SZ_NR] = { + {0x00240512, 0x00350512}, + {0x002b0617, 0x003f0617}, +}; +static u32 umc_spcctlb[DRAM_FREQ_NR] = {0x00ff0006, 0x00ff0008}; +static u32 umc_rdatactl[DRAM_FREQ_NR] = {0x000a00ac, 0x000c00ae}; + static void umc_start_ssif(void __iomem *ssif_base) { writel(0x00000000, ssif_base + 0x0000b004); @@ -47,35 +68,43 @@ static void umc_start_ssif(void __iomem *ssif_base) writel(0x00000001, ssif_base + UMC_DMDRST); } -static void umc_dramcont_init(void __iomem *dramcont, void __iomem *ca_base, - int size, int freq) +static int umc_dramcont_init(void __iomem *dramcont, void __iomem *ca_base, + int size, int freq) { - if (freq == 1333) { - writel(0x45990b11, dramcont + UMC_CMDCTLA); - writel(0x16958924, dramcont + UMC_CMDCTLB); - } else if (freq == 1600) { - writel(0x36BB0F17, dramcont + UMC_CMDCTLA); - writel(0x18C6AA24, dramcont + UMC_CMDCTLB); + enum dram_freq freq_e; + enum dram_size size_e; + + switch (freq) { + case 1333: + freq_e = DRAM_FREQ_1333M; + break; + case 1600: + freq_e = DRAM_FREQ_1600M; + break; + default: + pr_err("unsupported DRAM frequency %d MHz\n", freq); + return -EINVAL; } - if (freq == 1333) { - if (size == 1) - writel(0x00240512, dramcont + UMC_SPCCTLA); - else if (size == 2) - writel(0x00350512, dramcont + UMC_SPCCTLA); - - writel(0x00ff0006, dramcont + UMC_SPCCTLB); - writel(0x000a00ac, dramcont + UMC_RDATACTL_D0); - } else if (freq == 1600) { - if (size == 1) - writel(0x002B0617, dramcont + UMC_SPCCTLA); - else if (size == 2) - writel(0x003F0617, dramcont + UMC_SPCCTLA); - - writel(0x00ff0008, dramcont + UMC_SPCCTLB); - writel(0x000c00ae, dramcont + UMC_RDATACTL_D0); + switch (size) { + case 0: + return 0; + case 1: + size_e = DRAM_SZ_128M; + break; + case 2: + size_e = DRAM_SZ_256M; + break; + default: + pr_err("unsupported DRAM size\n"); + return -EINVAL; } + writel(umc_cmdctla_plus[freq_e], dramcont + UMC_CMDCTLA); + writel(umc_cmdctlb_plus[freq_e], dramcont + UMC_CMDCTLB); + writel(umc_spcctla[freq_e][size_e], dramcont + UMC_SPCCTLA); + writel(umc_spcctlb[freq_e], dramcont + UMC_SPCCTLB); + writel(umc_rdatactl[freq_e], dramcont + UMC_RDATACTL_D0); writel(0x04060806, dramcont + UMC_WDATACTL_D0); writel(0x04a02000, dramcont + UMC_DATASET); writel(0x00000000, ca_base + 0x2300); @@ -94,6 +123,8 @@ static void umc_dramcont_init(void __iomem *dramcont, void __iomem *ca_base, writel(0x200a0a00, dramcont + UMC_SPCSETB); writel(0x00000000, dramcont + UMC_SPCSETD); writel(0x00000520, dramcont + UMC_DFICUPDCTLA); + + return 0; } static int umc_init_sub(int freq, int size_ch0, int size_ch1, bool ddr3plus) From c5985b4bbbb79d789bb4fe1ad9d6fd374ca9eda8 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 14:21:47 +0900 Subject: [PATCH 27/38] ARM: uniphier: optimize PH1-sLD8 UMC init code with "for" loop Now this code can be re-written with a "for" statement instead of calling the same function multiple times. Signed-off-by: Masahiro Yamada --- arch/arm/mach-uniphier/dram/umc-ph1-sld8.c | 79 +++++++++++----------- 1 file changed, 41 insertions(+), 38 deletions(-) diff --git a/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c b/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c index b8d729c925..a2ed9ba832 100644 --- a/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c +++ b/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c @@ -13,6 +13,8 @@ #include "ddrphy-regs.h" #include "umc-regs.h" +#define DRAM_CH_NR 2 + enum dram_freq { DRAM_FREQ_1333M, DRAM_FREQ_1600M, @@ -37,6 +39,11 @@ static u32 umc_spcctla[DRAM_FREQ_NR][DRAM_SZ_NR] = { static u32 umc_spcctlb[DRAM_FREQ_NR] = {0x00ff0006, 0x00ff0008}; static u32 umc_rdatactl[DRAM_FREQ_NR] = {0x000a00ac, 0x000c00ac}; +static int umc_get_rank(int ch) +{ + return ch; /* ch0: rank0, ch1: rank1 for this SoC */ +} + static void umc_start_ssif(void __iomem *ssif_base) { writel(0x00000000, ssif_base + 0x0000b004); @@ -135,55 +142,51 @@ static int umc_dramcont_init(void __iomem *dramcont, void __iomem *ca_base, return 0; } -static int umc_init_sub(int freq, int size_ch0, int size_ch1, bool ddr3plus) +static int umc_ch_init(void __iomem *dc_base, void __iomem *ca_base, + int freq, int size, bool ddr3plus, int ch) { - void __iomem *ssif_base = (void __iomem *)UMC_SSIF_BASE; - void __iomem *ca_base0 = (void __iomem *)UMC_CA_BASE(0); - void __iomem *ca_base1 = (void __iomem *)UMC_CA_BASE(1); - void __iomem *dramcont0 = (void __iomem *)UMC_DRAMCONT_BASE(0); - void __iomem *dramcont1 = (void __iomem *)UMC_DRAMCONT_BASE(1); - void __iomem *phy0_0 = (void __iomem *)DDRPHY_BASE(0, 0); - void __iomem *phy1_0 = (void __iomem *)DDRPHY_BASE(1, 0); + void __iomem *phy_base = dc_base + 0x00001000; + int ret; - umc_dram_init_start(dramcont0); - umc_dram_init_start(dramcont1); - umc_dram_init_poll(dramcont0); - umc_dram_init_poll(dramcont1); + umc_dram_init_start(dc_base); + umc_dram_init_poll(dc_base); - writel(0x00000101, dramcont0 + UMC_DIOCTLA); + writel(0x00000101, dc_base + UMC_DIOCTLA); - ph1_ld4_ddrphy_init(phy0_0, freq, ddr3plus); + ret = ph1_ld4_ddrphy_init(phy_base, freq, ddr3plus); + if (ret) + return ret; - ddrphy_prepare_training(phy0_0, 0); - ddrphy_training(phy0_0); + ddrphy_prepare_training(phy_base, umc_get_rank(ch)); + ret = ddrphy_training(phy_base); + if (ret) + return ret; - writel(0x00000101, dramcont1 + UMC_DIOCTLA); + return umc_dramcont_init(dc_base, ca_base, size, freq, ddr3plus); +} - ph1_ld4_ddrphy_init(phy1_0, freq, ddr3plus); +int ph1_sld8_umc_init(const struct uniphier_board_data *bd) +{ + void __iomem *umc_base = (void __iomem *)0x5b800000; + void __iomem *ca_base = umc_base + 0x00001000; + void __iomem *dc_base = umc_base + 0x00400000; + void __iomem *ssif_base = umc_base; + int ch, ret; - ddrphy_prepare_training(phy1_0, 1); - ddrphy_training(phy1_0); + for (ch = 0; ch < DRAM_CH_NR; ch++) { + ret = umc_ch_init(dc_base, ca_base, bd->dram_freq, + bd->dram_ch[ch].size / SZ_128M, + bd->dram_ddr3plus, ch); + if (ret) { + pr_err("failed to initialize UMC ch%d\n", ch); + return ret; + } - umc_dramcont_init(dramcont0, ca_base0, size_ch0, freq, ddr3plus); - umc_dramcont_init(dramcont1, ca_base1, size_ch1, freq, ddr3plus); + ca_base += 0x00001000; + dc_base += 0x00200000; + } umc_start_ssif(ssif_base); return 0; } - -int ph1_sld8_umc_init(const struct uniphier_board_data *bd) -{ - if ((bd->dram_ch[0].size == SZ_128M || bd->dram_ch[0].size == SZ_256M) && - (bd->dram_ch[1].size == SZ_128M || bd->dram_ch[1].size == SZ_256M) && - bd->dram_freq == 1333 && - bd->dram_ch[0].width == 16 && bd->dram_ch[1].width == 16) { - return umc_init_sub(bd->dram_freq, - bd->dram_ch[0].size / SZ_128M, - bd->dram_ch[1].size / SZ_128M, - bd->dram_ddr3plus); - } else { - pr_err("Unsupported DDR configuration\n"); - return -EINVAL; - } -} From b8708487958d3846aabf306387e5f1c10948f228 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 14:21:48 +0900 Subject: [PATCH 28/38] ARM: uniphier: optimize PH1-LD4 UMC init code with "for" loop Now this code can be re-written with a "for" statement instead of calling the same function multiple times. Signed-off-by: Masahiro Yamada --- arch/arm/mach-uniphier/dram/umc-ph1-ld4.c | 86 +++++++++++++---------- 1 file changed, 47 insertions(+), 39 deletions(-) diff --git a/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c b/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c index 353ef6939e..92b0f1832f 100644 --- a/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c +++ b/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c @@ -13,6 +13,8 @@ #include "ddrphy-regs.h" #include "umc-regs.h" +#define DRAM_CH_NR 2 + enum dram_freq { DRAM_FREQ_1333M, DRAM_FREQ_1600M, @@ -34,6 +36,11 @@ static u32 umc_spcctla[DRAM_FREQ_NR][DRAM_SZ_NR] = { static u32 umc_spcctlb[DRAM_FREQ_NR] = {0x00ff0006, 0x00ff0008}; static u32 umc_rdatactl[DRAM_FREQ_NR] = {0x000a00ac, 0x000c00ae}; +static int umc_get_rank(int ch) +{ + return ch; /* ch0: rank0, ch1: rank1 for this SoC */ +} + static void umc_start_ssif(void __iomem *ssif_base) { writel(0x00000000, ssif_base + 0x0000b004); @@ -69,11 +76,16 @@ static void umc_start_ssif(void __iomem *ssif_base) } static int umc_dramcont_init(void __iomem *dramcont, void __iomem *ca_base, - int size, int freq) + int size, int freq, bool ddr3plus) { enum dram_freq freq_e; enum dram_size size_e; + if (!ddr3plus) { + pr_err("DDR3 standard is not supported\n"); + return -EINVAL; + } + switch (freq) { case 1333: freq_e = DRAM_FREQ_1333M; @@ -127,55 +139,51 @@ static int umc_dramcont_init(void __iomem *dramcont, void __iomem *ca_base, return 0; } -static int umc_init_sub(int freq, int size_ch0, int size_ch1, bool ddr3plus) +static int umc_ch_init(void __iomem *dc_base, void __iomem *ca_base, + int freq, int size, bool ddr3plus, int ch) { - void __iomem *ssif_base = (void __iomem *)UMC_SSIF_BASE; - void __iomem *ca_base0 = (void __iomem *)UMC_CA_BASE(0); - void __iomem *ca_base1 = (void __iomem *)UMC_CA_BASE(1); - void __iomem *dramcont0 = (void __iomem *)UMC_DRAMCONT_BASE(0); - void __iomem *dramcont1 = (void __iomem *)UMC_DRAMCONT_BASE(1); - void __iomem *phy0_0 = (void __iomem *)DDRPHY_BASE(0, 0); - void __iomem *phy1_0 = (void __iomem *)DDRPHY_BASE(1, 0); + void __iomem *phy_base = dc_base + 0x00001000; + int ret; - umc_dram_init_start(dramcont0); - umc_dram_init_start(dramcont1); - umc_dram_init_poll(dramcont0); - umc_dram_init_poll(dramcont1); + umc_dram_init_start(dc_base); + umc_dram_init_poll(dc_base); - writel(0x00000101, dramcont0 + UMC_DIOCTLA); + writel(0x00000101, dc_base + UMC_DIOCTLA); - ph1_ld4_ddrphy_init(phy0_0, freq, ddr3plus); + ret = ph1_ld4_ddrphy_init(phy_base, freq, ddr3plus); + if (ret) + return ret; - ddrphy_prepare_training(phy0_0, 0); - ddrphy_training(phy0_0); + ddrphy_prepare_training(phy_base, umc_get_rank(ch)); + ret = ddrphy_training(phy_base); + if (ret) + return ret; - writel(0x00000101, dramcont1 + UMC_DIOCTLA); + return umc_dramcont_init(dc_base, ca_base, size, freq, ddr3plus); +} - ph1_ld4_ddrphy_init(phy1_0, freq, ddr3plus); +int ph1_ld4_umc_init(const struct uniphier_board_data *bd) +{ + void __iomem *umc_base = (void __iomem *)0x5b800000; + void __iomem *ca_base = umc_base + 0x00001000; + void __iomem *dc_base = umc_base + 0x00400000; + void __iomem *ssif_base = umc_base; + int ch, ret; - ddrphy_prepare_training(phy1_0, 1); - ddrphy_training(phy1_0); + for (ch = 0; ch < DRAM_CH_NR; ch++) { + ret = umc_ch_init(dc_base, ca_base, bd->dram_freq, + bd->dram_ch[ch].size / SZ_128M, + bd->dram_ddr3plus, ch); + if (ret) { + pr_err("failed to initialize UMC ch%d\n", ch); + return ret; + } - umc_dramcont_init(dramcont0, ca_base0, size_ch0, freq); - umc_dramcont_init(dramcont1, ca_base1, size_ch1, freq); + ca_base += 0x00001000; + dc_base += 0x00200000; + } umc_start_ssif(ssif_base); return 0; } - -int ph1_ld4_umc_init(const struct uniphier_board_data *bd) -{ - if ((bd->dram_ch[0].size == SZ_128M || bd->dram_ch[0].size == SZ_256M) && - (bd->dram_ch[1].size == SZ_128M || bd->dram_ch[1].size == SZ_256M) && - (bd->dram_freq == 1333 || bd->dram_freq == 1600) && - bd->dram_ch[0].width == 16 && bd->dram_ch[1].width == 16) { - return umc_init_sub(bd->dram_freq, - bd->dram_ch[0].size / SZ_128M, - bd->dram_ch[1].size / SZ_128M, - bd->dram_ddr3plus); - } else { - pr_err("Unsupported DDR configuration\n"); - return -EINVAL; - } -} From 9a71844a381b606d1c9c28c5974e389671ee1cd5 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 14:21:49 +0900 Subject: [PATCH 29/38] ARM: uniphier: optimize PH1-Pro4 UMC init code with "for" loop Now this code can be re-written with a "for" statement instead of calling the same function multiple times. Signed-off-by: Masahiro Yamada --- arch/arm/mach-uniphier/dram/umc-ph1-pro4.c | 116 +++++++++++---------- 1 file changed, 60 insertions(+), 56 deletions(-) diff --git a/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c b/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c index 0a2485e6ae..9569c1070a 100644 --- a/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c +++ b/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c @@ -13,6 +13,8 @@ #include "ddrphy-regs.h" #include "umc-regs.h" +#define DRAM_CH_NR 2 + enum dram_size { DRAM_SZ_128M, DRAM_SZ_256M, @@ -66,11 +68,21 @@ static void umc_start_ssif(void __iomem *ssif_base) } static int umc_dramcont_init(void __iomem *dramcont, void __iomem *ca_base, - int size, int width) + int freq, unsigned long size, bool ddr3plus) { enum dram_size dram_size; - switch (size / (width / 16)) { + if (freq != 1600) { + pr_err("Unsupported DDR frequency %d MHz\n", freq); + return -EINVAL; + } + + if (ddr3plus) { + pr_err("DDR3+ is not supported\n"); + return -EINVAL; + } + + switch (size) { case SZ_128M: dram_size = DRAM_SZ_128M; break; @@ -81,7 +93,7 @@ static int umc_dramcont_init(void __iomem *dramcont, void __iomem *ca_base, dram_size = DRAM_SZ_512M; break; default: - pr_err("unsupported DRAM size\n"); + pr_err("unsupported DRAM size 0x%08lx (per 16bit)\n", size); return -EINVAL; } @@ -113,66 +125,58 @@ static int umc_dramcont_init(void __iomem *dramcont, void __iomem *ca_base, return 0; } -int ph1_pro4_umc_init(const struct uniphier_board_data *bd) +static int umc_ch_init(void __iomem *dc_base, void __iomem *ca_base, + int freq, unsigned long size, unsigned int width, + bool ddr3plus) { - void __iomem *ssif_base = (void __iomem *)UMC_SSIF_BASE; - void __iomem *ca_base0 = (void __iomem *)UMC_CA_BASE(0); - void __iomem *ca_base1 = (void __iomem *)UMC_CA_BASE(1); - void __iomem *dramcont0 = (void __iomem *)UMC_DRAMCONT_BASE(0); - void __iomem *dramcont1 = (void __iomem *)UMC_DRAMCONT_BASE(1); - void __iomem *phy0_0 = (void __iomem *)DDRPHY_BASE(0, 0); - void __iomem *phy0_1 = (void __iomem *)DDRPHY_BASE(0, 1); - void __iomem *phy1_0 = (void __iomem *)DDRPHY_BASE(1, 0); - void __iomem *phy1_1 = (void __iomem *)DDRPHY_BASE(1, 1); - int ret; + void __iomem *phy_base = dc_base + 0x00001000; + int nr_phy = width / 16; + int phy, ret; - if (bd->dram_freq != 1600) { - pr_err("Unsupported DDR configuration\n"); - return -EINVAL; + umc_dram_init_start(dc_base); + umc_dram_init_poll(dc_base); + + for (phy = 0; phy < nr_phy; phy++) { + writel(0x00000100 | ((1 << (phy + 1)) - 1), + dc_base + UMC_DIOCTLA); + + ret = ph1_ld4_ddrphy_init(phy_base, freq, ddr3plus); + if (ret) + return ret; + + ddrphy_prepare_training(phy_base, phy); + ret = ddrphy_training(phy_base); + if (ret) + return ret; + + phy_base += 0x00001000; } - umc_dram_init_start(dramcont0); - umc_dram_init_start(dramcont1); - umc_dram_init_poll(dramcont0); - umc_dram_init_poll(dramcont1); + return umc_dramcont_init(dc_base, ca_base, freq, size / (width / 16), + ddr3plus); +} - writel(0x00000101, dramcont0 + UMC_DIOCTLA); +int ph1_pro4_umc_init(const struct uniphier_board_data *bd) +{ + void __iomem *umc_base = (void __iomem *)0x5b800000; + void __iomem *ca_base = umc_base + 0x00001000; + void __iomem *dc_base = umc_base + 0x00400000; + void __iomem *ssif_base = umc_base; + int ch, ret; - ph1_ld4_ddrphy_init(phy0_0, bd->dram_freq, bd->dram_ddr3plus); + for (ch = 0; ch < DRAM_CH_NR; ch++) { + ret = umc_ch_init(dc_base, ca_base, bd->dram_freq, + bd->dram_ch[ch].size, + bd->dram_ch[ch].width, + bd->dram_ddr3plus); + if (ret) { + pr_err("failed to initialize UMC ch%d\n", ch); + return ret; + } - ddrphy_prepare_training(phy0_0, 0); - ddrphy_training(phy0_0); - - writel(0x00000103, dramcont0 + UMC_DIOCTLA); - - ph1_ld4_ddrphy_init(phy0_1, bd->dram_freq, bd->dram_ddr3plus); - - ddrphy_prepare_training(phy0_1, 1); - ddrphy_training(phy0_1); - - writel(0x00000101, dramcont1 + UMC_DIOCTLA); - - ph1_ld4_ddrphy_init(phy1_0, bd->dram_freq, bd->dram_ddr3plus); - - ddrphy_prepare_training(phy1_0, 0); - ddrphy_training(phy1_0); - - writel(0x00000103, dramcont1 + UMC_DIOCTLA); - - ph1_ld4_ddrphy_init(phy1_1, bd->dram_freq, bd->dram_ddr3plus); - - ddrphy_prepare_training(phy1_1, 1); - ddrphy_training(phy1_1); - - ret = umc_dramcont_init(dramcont0, ca_base0, bd->dram_ch[0].size, - bd->dram_ch[0].width); - if (ret) - return ret; - - ret = umc_dramcont_init(dramcont1, ca_base1, bd->dram_ch[1].size, - bd->dram_ch[1].width); - if (ret) - return ret; + ca_base += 0x00001000; + dc_base += 0x00200000; + } umc_start_ssif(ssif_base); From fd14397e93894995116583aced817f2fad9ac57b Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 14:21:50 +0900 Subject: [PATCH 30/38] ARM: uniphier: rework DRAM size handling in UMC init code Currently, DRAM size is converted twice: size in byte -> size in Gbit -> enum Optimize the code by converting the "size in byte" into enum directly. Signed-off-by: Masahiro Yamada --- arch/arm/mach-uniphier/dram/umc-ph1-ld4.c | 14 +++++++------- arch/arm/mach-uniphier/dram/umc-ph1-sld8.c | 16 ++++++++-------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c b/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c index 92b0f1832f..0eb47d73d7 100644 --- a/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c +++ b/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c @@ -76,7 +76,7 @@ static void umc_start_ssif(void __iomem *ssif_base) } static int umc_dramcont_init(void __iomem *dramcont, void __iomem *ca_base, - int size, int freq, bool ddr3plus) + int freq, unsigned long size, bool ddr3plus) { enum dram_freq freq_e; enum dram_size size_e; @@ -101,14 +101,14 @@ static int umc_dramcont_init(void __iomem *dramcont, void __iomem *ca_base, switch (size) { case 0: return 0; - case 1: + case SZ_128M: size_e = DRAM_SZ_128M; break; - case 2: + case SZ_256M: size_e = DRAM_SZ_256M; break; default: - pr_err("unsupported DRAM size\n"); + pr_err("unsupported DRAM size 0x%08lx\n", size); return -EINVAL; } @@ -140,7 +140,7 @@ static int umc_dramcont_init(void __iomem *dramcont, void __iomem *ca_base, } static int umc_ch_init(void __iomem *dc_base, void __iomem *ca_base, - int freq, int size, bool ddr3plus, int ch) + int freq, unsigned long size, bool ddr3plus, int ch) { void __iomem *phy_base = dc_base + 0x00001000; int ret; @@ -159,7 +159,7 @@ static int umc_ch_init(void __iomem *dc_base, void __iomem *ca_base, if (ret) return ret; - return umc_dramcont_init(dc_base, ca_base, size, freq, ddr3plus); + return umc_dramcont_init(dc_base, ca_base, freq, size, ddr3plus); } int ph1_ld4_umc_init(const struct uniphier_board_data *bd) @@ -172,7 +172,7 @@ int ph1_ld4_umc_init(const struct uniphier_board_data *bd) for (ch = 0; ch < DRAM_CH_NR; ch++) { ret = umc_ch_init(dc_base, ca_base, bd->dram_freq, - bd->dram_ch[ch].size / SZ_128M, + bd->dram_ch[ch].size, bd->dram_ddr3plus, ch); if (ret) { pr_err("failed to initialize UMC ch%d\n", ch); diff --git a/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c b/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c index a2ed9ba832..43e53fd562 100644 --- a/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c +++ b/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c @@ -79,7 +79,7 @@ static void umc_start_ssif(void __iomem *ssif_base) } static int umc_dramcont_init(void __iomem *dramcont, void __iomem *ca_base, - int size, int freq, bool ddr3plus) + int freq, unsigned long size, bool ddr3plus) { enum dram_freq freq_e; enum dram_size size_e; @@ -99,17 +99,17 @@ static int umc_dramcont_init(void __iomem *dramcont, void __iomem *ca_base, switch (size) { case 0: return 0; - case 1: + case SZ_128M: size_e = DRAM_SZ_128M; break; - case 2: + case SZ_256M: size_e = DRAM_SZ_256M; break; - case 4: + case SZ_512M: size_e = DRAM_SZ_512M; break; default: - pr_err("unsupported DRAM size\n"); + pr_err("unsupported DRAM size 0x%08lx\n", size); return -EINVAL; } @@ -143,7 +143,7 @@ static int umc_dramcont_init(void __iomem *dramcont, void __iomem *ca_base, } static int umc_ch_init(void __iomem *dc_base, void __iomem *ca_base, - int freq, int size, bool ddr3plus, int ch) + int freq, unsigned long size, bool ddr3plus, int ch) { void __iomem *phy_base = dc_base + 0x00001000; int ret; @@ -162,7 +162,7 @@ static int umc_ch_init(void __iomem *dc_base, void __iomem *ca_base, if (ret) return ret; - return umc_dramcont_init(dc_base, ca_base, size, freq, ddr3plus); + return umc_dramcont_init(dc_base, ca_base, freq, size, ddr3plus); } int ph1_sld8_umc_init(const struct uniphier_board_data *bd) @@ -175,7 +175,7 @@ int ph1_sld8_umc_init(const struct uniphier_board_data *bd) for (ch = 0; ch < DRAM_CH_NR; ch++) { ret = umc_ch_init(dc_base, ca_base, bd->dram_freq, - bd->dram_ch[ch].size / SZ_128M, + bd->dram_ch[ch].size, bd->dram_ddr3plus, ch); if (ret) { pr_err("failed to initialize UMC ch%d\n", ch); From 7c9cac9c227b1a05ed1a63931f3c03950e9e6603 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 14:21:51 +0900 Subject: [PATCH 31/38] ARM: uniphier: remove unused macros for UMC base addresses These macros are no longer used. These base addresses are SoC-dependent, so they should not be placed in the header. Signed-off-by: Masahiro Yamada --- arch/arm/mach-uniphier/dram/umc-regs.h | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/arch/arm/mach-uniphier/dram/umc-regs.h b/arch/arm/mach-uniphier/dram/umc-regs.h index 311cf3d352..c65dd82a31 100644 --- a/arch/arm/mach-uniphier/dram/umc-regs.h +++ b/arch/arm/mach-uniphier/dram/umc-regs.h @@ -9,11 +9,6 @@ #ifndef ARCH_UMC_REGS_H #define ARCH_UMC_REGS_H -#define UMC_BASE 0x5b800000 - -/* SSIF registers */ -#define UMC_SSIF_BASE UMC_BASE - #define UMC_CPURST 0x00000700 #define UMC_IDSRST 0x0000070C #define UMC_IXMRST 0x00000714 @@ -48,12 +43,6 @@ #define UMC_CLKEN_SSIF_RC 0x0000C080 #define UMC_CLKEN_SSIF_DST 0x0000C084 -/* CA registers */ -#define UMC_CA_BASE(ch) (UMC_BASE + 0x00001000 + 0x00001000 * (ch)) - -/* DRAM controller registers */ -#define UMC_DRAMCONT_BASE(ch) (UMC_BASE + 0x00400000 + 0x00200000 * (ch)) - #define UMC_CMDCTLA 0x00000000 #define UMC_CMDCTLB 0x00000004 #define UMC_INITSET 0x00000014 From a191e0dee02b3fb041880131535fe6b307e6b70d Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 14:21:52 +0900 Subject: [PATCH 32/38] ARM: uniphier: deprecate umc_dram_init_{start, poll} Signed-off-by: Masahiro Yamada --- arch/arm/mach-uniphier/dram/umc-ph1-ld4.c | 6 ++++-- arch/arm/mach-uniphier/dram/umc-ph1-pro4.c | 6 ++++-- arch/arm/mach-uniphier/dram/umc-ph1-sld8.c | 6 ++++-- arch/arm/mach-uniphier/dram/umc-regs.h | 23 ++++++---------------- 4 files changed, 18 insertions(+), 23 deletions(-) diff --git a/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c b/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c index 0eb47d73d7..09b2c1ce27 100644 --- a/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c +++ b/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c @@ -8,6 +8,7 @@ #include #include #include +#include #include "../init.h" #include "ddrphy-regs.h" @@ -145,8 +146,9 @@ static int umc_ch_init(void __iomem *dc_base, void __iomem *ca_base, void __iomem *phy_base = dc_base + 0x00001000; int ret; - umc_dram_init_start(dc_base); - umc_dram_init_poll(dc_base); + writel(UMC_INITSET_INIT1EN, dc_base + UMC_INITSET); + while (readl(dc_base + UMC_INITSET) & UMC_INITSTAT_INIT1ST) + cpu_relax(); writel(0x00000101, dc_base + UMC_DIOCTLA); diff --git a/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c b/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c index 9569c1070a..93d2e2c2a1 100644 --- a/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c +++ b/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c @@ -8,6 +8,7 @@ #include #include #include +#include #include "../init.h" #include "ddrphy-regs.h" @@ -133,8 +134,9 @@ static int umc_ch_init(void __iomem *dc_base, void __iomem *ca_base, int nr_phy = width / 16; int phy, ret; - umc_dram_init_start(dc_base); - umc_dram_init_poll(dc_base); + writel(UMC_INITSET_INIT1EN, dc_base + UMC_INITSET); + while (readl(dc_base + UMC_INITSET) & UMC_INITSTAT_INIT1ST) + cpu_relax(); for (phy = 0; phy < nr_phy; phy++) { writel(0x00000100 | ((1 << (phy + 1)) - 1), diff --git a/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c b/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c index 43e53fd562..d873130f9a 100644 --- a/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c +++ b/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c @@ -8,6 +8,7 @@ #include #include #include +#include #include "../init.h" #include "ddrphy-regs.h" @@ -148,8 +149,9 @@ static int umc_ch_init(void __iomem *dc_base, void __iomem *ca_base, void __iomem *phy_base = dc_base + 0x00001000; int ret; - umc_dram_init_start(dc_base); - umc_dram_init_poll(dc_base); + writel(UMC_INITSET_INIT1EN, dc_base + UMC_INITSET); + while (readl(dc_base + UMC_INITSET) & UMC_INITSTAT_INIT1ST) + cpu_relax(); writel(0x00000101, dc_base + UMC_DIOCTLA); diff --git a/arch/arm/mach-uniphier/dram/umc-regs.h b/arch/arm/mach-uniphier/dram/umc-regs.h index c65dd82a31..cc2dd27abf 100644 --- a/arch/arm/mach-uniphier/dram/umc-regs.h +++ b/arch/arm/mach-uniphier/dram/umc-regs.h @@ -9,6 +9,8 @@ #ifndef ARCH_UMC_REGS_H #define ARCH_UMC_REGS_H +#include + #define UMC_CPURST 0x00000700 #define UMC_IDSRST 0x0000070C #define UMC_IXMRST 0x00000714 @@ -46,7 +48,11 @@ #define UMC_CMDCTLA 0x00000000 #define UMC_CMDCTLB 0x00000004 #define UMC_INITSET 0x00000014 +#define UMC_INITSET_INIT1EN BIT(1) /* init without power-on wait */ +#define UMC_INITSET_INIT0EN BIT(0) /* init with power-on wait */ #define UMC_INITSTAT 0x00000018 +#define UMC_INITSTAT_INIT1ST BIT(1) /* init without power-on wait */ +#define UMC_INITSTAT_INIT0ST BIT(0) /* init with power-on wait */ #define UMC_SPCCTLA 0x00000030 #define UMC_SPCCTLB 0x00000034 #define UMC_SPCSETA 0x00000038 @@ -98,21 +104,4 @@ #define UMC_BITPERPIXELMODE_D0 0x010 #define UMC_PAIR1DOFF_D0 0x054 -#ifndef __ASSEMBLY__ - -#include - -static inline void umc_dram_init_start(void __iomem *dramcont) -{ - writel(0x00000002, dramcont + UMC_INITSET); -} - -static inline void umc_dram_init_poll(void __iomem *dramcont) -{ - while ((readl(dramcont + UMC_INITSTAT) & 0x00000002)) - ; -} - -#endif - #endif From 4e651003e5413530aaea6ff00841ef52fb48b797 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 14:21:53 +0900 Subject: [PATCH 33/38] ARM: uniphier: rename variable for DRAM controller base address Rename the variable that contains the base address for consistency. Signed-off-by: Masahiro Yamada --- arch/arm/mach-uniphier/dram/umc-ph1-ld4.c | 44 +++++----- arch/arm/mach-uniphier/dram/umc-ph1-pro4.c | 54 ++++++------ arch/arm/mach-uniphier/dram/umc-ph1-sld8.c | 44 +++++----- arch/arm/mach-uniphier/dram/umc-proxstream2.c | 85 +++++++++---------- 4 files changed, 113 insertions(+), 114 deletions(-) diff --git a/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c b/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c index 09b2c1ce27..72447cc776 100644 --- a/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c +++ b/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c @@ -76,7 +76,7 @@ static void umc_start_ssif(void __iomem *ssif_base) writel(0x00000001, ssif_base + UMC_DMDRST); } -static int umc_dramcont_init(void __iomem *dramcont, void __iomem *ca_base, +static int umc_dramcont_init(void __iomem *dc_base, void __iomem *ca_base, int freq, unsigned long size, bool ddr3plus) { enum dram_freq freq_e; @@ -113,29 +113,29 @@ static int umc_dramcont_init(void __iomem *dramcont, void __iomem *ca_base, return -EINVAL; } - writel(umc_cmdctla_plus[freq_e], dramcont + UMC_CMDCTLA); - writel(umc_cmdctlb_plus[freq_e], dramcont + UMC_CMDCTLB); - writel(umc_spcctla[freq_e][size_e], dramcont + UMC_SPCCTLA); - writel(umc_spcctlb[freq_e], dramcont + UMC_SPCCTLB); - writel(umc_rdatactl[freq_e], dramcont + UMC_RDATACTL_D0); - writel(0x04060806, dramcont + UMC_WDATACTL_D0); - writel(0x04a02000, dramcont + UMC_DATASET); + writel(umc_cmdctla_plus[freq_e], dc_base + UMC_CMDCTLA); + writel(umc_cmdctlb_plus[freq_e], dc_base + UMC_CMDCTLB); + writel(umc_spcctla[freq_e][size_e], dc_base + UMC_SPCCTLA); + writel(umc_spcctlb[freq_e], dc_base + UMC_SPCCTLB); + writel(umc_rdatactl[freq_e], dc_base + UMC_RDATACTL_D0); + writel(0x04060806, dc_base + UMC_WDATACTL_D0); + writel(0x04a02000, dc_base + UMC_DATASET); writel(0x00000000, ca_base + 0x2300); - writel(0x00400020, dramcont + UMC_DCCGCTL); - writel(0x00000003, dramcont + 0x7000); - writel(0x0000000f, dramcont + 0x8000); - writel(0x000000c3, dramcont + 0x8004); - writel(0x00000071, dramcont + 0x8008); - writel(0x0000003b, dramcont + UMC_DICGCTLA); - writel(0x020a0808, dramcont + UMC_DICGCTLB); - writel(0x00000004, dramcont + UMC_FLOWCTLG); + writel(0x00400020, dc_base + UMC_DCCGCTL); + writel(0x00000003, dc_base + 0x7000); + writel(0x0000000f, dc_base + 0x8000); + writel(0x000000c3, dc_base + 0x8004); + writel(0x00000071, dc_base + 0x8008); + writel(0x0000003b, dc_base + UMC_DICGCTLA); + writel(0x020a0808, dc_base + UMC_DICGCTLB); + writel(0x00000004, dc_base + UMC_FLOWCTLG); writel(0x80000201, ca_base + 0xc20); - writel(0x0801e01e, dramcont + UMC_FLOWCTLA); - writel(0x00200000, dramcont + UMC_FLOWCTLB); - writel(0x00004444, dramcont + UMC_FLOWCTLC); - writel(0x200a0a00, dramcont + UMC_SPCSETB); - writel(0x00000000, dramcont + UMC_SPCSETD); - writel(0x00000520, dramcont + UMC_DFICUPDCTLA); + writel(0x0801e01e, dc_base + UMC_FLOWCTLA); + writel(0x00200000, dc_base + UMC_FLOWCTLB); + writel(0x00004444, dc_base + UMC_FLOWCTLC); + writel(0x200a0a00, dc_base + UMC_SPCSETB); + writel(0x00000000, dc_base + UMC_SPCSETD); + writel(0x00000520, dc_base + UMC_DFICUPDCTLA); return 0; } diff --git a/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c b/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c index 93d2e2c2a1..23fb7b9f53 100644 --- a/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c +++ b/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c @@ -68,10 +68,10 @@ static void umc_start_ssif(void __iomem *ssif_base) writel(0x00000001, ssif_base + UMC_DMDRST); } -static int umc_dramcont_init(void __iomem *dramcont, void __iomem *ca_base, +static int umc_dramcont_init(void __iomem *dc_base, void __iomem *ca_base, int freq, unsigned long size, bool ddr3plus) { - enum dram_size dram_size; + enum dram_size size_e; if (freq != 1600) { pr_err("Unsupported DDR frequency %d MHz\n", freq); @@ -85,43 +85,43 @@ static int umc_dramcont_init(void __iomem *dramcont, void __iomem *ca_base, switch (size) { case SZ_128M: - dram_size = DRAM_SZ_128M; + size_e = DRAM_SZ_128M; break; case SZ_256M: - dram_size = DRAM_SZ_256M; + size_e = DRAM_SZ_256M; break; case SZ_512M: - dram_size = DRAM_SZ_512M; + size_e = DRAM_SZ_512M; break; default: pr_err("unsupported DRAM size 0x%08lx (per 16bit)\n", size); return -EINVAL; } - writel(0x66bb0f17, dramcont + UMC_CMDCTLA); - writel(0x18c6aa44, dramcont + UMC_CMDCTLB); - writel(umc_spcctla[dram_size], dramcont + UMC_SPCCTLA); - writel(0x00ff0008, dramcont + UMC_SPCCTLB); - writel(0x000c00ae, dramcont + UMC_RDATACTL_D0); - writel(0x000c00ae, dramcont + UMC_RDATACTL_D1); - writel(0x04060802, dramcont + UMC_WDATACTL_D0); - writel(0x04060802, dramcont + UMC_WDATACTL_D1); - writel(0x04a02000, dramcont + UMC_DATASET); + writel(0x66bb0f17, dc_base + UMC_CMDCTLA); + writel(0x18c6aa44, dc_base + UMC_CMDCTLB); + writel(umc_spcctla[size_e], dc_base + UMC_SPCCTLA); + writel(0x00ff0008, dc_base + UMC_SPCCTLB); + writel(0x000c00ae, dc_base + UMC_RDATACTL_D0); + writel(0x000c00ae, dc_base + UMC_RDATACTL_D1); + writel(0x04060802, dc_base + UMC_WDATACTL_D0); + writel(0x04060802, dc_base + UMC_WDATACTL_D1); + writel(0x04a02000, dc_base + UMC_DATASET); writel(0x00000000, ca_base + 0x2300); - writel(0x00400020, dramcont + UMC_DCCGCTL); - writel(0x0000000f, dramcont + 0x7000); - writel(0x0000000f, dramcont + 0x8000); - writel(0x000000c3, dramcont + 0x8004); - writel(0x00000071, dramcont + 0x8008); - writel(0x00000004, dramcont + UMC_FLOWCTLG); - writel(0x00000000, dramcont + 0x0060); + writel(0x00400020, dc_base + UMC_DCCGCTL); + writel(0x0000000f, dc_base + 0x7000); + writel(0x0000000f, dc_base + 0x8000); + writel(0x000000c3, dc_base + 0x8004); + writel(0x00000071, dc_base + 0x8008); + writel(0x00000004, dc_base + UMC_FLOWCTLG); + writel(0x00000000, dc_base + 0x0060); writel(0x80000201, ca_base + 0xc20); - writel(0x0801e01e, dramcont + UMC_FLOWCTLA); - writel(0x00200000, dramcont + UMC_FLOWCTLB); - writel(0x00004444, dramcont + UMC_FLOWCTLC); - writel(0x200a0a00, dramcont + UMC_SPCSETB); - writel(0x00010000, dramcont + UMC_SPCSETD); - writel(0x80000020, dramcont + UMC_DFICUPDCTLA); + writel(0x0801e01e, dc_base + UMC_FLOWCTLA); + writel(0x00200000, dc_base + UMC_FLOWCTLB); + writel(0x00004444, dc_base + UMC_FLOWCTLC); + writel(0x200a0a00, dc_base + UMC_SPCSETB); + writel(0x00010000, dc_base + UMC_SPCSETD); + writel(0x80000020, dc_base + UMC_DFICUPDCTLA); return 0; } diff --git a/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c b/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c index d873130f9a..6cacd25e7c 100644 --- a/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c +++ b/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c @@ -79,7 +79,7 @@ static void umc_start_ssif(void __iomem *ssif_base) writel(0x00000001, ssif_base + UMC_DMDRST); } -static int umc_dramcont_init(void __iomem *dramcont, void __iomem *ca_base, +static int umc_dramcont_init(void __iomem *dc_base, void __iomem *ca_base, int freq, unsigned long size, bool ddr3plus) { enum dram_freq freq_e; @@ -115,30 +115,30 @@ static int umc_dramcont_init(void __iomem *dramcont, void __iomem *ca_base, } writel((ddr3plus ? umc_cmdctla_plus : umc_cmdctla)[freq_e], - dramcont + UMC_CMDCTLA); + dc_base + UMC_CMDCTLA); writel((ddr3plus ? umc_cmdctlb_plus : umc_cmdctlb)[freq_e], - dramcont + UMC_CMDCTLB); - writel(umc_spcctla[freq_e][size_e], dramcont + UMC_SPCCTLA); - writel(umc_spcctlb[freq_e], dramcont + UMC_SPCCTLB); - writel(umc_rdatactl[freq_e], dramcont + UMC_RDATACTL_D0); - writel(0x04060806, dramcont + UMC_WDATACTL_D0); - writel(0x04a02000, dramcont + UMC_DATASET); + dc_base + UMC_CMDCTLB); + writel(umc_spcctla[freq_e][size_e], dc_base + UMC_SPCCTLA); + writel(umc_spcctlb[freq_e], dc_base + UMC_SPCCTLB); + writel(umc_rdatactl[freq_e], dc_base + UMC_RDATACTL_D0); + writel(0x04060806, dc_base + UMC_WDATACTL_D0); + writel(0x04a02000, dc_base + UMC_DATASET); writel(0x00000000, ca_base + 0x2300); - writel(0x00400020, dramcont + UMC_DCCGCTL); - writel(0x00000003, dramcont + 0x7000); - writel(0x0000004f, dramcont + 0x8000); - writel(0x000000c3, dramcont + 0x8004); - writel(0x00000077, dramcont + 0x8008); - writel(0x0000003b, dramcont + UMC_DICGCTLA); - writel(0x020a0808, dramcont + UMC_DICGCTLB); - writel(0x00000004, dramcont + UMC_FLOWCTLG); + writel(0x00400020, dc_base + UMC_DCCGCTL); + writel(0x00000003, dc_base + 0x7000); + writel(0x0000004f, dc_base + 0x8000); + writel(0x000000c3, dc_base + 0x8004); + writel(0x00000077, dc_base + 0x8008); + writel(0x0000003b, dc_base + UMC_DICGCTLA); + writel(0x020a0808, dc_base + UMC_DICGCTLB); + writel(0x00000004, dc_base + UMC_FLOWCTLG); writel(0x80000201, ca_base + 0xc20); - writel(0x0801e01e, dramcont + UMC_FLOWCTLA); - writel(0x00200000, dramcont + UMC_FLOWCTLB); - writel(0x00004444, dramcont + UMC_FLOWCTLC); - writel(0x200a0a00, dramcont + UMC_SPCSETB); - writel(0x00000000, dramcont + UMC_SPCSETD); - writel(0x00000520, dramcont + UMC_DFICUPDCTLA); + writel(0x0801e01e, dc_base + UMC_FLOWCTLA); + writel(0x00200000, dc_base + UMC_FLOWCTLB); + writel(0x00004444, dc_base + UMC_FLOWCTLC); + writel(0x200a0a00, dc_base + UMC_SPCSETB); + writel(0x00000000, dc_base + UMC_SPCSETD); + writel(0x00000520, dc_base + UMC_DFICUPDCTLA); return 0; } diff --git a/arch/arm/mach-uniphier/dram/umc-proxstream2.c b/arch/arm/mach-uniphier/dram/umc-proxstream2.c index 86909062b6..50c023825e 100644 --- a/arch/arm/mach-uniphier/dram/umc-proxstream2.c +++ b/arch/arm/mach-uniphier/dram/umc-proxstream2.c @@ -404,12 +404,12 @@ static int ddrphy_training(void __iomem *phy_base) } /* UMC */ -static void umc_set_system_latency(void __iomem *umc_dc_base, int phy_latency) +static void umc_set_system_latency(void __iomem *dc_base, int phy_latency) { u32 val; int latency; - val = readl(umc_dc_base + UMC_RDATACTL_D0); + val = readl(dc_base + UMC_RDATACTL_D0); latency = (val & UMC_RDATACTL_RADLTY_MASK) >> UMC_RDATACTL_RADLTY_SHIFT; latency += (val & UMC_RDATACTL_RAD2LTY_MASK) >> UMC_RDATACTL_RAD2LTY_SHIFT; @@ -427,18 +427,18 @@ static void umc_set_system_latency(void __iomem *umc_dc_base, int phy_latency) val |= latency << UMC_RDATACTL_RADLTY_SHIFT; } - writel(val, umc_dc_base + UMC_RDATACTL_D0); - writel(val, umc_dc_base + UMC_RDATACTL_D1); + writel(val, dc_base + UMC_RDATACTL_D0); + writel(val, dc_base + UMC_RDATACTL_D1); - readl(umc_dc_base + UMC_RDATACTL_D1); /* relax */ + readl(dc_base + UMC_RDATACTL_D1); /* relax */ } /* enable/disable auto refresh */ -void umc_refresh_ctrl(void __iomem *umc_dc_base, int enable) +void umc_refresh_ctrl(void __iomem *dc_base, int enable) { u32 tmp; - tmp = readl(umc_dc_base + UMC_SPCSETB); + tmp = readl(dc_base + UMC_SPCSETB); tmp &= ~UMC_SPCSETB_AREFMD_MASK; if (enable) @@ -446,7 +446,7 @@ void umc_refresh_ctrl(void __iomem *umc_dc_base, int enable) else tmp |= UMC_SPCSETB_AREFMD_REG; - writel(tmp, umc_dc_base + UMC_SPCSETB); + writel(tmp, dc_base + UMC_SPCSETB); udelay(1); } @@ -458,7 +458,7 @@ static void umc_ud_init(void __iomem *umc_base, int ch) writel(0x00000033, umc_base + UMC_PAIR1DOFF_D0); } -static int umc_dc_init(void __iomem *umc_dc_base, enum dram_freq freq, +static int umc_dc_init(void __iomem *dc_base, enum dram_freq freq, unsigned long size, int width, int ch) { enum dram_size size_e; @@ -480,14 +480,13 @@ static int umc_dc_init(void __iomem *umc_dc_base, enum dram_freq freq, return -EINVAL; } - writel(umc_cmdctla[freq], umc_dc_base + UMC_CMDCTLA); + writel(umc_cmdctla[freq], dc_base + UMC_CMDCTLA); writel(ch == 2 ? umc_cmdctlb_ch2[freq] : umc_cmdctlb_ch01[freq], - umc_dc_base + UMC_CMDCTLB); + dc_base + UMC_CMDCTLB); - writel(umc_spcctla[freq][size_e], - umc_dc_base + UMC_SPCCTLA); - writel(umc_spcctlb[freq], umc_dc_base + UMC_SPCCTLB); + writel(umc_spcctla[freq][size_e], dc_base + UMC_SPCCTLA); + writel(umc_spcctlb[freq], dc_base + UMC_SPCCTLB); val = 0x000e000e; latency = 12; @@ -502,38 +501,38 @@ static int umc_dc_init(void __iomem *umc_dc_base, enum dram_freq freq, val |= latency << UMC_RDATACTL_RADLTY_SHIFT; } - writel(val, umc_dc_base + UMC_RDATACTL_D0); + writel(val, dc_base + UMC_RDATACTL_D0); if (width >= 32) - writel(val, umc_dc_base + UMC_RDATACTL_D1); + writel(val, dc_base + UMC_RDATACTL_D1); - writel(0x04060A02, umc_dc_base + UMC_WDATACTL_D0); + writel(0x04060A02, dc_base + UMC_WDATACTL_D0); if (width >= 32) - writel(0x04060A02, umc_dc_base + UMC_WDATACTL_D1); - writel(0x04000000, umc_dc_base + UMC_DATASET); - writel(0x00400020, umc_dc_base + UMC_DCCGCTL); - writel(0x00000084, umc_dc_base + UMC_FLOWCTLG); - writel(0x00000000, umc_dc_base + UMC_ACSSETA); + writel(0x04060A02, dc_base + UMC_WDATACTL_D1); + writel(0x04000000, dc_base + UMC_DATASET); + writel(0x00400020, dc_base + UMC_DCCGCTL); + writel(0x00000084, dc_base + UMC_FLOWCTLG); + writel(0x00000000, dc_base + UMC_ACSSETA); writel(ch == 2 ? umc_flowctla_ch2[freq] : umc_flowctla_ch01[freq], - umc_dc_base + UMC_FLOWCTLA); + dc_base + UMC_FLOWCTLA); - writel(0x00004400, umc_dc_base + UMC_FLOWCTLC); - writel(0x200A0A00, umc_dc_base + UMC_SPCSETB); - writel(0x00000520, umc_dc_base + UMC_DFICUPDCTLA); - writel(0x0000000D, umc_dc_base + UMC_RESPCTL); + writel(0x00004400, dc_base + UMC_FLOWCTLC); + writel(0x200A0A00, dc_base + UMC_SPCSETB); + writel(0x00000520, dc_base + UMC_DFICUPDCTLA); + writel(0x0000000D, dc_base + UMC_RESPCTL); if (ch != 2) { - writel(0x00202000, umc_dc_base + UMC_FLOWCTLB); - writel(0xFDBFFFFF, umc_dc_base + UMC_FLOWCTLOB0); - writel(0xFFFFFFFF, umc_dc_base + UMC_FLOWCTLOB1); - writel(0x00080700, umc_dc_base + UMC_BSICMAPSET); + writel(0x00202000, dc_base + UMC_FLOWCTLB); + writel(0xFDBFFFFF, dc_base + UMC_FLOWCTLOB0); + writel(0xFFFFFFFF, dc_base + UMC_FLOWCTLOB1); + writel(0x00080700, dc_base + UMC_BSICMAPSET); } else { - writel(0x00200000, umc_dc_base + UMC_FLOWCTLB); - writel(0x00000000, umc_dc_base + UMC_BSICMAPSET); + writel(0x00200000, dc_base + UMC_FLOWCTLB); + writel(0x00000000, dc_base + UMC_BSICMAPSET); } - writel(0x00000000, umc_dc_base + UMC_ERRMASKA); - writel(0x00000000, umc_dc_base + UMC_ERRMASKB); + writel(0x00000000, dc_base + UMC_ERRMASKA); + writel(0x00000000, dc_base + UMC_ERRMASKB); return 0; } @@ -541,17 +540,17 @@ static int umc_dc_init(void __iomem *umc_dc_base, enum dram_freq freq, static int umc_ch_init(void __iomem *umc_ch_base, enum dram_freq freq, unsigned long size, unsigned int width, int ch) { - void __iomem *umc_dc_base = umc_ch_base + 0x00011000; + void __iomem *dc_base = umc_ch_base + 0x00011000; void __iomem *phy_base = umc_ch_base + 0x00030000; int ret; - writel(0x00000002, umc_dc_base + UMC_INITSET); - while (readl(umc_dc_base + UMC_INITSTAT) & BIT(2)) + writel(0x00000002, dc_base + UMC_INITSET); + while (readl(dc_base + UMC_INITSTAT) & BIT(2)) cpu_relax(); /* deassert PHY reset signals */ writel(UMC_DIOCTLA_CTL_NRST | UMC_DIOCTLA_CFG_NRST, - umc_dc_base + UMC_DIOCTLA); + dc_base + UMC_DIOCTLA); ddrphy_init(phy_base, freq, width, ch); @@ -563,7 +562,7 @@ static int umc_ch_init(void __iomem *umc_ch_base, enum dram_freq freq, if (ret) return ret; - ret = umc_dc_init(umc_dc_base, freq, size, width, ch); + ret = umc_dc_init(dc_base, freq, size, width, ch); if (ret) return ret; @@ -576,15 +575,15 @@ static int umc_ch_init(void __iomem *umc_ch_base, enum dram_freq freq, udelay(1); /* match the system latency between UMC and PHY */ - umc_set_system_latency(umc_dc_base, + umc_set_system_latency(dc_base, ddrphy_get_system_latency(phy_base, width)); udelay(1); /* stop auto refresh before clearing FIFO in PHY */ - umc_refresh_ctrl(umc_dc_base, 0); + umc_refresh_ctrl(dc_base, 0); ddrphy_fifo_reset(phy_base); - umc_refresh_ctrl(umc_dc_base, 1); + umc_refresh_ctrl(dc_base, 1); udelay(10); From fe7c95ee5c2e4a757941221ae3b624c78bdaf068 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 18:59:41 +0900 Subject: [PATCH 34/38] ARM: uniphier: merge two defconfig files PH1-Pro5 support and ProXstream2/PH1-LD6b support can coexist in one image and there is bit more room in SPL to accommodate all of them. Merge uniphier_pro5_defconfig into uniphier_pxs2_defconfig. Signed-off-by: Masahiro Yamada --- configs/uniphier_pro5_defconfig | 33 ---------------------------- configs/uniphier_pxs2_ld6b_defconfig | 1 + doc/README.uniphier | 4 ++-- 3 files changed, 3 insertions(+), 35 deletions(-) delete mode 100644 configs/uniphier_pro5_defconfig diff --git a/configs/uniphier_pro5_defconfig b/configs/uniphier_pro5_defconfig deleted file mode 100644 index 0029cd3ff9..0000000000 --- a/configs/uniphier_pro5_defconfig +++ /dev/null @@ -1,33 +0,0 @@ -CONFIG_ARM=y -CONFIG_ARCH_UNIPHIER=y -CONFIG_SYS_MALLOC_F_LEN=0x2000 -CONFIG_ARCH_UNIPHIER_PH1_PRO5=y -CONFIG_MICRO_SUPPORT_CARD=y -CONFIG_SYS_TEXT_BASE=0x84000000 -CONFIG_DEFAULT_DEVICE_TREE="uniphier-ph1-pro5-4kbox" -CONFIG_HUSH_PARSER=y -# CONFIG_CMD_XIMG is not set -# CONFIG_CMD_ENV_EXISTS is not set -CONFIG_CMD_NAND=y -CONFIG_CMD_I2C=y -CONFIG_CMD_USB=y -# CONFIG_CMD_FPGA is not set -CONFIG_CMD_GPIO=y -CONFIG_CMD_TFTPPUT=y -CONFIG_CMD_PING=y -CONFIG_CMD_TIME=y -# CONFIG_CMD_MISC is not set -CONFIG_NET_RANDOM_ETHADDR=y -CONFIG_SPL_SIMPLE_BUS=y -CONFIG_GPIO_UNIPHIER=y -CONFIG_MMC_UNIPHIER=y -CONFIG_NAND_DENALI=y -CONFIG_SYS_NAND_DENALI_64BIT=y -CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8 -CONFIG_SPL_NAND_DENALI=y -CONFIG_PINCTRL=y -CONFIG_SPL_PINCTRL=y -CONFIG_UNIPHIER_SERIAL=y -CONFIG_USB=y -CONFIG_USB_XHCI_HCD=y -CONFIG_USB_STORAGE=y diff --git a/configs/uniphier_pxs2_ld6b_defconfig b/configs/uniphier_pxs2_ld6b_defconfig index 0115c215f8..10af9c884b 100644 --- a/configs/uniphier_pxs2_ld6b_defconfig +++ b/configs/uniphier_pxs2_ld6b_defconfig @@ -1,6 +1,7 @@ CONFIG_ARM=y CONFIG_ARCH_UNIPHIER=y CONFIG_SYS_MALLOC_F_LEN=0x2000 +CONFIG_ARCH_UNIPHIER_PH1_PRO5=y CONFIG_ARCH_UNIPHIER_PROXSTREAM2=y CONFIG_ARCH_UNIPHIER_PH1_LD6B=y CONFIG_MICRO_SUPPORT_CARD=y diff --git a/doc/README.uniphier b/doc/README.uniphier index 5ac52bd41f..6c3b0924b2 100644 --- a/doc/README.uniphier +++ b/doc/README.uniphier @@ -45,8 +45,8 @@ PH1-Pro4 reference board: $ make CROSS_COMPILE=arm-linux-gnueabi- PH1-Pro5 4KBOX Board: - $ make uniphier_pro5_defconfig - $ make CROSS_COMPILE=arm-linux-gnueabi- + $ make uniphier_pxs2_ld6b_defconfig + $ make CROSS_COMPILE=arm-linux-gnueabi- DEVICE_TREE=uniphier-ph1-pro5-4kbox ProXstream2 Gentil board: $ make uniphier_pxs2_ld6b_defconfig From 5fb87a1632fbc7b5079b1497aff41de20647c759 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 18:59:42 +0900 Subject: [PATCH 35/38] ARM: uniphier: rework UniPhier SoC select in Kconfig The chains of "depends on " in the current Kconfig is clumsy. The idea here is to allow users to choose a SoC group first (SoC group consists of some SoCs that can coexist in one binary). Then, allow to enable/disable each SoC support in the selected SoC group. This makes the Kconfig menu clearer. Signed-off-by: Masahiro Yamada --- arch/arm/mach-uniphier/Kconfig | 62 +++++++++++++--------------- configs/uniphier_ld4_sld8_defconfig | 3 +- configs/uniphier_pxs2_ld6b_defconfig | 4 +- 3 files changed, 30 insertions(+), 39 deletions(-) diff --git a/arch/arm/mach-uniphier/Kconfig b/arch/arm/mach-uniphier/Kconfig index 03256be403..e859ca3ada 100644 --- a/arch/arm/mach-uniphier/Kconfig +++ b/arch/arm/mach-uniphier/Kconfig @@ -3,54 +3,48 @@ if ARCH_UNIPHIER config SYS_CONFIG_NAME default "uniphier" +choice + prompt "UniPhier SoC select" + default ARCH_UNIPHIER_PH1_PRO4 + config ARCH_UNIPHIER_PH1_SLD3 bool "UniPhier PH1-sLD3 SoC" - help - This enables support for UniPhier PH1-sLD3 SoC. -config ARCH_UNIPHIER_PH1_LD4 - bool "UniPhier PH1-LD4 SoC" - depends on !ARCH_UNIPHIER_PH1_SLD3 - help - This enables support for UniPhier PH1-LD4 SoC. +config ARCH_UNIPHIER_LD4_SLD8 + bool "UniPhier PH1-LD4/PH1-sLD8 SoC" config ARCH_UNIPHIER_PH1_PRO4 bool "UniPhier PH1-Pro4 SoC" - depends on !ARCH_UNIPHIER_PH1_SLD3 && \ - !ARCH_UNIPHIER_PH1_LD4 && \ - !ARCH_UNIPHIER_PH1_SLD8 - help - This enables support for UniPhier PH1-Pro4 SoC. + +config ARCH_UNIPHIER_PRO5_PXS2_LD6B + bool "UniPhier PH1-Pro5/ProXstream2/PH1-LD6b SoC" + +endchoice + +config ARCH_UNIPHIER_PH1_LD4 + bool "Enable UniPhier PH1-LD4 SoC support" + depends on ARCH_UNIPHIER_LD4_SLD8 + default y config ARCH_UNIPHIER_PH1_SLD8 - bool "UniPhier PH1-sLD8 SoC" - depends on !ARCH_UNIPHIER_PH1_SLD3 - help - This enables support for UniPhier PH1-sLD8 SoC. + bool "Enable UniPhier PH1-sLD8 SoC support" + depends on ARCH_UNIPHIER_LD4_SLD8 + default y config ARCH_UNIPHIER_PH1_PRO5 - bool "UniPhier PH1-Pro5 SoC" - depends on !ARCH_UNIPHIER_PH1_SLD3 && \ - !ARCH_UNIPHIER_PH1_LD4 && \ - !ARCH_UNIPHIER_PH1_SLD8 - help - This enables support for UniPhier PH1-Pro5 SoC. + bool "Enable UniPhier PH1-Pro5 SoC support" + depends on ARCH_UNIPHIER_PRO5_PXS2_LD6B + default y config ARCH_UNIPHIER_PROXSTREAM2 - bool "UniPhier ProXstream2 SoC" - depends on !ARCH_UNIPHIER_PH1_SLD3 && \ - !ARCH_UNIPHIER_PH1_LD4 && \ - !ARCH_UNIPHIER_PH1_SLD8 - help - This enables support for UniPhier ProXstream2 SoC. + bool "Enable UniPhier ProXstream2 SoC support" + depends on ARCH_UNIPHIER_PRO5_PXS2_LD6B + default y config ARCH_UNIPHIER_PH1_LD6B - bool "UniPhier PH1-LD6b SoC" - depends on !ARCH_UNIPHIER_PH1_SLD3 && \ - !ARCH_UNIPHIER_PH1_LD4 && \ - !ARCH_UNIPHIER_PH1_SLD8 - help - This enables support for UniPhier PH1-LD6b SoC. + bool "Enable UniPhier PH1-LD6b SoC support" + depends on ARCH_UNIPHIER_PRO5_PXS2_LD6B + default y config MICRO_SUPPORT_CARD bool "Use Micro Support Card" diff --git a/configs/uniphier_ld4_sld8_defconfig b/configs/uniphier_ld4_sld8_defconfig index 892bccc32f..4d7afb82c7 100644 --- a/configs/uniphier_ld4_sld8_defconfig +++ b/configs/uniphier_ld4_sld8_defconfig @@ -1,8 +1,7 @@ CONFIG_ARM=y CONFIG_ARCH_UNIPHIER=y CONFIG_SYS_MALLOC_F_LEN=0x2000 -CONFIG_ARCH_UNIPHIER_PH1_LD4=y -CONFIG_ARCH_UNIPHIER_PH1_SLD8=y +CONFIG_ARCH_UNIPHIER_LD4_SLD8=y CONFIG_MICRO_SUPPORT_CARD=y CONFIG_SYS_TEXT_BASE=0x84000000 CONFIG_DEFAULT_DEVICE_TREE="uniphier-ph1-ld4-ref" diff --git a/configs/uniphier_pxs2_ld6b_defconfig b/configs/uniphier_pxs2_ld6b_defconfig index 10af9c884b..4a8d70b801 100644 --- a/configs/uniphier_pxs2_ld6b_defconfig +++ b/configs/uniphier_pxs2_ld6b_defconfig @@ -1,9 +1,7 @@ CONFIG_ARM=y CONFIG_ARCH_UNIPHIER=y CONFIG_SYS_MALLOC_F_LEN=0x2000 -CONFIG_ARCH_UNIPHIER_PH1_PRO5=y -CONFIG_ARCH_UNIPHIER_PROXSTREAM2=y -CONFIG_ARCH_UNIPHIER_PH1_LD6B=y +CONFIG_ARCH_UNIPHIER_PRO5_PXS2_LD6B=y CONFIG_MICRO_SUPPORT_CARD=y CONFIG_SYS_TEXT_BASE=0x84000000 CONFIG_DEFAULT_DEVICE_TREE="uniphier-proxstream2-vodka" From 2247c332db395ef87a0e2f6ed16a9de6959fe204 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 18:59:43 +0900 Subject: [PATCH 36/38] ARM: uniphier: rename PH1-LD10/PH1-sLD11 to PH1-LD20/PH1-LD11 Due to the company's awful projecting, PH1-LD10 and PH1-sLD11 have been renamed to PH1-LD20 and PH1-LD11, respectively. Signed-off-by: Masahiro Yamada --- arch/arm/mach-uniphier/cpu_info.c | 4 ++-- arch/arm/mach-uniphier/soc-info.h | 16 ++++++++-------- arch/arm/mach-uniphier/soc_info.c | 8 ++++---- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/arch/arm/mach-uniphier/cpu_info.c b/arch/arm/mach-uniphier/cpu_info.c index 4e9d01bafd..aae8d1fabd 100644 --- a/arch/arm/mach-uniphier/cpu_info.c +++ b/arch/arm/mach-uniphier/cpu_info.c @@ -45,10 +45,10 @@ int print_cpuinfo(void) puts("PH1-LD6b (MN2WS0320)"); break; case 0x31: - puts("PH1-sLD11 ()"); + puts("PH1-LD11 ()"); break; case 0x32: - puts("PH1-LD10 ()"); + puts("PH1-LD20 ()"); break; default: printf("Unknown Processor ID (0x%x)\n", revision); diff --git a/arch/arm/mach-uniphier/soc-info.h b/arch/arm/mach-uniphier/soc-info.h index 3cfd1e9d6e..606094c80f 100644 --- a/arch/arm/mach-uniphier/soc-info.h +++ b/arch/arm/mach-uniphier/soc-info.h @@ -15,8 +15,8 @@ enum uniphier_soc_id { SOC_UNIPHIER_PH1_PRO5, SOC_UNIPHIER_PROXSTREAM2, SOC_UNIPHIER_PH1_LD6B, - SOC_UNIPHIER_PH1_SLD11, - SOC_UNIPHIER_PH1_LD10, + SOC_UNIPHIER_PH1_LD11, + SOC_UNIPHIER_PH1_LD20, SOC_UNIPHIER_UNKNOWN, }; @@ -28,8 +28,8 @@ enum uniphier_soc_id { IS_ENABLED(CONFIG_ARCH_UNIPHIER_PH1_PRO5) + \ IS_ENABLED(CONFIG_ARCH_UNIPHIER_PROXSTREAM2) + \ IS_ENABLED(CONFIG_ARCH_UNIPHIER_PH1_LD6B) + \ - IS_ENABLED(CONFIG_ARCH_UNIPHIER_PH1_SLD11) + \ - IS_ENABLED(CONFIG_ARCH_UNIPHIER_PH1_LD10) + IS_ENABLED(CONFIG_ARCH_UNIPHIER_PH1_LD11) + \ + IS_ENABLED(CONFIG_ARCH_UNIPHIER_PH1_LD20) #define UNIPHIER_MULTI_SOC ((UNIPHIER_NR_ENABLED_SOCS) > 1) @@ -59,11 +59,11 @@ static inline enum uniphier_soc_id uniphier_get_soc_type(void) #if defined(CONFIG_ARCH_UNIPHIER_PH1_LD6B) return SOC_UNIPHIER_PH1_LD6B; #endif -#if defined(CONFIG_ARCH_UNIPHIER_PH1_SLD11) - return SOC_UNIPHIER_PH1_SLD11; +#if defined(CONFIG_ARCH_UNIPHIER_PH1_LD11) + return SOC_UNIPHIER_PH1_LD11; #endif -#if defined(CONFIG_ARCH_UNIPHIER_PH1_LD10) - return SOC_UNIPHIER_PH1_LD10; +#if defined(CONFIG_ARCH_UNIPHIER_PH1_LD20) + return SOC_UNIPHIER_PH1_LD20; #endif return SOC_UNIPHIER_UNKNOWN; diff --git a/arch/arm/mach-uniphier/soc_info.c b/arch/arm/mach-uniphier/soc_info.c index fd799ca39a..3cfc183723 100644 --- a/arch/arm/mach-uniphier/soc_info.c +++ b/arch/arm/mach-uniphier/soc_info.c @@ -52,14 +52,14 @@ enum uniphier_soc_id uniphier_get_soc_type(void) ret = SOC_UNIPHIER_PH1_LD6B; break; #endif -#ifdef CONFIG_ARCH_UNIPHIER_PH1_SLD11 +#ifdef CONFIG_ARCH_UNIPHIER_PH1_LD11 case 0x31: - ret = SOC_UNIPHIER_PH1_SLD11; + ret = SOC_UNIPHIER_PH1_LD11; break; #endif -#ifdef CONFIG_ARCH_UNIPHIER_PH1_LD10 +#ifdef CONFIG_ARCH_UNIPHIER_PH1_LD20 case 0x32: - ret = SOC_UNIPHIER_PH1_LD10; + ret = SOC_UNIPHIER_PH1_LD20; break; #endif default: From fe5ea57bdbdeb8429793faaca2d6bd5f38218fe3 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 18:59:44 +0900 Subject: [PATCH 37/38] ARM: uniphier: prepare directory structure for ARMv8 SoC support Before adding ARMv8 support, this commit refactors the directory structure. Move ARMv7 specific files to arch/arm/mach-uniphier/arm32 to avoid a mess by mixture of ARMv7 and ARMv8 code. Also move the "select CPU_V7" to the lower-level menu because we will have to select ARM64 instead of CPU_V7 for ARMv8 SoCs. Signed-off-by: Masahiro Yamada --- arch/arm/Kconfig | 1 - arch/arm/mach-uniphier/Kconfig | 4 ++++ arch/arm/mach-uniphier/Makefile | 9 ++------- arch/arm/mach-uniphier/arm32/Makefile | 13 +++++++++++++ arch/arm/mach-uniphier/{ => arm32}/arm-mpcore.h | 0 arch/arm/mach-uniphier/{ => arm32}/cache_uniphier.c | 0 arch/arm/mach-uniphier/{ => arm32}/debug_ll.S | 6 +++--- .../mach-uniphier/{ => arm32}/late_lowlevel_init.S | 0 arch/arm/mach-uniphier/{ => arm32}/lowlevel_init.S | 0 arch/arm/mach-uniphier/{ => arm32}/ssc-regs.h | 0 arch/arm/mach-uniphier/{ => arm32}/timer.c | 0 11 files changed, 22 insertions(+), 11 deletions(-) create mode 100644 arch/arm/mach-uniphier/arm32/Makefile rename arch/arm/mach-uniphier/{ => arm32}/arm-mpcore.h (100%) rename arch/arm/mach-uniphier/{ => arm32}/cache_uniphier.c (100%) rename arch/arm/mach-uniphier/{ => arm32}/debug_ll.S (98%) rename arch/arm/mach-uniphier/{ => arm32}/late_lowlevel_init.S (100%) rename arch/arm/mach-uniphier/{ => arm32}/lowlevel_init.S (100%) rename arch/arm/mach-uniphier/{ => arm32}/ssc-regs.h (100%) rename arch/arm/mach-uniphier/{ => arm32}/timer.c (100%) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 37b20ff331..6e5544f9d7 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -690,7 +690,6 @@ config TARGET_COLIBRI_PXA270 config ARCH_UNIPHIER bool "Socionext UniPhier SoCs" select CLK_UNIPHIER - select CPU_V7 select SUPPORT_SPL select SPL select OF_CONTROL diff --git a/arch/arm/mach-uniphier/Kconfig b/arch/arm/mach-uniphier/Kconfig index e859ca3ada..660f83c855 100644 --- a/arch/arm/mach-uniphier/Kconfig +++ b/arch/arm/mach-uniphier/Kconfig @@ -9,15 +9,19 @@ choice config ARCH_UNIPHIER_PH1_SLD3 bool "UniPhier PH1-sLD3 SoC" + select CPU_V7 config ARCH_UNIPHIER_LD4_SLD8 bool "UniPhier PH1-LD4/PH1-sLD8 SoC" + select CPU_V7 config ARCH_UNIPHIER_PH1_PRO4 bool "UniPhier PH1-Pro4 SoC" + select CPU_V7 config ARCH_UNIPHIER_PRO5_PXS2_LD6B bool "UniPhier PH1-Pro5/ProXstream2/PH1-LD6b SoC" + select CPU_V7 endchoice diff --git a/arch/arm/mach-uniphier/Makefile b/arch/arm/mach-uniphier/Makefile index e65d602350..1a8c649964 100644 --- a/arch/arm/mach-uniphier/Makefile +++ b/arch/arm/mach-uniphier/Makefile @@ -4,16 +4,11 @@ ifdef CONFIG_SPL_BUILD -obj-y += lowlevel_init.o - obj-y += init/ bcu/ memconf/ pll/ early-clk/ early-pinctrl/ obj-$(CONFIG_MICRO_SUPPORT_CARD) += sbc/ -obj-$(CONFIG_DEBUG_LL) += debug_ll.o - else -obj-y += late_lowlevel_init.o obj-$(CONFIG_BOARD_EARLY_INIT_F) += board_early_init_f.o obj-$(CONFIG_DISPLAY_CPUINFO) += cpu_info.o obj-$(CONFIG_MISC_INIT_F) += print_misc_info.o @@ -22,16 +17,16 @@ obj-y += board_common.o obj-$(CONFIG_BOARD_EARLY_INIT_R) += board_early_init_r.o obj-$(CONFIG_BOARD_LATE_INIT) += board_late_init.o obj-y += reset.o -obj-y += cache_uniphier.o obj-y += pinctrl/ clk/ endif -obj-y += timer.o obj-y += boards.o obj-y += soc_info.o obj-y += boot-mode/ obj-y += dram/ obj-$(CONFIG_MICRO_SUPPORT_CARD) += micro-support-card.o + +obj-$(CONFIG_CPU_V7) += arm32/ diff --git a/arch/arm/mach-uniphier/arm32/Makefile b/arch/arm/mach-uniphier/arm32/Makefile new file mode 100644 index 0000000000..376c06b597 --- /dev/null +++ b/arch/arm/mach-uniphier/arm32/Makefile @@ -0,0 +1,13 @@ +# +# SPDX-License-Identifier: GPL-2.0+ +# + +ifdef CONFIG_SPL_BUILD +obj-y += lowlevel_init.o +obj-$(CONFIG_DEBUG_LL) += debug_ll.o +else +obj-y += late_lowlevel_init.o +obj-y += cache_uniphier.o +endif + +obj-y += timer.o diff --git a/arch/arm/mach-uniphier/arm-mpcore.h b/arch/arm/mach-uniphier/arm32/arm-mpcore.h similarity index 100% rename from arch/arm/mach-uniphier/arm-mpcore.h rename to arch/arm/mach-uniphier/arm32/arm-mpcore.h diff --git a/arch/arm/mach-uniphier/cache_uniphier.c b/arch/arm/mach-uniphier/arm32/cache_uniphier.c similarity index 100% rename from arch/arm/mach-uniphier/cache_uniphier.c rename to arch/arm/mach-uniphier/arm32/cache_uniphier.c diff --git a/arch/arm/mach-uniphier/debug_ll.S b/arch/arm/mach-uniphier/arm32/debug_ll.S similarity index 98% rename from arch/arm/mach-uniphier/debug_ll.S rename to arch/arm/mach-uniphier/arm32/debug_ll.S index 6aa5f897a1..a70954cbee 100644 --- a/arch/arm/mach-uniphier/debug_ll.S +++ b/arch/arm/mach-uniphier/arm32/debug_ll.S @@ -9,9 +9,9 @@ #include #include -#include "bcu/bcu-regs.h" -#include "sc-regs.h" -#include "sg-regs.h" +#include "../bcu/bcu-regs.h" +#include "../sc-regs.h" +#include "../sg-regs.h" #if !defined(CONFIG_DEBUG_SEMIHOSTING) #include CONFIG_DEBUG_LL_INCLUDE diff --git a/arch/arm/mach-uniphier/late_lowlevel_init.S b/arch/arm/mach-uniphier/arm32/late_lowlevel_init.S similarity index 100% rename from arch/arm/mach-uniphier/late_lowlevel_init.S rename to arch/arm/mach-uniphier/arm32/late_lowlevel_init.S diff --git a/arch/arm/mach-uniphier/lowlevel_init.S b/arch/arm/mach-uniphier/arm32/lowlevel_init.S similarity index 100% rename from arch/arm/mach-uniphier/lowlevel_init.S rename to arch/arm/mach-uniphier/arm32/lowlevel_init.S diff --git a/arch/arm/mach-uniphier/ssc-regs.h b/arch/arm/mach-uniphier/arm32/ssc-regs.h similarity index 100% rename from arch/arm/mach-uniphier/ssc-regs.h rename to arch/arm/mach-uniphier/arm32/ssc-regs.h diff --git a/arch/arm/mach-uniphier/timer.c b/arch/arm/mach-uniphier/arm32/timer.c similarity index 100% rename from arch/arm/mach-uniphier/timer.c rename to arch/arm/mach-uniphier/arm32/timer.c From 11d3ede42ceccef9b5941ea7907f398cb97ed361 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 18:59:45 +0900 Subject: [PATCH 38/38] ARM: uniphier: fix warnings reported by aarch64 compiler The UniPhier SoC family has not supported ARMv8 yet, but these would cause warnings if they were compiled with a 64bit compiler. Before adding the ARMv8 support really, fix them now. Because UniPhier SoCs do not support Large Physical Address Extension, casting "phys_addr_t" into "unsigned long" would carry the address as is. Signed-off-by: Masahiro Yamada --- arch/arm/mach-uniphier/dram_init.c | 5 +++-- arch/arm/mach-uniphier/micro-support-card.c | 3 ++- arch/arm/mach-uniphier/sg-regs.h | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-uniphier/dram_init.c b/arch/arm/mach-uniphier/dram_init.c index 32cc448aeb..cffdfc9841 100644 --- a/arch/arm/mach-uniphier/dram_init.c +++ b/arch/arm/mach-uniphier/dram_init.c @@ -32,7 +32,7 @@ int dram_init(void) gd->ram_size = fdt32_to_cpu(*(val + 1)); - debug("DRAM size = %08lx\n", gd->ram_size); + debug("DRAM size = %08lx\n", (unsigned long)gd->ram_size); return 0; } @@ -54,6 +54,7 @@ void dram_init_banksize(void) gd->bd->bi_dram[i].size = fdt32_to_cpu(*val++); debug("DRAM bank %d: start = %08lx, size = %08lx\n", - i, gd->bd->bi_dram[i].start, gd->bd->bi_dram[i].size); + i, (unsigned long)gd->bd->bi_dram[i].start, + (unsigned long)gd->bd->bi_dram[i].size); } } diff --git a/arch/arm/mach-uniphier/micro-support-card.c b/arch/arm/mach-uniphier/micro-support-card.c index f777ac1ffe..f7a37e3e4c 100644 --- a/arch/arm/mach-uniphier/micro-support-card.c +++ b/arch/arm/mach-uniphier/micro-support-card.c @@ -142,7 +142,8 @@ static void detect_num_flash_banks(void) memory_bank; debug("flash bank found: base = 0x%lx, size = 0x%lx\n", - memory_bank->base, memory_bank->size); + (unsigned long)memory_bank->base, + (unsigned long)memory_bank->size); cfi_flash_num_flash_banks++; } } diff --git a/arch/arm/mach-uniphier/sg-regs.h b/arch/arm/mach-uniphier/sg-regs.h index 678d437fc9..3a535c70b2 100644 --- a/arch/arm/mach-uniphier/sg-regs.h +++ b/arch/arm/mach-uniphier/sg-regs.h @@ -105,7 +105,7 @@ static inline void sg_set_pinsel(unsigned pin, unsigned muxval, unsigned mux_bits, unsigned reg_stride) { unsigned shift = pin * mux_bits % 32; - unsigned reg = SG_PINCTRL_BASE + pin * mux_bits / 32 * reg_stride; + unsigned long reg = SG_PINCTRL_BASE + pin * mux_bits / 32 * reg_stride; u32 mask = (1U << mux_bits) - 1; u32 tmp;