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