1 // SPDX-License-Identifier: GPL-2.0
3 // Copyright (c) 2015 Samsung Electronics Co., Ltd.
4 // http://www.samsung.com/
6 // Exynos - SROM Controller support
7 // Author: Pankaj Dubey <pankaj.dubey@samsung.com>
10 #include <linux/init.h>
12 #include <linux/of_address.h>
13 #include <linux/of_platform.h>
14 #include <linux/platform_device.h>
15 #include <linux/slab.h>
17 #include "exynos-srom.h"
19 static const unsigned long exynos_srom_offsets
[] = {
29 * struct exynos_srom_reg_dump: register dump of SROM Controller registers.
30 * @offset: srom register offset from the controller base address.
31 * @value: the value of register under the offset.
33 struct exynos_srom_reg_dump
{
39 * struct exynos_srom: platform data for exynos srom controller driver.
40 * @dev: platform device pointer
41 * @reg_base: srom base address
42 * @reg_offset: exynos_srom_reg_dump pointer to hold offset and its value.
46 void __iomem
*reg_base
;
47 struct exynos_srom_reg_dump
*reg_offset
;
50 static struct exynos_srom_reg_dump
*
51 exynos_srom_alloc_reg_dump(const unsigned long *rdump
,
52 unsigned long nr_rdump
)
54 struct exynos_srom_reg_dump
*rd
;
57 rd
= kcalloc(nr_rdump
, sizeof(*rd
), GFP_KERNEL
);
61 for (i
= 0; i
< nr_rdump
; ++i
)
62 rd
[i
].offset
= rdump
[i
];
67 static int exynos_srom_configure_bank(struct exynos_srom
*srom
,
68 struct device_node
*np
)
70 u32 bank
, width
, pmc
= 0;
74 if (of_property_read_u32(np
, "reg", &bank
))
76 if (of_property_read_u32(np
, "reg-io-width", &width
))
78 if (of_property_read_bool(np
, "samsung,srom-page-mode"))
79 pmc
= 1 << EXYNOS_SROM_BCX__PMC__SHIFT
;
80 if (of_property_read_u32_array(np
, "samsung,srom-timing", timing
,
84 bank
*= 4; /* Convert bank into shift/offset */
86 cs
= 1 << EXYNOS_SROM_BW__BYTEENABLE__SHIFT
;
88 cs
|= 1 << EXYNOS_SROM_BW__DATAWIDTH__SHIFT
;
90 bw
= readl_relaxed(srom
->reg_base
+ EXYNOS_SROM_BW
);
91 bw
= (bw
& ~(EXYNOS_SROM_BW__CS_MASK
<< bank
)) | (cs
<< bank
);
92 writel_relaxed(bw
, srom
->reg_base
+ EXYNOS_SROM_BW
);
94 writel_relaxed(pmc
| (timing
[0] << EXYNOS_SROM_BCX__TACP__SHIFT
) |
95 (timing
[1] << EXYNOS_SROM_BCX__TCAH__SHIFT
) |
96 (timing
[2] << EXYNOS_SROM_BCX__TCOH__SHIFT
) |
97 (timing
[3] << EXYNOS_SROM_BCX__TACC__SHIFT
) |
98 (timing
[4] << EXYNOS_SROM_BCX__TCOS__SHIFT
) |
99 (timing
[5] << EXYNOS_SROM_BCX__TACS__SHIFT
),
100 srom
->reg_base
+ EXYNOS_SROM_BC0
+ bank
);
105 static int exynos_srom_probe(struct platform_device
*pdev
)
107 struct device_node
*np
, *child
;
108 struct exynos_srom
*srom
;
109 struct device
*dev
= &pdev
->dev
;
110 bool bad_bank_config
= false;
114 dev_err(&pdev
->dev
, "could not find device info\n");
118 srom
= devm_kzalloc(&pdev
->dev
,
119 sizeof(struct exynos_srom
), GFP_KERNEL
);
124 srom
->reg_base
= of_iomap(np
, 0);
125 if (!srom
->reg_base
) {
126 dev_err(&pdev
->dev
, "iomap of exynos srom controller failed\n");
130 platform_set_drvdata(pdev
, srom
);
132 srom
->reg_offset
= exynos_srom_alloc_reg_dump(exynos_srom_offsets
,
133 ARRAY_SIZE(exynos_srom_offsets
));
134 if (!srom
->reg_offset
) {
135 iounmap(srom
->reg_base
);
139 for_each_child_of_node(np
, child
) {
140 if (exynos_srom_configure_bank(srom
, child
)) {
142 "Could not decode bank configuration for %pOFn\n",
144 bad_bank_config
= true;
149 * If any bank failed to configure, we still provide suspend/resume,
150 * but do not probe child devices
155 return of_platform_populate(np
, NULL
, NULL
, dev
);
158 #ifdef CONFIG_PM_SLEEP
159 static void exynos_srom_save(void __iomem
*base
,
160 struct exynos_srom_reg_dump
*rd
,
161 unsigned int num_regs
)
163 for (; num_regs
> 0; --num_regs
, ++rd
)
164 rd
->value
= readl(base
+ rd
->offset
);
167 static void exynos_srom_restore(void __iomem
*base
,
168 const struct exynos_srom_reg_dump
*rd
,
169 unsigned int num_regs
)
171 for (; num_regs
> 0; --num_regs
, ++rd
)
172 writel(rd
->value
, base
+ rd
->offset
);
175 static int exynos_srom_suspend(struct device
*dev
)
177 struct exynos_srom
*srom
= dev_get_drvdata(dev
);
179 exynos_srom_save(srom
->reg_base
, srom
->reg_offset
,
180 ARRAY_SIZE(exynos_srom_offsets
));
184 static int exynos_srom_resume(struct device
*dev
)
186 struct exynos_srom
*srom
= dev_get_drvdata(dev
);
188 exynos_srom_restore(srom
->reg_base
, srom
->reg_offset
,
189 ARRAY_SIZE(exynos_srom_offsets
));
194 static const struct of_device_id of_exynos_srom_ids
[] = {
196 .compatible
= "samsung,exynos4210-srom",
201 static SIMPLE_DEV_PM_OPS(exynos_srom_pm_ops
, exynos_srom_suspend
, exynos_srom_resume
);
203 static struct platform_driver exynos_srom_driver
= {
204 .probe
= exynos_srom_probe
,
206 .name
= "exynos-srom",
207 .of_match_table
= of_exynos_srom_ids
,
208 .pm
= &exynos_srom_pm_ops
,
209 .suppress_bind_attrs
= true,
212 builtin_platform_driver(exynos_srom_driver
);