From patchwork Mon Feb 26 16:40:42 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Garry X-Patchwork-Id: 129692 Delivered-To: patch@linaro.org Received: by 10.80.172.228 with SMTP id x91csp3975155edc; Mon, 26 Feb 2018 07:51:46 -0800 (PST) X-Google-Smtp-Source: AH8x22634znBwp9MsJrjNXN/K/Qb3xDwg0ksTRThfMEq5ahThONgsHl/g0x4IT95Sqs1oewlM0Xk X-Received: by 2002:a17:902:724b:: with SMTP id c11-v6mr11038541pll.352.1519660306489; Mon, 26 Feb 2018 07:51:46 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1519660306; cv=none; d=google.com; s=arc-20160816; b=HFVAG1zVas5ripBKG/O4C/IPyacDqc1brvVknA1cyMJElJnuIFEhRb2OaaysOHP7NI 3BzHXgdZI04oghyIwp1MBbMgKoxeoYsnfmygmAHwIWpjLIJp2PhMUZKZ0+8Hy7imQ1S2 ZgJTkOil0qWvY2IH42CfBpzlkY8aZfHAM9FgddM83bKXKqn1B5mYelmjn0OEIz4KVkv/ 5AS9VoPkwXrL9knQA4hzKU5j6OxEps5wNAtjB14xJcSd2tqtuVKUqnc80EH5hq0HSlxl kAax0/RV907tgKLF7YpbgiZMis8HG1pSNHqzmm/f4m1LvUuekey4snlZVFgC9RSSE9fc MLzw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:arc-authentication-results; bh=ta9LhXn85vb1XFnsfKaEKeCXMIG68OSksyEOb27OeKY=; b=uacFsZu2Zuc0SJdvFtf2qV/QnxGjufDhJIZh84ii9LEn2hx+wVSeutFThO7Rvi1tZG 8Jdq7VaG14XF2Y0EYJc7mZ7ncoqdLMUHcO+8PpBdLiN3+h8hm52s1sHvrCnmn+u2Aaqp WI2zKLQnvSzvT42+aaCzfrwVlYiypiWKNj8bTDsj/AvHhffBS1R/1qXAAcdQI3luElIi xsQbwIvcodVWgWBVkhpAktdmOuRmfMS1FG4m+WxE7sWfrUh5PJBsz3Ipd+lpDhjvWoWT WfCeRXhRqU/bGgeh66rYKBHnckmPd6zbL389WBSUNg/ceXsx1Y60lVPCq8RrAJerKqAT FjNw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id k6-v6si6880334pla.333.2018.02.26.07.51.46; Mon, 26 Feb 2018 07:51:46 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752188AbeBZPuV (ORCPT + 28 others); Mon, 26 Feb 2018 10:50:21 -0500 Received: from szxga07-in.huawei.com ([45.249.212.35]:49585 "EHLO huawei.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1751576AbeBZPuO (ORCPT ); Mon, 26 Feb 2018 10:50:14 -0500 Received: from DGGEMS413-HUB.china.huawei.com (unknown [172.30.72.59]) by Forcepoint Email with ESMTP id 588292AA35624; Mon, 26 Feb 2018 23:50:06 +0800 (CST) Received: from localhost.localdomain (10.67.212.75) by DGGEMS413-HUB.china.huawei.com (10.3.19.213) with Microsoft SMTP Server id 14.3.361.1; Mon, 26 Feb 2018 23:49:58 +0800 From: John Garry To: , , , , , , , , , , , , , CC: , , , , , , , , , , , , , Subject: [PATCH v15 2/9] PCI: Remove unused __weak attribute in pci_register_io_range() Date: Tue, 27 Feb 2018 00:40:42 +0800 Message-ID: <1519663249-9850-3-git-send-email-john.garry@huawei.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1519663249-9850-1-git-send-email-john.garry@huawei.com> References: <1519663249-9850-1-git-send-email-john.garry@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.67.212.75] X-CFilter-Loop: Reflected Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Gabriele Paoloni Currently pci_register_io_range() has only one definition; therefore there is no use of the __weak attribute. Signed-off-by: Gabriele Paoloni Acked-by: Bjorn Helgaas Reviewed-by: Andy Shevchenko Tested-by: dann frazier --- drivers/pci/pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) -- 1.9.1 diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index f6a4dd1..4666a01 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -3455,7 +3455,7 @@ struct io_range { * Record the PCI IO range (expressed as CPU physical address + size). * Return a negative value if an error has occured, zero otherwise */ -int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size) +int pci_register_io_range(phys_addr_t addr, resource_size_t size) { int err = 0; From patchwork Mon Feb 26 16:40:43 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Garry X-Patchwork-Id: 129694 Delivered-To: patch@linaro.org Received: by 10.80.172.228 with SMTP id x91csp3975711edc; Mon, 26 Feb 2018 07:52:23 -0800 (PST) X-Google-Smtp-Source: AH8x2247Lfk8C7z9i1VWo/Li/wIeSIFsG3w0eA8pwdfYs/JBDPNak7zOgszER2Git9CYY7fP2Avt X-Received: by 10.98.93.87 with SMTP id r84mr11017170pfb.131.1519660342968; Mon, 26 Feb 2018 07:52:22 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1519660342; cv=none; d=google.com; s=arc-20160816; b=BGg0HVkyReXr8qaXkbLlcy/UHAHTcVxXxw268d/hOqu74ToAXNjF6DC4UxQPNn96Be LGcuh/bpNBEDHbr933z3Opghq0bgPaI733Gqn+TZdeaHKh+mrC0OHuAwhzKQ7qWMJrGv 8SA/f8y9ihoGNpBLl3/f4tkp/zwMQ4pmpexkwgLPszU4RlqP9yY7bQ/pDv+x++35nEN1 mxpYt9dV+h7hKKsRMHNqwGiFD1/ZqPSRTt7NydyxdQz+VZ+8l/mK2HnhnbHGzXF+fk66 CIRn7pQRVYpoeg7zE6j5tGxR04KIn3q5nKXaNyp8qjp/Trbdt8DnPCllEEOD3JXSUMgX li4g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:arc-authentication-results; bh=ppJcILvgppFjd8Cc8fpNhrmVgJkSnG6DpVJ9RknLtEk=; b=yEsWMEauU5llCfjwDm3fc1mkW1eov4PJi8q0JBTdEF44yKlwJQjTof90wevTC6lTPa pkTCb8Lmc/t91Whr3Vns9Uags9ozsyYaTOeuvsVSKxgfLtaaUNOtvwiBFTXygF28+b3b xE8r9s63GbJfh5cCLROQ+kco9d6m5rKvFSsioqJ7EFdjnH3GmBZxvMoXr+NjZFa/Ok8Q Q33Q7S9RfQqD6AiFGFrrDyIKGHqjd0ds3pDlONzhvU2VIxL5IGw8sFBM6VsMAhp+H9rK 9ZQAqMEfZd156OtxpN6mlrWqgfwoBd5vroZ91BrrW64R53KTmJ35aXBC7scSq8M2qnIa Esdw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id d12si5643008pgq.734.2018.02.26.07.52.22; Mon, 26 Feb 2018 07:52:22 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752441AbeBZPwU (ORCPT + 28 others); Mon, 26 Feb 2018 10:52:20 -0500 Received: from szxga07-in.huawei.com ([45.249.212.35]:49679 "EHLO huawei.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1752079AbeBZPuU (ORCPT ); Mon, 26 Feb 2018 10:50:20 -0500 Received: from DGGEMS413-HUB.china.huawei.com (unknown [172.30.72.59]) by Forcepoint Email with ESMTP id E4B0CD3604B49; Mon, 26 Feb 2018 23:50:06 +0800 (CST) Received: from localhost.localdomain (10.67.212.75) by DGGEMS413-HUB.china.huawei.com (10.3.19.213) with Microsoft SMTP Server id 14.3.361.1; Mon, 26 Feb 2018 23:49:58 +0800 From: John Garry To: , , , , , , , , , , , , , CC: , , , , , , , , , , , , , Subject: [PATCH v15 3/9] PCI: Add fwnode handler as input param of pci_register_io_range() Date: Tue, 27 Feb 2018 00:40:43 +0800 Message-ID: <1519663249-9850-4-git-send-email-john.garry@huawei.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1519663249-9850-1-git-send-email-john.garry@huawei.com> References: <1519663249-9850-1-git-send-email-john.garry@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.67.212.75] X-CFilter-Loop: Reflected Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Gabriele Paoloni In preparation for having the PCI MMIO helpers to use the new generic I/O space management(logical PIO) we need to add the fwnode handler as extra input parameter. This patch changes the signature of pci_register_io_range() and of its callers as needed. Signed-off-by: Gabriele Paoloni Acked-by: Bjorn Helgaas Acked-by: Rob Herring Reviewed-by: Andy Shevchenko Tested-by: dann frazier --- drivers/acpi/pci_root.c | 8 +++++--- drivers/of/address.c | 4 +++- drivers/pci/pci.c | 3 ++- include/linux/pci.h | 3 ++- 4 files changed, 12 insertions(+), 6 deletions(-) -- 1.9.1 diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 6fc204a..1213479 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -729,7 +729,8 @@ static void acpi_pci_root_validate_resources(struct device *dev, } } -static void acpi_pci_root_remap_iospace(struct resource_entry *entry) +static void acpi_pci_root_remap_iospace(struct fwnode_handle *fwnode, + struct resource_entry *entry) { #ifdef PCI_IOBASE struct resource *res = entry->res; @@ -738,7 +739,7 @@ static void acpi_pci_root_remap_iospace(struct resource_entry *entry) resource_size_t length = resource_size(res); unsigned long port; - if (pci_register_io_range(cpu_addr, length)) + if (pci_register_io_range(fwnode, cpu_addr, length)) goto err; port = pci_address_to_pio(cpu_addr); @@ -780,7 +781,8 @@ int acpi_pci_probe_root_resources(struct acpi_pci_root_info *info) else { resource_list_for_each_entry_safe(entry, tmp, list) { if (entry->res->flags & IORESOURCE_IO) - acpi_pci_root_remap_iospace(entry); + acpi_pci_root_remap_iospace(&device->fwnode, + entry); if (entry->res->flags & IORESOURCE_DISABLED) resource_list_destroy_entry(entry); diff --git a/drivers/of/address.c b/drivers/of/address.c index ce4d3d8..cdf047b 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c @@ -2,6 +2,7 @@ #define pr_fmt(fmt) "OF: " fmt #include +#include #include #include #include @@ -333,7 +334,8 @@ int of_pci_range_to_resource(struct of_pci_range *range, if (res->flags & IORESOURCE_IO) { unsigned long port; - err = pci_register_io_range(range->cpu_addr, range->size); + err = pci_register_io_range(&np->fwnode, range->cpu_addr, + range->size); if (err) goto invalid_range; port = pci_address_to_pio(range->cpu_addr); diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 4666a01..07290a3 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -3455,7 +3455,8 @@ struct io_range { * Record the PCI IO range (expressed as CPU physical address + size). * Return a negative value if an error has occured, zero otherwise */ -int pci_register_io_range(phys_addr_t addr, resource_size_t size) +int pci_register_io_range(struct fwnode_handle *fwnode, phys_addr_t addr, + resource_size_t size) { int err = 0; diff --git a/include/linux/pci.h b/include/linux/pci.h index 25b7a35..17cc998 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1221,7 +1221,8 @@ int __must_check pci_bus_alloc_resource(struct pci_bus *bus, void *alignf_data); -int pci_register_io_range(phys_addr_t addr, resource_size_t size); +int pci_register_io_range(struct fwnode_handle *fwnode, phys_addr_t addr, + resource_size_t size); unsigned long pci_address_to_pio(phys_addr_t addr); phys_addr_t pci_pio_to_address(unsigned long pio); int pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr); From patchwork Mon Feb 26 16:40:44 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Garry X-Patchwork-Id: 129693 Delivered-To: patch@linaro.org Received: by 10.80.172.228 with SMTP id x91csp3975414edc; Mon, 26 Feb 2018 07:52:03 -0800 (PST) X-Google-Smtp-Source: AH8x225VT/OTpPauboa5G1j8PM+GuGrTt7zu9aRg7oVTSt7Xfmdujjxi1Xf8E0wu6xt1yIC3gW+Q X-Received: by 10.98.19.146 with SMTP id 18mr11069746pft.3.1519660323548; Mon, 26 Feb 2018 07:52:03 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1519660323; cv=none; d=google.com; s=arc-20160816; b=QA0CY/dzMdCovi4g/zM5GrGI2HVLO7hrWC6OUqBNwhYwAlvAhXrp/vEWY1LVUeMU9z KO47zU1i6q6mG+ftYfD9Yq7TPQVcN+do6v8w86BAUssJzNe5FAPm+5BMA69R3Wx3MO3n Vi8Tw8vVr6mj2S3OOKb11pemfEJEqnnZTrDQJ1BEppDyK35kqyXN7S/izaa9CSSsuElP m0vl6h/PEEbINGXBxKAMUOdpjFd3R0F2Ra1rYxdQO7UXM4OepUHubHL8viuJL7/Fk5vH 9tB6lUAD8XOKfjki4HND/tsr4UgqKlC6SpxpAa0aRNcpqV4N2y7EbD6EnOJ9n0AX42Ts lN1g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:arc-authentication-results; bh=yHujM6xcjQYoK4GeKKJ+aO72txxyen4/fJ8zNv0jvus=; b=aVnHO61GQ5hEYiiyilCSiw9+TA5TVr/DdCIevYEDt1bsiXs/vlM69hsBvN8KgXkaqJ A1lwuzz/NT4eK+UmW5vh5bz8xwzjDz8yX/W5o7/TiVsyoXykp+9y3rdBHw0sbxMHprvv OM232MfgN5qPPYQ4BH0f7AYaun0V3lD8LPxNl/n7wMQq1X41bjrjIFFBL2jvdDZHLl5M INQ0eUcfRlmuONCWkNNu259CPf19mCi+r5S0fruiMO8marO6w2FDN0Xdu1/PRe+tSRPm dP9gr2SMMUkdUNxcESV7f3GSNaZmGj75/9MWWaZuEitHl7Buq0UWH7HaHx2XOxZwuqs/ aALw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id e123si5670872pgc.406.2018.02.26.07.52.03; Mon, 26 Feb 2018 07:52:03 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752431AbeBZPwA (ORCPT + 28 others); Mon, 26 Feb 2018 10:52:00 -0500 Received: from szxga07-in.huawei.com ([45.249.212.35]:49344 "EHLO huawei.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1751671AbeBZPuV (ORCPT ); Mon, 26 Feb 2018 10:50:21 -0500 Received: from DGGEMS413-HUB.china.huawei.com (unknown [172.30.72.59]) by Forcepoint Email with ESMTP id 0FFF733B75693; Mon, 26 Feb 2018 23:50:06 +0800 (CST) Received: from localhost.localdomain (10.67.212.75) by DGGEMS413-HUB.china.huawei.com (10.3.19.213) with Microsoft SMTP Server id 14.3.361.1; Mon, 26 Feb 2018 23:49:59 +0800 From: John Garry To: , , , , , , , , , , , , , CC: , , , , , , , , , , , , , Subject: [PATCH v15 4/9] PCI: Apply the new generic I/O management on PCI IO hosts Date: Tue, 27 Feb 2018 00:40:44 +0800 Message-ID: <1519663249-9850-5-git-send-email-john.garry@huawei.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1519663249-9850-1-git-send-email-john.garry@huawei.com> References: <1519663249-9850-1-git-send-email-john.garry@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.67.212.75] X-CFilter-Loop: Reflected Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Zhichang Yuan After introducing the new generic I/O space management(Logical PIO), the original PCI MMIO relevant helpers need to be updated based on the new interfaces defined in logical PIO. This patch adapts the corresponding code to match the changes introduced by logical PIO. Signed-off-by: Zhichang Yuan Signed-off-by: Gabriele Paoloni Signed-off-by: Arnd Bergmann #earlier draft Acked-by: Bjorn Helgaas Reviewed-by: Andy Shevchenko Tested-by: dann frazier --- drivers/pci/pci.c | 92 +++++++++--------------------------------------- include/asm-generic/io.h | 2 +- 2 files changed, 18 insertions(+), 76 deletions(-) -- 1.9.1 diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 07290a3..83a263f 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -3440,17 +3441,6 @@ int pci_request_regions_exclusive(struct pci_dev *pdev, const char *res_name) } EXPORT_SYMBOL(pci_request_regions_exclusive); -#ifdef PCI_IOBASE -struct io_range { - struct list_head list; - phys_addr_t start; - resource_size_t size; -}; - -static LIST_HEAD(io_range_list); -static DEFINE_SPINLOCK(io_range_lock); -#endif - /* * Record the PCI IO range (expressed as CPU physical address + size). * Return a negative value if an error has occured, zero otherwise @@ -3458,51 +3448,28 @@ struct io_range { int pci_register_io_range(struct fwnode_handle *fwnode, phys_addr_t addr, resource_size_t size) { - int err = 0; - + int ret = 0; #ifdef PCI_IOBASE - struct io_range *range; - resource_size_t allocated_size = 0; - - /* check if the range hasn't been previously recorded */ - spin_lock(&io_range_lock); - list_for_each_entry(range, &io_range_list, list) { - if (addr >= range->start && addr + size <= range->start + size) { - /* range already registered, bail out */ - goto end_register; - } - allocated_size += range->size; - } + struct logic_pio_hwaddr *range; - /* range not registed yet, check for available space */ - if (allocated_size + size - 1 > IO_SPACE_LIMIT) { - /* if it's too big check if 64K space can be reserved */ - if (allocated_size + SZ_64K - 1 > IO_SPACE_LIMIT) { - err = -E2BIG; - goto end_register; - } - - size = SZ_64K; - pr_warn("Requested IO range too big, new size set to 64K\n"); - } + if (!size || addr + size < addr) + return -EINVAL; - /* add the range to the list */ range = kzalloc(sizeof(*range), GFP_ATOMIC); - if (!range) { - err = -ENOMEM; - goto end_register; - } + if (!range) + return -ENOMEM; - range->start = addr; + range->fwnode = fwnode; range->size = size; + range->hw_start = addr; + range->flags = LOGIC_PIO_CPU_MMIO; - list_add_tail(&range->list, &io_range_list); - -end_register: - spin_unlock(&io_range_lock); + ret = logic_pio_register_range(range); + if (ret) + kfree(range); #endif - return err; + return ret; } phys_addr_t pci_pio_to_address(unsigned long pio) @@ -3510,21 +3477,10 @@ phys_addr_t pci_pio_to_address(unsigned long pio) phys_addr_t address = (phys_addr_t)OF_BAD_ADDR; #ifdef PCI_IOBASE - struct io_range *range; - resource_size_t allocated_size = 0; - - if (pio > IO_SPACE_LIMIT) + if (pio >= MMIO_UPPER_LIMIT) return address; - spin_lock(&io_range_lock); - list_for_each_entry(range, &io_range_list, list) { - if (pio >= allocated_size && pio < allocated_size + range->size) { - address = range->start + pio - allocated_size; - break; - } - allocated_size += range->size; - } - spin_unlock(&io_range_lock); + address = logic_pio_to_hwaddr(pio); #endif return address; @@ -3533,21 +3489,7 @@ phys_addr_t pci_pio_to_address(unsigned long pio) unsigned long __weak pci_address_to_pio(phys_addr_t address) { #ifdef PCI_IOBASE - struct io_range *res; - resource_size_t offset = 0; - unsigned long addr = -1; - - spin_lock(&io_range_lock); - list_for_each_entry(res, &io_range_list, list) { - if (address >= res->start && address < res->start + res->size) { - addr = address - res->start + offset; - break; - } - offset += res->size; - } - spin_unlock(&io_range_lock); - - return addr; + return logic_pio_trans_cpuaddr(address); #else if (address > IO_SPACE_LIMIT) return (unsigned long)-1; diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h index f76fbd6..0016413 100644 --- a/include/asm-generic/io.h +++ b/include/asm-generic/io.h @@ -901,7 +901,7 @@ static inline void __iomem *ioremap_wt(phys_addr_t offset, size_t size) #define ioport_map ioport_map static inline void __iomem *ioport_map(unsigned long port, unsigned int nr) { - return PCI_IOBASE + (port & IO_SPACE_LIMIT); + return PCI_IOBASE + (port & MMIO_UPPER_LIMIT); } #endif From patchwork Mon Feb 26 16:40:46 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Garry X-Patchwork-Id: 129695 Delivered-To: patch@linaro.org Received: by 10.80.172.228 with SMTP id x91csp3976023edc; Mon, 26 Feb 2018 07:52:42 -0800 (PST) X-Google-Smtp-Source: AH8x224+Xwuc8OX0soKR9QHKAFIexEhM8hKGDv4AgPE8YRsVZfhuYaoCeC54tnVy1yOLrNERF08m X-Received: by 10.167.130.193 with SMTP id f1mr10834019pfn.241.1519660362577; Mon, 26 Feb 2018 07:52:42 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1519660362; cv=none; d=google.com; s=arc-20160816; b=JcmirdggRRM5aLga5Als8yP9C3b+9yFo9jgON5+qhJsS2frzy1CWyVAzz37JBfsgBE 8lQL2vWqYPre/gz4AeGTY+NCLaYFCbCOPubB30jJX9lpec3fA9YdPrYiC8uzhoRcaphV QywHsdlE00A0uq3C3WtskI2AspuoR9vZgf79c+o7Y56itecPBkweMEiPMzleQ4Ln8RL6 PeE8As0sSctPjEN/kUeg7vtZeKhff4hXxJtilW3ycRXcNvZjRECB7wkWWjpzSD+mAfIb OM+gqPItemc8gVBJ75Fr/GCML13R7M8w+pl585h/p54RotzKSMMTkcT/tw61exaoa6wp 3xTA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:arc-authentication-results; bh=tHUUQhuDWftuZhniSxUzOmX4vZgzQ9dsn6uM1zVtxv8=; b=Vor8RcLsFUwI7i5VsHD1tnG+Wc6hBq0BNcMomaM+YRbnNg+EnBV3HdZAO6W2KwODma j+uPME5wt6v9xFLT3Vx1tcdU+YGXqp/I4hz2v3cSCNWXIaXDStSLI0V5KvgRF3tVT5uS WX9x9tAZzbBjjDqUDwAOmxHfO0EPJiz6dUeod+BDseW6RweXGjeKHYCWMcg/CD6C0f69 7lvx1Co4Uf/PKD/Bnb0ZEligxR28WaQqn3Zr1Du7Px5dN7KW2ZQpqby2c3tgoxTBWZIU T5/CMUykh63fPkLm3/gbGZb2lvV7/zOhi6A7M6WX5RtyWgE7pTmBIBeASuCknOnpoW3v kKag== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id t12si5687028pgf.575.2018.02.26.07.52.42; Mon, 26 Feb 2018 07:52:42 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752463AbeBZPwj (ORCPT + 28 others); Mon, 26 Feb 2018 10:52:39 -0500 Received: from szxga07-in.huawei.com ([45.249.212.35]:49667 "EHLO huawei.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1752009AbeBZPuT (ORCPT ); Mon, 26 Feb 2018 10:50:19 -0500 Received: from DGGEMS413-HUB.china.huawei.com (unknown [172.30.72.59]) by Forcepoint Email with ESMTP id 6EAFF57160AB6; Mon, 26 Feb 2018 23:50:06 +0800 (CST) Received: from localhost.localdomain (10.67.212.75) by DGGEMS413-HUB.china.huawei.com (10.3.19.213) with Microsoft SMTP Server id 14.3.361.1; Mon, 26 Feb 2018 23:49:59 +0800 From: John Garry To: , , , , , , , , , , , , , CC: , , , , , , , , , , , , , Subject: [PATCH v15 6/9] HISI LPC: Support the LPC host on Hip06/Hip07 with DT bindings Date: Tue, 27 Feb 2018 00:40:46 +0800 Message-ID: <1519663249-9850-7-git-send-email-john.garry@huawei.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1519663249-9850-1-git-send-email-john.garry@huawei.com> References: <1519663249-9850-1-git-send-email-john.garry@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.67.212.75] X-CFilter-Loop: Reflected Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Zhichang Yuan The low-pin-count(LPC) interface of Hip06/Hip07 accesses the peripherals in I/O port addresses. This patch implements the LPC host controller driver which perform the I/O operations on the underlying hardware. We don't want to touch those existing peripherals' driver, such as ipmi-bt. So this driver applies the indirect-IO introduced in the previous patch after registering an indirect-IO node to the indirect-IO devices list which will be searched in the I/O accessors to retrieve the host-local I/O port. The driver config is set as a bool instead of a trisate. The reason here is that, by the very nature of the driver providing a logical PIO range, it does not make sense to have this driver as a loadable module. Another more specific reason is that the Huawei D03 board which includes hip06 SoC requires the LPC bus for UART console, so should be built in. Signed-off-by: Zou Rongrong Signed-off-by: Zhichang Yuan Signed-off-by: John Garry Acked-by: Rob Herring #dts part Reviewed-by: Andy Shevchenko Tested-by: dann frazier --- .../arm/hisilicon/hisilicon-low-pin-count.txt | 33 ++ drivers/bus/Kconfig | 8 + drivers/bus/Makefile | 2 + drivers/bus/hisi_lpc.c | 427 +++++++++++++++++++++ 4 files changed, 470 insertions(+) create mode 100644 Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt create mode 100644 drivers/bus/hisi_lpc.c -- 1.9.1 diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt new file mode 100644 index 0000000..213181f --- /dev/null +++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt @@ -0,0 +1,33 @@ +Hisilicon Hip06 low-pin-count device + Hisilicon Hip06 SoCs implement a Low Pin Count (LPC) controller, which + provides I/O access to some legacy ISA devices. + Hip06 is based on arm64 architecture where there is no I/O space. So, the + I/O ports here are not cpu addresses, and there is no 'ranges' property in + LPC device node. + +Required properties: +- compatible: value should be as follows: + (a) "hisilicon,hip06-lpc" + (b) "hisilicon,hip07-lpc" +- #address-cells: must be 2 which stick to the ISA/EISA binding doc. +- #size-cells: must be 1 which stick to the ISA/EISA binding doc. +- reg: base memory range where the LPC register set is mapped. + +Note: + The node name before '@' must be "isa" to represent the binding stick to the + ISA/EISA binding specification. + +Example: + +isa@a01b0000 { + compatible = "hisilicon,hip06-lpc"; + #address-cells = <2>; + #size-cells = <1>; + reg = <0x0 0xa01b0000 0x0 0x1000>; + + ipmi0: bt@e4 { + compatible = "ipmi-bt"; + device_type = "ipmi"; + reg = <0x01 0xe4 0x04>; + }; +}; diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig index 769599b..0097317 100644 --- a/drivers/bus/Kconfig +++ b/drivers/bus/Kconfig @@ -65,6 +65,14 @@ config BRCMSTB_GISB_ARB arbiter. This driver provides timeout and target abort error handling and internal bus master decoding. +config HISILICON_LPC + bool "Support for ISA I/O space on Hisilicon hip06/7" + depends on ARM64 && (ARCH_HISI || COMPILE_TEST) + select INDIRECT_PIO + help + Driver needed for some legacy ISA devices attached to Low-Pin-Count + on Hisilicon hip06/7 SoC. + config IMX_WEIM bool "Freescale EIM DRIVER" depends on ARCH_MXC diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile index b666c49..b8d9ffb 100644 --- a/drivers/bus/Makefile +++ b/drivers/bus/Makefile @@ -12,6 +12,8 @@ obj-$(CONFIG_BRCMSTB_GISB_ARB) += brcmstb_gisb.o # DPAA2 fsl-mc bus obj-$(CONFIG_FSL_MC_BUS) += fsl-mc/ +obj-$(CONFIG_HISILICON_LPC) += hisi_lpc.o + obj-$(CONFIG_IMX_WEIM) += imx-weim.o obj-$(CONFIG_MIPS_CDMM) += mips_cdmm.o obj-$(CONFIG_MVEBU_MBUS) += mvebu-mbus.o diff --git a/drivers/bus/hisi_lpc.c b/drivers/bus/hisi_lpc.c new file mode 100644 index 0000000..c2f3c14 --- /dev/null +++ b/drivers/bus/hisi_lpc.c @@ -0,0 +1,427 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved. + * Author: Zhichang Yuan + * Author: Zou Rongrong + * Author: John Garry + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRV_NAME "hisi-lpc" + +/* + * Setting this bit means each IO operation will target to a + * different port address: + * 0 means repeatedly IO operations will stick on the same port, + * such as BT; + */ +#define FG_INCRADDR_LPC 0x02 + +struct lpc_cycle_para { + unsigned int opflags; + unsigned int csize; /* the data length of each operation */ +}; + +struct hisi_lpc_dev { + spinlock_t cycle_lock; + void __iomem *membase; + struct logic_pio_hwaddr *io_host; +}; + +/* The maxIO cycle counts supported is four per operation at maximum */ +#define LPC_MAX_DWIDTH 4 + +#define LPC_REG_STARTUP_SIGNAL 0x00 +#define LPC_REG_STARTUP_SIGNAL_START BIT(0) +#define LPC_REG_OP_STATUS 0x04 +#define LPC_REG_OP_STATUS_IDLE BIT(0) +#define LPC_REG_OP_STATUS_FINISHED BIT(1) +#define LPC_REG_OP_LEN 0x10 /* LPC cycles count per start */ +#define LPC_REG_CMD 0x14 +#define LPC_REG_CMD_OP BIT(0) /* 0: read, 1: write */ +#define LPC_REG_CMD_SAMEADDR BIT(3) +#define LPC_REG_ADDR 0x20 /* target address */ +#define LPC_REG_WDATA 0x24 /* write FIFO */ +#define LPC_REG_RDATA 0x28 /* read FIFO */ + +/* The minimal nanosecond interval for each query on LPC cycle status. */ +#define LPC_NSEC_PERWAIT 100 + +/* + * The maximum waiting time is about 128us. + * It is specific for stream I/O, such as ins. + * The fastest IO cycle time is about 390ns, but the worst case will wait + * for extra 256 lpc clocks, so (256 + 13) * 30ns = 8 us. The maximum + * burst cycles is 16. So, the maximum waiting time is about 128us under + * worst case. + * choose 1300 as the maximum. + */ +#define LPC_MAX_WAITCNT 1300 +/* About 10us. This is specific for single IO operation, such as inb. */ +#define LPC_PEROP_WAITCNT 100 + +static inline int wait_lpc_idle(unsigned char *mbase, + unsigned int waitcnt) { + do { + u32 status; + + status = readl(mbase + LPC_REG_OP_STATUS); + if (status & LPC_REG_OP_STATUS_IDLE) + return (status & LPC_REG_OP_STATUS_FINISHED) ? 0 : -EIO; + ndelay(LPC_NSEC_PERWAIT); + } while (waitcnt--); + + return -ETIME; +} + +/* + * hisi_lpc_target_in - trigger a series of LPC cycles for read operation + * @lpcdev: pointer to hisi lpc device + * @para: some parameters used to control the lpc I/O operations + * @addr: the lpc I/O target port address + * @buf: where the read back data is stored + * @opcnt: how many I/O operations required, i.e. data width + * + * Returns 0 on success, non-zero on fail. + */ +static int +hisi_lpc_target_in(struct hisi_lpc_dev *lpcdev, struct lpc_cycle_para *para, + unsigned long addr, unsigned char *buf, + unsigned long opcnt) +{ + unsigned int cmd_word; + unsigned int waitcnt; + unsigned long flags; + int ret; + + if (!buf || !opcnt || !para || !para->csize || !lpcdev) + return -EINVAL; + + cmd_word = 0; /* IO mode, Read */ + waitcnt = LPC_PEROP_WAITCNT; + if (!(para->opflags & FG_INCRADDR_LPC)) { + cmd_word |= LPC_REG_CMD_SAMEADDR; + waitcnt = LPC_MAX_WAITCNT; + } + + /* whole operation must be atomic */ + spin_lock_irqsave(&lpcdev->cycle_lock, flags); + + writel_relaxed(opcnt, lpcdev->membase + LPC_REG_OP_LEN); + + writel_relaxed(cmd_word, lpcdev->membase + LPC_REG_CMD); + + writel_relaxed(addr, lpcdev->membase + LPC_REG_ADDR); + + writel(LPC_REG_STARTUP_SIGNAL_START, + lpcdev->membase + LPC_REG_STARTUP_SIGNAL); + + /* whether the operation is finished */ + ret = wait_lpc_idle(lpcdev->membase, waitcnt); + if (ret) { + spin_unlock_irqrestore(&lpcdev->cycle_lock, flags); + return ret; + } + + do { + *buf++ = readb(lpcdev->membase + LPC_REG_RDATA); + } while (--opcnt); + + spin_unlock_irqrestore(&lpcdev->cycle_lock, flags); + + return 0; +} + +/* + * hisi_lpc_target_out - trigger a series of LPC cycles for write operation + * @lpcdev: pointer to hisi lpc device + * @para: some parameters used to control the lpc I/O operations + * @addr: the lpc I/O target port address + * @buf: where the data to be written is stored + * @opcnt: how many I/O operations required, i.e. data width + * + * Returns 0 on success, non-zero on fail. + */ +static int +hisi_lpc_target_out(struct hisi_lpc_dev *lpcdev, struct lpc_cycle_para *para, + unsigned long addr, const unsigned char *buf, + unsigned long opcnt) +{ + unsigned int waitcnt; + unsigned long flags; + u32 cmd_word; + int ret; + + if (!buf || !opcnt || !para || !lpcdev) + return -EINVAL; + + /* default is increasing address */ + cmd_word = LPC_REG_CMD_OP; /* IO mode, write */ + waitcnt = LPC_PEROP_WAITCNT; + if (!(para->opflags & FG_INCRADDR_LPC)) { + cmd_word |= LPC_REG_CMD_SAMEADDR; + waitcnt = LPC_MAX_WAITCNT; + } + + spin_lock_irqsave(&lpcdev->cycle_lock, flags); + + writel_relaxed(opcnt, lpcdev->membase + LPC_REG_OP_LEN); + writel_relaxed(cmd_word, lpcdev->membase + LPC_REG_CMD); + writel_relaxed(addr, lpcdev->membase + LPC_REG_ADDR); + + do { + writeb(*buf++, lpcdev->membase + LPC_REG_WDATA); + } while (--opcnt); + + writel(LPC_REG_STARTUP_SIGNAL_START, + lpcdev->membase + LPC_REG_STARTUP_SIGNAL); + + /* whether the operation is finished */ + ret = wait_lpc_idle(lpcdev->membase, waitcnt); + + spin_unlock_irqrestore(&lpcdev->cycle_lock, flags); + + return ret; +} + +static inline unsigned long +hisi_lpc_pio_to_addr(struct hisi_lpc_dev *lpcdev, unsigned long pio) +{ + return pio - lpcdev->io_host->io_start + + lpcdev->io_host->hw_start; +} + +/* + * hisi_lpc_comm_in - input the data in a single operation + * @hostdata: pointer to the device information relevant to LPC controller. + * @pio: the target I/O port address. + * @dwidth: the data length required to read from the target I/O port. + * + * When success, data is returned. Otherwise, ~0 is returned. + */ +static u32 hisi_lpc_comm_in(void *hostdata, unsigned long pio, size_t dwidth) +{ + struct hisi_lpc_dev *lpcdev = hostdata; + struct lpc_cycle_para iopara; + unsigned long addr; + u32 rd_data = 0; + int ret; + + if (!lpcdev || !dwidth || dwidth > LPC_MAX_DWIDTH) + return ~0; + + addr = hisi_lpc_pio_to_addr(lpcdev, pio); + + iopara.opflags = FG_INCRADDR_LPC; + iopara.csize = dwidth; + + ret = hisi_lpc_target_in(lpcdev, &iopara, addr, + (unsigned char *)&rd_data, dwidth); + if (ret) + return ~0; + + return le32_to_cpu(rd_data); +} + +/* + * hisi_lpc_comm_out - output the data in a single operation + * @hostdata: pointer to the device information relevant to LPC controller. + * @pio: the target I/O port address. + * @val: a value to be outputted from caller, maximum is four bytes. + * @dwidth: the data width required writing to the target I/O port. + * + * This function is corresponding to out(b,w,l) only + * + */ +static void hisi_lpc_comm_out(void *hostdata, unsigned long pio, + u32 val, size_t dwidth) +{ + struct hisi_lpc_dev *lpcdev = hostdata; + struct lpc_cycle_para iopara; + const unsigned char *buf; + unsigned long addr; + + if (!lpcdev || !dwidth || dwidth > LPC_MAX_DWIDTH) + return; + + val = cpu_to_le32(val); + + buf = (const unsigned char *)&val; + addr = hisi_lpc_pio_to_addr(lpcdev, pio); + + iopara.opflags = FG_INCRADDR_LPC; + iopara.csize = dwidth; + + hisi_lpc_target_out(lpcdev, &iopara, addr, buf, dwidth); +} + +/* + * hisi_lpc_comm_ins - input the data in the buffer in multiple operations + * @hostdata: pointer to the device information relevant to LPC controller. + * @pio: the target I/O port address. + * @buffer: a buffer where read/input data bytes are stored. + * @dwidth: the data width required writing to the target I/O port. + * @count: how many data units whose length is dwidth will be read. + * + * When success, the data read back is stored in buffer pointed by buffer. + * Returns 0 on success, -errno otherwise + * + */ +static u32 +hisi_lpc_comm_ins(void *hostdata, unsigned long pio, void *buffer, + size_t dwidth, unsigned int count) +{ + struct hisi_lpc_dev *lpcdev = hostdata; + unsigned char *buf = buffer; + struct lpc_cycle_para iopara; + unsigned long addr; + + if (!lpcdev || !buf || !count || !dwidth || dwidth > LPC_MAX_DWIDTH) + return -EINVAL; + + iopara.opflags = 0; + if (dwidth > 1) + iopara.opflags |= FG_INCRADDR_LPC; + iopara.csize = dwidth; + + addr = hisi_lpc_pio_to_addr(lpcdev, pio); + + do { + int ret; + + ret = hisi_lpc_target_in(lpcdev, &iopara, addr, + buf, dwidth); + if (ret) + return ret; + buf += dwidth; + } while (--count); + + return 0; +} + +/* + * hisi_lpc_comm_outs - output the data in the buffer in multiple operations + * @hostdata: pointer to the device information relevant to LPC controller. + * @pio: the target I/O port address. + * @buffer: a buffer where write/output data bytes are stored. + * @dwidth: the data width required writing to the target I/O port . + * @count: how many data units whose length is dwidth will be written. + * + */ +static void +hisi_lpc_comm_outs(void *hostdata, unsigned long pio, const void *buffer, + size_t dwidth, unsigned int count) +{ + struct hisi_lpc_dev *lpcdev = hostdata; + struct lpc_cycle_para iopara; + const unsigned char *buf = buffer; + unsigned long addr; + + if (!lpcdev || !buf || !count || !dwidth || dwidth > LPC_MAX_DWIDTH) + return; + + iopara.opflags = 0; + if (dwidth > 1) + iopara.opflags |= FG_INCRADDR_LPC; + iopara.csize = dwidth; + + addr = hisi_lpc_pio_to_addr(lpcdev, pio); + do { + if (hisi_lpc_target_out(lpcdev, &iopara, addr, buf, + dwidth)) + break; + buf += dwidth; + } while (--count); +} + +static const struct logic_pio_host_ops hisi_lpc_ops = { + .in = hisi_lpc_comm_in, + .out = hisi_lpc_comm_out, + .ins = hisi_lpc_comm_ins, + .outs = hisi_lpc_comm_outs, +}; + +/* + * hisi_lpc_probe - the probe callback function for hisi lpc host, + * will finish all the initialization. + * @pdev: the platform device corresponding to hisi lpc host + * + * Returns 0 on success, non-zero on fail. + */ +static int hisi_lpc_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct acpi_device *acpi_device = ACPI_COMPANION(dev); + struct logic_pio_hwaddr *range; + struct hisi_lpc_dev *lpcdev; + struct resource *res; + int ret; + + lpcdev = devm_kzalloc(dev, sizeof(struct hisi_lpc_dev), GFP_KERNEL); + if (!lpcdev) + return -ENOMEM; + + spin_lock_init(&lpcdev->cycle_lock); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + lpcdev->membase = devm_ioremap_resource(dev, res); + if (IS_ERR(lpcdev->membase)) + return PTR_ERR(lpcdev->membase); + + range = devm_kzalloc(dev, sizeof(*range), GFP_KERNEL); + if (!range) + return -ENOMEM; + range->fwnode = dev->fwnode; + range->flags = LOGIC_PIO_INDIRECT; + range->size = PIO_INDIRECT_SIZE; + + ret = logic_pio_register_range(range); + if (ret) { + dev_err(dev, "register IO range failed (%d)!\n", ret); + return ret; + } + lpcdev->io_host = range; + + /* register the LPC host PIO resources */ + if (!acpi_device) + ret = of_platform_populate(dev->of_node, NULL, NULL, dev); + if (ret) + return ret; + + lpcdev->io_host->hostdata = lpcdev; + lpcdev->io_host->ops = &hisi_lpc_ops; + + dev_info(dev, "registered range[%pa - sz:%pa]\n", + &lpcdev->io_host->io_start, + &lpcdev->io_host->size); + + return ret; +} + +static const struct of_device_id hisi_lpc_of_match[] = { + { .compatible = "hisilicon,hip06-lpc", }, + { .compatible = "hisilicon,hip07-lpc", }, + {} +}; + +static struct platform_driver hisi_lpc_driver = { + .driver = { + .name = DRV_NAME, + .of_match_table = hisi_lpc_of_match, + }, + .probe = hisi_lpc_probe, +}; + +builtin_platform_driver(hisi_lpc_driver); From patchwork Mon Feb 26 16:40:48 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Garry X-Patchwork-Id: 129697 Delivered-To: patch@linaro.org Received: by 10.80.172.228 with SMTP id x91csp3976761edc; Mon, 26 Feb 2018 07:53:28 -0800 (PST) X-Google-Smtp-Source: AH8x227rdG0WsW4WcO0tR857TGuuOU15sPNu5muXQaBc+/QXLS0Wg/ojvt2vQQ68QHnziAvOaS90 X-Received: by 10.101.73.7 with SMTP id p7mr8681636pgs.250.1519660408338; Mon, 26 Feb 2018 07:53:28 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1519660408; cv=none; d=google.com; s=arc-20160816; b=P8QXIViyMkGoaVKrTMFUi05WHcAlMDFt3knXZAET3JqcIg2qrU4PdP77JMbMFC/9GQ ja/AFxbe11BQOToxu7glFexrOvM62cxPeiJd+vjzuQPMuLdrhRek/uXB1KQsr8PtZ/+C /qmCQmROMnWkBFwplBrhU+btoIqnXfv30G2ax+ij9kP7PDb1SJYjMpDWMD+6cngrBmQO 7hQ6CkM2PFyA9zEdF5hpAInKq5MhRyMuzTOXPB9F4V/QdAz3TSQ6mhxzEmz9jitKXdBs L1Dn1lx4Q4O6DZZGYBqwb4wkfT9NDd1WdekTkOaOvbJyoCkjZVY9rx7szoBhjsM+F+kO i2tQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:arc-authentication-results; bh=6PfO9WsrOzEx3rrYYECgVGyouxdFOLMokja/o1WS3io=; b=JPofwPndBv2d28ccO0CJudyAYt8t8BoeEEwzxCp+QxJZ1Uq6w3T5TlZCeGyzAr0GGa MYKQvUOtZWLeu3ozdgdWWXnk70h+Wbvjn+p6hizMN4bNUbFe5FOY+8D8jQOmkLDY9zJO jY5Kxx7iK4hqBJX5gUGLmBHECdIvtWq3fr20HmpEekc6DQCJC64JzBSG+FZWB5ZSr4+t BObcj+04i1Wglcx0ffO3Yw0QFWnoYlvtZwcNjCAgGx3oJEbMEGSYih4+rVD0Rv0jD58m RcVZOmevEt0elndcg3A1RADK1IBVn7ZVkDGryQRbeDntlcN1UtqEvfWujOWf7UaQPl5H Oa+g== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id m37-v6si6915231pla.244.2018.02.26.07.53.28; Mon, 26 Feb 2018 07:53:28 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752428AbeBZPxA (ORCPT + 28 others); Mon, 26 Feb 2018 10:53:00 -0500 Received: from szxga07-in.huawei.com ([45.249.212.35]:49666 "EHLO huawei.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1751926AbeBZPuS (ORCPT ); Mon, 26 Feb 2018 10:50:18 -0500 Received: from DGGEMS413-HUB.china.huawei.com (unknown [172.30.72.59]) by Forcepoint Email with ESMTP id 9DD2A6C97218C; Mon, 26 Feb 2018 23:50:06 +0800 (CST) Received: from localhost.localdomain (10.67.212.75) by DGGEMS413-HUB.china.huawei.com (10.3.19.213) with Microsoft SMTP Server id 14.3.361.1; Mon, 26 Feb 2018 23:50:00 +0800 From: John Garry To: , , , , , , , , , , , , , CC: , , , , , , , , , , , , , Subject: [PATCH v15 8/9] HISI LPC: Add ACPI support Date: Tue, 27 Feb 2018 00:40:48 +0800 Message-ID: <1519663249-9850-9-git-send-email-john.garry@huawei.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1519663249-9850-1-git-send-email-john.garry@huawei.com> References: <1519663249-9850-1-git-send-email-john.garry@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.67.212.75] X-CFilter-Loop: Reflected Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Based on the previous patches, this patch supports the LPC host on hip06/hip07 for ACPI FW. It is the responsibility of the LPC host driver to enumerate the child devices, as the ACPI scan code will not enumerate children of "indirect IO" hosts. The ACPI table for the LPC host controller and the child devices is in the following format: Device (LPC0) { Name (_HID, "HISI0191") // HiSi LPC Name (_CRS, ResourceTemplate () { Memory32Fixed (ReadWrite, 0xa01b0000, 0x1000) }) } Device (LPC0.IPMI) { Name (_HID, "IPI0001") Name (LORS, ResourceTemplate() { QWordIO ( ResourceConsumer, MinNotFixed, // _MIF MaxNotFixed, // _MAF PosDecode, EntireRange, 0x0, // _GRA 0xe4, // _MIN 0x3fff, // _MAX 0x0, // _TRA 0x04, // _LEN , , BTIO ) }) Since the IO resources of the child devices need to be translated from LPC bus addresses to logical PIO addresses, and we shouldn't modify the resources of the devices generated in the FW scan, a per-child MFD is created as a substitute. The MFD IO resources will be the translated bus addresses of the ACPI child. Signed-off-by: John Garry Signed-off-by: Zhichang Yuan Signed-off-by: Gabriele Paoloni Reviewed-by: Andy Shevchenko Tested-by: dann frazier --- drivers/bus/hisi_lpc.c | 197 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 197 insertions(+) -- 1.9.1 diff --git a/drivers/bus/hisi_lpc.c b/drivers/bus/hisi_lpc.c index c2f3c14..0c7c1ec 100644 --- a/drivers/bus/hisi_lpc.c +++ b/drivers/bus/hisi_lpc.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -353,6 +354,199 @@ static void hisi_lpc_comm_out(void *hostdata, unsigned long pio, .outs = hisi_lpc_comm_outs, }; +#ifdef CONFIG_ACPI +#define MFD_CHILD_NAME_PREFIX DRV_NAME"-" +#define MFD_CHILD_NAME_LEN (ACPI_ID_LEN + sizeof(MFD_CHILD_NAME_PREFIX)) + +struct hisi_lpc_mfd_cell { + struct mfd_cell_acpi_match acpi_match; + char name[MFD_CHILD_NAME_LEN]; + char pnpid[ACPI_ID_LEN]; +}; + +static int hisi_lpc_acpi_xlat_io_res(struct acpi_device *adev, + struct acpi_device *host, + struct resource *res) +{ + unsigned long sys_port; + resource_size_t len = res->end - res->start; + + sys_port = logic_pio_trans_hwaddr(&host->fwnode, res->start, len); + if (sys_port == ~0UL) + return -EFAULT; + + res->start = sys_port; + res->end = sys_port + len; + + return 0; +} + +/* + * hisi_lpc_acpi_set_io_res - set the resources for a child's MFD + * @child: the device node to be updated the I/O resource + * @hostdev: the device node associated with host controller + * @res: double pointer to be set to the address of translated resources + * @num_res: pointer to variable to hold the number of translated resources + * + * Returns 0 when successful, and a negative value for failure. + * + * For a given host controller, each child device will have an associated + * host-relative address resource. This function will return the translated + * logical PIO addresses for each child devices resources. + */ +static int hisi_lpc_acpi_set_io_res(struct device *child, + struct device *hostdev, + const struct resource **res, + int *num_res) +{ + struct acpi_device *adev; + struct acpi_device *host; + struct resource_entry *rentry; + LIST_HEAD(resource_list); + struct resource *resources; + int count; + int i; + + if (!child || !hostdev) + return -EINVAL; + + host = to_acpi_device(hostdev); + adev = to_acpi_device(child); + + /* check the device state */ + if (!adev->status.present) { + dev_dbg(child, "device is not present\n"); + return -EIO; + } + /* whether the child had been enumerated? */ + if (acpi_device_enumerated(adev)) { + dev_dbg(child, "has been enumerated\n"); + return -EIO; + } + + /* + * The following code segment to retrieve the resources is common to + * acpi_create_platform_device(), so consider a common helper function + * in future. + */ + count = acpi_dev_get_resources(adev, &resource_list, NULL, NULL); + if (count <= 0) { + dev_dbg(child, "failed to get resources\n"); + return count ? count : -EIO; + } + + resources = devm_kcalloc(hostdev, count, sizeof(*resources), + GFP_KERNEL); + if (!resources) { + dev_warn(hostdev, "could not allocate memory for %d resources\n", + count); + acpi_dev_free_resource_list(&resource_list); + return -ENOMEM; + } + count = 0; + list_for_each_entry(rentry, &resource_list, node) + resources[count++] = *rentry->res; + + acpi_dev_free_resource_list(&resource_list); + + /* translate the I/O resources */ + for (i = 0; i < count; i++) { + int ret; + + if (!(resources[i].flags & IORESOURCE_IO)) + continue; + ret = hisi_lpc_acpi_xlat_io_res(adev, host, &resources[i]); + if (ret) { + dev_err(child, "translate IO range failed(%d)\n", ret); + return ret; + } + } + *res = resources; + *num_res = count; + + return 0; +} + +/* + * hisi_lpc_acpi_probe - probe children for ACPI FW + * @hostdev: LPC host device pointer + * + * Returns 0 when successful, and a negative value for failure. + * + * Scan all child devices and create a per-device MFD with + * logical PIO translated IO resources. + */ +static int hisi_lpc_acpi_probe(struct device *hostdev) +{ + struct acpi_device *adev = ACPI_COMPANION(hostdev); + struct hisi_lpc_mfd_cell *hisi_lpc_mfd_cells; + struct mfd_cell *mfd_cells; + struct acpi_device *child; + int size, ret, count = 0, cell_num = 0; + + list_for_each_entry(child, &adev->children, node) + cell_num++; + + /* allocate the mfd cell and companion acpi info, one per child */ + size = sizeof(*mfd_cells) + sizeof(*hisi_lpc_mfd_cells); + mfd_cells = devm_kcalloc(hostdev, cell_num, size, GFP_KERNEL); + if (!mfd_cells) + return -ENOMEM; + + hisi_lpc_mfd_cells = (struct hisi_lpc_mfd_cell *) + &mfd_cells[cell_num]; + /* Only consider the children of the host */ + list_for_each_entry(child, &adev->children, node) { + struct mfd_cell *mfd_cell = &mfd_cells[count]; + struct hisi_lpc_mfd_cell *hisi_lpc_mfd_cell = + &hisi_lpc_mfd_cells[count]; + struct mfd_cell_acpi_match *acpi_match = + &hisi_lpc_mfd_cell->acpi_match; + char *name = hisi_lpc_mfd_cell[count].name; + char *pnpid = hisi_lpc_mfd_cell[count].pnpid; + struct mfd_cell_acpi_match match = { + .pnpid = pnpid, + }; + + snprintf(name, MFD_CHILD_NAME_LEN, MFD_CHILD_NAME_PREFIX"%s", + acpi_device_hid(child)); + snprintf(pnpid, ACPI_ID_LEN, "%s", acpi_device_hid(child)); + + memcpy(acpi_match, &match, sizeof(*acpi_match)); + mfd_cell->name = name; + mfd_cell->acpi_match = acpi_match; + + ret = hisi_lpc_acpi_set_io_res(&child->dev, &adev->dev, + &mfd_cell->resources, + &mfd_cell->num_resources); + if (ret) { + dev_warn(&child->dev, "set resource fail(%d)\n", ret); + return ret; + } + count++; + } + + ret = mfd_add_devices(hostdev, PLATFORM_DEVID_NONE, + mfd_cells, cell_num, NULL, 0, NULL); + if (ret) { + dev_err(hostdev, "failed to add mfd cells (%d)\n", ret); + return ret; + } + + return 0; +} + +static const struct acpi_device_id hisi_lpc_acpi_match[] = { + {"HISI0191"}, + {} +}; +#else +static int hisi_lpc_acpi_probe(struct device *dev) +{ + return -ENODEV; +} +#endif // CONFIG_ACPI + /* * hisi_lpc_probe - the probe callback function for hisi lpc host, * will finish all the initialization. @@ -397,6 +591,8 @@ static int hisi_lpc_probe(struct platform_device *pdev) /* register the LPC host PIO resources */ if (!acpi_device) ret = of_platform_populate(dev->of_node, NULL, NULL, dev); + else + ret = hisi_lpc_acpi_probe(dev); if (ret) return ret; @@ -420,6 +616,7 @@ static int hisi_lpc_probe(struct platform_device *pdev) .driver = { .name = DRV_NAME, .of_match_table = hisi_lpc_of_match, + .acpi_match_table = ACPI_PTR(hisi_lpc_acpi_match), }, .probe = hisi_lpc_probe, };