mirror of
https://github.com/torvalds/linux.git
synced 2024-12-03 17:41:22 +00:00
98a8f63e56
Under certain circumstances, the io-pgtable code may end up issuing two TLB sync operations without any intervening invalidations. This goes badly for the M4U hardware, since it means the second sync ends up polling for a non-existent operation to finish, and as a result times out and warns. The io_pgtable_tlb_* helpers implement a high-level optimisation to avoid issuing the second sync at all in such cases, but in order to work correctly that requires all pagetable operations to be serialised under a lock, thus is no longer applicable to all io-pgtable users. Since we're the only user actually relying on this flag for correctness, let's reimplement it locally to avoid the headache of trying to make the high-level version concurrency-safe for other users. CC: Yong Wu <yong.wu@mediatek.com> CC: Matthias Brugger <matthias.bgg@gmail.com> Tested-by: Yong Wu <yong.wu@mediatek.com> Signed-off-by: Robin Murphy <robin.murphy@arm.com> Signed-off-by: Will Deacon <will.deacon@arm.com>
80 lines
1.9 KiB
C
80 lines
1.9 KiB
C
/*
|
|
* Copyright (c) 2015-2016 MediaTek Inc.
|
|
* Author: Honghui Zhang <honghui.zhang@mediatek.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.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*/
|
|
|
|
#ifndef _MTK_IOMMU_H_
|
|
#define _MTK_IOMMU_H_
|
|
|
|
#include <linux/clk.h>
|
|
#include <linux/component.h>
|
|
#include <linux/device.h>
|
|
#include <linux/io.h>
|
|
#include <linux/iommu.h>
|
|
#include <linux/list.h>
|
|
#include <linux/spinlock.h>
|
|
#include <soc/mediatek/smi.h>
|
|
|
|
#include "io-pgtable.h"
|
|
|
|
struct mtk_iommu_suspend_reg {
|
|
u32 standard_axi_mode;
|
|
u32 dcm_dis;
|
|
u32 ctrl_reg;
|
|
u32 int_control0;
|
|
u32 int_main_control;
|
|
};
|
|
|
|
struct mtk_iommu_domain;
|
|
|
|
struct mtk_iommu_data {
|
|
void __iomem *base;
|
|
int irq;
|
|
struct device *dev;
|
|
struct clk *bclk;
|
|
phys_addr_t protect_base; /* protect memory base */
|
|
struct mtk_iommu_suspend_reg reg;
|
|
struct mtk_iommu_domain *m4u_dom;
|
|
struct iommu_group *m4u_group;
|
|
struct mtk_smi_iommu smi_imu; /* SMI larb iommu info */
|
|
bool enable_4GB;
|
|
bool tlb_flush_active;
|
|
|
|
struct iommu_device iommu;
|
|
};
|
|
|
|
static inline int compare_of(struct device *dev, void *data)
|
|
{
|
|
return dev->of_node == data;
|
|
}
|
|
|
|
static inline void release_of(struct device *dev, void *data)
|
|
{
|
|
of_node_put(data);
|
|
}
|
|
|
|
static inline int mtk_iommu_bind(struct device *dev)
|
|
{
|
|
struct mtk_iommu_data *data = dev_get_drvdata(dev);
|
|
|
|
return component_bind_all(dev, &data->smi_imu);
|
|
}
|
|
|
|
static inline void mtk_iommu_unbind(struct device *dev)
|
|
{
|
|
struct mtk_iommu_data *data = dev_get_drvdata(dev);
|
|
|
|
component_unbind_all(dev, &data->smi_imu);
|
|
}
|
|
|
|
#endif
|