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