* [PATCH v3 1/3] media: V3s: Add support for Allwinner CSI.
From: Yong Deng @ 2017-11-13 7:30 UTC (permalink / raw)
To: maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8
Cc: Yong Deng, Mauro Carvalho Chehab, Rob Herring, Mark Rutland,
Chen-Yu Tsai, David S. Miller, Greg Kroah-Hartman, Hans Verkuil,
Randy Dunlap, Benoit Parrot, Stanimir Varbanov, Arnd Bergmann,
Hugues Fruchet, Philipp Zabel, Benjamin Gaignard,
Ramesh Shanmugasundaram, Yannick Fertre, Sakari Ailus, Rick Chang,
linux-media-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
Allwinner V3s SoC have two CSI module. CSI0 is used for MIPI interface
and CSI1 is used for parallel interface. This is not documented in
datasheet but by testing and guess.
This patch implement a v4l2 framework driver for it.
Currently, the driver only support the parallel interface. MIPI-CSI2,
ISP's support are not included in this patch.
Signed-off-by: Yong Deng <yong.deng-+3dxTMOEIRNWk0Htik3J/w@public.gmane.org>
---
drivers/media/platform/Kconfig | 1 +
drivers/media/platform/Makefile | 2 +
drivers/media/platform/sunxi/sun6i-csi/Kconfig | 9 +
drivers/media/platform/sunxi/sun6i-csi/Makefile | 3 +
drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c | 918 +++++++++++++++++++++
drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.h | 146 ++++
.../media/platform/sunxi/sun6i-csi/sun6i_csi_reg.h | 203 +++++
.../media/platform/sunxi/sun6i-csi/sun6i_video.c | 722 ++++++++++++++++
.../media/platform/sunxi/sun6i-csi/sun6i_video.h | 61 ++
9 files changed, 2065 insertions(+)
create mode 100644 drivers/media/platform/sunxi/sun6i-csi/Kconfig
create mode 100644 drivers/media/platform/sunxi/sun6i-csi/Makefile
create mode 100644 drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c
create mode 100644 drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.h
create mode 100644 drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_reg.h
create mode 100644 drivers/media/platform/sunxi/sun6i-csi/sun6i_video.c
create mode 100644 drivers/media/platform/sunxi/sun6i-csi/sun6i_video.h
diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
index fd0c998..41017e3 100644
--- a/drivers/media/platform/Kconfig
+++ b/drivers/media/platform/Kconfig
@@ -150,6 +150,7 @@ source "drivers/media/platform/am437x/Kconfig"
source "drivers/media/platform/xilinx/Kconfig"
source "drivers/media/platform/rcar-vin/Kconfig"
source "drivers/media/platform/atmel/Kconfig"
+source "drivers/media/platform/sunxi/sun6i-csi/Kconfig"
config VIDEO_TI_CAL
tristate "TI CAL (Camera Adaptation Layer) driver"
diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile
index 012eb47..1cc806a 100644
--- a/drivers/media/platform/Makefile
+++ b/drivers/media/platform/Makefile
@@ -96,3 +96,5 @@ obj-$(CONFIG_VIDEO_QCOM_CAMSS) += qcom/camss-8x16/
obj-$(CONFIG_VIDEO_QCOM_VENUS) += qcom/venus/
obj-y += meson/
+
+obj-$(CONFIG_VIDEO_SUN6I_CSI) += sunxi/sun6i-csi/
diff --git a/drivers/media/platform/sunxi/sun6i-csi/Kconfig b/drivers/media/platform/sunxi/sun6i-csi/Kconfig
new file mode 100644
index 0000000..314188a
--- /dev/null
+++ b/drivers/media/platform/sunxi/sun6i-csi/Kconfig
@@ -0,0 +1,9 @@
+config VIDEO_SUN6I_CSI
+ tristate "Allwinner V3s Camera Sensor Interface driver"
+ depends on VIDEO_V4L2 && COMMON_CLK && VIDEO_V4L2_SUBDEV_API && HAS_DMA
+ depends on ARCH_SUNXI || COMPILE_TEST
+ select VIDEOBUF2_DMA_CONTIG
+ select REGMAP_MMIO
+ select V4L2_FWNODE
+ ---help---
+ Support for the Allwinner Camera Sensor Interface Controller on V3s.
diff --git a/drivers/media/platform/sunxi/sun6i-csi/Makefile b/drivers/media/platform/sunxi/sun6i-csi/Makefile
new file mode 100644
index 0000000..213cb6b
--- /dev/null
+++ b/drivers/media/platform/sunxi/sun6i-csi/Makefile
@@ -0,0 +1,3 @@
+sun6i-csi-y += sun6i_video.o sun6i_csi.o
+
+obj-$(CONFIG_VIDEO_SUN6I_CSI) += sun6i-csi.o
diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c
new file mode 100644
index 0000000..3f4de09
--- /dev/null
+++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c
@@ -0,0 +1,918 @@
+/*
+ * Copyright (c) 2017 Magewell Electronics Co., Ltd. (Nanjing).
+ * All rights reserved.
+ * Author: Yong Deng <yong.deng-+3dxTMOEIRNWk0Htik3J/w@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/ioctl.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+#include <linux/sched.h>
+#include <linux/sizes.h>
+#include <linux/slab.h>
+
+#include "sun6i_csi.h"
+#include "sun6i_csi_reg.h"
+
+#define MODULE_NAME "sun6i-csi"
+
+struct sun6i_csi_dev {
+ struct sun6i_csi csi;
+ struct device *dev;
+
+ struct regmap *regmap;
+ struct clk *clk_mod;
+ struct clk *clk_ram;
+ struct reset_control *rstc_bus;
+
+ int planar_offset[3];
+};
+
+static const u32 supported_pixformats[] = {
+ V4L2_PIX_FMT_SBGGR8,
+ V4L2_PIX_FMT_SGBRG8,
+ V4L2_PIX_FMT_SGRBG8,
+ V4L2_PIX_FMT_SRGGB8,
+ V4L2_PIX_FMT_SBGGR10,
+ V4L2_PIX_FMT_SGBRG10,
+ V4L2_PIX_FMT_SGRBG10,
+ V4L2_PIX_FMT_SRGGB10,
+ V4L2_PIX_FMT_SBGGR12,
+ V4L2_PIX_FMT_SGBRG12,
+ V4L2_PIX_FMT_SGRBG12,
+ V4L2_PIX_FMT_SRGGB12,
+ V4L2_PIX_FMT_YUYV,
+ V4L2_PIX_FMT_YVYU,
+ V4L2_PIX_FMT_UYVY,
+ V4L2_PIX_FMT_VYUY,
+ V4L2_PIX_FMT_HM12,
+ V4L2_PIX_FMT_NV12,
+ V4L2_PIX_FMT_NV21,
+ V4L2_PIX_FMT_YUV420,
+ V4L2_PIX_FMT_YVU420,
+ V4L2_PIX_FMT_NV16,
+ V4L2_PIX_FMT_NV61,
+ V4L2_PIX_FMT_YUV422P,
+};
+
+static inline struct sun6i_csi_dev *sun6i_csi_to_dev(struct sun6i_csi *csi)
+{
+ return container_of(csi, struct sun6i_csi_dev, csi);
+}
+
+/* TODO add 10&12 bit YUV, RGB support */
+static bool __is_format_support(struct sun6i_csi_dev *sdev,
+ u32 fourcc, u32 mbus_code)
+{
+ /*
+ * Some video receiver have capability both 8bit and 16bit.
+ * Identify the media bus format from device tree.
+ */
+ if ((sdev->csi.v4l2_ep.bus_type == V4L2_MBUS_PARALLEL
+ || sdev->csi.v4l2_ep.bus_type == V4L2_MBUS_BT656)
+ && sdev->csi.v4l2_ep.bus.parallel.bus_width == 16) {
+ switch (fourcc) {
+ case V4L2_PIX_FMT_HM12:
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_NV16:
+ case V4L2_PIX_FMT_NV61:
+ case V4L2_PIX_FMT_YUV420:
+ case V4L2_PIX_FMT_YVU420:
+ case V4L2_PIX_FMT_YUV422P:
+ switch (mbus_code) {
+ case MEDIA_BUS_FMT_UYVY8_1X16:
+ case MEDIA_BUS_FMT_VYUY8_1X16:
+ case MEDIA_BUS_FMT_YUYV8_1X16:
+ case MEDIA_BUS_FMT_YVYU8_1X16:
+ return true;
+ }
+ break;
+ }
+ return false;
+ }
+
+ switch (fourcc) {
+ case V4L2_PIX_FMT_SBGGR8:
+ if (mbus_code == MEDIA_BUS_FMT_SBGGR8_1X8)
+ return true;
+ break;
+ case V4L2_PIX_FMT_SGBRG8:
+ if (mbus_code == MEDIA_BUS_FMT_SGBRG8_1X8)
+ return true;
+ break;
+ case V4L2_PIX_FMT_SGRBG8:
+ if (mbus_code == MEDIA_BUS_FMT_SGRBG8_1X8)
+ return true;
+ break;
+ case V4L2_PIX_FMT_SRGGB8:
+ if (mbus_code == MEDIA_BUS_FMT_SRGGB8_1X8)
+ return true;
+ break;
+ case V4L2_PIX_FMT_SBGGR10:
+ if (mbus_code == MEDIA_BUS_FMT_SBGGR10_1X10)
+ return true;
+ break;
+ case V4L2_PIX_FMT_SGBRG10:
+ if (mbus_code == MEDIA_BUS_FMT_SGBRG10_1X10)
+ return true;
+ break;
+ case V4L2_PIX_FMT_SGRBG10:
+ if (mbus_code == MEDIA_BUS_FMT_SGRBG10_1X10)
+ return true;
+ break;
+ case V4L2_PIX_FMT_SRGGB10:
+ if (mbus_code == MEDIA_BUS_FMT_SRGGB10_1X10)
+ return true;
+ break;
+ case V4L2_PIX_FMT_SBGGR12:
+ if (mbus_code == MEDIA_BUS_FMT_SBGGR12_1X12)
+ return true;
+ break;
+ case V4L2_PIX_FMT_SGBRG12:
+ if (mbus_code == MEDIA_BUS_FMT_SGBRG12_1X12)
+ return true;
+ break;
+ case V4L2_PIX_FMT_SGRBG12:
+ if (mbus_code == MEDIA_BUS_FMT_SGRBG12_1X12)
+ return true;
+ break;
+ case V4L2_PIX_FMT_SRGGB12:
+ if (mbus_code == MEDIA_BUS_FMT_SRGGB12_1X12)
+ return true;
+ break;
+
+ case V4L2_PIX_FMT_YUYV:
+ if (mbus_code == MEDIA_BUS_FMT_YUYV8_2X8)
+ return true;
+ break;
+ case V4L2_PIX_FMT_YVYU:
+ if (mbus_code == MEDIA_BUS_FMT_YVYU8_2X8)
+ return true;
+ break;
+ case V4L2_PIX_FMT_UYVY:
+ if (mbus_code == MEDIA_BUS_FMT_UYVY8_2X8)
+ return true;
+ break;
+ case V4L2_PIX_FMT_VYUY:
+ if (mbus_code == MEDIA_BUS_FMT_VYUY8_2X8)
+ return true;
+ break;
+
+ case V4L2_PIX_FMT_HM12:
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_NV16:
+ case V4L2_PIX_FMT_NV61:
+ case V4L2_PIX_FMT_YUV420:
+ case V4L2_PIX_FMT_YVU420:
+ case V4L2_PIX_FMT_YUV422P:
+ switch (mbus_code) {
+ case MEDIA_BUS_FMT_UYVY8_2X8:
+ case MEDIA_BUS_FMT_VYUY8_2X8:
+ case MEDIA_BUS_FMT_YUYV8_2X8:
+ case MEDIA_BUS_FMT_YVYU8_2X8:
+ return true;
+ }
+ break;
+ }
+
+ return false;
+}
+
+static enum csi_input_fmt get_csi_input_format(u32 mbus_code, u32 pixformat)
+{
+ /* bayer */
+ if ((mbus_code & 0xF000) == 0x3000)
+ return CSI_INPUT_FORMAT_RAW;
+
+ switch (pixformat) {
+ case V4L2_PIX_FMT_YUYV:
+ case V4L2_PIX_FMT_YVYU:
+ case V4L2_PIX_FMT_UYVY:
+ case V4L2_PIX_FMT_VYUY:
+ return CSI_INPUT_FORMAT_RAW;
+ }
+
+ /* not support YUV420 input format yet */
+ return CSI_INPUT_FORMAT_YUV422;
+}
+
+static enum csi_output_fmt get_csi_output_format(u32 pixformat, u32 field)
+{
+ bool buf_interlaced = false;
+
+ if (field == V4L2_FIELD_INTERLACED
+ || field == V4L2_FIELD_INTERLACED_TB
+ || field == V4L2_FIELD_INTERLACED_BT)
+ buf_interlaced = true;
+
+ switch (pixformat) {
+ case V4L2_PIX_FMT_SBGGR8:
+ case V4L2_PIX_FMT_SGBRG8:
+ case V4L2_PIX_FMT_SGRBG8:
+ case V4L2_PIX_FMT_SRGGB8:
+ return buf_interlaced ? CSI_FRAME_RAW_8 : CSI_FIELD_RAW_8;
+ case V4L2_PIX_FMT_SBGGR10:
+ case V4L2_PIX_FMT_SGBRG10:
+ case V4L2_PIX_FMT_SGRBG10:
+ case V4L2_PIX_FMT_SRGGB10:
+ return buf_interlaced ? CSI_FRAME_RAW_10 : CSI_FIELD_RAW_10;
+ case V4L2_PIX_FMT_SBGGR12:
+ case V4L2_PIX_FMT_SGBRG12:
+ case V4L2_PIX_FMT_SGRBG12:
+ case V4L2_PIX_FMT_SRGGB12:
+ return buf_interlaced ? CSI_FRAME_RAW_12 : CSI_FIELD_RAW_12;
+
+ case V4L2_PIX_FMT_YUYV:
+ case V4L2_PIX_FMT_YVYU:
+ case V4L2_PIX_FMT_UYVY:
+ case V4L2_PIX_FMT_VYUY:
+ return buf_interlaced ? CSI_FRAME_RAW_8 : CSI_FIELD_RAW_8;
+
+ case V4L2_PIX_FMT_HM12:
+ return buf_interlaced ? CSI_FRAME_MB_YUV420 :
+ CSI_FIELD_MB_YUV420;
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV21:
+ return buf_interlaced ? CSI_FRAME_UV_CB_YUV420 :
+ CSI_FIELD_UV_CB_YUV420;
+ case V4L2_PIX_FMT_YUV420:
+ case V4L2_PIX_FMT_YVU420:
+ return buf_interlaced ? CSI_FRAME_PLANAR_YUV420 :
+ CSI_FIELD_PLANAR_YUV420;
+ case V4L2_PIX_FMT_NV16:
+ case V4L2_PIX_FMT_NV61:
+ return buf_interlaced ? CSI_FRAME_UV_CB_YUV422 :
+ CSI_FIELD_UV_CB_YUV422;
+ case V4L2_PIX_FMT_YUV422P:
+ return buf_interlaced ? CSI_FRAME_PLANAR_YUV422 :
+ CSI_FIELD_PLANAR_YUV422;
+ }
+
+ return 0;
+}
+
+static enum csi_input_seq get_csi_input_seq(u32 mbus_code, u32 pixformat)
+{
+
+ switch (pixformat) {
+ case V4L2_PIX_FMT_HM12:
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV16:
+ case V4L2_PIX_FMT_YUV420:
+ case V4L2_PIX_FMT_YUV422P:
+ switch (mbus_code) {
+ case MEDIA_BUS_FMT_UYVY8_2X8:
+ case MEDIA_BUS_FMT_UYVY8_1X16:
+ return CSI_INPUT_SEQ_UYVY;
+ case MEDIA_BUS_FMT_VYUY8_2X8:
+ case MEDIA_BUS_FMT_VYUY8_1X16:
+ return CSI_INPUT_SEQ_VYUY;
+ case MEDIA_BUS_FMT_YUYV8_2X8:
+ case MEDIA_BUS_FMT_YUYV8_1X16:
+ return CSI_INPUT_SEQ_YUYV;
+ case MEDIA_BUS_FMT_YVYU8_1X16:
+ case MEDIA_BUS_FMT_YVYU8_2X8:
+ return CSI_INPUT_SEQ_YVYU;
+ }
+ break;
+ case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_NV61:
+ case V4L2_PIX_FMT_YVU420:
+ switch (mbus_code) {
+ case MEDIA_BUS_FMT_UYVY8_2X8:
+ case MEDIA_BUS_FMT_UYVY8_1X16:
+ return CSI_INPUT_SEQ_VYUY;
+ case MEDIA_BUS_FMT_VYUY8_2X8:
+ case MEDIA_BUS_FMT_VYUY8_1X16:
+ return CSI_INPUT_SEQ_UYVY;
+ case MEDIA_BUS_FMT_YUYV8_2X8:
+ case MEDIA_BUS_FMT_YUYV8_1X16:
+ return CSI_INPUT_SEQ_YVYU;
+ case MEDIA_BUS_FMT_YVYU8_1X16:
+ case MEDIA_BUS_FMT_YVYU8_2X8:
+ return CSI_INPUT_SEQ_YUYV;
+ }
+ break;
+ }
+
+ return CSI_INPUT_SEQ_YUYV;
+}
+
+static void sun6i_csi_setup_bus(struct sun6i_csi_dev *sdev)
+{
+ struct v4l2_fwnode_endpoint *endpoint = &sdev->csi.v4l2_ep;
+ unsigned char bus_width;
+ u32 flags;
+ u32 cfg;
+
+ bus_width = endpoint->bus.parallel.bus_width;
+
+ regmap_read(sdev->regmap, CSI_IF_CFG_REG, &cfg);
+
+ cfg &= ~(CSI_IF_CFG_CSI_IF_MASK | CSI_IF_CFG_MIPI_IF_MASK |
+ CSI_IF_CFG_IF_DATA_WIDTH_MASK |
+ CSI_IF_CFG_CLK_POL_MASK | CSI_IF_CFG_VREF_POL_MASK |
+ CSI_IF_CFG_HREF_POL_MASK | CSI_IF_CFG_FIELD_MASK);
+
+ switch (endpoint->bus_type) {
+ case V4L2_MBUS_CSI2:
+ cfg |= CSI_IF_CFG_MIPI_IF_MIPI;
+ break;
+ case V4L2_MBUS_PARALLEL:
+ cfg |= CSI_IF_CFG_MIPI_IF_CSI;
+
+ flags = endpoint->bus.parallel.flags;
+
+ cfg |= (bus_width == 16) ? CSI_IF_CFG_CSI_IF_YUV422_16BIT :
+ CSI_IF_CFG_CSI_IF_YUV422_INTLV;
+
+ if (flags & V4L2_MBUS_FIELD_EVEN_LOW)
+ cfg |= CSI_IF_CFG_FIELD_POSITIVE;
+
+ if (flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH)
+ cfg |= CSI_IF_CFG_VREF_POL_POSITIVE;
+ if (flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH)
+ cfg |= CSI_IF_CFG_HREF_POL_POSITIVE;
+
+ if (flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
+ cfg |= CSI_IF_CFG_CLK_POL_FALLING_EDGE;
+ break;
+ case V4L2_MBUS_BT656:
+ cfg |= CSI_IF_CFG_MIPI_IF_CSI;
+
+ flags = endpoint->bus.parallel.flags;
+
+ cfg |= (bus_width == 16) ? CSI_IF_CFG_CSI_IF_BT1120 :
+ CSI_IF_CFG_CSI_IF_BT656;
+
+ if (flags & V4L2_MBUS_FIELD_EVEN_LOW)
+ cfg |= CSI_IF_CFG_FIELD_POSITIVE;
+
+ if (flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
+ cfg |= CSI_IF_CFG_CLK_POL_FALLING_EDGE;
+ break;
+ default:
+ WARN_ON(1);
+ break;
+ }
+
+ switch (bus_width) {
+ case 8:
+ cfg |= CSI_IF_CFG_IF_DATA_WIDTH_8BIT;
+ break;
+ case 10:
+ cfg |= CSI_IF_CFG_IF_DATA_WIDTH_10BIT;
+ break;
+ case 12:
+ cfg |= CSI_IF_CFG_IF_DATA_WIDTH_12BIT;
+ break;
+ default:
+ break;
+ }
+
+ regmap_write(sdev->regmap, CSI_IF_CFG_REG, cfg);
+}
+
+static void sun6i_csi_set_format(struct sun6i_csi_dev *sdev)
+{
+ struct sun6i_csi *csi = &sdev->csi;
+ u32 cfg;
+ u32 val;
+
+ regmap_read(sdev->regmap, CSI_CH_CFG_REG, &cfg);
+
+ cfg &= ~(CSI_CH_CFG_INPUT_FMT_MASK |
+ CSI_CH_CFG_OUTPUT_FMT_MASK | CSI_CH_CFG_VFLIP_EN |
+ CSI_CH_CFG_HFLIP_EN | CSI_CH_CFG_FIELD_SEL_MASK |
+ CSI_CH_CFG_INPUT_SEQ_MASK);
+
+ val = get_csi_input_format(csi->config.code, csi->config.pixelformat);
+ cfg |= CSI_CH_CFG_INPUT_FMT(val);
+
+ val = get_csi_output_format(csi->config.pixelformat, csi->config.field);
+ cfg |= CSI_CH_CFG_OUTPUT_FMT(val);
+
+ val = get_csi_input_seq(csi->config.code, csi->config.pixelformat);
+ cfg |= CSI_CH_CFG_INPUT_SEQ(val);
+
+ if (csi->config.field == V4L2_FIELD_TOP)
+ cfg |= CSI_CH_CFG_FIELD_SEL_FIELD0;
+ else if (csi->config.field == V4L2_FIELD_BOTTOM)
+ cfg |= CSI_CH_CFG_FIELD_SEL_FIELD1;
+ else
+ cfg |= CSI_CH_CFG_FIELD_SEL_BOTH;
+
+ regmap_write(sdev->regmap, CSI_CH_CFG_REG, cfg);
+}
+
+static void sun6i_csi_set_window(struct sun6i_csi_dev *sdev)
+{
+ struct sun6i_csi_config *config = &sdev->csi.config;
+ u32 bytesperline_y;
+ u32 bytesperline_c;
+ int *planar_offset = sdev->planar_offset;
+ u32 width = config->width;
+ u32 height = config->height;
+ u32 hor_len = width;
+
+ switch (config->pixelformat) {
+ case V4L2_PIX_FMT_YUYV:
+ case V4L2_PIX_FMT_YVYU:
+ case V4L2_PIX_FMT_UYVY:
+ case V4L2_PIX_FMT_VYUY:
+ hor_len = width * 2;
+ break;
+ }
+
+ regmap_write(sdev->regmap, CSI_CH_HSIZE_REG,
+ CSI_CH_HSIZE_HOR_LEN(hor_len) |
+ CSI_CH_HSIZE_HOR_START(0));
+ regmap_write(sdev->regmap, CSI_CH_VSIZE_REG,
+ CSI_CH_VSIZE_VER_LEN(height) |
+ CSI_CH_VSIZE_VER_START(0));
+
+ planar_offset[0] = 0;
+ switch (config->pixelformat) {
+ case V4L2_PIX_FMT_HM12:
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_NV16:
+ case V4L2_PIX_FMT_NV61:
+ bytesperline_y = width;
+ bytesperline_c = width;
+ planar_offset[1] = bytesperline_y * height;
+ planar_offset[2] = -1;
+ break;
+ case V4L2_PIX_FMT_YUV420:
+ case V4L2_PIX_FMT_YVU420:
+ bytesperline_y = width;
+ bytesperline_c = width / 2;
+ planar_offset[1] = bytesperline_y * height;
+ planar_offset[2] = planar_offset[1] +
+ bytesperline_c * height / 2;
+ break;
+ case V4L2_PIX_FMT_YUV422P:
+ bytesperline_y = width;
+ bytesperline_c = width / 2;
+ planar_offset[1] = bytesperline_y * height;
+ planar_offset[2] = planar_offset[1] +
+ bytesperline_c * height;
+ break;
+ default: /* raw */
+ bytesperline_y = (v4l2_pixformat_get_bpp(config->pixelformat) *
+ config->width) / 8;
+ bytesperline_c = 0;
+ planar_offset[1] = -1;
+ planar_offset[2] = -1;
+ break;
+ }
+
+ regmap_write(sdev->regmap, CSI_CH_BUF_LEN_REG,
+ CSI_CH_BUF_LEN_BUF_LEN_C(bytesperline_c) |
+ CSI_CH_BUF_LEN_BUF_LEN_Y(bytesperline_y));
+}
+
+int sun6i_csi_get_supported_pixformats(struct sun6i_csi *csi,
+ const u32 **pixformats)
+{
+ if (pixformats != NULL)
+ *pixformats = supported_pixformats;
+
+ return ARRAY_SIZE(supported_pixformats);
+}
+
+bool sun6i_csi_is_format_support(struct sun6i_csi *csi, u32 pixformat,
+ u32 mbus_code)
+{
+ struct sun6i_csi_dev *sdev = sun6i_csi_to_dev(csi);
+
+ return __is_format_support(sdev, pixformat, mbus_code);
+}
+
+int sun6i_csi_set_power(struct sun6i_csi *csi, bool enable)
+{
+ struct sun6i_csi_dev *sdev = sun6i_csi_to_dev(csi);
+ struct regmap *regmap = sdev->regmap;
+ int ret;
+
+ if (!enable) {
+ regmap_update_bits(regmap, CSI_EN_REG, CSI_EN_CSI_EN, 0);
+
+ clk_disable_unprepare(sdev->clk_ram);
+ clk_disable_unprepare(sdev->clk_mod);
+ reset_control_assert(sdev->rstc_bus);
+ return 0;
+ }
+
+ ret = clk_prepare_enable(sdev->clk_mod);
+ if (ret) {
+ dev_err(sdev->dev, "Enable csi clk err %d\n", ret);
+ return ret;
+ }
+
+ ret = clk_prepare_enable(sdev->clk_ram);
+ if (ret) {
+ dev_err(sdev->dev, "Enable clk_dram_csi clk err %d\n", ret);
+ return ret;
+ }
+
+ ret = reset_control_deassert(sdev->rstc_bus);
+ if (ret) {
+ dev_err(sdev->dev, "reset err %d\n", ret);
+ return ret;
+ }
+
+ regmap_update_bits(regmap, CSI_EN_REG, CSI_EN_CSI_EN, CSI_EN_CSI_EN);
+
+ return 0;
+}
+
+int sun6i_csi_update_config(struct sun6i_csi *csi,
+ struct sun6i_csi_config *config)
+{
+ struct sun6i_csi_dev *sdev = sun6i_csi_to_dev(csi);
+
+ if (config == NULL)
+ return -EINVAL;
+
+ memcpy(&csi->config, config, sizeof(csi->config));
+
+ sun6i_csi_setup_bus(sdev);
+ sun6i_csi_set_format(sdev);
+ sun6i_csi_set_window(sdev);
+
+ return 0;
+}
+
+int sun6i_csi_update_buf_addr(struct sun6i_csi *csi, dma_addr_t addr)
+{
+ struct sun6i_csi_dev *sdev = sun6i_csi_to_dev(csi);
+ /* transform physical address to bus address */
+ dma_addr_t bus_addr = addr - PHYS_OFFSET;
+
+ regmap_write(sdev->regmap, CSI_CH_F0_BUFA_REG,
+ (bus_addr + sdev->planar_offset[0]) >> 2);
+ if (sdev->planar_offset[1] != -1)
+ regmap_write(sdev->regmap, CSI_CH_F1_BUFA_REG,
+ (bus_addr + sdev->planar_offset[1]) >> 2);
+ if (sdev->planar_offset[2] != -1)
+ regmap_write(sdev->regmap, CSI_CH_F2_BUFA_REG,
+ (bus_addr + sdev->planar_offset[2]) >> 2);
+
+ return 0;
+}
+
+int sun6i_csi_set_stream(struct sun6i_csi *csi, bool enable)
+{
+ struct sun6i_csi_dev *sdev = sun6i_csi_to_dev(csi);
+ struct regmap *regmap = sdev->regmap;
+
+ if (!enable) {
+ regmap_update_bits(regmap, CSI_CAP_REG, CSI_CAP_CH0_VCAP_ON, 0);
+ regmap_write(regmap, CSI_CH_INT_EN_REG, 0);
+ return 0;
+ }
+
+ regmap_write(regmap, CSI_CH_INT_STA_REG, 0xFF);
+ regmap_write(regmap, CSI_CH_INT_EN_REG,
+ CSI_CH_INT_EN_HB_OF_INT_EN |
+ CSI_CH_INT_EN_FIFO2_OF_INT_EN |
+ CSI_CH_INT_EN_FIFO1_OF_INT_EN |
+ CSI_CH_INT_EN_FIFO0_OF_INT_EN |
+ CSI_CH_INT_EN_FD_INT_EN |
+ CSI_CH_INT_EN_CD_INT_EN);
+
+ regmap_update_bits(regmap, CSI_CAP_REG, CSI_CAP_CH0_VCAP_ON,
+ CSI_CAP_CH0_VCAP_ON);
+
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Media Controller and V4L2
+ */
+static int sun6i_csi_link_entity(struct sun6i_csi *csi,
+ struct media_entity *entity)
+{
+ struct media_entity *sink;
+ struct media_pad *sink_pad;
+ int ret;
+ int i;
+
+ if (!entity->num_pads) {
+ dev_err(csi->dev, "%s: invalid entity\n", entity->name);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < entity->num_pads; i++) {
+ if (entity->pads[i].flags & MEDIA_PAD_FL_SOURCE)
+ break;
+ }
+
+ if (i == entity->num_pads) {
+ dev_err(csi->dev, "%s: no source pad in external entity %s\n",
+ __func__, entity->name);
+ return -EINVAL;
+ }
+
+ sink = &csi->video.vdev.entity;
+ sink_pad = &csi->video.pad;
+
+ dev_dbg(csi->dev, "creating %s:%u -> %s:%u link\n",
+ entity->name, i, sink->name, sink_pad->index);
+ ret = media_create_pad_link(entity, i, sink, sink_pad->index,
+ MEDIA_LNK_FL_ENABLED);
+ if (ret < 0) {
+ dev_err(csi->dev, "failed to create %s:%u -> %s:%u link\n",
+ entity->name, i, sink->name, sink_pad->index);
+ return ret;
+ }
+
+ return media_entity_call(sink, link_setup, sink_pad, &entity->pads[i],
+ MEDIA_LNK_FL_ENABLED);
+}
+
+static int sun6i_subdev_notify_complete(struct v4l2_async_notifier *notifier)
+{
+ struct sun6i_csi *csi = container_of(notifier, struct sun6i_csi,
+ notifier);
+ struct v4l2_device *v4l2_dev = &csi->v4l2_dev;
+ struct v4l2_subdev *sd;
+ int ret;
+
+ dev_dbg(csi->dev, "notify complete, all subdevs registered\n");
+
+ if (notifier->num_subdevs != 1)
+ return -EINVAL;
+
+ sd = list_first_entry(&v4l2_dev->subdevs, struct v4l2_subdev, list);
+ if (sd == NULL)
+ return -EINVAL;
+
+ ret = sun6i_csi_link_entity(csi, &sd->entity);
+ if (ret < 0)
+ return ret;
+
+ ret = v4l2_device_register_subdev_nodes(&csi->v4l2_dev);
+ if (ret < 0)
+ return ret;
+
+ return media_device_register(&csi->media_dev);
+}
+
+static const struct v4l2_async_notifier_operations sun6i_csi_async_ops = {
+ .complete = sun6i_subdev_notify_complete,
+};
+
+static int sun6i_csi_fwnode_parse(struct device *dev,
+ struct v4l2_fwnode_endpoint *vep,
+ struct v4l2_async_subdev *asd)
+{
+ struct sun6i_csi *csi = dev_get_drvdata(dev);
+
+ if (vep->base.port || vep->base.id) {
+ dev_warn(dev, "Only support a single port with one endpoint\n");
+ return -ENOTCONN;
+ }
+
+ switch (vep->bus_type) {
+ case V4L2_MBUS_PARALLEL:
+ case V4L2_MBUS_BT656:
+ csi->v4l2_ep = *vep;
+ return 0;
+ default:
+ dev_err(dev, "Unsupported media bus type\n");
+ return -ENOTCONN;
+ }
+}
+
+static void sun6i_csi_v4l2_cleanup(struct sun6i_csi *csi)
+{
+ v4l2_async_notifier_cleanup(&csi->notifier);
+ v4l2_async_notifier_unregister(&csi->notifier);
+ sun6i_video_cleanup(&csi->video);
+ v4l2_device_unregister(&csi->v4l2_dev);
+ media_device_unregister(&csi->media_dev);
+ media_device_cleanup(&csi->media_dev);
+}
+
+static int sun6i_csi_v4l2_init(struct sun6i_csi *csi)
+{
+ int ret;
+
+ csi->media_dev.dev = csi->dev;
+ strlcpy(csi->media_dev.model, "Allwinner Video Capture Device",
+ sizeof(csi->media_dev.model));
+ csi->media_dev.hw_revision = 0;
+
+ media_device_init(&csi->media_dev);
+
+ csi->v4l2_dev.mdev = &csi->media_dev;
+ ret = v4l2_device_register(csi->dev, &csi->v4l2_dev);
+ if (ret) {
+ dev_err(csi->dev, "V4L2 device registration failed (%d)\n",
+ ret);
+ goto v4l2_reg_err;
+ }
+
+ ret = sun6i_video_init(&csi->video, csi, "sun6i-csi");
+ if (ret)
+ goto video_init_err;
+
+ ret = v4l2_async_notifier_parse_fwnode_endpoints(
+ csi->dev, &csi->notifier, sizeof(struct v4l2_async_subdev),
+ sun6i_csi_fwnode_parse);
+ if (ret)
+ goto fwnode_parse_err;
+
+ csi->notifier.ops = &sun6i_csi_async_ops;
+
+ ret = v4l2_async_notifier_register(&csi->v4l2_dev, &csi->notifier);
+ if (ret) {
+ dev_err(csi->dev, "notifier registration failed\n");
+ goto notifier_reg_err;
+ }
+
+ return 0;
+
+notifier_reg_err:
+ v4l2_async_notifier_cleanup(&csi->notifier);
+fwnode_parse_err:
+ sun6i_video_cleanup(&csi->video);
+video_init_err:
+ v4l2_device_unregister(&csi->v4l2_dev);
+v4l2_reg_err:
+ media_device_cleanup(&csi->media_dev);
+
+ return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * Resources and IRQ
+ */
+static irqreturn_t sun6i_csi_isr(int irq, void *dev_id)
+{
+ struct sun6i_csi_dev *sdev = (struct sun6i_csi_dev *)dev_id;
+ struct regmap *regmap = sdev->regmap;
+ u32 status;
+
+ regmap_read(regmap, CSI_CH_INT_STA_REG, &status);
+
+ if (!(status & 0xFF))
+ return IRQ_NONE;
+
+ if ((status & CSI_CH_INT_STA_FIFO0_OF_PD) ||
+ (status & CSI_CH_INT_STA_FIFO1_OF_PD) ||
+ (status & CSI_CH_INT_STA_FIFO2_OF_PD) ||
+ (status & CSI_CH_INT_STA_HB_OF_PD)) {
+ regmap_write(regmap, CSI_CH_INT_STA_REG, status);
+ regmap_update_bits(regmap, CSI_EN_REG, CSI_EN_CSI_EN, 0);
+ regmap_update_bits(regmap, CSI_EN_REG, CSI_EN_CSI_EN,
+ CSI_EN_CSI_EN);
+ return IRQ_HANDLED;
+ }
+
+ if (status & CSI_CH_INT_STA_FD_PD)
+ sun6i_video_frame_done(&sdev->csi.video);
+
+ regmap_write(regmap, CSI_CH_INT_STA_REG, status);
+
+ return IRQ_HANDLED;
+}
+
+static const struct regmap_config sun6i_csi_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x1000,
+};
+
+static int sun6i_csi_resource_request(struct sun6i_csi_dev *sdev,
+ struct platform_device *pdev)
+{
+ struct resource *res;
+ void __iomem *io_base;
+ int ret;
+ int irq;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ io_base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(io_base))
+ return PTR_ERR(io_base);
+
+ sdev->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "bus", io_base,
+ &sun6i_csi_regmap_config);
+ if (IS_ERR(sdev->regmap)) {
+ dev_err(&pdev->dev, "Failed to init register map\n");
+ return PTR_ERR(sdev->regmap);
+ }
+
+ sdev->clk_mod = devm_clk_get(&pdev->dev, "mod");
+ if (IS_ERR(sdev->clk_mod)) {
+ dev_err(&pdev->dev, "Unable to acquire csi clock\n");
+ return PTR_ERR(sdev->clk_mod);
+ }
+
+ sdev->clk_ram = devm_clk_get(&pdev->dev, "ram");
+ if (IS_ERR(sdev->clk_ram)) {
+ dev_err(&pdev->dev, "Unable to acquire dram-csi clock\n");
+ return PTR_ERR(sdev->clk_ram);
+ }
+
+ sdev->rstc_bus = devm_reset_control_get_shared(&pdev->dev, NULL);
+ if (IS_ERR(sdev->rstc_bus)) {
+ dev_err(&pdev->dev, "Cannot get reset controller\n");
+ return PTR_ERR(sdev->rstc_bus);
+ }
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(&pdev->dev, "No csi IRQ specified\n");
+ ret = -ENXIO;
+ return ret;
+ }
+
+ ret = devm_request_irq(&pdev->dev, irq, sun6i_csi_isr, 0, MODULE_NAME,
+ sdev);
+ if (ret) {
+ dev_err(&pdev->dev, "Cannot request csi IRQ\n");
+ return ret;
+ }
+ return 0;
+}
+
+static int sun6i_csi_probe(struct platform_device *pdev)
+{
+ struct sun6i_csi_dev *sdev;
+ int ret;
+
+ sdev = devm_kzalloc(&pdev->dev, sizeof(*sdev), GFP_KERNEL);
+ if (!sdev)
+ return -ENOMEM;
+
+ sdev->dev = &pdev->dev;
+
+ ret = sun6i_csi_resource_request(sdev, pdev);
+ if (ret)
+ return ret;
+
+ platform_set_drvdata(pdev, sdev);
+
+ sdev->csi.dev = &pdev->dev;
+ ret = sun6i_csi_v4l2_init(&sdev->csi);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int sun6i_csi_remove(struct platform_device *pdev)
+{
+ struct sun6i_csi_dev *sdev = platform_get_drvdata(pdev);
+
+ sun6i_csi_v4l2_cleanup(&sdev->csi);
+
+ return 0;
+}
+
+static const struct of_device_id sun6i_csi_of_match[] = {
+ { .compatible = "allwinner,sun8i-v3s-csi", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, sun6i_csi_of_match);
+
+static struct platform_driver sun6i_csi_platform_driver = {
+ .probe = sun6i_csi_probe,
+ .remove = sun6i_csi_remove,
+ .driver = {
+ .name = MODULE_NAME,
+ .of_match_table = of_match_ptr(sun6i_csi_of_match),
+ },
+};
+module_platform_driver(sun6i_csi_platform_driver);
+
+MODULE_DESCRIPTION("Allwinner V3s Camera Sensor Interface driver");
+MODULE_AUTHOR("Yong Deng <yong.deng-+3dxTMOEIRNWk0Htik3J/w@public.gmane.org>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.h b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.h
new file mode 100644
index 0000000..12508ff
--- /dev/null
+++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.h
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2017 Yong Deng <yong.deng-+3dxTMOEIRNWk0Htik3J/w@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __SUN6I_CSI_H__
+#define __SUN6I_CSI_H__
+
+#include <media/v4l2-device.h>
+#include <media/v4l2-fwnode.h>
+
+#include "sun6i_video.h"
+
+struct sun6i_csi;
+
+/**
+ * struct sun6i_csi_config - configs for sun6i csi
+ * @pixelformat: v4l2 pixel format (V4L2_PIX_FMT_*)
+ * @code: media bus format code (MEDIA_BUS_FMT_*)
+ * @field: used interlacing type (enum v4l2_field)
+ * @width: frame width
+ * @height: frame height
+ */
+struct sun6i_csi_config {
+ u32 pixelformat;
+ u32 code;
+ u32 field;
+ u32 width;
+ u32 height;
+};
+
+struct sun6i_csi {
+ struct device *dev;
+ struct v4l2_device v4l2_dev;
+ struct media_device media_dev;
+
+ struct v4l2_async_notifier notifier;
+
+ /* video port settings */
+ struct v4l2_fwnode_endpoint v4l2_ep;
+
+ struct sun6i_csi_config config;
+
+ struct sun6i_video video;
+};
+
+/**
+ * sun6i_csi_get_supported_pixformats() - get csi supported pixformats
+ * @csi: pointer to the csi
+ * @pixformats: supported pixformats return from csi
+ *
+ * @return the count of pixformats or error(< 0)
+ */
+int sun6i_csi_get_supported_pixformats(struct sun6i_csi *csi,
+ const u32 **pixformats);
+
+/**
+ * sun6i_csi_is_format_support() - check if the format supported by csi
+ * @csi: pointer to the csi
+ * @pixformat: v4l2 pixel format (V4L2_PIX_FMT_*)
+ * @mbus_code: media bus format code (MEDIA_BUS_FMT_*)
+ */
+bool sun6i_csi_is_format_support(struct sun6i_csi *csi, u32 pixformat,
+ u32 mbus_code);
+
+/**
+ * sun6i_csi_set_power() - power on/off the csi
+ * @csi: pointer to the csi
+ * @enable: on/off
+ */
+int sun6i_csi_set_power(struct sun6i_csi *csi, bool enable);
+
+/**
+ * sun6i_csi_update_config() - update the csi register setttings
+ * @csi: pointer to the csi
+ * @config: see struct sun6i_csi_config
+ */
+int sun6i_csi_update_config(struct sun6i_csi *csi,
+ struct sun6i_csi_config *config);
+
+/**
+ * sun6i_csi_update_buf_addr() - update the csi frame buffer address
+ * @csi: pointer to the csi
+ * @addr: frame buffer's physical address
+ */
+int sun6i_csi_update_buf_addr(struct sun6i_csi *csi, dma_addr_t addr);
+
+/**
+ * sun6i_csi_set_stream() - start/stop csi streaming
+ * @csi: pointer to the csi
+ * @enable: start/stop
+ */
+int sun6i_csi_set_stream(struct sun6i_csi *csi, bool enable);
+
+static inline int v4l2_pixformat_get_bpp(unsigned int pixformat)
+{
+ switch (pixformat) {
+ case V4L2_PIX_FMT_SBGGR8:
+ case V4L2_PIX_FMT_SGBRG8:
+ case V4L2_PIX_FMT_SGRBG8:
+ case V4L2_PIX_FMT_SRGGB8:
+ return 8;
+ case V4L2_PIX_FMT_SBGGR10:
+ case V4L2_PIX_FMT_SGBRG10:
+ case V4L2_PIX_FMT_SGRBG10:
+ case V4L2_PIX_FMT_SRGGB10:
+ return 10;
+ case V4L2_PIX_FMT_SBGGR12:
+ case V4L2_PIX_FMT_SGBRG12:
+ case V4L2_PIX_FMT_SGRBG12:
+ case V4L2_PIX_FMT_SRGGB12:
+ case V4L2_PIX_FMT_HM12:
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_YUV420:
+ case V4L2_PIX_FMT_YVU420:
+ return 12;
+ case V4L2_PIX_FMT_YUYV:
+ case V4L2_PIX_FMT_YVYU:
+ case V4L2_PIX_FMT_UYVY:
+ case V4L2_PIX_FMT_VYUY:
+ case V4L2_PIX_FMT_NV16:
+ case V4L2_PIX_FMT_NV61:
+ case V4L2_PIX_FMT_YUV422P:
+ return 16;
+ case V4L2_PIX_FMT_RGB24:
+ case V4L2_PIX_FMT_BGR24:
+ return 24;
+ case V4L2_PIX_FMT_RGB32:
+ case V4L2_PIX_FMT_BGR32:
+ return 32;
+ }
+
+ return 0;
+}
+
+#endif /* __SUN6I_CSI_H__ */
diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_reg.h b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_reg.h
new file mode 100644
index 0000000..8e80467
--- /dev/null
+++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_reg.h
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2017 Yong Deng <yong.deng-+3dxTMOEIRNWk0Htik3J/w@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __SUN6I_CSI_V3S_H__
+#define __SUN6I_CSI_V3S_H__
+
+#include <linux/kernel.h>
+
+#define CSI_EN_REG 0x0
+#define CSI_EN_VER_EN BIT(30)
+#define CSI_EN_CSI_EN BIT(0)
+
+#define CSI_IF_CFG_REG 0x4
+#define CSI_IF_CFG_SRC_TYPE_MASK BIT(21)
+#define CSI_IF_CFG_SRC_TYPE_PROGRESSED ((0 << 21) & CSI_IF_CFG_SRC_TYPE_MASK)
+#define CSI_IF_CFG_SRC_TYPE_INTERLACED ((1 << 21) & CSI_IF_CFG_SRC_TYPE_MASK)
+#define CSI_IF_CFG_FPS_DS_EN BIT(20)
+#define CSI_IF_CFG_FIELD_MASK BIT(19)
+#define CSI_IF_CFG_FIELD_NEGATIVE ((0 << 19) & CSI_IF_CFG_FIELD_MASK)
+#define CSI_IF_CFG_FIELD_POSITIVE ((1 << 19) & CSI_IF_CFG_FIELD_MASK)
+#define CSI_IF_CFG_VREF_POL_MASK BIT(18)
+#define CSI_IF_CFG_VREF_POL_NEGATIVE ((0 << 18) & CSI_IF_CFG_VREF_POL_MASK)
+#define CSI_IF_CFG_VREF_POL_POSITIVE ((1 << 18) & CSI_IF_CFG_VREF_POL_MASK)
+#define CSI_IF_CFG_HREF_POL_MASK BIT(17)
+#define CSI_IF_CFG_HREF_POL_NEGATIVE ((0 << 17) & CSI_IF_CFG_HREF_POL_MASK)
+#define CSI_IF_CFG_HREF_POL_POSITIVE ((1 << 17) & CSI_IF_CFG_HREF_POL_MASK)
+#define CSI_IF_CFG_CLK_POL_MASK BIT(16)
+#define CSI_IF_CFG_CLK_POL_RISING_EDGE ((0 << 16) & CSI_IF_CFG_CLK_POL_MASK)
+#define CSI_IF_CFG_CLK_POL_FALLING_EDGE ((1 << 16) & CSI_IF_CFG_CLK_POL_MASK)
+#define CSI_IF_CFG_IF_DATA_WIDTH_MASK GENMASK(10, 8)
+#define CSI_IF_CFG_IF_DATA_WIDTH_8BIT ((0 << 8) & CSI_IF_CFG_IF_DATA_WIDTH_MASK)
+#define CSI_IF_CFG_IF_DATA_WIDTH_10BIT ((1 << 8) & CSI_IF_CFG_IF_DATA_WIDTH_MASK)
+#define CSI_IF_CFG_IF_DATA_WIDTH_12BIT ((2 << 8) & CSI_IF_CFG_IF_DATA_WIDTH_MASK)
+#define CSI_IF_CFG_MIPI_IF_MASK BIT(7)
+#define CSI_IF_CFG_MIPI_IF_CSI (0 << 7)
+#define CSI_IF_CFG_MIPI_IF_MIPI (1 << 7)
+#define CSI_IF_CFG_CSI_IF_MASK GENMASK(4, 0)
+#define CSI_IF_CFG_CSI_IF_YUV422_INTLV ((0 << 0) & CSI_IF_CFG_CSI_IF_MASK)
+#define CSI_IF_CFG_CSI_IF_YUV422_16BIT ((1 << 0) & CSI_IF_CFG_CSI_IF_MASK)
+#define CSI_IF_CFG_CSI_IF_BT656 ((4 << 0) & CSI_IF_CFG_CSI_IF_MASK)
+#define CSI_IF_CFG_CSI_IF_BT1120 ((5 << 0) & CSI_IF_CFG_CSI_IF_MASK)
+
+#define CSI_CAP_REG 0x8
+#define CSI_CAP_CH0_CAP_MASK_MASK GENMASK(5, 2)
+#define CSI_CAP_CH0_CAP_MASK(count) ((count << 2) & CSI_CAP_CH0_CAP_MASK_MASK)
+#define CSI_CAP_CH0_VCAP_ON BIT(1)
+#define CSI_CAP_CH0_SCAP_ON BIT(0)
+
+#define CSI_SYNC_CNT_REG 0xc
+#define CSI_FIFO_THRS_REG 0x10
+#define CSI_BT656_HEAD_CFG_REG 0x14
+#define CSI_PTN_LEN_REG 0x30
+#define CSI_PTN_ADDR_REG 0x34
+#define CSI_VER_REG 0x3c
+
+#define CSI_CH_CFG_REG 0x44
+#define CSI_CH_CFG_INPUT_FMT_MASK GENMASK(23, 20)
+#define CSI_CH_CFG_INPUT_FMT(fmt) ((fmt << 20) & CSI_CH_CFG_INPUT_FMT_MASK)
+#define CSI_CH_CFG_OUTPUT_FMT_MASK GENMASK(19, 16)
+#define CSI_CH_CFG_OUTPUT_FMT(fmt) ((fmt << 16) & CSI_CH_CFG_OUTPUT_FMT_MASK)
+#define CSI_CH_CFG_VFLIP_EN BIT(13)
+#define CSI_CH_CFG_HFLIP_EN BIT(12)
+#define CSI_CH_CFG_FIELD_SEL_MASK GENMASK(11, 10)
+#define CSI_CH_CFG_FIELD_SEL_FIELD0 ((0 << 10) & CSI_CH_CFG_FIELD_SEL_MASK)
+#define CSI_CH_CFG_FIELD_SEL_FIELD1 ((1 << 10) & CSI_CH_CFG_FIELD_SEL_MASK)
+#define CSI_CH_CFG_FIELD_SEL_BOTH ((2 << 10) & CSI_CH_CFG_FIELD_SEL_MASK)
+#define CSI_CH_CFG_INPUT_SEQ_MASK GENMASK(9, 8)
+#define CSI_CH_CFG_INPUT_SEQ(seq) ((seq << 8) & CSI_CH_CFG_INPUT_SEQ_MASK)
+
+#define CSI_CH_SCALE_REG 0x4c
+#define CSI_CH_SCALE_QUART_EN BIT(0)
+
+#define CSI_CH_F0_BUFA_REG 0x50
+
+#define CSI_CH_F1_BUFA_REG 0x58
+
+#define CSI_CH_F2_BUFA_REG 0x60
+
+#define CSI_CH_STA_REG 0x6c
+#define CSI_CH_STA_FIELD_STA_MASK BIT(2)
+#define CSI_CH_STA_FIELD_STA_FIELD0 ((0 << 2) & CSI_CH_STA_FIELD_STA_MASK)
+#define CSI_CH_STA_FIELD_STA_FIELD1 ((1 << 2) & CSI_CH_STA_FIELD_STA_MASK)
+#define CSI_CH_STA_VCAP_STA BIT(1)
+#define CSI_CH_STA_SCAP_STA BIT(0)
+
+#define CSI_CH_INT_EN_REG 0x70
+#define CSI_CH_INT_EN_VS_INT_EN BIT(7)
+#define CSI_CH_INT_EN_HB_OF_INT_EN BIT(6)
+#define CSI_CH_INT_EN_MUL_ERR_INT_EN BIT(5)
+#define CSI_CH_INT_EN_FIFO2_OF_INT_EN BIT(4)
+#define CSI_CH_INT_EN_FIFO1_OF_INT_EN BIT(3)
+#define CSI_CH_INT_EN_FIFO0_OF_INT_EN BIT(2)
+#define CSI_CH_INT_EN_FD_INT_EN BIT(1)
+#define CSI_CH_INT_EN_CD_INT_EN BIT(0)
+
+#define CSI_CH_INT_STA_REG 0x74
+#define CSI_CH_INT_STA_VS_PD BIT(7)
+#define CSI_CH_INT_STA_HB_OF_PD BIT(6)
+#define CSI_CH_INT_STA_MUL_ERR_PD BIT(5)
+#define CSI_CH_INT_STA_FIFO2_OF_PD BIT(4)
+#define CSI_CH_INT_STA_FIFO1_OF_PD BIT(3)
+#define CSI_CH_INT_STA_FIFO0_OF_PD BIT(2)
+#define CSI_CH_INT_STA_FD_PD BIT(1)
+#define CSI_CH_INT_STA_CD_PD BIT(0)
+
+#define CSI_CH_FLD1_VSIZE_REG 0x78
+
+#define CSI_CH_HSIZE_REG 0x80
+#define CSI_CH_HSIZE_HOR_LEN_MASK GENMASK(28, 16)
+#define CSI_CH_HSIZE_HOR_LEN(len) ((len << 16) & CSI_CH_HSIZE_HOR_LEN_MASK)
+#define CSI_CH_HSIZE_HOR_START_MASK GENMASK(12, 0)
+#define CSI_CH_HSIZE_HOR_START(start) ((start << 0) & CSI_CH_HSIZE_HOR_START_MASK)
+
+#define CSI_CH_VSIZE_REG 0x84
+#define CSI_CH_VSIZE_VER_LEN_MASK GENMASK(28, 16)
+#define CSI_CH_VSIZE_VER_LEN(len) ((len << 16) & CSI_CH_VSIZE_VER_LEN_MASK)
+#define CSI_CH_VSIZE_VER_START_MASK GENMASK(12, 0)
+#define CSI_CH_VSIZE_VER_START(start) ((start << 0) & CSI_CH_VSIZE_VER_START_MASK)
+
+#define CSI_CH_BUF_LEN_REG 0x88
+#define CSI_CH_BUF_LEN_BUF_LEN_C_MASK GENMASK(29, 16)
+#define CSI_CH_BUF_LEN_BUF_LEN_C(len) ((len << 16) & CSI_CH_BUF_LEN_BUF_LEN_C_MASK)
+#define CSI_CH_BUF_LEN_BUF_LEN_Y_MASK GENMASK(13, 0)
+#define CSI_CH_BUF_LEN_BUF_LEN_Y(len) ((len << 0) & CSI_CH_BUF_LEN_BUF_LEN_Y_MASK)
+
+#define CSI_CH_FLIP_SIZE_REG 0x8c
+#define CSI_CH_FLIP_SIZE_VER_LEN_MASK GENMASK(28, 16)
+#define CSI_CH_FLIP_SIZE_VER_LEN(len) ((len << 16) & CSI_CH_FLIP_SIZE_VER_LEN_MASK)
+#define CSI_CH_FLIP_SIZE_VALID_LEN_MASK GENMASK(12, 0)
+#define CSI_CH_FLIP_SIZE_VALID_LEN(len) ((len << 0) & CSI_CH_FLIP_SIZE_VALID_LEN_MASK)
+
+#define CSI_CH_FRM_CLK_CNT_REG 0x90
+#define CSI_CH_ACC_ITNL_CLK_CNT_REG 0x94
+#define CSI_CH_FIFO_STAT_REG 0x98
+#define CSI_CH_PCLK_STAT_REG 0x9c
+
+/*
+ * csi input data format
+ */
+enum csi_input_fmt {
+ CSI_INPUT_FORMAT_RAW = 0,
+ CSI_INPUT_FORMAT_YUV422 = 3,
+ CSI_INPUT_FORMAT_YUV420 = 4,
+};
+
+/*
+ * csi output data format
+ */
+enum csi_output_fmt {
+ /* only when input format is RAW */
+ CSI_FIELD_RAW_8 = 0,
+ CSI_FIELD_RAW_10 = 1,
+ CSI_FIELD_RAW_12 = 2,
+ CSI_FIELD_RGB565 = 4,
+ CSI_FIELD_RGB888 = 5,
+ CSI_FIELD_PRGB888 = 6,
+ CSI_FRAME_RAW_8 = 8,
+ CSI_FRAME_RAW_10 = 9,
+ CSI_FRAME_RAW_12 = 10,
+ CSI_FRAME_RGB565 = 12,
+ CSI_FRAME_RGB888 = 13,
+ CSI_FRAME_PRGB888 = 14,
+
+ /* only when input format is YUV422 */
+ CSI_FIELD_PLANAR_YUV422 = 0,
+ CSI_FIELD_PLANAR_YUV420 = 1,
+ CSI_FRAME_PLANAR_YUV420 = 2,
+ CSI_FRAME_PLANAR_YUV422 = 3,
+ CSI_FIELD_UV_CB_YUV422 = 4,
+ CSI_FIELD_UV_CB_YUV420 = 5,
+ CSI_FRAME_UV_CB_YUV420 = 6,
+ CSI_FRAME_UV_CB_YUV422 = 7,
+ CSI_FIELD_MB_YUV422 = 8,
+ CSI_FIELD_MB_YUV420 = 9,
+ CSI_FRAME_MB_YUV420 = 10,
+ CSI_FRAME_MB_YUV422 = 11,
+ CSI_FIELD_UV_CB_YUV422_10 = 12,
+ CSI_FIELD_UV_CB_YUV420_10 = 13,
+};
+
+/*
+ * csi YUV input data sequence
+ */
+enum csi_input_seq {
+ /* only when input format is YUV422 */
+ CSI_INPUT_SEQ_YUYV = 0,
+ CSI_INPUT_SEQ_YVYU,
+ CSI_INPUT_SEQ_UYVY,
+ CSI_INPUT_SEQ_VYUY,
+};
+
+#endif /* __SUN6I_CSI_V3S_H__ */
diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_video.c b/drivers/media/platform/sunxi/sun6i-csi/sun6i_video.c
new file mode 100644
index 0000000..0cebcbd
--- /dev/null
+++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_video.c
@@ -0,0 +1,722 @@
+/*
+ * Copyright (c) 2017 Magewell Electronics Co., Ltd. (Nanjing).
+ * All rights reserved.
+ * Author: Yong Deng <yong.deng-+3dxTMOEIRNWk0Htik3J/w@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/of.h>
+
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-mc.h>
+#include <media/videobuf2-dma-contig.h>
+#include <media/videobuf2-v4l2.h>
+
+#include "sun6i_csi.h"
+#include "sun6i_video.h"
+
+struct sun6i_csi_buffer {
+ struct vb2_v4l2_buffer vb;
+ struct list_head list;
+
+ dma_addr_t dma_addr;
+};
+
+static struct sun6i_csi_format *
+find_format_by_fourcc(struct sun6i_video *video, unsigned int fourcc)
+{
+ unsigned int num_formats = video->num_formats;
+ struct sun6i_csi_format *fmt;
+ unsigned int i;
+
+ for (i = 0; i < num_formats; i++) {
+ fmt = &video->formats[i];
+ if (fmt->fourcc == fourcc)
+ return fmt;
+ }
+
+ return NULL;
+}
+
+static struct v4l2_subdev *
+sun6i_video_remote_subdev(struct sun6i_video *video, u32 *pad)
+{
+ struct media_pad *remote;
+
+ remote = media_entity_remote_pad(&video->pad);
+
+ if (!remote || !is_media_entity_v4l2_subdev(remote->entity))
+ return NULL;
+
+ if (pad)
+ *pad = remote->index;
+
+ return media_entity_to_v4l2_subdev(remote->entity);
+}
+
+static int sun6i_video_queue_setup(struct vb2_queue *vq,
+ unsigned int *nbuffers, unsigned int *nplanes,
+ unsigned int sizes[],
+ struct device *alloc_devs[])
+{
+ struct sun6i_video *video = vb2_get_drv_priv(vq);
+ unsigned int size = video->fmt.fmt.pix.sizeimage;
+
+ if (*nplanes)
+ return sizes[0] < size ? -EINVAL : 0;
+
+ *nplanes = 1;
+ sizes[0] = size;
+
+ return 0;
+}
+
+static int sun6i_video_buffer_prepare(struct vb2_buffer *vb)
+{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct sun6i_csi_buffer *buf =
+ container_of(vbuf, struct sun6i_csi_buffer, vb);
+ struct sun6i_video *video = vb2_get_drv_priv(vb->vb2_queue);
+ unsigned long size = video->fmt.fmt.pix.sizeimage;
+
+ if (vb2_plane_size(vb, 0) < size) {
+ v4l2_err(video->vdev.v4l2_dev, "buffer too small (%lu < %lu)\n",
+ vb2_plane_size(vb, 0), size);
+ return -EINVAL;
+ }
+
+ vb2_set_plane_payload(vb, 0, size);
+
+ buf->dma_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
+
+ vbuf->field = video->fmt.fmt.pix.field;
+
+ return 0;
+}
+
+static int sun6i_pipeline_set_stream(struct sun6i_video *video, bool enable)
+{
+ struct media_entity *entity;
+ struct media_pad *pad;
+ struct v4l2_subdev *subdev;
+ int ret;
+
+ entity = &video->vdev.entity;
+ while (1) {
+ pad = &entity->pads[0];
+ if (!(pad->flags & MEDIA_PAD_FL_SINK))
+ break;
+
+ pad = media_entity_remote_pad(pad);
+ if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
+ break;
+
+ entity = pad->entity;
+ subdev = media_entity_to_v4l2_subdev(entity);
+
+ ret = v4l2_subdev_call(subdev, video, s_stream, enable);
+ if (enable && ret < 0 && ret != -ENOIOCTLCMD)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int sun6i_video_start_streaming(struct vb2_queue *vq, unsigned int count)
+{
+ struct sun6i_video *video = vb2_get_drv_priv(vq);
+ struct sun6i_csi_buffer *buf;
+ struct sun6i_csi_config config;
+ unsigned long flags;
+ int ret;
+
+ video->sequence = 0;
+
+ ret = media_pipeline_start(&video->vdev.entity, &video->vdev.pipe);
+ if (ret < 0)
+ goto err_start_pipeline;
+
+ ret = sun6i_pipeline_set_stream(video, true);
+ if (ret < 0)
+ goto err_start_stream;
+
+ config.pixelformat = video->fmt.fmt.pix.pixelformat;
+ config.code = video->current_fmt->mbus_code;
+ config.field = video->fmt.fmt.pix.field;
+ config.width = video->fmt.fmt.pix.width;
+ config.height = video->fmt.fmt.pix.height;
+
+ ret = sun6i_csi_update_config(video->csi, &config);
+ if (ret < 0)
+ goto err_update_config;
+
+ spin_lock_irqsave(&video->dma_queue_lock, flags);
+ video->cur_frm = list_first_entry(&video->dma_queue,
+ struct sun6i_csi_buffer, list);
+ list_del(&video->cur_frm->list);
+ spin_unlock_irqrestore(&video->dma_queue_lock, flags);
+
+ ret = sun6i_csi_update_buf_addr(video->csi, video->cur_frm->dma_addr);
+ if (ret < 0)
+ goto err_update_addr;
+
+ ret = sun6i_csi_set_stream(video->csi, true);
+ if (ret < 0)
+ goto err_csi_stream;
+
+ return 0;
+
+err_csi_stream:
+err_update_addr:
+err_update_config:
+ sun6i_pipeline_set_stream(video, false);
+err_start_stream:
+ media_pipeline_stop(&video->vdev.entity);
+err_start_pipeline:
+ spin_lock_irqsave(&video->dma_queue_lock, flags);
+ list_for_each_entry(buf, &video->dma_queue, list)
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED);
+ INIT_LIST_HEAD(&video->dma_queue);
+ spin_unlock_irqrestore(&video->dma_queue_lock, flags);
+
+ return ret;
+}
+
+static void sun6i_video_stop_streaming(struct vb2_queue *vq)
+{
+ struct sun6i_video *video = vb2_get_drv_priv(vq);
+ unsigned long flags;
+ struct sun6i_csi_buffer *buf;
+
+ sun6i_pipeline_set_stream(video, false);
+
+ sun6i_csi_set_stream(video->csi, false);
+
+ media_pipeline_stop(&video->vdev.entity);
+
+ /* Release all active buffers */
+ spin_lock_irqsave(&video->dma_queue_lock, flags);
+ if (unlikely(video->cur_frm)) {
+ vb2_buffer_done(&video->cur_frm->vb.vb2_buf,
+ VB2_BUF_STATE_ERROR);
+ video->cur_frm = NULL;
+ }
+ list_for_each_entry(buf, &video->dma_queue, list)
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
+ INIT_LIST_HEAD(&video->dma_queue);
+ spin_unlock_irqrestore(&video->dma_queue_lock, flags);
+}
+
+static void sun6i_video_buffer_queue(struct vb2_buffer *vb)
+{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct sun6i_csi_buffer *buf =
+ container_of(vbuf, struct sun6i_csi_buffer, vb);
+ struct sun6i_video *video = vb2_get_drv_priv(vb->vb2_queue);
+ unsigned long flags;
+
+ spin_lock_irqsave(&video->dma_queue_lock, flags);
+ if (!video->cur_frm && list_empty(&video->dma_queue) &&
+ vb2_is_streaming(vb->vb2_queue)) {
+ video->cur_frm = buf;
+ sun6i_csi_update_buf_addr(video->csi, video->cur_frm->dma_addr);
+ sun6i_csi_set_stream(video->csi, 1);
+ } else
+ list_add_tail(&buf->list, &video->dma_queue);
+ spin_unlock_irqrestore(&video->dma_queue_lock, flags);
+}
+
+void sun6i_video_frame_done(struct sun6i_video *video)
+{
+ spin_lock(&video->dma_queue_lock);
+
+ if (video->cur_frm) {
+ struct vb2_v4l2_buffer *vbuf = &video->cur_frm->vb;
+ struct vb2_buffer *vb = &vbuf->vb2_buf;
+
+ vb->timestamp = ktime_get_ns();
+ vbuf->sequence = video->sequence++;
+ vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
+ video->cur_frm = NULL;
+ }
+
+ if (!list_empty(&video->dma_queue)
+ && vb2_is_streaming(&video->vb2_vidq)) {
+ video->cur_frm = list_first_entry(&video->dma_queue,
+ struct sun6i_csi_buffer, list);
+ list_del(&video->cur_frm->list);
+ sun6i_csi_update_buf_addr(video->csi, video->cur_frm->dma_addr);
+ } else
+ sun6i_csi_set_stream(video->csi, 0);
+
+ spin_unlock(&video->dma_queue_lock);
+}
+
+static struct vb2_ops sun6i_csi_vb2_ops = {
+ .queue_setup = sun6i_video_queue_setup,
+ .wait_prepare = vb2_ops_wait_prepare,
+ .wait_finish = vb2_ops_wait_finish,
+ .buf_prepare = sun6i_video_buffer_prepare,
+ .start_streaming = sun6i_video_start_streaming,
+ .stop_streaming = sun6i_video_stop_streaming,
+ .buf_queue = sun6i_video_buffer_queue,
+};
+
+static int vidioc_querycap(struct file *file, void *priv,
+ struct v4l2_capability *cap)
+{
+ struct sun6i_video *video = video_drvdata(file);
+
+ strlcpy(cap->driver, "sun6i-video", sizeof(cap->driver));
+ strlcpy(cap->card, video->vdev.name, sizeof(cap->card));
+ snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
+ video->csi->dev->of_node->name);
+
+ return 0;
+}
+
+static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_fmtdesc *f)
+{
+ struct sun6i_video *video = video_drvdata(file);
+ u32 index = f->index;
+
+ if (index >= video->num_formats)
+ return -EINVAL;
+
+ f->pixelformat = video->formats[index].fourcc;
+
+ return 0;
+}
+
+static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_format *fmt)
+{
+ struct sun6i_video *video = video_drvdata(file);
+
+ *fmt = video->fmt;
+
+ return 0;
+}
+
+static int sun6i_video_try_fmt(struct sun6i_video *video, struct v4l2_format *f,
+ struct sun6i_csi_format **current_fmt)
+{
+ struct sun6i_csi_format *csi_fmt;
+ struct v4l2_pix_format *pixfmt = &f->fmt.pix;
+ struct v4l2_subdev_format format;
+ struct v4l2_subdev *subdev;
+ u32 pad;
+ int ret;
+
+ subdev = sun6i_video_remote_subdev(video, &pad);
+ if (subdev == NULL)
+ return -ENXIO;
+
+ csi_fmt = find_format_by_fourcc(video, pixfmt->pixelformat);
+ if (csi_fmt == NULL) {
+ if (video->num_formats > 0) {
+ csi_fmt = &video->formats[0];
+ pixfmt->pixelformat = csi_fmt->fourcc;
+ } else
+ return -EINVAL;
+ }
+
+ format.pad = pad;
+ format.which = V4L2_SUBDEV_FORMAT_TRY;
+ v4l2_fill_mbus_format(&format.format, pixfmt, csi_fmt->mbus_code);
+ ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &format);
+ if (ret)
+ return ret;
+
+ v4l2_fill_pix_format(pixfmt, &format.format);
+
+ pixfmt->bytesperline = (pixfmt->width * csi_fmt->bpp) >> 3;
+ pixfmt->sizeimage = (pixfmt->width * csi_fmt->bpp * pixfmt->height) / 8;
+
+ if (current_fmt)
+ *current_fmt = csi_fmt;
+
+ return 0;
+}
+
+static int sun6i_video_set_fmt(struct sun6i_video *video, struct v4l2_format *f)
+{
+ struct v4l2_subdev_format format;
+ struct sun6i_csi_format *current_fmt;
+ struct v4l2_subdev *subdev;
+ u32 pad;
+ int ret;
+
+ subdev = sun6i_video_remote_subdev(video, &pad);
+ if (subdev == NULL)
+ return -ENXIO;
+
+ ret = sun6i_video_try_fmt(video, f, ¤t_fmt);
+ if (ret)
+ return ret;
+
+ format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+ v4l2_fill_mbus_format(&format.format, &f->fmt.pix,
+ current_fmt->mbus_code);
+ ret = v4l2_subdev_call(subdev, pad, set_fmt, NULL, &format);
+ if (ret < 0)
+ return ret;
+
+ video->fmt = *f;
+ video->current_fmt = current_fmt;
+
+ return 0;
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct sun6i_video *video = video_drvdata(file);
+
+ if (vb2_is_busy(&video->vb2_vidq))
+ return -EBUSY;
+
+ return sun6i_video_set_fmt(video, f);
+}
+
+static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct sun6i_video *video = video_drvdata(file);
+
+ return sun6i_video_try_fmt(video, f, NULL);
+}
+
+static int vidioc_enum_input(struct file *file, void *fh,
+ struct v4l2_input *inp)
+{
+ struct sun6i_video *video = video_drvdata(file);
+ struct v4l2_subdev *subdev;
+ u32 pad;
+ int ret;
+
+ if (inp->index != 0)
+ return -EINVAL;
+
+ subdev = sun6i_video_remote_subdev(video, &pad);
+ if (subdev == NULL)
+ return -ENXIO;
+
+ ret = v4l2_subdev_call(subdev, video, g_input_status, &inp->status);
+ if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
+ return ret;
+
+ inp->type = V4L2_INPUT_TYPE_CAMERA;
+
+ if (v4l2_subdev_has_op(subdev, pad, dv_timings_cap)) {
+ inp->capabilities = V4L2_IN_CAP_DV_TIMINGS;
+ inp->std = 0;
+ } else {
+ inp->capabilities = 0;
+ inp->std = 0;
+ }
+
+ strlcpy(inp->name, subdev->name, sizeof(inp->name));
+
+ return 0;
+}
+
+static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
+{
+ *i = 0;
+
+ return 0;
+}
+
+static int vidioc_s_input(struct file *file, void *fh, unsigned int i)
+{
+ if (i != 0)
+ return -EINVAL;
+
+ return 0;
+}
+
+static const struct v4l2_ioctl_ops sun6i_video_ioctl_ops = {
+ .vidioc_querycap = vidioc_querycap,
+ .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
+ .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
+ .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
+ .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
+
+ .vidioc_enum_input = vidioc_enum_input,
+ .vidioc_s_input = vidioc_s_input,
+ .vidioc_g_input = vidioc_g_input,
+
+ .vidioc_reqbufs = vb2_ioctl_reqbufs,
+ .vidioc_querybuf = vb2_ioctl_querybuf,
+ .vidioc_qbuf = vb2_ioctl_qbuf,
+ .vidioc_expbuf = vb2_ioctl_expbuf,
+ .vidioc_dqbuf = vb2_ioctl_dqbuf,
+ .vidioc_create_bufs = vb2_ioctl_create_bufs,
+ .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
+ .vidioc_streamon = vb2_ioctl_streamon,
+ .vidioc_streamoff = vb2_ioctl_streamoff,
+};
+
+/* -----------------------------------------------------------------------------
+ * V4L2 file operations
+ */
+static int sun6i_video_open(struct file *file)
+{
+ struct sun6i_video *video = video_drvdata(file);
+ int ret;
+
+ if (mutex_lock_interruptible(&video->lock))
+ return -ERESTARTSYS;
+
+ ret = v4l2_fh_open(file);
+ if (ret < 0)
+ goto unlock;
+
+ ret = v4l2_pipeline_pm_use(&video->vdev.entity, 1);
+ if (ret < 0)
+ goto fh_release;
+
+ if (!v4l2_fh_is_singular_file(file))
+ goto unlock;
+
+ ret = sun6i_csi_set_power(video->csi, true);
+ if (ret < 0)
+ goto fh_release;
+
+ mutex_unlock(&video->lock);
+ return 0;
+
+fh_release:
+ v4l2_fh_release(file);
+unlock:
+ mutex_unlock(&video->lock);
+ return ret;
+}
+
+static int sun6i_video_close(struct file *file)
+{
+ struct sun6i_video *video = video_drvdata(file);
+ bool last_fh;
+
+ mutex_lock(&video->lock);
+
+ last_fh = v4l2_fh_is_singular_file(file);
+
+ _vb2_fop_release(file, NULL);
+
+ v4l2_pipeline_pm_use(&video->vdev.entity, 0);
+
+ if (last_fh)
+ sun6i_csi_set_power(video->csi, false);
+
+ mutex_unlock(&video->lock);
+
+ return 0;
+}
+
+static const struct v4l2_file_operations sun6i_video_fops = {
+ .owner = THIS_MODULE,
+ .open = sun6i_video_open,
+ .release = sun6i_video_close,
+ .unlocked_ioctl = video_ioctl2,
+ .mmap = vb2_fop_mmap,
+ .poll = vb2_fop_poll
+};
+
+/* -----------------------------------------------------------------------------
+ * Media Operations
+ */
+static int sun6i_video_formats_init(struct sun6i_video *video)
+{
+ struct v4l2_subdev_mbus_code_enum mbus_code = { 0 };
+ struct sun6i_csi *csi = video->csi;
+ struct v4l2_format format;
+ struct v4l2_subdev *subdev;
+ u32 pad;
+ const u32 *pixformats;
+ int pixformat_count = 0;
+ u32 subdev_codes[32]; /* subdev format codes, 32 should be enough */
+ int codes_count = 0;
+ int num_fmts = 0;
+ int i, j;
+
+ subdev = sun6i_video_remote_subdev(video, &pad);
+ if (subdev == NULL)
+ return -ENXIO;
+
+ /* Get supported pixformats of CSI */
+ pixformat_count = sun6i_csi_get_supported_pixformats(csi, &pixformats);
+ if (pixformat_count <= 0)
+ return -ENXIO;
+
+ /* Get subdev formats codes */
+ mbus_code.pad = pad;
+ mbus_code.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+ while (!v4l2_subdev_call(subdev, pad, enum_mbus_code, NULL,
+ &mbus_code)) {
+ if (codes_count >= ARRAY_SIZE(subdev_codes)) {
+ dev_warn(video->csi->dev,
+ "subdev_codes array is full!\n");
+ break;
+ }
+ subdev_codes[codes_count] = mbus_code.code;
+ codes_count++;
+ mbus_code.index++;
+ }
+
+ if (!codes_count)
+ return -ENXIO;
+
+ /* Get supported formats count */
+ for (i = 0; i < codes_count; i++) {
+ for (j = 0; j < pixformat_count; j++) {
+ if (!sun6i_csi_is_format_support(csi, pixformats[j],
+ mbus_code.code)) {
+ continue;
+ }
+ num_fmts++;
+ }
+ }
+
+ if (!num_fmts)
+ return -ENXIO;
+
+ video->num_formats = num_fmts;
+ video->formats = devm_kcalloc(video->csi->dev, num_fmts,
+ sizeof(struct sun6i_csi_format), GFP_KERNEL);
+ if (!video->formats)
+ return -ENOMEM;
+
+ /* Get supported formats */
+ num_fmts = 0;
+ for (i = 0; i < codes_count; i++) {
+ for (j = 0; j < pixformat_count; j++) {
+ if (!sun6i_csi_is_format_support(csi, pixformats[j],
+ mbus_code.code)) {
+ continue;
+ }
+
+ video->formats[num_fmts].fourcc = pixformats[j];
+ video->formats[num_fmts].mbus_code =
+ mbus_code.code;
+ video->formats[num_fmts].bpp =
+ v4l2_pixformat_get_bpp(pixformats[j]);
+ num_fmts++;
+ }
+ }
+
+ /* setup default format */
+ format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ format.fmt.pix.width = 1280;
+ format.fmt.pix.height = 720;
+ format.fmt.pix.pixelformat = video->formats[0].fourcc;
+ sun6i_video_set_fmt(video, &format);
+
+ return 0;
+}
+
+static int sun6i_video_link_setup(struct media_entity *entity,
+ const struct media_pad *local,
+ const struct media_pad *remote, u32 flags)
+{
+ struct video_device *vdev = media_entity_to_video_device(entity);
+ struct sun6i_video *video = video_get_drvdata(vdev);
+
+ if (WARN_ON(video == NULL))
+ return 0;
+
+ return sun6i_video_formats_init(video);
+}
+
+static const struct media_entity_operations sun6i_video_media_ops = {
+ .link_setup = sun6i_video_link_setup,
+};
+
+int sun6i_video_init(struct sun6i_video *video, struct sun6i_csi *csi,
+ const char *name)
+{
+ struct video_device *vdev = &video->vdev;
+ struct vb2_queue *vidq = &video->vb2_vidq;
+ int ret;
+
+ video->csi = csi;
+
+ /* Initialize the media entity... */
+ video->pad.flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT;
+ vdev->entity.ops = &sun6i_video_media_ops;
+ ret = media_entity_pads_init(&vdev->entity, 1, &video->pad);
+ if (ret < 0)
+ return ret;
+
+ mutex_init(&video->lock);
+
+ INIT_LIST_HEAD(&video->dma_queue);
+ spin_lock_init(&video->dma_queue_lock);
+
+ video->cur_frm = NULL;
+ video->sequence = 0;
+ video->num_formats = 0;
+
+ /* Initialize videobuf2 queue */
+ vidq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ vidq->io_modes = VB2_MMAP | VB2_DMABUF;
+ vidq->drv_priv = video;
+ vidq->buf_struct_size = sizeof(struct sun6i_csi_buffer);
+ vidq->ops = &sun6i_csi_vb2_ops;
+ vidq->mem_ops = &vb2_dma_contig_memops;
+ vidq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+ vidq->lock = &video->lock;
+ vidq->min_buffers_needed = 1;
+ vidq->dev = csi->dev;
+
+ ret = vb2_queue_init(vidq);
+ if (ret) {
+ v4l2_err(&csi->v4l2_dev, "vb2_queue_init failed: %d\n", ret);
+ goto error;
+ }
+
+ /* Register video device */
+ strlcpy(vdev->name, name, sizeof(vdev->name));
+ vdev->release = video_device_release_empty;
+ vdev->fops = &sun6i_video_fops;
+ vdev->ioctl_ops = &sun6i_video_ioctl_ops;
+ vdev->vfl_type = VFL_TYPE_GRABBER;
+ vdev->vfl_dir = VFL_DIR_RX;
+ vdev->v4l2_dev = &csi->v4l2_dev;
+ vdev->queue = vidq;
+ vdev->lock = &video->lock;
+ vdev->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE;
+ video_set_drvdata(vdev, video);
+
+ ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
+ if (ret < 0) {
+ v4l2_err(&csi->v4l2_dev,
+ "video_register_device failed: %d\n", ret);
+ goto error;
+ }
+
+ return 0;
+
+error:
+ sun6i_video_cleanup(video);
+ return ret;
+}
+
+void sun6i_video_cleanup(struct sun6i_video *video)
+{
+ if (video_is_registered(&video->vdev))
+ video_unregister_device(&video->vdev);
+
+ media_entity_cleanup(&video->vdev.entity);
+}
diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_video.h b/drivers/media/platform/sunxi/sun6i-csi/sun6i_video.h
new file mode 100644
index 0000000..14eac6e
--- /dev/null
+++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_video.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2017 Yong Deng <yong.deng-+3dxTMOEIRNWk0Htik3J/w@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __SUN6I_VIDEO_H__
+#define __SUN6I_VIDEO_H__
+
+#include <media/v4l2-dev.h>
+#include <media/videobuf2-core.h>
+
+/*
+ * struct sun6i_csi_format - CSI media bus format information
+ * @fourcc: Fourcc code for this format
+ * @mbus_code: V4L2 media bus format code.
+ * @bpp: Bytes per pixel (when stored in memory)
+ */
+struct sun6i_csi_format {
+ u32 fourcc;
+ u32 mbus_code;
+ u8 bpp;
+};
+
+struct sun6i_csi;
+
+struct sun6i_video {
+ struct video_device vdev;
+ struct media_pad pad;
+ struct sun6i_csi *csi;
+
+ struct mutex lock;
+
+ struct vb2_queue vb2_vidq;
+ spinlock_t dma_queue_lock;
+ struct list_head dma_queue;
+
+ struct sun6i_csi_buffer *cur_frm;
+ unsigned int sequence;
+
+ struct sun6i_csi_format *formats;
+ unsigned int num_formats;
+ struct sun6i_csi_format *current_fmt;
+ struct v4l2_format fmt;
+};
+
+int sun6i_video_init(struct sun6i_video *video, struct sun6i_csi *csi,
+ const char *name);
+void sun6i_video_cleanup(struct sun6i_video *video);
+
+void sun6i_video_frame_done(struct sun6i_video *video);
+
+#endif /* __SUN6I_VIDEO_H__ */
--
1.8.3.1
^ permalink raw reply related
* [PATCH v3 2/3] dt-bindings: media: Add Allwinner V3s Camera Sensor Interface (CSI)
From: Yong Deng @ 2017-11-13 7:32 UTC (permalink / raw)
To: maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8
Cc: Yong Deng, Mauro Carvalho Chehab, Rob Herring, Mark Rutland,
Chen-Yu Tsai, David S. Miller, Greg Kroah-Hartman, Hans Verkuil,
Randy Dunlap, Benoit Parrot, Stanimir Varbanov, Arnd Bergmann,
Hugues Fruchet, Philipp Zabel, Benjamin Gaignard,
Ramesh Shanmugasundaram, Yannick Fertre, Sakari Ailus, Rick Chang,
linux-media-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
Add binding documentation for Allwinner V3s CSI.
Signed-off-by: Yong Deng <yong.deng-+3dxTMOEIRNWk0Htik3J/w@public.gmane.org>
---
.../devicetree/bindings/media/sun6i-csi.txt | 51 ++++++++++++++++++++++
1 file changed, 51 insertions(+)
create mode 100644 Documentation/devicetree/bindings/media/sun6i-csi.txt
diff --git a/Documentation/devicetree/bindings/media/sun6i-csi.txt b/Documentation/devicetree/bindings/media/sun6i-csi.txt
new file mode 100644
index 0000000..f3916a2
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/sun6i-csi.txt
@@ -0,0 +1,51 @@
+Allwinner V3s Camera Sensor Interface
+------------------------------
+
+Required properties:
+ - compatible: value must be "allwinner,sun8i-v3s-csi"
+ - reg: base address and size of the memory-mapped region.
+ - interrupts: interrupt associated to this IP
+ - clocks: phandles to the clocks feeding the CSI
+ * bus: the CSI interface clock
+ * mod: the CSI module clock
+ * ram: the CSI DRAM clock
+ - clock-names: the clock names mentioned above
+ - resets: phandles to the reset line driving the CSI
+
+- ports: A ports node with endpoint definitions as defined in
+ Documentation/devicetree/bindings/media/video-interfaces.txt.
+ Currently, the driver only support the parallel interface. So, a single port
+ node with one endpoint and parallel bus is supported.
+
+Example:
+
+ csi1: csi@01cb4000 {
+ compatible = "allwinner,sun8i-v3s-csi";
+ reg = <0x01cb4000 0x1000>;
+ interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_CSI>,
+ <&ccu CLK_CSI1_SCLK>,
+ <&ccu CLK_DRAM_CSI>;
+ clock-names = "bus", "mod", "ram";
+ resets = <&ccu RST_BUS_CSI>;
+
+ port {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /* Parallel bus endpoint */
+ csi1_ep: endpoint {
+ remote-endpoint = <&adv7611_ep>;
+ bus-width = <16>;
+ data-shift = <0>;
+
+ /* If hsync-active/vsync-active are missing,
+ embedded BT.656 sync is used */
+ hsync-active = <0>; /* Active low */
+ vsync-active = <0>; /* Active low */
+ data-active = <1>; /* Active high */
+ pclk-sample = <1>; /* Rising */
+ };
+ };
+ };
+
--
1.8.3.1
^ permalink raw reply related
* [PATCH v3 3/3] media: MAINTAINERS: add entries for Allwinner V3s CSI
From: Yong Deng @ 2017-11-13 7:37 UTC (permalink / raw)
To: maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8
Cc: Yong Deng, Mauro Carvalho Chehab, Rob Herring, Mark Rutland,
Chen-Yu Tsai, David S. Miller, Greg Kroah-Hartman, Hans Verkuil,
Randy Dunlap, Benoit Parrot, Stanimir Varbanov, Arnd Bergmann,
Hugues Fruchet, Philipp Zabel, Benjamin Gaignard,
Ramesh Shanmugasundaram, Yannick Fertre, Sakari Ailus, Rick Chang,
linux-media-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
Signed-off-by: Yong Deng <yong.deng-+3dxTMOEIRNWk0Htik3J/w@public.gmane.org>
---
MAINTAINERS | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index adbf693..1ba7782 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3744,6 +3744,14 @@ M: Jaya Kumar <jayakumar.alsa-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
S: Maintained
F: sound/pci/cs5535audio/
+CSI DRIVERS FOR ALLWINNER V3s
+M: Yong Deng <yong.deng-+3dxTMOEIRNWk0Htik3J/w@public.gmane.org>
+L: linux-media-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
+T: git git://linuxtv.org/media_tree.git
+S: Maintained
+F: drivers/media/platform/sun6i-csi/
+F: Documentation/devicetree/bindings/media/sun6i-csi.txt
+
CW1200 WLAN driver
M: Solomon Peachy <pizza-pCgMCH4qpMRg9hUCZPvPmw@public.gmane.org>
S: Maintained
--
1.8.3.1
^ permalink raw reply related
* Re: [PATCH v4 4/4] ARM64: dts: meson: drop "sana" clock from SAR ADC
From: Yixun Lan @ 2017-11-13 7:38 UTC (permalink / raw)
To: Martin Blumenstingl, Kevin Hilman
Cc: yixun.lan-LpR1jeaWuhtBDgjK7y7TUQ,
devicetree-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Mark Rutland,
Carlo Caione, Xingyu Chen,
linux-amlogic-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <CAFBinCAEgCzZQQN4V8bJMpkNJ9AJLDLWC2DSEkz7N7m60p=QDg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
Hi Kevin & others
I'd like to just re-send the patch [4/4] (while leave others[1-3/4]
unchanged), to have separated DT patch the for 32bit / 64bit platform.
is this ok for you?
On 11/12/17 09:33, Martin Blumenstingl wrote:
> Hi Yixun,
>
> On Tue, Nov 7, 2017 at 3:10 PM, Yixun Lan <yixun.lan-LpR1jeaWuhtBDgjK7y7TUQ@public.gmane.org> wrote:
>> From: Xingyu Chen <xingyu.chen-LpR1jeaWuhtBDgjK7y7TUQ@public.gmane.org>
>>
>> The SAR ADC modules doesn't require The "sana" clock.
>>
>> Singed-off-by: Xingyu Chen <xingyu.chen-LpR1jeaWuhtBDgjK7y7TUQ@public.gmane.org>
>> Signed-off-by: Yixun Lan <yixun.lan-LpR1jeaWuhtBDgjK7y7TUQ@public.gmane.org>
>> ---
>> arch/arm/boot/dts/meson8.dtsi | 5 ++---
>> arch/arm/boot/dts/meson8b.dtsi | 5 ++---
> these two should go into a separate patch (with "ARM: dts: ..."
> prefix) - the ARM maintainers want separate pull requests for the
> 32-bit and 64-bit .dts changes, so patches should also follow that
> schema
>
> with that fixed, you can add my ACK on both (32-bit and 64-bit) .dts patches:
> Acked-by: Martin Blumenstingl<martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
>
thanks, I will send separate patch for this, and I will add your 'Acked-by'
>> arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 3 +--
>> arch/arm64/boot/dts/amlogic/meson-gxl.dtsi | 3 +--
>> 4 files changed, 6 insertions(+), 10 deletions(-)
>>
>> diff --git a/arch/arm/boot/dts/meson8.dtsi b/arch/arm/boot/dts/meson8.dtsi
>> index b98d44fde6b6..f93d6cf6e094 100644
>> --- a/arch/arm/boot/dts/meson8.dtsi
>> +++ b/arch/arm/boot/dts/meson8.dtsi
>> @@ -289,9 +289,8 @@
>> &saradc {
>> compatible = "amlogic,meson8-saradc", "amlogic,meson-saradc";
>> clocks = <&clkc CLKID_XTAL>,
>> - <&clkc CLKID_SAR_ADC>,
>> - <&clkc CLKID_SANA>;
>> - clock-names = "clkin", "core", "sana";
>> + <&clkc CLKID_SAR_ADC>;
>> + clock-names = "clkin", "core";
>> };
>>
>> &spifc {
>> diff --git a/arch/arm/boot/dts/meson8b.dtsi b/arch/arm/boot/dts/meson8b.dtsi
>> index bc278da7df0d..4aa444284f0c 100644
>> --- a/arch/arm/boot/dts/meson8b.dtsi
>> +++ b/arch/arm/boot/dts/meson8b.dtsi
>> @@ -185,9 +185,8 @@
>> &saradc {
>> compatible = "amlogic,meson8b-saradc", "amlogic,meson-saradc";
>> clocks = <&clkc CLKID_XTAL>,
>> - <&clkc CLKID_SAR_ADC>,
>> - <&clkc CLKID_SANA>;
>> - clock-names = "clkin", "core", "sana";
>> + <&clkc CLKID_SAR_ADC>;
>> + clock-names = "clkin", "core";
>> };
>>
>> &uart_AO {
>> diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
>> index af834cdbba79..b77f2593cdc3 100644
>> --- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
>> +++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
>> @@ -686,10 +686,9 @@
>> compatible = "amlogic,meson-gxbb-saradc", "amlogic,meson-saradc";
>> clocks = <&xtal>,
>> <&clkc CLKID_SAR_ADC>,
>> - <&clkc CLKID_SANA>,
>> <&clkc CLKID_SAR_ADC_CLK>,
>> <&clkc CLKID_SAR_ADC_SEL>;
>> - clock-names = "clkin", "core", "sana", "adc_clk", "adc_sel";
>> + clock-names = "clkin", "core", "adc_clk", "adc_sel";
>> };
>>
>> &sd_emmc_a {
>> diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
>> index d8dd3298b15c..07805a3b4db0 100644
>> --- a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
>> +++ b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
>> @@ -628,10 +628,9 @@
>> compatible = "amlogic,meson-gxl-saradc", "amlogic,meson-saradc";
>> clocks = <&xtal>,
>> <&clkc CLKID_SAR_ADC>,
>> - <&clkc CLKID_SANA>,
>> <&clkc CLKID_SAR_ADC_CLK>,
>> <&clkc CLKID_SAR_ADC_SEL>;
>> - clock-names = "clkin", "core", "sana", "adc_clk", "adc_sel";
>> + clock-names = "clkin", "core", "adc_clk", "adc_sel";
>> };
>>
>> &sd_emmc_a {
>> --
>> 2.14.1
>>
>
> .
>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 0/3] Add R8A77970/Eagle PFC support
From: Simon Horman @ 2017-11-13 7:53 UTC (permalink / raw)
To: Sergei Shtylyov
Cc: Rob Herring, Catalin Marinas, Will Deacon,
linux-renesas-soc-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA, Magnus Damm, Mark Rutland,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <20171110200218.747996672-M4DtvfQ/ZS1MRgGoP+s0PdBPR1lH4CV8@public.gmane.org>
On Fri, Nov 10, 2017 at 11:02:18PM +0300, Sergei Shtylyov wrote:
> Hello!
>
> Here's the set of 3 patches against Simon Horman's 'renesas.git' repo's
> 'renesas-devel-20171110-v4.14-rc8' tag. We're adding the R8A77970 PFC node
> and then describing the pins for SCIF0 and EtherAVB devices declared earlier.
> These patches depend on the R8A77970 PFC suport in order to work properly.
>
> [1/3] arm64: dts: renesas: r8a77970: add PFC support
> [2/3] arm64: dts: renesas: eagle: add SCIF0 pins
> [3/3] arm64: dts: renesas: eagle: add EtherAVB pins
Hi Sergei,
I have marked these patches as deferred pending acceptance of the PFC
driver. Please repost or otherwise ping me once that dependency has been
accepted.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH] ARM: dts: imx6: Remove unneeded address-cells/size-cells
From: Uwe Kleine-König @ 2017-11-13 7:55 UTC (permalink / raw)
To: Christopher Spinrath
Cc: Fabio Estevam, Shawn Guo, Sascha Hauer, Mark Rutland,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Rob Herring,
Russell King,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
In-Reply-To: <62f3cb01-ff85-0fe0-2afa-0fe4732a7421-vA1bhqPz9FBZXbeN9DUtxg@public.gmane.org>
Hello,
On Sat, Nov 11, 2017 at 03:24:47PM +0100, Christopher Spinrath wrote:
> (I'm sorry if I've missed some recipients or broke the email thread but
> I got Fabio's email from the infradead archive.)
>
> On 11/10/2017 10:12 PM, festevam at gmail.com (Fabio Estevam) wrote:
> > From: Fabio Estevam <fabio.estevam at nxp.com>
> >
> > According to Documentation/devicetree/bindings/mtd/jedec,spi-nor.txt:
> >
> > "- #address-cells, #size-cells : Must be present if the device has
> > sub-nodes representing partitions."
> >
> > Remove the occurrences of #address-cells/size-cells where no sub-nodes
> > representing partitions are present.
>
> This results in a regression for those devices where U-Boot is supposed
> to inject the partition sub-nodes. For example, this is the case for
> cm-fx6 module based devices like the Utilite Pro.
sounds like an U-Boot bug that it inserts partition nodes, but doesn't
ensure matching #address-cells/size-cells are specified.
Best regards
Uwe
--
Pengutronix e.K. | Uwe Kleine-König |
Industrial Linux Solutions | http://www.pengutronix.de/ |
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH] ARM64: dts: meson-axg: add ethernet mac controller
From: Yixun Lan @ 2017-11-13 8:01 UTC (permalink / raw)
To: devicetree-u79uwXL29TY76Z2rM5mHXA, Kevin Hilman
Cc: Neil Armstrong, Jerome Brunet, Giuseppe Cavallaro,
Alexandre Torgue, Carlo Caione, Yixun Lan,
linux-amlogic-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
netdev-u79uwXL29TY76Z2rM5mHXA
Add DT info for the stmmac ethernet MAC which found in
the Amlogic's Meson-AXG SoC, also describe the ethernet
pinctrl & clock information here.
This is tested in the S400 dev board which use a RTL8211F PHY,
and the pins connect to the 'eth_rgmii_y_pins' group.
Signed-off-by: Yixun Lan <yixun.lan-LpR1jeaWuhtBDgjK7y7TUQ@public.gmane.org>
---
arch/arm64/boot/dts/amlogic/meson-axg-s400.dts | 7 ++++
arch/arm64/boot/dts/amlogic/meson-axg.dtsi | 53 ++++++++++++++++++++++++++
2 files changed, 60 insertions(+)
diff --git a/arch/arm64/boot/dts/amlogic/meson-axg-s400.dts b/arch/arm64/boot/dts/amlogic/meson-axg-s400.dts
index 9eb6aaee155d..7b39a9fe2b0f 100644
--- a/arch/arm64/boot/dts/amlogic/meson-axg-s400.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-axg-s400.dts
@@ -21,3 +21,10 @@
status = "okay";
};
+ðmac {
+ status = "okay";
+ phy-mode = "rgmii";
+
+ pinctrl-0 = <ð_rgmii_y_pins>;
+ pinctrl-names = "default";
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-axg.dtsi b/arch/arm64/boot/dts/amlogic/meson-axg.dtsi
index 65945c6c8b65..57faaa9d8013 100644
--- a/arch/arm64/boot/dts/amlogic/meson-axg.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-axg.dtsi
@@ -157,6 +157,19 @@
#address-cells = <0>;
};
+ ethmac: ethernet@ff3f0000 {
+ compatible = "amlogic,meson-axg-dwmac", "amlogic,meson-gxbb-dwmac", "snps,dwmac";
+ reg = <0x0 0xff3f0000 0x0 0x10000
+ 0x0 0xff634540 0x0 0x8>;
+ interrupts = <GIC_SPI 8 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "macirq";
+ status = "disabled";
+ clocks = <&clkc CLKID_ETH>,
+ <&clkc CLKID_FCLK_DIV2>,
+ <&clkc CLKID_MPLL2>;
+ clock-names = "stmmaceth", "clkin0", "clkin1";
+ };
+
hiubus: hiubus@ff63c000 {
compatible = "simple-bus";
reg = <0x0 0xff63c000 0x0 0x1c00>;
@@ -203,6 +216,46 @@
#gpio-cells = <2>;
gpio-ranges = <&pinctrl_periphs 0 0 86>;
};
+
+ eth_rgmii_x_pins: eth-x-rgmii {
+ mux {
+ groups = "eth_mdio_x",
+ "eth_mdc_x",
+ "eth_rgmii_rx_clk_x",
+ "eth_rx_dv_x",
+ "eth_rxd0_x",
+ "eth_rxd1_x",
+ "eth_rxd2_rgmii",
+ "eth_rxd3_rgmii",
+ "eth_rgmii_tx_clk",
+ "eth_txen_x",
+ "eth_txd0_x",
+ "eth_txd1_x",
+ "eth_txd2_rgmii",
+ "eth_txd3_rgmii";
+ function = "eth";
+ };
+ };
+
+ eth_rgmii_y_pins: eth-y-rgmii {
+ mux {
+ groups = "eth_mdio_y",
+ "eth_mdc_y",
+ "eth_rgmii_rx_clk_y",
+ "eth_rx_dv_y",
+ "eth_rxd0_y",
+ "eth_rxd1_y",
+ "eth_rxd2_rgmii",
+ "eth_rxd3_rgmii",
+ "eth_rgmii_tx_clk",
+ "eth_txen_y",
+ "eth_txd0_y",
+ "eth_txd1_y",
+ "eth_txd2_rgmii",
+ "eth_txd3_rgmii";
+ function = "eth";
+ };
+ };
};
};
--
2.14.1
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* Re: [PATCH v4 3/5] staging: Introduce NVIDIA Tegra video decoder driver
From: Dan Carpenter @ 2017-11-13 8:16 UTC (permalink / raw)
To: Vladimir Zapolskiy
Cc: devel, devicetree, Stephen Warren, Greg Kroah-Hartman,
linux-kernel, Rob Herring, Jonathan Hunter, Thierry Reding,
linux-tegra, Dmitry Osipenko, Mauro Carvalho Chehab, linux-media
In-Reply-To: <2c2910bc-40d4-b4ac-cdbe-b3c670a91f1b@mleia.com>
On Sat, Nov 11, 2017 at 04:06:52PM +0200, Vladimir Zapolskiy wrote:
> > + if (!wait_dma)
> > + return 0;
> > +
> > + err = readl_relaxed_poll_timeout(vde->bsev + INTR_STATUS, value,
> > + !(value & BSE_DMA_BUSY), 1, 100);
> > + if (err) {
> > + dev_err(dev, "BSEV DMA timeout\n");
> > + return err;
> > + }
> > +
> > + return 0;
>
> if (err)
> dev_err(dev, "BSEV DMA timeout\n");
>
> return err;
>
> is two lines shorter.
>
This is fine, but just watch out because getting clever with a last if
statement is a common anti-pattern. For example, you often see it where
people do success handling instead of failure handling. And it leads
to static checker bugs, and makes the code slightly more subtle.
> > + err = tegra_vde_attach_dmabuf(dev, source->aux_fd,
> > + source->aux_offset, csize,
> > + &frame->aux_dmabuf_attachment,
> > + &frame->aux_addr,
> > + &frame->aux_sgt,
> > + NULL, dma_dir);
> > + if (err)
> > + goto err_release_cr;
> > + }
> > +
> > + return 0;
>
> if (!err)
> return 0;
>
> and then remove a check above.
>
Argh!!!! Success handling. Always do failure handling, never success
handling.
The rest of your comments I agree with, though.
regards,
dan carpenter
^ permalink raw reply
* Re: [linux-sunxi] Re: [PATCH] ARM: sun8i: h2+: add support for Banana Pi M2 Zero board
From: Maxime Ripard @ 2017-11-13 8:20 UTC (permalink / raw)
To: Icenowy Zheng
Cc: Chen-Yu Tsai, devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw
In-Reply-To: <b548b74e04b29ec8c3cddb7cc42f2b4e-h8G6r0blFSE@public.gmane.org>
[-- Attachment #1: Type: text/plain, Size: 1821 bytes --]
Hi,
On Fri, Nov 03, 2017 at 07:53:17AM +0800, Icenowy Zheng wrote:
> 在 2017-11-02 23:50,Maxime Ripard 写道:
> > On Thu, Nov 02, 2017 at 05:07:30PM +0800, Icenowy Zheng wrote:
> > > > > +&mmc0 {
> > > > > + pinctrl-names = "default";
> > > > > + pinctrl-0 = <&mmc0_pins_a>;
> > > > > + vmmc-supply = <®_vcc3v3>;
> > > > > + bus-width = <4>;
> > > > > + /*
> > > > > + * In different revisions the board have different card detect
> > > > > + * configuration.
> > > > > + */
> > > >
> > > > Which ones?
> > >
> > > In the sample batch (1.2V fixed voltage) the card detect is normal
> > > (PF6 low as inserted), however in the final batch (1.1V/1.3V
> > > switchable) it's inverted at PF6 (high as inserted).
> >
> > Then just use the final version's.
> >
> > > > > +&usbphy {
> > > > > + usb0_id_det-gpios = <&r_pio 0 6 GPIO_ACTIVE_HIGH>; /* PL6 */
> > > > > + /* USB OTG VBUS is directly connected to 5V without any regulators
> > > > > */
> > > >
> > > > So it cannot operate in OTG, but it's host only?
> > >
> > > It can operate in OTG -- you can power the board via the OTG port,
> > > as the VBUS is not gated from 5V at all, so 5V power at VBUS will
> > > power up the board. Yes, it's a bit unsafe, but the board designer
> > > did it.
> >
> > What will provide the 5v in the first place then if a USB device is
> > connected to the micro-USB connector?
>
> There're two micro-USB connectors, one is power-only and another is
> OTG. The Vbus of these two connectors are connected together, so
> the external USB device will be powered just by the power input
> from the power-only USB port.
Can you put that in the comment?
Thanks.
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* Re: [PATCH v3 3/3] media: MAINTAINERS: add entries for Allwinner V3s CSI
From: Yong @ 2017-11-13 8:30 UTC (permalink / raw)
To: yong.deng-+3dxTMOEIRNWk0Htik3J/w
Cc: maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
Mauro Carvalho Chehab, Rob Herring, Mark Rutland, Chen-Yu Tsai,
David S. Miller, Greg Kroah-Hartman, Hans Verkuil, Randy Dunlap,
Benoit Parrot, Stanimir Varbanov, Arnd Bergmann, Hugues Fruchet,
Philipp Zabel, Benjamin Gaignard, Ramesh Shanmugasundaram,
Yannick Fertre, Sakari Ailus, Rick Chang,
linux-media-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, linux-kern
In-Reply-To: <1510558631-45511-1-git-send-email-yong.deng-+3dxTMOEIRNWk0Htik3J/w@public.gmane.org>
On Mon, 13 Nov 2017 15:37:11 +0800
Yong Deng <yong.deng-+3dxTMOEIRNWk0Htik3J/w@public.gmane.org> wrote:
> Signed-off-by: Yong Deng <yong.deng-+3dxTMOEIRNWk0Htik3J/w@public.gmane.org>
> ---
> MAINTAINERS | 8 ++++++++
> 1 file changed, 8 insertions(+)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index adbf693..1ba7782 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -3744,6 +3744,14 @@ M: Jaya Kumar <jayakumar.alsa-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> S: Maintained
> F: sound/pci/cs5535audio/
>
> +CSI DRIVERS FOR ALLWINNER V3s
> +M: Yong Deng <yong.deng-+3dxTMOEIRNWk0Htik3J/w@public.gmane.org>
> +L: linux-media-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> +T: git git://linuxtv.org/media_tree.git
> +S: Maintained
> +F: drivers/media/platform/sun6i-csi/
Sorry, the path has been changed to drivers/media/platform/sunxi/sun6i-csi/.
I will fix it.
> +F: Documentation/devicetree/bindings/media/sun6i-csi.txt
> +
> CW1200 WLAN driver
> M: Solomon Peachy <pizza-pCgMCH4qpMRg9hUCZPvPmw@public.gmane.org>
> S: Maintained
> --
> 1.8.3.1
>
> --
> You received this message because you are subscribed to the Google Groups "linux-sunxi" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
> For more options, visit https://groups.google.com/d/optout.
Thanks,
Yong
^ permalink raw reply
* Re: [PATCH RESEND 1/4] crypto: caam: add caam-dma node to SEC4.0 device tree binding
From: Horia Geantă @ 2017-11-13 8:32 UTC (permalink / raw)
To: Kim Phillips, Radu Andrei Alexe
Cc: Vinod Koul, Herbert Xu, David S. Miller, Dan Douglass, Shawn Guo,
dmaengine@vger.kernel.org, linux-crypto@vger.kernel.org,
devicetree@vger.kernel.org
In-Reply-To: <20171110104430.28b2f56f910b7514d778c4b2@arm.com>
On 11/10/2017 6:44 PM, Kim Phillips wrote:
> On Fri, 10 Nov 2017 08:02:01 +0000
> Radu Andrei Alexe <radu.alexe@nxp.com> wrote:
[snip]>> 2. I wanted this driver to be tracked by the dma engine team.
They have
>> the right expertise to provide adequate feedback. If all the code was in
>> the crypto directory they wouldn't know about this driver or any
>> subsequent changes to it.
>
> dma subsystem bits could still be put in the dma area if deemed
> necessary but I don't think it is: I see
> drivers/crypto/ccp/ccp-dmaengine.c calls dma_async_device_register for
> example.
>
Please see previous discussion with Vinod:
https://www.mail-archive.com/linux-crypto@vger.kernel.org/msg21468.html
> What is the rationale for using the crypto h/w as a dma engine anyway?
SoCs that don't have a system DMA, for e.g. LS1012A.
Horia
^ permalink raw reply
* Re: [PATCH v7 25/25] rcar-vin: enable support for r8a7796
From: Geert Uytterhoeven @ 2017-11-13 8:42 UTC (permalink / raw)
To: Niklas Söderlund
Cc: Laurent Pinchart, Hans Verkuil, Linux Media Mailing List,
Linux-Renesas, Fukawa, Kieran Bingham, Mark Rutland, Rob Herring,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <20171111003835.4909-26-niklas.soderlund+renesas-1zkq55x86MTxsAP9Fp7wbw@public.gmane.org>
CC DT
On Sat, Nov 11, 2017 at 1:38 AM, Niklas Söderlund
<niklas.soderlund+renesas-1zkq55x86MTxsAP9Fp7wbw@public.gmane.org> wrote:
> Add the SoC specific information for Renesas r8a7796.
>
> Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
> Reviewed-by: Hans Verkuil <hans.verkuil-FYB4Gu1CFyUAvxtiuMwx3w@public.gmane.org>
> ---
> .../devicetree/bindings/media/rcar_vin.txt | 1 +
> drivers/media/platform/rcar-vin/rcar-core.c | 64 ++++++++++++++++++++++
> 2 files changed, 65 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/media/rcar_vin.txt b/Documentation/devicetree/bindings/media/rcar_vin.txt
> index df1abd0fb20386f8..ddf249c2276600d2 100644
> --- a/Documentation/devicetree/bindings/media/rcar_vin.txt
> +++ b/Documentation/devicetree/bindings/media/rcar_vin.txt
> @@ -10,6 +10,7 @@ Depending on the instance the VIN input is connected to external SoC pins, or
> on Gen3 to a CSI-2 receiver.
>
> - compatible: Must be one or more of the following
> + - "renesas,vin-r8a7796" for the R8A7796 device
> - "renesas,vin-r8a7795" for the R8A7795 device
> - "renesas,vin-r8a7794" for the R8A7794 device
> - "renesas,vin-r8a7793" for the R8A7793 device
> diff --git a/drivers/media/platform/rcar-vin/rcar-core.c b/drivers/media/platform/rcar-vin/rcar-core.c
> index b22f6596700d2479..e329de4ce0172e8d 100644
> --- a/drivers/media/platform/rcar-vin/rcar-core.c
> +++ b/drivers/media/platform/rcar-vin/rcar-core.c
> @@ -1084,6 +1084,66 @@ static const struct rvin_info rcar_info_r8a7795es1 = {
> },
> };
>
> +static const struct rvin_info rcar_info_r8a7796 = {
> + .chip = RCAR_GEN3,
> + .use_mc = true,
> + .max_width = 4096,
> + .max_height = 4096,
> +
> + .num_chsels = 5,
> + .chsels = {
> + {
> + { .csi = RVIN_CSI40, .chan = 0 },
> + { .csi = RVIN_CSI20, .chan = 0 },
> + { .csi = RVIN_NC, .chan = 0 },
> + { .csi = RVIN_CSI40, .chan = 0 },
> + { .csi = RVIN_CSI20, .chan = 0 },
> + }, {
> + { .csi = RVIN_CSI20, .chan = 0 },
> + { .csi = RVIN_NC, .chan = 0 },
> + { .csi = RVIN_CSI40, .chan = 0 },
> + { .csi = RVIN_CSI40, .chan = 1 },
> + { .csi = RVIN_CSI20, .chan = 1 },
> + }, {
> + { .csi = RVIN_NC, .chan = 0 },
> + { .csi = RVIN_CSI40, .chan = 0 },
> + { .csi = RVIN_CSI20, .chan = 0 },
> + { .csi = RVIN_CSI40, .chan = 2 },
> + { .csi = RVIN_CSI20, .chan = 2 },
> + }, {
> + { .csi = RVIN_CSI40, .chan = 1 },
> + { .csi = RVIN_CSI20, .chan = 1 },
> + { .csi = RVIN_NC, .chan = 1 },
> + { .csi = RVIN_CSI40, .chan = 3 },
> + { .csi = RVIN_CSI20, .chan = 3 },
> + }, {
> + { .csi = RVIN_CSI40, .chan = 0 },
> + { .csi = RVIN_CSI20, .chan = 0 },
> + { .csi = RVIN_NC, .chan = 0 },
> + { .csi = RVIN_CSI40, .chan = 0 },
> + { .csi = RVIN_CSI20, .chan = 0 },
> + }, {
> + { .csi = RVIN_CSI20, .chan = 0 },
> + { .csi = RVIN_NC, .chan = 0 },
> + { .csi = RVIN_CSI40, .chan = 0 },
> + { .csi = RVIN_CSI40, .chan = 1 },
> + { .csi = RVIN_CSI20, .chan = 1 },
> + }, {
> + { .csi = RVIN_NC, .chan = 0 },
> + { .csi = RVIN_CSI40, .chan = 0 },
> + { .csi = RVIN_CSI20, .chan = 0 },
> + { .csi = RVIN_CSI40, .chan = 2 },
> + { .csi = RVIN_CSI20, .chan = 2 },
> + }, {
> + { .csi = RVIN_CSI40, .chan = 1 },
> + { .csi = RVIN_CSI20, .chan = 1 },
> + { .csi = RVIN_NC, .chan = 1 },
> + { .csi = RVIN_CSI40, .chan = 3 },
> + { .csi = RVIN_CSI20, .chan = 3 },
> + },
> + },
> +};
> +
> static const struct of_device_id rvin_of_id_table[] = {
> {
> .compatible = "renesas,vin-r8a7778",
> @@ -1117,6 +1177,10 @@ static const struct of_device_id rvin_of_id_table[] = {
> .compatible = "renesas,vin-r8a7795",
> .data = &rcar_info_r8a7795,
> },
> + {
> + .compatible = "renesas,vin-r8a7796",
> + .data = &rcar_info_r8a7796,
> + },
> { },
> };
> MODULE_DEVICE_TABLE(of, rvin_of_id_table);
> --
> 2.15.0
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH] ARM: dts: sunxi: Add codec for A13 Olinuxino
From: Maxime Ripard @ 2017-11-13 8:45 UTC (permalink / raw)
To: Emmanuel Vadot
Cc: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
linux-I+IVW8TIWO2tmTQ+vhA3Yw, wens-jdAy2FN1RRM,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20171106205139.82751-1-manu-h+KGxgPPiopAfugRpC6u6w@public.gmane.org>
[-- Attachment #1: Type: text/plain, Size: 373 bytes --]
On Mon, Nov 06, 2017 at 09:51:39PM +0100, Emmanuel Vadot wrote:
> The A13 Olinuxino have an headphone jack and audio is supported
> so enable it.
>
> Signed-off-by: Emmanuel Vadot <manu-h+KGxgPPiopAfugRpC6u6w@public.gmane.org>
Queued for 4.16, thanks!
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* Re: [PATCH 1/3] Input: twl4030-vibra: fix sibling-node lookup
From: Lee Jones @ 2017-11-13 9:11 UTC (permalink / raw)
To: Johan Hovold
Cc: Dmitry Torokhov, linux-input, linux-kernel, stable,
Peter Ujfalusi, Marek Belisko, Rob Herring, devicetree
In-Reply-To: <20171112121235.GO11226@localhost>
On Sun, 12 Nov 2017, Johan Hovold wrote:
> [ +CC: Lee, Rob and device-tree list ]
>
> On Sat, Nov 11, 2017 at 09:50:59AM -0800, Dmitry Torokhov wrote:
> > On Sat, Nov 11, 2017 at 04:43:37PM +0100, Johan Hovold wrote:
> > > A helper purported to look up a child node based on its name was using
> > > the wrong of-helper and ended up prematurely freeing the parent of-node
> > > while searching the whole device tree depth-first starting at the parent
> > > node.
> >
> > Ugh, this all is pretty ugly business. Can we teach MFD to allow
> > specifying firmware node to be attached to the platform devices it
> > creates in mfd_add_device() so that the leaf drivers simply call
> > device_property_read_XXX() on their own device and not be bothered with
> > weird OF refcount issues or what node they need to locate and parse?
If a child compatible is provided, we already set the child's
of_node. It's then up to the driver (set) author(s) to use it in the
correct manner.
> Yeah, that may have helped. You can actually specify a compatible string
> in struct mfd_cell today which does make mfd_add_device() associate a
> matching child node.
>
> Some best practice regarding how to deal with MFD and device tree would
> be good to determine and document too. For example, when should
> of_platform_populate() be used in favour of mfd_add_device()?
When the device supports DT and its entire hierarchical layout, along
with all of its attributes can be expressed in DT.
> And how best to deal with sibling nodes, which is part of the problem
> here (I think the mfd should have provided a flag rather than having
> subdrivers deal with sibling nodes, for example).
I disagree. The only properties the MFD (parent) driver is interested
in is ones which are shared across multiple child devices.
*Everything* which pertains to only a single child device should be
handled by its accompanying driver.
> That said, driver authors using the wrong of-helper could possibly have
> been avoided by amending the kernel docs (I'll do that as a follow up),
> but once these incorrect usages get in, only review can prevent them
> from being reproduced through copy-paste coding.
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
^ permalink raw reply
* Re: [PATCH] ARM: dts: sun8i: add support for Orange Pi R1
From: Maxime Ripard @ 2017-11-13 9:22 UTC (permalink / raw)
To: Icenowy Zheng
Cc: Chen-Yu Tsai, devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw
In-Reply-To: <20171112124129.15844-1-icenowy-h8G6r0blFSE@public.gmane.org>
[-- Attachment #1: Type: text/plain, Size: 493 bytes --]
On Sun, Nov 12, 2017 at 08:41:29PM +0800, Icenowy Zheng wrote:
> Orange Pi R1 is a board design based on Orange Pi Zero, with XR819 Wi-Fi
> chip replaced by RTL8189ETV Wi-Fi module and the USB Type-A jack
> replaced by an onboard USB RTL8152B USB-Ethernet adapter.
>
> Add support for it.
>
> Signed-off-by: Icenowy Zheng <icenowy-h8G6r0blFSE@public.gmane.org>
Queued for 416, thanks!
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
^ permalink raw reply
* Re: [PATCH 2/2] arm64: dts: orange-pi-zero-plus2: enable AP6212a WiFi/BT combo
From: Maxime Ripard @ 2017-11-13 9:25 UTC (permalink / raw)
To: Sergey Matyukevich
Cc: Chen-Yu Tsai, Rob Herring, Mark Rutland,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Jagan Teki
In-Reply-To: <20171103195855.15283-3-geomatsi-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
[-- Attachment #1: Type: text/plain, Size: 556 bytes --]
On Fri, Nov 03, 2017 at 10:58:55PM +0300, Sergey Matyukevich wrote:
> Enable AP6212a WiFi/BT combo chip on orange-pi-zero-plus2 board:
> - WiFi SDIO interface is connected to MMC1
> - WiFi REG_ON pin connected to gpio PA9: attach to mmc-pwrseq
> - WiFi HOST_WAKE pin connected to gpio PL7
> - BT is connected to UART1
>
> Signed-off-by: Sergey Matyukevich <geomatsi-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Queued for 4.16, thanks!
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* Re: [PATCH 1/3] Input: twl4030-vibra: fix sibling-node lookup
From: Johan Hovold @ 2017-11-13 9:35 UTC (permalink / raw)
To: Lee Jones
Cc: Johan Hovold, Dmitry Torokhov, linux-input, linux-kernel, stable,
Peter Ujfalusi, Marek Belisko, Rob Herring, devicetree
In-Reply-To: <20171113091144.5oz77shbu4oupoy7@dell>
On Mon, Nov 13, 2017 at 09:11:44AM +0000, Lee Jones wrote:
> On Sun, 12 Nov 2017, Johan Hovold wrote:
>
> > [ +CC: Lee, Rob and device-tree list ]
> >
> > On Sat, Nov 11, 2017 at 09:50:59AM -0800, Dmitry Torokhov wrote:
> > > On Sat, Nov 11, 2017 at 04:43:37PM +0100, Johan Hovold wrote:
> > > > A helper purported to look up a child node based on its name was using
> > > > the wrong of-helper and ended up prematurely freeing the parent of-node
> > > > while searching the whole device tree depth-first starting at the parent
> > > > node.
> > >
> > > Ugh, this all is pretty ugly business. Can we teach MFD to allow
> > > specifying firmware node to be attached to the platform devices it
> > > creates in mfd_add_device() so that the leaf drivers simply call
> > > device_property_read_XXX() on their own device and not be bothered with
> > > weird OF refcount issues or what node they need to locate and parse?
>
> If a child compatible is provided, we already set the child's
> of_node. It's then up to the driver (set) author(s) to use it in the
> correct manner.
>
> > Yeah, that may have helped. You can actually specify a compatible string
> > in struct mfd_cell today which does make mfd_add_device() associate a
> > matching child node.
> >
> > Some best practice regarding how to deal with MFD and device tree would
> > be good to determine and document too. For example, when should
> > of_platform_populate() be used in favour of mfd_add_device()?
>
> When the device supports DT and its entire hierarchical layout, along
> with all of its attributes can be expressed in DT.
Ok, a follow up: When there are different variants of an MFD and that
affects the child drivers, then that should be expressed in in the child
node compatibles rather than having the child match on the parent node?
I'm asking because this came up recently during review and their seems
to be no precedent for matching on the parent compatible in child
drivers:
https://lkml.kernel.org/r/20171105154725.GA11226@localhost
> > And how best to deal with sibling nodes, which is part of the problem
> > here (I think the mfd should have provided a flag rather than having
> > subdrivers deal with sibling nodes, for example).
>
> I disagree. The only properties the MFD (parent) driver is interested
> in is ones which are shared across multiple child devices.
> *Everything* which pertains to only a single child device should be
> handled by its accompanying driver.
Even if that means leaking details of one child driver into a sibling?
Isn't it then cleaner to use the parent MFD to coordinate between the
cells, just as we do for IO?
In this case a child driver looked up a sibling node based on name, but
that doesn't mean the node is active, that there's a driver bound, or
that the sibling node has some other random property for example. The
parent could be used for such coordination, if only to pass information
from one sibling to another.
Thanks,
Johan
^ permalink raw reply
* Re: [PATCH RESEND 1/4] crypto: caam: add caam-dma node to SEC4.0 device tree binding
From: Radu Andrei Alexe @ 2017-11-13 9:44 UTC (permalink / raw)
To: Kim Phillips
Cc: Horia Geantă, Vinod Koul, Herbert Xu, David S. Miller,
Dan Douglass, Shawn Guo, dmaengine@vger.kernel.org,
linux-crypto@vger.kernel.org, devicetree@vger.kernel.org
In-Reply-To: <20171110104430.28b2f56f910b7514d778c4b2@arm.com>
On 11/10/2017 6:44 PM, Kim Phillips wrote:
> On Fri, 10 Nov 2017 08:02:01 +0000
> Radu Andrei Alexe <radu.alexe@nxp.com> wrote:
>
>> On 11/9/2017 6:34 PM, Kim Phillips wrote:
>>> On Thu, 9 Nov 2017 11:54:13 +0000
>>> Radu Andrei Alexe <radu.alexe@nxp.com> wrote:
>>>> The next patch version will create the platform device dynamically at
>>>> run time.
>>>
>>> Why create a new device when that h/w already has one?
>>>
>>> Why doesn't the existing crypto driver register dma capabilities with
>>> the dma driver subsystem?
>>>
>> I can think of two reasons:
>>
>> 1. The code that this driver introduces has nothing to do with crypto
>> and everything to do with dma.
>
> I would think that at least a crypto "null" algorithm implementation
> would share code.
>
>> Placing the code in the same directory as
>> the caam subsystem would only create confusion for the reader of an
>> already complex driver.
>
> this different directory argument seems to be identical to your 2 below:
>
>> 2. I wanted this driver to be tracked by the dma engine team. They have
>> the right expertise to provide adequate feedback. If all the code was in
>> the crypto directory they wouldn't know about this driver or any
>> subsequent changes to it.
>
> dma subsystem bits could still be put in the dma area if deemed
> necessary but I don't think it is: I see
> drivers/crypto/ccp/ccp-dmaengine.c calls dma_async_device_register for
> example.
>
> I also don't see how that complicates things much further.
>
So who made their review? The guys from crypto?
If someone wants to enable only the DMA functionality of the CCP and not
the crypto part how do they do it? Look for it in the crypto submenu?
> What is the rationale for using the crypto h/w as a dma engine anyway?
> Are there supporting performance figures?
We have a platform that doesn't have a dedicated DMA controller but has
the CAAM hardware block that can perform dma transfers. We have a
use-case where we need to issue large transfers (hundred of MBs)
asynchronously, without using the core.
>
> Kim
>
BR,
Radu
^ permalink raw reply
* [PATCH] arm: dts: ls1021a: add reboot node to .dtsi
From: Rasmus Villemoes @ 2017-11-13 9:56 UTC (permalink / raw)
To: Rob Herring, Mark Rutland, Russell King
Cc: Rasmus Villemoes, devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
The LS1021A can be reset via the dcfg regmap in the same way as the
arm64 layerscape SoCs, so add the corresponding DT node.
Signed-off-by: Rasmus Villemoes <rasmus.villemoes-rjjw5hvvQKZaa/9Udqfwiw@public.gmane.org>
---
arch/arm/boot/dts/ls1021a.dtsi | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/arch/arm/boot/dts/ls1021a.dtsi b/arch/arm/boot/dts/ls1021a.dtsi
index 9319e1f..3ff2b8a 100644
--- a/arch/arm/boot/dts/ls1021a.dtsi
+++ b/arch/arm/boot/dts/ls1021a.dtsi
@@ -108,6 +108,13 @@
<GIC_SPI 139 IRQ_TYPE_LEVEL_HIGH>;
};
+ reboot {
+ compatible = "syscon-reboot";
+ regmap = <&dcfg>;
+ offset = <0xb0>;
+ mask = <0x02>;
+ };
+
soc {
compatible = "simple-bus";
#address-cells = <2>;
--
2.7.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* Re: split devicetree repository to be rebased/rewritten after v4.14-rcFINAL
From: Ian Campbell @ 2017-11-13 10:19 UTC (permalink / raw)
To: devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1506970413.4619.53.camel-KcIKpvwj1kUDXYZnReoRVg@public.gmane.org>
This has now been done.
Ian,
On Mon, 2017-10-02 at 19:53 +0100, Ian Campbell wrote:
> TL;DR: The tree[DT-R] at
>
> https://git.kernel.org/pub/scm/linux/kernel/git/devicetree/devicetree-rebasing.git/
>
> will be force pushed when v4.14 is released. This means a complete new
> history and tags for this tree. The original tree will remain
> available at [V1] but will not receive updates after v4.14-rcFINAL.
>
> I'm not sure how widely used this tree is but I have made some changes
> to the scripting which improves things in various ways:
>
> - The main change is that uninteresting merges (those which don't
> involve any files present in the output) are now removed, resulting
> in a _much_ cleaner history.
>
> - I've taken the chance to fix the dates on the vX.Y-dts tags so they
> reflect the date of the original vX.Y tag from Linus rather than
> whenever the conversion happened. Likewise the underlying merge
> commits now take their dates from the commit which Linus tagged.
>
> - I've also now upstreamed my changes to git filter-branch, which
> have been merged into git.git#master post v2.14.2. For now I am
> running v2.14.0 with the patches I sent upstream, but will switch
> to a real release with those changes ASAP. The switch to mainline
> git filter-branch has resulted in some irrelevant secondary roots
> (such as the one from the btrfs merge) being omitted, as they
> should have been all along. It's also nice to be using upstream!
>
> - Lastly I've improved the conversion scripting in various ways (unlike
> the others these do not change the output, but it is ~10-13x faster now
> for example).
>
> As above the original tree will remain available at [V1] but will not
> receive updates after v4.14-rcFINAL. The conversion state repo for
> this tree will remain at [STATE-V1].
>
> The new tree and its conversion state will be mirrored respectively at
> [V2] and [STATE-V2]. These trees are already active if you want a
> glimpse into the future. It's also not entirely too late to point out
> issues with the new tree as there is still a chance to rewrite from
> scratch (which takes around 3 days) before v4.14.
>
> The spurious/empty/irrelevant merges have bugged me from day 1 of this
> tree so I am glad to have had a chance to fix them. I'm not aware of
> any other reason why the tree would need rebasing again, although for
> now I am going to reserve the right to do so.
>
> Cheers,
> Ian.
>
> [DT-R] https://git.kernel.org/pub/scm/linux/kernel/git/devicetree/devicetree-rebasing.git/
> [V1] https://github.com/ijc/devicetree-rebasing-v1
> [V2] https://github.com/ijc/devicetree-rebasing-v2
> [STATE-V1] https://github.com/ijc/devicetree-conversion-state-v1
> [STATE-V2] https://github.com/ijc/devicetree-conversion-state-v2
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 1/3] Input: twl4030-vibra: fix sibling-node lookup
From: Lee Jones @ 2017-11-13 10:20 UTC (permalink / raw)
To: Johan Hovold
Cc: Dmitry Torokhov, linux-input, linux-kernel, stable,
Peter Ujfalusi, Marek Belisko, Rob Herring, devicetree
In-Reply-To: <20171113093544.GR11226@localhost>
On Mon, 13 Nov 2017, Johan Hovold wrote:
> On Mon, Nov 13, 2017 at 09:11:44AM +0000, Lee Jones wrote:
> > On Sun, 12 Nov 2017, Johan Hovold wrote:
> >
> > > [ +CC: Lee, Rob and device-tree list ]
> > >
> > > On Sat, Nov 11, 2017 at 09:50:59AM -0800, Dmitry Torokhov wrote:
> > > > On Sat, Nov 11, 2017 at 04:43:37PM +0100, Johan Hovold wrote:
> > > > > A helper purported to look up a child node based on its name was using
> > > > > the wrong of-helper and ended up prematurely freeing the parent of-node
> > > > > while searching the whole device tree depth-first starting at the parent
> > > > > node.
> > > >
> > > > Ugh, this all is pretty ugly business. Can we teach MFD to allow
> > > > specifying firmware node to be attached to the platform devices it
> > > > creates in mfd_add_device() so that the leaf drivers simply call
> > > > device_property_read_XXX() on their own device and not be bothered with
> > > > weird OF refcount issues or what node they need to locate and parse?
> >
> > If a child compatible is provided, we already set the child's
> > of_node. It's then up to the driver (set) author(s) to use it in the
> > correct manner.
> >
> > > Yeah, that may have helped. You can actually specify a compatible string
> > > in struct mfd_cell today which does make mfd_add_device() associate a
> > > matching child node.
> > >
> > > Some best practice regarding how to deal with MFD and device tree would
> > > be good to determine and document too. For example, when should
> > > of_platform_populate() be used in favour of mfd_add_device()?
> >
> > When the device supports DT and its entire hierarchical layout, along
> > with all of its attributes can be expressed in DT.
>
> Ok, a follow up: When there are different variants of an MFD and that
> affects the child drivers, then that should be expressed in in the child
> node compatibles rather than having the child match on the parent node?
>
> I'm asking because this came up recently during review and their seems
> to be no precedent for matching on the parent compatible in child
> drivers:
>
> https://lkml.kernel.org/r/20171105154725.GA11226@localhost
Accessing the parent's of_device_id .data directly doesn't sit well
with me. The parent driver should pass this type of configuration
though pdata IMHO.
> > > And how best to deal with sibling nodes, which is part of the problem
> > > here (I think the mfd should have provided a flag rather than having
> > > subdrivers deal with sibling nodes, for example).
> >
> > I disagree. The only properties the MFD (parent) driver is interested
> > in is ones which are shared across multiple child devices.
> > *Everything* which pertains to only a single child device should be
> > handled by its accompanying driver.
>
> Even if that means leaking details of one child driver into a sibling?
Not sure what you mean here. Could you please elaborate or provide an
example?
> Isn't it then cleaner to use the parent MFD to coordinate between the
> cells, just as we do for IO?
>
> In this case a child driver looked up a sibling node based on name, but
This should not be allowed. If >1 sibling requires access to a
particular property, this is normally evidence enough that this
property should be shared and handled by the parent.
> that doesn't mean the node is active, that there's a driver bound, or
> that the sibling node has some other random property for example. The
> parent could be used for such coordination, if only to pass information
> from one sibling to another.
Right.
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
^ permalink raw reply
* Re: [PATCH v5 2/2] crypto: stm32 - Support for STM32 CRYP crypto module
From: Fabien DESSENNE @ 2017-11-13 10:30 UTC (permalink / raw)
To: Herbert Xu
Cc: Corentin Labbe, David S . Miller, Rob Herring, Mark Rutland,
Maxime Coquelin, Alexandre TORGUE,
linux-crypto-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
Lionel DEBIEVE, Benjamin GAIGNARD, Ludovic BARRE
In-Reply-To: <d924a278-90d0-969e-f1ae-a12f92e8972d-qxv4g6HH51o@public.gmane.org>
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="utf-8", Size: 2270 bytes --]
Hi Herbert,
Can you check if this patchset (removed the AEAD part as you suggested +
libkcapi test OK as suggested by Corentin) can be applied now?
BR
Fabien
On 07/11/17 15:40, Fabien DESSENNE wrote:
>
> On 22/10/17 09:26, Corentin Labbe wrote:
>> On Thu, Oct 19, 2017 at 05:10:30PM +0200, Fabien Dessenne wrote:
>>> This module registers block cipher algorithms that make use of the
>>> STMicroelectronics STM32 crypto "CRYP1" hardware.
>>> The following algorithms are supported:
>>> - aes: ecb, cbc, ctr
>>> - des: ecb, cbc
>>> - tdes: ecb, cbc
>>>
>>> Signed-off-by: Fabien Dessenne <fabien.dessenne@st.com>
>>> ---
>>> drivers/crypto/stm32/Kconfig | 9 +
>>> drivers/crypto/stm32/Makefile | 3 +-
>>> drivers/crypto/stm32/stm32-cryp.c | 1172 +++++++++++++++++++++++++++++++++++++
>>> 3 files changed, 1183 insertions(+), 1 deletion(-)
>>> create mode 100644 drivers/crypto/stm32/stm32-cryp.c
>>>
>>> diff --git a/drivers/crypto/stm32/Kconfig b/drivers/crypto/stm32/Kconfig
>>> +static void stm32_cryp_irq_write_block(struct stm32_cryp *cryp)
>>> +{
>>> + unsigned int i, j;
>>> + u32 *src;
>>> + u8 d8[4];
>>> +
>>> + src = sg_virt(cryp->in_sg) + _walked_in;
>>> +
>>> + for (i = 0; i < cryp->hw_blocksize / sizeof(u32); i++) {
>>> + if (likely(cryp->total_in >= sizeof(u32))) {
>>> + /* Write a full u32 */
>>> + stm32_cryp_write(cryp, CRYP_DIN, *src);
>> Hello
>>
>> Try also to test your driver with userspace via AF_ALG (libkcapi is a good start).
>> It should probably crash here.
>> I have do the same on my first sunxi-ss driver and you should use kmap().
>>
>> Regards
> Hi Corentin,
>
> Thank you for suggesting to test from userspace through the AF_ALG
> socket with libkcapi.
> This increases my test coverage.
>
> I ran the miscellaneous tests (kcapi-enc-test(large).sh + test.sh) and
> could not observe any crash.
> Note that I had already fixed some 'memory crashes' while testing with
> testmgr / tcrypt while testing from the kernel.
>
> So it looks like the proposed implementation is fine.
>
> BR
>
> Fabien
N§²æìr¸yúèØb²X¬¶Ç§vØ^)Þº{.nÇ+·zøzÚÞz)í
æèw*\x1fjg¬±¨\x1e¶Ý¢j.ïÛ°\½½MúgjÌæa×\x02' ©Þ¢¸\f¢·¦j:+v¨wèjØm¶ÿ¾\a«êçzZ+ùÝ¢j"ú!¶i
^ permalink raw reply
* Re: [PATCH v4 15/13] firmware: arm_sdei: be more robust against cpu-hotplug
From: Will Deacon @ 2017-11-13 11:01 UTC (permalink / raw)
To: James Morse
Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
kvmarm-FPEHb7Xf0XXUo1n7N8X6UoWGPAHP3yOg,
devicetree-u79uwXL29TY76Z2rM5mHXA, Catalin Marinas, Mark Rutland,
Rob Herring, Marc Zyngier, Christoffer Dall, Lorenzo Pieralisi,
Loc Ho
In-Reply-To: <20171108160624.10355-1-james.morse-5wv7dgnIgG8@public.gmane.org>
On Wed, Nov 08, 2017 at 04:06:24PM +0000, James Morse wrote:
> dpm_suspend() calls the freeze/thaw callbacks for hibernate before
> disable_non_bootcpus() takes down secondaries.
>
> This leads to a fun race where the freeze/thaw callbacks reset the
> SDEI interface (as we may be restoring a kernel with a different
> layout due to KASLR), then the cpu-hotplug callbacks come in to
> save the current state, which has already been reset.
>
> I tried to solve this with a 'frozen' flag that stops the hotplug
> callback from overwriting the saved values. Instead this just
> moves the race around and makes it even harder to think about.
>
> Instead, make it look like the secondaries have gone offline.
> Call cpuhp_remove_state() in the freeze callback, this will call the
> teardown hook on all online CPUs, then remove the state. This saves
> all private events and makes future CPU up/down events invisible.
>
> Change sdei_event_unregister_all()/sdei_reregister_events() to
> only save/restore shared events, which are all that is left. With
> this we can remove the frozen flag. We can remove the device
> suspend/resume calls too as cpuhotplug's teardown call has masked
> the CPUs.
>
> All that is left is the reboot notifier, (which was abusing the
> frozen flag). Call cpuhp_remove_state() to make it look like
> secondary CPUs have gone offline.
>
> Suggested-by: Will Deacon <will.deacon-5wv7dgnIgG8@public.gmane.org>
> Signed-off-by: James Morse <james.morse-5wv7dgnIgG8@public.gmane.org>
> ---
> drivers/firmware/arm_sdei.c | 60 +++++++++++++++++++++++----------------------
> 1 file changed, 31 insertions(+), 29 deletions(-)
Thanks, this appears to address my concerns. It's too late for 4.15 now,
but please resend for 4.16 and Catalin can pick this series up.
Will
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* RE: [RFCv2 PATCH 01/36] iommu: Keep track of processes and PASIDs
From: Bharat Kumar Gogada @ 2017-11-13 11:06 UTC (permalink / raw)
To: Jean-Philippe Brucker,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
linux-pci-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-acpi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org
Cc: joro-zLv9SwRftAIdnm+yROfE0A@public.gmane.org,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org, Mark Rutland,
Catalin Marinas, Will Deacon,
lorenzo.pieralisi-5wv7dgnIgG8@public.gmane.org,
hanjun.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org, Sudeep Holla,
rjw-LthD3rsA81gm4RdzfppkhA@public.gmane.org,
lenb-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org, Robin Murphy,
bhelgaas-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org,
alex.williamson-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org,
tn-nYOzD4b6Jr9Wk0Htik3J/w@public.gmane.org,
liubo95-hv44wF8Li93QT0dZR+AlfA@public.gmane.org,
thunder.leizhen-hv44wF8Li93QT0dZR+AlfA@public.gmane.org,
xieyisheng1-hv44wF8Li93QT0dZR+AlfA@public.gmane.org, gabriele.pao
In-Reply-To: <16b6ba80-b15b-b278-0d06-350ae0201e82-5wv7dgnIgG8@public.gmane.org>
>
> In this case even though hardware supports PASID, BIND flow fails.
It should fail, since we're reserving PASID 0 for non-PASID transactions with S1DSS=0b10. In addition, the SMMUv3 specification does not allow using PASID with a single entry. See the description of S1CDMax in 5.2 Stream Table Entry:
"when this field is 0, the substreams of the STE are disabled and one CD is available. (The minimum useful number of substreams is 2.) Any transaction with a SubstreamID will be terminated with an abort and a C_BAD_SUBSTREAMID event recorded."
> Any reason why pasid allocation moved to idr allocations rather than
> bitmap allocations as in v1 patches ?
Yes, idr provides a convenient way to quickly retrieve the context associated with a PASID, when handling a fault. v1 had the allocation in a bitmap and storing in a rb-tree. By using an idr we combine both and rely on a well-tested infrastructure.
Note that in the future we might need to go back to handcrafting the PASID allocation, but it will probably still be based on idr.
Thanks for the clarification, Jean.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH] MIPS: implement a "bootargs-append" DT property
From: James Hogan @ 2017-11-13 11:23 UTC (permalink / raw)
To: Daniel Gimpelevich
Cc: linux-mips-6z/3iImG2C8G8FEW9MqTrA, Rob Herring, Frank Rowand,
devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1510420788-25184-1-git-send-email-daniel-R/FLGEdV95bo9U+Z1CfBt0SU0eOFXohjCypLqA8HKkk@public.gmane.org>
[-- Attachment #1: Type: text/plain, Size: 2248 bytes --]
On Sat, Nov 11, 2017 at 09:19:48AM -0800, Daniel Gimpelevich wrote:
> There are two uses for this:
>
> 1) It may be useful to split a device-specific kernel command line between
> a .dts file and a .dtsi file, with "bootargs" in one and "bootargs-append"
> in the other, such as for variations of a reference board.
>
> 2) There are kernel configuration options for prepending "bootargs" to the
> kernel command line that the bootloader has passed, but not for appending.
> A new option for this would be a less future-proof solution, since things
> like this should be in the dtb.
>
> This is tested on MIPS, but it can be useful on other architectures also.
>
> Signed-off-by: Daniel Gimpelevich <daniel-R/FLGEdV95bo9U+Z1CfBt0SU0eOFXohjCypLqA8HKkk@public.gmane.org>
The device tree maintainers should be on Cc. Adding them now.
Cheers
James
> ---
> arch/mips/kernel/setup.c | 3 +++
> drivers/of/fdt.c | 4 ++++
> 2 files changed, 7 insertions(+)
>
> diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
> index fe39397..95e9bf2 100644
> --- a/arch/mips/kernel/setup.c
> +++ b/arch/mips/kernel/setup.c
> @@ -826,7 +826,10 @@ static void __init arch_mem_init(char **cmdline_p)
> extern void plat_mem_setup(void);
>
> /* call board setup routine */
> + strlcpy(boot_command_line, arcs_cmdline, COMMAND_LINE_SIZE);
> plat_mem_setup();
> + if (strncmp(boot_command_line, arcs_cmdline, COMMAND_LINE_SIZE) == 0)
> + boot_command_line[0] = '\0';
>
> /*
> * Make sure all kernel memory is in the maps. The "UP" and
> diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
> index ce30c9a..65dbda6 100644
> --- a/drivers/of/fdt.c
> +++ b/drivers/of/fdt.c
> @@ -1127,6 +1127,10 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
> p = of_get_flat_dt_prop(node, "bootargs", &l);
> if (p != NULL && l > 0)
> strlcpy(data, p, min((int)l, COMMAND_LINE_SIZE));
> + p = of_get_flat_dt_prop(node, "bootargs-append", &l);
> + if (p != NULL && l > 0)
> + strlcat(data, p, min_t(int, strlen(data) + l,
> + COMMAND_LINE_SIZE));
>
> /*
> * CONFIG_CMDLINE is meant to be a default in case nothing else
> --
> 1.9.1
>
>
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ 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