From 4d7820b0465a78e6c85a74474b89fb4ab84768ba Mon Sep 17 00:00:00 2001 From: Pankaj Dubey Date: Mon, 11 Apr 2016 13:12:28 +0530 Subject: [PATCH 1/6] ARM: dts: change SROM node compatible from generic to model specific This patch changes SROM nodes compatible from generic to model specific to match with binding documentation. Also updating property "samsung,srom-page-mode" as it is not defined as bool instead of int Signed-off-by: Pankaj Dubey Signed-off-by: Krzysztof Kozlowski --- arch/arm/boot/dts/exynos4.dtsi | 4 ++-- arch/arm/boot/dts/exynos5.dtsi | 4 ++-- arch/arm/boot/dts/exynos5410-smdk5410.dts | 2 +- arch/arm/boot/dts/exynos5410.dtsi | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi index c679b3cc3c48..d68f572fc7e6 100644 --- a/arch/arm/boot/dts/exynos4.dtsi +++ b/arch/arm/boot/dts/exynos4.dtsi @@ -77,8 +77,8 @@ reg = <0x10000000 0x100>; }; - sromc@12570000 { - compatible = "samsung,exynos-srom"; + memory-controller@12570000 { + compatible = "samsung,exynos4210-srom"; reg = <0x12570000 0x14>; }; diff --git a/arch/arm/boot/dts/exynos5.dtsi b/arch/arm/boot/dts/exynos5.dtsi index 92313cac035e..d5c0f18a4223 100644 --- a/arch/arm/boot/dts/exynos5.dtsi +++ b/arch/arm/boot/dts/exynos5.dtsi @@ -31,8 +31,8 @@ reg = <0x10000000 0x100>; }; - sromc@12250000 { - compatible = "samsung,exynos-srom"; + memory-controller@12250000 { + compatible = "samsung,exynos4210-srom"; reg = <0x12250000 0x14>; }; diff --git a/arch/arm/boot/dts/exynos5410-smdk5410.dts b/arch/arm/boot/dts/exynos5410-smdk5410.dts index a731fbe28ebc..0f6429e1b75c 100644 --- a/arch/arm/boot/dts/exynos5410-smdk5410.dts +++ b/arch/arm/boot/dts/exynos5410-smdk5410.dts @@ -97,7 +97,7 @@ smsc,irq-push-pull; smsc,force-internal-phy; - samsung,srom-page-mode = <1>; + samsung,srom-page-mode; samsung,srom-timing = <9 12 1 9 1 1>; }; }; diff --git a/arch/arm/boot/dts/exynos5410.dtsi b/arch/arm/boot/dts/exynos5410.dtsi index fa558674ac76..7a56aec2c5ba 100644 --- a/arch/arm/boot/dts/exynos5410.dtsi +++ b/arch/arm/boot/dts/exynos5410.dtsi @@ -102,8 +102,8 @@ reg = <0x10000000 0x100>; }; - sromc: sromc@12250000 { - compatible = "samsung,exynos-srom"; + sromc: memory-controller@12250000 { + compatible = "samsung,exynos4210-srom"; reg = <0x12250000 0x14>; #address-cells = <2>; #size-cells = <1>; From 92537d65d58ede86d752d1390cf3b51480ab0179 Mon Sep 17 00:00:00 2001 From: Pankaj Dubey Date: Mon, 11 Apr 2016 13:12:23 +0530 Subject: [PATCH 2/6] dt-bindings: EXYNOS: Add exynos-srom device tree binding This patch adds exynos-srom binding information for SROM Controller driver on Exynos SoCs. Documentation for new subnode properties, allowing bank configuration are added based on u-boot implementation, but heavily reworked. CC: Rob Herring CC: Mark Rutland CC: Ian Campbell Signed-off-by: Pankaj Dubey [p.fedin: Added SROMc configuration description and fixed SROMc mapping] Signed-off-by: Pavel Fedin Reviewed-by: Krzysztof Kozlowski Signed-off-by: Kukjin Kim Signed-off-by: Krzysztof Kozlowski --- .../memory-controllers/exynos-srom.txt | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 Documentation/devicetree/bindings/memory-controllers/exynos-srom.txt diff --git a/Documentation/devicetree/bindings/memory-controllers/exynos-srom.txt b/Documentation/devicetree/bindings/memory-controllers/exynos-srom.txt new file mode 100644 index 000000000000..f633b5d0f8ca --- /dev/null +++ b/Documentation/devicetree/bindings/memory-controllers/exynos-srom.txt @@ -0,0 +1,79 @@ +SAMSUNG Exynos SoCs SROM Controller driver. + +Required properties: +- compatible : Should contain "samsung,exynos4210-srom". + +- reg: offset and length of the register set + +Optional properties: +The SROM controller can be used to attach external peripherals. In this case +extra properties, describing the bus behind it, should be specified as below: + +- #address-cells: Must be set to 2 to allow device address translation. + Address is specified as (bank#, offset). + +- #size-cells: Must be set to 1 to allow device size passing + +- ranges: Must be set up to reflect the memory layout with four integer values + per bank: + 0 + +Sub-nodes: +The actual device nodes should be added as subnodes to the SROMc node. These +subnodes, in addition to regular device specification, should contain the following +properties, describing configuration of the relevant SROM bank: + +Required properties: +- reg: bank number, base address (relative to start of the bank) and size of + the memory mapped for the device. Note that base address will be + typically 0 as this is the start of the bank. + +- samsung,srom-timing : array of 6 integers, specifying bank timings in the + following order: Tacp, Tcah, Tcoh, Tacc, Tcos, Tacs. + Each value is specified in cycles and has the following + meaning and valid range: + Tacp : Page mode access cycle at Page mode (0 - 15) + Tcah : Address holding time after CSn (0 - 15) + Tcoh : Chip selection hold on OEn (0 - 15) + Tacc : Access cycle (0 - 31, the actual time is N + 1) + Tcos : Chip selection set-up before OEn (0 - 15) + Tacs : Address set-up before CSn (0 - 15) + +Optional properties: +- reg-io-width : data width in bytes (1 or 2). If omitted, default of 1 is used. + +- samsung,srom-page-mode : if page mode is set, 4 data page mode will be configured, + else normal (1 data) page mode will be set. + +Example: basic definition, no banks are configured + memory-controller@12570000 { + compatible = "samsung,exynos4210-srom"; + reg = <0x12570000 0x14>; + }; + +Example: SROMc with SMSC911x ethernet chip on bank 3 + memory-controller@12570000 { + #address-cells = <2>; + #size-cells = <1>; + ranges = <0 0 0x04000000 0x20000 // Bank0 + 1 0 0x05000000 0x20000 // Bank1 + 2 0 0x06000000 0x20000 // Bank2 + 3 0 0x07000000 0x20000>; // Bank3 + + compatible = "samsung,exynos4210-srom"; + reg = <0x12570000 0x14>; + + ethernet@3,0 { + compatible = "smsc,lan9115"; + reg = <3 0 0x10000>; // Bank 3, offset = 0 + phy-mode = "mii"; + interrupt-parent = <&gpx0>; + interrupts = <5 8>; + reg-io-width = <2>; + smsc,irq-push-pull; + smsc,force-internal-phy; + + samsung,srom-page-mode; + samsung,srom-timing = <9 12 1 9 1 1>; + }; + }; From a8aabb91dc5bef0875d93d6a86d01779947604e1 Mon Sep 17 00:00:00 2001 From: Pankaj Dubey Date: Mon, 11 Apr 2016 13:12:24 +0530 Subject: [PATCH 3/6] memory: Add support for Exynos SROM driver This patch adds Exynos SROM controller driver which will handle save restore of SROM registers during S2R. Signed-off-by: Pankaj Dubey Reviewed-by: Krzysztof Kozlowski [p.fedin@samsung.com: tested on SMDK5410] Tested-by: Pavel Fedin Signed-off-by: Kukjin Kim [k.kozlowski: Minor COMPILE_TEST adjustments in Kconfig entries] Signed-off-by: Krzysztof Kozlowski --- drivers/memory/Kconfig | 1 + drivers/memory/Makefile | 1 + drivers/memory/samsung/Kconfig | 13 ++ drivers/memory/samsung/Makefile | 1 + drivers/memory/samsung/exynos-srom.c | 175 +++++++++++++++++++++++++++ drivers/memory/samsung/exynos-srom.h | 51 ++++++++ 6 files changed, 242 insertions(+) create mode 100644 drivers/memory/samsung/Kconfig create mode 100644 drivers/memory/samsung/Makefile create mode 100644 drivers/memory/samsung/exynos-srom.c create mode 100644 drivers/memory/samsung/exynos-srom.h diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig index 51d5cd20c26a..c61a284133e0 100644 --- a/drivers/memory/Kconfig +++ b/drivers/memory/Kconfig @@ -122,6 +122,7 @@ config MTK_SMI mainly help enable/disable iommu and control the power domain and clocks for each local arbiter. +source "drivers/memory/samsung/Kconfig" source "drivers/memory/tegra/Kconfig" endif diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile index 890bdf402449..cb0b7a1df11a 100644 --- a/drivers/memory/Makefile +++ b/drivers/memory/Makefile @@ -17,4 +17,5 @@ obj-$(CONFIG_TEGRA20_MC) += tegra20-mc.o obj-$(CONFIG_JZ4780_NEMC) += jz4780-nemc.o obj-$(CONFIG_MTK_SMI) += mtk-smi.o +obj-$(CONFIG_SAMSUNG_MC) += samsung/ obj-$(CONFIG_TEGRA_MC) += tegra/ diff --git a/drivers/memory/samsung/Kconfig b/drivers/memory/samsung/Kconfig new file mode 100644 index 000000000000..64ab5dd9f626 --- /dev/null +++ b/drivers/memory/samsung/Kconfig @@ -0,0 +1,13 @@ +config SAMSUNG_MC + bool "Samsung Exynos Memory Controller support" if COMPILE_TEST + help + Support for the Memory Controller (MC) devices found on + Samsung Exynos SoCs. + +if SAMSUNG_MC + +config EXYNOS_SROM + bool "Exynos SROM controller driver" if COMPILE_TEST + depends on (ARM && ARCH_EXYNOS && PM) || (COMPILE_TEST && HAS_IOMEM) + +endif diff --git a/drivers/memory/samsung/Makefile b/drivers/memory/samsung/Makefile new file mode 100644 index 000000000000..9c554d5522ad --- /dev/null +++ b/drivers/memory/samsung/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_EXYNOS_SROM) += exynos-srom.o diff --git a/drivers/memory/samsung/exynos-srom.c b/drivers/memory/samsung/exynos-srom.c new file mode 100644 index 000000000000..68e073c1651c --- /dev/null +++ b/drivers/memory/samsung/exynos-srom.c @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * EXYNOS - SROM Controller support + * Author: Pankaj Dubey + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include + +#include "exynos-srom.h" + +static const unsigned long exynos_srom_offsets[] = { + /* SROM side */ + EXYNOS_SROM_BW, + EXYNOS_SROM_BC0, + EXYNOS_SROM_BC1, + EXYNOS_SROM_BC2, + EXYNOS_SROM_BC3, +}; + +/** + * struct exynos_srom_reg_dump: register dump of SROM Controller registers. + * @offset: srom register offset from the controller base address. + * @value: the value of register under the offset. + */ +struct exynos_srom_reg_dump { + u32 offset; + u32 value; +}; + +/** + * struct exynos_srom: platform data for exynos srom controller driver. + * @dev: platform device pointer + * @reg_base: srom base address + * @reg_offset: exynos_srom_reg_dump pointer to hold offset and its value. + */ +struct exynos_srom { + struct device *dev; + void __iomem *reg_base; + struct exynos_srom_reg_dump *reg_offset; +}; + +static struct exynos_srom_reg_dump *exynos_srom_alloc_reg_dump( + const unsigned long *rdump, + unsigned long nr_rdump) +{ + struct exynos_srom_reg_dump *rd; + unsigned int i; + + rd = kcalloc(nr_rdump, sizeof(*rd), GFP_KERNEL); + if (!rd) + return NULL; + + for (i = 0; i < nr_rdump; ++i) + rd[i].offset = rdump[i]; + + return rd; +} + +static int exynos_srom_probe(struct platform_device *pdev) +{ + struct device_node *np; + struct exynos_srom *srom; + struct device *dev = &pdev->dev; + + np = dev->of_node; + if (!np) { + dev_err(&pdev->dev, "could not find device info\n"); + return -EINVAL; + } + + srom = devm_kzalloc(&pdev->dev, + sizeof(struct exynos_srom), GFP_KERNEL); + if (!srom) + return -ENOMEM; + + srom->dev = dev; + srom->reg_base = of_iomap(np, 0); + if (!srom->reg_base) { + dev_err(&pdev->dev, "iomap of exynos srom controller failed\n"); + return -ENOMEM; + } + + platform_set_drvdata(pdev, srom); + + srom->reg_offset = exynos_srom_alloc_reg_dump(exynos_srom_offsets, + sizeof(exynos_srom_offsets)); + if (!srom->reg_offset) { + iounmap(srom->reg_base); + return -ENOMEM; + } + + return 0; +} + +static int exynos_srom_remove(struct platform_device *pdev) +{ + struct exynos_srom *srom = platform_get_drvdata(pdev); + + kfree(srom->reg_offset); + iounmap(srom->reg_base); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static void exynos_srom_save(void __iomem *base, + struct exynos_srom_reg_dump *rd, + unsigned int num_regs) +{ + for (; num_regs > 0; --num_regs, ++rd) + rd->value = readl(base + rd->offset); +} + +static void exynos_srom_restore(void __iomem *base, + const struct exynos_srom_reg_dump *rd, + unsigned int num_regs) +{ + for (; num_regs > 0; --num_regs, ++rd) + writel(rd->value, base + rd->offset); +} + +static int exynos_srom_suspend(struct device *dev) +{ + struct exynos_srom *srom = dev_get_drvdata(dev); + + exynos_srom_save(srom->reg_base, srom->reg_offset, + ARRAY_SIZE(exynos_srom_offsets)); + return 0; +} + +static int exynos_srom_resume(struct device *dev) +{ + struct exynos_srom *srom = dev_get_drvdata(dev); + + exynos_srom_restore(srom->reg_base, srom->reg_offset, + ARRAY_SIZE(exynos_srom_offsets)); + return 0; +} +#endif + +static const struct of_device_id of_exynos_srom_ids[] = { + { + .compatible = "samsung,exynos4210-srom", + }, + {}, +}; +MODULE_DEVICE_TABLE(of, of_exynos_srom_ids); + +static SIMPLE_DEV_PM_OPS(exynos_srom_pm_ops, exynos_srom_suspend, exynos_srom_resume); + +static struct platform_driver exynos_srom_driver = { + .probe = exynos_srom_probe, + .remove = exynos_srom_remove, + .driver = { + .name = "exynos-srom", + .of_match_table = of_exynos_srom_ids, + .pm = &exynos_srom_pm_ops, + }, +}; +module_platform_driver(exynos_srom_driver); + +MODULE_AUTHOR("Pankaj Dubey "); +MODULE_DESCRIPTION("Exynos SROM Controller Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/memory/samsung/exynos-srom.h b/drivers/memory/samsung/exynos-srom.h new file mode 100644 index 000000000000..34660c6a57a9 --- /dev/null +++ b/drivers/memory/samsung/exynos-srom.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Exynos SROMC register definitions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __EXYNOS_SROM_H +#define __EXYNOS_SROM_H __FILE__ + +#define EXYNOS_SROMREG(x) (x) + +#define EXYNOS_SROM_BW EXYNOS_SROMREG(0x0) +#define EXYNOS_SROM_BC0 EXYNOS_SROMREG(0x4) +#define EXYNOS_SROM_BC1 EXYNOS_SROMREG(0x8) +#define EXYNOS_SROM_BC2 EXYNOS_SROMREG(0xc) +#define EXYNOS_SROM_BC3 EXYNOS_SROMREG(0x10) +#define EXYNOS_SROM_BC4 EXYNOS_SROMREG(0x14) +#define EXYNOS_SROM_BC5 EXYNOS_SROMREG(0x18) + +/* one register BW holds 4 x 4-bit packed settings for NCS0 - NCS3 */ + +#define EXYNOS_SROM_BW__DATAWIDTH__SHIFT 0 +#define EXYNOS_SROM_BW__ADDRMODE__SHIFT 1 +#define EXYNOS_SROM_BW__WAITENABLE__SHIFT 2 +#define EXYNOS_SROM_BW__BYTEENABLE__SHIFT 3 + +#define EXYNOS_SROM_BW__CS_MASK 0xf + +#define EXYNOS_SROM_BW__NCS0__SHIFT 0 +#define EXYNOS_SROM_BW__NCS1__SHIFT 4 +#define EXYNOS_SROM_BW__NCS2__SHIFT 8 +#define EXYNOS_SROM_BW__NCS3__SHIFT 12 +#define EXYNOS_SROM_BW__NCS4__SHIFT 16 +#define EXYNOS_SROM_BW__NCS5__SHIFT 20 + +/* applies to same to BCS0 - BCS3 */ + +#define EXYNOS_SROM_BCX__PMC__SHIFT 0 +#define EXYNOS_SROM_BCX__TACP__SHIFT 4 +#define EXYNOS_SROM_BCX__TCAH__SHIFT 8 +#define EXYNOS_SROM_BCX__TCOH__SHIFT 12 +#define EXYNOS_SROM_BCX__TACC__SHIFT 16 +#define EXYNOS_SROM_BCX__TCOS__SHIFT 24 +#define EXYNOS_SROM_BCX__TACS__SHIFT 28 + +#endif /* __EXYNOS_SROM_H */ From ffd51977beb3909c4626bab41cc5f405b308fcb2 Mon Sep 17 00:00:00 2001 From: Pankaj Dubey Date: Mon, 11 Apr 2016 13:12:25 +0530 Subject: [PATCH 4/6] MAINTAINERS: Add maintainers entry for drivers/memory/samsung Add maintainers entry for new driver folder drivers/memory/samsung. Signed-off-by: Pankaj Dubey Signed-off-by: Krzysztof Kozlowski --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 03e00c7c88eb..0d2a26437936 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1540,6 +1540,7 @@ F: arch/arm/mach-s5p*/ F: arch/arm/mach-exynos*/ F: drivers/*/*s3c2410* F: drivers/*/*/*s3c2410* +F: drivers/memory/samsung/* F: drivers/soc/samsung/* F: drivers/spi/spi-s3c* F: sound/soc/samsung/* From 5901f4c279f7ddbd32041ce1166387ffa05b902d Mon Sep 17 00:00:00 2001 From: Pankaj Dubey Date: Mon, 11 Apr 2016 13:12:26 +0530 Subject: [PATCH 5/6] ARM: EXYNOS: Remove SROM related register settings from mach-exynos As now we have dedicated driver for SROM controller, it will take care of saving register banks during S2R so we can safely remove these settings from mach-exynos. Signed-off-by: Pankaj Dubey Reviewed-by: Krzysztof Kozlowski Signed-off-by: Kukjin Kim [k.kozlowski: Need to select also SAMSUNG_MC] Signed-off-by: Krzysztof Kozlowski --- arch/arm/mach-exynos/Kconfig | 3 ++ arch/arm/mach-exynos/exynos.c | 17 ------- arch/arm/mach-exynos/include/mach/map.h | 3 -- arch/arm/mach-exynos/regs-srom.h | 53 -------------------- arch/arm/mach-exynos/suspend.c | 20 +------- arch/arm/plat-samsung/include/plat/map-s5p.h | 1 - 6 files changed, 5 insertions(+), 92 deletions(-) delete mode 100644 arch/arm/mach-exynos/regs-srom.h diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig index 207fa2c737a6..28f992886d67 100644 --- a/arch/arm/mach-exynos/Kconfig +++ b/arch/arm/mach-exynos/Kconfig @@ -18,6 +18,7 @@ menuconfig ARCH_EXYNOS select COMMON_CLK_SAMSUNG select EXYNOS_THERMAL select EXYNOS_PMU + select EXYNOS_SROM if PM select HAVE_ARM_SCU if SMP select HAVE_S3C2410_I2C if I2C select HAVE_S3C2410_WATCHDOG if WATCHDOG @@ -26,11 +27,13 @@ menuconfig ARCH_EXYNOS select PINCTRL_EXYNOS select PM_GENERIC_DOMAINS if PM select S5P_DEV_MFC + select SAMSUNG_MC select SOC_SAMSUNG select SRAM select THERMAL select THERMAL_OF select MFD_SYSCON + select MEMORY select CLKSRC_EXYNOS_MCT select POWER_RESET select POWER_RESET_SYSCON diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c index bbf51a46f772..f977eea1c496 100644 --- a/arch/arm/mach-exynos/exynos.c +++ b/arch/arm/mach-exynos/exynos.c @@ -31,11 +31,6 @@ static struct map_desc exynos4_iodesc[] __initdata = { { - .virtual = (unsigned long)S5P_VA_SROMC, - .pfn = __phys_to_pfn(EXYNOS4_PA_SROMC), - .length = SZ_4K, - .type = MT_DEVICE, - }, { .virtual = (unsigned long)S5P_VA_CMU, .pfn = __phys_to_pfn(EXYNOS4_PA_CMU), .length = SZ_128K, @@ -58,15 +53,6 @@ static struct map_desc exynos4_iodesc[] __initdata = { }, }; -static struct map_desc exynos5_iodesc[] __initdata = { - { - .virtual = (unsigned long)S5P_VA_SROMC, - .pfn = __phys_to_pfn(EXYNOS5_PA_SROMC), - .length = SZ_4K, - .type = MT_DEVICE, - }, -}; - static struct platform_device exynos_cpuidle = { .name = "exynos_cpuidle", #ifdef CONFIG_ARM_EXYNOS_CPUIDLE @@ -138,9 +124,6 @@ static void __init exynos_map_io(void) { if (soc_is_exynos4()) iotable_init(exynos4_iodesc, ARRAY_SIZE(exynos4_iodesc)); - - if (soc_is_exynos5()) - iotable_init(exynos5_iodesc, ARRAY_SIZE(exynos5_iodesc)); } static void __init exynos_init_io(void) diff --git a/arch/arm/mach-exynos/include/mach/map.h b/arch/arm/mach-exynos/include/mach/map.h index c88325d56743..c48ba4fbdfd2 100644 --- a/arch/arm/mach-exynos/include/mach/map.h +++ b/arch/arm/mach-exynos/include/mach/map.h @@ -25,7 +25,4 @@ #define EXYNOS4_PA_COREPERI 0x10500000 -#define EXYNOS4_PA_SROMC 0x12570000 -#define EXYNOS5_PA_SROMC 0x12250000 - #endif /* __ASM_ARCH_MAP_H */ diff --git a/arch/arm/mach-exynos/regs-srom.h b/arch/arm/mach-exynos/regs-srom.h deleted file mode 100644 index 5c4d4427db7b..000000000000 --- a/arch/arm/mach-exynos/regs-srom.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2010 Samsung Electronics Co., Ltd. - * http://www.samsung.com - * - * S5P SROMC register definitions - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. -*/ - -#ifndef __PLAT_SAMSUNG_REGS_SROM_H -#define __PLAT_SAMSUNG_REGS_SROM_H __FILE__ - -#include - -#define S5P_SROMREG(x) (S5P_VA_SROMC + (x)) - -#define S5P_SROM_BW S5P_SROMREG(0x0) -#define S5P_SROM_BC0 S5P_SROMREG(0x4) -#define S5P_SROM_BC1 S5P_SROMREG(0x8) -#define S5P_SROM_BC2 S5P_SROMREG(0xc) -#define S5P_SROM_BC3 S5P_SROMREG(0x10) -#define S5P_SROM_BC4 S5P_SROMREG(0x14) -#define S5P_SROM_BC5 S5P_SROMREG(0x18) - -/* one register BW holds 4 x 4-bit packed settings for NCS0 - NCS3 */ - -#define S5P_SROM_BW__DATAWIDTH__SHIFT 0 -#define S5P_SROM_BW__ADDRMODE__SHIFT 1 -#define S5P_SROM_BW__WAITENABLE__SHIFT 2 -#define S5P_SROM_BW__BYTEENABLE__SHIFT 3 - -#define S5P_SROM_BW__CS_MASK 0xf - -#define S5P_SROM_BW__NCS0__SHIFT 0 -#define S5P_SROM_BW__NCS1__SHIFT 4 -#define S5P_SROM_BW__NCS2__SHIFT 8 -#define S5P_SROM_BW__NCS3__SHIFT 12 -#define S5P_SROM_BW__NCS4__SHIFT 16 -#define S5P_SROM_BW__NCS5__SHIFT 20 - -/* applies to same to BCS0 - BCS3 */ - -#define S5P_SROM_BCX__PMC__SHIFT 0 -#define S5P_SROM_BCX__TACP__SHIFT 4 -#define S5P_SROM_BCX__TCAH__SHIFT 8 -#define S5P_SROM_BCX__TCOH__SHIFT 12 -#define S5P_SROM_BCX__TACC__SHIFT 16 -#define S5P_SROM_BCX__TCOS__SHIFT 24 -#define S5P_SROM_BCX__TACS__SHIFT 28 - -#endif /* __PLAT_SAMSUNG_REGS_SROM_H */ diff --git a/arch/arm/mach-exynos/suspend.c b/arch/arm/mach-exynos/suspend.c index fee2b003e662..f21690937b7d 100644 --- a/arch/arm/mach-exynos/suspend.c +++ b/arch/arm/mach-exynos/suspend.c @@ -34,10 +34,11 @@ #include #include +#include + #include #include "common.h" -#include "regs-srom.h" #define REG_TABLE_END (-1U) @@ -53,15 +54,6 @@ struct exynos_wkup_irq { u32 mask; }; -static struct sleep_save exynos_core_save[] = { - /* SROM side */ - SAVE_ITEM(S5P_SROM_BW), - SAVE_ITEM(S5P_SROM_BC0), - SAVE_ITEM(S5P_SROM_BC1), - SAVE_ITEM(S5P_SROM_BC2), - SAVE_ITEM(S5P_SROM_BC3), -}; - struct exynos_pm_data { const struct exynos_wkup_irq *wkup_irq; unsigned int wake_disable_mask; @@ -343,8 +335,6 @@ static void exynos_pm_prepare(void) /* Set wake-up mask registers */ exynos_pm_set_wakeup_mask(); - s3c_pm_do_save(exynos_core_save, ARRAY_SIZE(exynos_core_save)); - exynos_pm_enter_sleep_mode(); /* ensure at least INFORM0 has the resume address */ @@ -375,8 +365,6 @@ static void exynos5420_pm_prepare(void) /* Set wake-up mask registers */ exynos_pm_set_wakeup_mask(); - s3c_pm_do_save(exynos_core_save, ARRAY_SIZE(exynos_core_save)); - exynos_pmu_spare3 = pmu_raw_readl(S5P_PMU_SPARE3); /* * The cpu state needs to be saved and restored so that the @@ -467,8 +455,6 @@ static void exynos_pm_resume(void) /* For release retention */ exynos_pm_release_retention(); - s3c_pm_do_restore_core(exynos_core_save, ARRAY_SIZE(exynos_core_save)); - if (cpuid == ARM_CPU_PART_CORTEX_A9) scu_enable(S5P_VA_SCU); @@ -535,8 +521,6 @@ static void exynos5420_pm_resume(void) pmu_raw_writel(exynos_pmu_spare3, S5P_PMU_SPARE3); - s3c_pm_do_restore_core(exynos_core_save, ARRAY_SIZE(exynos_core_save)); - early_wakeup: tmp = pmu_raw_readl(EXYNOS5420_SFR_AXI_CGDIS1); diff --git a/arch/arm/plat-samsung/include/plat/map-s5p.h b/arch/arm/plat-samsung/include/plat/map-s5p.h index 4ec9a7050185..b63aeebb93f3 100644 --- a/arch/arm/plat-samsung/include/plat/map-s5p.h +++ b/arch/arm/plat-samsung/include/plat/map-s5p.h @@ -18,7 +18,6 @@ #define S5P_VA_DMC0 S3C_ADDR(0x02440000) #define S5P_VA_DMC1 S3C_ADDR(0x02480000) -#define S5P_VA_SROMC S3C_ADDR(0x024C0000) #define S5P_VA_COREPERI_BASE S3C_ADDR(0x02800000) #define S5P_VA_COREPERI(x) (S5P_VA_COREPERI_BASE + (x)) From 8ac2266d88318d348fa5f1dad5b525e0d2c665ef Mon Sep 17 00:00:00 2001 From: Pavel Fedin Date: Mon, 11 Apr 2016 13:12:27 +0530 Subject: [PATCH 6/6] memory: samsung: exynos-srom: Add support for bank configuration Implement handling properties in subnodes and adding child devices to the system. Child devices will not be added if configuration fails. Since the driver now does more than suspend-resume support, dependency on CONFIG_PM is removed. Signed-off-by: Pavel Fedin Reviewed-by: Krzysztof Kozlowski Signed-off-by: Pankaj Dubey Signed-off-by: Krzysztof Kozlowski --- arch/arm/mach-exynos/Kconfig | 2 +- drivers/memory/samsung/Kconfig | 2 +- drivers/memory/samsung/exynos-srom.c | 60 +++++++++++++++++++++++++++- 3 files changed, 60 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig index 28f992886d67..e65aa7d11b20 100644 --- a/arch/arm/mach-exynos/Kconfig +++ b/arch/arm/mach-exynos/Kconfig @@ -18,7 +18,7 @@ menuconfig ARCH_EXYNOS select COMMON_CLK_SAMSUNG select EXYNOS_THERMAL select EXYNOS_PMU - select EXYNOS_SROM if PM + select EXYNOS_SROM select HAVE_ARM_SCU if SMP select HAVE_S3C2410_I2C if I2C select HAVE_S3C2410_WATCHDOG if WATCHDOG diff --git a/drivers/memory/samsung/Kconfig b/drivers/memory/samsung/Kconfig index 64ab5dd9f626..9de12222061c 100644 --- a/drivers/memory/samsung/Kconfig +++ b/drivers/memory/samsung/Kconfig @@ -8,6 +8,6 @@ if SAMSUNG_MC config EXYNOS_SROM bool "Exynos SROM controller driver" if COMPILE_TEST - depends on (ARM && ARCH_EXYNOS && PM) || (COMPILE_TEST && HAS_IOMEM) + depends on (ARM && ARCH_EXYNOS) || (COMPILE_TEST && HAS_IOMEM) endif diff --git a/drivers/memory/samsung/exynos-srom.c b/drivers/memory/samsung/exynos-srom.c index 68e073c1651c..96756fb4d6bd 100644 --- a/drivers/memory/samsung/exynos-srom.c +++ b/drivers/memory/samsung/exynos-srom.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -67,11 +68,50 @@ static struct exynos_srom_reg_dump *exynos_srom_alloc_reg_dump( return rd; } +static int exynos_srom_configure_bank(struct exynos_srom *srom, + struct device_node *np) +{ + u32 bank, width, pmc = 0; + u32 timing[6]; + u32 cs, bw; + + if (of_property_read_u32(np, "reg", &bank)) + return -EINVAL; + if (of_property_read_u32(np, "reg-io-width", &width)) + width = 1; + if (of_property_read_bool(np, "samsung,srom-page-mode")) + pmc = 1 << EXYNOS_SROM_BCX__PMC__SHIFT; + if (of_property_read_u32_array(np, "samsung,srom-timing", timing, + ARRAY_SIZE(timing))) + return -EINVAL; + + bank *= 4; /* Convert bank into shift/offset */ + + cs = 1 << EXYNOS_SROM_BW__BYTEENABLE__SHIFT; + if (width == 2) + cs |= 1 << EXYNOS_SROM_BW__DATAWIDTH__SHIFT; + + bw = __raw_readl(srom->reg_base + EXYNOS_SROM_BW); + bw = (bw & ~(EXYNOS_SROM_BW__CS_MASK << bank)) | (cs << bank); + __raw_writel(bw, srom->reg_base + EXYNOS_SROM_BW); + + __raw_writel(pmc | (timing[0] << EXYNOS_SROM_BCX__TACP__SHIFT) | + (timing[1] << EXYNOS_SROM_BCX__TCAH__SHIFT) | + (timing[2] << EXYNOS_SROM_BCX__TCOH__SHIFT) | + (timing[3] << EXYNOS_SROM_BCX__TACC__SHIFT) | + (timing[4] << EXYNOS_SROM_BCX__TCOS__SHIFT) | + (timing[5] << EXYNOS_SROM_BCX__TACS__SHIFT), + srom->reg_base + EXYNOS_SROM_BC0 + bank); + + return 0; +} + static int exynos_srom_probe(struct platform_device *pdev) { - struct device_node *np; + struct device_node *np, *child; struct exynos_srom *srom; struct device *dev = &pdev->dev; + bool bad_bank_config = false; np = dev->of_node; if (!np) { @@ -100,7 +140,23 @@ static int exynos_srom_probe(struct platform_device *pdev) return -ENOMEM; } - return 0; + for_each_child_of_node(np, child) { + if (exynos_srom_configure_bank(srom, child)) { + dev_err(dev, + "Could not decode bank configuration for %s\n", + child->name); + bad_bank_config = true; + } + } + + /* + * If any bank failed to configure, we still provide suspend/resume, + * but do not probe child devices + */ + if (bad_bank_config) + return 0; + + return of_platform_populate(np, NULL, NULL, dev); } static int exynos_srom_remove(struct platform_device *pdev)