linux/drivers/pci/controller/pci-v3-semi.c

// SPDX-License-Identifier: GPL-2.0
/*
 * Support for V3 Semiconductor PCI Local Bus to PCI Bridge
 * Copyright (C) 2017 Linus Walleij <[email protected]>
 *
 * Based on the code from arch/arm/mach-integrator/pci_v3.c
 * Copyright (C) 1999 ARM Limited
 * Copyright (C) 2000-2001 Deep Blue Solutions Ltd
 *
 * Contributors to the old driver include:
 * Russell King <[email protected]>
 * David A. Rusling <[email protected]> (uHAL, ARM Firmware suite)
 * Rob Herring <[email protected]>
 * Liviu Dudau <[email protected]>
 * Grant Likely <[email protected]>
 * Arnd Bergmann <[email protected]>
 * Bjorn Helgaas <[email protected]>
 */
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/of.h>
#include <linux/of_pci.h>
#include <linux/pci.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/bitops.h>
#include <linux/irq.h>
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
#include <linux/clk.h>

#include "../pci.h"

#define V3_PCI_VENDOR
#define V3_PCI_DEVICE
#define V3_PCI_CMD
#define V3_PCI_STAT
#define V3_PCI_CC_REV
#define V3_PCI_HDR_CFG
#define V3_PCI_IO_BASE
#define V3_PCI_BASE0
#define V3_PCI_BASE1
#define V3_PCI_SUB_VENDOR
#define V3_PCI_SUB_ID
#define V3_PCI_ROM
#define V3_PCI_BPARAM
#define V3_PCI_MAP0
#define V3_PCI_MAP1
#define V3_PCI_INT_STAT
#define V3_PCI_INT_CFG
#define V3_LB_BASE0
#define V3_LB_BASE1
#define V3_LB_MAP0
#define V3_LB_MAP1
#define V3_LB_BASE2
#define V3_LB_MAP2
#define V3_LB_SIZE
#define V3_LB_IO_BASE
#define V3_FIFO_CFG
#define V3_FIFO_PRIORITY
#define V3_FIFO_STAT
#define V3_LB_ISTAT
#define V3_LB_IMASK
#define V3_SYSTEM
#define V3_LB_CFG
#define V3_PCI_CFG
#define V3_DMA_PCI_ADR0
#define V3_DMA_PCI_ADR1
#define V3_DMA_LOCAL_ADR0
#define V3_DMA_LOCAL_ADR1
#define V3_DMA_LENGTH0
#define V3_DMA_LENGTH1
#define V3_DMA_CSR0
#define V3_DMA_CSR1
#define V3_DMA_CTLB_ADR0
#define V3_DMA_CTLB_ADR1
#define V3_DMA_DELAY
#define V3_MAIL_DATA
#define V3_PCI_MAIL_IEWR
#define V3_PCI_MAIL_IERD
#define V3_LB_MAIL_IEWR
#define V3_LB_MAIL_IERD
#define V3_MAIL_WR_STAT
#define V3_MAIL_RD_STAT
#define V3_QBA_MAP

/* PCI STATUS bits */
#define V3_PCI_STAT_PAR_ERR
#define V3_PCI_STAT_SYS_ERR
#define V3_PCI_STAT_M_ABORT_ERR
#define V3_PCI_STAT_T_ABORT_ERR

/* LB ISTAT bits */
#define V3_LB_ISTAT_MAILBOX
#define V3_LB_ISTAT_PCI_RD
#define V3_LB_ISTAT_PCI_WR
#define V3_LB_ISTAT_PCI_INT
#define V3_LB_ISTAT_PCI_PERR
#define V3_LB_ISTAT_I2O_QWR
#define V3_LB_ISTAT_DMA1
#define V3_LB_ISTAT_DMA0

/* PCI COMMAND bits */
#define V3_COMMAND_M_FBB_EN
#define V3_COMMAND_M_SERR_EN
#define V3_COMMAND_M_PAR_EN
#define V3_COMMAND_M_MASTER_EN
#define V3_COMMAND_M_MEM_EN
#define V3_COMMAND_M_IO_EN

/* SYSTEM bits */
#define V3_SYSTEM_M_RST_OUT
#define V3_SYSTEM_M_LOCK
#define V3_SYSTEM_UNLOCK

/* PCI CFG bits */
#define V3_PCI_CFG_M_I2O_EN
#define V3_PCI_CFG_M_IO_REG_DIS
#define V3_PCI_CFG_M_IO_DIS
#define V3_PCI_CFG_M_EN3V
#define V3_PCI_CFG_M_RETRY_EN
#define V3_PCI_CFG_M_AD_LOW1
#define V3_PCI_CFG_M_AD_LOW0
/*
 * This is the value applied to C/BE[3:1], with bit 0 always held 0
 * during DMA access.
 */
#define V3_PCI_CFG_M_RTYPE_SHIFT
#define V3_PCI_CFG_M_WTYPE_SHIFT
#define V3_PCI_CFG_TYPE_DEFAULT

