mirror of
https://github.com/Fishwaldo/build.git
synced 2025-03-21 22:31:51 +00:00
9484 lines
282 KiB
Diff
9484 lines
282 KiB
Diff
|
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
|
||
|
index 041e15f..67e31ad 100644
|
||
|
--- a/drivers/video/Kconfig
|
||
|
+++ b/drivers/video/Kconfig
|
||
|
@@ -25,6 +25,8 @@ menu "Frame buffer Devices"
|
||
|
source "drivers/video/fbdev/Kconfig"
|
||
|
endmenu
|
||
|
|
||
|
+source "drivers/video/rk_vcodec/Kconfig"
|
||
|
+
|
||
|
source "drivers/video/backlight/Kconfig"
|
||
|
|
||
|
config VGASTATE
|
||
|
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
|
||
|
index 445b2c2..2da42ff 100644
|
||
|
--- a/drivers/video/Makefile
|
||
|
+++ b/drivers/video/Makefile
|
||
|
@@ -4,6 +4,8 @@ obj-$(CONFIG_HDMI) += hdmi.o
|
||
|
obj-$(CONFIG_VT) += console/
|
||
|
obj-$(CONFIG_FB_STI) += console/
|
||
|
obj-$(CONFIG_LOGO) += logo/
|
||
|
+obj-$(CONFIG_RK_VCODEC) += rk_vcodec/
|
||
|
+
|
||
|
obj-y += backlight/
|
||
|
|
||
|
obj-y += fbdev/
|
||
|
diff --git a/drivers/video/rk_vcodec/Kconfig b/drivers/video/rk_vcodec/Kconfig
|
||
|
new file mode 100644
|
||
|
index 0000000..1f86583
|
||
|
--- /dev/null
|
||
|
+++ b/drivers/video/rk_vcodec/Kconfig
|
||
|
@@ -0,0 +1,10 @@
|
||
|
+menu "VCODEC"
|
||
|
+ depends on ARCH_ROCKCHIP
|
||
|
+
|
||
|
+config RK_VCODEC
|
||
|
+ tristate "VCODEC (VPU HEVC) service driver in kernel"
|
||
|
+ depends on ARCH_ROCKCHIP
|
||
|
+ depends on ROCKCHIP_PM_DOMAINS
|
||
|
+ default n
|
||
|
+
|
||
|
+endmenu
|
||
|
diff --git a/drivers/video/rk_vcodec/Makefile b/drivers/video/rk_vcodec/Makefile
|
||
|
new file mode 100644
|
||
|
index 0000000..eb62b77
|
||
|
--- /dev/null
|
||
|
+++ b/drivers/video/rk_vcodec/Makefile
|
||
|
@@ -0,0 +1,8 @@
|
||
|
+ccflags-y += -I${src}/include
|
||
|
+
|
||
|
+rk-vcodec-objs := vcodec_service.o vcodec_iommu_ops.o
|
||
|
+
|
||
|
+rk-vcodec-objs += vcodec_iommu_drm.o
|
||
|
+
|
||
|
+obj-$(CONFIG_RK_VCODEC) += rk-vcodec.o
|
||
|
+
|
||
|
diff --git a/drivers/video/rk_vcodec/README.md b/drivers/video/rk_vcodec/README.md
|
||
|
new file mode 100644
|
||
|
index 0000000..f04f88f
|
||
|
--- /dev/null
|
||
|
+++ b/drivers/video/rk_vcodec/README.md
|
||
|
@@ -0,0 +1,74 @@
|
||
|
+If you appreciate this project, support me on Patreon !
|
||
|
+
|
||
|
+[](https://www.patreon.com/Miouyouyou)
|
||
|
+
|
||
|
+# About
|
||
|
+
|
||
|
+This repository goal is to focus on this Rockchip VPU driver code in
|
||
|
+order to use it with 4.13 kernels and onward.
|
||
|
+
|
||
|
+Most of the code is written by the Rockchip engineers, in the
|
||
|
+[rockchip_forwardports](https://github.com/rockchip-linux/rockchip_forwardports)
|
||
|
+repository initiated by [phh](https://github.com/phhusson), and updated
|
||
|
+by [wzyy2](https://github.com/wzyy2), and in the
|
||
|
+[kernel 4.4 patched and maintained by Rockchip](https://github.com/rockchip-linux/kernel).
|
||
|
+
|
||
|
+[phh](https://github.com/phhusson) took care of making it compilable in
|
||
|
+an Out-Of-Tree fashion.
|
||
|
+
|
||
|
+Currently being tested against
|
||
|
+[RockMyy-Build](https://github.com/Miouyouyou/RockMyy-Build) kernels.
|
||
|
+Note that this might generate crashes and/or freezes in its current
|
||
|
+state.
|
||
|
+
|
||
|
+The kernel patches required to use this driver will be integrated in
|
||
|
+RockMyy and RockMyy-Build this week-end.
|
||
|
+If you're in a hurry, for whatever reason,
|
||
|
+[the patch is here](https://raw.githubusercontent.com/Miouyouyou/MyyQi/master/patches/kernel/v4.11/0012-Export-rockchip_pmu_set_idle_request-for-out-of-tree.patch).
|
||
|
+
|
||
|
+# Compilation
|
||
|
+
|
||
|
+## If you're cross-compiling
|
||
|
+
|
||
|
+If you're cross-compiling this module, first set the `ARCH` and
|
||
|
+`CROSS_COMPILE` variables. If you're compiling from the Rockchip board
|
||
|
+itself, skip this example.
|
||
|
+
|
||
|
+Example :
|
||
|
+
|
||
|
+``bash
|
||
|
+export ARCH=arm
|
||
|
+export CROSS_COMPILE=armv7a-hardfloat-linux-gnueabi-
|
||
|
+``
|
||
|
+
|
||
|
+## Anyway
|
||
|
+
|
||
|
+To compile this module, type the following :
|
||
|
+
|
||
|
+ make M=$PWD -C /path/to/linux/sources CONFIG_RK_VCODEC=m
|
||
|
+
|
||
|
+The command will generate a 'rk-vcodec.ko' file that you can `insmod`
|
||
|
+on the Rockchip board executing the kernel generated from the sources
|
||
|
+you specified.
|
||
|
+
|
||
|
+# Installation
|
||
|
+
|
||
|
+## If you're cross-compiling
|
||
|
+
|
||
|
+Type the following command as **root**
|
||
|
+
|
||
|
+ make INSTALL_PATH=/install_root M=$PWD -C /path/to/linux/sources CONFIG_RK_VCODEC=m
|
||
|
+
|
||
|
+Note that this will install `extra/rk-vcodec.ko`, along with the others
|
||
|
+kernel modules, in `/install_root/lib/modules/kernel_version/kernel`.
|
||
|
+Once you copy the modules directory in the board's `/lib` directory,
|
||
|
+you'll be able to modprobe the module directly from the board.
|
||
|
+
|
||
|
+The kernel will also try to auto-load the module when possible.
|
||
|
+
|
||
|
+## If you're compiling directly
|
||
|
+
|
||
|
+ make M=$PWD -C /path/to/linux/sources CONFIG_RK_VCODEC=m modules_install
|
||
|
+
|
||
|
+The module will then be loaded at boot. You can still load it directly through
|
||
|
+`modprobe rk-vcodec`.
|
||
|
diff --git a/drivers/video/rk_vcodec/config.h b/drivers/video/rk_vcodec/config.h
|
||
|
new file mode 100644
|
||
|
index 0000000..822c053
|
||
|
--- /dev/null
|
||
|
+++ b/drivers/video/rk_vcodec/config.h
|
||
|
@@ -0,0 +1,7 @@
|
||
|
+#ifndef ROCKCHIP_VCODEC_CONFIG_H
|
||
|
+#define ROCKCHIP_VCODEC_CONFIG_H 1
|
||
|
+
|
||
|
+#define CONFIG_DRM 1
|
||
|
+#undef CONFIG_ION
|
||
|
+
|
||
|
+#endif
|
||
|
diff --git a/drivers/video/rk_vcodec/vcodec_hw_info.h b/drivers/video/rk_vcodec/vcodec_hw_info.h
|
||
|
new file mode 100644
|
||
|
index 0000000..a394650
|
||
|
--- /dev/null
|
||
|
+++ b/drivers/video/rk_vcodec/vcodec_hw_info.h
|
||
|
@@ -0,0 +1,240 @@
|
||
|
+/**
|
||
|
+ * Copyright (C) 2015 Fuzhou Rockchip Electronics Co., Ltd
|
||
|
+ * author: Herman Chen herman.chen@rock-chips.com
|
||
|
+ * Alpha Lin, alpha.lin@rock-chips.com
|
||
|
+ *
|
||
|
+ * This software is licensed under the terms of the GNU General Public
|
||
|
+ * License version 2, as published by the Free Software Foundation, and
|
||
|
+ * may be copied, distributed, and modified under those terms.
|
||
|
+ *
|
||
|
+ * 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 __ARCH_ARM_MACH_ROCKCHIP_VCODEC_HW_INFO_H
|
||
|
+#define __ARCH_ARM_MACH_ROCKCHIP_VCODEC_HW_INFO_H
|
||
|
+
|
||
|
+/*
|
||
|
+ * Hardware id is for hardware detection
|
||
|
+ * Driver will read the hardware ID register first, then try to find a mactch
|
||
|
+ * hardware from the enum ID below.
|
||
|
+ */
|
||
|
+enum VPU_HW_ID {
|
||
|
+ VPU_DEC_ID_9190 = 0x6731,
|
||
|
+ VPU_ID_8270 = 0x8270,
|
||
|
+ VPU_ID_4831 = 0x4831,
|
||
|
+ HEVC_ID = 0x6867,
|
||
|
+ RKV_DEC_ID = 0x6876,
|
||
|
+ RKV_DEC_ID2 = 0x3410,
|
||
|
+ VPU2_ID = 0x0000,
|
||
|
+};
|
||
|
+
|
||
|
+/*
|
||
|
+ * Different hardware has different feature. So we catalogue these features
|
||
|
+ * into three class:
|
||
|
+ *
|
||
|
+ * 1. register io feature determined by hardware type
|
||
|
+ * including register offset, register file size, etc
|
||
|
+ *
|
||
|
+ * 2. runtime register config feature determined by task type
|
||
|
+ * including irq / enable / length register, bit mask, etc
|
||
|
+ *
|
||
|
+ * 3. file handle translate feature determined by vcodec format type
|
||
|
+ * register translation map table
|
||
|
+ *
|
||
|
+ * These three type features composite a complete codec information structure
|
||
|
+ */
|
||
|
+
|
||
|
+/* VPU1 and VPU2 */
|
||
|
+#define VCODEC_DEVICE_TYPE_VPUX 0x56505558
|
||
|
+/* VPU Combo */
|
||
|
+#define VCODEC_DEVICE_TYPE_VPUC 0x56505543
|
||
|
+#define VCODEC_DEVICE_TYPE_HEVC 0x56505532
|
||
|
+#define VCODEC_DEVICE_TYPE_RKVD 0x524B5644
|
||
|
+
|
||
|
+enum TASK_TYPE {
|
||
|
+ TASK_ENC,
|
||
|
+ TASK_DEC,
|
||
|
+ TASK_PP,
|
||
|
+ TASK_DEC_PP,
|
||
|
+ TASK_TYPE_BUTT,
|
||
|
+};
|
||
|
+
|
||
|
+enum FORMAT_TYPE {
|
||
|
+ FMT_DEC_BASE = 0,
|
||
|
+ FMT_JPEGD = FMT_DEC_BASE,
|
||
|
+
|
||
|
+ FMT_H263D,
|
||
|
+ FMT_H264D,
|
||
|
+ FMT_H265D,
|
||
|
+
|
||
|
+ FMT_MPEG1D,
|
||
|
+ FMT_MPEG2D,
|
||
|
+ FMT_MPEG4D,
|
||
|
+
|
||
|
+ FMT_VP6D,
|
||
|
+ FMT_VP7D,
|
||
|
+ FMT_VP8D,
|
||
|
+ FMT_VP9D,
|
||
|
+
|
||
|
+ FMT_VC1D,
|
||
|
+ FMT_AVSD,
|
||
|
+
|
||
|
+ FMT_DEC_BUTT,
|
||
|
+
|
||
|
+ FMT_PP_BASE = FMT_DEC_BUTT,
|
||
|
+ FMT_PP = FMT_PP_BASE,
|
||
|
+ FMT_PP_BUTT,
|
||
|
+
|
||
|
+ FMT_ENC_BASE = FMT_PP_BUTT,
|
||
|
+ FMT_JPEGE = FMT_ENC_BASE,
|
||
|
+
|
||
|
+ FMT_H264E,
|
||
|
+
|
||
|
+ FMT_VP8E,
|
||
|
+
|
||
|
+ FMT_ENC_BUTT,
|
||
|
+ FMT_TYPE_BUTT = FMT_ENC_BUTT,
|
||
|
+};
|
||
|
+
|
||
|
+/**
|
||
|
+ * struct for hardware task operation
|
||
|
+ */
|
||
|
+struct vpu_hw_info {
|
||
|
+ enum VPU_HW_ID hw_id;
|
||
|
+ u32 enc_offset;
|
||
|
+ u32 enc_reg_num;
|
||
|
+ u32 enc_io_size;
|
||
|
+
|
||
|
+ u32 dec_offset;
|
||
|
+ u32 dec_reg_num;
|
||
|
+ u32 dec_io_size;
|
||
|
+
|
||
|
+ /*
|
||
|
+ * register range for enc/dec/pp/dec_pp
|
||
|
+ * base/end of dec/pp/dec_pp specify the register range to config
|
||
|
+ */
|
||
|
+ u32 base_dec;
|
||
|
+ u32 base_pp;
|
||
|
+ u32 base_dec_pp;
|
||
|
+ u32 end_dec;
|
||
|
+ u32 end_pp;
|
||
|
+ u32 end_dec_pp;
|
||
|
+};
|
||
|
+
|
||
|
+struct vpu_task_info {
|
||
|
+ char *name;
|
||
|
+ struct timeval start;
|
||
|
+ struct timeval end;
|
||
|
+
|
||
|
+ /*
|
||
|
+ * input stream register
|
||
|
+ * use for map/unmap drm buffer for avoiding
|
||
|
+ * cache sync issue
|
||
|
+ */
|
||
|
+ int reg_rlc;
|
||
|
+ /*
|
||
|
+ * task enable register
|
||
|
+ * use for enable hardware task process
|
||
|
+ * -1 for invalid
|
||
|
+ */
|
||
|
+ int reg_en;
|
||
|
+
|
||
|
+ /* register of task auto gating, alway valid */
|
||
|
+ int reg_gating;
|
||
|
+
|
||
|
+ /* register of task irq, alway valid */
|
||
|
+ int reg_irq;
|
||
|
+
|
||
|
+ /*
|
||
|
+ * stream length register
|
||
|
+ * only valid for decoder task
|
||
|
+ * -1 for invalid (encoder)
|
||
|
+ */
|
||
|
+ int reg_len;
|
||
|
+
|
||
|
+ /*
|
||
|
+ * direct mv register
|
||
|
+ * special offset scale, offset multiply by 16
|
||
|
+ *
|
||
|
+ * valid on vpu & vpu2
|
||
|
+ * -1 for invalid
|
||
|
+ */
|
||
|
+ int reg_dir_mv;
|
||
|
+
|
||
|
+ /*
|
||
|
+ * pps register
|
||
|
+ * special register for scaling list address process
|
||
|
+ *
|
||
|
+ * valid on rkv
|
||
|
+ * -1 for invalid
|
||
|
+ */
|
||
|
+ int reg_pps;
|
||
|
+
|
||
|
+ /*
|
||
|
+ * decoder pipeline mode register
|
||
|
+ *
|
||
|
+ * valid on vpu & vpu2
|
||
|
+ * -1 for invalid
|
||
|
+ */
|
||
|
+ int reg_pipe;
|
||
|
+
|
||
|
+ /* task enable bit mask for enable register */
|
||
|
+ u32 enable_mask;
|
||
|
+
|
||
|
+ /* task auto gating mask for enable register */
|
||
|
+ u32 gating_mask;
|
||
|
+
|
||
|
+ /* task pipeline mode mask for pipe register */
|
||
|
+ u32 pipe_mask;
|
||
|
+
|
||
|
+ /* task inturrpt bit mask for irq register */
|
||
|
+ u32 irq_mask;
|
||
|
+
|
||
|
+ /* task ready bit mask for irq register */
|
||
|
+ u32 ready_mask;
|
||
|
+
|
||
|
+ /* task error bit mask for irq register */
|
||
|
+ u32 error_mask;
|
||
|
+
|
||
|
+ enum FORMAT_TYPE (*get_fmt)(u32 *regs);
|
||
|
+};
|
||
|
+
|
||
|
+struct vpu_trans_info {
|
||
|
+ const int count;
|
||
|
+ const char * const table;
|
||
|
+};
|
||
|
+
|
||
|
+struct vcodec_info {
|
||
|
+ enum VPU_HW_ID hw_id;
|
||
|
+ struct vpu_hw_info *hw_info;
|
||
|
+ struct vpu_task_info *task_info;
|
||
|
+ const struct vpu_trans_info *trans_info;
|
||
|
+};
|
||
|
+
|
||
|
+struct vcodec_device_info {
|
||
|
+ int32_t device_type;
|
||
|
+ int8_t *name;
|
||
|
+};
|
||
|
+
|
||
|
+#define DEF_FMT_TRANS_TBL(fmt, args...) \
|
||
|
+ static const char trans_tbl_##fmt[] = { \
|
||
|
+ args \
|
||
|
+ }
|
||
|
+
|
||
|
+#define SETUP_FMT_TBL(id, fmt) \
|
||
|
+ [id] = { \
|
||
|
+ .count = sizeof(trans_tbl_##fmt), \
|
||
|
+ .table = trans_tbl_##fmt, \
|
||
|
+ }
|
||
|
+
|
||
|
+#define EMPTY_FMT_TBL(id) \
|
||
|
+ [id] = { \
|
||
|
+ .count = 0, \
|
||
|
+ .table = NULL, \
|
||
|
+ }
|
||
|
+
|
||
|
+#endif
|
||
|
diff --git a/drivers/video/rk_vcodec/vcodec_hw_rkv.h b/drivers/video/rk_vcodec/vcodec_hw_rkv.h
|
||
|
new file mode 100644
|
||
|
index 0000000..6839959
|
||
|
--- /dev/null
|
||
|
+++ b/drivers/video/rk_vcodec/vcodec_hw_rkv.h
|
||
|
@@ -0,0 +1,227 @@
|
||
|
+/**
|
||
|
+ * Copyright (C) 2015 Fuzhou Rockchip Electronics Co., Ltd
|
||
|
+ * author: chenhengming chm@rock-chips.com
|
||
|
+ * Alpha Lin, alpha.lin@rock-chips.com
|
||
|
+ *
|
||
|
+ * This software is licensed under the terms of the GNU General Public
|
||
|
+ * License version 2, as published by the Free Software Foundation, and
|
||
|
+ * may be copied, distributed, and modified under those terms.
|
||
|
+ *
|
||
|
+ * 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 __ARCH_ARM_MACH_ROCKCHIP_VCODEC_HW_RKV_H
|
||
|
+#define __ARCH_ARM_MACH_ROCKCHIP_VCODEC_HW_RKV_H
|
||
|
+
|
||
|
+#include "vcodec_hw_info.h"
|
||
|
+
|
||
|
+/* hardware information */
|
||
|
+#define REG_NUM_HEVC_DEC (68)
|
||
|
+#define REG_NUM_RKV_DEC (78)
|
||
|
+
|
||
|
+/* enable and gating register */
|
||
|
+#define RKV_REG_EN_DEC 1
|
||
|
+#define RKV_REG_DEC_GATING_BIT BIT(1)
|
||
|
+
|
||
|
+/* interrupt and error status register */
|
||
|
+#define HEVC_INTERRUPT_REGISTER 1
|
||
|
+#define HEVC_INTERRUPT_BIT BIT(8)
|
||
|
+#define HEVC_DEC_INT_RAW_BIT BIT(9)
|
||
|
+#define HEVC_READY_BIT BIT(12)
|
||
|
+#define HEVC_DEC_BUS_ERROR_BIT BIT(13)
|
||
|
+#define HEVC_DEC_STR_ERROR_BIT BIT(14)
|
||
|
+#define HEVC_DEC_TIMEOUT_BIT BIT(15)
|
||
|
+#define HEVC_DEC_BUFFER_EMPTY_BIT BIT(16)
|
||
|
+#define HEVC_DEC_COLMV_ERROR_BIT BIT(17)
|
||
|
+#define HEVC_DEC_ERR_MASK (HEVC_DEC_BUS_ERROR_BIT \
|
||
|
+ |HEVC_DEC_STR_ERROR_BIT \
|
||
|
+ |HEVC_DEC_TIMEOUT_BIT \
|
||
|
+ |HEVC_DEC_BUFFER_EMPTY_BIT \
|
||
|
+ |HEVC_DEC_COLMV_ERROR_BIT)
|
||
|
+
|
||
|
+#define RKV_DEC_INTERRUPT_REGISTER 1
|
||
|
+#define RKV_DEC_INTERRUPT_BIT BIT(8)
|
||
|
+#define RKV_DEC_INT_RAW_BIT BIT(9)
|
||
|
+#define RKV_DEC_READY_BIT BIT(12)
|
||
|
+#define RKV_DEC_BUS_ERROR_BIT BIT(13)
|
||
|
+#define RKV_DEC_STR_ERROR_BIT BIT(14)
|
||
|
+#define RKV_DEC_TIMEOUT_BIT BIT(15)
|
||
|
+#define RKV_DEC_BUFFER_EMPTY_BIT BIT(16)
|
||
|
+#define RKV_DEC_COLMV_ERROR_BIT BIT(17)
|
||
|
+#define RKV_DEC_ERR_MASK (RKV_DEC_BUS_ERROR_BIT \
|
||
|
+ |RKV_DEC_STR_ERROR_BIT \
|
||
|
+ |RKV_DEC_TIMEOUT_BIT \
|
||
|
+ |RKV_DEC_BUFFER_EMPTY_BIT \
|
||
|
+ |RKV_DEC_COLMV_ERROR_BIT)
|
||
|
+
|
||
|
+static const enum FORMAT_TYPE rkv_dec_fmt_tbl[] = {
|
||
|
+ [0] = FMT_H265D,
|
||
|
+ [1] = FMT_H264D,
|
||
|
+ [2] = FMT_VP9D,
|
||
|
+ [3] = FMT_TYPE_BUTT,
|
||
|
+};
|
||
|
+
|
||
|
+static enum FORMAT_TYPE rkv_dec_get_fmt(u32 *regs)
|
||
|
+{
|
||
|
+ u32 fmt_id = (regs[2] >> 20) & 0x3;
|
||
|
+ enum FORMAT_TYPE type = rkv_dec_fmt_tbl[fmt_id];
|
||
|
+ return type;
|
||
|
+}
|
||
|
+
|
||
|
+static struct vpu_task_info task_rkv[TASK_TYPE_BUTT] = {
|
||
|
+ {
|
||
|
+ .name = "invalid",
|
||
|
+ .reg_en = 0,
|
||
|
+ .reg_irq = 0,
|
||
|
+ .reg_len = 0,
|
||
|
+ .reg_dir_mv = 0,
|
||
|
+ .reg_pps = 0,
|
||
|
+ .reg_pipe = 0,
|
||
|
+ .enable_mask = 0,
|
||
|
+ .gating_mask = 0,
|
||
|
+ .pipe_mask = 0,
|
||
|
+ .irq_mask = 0,
|
||
|
+ .ready_mask = 0,
|
||
|
+ .error_mask = 0,
|
||
|
+ .get_fmt = NULL,
|
||
|
+ },
|
||
|
+ {
|
||
|
+ .name = "rkvdec",
|
||
|
+ .reg_rlc = 4,
|
||
|
+ .reg_en = RKV_REG_EN_DEC,
|
||
|
+ .reg_irq = RKV_DEC_INTERRUPT_REGISTER,
|
||
|
+ .reg_len = 4,
|
||
|
+ .reg_dir_mv = 52,
|
||
|
+ .reg_pps = 42,
|
||
|
+ .reg_pipe = 0,
|
||
|
+ .enable_mask = 0,
|
||
|
+ .gating_mask = RKV_REG_DEC_GATING_BIT,
|
||
|
+ .irq_mask = HEVC_INTERRUPT_BIT,
|
||
|
+ .pipe_mask = 0,
|
||
|
+ .ready_mask = HEVC_READY_BIT,
|
||
|
+ .error_mask = HEVC_DEC_ERR_MASK,
|
||
|
+ .get_fmt = rkv_dec_get_fmt,
|
||
|
+ },
|
||
|
+ {
|
||
|
+ .name = "invalid",
|
||
|
+ .reg_en = 0,
|
||
|
+ .reg_irq = 0,
|
||
|
+ .reg_len = 0,
|
||
|
+ .reg_dir_mv = 0,
|
||
|
+ .reg_pps = 0,
|
||
|
+ .reg_pipe = 0,
|
||
|
+ .enable_mask = 0,
|
||
|
+ .gating_mask = 0,
|
||
|
+ .pipe_mask = 0,
|
||
|
+ .irq_mask = 0,
|
||
|
+ .ready_mask = 0,
|
||
|
+ .error_mask = 0,
|
||
|
+ .get_fmt = NULL,
|
||
|
+ },
|
||
|
+ {
|
||
|
+ .name = "invalid",
|
||
|
+ .reg_en = 0,
|
||
|
+ .reg_irq = 0,
|
||
|
+ .reg_len = 0,
|
||
|
+ .reg_dir_mv = 0,
|
||
|
+ .reg_pps = 0,
|
||
|
+ .reg_pipe = 0,
|
||
|
+ .enable_mask = 0,
|
||
|
+ .gating_mask = 0,
|
||
|
+ .pipe_mask = 0,
|
||
|
+ .irq_mask = 0,
|
||
|
+ .ready_mask = 0,
|
||
|
+ .error_mask = 0,
|
||
|
+ .get_fmt = NULL,
|
||
|
+ },};
|
||
|
+
|
||
|
+static struct vpu_hw_info hw_rkhevc = {
|
||
|
+ .hw_id = HEVC_ID,
|
||
|
+
|
||
|
+ .enc_offset = 0,
|
||
|
+ .enc_reg_num = 0,
|
||
|
+ .enc_io_size = 0,
|
||
|
+
|
||
|
+ .dec_offset = 0,
|
||
|
+ .dec_reg_num = REG_NUM_HEVC_DEC,
|
||
|
+ .dec_io_size = REG_NUM_HEVC_DEC * 4,
|
||
|
+
|
||
|
+ /* NOTE: can not write to register 0 */
|
||
|
+ .base_dec = 1,
|
||
|
+ .base_pp = 0,
|
||
|
+ .base_dec_pp = 0,
|
||
|
+ .end_dec = REG_NUM_HEVC_DEC,
|
||
|
+ .end_pp = 0,
|
||
|
+ .end_dec_pp = 0,
|
||
|
+};
|
||
|
+
|
||
|
+static struct vpu_hw_info hw_rkvdec = {
|
||
|
+ .hw_id = RKV_DEC_ID,
|
||
|
+
|
||
|
+ .enc_offset = 0,
|
||
|
+ .enc_reg_num = 0,
|
||
|
+ .enc_io_size = 0,
|
||
|
+
|
||
|
+ .dec_offset = 0x0,
|
||
|
+ .dec_reg_num = REG_NUM_RKV_DEC,
|
||
|
+ .dec_io_size = REG_NUM_RKV_DEC * 4,
|
||
|
+
|
||
|
+ /* NOTE: can not write to register 0 */
|
||
|
+ .base_dec = 1,
|
||
|
+ .base_pp = 0,
|
||
|
+ .base_dec_pp = 0,
|
||
|
+ .end_dec = REG_NUM_RKV_DEC,
|
||
|
+ .end_pp = 0,
|
||
|
+ .end_dec_pp = 0,
|
||
|
+};
|
||
|
+
|
||
|
+/*
|
||
|
+ * file handle translate information
|
||
|
+ */
|
||
|
+DEF_FMT_TRANS_TBL(rkv_h264d,
|
||
|
+ 4, 6, 7, 10, 11, 12, 13, 14,
|
||
|
+ 15, 16, 17, 18, 19, 20, 21, 22,
|
||
|
+ 23, 24, 41, 42, 43, 48, 75
|
||
|
+);
|
||
|
+
|
||
|
+DEF_FMT_TRANS_TBL(rkv_h265d,
|
||
|
+ 4, 6, 7, 10, 11, 12, 13, 14,
|
||
|
+ 15, 16, 17, 18, 19, 20, 21, 22,
|
||
|
+ 23, 24, 42, 43
|
||
|
+);
|
||
|
+
|
||
|
+DEF_FMT_TRANS_TBL(rkv_vp9d,
|
||
|
+ 4, 6, 7, 11, 12, 13, 14, 15,
|
||
|
+ 16, 52
|
||
|
+);
|
||
|
+
|
||
|
+const struct vpu_trans_info trans_rkv[FMT_TYPE_BUTT] = {
|
||
|
+ EMPTY_FMT_TBL(FMT_JPEGD),
|
||
|
+ EMPTY_FMT_TBL(FMT_H263D),
|
||
|
+ SETUP_FMT_TBL(FMT_H264D , rkv_h264d),
|
||
|
+ SETUP_FMT_TBL(FMT_H265D , rkv_h265d),
|
||
|
+
|
||
|
+ EMPTY_FMT_TBL(FMT_MPEG1D),
|
||
|
+ EMPTY_FMT_TBL(FMT_MPEG2D),
|
||
|
+ EMPTY_FMT_TBL(FMT_MPEG4D),
|
||
|
+
|
||
|
+ EMPTY_FMT_TBL(FMT_VP6D),
|
||
|
+ EMPTY_FMT_TBL(FMT_VP7D),
|
||
|
+ EMPTY_FMT_TBL(FMT_VP8D),
|
||
|
+ SETUP_FMT_TBL(FMT_VP9D , rkv_vp9d),
|
||
|
+
|
||
|
+ EMPTY_FMT_TBL(FMT_PP),
|
||
|
+
|
||
|
+ EMPTY_FMT_TBL(FMT_VC1D),
|
||
|
+ EMPTY_FMT_TBL(FMT_AVSD),
|
||
|
+
|
||
|
+ EMPTY_FMT_TBL(FMT_JPEGE),
|
||
|
+ EMPTY_FMT_TBL(FMT_H264E),
|
||
|
+ EMPTY_FMT_TBL(FMT_VP8E),
|
||
|
+};
|
||
|
+
|
||
|
+#endif
|
||
|
diff --git a/drivers/video/rk_vcodec/vcodec_hw_vpu.h b/drivers/video/rk_vcodec/vcodec_hw_vpu.h
|
||
|
new file mode 100644
|
||
|
index 0000000..ae771b6
|
||
|
--- /dev/null
|
||
|
+++ b/drivers/video/rk_vcodec/vcodec_hw_vpu.h
|
||
|
@@ -0,0 +1,325 @@
|
||
|
+/**
|
||
|
+ * Copyright (C) 2015 Fuzhou Rockchip Electronics Co., Ltd
|
||
|
+ * author: chenhengming chm@rock-chips.com
|
||
|
+ * Alpha Lin, alpha.lin@rock-chips.com
|
||
|
+ *
|
||
|
+ * This software is licensed under the terms of the GNU General Public
|
||
|
+ * License version 2, as published by the Free Software Foundation, and
|
||
|
+ * may be copied, distributed, and modified under those terms.
|
||
|
+ *
|
||
|
+ * 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 __ARCH_ARM_MACH_ROCKCHIP_VCODEC_HW_VPU_H
|
||
|
+#define __ARCH_ARM_MACH_ROCKCHIP_VCODEC_HW_VPU_H
|
||
|
+
|
||
|
+#include "vcodec_hw_info.h"
|
||
|
+
|
||
|
+/* hardware information */
|
||
|
+#define REG_NUM_9190_DEC (60)
|
||
|
+#define REG_NUM_9190_PP (41)
|
||
|
+#define REG_NUM_9190_DEC_PP (REG_NUM_9190_DEC + REG_NUM_9190_PP)
|
||
|
+
|
||
|
+#define REG_NUM_DEC_PP (REG_NUM_9190_DEC + REG_NUM_9190_PP)
|
||
|
+
|
||
|
+#define REG_NUM_ENC_8270 (96)
|
||
|
+#define REG_SIZE_ENC_8270 (0x200)
|
||
|
+#define REG_NUM_ENC_4831 (164)
|
||
|
+#define REG_SIZE_ENC_4831 (0x400)
|
||
|
+
|
||
|
+
|
||
|
+/* enable and gating register */
|
||
|
+#define VPU_REG_EN_ENC 14
|
||
|
+#define VPU_REG_ENC_GATE 2
|
||
|
+#define VPU_REG_ENC_GATE_BIT BIT(4)
|
||
|
+
|
||
|
+#define VPU_REG_EN_DEC 1
|
||
|
+#define VPU_REG_DEC_GATE 2
|
||
|
+#define VPU_REG_DEC_GATE_BIT BIT(10)
|
||
|
+#define VPU_REG_EN_PP 0
|
||
|
+#define VPU_REG_PP_GATE 1
|
||
|
+#define VPU_REG_PP_GATE_BIT BIT(8)
|
||
|
+#define VPU_REG_EN_DEC_PP 1
|
||
|
+#define VPU_REG_DEC_PP_GATE 61
|
||
|
+#define VPU_REG_DEC_PP_GATE_BIT BIT(8)
|
||
|
+
|
||
|
+/* interrupt and error status register */
|
||
|
+#define VPU_DEC_INTERRUPT_REGISTER 1
|
||
|
+#define VPU_DEC_INTERRUPT_BIT BIT(8)
|
||
|
+#define VPU_DEC_READY_BIT BIT(12)
|
||
|
+#define VPU_DEC_BUS_ERROR_BIT BIT(13)
|
||
|
+#define VPU_DEC_BUFFER_EMPTY_BIT BIT(14)
|
||
|
+#define VPU_DEC_ASO_ERROR_BIT BIT(15)
|
||
|
+#define VPU_DEC_STREAM_ERROR_BIT BIT(16)
|
||
|
+#define VPU_DEC_SLICE_DONE_BIT BIT(17)
|
||
|
+#define VPU_DEC_TIMEOUT_BIT BIT(18)
|
||
|
+#define VPU_DEC_ERR_MASK (VPU_DEC_BUS_ERROR_BIT \
|
||
|
+ |VPU_DEC_BUFFER_EMPTY_BIT \
|
||
|
+ |VPU_DEC_STREAM_ERROR_BIT \
|
||
|
+ |VPU_DEC_TIMEOUT_BIT)
|
||
|
+
|
||
|
+#define VPU_PP_INTERRUPT_REGISTER 60
|
||
|
+#define VPU_PP_PIPELINE_MODE_BIT BIT(1)
|
||
|
+#define VPU_PP_INTERRUPT_BIT BIT(8)
|
||
|
+#define VPU_PP_READY_BIT BIT(12)
|
||
|
+#define VPU_PP_BUS_ERROR_BIT BIT(13)
|
||
|
+#define VPU_PP_ERR_MASK VPU_PP_BUS_ERROR_BIT
|
||
|
+
|
||
|
+#define VPU_ENC_INTERRUPT_REGISTER 1
|
||
|
+#define VPU_ENC_INTERRUPT_BIT BIT(0)
|
||
|
+#define VPU_ENC_READY_BIT BIT(2)
|
||
|
+#define VPU_ENC_BUS_ERROR_BIT BIT(3)
|
||
|
+#define VPU_ENC_BUFFER_FULL_BIT BIT(5)
|
||
|
+#define VPU_ENC_TIMEOUT_BIT BIT(6)
|
||
|
+#define VPU_ENC_ERR_MASK (VPU_ENC_BUS_ERROR_BIT \
|
||
|
+ |VPU_ENC_BUFFER_FULL_BIT \
|
||
|
+ |VPU_ENC_TIMEOUT_BIT)
|
||
|
+
|
||
|
+static const enum FORMAT_TYPE vpu_dec_fmt_tbl[] = {
|
||
|
+ [0] = FMT_H264D,
|
||
|
+ [1] = FMT_MPEG4D,
|
||
|
+ [2] = FMT_H263D,
|
||
|
+ [3] = FMT_JPEGD,
|
||
|
+ [4] = FMT_VC1D,
|
||
|
+ [5] = FMT_MPEG2D,
|
||
|
+ [6] = FMT_MPEG1D,
|
||
|
+ [7] = FMT_VP6D,
|
||
|
+ [8] = FMT_TYPE_BUTT,
|
||
|
+ [9] = FMT_VP7D,
|
||
|
+ [10] = FMT_VP8D,
|
||
|
+ [11] = FMT_AVSD,
|
||
|
+ [12] = FMT_TYPE_BUTT,
|
||
|
+ [13] = FMT_TYPE_BUTT,
|
||
|
+ [14] = FMT_TYPE_BUTT,
|
||
|
+ [15] = FMT_TYPE_BUTT,
|
||
|
+};
|
||
|
+
|
||
|
+static enum FORMAT_TYPE vpu_dec_get_fmt(u32 *regs)
|
||
|
+{
|
||
|
+ u32 fmt_id = (regs[3] >> 28) & 0xf;
|
||
|
+ enum FORMAT_TYPE type = vpu_dec_fmt_tbl[fmt_id];
|
||
|
+ return type;
|
||
|
+}
|
||
|
+
|
||
|
+static enum FORMAT_TYPE vpu_pp_get_fmt(u32 *regs)
|
||
|
+{
|
||
|
+ return FMT_PP;
|
||
|
+}
|
||
|
+
|
||
|
+static const enum FORMAT_TYPE vpu_enc_fmt_tbl[] = {
|
||
|
+ [0] = FMT_TYPE_BUTT,
|
||
|
+ [1] = FMT_VP8E,
|
||
|
+ [2] = FMT_JPEGE,
|
||
|
+ [3] = FMT_H264E,
|
||
|
+};
|
||
|
+
|
||
|
+static enum FORMAT_TYPE vpu_enc_get_fmt(u32 *regs)
|
||
|
+{
|
||
|
+ u32 fmt_id = (regs[VPU_REG_EN_ENC] >> 1) & 0x3;
|
||
|
+ enum FORMAT_TYPE type = vpu_enc_fmt_tbl[fmt_id];
|
||
|
+ return type;
|
||
|
+}
|
||
|
+
|
||
|
+static struct vpu_task_info task_vpu[TASK_TYPE_BUTT] = {
|
||
|
+ {
|
||
|
+ .name = "vpu_enc",
|
||
|
+ .reg_rlc = 11,
|
||
|
+ .reg_en = VPU_REG_EN_ENC,
|
||
|
+ .reg_irq = VPU_ENC_INTERRUPT_REGISTER,
|
||
|
+ .reg_len = -1,
|
||
|
+ .reg_dir_mv = -1,
|
||
|
+ .reg_pps = -1,
|
||
|
+ .reg_pipe = -1,
|
||
|
+ .enable_mask = 0x6,
|
||
|
+ .gating_mask = 0,
|
||
|
+ .pipe_mask = 0,
|
||
|
+ .irq_mask = VPU_ENC_INTERRUPT_BIT,
|
||
|
+ .ready_mask = VPU_ENC_READY_BIT,
|
||
|
+ .error_mask = VPU_ENC_ERR_MASK,
|
||
|
+ .get_fmt = vpu_enc_get_fmt,
|
||
|
+ },
|
||
|
+ {
|
||
|
+ .name = "vpu_dec",
|
||
|
+ .reg_rlc = 12,
|
||
|
+ .reg_en = VPU_REG_EN_DEC,
|
||
|
+ .reg_irq = VPU_DEC_INTERRUPT_REGISTER,
|
||
|
+ .reg_len = 12,
|
||
|
+ .reg_dir_mv = 41,
|
||
|
+ .reg_pps = -1,
|
||
|
+ .reg_pipe = VPU_PP_INTERRUPT_REGISTER,
|
||
|
+ .enable_mask = 0,
|
||
|
+ .gating_mask = 0,
|
||
|
+ .pipe_mask = VPU_PP_PIPELINE_MODE_BIT,
|
||
|
+ .irq_mask = VPU_DEC_INTERRUPT_BIT,
|
||
|
+ .ready_mask = VPU_DEC_READY_BIT,
|
||
|
+ .error_mask = VPU_DEC_ERR_MASK,
|
||
|
+ .get_fmt = vpu_dec_get_fmt,
|
||
|
+ },
|
||
|
+ {
|
||
|
+ .name = "vpu_pp",
|
||
|
+ .reg_en = VPU_REG_EN_PP,
|
||
|
+ .reg_irq = VPU_PP_INTERRUPT_REGISTER,
|
||
|
+ .reg_len = -1,
|
||
|
+ .reg_dir_mv = -1,
|
||
|
+ .reg_pps = -1,
|
||
|
+ .reg_pipe = VPU_PP_INTERRUPT_REGISTER,
|
||
|
+ .enable_mask = 0,
|
||
|
+ .gating_mask = 0,
|
||
|
+ .pipe_mask = VPU_PP_PIPELINE_MODE_BIT,
|
||
|
+ .irq_mask = VPU_PP_INTERRUPT_BIT,
|
||
|
+ .ready_mask = VPU_PP_READY_BIT,
|
||
|
+ .error_mask = VPU_PP_ERR_MASK,
|
||
|
+ .get_fmt = vpu_pp_get_fmt,
|
||
|
+ },
|
||
|
+ {
|
||
|
+ .name = "vpu_dec_pp",
|
||
|
+ .reg_rlc = 12,
|
||
|
+ .reg_en = VPU_REG_EN_DEC,
|
||
|
+ .reg_irq = VPU_DEC_INTERRUPT_REGISTER,
|
||
|
+ .reg_len = 12,
|
||
|
+ .reg_dir_mv = 41,
|
||
|
+ .reg_pps = -1,
|
||
|
+ .reg_pipe = VPU_PP_INTERRUPT_REGISTER,
|
||
|
+ .enable_mask = 0,
|
||
|
+ .gating_mask = 0,
|
||
|
+ .pipe_mask = VPU_PP_PIPELINE_MODE_BIT,
|
||
|
+ .irq_mask = VPU_DEC_INTERRUPT_BIT,
|
||
|
+ .ready_mask = VPU_DEC_READY_BIT,
|
||
|
+ .error_mask = VPU_DEC_ERR_MASK,
|
||
|
+ .get_fmt = vpu_dec_get_fmt,
|
||
|
+ },
|
||
|
+};
|
||
|
+
|
||
|
+static struct vpu_hw_info hw_vpu_8270 = {
|
||
|
+ .hw_id = VPU_ID_8270,
|
||
|
+
|
||
|
+ .enc_offset = 0x0,
|
||
|
+ .enc_reg_num = REG_NUM_ENC_8270,
|
||
|
+ .enc_io_size = REG_NUM_ENC_8270 * 4,
|
||
|
+
|
||
|
+ .dec_offset = REG_SIZE_ENC_8270,
|
||
|
+ .dec_reg_num = REG_NUM_9190_DEC_PP,
|
||
|
+ .dec_io_size = REG_NUM_9190_DEC_PP * 4,
|
||
|
+
|
||
|
+ .base_dec = 0,
|
||
|
+ .base_pp = VPU_PP_INTERRUPT_REGISTER,
|
||
|
+ .base_dec_pp = 0,
|
||
|
+ .end_dec = REG_NUM_9190_DEC,
|
||
|
+ .end_pp = REG_NUM_9190_DEC_PP,
|
||
|
+ .end_dec_pp = REG_NUM_9190_DEC_PP,
|
||
|
+};
|
||
|
+
|
||
|
+static struct vpu_hw_info hw_vpu_4831 = {
|
||
|
+ .hw_id = VPU_ID_4831,
|
||
|
+
|
||
|
+ .enc_offset = 0x0,
|
||
|
+ .enc_reg_num = REG_NUM_ENC_4831,
|
||
|
+ .enc_io_size = REG_NUM_ENC_4831 * 4,
|
||
|
+
|
||
|
+ .dec_offset = REG_SIZE_ENC_4831,
|
||
|
+ .dec_reg_num = REG_NUM_9190_DEC_PP,
|
||
|
+ .dec_io_size = REG_NUM_9190_DEC_PP * 4,
|
||
|
+
|
||
|
+ .base_dec = 0,
|
||
|
+ .base_pp = VPU_PP_INTERRUPT_REGISTER,
|
||
|
+ .base_dec_pp = 0,
|
||
|
+ .end_dec = REG_NUM_9190_DEC,
|
||
|
+ .end_pp = REG_NUM_9190_DEC_PP,
|
||
|
+ .end_dec_pp = REG_NUM_9190_DEC_PP,
|
||
|
+};
|
||
|
+
|
||
|
+static struct vpu_hw_info hw_vpu_9190 = {
|
||
|
+ .hw_id = VPU_DEC_ID_9190,
|
||
|
+
|
||
|
+ .enc_offset = 0x0,
|
||
|
+ .enc_reg_num = 0,
|
||
|
+ .enc_io_size = 0,
|
||
|
+
|
||
|
+ .dec_offset = 0,
|
||
|
+ .dec_reg_num = REG_NUM_9190_DEC_PP,
|
||
|
+ .dec_io_size = REG_NUM_9190_DEC_PP * 4,
|
||
|
+
|
||
|
+ .base_dec = 0,
|
||
|
+ .base_pp = VPU_PP_INTERRUPT_REGISTER,
|
||
|
+ .base_dec_pp = 0,
|
||
|
+ .end_dec = REG_NUM_9190_DEC,
|
||
|
+ .end_pp = REG_NUM_9190_DEC_PP,
|
||
|
+ .end_dec_pp = REG_NUM_9190_DEC_PP,
|
||
|
+};
|
||
|
+
|
||
|
+/*
|
||
|
+ * file handle translate information
|
||
|
+ */
|
||
|
+DEF_FMT_TRANS_TBL(vpu_jpegd,
|
||
|
+ 12, 13, 14, 40, 66, 67
|
||
|
+);
|
||
|
+
|
||
|
+DEF_FMT_TRANS_TBL(vpu_h264d,
|
||
|
+ 12, 13, 14, 15, 16, 17, 18, 19,
|
||
|
+ 20, 21, 22, 23, 24, 25, 26, 27,
|
||
|
+ 28, 29, 40, 41
|
||
|
+);
|
||
|
+
|
||
|
+DEF_FMT_TRANS_TBL(vpu_vp6d,
|
||
|
+ 12, 13, 14, 18, 27, 40
|
||
|
+);
|
||
|
+
|
||
|
+DEF_FMT_TRANS_TBL(vpu_vp8d,
|
||
|
+ 10, 12, 13, 14, 18, 19, 22, 23,
|
||
|
+ 24, 25, 26, 27, 28, 29, 40
|
||
|
+);
|
||
|
+
|
||
|
+DEF_FMT_TRANS_TBL(vpu_vc1d,
|
||
|
+ 12, 13, 14, 15, 16, 17, 27, 41
|
||
|
+);
|
||
|
+
|
||
|
+DEF_FMT_TRANS_TBL(vpu_avsd,
|
||
|
+ 12, 13, 14, 15, 16, 17, 40, 41, 45
|
||
|
+);
|
||
|
+
|
||
|
+DEF_FMT_TRANS_TBL(vpu_defaultd,
|
||
|
+ 12, 13, 14, 15, 16, 17, 40, 41
|
||
|
+);
|
||
|
+
|
||
|
+DEF_FMT_TRANS_TBL(vpu_default_pp,
|
||
|
+ 63, 64, 65, 66, 67, 73, 74
|
||
|
+);
|
||
|
+
|
||
|
+DEF_FMT_TRANS_TBL(vpu_vp8e,
|
||
|
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, 17, 26, 51, 52, 58, 59
|
||
|
+);
|
||
|
+
|
||
|
+DEF_FMT_TRANS_TBL(vpu_defaulte,
|
||
|
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 51
|
||
|
+);
|
||
|
+
|
||
|
+static const struct vpu_trans_info trans_vpu[FMT_TYPE_BUTT] = {
|
||
|
+ SETUP_FMT_TBL(FMT_JPEGD, vpu_jpegd),
|
||
|
+ SETUP_FMT_TBL(FMT_H263D, vpu_defaultd),
|
||
|
+ SETUP_FMT_TBL(FMT_H264D, vpu_h264d),
|
||
|
+ EMPTY_FMT_TBL(FMT_H265D),
|
||
|
+
|
||
|
+ SETUP_FMT_TBL(FMT_MPEG1D, vpu_defaultd),
|
||
|
+ SETUP_FMT_TBL(FMT_MPEG2D, vpu_defaultd),
|
||
|
+ SETUP_FMT_TBL(FMT_MPEG4D, vpu_defaultd),
|
||
|
+
|
||
|
+ SETUP_FMT_TBL(FMT_VP6D, vpu_vp6d),
|
||
|
+ SETUP_FMT_TBL(FMT_VP7D, vpu_defaultd),
|
||
|
+ SETUP_FMT_TBL(FMT_VP8D, vpu_vp8d),
|
||
|
+ EMPTY_FMT_TBL(FMT_VP9D),
|
||
|
+
|
||
|
+ SETUP_FMT_TBL(FMT_VC1D, vpu_vc1d),
|
||
|
+ SETUP_FMT_TBL(FMT_AVSD, vpu_avsd),
|
||
|
+
|
||
|
+ SETUP_FMT_TBL(FMT_PP, vpu_default_pp),
|
||
|
+
|
||
|
+ SETUP_FMT_TBL(FMT_JPEGE, vpu_defaulte),
|
||
|
+ SETUP_FMT_TBL(FMT_H264E, vpu_defaulte),
|
||
|
+ SETUP_FMT_TBL(FMT_VP8E, vpu_vp8e),
|
||
|
+};
|
||
|
+
|
||
|
+#endif
|
||
|
diff --git a/drivers/video/rk_vcodec/vcodec_hw_vpu2.h b/drivers/video/rk_vcodec/vcodec_hw_vpu2.h
|
||
|
new file mode 100644
|
||
|
index 0000000..86c1e16
|
||
|
--- /dev/null
|
||
|
+++ b/drivers/video/rk_vcodec/vcodec_hw_vpu2.h
|
||
|
@@ -0,0 +1,278 @@
|
||
|
+/**
|
||
|
+ * Copyright (C) 2015 Fuzhou Rockchip Electronics Co., Ltd
|
||
|
+ * author: chenhengming chm@rock-chips.com
|
||
|
+ * Alpha Lin, alpha.lin@rock-chips.com
|
||
|
+ *
|
||
|
+ * This software is licensed under the terms of the GNU General Public
|
||
|
+ * License version 2, as published by the Free Software Foundation, and
|
||
|
+ * may be copied, distributed, and modified under those terms.
|
||
|
+ *
|
||
|
+ * 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 __ARCH_ARM_MACH_ROCKCHIP_VCODEC_HW_VPU2_H
|
||
|
+#define __ARCH_ARM_MACH_ROCKCHIP_VCODEC_HW_VPU2_H
|
||
|
+
|
||
|
+#include "vcodec_hw_info.h"
|
||
|
+
|
||
|
+/* hardware information */
|
||
|
+#define REG_NUM_VPU2_DEC (159)
|
||
|
+#define REG_NUM_VPU2_DEC_START (50)
|
||
|
+#define REG_NUM_VPU2_DEC_END (159)
|
||
|
+#define REG_NUM_VPU2_PP (41)
|
||
|
+#define REG_NUM_VPU2_DEC_PP (159)
|
||
|
+#define REG_NUM_VPU2_ENC (184)
|
||
|
+#define REG_NUM_VPU2_DEC_OFFSET (0x400)
|
||
|
+
|
||
|
+/* enable and gating register */
|
||
|
+#define VPU2_REG_EN_ENC 103
|
||
|
+#define VPU2_REG_ENC_GATE 109
|
||
|
+#define VPU2_REG_ENC_GATE_BIT BIT(4)
|
||
|
+
|
||
|
+#define VPU2_REG_EN_DEC 57
|
||
|
+#define VPU2_REG_DEC_GATE 57
|
||
|
+#define VPU2_REG_DEC_GATE_BIT BIT(4)
|
||
|
+#define VPU2_REG_EN_PP 41
|
||
|
+#define VPU2_REG_PP_GATE 1
|
||
|
+#define VPU2_REG_PP_GATE_BIT BIT(8)
|
||
|
+#define VPU2_REG_EN_DEC_PP 57
|
||
|
+#define VPU2_REG_DEC_PP_GATE 57
|
||
|
+#define VPU2_REG_DEC_PP_GATE_BIT BIT(4)
|
||
|
+
|
||
|
+/* interrupt and error status register */
|
||
|
+#define VPU2_DEC_INTERRUPT_REGISTER 55
|
||
|
+#define VPU2_DEC_INTERRUPT_BIT BIT(0)
|
||
|
+#define VPU2_DEC_READY_BIT BIT(4)
|
||
|
+#define VPU2_DEC_BUS_ERROR_BIT BIT(5)
|
||
|
+#define VPU2_DEC_BUFFER_EMPTY_BIT BIT(6)
|
||
|
+#define VPU2_DEC_ASO_ERROR_BIT BIT(8)
|
||
|
+#define VPU2_DEC_SLICE_DONE_BIT BIT(9)
|
||
|
+#define VPU2_DEC_STREAM_ERROR_BIT BIT(12)
|
||
|
+#define VPU2_DEC_TIMEOUT_BIT BIT(13)
|
||
|
+#define VPU2_DEC_ERR_MASK (VPU2_DEC_BUS_ERROR_BIT \
|
||
|
+ |VPU2_DEC_BUFFER_EMPTY_BIT \
|
||
|
+ |VPU2_DEC_STREAM_ERROR_BIT \
|
||
|
+ |VPU2_DEC_TIMEOUT_BIT)
|
||
|
+
|
||
|
+#define VPU2_PP_INTERRUPT_REGISTER 40
|
||
|
+#define VPU2_PP_INTERRUPT_BIT BIT(0)
|
||
|
+#define VPU2_PP_READY_BIT BIT(2)
|
||
|
+#define VPU2_PP_BUS_ERROR_BIT BIT(3)
|
||
|
+#define VPU2_PP_ERR_MASK VPU2_PP_BUS_ERROR_BIT
|
||
|
+#define VPU2_PP_PIPELINE_REGISTER 41
|
||
|
+#define VPU2_PP_PIPELINE_MODE_BIT BIT(4)
|
||
|
+
|
||
|
+#define VPU2_ENC_INTERRUPT_REGISTER 109
|
||
|
+#define VPU2_ENC_INTERRUPT_BIT BIT(0)
|
||
|
+#define VPU2_ENC_READY_BIT BIT(1)
|
||
|
+#define VPU2_ENC_BUS_ERROR_BIT BIT(4)
|
||
|
+#define VPU2_ENC_BUFFER_FULL_BIT BIT(5)
|
||
|
+#define VPU2_ENC_TIMEOUT_BIT BIT(6)
|
||
|
+#define VPU2_ENC_ERR_MASK (VPU2_ENC_BUS_ERROR_BIT \
|
||
|
+ |VPU2_ENC_BUFFER_FULL_BIT \
|
||
|
+ |VPU2_ENC_TIMEOUT_BIT)
|
||
|
+
|
||
|
+static const enum FORMAT_TYPE vpu2_dec_fmt_tbl[] = {
|
||
|
+ [0] = FMT_H264D,
|
||
|
+ [1] = FMT_MPEG4D,
|
||
|
+ [2] = FMT_H263D,
|
||
|
+ [3] = FMT_JPEGD,
|
||
|
+ [4] = FMT_VC1D,
|
||
|
+ [5] = FMT_MPEG2D,
|
||
|
+ [6] = FMT_MPEG1D,
|
||
|
+ [7] = FMT_VP6D,
|
||
|
+ [8] = FMT_TYPE_BUTT,
|
||
|
+ [9] = FMT_VP7D,
|
||
|
+ [10] = FMT_VP8D,
|
||
|
+ [11] = FMT_AVSD,
|
||
|
+ [12] = FMT_TYPE_BUTT,
|
||
|
+ [13] = FMT_TYPE_BUTT,
|
||
|
+ [14] = FMT_TYPE_BUTT,
|
||
|
+ [15] = FMT_TYPE_BUTT,
|
||
|
+};
|
||
|
+
|
||
|
+static enum FORMAT_TYPE vpu2_dec_get_fmt(u32 *regs)
|
||
|
+{
|
||
|
+ u32 fmt_id = regs[53] & 0xf;
|
||
|
+ enum FORMAT_TYPE type = vpu2_dec_fmt_tbl[fmt_id];
|
||
|
+ return type;
|
||
|
+}
|
||
|
+
|
||
|
+static enum FORMAT_TYPE vpu2_pp_get_fmt(u32 *regs)
|
||
|
+{
|
||
|
+ return FMT_PP;
|
||
|
+}
|
||
|
+
|
||
|
+static const enum FORMAT_TYPE vpu2_enc_fmt_tbl[] = {
|
||
|
+ [0] = FMT_TYPE_BUTT,
|
||
|
+ [1] = FMT_VP8E,
|
||
|
+ [2] = FMT_JPEGE,
|
||
|
+ [3] = FMT_H264E,
|
||
|
+};
|
||
|
+
|
||
|
+static enum FORMAT_TYPE vpu2_enc_get_fmt(u32 *regs)
|
||
|
+{
|
||
|
+ u32 fmt_id = (regs[VPU2_REG_EN_ENC] >> 4) & 0x3;
|
||
|
+ enum FORMAT_TYPE type = vpu2_enc_fmt_tbl[fmt_id];
|
||
|
+ return type;
|
||
|
+}
|
||
|
+
|
||
|
+static struct vpu_task_info task_vpu2[TASK_TYPE_BUTT] = {
|
||
|
+ {
|
||
|
+ .name = "vpu2_enc",
|
||
|
+ .reg_rlc = 48,
|
||
|
+ .reg_en = VPU2_REG_EN_ENC,
|
||
|
+ .reg_gating = VPU2_REG_ENC_GATE,
|
||
|
+ .reg_irq = VPU2_ENC_INTERRUPT_REGISTER,
|
||
|
+ .reg_len = -1,
|
||
|
+ .reg_dir_mv = -1,
|
||
|
+ .reg_pps = -1,
|
||
|
+ .reg_pipe = -1,
|
||
|
+ .enable_mask = 0x30,
|
||
|
+ .gating_mask = VPU2_REG_ENC_GATE_BIT,
|
||
|
+ .pipe_mask = 0,
|
||
|
+ .irq_mask = VPU2_ENC_INTERRUPT_BIT,
|
||
|
+ .ready_mask = VPU2_ENC_READY_BIT,
|
||
|
+ .error_mask = VPU2_ENC_ERR_MASK,
|
||
|
+ .get_fmt = vpu2_enc_get_fmt,
|
||
|
+ },
|
||
|
+ {
|
||
|
+ .name = "vpu2_dec",
|
||
|
+ .reg_rlc = 64,
|
||
|
+ .reg_en = VPU2_REG_EN_DEC,
|
||
|
+ .reg_irq = VPU2_DEC_INTERRUPT_REGISTER,
|
||
|
+ .reg_len = 64,
|
||
|
+ .reg_dir_mv = 62,
|
||
|
+ .reg_pps = -1,
|
||
|
+ .reg_pipe = VPU2_PP_PIPELINE_REGISTER,
|
||
|
+ .enable_mask = 0,
|
||
|
+ .gating_mask = VPU2_REG_DEC_GATE_BIT,
|
||
|
+ .pipe_mask = VPU2_PP_PIPELINE_MODE_BIT,
|
||
|
+ .irq_mask = VPU2_DEC_INTERRUPT_BIT,
|
||
|
+ .ready_mask = VPU2_DEC_READY_BIT,
|
||
|
+ .error_mask = VPU2_DEC_ERR_MASK,
|
||
|
+ .get_fmt = vpu2_dec_get_fmt,
|
||
|
+ },
|
||
|
+ {
|
||
|
+ .name = "vpu2_pp",
|
||
|
+ .reg_en = VPU2_REG_EN_PP,
|
||
|
+ .reg_irq = VPU2_PP_INTERRUPT_REGISTER,
|
||
|
+ .reg_len = -1,
|
||
|
+ .reg_dir_mv = -1,
|
||
|
+ .reg_pps = -1,
|
||
|
+ .reg_pipe = VPU2_PP_PIPELINE_REGISTER,
|
||
|
+ .enable_mask = 0,
|
||
|
+ .gating_mask = VPU2_REG_PP_GATE_BIT,
|
||
|
+ .pipe_mask = VPU2_PP_PIPELINE_MODE_BIT,
|
||
|
+ .irq_mask = VPU2_PP_INTERRUPT_BIT,
|
||
|
+ .ready_mask = VPU2_PP_READY_BIT,
|
||
|
+ .error_mask = VPU2_PP_ERR_MASK,
|
||
|
+ .get_fmt = vpu2_pp_get_fmt,
|
||
|
+ },
|
||
|
+ {
|
||
|
+ .name = "vpu2_dec_pp",
|
||
|
+ .reg_rlc = 64,
|
||
|
+ .reg_en = VPU2_REG_EN_DEC_PP,
|
||
|
+ .reg_irq = VPU2_DEC_INTERRUPT_REGISTER,
|
||
|
+ .reg_len = 64,
|
||
|
+ .reg_dir_mv = 62,
|
||
|
+ .reg_pps = -1,
|
||
|
+ .reg_pipe = VPU2_PP_PIPELINE_REGISTER,
|
||
|
+ .enable_mask = 0,
|
||
|
+ .gating_mask = VPU2_REG_DEC_GATE_BIT,
|
||
|
+ .pipe_mask = VPU2_PP_PIPELINE_MODE_BIT,
|
||
|
+ .irq_mask = VPU2_DEC_INTERRUPT_BIT,
|
||
|
+ .ready_mask = VPU2_DEC_READY_BIT,
|
||
|
+ .error_mask = VPU2_DEC_ERR_MASK,
|
||
|
+ .get_fmt = vpu2_dec_get_fmt,
|
||
|
+ },
|
||
|
+};
|
||
|
+
|
||
|
+static struct vpu_hw_info hw_vpu2 = {
|
||
|
+ .hw_id = VPU2_ID,
|
||
|
+
|
||
|
+ .enc_offset = 0x0,
|
||
|
+ .enc_reg_num = REG_NUM_VPU2_ENC,
|
||
|
+ .enc_io_size = REG_NUM_VPU2_ENC * 4,
|
||
|
+
|
||
|
+ .dec_offset = REG_NUM_VPU2_DEC_OFFSET,
|
||
|
+ .dec_reg_num = REG_NUM_VPU2_DEC_PP,
|
||
|
+ .dec_io_size = REG_NUM_VPU2_DEC_PP * 4,
|
||
|
+
|
||
|
+ .base_dec = REG_NUM_VPU2_DEC_START,
|
||
|
+ .base_pp = 0,
|
||
|
+ .base_dec_pp = 0,
|
||
|
+ .end_dec = REG_NUM_VPU2_DEC_END,
|
||
|
+ .end_pp = REG_NUM_VPU2_PP,
|
||
|
+ .end_dec_pp = REG_NUM_VPU2_DEC_END,
|
||
|
+};
|
||
|
+
|
||
|
+/*
|
||
|
+ * file handle translate information
|
||
|
+ */
|
||
|
+DEF_FMT_TRANS_TBL(vpu2_jpegd,
|
||
|
+ 131, 64, 63, 61, 21, 22
|
||
|
+);
|
||
|
+
|
||
|
+DEF_FMT_TRANS_TBL(vpu2_h264d,
|
||
|
+ 64, 63, 84, 85, 86, 87, 88, 89,
|
||
|
+ 90, 91, 92, 93, 94, 95, 96, 97,
|
||
|
+ 98, 99, 61, 62
|
||
|
+);
|
||
|
+
|
||
|
+DEF_FMT_TRANS_TBL(vpu2_vp6d,
|
||
|
+ 64, 63, 131, 136, 145, 61
|
||
|
+);
|
||
|
+
|
||
|
+DEF_FMT_TRANS_TBL(vpu2_vp8d,
|
||
|
+ 149, 64, 63, 131, 136, 137, 140, 141,
|
||
|
+ 142, 143, 144, 145, 146, 147, 61
|
||
|
+);
|
||
|
+
|
||
|
+DEF_FMT_TRANS_TBL(vpu2_vc1d,
|
||
|
+ 64, 63, 131, 148, 134, 135, 145, 62
|
||
|
+);
|
||
|
+
|
||
|
+DEF_FMT_TRANS_TBL(vpu2_default_dec,
|
||
|
+ 64, 63, 131, 148, 134, 135, 61, 62
|
||
|
+);
|
||
|
+
|
||
|
+DEF_FMT_TRANS_TBL(vpu2_default_pp,
|
||
|
+ 12, 13, 18, 19, 20, 21, 22
|
||
|
+);
|
||
|
+
|
||
|
+DEF_FMT_TRANS_TBL(vpu2_default_enc,
|
||
|
+ 77, 78, 56, 57, 63, 64, 48, 49,
|
||
|
+ 50, 81
|
||
|
+);
|
||
|
+
|
||
|
+const struct vpu_trans_info trans_vpu2[FMT_TYPE_BUTT] = {
|
||
|
+ SETUP_FMT_TBL(FMT_JPEGD , vpu2_jpegd),
|
||
|
+ SETUP_FMT_TBL(FMT_H263D , vpu2_default_dec),
|
||
|
+ SETUP_FMT_TBL(FMT_H264D , vpu2_h264d),
|
||
|
+ EMPTY_FMT_TBL(FMT_H265D),
|
||
|
+
|
||
|
+ SETUP_FMT_TBL(FMT_MPEG1D, vpu2_default_dec),
|
||
|
+ SETUP_FMT_TBL(FMT_MPEG2D, vpu2_default_dec),
|
||
|
+ SETUP_FMT_TBL(FMT_MPEG4D, vpu2_default_dec),
|
||
|
+
|
||
|
+ SETUP_FMT_TBL(FMT_VP6D , vpu2_vp6d),
|
||
|
+ SETUP_FMT_TBL(FMT_VP7D , vpu2_default_dec),
|
||
|
+ SETUP_FMT_TBL(FMT_VP8D , vpu2_vp8d),
|
||
|
+ EMPTY_FMT_TBL(FMT_VP9D),
|
||
|
+
|
||
|
+ SETUP_FMT_TBL(FMT_PP , vpu2_default_pp),
|
||
|
+
|
||
|
+ SETUP_FMT_TBL(FMT_VC1D , vpu2_vc1d),
|
||
|
+ SETUP_FMT_TBL(FMT_AVSD , vpu2_default_dec),
|
||
|
+
|
||
|
+ SETUP_FMT_TBL(FMT_JPEGE , vpu2_default_enc),
|
||
|
+ SETUP_FMT_TBL(FMT_H264E , vpu2_default_enc),
|
||
|
+ SETUP_FMT_TBL(FMT_VP8E , vpu2_default_enc),
|
||
|
+};
|
||
|
+
|
||
|
+#endif
|
||
|
diff --git a/drivers/video/rk_vcodec/vcodec_iommu_drm.c b/drivers/video/rk_vcodec/vcodec_iommu_drm.c
|
||
|
new file mode 100755
|
||
|
index 0000000..0bc5100
|
||
|
--- /dev/null
|
||
|
+++ b/drivers/video/rk_vcodec/vcodec_iommu_drm.c
|
||
|
@@ -0,0 +1,859 @@
|
||
|
+/*
|
||
|
+ * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd
|
||
|
+ * author: Jung Zhao jung.zhao@rock-chips.com
|
||
|
+ * Randy Li, randy.li@rock-chips.com
|
||
|
+ *
|
||
|
+ * This software is licensed under the terms of the GNU General Public
|
||
|
+ * License version 2, as published by the Free Software Foundation, and
|
||
|
+ * may be copied, distributed, and modified under those terms.
|
||
|
+ *
|
||
|
+ * 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.
|
||
|
+ *
|
||
|
+ */
|
||
|
+#include <linux/dma-buf.h>
|
||
|
+#include <drm/drmP.h>
|
||
|
+#include <drm/drm_atomic.h>
|
||
|
+#include <drm/drm_crtc_helper.h>
|
||
|
+#include <drm/drm_fb_helper.h>
|
||
|
+#if 0
|
||
|
+#include <drm/drm_sync_helper.h>
|
||
|
+#include <drm/rockchip_drm.h>
|
||
|
+#endif
|
||
|
+#include <linux/dma-mapping.h>
|
||
|
+#include <asm/dma-iommu.h>
|
||
|
+#include <linux/rockchip-iovmm.h>
|
||
|
+#include <linux/pm_runtime.h>
|
||
|
+#include <linux/memblock.h>
|
||
|
+#include <linux/module.h>
|
||
|
+#include <linux/of_address.h>
|
||
|
+#include <linux/of_graph.h>
|
||
|
+#include <linux/component.h>
|
||
|
+#if 0
|
||
|
+#include <linux/fence.h>
|
||
|
+#endif
|
||
|
+#include <linux/iommu.h>
|
||
|
+#include <linux/console.h>
|
||
|
+#include <linux/kref.h>
|
||
|
+#include <linux/fdtable.h>
|
||
|
+#include <linux/ktime.h>
|
||
|
+#include <linux/iova.h>
|
||
|
+#include <linux/dma-iommu.h>
|
||
|
+
|
||
|
+#include "vcodec_iommu_ops.h"
|
||
|
+
|
||
|
+struct vcodec_drm_buffer {
|
||
|
+ struct list_head list;
|
||
|
+ struct dma_buf *dma_buf;
|
||
|
+ union {
|
||
|
+ unsigned long iova;
|
||
|
+ unsigned long phys;
|
||
|
+ };
|
||
|
+ void *cpu_addr;
|
||
|
+ unsigned long size;
|
||
|
+ int index;
|
||
|
+ struct dma_buf_attachment *attach;
|
||
|
+ struct sg_table *sgt;
|
||
|
+ struct sg_table *copy_sgt;
|
||
|
+ struct page **pages;
|
||
|
+ struct kref ref;
|
||
|
+ struct vcodec_iommu_session_info *session_info;
|
||
|
+ ktime_t last_used;
|
||
|
+};
|
||
|
+
|
||
|
+struct vcodec_iommu_drm_info {
|
||
|
+ struct iommu_domain *domain;
|
||
|
+ bool attached;
|
||
|
+};
|
||
|
+
|
||
|
+static struct vcodec_drm_buffer *
|
||
|
+vcodec_drm_get_buffer_no_lock(struct vcodec_iommu_session_info *session_info,
|
||
|
+ int idx)
|
||
|
+{
|
||
|
+ struct vcodec_drm_buffer *drm_buffer = NULL, *n;
|
||
|
+
|
||
|
+ list_for_each_entry_safe(drm_buffer, n, &session_info->buffer_list,
|
||
|
+ list) {
|
||
|
+ if (drm_buffer->index == idx) {
|
||
|
+ drm_buffer->last_used = ktime_get();
|
||
|
+ return drm_buffer;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ return NULL;
|
||
|
+}
|
||
|
+
|
||
|
+static struct vcodec_drm_buffer *
|
||
|
+vcodec_drm_get_buffer_fd_no_lock(struct vcodec_iommu_session_info *session_info,
|
||
|
+ int fd)
|
||
|
+{
|
||
|
+ struct vcodec_drm_buffer *drm_buffer = NULL, *n;
|
||
|
+ struct dma_buf *dma_buf = NULL;
|
||
|
+
|
||
|
+ dma_buf = dma_buf_get(fd);
|
||
|
+
|
||
|
+ list_for_each_entry_safe(drm_buffer, n, &session_info->buffer_list,
|
||
|
+ list) {
|
||
|
+ if (drm_buffer->dma_buf == dma_buf) {
|
||
|
+ drm_buffer->last_used = ktime_get();
|
||
|
+ dma_buf_put(dma_buf);
|
||
|
+ return drm_buffer;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ dma_buf_put(dma_buf);
|
||
|
+
|
||
|
+ return NULL;
|
||
|
+}
|
||
|
+
|
||
|
+static void vcodec_drm_detach(struct vcodec_iommu_info *iommu_info)
|
||
|
+{
|
||
|
+ struct vcodec_iommu_drm_info *drm_info = iommu_info->private;
|
||
|
+ struct device *dev = iommu_info->dev;
|
||
|
+ struct iommu_domain *domain = drm_info->domain;
|
||
|
+
|
||
|
+ mutex_lock(&iommu_info->iommu_mutex);
|
||
|
+
|
||
|
+ if (!drm_info->attached) {
|
||
|
+ mutex_unlock(&iommu_info->iommu_mutex);
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ iommu_detach_device(domain, dev);
|
||
|
+ drm_info->attached = false;
|
||
|
+
|
||
|
+ mutex_unlock(&iommu_info->iommu_mutex);
|
||
|
+}
|
||
|
+
|
||
|
+static int vcodec_drm_attach_unlock(struct vcodec_iommu_info *iommu_info)
|
||
|
+{
|
||
|
+ struct vcodec_iommu_drm_info *drm_info = iommu_info->private;
|
||
|
+ struct device *dev = iommu_info->dev;
|
||
|
+ struct iommu_domain *domain = drm_info->domain;
|
||
|
+ int ret = 0;
|
||
|
+
|
||
|
+ ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
|
||
|
+ if (ret)
|
||
|
+ return ret;
|
||
|
+
|
||
|
+ dma_set_max_seg_size(dev, DMA_BIT_MASK(32));
|
||
|
+ ret = iommu_attach_device(domain, dev);
|
||
|
+ if (ret) {
|
||
|
+ dev_err(dev, "Failed to attach iommu device\n");
|
||
|
+ return ret;
|
||
|
+ }
|
||
|
+
|
||
|
+ return ret;
|
||
|
+}
|
||
|
+
|
||
|
+static int vcodec_drm_attach(struct vcodec_iommu_info *iommu_info)
|
||
|
+{
|
||
|
+ struct vcodec_iommu_drm_info *drm_info = iommu_info->private;
|
||
|
+ int ret;
|
||
|
+
|
||
|
+ mutex_lock(&iommu_info->iommu_mutex);
|
||
|
+
|
||
|
+ if (drm_info->attached) {
|
||
|
+ mutex_unlock(&iommu_info->iommu_mutex);
|
||
|
+ return 0;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = vcodec_drm_attach_unlock(iommu_info);
|
||
|
+ if (ret) {
|
||
|
+ mutex_unlock(&iommu_info->iommu_mutex);
|
||
|
+ return ret;
|
||
|
+ }
|
||
|
+
|
||
|
+ drm_info->attached = true;
|
||
|
+
|
||
|
+ mutex_unlock(&iommu_info->iommu_mutex);
|
||
|
+
|
||
|
+ return ret;
|
||
|
+}
|
||
|
+
|
||
|
+static void *vcodec_drm_sgt_map_kernel(struct vcodec_drm_buffer *drm_buffer)
|
||
|
+{
|
||
|
+ struct vcodec_iommu_session_info *session_info =
|
||
|
+ drm_buffer->session_info;
|
||
|
+ struct device *dev = session_info->dev;
|
||
|
+ struct scatterlist *sgl, *sg;
|
||
|
+ int nr_pages = PAGE_ALIGN(drm_buffer->size) >> PAGE_SHIFT;
|
||
|
+ int i = 0, j = 0, k = 0;
|
||
|
+ struct page *page;
|
||
|
+
|
||
|
+ drm_buffer->pages = kmalloc_array(nr_pages, sizeof(*drm_buffer->pages),
|
||
|
+ GFP_KERNEL);
|
||
|
+ if (!(drm_buffer->pages)) {
|
||
|
+ dev_err(dev, "drm map can not alloc pages\n");
|
||
|
+
|
||
|
+ return NULL;
|
||
|
+ }
|
||
|
+
|
||
|
+ sgl = drm_buffer->sgt->sgl;
|
||
|
+
|
||
|
+ for_each_sg(sgl, sg, drm_buffer->sgt->nents, i) {
|
||
|
+ page = sg_page(sg);
|
||
|
+ for (j = 0; j < sg->length / PAGE_SIZE; j++)
|
||
|
+ drm_buffer->pages[k++] = page++;
|
||
|
+ }
|
||
|
+
|
||
|
+ return vmap(drm_buffer->pages, nr_pages, VM_MAP,
|
||
|
+ pgprot_noncached(PAGE_KERNEL));
|
||
|
+}
|
||
|
+
|
||
|
+static void vcodec_drm_sgt_unmap_kernel(struct vcodec_drm_buffer *drm_buffer)
|
||
|
+{
|
||
|
+ vunmap(drm_buffer->cpu_addr);
|
||
|
+ kfree(drm_buffer->pages);
|
||
|
+}
|
||
|
+
|
||
|
+static int vcodec_finalise_sg(struct scatterlist *sg,
|
||
|
+ int nents,
|
||
|
+ dma_addr_t dma_addr)
|
||
|
+{
|
||
|
+ struct scatterlist *s, *cur = sg;
|
||
|
+ unsigned long seg_mask = DMA_BIT_MASK(32);
|
||
|
+ unsigned int cur_len = 0, max_len = DMA_BIT_MASK(32);
|
||
|
+ int i, count = 0;
|
||
|
+
|
||
|
+ for_each_sg(sg, s, nents, i) {
|
||
|
+ /* Restore this segment's original unaligned fields first */
|
||
|
+ unsigned int s_iova_off = sg_dma_address(s);
|
||
|
+ unsigned int s_length = sg_dma_len(s);
|
||
|
+ unsigned int s_iova_len = s->length;
|
||
|
+
|
||
|
+ s->offset += s_iova_off;
|
||
|
+ s->length = s_length;
|
||
|
+ sg_dma_address(s) = ARM_MAPPING_ERROR;
|
||
|
+ sg_dma_len(s) = 0;
|
||
|
+
|
||
|
+ /*
|
||
|
+ * Now fill in the real DMA data. If...
|
||
|
+ * - there is a valid output segment to append to
|
||
|
+ * - and this segment starts on an IOVA page boundary
|
||
|
+ * - but doesn't fall at a segment boundary
|
||
|
+ * - and wouldn't make the resulting output segment too long
|
||
|
+ */
|
||
|
+ if (cur_len && !s_iova_off && (dma_addr & seg_mask) &&
|
||
|
+ (cur_len + s_length <= max_len)) {
|
||
|
+ /* ...then concatenate it with the previous one */
|
||
|
+ cur_len += s_length;
|
||
|
+ } else {
|
||
|
+ /* Otherwise start the next output segment */
|
||
|
+ if (i > 0)
|
||
|
+ cur = sg_next(cur);
|
||
|
+ cur_len = s_length;
|
||
|
+ count++;
|
||
|
+
|
||
|
+ sg_dma_address(cur) = dma_addr + s_iova_off;
|
||
|
+ }
|
||
|
+
|
||
|
+ sg_dma_len(cur) = cur_len;
|
||
|
+ dma_addr += s_iova_len;
|
||
|
+
|
||
|
+ if (s_length + s_iova_off < s_iova_len)
|
||
|
+ cur_len = 0;
|
||
|
+ }
|
||
|
+ return count;
|
||
|
+}
|
||
|
+
|
||
|
+static void vcodec_invalidate_sg(struct scatterlist *sg, int nents)
|
||
|
+{
|
||
|
+ struct scatterlist *s;
|
||
|
+ int i;
|
||
|
+
|
||
|
+ for_each_sg(sg, s, nents, i) {
|
||
|
+ if (sg_dma_address(s) != ARM_MAPPING_ERROR)
|
||
|
+ s->offset += sg_dma_address(s);
|
||
|
+ if (sg_dma_len(s))
|
||
|
+ s->length = sg_dma_len(s);
|
||
|
+ sg_dma_address(s) = ARM_MAPPING_ERROR;
|
||
|
+ sg_dma_len(s) = 0;
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+static dma_addr_t vcodec_dma_map_sg(struct iommu_domain *domain,
|
||
|
+ struct scatterlist *sg,
|
||
|
+ int nents, int prot)
|
||
|
+{
|
||
|
+ struct iova_domain *iovad = domain->iova_cookie;
|
||
|
+ struct iova *iova;
|
||
|
+ struct scatterlist *s, *prev = NULL;
|
||
|
+ dma_addr_t dma_addr;
|
||
|
+ size_t iova_len = 0;
|
||
|
+ unsigned long mask = DMA_BIT_MASK(32);
|
||
|
+ unsigned long shift = iova_shift(iovad);
|
||
|
+ int i;
|
||
|
+
|
||
|
+ /*
|
||
|
+ * Work out how much IOVA space we need, and align the segments to
|
||
|
+ * IOVA granules for the IOMMU driver to handle. With some clever
|
||
|
+ * trickery we can modify the list in-place, but reversibly, by
|
||
|
+ * stashing the unaligned parts in the as-yet-unused DMA fields.
|
||
|
+ */
|
||
|
+ for_each_sg(sg, s, nents, i) {
|
||
|
+ size_t s_iova_off = iova_offset(iovad, s->offset);
|
||
|
+ size_t s_length = s->length;
|
||
|
+ size_t pad_len = (mask - iova_len + 1) & mask;
|
||
|
+
|
||
|
+ sg_dma_address(s) = s_iova_off;
|
||
|
+ sg_dma_len(s) = s_length;
|
||
|
+ s->offset -= s_iova_off;
|
||
|
+ s_length = iova_align(iovad, s_length + s_iova_off);
|
||
|
+ s->length = s_length;
|
||
|
+
|
||
|
+ /*
|
||
|
+ * Due to the alignment of our single IOVA allocation, we can
|
||
|
+ * depend on these assumptions about the segment boundary mask:
|
||
|
+ * - If mask size >= IOVA size, then the IOVA range cannot
|
||
|
+ * possibly fall across a boundary, so we don't care.
|
||
|
+ * - If mask size < IOVA size, then the IOVA range must start
|
||
|
+ * exactly on a boundary, therefore we can lay things out
|
||
|
+ * based purely on segment lengths without needing to know
|
||
|
+ * the actual addresses beforehand.
|
||
|
+ * - The mask must be a power of 2, so pad_len == 0 if
|
||
|
+ * iova_len == 0, thus we cannot dereference prev the first
|
||
|
+ * time through here (i.e. before it has a meaningful value).
|
||
|
+ */
|
||
|
+ if (pad_len && pad_len < s_length - 1) {
|
||
|
+ prev->length += pad_len;
|
||
|
+ iova_len += pad_len;
|
||
|
+ }
|
||
|
+
|
||
|
+ iova_len += s_length;
|
||
|
+ prev = s;
|
||
|
+ }
|
||
|
+
|
||
|
+ iova = alloc_iova(iovad, iova_align(iovad, iova_len) >> shift,
|
||
|
+ mask >> shift, true);
|
||
|
+ if (!iova)
|
||
|
+ goto out_restore_sg;
|
||
|
+
|
||
|
+ /*
|
||
|
+ * We'll leave any physical concatenation to the IOMMU driver's
|
||
|
+ * implementation - it knows better than we do.
|
||
|
+ */
|
||
|
+ dma_addr = iova_dma_addr(iovad, iova);
|
||
|
+ if (iommu_map_sg(domain, dma_addr, sg, nents, prot) < iova_len)
|
||
|
+ goto out_free_iova;
|
||
|
+
|
||
|
+ return vcodec_finalise_sg(sg, nents, dma_addr);
|
||
|
+
|
||
|
+out_free_iova:
|
||
|
+ __free_iova(iovad, iova);
|
||
|
+out_restore_sg:
|
||
|
+ vcodec_invalidate_sg(sg, nents);
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static void vcodec_dma_unmap_sg(struct iommu_domain *domain,
|
||
|
+ dma_addr_t dma_addr)
|
||
|
+{
|
||
|
+ struct iova_domain *iovad = domain->iova_cookie;
|
||
|
+ unsigned long shift = iova_shift(iovad);
|
||
|
+ unsigned long pfn = dma_addr >> shift;
|
||
|
+ struct iova *iova = find_iova(iovad, pfn);
|
||
|
+ size_t size;
|
||
|
+
|
||
|
+ if (WARN_ON(!iova))
|
||
|
+ return;
|
||
|
+
|
||
|
+ size = iova_size(iova) << shift;
|
||
|
+ size -= iommu_unmap(domain, pfn << shift, size);
|
||
|
+ /* ...and if we can't, then something is horribly, horribly wrong */
|
||
|
+ WARN_ON(size > 0);
|
||
|
+ __free_iova(iovad, iova);
|
||
|
+}
|
||
|
+
|
||
|
+static void vcodec_drm_clear_map(struct kref *ref)
|
||
|
+{
|
||
|
+ struct vcodec_drm_buffer *drm_buffer =
|
||
|
+ container_of(ref, struct vcodec_drm_buffer, ref);
|
||
|
+ struct vcodec_iommu_session_info *session_info =
|
||
|
+ drm_buffer->session_info;
|
||
|
+ struct vcodec_iommu_info *iommu_info = session_info->iommu_info;
|
||
|
+ struct vcodec_iommu_drm_info *drm_info = iommu_info->private;
|
||
|
+
|
||
|
+ mutex_lock(&iommu_info->iommu_mutex);
|
||
|
+ drm_info = session_info->iommu_info->private;
|
||
|
+
|
||
|
+ if (drm_buffer->cpu_addr) {
|
||
|
+ vcodec_drm_sgt_unmap_kernel(drm_buffer);
|
||
|
+ drm_buffer->cpu_addr = NULL;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (drm_buffer->attach) {
|
||
|
+ vcodec_dma_unmap_sg(drm_info->domain, drm_buffer->iova);
|
||
|
+ sg_free_table(drm_buffer->copy_sgt);
|
||
|
+ kfree(drm_buffer->copy_sgt);
|
||
|
+ dma_buf_unmap_attachment(drm_buffer->attach, drm_buffer->sgt,
|
||
|
+ DMA_BIDIRECTIONAL);
|
||
|
+ dma_buf_detach(drm_buffer->dma_buf, drm_buffer->attach);
|
||
|
+ dma_buf_put(drm_buffer->dma_buf);
|
||
|
+ drm_buffer->attach = NULL;
|
||
|
+ }
|
||
|
+
|
||
|
+ mutex_unlock(&iommu_info->iommu_mutex);
|
||
|
+}
|
||
|
+
|
||
|
+static void vcdoec_drm_dump_info(struct vcodec_iommu_session_info *session_info)
|
||
|
+{
|
||
|
+ struct vcodec_drm_buffer *drm_buffer = NULL, *n;
|
||
|
+
|
||
|
+ vpu_iommu_debug(session_info->debug_level, DEBUG_IOMMU_OPS_DUMP,
|
||
|
+ "still there are below buffers stored in list\n");
|
||
|
+ list_for_each_entry_safe(drm_buffer, n, &session_info->buffer_list,
|
||
|
+ list) {
|
||
|
+ vpu_iommu_debug(session_info->debug_level, DEBUG_IOMMU_OPS_DUMP,
|
||
|
+ "index %d drm_buffer dma_buf %p cpu_addr %p\n",
|
||
|
+ drm_buffer->index,
|
||
|
+ drm_buffer->dma_buf, drm_buffer->cpu_addr);
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+static int vcodec_drm_free(struct vcodec_iommu_session_info *session_info,
|
||
|
+ int idx)
|
||
|
+{
|
||
|
+ struct device *dev = session_info->dev;
|
||
|
+ /* please double-check all maps have been release */
|
||
|
+ struct vcodec_drm_buffer *drm_buffer;
|
||
|
+
|
||
|
+ mutex_lock(&session_info->list_mutex);
|
||
|
+ drm_buffer = vcodec_drm_get_buffer_no_lock(session_info, idx);
|
||
|
+
|
||
|
+ if (!drm_buffer) {
|
||
|
+ dev_err(dev, "can not find %d buffer in list\n", idx);
|
||
|
+ mutex_unlock(&session_info->list_mutex);
|
||
|
+
|
||
|
+ return -EINVAL;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (refcount_read(&drm_buffer->ref.refcount) == 0) {
|
||
|
+ dma_buf_put(drm_buffer->dma_buf);
|
||
|
+ list_del_init(&drm_buffer->list);
|
||
|
+ kfree(drm_buffer);
|
||
|
+ session_info->buffer_nums--;
|
||
|
+ vpu_iommu_debug(session_info->debug_level, DEBUG_IOMMU_NORMAL,
|
||
|
+ "buffer nums %d\n", session_info->buffer_nums);
|
||
|
+ }
|
||
|
+ mutex_unlock(&session_info->list_mutex);
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static int
|
||
|
+vcodec_drm_unmap_iommu(struct vcodec_iommu_session_info *session_info,
|
||
|
+ int idx)
|
||
|
+{
|
||
|
+ struct device *dev = session_info->dev;
|
||
|
+ struct vcodec_drm_buffer *drm_buffer;
|
||
|
+
|
||
|
+ /* Force to flush iommu table */
|
||
|
+ if (of_machine_is_compatible("rockchip,rk3288"))
|
||
|
+ rockchip_iovmm_invalidate_tlb(session_info->mmu_dev);
|
||
|
+
|
||
|
+ mutex_lock(&session_info->list_mutex);
|
||
|
+ drm_buffer = vcodec_drm_get_buffer_no_lock(session_info, idx);
|
||
|
+ mutex_unlock(&session_info->list_mutex);
|
||
|
+
|
||
|
+ if (!drm_buffer) {
|
||
|
+ dev_err(dev, "can not find %d buffer in list\n", idx);
|
||
|
+ return -EINVAL;
|
||
|
+ }
|
||
|
+
|
||
|
+ kref_put(&drm_buffer->ref, vcodec_drm_clear_map);
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static int vcodec_drm_map_iommu(struct vcodec_iommu_session_info *session_info,
|
||
|
+ int idx,
|
||
|
+ unsigned long *iova,
|
||
|
+ unsigned long *size)
|
||
|
+{
|
||
|
+ struct device *dev = session_info->dev;
|
||
|
+ struct vcodec_drm_buffer *drm_buffer;
|
||
|
+
|
||
|
+ /* Force to flush iommu table */
|
||
|
+ if (of_machine_is_compatible("rockchip,rk3288"))
|
||
|
+ rockchip_iovmm_invalidate_tlb(session_info->mmu_dev);
|
||
|
+
|
||
|
+ mutex_lock(&session_info->list_mutex);
|
||
|
+ drm_buffer = vcodec_drm_get_buffer_no_lock(session_info, idx);
|
||
|
+ mutex_unlock(&session_info->list_mutex);
|
||
|
+
|
||
|
+ if (!drm_buffer) {
|
||
|
+ dev_err(dev, "can not find %d buffer in list\n", idx);
|
||
|
+ return -EINVAL;
|
||
|
+ }
|
||
|
+
|
||
|
+ kref_get(&drm_buffer->ref);
|
||
|
+ if (iova)
|
||
|
+ *iova = drm_buffer->iova;
|
||
|
+ if (size)
|
||
|
+ *size = drm_buffer->size;
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static int
|
||
|
+vcodec_drm_unmap_kernel(struct vcodec_iommu_session_info *session_info, int idx)
|
||
|
+{
|
||
|
+ struct device *dev = session_info->dev;
|
||
|
+ struct vcodec_drm_buffer *drm_buffer;
|
||
|
+
|
||
|
+ mutex_lock(&session_info->list_mutex);
|
||
|
+ drm_buffer = vcodec_drm_get_buffer_no_lock(session_info, idx);
|
||
|
+ mutex_unlock(&session_info->list_mutex);
|
||
|
+
|
||
|
+ if (!drm_buffer) {
|
||
|
+ dev_err(dev, "can not find %d buffer in list\n", idx);
|
||
|
+
|
||
|
+ return -EINVAL;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (drm_buffer->cpu_addr) {
|
||
|
+ vcodec_drm_sgt_unmap_kernel(drm_buffer);
|
||
|
+ drm_buffer->cpu_addr = NULL;
|
||
|
+ }
|
||
|
+
|
||
|
+ kref_put(&drm_buffer->ref, vcodec_drm_clear_map);
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static int
|
||
|
+vcodec_drm_free_fd(struct vcodec_iommu_session_info *session_info, int fd)
|
||
|
+{
|
||
|
+ struct device *dev = session_info->dev;
|
||
|
+ /* please double-check all maps have been release */
|
||
|
+ struct vcodec_drm_buffer *drm_buffer = NULL;
|
||
|
+
|
||
|
+ mutex_lock(&session_info->list_mutex);
|
||
|
+ drm_buffer = vcodec_drm_get_buffer_fd_no_lock(session_info, fd);
|
||
|
+
|
||
|
+ if (!drm_buffer) {
|
||
|
+ dev_err(dev, "can not find %d buffer in list\n", fd);
|
||
|
+ mutex_unlock(&session_info->list_mutex);
|
||
|
+
|
||
|
+ return -EINVAL;
|
||
|
+ }
|
||
|
+ mutex_unlock(&session_info->list_mutex);
|
||
|
+
|
||
|
+ vcodec_drm_unmap_iommu(session_info, drm_buffer->index);
|
||
|
+
|
||
|
+ mutex_lock(&session_info->list_mutex);
|
||
|
+ if (refcount_read(&drm_buffer->ref.refcount) == 0) {
|
||
|
+ dma_buf_put(drm_buffer->dma_buf);
|
||
|
+ list_del_init(&drm_buffer->list);
|
||
|
+ kfree(drm_buffer);
|
||
|
+ session_info->buffer_nums--;
|
||
|
+ vpu_iommu_debug(session_info->debug_level, DEBUG_IOMMU_NORMAL,
|
||
|
+ "buffer nums %d\n", session_info->buffer_nums);
|
||
|
+ }
|
||
|
+ mutex_unlock(&session_info->list_mutex);
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static void
|
||
|
+vcodec_drm_clear_session(struct vcodec_iommu_session_info *session_info)
|
||
|
+{
|
||
|
+ struct vcodec_drm_buffer *drm_buffer = NULL, *n;
|
||
|
+
|
||
|
+ list_for_each_entry_safe(drm_buffer, n, &session_info->buffer_list,
|
||
|
+ list) {
|
||
|
+ kref_put(&drm_buffer->ref, vcodec_drm_clear_map);
|
||
|
+ vcodec_drm_free(session_info, drm_buffer->index);
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+static void *
|
||
|
+vcodec_drm_map_kernel(struct vcodec_iommu_session_info *session_info, int idx)
|
||
|
+{
|
||
|
+ struct device *dev = session_info->dev;
|
||
|
+ struct vcodec_drm_buffer *drm_buffer;
|
||
|
+
|
||
|
+ mutex_lock(&session_info->list_mutex);
|
||
|
+ drm_buffer = vcodec_drm_get_buffer_no_lock(session_info, idx);
|
||
|
+ mutex_unlock(&session_info->list_mutex);
|
||
|
+
|
||
|
+ if (!drm_buffer) {
|
||
|
+ dev_err(dev, "can not find %d buffer in list\n", idx);
|
||
|
+ return NULL;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (!drm_buffer->cpu_addr)
|
||
|
+ drm_buffer->cpu_addr =
|
||
|
+ vcodec_drm_sgt_map_kernel(drm_buffer);
|
||
|
+
|
||
|
+ kref_get(&drm_buffer->ref);
|
||
|
+
|
||
|
+ return drm_buffer->cpu_addr;
|
||
|
+}
|
||
|
+
|
||
|
+static int vcodec_drm_import(struct vcodec_iommu_session_info *session_info,
|
||
|
+ int fd)
|
||
|
+{
|
||
|
+ struct vcodec_drm_buffer *drm_buffer = NULL, *n;
|
||
|
+ struct vcodec_drm_buffer *oldest_buffer = NULL, *loop_buffer = NULL;
|
||
|
+ struct vcodec_iommu_info *iommu_info = session_info->iommu_info;
|
||
|
+ struct vcodec_iommu_drm_info *drm_info = iommu_info->private;
|
||
|
+ struct device *dev = session_info->dev;
|
||
|
+ struct dma_buf_attachment *attach;
|
||
|
+ struct sg_table *sgt;
|
||
|
+ struct dma_buf *dma_buf;
|
||
|
+ ktime_t oldest_time = ktime_set(0, 0);
|
||
|
+ struct scatterlist *sg, *s;
|
||
|
+ int i;
|
||
|
+ int ret = 0;
|
||
|
+
|
||
|
+ dma_buf = dma_buf_get(fd);
|
||
|
+ if (IS_ERR(dma_buf)) {
|
||
|
+ ret = PTR_ERR(dma_buf);
|
||
|
+ return ret;
|
||
|
+ }
|
||
|
+
|
||
|
+ list_for_each_entry_safe(drm_buffer, n,
|
||
|
+ &session_info->buffer_list, list) {
|
||
|
+ if (drm_buffer->dma_buf == dma_buf) {
|
||
|
+ dma_buf_put(dma_buf);
|
||
|
+ drm_buffer->last_used = ktime_get();
|
||
|
+ return drm_buffer->index;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ drm_buffer = kzalloc(sizeof(*drm_buffer), GFP_KERNEL);
|
||
|
+ if (!drm_buffer) {
|
||
|
+ ret = -ENOMEM;
|
||
|
+ return ret;
|
||
|
+ }
|
||
|
+
|
||
|
+ drm_buffer->dma_buf = dma_buf;
|
||
|
+ drm_buffer->session_info = session_info;
|
||
|
+ drm_buffer->last_used = ktime_get();
|
||
|
+
|
||
|
+ kref_init(&drm_buffer->ref);
|
||
|
+
|
||
|
+ mutex_lock(&iommu_info->iommu_mutex);
|
||
|
+ drm_info = session_info->iommu_info->private;
|
||
|
+
|
||
|
+ attach = dma_buf_attach(drm_buffer->dma_buf, dev);
|
||
|
+ if (IS_ERR(attach)) {
|
||
|
+ ret = PTR_ERR(attach);
|
||
|
+ goto fail_out;
|
||
|
+ }
|
||
|
+
|
||
|
+ get_dma_buf(drm_buffer->dma_buf);
|
||
|
+
|
||
|
+ sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
|
||
|
+ if (IS_ERR(sgt)) {
|
||
|
+ ret = PTR_ERR(sgt);
|
||
|
+ goto fail_detach;
|
||
|
+ }
|
||
|
+
|
||
|
+ /*
|
||
|
+ * Since we call dma_buf_map_attachment outside attach/detach, this
|
||
|
+ * will cause incorrectly map. we have to re-build map table native
|
||
|
+ * and for avoiding destroy their origin map table, we need use a
|
||
|
+ * copy one sg_table.
|
||
|
+ */
|
||
|
+ drm_buffer->copy_sgt = kmalloc(sizeof(*drm_buffer->copy_sgt),
|
||
|
+ GFP_KERNEL);
|
||
|
+ if (!drm_buffer->copy_sgt) {
|
||
|
+ ret = -ENOMEM;
|
||
|
+ goto fail_detach;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = sg_alloc_table(drm_buffer->copy_sgt, sgt->nents, GFP_KERNEL);
|
||
|
+ s = drm_buffer->copy_sgt->sgl;
|
||
|
+ for_each_sg(sgt->sgl, sg, sgt->nents, i) {
|
||
|
+ sg_set_page(s, sg_page(sg),
|
||
|
+ PAGE_SIZE << compound_order(sg_page(sg)), 0);
|
||
|
+ sg_dma_address(s) = page_to_phys(sg_page(sg));
|
||
|
+ s->offset = sg->offset;
|
||
|
+ s->length = sg->length;
|
||
|
+ s = sg_next(s);
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = vcodec_dma_map_sg(drm_info->domain, drm_buffer->copy_sgt->sgl,
|
||
|
+ drm_buffer->copy_sgt->nents,
|
||
|
+ IOMMU_READ | IOMMU_WRITE);
|
||
|
+ if (!ret) {
|
||
|
+ ret = -ENOMEM;
|
||
|
+ goto fail_alloc;
|
||
|
+ }
|
||
|
+ drm_buffer->iova = sg_dma_address(drm_buffer->copy_sgt->sgl);
|
||
|
+ drm_buffer->size = drm_buffer->dma_buf->size;
|
||
|
+
|
||
|
+ drm_buffer->attach = attach;
|
||
|
+ drm_buffer->sgt = sgt;
|
||
|
+
|
||
|
+ mutex_unlock(&iommu_info->iommu_mutex);
|
||
|
+
|
||
|
+ INIT_LIST_HEAD(&drm_buffer->list);
|
||
|
+ mutex_lock(&session_info->list_mutex);
|
||
|
+ session_info->buffer_nums++;
|
||
|
+ vpu_iommu_debug(session_info->debug_level, DEBUG_IOMMU_NORMAL,
|
||
|
+ "buffer nums %d\n", session_info->buffer_nums);
|
||
|
+ if (session_info->buffer_nums > BUFFER_LIST_MAX_NUMS) {
|
||
|
+ list_for_each_entry_safe(loop_buffer, n,
|
||
|
+ &session_info->buffer_list, list) {
|
||
|
+ if (ktime_to_ns(oldest_time) == 0 ||
|
||
|
+ ktime_after(oldest_time,
|
||
|
+ loop_buffer->last_used)) {
|
||
|
+ oldest_time = loop_buffer->last_used;
|
||
|
+ oldest_buffer = loop_buffer;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ kref_put(&oldest_buffer->ref, vcodec_drm_clear_map);
|
||
|
+ dma_buf_put(oldest_buffer->dma_buf);
|
||
|
+ list_del_init(&oldest_buffer->list);
|
||
|
+ kfree(oldest_buffer);
|
||
|
+ session_info->buffer_nums--;
|
||
|
+ }
|
||
|
+ drm_buffer->index = session_info->max_idx;
|
||
|
+ list_add_tail(&drm_buffer->list, &session_info->buffer_list);
|
||
|
+ session_info->max_idx++;
|
||
|
+ if ((session_info->max_idx & 0xfffffff) == 0)
|
||
|
+ session_info->max_idx = 0;
|
||
|
+ mutex_unlock(&session_info->list_mutex);
|
||
|
+
|
||
|
+ return drm_buffer->index;
|
||
|
+
|
||
|
+fail_alloc:
|
||
|
+ sg_free_table(drm_buffer->copy_sgt);
|
||
|
+ kfree(drm_buffer->copy_sgt);
|
||
|
+ dma_buf_unmap_attachment(attach, sgt,
|
||
|
+ DMA_BIDIRECTIONAL);
|
||
|
+fail_detach:
|
||
|
+ dma_buf_detach(drm_buffer->dma_buf, attach);
|
||
|
+ dma_buf_put(drm_buffer->dma_buf);
|
||
|
+fail_out:
|
||
|
+ kfree(drm_buffer);
|
||
|
+ mutex_unlock(&iommu_info->iommu_mutex);
|
||
|
+
|
||
|
+ return ret;
|
||
|
+}
|
||
|
+
|
||
|
+static int vcodec_drm_create(struct vcodec_iommu_info *iommu_info)
|
||
|
+{
|
||
|
+ struct vcodec_iommu_drm_info *drm_info;
|
||
|
+ struct iommu_group *group;
|
||
|
+ int ret;
|
||
|
+
|
||
|
+ iommu_info->private = kzalloc(sizeof(*drm_info),
|
||
|
+ GFP_KERNEL);
|
||
|
+ drm_info = iommu_info->private;
|
||
|
+ if (!drm_info)
|
||
|
+ return -ENOMEM;
|
||
|
+
|
||
|
+ drm_info->domain = iommu_domain_alloc(&platform_bus_type);
|
||
|
+ drm_info->attached = false;
|
||
|
+ if (!drm_info->domain)
|
||
|
+ return -ENOMEM;
|
||
|
+#ifdef CONFIG_IOMMU_DMA
|
||
|
+ ret = iommu_get_dma_cookie(drm_info->domain);
|
||
|
+ if (ret)
|
||
|
+ goto err_free_domain;
|
||
|
+#else
|
||
|
+ {
|
||
|
+ unsigned long order, base_pfn, end_pfn;
|
||
|
+ dma_addr_t base;
|
||
|
+ u64 size;
|
||
|
+
|
||
|
+ base = 0x10000000;
|
||
|
+ size = SZ_2G;
|
||
|
+
|
||
|
+ order = __ffs(drm_info->domain->ops->pgsize_bitmap);
|
||
|
+ base_pfn = max_t(unsigned long, 1, base >> order);
|
||
|
+ end_pfn = (base + size - 1) >> order;
|
||
|
+
|
||
|
+ /* Check the domain allows at least some access to the device... */
|
||
|
+ if (drm_info->domain->geometry.force_aperture) {
|
||
|
+ if (base > drm_info->domain->geometry.aperture_end ||
|
||
|
+ base + size <= drm_info->domain->geometry.aperture_start) {
|
||
|
+ pr_warn("specified DMA range outside IOMMU capability\n");
|
||
|
+ return -EFAULT;
|
||
|
+ }
|
||
|
+ /* ...then finally give it a kicking to make sure it fits */
|
||
|
+ base_pfn = max_t(unsigned long, base_pfn,
|
||
|
+ drm_info->domain->geometry.aperture_start >> order);
|
||
|
+ end_pfn = min_t(unsigned long, end_pfn,
|
||
|
+ drm_info->domain->geometry.aperture_end >> order);
|
||
|
+ }
|
||
|
+ drm_info->domain->iova_cookie = kzalloc(sizeof(struct iova_domain), GFP_KERNEL);
|
||
|
+ init_iova_domain(drm_info->domain->iova_cookie, 1UL << order, base_pfn, end_pfn);
|
||
|
+ iova_cache_get();
|
||
|
+ }
|
||
|
+#endif
|
||
|
+ group = iommu_group_get(iommu_info->dev);
|
||
|
+ if (!group) {
|
||
|
+ group = iommu_group_alloc();
|
||
|
+ if (IS_ERR(group)) {
|
||
|
+ dev_err(iommu_info->dev,
|
||
|
+ "Failed to allocate IOMMU group\n");
|
||
|
+ goto err_put_cookie;
|
||
|
+ }
|
||
|
+ ret = iommu_group_add_device(group, iommu_info->dev);
|
||
|
+ if (ret) {
|
||
|
+ dev_err(iommu_info->dev,
|
||
|
+ "failed to add device to IOMMU group\n");
|
||
|
+ goto err_put_cookie;
|
||
|
+ }
|
||
|
+ }
|
||
|
+#ifdef CONFIG_IOMMU_DMA
|
||
|
+ iommu_dma_init_domain(drm_info->domain, 0x10000000, SZ_2G, iommu_info->dev);
|
||
|
+#endif
|
||
|
+ iommu_group_put(group);
|
||
|
+
|
||
|
+ return 0;
|
||
|
+
|
||
|
+err_put_cookie:
|
||
|
+#ifdef CONFIG_IOMMU_DMA
|
||
|
+ iommu_put_dma_cookie(drm_info->domain);
|
||
|
+#endif
|
||
|
+err_free_domain:
|
||
|
+ iommu_domain_free(drm_info->domain);
|
||
|
+
|
||
|
+ return ret;
|
||
|
+}
|
||
|
+
|
||
|
+static int vcodec_drm_destroy(struct vcodec_iommu_info *iommu_info)
|
||
|
+{
|
||
|
+ struct vcodec_iommu_drm_info *drm_info = iommu_info->private;
|
||
|
+#ifdef CONFIG_IOMMU_DMA
|
||
|
+ iommu_put_dma_cookie(drm_info->domain);
|
||
|
+#else
|
||
|
+ iova_cache_put();
|
||
|
+#endif
|
||
|
+ iommu_domain_free(drm_info->domain);
|
||
|
+
|
||
|
+ kfree(drm_info);
|
||
|
+ iommu_info->private = NULL;
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static struct vcodec_iommu_ops drm_ops = {
|
||
|
+ .create = vcodec_drm_create,
|
||
|
+ .import = vcodec_drm_import,
|
||
|
+ .free = vcodec_drm_free,
|
||
|
+ .free_fd = vcodec_drm_free_fd,
|
||
|
+ .map_kernel = vcodec_drm_map_kernel,
|
||
|
+ .unmap_kernel = vcodec_drm_unmap_kernel,
|
||
|
+ .map_iommu = vcodec_drm_map_iommu,
|
||
|
+ .unmap_iommu = vcodec_drm_unmap_iommu,
|
||
|
+ .destroy = vcodec_drm_destroy,
|
||
|
+ .dump = vcdoec_drm_dump_info,
|
||
|
+ .attach = vcodec_drm_attach,
|
||
|
+ .detach = vcodec_drm_detach,
|
||
|
+ .clear = vcodec_drm_clear_session,
|
||
|
+};
|
||
|
+
|
||
|
+void vcodec_iommu_drm_set_ops(struct vcodec_iommu_info *iommu_info)
|
||
|
+{
|
||
|
+ if (!iommu_info)
|
||
|
+ return;
|
||
|
+ iommu_info->ops = &drm_ops;
|
||
|
+}
|
||
|
diff --git a/drivers/video/rk_vcodec/vcodec_iommu_ion.c b/drivers/video/rk_vcodec/vcodec_iommu_ion.c
|
||
|
new file mode 100644
|
||
|
index 0000000..658e9d6
|
||
|
--- /dev/null
|
||
|
+++ b/drivers/video/rk_vcodec/vcodec_iommu_ion.c
|
||
|
@@ -0,0 +1,302 @@
|
||
|
+/*
|
||
|
+ * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd
|
||
|
+ * author: Jung Zhao jung.zhao@rock-chips.com
|
||
|
+ * Randy Li, randy.li@rock-chips.com
|
||
|
+ *
|
||
|
+ * This software is licensed under the terms of the GNU General Public
|
||
|
+ * License version 2, as published by the Free Software Foundation, and
|
||
|
+ * may be copied, distributed, and modified under those terms.
|
||
|
+ *
|
||
|
+ * 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.
|
||
|
+ *
|
||
|
+ */
|
||
|
+
|
||
|
+#include <linux/rockchip_ion.h>
|
||
|
+#include <linux/rockchip-iovmm.h>
|
||
|
+#include <linux/slab.h>
|
||
|
+#include <linux/pm_runtime.h>
|
||
|
+#include <linux/memblock.h>
|
||
|
+#include <linux/module.h>
|
||
|
+#include <linux/of_address.h>
|
||
|
+#include <linux/of_graph.h>
|
||
|
+#include <linux/component.h>
|
||
|
+#include <linux/fence.h>
|
||
|
+#include <linux/console.h>
|
||
|
+#include <linux/kref.h>
|
||
|
+#include <linux/fdtable.h>
|
||
|
+
|
||
|
+#include "vcodec_iommu_ops.h"
|
||
|
+
|
||
|
+struct vcodec_ion_buffer {
|
||
|
+ struct list_head list;
|
||
|
+ struct ion_handle *handle;
|
||
|
+ int index;
|
||
|
+};
|
||
|
+
|
||
|
+struct vcodec_iommu_ion_info {
|
||
|
+ struct ion_client *ion_client;
|
||
|
+ bool attached;
|
||
|
+};
|
||
|
+
|
||
|
+static struct vcodec_ion_buffer *
|
||
|
+vcodec_ion_get_buffer_no_lock(struct vcodec_iommu_session_info *session_info,
|
||
|
+ int idx)
|
||
|
+{
|
||
|
+ struct vcodec_ion_buffer *ion_buffer = NULL, *n;
|
||
|
+
|
||
|
+ list_for_each_entry_safe(ion_buffer, n,
|
||
|
+ &session_info->buffer_list, list) {
|
||
|
+ if (ion_buffer->index == idx)
|
||
|
+ return ion_buffer;
|
||
|
+ }
|
||
|
+
|
||
|
+ return NULL;
|
||
|
+}
|
||
|
+
|
||
|
+static void
|
||
|
+vcodec_ion_clear_session(struct vcodec_iommu_session_info *session_info)
|
||
|
+{
|
||
|
+ /* do nothing */
|
||
|
+}
|
||
|
+
|
||
|
+static int vcodec_ion_attach(struct vcodec_iommu_info *iommu_info)
|
||
|
+{
|
||
|
+ struct vcodec_iommu_ion_info *ion_info = iommu_info->private;
|
||
|
+ int ret;
|
||
|
+
|
||
|
+ mutex_lock(&iommu_info->iommu_mutex);
|
||
|
+
|
||
|
+ if (ion_info->attached) {
|
||
|
+ mutex_unlock(&iommu_info->iommu_mutex);
|
||
|
+ return 0;
|
||
|
+ }
|
||
|
+
|
||
|
+ rockchip_iovmm_activate(iommu_info->dev);
|
||
|
+
|
||
|
+ ion_info->attached = true;
|
||
|
+
|
||
|
+ mutex_unlock(&iommu_info->iommu_mutex);
|
||
|
+
|
||
|
+ return ret;
|
||
|
+}
|
||
|
+
|
||
|
+static void vcodec_ion_detach(struct vcodec_iommu_info *iommu_info)
|
||
|
+{
|
||
|
+ struct vcodec_iommu_ion_info *ion_info = iommu_info->private;
|
||
|
+
|
||
|
+ mutex_lock(&iommu_info->iommu_mutex);
|
||
|
+
|
||
|
+ if (!ion_info->attached) {
|
||
|
+ mutex_unlock(&iommu_info->iommu_mutex);
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ rockchip_iovmm_deactivate(iommu_info->dev);
|
||
|
+ ion_info->attached = false;
|
||
|
+
|
||
|
+ mutex_unlock(&iommu_info->iommu_mutex);
|
||
|
+}
|
||
|
+
|
||
|
+static int vcodec_ion_destroy(struct vcodec_iommu_info *iommu_info)
|
||
|
+{
|
||
|
+ struct vcodec_iommu_ion_info *ion_info = iommu_info->private;
|
||
|
+
|
||
|
+ vcodec_ion_detach(iommu_info);
|
||
|
+ kfree(ion_info);
|
||
|
+ iommu_info->private = NULL;
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static int
|
||
|
+vcodec_ion_free(struct vcodec_iommu_session_info *session_info, int idx)
|
||
|
+{
|
||
|
+ struct vcodec_ion_buffer *ion_buffer;
|
||
|
+
|
||
|
+ mutex_lock(&session_info->list_mutex);
|
||
|
+ ion_buffer = vcodec_ion_get_buffer_no_lock(session_info, idx);
|
||
|
+
|
||
|
+ if (!ion_buffer) {
|
||
|
+ mutex_unlock(&session_info->list_mutex);
|
||
|
+ pr_err("%s can not find %d buffer in list\n", __func__, idx);
|
||
|
+
|
||
|
+ return -EINVAL;
|
||
|
+ }
|
||
|
+
|
||
|
+ list_del_init(&ion_buffer->list);
|
||
|
+ mutex_unlock(&session_info->list_mutex);
|
||
|
+ kfree(ion_buffer);
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static int
|
||
|
+vcodec_ion_unmap_iommu(struct vcodec_iommu_session_info *session_info, int idx)
|
||
|
+{
|
||
|
+ struct vcodec_ion_buffer *ion_buffer;
|
||
|
+ struct vcodec_iommu_info *iommu_info = session_info->iommu_info;
|
||
|
+ struct vcodec_iommu_ion_info *ion_info = iommu_info->private;
|
||
|
+
|
||
|
+ mutex_lock(&session_info->list_mutex);
|
||
|
+ ion_buffer = vcodec_ion_get_buffer_no_lock(session_info, idx);
|
||
|
+ mutex_unlock(&session_info->list_mutex);
|
||
|
+
|
||
|
+ if (!ion_buffer) {
|
||
|
+ pr_err("%s can not find %d buffer in list\n", __func__, idx);
|
||
|
+
|
||
|
+ return -EINVAL;
|
||
|
+ }
|
||
|
+
|
||
|
+ ion_free(ion_info->ion_client, ion_buffer->handle);
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static int
|
||
|
+vcodec_ion_map_iommu(struct vcodec_iommu_session_info *session_info, int idx,
|
||
|
+ unsigned long *iova, unsigned long *size)
|
||
|
+{
|
||
|
+ struct vcodec_ion_buffer *ion_buffer;
|
||
|
+ struct device *dev = session_info->dev;
|
||
|
+ struct vcodec_iommu_info *iommu_info = session_info->iommu_info;
|
||
|
+ struct vcodec_iommu_ion_info *ion_info = iommu_info->private;
|
||
|
+ int ret = 0;
|
||
|
+
|
||
|
+ /* Force to flush iommu table */
|
||
|
+ rockchip_iovmm_invalidate_tlb(session_info->dev);
|
||
|
+
|
||
|
+ mutex_lock(&session_info->list_mutex);
|
||
|
+ ion_buffer = vcodec_ion_get_buffer_no_lock(session_info, idx);
|
||
|
+ mutex_unlock(&session_info->list_mutex);
|
||
|
+
|
||
|
+ if (!ion_buffer) {
|
||
|
+ pr_err("%s can not find %d buffer in list\n", __func__, idx);
|
||
|
+
|
||
|
+ return -EINVAL;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (session_info->mmu_dev)
|
||
|
+ ret = ion_map_iommu(dev, ion_info->ion_client,
|
||
|
+ ion_buffer->handle, iova, size);
|
||
|
+ else
|
||
|
+ ret = ion_phys(ion_info->ion_client, ion_buffer->handle,
|
||
|
+ iova, (size_t *)size);
|
||
|
+
|
||
|
+ return ret;
|
||
|
+}
|
||
|
+
|
||
|
+static int
|
||
|
+vcodec_ion_unmap_kernel(struct vcodec_iommu_session_info *session_info,
|
||
|
+ int idx)
|
||
|
+{
|
||
|
+ struct vcodec_ion_buffer *ion_buffer;
|
||
|
+
|
||
|
+ mutex_lock(&session_info->list_mutex);
|
||
|
+ ion_buffer = vcodec_ion_get_buffer_no_lock(session_info, idx);
|
||
|
+ mutex_unlock(&session_info->list_mutex);
|
||
|
+
|
||
|
+ if (!ion_buffer) {
|
||
|
+ pr_err("%s can not find %d buffer in list\n", __func__, idx);
|
||
|
+
|
||
|
+ return -EINVAL;
|
||
|
+ }
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static void *
|
||
|
+vcodec_ion_map_kernel(struct vcodec_iommu_session_info *session_info, int idx)
|
||
|
+{
|
||
|
+ struct vcodec_ion_buffer *ion_buffer;
|
||
|
+ struct vcodec_iommu_info *iommu_info = session_info->iommu_info;
|
||
|
+ struct vcodec_iommu_ion_info *ion_info = iommu_info->private;
|
||
|
+
|
||
|
+ rockchip_iovmm_invalidate_tlb(session_info->dev);
|
||
|
+
|
||
|
+ mutex_lock(&session_info->list_mutex);
|
||
|
+ ion_buffer = vcodec_ion_get_buffer_no_lock(session_info, idx);
|
||
|
+ mutex_unlock(&session_info->list_mutex);
|
||
|
+
|
||
|
+ if (!ion_buffer) {
|
||
|
+ pr_err("%s can not find %d buffer in list\n", __func__, idx);
|
||
|
+
|
||
|
+ return NULL;
|
||
|
+ }
|
||
|
+
|
||
|
+ return ion_map_kernel(ion_info->ion_client, ion_buffer->handle);
|
||
|
+}
|
||
|
+
|
||
|
+static int
|
||
|
+vcodec_ion_import(struct vcodec_iommu_session_info *session_info, int fd)
|
||
|
+{
|
||
|
+ struct vcodec_ion_buffer *ion_buffer = NULL;
|
||
|
+ struct vcodec_iommu_info *iommu_info = session_info->iommu_info;
|
||
|
+ struct vcodec_iommu_ion_info *ion_info = iommu_info->private;
|
||
|
+
|
||
|
+ ion_buffer = kzalloc(sizeof(*ion_buffer), GFP_KERNEL);
|
||
|
+ if (!ion_buffer)
|
||
|
+ return -ENOMEM;
|
||
|
+
|
||
|
+ ion_buffer->handle = ion_import_dma_buf(ion_info->ion_client, fd);
|
||
|
+
|
||
|
+ INIT_LIST_HEAD(&ion_buffer->list);
|
||
|
+ mutex_lock(&session_info->list_mutex);
|
||
|
+ ion_buffer->index = session_info->max_idx;
|
||
|
+ list_add_tail(&ion_buffer->list, &session_info->buffer_list);
|
||
|
+ session_info->max_idx++;
|
||
|
+ if ((session_info->max_idx & 0xfffffff) == 0)
|
||
|
+ session_info->max_idx = 0;
|
||
|
+ mutex_unlock(&session_info->list_mutex);
|
||
|
+
|
||
|
+ return ion_buffer->index;
|
||
|
+}
|
||
|
+
|
||
|
+static int vcodec_ion_create(struct vcodec_iommu_info *iommu_info)
|
||
|
+{
|
||
|
+ struct vcodec_iommu_ion_info *ion_info;
|
||
|
+
|
||
|
+ iommu_info->private = kmalloc(sizeof(*ion_info), GFP_KERNEL);
|
||
|
+
|
||
|
+ ion_info = iommu_info->private;
|
||
|
+ if (!ion_info)
|
||
|
+ return -ENOMEM;
|
||
|
+
|
||
|
+ ion_info->ion_client = rockchip_ion_client_create("vpu");
|
||
|
+ ion_info->attached = false;
|
||
|
+
|
||
|
+ vcodec_ion_attach(iommu_info);
|
||
|
+
|
||
|
+ return IS_ERR(ion_info->ion_client) ? -1 : 0;
|
||
|
+}
|
||
|
+
|
||
|
+static struct vcodec_iommu_ops ion_ops = {
|
||
|
+ .create = vcodec_ion_create,
|
||
|
+ .destroy = vcodec_ion_destroy,
|
||
|
+ .import = vcodec_ion_import,
|
||
|
+ .free = vcodec_ion_free,
|
||
|
+ .free_fd = NULL,
|
||
|
+ .map_kernel = vcodec_ion_map_kernel,
|
||
|
+ .unmap_kernel = vcodec_ion_unmap_kernel,
|
||
|
+ .map_iommu = vcodec_ion_map_iommu,
|
||
|
+ .unmap_iommu = vcodec_ion_unmap_iommu,
|
||
|
+ .dump = NULL,
|
||
|
+ .attach = vcodec_ion_attach,
|
||
|
+ .detach = vcodec_ion_detach,
|
||
|
+ .clear = vcodec_ion_clear_session,
|
||
|
+};
|
||
|
+
|
||
|
+/*
|
||
|
+ * we do not manage the ref number ourselves,
|
||
|
+ * since ion will help us to do that. what we
|
||
|
+ * need to do is just map/unmap and import/free
|
||
|
+ * every time
|
||
|
+ */
|
||
|
+void vcodec_iommu_ion_set_ops(struct vcodec_iommu_info *iommu_info)
|
||
|
+{
|
||
|
+ if (!iommu_info)
|
||
|
+ return;
|
||
|
+ iommu_info->ops = &ion_ops;
|
||
|
+}
|
||
|
diff --git a/drivers/video/rk_vcodec/vcodec_iommu_ops.c b/drivers/video/rk_vcodec/vcodec_iommu_ops.c
|
||
|
new file mode 100644
|
||
|
index 0000000..bb25db4
|
||
|
--- /dev/null
|
||
|
+++ b/drivers/video/rk_vcodec/vcodec_iommu_ops.c
|
||
|
@@ -0,0 +1,256 @@
|
||
|
+/**
|
||
|
+ * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd
|
||
|
+ * author: Jung Zhao jung.zhao@rock-chips.com
|
||
|
+ * Randy Li, randy.li@rock-chips.com
|
||
|
+ *
|
||
|
+ * This software is licensed under the terms of the GNU General Public
|
||
|
+ * License version 2, as published by the Free Software Foundation, and
|
||
|
+ * may be copied, distributed, and modified under those terms.
|
||
|
+ *
|
||
|
+ * 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.
|
||
|
+ *
|
||
|
+ */
|
||
|
+
|
||
|
+#include <linux/slab.h>
|
||
|
+
|
||
|
+#include "vcodec_iommu_ops.h"
|
||
|
+
|
||
|
+static
|
||
|
+struct vcodec_iommu_session_info *vcodec_iommu_get_session_info
|
||
|
+ (struct vcodec_iommu_info *iommu_info, struct vpu_session *session)
|
||
|
+{
|
||
|
+ struct vcodec_iommu_session_info *session_info = NULL, *n;
|
||
|
+
|
||
|
+ list_for_each_entry_safe(session_info, n, &iommu_info->session_list,
|
||
|
+ head) {
|
||
|
+ if (session_info->session == session)
|
||
|
+ return session_info;
|
||
|
+ }
|
||
|
+
|
||
|
+ return NULL;
|
||
|
+}
|
||
|
+
|
||
|
+int vcodec_iommu_create(struct vcodec_iommu_info *iommu_info)
|
||
|
+{
|
||
|
+ if (!iommu_info || !iommu_info->ops->create)
|
||
|
+ return -EINVAL;
|
||
|
+
|
||
|
+ return iommu_info->ops->create(iommu_info);
|
||
|
+}
|
||
|
+
|
||
|
+int vcodec_iommu_import(struct vcodec_iommu_info *iommu_info,
|
||
|
+ struct vpu_session *session, int fd)
|
||
|
+{
|
||
|
+ struct vcodec_iommu_session_info *session_info = NULL;
|
||
|
+
|
||
|
+ if (!iommu_info || !iommu_info->ops->import || !session)
|
||
|
+ return -EINVAL;
|
||
|
+
|
||
|
+ session_info = vcodec_iommu_get_session_info(iommu_info, session);
|
||
|
+ if (!session_info) {
|
||
|
+ session_info = kzalloc(sizeof(*session_info), GFP_KERNEL);
|
||
|
+ if (!session_info)
|
||
|
+ return -ENOMEM;
|
||
|
+
|
||
|
+ INIT_LIST_HEAD(&session_info->head);
|
||
|
+ INIT_LIST_HEAD(&session_info->buffer_list);
|
||
|
+ mutex_init(&session_info->list_mutex);
|
||
|
+ session_info->max_idx = 0;
|
||
|
+ session_info->session = session;
|
||
|
+ session_info->mmu_dev = iommu_info->mmu_dev;
|
||
|
+ session_info->dev = iommu_info->dev;
|
||
|
+ session_info->iommu_info = iommu_info;
|
||
|
+ session_info->buffer_nums = 0;
|
||
|
+ mutex_lock(&iommu_info->list_mutex);
|
||
|
+ list_add_tail(&session_info->head, &iommu_info->session_list);
|
||
|
+ mutex_unlock(&iommu_info->list_mutex);
|
||
|
+ }
|
||
|
+
|
||
|
+ session_info->debug_level = iommu_info->debug_level;
|
||
|
+
|
||
|
+ return iommu_info->ops->import(session_info, fd);
|
||
|
+}
|
||
|
+
|
||
|
+int vcodec_iommu_free(struct vcodec_iommu_info *iommu_info,
|
||
|
+ struct vpu_session *session, int idx)
|
||
|
+{
|
||
|
+ struct vcodec_iommu_session_info *session_info = NULL;
|
||
|
+
|
||
|
+ session_info = vcodec_iommu_get_session_info(iommu_info, session);
|
||
|
+
|
||
|
+ if (!iommu_info || !iommu_info->ops->free || !session_info)
|
||
|
+ return -EINVAL;
|
||
|
+
|
||
|
+ return iommu_info->ops->free(session_info, idx);
|
||
|
+}
|
||
|
+
|
||
|
+int vcodec_iommu_free_fd(struct vcodec_iommu_info *iommu_info,
|
||
|
+ struct vpu_session *session, int fd)
|
||
|
+{
|
||
|
+ struct vcodec_iommu_session_info *session_info = NULL;
|
||
|
+
|
||
|
+ session_info = vcodec_iommu_get_session_info(iommu_info, session);
|
||
|
+
|
||
|
+ if (!iommu_info || !iommu_info->ops->free_fd || !session_info)
|
||
|
+ return -EINVAL;
|
||
|
+
|
||
|
+ return iommu_info->ops->free_fd(session_info, fd);
|
||
|
+}
|
||
|
+
|
||
|
+void *vcodec_iommu_map_kernel(struct vcodec_iommu_info *iommu_info,
|
||
|
+ struct vpu_session *session, int idx)
|
||
|
+{
|
||
|
+ struct vcodec_iommu_session_info *session_info = NULL;
|
||
|
+
|
||
|
+ session_info = vcodec_iommu_get_session_info(iommu_info, session);
|
||
|
+
|
||
|
+ if (!iommu_info || !iommu_info->ops->map_kernel || !session_info)
|
||
|
+ return NULL;
|
||
|
+
|
||
|
+ return iommu_info->ops->map_kernel(session_info, idx);
|
||
|
+}
|
||
|
+
|
||
|
+int vcodec_iommu_unmap_kernel(struct vcodec_iommu_info *iommu_info,
|
||
|
+ struct vpu_session *session, int idx)
|
||
|
+{
|
||
|
+ struct vcodec_iommu_session_info *session_info = NULL;
|
||
|
+
|
||
|
+ session_info = vcodec_iommu_get_session_info(iommu_info, session);
|
||
|
+
|
||
|
+ if (!iommu_info || !iommu_info->ops->unmap_kernel || !session_info)
|
||
|
+ return -EINVAL;
|
||
|
+
|
||
|
+ return iommu_info->ops->unmap_kernel(session_info, idx);
|
||
|
+}
|
||
|
+
|
||
|
+int vcodec_iommu_map_iommu(struct vcodec_iommu_info *iommu_info,
|
||
|
+ struct vpu_session *session,
|
||
|
+ int idx, unsigned long *iova,
|
||
|
+ unsigned long *size)
|
||
|
+{
|
||
|
+ struct vcodec_iommu_session_info *session_info = NULL;
|
||
|
+
|
||
|
+ session_info = vcodec_iommu_get_session_info(iommu_info, session);
|
||
|
+
|
||
|
+ if (!iommu_info || !iommu_info->ops->map_iommu || !session_info)
|
||
|
+ return -EINVAL;
|
||
|
+
|
||
|
+ return iommu_info->ops->map_iommu(session_info, idx, iova, size);
|
||
|
+}
|
||
|
+
|
||
|
+int vcodec_iommu_unmap_iommu(struct vcodec_iommu_info *iommu_info,
|
||
|
+ struct vpu_session *session, int idx)
|
||
|
+{
|
||
|
+ struct vcodec_iommu_session_info *session_info = NULL;
|
||
|
+
|
||
|
+ session_info = vcodec_iommu_get_session_info(iommu_info, session);
|
||
|
+
|
||
|
+ if (!iommu_info || !iommu_info->ops->unmap_iommu || !session_info)
|
||
|
+ return -EINVAL;
|
||
|
+
|
||
|
+ return iommu_info->ops->unmap_iommu(session_info, idx);
|
||
|
+}
|
||
|
+
|
||
|
+int vcodec_iommu_destroy(struct vcodec_iommu_info *iommu_info)
|
||
|
+{
|
||
|
+ if (!iommu_info || !iommu_info->ops->destroy)
|
||
|
+ return -EINVAL;
|
||
|
+
|
||
|
+ return iommu_info->ops->destroy(iommu_info);
|
||
|
+}
|
||
|
+
|
||
|
+void vcodec_iommu_dump(struct vcodec_iommu_info *iommu_info,
|
||
|
+ struct vpu_session *session)
|
||
|
+{
|
||
|
+ struct vcodec_iommu_session_info *session_info = NULL;
|
||
|
+
|
||
|
+ session_info = vcodec_iommu_get_session_info(iommu_info, session);
|
||
|
+
|
||
|
+ if (!iommu_info || !iommu_info->ops->dump || !session_info)
|
||
|
+ return;
|
||
|
+
|
||
|
+ iommu_info->ops->dump(session_info);
|
||
|
+}
|
||
|
+
|
||
|
+void vcodec_iommu_clear(struct vcodec_iommu_info *iommu_info,
|
||
|
+ struct vpu_session *session)
|
||
|
+{
|
||
|
+ struct vcodec_iommu_session_info *session_info = NULL;
|
||
|
+
|
||
|
+ session_info = vcodec_iommu_get_session_info(iommu_info, session);
|
||
|
+
|
||
|
+ if (!iommu_info || !iommu_info->ops->clear || !session_info)
|
||
|
+ return;
|
||
|
+
|
||
|
+ iommu_info->ops->clear(session_info);
|
||
|
+
|
||
|
+ mutex_lock(&iommu_info->list_mutex);
|
||
|
+ list_del_init(&session_info->head);
|
||
|
+ kfree(session_info);
|
||
|
+ mutex_unlock(&iommu_info->list_mutex);
|
||
|
+}
|
||
|
+
|
||
|
+int vcodec_iommu_attach(struct vcodec_iommu_info *iommu_info)
|
||
|
+{
|
||
|
+ if (!iommu_info || !iommu_info->ops->attach)
|
||
|
+ return 0;
|
||
|
+
|
||
|
+ return iommu_info->ops->attach(iommu_info);
|
||
|
+}
|
||
|
+
|
||
|
+void vcodec_iommu_detach(struct vcodec_iommu_info *iommu_info)
|
||
|
+{
|
||
|
+ if (!iommu_info || !iommu_info->ops->detach)
|
||
|
+ return;
|
||
|
+
|
||
|
+ return iommu_info->ops->detach(iommu_info);
|
||
|
+}
|
||
|
+
|
||
|
+struct vcodec_iommu_info *
|
||
|
+vcodec_iommu_info_create(struct device *dev,
|
||
|
+ struct device *mmu_dev,
|
||
|
+ int alloc_type)
|
||
|
+{
|
||
|
+ struct vcodec_iommu_info *iommu_info = NULL;
|
||
|
+
|
||
|
+ iommu_info = kzalloc(sizeof(*iommu_info), GFP_KERNEL);
|
||
|
+ if (!iommu_info)
|
||
|
+ return NULL;
|
||
|
+
|
||
|
+ iommu_info->dev = dev;
|
||
|
+ INIT_LIST_HEAD(&iommu_info->session_list);
|
||
|
+ mutex_init(&iommu_info->list_mutex);
|
||
|
+ mutex_init(&iommu_info->iommu_mutex);
|
||
|
+ switch (alloc_type) {
|
||
|
+#ifdef CONFIG_DRM
|
||
|
+ case ALLOCATOR_USE_DRM:
|
||
|
+ vcodec_iommu_drm_set_ops(iommu_info);
|
||
|
+ break;
|
||
|
+#endif
|
||
|
+#ifdef CONFIG_ION
|
||
|
+ case ALLOCATOR_USE_ION:
|
||
|
+ vcodec_iommu_ion_set_ops(iommu_info);
|
||
|
+ break;
|
||
|
+#endif
|
||
|
+ default:
|
||
|
+ iommu_info->ops = NULL;
|
||
|
+ break;
|
||
|
+ }
|
||
|
+
|
||
|
+ iommu_info->mmu_dev = mmu_dev;
|
||
|
+
|
||
|
+ vcodec_iommu_create(iommu_info);
|
||
|
+
|
||
|
+ return iommu_info;
|
||
|
+}
|
||
|
+
|
||
|
+int vcodec_iommu_info_destroy(struct vcodec_iommu_info *iommu_info)
|
||
|
+{
|
||
|
+ vcodec_iommu_destroy(iommu_info);
|
||
|
+ kfree(iommu_info);
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
diff --git a/drivers/video/rk_vcodec/vcodec_iommu_ops.h b/drivers/video/rk_vcodec/vcodec_iommu_ops.h
|
||
|
new file mode 100644
|
||
|
index 0000000..807ad2f
|
||
|
--- /dev/null
|
||
|
+++ b/drivers/video/rk_vcodec/vcodec_iommu_ops.h
|
||
|
@@ -0,0 +1,132 @@
|
||
|
+/**
|
||
|
+ * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd
|
||
|
+ * author: Jung Zhao jung.zhao@rock-chips.com
|
||
|
+ *
|
||
|
+ * This software is licensed under the terms of the GNU General Public
|
||
|
+ * License version 2, as published by the Free Software Foundation, and
|
||
|
+ * may be copied, distributed, and modified under those terms.
|
||
|
+ *
|
||
|
+ * 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 __VCODEC_IOMMU_OPS_H__
|
||
|
+#define __VCODEC_IOMMU_OPS_H__
|
||
|
+
|
||
|
+#include <linux/platform_device.h>
|
||
|
+#include "vcodec_service.h"
|
||
|
+
|
||
|
+#define BUFFER_LIST_MAX_NUMS 30
|
||
|
+
|
||
|
+#define ALLOCATOR_USE_ION 0x00000000
|
||
|
+#define ALLOCATOR_USE_DRM 0x00000001
|
||
|
+
|
||
|
+#define DEBUG_IOMMU_OPS_DUMP 0x00020000
|
||
|
+#define DEBUG_IOMMU_NORMAL 0x00040000
|
||
|
+
|
||
|
+#define vpu_iommu_debug_func(debug_level, type, fmt, args...) \
|
||
|
+ do { \
|
||
|
+ if (unlikely(debug_level & type)) { \
|
||
|
+ pr_info("%s:%d: " fmt, \
|
||
|
+ __func__, __LINE__, ##args); \
|
||
|
+ } \
|
||
|
+ } while (0)
|
||
|
+#define vpu_iommu_debug(debug_level, type, fmt, args...) \
|
||
|
+ do { \
|
||
|
+ if (unlikely(debug_level & type)) { \
|
||
|
+ pr_info(fmt, ##args); \
|
||
|
+ } \
|
||
|
+ } while (0)
|
||
|
+
|
||
|
+struct vcodec_iommu_info;
|
||
|
+struct vcodec_iommu_session_info;
|
||
|
+
|
||
|
+struct vcodec_iommu_ops {
|
||
|
+ int (*create)(struct vcodec_iommu_info *iommu_info);
|
||
|
+ int (*import)(struct vcodec_iommu_session_info *session_info, int fd);
|
||
|
+ int (*free)(struct vcodec_iommu_session_info *session_info, int idx);
|
||
|
+ int (*free_fd)(struct vcodec_iommu_session_info *session_info, int fd);
|
||
|
+ void *(*map_kernel)(struct vcodec_iommu_session_info *session_info,
|
||
|
+ int idx);
|
||
|
+ int (*unmap_kernel)(struct vcodec_iommu_session_info *session_info,
|
||
|
+ int idx);
|
||
|
+ int (*map_iommu)(struct vcodec_iommu_session_info *session_info,
|
||
|
+ int idx,
|
||
|
+ unsigned long *iova, unsigned long *size);
|
||
|
+ int (*unmap_iommu)(struct vcodec_iommu_session_info *session_info,
|
||
|
+ int idx);
|
||
|
+ int (*destroy)(struct vcodec_iommu_info *iommu_info);
|
||
|
+ void (*dump)(struct vcodec_iommu_session_info *session_info);
|
||
|
+ int (*attach)(struct vcodec_iommu_info *iommu_info);
|
||
|
+ void (*detach)(struct vcodec_iommu_info *iommu_info);
|
||
|
+ void (*clear)(struct vcodec_iommu_session_info *session_info);
|
||
|
+};
|
||
|
+
|
||
|
+struct vcodec_iommu_session_info {
|
||
|
+ struct list_head head;
|
||
|
+ struct vpu_session *session;
|
||
|
+ int buffer_nums;
|
||
|
+ struct list_head buffer_list;
|
||
|
+ struct mutex list_mutex;
|
||
|
+ int max_idx;
|
||
|
+ struct device *dev;
|
||
|
+ struct device *mmu_dev;
|
||
|
+ struct vcodec_iommu_info *iommu_info;
|
||
|
+ int debug_level;
|
||
|
+};
|
||
|
+
|
||
|
+struct vcodec_iommu_info {
|
||
|
+ struct list_head session_list;
|
||
|
+ struct mutex list_mutex;
|
||
|
+ struct mutex iommu_mutex;
|
||
|
+ struct device *dev;
|
||
|
+ struct device *mmu_dev;
|
||
|
+ struct vcodec_iommu_ops *ops;
|
||
|
+ int debug_level;
|
||
|
+ void *private;
|
||
|
+};
|
||
|
+
|
||
|
+#ifdef CONFIG_DRM
|
||
|
+void vcodec_iommu_drm_set_ops(struct vcodec_iommu_info *iommu_info);
|
||
|
+#endif
|
||
|
+#ifdef CONFIG_ION
|
||
|
+void vcodec_iommu_ion_set_ops(struct vcodec_iommu_info *iommu_info);
|
||
|
+#endif
|
||
|
+
|
||
|
+struct vcodec_iommu_info *vcodec_iommu_info_create(struct device *dev,
|
||
|
+ struct device *mmu_dev,
|
||
|
+ int alloc_type);
|
||
|
+int vcodec_iommu_info_destroy(struct vcodec_iommu_info *iommu_info);
|
||
|
+
|
||
|
+int vcodec_iommu_create(struct vcodec_iommu_info *iommu_info);
|
||
|
+int vcodec_iommu_import(struct vcodec_iommu_info *iommu_info,
|
||
|
+ struct vpu_session *session, int fd);
|
||
|
+int vcodec_iommu_free(struct vcodec_iommu_info *iommu_info,
|
||
|
+ struct vpu_session *session, int idx);
|
||
|
+int vcodec_iommu_free_fd(struct vcodec_iommu_info *iommu_info,
|
||
|
+ struct vpu_session *session, int fd);
|
||
|
+void *vcodec_iommu_map_kernel(struct vcodec_iommu_info *iommu_info,
|
||
|
+ struct vpu_session *session, int idx);
|
||
|
+int vcodec_iommu_unmap_kernel(struct vcodec_iommu_info *iommu_info,
|
||
|
+ struct vpu_session *session, int idx);
|
||
|
+int vcodec_iommu_map_iommu(struct vcodec_iommu_info *iommu_info,
|
||
|
+ struct vpu_session *session,
|
||
|
+ int idx,
|
||
|
+ unsigned long *iova,
|
||
|
+ unsigned long *size);
|
||
|
+int vcodec_iommu_unmap_iommu(struct vcodec_iommu_info *iommu_info,
|
||
|
+ struct vpu_session *session,
|
||
|
+ int idx);
|
||
|
+int vcodec_iommu_destroy(struct vcodec_iommu_info *iommu_info);
|
||
|
+void vcodec_iommu_dump(struct vcodec_iommu_info *iommu_info,
|
||
|
+ struct vpu_session *session);
|
||
|
+void vcodec_iommu_clear(struct vcodec_iommu_info *iommu_info,
|
||
|
+ struct vpu_session *session);
|
||
|
+
|
||
|
+int vcodec_iommu_attach(struct vcodec_iommu_info *iommu_info);
|
||
|
+void vcodec_iommu_detach(struct vcodec_iommu_info *iommu_info);
|
||
|
+
|
||
|
+#endif
|
||
|
diff --git a/drivers/video/rk_vcodec/vcodec_service.c b/drivers/video/rk_vcodec/vcodec_service.c
|
||
|
new file mode 100755
|
||
|
index 0000000..9d44f12
|
||
|
--- /dev/null
|
||
|
+++ b/drivers/video/rk_vcodec/vcodec_service.c
|
||
|
@@ -0,0 +1,3058 @@
|
||
|
+/**
|
||
|
+ * Copyright (C) 2015 Fuzhou Rockchip Electronics Co., Ltd
|
||
|
+ * author: chenhengming, chm@rock-chips.com
|
||
|
+ * Alpha Lin, alpha.lin@rock-chips.com
|
||
|
+ * Jung Zhao, jung.zhao@rock-chips.com
|
||
|
+ *
|
||
|
+ * This software is licensed under the terms of the GNU General Public
|
||
|
+ * License version 2, as published by the Free Software Foundation, and
|
||
|
+ * may be copied, distributed, and modified under those terms.
|
||
|
+ *
|
||
|
+ * 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.
|
||
|
+ *
|
||
|
+ */
|
||
|
+
|
||
|
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||
|
+
|
||
|
+#include <linux/clk.h>
|
||
|
+#include <linux/compat.h>
|
||
|
+#include <linux/delay.h>
|
||
|
+#include <linux/init.h>
|
||
|
+#include <linux/interrupt.h>
|
||
|
+#include <linux/module.h>
|
||
|
+#include <linux/fs.h>
|
||
|
+#include <linux/mm.h>
|
||
|
+#include <linux/platform_device.h>
|
||
|
+#include <linux/reset.h>
|
||
|
+#include <linux/sched.h>
|
||
|
+#include <linux/slab.h>
|
||
|
+#ifdef CONFIG_WAKELOCK
|
||
|
+#include <linux/wakelock.h>
|
||
|
+#endif
|
||
|
+#include <linux/cdev.h>
|
||
|
+#include <linux/of.h>
|
||
|
+#include <linux/of_platform.h>
|
||
|
+#include <linux/of_irq.h>
|
||
|
+#include <linux/regmap.h>
|
||
|
+#include <linux/mfd/syscon.h>
|
||
|
+#include <linux/uaccess.h>
|
||
|
+#include <linux/debugfs.h>
|
||
|
+#include <linux/pm_runtime.h>
|
||
|
+#include <linux/iopoll.h>
|
||
|
+
|
||
|
+#include <linux/rockchip/cru.h>
|
||
|
+#include <linux/rockchip/pmu.h>
|
||
|
+#include <linux/rockchip/grf.h>
|
||
|
+
|
||
|
+#include <linux/dma-buf.h>
|
||
|
+#include <linux/rockchip-iovmm.h>
|
||
|
+
|
||
|
+#include "vcodec_hw_info.h"
|
||
|
+#include "vcodec_hw_vpu.h"
|
||
|
+#include "vcodec_hw_rkv.h"
|
||
|
+#include "vcodec_hw_vpu2.h"
|
||
|
+
|
||
|
+#include "vcodec_service.h"
|
||
|
+
|
||
|
+#include "vcodec_iommu_ops.h"
|
||
|
+
|
||
|
+/*
|
||
|
+ * debug flag usage:
|
||
|
+ * +------+-------------------+
|
||
|
+ * | 8bit | 24bit |
|
||
|
+ * +------+-------------------+
|
||
|
+ * 0~23 bit is for different information type
|
||
|
+ * 24~31 bit is for information print format
|
||
|
+ */
|
||
|
+
|
||
|
+#define DEBUG_POWER 0x00000001
|
||
|
+#define DEBUG_CLOCK 0x00000002
|
||
|
+#define DEBUG_IRQ_STATUS 0x00000004
|
||
|
+#define DEBUG_IOMMU 0x00000008
|
||
|
+#define DEBUG_IOCTL 0x00000010
|
||
|
+#define DEBUG_FUNCTION 0x00000020
|
||
|
+#define DEBUG_REGISTER 0x00000040
|
||
|
+#define DEBUG_EXTRA_INFO 0x00000080
|
||
|
+#define DEBUG_TIMING 0x00000100
|
||
|
+#define DEBUG_TASK_INFO 0x00000200
|
||
|
+
|
||
|
+#define DEBUG_SET_REG 0x00001000
|
||
|
+#define DEBUG_GET_REG 0x00002000
|
||
|
+#define DEBUG_PPS_FILL 0x00004000
|
||
|
+#define DEBUG_IRQ_CHECK 0x00008000
|
||
|
+#define DEBUG_CACHE_32B 0x00010000
|
||
|
+
|
||
|
+#define PRINT_FUNCTION 0x80000000
|
||
|
+#define PRINT_LINE 0x40000000
|
||
|
+
|
||
|
+#define MHZ (1000 * 1000)
|
||
|
+#define SIZE_REG(reg) ((reg) * 4)
|
||
|
+
|
||
|
+#define VCODEC_CLOCK_ENABLE 1
|
||
|
+#define EXTRA_INFO_MAGIC 0x4C4A46
|
||
|
+
|
||
|
+static int debug;
|
||
|
+module_param(debug, int, S_IRUGO | S_IWUSR);
|
||
|
+MODULE_PARM_DESC(debug, "bit switch for vcodec_service debug information");
|
||
|
+/*
|
||
|
+ * hardware information organization
|
||
|
+ *
|
||
|
+ * In order to support multiple hardware with different version the hardware
|
||
|
+ * information is organized as follow:
|
||
|
+ *
|
||
|
+ * 1. First, index hardware by register size / position.
|
||
|
+ * These information is fix for each hardware and do not relate to runtime
|
||
|
+ * work flow. It only related to resource allocation.
|
||
|
+ * Descriptor: struct vpu_hw_info
|
||
|
+ *
|
||
|
+ * 2. Then, index hardware by runtime configuration
|
||
|
+ * These information is related to runtime setting behave including enable
|
||
|
+ * register, irq register and other key control flag
|
||
|
+ * Descriptor: struct vpu_task_info
|
||
|
+ *
|
||
|
+ * 3. Final, on iommu case the fd translation is required
|
||
|
+ * Descriptor: struct vpu_trans_info
|
||
|
+ */
|
||
|
+
|
||
|
+enum VPU_FREQ {
|
||
|
+ VPU_FREQ_200M,
|
||
|
+ VPU_FREQ_266M,
|
||
|
+ VPU_FREQ_300M,
|
||
|
+ VPU_FREQ_400M,
|
||
|
+ VPU_FREQ_500M,
|
||
|
+ VPU_FREQ_600M,
|
||
|
+ VPU_FREQ_DEFAULT,
|
||
|
+ VPU_FREQ_BUT,
|
||
|
+};
|
||
|
+
|
||
|
+struct extra_info_elem {
|
||
|
+ u32 index;
|
||
|
+ u32 offset;
|
||
|
+};
|
||
|
+
|
||
|
+
|
||
|
+struct extra_info_for_iommu {
|
||
|
+ u32 magic;
|
||
|
+ u32 cnt;
|
||
|
+ struct extra_info_elem elem[20];
|
||
|
+};
|
||
|
+
|
||
|
+static const struct vcodec_info vcodec_info_set[] = {
|
||
|
+ {
|
||
|
+ .hw_id = VPU_ID_8270,
|
||
|
+ .hw_info = &hw_vpu_8270,
|
||
|
+ .task_info = task_vpu,
|
||
|
+ .trans_info = trans_vpu,
|
||
|
+ },
|
||
|
+ {
|
||
|
+ .hw_id = VPU_ID_4831,
|
||
|
+ .hw_info = &hw_vpu_4831,
|
||
|
+ .task_info = task_vpu,
|
||
|
+ .trans_info = trans_vpu,
|
||
|
+ },
|
||
|
+ {
|
||
|
+ .hw_id = VPU_DEC_ID_9190,
|
||
|
+ .hw_info = &hw_vpu_9190,
|
||
|
+ .task_info = task_vpu,
|
||
|
+ .trans_info = trans_vpu,
|
||
|
+ },
|
||
|
+ {
|
||
|
+ .hw_id = HEVC_ID,
|
||
|
+ .hw_info = &hw_rkhevc,
|
||
|
+ .task_info = task_rkv,
|
||
|
+ .trans_info = trans_rkv,
|
||
|
+ },
|
||
|
+ {
|
||
|
+ .hw_id = RKV_DEC_ID,
|
||
|
+ .hw_info = &hw_rkvdec,
|
||
|
+ .task_info = task_rkv,
|
||
|
+ .trans_info = trans_rkv,
|
||
|
+ },
|
||
|
+ {
|
||
|
+ .hw_id = VPU2_ID,
|
||
|
+ .hw_info = &hw_vpu2,
|
||
|
+ .task_info = task_vpu2,
|
||
|
+ .trans_info = trans_vpu2,
|
||
|
+ },
|
||
|
+ {
|
||
|
+ .hw_id = RKV_DEC_ID2,
|
||
|
+ .hw_info = &hw_rkvdec,
|
||
|
+ .task_info = task_rkv,
|
||
|
+ .trans_info = trans_rkv,
|
||
|
+ },
|
||
|
+};
|
||
|
+
|
||
|
+/* Both VPU1 and VPU2 */
|
||
|
+static const struct vcodec_device_info vpu_device_info = {
|
||
|
+ .device_type = VCODEC_DEVICE_TYPE_VPUX,
|
||
|
+ .name = "vpu-service",
|
||
|
+};
|
||
|
+
|
||
|
+static const struct vcodec_device_info vpu_combo_device_info = {
|
||
|
+ .device_type = VCODEC_DEVICE_TYPE_VPUC,
|
||
|
+ .name = "vpu-combo",
|
||
|
+};
|
||
|
+
|
||
|
+static const struct vcodec_device_info hevc_device_info = {
|
||
|
+ .device_type = VCODEC_DEVICE_TYPE_HEVC,
|
||
|
+ .name = "hevc-service",
|
||
|
+};
|
||
|
+
|
||
|
+static const struct vcodec_device_info rkvd_device_info = {
|
||
|
+ .device_type = VCODEC_DEVICE_TYPE_RKVD,
|
||
|
+ .name = "rkvdec",
|
||
|
+};
|
||
|
+
|
||
|
+#define DEBUG
|
||
|
+#ifdef DEBUG
|
||
|
+#define vpu_debug_func(type, fmt, args...) \
|
||
|
+ do { \
|
||
|
+ if (unlikely(debug & type)) { \
|
||
|
+ pr_info("%s:%d: " fmt, \
|
||
|
+ __func__, __LINE__, ##args); \
|
||
|
+ } \
|
||
|
+ } while (0)
|
||
|
+#define vpu_debug(type, fmt, args...) \
|
||
|
+ do { \
|
||
|
+ if (unlikely(debug & type)) { \
|
||
|
+ pr_info(fmt, ##args); \
|
||
|
+ } \
|
||
|
+ } while (0)
|
||
|
+#else
|
||
|
+#define vpu_debug_func(level, fmt, args...)
|
||
|
+#define vpu_debug(level, fmt, args...)
|
||
|
+#endif
|
||
|
+
|
||
|
+#define vpu_debug_enter() vpu_debug_func(DEBUG_FUNCTION, "enter\n")
|
||
|
+#define vpu_debug_leave() vpu_debug_func(DEBUG_FUNCTION, "leave\n")
|
||
|
+
|
||
|
+#define vpu_err(fmt, args...) \
|
||
|
+ pr_err("%s:%d: " fmt, __func__, __LINE__, ##args)
|
||
|
+
|
||
|
+enum VPU_DEC_FMT {
|
||
|
+ VPU_DEC_FMT_H264,
|
||
|
+ VPU_DEC_FMT_MPEG4,
|
||
|
+ VPU_DEC_FMT_H263,
|
||
|
+ VPU_DEC_FMT_JPEG,
|
||
|
+ VPU_DEC_FMT_VC1,
|
||
|
+ VPU_DEC_FMT_MPEG2,
|
||
|
+ VPU_DEC_FMT_MPEG1,
|
||
|
+ VPU_DEC_FMT_VP6,
|
||
|
+ VPU_DEC_FMT_RESERV0,
|
||
|
+ VPU_DEC_FMT_VP7,
|
||
|
+ VPU_DEC_FMT_VP8,
|
||
|
+ VPU_DEC_FMT_AVS,
|
||
|
+ VPU_DEC_FMT_RES
|
||
|
+};
|
||
|
+
|
||
|
+/**
|
||
|
+ * struct for process session which connect to vpu
|
||
|
+ *
|
||
|
+ * @author ChenHengming (2011-5-3)
|
||
|
+ */
|
||
|
+struct vpu_session {
|
||
|
+ enum VPU_CLIENT_TYPE type;
|
||
|
+ /* a linked list of data so we can access them for debugging */
|
||
|
+ struct list_head list_session;
|
||
|
+ /* a linked list of register data waiting for process */
|
||
|
+ struct list_head waiting;
|
||
|
+ /* a linked list of register data in processing */
|
||
|
+ struct list_head running;
|
||
|
+ /* a linked list of register data processed */
|
||
|
+ struct list_head done;
|
||
|
+ wait_queue_head_t wait;
|
||
|
+ pid_t pid;
|
||
|
+ atomic_t task_running;
|
||
|
+};
|
||
|
+
|
||
|
+/**
|
||
|
+ * struct for process register set
|
||
|
+ *
|
||
|
+ * @author ChenHengming (2011-5-4)
|
||
|
+ */
|
||
|
+struct vpu_reg {
|
||
|
+ enum VPU_CLIENT_TYPE type;
|
||
|
+ enum VPU_FREQ freq;
|
||
|
+ struct vpu_session *session;
|
||
|
+ struct vpu_subdev_data *data;
|
||
|
+ struct vpu_task_info *task;
|
||
|
+ const struct vpu_trans_info *trans;
|
||
|
+
|
||
|
+ /* link to vpu service session */
|
||
|
+ struct list_head session_link;
|
||
|
+ /* link to register set list */
|
||
|
+ struct list_head status_link;
|
||
|
+
|
||
|
+ unsigned long size;
|
||
|
+ struct list_head mem_region_list;
|
||
|
+ u32 dec_base;
|
||
|
+ u32 *reg;
|
||
|
+};
|
||
|
+
|
||
|
+struct vpu_device {
|
||
|
+ atomic_t irq_count_codec;
|
||
|
+ atomic_t irq_count_pp;
|
||
|
+ unsigned int iosize;
|
||
|
+ u32 *regs;
|
||
|
+};
|
||
|
+
|
||
|
+enum vcodec_device_id {
|
||
|
+ VCODEC_DEVICE_ID_VPU,
|
||
|
+ VCODEC_DEVICE_ID_HEVC,
|
||
|
+ VCODEC_DEVICE_ID_COMBO,
|
||
|
+ VCODEC_DEVICE_ID_RKVDEC,
|
||
|
+ VCODEC_DEVICE_ID_BUTT
|
||
|
+};
|
||
|
+
|
||
|
+enum VCODEC_RUNNING_MODE {
|
||
|
+ VCODEC_RUNNING_MODE_NONE = -1,
|
||
|
+ VCODEC_RUNNING_MODE_VPU,
|
||
|
+ VCODEC_RUNNING_MODE_HEVC,
|
||
|
+ VCODEC_RUNNING_MODE_RKVDEC
|
||
|
+};
|
||
|
+
|
||
|
+struct vcodec_mem_region {
|
||
|
+ struct list_head srv_lnk;
|
||
|
+ struct list_head reg_lnk;
|
||
|
+ struct list_head session_lnk;
|
||
|
+ unsigned long iova; /* virtual address for iommu */
|
||
|
+ unsigned long len;
|
||
|
+ u32 reg_idx;
|
||
|
+ int hdl;
|
||
|
+};
|
||
|
+
|
||
|
+enum vpu_ctx_state {
|
||
|
+ MMU_ACTIVATED = BIT(0)
|
||
|
+};
|
||
|
+
|
||
|
+struct vpu_subdev_data {
|
||
|
+ struct cdev cdev;
|
||
|
+ dev_t dev_t;
|
||
|
+ struct class *cls;
|
||
|
+ struct device *child_dev;
|
||
|
+
|
||
|
+ int irq_enc;
|
||
|
+ int irq_dec;
|
||
|
+ struct vpu_service_info *pservice;
|
||
|
+
|
||
|
+ u32 *regs;
|
||
|
+ enum VCODEC_RUNNING_MODE mode;
|
||
|
+ struct list_head lnk_service;
|
||
|
+
|
||
|
+ struct device *dev;
|
||
|
+
|
||
|
+ struct vpu_device enc_dev;
|
||
|
+ struct vpu_device dec_dev;
|
||
|
+
|
||
|
+ enum VPU_HW_ID hw_id;
|
||
|
+ struct vpu_hw_info *hw_info;
|
||
|
+ struct vpu_task_info *task_info;
|
||
|
+ const struct vpu_trans_info *trans_info;
|
||
|
+
|
||
|
+ u32 reg_size;
|
||
|
+ unsigned long state;
|
||
|
+
|
||
|
+#ifdef CONFIG_DEBUG_FS
|
||
|
+ struct dentry *debugfs_dir;
|
||
|
+ struct dentry *debugfs_file_regs;
|
||
|
+#endif
|
||
|
+
|
||
|
+ struct device *mmu_dev;
|
||
|
+ struct vcodec_iommu_info *iommu_info;
|
||
|
+ struct work_struct set_work;
|
||
|
+};
|
||
|
+
|
||
|
+struct vpu_service_info {
|
||
|
+#ifdef CONFIG_WAKELOCK
|
||
|
+ struct wake_lock wake_lock;
|
||
|
+ struct wake_lock set_wake_lock;
|
||
|
+#endif
|
||
|
+
|
||
|
+ struct delayed_work power_off_work;
|
||
|
+ struct workqueue_struct *set_workq;
|
||
|
+ ktime_t last; /* record previous power-on time */
|
||
|
+ /* vpu service structure global lock */
|
||
|
+ struct mutex lock;
|
||
|
+ /* link to link_reg in struct vpu_reg */
|
||
|
+ struct list_head waiting;
|
||
|
+ /* link to link_reg in struct vpu_reg */
|
||
|
+ struct list_head running;
|
||
|
+ /* link to link_reg in struct vpu_reg */
|
||
|
+ struct list_head done;
|
||
|
+ /* link to list_session in struct vpu_session */
|
||
|
+ struct list_head session;
|
||
|
+ atomic_t total_running;
|
||
|
+ atomic_t enabled;
|
||
|
+ atomic_t power_on_cnt;
|
||
|
+ atomic_t power_off_cnt;
|
||
|
+ atomic_t service_on;
|
||
|
+ struct mutex shutdown_lock;
|
||
|
+ struct vpu_reg *reg_codec;
|
||
|
+ struct vpu_reg *reg_pproc;
|
||
|
+ struct vpu_reg *reg_resev;
|
||
|
+ struct vpu_dec_config dec_config;
|
||
|
+ struct vpu_enc_config enc_config;
|
||
|
+
|
||
|
+ bool auto_freq;
|
||
|
+ bool bug_dec_addr;
|
||
|
+ atomic_t freq_status;
|
||
|
+
|
||
|
+ struct clk *aclk_vcodec;
|
||
|
+ struct clk *hclk_vcodec;
|
||
|
+ struct clk *clk_core;
|
||
|
+ struct clk *clk_cabac;
|
||
|
+ struct clk *pd_video;
|
||
|
+
|
||
|
+#ifdef CONFIG_RESET_CONTROLLER
|
||
|
+ struct reset_control *rst_a;
|
||
|
+ struct reset_control *rst_h;
|
||
|
+ struct reset_control *rst_v;
|
||
|
+ struct reset_control *rst_niu_a;
|
||
|
+ struct reset_control *rst_niu_h;
|
||
|
+#endif
|
||
|
+ struct device *dev;
|
||
|
+
|
||
|
+ u32 irq_status;
|
||
|
+ atomic_t reset_request;
|
||
|
+ struct list_head mem_region_list;
|
||
|
+
|
||
|
+ enum vcodec_device_id dev_id;
|
||
|
+
|
||
|
+ enum VCODEC_RUNNING_MODE curr_mode;
|
||
|
+ u32 prev_mode;
|
||
|
+
|
||
|
+ struct delayed_work simulate_work;
|
||
|
+
|
||
|
+ u32 mode_bit;
|
||
|
+ u32 mode_ctrl;
|
||
|
+ u32 *reg_base;
|
||
|
+ u32 ioaddr;
|
||
|
+ struct regmap *grf;
|
||
|
+ u32 *grf_base;
|
||
|
+
|
||
|
+ char *name;
|
||
|
+
|
||
|
+ u32 subcnt;
|
||
|
+ struct list_head subdev_list;
|
||
|
+
|
||
|
+ u32 alloc_type;
|
||
|
+};
|
||
|
+
|
||
|
+struct vpu_request {
|
||
|
+ u32 *req;
|
||
|
+ u32 size;
|
||
|
+};
|
||
|
+
|
||
|
+#ifdef CONFIG_COMPAT
|
||
|
+struct compat_vpu_request {
|
||
|
+ compat_uptr_t req;
|
||
|
+ u32 size;
|
||
|
+};
|
||
|
+#endif
|
||
|
+
|
||
|
+#define VDPU_SOFT_RESET_REG 101
|
||
|
+#define VDPU_CLEAN_CACHE_REG 516
|
||
|
+#define VEPU_CLEAN_CACHE_REG 772
|
||
|
+#define HEVC_CLEAN_CACHE_REG 260
|
||
|
+
|
||
|
+#define VPU_REG_ENABLE(base, reg) writel_relaxed(1, base + reg)
|
||
|
+
|
||
|
+#define VDPU_SOFT_RESET(base) VPU_REG_ENABLE(base, VDPU_SOFT_RESET_REG)
|
||
|
+#define VDPU_CLEAN_CACHE(base) VPU_REG_ENABLE(base, VDPU_CLEAN_CACHE_REG)
|
||
|
+#define VEPU_CLEAN_CACHE(base) VPU_REG_ENABLE(base, VEPU_CLEAN_CACHE_REG)
|
||
|
+#define HEVC_CLEAN_CACHE(base) VPU_REG_ENABLE(base, HEVC_CLEAN_CACHE_REG)
|
||
|
+
|
||
|
+#define VPU_POWER_OFF_DELAY (4 * HZ) /* 4s */
|
||
|
+#define VPU_TIMEOUT_DELAY (2 * HZ) /* 2s */
|
||
|
+
|
||
|
+static void *vcodec_get_drv_data(struct platform_device *pdev);
|
||
|
+
|
||
|
+static void vpu_service_power_on(struct vpu_subdev_data *data,
|
||
|
+ struct vpu_service_info *pservice);
|
||
|
+
|
||
|
+static void time_record(struct vpu_task_info *task, int is_end)
|
||
|
+{
|
||
|
+ if (unlikely(debug & DEBUG_TIMING) && task)
|
||
|
+ do_gettimeofday((is_end) ? (&task->end) : (&task->start));
|
||
|
+}
|
||
|
+
|
||
|
+static void time_diff(struct vpu_task_info *task)
|
||
|
+{
|
||
|
+ vpu_debug(DEBUG_TIMING, "%s task: %ld ms\n", task->name,
|
||
|
+ (task->end.tv_sec - task->start.tv_sec) * 1000 +
|
||
|
+ (task->end.tv_usec - task->start.tv_usec) / 1000);
|
||
|
+}
|
||
|
+
|
||
|
+static inline int try_reset_assert(struct reset_control *rst)
|
||
|
+{
|
||
|
+ if (rst)
|
||
|
+ return reset_control_assert(rst);
|
||
|
+ return -EINVAL;
|
||
|
+}
|
||
|
+
|
||
|
+static inline int try_reset_deassert(struct reset_control *rst)
|
||
|
+{
|
||
|
+ if (rst)
|
||
|
+ return reset_control_deassert(rst);
|
||
|
+ return -EINVAL;
|
||
|
+}
|
||
|
+
|
||
|
+static inline int grf_combo_switch(const struct vpu_subdev_data *data)
|
||
|
+{
|
||
|
+ struct vpu_service_info *pservice = data->pservice;
|
||
|
+ int bits;
|
||
|
+ u32 raw = 0;
|
||
|
+
|
||
|
+ bits = 1 << pservice->mode_bit;
|
||
|
+#ifdef CONFIG_MFD_SYSCON
|
||
|
+ if (pservice->grf) {
|
||
|
+ regmap_read(pservice->grf, pservice->mode_ctrl, &raw);
|
||
|
+
|
||
|
+ if (data->mode == VCODEC_RUNNING_MODE_HEVC)
|
||
|
+ regmap_write(pservice->grf, pservice->mode_ctrl,
|
||
|
+ raw | bits | (bits << 16));
|
||
|
+ else
|
||
|
+ regmap_write(pservice->grf, pservice->mode_ctrl,
|
||
|
+ (raw & (~bits)) | (bits << 16));
|
||
|
+ } else if (pservice->grf_base) {
|
||
|
+ u32 *grf_base = pservice->grf_base;
|
||
|
+
|
||
|
+ raw = readl_relaxed(grf_base + pservice->mode_ctrl / 4);
|
||
|
+ if (data->mode == VCODEC_RUNNING_MODE_HEVC)
|
||
|
+ writel_relaxed(raw | bits | (bits << 16),
|
||
|
+ grf_base + pservice->mode_ctrl / 4);
|
||
|
+ else
|
||
|
+ writel_relaxed((raw & (~bits)) | (bits << 16),
|
||
|
+ grf_base + pservice->mode_ctrl / 4);
|
||
|
+ } else {
|
||
|
+ vpu_err("no grf resource define, switch decoder failed\n");
|
||
|
+ return -EINVAL;
|
||
|
+ }
|
||
|
+#else
|
||
|
+ if (pservice->grf_base) {
|
||
|
+ u32 *grf_base = pservice->grf_base;
|
||
|
+
|
||
|
+ raw = readl_relaxed(grf_base + pservice->mode_ctrl / 4);
|
||
|
+ if (data->mode == VCODEC_RUNNING_MODE_HEVC)
|
||
|
+ writel_relaxed(raw | bits | (bits << 16),
|
||
|
+ grf_base + pservice->mode_ctrl / 4);
|
||
|
+ else
|
||
|
+ writel_relaxed((raw & (~bits)) | (bits << 16),
|
||
|
+ grf_base + pservice->mode_ctrl / 4);
|
||
|
+ } else {
|
||
|
+ vpu_err("no grf resource define, switch decoder failed\n");
|
||
|
+ return -EINVAL;
|
||
|
+ }
|
||
|
+#endif
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static void vcodec_enter_mode(struct vpu_subdev_data *data)
|
||
|
+{
|
||
|
+ struct vpu_service_info *pservice = data->pservice;
|
||
|
+ struct vpu_subdev_data *subdata, *n;
|
||
|
+
|
||
|
+ if (pservice->subcnt < 2 || pservice->mode_ctrl == 0) {
|
||
|
+ if (data->mmu_dev && !test_bit(MMU_ACTIVATED, &data->state)) {
|
||
|
+ set_bit(MMU_ACTIVATED, &data->state);
|
||
|
+
|
||
|
+ if (atomic_read(&pservice->enabled)) {
|
||
|
+ if (vcodec_iommu_attach(data->iommu_info))
|
||
|
+ dev_err(data->dev,
|
||
|
+ "vcodec service attach failed\n"
|
||
|
+ );
|
||
|
+ else
|
||
|
+ /* Stop here is enough */
|
||
|
+ return;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (pservice->curr_mode == data->mode)
|
||
|
+ return;
|
||
|
+
|
||
|
+ vpu_debug(DEBUG_IOMMU, "vcodec enter mode %d\n", data->mode);
|
||
|
+ list_for_each_entry_safe(subdata, n,
|
||
|
+ &pservice->subdev_list, lnk_service) {
|
||
|
+ if (data != subdata && subdata->mmu_dev &&
|
||
|
+ test_bit(MMU_ACTIVATED, &subdata->state)) {
|
||
|
+ clear_bit(MMU_ACTIVATED, &subdata->state);
|
||
|
+ vcodec_iommu_detach(subdata->iommu_info);
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ /*
|
||
|
+ * For the RK3228H, it is not necessary to write a register to
|
||
|
+ * switch vpu combo mode, it is unsafe to write the grf.
|
||
|
+ */
|
||
|
+ if (pservice->mode_ctrl)
|
||
|
+ if (grf_combo_switch(data))
|
||
|
+ return;
|
||
|
+
|
||
|
+ if (data->mmu_dev && !test_bit(MMU_ACTIVATED, &data->state)) {
|
||
|
+ set_bit(MMU_ACTIVATED, &data->state);
|
||
|
+ if (atomic_read(&pservice->enabled))
|
||
|
+ vcodec_iommu_attach(data->iommu_info);
|
||
|
+ else
|
||
|
+ /* FIXME BUG_ON should not be used in mass produce */
|
||
|
+ BUG_ON(!atomic_read(&pservice->enabled));
|
||
|
+ }
|
||
|
+
|
||
|
+ pservice->prev_mode = pservice->curr_mode;
|
||
|
+ pservice->curr_mode = data->mode;
|
||
|
+}
|
||
|
+
|
||
|
+static void vcodec_exit_mode(struct vpu_subdev_data *data)
|
||
|
+{
|
||
|
+ /*
|
||
|
+ * In case of VPU Combo, it require HW switch its running mode
|
||
|
+ * before the other HW component start work. set current HW running
|
||
|
+ * mode to none, can ensure HW switch to its reqired mode properly.
|
||
|
+ */
|
||
|
+ data->pservice->curr_mode = VCODEC_RUNNING_MODE_NONE;
|
||
|
+}
|
||
|
+
|
||
|
+static int vpu_get_clk(struct vpu_service_info *pservice)
|
||
|
+{
|
||
|
+#if VCODEC_CLOCK_ENABLE
|
||
|
+ struct device *dev = pservice->dev;
|
||
|
+
|
||
|
+ switch (pservice->dev_id) {
|
||
|
+ case VCODEC_DEVICE_ID_HEVC:
|
||
|
+ /* We won't regard the power domain as clocks at 4.4 */
|
||
|
+ pservice->pd_video = devm_clk_get(dev, "pd_hevc");
|
||
|
+ if (IS_ERR(pservice->pd_video)) {
|
||
|
+ pservice->pd_video = NULL;
|
||
|
+ dev_dbg(dev, "failed on clk_get pd_hevc\n");
|
||
|
+ }
|
||
|
+ case VCODEC_DEVICE_ID_COMBO:
|
||
|
+ case VCODEC_DEVICE_ID_RKVDEC:
|
||
|
+ pservice->clk_cabac = devm_clk_get(dev, "clk_cabac");
|
||
|
+ if (IS_ERR(pservice->clk_cabac)) {
|
||
|
+ dev_err(dev, "failed on clk_get clk_cabac\n");
|
||
|
+ pservice->clk_cabac = NULL;
|
||
|
+ }
|
||
|
+ pservice->clk_core = devm_clk_get(dev, "clk_core");
|
||
|
+ if (IS_ERR(pservice->clk_core)) {
|
||
|
+ dev_err(dev, "failed on clk_get clk_core\n");
|
||
|
+ pservice->clk_core = NULL;
|
||
|
+ /* The VDPU and AVSD combo doesn't need those clocks */
|
||
|
+ if (pservice->dev_id == VCODEC_DEVICE_ID_RKVDEC)
|
||
|
+ return -1;
|
||
|
+ }
|
||
|
+ case VCODEC_DEVICE_ID_VPU:
|
||
|
+ pservice->aclk_vcodec = devm_clk_get(dev, "aclk_vcodec");
|
||
|
+ if (IS_ERR(pservice->aclk_vcodec)) {
|
||
|
+ dev_err(dev, "failed on clk_get aclk_vcodec\n");
|
||
|
+ pservice->aclk_vcodec = NULL;
|
||
|
+ return -1;
|
||
|
+ }
|
||
|
+
|
||
|
+ pservice->hclk_vcodec = devm_clk_get(dev, "hclk_vcodec");
|
||
|
+ if (IS_ERR(pservice->hclk_vcodec)) {
|
||
|
+ dev_err(dev, "failed on clk_get hclk_vcodec\n");
|
||
|
+ pservice->hclk_vcodec = NULL;
|
||
|
+ return -1;
|
||
|
+ }
|
||
|
+ if (pservice->pd_video == NULL) {
|
||
|
+ pservice->pd_video = devm_clk_get(dev, "pd_video");
|
||
|
+ if (IS_ERR(pservice->pd_video)) {
|
||
|
+ pservice->pd_video = NULL;
|
||
|
+ dev_dbg(dev, "do not have pd_video\n");
|
||
|
+ }
|
||
|
+ }
|
||
|
+ break;
|
||
|
+ default:
|
||
|
+ break;
|
||
|
+ }
|
||
|
+
|
||
|
+ return 0;
|
||
|
+#else
|
||
|
+ return 0;
|
||
|
+#endif
|
||
|
+}
|
||
|
+
|
||
|
+static void _vpu_reset(struct vpu_subdev_data *data)
|
||
|
+{
|
||
|
+ struct vpu_service_info *pservice = data->pservice;
|
||
|
+ unsigned long rate = 0;
|
||
|
+
|
||
|
+ dev_info(pservice->dev, "resetting...\n");
|
||
|
+ WARN_ON(pservice->reg_codec != NULL);
|
||
|
+ WARN_ON(pservice->reg_pproc != NULL);
|
||
|
+ WARN_ON(pservice->reg_resev != NULL);
|
||
|
+ pservice->reg_codec = NULL;
|
||
|
+ pservice->reg_pproc = NULL;
|
||
|
+ pservice->reg_resev = NULL;
|
||
|
+
|
||
|
+#ifdef CONFIG_RESET_CONTROLLER
|
||
|
+ rockchip_pmu_set_idle_request(pservice->dev, true);
|
||
|
+
|
||
|
+ rate = clk_get_rate(pservice->aclk_vcodec);
|
||
|
+ /*
|
||
|
+ * Some old platforms can't run at 300MHZ, they don't request
|
||
|
+ * decrease the frequency at resetting either. It is safe to
|
||
|
+ * keep here in 200 MHZ.
|
||
|
+ */
|
||
|
+ clk_set_rate(pservice->aclk_vcodec, 200 * MHZ);
|
||
|
+
|
||
|
+ try_reset_assert(pservice->rst_niu_a);
|
||
|
+ try_reset_assert(pservice->rst_niu_h);
|
||
|
+ try_reset_assert(pservice->rst_v);
|
||
|
+ try_reset_assert(pservice->rst_a);
|
||
|
+ try_reset_assert(pservice->rst_h);
|
||
|
+ udelay(5);
|
||
|
+
|
||
|
+ try_reset_deassert(pservice->rst_h);
|
||
|
+ try_reset_deassert(pservice->rst_a);
|
||
|
+ try_reset_deassert(pservice->rst_v);
|
||
|
+ try_reset_deassert(pservice->rst_niu_h);
|
||
|
+ try_reset_deassert(pservice->rst_niu_a);
|
||
|
+
|
||
|
+#if 0
|
||
|
+ rockchip_pmu_set_idle_request(pservice->dev, false);
|
||
|
+#endif
|
||
|
+ clk_set_rate(pservice->aclk_vcodec, rate);
|
||
|
+ dev_info(pservice->dev, "reset done\n");
|
||
|
+#endif
|
||
|
+}
|
||
|
+
|
||
|
+static void vpu_reset(struct vpu_subdev_data *data)
|
||
|
+{
|
||
|
+ struct vpu_service_info *pservice = data->pservice;
|
||
|
+
|
||
|
+ _vpu_reset(data);
|
||
|
+ if (data->mmu_dev && test_bit(MMU_ACTIVATED, &data->state)) {
|
||
|
+ clear_bit(MMU_ACTIVATED, &data->state);
|
||
|
+ if (atomic_read(&pservice->enabled)) {
|
||
|
+ /* Need to reset iommu */
|
||
|
+ vcodec_iommu_detach(data->iommu_info);
|
||
|
+ } else {
|
||
|
+ /* FIXME BUG_ON should not be used in mass produce */
|
||
|
+ BUG_ON(!atomic_read(&pservice->enabled));
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ atomic_set(&pservice->reset_request, 0);
|
||
|
+ dev_info(pservice->dev, "reset done\n");
|
||
|
+}
|
||
|
+
|
||
|
+static void reg_deinit(struct vpu_subdev_data *data, struct vpu_reg *reg);
|
||
|
+static void vpu_service_session_clear(struct vpu_subdev_data *data,
|
||
|
+ struct vpu_session *session)
|
||
|
+{
|
||
|
+ struct vpu_reg *reg, *n;
|
||
|
+
|
||
|
+ list_for_each_entry_safe(reg, n, &session->waiting, session_link) {
|
||
|
+ reg_deinit(data, reg);
|
||
|
+ }
|
||
|
+ list_for_each_entry_safe(reg, n, &session->running, session_link) {
|
||
|
+ reg_deinit(data, reg);
|
||
|
+ }
|
||
|
+ list_for_each_entry_safe(reg, n, &session->done, session_link) {
|
||
|
+ reg_deinit(data, reg);
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+static void vpu_service_clear(struct vpu_subdev_data *data)
|
||
|
+{
|
||
|
+ struct vpu_reg *reg, *n;
|
||
|
+ struct vpu_session *session, *s;
|
||
|
+ struct vpu_service_info *pservice = data->pservice;
|
||
|
+
|
||
|
+ list_for_each_entry_safe(reg, n, &pservice->waiting, status_link) {
|
||
|
+ reg_deinit(reg->data, reg);
|
||
|
+ }
|
||
|
+
|
||
|
+ /* wake up session wait event to prevent the timeout hw reset
|
||
|
+ * during reboot procedure.
|
||
|
+ */
|
||
|
+ list_for_each_entry_safe(session, s,
|
||
|
+ &pservice->session, list_session)
|
||
|
+ wake_up(&session->wait);
|
||
|
+}
|
||
|
+
|
||
|
+static void vpu_service_dump(struct vpu_service_info *pservice)
|
||
|
+{
|
||
|
+}
|
||
|
+
|
||
|
+
|
||
|
+static void vpu_service_power_off(struct vpu_service_info *pservice)
|
||
|
+{
|
||
|
+ int total_running;
|
||
|
+ struct vpu_subdev_data *data = NULL, *n;
|
||
|
+ int ret = atomic_add_unless(&pservice->enabled, -1, 0);
|
||
|
+
|
||
|
+ if (!ret)
|
||
|
+ return;
|
||
|
+
|
||
|
+ total_running = atomic_read(&pservice->total_running);
|
||
|
+ if (total_running) {
|
||
|
+ pr_alert("alert: power off when %d task running!!\n",
|
||
|
+ total_running);
|
||
|
+ mdelay(50);
|
||
|
+ pr_alert("alert: delay 50 ms for running task\n");
|
||
|
+ vpu_service_dump(pservice);
|
||
|
+ }
|
||
|
+
|
||
|
+ dev_dbg(pservice->dev, "power off...\n");
|
||
|
+
|
||
|
+ udelay(5);
|
||
|
+
|
||
|
+ list_for_each_entry_safe(data, n, &pservice->subdev_list, lnk_service) {
|
||
|
+ if (data->mmu_dev && test_bit(MMU_ACTIVATED, &data->state)) {
|
||
|
+ clear_bit(MMU_ACTIVATED, &data->state);
|
||
|
+ vcodec_iommu_detach(data->iommu_info);
|
||
|
+ }
|
||
|
+ }
|
||
|
+ pservice->curr_mode = VCODEC_RUNNING_MODE_NONE;
|
||
|
+ pm_runtime_put(pservice->dev);
|
||
|
+#if VCODEC_CLOCK_ENABLE
|
||
|
+ if (pservice->pd_video)
|
||
|
+ clk_disable_unprepare(pservice->pd_video);
|
||
|
+ if (pservice->hclk_vcodec)
|
||
|
+ clk_disable_unprepare(pservice->hclk_vcodec);
|
||
|
+ if (pservice->aclk_vcodec)
|
||
|
+ clk_disable_unprepare(pservice->aclk_vcodec);
|
||
|
+ if (pservice->clk_core)
|
||
|
+ clk_disable_unprepare(pservice->clk_core);
|
||
|
+ if (pservice->clk_cabac)
|
||
|
+ clk_disable_unprepare(pservice->clk_cabac);
|
||
|
+#endif
|
||
|
+
|
||
|
+ atomic_add(1, &pservice->power_off_cnt);
|
||
|
+#ifdef CONFIG_WAKELOCK
|
||
|
+ wake_unlock(&pservice->wake_lock);
|
||
|
+#endif
|
||
|
+ dev_dbg(pservice->dev, "power off done\n");
|
||
|
+}
|
||
|
+
|
||
|
+static inline void vpu_queue_power_off_work(struct vpu_service_info *pservice)
|
||
|
+{
|
||
|
+ queue_delayed_work(system_wq, &pservice->power_off_work,
|
||
|
+ VPU_POWER_OFF_DELAY);
|
||
|
+}
|
||
|
+
|
||
|
+static void vpu_power_off_work(struct work_struct *work_s)
|
||
|
+{
|
||
|
+ struct delayed_work *dlwork = container_of(work_s,
|
||
|
+ struct delayed_work, work);
|
||
|
+ struct vpu_service_info *pservice = container_of(dlwork,
|
||
|
+ struct vpu_service_info, power_off_work);
|
||
|
+
|
||
|
+ if (mutex_trylock(&pservice->lock)) {
|
||
|
+ vpu_service_power_off(pservice);
|
||
|
+ mutex_unlock(&pservice->lock);
|
||
|
+ } else {
|
||
|
+ /* Come back later if the device is busy... */
|
||
|
+ vpu_queue_power_off_work(pservice);
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+static void vpu_service_power_on(struct vpu_subdev_data *data,
|
||
|
+ struct vpu_service_info *pservice)
|
||
|
+{
|
||
|
+ int ret;
|
||
|
+ ktime_t now = ktime_get();
|
||
|
+
|
||
|
+ if (ktime_to_ns(ktime_sub(now, pservice->last)) > NSEC_PER_SEC ||
|
||
|
+ atomic_read(&pservice->power_on_cnt)) {
|
||
|
+ /* NSEC_PER_SEC */
|
||
|
+ cancel_delayed_work_sync(&pservice->power_off_work);
|
||
|
+ vpu_queue_power_off_work(pservice);
|
||
|
+ pservice->last = now;
|
||
|
+ }
|
||
|
+ ret = atomic_add_unless(&pservice->enabled, 1, 1);
|
||
|
+ if (!ret)
|
||
|
+ return;
|
||
|
+
|
||
|
+ dev_dbg(pservice->dev, "power on\n");
|
||
|
+
|
||
|
+#define BIT_VCODEC_CLK_SEL (1<<10)
|
||
|
+ if (of_machine_is_compatible("rockchip,rk3126"))
|
||
|
+ writel_relaxed(readl_relaxed(RK_GRF_VIRT + RK312X_GRF_SOC_CON1)
|
||
|
+ | BIT_VCODEC_CLK_SEL | (BIT_VCODEC_CLK_SEL << 16),
|
||
|
+ RK_GRF_VIRT + RK312X_GRF_SOC_CON1);
|
||
|
+#if VCODEC_CLOCK_ENABLE
|
||
|
+ if (pservice->aclk_vcodec)
|
||
|
+ clk_prepare_enable(pservice->aclk_vcodec);
|
||
|
+ if (pservice->hclk_vcodec)
|
||
|
+ clk_prepare_enable(pservice->hclk_vcodec);
|
||
|
+ if (pservice->clk_core)
|
||
|
+ clk_prepare_enable(pservice->clk_core);
|
||
|
+ if (pservice->clk_cabac)
|
||
|
+ clk_prepare_enable(pservice->clk_cabac);
|
||
|
+ if (pservice->pd_video)
|
||
|
+ clk_prepare_enable(pservice->pd_video);
|
||
|
+#endif
|
||
|
+ pm_runtime_get_sync(pservice->dev);
|
||
|
+
|
||
|
+ udelay(5);
|
||
|
+ atomic_add(1, &pservice->power_on_cnt);
|
||
|
+#ifdef CONFIG_WAKELOCK
|
||
|
+ wake_lock(&pservice->wake_lock);
|
||
|
+#endif
|
||
|
+}
|
||
|
+
|
||
|
+static inline bool reg_check_interlace(struct vpu_reg *reg)
|
||
|
+{
|
||
|
+ u32 type = (reg->reg[3] & (1 << 23));
|
||
|
+
|
||
|
+ return (type > 0);
|
||
|
+}
|
||
|
+
|
||
|
+static inline enum VPU_DEC_FMT reg_check_fmt(struct vpu_reg *reg)
|
||
|
+{
|
||
|
+ enum VPU_DEC_FMT type = (enum VPU_DEC_FMT)((reg->reg[3] >> 28) & 0xf);
|
||
|
+
|
||
|
+ return type;
|
||
|
+}
|
||
|
+
|
||
|
+static inline int reg_probe_width(struct vpu_reg *reg)
|
||
|
+{
|
||
|
+ int width_in_mb = reg->reg[4] >> 23;
|
||
|
+
|
||
|
+ return width_in_mb * 16;
|
||
|
+}
|
||
|
+
|
||
|
+static inline int reg_probe_hevc_y_stride(struct vpu_reg *reg)
|
||
|
+{
|
||
|
+ int y_virstride = reg->reg[8];
|
||
|
+
|
||
|
+ return y_virstride;
|
||
|
+}
|
||
|
+
|
||
|
+static int vcodec_fd_to_iova(struct vpu_subdev_data *data,
|
||
|
+ struct vpu_session *session,
|
||
|
+ struct vpu_reg *reg,
|
||
|
+ int fd)
|
||
|
+{
|
||
|
+ int hdl;
|
||
|
+ int ret = 0;
|
||
|
+ struct vcodec_mem_region *mem_region;
|
||
|
+
|
||
|
+ hdl = vcodec_iommu_import(data->iommu_info, session, fd);
|
||
|
+ if (hdl < 0)
|
||
|
+ return hdl;
|
||
|
+
|
||
|
+ mem_region = kzalloc(sizeof(*mem_region), GFP_KERNEL);
|
||
|
+ if (mem_region == NULL) {
|
||
|
+ vpu_err("allocate memory for iommu memory region failed\n");
|
||
|
+ vcodec_iommu_free(data->iommu_info, session, hdl);
|
||
|
+ return -ENOMEM;
|
||
|
+ }
|
||
|
+
|
||
|
+ mem_region->hdl = hdl;
|
||
|
+ ret = vcodec_iommu_map_iommu(data->iommu_info, session, mem_region->hdl,
|
||
|
+ &mem_region->iova, &mem_region->len);
|
||
|
+ if (ret < 0) {
|
||
|
+ vpu_err("fd %d ion map iommu failed\n", fd);
|
||
|
+ kfree(mem_region);
|
||
|
+ vcodec_iommu_free(data->iommu_info, session, hdl);
|
||
|
+
|
||
|
+ return -EFAULT;
|
||
|
+ }
|
||
|
+ INIT_LIST_HEAD(&mem_region->reg_lnk);
|
||
|
+ list_add_tail(&mem_region->reg_lnk, ®->mem_region_list);
|
||
|
+ return mem_region->iova;
|
||
|
+}
|
||
|
+
|
||
|
+/*
|
||
|
+ * NOTE: rkvdec/rkhevc put scaling list address in pps buffer hardware will read
|
||
|
+ * it by pps id in video stream data.
|
||
|
+ *
|
||
|
+ * So we need to translate the address in iommu case. The address data is also
|
||
|
+ * 10bit fd + 22bit offset mode.
|
||
|
+ * Because userspace decoder do not give the pps id in the register file sets
|
||
|
+ * kernel driver need to translate each scaling list address in pps buffer which
|
||
|
+ * means 256 pps for H.264, 64 pps for H.265.
|
||
|
+ *
|
||
|
+ * In order to optimize the performance kernel driver ask userspace decoder to
|
||
|
+ * set all scaling list address in pps buffer to the same one which will be used
|
||
|
+ * on current decoding task. Then kernel driver can only translate the first
|
||
|
+ * address then copy it all pps buffer.
|
||
|
+ */
|
||
|
+static int fill_scaling_list_addr_in_pps(
|
||
|
+ struct vpu_subdev_data *data,
|
||
|
+ struct vpu_reg *reg,
|
||
|
+ char *pps,
|
||
|
+ int pps_info_count,
|
||
|
+ int pps_info_size,
|
||
|
+ int scaling_list_addr_offset)
|
||
|
+{
|
||
|
+ int base = scaling_list_addr_offset;
|
||
|
+ int scaling_fd = 0;
|
||
|
+ u32 scaling_offset;
|
||
|
+
|
||
|
+ scaling_offset = (u32)pps[base + 0];
|
||
|
+ scaling_offset += (u32)pps[base + 1] << 8;
|
||
|
+ scaling_offset += (u32)pps[base + 2] << 16;
|
||
|
+ scaling_offset += (u32)pps[base + 3] << 24;
|
||
|
+
|
||
|
+ scaling_fd = scaling_offset & 0x3ff;
|
||
|
+ scaling_offset = scaling_offset >> 10;
|
||
|
+
|
||
|
+ if (scaling_fd > 0) {
|
||
|
+ int i = 0;
|
||
|
+ u32 tmp = vcodec_fd_to_iova(data, reg->session, reg,
|
||
|
+ scaling_fd);
|
||
|
+
|
||
|
+ if (IS_ERR_VALUE(tmp))
|
||
|
+ return -1;
|
||
|
+ tmp += scaling_offset;
|
||
|
+
|
||
|
+ for (i = 0; i < pps_info_count; i++, base += pps_info_size) {
|
||
|
+ pps[base + 0] = (tmp >> 0) & 0xff;
|
||
|
+ pps[base + 1] = (tmp >> 8) & 0xff;
|
||
|
+ pps[base + 2] = (tmp >> 16) & 0xff;
|
||
|
+ pps[base + 3] = (tmp >> 24) & 0xff;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static int vcodec_bufid_to_iova(struct vpu_subdev_data *data,
|
||
|
+ struct vpu_session *session,
|
||
|
+ const u8 *tbl,
|
||
|
+ int size, struct vpu_reg *reg,
|
||
|
+ struct extra_info_for_iommu *ext_inf)
|
||
|
+{
|
||
|
+ struct vpu_service_info *pservice = data->pservice;
|
||
|
+ struct vpu_task_info *task = reg->task;
|
||
|
+ enum FORMAT_TYPE type;
|
||
|
+ int hdl;
|
||
|
+ int ret = 0;
|
||
|
+ struct vcodec_mem_region *mem_region;
|
||
|
+ int i;
|
||
|
+ int offset = 0;
|
||
|
+
|
||
|
+ if (tbl == NULL || size <= 0) {
|
||
|
+ dev_err(pservice->dev, "input arguments invalidate\n");
|
||
|
+ return -EINVAL;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (task->get_fmt)
|
||
|
+ type = task->get_fmt(reg->reg);
|
||
|
+ else {
|
||
|
+ dev_err(pservice->dev, "invalid task with NULL get_fmt\n");
|
||
|
+ return -EINVAL;
|
||
|
+ }
|
||
|
+
|
||
|
+ for (i = 0; i < size; i++) {
|
||
|
+ int usr_fd = reg->reg[tbl[i]] & 0x3FF;
|
||
|
+
|
||
|
+ /* if userspace do not set the fd at this register, skip */
|
||
|
+ if (usr_fd == 0)
|
||
|
+ continue;
|
||
|
+
|
||
|
+ /*
|
||
|
+ * for avoiding cache sync issue, we need to map/unmap
|
||
|
+ * input buffer every time. FIX ME, if it is unnecessary
|
||
|
+ */
|
||
|
+ if (task->reg_rlc == tbl[i])
|
||
|
+ vcodec_iommu_free_fd(data->iommu_info, session, usr_fd);
|
||
|
+ /*
|
||
|
+ * special offset scale case
|
||
|
+ *
|
||
|
+ * This translation is for fd + offset translation.
|
||
|
+ * One register has 32bits. We need to transfer both buffer file
|
||
|
+ * handle and the start address offset so we packet file handle
|
||
|
+ * and offset together using below format.
|
||
|
+ *
|
||
|
+ * 0~9 bit for buffer file handle range 0 ~ 1023
|
||
|
+ * 10~31 bit for offset range 0 ~ 4M
|
||
|
+ *
|
||
|
+ * But on 4K case the offset can be larger the 4M
|
||
|
+ * So on H.264 4K vpu/vpu2 decoder we scale the offset by 16
|
||
|
+ * But MPEG4 will use the same register for colmv and it do not
|
||
|
+ * need scale.
|
||
|
+ *
|
||
|
+ * RKVdec do not have this issue.
|
||
|
+ */
|
||
|
+ if ((type == FMT_H264D || type == FMT_VP9D) &&
|
||
|
+ task->reg_dir_mv > 0 && task->reg_dir_mv == tbl[i])
|
||
|
+ offset = reg->reg[tbl[i]] >> 10 << 4;
|
||
|
+ else
|
||
|
+ offset = reg->reg[tbl[i]] >> 10;
|
||
|
+
|
||
|
+ vpu_debug(DEBUG_IOMMU, "pos %3d fd %3d offset %10d i %d\n",
|
||
|
+ tbl[i], usr_fd, offset, i);
|
||
|
+
|
||
|
+ hdl = vcodec_iommu_import(data->iommu_info, session, usr_fd);
|
||
|
+
|
||
|
+ if (task->reg_pps > 0 && task->reg_pps == tbl[i]) {
|
||
|
+ int pps_info_offset;
|
||
|
+ int pps_info_count;
|
||
|
+ int pps_info_size;
|
||
|
+ int scaling_list_addr_offset;
|
||
|
+
|
||
|
+ switch (type) {
|
||
|
+ case FMT_H264D: {
|
||
|
+ pps_info_offset = offset;
|
||
|
+ pps_info_count = 256;
|
||
|
+ pps_info_size = 32;
|
||
|
+ scaling_list_addr_offset = 23;
|
||
|
+ } break;
|
||
|
+ case FMT_H265D: {
|
||
|
+ pps_info_offset = 0;
|
||
|
+ pps_info_count = 64;
|
||
|
+ pps_info_size = 80;
|
||
|
+ scaling_list_addr_offset = 74;
|
||
|
+ } break;
|
||
|
+ default: {
|
||
|
+ pps_info_offset = 0;
|
||
|
+ pps_info_count = 0;
|
||
|
+ pps_info_size = 0;
|
||
|
+ scaling_list_addr_offset = 0;
|
||
|
+ } break;
|
||
|
+ }
|
||
|
+
|
||
|
+ vpu_debug(DEBUG_PPS_FILL,
|
||
|
+ "scaling list filling parameter:\n");
|
||
|
+ vpu_debug(DEBUG_PPS_FILL,
|
||
|
+ "pps_info_offset %d\n", pps_info_offset);
|
||
|
+ vpu_debug(DEBUG_PPS_FILL,
|
||
|
+ "pps_info_count %d\n", pps_info_count);
|
||
|
+ vpu_debug(DEBUG_PPS_FILL,
|
||
|
+ "pps_info_size %d\n", pps_info_size);
|
||
|
+ vpu_debug(DEBUG_PPS_FILL,
|
||
|
+ "scaling_list_addr_offset %d\n",
|
||
|
+ scaling_list_addr_offset);
|
||
|
+
|
||
|
+ if (pps_info_count) {
|
||
|
+ u8 *pps;
|
||
|
+
|
||
|
+ pps = vcodec_iommu_map_kernel
|
||
|
+ (data->iommu_info, session, hdl);
|
||
|
+
|
||
|
+ vpu_debug(DEBUG_PPS_FILL,
|
||
|
+ "scaling list setting pps %p\n", pps);
|
||
|
+ pps += pps_info_offset;
|
||
|
+
|
||
|
+ fill_scaling_list_addr_in_pps
|
||
|
+ (data, reg, pps, pps_info_count,
|
||
|
+ pps_info_size,
|
||
|
+ scaling_list_addr_offset);
|
||
|
+
|
||
|
+ vcodec_iommu_unmap_kernel
|
||
|
+ (data->iommu_info, session, hdl);
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ mem_region = kzalloc(sizeof(*mem_region), GFP_KERNEL);
|
||
|
+
|
||
|
+ if (!mem_region) {
|
||
|
+ vcodec_iommu_free(data->iommu_info, session, hdl);
|
||
|
+ return -ENOMEM;
|
||
|
+ }
|
||
|
+
|
||
|
+ mem_region->hdl = hdl;
|
||
|
+ mem_region->reg_idx = tbl[i];
|
||
|
+
|
||
|
+ ret = vcodec_iommu_map_iommu(data->iommu_info, session,
|
||
|
+ mem_region->hdl, &mem_region->iova,
|
||
|
+ &mem_region->len);
|
||
|
+ if (ret < 0) {
|
||
|
+ dev_err(pservice->dev,
|
||
|
+ "reg %d fd %d ion map iommu failed\n",
|
||
|
+ tbl[i], usr_fd);
|
||
|
+ kfree(mem_region);
|
||
|
+ vcodec_iommu_free(data->iommu_info, session, hdl);
|
||
|
+ return ret;
|
||
|
+ }
|
||
|
+
|
||
|
+ /*
|
||
|
+ * special for vpu dec num 12: record decoded length
|
||
|
+ * hacking for decoded length
|
||
|
+ * NOTE: not a perfect fix, the fd is not recorded
|
||
|
+ */
|
||
|
+ if (task->reg_len > 0 && task->reg_len == tbl[i]) {
|
||
|
+ reg->dec_base = mem_region->iova + offset;
|
||
|
+ vpu_debug(DEBUG_REGISTER, "dec_set %08x\n",
|
||
|
+ reg->dec_base);
|
||
|
+ }
|
||
|
+
|
||
|
+ reg->reg[tbl[i]] = mem_region->iova + offset;
|
||
|
+ INIT_LIST_HEAD(&mem_region->reg_lnk);
|
||
|
+ list_add_tail(&mem_region->reg_lnk, ®->mem_region_list);
|
||
|
+ }
|
||
|
+
|
||
|
+ if (ext_inf != NULL && ext_inf->magic == EXTRA_INFO_MAGIC) {
|
||
|
+ for (i = 0; i < ext_inf->cnt; i++) {
|
||
|
+ vpu_debug(DEBUG_IOMMU, "reg[%d] + offset %d\n",
|
||
|
+ ext_inf->elem[i].index,
|
||
|
+ ext_inf->elem[i].offset);
|
||
|
+ reg->reg[ext_inf->elem[i].index] +=
|
||
|
+ ext_inf->elem[i].offset;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static int vcodec_reg_address_translate(struct vpu_subdev_data *data,
|
||
|
+ struct vpu_session *session,
|
||
|
+ struct vpu_reg *reg,
|
||
|
+ struct extra_info_for_iommu *ext_inf)
|
||
|
+{
|
||
|
+ struct vpu_service_info *pservice = data->pservice;
|
||
|
+ enum FORMAT_TYPE type = reg->task->get_fmt(reg->reg);
|
||
|
+
|
||
|
+ if (type < FMT_TYPE_BUTT) {
|
||
|
+ const struct vpu_trans_info *info = ®->trans[type];
|
||
|
+ const u8 *tbl = info->table;
|
||
|
+ int size = info->count;
|
||
|
+
|
||
|
+ return vcodec_bufid_to_iova(data, session, tbl, size, reg,
|
||
|
+ ext_inf);
|
||
|
+ }
|
||
|
+
|
||
|
+ dev_err(pservice->dev, "found invalid format type!\n");
|
||
|
+ return -EINVAL;
|
||
|
+}
|
||
|
+
|
||
|
+static void get_reg_freq(struct vpu_subdev_data *data, struct vpu_reg *reg)
|
||
|
+{
|
||
|
+
|
||
|
+ if (!of_machine_is_compatible("rockchip,rk2928g")) {
|
||
|
+ if (reg->type == VPU_DEC || reg->type == VPU_DEC_PP) {
|
||
|
+ if (reg_check_fmt(reg) == VPU_DEC_FMT_H264) {
|
||
|
+ if (reg_probe_width(reg) > 3200) {
|
||
|
+ /*raise frequency for 4k avc.*/
|
||
|
+ reg->freq = VPU_FREQ_600M;
|
||
|
+ }
|
||
|
+ } else {
|
||
|
+ if (reg_check_interlace(reg))
|
||
|
+ reg->freq = VPU_FREQ_400M;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ if (data->hw_id == HEVC_ID) {
|
||
|
+ if (reg_probe_hevc_y_stride(reg) > 60000)
|
||
|
+ reg->freq = VPU_FREQ_400M;
|
||
|
+ }
|
||
|
+ if (reg->type == VPU_PP)
|
||
|
+ reg->freq = VPU_FREQ_400M;
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+static struct vpu_reg *reg_init(struct vpu_subdev_data *data,
|
||
|
+ struct vpu_session *session,
|
||
|
+ void __user *src, u32 size)
|
||
|
+{
|
||
|
+ struct vpu_service_info *pservice = data->pservice;
|
||
|
+ int extra_size = 0;
|
||
|
+ struct extra_info_for_iommu extra_info;
|
||
|
+ struct vpu_reg *reg = kzalloc(sizeof(*reg) + data->reg_size,
|
||
|
+ GFP_KERNEL);
|
||
|
+
|
||
|
+ vpu_debug_enter();
|
||
|
+
|
||
|
+ if (!reg) {
|
||
|
+ vpu_err("error: kzalloc failed\n");
|
||
|
+ return NULL;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (size > data->reg_size) {
|
||
|
+ extra_size = size - data->reg_size;
|
||
|
+ size = data->reg_size;
|
||
|
+ }
|
||
|
+ reg->session = session;
|
||
|
+ reg->data = data;
|
||
|
+ reg->type = session->type;
|
||
|
+ reg->size = size;
|
||
|
+ reg->freq = VPU_FREQ_DEFAULT;
|
||
|
+ reg->task = &data->task_info[session->type];
|
||
|
+ reg->trans = data->trans_info;
|
||
|
+ reg->reg = (u32 *)®[1];
|
||
|
+ INIT_LIST_HEAD(®->session_link);
|
||
|
+ INIT_LIST_HEAD(®->status_link);
|
||
|
+
|
||
|
+ INIT_LIST_HEAD(®->mem_region_list);
|
||
|
+
|
||
|
+ if (copy_from_user(®->reg[0], (void __user *)src, size)) {
|
||
|
+ vpu_err("error: copy_from_user failed\n");
|
||
|
+ kfree(reg);
|
||
|
+ return NULL;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (copy_from_user(&extra_info, (u8 *)src + size, extra_size)) {
|
||
|
+ vpu_err("error: copy_from_user failed\n");
|
||
|
+ kfree(reg);
|
||
|
+ return NULL;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (vcodec_reg_address_translate(data, session, reg, &extra_info) < 0) {
|
||
|
+ int i = 0;
|
||
|
+
|
||
|
+ vpu_err("error: translate reg address failed, dumping regs\n");
|
||
|
+ for (i = 0; i < size >> 2; i++)
|
||
|
+ dev_err(pservice->dev, "reg[%02d]: %08x\n",
|
||
|
+ i, *((u32 *)src + i));
|
||
|
+
|
||
|
+ kfree(reg);
|
||
|
+ return NULL;
|
||
|
+ }
|
||
|
+
|
||
|
+ mutex_lock(&pservice->lock);
|
||
|
+ list_add_tail(®->status_link, &pservice->waiting);
|
||
|
+ list_add_tail(®->session_link, &session->waiting);
|
||
|
+ mutex_unlock(&pservice->lock);
|
||
|
+
|
||
|
+ if (pservice->auto_freq)
|
||
|
+ get_reg_freq(data, reg);
|
||
|
+
|
||
|
+ vpu_debug_leave();
|
||
|
+
|
||
|
+ return reg;
|
||
|
+}
|
||
|
+
|
||
|
+static void reg_deinit(struct vpu_subdev_data *data, struct vpu_reg *reg)
|
||
|
+{
|
||
|
+ struct vpu_service_info *pservice = data->pservice;
|
||
|
+ struct vcodec_mem_region *mem_region = NULL, *n;
|
||
|
+
|
||
|
+ list_del_init(®->session_link);
|
||
|
+ list_del_init(®->status_link);
|
||
|
+ if (reg == pservice->reg_codec)
|
||
|
+ pservice->reg_codec = NULL;
|
||
|
+ if (reg == pservice->reg_pproc)
|
||
|
+ pservice->reg_pproc = NULL;
|
||
|
+
|
||
|
+ /* release memory region attach to this registers table. */
|
||
|
+ list_for_each_entry_safe(mem_region, n,
|
||
|
+ ®->mem_region_list, reg_lnk) {
|
||
|
+ vcodec_iommu_unmap_iommu(data->iommu_info, reg->session,
|
||
|
+ mem_region->hdl);
|
||
|
+ vcodec_iommu_free(data->iommu_info, reg->session,
|
||
|
+ mem_region->hdl);
|
||
|
+ list_del_init(&mem_region->reg_lnk);
|
||
|
+ kfree(mem_region);
|
||
|
+ }
|
||
|
+
|
||
|
+ kfree(reg);
|
||
|
+}
|
||
|
+
|
||
|
+static void reg_from_wait_to_run(struct vpu_service_info *pservice,
|
||
|
+ struct vpu_reg *reg)
|
||
|
+{
|
||
|
+ vpu_debug_enter();
|
||
|
+ list_del_init(®->status_link);
|
||
|
+ list_add_tail(®->status_link, &pservice->running);
|
||
|
+
|
||
|
+ list_del_init(®->session_link);
|
||
|
+ list_add_tail(®->session_link, ®->session->running);
|
||
|
+ vpu_debug_leave();
|
||
|
+}
|
||
|
+
|
||
|
+static void reg_copy_from_hw(struct vpu_reg *reg, u32 *src, u32 count)
|
||
|
+{
|
||
|
+ int i;
|
||
|
+ u32 *dst = reg->reg;
|
||
|
+
|
||
|
+ vpu_debug_enter();
|
||
|
+ for (i = 0; i < count; i++, src++)
|
||
|
+ *dst++ = readl_relaxed(src);
|
||
|
+
|
||
|
+ dst = (u32 *)®->reg[0];
|
||
|
+ for (i = 0; i < count; i++)
|
||
|
+ vpu_debug(DEBUG_GET_REG, "get reg[%02d] %08x\n", i, dst[i]);
|
||
|
+
|
||
|
+ vpu_debug_leave();
|
||
|
+}
|
||
|
+
|
||
|
+static void reg_from_run_to_done(struct vpu_subdev_data *data,
|
||
|
+ struct vpu_reg *reg)
|
||
|
+{
|
||
|
+ struct vpu_service_info *pservice = data->pservice;
|
||
|
+ struct vpu_hw_info *hw_info = data->hw_info;
|
||
|
+ struct vpu_task_info *task = reg->task;
|
||
|
+
|
||
|
+ vpu_debug_enter();
|
||
|
+
|
||
|
+ list_del_init(®->status_link);
|
||
|
+ list_add_tail(®->status_link, &pservice->done);
|
||
|
+
|
||
|
+ list_del_init(®->session_link);
|
||
|
+ list_add_tail(®->session_link, ®->session->done);
|
||
|
+
|
||
|
+ switch (reg->type) {
|
||
|
+ case VPU_ENC: {
|
||
|
+ pservice->reg_codec = NULL;
|
||
|
+ reg_copy_from_hw(reg, data->enc_dev.regs, hw_info->enc_reg_num);
|
||
|
+ reg->reg[task->reg_irq] = pservice->irq_status;
|
||
|
+ } break;
|
||
|
+ case VPU_DEC: {
|
||
|
+ pservice->reg_codec = NULL;
|
||
|
+ reg_copy_from_hw(reg, data->dec_dev.regs, hw_info->dec_reg_num);
|
||
|
+
|
||
|
+ /* revert hack for decoded length */
|
||
|
+ if (task->reg_len > 0) {
|
||
|
+ int reg_len = task->reg_len;
|
||
|
+ u32 dec_get = reg->reg[reg_len];
|
||
|
+ s32 dec_length = dec_get - reg->dec_base;
|
||
|
+
|
||
|
+ vpu_debug(DEBUG_REGISTER,
|
||
|
+ "dec_get %08x dec_length %d\n",
|
||
|
+ dec_get, dec_length);
|
||
|
+ reg->reg[reg_len] = dec_length << 10;
|
||
|
+ }
|
||
|
+
|
||
|
+ reg->reg[task->reg_irq] = pservice->irq_status;
|
||
|
+ } break;
|
||
|
+ case VPU_PP: {
|
||
|
+ pservice->reg_pproc = NULL;
|
||
|
+ reg_copy_from_hw(reg, data->dec_dev.regs, hw_info->dec_reg_num);
|
||
|
+ writel_relaxed(0, data->dec_dev.regs + task->reg_irq);
|
||
|
+ } break;
|
||
|
+ case VPU_DEC_PP: {
|
||
|
+ u32 pipe_mode;
|
||
|
+ u32 *regs = data->dec_dev.regs;
|
||
|
+
|
||
|
+ pservice->reg_codec = NULL;
|
||
|
+ pservice->reg_pproc = NULL;
|
||
|
+
|
||
|
+ reg_copy_from_hw(reg, data->dec_dev.regs, hw_info->dec_reg_num);
|
||
|
+
|
||
|
+ /* NOTE: remove pp pipeline mode flag first */
|
||
|
+ pipe_mode = readl_relaxed(regs + task->reg_pipe);
|
||
|
+ pipe_mode &= ~task->pipe_mask;
|
||
|
+ writel_relaxed(pipe_mode, regs + task->reg_pipe);
|
||
|
+
|
||
|
+ /* revert hack for decoded length */
|
||
|
+ if (task->reg_len > 0) {
|
||
|
+ int reg_len = task->reg_len;
|
||
|
+ u32 dec_get = reg->reg[reg_len];
|
||
|
+ s32 dec_length = dec_get - reg->dec_base;
|
||
|
+
|
||
|
+ vpu_debug(DEBUG_REGISTER,
|
||
|
+ "dec_get %08x dec_length %d\n",
|
||
|
+ dec_get, dec_length);
|
||
|
+ reg->reg[reg_len] = dec_length << 10;
|
||
|
+ }
|
||
|
+
|
||
|
+ reg->reg[task->reg_irq] = pservice->irq_status;
|
||
|
+ } break;
|
||
|
+ default: {
|
||
|
+ vpu_err("error: copy reg from hw with unknown type %d\n",
|
||
|
+ reg->type);
|
||
|
+ } break;
|
||
|
+ }
|
||
|
+ vcodec_exit_mode(data);
|
||
|
+
|
||
|
+ atomic_sub(1, ®->session->task_running);
|
||
|
+ atomic_sub(1, &pservice->total_running);
|
||
|
+ wake_up(®->session->wait);
|
||
|
+
|
||
|
+ vpu_debug_leave();
|
||
|
+}
|
||
|
+
|
||
|
+static void vpu_service_set_freq(struct vpu_service_info *pservice,
|
||
|
+ struct vpu_reg *reg)
|
||
|
+{
|
||
|
+ enum VPU_FREQ curr = atomic_read(&pservice->freq_status);
|
||
|
+
|
||
|
+ if (curr == reg->freq)
|
||
|
+ return;
|
||
|
+
|
||
|
+ atomic_set(&pservice->freq_status, reg->freq);
|
||
|
+ switch (reg->freq) {
|
||
|
+ case VPU_FREQ_200M: {
|
||
|
+ clk_set_rate(pservice->aclk_vcodec, 200*MHZ);
|
||
|
+ } break;
|
||
|
+ case VPU_FREQ_266M: {
|
||
|
+ clk_set_rate(pservice->aclk_vcodec, 266*MHZ);
|
||
|
+ } break;
|
||
|
+ case VPU_FREQ_300M: {
|
||
|
+ clk_set_rate(pservice->aclk_vcodec, 300*MHZ);
|
||
|
+ } break;
|
||
|
+ case VPU_FREQ_400M: {
|
||
|
+ clk_set_rate(pservice->aclk_vcodec, 400*MHZ);
|
||
|
+ } break;
|
||
|
+ case VPU_FREQ_500M: {
|
||
|
+ clk_set_rate(pservice->aclk_vcodec, 500*MHZ);
|
||
|
+ } break;
|
||
|
+ case VPU_FREQ_600M: {
|
||
|
+ clk_set_rate(pservice->aclk_vcodec, 600*MHZ);
|
||
|
+ } break;
|
||
|
+ default: {
|
||
|
+ unsigned long rate = 300*MHZ;
|
||
|
+
|
||
|
+ if (of_machine_is_compatible("rockchip,rk2928g"))
|
||
|
+ rate = 400*MHZ;
|
||
|
+
|
||
|
+ clk_set_rate(pservice->aclk_vcodec, rate);
|
||
|
+ } break;
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+static void reg_copy_to_hw(struct vpu_subdev_data *data, struct vpu_reg *reg)
|
||
|
+{
|
||
|
+ struct vpu_service_info *pservice = data->pservice;
|
||
|
+ struct vpu_task_info *task = reg->task;
|
||
|
+ struct vpu_hw_info *hw_info = data->hw_info;
|
||
|
+ int i;
|
||
|
+ u32 *src = (u32 *)®->reg[0];
|
||
|
+ u32 enable_mask = task->enable_mask;
|
||
|
+ u32 gating_mask = task->gating_mask;
|
||
|
+ u32 reg_en = task->reg_en;
|
||
|
+
|
||
|
+ vpu_debug_enter();
|
||
|
+
|
||
|
+ atomic_add(1, &pservice->total_running);
|
||
|
+ atomic_add(1, ®->session->task_running);
|
||
|
+
|
||
|
+ if (pservice->auto_freq)
|
||
|
+ vpu_service_set_freq(pservice, reg);
|
||
|
+
|
||
|
+ vcodec_enter_mode(data);
|
||
|
+
|
||
|
+ switch (reg->type) {
|
||
|
+ case VPU_ENC: {
|
||
|
+ u32 *dst = data->enc_dev.regs;
|
||
|
+ u32 base = 0;
|
||
|
+ u32 end = hw_info->enc_reg_num;
|
||
|
+ /* u32 reg_gating = task->reg_gating; */
|
||
|
+
|
||
|
+ pservice->reg_codec = reg;
|
||
|
+
|
||
|
+ vpu_debug(DEBUG_TASK_INFO,
|
||
|
+ "reg: base %3d end %d en %2d mask: en %x gate %x\n",
|
||
|
+ base, end, reg_en, enable_mask, gating_mask);
|
||
|
+
|
||
|
+ VEPU_CLEAN_CACHE(dst);
|
||
|
+
|
||
|
+ if (debug & DEBUG_SET_REG)
|
||
|
+ for (i = base; i < end; i++)
|
||
|
+ vpu_debug(DEBUG_SET_REG, "set reg[%02d] %08x\n",
|
||
|
+ i, src[i]);
|
||
|
+
|
||
|
+ /*
|
||
|
+ * NOTE: encoder need to setup mode first
|
||
|
+ */
|
||
|
+ writel_relaxed(src[reg_en] & enable_mask, dst + reg_en);
|
||
|
+
|
||
|
+ /* NOTE: encoder gating is not on enable register */
|
||
|
+ /* src[reg_gating] |= gating_mask; */
|
||
|
+
|
||
|
+ for (i = base; i < end; i++) {
|
||
|
+ if (i != reg_en)
|
||
|
+ writel_relaxed(src[i], dst + i);
|
||
|
+ }
|
||
|
+
|
||
|
+ writel(src[reg_en], dst + reg_en);
|
||
|
+ dsb(sy);
|
||
|
+
|
||
|
+ time_record(reg->task, 0);
|
||
|
+ } break;
|
||
|
+ case VPU_DEC: {
|
||
|
+ u32 *dst = data->dec_dev.regs;
|
||
|
+ u32 len = hw_info->dec_reg_num;
|
||
|
+ u32 base = hw_info->base_dec;
|
||
|
+ u32 end = hw_info->end_dec;
|
||
|
+
|
||
|
+ pservice->reg_codec = reg;
|
||
|
+
|
||
|
+ vpu_debug(DEBUG_TASK_INFO,
|
||
|
+ "reg: base %3d end %d en %2d mask: en %x gate %x\n",
|
||
|
+ base, end, reg_en, enable_mask, gating_mask);
|
||
|
+
|
||
|
+ VDPU_CLEAN_CACHE(dst);
|
||
|
+
|
||
|
+ /* on rkvdec set cache size to 64byte */
|
||
|
+ if (pservice->dev_id == VCODEC_DEVICE_ID_RKVDEC) {
|
||
|
+ u32 *cache_base = dst + 0x100;
|
||
|
+ u32 val = (debug & DEBUG_CACHE_32B) ? (0x3) : (0x13);
|
||
|
+ writel_relaxed(val, cache_base + 0x07);
|
||
|
+ writel_relaxed(val, cache_base + 0x17);
|
||
|
+ }
|
||
|
+
|
||
|
+ if (debug & DEBUG_SET_REG)
|
||
|
+ for (i = 0; i < len; i++)
|
||
|
+ vpu_debug(DEBUG_SET_REG, "set reg[%02d] %08x\n",
|
||
|
+ i, src[i]);
|
||
|
+ /*
|
||
|
+ * NOTE: The end register is invalid. Do NOT write to it
|
||
|
+ * Also the base register must be written
|
||
|
+ */
|
||
|
+ for (i = base; i < end; i++) {
|
||
|
+ if (i != reg_en)
|
||
|
+ writel_relaxed(src[i], dst + i);
|
||
|
+ }
|
||
|
+
|
||
|
+ writel(src[reg_en] | gating_mask, dst + reg_en);
|
||
|
+ dsb(sy);
|
||
|
+
|
||
|
+ time_record(reg->task, 0);
|
||
|
+ } break;
|
||
|
+ case VPU_PP: {
|
||
|
+ u32 *dst = data->dec_dev.regs;
|
||
|
+ u32 base = hw_info->base_pp;
|
||
|
+ u32 end = hw_info->end_pp;
|
||
|
+
|
||
|
+ pservice->reg_pproc = reg;
|
||
|
+
|
||
|
+ vpu_debug(DEBUG_TASK_INFO,
|
||
|
+ "reg: base %3d end %d en %2d mask: en %x gate %x\n",
|
||
|
+ base, end, reg_en, enable_mask, gating_mask);
|
||
|
+
|
||
|
+ if (debug & DEBUG_SET_REG)
|
||
|
+ for (i = base; i < end; i++)
|
||
|
+ vpu_debug(DEBUG_SET_REG, "set reg[%02d] %08x\n",
|
||
|
+ i, src[i]);
|
||
|
+
|
||
|
+ for (i = base; i < end; i++) {
|
||
|
+ if (i != reg_en)
|
||
|
+ writel_relaxed(src[i], dst + i);
|
||
|
+ }
|
||
|
+
|
||
|
+ writel(src[reg_en] | gating_mask, dst + reg_en);
|
||
|
+ dsb(sy);
|
||
|
+
|
||
|
+ time_record(reg->task, 0);
|
||
|
+ } break;
|
||
|
+ case VPU_DEC_PP: {
|
||
|
+ u32 *dst = data->dec_dev.regs;
|
||
|
+ u32 base = hw_info->base_dec_pp;
|
||
|
+ u32 end = hw_info->end_dec_pp;
|
||
|
+
|
||
|
+ pservice->reg_codec = reg;
|
||
|
+ pservice->reg_pproc = reg;
|
||
|
+
|
||
|
+ vpu_debug(DEBUG_TASK_INFO,
|
||
|
+ "reg: base %3d end %d en %2d mask: en %x gate %x\n",
|
||
|
+ base, end, reg_en, enable_mask, gating_mask);
|
||
|
+
|
||
|
+ /* VDPU_SOFT_RESET(dst); */
|
||
|
+ VDPU_CLEAN_CACHE(dst);
|
||
|
+
|
||
|
+ if (debug & DEBUG_SET_REG)
|
||
|
+ for (i = base; i < end; i++)
|
||
|
+ vpu_debug(DEBUG_SET_REG, "set reg[%02d] %08x\n",
|
||
|
+ i, src[i]);
|
||
|
+
|
||
|
+ for (i = base; i < end; i++) {
|
||
|
+ if (i != reg_en)
|
||
|
+ writel_relaxed(src[i], dst + i);
|
||
|
+ }
|
||
|
+
|
||
|
+ /* NOTE: dec output must be disabled */
|
||
|
+
|
||
|
+ writel(src[reg_en] | gating_mask, dst + reg_en);
|
||
|
+ dsb(sy);
|
||
|
+
|
||
|
+ time_record(reg->task, 0);
|
||
|
+ } break;
|
||
|
+ default: {
|
||
|
+ vpu_err("error: unsupport session type %d", reg->type);
|
||
|
+ atomic_sub(1, &pservice->total_running);
|
||
|
+ atomic_sub(1, ®->session->task_running);
|
||
|
+ } break;
|
||
|
+ }
|
||
|
+
|
||
|
+ vpu_debug_leave();
|
||
|
+}
|
||
|
+
|
||
|
+static void try_set_reg(struct vpu_subdev_data *data)
|
||
|
+{
|
||
|
+ struct vpu_service_info *pservice = data->pservice;
|
||
|
+
|
||
|
+ vpu_debug_enter();
|
||
|
+
|
||
|
+ mutex_lock(&pservice->shutdown_lock);
|
||
|
+ if (atomic_read(&pservice->service_on) == 0) {
|
||
|
+ mutex_unlock(&pservice->shutdown_lock);
|
||
|
+ return;
|
||
|
+ }
|
||
|
+ if (!list_empty(&pservice->waiting)) {
|
||
|
+ struct vpu_reg *reg_codec = pservice->reg_codec;
|
||
|
+ struct vpu_reg *reg_pproc = pservice->reg_pproc;
|
||
|
+ int can_set = 0;
|
||
|
+ bool change_able = (reg_codec == NULL) && (reg_pproc == NULL);
|
||
|
+ int reset_request = atomic_read(&pservice->reset_request);
|
||
|
+ struct vpu_reg *reg = list_entry(pservice->waiting.next,
|
||
|
+ struct vpu_reg, status_link);
|
||
|
+
|
||
|
+ vpu_service_power_on(data, pservice);
|
||
|
+
|
||
|
+ if (change_able || !reset_request) {
|
||
|
+ switch (reg->type) {
|
||
|
+ case VPU_ENC: {
|
||
|
+ if (change_able)
|
||
|
+ can_set = 1;
|
||
|
+ } break;
|
||
|
+ case VPU_DEC: {
|
||
|
+ if (reg_codec == NULL)
|
||
|
+ can_set = 1;
|
||
|
+ if (pservice->auto_freq && (reg_pproc != NULL))
|
||
|
+ can_set = 0;
|
||
|
+ } break;
|
||
|
+ case VPU_PP: {
|
||
|
+ if (reg_codec == NULL) {
|
||
|
+ if (reg_pproc == NULL)
|
||
|
+ can_set = 1;
|
||
|
+ } else {
|
||
|
+ if ((reg_codec->type == VPU_DEC) &&
|
||
|
+ (reg_pproc == NULL))
|
||
|
+ can_set = 1;
|
||
|
+
|
||
|
+ /*
|
||
|
+ * NOTE:
|
||
|
+ * can not charge frequency
|
||
|
+ * when vpu is working
|
||
|
+ */
|
||
|
+ if (pservice->auto_freq)
|
||
|
+ can_set = 0;
|
||
|
+ }
|
||
|
+ } break;
|
||
|
+ case VPU_DEC_PP: {
|
||
|
+ if (change_able)
|
||
|
+ can_set = 1;
|
||
|
+ } break;
|
||
|
+ default: {
|
||
|
+ dev_err(pservice->dev,
|
||
|
+ "undefined reg type %d\n",
|
||
|
+ reg->type);
|
||
|
+ } break;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ /* then check reset request */
|
||
|
+ if (reset_request && !change_able)
|
||
|
+ reset_request = 0;
|
||
|
+
|
||
|
+ /* do reset before setting registers */
|
||
|
+ if (reset_request)
|
||
|
+ vpu_reset(data);
|
||
|
+
|
||
|
+ if (can_set) {
|
||
|
+ reg_from_wait_to_run(pservice, reg);
|
||
|
+ reg_copy_to_hw(reg->data, reg);
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ mutex_unlock(&pservice->shutdown_lock);
|
||
|
+ vpu_debug_leave();
|
||
|
+}
|
||
|
+
|
||
|
+static void vpu_set_register_work(struct work_struct *work_s)
|
||
|
+{
|
||
|
+ struct vpu_subdev_data *data = container_of(work_s,
|
||
|
+ struct vpu_subdev_data,
|
||
|
+ set_work);
|
||
|
+ struct vpu_service_info *pservice = data->pservice;
|
||
|
+
|
||
|
+ mutex_lock(&pservice->lock);
|
||
|
+ try_set_reg(data);
|
||
|
+ mutex_unlock(&pservice->lock);
|
||
|
+}
|
||
|
+
|
||
|
+static int return_reg(struct vpu_subdev_data *data,
|
||
|
+ struct vpu_reg *reg, u32 __user *dst)
|
||
|
+{
|
||
|
+ struct vpu_hw_info *hw_info = data->hw_info;
|
||
|
+ size_t size = reg->size;
|
||
|
+ u32 base;
|
||
|
+
|
||
|
+ vpu_debug_enter();
|
||
|
+ switch (reg->type) {
|
||
|
+ case VPU_ENC: {
|
||
|
+ base = 0;
|
||
|
+ } break;
|
||
|
+ case VPU_DEC: {
|
||
|
+ base = hw_info->base_dec_pp;
|
||
|
+ } break;
|
||
|
+ case VPU_PP: {
|
||
|
+ base = hw_info->base_pp;
|
||
|
+ } break;
|
||
|
+ case VPU_DEC_PP: {
|
||
|
+ base = hw_info->base_dec_pp;
|
||
|
+ } break;
|
||
|
+ default: {
|
||
|
+ vpu_err("error: copy reg to user with unknown type %d\n",
|
||
|
+ reg->type);
|
||
|
+ return -EFAULT;
|
||
|
+ } break;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (copy_to_user(dst, ®->reg[base], size)) {
|
||
|
+ vpu_err("error: copy_to_user failed\n");
|
||
|
+ return -EFAULT;
|
||
|
+ }
|
||
|
+
|
||
|
+ reg_deinit(data, reg);
|
||
|
+ vpu_debug_leave();
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static long vpu_service_ioctl(struct file *filp, unsigned int cmd,
|
||
|
+ unsigned long arg)
|
||
|
+{
|
||
|
+ struct vpu_subdev_data *data =
|
||
|
+ container_of(filp->f_path.dentry->d_inode->i_cdev,
|
||
|
+ struct vpu_subdev_data, cdev);
|
||
|
+ struct vpu_service_info *pservice = data->pservice;
|
||
|
+ struct vpu_session *session = (struct vpu_session *)filp->private_data;
|
||
|
+
|
||
|
+ vpu_debug_enter();
|
||
|
+ if (NULL == session)
|
||
|
+ return -EINVAL;
|
||
|
+
|
||
|
+ switch (cmd) {
|
||
|
+ case VPU_IOC_SET_CLIENT_TYPE: {
|
||
|
+ session->type = (enum VPU_CLIENT_TYPE)arg;
|
||
|
+ vpu_debug(DEBUG_IOCTL, "pid %d set client type %d\n",
|
||
|
+ session->pid, session->type);
|
||
|
+ } break;
|
||
|
+ case VPU_IOC_GET_HW_FUSE_STATUS: {
|
||
|
+ struct vpu_request req;
|
||
|
+
|
||
|
+ vpu_debug(DEBUG_IOCTL, "pid %d get hw status %d\n",
|
||
|
+ session->pid, session->type);
|
||
|
+ if (copy_from_user(&req, (void __user *)arg, sizeof(req))) {
|
||
|
+ vpu_err("error: get hw status copy_from_user failed\n");
|
||
|
+ return -EFAULT;
|
||
|
+ } else {
|
||
|
+ void *config = (session->type != VPU_ENC) ?
|
||
|
+ ((void *)&pservice->dec_config) :
|
||
|
+ ((void *)&pservice->enc_config);
|
||
|
+ size_t size = (session->type != VPU_ENC) ?
|
||
|
+ (sizeof(struct vpu_dec_config)) :
|
||
|
+ (sizeof(struct vpu_enc_config));
|
||
|
+ if (copy_to_user((void __user *)req.req,
|
||
|
+ config, size)) {
|
||
|
+ vpu_err("error: get hw status copy_to_user failed type %d\n",
|
||
|
+ session->type);
|
||
|
+ return -EFAULT;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ } break;
|
||
|
+ case VPU_IOC_SET_REG: {
|
||
|
+ struct vpu_request req;
|
||
|
+ struct vpu_reg *reg;
|
||
|
+
|
||
|
+ vpu_debug(DEBUG_IOCTL, "pid %d set reg type %d\n",
|
||
|
+ session->pid, session->type);
|
||
|
+ if (copy_from_user(&req, (void __user *)arg,
|
||
|
+ sizeof(struct vpu_request))) {
|
||
|
+ vpu_err("error: set reg copy_from_user failed\n");
|
||
|
+ return -EFAULT;
|
||
|
+ }
|
||
|
+
|
||
|
+ reg = reg_init(data, session, (void __user *)req.req, req.size);
|
||
|
+ if (NULL == reg) {
|
||
|
+ return -EFAULT;
|
||
|
+ } else {
|
||
|
+ queue_work(pservice->set_workq, &data->set_work);
|
||
|
+ }
|
||
|
+ } break;
|
||
|
+ case VPU_IOC_GET_REG: {
|
||
|
+ struct vpu_request req;
|
||
|
+ struct vpu_reg *reg;
|
||
|
+ int ret;
|
||
|
+
|
||
|
+ vpu_debug(DEBUG_IOCTL, "pid %d get reg type %d\n",
|
||
|
+ session->pid, session->type);
|
||
|
+ if (copy_from_user(&req, (void __user *)arg,
|
||
|
+ sizeof(struct vpu_request))) {
|
||
|
+ vpu_err("error: get reg copy_from_user failed\n");
|
||
|
+ return -EFAULT;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = wait_event_timeout(session->wait,
|
||
|
+ !list_empty(&session->done),
|
||
|
+ VPU_TIMEOUT_DELAY);
|
||
|
+
|
||
|
+ if (!list_empty(&session->done)) {
|
||
|
+ if (ret < 0)
|
||
|
+ vpu_err("warning: pid %d wait task error ret %d\n",
|
||
|
+ session->pid, ret);
|
||
|
+ ret = 0;
|
||
|
+ } else {
|
||
|
+ if (unlikely(ret < 0)) {
|
||
|
+ vpu_err("error: pid %d wait task ret %d\n",
|
||
|
+ session->pid, ret);
|
||
|
+ } else if (ret == 0) {
|
||
|
+ vpu_err("error: pid %d wait %d task done timeout\n",
|
||
|
+ session->pid,
|
||
|
+ atomic_read(&session->task_running));
|
||
|
+ ret = -ETIMEDOUT;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ if (ret < 0) {
|
||
|
+ int task_running = atomic_read(&session->task_running);
|
||
|
+
|
||
|
+ mutex_lock(&pservice->lock);
|
||
|
+ vpu_service_dump(pservice);
|
||
|
+ if (task_running) {
|
||
|
+ atomic_set(&session->task_running, 0);
|
||
|
+ atomic_sub(task_running,
|
||
|
+ &pservice->total_running);
|
||
|
+ dev_err(pservice->dev,
|
||
|
+ "%d task is running but not return, reset hardware...",
|
||
|
+ task_running);
|
||
|
+ vpu_reset(data);
|
||
|
+ dev_err(pservice->dev, "done\n");
|
||
|
+ }
|
||
|
+ vpu_service_session_clear(data, session);
|
||
|
+ mutex_unlock(&pservice->lock);
|
||
|
+
|
||
|
+ return ret;
|
||
|
+ }
|
||
|
+ mutex_lock(&pservice->lock);
|
||
|
+ reg = list_entry(session->done.next,
|
||
|
+ struct vpu_reg, session_link);
|
||
|
+ return_reg(data, reg, (u32 __user *)req.req);
|
||
|
+ mutex_unlock(&pservice->lock);
|
||
|
+ } break;
|
||
|
+ case VPU_IOC_PROBE_IOMMU_STATUS: {
|
||
|
+ int iommu_enable = 1;
|
||
|
+
|
||
|
+ vpu_debug(DEBUG_IOCTL, "VPU_IOC_PROBE_IOMMU_STATUS\n");
|
||
|
+
|
||
|
+ if (copy_to_user((void __user *)arg,
|
||
|
+ &iommu_enable, sizeof(int))) {
|
||
|
+ vpu_err("error: iommu status copy_to_user failed\n");
|
||
|
+ return -EFAULT;
|
||
|
+ }
|
||
|
+ } break;
|
||
|
+ default: {
|
||
|
+ vpu_err("error: unknow vpu service ioctl cmd %x\n", cmd);
|
||
|
+ } break;
|
||
|
+ }
|
||
|
+ vpu_debug_leave();
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+#ifdef CONFIG_COMPAT
|
||
|
+static long compat_vpu_service_ioctl(struct file *filp, unsigned int cmd,
|
||
|
+ unsigned long arg)
|
||
|
+{
|
||
|
+ struct vpu_subdev_data *data =
|
||
|
+ container_of(filp->f_path.dentry->d_inode->i_cdev,
|
||
|
+ struct vpu_subdev_data, cdev);
|
||
|
+ struct vpu_service_info *pservice = data->pservice;
|
||
|
+ struct vpu_session *session = (struct vpu_session *)filp->private_data;
|
||
|
+
|
||
|
+ vpu_debug_enter();
|
||
|
+ vpu_debug(3, "cmd %x, COMPAT_VPU_IOC_SET_CLIENT_TYPE %x\n", cmd,
|
||
|
+ (u32)COMPAT_VPU_IOC_SET_CLIENT_TYPE);
|
||
|
+ if (NULL == session)
|
||
|
+ return -EINVAL;
|
||
|
+
|
||
|
+ switch (cmd) {
|
||
|
+ case COMPAT_VPU_IOC_SET_CLIENT_TYPE: {
|
||
|
+ session->type = (enum VPU_CLIENT_TYPE)arg;
|
||
|
+ vpu_debug(DEBUG_IOCTL, "compat set client type %d\n",
|
||
|
+ session->type);
|
||
|
+ } break;
|
||
|
+ case COMPAT_VPU_IOC_GET_HW_FUSE_STATUS: {
|
||
|
+ struct compat_vpu_request req;
|
||
|
+
|
||
|
+ vpu_debug(DEBUG_IOCTL, "compat get hw status %d\n",
|
||
|
+ session->type);
|
||
|
+ if (copy_from_user(&req, compat_ptr((compat_uptr_t)arg),
|
||
|
+ sizeof(struct compat_vpu_request))) {
|
||
|
+ vpu_err("error: compat get hw status copy_from_user failed\n");
|
||
|
+ return -EFAULT;
|
||
|
+ } else {
|
||
|
+ void *config = (session->type != VPU_ENC) ?
|
||
|
+ ((void *)&pservice->dec_config) :
|
||
|
+ ((void *)&pservice->enc_config);
|
||
|
+ size_t size = (session->type != VPU_ENC) ?
|
||
|
+ (sizeof(struct vpu_dec_config)) :
|
||
|
+ (sizeof(struct vpu_enc_config));
|
||
|
+
|
||
|
+ if (copy_to_user(compat_ptr((compat_uptr_t)req.req),
|
||
|
+ config, size)) {
|
||
|
+ vpu_err("error: compat get hw status copy_to_user failed type %d\n",
|
||
|
+ session->type);
|
||
|
+ return -EFAULT;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ } break;
|
||
|
+ case COMPAT_VPU_IOC_SET_REG: {
|
||
|
+ struct compat_vpu_request req;
|
||
|
+ struct vpu_reg *reg;
|
||
|
+
|
||
|
+ vpu_debug(DEBUG_IOCTL, "compat set reg type %d\n",
|
||
|
+ session->type);
|
||
|
+ if (copy_from_user(&req, compat_ptr((compat_uptr_t)arg),
|
||
|
+ sizeof(struct compat_vpu_request))) {
|
||
|
+ vpu_err("compat set_reg copy_from_user failed\n");
|
||
|
+ return -EFAULT;
|
||
|
+ }
|
||
|
+ reg = reg_init(data, session,
|
||
|
+ compat_ptr((compat_uptr_t)req.req), req.size);
|
||
|
+ if (NULL == reg) {
|
||
|
+ return -EFAULT;
|
||
|
+ } else {
|
||
|
+ queue_work(pservice->set_workq, &data->set_work);
|
||
|
+ }
|
||
|
+ } break;
|
||
|
+ case COMPAT_VPU_IOC_GET_REG: {
|
||
|
+ struct compat_vpu_request req;
|
||
|
+ struct vpu_reg *reg;
|
||
|
+ int ret;
|
||
|
+
|
||
|
+ vpu_debug(DEBUG_IOCTL, "compat get reg type %d\n",
|
||
|
+ session->type);
|
||
|
+ if (copy_from_user(&req, compat_ptr((compat_uptr_t)arg),
|
||
|
+ sizeof(struct compat_vpu_request))) {
|
||
|
+ vpu_err("compat get reg copy_from_user failed\n");
|
||
|
+ return -EFAULT;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = wait_event_timeout(session->wait,
|
||
|
+ !list_empty(&session->done),
|
||
|
+ VPU_TIMEOUT_DELAY);
|
||
|
+
|
||
|
+ if (!list_empty(&session->done)) {
|
||
|
+ if (ret < 0)
|
||
|
+ vpu_err("warning: pid %d wait task error ret %d\n",
|
||
|
+ session->pid, ret);
|
||
|
+ ret = 0;
|
||
|
+ } else {
|
||
|
+ if (unlikely(ret < 0)) {
|
||
|
+ vpu_err("error: pid %d wait task ret %d\n",
|
||
|
+ session->pid, ret);
|
||
|
+ } else if (ret == 0) {
|
||
|
+ vpu_err("error: pid %d wait %d task done timeout\n",
|
||
|
+ session->pid,
|
||
|
+ atomic_read(&session->task_running));
|
||
|
+ ret = -ETIMEDOUT;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ if (ret < 0) {
|
||
|
+ int task_running = atomic_read(&session->task_running);
|
||
|
+
|
||
|
+ mutex_lock(&pservice->lock);
|
||
|
+ vpu_service_dump(pservice);
|
||
|
+ if (task_running) {
|
||
|
+ atomic_set(&session->task_running, 0);
|
||
|
+ atomic_sub(task_running,
|
||
|
+ &pservice->total_running);
|
||
|
+ dev_err(pservice->dev,
|
||
|
+ "%d task is running but not return, reset hardware...",
|
||
|
+ task_running);
|
||
|
+ vpu_reset(data);
|
||
|
+ dev_err(pservice->dev, "done\n");
|
||
|
+ }
|
||
|
+ vpu_service_session_clear(data, session);
|
||
|
+ mutex_unlock(&pservice->lock);
|
||
|
+ return ret;
|
||
|
+ }
|
||
|
+
|
||
|
+ mutex_lock(&pservice->lock);
|
||
|
+ reg = list_entry(session->done.next,
|
||
|
+ struct vpu_reg, session_link);
|
||
|
+ return_reg(data, reg, compat_ptr((compat_uptr_t)req.req));
|
||
|
+ mutex_unlock(&pservice->lock);
|
||
|
+ } break;
|
||
|
+ case COMPAT_VPU_IOC_PROBE_IOMMU_STATUS: {
|
||
|
+ int iommu_enable = 1;
|
||
|
+
|
||
|
+ vpu_debug(DEBUG_IOCTL, "COMPAT_VPU_IOC_PROBE_IOMMU_STATUS\n");
|
||
|
+
|
||
|
+ if (copy_to_user(compat_ptr((compat_uptr_t)arg),
|
||
|
+ &iommu_enable, sizeof(int))) {
|
||
|
+ vpu_err("error: VPU_IOC_PROBE_IOMMU_STATUS copy_to_user failed\n");
|
||
|
+ return -EFAULT;
|
||
|
+ }
|
||
|
+ } break;
|
||
|
+ default: {
|
||
|
+ vpu_err("error: unknow vpu service ioctl cmd %x\n", cmd);
|
||
|
+ } break;
|
||
|
+ }
|
||
|
+ vpu_debug_leave();
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+#endif
|
||
|
+
|
||
|
+static int vpu_service_check_hw(struct vpu_subdev_data *data)
|
||
|
+{
|
||
|
+ int ret = -EINVAL, i = 0;
|
||
|
+ u32 hw_id = readl_relaxed(data->regs);
|
||
|
+
|
||
|
+ hw_id = (hw_id >> 16) & 0xFFFF;
|
||
|
+ dev_info(data->dev, "checking hw id %x\n", hw_id);
|
||
|
+ data->hw_info = NULL;
|
||
|
+
|
||
|
+ for (i = 0; i < ARRAY_SIZE(vcodec_info_set); i++) {
|
||
|
+ const struct vcodec_info *info = &vcodec_info_set[i];
|
||
|
+
|
||
|
+ if (hw_id == info->hw_id) {
|
||
|
+ data->hw_id = info->hw_id;
|
||
|
+ data->hw_info = info->hw_info;
|
||
|
+ data->task_info = info->task_info;
|
||
|
+ data->trans_info = info->trans_info;
|
||
|
+ ret = 0;
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ return ret;
|
||
|
+}
|
||
|
+
|
||
|
+static int vpu_service_open(struct inode *inode, struct file *filp)
|
||
|
+{
|
||
|
+ struct vpu_subdev_data *data = container_of(
|
||
|
+ inode->i_cdev, struct vpu_subdev_data, cdev);
|
||
|
+ struct vpu_service_info *pservice = data->pservice;
|
||
|
+ struct vpu_session *session = NULL;
|
||
|
+
|
||
|
+ vpu_debug_enter();
|
||
|
+
|
||
|
+ session = kzalloc(sizeof(*session), GFP_KERNEL);
|
||
|
+ if (!session) {
|
||
|
+ vpu_err("error: unable to allocate memory for vpu_session.");
|
||
|
+ return -ENOMEM;
|
||
|
+ }
|
||
|
+
|
||
|
+ data->iommu_info->debug_level = debug;
|
||
|
+
|
||
|
+ session->type = VPU_TYPE_BUTT;
|
||
|
+ session->pid = current->pid;
|
||
|
+ INIT_LIST_HEAD(&session->waiting);
|
||
|
+ INIT_LIST_HEAD(&session->running);
|
||
|
+ INIT_LIST_HEAD(&session->done);
|
||
|
+ INIT_LIST_HEAD(&session->list_session);
|
||
|
+ init_waitqueue_head(&session->wait);
|
||
|
+ atomic_set(&session->task_running, 0);
|
||
|
+ mutex_lock(&pservice->lock);
|
||
|
+ list_add_tail(&session->list_session, &pservice->session);
|
||
|
+ filp->private_data = (void *)session;
|
||
|
+ mutex_unlock(&pservice->lock);
|
||
|
+
|
||
|
+ dev_dbg(pservice->dev, "dev opened\n");
|
||
|
+ vpu_debug_leave();
|
||
|
+ return nonseekable_open(inode, filp);
|
||
|
+}
|
||
|
+
|
||
|
+static int vpu_service_release(struct inode *inode, struct file *filp)
|
||
|
+{
|
||
|
+ struct vpu_subdev_data *data = container_of(
|
||
|
+ inode->i_cdev, struct vpu_subdev_data, cdev);
|
||
|
+ struct vpu_service_info *pservice = data->pservice;
|
||
|
+ int task_running;
|
||
|
+ struct vpu_session *session = (struct vpu_session *)filp->private_data;
|
||
|
+
|
||
|
+ vpu_debug_enter();
|
||
|
+ if (NULL == session)
|
||
|
+ return -EINVAL;
|
||
|
+
|
||
|
+ task_running = atomic_read(&session->task_running);
|
||
|
+ if (task_running) {
|
||
|
+ dev_err(pservice->dev,
|
||
|
+ "error: session %d still has %d task running when closing\n",
|
||
|
+ session->pid, task_running);
|
||
|
+ msleep(50);
|
||
|
+ }
|
||
|
+ wake_up(&session->wait);
|
||
|
+
|
||
|
+ mutex_lock(&pservice->lock);
|
||
|
+ /* remove this filp from the asynchronusly notified filp's */
|
||
|
+ list_del_init(&session->list_session);
|
||
|
+ vpu_service_session_clear(data, session);
|
||
|
+ vcodec_iommu_clear(data->iommu_info, session);
|
||
|
+ kfree(session);
|
||
|
+ filp->private_data = NULL;
|
||
|
+ mutex_unlock(&pservice->lock);
|
||
|
+
|
||
|
+ dev_info(pservice->dev, "closed\n");
|
||
|
+ vpu_debug_leave();
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static const struct file_operations vpu_service_fops = {
|
||
|
+ .unlocked_ioctl = vpu_service_ioctl,
|
||
|
+ .open = vpu_service_open,
|
||
|
+ .release = vpu_service_release,
|
||
|
+#ifdef CONFIG_COMPAT
|
||
|
+ .compat_ioctl = compat_vpu_service_ioctl,
|
||
|
+#endif
|
||
|
+};
|
||
|
+
|
||
|
+static irqreturn_t vdpu_irq(int irq, void *dev_id);
|
||
|
+static irqreturn_t vdpu_isr(int irq, void *dev_id);
|
||
|
+static irqreturn_t vepu_irq(int irq, void *dev_id);
|
||
|
+static irqreturn_t vepu_isr(int irq, void *dev_id);
|
||
|
+static void get_hw_info(struct vpu_subdev_data *data);
|
||
|
+
|
||
|
+static struct device *rockchip_get_sysmmu_dev(const char *compt)
|
||
|
+{
|
||
|
+ struct device_node *dn = NULL;
|
||
|
+ struct platform_device *pd = NULL;
|
||
|
+ struct device *ret = NULL;
|
||
|
+
|
||
|
+ dn = of_find_compatible_node(NULL, NULL, compt);
|
||
|
+ if (!dn) {
|
||
|
+ pr_err("can't find device node %s \r\n", compt);
|
||
|
+ return NULL;
|
||
|
+ }
|
||
|
+
|
||
|
+ pd = of_find_device_by_node(dn);
|
||
|
+ if (!pd) {
|
||
|
+ pr_err("can't find platform device in device node %s\n", compt);
|
||
|
+ return NULL;
|
||
|
+ }
|
||
|
+ ret = &pd->dev;
|
||
|
+
|
||
|
+ return ret;
|
||
|
+}
|
||
|
+
|
||
|
+#ifdef CONFIG_IOMMU_API
|
||
|
+static inline void platform_set_sysmmu(struct device *iommu,
|
||
|
+ struct device *dev)
|
||
|
+{
|
||
|
+ dev->archdata.iommu = iommu;
|
||
|
+}
|
||
|
+#else
|
||
|
+static inline void platform_set_sysmmu(struct device *iommu,
|
||
|
+ struct device *dev)
|
||
|
+{
|
||
|
+}
|
||
|
+#endif
|
||
|
+
|
||
|
+int vcodec_sysmmu_fault_hdl(struct device *dev,
|
||
|
+ enum rk_iommu_inttype itype,
|
||
|
+ unsigned long pgtable_base,
|
||
|
+ unsigned long fault_addr, unsigned int status)
|
||
|
+{
|
||
|
+ struct platform_device *pdev;
|
||
|
+ struct vpu_service_info *pservice;
|
||
|
+ struct vpu_subdev_data *data;
|
||
|
+
|
||
|
+ vpu_debug_enter();
|
||
|
+
|
||
|
+ if (dev == NULL) {
|
||
|
+ pr_err("invalid NULL dev\n");
|
||
|
+ return 0;
|
||
|
+ }
|
||
|
+
|
||
|
+ pdev = container_of(dev, struct platform_device, dev);
|
||
|
+ if (pdev == NULL) {
|
||
|
+ pr_err("invalid NULL platform_device\n");
|
||
|
+ return 0;
|
||
|
+ }
|
||
|
+
|
||
|
+ data = platform_get_drvdata(pdev);
|
||
|
+ if (data == NULL) {
|
||
|
+ pr_err("invalid NULL vpu_subdev_data\n");
|
||
|
+ return 0;
|
||
|
+ }
|
||
|
+
|
||
|
+ pservice = data->pservice;
|
||
|
+ if (pservice == NULL) {
|
||
|
+ pr_err("invalid NULL vpu_service_info\n");
|
||
|
+ return 0;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (pservice->reg_codec) {
|
||
|
+ struct vpu_reg *reg = pservice->reg_codec;
|
||
|
+ struct vcodec_mem_region *mem, *n;
|
||
|
+ int i = 0;
|
||
|
+
|
||
|
+ pr_err("vcodec, fault addr 0x%08lx\n", fault_addr);
|
||
|
+ if (!list_empty(®->mem_region_list)) {
|
||
|
+ list_for_each_entry_safe(mem, n, ®->mem_region_list,
|
||
|
+ reg_lnk) {
|
||
|
+ pr_err("vcodec, reg[%02u] mem region [%02d] 0x%lx %lx\n",
|
||
|
+ mem->reg_idx, i, mem->iova, mem->len);
|
||
|
+ i++;
|
||
|
+ }
|
||
|
+ } else {
|
||
|
+ pr_err("no memory region mapped\n");
|
||
|
+ }
|
||
|
+
|
||
|
+ if (reg->data) {
|
||
|
+ struct vpu_subdev_data *data = reg->data;
|
||
|
+ u32 *base = (u32 *)data->dec_dev.regs;
|
||
|
+ u32 len = data->hw_info->dec_reg_num;
|
||
|
+
|
||
|
+ pr_err("current errror register set:\n");
|
||
|
+
|
||
|
+ for (i = 0; i < len; i++)
|
||
|
+ pr_err("reg[%02d] %08x\n",
|
||
|
+ i, readl_relaxed(base + i));
|
||
|
+ }
|
||
|
+
|
||
|
+ pr_alert("vcodec, page fault occur, reset hw\n");
|
||
|
+
|
||
|
+ /* reg->reg[101] = 1; */
|
||
|
+ _vpu_reset(data);
|
||
|
+ }
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static int vcodec_subdev_probe(struct platform_device *pdev,
|
||
|
+ struct vpu_service_info *pservice)
|
||
|
+{
|
||
|
+ uint8_t *regs = NULL;
|
||
|
+ int32_t ret = 0;
|
||
|
+ uint32_t ioaddr = 0;
|
||
|
+ struct resource *res = NULL;
|
||
|
+ struct vpu_hw_info *hw_info = NULL;
|
||
|
+ struct device *dev = &pdev->dev;
|
||
|
+ struct device_node *np = pdev->dev.of_node;
|
||
|
+ struct vpu_subdev_data *data = NULL;
|
||
|
+ struct platform_device *sub_dev = NULL;
|
||
|
+ struct device_node *sub_np = NULL;
|
||
|
+ const char *name = np->name;
|
||
|
+ char mmu_dev_dts_name[40];
|
||
|
+
|
||
|
+ dev_info(dev, "probe device");
|
||
|
+
|
||
|
+ data = devm_kzalloc(dev, sizeof(struct vpu_subdev_data), GFP_KERNEL);
|
||
|
+ if (!data)
|
||
|
+ return -ENOMEM;
|
||
|
+
|
||
|
+ data->pservice = pservice;
|
||
|
+ data->dev = dev;
|
||
|
+
|
||
|
+ INIT_WORK(&data->set_work, vpu_set_register_work);
|
||
|
+
|
||
|
+ switch (pservice->dev_id) {
|
||
|
+ case VCODEC_DEVICE_ID_VPU:
|
||
|
+ data->mode = VCODEC_RUNNING_MODE_VPU;
|
||
|
+ break;
|
||
|
+ case VCODEC_DEVICE_ID_HEVC:
|
||
|
+ data->mode = VCODEC_RUNNING_MODE_HEVC;
|
||
|
+ break;
|
||
|
+ case VCODEC_DEVICE_ID_RKVDEC:
|
||
|
+ data->mode = VCODEC_RUNNING_MODE_RKVDEC;
|
||
|
+ break;
|
||
|
+ case VCODEC_DEVICE_ID_COMBO:
|
||
|
+ default:
|
||
|
+ of_property_read_u32(np, "dev_mode", (u32 *)&data->mode);
|
||
|
+ break;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (pservice->reg_base == 0) {
|
||
|
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||
|
+ data->regs = devm_ioremap_resource(dev, res);
|
||
|
+ if (IS_ERR(data->regs)) {
|
||
|
+ ret = PTR_ERR(data->regs);
|
||
|
+ goto err;
|
||
|
+ }
|
||
|
+ ioaddr = res->start;
|
||
|
+ } else {
|
||
|
+ data->regs = pservice->reg_base;
|
||
|
+ ioaddr = pservice->ioaddr;
|
||
|
+ }
|
||
|
+
|
||
|
+ sub_np = of_parse_phandle(np, "iommus", 0);
|
||
|
+ if (sub_np) {
|
||
|
+ sub_dev = of_find_device_by_node(sub_np);
|
||
|
+ data->mmu_dev = &sub_dev->dev;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Back to legacy iommu probe */
|
||
|
+ if (!data->mmu_dev) {
|
||
|
+ switch (data->mode) {
|
||
|
+ case VCODEC_RUNNING_MODE_VPU:
|
||
|
+ sprintf(mmu_dev_dts_name,
|
||
|
+ VPU_IOMMU_COMPATIBLE_NAME);
|
||
|
+ break;
|
||
|
+ case VCODEC_RUNNING_MODE_RKVDEC:
|
||
|
+ sprintf(mmu_dev_dts_name,
|
||
|
+ VDEC_IOMMU_COMPATIBLE_NAME);
|
||
|
+ break;
|
||
|
+ case VCODEC_RUNNING_MODE_HEVC:
|
||
|
+ default:
|
||
|
+ sprintf(mmu_dev_dts_name,
|
||
|
+ HEVC_IOMMU_COMPATIBLE_NAME);
|
||
|
+ break;
|
||
|
+ }
|
||
|
+
|
||
|
+ data->mmu_dev =
|
||
|
+ rockchip_get_sysmmu_dev(mmu_dev_dts_name);
|
||
|
+ if (data->mmu_dev)
|
||
|
+ platform_set_sysmmu(data->mmu_dev, dev);
|
||
|
+
|
||
|
+ rockchip_iovmm_set_fault_handler
|
||
|
+ (dev, vcodec_sysmmu_fault_hdl);
|
||
|
+ }
|
||
|
+
|
||
|
+ dev_info(dev, "vpu mmu dec %p\n", data->mmu_dev);
|
||
|
+
|
||
|
+ clear_bit(MMU_ACTIVATED, &data->state);
|
||
|
+ vpu_service_power_on(data, pservice);
|
||
|
+
|
||
|
+ of_property_read_u32(np, "allocator", (u32 *)&pservice->alloc_type);
|
||
|
+ data->iommu_info = vcodec_iommu_info_create(dev, data->mmu_dev,
|
||
|
+ pservice->alloc_type);
|
||
|
+ dev_info(dev, "allocator is %s\n", pservice->alloc_type == 1 ? "drm" :
|
||
|
+ (pservice->alloc_type == 2 ? "ion" : "null"));
|
||
|
+ vcodec_enter_mode(data);
|
||
|
+ ret = vpu_service_check_hw(data);
|
||
|
+ if (ret < 0) {
|
||
|
+ dev_err(dev, "error: hw info check failed\n");
|
||
|
+ goto err;
|
||
|
+ }
|
||
|
+ vcodec_exit_mode(data);
|
||
|
+
|
||
|
+ hw_info = data->hw_info;
|
||
|
+ regs = (u8 *)data->regs;
|
||
|
+
|
||
|
+ if (hw_info->dec_reg_num) {
|
||
|
+ data->dec_dev.iosize = hw_info->dec_io_size;
|
||
|
+ data->dec_dev.regs = (u32 *)(regs + hw_info->dec_offset);
|
||
|
+ }
|
||
|
+
|
||
|
+ if (hw_info->enc_reg_num) {
|
||
|
+ data->enc_dev.iosize = hw_info->enc_io_size;
|
||
|
+ data->enc_dev.regs = (u32 *)(regs + hw_info->enc_offset);
|
||
|
+ }
|
||
|
+
|
||
|
+ data->reg_size = max(hw_info->dec_io_size, hw_info->enc_io_size);
|
||
|
+
|
||
|
+ data->irq_enc = platform_get_irq_byname(pdev, "irq_enc");
|
||
|
+ if (data->irq_enc > 0) {
|
||
|
+ ret = devm_request_threaded_irq(dev, data->irq_enc,
|
||
|
+ vepu_irq, vepu_isr,
|
||
|
+ IRQF_SHARED, dev_name(dev),
|
||
|
+ (void *)data);
|
||
|
+ if (ret) {
|
||
|
+ dev_err(dev, "error: can't request vepu irq %d\n",
|
||
|
+ data->irq_enc);
|
||
|
+ goto err;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ data->irq_dec = platform_get_irq_byname(pdev, "irq_dec");
|
||
|
+ if (data->irq_dec > 0) {
|
||
|
+ ret = devm_request_threaded_irq(dev, data->irq_dec,
|
||
|
+ vdpu_irq, vdpu_isr,
|
||
|
+ IRQF_SHARED, dev_name(dev),
|
||
|
+ (void *)data);
|
||
|
+ if (ret) {
|
||
|
+ dev_err(dev, "error: can't request vdpu irq %d\n",
|
||
|
+ data->irq_dec);
|
||
|
+ goto err;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ atomic_set(&data->dec_dev.irq_count_codec, 0);
|
||
|
+ atomic_set(&data->dec_dev.irq_count_pp, 0);
|
||
|
+ atomic_set(&data->enc_dev.irq_count_codec, 0);
|
||
|
+ atomic_set(&data->enc_dev.irq_count_pp, 0);
|
||
|
+
|
||
|
+ get_hw_info(data);
|
||
|
+ pservice->auto_freq = true;
|
||
|
+
|
||
|
+ /* create device node */
|
||
|
+ ret = alloc_chrdev_region(&data->dev_t, 0, 1, name);
|
||
|
+ if (ret) {
|
||
|
+ dev_err(dev, "alloc dev_t failed\n");
|
||
|
+ goto err;
|
||
|
+ }
|
||
|
+
|
||
|
+ cdev_init(&data->cdev, &vpu_service_fops);
|
||
|
+
|
||
|
+ data->cdev.owner = THIS_MODULE;
|
||
|
+ data->cdev.ops = &vpu_service_fops;
|
||
|
+
|
||
|
+ ret = cdev_add(&data->cdev, data->dev_t, 1);
|
||
|
+
|
||
|
+ if (ret) {
|
||
|
+ dev_err(dev, "add dev_t failed\n");
|
||
|
+ goto err;
|
||
|
+ }
|
||
|
+
|
||
|
+ data->cls = class_create(THIS_MODULE, name);
|
||
|
+
|
||
|
+ if (IS_ERR(data->cls)) {
|
||
|
+ ret = PTR_ERR(data->cls);
|
||
|
+ dev_err(dev, "class_create err:%d\n", ret);
|
||
|
+ goto err;
|
||
|
+ }
|
||
|
+
|
||
|
+ data->child_dev = device_create(data->cls, dev,
|
||
|
+ data->dev_t, NULL, "%s", name);
|
||
|
+
|
||
|
+ platform_set_drvdata(pdev, data);
|
||
|
+
|
||
|
+ INIT_LIST_HEAD(&data->lnk_service);
|
||
|
+ list_add_tail(&data->lnk_service, &pservice->subdev_list);
|
||
|
+
|
||
|
+ /* After the subdev was appened to the list of pservice */
|
||
|
+ vpu_service_power_off(pservice);
|
||
|
+
|
||
|
+ return 0;
|
||
|
+err:
|
||
|
+ dev_err(dev, "probe err:%d\n", ret);
|
||
|
+ if (data->child_dev) {
|
||
|
+ device_destroy(data->cls, data->dev_t);
|
||
|
+ cdev_del(&data->cdev);
|
||
|
+ unregister_chrdev_region(data->dev_t, 1);
|
||
|
+ }
|
||
|
+
|
||
|
+ if (data->cls)
|
||
|
+ class_destroy(data->cls);
|
||
|
+ vpu_service_power_off(pservice);
|
||
|
+ return -1;
|
||
|
+}
|
||
|
+
|
||
|
+static void vcodec_subdev_remove(struct vpu_subdev_data *data)
|
||
|
+{
|
||
|
+ struct vpu_service_info *pservice = data->pservice;
|
||
|
+
|
||
|
+ vcodec_iommu_info_destroy(data->iommu_info);
|
||
|
+ data->iommu_info = NULL;
|
||
|
+
|
||
|
+ mutex_lock(&pservice->lock);
|
||
|
+ cancel_delayed_work_sync(&pservice->power_off_work);
|
||
|
+ vpu_service_power_off(pservice);
|
||
|
+ mutex_unlock(&pservice->lock);
|
||
|
+
|
||
|
+ device_destroy(data->cls, data->dev_t);
|
||
|
+ class_destroy(data->cls);
|
||
|
+ cdev_del(&data->cdev);
|
||
|
+ unregister_chrdev_region(data->dev_t, 1);
|
||
|
+
|
||
|
+#ifdef CONFIG_DEBUG_FS
|
||
|
+ if (!IS_ERR_OR_NULL(data->debugfs_dir))
|
||
|
+ debugfs_remove_recursive(data->debugfs_dir);
|
||
|
+#endif
|
||
|
+}
|
||
|
+
|
||
|
+static void vcodec_read_property(struct device_node *np,
|
||
|
+ struct vpu_service_info *pservice)
|
||
|
+{
|
||
|
+ pservice->mode_bit = 0;
|
||
|
+ pservice->mode_ctrl = 0;
|
||
|
+ pservice->subcnt = 0;
|
||
|
+ pservice->grf_base = NULL;
|
||
|
+
|
||
|
+ of_property_read_u32(np, "subcnt", &pservice->subcnt);
|
||
|
+
|
||
|
+ if (pservice->subcnt > 1) {
|
||
|
+ of_property_read_u32(np, "mode_bit", &pservice->mode_bit);
|
||
|
+ of_property_read_u32(np, "mode_ctrl", &pservice->mode_ctrl);
|
||
|
+ }
|
||
|
+#ifdef CONFIG_MFD_SYSCON
|
||
|
+ pservice->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
|
||
|
+ if (IS_ERR_OR_NULL(pservice->grf)) {
|
||
|
+ pservice->grf = NULL;
|
||
|
+#ifdef CONFIG_ARM
|
||
|
+ pservice->grf_base = RK_GRF_VIRT;
|
||
|
+#else
|
||
|
+ vpu_err("can't find vpu grf property\n");
|
||
|
+ return;
|
||
|
+#endif
|
||
|
+ }
|
||
|
+#else
|
||
|
+#ifdef CONFIG_ARM
|
||
|
+ pservice->grf_base = RK_GRF_VIRT;
|
||
|
+#else
|
||
|
+ vpu_err("can't find vpu grf property\n");
|
||
|
+ return;
|
||
|
+#endif
|
||
|
+#endif
|
||
|
+
|
||
|
+#ifdef CONFIG_RESET_CONTROLLER
|
||
|
+ pservice->rst_a = devm_reset_control_get(pservice->dev, "video_a");
|
||
|
+ pservice->rst_h = devm_reset_control_get(pservice->dev, "video_h");
|
||
|
+ pservice->rst_v = devm_reset_control_get(pservice->dev, "video");
|
||
|
+ pservice->rst_niu_a = devm_reset_control_get(pservice->dev, "niu_a");
|
||
|
+ pservice->rst_niu_h = devm_reset_control_get(pservice->dev, "niu_h");
|
||
|
+
|
||
|
+ if (IS_ERR_OR_NULL(pservice->rst_a)) {
|
||
|
+ dev_dbg(pservice->dev, "No aclk reset resource define\n");
|
||
|
+ pservice->rst_a = NULL;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (IS_ERR_OR_NULL(pservice->rst_h)) {
|
||
|
+ dev_dbg(pservice->dev, "No hclk reset resource define\n");
|
||
|
+ pservice->rst_h = NULL;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (IS_ERR_OR_NULL(pservice->rst_v)) {
|
||
|
+ dev_dbg(pservice->dev, "No core reset resource define\n");
|
||
|
+ pservice->rst_v = NULL;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (IS_ERR_OR_NULL(pservice->rst_niu_a)) {
|
||
|
+ dev_dbg(pservice->dev, "No NIU aclk reset resource define\n");
|
||
|
+ pservice->rst_niu_a = NULL;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (IS_ERR_OR_NULL(pservice->rst_niu_h)) {
|
||
|
+ dev_dbg(pservice->dev, "No NIU hclk reset resource define\n");
|
||
|
+ pservice->rst_niu_h = NULL;
|
||
|
+ }
|
||
|
+#endif
|
||
|
+
|
||
|
+ of_property_read_string(np, "name", (const char **)&pservice->name);
|
||
|
+}
|
||
|
+
|
||
|
+static void vcodec_init_drvdata(struct vpu_service_info *pservice)
|
||
|
+{
|
||
|
+ pservice->dev_id = VCODEC_DEVICE_ID_VPU;
|
||
|
+ pservice->curr_mode = -1;
|
||
|
+#ifdef CONFIG_WAKELOCK
|
||
|
+ wake_lock_init(&pservice->wake_lock, WAKE_LOCK_SUSPEND, "vpu");
|
||
|
+#endif
|
||
|
+ INIT_LIST_HEAD(&pservice->waiting);
|
||
|
+ INIT_LIST_HEAD(&pservice->running);
|
||
|
+ mutex_init(&pservice->lock);
|
||
|
+ mutex_init(&pservice->shutdown_lock);
|
||
|
+ atomic_set(&pservice->service_on, 1);
|
||
|
+
|
||
|
+ INIT_LIST_HEAD(&pservice->done);
|
||
|
+ INIT_LIST_HEAD(&pservice->session);
|
||
|
+ INIT_LIST_HEAD(&pservice->subdev_list);
|
||
|
+
|
||
|
+ pservice->reg_pproc = NULL;
|
||
|
+ atomic_set(&pservice->total_running, 0);
|
||
|
+ atomic_set(&pservice->enabled, 0);
|
||
|
+ atomic_set(&pservice->power_on_cnt, 0);
|
||
|
+ atomic_set(&pservice->power_off_cnt, 0);
|
||
|
+ atomic_set(&pservice->reset_request, 0);
|
||
|
+
|
||
|
+ INIT_DELAYED_WORK(&pservice->power_off_work, vpu_power_off_work);
|
||
|
+ pservice->last = 0;
|
||
|
+
|
||
|
+ pservice->alloc_type = 0;
|
||
|
+}
|
||
|
+
|
||
|
+static int vcodec_probe(struct platform_device *pdev)
|
||
|
+{
|
||
|
+ int i;
|
||
|
+ int ret = 0;
|
||
|
+ struct resource *res = NULL;
|
||
|
+ struct device *dev = &pdev->dev;
|
||
|
+ struct device_node *np = pdev->dev.of_node;
|
||
|
+ struct vpu_service_info *pservice = NULL;
|
||
|
+ struct vcodec_device_info *driver_data;
|
||
|
+
|
||
|
+ pservice = devm_kzalloc(dev, sizeof(struct vpu_service_info),
|
||
|
+ GFP_KERNEL);
|
||
|
+ if (!pservice)
|
||
|
+ return -ENOMEM;
|
||
|
+ pservice->dev = dev;
|
||
|
+
|
||
|
+ pservice->set_workq = create_singlethread_workqueue("vcodec");
|
||
|
+ if (!pservice->set_workq) {
|
||
|
+ dev_err(dev, "failed to create workqueue\n");
|
||
|
+ return -ENOMEM;
|
||
|
+ }
|
||
|
+
|
||
|
+ driver_data = vcodec_get_drv_data(pdev);
|
||
|
+ if (!driver_data)
|
||
|
+ return -EINVAL;
|
||
|
+
|
||
|
+ vcodec_read_property(np, pservice);
|
||
|
+ vcodec_init_drvdata(pservice);
|
||
|
+
|
||
|
+ /* Underscore for label, hyphens for name */
|
||
|
+ switch (driver_data->device_type) {
|
||
|
+ case VCODEC_DEVICE_TYPE_VPUX:
|
||
|
+ pservice->dev_id = VCODEC_DEVICE_ID_VPU;
|
||
|
+ break;
|
||
|
+ case VCODEC_DEVICE_TYPE_VPUC:
|
||
|
+ pservice->dev_id = VCODEC_DEVICE_ID_COMBO;
|
||
|
+ break;
|
||
|
+ case VCODEC_DEVICE_TYPE_HEVC:
|
||
|
+ pservice->dev_id = VCODEC_DEVICE_ID_HEVC;
|
||
|
+ break;
|
||
|
+ case VCODEC_DEVICE_TYPE_RKVD:
|
||
|
+ pservice->dev_id = VCODEC_DEVICE_ID_RKVDEC;
|
||
|
+ break;
|
||
|
+ default:
|
||
|
+ dev_err(dev, "unsupported device type\n");
|
||
|
+ return -ENODEV;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (0 > vpu_get_clk(pservice))
|
||
|
+ goto err;
|
||
|
+
|
||
|
+ if (of_property_read_bool(np, "reg")) {
|
||
|
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||
|
+
|
||
|
+ pservice->reg_base = devm_ioremap_resource(pservice->dev, res);
|
||
|
+ if (IS_ERR(pservice->reg_base)) {
|
||
|
+ vpu_err("ioremap registers base failed\n");
|
||
|
+ ret = PTR_ERR(pservice->reg_base);
|
||
|
+ goto err;
|
||
|
+ }
|
||
|
+ pservice->ioaddr = res->start;
|
||
|
+ } else {
|
||
|
+ pservice->reg_base = 0;
|
||
|
+ }
|
||
|
+
|
||
|
+ pm_runtime_enable(dev);
|
||
|
+
|
||
|
+ if (of_property_read_bool(np, "subcnt")) {
|
||
|
+ struct vpu_subdev_data *data = NULL;
|
||
|
+
|
||
|
+ data = devm_kzalloc(dev, sizeof(struct vpu_subdev_data),
|
||
|
+ GFP_KERNEL);
|
||
|
+ if (!data)
|
||
|
+ return -ENOMEM;
|
||
|
+
|
||
|
+ for (i = 0; i < pservice->subcnt; i++) {
|
||
|
+ struct device_node *sub_np;
|
||
|
+ struct platform_device *sub_pdev;
|
||
|
+
|
||
|
+ sub_np = of_parse_phandle(np, "rockchip,sub", i);
|
||
|
+ sub_pdev = of_find_device_by_node(sub_np);
|
||
|
+
|
||
|
+ vcodec_subdev_probe(sub_pdev, pservice);
|
||
|
+ }
|
||
|
+ data->pservice = pservice;
|
||
|
+ platform_set_drvdata(pdev, data);
|
||
|
+ } else {
|
||
|
+ vcodec_subdev_probe(pdev, pservice);
|
||
|
+ }
|
||
|
+
|
||
|
+ dev_info(dev, "init success\n");
|
||
|
+
|
||
|
+ return 0;
|
||
|
+
|
||
|
+err:
|
||
|
+ dev_info(dev, "init failed\n");
|
||
|
+ destroy_workqueue(pservice->set_workq);
|
||
|
+#ifdef CONFIG_WAKELOCK
|
||
|
+ wake_lock_destroy(&pservice->wake_lock);
|
||
|
+#endif
|
||
|
+ return ret;
|
||
|
+}
|
||
|
+
|
||
|
+static int vcodec_remove(struct platform_device *pdev)
|
||
|
+{
|
||
|
+ struct vpu_subdev_data *data = platform_get_drvdata(pdev);
|
||
|
+
|
||
|
+ vcodec_subdev_remove(data);
|
||
|
+
|
||
|
+ pm_runtime_disable(data->pservice->dev);
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static void vcodec_shutdown(struct platform_device *pdev)
|
||
|
+{
|
||
|
+ struct vpu_subdev_data *data = platform_get_drvdata(pdev);
|
||
|
+ struct vpu_service_info *pservice = data->pservice;
|
||
|
+ struct device_node *np = pdev->dev.of_node;
|
||
|
+ int val;
|
||
|
+ int ret;
|
||
|
+ int i;
|
||
|
+
|
||
|
+ dev_info(&pdev->dev, "vcodec shutdown");
|
||
|
+
|
||
|
+ mutex_lock(&pservice->shutdown_lock);
|
||
|
+ atomic_set(&pservice->service_on, 0);
|
||
|
+ mutex_unlock(&pservice->shutdown_lock);
|
||
|
+
|
||
|
+ ret = readx_poll_timeout(atomic_read,
|
||
|
+ &pservice->total_running,
|
||
|
+ val, val == 0, 20000, 200000);
|
||
|
+ if (ret == -ETIMEDOUT)
|
||
|
+ dev_err(&pdev->dev, "wait total running time out\n");
|
||
|
+
|
||
|
+ vcodec_exit_mode(data);
|
||
|
+ vpu_service_clear(data);
|
||
|
+ if (of_property_read_bool(np, "subcnt")) {
|
||
|
+ for (i = 0; i < pservice->subcnt; i++) {
|
||
|
+ struct device_node *sub_np;
|
||
|
+ struct platform_device *sub_pdev;
|
||
|
+
|
||
|
+ sub_np = of_parse_phandle(np, "rockchip,sub", i);
|
||
|
+ sub_pdev = of_find_device_by_node(sub_np);
|
||
|
+ vcodec_subdev_remove(platform_get_drvdata(sub_pdev));
|
||
|
+ }
|
||
|
+
|
||
|
+ } else {
|
||
|
+ vcodec_subdev_remove(data);
|
||
|
+ }
|
||
|
+
|
||
|
+ pm_runtime_disable(&pdev->dev);
|
||
|
+}
|
||
|
+
|
||
|
+static const struct of_device_id vcodec_service_dt_ids[] = {
|
||
|
+ {
|
||
|
+ .compatible = "rockchip,vpu_service",
|
||
|
+ .data = &vpu_device_info,
|
||
|
+ },
|
||
|
+ {
|
||
|
+ .compatible = "rockchip,hevc_service",
|
||
|
+ .data = &hevc_device_info,
|
||
|
+ },
|
||
|
+ {
|
||
|
+ .compatible = "rockchip,vpu_combo",
|
||
|
+ .data = &vpu_combo_device_info,
|
||
|
+ },
|
||
|
+ {
|
||
|
+ .compatible = "rockchip,rkvdec",
|
||
|
+ .data = &rkvd_device_info,
|
||
|
+ },
|
||
|
+ {},
|
||
|
+};
|
||
|
+
|
||
|
+MODULE_DEVICE_TABLE(of, vcodec_service_dt_ids);
|
||
|
+
|
||
|
+static void *vcodec_get_drv_data(struct platform_device *pdev)
|
||
|
+{
|
||
|
+ struct vcodec_device_info *driver_data = NULL;
|
||
|
+ const struct of_device_id *match;
|
||
|
+
|
||
|
+ match = of_match_node(vcodec_service_dt_ids, pdev->dev.of_node);
|
||
|
+ if (match)
|
||
|
+ driver_data = (struct vcodec_device_info *)match->data;
|
||
|
+
|
||
|
+ return driver_data;
|
||
|
+}
|
||
|
+
|
||
|
+static struct platform_driver vcodec_driver = {
|
||
|
+ .probe = vcodec_probe,
|
||
|
+ .remove = vcodec_remove,
|
||
|
+ .shutdown = vcodec_shutdown,
|
||
|
+ .driver = {
|
||
|
+ .name = "rk-vcodec",
|
||
|
+ .owner = THIS_MODULE,
|
||
|
+ .of_match_table = of_match_ptr(vcodec_service_dt_ids),
|
||
|
+ },
|
||
|
+};
|
||
|
+
|
||
|
+static void get_hw_info(struct vpu_subdev_data *data)
|
||
|
+{
|
||
|
+ struct vpu_service_info *pservice = data->pservice;
|
||
|
+ struct vpu_dec_config *dec = &pservice->dec_config;
|
||
|
+ struct vpu_enc_config *enc = &pservice->enc_config;
|
||
|
+
|
||
|
+ if (of_machine_is_compatible("rockchip,rk2928") ||
|
||
|
+ of_machine_is_compatible("rockchip,rk3036") ||
|
||
|
+ of_machine_is_compatible("rockchip,rk3066") ||
|
||
|
+ of_machine_is_compatible("rockchip,rk3126") ||
|
||
|
+ of_machine_is_compatible("rockchip,rk3188"))
|
||
|
+ dec->max_dec_pic_width = 1920;
|
||
|
+ else
|
||
|
+ dec->max_dec_pic_width = 4096;
|
||
|
+
|
||
|
+ if (data->mode == VCODEC_RUNNING_MODE_VPU) {
|
||
|
+ dec->h264_support = 3;
|
||
|
+ dec->jpeg_support = 1;
|
||
|
+ dec->mpeg4_support = 2;
|
||
|
+ dec->vc1_support = 3;
|
||
|
+ dec->mpeg2_support = 1;
|
||
|
+ dec->pp_support = 1;
|
||
|
+ dec->sorenson_support = 1;
|
||
|
+ dec->ref_buf_support = 3;
|
||
|
+ dec->vp6_support = 1;
|
||
|
+ dec->vp7_support = 1;
|
||
|
+ dec->vp8_support = 1;
|
||
|
+ dec->avs_support = 1;
|
||
|
+ dec->jpeg_ext_support = 0;
|
||
|
+ dec->custom_mpeg4_support = 1;
|
||
|
+ dec->reserve = 0;
|
||
|
+ dec->mvc_support = 1;
|
||
|
+
|
||
|
+ if (data->enc_dev.regs) {
|
||
|
+ u32 config_reg = readl_relaxed(data->enc_dev.regs + 63);
|
||
|
+
|
||
|
+ enc->max_encoded_width = config_reg & ((1 << 11) - 1);
|
||
|
+ enc->h264_enabled = 1;
|
||
|
+ enc->mpeg4_enabled = (config_reg >> 26) & 1;
|
||
|
+ enc->jpeg_enabled = 1;
|
||
|
+ enc->vs_enabled = (config_reg >> 24) & 1;
|
||
|
+ enc->rgb_enabled = (config_reg >> 28) & 1;
|
||
|
+ enc->reg_size = data->reg_size;
|
||
|
+ enc->reserv[0] = 0;
|
||
|
+ enc->reserv[1] = 0;
|
||
|
+ }
|
||
|
+
|
||
|
+ pservice->auto_freq = true;
|
||
|
+ vpu_debug(DEBUG_EXTRA_INFO,
|
||
|
+ "vpu_service set to auto frequency mode\n");
|
||
|
+ atomic_set(&pservice->freq_status, VPU_FREQ_BUT);
|
||
|
+
|
||
|
+ pservice->bug_dec_addr = of_machine_is_compatible
|
||
|
+ ("rockchip,rk30xx");
|
||
|
+ } else if (data->mode == VCODEC_RUNNING_MODE_RKVDEC) {
|
||
|
+ pservice->auto_freq = true;
|
||
|
+ atomic_set(&pservice->freq_status, VPU_FREQ_BUT);
|
||
|
+ } else {
|
||
|
+ /* disable frequency switch in hevc.*/
|
||
|
+ pservice->auto_freq = false;
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+static bool check_irq_err(struct vpu_task_info *task, u32 irq_status)
|
||
|
+{
|
||
|
+ vpu_debug(DEBUG_IRQ_CHECK, "task %s status %08x mask %08x\n",
|
||
|
+ task->name, irq_status, task->error_mask);
|
||
|
+
|
||
|
+ return (task->error_mask & irq_status) ? true : false;
|
||
|
+}
|
||
|
+
|
||
|
+static irqreturn_t vdpu_irq(int irq, void *dev_id)
|
||
|
+{
|
||
|
+ struct vpu_subdev_data *data = (struct vpu_subdev_data *)dev_id;
|
||
|
+ struct vpu_service_info *pservice = data->pservice;
|
||
|
+ struct vpu_task_info *task = NULL;
|
||
|
+ struct vpu_device *dev = &data->dec_dev;
|
||
|
+ u32 hw_id = data->hw_info->hw_id;
|
||
|
+ u32 raw_status;
|
||
|
+ u32 dec_status;
|
||
|
+
|
||
|
+ task = &data->task_info[TASK_DEC];
|
||
|
+
|
||
|
+ raw_status = readl_relaxed(dev->regs + task->reg_irq);
|
||
|
+ dec_status = raw_status;
|
||
|
+
|
||
|
+ vpu_debug(DEBUG_TASK_INFO,
|
||
|
+ "vdpu_irq reg %d status %x mask: irq %x ready %x error %0x\n",
|
||
|
+ task->reg_irq, dec_status,
|
||
|
+ task->irq_mask, task->ready_mask, task->error_mask);
|
||
|
+
|
||
|
+ if (dec_status & task->irq_mask) {
|
||
|
+ time_record(task, 1);
|
||
|
+ vpu_debug(DEBUG_IRQ_STATUS, "vdpu_irq dec status %08x\n",
|
||
|
+ dec_status);
|
||
|
+ if ((dec_status & 0x40001) == 0x40001) {
|
||
|
+ do {
|
||
|
+ dec_status = readl_relaxed(dev->regs +
|
||
|
+ task->reg_irq);
|
||
|
+ } while ((dec_status & 0x40001) == 0x40001);
|
||
|
+ }
|
||
|
+
|
||
|
+ if (check_irq_err(task, dec_status))
|
||
|
+ atomic_add(1, &pservice->reset_request);
|
||
|
+
|
||
|
+ writel_relaxed(0, dev->regs + task->reg_irq);
|
||
|
+
|
||
|
+ /* set clock gating to save power */
|
||
|
+ writel(task->gating_mask, dev->regs + task->reg_en);
|
||
|
+
|
||
|
+ atomic_add(1, &dev->irq_count_codec);
|
||
|
+ time_diff(task);
|
||
|
+ pservice->irq_status = raw_status;
|
||
|
+ }
|
||
|
+
|
||
|
+ task = &data->task_info[TASK_PP];
|
||
|
+ if (hw_id != HEVC_ID && hw_id != RKV_DEC_ID) {
|
||
|
+ u32 pp_status = readl_relaxed(dev->regs + task->irq_mask);
|
||
|
+
|
||
|
+ if (pp_status & task->irq_mask) {
|
||
|
+ time_record(task, 1);
|
||
|
+ vpu_debug(DEBUG_IRQ_STATUS, "vdpu_irq pp status %08x\n",
|
||
|
+ pp_status);
|
||
|
+
|
||
|
+ if (check_irq_err(task, dec_status))
|
||
|
+ atomic_add(1, &pservice->reset_request);
|
||
|
+
|
||
|
+ /* clear pp IRQ */
|
||
|
+ writel_relaxed(pp_status & (~task->reg_irq),
|
||
|
+ dev->regs + task->irq_mask);
|
||
|
+ atomic_add(1, &dev->irq_count_pp);
|
||
|
+ time_diff(task);
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ if (atomic_read(&dev->irq_count_pp) ||
|
||
|
+ atomic_read(&dev->irq_count_codec))
|
||
|
+ return IRQ_WAKE_THREAD;
|
||
|
+ else
|
||
|
+ return IRQ_NONE;
|
||
|
+}
|
||
|
+
|
||
|
+static irqreturn_t vdpu_isr(int irq, void *dev_id)
|
||
|
+{
|
||
|
+ struct vpu_subdev_data *data = (struct vpu_subdev_data *)dev_id;
|
||
|
+ struct vpu_service_info *pservice = data->pservice;
|
||
|
+ struct vpu_device *dev = &data->dec_dev;
|
||
|
+
|
||
|
+ mutex_lock(&pservice->lock);
|
||
|
+ if (atomic_read(&dev->irq_count_codec)) {
|
||
|
+ atomic_sub(1, &dev->irq_count_codec);
|
||
|
+ if (pservice->reg_codec == NULL) {
|
||
|
+ vpu_err("error: dec isr with no task waiting\n");
|
||
|
+ } else {
|
||
|
+ reg_from_run_to_done(data, pservice->reg_codec);
|
||
|
+ /* avoid vpu timeout and can't recover problem */
|
||
|
+ if (data->mode == VCODEC_RUNNING_MODE_VPU)
|
||
|
+ VDPU_SOFT_RESET(data->regs);
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ if (atomic_read(&dev->irq_count_pp)) {
|
||
|
+ atomic_sub(1, &dev->irq_count_pp);
|
||
|
+ if (pservice->reg_pproc == NULL)
|
||
|
+ vpu_err("error: pp isr with no task waiting\n");
|
||
|
+ else
|
||
|
+ reg_from_run_to_done(data, pservice->reg_pproc);
|
||
|
+ }
|
||
|
+
|
||
|
+ queue_work(pservice->set_workq, &data->set_work);
|
||
|
+ mutex_unlock(&pservice->lock);
|
||
|
+ return IRQ_HANDLED;
|
||
|
+}
|
||
|
+
|
||
|
+static irqreturn_t vepu_irq(int irq, void *dev_id)
|
||
|
+{
|
||
|
+ struct vpu_subdev_data *data = (struct vpu_subdev_data *)dev_id;
|
||
|
+ struct vpu_service_info *pservice = data->pservice;
|
||
|
+ struct vpu_task_info *task = &data->task_info[TASK_ENC];
|
||
|
+ struct vpu_device *dev = &data->enc_dev;
|
||
|
+ u32 irq_status;
|
||
|
+
|
||
|
+ irq_status = readl_relaxed(dev->regs + task->reg_irq);
|
||
|
+
|
||
|
+ vpu_debug(DEBUG_TASK_INFO,
|
||
|
+ "vepu_irq reg %d status %x mask: irq %x ready %x error %0x\n",
|
||
|
+ task->reg_irq, irq_status,
|
||
|
+ task->irq_mask, task->ready_mask, task->error_mask);
|
||
|
+
|
||
|
+ vpu_debug(DEBUG_IRQ_STATUS, "vepu_irq enc status %08x\n", irq_status);
|
||
|
+
|
||
|
+ if (likely(irq_status & task->irq_mask)) {
|
||
|
+ time_record(task, 1);
|
||
|
+
|
||
|
+ if (check_irq_err(task, irq_status))
|
||
|
+ atomic_add(1, &pservice->reset_request);
|
||
|
+
|
||
|
+ /* clear enc IRQ */
|
||
|
+ writel_relaxed(irq_status & (~task->irq_mask),
|
||
|
+ dev->regs + task->reg_irq);
|
||
|
+
|
||
|
+ atomic_add(1, &dev->irq_count_codec);
|
||
|
+ time_diff(task);
|
||
|
+ }
|
||
|
+
|
||
|
+ pservice->irq_status = irq_status;
|
||
|
+
|
||
|
+ if (atomic_read(&dev->irq_count_codec))
|
||
|
+ return IRQ_WAKE_THREAD;
|
||
|
+ else
|
||
|
+ return IRQ_NONE;
|
||
|
+}
|
||
|
+
|
||
|
+static irqreturn_t vepu_isr(int irq, void *dev_id)
|
||
|
+{
|
||
|
+ struct vpu_subdev_data *data = (struct vpu_subdev_data *)dev_id;
|
||
|
+ struct vpu_service_info *pservice = data->pservice;
|
||
|
+ struct vpu_device *dev = &data->enc_dev;
|
||
|
+
|
||
|
+ mutex_lock(&pservice->lock);
|
||
|
+ if (atomic_read(&dev->irq_count_codec)) {
|
||
|
+ atomic_sub(1, &dev->irq_count_codec);
|
||
|
+ if (NULL == pservice->reg_codec)
|
||
|
+ vpu_err("error: enc isr with no task waiting\n");
|
||
|
+ else
|
||
|
+ reg_from_run_to_done(data, pservice->reg_codec);
|
||
|
+ }
|
||
|
+ queue_work(pservice->set_workq, &data->set_work);
|
||
|
+ mutex_unlock(&pservice->lock);
|
||
|
+
|
||
|
+ return IRQ_HANDLED;
|
||
|
+}
|
||
|
+
|
||
|
+module_platform_driver(vcodec_driver);
|
||
|
+MODULE_LICENSE("GPL v2");
|
||
|
diff --git a/drivers/video/rk_vcodec/vcodec_service.h b/drivers/video/rk_vcodec/vcodec_service.h
|
||
|
new file mode 100644
|
||
|
index 0000000..956c692
|
||
|
--- /dev/null
|
||
|
+++ b/drivers/video/rk_vcodec/vcodec_service.h
|
||
|
@@ -0,0 +1,116 @@
|
||
|
+/*
|
||
|
+ * Copyright (C) 2015 Fuzhou Rockchip Electronics Co., Ltd
|
||
|
+ * author: chenhengming chm@rock-chips.com
|
||
|
+ * Alpha Lin, alpha.lin@rock-chips.com
|
||
|
+ *
|
||
|
+ * This software is licensed under the terms of the GNU General Public
|
||
|
+ * License version 2, as published by the Free Software Foundation, and
|
||
|
+ * may be copied, distributed, and modified under those terms.
|
||
|
+ *
|
||
|
+ * 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 __ARCH_ARM_MACH_RK29_VCODEC_SERVICE_H
|
||
|
+#define __ARCH_ARM_MACH_RK29_VCODEC_SERVICE_H
|
||
|
+
|
||
|
+#include <linux/ioctl.h> /* needed for the _IOW etc stuff used later */
|
||
|
+#include "config.h"
|
||
|
+
|
||
|
+/*
|
||
|
+ * Ioctl definitions
|
||
|
+ */
|
||
|
+
|
||
|
+/* Use 'k' as magic number */
|
||
|
+#define VPU_IOC_MAGIC 'l'
|
||
|
+
|
||
|
+#define VPU_IOC_SET_CLIENT_TYPE _IOW(VPU_IOC_MAGIC, 1, unsigned long)
|
||
|
+#define VPU_IOC_GET_HW_FUSE_STATUS _IOW(VPU_IOC_MAGIC, 2, unsigned long)
|
||
|
+
|
||
|
+#define VPU_IOC_SET_REG _IOW(VPU_IOC_MAGIC, 3, unsigned long)
|
||
|
+#define VPU_IOC_GET_REG _IOW(VPU_IOC_MAGIC, 4, unsigned long)
|
||
|
+
|
||
|
+#define VPU_IOC_PROBE_IOMMU_STATUS _IOR(VPU_IOC_MAGIC, 5, unsigned long)
|
||
|
+
|
||
|
+#ifdef CONFIG_COMPAT
|
||
|
+#define COMPAT_VPU_IOC_SET_CLIENT_TYPE _IOW(VPU_IOC_MAGIC, 1, u32)
|
||
|
+#define COMPAT_VPU_IOC_GET_HW_FUSE_STATUS _IOW(VPU_IOC_MAGIC, 2, u32)
|
||
|
+
|
||
|
+#define COMPAT_VPU_IOC_SET_REG _IOW(VPU_IOC_MAGIC, 3, u32)
|
||
|
+#define COMPAT_VPU_IOC_GET_REG _IOW(VPU_IOC_MAGIC, 4, u32)
|
||
|
+
|
||
|
+#define COMPAT_VPU_IOC_PROBE_IOMMU_STATUS _IOR(VPU_IOC_MAGIC, 5, u32)
|
||
|
+#endif
|
||
|
+
|
||
|
+enum VPU_CLIENT_TYPE {
|
||
|
+ VPU_ENC = 0x0,
|
||
|
+ VPU_DEC = 0x1,
|
||
|
+ VPU_PP = 0x2,
|
||
|
+ VPU_DEC_PP = 0x3,
|
||
|
+ VPU_TYPE_BUTT,
|
||
|
+};
|
||
|
+
|
||
|
+/* Hardware decoder configuration description */
|
||
|
+struct vpu_dec_config {
|
||
|
+ /* Maximum video decoding width supported */
|
||
|
+ u32 max_dec_pic_width;
|
||
|
+ /* Maximum output width of Post-Processor */
|
||
|
+ u32 max_pp_out_pic_width;
|
||
|
+ /* HW supports h.264 */
|
||
|
+ u32 h264_support;
|
||
|
+ /* HW supports JPEG */
|
||
|
+ u32 jpeg_support;
|
||
|
+ /* HW supports MPEG-4 */
|
||
|
+ u32 mpeg4_support;
|
||
|
+ /* HW supports custom MPEG-4 features */
|
||
|
+ u32 custom_mpeg4_support;
|
||
|
+ /* HW supports VC-1 Simple */
|
||
|
+ u32 vc1_support;
|
||
|
+ /* HW supports MPEG-2 */
|
||
|
+ u32 mpeg2_support;
|
||
|
+ /* HW supports post-processor */
|
||
|
+ u32 pp_support;
|
||
|
+ /* HW post-processor functions bitmask */
|
||
|
+ u32 pp_config;
|
||
|
+ /* HW supports Sorenson Spark */
|
||
|
+ u32 sorenson_support;
|
||
|
+ /* HW supports reference picture buffering */
|
||
|
+ u32 ref_buf_support;
|
||
|
+ /* HW supports VP6 */
|
||
|
+ u32 vp6_support;
|
||
|
+ /* HW supports VP7 */
|
||
|
+ u32 vp7_support;
|
||
|
+ /* HW supports VP8 */
|
||
|
+ u32 vp8_support;
|
||
|
+ /* HW supports AVS */
|
||
|
+ u32 avs_support;
|
||
|
+ /* HW supports JPEG extensions */
|
||
|
+ u32 jpeg_ext_support;
|
||
|
+ u32 reserve;
|
||
|
+ /* HW supports H264 MVC extension */
|
||
|
+ u32 mvc_support;
|
||
|
+};
|
||
|
+
|
||
|
+/* Hardware encoder configuration description */
|
||
|
+struct vpu_enc_config {
|
||
|
+ /* Maximum supported width for video encoding (not JPEG) */
|
||
|
+ u32 max_encoded_width;
|
||
|
+ /* HW supports H.264 */
|
||
|
+ u32 h264_enabled;
|
||
|
+ /* HW supports JPEG */
|
||
|
+ u32 jpeg_enabled;
|
||
|
+ /* HW supports MPEG-4 */
|
||
|
+ u32 mpeg4_enabled;
|
||
|
+ /* HW supports video stabilization */
|
||
|
+ u32 vs_enabled;
|
||
|
+ /* HW supports RGB input */
|
||
|
+ u32 rgb_enabled;
|
||
|
+ u32 reg_size;
|
||
|
+ u32 reserv[2];
|
||
|
+};
|
||
|
+
|
||
|
+#endif
|
||
|
+
|
||
|
diff --git a/include/dt-bindings/clock/rockchip,rk3036.h b/include/dt-bindings/clock/rockchip,rk3036.h
|
||
|
new file mode 100644
|
||
|
index 0000000..019550c
|
||
|
--- /dev/null
|
||
|
+++ b/include/dt-bindings/clock/rockchip,rk3036.h
|
||
|
@@ -0,0 +1,155 @@
|
||
|
+#ifndef _DT_BINDINGS_CLOCK_ROCKCHIP_RK3036_H
|
||
|
+#define _DT_BINDINGS_CLOCK_ROCKCHIP_RK3036_H
|
||
|
+
|
||
|
+#include "rockchip.h"
|
||
|
+
|
||
|
+/* pll id */
|
||
|
+#define RK3036_APLL_ID 0
|
||
|
+#define RK3036_DPLL_ID 1
|
||
|
+#define RK3036_GPLL_ID 2
|
||
|
+#define RK3036_END_PLL_ID 3
|
||
|
+
|
||
|
+/* reset id */
|
||
|
+#define RK3036_RST_CORE0 0
|
||
|
+#define RK3036_RST_CORE1 1
|
||
|
+#define RK3036_RST_0RES2 2
|
||
|
+#define RK3036_RST_0RES3 3
|
||
|
+#define RK3036_RST_CORE0_DBG 4
|
||
|
+#define RK3036_RST_CORE1_DBG 5
|
||
|
+#define RK3036_RST_0RES6 6
|
||
|
+#define RK3036_RST_0RES7 7
|
||
|
+#define RK3036_RST_CORE0_POR 8
|
||
|
+#define RK3036_RST_CORE1_POR 9
|
||
|
+#define RK3036_RST_0RES10 10
|
||
|
+#define RK3036_RST_0RES11 11
|
||
|
+#define RK3036_RST_L2C 12
|
||
|
+#define RK3036_RST_TOPDBG 13
|
||
|
+#define RK3036_RST_STRC_SYS_A 14
|
||
|
+#define RK3036_RST_PD_CORE_NIU 15
|
||
|
+
|
||
|
+#define RK3036_RST_TIMER2 16
|
||
|
+#define RK3036_RST_CPUSYS_H 17
|
||
|
+#define RK3036_RST_1RES2 18
|
||
|
+#define RK3036_RST_AHB2APB_H 19
|
||
|
+#define RK3036_RST_TIMER3 20
|
||
|
+#define RK3036_RST_INTMEM 21
|
||
|
+#define RK3036_RST_ROM 22
|
||
|
+#define RK3036_RST_PERI_NIU 23
|
||
|
+#define RK3036_RST_I2S 24
|
||
|
+#define RK3036_RST_DDR_PLL 25
|
||
|
+#define RK3036_RST_GPU_DLL 26
|
||
|
+#define RK3036_RST_TIMER0 27
|
||
|
+#define RK3036_RST_TIMER1 28
|
||
|
+#define RK3036_RST_CORE_DLL 29
|
||
|
+#define RK3036_RST_EFUSE_P 30
|
||
|
+#define RK3036_RST_ACODEC_P 31
|
||
|
+
|
||
|
+#define RK3036_RST_GPIO0 32
|
||
|
+#define RK3036_RST_GPIO1 33
|
||
|
+#define RK3036_RST_GPIO2 34
|
||
|
+#define RK3036_RST_2RES3 35
|
||
|
+#define RK3036_RST_2RES4 36
|
||
|
+#define RK3036_RST_2RES5 37
|
||
|
+#define RK3036_RST_2RES6 38
|
||
|
+#define RK3036_RST_UART0 39
|
||
|
+#define RK3036_RST_UART1 40
|
||
|
+#define RK3036_RST_UART2 41
|
||
|
+#define RK3036_RST_2RES10 42
|
||
|
+#define RK3036_RST_I2C0 43
|
||
|
+#define RK3036_RST_I2C1 44
|
||
|
+#define RK3036_RST_I2C2 45
|
||
|
+#define RK3036_RST_2RES14 46
|
||
|
+#define RK3036_RST_SFC 47
|
||
|
+
|
||
|
+#define RK3036_RST_PWM0 48
|
||
|
+#define RK3036_RST_3RES1 49
|
||
|
+#define RK3036_RST_3RES2 50
|
||
|
+#define RK3036_RST_DAP 51
|
||
|
+#define RK3036_RST_DAP_SYS 52
|
||
|
+#define RK3036_RST_3RES5 53
|
||
|
+#define RK3036_RST_3RES6 54
|
||
|
+#define RK3036_RST_GRF 55
|
||
|
+#define RK3036_RST_3RES8 56
|
||
|
+#define RK3036_RST_PERIPHSYS_A 57
|
||
|
+#define RK3036_RST_PERIPHSYS_H 58
|
||
|
+#define RK3036_RST_PERIPHSYS_P 59
|
||
|
+#define RK3036_RST_3RES12 60
|
||
|
+#define RK3036_RST_CPU_PERI 61
|
||
|
+#define RK3036_RST_EMEM_PERI 62
|
||
|
+#define RK3036_RST_USB_PERI 63
|
||
|
+
|
||
|
+#define RK3036_RST_DMA2 64
|
||
|
+#define RK3036_RST_4RES1 65
|
||
|
+#define RK3036_RST_MAC 66
|
||
|
+#define RK3036_RST_4RES3 67
|
||
|
+#define RK3036_RST_NANDC 68
|
||
|
+#define RK3036_RST_USBOTG0 69
|
||
|
+#define RK3036_RST_4RES6 70
|
||
|
+#define RK3036_RST_OTGC0 71
|
||
|
+#define RK3036_RST_USBOTG1 72
|
||
|
+#define RK3036_RST_4RES9 73
|
||
|
+#define RK3036_RST_OTGC1 74
|
||
|
+#define RK3036_RST_4RES11 75
|
||
|
+#define RK3036_RST_4RES12 76
|
||
|
+#define RK3036_RST_4RES13 77
|
||
|
+#define RK3036_RST_4RES14 78
|
||
|
+#define RK3036_RST_DDRMSCH 79
|
||
|
+
|
||
|
+#define RK3036_RST_5RES0 80
|
||
|
+#define RK3036_RST_MMC0 81
|
||
|
+#define RK3036_RST_SDIO 82
|
||
|
+#define RK3036_RST_EMMC 83
|
||
|
+#define RK3036_RST_SPI0 84
|
||
|
+#define RK3036_RST_5RES5 85
|
||
|
+#define RK3036_RST_WDT 86
|
||
|
+#define RK3036_RST_5RES7 87
|
||
|
+#define RK3036_RST_DDRPHY 88
|
||
|
+#define RK3036_RST_DDRPHY_P 89
|
||
|
+#define RK3036_RST_DDRCTRL 90
|
||
|
+#define RK3036_RST_DDRCTRL_P 91
|
||
|
+#define RK3036_RST_5RES12 92
|
||
|
+#define RK3036_RST_5RES13 93
|
||
|
+#define RK3036_RST_5RES14 94
|
||
|
+#define RK3036_RST_5RES15 95
|
||
|
+
|
||
|
+#define RK3036_RST_HDMI_P 96
|
||
|
+#define RK3036_RST_6RES1 97
|
||
|
+#define RK3036_RST_6RES2 98
|
||
|
+#define RK3036_RST_VIO_BUS_H 99
|
||
|
+#define RK3036_RST_6RES4 100
|
||
|
+#define RK3036_RST_6RES5 101
|
||
|
+#define RK3036_RST_6RES6 102
|
||
|
+#define RK3036_RST_UTMI0 103
|
||
|
+#define RK3036_RST_UTMI1 104
|
||
|
+#define RK3036_RST_USBPOR 105
|
||
|
+#define RK3036_RST_6RES10 106
|
||
|
+#define RK3036_RST_6RES11 107
|
||
|
+#define RK3036_RST_6RES12 108
|
||
|
+#define RK3036_RST_6RES13 109
|
||
|
+#define RK3036_RST_6RES14 110
|
||
|
+#define RK3036_RST_6RES15 111
|
||
|
+
|
||
|
+#define RK3036_RST_VCODEC_A 112
|
||
|
+#define RK3036_RST_VCODEC_H 113
|
||
|
+#define RK3036_RST_VIO1_A 114
|
||
|
+#define RK3036_RST_HEVC 115
|
||
|
+#define RK3036_RST_VCODEC_NIU_A 116
|
||
|
+#define RK3036_RST_LCDC1_A 117
|
||
|
+#define RK3036_RST_LCDC1_H 118
|
||
|
+#define RK3036_RST_LCDC1_D 119
|
||
|
+#define RK3036_RST_GPU 120
|
||
|
+#define RK3036_RST_7RES9 121
|
||
|
+#define RK3036_RST_GPU_NIU_A 122
|
||
|
+#define RK3036_RST_7RES11 123
|
||
|
+#define RK3036_RST_7RES12 124
|
||
|
+#define RK3036_RST_7RES13 125
|
||
|
+#define RK3036_RST_7RES14 126
|
||
|
+#define RK3036_RST_7RES15 127
|
||
|
+
|
||
|
+#define RK3036_RST_8RES0 128
|
||
|
+#define RK3036_RST_8RES1 129
|
||
|
+#define RK3036_RST_8RES2 130
|
||
|
+#define RK3036_RST_DBG_P 131
|
||
|
+/* con8[15:4] is reserved */
|
||
|
+
|
||
|
+#endif /* _DT_BINDINGS_CLOCK_ROCKCHIP_RK3036_H */
|
||
|
diff --git a/include/dt-bindings/clock/rockchip,rk312x.h b/include/dt-bindings/clock/rockchip,rk312x.h
|
||
|
new file mode 100755
|
||
|
index 0000000..0af5abc
|
||
|
--- /dev/null
|
||
|
+++ b/include/dt-bindings/clock/rockchip,rk312x.h
|
||
|
@@ -0,0 +1,167 @@
|
||
|
+#ifndef _DT_BINDINGS_CLOCK_ROCKCHIP_RK3128_H
|
||
|
+#define _DT_BINDINGS_CLOCK_ROCKCHIP_RK3128_H
|
||
|
+
|
||
|
+#include "rockchip.h"
|
||
|
+
|
||
|
+/* pll id */
|
||
|
+#define RK3128_APLL_ID 0
|
||
|
+#define RK3128_DPLL_ID 1
|
||
|
+#define RK3128_CPLL_ID 2
|
||
|
+#define RK3128_GPLL_ID 3
|
||
|
+#define RK3128_END_PLL_ID 4
|
||
|
+
|
||
|
+/* reset id */
|
||
|
+#define RK3128_RST_CORE0_PO 0
|
||
|
+#define RK3128_RST_CORE1_PO 1
|
||
|
+#define RK3128_RST_CORE2_PO 2
|
||
|
+#define RK3128_RST_CORE3_PO 3
|
||
|
+#define RK3128_RST_CORE0 4
|
||
|
+#define RK3128_RST_CORE1 5
|
||
|
+#define RK3128_RST_CORE2 6
|
||
|
+#define RK3128_RST_CORE3 7
|
||
|
+#define RK3128_RST_CORE0_DBG 8
|
||
|
+#define RK3128_RST_CORE1_DBG 9
|
||
|
+#define RK3128_RST_CORE2_DBG 10
|
||
|
+#define RK3128_RST_CORE3_DBG 11
|
||
|
+#define RK3128_RST_TOPDBG 12
|
||
|
+#define RK3128_RST_ACLK_CORE 13
|
||
|
+#define RK3128_RST_STRC_SYS_A 14
|
||
|
+#define RK3128_RST_L2C 15
|
||
|
+
|
||
|
+#define RK3128_RST_1RES0 16
|
||
|
+#define RK3128_RST_1RES1 17
|
||
|
+#define RK3128_RST_CPUSYS_H 18
|
||
|
+#define RK3128_RST_AHB2APB_H 19
|
||
|
+#define RK3128_RST_SPDIF 20
|
||
|
+#define RK3128_RST_INTMEM 21
|
||
|
+#define RK3128_RST_ROM 22
|
||
|
+#define RK3128_RST_PERI_NIU 23
|
||
|
+#define RK3128_RST_I2S_2CH 24
|
||
|
+#define RK3128_RST_I2S_8CH 25
|
||
|
+#define RK3128_RST_GPU_PVTM 26
|
||
|
+#define RK3128_RST_FUNC_PVTM 27
|
||
|
+#define RK3128_RST_1RES12 28
|
||
|
+#define RK3128_RST_CORE_PVTM 29
|
||
|
+#define RK3128_RST_EFUSE_P 30
|
||
|
+#define RK3128_RST_ACODEC_P 31
|
||
|
+
|
||
|
+#define RK3128_RST_GPIO0 32
|
||
|
+#define RK3128_RST_GPIO1 33
|
||
|
+#define RK3128_RST_GPIO2 34
|
||
|
+#define RK3128_RST_GPIO3 35
|
||
|
+#define RK3128_RST_MIPIPHY 36
|
||
|
+#define RK3128_RST_2RES5 37
|
||
|
+#define RK3128_RST_2RES6 38
|
||
|
+#define RK3128_RST_UART0 39
|
||
|
+#define RK3128_RST_UART1 40
|
||
|
+#define RK3128_RST_UART2 41
|
||
|
+#define RK3128_RST_2RES10 42
|
||
|
+#define RK3128_RST_I2C0 43
|
||
|
+#define RK3128_RST_I2C1 44
|
||
|
+#define RK3128_RST_I2C2 45
|
||
|
+#define RK3128_RST_I2C3 46
|
||
|
+#define RK3128_RST_SFC 47
|
||
|
+
|
||
|
+#define RK3128_RST_PWM0 48
|
||
|
+#define RK3128_RST_3RES1 49
|
||
|
+#define RK3128_RST_DAP_P 50
|
||
|
+#define RK3128_RST_DAP 51
|
||
|
+#define RK3128_RST_DAP_SYS 52
|
||
|
+#define RK3128_RST_CRYPTO 53
|
||
|
+#define RK3128_RST_3RES6 54
|
||
|
+#define RK3128_RST_GRF 55
|
||
|
+#define RK3128_RST_GMAC 56
|
||
|
+#define RK3128_RST_PERIPHSYS_A 57
|
||
|
+#define RK3128_RST_PERIPHSYS_H 58
|
||
|
+#define RK3128_RST_PERIPHSYS_P 59
|
||
|
+#define RK3128_RST_SMART_CARD 60
|
||
|
+#define RK3128_RST_CPU_PERI 61
|
||
|
+#define RK3128_RST_EMEM_PERI 62
|
||
|
+#define RK3128_RST_USB_PERI 63
|
||
|
+
|
||
|
+#define RK3128_RST_DMA2 64
|
||
|
+#define RK3128_RST_4RES1 65
|
||
|
+#define RK3128_RST_4RES2 66
|
||
|
+#define RK3128_RST_GPS 67
|
||
|
+#define RK3128_RST_NANDC 68
|
||
|
+#define RK3128_RST_USBOTG0 69
|
||
|
+#define RK3128_RST_4RES6 70
|
||
|
+#define RK3128_RST_OTGC0 71
|
||
|
+#define RK3128_RST_USBOTG1 72
|
||
|
+#define RK3128_RST_4RES9 73
|
||
|
+#define RK3128_RST_OTGC1 74
|
||
|
+#define RK3128_RST_4RES11 75
|
||
|
+#define RK3128_RST_4RES12 76
|
||
|
+#define RK3128_RST_4RES13 77
|
||
|
+#define RK3128_RST_4RES14 78
|
||
|
+#define RK3128_RST_DDRMSCH 79
|
||
|
+
|
||
|
+#define RK3128_RST_5RES0 80
|
||
|
+#define RK3128_RST_MMC0 81
|
||
|
+#define RK3128_RST_SDIO 82
|
||
|
+#define RK3128_RST_EMMC 83
|
||
|
+#define RK3128_RST_SPI0 84
|
||
|
+#define RK3128_RST_5RES5 85
|
||
|
+#define RK3128_RST_WDT 86
|
||
|
+#define RK3128_RST_SARADC 87
|
||
|
+#define RK3128_RST_DDRPHY 88
|
||
|
+#define RK3128_RST_DDRPHY_P 89
|
||
|
+#define RK3128_RST_DDRCTRL 90
|
||
|
+#define RK3128_RST_DDRCTRL_P 91
|
||
|
+#define RK3128_RST_TSP 92
|
||
|
+#define RK3128_RST_TSP_CLKIN0 93
|
||
|
+#define RK3128_RST_USBHOST0_EHCI 94
|
||
|
+#define RK3128_RST_5RES15 95
|
||
|
+
|
||
|
+#define RK3128_RST_HDMI_P 96
|
||
|
+#define RK3128_RST_VIO_ARBI_H 97
|
||
|
+#define RK3128_RST_VIO_A 98
|
||
|
+#define RK3128_RST_VIO_BUS_H 99
|
||
|
+#define RK3128_RST_LCDC0_A 100
|
||
|
+#define RK3128_RST_LCDC0_H 101
|
||
|
+#define RK3128_RST_LCDC0_D 102
|
||
|
+#define RK3128_RST_UTMI0 103
|
||
|
+#define RK3128_RST_UTMI1 104
|
||
|
+#define RK3128_RST_USBPOR 105
|
||
|
+#define RK3128_RST_IEP_A 106
|
||
|
+#define RK3128_RST_IEP_H 107
|
||
|
+#define RK3128_RST_RGA_A 108
|
||
|
+#define RK3128_RST_RGA_H 109
|
||
|
+#define RK3128_RST_CIF0 110
|
||
|
+#define RK3128_RST_PMU 111
|
||
|
+
|
||
|
+#define RK3128_RST_VCODEC_A 112
|
||
|
+#define RK3128_RST_VCODEC_H 113
|
||
|
+#define RK3128_RST_VIO1_A 114
|
||
|
+#define RK3128_RST_HEVC 115
|
||
|
+#define RK3128_RST_VCODEC_NIU_A 116
|
||
|
+#define RK3128_RST_PMU_NIU 117
|
||
|
+#define RK3128_RST_7RES6 118
|
||
|
+#define RK3128_RST_LCDC0_S 119
|
||
|
+#define RK3128_RST_GPU 120
|
||
|
+#define RK3128_RST_7RES9 121
|
||
|
+#define RK3128_RST_GPU_NIU_A 122
|
||
|
+#define RK3128_RST_EBC_A 123
|
||
|
+#define RK3128_RST_EBC_H 124
|
||
|
+#define RK3128_RST_7RES13 125
|
||
|
+#define RK3128_RST_7RES14 126
|
||
|
+#define RK3128_RST_7RES15 127
|
||
|
+
|
||
|
+#define RK3128_RST_CORE_DBG 128
|
||
|
+#define RK3128_RST_DBG_P 129
|
||
|
+#define RK3128_RST_TIMER0 130
|
||
|
+#define RK3128_RST_TIMER1 131
|
||
|
+#define RK3128_RST_TIMER2 132
|
||
|
+#define RK3128_RST_TIMER3 133
|
||
|
+#define RK3128_RST_TIMER4 134
|
||
|
+#define RK3128_RST_TIMER5 135
|
||
|
+#define RK3128_RST_VIO_H2P 136
|
||
|
+#define RK3128_RST_VIO_MIPI_DSI 137
|
||
|
+#define RK3128_RST_8RES10 138
|
||
|
+#define RK3128_RST_8RES11 139
|
||
|
+#define RK3128_RST_8RES12 140
|
||
|
+#define RK3128_RST_8RES13 141
|
||
|
+#define RK3128_RST_8RES14 142
|
||
|
+#define RK3128_RST_8RES15 143
|
||
|
+
|
||
|
+#endif /* _DT_BINDINGS_CLOCK_ROCKCHIP_RK3128_H */
|
||
|
diff --git a/include/dt-bindings/clock/rockchip,rk3188.h b/include/dt-bindings/clock/rockchip,rk3188.h
|
||
|
new file mode 100644
|
||
|
index 0000000..b8c57e1
|
||
|
--- /dev/null
|
||
|
+++ b/include/dt-bindings/clock/rockchip,rk3188.h
|
||
|
@@ -0,0 +1,13 @@
|
||
|
+#ifndef _DT_BINDINGS_CLOCK_ROCKCHIP_RK3188_H
|
||
|
+#define _DT_BINDINGS_CLOCK_ROCKCHIP_RK3188_H
|
||
|
+
|
||
|
+#include "rockchip.h"
|
||
|
+
|
||
|
+/* pll id */
|
||
|
+#define RK3188_APLL_ID 0
|
||
|
+#define RK3188_DPLL_ID 1
|
||
|
+#define RK3188_CPLL_ID 2
|
||
|
+#define RK3188_GPLL_ID 3
|
||
|
+#define RK3188_END_PLL_ID 4
|
||
|
+
|
||
|
+#endif /* _DT_BINDINGS_CLOCK_ROCKCHIP_RK3188_H */
|
||
|
diff --git a/include/dt-bindings/clock/rockchip,rk3228.h b/include/dt-bindings/clock/rockchip,rk3228.h
|
||
|
new file mode 100644
|
||
|
index 0000000..b86e445
|
||
|
--- /dev/null
|
||
|
+++ b/include/dt-bindings/clock/rockchip,rk3228.h
|
||
|
@@ -0,0 +1,167 @@
|
||
|
+#ifndef _DT_BINDINGS_CLOCK_ROCKCHIP_RK3228_H
|
||
|
+#define _DT_BINDINGS_CLOCK_ROCKCHIP_RK3228_H
|
||
|
+
|
||
|
+#include "rockchip.h"
|
||
|
+
|
||
|
+/* pll id */
|
||
|
+#define RK3228_APLL_ID 0
|
||
|
+#define RK3228_DPLL_ID 1
|
||
|
+#define RK3228_CPLL_ID 2
|
||
|
+#define RK3228_GPLL_ID 3
|
||
|
+#define RK3228_END_PLL_ID 4
|
||
|
+
|
||
|
+/* reset id */
|
||
|
+#define RK3228_RST_CORE0_PO 0
|
||
|
+#define RK3228_RST_CORE1_PO 1
|
||
|
+#define RK3228_RST_CORE2_PO 2
|
||
|
+#define RK3228_RST_CORE3_PO 3
|
||
|
+#define RK3228_RST_CORE0 4
|
||
|
+#define RK3228_RST_CORE1 5
|
||
|
+#define RK3228_RST_CORE2 6
|
||
|
+#define RK3228_RST_CORE3 7
|
||
|
+#define RK3228_RST_CORE0_DBG 8
|
||
|
+#define RK3228_RST_CORE1_DBG 9
|
||
|
+#define RK3228_RST_CORE2_DBG 10
|
||
|
+#define RK3228_RST_CORE3_DBG 11
|
||
|
+#define RK3228_RST_TOPDBG 12
|
||
|
+#define RK3228_RST_ACLK_CORE 13
|
||
|
+#define RK3228_RST_NOC_A 14
|
||
|
+#define RK3228_RST_L2C 15
|
||
|
+
|
||
|
+#define RK3228_RST_1RES0 16
|
||
|
+#define RK3228_RST_1RES1 17
|
||
|
+#define RK3228_RST_CPUSYS_H 18
|
||
|
+#define RK3228_RST_BUSSYS_H 19
|
||
|
+#define RK3228_RST_SPDIF 20
|
||
|
+#define RK3228_RST_INTMEM 21
|
||
|
+#define RK3228_RST_ROM 22
|
||
|
+#define RK3228_RST_OTG_ADP 23
|
||
|
+#define RK3228_RST_I2S0 24
|
||
|
+#define RK3228_RST_I2S1 25
|
||
|
+#define RK3228_RST_I2S2 26
|
||
|
+#define RK3228_RST_ACODEC_P 27
|
||
|
+#define RK3228_RST_DFIMON 28
|
||
|
+#define RK3228_RST_MSCH 29
|
||
|
+#define RK3228_RST_EFUSE_1024 30
|
||
|
+#define RK3228_RST_EFUSE_256 31
|
||
|
+
|
||
|
+#define RK3228_RST_GPIO0 32
|
||
|
+#define RK3228_RST_GPIO1 33
|
||
|
+#define RK3228_RST_GPIO2 34
|
||
|
+#define RK3228_RST_GPIO3 35
|
||
|
+#define RK3228_RST_PERIPH_NOC_A 36
|
||
|
+#define RK3228_RST_PERIPH_NOC_H 37
|
||
|
+#define RK3228_RST_PERIPH_NOC_P 38
|
||
|
+#define RK3228_RST_UART0 39
|
||
|
+#define RK3228_RST_UART1 40
|
||
|
+#define RK3228_RST_UART2 41
|
||
|
+#define RK3228_RST_PHYNOC 42
|
||
|
+#define RK3228_RST_I2C0 43
|
||
|
+#define RK3228_RST_I2C1 44
|
||
|
+#define RK3228_RST_I2C2 45
|
||
|
+#define RK3228_RST_I2C3 46
|
||
|
+#define RK3228_RST_2RES15 47
|
||
|
+
|
||
|
+#define RK3228_RST_PWM0 48
|
||
|
+#define RK3228_RST_A53_GIC 49
|
||
|
+#define RK3228_RST_3RES2 50
|
||
|
+#define RK3228_RST_DAP 51
|
||
|
+#define RK3228_RST_DAP_NOC 52
|
||
|
+#define RK3228_RST_CRYPTO 53
|
||
|
+#define RK3228_RST_SGRF 54
|
||
|
+#define RK3228_RST_GRF 55
|
||
|
+#define RK3228_RST_GMAC 56
|
||
|
+#define RK3228_RST_3RES9 57
|
||
|
+#define RK3228_RST_PERIPHSYS_A 58
|
||
|
+#define RK3228_RST_3RES11 59
|
||
|
+#define RK3228_RST_3RES12 60
|
||
|
+#define RK3228_RST_3RES13 61
|
||
|
+#define RK3228_RST_3RES14 62
|
||
|
+#define RK3228_RST_MACPHY 63
|
||
|
+
|
||
|
+#define RK3228_RST_4RES0 64
|
||
|
+#define RK3228_RST_4RES1 65
|
||
|
+#define RK3228_RST_4RES2 66
|
||
|
+#define RK3228_RST_4RES3 67
|
||
|
+#define RK3228_RST_NANDC 68
|
||
|
+#define RK3228_RST_USBOTG0 69
|
||
|
+#define RK3228_RST_OTGC0 70
|
||
|
+#define RK3228_RST_USBHOST0 71
|
||
|
+#define RK3228_RST_HOST_CTRL0 72
|
||
|
+#define RK3228_RST_USBHOST1 73
|
||
|
+#define RK3228_RST_HOST_CTRL1 74
|
||
|
+#define RK3228_RST_USBHOST2 75
|
||
|
+#define RK3228_RST_HOST_CTRL2 76
|
||
|
+#define RK3228_RST_USBPOR0 77
|
||
|
+#define RK3228_RST_USBPOR1 78
|
||
|
+#define RK3228_RST_DDRMSCH 79
|
||
|
+
|
||
|
+#define RK3228_RST_SMART_CARD 80
|
||
|
+#define RK3228_RST_SDMMC0 81
|
||
|
+#define RK3228_RST_SDIO 82
|
||
|
+#define RK3228_RST_EMMC 83
|
||
|
+#define RK3228_RST_SPI0 84
|
||
|
+#define RK3228_RST_TSP_H 85
|
||
|
+#define RK3228_RST_TSP 86
|
||
|
+#define RK3228_RST_TSADC 87
|
||
|
+#define RK3228_RST_DDRPHY 88
|
||
|
+#define RK3228_RST_DDRPHY_P 89
|
||
|
+#define RK3228_RST_DDRCTRL 90
|
||
|
+#define RK3228_RST_DDRCTRL_P 91
|
||
|
+#define RK3228_RST_HOST0_ECHI 92
|
||
|
+#define RK3228_RST_HOST1_ECHI 93
|
||
|
+#define RK3228_RST_HOST2_ECHI 94
|
||
|
+#define RK3228_RST_VOP 95
|
||
|
+
|
||
|
+#define RK3228_RST_HDMI_P 96
|
||
|
+#define RK3228_RST_VIO_ARBI_H 97
|
||
|
+#define RK3228_RST_IEP_NOC_A 98
|
||
|
+#define RK3228_RST_VIO_NOC_H 99
|
||
|
+#define RK3228_RST_VOP_A 100
|
||
|
+#define RK3228_RST_VOP_H 101
|
||
|
+#define RK3228_RST_VOP_D 102
|
||
|
+#define RK3228_RST_UTMI0 103
|
||
|
+#define RK3228_RST_UTMI1 104
|
||
|
+#define RK3228_RST_UTMI2 105
|
||
|
+#define RK3228_RST_UTMI3 106
|
||
|
+#define RK3228_RST_RGA 107
|
||
|
+#define RK3228_RST_RGA_NOC_A 108
|
||
|
+#define RK3228_RST_RGA_A 109
|
||
|
+#define RK3228_RST_RGA_H 110
|
||
|
+#define RK3228_RST_HDCP_A 111
|
||
|
+
|
||
|
+#define RK3228_RST_VPU_A 112
|
||
|
+#define RK3228_RST_VPU_H 113
|
||
|
+#define RK3228_RST_7RES2 114
|
||
|
+#define RK3228_RST_7RES3 115
|
||
|
+#define RK3228_RST_VPU_NOC_A 116
|
||
|
+#define RK3228_RST_VPU_NOC_H 117
|
||
|
+#define RK3228_RST_RKVDEC_A 118
|
||
|
+#define RK3228_RST_RKVDEC_NOC_A 119
|
||
|
+#define RK3228_RST_RKVDEC_H 120
|
||
|
+#define RK3228_RST_RKVDEC_NOC_H 121
|
||
|
+#define RK3228_RST_RKVDEC_CORE 122
|
||
|
+#define RK3228_RST_RKVDEC_CABAC 123
|
||
|
+#define RK3228_RST_IEP_A 124
|
||
|
+#define RK3228_RST_IEP_H 125
|
||
|
+#define RK3228_RST_GPU_A 126
|
||
|
+#define RK3228_RST_GPU_NOC_A 127
|
||
|
+
|
||
|
+#define RK3228_RST_CORE_DBG 128
|
||
|
+#define RK3228_RST_DBG_P 129
|
||
|
+#define RK3228_RST_TIMER0 130
|
||
|
+#define RK3228_RST_TIMER1 131
|
||
|
+#define RK3228_RST_TIMER2 132
|
||
|
+#define RK3228_RST_TIMER3 133
|
||
|
+#define RK3228_RST_TIMER4 134
|
||
|
+#define RK3228_RST_TIMER5 135
|
||
|
+#define RK3228_RST_VIO_H2P 136
|
||
|
+#define RK3228_RST_8RES9 137
|
||
|
+#define RK3228_RST_8RES10 138
|
||
|
+#define RK3228_RST_HDMIPHY 139
|
||
|
+#define RK3228_RST_VDAC 140
|
||
|
+#define RK3228_RST_TIMER_6CH 141
|
||
|
+#define RK3228_RST_8RES14 142
|
||
|
+#define RK3228_RST_8RES15 143
|
||
|
+
|
||
|
+#endif /* _DT_BINDINGS_CLOCK_ROCKCHIP_RK3228_H */
|
||
|
diff --git a/include/dt-bindings/clock/rockchip,rk3288.h b/include/dt-bindings/clock/rockchip,rk3288.h
|
||
|
new file mode 100644
|
||
|
index 0000000..1a2803c
|
||
|
--- /dev/null
|
||
|
+++ b/include/dt-bindings/clock/rockchip,rk3288.h
|
||
|
@@ -0,0 +1,220 @@
|
||
|
+#ifndef _DT_BINDINGS_CLOCK_ROCKCHIP_RK3288_H
|
||
|
+#define _DT_BINDINGS_CLOCK_ROCKCHIP_RK3288_H
|
||
|
+
|
||
|
+#include "rockchip.h"
|
||
|
+
|
||
|
+/* pll id */
|
||
|
+#define RK3288_APLL_ID 0
|
||
|
+#define RK3288_DPLL_ID 1
|
||
|
+#define RK3288_CPLL_ID 2
|
||
|
+#define RK3288_GPLL_ID 3
|
||
|
+#define RK3288_NPLL_ID 4
|
||
|
+#define RK3288_END_PLL_ID 5
|
||
|
+
|
||
|
+/* reset id */
|
||
|
+#define RK3288_SOFT_RST_CORE0 0
|
||
|
+#define RK3288_SOFT_RST_CORE1 1
|
||
|
+#define RK3288_SOFT_RST_CORE2 2
|
||
|
+#define RK3288_SOFT_RST_CORE3 3
|
||
|
+#define RK3288_SOFT_RST_CORE0_PO 4
|
||
|
+#define RK3288_SOFT_RST_CORE1_PO 5
|
||
|
+#define RK3288_SOFT_RST_CORE2_PO 6
|
||
|
+#define RK3288_SOFT_RST_CORE3_PO 7
|
||
|
+#define RK3288_SOFT_RST_PD_CORE_STR_SYS_A 8
|
||
|
+#define RK3288_SOFT_RST_PD_BUS_STR_SYS_A 9
|
||
|
+#define RK3288_SOFT_RST_L2C 10
|
||
|
+#define RK3288_SOFT_RST_TOPDBG 11
|
||
|
+#define RK3288_SOFT_RST_CORE0_DBG 12
|
||
|
+#define RK3288_SOFT_RST_CORE1_DBG 13
|
||
|
+#define RK3288_SOFT_RST_CORE2_DBG 14
|
||
|
+#define RK3288_SOFT_RST_CORE3_DBG 15
|
||
|
+
|
||
|
+#define RK3288_SOFT_RST_PD_BUS_AHB_ARBITOR 16
|
||
|
+#define RK3288_SOFT_RST_EFUSE_256BIT_P 17
|
||
|
+#define RK3288_SOFT_RST_DMA1 18
|
||
|
+#define RK3288_SOFT_RST_INTMEM 19
|
||
|
+#define RK3288_SOFT_RST_ROM 20
|
||
|
+#define RK3288_SOFT_RST_SPDIF_8CH 21
|
||
|
+#define RK3288_SOFT_RST_TIMER_P 22
|
||
|
+#define RK3288_SOFT_RST_I2S 23
|
||
|
+#define RK3288_SOFT_RST_SPDIF 24
|
||
|
+#define RK3288_SOFT_RST_TIMER0 25
|
||
|
+#define RK3288_SOFT_RST_TIMER1 26
|
||
|
+#define RK3288_SOFT_RST_TIMER2 27
|
||
|
+#define RK3288_SOFT_RST_TIMER3 28
|
||
|
+#define RK3288_SOFT_RST_TIMER4 29
|
||
|
+#define RK3288_SOFT_RST_TIMER5 30
|
||
|
+#define RK3288_SOFT_RST_EFUSE_P 31
|
||
|
+
|
||
|
+#define RK3288_SOFT_RST_GPIO0 32
|
||
|
+#define RK3288_SOFT_RST_GPIO1 33
|
||
|
+#define RK3288_SOFT_RST_GPIO2 34
|
||
|
+#define RK3288_SOFT_RST_GPIO3 35
|
||
|
+#define RK3288_SOFT_RST_GPIO4 36
|
||
|
+#define RK3288_SOFT_RST_GPIO5 37
|
||
|
+#define RK3288_SOFT_RST_GPIO6 38
|
||
|
+#define RK3288_SOFT_RST_GPIO7 39
|
||
|
+#define RK3288_SOFT_RST_GPIO8 40
|
||
|
+#define RK3288_SOFT_RST_2RES9 41
|
||
|
+#define RK3288_SOFT_RST_I2C0 42
|
||
|
+#define RK3288_SOFT_RST_I2C1 43
|
||
|
+#define RK3288_SOFT_RST_I2C2 44
|
||
|
+#define RK3288_SOFT_RST_I2C3 45
|
||
|
+#define RK3288_SOFT_RST_I2C4 46
|
||
|
+#define RK3288_SOFT_RST_I2C5 47
|
||
|
+
|
||
|
+#define RK3288_SOFT_RST_DW_PWM 48
|
||
|
+#define RK3288_SOFT_RST_MMC_PERI 49
|
||
|
+#define RK3288_SOFT_RST_PERIPH_MMU 50
|
||
|
+#define RK3288_SOFT_RST_DAP 51
|
||
|
+#define RK3288_SOFT_RST_DAP_SYS 52
|
||
|
+#define RK3288_SOFT_RST_TPIU_AT 53
|
||
|
+#define RK3288_SOFT_RST_PMU_P 54
|
||
|
+#define RK3288_SOFT_RST_GRF 55
|
||
|
+#define RK3288_SOFT_RST_PMU 56
|
||
|
+#define RK3288_SOFT_RST_PERIPHSYS_A 57
|
||
|
+#define RK3288_SOFT_RST_PERIPHSYS_H 58
|
||
|
+#define RK3288_SOFT_RST_PERIPHSYS_P 59
|
||
|
+#define RK3288_SOFT_RST_PERIPH_NIU 60
|
||
|
+#define RK3288_SOFT_RST_PD_PERI_AHB_ARBITOR 61
|
||
|
+#define RK3288_SOFT_RST_EMEM_PERI 62
|
||
|
+#define RK3288_SOFT_RST_USB_PERI 63
|
||
|
+
|
||
|
+#define RK3288_SOFT_RST_DMA2 64
|
||
|
+#define RK3288_SOFT_RST_4RES1 65
|
||
|
+#define RK3288_SOFT_RST_MAC 66
|
||
|
+#define RK3288_SOFT_RST_GPS 67
|
||
|
+#define RK3288_SOFT_RST_4RES4 68
|
||
|
+#define RK3288_SOFT_RST_RK_PWM 69
|
||
|
+#define RK3288_SOFT_RST_4RES6 70
|
||
|
+#define RK3288_SOFT_RST_CCP 71
|
||
|
+#define RK3288_SOFT_RST_USB_HOST0 72
|
||
|
+#define RK3288_SOFT_RST_EHCI1 73
|
||
|
+#define RK3288_SOFT_RST_EHCI1_AUX 74
|
||
|
+#define RK3288_SOFT_RST_EHCI1PHY 75
|
||
|
+#define RK3288_SOFT_RST_HSADC 76
|
||
|
+#define RK3288_SOFT_RST_NANDC0 77
|
||
|
+#define RK3288_SOFT_RST_NANDC1 78
|
||
|
+#define RK3288_SOFT_RST_4RES15 79
|
||
|
+
|
||
|
+#define RK3288_SOFT_RST_TZPC 80
|
||
|
+#define RK3288_SOFT_RST_5RES1 81
|
||
|
+#define RK3288_SOFT_RST_5RES2 82
|
||
|
+#define RK3288_SOFT_RST_SPI0 83
|
||
|
+#define RK3288_SOFT_RST_SPI1 84
|
||
|
+#define RK3288_SOFT_RST_SPI2 85
|
||
|
+#define RK3288_SOFT_RST_5RES6 86
|
||
|
+#define RK3288_SOFT_RST_SARADC 87
|
||
|
+#define RK3288_SOFT_RST_PD_ALIVE_NIU_P 88
|
||
|
+#define RK3288_SOFT_RST_PD_PMU_INTMEM_P 89
|
||
|
+#define RK3288_SOFT_RST_PD_PMU_NIU_P 90
|
||
|
+#define RK3288_SOFT_RST_SECURITY_GRF_P 91
|
||
|
+#define RK3288_SOFT_RST_5RES12 92
|
||
|
+#define RK3288_SOFT_RST_5RES13 93
|
||
|
+#define RK3288_SOFT_RST_5RES14 94
|
||
|
+#define RK3288_SOFT_RST_5RES15 95
|
||
|
+
|
||
|
+#define RK3288_SOFT_RST_VIO_ARBI_H 96
|
||
|
+#define RK3288_SOFT_RST_RGA_NIU_A 97
|
||
|
+#define RK3288_SOFT_RST_VIO0_NIU_A 98
|
||
|
+#define RK3288_SOFT_RST_VIO_NIU_H 99
|
||
|
+#define RK3288_SOFT_RST_LCDC0_A 100
|
||
|
+#define RK3288_SOFT_RST_LCDC0_H 101
|
||
|
+#define RK3288_SOFT_RST_LCDC0_D 102
|
||
|
+#define RK3288_SOFT_RST_VIO1_NIU_A 103
|
||
|
+#define RK3288_SOFT_RST_VIP 104
|
||
|
+#define RK3288_SOFT_RST_RGA_CORE 105
|
||
|
+#define RK3288_SOFT_RST_IEP_A 106
|
||
|
+#define RK3288_SOFT_RST_IEP_H 107
|
||
|
+#define RK3288_SOFT_RST_RGA_A 108
|
||
|
+#define RK3288_SOFT_RST_RGA_H 109
|
||
|
+#define RK3288_SOFT_RST_ISP 110
|
||
|
+#define RK3288_SOFT_RST_EDP 111
|
||
|
+
|
||
|
+#define RK3288_SOFT_RST_VCODEC_A 112
|
||
|
+#define RK3288_SOFT_RST_VCODEC_H 113
|
||
|
+#define RK3288_SOFT_RST_VIO_H2P_H 114
|
||
|
+#define RK3288_SOFT_RST_MIPIDSI0_P 115
|
||
|
+#define RK3288_SOFT_RST_MIPIDSI1_P 116
|
||
|
+#define RK3288_SOFT_RST_MIPICSI_P 117
|
||
|
+#define RK3288_SOFT_RST_LVDS_PHY_P 118
|
||
|
+#define RK3288_SOFT_RST_LVDS_CON 119
|
||
|
+#define RK3288_SOFT_RST_GPU 120
|
||
|
+#define RK3288_SOFT_RST_HDMI 121
|
||
|
+#define RK3288_SOFT_RST_7RES10 122
|
||
|
+#define RK3288_SOFT_RST_7RES11 123
|
||
|
+#define RK3288_SOFT_RST_CORE_PVTM 124
|
||
|
+#define RK3288_SOFT_RST_GPU_PVTM 125
|
||
|
+#define RK3288_SOFT_RST_7RES14 126
|
||
|
+#define RK3288_SOFT_RST_7RES15 127
|
||
|
+
|
||
|
+#define RK3288_SOFT_RST_MMC0 128
|
||
|
+#define RK3288_SOFT_RST_SDIO0 129
|
||
|
+#define RK3288_SOFT_RST_SDIO1 130
|
||
|
+#define RK3288_SOFT_RST_EMMC 131
|
||
|
+#define RK3288_SOFT_RST_USBOTG_H 132
|
||
|
+#define RK3288_SOFT_RST_USBOTGPHY 133
|
||
|
+#define RK3288_SOFT_RST_USBOTGC 134
|
||
|
+#define RK3288_SOFT_RST_USBHOST0_H 135
|
||
|
+#define RK3288_SOFT_RST_USBHOST0PHY 136
|
||
|
+#define RK3288_SOFT_RST_USBHOST0C 137
|
||
|
+#define RK3288_SOFT_RST_USBHOST1_H 138
|
||
|
+#define RK3288_SOFT_RST_USBHOST1PHY 139
|
||
|
+#define RK3288_SOFT_RST_USBHOST1C 140
|
||
|
+#define RK3288_SOFT_RST_USB_ADP 141
|
||
|
+#define RK3288_SOFT_RST_ACC_EFUSE 142
|
||
|
+#define RK3288_SOFT_RST_8RES15 143
|
||
|
+
|
||
|
+#define RK3288_SOFT_RST_CORESIGHT 144
|
||
|
+#define RK3288_SOFT_RST_PD_CORE_AHB_NOC 145
|
||
|
+#define RK3288_SOFT_RST_PD_CORE_APB_NOC 146
|
||
|
+#define RK3288_SOFT_RST_PD_CORE_MP_AXI 147
|
||
|
+#define RK3288_SOFT_RST_GIC 148
|
||
|
+#define RK3288_SOFT_RST_LCDCPWM0 149
|
||
|
+#define RK3288_SOFT_RST_LCDCPWM1 150
|
||
|
+#define RK3288_SOFT_RST_VIO0_H2P_BRG 151
|
||
|
+#define RK3288_SOFT_RST_VIO1_H2P_BRG 152
|
||
|
+#define RK3288_SOFT_RST_RGA_H2P_BRG 153
|
||
|
+#define RK3288_SOFT_RST_HEVC 154
|
||
|
+#define RK3288_SOFT_RST_9RES11 155
|
||
|
+#define RK3288_SOFT_RST_9RES12 156
|
||
|
+#define RK3288_SOFT_RST_9RES13 157
|
||
|
+#define RK3288_SOFT_RST_9RES14 158
|
||
|
+#define RK3288_SOFT_RST_TSADC_P 159
|
||
|
+
|
||
|
+#define RK3288_SOFT_RST_DDRPHY0 160
|
||
|
+#define RK3288_SOFT_RST_DDRPHY0_P 161
|
||
|
+#define RK3288_SOFT_RST_DDRCTRL0 162
|
||
|
+#define RK3288_SOFT_RST_DDRCTRL0_P 163
|
||
|
+#define RK3288_SOFT_RST_DDRPHY0_CTL 164
|
||
|
+#define RK3288_SOFT_RST_DDRPHY1 165
|
||
|
+#define RK3288_SOFT_RST_DDRPHY1_P 166
|
||
|
+#define RK3288_SOFT_RST_DDRCTRL1 167
|
||
|
+#define RK3288_SOFT_RST_DDRCTRL1_P 168
|
||
|
+#define RK3288_SOFT_RST_DDRPHY1_CTL 169
|
||
|
+#define RK3288_SOFT_RST_DDRMSCH0 170
|
||
|
+#define RK3288_SOFT_RST_DDRMSCH1 171
|
||
|
+#define RK3288_SOFT_RST_10RES12 172
|
||
|
+#define RK3288_SOFT_RST_10RES13 173
|
||
|
+#define RK3288_SOFT_RST_CRYPTO 174
|
||
|
+#define RK3288_SOFT_RST_C2C_HOST 175
|
||
|
+
|
||
|
+#define RK3288_SOFT_RST_LCDC1_A 176
|
||
|
+#define RK3288_SOFT_RST_LCDC1_H 177
|
||
|
+#define RK3288_SOFT_RST_LCDC1_D 178
|
||
|
+#define RK3288_SOFT_RST_UART0 179
|
||
|
+#define RK3288_SOFT_RST_UART1 180
|
||
|
+#define RK3288_SOFT_RST_UART2 181
|
||
|
+#define RK3288_SOFT_RST_UART3 182
|
||
|
+#define RK3288_SOFT_RST_UART4 183
|
||
|
+#define RK3288_SOFT_RST_11RES8 184
|
||
|
+#define RK3288_SOFT_RST_11RES9 185
|
||
|
+#define RK3288_SOFT_RST_SIMC 186
|
||
|
+#define RK3288_SOFT_RST_PS2C 187
|
||
|
+#define RK3288_SOFT_RST_TSP 188
|
||
|
+#define RK3288_SOFT_RST_TSP_CLKIN0 189
|
||
|
+#define RK3288_SOFT_RST_TSP_CLKIN1 190
|
||
|
+#define RK3288_SOFT_RST_TSP_27M 191
|
||
|
+
|
||
|
+
|
||
|
+#endif /* _DT_BINDINGS_CLOCK_ROCKCHIP_RK3288_H */
|
||
|
diff --git a/include/dt-bindings/clock/rockchip,rk3368.h b/include/dt-bindings/clock/rockchip,rk3368.h
|
||
|
new file mode 100644
|
||
|
index 0000000..9ebf185
|
||
|
--- /dev/null
|
||
|
+++ b/include/dt-bindings/clock/rockchip,rk3368.h
|
||
|
@@ -0,0 +1,262 @@
|
||
|
+#ifndef _DT_BINDINGS_CLOCK_ROCKCHIP_RK3368_H
|
||
|
+#define _DT_BINDINGS_CLOCK_ROCKCHIP_RK3368_H
|
||
|
+
|
||
|
+#include "rockchip.h"
|
||
|
+
|
||
|
+/* reset id */
|
||
|
+#define RK3368_SRST_CORE_B_0_SC 0
|
||
|
+#define RK3368_SRST_CORE_B_1 1
|
||
|
+#define RK3368_SRST_CORE_B_2 2
|
||
|
+#define RK3368_SRST_CORE_B_3 3
|
||
|
+#define RK3368_SRST_CORE_B_PO0_SC 4
|
||
|
+#define RK3368_SRST_CORE_B_PO1 5
|
||
|
+#define RK3368_SRST_CORE_B_PO2 6
|
||
|
+#define RK3368_SRST_CORE_B_PO3 7
|
||
|
+#define RK3368_SRST_L2_B_SC 8
|
||
|
+#define RK3368_SRST_ADB_B_SC 9
|
||
|
+#define RK3368_SRST_PD_CORE_B_NIU 10
|
||
|
+#define RK3368_SRST_STRC_SYS_A_SC 11
|
||
|
+#define RK3368_SRST_0RES12 12
|
||
|
+#define RK3368_SRST_0RES13 13
|
||
|
+#define RK3368_SRST_SOCDBG_B 14
|
||
|
+#define RK3368_SRST_CORE_B_DBG 15
|
||
|
+
|
||
|
+#define RK3368_SRST_1RES0 16
|
||
|
+#define RK3368_SRST_1RES1 17
|
||
|
+#define RK3368_SRST_DMA1 18
|
||
|
+#define RK3368_SRST_INTMEM 19
|
||
|
+#define RK3368_SRST_ROM 20
|
||
|
+#define RK3368_SRST_SPDIF_8CH 21
|
||
|
+#define RK3368_SRST_1RES6 22
|
||
|
+#define RK3368_SRST_I2S 23
|
||
|
+#define RK3368_SRST_MAILBOX 24
|
||
|
+#define RK3368_SRST_I2S_2CH 25
|
||
|
+#define RK3368_SRST_EFUSE_256_P 26
|
||
|
+#define RK3368_SRST_1RES11 27
|
||
|
+#define RK3368_SRST_MCU_SYS 28
|
||
|
+#define RK3368_SRST_MCU_PO 29
|
||
|
+#define RK3368_SRST_MCU_NOC_H 30
|
||
|
+#define RK3368_SRST_EFUSE_P 31
|
||
|
+
|
||
|
+#define RK3368_SRST_GPIO0 32
|
||
|
+#define RK3368_SRST_GPIO1 33
|
||
|
+#define RK3368_SRST_GPIO2 34
|
||
|
+#define RK3368_SRST_GPIO3 35
|
||
|
+#define RK3368_SRST_GPIO4 36
|
||
|
+#define RK3368_SRST_2RES5 37
|
||
|
+#define RK3368_SRST_2RES6 38
|
||
|
+#define RK3368_SRST_2RES7 39
|
||
|
+#define RK3368_SRST_2RES8 40
|
||
|
+#define RK3368_SRST_PMUGRF_P 41
|
||
|
+#define RK3368_SRST_I2C0 42
|
||
|
+#define RK3368_SRST_I2C1 43
|
||
|
+#define RK3368_SRST_I2C2 44
|
||
|
+#define RK3368_SRST_I2C3 45
|
||
|
+#define RK3368_SRST_I2C4 46
|
||
|
+#define RK3368_SRST_I2C5 47
|
||
|
+
|
||
|
+#define RK3368_SRST_DW_PWM 48
|
||
|
+#define RK3368_SRST_MMC_PERI 49
|
||
|
+#define RK3368_SRST_PERIPH_MMU 50
|
||
|
+#define RK3368_SRST_3RES3 51
|
||
|
+#define RK3368_SRST_3RES4 52
|
||
|
+#define RK3368_SRST_3RES5 53
|
||
|
+#define RK3368_SRST_3RES6 54
|
||
|
+#define RK3368_SRST_GRF 55
|
||
|
+#define RK3368_SRST_PMU 56
|
||
|
+#define RK3368_SRST_PERIPH_SYS_A 57
|
||
|
+#define RK3368_SRST_PERIPH_SYS_H 58
|
||
|
+#define RK3368_SRST_PERIPH_SYS_P 59
|
||
|
+#define RK3368_SRST_PERIPH_NIU 60
|
||
|
+#define RK3368_SRST_PD_PERI_AHB_ARBITOR 61
|
||
|
+#define RK3368_SRST_EMEM_PERI 62
|
||
|
+#define RK3368_SRST_USB_PERI 63
|
||
|
+
|
||
|
+#define RK3368_SRST_DMA2 64
|
||
|
+#define RK3368_SRST_4RES1 65
|
||
|
+#define RK3368_SRST_MAC 66
|
||
|
+#define RK3368_SRST_GPS 67
|
||
|
+#define RK3368_SRST_4RES4 68
|
||
|
+#define RK3368_SRST_RK_PWM 69
|
||
|
+#define RK3368_SRST_4RES6 70
|
||
|
+#define RK3368_SRST_4RES7 71
|
||
|
+#define RK3368_SRST_HOST0_H 72
|
||
|
+#define RK3368_SRST_EHCI1 73
|
||
|
+#define RK3368_SRST_EHCI1_AUX 74
|
||
|
+#define RK3368_SRST_EHCI1PHY 75
|
||
|
+#define RK3368_SRST_HSADC_H 76
|
||
|
+#define RK3368_SRST_NANDC0 77
|
||
|
+#define RK3368_SRST_4RES14 78
|
||
|
+#define RK3368_SRST_SFC 79
|
||
|
+
|
||
|
+#define RK3368_SRST_5RES0 80
|
||
|
+#define RK3368_SRST_5RES1 81
|
||
|
+#define RK3368_SRST_5RES2 82
|
||
|
+#define RK3368_SRST_SPI0 83
|
||
|
+#define RK3368_SRST_SPI1 84
|
||
|
+#define RK3368_SRST_SPI2 85
|
||
|
+#define RK3368_SRST_5RES6 86
|
||
|
+#define RK3368_SRST_SARADC 87
|
||
|
+#define RK3368_SRST_PD_ALIVE_NIU_P 88
|
||
|
+#define RK3368_SRST_PD_PMU_INTMEM_P 89
|
||
|
+#define RK3368_SRST_PD_PMU_NIU_P 90
|
||
|
+#define RK3368_SRST_SGRF_P 91
|
||
|
+#define RK3368_SRST_5RES12 92
|
||
|
+#define RK3368_SRST_5RES13 93
|
||
|
+#define RK3368_SRST_5RES14 94
|
||
|
+#define RK3368_SRST_5RES15 95
|
||
|
+
|
||
|
+#define RK3368_SRST_VIO_ARBI_H 96
|
||
|
+#define RK3368_SRST_RGA_NIU_A 97
|
||
|
+#define RK3368_SRST_VIO0_NIU_A 98
|
||
|
+#define RK3368_SRST_VIO0_BUS_H 99
|
||
|
+#define RK3368_SRST_LCDC0_A 100
|
||
|
+#define RK3368_SRST_LCDC0_H 101
|
||
|
+#define RK3368_SRST_LCDC0_D 102
|
||
|
+#define RK3368_SRST_6RES7 103
|
||
|
+#define RK3368_SRST_VIP 104
|
||
|
+#define RK3368_SRST_RGA_CORE 105
|
||
|
+#define RK3368_SRST_IEP_A 106
|
||
|
+#define RK3368_SRST_IEP_H 107
|
||
|
+#define RK3368_SRST_RGA_A 108
|
||
|
+#define RK3368_SRST_RGA_H 109
|
||
|
+#define RK3368_SRST_ISP 110
|
||
|
+#define RK3368_SRST_EDP_24M 111
|
||
|
+
|
||
|
+#define RK3368_SRST_VIDEO_A 112
|
||
|
+#define RK3368_SRST_VIDEO_H 113
|
||
|
+#define RK3368_SRST_MIPIDPHYTX_P 114
|
||
|
+#define RK3368_SRST_MIPIDSI0_P 115
|
||
|
+#define RK3368_SRST_MIPIDPHYRX_P 116
|
||
|
+#define RK3368_SRST_MIPICSI_P 117
|
||
|
+#define RK3368_SRST_7RES6 118
|
||
|
+#define RK3368_SRST_7RES7 119
|
||
|
+#define RK3368_SRST_GPU_CORE 120
|
||
|
+#define RK3368_SRST_HDMI 121
|
||
|
+#define RK3368_SRST_EDP_P 122
|
||
|
+#define RK3368_SRST_PMU_PVTM 123
|
||
|
+#define RK3368_SRST_CORE_PVTM 124
|
||
|
+#define RK3368_SRST_GPU_PVTM 125
|
||
|
+#define RK3368_SRST_GPU_SYS_A 126
|
||
|
+#define RK3368_SRST_GPU_MEM_NIU_A 127
|
||
|
+
|
||
|
+#define RK3368_SRST_MMC0 128
|
||
|
+#define RK3368_SRST_SDIO0 129
|
||
|
+#define RK3368_SRST_8RES2 130
|
||
|
+#define RK3368_SRST_EMMC 131
|
||
|
+#define RK3368_SRST_USBOTG0_H 132
|
||
|
+#define RK3368_SRST_USBOTGPHY0 133
|
||
|
+#define RK3368_SRST_USBOTGC0 134
|
||
|
+#define RK3368_SRST_USBHOSTC0_H 135
|
||
|
+#define RK3368_SRST_USBOTGPHY1 136
|
||
|
+#define RK3368_SRST_USBHOSTC0 137
|
||
|
+#define RK3368_SRST_USBPHY0_UTMI 138
|
||
|
+#define RK3368_SRST_USBPHY1_UTMI 139
|
||
|
+#define RK3368_SRST_8RES12 140
|
||
|
+#define RK3368_SRST_USB_ADP 141
|
||
|
+#define RK3368_SRST_8RES14 142
|
||
|
+#define RK3368_SRST_8RES15 143
|
||
|
+
|
||
|
+#define RK3368_SRST_DBG 144
|
||
|
+#define RK3368_SRST_PD_CORE_AHB_NOC 145
|
||
|
+#define RK3368_SRST_PD_CORE_APB_NOC 146
|
||
|
+#define RK3368_SRST_9RES3 147
|
||
|
+#define RK3368_SRST_GIC 148
|
||
|
+#define RK3368_SRST_LCDCPWM0 149
|
||
|
+#define RK3368_SRST_9RES6 150
|
||
|
+#define RK3368_SRST_9RES7 151
|
||
|
+#define RK3368_SRST_9RES8 152
|
||
|
+#define RK3368_SRST_RGA_H2P_BRG 153
|
||
|
+#define RK3368_SRST_VIDEO 154
|
||
|
+#define RK3368_SRST_9RES11 155
|
||
|
+#define RK3368_SRST_9RES12 156
|
||
|
+#define RK3368_SRST_GPU_CFG_NIU_A 157
|
||
|
+#define RK3368_SRST_9RES14 158
|
||
|
+#define RK3368_SRST_TSADC_P 159
|
||
|
+
|
||
|
+#define RK3368_SRST_DDRPHY0 160
|
||
|
+#define RK3368_SRST_DDRPHY0_P 161
|
||
|
+#define RK3368_SRST_DDRCTRL0 162
|
||
|
+#define RK3368_SRST_DDRCTRL0_P 163
|
||
|
+#define RK3368_SRST_10RES4 164
|
||
|
+#define RK3368_SRST_VIDEO_NIU_A 165
|
||
|
+#define RK3368_SRST_10RES6 166
|
||
|
+#define RK3368_SRST_VIDEO_NIU_H 167
|
||
|
+#define RK3368_SRST_10RES8 168
|
||
|
+#define RK3368_SRST_10RES9 169
|
||
|
+#define RK3368_SRST_DDRMSCH0 170
|
||
|
+#define RK3368_SRST_10RES11 171
|
||
|
+#define RK3368_SRST_10RES12 172
|
||
|
+#define RK3368_SRST_SYS_BUS 173
|
||
|
+#define RK3368_SRST_CRYPTO 174
|
||
|
+#define RK3368_SRST_10RES15 175
|
||
|
+
|
||
|
+#define RK3368_SRST_11RES0 176
|
||
|
+#define RK3368_SRST_11RES1 177
|
||
|
+#define RK3368_SRST_11RES2 178
|
||
|
+#define RK3368_SRST_UART0 179
|
||
|
+#define RK3368_SRST_UART1 180
|
||
|
+#define RK3368_SRST_UART2 181
|
||
|
+#define RK3368_SRST_UART3 182
|
||
|
+#define RK3368_SRST_UART4 183
|
||
|
+#define RK3368_SRST_11RES8 184
|
||
|
+#define RK3368_SRST_11RES9 185
|
||
|
+#define RK3368_SRST_SIMC_P 186
|
||
|
+#define RK3368_SRST_11RES11 187
|
||
|
+#define RK3368_SRST_TSP_H 188
|
||
|
+#define RK3368_SRST_TSP_CLKIN0 189
|
||
|
+#define RK3368_SRST_11RES14 190
|
||
|
+#define RK3368_SRST_11RES15 191
|
||
|
+
|
||
|
+#define RK3368_SRST_CORE_L_0_SC 192
|
||
|
+#define RK3368_SRST_CORE_L_1 193
|
||
|
+#define RK3368_SRST_CORE_L_2 194
|
||
|
+#define RK3368_SRST_CORE_L_3 195
|
||
|
+#define RK3368_SRST_CORE_L_PO0_SC 196
|
||
|
+#define RK3368_SRST_CORE_L_PO1 197
|
||
|
+#define RK3368_SRST_CORE_L_PO2 198
|
||
|
+#define RK3368_SRST_CORE_L_PO3 199
|
||
|
+#define RK3368_SRST_L2_L_SC 200
|
||
|
+#define RK3368_SRST_ADB_L_SC 201
|
||
|
+#define RK3368_SRST_PD_CORE_L_NIU_A_SC 202
|
||
|
+#define RK3368_SRST_CCI400_SYS_SC 203
|
||
|
+#define RK3368_SRST_CCI400_DDR_SC 204
|
||
|
+#define RK3368_SRST_CCI400_SC 205
|
||
|
+#define RK3368_SRST_SOCDBG_L 206
|
||
|
+#define RK3368_SRST_CORE_L_DBG 207
|
||
|
+
|
||
|
+#define RK3368_SRST_CORE_B_0 208
|
||
|
+#define RK3368_SRST_CORE_B_PO0 209
|
||
|
+#define RK3368_SRST_L2_B 210
|
||
|
+#define RK3368_SRST_ADB_B 211
|
||
|
+#define RK3368_SRST_PD_CORE_B_NIU_A 212
|
||
|
+#define RK3368_SRST_STRC_SYS_A 213
|
||
|
+#define RK3368_SRST_CORE_L_0 214
|
||
|
+#define RK3368_SRST_CORE_L_PO0 215
|
||
|
+#define RK3368_SRST_L2_L 216
|
||
|
+#define RK3368_SRST_ADB_L 217
|
||
|
+#define RK3368_SRST_PD_CORE_L_NIU_A 218
|
||
|
+#define RK3368_SRST_CCI400_SYS 219
|
||
|
+#define RK3368_SRST_CCI400_DDR 220
|
||
|
+#define RK3368_SRST_CCI400 221
|
||
|
+#define RK3368_SRST_TRACE 222
|
||
|
+#define RK3368_SRST_13RES15 223
|
||
|
+
|
||
|
+#define RK3368_SRST_TIMER00 224
|
||
|
+#define RK3368_SRST_TIMER01 225
|
||
|
+#define RK3368_SRST_TIMER02 226
|
||
|
+#define RK3368_SRST_TIMER03 227
|
||
|
+#define RK3368_SRST_TIMER04 228
|
||
|
+#define RK3368_SRST_TIMER05 229
|
||
|
+#define RK3368_SRST_TIMER10 230
|
||
|
+#define RK3368_SRST_TIMER11 231
|
||
|
+#define RK3368_SRST_TIMER12 232
|
||
|
+#define RK3368_SRST_TIMER13 233
|
||
|
+#define RK3368_SRST_TIMER14 234
|
||
|
+#define RK3368_SRST_TIMER15 235
|
||
|
+#define RK3368_SRST_TIMER0_P 236
|
||
|
+#define RK3368_SRST_TIMER1_P 237
|
||
|
+#define RK3368_SRST_14RES14 238
|
||
|
+#define RK3368_SRST_14RES15 239
|
||
|
+
|
||
|
+#endif /* _DT_BINDINGS_CLOCK_ROCKCHIP_RK3368_H */
|
||
|
diff --git a/include/dt-bindings/clock/rockchip.h b/include/dt-bindings/clock/rockchip.h
|
||
|
new file mode 100644
|
||
|
index 0000000..a7c8c5c
|
||
|
--- /dev/null
|
||
|
+++ b/include/dt-bindings/clock/rockchip.h
|
||
|
@@ -0,0 +1,100 @@
|
||
|
+#ifndef _DT_BINDINGS_CLOCK_ROCKCHIP_H
|
||
|
+#define _DT_BINDINGS_CLOCK_ROCKCHIP_H
|
||
|
+
|
||
|
+#ifndef BIT
|
||
|
+#define BIT(nr) (1 << (nr))
|
||
|
+#endif
|
||
|
+
|
||
|
+#define CLK_DIVIDER_PLUS_ONE (0)
|
||
|
+#define CLK_DIVIDER_ONE_BASED BIT(0)
|
||
|
+#define CLK_DIVIDER_POWER_OF_TWO BIT(1)
|
||
|
+#define CLK_DIVIDER_ALLOW_ZERO BIT(2)
|
||
|
+#define CLK_DIVIDER_HIWORD_MASK BIT(3)
|
||
|
+
|
||
|
+/* Rockchip special defined */
|
||
|
+//#define CLK_DIVIDER_FIXED BIT(6)
|
||
|
+#define CLK_DIVIDER_USER_DEFINE BIT(7)
|
||
|
+
|
||
|
+/*
|
||
|
+ * flags used across common struct clk. these flags should only affect the
|
||
|
+ * top-level framework. custom flags for dealing with hardware specifics
|
||
|
+ * belong in struct clk_foo
|
||
|
+ */
|
||
|
+#define CLK_SET_RATE_GATE BIT(0) /* must be gated across rate change */
|
||
|
+#define CLK_SET_PARENT_GATE BIT(1) /* must be gated across re-parent */
|
||
|
+#define CLK_SET_RATE_PARENT BIT(2) /* propagate rate change up one level */
|
||
|
+#define CLK_IGNORE_UNUSED BIT(3) /* do not gate even if unused */
|
||
|
+#define CLK_IS_ROOT BIT(4) /* root clk, has no parent */
|
||
|
+#define CLK_IS_BASIC BIT(5) /* Basic clk, can't do a to_clk_foo() */
|
||
|
+#define CLK_GET_RATE_NOCACHE BIT(6) /* do not use the cached clk rate */
|
||
|
+#define CLK_SET_RATE_NO_REPARENT BIT(7) /* don't re-parent on rate change */
|
||
|
+#define CLK_SET_RATE_PARENT_IN_ORDER BIT(8) /* consider the order of re-parent
|
||
|
+ and set_div on rate change */
|
||
|
+
|
||
|
+
|
||
|
+
|
||
|
+/* Rockchip pll flags */
|
||
|
+#define CLK_PLL_3188 BIT(0)
|
||
|
+#define CLK_PLL_3188_APLL BIT(1)
|
||
|
+#define CLK_PLL_3188PLUS BIT(2)
|
||
|
+#define CLK_PLL_3188PLUS_APLL BIT(3)
|
||
|
+#define CLK_PLL_3288_APLL BIT(4)
|
||
|
+#define CLK_PLL_3188PLUS_AUTO BIT(5)
|
||
|
+#define CLK_PLL_3036_APLL BIT(6)
|
||
|
+#define CLK_PLL_3036PLUS_AUTO BIT(7)
|
||
|
+#define CLK_PLL_312XPLUS BIT(8)
|
||
|
+#define CLK_PLL_3368_APLLB BIT(9)
|
||
|
+#define CLK_PLL_3368_APLLL BIT(10)
|
||
|
+#define CLK_PLL_3368_LOW_JITTER BIT(11)
|
||
|
+
|
||
|
+
|
||
|
+/* rate_ops index */
|
||
|
+#define CLKOPS_RATE_MUX_DIV 1
|
||
|
+#define CLKOPS_RATE_EVENDIV 2
|
||
|
+#define CLKOPS_RATE_MUX_EVENDIV 3
|
||
|
+#define CLKOPS_RATE_I2S_FRAC 4
|
||
|
+#define CLKOPS_RATE_FRAC 5
|
||
|
+#define CLKOPS_RATE_I2S 6
|
||
|
+#define CLKOPS_RATE_CIFOUT 7
|
||
|
+#define CLKOPS_RATE_UART 8
|
||
|
+#define CLKOPS_RATE_HSADC 9
|
||
|
+#define CLKOPS_RATE_MAC_REF 10
|
||
|
+#define CLKOPS_RATE_CORE 11
|
||
|
+#define CLKOPS_RATE_CORE_CHILD 12
|
||
|
+#define CLKOPS_RATE_DDR 13
|
||
|
+#define CLKOPS_RATE_RK3288_I2S 14
|
||
|
+#define CLKOPS_RATE_RK3288_USB480M 15
|
||
|
+#define CLKOPS_RATE_RK3288_DCLK_LCDC0 16
|
||
|
+#define CLKOPS_RATE_RK3288_DCLK_LCDC1 17
|
||
|
+#define CLKOPS_RATE_DDR_DIV2 18
|
||
|
+#define CLKOPS_RATE_DDR_DIV4 19
|
||
|
+#define CLKOPS_RATE_RK3368_MUX_DIV_NPLL 20
|
||
|
+#define CLKOPS_RATE_RK3368_DCLK_LCDC 21
|
||
|
+#define CLKOPS_RATE_RK3368_DDR 22
|
||
|
+
|
||
|
+#define CLKOPS_TABLE_END (~0)
|
||
|
+
|
||
|
+/* pd id */
|
||
|
+#define CLK_PD_BCPU 0
|
||
|
+#define CLK_PD_BDSP 1
|
||
|
+#define CLK_PD_BUS 2
|
||
|
+#define CLK_PD_CPU_0 3
|
||
|
+#define CLK_PD_CPU_1 4
|
||
|
+#define CLK_PD_CPU_2 5
|
||
|
+#define CLK_PD_CPU_3 6
|
||
|
+#define CLK_PD_CS 7
|
||
|
+#define CLK_PD_GPU 8
|
||
|
+#define CLK_PD_HEVC 9
|
||
|
+#define CLK_PD_PERI 10
|
||
|
+#define CLK_PD_SCU 11
|
||
|
+#define CLK_PD_VIDEO 12
|
||
|
+#define CLK_PD_VIO 13
|
||
|
+#define CLK_PD_GPU_0 14
|
||
|
+#define CLK_PD_GPU_1 15
|
||
|
+
|
||
|
+#define CLK_PD_VIRT 255
|
||
|
+
|
||
|
+/* reset flag */
|
||
|
+#define ROCKCHIP_RESET_HIWORD_MASK BIT(0)
|
||
|
+
|
||
|
+#endif /* _DT_BINDINGS_CLOCK_ROCKCHIP_H */
|
||
|
diff --git a/include/linux/rockchip-iovmm.h b/include/linux/rockchip-iovmm.h
|
||
|
new file mode 100644
|
||
|
index 0000000..73e2ff1
|
||
|
--- /dev/null
|
||
|
+++ b/include/linux/rockchip-iovmm.h
|
||
|
@@ -0,0 +1,156 @@
|
||
|
+/*
|
||
|
+ * 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.
|
||
|
+ */
|
||
|
+
|
||
|
+#ifndef __ASM_PLAT_IOVMM_H
|
||
|
+#define __ASM_PLAT_IOVMM_H
|
||
|
+
|
||
|
+#include <linux/list.h>
|
||
|
+#include <linux/atomic.h>
|
||
|
+#include <linux/spinlock.h>
|
||
|
+
|
||
|
+#define IEP_IOMMU_COMPATIBLE_NAME "rockchip,iep_mmu"
|
||
|
+#define VIP_IOMMU_COMPATIBLE_NAME "rockchip,vip_mmu"
|
||
|
+#define ISP_IOMMU_COMPATIBLE_NAME "rockchip,isp_mmu"
|
||
|
+#define ISP0_IOMMU_COMPATIBLE_NAME "rockchip,isp0_mmu"
|
||
|
+#define ISP1_IOMMU_COMPATIBLE_NAME "rockchip,isp1_mmu"
|
||
|
+#define VOPB_IOMMU_COMPATIBLE_NAME "rockchip,vopb_mmu"
|
||
|
+#define VOPL_IOMMU_COMPATIBLE_NAME "rockchip,vopl_mmu"
|
||
|
+#define VOP_IOMMU_COMPATIBLE_NAME "rockchip,vop_mmu"
|
||
|
+#define HEVC_IOMMU_COMPATIBLE_NAME "rockchip,hevc_mmu"
|
||
|
+#define VPU_IOMMU_COMPATIBLE_NAME "rockchip,vpu_mmu"
|
||
|
+#define VDEC_IOMMU_COMPATIBLE_NAME "rockchip,vdec_mmu"
|
||
|
+
|
||
|
+enum rk_iommu_inttype {
|
||
|
+ IOMMU_PAGEFAULT,
|
||
|
+ IOMMU_BUSERROR,
|
||
|
+ IOMMU_FAULT_UNKNOWN,
|
||
|
+ IOMMU_FAULTS_NUM
|
||
|
+};
|
||
|
+
|
||
|
+struct iommu_drvdata;
|
||
|
+
|
||
|
+/*
|
||
|
+ * @itype: type of fault.
|
||
|
+ * @pgtable_base: the physical address of page table base. This is 0 if @itype
|
||
|
+ * is IOMMU_BUSERROR.
|
||
|
+ * @fault_addr: the device (virtual) address that the System MMU tried to
|
||
|
+ * translated. This is 0 if @itype is IOMMU_BUSERROR.
|
||
|
+ */
|
||
|
+typedef int (*rockchip_iommu_fault_handler_t)(struct device *dev,
|
||
|
+ enum rk_iommu_inttype itype,
|
||
|
+ unsigned long pgtable_base,
|
||
|
+ unsigned long fault_addr,
|
||
|
+ unsigned int statu
|
||
|
+ );
|
||
|
+
|
||
|
+
|
||
|
+struct scatterlist;
|
||
|
+struct device;
|
||
|
+
|
||
|
+#ifdef CONFIG_RK_IOVMM
|
||
|
+
|
||
|
+int rockchip_iovmm_activate(struct device *dev);
|
||
|
+void rockchip_iovmm_deactivate(struct device *dev);
|
||
|
+
|
||
|
+/* rockchip_iovmm_map() - Maps a list of physical memory chunks
|
||
|
+ * @dev: the owner of the IO address space where the mapping is created
|
||
|
+ * @sg: list of physical memory chunks to map
|
||
|
+ * @offset: length in bytes where the mapping starts
|
||
|
+ * @size: how much memory to map in bytes. @offset + @size must not exceed
|
||
|
+ * total size of @sg
|
||
|
+ *
|
||
|
+ * This function returns mapped IO address in the address space of @dev.
|
||
|
+ * Returns minus error number if mapping fails.
|
||
|
+ * Caller must check its return code with IS_ERROR_VALUE() if the function
|
||
|
+ * succeeded.
|
||
|
+ *
|
||
|
+ * The caller of this function must ensure that iovmm_cleanup() is not called
|
||
|
+ * while this function is called.
|
||
|
+ *
|
||
|
+ */
|
||
|
+dma_addr_t rockchip_iovmm_map(struct device *dev, struct scatterlist *sg,
|
||
|
+ off_t offset, size_t size);
|
||
|
+
|
||
|
+/* rockchip_iovmm_unmap() - unmaps the given IO address
|
||
|
+ * @dev: the owner of the IO address space where @iova belongs
|
||
|
+ * @iova: IO address that needs to be unmapped and freed.
|
||
|
+ *
|
||
|
+ * The caller of this function must ensure that iovmm_cleanup() is not called
|
||
|
+ * while this function is called.
|
||
|
+ */
|
||
|
+void rockchip_iovmm_unmap(struct device *dev, dma_addr_t iova);
|
||
|
+
|
||
|
+/* rockchip_iovmm_map_oto - create one to one mapping for the given physical address
|
||
|
+ * @dev: the owner of the IO address space to map
|
||
|
+ * @phys: physical address to map
|
||
|
+ * @size: size of the mapping to create
|
||
|
+ *
|
||
|
+ * This function return 0 if mapping is successful. Otherwise, minus error
|
||
|
+ * value.
|
||
|
+ */
|
||
|
+int rockchip_iovmm_map_oto(struct device *dev, phys_addr_t phys, size_t size);
|
||
|
+
|
||
|
+/* rockchip_iovmm_unmap_oto - remove one to one mapping
|
||
|
+ * @dev: the owner ofthe IO address space
|
||
|
+ * @phys: physical address to remove mapping
|
||
|
+ */
|
||
|
+void rockchip_iovmm_unmap_oto(struct device *dev, phys_addr_t phys);
|
||
|
+
|
||
|
+void rockchip_iovmm_set_fault_handler(struct device *dev,
|
||
|
+ rockchip_iommu_fault_handler_t handler);
|
||
|
+/** rockchip_iovmm_set_fault_handler() - Fault handler for IOMMUs
|
||
|
+ * Called when interrupt occurred by the IOMMUs
|
||
|
+ * The device drivers of peripheral devices that has a IOMMU can implement
|
||
|
+ * a fault handler to resolve address translation fault by IOMMU.
|
||
|
+ * The meanings of return value and parameters are described below.
|
||
|
+ *
|
||
|
+ * return value: non-zero if the fault is correctly resolved.
|
||
|
+ * zero if the fault is not handled.
|
||
|
+ */
|
||
|
+
|
||
|
+int rockchip_iovmm_invalidate_tlb(struct device *dev);
|
||
|
+#else
|
||
|
+static inline int rockchip_iovmm_activate(struct device *dev)
|
||
|
+{
|
||
|
+ return -ENOSYS;
|
||
|
+}
|
||
|
+
|
||
|
+static inline void rockchip_iovmm_deactivate(struct device *dev)
|
||
|
+{
|
||
|
+}
|
||
|
+
|
||
|
+static inline dma_addr_t rockchip_iovmm_map(struct device *dev,
|
||
|
+ struct scatterlist *sg, off_t offset, size_t size)
|
||
|
+{
|
||
|
+ return -ENOSYS;
|
||
|
+}
|
||
|
+
|
||
|
+static inline void rockchip_iovmm_unmap(struct device *dev, dma_addr_t iova)
|
||
|
+{
|
||
|
+}
|
||
|
+
|
||
|
+static inline int rockchip_iovmm_map_oto(struct device *dev, phys_addr_t phys,
|
||
|
+ size_t size)
|
||
|
+{
|
||
|
+ return -ENOSYS;
|
||
|
+}
|
||
|
+
|
||
|
+static inline void rockchip_iovmm_unmap_oto(struct device *dev, phys_addr_t phys)
|
||
|
+{
|
||
|
+}
|
||
|
+
|
||
|
+static inline void rockchip_iovmm_set_fault_handler(struct device *dev,
|
||
|
+ rockchip_iommu_fault_handler_t handler)
|
||
|
+{
|
||
|
+}
|
||
|
+static inline int rockchip_iovmm_invalidate_tlb(struct device *dev)
|
||
|
+{
|
||
|
+ return -ENOSYS;
|
||
|
+}
|
||
|
+
|
||
|
+#endif /* CONFIG_RK_IOVMM */
|
||
|
+
|
||
|
+#endif /*__ASM_PLAT_IOVMM_H*/
|
||
|
diff --git a/include/linux/rockchip/common.h b/include/linux/rockchip/common.h
|
||
|
new file mode 100644
|
||
|
index 0000000..006d52d
|
||
|
--- /dev/null
|
||
|
+++ b/include/linux/rockchip/common.h
|
||
|
@@ -0,0 +1,100 @@
|
||
|
+#ifndef __MACH_ROCKCHIP_COMMON_H
|
||
|
+#define __MACH_ROCKCHIP_COMMON_H
|
||
|
+
|
||
|
+#include <linux/notifier.h>
|
||
|
+
|
||
|
+#define RK_DEVICE(VIRT, PHYS, SIZE) \
|
||
|
+ { \
|
||
|
+ .virtual = (unsigned long)(VIRT), \
|
||
|
+ .pfn = __phys_to_pfn(PHYS), \
|
||
|
+ .length = SIZE, \
|
||
|
+ .type = MT_DEVICE, \
|
||
|
+ }
|
||
|
+
|
||
|
+extern bool rockchip_jtag_enabled;
|
||
|
+extern unsigned long rockchip_boot_fn;
|
||
|
+extern struct smp_operations rockchip_smp_ops;
|
||
|
+
|
||
|
+struct ddr_bw_info {
|
||
|
+ u32 ddr_wr;
|
||
|
+ u32 ddr_rd;
|
||
|
+ u32 ddr_act;
|
||
|
+ u32 ddr_time;
|
||
|
+ u32 ddr_total;
|
||
|
+ u32 ddr_percent;
|
||
|
+
|
||
|
+ u32 cpum;
|
||
|
+ u32 gpu;
|
||
|
+ u32 peri;
|
||
|
+ u32 video;
|
||
|
+ u32 vio0;
|
||
|
+ u32 vio1;
|
||
|
+ u32 vio2;
|
||
|
+};
|
||
|
+extern void (*ddr_bandwidth_get)(struct ddr_bw_info *ddr_bw_ch0,
|
||
|
+ struct ddr_bw_info *ddr_bw_ch1);
|
||
|
+extern int (*ddr_change_freq)(uint32_t mhz);
|
||
|
+extern long (*ddr_round_rate)(uint32_t mhz);
|
||
|
+extern void (*ddr_set_auto_self_refresh)(bool en);
|
||
|
+extern int (*ddr_recalc_rate)(void);
|
||
|
+
|
||
|
+int rockchip_cpu_kill(unsigned int cpu);
|
||
|
+void rockchip_cpu_die(unsigned int cpu);
|
||
|
+int rockchip_cpu_disable(unsigned int cpu);
|
||
|
+
|
||
|
+#define BOOT_MODE_NORMAL 0
|
||
|
+#define BOOT_MODE_FACTORY2 1
|
||
|
+#define BOOT_MODE_RECOVERY 2
|
||
|
+#define BOOT_MODE_CHARGE 3
|
||
|
+#define BOOT_MODE_POWER_TEST 4
|
||
|
+#define BOOT_MODE_OFFMODE_CHARGING 5
|
||
|
+#define BOOT_MODE_REBOOT 6
|
||
|
+#define BOOT_MODE_PANIC 7
|
||
|
+#define BOOT_MODE_WATCHDOG 8
|
||
|
+#define BOOT_MODE_TSADC 9
|
||
|
+
|
||
|
+int rockchip_boot_mode(void);
|
||
|
+void __init rockchip_boot_mode_init(u32 flag, u32 mode);
|
||
|
+void rockchip_restart_get_boot_mode(const char *cmd, u32 *flag, u32 *mode);
|
||
|
+void __init rockchip_efuse_init(void);
|
||
|
+void __init rockchip_suspend_init(void);
|
||
|
+void __init rockchip_ion_reserve(void);
|
||
|
+void __init rockchip_uboot_mem_reserve(void);
|
||
|
+
|
||
|
+enum rockchip_pm_policy {
|
||
|
+ ROCKCHIP_PM_POLICY_PERFORMANCE = 0,
|
||
|
+ ROCKCHIP_PM_POLICY_NORMAL,
|
||
|
+ ROCKCHIP_PM_POLICY_POWERSAVE,
|
||
|
+ ROCKCHIP_PM_NR_POLICYS,
|
||
|
+};
|
||
|
+
|
||
|
+enum rockchip_pm_policy rockchip_pm_get_policy(void);
|
||
|
+int rockchip_pm_set_policy(enum rockchip_pm_policy policy);
|
||
|
+int rockchip_pm_policy_register_notifier(struct notifier_block *nb);
|
||
|
+int rockchip_pm_policy_unregister_notifier(struct notifier_block *nb);
|
||
|
+
|
||
|
+int rockchip_register_system_status_notifier(struct notifier_block *nb);
|
||
|
+int rockchip_unregister_system_status_notifier(struct notifier_block *nb);
|
||
|
+int rockchip_set_system_status(unsigned long status);
|
||
|
+int rockchip_clear_system_status(unsigned long status);
|
||
|
+unsigned long rockchip_get_system_status(void);
|
||
|
+u32 pvtm_get_value(u32 ch, u32 time_us);
|
||
|
+
|
||
|
+#define INVALID_TEMP INT_MAX
|
||
|
+#if IS_ENABLED(CONFIG_ROCKCHIP_THERMAL)
|
||
|
+int rockchip_tsadc_get_temp(int chn, int voltage);
|
||
|
+#else
|
||
|
+#if IS_ENABLED(CONFIG_SENSORS_ROCKCHIP_TSADC)
|
||
|
+int rockchip_tsadc_get_temp(int chn);
|
||
|
+#else
|
||
|
+static inline int rockchip_tsadc_get_temp(int chn) { return INVALID_TEMP; }
|
||
|
+#endif
|
||
|
+#endif
|
||
|
+
|
||
|
+#ifdef CONFIG_RK_LAST_LOG
|
||
|
+void rk_last_log_text(char *text, size_t size);
|
||
|
+#else
|
||
|
+static inline void rk_last_log_text(char *text, size_t size) {}
|
||
|
+#endif
|
||
|
+
|
||
|
+#endif
|
||
|
diff --git a/include/linux/rockchip/cpu.h b/include/linux/rockchip/cpu.h
|
||
|
new file mode 100644
|
||
|
index 0000000..ad6cdc4
|
||
|
--- /dev/null
|
||
|
+++ b/include/linux/rockchip/cpu.h
|
||
|
@@ -0,0 +1,135 @@
|
||
|
+#ifndef __MACH_ROCKCHIP_CPU_H
|
||
|
+#define __MACH_ROCKCHIP_CPU_H
|
||
|
+
|
||
|
+#ifdef CONFIG_ROCKCHIP_CPUINFO
|
||
|
+
|
||
|
+extern unsigned long rockchip_soc_id;
|
||
|
+
|
||
|
+static inline bool cpu_is_rockchip(void)
|
||
|
+{
|
||
|
+ return rockchip_soc_id;
|
||
|
+}
|
||
|
+
|
||
|
+#define ROCKCHIP_CPU_VERION_MASK 0x0000f000
|
||
|
+#define ROCKCHIP_CPU_VERION_SHIFT 12
|
||
|
+
|
||
|
+static inline unsigned long rockchip_get_cpu_version(void)
|
||
|
+{
|
||
|
+ return (rockchip_soc_id & ROCKCHIP_CPU_VERION_MASK)
|
||
|
+ >> ROCKCHIP_CPU_VERION_SHIFT;
|
||
|
+}
|
||
|
+
|
||
|
+static inline void rockchip_set_cpu_version(unsigned long ver)
|
||
|
+{
|
||
|
+ rockchip_soc_id &= ~ROCKCHIP_CPU_VERION_MASK;
|
||
|
+ rockchip_soc_id |=
|
||
|
+ (ver << ROCKCHIP_CPU_VERION_SHIFT) & ROCKCHIP_CPU_VERION_MASK;
|
||
|
+}
|
||
|
+
|
||
|
+#else
|
||
|
+
|
||
|
+static inline bool cpu_is_rockchip(void)
|
||
|
+{
|
||
|
+ return true;
|
||
|
+}
|
||
|
+
|
||
|
+static inline unsigned long rockchip_get_cpu_version(void)
|
||
|
+{
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static inline void rockchip_set_cpu_version(unsigned long ver)
|
||
|
+{
|
||
|
+}
|
||
|
+
|
||
|
+#endif
|
||
|
+
|
||
|
+#define ROCKCHIP_CPU_MASK 0xffff0000
|
||
|
+#define ROCKCHIP_CPU_RK2928 0x29280000
|
||
|
+#define ROCKCHIP_CPU_RK3026 0x30260000
|
||
|
+#define ROCKCHIP_CPU_RK312X 0x31260000
|
||
|
+#define ROCKCHIP_CPU_RK3036 0x30360000
|
||
|
+#define ROCKCHIP_CPU_RK30XX 0x30660000
|
||
|
+#define ROCKCHIP_CPU_RK3066B 0x31680000
|
||
|
+#define ROCKCHIP_CPU_RK3188 0x31880000
|
||
|
+#define ROCKCHIP_CPU_RK319X 0x31900000
|
||
|
+#define ROCKCHIP_CPU_RK3288 0x32880000
|
||
|
+#define ROCKCHIP_CPU_RK3228 0x32280000
|
||
|
+
|
||
|
+#ifdef CONFIG_ROCKCHIP_CPUINFO
|
||
|
+#define ROCKCHIP_CPU(id, ID) \
|
||
|
+static inline bool cpu_is_rk##id(void) \
|
||
|
+{ \
|
||
|
+ return (rockchip_soc_id & ROCKCHIP_CPU_MASK) == ROCKCHIP_CPU_RK ##ID; \
|
||
|
+}
|
||
|
+#else
|
||
|
+#define ROCKCHIP_CPU(id, ID) \
|
||
|
+static inline bool cpu_is_rk##id(void) { return false; }
|
||
|
+#endif
|
||
|
+
|
||
|
+ROCKCHIP_CPU(2928, 2928)
|
||
|
+ROCKCHIP_CPU(3026, 3026)
|
||
|
+ROCKCHIP_CPU(3036, 3036)
|
||
|
+ROCKCHIP_CPU(30xx, 30XX)
|
||
|
+ROCKCHIP_CPU(3066b, 3066B)
|
||
|
+ROCKCHIP_CPU(312x, 312X)
|
||
|
+ROCKCHIP_CPU(3188, 3188)
|
||
|
+ROCKCHIP_CPU(319x, 319X)
|
||
|
+ROCKCHIP_CPU(3288, 3288)
|
||
|
+ROCKCHIP_CPU(3228, 3228)
|
||
|
+
|
||
|
+#define ROCKCHIP_SOC_MASK (ROCKCHIP_CPU_MASK | 0xff)
|
||
|
+#define ROCKCHIP_SOC_RK2926 (ROCKCHIP_CPU_RK2928 | 0x00)
|
||
|
+#define ROCKCHIP_SOC_RK2928G (ROCKCHIP_CPU_RK2928 | 0x01)
|
||
|
+#define ROCKCHIP_SOC_RK2928L (ROCKCHIP_CPU_RK2928 | 0x02)
|
||
|
+#define ROCKCHIP_SOC_RK3028A (ROCKCHIP_CPU_RK3026 | 0x03)
|
||
|
+#define ROCKCHIP_SOC_RK3026 (ROCKCHIP_CPU_RK3026 | 0x04)
|
||
|
+#define ROCKCHIP_SOC_RK3126 (ROCKCHIP_CPU_RK312X | 0x00)
|
||
|
+#define ROCKCHIP_SOC_RK3126B (ROCKCHIP_CPU_RK312X | 0x10)
|
||
|
+#define ROCKCHIP_SOC_RK3128 (ROCKCHIP_CPU_RK312X | 0x01)
|
||
|
+#define ROCKCHIP_SOC_RK3036 (ROCKCHIP_CPU_RK3036 | 0x00)
|
||
|
+#define ROCKCHIP_SOC_RK3000 (ROCKCHIP_CPU_RK30XX | 0x00)
|
||
|
+#define ROCKCHIP_SOC_RK3066 (ROCKCHIP_CPU_RK30XX | 0x01)
|
||
|
+#define ROCKCHIP_SOC_RK3068 (ROCKCHIP_CPU_RK30XX | 0x02)
|
||
|
+#define ROCKCHIP_SOC_RK3066B (ROCKCHIP_CPU_RK3066B| 0x00)
|
||
|
+#define ROCKCHIP_SOC_RK3168 (ROCKCHIP_CPU_RK3066B| 0x01)
|
||
|
+#define ROCKCHIP_SOC_RK3028 (ROCKCHIP_CPU_RK3066B| 0x03)
|
||
|
+#define ROCKCHIP_SOC_RK3188 (ROCKCHIP_CPU_RK3188 | 0x00)
|
||
|
+#define ROCKCHIP_SOC_RK3188PLUS (ROCKCHIP_CPU_RK3188 | 0x10)
|
||
|
+#define ROCKCHIP_SOC_RK3190 (ROCKCHIP_CPU_RK319X | 0x00)
|
||
|
+#define ROCKCHIP_SOC_RK3288 (ROCKCHIP_CPU_RK3288 | 0x00)
|
||
|
+#define ROCKCHIP_SOC_RK3228 (ROCKCHIP_CPU_RK3228 | 0x00)
|
||
|
+
|
||
|
+#ifdef CONFIG_ROCKCHIP_CPUINFO
|
||
|
+#define ROCKCHIP_SOC(id, ID) \
|
||
|
+static inline bool soc_is_rk##id(void) \
|
||
|
+{ \
|
||
|
+ return (rockchip_soc_id & ROCKCHIP_SOC_MASK) == ROCKCHIP_SOC_RK ##ID; \
|
||
|
+}
|
||
|
+#else
|
||
|
+#define ROCKCHIP_SOC(id, ID) \
|
||
|
+static inline bool soc_is_rk##id(void) { return false; }
|
||
|
+#endif
|
||
|
+
|
||
|
+ROCKCHIP_SOC(2926, 2926)
|
||
|
+ROCKCHIP_SOC(2928g, 2928G)
|
||
|
+ROCKCHIP_SOC(2928l, 2928L)
|
||
|
+ROCKCHIP_SOC(3028a, 3028A)
|
||
|
+ROCKCHIP_SOC(3026, 3026)
|
||
|
+ROCKCHIP_SOC(3126, 3126)
|
||
|
+ROCKCHIP_SOC(3126b, 3126B)
|
||
|
+ROCKCHIP_SOC(3128, 3128)
|
||
|
+ROCKCHIP_SOC(3036, 3036)
|
||
|
+ROCKCHIP_SOC(3000, 3000)
|
||
|
+ROCKCHIP_SOC(3066, 3066)
|
||
|
+ROCKCHIP_SOC(3068, 3068)
|
||
|
+ROCKCHIP_SOC(3066b, 3066B)
|
||
|
+ROCKCHIP_SOC(3168, 3168)
|
||
|
+ROCKCHIP_SOC(3028, 3028)
|
||
|
+ROCKCHIP_SOC(3188, 3188)
|
||
|
+ROCKCHIP_SOC(3188plus, 3188PLUS)
|
||
|
+ROCKCHIP_SOC(3190, 3190)
|
||
|
+ROCKCHIP_SOC(3288, 3288)
|
||
|
+ROCKCHIP_SOC(3228, 3228)
|
||
|
+
|
||
|
+#endif
|
||
|
diff --git a/include/linux/rockchip/cru.h b/include/linux/rockchip/cru.h
|
||
|
new file mode 100755
|
||
|
index 0000000..ee33f5a
|
||
|
--- /dev/null
|
||
|
+++ b/include/linux/rockchip/cru.h
|
||
|
@@ -0,0 +1,281 @@
|
||
|
+#ifndef __MACH_ROCKCHIP_CRU_H
|
||
|
+#define __MACH_ROCKCHIP_CRU_H
|
||
|
+
|
||
|
+#include <dt-bindings/clock/rockchip,rk3188.h>
|
||
|
+#include <dt-bindings/clock/rockchip,rk3288.h>
|
||
|
+#include <linux/rockchip/iomap.h>
|
||
|
+
|
||
|
+
|
||
|
+/*******************CRU BITS*******************************/
|
||
|
+
|
||
|
+#define CRU_W_MSK(bits_shift, msk) ((msk) << ((bits_shift) + 16))
|
||
|
+
|
||
|
+#define CRU_SET_BITS(val, bits_shift, msk) (((val)&(msk)) << (bits_shift))
|
||
|
+
|
||
|
+#define CRU_W_MSK_SETBITS(val, bits_shift,msk) \
|
||
|
+ (CRU_W_MSK(bits_shift, msk) | CRU_SET_BITS(val, bits_shift, msk))
|
||
|
+
|
||
|
+/*******************RK3188********************************/
|
||
|
+/*******************CRU OFFSET*********************/
|
||
|
+#define RK3188_CRU_MODE_CON 0x40
|
||
|
+#define RK3188_CRU_CLKSEL_CON 0x44
|
||
|
+#define RK3188_CRU_CLKGATE_CON 0xd0
|
||
|
+#define RK3188_CRU_GLB_SRST_FST 0x100
|
||
|
+#define RK3188_CRU_GLB_SRST_SND 0x104
|
||
|
+#define RK3188_CRU_SOFTRST_CON 0x110
|
||
|
+
|
||
|
+#define RK3188_PLL_CONS(id, i) ((id) * 0x10 + ((i) * 4))
|
||
|
+
|
||
|
+#define RK3188_CRU_CLKSELS_CON_CNT (35)
|
||
|
+#define RK3188_CRU_CLKSELS_CON(i) (RK3188_CRU_CLKSEL_CON + ((i) * 4))
|
||
|
+
|
||
|
+#define RK3188_CRU_CLKGATES_CON_CNT (10)
|
||
|
+#define RK3188_CRU_CLKGATES_CON(i) (RK3188_CRU_CLKGATE_CON + ((i) * 4))
|
||
|
+
|
||
|
+#define RK3188_CRU_SOFTRSTS_CON_CNT (9)
|
||
|
+#define RK3188_CRU_SOFTRSTS_CON(i) (RK3188_CRU_SOFTRST_CON + ((i) * 4))
|
||
|
+
|
||
|
+#define RK3188_CRU_MISC_CON (0x134)
|
||
|
+#define RK3188_CRU_GLB_CNT_TH (0x140)
|
||
|
+
|
||
|
+/******************PLL MODE BITS*******************/
|
||
|
+#define RK3188_PLL_MODE_MSK(id) (0x3 << ((id) * 4))
|
||
|
+#define RK3188_PLL_MODE_SLOW(id) ((0x0<<((id)*4))|(0x3<<(16+(id)*4)))
|
||
|
+#define RK3188_PLL_MODE_NORM(id) ((0x1<<((id)*4))|(0x3<<(16+(id)*4)))
|
||
|
+#define RK3188_PLL_MODE_DEEP(id) ((0x2<<((id)*4))|(0x3<<(16+(id)*4)))
|
||
|
+
|
||
|
+/******************CRU GATINGS**********************************/
|
||
|
+#define RK3188_CRU_GATEID_CONS(ID) (RK3188_CRU_CLKGATE_CON+(ID/16)*4)
|
||
|
+
|
||
|
+/*************************RK3288********************************/
|
||
|
+
|
||
|
+/*******************CRU OFFSET*********************/
|
||
|
+#define RK3288_CRU_MODE_CON 0x50
|
||
|
+#define RK3288_CRU_CLKSEL_CON 0x60
|
||
|
+#define RK3288_CRU_CLKGATE_CON 0x160
|
||
|
+
|
||
|
+#define RK3288_PLL_CONS(id, i) ((id) * 0x10 + ((i) * 4))
|
||
|
+#define RK3288_CRU_CLKSELS_CON(i) (RK3288_CRU_CLKSEL_CON + ((i) * 4))
|
||
|
+#define RK3288_CRU_CLKGATES_CON(i) (RK3288_CRU_CLKGATE_CON + ((i) * 4))
|
||
|
+
|
||
|
+/******************PLL MODE BITS*******************/
|
||
|
+/*************apll dpll,cpll,gpll,npll 0~4************/
|
||
|
+#define RK3288_PLLS_MODE_OFFSET(id) ((id)<=3 ? (id*4) : 14)
|
||
|
+#define RK3288_PLL_MODE_MSK(id) (0x3 << RK3288_PLLS_MODE_OFFSET(id))
|
||
|
+#define RK3288_PLL_MODE_SLOW(id) ((0x0<<RK3288_PLLS_MODE_OFFSET(id))|(0x3<<(16+RK3288_PLLS_MODE_OFFSET(id))))
|
||
|
+#define RK3288_PLL_MODE_NORM(id) ((0x1<<RK3288_PLLS_MODE_OFFSET(id))|(0x3<<(16+RK3288_PLLS_MODE_OFFSET(id))))
|
||
|
+#define RK3288_PLL_MODE_DEEP(id) ((0x2<<RK3288_PLLS_MODE_OFFSET(id))|(0x3<<(16+RK3288_PLLS_MODE_OFFSET(id))))
|
||
|
+
|
||
|
+/*******************CRU GATING*********************/
|
||
|
+#define RK3288_CRU_CLKGATES_CON_CNT (19)
|
||
|
+#define RK3288_CRU_CONS_GATEID(i) (16 * (i))
|
||
|
+#define RK3288_CRU_GATEID_CONS(ID) (RK3288_CRU_CLKGATE_CON+(ID/16)*4)
|
||
|
+
|
||
|
+enum rk3288_cru_clk_gate {
|
||
|
+ /* SCU CLK GATE 0 CON */
|
||
|
+ RK3288_CLKGATE_UART0_SRC = (RK3288_CRU_CONS_GATEID(1)+8),
|
||
|
+
|
||
|
+ RK3288_CLKGATE_UART4_SRC = (RK3288_CRU_CONS_GATEID(2)+12),
|
||
|
+
|
||
|
+ RK3288_CLKGATE_PCLK_UART0= (RK3288_CRU_CONS_GATEID(6)+8),
|
||
|
+ RK3288_CLKGATE_PCLK_UART1,
|
||
|
+ RK3288_CLKGATE6_DUMP1,
|
||
|
+ RK3288_CLKGATE_PCLK_UART3,
|
||
|
+ RK3288_CLKGATE_PCLK_I2C2,
|
||
|
+ RK3288_CLKGATE_PCLK_I2C3,
|
||
|
+ RK3288_CLKGATE_PCLK_I2C4,
|
||
|
+
|
||
|
+ RK3288_CLKGATE_PCLK_I2C0 = (RK3288_CRU_CONS_GATEID(10)+2),
|
||
|
+ RK3288_CLKGATE_PCLK_I2C1,
|
||
|
+
|
||
|
+ RK3288_CLKGATE_PCLK_UART2 = (RK3288_CRU_CONS_GATEID(11)+9),
|
||
|
+
|
||
|
+
|
||
|
+ RK3288_CLKGATE_PCLK_GPIO1 = (RK3288_CRU_CONS_GATEID(14)+1),
|
||
|
+
|
||
|
+ RK3288_CLKGATE_PCLK_GPIO0 = (RK3288_CRU_CONS_GATEID(17)+4),
|
||
|
+ //gate6
|
||
|
+};
|
||
|
+
|
||
|
+#define RK3288_CRU_GLB_SRST_FST_VALUE 0x1b0
|
||
|
+#define RK3288_CRU_GLB_SRST_SND_VALUE 0x1b4
|
||
|
+#define RK3288_CRU_SOFTRST_CON 0x1b8
|
||
|
+#define RK3288_CRU_MISC_CON 0x1e8
|
||
|
+#define RK3288_CRU_GLB_CNT_TH 0x1ec
|
||
|
+#define RK3288_CRU_GLB_RST_CON 0x1f0
|
||
|
+#define RK3288_CRU_GLB_RST_ST 0x1f8
|
||
|
+#define RK3288_CRU_SDMMC_CON0 0x200
|
||
|
+#define RK3288_CRU_SDMMC_CON1 0x204
|
||
|
+#define RK3288_CRU_SDIO0_CON0 0x208
|
||
|
+#define RK3288_CRU_SDIO0_CON1 0x20c
|
||
|
+#define RK3288_CRU_SDIO1_CON0 0x210
|
||
|
+#define RK3288_CRU_SDIO1_CON1 0x214
|
||
|
+#define RK3288_CRU_EMMC_CON0 0x218
|
||
|
+#define RK3288_CRU_EMMC_CON1 0x21c
|
||
|
+
|
||
|
+#define RK3288_CRU_SOFTRSTS_CON_CNT (12)
|
||
|
+#define RK3288_CRU_SOFTRSTS_CON(i) (RK3288_CRU_SOFTRST_CON + ((i) * 4))
|
||
|
+
|
||
|
+static inline void rk3288_cru_set_soft_reset(u32 idx, bool on)
|
||
|
+{
|
||
|
+ void __iomem *reg = RK_CRU_VIRT + RK3288_CRU_SOFTRSTS_CON(idx >> 4);
|
||
|
+ u32 val = on ? 0x10001U << (idx & 0xf) : 0x10000U << (idx & 0xf);
|
||
|
+ writel_relaxed(val, reg);
|
||
|
+ dsb(sy);
|
||
|
+}
|
||
|
+
|
||
|
+#define RK3036_CRU_MODE_CON 0x0040
|
||
|
+
|
||
|
+/******************PLL MODE BITS*******************/
|
||
|
+/****************apll dpll,gpll 0~2******************/
|
||
|
+#define RK3036_PLLS_MODE_OFFSET(id) ((id) < 2 ? (id*4) : 12)
|
||
|
+
|
||
|
+#define RK3036_PLL_MODE_SLOW(id) ((0x0 << RK3036_PLLS_MODE_OFFSET(id)) \
|
||
|
+ | (((id) < 2 ? 0x1 : 0x3) << (16 + RK3036_PLLS_MODE_OFFSET(id))))
|
||
|
+
|
||
|
+#define RK3036_PLL_MODE_MSK(id) (0x1 << RK3036_PLLS_MODE_OFFSET(id))
|
||
|
+
|
||
|
+#define RK3036_APLL_MODE_SLOW ((0x0<<0x00)|(0x1<<(16+0x00)))
|
||
|
+#define RK3036_DPLL_MODE_SLOW ((0x0<<0x04)|(0x1<<(16+0x04)))
|
||
|
+#define RK3036_GPLL_MODE_SLOW ((0x0<<0x12)|(0x3<<(16+0x12)))
|
||
|
+
|
||
|
+#define RK3036_APLL_MODE_NORM ((0x1<<0x00)|(0x1<<(16+0x00)))
|
||
|
+#define RK3036_DPLL_MODE_NORM ((0x1<<0x04)|(0x1<<(16+0x04)))
|
||
|
+#define RK3036_GPLL_MODE_NORM ((0x1<<0x12)|(0x3<<(16+0x12)))
|
||
|
+
|
||
|
+#define RK3036_GPLL_MODE_DEEP ((0x10<<0x12)|(0x3<<(16+0x12)))
|
||
|
+
|
||
|
+#define RK3036_PLL_CONS(id, i) (((id) < 2 ? id : (id + 1)) * 0x10 + ((i) * 4))
|
||
|
+
|
||
|
+#define RK3036_CRU_GLB_SRST_FST_VALUE 0x00100
|
||
|
+#define RK3036_CRU_GLB_SRST_SND_VALUE 0x00104
|
||
|
+#define RK3036_CRU_SOFTRST0_CON 0x00110
|
||
|
+#define RK3036_CRU_SOFTRST1_CON 0x00114
|
||
|
+#define RK3036_CRU_SOFTRST2_CON 0x00118
|
||
|
+#define RK3036_CRU_SOFTRST3_CON 0x0011c
|
||
|
+#define RK3036_CRU_SOFTRST4_CON 0x00120
|
||
|
+#define RK3036_CRU_SOFTRST5_CON 0x00124
|
||
|
+#define RK3036_CRU_SOFTRST6_CON 0x00128
|
||
|
+#define RK3036_CRU_SOFTRST7_CON 0x0012c
|
||
|
+#define RK3036_CRU_SOFTRST8_CON 0x00130
|
||
|
+#define RK3036_CRU_MISC_CON 0x00134
|
||
|
+#define RK3036_CRU_GLB_CNT_TH 0x00140
|
||
|
+#define RK3036_CRU_SDMMC_CON0 0x00144
|
||
|
+#define RK3036_CRU_SDMMC_CON1 0x00148
|
||
|
+#define RK3036_CRU_SDIO_CON0 0x0014c
|
||
|
+#define RK3036_CRU_SDIO_CON1 0x00150
|
||
|
+#define RK3036_CRU_EMMC_CON0 0x00154
|
||
|
+#define RK3036_CRU_EMMC_CON1 0x00158
|
||
|
+#define RK3036_CRU_RST_ST 0x00160
|
||
|
+#define RK3036_CRU_PLL_MASK_CON 0x001f0
|
||
|
+
|
||
|
+#define RK3036_CRU_CLKSEL_CON 0x44
|
||
|
+#define RK3036_CRU_CLKGATE_CON 0xd0
|
||
|
+
|
||
|
+#define RK3036_CRU_CLKSELS_CON_CNT (35)
|
||
|
+#define RK3036_CRU_CLKSELS_CON(i) (RK3036_CRU_CLKSEL_CON + ((i) * 4))
|
||
|
+
|
||
|
+#define RK3036_CRU_CLKGATES_CON_CNT (11)
|
||
|
+#define RK3036_CRU_CLKGATES_CON(i) (RK3036_CRU_CLKGATE_CON + ((i) * 4))
|
||
|
+
|
||
|
+#define RK3036_CRU_SOFTRSTS_CON_CNT (9)
|
||
|
+#define RK3036_CRU_SOFTRSTS_CON(i) (RK3036_CRU_SOFTRST_CON + ((i) * 4))
|
||
|
+
|
||
|
+/*******************CRU GATING*********************/
|
||
|
+#define RK3036_CRU_UART_GATE 0xd4
|
||
|
+#define RK3036_CLKGATE_UART0_SRC 8
|
||
|
+#define RK3036_CLKGATE_UART0_PCLK 9
|
||
|
+
|
||
|
+#define RK312X_PLL_CONS(id, i) ((id) * 0x10 + ((i) * 4))
|
||
|
+
|
||
|
+#define RK312X_CRU_GLB_SRST_FST_VALUE 0x00100
|
||
|
+#define RK312X_CRU_GLB_SRST_SND_VALUE 0x00104
|
||
|
+#define RK312X_CRU_MISC_CON 0x00134
|
||
|
+#define RK312X_CRU_GLB_CNT_TH 0x00140
|
||
|
+#define RK312X_CRU_GLB_RST_ST 0x00150
|
||
|
+#define RK312X_CRU_SDMMC_CON0 0x01c0
|
||
|
+#define RK312X_CRU_SDMMC_CON1 0x01c4
|
||
|
+#define RK312X_CRU_SDIO_CON0 0x01c8
|
||
|
+#define RK312X_CRU_SDIO_CON1 0x01cc
|
||
|
+#define RK312X_CRU_EMMC_CON0 0x01d8
|
||
|
+#define RK312X_CRU_EMMC_CON1 0x01dc
|
||
|
+#define RK312X_CRU_PLL_PRG_EN 0x01f0
|
||
|
+#define RK312X_CRU_MODE_CON 0x40
|
||
|
+#define RK312X_CRU_RST_ST 0x00160
|
||
|
+#define RK312X_CRU_PLL_MASK_CON 0x001f0
|
||
|
+
|
||
|
+#define RK312X_CRU_CLKSEL_CON 0x44
|
||
|
+#define RK312X_CRU_CLKGATE_CON 0xd0
|
||
|
+
|
||
|
+#define RK312X_PLL_CONS(id, i) ((id) * 0x10 + ((i) * 4))
|
||
|
+
|
||
|
+/******************PLL MODE BITS*******************/
|
||
|
+#define RK312X_PLLS_MODE_OFFSET(id) ((id) <= 3 ? (id * 4) : 14)
|
||
|
+#define RK312X_PLL_MODE_MSK(id) (0x1 << RK312X_PLLS_MODE_OFFSET(id))
|
||
|
+#define RK312X_PLL_MODE_SLOW(id) ((0x0 << RK312X_PLLS_MODE_OFFSET(id))\
|
||
|
+| (0x1 << (16 + RK312X_PLLS_MODE_OFFSET(id))))
|
||
|
+#define RK312X_PLL_MODE_NORM(id) ((0x1 << RK312X_PLLS_MODE_OFFSET(id))\
|
||
|
+| (0x1 << (16 + RK312X_PLLS_MODE_OFFSET(id))))
|
||
|
+
|
||
|
+
|
||
|
+#define RK312X_CRU_SOFTRST_CON 0x110
|
||
|
+
|
||
|
+#define RK312X_CRU_CLKSELS_CON_CNT (35)
|
||
|
+#define RK312X_CRU_CLKSELS_CON(i) (RK3036_CRU_CLKSEL_CON + ((i) * 4))
|
||
|
+
|
||
|
+#define RK312X_CRU_CLKGATES_CON_CNT (11)
|
||
|
+#define RK312X_CRU_CLKGATES_CON(i) (RK3036_CRU_CLKGATE_CON + ((i) * 4))
|
||
|
+
|
||
|
+#define RK312X_CRU_SOFTRSTS_CON_CNT (9)
|
||
|
+#define RK312X_CRU_SOFTRSTS_CON(i) (RK312X_CRU_SOFTRST_CON + ((i) * 4))
|
||
|
+
|
||
|
+/*******************CRU GATING*********************/
|
||
|
+#define RK312X_CRU_CONS_GATEID(i) (16 * (i))
|
||
|
+#define RK312X_CRU_GATEID_CONS(ID) (RK312X_CRU_CLKGATE_CON\
|
||
|
+ + ((ID) / 16) * 4)
|
||
|
+
|
||
|
+enum rk312x_cru_clk_gate {
|
||
|
+ /* SCU CLK GATE 0 CON */
|
||
|
+ RK312X_CLKGATE_UART0_SRC = (RK312X_CRU_CONS_GATEID(1) + 8),
|
||
|
+ RK312X_CLKGATE_PCLK_UART0 = (RK312X_CRU_CONS_GATEID(8) + 0),
|
||
|
+ RK312X_CLKGATE_PCLK_UART1,
|
||
|
+ RK312X_CLKGATE_PCLK_UART2,
|
||
|
+};
|
||
|
+
|
||
|
+#define RK3228_PLL_CONS(id, i) RK312X_PLL_CONS(id, i)
|
||
|
+#define RK3228_CRU_MODE_CON RK312X_CRU_MODE_CON
|
||
|
+#define RK3228_CRU_CLKSELS_CON_CNT RK312X_CRU_CLKSELS_CON_CNT
|
||
|
+#define RK3228_CRU_CLKSELS_CON(i) RK312X_CRU_CLKSELS_CON(i)
|
||
|
+#define RK3228_CRU_CLKGATES_CON_CNT (16)
|
||
|
+#define RK3228_CRU_CLKGATES_CON(i) RK312X_CRU_CLKGATES_CON(i)
|
||
|
+#define RK3228_CRU_SOFTRSTS_CON_CNT RK312X_CRU_SOFTRSTS_CON_CNT
|
||
|
+#define RK3228_CRU_SOFTRSTS_CON(i) RK312X_CRU_SOFTRSTS_CON(i)
|
||
|
+#define RK3228_CRU_MISC_CON RK312X_CRU_MISC_CON
|
||
|
+#define RK3228_CRU_GLB_CNT_TH RK312X_CRU_GLB_CNT_TH
|
||
|
+#define RK3228_CRU_GLB_RST_ST RK312X_CRU_GLB_RST_ST
|
||
|
+#define RK3228_CRU_SDMMC_CON0 RK312X_CRU_SDMMC_CON0
|
||
|
+#define RK3228_CRU_SDMMC_CON1 RK312X_CRU_SDMMC_CON1
|
||
|
+#define RK3228_CRU_SDIO_CON0 RK312X_CRU_SDIO_CON0
|
||
|
+#define RK3228_CRU_SDIO_CON1 RK312X_CRU_SDIO_CON1
|
||
|
+#define RK3228_CRU_EMMC_CON0 RK312X_CRU_EMMC_CON0
|
||
|
+#define RK3228_CRU_EMMC_CON1 RK312X_CRU_EMMC_CON1
|
||
|
+#define RK3228_CRU_GLB_SRST_FST_VALUE 0x001f0
|
||
|
+#define RK3228_CRU_GLB_SRST_SND_VALUE 0x001f4
|
||
|
+#define RK3228_CRU_PLL_MASK_CON 0x001f8
|
||
|
+
|
||
|
+/*************************RK3368********************************/
|
||
|
+
|
||
|
+/*******************CRU OFFSET*********************/
|
||
|
+#define RK3368_CRU_CLKSEL_CON 0x100
|
||
|
+#define RK3368_CRU_CLKGATE_CON 0x200
|
||
|
+#define RK3368_CRU_CLKGATES_CON_CNT 25
|
||
|
+
|
||
|
+#define RK3368_PLL_CONS(id, i) ((id) * 0x10 + ((i) * 4))
|
||
|
+#define RK3368_CRU_CLKSELS_CON(i) (RK3368_CRU_CLKSEL_CON + ((i) * 4))
|
||
|
+#define RK3368_CRU_CLKGATES_CON(i) (RK3368_CRU_CLKGATE_CON + ((i) * 4))
|
||
|
+
|
||
|
+#define RK3368_CRU_SOFTRSTS_CON_CNT (15)
|
||
|
+#define RK3368_CRU_SOFTRST_CON 0x300
|
||
|
+#define RK3368_CRU_SOFTRSTS_CON(i) (RK3368_CRU_SOFTRST_CON + ((i) * 4))
|
||
|
+
|
||
|
+#endif
|
||
|
diff --git a/include/linux/rockchip/dvfs.h b/include/linux/rockchip/dvfs.h
|
||
|
new file mode 100644
|
||
|
index 0000000..1aaffbd
|
||
|
--- /dev/null
|
||
|
+++ b/include/linux/rockchip/dvfs.h
|
||
|
@@ -0,0 +1,258 @@
|
||
|
+/* arch/arm/mach-rk30/rk30_dvfs.h
|
||
|
+ *
|
||
|
+ * Copyright (C) 2012 ROCKCHIP, Inc.
|
||
|
+ *
|
||
|
+ * This software is licensed under the terms of the GNU General Public
|
||
|
+ * License version 2, as published by the Free Software Foundation, and
|
||
|
+ * may be copied, distributed, and modified under those terms.
|
||
|
+ *
|
||
|
+ * 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 _RK30_DVFS_H_
|
||
|
+#define _RK30_DVFS_H_
|
||
|
+
|
||
|
+#include <linux/device.h>
|
||
|
+#include <linux/clk-provider.h>
|
||
|
+
|
||
|
+#define ARM_DVFS_CH 0
|
||
|
+#define GPU_DVFS_CH 1
|
||
|
+#define LOG_DVFS_CH 2
|
||
|
+
|
||
|
+struct dvfs_node;
|
||
|
+typedef int (*dvfs_set_rate_callback)(struct dvfs_node *clk_dvfs_node, unsigned long rate);
|
||
|
+typedef int (*clk_set_rate_callback)(struct clk *clk, unsigned long rate);
|
||
|
+
|
||
|
+/**
|
||
|
+ * struct vd_node: To Store All Voltage Domains' info
|
||
|
+ * @name: Voltage Domain's Name
|
||
|
+ * @regulator_name: Voltage domain's regulator name
|
||
|
+ * @cur_volt: Voltage Domain's Current Voltage
|
||
|
+ * @regulator: Voltage Domain's regulator point
|
||
|
+ * @node: Point of he Voltage Domain List Node
|
||
|
+ * @pd_list: Head of Power Domain List Belongs to This Voltage Domain
|
||
|
+ * @req_volt_list: The list of clocks requests
|
||
|
+ * @dvfs_mutex: Lock
|
||
|
+ * @vd_dvfs_target: Callback function
|
||
|
+ */
|
||
|
+ #define VD_VOL_LIST_CNT (200)
|
||
|
+ #define VD_LIST_RELATION_L 0
|
||
|
+ #define VD_LIST_RELATION_H 1
|
||
|
+
|
||
|
+struct vd_node {
|
||
|
+ const char *name;
|
||
|
+ const char *regulator_name;
|
||
|
+ int volt_time_flag;// =0 ,is no initing checking ,>0 ,support,<0 not support
|
||
|
+ int mode_flag;// =0 ,is no initing checking ,>0 ,support,<0 not support;
|
||
|
+ int cur_volt;
|
||
|
+ int volt_set_flag;
|
||
|
+ int suspend_volt;
|
||
|
+ struct regulator *regulator;
|
||
|
+ struct list_head node;
|
||
|
+ struct list_head pd_list;
|
||
|
+ struct mutex mutex;
|
||
|
+ dvfs_set_rate_callback vd_dvfs_target;
|
||
|
+ unsigned int n_voltages;
|
||
|
+ int volt_list[VD_VOL_LIST_CNT];
|
||
|
+ unsigned int regu_mode;
|
||
|
+};
|
||
|
+
|
||
|
+/**
|
||
|
+ * struct pd_node: To Store All Power Domains' info
|
||
|
+ * @name: Power Domain's Name
|
||
|
+ * @cur_volt: Power Domain's Current Voltage
|
||
|
+ * @pd_status: Power Domain's status
|
||
|
+ * @vd: Voltage Domain the power domain belongs to
|
||
|
+ * @pd_clk: Look power domain as a clock
|
||
|
+ * @node: List node to Voltage Domain
|
||
|
+ * @clk_list: Head of Power Domain's Clocks List
|
||
|
+ */
|
||
|
+struct pd_node {
|
||
|
+ const char *name;
|
||
|
+ int cur_volt;
|
||
|
+ unsigned char pd_status;
|
||
|
+ struct vd_node *vd;
|
||
|
+ struct list_head node;
|
||
|
+ struct list_head clk_list;
|
||
|
+ unsigned int regu_mode;
|
||
|
+};
|
||
|
+
|
||
|
+struct pvtm_info {
|
||
|
+ const char *compatible;
|
||
|
+ struct cpufreq_frequency_table *pvtm_table;
|
||
|
+ int channel;
|
||
|
+ int process_version;
|
||
|
+ int scan_rate_hz;
|
||
|
+ int sample_time_us;
|
||
|
+ int volt_step_uv;
|
||
|
+ int delta_pvtm_by_volt;
|
||
|
+ int delta_pvtm_by_temp;
|
||
|
+ int volt_margin_uv;
|
||
|
+ int min_volt_uv;
|
||
|
+ int max_volt_uv;
|
||
|
+ int cluster;
|
||
|
+};
|
||
|
+
|
||
|
+struct lkg_adjust_volt_table {
|
||
|
+ int lkg;
|
||
|
+ int dlt_volt;
|
||
|
+};
|
||
|
+
|
||
|
+struct lkg_info {
|
||
|
+ int def_table_lkg;
|
||
|
+ int min_adjust_freq;
|
||
|
+ struct lkg_adjust_volt_table *table;
|
||
|
+};
|
||
|
+
|
||
|
+/**
|
||
|
+ * struct dvfs_node: To Store All dvfs clocks' info
|
||
|
+ * @name: Dvfs clock's Name
|
||
|
+ * @set_freq: Dvfs clock's Current Frequency
|
||
|
+ * @set_volt: Dvfs clock's Current Voltage
|
||
|
+ * @enable_dvfs: Sign if DVFS clock enable
|
||
|
+ * @clk: System clk's point
|
||
|
+ * @pd: Power Domains dvfs clock belongs to
|
||
|
+ * @vd: Voltage Domains dvfs clock belongs to
|
||
|
+ * @dvfs_nb: Notify list
|
||
|
+ * @dvfs_table: Frequency and voltage table for dvfs
|
||
|
+ * @clk_dvfs_target: Callback function
|
||
|
+ */
|
||
|
+struct dvfs_node {
|
||
|
+ struct device dev; //for opp
|
||
|
+ const char *name;
|
||
|
+ int set_freq; //KHZ
|
||
|
+ int set_volt; //MV
|
||
|
+ int enable_count;
|
||
|
+ int freq_limit_en; //sign if use limit frequency
|
||
|
+ int support_pvtm;
|
||
|
+ unsigned int min_rate; //limit min frequency
|
||
|
+ unsigned int max_rate; //limit max frequency
|
||
|
+ unsigned long last_set_rate;
|
||
|
+ unsigned int channel;
|
||
|
+ unsigned int temp_channel;
|
||
|
+ unsigned long temp_limit_rate;
|
||
|
+ unsigned int target_temp;
|
||
|
+ unsigned int temp_limit_enable;
|
||
|
+ unsigned int min_temp_limit;
|
||
|
+ int old_temp;
|
||
|
+ struct clk *clk;
|
||
|
+ struct pd_node *pd;
|
||
|
+ struct vd_node *vd;
|
||
|
+ struct list_head node;
|
||
|
+ struct notifier_block *dvfs_nb;
|
||
|
+ struct cpufreq_frequency_table *dvfs_table;
|
||
|
+ struct cpufreq_frequency_table *pvtm_table;
|
||
|
+ struct cpufreq_frequency_table *per_temp_limit_table;
|
||
|
+ struct cpufreq_frequency_table *nor_temp_limit_table;
|
||
|
+ struct cpufreq_frequency_table *virt_temp_limit_table[4];
|
||
|
+ clk_set_rate_callback clk_dvfs_target;
|
||
|
+ struct cpufreq_frequency_table *regu_mode_table;
|
||
|
+ int regu_mode_en;
|
||
|
+ unsigned int regu_mode;
|
||
|
+ struct pvtm_info *pvtm_info;
|
||
|
+ int lkg_adjust_volt_en;
|
||
|
+ struct lkg_info lkg_info;
|
||
|
+ unsigned int cluster;
|
||
|
+ unsigned int max_limit_freq;
|
||
|
+ unsigned int pvtm_min_temp;
|
||
|
+};
|
||
|
+
|
||
|
+
|
||
|
+
|
||
|
+#define DVFS_MHZ (1000*1000)
|
||
|
+#define DVFS_KHZ (1000)
|
||
|
+
|
||
|
+#define DVFS_V (1000*1000)
|
||
|
+#define DVFS_MV (1000)
|
||
|
+#if 0
|
||
|
+#define DVFS_DBG(fmt, args...) printk(KERN_INFO "DVFS DBG:\t"fmt, ##args)
|
||
|
+#else
|
||
|
+#define DVFS_DBG(fmt, args...) {while(0);}
|
||
|
+#endif
|
||
|
+
|
||
|
+#define DVFS_ERR(fmt, args...) printk(KERN_ERR "DVFS ERR:\t"fmt, ##args)
|
||
|
+#define DVFS_LOG(fmt, args...) printk(KERN_DEBUG "DVFS LOG:\t"fmt, ##args)
|
||
|
+#define DVFS_WARNING(fmt, args...) printk(KERN_WARNING "DVFS WARNING:\t"fmt, ##args)
|
||
|
+
|
||
|
+#define DVFS_SET_VOLT_FAILURE 1
|
||
|
+#define DVFS_SET_VOLT_SUCCESS 0
|
||
|
+
|
||
|
+#define dvfs_regulator_get(dev,id) regulator_get((dev),(id))
|
||
|
+#define dvfs_regulator_put(regu) regulator_put((regu))
|
||
|
+#define dvfs_regulator_set_voltage(regu,min_uV,max_uV) regulator_set_voltage((regu),(min_uV),(max_uV))
|
||
|
+#define dvfs_regulator_get_voltage(regu) regulator_get_voltage((regu))
|
||
|
+#define dvfs_regulator_set_voltage_time(regu, old_uV, new_uV) regulator_set_voltage_time((regu), (old_uV), (new_uV))
|
||
|
+#define dvfs_regulator_set_mode(regu, mode) regulator_set_mode((regu), (mode))
|
||
|
+#define dvfs_regulator_get_mode(regu) regulator_get_mode((regu))
|
||
|
+#define dvfs_regulator_list_voltage(regu,selector) regulator_list_voltage((regu),(selector))
|
||
|
+#define dvfs_regulator_count_voltages(regu) regulator_count_voltages((regu))
|
||
|
+
|
||
|
+#define clk_dvfs_node_get(a,b) clk_get((a),(b))
|
||
|
+#define clk_dvfs_node_get_rate_kz(a) (clk_get_rate((a))/1000)
|
||
|
+#define clk_dvfs_node_set_rate(a,b) clk_set_rate((a),(b))
|
||
|
+
|
||
|
+typedef void (*avs_init_fn)(void);
|
||
|
+typedef u8 (*avs_get_val_fn)(void);
|
||
|
+struct avs_ctr_st {
|
||
|
+ avs_init_fn avs_init;
|
||
|
+ avs_get_val_fn avs_get_val;
|
||
|
+};
|
||
|
+
|
||
|
+#ifdef CONFIG_DVFS
|
||
|
+struct dvfs_node *clk_get_dvfs_node(char *clk_name);
|
||
|
+void clk_put_dvfs_node(struct dvfs_node *clk_dvfs_node);
|
||
|
+unsigned long dvfs_clk_get_rate(struct dvfs_node *clk_dvfs_node);
|
||
|
+unsigned long dvfs_clk_get_last_set_rate(struct dvfs_node *clk_dvfs_node);
|
||
|
+unsigned long dvfs_clk_round_rate(struct dvfs_node *clk_dvfs_node, unsigned long rate);
|
||
|
+int dvfs_clk_set_rate(struct dvfs_node *clk_dvfs_node, unsigned long rate);
|
||
|
+int dvfs_clk_enable(struct dvfs_node *clk_dvfs_node);
|
||
|
+void dvfs_clk_disable(struct dvfs_node *clk_dvfs_node);
|
||
|
+int dvfs_clk_prepare_enable(struct dvfs_node *clk_dvfs_node);
|
||
|
+void dvfs_clk_disable_unprepare(struct dvfs_node *clk_dvfs_node);
|
||
|
+int dvfs_set_freq_volt_table(struct dvfs_node *clk_dvfs_node, struct cpufreq_frequency_table *table);
|
||
|
+int dvfs_clk_register_set_rate_callback(struct dvfs_node *clk_dvfs_node, clk_set_rate_callback clk_dvfs_target);
|
||
|
+int dvfs_clk_enable_limit(struct dvfs_node *clk_dvfs_node, unsigned int min_rate, unsigned max_rate);
|
||
|
+int dvfs_clk_get_limit(struct dvfs_node *clk_dvfs_node, unsigned int *min_rate, unsigned int *max_rate) ;
|
||
|
+int dvfs_clk_disable_limit(struct dvfs_node *clk_dvfs_node);
|
||
|
+int clk_disable_dvfs(struct dvfs_node *clk_dvfs_node);
|
||
|
+int clk_enable_dvfs(struct dvfs_node *clk_dvfs_node);
|
||
|
+void dvfs_disable_temp_limit(void);
|
||
|
+struct cpufreq_frequency_table *dvfs_get_freq_volt_table(struct dvfs_node *clk_dvfs_node);
|
||
|
+int rk_regist_vd(struct vd_node *vd);
|
||
|
+int rk_regist_pd(struct pd_node *pd);
|
||
|
+int rk_regist_clk(struct dvfs_node *clk_dvfs_node);
|
||
|
+struct regulator *dvfs_get_regulator(char *regulator_name);
|
||
|
+int of_dvfs_init(void);
|
||
|
+
|
||
|
+#else
|
||
|
+
|
||
|
+static inline struct dvfs_node *clk_get_dvfs_node(char *clk_name){ return NULL; };
|
||
|
+static inline void clk_put_dvfs_node(struct dvfs_node *clk_dvfs_node){ return; };
|
||
|
+static inline unsigned long dvfs_clk_get_rate(struct dvfs_node *clk_dvfs_node){ return 0; };
|
||
|
+static inline unsigned long dvfs_clk_get_last_set_rate(struct dvfs_node *clk_dvfs_node){ return 0; };
|
||
|
+static inline unsigned long dvfs_clk_round_rate(struct dvfs_node *clk_dvfs_node, unsigned long rate) { return 0; };
|
||
|
+static inline int dvfs_clk_set_rate(struct dvfs_node *clk_dvfs_node, unsigned long rate){ return 0; };
|
||
|
+static inline int dvfs_clk_enable(struct dvfs_node *clk_dvfs_node){ return 0; };
|
||
|
+static inline void dvfs_clk_disable(struct dvfs_node *clk_dvfs_node){ };
|
||
|
+static inline int dvfs_clk_prepare_enable(struct dvfs_node *clk_dvfs_node){ return 0; };
|
||
|
+static inline void dvfs_clk_disable_unprepare(struct dvfs_node *clk_dvfs_node){ };
|
||
|
+static inline int dvfs_set_freq_volt_table(struct dvfs_node *clk_dvfs_node, struct cpufreq_frequency_table *table){ return 0; };
|
||
|
+static inline int dvfs_clk_register_set_rate_callback(struct dvfs_node *clk_dvfs_node, clk_set_rate_callback clk_dvfs_target){ return 0; };
|
||
|
+static inline int dvfs_clk_enable_limit(struct dvfs_node *clk_dvfs_node, unsigned int min_rate, unsigned max_rate){ return 0; };
|
||
|
+static inline int dvfs_clk_get_limit(struct dvfs_node *clk_dvfs_node, unsigned int *min_rate, unsigned int *max_rate) { return 0; };
|
||
|
+static inline int dvfs_clk_disable_limit(struct dvfs_node *clk_dvfs_node){ return 0; };
|
||
|
+static inline int clk_disable_dvfs(struct dvfs_node *clk_dvfs_node){ return 0; };
|
||
|
+static inline int clk_enable_dvfs(struct dvfs_node *clk_dvfs_node){ return 0; };
|
||
|
+static inline void dvfs_disable_temp_limit(void) {};
|
||
|
+static inline struct cpufreq_frequency_table *dvfs_get_freq_volt_table(struct dvfs_node *clk_dvfs_node){ return NULL; };
|
||
|
+static inline int rk_regist_vd(struct vd_node *vd){ return 0; };
|
||
|
+static inline int rk_regist_pd(struct pd_node *pd){ return 0; };
|
||
|
+static inline int rk_regist_clk(struct dvfs_node *clk_dvfs_node){ return 0; };
|
||
|
+static inline struct regulator *dvfs_get_regulator(char *regulator_name){ return NULL; };
|
||
|
+static inline int of_dvfs_init(void){ return 0; };
|
||
|
+#endif
|
||
|
+
|
||
|
+#endif
|
||
|
diff --git a/include/linux/rockchip/grf.h b/include/linux/rockchip/grf.h
|
||
|
new file mode 100755
|
||
|
index 0000000..ab03372
|
||
|
--- /dev/null
|
||
|
+++ b/include/linux/rockchip/grf.h
|
||
|
@@ -0,0 +1,699 @@
|
||
|
+#ifndef __MACH_ROCKCHIP_GRF_H
|
||
|
+#define __MACH_ROCKCHIP_GRF_H
|
||
|
+
|
||
|
+#define RK3188_GRF_GPIO0L_DIR 0x0000
|
||
|
+#define RK3188_GRF_GPIO0H_DIR 0x0004
|
||
|
+#define RK3188_GRF_GPIO1L_DIR 0x0008
|
||
|
+#define RK3188_GRF_GPIO1H_DIR 0x000c
|
||
|
+#define RK3188_GRF_GPIO2L_DIR 0x0010
|
||
|
+#define RK3188_GRF_GPIO2H_DIR 0x0014
|
||
|
+#define RK3188_GRF_GPIO3L_DIR 0x0018
|
||
|
+#define RK3188_GRF_GPIO3H_DIR 0x001c
|
||
|
+#define RK3188_GRF_GPIO0L_DO 0x0020
|
||
|
+#define RK3188_GRF_GPIO0H_DO 0x0024
|
||
|
+#define RK3188_GRF_GPIO1L_DO 0x0028
|
||
|
+#define RK3188_GRF_GPIO1H_DO 0x002c
|
||
|
+#define RK3188_GRF_GPIO2L_DO 0x0030
|
||
|
+#define RK3188_GRF_GPIO2H_DO 0x0034
|
||
|
+#define RK3188_GRF_GPIO3L_DO 0x0038
|
||
|
+#define RK3188_GRF_GPIO3H_DO 0x003c
|
||
|
+#define RK3188_GRF_GPIO0L_EN 0x0040
|
||
|
+#define RK3188_GRF_GPIO0H_EN 0x0044
|
||
|
+#define RK3188_GRF_GPIO1L_EN 0x0048
|
||
|
+#define RK3188_GRF_GPIO1H_EN 0x004c
|
||
|
+#define RK3188_GRF_GPIO2L_EN 0x0050
|
||
|
+#define RK3188_GRF_GPIO2H_EN 0x0054
|
||
|
+#define RK3188_GRF_GPIO3L_EN 0x0058
|
||
|
+#define RK3188_GRF_GPIO3H_EN 0x005c
|
||
|
+
|
||
|
+#define RK3188_GRF_GPIO0C_IOMUX 0x0068
|
||
|
+#define RK3188_GRF_GPIO0D_IOMUX 0x006c
|
||
|
+#define RK3188_GRF_GPIO1A_IOMUX 0x0070
|
||
|
+#define RK3188_GRF_GPIO1B_IOMUX 0x0074
|
||
|
+#define RK3188_GRF_GPIO1C_IOMUX 0x0078
|
||
|
+#define RK3188_GRF_GPIO1D_IOMUX 0x007c
|
||
|
+#define RK3188_GRF_GPIO2A_IOMUX 0x0080
|
||
|
+#define RK3188_GRF_GPIO2B_IOMUX 0x0084
|
||
|
+#define RK3188_GRF_GPIO2C_IOMUX 0x0088
|
||
|
+#define RK3188_GRF_GPIO2D_IOMUX 0x008c
|
||
|
+#define RK3188_GRF_GPIO3A_IOMUX 0x0090
|
||
|
+#define RK3188_GRF_GPIO3B_IOMUX 0x0094
|
||
|
+#define RK3188_GRF_GPIO3C_IOMUX 0x0098
|
||
|
+#define RK3188_GRF_GPIO3D_IOMUX 0x009c
|
||
|
+#define RK3188_GRF_SOC_CON0 0x00a0
|
||
|
+#define RK3188_GRF_SOC_CON1 0x00a4
|
||
|
+#define RK3188_GRF_SOC_CON2 0x00a8
|
||
|
+#define RK3188_GRF_SOC_STATUS0 0x00ac
|
||
|
+#define RK3188_GRF_DMAC1_CON0 0x00b0
|
||
|
+#define RK3188_GRF_DMAC1_CON1 0x00b4
|
||
|
+#define RK3188_GRF_DMAC1_CON2 0x00b8
|
||
|
+#define RK3188_GRF_DMAC2_CON0 0x00bc
|
||
|
+#define RK3188_GRF_DMAC2_CON1 0x00c0
|
||
|
+#define RK3188_GRF_DMAC2_CON2 0x00c4
|
||
|
+#define RK3188_GRF_DMAC2_CON3 0x00c8
|
||
|
+#define RK3188_GRF_CPU_CON0 0x00cc
|
||
|
+#define RK3188_GRF_CPU_CON1 0x00d0
|
||
|
+#define RK3188_GRF_CPU_CON2 0x00d4
|
||
|
+#define RK3188_GRF_CPU_CON3 0x00d8
|
||
|
+#define RK3188_GRF_CPU_CON4 0x00dc
|
||
|
+#define RK3188_GRF_CPU_CON5 0x00e0
|
||
|
+
|
||
|
+#define RK3188_GRF_DDRC_CON0 0x00ec
|
||
|
+#define RK3188_GRF_DDRC_STAT 0x00f0
|
||
|
+#define RK3188_GRF_IO_CON0 0x00f4
|
||
|
+#define RK3188_GRF_IO_CON1 0x00f8
|
||
|
+#define RK3188_GRF_IO_CON2 0x00fc
|
||
|
+#define RK3188_GRF_IO_CON3 0x0100
|
||
|
+#define RK3188_GRF_IO_CON4 0x0104
|
||
|
+#define RK3188_GRF_SOC_STATUS1 0x0108
|
||
|
+#define RK3188_GRF_UOC0_CON0 0x010c
|
||
|
+#define RK3188_GRF_UOC0_CON1 0x0110
|
||
|
+#define RK3188_GRF_UOC0_CON2 0x0114
|
||
|
+#define RK3188_GRF_UOC0_CON3 0x0118
|
||
|
+#define RK3188_GRF_UOC1_CON0 0x011c
|
||
|
+#define RK3188_GRF_UOC1_CON1 0x0120
|
||
|
+#define RK3188_GRF_UOC1_CON2 0x0124
|
||
|
+#define RK3188_GRF_UOC1_CON3 0x0128
|
||
|
+#define RK3188_GRF_UOC2_CON0 0x012c
|
||
|
+#define RK3188_GRF_UOC2_CON1 0x0130
|
||
|
+
|
||
|
+#define RK3188_GRF_UOC3_CON0 0x0138
|
||
|
+#define RK3188_GRF_UOC3_CON1 0x013c
|
||
|
+#define RK3188_GRF_EHCI_STAT 0x0140
|
||
|
+#define RK3188_GRF_OS_REG0 0x0144
|
||
|
+#define RK3188_GRF_OS_REG1 0x0148
|
||
|
+#define RK3188_GRF_OS_REG2 0x014c
|
||
|
+#define RK3188_GRF_OS_REG3 0x0150
|
||
|
+#define RK3188_GRF_OS_REG4 0x0154
|
||
|
+#define RK3188_GRF_OS_REG5 0x0158
|
||
|
+#define RK3188_GRF_OS_REG6 0x015c
|
||
|
+#define RK3188_GRF_OS_REG7 0x0160
|
||
|
+#define RK3188_GRF_GPIO0B_PULL 0x0164
|
||
|
+#define RK3188_GRF_GPIO0C_PULL 0x0168
|
||
|
+#define RK3188_GRF_GPIO0D_PULL 0x016c
|
||
|
+#define RK3188_GRF_GPIO1A_PULL 0x0170
|
||
|
+#define RK3188_GRF_GPIO1B_PULL 0x0174
|
||
|
+#define RK3188_GRF_GPIO1C_PULL 0x0178
|
||
|
+#define RK3188_GRF_GPIO1D_PULL 0x017c
|
||
|
+#define RK3188_GRF_GPIO2A_PULL 0x0180
|
||
|
+#define RK3188_GRF_GPIO2B_PULL 0x0184
|
||
|
+#define RK3188_GRF_GPIO2C_PULL 0x0188
|
||
|
+#define RK3188_GRF_GPIO2D_PULL 0x018c
|
||
|
+#define RK3188_GRF_GPIO3A_PULL 0x0190
|
||
|
+#define RK3188_GRF_GPIO3B_PULL 0x0194
|
||
|
+#define RK3188_GRF_GPIO3C_PULL 0x0198
|
||
|
+#define RK3188_GRF_GPIO3D_PULL 0x019c
|
||
|
+#define RK3188_GRF_FLASH_DATA_PULL 0x01a0
|
||
|
+#define RK3188_GRF_FLASH_CMD_PULL 0x01a4
|
||
|
+
|
||
|
+
|
||
|
+#define RK3288_GRF_GPIO0_A_IOMUX 0x0084
|
||
|
+#define RK3288_GRF_GPIO0_B_IOMUX 0x0088
|
||
|
+#define RK3288_GRF_GPIO0_C_IOMUX 0x008c
|
||
|
+
|
||
|
+#define RK3288_GRF_GPIO1D_IOMUX 0x000c
|
||
|
+#define RK3288_GRF_GPIO2A_IOMUX 0x0010
|
||
|
+#define RK3288_GRF_GPIO2B_IOMUX 0x0014
|
||
|
+#define RK3288_GRF_GPIO2C_IOMUX 0x0018
|
||
|
+
|
||
|
+#define RK3288_GRF_GPIO3A_IOMUX 0x0020
|
||
|
+#define RK3288_GRF_GPIO3B_IOMUX 0x0024
|
||
|
+#define RK3288_GRF_GPIO3C_IOMUX 0x0028
|
||
|
+#define RK3288_GRF_GPIO3DL_IOMUX 0x002c
|
||
|
+#define RK3288_GRF_GPIO3DH_IOMUX 0x0030
|
||
|
+#define RK3288_GRF_GPIO4AL_IOMUX 0x0034
|
||
|
+#define RK3288_GRF_GPIO4AH_IOMUX 0x0038
|
||
|
+#define RK3288_GRF_GPIO4BL_IOMUX 0x003c
|
||
|
+
|
||
|
+#define RK3288_GRF_GPIO4C_IOMUX 0x0044
|
||
|
+#define RK3288_GRF_GPIO4D_IOMUX 0x0048
|
||
|
+
|
||
|
+#define RK3288_GRF_GPIO5B_IOMUX 0x0050
|
||
|
+#define RK3288_GRF_GPIO5C_IOMUX 0x0054
|
||
|
+
|
||
|
+#define RK3288_GRF_GPIO6A_IOMUX 0x005c
|
||
|
+#define RK3288_GRF_GPIO6B_IOMUX 0x0060
|
||
|
+#define RK3288_GRF_GPIO6C_IOMUX 0x0064
|
||
|
+
|
||
|
+#define RK3288_GRF_GPIO7A_IOMUX 0x006c
|
||
|
+#define RK3288_GRF_GPIO7B_IOMUX 0x0070
|
||
|
+#define RK3288_GRF_GPIO7CL_IOMUX 0x0074
|
||
|
+#define RK3288_GRF_GPIO7CH_IOMUX 0x0078
|
||
|
+
|
||
|
+#define RK3288_GRF_GPIO8A_IOMUX 0x0080
|
||
|
+#define RK3288_GRF_GPIO8B_IOMUX 0x0084
|
||
|
+
|
||
|
+#define RK3288_GRF_GPIO1H_SR 0x0104
|
||
|
+#define RK3288_GRF_GPIO2L_SR 0x0108
|
||
|
+#define RK3288_GRF_GPIO2H_SR 0x010c
|
||
|
+#define RK3288_GRF_GPIO3L_SR 0x0110
|
||
|
+#define RK3288_GRF_GPIO3H_SR 0x0114
|
||
|
+#define RK3288_GRF_GPIO4L_SR 0x0118
|
||
|
+#define RK3288_GRF_GPIO4H_SR 0x011c
|
||
|
+#define RK3288_GRF_GPIO5L_SR 0x0120
|
||
|
+#define RK3288_GRF_GPIO5H_SR 0x0124
|
||
|
+#define RK3288_GRF_GPIO6L_SR 0x0128
|
||
|
+#define RK3288_GRF_GPIO6H_SR 0x012c
|
||
|
+#define RK3288_GRF_GPIO7L_SR 0x0130
|
||
|
+#define RK3288_GRF_GPIO7H_SR 0x0134
|
||
|
+#define RK3288_GRF_GPIO8L_SR 0x0138
|
||
|
+
|
||
|
+#define RK3288_GRF_GPIO1D_P 0x014c
|
||
|
+#define RK3288_GRF_GPIO2A_P 0x0150
|
||
|
+#define RK3288_GRF_GPIO2B_P 0x0154
|
||
|
+#define RK3288_GRF_GPIO2C_P 0x0158
|
||
|
+
|
||
|
+#define RK3288_GRF_GPIO3A_P 0x0160
|
||
|
+#define RK3288_GRF_GPIO3B_P 0x0164
|
||
|
+#define RK3288_GRF_GPIO3C_P 0x0168
|
||
|
+#define RK3288_GRF_GPIO3D_P 0x016c
|
||
|
+#define RK3288_GRF_GPIO4A_P 0x0170
|
||
|
+#define RK3288_GRF_GPIO4B_P 0x0174
|
||
|
+#define RK3288_GRF_GPIO4C_P 0x0178
|
||
|
+#define RK3288_GRF_GPIO4D_P 0x017c
|
||
|
+
|
||
|
+#define RK3288_GRF_GPIO5B_P 0x0184
|
||
|
+#define RK3288_GRF_GPIO5C_P 0x0188
|
||
|
+
|
||
|
+#define RK3288_GRF_GPIO6A_P 0x0190
|
||
|
+#define RK3288_GRF_GPIO6B_P 0x0194
|
||
|
+#define RK3288_GRF_GPIO6C_P 0x0198
|
||
|
+
|
||
|
+#define RK3288_GRF_GPIO7A_P 0x01a0
|
||
|
+#define RK3288_GRF_GPIO7B_P 0x01a4
|
||
|
+#define RK3288_GRF_GPIO7C_P 0x01a8
|
||
|
+
|
||
|
+#define RK3288_GRF_GPIO8A_P 0x01b0
|
||
|
+#define RK3288_GRF_GPIO8B_P 0x01b4
|
||
|
+
|
||
|
+#define RK3288_GRF_GPIO1D_E 0x01cc
|
||
|
+#define RK3288_GRF_GPIO2A_E 0x01d0
|
||
|
+#define RK3288_GRF_GPIO2B_E 0x01d4
|
||
|
+#define RK3288_GRF_GPIO2C_E 0x01d8
|
||
|
+
|
||
|
+#define RK3288_GRF_GPIO3A_E 0x01e0
|
||
|
+#define RK3288_GRF_GPIO3B_E 0x01e4
|
||
|
+#define RK3288_GRF_GPIO3C_E 0x01e8
|
||
|
+#define RK3288_GRF_GPIO3D_E 0x01ec
|
||
|
+#define RK3288_GRF_GPIO4A_E 0x01f0
|
||
|
+#define RK3288_GRF_GPIO4B_E 0x01f4
|
||
|
+#define RK3288_GRF_GPIO4C_E 0x01f8
|
||
|
+#define RK3288_GRF_GPIO4D_E 0x01fc
|
||
|
+
|
||
|
+#define RK3288_GRF_GPIO5B_E 0x0204
|
||
|
+#define RK3288_GRF_GPIO5C_E 0x0208
|
||
|
+
|
||
|
+#define RK3288_GRF_GPIO6A_E 0x0210
|
||
|
+#define RK3288_GRF_GPIO6B_E 0x0214
|
||
|
+#define RK3288_GRF_GPIO6C_E 0x0218
|
||
|
+
|
||
|
+#define RK3288_GRF_GPIO7A_E 0x0220
|
||
|
+#define RK3288_GRF_GPIO7B_E 0x0224
|
||
|
+#define RK3288_GRF_GPIO7C_E 0x0228
|
||
|
+
|
||
|
+#define RK3288_GRF_GPIO8A_E 0x0230
|
||
|
+#define RK3288_GRF_GPIO8B_E 0x0234
|
||
|
+
|
||
|
+#define RK3288_GRF_GPIO_SMT 0x0240
|
||
|
+#define RK3288_GRF_SOC_CON0 0x0244
|
||
|
+#define RK3288_GRF_SOC_CON1 0x0248
|
||
|
+#define RK3288_GRF_SOC_CON2 0x024c
|
||
|
+#define RK3288_GRF_SOC_CON3 0x0250
|
||
|
+#define RK3288_GRF_SOC_CON4 0x0254
|
||
|
+#define RK3288_GRF_SOC_CON5 0x0258
|
||
|
+#define RK3288_GRF_SOC_CON6 0x025c
|
||
|
+#define RK3288_GRF_SOC_CON7 0x0260
|
||
|
+#define RK3288_GRF_SOC_CON8 0x0264
|
||
|
+#define RK3288_GRF_SOC_CON9 0x0268
|
||
|
+#define RK3288_GRF_SOC_CON10 0x026c
|
||
|
+#define RK3288_GRF_SOC_CON11 0x0270
|
||
|
+#define RK3288_GRF_SOC_CON12 0x0274
|
||
|
+#define RK3288_GRF_SOC_CON13 0x0278
|
||
|
+#define RK3288_GRF_SOC_CON14 0x027c
|
||
|
+#define RK3288_GRF_SOC_STATUS0 0x0280
|
||
|
+#define RK3288_GRF_SOC_STATUS1 0x0284
|
||
|
+#define RK3288_GRF_SOC_STATUS2 0x0288
|
||
|
+#define RK3288_GRF_SOC_STATUS3 0x028c
|
||
|
+#define RK3288_GRF_SOC_STATUS4 0x0290
|
||
|
+#define RK3288_GRF_SOC_STATUS5 0x0294
|
||
|
+#define RK3288_GRF_SOC_STATUS6 0x0298
|
||
|
+#define RK3288_GRF_SOC_STATUS7 0x029c
|
||
|
+#define RK3288_GRF_SOC_STATUS8 0x02a0
|
||
|
+#define RK3288_GRF_SOC_STATUS9 0x02a4
|
||
|
+#define RK3288_GRF_SOC_STATUS10 0x02a8
|
||
|
+#define RK3288_GRF_SOC_STATUS11 0x02ac
|
||
|
+#define RK3288_GRF_SOC_STATUS12 0x02b0
|
||
|
+#define RK3288_GRF_SOC_STATUS13 0x02b4
|
||
|
+#define RK3288_GRF_SOC_STATUS14 0x02b8
|
||
|
+#define RK3288_GRF_SOC_STATUS15 0x02bc
|
||
|
+#define RK3288_GRF_SOC_STATUS16 0x02c0
|
||
|
+#define RK3288_GRF_SOC_STATUS17 0x02c4
|
||
|
+#define RK3288_GRF_SOC_STATUS18 0x02c8
|
||
|
+#define RK3288_GRF_SOC_STATUS19 0x02cc
|
||
|
+#define RK3288_GRF_SOC_STATUS20 0x02d0
|
||
|
+#define RK3288_GRF_SOC_STATUS21 0x02d4
|
||
|
+
|
||
|
+#define RK3288_GRF_PERIDMAC_CON0 0x02e0
|
||
|
+#define RK3288_GRF_PERIDMAC_CON1 0x02e4
|
||
|
+#define RK3288_GRF_PERIDMAC_CON2 0x02e8
|
||
|
+#define RK3288_GRF_PERIDMAC_CON3 0x02ec
|
||
|
+#define RK3288_GRF_DDRC0_CON0 0x02f0
|
||
|
+#define RK3288_GRF_DDRC1_CON0 0x02f4
|
||
|
+#define RK3288_GRF_CPU_CON0 0x02f8
|
||
|
+#define RK3288_GRF_CPU_CON1 0x02fc
|
||
|
+#define RK3288_GRF_CPU_CON2 0x0300
|
||
|
+#define RK3288_GRF_CPU_CON3 0x0304
|
||
|
+#define RK3288_GRF_CPU_CON4 0x0308
|
||
|
+
|
||
|
+#define RK3288_GRF_CPU_STATUS0 0x0318
|
||
|
+
|
||
|
+#define RK3288_GRF_UOC0_CON0 0x0320
|
||
|
+#define RK3288_GRF_UOC0_CON1 0x0324
|
||
|
+#define RK3288_GRF_UOC0_CON2 0x0328
|
||
|
+#define RK3288_GRF_UOC0_CON3 0x032c
|
||
|
+#define RK3288_GRF_UOC0_CON4 0x0330
|
||
|
+#define RK3288_GRF_UOC1_CON0 0x0334
|
||
|
+#define RK3288_GRF_UOC1_CON1 0x0338
|
||
|
+#define RK3288_GRF_UOC1_CON2 0x033c
|
||
|
+#define RK3288_GRF_UOC1_CON3 0x0340
|
||
|
+#define RK3288_GRF_UOC1_CON4 0x0344
|
||
|
+#define RK3288_GRF_UOC2_CON0 0x0348
|
||
|
+#define RK3288_GRF_UOC2_CON1 0x034c
|
||
|
+#define RK3288_GRF_UOC2_CON2 0x0350
|
||
|
+#define RK3288_GRF_UOC2_CON3 0x0354
|
||
|
+#define RK3288_GRF_UOC3_CON0 0x0358
|
||
|
+#define RK3288_GRF_UOC3_CON1 0x035c
|
||
|
+#define RK3288_GRF_UOC4_CON0 0x0360
|
||
|
+#define RK3288_GRF_UOC4_CON1 0x0364
|
||
|
+#define RK3288_GRF_PVTM_CON0 0x0368
|
||
|
+#define RK3288_GRF_PVTM_CON1 0x036c
|
||
|
+#define RK3288_GRF_PVTM_CON2 0x0370
|
||
|
+#define RK3288_GRF_PVTM_STATUS0 0x0374
|
||
|
+#define RK3288_GRF_PVTM_STATUS1 0x0378
|
||
|
+#define RK3288_GRF_PVTM_STATUS2 0x037c
|
||
|
+#define RK3288_GRF_IO_VSEL 0x0380
|
||
|
+#define RK3288_GRF_SARADC_TESTBIT 0x0384
|
||
|
+#define RK3288_GRF_TSADC_TESTBIT_L 0x0388
|
||
|
+#define RK3288_GRF_TSADC_TESTBIT_H 0x038c
|
||
|
+#define RK3288_GRF_OS_REG0 0x0390
|
||
|
+#define RK3288_GRF_OS_REG1 0x0394
|
||
|
+#define RK3288_GRF_OS_REG2 0x0398
|
||
|
+#define RK3288_GRF_OS_REG3 0x039c
|
||
|
+
|
||
|
+#define RK3288_GRF_SOC_CON15 0x03a4
|
||
|
+#define RK3288_GRF_SOC_CON16 0x03a8
|
||
|
+
|
||
|
+#define RK3288_SGRF_SOC_CON0 0x0000
|
||
|
+#define RK3288_SGRF_SOC_CON1 0x0004
|
||
|
+#define RK3288_SGRF_SOC_CON2 0x0008
|
||
|
+#define RK3288_SGRF_SOC_CON3 0x000c
|
||
|
+#define RK3288_SGRF_SOC_CON4 0x0010
|
||
|
+#define RK3288_SGRF_SOC_CON5 0x0014
|
||
|
+
|
||
|
+#define RK3288_SGRF_BUSDMAC_CON0 0x0020
|
||
|
+#define RK3288_SGRF_BUSDMAC_CON1 0x0024
|
||
|
+
|
||
|
+#define RK3288_SGRF_CPU_CON0 0x0040
|
||
|
+#define RK3288_SGRF_CPU_CON1 0x0044
|
||
|
+#define RK3288_SGRF_CPU_CON2 0x0048
|
||
|
+
|
||
|
+#define RK3288_SGRF_SOC_CON6 0x0050
|
||
|
+#define RK3288_SGRF_SOC_CON7 0x0054
|
||
|
+#define RK3288_SGRF_SOC_CON8 0x0058
|
||
|
+#define RK3288_SGRF_SOC_CON9 0x005c
|
||
|
+#define RK3288_SGRF_SOC_CON10 0x0060
|
||
|
+#define RK3288_SGRF_SOC_CON11 0x0064
|
||
|
+#define RK3288_SGRF_SOC_CON12 0x0068
|
||
|
+#define RK3288_SGRF_SOC_CON13 0x006c
|
||
|
+#define RK3288_SGRF_SOC_CON14 0x0070
|
||
|
+#define RK3288_SGRF_SOC_CON15 0x0074
|
||
|
+#define RK3288_SGRF_SOC_CON16 0x0078
|
||
|
+#define RK3288_SGRF_SOC_CON17 0x007c
|
||
|
+#define RK3288_SGRF_SOC_CON18 0x0080
|
||
|
+#define RK3288_SGRF_SOC_CON19 0x0084
|
||
|
+#define RK3288_SGRF_SOC_CON20 0x0088
|
||
|
+#define RK3288_SGRF_SOC_CON21 0x008c
|
||
|
+
|
||
|
+#define RK3288_SGRF_SOC_STATUS0 0x0100
|
||
|
+#define RK3288_SGRF_SOC_STATUS1 0x0104
|
||
|
+
|
||
|
+#define RK3288_SGRF_FAST_BOOT_ADDR 0x0120
|
||
|
+
|
||
|
+
|
||
|
+#define RK3036_GRF_GPIO0A_IOMUX 0x000a8
|
||
|
+#define RK3036_GRF_GPIO0B_IOMUX 0x000ac
|
||
|
+#define RK3036_GRF_GPIO0C_IOMUX 0x000b0
|
||
|
+#define RK3036_GRF_GPIO0D_IOMUX 0x000b4
|
||
|
+#define RK3036_GRF_GPIO1A_IOMUX 0x000b8
|
||
|
+#define RK3036_GRF_GPIO1B_IOMUX 0x000bc
|
||
|
+#define RK3036_GRF_GPIO1C_IOMUX 0x000c0
|
||
|
+#define RK3036_GRF_GPIO1D_IOMUX 0x000c4
|
||
|
+#define RK3036_GRF_GPIO2A_IOMUX 0x000c8
|
||
|
+#define RK3036_GRF_GPIO2B_IOMUX 0x000cc
|
||
|
+#define RK3036_GRF_GPIO2C_IOMUX 0x000d0
|
||
|
+#define RK3036_GRF_GPIO2D_IOMUX 0x000d4
|
||
|
+#define RK3036_GRF_GPIO_DS 0x00100
|
||
|
+#define RK3036_GRF_GPIO0L_PULL 0x00118
|
||
|
+#define RK3036_GRF_GPIO0H_PULL 0x0011c
|
||
|
+#define RK3036_GRF_GPIO1L_PULL 0x00120
|
||
|
+#define RK3036_GRF_GPIO1H_PULL 0x00124
|
||
|
+
|
||
|
+#define RK3036_GRF_GPIO2L_PULL 0x00128
|
||
|
+#define RK3036_GRF_GPIO2H_PULL 0x0012c
|
||
|
+#define RK3036_GRF_SOC_CON0 0x00140
|
||
|
+#define RK3036_GRF_SOC_CON1 0x00144
|
||
|
+#define RK3036_GRF_SOC_CON2 0x00148
|
||
|
+#define RK3036_GRF_SOC_STATUS0 0x0014c
|
||
|
+#define RK3036_GRF_SOC_CON3 0x00154
|
||
|
+#define RK3036_GRF_DMAC_CON0 0x0015c
|
||
|
+#define RK3036_GRF_DMAC_CON1 0x00160
|
||
|
+#define RK3036_GRF_DMAC_CON2 0x00164
|
||
|
+#define RK3036_GRF_UOC0_CON5 0x0017c
|
||
|
+#define RK3036_GRF_UOC1_CON4 0x00190
|
||
|
+#define RK3036_GRF_UOC1_CON5 0x00194
|
||
|
+#define RK3036_GRF_DDRC_STAT 0x0019c
|
||
|
+#define RK3036_GRF_UOC_CON6 0x001a0
|
||
|
+#define RK3036_GRF_SOC_STATUS1 0x001a4
|
||
|
+#define RK3036_GRF_CPU_CON0 0x001a8
|
||
|
+#define RK3036_GRF_CPU_CON1 0x001ac
|
||
|
+#define RK3036_GRF_CPU_CON2 0x001b0
|
||
|
+#define RK3036_GRF_CPU_CON3 0x001b4
|
||
|
+#define RK3036_GRF_CPU_STATUS0 0x001c0
|
||
|
+#define RK3036_GRF_CPU_STATUS1 0x001c4
|
||
|
+#define RK3036_GRF_OS_REG0 0x001c8
|
||
|
+#define RK3036_GRF_OS_REG1 0x001cc
|
||
|
+#define RK3036_GRF_OS_REG2 0x001d0
|
||
|
+#define RK3036_GRF_OS_REG3 0x001d4
|
||
|
+#define RK3036_GRF_OS_REG4 0x001d8
|
||
|
+#define RK3036_GRF_OS_REG5 0x001dc
|
||
|
+#define RK3036_GRF_OS_REG6 0x001e0
|
||
|
+#define RK3036_GRF_OS_REG7 0x001e4
|
||
|
+#define RK3036_GRF_DLL_CON0 0x00200
|
||
|
+#define RK3036_GRF_DLL_CON1 0x00204
|
||
|
+#define RK3036_GRF_DLL_CON2 0x00208
|
||
|
+#define RK3036_GRF_DLL_CON3 0x0020c
|
||
|
+#define RK3036_GRF_DLL_STATUS0 0x00210
|
||
|
+#define RK3036_GRF_DLL_STATUS1 0x00214
|
||
|
+
|
||
|
+#define RK3036_GRF_DLL_STATUS2 0x00218
|
||
|
+#define RK3036_GRF_DLL_STATUS3 0x0021c
|
||
|
+#define RK3036_GRF_DFI_WRNUM 0x00220
|
||
|
+#define RK3036_GRF_DFI_RDNUM 0x00224
|
||
|
+#define RK3036_GRF_DFI_ACTNUM 0x00228
|
||
|
+#define RK3036_GRF_DFI_TIMERVAL 0x0022c
|
||
|
+#define RK3036_GRF_NIF_FIFO0 0x00230
|
||
|
+#define RK3036_GRF_NIF_FIFO1 0x00234
|
||
|
+#define RK3036_GRF_NIF_FIFO2 0x00238
|
||
|
+#define RK3036_GRF_NIF_FIFO3 0x0023c
|
||
|
+#define RK3036_GRF_USBPHY0_CON0 0x00280
|
||
|
+#define RK3036_GRF_USBPHY0_CON1 0x00284
|
||
|
+#define RK3036_GRF_USBPHY0_CON2 0x00288
|
||
|
+#define RK3036_GRF_USBPHY0_CON3 0x0028c
|
||
|
+#define RK3036_GRF_USBPHY0_CON4 0x00290
|
||
|
+#define RK3036_GRF_USBPHY0_CON5 0x00294
|
||
|
+#define RK3036_GRF_USBPHY0_CON6 0x00298
|
||
|
+#define RK3036_GRF_USBPHY0_CON7 0x0029c
|
||
|
+#define RK3036_GRF_USBPHY1_CON0 0x002a0
|
||
|
+#define RK3036_GRF_USBPHY1_CON1 0x002a4
|
||
|
+#define RK3036_GRF_USBPHY1_CON2 0x002a8
|
||
|
+#define RK3036_GRF_USBPHY1_CON3 0x002ac
|
||
|
+#define RK3036_GRF_USBPHY1_CON4 0x002b0
|
||
|
+#define RK3036_GRF_USBPHY1_CON5 0x002b4
|
||
|
+#define RK3036_GRF_USBPHY1_CON6 0x002b8
|
||
|
+
|
||
|
+#define RK3036_GRF_USBPHY1_CON7 0x002bc
|
||
|
+#define RK3036_GRF_CHIP_TAG 0x00300
|
||
|
+#define RK3036_GRF_SDMMC_DET_CNT 0x00304
|
||
|
+
|
||
|
+#define RK312X_GRF_GPIO0A_IOMUX 0x000a8
|
||
|
+#define RK312X_GRF_GPIO0B_IOMUX 0x000ac
|
||
|
+#define RK312X_GRF_GPIO0C_IOMUX 0x000b0
|
||
|
+#define RK312X_GRF_GPIO0D_IOMUX 0x000b4
|
||
|
+#define RK312X_GRF_GPIO1A_IOMUX 0x000b8
|
||
|
+#define RK312X_GRF_GPIO1B_IOMUX 0x000bc
|
||
|
+#define RK312X_GRF_GPIO1C_IOMUX 0x000c0
|
||
|
+#define RK312X_GRF_GPIO1D_IOMUX 0x000c4
|
||
|
+#define RK312X_GRF_GPIO2A_IOMUX 0x000c8
|
||
|
+#define RK312X_GRF_GPIO2B_IOMUX 0x000cc
|
||
|
+#define RK312X_GRF_GPIO2C_IOMUX 0x000d0
|
||
|
+#define RK312X_GRF_GPIO2D_IOMUX 0x000d4
|
||
|
+#define RK312X_GRF_GPIO3A_IOMUX 0x000d8
|
||
|
+#define RK312X_GRF_GPIO3B_IOMUX 0x000dc
|
||
|
+#define RK312X_GRF_GPIO3C_IOMUX 0x000e0
|
||
|
+#define RK312X_GRF_GPIO3D_IOMUX 0x000e4
|
||
|
+#define RK312X_GRF_CIF_IOMUX 0x000ec
|
||
|
+#define RK312X_GRF_CIF_IOMUX1 0x000f0
|
||
|
+#define RK312X_GRF_GPIO_DS 0x00100
|
||
|
+#define RK312X_GRF_GPIO0L_PULL 0x00118
|
||
|
+#define RK312X_GRF_GPIO0H_PULL 0x0011c
|
||
|
+#define RK312X_GRF_GPIO1L_PULL 0x00120
|
||
|
+#define RK312X_GRF_GPIO1H_PULL 0x00124
|
||
|
+#define RK312X_GRF_GPIO2L_PULL 0x00128
|
||
|
+#define RK312X_GRF_GPIO2H_PULL 0x0012c
|
||
|
+#define RK312X_GRF_GPIO3L_PULL 0x00130
|
||
|
+#define RK312X_GRF_GPIO3H_PULL 0x00134
|
||
|
+#define RK312X_GRF_ACODEC_CON 0x0013c
|
||
|
+
|
||
|
+#define RK312X_GRF_SOC_CON0 0x00140
|
||
|
+#define RK312X_GRF_SOC_CON1 0x00144
|
||
|
+#define RK312X_GRF_SOC_CON2 0x00148
|
||
|
+#define RK312X_GRF_SOC_STATUS0 0x0014c
|
||
|
+#define RK312X_GRF_LVDS_CON0 0x00150
|
||
|
+#define RK312X_GRF_SOC_CON3 0x00154
|
||
|
+#define RK312X_GRF_DMAC_CON0 0x0015c
|
||
|
+#define RK312X_GRF_DMAC_CON1 0x00160
|
||
|
+#define RK312X_GRF_DMAC_CON2 0x00164
|
||
|
+#define RK312X_GRF_MAC_CON0 0x00168
|
||
|
+#define RK312X_GRF_MAC_CON1 0x0016c
|
||
|
+#define RK312X_GRF_TVE_CON 0x00170
|
||
|
+#define RK312X_GRF_UOC0_CON0 0x0017c
|
||
|
+#define RK312X_GRF_UOC1_CON1 0x00184
|
||
|
+#define RK312X_GRF_UOC1_CON2 0x00188
|
||
|
+#define RK312X_GRF_UOC1_CON3 0x0018c
|
||
|
+#define RK312X_GRF_UOC1_CON4 0x00190
|
||
|
+#define RK312X_GRF_UOC1_CON5 0x00194
|
||
|
+#define RK312X_GRF_DDRC_STAT 0x0019c
|
||
|
+#define RK312X_GRF_SOC_STATUS1 0x001a4
|
||
|
+#define RK312X_GRF_CPU_CON0 0x001a8
|
||
|
+#define RK312X_GRF_CPU_CON1 0x001ac
|
||
|
+#define RK312X_GRF_CPU_CON2 0x001b0
|
||
|
+#define RK312X_GRF_CPU_CON3 0x001b4
|
||
|
+#define RK312X_GRF_CPU_STATUS0 0x001c0
|
||
|
+#define RK312X_GRF_CPU_STATUS1 0x001c4
|
||
|
+#define RK312X_GRF_OS_REG0 0x001c8
|
||
|
+#define RK312X_GRF_OS_REG1 0x001cc
|
||
|
+#define RK312X_GRF_OS_REG2 0x001d0
|
||
|
+#define RK312X_GRF_OS_REG3 0x001d4
|
||
|
+#define RK312X_GRF_OS_REG4 0x001d8
|
||
|
+#define RK312X_GRF_OS_REG5 0x001dc
|
||
|
+#define RK312X_GRF_OS_REG6 0x001e0
|
||
|
+#define RK312X_GRF_OS_REG7 0x001e4
|
||
|
+#define RK312X_GRF_PVTM_CON0 0x00200
|
||
|
+#define RK312X_GRF_PVTM_CON1 0x00204
|
||
|
+#define RK312X_GRF_PVTM_CON2 0x00208
|
||
|
+#define RK312X_GRF_PVTM_CON3 0x0020c
|
||
|
+#define RK312X_GRF_PVTM_STATUS0 0x00210
|
||
|
+#define RK312X_GRF_PVTM_STATUS1 0x00214
|
||
|
+#define RK312X_GRF_PVTM_STATUS2 0x00218
|
||
|
+#define RK312X_GRF_PVTM_STATUS3 0x0021c
|
||
|
+#define RK312X_GRF_DFI_WRNUM 0x00220
|
||
|
+#define RK312X_GRF_DFI_RDNUM 0x00224
|
||
|
+#define RK312X_GRF_DFI_ACTNUM 0x00228
|
||
|
+#define RK312X_GRF_DFI_TIMERVAL 0x0022c
|
||
|
+#define RK312X_GRF_NIF_FIFO0 0x00230
|
||
|
+#define RK312X_GRF_NIF_FIFO1 0x00234
|
||
|
+#define RK312X_GRF_NIF_FIFO2 0x00238
|
||
|
+#define RK312X_GRF_NIF_FIFO3 0x0023c
|
||
|
+#define RK312X_GRF_USBPHY0_CON0 0x00280
|
||
|
+#define RK312X_GRF_USBPHY0_CON1 0x00284
|
||
|
+#define RK312X_GRF_USBPHY0_CON2 0x00288
|
||
|
+#define RK312X_GRF_USBPHY0_CON3 0x0028c
|
||
|
+#define RK312X_GRF_USBPHY0_CON4 0x00290
|
||
|
+#define RK312X_GRF_USBPHY0_CON5 0x00294
|
||
|
+#define RK312X_GRF_USBPHY0_CON6 0x00298
|
||
|
+#define RK312X_GRF_USBPHY0_CON7 0x0029c
|
||
|
+#define RK312X_GRF_USBPHY1_CON0 0x002a0
|
||
|
+#define RK312X_GRF_USBPHY1_CON1 0x002a4
|
||
|
+#define RK312X_GRF_USBPHY1_CON2 0x002a8
|
||
|
+#define RK312X_GRF_USBPHY1_CON3 0x002ac
|
||
|
+#define RK312X_GRF_USBPHY1_CON4 0x002b0
|
||
|
+#define RK312X_GRF_USBPHY1_CON5 0x002b4
|
||
|
+#define RK312X_GRF_USBPHY1_CON6 0x002b8
|
||
|
+#define RK312X_GRF_USBPHY1_CON7 0x002bc
|
||
|
+#define RK312X_GRF_UOC_STATUS0 0x002c0
|
||
|
+#define RK312X_GRF_CHIP_TAG 0x00300
|
||
|
+#define RK312X_GRF_SDMMC_DET_CNT 0x00304
|
||
|
+#define RK312X_GRF_EFUSE_PRG_EN 0x0037c
|
||
|
+
|
||
|
+#define RK3228_GRF_GPIO0A_IOMUX 0x0000
|
||
|
+#define RK3228_GRF_GPIO0B_IOMUX 0x0004
|
||
|
+#define RK3228_GRF_GPIO0C_IOMUX 0x0008
|
||
|
+#define RK3228_GRF_GPIO0D_IOMUX 0x000c
|
||
|
+#define RK3228_GRF_GPIO1A_IOMUX 0x0010
|
||
|
+#define RK3228_GRF_GPIO1B_IOMUX 0x0014
|
||
|
+#define RK3228_GRF_GPIO1C_IOMUX 0x0018
|
||
|
+#define RK3228_GRF_GPIO1D_IOMUX 0x001c
|
||
|
+#define RK3228_GRF_GPIO2A_IOMUX 0x0020
|
||
|
+#define RK3228_GRF_GPIO2B_IOMUX 0x0024
|
||
|
+#define RK3228_GRF_GPIO2C_IOMUX 0x0028
|
||
|
+#define RK3228_GRF_GPIO2D_IOMUX 0x002c
|
||
|
+#define RK3228_GRF_GPIO3A_IOMUX 0x0030
|
||
|
+#define RK3228_GRF_GPIO3B_IOMUX 0x0034
|
||
|
+#define RK3228_GRF_GPIO3C_IOMUX 0x0038
|
||
|
+#define RK3228_GRF_GPIO3D_IOMUX 0x003c
|
||
|
+#define RK3228_GRF_COM_IOMUX 0x0050
|
||
|
+#define RK3228_GRF_GPIO0A_P 0x0100
|
||
|
+#define RK3228_GRF_GPIO0B_P 0x0104
|
||
|
+#define RK3228_GRF_GPIO0C_P 0x0108
|
||
|
+#define RK3228_GRF_GPIO0D_P 0x010c
|
||
|
+#define RK3228_GRF_GPIO1A_P 0x0110
|
||
|
+#define RK3228_GRF_GPIO1B_P 0x0114
|
||
|
+#define RK3228_GRF_GPIO1C_P 0x0118
|
||
|
+#define RK3228_GRF_GPIO1D_P 0x011c
|
||
|
+#define RK3228_GRF_GPIO2A_P 0x0120
|
||
|
+#define RK3228_GRF_GPIO2B_P 0x0124
|
||
|
+#define RK3228_GRF_GPIO2C_P 0x0128
|
||
|
+#define RK3228_GRF_GPIO2D_P 0x012c
|
||
|
+#define RK3228_GRF_GPIO3A_P 0x0130
|
||
|
+#define RK3228_GRF_GPIO3B_P 0x0134
|
||
|
+#define RK3228_GRF_GPIO3C_P 0x0138
|
||
|
+#define RK3228_GRF_GPIO3D_P 0x013c
|
||
|
+#define RK3228_GRF_GPIO0A_E 0x0200
|
||
|
+#define RK3228_GRF_GPIO0B_E 0x0204
|
||
|
+#define RK3228_GRF_GPIO0C_E 0x0208
|
||
|
+#define RK3228_GRF_GPIO0D_E 0x020c
|
||
|
+#define RK3228_GRF_GPIO1A_E 0x0210
|
||
|
+#define RK3228_GRF_GPIO1B_E 0x0214
|
||
|
+#define RK3228_GRF_GPIO1C_E 0x0218
|
||
|
+#define RK3228_GRF_GPIO1D_E 0x021c
|
||
|
+#define RK3228_GRF_GPIO2A_E 0x0220
|
||
|
+#define RK3228_GRF_GPIO2B_E 0x0224
|
||
|
+#define RK3228_GRF_GPIO2C_E 0x0228
|
||
|
+#define RK3228_GRF_GPIO2D_E 0x022c
|
||
|
+#define RK3228_GRF_GPIO3A_E 0x0230
|
||
|
+#define RK3228_GRF_GPIO3B_E 0x0234
|
||
|
+#define RK3228_GRF_GPIO3C_E 0x0238
|
||
|
+#define RK3228_GRF_GPIO3D_E 0x023c
|
||
|
+#define RK3228_GRF_GPIO0L_SR 0x0300
|
||
|
+#define RK3228_GRF_GPIO0H_SR 0x0304
|
||
|
+#define RK3228_GRF_GPIO1L_SR 0x0308
|
||
|
+#define RK3228_GRF_GPIO1H_SR 0x030c
|
||
|
+#define RK3228_GRF_GPIO2L_SR 0x0310
|
||
|
+#define RK3228_GRF_GPIO2H_SR 0x0314
|
||
|
+#define RK3228_GRF_GPIO3L_SR 0x0318
|
||
|
+#define RK3228_GRF_GPIO3H_SR 0x031c
|
||
|
+#define RK3228_GRF_GPIO0L_SMT 0x0380
|
||
|
+#define RK3228_GRF_GPIO0H_SMT 0x0384
|
||
|
+#define RK3228_GRF_GPIO1L_SMT 0x0388
|
||
|
+#define RK3228_GRF_GPIO1H_SMT 0x038c
|
||
|
+#define RK3228_GRF_GPIO2L_SMT 0x0390
|
||
|
+#define RK3228_GRF_GPIO2H_SMT 0x0394
|
||
|
+#define RK3228_GRF_GPIO3L_SMT 0x0398
|
||
|
+#define RK3228_GRF_GPIO3H_SMT 0x039c
|
||
|
+#define RK3228_GRF_SOC_CON0 0x0400
|
||
|
+#define RK3228_GRF_SOC_CON1 0x0404
|
||
|
+#define RK3228_GRF_SOC_CON2 0x0408
|
||
|
+#define RK3228_GRF_SOC_CON3 0x040c
|
||
|
+#define RK3228_GRF_SOC_CON4 0x0410
|
||
|
+#define RK3228_GRF_SOC_CON5 0x0414
|
||
|
+#define RK3228_GRF_SOC_CON6 0x0418
|
||
|
+#define RK3228_GRF_SOC_STATUS0 0x0480
|
||
|
+#define RK3228_GRF_SOC_STATUS1 0x0484
|
||
|
+#define RK3228_GRF_SOC_STATUS2 0x0488
|
||
|
+#define RK3228_GRF_CHIP_ID 0x048c
|
||
|
+#define RK3228_GRF_CPU_CON0 0x0500
|
||
|
+#define RK3228_GRF_CPU_CON1 0x0504
|
||
|
+#define RK3228_GRF_CPU_CON2 0x0508
|
||
|
+#define RK3228_GRF_CPU_CON3 0x050c
|
||
|
+#define RK3228_GRF_CPU_STATUS0 0x0520
|
||
|
+#define RK3228_GRF_CPU_STATUS1 0x0524
|
||
|
+#define RK3228_GRF_OS_REG0 0x05c8
|
||
|
+#define RK3228_GRF_OS_REG1 0x05cc
|
||
|
+#define RK3228_GRF_OS_REG2 0x05d0
|
||
|
+#define RK3228_GRF_OS_REG3 0x05d4
|
||
|
+#define RK3228_GRF_OS_REG4 0x05d8
|
||
|
+#define RK3228_GRF_OS_REG5 0x05dc
|
||
|
+#define RK3228_GRF_OS_REG6 0x05e0
|
||
|
+#define RK3228_GRF_OS_REG7 0x05e4
|
||
|
+#define RK3228_GRF_DDRC_STAT 0x0604
|
||
|
+#define RK3228_GRF_SIG_DETECT_CON 0x0680
|
||
|
+#define RK3228_GRF_SIG_DETECT_CON1 0x0684
|
||
|
+#define RK3228_GRF_SIG_DETECT_STATUS 0x0690
|
||
|
+#define RK3228_GRF_SIG_DETECT_STATUS1 0x0694
|
||
|
+#define RK3228_GRF_SIG_DETECT_CLR 0x06a0
|
||
|
+#define RK3228_GRF_SIG_DETECT_CLR1 0x06a4
|
||
|
+#define RK3228_GRF_EMMC_DET 0x06b0
|
||
|
+#define RK3228_GRF_HOST0_CON0 0x0700
|
||
|
+#define RK3228_GRF_HOST0_CON1 0x0704
|
||
|
+#define RK3228_GRF_HOST0_CON2 0x0708
|
||
|
+#define RK3228_GRF_HOST1_CON0 0x0710
|
||
|
+#define RK3228_GRF_HOST1_CON1 0x0714
|
||
|
+#define RK3228_GRF_HOST1_CON2 0x0718
|
||
|
+#define RK3228_GRF_HOST2_CON0 0x0720
|
||
|
+#define RK3228_GRF_HOST2_CON1 0x0724
|
||
|
+#define RK3228_GRF_HOST2_CON2 0x0728
|
||
|
+#define RK3228_GRF_USBPHY0_CON0 0x0760
|
||
|
+#define RK3228_GRF_USBPHY0_CON1 0x0764
|
||
|
+#define RK3228_GRF_USBPHY0_CON2 0x0768
|
||
|
+#define RK3228_GRF_USBPHY0_CON3 0x076c
|
||
|
+#define RK3228_GRF_USBPHY0_CON4 0x0770
|
||
|
+#define RK3228_GRF_USBPHY0_CON5 0x0774
|
||
|
+#define RK3228_GRF_USBPHY0_CON6 0x0778
|
||
|
+#define RK3228_GRF_USBPHY0_CON7 0x077c
|
||
|
+#define RK3228_GRF_USBPHY0_CON8 0x0780
|
||
|
+#define RK3228_GRF_USBPHY0_CON9 0x0784
|
||
|
+#define RK3228_GRF_USBPHY0_CON10 0x0788
|
||
|
+#define RK3228_GRF_USBPHY0_CON11 0x078c
|
||
|
+#define RK3228_GRF_USBPHY0_CON12 0x0790
|
||
|
+#define RK3228_GRF_USBPHY0_CON13 0x0794
|
||
|
+#define RK3228_GRF_USBPHY0_CON14 0x0798
|
||
|
+#define RK3228_GRF_USBPHY0_CON15 0x079c
|
||
|
+#define RK3228_GRF_USBPHY0_CON16 0x07a0
|
||
|
+#define RK3228_GRF_USBPHY0_CON17 0x07a4
|
||
|
+#define RK3228_GRF_USBPHY0_CON18 0x07a8
|
||
|
+#define RK3228_GRF_USBPHY0_CON19 0x07ac
|
||
|
+#define RK3228_GRF_USBPHY0_CON20 0x07b0
|
||
|
+#define RK3228_GRF_USBPHY0_CON21 0x07b4
|
||
|
+#define RK3228_GRF_USBPHY0_CON22 0x07b8
|
||
|
+#define RK3228_GRF_USBPHY0_CON23 0x07bc
|
||
|
+#define RK3228_GRF_USBPHY0_CON24 0x07c0
|
||
|
+#define RK3228_GRF_USBPHY0_CON25 0x07c4
|
||
|
+#define RK3228_GRF_USBPHY0_CON26 0x07c8
|
||
|
+#define RK3228_GRF_USBPHY1_CON0 0x0800
|
||
|
+#define RK3228_GRF_USBPHY1_CON1 0x0804
|
||
|
+#define RK3228_GRF_USBPHY1_CON2 0x0808
|
||
|
+#define RK3228_GRF_USBPHY1_CON3 0x080c
|
||
|
+#define RK3228_GRF_USBPHY1_CON4 0x0810
|
||
|
+#define RK3228_GRF_USBPHY1_CON5 0x0814
|
||
|
+#define RK3228_GRF_USBPHY1_CON6 0x0818
|
||
|
+#define RK3228_GRF_USBPHY1_CON7 0x081c
|
||
|
+#define RK3228_GRF_USBPHY1_CON8 0x0820
|
||
|
+#define RK3228_GRF_USBPHY1_CON9 0x0824
|
||
|
+#define RK3228_GRF_USBPHY1_CON10 0x0828
|
||
|
+#define RK3228_GRF_USBPHY1_CON11 0x082c
|
||
|
+#define RK3228_GRF_USBPHY1_CON12 0x0830
|
||
|
+#define RK3228_GRF_USBPHY1_CON13 0x0834
|
||
|
+#define RK3228_GRF_USBPHY1_CON14 0x0838
|
||
|
+#define RK3228_GRF_USBPHY1_CON15 0x083c
|
||
|
+#define RK3228_GRF_USBPHY1_CON16 0x0840
|
||
|
+#define RK3228_GRF_USBPHY1_CON17 0x0844
|
||
|
+#define RK3228_GRF_USBPHY1_CON18 0x0848
|
||
|
+#define RK3228_GRF_USBPHY1_CON19 0x084c
|
||
|
+#define RK3228_GRF_USBPHY1_CON20 0x0850
|
||
|
+#define RK3228_GRF_USBPHY1_CON21 0x0854
|
||
|
+#define RK3228_GRF_USBPHY1_CON22 0x0858
|
||
|
+#define RK3228_GRF_USBPHY1_CON23 0x085c
|
||
|
+#define RK3228_GRF_USBPHY1_CON24 0x0860
|
||
|
+#define RK3228_GRF_USBPHY1_CON25 0x0864
|
||
|
+#define RK3228_GRF_USBPHY1_CON26 0x0868
|
||
|
+#define RK3228_GRF_OTG_CON0 0x0880
|
||
|
+#define RK3228_GRF_UOC_CON0 0x0884
|
||
|
+#define RK3228_GRF_MAC_CON0 0x0900
|
||
|
+#define RK3228_GRF_MAC_CON1 0x0904
|
||
|
+#define RK3228_GRF_MACPHY_CON0 0x0b00
|
||
|
+#define RK3228_GRF_MACPHY_CON1 0x0b04
|
||
|
+#define RK3228_GRF_MACPHY_CON2 0x0b08
|
||
|
+#define RK3228_GRF_MACPHY_CON3 0x0b0c
|
||
|
+#define RK3228_GRF_MACPHY_STATUS 0x0b10
|
||
|
+
|
||
|
+#endif
|
||
|
diff --git a/include/linux/rockchip/iomap.h b/include/linux/rockchip/iomap.h
|
||
|
new file mode 100755
|
||
|
index 0000000..e6ffe50
|
||
|
--- /dev/null
|
||
|
+++ b/include/linux/rockchip/iomap.h
|
||
|
@@ -0,0 +1,228 @@
|
||
|
+#ifndef __MACH_ROCKCHIP_IOMAP_H
|
||
|
+#define __MACH_ROCKCHIP_IOMAP_H
|
||
|
+
|
||
|
+#ifndef __ASSEMBLY__
|
||
|
+#include <asm/io.h>
|
||
|
+#endif
|
||
|
+
|
||
|
+#ifdef IOMEM
|
||
|
+#define RK_IO_ADDRESS(x) IOMEM(0xFED00000 + x)
|
||
|
+#else
|
||
|
+#define RK_IO_ADDRESS(x) ((void __force __iomem *)(0xFED00000 + x))
|
||
|
+#endif
|
||
|
+
|
||
|
+#define RK_CRU_VIRT RK_IO_ADDRESS(0x00000000)
|
||
|
+#define RK_GRF_VIRT RK_IO_ADDRESS(0x00010000)
|
||
|
+#define RK_SGRF_VIRT (RK_GRF_VIRT + 0x1000)
|
||
|
+#define RK_PMU_VIRT RK_IO_ADDRESS(0x00020000)
|
||
|
+#define RK_ROM_VIRT RK_IO_ADDRESS(0x00030000)
|
||
|
+#define RK_EFUSE_VIRT RK_IO_ADDRESS(0x00040000)
|
||
|
+#define RK_GPIO_VIRT(n) RK_IO_ADDRESS(0x00050000 + (n) * 0x1000)
|
||
|
+#define RK_DEBUG_UART_VIRT RK_IO_ADDRESS(0x00060000)
|
||
|
+#define RK_CPU_AXI_BUS_VIRT RK_IO_ADDRESS(0x00070000)
|
||
|
+#define RK_TIMER_VIRT RK_IO_ADDRESS(0x00080000)
|
||
|
+#define RK_PWM_VIRT RK_IO_ADDRESS(0x00088000)
|
||
|
+#define RK_GIC_VIRT RK_IO_ADDRESS(0x00090000)
|
||
|
+#define RK_BOOTRAM_VIRT RK_IO_ADDRESS(0x000a0000)
|
||
|
+#define RK_DDR_VIRT RK_IO_ADDRESS(0x000d0000)
|
||
|
+
|
||
|
+#define RK3188_CRU_PHYS 0x20000000
|
||
|
+#define RK3188_CRU_SIZE SZ_4K
|
||
|
+#define RK3188_GRF_PHYS 0x20008000
|
||
|
+#define RK3188_GRF_SIZE SZ_4K
|
||
|
+#define RK3188_PMU_PHYS 0x20004000
|
||
|
+#define RK3188_PMU_SIZE SZ_4K
|
||
|
+#define RK3188_ROM_PHYS 0x10120000
|
||
|
+#define RK3188_ROM_SIZE SZ_16K
|
||
|
+#define RK3188_EFUSE_PHYS 0x20010000
|
||
|
+#define RK3188_EFUSE_SIZE SZ_4K
|
||
|
+#define RK3188_GPIO0_PHYS 0x2000a000
|
||
|
+#define RK3188_GPIO1_PHYS 0x2003c000
|
||
|
+#define RK3188_GPIO2_PHYS 0x2003e000
|
||
|
+#define RK3188_GPIO3_PHYS 0x20080000
|
||
|
+#define RK3188_GPIO_SIZE SZ_4K
|
||
|
+#define RK3188_CPU_AXI_BUS_PHYS 0x10128000
|
||
|
+#define RK3188_CPU_AXI_BUS_SIZE SZ_32K
|
||
|
+#define RK3188_TIMER0_PHYS 0x20038000
|
||
|
+#define RK3188_TIMER3_PHYS 0x2000e000
|
||
|
+#define RK3188_TIMER_SIZE SZ_4K
|
||
|
+#define RK3188_DDR_PCTL_PHYS 0x20020000
|
||
|
+#define RK3188_DDR_PCTL_SIZE SZ_4K
|
||
|
+#define RK3188_DDR_PUBL_PHYS 0x20040000
|
||
|
+#define RK3188_DDR_PUBL_SIZE SZ_4K
|
||
|
+#define RK3188_UART0_PHYS 0x10124000
|
||
|
+#define RK3188_UART1_PHYS 0x10126000
|
||
|
+#define RK3188_UART2_PHYS 0x20064000
|
||
|
+#define RK3188_UART3_PHYS 0x20068000
|
||
|
+#define RK3188_UART_SIZE SZ_4K
|
||
|
+
|
||
|
+#define RK3288_CRU_PHYS 0xFF760000
|
||
|
+#define RK3288_CRU_SIZE SZ_4K
|
||
|
+#define RK3288_GRF_PHYS 0xFF770000
|
||
|
+#define RK3288_GRF_SIZE SZ_4K
|
||
|
+#define RK3288_SGRF_PHYS 0xFF740000
|
||
|
+#define RK3288_SGRF_SIZE SZ_4K
|
||
|
+#define RK3288_PMU_PHYS 0xFF730000
|
||
|
+#define RK3288_PMU_SIZE SZ_4K
|
||
|
+#define RK3288_ROM_PHYS 0xFFFD0000
|
||
|
+#define RK3288_ROM_SIZE (SZ_16K + SZ_4K)
|
||
|
+#define RK3288_EFUSE_PHYS 0xFFB40000
|
||
|
+#define RK3288_EFUSE_SIZE SZ_4K
|
||
|
+#define RK3288_GPIO0_PHYS 0xFF750000
|
||
|
+#define RK3288_GPIO1_PHYS 0xFF780000
|
||
|
+#define RK3288_GPIO2_PHYS 0xFF790000
|
||
|
+#define RK3288_GPIO3_PHYS 0xFF7A0000
|
||
|
+#define RK3288_GPIO4_PHYS 0xFF7B0000
|
||
|
+#define RK3288_GPIO5_PHYS 0xFF7C0000
|
||
|
+#define RK3288_GPIO6_PHYS 0xFF7D0000
|
||
|
+#define RK3288_GPIO7_PHYS 0xFF7E0000
|
||
|
+#define RK3288_GPIO8_PHYS 0xFF7F0000
|
||
|
+#define RK3288_GPIO_SIZE SZ_4K
|
||
|
+#define RK3288_SERVICE_CORE_PHYS 0XFFA80000
|
||
|
+#define RK3288_SERVICE_CORE_SIZE SZ_4K
|
||
|
+#define RK3288_SERVICE_DMAC_PHYS 0XFFA90000
|
||
|
+#define RK3288_SERVICE_DMAC_SIZE SZ_4K
|
||
|
+#define RK3288_SERVICE_GPU_PHYS 0XFFAA0000
|
||
|
+#define RK3288_SERVICE_GPU_SIZE SZ_4K
|
||
|
+#define RK3288_SERVICE_PERI_PHYS 0XFFAB0000
|
||
|
+#define RK3288_SERVICE_PERI_SIZE SZ_4K
|
||
|
+#define RK3288_SERVICE_BUS_PHYS 0XFFAC0000
|
||
|
+#define RK3288_SERVICE_BUS_SIZE SZ_16K
|
||
|
+#define RK3288_SERVICE_VIO_PHYS 0XFFAD0000
|
||
|
+#define RK3288_SERVICE_VIO_SIZE SZ_4K
|
||
|
+#define RK3288_SERVICE_VIDEO_PHYS 0XFFAE0000
|
||
|
+#define RK3288_SERVICE_VIDEO_SIZE SZ_4K
|
||
|
+#define RK3288_SERVICE_HEVC_PHYS 0XFFAF0000
|
||
|
+#define RK3288_SERVICE_HEVC_SIZE SZ_4K
|
||
|
+#define RK3288_TIMER0_PHYS 0xFF6B0000
|
||
|
+#define RK3288_TIMER6_PHYS 0xFF810000
|
||
|
+#define RK3288_TIMER_SIZE SZ_4K
|
||
|
+#define RK3288_DDR_PCTL0_PHYS 0xFF610000
|
||
|
+#define RK3288_DDR_PCTL1_PHYS 0xFF630000
|
||
|
+#define RK3288_DDR_PCTL_SIZE SZ_4K
|
||
|
+#define RK3288_DDR_PUBL0_PHYS 0xFF620000
|
||
|
+#define RK3288_DDR_PUBL1_PHYS 0xFF640000
|
||
|
+#define RK3288_DDR_PUBL_SIZE SZ_4K
|
||
|
+#define RK3288_UART_BT_PHYS 0xFF180000
|
||
|
+#define RK3288_UART_BB_PHYS 0xFF190000
|
||
|
+#define RK3288_UART_DBG_PHYS 0xFF690000
|
||
|
+#define RK3288_UART_GPS_PHYS 0xFF1B0000
|
||
|
+#define RK3288_UART_EXP_PHYS 0xFF1C0000
|
||
|
+#define RK3288_UART_SIZE SZ_4K
|
||
|
+#define RK3288_GIC_DIST_PHYS 0xFFC01000
|
||
|
+#define RK3288_GIC_DIST_SIZE SZ_4K
|
||
|
+#define RK3288_GIC_CPU_PHYS 0xFFC02000
|
||
|
+#define RK3288_GIC_CPU_SIZE SZ_4K
|
||
|
+#define RK3288_BOOTRAM_PHYS 0xFF720000
|
||
|
+#define RK3288_BOOTRAM_SIZE SZ_4K
|
||
|
+#define RK3288_IMEM_PHYS 0xFF700000
|
||
|
+#define RK3288_IMEM_SZIE 0x00018000
|
||
|
+
|
||
|
+#define RK3036_IMEM_PHYS 0x10080000
|
||
|
+#define RK3036_IMEM_SIZE SZ_8K
|
||
|
+#define RK3036_ROM_PHYS 0x10100000
|
||
|
+#define RK3036_ROM_SIZE SZ_16K
|
||
|
+#define RK3036_CPU_AXI_BUS_PHYS 0x10128000
|
||
|
+#define RK3036_CPU_AXI_BUS_SIZE SZ_32K
|
||
|
+#define RK3036_GIC_DIST_PHYS 0x10139000
|
||
|
+#define RK3036_GIC_DIST_SIZE SZ_4K
|
||
|
+#define RK3036_GIC_CPU_PHYS 0x1013a000
|
||
|
+#define RK3036_GIC_CPU_SIZE SZ_4K
|
||
|
+#define RK3036_CRU_PHYS 0x20000000
|
||
|
+#define RK3036_CRU_SIZE SZ_4K
|
||
|
+#define RK3036_DDR_PCTL_PHYS 0x20004000
|
||
|
+#define RK3036_DDR_PCTL_SIZE SZ_4K
|
||
|
+#define RK3036_GRF_PHYS 0x20008000
|
||
|
+#define RK3036_GRF_SIZE SZ_4K
|
||
|
+#define RK3036_DDR_PHY_PHYS 0x2000a000
|
||
|
+#define RK3036_DDR_PHY_SIZE SZ_4K
|
||
|
+#define RK3036_TIMER_PHYS 0x20044000
|
||
|
+#define RK3036_TIMER_SIZE SZ_4K
|
||
|
+#define RK3036_UART0_PHYS 0x20060000
|
||
|
+#define RK3036_UART1_PHYS 0x20064000
|
||
|
+#define RK3036_UART2_PHYS 0x20068000
|
||
|
+#define RK3036_UART_SIZE SZ_4K
|
||
|
+#define RK3036_GPIO0_PHYS 0x2007c000
|
||
|
+#define RK3036_GPIO1_PHYS 0x20080000
|
||
|
+#define RK3036_GPIO2_PHYS 0x20084000
|
||
|
+#define RK3036_GPIO_SIZE SZ_4K
|
||
|
+#define RK3036_EFUSE_PHYS 0x20090000
|
||
|
+#define RK3036_EFUSE_SIZE SZ_4K
|
||
|
+#define RK3036_PWM_PHYS 0x20050000
|
||
|
+#define RK3036_PWM_SIZE SZ_16K
|
||
|
+
|
||
|
+#define RK312X_IMEM_PHYS RK3036_IMEM_PHYS
|
||
|
+#define RK312X_IMEM_SIZE RK3036_IMEM_SIZE
|
||
|
+#define RK312X_ROM_PHYS RK3036_ROM_PHYS
|
||
|
+#define RK312X_ROM_SIZE RK3036_ROM_SIZE
|
||
|
+#define RK312X_CPU_AXI_BUS_PHYS RK3036_CPU_AXI_BUS_PHYS
|
||
|
+#define RK312X_CPU_AXI_BUS_SIZE RK3036_CPU_AXI_BUS_SIZE
|
||
|
+#define RK312X_GIC_DIST_PHYS RK3036_GIC_DIST_PHYS
|
||
|
+#define RK312X_GIC_DIST_SIZE RK3036_GIC_DIST_SIZE
|
||
|
+#define RK312X_GIC_CPU_PHYS RK3036_GIC_CPU_PHYS
|
||
|
+#define RK312X_GIC_CPU_SIZE RK3036_GIC_CPU_SIZE
|
||
|
+#define RK312X_CRU_PHYS RK3036_CRU_PHYS
|
||
|
+#define RK312X_CRU_SIZE RK3036_CRU_SIZE
|
||
|
+#define RK312X_DDR_PCTL_PHYS RK3036_DDR_PCTL_PHYS
|
||
|
+#define RK312X_DDR_PCTL_SIZE RK3036_DDR_PCTL_SIZE
|
||
|
+#define RK312X_GRF_PHYS RK3036_GRF_PHYS
|
||
|
+#define RK312X_GRF_SIZE RK3036_GRF_SIZE
|
||
|
+#define RK312X_DDR_PHY_PHYS RK3036_DDR_PHY_PHYS
|
||
|
+#define RK312X_DDR_PHY_SIZE RK3036_DDR_PHY_SIZE
|
||
|
+#define RK312X_TIMER_PHYS RK3036_TIMER_PHYS
|
||
|
+#define RK312X_TIMER_SIZE RK3036_TIMER_SIZE
|
||
|
+#define RK312X_UART0_PHYS RK3036_UART0_PHYS
|
||
|
+#define RK312X_UART1_PHYS RK3036_UART1_PHYS
|
||
|
+#define RK312X_UART2_PHYS RK3036_UART2_PHYS
|
||
|
+#define RK312X_UART_SIZE RK3036_UART_SIZE
|
||
|
+#define RK312X_GPIO0_PHYS RK3036_GPIO0_PHYS
|
||
|
+#define RK312X_GPIO1_PHYS RK3036_GPIO1_PHYS
|
||
|
+#define RK312X_GPIO2_PHYS RK3036_GPIO2_PHYS
|
||
|
+#define RK312X_GPIO3_PHYS 0x20088000
|
||
|
+#define RK312X_GPIO_SIZE RK3036_GPIO_SIZE
|
||
|
+#define RK312X_EFUSE_PHYS RK3036_EFUSE_PHYS
|
||
|
+#define RK312X_EFUSE_SIZE RK3036_EFUSE_SIZE
|
||
|
+#define RK312X_PMU_PHYS 0x100a0000
|
||
|
+#define RK312X_PMU_SIZE SZ_64K
|
||
|
+#define RK312X_PWM_PHYS 0x20050000
|
||
|
+#define RK312X_PWM_SIZE SZ_16K
|
||
|
+
|
||
|
+#define RK3228_IMEM_PHYS RK3036_IMEM_PHYS
|
||
|
+#define RK3228_IMEM_SIZE SZ_32K
|
||
|
+#define RK3228_ROM_PHYS RK3036_ROM_PHYS
|
||
|
+#define RK3228_ROM_SIZE RK3036_ROM_SIZE
|
||
|
+#define RK3228_CPU_AXI_BUS_PHYS 0x31000000
|
||
|
+#define RK3228_CPU_AXI_BUS_SIZE SZ_32K
|
||
|
+#define RK3228_GIC_DIST_PHYS 0x32011000
|
||
|
+#define RK3228_GIC_DIST_SIZE SZ_4K
|
||
|
+#define RK3228_GIC_CPU_PHYS 0x32012000
|
||
|
+#define RK3228_GIC_CPU_SIZE SZ_4K
|
||
|
+#define RK3228_CRU_PHYS 0x110e0000
|
||
|
+#define RK3228_CRU_SIZE SZ_4K
|
||
|
+#define RK3228_DDR_PCTL_PHYS 0x11200000
|
||
|
+#define RK3228_DDR_PCTL_SIZE SZ_4K
|
||
|
+#define RK3228_GRF_PHYS 0x11000000
|
||
|
+#define RK3228_GRF_SIZE SZ_4K
|
||
|
+#define RK3228_SGRF_PHYS 0x10140000
|
||
|
+#define RK3228_SGRF_SIZE SZ_4K
|
||
|
+#define RK3228_DDR_PHY_PHYS 0x12000000
|
||
|
+#define RK3228_DDR_PHY_SIZE SZ_4K
|
||
|
+#define RK3228_TIMER_PHYS 0x110c0000
|
||
|
+#define RK3228_TIMER_SIZE SZ_4K
|
||
|
+#define RK3228_STIMER_PHYS 0x110d0000
|
||
|
+#define RK3228_STIMER_SIZE SZ_4K
|
||
|
+#define RK3228_UART0_PHYS 0x11010000
|
||
|
+#define RK3228_UART1_PHYS 0x11020000
|
||
|
+#define RK3228_UART2_PHYS 0x11030000
|
||
|
+#define RK3228_UART_SIZE SZ_4K
|
||
|
+#define RK3228_GPIO0_PHYS 0x11110000
|
||
|
+#define RK3228_GPIO1_PHYS 0x11120000
|
||
|
+#define RK3228_GPIO2_PHYS 0x11130000
|
||
|
+#define RK3228_GPIO3_PHYS 0x11140000
|
||
|
+#define RK3228_GPIO_SIZE SZ_4K
|
||
|
+#define RK3228_EFUSE_PHYS 0x11040000
|
||
|
+#define RK3228_EFUSE_SIZE SZ_4K
|
||
|
+#define RK3228_PWM_PHYS 0x110b0000
|
||
|
+#define RK3228_PWM_SIZE SZ_16K
|
||
|
+
|
||
|
+#endif
|
||
|
diff --git a/include/linux/rockchip/pmu.h b/include/linux/rockchip/pmu.h
|
||
|
new file mode 100644
|
||
|
index 0000000..0092edf
|
||
|
--- /dev/null
|
||
|
+++ b/include/linux/rockchip/pmu.h
|
||
|
@@ -0,0 +1,140 @@
|
||
|
+#ifndef __MACH_ROCKCHIP_PMU_H
|
||
|
+#define __MACH_ROCKCHIP_PMU_H
|
||
|
+
|
||
|
+#define RK3188_PMU_WAKEUP_CFG0 0x00
|
||
|
+#define RK3188_PMU_WAKEUP_CFG1 0x04
|
||
|
+#define RK3188_PMU_PWRDN_CON 0x08
|
||
|
+#define RK3188_PMU_PWRDN_ST 0x0c
|
||
|
+#define RK3188_PMU_INT_CON 0x10
|
||
|
+#define RK3188_PMU_INT_ST 0x14
|
||
|
+#define RK3188_PMU_MISC_CON 0x18
|
||
|
+#define RK3188_PMU_OSC_CNT 0x1c
|
||
|
+#define RK3188_PMU_PLL_CNT 0x20
|
||
|
+#define RK3188_PMU_PMU_CNT 0x24
|
||
|
+#define RK3188_PMU_DDRIO_PWRON_CNT 0x28
|
||
|
+#define RK3188_PMU_WAKEUP_RST_CLR_CNT 0x2c
|
||
|
+#define RK3188_PMU_SCU_PWRDWN_CNT 0x30
|
||
|
+#define RK3188_PMU_SCU_PWRUP_CNT 0x34
|
||
|
+#define RK3188_PMU_MISC_CON1 0x38
|
||
|
+#define RK3188_PMU_GPIO0_CON 0x3c
|
||
|
+#define RK3188_PMU_SYS_REG0 0x40
|
||
|
+#define RK3188_PMU_SYS_REG1 0x44
|
||
|
+#define RK3188_PMU_SYS_REG2 0x48
|
||
|
+#define RK3188_PMU_SYS_REG3 0x4c
|
||
|
+#define RK3188_PMU_STOP_INT_DLY 0x60
|
||
|
+#define RK3188_PMU_GPIO0A_PULL 0x64
|
||
|
+#define RK3188_PMU_GPIO0B_PULL 0x68
|
||
|
+
|
||
|
+#define RK3288_PMU_WAKEUP_CFG0 0x00
|
||
|
+#define RK3288_PMU_WAKEUP_CFG1 0x04
|
||
|
+#define RK3288_PMU_PWRDN_CON 0x08
|
||
|
+#define RK3288_PMU_PWRDN_ST 0x0c
|
||
|
+#define RK3288_PMU_IDLE_REQ 0x10
|
||
|
+#define RK3288_PMU_IDLE_ST 0x14
|
||
|
+#define RK3288_PMU_PWRMODE_CON 0x18
|
||
|
+#define RK3288_PMU_PWR_STATE 0x1c
|
||
|
+#define RK3288_PMU_OSC_CNT 0x20
|
||
|
+#define RK3288_PMU_PLL_CNT 0x24
|
||
|
+#define RK3288_PMU_STABL_CNT 0x28
|
||
|
+#define RK3288_PMU_DDR0IO_PWRON_CNT 0x2c
|
||
|
+#define RK3288_PMU_DDR1IO_PWRON_CNT 0x30
|
||
|
+#define RK3288_PMU_CORE_PWRDWN_CNT 0x34
|
||
|
+#define RK3288_PMU_CORE_PWRUP_CNT 0x38
|
||
|
+#define RK3288_PMU_GPU_PWRDWN_CNT 0x3c
|
||
|
+#define RK3288_PMU_GPU_PWRUP_CNT 0x40
|
||
|
+#define RK3288_PMU_WAKEUP_RST_CLR_CNT 0x44
|
||
|
+#define RK3288_PMU_SFT_CON 0x48
|
||
|
+#define RK3288_PMU_DDR_SREF_ST 0x4c
|
||
|
+#define RK3288_PMU_INT_CON 0x50
|
||
|
+#define RK3288_PMU_INT_ST 0x54
|
||
|
+#define RK3288_PMU_BOOT_ADDR_SEL 0x58
|
||
|
+#define RK3288_PMU_GRF_CON 0x5c
|
||
|
+#define RK3288_PMU_GPIO_SR 0x60
|
||
|
+#define RK3288_PMU_GPIO0_A_PULL 0x64
|
||
|
+#define RK3288_PMU_GPIO0_B_PULL 0x68
|
||
|
+#define RK3288_PMU_GPIO0_C_PULL 0x6c
|
||
|
+#define RK3288_PMU_GPIO0_A_DRV 0x70
|
||
|
+#define RK3288_PMU_GPIO0_B_DRV 0x74
|
||
|
+#define RK3288_PMU_GPIO0_C_DRV 0x78
|
||
|
+#define RK3288_PMU_GPIO_OP 0x7c
|
||
|
+#define RK3288_PMU_GPIO0_SEL18 0x80
|
||
|
+#define RK3288_PMU_GPIO0_A_IOMUX 0x84
|
||
|
+#define RK3288_PMU_GPIO0_B_IOMUX 0x88
|
||
|
+#define RK3288_PMU_GPIO0_C_IOMUX 0x8c
|
||
|
+#define RK3288_PMU_PWRMODE_CON1 0x90
|
||
|
+#define RK3288_PMU_SYS_REG0 0x94
|
||
|
+#define RK3288_PMU_SYS_REG1 0x98
|
||
|
+#define RK3288_PMU_SYS_REG2 0x9c
|
||
|
+#define RK3288_PMU_SYS_REG3 0xa0
|
||
|
+
|
||
|
+#define RK312X_PMU_WAKEUP_CFG 0x00
|
||
|
+#define RK312X_PMU_PWRDN_CON 0x04
|
||
|
+#define RK312X_PMU_PWRDN_ST 0x08
|
||
|
+#define RK312X_PMU_IDLE_REQ 0x0C
|
||
|
+#define RK312X_PMU_IDLE_ST 0x10
|
||
|
+#define RK312X_PMU_PWRMODE_CON 0x14
|
||
|
+#define RK312X_PMU_PWR_STATE 0x18
|
||
|
+#define RK312X_PMU_OSC_CNT 0x1C
|
||
|
+#define RK312X_PMU_CORE_PWRDWN_CNT 0x20
|
||
|
+#define RK312X_PMU_CORE_PWRUP_CNT 0x24
|
||
|
+#define RK312X_PMU_SFT_CON 0x28
|
||
|
+#define RK312X_PMU_DDR_SREF_ST 0x2C
|
||
|
+#define RK312X_PMU_INT_CON 0x30
|
||
|
+#define RK312X_PMU_INT_ST 0x34
|
||
|
+#define RK312X_PMU_SYS_REG0 0x38
|
||
|
+#define RK312X_PMU_SYS_REG1 0x3C
|
||
|
+#define RK312X_PMU_SYS_REG2 0x40
|
||
|
+#define RK312X_PMU_SYS_REG3 0x44
|
||
|
+
|
||
|
+#define RK3368_PMU_PWRDN_CON 0x0c
|
||
|
+#define RK3368_PMU_PWRDN_ST 0x10
|
||
|
+#define RK3368_PMU_IDLE_REQ 0x3c
|
||
|
+#define RK3368_PMU_IDLE_ST 0x40
|
||
|
+
|
||
|
+enum pmu_power_domain {
|
||
|
+ PD_BCPU,
|
||
|
+ PD_BDSP,
|
||
|
+ PD_BUS,
|
||
|
+ PD_CPU_0,
|
||
|
+ PD_CPU_1,
|
||
|
+ PD_CPU_2,
|
||
|
+ PD_CPU_3,
|
||
|
+ PD_CS,
|
||
|
+ PD_GPU,
|
||
|
+ PD_HEVC,
|
||
|
+ PD_PERI,
|
||
|
+ PD_SCU,
|
||
|
+ PD_VIDEO,
|
||
|
+ PD_VIO,
|
||
|
+ PD_GPU_0,
|
||
|
+ PD_GPU_1,
|
||
|
+};
|
||
|
+
|
||
|
+enum pmu_idle_req {
|
||
|
+ IDLE_REQ_ALIVE,
|
||
|
+ IDLE_REQ_AP2BP,
|
||
|
+ IDLE_REQ_BP2AP,
|
||
|
+ IDLE_REQ_BUS,
|
||
|
+ IDLE_REQ_CORE,
|
||
|
+ IDLE_REQ_CPUP,
|
||
|
+ IDLE_REQ_DMA,
|
||
|
+ IDLE_REQ_GPU,
|
||
|
+ IDLE_REQ_HEVC,
|
||
|
+ IDLE_REQ_PERI,
|
||
|
+ IDLE_REQ_VIDEO,
|
||
|
+ IDLE_REQ_VIO,
|
||
|
+ IDLE_REQ_SYS,
|
||
|
+ IDLE_REQ_MSCH,
|
||
|
+ IDLE_REQ_CRYPTO,
|
||
|
+};
|
||
|
+
|
||
|
+struct rockchip_pmu_operations {
|
||
|
+ int (*set_power_domain)(enum pmu_power_domain pd, bool on);
|
||
|
+ bool (*power_domain_is_on)(enum pmu_power_domain pd);
|
||
|
+ int (*set_idle_request)(enum pmu_idle_req req, bool idle);
|
||
|
+};
|
||
|
+
|
||
|
+int rockchip_pmu_set_idle_request(struct device *dev, bool idle);
|
||
|
+extern struct rockchip_pmu_operations rockchip_pmu_ops;
|
||
|
+
|
||
|
+#endif
|
||
|
diff --git a/include/linux/rockchip/psci.h b/include/linux/rockchip/psci.h
|
||
|
new file mode 100644
|
||
|
index 0000000..7a3eed6
|
||
|
--- /dev/null
|
||
|
+++ b/include/linux/rockchip/psci.h
|
||
|
@@ -0,0 +1,75 @@
|
||
|
+#ifndef __ROCKCHIP_PSCI_H
|
||
|
+#define __ROCKCHIP_PSCI_H
|
||
|
+
|
||
|
+#define SEC_REG_RD (0x0)
|
||
|
+#define SEC_REG_WR (0x1)
|
||
|
+
|
||
|
+/*
|
||
|
+ * trust firmware verison
|
||
|
+ */
|
||
|
+#define RKTF_VER_MAJOR(ver) (((ver) >> 16) & 0xffff)
|
||
|
+#define RKTF_VER_MINOR(ver) ((ver) & 0xffff)
|
||
|
+
|
||
|
+/*
|
||
|
+ * pcsi smc funciton id
|
||
|
+ */
|
||
|
+#define PSCI_SIP_RKTF_VER (0x82000001)
|
||
|
+#define PSCI_SIP_ACCESS_REG (0x82000002)
|
||
|
+#define PSCI_SIP_ACCESS_REG64 (0xc2000002)
|
||
|
+#define PSCI_SIP_SUSPEND_WR_CTRBITS (0x82000003)
|
||
|
+#define PSCI_SIP_PENDING_CPUS (0x82000004)
|
||
|
+#define PSCI_SIP_UARTDBG_CFG (0x82000005)
|
||
|
+#define PSCI_SIP_UARTDBG_CFG64 (0xc2000005)
|
||
|
+#define PSCI_SIP_EL3FIQ_CFG (0x82000006)
|
||
|
+#define PSCI_SIP_SMEM_CONFIG (0x82000007)
|
||
|
+
|
||
|
+/*
|
||
|
+ * pcsi smc funciton err code
|
||
|
+ */
|
||
|
+#define PSCI_SMC_FUNC_UNK 0xffffffff
|
||
|
+
|
||
|
+/*
|
||
|
+ * define PSCI_SIP_UARTDBG_CFG call type
|
||
|
+ */
|
||
|
+#define UARTDBG_CFG_INIT 0xf0
|
||
|
+#define UARTDBG_CFG_OSHDL_TO_OS 0xf1
|
||
|
+#define UARTDBG_CFG_OSHDL_CPUSW 0xf3
|
||
|
+#define UARTDBG_CFG_OSHDL_DEBUG_ENABLE 0xf4
|
||
|
+#define UARTDBG_CFG_OSHDL_DEBUG_DISABLE 0xf5
|
||
|
+
|
||
|
+/*
|
||
|
+ * rockchip psci function call interface
|
||
|
+ */
|
||
|
+
|
||
|
+u32 rockchip_psci_smc_read(u32 function_id, u32 arg0, u32 arg1, u32 arg2,
|
||
|
+ u32 *val);
|
||
|
+u32 rockchip_psci_smc_write(u32 function_id, u32 arg0, u32 arg1, u32 arg2);
|
||
|
+
|
||
|
+u32 rockchip_psci_smc_get_tf_ver(void);
|
||
|
+u32 rockchip_secure_reg_read(u32 addr_phy);
|
||
|
+u32 rockchip_secure_reg_write(u32 addr_phy, u32 val);
|
||
|
+
|
||
|
+#ifdef CONFIG_ARM64
|
||
|
+u32 rockchip_psci_smc_write64(u64 function_id, u64 arg0, u64 arg1, u64 arg2);
|
||
|
+u32 rockchip_psci_smc_read64(u64 function_id, u64 arg0, u64 arg1, u64 arg2,
|
||
|
+ u64 *val);
|
||
|
+u64 rockchip_secure_reg_read64(u64 addr_phy);
|
||
|
+u32 rockchip_secure_reg_write64(u64 addr_phy, u64 val);
|
||
|
+
|
||
|
+void psci_fiq_debugger_uart_irq_tf_cb(u64 sp_el1, u64 offset);
|
||
|
+#endif
|
||
|
+
|
||
|
+u32 psci_fiq_debugger_switch_cpu(u32 cpu);
|
||
|
+void psci_fiq_debugger_uart_irq_tf_init(u32 irq_id, void *callback);
|
||
|
+void psci_fiq_debugger_enable_debug(bool val);
|
||
|
+
|
||
|
+#if defined(CONFIG_ARM_PSCI) || defined(CONFIG_ARM64)
|
||
|
+u32 psci_set_memory_secure(bool val);
|
||
|
+#else
|
||
|
+static inline u32 psci_set_memory_secure(bool val)
|
||
|
+{
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+#endif
|
||
|
+
|
||
|
+#endif /* __ROCKCHIP_PSCI_H */
|
||
|
diff --git a/include/linux/rockchip/rockchip_sip.h b/include/linux/rockchip/rockchip_sip.h
|
||
|
new file mode 100644
|
||
|
index 0000000..3b853d8
|
||
|
--- /dev/null
|
||
|
+++ b/include/linux/rockchip/rockchip_sip.h
|
||
|
@@ -0,0 +1,223 @@
|
||
|
+/* Copyright (c) 2016, Fuzhou Rockchip Electronics Co., Ltd
|
||
|
+ *
|
||
|
+ * This program is free software; you can redistribute it and/or modify
|
||
|
+ * it under the terms of the GNU General Public License version 2 and
|
||
|
+ * only 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 __ROCKCHIP_SIP_H
|
||
|
+#define __ROCKCHIP_SIP_H
|
||
|
+
|
||
|
+#include <linux/arm-smccc.h>
|
||
|
+#include <linux/io.h>
|
||
|
+
|
||
|
+/* SMC function IDs for SiP Service queries, compatible with kernel-3.10 */
|
||
|
+#define SIP_ATF_VERSION 0x82000001
|
||
|
+#define SIP_ACCESS_REG 0x82000002
|
||
|
+#define SIP_SUSPEND_MODE 0x82000003
|
||
|
+#define SIP_PENDING_CPUS 0x82000004
|
||
|
+#define SIP_UARTDBG_CFG 0x82000005
|
||
|
+#define SIP_UARTDBG_CFG64 0xc2000005
|
||
|
+#define SIP_MCU_EL3FIQ_CFG 0x82000006
|
||
|
+#define SIP_ACCESS_CHIP_STATE64 0xc2000006
|
||
|
+#define SIP_SECURE_MEM_CONFIG 0x82000007
|
||
|
+#define SIP_ACCESS_CHIP_EXTRA_STATE64 0xc2000007
|
||
|
+#define SIP_DRAM_CONFIG 0x82000008
|
||
|
+#define SIP_SHARE_MEM 0x82000009
|
||
|
+#define SIP_SIP_VERSION 0x8200000a
|
||
|
+#define SIP_REMOTECTL_CFG 0x8200000b
|
||
|
+
|
||
|
+/* Rockchip Sip version */
|
||
|
+#define SIP_IMPLEMENT_V1 (1)
|
||
|
+#define SIP_IMPLEMENT_V2 (2)
|
||
|
+
|
||
|
+/* Trust firmware version */
|
||
|
+#define ATF_VER_MAJOR(ver) (((ver) >> 16) & 0xffff)
|
||
|
+#define ATF_VER_MINOR(ver) (((ver) >> 0) & 0xffff)
|
||
|
+
|
||
|
+/* SIP_ACCESS_REG: read or write */
|
||
|
+#define SECURE_REG_RD 0x0
|
||
|
+#define SECURE_REG_WR 0x1
|
||
|
+
|
||
|
+/* Fiq debugger share memory: 8KB enough */
|
||
|
+#define FIQ_UARTDBG_PAGE_NUMS 2
|
||
|
+#define FIQ_UARTDBG_SHARE_MEM_SIZE ((FIQ_UARTDBG_PAGE_NUMS) * 4096)
|
||
|
+
|
||
|
+/* Error return code */
|
||
|
+#define IS_SIP_ERROR(x) (!!(x))
|
||
|
+
|
||
|
+#define SIP_RET_SUCCESS 0
|
||
|
+#define SIP_RET_SMC_UNKNOWN -1
|
||
|
+#define SIP_RET_NOT_SUPPORTED -2
|
||
|
+#define SIP_RET_INVALID_PARAMS -3
|
||
|
+#define SIP_RET_INVALID_ADDRESS -4
|
||
|
+#define SIP_RET_DENIED -5
|
||
|
+
|
||
|
+/* SIP_UARTDBG_CFG64 call types */
|
||
|
+#define UARTDBG_CFG_INIT 0xf0
|
||
|
+#define UARTDBG_CFG_OSHDL_TO_OS 0xf1
|
||
|
+#define UARTDBG_CFG_OSHDL_CPUSW 0xf3
|
||
|
+#define UARTDBG_CFG_OSHDL_DEBUG_ENABLE 0xf4
|
||
|
+#define UARTDBG_CFG_OSHDL_DEBUG_DISABLE 0xf5
|
||
|
+#define UARTDBG_CFG_PRINT_PORT 0xf7
|
||
|
+#define UARTDBG_CFG_FIQ_ENABEL 0xf8
|
||
|
+#define UARTDBG_CFG_FIQ_DISABEL 0xf9
|
||
|
+
|
||
|
+/* SIP_SUSPEND_MODE32 call types */
|
||
|
+#define SUSPEND_MODE_CONFIG 0x01
|
||
|
+#define WKUP_SOURCE_CONFIG 0x02
|
||
|
+#define PWM_REGULATOR_CONFIG 0x03
|
||
|
+#define GPIO_POWER_CONFIG 0x04
|
||
|
+#define SUSPEND_DEBUG_ENABLE 0x05
|
||
|
+#define APIOS_SUSPEND_CONFIG 0x06
|
||
|
+#define VIRTUAL_POWEROFF 0x07
|
||
|
+
|
||
|
+/* SIP_REMOTECTL_CFG call types */
|
||
|
+#define REMOTECTL_SET_IRQ 0xf0
|
||
|
+#define REMOTECTL_SET_PWM_CH 0xf1
|
||
|
+#define REMOTECTL_SET_PWRKEY 0xf2
|
||
|
+#define REMOTECTL_GET_WAKEUP_STATE 0xf3
|
||
|
+#define REMOTECTL_ENABLE 0xf4
|
||
|
+/* wakeup state */
|
||
|
+#define REMOTECTL_PWRKEY_WAKEUP 0xdeadbeaf
|
||
|
+
|
||
|
+/* Share mem page types */
|
||
|
+typedef enum {
|
||
|
+ SHARE_PAGE_TYPE_INVALID = 0,
|
||
|
+ SHARE_PAGE_TYPE_UARTDBG,
|
||
|
+ SHARE_PAGE_TYPE_DDR,
|
||
|
+ SHARE_PAGE_TYPE_MAX,
|
||
|
+} share_page_type_t;
|
||
|
+
|
||
|
+/*
|
||
|
+ * Rules: struct arm_smccc_res contains result and data, details:
|
||
|
+ *
|
||
|
+ * a0: error code(0: success, !0: error);
|
||
|
+ * a1~a3: data
|
||
|
+ */
|
||
|
+#ifdef CONFIG_ROCKCHIP_SIP
|
||
|
+struct arm_smccc_res sip_smc_get_atf_version(void);
|
||
|
+struct arm_smccc_res sip_smc_get_sip_version(void);
|
||
|
+struct arm_smccc_res sip_smc_dram(u32 arg0, u32 arg1, u32 arg2);
|
||
|
+struct arm_smccc_res sip_smc_request_share_mem(u32 page_num,
|
||
|
+ share_page_type_t page_type);
|
||
|
+struct arm_smccc_res sip_smc_mcu_el3fiq(u32 arg0, u32 arg1, u32 arg2);
|
||
|
+
|
||
|
+int sip_smc_set_suspend_mode(u32 ctrl, u32 config1, u32 config2);
|
||
|
+int sip_smc_virtual_poweroff(void);
|
||
|
+
|
||
|
+int sip_smc_secure_reg_write(u32 addr_phy, u32 val);
|
||
|
+u32 sip_smc_secure_reg_read(u32 addr_phy);
|
||
|
+
|
||
|
+/***************************fiq debugger **************************************/
|
||
|
+void sip_fiq_debugger_enable_fiq(bool enable, uint32_t tgt_cpu);
|
||
|
+void sip_fiq_debugger_enable_debug(bool enable);
|
||
|
+int sip_fiq_debugger_uart_irq_tf_init(u32 irq_id, void *callback_fn);
|
||
|
+int sip_fiq_debugger_set_print_port(u32 port_phyaddr, u32 baudrate);
|
||
|
+int sip_fiq_debugger_request_share_memory(void);
|
||
|
+int sip_fiq_debugger_get_target_cpu(void);
|
||
|
+int sip_fiq_debugger_switch_cpu(u32 cpu);
|
||
|
+int sip_fiq_debugger_is_enabled(void);
|
||
|
+#else
|
||
|
+static inline struct arm_smccc_res sip_smc_get_atf_version(void)
|
||
|
+{
|
||
|
+ struct arm_smccc_res tmp = {0};
|
||
|
+ return tmp;
|
||
|
+}
|
||
|
+
|
||
|
+static inline struct arm_smccc_res sip_smc_get_sip_version(void)
|
||
|
+{
|
||
|
+ struct arm_smccc_res tmp = {0};
|
||
|
+ return tmp;
|
||
|
+}
|
||
|
+
|
||
|
+static inline struct arm_smccc_res sip_smc_dram(u32 arg0, u32 arg1, u32 arg2)
|
||
|
+{
|
||
|
+ struct arm_smccc_res tmp = {0};
|
||
|
+ return tmp;
|
||
|
+}
|
||
|
+
|
||
|
+static inline struct arm_smccc_res sip_smc_request_share_mem
|
||
|
+ (u32 page_num, share_page_type_t page_type)
|
||
|
+{
|
||
|
+ struct arm_smccc_res tmp = {0};
|
||
|
+ return tmp;
|
||
|
+}
|
||
|
+
|
||
|
+static inline struct arm_smccc_res sip_smc_mcu_el3fiq
|
||
|
+ (u32 arg0, u32 arg1, u32 arg2)
|
||
|
+{
|
||
|
+ struct arm_smccc_res tmp = {0};
|
||
|
+ return tmp;
|
||
|
+}
|
||
|
+
|
||
|
+static inline int sip_smc_set_suspend_mode(u32 ctrl, u32 config1, u32 config2)
|
||
|
+{
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static inline int sip_smc_virtual_poweroff(void) { return 0; }
|
||
|
+static inline u32 sip_smc_secure_reg_read(u32 addr_phy) { return 0; }
|
||
|
+static inline int sip_smc_secure_reg_write(u32 addr_phy, u32 val) { return 0; }
|
||
|
+
|
||
|
+/***************************fiq debugger **************************************/
|
||
|
+static inline void sip_fiq_debugger_enable_fiq
|
||
|
+ (bool enable, uint32_t tgt_cpu) { return; }
|
||
|
+
|
||
|
+static inline void sip_fiq_debugger_enable_debug(bool enable) { return; }
|
||
|
+static inline int sip_fiq_debugger_uart_irq_tf_init(u32 irq_id,
|
||
|
+ void *callback_fn)
|
||
|
+{
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static inline int sip_fiq_debugger_set_print_port(u32 port_phyaddr,
|
||
|
+ u32 baudrate)
|
||
|
+{
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static inline int sip_fiq_debugger_request_share_memory(void) { return 0; }
|
||
|
+static inline int sip_fiq_debugger_get_target_cpu(void) { return 0; }
|
||
|
+static inline int sip_fiq_debugger_switch_cpu(u32 cpu) { return 0; }
|
||
|
+static inline int sip_fiq_debugger_is_enabled(void) { return 0; }
|
||
|
+#endif
|
||
|
+
|
||
|
+/* optee cpu_context */
|
||
|
+struct sm_nsec_ctx {
|
||
|
+ u32 usr_sp;
|
||
|
+ u32 usr_lr;
|
||
|
+ u32 irq_spsr;
|
||
|
+ u32 irq_sp;
|
||
|
+ u32 irq_lr;
|
||
|
+ u32 svc_spsr;
|
||
|
+ u32 svc_sp;
|
||
|
+ u32 svc_lr;
|
||
|
+ u32 abt_spsr;
|
||
|
+ u32 abt_sp;
|
||
|
+ u32 abt_lr;
|
||
|
+ u32 und_spsr;
|
||
|
+ u32 und_sp;
|
||
|
+ u32 und_lr;
|
||
|
+ u32 mon_lr;
|
||
|
+ u32 mon_spsr;
|
||
|
+ u32 r4;
|
||
|
+ u32 r5;
|
||
|
+ u32 r6;
|
||
|
+ u32 r7;
|
||
|
+ u32 r8;
|
||
|
+ u32 r9;
|
||
|
+ u32 r10;
|
||
|
+ u32 r11;
|
||
|
+ u32 r12;
|
||
|
+ u32 r0;
|
||
|
+ u32 r1;
|
||
|
+ u32 r2;
|
||
|
+ u32 r3;
|
||
|
+};
|
||
|
+
|
||
|
+#endif
|