onenand.c 2.5 KB

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