/* PCI BASE bits (PCI -> Local Bus) */
#define V3_PCI_BASE_M_ADR_BASE
#define V3_PCI_BASE_M_ADR_BASEL
#define V3_PCI_BASE_M_PREFETCH
#define V3_PCI_BASE_M_TYPE
#define V3_PCI_BASE_M_IO

/* PCI MAP bits (PCI -> Local bus) */
#define V3_PCI_MAP_M_MAP_ADR
#define V3_PCI_MAP_M_RD_POST_INH
#define V3_PCI_MAP_M_ROM_SIZE
#define V3_PCI_MAP_M_SWAP
#define V3_PCI_MAP_M_ADR_SIZE
#define V3_PCI_MAP_M_REG_EN
#define V3_PCI_MAP_M_ENABLE

/* LB_BASE0,1 bits (Local bus -> PCI) */
#define V3_LB_BASE_ADR_BASE
#define V3_LB_BASE_SWAP
#define V3_LB_BASE_ADR_SIZE
#define V3_LB_BASE_PREFETCH
#define V3_LB_BASE_ENABLE

#define V3_LB_BASE_ADR_SIZE_1MB
#define V3_LB_BASE_ADR_SIZE_2MB
#define V3_LB_BASE_ADR_SIZE_4MB
#define V3_LB_BASE_ADR_SIZE_8MB
#define V3_LB_BASE_ADR_SIZE_16MB
#define V3_LB_BASE_ADR_SIZE_32MB
#define V3_LB_BASE_ADR_SIZE_64MB
#define V3_LB_BASE_ADR_SIZE_128MB
#define V3_LB_BASE_ADR_SIZE_256MB
#define V3_LB_BASE_ADR_SIZE_512MB
#define V3_LB_BASE_ADR_SIZE_1GB
#define V3_LB_BASE_ADR_SIZE_2GB

#define v3_addr_to_lb_base(a)

/* LB_MAP0,1 bits (Local bus -> PCI) */
#define V3_LB_MAP_MAP_ADR
#define V3_LB_MAP_TYPE
#define V3_LB_MAP_AD_LOW_EN

#define V3_LB_MAP_TYPE_IACK
#define V3_LB_MAP_TYPE_IO
#define V3_LB_MAP_TYPE_MEM
#define V3_LB_MAP_TYPE_CONFIG
#define V3_LB_MAP_TYPE_MEM_MULTIPLE

#define v3_addr_to_lb_map(a)

/* LB_BASE2 bits (Local bus -> PCI IO) */
#define V3_LB_BASE2_ADR_BASE
#define V3_LB_BASE2_SWAP_AUTO
#define V3_LB_BASE2_ENABLE

#define v3_addr_to_lb_base2(a)

/* LB_MAP2 bits (Local bus -> PCI IO) */
#define V3_LB_MAP2_MAP_ADR

#define v3_addr_to_lb_map2(a)

/* FIFO priority bits */
#define V3_FIFO_PRIO_LOCAL
#define V3_FIFO_PRIO_LB_RD1_FLUSH_EOB
#define V3_FIFO_PRIO_LB_RD1_FLUSH_AP1
#define V3_FIFO_PRIO_LB_RD1_FLUSH_ANY
#define V3_FIFO_PRIO_LB_RD0_FLUSH_EOB
#define V3_FIFO_PRIO_LB_RD0_FLUSH_AP1
#define V3_FIFO_PRIO_LB_RD0_FLUSH_ANY
#define V3_FIFO_PRIO_PCI
#define V3_FIFO_PRIO_PCI_RD1_FLUSH_EOB
#define V3_FIFO_PRIO_PCI_RD1_FLUSH_AP1
#define V3_FIFO_PRIO_PCI_RD1_FLUSH_ANY
#define V3_FIFO_PRIO_PCI_RD0_FLUSH_EOB
#define V3_FIFO_PRIO_PCI_RD0_FLUSH_AP1
#define V3_FIFO_PRIO_PCI_RD0_FLUSH_ANY

/* Local bus configuration bits */
#define V3_LB_CFG_LB_TO_64_CYCLES
#define V3_LB_CFG_LB_TO_256_CYCLES
#define V3_LB_CFG_LB_TO_512_CYCLES
#define V3_LB_CFG_LB_TO_1024_CYCLES
#define V3_LB_CFG_LB_RST
#define V3_LB_CFG_LB_PPC_RDY
#define V3_LB_CFG_LB_LB_INT
#define V3_LB_CFG_LB_ERR_EN
#define V3_LB_CFG_LB_RDY_EN
#define V3_LB_CFG_LB_BE_IMODE
#define V3_LB_CFG_LB_BE_OMODE
#define V3_LB_CFG_LB_ENDIAN
#define V3_LB_CFG_LB_PARK_EN
#define V3_LB_CFG_LB_FBB_DIS

/* ARM Integrator-specific extended control registers */
#define INTEGRATOR_SC_PCI_OFFSET
#define INTEGRATOR_SC_PCI_ENABLE
#define INTEGRATOR_SC_PCI_INTCLR
#define INTEGRATOR_SC_LBFADDR_OFFSET
#define INTEGRATOR_SC_LBFCODE_OFFSET

struct v3_pci {};

/*
 * The V3 PCI interface chip in Integrator provides several windows from
 * local bus memory into the PCI memory areas. Unfortunately, there
 * are not really enough windows for our usage, therefore we reuse
 * one of the windows for access to PCI configuration space. On the
 * Integrator/AP, the memory map is as follows:
 *
 * Local Bus Memory         Usage
 *
 * 40000000 - 4FFFFFFF      PCI memory.  256M non-prefetchable
 * 50000000 - 5FFFFFFF      PCI memory.  256M prefetchable
 * 60000000 - 60FFFFFF      PCI IO.  16M
 * 61000000 - 61FFFFFF      PCI Configuration. 16M
 *
 * There are three V3 windows, each described by a pair of V3 registers.
 * These are LB_BASE0/LB_MAP0, LB_BASE1/LB_MAP1 and LB_BASE2/LB_MAP2.
 * Base0 and Base1 can be used for any type of PCI memory access.   Base2
 * can be used either for PCI I/O or for I20 accesses.  By default, uHAL
 * uses this only for PCI IO space.
 *
 * Normally these spaces are mapped using the following base registers:
 *
 * Usage Local Bus Memory         Base/Map registers used
 *
 * Mem   40000000 - 4FFFFFFF      LB_BASE0/LB_MAP0
 * Mem   50000000 - 5FFFFFFF      LB_BASE1/LB_MAP1
 * IO    60000000 - 60FFFFFF      LB_BASE2/LB_MAP2
 * Cfg   61000000 - 61FFFFFF
 *
 * This means that I20 and PCI configuration space accesses will fail.
 * When PCI configuration accesses are needed (via the uHAL PCI
 * configuration space primitives) we must remap the spaces as follows:
 *
 * Usage Local Bus Memory         Base/Map registers used
 *
 * Mem   40000000 - 4FFFFFFF      LB_BASE0/LB_MAP0
 * Mem   50000000 - 5FFFFFFF      LB_BASE0/LB_MAP0
 * IO    60000000 - 60FFFFFF      LB_BASE2/LB_MAP2
 * Cfg   61000000 - 61FFFFFF      LB_BASE1/LB_MAP1
 *
 * To make this work, the code depends on overlapping windows working.
 * The V3 chip translates an address by checking its range within
 * each of the BASE/MAP pairs in turn (in ascending register number
 * order).  It will use the first matching pair.   So, for example,
 * if the same address is mapped by both LB_BASE0/LB_MAP0 and
 * LB_BASE1/LB_MAP1, the V3 will use the translation from
 * LB_BASE0/LB_MAP0.
 *
 * To allow PCI Configuration space access, the code enlarges the
 * window mapped by LB_BASE0/LB_MAP0 from 256M to 512M.  This occludes
 * the windows currently mapped by LB_BASE1/LB_MAP1 so that it can
 * be remapped for use by configuration cycles.
 *
 * At the end of the PCI Configuration space accesses,
 * LB_BASE1/LB_MAP1 is reset to map PCI Memory.  Finally the window
 * mapped by LB_BASE0/LB_MAP0 is reduced in size from 512M to 256M to
 * reveal the now restored LB_BASE1/LB_MAP1 window.
 *
 * NOTE: We do not set up I2O mapping.  I suspect that this is only
 * for an intelligent (target) device.  Using I2O disables most of
 * the mappings into PCI memory.
 */
static void __iomem *v3_map_bus(struct pci_bus *bus,
				unsigned int devfn, int offset)
{}

static void v3_unmap_bus(struct v3_pci *v3)
{}

static int v3_pci_read_config(struct pci_bus *bus, unsigned int fn,
			      int config, int size, u32 *value)
{}

static int v3_pci_write_config(struct pci_bus *bus, unsigned int fn,
				    int config, int size, u32 value)
{}

static struct pci_ops v3_pci_ops =;

static irqreturn_t v3_irq(int irq, void *data)
{}

static int v3_integrator_init(struct v3_pci *v3)
{}

static int v3_pci_setup_resource(struct v3_pci *v3,
				 struct pci_host_bridge *host,
				 struct resource_entry *win)
{}

static int v3_get_dma_range_config(struct v3_pci *v3,
				   struct resource_entry *entry,
				   u32 *pci_base, u32 *pci_map)
{}

static int v3_pci_parse_map_dma_ranges(struct v3_pci *v3,
				       struct device_node *np)
{}

static int v3_pci_probe(struct platform_device *pdev)
{}

static const struct of_device_id v3_pci_of_match[] =;

static struct platform_driver v3_pci_driver =;
builtin_platform_driver();