0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/io.h>
0010 #include <linux/init.h>
0011 #include <linux/of.h>
0012 #include <linux/of_address.h>
0013 #include <linux/of_platform.h>
0014 #include <linux/platform_device.h>
0015 #include <linux/slab.h>
0016
0017 #include "exynos-srom.h"
0018
0019 static const unsigned long exynos_srom_offsets[] = {
0020
0021 EXYNOS_SROM_BW,
0022 EXYNOS_SROM_BC0,
0023 EXYNOS_SROM_BC1,
0024 EXYNOS_SROM_BC2,
0025 EXYNOS_SROM_BC3,
0026 };
0027
0028
0029
0030
0031
0032
0033 struct exynos_srom_reg_dump {
0034 u32 offset;
0035 u32 value;
0036 };
0037
0038
0039
0040
0041
0042
0043
0044 struct exynos_srom {
0045 struct device *dev;
0046 void __iomem *reg_base;
0047 struct exynos_srom_reg_dump *reg_offset;
0048 };
0049
0050 static struct exynos_srom_reg_dump *
0051 exynos_srom_alloc_reg_dump(const unsigned long *rdump,
0052 unsigned long nr_rdump)
0053 {
0054 struct exynos_srom_reg_dump *rd;
0055 unsigned int i;
0056
0057 rd = kcalloc(nr_rdump, sizeof(*rd), GFP_KERNEL);
0058 if (!rd)
0059 return NULL;
0060
0061 for (i = 0; i < nr_rdump; ++i)
0062 rd[i].offset = rdump[i];
0063
0064 return rd;
0065 }
0066
0067 static int exynos_srom_configure_bank(struct exynos_srom *srom,
0068 struct device_node *np)
0069 {
0070 u32 bank, width, pmc = 0;
0071 u32 timing[6];
0072 u32 cs, bw;
0073
0074 if (of_property_read_u32(np, "reg", &bank))
0075 return -EINVAL;
0076 if (of_property_read_u32(np, "reg-io-width", &width))
0077 width = 1;
0078 if (of_property_read_bool(np, "samsung,srom-page-mode"))
0079 pmc = 1 << EXYNOS_SROM_BCX__PMC__SHIFT;
0080 if (of_property_read_u32_array(np, "samsung,srom-timing", timing,
0081 ARRAY_SIZE(timing)))
0082 return -EINVAL;
0083
0084 bank *= 4;
0085
0086 cs = 1 << EXYNOS_SROM_BW__BYTEENABLE__SHIFT;
0087 if (width == 2)
0088 cs |= 1 << EXYNOS_SROM_BW__DATAWIDTH__SHIFT;
0089
0090 bw = readl_relaxed(srom->reg_base + EXYNOS_SROM_BW);
0091 bw = (bw & ~(EXYNOS_SROM_BW__CS_MASK << bank)) | (cs << bank);
0092 writel_relaxed(bw, srom->reg_base + EXYNOS_SROM_BW);
0093
0094 writel_relaxed(pmc | (timing[0] << EXYNOS_SROM_BCX__TACP__SHIFT) |
0095 (timing[1] << EXYNOS_SROM_BCX__TCAH__SHIFT) |
0096 (timing[2] << EXYNOS_SROM_BCX__TCOH__SHIFT) |
0097 (timing[3] << EXYNOS_SROM_BCX__TACC__SHIFT) |
0098 (timing[4] << EXYNOS_SROM_BCX__TCOS__SHIFT) |
0099 (timing[5] << EXYNOS_SROM_BCX__TACS__SHIFT),
0100 srom->reg_base + EXYNOS_SROM_BC0 + bank);
0101
0102 return 0;
0103 }
0104
0105 static int exynos_srom_probe(struct platform_device *pdev)
0106 {
0107 struct device_node *np, *child;
0108 struct exynos_srom *srom;
0109 struct device *dev = &pdev->dev;
0110 bool bad_bank_config = false;
0111
0112 np = dev->of_node;
0113 if (!np) {
0114 dev_err(&pdev->dev, "could not find device info\n");
0115 return -EINVAL;
0116 }
0117
0118 srom = devm_kzalloc(&pdev->dev,
0119 sizeof(struct exynos_srom), GFP_KERNEL);
0120 if (!srom)
0121 return -ENOMEM;
0122
0123 srom->dev = dev;
0124 srom->reg_base = of_iomap(np, 0);
0125 if (!srom->reg_base) {
0126 dev_err(&pdev->dev, "iomap of exynos srom controller failed\n");
0127 return -ENOMEM;
0128 }
0129
0130 platform_set_drvdata(pdev, srom);
0131
0132 srom->reg_offset = exynos_srom_alloc_reg_dump(exynos_srom_offsets,
0133 ARRAY_SIZE(exynos_srom_offsets));
0134 if (!srom->reg_offset) {
0135 iounmap(srom->reg_base);
0136 return -ENOMEM;
0137 }
0138
0139 for_each_child_of_node(np, child) {
0140 if (exynos_srom_configure_bank(srom, child)) {
0141 dev_err(dev,
0142 "Could not decode bank configuration for %pOFn\n",
0143 child);
0144 bad_bank_config = true;
0145 }
0146 }
0147
0148
0149
0150
0151
0152 if (bad_bank_config)
0153 return 0;
0154
0155 return of_platform_populate(np, NULL, NULL, dev);
0156 }
0157
0158 #ifdef CONFIG_PM_SLEEP
0159 static void exynos_srom_save(void __iomem *base,
0160 struct exynos_srom_reg_dump *rd,
0161 unsigned int num_regs)
0162 {
0163 for (; num_regs > 0; --num_regs, ++rd)
0164 rd->value = readl(base + rd->offset);
0165 }
0166
0167 static void exynos_srom_restore(void __iomem *base,
0168 const struct exynos_srom_reg_dump *rd,
0169 unsigned int num_regs)
0170 {
0171 for (; num_regs > 0; --num_regs, ++rd)
0172 writel(rd->value, base + rd->offset);
0173 }
0174
0175 static int exynos_srom_suspend(struct device *dev)
0176 {
0177 struct exynos_srom *srom = dev_get_drvdata(dev);
0178
0179 exynos_srom_save(srom->reg_base, srom->reg_offset,
0180 ARRAY_SIZE(exynos_srom_offsets));
0181 return 0;
0182 }
0183
0184 static int exynos_srom_resume(struct device *dev)
0185 {
0186 struct exynos_srom *srom = dev_get_drvdata(dev);
0187
0188 exynos_srom_restore(srom->reg_base, srom->reg_offset,
0189 ARRAY_SIZE(exynos_srom_offsets));
0190 return 0;
0191 }
0192 #endif
0193
0194 static const struct of_device_id of_exynos_srom_ids[] = {
0195 {
0196 .compatible = "samsung,exynos4210-srom",
0197 },
0198 {},
0199 };
0200
0201 static SIMPLE_DEV_PM_OPS(exynos_srom_pm_ops, exynos_srom_suspend, exynos_srom_resume);
0202
0203 static struct platform_driver exynos_srom_driver = {
0204 .probe = exynos_srom_probe,
0205 .driver = {
0206 .name = "exynos-srom",
0207 .of_match_table = of_exynos_srom_ids,
0208 .pm = &exynos_srom_pm_ops,
0209 .suppress_bind_attrs = true,
0210 },
0211 };
0212 builtin_platform_driver(exynos_srom_driver);