linux/drivers/pci/controller/pcie-rcar.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * PCIe driver for Renesas R-Car SoCs
   4 *  Copyright (C) 2014-2020 Renesas Electronics Europe Ltd
   5 *
   6 * Author: Phil Edworthy <phil.edworthy@renesas.com>
   7 */
   8
   9#include <linux/delay.h>
  10#include <linux/pci.h>
  11
  12#include "pcie-rcar.h"
  13
  14void rcar_pci_write_reg(struct rcar_pcie *pcie, u32 val, unsigned int reg)
  15{
  16        writel(val, pcie->base + reg);
  17}
  18
  19u32 rcar_pci_read_reg(struct rcar_pcie *pcie, unsigned int reg)
  20{
  21        return readl(pcie->base + reg);
  22}
  23
  24void rcar_rmw32(struct rcar_pcie *pcie, int where, u32 mask, u32 data)
  25{
  26        unsigned int shift = BITS_PER_BYTE * (where & 3);
  27        u32 val = rcar_pci_read_reg(pcie, where & ~3);
  28
  29        val &= ~(mask << shift);
  30        val |= data << shift;
  31        rcar_pci_write_reg(pcie, val, where & ~3);
  32}
  33
  34int rcar_pcie_wait_for_phyrdy(struct rcar_pcie *pcie)
  35{
  36        unsigned int timeout = 10;
  37
  38        while (timeout--) {
  39                if (rcar_pci_read_reg(pcie, PCIEPHYSR) & PHYRDY)
  40                        return 0;
  41
  42                msleep(5);
  43        }
  44
  45        return -ETIMEDOUT;
  46}
  47
  48int rcar_pcie_wait_for_dl(struct rcar_pcie *pcie)
  49{
  50        unsigned int timeout = 10000;
  51
  52        while (timeout--) {
  53                if ((rcar_pci_read_reg(pcie, PCIETSTR) & DATA_LINK_ACTIVE))
  54                        return 0;
  55
  56                udelay(5);
  57                cpu_relax();
  58        }
  59
  60        return -ETIMEDOUT;
  61}
  62
  63void rcar_pcie_set_outbound(struct rcar_pcie *pcie, int win,
  64                            struct resource_entry *window)
  65{
  66        /* Setup PCIe address space mappings for each resource */
  67        struct resource *res = window->res;
  68        resource_size_t res_start;
  69        resource_size_t size;
  70        u32 mask;
  71
  72        rcar_pci_write_reg(pcie, 0x00000000, PCIEPTCTLR(win));
  73
  74        /*
  75         * The PAMR mask is calculated in units of 128Bytes, which
  76         * keeps things pretty simple.
  77         */
  78        size = resource_size(res);
  79        if (size > 128)
  80                mask = (roundup_pow_of_two(size) / SZ_128) - 1;
  81        else
  82                mask = 0x0;
  83        rcar_pci_write_reg(pcie, mask << 7, PCIEPAMR(win));
  84
  85        if (res->flags & IORESOURCE_IO)
  86                res_start = pci_pio_to_address(res->start) - window->offset;
  87        else
  88                res_start = res->start - window->offset;
  89
  90        rcar_pci_write_reg(pcie, upper_32_bits(res_start), PCIEPAUR(win));
  91        rcar_pci_write_reg(pcie, lower_32_bits(res_start) & ~0x7F,
  92                           PCIEPALR(win));
  93
  94        /* First resource is for IO */
  95        mask = PAR_ENABLE;
  96        if (res->flags & IORESOURCE_IO)
  97                mask |= IO_SPACE;
  98
  99        rcar_pci_write_reg(pcie, mask, PCIEPTCTLR(win));
 100}
 101
 102void rcar_pcie_set_inbound(struct rcar_pcie *pcie, u64 cpu_addr,
 103                           u64 pci_addr, u64 flags, int idx, bool host)
 104{
 105        /*
 106         * Set up 64-bit inbound regions as the range parser doesn't
 107         * distinguish between 32 and 64-bit types.
 108         */
 109        if (host)
 110                rcar_pci_write_reg(pcie, lower_32_bits(pci_addr),
 111                                   PCIEPRAR(idx));
 112        rcar_pci_write_reg(pcie, lower_32_bits(cpu_addr), PCIELAR(idx));
 113        rcar_pci_write_reg(pcie, flags, PCIELAMR(idx));
 114
 115        if (host)
 116                rcar_pci_write_reg(pcie, upper_32_bits(pci_addr),
 117                                   PCIEPRAR(idx + 1));
 118        rcar_pci_write_reg(pcie, upper_32_bits(cpu_addr), PCIELAR(idx + 1));
 119        rcar_pci_write_reg(pcie, 0, PCIELAMR(idx + 1));
 120}
 121