Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 <pankaj.dubey@samsung.com>
Reviewed-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
[p.fedin@samsung.com: tested on SMDK5410]
Tested-by: Pavel Fedin <p.fedin@samsung.com>
Signed-off-by: Kukjin Kim <kgene@kernel.org>
[k.kozlowski: Minor COMPILE_TEST adjustments in Kconfig entries]
Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>

authored by

Pankaj Dubey and committed by
Krzysztof Kozlowski
a8aabb91 92537d65

+242
+1
drivers/memory/Kconfig
··· 122 122 mainly help enable/disable iommu and control the power domain and 123 123 clocks for each local arbiter. 124 124 125 + source "drivers/memory/samsung/Kconfig" 125 126 source "drivers/memory/tegra/Kconfig" 126 127 127 128 endif
+1
drivers/memory/Makefile
··· 17 17 obj-$(CONFIG_JZ4780_NEMC) += jz4780-nemc.o 18 18 obj-$(CONFIG_MTK_SMI) += mtk-smi.o 19 19 20 + obj-$(CONFIG_SAMSUNG_MC) += samsung/ 20 21 obj-$(CONFIG_TEGRA_MC) += tegra/
+13
drivers/memory/samsung/Kconfig
··· 1 + config SAMSUNG_MC 2 + bool "Samsung Exynos Memory Controller support" if COMPILE_TEST 3 + help 4 + Support for the Memory Controller (MC) devices found on 5 + Samsung Exynos SoCs. 6 + 7 + if SAMSUNG_MC 8 + 9 + config EXYNOS_SROM 10 + bool "Exynos SROM controller driver" if COMPILE_TEST 11 + depends on (ARM && ARCH_EXYNOS && PM) || (COMPILE_TEST && HAS_IOMEM) 12 + 13 + endif
+1
drivers/memory/samsung/Makefile
··· 1 + obj-$(CONFIG_EXYNOS_SROM) += exynos-srom.o
+175
drivers/memory/samsung/exynos-srom.c
··· 1 + /* 2 + * Copyright (c) 2015 Samsung Electronics Co., Ltd. 3 + * http://www.samsung.com/ 4 + * 5 + * EXYNOS - SROM Controller support 6 + * Author: Pankaj Dubey <pankaj.dubey@samsung.com> 7 + * 8 + * This program is free software; you can redistribute it and/or modify 9 + * it under the terms of the GNU General Public License version 2 as 10 + * published by the Free Software Foundation. 11 + */ 12 + 13 + #include <linux/io.h> 14 + #include <linux/module.h> 15 + #include <linux/of.h> 16 + #include <linux/of_address.h> 17 + #include <linux/platform_device.h> 18 + #include <linux/slab.h> 19 + 20 + #include "exynos-srom.h" 21 + 22 + static const unsigned long exynos_srom_offsets[] = { 23 + /* SROM side */ 24 + EXYNOS_SROM_BW, 25 + EXYNOS_SROM_BC0, 26 + EXYNOS_SROM_BC1, 27 + EXYNOS_SROM_BC2, 28 + EXYNOS_SROM_BC3, 29 + }; 30 + 31 + /** 32 + * struct exynos_srom_reg_dump: register dump of SROM Controller registers. 33 + * @offset: srom register offset from the controller base address. 34 + * @value: the value of register under the offset. 35 + */ 36 + struct exynos_srom_reg_dump { 37 + u32 offset; 38 + u32 value; 39 + }; 40 + 41 + /** 42 + * struct exynos_srom: platform data for exynos srom controller driver. 43 + * @dev: platform device pointer 44 + * @reg_base: srom base address 45 + * @reg_offset: exynos_srom_reg_dump pointer to hold offset and its value. 46 + */ 47 + struct exynos_srom { 48 + struct device *dev; 49 + void __iomem *reg_base; 50 + struct exynos_srom_reg_dump *reg_offset; 51 + }; 52 + 53 + static struct exynos_srom_reg_dump *exynos_srom_alloc_reg_dump( 54 + const unsigned long *rdump, 55 + unsigned long nr_rdump) 56 + { 57 + struct exynos_srom_reg_dump *rd; 58 + unsigned int i; 59 + 60 + rd = kcalloc(nr_rdump, sizeof(*rd), GFP_KERNEL); 61 + if (!rd) 62 + return NULL; 63 + 64 + for (i = 0; i < nr_rdump; ++i) 65 + rd[i].offset = rdump[i]; 66 + 67 + return rd; 68 + } 69 + 70 + static int exynos_srom_probe(struct platform_device *pdev) 71 + { 72 + struct device_node *np; 73 + struct exynos_srom *srom; 74 + struct device *dev = &pdev->dev; 75 + 76 + np = dev->of_node; 77 + if (!np) { 78 + dev_err(&pdev->dev, "could not find device info\n"); 79 + return -EINVAL; 80 + } 81 + 82 + srom = devm_kzalloc(&pdev->dev, 83 + sizeof(struct exynos_srom), GFP_KERNEL); 84 + if (!srom) 85 + return -ENOMEM; 86 + 87 + srom->dev = dev; 88 + srom->reg_base = of_iomap(np, 0); 89 + if (!srom->reg_base) { 90 + dev_err(&pdev->dev, "iomap of exynos srom controller failed\n"); 91 + return -ENOMEM; 92 + } 93 + 94 + platform_set_drvdata(pdev, srom); 95 + 96 + srom->reg_offset = exynos_srom_alloc_reg_dump(exynos_srom_offsets, 97 + sizeof(exynos_srom_offsets)); 98 + if (!srom->reg_offset) { 99 + iounmap(srom->reg_base); 100 + return -ENOMEM; 101 + } 102 + 103 + return 0; 104 + } 105 + 106 + static int exynos_srom_remove(struct platform_device *pdev) 107 + { 108 + struct exynos_srom *srom = platform_get_drvdata(pdev); 109 + 110 + kfree(srom->reg_offset); 111 + iounmap(srom->reg_base); 112 + 113 + return 0; 114 + } 115 + 116 + #ifdef CONFIG_PM_SLEEP 117 + static void exynos_srom_save(void __iomem *base, 118 + struct exynos_srom_reg_dump *rd, 119 + unsigned int num_regs) 120 + { 121 + for (; num_regs > 0; --num_regs, ++rd) 122 + rd->value = readl(base + rd->offset); 123 + } 124 + 125 + static void exynos_srom_restore(void __iomem *base, 126 + const struct exynos_srom_reg_dump *rd, 127 + unsigned int num_regs) 128 + { 129 + for (; num_regs > 0; --num_regs, ++rd) 130 + writel(rd->value, base + rd->offset); 131 + } 132 + 133 + static int exynos_srom_suspend(struct device *dev) 134 + { 135 + struct exynos_srom *srom = dev_get_drvdata(dev); 136 + 137 + exynos_srom_save(srom->reg_base, srom->reg_offset, 138 + ARRAY_SIZE(exynos_srom_offsets)); 139 + return 0; 140 + } 141 + 142 + static int exynos_srom_resume(struct device *dev) 143 + { 144 + struct exynos_srom *srom = dev_get_drvdata(dev); 145 + 146 + exynos_srom_restore(srom->reg_base, srom->reg_offset, 147 + ARRAY_SIZE(exynos_srom_offsets)); 148 + return 0; 149 + } 150 + #endif 151 + 152 + static const struct of_device_id of_exynos_srom_ids[] = { 153 + { 154 + .compatible = "samsung,exynos4210-srom", 155 + }, 156 + {}, 157 + }; 158 + MODULE_DEVICE_TABLE(of, of_exynos_srom_ids); 159 + 160 + static SIMPLE_DEV_PM_OPS(exynos_srom_pm_ops, exynos_srom_suspend, exynos_srom_resume); 161 + 162 + static struct platform_driver exynos_srom_driver = { 163 + .probe = exynos_srom_probe, 164 + .remove = exynos_srom_remove, 165 + .driver = { 166 + .name = "exynos-srom", 167 + .of_match_table = of_exynos_srom_ids, 168 + .pm = &exynos_srom_pm_ops, 169 + }, 170 + }; 171 + module_platform_driver(exynos_srom_driver); 172 + 173 + MODULE_AUTHOR("Pankaj Dubey <pankaj.dubey@samsung.com>"); 174 + MODULE_DESCRIPTION("Exynos SROM Controller Driver"); 175 + MODULE_LICENSE("GPL");
+51
drivers/memory/samsung/exynos-srom.h
··· 1 + /* 2 + * Copyright (c) 2015 Samsung Electronics Co., Ltd. 3 + * http://www.samsung.com 4 + * 5 + * Exynos SROMC register definitions 6 + * 7 + * This program is free software; you can redistribute it and/or modify 8 + * it under the terms of the GNU General Public License version 2 as 9 + * published by the Free Software Foundation. 10 + */ 11 + 12 + #ifndef __EXYNOS_SROM_H 13 + #define __EXYNOS_SROM_H __FILE__ 14 + 15 + #define EXYNOS_SROMREG(x) (x) 16 + 17 + #define EXYNOS_SROM_BW EXYNOS_SROMREG(0x0) 18 + #define EXYNOS_SROM_BC0 EXYNOS_SROMREG(0x4) 19 + #define EXYNOS_SROM_BC1 EXYNOS_SROMREG(0x8) 20 + #define EXYNOS_SROM_BC2 EXYNOS_SROMREG(0xc) 21 + #define EXYNOS_SROM_BC3 EXYNOS_SROMREG(0x10) 22 + #define EXYNOS_SROM_BC4 EXYNOS_SROMREG(0x14) 23 + #define EXYNOS_SROM_BC5 EXYNOS_SROMREG(0x18) 24 + 25 + /* one register BW holds 4 x 4-bit packed settings for NCS0 - NCS3 */ 26 + 27 + #define EXYNOS_SROM_BW__DATAWIDTH__SHIFT 0 28 + #define EXYNOS_SROM_BW__ADDRMODE__SHIFT 1 29 + #define EXYNOS_SROM_BW__WAITENABLE__SHIFT 2 30 + #define EXYNOS_SROM_BW__BYTEENABLE__SHIFT 3 31 + 32 + #define EXYNOS_SROM_BW__CS_MASK 0xf 33 + 34 + #define EXYNOS_SROM_BW__NCS0__SHIFT 0 35 + #define EXYNOS_SROM_BW__NCS1__SHIFT 4 36 + #define EXYNOS_SROM_BW__NCS2__SHIFT 8 37 + #define EXYNOS_SROM_BW__NCS3__SHIFT 12 38 + #define EXYNOS_SROM_BW__NCS4__SHIFT 16 39 + #define EXYNOS_SROM_BW__NCS5__SHIFT 20 40 + 41 + /* applies to same to BCS0 - BCS3 */ 42 + 43 + #define EXYNOS_SROM_BCX__PMC__SHIFT 0 44 + #define EXYNOS_SROM_BCX__TACP__SHIFT 4 45 + #define EXYNOS_SROM_BCX__TCAH__SHIFT 8 46 + #define EXYNOS_SROM_BCX__TCOH__SHIFT 12 47 + #define EXYNOS_SROM_BCX__TACC__SHIFT 16 48 + #define EXYNOS_SROM_BCX__TCOS__SHIFT 24 49 + #define EXYNOS_SROM_BCX__TACS__SHIFT 28 50 + 51 + #endif /* __EXYNOS_SROM_H */