Received: by 2002:a05:6a10:af89:0:0:0:0 with SMTP id iu9csp1285307pxb; Fri, 21 Jan 2022 14:21:38 -0800 (PST) X-Google-Smtp-Source: ABdhPJwKCkSxs3z1h7YxF/vZDfnZFOIZKaF41QafEy1QZ4ZyiNG2S1i6LhQDoDQ1nRrJb/AAvRSu X-Received: by 2002:a63:8749:: with SMTP id i70mr4307941pge.41.1642803697895; Fri, 21 Jan 2022 14:21:37 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1642803697; cv=none; d=google.com; s=arc-20160816; b=KFyRs9w2yrDHfH/eXwEMo7RbAHqRE1j/tQ0rdm3IMwNwgZp8/n6rRGbkxqYsg+V3QW 6KZUOu0DVXruYkJUm3AEbsh6RzHoaonyDZuPblhqbQAgYEy7/WnCHsvXIPoIuIjr7mJm u3q3k0MF/hVRP74wgiG1KpH49LccnXyhd/DLNCVvjZmcHiV9eoaDXeFApo1TpHxZJiHG YLPOQpkFzQFIO9/XLVMADNIvD7Dhge5wRH2Cno2gmSCf9jvpihhP0Q8svcGrN6CuGQ1Q dw1y2dUwRFetMAncSNCknTRc+lE0tpf0dfLLubbDsXDHA0LODp7z0DHdvcQ2RKiWR0iX JWSg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=J1KFtLA72rUdpUjOvuGgju8vWnTPzn8zGAKeWhxRcjo=; b=akqFx0RJYNZCLRwrfS0a3mB0k1O1VMThVts4z6jtVxX8z79ZP1C+h/SzpyjukgN58r klr4d6z918RupQZtRGtEifEaHvjXOSlFBffHMjg+8iZdqMFx9ZM+dmZbqU/+r7j4HXid n0vniWS+1Da98H3Hakf8/egSOn3s2mNyDtD91vHRQog6VpaftGuGDB8qGmxfJS4izXDp msihH3E0SbgdH0gWRWklEwjErgoGaf25tWAgolo5c3yKVKvHmy17rYemB9FBInAZVncW OXXTQNMskONftJUbgPRAbi1lGzc+97igpPuyX6o7wsakbQq0HDcQwRo4RXH/626GxLHP zmyw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@collabora.com header.s=mail header.b=gGw6L5wx; 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; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=collabora.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id k7si6514897pll.543.2022.01.21.14.21.24; Fri, 21 Jan 2022 14:21:37 -0800 (PST) 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=@collabora.com header.s=mail header.b=gGw6L5wx; 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; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=collabora.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1376603AbiATPWn (ORCPT + 99 others); Thu, 20 Jan 2022 10:22:43 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44596 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1376574AbiATPWf (ORCPT ); Thu, 20 Jan 2022 10:22:35 -0500 Received: from bhuna.collabora.co.uk (bhuna.collabora.co.uk [IPv6:2a00:1098:0:82:1000:25:2eeb:e3e3]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 96B05C061574 for ; Thu, 20 Jan 2022 07:22:34 -0800 (PST) Received: from [127.0.0.1] (localhost [127.0.0.1]) (Authenticated sender: detlev) with ESMTPSA id F18A61F45342 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1642692153; bh=bCIz9lIKmGxNsVU4TA/XNq7Ir5i7GiXO8VWDQOzf+eY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=gGw6L5wxjvuVIVh/2+jD8cmP3JrWb1Q/aLZ1YAJSAr8PlZOuwBXSftRrvnCCVG1V4 1CvZ6OaWZNLAN9RLUFJsvVISvkurrVMeNADxF/iLwT7riCIyNzrgw9tERRULmZhOmP hn2r/RfcxrRDyy6ym+M2gP8cJmFnD79nY/0a+xgiNpujLzFwp3CZnX5Um33YAIE9Da +w0crlfuxnjDbc70oWsHexjD7MRuI0pg+kIKF3/iLJahAVZLvEgwHHkUyEfbwLMhgs wvT0kRTto6u/GJSSa9qem8T/o1oiQT0a76coFm+fLz0JP0PGThoYI2WOeZzB6kOnPr OVgrgdAyK1e9A== From: Detlev Casanova To: linux-kernel@vger.kernel.org Cc: Dave Stevenson , Liam Girdwood , Mark Brown Subject: [PATCH 3/9] regulator: rpi-panel: Serialise operations. Date: Thu, 20 Jan 2022 10:21:44 -0500 Message-Id: <20220120152150.1952568-4-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220120152150.1952568-1-detlev.casanova@collabora.com> References: <20220120152150.1952568-1-detlev.casanova@collabora.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Dave Stevenson The driver was using the regmap lock to serialise the individual accesses, but we really need to protect the timings of enabling the regulators, including any communication with the Atmel. Use a mutex within the driver to control overall accesses to the Atmel, instead of the regmap lock. Signed-off-by: Dave Stevenson --- .../regulator/rpi-panel-attiny-regulator.c | 91 ++++++++++++++++--- 1 file changed, 80 insertions(+), 11 deletions(-) diff --git a/drivers/regulator/rpi-panel-attiny-regulator.c b/drivers/regulator/rpi-panel-attiny-regulator.c index 00fb69efcfa2..a4af7adad2b5 100644 --- a/drivers/regulator/rpi-panel-attiny-regulator.c +++ b/drivers/regulator/rpi-panel-attiny-regulator.c @@ -27,18 +27,28 @@ #define REG_POWERON 0x85 #define REG_PWM 0x86 +struct attiny_lcd { + /* lock to serialise overall accesses to the Atmel */ + struct mutex lock; + struct regmap *regmap; +}; + static const struct regmap_config attiny_regmap_config = { .reg_bits = 8, .val_bits = 8, + .disable_locking = 1, .max_register = REG_PWM, .cache_type = REGCACHE_NONE, }; static int attiny_lcd_power_enable(struct regulator_dev *rdev) { + struct mutex *lock = rdev_get_drvdata(rdev); unsigned int data; int ret, i; + mutex_lock(lock); + regmap_write(rdev->regmap, REG_POWERON, 1); msleep(80); @@ -63,33 +73,49 @@ static int attiny_lcd_power_enable(struct regulator_dev *rdev) */ regmap_write(rdev->regmap, REG_PORTA, BIT(2)); + mutex_unlock(lock); + return 0; } static int attiny_lcd_power_disable(struct regulator_dev *rdev) { + struct mutex *lock = rdev_get_drvdata(rdev); + + mutex_lock(lock); + regmap_write(rdev->regmap, REG_PWM, 0); regmap_write(rdev->regmap, REG_POWERON, 0); msleep(30); + + mutex_unlock(lock); + return 0; } static int attiny_lcd_power_is_enabled(struct regulator_dev *rdev) { + struct mutex *lock = rdev_get_drvdata(rdev); unsigned int data; int ret, i; + mutex_lock(lock); + for (i = 0; i < 10; i++) { ret = regmap_read(rdev->regmap, REG_POWERON, &data); if (!ret) break; usleep_range(10000, 12000); } - if (ret < 0) + if (ret < 0) { + mutex_unlock(lock); return ret; + } - if (!(data & BIT(0))) + if (!(data & BIT(0))) { + mutex_unlock(lock); return 0; + } for (i = 0; i < 10; i++) { ret = regmap_read(rdev->regmap, REG_PORTB, &data); @@ -98,6 +124,8 @@ static int attiny_lcd_power_is_enabled(struct regulator_dev *rdev) usleep_range(10000, 12000); } + mutex_unlock(lock); + if (ret < 0) return ret; @@ -125,10 +153,13 @@ static const struct regulator_desc attiny_regulator = { static int attiny_update_status(struct backlight_device *bl) { - struct regmap *regmap = bl_get_data(bl); + struct attiny_lcd *state = bl_get_data(bl); + struct regmap *regmap = state->regmap; int brightness = bl->props.brightness; int ret, i; + mutex_lock(&state->lock); + if (bl->props.power != FB_BLANK_UNBLANK || bl->props.fb_blank != FB_BLANK_UNBLANK) brightness = 0; @@ -139,20 +170,27 @@ static int attiny_update_status(struct backlight_device *bl) break; } + mutex_unlock(&state->lock); + return ret; } static int attiny_get_brightness(struct backlight_device *bl) { - struct regmap *regmap = bl_get_data(bl); + struct attiny_lcd *state = bl_get_data(bl); + struct regmap *regmap = state->regmap; int ret, brightness, i; + mutex_lock(&state->lock); + for (i = 0; i < 10; i++) { ret = regmap_read(regmap, REG_PWM, &brightness); if (!ret) break; } + mutex_unlock(&state->lock); + if (ret) return ret; @@ -174,22 +212,30 @@ static int attiny_i2c_probe(struct i2c_client *i2c, struct regulator_config config = { }; struct backlight_device *bl; struct regulator_dev *rdev; + struct attiny_lcd *state; struct regmap *regmap; unsigned int data; int ret; + state = devm_kzalloc(&i2c->dev, sizeof(*state), GFP_KERNEL); + if (!state) + return -ENOMEM; + + mutex_init(&state->lock); + i2c_set_clientdata(i2c, state); + regmap = devm_regmap_init_i2c(i2c, &attiny_regmap_config); if (IS_ERR(regmap)) { ret = PTR_ERR(regmap); dev_err(&i2c->dev, "Failed to allocate register map: %d\n", ret); - return ret; + goto error; } ret = regmap_read(regmap, REG_ID, &data); if (ret < 0) { dev_err(&i2c->dev, "Failed to read REG_ID reg: %d\n", ret); - return ret; + goto error; } switch (data) { @@ -198,7 +244,8 @@ static int attiny_i2c_probe(struct i2c_client *i2c, break; default: dev_err(&i2c->dev, "Unknown Atmel firmware revision: 0x%02x\n", data); - return -ENODEV; + ret = -ENODEV; + goto error; } regmap_write(regmap, REG_POWERON, 0); @@ -208,23 +255,44 @@ static int attiny_i2c_probe(struct i2c_client *i2c, config.regmap = regmap; config.of_node = i2c->dev.of_node; config.init_data = &attiny_regulator_default; + config.driver_data = &state->lock; rdev = devm_regulator_register(&i2c->dev, &attiny_regulator, &config); if (IS_ERR(rdev)) { dev_err(&i2c->dev, "Failed to register ATTINY regulator\n"); - return PTR_ERR(rdev); + ret = PTR_ERR(rdev); + goto error; } props.type = BACKLIGHT_RAW; props.max_brightness = 0xff; + + state->regmap = regmap; + bl = devm_backlight_device_register(&i2c->dev, dev_name(&i2c->dev), - &i2c->dev, regmap, &attiny_bl, + &i2c->dev, state, &attiny_bl, &props); - if (IS_ERR(bl)) - return PTR_ERR(bl); + if (IS_ERR(bl)) { + ret = PTR_ERR(bl); + goto error; + } bl->props.brightness = 0xff; + return 0; + +error: + mutex_destroy(&state->lock); + + return ret; +} + +static int attiny_i2c_remove(struct i2c_client *client) +{ + struct attiny_lcd *state = i2c_get_clientdata(client); + + mutex_destroy(&state->lock); + return 0; } @@ -240,6 +308,7 @@ static struct i2c_driver attiny_regulator_driver = { .of_match_table = of_match_ptr(attiny_dt_ids), }, .probe = attiny_i2c_probe, + .remove = attiny_i2c_remove, }; module_i2c_driver(attiny_regulator_driver); -- 2.34.1