1*6f12ebf6SStephen Warren /* 2*6f12ebf6SStephen Warren * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. 3*6f12ebf6SStephen Warren * 4*6f12ebf6SStephen Warren * SPDX-License-Identifier: GPL-2.0+ 5*6f12ebf6SStephen Warren */ 6*6f12ebf6SStephen Warren 7*6f12ebf6SStephen Warren #include <common.h> 8*6f12ebf6SStephen Warren #include <malloc.h> 9*6f12ebf6SStephen Warren #include <errno.h> 10*6f12ebf6SStephen Warren #include <div64.h> 11*6f12ebf6SStephen Warren #include <dfu.h> 12*6f12ebf6SStephen Warren #include <spi_flash.h> 13*6f12ebf6SStephen Warren 14*6f12ebf6SStephen Warren static long dfu_get_medium_size_sf(struct dfu_entity *dfu) 15*6f12ebf6SStephen Warren { 16*6f12ebf6SStephen Warren return dfu->data.sf.size; 17*6f12ebf6SStephen Warren } 18*6f12ebf6SStephen Warren 19*6f12ebf6SStephen Warren static int dfu_read_medium_sf(struct dfu_entity *dfu, u64 offset, void *buf, 20*6f12ebf6SStephen Warren long *len) 21*6f12ebf6SStephen Warren { 22*6f12ebf6SStephen Warren return spi_flash_read(dfu->data.sf.dev, offset, *len, buf); 23*6f12ebf6SStephen Warren } 24*6f12ebf6SStephen Warren 25*6f12ebf6SStephen Warren static int dfu_write_medium_sf(struct dfu_entity *dfu, 26*6f12ebf6SStephen Warren u64 offset, void *buf, long *len) 27*6f12ebf6SStephen Warren { 28*6f12ebf6SStephen Warren int ret; 29*6f12ebf6SStephen Warren 30*6f12ebf6SStephen Warren ret = spi_flash_erase(dfu->data.sf.dev, offset, *len); 31*6f12ebf6SStephen Warren if (ret) 32*6f12ebf6SStephen Warren return ret; 33*6f12ebf6SStephen Warren 34*6f12ebf6SStephen Warren ret = spi_flash_write(dfu->data.sf.dev, offset, *len, buf); 35*6f12ebf6SStephen Warren if (ret) 36*6f12ebf6SStephen Warren return ret; 37*6f12ebf6SStephen Warren 38*6f12ebf6SStephen Warren return 0; 39*6f12ebf6SStephen Warren } 40*6f12ebf6SStephen Warren 41*6f12ebf6SStephen Warren static int dfu_flush_medium_sf(struct dfu_entity *dfu) 42*6f12ebf6SStephen Warren { 43*6f12ebf6SStephen Warren return 0; 44*6f12ebf6SStephen Warren } 45*6f12ebf6SStephen Warren 46*6f12ebf6SStephen Warren static unsigned int dfu_polltimeout_sf(struct dfu_entity *dfu) 47*6f12ebf6SStephen Warren { 48*6f12ebf6SStephen Warren return DFU_DEFAULT_POLL_TIMEOUT; 49*6f12ebf6SStephen Warren } 50*6f12ebf6SStephen Warren 51*6f12ebf6SStephen Warren static void dfu_free_entity_sf(struct dfu_entity *dfu) 52*6f12ebf6SStephen Warren { 53*6f12ebf6SStephen Warren spi_flash_free(dfu->data.sf.dev); 54*6f12ebf6SStephen Warren } 55*6f12ebf6SStephen Warren 56*6f12ebf6SStephen Warren static struct spi_flash *parse_dev(char *devstr) 57*6f12ebf6SStephen Warren { 58*6f12ebf6SStephen Warren unsigned int bus; 59*6f12ebf6SStephen Warren unsigned int cs; 60*6f12ebf6SStephen Warren unsigned int speed = CONFIG_SF_DEFAULT_SPEED; 61*6f12ebf6SStephen Warren unsigned int mode = CONFIG_SF_DEFAULT_MODE; 62*6f12ebf6SStephen Warren char *s, *endp; 63*6f12ebf6SStephen Warren struct spi_flash *dev; 64*6f12ebf6SStephen Warren 65*6f12ebf6SStephen Warren s = strsep(&devstr, ":"); 66*6f12ebf6SStephen Warren if (!s || !*s || (bus = simple_strtoul(s, &endp, 0), *endp)) { 67*6f12ebf6SStephen Warren printf("Invalid SPI bus %s\n", s); 68*6f12ebf6SStephen Warren return NULL; 69*6f12ebf6SStephen Warren } 70*6f12ebf6SStephen Warren 71*6f12ebf6SStephen Warren s = strsep(&devstr, ":"); 72*6f12ebf6SStephen Warren if (!s || !*s || (cs = simple_strtoul(s, &endp, 0), *endp)) { 73*6f12ebf6SStephen Warren printf("Invalid SPI chip-select %s\n", s); 74*6f12ebf6SStephen Warren return NULL; 75*6f12ebf6SStephen Warren } 76*6f12ebf6SStephen Warren 77*6f12ebf6SStephen Warren s = strsep(&devstr, ":"); 78*6f12ebf6SStephen Warren if (s && *s) { 79*6f12ebf6SStephen Warren speed = simple_strtoul(s, &endp, 0); 80*6f12ebf6SStephen Warren if (*endp || !speed) { 81*6f12ebf6SStephen Warren printf("Invalid SPI speed %s\n", s); 82*6f12ebf6SStephen Warren return NULL; 83*6f12ebf6SStephen Warren } 84*6f12ebf6SStephen Warren } 85*6f12ebf6SStephen Warren 86*6f12ebf6SStephen Warren s = strsep(&devstr, ":"); 87*6f12ebf6SStephen Warren if (s && *s) { 88*6f12ebf6SStephen Warren mode = simple_strtoul(s, &endp, 0); 89*6f12ebf6SStephen Warren if (*endp || mode > 3) { 90*6f12ebf6SStephen Warren printf("Invalid SPI mode %s\n", s); 91*6f12ebf6SStephen Warren return NULL; 92*6f12ebf6SStephen Warren } 93*6f12ebf6SStephen Warren } 94*6f12ebf6SStephen Warren 95*6f12ebf6SStephen Warren dev = spi_flash_probe(bus, cs, speed, mode); 96*6f12ebf6SStephen Warren if (!dev) { 97*6f12ebf6SStephen Warren printf("Failed to create SPI flash at %d:%d:%d:%d\n", 98*6f12ebf6SStephen Warren bus, cs, speed, mode); 99*6f12ebf6SStephen Warren return NULL; 100*6f12ebf6SStephen Warren } 101*6f12ebf6SStephen Warren 102*6f12ebf6SStephen Warren return dev; 103*6f12ebf6SStephen Warren } 104*6f12ebf6SStephen Warren 105*6f12ebf6SStephen Warren int dfu_fill_entity_sf(struct dfu_entity *dfu, char *devstr, char *s) 106*6f12ebf6SStephen Warren { 107*6f12ebf6SStephen Warren char *st; 108*6f12ebf6SStephen Warren 109*6f12ebf6SStephen Warren dfu->data.sf.dev = parse_dev(devstr); 110*6f12ebf6SStephen Warren if (!dfu->data.sf.dev) 111*6f12ebf6SStephen Warren return -ENODEV; 112*6f12ebf6SStephen Warren 113*6f12ebf6SStephen Warren dfu->dev_type = DFU_DEV_SF; 114*6f12ebf6SStephen Warren dfu->max_buf_size = dfu->data.sf.dev->sector_size; 115*6f12ebf6SStephen Warren 116*6f12ebf6SStephen Warren st = strsep(&s, " "); 117*6f12ebf6SStephen Warren if (!strcmp(st, "raw")) { 118*6f12ebf6SStephen Warren dfu->layout = DFU_RAW_ADDR; 119*6f12ebf6SStephen Warren dfu->data.sf.start = simple_strtoul(s, &s, 16); 120*6f12ebf6SStephen Warren s++; 121*6f12ebf6SStephen Warren dfu->data.sf.size = simple_strtoul(s, &s, 16); 122*6f12ebf6SStephen Warren } else { 123*6f12ebf6SStephen Warren printf("%s: Memory layout (%s) not supported!\n", __func__, st); 124*6f12ebf6SStephen Warren spi_flash_free(dfu->data.sf.dev); 125*6f12ebf6SStephen Warren return -1; 126*6f12ebf6SStephen Warren } 127*6f12ebf6SStephen Warren 128*6f12ebf6SStephen Warren dfu->get_medium_size = dfu_get_medium_size_sf; 129*6f12ebf6SStephen Warren dfu->read_medium = dfu_read_medium_sf; 130*6f12ebf6SStephen Warren dfu->write_medium = dfu_write_medium_sf; 131*6f12ebf6SStephen Warren dfu->flush_medium = dfu_flush_medium_sf; 132*6f12ebf6SStephen Warren dfu->poll_timeout = dfu_polltimeout_sf; 133*6f12ebf6SStephen Warren dfu->free_entity = dfu_free_entity_sf; 134*6f12ebf6SStephen Warren 135*6f12ebf6SStephen Warren /* initial state */ 136*6f12ebf6SStephen Warren dfu->inited = 0; 137*6f12ebf6SStephen Warren 138*6f12ebf6SStephen Warren return 0; 139*6f12ebf6SStephen Warren } 140