onenand.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * (C) Copyright 2010 DENX Software Engineering
  4. * Wolfgang Denk <wd@denx.de>
  5. *
  6. * (C) Copyright 2005-2009 Samsung Electronics
  7. * Kyungmin Park <kyungmin.park@samsung.com>
  8. */
  9. #include <common.h>
  10. #include <command.h>
  11. #include <env_internal.h>
  12. #include <linux/stddef.h>
  13. #include <malloc.h>
  14. #include <search.h>
  15. #include <errno.h>
  16. #include <onenand_uboot.h>
  17. #include <linux/compat.h>
  18. #include <linux/mtd/mtd.h>
  19. #include <linux/mtd/onenand.h>
  20. #define ONENAND_MAX_ENV_SIZE CONFIG_ENV_SIZE
  21. #define ONENAND_ENV_SIZE(mtd) (ONENAND_MAX_ENV_SIZE - ENV_HEADER_SIZE)
  22. DECLARE_GLOBAL_DATA_PTR;
  23. static int env_onenand_load(void)
  24. {
  25. struct mtd_info *mtd = &onenand_mtd;
  26. #ifdef CONFIG_ENV_ADDR_FLEX
  27. struct onenand_chip *this = &onenand_chip;
  28. #endif
  29. int rc;
  30. size_t retlen;
  31. #ifdef ENV_IS_EMBEDDED
  32. char *buf = (char *)&environment;
  33. #else
  34. loff_t env_addr = CONFIG_ENV_ADDR;
  35. char onenand_env[ONENAND_MAX_ENV_SIZE];
  36. char *buf = (char *)&onenand_env[0];
  37. #endif /* ENV_IS_EMBEDDED */
  38. #ifndef ENV_IS_EMBEDDED
  39. # ifdef CONFIG_ENV_ADDR_FLEX
  40. if (FLEXONENAND(this))
  41. env_addr = CONFIG_ENV_ADDR_FLEX;
  42. # endif
  43. /* Check OneNAND exist */
  44. if (mtd->writesize)
  45. /* Ignore read fail */
  46. mtd_read(mtd, env_addr, ONENAND_MAX_ENV_SIZE,
  47. &retlen, (u_char *)buf);
  48. else
  49. mtd->writesize = MAX_ONENAND_PAGESIZE;
  50. #endif /* !ENV_IS_EMBEDDED */
  51. rc = env_import(buf, 1);
  52. if (!rc)
  53. gd->env_valid = ENV_VALID;
  54. return rc;
  55. }
  56. static int env_onenand_save(void)
  57. {
  58. env_t env_new;
  59. int ret;
  60. struct mtd_info *mtd = &onenand_mtd;
  61. #ifdef CONFIG_ENV_ADDR_FLEX
  62. struct onenand_chip *this = &onenand_chip;
  63. #endif
  64. loff_t env_addr = CONFIG_ENV_ADDR;
  65. size_t retlen;
  66. struct erase_info instr = {
  67. .callback = NULL,
  68. };
  69. ret = env_export(&env_new);
  70. if (ret)
  71. return ret;
  72. instr.len = CONFIG_ENV_SIZE;
  73. #ifdef CONFIG_ENV_ADDR_FLEX
  74. if (FLEXONENAND(this)) {
  75. env_addr = CONFIG_ENV_ADDR_FLEX;
  76. instr.len = CONFIG_ENV_SIZE_FLEX;
  77. instr.len <<= onenand_mtd.eraseregions[0].numblocks == 1 ?
  78. 1 : 0;
  79. }
  80. #endif
  81. instr.addr = env_addr;
  82. instr.mtd = mtd;
  83. if (mtd_erase(mtd, &instr)) {
  84. printf("OneNAND: erase failed at 0x%08llx\n", env_addr);
  85. return 1;
  86. }
  87. if (mtd_write(mtd, env_addr, ONENAND_MAX_ENV_SIZE, &retlen,
  88. (u_char *)&env_new)) {
  89. printf("OneNAND: write failed at 0x%llx\n", instr.addr);
  90. return 2;
  91. }
  92. return 0;
  93. }
  94. U_BOOT_ENV_LOCATION(onenand) = {
  95. .location = ENVL_ONENAND,
  96. ENV_NAME("OneNAND")
  97. .load = env_onenand_load,
  98. .save = env_save_ptr(env_onenand_save),
  99. };