mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 20:07:46 +09:00
rk3036, rk312x: add iommu switch in dts for vcodec and iep
This commit is contained in:
@@ -643,8 +643,9 @@
|
||||
};
|
||||
};
|
||||
|
||||
vpu: vpu_service@10108000 {
|
||||
vpu: vpu_service@10108000 {
|
||||
compatible = "vpu_service";
|
||||
iommu_enabled = <1>;
|
||||
reg = <0x10108000 0x800>;
|
||||
interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "irq_dec";
|
||||
@@ -656,6 +657,7 @@
|
||||
|
||||
hevc: hevc_service@1010c000 {
|
||||
compatible = "rockchip,hevc_service";
|
||||
iommu_enabled = <1>;
|
||||
reg = <0x1010c000 0x400>;
|
||||
interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "irq_dec";
|
||||
@@ -663,7 +665,7 @@
|
||||
clock-names = "aclk_vcodec", "hclk_vcodec", "clk_core";
|
||||
name = "hevc_service";
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
|
||||
vop_mmu {
|
||||
dbgname = "vop";
|
||||
|
||||
@@ -657,6 +657,7 @@
|
||||
|
||||
vpu: vpu_service@10106000 {
|
||||
compatible = "vpu_service";
|
||||
iommu_enabled = <1>;
|
||||
reg = <0x10106000 0x800>;
|
||||
interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "irq_enc", "irq_dec";
|
||||
@@ -668,6 +669,7 @@
|
||||
|
||||
hevc: hevc_service@10104000 {
|
||||
compatible = "rockchip,hevc_service";
|
||||
iommu_enabled = <1>;
|
||||
reg = <0x10104000 0x400>;
|
||||
interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "irq_dec";
|
||||
@@ -679,6 +681,7 @@
|
||||
|
||||
iep: iep@10108000 {
|
||||
compatible = "rockchip,iep";
|
||||
iommu_enabled = <1>;
|
||||
reg = <0x10108000 0x800>;
|
||||
interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&clk_gates9 8>, <&clk_gates9 7>;
|
||||
|
||||
@@ -405,9 +405,9 @@ static const struct file_operations debug_vcodec_fops = {
|
||||
#define BIT_VCODEC_SEL_RK312X (1<<15)
|
||||
static void vcodec_enter_mode_nolock(enum vcodec_device_id id, u32 *reserved_mode)
|
||||
{
|
||||
if (soc_is_rk3036() || soc_is_rk3126() || soc_is_rk3128()) {
|
||||
int bits = soc_is_rk3036() ? BIT_VCODEC_SEL_RK3036 : BIT_VCODEC_SEL_RK312X;
|
||||
void __iomem *addr = soc_is_rk3036() ? (RK_GRF_VIRT + RK3036_GRF_SOC_CON1) : (RK_GRF_VIRT + RK312X_GRF_SOC_CON1);
|
||||
if (cpu_is_rk3036() || cpu_is_rk312x()) {
|
||||
int bits = cpu_is_rk3036() ? BIT_VCODEC_SEL_RK3036 : BIT_VCODEC_SEL_RK312X;
|
||||
void __iomem *addr = cpu_is_rk3036() ? (RK_GRF_VIRT + RK3036_GRF_SOC_CON1) : (RK_GRF_VIRT + RK312X_GRF_SOC_CON1);
|
||||
if (reserved_mode)
|
||||
*reserved_mode = readl_relaxed(addr);
|
||||
if (id == VCODEC_DEVICE_ID_HEVC)
|
||||
@@ -419,23 +419,23 @@ static void vcodec_enter_mode_nolock(enum vcodec_device_id id, u32 *reserved_mod
|
||||
|
||||
static void vcodec_exit_mode_nolock(enum vcodec_device_id id, u32 reserved_mode)
|
||||
{
|
||||
if (soc_is_rk3036() || soc_is_rk3126() || soc_is_rk3128()) {
|
||||
int bits = soc_is_rk3036() ? BIT_VCODEC_SEL_RK3036 : BIT_VCODEC_SEL_RK312X;
|
||||
void __iomem *addr = soc_is_rk3036() ? (RK_GRF_VIRT + RK3036_GRF_SOC_CON1) : (RK_GRF_VIRT + RK312X_GRF_SOC_CON1);
|
||||
if (cpu_is_rk3036() || cpu_is_rk312x()) {
|
||||
int bits = cpu_is_rk3036() ? BIT_VCODEC_SEL_RK3036 : BIT_VCODEC_SEL_RK312X;
|
||||
void __iomem *addr = cpu_is_rk3036() ? (RK_GRF_VIRT + RK3036_GRF_SOC_CON1) : (RK_GRF_VIRT + RK312X_GRF_SOC_CON1);
|
||||
writel_relaxed(reserved_mode | (bits << 16), addr);
|
||||
}
|
||||
}
|
||||
|
||||
static void vcodec_enter_mode(enum vcodec_device_id id)
|
||||
{
|
||||
if (soc_is_rk3036() || soc_is_rk3126() || soc_is_rk3128())
|
||||
if (cpu_is_rk3036() || cpu_is_rk312x())
|
||||
mutex_lock(&g_mode_mutex);
|
||||
vcodec_enter_mode_nolock(id, NULL);
|
||||
}
|
||||
|
||||
static void vcodec_exit_mode(void)
|
||||
{
|
||||
if (soc_is_rk3036() || soc_is_rk3126() || soc_is_rk3128())
|
||||
if (cpu_is_rk3036() || cpu_is_rk312x())
|
||||
mutex_unlock(&g_mode_mutex);
|
||||
}
|
||||
|
||||
@@ -462,7 +462,7 @@ static int vpu_get_clk(struct vpu_service_info *pservice)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!soc_is_rk3036() && !soc_is_rk3126() && !soc_is_rk3128()) {
|
||||
if (!cpu_is_rk3036() && !cpu_is_rk312x()) {
|
||||
pservice->clk_cabac = devm_clk_get(pservice->dev, "clk_cabac");
|
||||
if (IS_ERR(pservice->clk_cabac)) {
|
||||
dev_err(pservice->dev, "failed on clk_get clk_cabac\n");
|
||||
@@ -472,7 +472,7 @@ static int vpu_get_clk(struct vpu_service_info *pservice)
|
||||
pservice->clk_cabac = NULL;
|
||||
}
|
||||
|
||||
if (!soc_is_rk3036() && !soc_is_rk3126() && !soc_is_rk3128()) {
|
||||
if (!cpu_is_rk3036() && !cpu_is_rk312x()) {
|
||||
pservice->pd_video = devm_clk_get(pservice->dev, "pd_hevc");
|
||||
if (IS_ERR(pservice->pd_video)) {
|
||||
dev_err(pservice->dev, "failed on clk_get pd_hevc\n");
|
||||
@@ -482,7 +482,7 @@ static int vpu_get_clk(struct vpu_service_info *pservice)
|
||||
pservice->pd_video = NULL;
|
||||
}
|
||||
} else {
|
||||
if (!soc_is_rk3036() && !soc_is_rk3126() && !soc_is_rk3128()) {
|
||||
if (!cpu_is_rk3036() && !cpu_is_rk312x()) {
|
||||
pservice->pd_video = devm_clk_get(pservice->dev, "pd_video");
|
||||
if (IS_ERR(pservice->pd_video)) {
|
||||
dev_err(pservice->dev, "failed on clk_get pd_video\n");
|
||||
@@ -493,7 +493,7 @@ static int vpu_get_clk(struct vpu_service_info *pservice)
|
||||
}
|
||||
}
|
||||
|
||||
if (soc_is_rk3126() || soc_is_rk3128()) {
|
||||
if (cpu_is_rk312x()) {
|
||||
pservice->pd_video = devm_clk_get(pservice->dev, "pd_video");
|
||||
if (IS_ERR(pservice->pd_video)) {
|
||||
dev_err(pservice->dev, "failed on clk_get pd_video\n");
|
||||
@@ -1415,7 +1415,7 @@ static long vpu_service_ioctl(struct file *filp, unsigned int cmd, unsigned long
|
||||
|
||||
return 0;
|
||||
}
|
||||
#if 1
|
||||
|
||||
static int vpu_service_check_hw(vpu_service_info *p, unsigned long hw_addr)
|
||||
{
|
||||
int ret = -EINVAL, i = 0;
|
||||
@@ -1442,7 +1442,6 @@ static int vpu_service_check_hw(vpu_service_info *p, unsigned long hw_addr)
|
||||
iounmap((void *)tmp);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int vpu_service_open(struct inode *inode, struct file *filp)
|
||||
{
|
||||
@@ -1554,7 +1553,9 @@ static int vcodec_probe(struct platform_device *pdev)
|
||||
struct vpu_service_info *pservice = devm_kzalloc(dev, sizeof(struct vpu_service_info), GFP_KERNEL);
|
||||
char *prop = (char*)dev_name(dev);
|
||||
#if defined(CONFIG_VCODEC_MMU)
|
||||
u32 iommu_en = 0;
|
||||
char mmu_dev_dts_name[40];
|
||||
of_property_read_u32(np, "iommu_enabled", &iommu_en);
|
||||
#endif
|
||||
|
||||
pr_info("probe device %s\n", dev_name(dev));
|
||||
@@ -1584,7 +1585,7 @@ static int vcodec_probe(struct platform_device *pdev)
|
||||
pservice->reg_pproc = NULL;
|
||||
atomic_set(&pservice->total_running, 0);
|
||||
pservice->enabled = false;
|
||||
#if defined(CONFIG_VCODEC_MMU)
|
||||
#if defined(CONFIG_VCODEC_MMU)
|
||||
pservice->mmu_dev = NULL;
|
||||
#endif
|
||||
pservice->dev = dev;
|
||||
@@ -1610,7 +1611,7 @@ static int vcodec_probe(struct platform_device *pdev)
|
||||
|
||||
{
|
||||
u32 offset = res->start;
|
||||
if (soc_is_rk3036()) {
|
||||
if (cpu_is_rk3036()) {
|
||||
if (pservice->dev_id == VCODEC_DEVICE_ID_VPU)
|
||||
offset += 0x400;
|
||||
}
|
||||
@@ -1629,7 +1630,7 @@ static int vcodec_probe(struct platform_device *pdev)
|
||||
|
||||
pservice->reg_size = pservice->dec_dev.iosize;
|
||||
|
||||
if (pservice->hw_info->hw_id != HEVC_ID && !soc_is_rk3036()) {
|
||||
if (pservice->hw_info->hw_id != HEVC_ID && !cpu_is_rk3036()) {
|
||||
pservice->enc_dev.iobaseaddr = res->start + pservice->hw_info->enc_offset;
|
||||
pservice->enc_dev.iosize = pservice->hw_info->enc_io_size;
|
||||
|
||||
@@ -1716,23 +1717,26 @@ static int vcodec_probe(struct platform_device *pdev)
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_VCODEC_MMU)
|
||||
pservice->ion_client = rockchip_ion_client_create("vpu");
|
||||
if (IS_ERR(pservice->ion_client)) {
|
||||
dev_err(&pdev->dev, "failed to create ion client for vcodec");
|
||||
return PTR_ERR(pservice->ion_client);
|
||||
} else {
|
||||
dev_info(&pdev->dev, "vcodec ion client create success!\n");
|
||||
}
|
||||
if (iommu_en) {
|
||||
pservice->ion_client = rockchip_ion_client_create("vpu");
|
||||
if (IS_ERR(pservice->ion_client)) {
|
||||
dev_err(&pdev->dev, "failed to create ion client for vcodec");
|
||||
return PTR_ERR(pservice->ion_client);
|
||||
} else {
|
||||
dev_info(&pdev->dev, "vcodec ion client create success!\n");
|
||||
}
|
||||
|
||||
if (pservice->hw_info->hw_id == HEVC_ID)
|
||||
sprintf(mmu_dev_dts_name, "iommu,hevc_mmu");
|
||||
else
|
||||
sprintf(mmu_dev_dts_name, "iommu,vpu_mmu");
|
||||
pservice->mmu_dev = rockchip_get_sysmmu_device_by_compatible(mmu_dev_dts_name);
|
||||
if (pservice->hw_info->hw_id == HEVC_ID)
|
||||
sprintf(mmu_dev_dts_name, "iommu,hevc_mmu");
|
||||
else
|
||||
sprintf(mmu_dev_dts_name, "iommu,vpu_mmu");
|
||||
|
||||
if (pservice->mmu_dev) {
|
||||
platform_set_sysmmu(pservice->mmu_dev, pservice->dev);
|
||||
iovmm_activate(pservice->dev);
|
||||
pservice->mmu_dev = rockchip_get_sysmmu_device_by_compatible(mmu_dev_dts_name);
|
||||
|
||||
if (pservice->mmu_dev) {
|
||||
platform_set_sysmmu(pservice->mmu_dev, pservice->dev);
|
||||
iovmm_activate(pservice->dev);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1844,7 +1848,7 @@ static void get_hw_info(struct vpu_service_info *pservice)
|
||||
|
||||
if (soc_is_rk3190() || soc_is_rk3288())
|
||||
dec->maxDecPicWidth = 4096;
|
||||
else if (soc_is_rk3036() || soc_is_rk3126() || soc_is_rk3128())
|
||||
else if (cpu_is_rk3036() || cpu_is_rk312x())
|
||||
dec->maxDecPicWidth = 1920;
|
||||
else
|
||||
dec->maxDecPicWidth = configReg & 0x07FFU;
|
||||
@@ -1878,7 +1882,7 @@ static void get_hw_info(struct vpu_service_info *pservice)
|
||||
dec->refBufSupport |= 8; /* enable HW support for offset */
|
||||
|
||||
/// invalidate fuse register value in rk319x vpu and following.
|
||||
if (!soc_is_rk3190() && !soc_is_rk3288() && !soc_is_rk3036() && !soc_is_rk3126() && !soc_is_rk3128()) {
|
||||
if (!soc_is_rk3190() && !soc_is_rk3288() && !cpu_is_rk3036() && !cpu_is_rk312x()) {
|
||||
VPUHwFuseStatus_t hwFuseSts;
|
||||
/* Decoder fuse configuration */
|
||||
u32 fuseReg = pservice->dec_dev.hwregs[VPU_DEC_HW_FUSE_CFG];
|
||||
@@ -1995,7 +1999,7 @@ static void get_hw_info(struct vpu_service_info *pservice)
|
||||
}
|
||||
}
|
||||
|
||||
if (!soc_is_rk3036()) {
|
||||
if (!cpu_is_rk3036()) {
|
||||
configReg = pservice->enc_dev.hwregs[63];
|
||||
enc->maxEncodedWidth = configReg & ((1 << 11) - 1);
|
||||
enc->h264Enabled = (configReg >> 27) & 1;
|
||||
@@ -2018,7 +2022,7 @@ static void get_hw_info(struct vpu_service_info *pservice)
|
||||
|
||||
pservice->bug_dec_addr = cpu_is_rk30xx();
|
||||
} else {
|
||||
if (soc_is_rk3036() || soc_is_rk3126() || soc_is_rk3128())
|
||||
if (cpu_is_rk3036() || cpu_is_rk312x())
|
||||
dec->maxDecPicWidth = 1920;
|
||||
else
|
||||
dec->maxDecPicWidth = 4096;
|
||||
|
||||
@@ -1195,7 +1195,7 @@ void iep_config(iep_session *session, IEP_MSG *iep_msg)
|
||||
|
||||
#if defined(CONFIG_IEP_IOMMU)
|
||||
INIT_LIST_HEAD(®->mem_region_list);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//write config
|
||||
iep_config_src_size(iep_msg);
|
||||
@@ -1249,10 +1249,12 @@ void iep_config(iep_session *session, IEP_MSG *iep_msg)
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_IEP_IOMMU)
|
||||
if (0 > iep_reg_address_translate(&iep_service, reg)) {
|
||||
IEP_ERR("error: translate reg address failed\n");
|
||||
kfree(reg);
|
||||
return;
|
||||
if (iep_service.iommu_dev) {
|
||||
if (0 > iep_reg_address_translate(&iep_service, reg)) {
|
||||
IEP_ERR("error: translate reg address failed\n");
|
||||
kfree(reg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -79,11 +79,13 @@ static void iep_reg_deinit(struct iep_reg *reg)
|
||||
#if defined(CONFIG_IEP_IOMMU)
|
||||
struct iep_mem_region *mem_region = NULL, *n;
|
||||
// release memory region attach to this registers table.
|
||||
list_for_each_entry_safe(mem_region, n, ®->mem_region_list, reg_lnk) {
|
||||
ion_unmap_iommu(iep_service.iommu_dev, iep_service.ion_client, mem_region->hdl);
|
||||
ion_free(iep_service.ion_client, mem_region->hdl);
|
||||
list_del_init(&mem_region->reg_lnk);
|
||||
kfree(mem_region);
|
||||
if (iep_service.iommu_dev) {
|
||||
list_for_each_entry_safe(mem_region, n, ®->mem_region_list, reg_lnk) {
|
||||
ion_unmap_iommu(iep_service.iommu_dev, iep_service.ion_client, mem_region->hdl);
|
||||
ion_free(iep_service.ion_client, mem_region->hdl);
|
||||
list_del_init(&mem_region->reg_lnk);
|
||||
kfree(mem_region);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
list_del_init(®->session_link);
|
||||
@@ -797,7 +799,10 @@ static int iep_drv_probe(struct platform_device *pdev)
|
||||
int ret = 0;
|
||||
struct resource *res = NULL;
|
||||
#if defined(CONFIG_IEP_IOMMU)
|
||||
u32 iommu_en = 0;
|
||||
struct device *mmu_dev = NULL;
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
of_property_read_u32(np, "iommu_enabled", &iommu_en);
|
||||
#endif
|
||||
|
||||
data = (struct iep_drvdata*)devm_kzalloc(&pdev->dev, sizeof(struct iep_drvdata), GFP_KERNEL);
|
||||
@@ -884,24 +889,26 @@ static int iep_drv_probe(struct platform_device *pdev)
|
||||
|
||||
#if defined(CONFIG_IEP_IOMMU)
|
||||
iep_service.iommu_dev = NULL;
|
||||
iep_power_on();
|
||||
iep_service.ion_client = rockchip_ion_client_create("iep");
|
||||
if (IS_ERR(iep_service.ion_client)) {
|
||||
IEP_ERR("failed to create ion client for vcodec");
|
||||
return PTR_ERR(iep_service.ion_client);
|
||||
} else {
|
||||
IEP_INFO("iep ion client create success!\n");
|
||||
if (iommu_en) {
|
||||
iep_power_on();
|
||||
iep_service.ion_client = rockchip_ion_client_create("iep");
|
||||
if (IS_ERR(iep_service.ion_client)) {
|
||||
IEP_ERR("failed to create ion client for vcodec");
|
||||
return PTR_ERR(iep_service.ion_client);
|
||||
} else {
|
||||
IEP_INFO("iep ion client create success!\n");
|
||||
}
|
||||
|
||||
mmu_dev = rockchip_get_sysmmu_device_by_compatible("iommu,iep_mmu");
|
||||
|
||||
if (mmu_dev) {
|
||||
platform_set_sysmmu(mmu_dev, &pdev->dev);
|
||||
iovmm_activate(&pdev->dev);
|
||||
}
|
||||
|
||||
iep_service.iommu_dev = &pdev->dev;
|
||||
iep_power_off();
|
||||
}
|
||||
|
||||
mmu_dev = rockchip_get_sysmmu_device_by_compatible("iommu,iep_mmu");
|
||||
|
||||
if (mmu_dev) {
|
||||
platform_set_sysmmu(mmu_dev, &pdev->dev);
|
||||
iovmm_activate(&pdev->dev);
|
||||
}
|
||||
|
||||
iep_service.iommu_dev = &pdev->dev;
|
||||
iep_power_off();
|
||||
#endif
|
||||
|
||||
IEP_INFO("IEP Driver loaded succesfully\n");
|
||||
|
||||
Reference in New Issue
Block a user