2 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
3 * http://www.samsung.com/
5 * EXYNOS - SROM Controller support
6 * Author: Pankaj Dubey <pankaj.dubey@samsung.com>
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.
14 #include <linux/module.h>
16 #include <linux/of_address.h>
17 #include <linux/platform_device.h>
18 #include <linux/slab.h>
20 #include "exynos-srom.h"
22 static const unsigned long exynos_srom_offsets[] = {
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.
36 struct exynos_srom_reg_dump {
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.
49 void __iomem *reg_base;
50 struct exynos_srom_reg_dump *reg_offset;
53 static struct exynos_srom_reg_dump *exynos_srom_alloc_reg_dump(
54 const unsigned long *rdump,
55 unsigned long nr_rdump)
57 struct exynos_srom_reg_dump *rd;
60 rd = kcalloc(nr_rdump, sizeof(*rd), GFP_KERNEL);
64 for (i = 0; i < nr_rdump; ++i)
65 rd[i].offset = rdump[i];
70 static int exynos_srom_probe(struct platform_device *pdev)
72 struct device_node *np;
73 struct exynos_srom *srom;
74 struct device *dev = &pdev->dev;
78 dev_err(&pdev->dev, "could not find device info\n");
82 srom = devm_kzalloc(&pdev->dev,
83 sizeof(struct exynos_srom), GFP_KERNEL);
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");
94 platform_set_drvdata(pdev, srom);
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);
106 static int exynos_srom_remove(struct platform_device *pdev)
108 struct exynos_srom *srom = platform_get_drvdata(pdev);
110 kfree(srom->reg_offset);
111 iounmap(srom->reg_base);
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)
121 for (; num_regs > 0; --num_regs, ++rd)
122 rd->value = readl(base + rd->offset);
125 static void exynos_srom_restore(void __iomem *base,
126 const struct exynos_srom_reg_dump *rd,
127 unsigned int num_regs)
129 for (; num_regs > 0; --num_regs, ++rd)
130 writel(rd->value, base + rd->offset);
133 static int exynos_srom_suspend(struct device *dev)
135 struct exynos_srom *srom = dev_get_drvdata(dev);
137 exynos_srom_save(srom->reg_base, srom->reg_offset,
138 ARRAY_SIZE(exynos_srom_offsets));
142 static int exynos_srom_resume(struct device *dev)
144 struct exynos_srom *srom = dev_get_drvdata(dev);
146 exynos_srom_restore(srom->reg_base, srom->reg_offset,
147 ARRAY_SIZE(exynos_srom_offsets));
152 static const struct of_device_id of_exynos_srom_ids[] = {
154 .compatible = "samsung,exynos-srom",
158 MODULE_DEVICE_TABLE(of, of_exynos_srom_ids);
160 static SIMPLE_DEV_PM_OPS(exynos_srom_pm_ops, exynos_srom_suspend, exynos_srom_resume);
162 static struct platform_driver exynos_srom_driver = {
163 .probe = exynos_srom_probe,
164 .remove = exynos_srom_remove,
166 .name = "exynos-srom",
167 .of_match_table = of_exynos_srom_ids,
168 .pm = &exynos_srom_pm_ops,
171 module_platform_driver(exynos_srom_driver);
173 MODULE_AUTHOR("Pankaj Dubey <pankaj.dubey@samsung.com>");
174 MODULE_DESCRIPTION("Exynos SROM Controller Driver");
175 MODULE_LICENSE("GPL");