Received: by 2002:a05:6a10:af89:0:0:0:0 with SMTP id iu9csp1405961pxb; Fri, 21 Jan 2022 17:54:47 -0800 (PST) X-Google-Smtp-Source: ABdhPJxnnoY4Lmc2M8rxxe8JDjP6rpIGDcUbPSg3wHQQaVh4bv8+7GKaBk5NyM50Rya+LjW8QluN X-Received: by 2002:a17:902:e887:b0:14b:457:a7e6 with SMTP id w7-20020a170902e88700b0014b0457a7e6mr6236893plg.161.1642816486848; Fri, 21 Jan 2022 17:54:46 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1642816486; cv=none; d=google.com; s=arc-20160816; b=xrj9UR23/qOQKQ0UMzTx8GN6Sk2fxW9oMmkZM0+r7i+nNbb7RycTEoC4wBKIhJvzcv eoUddlJllYKU4FxRgjvSHzQm5uKSMcRq/m3CWe/WMm65VsnVpUEgII4VWeSEeDLZnLgc pGVpvtCZDBN7Tq4UxUrDNCtWa0enZeaHKWikRB2Yl/DtIUAZ32GY6Hgyg2A2ibM0jX5q z42Ka4PSMj1FRO57BdlAR4dXjX2ZgRBZSfnV2VPGY5g0F7rgaZmHAnUEwJfwBhty5KJI DabAlIMwpng8cBnXXjcKX1Ps5ODyOjQbNA3w+YIpCcrncD/13kQSX2aw9aujpVxlajKj BZ5Q== 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=SUUIVNv+WUJ74hmcWqkljh4cPVNJPcZ+JZobC/eXUDFRSi2fTIQRJ/kWDIJ/6wNTzJ 2N6mwhd9x7SmvYxfye2IEQCTV02D3na7DwoRofQy2qjIGzOoXCz4m8BONOcHimnfV+O1 I/nYe9WMJXWzCE2icGi7gop1EnJZXqWGVdJTTfrvKYTItWIxqV0/VoqbJco1XPyyCsx0 RdIu2bKx4fNgxoGx9hbtvmo1hW78PMj10yv5iiP8EKOY/lcVwbQhcfPj0WFuSU7r2rmC 7RT+jZFa+qIZ2gEqgI+JqtjcrLNgTuriffKc7/zmm0CWTDds+YfyTWAx5DOVva2nTi3R amhg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@collabora.com header.s=mail header.b=Ii0FG1zh; 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 j3si7207293pll.394.2022.01.21.17.54.35; Fri, 21 Jan 2022 17:54:46 -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=Ii0FG1zh; 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 S1381498AbiAUPVn (ORCPT + 99 others); Fri, 21 Jan 2022 10:21:43 -0500 Received: from bhuna.collabora.co.uk ([46.235.227.227]:47812 "EHLO bhuna.collabora.co.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1381527AbiAUPVa (ORCPT ); Fri, 21 Jan 2022 10:21:30 -0500 Received: from [127.0.0.1] (localhost [127.0.0.1]) (Authenticated sender: detlev) with ESMTPSA id C46071F46211 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1642778489; bh=bCIz9lIKmGxNsVU4TA/XNq7Ir5i7GiXO8VWDQOzf+eY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Ii0FG1zha6Ib46oLatCM1En00pYGm/MeAOANcofcs24rTfer5l0gg8s3RexjIB87y Qja5plVupBYOBvcDdDyI6l3IykwYz/rI8d0Ssp0UHu5Bm1Qb93B/C+GIKKmDCrJUJN kGizNNRGuXyMweqFpJmealBRTAs+KMKy6Z2Ku4NFFTfzPPUWeI9Yg2/yLeJJ3kM4mv RRjyTAW5xagp2q/uQxBqyPJ6uzqo6drel/KeWeUvJ4ZfjoOgVfsHncqTeUHe/AClv0 5fso60gAGIpC054EauWh/tbVA15l5Vnn14dptscv7oddx43wJ3GEAhE3w8/R3XjeFu XkqmpcLrAMHpg== From: Detlev Casanova To: linux-kernel@vger.kernel.org Cc: Dave Stevenson , Liam Girdwood , Mark Brown Subject: [PATCH v2 3/9] regulator: rpi-panel: Serialise operations. Date: Fri, 21 Jan 2022 10:20:50 -0500 Message-Id: <20220121152056.2044551-4-detlev.casanova@collabora.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220121152056.2044551-1-detlev.casanova@collabora.com> References: <20220121152056.2044551-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