denali_dt.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2017 Socionext Inc.
  4. * Author: Masahiro Yamada <yamada.masahiro@socionext.com>
  5. */
  6. #include <clk.h>
  7. #include <dm.h>
  8. #include <dm/device_compat.h>
  9. #include <linux/bug.h>
  10. #include <linux/delay.h>
  11. #include <linux/io.h>
  12. #include <linux/ioport.h>
  13. #include <linux/printk.h>
  14. #include <reset.h>
  15. #include "denali.h"
  16. struct denali_dt_data {
  17. unsigned int revision;
  18. unsigned int caps;
  19. unsigned int oob_skip_bytes;
  20. const struct nand_ecc_caps *ecc_caps;
  21. };
  22. NAND_ECC_CAPS_SINGLE(denali_socfpga_ecc_caps, denali_calc_ecc_bytes,
  23. 512, 8, 15);
  24. static const struct denali_dt_data denali_socfpga_data = {
  25. .caps = DENALI_CAP_HW_ECC_FIXUP,
  26. .oob_skip_bytes = 2,
  27. .ecc_caps = &denali_socfpga_ecc_caps,
  28. };
  29. NAND_ECC_CAPS_SINGLE(denali_uniphier_v5a_ecc_caps, denali_calc_ecc_bytes,
  30. 1024, 8, 16, 24);
  31. static const struct denali_dt_data denali_uniphier_v5a_data = {
  32. .caps = DENALI_CAP_HW_ECC_FIXUP |
  33. DENALI_CAP_DMA_64BIT,
  34. .oob_skip_bytes = 8,
  35. .ecc_caps = &denali_uniphier_v5a_ecc_caps,
  36. };
  37. NAND_ECC_CAPS_SINGLE(denali_uniphier_v5b_ecc_caps, denali_calc_ecc_bytes,
  38. 1024, 8, 16);
  39. static const struct denali_dt_data denali_uniphier_v5b_data = {
  40. .revision = 0x0501,
  41. .caps = DENALI_CAP_HW_ECC_FIXUP |
  42. DENALI_CAP_DMA_64BIT,
  43. .oob_skip_bytes = 8,
  44. .ecc_caps = &denali_uniphier_v5b_ecc_caps,
  45. };
  46. static const struct udevice_id denali_nand_dt_ids[] = {
  47. {
  48. .compatible = "altr,socfpga-denali-nand",
  49. .data = (unsigned long)&denali_socfpga_data,
  50. },
  51. {
  52. .compatible = "socionext,uniphier-denali-nand-v5a",
  53. .data = (unsigned long)&denali_uniphier_v5a_data,
  54. },
  55. {
  56. .compatible = "socionext,uniphier-denali-nand-v5b",
  57. .data = (unsigned long)&denali_uniphier_v5b_data,
  58. },
  59. { /* sentinel */ }
  60. };
  61. static int denali_dt_probe(struct udevice *dev)
  62. {
  63. struct denali_nand_info *denali = dev_get_priv(dev);
  64. const struct denali_dt_data *data;
  65. struct clk clk, clk_x, clk_ecc;
  66. struct reset_ctl_bulk resets;
  67. struct resource res;
  68. int ret;
  69. data = (void *)dev_get_driver_data(dev);
  70. if (WARN_ON(!data))
  71. return -EINVAL;
  72. denali->revision = data->revision;
  73. denali->caps = data->caps;
  74. denali->oob_skip_bytes = data->oob_skip_bytes;
  75. denali->ecc_caps = data->ecc_caps;
  76. denali->dev = dev;
  77. ret = dev_read_resource_byname(dev, "denali_reg", &res);
  78. if (ret)
  79. return ret;
  80. denali->reg = devm_ioremap(dev, res.start, resource_size(&res));
  81. ret = dev_read_resource_byname(dev, "nand_data", &res);
  82. if (ret)
  83. return ret;
  84. denali->host = devm_ioremap(dev, res.start, resource_size(&res));
  85. ret = clk_get_by_name(dev, "nand", &clk);
  86. if (ret)
  87. ret = clk_get_by_index(dev, 0, &clk);
  88. if (ret)
  89. clk.dev = NULL;
  90. ret = clk_get_by_name(dev, "nand_x", &clk_x);
  91. if (ret)
  92. clk_x.dev = NULL;
  93. ret = clk_get_by_name(dev, "ecc", &clk_ecc);
  94. if (ret)
  95. clk_ecc.dev = NULL;
  96. if (clk.dev) {
  97. ret = clk_enable(&clk);
  98. if (ret)
  99. return ret;
  100. }
  101. if (clk_x.dev) {
  102. ret = clk_enable(&clk_x);
  103. if (ret)
  104. return ret;
  105. }
  106. if (clk_ecc.dev) {
  107. ret = clk_enable(&clk_ecc);
  108. if (ret)
  109. return ret;
  110. }
  111. if (clk_x.dev) {
  112. denali->clk_rate = clk_get_rate(&clk);
  113. denali->clk_x_rate = clk_get_rate(&clk_x);
  114. } else {
  115. /*
  116. * Hardcode the clock rates for the backward compatibility.
  117. * This works for both SOCFPGA and UniPhier.
  118. */
  119. dev_notice(dev,
  120. "necessary clock is missing. default clock rates are used.\n");
  121. denali->clk_rate = 50000000;
  122. denali->clk_x_rate = 200000000;
  123. }
  124. ret = reset_get_bulk(dev, &resets);
  125. if (ret) {
  126. dev_warn(dev, "Can't get reset: %d\n", ret);
  127. } else {
  128. reset_assert_bulk(&resets);
  129. udelay(2);
  130. reset_deassert_bulk(&resets);
  131. /*
  132. * When the reset is deasserted, the initialization sequence is
  133. * kicked (bootstrap process). The driver must wait until it is
  134. * finished. Otherwise, it will result in unpredictable behavior.
  135. */
  136. ret = denali_wait_reset_complete(denali);
  137. if (ret) {
  138. dev_err(denali->dev, "reset not completed.\n");
  139. return ret;
  140. }
  141. }
  142. return denali_init(denali);
  143. }
  144. U_BOOT_DRIVER(denali_nand_dt) = {
  145. .name = "denali-nand-dt",
  146. .id = UCLASS_MTD,
  147. .of_match = denali_nand_dt_ids,
  148. .probe = denali_dt_probe,
  149. .priv_auto = sizeof(struct denali_nand_info),
  150. };
  151. void board_nand_init(void)
  152. {
  153. struct udevice *dev;
  154. int ret;
  155. ret = uclass_get_device_by_driver(UCLASS_MTD,
  156. DM_DRIVER_GET(denali_nand_dt),
  157. &dev);
  158. if (ret && ret != -ENODEV)
  159. pr_err("Failed to initialize Denali NAND controller. (error %d)\n",
  160. ret);
  161. }