1*0bcaecc8SYifeng Zhao /* 2*0bcaecc8SYifeng Zhao * (C) Copyright 2021 Rockchip Electronics Co., Ltd 3*0bcaecc8SYifeng Zhao * 4*0bcaecc8SYifeng Zhao * SPDX-License-Identifier: GPL-2.0+ 5*0bcaecc8SYifeng Zhao */ 6*0bcaecc8SYifeng Zhao #include <common.h> 7*0bcaecc8SYifeng Zhao #include <boot_rkimg.h> 8*0bcaecc8SYifeng Zhao #include <div64.h> 9*0bcaecc8SYifeng Zhao #include <dfu.h> 10*0bcaecc8SYifeng Zhao #include <errno.h> 11*0bcaecc8SYifeng Zhao #include <linux/mtd/mtd.h> 12*0bcaecc8SYifeng Zhao #include <malloc.h> 13*0bcaecc8SYifeng Zhao #include <part.h> 14*0bcaecc8SYifeng Zhao 15*0bcaecc8SYifeng Zhao static int dfu_write_medium_mtd(struct dfu_entity *dfu, u64 offset, void *buf, long *len) 16*0bcaecc8SYifeng Zhao { 17*0bcaecc8SYifeng Zhao struct blk_desc *dev_desc; 18*0bcaecc8SYifeng Zhao u64 block_start, block_len; 19*0bcaecc8SYifeng Zhao int ret = -ENODEV; 20*0bcaecc8SYifeng Zhao 21*0bcaecc8SYifeng Zhao switch (dfu->layout) { 22*0bcaecc8SYifeng Zhao case DFU_RAW_ADDR: 23*0bcaecc8SYifeng Zhao /* if buf == NULL return total size of the area */ 24*0bcaecc8SYifeng Zhao if (!buf) { 25*0bcaecc8SYifeng Zhao *len = dfu->data.nand.size; 26*0bcaecc8SYifeng Zhao return 0; 27*0bcaecc8SYifeng Zhao } 28*0bcaecc8SYifeng Zhao 29*0bcaecc8SYifeng Zhao dev_desc = rockchip_get_bootdev(); 30*0bcaecc8SYifeng Zhao if (!dev_desc) { 31*0bcaecc8SYifeng Zhao printf("%s: dev_desc is NULL!\n", __func__); 32*0bcaecc8SYifeng Zhao return -ENODEV; 33*0bcaecc8SYifeng Zhao } 34*0bcaecc8SYifeng Zhao 35*0bcaecc8SYifeng Zhao /* in case of ubi partition, erase rest of the partition */ 36*0bcaecc8SYifeng Zhao if (dfu->data.mtd.ubi && !offset) { 37*0bcaecc8SYifeng Zhao block_start = dfu->data.mtd.start >> 9; 38*0bcaecc8SYifeng Zhao block_len = dfu->data.mtd.size >> 9; 39*0bcaecc8SYifeng Zhao 40*0bcaecc8SYifeng Zhao ret = blk_derase(dev_desc, block_start, block_len); 41*0bcaecc8SYifeng Zhao if (ret != 0) 42*0bcaecc8SYifeng Zhao printf("Failure erase: %d\n", ret); 43*0bcaecc8SYifeng Zhao } 44*0bcaecc8SYifeng Zhao 45*0bcaecc8SYifeng Zhao block_start = (dfu->data.mtd.start + offset) >> 9; 46*0bcaecc8SYifeng Zhao block_len = (*len) >> 9; 47*0bcaecc8SYifeng Zhao 48*0bcaecc8SYifeng Zhao ret = blk_dwrite(dev_desc, block_start, block_len, buf); 49*0bcaecc8SYifeng Zhao if (ret == block_len) 50*0bcaecc8SYifeng Zhao ret = 0; 51*0bcaecc8SYifeng Zhao break; 52*0bcaecc8SYifeng Zhao default: 53*0bcaecc8SYifeng Zhao printf("%s: Layout (%s) not (yet) supported!\n", __func__, 54*0bcaecc8SYifeng Zhao dfu_get_layout(dfu->layout)); 55*0bcaecc8SYifeng Zhao } 56*0bcaecc8SYifeng Zhao 57*0bcaecc8SYifeng Zhao return ret; 58*0bcaecc8SYifeng Zhao } 59*0bcaecc8SYifeng Zhao 60*0bcaecc8SYifeng Zhao static int dfu_get_medium_size_mtd(struct dfu_entity *dfu, u64 *size) 61*0bcaecc8SYifeng Zhao { 62*0bcaecc8SYifeng Zhao *size = dfu->data.mtd.size; 63*0bcaecc8SYifeng Zhao 64*0bcaecc8SYifeng Zhao return 0; 65*0bcaecc8SYifeng Zhao } 66*0bcaecc8SYifeng Zhao 67*0bcaecc8SYifeng Zhao static int dfu_read_medium_mtd(struct dfu_entity *dfu, u64 offset, void *buf, long *len) 68*0bcaecc8SYifeng Zhao { 69*0bcaecc8SYifeng Zhao struct blk_desc *dev_desc; 70*0bcaecc8SYifeng Zhao u64 block_start, block_len; 71*0bcaecc8SYifeng Zhao int ret = -ENODEV; 72*0bcaecc8SYifeng Zhao 73*0bcaecc8SYifeng Zhao switch (dfu->layout) { 74*0bcaecc8SYifeng Zhao case DFU_RAW_ADDR: 75*0bcaecc8SYifeng Zhao /* if buf == NULL return total size of the area */ 76*0bcaecc8SYifeng Zhao if (!buf) { 77*0bcaecc8SYifeng Zhao *len = dfu->data.nand.size; 78*0bcaecc8SYifeng Zhao return 0; 79*0bcaecc8SYifeng Zhao } 80*0bcaecc8SYifeng Zhao 81*0bcaecc8SYifeng Zhao dev_desc = rockchip_get_bootdev(); 82*0bcaecc8SYifeng Zhao if (!dev_desc) { 83*0bcaecc8SYifeng Zhao printf("%s: dev_desc is NULL!\n", __func__); 84*0bcaecc8SYifeng Zhao return -ENODEV; 85*0bcaecc8SYifeng Zhao } 86*0bcaecc8SYifeng Zhao 87*0bcaecc8SYifeng Zhao block_start = (dfu->data.mtd.start + offset) >> 9; 88*0bcaecc8SYifeng Zhao block_len = (*len) >> 9; 89*0bcaecc8SYifeng Zhao 90*0bcaecc8SYifeng Zhao ret = blk_dread(dev_desc, block_start, block_len, buf); 91*0bcaecc8SYifeng Zhao if (ret == block_len) 92*0bcaecc8SYifeng Zhao ret = 0; 93*0bcaecc8SYifeng Zhao break; 94*0bcaecc8SYifeng Zhao default: 95*0bcaecc8SYifeng Zhao printf("%s: Layout (%s) not (yet) supported!\n", __func__, 96*0bcaecc8SYifeng Zhao dfu_get_layout(dfu->layout)); 97*0bcaecc8SYifeng Zhao } 98*0bcaecc8SYifeng Zhao 99*0bcaecc8SYifeng Zhao return ret; 100*0bcaecc8SYifeng Zhao } 101*0bcaecc8SYifeng Zhao 102*0bcaecc8SYifeng Zhao static int dfu_flush_medium_mtd(struct dfu_entity *dfu) 103*0bcaecc8SYifeng Zhao { 104*0bcaecc8SYifeng Zhao return 0; 105*0bcaecc8SYifeng Zhao } 106*0bcaecc8SYifeng Zhao 107*0bcaecc8SYifeng Zhao unsigned int dfu_polltimeout_mtd(struct dfu_entity *dfu) 108*0bcaecc8SYifeng Zhao { 109*0bcaecc8SYifeng Zhao /* 110*0bcaecc8SYifeng Zhao * Currently, Poll Timeout != 0 is only needed on nand 111*0bcaecc8SYifeng Zhao * ubi partition, as the not used sectors need an erase 112*0bcaecc8SYifeng Zhao */ 113*0bcaecc8SYifeng Zhao if (dfu->data.mtd.ubi) 114*0bcaecc8SYifeng Zhao return DFU_MANIFEST_POLL_TIMEOUT; 115*0bcaecc8SYifeng Zhao 116*0bcaecc8SYifeng Zhao return DFU_DEFAULT_POLL_TIMEOUT; 117*0bcaecc8SYifeng Zhao } 118*0bcaecc8SYifeng Zhao 119*0bcaecc8SYifeng Zhao int dfu_fill_entity_mtd(struct dfu_entity *dfu, char *devstr, char *s) 120*0bcaecc8SYifeng Zhao { 121*0bcaecc8SYifeng Zhao struct blk_desc *dev_desc; 122*0bcaecc8SYifeng Zhao disk_partition_t dfu_part; 123*0bcaecc8SYifeng Zhao char *st; 124*0bcaecc8SYifeng Zhao 125*0bcaecc8SYifeng Zhao dfu->data.mtd.ubi = 0; 126*0bcaecc8SYifeng Zhao dfu->dev_type = DFU_DEV_MTD; 127*0bcaecc8SYifeng Zhao st = strsep(&s, " "); 128*0bcaecc8SYifeng Zhao 129*0bcaecc8SYifeng Zhao if (!strcmp(st, "raw")) { 130*0bcaecc8SYifeng Zhao dfu->layout = DFU_RAW_ADDR; 131*0bcaecc8SYifeng Zhao dfu->data.mtd.start = simple_strtoul(s, &s, 16); 132*0bcaecc8SYifeng Zhao s++; 133*0bcaecc8SYifeng Zhao dfu->data.mtd.size = simple_strtoul(s, &s, 16); 134*0bcaecc8SYifeng Zhao } else if ((!strcmp(st, "part")) || (!strcmp(st, "partubi"))) { 135*0bcaecc8SYifeng Zhao dev_desc = rockchip_get_bootdev(); 136*0bcaecc8SYifeng Zhao if (!dev_desc) { 137*0bcaecc8SYifeng Zhao printf("%s: dev_desc is NULL!\n", __func__); 138*0bcaecc8SYifeng Zhao return -ENODEV; 139*0bcaecc8SYifeng Zhao } 140*0bcaecc8SYifeng Zhao dfu->layout = DFU_RAW_ADDR; 141*0bcaecc8SYifeng Zhao if (part_get_info_by_name(dev_desc, s, &dfu_part) < 0) 142*0bcaecc8SYifeng Zhao return -EIO; 143*0bcaecc8SYifeng Zhao 144*0bcaecc8SYifeng Zhao dfu->data.mtd.start = dfu_part.start << 9; 145*0bcaecc8SYifeng Zhao dfu->data.mtd.size = dfu_part.size << 9; 146*0bcaecc8SYifeng Zhao if (!strcmp(st, "partubi")) 147*0bcaecc8SYifeng Zhao dfu->data.mtd.ubi = 1; 148*0bcaecc8SYifeng Zhao } else { 149*0bcaecc8SYifeng Zhao printf("%s: Memory layout (%s) not supported!\n", __func__, st); 150*0bcaecc8SYifeng Zhao return -1; 151*0bcaecc8SYifeng Zhao } 152*0bcaecc8SYifeng Zhao 153*0bcaecc8SYifeng Zhao dfu->get_medium_size = dfu_get_medium_size_mtd; 154*0bcaecc8SYifeng Zhao dfu->read_medium = dfu_read_medium_mtd; 155*0bcaecc8SYifeng Zhao dfu->write_medium = dfu_write_medium_mtd; 156*0bcaecc8SYifeng Zhao dfu->flush_medium = dfu_flush_medium_mtd; 157*0bcaecc8SYifeng Zhao dfu->poll_timeout = dfu_polltimeout_mtd; 158*0bcaecc8SYifeng Zhao 159*0bcaecc8SYifeng Zhao /* initial state */ 160*0bcaecc8SYifeng Zhao dfu->inited = 0; 161*0bcaecc8SYifeng Zhao 162*0bcaecc8SYifeng Zhao return 0; 163*0bcaecc8SYifeng Zhao } 164