xref: /linux/drivers/media/platform/qcom/camss/camss-csid-gen3.c (revision f79e772258df311c2cb21594ca0996318e720d28)
10d6d5f49SVikram Sharma // SPDX-License-Identifier: GPL-2.0
20d6d5f49SVikram Sharma /*
30d6d5f49SVikram Sharma  * Qualcomm MSM Camera Subsystem - CSID (CSI Decoder) Module
40d6d5f49SVikram Sharma  *
50d6d5f49SVikram Sharma  * Copyright (c) 2024 Qualcomm Technologies, Inc.
60d6d5f49SVikram Sharma  */
70d6d5f49SVikram Sharma #include <linux/completion.h>
80d6d5f49SVikram Sharma #include <linux/delay.h>
90d6d5f49SVikram Sharma #include <linux/interrupt.h>
100d6d5f49SVikram Sharma #include <linux/io.h>
110d6d5f49SVikram Sharma #include <linux/kernel.h>
120d6d5f49SVikram Sharma #include <linux/of.h>
130d6d5f49SVikram Sharma 
140d6d5f49SVikram Sharma #include "camss.h"
150d6d5f49SVikram Sharma #include "camss-csid.h"
160d6d5f49SVikram Sharma #include "camss-csid-gen3.h"
170d6d5f49SVikram Sharma 
180d6d5f49SVikram Sharma #define CSID_IO_PATH_CFG0(csid)		(0x4 * (csid))
190d6d5f49SVikram Sharma #define		OUTPUT_IFE_EN			0x100
200d6d5f49SVikram Sharma #define		INTERNAL_CSID			1
210d6d5f49SVikram Sharma 
220d6d5f49SVikram Sharma #define CSID_RST_CFG			0xC
230d6d5f49SVikram Sharma #define		RST_MODE			BIT(0)
240d6d5f49SVikram Sharma #define		RST_LOCATION			BIT(4)
250d6d5f49SVikram Sharma 
260d6d5f49SVikram Sharma #define CSID_RST_CMD			0x10
270d6d5f49SVikram Sharma #define		SELECT_HW_RST			BIT(0)
280d6d5f49SVikram Sharma #define		SELECT_IRQ_RST			BIT(2)
290d6d5f49SVikram Sharma 
300d6d5f49SVikram Sharma #define CSID_IRQ_CMD			0x14
310d6d5f49SVikram Sharma #define		IRQ_CMD_CLEAR			BIT(0)
320d6d5f49SVikram Sharma 
330d6d5f49SVikram Sharma #define CSID_RUP_AUP_CMD		0x18
340d6d5f49SVikram Sharma #define		CSID_RUP_AUP_RDI(rdi)		((BIT(4) | BIT(20)) << (rdi))
350d6d5f49SVikram Sharma 
360d6d5f49SVikram Sharma #define CSID_TOP_IRQ_STATUS		0x7C
370d6d5f49SVikram Sharma #define		 TOP_IRQ_STATUS_RESET_DONE	BIT(0)
380d6d5f49SVikram Sharma 
390d6d5f49SVikram Sharma #define CSID_TOP_IRQ_MASK		0x80
400d6d5f49SVikram Sharma #define CSID_TOP_IRQ_CLEAR		0x84
410d6d5f49SVikram Sharma #define CSID_TOP_IRQ_SET		0x88
420d6d5f49SVikram Sharma 
430d6d5f49SVikram Sharma #define CSID_CSI2_RX_IRQ_STATUS		0x9C
440d6d5f49SVikram Sharma #define CSID_CSI2_RX_IRQ_MASK		0xA0
450d6d5f49SVikram Sharma #define CSID_CSI2_RX_IRQ_CLEAR		0xA4
460d6d5f49SVikram Sharma #define CSID_CSI2_RX_IRQ_SET		0xA8
470d6d5f49SVikram Sharma 
48*950f3d30SVikram Sharma #define IS_CSID_690(csid)	((csid->camss->res->version == CAMSS_8775P) \
49*950f3d30SVikram Sharma 				 || (csid->camss->res->version == CAMSS_8300))
500d6d5f49SVikram Sharma #define CSID_BUF_DONE_IRQ_STATUS	0x8C
51ed03e99dSVikram Sharma #define BUF_DONE_IRQ_STATUS_RDI_OFFSET  (csid_is_lite(csid) ?\
52ed03e99dSVikram Sharma 						1 : (IS_CSID_690(csid) ?\
53ed03e99dSVikram Sharma 						13 : 14))
540d6d5f49SVikram Sharma #define CSID_BUF_DONE_IRQ_MASK		0x90
550d6d5f49SVikram Sharma #define CSID_BUF_DONE_IRQ_CLEAR		0x94
560d6d5f49SVikram Sharma #define CSID_BUF_DONE_IRQ_SET		0x98
570d6d5f49SVikram Sharma 
580d6d5f49SVikram Sharma #define CSID_CSI2_RDIN_IRQ_STATUS(rdi)	(0xEC + 0x10 * (rdi))
590d6d5f49SVikram Sharma #define		RUP_DONE_IRQ_STATUS		BIT(23)
600d6d5f49SVikram Sharma 
610d6d5f49SVikram Sharma #define CSID_CSI2_RDIN_IRQ_CLEAR(rdi)	(0xF4 + 0x10 * (rdi))
620d6d5f49SVikram Sharma #define CSID_CSI2_RDIN_IRQ_SET(rdi)	(0xF8 + 0x10 * (rdi))
630d6d5f49SVikram Sharma 
640d6d5f49SVikram Sharma #define CSID_CSI2_RX_CFG0		0x200
650d6d5f49SVikram Sharma #define		CSI2_RX_CFG0_NUM_ACTIVE_LANES	0
66ed03e99dSVikram Sharma #define		CSI2_RX_CFG0_VC_MODE		3
670d6d5f49SVikram Sharma #define		CSI2_RX_CFG0_DL0_INPUT_SEL	4
680d6d5f49SVikram Sharma #define		CSI2_RX_CFG0_PHY_NUM_SEL	20
690d6d5f49SVikram Sharma 
700d6d5f49SVikram Sharma #define CSID_CSI2_RX_CFG1		0x204
710d6d5f49SVikram Sharma #define		CSI2_RX_CFG1_ECC_CORRECTION_EN	BIT(0)
720d6d5f49SVikram Sharma #define		CSI2_RX_CFG1_VC_MODE		BIT(2)
730d6d5f49SVikram Sharma 
74ed03e99dSVikram Sharma #define CSID_RDI_CFG0(rdi)	(csid_is_lite(csid) && IS_CSID_690(csid) ?\
75ed03e99dSVikram Sharma 					(0x300 + 0x100 * (rdi)) :\
76ed03e99dSVikram Sharma 					(0x500 + 0x100 * (rdi)))
770d6d5f49SVikram Sharma #define		RDI_CFG0_TIMESTAMP_EN		BIT(6)
780d6d5f49SVikram Sharma #define		RDI_CFG0_TIMESTAMP_STB_SEL	BIT(8)
790d6d5f49SVikram Sharma #define		RDI_CFG0_DECODE_FORMAT		12
800d6d5f49SVikram Sharma #define		RDI_CFG0_DT			16
810d6d5f49SVikram Sharma #define		RDI_CFG0_VC			22
820d6d5f49SVikram Sharma #define		RDI_CFG0_DT_ID			27
830d6d5f49SVikram Sharma #define		RDI_CFG0_EN			BIT(31)
840d6d5f49SVikram Sharma 
85ed03e99dSVikram Sharma #define CSID_RDI_CTRL(rdi)	(csid_is_lite(csid) && IS_CSID_690(csid) ?\
86ed03e99dSVikram Sharma 					(0x304 + 0x100 * (rdi)) :\
87ed03e99dSVikram Sharma 					(0x504 + 0x100 * (rdi)))
880d6d5f49SVikram Sharma #define		RDI_CTRL_START_CMD		BIT(0)
890d6d5f49SVikram Sharma 
90ed03e99dSVikram Sharma #define CSID_RDI_CFG1(rdi)	(csid_is_lite(csid) && IS_CSID_690(csid) ?\
91ed03e99dSVikram Sharma 					(0x310 + 0x100 * (rdi)) :\
92ed03e99dSVikram Sharma 					(0x510 + 0x100 * (rdi)))
930d6d5f49SVikram Sharma #define		RDI_CFG1_DROP_H_EN		BIT(5)
940d6d5f49SVikram Sharma #define		RDI_CFG1_DROP_V_EN		BIT(6)
950d6d5f49SVikram Sharma #define		RDI_CFG1_CROP_H_EN		BIT(7)
960d6d5f49SVikram Sharma #define		RDI_CFG1_CROP_V_EN		BIT(8)
970d6d5f49SVikram Sharma #define		RDI_CFG1_PIX_STORE		BIT(10)
980d6d5f49SVikram Sharma #define		RDI_CFG1_PACKING_FORMAT_MIPI	BIT(15)
990d6d5f49SVikram Sharma 
100ed03e99dSVikram Sharma #define CSID_RDI_IRQ_SUBSAMPLE_PATTERN(rdi)	(csid_is_lite(csid) && IS_CSID_690(csid) ?\
101ed03e99dSVikram Sharma 							(0x348 + 0x100 * (rdi)) :\
102ed03e99dSVikram Sharma 							(0x548 + 0x100 * (rdi)))
103ed03e99dSVikram Sharma #define CSID_RDI_IRQ_SUBSAMPLE_PERIOD(rdi)	(csid_is_lite(csid) && IS_CSID_690(csid) ?\
104ed03e99dSVikram Sharma 							(0x34C + 0x100 * (rdi)) :\
105ed03e99dSVikram Sharma 							(0x54C + 0x100 * (rdi)))
1060d6d5f49SVikram Sharma #define CSI2_RX_CFG0_PHY_SEL_BASE_IDX	1
1070d6d5f49SVikram Sharma 
1080d6d5f49SVikram Sharma static void __csid_configure_rx(struct csid_device *csid,
1090d6d5f49SVikram Sharma 				struct csid_phy_config *phy, int vc)
1100d6d5f49SVikram Sharma {
1110d6d5f49SVikram Sharma 	int val;
1120d6d5f49SVikram Sharma 
1130d6d5f49SVikram Sharma 	val = (phy->lane_cnt - 1) << CSI2_RX_CFG0_NUM_ACTIVE_LANES;
1140d6d5f49SVikram Sharma 	val |= phy->lane_assign << CSI2_RX_CFG0_DL0_INPUT_SEL;
1150d6d5f49SVikram Sharma 	val |= (phy->csiphy_id + CSI2_RX_CFG0_PHY_SEL_BASE_IDX) << CSI2_RX_CFG0_PHY_NUM_SEL;
1160d6d5f49SVikram Sharma 
1170d6d5f49SVikram Sharma 	writel(val, csid->base + CSID_CSI2_RX_CFG0);
1180d6d5f49SVikram Sharma 
1190d6d5f49SVikram Sharma 	val = CSI2_RX_CFG1_ECC_CORRECTION_EN;
1200d6d5f49SVikram Sharma 	if (vc > 3)
1210d6d5f49SVikram Sharma 		val |= CSI2_RX_CFG1_VC_MODE;
1220d6d5f49SVikram Sharma 
1230d6d5f49SVikram Sharma 	writel(val, csid->base + CSID_CSI2_RX_CFG1);
1240d6d5f49SVikram Sharma }
1250d6d5f49SVikram Sharma 
1260d6d5f49SVikram Sharma static void __csid_ctrl_rdi(struct csid_device *csid, int enable, u8 rdi)
1270d6d5f49SVikram Sharma {
1280d6d5f49SVikram Sharma 	int val = 0;
1290d6d5f49SVikram Sharma 
1300d6d5f49SVikram Sharma 	if (enable)
1310d6d5f49SVikram Sharma 		val = RDI_CTRL_START_CMD;
1320d6d5f49SVikram Sharma 
1330d6d5f49SVikram Sharma 	writel(val, csid->base + CSID_RDI_CTRL(rdi));
1340d6d5f49SVikram Sharma }
1350d6d5f49SVikram Sharma 
1360d6d5f49SVikram Sharma static void __csid_configure_wrapper(struct csid_device *csid)
1370d6d5f49SVikram Sharma {
1380d6d5f49SVikram Sharma 	u32 val;
1390d6d5f49SVikram Sharma 
1400d6d5f49SVikram Sharma 	/* csid lite doesn't need to configure top register */
1410d6d5f49SVikram Sharma 	if (csid->res->is_lite)
1420d6d5f49SVikram Sharma 		return;
1430d6d5f49SVikram Sharma 
1440d6d5f49SVikram Sharma 	val = OUTPUT_IFE_EN | INTERNAL_CSID;
1450d6d5f49SVikram Sharma 	writel(val, csid->camss->csid_wrapper_base + CSID_IO_PATH_CFG0(csid->id));
1460d6d5f49SVikram Sharma }
1470d6d5f49SVikram Sharma 
1480d6d5f49SVikram Sharma static void __csid_configure_rdi_stream(struct csid_device *csid, u8 enable, u8 vc)
1490d6d5f49SVikram Sharma {
1500d6d5f49SVikram Sharma 	u32 val;
1510d6d5f49SVikram Sharma 	u8 lane_cnt = csid->phy.lane_cnt;
1520d6d5f49SVikram Sharma 	/* Source pads matching RDI channels on hardware. Pad 1 -> RDI0, Pad 2 -> RDI1, etc. */
1530d6d5f49SVikram Sharma 	struct v4l2_mbus_framefmt *input_format = &csid->fmt[MSM_CSID_PAD_FIRST_SRC + vc];
1540d6d5f49SVikram Sharma 	const struct csid_format_info *format = csid_get_fmt_entry(csid->res->formats->formats,
1550d6d5f49SVikram Sharma 								   csid->res->formats->nformats,
1560d6d5f49SVikram Sharma 								   input_format->code);
1570d6d5f49SVikram Sharma 
1580d6d5f49SVikram Sharma 	if (!lane_cnt)
1590d6d5f49SVikram Sharma 		lane_cnt = 4;
1600d6d5f49SVikram Sharma 
1610d6d5f49SVikram Sharma 	/*
1620d6d5f49SVikram Sharma 	 * DT_ID is a two bit bitfield that is concatenated with
1630d6d5f49SVikram Sharma 	 * the four least significant bits of the five bit VC
1640d6d5f49SVikram Sharma 	 * bitfield to generate an internal CID value.
1650d6d5f49SVikram Sharma 	 *
1660d6d5f49SVikram Sharma 	 * CSID_RDI_CFG0(vc)
1670d6d5f49SVikram Sharma 	 * DT_ID : 28:27
1680d6d5f49SVikram Sharma 	 * VC    : 26:22
1690d6d5f49SVikram Sharma 	 * DT    : 21:16
1700d6d5f49SVikram Sharma 	 *
1710d6d5f49SVikram Sharma 	 * CID   : VC 3:0 << 2 | DT_ID 1:0
1720d6d5f49SVikram Sharma 	 */
1730d6d5f49SVikram Sharma 	u8 dt_id = vc & 0x03;
1740d6d5f49SVikram Sharma 
1750d6d5f49SVikram Sharma 	val = RDI_CFG0_TIMESTAMP_EN;
1760d6d5f49SVikram Sharma 	val |= RDI_CFG0_TIMESTAMP_STB_SEL;
1770d6d5f49SVikram Sharma 	/* note: for non-RDI path, this should be format->decode_format */
1780d6d5f49SVikram Sharma 	val |= DECODE_FORMAT_PAYLOAD_ONLY << RDI_CFG0_DECODE_FORMAT;
1790d6d5f49SVikram Sharma 	val |= vc << RDI_CFG0_VC;
1800d6d5f49SVikram Sharma 	val |= format->data_type << RDI_CFG0_DT;
1810d6d5f49SVikram Sharma 	val |= dt_id << RDI_CFG0_DT_ID;
1820d6d5f49SVikram Sharma 
1830d6d5f49SVikram Sharma 	writel(val, csid->base + CSID_RDI_CFG0(vc));
1840d6d5f49SVikram Sharma 
1850d6d5f49SVikram Sharma 	val = RDI_CFG1_PACKING_FORMAT_MIPI;
1860d6d5f49SVikram Sharma 	val |= RDI_CFG1_PIX_STORE;
1870d6d5f49SVikram Sharma 	val |= RDI_CFG1_DROP_H_EN;
1880d6d5f49SVikram Sharma 	val |= RDI_CFG1_DROP_V_EN;
1890d6d5f49SVikram Sharma 	val |= RDI_CFG1_CROP_H_EN;
1900d6d5f49SVikram Sharma 	val |= RDI_CFG1_CROP_V_EN;
1910d6d5f49SVikram Sharma 
1920d6d5f49SVikram Sharma 	writel(val, csid->base + CSID_RDI_CFG1(vc));
1930d6d5f49SVikram Sharma 
1940d6d5f49SVikram Sharma 	val = 0;
1950d6d5f49SVikram Sharma 	writel(val, csid->base + CSID_RDI_IRQ_SUBSAMPLE_PERIOD(vc));
1960d6d5f49SVikram Sharma 
1970d6d5f49SVikram Sharma 	val = 1;
1980d6d5f49SVikram Sharma 	writel(val, csid->base + CSID_RDI_IRQ_SUBSAMPLE_PATTERN(vc));
1990d6d5f49SVikram Sharma 
2000d6d5f49SVikram Sharma 	val = 0;
2010d6d5f49SVikram Sharma 	writel(val, csid->base + CSID_RDI_CTRL(vc));
2020d6d5f49SVikram Sharma 
2030d6d5f49SVikram Sharma 	val = readl(csid->base + CSID_RDI_CFG0(vc));
2040d6d5f49SVikram Sharma 
2050d6d5f49SVikram Sharma 	if (enable)
2060d6d5f49SVikram Sharma 		val |= RDI_CFG0_EN;
2070d6d5f49SVikram Sharma 	writel(val, csid->base + CSID_RDI_CFG0(vc));
2080d6d5f49SVikram Sharma }
2090d6d5f49SVikram Sharma 
2100d6d5f49SVikram Sharma static void csid_configure_stream(struct csid_device *csid, u8 enable)
2110d6d5f49SVikram Sharma {
2120d6d5f49SVikram Sharma 	u8 i;
2130d6d5f49SVikram Sharma 
2140d6d5f49SVikram Sharma 	__csid_configure_wrapper(csid);
2150d6d5f49SVikram Sharma 
2160d6d5f49SVikram Sharma 	/* Loop through all enabled VCs and configure stream for each */
2170d6d5f49SVikram Sharma 	for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS; i++)
2180d6d5f49SVikram Sharma 		if (csid->phy.en_vc & BIT(i)) {
2190d6d5f49SVikram Sharma 			__csid_configure_rdi_stream(csid, enable, i);
2200d6d5f49SVikram Sharma 			__csid_configure_rx(csid, &csid->phy, i);
2210d6d5f49SVikram Sharma 			__csid_ctrl_rdi(csid, enable, i);
2220d6d5f49SVikram Sharma 		}
2230d6d5f49SVikram Sharma }
2240d6d5f49SVikram Sharma 
2250d6d5f49SVikram Sharma static int csid_configure_testgen_pattern(struct csid_device *csid, s32 val)
2260d6d5f49SVikram Sharma {
2270d6d5f49SVikram Sharma 	return 0;
2280d6d5f49SVikram Sharma }
2290d6d5f49SVikram Sharma 
2300d6d5f49SVikram Sharma static void csid_subdev_reg_update(struct csid_device *csid, int port_id, bool clear)
2310d6d5f49SVikram Sharma {
2320d6d5f49SVikram Sharma 	if (clear) {
2330d6d5f49SVikram Sharma 		csid->reg_update &= ~CSID_RUP_AUP_RDI(port_id);
2340d6d5f49SVikram Sharma 	} else {
2350d6d5f49SVikram Sharma 		csid->reg_update |= CSID_RUP_AUP_RDI(port_id);
2360d6d5f49SVikram Sharma 		writel(csid->reg_update, csid->base + CSID_RUP_AUP_CMD);
2370d6d5f49SVikram Sharma 	}
2380d6d5f49SVikram Sharma }
2390d6d5f49SVikram Sharma 
2400d6d5f49SVikram Sharma /*
2410d6d5f49SVikram Sharma  * csid_isr - CSID module interrupt service routine
2420d6d5f49SVikram Sharma  * @irq: Interrupt line
2430d6d5f49SVikram Sharma  * @dev: CSID device
2440d6d5f49SVikram Sharma  *
2450d6d5f49SVikram Sharma  * Return IRQ_HANDLED on success
2460d6d5f49SVikram Sharma  */
2470d6d5f49SVikram Sharma static irqreturn_t csid_isr(int irq, void *dev)
2480d6d5f49SVikram Sharma {
2490d6d5f49SVikram Sharma 	struct csid_device *csid = dev;
2500d6d5f49SVikram Sharma 	u32 val, buf_done_val;
2510d6d5f49SVikram Sharma 	u8 reset_done;
2520d6d5f49SVikram Sharma 	int i;
2530d6d5f49SVikram Sharma 
2540d6d5f49SVikram Sharma 	val = readl(csid->base + CSID_TOP_IRQ_STATUS);
2550d6d5f49SVikram Sharma 	writel(val, csid->base + CSID_TOP_IRQ_CLEAR);
2560d6d5f49SVikram Sharma 	reset_done = val & TOP_IRQ_STATUS_RESET_DONE;
2570d6d5f49SVikram Sharma 
2580d6d5f49SVikram Sharma 	val = readl(csid->base + CSID_CSI2_RX_IRQ_STATUS);
2590d6d5f49SVikram Sharma 	writel(val, csid->base + CSID_CSI2_RX_IRQ_CLEAR);
2600d6d5f49SVikram Sharma 
2610d6d5f49SVikram Sharma 	buf_done_val = readl(csid->base + CSID_BUF_DONE_IRQ_STATUS);
2620d6d5f49SVikram Sharma 	writel(buf_done_val, csid->base + CSID_BUF_DONE_IRQ_CLEAR);
2630d6d5f49SVikram Sharma 
2640d6d5f49SVikram Sharma 	/* Read and clear IRQ status for each enabled RDI channel */
2650d6d5f49SVikram Sharma 	for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS; i++)
2660d6d5f49SVikram Sharma 		if (csid->phy.en_vc & BIT(i)) {
2670d6d5f49SVikram Sharma 			val = readl(csid->base + CSID_CSI2_RDIN_IRQ_STATUS(i));
2680d6d5f49SVikram Sharma 			writel(val, csid->base + CSID_CSI2_RDIN_IRQ_CLEAR(i));
2690d6d5f49SVikram Sharma 
2700d6d5f49SVikram Sharma 			if (val & RUP_DONE_IRQ_STATUS)
2710d6d5f49SVikram Sharma 				/* clear the reg update bit */
2720d6d5f49SVikram Sharma 				csid_subdev_reg_update(csid, i, true);
2730d6d5f49SVikram Sharma 
2740d6d5f49SVikram Sharma 			if (buf_done_val & BIT(BUF_DONE_IRQ_STATUS_RDI_OFFSET + i)) {
2750d6d5f49SVikram Sharma 				/*
2760d6d5f49SVikram Sharma 				 * For Titan Gen3, bus done and RUP IRQ have been moved to
2770d6d5f49SVikram Sharma 				 * CSID from VFE. Once CSID received bus done, need notify
2780d6d5f49SVikram Sharma 				 * VFE of this event. Trigger VFE to handle bus done process.
2790d6d5f49SVikram Sharma 				 */
2800d6d5f49SVikram Sharma 				camss_buf_done(csid->camss, csid->id, i);
2810d6d5f49SVikram Sharma 			}
2820d6d5f49SVikram Sharma 		}
2830d6d5f49SVikram Sharma 
2840d6d5f49SVikram Sharma 	val = IRQ_CMD_CLEAR;
2850d6d5f49SVikram Sharma 	writel(val, csid->base + CSID_IRQ_CMD);
2860d6d5f49SVikram Sharma 
2870d6d5f49SVikram Sharma 	if (reset_done)
2880d6d5f49SVikram Sharma 		complete(&csid->reset_complete);
2890d6d5f49SVikram Sharma 
2900d6d5f49SVikram Sharma 	return IRQ_HANDLED;
2910d6d5f49SVikram Sharma }
2920d6d5f49SVikram Sharma 
2930d6d5f49SVikram Sharma /*
2940d6d5f49SVikram Sharma  * csid_reset - Trigger reset on CSID module and wait to complete
2950d6d5f49SVikram Sharma  * @csid: CSID device
2960d6d5f49SVikram Sharma  *
2970d6d5f49SVikram Sharma  * Return 0 on success or a negative error code otherwise
2980d6d5f49SVikram Sharma  */
2990d6d5f49SVikram Sharma static int csid_reset(struct csid_device *csid)
3000d6d5f49SVikram Sharma {
3010d6d5f49SVikram Sharma 	unsigned long time;
3020d6d5f49SVikram Sharma 	u32 val;
3030d6d5f49SVikram Sharma 	int i;
3040d6d5f49SVikram Sharma 
3050d6d5f49SVikram Sharma 	reinit_completion(&csid->reset_complete);
3060d6d5f49SVikram Sharma 
3070d6d5f49SVikram Sharma 	writel(1, csid->base + CSID_TOP_IRQ_CLEAR);
3080d6d5f49SVikram Sharma 	writel(1, csid->base + CSID_IRQ_CMD);
3090d6d5f49SVikram Sharma 	writel(1, csid->base + CSID_TOP_IRQ_MASK);
3100d6d5f49SVikram Sharma 
3110d6d5f49SVikram Sharma 	for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS; i++)
3120d6d5f49SVikram Sharma 		if (csid->phy.en_vc & BIT(i)) {
3130d6d5f49SVikram Sharma 			writel(BIT(BUF_DONE_IRQ_STATUS_RDI_OFFSET + i),
3140d6d5f49SVikram Sharma 			       csid->base + CSID_BUF_DONE_IRQ_CLEAR);
3150d6d5f49SVikram Sharma 			writel(IRQ_CMD_CLEAR, csid->base + CSID_IRQ_CMD);
3160d6d5f49SVikram Sharma 			writel(BIT(BUF_DONE_IRQ_STATUS_RDI_OFFSET + i),
3170d6d5f49SVikram Sharma 			       csid->base + CSID_BUF_DONE_IRQ_MASK);
3180d6d5f49SVikram Sharma 		}
3190d6d5f49SVikram Sharma 
3200d6d5f49SVikram Sharma 	/* preserve registers */
3210d6d5f49SVikram Sharma 	val = RST_LOCATION | RST_MODE;
3220d6d5f49SVikram Sharma 	writel(val, csid->base + CSID_RST_CFG);
3230d6d5f49SVikram Sharma 
3240d6d5f49SVikram Sharma 	val = SELECT_HW_RST | SELECT_IRQ_RST;
3250d6d5f49SVikram Sharma 	writel(val, csid->base + CSID_RST_CMD);
3260d6d5f49SVikram Sharma 
3270d6d5f49SVikram Sharma 	time = wait_for_completion_timeout(&csid->reset_complete,
3280d6d5f49SVikram Sharma 					   msecs_to_jiffies(CSID_RESET_TIMEOUT_MS));
3290d6d5f49SVikram Sharma 	if (!time) {
3300d6d5f49SVikram Sharma 		dev_err(csid->camss->dev, "CSID reset timeout\n");
3310d6d5f49SVikram Sharma 		return -EIO;
3320d6d5f49SVikram Sharma 	}
3330d6d5f49SVikram Sharma 
3340d6d5f49SVikram Sharma 	return 0;
3350d6d5f49SVikram Sharma }
3360d6d5f49SVikram Sharma 
3370d6d5f49SVikram Sharma static void csid_subdev_init(struct csid_device *csid)
3380d6d5f49SVikram Sharma {
3390d6d5f49SVikram Sharma 	csid->testgen.nmodes = CSID_PAYLOAD_MODE_DISABLED;
3400d6d5f49SVikram Sharma }
3410d6d5f49SVikram Sharma 
3420d6d5f49SVikram Sharma const struct csid_hw_ops csid_ops_gen3 = {
3430d6d5f49SVikram Sharma 	.configure_stream = csid_configure_stream,
3440d6d5f49SVikram Sharma 	.configure_testgen_pattern = csid_configure_testgen_pattern,
3450d6d5f49SVikram Sharma 	.hw_version = csid_hw_version,
3460d6d5f49SVikram Sharma 	.isr = csid_isr,
3470d6d5f49SVikram Sharma 	.reset = csid_reset,
3480d6d5f49SVikram Sharma 	.src_pad_code = csid_src_pad_code,
3490d6d5f49SVikram Sharma 	.subdev_init = csid_subdev_init,
3500d6d5f49SVikram Sharma 	.reg_update = csid_subdev_reg_update,
3510d6d5f49SVikram Sharma };
352