xref: /rk3399_rockchip-uboot/drivers/mtd/spi/sf_probe.c (revision 951aa503aa95ecb9b51cf56f3ea349070264a0a9)
1898e76c9SJagannadha Sutradharudu Teki /*
2898e76c9SJagannadha Sutradharudu Teki  * SPI flash probing
3898e76c9SJagannadha Sutradharudu Teki  *
4898e76c9SJagannadha Sutradharudu Teki  * Copyright (C) 2008 Atmel Corporation
5898e76c9SJagannadha Sutradharudu Teki  * Copyright (C) 2010 Reinhard Meyer, EMK Elektronik
6898e76c9SJagannadha Sutradharudu Teki  * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc.
7898e76c9SJagannadha Sutradharudu Teki  *
80c88a84aSJagannadha Sutradharudu Teki  * SPDX-License-Identifier:	GPL-2.0+
9898e76c9SJagannadha Sutradharudu Teki  */
10898e76c9SJagannadha Sutradharudu Teki 
11898e76c9SJagannadha Sutradharudu Teki #include <common.h>
12a5ce032fSJason Zhu #include <blk.h>
13fbb09918SSimon Glass #include <dm.h>
14ae242cbfSSimon Glass #include <errno.h>
15898e76c9SJagannadha Sutradharudu Teki #include <malloc.h>
16898e76c9SJagannadha Sutradharudu Teki #include <spi.h>
17898e76c9SJagannadha Sutradharudu Teki #include <spi_flash.h>
18898e76c9SJagannadha Sutradharudu Teki 
19898e76c9SJagannadha Sutradharudu Teki #include "sf_internal.h"
20898e76c9SJagannadha Sutradharudu Teki 
21ae242cbfSSimon Glass /**
22ae242cbfSSimon Glass  * spi_flash_probe_slave() - Probe for a SPI flash device on a bus
23ae242cbfSSimon Glass  *
24ae242cbfSSimon Glass  * @flashp: Pointer to place to put flash info, which may be NULL if the
25ae242cbfSSimon Glass  * space should be allocated
26ae242cbfSSimon Glass  */
spi_flash_probe_slave(struct spi_flash * flash)27339fd6dcSJagan Teki static int spi_flash_probe_slave(struct spi_flash *flash)
28898e76c9SJagannadha Sutradharudu Teki {
29bfdb07ebSJagan Teki 	struct spi_slave *spi = flash->spi;
30898e76c9SJagannadha Sutradharudu Teki 	int ret;
31898e76c9SJagannadha Sutradharudu Teki 
32898e76c9SJagannadha Sutradharudu Teki 	/* Setup spi_slave */
33898e76c9SJagannadha Sutradharudu Teki 	if (!spi) {
34898e76c9SJagannadha Sutradharudu Teki 		printf("SF: Failed to set up slave\n");
35ae242cbfSSimon Glass 		return -ENODEV;
36898e76c9SJagannadha Sutradharudu Teki 	}
37898e76c9SJagannadha Sutradharudu Teki 
38898e76c9SJagannadha Sutradharudu Teki 	/* Claim spi bus */
39898e76c9SJagannadha Sutradharudu Teki 	ret = spi_claim_bus(spi);
40898e76c9SJagannadha Sutradharudu Teki 	if (ret) {
41898e76c9SJagannadha Sutradharudu Teki 		debug("SF: Failed to claim SPI bus: %d\n", ret);
42ae242cbfSSimon Glass 		return ret;
43898e76c9SJagannadha Sutradharudu Teki 	}
44898e76c9SJagannadha Sutradharudu Teki 
45*951aa503SJon Lin #if !CONFIG_IS_ENABLED(SPI_FLASH_TINY)
46*951aa503SJon Lin 	flash->mtd.name = (char *)ofnode_read_string(spi->dev->node, "label");
47*951aa503SJon Lin #endif
48*951aa503SJon Lin 
49f2313133SVignesh R 	ret = spi_nor_scan(flash);
500badb23dSSimon Glass 	if (ret)
51898e76c9SJagannadha Sutradharudu Teki 		goto err_read_id;
52898e76c9SJagannadha Sutradharudu Teki 
539fe6d871SDaniel Schwierzeck #ifdef CONFIG_SPI_FLASH_MTD
549fe6d871SDaniel Schwierzeck 	ret = spi_flash_mtd_register(flash);
559fe6d871SDaniel Schwierzeck #endif
56898e76c9SJagannadha Sutradharudu Teki 
57898e76c9SJagannadha Sutradharudu Teki err_read_id:
58898e76c9SJagannadha Sutradharudu Teki 	spi_release_bus(spi);
59ae242cbfSSimon Glass 	return ret;
60ae242cbfSSimon Glass }
61ae242cbfSSimon Glass 
62fbb09918SSimon Glass #ifndef CONFIG_DM_SPI_FLASH
spi_flash_probe(unsigned int busnum,unsigned int cs,unsigned int max_hz,unsigned int spi_mode)638a91194bSMario Six struct spi_flash *spi_flash_probe(unsigned int busnum, unsigned int cs,
648a91194bSMario Six 				  unsigned int max_hz, unsigned int spi_mode)
65ae242cbfSSimon Glass {
668a91194bSMario Six 	struct spi_slave *bus;
67ae242cbfSSimon Glass 	struct spi_flash *flash;
68ae242cbfSSimon Glass 
698a91194bSMario Six 	bus = spi_setup_slave(busnum, cs, max_hz, spi_mode);
708a91194bSMario Six 	if (!bus)
718a91194bSMario Six 		return NULL;
728a91194bSMario Six 
73ae242cbfSSimon Glass 	/* Allocate space if needed (not used by sf-uclass */
74ae242cbfSSimon Glass 	flash = calloc(1, sizeof(*flash));
75ae242cbfSSimon Glass 	if (!flash) {
76ae242cbfSSimon Glass 		debug("SF: Failed to allocate spi_flash\n");
77898e76c9SJagannadha Sutradharudu Teki 		return NULL;
78898e76c9SJagannadha Sutradharudu Teki 	}
79898e76c9SJagannadha Sutradharudu Teki 
80bfdb07ebSJagan Teki 	flash->spi = bus;
81bfdb07ebSJagan Teki 	if (spi_flash_probe_slave(flash)) {
82ae242cbfSSimon Glass 		spi_free_slave(bus);
83ae242cbfSSimon Glass 		free(flash);
84ae242cbfSSimon Glass 		return NULL;
85ae242cbfSSimon Glass 	}
86ae242cbfSSimon Glass 
87ae242cbfSSimon Glass 	return flash;
88ae242cbfSSimon Glass }
89ae242cbfSSimon Glass 
spi_flash_free(struct spi_flash * flash)90898e76c9SJagannadha Sutradharudu Teki void spi_flash_free(struct spi_flash *flash)
91898e76c9SJagannadha Sutradharudu Teki {
929fe6d871SDaniel Schwierzeck #ifdef CONFIG_SPI_FLASH_MTD
939fe6d871SDaniel Schwierzeck 	spi_flash_mtd_unregister();
949fe6d871SDaniel Schwierzeck #endif
95898e76c9SJagannadha Sutradharudu Teki 	spi_free_slave(flash->spi);
96898e76c9SJagannadha Sutradharudu Teki 	free(flash);
97898e76c9SJagannadha Sutradharudu Teki }
98fbb09918SSimon Glass 
99fbb09918SSimon Glass #else /* defined CONFIG_DM_SPI_FLASH */
100fbb09918SSimon Glass 
spi_flash_std_read(struct udevice * dev,u32 offset,size_t len,void * buf)101fbb09918SSimon Glass static int spi_flash_std_read(struct udevice *dev, u32 offset, size_t len,
102fbb09918SSimon Glass 			      void *buf)
103fbb09918SSimon Glass {
104e564f054SSimon Glass 	struct spi_flash *flash = dev_get_uclass_priv(dev);
105f2313133SVignesh R 	struct mtd_info *mtd = &flash->mtd;
106f2313133SVignesh R 	size_t retlen;
107fbb09918SSimon Glass 
108f2313133SVignesh R 	return log_ret(mtd->_read(mtd, offset, len, &retlen, buf));
109fbb09918SSimon Glass }
110fbb09918SSimon Glass 
spi_flash_std_write(struct udevice * dev,u32 offset,size_t len,const void * buf)111339fd6dcSJagan Teki static int spi_flash_std_write(struct udevice *dev, u32 offset, size_t len,
112fbb09918SSimon Glass 			       const void *buf)
113fbb09918SSimon Glass {
114e564f054SSimon Glass 	struct spi_flash *flash = dev_get_uclass_priv(dev);
115f2313133SVignesh R 	struct mtd_info *mtd = &flash->mtd;
116f2313133SVignesh R 	size_t retlen;
117fbb09918SSimon Glass 
118f2313133SVignesh R 	return mtd->_write(mtd, offset, len, &retlen, buf);
119fbb09918SSimon Glass }
120fbb09918SSimon Glass 
spi_flash_std_erase(struct udevice * dev,u32 offset,size_t len)121339fd6dcSJagan Teki static int spi_flash_std_erase(struct udevice *dev, u32 offset, size_t len)
122fbb09918SSimon Glass {
123e564f054SSimon Glass 	struct spi_flash *flash = dev_get_uclass_priv(dev);
124f2313133SVignesh R 	struct mtd_info *mtd = &flash->mtd;
125f2313133SVignesh R 	struct erase_info instr;
126fbb09918SSimon Glass 
127f2313133SVignesh R 	if (offset % mtd->erasesize || len % mtd->erasesize) {
128f2313133SVignesh R 		printf("SF: Erase offset/length not multiple of erase size\n");
129f2313133SVignesh R 		return -EINVAL;
130f2313133SVignesh R 	}
131f2313133SVignesh R 
132f2313133SVignesh R 	memset(&instr, 0, sizeof(instr));
133f2313133SVignesh R 	instr.addr = offset;
134f2313133SVignesh R 	instr.len = len;
135f2313133SVignesh R 
136f2313133SVignesh R 	return mtd->_erase(mtd, &instr);
137fbb09918SSimon Glass }
138fbb09918SSimon Glass 
spi_flash_std_get_sw_write_prot(struct udevice * dev)139b6e92505SSimon Glass static int spi_flash_std_get_sw_write_prot(struct udevice *dev)
140b6e92505SSimon Glass {
141b6e92505SSimon Glass 	struct spi_flash *flash = dev_get_uclass_priv(dev);
142b6e92505SSimon Glass 
143b6e92505SSimon Glass 	return spi_flash_cmd_get_sw_write_prot(flash);
144b6e92505SSimon Glass }
145b6e92505SSimon Glass 
spi_flash_std_bind(struct udevice * udev)146a5ce032fSJason Zhu static int spi_flash_std_bind(struct udevice *udev)
147a5ce032fSJason Zhu {
148a5ce032fSJason Zhu 	int ret = 0;
149a5ce032fSJason Zhu 
150a5ce032fSJason Zhu #ifdef CONFIG_MTD_BLK
151a5ce032fSJason Zhu 	struct udevice *bdev;
152a5ce032fSJason Zhu 
153a5ce032fSJason Zhu 	ret = blk_create_devicef(udev, "mtd_blk", "blk", IF_TYPE_MTD,
154a5ce032fSJason Zhu 				 BLK_MTD_SPI_NOR, 512, 0, &bdev);
155a5ce032fSJason Zhu 	if (ret)
156a5ce032fSJason Zhu 		printf("Cannot create block device\n");
157a5ce032fSJason Zhu #endif
158a5ce032fSJason Zhu 	return ret;
159a5ce032fSJason Zhu }
160a5ce032fSJason Zhu 
spi_flash_std_probe(struct udevice * dev)161339fd6dcSJagan Teki static int spi_flash_std_probe(struct udevice *dev)
162fbb09918SSimon Glass {
163bcbe3d15SSimon Glass 	struct spi_slave *slave = dev_get_parent_priv(dev);
164d0cff03eSSimon Glass 	struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev);
165fbb09918SSimon Glass 	struct spi_flash *flash;
166fbb09918SSimon Glass 
167e564f054SSimon Glass 	flash = dev_get_uclass_priv(dev);
168fbb09918SSimon Glass 	flash->dev = dev;
169bfdb07ebSJagan Teki 	flash->spi = slave;
170d0cff03eSSimon Glass 	debug("%s: slave=%p, cs=%d\n", __func__, slave, plat->cs);
171bfdb07ebSJagan Teki 	return spi_flash_probe_slave(flash);
172fbb09918SSimon Glass }
173fbb09918SSimon Glass 
spi_flash_std_remove(struct udevice * dev)1742233bdccSBoris Brezillon static int spi_flash_std_remove(struct udevice *dev)
1752233bdccSBoris Brezillon {
1762233bdccSBoris Brezillon #ifdef CONFIG_SPI_FLASH_MTD
1772233bdccSBoris Brezillon 	spi_flash_mtd_unregister();
1782233bdccSBoris Brezillon #endif
1792233bdccSBoris Brezillon 	return 0;
1802233bdccSBoris Brezillon }
1812233bdccSBoris Brezillon 
182fbb09918SSimon Glass static const struct dm_spi_flash_ops spi_flash_std_ops = {
183fbb09918SSimon Glass 	.read = spi_flash_std_read,
184fbb09918SSimon Glass 	.write = spi_flash_std_write,
185fbb09918SSimon Glass 	.erase = spi_flash_std_erase,
186b6e92505SSimon Glass 	.get_sw_write_prot = spi_flash_std_get_sw_write_prot,
187fbb09918SSimon Glass };
188fbb09918SSimon Glass 
189fbb09918SSimon Glass static const struct udevice_id spi_flash_std_ids[] = {
190a1e428c2SVignesh R 	{ .compatible = "jedec,spi-nor" },
191fbb09918SSimon Glass 	{ }
192fbb09918SSimon Glass };
193fbb09918SSimon Glass 
194fbb09918SSimon Glass U_BOOT_DRIVER(spi_flash_std) = {
195fbb09918SSimon Glass 	.name		= "spi_flash_std",
196fbb09918SSimon Glass 	.id		= UCLASS_SPI_FLASH,
197fbb09918SSimon Glass 	.of_match	= spi_flash_std_ids,
198a5ce032fSJason Zhu 	.bind		= spi_flash_std_bind,
199fbb09918SSimon Glass 	.probe		= spi_flash_std_probe,
2002233bdccSBoris Brezillon 	.remove		= spi_flash_std_remove,
201fbb09918SSimon Glass 	.priv_auto_alloc_size = sizeof(struct spi_flash),
202fbb09918SSimon Glass 	.ops		= &spi_flash_std_ops,
203fbb09918SSimon Glass };
204fbb09918SSimon Glass 
205fbb09918SSimon Glass #endif /* CONFIG_DM_SPI_FLASH */
206