From patchwork Sat Aug 8 14:26:55 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 505327 X-Patchwork-Delegate: sjg@chromium.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id DB5AF14016A for ; Sun, 9 Aug 2015 00:27:26 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=google.com header.i=@google.com header.b=i/tQSdq/; dkim-atps=neutral Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 96FE74BDD7; Sat, 8 Aug 2015 16:27:25 +0200 (CEST) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Jasg1Al7SRZG; Sat, 8 Aug 2015 16:27:25 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 3457B4BDCE; Sat, 8 Aug 2015 16:27:25 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 9BBCD4BE33 for ; Sat, 8 Aug 2015 16:27:21 +0200 (CEST) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id AEPCvnZast_a for ; Sat, 8 Aug 2015 16:27:21 +0200 (CEST) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from mail-io0-f177.google.com (mail-io0-f177.google.com [209.85.223.177]) by theia.denx.de (Postfix) with ESMTPS id 216844BDF0 for ; Sat, 8 Aug 2015 16:27:15 +0200 (CEST) Received: by iodb91 with SMTP id b91so75437257iod.1 for ; Sat, 08 Aug 2015 07:27:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=MkzFlvJQjcf+bW2QwzXuBu4Avf57dbkyuFiz8hzMyl8=; b=i/tQSdq/GdPvPR62v4cmAXB/SjhHaQTbDQHA0KvK1RejAQln3wTJYtrnR46m+OP+RZ dKNgiK9ceWl9D3bzua1x7AFA/MwXtRKJwF+eSPgdjp7e3BlI2d5WW3/HxosP5hb9u0W8 UwuMKlzpHkWn1Y7yKhIBtKaxC8JEYPl6aDhk36ba1Z019oDwqVVj51Jy+JdggJBhjdYF rSLGudTs8NIXMPE4b/Y4VFLx0pxwIzhTWbq+mRXI+/2PpX5j1Z1SZyOOqIAzn99Gsatz ozcOKqAWG+qfos2BMjg2nwh3l8GsrzYFTJZ+j8UYQkVoVuWsRXuJ2HgTMAO6g7SnYsPl B2ow== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=MkzFlvJQjcf+bW2QwzXuBu4Avf57dbkyuFiz8hzMyl8=; b=AffaUfpDPmBYgE8XanivvzdbSZ3edchjRGZMzSG1i0kxCSctKvg0XzZ+mnRaZo7tL2 r0XStPG+4R8/bV5Ycv6rtBT6QMFMoZsUAuHQVLTSqVblbrtKtykajorS+OOLy7AH3tcv jlPoE8kbovb9K2W60gI29l081akLjNuJpar2n23Ye74KknIUpIHrnK8YKFmM0HZK/7i/ J6ciKhTy2XHFkp6ROErRANexVG5GIF7RqSci2i0FSYy5nlEK7UcmVOLjfVfv4/LSF7C1 gmtikYYuzEv6YOVLct3FTV0cbZvVgXF05K8xTe1RxzJZ6WGaEaUdbLMxCYTE0s0mtssZ xd0A== X-Gm-Message-State: ALoCoQkP+MkkRd1Cv9hFKRumSgAgEsVI2848fJP1h0YVy5/oBPfTGF7I/RfkgaHcqeGemP72GzF1 X-Received: by 10.107.7.11 with SMTP id 11mr13232008ioh.81.1439044034301; Sat, 08 Aug 2015 07:27:14 -0700 (PDT) Received: from kaki.bld.corp.google.com ([2620:0:1005:1100:d0b4:6f04:8e14:3177]) by smtp.gmail.com with ESMTPSA id o140sm9169948ioe.27.2015.08.08.07.27.12 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sat, 08 Aug 2015 07:27:13 -0700 (PDT) Received: by kaki.bld.corp.google.com (Postfix, from userid 121222) id 2F889220BF8; Sat, 8 Aug 2015 08:27:12 -0600 (MDT) From: Simon Glass To: U-Boot Mailing List Date: Sat, 8 Aug 2015 08:26:55 -0600 Message-Id: <1439044022-14481-3-git-send-email-sjg@chromium.org> X-Mailer: git-send-email 2.5.0.rc2.392.g76e840b In-Reply-To: <1439044022-14481-1-git-send-email-sjg@chromium.org> References: <1439044022-14481-1-git-send-email-sjg@chromium.org> Cc: Tom Rini , Joe Hershberger , Masahiro Yamada , Thierry Reding , York Sun Subject: [U-Boot] [PATCH v2 2/9] dm: pci: Add a way to iterate through all PCI devices X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.15 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" These functions allow iteration through all PCI devices including bridges. The children of each PCI bus are returned in turn. This can be useful for configuring, checking or enumerating all the devices. Signed-off-by: Simon Glass --- Changes in v2: - Add a comment as to why we need to scan multiple PCI controllers drivers/pci/pci-uclass.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++ include/pci.h | 25 +++++++++++++++++++ 2 files changed, 87 insertions(+) diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c index b79927e..2d5a0c1 100644 --- a/drivers/pci/pci-uclass.c +++ b/drivers/pci/pci-uclass.c @@ -775,6 +775,68 @@ static int pci_bridge_write_config(struct udevice *bus, pci_dev_t bdf, return pci_bus_write_config(hose->ctlr, bdf, offset, value, size); } +static int skip_to_next_device(struct udevice *bus, struct udevice **devp) +{ + struct udevice *dev; + int ret = 0; + + /* + * Scan through all the PCI controllers. On x86 there will only be one + * but that is not necessarily true on other hardware. + */ + do { + do { + device_find_first_child(bus, &dev); + if (dev) { + *devp = dev; + return 0; + } + } while (dev); + ret = uclass_next_device(&bus); + if (ret) + return ret; + } while (bus); + + return 0; +} + +int pci_find_next_device(struct udevice **devp) +{ + struct udevice *child = *devp; + struct udevice *bus = child->parent; + int ret; + + /* First try all the siblings */ + *devp = NULL; + while (child) { + device_find_next_child(&child); + if (child) { + *devp = child; + return 0; + } + } + + /* We ran out of siblings. Try the next bus */ + ret = uclass_next_device(&bus); + if (ret) + return ret; + + return bus ? skip_to_next_device(bus, devp) : 0; +} + +int pci_find_first_device(struct udevice **devp) +{ + struct udevice *bus; + int ret; + + *devp = NULL; + ret = uclass_first_device(UCLASS_PCI, &bus); + if (ret) + return ret; + + return skip_to_next_device(bus, devp); +} + UCLASS_DRIVER(pci) = { .id = UCLASS_PCI, .name = "pci", diff --git a/include/pci.h b/include/pci.h index d1e2765..488ff44 100644 --- a/include/pci.h +++ b/include/pci.h @@ -910,6 +910,31 @@ int pci_bus_find_devfn(struct udevice *bus, pci_dev_t find_devfn, struct udevice **devp); /** + * pci_find_first_device() - return the first available PCI device + * + * This function and pci_find_first_device() allow iteration through all + * available PCI devices on all buses. Assuming there are any, this will + * return the first one. + * + * @devp: Set to the first available device, or NULL if no more are left + * or we got an error + * @return 0 if all is OK, -ve on error (e.g. a bus/bridge failed to probe) + */ +int pci_find_first_device(struct udevice **devp); + +/** + * pci_find_next_device() - return the next available PCI device + * + * Finds the next available PCI device after the one supplied, or sets @devp + * to NULL if there are no more. + * + * @devp: On entry, the last device returned. Set to the next available + * device, or NULL if no more are left or we got an error + * @return 0 if all is OK, -ve on error (e.g. a bus/bridge failed to probe) + */ +int pci_find_next_device(struct udevice **devp); + +/** * pci_get_ff() - Returns a mask for the given access size * * @size: Access size