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