]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
4c2dbefd SG |
2 | /* |
3 | * Copyright (c) 2014 Google, Inc | |
4c2dbefd SG |
4 | */ |
5 | ||
6 | #include <common.h> | |
7 | #include <dm.h> | |
336d4615 | 8 | #include <malloc.h> |
4c2dbefd SG |
9 | #include <spi.h> |
10 | #include <spi_flash.h> | |
11 | #include <dm/device-internal.h> | |
12 | #include "sf_internal.h" | |
13 | ||
2588f2dd MS |
14 | DECLARE_GLOBAL_DATA_PTR; |
15 | ||
8d987abc SG |
16 | int spi_flash_read_dm(struct udevice *dev, u32 offset, size_t len, void *buf) |
17 | { | |
5e24a2ef | 18 | return log_ret(sf_get_ops(dev)->read(dev, offset, len, buf)); |
8d987abc SG |
19 | } |
20 | ||
21 | int spi_flash_write_dm(struct udevice *dev, u32 offset, size_t len, | |
22 | const void *buf) | |
23 | { | |
5e24a2ef | 24 | return log_ret(sf_get_ops(dev)->write(dev, offset, len, buf)); |
8d987abc SG |
25 | } |
26 | ||
27 | int spi_flash_erase_dm(struct udevice *dev, u32 offset, size_t len) | |
28 | { | |
5e24a2ef | 29 | return log_ret(sf_get_ops(dev)->erase(dev, offset, len)); |
8d987abc SG |
30 | } |
31 | ||
a58986ca SG |
32 | int spl_flash_get_sw_write_prot(struct udevice *dev) |
33 | { | |
34 | struct dm_spi_flash_ops *ops = sf_get_ops(dev); | |
35 | ||
36 | if (!ops->get_sw_write_prot) | |
37 | return -ENOSYS; | |
38 | return log_ret(ops->get_sw_write_prot(dev)); | |
39 | } | |
40 | ||
4c2dbefd SG |
41 | /* |
42 | * TODO(sjg@chromium.org): This is an old-style function. We should remove | |
43 | * it when all SPI flash drivers use dm | |
44 | */ | |
45 | struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs, | |
46 | unsigned int max_hz, unsigned int spi_mode) | |
47 | { | |
48 | struct udevice *dev; | |
49 | ||
50 | if (spi_flash_probe_bus_cs(bus, cs, max_hz, spi_mode, &dev)) | |
51 | return NULL; | |
52 | ||
e564f054 | 53 | return dev_get_uclass_priv(dev); |
4c2dbefd SG |
54 | } |
55 | ||
56 | void spi_flash_free(struct spi_flash *flash) | |
57 | { | |
706865af | 58 | device_remove(flash->spi->dev, DM_REMOVE_NORMAL); |
4c2dbefd SG |
59 | } |
60 | ||
61 | int spi_flash_probe_bus_cs(unsigned int busnum, unsigned int cs, | |
62 | unsigned int max_hz, unsigned int spi_mode, | |
63 | struct udevice **devp) | |
64 | { | |
65 | struct spi_slave *slave; | |
66 | struct udevice *bus; | |
3c8fb12b | 67 | char *str; |
4c2dbefd SG |
68 | int ret; |
69 | ||
27084c03 | 70 | #if defined(CONFIG_SPL_BUILD) && CONFIG_IS_ENABLED(USE_TINY_PRINTF) |
3c8fb12b SG |
71 | str = "spi_flash"; |
72 | #else | |
73 | char name[30]; | |
74 | ||
a5e1bcde | 75 | snprintf(name, sizeof(name), "spi_flash@%d:%d", busnum, cs); |
4c2dbefd | 76 | str = strdup(name); |
3c8fb12b | 77 | #endif |
4c2dbefd SG |
78 | ret = spi_get_bus_and_cs(busnum, cs, max_hz, spi_mode, |
79 | "spi_flash_std", str, &bus, &slave); | |
80 | if (ret) | |
81 | return ret; | |
82 | ||
83 | *devp = slave->dev; | |
84 | return 0; | |
85 | } | |
86 | ||
2588f2dd MS |
87 | static int spi_flash_post_bind(struct udevice *dev) |
88 | { | |
89 | #if defined(CONFIG_NEEDS_MANUAL_RELOC) | |
90 | struct dm_spi_flash_ops *ops = sf_get_ops(dev); | |
91 | static int reloc_done; | |
92 | ||
93 | if (!reloc_done) { | |
94 | if (ops->read) | |
95 | ops->read += gd->reloc_off; | |
96 | if (ops->write) | |
97 | ops->write += gd->reloc_off; | |
98 | if (ops->erase) | |
99 | ops->erase += gd->reloc_off; | |
100 | ||
101 | reloc_done++; | |
102 | } | |
103 | #endif | |
104 | return 0; | |
105 | } | |
106 | ||
4c2dbefd SG |
107 | UCLASS_DRIVER(spi_flash) = { |
108 | .id = UCLASS_SPI_FLASH, | |
109 | .name = "spi_flash", | |
2588f2dd | 110 | .post_bind = spi_flash_post_bind, |
4c2dbefd SG |
111 | .per_device_auto_alloc_size = sizeof(struct spi_flash), |
112 | }; |