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 14*d508c82bSSimon Glass static const char *if_typename_str[IF_TYPE_COUNT] = { 15*d508c82bSSimon Glass [IF_TYPE_IDE] = "ide", 16*d508c82bSSimon Glass [IF_TYPE_SCSI] = "scsi", 17*d508c82bSSimon Glass [IF_TYPE_ATAPI] = "atapi", 18*d508c82bSSimon Glass [IF_TYPE_USB] = "usb", 19*d508c82bSSimon Glass [IF_TYPE_DOC] = "doc", 20*d508c82bSSimon Glass [IF_TYPE_MMC] = "mmc", 21*d508c82bSSimon Glass [IF_TYPE_SD] = "sd", 22*d508c82bSSimon Glass [IF_TYPE_SATA] = "sata", 23*d508c82bSSimon Glass [IF_TYPE_HOST] = "host", 24*d508c82bSSimon Glass [IF_TYPE_SYSTEMACE] = "ace", 25*d508c82bSSimon Glass }; 26*d508c82bSSimon Glass 27*d508c82bSSimon Glass static enum uclass_id if_type_uclass_id[IF_TYPE_COUNT] = { 28*d508c82bSSimon Glass [IF_TYPE_IDE] = UCLASS_INVALID, 29*d508c82bSSimon Glass [IF_TYPE_SCSI] = UCLASS_INVALID, 30*d508c82bSSimon Glass [IF_TYPE_ATAPI] = UCLASS_INVALID, 31*d508c82bSSimon Glass [IF_TYPE_USB] = UCLASS_MASS_STORAGE, 32*d508c82bSSimon Glass [IF_TYPE_DOC] = UCLASS_INVALID, 33*d508c82bSSimon Glass [IF_TYPE_MMC] = UCLASS_MMC, 34*d508c82bSSimon Glass [IF_TYPE_SD] = UCLASS_INVALID, 35*d508c82bSSimon Glass [IF_TYPE_SATA] = UCLASS_AHCI, 36*d508c82bSSimon Glass [IF_TYPE_HOST] = UCLASS_ROOT, 37*d508c82bSSimon Glass [IF_TYPE_SYSTEMACE] = UCLASS_INVALID, 38*d508c82bSSimon Glass }; 39*d508c82bSSimon Glass 40*d508c82bSSimon Glass static enum if_type if_typename_to_iftype(const char *if_typename) 41*d508c82bSSimon Glass { 42*d508c82bSSimon Glass int i; 43*d508c82bSSimon Glass 44*d508c82bSSimon Glass for (i = 0; i < IF_TYPE_COUNT; i++) { 45*d508c82bSSimon Glass if (if_typename_str[i] && 46*d508c82bSSimon Glass !strcmp(if_typename, if_typename_str[i])) 47*d508c82bSSimon Glass return i; 48*d508c82bSSimon Glass } 49*d508c82bSSimon Glass 50*d508c82bSSimon Glass return IF_TYPE_UNKNOWN; 51*d508c82bSSimon Glass } 52*d508c82bSSimon Glass 53*d508c82bSSimon Glass static enum uclass_id if_type_to_uclass_id(enum if_type if_type) 54*d508c82bSSimon Glass { 55*d508c82bSSimon Glass return if_type_uclass_id[if_type]; 56*d508c82bSSimon Glass } 57*d508c82bSSimon Glass 58*d508c82bSSimon Glass struct blk_desc *blk_get_devnum_by_type(enum if_type if_type, int devnum) 59*d508c82bSSimon Glass { 60*d508c82bSSimon Glass struct blk_desc *desc; 61*d508c82bSSimon Glass struct udevice *dev; 62*d508c82bSSimon Glass int ret; 63*d508c82bSSimon Glass 64*d508c82bSSimon Glass ret = blk_get_device(if_type, devnum, &dev); 65*d508c82bSSimon Glass if (ret) 66*d508c82bSSimon Glass return NULL; 67*d508c82bSSimon Glass desc = dev_get_uclass_platdata(dev); 68*d508c82bSSimon Glass 69*d508c82bSSimon Glass return desc; 70*d508c82bSSimon Glass } 71*d508c82bSSimon Glass 72*d508c82bSSimon Glass /* 73*d508c82bSSimon Glass * This function is complicated with driver model. We look up the interface 74*d508c82bSSimon Glass * name in a local table. This gives us an interface type which we can match 75*d508c82bSSimon Glass * against the uclass of the block device's parent. 76*d508c82bSSimon Glass */ 77*d508c82bSSimon Glass struct blk_desc *blk_get_devnum_by_typename(const char *if_typename, int devnum) 78*d508c82bSSimon Glass { 79*d508c82bSSimon Glass enum uclass_id uclass_id; 80*d508c82bSSimon Glass enum if_type if_type; 81*d508c82bSSimon Glass struct udevice *dev; 82*d508c82bSSimon Glass struct uclass *uc; 83*d508c82bSSimon Glass int ret; 84*d508c82bSSimon Glass 85*d508c82bSSimon Glass if_type = if_typename_to_iftype(if_typename); 86*d508c82bSSimon Glass if (if_type == IF_TYPE_UNKNOWN) { 87*d508c82bSSimon Glass debug("%s: Unknown interface type '%s'\n", __func__, 88*d508c82bSSimon Glass if_typename); 89*d508c82bSSimon Glass return NULL; 90*d508c82bSSimon Glass } 91*d508c82bSSimon Glass uclass_id = if_type_to_uclass_id(if_type); 92*d508c82bSSimon Glass if (uclass_id == UCLASS_INVALID) { 93*d508c82bSSimon Glass debug("%s: Unknown uclass for interface type'\n", 94*d508c82bSSimon Glass if_typename_str[if_type]); 95*d508c82bSSimon Glass return NULL; 96*d508c82bSSimon Glass } 97*d508c82bSSimon Glass 98*d508c82bSSimon Glass ret = uclass_get(UCLASS_BLK, &uc); 99*d508c82bSSimon Glass if (ret) 100*d508c82bSSimon Glass return NULL; 101*d508c82bSSimon Glass uclass_foreach_dev(dev, uc) { 102*d508c82bSSimon Glass struct blk_desc *desc = dev_get_uclass_platdata(dev); 103*d508c82bSSimon Glass 104*d508c82bSSimon Glass debug("%s: if_type=%d, devnum=%d: %s, %d, %d\n", __func__, 105*d508c82bSSimon Glass if_type, devnum, dev->name, desc->if_type, desc->devnum); 106*d508c82bSSimon Glass if (desc->devnum != devnum) 107*d508c82bSSimon Glass continue; 108*d508c82bSSimon Glass 109*d508c82bSSimon Glass /* Find out the parent device uclass */ 110*d508c82bSSimon Glass if (device_get_uclass_id(dev->parent) != uclass_id) { 111*d508c82bSSimon Glass debug("%s: parent uclass %d, this dev %d\n", __func__, 112*d508c82bSSimon Glass device_get_uclass_id(dev->parent), uclass_id); 113*d508c82bSSimon Glass continue; 114*d508c82bSSimon Glass } 115*d508c82bSSimon Glass 116*d508c82bSSimon Glass if (device_probe(dev)) 117*d508c82bSSimon Glass return NULL; 118*d508c82bSSimon Glass 119*d508c82bSSimon Glass debug("%s: Device desc %p\n", __func__, desc); 120*d508c82bSSimon Glass return desc; 121*d508c82bSSimon Glass } 122*d508c82bSSimon Glass debug("%s: No device found\n", __func__); 123*d508c82bSSimon Glass 124*d508c82bSSimon Glass return NULL; 125*d508c82bSSimon Glass } 126*d508c82bSSimon Glass 127*d508c82bSSimon Glass /** 128*d508c82bSSimon Glass * get_desc() - Get the block device descriptor for the given device number 129*d508c82bSSimon Glass * 130*d508c82bSSimon Glass * @if_type: Interface type 131*d508c82bSSimon Glass * @devnum: Device number (0 = first) 132*d508c82bSSimon Glass * @descp: Returns block device descriptor on success 133*d508c82bSSimon Glass * @return 0 on success, -ENODEV if there is no such device and no device 134*d508c82bSSimon Glass * with a higher device number, -ENOENT if there is no such device but there 135*d508c82bSSimon Glass * is one with a higher number, or other -ve on other error. 136*d508c82bSSimon Glass */ 137*d508c82bSSimon Glass static int get_desc(enum if_type if_type, int devnum, struct blk_desc **descp) 138*d508c82bSSimon Glass { 139*d508c82bSSimon Glass bool found_more = false; 140*d508c82bSSimon Glass struct udevice *dev; 141*d508c82bSSimon Glass struct uclass *uc; 142*d508c82bSSimon Glass int ret; 143*d508c82bSSimon Glass 144*d508c82bSSimon Glass *descp = NULL; 145*d508c82bSSimon Glass ret = uclass_get(UCLASS_BLK, &uc); 146*d508c82bSSimon Glass if (ret) 147*d508c82bSSimon Glass return ret; 148*d508c82bSSimon Glass uclass_foreach_dev(dev, uc) { 149*d508c82bSSimon Glass struct blk_desc *desc = dev_get_uclass_platdata(dev); 150*d508c82bSSimon Glass 151*d508c82bSSimon Glass debug("%s: if_type=%d, devnum=%d: %s, %d, %d\n", __func__, 152*d508c82bSSimon Glass if_type, devnum, dev->name, desc->if_type, desc->devnum); 153*d508c82bSSimon Glass if (desc->if_type == if_type) { 154*d508c82bSSimon Glass if (desc->devnum == devnum) { 155*d508c82bSSimon Glass ret = device_probe(dev); 156*d508c82bSSimon Glass if (ret) 157*d508c82bSSimon Glass return ret; 158*d508c82bSSimon Glass 159*d508c82bSSimon Glass } else if (desc->devnum > devnum) { 160*d508c82bSSimon Glass found_more = true; 161*d508c82bSSimon Glass } 162*d508c82bSSimon Glass } 163*d508c82bSSimon Glass } 164*d508c82bSSimon Glass 165*d508c82bSSimon Glass return found_more ? -ENOENT : -ENODEV; 166*d508c82bSSimon Glass } 167*d508c82bSSimon Glass 168*d508c82bSSimon Glass int blk_list_part(enum if_type if_type) 169*d508c82bSSimon Glass { 170*d508c82bSSimon Glass struct blk_desc *desc; 171*d508c82bSSimon Glass int devnum, ok; 172*d508c82bSSimon Glass int ret; 173*d508c82bSSimon Glass 174*d508c82bSSimon Glass for (ok = 0, devnum = 0;; ++devnum) { 175*d508c82bSSimon Glass ret = get_desc(if_type, devnum, &desc); 176*d508c82bSSimon Glass if (ret == -ENODEV) 177*d508c82bSSimon Glass break; 178*d508c82bSSimon Glass else if (ret) 179*d508c82bSSimon Glass continue; 180*d508c82bSSimon Glass if (desc->part_type != PART_TYPE_UNKNOWN) { 181*d508c82bSSimon Glass ++ok; 182*d508c82bSSimon Glass if (devnum) 183*d508c82bSSimon Glass putc('\n'); 184*d508c82bSSimon Glass part_print(desc); 185*d508c82bSSimon Glass } 186*d508c82bSSimon Glass } 187*d508c82bSSimon Glass if (!ok) 188*d508c82bSSimon Glass return -ENODEV; 189*d508c82bSSimon Glass 190*d508c82bSSimon Glass return 0; 191*d508c82bSSimon Glass } 192*d508c82bSSimon Glass 193*d508c82bSSimon Glass int blk_print_part_devnum(enum if_type if_type, int devnum) 194*d508c82bSSimon Glass { 195*d508c82bSSimon Glass struct blk_desc *desc; 196*d508c82bSSimon Glass int ret; 197*d508c82bSSimon Glass 198*d508c82bSSimon Glass ret = get_desc(if_type, devnum, &desc); 199*d508c82bSSimon Glass if (ret) 200*d508c82bSSimon Glass return ret; 201*d508c82bSSimon Glass if (desc->type == DEV_TYPE_UNKNOWN) 202*d508c82bSSimon Glass return -ENOENT; 203*d508c82bSSimon Glass part_print(desc); 204*d508c82bSSimon Glass 205*d508c82bSSimon Glass return 0; 206*d508c82bSSimon Glass } 207*d508c82bSSimon Glass 208*d508c82bSSimon Glass void blk_list_devices(enum if_type if_type) 209*d508c82bSSimon Glass { 210*d508c82bSSimon Glass struct blk_desc *desc; 211*d508c82bSSimon Glass int ret; 212*d508c82bSSimon Glass int i; 213*d508c82bSSimon Glass 214*d508c82bSSimon Glass for (i = 0;; ++i) { 215*d508c82bSSimon Glass ret = get_desc(if_type, i, &desc); 216*d508c82bSSimon Glass if (ret == -ENODEV) 217*d508c82bSSimon Glass break; 218*d508c82bSSimon Glass else if (ret) 219*d508c82bSSimon Glass continue; 220*d508c82bSSimon Glass if (desc->type == DEV_TYPE_UNKNOWN) 221*d508c82bSSimon Glass continue; /* list only known devices */ 222*d508c82bSSimon Glass printf("Device %d: ", i); 223*d508c82bSSimon Glass dev_print(desc); 224*d508c82bSSimon Glass } 225*d508c82bSSimon Glass } 226*d508c82bSSimon Glass 227*d508c82bSSimon Glass int blk_print_device_num(enum if_type if_type, int devnum) 228*d508c82bSSimon Glass { 229*d508c82bSSimon Glass struct blk_desc *desc; 230*d508c82bSSimon Glass int ret; 231*d508c82bSSimon Glass 232*d508c82bSSimon Glass ret = get_desc(if_type, devnum, &desc); 233*d508c82bSSimon Glass if (ret) 234*d508c82bSSimon Glass return ret; 235*d508c82bSSimon Glass printf("\nIDE device %d: ", devnum); 236*d508c82bSSimon Glass dev_print(desc); 237*d508c82bSSimon Glass 238*d508c82bSSimon Glass return 0; 239*d508c82bSSimon Glass } 240*d508c82bSSimon Glass 241*d508c82bSSimon Glass int blk_show_device(enum if_type if_type, int devnum) 242*d508c82bSSimon Glass { 243*d508c82bSSimon Glass struct blk_desc *desc; 244*d508c82bSSimon Glass int ret; 245*d508c82bSSimon Glass 246*d508c82bSSimon Glass printf("\nDevice %d: ", devnum); 247*d508c82bSSimon Glass ret = get_desc(if_type, devnum, &desc); 248*d508c82bSSimon Glass if (ret == -ENODEV || ret == -ENOENT) { 249*d508c82bSSimon Glass printf("unknown device\n"); 250*d508c82bSSimon Glass return -ENODEV; 251*d508c82bSSimon Glass } 252*d508c82bSSimon Glass if (ret) 253*d508c82bSSimon Glass return ret; 254*d508c82bSSimon Glass dev_print(desc); 255*d508c82bSSimon Glass 256*d508c82bSSimon Glass if (desc->type == DEV_TYPE_UNKNOWN) 257*d508c82bSSimon Glass return -ENOENT; 258*d508c82bSSimon Glass 259*d508c82bSSimon Glass return 0; 260*d508c82bSSimon Glass } 261*d508c82bSSimon Glass 262*d508c82bSSimon Glass ulong blk_read_devnum(enum if_type if_type, int devnum, lbaint_t start, 263*d508c82bSSimon Glass lbaint_t blkcnt, void *buffer) 264*d508c82bSSimon Glass { 265*d508c82bSSimon Glass struct blk_desc *desc; 266*d508c82bSSimon Glass ulong n; 267*d508c82bSSimon Glass int ret; 268*d508c82bSSimon Glass 269*d508c82bSSimon Glass ret = get_desc(if_type, devnum, &desc); 270*d508c82bSSimon Glass if (ret) 271*d508c82bSSimon Glass return ret; 272*d508c82bSSimon Glass n = blk_dread(desc, start, blkcnt, buffer); 273*d508c82bSSimon Glass if (IS_ERR_VALUE(n)) 274*d508c82bSSimon Glass return n; 275*d508c82bSSimon Glass 276*d508c82bSSimon Glass /* flush cache after read */ 277*d508c82bSSimon Glass flush_cache((ulong)buffer, blkcnt * desc->blksz); 278*d508c82bSSimon Glass 279*d508c82bSSimon Glass return n; 280*d508c82bSSimon Glass } 281*d508c82bSSimon Glass 282*d508c82bSSimon Glass ulong blk_write_devnum(enum if_type if_type, int devnum, lbaint_t start, 283*d508c82bSSimon Glass lbaint_t blkcnt, const void *buffer) 284*d508c82bSSimon Glass { 285*d508c82bSSimon Glass struct blk_desc *desc; 286*d508c82bSSimon Glass int ret; 287*d508c82bSSimon Glass 288*d508c82bSSimon Glass ret = get_desc(if_type, devnum, &desc); 289*d508c82bSSimon Glass if (ret) 290*d508c82bSSimon Glass return ret; 291*d508c82bSSimon Glass return blk_dwrite(desc, start, blkcnt, buffer); 292*d508c82bSSimon Glass } 293*d508c82bSSimon Glass 29409d71aacSSimon Glass int blk_first_device(int if_type, struct udevice **devp) 29509d71aacSSimon Glass { 29609d71aacSSimon Glass struct blk_desc *desc; 29709d71aacSSimon Glass int ret; 29809d71aacSSimon Glass 29909d71aacSSimon Glass ret = uclass_first_device(UCLASS_BLK, devp); 30009d71aacSSimon Glass if (ret) 30109d71aacSSimon Glass return ret; 30209d71aacSSimon Glass if (!*devp) 30309d71aacSSimon Glass return -ENODEV; 30409d71aacSSimon Glass do { 30509d71aacSSimon Glass desc = dev_get_uclass_platdata(*devp); 30609d71aacSSimon Glass if (desc->if_type == if_type) 30709d71aacSSimon Glass return 0; 30809d71aacSSimon Glass ret = uclass_next_device(devp); 30909d71aacSSimon Glass if (ret) 31009d71aacSSimon Glass return ret; 31109d71aacSSimon Glass } while (*devp); 31209d71aacSSimon Glass 31309d71aacSSimon Glass return -ENODEV; 31409d71aacSSimon Glass } 31509d71aacSSimon Glass 31609d71aacSSimon Glass int blk_next_device(struct udevice **devp) 31709d71aacSSimon Glass { 31809d71aacSSimon Glass struct blk_desc *desc; 31909d71aacSSimon Glass int ret, if_type; 32009d71aacSSimon Glass 32109d71aacSSimon Glass desc = dev_get_uclass_platdata(*devp); 32209d71aacSSimon Glass if_type = desc->if_type; 32309d71aacSSimon Glass do { 32409d71aacSSimon Glass ret = uclass_next_device(devp); 32509d71aacSSimon Glass if (ret) 32609d71aacSSimon Glass return ret; 32709d71aacSSimon Glass if (!*devp) 32809d71aacSSimon Glass return -ENODEV; 32909d71aacSSimon Glass desc = dev_get_uclass_platdata(*devp); 33009d71aacSSimon Glass if (desc->if_type == if_type) 33109d71aacSSimon Glass return 0; 33209d71aacSSimon Glass } while (1); 33309d71aacSSimon Glass } 33409d71aacSSimon Glass 33509d71aacSSimon Glass int blk_get_device(int if_type, int devnum, struct udevice **devp) 33609d71aacSSimon Glass { 33709d71aacSSimon Glass struct uclass *uc; 33809d71aacSSimon Glass struct udevice *dev; 33909d71aacSSimon Glass int ret; 34009d71aacSSimon Glass 34109d71aacSSimon Glass ret = uclass_get(UCLASS_BLK, &uc); 34209d71aacSSimon Glass if (ret) 34309d71aacSSimon Glass return ret; 34409d71aacSSimon Glass uclass_foreach_dev(dev, uc) { 34509d71aacSSimon Glass struct blk_desc *desc = dev_get_uclass_platdata(dev); 34609d71aacSSimon Glass 34709d71aacSSimon Glass debug("%s: if_type=%d, devnum=%d: %s, %d, %d\n", __func__, 34809d71aacSSimon Glass if_type, devnum, dev->name, desc->if_type, desc->devnum); 34909d71aacSSimon Glass if (desc->if_type == if_type && desc->devnum == devnum) { 35009d71aacSSimon Glass *devp = dev; 35109d71aacSSimon Glass return device_probe(dev); 35209d71aacSSimon Glass } 35309d71aacSSimon Glass } 35409d71aacSSimon Glass 35509d71aacSSimon Glass return -ENODEV; 35609d71aacSSimon Glass } 35709d71aacSSimon Glass 35809d71aacSSimon Glass unsigned long blk_dread(struct blk_desc *block_dev, lbaint_t start, 35909d71aacSSimon Glass lbaint_t blkcnt, void *buffer) 36009d71aacSSimon Glass { 36109d71aacSSimon Glass struct udevice *dev = block_dev->bdev; 36209d71aacSSimon Glass const struct blk_ops *ops = blk_get_ops(dev); 363e40cf34aSEric Nelson ulong blks_read; 36409d71aacSSimon Glass 36509d71aacSSimon Glass if (!ops->read) 36609d71aacSSimon Glass return -ENOSYS; 36709d71aacSSimon Glass 368e40cf34aSEric Nelson if (blkcache_read(block_dev->if_type, block_dev->devnum, 369e40cf34aSEric Nelson start, blkcnt, block_dev->blksz, buffer)) 370e40cf34aSEric Nelson return blkcnt; 371e40cf34aSEric Nelson blks_read = ops->read(dev, start, blkcnt, buffer); 372e40cf34aSEric Nelson if (blks_read == blkcnt) 373e40cf34aSEric Nelson blkcache_fill(block_dev->if_type, block_dev->devnum, 374e40cf34aSEric Nelson start, blkcnt, block_dev->blksz, buffer); 375e40cf34aSEric Nelson 376e40cf34aSEric Nelson return blks_read; 37709d71aacSSimon Glass } 37809d71aacSSimon Glass 37909d71aacSSimon Glass unsigned long blk_dwrite(struct blk_desc *block_dev, lbaint_t start, 38009d71aacSSimon Glass lbaint_t blkcnt, const void *buffer) 38109d71aacSSimon Glass { 38209d71aacSSimon Glass struct udevice *dev = block_dev->bdev; 38309d71aacSSimon Glass const struct blk_ops *ops = blk_get_ops(dev); 38409d71aacSSimon Glass 38509d71aacSSimon Glass if (!ops->write) 38609d71aacSSimon Glass return -ENOSYS; 38709d71aacSSimon Glass 388e40cf34aSEric Nelson blkcache_invalidate(block_dev->if_type, block_dev->devnum); 38909d71aacSSimon Glass return ops->write(dev, start, blkcnt, buffer); 39009d71aacSSimon Glass } 39109d71aacSSimon Glass 39209d71aacSSimon Glass unsigned long blk_derase(struct blk_desc *block_dev, lbaint_t start, 39309d71aacSSimon Glass lbaint_t blkcnt) 39409d71aacSSimon Glass { 39509d71aacSSimon Glass struct udevice *dev = block_dev->bdev; 39609d71aacSSimon Glass const struct blk_ops *ops = blk_get_ops(dev); 39709d71aacSSimon Glass 39809d71aacSSimon Glass if (!ops->erase) 39909d71aacSSimon Glass return -ENOSYS; 40009d71aacSSimon Glass 401e40cf34aSEric Nelson blkcache_invalidate(block_dev->if_type, block_dev->devnum); 40209d71aacSSimon Glass return ops->erase(dev, start, blkcnt); 40309d71aacSSimon Glass } 40409d71aacSSimon Glass 40509d71aacSSimon Glass int blk_prepare_device(struct udevice *dev) 40609d71aacSSimon Glass { 40709d71aacSSimon Glass struct blk_desc *desc = dev_get_uclass_platdata(dev); 40809d71aacSSimon Glass 40909d71aacSSimon Glass part_init(desc); 41009d71aacSSimon Glass 41109d71aacSSimon Glass return 0; 41209d71aacSSimon Glass } 41309d71aacSSimon Glass 41409d71aacSSimon Glass int blk_create_device(struct udevice *parent, const char *drv_name, 41509d71aacSSimon Glass const char *name, int if_type, int devnum, int blksz, 41609d71aacSSimon Glass lbaint_t size, struct udevice **devp) 41709d71aacSSimon Glass { 41809d71aacSSimon Glass struct blk_desc *desc; 41909d71aacSSimon Glass struct udevice *dev; 42009d71aacSSimon Glass int ret; 42109d71aacSSimon Glass 42209d71aacSSimon Glass ret = device_bind_driver(parent, drv_name, name, &dev); 42309d71aacSSimon Glass if (ret) 42409d71aacSSimon Glass return ret; 42509d71aacSSimon Glass desc = dev_get_uclass_platdata(dev); 42609d71aacSSimon Glass desc->if_type = if_type; 42709d71aacSSimon Glass desc->blksz = blksz; 42809d71aacSSimon Glass desc->lba = size / blksz; 42909d71aacSSimon Glass desc->part_type = PART_TYPE_UNKNOWN; 43009d71aacSSimon Glass desc->bdev = dev; 43109d71aacSSimon Glass desc->devnum = devnum; 43209d71aacSSimon Glass *devp = dev; 43309d71aacSSimon Glass 43409d71aacSSimon Glass return 0; 43509d71aacSSimon Glass } 43609d71aacSSimon Glass 43709d71aacSSimon Glass int blk_unbind_all(int if_type) 43809d71aacSSimon Glass { 43909d71aacSSimon Glass struct uclass *uc; 44009d71aacSSimon Glass struct udevice *dev, *next; 44109d71aacSSimon Glass int ret; 44209d71aacSSimon Glass 44309d71aacSSimon Glass ret = uclass_get(UCLASS_BLK, &uc); 44409d71aacSSimon Glass if (ret) 44509d71aacSSimon Glass return ret; 44609d71aacSSimon Glass uclass_foreach_dev_safe(dev, next, uc) { 44709d71aacSSimon Glass struct blk_desc *desc = dev_get_uclass_platdata(dev); 44809d71aacSSimon Glass 44909d71aacSSimon Glass if (desc->if_type == if_type) { 45009d71aacSSimon Glass ret = device_remove(dev); 45109d71aacSSimon Glass if (ret) 45209d71aacSSimon Glass return ret; 45309d71aacSSimon Glass ret = device_unbind(dev); 45409d71aacSSimon Glass if (ret) 45509d71aacSSimon Glass return ret; 45609d71aacSSimon Glass } 45709d71aacSSimon Glass } 45809d71aacSSimon Glass 45909d71aacSSimon Glass return 0; 46009d71aacSSimon Glass } 46109d71aacSSimon Glass 46209d71aacSSimon Glass UCLASS_DRIVER(blk) = { 46309d71aacSSimon Glass .id = UCLASS_BLK, 46409d71aacSSimon Glass .name = "blk", 46509d71aacSSimon Glass .per_device_platdata_auto_alloc_size = sizeof(struct blk_desc), 46609d71aacSSimon Glass }; 467