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

iss.c (33239B)


      1// SPDX-License-Identifier: GPL-2.0+
      2/*
      3 * TI OMAP4 ISS V4L2 Driver
      4 *
      5 * Copyright (C) 2012, Texas Instruments
      6 *
      7 * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
      8 */
      9
     10#include <linux/clk.h>
     11#include <linux/delay.h>
     12#include <linux/device.h>
     13#include <linux/dma-mapping.h>
     14#include <linux/i2c.h>
     15#include <linux/interrupt.h>
     16#include <linux/mfd/syscon.h>
     17#include <linux/module.h>
     18#include <linux/platform_device.h>
     19#include <linux/slab.h>
     20#include <linux/sched.h>
     21#include <linux/vmalloc.h>
     22
     23#include <media/v4l2-common.h>
     24#include <media/v4l2-device.h>
     25#include <media/v4l2-ctrls.h>
     26
     27#include "iss.h"
     28#include "iss_regs.h"
     29
     30#define ISS_PRINT_REGISTER(iss, name)\
     31	dev_dbg(iss->dev, "###ISS " #name "=0x%08x\n", \
     32		iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_##name))
     33
     34static void iss_print_status(struct iss_device *iss)
     35{
     36	dev_dbg(iss->dev, "-------------ISS HL Register dump-------------\n");
     37
     38	ISS_PRINT_REGISTER(iss, HL_REVISION);
     39	ISS_PRINT_REGISTER(iss, HL_SYSCONFIG);
     40	ISS_PRINT_REGISTER(iss, HL_IRQSTATUS(5));
     41	ISS_PRINT_REGISTER(iss, HL_IRQENABLE_SET(5));
     42	ISS_PRINT_REGISTER(iss, HL_IRQENABLE_CLR(5));
     43	ISS_PRINT_REGISTER(iss, CTRL);
     44	ISS_PRINT_REGISTER(iss, CLKCTRL);
     45	ISS_PRINT_REGISTER(iss, CLKSTAT);
     46
     47	dev_dbg(iss->dev, "-----------------------------------------------\n");
     48}
     49
     50/*
     51 * omap4iss_flush - Post pending L3 bus writes by doing a register readback
     52 * @iss: OMAP4 ISS device
     53 *
     54 * In order to force posting of pending writes, we need to write and
     55 * readback the same register, in this case the revision register.
     56 *
     57 * See this link for reference:
     58 *   https://www.mail-archive.com/linux-omap@vger.kernel.org/msg08149.html
     59 */
     60static void omap4iss_flush(struct iss_device *iss)
     61{
     62	iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_HL_REVISION, 0);
     63	iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_HL_REVISION);
     64}
     65
     66/*
     67 * iss_isp_enable_interrupts - Enable ISS ISP interrupts.
     68 * @iss: OMAP4 ISS device
     69 */
     70static void omap4iss_isp_enable_interrupts(struct iss_device *iss)
     71{
     72	static const u32 isp_irq = ISP5_IRQ_OCP_ERR |
     73				   ISP5_IRQ_RSZ_FIFO_IN_BLK_ERR |
     74				   ISP5_IRQ_RSZ_FIFO_OVF |
     75				   ISP5_IRQ_RSZ_INT_DMA |
     76				   ISP5_IRQ_ISIF_INT(0);
     77
     78	/* Enable ISP interrupts */
     79	iss_reg_write(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_IRQSTATUS(0), isp_irq);
     80	iss_reg_write(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_IRQENABLE_SET(0),
     81		      isp_irq);
     82}
     83
     84/*
     85 * iss_isp_disable_interrupts - Disable ISS interrupts.
     86 * @iss: OMAP4 ISS device
     87 */
     88static void omap4iss_isp_disable_interrupts(struct iss_device *iss)
     89{
     90	iss_reg_write(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_IRQENABLE_CLR(0), ~0);
     91}
     92
     93/*
     94 * iss_enable_interrupts - Enable ISS interrupts.
     95 * @iss: OMAP4 ISS device
     96 */
     97static void iss_enable_interrupts(struct iss_device *iss)
     98{
     99	static const u32 hl_irq = ISS_HL_IRQ_CSIA | ISS_HL_IRQ_CSIB
    100				| ISS_HL_IRQ_ISP(0);
    101
    102	/* Enable HL interrupts */
    103	iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_HL_IRQSTATUS(5), hl_irq);
    104	iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_HL_IRQENABLE_SET(5), hl_irq);
    105
    106	if (iss->regs[OMAP4_ISS_MEM_ISP_SYS1])
    107		omap4iss_isp_enable_interrupts(iss);
    108}
    109
    110/*
    111 * iss_disable_interrupts - Disable ISS interrupts.
    112 * @iss: OMAP4 ISS device
    113 */
    114static void iss_disable_interrupts(struct iss_device *iss)
    115{
    116	if (iss->regs[OMAP4_ISS_MEM_ISP_SYS1])
    117		omap4iss_isp_disable_interrupts(iss);
    118
    119	iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_HL_IRQENABLE_CLR(5), ~0);
    120}
    121
    122int omap4iss_get_external_info(struct iss_pipeline *pipe,
    123			       struct media_link *link)
    124{
    125	struct iss_device *iss =
    126		container_of(pipe, struct iss_video, pipe)->iss;
    127	struct v4l2_subdev_format fmt;
    128	struct v4l2_ctrl *ctrl;
    129	int ret;
    130
    131	if (!pipe->external)
    132		return 0;
    133
    134	if (pipe->external_rate)
    135		return 0;
    136
    137	memset(&fmt, 0, sizeof(fmt));
    138
    139	fmt.pad = link->source->index;
    140	fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
    141	ret = v4l2_subdev_call(media_entity_to_v4l2_subdev(link->sink->entity),
    142			       pad, get_fmt, NULL, &fmt);
    143	if (ret < 0)
    144		return -EPIPE;
    145
    146	pipe->external_bpp = omap4iss_video_format_info(fmt.format.code)->bpp;
    147
    148	ctrl = v4l2_ctrl_find(pipe->external->ctrl_handler,
    149			      V4L2_CID_PIXEL_RATE);
    150	if (!ctrl) {
    151		dev_warn(iss->dev, "no pixel rate control in subdev %s\n",
    152			 pipe->external->name);
    153		return -EPIPE;
    154	}
    155
    156	pipe->external_rate = v4l2_ctrl_g_ctrl_int64(ctrl);
    157
    158	return 0;
    159}
    160
    161/*
    162 * Configure the bridge. Valid inputs are
    163 *
    164 * IPIPEIF_INPUT_CSI2A: CSI2a receiver
    165 * IPIPEIF_INPUT_CSI2B: CSI2b receiver
    166 *
    167 * The bridge and lane shifter are configured according to the selected input
    168 * and the ISP platform data.
    169 */
    170void omap4iss_configure_bridge(struct iss_device *iss,
    171			       enum ipipeif_input_entity input)
    172{
    173	u32 issctrl_val;
    174	u32 isp5ctrl_val;
    175
    176	issctrl_val = iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_CTRL);
    177	issctrl_val &= ~ISS_CTRL_INPUT_SEL_MASK;
    178	issctrl_val &= ~ISS_CTRL_CLK_DIV_MASK;
    179
    180	isp5ctrl_val = iss_reg_read(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_CTRL);
    181
    182	switch (input) {
    183	case IPIPEIF_INPUT_CSI2A:
    184		issctrl_val |= ISS_CTRL_INPUT_SEL_CSI2A;
    185		break;
    186
    187	case IPIPEIF_INPUT_CSI2B:
    188		issctrl_val |= ISS_CTRL_INPUT_SEL_CSI2B;
    189		break;
    190
    191	default:
    192		return;
    193	}
    194
    195	issctrl_val |= ISS_CTRL_SYNC_DETECT_VS_RAISING;
    196
    197	isp5ctrl_val |= ISP5_CTRL_VD_PULSE_EXT | ISP5_CTRL_PSYNC_CLK_SEL |
    198			ISP5_CTRL_SYNC_ENABLE;
    199
    200	iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_CTRL, issctrl_val);
    201	iss_reg_write(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_CTRL, isp5ctrl_val);
    202}
    203
    204#ifdef ISS_ISR_DEBUG
    205static void iss_isr_dbg(struct iss_device *iss, u32 irqstatus)
    206{
    207	static const char * const name[] = {
    208		"ISP_0",
    209		"ISP_1",
    210		"ISP_2",
    211		"ISP_3",
    212		"CSIA",
    213		"CSIB",
    214		"CCP2_0",
    215		"CCP2_1",
    216		"CCP2_2",
    217		"CCP2_3",
    218		"CBUFF",
    219		"BTE",
    220		"SIMCOP_0",
    221		"SIMCOP_1",
    222		"SIMCOP_2",
    223		"SIMCOP_3",
    224		"CCP2_8",
    225		"HS_VS",
    226		"18",
    227		"19",
    228		"20",
    229		"21",
    230		"22",
    231		"23",
    232		"24",
    233		"25",
    234		"26",
    235		"27",
    236		"28",
    237		"29",
    238		"30",
    239		"31",
    240	};
    241	unsigned int i;
    242
    243	dev_dbg(iss->dev, "ISS IRQ: ");
    244
    245	for (i = 0; i < ARRAY_SIZE(name); i++) {
    246		if ((1 << i) & irqstatus)
    247			pr_cont("%s ", name[i]);
    248	}
    249	pr_cont("\n");
    250}
    251
    252static void iss_isp_isr_dbg(struct iss_device *iss, u32 irqstatus)
    253{
    254	static const char * const name[] = {
    255		"ISIF_0",
    256		"ISIF_1",
    257		"ISIF_2",
    258		"ISIF_3",
    259		"IPIPEREQ",
    260		"IPIPELAST_PIX",
    261		"IPIPEDMA",
    262		"IPIPEBSC",
    263		"IPIPEHST",
    264		"IPIPEIF",
    265		"AEW",
    266		"AF",
    267		"H3A",
    268		"RSZ_REG",
    269		"RSZ_LAST_PIX",
    270		"RSZ_DMA",
    271		"RSZ_CYC_RZA",
    272		"RSZ_CYC_RZB",
    273		"RSZ_FIFO_OVF",
    274		"RSZ_FIFO_IN_BLK_ERR",
    275		"20",
    276		"21",
    277		"RSZ_EOF0",
    278		"RSZ_EOF1",
    279		"H3A_EOF",
    280		"IPIPE_EOF",
    281		"26",
    282		"IPIPE_DPC_INI",
    283		"IPIPE_DPC_RNEW0",
    284		"IPIPE_DPC_RNEW1",
    285		"30",
    286		"OCP_ERR",
    287	};
    288	unsigned int i;
    289
    290	dev_dbg(iss->dev, "ISP IRQ: ");
    291
    292	for (i = 0; i < ARRAY_SIZE(name); i++) {
    293		if ((1 << i) & irqstatus)
    294			pr_cont("%s ", name[i]);
    295	}
    296	pr_cont("\n");
    297}
    298#endif
    299
    300/*
    301 * iss_isr - Interrupt Service Routine for ISS module.
    302 * @irq: Not used currently.
    303 * @_iss: Pointer to the OMAP4 ISS device
    304 *
    305 * Handles the corresponding callback if plugged in.
    306 *
    307 * Returns IRQ_HANDLED when IRQ was correctly handled, or IRQ_NONE when the
    308 * IRQ wasn't handled.
    309 */
    310static irqreturn_t iss_isr(int irq, void *_iss)
    311{
    312	static const u32 ipipeif_events = ISP5_IRQ_IPIPEIF_IRQ |
    313					  ISP5_IRQ_ISIF_INT(0);
    314	static const u32 resizer_events = ISP5_IRQ_RSZ_FIFO_IN_BLK_ERR |
    315					  ISP5_IRQ_RSZ_FIFO_OVF |
    316					  ISP5_IRQ_RSZ_INT_DMA;
    317	struct iss_device *iss = _iss;
    318	u32 irqstatus;
    319
    320	irqstatus = iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_HL_IRQSTATUS(5));
    321	iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_HL_IRQSTATUS(5), irqstatus);
    322
    323	if (irqstatus & ISS_HL_IRQ_CSIA)
    324		omap4iss_csi2_isr(&iss->csi2a);
    325
    326	if (irqstatus & ISS_HL_IRQ_CSIB)
    327		omap4iss_csi2_isr(&iss->csi2b);
    328
    329	if (irqstatus & ISS_HL_IRQ_ISP(0)) {
    330		u32 isp_irqstatus = iss_reg_read(iss, OMAP4_ISS_MEM_ISP_SYS1,
    331						 ISP5_IRQSTATUS(0));
    332		iss_reg_write(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_IRQSTATUS(0),
    333			      isp_irqstatus);
    334
    335		if (isp_irqstatus & ISP5_IRQ_OCP_ERR)
    336			dev_dbg(iss->dev, "ISP5 OCP Error!\n");
    337
    338		if (isp_irqstatus & ipipeif_events) {
    339			omap4iss_ipipeif_isr(&iss->ipipeif,
    340					     isp_irqstatus & ipipeif_events);
    341		}
    342
    343		if (isp_irqstatus & resizer_events)
    344			omap4iss_resizer_isr(&iss->resizer,
    345					     isp_irqstatus & resizer_events);
    346
    347#ifdef ISS_ISR_DEBUG
    348		iss_isp_isr_dbg(iss, isp_irqstatus);
    349#endif
    350	}
    351
    352	omap4iss_flush(iss);
    353
    354#ifdef ISS_ISR_DEBUG
    355	iss_isr_dbg(iss, irqstatus);
    356#endif
    357
    358	return IRQ_HANDLED;
    359}
    360
    361static const struct media_device_ops iss_media_ops = {
    362	.link_notify = v4l2_pipeline_link_notify,
    363};
    364
    365/* -----------------------------------------------------------------------------
    366 * Pipeline stream management
    367 */
    368
    369/*
    370 * iss_pipeline_disable - Disable streaming on a pipeline
    371 * @pipe: ISS pipeline
    372 * @until: entity at which to stop pipeline walk
    373 *
    374 * Walk the entities chain starting at the pipeline output video node and stop
    375 * all modules in the chain. Wait synchronously for the modules to be stopped if
    376 * necessary.
    377 *
    378 * If the until argument isn't NULL, stop the pipeline walk when reaching the
    379 * until entity. This is used to disable a partially started pipeline due to a
    380 * subdev start error.
    381 */
    382static int iss_pipeline_disable(struct iss_pipeline *pipe,
    383				struct media_entity *until)
    384{
    385	struct iss_device *iss = pipe->output->iss;
    386	struct media_entity *entity;
    387	struct media_pad *pad;
    388	struct v4l2_subdev *subdev;
    389	int failure = 0;
    390	int ret;
    391
    392	entity = &pipe->output->video.entity;
    393	while (1) {
    394		pad = &entity->pads[0];
    395		if (!(pad->flags & MEDIA_PAD_FL_SINK))
    396			break;
    397
    398		pad = media_entity_remote_pad(pad);
    399		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
    400			break;
    401
    402		entity = pad->entity;
    403		if (entity == until)
    404			break;
    405
    406		subdev = media_entity_to_v4l2_subdev(entity);
    407		ret = v4l2_subdev_call(subdev, video, s_stream, 0);
    408		if (ret < 0) {
    409			dev_warn(iss->dev, "%s: module stop timeout.\n",
    410				 subdev->name);
    411			/* If the entity failed to stopped, assume it has
    412			 * crashed. Mark it as such, the ISS will be reset when
    413			 * applications will release it.
    414			 */
    415			media_entity_enum_set(&iss->crashed, &subdev->entity);
    416			failure = -ETIMEDOUT;
    417		}
    418	}
    419
    420	return failure;
    421}
    422
    423/*
    424 * iss_pipeline_enable - Enable streaming on a pipeline
    425 * @pipe: ISS pipeline
    426 * @mode: Stream mode (single shot or continuous)
    427 *
    428 * Walk the entities chain starting at the pipeline output video node and start
    429 * all modules in the chain in the given mode.
    430 *
    431 * Return 0 if successful, or the return value of the failed video::s_stream
    432 * operation otherwise.
    433 */
    434static int iss_pipeline_enable(struct iss_pipeline *pipe,
    435			       enum iss_pipeline_stream_state mode)
    436{
    437	struct iss_device *iss = pipe->output->iss;
    438	struct media_entity *entity;
    439	struct media_pad *pad;
    440	struct v4l2_subdev *subdev;
    441	unsigned long flags;
    442	int ret;
    443
    444	/* If one of the entities in the pipeline has crashed it will not work
    445	 * properly. Refuse to start streaming in that case. This check must be
    446	 * performed before the loop below to avoid starting entities if the
    447	 * pipeline won't start anyway (those entities would then likely fail to
    448	 * stop, making the problem worse).
    449	 */
    450	if (media_entity_enum_intersects(&pipe->ent_enum, &iss->crashed))
    451		return -EIO;
    452
    453	spin_lock_irqsave(&pipe->lock, flags);
    454	pipe->state &= ~(ISS_PIPELINE_IDLE_INPUT | ISS_PIPELINE_IDLE_OUTPUT);
    455	spin_unlock_irqrestore(&pipe->lock, flags);
    456
    457	pipe->do_propagation = false;
    458
    459	mutex_lock(&iss->media_dev.graph_mutex);
    460
    461	entity = &pipe->output->video.entity;
    462	while (1) {
    463		pad = &entity->pads[0];
    464		if (!(pad->flags & MEDIA_PAD_FL_SINK))
    465			break;
    466
    467		pad = media_entity_remote_pad(pad);
    468		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
    469			break;
    470
    471		entity = pad->entity;
    472		subdev = media_entity_to_v4l2_subdev(entity);
    473
    474		ret = v4l2_subdev_call(subdev, video, s_stream, mode);
    475		if (ret < 0 && ret != -ENOIOCTLCMD) {
    476			iss_pipeline_disable(pipe, entity);
    477			mutex_unlock(&iss->media_dev.graph_mutex);
    478			return ret;
    479		}
    480
    481		if (subdev == &iss->csi2a.subdev ||
    482		    subdev == &iss->csi2b.subdev)
    483			pipe->do_propagation = true;
    484	}
    485
    486	mutex_unlock(&iss->media_dev.graph_mutex);
    487	iss_print_status(pipe->output->iss);
    488
    489	return 0;
    490}
    491
    492/*
    493 * omap4iss_pipeline_set_stream - Enable/disable streaming on a pipeline
    494 * @pipe: ISS pipeline
    495 * @state: Stream state (stopped, single shot or continuous)
    496 *
    497 * Set the pipeline to the given stream state. Pipelines can be started in
    498 * single-shot or continuous mode.
    499 *
    500 * Return 0 if successful, or the return value of the failed video::s_stream
    501 * operation otherwise. The pipeline state is not updated when the operation
    502 * fails, except when stopping the pipeline.
    503 */
    504int omap4iss_pipeline_set_stream(struct iss_pipeline *pipe,
    505				 enum iss_pipeline_stream_state state)
    506{
    507	int ret;
    508
    509	if (state == ISS_PIPELINE_STREAM_STOPPED)
    510		ret = iss_pipeline_disable(pipe, NULL);
    511	else
    512		ret = iss_pipeline_enable(pipe, state);
    513
    514	if (ret == 0 || state == ISS_PIPELINE_STREAM_STOPPED)
    515		pipe->stream_state = state;
    516
    517	return ret;
    518}
    519
    520/*
    521 * omap4iss_pipeline_cancel_stream - Cancel stream on a pipeline
    522 * @pipe: ISS pipeline
    523 *
    524 * Cancelling a stream mark all buffers on all video nodes in the pipeline as
    525 * erroneous and makes sure no new buffer can be queued. This function is called
    526 * when a fatal error that prevents any further operation on the pipeline
    527 * occurs.
    528 */
    529void omap4iss_pipeline_cancel_stream(struct iss_pipeline *pipe)
    530{
    531	if (pipe->input)
    532		omap4iss_video_cancel_stream(pipe->input);
    533	if (pipe->output)
    534		omap4iss_video_cancel_stream(pipe->output);
    535}
    536
    537/*
    538 * iss_pipeline_is_last - Verify if entity has an enabled link to the output
    539 *			  video node
    540 * @me: ISS module's media entity
    541 *
    542 * Returns 1 if the entity has an enabled link to the output video node or 0
    543 * otherwise. It's true only while pipeline can have no more than one output
    544 * node.
    545 */
    546static int iss_pipeline_is_last(struct media_entity *me)
    547{
    548	struct iss_pipeline *pipe;
    549	struct media_pad *pad;
    550
    551	if (!me->pipe)
    552		return 0;
    553	pipe = to_iss_pipeline(me);
    554	if (pipe->stream_state == ISS_PIPELINE_STREAM_STOPPED)
    555		return 0;
    556	pad = media_entity_remote_pad(&pipe->output->pad);
    557	return pad->entity == me;
    558}
    559
    560static int iss_reset(struct iss_device *iss)
    561{
    562	unsigned int timeout;
    563
    564	iss_reg_set(iss, OMAP4_ISS_MEM_TOP, ISS_HL_SYSCONFIG,
    565		    ISS_HL_SYSCONFIG_SOFTRESET);
    566
    567	timeout = iss_poll_condition_timeout(
    568		!(iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_HL_SYSCONFIG) &
    569		ISS_HL_SYSCONFIG_SOFTRESET), 1000, 10, 100);
    570	if (timeout) {
    571		dev_err(iss->dev, "ISS reset timeout\n");
    572		return -ETIMEDOUT;
    573	}
    574
    575	media_entity_enum_zero(&iss->crashed);
    576
    577	return 0;
    578}
    579
    580static int iss_isp_reset(struct iss_device *iss)
    581{
    582	unsigned int timeout;
    583
    584	/* Fist, ensure that the ISP is IDLE (no transactions happening) */
    585	iss_reg_update(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_SYSCONFIG,
    586		       ISP5_SYSCONFIG_STANDBYMODE_MASK,
    587		       ISP5_SYSCONFIG_STANDBYMODE_SMART);
    588
    589	iss_reg_set(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_CTRL, ISP5_CTRL_MSTANDBY);
    590
    591	timeout = iss_poll_condition_timeout(
    592		iss_reg_read(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_CTRL) &
    593		ISP5_CTRL_MSTANDBY_WAIT, 1000000, 1000, 1500);
    594	if (timeout) {
    595		dev_err(iss->dev, "ISP5 standby timeout\n");
    596		return -ETIMEDOUT;
    597	}
    598
    599	/* Now finally, do the reset */
    600	iss_reg_set(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_SYSCONFIG,
    601		    ISP5_SYSCONFIG_SOFTRESET);
    602
    603	timeout = iss_poll_condition_timeout(
    604		!(iss_reg_read(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_SYSCONFIG) &
    605		ISP5_SYSCONFIG_SOFTRESET), 1000000, 1000, 1500);
    606	if (timeout) {
    607		dev_err(iss->dev, "ISP5 reset timeout\n");
    608		return -ETIMEDOUT;
    609	}
    610
    611	return 0;
    612}
    613
    614/*
    615 * iss_module_sync_idle - Helper to sync module with its idle state
    616 * @me: ISS submodule's media entity
    617 * @wait: ISS submodule's wait queue for streamoff/interrupt synchronization
    618 * @stopping: flag which tells module wants to stop
    619 *
    620 * This function checks if ISS submodule needs to wait for next interrupt. If
    621 * yes, makes the caller to sleep while waiting for such event.
    622 */
    623int omap4iss_module_sync_idle(struct media_entity *me, wait_queue_head_t *wait,
    624			      atomic_t *stopping)
    625{
    626	struct iss_pipeline *pipe = to_iss_pipeline(me);
    627	struct iss_video *video = pipe->output;
    628	unsigned long flags;
    629
    630	if (pipe->stream_state == ISS_PIPELINE_STREAM_STOPPED ||
    631	    (pipe->stream_state == ISS_PIPELINE_STREAM_SINGLESHOT &&
    632	     !iss_pipeline_ready(pipe)))
    633		return 0;
    634
    635	/*
    636	 * atomic_set() doesn't include memory barrier on ARM platform for SMP
    637	 * scenario. We'll call it here to avoid race conditions.
    638	 */
    639	atomic_set(stopping, 1);
    640	smp_wmb();
    641
    642	/*
    643	 * If module is the last one, it's writing to memory. In this case,
    644	 * it's necessary to check if the module is already paused due to
    645	 * DMA queue underrun or if it has to wait for next interrupt to be
    646	 * idle.
    647	 * If it isn't the last one, the function won't sleep but *stopping
    648	 * will still be set to warn next submodule caller's interrupt the
    649	 * module wants to be idle.
    650	 */
    651	if (!iss_pipeline_is_last(me))
    652		return 0;
    653
    654	spin_lock_irqsave(&video->qlock, flags);
    655	if (video->dmaqueue_flags & ISS_VIDEO_DMAQUEUE_UNDERRUN) {
    656		spin_unlock_irqrestore(&video->qlock, flags);
    657		atomic_set(stopping, 0);
    658		smp_wmb();
    659		return 0;
    660	}
    661	spin_unlock_irqrestore(&video->qlock, flags);
    662	if (!wait_event_timeout(*wait, !atomic_read(stopping),
    663				msecs_to_jiffies(1000))) {
    664		atomic_set(stopping, 0);
    665		smp_wmb();
    666		return -ETIMEDOUT;
    667	}
    668
    669	return 0;
    670}
    671
    672/*
    673 * omap4iss_module_sync_is_stopped - Helper to verify if module was stopping
    674 * @wait: ISS submodule's wait queue for streamoff/interrupt synchronization
    675 * @stopping: flag which tells module wants to stop
    676 *
    677 * This function checks if ISS submodule was stopping. In case of yes, it
    678 * notices the caller by setting stopping to 0 and waking up the wait queue.
    679 * Returns 1 if it was stopping or 0 otherwise.
    680 */
    681int omap4iss_module_sync_is_stopping(wait_queue_head_t *wait,
    682				     atomic_t *stopping)
    683{
    684	if (atomic_cmpxchg(stopping, 1, 0)) {
    685		wake_up(wait);
    686		return 1;
    687	}
    688
    689	return 0;
    690}
    691
    692/* --------------------------------------------------------------------------
    693 * Clock management
    694 */
    695
    696#define ISS_CLKCTRL_MASK	(ISS_CLKCTRL_CSI2_A |\
    697				 ISS_CLKCTRL_CSI2_B |\
    698				 ISS_CLKCTRL_ISP)
    699
    700static int __iss_subclk_update(struct iss_device *iss)
    701{
    702	u32 clk = 0;
    703	int ret = 0, timeout = 1000;
    704
    705	if (iss->subclk_resources & OMAP4_ISS_SUBCLK_CSI2_A)
    706		clk |= ISS_CLKCTRL_CSI2_A;
    707
    708	if (iss->subclk_resources & OMAP4_ISS_SUBCLK_CSI2_B)
    709		clk |= ISS_CLKCTRL_CSI2_B;
    710
    711	if (iss->subclk_resources & OMAP4_ISS_SUBCLK_ISP)
    712		clk |= ISS_CLKCTRL_ISP;
    713
    714	iss_reg_update(iss, OMAP4_ISS_MEM_TOP, ISS_CLKCTRL,
    715		       ISS_CLKCTRL_MASK, clk);
    716
    717	/* Wait for HW assertion */
    718	while (--timeout > 0) {
    719		udelay(1);
    720		if ((iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_CLKSTAT) &
    721		    ISS_CLKCTRL_MASK) == clk)
    722			break;
    723	}
    724
    725	if (!timeout)
    726		ret = -EBUSY;
    727
    728	return ret;
    729}
    730
    731int omap4iss_subclk_enable(struct iss_device *iss,
    732			   enum iss_subclk_resource res)
    733{
    734	iss->subclk_resources |= res;
    735
    736	return __iss_subclk_update(iss);
    737}
    738
    739int omap4iss_subclk_disable(struct iss_device *iss,
    740			    enum iss_subclk_resource res)
    741{
    742	iss->subclk_resources &= ~res;
    743
    744	return __iss_subclk_update(iss);
    745}
    746
    747#define ISS_ISP5_CLKCTRL_MASK	(ISP5_CTRL_BL_CLK_ENABLE |\
    748				 ISP5_CTRL_ISIF_CLK_ENABLE |\
    749				 ISP5_CTRL_H3A_CLK_ENABLE |\
    750				 ISP5_CTRL_RSZ_CLK_ENABLE |\
    751				 ISP5_CTRL_IPIPE_CLK_ENABLE |\
    752				 ISP5_CTRL_IPIPEIF_CLK_ENABLE)
    753
    754static void __iss_isp_subclk_update(struct iss_device *iss)
    755{
    756	u32 clk = 0;
    757
    758	if (iss->isp_subclk_resources & OMAP4_ISS_ISP_SUBCLK_ISIF)
    759		clk |= ISP5_CTRL_ISIF_CLK_ENABLE;
    760
    761	if (iss->isp_subclk_resources & OMAP4_ISS_ISP_SUBCLK_H3A)
    762		clk |= ISP5_CTRL_H3A_CLK_ENABLE;
    763
    764	if (iss->isp_subclk_resources & OMAP4_ISS_ISP_SUBCLK_RSZ)
    765		clk |= ISP5_CTRL_RSZ_CLK_ENABLE;
    766
    767	if (iss->isp_subclk_resources & OMAP4_ISS_ISP_SUBCLK_IPIPE)
    768		clk |= ISP5_CTRL_IPIPE_CLK_ENABLE;
    769
    770	if (iss->isp_subclk_resources & OMAP4_ISS_ISP_SUBCLK_IPIPEIF)
    771		clk |= ISP5_CTRL_IPIPEIF_CLK_ENABLE;
    772
    773	if (clk)
    774		clk |= ISP5_CTRL_BL_CLK_ENABLE;
    775
    776	iss_reg_update(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_CTRL,
    777		       ISS_ISP5_CLKCTRL_MASK, clk);
    778}
    779
    780void omap4iss_isp_subclk_enable(struct iss_device *iss,
    781				enum iss_isp_subclk_resource res)
    782{
    783	iss->isp_subclk_resources |= res;
    784
    785	__iss_isp_subclk_update(iss);
    786}
    787
    788void omap4iss_isp_subclk_disable(struct iss_device *iss,
    789				 enum iss_isp_subclk_resource res)
    790{
    791	iss->isp_subclk_resources &= ~res;
    792
    793	__iss_isp_subclk_update(iss);
    794}
    795
    796/*
    797 * iss_enable_clocks - Enable ISS clocks
    798 * @iss: OMAP4 ISS device
    799 *
    800 * Return 0 if successful, or clk_enable return value if any of tthem fails.
    801 */
    802static int iss_enable_clocks(struct iss_device *iss)
    803{
    804	int ret;
    805
    806	ret = clk_enable(iss->iss_fck);
    807	if (ret) {
    808		dev_err(iss->dev, "clk_enable iss_fck failed\n");
    809		return ret;
    810	}
    811
    812	ret = clk_enable(iss->iss_ctrlclk);
    813	if (ret) {
    814		dev_err(iss->dev, "clk_enable iss_ctrlclk failed\n");
    815		clk_disable(iss->iss_fck);
    816		return ret;
    817	}
    818
    819	return 0;
    820}
    821
    822/*
    823 * iss_disable_clocks - Disable ISS clocks
    824 * @iss: OMAP4 ISS device
    825 */
    826static void iss_disable_clocks(struct iss_device *iss)
    827{
    828	clk_disable(iss->iss_ctrlclk);
    829	clk_disable(iss->iss_fck);
    830}
    831
    832static int iss_get_clocks(struct iss_device *iss)
    833{
    834	iss->iss_fck = devm_clk_get(iss->dev, "iss_fck");
    835	if (IS_ERR(iss->iss_fck)) {
    836		dev_err(iss->dev, "Unable to get iss_fck clock info\n");
    837		return PTR_ERR(iss->iss_fck);
    838	}
    839
    840	iss->iss_ctrlclk = devm_clk_get(iss->dev, "iss_ctrlclk");
    841	if (IS_ERR(iss->iss_ctrlclk)) {
    842		dev_err(iss->dev, "Unable to get iss_ctrlclk clock info\n");
    843		return PTR_ERR(iss->iss_ctrlclk);
    844	}
    845
    846	return 0;
    847}
    848
    849/*
    850 * omap4iss_get - Acquire the ISS resource.
    851 *
    852 * Initializes the clocks for the first acquire.
    853 *
    854 * Increment the reference count on the ISS. If the first reference is taken,
    855 * enable clocks and power-up all submodules.
    856 *
    857 * Return a pointer to the ISS device structure, or NULL if an error occurred.
    858 */
    859struct iss_device *omap4iss_get(struct iss_device *iss)
    860{
    861	struct iss_device *__iss = iss;
    862
    863	if (!iss)
    864		return NULL;
    865
    866	mutex_lock(&iss->iss_mutex);
    867	if (iss->ref_count > 0)
    868		goto out;
    869
    870	if (iss_enable_clocks(iss) < 0) {
    871		__iss = NULL;
    872		goto out;
    873	}
    874
    875	iss_enable_interrupts(iss);
    876
    877out:
    878	if (__iss)
    879		iss->ref_count++;
    880	mutex_unlock(&iss->iss_mutex);
    881
    882	return __iss;
    883}
    884
    885/*
    886 * omap4iss_put - Release the ISS
    887 *
    888 * Decrement the reference count on the ISS. If the last reference is released,
    889 * power-down all submodules, disable clocks and free temporary buffers.
    890 */
    891void omap4iss_put(struct iss_device *iss)
    892{
    893	if (!iss)
    894		return;
    895
    896	mutex_lock(&iss->iss_mutex);
    897	WARN_ON(iss->ref_count == 0);
    898	if (--iss->ref_count == 0) {
    899		iss_disable_interrupts(iss);
    900		/* Reset the ISS if an entity has failed to stop. This is the
    901		 * only way to recover from such conditions, although it would
    902		 * be worth investigating whether resetting the ISP only can't
    903		 * fix the problem in some cases.
    904		 */
    905		if (!media_entity_enum_empty(&iss->crashed))
    906			iss_reset(iss);
    907		iss_disable_clocks(iss);
    908	}
    909	mutex_unlock(&iss->iss_mutex);
    910}
    911
    912static int iss_map_mem_resource(struct platform_device *pdev,
    913				struct iss_device *iss,
    914				enum iss_mem_resources res)
    915{
    916	iss->regs[res] = devm_platform_ioremap_resource(pdev, res);
    917
    918	return PTR_ERR_OR_ZERO(iss->regs[res]);
    919}
    920
    921static void iss_unregister_entities(struct iss_device *iss)
    922{
    923	omap4iss_resizer_unregister_entities(&iss->resizer);
    924	omap4iss_ipipe_unregister_entities(&iss->ipipe);
    925	omap4iss_ipipeif_unregister_entities(&iss->ipipeif);
    926	omap4iss_csi2_unregister_entities(&iss->csi2a);
    927	omap4iss_csi2_unregister_entities(&iss->csi2b);
    928
    929	v4l2_device_unregister(&iss->v4l2_dev);
    930	media_device_unregister(&iss->media_dev);
    931}
    932
    933/*
    934 * iss_register_subdev_group - Register a group of subdevices
    935 * @iss: OMAP4 ISS device
    936 * @board_info: I2C subdevs board information array
    937 *
    938 * Register all I2C subdevices in the board_info array. The array must be
    939 * terminated by a NULL entry, and the first entry must be the sensor.
    940 *
    941 * Return a pointer to the sensor media entity if it has been successfully
    942 * registered, or NULL otherwise.
    943 */
    944static struct v4l2_subdev *
    945iss_register_subdev_group(struct iss_device *iss,
    946			  struct iss_subdev_i2c_board_info *board_info)
    947{
    948	struct v4l2_subdev *sensor = NULL;
    949	unsigned int first;
    950
    951	if (!board_info->board_info)
    952		return NULL;
    953
    954	for (first = 1; board_info->board_info; ++board_info, first = 0) {
    955		struct v4l2_subdev *subdev;
    956		struct i2c_adapter *adapter;
    957
    958		adapter = i2c_get_adapter(board_info->i2c_adapter_id);
    959		if (!adapter) {
    960			dev_err(iss->dev,
    961				"%s: Unable to get I2C adapter %d for device %s\n",
    962				__func__, board_info->i2c_adapter_id,
    963				board_info->board_info->type);
    964			continue;
    965		}
    966
    967		subdev = v4l2_i2c_new_subdev_board(&iss->v4l2_dev, adapter,
    968						   board_info->board_info, NULL);
    969		if (!subdev) {
    970			dev_err(iss->dev, "Unable to register subdev %s\n",
    971				board_info->board_info->type);
    972			continue;
    973		}
    974
    975		if (first)
    976			sensor = subdev;
    977	}
    978
    979	return sensor;
    980}
    981
    982static int iss_register_entities(struct iss_device *iss)
    983{
    984	struct iss_platform_data *pdata = iss->pdata;
    985	struct iss_v4l2_subdevs_group *subdevs;
    986	int ret;
    987
    988	iss->media_dev.dev = iss->dev;
    989	strscpy(iss->media_dev.model, "TI OMAP4 ISS",
    990		sizeof(iss->media_dev.model));
    991	iss->media_dev.hw_revision = iss->revision;
    992	iss->media_dev.ops = &iss_media_ops;
    993	ret = media_device_register(&iss->media_dev);
    994	if (ret < 0) {
    995		dev_err(iss->dev, "Media device registration failed (%d)\n",
    996			ret);
    997		return ret;
    998	}
    999
   1000	iss->v4l2_dev.mdev = &iss->media_dev;
   1001	ret = v4l2_device_register(iss->dev, &iss->v4l2_dev);
   1002	if (ret < 0) {
   1003		dev_err(iss->dev, "V4L2 device registration failed (%d)\n",
   1004			ret);
   1005		goto done;
   1006	}
   1007
   1008	/* Register internal entities */
   1009	ret = omap4iss_csi2_register_entities(&iss->csi2a, &iss->v4l2_dev);
   1010	if (ret < 0)
   1011		goto done;
   1012
   1013	ret = omap4iss_csi2_register_entities(&iss->csi2b, &iss->v4l2_dev);
   1014	if (ret < 0)
   1015		goto done;
   1016
   1017	ret = omap4iss_ipipeif_register_entities(&iss->ipipeif, &iss->v4l2_dev);
   1018	if (ret < 0)
   1019		goto done;
   1020
   1021	ret = omap4iss_ipipe_register_entities(&iss->ipipe, &iss->v4l2_dev);
   1022	if (ret < 0)
   1023		goto done;
   1024
   1025	ret = omap4iss_resizer_register_entities(&iss->resizer, &iss->v4l2_dev);
   1026	if (ret < 0)
   1027		goto done;
   1028
   1029	/* Register external entities */
   1030	for (subdevs = pdata->subdevs; subdevs && subdevs->subdevs; ++subdevs) {
   1031		struct v4l2_subdev *sensor;
   1032		struct media_entity *input;
   1033		unsigned int flags;
   1034		unsigned int pad;
   1035
   1036		sensor = iss_register_subdev_group(iss, subdevs->subdevs);
   1037		if (!sensor)
   1038			continue;
   1039
   1040		sensor->host_priv = subdevs;
   1041
   1042		/* Connect the sensor to the correct interface module.
   1043		 * CSI2a receiver through CSIPHY1, or
   1044		 * CSI2b receiver through CSIPHY2
   1045		 */
   1046		switch (subdevs->interface) {
   1047		case ISS_INTERFACE_CSI2A_PHY1:
   1048			input = &iss->csi2a.subdev.entity;
   1049			pad = CSI2_PAD_SINK;
   1050			flags = MEDIA_LNK_FL_IMMUTABLE
   1051			      | MEDIA_LNK_FL_ENABLED;
   1052			break;
   1053
   1054		case ISS_INTERFACE_CSI2B_PHY2:
   1055			input = &iss->csi2b.subdev.entity;
   1056			pad = CSI2_PAD_SINK;
   1057			flags = MEDIA_LNK_FL_IMMUTABLE
   1058			      | MEDIA_LNK_FL_ENABLED;
   1059			break;
   1060
   1061		default:
   1062			dev_err(iss->dev, "invalid interface type %u\n",
   1063				subdevs->interface);
   1064			ret = -EINVAL;
   1065			goto done;
   1066		}
   1067
   1068		ret = media_create_pad_link(&sensor->entity, 0, input, pad,
   1069					    flags);
   1070		if (ret < 0)
   1071			goto done;
   1072	}
   1073
   1074	ret = v4l2_device_register_subdev_nodes(&iss->v4l2_dev);
   1075
   1076done:
   1077	if (ret < 0)
   1078		iss_unregister_entities(iss);
   1079
   1080	return ret;
   1081}
   1082
   1083/*
   1084 * iss_create_links() - Pads links creation for the subdevices
   1085 * @iss : Pointer to ISS device
   1086 *
   1087 * return negative error code or zero on success
   1088 */
   1089static int iss_create_links(struct iss_device *iss)
   1090{
   1091	int ret;
   1092
   1093	ret = omap4iss_csi2_create_links(iss);
   1094	if (ret < 0) {
   1095		dev_err(iss->dev, "CSI2 pads links creation failed\n");
   1096		return ret;
   1097	}
   1098
   1099	ret = omap4iss_ipipeif_create_links(iss);
   1100	if (ret < 0) {
   1101		dev_err(iss->dev, "ISP IPIPEIF pads links creation failed\n");
   1102		return ret;
   1103	}
   1104
   1105	ret = omap4iss_resizer_create_links(iss);
   1106	if (ret < 0) {
   1107		dev_err(iss->dev, "ISP RESIZER pads links creation failed\n");
   1108		return ret;
   1109	}
   1110
   1111	/* Connect the submodules. */
   1112	ret = media_create_pad_link(
   1113			&iss->csi2a.subdev.entity, CSI2_PAD_SOURCE,
   1114			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0);
   1115	if (ret < 0)
   1116		return ret;
   1117
   1118	ret = media_create_pad_link(
   1119			&iss->csi2b.subdev.entity, CSI2_PAD_SOURCE,
   1120			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0);
   1121	if (ret < 0)
   1122		return ret;
   1123
   1124	ret = media_create_pad_link(
   1125			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SOURCE_VP,
   1126			&iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0);
   1127	if (ret < 0)
   1128		return ret;
   1129
   1130	ret = media_create_pad_link(
   1131			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SOURCE_VP,
   1132			&iss->ipipe.subdev.entity, IPIPE_PAD_SINK, 0);
   1133	if (ret < 0)
   1134		return ret;
   1135
   1136	ret = media_create_pad_link(
   1137			&iss->ipipe.subdev.entity, IPIPE_PAD_SOURCE_VP,
   1138			&iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0);
   1139	if (ret < 0)
   1140		return ret;
   1141
   1142	return 0;
   1143};
   1144
   1145static void iss_cleanup_modules(struct iss_device *iss)
   1146{
   1147	omap4iss_csi2_cleanup(iss);
   1148	omap4iss_ipipeif_cleanup(iss);
   1149	omap4iss_ipipe_cleanup(iss);
   1150	omap4iss_resizer_cleanup(iss);
   1151}
   1152
   1153static int iss_initialize_modules(struct iss_device *iss)
   1154{
   1155	int ret;
   1156
   1157	ret = omap4iss_csiphy_init(iss);
   1158	if (ret < 0) {
   1159		dev_err(iss->dev, "CSI PHY initialization failed\n");
   1160		goto error_csiphy;
   1161	}
   1162
   1163	ret = omap4iss_csi2_init(iss);
   1164	if (ret < 0) {
   1165		dev_err(iss->dev, "CSI2 initialization failed\n");
   1166		goto error_csi2;
   1167	}
   1168
   1169	ret = omap4iss_ipipeif_init(iss);
   1170	if (ret < 0) {
   1171		dev_err(iss->dev, "ISP IPIPEIF initialization failed\n");
   1172		goto error_ipipeif;
   1173	}
   1174
   1175	ret = omap4iss_ipipe_init(iss);
   1176	if (ret < 0) {
   1177		dev_err(iss->dev, "ISP IPIPE initialization failed\n");
   1178		goto error_ipipe;
   1179	}
   1180
   1181	ret = omap4iss_resizer_init(iss);
   1182	if (ret < 0) {
   1183		dev_err(iss->dev, "ISP RESIZER initialization failed\n");
   1184		goto error_resizer;
   1185	}
   1186
   1187	return 0;
   1188
   1189error_resizer:
   1190	omap4iss_ipipe_cleanup(iss);
   1191error_ipipe:
   1192	omap4iss_ipipeif_cleanup(iss);
   1193error_ipipeif:
   1194	omap4iss_csi2_cleanup(iss);
   1195error_csi2:
   1196error_csiphy:
   1197	return ret;
   1198}
   1199
   1200static int iss_probe(struct platform_device *pdev)
   1201{
   1202	struct iss_platform_data *pdata = pdev->dev.platform_data;
   1203	struct iss_device *iss;
   1204	unsigned int i;
   1205	int ret;
   1206
   1207	if (!pdata)
   1208		return -EINVAL;
   1209
   1210	iss = devm_kzalloc(&pdev->dev, sizeof(*iss), GFP_KERNEL);
   1211	if (!iss)
   1212		return -ENOMEM;
   1213
   1214	mutex_init(&iss->iss_mutex);
   1215
   1216	iss->dev = &pdev->dev;
   1217	iss->pdata = pdata;
   1218
   1219	iss->raw_dmamask = DMA_BIT_MASK(32);
   1220	iss->dev->dma_mask = &iss->raw_dmamask;
   1221	iss->dev->coherent_dma_mask = DMA_BIT_MASK(32);
   1222
   1223	platform_set_drvdata(pdev, iss);
   1224
   1225	/*
   1226	 * TODO: When implementing DT support switch to syscon regmap lookup by
   1227	 * phandle.
   1228	 */
   1229	iss->syscon = syscon_regmap_lookup_by_compatible("syscon");
   1230	if (IS_ERR(iss->syscon)) {
   1231		ret = PTR_ERR(iss->syscon);
   1232		goto error;
   1233	}
   1234
   1235	/* Clocks */
   1236	ret = iss_map_mem_resource(pdev, iss, OMAP4_ISS_MEM_TOP);
   1237	if (ret < 0)
   1238		goto error;
   1239
   1240	ret = iss_get_clocks(iss);
   1241	if (ret < 0)
   1242		goto error;
   1243
   1244	if (!omap4iss_get(iss)) {
   1245		ret = -EINVAL;
   1246		goto error;
   1247	}
   1248
   1249	ret = iss_reset(iss);
   1250	if (ret < 0)
   1251		goto error_iss;
   1252
   1253	iss->revision = iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_HL_REVISION);
   1254	dev_info(iss->dev, "Revision %08x found\n", iss->revision);
   1255
   1256	for (i = 1; i < OMAP4_ISS_MEM_LAST; i++) {
   1257		ret = iss_map_mem_resource(pdev, iss, i);
   1258		if (ret)
   1259			goto error_iss;
   1260	}
   1261
   1262	/* Configure BTE BW_LIMITER field to max recommended value (1 GB) */
   1263	iss_reg_update(iss, OMAP4_ISS_MEM_BTE, BTE_CTRL,
   1264		       BTE_CTRL_BW_LIMITER_MASK,
   1265		       18 << BTE_CTRL_BW_LIMITER_SHIFT);
   1266
   1267	/* Perform ISP reset */
   1268	ret = omap4iss_subclk_enable(iss, OMAP4_ISS_SUBCLK_ISP);
   1269	if (ret < 0)
   1270		goto error_iss;
   1271
   1272	ret = iss_isp_reset(iss);
   1273	if (ret < 0)
   1274		goto error_iss;
   1275
   1276	dev_info(iss->dev, "ISP Revision %08x found\n",
   1277		 iss_reg_read(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_REVISION));
   1278
   1279	/* Interrupt */
   1280	ret = platform_get_irq(pdev, 0);
   1281	if (ret <= 0) {
   1282		ret = -ENODEV;
   1283		goto error_iss;
   1284	}
   1285	iss->irq_num = ret;
   1286
   1287	if (devm_request_irq(iss->dev, iss->irq_num, iss_isr, IRQF_SHARED,
   1288			     "OMAP4 ISS", iss)) {
   1289		dev_err(iss->dev, "Unable to request IRQ\n");
   1290		ret = -EINVAL;
   1291		goto error_iss;
   1292	}
   1293
   1294	/* Entities */
   1295	ret = iss_initialize_modules(iss);
   1296	if (ret < 0)
   1297		goto error_iss;
   1298
   1299	ret = iss_register_entities(iss);
   1300	if (ret < 0)
   1301		goto error_modules;
   1302
   1303	ret = media_entity_enum_init(&iss->crashed, &iss->media_dev);
   1304	if (ret)
   1305		goto error_entities;
   1306
   1307	ret = iss_create_links(iss);
   1308	if (ret < 0)
   1309		goto error_entities;
   1310
   1311	omap4iss_put(iss);
   1312
   1313	return 0;
   1314
   1315error_entities:
   1316	iss_unregister_entities(iss);
   1317	media_entity_enum_cleanup(&iss->crashed);
   1318error_modules:
   1319	iss_cleanup_modules(iss);
   1320error_iss:
   1321	omap4iss_put(iss);
   1322error:
   1323	mutex_destroy(&iss->iss_mutex);
   1324
   1325	return ret;
   1326}
   1327
   1328static int iss_remove(struct platform_device *pdev)
   1329{
   1330	struct iss_device *iss = platform_get_drvdata(pdev);
   1331
   1332	iss_unregister_entities(iss);
   1333	media_entity_enum_cleanup(&iss->crashed);
   1334	iss_cleanup_modules(iss);
   1335
   1336	return 0;
   1337}
   1338
   1339static const struct platform_device_id omap4iss_id_table[] = {
   1340	{ "omap4iss", 0 },
   1341	{ },
   1342};
   1343MODULE_DEVICE_TABLE(platform, omap4iss_id_table);
   1344
   1345static struct platform_driver iss_driver = {
   1346	.probe		= iss_probe,
   1347	.remove		= iss_remove,
   1348	.id_table	= omap4iss_id_table,
   1349	.driver = {
   1350		.name	= "omap4iss",
   1351	},
   1352};
   1353
   1354module_platform_driver(iss_driver);
   1355
   1356MODULE_DESCRIPTION("TI OMAP4 ISS driver");
   1357MODULE_AUTHOR("Sergio Aguirre <sergio.a.aguirre@gmail.com>");
   1358MODULE_LICENSE("GPL");