xref: /rk3399_rockchip-uboot/drivers/block/blk-uclass.c (revision e40cf34a29f1b248643731a11fb1c6f0520d016c)
109d71aacSSimon Glass /*
209d71aacSSimon Glass  * Copyright (C) 2016 Google, Inc
309d71aacSSimon Glass  * Written by Simon Glass <sjg@chromium.org>
409d71aacSSimon Glass  *
509d71aacSSimon Glass  * SPDX-License-Identifier:	GPL-2.0+
609d71aacSSimon Glass  */
709d71aacSSimon Glass 
809d71aacSSimon Glass #include <common.h>
909d71aacSSimon Glass #include <blk.h>
1009d71aacSSimon Glass #include <dm.h>
1109d71aacSSimon Glass #include <dm/device-internal.h>
1209d71aacSSimon Glass #include <dm/lists.h>
1309d71aacSSimon Glass 
1409d71aacSSimon Glass int blk_first_device(int if_type, struct udevice **devp)
1509d71aacSSimon Glass {
1609d71aacSSimon Glass 	struct blk_desc *desc;
1709d71aacSSimon Glass 	int ret;
1809d71aacSSimon Glass 
1909d71aacSSimon Glass 	ret = uclass_first_device(UCLASS_BLK, devp);
2009d71aacSSimon Glass 	if (ret)
2109d71aacSSimon Glass 		return ret;
2209d71aacSSimon Glass 	if (!*devp)
2309d71aacSSimon Glass 		return -ENODEV;
2409d71aacSSimon Glass 	do {
2509d71aacSSimon Glass 		desc = dev_get_uclass_platdata(*devp);
2609d71aacSSimon Glass 		if (desc->if_type == if_type)
2709d71aacSSimon Glass 			return 0;
2809d71aacSSimon Glass 		ret = uclass_next_device(devp);
2909d71aacSSimon Glass 		if (ret)
3009d71aacSSimon Glass 			return ret;
3109d71aacSSimon Glass 	} while (*devp);
3209d71aacSSimon Glass 
3309d71aacSSimon Glass 	return -ENODEV;
3409d71aacSSimon Glass }
3509d71aacSSimon Glass 
3609d71aacSSimon Glass int blk_next_device(struct udevice **devp)
3709d71aacSSimon Glass {
3809d71aacSSimon Glass 	struct blk_desc *desc;
3909d71aacSSimon Glass 	int ret, if_type;
4009d71aacSSimon Glass 
4109d71aacSSimon Glass 	desc = dev_get_uclass_platdata(*devp);
4209d71aacSSimon Glass 	if_type = desc->if_type;
4309d71aacSSimon Glass 	do {
4409d71aacSSimon Glass 		ret = uclass_next_device(devp);
4509d71aacSSimon Glass 		if (ret)
4609d71aacSSimon Glass 			return ret;
4709d71aacSSimon Glass 		if (!*devp)
4809d71aacSSimon Glass 			return -ENODEV;
4909d71aacSSimon Glass 		desc = dev_get_uclass_platdata(*devp);
5009d71aacSSimon Glass 		if (desc->if_type == if_type)
5109d71aacSSimon Glass 			return 0;
5209d71aacSSimon Glass 	} while (1);
5309d71aacSSimon Glass }
5409d71aacSSimon Glass 
5509d71aacSSimon Glass int blk_get_device(int if_type, int devnum, struct udevice **devp)
5609d71aacSSimon Glass {
5709d71aacSSimon Glass 	struct uclass *uc;
5809d71aacSSimon Glass 	struct udevice *dev;
5909d71aacSSimon Glass 	int ret;
6009d71aacSSimon Glass 
6109d71aacSSimon Glass 	ret = uclass_get(UCLASS_BLK, &uc);
6209d71aacSSimon Glass 	if (ret)
6309d71aacSSimon Glass 		return ret;
6409d71aacSSimon Glass 	uclass_foreach_dev(dev, uc) {
6509d71aacSSimon Glass 		struct blk_desc *desc = dev_get_uclass_platdata(dev);
6609d71aacSSimon Glass 
6709d71aacSSimon Glass 		debug("%s: if_type=%d, devnum=%d: %s, %d, %d\n", __func__,
6809d71aacSSimon Glass 		      if_type, devnum, dev->name, desc->if_type, desc->devnum);
6909d71aacSSimon Glass 		if (desc->if_type == if_type && desc->devnum == devnum) {
7009d71aacSSimon Glass 			*devp = dev;
7109d71aacSSimon Glass 			return device_probe(dev);
7209d71aacSSimon Glass 		}
7309d71aacSSimon Glass 	}
7409d71aacSSimon Glass 
7509d71aacSSimon Glass 	return -ENODEV;
7609d71aacSSimon Glass }
7709d71aacSSimon Glass 
7809d71aacSSimon Glass unsigned long blk_dread(struct blk_desc *block_dev, lbaint_t start,
7909d71aacSSimon Glass 			lbaint_t blkcnt, void *buffer)
8009d71aacSSimon Glass {
8109d71aacSSimon Glass 	struct udevice *dev = block_dev->bdev;
8209d71aacSSimon Glass 	const struct blk_ops *ops = blk_get_ops(dev);
83*e40cf34aSEric Nelson 	ulong blks_read;
8409d71aacSSimon Glass 
8509d71aacSSimon Glass 	if (!ops->read)
8609d71aacSSimon Glass 		return -ENOSYS;
8709d71aacSSimon Glass 
88*e40cf34aSEric Nelson 	if (blkcache_read(block_dev->if_type, block_dev->devnum,
89*e40cf34aSEric Nelson 			  start, blkcnt, block_dev->blksz, buffer))
90*e40cf34aSEric Nelson 		return blkcnt;
91*e40cf34aSEric Nelson 	blks_read = ops->read(dev, start, blkcnt, buffer);
92*e40cf34aSEric Nelson 	if (blks_read == blkcnt)
93*e40cf34aSEric Nelson 		blkcache_fill(block_dev->if_type, block_dev->devnum,
94*e40cf34aSEric Nelson 			      start, blkcnt, block_dev->blksz, buffer);
95*e40cf34aSEric Nelson 
96*e40cf34aSEric Nelson 	return blks_read;
9709d71aacSSimon Glass }
9809d71aacSSimon Glass 
9909d71aacSSimon Glass unsigned long blk_dwrite(struct blk_desc *block_dev, lbaint_t start,
10009d71aacSSimon Glass 			 lbaint_t blkcnt, const void *buffer)
10109d71aacSSimon Glass {
10209d71aacSSimon Glass 	struct udevice *dev = block_dev->bdev;
10309d71aacSSimon Glass 	const struct blk_ops *ops = blk_get_ops(dev);
10409d71aacSSimon Glass 
10509d71aacSSimon Glass 	if (!ops->write)
10609d71aacSSimon Glass 		return -ENOSYS;
10709d71aacSSimon Glass 
108*e40cf34aSEric Nelson 	blkcache_invalidate(block_dev->if_type, block_dev->devnum);
10909d71aacSSimon Glass 	return ops->write(dev, start, blkcnt, buffer);
11009d71aacSSimon Glass }
11109d71aacSSimon Glass 
11209d71aacSSimon Glass unsigned long blk_derase(struct blk_desc *block_dev, lbaint_t start,
11309d71aacSSimon Glass 			 lbaint_t blkcnt)
11409d71aacSSimon Glass {
11509d71aacSSimon Glass 	struct udevice *dev = block_dev->bdev;
11609d71aacSSimon Glass 	const struct blk_ops *ops = blk_get_ops(dev);
11709d71aacSSimon Glass 
11809d71aacSSimon Glass 	if (!ops->erase)
11909d71aacSSimon Glass 		return -ENOSYS;
12009d71aacSSimon Glass 
121*e40cf34aSEric Nelson 	blkcache_invalidate(block_dev->if_type, block_dev->devnum);
12209d71aacSSimon Glass 	return ops->erase(dev, start, blkcnt);
12309d71aacSSimon Glass }
12409d71aacSSimon Glass 
12509d71aacSSimon Glass int blk_prepare_device(struct udevice *dev)
12609d71aacSSimon Glass {
12709d71aacSSimon Glass 	struct blk_desc *desc = dev_get_uclass_platdata(dev);
12809d71aacSSimon Glass 
12909d71aacSSimon Glass 	part_init(desc);
13009d71aacSSimon Glass 
13109d71aacSSimon Glass 	return 0;
13209d71aacSSimon Glass }
13309d71aacSSimon Glass 
13409d71aacSSimon Glass int blk_create_device(struct udevice *parent, const char *drv_name,
13509d71aacSSimon Glass 		      const char *name, int if_type, int devnum, int blksz,
13609d71aacSSimon Glass 		      lbaint_t size, struct udevice **devp)
13709d71aacSSimon Glass {
13809d71aacSSimon Glass 	struct blk_desc *desc;
13909d71aacSSimon Glass 	struct udevice *dev;
14009d71aacSSimon Glass 	int ret;
14109d71aacSSimon Glass 
14209d71aacSSimon Glass 	ret = device_bind_driver(parent, drv_name, name, &dev);
14309d71aacSSimon Glass 	if (ret)
14409d71aacSSimon Glass 		return ret;
14509d71aacSSimon Glass 	desc = dev_get_uclass_platdata(dev);
14609d71aacSSimon Glass 	desc->if_type = if_type;
14709d71aacSSimon Glass 	desc->blksz = blksz;
14809d71aacSSimon Glass 	desc->lba = size / blksz;
14909d71aacSSimon Glass 	desc->part_type = PART_TYPE_UNKNOWN;
15009d71aacSSimon Glass 	desc->bdev = dev;
15109d71aacSSimon Glass 	desc->devnum = devnum;
15209d71aacSSimon Glass 	*devp = dev;
15309d71aacSSimon Glass 
15409d71aacSSimon Glass 	return 0;
15509d71aacSSimon Glass }
15609d71aacSSimon Glass 
15709d71aacSSimon Glass int blk_unbind_all(int if_type)
15809d71aacSSimon Glass {
15909d71aacSSimon Glass 	struct uclass *uc;
16009d71aacSSimon Glass 	struct udevice *dev, *next;
16109d71aacSSimon Glass 	int ret;
16209d71aacSSimon Glass 
16309d71aacSSimon Glass 	ret = uclass_get(UCLASS_BLK, &uc);
16409d71aacSSimon Glass 	if (ret)
16509d71aacSSimon Glass 		return ret;
16609d71aacSSimon Glass 	uclass_foreach_dev_safe(dev, next, uc) {
16709d71aacSSimon Glass 		struct blk_desc *desc = dev_get_uclass_platdata(dev);
16809d71aacSSimon Glass 
16909d71aacSSimon Glass 		if (desc->if_type == if_type) {
17009d71aacSSimon Glass 			ret = device_remove(dev);
17109d71aacSSimon Glass 			if (ret)
17209d71aacSSimon Glass 				return ret;
17309d71aacSSimon Glass 			ret = device_unbind(dev);
17409d71aacSSimon Glass 			if (ret)
17509d71aacSSimon Glass 				return ret;
17609d71aacSSimon Glass 		}
17709d71aacSSimon Glass 	}
17809d71aacSSimon Glass 
17909d71aacSSimon Glass 	return 0;
18009d71aacSSimon Glass }
18109d71aacSSimon Glass 
18209d71aacSSimon Glass UCLASS_DRIVER(blk) = {
18309d71aacSSimon Glass 	.id		= UCLASS_BLK,
18409d71aacSSimon Glass 	.name		= "blk",
18509d71aacSSimon Glass 	.per_device_platdata_auto_alloc_size = sizeof(struct blk_desc),
18609d71aacSSimon Glass };
187