aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/bcm27xx/patches-5.15/950-0482-regulator-rpi-panel-Serialise-operations.patch
diff options
context:
space:
mode:
authorÁlvaro Fernández Rojas <noltari@gmail.com>2022-05-16 23:40:32 +0200
committerÁlvaro Fernández Rojas <noltari@gmail.com>2022-05-17 15:11:22 +0200
commit20ea6adbf199097c4f5f591ffee088340630dae4 (patch)
treed6719d95e136611a1c25bbf7789652d6d402779d /target/linux/bcm27xx/patches-5.15/950-0482-regulator-rpi-panel-Serialise-operations.patch
parentbca05bd072180dc38ef740b37ded9572a6db1981 (diff)
downloadupstream-20ea6adbf199097c4f5f591ffee088340630dae4.tar.gz
upstream-20ea6adbf199097c4f5f591ffee088340630dae4.tar.bz2
upstream-20ea6adbf199097c4f5f591ffee088340630dae4.zip
bcm27xx: add support for linux v5.15
Build system: x86_64 Build-tested: bcm2708, bcm2709, bcm2710, bcm2711 Run-tested: bcm2708/RPiB+, bcm2709/RPi3B, bcm2710/RPi3B, bcm2711/RPi4B Signed-off-by: Marty Jones <mj8263788@gmail.com> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Diffstat (limited to 'target/linux/bcm27xx/patches-5.15/950-0482-regulator-rpi-panel-Serialise-operations.patch')
-rw-r--r--target/linux/bcm27xx/patches-5.15/950-0482-regulator-rpi-panel-Serialise-operations.patch255
1 files changed, 255 insertions, 0 deletions
diff --git a/target/linux/bcm27xx/patches-5.15/950-0482-regulator-rpi-panel-Serialise-operations.patch b/target/linux/bcm27xx/patches-5.15/950-0482-regulator-rpi-panel-Serialise-operations.patch
new file mode 100644
index 0000000000..67543ea197
--- /dev/null
+++ b/target/linux/bcm27xx/patches-5.15/950-0482-regulator-rpi-panel-Serialise-operations.patch
@@ -0,0 +1,255 @@
+From 354dfe9793ff5f814830c6841ca07ef04bfd66e9 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Wed, 8 Sep 2021 15:02:05 +0100
+Subject: [PATCH] regulator: rpi-panel: Serialise operations.
+
+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 <dave.stevenson@raspberrypi.com>
+---
+ .../regulator/rpi-panel-attiny-regulator.c | 91 ++++++++++++++++---
+ 1 file changed, 80 insertions(+), 11 deletions(-)
+
+--- 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(struc
+ */
+ 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(s
+ usleep_range(10000, 12000);
+ }
+
++ mutex_unlock(lock);
++
+ if (ret < 0)
+ return ret;
+
+@@ -125,10 +153,13 @@ static const struct regulator_desc attin
+
+ 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 b
+ 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_c
+ 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_c
+ 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,24 +255,45 @@ static int attiny_i2c_probe(struct i2c_c
+ 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;
+ }
+
+ static const struct of_device_id attiny_dt_ids[] = {
+@@ -240,6 +308,7 @@ static struct i2c_driver attiny_regulato
+ .of_match_table = of_match_ptr(attiny_dt_ids),
+ },
+ .probe = attiny_i2c_probe,
++ .remove = attiny_i2c_remove,
+ };
+
+ module_i2c_driver(attiny_regulator_driver);