onenand.c 2.44 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0+
2
/*
3 4 5
 * (C) Copyright 2010 DENX Software Engineering
 * Wolfgang Denk <wd@denx.de>
 *
6
 * (C) Copyright 2005-2009 Samsung Electronics
7 8 9 10 11 12 13 14
 * Kyungmin Park <kyungmin.park@samsung.com>
 */

#include <common.h>
#include <command.h>
#include <environment.h>
#include <linux/stddef.h>
#include <malloc.h>
15 16
#include <search.h>
#include <errno.h>
17
#include <onenand_uboot.h>
18

19
#include <linux/compat.h>
20 21 22
#include <linux/mtd/mtd.h>
#include <linux/mtd/onenand.h>

23
#define ONENAND_MAX_ENV_SIZE	CONFIG_ENV_SIZE
24 25
#define ONENAND_ENV_SIZE(mtd)	(ONENAND_MAX_ENV_SIZE - ENV_HEADER_SIZE)

26 27
DECLARE_GLOBAL_DATA_PTR;

28
static 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 39
#else
	loff_t env_addr = CONFIG_ENV_ADDR;
40 41
	char onenand_env[ONENAND_MAX_ENV_SIZE];
	char *buf = (char *)&onenand_env[0];
42
#endif /* ENV_IS_EMBEDDED */
43

44 45
#ifndef ENV_IS_EMBEDDED
# ifdef CONFIG_ENV_ADDR_FLEX
46 47
	if (FLEXONENAND(this))
		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
}

65
static 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 74
	loff_t	env_addr = CONFIG_ENV_ADDR;
	size_t	retlen;
75 76 77
	struct erase_info instr = {
		.callback	= NULL,
	};
78

79 80 81
	ret = env_export(&env_new);
	if (ret)
		return ret;
82

83
	instr.len = CONFIG_ENV_SIZE;
84
#ifdef CONFIG_ENV_ADDR_FLEX
85 86 87 88 89 90
	if (FLEXONENAND(this)) {
		env_addr = CONFIG_ENV_ADDR_FLEX;
		instr.len = CONFIG_ENV_SIZE_FLEX;
		instr.len <<= onenand_mtd.eraseregions[0].numblocks == 1 ?
				1 : 0;
	}
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 97 98
		return 1;
	}

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 103 104 105 106 107
		return 2;
	}

	return 0;
}

108 109
U_BOOT_ENV_LOCATION(onenand) = {
	.location	= ENVL_ONENAND,
110
	ENV_NAME("OneNAND")
111 112
	.load		= env_onenand_load,
	.save		= env_save_ptr(env_onenand_save),
113
};