* [RFC PATCH V3 2/3] dts: arm64: mt8183: Add FD nodes
From: Jerry-ch Chen @ 2019-09-06 10:11 UTC (permalink / raw)
To: hans.verkuil, laurent.pinchart+renesas, tfiga, matthias.bgg,
mchehab, lkml
Cc: devicetree, Sean.Cheng, Rynn.Wu, srv_heupstream, po-yang.huang,
Jerry-ch Chen, jungo.lin, sj.huang, yuzhao, linux-mediatek,
zwisler, ck.hu, christie.yu, frederic.chen, linux-arm-kernel,
linux-media
In-Reply-To: <20190906101125.3784-1-Jerry-Ch.chen@mediatek.com>
From: Jerry-ch Chen <jerry-ch.chen@mediatek.com>
This patch adds nodes for Face Detection (FD) unit. FD is embedded
in Mediatek SoCs and works with the co-processor to perform face
detection on the input data and image and output detected face result.
Signed-off-by: Jerry-ch Chen <jerry-ch.chen@mediatek.com>
---
arch/arm64/boot/dts/mediatek/mt8183.dtsi | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/arch/arm64/boot/dts/mediatek/mt8183.dtsi b/arch/arm64/boot/dts/mediatek/mt8183.dtsi
index c3a516e63141..6f31b5f4c17c 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8183.dtsi
@@ -432,6 +432,19 @@
#clock-cells = <1>;
};
+ fd:fd@1502b000 {
+ compatible = "mediatek,mt8183-fd";
+ mediatek,scp = <&scp>;
+ iommus = <&iommu M4U_PORT_CAM_FDVT_RP>,
+ <&iommu M4U_PORT_CAM_FDVT_WR>,
+ <&iommu M4U_PORT_CAM_FDVT_RB>;
+ reg = <0 0x1502b000 0 0x1000>;
+ interrupts = <GIC_SPI 269 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&imgsys CLK_IMG_FDVT>;
+ clock-names = "fd";
+ power-domains = <&scpsys MT8183_POWER_DOMAIN_ISP>;
+ };
+
vdecsys: syscon@16000000 {
compatible = "mediatek,mt8183-vdecsys", "syscon";
reg = <0 0x16000000 0 0x1000>;
--
2.18.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [RFC PATCH V3 0/3] media: platform: Add support for Face Detection (FD) on mt8183 SoC
From: Jerry-ch Chen @ 2019-09-06 10:11 UTC (permalink / raw)
To: hans.verkuil, laurent.pinchart+renesas, tfiga, matthias.bgg,
mchehab, lkml
Cc: devicetree, Sean.Cheng, Rynn.Wu, srv_heupstream, po-yang.huang,
Jerry-ch.Chen, jungo.lin, sj.huang, yuzhao, linux-mediatek,
zwisler, ck.hu, christie.yu, frederic.chen, linux-arm-kernel,
linux-media
Hello,
This RFC patch series is adding Face Detection (FD) driver on Mediatek
mt8183 SoC. It belongs to the first Mediatek's camera driver series based
on V4L2 and media controller framework. I posted the main part of the FD
driver as RFC to discuss first and would like some review comments.
==============
Introduction
==============
Face Detection (FD) unit provides hardware accelerated face detection
feature. It can detect different sizes of faces in a given image.
The driver is implemented as a normal V4L2 memory-to-memory device and
supports V4L2 controls for detection settings. It has two buffer queues.
1. Video output buffer: RAW image for face detection.
2. Meta capture buffer: Result of the detected faces.
==================
Changes in v3
==================
RFC v3 includes the following modification:
1. Adjust the private control ids and place them in
include/uapi/linux/mtk-fd-v4l2-controls.h
2. Fixing review commnets in mtk_fd_40.c and mtk_fd.h
3. Define FD meta capture buffer in include/uapi/linux/videodev2.h
4. Remove the usage of get_reserved_memory by scp driver and
use dma_alloc api instead
Todo:
- Add v4l2 control menus for private mtk fd control
- Refine the job finish flow when system suspend
==================
Changes in v2
==================
RFC v2 includes the following modification:
1. Implement FD as a V4L2 mem2mem driver
2. Replace meta input with V4L2 controls
==================
Changes in v1
==================
RFC v1 includes the following modification:
1. Uses Request API instead of FD's buffer collection design
2. removed unnecessary abstraction structurally, including mtk_fd_ctx and
related ops
3. removed the fd_smem node from device tree
4. Fixed the common issues Tomasz commented on Mediatek ISP Pass 1's RFC v0
patch series
==================
Dependent patch
==================
FD driver depends on SCP driver. The patches are as following:
[1]. Add support for mt8183 SCP
https://patchwork.kernel.org/cover/11132177/
==================
Compliance test
==================
* Version: https://git.linuxtv.org/v4l-utils.git/commit/?id=b16f9e945d74aa5
* Note: Some of the failures are caused by the implementation of FD driver,
which is a m2m device with VIDEO_OUT and META_CAPTURE queues,
therefore we can't set V4L2_CAP_VIDEO_M2M in device capability, and
fail in some non-m2m v4l2 test cases.
* Test command: v4l2-compliance -m 0
* test output:
v4l2-compliance SHA: not available, 32 bits
Compliance test for mtk-fd-4.0 device /dev/media0:
Media Driver Info:
Driver name : mtk-fd-4.0
Model : mtk-fd-4.0
Serial :
Bus info : platform:1502b000.fd
Media version : 4.19.67
Hardware revision: 0x00000000 (0)
Driver version : 4.19.67
Required ioctls:
test MEDIA_IOC_DEVICE_INFO: OK
Allow for multiple opens:
test second /dev/media0 open: OK
test MEDIA_IOC_DEVICE_INFO: OK
test for unlimited opens: OK
Media Controller ioctls:
test MEDIA_IOC_G_TOPOLOGY: OK
Entities: 3 Interfaces: 1 Pads: 4 Links: 4
test MEDIA_IOC_ENUM_ENTITIES/LINKS: OK
test MEDIA_IOC_SETUP_LINK: OK
Total for mtk-fd-4.0 device /dev/media0: 7, Succeeded: 7, Failed: 0, Warnings: 0
--------------------------------------------------------------------------------
Compliance test for mtk-fd-4.0 device /dev/video0:
Driver Info:
Driver name : mtk-fd-4.0
Card type : mtk-fd-4.0
Bus info : platform:1502b000.fd
Driver version : 4.19.67
Capabilities : 0x84a02000
Video Output Multiplanar
Metadata Capture
Streaming
Extended Pix Format
Device Capabilities
Device Caps : 0x04a02000
Video Output Multiplanar
Metadata Capture
Streaming
Extended Pix Format
Media Driver Info:
Driver name : mtk-fd-4.0
Model : mtk-fd-4.0
Serial :
Bus info : platform:1502b000.fd
Media version : 4.19.67
Hardware revision: 0x00000000 (0)
Driver version : 4.19.67
Interface Info:
ID : 0x0300000c
Type : V4L Video
Entity Info:
ID : 0x00000001 (1)
Name : mtk-fd-4.0-source
Function : V4L2 I/O
Pad 0x01000002 : 0: Source
Link 0x02000008: to remote pad 0x1000005 of entity 'mtk-fd-4.0-proc': Data, Enabled, Immutable
Required ioctls:
test MC information (see 'Media Driver Info' above): OK
fail: v4l2-compliance.cpp(668): dcaps & output_caps
test VIDIOC_QUERYCAP: FAIL
Allow for multiple opens:
test second /dev/video0 open: OK
fail: v4l2-compliance.cpp(668): dcaps & output_caps
test VIDIOC_QUERYCAP: FAIL
test VIDIOC_G/S_PRIORITY: OK
test for unlimited opens: OK
Debug ioctls:
test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
test VIDIOC_LOG_STATUS: OK (Not Supported)
Input ioctls:
test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
test VIDIOC_ENUMAUDIO: OK (Not Supported)
test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
test VIDIOC_G/S_AUDIO: OK (Not Supported)
Inputs: 0 Audio Inputs: 0 Tuners: 0
Output ioctls:
test VIDIOC_G/S_MODULATOR: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
test VIDIOC_ENUMAUDOUT: OK (Not Supported)
test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
test VIDIOC_G/S_AUDOUT: OK (Not Supported)
Outputs: 0 Audio Outputs: 0 Modulators: 0
Input/Output configuration ioctls:
test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
test VIDIOC_G/S_EDID: OK (Not Supported)
Control ioctls:
test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: OK
test VIDIOC_QUERYCTRL: OK
test VIDIOC_G/S_CTRL: OK
test VIDIOC_G/S/TRY_EXT_CTRLS: OK
test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK
test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
Standard Controls: 1 Private Controls: 6
Format ioctls:
test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
test VIDIOC_G/S_PARM: OK (Not Supported)
test VIDIOC_G_FBUF: OK (Not Supported)
fail: v4l2-test-formats.cpp(457): pixelformat 00000000 () for buftype 10 not reported by ENUM_FMT
test VIDIOC_G_FMT: FAIL
fail: v4l2-test-formats.cpp(457): pixelformat 00000000 () for buftype 10 not reported by ENUM_FMT
test VIDIOC_TRY_FMT: FAIL
fail: v4l2-test-formats.cpp(457): pixelformat ffffffff (-BE) for buftype 10 not reported by ENUM_FMT
test VIDIOC_S_FMT: FAIL
test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
test Cropping: OK (Not Supported)
test Composing: OK (Not Supported)
test Scaling: OK (Not Supported)
Codec ioctls:
test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
test VIDIOC_G_ENC_INDEX: OK (Not Supported)
test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)
Buffer ioctls:
fail: v4l2-test-buffers.cpp(667): q2.reqbufs(node->node2, 1) != EBUSY
test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: FAIL
test VIDIOC_EXPBUF: OK
test Requests: OK
Total for mtk-fd-4.0 device /dev/video0: 45, Succeeded: 39, Failed: 6, Warnings: 0
Grand Total for mtk-fd-4.0 device /dev/media0: 52, Succeeded: 46, Failed: 6, Warnings: 0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [RFC PATCH V3 3/3] platform: mtk-isp: Add Mediatek FD driver
From: Jerry-ch Chen @ 2019-09-06 10:11 UTC (permalink / raw)
To: hans.verkuil, laurent.pinchart+renesas, tfiga, matthias.bgg,
mchehab, lkml
Cc: devicetree, Sean.Cheng, Rynn.Wu, srv_heupstream, po-yang.huang,
Jerry-ch Chen, jungo.lin, sj.huang, yuzhao, linux-mediatek,
zwisler, ck.hu, christie.yu, frederic.chen, linux-arm-kernel,
linux-media
In-Reply-To: <20190906101125.3784-1-Jerry-Ch.chen@mediatek.com>
From: Jerry-ch Chen <jerry-ch.chen@mediatek.com>
This patch adds the driver of Face Detection (FD) unit in
Mediatek camera system, providing face detection function.
The mtk-isp directory will contain drivers for multiple IP
blocks found in Mediatek ISP system. It will include ISP Pass 1
driver (CAM), sensor interface driver, DIP driver and face
detection driver.
Signed-off-by: Jerry-ch Chen <jerry-ch.chen@mediatek.com>
---
drivers/media/platform/Kconfig | 2 +
drivers/media/platform/Makefile | 2 +
drivers/media/platform/mtk-isp/fd/Kconfig | 19 +
drivers/media/platform/mtk-isp/fd/Makefile | 5 +
drivers/media/platform/mtk-isp/fd/mtk_fd.h | 148 ++
drivers/media/platform/mtk-isp/fd/mtk_fd_40.c | 1219 +++++++++++++++++
include/uapi/linux/mtk-fd-v4l2-controls.h | 69 +
include/uapi/linux/v4l2-controls.h | 4 +
8 files changed, 1468 insertions(+)
create mode 100644 drivers/media/platform/mtk-isp/fd/Kconfig
create mode 100644 drivers/media/platform/mtk-isp/fd/Makefile
create mode 100644 drivers/media/platform/mtk-isp/fd/mtk_fd.h
create mode 100644 drivers/media/platform/mtk-isp/fd/mtk_fd_40.c
create mode 100644 include/uapi/linux/mtk-fd-v4l2-controls.h
diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
index a505e9f5a1e2..ae99258e26a5 100644
--- a/drivers/media/platform/Kconfig
+++ b/drivers/media/platform/Kconfig
@@ -32,6 +32,8 @@ source "drivers/media/platform/davinci/Kconfig"
source "drivers/media/platform/omap/Kconfig"
+source "drivers/media/platform/mtk-isp/fd/Kconfig"
+
config VIDEO_ASPEED
tristate "Aspeed AST2400 and AST2500 Video Engine driver"
depends on VIDEO_V4L2
diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile
index e6deb2597738..8b817cc80f43 100644
--- a/drivers/media/platform/Makefile
+++ b/drivers/media/platform/Makefile
@@ -94,6 +94,8 @@ obj-$(CONFIG_VIDEO_MEDIATEK_MDP) += mtk-mdp/
obj-$(CONFIG_VIDEO_MEDIATEK_JPEG) += mtk-jpeg/
+obj-$(CONFIG_VIDEO_MEDIATEK_FD) += mtk-isp/fd/
+
obj-$(CONFIG_VIDEO_QCOM_CAMSS) += qcom/camss/
obj-$(CONFIG_VIDEO_QCOM_VENUS) += qcom/venus/
diff --git a/drivers/media/platform/mtk-isp/fd/Kconfig b/drivers/media/platform/mtk-isp/fd/Kconfig
new file mode 100644
index 000000000000..126aad0eb9d8
--- /dev/null
+++ b/drivers/media/platform/mtk-isp/fd/Kconfig
@@ -0,0 +1,19 @@
+config VIDEO_MEDIATEK_FD
+ bool "Mediatek face detection processing function"
+ depends on VIDEO_V4L2
+ depends on ARCH_MEDIATEK || COMPILE_TEST
+ select VIDEOBUF2_DMA_CONTIG
+ select VIDEOBUF2_CORE
+ select VIDEOBUF2_V4L2
+ select VIDEOBUF2_MEMOPS
+ select MEDIA_CONTROLLER
+ select MTK_SCP
+
+ default n
+ help
+ Support the Face Detection (FD) feature in the Mediatek
+ mt8183 Soc.
+
+ FD driver is a V4L2 memory-to-memory device driver which
+ provides hardware accelerated face detection function,
+ it can detect different sizes of faces in a raw image.
diff --git a/drivers/media/platform/mtk-isp/fd/Makefile b/drivers/media/platform/mtk-isp/fd/Makefile
new file mode 100644
index 000000000000..9b1c501d73e1
--- /dev/null
+++ b/drivers/media/platform/mtk-isp/fd/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+
+mtk-fd-objs += mtk_fd_40.o
+
+obj-$(CONFIG_VIDEO_MEDIATEK_FD) += mtk-fd.o
\ No newline at end of file
diff --git a/drivers/media/platform/mtk-isp/fd/mtk_fd.h b/drivers/media/platform/mtk-isp/fd/mtk_fd.h
new file mode 100644
index 000000000000..bdba73fc45ab
--- /dev/null
+++ b/drivers/media/platform/mtk-isp/fd/mtk_fd.h
@@ -0,0 +1,148 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+//
+// Copyright (c) 2018 MediaTek Inc.
+
+#ifndef __MTK_FD_HW_H__
+#define __MTK_FD_HW_H__
+
+#include <linux/completion.h>
+#include <linux/io.h>
+#include <linux/types.h>
+#include <linux/platform_device.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/videobuf2-v4l2.h>
+#include <linux/mtk-fd-v4l2-controls.h>
+
+#define MTK_FD_OUTPUT_MIN_WIDTH 26U
+#define MTK_FD_OUTPUT_MIN_HEIGHT 26U
+#define MTK_FD_OUTPUT_MAX_WIDTH 640U
+#define MTK_FD_OUTPUT_MAX_HEIGHT 480U
+#define MTK_FD_IPI_SEND_TIMEOUT 0U
+
+#define MTK_FD_HW_FMT_VYUY 2
+#define MTK_FD_HW_FMT_UYVY 3
+#define MTK_FD_HW_FMT_YVYU 4
+#define MTK_FD_HW_FMT_YUYV 5
+#define MTK_FD_HW_FMT_YVU_2P 6
+#define MTK_FD_HW_FMT_YUV_2P 7
+#define MTK_FD_HW_FMT_UNKNOWN 8
+
+#define MTK_FD_IPI_CMD_INIT 0
+#define MTK_FD_IPI_CMD_INIT_ACK 1
+#define MTK_FD_IPI_CMD_ENQUEUE 2
+#define MTK_FD_IPI_CMD_ENQ_ACK 3
+#define MTK_FD_IPI_CMD_RESET 4
+#define MTK_FD_IPI_CMD_RESET_ACK 5
+
+#define MTK_FD_REG_OFFSET_HW_ENABLE 0x4
+#define MTK_FD_REG_OFFSET_INT_EN 0x15c
+#define MTK_FD_REG_OFFSET_INT_VAL 0x168
+#define MTK_FD_REG_OFFSET_RESULT 0x178
+
+#define MTK_FD_SET_HW_ENABLE 0x111
+#define MTK_FD_RS_BUF_SIZE 2289664
+#define MTK_FD_HW_WORK_BUF_SIZE 0x100000
+#define MTK_FD_MAX_SPEEDUP 7
+#define MTK_FD_MAX_RESULT_NUM 1026
+
+/* Max scale size counts */
+#define MTK_FD_SCALE_ARR_NUM 15
+
+#define MTK_FD_HW_TIMEOUT 1000
+
+enum face_angle {
+ MTK_FD_FACE_FRONT,
+ MTK_FD_FACE_RIGHT_50,
+ MTK_FD_FACE_LEFT_50,
+ MTK_FD_FACE_RIGHT_90,
+ MTK_FD_FACE_LEFT_90,
+ MTK_FD_FACE_ANGLE_NUM,
+};
+
+struct fd_buffer {
+ __u32 scp_addr; /* used by SCP */
+ __u32 dma_addr; /* used by DMA HW */
+} __packed;
+
+struct fd_face_result {
+ char data[16];
+};
+
+struct fd_user_output {
+ struct fd_face_result results[MTK_FD_MAX_RESULT_NUM];
+ __u16 number;
+};
+
+struct user_param {
+ u8 fd_speedup;
+ u8 fd_extra_model;
+ u8 scale_img_num;
+ u8 src_img_fmt;
+ __u16 scale_img_width[MTK_FD_SCALE_ARR_NUM];
+ __u16 scale_img_height[MTK_FD_SCALE_ARR_NUM];
+ __u16 face_directions[MTK_FD_FACE_ANGLE_NUM];
+} __packed;
+
+struct fd_init_param {
+ struct fd_buffer fd_manager;
+ __u32 rs_dma_addr;
+} __packed;
+
+struct fd_enq_param {
+ __u64 output_vaddr;
+ struct fd_buffer src_img[2];
+ struct fd_buffer user_result;
+ struct user_param user_param;
+} __packed;
+
+struct fd_ack_param {
+ __u32 ret_code;
+ __u32 ret_msg;
+} __packed;
+
+struct ipi_message {
+ u8 cmd_id;
+ union {
+ struct fd_init_param fd_init_param;
+ struct fd_enq_param fd_enq_param;
+ struct fd_ack_param fd_ack_param;
+ };
+} __packed;
+
+struct mtk_fd_dev {
+ struct device *dev;
+ struct mtk_fd_ctx *ctx;
+ struct v4l2_device v4l2_dev;
+ struct v4l2_m2m_dev *m2m_dev;
+ struct media_device mdev;
+ struct video_device vfd;
+ struct platform_device *scp_pdev;
+ struct clk *fd_clk;
+ struct rproc *rproc_handle;
+
+ /* Lock for V4L2 operations */
+ struct mutex vfd_lock;
+
+ struct fd_user_output *output;
+ struct fd_buffer scp_mem;
+ void __iomem *fd_base;
+ void *rs_dma_buf;
+ dma_addr_t rs_dma_handle;
+ void *scp_mem_virt_addr;
+
+ u32 fd_stream_count;
+ struct completion fd_irq_done;
+};
+
+struct mtk_fd_ctx {
+ struct mtk_fd_dev *fd_dev;
+ struct device *dev;
+ struct v4l2_fh fh;
+ struct v4l2_ctrl_handler hdl;
+ struct v4l2_pix_format_mplane src_fmt;
+ struct v4l2_meta_format dst_fmt;
+ struct user_param user_param;
+};
+
+#endif/*__MTK_FD_HW_H__*/
diff --git a/drivers/media/platform/mtk-isp/fd/mtk_fd_40.c b/drivers/media/platform/mtk-isp/fd/mtk_fd_40.c
new file mode 100644
index 000000000000..901fa36a2305
--- /dev/null
+++ b/drivers/media/platform/mtk-isp/fd/mtk_fd_40.c
@@ -0,0 +1,1219 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (c) 2018 MediaTek Inc.
+
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/iopoll.h>
+#include <linux/jiffies.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/remoteproc/mtk_scp.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/remoteproc.h>
+#include <media/videobuf2-dma-contig.h>
+#include <media/videobuf2-v4l2.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-mem2mem.h>
+#include <media/videobuf2-core.h>
+
+#include "mtk_fd.h"
+
+static const struct v4l2_pix_format_mplane mtk_fd_img_fmts[] = {
+ {
+ .pixelformat = V4L2_PIX_FMT_VYUY,
+ .num_planes = 1,
+ },
+ {
+ .pixelformat = V4L2_PIX_FMT_YUYV,
+ .num_planes = 1,
+ },
+ {
+ .pixelformat = V4L2_PIX_FMT_YVYU,
+ .num_planes = 1,
+ },
+ {
+ .pixelformat = V4L2_PIX_FMT_UYVY,
+ .num_planes = 1,
+ },
+ {
+ .pixelformat = V4L2_PIX_FMT_NV16M,
+ .num_planes = 2,
+ },
+ {
+ .pixelformat = V4L2_PIX_FMT_NV61M,
+ .num_planes = 2,
+ },
+};
+
+#define NUM_FORMATS ARRAY_SIZE(mtk_fd_img_fmts)
+
+static inline struct mtk_fd_ctx *fh_to_ctx(struct v4l2_fh *fh)
+{
+ return container_of(fh, struct mtk_fd_ctx, fh);
+}
+
+/* */
+static dma_addr_t mtk_fd_hw_alloc_rs_dma_addr(struct mtk_fd_dev *fd)
+{
+ struct device *dev = fd->dev;
+ void *va;
+ dma_addr_t dma_handle;
+
+ va = dma_alloc_coherent(dev, MTK_FD_RS_BUF_SIZE, &dma_handle,
+ GFP_KERNEL);
+ if (!va) {
+ dev_err(dev, "dma_alloc null va\n");
+ return -ENOMEM;
+ }
+ memset(va, 0, MTK_FD_RS_BUF_SIZE);
+ fd->rs_dma_buf = va;
+ fd->rs_dma_handle = dma_handle;
+
+ return dma_handle;
+}
+
+static int mtk_fd_send_ipi_init(struct mtk_fd_dev *fd)
+{
+ struct ipi_message fd_init_msg;
+ dma_addr_t rs_dma_addr;
+
+ fd_init_msg.cmd_id = MTK_FD_IPI_CMD_INIT;
+
+ fd_init_msg.fd_init_param.fd_manager.scp_addr = fd->scp_mem.scp_addr;
+ fd_init_msg.fd_init_param.fd_manager.dma_addr = fd->scp_mem.dma_addr;
+
+ rs_dma_addr = mtk_fd_hw_alloc_rs_dma_addr(fd);
+ if (!rs_dma_addr)
+ return -ENOMEM;
+ memset(fd->rs_dma_buf, 0, MTK_FD_RS_BUF_SIZE);
+
+ fd_init_msg.fd_init_param.rs_dma_addr = fd->rs_dma_handle;
+
+ return scp_ipi_send(fd->scp_pdev, SCP_IPI_FD_CMD, &fd_init_msg,
+ sizeof(fd_init_msg), MTK_FD_IPI_SEND_TIMEOUT);
+}
+
+static void mtk_fd_free_dma_handle(struct mtk_fd_dev *fd)
+{
+ if (!IS_ERR(fd->rs_dma_buf))
+ dma_free_coherent(fd->dev, MTK_FD_RS_BUF_SIZE,
+ fd->rs_dma_buf,
+ fd->rs_dma_handle);
+}
+
+static int mtk_fd_hw_enable(struct mtk_fd_dev *fd)
+{
+ int ret;
+
+ ret = mtk_fd_send_ipi_init(fd);
+ if (ret) {
+ dev_err(fd->dev, "Failed to send fd ipi init\n");
+ if (!IS_ERR(fd->rs_dma_buf))
+ mtk_fd_free_dma_handle(fd);
+ return ret;
+ }
+ return 0;
+}
+
+static void mtk_fd_hw_job_finish(struct mtk_fd_dev *fd,
+ enum vb2_buffer_state vb_state)
+{
+ struct mtk_fd_ctx *ctx;
+ struct vb2_v4l2_buffer *src_vbuf = NULL, *dst_vbuf = NULL;
+
+ ctx = v4l2_m2m_get_curr_priv(fd->m2m_dev);
+ src_vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+ dst_vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+
+ v4l2_m2m_buf_copy_metadata(src_vbuf, dst_vbuf,
+ V4L2_BUF_FLAG_TSTAMP_SRC_MASK);
+ v4l2_m2m_buf_done(src_vbuf, vb_state);
+ v4l2_m2m_buf_done(dst_vbuf, vb_state);
+ v4l2_m2m_job_finish(fd->m2m_dev, ctx->fh.m2m_ctx);
+}
+
+static void mtk_fd_ipi_handler(void *data, unsigned int len, void *priv)
+{
+ struct mtk_fd_dev *fd = (struct mtk_fd_dev *)priv;
+ struct device *dev = fd->dev;
+ struct ipi_message *fd_ack_msg = (struct ipi_message *)data;
+ struct fd_ack_param *fd_ack = &fd_ack_msg->fd_ack_param;
+
+ dev_dbg(fd->dev, "fd_ipi_ack_id: %d\n", fd_ack_msg->cmd_id);
+ switch (fd_ack_msg->cmd_id) {
+ case MTK_FD_IPI_CMD_INIT_ACK:
+ return;
+ case MTK_FD_IPI_CMD_ENQ_ACK:
+ if (fd_ack->ret_code) {
+ dev_err(dev, "ipi ret: %d, message: %d\n",
+ fd_ack->ret_code, fd_ack->ret_msg);
+ pm_runtime_put((fd->dev));
+ mtk_fd_hw_job_finish(fd, VB2_BUF_STATE_ERROR);
+ }
+ return;
+ case MTK_FD_IPI_CMD_RESET_ACK:
+ return;
+ }
+}
+
+static int mtk_fd_hw_connect(struct mtk_fd_dev *fd)
+{
+ int ret;
+
+ ret = rproc_boot(fd->rproc_handle);
+
+ if (ret < 0) {
+ /**
+ * Return 0 if downloading firmware successfully,
+ * otherwise it is failed
+ */
+ dev_err(fd->dev, "Failed to boot rproc\n");
+ return ret;
+ }
+
+ ret = scp_ipi_register(fd->scp_pdev, SCP_IPI_FD_CMD,
+ mtk_fd_ipi_handler, fd);
+ if (ret) {
+ dev_err(fd->dev, "Failed to register IPI cmd handler\n");
+ goto err_rproc_shutdown;
+ }
+
+ fd->fd_stream_count++;
+ if (fd->fd_stream_count == 1) {
+ if (mtk_fd_hw_enable(fd)) {
+ ret = -EINVAL;
+ goto err_rproc_shutdown;
+ }
+ }
+ return 0;
+
+err_rproc_shutdown:
+ rproc_shutdown(fd->rproc_handle);
+ return ret;
+}
+
+static void mtk_fd_hw_disconnect(struct mtk_fd_dev *fd)
+{
+ fd->fd_stream_count--;
+
+ if (fd->fd_stream_count == 0) {
+ if (!IS_ERR(fd->rs_dma_buf))
+ mtk_fd_free_dma_handle(fd);
+
+ rproc_shutdown(fd->rproc_handle);
+ }
+}
+
+static int mtk_fd_hw_job_exec(struct mtk_fd_dev *fd,
+ struct fd_enq_param *fd_param)
+{
+ struct ipi_message fd_ipi_msg;
+ int ret;
+
+ pm_runtime_get_sync((fd->dev));
+
+ reinit_completion(&fd->fd_irq_done);
+ fd_ipi_msg.cmd_id = MTK_FD_IPI_CMD_ENQUEUE;
+ memcpy(&fd_ipi_msg.fd_enq_param, fd_param, sizeof(struct fd_enq_param));
+ ret = scp_ipi_send(fd->scp_pdev, SCP_IPI_FD_CMD, &fd_ipi_msg,
+ sizeof(fd_ipi_msg), MTK_FD_IPI_SEND_TIMEOUT);
+ if (ret) {
+ pm_runtime_put((fd->dev));
+ mtk_fd_hw_job_finish(fd, VB2_BUF_STATE_ERROR);
+ return ret;
+ }
+ return 0;
+}
+
+static int mtk_fd_vb2_buf_out_validate(struct vb2_buffer *vb)
+{
+ struct vb2_v4l2_buffer *v4l2_buf = to_vb2_v4l2_buffer(vb);
+
+ if (v4l2_buf->field == V4L2_FIELD_ANY)
+ v4l2_buf->field = V4L2_FIELD_NONE;
+ if (v4l2_buf->field != V4L2_FIELD_NONE)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int mtk_fd_vb2_buf_prepare(struct vb2_buffer *vb)
+{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct vb2_queue *vq = vb->vb2_queue;
+ struct mtk_fd_ctx *ctx = vb2_get_drv_priv(vq);
+ struct device *dev = ctx->dev;
+ struct v4l2_pix_format_mplane *pixfmt;
+
+ switch (vq->type) {
+ case V4L2_BUF_TYPE_META_CAPTURE:
+ if (vb2_plane_size(vb, 0) < ctx->dst_fmt.buffersize) {
+ dev_dbg(dev, "meta size %d is too small\n");
+ return -EINVAL;
+ }
+ break;
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+ pixfmt = &ctx->src_fmt;
+
+ if (vbuf->field == V4L2_FIELD_ANY)
+ vbuf->field = V4L2_FIELD_NONE;
+
+ if (vb->num_planes > 2 || vbuf->field != V4L2_FIELD_NONE) {
+ dev_dbg(dev, "plane or field %d not supported\n",
+ vb->num_planes, vbuf->field);
+ return -EINVAL;
+ }
+ if (vb2_plane_size(vb, 0) < pixfmt->plane_fmt[0].sizeimage) {
+ dev_dbg(dev, "plane %d is too small\n");
+ return -EINVAL;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+static void mtk_fd_vb2_buf_queue(struct vb2_buffer *vb)
+{
+ struct mtk_fd_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+
+ v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
+}
+
+static int mtk_fd_vb2_queue_setup(struct vb2_queue *vq,
+ unsigned int *num_buffers,
+ unsigned int *num_planes,
+ unsigned int sizes[],
+ struct device *alloc_devs[])
+{
+ struct mtk_fd_ctx *ctx = vb2_get_drv_priv(vq);
+ unsigned int size[2];
+ unsigned int plane;
+
+ switch (vq->type) {
+ case V4L2_BUF_TYPE_META_CAPTURE:
+ size[0] = ctx->dst_fmt.buffersize;
+ break;
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+ size[0] = ctx->src_fmt.plane_fmt[0].sizeimage;
+ if (*num_planes == 2)
+ size[1] = ctx->src_fmt.plane_fmt[1].sizeimage;
+ break;
+ }
+
+ if (*num_planes > 2)
+ return -EINVAL;
+ if (*num_planes == 0) {
+ if (vq->type == V4L2_BUF_TYPE_META_CAPTURE) {
+ sizes[0] = ctx->dst_fmt.buffersize;
+ *num_planes = 1;
+ return 0;
+ }
+
+ *num_planes = ctx->src_fmt.num_planes;
+ for (plane = 0; plane < *num_planes; plane++)
+ sizes[plane] = ctx->src_fmt.plane_fmt[plane].sizeimage;
+ return 0;
+ }
+
+ for (plane = 0; plane < *num_planes; plane++) {
+ if (sizes[plane] < size[plane])
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int mtk_fd_vb2_start_streaming(struct vb2_queue *vq, unsigned int count)
+{
+ struct mtk_fd_ctx *ctx = vb2_get_drv_priv(vq);
+
+ if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+ return mtk_fd_hw_connect(ctx->fd_dev);
+ else
+ return 0;
+}
+
+static int mtk_fd_job_abort(struct mtk_fd_dev *fd)
+{
+ u32 ret;
+
+ ret = wait_for_completion_timeout(&fd->fd_irq_done,
+ msecs_to_jiffies(MTK_FD_HW_TIMEOUT));
+ /* Reset FD HW */
+ if (!ret) {
+ struct ipi_message fd_ipi_msg;
+
+ fd_ipi_msg.cmd_id = MTK_FD_IPI_CMD_RESET;
+ if (scp_ipi_send(fd->scp_pdev, SCP_IPI_FD_CMD, &fd_ipi_msg,
+ sizeof(fd_ipi_msg), MTK_FD_IPI_SEND_TIMEOUT))
+ dev_err(fd->dev, "FD Reset HW error\n");
+ return -ETIMEDOUT;
+ }
+ return 0;
+}
+
+static void mtk_fd_vb2_stop_streaming(struct vb2_queue *vq)
+{
+ struct mtk_fd_ctx *ctx = vb2_get_drv_priv(vq);
+ struct mtk_fd_dev *fd = ctx->fd_dev;
+ struct vb2_v4l2_buffer *vb;
+ struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx;
+ struct v4l2_m2m_queue_ctx *queue_ctx;
+
+ mtk_fd_job_abort(fd);
+ queue_ctx = V4L2_TYPE_IS_OUTPUT(vq->type) ?
+ &m2m_ctx->out_q_ctx :
+ &m2m_ctx->cap_q_ctx;
+ while ((vb = v4l2_m2m_buf_remove(queue_ctx)))
+ v4l2_m2m_buf_done(vb, VB2_BUF_STATE_ERROR);
+
+ if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+ mtk_fd_hw_disconnect(fd);
+}
+
+static void mtk_fd_vb2_request_complete(struct vb2_buffer *vb)
+{
+ struct mtk_fd_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+
+ v4l2_ctrl_request_complete(vb->req_obj.req, &ctx->hdl);
+}
+
+static int mtk_fd_querycap(struct file *file, void *fh,
+ struct v4l2_capability *cap)
+{
+ struct mtk_fd_dev *fd = video_drvdata(file);
+ struct device *dev = fd->dev;
+
+ strscpy(cap->driver, dev_driver_string(dev), sizeof(cap->driver));
+ strscpy(cap->card, dev_driver_string(dev), sizeof(cap->card));
+ snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
+ dev_name(fd->dev));
+
+ return 0;
+}
+
+static int mtk_fd_enum_fmt_out_mp(struct file *file, void *fh,
+ struct v4l2_fmtdesc *f)
+{
+ if (f->index >= NUM_FORMATS)
+ return -EINVAL;
+
+ f->pixelformat = mtk_fd_img_fmts[f->index].pixelformat;
+ return 0;
+}
+
+static void mtk_fd_fill_pixfmt_mp(struct v4l2_pix_format_mplane *dfmt,
+ const struct v4l2_pix_format_mplane *sfmt)
+{
+ dfmt->field = V4L2_FIELD_NONE;
+ dfmt->colorspace = V4L2_COLORSPACE_BT2020;
+ dfmt->num_planes = sfmt->num_planes;
+ dfmt->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
+ dfmt->quantization = V4L2_QUANTIZATION_DEFAULT;
+ dfmt->xfer_func =
+ V4L2_MAP_XFER_FUNC_DEFAULT(dfmt->colorspace);
+
+ /* Keep user setting as possible */
+ dfmt->width = clamp(dfmt->width,
+ MTK_FD_OUTPUT_MIN_WIDTH,
+ MTK_FD_OUTPUT_MAX_WIDTH);
+ dfmt->height = clamp(dfmt->height,
+ MTK_FD_OUTPUT_MIN_HEIGHT,
+ MTK_FD_OUTPUT_MAX_HEIGHT);
+
+ if (sfmt->num_planes == 2) {
+ /* NV16M and NV61M has 1 byte per pixel */
+ dfmt->plane_fmt[0].bytesperline = dfmt->width;
+ dfmt->plane_fmt[1].bytesperline = dfmt->width;
+ } else {
+ /* 2 bytes per pixel */
+ dfmt->plane_fmt[0].bytesperline = dfmt->width * 2;
+ }
+
+ dfmt->plane_fmt[0].sizeimage =
+ dfmt->height * dfmt->plane_fmt[0].bytesperline;
+}
+
+static const struct v4l2_pix_format_mplane *mtk_fd_find_fmt(u32 format)
+{
+ unsigned int i;
+ const struct v4l2_pix_format_mplane *dev_fmt;
+
+ for (i = 0; i < NUM_FORMATS; i++) {
+ dev_fmt = &mtk_fd_img_fmts[i];
+ if (dev_fmt->pixelformat == format)
+ return dev_fmt;
+ }
+
+ return NULL;
+}
+
+static int mtk_fd_try_fmt_out_mp(struct file *file,
+ void *fh,
+ struct v4l2_format *f)
+{
+ struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
+ const struct v4l2_pix_format_mplane *fmt;
+
+ fmt = mtk_fd_find_fmt(pix_mp->pixelformat);
+ if (!fmt)
+ fmt = &mtk_fd_img_fmts[0]; /* Get default img fmt */
+
+ mtk_fd_fill_pixfmt_mp(pix_mp, fmt);
+ return 0;
+}
+
+static int mtk_fd_g_fmt_out_mp(struct file *file, void *fh,
+ struct v4l2_format *f)
+{
+ struct mtk_fd_ctx *ctx = fh_to_ctx(fh);
+
+ f->fmt.pix_mp = ctx->src_fmt;
+
+ return 0;
+}
+
+static int mtk_fd_s_fmt_out_mp(struct file *file, void *fh,
+ struct v4l2_format *f)
+{
+ struct mtk_fd_ctx *ctx = fh_to_ctx(fh);
+ struct vb2_queue *vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
+
+ /* Change not allowed if queue is streaming. */
+ if (vb2_is_streaming(vq)) {
+ dev_err(ctx->dev, "Failed to set format, vb2 is busy\n");
+ return -EBUSY;
+ }
+
+ mtk_fd_try_fmt_out_mp(file, fh, f);
+ ctx->src_fmt = f->fmt.pix_mp;
+
+ return 0;
+}
+
+static int mtk_fd_enum_fmt_meta_cap(struct file *file, void *fh,
+ struct v4l2_fmtdesc *f)
+{
+ if (f->index)
+ return -EINVAL;
+
+ strscpy(f->description, "Face detection result",
+ sizeof(f->description));
+ f->pixelformat = V4L2_META_FMT_MTFD_RESULT;
+ f->flags = 0;
+
+ return 0;
+}
+
+static int mtk_fd_g_fmt_meta_cap(struct file *file, void *fh,
+ struct v4l2_format *f)
+{
+ f->fmt.meta.dataformat = V4L2_META_FMT_MTFD_RESULT;
+ f->fmt.meta.buffersize = sizeof(struct fd_user_output);
+
+ return 0;
+}
+
+static const struct vb2_ops mtk_fd_vb2_ops = {
+ .queue_setup = mtk_fd_vb2_queue_setup,
+ .buf_out_validate = mtk_fd_vb2_buf_out_validate,
+ .buf_prepare = mtk_fd_vb2_buf_prepare,
+ .buf_queue = mtk_fd_vb2_buf_queue,
+ .start_streaming = mtk_fd_vb2_start_streaming,
+ .stop_streaming = mtk_fd_vb2_stop_streaming,
+ .wait_prepare = vb2_ops_wait_prepare,
+ .wait_finish = vb2_ops_wait_finish,
+ .buf_request_complete = mtk_fd_vb2_request_complete,
+};
+
+static const struct v4l2_ioctl_ops mtk_fd_v4l2_video_out_ioctl_ops = {
+ .vidioc_querycap = mtk_fd_querycap,
+ .vidioc_enum_fmt_vid_out = mtk_fd_enum_fmt_out_mp,
+ .vidioc_g_fmt_vid_out_mplane = mtk_fd_g_fmt_out_mp,
+ .vidioc_s_fmt_vid_out_mplane = mtk_fd_s_fmt_out_mp,
+ .vidioc_try_fmt_vid_out_mplane = mtk_fd_try_fmt_out_mp,
+ .vidioc_enum_fmt_meta_cap = mtk_fd_enum_fmt_meta_cap,
+ .vidioc_g_fmt_meta_cap = mtk_fd_g_fmt_meta_cap,
+ .vidioc_s_fmt_meta_cap = mtk_fd_g_fmt_meta_cap,
+ .vidioc_try_fmt_meta_cap = mtk_fd_g_fmt_meta_cap,
+ .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs,
+ .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs,
+ .vidioc_expbuf = v4l2_m2m_ioctl_expbuf,
+ .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf,
+ .vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
+ .vidioc_qbuf = v4l2_m2m_ioctl_qbuf,
+ .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,
+ .vidioc_streamon = v4l2_m2m_ioctl_streamon,
+ .vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
+ .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+ .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+};
+
+static int
+mtk_fd_queue_init(void *priv, struct vb2_queue *src_vq,
+ struct vb2_queue *dst_vq)
+{
+ struct mtk_fd_ctx *ctx = priv;
+ int ret;
+
+ src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+ src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
+ src_vq->supports_requests = true;
+ src_vq->drv_priv = ctx;
+ src_vq->ops = &mtk_fd_vb2_ops;
+ src_vq->mem_ops = &vb2_dma_contig_memops;
+ src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
+ src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+ src_vq->lock = &ctx->fd_dev->vfd_lock;
+ src_vq->dev = ctx->fd_dev->v4l2_dev.dev;
+
+ ret = vb2_queue_init(src_vq);
+ if (ret)
+ return ret;
+
+ dst_vq->type = V4L2_BUF_TYPE_META_CAPTURE;
+ dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
+ dst_vq->drv_priv = ctx;
+ dst_vq->ops = &mtk_fd_vb2_ops;
+ dst_vq->mem_ops = &vb2_dma_contig_memops;
+ dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
+ dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+ dst_vq->lock = &ctx->fd_dev->vfd_lock;
+ dst_vq->dev = ctx->fd_dev->v4l2_dev.dev;
+
+ return vb2_queue_init(dst_vq);
+}
+
+struct v4l2_ctrl_config mtk_fd_controls[] = {
+ {
+ .id = V4L2_CID_MTK_FD_SCALE_DOWN_IMG_WIDTH,
+ .name = "FD scale image widths",
+ .type = V4L2_CTRL_TYPE_U16,
+ .min = MTK_FD_OUTPUT_MIN_WIDTH,
+ .max = MTK_FD_OUTPUT_MAX_WIDTH,
+ .step = 1,
+ .def = MTK_FD_OUTPUT_MAX_WIDTH,
+ .dims = { MTK_FD_SCALE_ARR_NUM },
+ },
+ {
+ .id = V4L2_CID_MTK_FD_SCALE_DOWN_IMG_HEIGHT,
+ .name = "FD scale image heights",
+ .type = V4L2_CTRL_TYPE_U16,
+ .min = MTK_FD_OUTPUT_MIN_HEIGHT,
+ .max = MTK_FD_OUTPUT_MAX_HEIGHT,
+ .step = 1,
+ .def = MTK_FD_OUTPUT_MAX_HEIGHT,
+ .dims = { MTK_FD_SCALE_ARR_NUM },
+ },
+ {
+ .id = V4L2_CID_MTK_FD_SCALE_IMG_NUM,
+ .name = "FD scale size counts",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .min = 0,
+ .max = MTK_FD_SCALE_ARR_NUM,
+ .step = 1,
+ .def = 0,
+ },
+ {
+ .id = V4L2_CID_MTK_FD_DETECT_POSE,
+ .name = "FD detect face angle and directions",
+ .type = V4L2_CTRL_TYPE_U16,
+ .min = 0,
+ .max = 0xffff,
+ .step = 1,
+ .def = 0x3ff,
+ .dims = { MTK_FD_FACE_ANGLE_NUM},
+ },
+ {
+ .id = V4L2_CID_MTK_FD_DETECT_SPEED,
+ .name = "FD detection speedup",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .min = 0,
+ .max = MTK_FD_MAX_SPEEDUP,
+ .step = 1,
+ .def = 0,
+ },
+ {
+ .id = V4L2_CID_MTK_FD_DETECTION_MODEL,
+ .name = "FD use extra model",
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .min = 0,
+ .max = 1,
+ .step = 1,
+ .def = 0,
+ },
+};
+
+static int mtk_fd_ctrls_setup(struct mtk_fd_ctx *ctx)
+{
+ struct v4l2_ctrl_handler *hdl = &ctx->hdl;
+ struct v4l2_ctrl *ctl;
+ int i;
+
+ v4l2_ctrl_handler_init(hdl, V4L2_CID_MTK_FD_MAX);
+ if (hdl->error)
+ return hdl->error;
+
+ for (i = 0; i < ARRAY_SIZE(mtk_fd_controls); i++) {
+ ctl = v4l2_ctrl_new_custom(hdl, &mtk_fd_controls[i], ctx);
+ if (hdl->error) {
+ v4l2_ctrl_handler_free(hdl);
+ dev_err(ctx->dev, "Failed to register controls:%d", i);
+ return hdl->error;
+ }
+ }
+
+ ctx->fh.ctrl_handler = &ctx->hdl;
+ v4l2_ctrl_handler_setup(hdl);
+
+ return 0;
+}
+
+static unsigned int get_fd_img_fmt(unsigned int fourcc)
+{
+ switch (fourcc) {
+ case V4L2_PIX_FMT_VYUY:
+ return MTK_FD_HW_FMT_VYUY;
+ case V4L2_PIX_FMT_YUYV:
+ return MTK_FD_HW_FMT_YUYV;
+ case V4L2_PIX_FMT_YVYU:
+ return MTK_FD_HW_FMT_YVYU;
+ case V4L2_PIX_FMT_UYVY:
+ return MTK_FD_HW_FMT_UYVY;
+ case V4L2_PIX_FMT_NV16M:
+ return MTK_FD_HW_FMT_YUV_2P;
+ case V4L2_PIX_FMT_NV61M:
+ return MTK_FD_HW_FMT_YVU_2P;
+ default:
+ return MTK_FD_HW_FMT_UNKNOWN;
+ }
+}
+
+static void init_ctx_fmt(struct mtk_fd_ctx *ctx)
+{
+ struct v4l2_pix_format_mplane *src_fmt = &ctx->src_fmt;
+ struct v4l2_meta_format *dst_fmt = &ctx->dst_fmt;
+
+ /* Initialize M2M source fmt */
+ src_fmt->width = MTK_FD_OUTPUT_MAX_WIDTH;
+ src_fmt->height = MTK_FD_OUTPUT_MAX_HEIGHT;
+ mtk_fd_fill_pixfmt_mp(src_fmt, &mtk_fd_img_fmts[0]);
+
+ /* Initialize M2M destination fmt */
+ dst_fmt->buffersize = sizeof(struct fd_user_output);
+ dst_fmt->dataformat = V4L2_META_FMT_MTFD_RESULT;
+}
+
+/*
+ * V4L2 file operations.
+ */
+static int mtk_vfd_open(struct file *filp)
+{
+ struct mtk_fd_dev *fd = video_drvdata(filp);
+ struct video_device *vdev = video_devdata(filp);
+ struct mtk_fd_ctx *ctx;
+ int ret;
+
+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+ ctx->fd_dev = fd;
+ ctx->dev = fd->dev;
+ fd->ctx = ctx;
+
+ v4l2_fh_init(&ctx->fh, vdev);
+ filp->private_data = &ctx->fh;
+
+ init_ctx_fmt(ctx);
+
+ ret = mtk_fd_ctrls_setup(ctx);
+ if (ret) {
+ dev_err(ctx->dev, "Failed to set up controls:%d\n", ret);
+ goto err_fh_exit;
+ }
+
+ ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(fd->m2m_dev, ctx,
+ &mtk_fd_queue_init);
+ if (IS_ERR(ctx->fh.m2m_ctx)) {
+ ret = PTR_ERR(ctx->fh.m2m_ctx);
+ goto err_free_ctrl_handler;
+ }
+
+ v4l2_fh_add(&ctx->fh);
+
+ return 0;
+
+err_free_ctrl_handler:
+ v4l2_ctrl_handler_free(&ctx->hdl);
+err_fh_exit:
+ v4l2_fh_exit(&ctx->fh);
+ kfree(ctx);
+
+ return ret;
+}
+
+static int mtk_vfd_release(struct file *filp)
+{
+ struct mtk_fd_ctx *ctx = container_of(filp->private_data,
+ struct mtk_fd_ctx, fh);
+
+ v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
+
+ v4l2_ctrl_handler_free(&ctx->hdl);
+ v4l2_fh_del(&ctx->fh);
+ v4l2_fh_exit(&ctx->fh);
+
+ kfree(ctx);
+
+ return 0;
+}
+
+static const struct v4l2_file_operations fd_video_fops = {
+ .owner = THIS_MODULE,
+ .open = mtk_vfd_open,
+ .release = mtk_vfd_release,
+ .poll = v4l2_m2m_fop_poll,
+ .unlocked_ioctl = video_ioctl2,
+ .mmap = v4l2_m2m_fop_mmap,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl32 = v4l2_compat_ioctl32,
+#endif
+
+};
+
+static void mtk_fd_fill_user_param(struct user_param *user_param,
+ struct v4l2_ctrl_handler *hdl)
+{
+ struct v4l2_ctrl *ctrl;
+ int i;
+
+ ctrl = v4l2_ctrl_find(hdl, V4L2_CID_MTK_FD_SCALE_DOWN_IMG_WIDTH);
+ if (ctrl)
+ for (i = 0; i < ctrl->elems; i++)
+ user_param->scale_img_width[i] = ctrl->p_new.p_u16[i];
+ ctrl = v4l2_ctrl_find(hdl, V4L2_CID_MTK_FD_SCALE_DOWN_IMG_HEIGHT);
+ if (ctrl)
+ for (i = 0; i < ctrl->elems; i++)
+ user_param->scale_img_height[i] = ctrl->p_new.p_u16[i];
+ ctrl = v4l2_ctrl_find(hdl, V4L2_CID_MTK_FD_SCALE_IMG_NUM);
+ if (ctrl)
+ user_param->scale_img_num = ctrl->val;
+
+ ctrl = v4l2_ctrl_find(hdl, V4L2_CID_MTK_FD_DETECT_POSE);
+ if (ctrl)
+ for (i = 0; i < ctrl->elems; i++)
+ user_param->face_directions[i] = ctrl->p_new.p_u16[i];
+ ctrl = v4l2_ctrl_find(hdl, V4L2_CID_MTK_FD_DETECT_SPEED);
+ if (ctrl)
+ user_param->fd_speedup = ctrl->val;
+ ctrl = v4l2_ctrl_find(hdl, V4L2_CID_MTK_FD_DETECTION_MODEL);
+ if (ctrl)
+ user_param->fd_extra_model = ctrl->val;
+}
+
+static void mtk_fd_device_run(void *priv)
+{
+ struct mtk_fd_ctx *ctx = priv;
+ struct mtk_fd_dev *fd = ctx->fd_dev;
+ struct vb2_v4l2_buffer *src_buf, *dst_buf;
+ struct fd_enq_param fd_param;
+
+ src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+ dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
+
+ fd_param.src_img[0].dma_addr =
+ vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0);
+ fd_param.user_result.dma_addr =
+ vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0);
+ fd_param.output_vaddr = (u64)vb2_plane_vaddr(&dst_buf->vb2_buf, 0);
+ fd_param.user_param.src_img_fmt =
+ get_fd_img_fmt(ctx->src_fmt.pixelformat);
+ if (ctx->src_fmt.num_planes == 2)
+ fd_param.src_img[1].dma_addr =
+ vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 1);
+ mtk_fd_fill_user_param(&fd_param.user_param, &ctx->hdl);
+
+ /* Complete request controls if any */
+ v4l2_ctrl_request_complete(src_buf->vb2_buf.req_obj.req, &ctx->hdl);
+
+ fd->output = (struct fd_user_output *)fd_param.output_vaddr;
+ mtk_fd_hw_job_exec(fd, &fd_param);
+}
+
+static struct v4l2_m2m_ops fd_m2m_ops = {
+ .device_run = mtk_fd_device_run,
+};
+
+static const struct media_device_ops fd_m2m_media_ops = {
+ .req_validate = vb2_request_validate,
+ .req_queue = v4l2_m2m_request_queue,
+};
+
+static int mtk_fd_video_device_register(struct mtk_fd_dev *fd)
+{
+ struct video_device *vfd = &fd->vfd;
+ struct v4l2_m2m_dev *m2m_dev = fd->m2m_dev;
+ struct device *dev = fd->dev;
+ int ret;
+
+ vfd->fops = &fd_video_fops;
+ vfd->release = video_device_release;
+ vfd->lock = &fd->vfd_lock;
+ vfd->v4l2_dev = &fd->v4l2_dev;
+ vfd->vfl_dir = VFL_DIR_M2M;
+ vfd->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_OUTPUT_MPLANE |
+ V4L2_CAP_META_CAPTURE;
+ vfd->ioctl_ops = &mtk_fd_v4l2_video_out_ioctl_ops;
+
+ strscpy(vfd->name, dev_driver_string(dev), sizeof(vfd->name));
+
+ video_set_drvdata(vfd, fd);
+
+ ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
+ if (ret) {
+ dev_err(dev, "Failed to register video device\n");
+ goto err_free_dev;
+ }
+
+ ret = v4l2_m2m_register_media_controller(m2m_dev, vfd,
+ MEDIA_ENT_F_PROC_VIDEO_STATISTICS);
+ if (ret) {
+ dev_err(dev, "Failed to init mem2mem media controller\n");
+ goto err_unreg_video;
+ }
+ return 0;
+
+err_unreg_video:
+ video_unregister_device(vfd);
+err_free_dev:
+ video_device_release(vfd);
+ return ret;
+}
+
+static int mtk_fd_dev_v4l2_init(struct mtk_fd_dev *fd)
+{
+ struct media_device *mdev = &fd->mdev;
+ struct device *dev = fd->dev;
+ int ret;
+
+ ret = v4l2_device_register(dev, &fd->v4l2_dev);
+ if (ret) {
+ dev_err(dev, "Failed to register v4l2 device\n");
+ return ret;
+ }
+
+ fd->m2m_dev = v4l2_m2m_init(&fd_m2m_ops);
+ if (IS_ERR(fd->m2m_dev)) {
+ dev_err(dev, "Failed to init mem2mem device\n");
+ ret = PTR_ERR(fd->m2m_dev);
+ goto err_unreg_v4l2_dev;
+ }
+
+ mdev->dev = dev;
+ strscpy(mdev->model, dev_driver_string(dev), sizeof(mdev->model));
+ snprintf(mdev->bus_info, sizeof(mdev->bus_info),
+ "platform:%s", dev_name(dev));
+ media_device_init(mdev);
+ mdev->ops = &fd_m2m_media_ops;
+ fd->v4l2_dev.mdev = mdev;
+
+ ret = mtk_fd_video_device_register(fd);
+ if (ret) {
+ dev_err(dev, "Failed to register video device\n");
+ goto err_cleanup_mdev;
+ }
+
+ ret = media_device_register(mdev);
+ if (ret) {
+ dev_err(dev, "Failed to register mem2mem media device\n");
+ goto err_unreg_vdev;
+ }
+
+ return 0;
+
+err_unreg_vdev:
+ v4l2_m2m_unregister_media_controller(fd->m2m_dev);
+ video_unregister_device(&fd->vfd);
+ video_device_release(&fd->vfd);
+err_cleanup_mdev:
+ media_device_cleanup(mdev);
+ v4l2_m2m_release(fd->m2m_dev);
+err_unreg_v4l2_dev:
+ v4l2_device_unregister(&fd->v4l2_dev);
+ return ret;
+}
+
+static void mtk_fd_dev_v4l2_release(struct mtk_fd_dev *fd)
+{
+ v4l2_m2m_unregister_media_controller(fd->m2m_dev);
+ video_unregister_device(&fd->vfd);
+ video_device_release(&fd->vfd);
+ media_device_cleanup(&fd->mdev);
+ v4l2_m2m_release(fd->m2m_dev);
+ v4l2_device_unregister(&fd->v4l2_dev);
+}
+
+static irqreturn_t mtk_fd_irq(int irq, void *data)
+{
+ struct mtk_fd_dev *fd = (struct mtk_fd_dev *)data;
+
+ /* must read this register otherwise HW will keep sending irq */
+ readl(fd->fd_base + MTK_FD_REG_OFFSET_INT_VAL);
+ fd->output->number = readl(fd->fd_base + MTK_FD_REG_OFFSET_RESULT);
+ dev_dbg(fd->dev, "mtk_fd_face_num:%d\n", fd->output->number);
+
+ pm_runtime_put((fd->dev));
+ mtk_fd_hw_job_finish(fd, VB2_BUF_STATE_DONE);
+ complete_all(&fd->fd_irq_done);
+ return IRQ_HANDLED;
+}
+
+static int mtk_fd_hw_get_scp_mem(struct mtk_fd_dev *fd)
+{
+ struct device *dev = fd->dev;
+ dma_addr_t addr;
+ void *ptr;
+ u32 ret;
+
+ /*
+ * Allocate coherent reserved memory for SCP firmware usage.
+ * The size of SCP composer's memory is fixed to 0x100000
+ * for the requirement of firmware.
+ */
+ ptr = dma_alloc_coherent(&fd->scp_pdev->dev,
+ MTK_FD_HW_WORK_BUF_SIZE, &addr, GFP_KERNEL);
+ if (!ptr)
+ return -ENOMEM;
+
+ fd->scp_mem.scp_addr = addr;
+ fd->scp_mem_virt_addr = ptr;
+ dev_info(dev, "scp addr:%pad va:%pK\n", &addr, ptr);
+
+ /*
+ * This reserved memory is also be used by FD HW.
+ * Need to get iova address for FD DMA.
+ */
+ addr = dma_map_resource(dev, addr, MTK_FD_HW_WORK_BUF_SIZE,
+ DMA_TO_DEVICE, DMA_ATTR_SKIP_CPU_SYNC);
+ if (dma_mapping_error(dev, addr)) {
+ dev_err(dev, "Failed to map scp iova\n");
+ ret = -ENOMEM;
+ goto fail_free_mem;
+ }
+ fd->scp_mem.dma_addr = addr;
+ dev_info(dev, "scp iova addr:%pad\n", &addr);
+
+ return 0;
+
+fail_free_mem:
+ dma_free_coherent(&fd->scp_pdev->dev, MTK_FD_HW_WORK_BUF_SIZE,
+ ptr, fd->scp_mem.scp_addr);
+ fd->scp_mem.scp_addr = 0;
+
+ return ret;
+}
+
+static int mtk_fd_probe(struct platform_device *pdev)
+{
+ struct mtk_fd_dev *fd;
+ struct device *dev = &pdev->dev;
+
+ struct resource *res;
+ phandle rproc_phandle;
+ int irq;
+ int ret;
+
+ fd = devm_kzalloc(&pdev->dev, sizeof(*fd), GFP_KERNEL);
+ if (!fd)
+ return -ENOMEM;
+
+ dev_set_drvdata(dev, fd);
+ fd->dev = dev;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(dev, "Failed to get irq by platform: %d\n", irq);
+ return irq;
+ }
+ ret = devm_request_irq(dev, irq, mtk_fd_irq, IRQF_SHARED,
+ dev_driver_string(dev),
+ fd);
+ if (ret) {
+ dev_err(dev, "Failed to request irq\n");
+ return ret;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ fd->fd_base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(fd->fd_base)) {
+ dev_err(dev, "Failed to get fd reg base\n");
+ return PTR_ERR(fd->fd_base);
+ }
+
+ fd->fd_clk = devm_clk_get(dev, "fd");
+ if (IS_ERR(fd->fd_clk)) {
+ dev_err(dev, "Failed to get fd_clk_img_fd clock\n");
+ return PTR_ERR(fd->fd_clk);
+ }
+
+ /* init scp */
+ fd->scp_pdev = scp_get_pdev(pdev);
+ if (!fd->scp_pdev) {
+ dev_err(dev, "Failed to get scp device\n");
+ return -ENODEV;
+ }
+
+ if (of_property_read_u32(fd->dev->of_node, "mediatek,scp",
+ &rproc_phandle)) {
+ dev_err(dev, "Failed to get scp device\n");
+ return -EINVAL;
+ }
+
+ fd->rproc_handle = rproc_get_by_phandle(rproc_phandle);
+ if (!fd->rproc_handle) {
+ dev_err(dev, "Failed to get FD's rproc_handle\n");
+ return -EINVAL;
+ }
+
+ ret = mtk_fd_hw_get_scp_mem(fd);
+ if (ret) {
+ dev_err(dev, "Failed to init scp memory: %d\n", ret);
+ return ret;
+ }
+
+ mutex_init(&fd->vfd_lock);
+ init_completion(&fd->fd_irq_done);
+ pm_runtime_enable(dev);
+
+ ret = mtk_fd_dev_v4l2_init(fd);
+ if (ret) {
+ dev_err(dev, "Failed to init v4l2 device: %d\n", ret);
+ goto err_destroy_mutex;
+ }
+
+ return 0;
+
+err_destroy_mutex:
+ mutex_destroy(&fd->vfd_lock);
+ pm_runtime_disable(fd->dev);
+ return ret;
+}
+
+static int mtk_fd_remove(struct platform_device *pdev)
+{
+ struct mtk_fd_dev *fd = dev_get_drvdata(&pdev->dev);
+
+ mtk_fd_dev_v4l2_release(fd);
+ pm_runtime_disable(&pdev->dev);
+ dma_unmap_page_attrs(fd->dev,
+ fd->scp_mem.dma_addr,
+ MTK_FD_HW_WORK_BUF_SIZE,
+ DMA_TO_DEVICE,
+ DMA_ATTR_SKIP_CPU_SYNC);
+ dma_free_coherent(&fd->scp_pdev->dev,
+ MTK_FD_HW_WORK_BUF_SIZE,
+ fd->scp_mem_virt_addr,
+ fd->scp_mem.scp_addr);
+ mutex_destroy(&fd->vfd_lock);
+ rproc_put(fd->rproc_handle);
+
+ return 0;
+}
+
+static int mtk_fd_suspend(struct device *dev)
+{
+ struct mtk_fd_dev *fd = dev_get_drvdata(dev);
+
+ if (pm_runtime_suspended(dev))
+ return 0;
+
+ if (fd->fd_stream_count)
+ if (mtk_fd_job_abort(fd))
+ mtk_fd_hw_job_finish(fd, VB2_BUF_STATE_ERROR);
+
+ /* suspend FD HW */
+ writel(0x0, fd->fd_base + MTK_FD_REG_OFFSET_INT_EN);
+ writel(0x0, fd->fd_base + MTK_FD_REG_OFFSET_HW_ENABLE);
+ clk_disable_unprepare(fd->fd_clk);
+ dev_dbg(dev, "%s:disable clock\n", __func__);
+
+ return 0;
+}
+
+static int mtk_fd_resume(struct device *dev)
+{
+ struct mtk_fd_dev *fd = dev_get_drvdata(dev);
+ int ret;
+
+ if (pm_runtime_suspended(dev))
+ return 0;
+
+ ret = clk_prepare_enable(fd->fd_clk);
+ if (ret < 0) {
+ dev_dbg(dev, "Failed to open fd clk:%d\n", ret);
+ return ret;
+ }
+
+ /* resume FD HW */
+ writel(MTK_FD_SET_HW_ENABLE, fd->fd_base + MTK_FD_REG_OFFSET_HW_ENABLE);
+ writel(0x1, fd->fd_base + MTK_FD_REG_OFFSET_INT_EN);
+ dev_dbg(dev, "%s:enable clock\n", __func__);
+
+ return 0;
+}
+
+static int mtk_fd_runtime_suspend(struct device *dev)
+{
+ struct mtk_fd_dev *fd = dev_get_drvdata(dev);
+
+ clk_disable_unprepare(fd->fd_clk);
+ return 0;
+}
+
+static int mtk_fd_runtime_resume(struct device *dev)
+{
+ struct mtk_fd_dev *fd = dev_get_drvdata(dev);
+ int ret;
+
+ ret = clk_prepare_enable(fd->fd_clk);
+ if (ret < 0) {
+ dev_err(dev, "Failed to open fd clk:%d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct dev_pm_ops mtk_fd_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(mtk_fd_suspend, mtk_fd_resume)
+ SET_RUNTIME_PM_OPS(mtk_fd_runtime_suspend, mtk_fd_runtime_resume, NULL)
+};
+
+static const struct of_device_id mtk_fd_of_ids[] = {
+ { .compatible = "mediatek,mt8183-fd", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, mtk_fd_of_ids);
+
+static struct platform_driver mtk_fd_driver = {
+ .probe = mtk_fd_probe,
+ .remove = mtk_fd_remove,
+ .driver = {
+ .name = "mtk-fd-4.0",
+ .of_match_table = of_match_ptr(mtk_fd_of_ids),
+ .pm = &mtk_fd_pm_ops,
+ }
+};
+module_platform_driver(mtk_fd_driver);
+
+MODULE_DESCRIPTION("Mediatek FD driver");
+MODULE_LICENSE("GPL");
diff --git a/include/uapi/linux/mtk-fd-v4l2-controls.h b/include/uapi/linux/mtk-fd-v4l2-controls.h
new file mode 100644
index 000000000000..9b814de05b0c
--- /dev/null
+++ b/include/uapi/linux/mtk-fd-v4l2-controls.h
@@ -0,0 +1,69 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+//
+// Copyright (c) 2019 MediaTek Inc.
+/*
+ * For V4L2_CID_MTK_FD_DETECT_POSE, User can set the desired face direction to
+ * be detected for each face angle, there are five face angle and 12 directions.
+ * Below shows the definition of face angle and face direction,
+ * and a recommended usage of for face detection, the more selected directions
+ * the longer HW process time needed.
+ *
+ * enum face_angle {
+ * MTK_FD_FACE_FRONT,
+ * MTK_FD_FACE_RIGHT_50,
+ * MTK_FD_FACE_LEFT_50,
+ * MTK_FD_FACE_RIGHT_90,
+ * MTK_FD_FACE_LEFT_90,
+ * MTK_FD_FACE_ANGLE_NUM,
+ * };
+ *
+ * struct face_direction_def {
+ * __u16 MTK_FD_FACE_DIR_0 : 1,
+ * MTK_FD_FACE_DIR_30 : 1,
+ * MTK_FD_FACE_DIR_60 : 1,
+ * MTK_FD_FACE_DIR_90 : 1,
+ * MTK_FD_FACE_DIR_120 : 1,
+ * MTK_FD_FACE_DIR_150 : 1,
+ * MTK_FD_FACE_DIR_180 : 1,
+ * MTK_FD_FACE_DIR_210 : 1,
+ * MTK_FD_FACE_DIR_240 : 1,
+ * MTK_FD_FACE_DIR_270 : 1,
+ * MTK_FD_FACE_DIR_300 : 1,
+ * MTK_FD_FACE_DIR_330 : 1,
+ * : 4;
+ * };
+ *
+ * Sample usage:
+ * u16 face_directions[MTK_FD_FACE_ANGLE_NUM] = {0};
+ *
+ * face_directions[MTK_FD_FACE_FRONT] = 0x3ff;
+ *
+ */
+
+#ifndef __UAPI_MTK_FD_V4L2_CONTROLS_H__
+#define __UAPI_MTK_FD_V4L2_CONTROLS_H__
+
+#include <linux/v4l2-controls.h>
+
+/* Set the face angle and directions to be detected */
+#define V4L2_CID_MTK_FD_DETECT_POSE (V4L2_CID_USER_MTK_FD_BASE + 1)
+
+/* Set image widths for an input image to be scaled down for face detection */
+#define V4L2_CID_MTK_FD_SCALE_DOWN_IMG_WIDTH (V4L2_CID_USER_MTK_FD_BASE + 2)
+
+/* Set image heights for an input image to be scaled down for face detection */
+#define V4L2_CID_MTK_FD_SCALE_DOWN_IMG_HEIGHT (V4L2_CID_USER_MTK_FD_BASE + 3)
+
+/* Set the length of scale down size array */
+#define V4L2_CID_MTK_FD_SCALE_IMG_NUM (V4L2_CID_USER_MTK_FD_BASE + 4)
+
+/* Set the detection speed, usually reducing accuracy. */
+#define V4L2_CID_MTK_FD_DETECT_SPEED (V4L2_CID_USER_MTK_FD_BASE + 5)
+
+/* Select the detection model or algorithm to be used. */
+#define V4L2_CID_MTK_FD_DETECTION_MODEL (V4L2_CID_USER_MTK_FD_BASE + 6)
+
+/* We reserve 16 controls for this driver. */
+#define V4L2_CID_MTK_FD_MAX 16
+
+#endif /* __UAPI_MTK_FD_V4L2_CONTROLS_H__ */
diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
index 3dcfc6148f99..eae876ea6d0a 100644
--- a/include/uapi/linux/v4l2-controls.h
+++ b/include/uapi/linux/v4l2-controls.h
@@ -192,6 +192,10 @@ enum v4l2_colorfx {
* We reserve 16 controls for this driver. */
#define V4L2_CID_USER_IMX_BASE (V4L2_CID_USER_BASE + 0x10b0)
+/* The base for the mediatek FD driver controls */
+/* We reserve 16 controls for this driver. */
+#define V4L2_CID_USER_MTK_FD_BASE (V4L2_CID_USER_BASE + 0x10d0)
+
/* MPEG-class control IDs */
/* The MPEG controls are applicable to all codec controls
* and the 'MPEG' part of the define is historical */
--
2.18.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 0/3] Exynos5 DMC minor fixes
From: Lukasz Luba @ 2019-09-06 10:13 UTC (permalink / raw)
To: devicetree, linux-kernel, linux-pm, linux-samsung-soc,
linux-arm-kernel
Cc: mark.rutland, willy.mh.wolff.ml, b.zolnierkie, krzk, Lukasz Luba,
cw00.choi, kyungmin.park, robh+dt, kgene, s.nawrocki,
myungjoo.ham, m.szyprowski
In-Reply-To: <CGME20190906101404eucas1p1d11e26276bfdacb7748f1391e29f45d0@eucas1p1.samsung.com>
Hi all,
This is a follow up patch set for the Exynos5 Dynamic Memory Controller
driver v13 [1]. The patches are based on Krzysztof's 'for-next' branch [2].
There are a few minor fixes captured during static analysis and a new
binding for 'samsung,K3QF2F20DB' LPDDR3 memory.
Regards,
Lukasz Luba
[1] https://lkml.org/lkml/2019/8/21/283
[2] https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux.git/log/?h=for-next
Lukasz Luba (3):
memory: Exynos5422: minor fixes in DMC
ARM: dts: exynos: fix too long line in memory device
dt-bindings: ddr: Add bindings for Samsung LPDDR3 memories
.../devicetree/bindings/ddr/lpddr3.txt | 29 +++++++++++++++++--
arch/arm/boot/dts/exynos5422-odroid-core.dtsi | 3 +-
drivers/memory/samsung/exynos5422-dmc.c | 4 +--
3 files changed, 31 insertions(+), 5 deletions(-)
--
2.17.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH 1/3] memory: Exynos5422: minor fixes in DMC
From: Lukasz Luba @ 2019-09-06 10:13 UTC (permalink / raw)
To: devicetree, linux-kernel, linux-pm, linux-samsung-soc,
linux-arm-kernel
Cc: mark.rutland, willy.mh.wolff.ml, b.zolnierkie, krzk, Lukasz Luba,
cw00.choi, kyungmin.park, robh+dt, kgene, s.nawrocki,
myungjoo.ham, m.szyprowski
In-Reply-To: <20190906101344.3535-1-l.luba@partner.samsung.com>
Small fixes captured by static analyzes.
Signed-off-by: Lukasz Luba <l.luba@partner.samsung.com>
---
drivers/memory/samsung/exynos5422-dmc.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/memory/samsung/exynos5422-dmc.c b/drivers/memory/samsung/exynos5422-dmc.c
index 8c2ec29a7d57..a809fa997c03 100644
--- a/drivers/memory/samsung/exynos5422-dmc.c
+++ b/drivers/memory/samsung/exynos5422-dmc.c
@@ -269,7 +269,7 @@ static int exynos5_init_freq_table(struct exynos5_dmc *dmc,
return 0;
err_free_tables:
- kfree(dmc->opp);
+ devm_kfree(dmc->dev, dmc->opp);
err_opp:
dev_pm_opp_of_remove_table(dmc->dev);
@@ -732,7 +732,7 @@ static struct devfreq_dev_profile exynos5_dmc_df_profile = {
* statistics engine which supports only registered values. Thus, some alignment
* must be made.
*/
-unsigned long
+static unsigned long
exynos5_dmc_align_init_freq(struct exynos5_dmc *dmc,
unsigned long bootloader_init_freq)
{
--
2.17.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 2/3] ARM: dts: exynos: fix too long line in memory device
From: Lukasz Luba @ 2019-09-06 10:13 UTC (permalink / raw)
To: devicetree, linux-kernel, linux-pm, linux-samsung-soc,
linux-arm-kernel
Cc: mark.rutland, willy.mh.wolff.ml, b.zolnierkie, krzk, Lukasz Luba,
cw00.choi, kyungmin.park, robh+dt, kgene, s.nawrocki,
myungjoo.ham, m.szyprowski
In-Reply-To: <20190906101344.3535-1-l.luba@partner.samsung.com>
Small fix moving the comment to line above making sure the lines do not
exceed 80 characters.
Signed-off-by: Lukasz Luba <l.luba@partner.samsung.com>
---
arch/arm/boot/dts/exynos5422-odroid-core.dtsi | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/exynos5422-odroid-core.dtsi b/arch/arm/boot/dts/exynos5422-odroid-core.dtsi
index fe885ca969af..059fa32d1a8f 100644
--- a/arch/arm/boot/dts/exynos5422-odroid-core.dtsi
+++ b/arch/arm/boot/dts/exynos5422-odroid-core.dtsi
@@ -103,7 +103,8 @@
timings_samsung_K3QF2F20DB_800mhz: lpddr3-timings@800000000 {
compatible = "jedec,lpddr3-timings";
- reg = <800000000>; /* workaround: it shows max-freq */
+ /* workaround: 'reg' shows max-freq */
+ reg = <800000000>;
min-freq = <100000000>;
tRFC = <65000>;
tRRD = <6000>;
--
2.17.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 3/3] dt-bindings: ddr: Add bindings for Samsung LPDDR3 memories
From: Lukasz Luba @ 2019-09-06 10:13 UTC (permalink / raw)
To: devicetree, linux-kernel, linux-pm, linux-samsung-soc,
linux-arm-kernel
Cc: mark.rutland, willy.mh.wolff.ml, b.zolnierkie, krzk, Lukasz Luba,
cw00.choi, kyungmin.park, robh+dt, kgene, s.nawrocki,
myungjoo.ham, m.szyprowski
In-Reply-To: <20190906101344.3535-1-l.luba@partner.samsung.com>
Add description of bindings for Samsung k3qf2f20db LPDDR3 memory.
Minor fixes in the old documentation.
Signed-off-by: Lukasz Luba <l.luba@partner.samsung.com>
---
.../devicetree/bindings/ddr/lpddr3.txt | 29 +++++++++++++++++--
1 file changed, 27 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/ddr/lpddr3.txt b/Documentation/devicetree/bindings/ddr/lpddr3.txt
index 3b2485b84b3f..de0905239767 100644
--- a/Documentation/devicetree/bindings/ddr/lpddr3.txt
+++ b/Documentation/devicetree/bindings/ddr/lpddr3.txt
@@ -40,10 +40,34 @@ Child nodes:
a given speed-bin. Please see Documentation/devicetree/
bindings/ddr/lpddr3-timings.txt for more information on "lpddr3-timings"
+Samsung K3QF2F20DB LPDDR3 memory
+------------------------------------------------------------
+
+This binding uses the LPDDR3 binding (described above)
+
+Required properties:
+- compatible: Should be:
+ "samsung,K3QF2F20DB"
+ followed by "jedec,lpddr3"
+- density : <u32> representing density in Mb (Mega bits)
+- io-width : <u32> representing bus width. Possible value 32
+- #address-cells: Must be set to 1
+- #size-cells: Must be set to 0
+
+Optional properties:
+
+The optional properties are the same as in the LPDDR3 generic bindings and
+values should be taken from the data-sheet. Detailed bindings are described
+above.
+
+Child nodes:
+
+Detailed bindings are described in LPDDR3 generic bindings described above.
+
Example:
samsung_K3QF2F20DB: lpddr3 {
- compatible = "Samsung,K3QF2F20DB", "jedec,lpddr3";
+ compatible = "samsung,K3QF2F20DB", "jedec,lpddr3";
density = <16384>;
io-width = <32>;
#address-cells = <1>;
@@ -73,7 +97,8 @@ samsung_K3QF2F20DB: lpddr3 {
timings_samsung_K3QF2F20DB_800mhz: lpddr3-timings@800000000 {
compatible = "jedec,lpddr3-timings";
- reg = <800000000>; /* workaround: it shows max-freq */
+ /* workaround: 'reg' shows max-freq */
+ reg = <800000000>;
min-freq = <100000000>;
tRFC = <65000>;
tRRD = <6000>;
--
2.17.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* Re: [PATCH v5 0/3] PM / AVS: SVS: Introduce SVS engine
From: Roger Lu @ 2019-09-06 10:15 UTC (permalink / raw)
To: Kevin Hilman
Cc: Mark Rutland, Nicolas Boichat, Angus Lin, devicetree,
Stephen Boyd, linux-pm, linux-kernel, HenryC Chen, yt.lee,
Fan Chen, Rob Herring, linux-mediatek, Matthias Brugger,
Nishanth Menon, linux-arm-kernel
In-Reply-To: <20190906100514.30803-1-roger.lu@mediatek.com>
Excuse me, I forgot to add "changes since" below. Add it back now.
On Fri, 2019-09-06 at 18:05 +0800, Roger Lu wrote:
> 1. SVS driver use OPP adjust event in [1] to update OPP table voltage part.
> 2. SVS dts node refers to CPU opp table [2] and GPU opp table [3].
> 3. SVS dts node refers to thermal efuse [4] and PMIC regulator [5].
>
> [1] https://patchwork.kernel.org/patch/11092245/
> [2] https://patchwork.kernel.org/patch/10934123/
> [3] https://patchwork.kernel.org/patch/11132381/
> [4] https://patchwork.kernel.org/patch/11093655/
> [5] https://patchwork.kernel.org/patch/11110493/
changes since v4:
- Add SVS dts node patch in SVS patch series.
> Roger Lu (3):
> dt-bindings: soc: add mtk svs dt-bindings
> arm64: dts: mt8183: add svs device information
> PM / AVS: SVS: Introduce SVS engine
>
> .../devicetree/bindings/power/mtk-svs.txt | 88 +
> arch/arm64/boot/dts/mediatek/mt8183-evb.dts | 16 +
> arch/arm64/boot/dts/mediatek/mt8183.dtsi | 38 +
> drivers/power/avs/Kconfig | 10 +
> drivers/power/avs/Makefile | 1 +
> drivers/power/avs/mtk_svs.c | 2075 +++++++++++++++++
> include/linux/power/mtk_svs.h | 23 +
> 7 files changed, 2251 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/power/mtk-svs.txt
> create mode 100644 drivers/power/avs/mtk_svs.c
> create mode 100644 include/linux/power/mtk_svs.h
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v5 02/11] kselftest: arm64: add common utils and one testcase
From: Cristian Marussi @ 2019-09-06 10:26 UTC (permalink / raw)
To: Dave Martin
Cc: amit.kachhap, andreyknvl, shuah, linux-arm-kernel,
linux-kselftest
In-Reply-To: <20190904114752.GS27757@arm.com>
Hi
On 04/09/2019 12:47, Dave Martin wrote:
> ^Nit: "add one testcase" doesn't really describe what is being added here.
>
Yep I know...I was trying to stay under first commit line length limitations
> Maybe the following would work as the subject line:
>
> --8<--
> kselftest: arm64: mangle_pstate_invalid_compat_toggle and common utils
> -->8--
>
I'll grab it
> The remainder of the commit message looks fine.
>
> On Mon, Sep 02, 2019 at 12:29:23pm +0100, Cristian Marussi wrote:
>> Add some arm64/signal specific boilerplate and utility code to help
>> further testcases' development.
>>
>> Introduce also one simple testcase mangle_pstate_invalid_compat_toggle
>> and some related helpers: it is a simple mangle testcase which messes
>> with the ucontext_t from within the signal handler, trying to toggle
>> PSTATE state bits to switch the system between 32bit/64bit execution
>> state. Expects SIGSEGV on test PASS.
>>
>> Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
>> ---
>> v4 --> v5
>> - moved kernel headers include search to top level KSFT arm64 Makefile
>> - removed warning about kernel headers not found
>> - moved testcases/.gitignore up one level
>> v3 --> v4
>> - removed standalone mode
>> - fixed arm64/signal/README
>> - add file level comments: test layout / test description
>> - reduced verbosity
>> - removed spurious headers includes
>> - reviewed ID_AA64MMFR[1,2]_EL1 macros
>> - removed unused feats_ok
>> - simplified CPU features gathering
>> - reviewed included headers
>> - fixed/refactored get_header() and validation routines
>> - added test description
>> ---
>
> [...]
>
>> diff --git a/tools/testing/selftests/arm64/signal/test_signals.c b/tools/testing/selftests/arm64/signal/test_signals.c
>> new file mode 100644
>> index 000000000000..f05c6dbf8659
>> --- /dev/null
>> +++ b/tools/testing/selftests/arm64/signal/test_signals.c
>> @@ -0,0 +1,29 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Copyright (C) 2019 ARM Limited
>> + *
>> + * Generic test wrapper for arm64 signal tests.
>> + *
>> + * Each test provides its own tde struct tddescr descriptor to link with
>
> Typo? tdescr
>
Yes
> [...]
>
>> diff --git a/tools/testing/selftests/arm64/signal/test_signals_utils.c b/tools/testing/selftests/arm64/signal/test_signals_utils.c
>> new file mode 100644
>> index 000000000000..e2a5f37e6ad3
>> --- /dev/null
>> +++ b/tools/testing/selftests/arm64/signal/test_signals_utils.c
>> @@ -0,0 +1,269 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/* Copyright (C) 2019 ARM Limited */
>> +
>> +#include <stdio.h>
>> +#include <stdlib.h>
>> +#include <signal.h>
>> +#include <string.h>
>> +#include <unistd.h>
>> +#include <assert.h>
>> +#include <sys/auxv.h>
>> +#include <linux/auxvec.h>
>> +#include <ucontext.h>
>> +
>> +#include "test_signals.h"
>> +#include "test_signals_utils.h"
>> +#include "testcases/testcases.h"
>> +
>> +extern struct tdescr *current;
>> +
>> +static char *feats_store[FMAX_END] = {
>
> Nit: can we call this feat_names[]?ok
>
> "store" makes me think of loads and stores...
>
> Also, nit: can this be static const char *const []?
>
> String literals are immutable anyway, and I guess we don't intend too
> modify the pointers to the strings either...
>
Yes of course.
>> + " SSBS ",
>> + " PAN ",
>> + " UAO ",
>> +};
>> +
>> +#define MAX_FEATS_SZ 128
>> +static char feats_string[MAX_FEATS_SZ];
>> +
>> +static inline char *feats_to_string(unsigned long feats)
>> +{
>> + size_t flen = MAX_FEATS_SZ - 1;
>> +
>> + for (int i = 0; i < FMAX_END; i++) {
>> + if (feats & 1UL << i) {
>
> Nit: maybe have () around (1UL << i), though I think it makes no
> difference.
Yes it's better, I feared that, being not required, was frown upon.
>
>> + size_t tlen = strlen(feats_store[i]);
>> +
>> + assert(flen > tlen);
>> + flen -= tlen;
>> + strncat(feats_string, feats_store[i], flen);
>> + }
>> + }
>> +
>> + return feats_string;
>> +}
>> +
>> +static void unblock_signal(int signum)
>> +{
>> + sigset_t sset;
>> +
>> + sigemptyset(&sset);
>> + sigaddset(&sset, signum);
>> + sigprocmask(SIG_UNBLOCK, &sset, NULL);
>> +}
>> +
>> +static void default_result(struct tdescr *td, bool force_exit)
>> +{
>> + if (td->pass)
>> + fprintf(stderr, "==>> completed. PASS(1)\n");
>> + else
>> + fprintf(stdout, "==>> completed. FAIL(0)\n");
>> + if (force_exit)
>> + exit(td->pass ? EXIT_SUCCESS : EXIT_FAILURE);
>> +}
>> +
>> +static inline bool are_feats_ok(struct tdescr *td)
>> +{
>> + return (td->feats_required & td->feats_supported) == td->feats_required;
>> +}
>> +
>> +static void default_handler(int signum, siginfo_t *si, void *uc)
>> +{
>> + if (current->sig_trig && signum == current->sig_trig) {
>
> (Thinking about it, signum is never 0 because there is no signal 0.
> So we could write if (signum == current->sig_trig). But I think your
> code makes the intention clearer -- so no need to change it.)
>
Yes, in fact that's the reason I left it even if unneeded.
>> + fprintf(stderr, "Handling SIG_TRIG\n");
>> + current->triggered = 1;
>> + /* ->run was asserted NON-NULL in test_setup() already */
>> + current->run(current, si, uc);
>> + } else if (signum == SIGILL && !current->initialized) {
>> + /*
>> + * A SIGILL here while still not initialized means we failed
>> + * even to asses the existence of features during init
>> + */
>> + fprintf(stdout,
>> + "Got SIGILL test_init. Marking ALL features UNSUPPORTED.\n");
>> + current->feats_supported = 0;
>> + } else if (current->sig_ok && signum == current->sig_ok) {
>> + /*
>> + * it's a bug in the test code when this assert fail:
>> + * if a sig_trig was defined, it must have been used before
>> + * arriving here.
>> + */
>> + assert(!current->sig_trig || current->triggered);
>> + fprintf(stderr,
>> + "SIG_OK -- SP:0x%llX si_addr@:%p si_code:%d token@:%p offset:%ld\n",
>> + ((ucontext_t *)uc)->uc_mcontext.sp,
>> + si->si_addr, si->si_code, current->token,
>> + current->token - si->si_addr);
>> + /*
>> + * fake_sigreturn tests, which have sanity_enabled=1, set, at
>> + * the very last time, the token field to the SP address used
>> + * to place the fake sigframe: so token==0 means we never made
>> + * it to the end, segfaulting well-before, and the test is
>> + * possibly broken.
>> + */
>> + if (!current->sanity_disabled && !current->token) {
>> + fprintf(stdout,
>> + "current->token ZEROED...test is probably broken!\n");
>> + abort();
>> + }
>> + /*
>> + * Trying to narrow down the SEGV to the ones generated by
>> + * Kernel itself via arm64_notify_segfault().
>> + * This is a best-effort check anyway, and the si_code check may
>> + * need to change if this aspect of the kernel ABI changes.
>> + */
>> + if (current->sig_ok == SIGSEGV && si->si_code != SEGV_ACCERR) {
>> + fprintf(stdout,
>> + "si_code != SEGV_ACCERR...test is probably broken!\n");
>> + abort();
>> + }
>> + fprintf(stderr, "Handling SIG_OK\n");
>> + current->pass = 1;
>> + /*
>> + * Some tests can lead to SEGV loops: in such a case we want
>> + * to terminate immediately exiting straight away
>> + */
>> + default_result(current, 1);
>> + } else {
>> + if (signum == current->sig_unsupp && !are_feats_ok(current)) {
>> + fprintf(stderr,
>> + "-- RX SIG_UNSUPP on unsupported feat...OK\n");
>> + current->pass = 1;
>> + } else if (signum == SIGALRM && current->timeout) {
>> + fprintf(stderr, "-- Timeout !\n");
>> + } else {
>> + fprintf(stderr,
>> + "-- RX UNEXPECTED SIGNAL: %d\n", signum);
>> + }
>> + default_result(current, 1);
>> + }
>> +}
>> +
>> +static int default_setup(struct tdescr *td)
>> +{
>> + struct sigaction sa;
>> +
>> + sa.sa_sigaction = default_handler;
>> + sa.sa_flags = SA_SIGINFO | SA_RESTART;
>> + sa.sa_flags |= td->sa_flags;
>> + sigemptyset(&sa.sa_mask);
>> + /* uncatchable signals naturally skipped ... */
>> + for (int sig = 1; sig < 32; sig++)
>> + sigaction(sig, &sa, NULL);
>> + /*
>> + * RT Signals default disposition is Term but they cannot be
>> + * generated by the Kernel in response to our tests; so just catch
>> + * them all and report them as UNEXPECTED signals.
>> + */
>> + for (int sig = SIGRTMIN; sig <= SIGRTMAX; sig++)
>> + sigaction(sig, &sa, NULL);
>> +
>> + /* just in case...unblock explicitly all we need */
>> + if (td->sig_trig)
>> + unblock_signal(td->sig_trig);
>> + if (td->sig_ok)
>> + unblock_signal(td->sig_ok);
>> + if (td->sig_unsupp)
>> + unblock_signal(td->sig_unsupp);
>> +
>> + if (td->timeout) {
>> + unblock_signal(SIGALRM);
>> + alarm(td->timeout);
>> + }
>> + fprintf(stderr, "Registered handlers for all signals.\n");
>> +
>> + return 1;
>> +}
>> +
>> +static inline int default_trigger(struct tdescr *td)
>> +{
>> + return !raise(td->sig_trig);
>> +}
>> +
>> +static int test_init(struct tdescr *td)
>> +{
>> + td->minsigstksz = getauxval(AT_MINSIGSTKSZ);
>> + if (!td->minsigstksz)
>> + td->minsigstksz = MINSIGSTKSZ;
>> + fprintf(stderr, "Detected MINSTKSIGSZ:%d\n", td->minsigstksz);
>> +
>> + if (td->feats_required) {
>> + bool feats_ok = false;
>> +
>> + td->feats_supported = 0;
>> + /*
>> + * Checking for CPU required features using both the
>> + * auxval and the arm64 MRS Emulation to read sysregs.
>> + */
>> + if (getauxval(AT_HWCAP) & HWCAP_CPUID) {
>> + uint64_t val = 0;
>> +
>> + /* Uses HWCAP to check capability */
>> + if (getauxval(AT_HWCAP) & HWCAP_SSBS)
>> + td->feats_supported |= FEAT_SSBS;
>
> Should this be outside the HWCAP_CPUID check?
Right.
>
> It's only the get_regval(SYS_ID_foo) based checks that depend on
> HWCAP_CPUID.
>
>> + /* Uses MRS emulation to check capability */
>> + get_regval(SYS_ID_AA64MMFR1_EL1, val);
>> + if (ID_AA64MMFR1_EL1_PAN_SUPPORTED(val))
>> + td->feats_supported |= FEAT_PAN;
>> + /* Uses MRS emulation to check capability */
>> + get_regval(SYS_ID_AA64MMFR2_EL1, val);
>> + if (ID_AA64MMFR2_EL1_UAO_SUPPORTED(val))
>> + td->feats_supported |= FEAT_UAO;
>> + } else {
>> + fprintf(stderr,
>> + "HWCAP_CPUID NOT available. Mark ALL feats UNSUPPORTED.\n");
>> + }
>> + feats_ok = are_feats_ok(td);
>> + fprintf(stderr,
>> + "Required Features: [%s] %ssupported\n",
>> + feats_ok ? feats_to_string(td->feats_supported) :
>> + feats_to_string(td->feats_required ^
>> + td->feats_supported),
>
> Should this be something like:
> td->feats_required & ~td->feats_supported ?
>
> Otherwise we'll include features that are supported but not required,
> when printing the features that are NOT supported.
>
> Alternatively, we could just print out the required and supported sets
> separately and leave it up to the user to obverse how they are
> different.
>
> (Watch out for calling feats_to_string() twice in the same printf() call
> though.)
>
Ok. Reported information was poor in fact.
>> + !feats_ok ? "NOT " : "");
>> + }
>> +
>> + td->initialized = 1;
>> + return 1;
>> +}
>> +
>> +int test_setup(struct tdescr *td)
>> +{
>> + /* assert core invariants symptom of a rotten testcase */
>> + assert(current);
>> + assert(td);
>> + assert(td->name);
>> + assert(td->run);
>> +
>> + if (!test_init(td))
>> + return 0;
>> +
>> + if (td->setup)
>> + return td->setup(td);
>> + else
>> + return default_setup(td);
>> +}
>> +
>> +int test_run(struct tdescr *td)
>> +{
>> + if (td->sig_trig) {
>> + if (td->trigger)
>> + return td->trigger(td);
>> + else
>> + return default_trigger(td);
>> + } else {
>> + return td->run(td, NULL, NULL);
>> + }
>> +}
>> +
>> +void test_result(struct tdescr *td)
>> +{
>> + if (td->check_result)
>> + td->check_result(td);
>> + default_result(td, 0);
>> +}
>> +
>> +void test_cleanup(struct tdescr *td)
>> +{
>> + if (td->cleanup)
>> + td->cleanup(td);
>> +}
>> diff --git a/tools/testing/selftests/arm64/signal/test_signals_utils.h b/tools/testing/selftests/arm64/signal/test_signals_utils.h
>> new file mode 100644
>> index 000000000000..8658d1a7d4b9
>> --- /dev/null
>> +++ b/tools/testing/selftests/arm64/signal/test_signals_utils.h
>> @@ -0,0 +1,13 @@
>> +/* SPDX-License-Identifier: GPL-2.0 */
>> +/* Copyright (C) 2019 ARM Limited */
>> +
>> +#ifndef __TEST_SIGNALS_UTILS_H__
>> +#define __TEST_SIGNALS_UTILS_H__
>> +
>> +#include "test_signals.h"
>> +
>> +int test_setup(struct tdescr *td);
>> +void test_cleanup(struct tdescr *td);
>> +int test_run(struct tdescr *td);
>> +void test_result(struct tdescr *td);
>> +#endif
>> diff --git a/tools/testing/selftests/arm64/signal/testcases/mangle_pstate_invalid_compat_toggle.c b/tools/testing/selftests/arm64/signal/testcases/mangle_pstate_invalid_compat_toggle.c
>> new file mode 100644
>> index 000000000000..2cb118b0ba05
>> --- /dev/null
>> +++ b/tools/testing/selftests/arm64/signal/testcases/mangle_pstate_invalid_compat_toggle.c
>> @@ -0,0 +1,31 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Copyright (C) 2019 ARM Limited
>> + *
>> + * Try to mangle the ucontext from inside a signal handler, toggling
>> + * the execution state bit: this attempt must be spotted by Kernel and
>> + * the test case is expected to be terminated via SEGV.
>> + */
>> +
>> +#include "test_signals_utils.h"
>> +#include "testcases.h"
>> +
>> +static int mangle_invalid_pstate_run(struct tdescr *td, siginfo_t *si,
>> + ucontext_t *uc)
>> +{
>> + ASSERT_GOOD_CONTEXT(uc);
>> +
>> + /* This config should trigger a SIGSEGV by Kernel */
>> + uc->uc_mcontext.pstate ^= PSR_MODE32_BIT;
>> +
>> + return 1;
>> +}
>> +
>> +struct tdescr tde = {
>> + .sanity_disabled = true,
>> + .name = "MANGLE_PSTATE_INVALID_STATE_TOGGLE",
>> + .descr = "Mangling uc_mcontext with INVALID STATE_TOGGLE",
>> + .sig_trig = SIGUSR1,
>> + .sig_ok = SIGSEGV,
>> + .run = mangle_invalid_pstate_run,
>> +};
>> diff --git a/tools/testing/selftests/arm64/signal/testcases/testcases.c b/tools/testing/selftests/arm64/signal/testcases/testcases.c
>> new file mode 100644
>> index 000000000000..72e3f482b177
>> --- /dev/null
>> +++ b/tools/testing/selftests/arm64/signal/testcases/testcases.c
>> @@ -0,0 +1,151 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/* Copyright (C) 2019 ARM Limited */
>> +#include "testcases.h"
>> +
>> +struct _aarch64_ctx *get_header(struct _aarch64_ctx *head, uint32_t magic,
>> + size_t resv_sz, size_t *offset)
>> +{
>> + size_t offs = 0;
>> + struct _aarch64_ctx *found = NULL;
>> +
>> + if (!head)
>> + return found;
>> +
>
> I suggest you also check for resv_sz < HDR_SZ, since the while()
> condition assumes that resv_sz - HDR_SZ doesn't underflow.
>
> For now, I think resv_sz is already sizeof(__reserved) so this is never
> true, but I suspect we will want to reuse this code eventually to looko
> at the contents of extra_context. Then, resv_sz would be the
> extra_context size rather than a fixed constant.
>
Ok....in fact I think I removed recently such check...not sure why o_O
I'll fix it.
>> + while (offs <= resv_sz - HDR_SZ &&
>> + head->magic != magic && head->magic) {
>> + offs += head->size;
>> + head = GET_RESV_NEXT_HEAD(head);
>> + }
>> + if (head->magic == magic) {
>> + found = head;
>> + if (offset)
>> + *offset = offs;
>> + }
>
> Although there appears to be some code duplication here, I guess you
> need things this way to do the right thing if called with magic==0.
>
> So I guess this is fine.
>
Yes that was exactly the point, and it seemed to me that removing further
duplication would have made the code more complex and unreadable.
> Ultimately it would be good to have GET_RESV_NEXT_HEAD() work more
> like an iterator, doing integrity bounds/alignment checks and updating
> offs as it goes, but for now I think the code is sufficient. We can
> always beef it up later to catch more kinds of error from the kernel.
>
Yes I remember you told me that on a previous iteration, but for now I left the
GET_RESV_NEXT_HEAD() as it was without embedding the bounds checking logic
because it is indirectly used also by the validation function that I use in
the ASSERT_GOOD/BAD_CONTEXT() macros, so it should be able to handle
artficially badly formed and corrupted frames without bailing out: it just walks
and any kind of logic is handled outside...but maybe I'm overthinking
(certainly I have not explained this reasons anywhere...I'll add a comment)
>> +
>> + return found;
>> +}
>> +
>> +bool validate_extra_context(struct extra_context *extra, char **err)
>> +{
>> + struct _aarch64_ctx *term;
>> +
>> + if (!extra || !err)
>> + return false;
>> +
>> + fprintf(stderr, "Validating EXTRA...\n");
>> + term = GET_RESV_NEXT_HEAD(extra);
>> + if (!term || term->magic || term->size) {
>> + *err = "Missing terminator after EXTRA context";
>> + return false;
>> + }
>> + if (extra->datap & 0x0fUL)
>> + *err = "Extra DATAP misaligned";
>> + else if (extra->size & 0x0fUL)
>> + *err = "Extra SIZE misaligned";
>> + else if (extra->datap != (uint64_t)term + sizeof(*term))
>> + *err = "Extra DATAP misplaced (not contiguos)";
>> + if (*err)
>> + return false;
>> +
>> + return true;
>> +}
>> +
>> +bool validate_reserved(ucontext_t *uc, size_t resv_sz, char **err)
>> +{
>> + bool terminated = false;
>> + size_t offs = 0;
>> + int flags = 0;
>> + struct extra_context *extra = NULL;
>> + struct _aarch64_ctx *head =
>> + (struct _aarch64_ctx *)uc->uc_mcontext.__reserved;
>> +
>> + if (!err)
>> + return false;
>> + /* Walk till the end terminator verifying __reserved contents */
>> + while (head && !terminated && offs < resv_sz) {
>> + if ((uint64_t)head & 0x0fUL) {
>> + *err = "Misaligned HEAD";
>> + return false;
>> + }
>> +
>> + switch (head->magic) {
>> + case 0:
>> + if (head->size)
>> + *err = "Bad size for terminator";
>> + else
>> + terminated = true;
>> + break;
>> + case FPSIMD_MAGIC:
>> + if (flags & FPSIMD_CTX)
>> + *err = "Multiple FPSIMD_MAGIC";
>> + else if (head->size !=
>> + sizeof(struct fpsimd_context))
>> + *err = "Bad size for fpsimd_context";
>> + flags |= FPSIMD_CTX;
>> + break;
>> + case ESR_MAGIC:
>> + if (head->size != sizeof(struct esr_context))
>> + fprintf(stderr,
>> + "Bad size for esr_context is not an error...just ignore.\n");
>> + break;
>
> Although it's not essential, I'd prefer that we enforce the correct
> size here. All records, including esr_context are intended to be
> fixed-size.
>
> In the kernel we check a bit more loosely -- this allows userspace to
> delete a record using head->size += next_head->size. This way no
> memmove() is needed to shuffle subsequent records down. I don't know
> whether any userspace code makes use of this -- prior to SVE there were
> no optional records except for esr_context, and sigreturn ignores that
> in any case so deleting it is pointless.
>
> The kernel should never insert extra padding between records though,
> so I think it makes sense to have strict size checks in this test.
>
Ok, I'll do. I kept it loose as it is in Kernel, because in some past tests
(now removed) I used to play also with esr_context size to build easily an inflated
fake sigframe (but good) and adding some badness on top of it.
> [...]
>
> Cheers
> ---Dave
>
Cheers
Cristian
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [v2] ACPI: support for NXP i2c controller
From: Andy Shevchenko @ 2019-09-06 10:31 UTC (permalink / raw)
To: Biwen Li
Cc: Wolfram Sang, Sascha Hauer, Udit Kumar, Rafael J. Wysocki,
Linux Kernel Mailing List, Leo Li, ACPI Devel Maling List,
Meenakshi Aggarwal, linux-i2c, Chuanhua Han, Rafael J. Wysocki,
Shawn Guo, linux-arm Mailing List
In-Reply-To: <20190906075319.21244-1-biwen.li@nxp.com>
On Fri, Sep 6, 2019 at 11:03 AM Biwen Li <biwen.li@nxp.com> wrote:
>
> From: Chuanhua Han <chuanhua.han@nxp.com>
>
> Enable NXP i2c controller to boot with ACPI
>
Thanks, the code looks good to me,
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
though...
> Signed-off-by: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>
> Signed-off-by: Udit Kumar <udit.kumar@nxp.com>
> Signed-off-by: Chuanhua Han <chuanhua.han@nxp.com>
This SoB chain is a bit odd. Who is the author of this? The first SoB
in the chain usually points to the first (main) author. There is also
possible to change that, though in that case for the rest we now use
Co-developed-by tag rather than SoB.
In any case, if Rafael and Wolfram are okay with this, I have no objections.
> Signed-off-by: Biwen Li <biwen.li@nxp.com>
> ---
> Change in v2:
> - Simplify code
> - Adjust header file order
> - Not use ACPI_PTR()
>
> drivers/acpi/acpi_apd.c | 7 +++++++
> drivers/i2c/busses/i2c-imx.c | 17 +++++++++++++----
> 2 files changed, 20 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/acpi/acpi_apd.c b/drivers/acpi/acpi_apd.c
> index 7cd0c9ac71ea..71511ae2dfcd 100644
> --- a/drivers/acpi/acpi_apd.c
> +++ b/drivers/acpi/acpi_apd.c
> @@ -160,11 +160,17 @@ static const struct apd_device_desc hip08_i2c_desc = {
> .setup = acpi_apd_setup,
> .fixed_clk_rate = 250000000,
> };
> +
> static const struct apd_device_desc thunderx2_i2c_desc = {
> .setup = acpi_apd_setup,
> .fixed_clk_rate = 125000000,
> };
>
> +static const struct apd_device_desc nxp_i2c_desc = {
> + .setup = acpi_apd_setup,
> + .fixed_clk_rate = 350000000,
> +};
> +
> static const struct apd_device_desc hip08_spi_desc = {
> .setup = acpi_apd_setup,
> .fixed_clk_rate = 250000000,
> @@ -238,6 +244,7 @@ static const struct acpi_device_id acpi_apd_device_ids[] = {
> { "HISI02A1", APD_ADDR(hip07_i2c_desc) },
> { "HISI02A2", APD_ADDR(hip08_i2c_desc) },
> { "HISI0173", APD_ADDR(hip08_spi_desc) },
> + { "NXP0001", APD_ADDR(nxp_i2c_desc) },
> #endif
> { }
> };
> diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
> index 15f6cde6452f..a3b61336fe55 100644
> --- a/drivers/i2c/busses/i2c-imx.c
> +++ b/drivers/i2c/busses/i2c-imx.c
> @@ -20,6 +20,7 @@
> *
> */
>
> +#include <linux/acpi.h>
> #include <linux/clk.h>
> #include <linux/completion.h>
> #include <linux/delay.h>
> @@ -255,6 +256,12 @@ static const struct of_device_id i2c_imx_dt_ids[] = {
> };
> MODULE_DEVICE_TABLE(of, i2c_imx_dt_ids);
>
> +static const struct acpi_device_id i2c_imx_acpi_ids[] = {
> + {"NXP0001", .driver_data = (kernel_ulong_t)&vf610_i2c_hwdata},
> + { }
> +};
> +MODULE_DEVICE_TABLE(acpi, i2c_imx_acpi_ids);
> +
> static inline int is_imx1_i2c(struct imx_i2c_struct *i2c_imx)
> {
> return i2c_imx->hwdata->devtype == IMX1_I2C;
> @@ -1048,14 +1055,13 @@ static const struct i2c_algorithm i2c_imx_algo = {
>
> static int i2c_imx_probe(struct platform_device *pdev)
> {
> - const struct of_device_id *of_id = of_match_device(i2c_imx_dt_ids,
> - &pdev->dev);
> struct imx_i2c_struct *i2c_imx;
> struct resource *res;
> struct imxi2c_platform_data *pdata = dev_get_platdata(&pdev->dev);
> void __iomem *base;
> int irq, ret;
> dma_addr_t phy_addr;
> + const struct imx_i2c_hwdata *match;
>
> dev_dbg(&pdev->dev, "<%s>\n", __func__);
>
> @@ -1075,8 +1081,9 @@ static int i2c_imx_probe(struct platform_device *pdev)
> if (!i2c_imx)
> return -ENOMEM;
>
> - if (of_id)
> - i2c_imx->hwdata = of_id->data;
> + match = device_get_match_data(&pdev->dev);
> + if (match)
> + i2c_imx->hwdata = match;
> else
> i2c_imx->hwdata = (struct imx_i2c_hwdata *)
> platform_get_device_id(pdev)->driver_data;
> @@ -1089,6 +1096,7 @@ static int i2c_imx_probe(struct platform_device *pdev)
> i2c_imx->adapter.nr = pdev->id;
> i2c_imx->adapter.dev.of_node = pdev->dev.of_node;
> i2c_imx->base = base;
> + ACPI_COMPANION_SET(&i2c_imx->adapter.dev, ACPI_COMPANION(&pdev->dev));
>
> /* Get I2C clock */
> i2c_imx->clk = devm_clk_get(&pdev->dev, NULL);
> @@ -1247,6 +1255,7 @@ static struct platform_driver i2c_imx_driver = {
> .name = DRIVER_NAME,
> .pm = &i2c_imx_pm_ops,
> .of_match_table = i2c_imx_dt_ids,
> + .acpi_match_table = i2c_imx_acpi_ids,
> },
> .id_table = imx_i2c_devtype,
> };
> --
> 2.17.1
>
--
With Best Regards,
Andy Shevchenko
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH 1/2] soc: imx: gpc: set DMA mask for PD platform devices
From: Lucas Stach @ 2019-09-06 10:34 UTC (permalink / raw)
To: Shawn Guo, Fabio Estevam
Cc: kernel, NXP Linux Team, linux-arm-kernel, patchwork-lst
In-Reply-To: <20190906103401.22294-1-l.stach@pengutronix.de>
The PD platform devices aren't DMA capable (as is correctly reflected
in with a zero mask coherent_dma_mask). As they have a of_node attached
they will go through of_dma_configure, which will warn if it finds an
uninitialized DMA mask. Let the driver core know that this isn't a
missing configuration, but a non DMA capable device by pointing the
dma_mask to the coherent_dma_mask.
Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
---
drivers/soc/imx/gpc.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/soc/imx/gpc.c b/drivers/soc/imx/gpc.c
index 34d167a8b08a..136d328690fb 100644
--- a/drivers/soc/imx/gpc.c
+++ b/drivers/soc/imx/gpc.c
@@ -498,6 +498,7 @@ static int imx_gpc_probe(struct platform_device *pdev)
pd_pdev->dev.parent = &pdev->dev;
pd_pdev->dev.of_node = np;
+ pd_pdev->dev.dma_mask = &pd_pdev->dev.coherent_dma_mask;
ret = platform_device_add(pd_pdev);
if (ret) {
--
2.20.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 2/2] soc: imx: gpcv2: set DMA mask for PD platform devices
From: Lucas Stach @ 2019-09-06 10:34 UTC (permalink / raw)
To: Shawn Guo, Fabio Estevam
Cc: kernel, NXP Linux Team, linux-arm-kernel, patchwork-lst
In-Reply-To: <20190906103401.22294-1-l.stach@pengutronix.de>
The PD platform devices aren't DMA capable (as is correctly reflected
in with a zero mask coherent_dma_mask). As they have a of_node attached
they will go through of_dma_configure, which will warn if it finds an
uninitialized DMA mask. Let the driver core know that this isn't a
missing configuration, but a non DMA capable device by pointing the
dma_mask to the coherent_dma_mask.
Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
---
drivers/soc/imx/gpcv2.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c
index 31b8d002d855..7268f69a8d03 100644
--- a/drivers/soc/imx/gpcv2.c
+++ b/drivers/soc/imx/gpcv2.c
@@ -626,6 +626,7 @@ static int imx_gpcv2_probe(struct platform_device *pdev)
pd_pdev->dev.parent = dev;
pd_pdev->dev.of_node = np;
+ pd_pdev->dev.dma_mask = &pd_pdev->dev.coherent_dma_mask;
ret = platform_device_add(pd_pdev);
if (ret) {
--
2.20.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 0/2] i.MX GPC DMA warning fixes
From: Lucas Stach @ 2019-09-06 10:33 UTC (permalink / raw)
To: Shawn Guo, Fabio Estevam
Cc: kernel, NXP Linux Team, linux-arm-kernel, patchwork-lst
Hi all,
those two patches get rid of an annoying boot warning on all i.MX6+
devices, as the generic OF DMA code tries to forcefully configure the
DMA capabilities for the virtual GPX power domain devices, which will
never do any DMA.
This solution isn't the most elegant, as we are making up a 0 DMA mask
to silence the warning instead of skipping the DMA configuration
completely. A previous submission of this change for just the GPC v1 [1]
was shot down for this reason. But then we haven't made any progress in
fixing this in a better way, as other systems depend on the forceful
OF DMA configuration to work correctly. So we are stuck between a rock
and a hard place here.
IMHO we should accept the slight uglyness of this solution in order to
get rid of the warning now, as it is confusing users into thinking their
kernel configuration or system setup is faulty, while everything is
perfectly in order.
Regards,
Lucas
[1] https://patchwork.kernel.org/patch/10621589/
Lucas Stach (2):
soc: imx: gpc: set DMA mask for PD platform devices
soc: imx: gpcv2: set DMA mask for PD platform devices
drivers/soc/imx/gpc.c | 1 +
drivers/soc/imx/gpcv2.c | 1 +
2 files changed, 2 insertions(+)
--
2.20.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCHv4 01/10] dt-bindings: omap: add new binding for PRM instances
From: Tero Kristo @ 2019-09-06 10:35 UTC (permalink / raw)
To: ssantosh, linux-omap, tony, s-anna, p.zabel, robh+dt
Cc: devicetree, linux-arm-kernel
In-Reply-To: <20190830121816.30034-2-t-kristo@ti.com>
Add new binding for OMAP PRM (Power and Reset Manager) instances. Each
of these will act as a power domain controller and potentially as a reset
provider.
Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
v4:
- renamed nodes as power-controller
- added documentation about hierarchy
.../devicetree/bindings/arm/omap/prm-inst.txt | 31 +++++++++++++++++++
1 file changed, 31 insertions(+)
create mode 100644 Documentation/devicetree/bindings/arm/omap/prm-inst.txt
diff --git a/Documentation/devicetree/bindings/arm/omap/prm-inst.txt b/Documentation/devicetree/bindings/arm/omap/prm-inst.txt
new file mode 100644
index 000000000000..7c7527c37734
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/omap/prm-inst.txt
@@ -0,0 +1,35 @@
+OMAP PRM instance bindings
+
+Power and Reset Manager is an IP block on OMAP family of devices which
+handle the power domains and their current state, and provide reset
+handling for the domains and/or separate IP blocks under the power domain
+hierarchy. A PRM instance node must be a child of a PRM node [1].
+
+[1] Documentation/devicetree/bindings/arm/omap/prcm.txt
+
+Required properties:
+- compatible: Must be one of:
+ "ti,am3-prm-inst"
+ "ti,am4-prm-inst"
+ "ti,omap4-prm-inst"
+ "ti,omap5-prm-inst"
+ "ti,dra7-prm-inst"
+- reg: Contains PRM instance register address range
+ (base address and length)
+
+Optional properties:
+- #reset-cells: Should be 1 if the PRM instance in question supports resets.
+- clocks: Associated clocks for the reset signals if any. Certain reset
+ signals can't be toggled properly without functional clock
+ being active for them.
+
+Example:
+
+&prm {
+ prm_dsp2: power-controller@1b00 {
+ compatible = "ti,dra7-prm-inst";
+ reg = <0x1b00 0x40>;
+ #reset-cells = <1>;
+ clocks = <&dsp2_clkctrl DRA7_DSP2_MMU0_DSP2_CLKCTRL 0>;
+ };
+};
--
2.17.1
--
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* Re: [PATCH] arm64: dts: imx8mq: Add CAAM node
From: Horia Geanta @ 2019-09-06 10:36 UTC (permalink / raw)
To: Andrey Smirnov, Herbert Xu, Shawn Guo
Cc: Cory Tusar, devicetree@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, Iuliana Prodan,
Sascha Hauer, linux-kernel@vger.kernel.org,
linux-crypto@vger.kernel.org, Pengutronix Kernel Team,
dl-linux-imx, Chris Healy, Lucas Stach
In-Reply-To: <20190830210139.7028-1-andrew.smirnov@gmail.com>
On 8/31/2019 12:01 AM, Andrey Smirnov wrote:
> Add node for CAAM - Cryptographic Acceleration and Assurance Module.
>
> Signed-off-by: Horia Geantă <horia.geanta@nxp.com>
> Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
> Cc: Cory Tusar <cory.tusar@zii.aero>
> Cc: Chris Healy <cphealy@gmail.com>
> Cc: Lucas Stach <l.stach@pengutronix.de>
> Cc: Herbert Xu <herbert@gondor.apana.org.au>
> Cc: Shawn Guo <shawnguo@kernel.org>
> Cc: Iuliana Prodan <iuliana.prodan@nxp.com>
> Cc: linux-crypto@vger.kernel.org
> Cc: linux-kernel@vger.kernel.org
> ---
>
> Shawn:
>
> Just a bit of a context: as per this thread
> https://lore.kernel.org/linux-crypto/20190830131547.GA27480@gondor.apana.org.au/
> I am hoping I can get and Ack from you for this patch, so it can go
> via cryptodev tree.
>
Could we please get an Ack in time for v5.4?
Thanks,
Horia
> Thanks,
> Andrey Smirnov
>
> arch/arm64/boot/dts/freescale/imx8mq.dtsi | 30 +++++++++++++++++++++++
> 1 file changed, 30 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/freescale/imx8mq.dtsi b/arch/arm64/boot/dts/freescale/imx8mq.dtsi
> index d09b808eff87..752d5a61878c 100644
> --- a/arch/arm64/boot/dts/freescale/imx8mq.dtsi
> +++ b/arch/arm64/boot/dts/freescale/imx8mq.dtsi
> @@ -728,6 +728,36 @@
> status = "disabled";
> };
>
> + crypto: crypto@30900000 {
> + compatible = "fsl,sec-v4.0";
> + #address-cells = <1>;
> + #size-cells = <1>;
> + reg = <0x30900000 0x40000>;
> + ranges = <0 0x30900000 0x40000>;
> + interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
> + clocks = <&clk IMX8MQ_CLK_AHB>,
> + <&clk IMX8MQ_CLK_IPG_ROOT>;
> + clock-names = "aclk", "ipg";
> +
> + sec_jr0: jr@1000 {
> + compatible = "fsl,sec-v4.0-job-ring";
> + reg = <0x1000 0x1000>;
> + interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
> + };
> +
> + sec_jr1: jr@2000 {
> + compatible = "fsl,sec-v4.0-job-ring";
> + reg = <0x2000 0x1000>;
> + interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
> + };
> +
> + sec_jr2: jr@3000 {
> + compatible = "fsl,sec-v4.0-job-ring";
> + reg = <0x3000 0x1000>;
> + interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
> + };
> + };
> +
> i2c1: i2c@30a20000 {
> compatible = "fsl,imx8mq-i2c", "fsl,imx21-i2c";
> reg = <0x30a20000 0x10000>;
>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v2] pinctrl: at91-pio4: implement .get_multiple and .set_multiple
From: Alexandre Belloni @ 2019-09-06 10:42 UTC (permalink / raw)
To: David Laight
Cc: Linus Walleij, linux-kernel@vger.kernel.org,
linux-gpio@vger.kernel.org, Ludovic Desroches,
Claudiu.Beznea@microchip.com,
linux-arm-kernel@lists.infradead.org
In-Reply-To: <b010053340ef48dfa244ff48c8decd38@AcuMS.aculab.com>
On 06/09/2019 09:46:02+0000, David Laight wrote:
> From: Alexandre Belloni
> > Sent: 06 September 2019 10:12
> > On 06/09/2019 09:05:36+0000, David Laight wrote:
> > > From: Alexandre Belloni
> > > > Implement .get_multiple and .set_multiple to allow reading or setting
> > > > multiple pins simultaneously. Pins in the same bank will all be switched at
> > > > the same time, improving synchronization and performances.
> > >
> > > Actually it won't 'improve synchronisation', instead it will lead to
> > > random synchronisation errors and potential metastability if one
> > > pin is used as a clock and another as data, or if the code is reading
> > > a free-flowing counter.
> > >
> >
> > It does improve gpio switching synchronisation when they are in the same
> > bank as it will remove the 250ns delay. Of course, if you need this
> > delay between clk and data, then the consumer driver should ensure the
> > delay is present.
>
> With multiple requests the output pin changes will always be in the
> same order and will be separated by (say) 250ns.
> This is a guaranteed synchronisation.
>
> If you change multiple pins with the same 'iowrite()' then the pins
> will change at approximately the same time.
> But the actual order will depend on internal device delays (which
> may depend on the actual silicon and temperature).
> You then have to take account of varying track lengths and the
> target devices input stage properties before knowing which change
> arrives first.
> The delays might be sub-nanosecond, but they matter if you are
> talking about synchronisation.
>
And my point is that this means that your gpio consumer driver is buggy
if it doesn't do multiple requests if it requires a delay between two
pin changes.
> IIRC both SMBus and I2C now quote 0ns setup time.
> Changing both clock and data with the same IOW isn't enough to
> guarantee this.
> (In practise the I2C setup time required by a device is probably
> slightly negative (In order to support 0ns inputs) so a very small
> -ve setup will (mostly) work.)
I'm not sure what is your point exactly as this patch doesn't break any
existing use cases.
--
Alexandre Belloni, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH] gpio/mpc8xxx: change irq handler from chained to normal
From: Hui Song @ 2019-09-06 10:37 UTC (permalink / raw)
To: Shawn Guo, Li Yang, Rob Herring, Mark Rutland, Linus Walleij,
Bartosz Golaszewski
Cc: devicetree, Song Hui, linux-kernel, linux-arm-kernel, linux-gpio
From: Song Hui <hui.song_1@nxp.com>
more one gpio controller use share one interrupt,
make request interrupt to be shared.
Signed-off-by: Laurentiu Tudor <Laurentiu.Tudor@nxp.com>
Signed-off-by: Alex Marginean <alexandru.marginean@nxp.com>
Signed-off-by: Song Hui <hui.song_1@nxp.com>
---
drivers/gpio/gpio-mpc8xxx.c | 21 ++++++++++++++-------
1 file changed, 14 insertions(+), 7 deletions(-)
diff --git a/drivers/gpio/gpio-mpc8xxx.c b/drivers/gpio/gpio-mpc8xxx.c
index 1a680aa..4006250 100644
--- a/drivers/gpio/gpio-mpc8xxx.c
+++ b/drivers/gpio/gpio-mpc8xxx.c
@@ -22,6 +22,7 @@
#include <linux/irq.h>
#include <linux/gpio/driver.h>
#include <linux/bitops.h>
+#include <linux/interrupt.h>
#define MPC8XXX_GPIO_PINS 32
@@ -127,10 +128,9 @@ static int mpc8xxx_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
return -ENXIO;
}
-static void mpc8xxx_gpio_irq_cascade(struct irq_desc *desc)
+static irqreturn_t mpc8xxx_gpio_irq_cascade(int irq, void *data)
{
- struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_desc_get_handler_data(desc);
- struct irq_chip *chip = irq_desc_get_chip(desc);
+ struct mpc8xxx_gpio_chip *mpc8xxx_gc = (struct mpc8xxx_gpio_chip *)data;
struct gpio_chip *gc = &mpc8xxx_gc->gc;
unsigned int mask;
@@ -139,8 +139,8 @@ static void mpc8xxx_gpio_irq_cascade(struct irq_desc *desc)
if (mask)
generic_handle_irq(irq_linear_revmap(mpc8xxx_gc->irq,
32 - ffs(mask)));
- if (chip->irq_eoi)
- chip->irq_eoi(&desc->irq_data);
+
+ return IRQ_HANDLED;
}
static void mpc8xxx_irq_unmask(struct irq_data *d)
@@ -319,6 +319,7 @@ static const struct of_device_id mpc8xxx_gpio_ids[] = {
{ .compatible = "fsl,mpc5125-gpio", .data = &mpc5125_gpio_devtype, },
{ .compatible = "fsl,pq3-gpio", },
{ .compatible = "fsl,ls1028a-gpio", .data = &ls1028a_gpio_devtype, },
+ { .compatible = "fsl,ls1088a-gpio", .data = &ls1028a_gpio_devtype, },
{ .compatible = "fsl,qoriq-gpio", },
{}
};
@@ -408,8 +409,14 @@ static int mpc8xxx_probe(struct platform_device *pdev)
if (devtype->gpio_dir_in_init)
devtype->gpio_dir_in_init(gc);
- irq_set_chained_handler_and_data(mpc8xxx_gc->irqn,
- mpc8xxx_gpio_irq_cascade, mpc8xxx_gc);
+ ret = request_irq(mpc8xxx_gc->irqn, mpc8xxx_gpio_irq_cascade,
+ IRQF_NO_THREAD | IRQF_SHARED, "gpio-cascade", mpc8xxx_gc);
+ if (ret) {
+ pr_err("%s: failed to request_irq(%d), ret = %d\n",
+ np->full_name, mpc8xxx_gc->irqn, ret);
+ goto err;
+ }
+
return 0;
err:
iounmap(mpc8xxx_gc->regs);
--
2.9.5
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* Re: [PATCH 1/3] memory: Exynos5422: minor fixes in DMC
From: Krzysztof Kozlowski @ 2019-09-06 10:51 UTC (permalink / raw)
To: Lukasz Luba
Cc: mark.rutland, devicetree, willy.mh.wolff.ml,
linux-samsung-soc@vger.kernel.org,
Bartłomiej Żołnierkiewicz, linux-pm,
linux-kernel@vger.kernel.org, robh+dt, Chanwoo Choi,
kyungmin.park, kgene, myungjoo.ham, s.nawrocki, linux-arm-kernel,
Marek Szyprowski
In-Reply-To: <20190906101344.3535-2-l.luba@partner.samsung.com>
On Fri, 6 Sep 2019 at 12:14, Lukasz Luba <l.luba@partner.samsung.com> wrote:
>
> Small fixes captured by static analyzes.
Explain please what are the errors being fixed. Additionally error
message from tool might be useful.
Also:
Reported-by: Krzysztof Kozlowski <krzk@kernel.org>
Best regards,
Krzysztof
> Signed-off-by: Lukasz Luba <l.luba@partner.samsung.com>
> ---
> drivers/memory/samsung/exynos5422-dmc.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/memory/samsung/exynos5422-dmc.c b/drivers/memory/samsung/exynos5422-dmc.c
> index 8c2ec29a7d57..a809fa997c03 100644
> --- a/drivers/memory/samsung/exynos5422-dmc.c
> +++ b/drivers/memory/samsung/exynos5422-dmc.c
> @@ -269,7 +269,7 @@ static int exynos5_init_freq_table(struct exynos5_dmc *dmc,
> return 0;
>
> err_free_tables:
> - kfree(dmc->opp);
> + devm_kfree(dmc->dev, dmc->opp);
> err_opp:
> dev_pm_opp_of_remove_table(dmc->dev);
>
> @@ -732,7 +732,7 @@ static struct devfreq_dev_profile exynos5_dmc_df_profile = {
> * statistics engine which supports only registered values. Thus, some alignment
> * must be made.
> */
> -unsigned long
> +static unsigned long
> exynos5_dmc_align_init_freq(struct exynos5_dmc *dmc,
> unsigned long bootloader_init_freq)
> {
> --
> 2.17.1
>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH 3/3] dt-bindings: ddr: Add bindings for Samsung LPDDR3 memories
From: Krzysztof Kozlowski @ 2019-09-06 10:56 UTC (permalink / raw)
To: Lukasz Luba
Cc: mark.rutland, devicetree, willy.mh.wolff.ml,
linux-samsung-soc@vger.kernel.org,
Bartłomiej Żołnierkiewicz, linux-pm,
linux-kernel@vger.kernel.org, robh+dt, Chanwoo Choi,
kyungmin.park, kgene, myungjoo.ham, s.nawrocki, linux-arm-kernel,
Marek Szyprowski
In-Reply-To: <20190906101344.3535-4-l.luba@partner.samsung.com>
On Fri, 6 Sep 2019 at 12:14, Lukasz Luba <l.luba@partner.samsung.com> wrote:
>
> Add description of bindings for Samsung k3qf2f20db LPDDR3 memory.
> Minor fixes in the old documentation.
>
> Signed-off-by: Lukasz Luba <l.luba@partner.samsung.com>
> ---
> .../devicetree/bindings/ddr/lpddr3.txt | 29 +++++++++++++++++--
> 1 file changed, 27 insertions(+), 2 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/ddr/lpddr3.txt b/Documentation/devicetree/bindings/ddr/lpddr3.txt
> index 3b2485b84b3f..de0905239767 100644
> --- a/Documentation/devicetree/bindings/ddr/lpddr3.txt
> +++ b/Documentation/devicetree/bindings/ddr/lpddr3.txt
> @@ -40,10 +40,34 @@ Child nodes:
> a given speed-bin. Please see Documentation/devicetree/
> bindings/ddr/lpddr3-timings.txt for more information on "lpddr3-timings"
>
> +Samsung K3QF2F20DB LPDDR3 memory
> +------------------------------------------------------------
> +
> +This binding uses the LPDDR3 binding (described above)
> +
> +Required properties:
> +- compatible: Should be:
> + "samsung,K3QF2F20DB"
> + followed by "jedec,lpddr3"
> +- density : <u32> representing density in Mb (Mega bits)
> +- io-width : <u32> representing bus width. Possible value 32
> +- #address-cells: Must be set to 1
> +- #size-cells: Must be set to 0
If you decided to repeat all properties again, then it deserves its
own bindings file. However I though about simpler solution - just
document compatible. Exactly the same as AT24 or AT25 EEPROM bindings.
There is not much benefit from copying all these properties.
Best regards,
Krzysztof
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH] dt-bindings: arm: renesas: Convert 'renesas, prr' to json-schema
From: Simon Horman @ 2019-09-06 11:14 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: Mark Rutland, devicetree, Magnus Damm, linux-renesas-soc,
Rob Herring, Simon Horman, linux-arm-kernel
Convert Renesas Product Register bindings documentation to json-schema.
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
---
Based on v5.3-rc1
Tested using:
make dtbs_check DT_SCHEMA_FILES=Documentation/devicetree/bindings/arm/renesas,prr.yaml
---
.../devicetree/bindings/arm/renesas,prr.txt | 20 ------------
.../devicetree/bindings/arm/renesas,prr.yaml | 36 ++++++++++++++++++++++
2 files changed, 36 insertions(+), 20 deletions(-)
delete mode 100644 Documentation/devicetree/bindings/arm/renesas,prr.txt
create mode 100644 Documentation/devicetree/bindings/arm/renesas,prr.yaml
diff --git a/Documentation/devicetree/bindings/arm/renesas,prr.txt b/Documentation/devicetree/bindings/arm/renesas,prr.txt
deleted file mode 100644
index 08e482e953ca..000000000000
--- a/Documentation/devicetree/bindings/arm/renesas,prr.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-Renesas Product Register
-
-Most Renesas ARM SoCs have a Product Register or Boundary Scan ID Register that
-allows to retrieve SoC product and revision information. If present, a device
-node for this register should be added.
-
-Required properties:
- - compatible: Must be one of:
- "renesas,prr"
- "renesas,bsid"
- - reg: Base address and length of the register block.
-
-
-Examples
---------
-
- prr: chipid@ff000044 {
- compatible = "renesas,prr";
- reg = <0 0xff000044 0 4>;
- };
diff --git a/Documentation/devicetree/bindings/arm/renesas,prr.yaml b/Documentation/devicetree/bindings/arm/renesas,prr.yaml
new file mode 100644
index 000000000000..9df003041456
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/renesas,prr.yaml
@@ -0,0 +1,36 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/arm/renesas,prr.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Renesas Product Register
+
+maintainers:
+ - Geert Uytterhoeven <geert+renesas@glider.be>
+ - Magnus Damm <magnus.damm@gmail.com>
+
+description: |
+ Most Renesas ARM SoCs have a Product Register or Boundary Scan ID
+ Register that allows to retrieve SoC product and revision information.
+ If present, a device node for this register should be added.
+
+properties:
+ compatible:
+ oneOf:
+ - const: "renesas,prr"
+ - const: "renesas,bsid"
+ reg:
+ items:
+ - description: Base address and length of the register block.
+
+required:
+ - compatible
+ - reg
+
+examples:
+ - |
+ prr: chipid@ff000044 {
+ compatible = "renesas,prr";
+ reg = <0 0xff000044 0 4>;
+ };
--
2.11.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* Re: [PATCH] dt-bindings: arm: renesas: Convert 'renesas, prr' to json-schema
From: Rob Herring @ 2019-09-06 11:21 UTC (permalink / raw)
To: Simon Horman
Cc: Mark Rutland, devicetree, Geert Uytterhoeven, Magnus Damm,
open list:MEDIA DRIVERS FOR RENESAS - FCP,
moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
In-Reply-To: <20190906111435.5706-1-horms+renesas@verge.net.au>
On Fri, Sep 6, 2019 at 12:14 PM Simon Horman <horms+renesas@verge.net.au> wrote:
>
> Convert Renesas Product Register bindings documentation to json-schema.
>
> Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
> ---
> Based on v5.3-rc1
> Tested using:
> make dtbs_check DT_SCHEMA_FILES=Documentation/devicetree/bindings/arm/renesas,prr.yaml
> ---
> .../devicetree/bindings/arm/renesas,prr.txt | 20 ------------
> .../devicetree/bindings/arm/renesas,prr.yaml | 36 ++++++++++++++++++++++
> 2 files changed, 36 insertions(+), 20 deletions(-)
> delete mode 100644 Documentation/devicetree/bindings/arm/renesas,prr.txt
> create mode 100644 Documentation/devicetree/bindings/arm/renesas,prr.yaml
>
> diff --git a/Documentation/devicetree/bindings/arm/renesas,prr.txt b/Documentation/devicetree/bindings/arm/renesas,prr.txt
> deleted file mode 100644
> index 08e482e953ca..000000000000
> --- a/Documentation/devicetree/bindings/arm/renesas,prr.txt
> +++ /dev/null
> @@ -1,20 +0,0 @@
> -Renesas Product Register
> -
> -Most Renesas ARM SoCs have a Product Register or Boundary Scan ID Register that
> -allows to retrieve SoC product and revision information. If present, a device
> -node for this register should be added.
> -
> -Required properties:
> - - compatible: Must be one of:
> - "renesas,prr"
> - "renesas,bsid"
> - - reg: Base address and length of the register block.
> -
> -
> -Examples
> ---------
> -
> - prr: chipid@ff000044 {
> - compatible = "renesas,prr";
> - reg = <0 0xff000044 0 4>;
> - };
> diff --git a/Documentation/devicetree/bindings/arm/renesas,prr.yaml b/Documentation/devicetree/bindings/arm/renesas,prr.yaml
> new file mode 100644
> index 000000000000..9df003041456
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/renesas,prr.yaml
> @@ -0,0 +1,36 @@
> +# SPDX-License-Identifier: GPL-2.0
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/arm/renesas,prr.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Renesas Product Register
> +
> +maintainers:
> + - Geert Uytterhoeven <geert+renesas@glider.be>
> + - Magnus Damm <magnus.damm@gmail.com>
> +
> +description: |
> + Most Renesas ARM SoCs have a Product Register or Boundary Scan ID
> + Register that allows to retrieve SoC product and revision information.
> + If present, a device node for this register should be added.
> +
> +properties:
> + compatible:
> + oneOf:
> + - const: "renesas,prr"
> + - const: "renesas,bsid"
enum is better than oneOf+const and drop the quotes. oneOf/allOf/anyOf
result in terrible error messages.
> + reg:
> + items:
> + - description: Base address and length of the register block.
That's what 'reg' *always* is... Just 'maxItems: 1' is sufficient when
there is only 1 entry.
> +
> +required:
> + - compatible
> + - reg
> +
> +examples:
> + - |
> + prr: chipid@ff000044 {
> + compatible = "renesas,prr";
> + reg = <0 0xff000044 0 4>;
> + };
> --
> 2.11.0
>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH 3/3] dt-bindings: ddr: Add bindings for Samsung LPDDR3 memories
From: Lukasz Luba @ 2019-09-06 11:39 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: mark.rutland, devicetree, willy.mh.wolff.ml,
linux-samsung-soc@vger.kernel.org,
Bartłomiej Żołnierkiewicz, linux-pm,
linux-kernel@vger.kernel.org, robh+dt, Chanwoo Choi,
kyungmin.park, kgene, myungjoo.ham, s.nawrocki, linux-arm-kernel,
Marek Szyprowski
In-Reply-To: <CAJKOXPfoYxTVvt_bMQOs1=BkHzUuW_WvL9zn0jTGS6LLpv=fhQ@mail.gmail.com>
Hi Krzysztof,
On 9/6/19 12:56 PM, Krzysztof Kozlowski wrote:
> On Fri, 6 Sep 2019 at 12:14, Lukasz Luba <l.luba@partner.samsung.com> wrote:
>>
>> Add description of bindings for Samsung k3qf2f20db LPDDR3 memory.
>> Minor fixes in the old documentation.
>>
>> Signed-off-by: Lukasz Luba <l.luba@partner.samsung.com>
>> ---
>> .../devicetree/bindings/ddr/lpddr3.txt | 29 +++++++++++++++++--
>> 1 file changed, 27 insertions(+), 2 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/ddr/lpddr3.txt b/Documentation/devicetree/bindings/ddr/lpddr3.txt
>> index 3b2485b84b3f..de0905239767 100644
>> --- a/Documentation/devicetree/bindings/ddr/lpddr3.txt
>> +++ b/Documentation/devicetree/bindings/ddr/lpddr3.txt
>> @@ -40,10 +40,34 @@ Child nodes:
>> a given speed-bin. Please see Documentation/devicetree/
>> bindings/ddr/lpddr3-timings.txt for more information on "lpddr3-timings"
>>
>> +Samsung K3QF2F20DB LPDDR3 memory
>> +------------------------------------------------------------
>> +
>> +This binding uses the LPDDR3 binding (described above)
>> +
>> +Required properties:
>> +- compatible: Should be:
>> + "samsung,K3QF2F20DB"
>> + followed by "jedec,lpddr3"
>> +- density : <u32> representing density in Mb (Mega bits)
>> +- io-width : <u32> representing bus width. Possible value 32
>> +- #address-cells: Must be set to 1
>> +- #size-cells: Must be set to 0
>
> If you decided to repeat all properties again, then it deserves its
> own bindings file. However I though about simpler solution - just
> document compatible. Exactly the same as AT24 or AT25 EEPROM bindings.
> There is not much benefit from copying all these properties.
OK, I see. I will add only 'compatible' and skip the rest then.
So the lpddr3.txt file will get this addition:
+Samsung K3QF2F20DB LPDDR3 memory
+------------------------------------------------------------
+
+This binding uses the LPDDR3 binding (described above)
+
+Required properties:
+- compatible: Should be:
+ "samsung,K3QF2F20DB"
+ followed by "jedec,lpddr3"
+
+Optional properties:
+
+The optional properties are the same as in the LPDDR3 generic bindings and
+values should be taken from the data-sheet. Detailed bindings are described
+above.
+
+Child nodes:
+
+Detailed bindings are described in LPDDR3 generic bindings described above.
+
Is it OK?
Regards,
Lukasz
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH 1/3] memory: Exynos5422: minor fixes in DMC
From: Lukasz Luba @ 2019-09-06 11:43 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: mark.rutland, devicetree, willy.mh.wolff.ml,
linux-samsung-soc@vger.kernel.org,
Bartłomiej Żołnierkiewicz, linux-pm,
linux-kernel@vger.kernel.org, robh+dt, Chanwoo Choi,
kyungmin.park, kgene, myungjoo.ham, s.nawrocki, linux-arm-kernel,
Marek Szyprowski
In-Reply-To: <CAJKOXPdLhrvqR==k4a9w9cmdnwGRYaTXC1ya+vOeVaGpML0zcQ@mail.gmail.com>
On 9/6/19 12:51 PM, Krzysztof Kozlowski wrote:
> On Fri, 6 Sep 2019 at 12:14, Lukasz Luba <l.luba@partner.samsung.com> wrote:
>>
>> Small fixes captured by static analyzes.
>
> Explain please what are the errors being fixed. Additionally error
> message from tool might be useful.
>
> Also:
> Reported-by: Krzysztof Kozlowski <krzk@kernel.org>
OK, I will add it in the next version.
My apologies for missing your name there.
Regards,
Lukasz
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH] dt-bindings: arm: renesas: Convert 'renesas,prr' to json-schema
From: Simon Horman @ 2019-09-06 11:48 UTC (permalink / raw)
To: Rob Herring
Cc: Mark Rutland, devicetree, Geert Uytterhoeven, Magnus Damm,
open list:MEDIA DRIVERS FOR RENESAS - FCP,
moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
In-Reply-To: <CAL_JsqLvU4=kaQ-nSwMuh4VXX67U5URZAPvVJohfKzQsQdFTrA@mail.gmail.com>
On Fri, Sep 06, 2019 at 12:21:58PM +0100, Rob Herring wrote:
> On Fri, Sep 6, 2019 at 12:14 PM Simon Horman <horms+renesas@verge.net.au> wrote:
> >
> > Convert Renesas Product Register bindings documentation to json-schema.
> >
> > Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
> > ---
> > Based on v5.3-rc1
> > Tested using:
> > make dtbs_check DT_SCHEMA_FILES=Documentation/devicetree/bindings/arm/renesas,prr.yaml
> > ---
> > .../devicetree/bindings/arm/renesas,prr.txt | 20 ------------
> > .../devicetree/bindings/arm/renesas,prr.yaml | 36 ++++++++++++++++++++++
> > 2 files changed, 36 insertions(+), 20 deletions(-)
> > delete mode 100644 Documentation/devicetree/bindings/arm/renesas,prr.txt
> > create mode 100644 Documentation/devicetree/bindings/arm/renesas,prr.yaml
> >
> > diff --git a/Documentation/devicetree/bindings/arm/renesas,prr.txt b/Documentation/devicetree/bindings/arm/renesas,prr.txt
> > deleted file mode 100644
> > index 08e482e953ca..000000000000
> > --- a/Documentation/devicetree/bindings/arm/renesas,prr.txt
> > +++ /dev/null
> > @@ -1,20 +0,0 @@
> > -Renesas Product Register
> > -
> > -Most Renesas ARM SoCs have a Product Register or Boundary Scan ID Register that
> > -allows to retrieve SoC product and revision information. If present, a device
> > -node for this register should be added.
> > -
> > -Required properties:
> > - - compatible: Must be one of:
> > - "renesas,prr"
> > - "renesas,bsid"
> > - - reg: Base address and length of the register block.
> > -
> > -
> > -Examples
> > ---------
> > -
> > - prr: chipid@ff000044 {
> > - compatible = "renesas,prr";
> > - reg = <0 0xff000044 0 4>;
> > - };
> > diff --git a/Documentation/devicetree/bindings/arm/renesas,prr.yaml b/Documentation/devicetree/bindings/arm/renesas,prr.yaml
> > new file mode 100644
> > index 000000000000..9df003041456
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/arm/renesas,prr.yaml
> > @@ -0,0 +1,36 @@
> > +# SPDX-License-Identifier: GPL-2.0
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/arm/renesas,prr.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: Renesas Product Register
> > +
> > +maintainers:
> > + - Geert Uytterhoeven <geert+renesas@glider.be>
> > + - Magnus Damm <magnus.damm@gmail.com>
> > +
> > +description: |
> > + Most Renesas ARM SoCs have a Product Register or Boundary Scan ID
> > + Register that allows to retrieve SoC product and revision information.
> > + If present, a device node for this register should be added.
> > +
> > +properties:
> > + compatible:
> > + oneOf:
> > + - const: "renesas,prr"
> > + - const: "renesas,bsid"
>
> enum is better than oneOf+const and drop the quotes. oneOf/allOf/anyOf
> result in terrible error messages.
Thanks Rob,
Like this?
compatible:
enum:
- renesas,prr
- renesas,bsid
> > + reg:
> > + items:
> > + - description: Base address and length of the register block.
>
> That's what 'reg' *always* is... Just 'maxItems: 1' is sufficient when
> there is" only 1 entry.
And this?
reg:
maxItems: 1
> > +
> > +required:
> > + - compatible
> > + - reg
> > +
> > +examples:
> > + - |
> > + prr: chipid@ff000044 {
> > + compatible = "renesas,prr";
> > + reg = <0 0xff000044 0 4>;
> > + };
> > --
> > 2.11.0
> >
>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH 3/3] dt-bindings: ddr: Add bindings for Samsung LPDDR3 memories
From: Krzysztof Kozlowski @ 2019-09-06 11:50 UTC (permalink / raw)
To: Lukasz Luba
Cc: mark.rutland, devicetree, willy.mh.wolff.ml,
linux-samsung-soc@vger.kernel.org,
Bartłomiej Żołnierkiewicz, linux-pm,
linux-kernel@vger.kernel.org, robh+dt, Chanwoo Choi,
kyungmin.park, kgene, myungjoo.ham, s.nawrocki, linux-arm-kernel,
Marek Szyprowski
In-Reply-To: <52963d0d-cf48-7085-5581-a94c6e15e0bd@partner.samsung.com>
On Fri, 6 Sep 2019 at 13:39, Lukasz Luba <l.luba@partner.samsung.com> wrote:
>
> Hi Krzysztof,
>
> On 9/6/19 12:56 PM, Krzysztof Kozlowski wrote:
> > On Fri, 6 Sep 2019 at 12:14, Lukasz Luba <l.luba@partner.samsung.com> wrote:
> >>
> >> Add description of bindings for Samsung k3qf2f20db LPDDR3 memory.
> >> Minor fixes in the old documentation.
> >>
> >> Signed-off-by: Lukasz Luba <l.luba@partner.samsung.com>
> >> ---
> >> .../devicetree/bindings/ddr/lpddr3.txt | 29 +++++++++++++++++--
> >> 1 file changed, 27 insertions(+), 2 deletions(-)
> >>
> >> diff --git a/Documentation/devicetree/bindings/ddr/lpddr3.txt b/Documentation/devicetree/bindings/ddr/lpddr3.txt
> >> index 3b2485b84b3f..de0905239767 100644
> >> --- a/Documentation/devicetree/bindings/ddr/lpddr3.txt
> >> +++ b/Documentation/devicetree/bindings/ddr/lpddr3.txt
> >> @@ -40,10 +40,34 @@ Child nodes:
> >> a given speed-bin. Please see Documentation/devicetree/
> >> bindings/ddr/lpddr3-timings.txt for more information on "lpddr3-timings"
> >>
> >> +Samsung K3QF2F20DB LPDDR3 memory
> >> +------------------------------------------------------------
> >> +
> >> +This binding uses the LPDDR3 binding (described above)
> >> +
> >> +Required properties:
> >> +- compatible: Should be:
> >> + "samsung,K3QF2F20DB"
> >> + followed by "jedec,lpddr3"
> >> +- density : <u32> representing density in Mb (Mega bits)
> >> +- io-width : <u32> representing bus width. Possible value 32
> >> +- #address-cells: Must be set to 1
> >> +- #size-cells: Must be set to 0
> >
> > If you decided to repeat all properties again, then it deserves its
> > own bindings file. However I though about simpler solution - just
> > document compatible. Exactly the same as AT24 or AT25 EEPROM bindings.
> > There is not much benefit from copying all these properties.
> OK, I see. I will add only 'compatible' and skip the rest then.
> So the lpddr3.txt file will get this addition:
>
> +Samsung K3QF2F20DB LPDDR3 memory
> +------------------------------------------------------------
> +
> +This binding uses the LPDDR3 binding (described above)
> +
> +Required properties:
> +- compatible: Should be:
> + "samsung,K3QF2F20DB"
> + followed by "jedec,lpddr3"
> +
> +Optional properties:
> +
> +The optional properties are the same as in the LPDDR3 generic bindings and
> +values should be taken from the data-sheet. Detailed bindings are described
> +above.
> +
> +Child nodes:
> +
> +Detailed bindings are described in LPDDR3 generic bindings described above.
> +
>
> Is it OK?
To me it is still a lot of text just for one compatible and I can
image more of such entries for other memories... However I do not mind
and anyway, YAML will simplify it. If you're in doubt, wait for Rob's
reply as this is his part.
Best regards,
Krzysztof
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox