cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

camss-csid-gen2.c (15772B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * camss-csid-4-7.c
      4 *
      5 * Qualcomm MSM Camera Subsystem - CSID (CSI Decoder) Module
      6 *
      7 * Copyright (C) 2020 Linaro Ltd.
      8 */
      9#include <linux/completion.h>
     10#include <linux/interrupt.h>
     11#include <linux/io.h>
     12#include <linux/kernel.h>
     13#include <linux/of.h>
     14
     15#include "camss-csid.h"
     16#include "camss-csid-gen2.h"
     17#include "camss.h"
     18
     19/* The CSID 2 IP-block is different from the others,
     20 * and is of a bare-bones Lite version, with no PIX
     21 * interface support. As a result of that it has an
     22 * alternate register layout.
     23 */
     24#define IS_LITE		(csid->id >= 2 ? 1 : 0)
     25
     26#define CSID_HW_VERSION		0x0
     27#define		HW_VERSION_STEPPING	0
     28#define		HW_VERSION_REVISION	16
     29#define		HW_VERSION_GENERATION	28
     30
     31#define CSID_RST_STROBES	0x10
     32#define		RST_STROBES	0
     33
     34#define CSID_CSI2_RX_IRQ_STATUS	0x20
     35#define	CSID_CSI2_RX_IRQ_MASK	0x24
     36#define CSID_CSI2_RX_IRQ_CLEAR	0x28
     37
     38#define CSID_CSI2_RDIN_IRQ_STATUS(rdi)		((IS_LITE ? 0x30 : 0x40) \
     39						 + 0x10 * (rdi))
     40#define CSID_CSI2_RDIN_IRQ_MASK(rdi)		((IS_LITE ? 0x34 : 0x44) \
     41						 + 0x10 * (rdi))
     42#define CSID_CSI2_RDIN_IRQ_CLEAR(rdi)		((IS_LITE ? 0x38 : 0x48) \
     43						 + 0x10 * (rdi))
     44#define CSID_CSI2_RDIN_IRQ_SET(rdi)		((IS_LITE ? 0x3C : 0x4C) \
     45						 + 0x10 * (rdi))
     46
     47#define CSID_TOP_IRQ_STATUS	0x70
     48#define		TOP_IRQ_STATUS_RESET_DONE 0
     49#define CSID_TOP_IRQ_MASK	0x74
     50#define CSID_TOP_IRQ_CLEAR	0x78
     51#define CSID_TOP_IRQ_SET	0x7C
     52#define CSID_IRQ_CMD		0x80
     53#define		IRQ_CMD_CLEAR	0
     54#define		IRQ_CMD_SET	4
     55
     56#define CSID_CSI2_RX_CFG0	0x100
     57#define		CSI2_RX_CFG0_NUM_ACTIVE_LANES	0
     58#define		CSI2_RX_CFG0_DL0_INPUT_SEL	4
     59#define		CSI2_RX_CFG0_DL1_INPUT_SEL	8
     60#define		CSI2_RX_CFG0_DL2_INPUT_SEL	12
     61#define		CSI2_RX_CFG0_DL3_INPUT_SEL	16
     62#define		CSI2_RX_CFG0_PHY_NUM_SEL	20
     63#define		CSI2_RX_CFG0_PHY_TYPE_SEL	24
     64
     65#define CSID_CSI2_RX_CFG1	0x104
     66#define		CSI2_RX_CFG1_PACKET_ECC_CORRECTION_EN		0
     67#define		CSI2_RX_CFG1_DE_SCRAMBLE_EN			1
     68#define		CSI2_RX_CFG1_VC_MODE				2
     69#define		CSI2_RX_CFG1_COMPLETE_STREAM_EN			4
     70#define		CSI2_RX_CFG1_COMPLETE_STREAM_FRAME_TIMING	5
     71#define		CSI2_RX_CFG1_MISR_EN				6
     72#define		CSI2_RX_CFG1_CGC_MODE				7
     73#define			CGC_MODE_DYNAMIC_GATING		0
     74#define			CGC_MODE_ALWAYS_ON		1
     75
     76#define CSID_RDI_CFG0(rdi)			((IS_LITE ? 0x200 : 0x300) \
     77						 + 0x100 * (rdi))
     78#define		RDI_CFG0_BYTE_CNTR_EN		0
     79#define		RDI_CFG0_FORMAT_MEASURE_EN	1
     80#define		RDI_CFG0_TIMESTAMP_EN		2
     81#define		RDI_CFG0_DROP_H_EN		3
     82#define		RDI_CFG0_DROP_V_EN		4
     83#define		RDI_CFG0_CROP_H_EN		5
     84#define		RDI_CFG0_CROP_V_EN		6
     85#define		RDI_CFG0_MISR_EN		7
     86#define		RDI_CFG0_CGC_MODE		8
     87#define			CGC_MODE_DYNAMIC	0
     88#define			CGC_MODE_ALWAYS_ON	1
     89#define		RDI_CFG0_PLAIN_ALIGNMENT	9
     90#define			PLAIN_ALIGNMENT_LSB	0
     91#define			PLAIN_ALIGNMENT_MSB	1
     92#define		RDI_CFG0_PLAIN_FORMAT		10
     93#define		RDI_CFG0_DECODE_FORMAT		12
     94#define		RDI_CFG0_DATA_TYPE		16
     95#define		RDI_CFG0_VIRTUAL_CHANNEL	22
     96#define		RDI_CFG0_DT_ID			27
     97#define		RDI_CFG0_EARLY_EOF_EN		29
     98#define		RDI_CFG0_PACKING_FORMAT		30
     99#define		RDI_CFG0_ENABLE			31
    100
    101#define CSID_RDI_CFG1(rdi)			((IS_LITE ? 0x204 : 0x304)\
    102						+ 0x100 * (rdi))
    103#define		RDI_CFG1_TIMESTAMP_STB_SEL	0
    104
    105#define CSID_RDI_CTRL(rdi)			((IS_LITE ? 0x208 : 0x308)\
    106						+ 0x100 * (rdi))
    107#define		RDI_CTRL_HALT_CMD		0
    108#define			HALT_CMD_HALT_AT_FRAME_BOUNDARY		0
    109#define			HALT_CMD_RESUME_AT_FRAME_BOUNDARY	1
    110#define		RDI_CTRL_HALT_MODE		2
    111
    112#define CSID_RDI_FRM_DROP_PATTERN(rdi)			((IS_LITE ? 0x20C : 0x30C)\
    113							+ 0x100 * (rdi))
    114#define CSID_RDI_FRM_DROP_PERIOD(rdi)			((IS_LITE ? 0x210 : 0x310)\
    115							+ 0x100 * (rdi))
    116#define CSID_RDI_IRQ_SUBSAMPLE_PATTERN(rdi)		((IS_LITE ? 0x214 : 0x314)\
    117							+ 0x100 * (rdi))
    118#define CSID_RDI_IRQ_SUBSAMPLE_PERIOD(rdi)		((IS_LITE ? 0x218 : 0x318)\
    119							+ 0x100 * (rdi))
    120#define CSID_RDI_RPP_PIX_DROP_PATTERN(rdi)		((IS_LITE ? 0x224 : 0x324)\
    121							+ 0x100 * (rdi))
    122#define CSID_RDI_RPP_PIX_DROP_PERIOD(rdi)		((IS_LITE ? 0x228 : 0x328)\
    123							+ 0x100 * (rdi))
    124#define CSID_RDI_RPP_LINE_DROP_PATTERN(rdi)		((IS_LITE ? 0x22C : 0x32C)\
    125							+ 0x100 * (rdi))
    126#define CSID_RDI_RPP_LINE_DROP_PERIOD(rdi)		((IS_LITE ? 0x230 : 0x330)\
    127							+ 0x100 * (rdi))
    128
    129#define CSID_TPG_CTRL		0x600
    130#define		TPG_CTRL_TEST_EN		0
    131#define		TPG_CTRL_FS_PKT_EN		1
    132#define		TPG_CTRL_FE_PKT_EN		2
    133#define		TPG_CTRL_NUM_ACTIVE_LANES	4
    134#define		TPG_CTRL_CYCLES_BETWEEN_PKTS	8
    135#define		TPG_CTRL_NUM_TRAIL_BYTES	20
    136
    137#define CSID_TPG_VC_CFG0	0x604
    138#define		TPG_VC_CFG0_VC_NUM			0
    139#define		TPG_VC_CFG0_NUM_ACTIVE_SLOTS		8
    140#define			NUM_ACTIVE_SLOTS_0_ENABLED	0
    141#define			NUM_ACTIVE_SLOTS_0_1_ENABLED	1
    142#define			NUM_ACTIVE_SLOTS_0_1_2_ENABLED	2
    143#define			NUM_ACTIVE_SLOTS_0_1_3_ENABLED	3
    144#define		TPG_VC_CFG0_LINE_INTERLEAVING_MODE	10
    145#define			INTELEAVING_MODE_INTERLEAVED	0
    146#define			INTELEAVING_MODE_ONE_SHOT	1
    147#define		TPG_VC_CFG0_NUM_FRAMES			16
    148
    149#define CSID_TPG_VC_CFG1	0x608
    150#define		TPG_VC_CFG1_H_BLANKING_COUNT		0
    151#define		TPG_VC_CFG1_V_BLANKING_COUNT		12
    152#define		TPG_VC_CFG1_V_BLANK_FRAME_WIDTH_SEL	24
    153
    154#define CSID_TPG_LFSR_SEED	0x60C
    155
    156#define CSID_TPG_DT_n_CFG_0(n)	(0x610 + (n) * 0xC)
    157#define		TPG_DT_n_CFG_0_FRAME_HEIGHT	0
    158#define		TPG_DT_n_CFG_0_FRAME_WIDTH	16
    159
    160#define CSID_TPG_DT_n_CFG_1(n)	(0x614 + (n) * 0xC)
    161#define		TPG_DT_n_CFG_1_DATA_TYPE	0
    162#define		TPG_DT_n_CFG_1_ECC_XOR_MASK	8
    163#define		TPG_DT_n_CFG_1_CRC_XOR_MASK	16
    164
    165#define CSID_TPG_DT_n_CFG_2(n)	(0x618 + (n) * 0xC)
    166#define		TPG_DT_n_CFG_2_PAYLOAD_MODE		0
    167#define		TPG_DT_n_CFG_2_USER_SPECIFIED_PAYLOAD	4
    168#define		TPG_DT_n_CFG_2_ENCODE_FORMAT		16
    169
    170#define CSID_TPG_COLOR_BARS_CFG	0x640
    171#define		TPG_COLOR_BARS_CFG_UNICOLOR_BAR_EN	0
    172#define		TPG_COLOR_BARS_CFG_UNICOLOR_BAR_SEL	4
    173#define		TPG_COLOR_BARS_CFG_SPLIT_EN		5
    174#define		TPG_COLOR_BARS_CFG_ROTATE_PERIOD	8
    175
    176#define CSID_TPG_COLOR_BOX_CFG	0x644
    177#define		TPG_COLOR_BOX_CFG_MODE		0
    178#define		TPG_COLOR_BOX_PATTERN_SEL	2
    179
    180static const struct csid_format csid_formats[] = {
    181	{
    182		MEDIA_BUS_FMT_UYVY8_2X8,
    183		DATA_TYPE_YUV422_8BIT,
    184		DECODE_FORMAT_UNCOMPRESSED_8_BIT,
    185		8,
    186		2,
    187	},
    188	{
    189		MEDIA_BUS_FMT_VYUY8_2X8,
    190		DATA_TYPE_YUV422_8BIT,
    191		DECODE_FORMAT_UNCOMPRESSED_8_BIT,
    192		8,
    193		2,
    194	},
    195	{
    196		MEDIA_BUS_FMT_YUYV8_2X8,
    197		DATA_TYPE_YUV422_8BIT,
    198		DECODE_FORMAT_UNCOMPRESSED_8_BIT,
    199		8,
    200		2,
    201	},
    202	{
    203		MEDIA_BUS_FMT_YVYU8_2X8,
    204		DATA_TYPE_YUV422_8BIT,
    205		DECODE_FORMAT_UNCOMPRESSED_8_BIT,
    206		8,
    207		2,
    208	},
    209	{
    210		MEDIA_BUS_FMT_SBGGR8_1X8,
    211		DATA_TYPE_RAW_8BIT,
    212		DECODE_FORMAT_UNCOMPRESSED_8_BIT,
    213		8,
    214		1,
    215	},
    216	{
    217		MEDIA_BUS_FMT_SGBRG8_1X8,
    218		DATA_TYPE_RAW_8BIT,
    219		DECODE_FORMAT_UNCOMPRESSED_8_BIT,
    220		8,
    221		1,
    222	},
    223	{
    224		MEDIA_BUS_FMT_SGRBG8_1X8,
    225		DATA_TYPE_RAW_8BIT,
    226		DECODE_FORMAT_UNCOMPRESSED_8_BIT,
    227		8,
    228		1,
    229	},
    230	{
    231		MEDIA_BUS_FMT_SRGGB8_1X8,
    232		DATA_TYPE_RAW_8BIT,
    233		DECODE_FORMAT_UNCOMPRESSED_8_BIT,
    234		8,
    235		1,
    236	},
    237	{
    238		MEDIA_BUS_FMT_SBGGR10_1X10,
    239		DATA_TYPE_RAW_10BIT,
    240		DECODE_FORMAT_UNCOMPRESSED_10_BIT,
    241		10,
    242		1,
    243	},
    244	{
    245		MEDIA_BUS_FMT_SGBRG10_1X10,
    246		DATA_TYPE_RAW_10BIT,
    247		DECODE_FORMAT_UNCOMPRESSED_10_BIT,
    248		10,
    249		1,
    250	},
    251	{
    252		MEDIA_BUS_FMT_SGRBG10_1X10,
    253		DATA_TYPE_RAW_10BIT,
    254		DECODE_FORMAT_UNCOMPRESSED_10_BIT,
    255		10,
    256		1,
    257	},
    258	{
    259		MEDIA_BUS_FMT_SRGGB10_1X10,
    260		DATA_TYPE_RAW_10BIT,
    261		DECODE_FORMAT_UNCOMPRESSED_10_BIT,
    262		10,
    263		1,
    264	},
    265	{
    266		MEDIA_BUS_FMT_Y8_1X8,
    267		DATA_TYPE_RAW_8BIT,
    268		DECODE_FORMAT_UNCOMPRESSED_8_BIT,
    269		8,
    270		1,
    271	},
    272	{
    273		MEDIA_BUS_FMT_Y10_1X10,
    274		DATA_TYPE_RAW_10BIT,
    275		DECODE_FORMAT_UNCOMPRESSED_10_BIT,
    276		10,
    277		1,
    278	},
    279	{
    280		MEDIA_BUS_FMT_SBGGR12_1X12,
    281		DATA_TYPE_RAW_12BIT,
    282		DECODE_FORMAT_UNCOMPRESSED_12_BIT,
    283		12,
    284		1,
    285	},
    286	{
    287		MEDIA_BUS_FMT_SGBRG12_1X12,
    288		DATA_TYPE_RAW_12BIT,
    289		DECODE_FORMAT_UNCOMPRESSED_12_BIT,
    290		12,
    291		1,
    292	},
    293	{
    294		MEDIA_BUS_FMT_SGRBG12_1X12,
    295		DATA_TYPE_RAW_12BIT,
    296		DECODE_FORMAT_UNCOMPRESSED_12_BIT,
    297		12,
    298		1,
    299	},
    300	{
    301		MEDIA_BUS_FMT_SRGGB12_1X12,
    302		DATA_TYPE_RAW_12BIT,
    303		DECODE_FORMAT_UNCOMPRESSED_12_BIT,
    304		12,
    305		1,
    306	},
    307	{
    308		MEDIA_BUS_FMT_SBGGR14_1X14,
    309		DATA_TYPE_RAW_14BIT,
    310		DECODE_FORMAT_UNCOMPRESSED_14_BIT,
    311		14,
    312		1,
    313	},
    314	{
    315		MEDIA_BUS_FMT_SGBRG14_1X14,
    316		DATA_TYPE_RAW_14BIT,
    317		DECODE_FORMAT_UNCOMPRESSED_14_BIT,
    318		14,
    319		1,
    320	},
    321	{
    322		MEDIA_BUS_FMT_SGRBG14_1X14,
    323		DATA_TYPE_RAW_14BIT,
    324		DECODE_FORMAT_UNCOMPRESSED_14_BIT,
    325		14,
    326		1,
    327	},
    328	{
    329		MEDIA_BUS_FMT_SRGGB14_1X14,
    330		DATA_TYPE_RAW_14BIT,
    331		DECODE_FORMAT_UNCOMPRESSED_14_BIT,
    332		14,
    333		1,
    334	},
    335};
    336
    337static void csid_configure_stream(struct csid_device *csid, u8 enable)
    338{
    339	struct csid_testgen_config *tg = &csid->testgen;
    340	u32 val;
    341	u32 phy_sel = 0;
    342	u8 lane_cnt = csid->phy.lane_cnt;
    343	struct v4l2_mbus_framefmt *input_format = &csid->fmt[MSM_CSID_PAD_SRC];
    344	const struct csid_format *format = csid_get_fmt_entry(csid->formats, csid->nformats,
    345							      input_format->code);
    346
    347	if (!lane_cnt)
    348		lane_cnt = 4;
    349
    350	if (!tg->enabled)
    351		phy_sel = csid->phy.csiphy_id;
    352
    353	if (enable) {
    354		u8 vc = 0; /* Virtual Channel 0 */
    355		u8 dt_id = vc * 4;
    356
    357		if (tg->enabled) {
    358			/* Config Test Generator */
    359			vc = 0xa;
    360
    361			/* configure one DT, infinite frames */
    362			val = vc << TPG_VC_CFG0_VC_NUM;
    363			val |= INTELEAVING_MODE_ONE_SHOT << TPG_VC_CFG0_LINE_INTERLEAVING_MODE;
    364			val |= 0 << TPG_VC_CFG0_NUM_FRAMES;
    365			writel_relaxed(val, csid->base + CSID_TPG_VC_CFG0);
    366
    367			val = 0x740 << TPG_VC_CFG1_H_BLANKING_COUNT;
    368			val |= 0x3ff << TPG_VC_CFG1_V_BLANKING_COUNT;
    369			writel_relaxed(val, csid->base + CSID_TPG_VC_CFG1);
    370
    371			writel_relaxed(0x12345678, csid->base + CSID_TPG_LFSR_SEED);
    372
    373			val = input_format->height & 0x1fff << TPG_DT_n_CFG_0_FRAME_HEIGHT;
    374			val |= input_format->width & 0x1fff << TPG_DT_n_CFG_0_FRAME_WIDTH;
    375			writel_relaxed(val, csid->base + CSID_TPG_DT_n_CFG_0(0));
    376
    377			val = format->data_type << TPG_DT_n_CFG_1_DATA_TYPE;
    378			writel_relaxed(val, csid->base + CSID_TPG_DT_n_CFG_1(0));
    379
    380			val = tg->mode << TPG_DT_n_CFG_2_PAYLOAD_MODE;
    381			val |= 0xBE << TPG_DT_n_CFG_2_USER_SPECIFIED_PAYLOAD;
    382			val |= format->decode_format << TPG_DT_n_CFG_2_ENCODE_FORMAT;
    383			writel_relaxed(val, csid->base + CSID_TPG_DT_n_CFG_2(0));
    384
    385			writel_relaxed(0, csid->base + CSID_TPG_COLOR_BARS_CFG);
    386
    387			writel_relaxed(0, csid->base + CSID_TPG_COLOR_BOX_CFG);
    388		}
    389
    390		val = 1 << RDI_CFG0_BYTE_CNTR_EN;
    391		val |= 1 << RDI_CFG0_FORMAT_MEASURE_EN;
    392		val |= 1 << RDI_CFG0_TIMESTAMP_EN;
    393		/* note: for non-RDI path, this should be format->decode_format */
    394		val |= DECODE_FORMAT_PAYLOAD_ONLY << RDI_CFG0_DECODE_FORMAT;
    395		val |= format->data_type << RDI_CFG0_DATA_TYPE;
    396		val |= vc << RDI_CFG0_VIRTUAL_CHANNEL;
    397		val |= dt_id << RDI_CFG0_DT_ID;
    398		writel_relaxed(val, csid->base + CSID_RDI_CFG0(0));
    399
    400		/* CSID_TIMESTAMP_STB_POST_IRQ */
    401		val = 2 << RDI_CFG1_TIMESTAMP_STB_SEL;
    402		writel_relaxed(val, csid->base + CSID_RDI_CFG1(0));
    403
    404		val = 1;
    405		writel_relaxed(val, csid->base + CSID_RDI_FRM_DROP_PERIOD(0));
    406
    407		val = 0;
    408		writel_relaxed(val, csid->base + CSID_RDI_FRM_DROP_PATTERN(0));
    409
    410		val = 1;
    411		writel_relaxed(val, csid->base + CSID_RDI_IRQ_SUBSAMPLE_PERIOD(0));
    412
    413		val = 0;
    414		writel_relaxed(val, csid->base + CSID_RDI_IRQ_SUBSAMPLE_PATTERN(0));
    415
    416		val = 1;
    417		writel_relaxed(val, csid->base + CSID_RDI_RPP_PIX_DROP_PERIOD(0));
    418
    419		val = 0;
    420		writel_relaxed(val, csid->base + CSID_RDI_RPP_PIX_DROP_PATTERN(0));
    421
    422		val = 1;
    423		writel_relaxed(val, csid->base + CSID_RDI_RPP_LINE_DROP_PERIOD(0));
    424
    425		val = 0;
    426		writel_relaxed(val, csid->base + CSID_RDI_RPP_LINE_DROP_PATTERN(0));
    427
    428		val = 0;
    429		writel_relaxed(val, csid->base + CSID_RDI_CTRL(0));
    430
    431		val = readl_relaxed(csid->base + CSID_RDI_CFG0(0));
    432		val |=  1 << RDI_CFG0_ENABLE;
    433		writel_relaxed(val, csid->base + CSID_RDI_CFG0(0));
    434	}
    435
    436	if (tg->enabled) {
    437		val = enable << TPG_CTRL_TEST_EN;
    438		val |= 1 << TPG_CTRL_FS_PKT_EN;
    439		val |= 1 << TPG_CTRL_FE_PKT_EN;
    440		val |= (lane_cnt - 1) << TPG_CTRL_NUM_ACTIVE_LANES;
    441		val |= 0x64 << TPG_CTRL_CYCLES_BETWEEN_PKTS;
    442		val |= 0xA << TPG_CTRL_NUM_TRAIL_BYTES;
    443		writel_relaxed(val, csid->base + CSID_TPG_CTRL);
    444	}
    445
    446	val = (lane_cnt - 1) << CSI2_RX_CFG0_NUM_ACTIVE_LANES;
    447	val |= csid->phy.lane_assign << CSI2_RX_CFG0_DL0_INPUT_SEL;
    448	val |= phy_sel << CSI2_RX_CFG0_PHY_NUM_SEL;
    449	writel_relaxed(val, csid->base + CSID_CSI2_RX_CFG0);
    450
    451	val = 1 << CSI2_RX_CFG1_PACKET_ECC_CORRECTION_EN;
    452	val |= 1 << CSI2_RX_CFG1_MISR_EN;
    453	writel_relaxed(val, csid->base + CSID_CSI2_RX_CFG1);
    454
    455	if (enable)
    456		val = HALT_CMD_RESUME_AT_FRAME_BOUNDARY << RDI_CTRL_HALT_CMD;
    457	else
    458		val = HALT_CMD_HALT_AT_FRAME_BOUNDARY << RDI_CTRL_HALT_CMD;
    459	writel_relaxed(val, csid->base + CSID_RDI_CTRL(0));
    460}
    461
    462static int csid_configure_testgen_pattern(struct csid_device *csid, s32 val)
    463{
    464	if (val > 0 && val <= csid->testgen.nmodes)
    465		csid->testgen.mode = val;
    466
    467	return 0;
    468}
    469
    470/*
    471 * csid_hw_version - CSID hardware version query
    472 * @csid: CSID device
    473 *
    474 * Return HW version or error
    475 */
    476static u32 csid_hw_version(struct csid_device *csid)
    477{
    478	u32 hw_version;
    479	u32 hw_gen;
    480	u32 hw_rev;
    481	u32 hw_step;
    482
    483	hw_version = readl_relaxed(csid->base + CSID_HW_VERSION);
    484	hw_gen = (hw_version >> HW_VERSION_GENERATION) & 0xF;
    485	hw_rev = (hw_version >> HW_VERSION_REVISION) & 0xFFF;
    486	hw_step = (hw_version >> HW_VERSION_STEPPING) & 0xFFFF;
    487	dev_dbg(csid->camss->dev, "CSID HW Version = %u.%u.%u\n",
    488		hw_gen, hw_rev, hw_step);
    489
    490	return hw_version;
    491}
    492
    493/*
    494 * csid_isr - CSID module interrupt service routine
    495 * @irq: Interrupt line
    496 * @dev: CSID device
    497 *
    498 * Return IRQ_HANDLED on success
    499 */
    500static irqreturn_t csid_isr(int irq, void *dev)
    501{
    502	struct csid_device *csid = dev;
    503	u32 val;
    504	u8 reset_done;
    505
    506	val = readl_relaxed(csid->base + CSID_TOP_IRQ_STATUS);
    507	writel_relaxed(val, csid->base + CSID_TOP_IRQ_CLEAR);
    508	reset_done = val & BIT(TOP_IRQ_STATUS_RESET_DONE);
    509
    510	val = readl_relaxed(csid->base + CSID_CSI2_RX_IRQ_STATUS);
    511	writel_relaxed(val, csid->base + CSID_CSI2_RX_IRQ_CLEAR);
    512
    513	val = readl_relaxed(csid->base + CSID_CSI2_RDIN_IRQ_STATUS(0));
    514	writel_relaxed(val, csid->base + CSID_CSI2_RDIN_IRQ_CLEAR(0));
    515
    516	val = 1 << IRQ_CMD_CLEAR;
    517	writel_relaxed(val, csid->base + CSID_IRQ_CMD);
    518
    519	if (reset_done)
    520		complete(&csid->reset_complete);
    521
    522	return IRQ_HANDLED;
    523}
    524
    525/*
    526 * csid_reset - Trigger reset on CSID module and wait to complete
    527 * @csid: CSID device
    528 *
    529 * Return 0 on success or a negative error code otherwise
    530 */
    531static int csid_reset(struct csid_device *csid)
    532{
    533	unsigned long time;
    534	u32 val;
    535
    536	reinit_completion(&csid->reset_complete);
    537
    538	writel_relaxed(1, csid->base + CSID_TOP_IRQ_CLEAR);
    539	writel_relaxed(1, csid->base + CSID_IRQ_CMD);
    540	writel_relaxed(1, csid->base + CSID_TOP_IRQ_MASK);
    541	writel_relaxed(1, csid->base + CSID_IRQ_CMD);
    542
    543	/* preserve registers */
    544	val = 0x1e << RST_STROBES;
    545	writel_relaxed(val, csid->base + CSID_RST_STROBES);
    546
    547	time = wait_for_completion_timeout(&csid->reset_complete,
    548					   msecs_to_jiffies(CSID_RESET_TIMEOUT_MS));
    549	if (!time) {
    550		dev_err(csid->camss->dev, "CSID reset timeout\n");
    551		return -EIO;
    552	}
    553
    554	return 0;
    555}
    556
    557static u32 csid_src_pad_code(struct csid_device *csid, u32 sink_code,
    558			     unsigned int match_format_idx, u32 match_code)
    559{
    560	switch (sink_code) {
    561	case MEDIA_BUS_FMT_SBGGR10_1X10:
    562	{
    563		u32 src_code[] = {
    564			MEDIA_BUS_FMT_SBGGR10_1X10,
    565			MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE,
    566		};
    567
    568		return csid_find_code(src_code, ARRAY_SIZE(src_code),
    569				      match_format_idx, match_code);
    570	}
    571	case MEDIA_BUS_FMT_Y10_1X10:
    572	{
    573		u32 src_code[] = {
    574			MEDIA_BUS_FMT_Y10_1X10,
    575			MEDIA_BUS_FMT_Y10_2X8_PADHI_LE,
    576		};
    577
    578		return csid_find_code(src_code, ARRAY_SIZE(src_code),
    579				      match_format_idx, match_code);
    580	}
    581	default:
    582		if (match_format_idx > 0)
    583			return 0;
    584
    585		return sink_code;
    586	}
    587}
    588
    589static void csid_subdev_init(struct csid_device *csid)
    590{
    591	csid->formats = csid_formats;
    592	csid->nformats = ARRAY_SIZE(csid_formats);
    593	csid->testgen.modes = csid_testgen_modes;
    594	csid->testgen.nmodes = CSID_PAYLOAD_MODE_NUM_SUPPORTED_GEN2;
    595}
    596
    597const struct csid_hw_ops csid_ops_gen2 = {
    598	.configure_stream = csid_configure_stream,
    599	.configure_testgen_pattern = csid_configure_testgen_pattern,
    600	.hw_version = csid_hw_version,
    601	.isr = csid_isr,
    602	.reset = csid_reset,
    603	.src_pad_code = csid_src_pad_code,
    604	.subdev_init = csid_subdev_init,
    605};