]>
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 | ||
2727f3bf FE |
26 | static u64 find_sector(struct dfu_entity *dfu, u64 start, u64 offset) |
27 | { | |
28 | return (lldiv((start + offset), dfu->data.sf.dev->sector_size)) * | |
29 | dfu->data.sf.dev->sector_size; | |
30 | } | |
31 | ||
6f12ebf6 SW |
32 | static int dfu_write_medium_sf(struct dfu_entity *dfu, |
33 | u64 offset, void *buf, long *len) | |
34 | { | |
35 | int ret; | |
36 | ||
2727f3bf FE |
37 | ret = spi_flash_erase(dfu->data.sf.dev, |
38 | find_sector(dfu, dfu->data.sf.start, offset), | |
f4c92582 | 39 | dfu->data.sf.dev->sector_size); |
6f12ebf6 SW |
40 | if (ret) |
41 | return ret; | |
42 | ||
2727f3bf FE |
43 | ret = spi_flash_write(dfu->data.sf.dev, dfu->data.sf.start + offset, |
44 | *len, buf); | |
6f12ebf6 SW |
45 | if (ret) |
46 | return ret; | |
47 | ||
48 | return 0; | |
49 | } | |
50 | ||
51 | static int dfu_flush_medium_sf(struct dfu_entity *dfu) | |
52 | { | |
53 | return 0; | |
54 | } | |
55 | ||
56 | static unsigned int dfu_polltimeout_sf(struct dfu_entity *dfu) | |
57 | { | |
58 | return DFU_DEFAULT_POLL_TIMEOUT; | |
59 | } | |
60 | ||
61 | static void dfu_free_entity_sf(struct dfu_entity *dfu) | |
62 | { | |
63 | spi_flash_free(dfu->data.sf.dev); | |
64 | } | |
65 | ||
66 | static struct spi_flash *parse_dev(char *devstr) | |
67 | { | |
68 | unsigned int bus; | |
69 | unsigned int cs; | |
70 | unsigned int speed = CONFIG_SF_DEFAULT_SPEED; | |
71 | unsigned int mode = CONFIG_SF_DEFAULT_MODE; | |
72 | char *s, *endp; | |
73 | struct spi_flash *dev; | |
74 | ||
75 | s = strsep(&devstr, ":"); | |
76 | if (!s || !*s || (bus = simple_strtoul(s, &endp, 0), *endp)) { | |
77 | printf("Invalid SPI bus %s\n", s); | |
78 | return NULL; | |
79 | } | |
80 | ||
81 | s = strsep(&devstr, ":"); | |
82 | if (!s || !*s || (cs = simple_strtoul(s, &endp, 0), *endp)) { | |
83 | printf("Invalid SPI chip-select %s\n", s); | |
84 | return NULL; | |
85 | } | |
86 | ||
87 | s = strsep(&devstr, ":"); | |
88 | if (s && *s) { | |
89 | speed = simple_strtoul(s, &endp, 0); | |
90 | if (*endp || !speed) { | |
91 | printf("Invalid SPI speed %s\n", s); | |
92 | return NULL; | |
93 | } | |
94 | } | |
95 | ||
96 | s = strsep(&devstr, ":"); | |
97 | if (s && *s) { | |
98 | mode = simple_strtoul(s, &endp, 0); | |
99 | if (*endp || mode > 3) { | |
100 | printf("Invalid SPI mode %s\n", s); | |
101 | return NULL; | |
102 | } | |
103 | } | |
104 | ||
105 | dev = spi_flash_probe(bus, cs, speed, mode); | |
106 | if (!dev) { | |
107 | printf("Failed to create SPI flash at %d:%d:%d:%d\n", | |
108 | bus, cs, speed, mode); | |
109 | return NULL; | |
110 | } | |
111 | ||
112 | return dev; | |
113 | } | |
114 | ||
115 | int dfu_fill_entity_sf(struct dfu_entity *dfu, char *devstr, char *s) | |
116 | { | |
117 | char *st; | |
30e3ea4c | 118 | char *devstr_bkup = strdup(devstr); |
6f12ebf6 | 119 | |
30e3ea4c V |
120 | dfu->data.sf.dev = parse_dev(devstr_bkup); |
121 | free(devstr_bkup); | |
6f12ebf6 SW |
122 | if (!dfu->data.sf.dev) |
123 | return -ENODEV; | |
124 | ||
125 | dfu->dev_type = DFU_DEV_SF; | |
126 | dfu->max_buf_size = dfu->data.sf.dev->sector_size; | |
127 | ||
128 | st = strsep(&s, " "); | |
129 | if (!strcmp(st, "raw")) { | |
130 | dfu->layout = DFU_RAW_ADDR; | |
131 | dfu->data.sf.start = simple_strtoul(s, &s, 16); | |
132 | s++; | |
133 | dfu->data.sf.size = simple_strtoul(s, &s, 16); | |
134 | } else { | |
135 | printf("%s: Memory layout (%s) not supported!\n", __func__, st); | |
136 | spi_flash_free(dfu->data.sf.dev); | |
137 | return -1; | |
138 | } | |
139 | ||
140 | dfu->get_medium_size = dfu_get_medium_size_sf; | |
141 | dfu->read_medium = dfu_read_medium_sf; | |
142 | dfu->write_medium = dfu_write_medium_sf; | |
143 | dfu->flush_medium = dfu_flush_medium_sf; | |
144 | dfu->poll_timeout = dfu_polltimeout_sf; | |
145 | dfu->free_entity = dfu_free_entity_sf; | |
146 | ||
147 | /* initial state */ | |
148 | dfu->inited = 0; | |
149 | ||
150 | return 0; | |
151 | } |