16494d708SSimon Glass /*
26494d708SSimon Glass * Device manager
36494d708SSimon Glass *
46494d708SSimon Glass * Copyright (c) 2013 Google, Inc
56494d708SSimon Glass *
66494d708SSimon Glass * (C) Copyright 2012
76494d708SSimon Glass * Pavel Herrmann <morpheus.ibis@gmail.com>
86494d708SSimon Glass *
96494d708SSimon Glass * SPDX-License-Identifier: GPL-2.0+
106494d708SSimon Glass */
116494d708SSimon Glass
126494d708SSimon Glass #include <common.h>
137c616862SVignesh R #include <asm/io.h>
140b2881acSPhilipp Tomsich #include <clk.h>
155a66a8ffSSimon Glass #include <fdtdec.h>
16ef5cd330SStefan Roese #include <fdt_support.h>
176494d708SSimon Glass #include <malloc.h>
186494d708SSimon Glass #include <dm/device.h>
196494d708SSimon Glass #include <dm/device-internal.h>
206494d708SSimon Glass #include <dm/lists.h>
2118aa8da9SMario Six #include <dm/of_access.h>
22d90a5a30SMasahiro Yamada #include <dm/pinctrl.h>
236494d708SSimon Glass #include <dm/platdata.h>
24396e343bSSimon Glass #include <dm/read.h>
256494d708SSimon Glass #include <dm/uclass.h>
266494d708SSimon Glass #include <dm/uclass-internal.h>
276494d708SSimon Glass #include <dm/util.h>
286494d708SSimon Glass #include <linux/err.h>
296494d708SSimon Glass #include <linux/list.h>
306494d708SSimon Glass
315a66a8ffSSimon Glass DECLARE_GLOBAL_DATA_PTR;
325a66a8ffSSimon Glass
device_bind_common(struct udevice * parent,const struct driver * drv,const char * name,void * platdata,ulong driver_data,ofnode node,uint of_platdata_size,struct udevice ** devp)33daac3bfeSStephen Warren static int device_bind_common(struct udevice *parent, const struct driver *drv,
34daac3bfeSStephen Warren const char *name, void *platdata,
357a61b0b5SSimon Glass ulong driver_data, ofnode node,
369fa28190SSimon Glass uint of_platdata_size, struct udevice **devp)
376494d708SSimon Glass {
3854c5d08aSHeiko Schocher struct udevice *dev;
396494d708SSimon Glass struct uclass *uc;
40d9da4b44SJoseph Chen bool after_u_boot_dev = true;
415eaed880SPrzemyslaw Marczak int size, ret = 0;
426494d708SSimon Glass
43e6cabe4aSMasahiro Yamada if (devp)
446494d708SSimon Glass *devp = NULL;
456494d708SSimon Glass if (!name)
466494d708SSimon Glass return -EINVAL;
476494d708SSimon Glass
486494d708SSimon Glass ret = uclass_get(drv->id, &uc);
493346c876SSimon Glass if (ret) {
503346c876SSimon Glass debug("Missing uclass for driver %s\n", drv->name);
516494d708SSimon Glass return ret;
523346c876SSimon Glass }
536494d708SSimon Glass
54d9da4b44SJoseph Chen #if defined(CONFIG_USING_KERNEL_DTB) && !defined(CONFIG_USING_KERNEL_DTB_V2)
55527e4be7SKever Yang if (gd->flags & GD_FLG_RELOC) {
56d24a078fSJoseph Chen /* For mmc/nand/spiflash, just update from kernel dtb instead bind again*/
57d24a078fSJoseph Chen if (drv->id == UCLASS_MMC || drv->id == UCLASS_RKNAND ||
5880907d3cSShawn Lin drv->id == UCLASS_SPI_FLASH || drv->id == UCLASS_MTD ||
59e30e978dSYifeng Zhao drv->id == UCLASS_PCI || drv->id == UCLASS_AHCI) {
6033273e09SJoseph Chen /*
6133273e09SJoseph Chen * Reject all mmc device from kernel.
6233273e09SJoseph Chen *
6333273e09SJoseph Chen * - we always follow the rule: use mmc device from U-Boot
6433273e09SJoseph Chen * - avoid alias id on defferent device between U-Boot and kernel
6533273e09SJoseph Chen */
6633273e09SJoseph Chen if ((gd->flags & GD_FLG_KDTB_READY) &&
6733273e09SJoseph Chen (drv->id == UCLASS_MMC))
6833273e09SJoseph Chen return 0;
6933273e09SJoseph Chen
7089f947ecSKever Yang list_for_each_entry(dev, &uc->dev_head, uclass_node) {
7189f947ecSKever Yang if (!strcmp(name, dev->name)) {
7289f947ecSKever Yang debug("%s do not bind dev already in list %s\n",
73527e4be7SKever Yang __func__, dev->name);
7430a85904SJoseph Chen /*
7530a85904SJoseph Chen * There is no clearly reason for this
7630a85904SJoseph Chen * legacy code, but remain it here since
7730a85904SJoseph Chen * everything seems fine with or without
7830a85904SJoseph Chen * this. Maybe removed in the future.
7930a85904SJoseph Chen */
8089f947ecSKever Yang dev->node = node;
8189f947ecSKever Yang return 0;
8289f947ecSKever Yang }
8389f947ecSKever Yang }
84527e4be7SKever Yang }
85713d9646SFinley Xiao
86527e4be7SKever Yang /* Use other nodes from kernel dtb */
87713d9646SFinley Xiao struct udevice *n;
88713d9646SFinley Xiao
89713d9646SFinley Xiao list_for_each_entry_safe(dev, n, &uc->dev_head, uclass_node) {
90d7a244f9SJoseph Chen if (!strcmp(name, dev->name) &&
91930ceb12SJoseph Chen (dev_read_bool(dev, "u-boot,dm-pre-reloc") ||
92930ceb12SJoseph Chen dev_read_bool(dev, "u-boot,dm-spl"))) {
9330a85904SJoseph Chen
94ef5a68b1SJoseph Chen /* Always use these node from U-Boot dtb */
95ef5a68b1SJoseph Chen if (drv->id == UCLASS_CRYPTO ||
96ef5a68b1SJoseph Chen drv->id == UCLASS_WDT) {
97527e4be7SKever Yang debug("%s do not delete uboot dev: %s\n",
98527e4be7SKever Yang __func__, dev->name);
99527e4be7SKever Yang return 0;
100527e4be7SKever Yang } else {
1018f5dfc4aSJoseph Chen list_del_init(&dev->uclass_node);
102713d9646SFinley Xiao }
103713d9646SFinley Xiao }
104527e4be7SKever Yang }
105527e4be7SKever Yang }
1065039ac47SKever Yang #endif
10754c5d08aSHeiko Schocher dev = calloc(1, sizeof(struct udevice));
1086494d708SSimon Glass if (!dev)
1096494d708SSimon Glass return -ENOMEM;
1106494d708SSimon Glass
1116494d708SSimon Glass INIT_LIST_HEAD(&dev->sibling_node);
1126494d708SSimon Glass INIT_LIST_HEAD(&dev->child_head);
1136494d708SSimon Glass INIT_LIST_HEAD(&dev->uclass_node);
114e2282d70SMasahiro Yamada #ifdef CONFIG_DEVRES
115608f26c5SMasahiro Yamada INIT_LIST_HEAD(&dev->devres_head);
116e2282d70SMasahiro Yamada #endif
1176494d708SSimon Glass dev->platdata = platdata;
118daac3bfeSStephen Warren dev->driver_data = driver_data;
1196494d708SSimon Glass dev->name = name;
1207a61b0b5SSimon Glass dev->node = node;
1216494d708SSimon Glass dev->parent = parent;
1226494d708SSimon Glass dev->driver = drv;
1236494d708SSimon Glass dev->uclass = uc;
1245a66a8ffSSimon Glass
1255a66a8ffSSimon Glass dev->seq = -1;
12691cbd792SSimon Glass dev->req_seq = -1;
1274f627c5aSNathan Rossi if (CONFIG_IS_ENABLED(OF_CONTROL) && CONFIG_IS_ENABLED(DM_SEQ_ALIAS)) {
1289cc36a2bSSimon Glass /*
12936fa61dcSSimon Glass * Some devices, such as a SPI bus, I2C bus and serial ports
13036fa61dcSSimon Glass * are numbered using aliases.
1319cc36a2bSSimon Glass *
1329cc36a2bSSimon Glass * This is just a 'requested' sequence, and will be
1339cc36a2bSSimon Glass * resolved (and ->seq updated) when the device is probed.
1349cc36a2bSSimon Glass */
1359cc36a2bSSimon Glass if (uc->uc_drv->flags & DM_UC_FLAG_SEQ_ALIAS) {
1367a61b0b5SSimon Glass if (uc->uc_drv->name && ofnode_valid(node)) {
137396e343bSSimon Glass dev_read_alias_seq(dev, &dev->req_seq);
1389cc36a2bSSimon Glass }
1399cc36a2bSSimon Glass }
14036fa61dcSSimon Glass }
14136fa61dcSSimon Glass
1429fa28190SSimon Glass if (drv->platdata_auto_alloc_size) {
1439fa28190SSimon Glass bool alloc = !platdata;
1449fa28190SSimon Glass
1459fa28190SSimon Glass if (CONFIG_IS_ENABLED(OF_PLATDATA)) {
1469fa28190SSimon Glass if (of_platdata_size) {
1479fa28190SSimon Glass dev->flags |= DM_FLAG_OF_PLATDATA;
1489fa28190SSimon Glass if (of_platdata_size <
1499fa28190SSimon Glass drv->platdata_auto_alloc_size)
1509fa28190SSimon Glass alloc = true;
1519fa28190SSimon Glass }
1529fa28190SSimon Glass }
1539fa28190SSimon Glass if (alloc) {
1546494d708SSimon Glass dev->flags |= DM_FLAG_ALLOC_PDATA;
1559fa28190SSimon Glass dev->platdata = calloc(1,
1569fa28190SSimon Glass drv->platdata_auto_alloc_size);
157f8a85449SSimon Glass if (!dev->platdata) {
158f8a85449SSimon Glass ret = -ENOMEM;
159f8a85449SSimon Glass goto fail_alloc1;
160f8a85449SSimon Glass }
1619fa28190SSimon Glass if (CONFIG_IS_ENABLED(OF_PLATDATA) && platdata) {
1629fa28190SSimon Glass memcpy(dev->platdata, platdata,
1639fa28190SSimon Glass of_platdata_size);
1649fa28190SSimon Glass }
1659fa28190SSimon Glass }
166f8a85449SSimon Glass }
167cdc133bdSSimon Glass
1685eaed880SPrzemyslaw Marczak size = uc->uc_drv->per_device_platdata_auto_alloc_size;
1695eaed880SPrzemyslaw Marczak if (size) {
1705eaed880SPrzemyslaw Marczak dev->flags |= DM_FLAG_ALLOC_UCLASS_PDATA;
1715eaed880SPrzemyslaw Marczak dev->uclass_platdata = calloc(1, size);
1725eaed880SPrzemyslaw Marczak if (!dev->uclass_platdata) {
1735eaed880SPrzemyslaw Marczak ret = -ENOMEM;
1745eaed880SPrzemyslaw Marczak goto fail_alloc2;
1755eaed880SPrzemyslaw Marczak }
1765eaed880SPrzemyslaw Marczak }
1775eaed880SPrzemyslaw Marczak
1785eaed880SPrzemyslaw Marczak if (parent) {
1795eaed880SPrzemyslaw Marczak size = parent->driver->per_child_platdata_auto_alloc_size;
180ba8da9dcSSimon Glass if (!size) {
181ba8da9dcSSimon Glass size = parent->uclass->uc_drv->
182ba8da9dcSSimon Glass per_child_platdata_auto_alloc_size;
183ba8da9dcSSimon Glass }
184cdc133bdSSimon Glass if (size) {
185cdc133bdSSimon Glass dev->flags |= DM_FLAG_ALLOC_PARENT_PDATA;
186cdc133bdSSimon Glass dev->parent_platdata = calloc(1, size);
187cdc133bdSSimon Glass if (!dev->parent_platdata) {
188cdc133bdSSimon Glass ret = -ENOMEM;
1895eaed880SPrzemyslaw Marczak goto fail_alloc3;
190cdc133bdSSimon Glass }
191cdc133bdSSimon Glass }
192cdc133bdSSimon Glass }
1936494d708SSimon Glass
1946494d708SSimon Glass /* put dev into parent's successor list */
1956494d708SSimon Glass if (parent)
1966494d708SSimon Glass list_add_tail(&dev->sibling_node, &parent->child_head);
1976494d708SSimon Glass
198d9da4b44SJoseph Chen #ifdef CONFIG_USING_KERNEL_DTB
199d9da4b44SJoseph Chen #ifdef CONFIG_USING_KERNEL_DTB_V2
200d9da4b44SJoseph Chen /*
201d9da4b44SJoseph Chen * Put these U-Boot devices in the head of uclass device list for
202d9da4b44SJoseph Chen * the primary get by uclass_get_device_xxx().
203d9da4b44SJoseph Chen *
204d9da4b44SJoseph Chen * device-list: U0, U1, U2, ... K0, K1, K2, ... (prior u-boot dev)
205d9da4b44SJoseph Chen * device-list: K0, K1, K2, ... U0, U1, U2, ... (normal)
206d9da4b44SJoseph Chen *
207d9da4b44SJoseph Chen * U: u-boot dev
208d9da4b44SJoseph Chen * K: kernel dev
209d9da4b44SJoseph Chen */
210d9da4b44SJoseph Chen u32 i, prior_u_boot_uclass_id[] = {
211d9da4b44SJoseph Chen UCLASS_AHCI, /* boot device */
212d9da4b44SJoseph Chen UCLASS_BLK,
213d9da4b44SJoseph Chen UCLASS_MMC,
214d9da4b44SJoseph Chen UCLASS_MTD,
215d9da4b44SJoseph Chen UCLASS_PCI,
216d9da4b44SJoseph Chen UCLASS_RKNAND,
217d9da4b44SJoseph Chen UCLASS_SPI_FLASH,
218d9da4b44SJoseph Chen
219d9da4b44SJoseph Chen UCLASS_CRYPTO, /* RSA security */
220d9da4b44SJoseph Chen UCLASS_FIRMWARE, /* psci sysreset */
221d9da4b44SJoseph Chen UCLASS_RNG, /* ramdom number */
222d9da4b44SJoseph Chen UCLASS_SYSCON, /* grf, pmugrf */
223d9da4b44SJoseph Chen UCLASS_SYSRESET, /* psci sysreset */
224d9da4b44SJoseph Chen UCLASS_WDT, /* reliable sysreset */
225d9da4b44SJoseph Chen };
226d9da4b44SJoseph Chen
227d9da4b44SJoseph Chen if (gd->flags & GD_FLG_KDTB_READY) {
228d9da4b44SJoseph Chen after_u_boot_dev = false;
229d9da4b44SJoseph Chen dev->flags |= DM_FLAG_KNRL_DTB;
230d9da4b44SJoseph Chen
231d9da4b44SJoseph Chen for (i = 0; i < ARRAY_SIZE(prior_u_boot_uclass_id); i++) {
232d9da4b44SJoseph Chen if (drv->id == prior_u_boot_uclass_id[i]) {
233d9da4b44SJoseph Chen after_u_boot_dev = true;
234d9da4b44SJoseph Chen break;
235d9da4b44SJoseph Chen }
236d9da4b44SJoseph Chen }
237d9da4b44SJoseph Chen
238d9da4b44SJoseph Chen /* no u-boot dev ? */
239d9da4b44SJoseph Chen if (!dev->uclass->u_boot_dev_head)
240d9da4b44SJoseph Chen dev->uclass->u_boot_dev_head = &uc->dev_head;
241d9da4b44SJoseph Chen } else {
242d9da4b44SJoseph Chen if (!dev->uclass->u_boot_dev_head)
243d9da4b44SJoseph Chen dev->uclass->u_boot_dev_head = &dev->uclass_node;
244d9da4b44SJoseph Chen }
245d9da4b44SJoseph Chen #else
246d9da4b44SJoseph Chen if (gd->flags & GD_FLG_KDTB_READY)
247d9da4b44SJoseph Chen dev->flags |= DM_FLAG_KNRL_DTB;
248d9da4b44SJoseph Chen #endif
249d9da4b44SJoseph Chen #endif
250d9da4b44SJoseph Chen ret = uclass_bind_device(dev, after_u_boot_dev);
2516494d708SSimon Glass if (ret)
25272ebfe86SSimon Glass goto fail_uclass_bind;
2536494d708SSimon Glass
2546494d708SSimon Glass /* if we fail to bind we remove device from successors and free it */
2556494d708SSimon Glass if (drv->bind) {
2566494d708SSimon Glass ret = drv->bind(dev);
25772ebfe86SSimon Glass if (ret)
2586494d708SSimon Glass goto fail_bind;
2596494d708SSimon Glass }
2600118ce79SSimon Glass if (parent && parent->driver->child_post_bind) {
2610118ce79SSimon Glass ret = parent->driver->child_post_bind(dev);
2620118ce79SSimon Glass if (ret)
2630118ce79SSimon Glass goto fail_child_post_bind;
2640118ce79SSimon Glass }
26520af3c0aSSimon Glass if (uc->uc_drv->post_bind) {
26620af3c0aSSimon Glass ret = uc->uc_drv->post_bind(dev);
26720af3c0aSSimon Glass if (ret)
26820af3c0aSSimon Glass goto fail_uclass_post_bind;
26920af3c0aSSimon Glass }
2700118ce79SSimon Glass
2716494d708SSimon Glass if (parent)
272d42197e4SMasahiro Yamada pr_debug("Bound device %s to %s\n", dev->name, parent->name);
273e6cabe4aSMasahiro Yamada if (devp)
2746494d708SSimon Glass *devp = dev;
2756494d708SSimon Glass
276aed1a4ddSMasahiro Yamada dev->flags |= DM_FLAG_BOUND;
277aed1a4ddSMasahiro Yamada
2786494d708SSimon Glass return 0;
2796494d708SSimon Glass
28020af3c0aSSimon Glass fail_uclass_post_bind:
28120af3c0aSSimon Glass /* There is no child unbind() method, so no clean-up required */
2820118ce79SSimon Glass fail_child_post_bind:
2830a5804b5SMasahiro Yamada if (CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)) {
2840118ce79SSimon Glass if (drv->unbind && drv->unbind(dev)) {
2850118ce79SSimon Glass dm_warn("unbind() method failed on dev '%s' on error path\n",
2860118ce79SSimon Glass dev->name);
2870118ce79SSimon Glass }
2885a87c417SSimon Glass }
2890118ce79SSimon Glass
2906494d708SSimon Glass fail_bind:
2910a5804b5SMasahiro Yamada if (CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)) {
29272ebfe86SSimon Glass if (uclass_unbind_device(dev)) {
29372ebfe86SSimon Glass dm_warn("Failed to unbind dev '%s' on error path\n",
29472ebfe86SSimon Glass dev->name);
29572ebfe86SSimon Glass }
2965a87c417SSimon Glass }
29772ebfe86SSimon Glass fail_uclass_bind:
2980a5804b5SMasahiro Yamada if (CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)) {
2996494d708SSimon Glass list_del(&dev->sibling_node);
300cdc133bdSSimon Glass if (dev->flags & DM_FLAG_ALLOC_PARENT_PDATA) {
301cdc133bdSSimon Glass free(dev->parent_platdata);
302cdc133bdSSimon Glass dev->parent_platdata = NULL;
303cdc133bdSSimon Glass }
3045a87c417SSimon Glass }
3055eaed880SPrzemyslaw Marczak fail_alloc3:
3065eaed880SPrzemyslaw Marczak if (dev->flags & DM_FLAG_ALLOC_UCLASS_PDATA) {
3075eaed880SPrzemyslaw Marczak free(dev->uclass_platdata);
3085eaed880SPrzemyslaw Marczak dev->uclass_platdata = NULL;
3095eaed880SPrzemyslaw Marczak }
310cdc133bdSSimon Glass fail_alloc2:
311f8a85449SSimon Glass if (dev->flags & DM_FLAG_ALLOC_PDATA) {
312f8a85449SSimon Glass free(dev->platdata);
313f8a85449SSimon Glass dev->platdata = NULL;
314f8a85449SSimon Glass }
315f8a85449SSimon Glass fail_alloc1:
316608f26c5SMasahiro Yamada devres_release_all(dev);
317608f26c5SMasahiro Yamada
3186494d708SSimon Glass free(dev);
31972ebfe86SSimon Glass
3206494d708SSimon Glass return ret;
3216494d708SSimon Glass }
3226494d708SSimon Glass
device_bind_with_driver_data(struct udevice * parent,const struct driver * drv,const char * name,ulong driver_data,ofnode node,struct udevice ** devp)323daac3bfeSStephen Warren int device_bind_with_driver_data(struct udevice *parent,
324daac3bfeSStephen Warren const struct driver *drv, const char *name,
325396e343bSSimon Glass ulong driver_data, ofnode node,
326daac3bfeSStephen Warren struct udevice **devp)
327daac3bfeSStephen Warren {
328396e343bSSimon Glass return device_bind_common(parent, drv, name, NULL, driver_data, node,
329396e343bSSimon Glass 0, devp);
330daac3bfeSStephen Warren }
331daac3bfeSStephen Warren
device_bind(struct udevice * parent,const struct driver * drv,const char * name,void * platdata,int of_offset,struct udevice ** devp)332daac3bfeSStephen Warren int device_bind(struct udevice *parent, const struct driver *drv,
333daac3bfeSStephen Warren const char *name, void *platdata, int of_offset,
334daac3bfeSStephen Warren struct udevice **devp)
335daac3bfeSStephen Warren {
3367a61b0b5SSimon Glass return device_bind_common(parent, drv, name, platdata, 0,
3377a61b0b5SSimon Glass offset_to_ofnode(of_offset), 0, devp);
338daac3bfeSStephen Warren }
339daac3bfeSStephen Warren
device_bind_by_name(struct udevice * parent,bool pre_reloc_only,const struct driver_info * info,struct udevice ** devp)34000606d7eSSimon Glass int device_bind_by_name(struct udevice *parent, bool pre_reloc_only,
34100606d7eSSimon Glass const struct driver_info *info, struct udevice **devp)
3426494d708SSimon Glass {
3436494d708SSimon Glass struct driver *drv;
3449fa28190SSimon Glass uint platdata_size = 0;
3456494d708SSimon Glass
3466494d708SSimon Glass drv = lists_driver_lookup_name(info->name);
3476494d708SSimon Glass if (!drv)
3486494d708SSimon Glass return -ENOENT;
34900606d7eSSimon Glass if (pre_reloc_only && !(drv->flags & DM_FLAG_PRE_RELOC))
35000606d7eSSimon Glass return -EPERM;
3516494d708SSimon Glass
3529fa28190SSimon Glass #if CONFIG_IS_ENABLED(OF_PLATDATA)
3539fa28190SSimon Glass platdata_size = info->platdata_size;
3549fa28190SSimon Glass #endif
3559fa28190SSimon Glass return device_bind_common(parent, drv, info->name,
356396e343bSSimon Glass (void *)info->platdata, 0, ofnode_null(), platdata_size,
357396e343bSSimon Glass devp);
3586494d708SSimon Glass }
3596494d708SSimon Glass
alloc_priv(int size,uint flags)3602c03c463SSimon Glass static void *alloc_priv(int size, uint flags)
3612c03c463SSimon Glass {
3622c03c463SSimon Glass void *priv;
3632c03c463SSimon Glass
3642c03c463SSimon Glass if (flags & DM_FLAG_ALLOC_PRIV_DMA) {
3659ab2e5ebSFaiz Abbas size = ROUND(size, ARCH_DMA_MINALIGN);
3662c03c463SSimon Glass priv = memalign(ARCH_DMA_MINALIGN, size);
3675a8a8045SSimon Glass if (priv) {
3682c03c463SSimon Glass memset(priv, '\0', size);
3695a8a8045SSimon Glass
3705a8a8045SSimon Glass /*
3715a8a8045SSimon Glass * Ensure that the zero bytes are flushed to memory.
3725a8a8045SSimon Glass * This prevents problems if the driver uses this as
3735a8a8045SSimon Glass * both an input and an output buffer:
3745a8a8045SSimon Glass *
3755a8a8045SSimon Glass * 1. Zeroes written to buffer (here) and sit in the
3765a8a8045SSimon Glass * cache
3775a8a8045SSimon Glass * 2. Driver issues a read command to DMA
3785a8a8045SSimon Glass * 3. CPU runs out of cache space and evicts some cache
3795a8a8045SSimon Glass * data in the buffer, writing zeroes to RAM from
3805a8a8045SSimon Glass * the memset() above
3815a8a8045SSimon Glass * 4. DMA completes
3825a8a8045SSimon Glass * 5. Buffer now has some DMA data and some zeroes
3835a8a8045SSimon Glass * 6. Data being read is now incorrect
3845a8a8045SSimon Glass *
3855a8a8045SSimon Glass * To prevent this, ensure that the cache is clean
3865a8a8045SSimon Glass * within this range at the start. The driver can then
3875a8a8045SSimon Glass * use normal flush-after-write, invalidate-before-read
3885a8a8045SSimon Glass * procedures.
3895a8a8045SSimon Glass *
3905a8a8045SSimon Glass * TODO(sjg@chromium.org): Drop this microblaze
3915a8a8045SSimon Glass * exception.
3925a8a8045SSimon Glass */
3935a8a8045SSimon Glass #ifndef CONFIG_MICROBLAZE
3945a8a8045SSimon Glass flush_dcache_range((ulong)priv, (ulong)priv + size);
3955a8a8045SSimon Glass #endif
3965a8a8045SSimon Glass }
3972c03c463SSimon Glass } else {
3982c03c463SSimon Glass priv = calloc(1, size);
3992c03c463SSimon Glass }
4002c03c463SSimon Glass
4012c03c463SSimon Glass return priv;
4022c03c463SSimon Glass }
4032c03c463SSimon Glass
device_probe(struct udevice * dev)404c6db965fSSimon Glass int device_probe(struct udevice *dev)
4056494d708SSimon Glass {
4063479253dSSimon Glass const struct driver *drv;
4076494d708SSimon Glass int size = 0;
4086494d708SSimon Glass int ret;
4095a66a8ffSSimon Glass int seq;
4106494d708SSimon Glass
4116494d708SSimon Glass if (!dev)
4126494d708SSimon Glass return -EINVAL;
4136494d708SSimon Glass
4146494d708SSimon Glass if (dev->flags & DM_FLAG_ACTIVATED)
4156494d708SSimon Glass return 0;
4166494d708SSimon Glass
4176494d708SSimon Glass drv = dev->driver;
4186494d708SSimon Glass assert(drv);
4196494d708SSimon Glass
420cdeb2ba9SBin Meng /* Allocate private data if requested and not reentered */
421cdeb2ba9SBin Meng if (drv->priv_auto_alloc_size && !dev->priv) {
4222c03c463SSimon Glass dev->priv = alloc_priv(drv->priv_auto_alloc_size, drv->flags);
4236494d708SSimon Glass if (!dev->priv) {
4246494d708SSimon Glass ret = -ENOMEM;
4256494d708SSimon Glass goto fail;
4266494d708SSimon Glass }
4276494d708SSimon Glass }
428cdeb2ba9SBin Meng /* Allocate private data if requested and not reentered */
4296494d708SSimon Glass size = dev->uclass->uc_drv->per_device_auto_alloc_size;
430cdeb2ba9SBin Meng if (size && !dev->uclass_priv) {
4316494d708SSimon Glass dev->uclass_priv = calloc(1, size);
4326494d708SSimon Glass if (!dev->uclass_priv) {
4336494d708SSimon Glass ret = -ENOMEM;
4346494d708SSimon Glass goto fail;
4356494d708SSimon Glass }
4366494d708SSimon Glass }
4376494d708SSimon Glass
4386494d708SSimon Glass /* Ensure all parents are probed */
4396494d708SSimon Glass if (dev->parent) {
440e59f458dSSimon Glass size = dev->parent->driver->per_child_auto_alloc_size;
441dac8db2cSSimon Glass if (!size) {
442dac8db2cSSimon Glass size = dev->parent->uclass->uc_drv->
443dac8db2cSSimon Glass per_child_auto_alloc_size;
444dac8db2cSSimon Glass }
445cdeb2ba9SBin Meng if (size && !dev->parent_priv) {
4462c03c463SSimon Glass dev->parent_priv = alloc_priv(size, drv->flags);
447e59f458dSSimon Glass if (!dev->parent_priv) {
448e59f458dSSimon Glass ret = -ENOMEM;
449e59f458dSSimon Glass goto fail;
450e59f458dSSimon Glass }
451e59f458dSSimon Glass }
452e59f458dSSimon Glass
4536494d708SSimon Glass ret = device_probe(dev->parent);
4546494d708SSimon Glass if (ret)
4556494d708SSimon Glass goto fail;
456cdeb2ba9SBin Meng
457cdeb2ba9SBin Meng /*
458cdeb2ba9SBin Meng * The device might have already been probed during
459cdeb2ba9SBin Meng * the call to device_probe() on its parent device
460cdeb2ba9SBin Meng * (e.g. PCI bridge devices). Test the flags again
461cdeb2ba9SBin Meng * so that we don't mess up the device.
462cdeb2ba9SBin Meng */
463cdeb2ba9SBin Meng if (dev->flags & DM_FLAG_ACTIVATED)
464cdeb2ba9SBin Meng return 0;
4656494d708SSimon Glass }
4666494d708SSimon Glass
4675a66a8ffSSimon Glass seq = uclass_resolve_seq(dev);
4685a66a8ffSSimon Glass if (seq < 0) {
4695a66a8ffSSimon Glass ret = seq;
4705a66a8ffSSimon Glass goto fail;
4715a66a8ffSSimon Glass }
4725a66a8ffSSimon Glass dev->seq = seq;
4735a66a8ffSSimon Glass
474206d4d2bSSimon Glass dev->flags |= DM_FLAG_ACTIVATED;
475206d4d2bSSimon Glass
47684d26e29SSimon Glass /*
47784d26e29SSimon Glass * Process pinctrl for everything except the root device, and
4780379597eSSimon Glass * continue regardless of the result of pinctrl. Don't process pinctrl
4790379597eSSimon Glass * settings for pinctrl devices since the device may not yet be
4800379597eSSimon Glass * probed.
48184d26e29SSimon Glass */
4820379597eSSimon Glass if (dev->parent && device_get_uclass_id(dev) != UCLASS_PINCTRL)
483d90a5a30SMasahiro Yamada pinctrl_select_state(dev, "default");
484d90a5a30SMasahiro Yamada
48502c07b37SSimon Glass ret = uclass_pre_probe_device(dev);
48683c7e434SSimon Glass if (ret)
48783c7e434SSimon Glass goto fail;
48883c7e434SSimon Glass
489a327dee0SSimon Glass if (dev->parent && dev->parent->driver->child_pre_probe) {
490a327dee0SSimon Glass ret = dev->parent->driver->child_pre_probe(dev);
491a327dee0SSimon Glass if (ret)
492a327dee0SSimon Glass goto fail;
493a327dee0SSimon Glass }
494a327dee0SSimon Glass
495396e343bSSimon Glass if (drv->ofdata_to_platdata && dev_has_of_node(dev)) {
4966494d708SSimon Glass ret = drv->ofdata_to_platdata(dev);
4976494d708SSimon Glass if (ret)
4986494d708SSimon Glass goto fail;
4996494d708SSimon Glass }
5006494d708SSimon Glass
5016494d708SSimon Glass if (drv->probe) {
5026494d708SSimon Glass ret = drv->probe(dev);
50302eeb1bbSSimon Glass if (ret) {
50402eeb1bbSSimon Glass dev->flags &= ~DM_FLAG_ACTIVATED;
5056494d708SSimon Glass goto fail;
5066494d708SSimon Glass }
50702eeb1bbSSimon Glass }
5086494d708SSimon Glass
5096494d708SSimon Glass ret = uclass_post_probe_device(dev);
510206d4d2bSSimon Glass if (ret)
5116494d708SSimon Glass goto fail_uclass;
5126494d708SSimon Glass
513*d00cf31cSCody Xie if (dev->parent && device_get_uclass_id(dev) == UCLASS_PINCTRL) {
514*d00cf31cSCody Xie pinctrl_select_state(dev, "init");
515c3ab9853SPeng Fan pinctrl_select_state(dev, "default");
516*d00cf31cSCody Xie }
517c3ab9853SPeng Fan
5186494d708SSimon Glass return 0;
5196494d708SSimon Glass fail_uclass:
520706865afSStefan Roese if (device_remove(dev, DM_REMOVE_NORMAL)) {
5216494d708SSimon Glass dm_warn("%s: Device '%s' failed to remove on error path\n",
5226494d708SSimon Glass __func__, dev->name);
5236494d708SSimon Glass }
5246494d708SSimon Glass fail:
525206d4d2bSSimon Glass dev->flags &= ~DM_FLAG_ACTIVATED;
526206d4d2bSSimon Glass
5275a66a8ffSSimon Glass dev->seq = -1;
5286494d708SSimon Glass device_free(dev);
5296494d708SSimon Glass
5306494d708SSimon Glass return ret;
5316494d708SSimon Glass }
5326494d708SSimon Glass
dev_get_platdata(struct udevice * dev)53354c5d08aSHeiko Schocher void *dev_get_platdata(struct udevice *dev)
5346494d708SSimon Glass {
5356494d708SSimon Glass if (!dev) {
536964d153cSSimon Glass dm_warn("%s: null device\n", __func__);
5376494d708SSimon Glass return NULL;
5386494d708SSimon Glass }
5396494d708SSimon Glass
5406494d708SSimon Glass return dev->platdata;
5416494d708SSimon Glass }
5426494d708SSimon Glass
dev_get_parent_platdata(struct udevice * dev)543cdc133bdSSimon Glass void *dev_get_parent_platdata(struct udevice *dev)
544cdc133bdSSimon Glass {
545cdc133bdSSimon Glass if (!dev) {
54636d7cc17SSimon Glass dm_warn("%s: null device\n", __func__);
547cdc133bdSSimon Glass return NULL;
548cdc133bdSSimon Glass }
549cdc133bdSSimon Glass
550cdc133bdSSimon Glass return dev->parent_platdata;
551cdc133bdSSimon Glass }
552cdc133bdSSimon Glass
dev_get_uclass_platdata(struct udevice * dev)5535eaed880SPrzemyslaw Marczak void *dev_get_uclass_platdata(struct udevice *dev)
5545eaed880SPrzemyslaw Marczak {
5555eaed880SPrzemyslaw Marczak if (!dev) {
55636d7cc17SSimon Glass dm_warn("%s: null device\n", __func__);
5575eaed880SPrzemyslaw Marczak return NULL;
5585eaed880SPrzemyslaw Marczak }
5595eaed880SPrzemyslaw Marczak
5605eaed880SPrzemyslaw Marczak return dev->uclass_platdata;
5615eaed880SPrzemyslaw Marczak }
5625eaed880SPrzemyslaw Marczak
dev_get_priv(struct udevice * dev)56354c5d08aSHeiko Schocher void *dev_get_priv(struct udevice *dev)
5646494d708SSimon Glass {
5656494d708SSimon Glass if (!dev) {
566964d153cSSimon Glass dm_warn("%s: null device\n", __func__);
5676494d708SSimon Glass return NULL;
5686494d708SSimon Glass }
5696494d708SSimon Glass
5706494d708SSimon Glass return dev->priv;
5716494d708SSimon Glass }
572997c87bbSSimon Glass
dev_get_uclass_priv(struct udevice * dev)573e564f054SSimon Glass void *dev_get_uclass_priv(struct udevice *dev)
574e564f054SSimon Glass {
575e564f054SSimon Glass if (!dev) {
576e564f054SSimon Glass dm_warn("%s: null device\n", __func__);
577e564f054SSimon Glass return NULL;
578e564f054SSimon Glass }
579e564f054SSimon Glass
580e564f054SSimon Glass return dev->uclass_priv;
581e564f054SSimon Glass }
582e564f054SSimon Glass
dev_get_parent_priv(struct udevice * dev)583bcbe3d15SSimon Glass void *dev_get_parent_priv(struct udevice *dev)
584e59f458dSSimon Glass {
585e59f458dSSimon Glass if (!dev) {
586964d153cSSimon Glass dm_warn("%s: null device\n", __func__);
587e59f458dSSimon Glass return NULL;
588e59f458dSSimon Glass }
589e59f458dSSimon Glass
590e59f458dSSimon Glass return dev->parent_priv;
591e59f458dSSimon Glass }
592e59f458dSSimon Glass
device_get_device_tail(struct udevice * dev,int ret,struct udevice ** devp)593997c87bbSSimon Glass static int device_get_device_tail(struct udevice *dev, int ret,
594997c87bbSSimon Glass struct udevice **devp)
595997c87bbSSimon Glass {
596997c87bbSSimon Glass if (ret)
597997c87bbSSimon Glass return ret;
598997c87bbSSimon Glass
599997c87bbSSimon Glass ret = device_probe(dev);
600997c87bbSSimon Glass if (ret)
601997c87bbSSimon Glass return ret;
602997c87bbSSimon Glass
603997c87bbSSimon Glass *devp = dev;
604997c87bbSSimon Glass
605997c87bbSSimon Glass return 0;
606997c87bbSSimon Glass }
607997c87bbSSimon Glass
device_get_child(struct udevice * parent,int index,struct udevice ** devp)608997c87bbSSimon Glass int device_get_child(struct udevice *parent, int index, struct udevice **devp)
609997c87bbSSimon Glass {
610997c87bbSSimon Glass struct udevice *dev;
611997c87bbSSimon Glass
612997c87bbSSimon Glass list_for_each_entry(dev, &parent->child_head, sibling_node) {
613997c87bbSSimon Glass if (!index--)
614997c87bbSSimon Glass return device_get_device_tail(dev, 0, devp);
615997c87bbSSimon Glass }
616997c87bbSSimon Glass
617997c87bbSSimon Glass return -ENODEV;
618997c87bbSSimon Glass }
619997c87bbSSimon Glass
device_find_child_by_seq(struct udevice * parent,int seq_or_req_seq,bool find_req_seq,struct udevice ** devp)620997c87bbSSimon Glass int device_find_child_by_seq(struct udevice *parent, int seq_or_req_seq,
621997c87bbSSimon Glass bool find_req_seq, struct udevice **devp)
622997c87bbSSimon Glass {
623997c87bbSSimon Glass struct udevice *dev;
624997c87bbSSimon Glass
625997c87bbSSimon Glass *devp = NULL;
626997c87bbSSimon Glass if (seq_or_req_seq == -1)
627997c87bbSSimon Glass return -ENODEV;
628997c87bbSSimon Glass
629997c87bbSSimon Glass list_for_each_entry(dev, &parent->child_head, sibling_node) {
630997c87bbSSimon Glass if ((find_req_seq ? dev->req_seq : dev->seq) ==
631997c87bbSSimon Glass seq_or_req_seq) {
632997c87bbSSimon Glass *devp = dev;
633997c87bbSSimon Glass return 0;
634997c87bbSSimon Glass }
635997c87bbSSimon Glass }
636997c87bbSSimon Glass
637997c87bbSSimon Glass return -ENODEV;
638997c87bbSSimon Glass }
639997c87bbSSimon Glass
device_get_child_by_seq(struct udevice * parent,int seq,struct udevice ** devp)640997c87bbSSimon Glass int device_get_child_by_seq(struct udevice *parent, int seq,
641997c87bbSSimon Glass struct udevice **devp)
642997c87bbSSimon Glass {
643997c87bbSSimon Glass struct udevice *dev;
644997c87bbSSimon Glass int ret;
645997c87bbSSimon Glass
646997c87bbSSimon Glass *devp = NULL;
647997c87bbSSimon Glass ret = device_find_child_by_seq(parent, seq, false, &dev);
648997c87bbSSimon Glass if (ret == -ENODEV) {
649997c87bbSSimon Glass /*
650997c87bbSSimon Glass * We didn't find it in probed devices. See if there is one
651997c87bbSSimon Glass * that will request this seq if probed.
652997c87bbSSimon Glass */
653997c87bbSSimon Glass ret = device_find_child_by_seq(parent, seq, true, &dev);
654997c87bbSSimon Glass }
655997c87bbSSimon Glass return device_get_device_tail(dev, ret, devp);
656997c87bbSSimon Glass }
657997c87bbSSimon Glass
device_find_child_by_of_offset(struct udevice * parent,int of_offset,struct udevice ** devp)658997c87bbSSimon Glass int device_find_child_by_of_offset(struct udevice *parent, int of_offset,
659997c87bbSSimon Glass struct udevice **devp)
660997c87bbSSimon Glass {
661997c87bbSSimon Glass struct udevice *dev;
662997c87bbSSimon Glass
663997c87bbSSimon Glass *devp = NULL;
664997c87bbSSimon Glass
665997c87bbSSimon Glass list_for_each_entry(dev, &parent->child_head, sibling_node) {
666e160f7d4SSimon Glass if (dev_of_offset(dev) == of_offset) {
667997c87bbSSimon Glass *devp = dev;
668997c87bbSSimon Glass return 0;
669997c87bbSSimon Glass }
670997c87bbSSimon Glass }
671997c87bbSSimon Glass
672997c87bbSSimon Glass return -ENODEV;
673997c87bbSSimon Glass }
674997c87bbSSimon Glass
device_get_child_by_of_offset(struct udevice * parent,int node,struct udevice ** devp)675132f9bfcSSimon Glass int device_get_child_by_of_offset(struct udevice *parent, int node,
676997c87bbSSimon Glass struct udevice **devp)
677997c87bbSSimon Glass {
678997c87bbSSimon Glass struct udevice *dev;
679997c87bbSSimon Glass int ret;
680997c87bbSSimon Glass
681997c87bbSSimon Glass *devp = NULL;
682132f9bfcSSimon Glass ret = device_find_child_by_of_offset(parent, node, &dev);
683997c87bbSSimon Glass return device_get_device_tail(dev, ret, devp);
684997c87bbSSimon Glass }
685a8981d4fSSimon Glass
_device_find_global_by_of_offset(struct udevice * parent,int of_offset)6862693047aSSimon Glass static struct udevice *_device_find_global_by_of_offset(struct udevice *parent,
6872693047aSSimon Glass int of_offset)
6882693047aSSimon Glass {
6892693047aSSimon Glass struct udevice *dev, *found;
6902693047aSSimon Glass
691e160f7d4SSimon Glass if (dev_of_offset(parent) == of_offset)
6922693047aSSimon Glass return parent;
6932693047aSSimon Glass
6942693047aSSimon Glass list_for_each_entry(dev, &parent->child_head, sibling_node) {
6952693047aSSimon Glass found = _device_find_global_by_of_offset(dev, of_offset);
6962693047aSSimon Glass if (found)
6972693047aSSimon Glass return found;
6982693047aSSimon Glass }
6992693047aSSimon Glass
7002693047aSSimon Glass return NULL;
7012693047aSSimon Glass }
7022693047aSSimon Glass
device_get_global_by_of_offset(int of_offset,struct udevice ** devp)7032693047aSSimon Glass int device_get_global_by_of_offset(int of_offset, struct udevice **devp)
7042693047aSSimon Glass {
7052693047aSSimon Glass struct udevice *dev;
7062693047aSSimon Glass
7072693047aSSimon Glass dev = _device_find_global_by_of_offset(gd->dm_root, of_offset);
7082693047aSSimon Glass return device_get_device_tail(dev, dev ? 0 : -ENOENT, devp);
7092693047aSSimon Glass }
7102693047aSSimon Glass
device_find_first_child(struct udevice * parent,struct udevice ** devp)711a8981d4fSSimon Glass int device_find_first_child(struct udevice *parent, struct udevice **devp)
712a8981d4fSSimon Glass {
713a8981d4fSSimon Glass if (list_empty(&parent->child_head)) {
714a8981d4fSSimon Glass *devp = NULL;
715a8981d4fSSimon Glass } else {
716a8981d4fSSimon Glass *devp = list_first_entry(&parent->child_head, struct udevice,
717a8981d4fSSimon Glass sibling_node);
718a8981d4fSSimon Glass }
719a8981d4fSSimon Glass
720a8981d4fSSimon Glass return 0;
721a8981d4fSSimon Glass }
722a8981d4fSSimon Glass
device_find_next_child(struct udevice ** devp)723a8981d4fSSimon Glass int device_find_next_child(struct udevice **devp)
724a8981d4fSSimon Glass {
725a8981d4fSSimon Glass struct udevice *dev = *devp;
726a8981d4fSSimon Glass struct udevice *parent = dev->parent;
727a8981d4fSSimon Glass
728a8981d4fSSimon Glass if (list_is_last(&dev->sibling_node, &parent->child_head)) {
729a8981d4fSSimon Glass *devp = NULL;
730a8981d4fSSimon Glass } else {
731a8981d4fSSimon Glass *devp = list_entry(dev->sibling_node.next, struct udevice,
732a8981d4fSSimon Glass sibling_node);
733a8981d4fSSimon Glass }
734a8981d4fSSimon Glass
735a8981d4fSSimon Glass return 0;
736a8981d4fSSimon Glass }
7372ef249b4SSimon Glass
dev_get_parent(struct udevice * child)738479728cbSSimon Glass struct udevice *dev_get_parent(struct udevice *child)
739479728cbSSimon Glass {
740479728cbSSimon Glass return child->parent;
741479728cbSSimon Glass }
742479728cbSSimon Glass
dev_get_driver_data(struct udevice * dev)74339de8433SSimon Glass ulong dev_get_driver_data(struct udevice *dev)
7442ef249b4SSimon Glass {
74539de8433SSimon Glass return dev->driver_data;
7462ef249b4SSimon Glass }
747b3670531SSimon Glass
dev_get_driver_ops(struct udevice * dev)748cc73d37bSPrzemyslaw Marczak const void *dev_get_driver_ops(struct udevice *dev)
749cc73d37bSPrzemyslaw Marczak {
750cc73d37bSPrzemyslaw Marczak if (!dev || !dev->driver->ops)
751cc73d37bSPrzemyslaw Marczak return NULL;
752cc73d37bSPrzemyslaw Marczak
753cc73d37bSPrzemyslaw Marczak return dev->driver->ops;
754cc73d37bSPrzemyslaw Marczak }
755cc73d37bSPrzemyslaw Marczak
device_get_uclass_id(struct udevice * dev)756b3670531SSimon Glass enum uclass_id device_get_uclass_id(struct udevice *dev)
757b3670531SSimon Glass {
758b3670531SSimon Glass return dev->uclass->uc_drv->id;
759b3670531SSimon Glass }
760c9cac3f8SPeng Fan
dev_get_uclass_name(struct udevice * dev)761f9c370dcSPrzemyslaw Marczak const char *dev_get_uclass_name(struct udevice *dev)
762f9c370dcSPrzemyslaw Marczak {
763f9c370dcSPrzemyslaw Marczak if (!dev)
764f9c370dcSPrzemyslaw Marczak return NULL;
765f9c370dcSPrzemyslaw Marczak
766f9c370dcSPrzemyslaw Marczak return dev->uclass->uc_drv->name;
767f9c370dcSPrzemyslaw Marczak }
768f9c370dcSPrzemyslaw Marczak
device_has_children(struct udevice * dev)769c5785673SSimon Glass bool device_has_children(struct udevice *dev)
770c5785673SSimon Glass {
771c5785673SSimon Glass return !list_empty(&dev->child_head);
772c5785673SSimon Glass }
773c5785673SSimon Glass
device_has_active_children(struct udevice * dev)774c5785673SSimon Glass bool device_has_active_children(struct udevice *dev)
775c5785673SSimon Glass {
776c5785673SSimon Glass struct udevice *child;
777c5785673SSimon Glass
778c5785673SSimon Glass for (device_find_first_child(dev, &child);
779c5785673SSimon Glass child;
780c5785673SSimon Glass device_find_next_child(&child)) {
781c5785673SSimon Glass if (device_active(child))
782c5785673SSimon Glass return true;
783c5785673SSimon Glass }
784c5785673SSimon Glass
785c5785673SSimon Glass return false;
786c5785673SSimon Glass }
787c5785673SSimon Glass
device_is_last_sibling(struct udevice * dev)788c5785673SSimon Glass bool device_is_last_sibling(struct udevice *dev)
789c5785673SSimon Glass {
790c5785673SSimon Glass struct udevice *parent = dev->parent;
791c5785673SSimon Glass
792c5785673SSimon Glass if (!parent)
793c5785673SSimon Glass return false;
794c5785673SSimon Glass return list_is_last(&dev->sibling_node, &parent->child_head);
795c5785673SSimon Glass }
796f5c67ea0SSimon Glass
device_set_name_alloced(struct udevice * dev)797a2040facSSimon Glass void device_set_name_alloced(struct udevice *dev)
798a2040facSSimon Glass {
799fd1c2d9bSSimon Glass dev->flags |= DM_FLAG_NAME_ALLOCED;
800a2040facSSimon Glass }
801a2040facSSimon Glass
device_set_name(struct udevice * dev,const char * name)802f5c67ea0SSimon Glass int device_set_name(struct udevice *dev, const char *name)
803f5c67ea0SSimon Glass {
804f5c67ea0SSimon Glass name = strdup(name);
805f5c67ea0SSimon Glass if (!name)
806f5c67ea0SSimon Glass return -ENOMEM;
807f5c67ea0SSimon Glass dev->name = name;
808a2040facSSimon Glass device_set_name_alloced(dev);
809f5c67ea0SSimon Glass
810f5c67ea0SSimon Glass return 0;
811f5c67ea0SSimon Glass }
81273443b9eSMugunthan V N
device_is_compatible(struct udevice * dev,const char * compat)813911f3aefSSimon Glass bool device_is_compatible(struct udevice *dev, const char *compat)
81473443b9eSMugunthan V N {
81573443b9eSMugunthan V N const void *fdt = gd->fdt_blob;
81618aa8da9SMario Six ofnode node = dev_ofnode(dev);
81773443b9eSMugunthan V N
81818aa8da9SMario Six if (ofnode_is_np(node))
81918aa8da9SMario Six return of_device_is_compatible(ofnode_to_np(node), compat, NULL, NULL);
82018aa8da9SMario Six else
82118aa8da9SMario Six return !fdt_node_check_compatible(fdt, ofnode_to_offset(node), compat);
82273443b9eSMugunthan V N }
82373443b9eSMugunthan V N
of_machine_is_compatible(const char * compat)82473443b9eSMugunthan V N bool of_machine_is_compatible(const char *compat)
82573443b9eSMugunthan V N {
82673443b9eSMugunthan V N const void *fdt = gd->fdt_blob;
82773443b9eSMugunthan V N
82873443b9eSMugunthan V N return !fdt_node_check_compatible(fdt, 0, compat);
82973443b9eSMugunthan V N }
830