Blame view

drivers/dfu/dfu_sf.c 3.28 KB
6f12ebf6e   Stephen Warren   dfu: add SF backend
1
2
3
4
5
6
7
8
9
10
11
  /*
   * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
   *
   * SPDX-License-Identifier: GPL-2.0+
   */
  
  #include <common.h>
  #include <malloc.h>
  #include <errno.h>
  #include <div64.h>
  #include <dfu.h>
843c9e879   Simon Glass   dm: Add spi.h hea...
12
  #include <spi.h>
6f12ebf6e   Stephen Warren   dfu: add SF backend
13
  #include <spi_flash.h>
15970d871   Patrick Delaunay   dfu: remove limit...
14
  static int dfu_get_medium_size_sf(struct dfu_entity *dfu, u64 *size)
6f12ebf6e   Stephen Warren   dfu: add SF backend
15
  {
4de512018   Patrick Delaunay   dfu: allow dfu re...
16
17
18
  	*size = dfu->data.sf.size;
  
  	return 0;
6f12ebf6e   Stephen Warren   dfu: add SF backend
19
20
21
22
23
  }
  
  static int dfu_read_medium_sf(struct dfu_entity *dfu, u64 offset, void *buf,
  		long *len)
  {
e5f00f018   Phil Edworthy   dfu: dfu_sf: Fix ...
24
25
  	return spi_flash_read(dfu->data.sf.dev, dfu->data.sf.start + offset,
  		*len, buf);
6f12ebf6e   Stephen Warren   dfu: add SF backend
26
  }
2727f3bfb   Fabio Estevam   dfu: dfu_sf: Take...
27
28
29
30
31
  static u64 find_sector(struct dfu_entity *dfu, u64 start, u64 offset)
  {
  	return (lldiv((start + offset), dfu->data.sf.dev->sector_size)) *
  		dfu->data.sf.dev->sector_size;
  }
6f12ebf6e   Stephen Warren   dfu: add SF backend
32
33
34
35
  static int dfu_write_medium_sf(struct dfu_entity *dfu,
  		u64 offset, void *buf, long *len)
  {
  	int ret;
2727f3bfb   Fabio Estevam   dfu: dfu_sf: Take...
36
37
  	ret = spi_flash_erase(dfu->data.sf.dev,
  			      find_sector(dfu, dfu->data.sf.start, offset),
f4c925821   Fabio Estevam   dfu: dfu_sf: Use ...
38
  			      dfu->data.sf.dev->sector_size);
6f12ebf6e   Stephen Warren   dfu: add SF backend
39
40
  	if (ret)
  		return ret;
2727f3bfb   Fabio Estevam   dfu: dfu_sf: Take...
41
42
  	ret = spi_flash_write(dfu->data.sf.dev, dfu->data.sf.start + offset,
  			      *len, buf);
6f12ebf6e   Stephen Warren   dfu: add SF backend
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
  	if (ret)
  		return ret;
  
  	return 0;
  }
  
  static int dfu_flush_medium_sf(struct dfu_entity *dfu)
  {
  	return 0;
  }
  
  static unsigned int dfu_polltimeout_sf(struct dfu_entity *dfu)
  {
  	return DFU_DEFAULT_POLL_TIMEOUT;
  }
  
  static void dfu_free_entity_sf(struct dfu_entity *dfu)
  {
  	spi_flash_free(dfu->data.sf.dev);
  }
  
  static struct spi_flash *parse_dev(char *devstr)
  {
  	unsigned int bus;
  	unsigned int cs;
  	unsigned int speed = CONFIG_SF_DEFAULT_SPEED;
  	unsigned int mode = CONFIG_SF_DEFAULT_MODE;
  	char *s, *endp;
  	struct spi_flash *dev;
  
  	s = strsep(&devstr, ":");
  	if (!s || !*s || (bus = simple_strtoul(s, &endp, 0), *endp)) {
  		printf("Invalid SPI bus %s
  ", s);
  		return NULL;
  	}
  
  	s = strsep(&devstr, ":");
  	if (!s || !*s || (cs = simple_strtoul(s, &endp, 0), *endp)) {
  		printf("Invalid SPI chip-select %s
  ", s);
  		return NULL;
  	}
  
  	s = strsep(&devstr, ":");
  	if (s && *s) {
  		speed = simple_strtoul(s, &endp, 0);
  		if (*endp || !speed) {
  			printf("Invalid SPI speed %s
  ", s);
  			return NULL;
  		}
  	}
  
  	s = strsep(&devstr, ":");
  	if (s && *s) {
  		mode = simple_strtoul(s, &endp, 0);
  		if (*endp || mode > 3) {
  			printf("Invalid SPI mode %s
  ", s);
  			return NULL;
  		}
  	}
  
  	dev = spi_flash_probe(bus, cs, speed, mode);
  	if (!dev) {
  		printf("Failed to create SPI flash at %d:%d:%d:%d
  ",
  		       bus, cs, speed, mode);
  		return NULL;
  	}
  
  	return dev;
  }
  
  int dfu_fill_entity_sf(struct dfu_entity *dfu, char *devstr, char *s)
  {
  	char *st;
30e3ea4c7   Vignesh R   dfu: dfu_sf: Pass...
121
  	char *devstr_bkup = strdup(devstr);
6f12ebf6e   Stephen Warren   dfu: add SF backend
122

30e3ea4c7   Vignesh R   dfu: dfu_sf: Pass...
123
124
  	dfu->data.sf.dev = parse_dev(devstr_bkup);
  	free(devstr_bkup);
6f12ebf6e   Stephen Warren   dfu: add SF backend
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
  	if (!dfu->data.sf.dev)
  		return -ENODEV;
  
  	dfu->dev_type = DFU_DEV_SF;
  	dfu->max_buf_size = dfu->data.sf.dev->sector_size;
  
  	st = strsep(&s, " ");
  	if (!strcmp(st, "raw")) {
  		dfu->layout = DFU_RAW_ADDR;
  		dfu->data.sf.start = simple_strtoul(s, &s, 16);
  		s++;
  		dfu->data.sf.size = simple_strtoul(s, &s, 16);
  	} else {
  		printf("%s: Memory layout (%s) not supported!
  ", __func__, st);
  		spi_flash_free(dfu->data.sf.dev);
  		return -1;
  	}
  
  	dfu->get_medium_size = dfu_get_medium_size_sf;
  	dfu->read_medium = dfu_read_medium_sf;
  	dfu->write_medium = dfu_write_medium_sf;
  	dfu->flush_medium = dfu_flush_medium_sf;
  	dfu->poll_timeout = dfu_polltimeout_sf;
  	dfu->free_entity = dfu_free_entity_sf;
  
  	/* initial state */
  	dfu->inited = 0;
  
  	return 0;
  }