
Signed-off-by: Andrzej Pietrasiewicz andrzej.p@samsung.com Signed-off-by: Kyungmin Park kyungmin.park@samsung.com --- board/samsung/goni/Makefile | 2 + board/samsung/goni/flash.c | 341 +++++++++++++++++++++++++++++++++++++++++++ board/samsung/goni/flash.h | 28 ++++ board/samsung/goni/goni.c | 17 ++ include/configs/s5p_goni.h | 4 + 5 files changed, 392 insertions(+), 0 deletions(-) create mode 100644 board/samsung/goni/flash.c create mode 100644 board/samsung/goni/flash.h
diff --git a/board/samsung/goni/Makefile b/board/samsung/goni/Makefile index ecde7a7..3f13cb8 100644 --- a/board/samsung/goni/Makefile +++ b/board/samsung/goni/Makefile @@ -31,6 +31,8 @@ LIB = $(obj)lib$(BOARD).o COBJS-y := goni.o onenand.o SOBJS := lowlevel_init.o
+COBJS-$(CONFIG_DFU_FOR_BOARD) += flash.o + SRCS := $(SOBJS:.o=.S) $(COBJS-y:.o=.c) OBJS := $(addprefix $(obj),$(COBJS-y)) SOBJS := $(addprefix $(obj),$(SOBJS)) diff --git a/board/samsung/goni/flash.c b/board/samsung/goni/flash.c new file mode 100644 index 0000000..29c7ec1 --- /dev/null +++ b/board/samsung/goni/flash.c @@ -0,0 +1,341 @@ +/* + * flash.c -- board flashing routines + * + * Copyright (C) 2011 Samsung Electronics + * author: Andrzej Pietrasiewicz andrzej.p@samsung.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <common.h> +#include <malloc.h> +#include <mmc.h> +#include <dfu_backend.h> +#include <flash_entity.h> +#include <linux/types.h> +#include <jffs2/load_kernel.h> + +#define MMC_BLOCK_SZ (256 * 1024) +#define MMC_UBOOT_OFFSET 128 +#define MMC_UBOOT_SZ 512 +#define MMC_NAME_LEN 12 +#define SHORT_PART_NAME 15 +#define LONG_PART_NAME 20 +#define CALLOC_STRUCT(n, type) (struct type *) calloc(n, sizeof(struct type)) +#define DEFAULT_MMC_PART_NAME "mmc-default-part" + +/* partition IDs counted from 0, eg. mmc0-pri-1's ID is 0 */ +#define UIMAGE_PART_ID 1 +#define EXTENDED_PART_ID 3 +#define UMS_PART_ID 7 +#define UIMAGE_PART_NAME "mmc0-pri-2" + +#define USE_MMC_UBOOT +#define USE_MMC + +/* + * MMC u-boot partitions + */ +static struct mbr_part_data *uboot_pdata; + +static u8 uboot_part_num; +static u8 used_uboot_parts; + +int use_uboot(struct mbr_part_data *pdata, u8 i) +{ + /* + * Use i and pdata[i] members to decide if the partition is used + */ + return 1; +} + +char *alloc_uboot_name(u8 i) +{ + char *name = calloc(SHORT_PART_NAME, 1); + + if (name) { + sprintf(name, "mmc-u-boot"); + return name; + } + + return DEFAULT_MMC_PART_NAME; +} + +/* + * MMC partitions and MMC operations + */ +struct mmc *mmc; + +static struct mbr_part_data *mmc_pdata; + +static u8 mmc_part_num; +static u8 used_mmc_parts; + +static u8 mmc_buf[MMC_BLOCK_SZ]; + +static int extended_lba; + +static int mmc_mbr_dev; + +static u8 pri_count; +static u8 ext_count = 4; + +/* + * Define files available in the UIMAGE partition which has FAT on it. + * Only flat structure without subdirectories is supported. + */ +static char *uImage_part_files[] = { + "uImage", +}; +#define UIMAGE_PART_NUM_FILES ARRAY_SIZE(uImage_part_files) + +/* + * Return number of flash entities per this partition + */ +u8 use_mmc(struct mbr_part_data *pdata, u8 i) +{ + /* + * Use i and pdata[i] members to decide if the partition is used + */ + if (i == UIMAGE_PART_ID) + return UIMAGE_PART_NUM_FILES; + if (i == EXTENDED_PART_ID) + return 0; /* do not expose the extended partition as a whole */ + if (i == UMS_PART_ID) + return 0; /* do not expose UMS; there is a separate command */ + return 1; +} + +char *alloc_mmc_name(struct mbr_part_data *pdata, u8 i, u8 l) +{ + char *name = calloc(MMC_NAME_LEN, 1); + + if (name) { + sprintf(name, "mmc0-"); + if (pdata[i].primary) + sprintf(name + strlen(name), "pri-%d", + l ? pri_count : ++pri_count); + else + sprintf(name + strlen(name), "ext-%d", + l ? ext_count : ++ext_count); + + return name; + } + + return DEFAULT_MMC_PART_NAME; +} + +/* + * FAT operations + */ +static u8 fat_buf[MMC_FAT_BLOCK_SZ]; + +/* + * Transport layer to storage adaptation + */ + +static int prepare_fat(void *ctx, u8 mode) +{ + struct flash_entity_ctx *ct = ctx; + + set_fat_filename(ct->associated); + if (!strncmp(ct->this_entity->name, UIMAGE_PART_NAME, + strlen(UIMAGE_PART_NAME))) + set_fat_part_num(UIMAGE_PART_ID + 1); + return generic_prepare(ctx, mode); +} + +/* + * Flash entities definitions for this board + */ +static struct flash_entity *flash_ents; + +static void customize_entities(struct flash_entity *fe, u8 n_ents) +{ + int i; + for (i = 0; i < n_ents; ++i) { + /* i counts all entities, not just mmc entities */ + /* add similar "if" blocks for other customizable entities */ + if (!strcmp(fe[i].name, UIMAGE_PART_NAME)) { + struct flash_entity_ctx *ctx; + char *name, file_number; + + fe[i].prepare = prepare_fat; + ctx = fe[i].ctx; + ctx->length = min(ctx->length, MMC_FAT_BLOCK_SZ); + ctx->buf = fat_buf; + ctx->buf_len = ctx->length; + ctx->read = read_fat; + ctx->write = write_fat; + file_number = (char)ctx->associated; + /* by design file_number cannot exceed array size */ + ctx->associated = uImage_part_files[file_number]; + + name = calloc(LONG_PART_NAME, 1); + if (name) { + sprintf(name, "%s-%s", fe[i].name, + (char *)ctx->associated); + free(fe[i].name); + fe[i].name = name; + } + + continue; + } + } +} + +static inline void generic_flash_entity(struct flash_entity *fe) +{ + fe->prepare = generic_prepare; + fe->finish = generic_finish; + fe->read_block = read_block; + fe->write_block = write_block; +} + +static inline void generic_flash_entity_ctx(struct flash_entity_ctx *ctx, + struct flash_entity *fe) +{ + ctx->buf = mmc_buf; + ctx->buf_len = MMC_BLOCK_SZ; + ctx->read = read_mmc; + ctx->write = write_mmc; + ctx->erase = NULL; + ctx->this_entity = fe; + fe->ctx = ctx; +} + +void register_flash_areas(void) +{ + u8 i, j; + +#ifdef USE_MMC + mmc = find_mmc_device(mmc_mbr_dev); + if (mmc && !mmc_init(mmc)) { + mmc_part_num = read_mbr(mmc, NULL, &extended_lba, mmc_mbr_dev); + if (mmc_part_num) { + mmc_pdata = CALLOC_STRUCT(mmc_part_num, + mbr_part_data); + if (mmc_pdata) { + if (!read_mbr(mmc, mmc_pdata, &extended_lba, mmc_mbr_dev)) { + free(mmc_pdata); + mmc_pdata = NULL; + } + set_fat_dev(&mmc->block_dev); + } + } + } + used_mmc_parts = 0; + for (i = 0; mmc_pdata && i < mmc_part_num; ++i) + used_mmc_parts += use_mmc(mmc_pdata, i); + pri_count = 0; + ext_count = 4; +#endif + +#ifdef USE_MMC_UBOOT + if (mmc) { + uboot_part_num = 1; + if (uboot_part_num) { + uboot_pdata = CALLOC_STRUCT(uboot_part_num, + mbr_part_data); + if (uboot_pdata) + for (i = 0; i < uboot_part_num; ++i) { + uboot_pdata[i].offset = + MMC_UBOOT_OFFSET; + uboot_pdata[i].length = + MMC_UBOOT_SZ; + uboot_pdata[i].primary = 0; + } + } + } + used_uboot_parts = 0; + for (i = 0; uboot_pdata && i < uboot_part_num; ++i) + used_uboot_parts += use_uboot(uboot_pdata, i); +#endif + + flash_ents = CALLOC_STRUCT(used_uboot_parts + used_mmc_parts, + flash_entity); + if (!flash_ents) + goto partinfo_alloc_rollback; + + j = 0; + for (i = 0; i < uboot_part_num; ++i) + if (use_uboot(uboot_pdata, i)) { + struct flash_entity *fe; + struct flash_entity_ctx *ctx; + + fe = &flash_ents[j++]; + fe->name = alloc_uboot_name(i); + generic_flash_entity(fe); + + ctx = CALLOC_STRUCT(1, flash_entity_ctx); + if (!ctx) + goto flash_ents_alloc_rollback; + generic_flash_entity_ctx(ctx, fe); + ctx->offset = uboot_pdata[i].offset * MMC_SECTOR_SZ; + ctx->length = uboot_pdata[i].length * MMC_SECTOR_SZ; + } + uboot_part_num = used_uboot_parts; + + for (i = 0; i < mmc_part_num; ++i) { + u8 k = use_mmc(mmc_pdata, i); + u8 l; + for (l = 0; l < k; ++l) { + struct flash_entity *fe; + struct flash_entity_ctx *ctx; + + fe = &flash_ents[j++]; + fe->name = alloc_mmc_name(mmc_pdata, i, l); + generic_flash_entity(fe); + + ctx = CALLOC_STRUCT(1, flash_entity_ctx); + if (!ctx) + goto flash_ents_alloc_rollback; + generic_flash_entity_ctx(ctx, fe); + ctx->offset = mmc_pdata[i].offset * MMC_SECTOR_SZ; + ctx->length = mmc_pdata[i].length * MMC_SECTOR_SZ; + ctx->associated = (void *)l; + } + } + mmc_part_num = used_mmc_parts; + customize_entities(flash_ents, uboot_part_num + mmc_part_num); + register_flash_entities(flash_ents, uboot_part_num + mmc_part_num); +printf("NUM ENTITIES:%d\n", uboot_part_num + mmc_part_num); + + return; + +flash_ents_alloc_rollback: + while (j--) { + free(flash_ents[j].name); + free(flash_ents[j].ctx); + } + free(flash_ents); + +partinfo_alloc_rollback: + free(uboot_pdata); + free(mmc_pdata); +} + +void unregister_flash_areas(void) +{ + int j = uboot_part_num + mmc_part_num; + while (j--) { + free(flash_ents[j].name); + free(flash_ents[j].ctx); + } + free(flash_ents); + free(uboot_pdata); + free(mmc_pdata); +} + diff --git a/board/samsung/goni/flash.h b/board/samsung/goni/flash.h new file mode 100644 index 0000000..ffe4d6d --- /dev/null +++ b/board/samsung/goni/flash.h @@ -0,0 +1,28 @@ +/* + * flash.h -- board flashing routines interface + * + * Copyright (C) 2011 Samsung Electronics + * author: Andrzej Pietrasiewicz andrzej.p@samsung.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef FLASH_GONI_H_ +#define FLASH_GONI_H_ + +void register_flash_areas(void); +void unregister_flash_areas(void); + +#endif diff --git a/board/samsung/goni/goni.c b/board/samsung/goni/goni.c index c4fc3e9..7e693be 100644 --- a/board/samsung/goni/goni.c +++ b/board/samsung/goni/goni.c @@ -29,6 +29,9 @@ #include <asm/arch/hs_otg.h> #include <asm/arch/cpu.h> #include <max8998_pmic.h> + +#include "flash.h" + DECLARE_GLOBAL_DATA_PTR;
static struct s5pc110_gpio *s5pc110_gpio; @@ -144,4 +147,18 @@ struct s3c_plat_otg_data s5pc110_otg_data = { .regs_phy = S5PC110_PHY_BASE, .regs_otg = S5PC110_OTG_BASE, }; + +#ifdef CONFIG_DFU_FOR_BOARD +void board_dfu_init(void) +{ + register_flash_areas(); + s3c_udc_probe(&s5pc110_otg_data); +} + +void board_dfu_cleanup(void) +{ + unregister_flash_areas(); +} +#endif + #endif diff --git a/include/configs/s5p_goni.h b/include/configs/s5p_goni.h index df97802..3881f92 100644 --- a/include/configs/s5p_goni.h +++ b/include/configs/s5p_goni.h @@ -86,6 +86,8 @@ #define CONFIG_CMD_ONENAND #define CONFIG_CMD_MTDPARTS #define CONFIG_CMD_MMC +#define CONFIG_CMD_FAT +#define CONFIG_CMD_DEVICE_FIRMWARE_UPGRADE
#define CONFIG_BOOTDELAY 1 #define CONFIG_ZERO_BOOTDELAY_CHECK @@ -241,4 +243,6 @@ #define CONFIG_USB_GADGET_S3C_UDC_OTG 1 #define CONFIG_USB_GADGET_DUALSPEED 1
+#define CONFIG_DFU_GADGET +#define CONFIG_DFU_FOR_BOARD #endif /* __CONFIG_H */