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