exynos-srom.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  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. #include <linux/io.h>
  13. #include <linux/init.h>
  14. #include <linux/of.h>
  15. #include <linux/of_address.h>
  16. #include <linux/of_platform.h>
  17. #include <linux/platform_device.h>
  18. #include <linux/slab.h>
  19. #include "exynos-srom.h"
  20. static const unsigned long exynos_srom_offsets[] = {
  21. /* SROM side */
  22. EXYNOS_SROM_BW,
  23. EXYNOS_SROM_BC0,
  24. EXYNOS_SROM_BC1,
  25. EXYNOS_SROM_BC2,
  26. EXYNOS_SROM_BC3,
  27. };
  28. /**
  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.
  32. */
  33. struct exynos_srom_reg_dump {
  34. u32 offset;
  35. u32 value;
  36. };
  37. /**
  38. * struct exynos_srom: platform data for exynos srom controller driver.
  39. * @dev: platform device pointer
  40. * @reg_base: srom base address
  41. * @reg_offset: exynos_srom_reg_dump pointer to hold offset and its value.
  42. */
  43. struct exynos_srom {
  44. struct device *dev;
  45. void __iomem *reg_base;
  46. struct exynos_srom_reg_dump *reg_offset;
  47. };
  48. static struct exynos_srom_reg_dump *exynos_srom_alloc_reg_dump(
  49. const unsigned long *rdump,
  50. unsigned long nr_rdump)
  51. {
  52. struct exynos_srom_reg_dump *rd;
  53. unsigned int i;
  54. rd = kcalloc(nr_rdump, sizeof(*rd), GFP_KERNEL);
  55. if (!rd)
  56. return NULL;
  57. for (i = 0; i < nr_rdump; ++i)
  58. rd[i].offset = rdump[i];
  59. return rd;
  60. }
  61. static int exynos_srom_configure_bank(struct exynos_srom *srom,
  62. struct device_node *np)
  63. {
  64. u32 bank, width, pmc = 0;
  65. u32 timing[6];
  66. u32 cs, bw;
  67. if (of_property_read_u32(np, "reg", &bank))
  68. return -EINVAL;
  69. if (of_property_read_u32(np, "reg-io-width", &width))
  70. width = 1;
  71. if (of_property_read_bool(np, "samsung,srom-page-mode"))
  72. pmc = 1 << EXYNOS_SROM_BCX__PMC__SHIFT;
  73. if (of_property_read_u32_array(np, "samsung,srom-timing", timing,
  74. ARRAY_SIZE(timing)))
  75. return -EINVAL;
  76. bank *= 4; /* Convert bank into shift/offset */
  77. cs = 1 << EXYNOS_SROM_BW__BYTEENABLE__SHIFT;
  78. if (width == 2)
  79. cs |= 1 << EXYNOS_SROM_BW__DATAWIDTH__SHIFT;
  80. bw = readl_relaxed(srom->reg_base + EXYNOS_SROM_BW);
  81. bw = (bw & ~(EXYNOS_SROM_BW__CS_MASK << bank)) | (cs << bank);
  82. writel_relaxed(bw, srom->reg_base + EXYNOS_SROM_BW);
  83. writel_relaxed(pmc | (timing[0] << EXYNOS_SROM_BCX__TACP__SHIFT) |
  84. (timing[1] << EXYNOS_SROM_BCX__TCAH__SHIFT) |
  85. (timing[2] << EXYNOS_SROM_BCX__TCOH__SHIFT) |
  86. (timing[3] << EXYNOS_SROM_BCX__TACC__SHIFT) |
  87. (timing[4] << EXYNOS_SROM_BCX__TCOS__SHIFT) |
  88. (timing[5] << EXYNOS_SROM_BCX__TACS__SHIFT),
  89. srom->reg_base + EXYNOS_SROM_BC0 + bank);
  90. return 0;
  91. }
  92. static int exynos_srom_probe(struct platform_device *pdev)
  93. {
  94. struct device_node *np, *child;
  95. struct exynos_srom *srom;
  96. struct device *dev = &pdev->dev;
  97. bool bad_bank_config = false;
  98. np = dev->of_node;
  99. if (!np) {
  100. dev_err(&pdev->dev, "could not find device info\n");
  101. return -EINVAL;
  102. }
  103. srom = devm_kzalloc(&pdev->dev,
  104. sizeof(struct exynos_srom), GFP_KERNEL);
  105. if (!srom)
  106. return -ENOMEM;
  107. srom->dev = dev;
  108. srom->reg_base = of_iomap(np, 0);
  109. if (!srom->reg_base) {
  110. dev_err(&pdev->dev, "iomap of exynos srom controller failed\n");
  111. return -ENOMEM;
  112. }
  113. platform_set_drvdata(pdev, srom);
  114. srom->reg_offset = exynos_srom_alloc_reg_dump(exynos_srom_offsets,
  115. ARRAY_SIZE(exynos_srom_offsets));
  116. if (!srom->reg_offset) {
  117. iounmap(srom->reg_base);
  118. return -ENOMEM;
  119. }
  120. for_each_child_of_node(np, child) {
  121. if (exynos_srom_configure_bank(srom, child)) {
  122. dev_err(dev,
  123. "Could not decode bank configuration for %s\n",
  124. child->name);
  125. bad_bank_config = true;
  126. }
  127. }
  128. /*
  129. * If any bank failed to configure, we still provide suspend/resume,
  130. * but do not probe child devices
  131. */
  132. if (bad_bank_config)
  133. return 0;
  134. return of_platform_populate(np, NULL, NULL, dev);
  135. }
  136. #ifdef CONFIG_PM_SLEEP
  137. static void exynos_srom_save(void __iomem *base,
  138. struct exynos_srom_reg_dump *rd,
  139. unsigned int num_regs)
  140. {
  141. for (; num_regs > 0; --num_regs, ++rd)
  142. rd->value = readl(base + rd->offset);
  143. }
  144. static void exynos_srom_restore(void __iomem *base,
  145. const struct exynos_srom_reg_dump *rd,
  146. unsigned int num_regs)
  147. {
  148. for (; num_regs > 0; --num_regs, ++rd)
  149. writel(rd->value, base + rd->offset);
  150. }
  151. static int exynos_srom_suspend(struct device *dev)
  152. {
  153. struct exynos_srom *srom = dev_get_drvdata(dev);
  154. exynos_srom_save(srom->reg_base, srom->reg_offset,
  155. ARRAY_SIZE(exynos_srom_offsets));
  156. return 0;
  157. }
  158. static int exynos_srom_resume(struct device *dev)
  159. {
  160. struct exynos_srom *srom = dev_get_drvdata(dev);
  161. exynos_srom_restore(srom->reg_base, srom->reg_offset,
  162. ARRAY_SIZE(exynos_srom_offsets));
  163. return 0;
  164. }
  165. #endif
  166. static const struct of_device_id of_exynos_srom_ids[] = {
  167. {
  168. .compatible = "samsung,exynos4210-srom",
  169. },
  170. {},
  171. };
  172. static SIMPLE_DEV_PM_OPS(exynos_srom_pm_ops, exynos_srom_suspend, exynos_srom_resume);
  173. static struct platform_driver exynos_srom_driver = {
  174. .probe = exynos_srom_probe,
  175. .driver = {
  176. .name = "exynos-srom",
  177. .of_match_table = of_exynos_srom_ids,
  178. .pm = &exynos_srom_pm_ops,
  179. .suppress_bind_attrs = true,
  180. },
  181. };
  182. builtin_platform_driver(exynos_srom_driver);