diff --git a/drivers/video/rockchip/mpp/Makefile b/drivers/video/rockchip/mpp/Makefile index 4e5d59e88766..67d7039ae4a8 100644 --- a/drivers/video/rockchip/mpp/Makefile +++ b/drivers/video/rockchip/mpp/Makefile @@ -21,4 +21,7 @@ rk_vcodec-$(CONFIG_ROCKCHIP_MPP_VEPU2) += mpp_vepu2.o rk_vcodec-$(CONFIG_ROCKCHIP_MPP_IEP2) += mpp_iep2.o rk_vcodec-$(CONFIG_ROCKCHIP_MPP_JPGDEC) += mpp_jpgdec.o +# hack for workaround +rk_vcodec-$(CONFIG_CPU_PX30) += hack/mpp_hack_px30.o + obj-$(CONFIG_ROCKCHIP_MPP_SERVICE) += rk_vcodec.o diff --git a/drivers/video/rockchip/mpp/hack/mpp_hack_px30.c b/drivers/video/rockchip/mpp/hack/mpp_hack_px30.c new file mode 100644 index 000000000000..379049eaf8fc --- /dev/null +++ b/drivers/video/rockchip/mpp/hack/mpp_hack_px30.c @@ -0,0 +1,230 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd + * + * author: + * Ding Wei, leo.ding@rock-chips.com + * + */ + +#include +#include +#include +#include +#include + +#include + +#include "../mpp_debug.h" +#include "../mpp_common.h" +#include "../mpp_iommu.h" +#include "mpp_hack_px30.h" + +#define RK_MMU_DTE_ADDR 0x00 /* Directory table address */ +#define RK_MMU_STATUS 0x04 +#define RK_MMU_COMMAND 0x08 +#define RK_MMU_INT_MASK 0x1C /* IRQ enable */ + +/* RK_MMU_COMMAND command values */ +#define RK_MMU_CMD_ENABLE_PAGING 0 /* Enable memory translation */ +#define RK_MMU_CMD_DISABLE_PAGING 1 /* Disable memory translation */ +#define RK_MMU_CMD_ENABLE_STALL 2 /* Stall paging to allow other cmds */ +#define RK_MMU_CMD_DISABLE_STALL 3 /* Stop stall re-enables paging */ +#define RK_MMU_CMD_ZAP_CACHE 4 /* Shoot down entire IOTLB */ +#define RK_MMU_CMD_PAGE_FAULT_DONE 5 /* Clear page fault */ +#define RK_MMU_CMD_FORCE_RESET 6 /* Reset all registers */ + +/* RK_MMU_INT_* register fields */ +#define RK_MMU_IRQ_MASK 0x03 +/* RK_MMU_STATUS fields */ +#define RK_MMU_STATUS_PAGING_ENABLED BIT(0) +#define RK_MMU_STATUS_STALL_ACTIVE BIT(2) + +static bool mpp_iommu_is_paged(struct mpp_rk_iommu *iommu) +{ + int i; + u32 status; + bool active = true; + + for (i = 0; i < iommu->mmu_num; i++) { + status = readl(iommu->bases[i] + RK_MMU_STATUS); + active &= !!(status & RK_MMU_STATUS_PAGING_ENABLED); + } + + return active; +} + +static u32 mpp_iommu_get_dte_addr(struct mpp_rk_iommu *iommu) +{ + return readl(iommu->bases[0] + RK_MMU_DTE_ADDR); +} + +static int mpp_iommu_enable(struct mpp_rk_iommu *iommu) +{ + int i; + + /* check iommu whether is paged */ + iommu->is_paged = mpp_iommu_is_paged(iommu); + if (iommu->is_paged) + return 0; + + /* enable stall */ + for (i = 0; i < iommu->mmu_num; i++) + writel(RK_MMU_CMD_ENABLE_STALL, + iommu->bases[i] + RK_MMU_COMMAND); + udelay(2); + /* force reset */ + for (i = 0; i < iommu->mmu_num; i++) + writel(RK_MMU_CMD_FORCE_RESET, + iommu->bases[i] + RK_MMU_COMMAND); + udelay(2); + + for (i = 0; i < iommu->mmu_num; i++) { + /* restore dte and status */ + writel(iommu->dte_addr, + iommu->bases[i] + RK_MMU_DTE_ADDR); + /* zap cache */ + writel(RK_MMU_CMD_ZAP_CACHE, + iommu->bases[i] + RK_MMU_COMMAND); + /* irq mask */ + writel(RK_MMU_IRQ_MASK, + iommu->bases[i] + RK_MMU_INT_MASK); + } + udelay(2); + /* enable paging */ + for (i = 0; i < iommu->mmu_num; i++) + writel(RK_MMU_CMD_ENABLE_PAGING, + iommu->bases[i] + RK_MMU_COMMAND); + udelay(2); + /* disable stall */ + for (i = 0; i < iommu->mmu_num; i++) + writel(RK_MMU_CMD_DISABLE_STALL, + iommu->bases[i] + RK_MMU_COMMAND); + udelay(2); + + /* iommu should be paging enable */ + iommu->is_paged = mpp_iommu_is_paged(iommu); + if (!iommu->is_paged) { + mpp_err("iommu->base_addr=%08x enable failed\n", + iommu->base_addr[0]); + return -EINVAL; + } + + return 0; +} + +static int mpp_iommu_disable(struct mpp_rk_iommu *iommu) +{ + int i; + u32 dte; + + if (iommu->is_paged) { + dte = readl(iommu->bases[0] + RK_MMU_DTE_ADDR); + if (!dte) + return -EINVAL; + udelay(2); + /* enable stall */ + for (i = 0; i < iommu->mmu_num; i++) + writel(RK_MMU_CMD_ENABLE_STALL, + iommu->bases[i] + RK_MMU_COMMAND); + udelay(2); + /* disable paging */ + for (i = 0; i < iommu->mmu_num; i++) + writel(RK_MMU_CMD_DISABLE_PAGING, + iommu->bases[i] + RK_MMU_COMMAND); + udelay(2); + /* disable stall */ + for (i = 0; i < iommu->mmu_num; i++) + writel(RK_MMU_CMD_DISABLE_STALL, + iommu->bases[i] + RK_MMU_COMMAND); + udelay(2); + } + + return 0; +} + +int px30_workaround_combo_init(struct mpp_dev *mpp) +{ + struct mpp_rk_iommu *iommu = NULL, *loop = NULL, *n; + struct platform_device *pdev = mpp->iommu_info->pdev; + + /* find whether exist in iommu link */ + list_for_each_entry_safe(loop, n, &mpp->queue->mmu_list, link) { + if (loop->base_addr[0] == pdev->resource[0].start) { + iommu = loop; + break; + } + } + /* if not exist, add it */ + if (!iommu) { + int i; + struct resource *res; + void __iomem *base; + + iommu = devm_kzalloc(mpp->srv->dev, sizeof(*iommu), GFP_KERNEL); + for (i = 0; i < pdev->num_resources; i++) { + res = platform_get_resource(pdev, IORESOURCE_MEM, i); + if (!res) + continue; + base = devm_ioremap(&pdev->dev, + res->start, resource_size(res)); + if (IS_ERR(base)) + continue; + iommu->base_addr[i] = res->start; + iommu->bases[i] = base; + iommu->mmu_num++; + } + iommu->grf_val = mpp->grf_info->val & MPP_GRF_VAL_MASK; + if (mpp->hw_ops->clk_on) + mpp->hw_ops->clk_on(mpp); + iommu->dte_addr = mpp_iommu_get_dte_addr(iommu); + if (mpp->hw_ops->clk_off) + mpp->hw_ops->clk_off(mpp); + INIT_LIST_HEAD(&iommu->link); + mutex_lock(&mpp->queue->mmu_lock); + list_add_tail(&iommu->link, &mpp->queue->mmu_list); + mutex_unlock(&mpp->queue->mmu_lock); + } + mpp->iommu_info->iommu = iommu; + + return 0; +} + +int px30_workaround_combo_switch_grf(struct mpp_dev *mpp) +{ + int ret = 0; + u32 curr_val; + u32 next_val; + bool pd_is_on; + struct mpp_rk_iommu *loop = NULL, *n; + + if (!mpp->grf_info->grf || !mpp->grf_info->val) + return 0; + + curr_val = mpp_get_grf(mpp->grf_info); + next_val = mpp->grf_info->val & MPP_GRF_VAL_MASK; + if (curr_val == next_val) + return 0; + + pd_is_on = rockchip_pmu_pd_is_on(mpp->dev); + if (!pd_is_on) + rockchip_pmu_pd_on(mpp->dev); + mpp->hw_ops->clk_on(mpp); + + list_for_each_entry_safe(loop, n, &mpp->queue->mmu_list, link) { + /* update iommu parameters */ + if (loop->grf_val == curr_val) + loop->is_paged = mpp_iommu_is_paged(loop); + /* disable all iommu */ + mpp_iommu_disable(loop); + } + mpp_set_grf(mpp->grf_info); + /* enable current iommu */ + ret = mpp_iommu_enable(mpp->iommu_info->iommu); + + mpp->hw_ops->clk_off(mpp); + if (!pd_is_on) + rockchip_pmu_pd_off(mpp->dev); + + return ret; +} diff --git a/drivers/video/rockchip/mpp/hack/mpp_hack_px30.h b/drivers/video/rockchip/mpp/hack/mpp_hack_px30.h new file mode 100644 index 000000000000..c8402e30d810 --- /dev/null +++ b/drivers/video/rockchip/mpp/hack/mpp_hack_px30.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ +/* + * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd + * + * author: + * Ding Wei, leo.ding@rock-chips.com + * + */ +#ifndef __ROCKCHIP_MPP_HACK_PX30_H__ +#define __ROCKCHIP_MPP_HACK_PX30_H__ + +#ifdef CONFIG_CPU_PX30 +int px30_workaround_combo_init(struct mpp_dev *mpp); +int px30_workaround_combo_switch_grf(struct mpp_dev *mpp); +#else +static inline int px30_workaround_combo_init(struct mpp_dev *mpp) +{ + return 0; +} + +static inline int px30_workaround_combo_switch_grf(struct mpp_dev *mpp) +{ + return 0; +} +#endif + +#endif diff --git a/drivers/video/rockchip/mpp/mpp_common.c b/drivers/video/rockchip/mpp/mpp_common.c index f4effb69af74..37fc4034acc1 100644 --- a/drivers/video/rockchip/mpp/mpp_common.c +++ b/drivers/video/rockchip/mpp/mpp_common.c @@ -1997,8 +1997,6 @@ irqreturn_t mpp_dev_isr_sched(int irq, void *param) return ret; } -#define MPP_GRF_VAL_MASK 0xFFFF - u32 mpp_get_grf(struct mpp_grf_info *grf_info) { u32 val = 0; @@ -2234,89 +2232,3 @@ mpp_procfs_create_u32(const char *name, umode_t mode, return proc_create_data(name, mode, parent, &procfs_fops_u32, data); } #endif - -int px30_workaround_combo_init(struct mpp_dev *mpp) -{ - struct mpp_rk_iommu *iommu = NULL, *loop = NULL, *n; - struct platform_device *pdev = mpp->iommu_info->pdev; - - /* find whether exist in iommu link */ - list_for_each_entry_safe(loop, n, &mpp->queue->mmu_list, link) { - if (loop->base_addr[0] == pdev->resource[0].start) { - iommu = loop; - break; - } - } - /* if not exist, add it */ - if (!iommu) { - int i; - struct resource *res; - void __iomem *base; - - iommu = devm_kzalloc(mpp->srv->dev, sizeof(*iommu), GFP_KERNEL); - for (i = 0; i < pdev->num_resources; i++) { - res = platform_get_resource(pdev, IORESOURCE_MEM, i); - if (!res) - continue; - base = devm_ioremap(&pdev->dev, - res->start, resource_size(res)); - if (IS_ERR(base)) - continue; - iommu->base_addr[i] = res->start; - iommu->bases[i] = base; - iommu->mmu_num++; - } - iommu->grf_val = mpp->grf_info->val & MPP_GRF_VAL_MASK; - if (mpp->hw_ops->clk_on) - mpp->hw_ops->clk_on(mpp); - iommu->dte_addr = mpp_iommu_get_dte_addr(iommu); - if (mpp->hw_ops->clk_off) - mpp->hw_ops->clk_off(mpp); - INIT_LIST_HEAD(&iommu->link); - mutex_lock(&mpp->queue->mmu_lock); - list_add_tail(&iommu->link, &mpp->queue->mmu_list); - mutex_unlock(&mpp->queue->mmu_lock); - } - mpp->iommu_info->iommu = iommu; - - return 0; -} - -int px30_workaround_combo_switch_grf(struct mpp_dev *mpp) -{ - int ret = 0; - u32 curr_val; - u32 next_val; - bool pd_is_on; - struct mpp_rk_iommu *loop = NULL, *n; - - if (!mpp->grf_info->grf || !mpp->grf_info->val) - return 0; - - curr_val = mpp_get_grf(mpp->grf_info); - next_val = mpp->grf_info->val & MPP_GRF_VAL_MASK; - if (curr_val == next_val) - return 0; - - pd_is_on = rockchip_pmu_pd_is_on(mpp->dev); - if (!pd_is_on) - rockchip_pmu_pd_on(mpp->dev); - mpp->hw_ops->clk_on(mpp); - - list_for_each_entry_safe(loop, n, &mpp->queue->mmu_list, link) { - /* update iommu parameters */ - if (loop->grf_val == curr_val) - loop->is_paged = mpp_iommu_is_paged(loop); - /* disable all iommu */ - mpp_iommu_disable(loop); - } - mpp_set_grf(mpp->grf_info); - /* enable current iommu */ - ret = mpp_iommu_enable(mpp->iommu_info->iommu); - - mpp->hw_ops->clk_off(mpp); - if (!pd_is_on) - rockchip_pmu_pd_off(mpp->dev); - - return ret; -} diff --git a/drivers/video/rockchip/mpp/mpp_common.h b/drivers/video/rockchip/mpp/mpp_common.h index 0efc88c6a912..50806d078b3a 100644 --- a/drivers/video/rockchip/mpp/mpp_common.h +++ b/drivers/video/rockchip/mpp/mpp_common.h @@ -36,6 +36,9 @@ #define MPP_FLAGS_REG_NO_OFFSET (0x00000010) #define MPP_FLAGS_SECURE_MODE (0x00010000) +/* grf mask for get value */ +#define MPP_GRF_VAL_MASK (0xFFFF) + /** * Device type: classified by hardware feature */ @@ -749,10 +752,6 @@ extern const char *mpp_device_name[MPP_DEVICE_BUTT]; extern const char *enc_info_item_name[ENC_INFO_BUTT]; #endif -/* workaround according hardware */ -int px30_workaround_combo_init(struct mpp_dev *mpp); -int px30_workaround_combo_switch_grf(struct mpp_dev *mpp); - extern const struct file_operations rockchip_mpp_fops; extern struct platform_driver rockchip_rkvdec_driver; diff --git a/drivers/video/rockchip/mpp/mpp_iommu.c b/drivers/video/rockchip/mpp/mpp_iommu.c index e4292d62b111..9b9313b97c26 100644 --- a/drivers/video/rockchip/mpp/mpp_iommu.c +++ b/drivers/video/rockchip/mpp/mpp_iommu.c @@ -458,129 +458,6 @@ int mpp_iommu_remove(struct mpp_iommu_info *info) return 0; } -#define RK_MMU_DTE_ADDR 0x00 /* Directory table address */ -#define RK_MMU_STATUS 0x04 -#define RK_MMU_COMMAND 0x08 -#define RK_MMU_INT_MASK 0x1C /* IRQ enable */ - -/* RK_MMU_COMMAND command values */ -#define RK_MMU_CMD_ENABLE_PAGING 0 /* Enable memory translation */ -#define RK_MMU_CMD_DISABLE_PAGING 1 /* Disable memory translation */ -#define RK_MMU_CMD_ENABLE_STALL 2 /* Stall paging to allow other cmds */ -#define RK_MMU_CMD_DISABLE_STALL 3 /* Stop stall re-enables paging */ -#define RK_MMU_CMD_ZAP_CACHE 4 /* Shoot down entire IOTLB */ -#define RK_MMU_CMD_PAGE_FAULT_DONE 5 /* Clear page fault */ -#define RK_MMU_CMD_FORCE_RESET 6 /* Reset all registers */ - -/* RK_MMU_INT_* register fields */ -#define RK_MMU_IRQ_MASK 0x03 -/* RK_MMU_STATUS fields */ -#define RK_MMU_STATUS_PAGING_ENABLED BIT(0) -#define RK_MMU_STATUS_STALL_ACTIVE BIT(2) - -bool mpp_iommu_is_paged(struct mpp_rk_iommu *iommu) -{ - int i; - u32 status; - bool active = true; - - for (i = 0; i < iommu->mmu_num; i++) { - status = readl(iommu->bases[i] + RK_MMU_STATUS); - active &= !!(status & RK_MMU_STATUS_PAGING_ENABLED); - } - - return active; -} - -u32 mpp_iommu_get_dte_addr(struct mpp_rk_iommu *iommu) -{ - return readl(iommu->bases[0] + RK_MMU_DTE_ADDR); -} - -int mpp_iommu_enable(struct mpp_rk_iommu *iommu) -{ - int i; - - /* check iommu whether is paged */ - iommu->is_paged = mpp_iommu_is_paged(iommu); - if (iommu->is_paged) - return 0; - - /* enable stall */ - for (i = 0; i < iommu->mmu_num; i++) - writel(RK_MMU_CMD_ENABLE_STALL, - iommu->bases[i] + RK_MMU_COMMAND); - udelay(2); - /* force reset */ - for (i = 0; i < iommu->mmu_num; i++) - writel(RK_MMU_CMD_FORCE_RESET, - iommu->bases[i] + RK_MMU_COMMAND); - udelay(2); - - for (i = 0; i < iommu->mmu_num; i++) { - /* restore dte and status */ - writel(iommu->dte_addr, - iommu->bases[i] + RK_MMU_DTE_ADDR); - /* zap cache */ - writel(RK_MMU_CMD_ZAP_CACHE, - iommu->bases[i] + RK_MMU_COMMAND); - /* irq mask */ - writel(RK_MMU_IRQ_MASK, - iommu->bases[i] + RK_MMU_INT_MASK); - } - udelay(2); - /* enable paging */ - for (i = 0; i < iommu->mmu_num; i++) - writel(RK_MMU_CMD_ENABLE_PAGING, - iommu->bases[i] + RK_MMU_COMMAND); - udelay(2); - /* disable stall */ - for (i = 0; i < iommu->mmu_num; i++) - writel(RK_MMU_CMD_DISABLE_STALL, - iommu->bases[i] + RK_MMU_COMMAND); - udelay(2); - - /* iommu should be paging enable */ - iommu->is_paged = mpp_iommu_is_paged(iommu); - if (!iommu->is_paged) { - mpp_err("iommu->base_addr=%08x enable failed\n", - iommu->base_addr[0]); - return -EINVAL; - } - - return 0; -} - -int mpp_iommu_disable(struct mpp_rk_iommu *iommu) -{ - int i; - u32 dte; - - if (iommu->is_paged) { - dte = readl(iommu->bases[0] + RK_MMU_DTE_ADDR); - if (!dte) - return -EINVAL; - udelay(2); - /* enable stall */ - for (i = 0; i < iommu->mmu_num; i++) - writel(RK_MMU_CMD_ENABLE_STALL, - iommu->bases[i] + RK_MMU_COMMAND); - udelay(2); - /* disable paging */ - for (i = 0; i < iommu->mmu_num; i++) - writel(RK_MMU_CMD_DISABLE_PAGING, - iommu->bases[i] + RK_MMU_COMMAND); - udelay(2); - /* disable stall */ - for (i = 0; i < iommu->mmu_num; i++) - writel(RK_MMU_CMD_DISABLE_STALL, - iommu->bases[i] + RK_MMU_COMMAND); - udelay(2); - } - - return 0; -} - int mpp_iommu_refresh(struct mpp_iommu_info *info, struct device *dev) { int i; diff --git a/drivers/video/rockchip/mpp/mpp_iommu.h b/drivers/video/rockchip/mpp/mpp_iommu.h index a2de8abb0a4b..9ae1b6ba3567 100644 --- a/drivers/video/rockchip/mpp/mpp_iommu.h +++ b/drivers/video/rockchip/mpp/mpp_iommu.h @@ -102,10 +102,6 @@ int mpp_iommu_remove(struct mpp_iommu_info *info); int mpp_iommu_attach(struct mpp_iommu_info *info); int mpp_iommu_detach(struct mpp_iommu_info *info); -bool mpp_iommu_is_paged(struct mpp_rk_iommu *iommu); -u32 mpp_iommu_get_dte_addr(struct mpp_rk_iommu *iommu); -int mpp_iommu_enable(struct mpp_rk_iommu *iommu); -int mpp_iommu_disable(struct mpp_rk_iommu *iommu); int mpp_iommu_refresh(struct mpp_iommu_info *info, struct device *dev); int mpp_iommu_flush_tlb(struct mpp_iommu_info *info); diff --git a/drivers/video/rockchip/mpp/mpp_rkvdec.c b/drivers/video/rockchip/mpp/mpp_rkvdec.c index 0aea85cb0fb4..60d59cc1c86e 100644 --- a/drivers/video/rockchip/mpp/mpp_rkvdec.c +++ b/drivers/video/rockchip/mpp/mpp_rkvdec.c @@ -37,6 +37,8 @@ #include "mpp_common.h" #include "mpp_iommu.h" +#include "hack/mpp_hack_px30.h" + #define RKVDEC_DRIVER_NAME "mpp_rkvdec" #define IOMMU_GET_BUS_ID(x) (((x) >> 6) & 0x1f) diff --git a/drivers/video/rockchip/mpp/mpp_vdpu2.c b/drivers/video/rockchip/mpp/mpp_vdpu2.c index 98751eb3eab7..c1972624ed70 100644 --- a/drivers/video/rockchip/mpp/mpp_vdpu2.c +++ b/drivers/video/rockchip/mpp/mpp_vdpu2.c @@ -25,6 +25,7 @@ #include "mpp_debug.h" #include "mpp_common.h" #include "mpp_iommu.h" +#include "hack/mpp_hack_px30.h" #define VDPU2_DRIVER_NAME "mpp_vdpu2" diff --git a/drivers/video/rockchip/mpp/mpp_vepu2.c b/drivers/video/rockchip/mpp/mpp_vepu2.c index 67f424af6a21..a90b5ad6abb2 100644 --- a/drivers/video/rockchip/mpp/mpp_vepu2.c +++ b/drivers/video/rockchip/mpp/mpp_vepu2.c @@ -26,6 +26,7 @@ #include "mpp_debug.h" #include "mpp_common.h" #include "mpp_iommu.h" +#include "hack/mpp_hack_px30.h" #define VEPU2_DRIVER_NAME "mpp_vepu2"