Received: by 2002:a25:1985:0:0:0:0:0 with SMTP id 127csp1665840ybz; Thu, 16 Apr 2020 13:15:47 -0700 (PDT) X-Google-Smtp-Source: APiQypKy/ULs3Yq8yu7HcxPmpTq+FoHia/0nEhwB32hmVBKbhuLqkdVytVBiz2sCQ5c/0BgEochA X-Received: by 2002:a05:6402:1505:: with SMTP id f5mr29700935edw.208.1587068147794; Thu, 16 Apr 2020 13:15:47 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1587068147; cv=none; d=google.com; s=arc-20160816; b=VvSxPEdjvuoGKjYN237paYNdR+zEXG2Iri9Y+EyLpucg+Zu5bfo8mTCa/diMLMgunK G+hLr5Znlc5gHbLnGLj2vz62Kw5x5bnoLfuT/L1gjgl83clGZWGlCi9s1ltPdUwbg3Rw vOCNilYKfAU/JtoiNp9gSnlxLo/PTZdwLjELFS6eYSgyYLO5T/2ozvXRAshSz9dJEmcd OQbLsBZhj4jfH659KVsQBNU+Dp8RCXqcqeRlaYtc0NrU1xsQwc2tBAXVXxMKalxJ8pYV QXkOoTx0jsr5xqp5hi9rEnyocSIYWZgWjypsi9IuSzRz72vCG+9idKATlvvttlrQgZy2 xlwQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=rhsjJ/Q4cNK/H85nyC8Rn+EV6rjJ1MTwv/yXZKhvleg=; b=JC7O+G/khwywviYdUQjxQ4HFj2+9NURer6vw45UDsQPLDjswgotAhEKR9uoYUlfAL9 OhJMJEkNPCVx53wFT/Wt3rAfqvxMPHPDJbmUawQuSp28MRRMABaUx0HJMC0KqYJR7QuR mzy8NLrU5VTs16pDwN+ZozAi+X6f+WHcy0sLQddNH/bRijw81+WJwV3/hTPEO1GAjVgc leihCkutPtBVRyx+NTfjrTDUfM4RJ/EyG9P0Bl0CpqzetzydqUZLlViPad+aJ7qTa/9m TjXocREvsh7tSwB9yZSy0jUengQqCFdfnBhgsUGmWh6z3MwFJeM/mHgvdWoTCucktnQ4 k5Nw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=B1mFIm1m; 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 4si12770010ejz.429.2020.04.16.13.15.24; Thu, 16 Apr 2020 13:15: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; dkim=pass header.i=@kernel.org header.s=default header.b=B1mFIm1m; 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 S2409681AbgDPOGx (ORCPT + 99 others); Thu, 16 Apr 2020 10:06:53 -0400 Received: from mail.kernel.org ([198.145.29.99]:57852 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2898456AbgDPNoh (ORCPT ); Thu, 16 Apr 2020 09:44:37 -0400 Received: from localhost (83-86-89-107.cable.dynamic.v4.ziggo.nl [83.86.89.107]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 020B7208E4; Thu, 16 Apr 2020 13:44:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1587044676; bh=EcDjb+tFM4yNiTfg1D6Ed/fB5P+qg1QBJfyiwJqtlsY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=B1mFIm1mgxIiGnRJacIO4RelpMkHs2xnMwiIU/qq8aVTe/VTzr0nJvLIPlLLxb79Y yWQAwoMnKVJJ6YYP9SVo7mPIop4lbCd17cGkleifFnGa4pAtcPKnv87agK9wQqbm0e ZWeZnKWnrluH9MHE8yZdzWoN7zQRms4piw8jH6dA= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Dongchun Zhu , Tomasz Figa , Sakari Ailus , Mauro Carvalho Chehab , Sasha Levin Subject: [PATCH 5.4 057/232] media: i2c: ov5695: Fix power on and off sequences Date: Thu, 16 Apr 2020 15:22:31 +0200 Message-Id: <20200416131322.683971780@linuxfoundation.org> X-Mailer: git-send-email 2.26.1 In-Reply-To: <20200416131316.640996080@linuxfoundation.org> References: <20200416131316.640996080@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Dongchun Zhu [ Upstream commit f1a64f56663e9d03e509439016dcbddd0166b2da ] >From the measured hardware signal, OV5695 reset pin goes high for a short period of time during boot-up. From the sensor specification, the reset pin is active low and the DT binding defines the pin as active low, which means that the values set by the driver are inverted and thus the value requested in probe ends up high. Fix it by changing probe to request the reset GPIO initialized to high, which makes the initial state of the physical signal low. In addition, DOVDD rising must occur before DVDD rising from spec., but regulator_bulk_enable() API enables all the regulators asynchronously. Use an explicit loops of regulator_enable() instead. For power off sequence, it is required that DVDD falls first. Given the bulk API does not give any guarantee about the order of regulators, change the driver to use regulator_disable() instead. The sensor also requires a delay between reset high and first I2C transaction, which was assumed to be 8192 XVCLK cycles, but 1ms is recommended by the vendor. Fix this as well. Signed-off-by: Dongchun Zhu Signed-off-by: Tomasz Figa Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Sasha Levin --- drivers/media/i2c/ov5695.c | 49 ++++++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/drivers/media/i2c/ov5695.c b/drivers/media/i2c/ov5695.c index 34b7046d97021..1adcd1ed16641 100644 --- a/drivers/media/i2c/ov5695.c +++ b/drivers/media/i2c/ov5695.c @@ -971,16 +971,9 @@ unlock_and_return: return ret; } -/* Calculate the delay in us by clock rate and clock cycles */ -static inline u32 ov5695_cal_delay(u32 cycles) -{ - return DIV_ROUND_UP(cycles, OV5695_XVCLK_FREQ / 1000 / 1000); -} - static int __ov5695_power_on(struct ov5695 *ov5695) { - int ret; - u32 delay_us; + int i, ret; struct device *dev = &ov5695->client->dev; ret = clk_prepare_enable(ov5695->xvclk); @@ -991,21 +984,28 @@ static int __ov5695_power_on(struct ov5695 *ov5695) gpiod_set_value_cansleep(ov5695->reset_gpio, 1); - ret = regulator_bulk_enable(OV5695_NUM_SUPPLIES, ov5695->supplies); - if (ret < 0) { - dev_err(dev, "Failed to enable regulators\n"); - goto disable_clk; + /* + * The hardware requires the regulators to be powered on in order, + * so enable them one by one. + */ + for (i = 0; i < OV5695_NUM_SUPPLIES; i++) { + ret = regulator_enable(ov5695->supplies[i].consumer); + if (ret) { + dev_err(dev, "Failed to enable %s: %d\n", + ov5695->supplies[i].supply, ret); + goto disable_reg_clk; + } } gpiod_set_value_cansleep(ov5695->reset_gpio, 0); - /* 8192 cycles prior to first SCCB transaction */ - delay_us = ov5695_cal_delay(8192); - usleep_range(delay_us, delay_us * 2); + usleep_range(1000, 1200); return 0; -disable_clk: +disable_reg_clk: + for (--i; i >= 0; i--) + regulator_disable(ov5695->supplies[i].consumer); clk_disable_unprepare(ov5695->xvclk); return ret; @@ -1013,9 +1013,22 @@ disable_clk: static void __ov5695_power_off(struct ov5695 *ov5695) { + struct device *dev = &ov5695->client->dev; + int i, ret; + clk_disable_unprepare(ov5695->xvclk); gpiod_set_value_cansleep(ov5695->reset_gpio, 1); - regulator_bulk_disable(OV5695_NUM_SUPPLIES, ov5695->supplies); + + /* + * The hardware requires the regulators to be powered off in order, + * so disable them one by one. + */ + for (i = OV5695_NUM_SUPPLIES - 1; i >= 0; i--) { + ret = regulator_disable(ov5695->supplies[i].consumer); + if (ret) + dev_err(dev, "Failed to disable %s: %d\n", + ov5695->supplies[i].supply, ret); + } } static int __maybe_unused ov5695_runtime_resume(struct device *dev) @@ -1285,7 +1298,7 @@ static int ov5695_probe(struct i2c_client *client, if (clk_get_rate(ov5695->xvclk) != OV5695_XVCLK_FREQ) dev_warn(dev, "xvclk mismatched, modes are based on 24MHz\n"); - ov5695->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); + ov5695->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); if (IS_ERR(ov5695->reset_gpio)) { dev_err(dev, "Failed to get reset-gpios\n"); return -EINVAL; -- 2.20.1