* [PATCH 4/5] tty: serial: 8250 core: add runtime pm
From: Sebastian Andrzej Siewior @ 2014-07-17 15:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <53C7EC6F.6060902@hurleysoftware.com>
* Peter Hurley | 2014-07-17 11:31:59 [-0400]:
>On 07/16/2014 12:06 PM, Felipe Balbi wrote:
>>On Wed, Jul 16, 2014 at 05:54:56PM +0200, Sebastian Andrzej Siewior wrote:
>>>On 07/16/2014 05:16 PM, Felipe Balbi wrote:
>
>>>>I wonder if you should get_sync() on start_tx() and only
>>>>put_autosuspend() at stop_tx(). I guess the outcome would be
>>>>largely the same, no ?
>>>
>>>I just opened minicom on ttyS0 and gave a try. start_tx() was invoked
>>>each time I pressed a key (sent a character). I haven't seen stop_tx()
>>>even after after I closed minicom. I guess stop_tx() is invoked if you
>>>switch half-duplex communication.
>>
>>that's bad, I expected stop to be called also after each character.
>
>The 8250 core auto-stops tx when the tx ring buffer is empty (except
>in the case of dma, where stopping tx isn't necessary).
This is correct. So this is what I have now for the non-dma case:
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index 2e4a93b..480a1c0 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -1283,6 +1283,9 @@ static inline void __stop_tx(struct uart_8250_port *p)
if (p->ier & UART_IER_THRI) {
p->ier &= ~UART_IER_THRI;
serial_out(p, UART_IER, p->ier);
+
+ pm_runtime_mark_last_busy(p->port.dev);
+ pm_runtime_put_autosuspend(p->port.dev);
}
}
@@ -1310,12 +1313,12 @@ static void serial8250_start_tx(struct uart_port *port)
struct uart_8250_port *up =
container_of(port, struct uart_8250_port, port);
- pm_runtime_get_sync(port->dev);
if (up->dma && !serial8250_tx_dma(up)) {
goto out;
} else if (!(up->ier & UART_IER_THRI)) {
up->ier |= UART_IER_THRI;
+ pm_runtime_get_sync(port->dev);
serial_port_out(port, UART_IER, up->ier);
if (up->bugs & UART_BUG_TXEN) {
unsigned char lsr;
@@ -1500,9 +1503,10 @@ void serial8250_tx_chars(struct uart_8250_port *up)
uart_write_wakeup(port);
DEBUG_INTR("THRE...");
-
+#if 0
if (uart_circ_empty(xmit))
__stop_tx(up);
+#endif
}
EXPORT_SYMBOL_GPL(serial8250_tx_chars);
and now I need to come up with something that is not if (port != omap)
for that #if 0 block. The code disables the TX FIFO empty interrupt once
the transfer is complete. I want to call __stop_tx() once the tx fifo is
empty.
Felipe, Would a check for dev->power.use_autosuspend be the right thing
to do?
>Regards,
>Peter Hurley
Sebastian
^ permalink raw reply related
* [PATCH] irqchip: gic: Fix core ID calculation when topology is read from DT
From: Tomasz Figa @ 2014-07-17 15:40 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140717153236.GS13108@titan.lakedaemon.net>
Hi Jason,
On 17.07.2014 17:32, Jason Cooper wrote:
> On Thu, Jul 17, 2014 at 05:23:44PM +0200, Tomasz Figa wrote:
>> Certain GIC implementation, namely those found on earlier, single
>> cluster, Exynos SoCs, have registers mapped without per-CPU banking,
>> which means that the driver needs to use different offset for each CPU.
>>
>> Currently the driver calculates the offset by multiplying value returned
>> by cpu_logical_map() by CPU offset parsed from DT. This is correct when
>> CPU topology is not specified in DT and aforementioned function returns
>> core ID alone. However when DT contains CPU topology, the function
>> changes to return cluster ID as well, which is non-zero on mentioned
>> SoCs and so breaks the calculation in GIC driver.
>>
>> This patch fixes this by masking out cluster ID in CPU offset
>> calculation so that only core ID is considered. Multi-cluster Exynos
>> SoCs already have banked GIC implementations, so this simple fix should
>> be enough.
>>
>> Reported-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
>> Reported-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
>> Signed-off-by: Tomasz Figa <t.figa@samsung.com>
>> ---
>> drivers/irqchip/irq-gic.c | 5 ++++-
>> 1 file changed, 4 insertions(+), 1 deletion(-)
>
> iiuc, this was introduced by:
>
> db0d4db22a78d ARM: gic: allow GIC to support non-banked setups
>
> and so should be for v3.3 and up, correct?
Could be, although there was and still is no topology data specified in
DT for affected Exynos SoCs. The need for it showed up just recently, so
I'm not sure this is a regression to fix in older kernels.
Best regards,
Tomasz
^ permalink raw reply
* [PATCH] ARM: DMA: ensure that old section mappings are flushed from the TLB
From: Russell King @ 2014-07-17 15:38 UTC (permalink / raw)
To: linux-arm-kernel
When setting up the CMA region, we must ensure that the old section
mappings are flushed from the TLB before replacing them with page
tables, otherwise we can suffer from mismatched aliases if the CPU
speculatively prefetches from these mappings at an inopportune time.
A mismatched alias can occur when the TLB contains a section mapping,
but a subsequent prefetch causes it to load a page table mapping,
resulting in the possibility of the TLB containing two matching
mappings for the same virtual address region.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
arch/arm/mm/dma-mapping.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 4c88935654ca..1f88db06b133 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -461,12 +461,21 @@ void __init dma_contiguous_remap(void)
map.type = MT_MEMORY_DMA_READY;
/*
- * Clear previous low-memory mapping
+ * Clear previous low-memory mapping to ensure that the
+ * TLB does not see any conflicting entries, then flush
+ * the TLB of the old entries before creating new mappings.
+ *
+ * This ensures that any speculatively loaded TLB entries
+ * (even though they may be rare) can not cause any problems,
+ * and ensures that this code is architecturally compliant.
*/
for (addr = __phys_to_virt(start); addr < __phys_to_virt(end);
addr += PMD_SIZE)
pmd_clear(pmd_off_k(addr));
+ flush_tlb_kernel_range(__phys_to_virt(start),
+ __phys_to_virt(end));
+
iotable_init(&map, 1);
}
}
--
1.8.3.1
^ permalink raw reply related
* [PATCH v5 4/5] PCI: add PCI controller for keystone PCIe h/w
From: Murali Karicheri @ 2014-07-17 15:35 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1405528686-16539-5-git-send-email-m-karicheri2@ti.com>
On 07/16/2014 12:38 PM, Murali Karicheri wrote:
> keystone PCIe controller is based on v3.65 version of the
> designware h/w. Main differences are
> 1. No ATU support
> 2. Legacy and MSI irq functions are implemented in
> application register space
> 3. MSI interrupts are multiplexed over 8 IRQ lines to the Host
> side.
> All of the Application register space handing code are organized into
> pci-keystone-dw.c and the functions are called from pci-keystone.c
> to implement PCI controller driver. Also add necessary DT documentation
> for the driver.
>
> Signed-off-by: Murali Karicheri<m-karicheri2@ti.com>
> Acked-by: Santosh Shilimkar<santosh.shilimkar@ti.com>
>
> CC: Russell King<linux@arm.linux.org.uk>
> CC: Grant Likely<grant.likely@linaro.org>
> CC: Rob Herring<robh+dt@kernel.org>
> CC: Mohit Kumar<mohit.kumar@st.com>
> CC: Jingoo Han<jg1.han@samsung.com>
> CC: Bjorn Helgaas<bhelgaas@google.com>
> CC: Pratyush Anand<pratyush.anand@st.com>
> CC: Richard Zhu<r65037@freescale.com>
> CC: Kishon Vijay Abraham I<kishon@ti.com>
> CC: Marek Vasut<marex@denx.de>
> CC: Arnd Bergmann<arnd@arndb.de>
> CC: Pawel Moll<pawel.moll@arm.com>
> CC: Mark Rutland<mark.rutland@arm.com>
> CC: Ian Campbell<ijc+devicetree@hellion.org.uk>
> CC: Kumar Gala<galak@codeaurora.org>
> CC: Randy Dunlap<rdunlap@infradead.org>
> CC: Grant Likely<grant.likely@linaro.org>
> ---
> .../devicetree/bindings/pci/pci-keystone.txt | 71 +++
> drivers/pci/host/Kconfig | 5 +
> drivers/pci/host/Makefile | 1 +
> drivers/pci/host/pci-keystone-dw.c | 516 ++++++++++++++++++++
> drivers/pci/host/pci-keystone.c | 385 +++++++++++++++
> drivers/pci/host/pci-keystone.h | 59 +++
> 6 files changed, 1037 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/pci/pci-keystone.txt
> create mode 100644 drivers/pci/host/pci-keystone-dw.c
> create mode 100644 drivers/pci/host/pci-keystone.c
> create mode 100644 drivers/pci/host/pci-keystone.h
>
> diff --git a/Documentation/devicetree/bindings/pci/pci-keystone.txt b/Documentation/devicetree/bindings/pci/pci-keystone.txt
> new file mode 100644
> index 0000000..9c96164
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/pci/pci-keystone.txt
> @@ -0,0 +1,71 @@
> +TI Keystone PCIe interface
> +
> +Keystone PCI host Controller is based on Designware PCI h/w version 3.65.
> +It shares common functions with PCIE Designware core driver and inherit
> +common properties defined in
> +Documentation/devicetree/bindings/pci/designware-pci.txt
> +
> +Please refer to Documentation/devicetree/bindings/pci/designware-pci.txt
> +for the details of designware DT bindings. Additional properties are
> +described here as well propeties that are not applicable.
> +
> +Required Properties:-
> +
> +compatibility: "ti,keystone-pcie"
> +reg: index 1 is the base address and length of DW application registers.
> + index 2 is the base address and length of PCI mode configuration
> + register.
> + index 3 is the base address and length of PCI device ID register.
> +
> +pcie_msi_intc : Interrupt controller device node for MSI irq chip
> + interrupt-cells: should be set to 1
> + interrupt-parent: Parent interrupt controller phandle
> + interrupts: GIC interrupt lines connected to PCI MSI interrupt lines
> +
> + Example:
> + pcie_msi_intc: msi-interrupt-controller {
> + interrupt-controller;
> + #interrupt-cells =<1>;
> + interrupt-parent =<&gic>;
> + interrupts =<GIC_SPI 30 IRQ_TYPE_EDGE_RISING>,
> + <GIC_SPI 31 IRQ_TYPE_EDGE_RISING>,
> + <GIC_SPI 32 IRQ_TYPE_EDGE_RISING>,
> + <GIC_SPI 33 IRQ_TYPE_EDGE_RISING>,
> + <GIC_SPI 34 IRQ_TYPE_EDGE_RISING>,
> + <GIC_SPI 35 IRQ_TYPE_EDGE_RISING>,
> + <GIC_SPI 36 IRQ_TYPE_EDGE_RISING>,
> + <GIC_SPI 37 IRQ_TYPE_EDGE_RISING>;
> + };
> +
> +pcie_intc: Interrupt controller device node for Legacy irq chip
> + interrupt-cells: should be set to 1
> + interrupt-parent: Parent interrupt controller phandle
> + interrupts: GIC interrupt lines connected to PCI Legacy interrupt lines
> +
> + Example:
> + pcie_intc: legacy-interrupt-controller {
> + interrupt-controller;
> + #interrupt-cells =<1>;
> + interrupt-parent =<&gic>;
> + interrupts =<GIC_SPI 26 IRQ_TYPE_EDGE_RISING>,
> + <GIC_SPI 27 IRQ_TYPE_EDGE_RISING>,
> + <GIC_SPI 28 IRQ_TYPE_EDGE_RISING>,
> + <GIC_SPI 29 IRQ_TYPE_EDGE_RISING>;
> + };
> +
> +Optional properties:-
> + phys: phandle to Generic Keystone SerDes phy for PCI
> + phy-names: name of the Generic Keystine SerDes phy for PCI
> + - If boot loader already does PCI link establishment, then phys and
> + phy-names shouldn't be present.
> + ti,enable-linktrain - Enable Link training.
> + - If boot loader already does PCI link establishment, then this
> + shouldn't be present.
> +
> +Designware DT Properties not applicable for Keystone PCI
> +
> +1. pcie_bus clock-names not used. Instead, a phandle to phys is used.
> +
> +Note for PCI driver usage
> +=========================
> +Driver requires pci=pcie_bus_perf in the bootargs for proper functioning.
> diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
> index 21df477..f8bc475 100644
> --- a/drivers/pci/host/Kconfig
> +++ b/drivers/pci/host/Kconfig
> @@ -46,4 +46,9 @@ config PCI_HOST_GENERIC
> Say Y here if you want to support a simple generic PCI host
> controller, such as the one emulated by kvmtool.
>
> +config PCI_KEYSTONE
> + bool "TI Keystone PCIe controller"
> + depends on ARCH_KEYSTONE
> + select PCIE_DW
> + select PCIEPORTBUS
> endmenu
> diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile
> index 611ba4b..d1b6ce1 100644
> --- a/drivers/pci/host/Makefile
> +++ b/drivers/pci/host/Makefile
> @@ -6,3 +6,4 @@ obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o
> obj-$(CONFIG_PCI_RCAR_GEN2) += pci-rcar-gen2.o
> obj-$(CONFIG_PCI_RCAR_GEN2_PCIE) += pcie-rcar.o
> obj-$(CONFIG_PCI_HOST_GENERIC) += pci-host-generic.o
> +obj-$(CONFIG_PCI_KEYSTONE) += pci-keystone-dw.o pci-keystone.o
> diff --git a/drivers/pci/host/pci-keystone-dw.c b/drivers/pci/host/pci-keystone-dw.c
> new file mode 100644
> index 0000000..b75582c
> --- /dev/null
> +++ b/drivers/pci/host/pci-keystone-dw.c
> @@ -0,0 +1,516 @@
> +/*
> + * Designware application register space functions for Keystone PCI controller
> + *
> + * Copyright (C) 2013-2014 Texas Instruments., Ltd.
> + * http://www.ti.com
> + *
> + * Author: Murali Karicheri<m-karicheri2@ti.com>
> + *
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include<linux/irq.h>
> +#include<linux/irqdomain.h>
> +#include<linux/module.h>
> +#include<linux/of.h>
> +#include<linux/of_pci.h>
> +#include<linux/pci.h>
> +#include<linux/platform_device.h>
> +
> +#include "pcie-designware.h"
> +#include "pci-keystone.h"
> +
> +/* Application register defines */
> +#define LTSSM_EN_VAL 1
> +#define LTSSM_STATE_MASK 0x1f
> +#define LTSSM_STATE_L0 0x11
> +#define DBI_CS2_EN_VAL 0x20
> +#define OB_XLAT_EN_VAL 2
> +
> +/* Application registers */
> +#define CMD_STATUS 0x004
> +#define CFG_SETUP 0x008
> +#define OB_SIZE 0x030
> +#define CFG_PCIM_WIN_SZ_IDX 3
> +#define CFG_PCIM_WIN_CNT 32
> +#define SPACE0_REMOTE_CFG_OFFSET 0x1000
> +#define OB_OFFSET_INDEX(n) (0x200 + (8 * n))
> +#define OB_OFFSET_HI(n) (0x204 + (8 * n))
> +
> +/* IRQ register defines */
> +#define IRQ_EOI 0x050
> +#define IRQ_STATUS 0x184
> +#define IRQ_ENABLE_SET 0x188
> +#define IRQ_ENABLE_CLR 0x18c
> +
> +#define MSI_IRQ 0x054
> +#define MSI0_IRQ_STATUS 0x104
> +#define MSI0_IRQ_ENABLE_SET 0x108
> +#define MSI0_IRQ_ENABLE_CLR 0x10c
> +#define IRQ_STATUS 0x184
> +#define MSI_IRQ_OFFSET 4
> +
> +/* Config space registers */
> +#define DEBUG0 0x728
> +
> +#define to_keystone_pcie(x) container_of(x, struct keystone_pcie, pp)
> +
> +static inline struct pcie_port *sys_to_pcie(struct pci_sys_data *sys)
> +{
> + return sys->private_data;
> +}
> +
> +static inline void update_reg_offset_bit_pos(u32 offset, u32 *reg_offset,
> + u32 *bit_pos)
> +{
> + *reg_offset = offset % 8;
> + *bit_pos = offset>> 3;
> +}
> +
> +u32 ks_dw_pcie_get_msi_data(struct pcie_port *pp)
> +{
> + struct keystone_pcie *ks_pcie = to_keystone_pcie(pp);
> +
> + return ks_pcie->app.start + MSI_IRQ;
> +}
> +
> +void ks_dw_pcie_handle_msi_irq(struct keystone_pcie *ks_pcie , int offset)
> +{
> + struct pcie_port *pp =&ks_pcie->pp;
> + u32 pending, vector;
> + int src, virq;
> +
> + pending = readl(ks_pcie->va_app_base + MSI0_IRQ_STATUS + (offset<< 4));
> + /*
> + * MSI0, Status bit 0-3 shows vectors 0, 8, 16, 24, MSI1 status bit
> + * shows 1, 9, 17, 25 and so forth
> + */
> + for (src = 0; src< 4; src++) {
> + if (BIT(src)& pending) {
> + vector = offset + (src<< 3);
> + virq = irq_linear_revmap(pp->irq_domain, vector);
> + dev_dbg(pp->dev,
> + "irq: bit %d, vector %d, virq %d\n",
> + src, vector, virq);
> + generic_handle_irq(virq);
> + }
> + }
> +}
> +
> +static void ks_dw_pcie_msi_irq_ack(struct irq_data *d)
> +{
> + u32 offset, reg_offset, bit_pos;
> + struct keystone_pcie *ks_pcie;
> + unsigned int irq = d->irq;
> + struct msi_desc *msi;
> + struct pcie_port *pp;
> +
> + msi = irq_get_msi_desc(irq);
> + pp = sys_to_pcie(msi->dev->bus->sysdata);
> + ks_pcie = to_keystone_pcie(pp);
> + offset = irq - irq_linear_revmap(pp->irq_domain, 0);
> + update_reg_offset_bit_pos(offset,®_offset,&bit_pos);
> +
> + writel(BIT(bit_pos),
> + ks_pcie->va_app_base + MSI0_IRQ_STATUS + (reg_offset<< 4));
> + writel(reg_offset + MSI_IRQ_OFFSET, ks_pcie->va_app_base + IRQ_EOI);
> +}
> +
> +void ks_dw_pcie_msi_set_irq(struct pcie_port *pp, int irq)
> +{
> + u32 reg_offset, bit_pos;
> + struct keystone_pcie *ks_pcie = to_keystone_pcie(pp);
> +
> + update_reg_offset_bit_pos(irq,®_offset,&bit_pos);
> + writel(BIT(bit_pos),
> + ks_pcie->va_app_base + MSI0_IRQ_ENABLE_SET + (reg_offset<< 4));
> +}
> +
> +void ks_dw_pcie_msi_clear_irq(struct pcie_port *pp, int irq)
> +{
> + u32 reg_offset, bit_pos;
> + struct keystone_pcie *ks_pcie = to_keystone_pcie(pp);
> +
> + update_reg_offset_bit_pos(irq,®_offset,&bit_pos);
> + writel(BIT(bit_pos),
> + ks_pcie->va_app_base + MSI0_IRQ_ENABLE_CLR + (reg_offset<< 4));
> +}
> +
> +static void ks_dw_pcie_msi_irq_mask(struct irq_data *d)
> +{
> + struct keystone_pcie *ks_pcie;
> + unsigned int irq = d->irq;
> + struct msi_desc *msi;
> + struct pcie_port *pp;
> + u32 offset;
> +
> + msi = irq_get_msi_desc(irq);
> + pp = sys_to_pcie(msi->dev->bus->sysdata);
> + ks_pcie = to_keystone_pcie(pp);
> + offset = irq - irq_linear_revmap(pp->irq_domain, 0);
> +
> + /* mask the end point if PVM implemented */
> + if (IS_ENABLED(CONFIG_PCI_MSI)) {
> + if (msi->msi_attrib.maskbit)
> + mask_msi_irq(d);
> + }
> +
> + ks_dw_pcie_msi_clear_irq(pp, offset);
> +}
> +
> +static void ks_dw_pcie_msi_irq_unmask(struct irq_data *d)
> +{
> + struct keystone_pcie *ks_pcie;
> + unsigned int irq = d->irq;
> + struct msi_desc *msi;
> + struct pcie_port *pp;
> + u32 offset;
> +
> + msi = irq_get_msi_desc(irq);
> + pp = sys_to_pcie(msi->dev->bus->sysdata);
> + ks_pcie = to_keystone_pcie(pp);
> + offset = irq - irq_linear_revmap(pp->irq_domain, 0);
> +
> + /* mask the end point if PVM implemented */
> + if (IS_ENABLED(CONFIG_PCI_MSI)) {
> + if (msi->msi_attrib.maskbit)
> + unmask_msi_irq(d);
> + }
> +
> + ks_dw_pcie_msi_set_irq(pp, offset);
> +}
> +
> +static struct irq_chip ks_dw_pcie_msi_irq_chip = {
> + .name = "Keystone-PCIe-MSI-IRQ",
> + .irq_ack = ks_dw_pcie_msi_irq_ack,
> + .irq_mask = ks_dw_pcie_msi_irq_mask,
> + .irq_unmask = ks_dw_pcie_msi_irq_unmask,
> +};
> +
> +static int ks_dw_pcie_msi_map(struct irq_domain *domain, unsigned int irq,
> + irq_hw_number_t hwirq)
> +{
> + irq_set_chip_and_handler(irq,&ks_dw_pcie_msi_irq_chip,
> + handle_level_irq);
> + irq_set_chip_data(irq, domain->host_data);
> + set_irq_flags(irq, IRQF_VALID);
> +
> + return 0;
> +}
> +
> +const struct irq_domain_ops ks_dw_pcie_msi_domain_ops = {
> + .map = ks_dw_pcie_msi_map,
> +};
> +
> +int ks_dw_pcie_msi_host_init(struct pcie_port *pp,
> + struct msi_chip *chip)
> +{
> + struct keystone_pcie *ks_pcie = to_keystone_pcie(pp);
> + int i;
> +
> + pp->irq_domain = irq_domain_add_linear(ks_pcie->msi_intc_np,
> + MAX_MSI_IRQS,
> + &ks_dw_pcie_msi_domain_ops,
> + chip);
> + if (!pp->irq_domain) {
> + dev_err(pp->dev, "irq domain init failed\n");
> + return -ENXIO;
> + }
> +
> + for (i = 0; i< MAX_MSI_IRQS; i++)
> + irq_create_mapping(pp->irq_domain, i);
> +
> + return 0;
> +}
> +
> +void ks_dw_pcie_enable_legacy_irqs(struct keystone_pcie *ks_pcie)
> +{
> + int i;
> +
> + for (i = 0; i< MAX_LEGACY_IRQS; i++)
> + writel(0x1, ks_pcie->va_app_base + IRQ_ENABLE_SET + (i<< 4));
> +}
> +
> +void ks_dw_pcie_handle_legacy_irq(struct keystone_pcie *ks_pcie, int offset)
> +{
> + struct pcie_port *pp =&ks_pcie->pp;
> + u32 pending;
> + int virq;
> +
> + pending = readl(ks_pcie->va_app_base + IRQ_STATUS + (offset<< 4));
> +
> + if (BIT(0)& pending) {
> + virq = irq_linear_revmap(ks_pcie->legacy_irq_domain, offset);
> + dev_dbg(pp->dev,
> + ": irq: irq_offset %d, virq %d\n", offset, virq);
> + generic_handle_irq(virq);
> + }
> +
> + /* EOI the INTx interrupt */
> + writel(offset, ks_pcie->va_app_base + IRQ_EOI);
> +}
> +
> +static void ks_dw_pcie_ack_legacy_irq(struct irq_data *d)
> +{
> +}
> +
> +static void ks_dw_pcie_mask_legacy_irq(struct irq_data *d)
> +{
> +}
> +
> +static void ks_dw_pcie_unmask_legacy_irq(struct irq_data *d)
> +{
> +}
> +
> +static struct irq_chip ks_dw_pcie_legacy_irq_chip = {
> + .name = "Keystone-PCI-Legacy-IRQ",
> + .irq_ack = ks_dw_pcie_ack_legacy_irq,
> + .irq_mask = ks_dw_pcie_mask_legacy_irq,
> + .irq_unmask = ks_dw_pcie_unmask_legacy_irq,
> +};
> +
> +static int ks_dw_pcie_init_legacy_irq_map(struct irq_domain *d,
> + unsigned int irq, irq_hw_number_t hw_irq)
> +{
> + irq_set_chip_and_handler(irq,&ks_dw_pcie_legacy_irq_chip,
> + handle_level_irq);
> + irq_set_chip_data(irq, d->host_data);
> + set_irq_flags(irq, IRQF_VALID);
> +
> + return 0;
> +}
> +
> +static const struct irq_domain_ops ks_dw_pcie_legacy_irq_domian_ops = {
> + .map = ks_dw_pcie_init_legacy_irq_map,
> + .xlate = irq_domain_xlate_onetwocell,
> +};
> +
> +/**
> + * ks_dw_pcie_set_dbi_mode() - Set DBI mode to access overlaid BAR mask registers
> + *
> + * Since modification of dbi_cs2 involves different clock domain, read the
> + * status back to ensure the transition is complete.
> + */
> +static void ks_dw_pcie_set_dbi_mode(void __iomem *reg_virt)
> +{
> + u32 val;
> +
> + writel(DBI_CS2_EN_VAL | readl(reg_virt + CMD_STATUS),
> + reg_virt + CMD_STATUS);
> +
> + do {
> + val = readl(reg_virt + CMD_STATUS);
> + } while (!(val& DBI_CS2_EN_VAL));
> +}
> +
> +/**
> + * ks_dw_pcie_clear_dbi_mode() - Disable DBI mode
> + *
> + * Since modification of dbi_cs2 involves different clock domain, read the
> + * status back to ensure the transition is complete.
> + */
> +static void ks_dw_pcie_clear_dbi_mode(void __iomem *reg_virt)
> +{
> + u32 val;
> +
> + writel(~DBI_CS2_EN_VAL& readl(reg_virt + CMD_STATUS),
> + reg_virt + CMD_STATUS);
> +
> + do {
> + val = readl(reg_virt + CMD_STATUS);
> + } while (val& DBI_CS2_EN_VAL);
> +}
> +
> +void ks_dw_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie)
> +{
> + struct pcie_port *pp =&ks_pcie->pp;
> + u32 start = pp->mem.start, end = pp->mem.end;
> + int i, tr_size;
> +
> + /* disable BARS for inbound access */
> + ks_dw_pcie_set_dbi_mode(ks_pcie->va_app_base);
> + writel(0, pp->dbi_base + PCI_BASE_ADDRESS_0);
> + writel(0, pp->dbi_base + PCI_BASE_ADDRESS_1);
> + ks_dw_pcie_clear_dbi_mode(ks_pcie->va_app_base);
> +
> + /* Set outbound translation size per window division */
> + writel(CFG_PCIM_WIN_SZ_IDX& 0x7, ks_pcie->va_app_base + OB_SIZE);
> +
> + tr_size = (1<< (CFG_PCIM_WIN_SZ_IDX& 0x7)) * SZ_1M;
> +
> + /* Using Direct 1:1 mapping of RC<-> PCI memory space */
> + for (i = 0; (i< CFG_PCIM_WIN_CNT)&& (start< end); i++) {
> + writel(start | 1, ks_pcie->va_app_base + OB_OFFSET_INDEX(i));
> + writel(0, ks_pcie->va_app_base + OB_OFFSET_HI(i));
> + start += tr_size;
> + }
> +
> + /* Enable OB translation */
> + writel(OB_XLAT_EN_VAL | readl(ks_pcie->va_app_base + CMD_STATUS),
> + ks_pcie->va_app_base + CMD_STATUS);
> +}
> +
> +/**
> + * ks_pcie_cfg_setup() - Set up configuration space address for a
> + * device
> + *
> + * @ks_pcie: ptr to keystone_pcie structure
> + * @bus: Bus number the device is residing on
> + * @devfn: device, function number info
> + *
> + * Forms and returns the address of configuration space mapped in PCIESS
> + * address space 0. Also configures CFG_SETUP for remote configuration space
> + * access.
> + *
> + * The address space has two regions to access configuration - local and remote.
> + * We access local region for bus 0 (as RC is attached on bus 0) and remote
> + * region for others with TYPE 1 access when bus> 1. As for device on bus = 1,
> + * we will do TYPE 0 access as it will be on our secondary bus (logical).
> + * CFG_SETUP is needed only for remote configuration access.
> + */
> +static void __iomem *ks_pcie_cfg_setup(struct keystone_pcie *ks_pcie, u8 bus,
> + unsigned int devfn)
> +{
> + u8 device = PCI_SLOT(devfn), function = PCI_FUNC(devfn);
> + struct pcie_port *pp =&ks_pcie->pp;
> + u32 regval;
> +
> + if (bus == 0)
> + return pp->dbi_base;
> +
> + regval = (bus<< 16) | (device<< 8) | function;
> + /*
> + * Since Bus#1 will be a virtual bus, we need to have TYPE0
> + * access only.
> + * TYPE 1
> + */
> + if (bus != 1)
> + regval |= BIT(24);
> +
> + writel(regval, ks_pcie->va_app_base + CFG_SETUP);
> + return pp->va_cfg0_base;
> +}
> +
> +int ks_dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
> + unsigned int devfn, int where, int size, u32 *val)
> +{
> + struct keystone_pcie *ks_pcie = to_keystone_pcie(pp);
> + u8 bus_num = bus->number;
> + void __iomem *addr;
> + int ret;
> +
> + addr = ks_pcie_cfg_setup(ks_pcie, bus_num, devfn);
> + ret = dw_pcie_cfg_read(addr + (where& ~0x3), where, size, val);
> +
> + return ret;
> +}
> +
> +int ks_dw_pcie_wr_other_conf(struct pcie_port *pp,
> + struct pci_bus *bus, unsigned int devfn, int where,
> + int size, u32 val)
> +{
> + struct keystone_pcie *ks_pcie = to_keystone_pcie(pp);
> + u8 bus_num = bus->number;
> + void __iomem *addr;
> +
> + addr = ks_pcie_cfg_setup(ks_pcie, bus_num, devfn);
> +
> + return dw_pcie_cfg_write(addr + (where& ~0x3), where, size, val);
> +}
> +
> +/**
> + * ks_dw_pcie_v3_65_scan_bus() - keystone scan_bus post initialization
> + *
> + * This sets BAR0 to enable inbound access for MSI_IRQ register
> + */
> +void ks_dw_pcie_v3_65_scan_bus(struct pcie_port *pp)
> +{
> + struct keystone_pcie *ks_pcie = to_keystone_pcie(pp);
> +
> + /* Configure and set up BAR0 */
> + ks_dw_pcie_set_dbi_mode(ks_pcie->va_app_base);
> +
> + /* Enable BAR0 */
> + writel(1, pp->dbi_base + PCI_BASE_ADDRESS_0);
> + writel(SZ_4K - 1, pp->dbi_base + PCI_BASE_ADDRESS_0);
> +
> + ks_dw_pcie_clear_dbi_mode(ks_pcie->va_app_base);
> +
> + /*
> + * For BAR0, just setting bus address for inbound writes (MSI) should
> + * be sufficient. Use physical address to avoid any conflicts.
> + */
> + writel(ks_pcie->app.start, pp->dbi_base + PCI_BASE_ADDRESS_0);
> +}
> +
> +/**
> + * ks_dw_pcie_link_up() - Check if link up
> + *
> + */
> +int ks_dw_pcie_link_up(struct pcie_port *pp)
> +{
> + u32 val = readl(pp->dbi_base + DEBUG0);
> +
> + return (val& LTSSM_STATE_MASK) == LTSSM_STATE_L0;
> +}
> +
> +void ks_dw_pcie_initiate_link_train(struct keystone_pcie *ks_pcie)
> +{
> + u32 val;
> +
> + /* Initiate Link Training. */
> + val = readl(ks_pcie->va_app_base + CMD_STATUS);
> + writel(LTSSM_EN_VAL | val, ks_pcie->va_app_base + CMD_STATUS);
> +}
> +
> +/**
> + * ks_dw_pcie_host_init() - initialize host for v3_65 dw hardware
> + *
> + * It ioremap the register resources, initialize legacy irq domain
> + * and then call dw_pcie_v3_65_host_init() API to intialize the Keystone
> + * PCI host controller.
> + *
> + */
> +int __init ks_dw_pcie_host_init(struct keystone_pcie *ks_pcie,
> + struct device_node *msi_intc_np)
> +{
> + struct pcie_port *pp =&ks_pcie->pp;
> + struct platform_device *pdev = to_platform_device(pp->dev);
> + struct resource *res;
> +
> + /* index 0 is the config reg. space address */
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + pp->dbi_base = devm_ioremap_resource(pp->dev, res);
> + if (IS_ERR(pp->dbi_base))
> + return PTR_ERR(pp->dbi_base);
> +
> + /*
> + * we set these same and is used in pcie rd/wr_other_conf
> + * functions
> + */
> + pp->va_cfg0_base = pp->dbi_base + SPACE0_REMOTE_CFG_OFFSET;
> + pp->va_cfg1_base = pp->va_cfg0_base;
> +
> + /* index 1 is the application reg. space address */
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> + ks_pcie->app = *res;
> + ks_pcie->va_app_base = devm_ioremap_resource(pp->dev, res);
> + if (IS_ERR(ks_pcie->va_app_base))
> + return PTR_ERR(ks_pcie->va_app_base);
> +
> + /* create legacy irq domain */
> + ks_pcie->legacy_irq_domain =
> + irq_domain_add_linear(ks_pcie->legacy_intc_np,
> + MAX_LEGACY_IRQS,
> + &ks_dw_pcie_legacy_irq_domian_ops,
> + NULL);
> + if (!ks_pcie->legacy_irq_domain) {
> + dev_err(pp->dev, "Failed to add irq domain for legacy irqs\n");
> + return -EINVAL;
> + }
> +
> + return dw_pcie_host_init(pp);
> +}
> diff --git a/drivers/pci/host/pci-keystone.c b/drivers/pci/host/pci-keystone.c
> new file mode 100644
> index 0000000..341ced8
> --- /dev/null
> +++ b/drivers/pci/host/pci-keystone.c
> @@ -0,0 +1,385 @@
> +/*
> + * PCIe host controller driver for Texas Instruments Keystone SoCs
> + *
> + * Copyright (C) 2013-2014 Texas Instruments., Ltd.
> + * http://www.ti.com
> + *
> + * Author: Murali Karicheri<m-karicheri2@ti.com>
> + * Implementation based on pci-exynos.c and pcie-designware.c
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include<linux/irqchip/chained_irq.h>
> +#include<linux/clk.h>
> +#include<linux/delay.h>
> +#include<linux/irqdomain.h>
> +#include<linux/module.h>
> +#include<linux/msi.h>
> +#include<linux/of_irq.h>
> +#include<linux/of.h>
> +#include<linux/of_pci.h>
> +#include<linux/platform_device.h>
> +#include<linux/phy/phy.h>
> +#include<linux/resource.h>
> +#include<linux/signal.h>
> +
> +#include "pcie-designware.h"
> +#include "pci-keystone.h"
> +
> +#define DRIVER_NAME "keystone-pcie"
> +
> +/* driver specific constants */
> +#define MAX_MSI_HOST_IRQS 8
> +#define MAX_LEGACY_HOST_IRQS 4
> +
> +/* RC mode settings masks */
> +#define PCIE_RC_MODE BIT(2)
> +#define PCIE_MODE_MASK (BIT(1) | BIT(2))
> +
> +/* DEV_STAT_CTRL */
> +#define PCIE_CAP_BASE 0x70
> +
> +#define to_keystone_pcie(x) container_of(x, struct keystone_pcie, pp)
> +
> +static int ks_pcie_establish_link(struct keystone_pcie *ks_pcie)
> +{
> + struct pcie_port *pp =&ks_pcie->pp;
> + int count = 200;
> +
> + dw_pcie_setup_rc(pp);
> + if (ks_pcie->link_train)
> + ks_dw_pcie_initiate_link_train(ks_pcie);
> +
> + /* check if the link is up or not */
> + while (!dw_pcie_link_up(pp)) {
> + usleep_range(100, 1000);
> + if (--count)
> + continue;
> + dev_err(pp->dev, "phy link never came up\n");
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> +static void ks_pcie_msi_irq_handler(unsigned int irq, struct irq_desc *desc)
> +{
> + struct keystone_pcie *ks_pcie = irq_desc_get_handler_data(desc);
> + u32 offset = irq - ks_pcie->msi_host_irqs[0];
> + struct pcie_port *pp =&ks_pcie->pp;
> + struct irq_chip *chip = irq_desc_get_chip(desc);
> +
> + dev_dbg(pp->dev, "ks_pci_msi_irq_handler, irq %d\n", irq);
> +
> + /*
> + * The chained irq handler installation would have replaced normal
> + * interrupt driver handler so we need to take care of mask/unmask and
> + * ack operation.
> + */
> + chained_irq_enter(chip, desc);
> + ks_dw_pcie_handle_msi_irq(ks_pcie, offset);
> + chained_irq_exit(chip, desc);
> +}
> +
> +/**
> + * ks_pcie_legacy_irq_handler() - Handle legacy interrupt
> + * @irq: IRQ line for legacy interrupts
> + * @desc: Pointer to irq descriptor
> + *
> + * Traverse through pending legacy interrupts and invoke handler for each. Also
> + * takes care of interrupt controller level mask/ack operation.
> + */
> +static void ks_pcie_legacy_irq_handler(unsigned int irq, struct irq_desc *desc)
> +{
> + struct keystone_pcie *ks_pcie = irq_desc_get_handler_data(desc);
> + struct pcie_port *pp =&ks_pcie->pp;
> + u32 irq_offset = irq - ks_pcie->legacy_host_irqs[0];
> + struct irq_chip *chip = irq_desc_get_chip(desc);
> +
> + dev_dbg(pp->dev, ": Handling legacy irq %d\n", irq);
> +
> + /*
> + * The chained irq handler installation would have replaced normal
> + * interrupt driver handler so we need to take care of mask/unmask and
> + * ack operation.
> + */
> + chained_irq_enter(chip, desc);
> + ks_dw_pcie_handle_legacy_irq(ks_pcie, irq_offset);
> + chained_irq_exit(chip, desc);
> +}
> +
> +static int ks_pcie_get_irq_controller_info(struct keystone_pcie *ks_pcie,
> + char *controller, int *num_irqs)
> +{
> + int temp, max_host_irqs, legacy = 1, *host_irqs, ret = -EINVAL;
> + struct device *dev = ks_pcie->pp.dev;
> + struct device_node *np_pcie = dev->of_node, **np_temp;
> +
> + if (!strcmp(controller, "msi-interrupt-controller"))
> + legacy = 0;
> +
> + if (legacy) {
> + np_temp =&ks_pcie->legacy_intc_np;
> + max_host_irqs = MAX_LEGACY_HOST_IRQS;
> + host_irqs =&ks_pcie->legacy_host_irqs[0];
> + } else {
> + np_temp =&ks_pcie->msi_intc_np;
> + max_host_irqs = MAX_MSI_HOST_IRQS;
> + host_irqs =&ks_pcie->msi_host_irqs[0];
> + }
> +
> + /* interrupt controller is in a child node */
> + *np_temp = of_find_node_by_name(np_pcie, controller);
> + if (!(*np_temp)) {
> + dev_err(dev, "Node for %s is absent\n", controller);
> + goto out;
> + }
> + temp = of_irq_count(*np_temp);
> + if (!temp)
> + goto out;
> + if (temp> max_host_irqs)
> + dev_warn(dev, "Too many %s interrupts defined %u\n",
> + (legacy ? "legacy" : "MSI"), temp);
> +
> + /*
> + * support upto max_host_irqs. In dt from index 0 to 3 (legacy) or 0 to
> + * 7 (MSI)
> + */
> + for (temp = 0; temp< max_host_irqs; temp++) {
> + host_irqs[temp] = irq_of_parse_and_map(*np_temp, temp);
> + if (host_irqs[temp]< 0)
> + break;
> + }
> + if (temp) {
> + *num_irqs = temp;
> + ret = 0;
> + }
> +out:
> + return ret;
> +}
> +
> +static void ks_pcie_setup_interrupts(struct keystone_pcie *ks_pcie)
> +{
> + int i;
> +
> + /* Legacy IRQ */
> + for (i = 0; i< ks_pcie->num_legacy_host_irqs; i++) {
> + irq_set_handler_data(ks_pcie->legacy_host_irqs[i], ks_pcie);
> + irq_set_chained_handler(ks_pcie->legacy_host_irqs[i],
> + ks_pcie_legacy_irq_handler);
> + }
> + ks_dw_pcie_enable_legacy_irqs(ks_pcie);
> +
> + /* MSI IRQ */
> + if (IS_ENABLED(CONFIG_PCI_MSI)) {
> + for (i = 0; i< ks_pcie->num_msi_host_irqs; i++) {
> + irq_set_chained_handler(ks_pcie->msi_host_irqs[i],
> + ks_pcie_msi_irq_handler);
> + irq_set_handler_data(ks_pcie->msi_host_irqs[i],
> + ks_pcie);
> + }
> + }
> +}
> +
> +/*
> + * When a PCI device does not exist during config cycles, keystone host gets a
> + * bus error instead of returning 0xffffffff. This handler always returns 0
> + * for this kind of faults.
> + */
> +static int keystone_pcie_fault(unsigned long addr, unsigned int fsr,
> + struct pt_regs *regs)
> +{
> + unsigned long instr = *(unsigned long *) instruction_pointer(regs);
> +
> + if ((instr& 0x0e100090) == 0x00100090) {
> + int reg = (instr>> 12)& 15;
> +
> + regs->uregs[reg] = -1;
> + regs->ARM_pc += 4;
> + }
> +
> + return 0;
> +}
> +
> +static void __init ks_pcie_host_init(struct pcie_port *pp)
> +{
> + u32 vendor_device_id, val;
> + struct keystone_pcie *ks_pcie = to_keystone_pcie(pp);
> +
> + ks_pcie_establish_link(ks_pcie);
> + ks_dw_pcie_setup_rc_app_regs(ks_pcie);
> + ks_pcie_setup_interrupts(ks_pcie);
> + writew(PCI_IO_RANGE_TYPE_32 | (PCI_IO_RANGE_TYPE_32<< 8),
> + pp->dbi_base + PCI_IO_BASE);
> +
> + /* update the Vendor ID */
> + vendor_device_id = readl(ks_pcie->va_reg_pciid);
> + writew((vendor_device_id>> 16), pp->dbi_base + PCI_DEVICE_ID);
> +
> + /* update the DEV_STAT_CTRL to publish right mrrs */
> + val = readl(pp->dbi_base + PCIE_CAP_BASE + PCI_EXP_DEVCTL);
> + val&= ~PCI_EXP_DEVCTL_READRQ;
> + /* set the mrrs to 256 bytes */
> + val |= BIT(12);
> + writel(val, pp->dbi_base + PCIE_CAP_BASE + PCI_EXP_DEVCTL);
> +
> + /*
> + * PCIe access errors that result into OCP errors are caught by ARM as
> + * "External aborts"
> + */
> + hook_fault_code(17, keystone_pcie_fault, SIGBUS, 0,
> + "Asynchronous external abort");
> +}
> +
> +static struct pcie_host_ops keystone_pcie_host_ops = {
> + .rd_other_conf = ks_dw_pcie_rd_other_conf,
> + .wr_other_conf = ks_dw_pcie_wr_other_conf,
> + .link_up = ks_dw_pcie_link_up,
> + .host_init = ks_pcie_host_init,
> + .msi_set_irq = ks_dw_pcie_msi_set_irq,
> + .msi_clear_irq = ks_dw_pcie_msi_clear_irq,
> + .get_msi_data = ks_dw_pcie_get_msi_data,
> + .msi_host_init = ks_dw_pcie_msi_host_init,
> + .scan_bus = ks_dw_pcie_v3_65_scan_bus,
> +};
> +
> +static int __init ks_add_pcie_port(struct keystone_pcie *ks_pcie,
> + struct platform_device *pdev)
> +{
> + struct pcie_port *pp =&ks_pcie->pp;
> + int ret;
> +
> + ret = ks_pcie_get_irq_controller_info(ks_pcie,
> + "legacy-interrupt-controller",
> + &ks_pcie->num_legacy_host_irqs);
> + if (ret)
> + return ret;
> +
> + if (IS_ENABLED(CONFIG_PCI_MSI)) {
> + ret = ks_pcie_get_irq_controller_info(ks_pcie,
> + "msi-interrupt-controller",
> + &ks_pcie->num_msi_host_irqs);
> + if (ret)
> + return ret;
> + }
> +
> + pp->root_bus_nr = -1;
> + pp->ops =&keystone_pcie_host_ops;
> + ret = ks_dw_pcie_host_init(ks_pcie, ks_pcie->msi_intc_np);
> + if (ret) {
> + dev_err(&pdev->dev, "failed to initialize host\n");
> + return ret;
> + }
> +
> + return ret;
> +}
> +
> +static const struct of_device_id ks_pcie_of_match[] = {
> + {
> + .type = "pci",
> + .compatible = "ti,keystone-pcie",
> + },
> + { },
> +};
> +MODULE_DEVICE_TABLE(of, ks_pcie_of_match);
> +
> +static int __exit ks_pcie_remove(struct platform_device *pdev)
> +{
> + struct keystone_pcie *ks_pcie = platform_get_drvdata(pdev);
> +
> + clk_disable_unprepare(ks_pcie->clk);
> +
> + return 0;
> +}
> +
> +static int __init ks_pcie_probe(struct platform_device *pdev)
> +{
> + struct device_node *np = pdev->dev.of_node;
> + struct device *dev =&pdev->dev;
> + struct keystone_pcie *ks_pcie;
> + struct pcie_port *pp;
> + struct resource *res;
> + void __iomem *reg_p;
> + struct phy *phy;
> + int ret = 0;
> + u32 val;
> +
> + ks_pcie = devm_kzalloc(&pdev->dev, sizeof(*ks_pcie),
> + GFP_KERNEL);
> + if (!ks_pcie) {
> + dev_err(dev, "no memory for keystone pcie\n");
> + return -ENOMEM;
> + }
> + pp =&ks_pcie->pp;
> +
> + /* initialize SerDes Phy if present */
> + phy = devm_phy_get(dev, "pcie-phy");
> + if (!IS_ERR_OR_NULL(phy)) {
> + ret = phy_init(phy);
> + if (ret< 0)
> + return ret;
> + }
> +
> + /* index 2 is the devcfg register for RC mode settings */
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
> + reg_p = devm_ioremap_resource(dev, res);
> + if (IS_ERR(reg_p))
> + return PTR_ERR(reg_p);
> +
> + /* enable RC mode in devcfg */
> + val = readl(reg_p);
> + val&= ~PCIE_MODE_MASK;
> + val |= PCIE_RC_MODE;
> + writel(val, reg_p);
> +
> + /* index 3 is to read PCI DEVICE_ID */
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 3);
> + reg_p = devm_ioremap_resource(dev, res);
> + if (IS_ERR(reg_p))
> + return PTR_ERR(reg_p);
> + ks_pcie->va_reg_pciid = reg_p;
> +
> + /* check if we need to enable link training */
> + ks_pcie->link_train =
> + (of_get_property(np, "ti,enable-linktrain", NULL) != NULL);
> +
> + pp->dev = dev;
> + platform_set_drvdata(pdev, ks_pcie);
> + ks_pcie->clk = devm_clk_get(dev, "pcie");
> + if (IS_ERR(ks_pcie->clk)) {
> + dev_err(dev, "Failed to get pcie rc clock\n");
> + return PTR_ERR(ks_pcie->clk);
> + }
> + ret = clk_prepare_enable(ks_pcie->clk);
> + if (ret)
> + return ret;
> +
> + ret = ks_add_pcie_port(ks_pcie, pdev);
> + if (ret< 0)
> + goto fail_clk;
> +
> + return 0;
> +fail_clk:
> + clk_disable_unprepare(ks_pcie->clk);
> +
> + return ret;
> +}
> +
> +static struct platform_driver ks_pcie_driver __refdata = {
> + .probe = ks_pcie_probe,
> + .remove = __exit_p(ks_pcie_remove),
> + .driver = {
> + .name = "keystone-pcie",
> + .owner = THIS_MODULE,
> + .of_match_table = of_match_ptr(ks_pcie_of_match),
> + },
> +};
> +
> +module_platform_driver(ks_pcie_driver);
> +
> +MODULE_AUTHOR("Murali Karicheri<m-karicheri2@ti.com>");
> +MODULE_DESCRIPTION("Keystone PCIe host controller driver");
> +MODULE_LICENSE("GPL v2");
> diff --git a/drivers/pci/host/pci-keystone.h b/drivers/pci/host/pci-keystone.h
> new file mode 100644
> index 0000000..0bedfc5
> --- /dev/null
> +++ b/drivers/pci/host/pci-keystone.h
> @@ -0,0 +1,59 @@
> +/*
> + * Keystone PCI Controller's common includes
> + *
> + * Copyright (C) 2013-2014 Texas Instruments., Ltd.
> + * http://www.ti.com
> + *
> + * Author: Murali Karicheri<m-karicheri2@ti.com>
> + *
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#define MAX_LEGACY_IRQS 4
> +#define MAX_MSI_HOST_IRQS 8
> +#define MAX_LEGACY_HOST_IRQS 4
> +
> +struct keystone_pcie {
> + struct clk *clk;
> + int link_train;
> + struct pcie_port pp;
> + void __iomem *va_reg_pciid;
> +
> + int num_legacy_host_irqs;
> + int legacy_host_irqs[MAX_LEGACY_HOST_IRQS];
> + struct device_node *legacy_intc_np;
> +
> + int num_msi_host_irqs;
> + int msi_host_irqs[MAX_MSI_HOST_IRQS];
> + struct device_node *msi_intc_np;
> + struct irq_domain *legacy_irq_domain;
> +
> + /* Application register space */
> + void __iomem *va_app_base;
> + struct resource app;
> +};
> +
> +/* Keystone DW specific MSI controller APIs/definitions */
> +void ks_dw_pcie_handle_msi_irq(struct keystone_pcie *ks_pcie, int offset);
> +u32 ks_dw_pcie_get_msi_data(struct pcie_port *pp);
> +
> +/* Keystone specific PCI controller APIs */
> +void ks_dw_pcie_enable_legacy_irqs(struct keystone_pcie *ks_pcie);
> +void ks_dw_pcie_handle_legacy_irq(struct keystone_pcie *ks_pcie, int offset);
> +int ks_dw_pcie_host_init(struct keystone_pcie *ks_pcie,
> + struct device_node *msi_intc_np);
> +int ks_dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
> + unsigned int devfn, int where, int size, u32 val);
> +int ks_dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
> + unsigned int devfn, int where, int size, u32 *val);
> +void ks_dw_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie);
> +int ks_dw_pcie_link_up(struct pcie_port *pp);
> +void ks_dw_pcie_initiate_link_train(struct keystone_pcie *ks_pcie);
> +void ks_dw_pcie_msi_set_irq(struct pcie_port *pp, int irq);
> +void ks_dw_pcie_msi_clear_irq(struct pcie_port *pp, int irq);
> +void ks_dw_pcie_v3_65_scan_bus(struct pcie_port *pp);
> +int ks_dw_pcie_msi_host_init(struct pcie_port *pp,
> + struct msi_chip *chip);
Rob,
Could you please review the DT documentation of this patch and ack if
looks good? I have all the Acks needed to merge this series, but DT
maintainers ack is missing
Thanks and regards,
Murali
^ permalink raw reply
* [PATCH 0/3] ARM: mvebu: disable I/O coherency on !SMP
From: Russell King - ARM Linux @ 2014-07-17 15:34 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <10673994.kkICTRHJxL@wuerfel>
On Thu, Jul 17, 2014 at 04:40:21PM +0200, Arnd Bergmann wrote:
> On Thursday 17 July 2014 15:27:20 Will Deacon wrote:
> > Just an FYI, but I've had to check internally to clarify the behaviour
> > around TLB conflict aborts. We're changing live page tables here, but the
> > *only* thing to differ is the output address, which I would hope is ok but
> > need to check to be sure.
>
> The two cases are slightly different:
>
> - The existing keystone code changes the output address but not the flags
> - The hypothetical mvebu code needs to change the flags but not the address.
Don't base too much confidence in the keystone code:
map_start = init_mm.start_code;
map_end = init_mm.brk;
phys = __pa(map_start) & PMD_MASK;
do {
...
phys += PMD_SIZE;
} while (phys < map_end);
Consider what happens when map_end is not PMD aligned - it misses the
PMD covering the end of the kernel BSS, which will be quite a common
case. Obviously something that needs fixing...
--
FTTC broadband for 0.8mile line: currently@9.5Mbps down 400kbps up
according to speedtest.net.
^ permalink raw reply
* [PATCH] irqchip: gic: Fix core ID calculation when topology is read from DT
From: Jason Cooper @ 2014-07-17 15:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1405610624-18722-1-git-send-email-t.figa@samsung.com>
On Thu, Jul 17, 2014 at 05:23:44PM +0200, Tomasz Figa wrote:
> Certain GIC implementation, namely those found on earlier, single
> cluster, Exynos SoCs, have registers mapped without per-CPU banking,
> which means that the driver needs to use different offset for each CPU.
>
> Currently the driver calculates the offset by multiplying value returned
> by cpu_logical_map() by CPU offset parsed from DT. This is correct when
> CPU topology is not specified in DT and aforementioned function returns
> core ID alone. However when DT contains CPU topology, the function
> changes to return cluster ID as well, which is non-zero on mentioned
> SoCs and so breaks the calculation in GIC driver.
>
> This patch fixes this by masking out cluster ID in CPU offset
> calculation so that only core ID is considered. Multi-cluster Exynos
> SoCs already have banked GIC implementations, so this simple fix should
> be enough.
>
> Reported-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> Reported-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> Signed-off-by: Tomasz Figa <t.figa@samsung.com>
> ---
> drivers/irqchip/irq-gic.c | 5 ++++-
> 1 file changed, 4 insertions(+), 1 deletion(-)
iiuc, this was introduced by:
db0d4db22a78d ARM: gic: allow GIC to support non-banked setups
and so should be for v3.3 and up, correct?
thx,
Jason.
^ permalink raw reply
* [PATCH 4/5] tty: serial: 8250 core: add runtime pm
From: Peter Hurley @ 2014-07-17 15:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140716160614.GI1365@saruman.home>
On 07/16/2014 12:06 PM, Felipe Balbi wrote:
> On Wed, Jul 16, 2014 at 05:54:56PM +0200, Sebastian Andrzej Siewior wrote:
>> On 07/16/2014 05:16 PM, Felipe Balbi wrote:
>>> I wonder if you should get_sync() on start_tx() and only
>>> put_autosuspend() at stop_tx(). I guess the outcome would be
>>> largely the same, no ?
>>
>> I just opened minicom on ttyS0 and gave a try. start_tx() was invoked
>> each time I pressed a key (sent a character). I haven't seen stop_tx()
>> even after after I closed minicom. I guess stop_tx() is invoked if you
>> switch half-duplex communication.
>
> that's bad, I expected stop to be called also after each character.
The 8250 core auto-stops tx when the tx ring buffer is empty (except
in the case of dma, where stopping tx isn't necessary).
Regards,
Peter Hurley
^ permalink raw reply
* HYP panic with 3.16-rc5, arm64 + 64k pages
From: Will Deacon @ 2014-07-17 15:28 UTC (permalink / raw)
To: linux-arm-kernel
Hi all,
If I try to spawn a kvm guest with kvmtool (not tried qemu) with a vanilla
3.16-rc5 kernel (same for host and guest) using 64k pages, I'm greeted by:
Kernel panic - not syncing: HYP panic:
PS:800002c5 PC:fffffe000042bd10 ESR:00000000bf000000
FAR: (null) HPFAR: (null) PAR: (null)
VCPU:0000020979e20000
CPU: 0 PID: 0 Comm: swapper/0 Not tainted 3.16.0-rc5 #4
Call trace:
[<fffffe000009642c>] dump_backtrace+0x0/0x130
on the host. The problem happens every time on Juno and the fastmodel.
Any ideas? Is anybody else seeing this problem? The limited guest output
is below.
Will
--->8
Initializing cgroup subsys cpu
Linux version 3.16.0-rc5 (will at edgewater-inn) (gcc version 4.9.0 20140214 (experimental) (aarch64-trunk.530) ) #1 SMP PREEMPT Thu Jul 17 16:19:36 BST 2014
CPU: AArch64 Processor [410fd070] revision 0
Early serial console at I/O port 0x0 (options '')
bootconsole [uart0] enabled
efi: Getting parameters from FDT:
efi: Can't find System Table in device tree!
cma: CMA: failed to reserve 512 MiB
psci: probing for conduit method from DT.
psci: Using PSCI v0.1 Function IDs from DT
PERCPU: Embedded 1 pages/cpu @fffffe0023e80000 s13120 r8192 d44224 u65536
Built 1 zonelists in Zone order, mobility grouping off. Total pages: 9208
Kernel command line: console=hvc0,38400 earlycon=uart8250,0x3f8 root=/dev/root rw rootflags=rw,trans=virtio,version=9p2000.L rootfstype=9p init=/virt/init ip=dhcp
PID hash table entries: 4096 (order: -1, 32768 bytes)
Dentry cache hash table entries: 131072 (order: 4, 1048576 bytes)
Inode-cache hash table entries: 65536 (order: 3, 524288 bytes)
Memory: 579264K/589824K available (4359K kernel code, 455K rwdata, 1536K rodata, 332K init, 280K bss, 10560K reserved)
Virtual kernel memory layout:
vmalloc : 0xfffffc0000000000 - 0xfffffdfbffff0000 (2080767 MB)
vmemmap : 0xfffffdfc001c0000 - 0xfffffdfc0023e000 ( 0 MB)
modules : 0xfffffdfffc000000 - 0xfffffe0000000000 ( 64 MB)
memory : 0xfffffe0000000000 - 0xfffffe0024000000 ( 576 MB)
.init : 0xfffffe0000660000 - 0xfffffe00006b3340 ( 333 kB)
.text : 0xfffffe0000080000 - 0xfffffe0000651f94 ( 5960 kB)
.data : 0xfffffe00006c0000 - 0xfffffe0000731ca8 ( 456 kB)
SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=4, Nodes=1
Preemptible hierarchical RCU implementation.
RCU restricting CPUs from NR_CPUS=8 to nr_cpu_ids=4.
RCU: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=4
NR_IRQS:64 nr_irqs:64 0
< next line is usually architected timer initialisation >
^ permalink raw reply
* [PATCH 02/16] i2c: i2c-at91: Drop class based scanning to improve bootup time
From: Ludovic Desroches @ 2014-07-17 15:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1404992799-3705-3-git-send-email-wsa@the-dreams.de>
On Thu, Jul 10, 2014 at 01:46:22PM +0200, Wolfram Sang wrote:
> This driver has been flagged to drop class based instantiation. The removal
> improves boot-up time and is unneeded for embedded controllers. Users have been
> warned to switch for some time now, so we can actually do the removal. Keep the
> DEPRECATED flag, so the core can inform users that the behaviour finally
> changed now. After another transition period, this flag can go, too.
>
> Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
Acked-by: Ludovic Desroches <ludovic.desroches@atmel.com>
Thanks
> ---
> drivers/i2c/busses/i2c-at91.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c
> index e95f9ba96790..7033e9166d1f 100644
> --- a/drivers/i2c/busses/i2c-at91.c
> +++ b/drivers/i2c/busses/i2c-at91.c
> @@ -768,7 +768,7 @@ static int at91_twi_probe(struct platform_device *pdev)
> snprintf(dev->adapter.name, sizeof(dev->adapter.name), "AT91");
> i2c_set_adapdata(&dev->adapter, dev);
> dev->adapter.owner = THIS_MODULE;
> - dev->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_DEPRECATED;
> + dev->adapter.class = I2C_CLASS_DEPRECATED;
> dev->adapter.algo = &at91_twi_algorithm;
> dev->adapter.dev.parent = dev->dev;
> dev->adapter.nr = pdev->id;
> --
> 2.0.0
>
^ permalink raw reply
* [RFC] PCI: pci-imx6: Add delay to workaround kernel hang
From: Shawn Guo @ 2014-07-17 15:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <201407171023.10908.marex@denx.de>
On Thu, Jul 17, 2014 at 10:23:10AM +0200, Marek Vasut wrote:
> On Thursday, July 17, 2014 at 08:51:48 AM, Uwe Kleine-K?nig wrote:
> > Hello,
> >
> > On Tue, Jun 24, 2014 at 04:18:27PM -0300, Fabio Estevam wrote:
> > > From: Fabio Estevam <fabio.estevam@freescale.com>
> > >
> > > When the mx6 PCI conctroller is initialized in the bootloader we see a
> > > kernel hang inside imx6_add_pcie_port().
> > >
> > > Adding a 30ms delay allows the kernel to boot.
> >
> > Just my thought on how to debug that: I'd try to bisect the pci init
> > routine in the boot loader. I.e. first only do the first half of the
> > initialisation in U-Boot. Depending on Linux being able to boot or not
> > initialize more or less on the next run.
> >
> > Maybe there is a single register write that makes Linux fail?!
>
> I am still hell-bent on thinking that the missing PCIe block reset is what makes
> the Linux fail. Missing block reset is always a problem.
Indeed. We're missing a hardware reset for PCIe on i.MX6Q and i.MX6DL.
Such reset is available on i.MX6SX, so there is no this problem for
i.MX6SX PCIe.
> Or do we now have a
> mean to reset the PCIe block and it's PHY from software?
Richard is trying to find a SW workaround for it, but we're not really
sure if it's possible.
Shawn
^ permalink raw reply
* [PATCH] irqchip: gic: Fix core ID calculation when topology is read from DT
From: Tomasz Figa @ 2014-07-17 15:23 UTC (permalink / raw)
To: linux-arm-kernel
Certain GIC implementation, namely those found on earlier, single
cluster, Exynos SoCs, have registers mapped without per-CPU banking,
which means that the driver needs to use different offset for each CPU.
Currently the driver calculates the offset by multiplying value returned
by cpu_logical_map() by CPU offset parsed from DT. This is correct when
CPU topology is not specified in DT and aforementioned function returns
core ID alone. However when DT contains CPU topology, the function
changes to return cluster ID as well, which is non-zero on mentioned
SoCs and so breaks the calculation in GIC driver.
This patch fixes this by masking out cluster ID in CPU offset
calculation so that only core ID is considered. Multi-cluster Exynos
SoCs already have banked GIC implementations, so this simple fix should
be enough.
Reported-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Reported-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Tomasz Figa <t.figa@samsung.com>
---
drivers/irqchip/irq-gic.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index ddee133..5c15a09 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -40,6 +40,7 @@
#include <linux/irqchip/chained_irq.h>
#include <linux/irqchip/arm-gic.h>
+#include <asm/cputype.h>
#include <asm/irq.h>
#include <asm/exception.h>
#include <asm/smp_plat.h>
@@ -901,7 +902,9 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
}
for_each_possible_cpu(cpu) {
- unsigned long offset = percpu_offset * cpu_logical_map(cpu);
+ u32 mpidr = cpu_logical_map(cpu);
+ u32 core_id = MPIDR_AFFINITY_LEVEL(mpidr, 0);
+ unsigned long offset = percpu_offset * core_id;
*per_cpu_ptr(gic->dist_base.percpu_base, cpu) = dist_base + offset;
*per_cpu_ptr(gic->cpu_base.percpu_base, cpu) = cpu_base + offset;
}
--
1.9.3
^ permalink raw reply related
* [PATCH 5/5] tty: serial: Add 8250-core based omap driver
From: Sebastian Andrzej Siewior @ 2014-07-17 15:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140717145430.GF10459@saruman.home>
On 07/17/2014 04:54 PM, Felipe Balbi wrote:
> Hi,
>
> On Wed, Jul 16, 2014 at 04:45:03PM +0200, Sebastian Andrzej Siewior wrote:
>> +static int omap_8250_startup(struct uart_port *port)
>> +{
>> + struct uart_8250_port *up =
>> + container_of(port, struct uart_8250_port, port);
>> + struct omap8250_priv *priv = port->private_data;
>> +
>> + int ret;
>> +
>> + if (priv->wakeirq) {
>> + ret = request_irq(priv->wakeirq, omap_wake_irq,
>> + port->irqflags, "wakeup irq", port);
>> + if (ret)
>> + return ret;
>> + disable_irq(priv->wakeirq);
>> + }
>> +
>> + ret = serial8250_do_startup(port);
>> + if (ret)
>> + goto err;
>> +
>> + pm_runtime_get_sync(port->dev);
>
> should this pm_runtime_get_sync() be placed above
> serial8250_do_startup() call ?
I don't think it matters since serial8250_do_startup() has its own
pm_runtime_get_sync().
->startup(), ->shutdown() are called via omap callbacks so we could
spare in the 8250-core if we do it in the omap code before invoking the
function. The same goes for serial8250_set_termios() which is not used
by omap but has those runtime-pm stuff, too.
It would be wrong if someone would use the serial8250_do_startup()
without his own runtime-pm get but it is omap only which does this
things.
So it is not used by anyone else (right now) and if you want to keep it
to a minimum I could remove them from those places.
Sebastian
^ permalink raw reply
* [PATCH v5 3/5] PCI: designware: enhance dw_pcie_host_init() to support v3.65 DW hardware
From: Murali Karicheri @ 2014-07-17 15:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <2CC2A0A4A178534D93D5159BF3BCB661A47A2A83BB@EAPEX1MAIL1.st.com>
On 07/17/2014 12:18 AM, Mohit KUMAR DCG wrote:
>
>
>> -----Original Message-----
>> From: Pratyush ANAND
>> Sent: Thursday, July 17, 2014 9:07 AM
>> To: Murali Karicheri
>> Cc: linux-pci at vger.kernel.org; linux-kernel at vger.kernel.org; linux-arm-
>> kernel at lists.infradead.org; Santosh Shilimkar; Russell King; Grant Likely; Rob
>> Herring; Mohit KUMAR DCG; Jingoo Han; Bjorn Helgaas; Richard Zhu; Kishon
>> Vijay Abraham I; Marek Vasut; Arnd Bergmann; Pawel Moll; Mark Rutland;
>> Ian Campbell; Kumar Gala; Randy Dunlap
>> Subject: Re: [PATCH v5 3/5] PCI: designware: enhance dw_pcie_host_init()
>> to support v3.65 DW hardware
>>
>> On Thu, Jul 17, 2014 at 12:38:04AM +0800, Murali Karicheri wrote:
>>> keystone PCI controller is based on v3.65 designware hardware. This
>>> version differs from newer versions of the hardware in few functional
>>> areas discussed below that makes it necessary to change
>>> dw_pcie_host_init() to support v3.65 based PCI controller.
>>>
>>> 1. No support for ATU port. So any ATU specific resource handling code
>>> is to be bypassed for v3.65 h/w.
>>> 2. MSI controller uses Application space to implement MSI and 32 MSI
>>> interrupts are multiplexed over 8 IRQs to the host. Hence the code
>>> to process MSI IRQ needs to be different. This patch allows platform
>>> driver to provide its own irq_domain_ops ptr to irq_domain_add_linear()
>>> through an API callback from the designware core driver.
>>> 3. MSI interrupt generation requires EP to write to the RC's application
>>> register. So enhance the driver to allow setup of inbound access to
>>> MSI irq register as a post scan bus API callback.
>>>
>>> Signed-off-by: Murali Karicheri<m-karicheri2@ti.com>
>>
>> Looks almost ok to me.
>>
>> Reviewed-by: Pratyush Anand<pratyush.anand@st.com>
>>
>
> - Now looks fine to me.
>
> Acked-by: Mohit KUMAR<mohit.kumar@st.com>
>
> Jingoo,
> After Murali's patches, dw code can be used by older Synopsys controller based driver too.
> Pls have a look at the series if you have any further comment.
>
> Thanks
> Mohit
Mohit,
Thanks for the review and Ack.
Murali
>
>>> int __init dw_pcie_host_init(struct pcie_port *pp) {
>>> struct device_node *np = pp->dev->of_node;
>>> - struct of_pci_range range;
>>> struct of_pci_range_parser parser;
>>> + struct of_pci_range range;
>>
>> You may avoid moving the above line.
>>
>> ~Pratyush
^ permalink raw reply
* [PATCH v2 1/5] i2c: Don't start transfers when suspended
From: Wolfram Sang @ 2014-07-17 15:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CABYn4swJ5NHyUd5+zCK6jhHex4v9DCMe5Qo-BZqxjPf90JfusQ@mail.gmail.com>
On Thu, Jul 17, 2014 at 04:58:17PM +0200, Bastian Hecht wrote:
> I want to add the remark that I can't help further on the patch series
> in the next month about. So this is free to be taken/ignored/modified
> without any approval by my side.
Good to know. I'd like to get some Tested-by tags before applying to
make sure we have no regressions. So, with you being away, let's just
schedule this for 3.18 and we have all the time we need. Thanks for
finishing this code before you left. Have a great month!
Wolfram
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140717/d4afdd25/attachment.sig>
^ permalink raw reply
* [PATCH 7/8] mailbox: f_mhu: add driver for Fujitsu MHU controller
From: Sudeep Holla @ 2014-07-17 15:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAJe_ZhegVczzcRVikt=nWnwU3nGx2G2mNg9nGR3bF4FfHnPeEg@mail.gmail.com>
On 17/07/14 13:56, Jassi Brar wrote:
> On 17 July 2014 16:01, Sudeep Holla <sudeep.holla@arm.com> wrote:
>> On 17/07/14 07:25, Jassi Brar wrote:
>>>
>>>>
>>>>> + u32 val;
>>>>> +
>>>>> + pr_debug("%s:%d\n", __func__, __LINE__);
>>>>
>>>>
>>>>
>>>> Please remove all these debug prints.
>>>>
>>> These are as good as absent unless DEBUG is defined.
>>>
>>
>> Yes, but with mailbox framework, the controller driver(esp. this one)is
>> almost like a shim layer. Instead of each driver adding these debugs,
>> IMO it would be good to have these in the framework.
>>
> OK
>
>>>>
>>>>> + /* See NOTE_RX_DONE */
>>>>> + val = readl_relaxed(mlink->rx_reg + INTR_STAT_OFS);
>>>>> + mbox_chan_received_data(chan, (void *)val);
>>>>> +
>>>>> + /*
>>>>> + * It is agreed with the remote firmware that the receiver
>>>>> + * will clear the STAT register indicating it is ready to
>>>>> + * receive next data - NOTE_RX_DONE
>>>>> + */
>>>>
>>>>
>>>> This note could be added as how this mailbox works in general and
>>>> it's not just Rx right ? Even Tx done is based on this logic.
>>>> Basically the logic is valid on both directions.
>>>>
>>> Yes that is a protocol level agreement. Different f/w may behave
>>> differently.
>>>
>>
>> Ok, I am not sure if that's entirely true because the MHU spec says it
>> drives
>> the signal using a 32-bit register, with all 32 bits logically ORed
>> together.
>> Usually only Rx signals are wired to interrupts and Tx needs to be polled
>> but that's entirely implementation choice I believe.
>>
> On my platform, _STAT register only carries the command code but
> actual data is exchanged via SharedMemory/SHM. Now we need to know
> when the sent data packet (in SHM) has been consumed by the remote -
> for which our protocol mandates the remote clear the TX_STAT register.
> And vice-versa for RX.
>
> Some other f/w may choose some other mechanism for TX-Done - say some
> ACK bit set or even some time bound guarantee.
>
>> More over if it's protocol level agreement it should not belong here :)
>>
> My f/w expects the RX_STAT cleared after reading data from SHM. Where
> do you think is the right place to clear RX_STAT?
>
I understand that and what I am saying is the MHU is designed like that
and protocol is just using it. There's nothing specific to protocol. Ideally
if an implementation has both Rx and Tx interrupts, the RX_CLEAR from here
raises an interrupt to the firmware. In absence of it we need polling that's
what both Linux and firmware does for Tx case.
Even on Juno, it's same. But we should be able to extend it to support Tx
if an implementation supports. Similarly the firmware can make use of the
same when Linux clears Rx(it would be Tx complete/ack for the firmware)
When we need to make this driver work across different firmware, you just
can't rely on the firmware protocol, hence I am asking to drop those
comments.
> I have said many times in many threads... its the mailbox controller
> _and_ the remote f/w that should be seen as one entity. It may not be
> possible to write a controller driver that works with any remote
> firmware.
>
It should be possible if the remote protocol just use the same hardware
feature without any extra software policy at the lowest level(raw Tx and
Rx). I believe that's what we need here if we want this driver to work
on both Juno and your platform. Agree ?
>>
>>>>> +static int mhu_startup(struct mbox_chan *chan)
>>>>> +{
>>>>> + struct mhu_link *mlink = (struct mhu_link *)chan->con_priv;
>>>>> + unsigned long flags;
>>>>> + u32 val;
>>>>> + int ret;
>>>>> +
>>>>> + pr_debug("%s:%d\n", __func__, __LINE__);
>>>>> + spin_lock_irqsave(&mlink->lock, flags);
>>>>> + val = readl_relaxed(mlink->tx_reg + INTR_STAT_OFS);
>>>>> + writel_relaxed(val, mlink->tx_reg + INTR_CLR_OFS);
>>>>> + spin_unlock_irqrestore(&mlink->lock, flags);
>>>>> +
>>>>> + ret = request_irq(mlink->irq, mhu_rx_interrupt,
>>>>> + IRQF_SHARED, "mhu_link", chan);
>>>>
>>>>
>>>>
>>>> Just a thought: Can this be threaded_irq instead ?
>>>> Can move request_irq to probe instead esp. if threaded_irq ?
>>>> That provides some flexibility to client's rx_callback.
>>>>
>>> This is controller driver, and can not know which client want
>>> rx_callback in hard-irq context and which in thread_fn context.
>>> Otherwise, request_irq() does evaluate to request_threaded_irq(), if
>>> thats what you mean.
>>
>> Agreed but on contrary since MHU involves external firmware(running
>> on different processor) which might have it's own latency, I prefer
>> threaded over hard irq. And yes request_irq does evaluate to
>> request_threaded_irq but with thread_fn = NULL which is not what I want.
>>
> If remote has its own latency, that does not mean we add some more :)
>
No what I meant is unless there is a real need to use hard irq, we
should prefer threaded one otherwise. Also by latency I meant what if
the remote firmware misbehaves. In threaded version you have little
more flexibility whereas hard irq is executed with interrupts disabled.
At least the system is responsive and only MHU interrupts are disabled.
Regards,
Sudeep
^ permalink raw reply
* [PATCH] arm: clk-imx6q: parent lvds_sel input from upstream clock gates
From: Shawn Guo @ 2014-07-17 15:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1405592414-19550-1-git-send-email-l.stach@pengutronix.de>
On Thu, Jul 17, 2014 at 12:20:14PM +0200, Lucas Stach wrote:
> The i.MX6 reference manual doesn't make a clear distinction
> between the fixed clock divider and the enable gate for the
> pcie and sata reference clocks. This lead to the lvds mux
> inputs in the imx6q clk driver to be parented from the
> ref clock (which is the divider) instead of the actual gate,
> which in turn prevents the upstream clock to actually be
> enabled when lvds clk out is active.
>
> This fixes a hard machine hang regression in kernel 3.16 for
> boards where only pcie is active but no sata, as with this
> kernel version the imx6-pcie driver is no longer enabling
> the upstream clock directly but only lvds clk out.
>
> Reported-by: Arne Ruhnau <arne.ruhnau@target-sg.com>
> Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
> Tested-by: Arne Ruhnau <arne.ruhnau@target-sg.com>
> ---
> Shawn, this is an urgent fix for 3.16. Can you please
> Ack it so arm-soc people can take this directly?
> ---
Acked-by: Shawn Guo <shawn.guo@freescale.com>
It will conflict with the patch switching to use macro for clock IDs,
which I'm about to send for 3.17, though.
Shawn
^ permalink raw reply
* [PATCH v11 11/11] seccomp: implement SECCOMP_FILTER_FLAG_TSYNC
From: David Drysdale @ 2014-07-17 15:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1405547442-26641-12-git-send-email-keescook@chromium.org>
On Wed, Jul 16, 2014 at 10:50 PM, Kees Cook <keescook@chromium.org> wrote:
> diff --git a/kernel/seccomp.c b/kernel/seccomp.c
> index 9065d2c79c56..2125b83ccfd4 100644
> +/**
> + * seccomp_can_sync_threads: checks if all threads can be synchronized
> + *
> + * Expects sighand and cred_guard_mutex locks to be held.
> + *
> + * Returns 0 on success, -ve on error, or the pid of a thread which was
> + * either not in the correct seccomp mode or it did not have an ancestral
> + * seccomp filter.
> + */
> +static inline pid_t seccomp_can_sync_threads(void)
> +{
> + struct task_struct *thread, *caller;
> +
> + BUG_ON(!mutex_is_locked(¤t->signal->cred_guard_mutex));
> + BUG_ON(!spin_is_locked(¤t->sighand->siglock));
> +
> + if (current->seccomp.mode != SECCOMP_MODE_FILTER)
> + return -EACCES;
Quick question -- is it possible to apply the first filter and also synchronize
it across threads in the same operation? If so, does this arm also need to
cope with seccomp.mode being SECCOMP_MODE_DISABLED?
[seccomp_set_mode_filter() looks to call this via seccomp_attach_filter()
before it does seccomp_assign_mode()]
> +
> + /* Validate all threads being eligible for synchronization. */
> + caller = current;
> + for_each_thread(caller, thread) {
> + pid_t failed;
> +
> + if (thread->seccomp.mode == SECCOMP_MODE_DISABLED ||
> + (thread->seccomp.mode == SECCOMP_MODE_FILTER &&
> + is_ancestor(thread->seccomp.filter,
> + caller->seccomp.filter)))
> + continue;
> +
> + /* Return the first thread that cannot be synchronized. */
> + failed = task_pid_vnr(thread);
> + /* If the pid cannot be resolved, then return -ESRCH */
> + if (unlikely(WARN_ON(failed == 0)))
> + failed = -ESRCH;
> + return failed;
> + }
> +
> + return 0;
> +}
^ permalink raw reply
* [PATCH v5 3/5] PCI: designware: enhance dw_pcie_host_init() to support v3.65 DW hardware
From: Murali Karicheri @ 2014-07-17 15:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140717033638.GI12278@pratyush-vbox>
On 07/16/2014 11:36 PM, Pratyush Anand wrote:
> On Thu, Jul 17, 2014 at 12:38:04AM +0800, Murali Karicheri wrote:
>> keystone PCI controller is based on v3.65 designware hardware. This
>> version differs from newer versions of the hardware in few functional
>> areas discussed below that makes it necessary to change dw_pcie_host_init()
>> to support v3.65 based PCI controller.
>>
>> 1. No support for ATU port. So any ATU specific resource handling code
>> is to be bypassed for v3.65 h/w.
>> 2. MSI controller uses Application space to implement MSI and 32 MSI
>> interrupts are multiplexed over 8 IRQs to the host. Hence the code
>> to process MSI IRQ needs to be different. This patch allows platform
>> driver to provide its own irq_domain_ops ptr to irq_domain_add_linear()
>> through an API callback from the designware core driver.
>> 3. MSI interrupt generation requires EP to write to the RC's application
>> register. So enhance the driver to allow setup of inbound access to
>> MSI irq register as a post scan bus API callback.
>>
>> Signed-off-by: Murali Karicheri<m-karicheri2@ti.com>
> Looks almost ok to me.
>
> Reviewed-by: Pratyush Anand<pratyush.anand@st.com>
>
>> int __init dw_pcie_host_init(struct pcie_port *pp)
>> {
>> struct device_node *np = pp->dev->of_node;
>> - struct of_pci_range range;
>> struct of_pci_range_parser parser;
>> + struct of_pci_range range;
> You may avoid moving the above line.
Thought the variables are to be sorted. I can fix this when I resend it
today with your reviewed by and Mohit's Ack.
Regards,
Murali
> ~Pratyush
^ permalink raw reply
* [PATCH v7 07/11] arm64: mm: Implement 4 levels of translation tables
From: Jungseok Lee @ 2014-07-17 15:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <2211E520-32A4-435C-9F63-A7EFEE8B677A@gmail.com>
On Wed, 16 Jul 2014 20:09:48 +0100, Catalin Marinas wrote:
[ ... ]
> diff --git a/arch/arm64/mm/ioremap.c b/arch/arm64/mm/ioremap.c
> index 69000efa015e..fa324bd5a5c4 100644
> --- a/arch/arm64/mm/ioremap.c
> +++ b/arch/arm64/mm/ioremap.c
> @@ -104,9 +104,12 @@ void __iomem *ioremap_cache(phys_addr_t phys_addr, size_t size)
> EXPORT_SYMBOL(ioremap_cache);
>
> static pte_t bm_pte[PTRS_PER_PTE] __page_aligned_bss;
> -#ifndef CONFIG_ARM64_64K_PAGES
> +#if CONFIG_ARM64_PGTABLE_LEVELS > 2
In this patch frame, it causes a compile error since [08/11] patch introduces
CONFIG_ARM64_PGTABLE_LEVELS. Please ignore my comment if it does not matter.
> static pte_t bm_pmd[PTRS_PER_PMD] __page_aligned_bss;
> #endif
> +#if CONFIG_ARM64_PGTABLE_LEVELS > 3
Ditto
- Jungseok Lee
^ permalink raw reply
* [PATCH] arm64: audit: Fix build for audit changes
From: Mark Brown @ 2014-07-17 15:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140717145838.GJ18203@arm.com>
On Thu, Jul 17, 2014 at 03:58:38PM +0100, Catalin Marinas wrote:
> On Thu, Jul 17, 2014 at 03:50:02PM +0100, Mark Brown wrote:
> > What would be better would be if we could get the two trees synced up,
> > in this case something like picking the audit change up in the ARMv8
> > tree (or vice versa) seems like it'd be quick and easy since it looks
> > like neither tree uses topic branches.
> It's not ideal indeed but applying this patch on my tree would break it.
> So we need a common base where the audit API is changed, guaranteed not
> to be rebased so that I can merge it in the arm64 for-next/core branch.
> Do you know which tree commit 3efe33f5d2 is in? I assume some tip
> branch?
It's the head commit in Eric's audit tree.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140717/97456dab/attachment-0001.sig>
^ permalink raw reply
* [PATCH v2 5/5] i2c: tegra: Remove suspension check
From: Thierry Reding @ 2014-07-17 14:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1405608520-5644-5-git-send-email-hechtb@gmail.com>
On Thu, Jul 17, 2014 at 04:48:40PM +0200, Bastian Hecht wrote:
[...]
> #ifdef CONFIG_PM_SLEEP
> -static int tegra_i2c_suspend(struct device *dev)
> -{
> - struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev);
> -
> - i2c_lock_adapter(&i2c_dev->adapter);
> - i2c_dev->is_suspended = true;
> - i2c_unlock_adapter(&i2c_dev->adapter);
> -
> - return 0;
> -}
> -
> static int tegra_i2c_resume(struct device *dev)
> {
> struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev);
> @@ -842,14 +827,12 @@ static int tegra_i2c_resume(struct device *dev)
> return ret;
> }
>
> - i2c_dev->is_suspended = false;
> -
> i2c_unlock_adapter(&i2c_dev->adapter);
>
> return 0;
> }
>
> -static SIMPLE_DEV_PM_OPS(tegra_i2c_pm, tegra_i2c_suspend, tegra_i2c_resume);
> +static SIMPLE_DEV_PM_OPS(tegra_i2c_pm, tegra_i2c_resume);
Shouldn't this be:
static SIMPLE_DEV_OPS(tegra_i2c_pm, NULL, tegra_i2c_resume);
instead?
Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140717/0c2d9e59/attachment.sig>
^ permalink raw reply
* [PATCH 1/3] ARM: dts: keystone: add mdio devices entries
From: Grygorii Strashko @ 2014-07-17 14:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1405609087-9128-1-git-send-email-grygorii.strashko@ti.com>
Hi Santosh,
On 07/17/2014 05:58 PM, Grygorii Strashko wrote:
> The Keystone 2 has MDIO HW block which are compatible
> to Davinci SoCs:
> See "Gigabit Ethernet (GbE) Switch Subsystem"
> See http://www.ti.com/lit/ug/sprugv9d/sprugv9d.pdf
>
> Hence, add corresponding DT entry for Keystone 2.
This is updated version of patch (missed v2 in subj).
>
> Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
> ---
> arch/arm/boot/dts/keystone.dtsi | 11 +++++++++++
> 1 file changed, 11 insertions(+)
>
> diff --git a/arch/arm/boot/dts/keystone.dtsi b/arch/arm/boot/dts/keystone.dtsi
> index c1414cb..9e31fe7 100644
> --- a/arch/arm/boot/dts/keystone.dtsi
> +++ b/arch/arm/boot/dts/keystone.dtsi
> @@ -266,5 +266,16 @@
> ranges = <0 0 0x30000000 0x10000000
> 1 0 0x21000A00 0x00000100>;
> };
> +
> + mdio: mdio at 02090300 {
> + compatible = "ti,keystone_mdio", "ti,davinci_mdio";
> + #address-cells = <1>;
> + #size-cells = <0>;
> + reg = <0x02090300 0x100>;
> + status = "disabled";
> + clocks = <&clkpa>;
> + clock-names = "fck";
> + bus_freq = <2500000>;
> + };
> };
> };
>
^ permalink raw reply
* [PATCH] arm64: audit: Fix build for audit changes
From: Catalin Marinas @ 2014-07-17 14:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140717145002.GW17528@sirena.org.uk>
On Thu, Jul 17, 2014 at 03:50:02PM +0100, Mark Brown wrote:
> On Thu, Jul 17, 2014 at 12:59:38PM +0100, Catalin Marinas wrote:
> > On Thu, Jul 17, 2014 at 12:26:42PM +0100, Mark Brown wrote:
>
> > > Commit 3efe33f5d2 (audit: x86: drop arch from __audit_syscall_entry()
> > > interface) removed the arch parameter from __audit_syscall_entry() and
>
> > Thanks. This will have to be applied after 3.17-rc1 since commit
> > 3efe33f5d2 does not seem to be in mainline yet (nor the arm64 audit
> > patches).
>
> That's not great and is kind of missing the point of -next - the core
> idea is to find these inter-tree dependencies, ensure things work when
> they're merged together and avoid things like massive bisection breaks.
> Leaving things also causes problems for anyone trying to do integration
> testing on -next.
>
> What would be better would be if we could get the two trees synced up,
> in this case something like picking the audit change up in the ARMv8
> tree (or vice versa) seems like it'd be quick and easy since it looks
> like neither tree uses topic branches.
It's not ideal indeed but applying this patch on my tree would break it.
So we need a common base where the audit API is changed, guaranteed not
to be rebased so that I can merge it in the arm64 for-next/core branch.
Do you know which tree commit 3efe33f5d2 is in? I assume some tip
branch?
--
Catalin
^ permalink raw reply
* [PATCH v2 1/5] i2c: Don't start transfers when suspended
From: Bastian Hecht @ 2014-07-17 14:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1405608520-5644-1-git-send-email-hechtb@gmail.com>
I want to add the remark that I can't help further on the patch series
in the next month about. So this is free to be taken/ignored/modified
without any approval by my side.
Have fun coding,
Bastian
2014-07-17 16:48 GMT+02:00 Bastian Hecht <hechtb@gmail.com>:
> i2c transfer requests come in very uncontrolled, like from interrupt routines.
> We might be suspended when this happens. To avoid i2c timeouts caused by
> powered down busses we check for suspension.
>
> Several bus drivers handle this problem on their own. We can clean things up
> by moving the protection mechanism into the core.
>
> Signed-off-by: Bastian Hecht <hechtb@gmail.com>
> ---
> changelog v2:
>
> - commit message extended.
> - initialization added for adap->suspended
> - swapped branch for increased performance
>
>
> drivers/i2c/i2c-core.c | 25 ++++++++++++++++++++++++-
> include/linux/i2c.h | 1 +
> 2 files changed, 25 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
> index 7c7f4b8..b15dc20 100644
> --- a/drivers/i2c/i2c-core.c
> +++ b/drivers/i2c/i2c-core.c
> @@ -343,6 +343,13 @@ static int i2c_legacy_resume(struct device *dev)
> static int i2c_device_pm_suspend(struct device *dev)
> {
> const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
> + struct i2c_adapter *adap = i2c_verify_adapter(dev);
> +
> + if (adap) {
> + i2c_lock_adapter(adap);
> + adap->suspended = true;
> + i2c_unlock_adapter(adap);
> + }
>
> if (pm)
> return pm_generic_suspend(dev);
> @@ -353,6 +360,13 @@ static int i2c_device_pm_suspend(struct device *dev)
> static int i2c_device_pm_resume(struct device *dev)
> {
> const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
> + struct i2c_adapter *adap = i2c_verify_adapter(dev);
> +
> + if (adap) {
> + i2c_lock_adapter(adap);
> + adap->suspended = false;
> + i2c_unlock_adapter(adap);
> + }
>
> if (pm)
> return pm_generic_resume(dev);
> @@ -1243,6 +1257,7 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
> dev_set_name(&adap->dev, "i2c-%d", adap->nr);
> adap->dev.bus = &i2c_bus_type;
> adap->dev.type = &i2c_adapter_type;
> + adap->suspended = false;
> res = device_register(&adap->dev);
> if (res)
> goto out_list;
> @@ -1819,7 +1834,10 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
> i2c_lock_adapter(adap);
> }
>
> - ret = __i2c_transfer(adap, msgs, num);
> + if (!adap->suspended)
> + ret = __i2c_transfer(adap, msgs, num);
> + else
> + ret = -EIO;
> i2c_unlock_adapter(adap);
>
> return ret;
> @@ -2577,6 +2595,10 @@ s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags,
>
> if (adapter->algo->smbus_xfer) {
> i2c_lock_adapter(adapter);
> + if (adapter->suspended) {
> + res = -EIO;
> + goto unlock;
> + }
>
> /* Retry automatically on arbitration loss */
> orig_jiffies = jiffies;
> @@ -2590,6 +2612,7 @@ s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags,
> orig_jiffies + adapter->timeout))
> break;
> }
> +unlock:
> i2c_unlock_adapter(adapter);
>
> if (res != -EOPNOTSUPP || !adapter->algo->master_xfer)
> diff --git a/include/linux/i2c.h b/include/linux/i2c.h
> index b556e0a..af08c75 100644
> --- a/include/linux/i2c.h
> +++ b/include/linux/i2c.h
> @@ -434,6 +434,7 @@ struct i2c_adapter {
> int timeout; /* in jiffies */
> int retries;
> struct device dev; /* the adapter device */
> + unsigned int suspended:1;
>
> int nr;
> char name[48];
> --
> 1.9.1
>
^ permalink raw reply
* [PATCH 1/3] ARM: dts: keystone: add mdio devices entries
From: Grygorii Strashko @ 2014-07-17 14:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1404911660-10047-2-git-send-email-grygorii.strashko@ti.com>
The Keystone 2 has MDIO HW block which are compatible
to Davinci SoCs:
See "Gigabit Ethernet (GbE) Switch Subsystem"
See http://www.ti.com/lit/ug/sprugv9d/sprugv9d.pdf
Hence, add corresponding DT entry for Keystone 2.
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
---
arch/arm/boot/dts/keystone.dtsi | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/arch/arm/boot/dts/keystone.dtsi b/arch/arm/boot/dts/keystone.dtsi
index c1414cb..9e31fe7 100644
--- a/arch/arm/boot/dts/keystone.dtsi
+++ b/arch/arm/boot/dts/keystone.dtsi
@@ -266,5 +266,16 @@
ranges = <0 0 0x30000000 0x10000000
1 0 0x21000A00 0x00000100>;
};
+
+ mdio: mdio at 02090300 {
+ compatible = "ti,keystone_mdio", "ti,davinci_mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x02090300 0x100>;
+ status = "disabled";
+ clocks = <&clkpa>;
+ clock-names = "fck";
+ bus_freq = <2500000>;
+ };
};
};
--
1.7.9.5
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox