// SPDX-License-Identifier: GPL-2.0
/*
* Freescale Management Complex (MC) bus driver
*
* Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
* Copyright 2019-2020 NXP
* Author: German Rivera <German.Rivera@freescale.com>
*
*/
#define pr_fmt(fmt) "fsl-mc: " fmt
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/of_address.h>
#include <linux/ioport.h>
#include <linux/slab.h>
#include <linux/limits.h>
#include <linux/bitops.h>
#include <linux/dma-mapping.h>
#include <linux/acpi.h>
#include <linux/iommu.h>
#include <linux/dma-map-ops.h>
#include "fsl-mc-private.h"
/*
* Default DMA mask for devices on a fsl-mc bus
*/
#define FSL_MC_DEFAULT_DMA_MASK (~0ULL)
static struct fsl_mc_version mc_version;
/**
* struct fsl_mc - Private data of a "fsl,qoriq-mc" platform device
* @root_mc_bus_dev: fsl-mc device representing the root DPRC
* @num_translation_ranges: number of entries in addr_translation_ranges
* @translation_ranges: array of bus to system address translation ranges
* @fsl_mc_regs: base address of register bank
*/
struct fsl_mc {
struct fsl_mc_device *root_mc_bus_dev;
u8 num_translation_ranges;
struct fsl_mc_addr_translation_range *translation_ranges;
void __iomem *fsl_mc_regs;
};
/**
* struct fsl_mc_addr_translation_range - bus to system address translation
* range
* @mc_region_type: Type of MC region for the range being translated
* @start_mc_offset: Start MC offset of the range being translated
* @end_mc_offset: MC offset of the first byte after the range (last MC
* offset of the range is end_mc_offset - 1)
* @start_phys_addr: system physical address corresponding to start_mc_addr
*/
struct fsl_mc_addr_translation_range {
enum dprc_region_type mc_region_type;
u64 start_mc_offset;
u64 end_mc_offset;
phys_addr_t start_phys_addr;
};
#define FSL_MC_GCR1 0x0
#define GCR1_P1_STOP BIT(31)
#define GCR1_P2_STOP BIT(30)
#define FSL_MC_FAPR 0x28
#define MC_FAPR_PL BIT(18)
#define MC_FAPR_BMT BIT(17)
static phys_addr_t mc_portal_base_phys_addr;
/**
* fsl_mc_bus_match - device to driver matching callback
* @dev: the fsl-mc device to match against
* @drv: the device driver to search for matching fsl-mc object type
* structures
*
* Returns 1 on success, 0 otherwise.
*/
static int fsl_mc_bus_match(struct device *dev, struct device_driver *drv)
{
const struct fsl_mc_device_id *id;
struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(drv);
bool found = false;
/* When driver_override is set, only bind to the matching driver */
if (mc_dev->driver_override) {
found = !strcmp(mc_dev->driver_override, mc_drv->driver.name);
goto out;
}
if (!mc_drv->match_id_table)
goto out;
/*
* If the object is not 'plugged' don't match.
* Only exception is the root DPRC, which is a special case.
*/
if ((mc_dev->obj_desc.state & FSL_MC_OBJ_STATE_PLUGGED) == 0 &&
!fsl_mc_is_root_dprc(&mc_dev->dev))
goto out;
/*