diff options
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 |
commit | 20ea6adbf199097c4f5f591ffee088340630dae4 (patch) | |
tree | d6719d95e136611a1c25bbf7789652d6d402779d /target/linux/bcm27xx/patches-5.15/950-0482-regulator-rpi-panel-Serialise-operations.patch | |
parent | bca05bd072180dc38ef740b37ded9572a6db1981 (diff) | |
download | upstream-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.patch | 255 |
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); |