From 0f5fb8ce408eb790f9fc33c4545757782aaa790b Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 16 Feb 2016 17:00:22 +0900 Subject: ARM: dts: uniphier: rework System Bus nodes Follow the changes of DTS in Linux. Signed-off-by: Masahiro Yamada diff --git a/arch/arm/dts/uniphier-common32.dtsi b/arch/arm/dts/uniphier-common32.dtsi index 59511bd..7d59112 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 85dde66..e01bd30 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 { -- cgit v0.10.2 From b9a66b63b49ce8ce7a43de68e46ef8c1c0a781fc Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 16 Feb 2016 17:03:48 +0900 Subject: 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 diff --git a/doc/README.uniphier b/doc/README.uniphier index bcf0ac3..f03c207 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 845dc72..94fabb9 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 845a6d4..ca8c487 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 0000000..80bb16e --- /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, +}; -- cgit v0.10.2 From f8facbe71ecb4c9411e3da6e40d90152d066879a Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 16 Feb 2016 17:03:49 +0900 Subject: 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 diff --git a/arch/arm/include/asm/gpio.h b/arch/arm/include/asm/gpio.h index d49ad08..fe4419c 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 -- cgit v0.10.2 From b800cbde4fecd26b52aa1736b045ca3c3673fc94 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 16 Feb 2016 17:03:50 +0900 Subject: 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 diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index d8b63e9..94bd7ec 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 535f96f..dbee08e 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 2361db6..3c2f7b0 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 be0d7b5..cf5f1ce 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 f8cb794..00a2900 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 e369c45..013fc8a 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 -- cgit v0.10.2 From 595dc1e162e2d8dce6a97a0199554d59b2589a5f Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 16 Feb 2016 17:03:51 +0900 Subject: ARM: dts: uniphier: add GPIO controller nodes Make the GPIO driver really active. Signed-off-by: Masahiro Yamada diff --git a/arch/arm/dts/uniphier-ph1-ld4.dtsi b/arch/arm/dts/uniphier-ph1-ld4.dtsi index 7c8759f..f13c6db 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 cb5b8f1..6637aea 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 087b25a..67a435e 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 e01bd30..9a6ca57 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 f93db83..985848a 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 2d324f9..21fad0c 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"; -- cgit v0.10.2 From a111bfbfad21dd83aae5a6d96c620c3666e9b654 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 18 Feb 2016 19:52:48 +0900 Subject: 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 diff --git a/doc/README.uniphier b/doc/README.uniphier index f03c207..c270ecb 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 9d3f7e9..dc8532f 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 c9c3e3e..b85e4bf 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 0000000..3bc4d94 --- /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), +}; -- cgit v0.10.2 From 4aceb3f8d4bfcafa895ecbc3108e1f35f2b8c091 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 18 Feb 2016 19:52:49 +0900 Subject: 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 diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 94bd7ec..37b20ff 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 dbee08e..892bccc 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 3c2f7b0..45ef883 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 cf5f1ce..0029cd3 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 00a2900..0115c21 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 013fc8a..5f0d678 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 fcec0c0..9d14155 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) -- cgit v0.10.2 From c7f94eecfd46bb62d173169caa8c6d9493a9859b Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 18 Feb 2016 19:52:50 +0900 Subject: ARM: dts: uniphier: add SD/MMC host controller nodes This host controller is available for all UniPhier SoCs. Signed-off-by: Masahiro Yamada diff --git a/arch/arm/dts/uniphier-ph1-ld4-ref.dts b/arch/arm/dts/uniphier-ph1-ld4-ref.dts index f62916d..d7b0007 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 f13c6db..5ae029e 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 dca408b..13a29fd 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 6e741ea..37e0853 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 202a642..07a9783 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 91a71ef..1ca1042 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 6637aea..d5767b6 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 02a3362..cbdc3eb 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 67a435e..bd1b4b1 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 ff17945..c7213c9 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 9a6ca57..789713d 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 b5b6f65..ec5c5bd 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 985848a..61e0b45 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 b1691d0..494139a 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 dc0def3..c3551fe 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 3703ad3..d61e0b6 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 21fad0c..12968bd 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"; -- cgit v0.10.2 From a55d9feeec141bc5ec04cf84c86e270cf0ed0d3c Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 16 Feb 2016 17:08:39 +0900 Subject: 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 diff --git a/arch/arm/dts/uniphier-ph1-pro4-sanji.dts b/arch/arm/dts/uniphier-ph1-pro4-sanji.dts index 1ca1042..82e2bd0 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 c3551fe..eb1d2bc 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 d61e0b6..e7d5db8 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 935e551..2f2e45d 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 9d14155..19dbfbb 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 -- cgit v0.10.2 From 569e4be172d1bf2041e97c0b65f872a7451b178a Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 16 Feb 2016 17:08:40 +0900 Subject: 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 diff --git a/arch/arm/mach-uniphier/boot-mode/boot-mode.c b/arch/arm/mach-uniphier/boot-mode/boot-mode.c index 2f2e45d..0547762 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 -- cgit v0.10.2 From c231c4367ace6574e27ff0d1844d163fc471287b Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 16 Feb 2016 17:08:41 +0900 Subject: 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 diff --git a/doc/README.uniphier b/doc/README.uniphier index c270ecb..5ac52bd 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 19dbfbb..1b28cdc 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 &&" \ -- cgit v0.10.2 From aa8a93480e072d8d0473e512b66c31f3c4cc3cc7 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 16 Feb 2016 17:08:42 +0900 Subject: 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 diff --git a/arch/arm/mach-uniphier/boot-mode/boot-mode.c b/arch/arm/mach-uniphier/boot-mode/boot-mode.c index 0547762..cf39bf5 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 1b28cdc..b1c8ccb 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 -- cgit v0.10.2 From 8353266825d7b7d673519bce3a54cdddf2c3d459 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 14:21:33 +0900 Subject: ARM: uniphier: remove unused umc_polling() This function is unused. Signed-off-by: Masahiro Yamada diff --git a/arch/arm/mach-uniphier/dram/umc-regs.h b/arch/arm/mach-uniphier/dram/umc-regs.h index a6957a4..b33e2da 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); -- cgit v0.10.2 From 46abfcc99e04efa75ed293bd871092c31d0f3be3 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 14:21:34 +0900 Subject: 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 diff --git a/arch/arm/mach-uniphier/bcu/bcu-ph1-ld4.c b/arch/arm/mach-uniphier/bcu/bcu-ph1-ld4.c index f82c7d1..bbe8a74 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 75ccd15..b7497e9 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 d70c712..05b7c76 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 ffd7aa9..f2889c0 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 261f7cf..16c8264 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 09f9ccf..3c2724e 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 6e7fa88..6e6fff9 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 0a47e70..aabd84a 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 9718cc5..6fdf910 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 9a91fb3..c47fe0a 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 f2a0eaf..3d4b504 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; -- cgit v0.10.2 From 59fe23c2e0bc442c9344852425155f0d683e217c Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 14:21:35 +0900 Subject: 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 diff --git a/arch/arm/mach-uniphier/dram/umc-proxstream2.c b/arch/arm/mach-uniphier/dram/umc-proxstream2.c index 6e6fff9..dca34ba 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; - } - - 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; - } + 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_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); -- cgit v0.10.2 From a54c879a423959b475f6f67c4cbf1c744e08849a Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 14:21:36 +0900 Subject: ARM: uniphier: use pr_err() where possible Signed-off-by: Masahiro Yamada diff --git a/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c b/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c index 16c8264..ff988e3 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 dca34ba..d98765b 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; } -- cgit v0.10.2 From 94b756f3318b5dea3c1aefa670f43ae85d780144 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 14:21:37 +0900 Subject: 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 diff --git a/arch/arm/mach-uniphier/dram/umc-proxstream2.c b/arch/arm/mach-uniphier/dram/umc-proxstream2.c index d98765b..8690906 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; -- cgit v0.10.2 From 00dd3f6ab068276f8baa409e9317fbf466187a34 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 14:21:38 +0900 Subject: 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 diff --git a/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c b/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c index f2889c0..638aa11 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 ff988e3..c28492c 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 3c2724e..fa0619f 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 b33e2da..311cf3d 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 -- cgit v0.10.2 From 3c963d48995ed4ca4e6d742de3d234cb0bcf699e Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 14:21:39 +0900 Subject: 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 diff --git a/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c b/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c index c28492c..f89b1da 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); -- cgit v0.10.2 From 4021b4381d8d3c18a3d8732967eec3ec1624ab7b Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 14:21:40 +0900 Subject: 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 diff --git a/arch/arm/mach-uniphier/boards.c b/arch/arm/mach-uniphier/boards.c index 05b7c76..408aff0 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 d2bc5a1..3000a28 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 9fb34f7..b4dca35 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 6510690..0d2ae42 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 03aedc2..206fabd 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 638aa11..957a38f 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 f89b1da..38dd338 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 fa0619f..3cbb7ba 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 aabd84a..e969fd0 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]; }; -- cgit v0.10.2 From 4f19f6118478c8bbf4bd435404094b23991ad225 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 14:21:41 +0900 Subject: 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 diff --git a/arch/arm/mach-uniphier/dram/Makefile b/arch/arm/mach-uniphier/dram/Makefile index a0a6003..3d1553c 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 3000a28..27be1cc 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 b4dca35..0000000 --- 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 0d2ae42..0000000 --- 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 206fabd..a466118 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 38dd338..877f5ef 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 3cbb7ba..a27f91f 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); -- cgit v0.10.2 From 78876704984f44e96578f887035aabaec2b776f5 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 14:21:42 +0900 Subject: 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 diff --git a/arch/arm/mach-uniphier/dram/ddrphy-ph1-ld4.c b/arch/arm/mach-uniphier/dram/ddrphy-ph1-ld4.c index 27be1cc..ef1941e 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 a466118..87f6d0d 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 957a38f..bee3ef4 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 877f5ef..0a2485e 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 a27f91f..73ad934 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); -- cgit v0.10.2 From 6257a0b0e9b84fca5853e225e1de8023de5f1668 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 14:21:43 +0900 Subject: 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 diff --git a/arch/arm/mach-uniphier/dram/ddrphy-ph1-ld4.c b/arch/arm/mach-uniphier/dram/ddrphy-ph1-ld4.c index ef1941e..eb9bf24 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; - 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]); + 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]); + 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)) -- cgit v0.10.2 From 82e5950802137d8bb5ee389e16c6a9f3b0361faf Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 14:21:44 +0900 Subject: ARM: uniphier: refactor UMC init code for PH1-sLD8 Move frequency-dependent register settings to arrays for clean-up. Signed-off-by: Masahiro Yamada diff --git a/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c b/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c index 73ad934..5e333e0 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) -- cgit v0.10.2 From 380a8cafc09800e4a6573c938e28f1bc1c93793f Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 14:21:45 +0900 Subject: ARM: uniphier: support more DRAM use cases for PH1-sLD8 Support DDR3-1600 / 512MB DDR size. Signed-off-by: Masahiro Yamada diff --git a/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c b/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c index 5e333e0..b8d729c 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); -- cgit v0.10.2 From 71d7ef35df49b94797ad6f32c23e23af4728b18d Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 14:21:46 +0900 Subject: ARM: uniphier: refactor UMC init code for PH1-LD4 Move frequency-dependent register settings to arrays for clean-up. Signed-off-by: Masahiro Yamada diff --git a/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c b/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c index bee3ef4..353ef69 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) -- cgit v0.10.2 From c5985b4bbbb79d789bb4fe1ad9d6fd374ca9eda8 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 14:21:47 +0900 Subject: 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 diff --git a/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c b/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c index b8d729c..a2ed9ba 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); - - umc_dram_init_start(dramcont0); - umc_dram_init_start(dramcont1); - umc_dram_init_poll(dramcont0); - umc_dram_init_poll(dramcont1); - - writel(0x00000101, dramcont0 + UMC_DIOCTLA); - - ph1_ld4_ddrphy_init(phy0_0, freq, ddr3plus); - - ddrphy_prepare_training(phy0_0, 0); - ddrphy_training(phy0_0); + void __iomem *phy_base = dc_base + 0x00001000; + int ret; - writel(0x00000101, dramcont1 + UMC_DIOCTLA); + umc_dram_init_start(dc_base); + umc_dram_init_poll(dc_base); - ph1_ld4_ddrphy_init(phy1_0, freq, ddr3plus); + writel(0x00000101, dc_base + UMC_DIOCTLA); - ddrphy_prepare_training(phy1_0, 1); - ddrphy_training(phy1_0); + ret = ph1_ld4_ddrphy_init(phy_base, freq, ddr3plus); + if (ret) + return ret; - umc_dramcont_init(dramcont0, ca_base0, size_ch0, freq, ddr3plus); - umc_dramcont_init(dramcont1, ca_base1, size_ch1, freq, ddr3plus); + ddrphy_prepare_training(phy_base, umc_get_rank(ch)); + ret = ddrphy_training(phy_base); + if (ret) + return ret; - umc_start_ssif(ssif_base); - - return 0; + return umc_dramcont_init(dc_base, ca_base, size, freq, ddr3plus); } 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; + 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; + + 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; + } + + ca_base += 0x00001000; + dc_base += 0x00200000; } + + umc_start_ssif(ssif_base); + + return 0; } -- cgit v0.10.2 From b8708487958d3846aabf306387e5f1c10948f228 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 14:21:48 +0900 Subject: 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 diff --git a/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c b/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c index 353ef69..92b0f18 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); - - umc_dram_init_start(dramcont0); - umc_dram_init_start(dramcont1); - umc_dram_init_poll(dramcont0); - umc_dram_init_poll(dramcont1); - - writel(0x00000101, dramcont0 + UMC_DIOCTLA); - - ph1_ld4_ddrphy_init(phy0_0, freq, ddr3plus); + void __iomem *phy_base = dc_base + 0x00001000; + int ret; - ddrphy_prepare_training(phy0_0, 0); - ddrphy_training(phy0_0); + umc_dram_init_start(dc_base); + umc_dram_init_poll(dc_base); - writel(0x00000101, dramcont1 + UMC_DIOCTLA); + writel(0x00000101, dc_base + UMC_DIOCTLA); - ph1_ld4_ddrphy_init(phy1_0, freq, ddr3plus); + ret = ph1_ld4_ddrphy_init(phy_base, freq, ddr3plus); + if (ret) + return ret; - ddrphy_prepare_training(phy1_0, 1); - ddrphy_training(phy1_0); + ddrphy_prepare_training(phy_base, umc_get_rank(ch)); + ret = ddrphy_training(phy_base); + if (ret) + return ret; - umc_dramcont_init(dramcont0, ca_base0, size_ch0, freq); - umc_dramcont_init(dramcont1, ca_base1, size_ch1, freq); - - umc_start_ssif(ssif_base); - - return 0; + return umc_dramcont_init(dc_base, ca_base, size, freq, ddr3plus); } 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; + 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; + + 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; + } + + ca_base += 0x00001000; + dc_base += 0x00200000; } + + umc_start_ssif(ssif_base); + + return 0; } -- cgit v0.10.2 From 9a71844a381b606d1c9c28c5974e389671ee1cd5 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 14:21:49 +0900 Subject: 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 diff --git a/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c b/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c index 0a2485e..9569c10 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; - - if (bd->dram_freq != 1600) { - pr_err("Unsupported DDR configuration\n"); - return -EINVAL; - } - - umc_dram_init_start(dramcont0); - umc_dram_init_start(dramcont1); - umc_dram_init_poll(dramcont0); - umc_dram_init_poll(dramcont1); - - writel(0x00000101, dramcont0 + UMC_DIOCTLA); + void __iomem *phy_base = dc_base + 0x00001000; + int nr_phy = width / 16; + int phy, ret; - ph1_ld4_ddrphy_init(phy0_0, bd->dram_freq, bd->dram_ddr3plus); + umc_dram_init_start(dc_base); + umc_dram_init_poll(dc_base); - ddrphy_prepare_training(phy0_0, 0); - ddrphy_training(phy0_0); + for (phy = 0; phy < nr_phy; phy++) { + writel(0x00000100 | ((1 << (phy + 1)) - 1), + dc_base + UMC_DIOCTLA); - writel(0x00000103, dramcont0 + UMC_DIOCTLA); + ret = ph1_ld4_ddrphy_init(phy_base, freq, ddr3plus); + if (ret) + return ret; - ph1_ld4_ddrphy_init(phy0_1, bd->dram_freq, bd->dram_ddr3plus); + ddrphy_prepare_training(phy_base, phy); + ret = ddrphy_training(phy_base); + if (ret) + return ret; - 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); + phy_base += 0x00001000; + } - ret = umc_dramcont_init(dramcont0, ca_base0, bd->dram_ch[0].size, - bd->dram_ch[0].width); - if (ret) - return ret; + return umc_dramcont_init(dc_base, ca_base, freq, size / (width / 16), + ddr3plus); +} - ret = umc_dramcont_init(dramcont1, ca_base1, bd->dram_ch[1].size, - bd->dram_ch[1].width); - if (ret) - return ret; +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; + + 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; + } + + ca_base += 0x00001000; + dc_base += 0x00200000; + } umc_start_ssif(ssif_base); -- cgit v0.10.2 From fd14397e93894995116583aced817f2fad9ac57b Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 14:21:50 +0900 Subject: 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 diff --git a/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c b/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c index 92b0f18..0eb47d7 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 a2ed9ba..43e53fd 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); -- cgit v0.10.2 From 7c9cac9c227b1a05ed1a63931f3c03950e9e6603 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 14:21:51 +0900 Subject: 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 diff --git a/arch/arm/mach-uniphier/dram/umc-regs.h b/arch/arm/mach-uniphier/dram/umc-regs.h index 311cf3d..c65dd82 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 -- cgit v0.10.2 From a191e0dee02b3fb041880131535fe6b307e6b70d Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 14:21:52 +0900 Subject: ARM: uniphier: deprecate umc_dram_init_{start, poll} Signed-off-by: Masahiro Yamada diff --git a/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c b/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c index 0eb47d7..09b2c1c 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 9569c10..93d2e2c 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 43e53fd..d873130 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 c65dd82..cc2dd27 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 -- cgit v0.10.2 From 4e651003e5413530aaea6ff00841ef52fb48b797 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 14:21:53 +0900 Subject: ARM: uniphier: rename variable for DRAM controller base address Rename the variable that contains the base address for consistency. Signed-off-by: Masahiro Yamada diff --git a/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c b/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c index 09b2c1c..72447cc 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 93d2e2c..23fb7b9 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 d873130..6cacd25 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 8690906..50c0238 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); -- cgit v0.10.2 From fe7c95ee5c2e4a757941221ae3b624c78bdaf068 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 18:59:41 +0900 Subject: 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 diff --git a/configs/uniphier_pro5_defconfig b/configs/uniphier_pro5_defconfig deleted file mode 100644 index 0029cd3..0000000 --- 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 0115c21..10af9c8 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 5ac52bd..6c3b092 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 -- cgit v0.10.2 From 5fb87a1632fbc7b5079b1497aff41de20647c759 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 18:59:42 +0900 Subject: 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 diff --git a/arch/arm/mach-uniphier/Kconfig b/arch/arm/mach-uniphier/Kconfig index 03256be..e859ca3 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 892bccc..4d7afb8 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 10af9c8..4a8d70b 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" -- cgit v0.10.2 From 2247c332db395ef87a0e2f6ed16a9de6959fe204 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 18:59:43 +0900 Subject: 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 diff --git a/arch/arm/mach-uniphier/cpu_info.c b/arch/arm/mach-uniphier/cpu_info.c index 4e9d01b..aae8d1f 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 3cfd1e9..606094c 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 fd799ca..3cfc183 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: -- cgit v0.10.2 From fe5ea57bdbdeb8429793faaca2d6bd5f38218fe3 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 18:59:44 +0900 Subject: 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 diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 37b20ff..6e5544f 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 e859ca3..660f83c 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 e65d602..1a8c649 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/arm-mpcore.h b/arch/arm/mach-uniphier/arm-mpcore.h deleted file mode 100644 index cf7cd46..0000000 --- a/arch/arm/mach-uniphier/arm-mpcore.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2011-2014 Panasonic Corporation - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifndef ARCH_ARM_MPCORE_H -#define ARCH_ARM_MPCORE_H - -/* Snoop Control Unit */ -#define SCU_OFFSET 0x00 - -/* SCU Control Register */ -#define SCU_CTRL 0x00 -/* SCU Configuration Register */ -#define SCU_CONF 0x04 -/* SCU CPU Power Status Register */ -#define SCU_PWR_STATUS 0x08 -/* SCU Invalidate All Registers in Secure State */ -#define SCU_INV_ALL 0x0C -/* SCU Filtering Start Address Register */ -#define SCU_FILTER_START 0x40 -/* SCU Filtering End Address Register */ -#define SCU_FILTER_END 0x44 -/* SCU Access Control Register */ -#define SCU_SAC 0x50 -/* SCU Non-secure Access Control Register */ -#define SCU_SNSAC 0x54 - -/* Global Timer */ -#define GLOBAL_TIMER_OFFSET 0x200 - -/* Global Timer Counter Registers */ -#define GTIMER_CNT_L 0x00 -#define GTIMER_CNT_H 0x04 -/* Global Timer Control Register */ -#define GTIMER_CTRL 0x08 -/* Global Timer Interrupt Status Register */ -#define GTIMER_STAT 0x0C -/* Comparator Value Registers */ -#define GTIMER_CMP_L 0x10 -#define GTIMER_CMP_H 0x14 -/* Auto-increment Register */ -#define GTIMER_INC 0x18 - -#endif /* ARCH_ARM_MPCORE_H */ diff --git a/arch/arm/mach-uniphier/arm32/Makefile b/arch/arm/mach-uniphier/arm32/Makefile new file mode 100644 index 0000000..376c06b --- /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/arm32/arm-mpcore.h b/arch/arm/mach-uniphier/arm32/arm-mpcore.h new file mode 100644 index 0000000..cf7cd46 --- /dev/null +++ b/arch/arm/mach-uniphier/arm32/arm-mpcore.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2011-2014 Panasonic Corporation + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef ARCH_ARM_MPCORE_H +#define ARCH_ARM_MPCORE_H + +/* Snoop Control Unit */ +#define SCU_OFFSET 0x00 + +/* SCU Control Register */ +#define SCU_CTRL 0x00 +/* SCU Configuration Register */ +#define SCU_CONF 0x04 +/* SCU CPU Power Status Register */ +#define SCU_PWR_STATUS 0x08 +/* SCU Invalidate All Registers in Secure State */ +#define SCU_INV_ALL 0x0C +/* SCU Filtering Start Address Register */ +#define SCU_FILTER_START 0x40 +/* SCU Filtering End Address Register */ +#define SCU_FILTER_END 0x44 +/* SCU Access Control Register */ +#define SCU_SAC 0x50 +/* SCU Non-secure Access Control Register */ +#define SCU_SNSAC 0x54 + +/* Global Timer */ +#define GLOBAL_TIMER_OFFSET 0x200 + +/* Global Timer Counter Registers */ +#define GTIMER_CNT_L 0x00 +#define GTIMER_CNT_H 0x04 +/* Global Timer Control Register */ +#define GTIMER_CTRL 0x08 +/* Global Timer Interrupt Status Register */ +#define GTIMER_STAT 0x0C +/* Comparator Value Registers */ +#define GTIMER_CMP_L 0x10 +#define GTIMER_CMP_H 0x14 +/* Auto-increment Register */ +#define GTIMER_INC 0x18 + +#endif /* ARCH_ARM_MPCORE_H */ diff --git a/arch/arm/mach-uniphier/arm32/cache_uniphier.c b/arch/arm/mach-uniphier/arm32/cache_uniphier.c new file mode 100644 index 0000000..4398114 --- /dev/null +++ b/arch/arm/mach-uniphier/arm32/cache_uniphier.c @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2012-2015 Masahiro Yamada + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include + +#include "ssc-regs.h" + +#ifdef CONFIG_UNIPHIER_L2CACHE_ON +static void uniphier_cache_sync(void) +{ + writel(SSCOPE_CM_SYNC, SSCOPE); /* drain internal buffers */ + readl(SSCOPE); /* need a read back to confirm */ +} + +static void uniphier_cache_maint_all(u32 operation) +{ + /* try until the command is successfully set */ + do { + writel(SSCOQM_S_ALL | SSCOQM_CE | operation, SSCOQM); + } while (readl(SSCOPPQSEF) & (SSCOPPQSEF_FE | SSCOPPQSEF_OE)); + + /* wait until the operation is completed */ + while (readl(SSCOLPQS) != SSCOLPQS_EF) + ; + + /* clear the complete notification flag */ + writel(SSCOLPQS_EF, SSCOLPQS); + + uniphier_cache_sync(); +} + +void v7_outer_cache_flush_all(void) +{ + uniphier_cache_maint_all(SSCOQM_CM_WB_INV); +} + +void v7_outer_cache_inval_all(void) +{ + uniphier_cache_maint_all(SSCOQM_CM_INV); +} + +static void __uniphier_cache_maint_range(u32 start, u32 size, u32 operation) +{ + /* try until the command is successfully set */ + do { + writel(SSCOQM_S_ADDRESS | SSCOQM_CE | operation, SSCOQM); + writel(start, SSCOQAD); + writel(size, SSCOQSZ); + + } while (readl(SSCOPPQSEF) & (SSCOPPQSEF_FE | SSCOPPQSEF_OE)); + + /* wait until the operation is completed */ + while (readl(SSCOLPQS) != SSCOLPQS_EF) + ; + + /* clear the complete notification flag */ + writel(SSCOLPQS_EF, SSCOLPQS); +} + +static void uniphier_cache_maint_range(u32 start, u32 end, u32 operation) +{ + u32 size; + + /* + * If start address is not aligned to cache-line, + * do cache operation for the first cache-line + */ + start = start & ~(SSC_LINE_SIZE - 1); + + size = end - start; + + if (unlikely(size >= (u32)(-SSC_LINE_SIZE))) { + /* this means cache operation for all range */ + uniphier_cache_maint_all(operation); + return; + } + + /* + * If end address is not aligned to cache-line, + * do cache operation for the last cache-line + */ + size = ALIGN(size, SSC_LINE_SIZE); + + while (size) { + u32 chunk_size = size > SSC_RANGE_OP_MAX_SIZE ? + SSC_RANGE_OP_MAX_SIZE : size; + __uniphier_cache_maint_range(start, chunk_size, operation); + + start += chunk_size; + size -= chunk_size; + } + + uniphier_cache_sync(); +} + +void v7_outer_cache_flush_range(u32 start, u32 end) +{ + uniphier_cache_maint_range(start, end, SSCOQM_CM_WB_INV); +} + +void v7_outer_cache_inval_range(u32 start, u32 end) +{ + if (start & (SSC_LINE_SIZE - 1)) { + start &= ~(SSC_LINE_SIZE - 1); + __uniphier_cache_maint_range(start, SSC_LINE_SIZE, + SSCOQM_CM_WB_INV); + start += SSC_LINE_SIZE; + } + + if (start >= end) { + uniphier_cache_sync(); + return; + } + + if (end & (SSC_LINE_SIZE - 1)) { + end &= ~(SSC_LINE_SIZE - 1); + __uniphier_cache_maint_range(end, SSC_LINE_SIZE, + SSCOQM_CM_WB_INV); + } + + if (start >= end) { + uniphier_cache_sync(); + return; + } + + uniphier_cache_maint_range(start, end, SSCOQM_CM_INV); +} + +void v7_outer_cache_enable(void) +{ + u32 tmp; + + writel(U32_MAX, SSCLPDAWCR); /* activate all ways */ + tmp = readl(SSCC); + tmp |= SSCC_ON; + writel(tmp, SSCC); +} +#endif + +void v7_outer_cache_disable(void) +{ + u32 tmp; + tmp = readl(SSCC); + tmp &= ~SSCC_ON; + writel(tmp, SSCC); +} + +void enable_caches(void) +{ + dcache_enable(); +} diff --git a/arch/arm/mach-uniphier/arm32/debug_ll.S b/arch/arm/mach-uniphier/arm32/debug_ll.S new file mode 100644 index 0000000..a70954c --- /dev/null +++ b/arch/arm/mach-uniphier/arm32/debug_ll.S @@ -0,0 +1,186 @@ +/* + * On-chip UART initializaion for low-level debugging + * + * Copyright (C) 2014-2015 Masahiro Yamada + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include + +#include "../bcu/bcu-regs.h" +#include "../sc-regs.h" +#include "../sg-regs.h" + +#if !defined(CONFIG_DEBUG_SEMIHOSTING) +#include CONFIG_DEBUG_LL_INCLUDE +#endif + +#define BAUDRATE 115200 +#define DIV_ROUND(x, d) (((x) + ((d) / 2)) / (d)) + +ENTRY(debug_ll_init) + ldr r0, =SG_REVISION + ldr r1, [r0] + and r1, r1, #SG_REVISION_TYPE_MASK + mov r1, r1, lsr #SG_REVISION_TYPE_SHIFT + +#if defined(CONFIG_ARCH_UNIPHIER_PH1_SLD3) +#define PH1_SLD3_UART_CLK 36864000 + cmp r1, #0x25 + bne ph1_sld3_end + + sg_set_pinsel 64, 1, 4, 4, r0, r1 @ TXD0 -> TXD0 + + ldr r0, =BCSCR5 + ldr r1, =0x24440000 + str r1, [r0] + + ldr r0, =SC_CLKCTRL + ldr r1, [r0] + orr r1, r1, #SC_CLKCTRL_CEN_PERI + str r1, [r0] + + ldr r3, =DIV_ROUND(PH1_SLD3_UART_CLK, 16 * BAUDRATE) + + b init_uart +ph1_sld3_end: +#endif +#if defined(CONFIG_ARCH_UNIPHIER_PH1_LD4) +#define PH1_LD4_UART_CLK 36864000 + cmp r1, #0x26 + bne ph1_ld4_end + + ldr r0, =SG_IECTRL + ldr r1, [r0] + orr r1, r1, #1 + str r1, [r0] + + sg_set_pinsel 88, 1, 8, 4, r0, r1 @ HSDOUT6 -> TXD0 + + ldr r3, =DIV_ROUND(PH1_LD4_UART_CLK, 16 * BAUDRATE) + + b init_uart +ph1_ld4_end: +#endif +#if defined(CONFIG_ARCH_UNIPHIER_PH1_PRO4) +#define PH1_PRO4_UART_CLK 73728000 + cmp r1, #0x28 + bne ph1_pro4_end + + sg_set_pinsel 128, 0, 4, 8, r0, r1 @ TXD0 -> TXD0 + + ldr r0, =SG_LOADPINCTRL + mov r1, #1 + str r1, [r0] + + ldr r0, =SC_CLKCTRL + ldr r1, [r0] + orr r1, r1, #SC_CLKCTRL_CEN_PERI + str r1, [r0] + + ldr r3, =DIV_ROUND(PH1_PRO4_UART_CLK, 16 * BAUDRATE) + + b init_uart +ph1_pro4_end: +#endif +#if defined(CONFIG_ARCH_UNIPHIER_PH1_SLD8) +#define PH1_SLD8_UART_CLK 80000000 + cmp r1, #0x29 + bne ph1_sld8_end + + ldr r0, =SG_IECTRL + ldr r1, [r0] + orr r1, r1, #1 + str r1, [r0] + + sg_set_pinsel 70, 3, 8, 4, r0, r1 @ HSDOUT0 -> TXD0 + + ldr r3, =DIV_ROUND(PH1_SLD8_UART_CLK, 16 * BAUDRATE) + + b init_uart +ph1_sld8_end: +#endif +#if defined(CONFIG_ARCH_UNIPHIER_PH1_PRO5) +#define PH1_PRO5_UART_CLK 73728000 + cmp r1, #0x2A + bne ph1_pro5_end + + sg_set_pinsel 47, 0, 4, 8, r0, r1 @ TXD0 -> TXD0 + sg_set_pinsel 49, 0, 4, 8, r0, r1 @ TXD1 -> TXD1 + sg_set_pinsel 51, 0, 4, 8, r0, r1 @ TXD2 -> TXD2 + sg_set_pinsel 53, 0, 4, 8, r0, r1 @ TXD3 -> TXD3 + + ldr r0, =SG_LOADPINCTRL + mov r1, #1 + str r1, [r0] + + ldr r0, =SC_CLKCTRL + ldr r1, [r0] + orr r1, r1, #SC_CLKCTRL_CEN_PERI + str r1, [r0] + + ldr r3, =DIV_ROUND(PH1_PRO5_UART_CLK, 16 * BAUDRATE) + + b init_uart +ph1_pro5_end: +#endif +#if defined(CONFIG_ARCH_UNIPHIER_PROXSTREAM2) +#define PROXSTREAM2_UART_CLK 88900000 + cmp r1, #0x2E + bne proxstream2_end + + ldr r0, =SG_IECTRL + ldr r1, [r0] + orr r1, r1, #1 + str r1, [r0] + + sg_set_pinsel 217, 8, 8, 4, r0, r1 @ TXD0 -> TXD0 + sg_set_pinsel 115, 8, 8, 4, r0, r1 @ TXD1 -> TXD1 + sg_set_pinsel 113, 8, 8, 4, r0, r1 @ TXD2 -> TXD2 + sg_set_pinsel 219, 8, 8, 4, r0, r1 @ TXD3 -> TXD3 + + ldr r0, =SC_CLKCTRL + ldr r1, [r0] + orr r1, r1, #SC_CLKCTRL_CEN_PERI + str r1, [r0] + + ldr r3, =DIV_ROUND(PROXSTREAM2_UART_CLK, 16 * BAUDRATE) + + b init_uart +proxstream2_end: +#endif +#if defined(CONFIG_ARCH_UNIPHIER_PH1_LD6B) +#define PH1_LD6B_UART_CLK 88900000 + cmp r1, #0x2F + bne ph1_ld6b_end + + ldr r0, =SG_IECTRL + ldr r1, [r0] + orr r1, r1, #1 + str r1, [r0] + + sg_set_pinsel 135, 3, 8, 4, r0, r1 @ PORT10 -> TXD0 + sg_set_pinsel 115, 0, 8, 4, r0, r1 @ TXD1 -> TXD1 + sg_set_pinsel 113, 2, 8, 4, r0, r1 @ SBO0 -> TXD2 + + ldr r0, =SC_CLKCTRL + ldr r1, [r0] + orr r1, r1, #SC_CLKCTRL_CEN_PERI + str r1, [r0] + + ldr r3, =DIV_ROUND(PH1_LD6B_UART_CLK, 16 * BAUDRATE) + + b init_uart +ph1_ld6b_end: +#endif + +init_uart: + addruart r0, r1, r2 + mov r1, #UART_LCR_WLEN8 << 8 + str r1, [r0, #0x10] + str r3, [r0, #0x24] + + mov pc, lr +ENDPROC(debug_ll_init) diff --git a/arch/arm/mach-uniphier/arm32/late_lowlevel_init.S b/arch/arm/mach-uniphier/arm32/late_lowlevel_init.S new file mode 100644 index 0000000..cce91df --- /dev/null +++ b/arch/arm/mach-uniphier/arm32/late_lowlevel_init.S @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2015 Socionext Inc. + * Author: Masahiro Yamada + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include + +#include "ssc-regs.h" + +ENTRY(lowlevel_init) + ldr r1, = SSCC + ldr r0, [r1] + bic r0, r0, #SSCC_ON @ L2 disable + str r0, [r1] + mov pc, lr +ENDPROC(lowlevel_init) diff --git a/arch/arm/mach-uniphier/arm32/lowlevel_init.S b/arch/arm/mach-uniphier/arm32/lowlevel_init.S new file mode 100644 index 0000000..dd03ad8 --- /dev/null +++ b/arch/arm/mach-uniphier/arm32/lowlevel_init.S @@ -0,0 +1,207 @@ +/* + * Copyright (C) 2012-2015 Masahiro Yamada + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include + +#include "ssc-regs.h" + +ENTRY(lowlevel_init) + mov r8, lr @ persevere link reg across call + + /* + * The UniPhier Boot ROM loads SPL code to the L2 cache. + * But CPUs can only do instruction fetch now because start.S has + * cleared C and M bits. + * First we need to turn on MMU and Dcache again to get back + * data access to L2. + */ + mrc p15, 0, r0, c1, c0, 0 @ SCTLR (System Control Register) + orr r0, r0, #(CR_C | CR_M) @ enable MMU and Dcache + mcr p15, 0, r0, c1, c0, 0 + +#ifdef CONFIG_DEBUG_LL + bl debug_ll_init +#endif + + bl setup_init_ram @ RAM area for stack and page talbe + + /* + * Now we are using the page table embedded in the Boot ROM. + * It is not handy since it is not a straight mapped table for sLD3. + * Also, the access to the external bus is prohibited. What we need + * to do next is to create a page table and switch over to it. + */ + bl create_page_table + bl v7_flush_dcache_all + + /* Disable MMU and Dcache before switching Page Table */ + mrc p15, 0, r0, c1, c0, 0 @ SCTLR (System Control Register) + bic r0, r0, #(CR_C | CR_M) @ disable MMU and Dcache + mcr p15, 0, r0, c1, c0, 0 + + bl enable_mmu + + mov lr, r8 @ restore link + mov pc, lr @ back to my caller +ENDPROC(lowlevel_init) + +ENTRY(enable_mmu) + mrc p15, 0, r0, c2, c0, 2 @ TTBCR (Translation Table Base Control Register) + bic r0, r0, #0x37 + orr r0, r0, #0x20 @ disable TTBR1 + mcr p15, 0, r0, c2, c0, 2 + + orr r0, r12, #0x8 @ Outer Cacheability for table walks: WBWA + mcr p15, 0, r0, c2, c0, 0 @ TTBR0 + + mov r0, #0 + mcr p15, 0, r0, c8, c7, 0 @ invalidate TLBs + + mov r0, #-1 @ manager for all domains (No permission check) + mcr p15, 0, r0, c3, c0, 0 @ DACR (Domain Access Control Register) + + dsb + isb + /* + * MMU on: + * TLBs was already invalidated in "../start.S" + * So, we don't need to invalidate it here. + */ + mrc p15, 0, r0, c1, c0, 0 @ SCTLR (System Control Register) + orr r0, r0, #(CR_C | CR_M) @ MMU and Dcache enable + mcr p15, 0, r0, c1, c0, 0 + + mov pc, lr +ENDPROC(enable_mmu) + +/* + * For PH1-Pro4 or older SoCs, the size of WAY is 32KB. + * It is large enough for tmp RAM. + */ +#define BOOT_RAM_SIZE (SZ_32K) +#define BOOT_RAM_BASE ((CONFIG_SPL_STACK) - (BOOT_RAM_SIZE)) +#define BOOT_WAY_BITS (0x00000100) /* way 8 */ + +ENTRY(setup_init_ram) + /* + * Touch to zero for the boot way + */ +0: + /* + * set SSCOQM, SSCOQAD, SSCOQSZ, SSCOQWN in this order + */ + ldr r0, = 0x00408006 @ touch to zero with address range + ldr r1, = SSCOQM + str r0, [r1] + ldr r0, = BOOT_RAM_BASE + ldr r1, = SSCOQAD + str r0, [r1] + ldr r0, = BOOT_RAM_SIZE + ldr r1, = SSCOQSZ + str r0, [r1] + ldr r0, = BOOT_WAY_BITS + ldr r1, = SSCOQWN + str r0, [r1] + ldr r1, = SSCOPPQSEF + ldr r0, [r1] + cmp r0, #0 @ check if the command is successfully set + bne 0b @ try again if an error occurs + + ldr r1, = SSCOLPQS +1: + ldr r0, [r1] + cmp r0, #0x4 + bne 1b @ wait until the operation is completed + str r0, [r1] @ clear the complete notification flag + + mov pc, lr +ENDPROC(setup_init_ram) + +#define DEVICE 0x00002002 /* Non-shareable Device */ +#define NORMAL 0x0000000e /* Normal Memory Write-Back, No Write-Allocate */ + +ENTRY(create_page_table) + ldr r0, = DEVICE + ldr r1, = BOOT_RAM_BASE + mov r12, r1 @ r12 is preserved during D-cache flush +0: str r0, [r1], #4 @ specify all the sections as Device + adds r0, r0, #0x00100000 + bcc 0b + + ldr r0, = NORMAL + str r0, [r12] @ mark the first section as Normal + add r0, r0, #0x00100000 + str r0, [r12, #4] @ mark the second section as Normal + mov pc, lr +ENDPROC(create_page_table) + +/* We don't use Thumb instructions for now */ +#define ARM(x...) x +#define THUMB(x...) + +/* + * v7_flush_dcache_all() + * + * Flush the whole D-cache. + * + * Corrupted registers: r0-r7, r9-r11 (r6 only in Thumb mode) + * + * - mm - mm_struct describing address space + * + * Note: copied from arch/arm/mm/cache-v7.S of Linux 4.4 + */ +ENTRY(v7_flush_dcache_all) + dmb @ ensure ordering with previous memory accesses + mrc p15, 1, r0, c0, c0, 1 @ read clidr + mov r3, r0, lsr #23 @ move LoC into position + ands r3, r3, #7 << 1 @ extract LoC*2 from clidr + beq finished @ if loc is 0, then no need to clean +start_flush_levels: + mov r10, #0 @ start clean at cache level 0 +flush_levels: + add r2, r10, r10, lsr #1 @ work out 3x current cache level + mov r1, r0, lsr r2 @ extract cache type bits from clidr + and r1, r1, #7 @ mask of the bits for current cache only + cmp r1, #2 @ see what cache we have at this level + blt skip @ skip if no cache, or just i-cache + mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr + isb @ isb to sych the new cssr&csidr + mrc p15, 1, r1, c0, c0, 0 @ read the new csidr + and r2, r1, #7 @ extract the length of the cache lines + add r2, r2, #4 @ add 4 (line length offset) + movw r4, #0x3ff + ands r4, r4, r1, lsr #3 @ find maximum number on the way size + clz r5, r4 @ find bit position of way size increment + movw r7, #0x7fff + ands r7, r7, r1, lsr #13 @ extract max number of the index size +loop1: + mov r9, r7 @ create working copy of max index +loop2: + ARM( orr r11, r10, r4, lsl r5 ) @ factor way and cache number into r11 + THUMB( lsl r6, r4, r5 ) + THUMB( orr r11, r10, r6 ) @ factor way and cache number into r11 + ARM( orr r11, r11, r9, lsl r2 ) @ factor index number into r11 + THUMB( lsl r6, r9, r2 ) + THUMB( orr r11, r11, r6 ) @ factor index number into r11 + mcr p15, 0, r11, c7, c14, 2 @ clean & invalidate by set/way + subs r9, r9, #1 @ decrement the index + bge loop2 + subs r4, r4, #1 @ decrement the way + bge loop1 +skip: + add r10, r10, #2 @ increment cache number + cmp r3, r10 + bgt flush_levels +finished: + mov r10, #0 @ swith back to cache level 0 + mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr + dsb st + isb + mov pc, lr +ENDPROC(v7_flush_dcache_all) diff --git a/arch/arm/mach-uniphier/arm32/ssc-regs.h b/arch/arm/mach-uniphier/arm32/ssc-regs.h new file mode 100644 index 0000000..02fca3b --- /dev/null +++ b/arch/arm/mach-uniphier/arm32/ssc-regs.h @@ -0,0 +1,65 @@ +/* + * UniPhier System Cache (L2 Cache) registers + * + * Copyright (C) 2011-2014 Panasonic Corporation + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef ARCH_SSC_REGS_H +#define ARCH_SSC_REGS_H + +#define SSCC 0x500c0000 +#define SSCC_BST (0x1 << 20) +#define SSCC_ACT (0x1 << 19) +#define SSCC_WTG (0x1 << 18) +#define SSCC_PRD (0x1 << 17) +#define SSCC_WBWA (0x1 << 16) +#define SSCC_EX (0x1 << 13) +#define SSCC_ON (0x1 << 0) + +#define SSCLPDAWCR 0x500c0030 + +#define SSCOPE 0x506c0244 +#define SSCOPE_CM_SYNC 0x00000008 + +#define SSCOQM 0x506c0248 +#define SSCOQM_TID_MASK (0x3 << 21) +#define SSCOQM_TID_BY_WAY (0x2 << 21) +#define SSCOQM_TID_BY_INST_WAY (0x1 << 21) +#define SSCOQM_TID_BY_DATA_WAY (0x0 << 21) +#define SSCOQM_S_MASK (0x3 << 17) +#define SSCOQM_S_WAY (0x2 << 17) +#define SSCOQM_S_ALL (0x1 << 17) +#define SSCOQM_S_ADDRESS (0x0 << 17) +#define SSCOQM_CE (0x1 << 15) +#define SSCOQM_CW (0x1 << 14) +#define SSCOQM_CM_MASK (0x7) +#define SSCOQM_CM_DIRT_TOUCH (0x7) +#define SSCOQM_CM_ZERO_TOUCH (0x6) +#define SSCOQM_CM_NORM_TOUCH (0x5) +#define SSCOQM_CM_PREF_FETCH (0x4) +#define SSCOQM_CM_SSC_FETCH (0x3) +#define SSCOQM_CM_WB_INV (0x2) +#define SSCOQM_CM_WB (0x1) +#define SSCOQM_CM_INV (0x0) + +#define SSCOQAD 0x506c024c +#define SSCOQSZ 0x506c0250 +#define SSCOQWN 0x506c0258 + +#define SSCOPPQSEF 0x506c025c +#define SSCOPPQSEF_FE (0x1 << 1) +#define SSCOPPQSEF_OE (0x1 << 0) + +#define SSCOLPQS 0x506c0260 +#define SSCOLPQS_EF (0x1 << 2) +#define SSCOLPQS_EST (0x1 << 1) +#define SSCOLPQS_QST (0x1 << 0) + +#define SSCOQCE0 0x506c0270 + +#define SSC_LINE_SIZE 128 +#define SSC_RANGE_OP_MAX_SIZE (0x00400000 - (SSC_LINE_SIZE)) + +#endif /* ARCH_SSC_REGS_H */ diff --git a/arch/arm/mach-uniphier/arm32/timer.c b/arch/arm/mach-uniphier/arm32/timer.c new file mode 100644 index 0000000..a34e30b --- /dev/null +++ b/arch/arm/mach-uniphier/arm32/timer.c @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2012-2015 Masahiro Yamada + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include + +#include "arm-mpcore.h" + +#define PERIPHCLK (50 * 1000 * 1000) /* 50 MHz */ +#define PRESCALER ((PERIPHCLK) / (CONFIG_SYS_TIMER_RATE) - 1) + +static void *get_global_timer_base(void) +{ + void *val; + + asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (val) : : "memory"); + + return val + GLOBAL_TIMER_OFFSET; +} + +unsigned long timer_read_counter(void) +{ + /* + * ARM 64bit Global Timer is too much for our purpose. + * We use only lower 32 bit of the timer counter. + */ + return readl(get_global_timer_base() + GTIMER_CNT_L); +} + +int timer_init(void) +{ + /* enable timer */ + writel(PRESCALER << 8 | 1, get_global_timer_base() + GTIMER_CTRL); + + return 0; +} diff --git a/arch/arm/mach-uniphier/cache_uniphier.c b/arch/arm/mach-uniphier/cache_uniphier.c deleted file mode 100644 index 4398114..0000000 --- a/arch/arm/mach-uniphier/cache_uniphier.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (C) 2012-2015 Masahiro Yamada - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include - -#include "ssc-regs.h" - -#ifdef CONFIG_UNIPHIER_L2CACHE_ON -static void uniphier_cache_sync(void) -{ - writel(SSCOPE_CM_SYNC, SSCOPE); /* drain internal buffers */ - readl(SSCOPE); /* need a read back to confirm */ -} - -static void uniphier_cache_maint_all(u32 operation) -{ - /* try until the command is successfully set */ - do { - writel(SSCOQM_S_ALL | SSCOQM_CE | operation, SSCOQM); - } while (readl(SSCOPPQSEF) & (SSCOPPQSEF_FE | SSCOPPQSEF_OE)); - - /* wait until the operation is completed */ - while (readl(SSCOLPQS) != SSCOLPQS_EF) - ; - - /* clear the complete notification flag */ - writel(SSCOLPQS_EF, SSCOLPQS); - - uniphier_cache_sync(); -} - -void v7_outer_cache_flush_all(void) -{ - uniphier_cache_maint_all(SSCOQM_CM_WB_INV); -} - -void v7_outer_cache_inval_all(void) -{ - uniphier_cache_maint_all(SSCOQM_CM_INV); -} - -static void __uniphier_cache_maint_range(u32 start, u32 size, u32 operation) -{ - /* try until the command is successfully set */ - do { - writel(SSCOQM_S_ADDRESS | SSCOQM_CE | operation, SSCOQM); - writel(start, SSCOQAD); - writel(size, SSCOQSZ); - - } while (readl(SSCOPPQSEF) & (SSCOPPQSEF_FE | SSCOPPQSEF_OE)); - - /* wait until the operation is completed */ - while (readl(SSCOLPQS) != SSCOLPQS_EF) - ; - - /* clear the complete notification flag */ - writel(SSCOLPQS_EF, SSCOLPQS); -} - -static void uniphier_cache_maint_range(u32 start, u32 end, u32 operation) -{ - u32 size; - - /* - * If start address is not aligned to cache-line, - * do cache operation for the first cache-line - */ - start = start & ~(SSC_LINE_SIZE - 1); - - size = end - start; - - if (unlikely(size >= (u32)(-SSC_LINE_SIZE))) { - /* this means cache operation for all range */ - uniphier_cache_maint_all(operation); - return; - } - - /* - * If end address is not aligned to cache-line, - * do cache operation for the last cache-line - */ - size = ALIGN(size, SSC_LINE_SIZE); - - while (size) { - u32 chunk_size = size > SSC_RANGE_OP_MAX_SIZE ? - SSC_RANGE_OP_MAX_SIZE : size; - __uniphier_cache_maint_range(start, chunk_size, operation); - - start += chunk_size; - size -= chunk_size; - } - - uniphier_cache_sync(); -} - -void v7_outer_cache_flush_range(u32 start, u32 end) -{ - uniphier_cache_maint_range(start, end, SSCOQM_CM_WB_INV); -} - -void v7_outer_cache_inval_range(u32 start, u32 end) -{ - if (start & (SSC_LINE_SIZE - 1)) { - start &= ~(SSC_LINE_SIZE - 1); - __uniphier_cache_maint_range(start, SSC_LINE_SIZE, - SSCOQM_CM_WB_INV); - start += SSC_LINE_SIZE; - } - - if (start >= end) { - uniphier_cache_sync(); - return; - } - - if (end & (SSC_LINE_SIZE - 1)) { - end &= ~(SSC_LINE_SIZE - 1); - __uniphier_cache_maint_range(end, SSC_LINE_SIZE, - SSCOQM_CM_WB_INV); - } - - if (start >= end) { - uniphier_cache_sync(); - return; - } - - uniphier_cache_maint_range(start, end, SSCOQM_CM_INV); -} - -void v7_outer_cache_enable(void) -{ - u32 tmp; - - writel(U32_MAX, SSCLPDAWCR); /* activate all ways */ - tmp = readl(SSCC); - tmp |= SSCC_ON; - writel(tmp, SSCC); -} -#endif - -void v7_outer_cache_disable(void) -{ - u32 tmp; - tmp = readl(SSCC); - tmp &= ~SSCC_ON; - writel(tmp, SSCC); -} - -void enable_caches(void) -{ - dcache_enable(); -} diff --git a/arch/arm/mach-uniphier/debug_ll.S b/arch/arm/mach-uniphier/debug_ll.S deleted file mode 100644 index 6aa5f89..0000000 --- a/arch/arm/mach-uniphier/debug_ll.S +++ /dev/null @@ -1,186 +0,0 @@ -/* - * On-chip UART initializaion for low-level debugging - * - * Copyright (C) 2014-2015 Masahiro Yamada - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include - -#include "bcu/bcu-regs.h" -#include "sc-regs.h" -#include "sg-regs.h" - -#if !defined(CONFIG_DEBUG_SEMIHOSTING) -#include CONFIG_DEBUG_LL_INCLUDE -#endif - -#define BAUDRATE 115200 -#define DIV_ROUND(x, d) (((x) + ((d) / 2)) / (d)) - -ENTRY(debug_ll_init) - ldr r0, =SG_REVISION - ldr r1, [r0] - and r1, r1, #SG_REVISION_TYPE_MASK - mov r1, r1, lsr #SG_REVISION_TYPE_SHIFT - -#if defined(CONFIG_ARCH_UNIPHIER_PH1_SLD3) -#define PH1_SLD3_UART_CLK 36864000 - cmp r1, #0x25 - bne ph1_sld3_end - - sg_set_pinsel 64, 1, 4, 4, r0, r1 @ TXD0 -> TXD0 - - ldr r0, =BCSCR5 - ldr r1, =0x24440000 - str r1, [r0] - - ldr r0, =SC_CLKCTRL - ldr r1, [r0] - orr r1, r1, #SC_CLKCTRL_CEN_PERI - str r1, [r0] - - ldr r3, =DIV_ROUND(PH1_SLD3_UART_CLK, 16 * BAUDRATE) - - b init_uart -ph1_sld3_end: -#endif -#if defined(CONFIG_ARCH_UNIPHIER_PH1_LD4) -#define PH1_LD4_UART_CLK 36864000 - cmp r1, #0x26 - bne ph1_ld4_end - - ldr r0, =SG_IECTRL - ldr r1, [r0] - orr r1, r1, #1 - str r1, [r0] - - sg_set_pinsel 88, 1, 8, 4, r0, r1 @ HSDOUT6 -> TXD0 - - ldr r3, =DIV_ROUND(PH1_LD4_UART_CLK, 16 * BAUDRATE) - - b init_uart -ph1_ld4_end: -#endif -#if defined(CONFIG_ARCH_UNIPHIER_PH1_PRO4) -#define PH1_PRO4_UART_CLK 73728000 - cmp r1, #0x28 - bne ph1_pro4_end - - sg_set_pinsel 128, 0, 4, 8, r0, r1 @ TXD0 -> TXD0 - - ldr r0, =SG_LOADPINCTRL - mov r1, #1 - str r1, [r0] - - ldr r0, =SC_CLKCTRL - ldr r1, [r0] - orr r1, r1, #SC_CLKCTRL_CEN_PERI - str r1, [r0] - - ldr r3, =DIV_ROUND(PH1_PRO4_UART_CLK, 16 * BAUDRATE) - - b init_uart -ph1_pro4_end: -#endif -#if defined(CONFIG_ARCH_UNIPHIER_PH1_SLD8) -#define PH1_SLD8_UART_CLK 80000000 - cmp r1, #0x29 - bne ph1_sld8_end - - ldr r0, =SG_IECTRL - ldr r1, [r0] - orr r1, r1, #1 - str r1, [r0] - - sg_set_pinsel 70, 3, 8, 4, r0, r1 @ HSDOUT0 -> TXD0 - - ldr r3, =DIV_ROUND(PH1_SLD8_UART_CLK, 16 * BAUDRATE) - - b init_uart -ph1_sld8_end: -#endif -#if defined(CONFIG_ARCH_UNIPHIER_PH1_PRO5) -#define PH1_PRO5_UART_CLK 73728000 - cmp r1, #0x2A - bne ph1_pro5_end - - sg_set_pinsel 47, 0, 4, 8, r0, r1 @ TXD0 -> TXD0 - sg_set_pinsel 49, 0, 4, 8, r0, r1 @ TXD1 -> TXD1 - sg_set_pinsel 51, 0, 4, 8, r0, r1 @ TXD2 -> TXD2 - sg_set_pinsel 53, 0, 4, 8, r0, r1 @ TXD3 -> TXD3 - - ldr r0, =SG_LOADPINCTRL - mov r1, #1 - str r1, [r0] - - ldr r0, =SC_CLKCTRL - ldr r1, [r0] - orr r1, r1, #SC_CLKCTRL_CEN_PERI - str r1, [r0] - - ldr r3, =DIV_ROUND(PH1_PRO5_UART_CLK, 16 * BAUDRATE) - - b init_uart -ph1_pro5_end: -#endif -#if defined(CONFIG_ARCH_UNIPHIER_PROXSTREAM2) -#define PROXSTREAM2_UART_CLK 88900000 - cmp r1, #0x2E - bne proxstream2_end - - ldr r0, =SG_IECTRL - ldr r1, [r0] - orr r1, r1, #1 - str r1, [r0] - - sg_set_pinsel 217, 8, 8, 4, r0, r1 @ TXD0 -> TXD0 - sg_set_pinsel 115, 8, 8, 4, r0, r1 @ TXD1 -> TXD1 - sg_set_pinsel 113, 8, 8, 4, r0, r1 @ TXD2 -> TXD2 - sg_set_pinsel 219, 8, 8, 4, r0, r1 @ TXD3 -> TXD3 - - ldr r0, =SC_CLKCTRL - ldr r1, [r0] - orr r1, r1, #SC_CLKCTRL_CEN_PERI - str r1, [r0] - - ldr r3, =DIV_ROUND(PROXSTREAM2_UART_CLK, 16 * BAUDRATE) - - b init_uart -proxstream2_end: -#endif -#if defined(CONFIG_ARCH_UNIPHIER_PH1_LD6B) -#define PH1_LD6B_UART_CLK 88900000 - cmp r1, #0x2F - bne ph1_ld6b_end - - ldr r0, =SG_IECTRL - ldr r1, [r0] - orr r1, r1, #1 - str r1, [r0] - - sg_set_pinsel 135, 3, 8, 4, r0, r1 @ PORT10 -> TXD0 - sg_set_pinsel 115, 0, 8, 4, r0, r1 @ TXD1 -> TXD1 - sg_set_pinsel 113, 2, 8, 4, r0, r1 @ SBO0 -> TXD2 - - ldr r0, =SC_CLKCTRL - ldr r1, [r0] - orr r1, r1, #SC_CLKCTRL_CEN_PERI - str r1, [r0] - - ldr r3, =DIV_ROUND(PH1_LD6B_UART_CLK, 16 * BAUDRATE) - - b init_uart -ph1_ld6b_end: -#endif - -init_uart: - addruart r0, r1, r2 - mov r1, #UART_LCR_WLEN8 << 8 - str r1, [r0, #0x10] - str r3, [r0, #0x24] - - mov pc, lr -ENDPROC(debug_ll_init) diff --git a/arch/arm/mach-uniphier/late_lowlevel_init.S b/arch/arm/mach-uniphier/late_lowlevel_init.S deleted file mode 100644 index cce91df..0000000 --- a/arch/arm/mach-uniphier/late_lowlevel_init.S +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (C) 2015 Socionext Inc. - * Author: Masahiro Yamada - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include - -#include "ssc-regs.h" - -ENTRY(lowlevel_init) - ldr r1, = SSCC - ldr r0, [r1] - bic r0, r0, #SSCC_ON @ L2 disable - str r0, [r1] - mov pc, lr -ENDPROC(lowlevel_init) diff --git a/arch/arm/mach-uniphier/lowlevel_init.S b/arch/arm/mach-uniphier/lowlevel_init.S deleted file mode 100644 index dd03ad8..0000000 --- a/arch/arm/mach-uniphier/lowlevel_init.S +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright (C) 2012-2015 Masahiro Yamada - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include - -#include "ssc-regs.h" - -ENTRY(lowlevel_init) - mov r8, lr @ persevere link reg across call - - /* - * The UniPhier Boot ROM loads SPL code to the L2 cache. - * But CPUs can only do instruction fetch now because start.S has - * cleared C and M bits. - * First we need to turn on MMU and Dcache again to get back - * data access to L2. - */ - mrc p15, 0, r0, c1, c0, 0 @ SCTLR (System Control Register) - orr r0, r0, #(CR_C | CR_M) @ enable MMU and Dcache - mcr p15, 0, r0, c1, c0, 0 - -#ifdef CONFIG_DEBUG_LL - bl debug_ll_init -#endif - - bl setup_init_ram @ RAM area for stack and page talbe - - /* - * Now we are using the page table embedded in the Boot ROM. - * It is not handy since it is not a straight mapped table for sLD3. - * Also, the access to the external bus is prohibited. What we need - * to do next is to create a page table and switch over to it. - */ - bl create_page_table - bl v7_flush_dcache_all - - /* Disable MMU and Dcache before switching Page Table */ - mrc p15, 0, r0, c1, c0, 0 @ SCTLR (System Control Register) - bic r0, r0, #(CR_C | CR_M) @ disable MMU and Dcache - mcr p15, 0, r0, c1, c0, 0 - - bl enable_mmu - - mov lr, r8 @ restore link - mov pc, lr @ back to my caller -ENDPROC(lowlevel_init) - -ENTRY(enable_mmu) - mrc p15, 0, r0, c2, c0, 2 @ TTBCR (Translation Table Base Control Register) - bic r0, r0, #0x37 - orr r0, r0, #0x20 @ disable TTBR1 - mcr p15, 0, r0, c2, c0, 2 - - orr r0, r12, #0x8 @ Outer Cacheability for table walks: WBWA - mcr p15, 0, r0, c2, c0, 0 @ TTBR0 - - mov r0, #0 - mcr p15, 0, r0, c8, c7, 0 @ invalidate TLBs - - mov r0, #-1 @ manager for all domains (No permission check) - mcr p15, 0, r0, c3, c0, 0 @ DACR (Domain Access Control Register) - - dsb - isb - /* - * MMU on: - * TLBs was already invalidated in "../start.S" - * So, we don't need to invalidate it here. - */ - mrc p15, 0, r0, c1, c0, 0 @ SCTLR (System Control Register) - orr r0, r0, #(CR_C | CR_M) @ MMU and Dcache enable - mcr p15, 0, r0, c1, c0, 0 - - mov pc, lr -ENDPROC(enable_mmu) - -/* - * For PH1-Pro4 or older SoCs, the size of WAY is 32KB. - * It is large enough for tmp RAM. - */ -#define BOOT_RAM_SIZE (SZ_32K) -#define BOOT_RAM_BASE ((CONFIG_SPL_STACK) - (BOOT_RAM_SIZE)) -#define BOOT_WAY_BITS (0x00000100) /* way 8 */ - -ENTRY(setup_init_ram) - /* - * Touch to zero for the boot way - */ -0: - /* - * set SSCOQM, SSCOQAD, SSCOQSZ, SSCOQWN in this order - */ - ldr r0, = 0x00408006 @ touch to zero with address range - ldr r1, = SSCOQM - str r0, [r1] - ldr r0, = BOOT_RAM_BASE - ldr r1, = SSCOQAD - str r0, [r1] - ldr r0, = BOOT_RAM_SIZE - ldr r1, = SSCOQSZ - str r0, [r1] - ldr r0, = BOOT_WAY_BITS - ldr r1, = SSCOQWN - str r0, [r1] - ldr r1, = SSCOPPQSEF - ldr r0, [r1] - cmp r0, #0 @ check if the command is successfully set - bne 0b @ try again if an error occurs - - ldr r1, = SSCOLPQS -1: - ldr r0, [r1] - cmp r0, #0x4 - bne 1b @ wait until the operation is completed - str r0, [r1] @ clear the complete notification flag - - mov pc, lr -ENDPROC(setup_init_ram) - -#define DEVICE 0x00002002 /* Non-shareable Device */ -#define NORMAL 0x0000000e /* Normal Memory Write-Back, No Write-Allocate */ - -ENTRY(create_page_table) - ldr r0, = DEVICE - ldr r1, = BOOT_RAM_BASE - mov r12, r1 @ r12 is preserved during D-cache flush -0: str r0, [r1], #4 @ specify all the sections as Device - adds r0, r0, #0x00100000 - bcc 0b - - ldr r0, = NORMAL - str r0, [r12] @ mark the first section as Normal - add r0, r0, #0x00100000 - str r0, [r12, #4] @ mark the second section as Normal - mov pc, lr -ENDPROC(create_page_table) - -/* We don't use Thumb instructions for now */ -#define ARM(x...) x -#define THUMB(x...) - -/* - * v7_flush_dcache_all() - * - * Flush the whole D-cache. - * - * Corrupted registers: r0-r7, r9-r11 (r6 only in Thumb mode) - * - * - mm - mm_struct describing address space - * - * Note: copied from arch/arm/mm/cache-v7.S of Linux 4.4 - */ -ENTRY(v7_flush_dcache_all) - dmb @ ensure ordering with previous memory accesses - mrc p15, 1, r0, c0, c0, 1 @ read clidr - mov r3, r0, lsr #23 @ move LoC into position - ands r3, r3, #7 << 1 @ extract LoC*2 from clidr - beq finished @ if loc is 0, then no need to clean -start_flush_levels: - mov r10, #0 @ start clean at cache level 0 -flush_levels: - add r2, r10, r10, lsr #1 @ work out 3x current cache level - mov r1, r0, lsr r2 @ extract cache type bits from clidr - and r1, r1, #7 @ mask of the bits for current cache only - cmp r1, #2 @ see what cache we have at this level - blt skip @ skip if no cache, or just i-cache - mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr - isb @ isb to sych the new cssr&csidr - mrc p15, 1, r1, c0, c0, 0 @ read the new csidr - and r2, r1, #7 @ extract the length of the cache lines - add r2, r2, #4 @ add 4 (line length offset) - movw r4, #0x3ff - ands r4, r4, r1, lsr #3 @ find maximum number on the way size - clz r5, r4 @ find bit position of way size increment - movw r7, #0x7fff - ands r7, r7, r1, lsr #13 @ extract max number of the index size -loop1: - mov r9, r7 @ create working copy of max index -loop2: - ARM( orr r11, r10, r4, lsl r5 ) @ factor way and cache number into r11 - THUMB( lsl r6, r4, r5 ) - THUMB( orr r11, r10, r6 ) @ factor way and cache number into r11 - ARM( orr r11, r11, r9, lsl r2 ) @ factor index number into r11 - THUMB( lsl r6, r9, r2 ) - THUMB( orr r11, r11, r6 ) @ factor index number into r11 - mcr p15, 0, r11, c7, c14, 2 @ clean & invalidate by set/way - subs r9, r9, #1 @ decrement the index - bge loop2 - subs r4, r4, #1 @ decrement the way - bge loop1 -skip: - add r10, r10, #2 @ increment cache number - cmp r3, r10 - bgt flush_levels -finished: - mov r10, #0 @ swith back to cache level 0 - mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr - dsb st - isb - mov pc, lr -ENDPROC(v7_flush_dcache_all) diff --git a/arch/arm/mach-uniphier/ssc-regs.h b/arch/arm/mach-uniphier/ssc-regs.h deleted file mode 100644 index 02fca3b..0000000 --- a/arch/arm/mach-uniphier/ssc-regs.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * UniPhier System Cache (L2 Cache) registers - * - * Copyright (C) 2011-2014 Panasonic Corporation - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifndef ARCH_SSC_REGS_H -#define ARCH_SSC_REGS_H - -#define SSCC 0x500c0000 -#define SSCC_BST (0x1 << 20) -#define SSCC_ACT (0x1 << 19) -#define SSCC_WTG (0x1 << 18) -#define SSCC_PRD (0x1 << 17) -#define SSCC_WBWA (0x1 << 16) -#define SSCC_EX (0x1 << 13) -#define SSCC_ON (0x1 << 0) - -#define SSCLPDAWCR 0x500c0030 - -#define SSCOPE 0x506c0244 -#define SSCOPE_CM_SYNC 0x00000008 - -#define SSCOQM 0x506c0248 -#define SSCOQM_TID_MASK (0x3 << 21) -#define SSCOQM_TID_BY_WAY (0x2 << 21) -#define SSCOQM_TID_BY_INST_WAY (0x1 << 21) -#define SSCOQM_TID_BY_DATA_WAY (0x0 << 21) -#define SSCOQM_S_MASK (0x3 << 17) -#define SSCOQM_S_WAY (0x2 << 17) -#define SSCOQM_S_ALL (0x1 << 17) -#define SSCOQM_S_ADDRESS (0x0 << 17) -#define SSCOQM_CE (0x1 << 15) -#define SSCOQM_CW (0x1 << 14) -#define SSCOQM_CM_MASK (0x7) -#define SSCOQM_CM_DIRT_TOUCH (0x7) -#define SSCOQM_CM_ZERO_TOUCH (0x6) -#define SSCOQM_CM_NORM_TOUCH (0x5) -#define SSCOQM_CM_PREF_FETCH (0x4) -#define SSCOQM_CM_SSC_FETCH (0x3) -#define SSCOQM_CM_WB_INV (0x2) -#define SSCOQM_CM_WB (0x1) -#define SSCOQM_CM_INV (0x0) - -#define SSCOQAD 0x506c024c -#define SSCOQSZ 0x506c0250 -#define SSCOQWN 0x506c0258 - -#define SSCOPPQSEF 0x506c025c -#define SSCOPPQSEF_FE (0x1 << 1) -#define SSCOPPQSEF_OE (0x1 << 0) - -#define SSCOLPQS 0x506c0260 -#define SSCOLPQS_EF (0x1 << 2) -#define SSCOLPQS_EST (0x1 << 1) -#define SSCOLPQS_QST (0x1 << 0) - -#define SSCOQCE0 0x506c0270 - -#define SSC_LINE_SIZE 128 -#define SSC_RANGE_OP_MAX_SIZE (0x00400000 - (SSC_LINE_SIZE)) - -#endif /* ARCH_SSC_REGS_H */ diff --git a/arch/arm/mach-uniphier/timer.c b/arch/arm/mach-uniphier/timer.c deleted file mode 100644 index a34e30b..0000000 --- a/arch/arm/mach-uniphier/timer.c +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2012-2015 Masahiro Yamada - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include - -#include "arm-mpcore.h" - -#define PERIPHCLK (50 * 1000 * 1000) /* 50 MHz */ -#define PRESCALER ((PERIPHCLK) / (CONFIG_SYS_TIMER_RATE) - 1) - -static void *get_global_timer_base(void) -{ - void *val; - - asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (val) : : "memory"); - - return val + GLOBAL_TIMER_OFFSET; -} - -unsigned long timer_read_counter(void) -{ - /* - * ARM 64bit Global Timer is too much for our purpose. - * We use only lower 32 bit of the timer counter. - */ - return readl(get_global_timer_base() + GTIMER_CNT_L); -} - -int timer_init(void) -{ - /* enable timer */ - writel(PRESCALER << 8 | 1, get_global_timer_base() + GTIMER_CTRL); - - return 0; -} -- cgit v0.10.2 From 11d3ede42ceccef9b5941ea7907f398cb97ed361 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 18:59:45 +0900 Subject: 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 diff --git a/arch/arm/mach-uniphier/dram_init.c b/arch/arm/mach-uniphier/dram_init.c index 32cc448..cffdfc9 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 f777ac1..f7a37e3 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 678d437..3a535c7 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; -- cgit v0.10.2