]>
Commit | Line | Data |
---|---|---|
4d5e29a6 JT |
1 | /* |
2 | * SPI flash probing | |
3 | * | |
4 | * Copyright (C) 2008 Atmel Corporation | |
5 | * Copyright (C) 2010 Reinhard Meyer, EMK Elektronik | |
6 | * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc. | |
7 | * | |
0c88a84a | 8 | * SPDX-License-Identifier: GPL-2.0+ |
4d5e29a6 JT |
9 | */ |
10 | ||
11 | #include <common.h> | |
fbb09918 | 12 | #include <dm.h> |
ae242cbf | 13 | #include <errno.h> |
4d5e29a6 JT |
14 | #include <malloc.h> |
15 | #include <spi.h> | |
16 | #include <spi_flash.h> | |
17 | ||
898e76c9 | 18 | #include "sf_internal.h" |
4d5e29a6 | 19 | |
ae242cbf SG |
20 | /** |
21 | * spi_flash_probe_slave() - Probe for a SPI flash device on a bus | |
22 | * | |
ae242cbf SG |
23 | * @flashp: Pointer to place to put flash info, which may be NULL if the |
24 | * space should be allocated | |
25 | */ | |
bfdb07eb | 26 | int spi_flash_probe_slave(struct spi_flash *flash) |
4d5e29a6 | 27 | { |
bfdb07eb | 28 | struct spi_slave *spi = flash->spi; |
4d4ec992 | 29 | int ret; |
4d5e29a6 | 30 | |
4d4ec992 | 31 | /* Setup spi_slave */ |
4d5e29a6 JT |
32 | if (!spi) { |
33 | printf("SF: Failed to set up slave\n"); | |
ae242cbf | 34 | return -ENODEV; |
4d5e29a6 JT |
35 | } |
36 | ||
4d4ec992 | 37 | /* Claim spi bus */ |
4d5e29a6 JT |
38 | ret = spi_claim_bus(spi); |
39 | if (ret) { | |
40 | debug("SF: Failed to claim SPI bus: %d\n", ret); | |
ae242cbf | 41 | return ret; |
4d5e29a6 JT |
42 | } |
43 | ||
bfdb07eb | 44 | ret = spi_flash_scan(flash); |
3a1adb62 | 45 | if (ret) { |
ae242cbf | 46 | ret = -EINVAL; |
4d4ec992 | 47 | goto err_read_id; |
ae242cbf | 48 | } |
4d5e29a6 | 49 | |
9fe6d871 DS |
50 | #ifdef CONFIG_SPI_FLASH_MTD |
51 | ret = spi_flash_mtd_register(flash); | |
52 | #endif | |
4d5e29a6 | 53 | |
4d5e29a6 JT |
54 | err_read_id: |
55 | spi_release_bus(spi); | |
ae242cbf SG |
56 | return ret; |
57 | } | |
58 | ||
fbb09918 SG |
59 | #ifndef CONFIG_DM_SPI_FLASH |
60 | struct spi_flash *spi_flash_probe_tail(struct spi_slave *bus) | |
ae242cbf SG |
61 | { |
62 | struct spi_flash *flash; | |
63 | ||
64 | /* Allocate space if needed (not used by sf-uclass */ | |
65 | flash = calloc(1, sizeof(*flash)); | |
66 | if (!flash) { | |
67 | debug("SF: Failed to allocate spi_flash\n"); | |
68 | return NULL; | |
69 | } | |
70 | ||
bfdb07eb JT |
71 | flash->spi = bus; |
72 | if (spi_flash_probe_slave(flash)) { | |
ae242cbf SG |
73 | spi_free_slave(bus); |
74 | free(flash); | |
75 | return NULL; | |
76 | } | |
77 | ||
78 | return flash; | |
4d5e29a6 JT |
79 | } |
80 | ||
ae242cbf | 81 | struct spi_flash *spi_flash_probe(unsigned int busnum, unsigned int cs, |
0efc0249 SG |
82 | unsigned int max_hz, unsigned int spi_mode) |
83 | { | |
ae242cbf | 84 | struct spi_slave *bus; |
0efc0249 | 85 | |
ae242cbf | 86 | bus = spi_setup_slave(busnum, cs, max_hz, spi_mode); |
4fbad92e PF |
87 | if (!bus) |
88 | return NULL; | |
ae242cbf | 89 | return spi_flash_probe_tail(bus); |
0efc0249 SG |
90 | } |
91 | ||
92 | #ifdef CONFIG_OF_SPI_FLASH | |
93 | struct spi_flash *spi_flash_probe_fdt(const void *blob, int slave_node, | |
94 | int spi_node) | |
95 | { | |
ae242cbf | 96 | struct spi_slave *bus; |
0efc0249 | 97 | |
ae242cbf | 98 | bus = spi_setup_slave_fdt(blob, slave_node, spi_node); |
4fbad92e PF |
99 | if (!bus) |
100 | return NULL; | |
ae242cbf | 101 | return spi_flash_probe_tail(bus); |
0efc0249 SG |
102 | } |
103 | #endif | |
104 | ||
4d5e29a6 JT |
105 | void spi_flash_free(struct spi_flash *flash) |
106 | { | |
9fe6d871 DS |
107 | #ifdef CONFIG_SPI_FLASH_MTD |
108 | spi_flash_mtd_unregister(); | |
109 | #endif | |
4d5e29a6 JT |
110 | spi_free_slave(flash->spi); |
111 | free(flash); | |
112 | } | |
fbb09918 SG |
113 | |
114 | #else /* defined CONFIG_DM_SPI_FLASH */ | |
115 | ||
116 | static int spi_flash_std_read(struct udevice *dev, u32 offset, size_t len, | |
117 | void *buf) | |
118 | { | |
e564f054 | 119 | struct spi_flash *flash = dev_get_uclass_priv(dev); |
fbb09918 SG |
120 | |
121 | return spi_flash_cmd_read_ops(flash, offset, len, buf); | |
122 | } | |
123 | ||
124 | int spi_flash_std_write(struct udevice *dev, u32 offset, size_t len, | |
125 | const void *buf) | |
126 | { | |
e564f054 | 127 | struct spi_flash *flash = dev_get_uclass_priv(dev); |
fbb09918 | 128 | |
074eed51 | 129 | #if defined(CONFIG_SPI_FLASH_SST) |
1fabefdd | 130 | if (flash->flags & SNOR_F_SST_WR) { |
074eed51 BM |
131 | if (flash->spi->op_mode_tx & SPI_OPM_TX_BP) |
132 | return sst_write_bp(flash, offset, len, buf); | |
133 | else | |
134 | return sst_write_wp(flash, offset, len, buf); | |
135 | } | |
136 | #endif | |
137 | ||
fbb09918 SG |
138 | return spi_flash_cmd_write_ops(flash, offset, len, buf); |
139 | } | |
140 | ||
141 | int spi_flash_std_erase(struct udevice *dev, u32 offset, size_t len) | |
142 | { | |
e564f054 | 143 | struct spi_flash *flash = dev_get_uclass_priv(dev); |
fbb09918 SG |
144 | |
145 | return spi_flash_cmd_erase_ops(flash, offset, len); | |
146 | } | |
147 | ||
148 | int spi_flash_std_probe(struct udevice *dev) | |
149 | { | |
bcbe3d15 | 150 | struct spi_slave *slave = dev_get_parent_priv(dev); |
d0cff03e | 151 | struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev); |
fbb09918 SG |
152 | struct spi_flash *flash; |
153 | ||
e564f054 | 154 | flash = dev_get_uclass_priv(dev); |
fbb09918 | 155 | flash->dev = dev; |
bfdb07eb | 156 | flash->spi = slave; |
d0cff03e | 157 | debug("%s: slave=%p, cs=%d\n", __func__, slave, plat->cs); |
bfdb07eb | 158 | return spi_flash_probe_slave(flash); |
fbb09918 SG |
159 | } |
160 | ||
161 | static const struct dm_spi_flash_ops spi_flash_std_ops = { | |
162 | .read = spi_flash_std_read, | |
163 | .write = spi_flash_std_write, | |
164 | .erase = spi_flash_std_erase, | |
165 | }; | |
166 | ||
167 | static const struct udevice_id spi_flash_std_ids[] = { | |
168 | { .compatible = "spi-flash" }, | |
169 | { } | |
170 | }; | |
171 | ||
172 | U_BOOT_DRIVER(spi_flash_std) = { | |
173 | .name = "spi_flash_std", | |
174 | .id = UCLASS_SPI_FLASH, | |
175 | .of_match = spi_flash_std_ids, | |
176 | .probe = spi_flash_std_probe, | |
177 | .priv_auto_alloc_size = sizeof(struct spi_flash), | |
178 | .ops = &spi_flash_std_ops, | |
179 | }; | |
180 | ||
181 | #endif /* CONFIG_DM_SPI_FLASH */ |