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/init.h>
16 #include <linux/of_address.h>
17 #include <linux/of_platform.h>
18 #include <linux/platform_device.h>
19 #include <linux/slab.h>
21 #include "exynos-srom.h"
23 static const unsigned long exynos_srom_offsets
[] = {
33 * struct exynos_srom_reg_dump: register dump of SROM Controller registers.
34 * @offset: srom register offset from the controller base address.
35 * @value: the value of register under the offset.
37 struct exynos_srom_reg_dump
{
43 * struct exynos_srom: platform data for exynos srom controller driver.
44 * @dev: platform device pointer
45 * @reg_base: srom base address
46 * @reg_offset: exynos_srom_reg_dump pointer to hold offset and its value.
50 void __iomem
*reg_base
;
51 struct exynos_srom_reg_dump
*reg_offset
;
54 static struct exynos_srom_reg_dump
*exynos_srom_alloc_reg_dump(
55 const unsigned long *rdump
,
56 unsigned long nr_rdump
)
58 struct exynos_srom_reg_dump
*rd
;
61 rd
= kcalloc(nr_rdump
, sizeof(*rd
), GFP_KERNEL
);
65 for (i
= 0; i
< nr_rdump
; ++i
)
66 rd
[i
].offset
= rdump
[i
];
71 static int exynos_srom_configure_bank(struct exynos_srom
*srom
,
72 struct device_node
*np
)
74 u32 bank
, width
, pmc
= 0;
78 if (of_property_read_u32(np
, "reg", &bank
))
80 if (of_property_read_u32(np
, "reg-io-width", &width
))
82 if (of_property_read_bool(np
, "samsung,srom-page-mode"))
83 pmc
= 1 << EXYNOS_SROM_BCX__PMC__SHIFT
;
84 if (of_property_read_u32_array(np
, "samsung,srom-timing", timing
,
88 bank
*= 4; /* Convert bank into shift/offset */
90 cs
= 1 << EXYNOS_SROM_BW__BYTEENABLE__SHIFT
;
92 cs
|= 1 << EXYNOS_SROM_BW__DATAWIDTH__SHIFT
;
94 bw
= readl_relaxed(srom
->reg_base
+ EXYNOS_SROM_BW
);
95 bw
= (bw
& ~(EXYNOS_SROM_BW__CS_MASK
<< bank
)) | (cs
<< bank
);
96 writel_relaxed(bw
, srom
->reg_base
+ EXYNOS_SROM_BW
);
98 writel_relaxed(pmc
| (timing
[0] << EXYNOS_SROM_BCX__TACP__SHIFT
) |
99 (timing
[1] << EXYNOS_SROM_BCX__TCAH__SHIFT
) |
100 (timing
[2] << EXYNOS_SROM_BCX__TCOH__SHIFT
) |
101 (timing
[3] << EXYNOS_SROM_BCX__TACC__SHIFT
) |
102 (timing
[4] << EXYNOS_SROM_BCX__TCOS__SHIFT
) |
103 (timing
[5] << EXYNOS_SROM_BCX__TACS__SHIFT
),
104 srom
->reg_base
+ EXYNOS_SROM_BC0
+ bank
);
109 static int exynos_srom_probe(struct platform_device
*pdev
)
111 struct device_node
*np
, *child
;
112 struct exynos_srom
*srom
;
113 struct device
*dev
= &pdev
->dev
;
114 bool bad_bank_config
= false;
118 dev_err(&pdev
->dev
, "could not find device info\n");
122 srom
= devm_kzalloc(&pdev
->dev
,
123 sizeof(struct exynos_srom
), GFP_KERNEL
);
128 srom
->reg_base
= of_iomap(np
, 0);
129 if (!srom
->reg_base
) {
130 dev_err(&pdev
->dev
, "iomap of exynos srom controller failed\n");
134 platform_set_drvdata(pdev
, srom
);
136 srom
->reg_offset
= exynos_srom_alloc_reg_dump(exynos_srom_offsets
,
137 ARRAY_SIZE(exynos_srom_offsets
));
138 if (!srom
->reg_offset
) {
139 iounmap(srom
->reg_base
);
143 for_each_child_of_node(np
, child
) {
144 if (exynos_srom_configure_bank(srom
, child
)) {
146 "Could not decode bank configuration for %s\n",
148 bad_bank_config
= true;
153 * If any bank failed to configure, we still provide suspend/resume,
154 * but do not probe child devices
159 return of_platform_populate(np
, NULL
, NULL
, dev
);
162 #ifdef CONFIG_PM_SLEEP
163 static void exynos_srom_save(void __iomem
*base
,
164 struct exynos_srom_reg_dump
*rd
,
165 unsigned int num_regs
)
167 for (; num_regs
> 0; --num_regs
, ++rd
)
168 rd
->value
= readl(base
+ rd
->offset
);
171 static void exynos_srom_restore(void __iomem
*base
,
172 const struct exynos_srom_reg_dump
*rd
,
173 unsigned int num_regs
)
175 for (; num_regs
> 0; --num_regs
, ++rd
)
176 writel(rd
->value
, base
+ rd
->offset
);
179 static int exynos_srom_suspend(struct device
*dev
)
181 struct exynos_srom
*srom
= dev_get_drvdata(dev
);
183 exynos_srom_save(srom
->reg_base
, srom
->reg_offset
,
184 ARRAY_SIZE(exynos_srom_offsets
));
188 static int exynos_srom_resume(struct device
*dev
)
190 struct exynos_srom
*srom
= dev_get_drvdata(dev
);
192 exynos_srom_restore(srom
->reg_base
, srom
->reg_offset
,
193 ARRAY_SIZE(exynos_srom_offsets
));
198 static const struct of_device_id of_exynos_srom_ids
[] = {
200 .compatible
= "samsung,exynos4210-srom",
205 static SIMPLE_DEV_PM_OPS(exynos_srom_pm_ops
, exynos_srom_suspend
, exynos_srom_resume
);
207 static struct platform_driver exynos_srom_driver
= {
208 .probe
= exynos_srom_probe
,
210 .name
= "exynos-srom",
211 .of_match_table
= of_exynos_srom_ids
,
212 .pm
= &exynos_srom_pm_ops
,
213 .suppress_bind_attrs
= true,
216 builtin_platform_driver(exynos_srom_driver
);