xref: /rk3399_rockchip-uboot/drivers/dfu/dfu_sf.c (revision 6f12ebf6ea7bcae1b6d9ff090b5c1e7452be90e9)
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