From patchwork Tue Mar 6 10:47:40 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Garry X-Patchwork-Id: 130765 Delivered-To: patch@linaro.org Received: by 10.46.66.2 with SMTP id p2csp3782680lja; Tue, 6 Mar 2018 02:48:38 -0800 (PST) X-Google-Smtp-Source: AG47ELusID1ri+UNLtG3o3dkDhZ/2xO6l4Pd3/mDItREyJskDeGfVCY0SaRH/Kpk2RR8j+36VniS X-Received: by 10.167.128.80 with SMTP id y16mr18322843pfm.91.1520333318667; Tue, 06 Mar 2018 02:48:38 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1520333318; cv=none; d=google.com; s=arc-20160816; b=dYmKlACGt+vVBOuzwAuc3dSR7J/LW6QrRAWetDAHBxt+1R95AgDN3UlUYBhhkgSlql s72w9p7FSRh5ylmugaCKXefClqCxD8KPIcrDSGSOqWmhYN+BRnHBudIyTPWI6yDjDpt7 ZqFliKAgdnz/tXEFpaS6ljZRQJHbquNkZ0XxBXK6fS6+1c/rxoMdyzUfktfxUwKGCnVC gj+5tH+QkBNmYbWfH9+Lu9NCXMkvfmU5iwSWFQPn4aZt/1P9BfOoxeDx67cxVugbgtsH 5Mj3MP6PD4FHrbr4HH9zDiL3IwkZx0KFWo9kmHeBHxrvcJg+CWsMdiJKHqPNSaltmwJQ JOVA== 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=qHMndm1BG0GbN1B03+rt7E6cJaQZk8enVqRwdeY9RyA=; b=AlRFY00JYAzVbPMSvSlws1DnBcCB5XFOdbZ24w/DgJcL9oxLPG0EZctEf/6+W3d4eG RrCr0MU04DKWTLa8vIu1eP+GU/hP3+2UEn/99wyp94+bZJ4vkQVgMKzMA9GIPJombddz y71BHN5XMoMDaEL9UF+0RRhvn86Qdg/H8vMxx3pcn84obS4w/KHiHtRWT/wpNs2//Ugh HffFPjgTz1OC8ygrVBxzLEB2IjpNuLUTw7UKKCGbyhQz+BdAvbfiyl9df/U4pOgZgDvS NqGupECO/LdaW2Gm8iQb0P7vQlCrPpGvHQIsK2labF2CToZ1cBZUYMjGmxxwZ4BNf9mL 0Mxw== 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 b10si11887247pff.317.2018.03.06.02.48.38; Tue, 06 Mar 2018 02:48:38 -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 S1753488AbeCFKsc (ORCPT + 28 others); Tue, 6 Mar 2018 05:48:32 -0500 Received: from szxga04-in.huawei.com ([45.249.212.190]:6150 "EHLO huawei.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1750897AbeCFKs0 (ORCPT ); Tue, 6 Mar 2018 05:48:26 -0500 Received: from DGGEMS404-HUB.china.huawei.com (unknown [172.30.72.58]) by Forcepoint Email with ESMTP id D1D8614115D28; Tue, 6 Mar 2018 18:48:08 +0800 (CST) Received: from localhost.localdomain (10.67.212.75) by DGGEMS404-HUB.china.huawei.com (10.3.19.204) with Microsoft SMTP Server id 14.3.361.1; Tue, 6 Mar 2018 18:48:04 +0800 From: John Garry To: , , , , , , , , , , , , , CC: , , , , , , , , , , , , , Subject: [PATCH v16 1/9] LIB: Introduce a generic PIO mapping method Date: Tue, 6 Mar 2018 18:47:40 +0800 Message-ID: <1520333268-82754-2-git-send-email-john.garry@huawei.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1520333268-82754-1-git-send-email-john.garry@huawei.com> References: <1520333268-82754-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 In commit 41f8bba7f555 ("of/pci: Add pci_register_io_range() and pci_pio_to_address()"), a new I/O space management was supported. With that driver, the I/O ranges configured for PCI/PCIe hosts on some architectures can be mapped to logical PIO, converted easily between CPU address and the corresponding logicial PIO. Based on this, PCI I/O devices can be accessed in a memory read/write way through the unified in/out accessors. But on some archs/platforms, there are bus hosts which access I/O peripherals with host-local I/O port addresses rather than memory addresses after memory-mapped. To support those devices, a more generic I/O mapping method is introduced here. Through this patch, both the CPU addresses and the host-local port can be mapped into the logical PIO space with different logical/fake PIOs. After this, all the I/O accesses to either PCI MMIO devices or host-local I/O peripherals can be unified into the existing I/O accessors defined in asm-generic/io.h and be redirected to the right device-specific hooks based on the input logical PIO. Signed-off-by: Zhichang Yuan Signed-off-by: Gabriele Paoloni Signed-off-by: John Garry Reviewed-by: Andy Shevchenko Tested-by: dann frazier --- include/asm-generic/io.h | 2 + include/linux/logic_pio.h | 124 ++++++++++++++++++++ lib/Kconfig | 15 +++ lib/Makefile | 2 + lib/logic_pio.c | 282 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 425 insertions(+) create mode 100644 include/linux/logic_pio.h create mode 100644 lib/logic_pio.c -- 1.9.1 diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h index 7c6a39e..f76fbd6 100644 --- a/include/asm-generic/io.h +++ b/include/asm-generic/io.h @@ -351,6 +351,8 @@ static inline void writesq(volatile void __iomem *addr, const void *buffer, #define IO_SPACE_LIMIT 0xffff #endif +#include + /* * {in,out}{b,w,l}() access little endian I/O. {in,out}{b,w,l}_p() can be * implemented on hardware that needs an additional delay for I/O accesses to diff --git a/include/linux/logic_pio.h b/include/linux/logic_pio.h new file mode 100644 index 0000000..8c78ff4 --- /dev/null +++ b/include/linux/logic_pio.h @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved. + * Author: Gabriele Paoloni + * Author: Zhichang Yuan + * + */ + +#ifndef __LINUX_LOGIC_PIO_H +#define __LINUX_LOGIC_PIO_H + +#include + +enum { + LOGIC_PIO_INDIRECT, /* Indirect IO flag */ + LOGIC_PIO_CPU_MMIO, /* Memory mapped IO flag */ +}; + +struct logic_pio_hwaddr { + struct list_head list; + struct fwnode_handle *fwnode; + resource_size_t hw_start; + resource_size_t io_start; + resource_size_t size; /* range size populated */ + unsigned long flags; + + void *hostdata; + const struct logic_pio_host_ops *ops; +}; + +struct logic_pio_host_ops { + u32 (*in)(void *hostdata, unsigned long addr, size_t dwidth); + void (*out)(void *hostdata, unsigned long addr, u32 val, + size_t dwidth); + u32 (*ins)(void *hostdata, unsigned long addr, void *buffer, + size_t dwidth, unsigned int count); + void (*outs)(void *hostdata, unsigned long addr, const void *buffer, + size_t dwidth, unsigned int count); +}; + +#ifdef CONFIG_INDIRECT_PIO +u8 logic_inb(unsigned long addr); +void logic_outb(u8 value, unsigned long addr); +void logic_outw(u16 value, unsigned long addr); +void logic_outl(u32 value, unsigned long addr); +u16 logic_inw(unsigned long addr); +u32 logic_inl(unsigned long addr); +void logic_outb(u8 value, unsigned long addr); +void logic_outw(u16 value, unsigned long addr); +void logic_outl(u32 value, unsigned long addr); +void logic_insb(unsigned long addr, void *buffer, unsigned int count); +void logic_insl(unsigned long addr, void *buffer, unsigned int count); +void logic_insw(unsigned long addr, void *buffer, unsigned int count); +void logic_outsb(unsigned long addr, const void *buffer, unsigned int count); +void logic_outsw(unsigned long addr, const void *buffer, unsigned int count); +void logic_outsl(unsigned long addr, const void *buffer, unsigned int count); + +#ifndef inb +#define inb logic_inb +#endif + +#ifndef inw +#define inw logic_inw +#endif + +#ifndef inl +#define inl logic_inl +#endif + +#ifndef outb +#define outb logic_outb +#endif + +#ifndef outw +#define outw logic_outw +#endif + +#ifndef outl +#define outl logic_outl +#endif + +#ifndef insb +#define insb logic_insb +#endif + +#ifndef insw +#define insw logic_insw +#endif + +#ifndef insl +#define insl logic_insl +#endif + +#ifndef outsb +#define outsb logic_outsb +#endif + +#ifndef outsw +#define outsw logic_outsw +#endif + +#ifndef outsl +#define outsl logic_outsl +#endif + +/* + * Below we reserve 0x4000 bytes for Indirect IO as so far this library is only + * used by Hisilicon LPC Host. If needed in future we may reserve a wider IO + * area by redefining the macro below. + */ +#define PIO_INDIRECT_SIZE 0x4000 +#define MMIO_UPPER_LIMIT (IO_SPACE_LIMIT - PIO_INDIRECT_SIZE) +#else +#define MMIO_UPPER_LIMIT IO_SPACE_LIMIT +#endif /* CONFIG_INDIRECT_PIO */ + +struct logic_pio_hwaddr *find_io_range_by_fwnode(struct fwnode_handle *fwnode); +unsigned long logic_pio_trans_hwaddr(struct fwnode_handle *fwnode, + resource_size_t hw_addr, resource_size_t size); +int logic_pio_register_range(struct logic_pio_hwaddr *newrange); +extern resource_size_t logic_pio_to_hwaddr(unsigned long pio); +extern unsigned long logic_pio_trans_cpuaddr(resource_size_t hw_addr); + +#endif /* __LINUX_LOGIC_PIO_H */ diff --git a/lib/Kconfig b/lib/Kconfig index e960894..d9dd02c 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -55,6 +55,21 @@ config ARCH_USE_CMPXCHG_LOCKREF config ARCH_HAS_FAST_MULTIPLIER bool +config INDIRECT_PIO + bool "Access I/O in non-MMIO mode" + depends on ARM64 + help + On some platforms where no separate I/O space exists, there are I/O + hosts which can not be accessed in MMIO mode. Using the logical PIO + mechanism, the host-local I/O resource can be mapped into system + logic PIO space shared with MMIO hosts, such as PCI/PCIE, then the + system can access the I/O devices with the mapped logic PIO through + I/O accessors. + This way has relatively little I/O performance cost. Please make + sure your devices really need this configure item enabled. + + When in doubt, say N. + config CRC_CCITT tristate "CRC-CCITT functions" help diff --git a/lib/Makefile b/lib/Makefile index 0bd50d71f..8fc0d3a 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -82,6 +82,8 @@ obj-$(CONFIG_HAS_IOMEM) += iomap_copy.o devres.o obj-$(CONFIG_CHECK_SIGNATURE) += check_signature.o obj-$(CONFIG_DEBUG_LOCKING_API_SELFTESTS) += locking-selftest.o +obj-y += logic_pio.o + obj-$(CONFIG_GENERIC_HWEIGHT) += hweight.o obj-$(CONFIG_BTREE) += btree.o diff --git a/lib/logic_pio.c b/lib/logic_pio.c new file mode 100644 index 0000000..8394c2d --- /dev/null +++ b/lib/logic_pio.c @@ -0,0 +1,282 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved. + * Author: Gabriele Paoloni + * Author: Zhichang Yuan + * + */ + +#define pr_fmt(fmt) "LOGIC PIO: " fmt + +#include +#include +#include +#include +#include +#include +#include + +/* The unique hardware address list. */ +static LIST_HEAD(io_range_list); +static DEFINE_MUTEX(io_range_mutex); + +/* Consider a kernel general helper for this */ +#define in_range(b, first, len) ((b) >= (first) && (b) < (first) + (len)) + +/** + * logic_pio_register_range - register logical PIO range for a host + * @new_range: pointer to the io range to be registered. + * + * returns 0 on success, the error code in case of failure + * + * Register a new io range node in the io range list. + */ +int logic_pio_register_range(struct logic_pio_hwaddr *new_range) +{ + struct logic_pio_hwaddr *range; + resource_size_t start = new_range->hw_start; + resource_size_t end = new_range->hw_start + new_range->size; + resource_size_t mmio_sz = 0; + resource_size_t iio_sz = MMIO_UPPER_LIMIT; + int ret = 0; + + if (!new_range || !new_range->fwnode || !new_range->size) + return -EINVAL; + + mutex_lock(&io_range_mutex); + list_for_each_entry_rcu(range, &io_range_list, list) { + if (range->fwnode == new_range->fwnode) { + /* range already there */ + ret = -EFAULT; + goto end_register; + } + if (range->flags == LOGIC_PIO_CPU_MMIO && + new_range->flags == LOGIC_PIO_CPU_MMIO) { + /* for MMIO ranges we need to check for overlap */ + if (start >= range->hw_start + range->size || + end < range->hw_start) { + mmio_sz += range->size; + } else { + ret = -EFAULT; + goto end_register; + } + } else if (range->flags == LOGIC_PIO_INDIRECT && + new_range->flags == LOGIC_PIO_INDIRECT) { + iio_sz += range->size; + } + } + + /* range not registered yet, check for available space */ + if (new_range->flags == LOGIC_PIO_CPU_MMIO) { + if (mmio_sz + new_range->size - 1 > MMIO_UPPER_LIMIT) { + /* if it's too big check if 64K space can be reserved */ + if (mmio_sz + SZ_64K - 1 > MMIO_UPPER_LIMIT) { + ret = -E2BIG; + goto end_register; + } + new_range->size = SZ_64K; + pr_warn("Requested IO range too big, new size set to 64K\n"); + } + new_range->io_start = mmio_sz; + } else if (new_range->flags == LOGIC_PIO_INDIRECT) { + if (iio_sz + new_range->size - 1 > IO_SPACE_LIMIT) { + ret = -E2BIG; + goto end_register; + } + new_range->io_start = iio_sz; + } else { + /* invalid flag */ + ret = -EINVAL; + goto end_register; + } + + list_add_tail_rcu(&new_range->list, &io_range_list); + +end_register: + mutex_unlock(&io_range_mutex); + return ret; +} + +/** + * find_io_range_by_fwnode - find logical PIO range for given FW node + * @fwnode: FW node handle associated with logical PIO range + * + * Returns pointer to node on success, NULL otherwise + * + * Traverse the io_range_list to find the registered node whose device node + * and/or physical IO address match to. + */ +struct logic_pio_hwaddr *find_io_range_by_fwnode(struct fwnode_handle *fwnode) +{ + struct logic_pio_hwaddr *range; + + list_for_each_entry_rcu(range, &io_range_list, list) { + if (range->fwnode == fwnode) + return range; + } + return NULL; +} + +/* Return a registered range given an input PIO token */ +static struct logic_pio_hwaddr *find_io_range(unsigned long pio) +{ + struct logic_pio_hwaddr *range; + + list_for_each_entry_rcu(range, &io_range_list, list) { + if (in_range(pio, range->io_start, range->size)) + return range; + } + pr_err("PIO entry token invalid\n"); + return NULL; +} + +/** + * logic_pio_to_hwaddr - translate logical PIO to HW address + * @pio: logical PIO value + * + * Returns HW address if valid, ~0 otherwise + * + * Translate the input logical pio to the corresponding hardware address. + * The input pio should be unique in the whole logical PIO space. + */ +resource_size_t logic_pio_to_hwaddr(unsigned long pio) +{ + struct logic_pio_hwaddr *range; + resource_size_t hwaddr = (resource_size_t)~0; + + range = find_io_range(pio); + if (range) + hwaddr = range->hw_start + pio - range->io_start; + + return hwaddr; +} + +/** + * logic_pio_trans_hwaddr - translate HW address to logical PIO + * @fwnode: FW node reference for the host + * @addr: Host-relative HW address + * @size: size to translate + * + * Returns Logical PIO value if successful, ~0UL otherwise + */ +unsigned long +logic_pio_trans_hwaddr(struct fwnode_handle *fwnode, resource_size_t addr, + resource_size_t size) +{ + struct logic_pio_hwaddr *range; + + range = find_io_range_by_fwnode(fwnode); + if (!range || range->flags == LOGIC_PIO_CPU_MMIO) { + pr_err("range not found or invalid\n"); + return ~0UL; + } + if (range->size < size) { + pr_err("resource size %pa cannot fit in IO range size %pa\n", + &size, &range->size); + return ~0UL; + } + return addr - range->hw_start + range->io_start; +} + +unsigned long +logic_pio_trans_cpuaddr(resource_size_t addr) +{ + struct logic_pio_hwaddr *range; + + list_for_each_entry_rcu(range, &io_range_list, list) { + if (range->flags != LOGIC_PIO_CPU_MMIO) + continue; + if (in_range(addr, range->hw_start, range->size)) + return addr - range->hw_start + range->io_start; + } + pr_err("addr not registered in io_range_list\n"); + return ~0UL; +} + +#if defined(CONFIG_INDIRECT_PIO) && defined(PCI_IOBASE) +#define BUILD_LOGIC_IO(bw, type) \ +type logic_in##bw(unsigned long addr) \ +{ \ + type ret = (type)~0; \ + \ + if (addr < MMIO_UPPER_LIMIT) { \ + ret = read##bw(PCI_IOBASE + addr); \ + } else if (addr >= MMIO_UPPER_LIMIT && addr < IO_SPACE_LIMIT) { \ + struct logic_pio_hwaddr *entry = find_io_range(addr); \ + \ + if (entry && entry->ops) \ + ret = entry->ops->in(entry->hostdata, \ + addr, sizeof(type)); \ + else \ + WARN_ON_ONCE(1); \ + } \ + return ret; \ +} \ + \ +void logic_out##bw(type value, unsigned long addr) \ +{ \ + if (addr < MMIO_UPPER_LIMIT) { \ + write##bw(value, PCI_IOBASE + addr); \ + } else if (addr >= MMIO_UPPER_LIMIT && addr < IO_SPACE_LIMIT) { \ + struct logic_pio_hwaddr *entry = find_io_range(addr); \ + \ + if (entry && entry->ops) \ + entry->ops->out(entry->hostdata, \ + addr, value, sizeof(type)); \ + else \ + WARN_ON_ONCE(1); \ + } \ +} \ + \ +void logic_ins##bw(unsigned long addr, void *buffer, \ + unsigned int count) \ +{ \ + if (addr < MMIO_UPPER_LIMIT) { \ + reads##bw(PCI_IOBASE + addr, buffer, count); \ + } else if (addr >= MMIO_UPPER_LIMIT && addr < IO_SPACE_LIMIT) { \ + struct logic_pio_hwaddr *entry = find_io_range(addr); \ + \ + if (entry && entry->ops) \ + entry->ops->ins(entry->hostdata, \ + addr, buffer, sizeof(type), count); \ + else \ + WARN_ON_ONCE(1); \ + } \ + \ +} \ + \ +void logic_outs##bw(unsigned long addr, const void *buffer, \ + unsigned int count) \ +{ \ + if (addr < MMIO_UPPER_LIMIT) { \ + writes##bw(PCI_IOBASE + addr, buffer, count); \ + } else if (addr >= MMIO_UPPER_LIMIT && addr < IO_SPACE_LIMIT) { \ + struct logic_pio_hwaddr *entry = find_io_range(addr); \ + \ + if (entry && entry->ops) \ + entry->ops->outs(entry->hostdata, \ + addr, buffer, sizeof(type), count); \ + else \ + WARN_ON_ONCE(1); \ + } \ +} + +BUILD_LOGIC_IO(b, u8) +EXPORT_SYMBOL(logic_inb); +EXPORT_SYMBOL(logic_insb); +EXPORT_SYMBOL(logic_outb); +EXPORT_SYMBOL(logic_outsb); + +BUILD_LOGIC_IO(w, u16) +EXPORT_SYMBOL(logic_inw); +EXPORT_SYMBOL(logic_insw); +EXPORT_SYMBOL(logic_outw); +EXPORT_SYMBOL(logic_outsw); + +BUILD_LOGIC_IO(l, u32) +EXPORT_SYMBOL(logic_inl); +EXPORT_SYMBOL(logic_insl); +EXPORT_SYMBOL(logic_outl); +EXPORT_SYMBOL(logic_outsl); + +#endif /* CONFIG_INDIRECT_PIO && PCI_IOBASE */ From patchwork Tue Mar 6 10:47:41 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Garry X-Patchwork-Id: 130771 Delivered-To: patch@linaro.org Received: by 10.46.66.2 with SMTP id p2csp3784239lja; Tue, 6 Mar 2018 02:50:28 -0800 (PST) X-Google-Smtp-Source: AG47ELvu4Xj45C0R2CdCTtSzX5boKljd8C6o3m6ccW/fiSxFIwHa+vUTfQLSsDVq025Gyysmx47r X-Received: by 10.99.179.77 with SMTP id x13mr13877153pgt.148.1520333428364; Tue, 06 Mar 2018 02:50:28 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1520333428; cv=none; d=google.com; s=arc-20160816; b=HStjefy0sBlD/geiQlSQP/bBQtMSkoxG5ZX+xT62Sat2FTWB7AZwwnraHgCR8MXb/i BYP71PkiMAIVTlcYoFUnMKnHryxhOlkNkuN2LySJpGVt3wZAOPL/EXnpZ5eBdlfsGunX yMzomjL3apmTnMVdS/DP/2dWcli3P+8/6eFnZhAZquK3I+H1xmaA48VAB2yddsMXRB+c 4bTbvXXgIr/Pe0YuipkIAwWU2YazOtCQigC37indOW8yHXhs7F0gUMgkyKHUyyGMspiA 66NVMKLsMzmNjJ2/0q5bIaI97Fmdl9BgxYBtPtYr003AgXomr/JSIC04K7zhj701WCds Q+CQ== 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=N2pWP9N2ook620oBtwdAxvf3HmhAmACKGOLfNUkJs7U=; b=PW7yqJQnWFkqG3SbwlyOJ6K3Ec8VqLhKnLrf/lQTHI5VzzFMXz13jpf0OHxmk49BMf gDMsblJBGyrtn/aKd0VIIaJJniGvyui4dnxJQ++rYkUWXzadgi2YRJBOLqWO/VhEXAI6 cuYShVnvhGWmUfLe+RpIqxAWa3iXxzEn0AhlGXMtzpVn88lCufxJzvmrs9mua3yeM3WD cme4Q2YIzZFHfkjZQ2oUFirqt+gLIe2nWrrAhKn0dSKcyAW3VsYQjV2lnPR/mAbYL4qc 4swkW5K9+P0QfAUvBp73Ur8mPnBRvRKxMvIFJzorRMAs+U11fxQa15OhHcteDxRIubVe Uf5g== 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 ay8-v6si10872955plb.614.2018.03.06.02.50.28; Tue, 06 Mar 2018 02:50: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 S1753677AbeCFKuD (ORCPT + 28 others); Tue, 6 Mar 2018 05:50:03 -0500 Received: from szxga04-in.huawei.com ([45.249.212.190]:6156 "EHLO huawei.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1753431AbeCFKsb (ORCPT ); Tue, 6 Mar 2018 05:48:31 -0500 Received: from DGGEMS404-HUB.china.huawei.com (unknown [172.30.72.59]) by Forcepoint Email with ESMTP id 4BD3F8250994C; Tue, 6 Mar 2018 18:48:14 +0800 (CST) Received: from localhost.localdomain (10.67.212.75) by DGGEMS404-HUB.china.huawei.com (10.3.19.204) with Microsoft SMTP Server id 14.3.361.1; Tue, 6 Mar 2018 18:48:05 +0800 From: John Garry To: , , , , , , , , , , , , , CC: , , , , , , , , , , , , , Subject: [PATCH v16 2/9] PCI: Remove unused __weak attribute in pci_register_io_range() Date: Tue, 6 Mar 2018 18:47:41 +0800 Message-ID: <1520333268-82754-3-git-send-email-john.garry@huawei.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1520333268-82754-1-git-send-email-john.garry@huawei.com> References: <1520333268-82754-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 ae654e2..ff41a64 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -3451,7 +3451,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 Tue Mar 6 10:47: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: 130773 Delivered-To: patch@linaro.org Received: by 10.46.66.2 with SMTP id p2csp3784698lja; Tue, 6 Mar 2018 02:51:02 -0800 (PST) X-Google-Smtp-Source: AG47ELtXaQXxxtAAeoAQQC9RwFaEcMh/PUvwSG6j7qHqmiqjUgo5zYWraI1Vw+bnkHFkHv5v2bLZ X-Received: by 2002:a17:902:8c83:: with SMTP id t3-v6mr16704670plo.310.1520333461919; Tue, 06 Mar 2018 02:51:01 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1520333461; cv=none; d=google.com; s=arc-20160816; b=dqGwGmHKuEdqLzQPdiNUzwXdvq7oKMFQdfuehNqzs5B/Df+n+FTmSFLgBIh097JPLM KgJNTMgA7An4CNkFkVYRKx4QxEgvivrEfIwvE5l5UNfMwopFFvGnMjW3pfGK+AmKjwLP DCoOt/dvPZcGTI+xKfRVsq1fkFXFYa02NlmQWA7xU4YtrDOqupyFrDNBpdyyg81NvACH zBNtjOS/1IbJ2lnTZDhjdTrOk6xC6Bb6C0LkOCihW6n03HZvUjjOz36gV4XT6+zDulVL kPBtnYenzohMTFyI+f0Ca0oomW8Z2KGZnizhr0alce3DbGrI8Ic4r0V9X68SiXB64HN7 FK7g== 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=OA7cjhpliCNDOhxGQb5JT1Tyzni2iDNL/x3EBcw9IO4=; b=hPPvFMHlwr6YNzngYlBeAlxmdDo+pP5InRmL0xd2lpYr4VCkjsWJOEHIyQ4XGu+rcy X6R6IVRn0i0JrfooSurJuNCymZdBTj2o11MawVI6S9W2XK0p9IjvRXrkCUPSyoopVSXI vGgOcu6o/2DMW1z+uMdhpHrbzHz81la5Mr3CAkmSS4PeKyL/mgwi6CGNtXPu1Spyva8X 5+3reHyqgvg0ZkCknle5H9A9psowJh3cqeLQrooGDVIb6dihB/sAqX31WRPem5bAmIbg zzJXmsOlpsqCEEQ4Qqw5ZYBfeopdPXOQ03ChkoiC4WOhTzYFmw01hKu2XsQhdusPKBid Inlg== 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 1-v6si10999909plw.164.2018.03.06.02.51.01; Tue, 06 Mar 2018 02:51:01 -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 S932581AbeCFKum (ORCPT + 28 others); Tue, 6 Mar 2018 05:50:42 -0500 Received: from szxga04-in.huawei.com ([45.249.212.190]:6154 "EHLO huawei.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1753369AbeCFKsa (ORCPT ); Tue, 6 Mar 2018 05:48:30 -0500 Received: from DGGEMS404-HUB.china.huawei.com (unknown [172.30.72.59]) by Forcepoint Email with ESMTP id 21A66844839A2; Tue, 6 Mar 2018 18:48:14 +0800 (CST) Received: from localhost.localdomain (10.67.212.75) by DGGEMS404-HUB.china.huawei.com (10.3.19.204) with Microsoft SMTP Server id 14.3.361.1; Tue, 6 Mar 2018 18:48:06 +0800 From: John Garry To: , , , , , , , , , , , , , CC: , , , , , , , , , , , , , Subject: [PATCH v16 3/9] PCI: Add fwnode handler as input param of pci_register_io_range() Date: Tue, 6 Mar 2018 18:47:42 +0800 Message-ID: <1520333268-82754-4-git-send-email-john.garry@huawei.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1520333268-82754-1-git-send-email-john.garry@huawei.com> References: <1520333268-82754-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 ff41a64..3f30b7d 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -3451,7 +3451,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 Tue Mar 6 10:47: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: 130769 Delivered-To: patch@linaro.org Received: by 10.46.66.2 with SMTP id p2csp3783437lja; Tue, 6 Mar 2018 02:49:33 -0800 (PST) X-Google-Smtp-Source: AG47ELtbktD+P0j2q95xEpxbiQ0KIi1v0ic7XUaSysnq7rmPKIkCmus/F+K0S3I1oKdfXeRbrP4d X-Received: by 10.99.140.85 with SMTP id q21mr14458312pgn.51.1520333373612; Tue, 06 Mar 2018 02:49:33 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1520333373; cv=none; d=google.com; s=arc-20160816; b=fbxOCi7Ao37v5Cy6and61yhsSN0J5o+FRR3sTI/ZHks53avuikVhFDPPzdgKVD0bb+ cmoi/Pmxd6uviKRQG/2VA4VsNfdoF8aOhmr0ABU6TJeB3ySbDWs20xVgmhskQuNpvtJ/ EuTuWpZ0isOVbcKyHELoCXp0NZA0U65duJxs6xf6vRVApN4Gcyrw9y84O7NY0yGS1CU3 JDoZVyODcfBIhbJY8RZmnPbrXTTefLED+ISRlaV9Sb2XXDRT9CYsZBwbvTVmlG60Gwoc 3eaHo5FJMX/ErifKSOBbLU7KDwl9BI3tc0Qr/qFd2PSSLCYew31JNpYkyncZk02EYUQ0 +YMQ== 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=YY5/xfa6Q6jO3B9AmF91X3fG8bvtn1Lz1KUNcgUPL3E=; b=geyokbblRrCnenmrtlSt9NOdN0OV2/bcTMnfEpsmdtoMcW0LCfVJCtDwO1s7U89Smv DGcXB8vsJTFFNGqmsx7M4DVAykY9EH79nhOocxovjLMAvl3S0YbAyo3chlmb7gxtKpmk xNRK5lf5tdYZB18srTu6N2ASSchtcXf8+g5ShQ2YBKXKJMAO1Os4se380vnn9uKoN7lV ApQUiylzRNAp03vNrYiqZGn/cHZSgz8OO5TuwgIigf2Heho9gjb3zym9sdvh55KUph9Q oAMHcFu9nRgD+X6iJp5F8h+QSKp5rIB7ha2EaiqmvCq6oAxkXRtTIRXMCOPytHtejAeN GFoA== 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 r3-v6si11046385plb.197.2018.03.06.02.49.33; Tue, 06 Mar 2018 02:49:33 -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 S1753628AbeCFKtb (ORCPT + 28 others); Tue, 6 Mar 2018 05:49:31 -0500 Received: from szxga04-in.huawei.com ([45.249.212.190]:6153 "EHLO huawei.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1753361AbeCFKsb (ORCPT ); Tue, 6 Mar 2018 05:48:31 -0500 Received: from DGGEMS404-HUB.china.huawei.com (unknown [172.30.72.59]) by Forcepoint Email with ESMTP id 0BCED59ED919A; Tue, 6 Mar 2018 18:48:14 +0800 (CST) Received: from localhost.localdomain (10.67.212.75) by DGGEMS404-HUB.china.huawei.com (10.3.19.204) with Microsoft SMTP Server id 14.3.361.1; Tue, 6 Mar 2018 18:48:06 +0800 From: John Garry To: , , , , , , , , , , , , , CC: , , , , , , , , , , , , , Subject: [PATCH v16 4/9] PCI: Apply the new generic I/O management on PCI IO hosts Date: Tue, 6 Mar 2018 18:47:43 +0800 Message-ID: <1520333268-82754-5-git-send-email-john.garry@huawei.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1520333268-82754-1-git-send-email-john.garry@huawei.com> References: <1520333268-82754-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 3f30b7d..09c2490 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -3436,17 +3437,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 @@ -3454,51 +3444,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) @@ -3506,21 +3473,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; @@ -3529,21 +3485,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 Tue Mar 6 10:47: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: 130766 Delivered-To: patch@linaro.org Received: by 10.46.66.2 with SMTP id p2csp3782745lja; Tue, 6 Mar 2018 02:48:43 -0800 (PST) X-Google-Smtp-Source: AG47ELs5qNw/lV8Th8JzJswJolBOwebzI/cFBCF7qGAbTTzpx4a2IDAstAj6Q+8KY6qSjOVVnkIg X-Received: by 2002:a17:902:f44:: with SMTP id 62-v6mr16000468ply.27.1520333323413; Tue, 06 Mar 2018 02:48:43 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1520333323; cv=none; d=google.com; s=arc-20160816; b=KzDv4+ReDO190zL4wHtZGc6JYx5IQZw9ET6C1bFT6StMU18LKRWIckBBSZRuRM1+vQ AYvtMrC57LJujK3467rBwA8fKwkg6dU9ygrC/SHfQr9IAu098D75jDzXq9VaQbPHzsS7 2apa3M1mgMa+Rl+sSZE0TBpcuCrX4gZkmQ8HPifzVoXgqnkFWBzBXD2ZmJ5crOXcT5Hk uosdpyW0lTZMll/6rUhxUedEtXscm7CdhxQs93lNJS8fhX7cF3yhTUgjSj2zbSPT+kej C+qtXODtuCWYccMjNi7NJl/8M0ApZbr13bGdTjGbBdhLLwvWy7KwNy/IydA5NyT906eb Jebw== 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=Z0uXAtNDkj72As2awn2LlidDV/LGt+pVLAUtK030rNc=; b=dPwjSwmWxpR6ZRvgSOtiFAUv79HJg6Y2g61aRT12ObbP1UU7R96whZ/fuxkDnChs++ vViyM3c3VlGbd5rJFLglo+g1JxyoRcaykdZtiGoGBxLfLSCFEjrD8limKN/jr108zgVz 9hmx+9JytMq5gFxgNc8DQfirxVQIBpb5TGIEb6EWVLCRukgn4CoSIQ7WyXjDWOp1R7kv vtGmUbIYzwijXmv8NKw3W6BducyQwWjVJygQoLxLMX7+LMRBiY9i4lZzS6qiWlVNzbza rPForwxHmYu2vYeUUEuXI32glGfI6Yuk1LIC6O1lcYhLXZgwsDFC9AN+VKalwLYLGO1S a7BQ== 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 s62si9714450pgc.184.2018.03.06.02.48.43; Tue, 06 Mar 2018 02:48:43 -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 S1753541AbeCFKsj (ORCPT + 28 others); Tue, 6 Mar 2018 05:48:39 -0500 Received: from szxga04-in.huawei.com ([45.249.212.190]:6157 "EHLO huawei.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1753433AbeCFKsd (ORCPT ); Tue, 6 Mar 2018 05:48:33 -0500 Received: from DGGEMS404-HUB.china.huawei.com (unknown [172.30.72.59]) by Forcepoint Email with ESMTP id 60194703C77F8; Tue, 6 Mar 2018 18:48:14 +0800 (CST) Received: from localhost.localdomain (10.67.212.75) by DGGEMS404-HUB.china.huawei.com (10.3.19.204) with Microsoft SMTP Server id 14.3.361.1; Tue, 6 Mar 2018 18:48:07 +0800 From: John Garry To: , , , , , , , , , , , , , CC: , , , , , , , , , , , , , Subject: [PATCH v16 5/9] OF: Add missing I/O range exception for indirect-IO devices Date: Tue, 6 Mar 2018 18:47:44 +0800 Message-ID: <1520333268-82754-6-git-send-email-john.garry@huawei.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1520333268-82754-1-git-send-email-john.garry@huawei.com> References: <1520333268-82754-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 There are some special ISA/LPC devices that work on a specific I/O range where it is not correct to specify a 'ranges' property in DTS parent node as CPU addresses translated from DTS node are only for memory space on some architectures, such as Arm64. Without the parent 'ranges' property, current of_translate_address() return an error. Here we add special handling for this case. During the OF address translation, some checking will be performed to identify whether the device node is registered as indirect-IO. If yes, the I/O translation will be done in a different way from that one of PCI MMIO. In this way, the I/O 'reg' property of the special ISA/LPC devices will be parsed correctly. Signed-off-by: Zhichang Yuan Signed-off-by: Gabriele Paoloni Signed-off-by: Arnd Bergmann #earlier draft Acked-by: Rob Herring Reviewed-by: Andy Shevchenko Tested-by: dann frazier --- drivers/of/address.c | 92 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 76 insertions(+), 16 deletions(-) -- 1.9.1 diff --git a/drivers/of/address.c b/drivers/of/address.c index cdf047b..c434f659 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -562,9 +563,14 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus, * that translation is impossible (that is we are not dealing with a value * that can be mapped to a cpu physical address). This is not really specified * that way, but this is traditionally the way IBM at least do things + * + * Whenever the translation fails, the *host pointer will be set to the + * device that had registered logical PIO mapping, and the return code is + * relative to that node. */ static u64 __of_translate_address(struct device_node *dev, - const __be32 *in_addr, const char *rprop) + const __be32 *in_addr, const char *rprop, + struct device_node **host) { struct device_node *parent = NULL; struct of_bus *bus, *pbus; @@ -577,6 +583,7 @@ static u64 __of_translate_address(struct device_node *dev, /* Increase refcount at current level */ of_node_get(dev); + *host = NULL; /* Get parent & match bus type */ parent = of_get_parent(dev); if (parent == NULL) @@ -597,6 +604,8 @@ static u64 __of_translate_address(struct device_node *dev, /* Translate */ for (;;) { + struct logic_pio_hwaddr *iorange; + /* Switch to parent bus */ of_node_put(dev); dev = parent; @@ -609,6 +618,19 @@ static u64 __of_translate_address(struct device_node *dev, break; } + /* + * For indirectIO device which has no ranges property, get + * the address from reg directly. + */ + iorange = find_io_range_by_fwnode(&dev->fwnode); + if (iorange && (iorange->flags != LOGIC_PIO_CPU_MMIO)) { + result = of_read_number(addr + 1, na - 1); + pr_debug("indirectIO matched(%pOF) 0x%llx\n", + dev, result); + *host = of_node_get(dev); + break; + } + /* Get new parent bus and counts */ pbus = of_match_bus(parent); pbus->count_cells(dev, &pna, &pns); @@ -640,13 +662,32 @@ static u64 __of_translate_address(struct device_node *dev, u64 of_translate_address(struct device_node *dev, const __be32 *in_addr) { - return __of_translate_address(dev, in_addr, "ranges"); + struct device_node *host; + u64 ret; + + ret = __of_translate_address(dev, in_addr, "ranges", &host); + if (host) { + of_node_put(host); + return OF_BAD_ADDR; + } + + return ret; } EXPORT_SYMBOL(of_translate_address); u64 of_translate_dma_address(struct device_node *dev, const __be32 *in_addr) { - return __of_translate_address(dev, in_addr, "dma-ranges"); + struct device_node *host; + u64 ret; + + ret = __of_translate_address(dev, in_addr, "dma-ranges", &host); + + if (host) { + of_node_put(host); + return OF_BAD_ADDR; + } + + return ret; } EXPORT_SYMBOL(of_translate_dma_address); @@ -688,29 +729,48 @@ const __be32 *of_get_address(struct device_node *dev, int index, u64 *size, } EXPORT_SYMBOL(of_get_address); +static u64 of_translate_ioport(struct device_node *dev, const __be32 *in_addr, + u64 size) +{ + u64 taddr; + unsigned long port; + struct device_node *host; + + taddr = __of_translate_address(dev, in_addr, "ranges", &host); + if (host) { + /* host specific port access */ + port = logic_pio_trans_hwaddr(&host->fwnode, taddr, size); + of_node_put(host); + } else { + /* memory mapped I/O range */ + port = pci_address_to_pio(taddr); + } + + if (port == (unsigned long)-1) + return OF_BAD_ADDR; + + return port; +} + static int __of_address_to_resource(struct device_node *dev, const __be32 *addrp, u64 size, unsigned int flags, const char *name, struct resource *r) { u64 taddr; - if ((flags & (IORESOURCE_IO | IORESOURCE_MEM)) == 0) + if (flags & IORESOURCE_MEM) + taddr = of_translate_address(dev, addrp); + else if (flags & IORESOURCE_IO) + taddr = of_translate_ioport(dev, addrp, size); + else return -EINVAL; - taddr = of_translate_address(dev, addrp); + if (taddr == OF_BAD_ADDR) return -EINVAL; memset(r, 0, sizeof(struct resource)); - if (flags & IORESOURCE_IO) { - unsigned long port; - port = pci_address_to_pio(taddr); - if (port == (unsigned long)-1) - return -EINVAL; - r->start = port; - r->end = port + size - 1; - } else { - r->start = taddr; - r->end = taddr + size - 1; - } + + r->start = taddr; + r->end = taddr + size - 1; r->flags = flags; r->name = name ? name : dev->full_name; From patchwork Tue Mar 6 10:47:45 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Garry X-Patchwork-Id: 130772 Delivered-To: patch@linaro.org Received: by 10.46.66.2 with SMTP id p2csp3784494lja; Tue, 6 Mar 2018 02:50:47 -0800 (PST) X-Google-Smtp-Source: AG47ELtETXPvcYX5cCiNlVpBNPjL4maFIBMltqEeH+H8rj/kaBJutOAMqS0162U20AX1LHDsbIht X-Received: by 10.101.91.78 with SMTP id y14mr14838459pgr.243.1520333447375; Tue, 06 Mar 2018 02:50:47 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1520333447; cv=none; d=google.com; s=arc-20160816; b=nivNs7QaO4hqIgE16YnCcJVzd6w2K4TG/mWjLPkCKbhNklt//TGuUgkOvC4OMAzYy6 wiyN8yxwYUD5ly9VivX4A8DmsAn9AYfHLv0uMI9MI7Sy4x+gFH1km1zvNMTGIORA3zdm JJE8XDtWrlqB/N9kVuh/vS6UTokx+h0Pqm89MdLgIM0Jbpk9ueB6BzrFWE6X0GymHViS 5puwBuxQJVT37OP77qmpXvtld3NiKrRcqedbq4ZFWtoIiubhJnx6yVakOVlKVrcEzN/a KOZckO4zlLvKYRTbLMvW1+rOI9abNlted3cg1/nvq2w6wykiv2v4G3NHkh6PtC75vHx8 G9aQ== 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=vypuDcRBPOgftbISRytLvNet0g6HomzWuYEp4rVrciI=; b=MSver0X/zQUunsldO7KJDrG5s/wchfYAcl56peNkPeAy+MjAofoHcaPbCxZ+bYdaF7 N+W/3zTVz5uM2Djfm6YTbLiJsOtFOKeqDXFwelFcZtDdp2yU5htPa+KEeuO3IZi3DcVR Y0Yog90nxrzS2pDOPi7ngGplBwS7pY0TdBenhTLbDHIi+NE/h0uM/FdRuGO5Fe4dienP xYBO00JWKtg/jMXO8IFaPlPMaiGoxBnI9htKLEieS4PW29wxoXEmeeFwF7sZYxk3ZhiO P22muENKVdQ2DZx7l0+7JCpGOmYYPzIcm8BYUo9XWt4LfY243EWAzqfdwf6kzELmoESk zprQ== 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 p3-v6si3515358plk.813.2018.03.06.02.50.46; Tue, 06 Mar 2018 02:50:47 -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 S932695AbeCFKun (ORCPT + 28 others); Tue, 6 Mar 2018 05:50:43 -0500 Received: from szxga04-in.huawei.com ([45.249.212.190]:6151 "EHLO huawei.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1753065AbeCFKsa (ORCPT ); Tue, 6 Mar 2018 05:48:30 -0500 Received: from DGGEMS404-HUB.china.huawei.com (unknown [172.30.72.59]) by Forcepoint Email with ESMTP id D29EE64E9225; Tue, 6 Mar 2018 18:48:13 +0800 (CST) Received: from localhost.localdomain (10.67.212.75) by DGGEMS404-HUB.china.huawei.com (10.3.19.204) with Microsoft SMTP Server id 14.3.361.1; Tue, 6 Mar 2018 18:48:07 +0800 From: John Garry To: , , , , , , , , , , , , , CC: , , , , , , , , , , , , , Subject: [PATCH v16 6/9] HISI LPC: Support the LPC host on Hip06/Hip07 with DT bindings Date: Tue, 6 Mar 2018 18:47:45 +0800 Message-ID: <1520333268-82754-7-git-send-email-john.garry@huawei.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1520333268-82754-1-git-send-email-john.garry@huawei.com> References: <1520333268-82754-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 | 421 +++++++++++++++++++++ 4 files changed, 464 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..c331609 --- /dev/null +++ b/drivers/bus/hisi_lpc.c @@ -0,0 +1,421 @@ +// 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; + } + + readsb(lpcdev->membase + LPC_REG_RDATA, buf, 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); + + writesb(lpcdev->membase + LPC_REG_WDATA, buf, 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; + resource_size_t io_end; + struct resource *res; + int ret; + + lpcdev = devm_kzalloc(dev, sizeof(*lpcdev), 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; + + io_end = lpcdev->io_host->io_start + lpcdev->io_host->size; + dev_info(dev, "registered range [%pa - %pa]\n", + &lpcdev->io_host->io_start, &io_end); + + 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 Tue Mar 6 10:47: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: 130770 Delivered-To: patch@linaro.org Received: by 10.46.66.2 with SMTP id p2csp3783672lja; Tue, 6 Mar 2018 02:49:49 -0800 (PST) X-Google-Smtp-Source: AG47ELtFPtoBBEch3rJfoEwCBYtTbUX9ODnz3ndg+YRukVOuLlM3NsLRFWPqu3JVYTb1Vv456Fy3 X-Received: by 10.99.39.131 with SMTP id n125mr14732665pgn.292.1520333388982; Tue, 06 Mar 2018 02:49:48 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1520333388; cv=none; d=google.com; s=arc-20160816; b=PDFcFHhR8zzZ5BGWS90Kz3X5JYJGWmEdFNLFtnMo5pb890mPfGvxpOOjSAfLzxDJE0 XL+kn0MhLAeDDVFcY3803UxRAXJA24peQCKo/Xp+BeIJofMr/RT05UmN3UyUpmUsODhG F7PM/60qHSdE2YCO81ZlITH9G1Dvl5br0f9Fey+8oz/NOiObE/h0tGYoqwfghilqRhRA iP0wW9Kt/pmN0qJ5LmV1ClCCvot7exIrQV+g3i6mUrZrPjp71qv6BBbwOR/X37h89Aek CHTh2S2cUahOGVkuIImOyleVDhictmG8M7qrgmPFZBZwGtECILFJgemHtxd+1ssv003j GO+A== 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=nvhWHZCipRIdJIkl7+hQmKOw1hwhNHiP712hSO7D/40=; b=k7baFC+gxqWHOB8Rc5//5Qj2zdtc3PiVjGNtJXaLIcBu3M93Ak3OhPBMz3fOEo3r7U CRcjhYWapvId6bwqj6DjucvwhnHwuzVjfds7LDiwe8cHyv3+0SeDUcD4GcspZ6VlM/wc vlRtz1EDgBZ4JRXcWhRqJB0+2PaQLB9vfrci5NMnDBkbwfVMbLGNWkwc+1EJykEFJQeZ ZDefkxPU0pCt/m7jt+75xi9V5VbvTfr4po7x0DwX/iLDEDEuj5TydpGkutEudCywT3LT EC5EFHEuQfH/NA0BOskH++7T+m4ZzUUO2ZdkDXVf18SzNFm5Nj++zCWowl6v98W8iCdk E8Tw== 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 m14si4284715pgs.206.2018.03.06.02.49.48; Tue, 06 Mar 2018 02:49:48 -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 S1753600AbeCFKt3 (ORCPT + 28 others); Tue, 6 Mar 2018 05:49:29 -0500 Received: from szxga04-in.huawei.com ([45.249.212.190]:6155 "EHLO huawei.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1753423AbeCFKsb (ORCPT ); Tue, 6 Mar 2018 05:48:31 -0500 Received: from DGGEMS404-HUB.china.huawei.com (unknown [172.30.72.59]) by Forcepoint Email with ESMTP id 363A79576D828; Tue, 6 Mar 2018 18:48:14 +0800 (CST) Received: from localhost.localdomain (10.67.212.75) by DGGEMS404-HUB.china.huawei.com (10.3.19.204) with Microsoft SMTP Server id 14.3.361.1; Tue, 6 Mar 2018 18:48:08 +0800 From: John Garry To: , , , , , , , , , , , , , CC: , , , , , , , , , , , , , Subject: [PATCH v16 7/9] ACPI / scan: do not enumerate Indirect IO host children Date: Tue, 6 Mar 2018 18:47:46 +0800 Message-ID: <1520333268-82754-8-git-send-email-john.garry@huawei.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1520333268-82754-1-git-send-email-john.garry@huawei.com> References: <1520333268-82754-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 Through the logical PIO framework systems which otherwise have no IO space access to legacy ISA/LPC devices may access these devices through so-called "indirect IO" method. In this, IO space accesses for non-PCI hosts are redirected to a host LLDD to manually generate the IO space (bus) accesses. Hosts are able to register a region in logical PIO space to map to its bus address range. Indirect IO child devices have an associated host-specific bus address. Special translation is required to map between a logical PIO address for a device and it's host bus address. Since in the ACPI tables the child device IO resources would be the host-specific values, it is required the ACPI scan code should not enumerate these devices, and that this should be the responsibility of the host driver so that it can "fixup" the resources so that they map to the appropriate logical PIO addresses. To avoid enumerating these child devices, we check whether the parent for a device is a member of a known list of "indirect IO" hosts. For now, the HiSilicon LPC host controller ID is added. To flag a device to not be enumerated, we reuse the existing serial bus slave flag. Signed-off-by: John Garry Acked-by: Rafael J. Wysocki Reviewed-by: Andy Shevchenko Tested-by: dann frazier --- drivers/acpi/scan.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) -- 1.9.1 diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 8e63d93..c1a60852 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1524,11 +1524,25 @@ static int acpi_check_serial_bus_slave(struct acpi_resource *ares, void *data) return -1; } +static bool acpi_is_indirect_io_slave(struct acpi_device *device) +{ + struct acpi_device *parent = device->parent; + const struct acpi_device_id indirect_io_hosts[] = { + {"HISI0191", 0}, + {} + }; + + return parent && !acpi_match_device_ids(parent, indirect_io_hosts); +} + static bool acpi_is_serial_bus_slave(struct acpi_device *device) { struct list_head resource_list; bool is_serial_bus_slave = false; + if (acpi_is_indirect_io_slave(device)) + return true; + /* Macs use device properties in lieu of _CRS resources */ if (x86_apple_machine && (fwnode_property_present(&device->fwnode, "spiSclkPeriod") || From patchwork Tue Mar 6 10:47:47 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Garry X-Patchwork-Id: 130767 Delivered-To: patch@linaro.org Received: by 10.46.66.2 with SMTP id p2csp3782851lja; Tue, 6 Mar 2018 02:48:52 -0800 (PST) X-Google-Smtp-Source: AG47ELurbZnGZgbwhc9L6JzzsUrfOGemmpOhypN4cb9EYjbs9opfQ6OpXB6tUJCL+G83hQ01Lx1R X-Received: by 10.101.71.138 with SMTP id e10mr15252541pgs.317.1520333332727; Tue, 06 Mar 2018 02:48:52 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1520333332; cv=none; d=google.com; s=arc-20160816; b=Xws13WJ5iBEEkRVZZGwE2S0t3SVAa3V+aUaSLfUiII1hUwSgoGag5/nSnXB5pYqIls /Wf2/KwFgZnGFaWr/axxhexi5qhgvxukkHUGokK4oKPwQnVNy0E4dP1CPDLlIEz4CkbS 561ZxIunns5yuCDO9hHAeyzJzi6Qu9HUVnUpxKfxWfEbBIU5qkOwhc4EOxf8gUlRQYkK MROikr/BAmlQwQziL2EXpBRJrkTHHDYikosHCZyxsiuyZ02Y+m7luTZWk30p0utqn+wv TtuYc5koRTw5sfdnmMIAE9CZh0E8YQER9TwKscjQ4G8BRw8jeA2eaUiPSoud3R0KWcP1 zfIw== 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=u5tlPEl92qBaHHaVFmr0JXx5hr8xJngcDkNjXZTR7aY=; b=exSTzMineE3+StcgTppZm6HAQNAM4s36hHqj4TVbh05f0zKbIPs0TrnszpiQba7+l7 632S12dEv4ZGnee/cYRK6gz1n8hLzk0jXn6o4OTxXtmpN5PX9D4T1/aM9GldhqmMygC/ uA148FXFXn9PKfj81kWk7oPrUTI1jG9rDy5/f7/9/NZOQ67EV52Wam98p5KyE3BJGUtX O/y+HTWLPDIFJZJRihXguhukl120NdT5MOcT9Yuncj3TPEkBuM/cFRsvdG7+0J4Siop5 1VnmNlpWNV0YMTQtZdrWDQCfEtkY1UOpGAZRolCAJFjD4NfCS+Z7eoExQFdNvcdC9eb8 OdBA== 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 s62si9714450pgc.184.2018.03.06.02.48.52; Tue, 06 Mar 2018 02:48:52 -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 S1753568AbeCFKsu (ORCPT + 28 others); Tue, 6 Mar 2018 05:48:50 -0500 Received: from szxga04-in.huawei.com ([45.249.212.190]:6158 "EHLO huawei.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1750897AbeCFKsi (ORCPT ); Tue, 6 Mar 2018 05:48:38 -0500 Received: from DGGEMS404-HUB.china.huawei.com (unknown [172.30.72.59]) by Forcepoint Email with ESMTP id 75BEE4C50E451; Tue, 6 Mar 2018 18:48:14 +0800 (CST) Received: from localhost.localdomain (10.67.212.75) by DGGEMS404-HUB.china.huawei.com (10.3.19.204) with Microsoft SMTP Server id 14.3.361.1; Tue, 6 Mar 2018 18:48:08 +0800 From: John Garry To: , , , , , , , , , , , , , CC: , , , , , , , , , , , , , Subject: [PATCH v16 8/9] HISI LPC: Add ACPI support Date: Tue, 6 Mar 2018 18:47:47 +0800 Message-ID: <1520333268-82754-9-git-send-email-john.garry@huawei.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1520333268-82754-1-git-send-email-john.garry@huawei.com> References: <1520333268-82754-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 | 202 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 202 insertions(+) -- 1.9.1 diff --git a/drivers/bus/hisi_lpc.c b/drivers/bus/hisi_lpc.c index c331609..9d38cfa 100644 --- a/drivers/bus/hisi_lpc.c +++ b/drivers/bus/hisi_lpc.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -346,6 +347,204 @@ 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) - 1) + +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 = resource_size(res); + + 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, + }; + + /* + * For any instances of this host controller (hip06 and hip07 + * are the only chipsets), we would not have multiple slaves + * with the same HID. And in any system we would have just one + * controller active. So don't worrry about MFD name clashes. + */ + 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. @@ -391,6 +590,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; @@ -414,6 +615,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, }; From patchwork Tue Mar 6 10:47: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: 130768 Delivered-To: patch@linaro.org Received: by 10.46.66.2 with SMTP id p2csp3783166lja; Tue, 6 Mar 2018 02:49:15 -0800 (PST) X-Google-Smtp-Source: AG47ELtIV/qN2DFvXugTvhGyMB94OslCQOBHPOln1nJTen9vwXFrVaLMni9qX2ryZMHGyhdT8As+ X-Received: by 10.98.41.134 with SMTP id p128mr18667732pfp.120.1520333355111; Tue, 06 Mar 2018 02:49:15 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1520333355; cv=none; d=google.com; s=arc-20160816; b=vJhlDI3fwX7D2GbJAMJpWlYB0f/9vl3QWVSILDHRBvWD3C2QLHRFgX3vffJS8tZSjJ o+hZ+zz7/8kD7EH4Ksc9LinpaxOLQhaU2d8JYt3GDPV8HM1PnTIMwNKX+NaXvqqjcVHN Uw/90XsJT4Jf6VpyLnseOoFea5cdRtUhPQVUpmcKgRDGGyvMqC8A5tq2DgXKg71pj4Uk ZDcf1fjrhcWnGk2AAtFgBHULXbEN3AyQBJpJAmKJ1lxjWtk94t4Vqip98IKc50qJQXDY tOZr7/lQipqs4zJQGEdKbZJWt5yMnh+IEVeV3nbsW6ZCEuLuK1eb8f6kFS1k8r616hUb eLnA== 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=I1Ny4etVpnhj4w4E0Liop+7XjFBzJdOKJp6JVI/JQQs=; b=yx4WEcxgEwMbbg+NmcMK73LH6le9YN5/YOEHnJlGSqXj9+JHF3AQNFxVtHLpRg7NxD HutHeGgBIeIYaOpWR5zEwEnzsM2pU0OrNZBLO9wfQWN6cPcS8Mg+lytwO9hC1ycOzaES QvZEb1xKqn0cnb2rlKXThcqzufRAtA2i5N67/l3sknIosvaKFXdcg+ce/Ofr9fs3Wb4O bhbpR5PHPcFtikTyuAWKGsbk6sqt2+LjgkSVRA+WZIwjkp/pDucBx4Yxoe5xdpxo6B0F gQ93wG0OGG61tJKuEw4loiYU7blEbARDpr+8rAD5aQxb9JKFFQlsNsHp5RKfxv5tBWEz Qy+A== 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 m9si11854172pfi.212.2018.03.06.02.49.14; Tue, 06 Mar 2018 02:49:15 -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 S1753515AbeCFKsg (ORCPT + 28 others); Tue, 6 Mar 2018 05:48:36 -0500 Received: from szxga04-in.huawei.com ([45.249.212.190]:6152 "EHLO huawei.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1753385AbeCFKsd (ORCPT ); Tue, 6 Mar 2018 05:48:33 -0500 Received: from DGGEMS404-HUB.china.huawei.com (unknown [172.30.72.59]) by Forcepoint Email with ESMTP id EA563596C4769; Tue, 6 Mar 2018 18:48:13 +0800 (CST) Received: from localhost.localdomain (10.67.212.75) by DGGEMS404-HUB.china.huawei.com (10.3.19.204) with Microsoft SMTP Server id 14.3.361.1; Tue, 6 Mar 2018 18:48:08 +0800 From: John Garry To: , , , , , , , , , , , , , CC: , , , , , , , , , , , , , Subject: [PATCH v16 9/9] MAINTAINERS: Add maintainer for HiSilicon LPC driver Date: Tue, 6 Mar 2018 18:47:48 +0800 Message-ID: <1520333268-82754-10-git-send-email-john.garry@huawei.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1520333268-82754-1-git-send-email-john.garry@huawei.com> References: <1520333268-82754-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 Added maintainer for drivers/bus/hisi_lpc.c Signed-off-by: John Garry --- MAINTAINERS | 7 +++++++ 1 file changed, 7 insertions(+) -- 1.9.1 diff --git a/MAINTAINERS b/MAINTAINERS index c187bc8..cd4f9dc 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6403,6 +6403,13 @@ W: http://www.hisilicon.com S: Maintained F: drivers/net/ethernet/hisilicon/hns3/ +HISILICON LPC BUS DRIVER +M: john.garry@huawei.com +W: http://www.hisilicon.com +S: Maintained +F: drivers/bus/hisi_lpc.c +F: Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt + HISILICON NETWORK SUBSYSTEM DRIVER M: Yisen Zhuang M: Salil Mehta