Received: by 2002:a05:6a10:9848:0:0:0:0 with SMTP id x8csp1236954pxf; Fri, 26 Mar 2021 04:08:47 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxSBfChdkOwFfH4SldcMDkjV5m8GPyqjrP3QuGTVnv+MGqgHKBj+e4P8icr8vpDHfP13xfU X-Received: by 2002:a17:906:d790:: with SMTP id pj16mr14361252ejb.255.1616756927188; Fri, 26 Mar 2021 04:08:47 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1616756927; cv=none; d=google.com; s=arc-20160816; b=HTBdjxlacoyX8icRbqmkZqlQtrTHPEfxQ+4OIJ9OMW3oPyxfLVlkyx2UOXc2lewIUE NcpUztE0AXZvyGOy8+3Ovt2ytJoMz7HB6NxC13GZ0PA3/3qLHMRuLT7l+8qIlMUuGm5C Lszq42OZKuAE0yleRNH1Rl99qVBtyq7LX/Oqa0Gfy6ieJHO0gp5V6FfJBEBtlSBupfAr kNy2FeEBaNNjzh9ZaCu9U6YPZKiW7r/rwKaQ4NFYhz3lgtVu14lR1tSaiaHMrlt/wJih L+4RI08BmMIL1u7L1YpCHuMkENITyQiNJXzBgMpaq8Li7i2xCkZ/SSJiJPEdCzegcyPZ kZ6g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:in-reply-to:content-disposition:mime-version :references:message-id:subject:cc:to:from:date; bh=qc1EQMi6n+qkku6TsH7pvTvdW4jtW1EEuNLxh0VuBK4=; b=0UM8IONvpW756baUagDmhCYG5pCVqgqMsBclP+M4F7Y3LmfW2vJmt1N6tNaT70MRQ9 Zoll1FaetktK2gbrtjyOjWgl+fV/IknP7Kk2qTZaxaxfVGz3PwfpDZ6OcqdTIDBGFbqY amzYk0WYRJ8A4PcAAe+zWpmdlySPFXGOZLVr625QLURiFd11I+zpFAQGyFSO1TRRlUXm Yk2k3DBcAKY+hR8efH+nrQ4WDNaOY4v8ConJSM8VxDovbB/Ay1QNcaNbAiTrJML/r0+a ns+0EINK4Bwp6ycrO5pq7ZgncAqIlg3+6uorEs/Oq9F5ZEhyzuGikxwXsW2WTshy9y9r 2V2Q== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id d16si6649229edc.45.2021.03.26.04.08.24; Fri, 26 Mar 2021 04:08:47 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230026AbhCZLHE (ORCPT + 99 others); Fri, 26 Mar 2021 07:07:04 -0400 Received: from relay10.mail.gandi.net ([217.70.178.230]:39405 "EHLO relay10.mail.gandi.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230027AbhCZLGk (ORCPT ); Fri, 26 Mar 2021 07:06:40 -0400 Received: from uno.localdomain (93-34-118-233.ip49.fastwebnet.it [93.34.118.233]) (Authenticated sender: jacopo@jmondi.org) by relay10.mail.gandi.net (Postfix) with ESMTPSA id 4AA12240003; Fri, 26 Mar 2021 11:06:36 +0000 (UTC) Date: Fri, 26 Mar 2021 12:07:06 +0100 From: Jacopo Mondi To: Laurent Pinchart Cc: Jacopo Mondi , kieran.bingham+renesas@ideasonboard.com, niklas.soderlund+renesas@ragnatech.se, geert@linux-m68k.org, Mauro Carvalho Chehab , linux-media@vger.kernel.org, linux-renesas-soc@vger.kernel.org, linux-kernel@vger.kernel.org Subject: Re: [PATCH v3 13/19] media: i2c: rdacm21: Power up OV10640 before OV490 Message-ID: <20210326110706.qcu5ptxqeem3stot@uno.localdomain> References: <20210319164148.199192-1-jacopo+renesas@jmondi.org> <20210319164148.199192-14-jacopo+renesas@jmondi.org> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline In-Reply-To: Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi Laurent, On Sat, Mar 20, 2021 at 06:14:43PM +0200, Laurent Pinchart wrote: > Hi Jacopo, > > Thank you for the patch. > > On Fri, Mar 19, 2021 at 05:41:42PM +0100, Jacopo Mondi wrote: > > The current RDACM21 initialization routine powers up the > > OV10640 image sensor after the OV490 ISP. The ISP is programmed with > > a firmware loaded from an embedded EEPROM that (most probably) tries > > It's actually a serial flash, not an EEPROM. > > > to interact and program also the image sensor connected to the ISP. > > > > As described in commit ccb26c5742f5 ("media: i2c: rdacm21: Fix OV10640 > > That commit ID won't be valid anymore once the patches get merged, > unless they are pulled instead of cherry-picked, which is currently not > done in the Linux media subsystem. I'd drop it an only mention the > commit's subject. > > > powerup") the image sensor powerdown signal is kept high by an internal > > pull up resistor and occasionally fails to startup correctly if the > > powerdown line is not asserted explicitly. Failures in the OV10640 > > startup causes the OV490 firmware to fail to boot correctly resulting in > > the camera module initialization to fail consequentially. > > > > Fix this by powering up the OV10640 image sensor before testing the > > OV490 firmware boot completion, by splitting the ov10640_initialize() > > function in an ov10640_power_up() one and an ov10640_check_id() one. > > > > Also make sure the OV10640 identification procedure gives enough time to > > the image sensor to resume after the programming phase performed by the > > OV490 firmware by repeating the ID read procedure, > > s/,/./ > I'll rework > > > > This commit fixes a sporadic start-up error triggered by a failure to > > detect the OV490 firmware boot completion: > > rdacm21 8-0054: Timeout waiting for firmware boot > > > > Fixes: a59f853b3b4b ("media: i2c: Add driver for RDACM21 camera module") > > Signed-off-by: Jacopo Mondi > > --- > > drivers/media/i2c/rdacm21.c | 46 ++++++++++++++++++++++++++----------- > > 1 file changed, 32 insertions(+), 14 deletions(-) > > > > diff --git a/drivers/media/i2c/rdacm21.c b/drivers/media/i2c/rdacm21.c > > index 3f38c465b348..3763eb690d74 100644 > > --- a/drivers/media/i2c/rdacm21.c > > +++ b/drivers/media/i2c/rdacm21.c > > @@ -69,6 +69,7 @@ > > #define OV490_ISP_VSIZE_LOW 0x80820062 > > #define OV490_ISP_VSIZE_HIGH 0x80820063 > > > > +#define OV10640_PID_TIMEOUT 20 > > #define OV10640_ID_HIGH 0xa6 > > #define OV10640_CHIP_ID 0x300a > > #define OV10640_PIXEL_RATE 55000000 > > @@ -314,10 +315,8 @@ static int rdacm21_get_fmt(struct v4l2_subdev *sd, > > return 0; > > } > > > > -static int ov10640_initialize(struct rdacm21_device *dev) > > +static void ov10640_power_up(struct rdacm21_device *dev) > > { > > - u8 val; > > - > > /* Enable GPIO0#0 (reset) and GPIO1#0 (pwdn) as output lines. */ > > ov490_write_reg(dev, OV490_GPIO_SEL0, OV490_GPIO0); > > ov490_write_reg(dev, OV490_GPIO_SEL1, OV490_SPWDN0); > > @@ -332,18 +331,35 @@ static int ov10640_initialize(struct rdacm21_device *dev) > > usleep_range(1500, 3000); > > ov490_write_reg(dev, OV490_GPIO_OUTPUT_VALUE0, OV490_GPIO0); > > usleep_range(3000, 5000); > > +} > > > > - /* Read OV10640 ID to test communications. */ > > - ov490_write_reg(dev, OV490_SCCB_SLAVE0_DIR, OV490_SCCB_SLAVE_READ); > > - ov490_write_reg(dev, OV490_SCCB_SLAVE0_ADDR_HIGH, OV10640_CHIP_ID >> 8); > > - ov490_write_reg(dev, OV490_SCCB_SLAVE0_ADDR_LOW, OV10640_CHIP_ID & 0xff); > > - > > - /* Trigger SCCB slave transaction and give it some time to complete. */ > > - ov490_write_reg(dev, OV490_HOST_CMD, OV490_HOST_CMD_TRIGGER); > > - usleep_range(1000, 1500); > > +static int ov10640_check_id(struct rdacm21_device *dev) > > +{ > > + unsigned int i; > > + u8 val; > > > > - ov490_read_reg(dev, OV490_SCCB_SLAVE0_DIR, &val); > > - if (val != OV10640_ID_HIGH) { > > + /* Read OV10640 ID to test communications. */ > > + for (i = 0; i < OV10640_PID_TIMEOUT; ++i) { > > OV10640_PID_TIMEOUT is used in this function only, I would have made it > local. > I don't think a local variable is better. The timeout is a read-only constant which is better defined as a macro than a variable. > > + ov490_write_reg(dev, OV490_SCCB_SLAVE0_DIR, > > + OV490_SCCB_SLAVE_READ); > > + ov490_write_reg(dev, OV490_SCCB_SLAVE0_ADDR_HIGH, > > + OV10640_CHIP_ID >> 8); > > + ov490_write_reg(dev, OV490_SCCB_SLAVE0_ADDR_LOW, > > + OV10640_CHIP_ID & 0xff); > > + > > + /* > > + * Trigger SCCB slave transaction and give it some time > > + * to complete. > > + */ > > + ov490_write_reg(dev, OV490_HOST_CMD, OV490_HOST_CMD_TRIGGER); > > + usleep_range(1000, 1500); > > It would make sense to create an ov490_sensor_read() function to > encapsulate all this. > Maybe on top when we'll have more users > It would also be nicer to poll an OV490 register instead of sleeping > blindly. That likely requires the OV490 application note (referenced in > the datasheet), which we don't have. It may be useful to try and get > hold of that. I still feel there may be something a bit fishy, but way > less than before. > > > + > > + ov490_read_reg(dev, OV490_SCCB_SLAVE0_DIR, &val); > > + if (val == OV10640_ID_HIGH) > > + break; > > + usleep_range(1000, 1500); > > + } > > Blank line ? > There isn't one intentionally as the two blocks are tightly coupled. > > + if (i == OV10640_PID_TIMEOUT) { > > dev_err(dev->dev, "OV10640 ID mismatch: (0x%02x)\n", val); > > return -ENODEV; > > } > > @@ -359,6 +375,8 @@ static int ov490_initialize(struct rdacm21_device *dev) > > unsigned int i; > > int ret; > > > > + ov10640_power_up(dev); > > On top of this series, error handling of OV490 writes would make sense. > Maybe on top, yes Is there anything major I should do to get a tag here ? Thanks j > > + > > /* > > * Read OV490 Id to test communications. Give it up to 40msec to > > * exit from reset. > > @@ -396,7 +414,7 @@ static int ov490_initialize(struct rdacm21_device *dev) > > return -ENODEV; > > } > > > > - ret = ov10640_initialize(dev); > > + ret = ov10640_check_id(dev); > > if (ret) > > return ret; > > > > -- > Regards, > > Laurent Pinchart