From f31fb2fe1ea4a03279c538612e7ecf0e5017639a Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 21 Sep 2018 12:13:07 +0200 Subject: [PATCH 01/20] pwm: tegra: Remove gratuituous blank line It's common to follow a device tree ID table by the MODULE_DEVICE_TABLE immediately, without an extra blank line between. Signed-off-by: Thierry Reding Signed-off-by: Thierry Reding --- drivers/pwm/pwm-tegra.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/pwm/pwm-tegra.c b/drivers/pwm/pwm-tegra.c index f8ebbece57b7..48c4595a0ffc 100644 --- a/drivers/pwm/pwm-tegra.c +++ b/drivers/pwm/pwm-tegra.c @@ -300,7 +300,6 @@ static const struct of_device_id tegra_pwm_of_match[] = { { .compatible = "nvidia,tegra186-pwm", .data = &tegra186_pwm_soc }, { } }; - MODULE_DEVICE_TABLE(of, tegra_pwm_of_match); static const struct dev_pm_ops tegra_pwm_pm_ops = { From fe650c8ba7c9dde2816d09e335b0be37757e49df Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 12 Oct 2018 12:12:24 +0200 Subject: [PATCH 02/20] ACPI / PM: Export acpi_device_get_power() for use by modular build drivers Export acpi_device_get_power() for use by modular build drivers. Reviewed-by: Andy Shevchenko Acked-by: Rafael J. Wysocki Signed-off-by: Hans de Goede Signed-off-by: Thierry Reding --- drivers/acpi/device_pm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index a7c2673ffd36..824ae985ad93 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c @@ -126,6 +126,7 @@ int acpi_device_get_power(struct acpi_device *device, int *state) return 0; } +EXPORT_SYMBOL(acpi_device_get_power); static int acpi_dev_pm_explicit_set(struct acpi_device *adev, int state) { From 1688c8717118f37191d824862a006c8373d261de Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 12 Oct 2018 12:12:25 +0200 Subject: [PATCH 03/20] pwm: lpss: Add ACPI HID for second PWM controller on Cherry Trail devices The second PWM controller on Cherry Trail devices uses a separate ACPI HID: "80862289", add this so that the driver will properly bind to the second PWM controller. The second PWM controller is usually not used, the main thing gained by this is properly putting the PWM controller in D3 on suspend. Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Thierry Reding --- drivers/pwm/pwm-lpss-platform.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/pwm/pwm-lpss-platform.c b/drivers/pwm/pwm-lpss-platform.c index 5561b9e190f8..7304f36ee715 100644 --- a/drivers/pwm/pwm-lpss-platform.c +++ b/drivers/pwm/pwm-lpss-platform.c @@ -81,6 +81,7 @@ static SIMPLE_DEV_PM_OPS(pwm_lpss_platform_pm_ops, static const struct acpi_device_id pwm_lpss_acpi_match[] = { { "80860F09", (unsigned long)&pwm_lpss_byt_info }, { "80862288", (unsigned long)&pwm_lpss_bsw_info }, + { "80862289", (unsigned long)&pwm_lpss_bsw_info }, { "80865AC8", (unsigned long)&pwm_lpss_bxt_info }, { }, }; From 9dc419b6c7e4bb67c0966758c1e4c9a9c9a4309d Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 12 Oct 2018 12:12:26 +0200 Subject: [PATCH 04/20] pwm: lpss: Move struct pwm_lpss_chip definition to the header file Move struct pwm_lpss_chip definition from pwm-lpss.c to pwm-lpss.h, so that the pci/platform drivers can access the info member (struct pwm_lpss_boardinfo *). This is a preparation patch for adding platform specific quirks, which the drivers need access to, to pwm_lpss_boardinfo. Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Thierry Reding --- drivers/pwm/pwm-lpss.c | 9 --------- drivers/pwm/pwm-lpss.h | 9 ++++++++- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/pwm/pwm-lpss.c b/drivers/pwm/pwm-lpss.c index 4721a264bac2..e602835fd6de 100644 --- a/drivers/pwm/pwm-lpss.c +++ b/drivers/pwm/pwm-lpss.c @@ -32,15 +32,6 @@ /* Size of each PWM register space if multiple */ #define PWM_SIZE 0x400 -#define MAX_PWMS 4 - -struct pwm_lpss_chip { - struct pwm_chip chip; - void __iomem *regs; - const struct pwm_lpss_boardinfo *info; - u32 saved_ctrl[MAX_PWMS]; -}; - static inline struct pwm_lpss_chip *to_lpwm(struct pwm_chip *chip) { return container_of(chip, struct pwm_lpss_chip, chip); diff --git a/drivers/pwm/pwm-lpss.h b/drivers/pwm/pwm-lpss.h index 7a4238ad1fcb..8f029ed263af 100644 --- a/drivers/pwm/pwm-lpss.h +++ b/drivers/pwm/pwm-lpss.h @@ -16,7 +16,14 @@ #include #include -struct pwm_lpss_chip; +#define MAX_PWMS 4 + +struct pwm_lpss_chip { + struct pwm_chip chip; + void __iomem *regs; + const struct pwm_lpss_boardinfo *info; + u32 saved_ctrl[MAX_PWMS]; +}; struct pwm_lpss_boardinfo { unsigned long clk_rate; From 6a425ecd19a2c0e19a501323216ecf987de07841 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 12 Oct 2018 12:12:27 +0200 Subject: [PATCH 05/20] pwm: lpss: Check PWM powerstate after resume on Cherry Trail devices The _PS0 method for the integrated graphics on some Cherry Trail devices (observed on a HP Pavilion X2 10-p0XX) turns on the PWM chip (puts it in D0), causing an inconsistency between the state the pm-core thinks it is in (left runtime suspended as it was before the suspend/resume) and the state it actually is in. Interestingly enough this is done on a device where the pwm controller is not used for the backlight at all, since it uses an eDP panel. On devices where the PWM is used this is not a problem since we will resume it ourselves anyways. This inconsistency causes us to never suspend the pwm controller again, which causes the device to not be able to reach S0ix states when suspended. This commit adds a resume-complete handler, which when we think the device is still run-time suspended checks the actual power-state and if necessary updates the rpm-core's internal state. This fixes the Pavilion X2 10-p0XX not reaching S0ix states when suspended. Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Thierry Reding --- drivers/pwm/pwm-lpss-platform.c | 25 ++++++++++++++++++++++--- drivers/pwm/pwm-lpss.h | 2 ++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/drivers/pwm/pwm-lpss-platform.c b/drivers/pwm/pwm-lpss-platform.c index 7304f36ee715..b6edf8af26cc 100644 --- a/drivers/pwm/pwm-lpss-platform.c +++ b/drivers/pwm/pwm-lpss-platform.c @@ -30,6 +30,7 @@ static const struct pwm_lpss_boardinfo pwm_lpss_bsw_info = { .clk_rate = 19200000, .npwm = 1, .base_unit_bits = 16, + .check_power_on_resume = true, }; /* Broxton */ @@ -74,9 +75,27 @@ static int pwm_lpss_remove_platform(struct platform_device *pdev) return pwm_lpss_remove(lpwm); } -static SIMPLE_DEV_PM_OPS(pwm_lpss_platform_pm_ops, - pwm_lpss_suspend, - pwm_lpss_resume); +static void pwm_lpss_complete(struct device *dev) +{ + struct pwm_lpss_chip *lpwm = dev_get_drvdata(dev); + int ret, state; + + /* The PWM may be turned on by AML code, update our state to match */ + if (pm_runtime_suspended(dev) && lpwm->info->check_power_on_resume) { + pm_runtime_disable(dev); + + ret = acpi_device_get_power(ACPI_COMPANION(dev), &state); + if (ret == 0 && state == ACPI_STATE_D0) + pm_runtime_set_active(dev); + + pm_runtime_enable(dev); + } +} + +static const struct dev_pm_ops pwm_lpss_platform_pm_ops = { + .complete = pwm_lpss_complete, + SET_SYSTEM_SLEEP_PM_OPS(pwm_lpss_suspend, pwm_lpss_resume) +}; static const struct acpi_device_id pwm_lpss_acpi_match[] = { { "80860F09", (unsigned long)&pwm_lpss_byt_info }, diff --git a/drivers/pwm/pwm-lpss.h b/drivers/pwm/pwm-lpss.h index 8f029ed263af..1a2575d25bea 100644 --- a/drivers/pwm/pwm-lpss.h +++ b/drivers/pwm/pwm-lpss.h @@ -30,6 +30,8 @@ struct pwm_lpss_boardinfo { unsigned int npwm; unsigned long base_unit_bits; bool bypass; + /* Some devices have AML code messing with the state underneath us */ + bool check_power_on_resume; }; struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev, struct resource *r, From 42885551cedb45961879d2fc3dc3c4dc545cc23e Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 12 Oct 2018 12:12:28 +0200 Subject: [PATCH 06/20] pwm: lpss: Release runtime-pm reference from the driver's remove callback For each pwm output which gets enabled through pwm_lpss_apply(), we do a pm_runtime_get_sync(). This commit adds pm_runtime_put() calls to pwm_lpss_remove() to balance these when the driver gets removed with some of the outputs still enabled. Fixes: f080be27d7d9 ("pwm: lpss: Add support for runtime PM") Acked-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Thierry Reding --- drivers/pwm/pwm-lpss.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/pwm/pwm-lpss.c b/drivers/pwm/pwm-lpss.c index e602835fd6de..723ca9de8325 100644 --- a/drivers/pwm/pwm-lpss.c +++ b/drivers/pwm/pwm-lpss.c @@ -205,6 +205,12 @@ EXPORT_SYMBOL_GPL(pwm_lpss_probe); int pwm_lpss_remove(struct pwm_lpss_chip *lpwm) { + int i; + + for (i = 0; i < lpwm->info->npwm; i++) { + if (pwm_is_enabled(&lpwm->chip.pwms[i])) + pm_runtime_put(lpwm->chip.dev); + } return pwmchip_remove(&lpwm->chip); } EXPORT_SYMBOL_GPL(pwm_lpss_remove); From 280fec4c3ad6701567d7d840506b9b1463a48b71 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 12 Oct 2018 12:12:29 +0200 Subject: [PATCH 07/20] pwm: lpss: Add get_state callback Add a get_state callback so that the initial state correctly reflects the actual hardware state. Cc: Andy Shevchenko Acked-by: Jani Nikula Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Thierry Reding --- drivers/pwm/pwm-lpss.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/drivers/pwm/pwm-lpss.c b/drivers/pwm/pwm-lpss.c index 723ca9de8325..ea93ef9f3672 100644 --- a/drivers/pwm/pwm-lpss.c +++ b/drivers/pwm/pwm-lpss.c @@ -159,8 +159,42 @@ static int pwm_lpss_apply(struct pwm_chip *chip, struct pwm_device *pwm, return 0; } +/* This function gets called once from pwmchip_add to get the initial state */ +static void pwm_lpss_get_state(struct pwm_chip *chip, struct pwm_device *pwm, + struct pwm_state *state) +{ + struct pwm_lpss_chip *lpwm = to_lpwm(chip); + unsigned long base_unit_range; + unsigned long long base_unit, freq, on_time_div; + u32 ctrl; + + base_unit_range = BIT(lpwm->info->base_unit_bits); + + ctrl = pwm_lpss_read(pwm); + on_time_div = 255 - (ctrl & PWM_ON_TIME_DIV_MASK); + base_unit = (ctrl >> PWM_BASE_UNIT_SHIFT) & (base_unit_range - 1); + + freq = base_unit * lpwm->info->clk_rate; + do_div(freq, base_unit_range); + if (freq == 0) + state->period = NSEC_PER_SEC; + else + state->period = NSEC_PER_SEC / (unsigned long)freq; + + on_time_div *= state->period; + do_div(on_time_div, 255); + state->duty_cycle = on_time_div; + + state->polarity = PWM_POLARITY_NORMAL; + state->enabled = !!(ctrl & PWM_ENABLE); + + if (state->enabled) + pm_runtime_get(chip->dev); +} + static const struct pwm_ops pwm_lpss_ops = { .apply = pwm_lpss_apply, + .get_state = pwm_lpss_get_state, .owner = THIS_MODULE, }; From e4ab5172ea6be4d3a95411d7a7867f3c2be12754 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 22 Aug 2018 00:02:21 +0200 Subject: [PATCH 08/20] pwm: Use SPDX identifier for Renesas drivers Signed-off-by: Wolfram Sang Reviewed-by: Simon Horman Signed-off-by: Thierry Reding --- drivers/pwm/pwm-rcar.c | 5 +---- drivers/pwm/pwm-renesas-tpu.c | 10 +--------- 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/drivers/pwm/pwm-rcar.c b/drivers/pwm/pwm-rcar.c index 748f614d5375..a41812fc6f95 100644 --- a/drivers/pwm/pwm-rcar.c +++ b/drivers/pwm/pwm-rcar.c @@ -1,11 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* * R-Car PWM Timer driver * * Copyright (C) 2015 Renesas Electronics Corporation - * - * This is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. */ #include diff --git a/drivers/pwm/pwm-renesas-tpu.c b/drivers/pwm/pwm-renesas-tpu.c index 29267d12fb4c..4a855a21b782 100644 --- a/drivers/pwm/pwm-renesas-tpu.c +++ b/drivers/pwm/pwm-renesas-tpu.c @@ -1,16 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* * R-Mobile TPU PWM driver * * Copyright (C) 2012 Renesas Solutions Corp. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. */ #include From 01e194bbd64a7c65af428561fa97653be8b74564 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Sat, 22 Sep 2018 22:43:24 +0300 Subject: [PATCH 09/20] dt-bindings: pwm: renesas: tpu: Fix "compatible" prop description The "compatible" property description contradicts even the example given: it only says that there must be a single value while the example has the fallback value too -- which makes much more sense. Moreover, the generic property value is misdocumented as being R-Car (and RZ/G1) specific... Fixes: 382457e562bb ("pwm: renesas-tpu: Add DT support") Fixes: 3ba111a01822 ("dt-bindings: pwm: renesas-tpu: Document r8a774[35] support") Signed-off-by: Sergei Shtylyov Signed-off-by: Thierry Reding --- Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt b/Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt index d53a16715da6..d276693cf301 100644 --- a/Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt +++ b/Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt @@ -2,13 +2,14 @@ Required Properties: - - compatible: should be one of the following. + - compatible: must contain one or more of the following: - "renesas,tpu-r8a73a4": for R8A73A4 (R-Mobile APE6) compatible PWM controller. - "renesas,tpu-r8a7740": for R8A7740 (R-Mobile A1) compatible PWM controller. - "renesas,tpu-r8a7743": for R8A7743 (RZ/G1M) compatible PWM controller. - "renesas,tpu-r8a7745": for R8A7745 (RZ/G1E) compatible PWM controller. - "renesas,tpu-r8a7790": for R8A7790 (R-Car H2) compatible PWM controller. - - "renesas,tpu": for generic R-Car and RZ/G1 TPU PWM controller. + - "renesas,tpu": for the generic TPU PWM controller; this is a fallback for + the entries listed above. - reg: Base address and length of each memory resource used by the PWM controller hardware module. From 2360fc6a704e8dc1f8183a048980052bfe64388b Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Mon, 1 Oct 2018 22:57:39 +0300 Subject: [PATCH 10/20] dt-bindings: pwm: renesas: pwm-rcar: Document R8A779{7|8}0 bindings Document the R-Car V3{M|H} (R8A779{7|8}0) SoC in the Renesas R-Car PWM bindings. R8A77970's hardware is a generic R-Car gen3 PWM, while R8A77980 has an extra error injection register... Signed-off-by: Sergei Shtylyov Reviewed-by: Geert Uytterhoeven Reviewed-by: Simon Horman Signed-off-by: Thierry Reding --- Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt b/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt index e1ef6afbe3a7..e68a34e57ff6 100644 --- a/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt +++ b/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt @@ -12,6 +12,8 @@ Required Properties: - "renesas,pwm-r8a7795": for R-Car H3 - "renesas,pwm-r8a7796": for R-Car M3-W - "renesas,pwm-r8a77965": for R-Car M3-N + - "renesas,pwm-r8a77970": for R-Car V3M + - "renesas,pwm-r8a77980": for R-Car V3H - "renesas,pwm-r8a77990": for R-Car E3 - "renesas,pwm-r8a77995": for R-Car D3 - reg: base address and length of the registers block for the PWM. From 136d822a9e4e947609d2fbf8d3fa5f15b8c20970 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Sat, 22 Sep 2018 22:57:29 +0300 Subject: [PATCH 11/20] dt-bindings: pwm: renesas: tpu: Document R8A779{7|8}0 bindings Document the R-Car V3{M|H} (R8A779{7|8}0) SoC in the Renesas TPU bindings; the TPU hardware in those is the Renesas standard 4-channel timer pulse unit. Signed-off-by: Sergei Shtylyov Reviewed-by: Geert Uytterhoeven Reviewed-by: Simon Horman Signed-off-by: Thierry Reding --- Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt b/Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt index d276693cf301..af5f4c745597 100644 --- a/Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt +++ b/Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt @@ -8,6 +8,10 @@ Required Properties: - "renesas,tpu-r8a7743": for R8A7743 (RZ/G1M) compatible PWM controller. - "renesas,tpu-r8a7745": for R8A7745 (RZ/G1E) compatible PWM controller. - "renesas,tpu-r8a7790": for R8A7790 (R-Car H2) compatible PWM controller. + - "renesas,tpu-r8a77970": for R8A77970 (R-Car V3M) compatible PWM + controller. + - "renesas,tpu-r8a77980": for R8A77980 (R-Car V3H) compatible PWM + controller. - "renesas,tpu": for the generic TPU PWM controller; this is a fallback for the entries listed above. From a4675881ed71f73f5ea96afda6a1ddc1526fde4d Mon Sep 17 00:00:00 2001 From: Biju Das Date: Thu, 4 Oct 2018 17:17:19 +0100 Subject: [PATCH 12/20] dt-bindings: pwm: rcar: Add r8a7744 support Document RZ/G1N (R8A7744) SoC bindings. Signed-off-by: Biju Das Reviewed-by: Chris Paterson Reviewed-by: Simon Horman Signed-off-by: Thierry Reding --- Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt b/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt index e68a34e57ff6..bdbf1e4070e2 100644 --- a/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt +++ b/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt @@ -3,6 +3,7 @@ Required Properties: - compatible: should be "renesas,pwm-rcar" and one of the following. - "renesas,pwm-r8a7743": for RZ/G1M + - "renesas,pwm-r8a7744": for RZ/G1N - "renesas,pwm-r8a7745": for RZ/G1E - "renesas,pwm-r8a7778": for R-Car M1A - "renesas,pwm-r8a7779": for R-Car H1 From d5a7060022cd443cc6a054bc73383acac6a8f53d Mon Sep 17 00:00:00 2001 From: Biju Das Date: Thu, 4 Oct 2018 17:21:34 +0100 Subject: [PATCH 13/20] dt-bindings: pwm: renesas-tpu: Document r8a7744 support Document r8a7744 specific compatible strings. No driver change is needed as the fallback compatible string "renesas,tpu" activates the right code in the driver. Signed-off-by: Biju Das Reviewed-by: Chris Paterson Reviewed-by: Simon Horman Signed-off-by: Thierry Reding --- Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt b/Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt index af5f4c745597..848a92b53d81 100644 --- a/Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt +++ b/Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt @@ -6,6 +6,7 @@ Required Properties: - "renesas,tpu-r8a73a4": for R8A73A4 (R-Mobile APE6) compatible PWM controller. - "renesas,tpu-r8a7740": for R8A7740 (R-Mobile A1) compatible PWM controller. - "renesas,tpu-r8a7743": for R8A7743 (RZ/G1M) compatible PWM controller. + - "renesas,tpu-r8a7744": for R8A7744 (RZ/G1N) compatible PWM controller. - "renesas,tpu-r8a7745": for R8A7745 (RZ/G1E) compatible PWM controller. - "renesas,tpu-r8a7790": for R8A7790 (R-Car H2) compatible PWM controller. - "renesas,tpu-r8a77970": for R8A77970 (R-Car V3M) compatible PWM From c289d6625237aa785b484b4e94c23b3b91ea7e60 Mon Sep 17 00:00:00 2001 From: Fabrice Gasnier Date: Mon, 1 Oct 2018 15:23:56 +0200 Subject: [PATCH 14/20] Revert "pwm: Set class for exported channels in sysfs" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 7e5d1fd75c3dde9fc10c4472b9368089d1b81d00 ("pwm: Set class for exported channels in sysfs") as it causes regression with multiple pwm chip[1], when exporting a pwm channel (echo X > export): - ABI (Documentation/ABI/testing/sysfs-class-pwm) states pwmX should be created in /sys/class/pwm/pwmchipN/pwmX - Reverted patch causes new entry to be also created directly in /sys/class/pwm/pwmX - 1st time, exporting pwmX will create an entry in /sys/class/pwm/pwmX - class attributes are added under pwmX folder, such as export, unexport npwm, symlinks. This is wrong as it belongs to pwmchipN. It may cause bad behavior and report wrong values. - when another export happens on another pwmchip, it can't be created (e.g. -EEXIST). This is causing the issue with multiple pwmchip. Example on stm32 (stm32429i-eval) platform: $ ls /sys/class/pwm pwmchip0 pwmchip4 $ cd /sys/class/pwm/pwmchip0/ $ echo 0 > export $ ls /sys/class/pwm pwm0 pwmchip0 pwmchip4 $ cd /sys/class/pwm/pwmchip4/ $ echo 0 > export sysfs: cannot create duplicate filename '/class/pwm/pwm0' ...Exception stack follows... This is also seen on other platform [2] [1] https://lkml.org/lkml/2018/9/25/713 [2] https://lkml.org/lkml/2018/9/25/447 Signed-off-by: Fabrice Gasnier Tested-by: Gottfried Haider Tested-by: Michal Vokáč Signed-off-by: Thierry Reding --- drivers/pwm/sysfs.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/pwm/sysfs.c b/drivers/pwm/sysfs.c index 7c71cdb8a9d8..4726d43aaa0c 100644 --- a/drivers/pwm/sysfs.c +++ b/drivers/pwm/sysfs.c @@ -263,7 +263,6 @@ static int pwm_export_child(struct device *parent, struct pwm_device *pwm) export->pwm = pwm; mutex_init(&export->lock); - export->child.class = parent->class; export->child.release = pwm_export_release; export->child.parent = parent; export->child.devt = MKDEV(0, 0); From 552c02e3e7cfe2744b59de285aaea70021ae95c9 Mon Sep 17 00:00:00 2001 From: Fabrice Gasnier Date: Mon, 1 Oct 2018 15:23:57 +0200 Subject: [PATCH 15/20] pwm: Send a uevent on the pwmchip device upon channel sysfs (un)export MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch sends a uevent (KOBJ_CHANGE) on the pwmchipN device, everytime a pwmX channel has been exported/unexported via sysfs. This allows udev to implement rules on such events, like: SUBSYSTEM=="pwm*", PROGRAM="/bin/sh -c '\ chown -R root:gpio /sys/class/pwm && chmod -R 770 /sys/class/pwm;\ chown -R root:gpio /sys/devices/platform/soc/*.pwm/pwm/pwmchip* && chmod -R 770 /sys/devices/platform/soc/*.pwm/pwm/pwmchip*\ '" This is a replacement patch for commit 7e5d1fd75c3d ("pwm: Set class for exported channels in sysfs"), see [1]. basic testing: $ udevadm monitor --environment & $ echo 0 > /sys/class/pwm/pwmchip0/export KERNEL[197.321736] change /devices/.../pwm/pwmchip0 (pwm) ACTION=change DEVPATH=/devices/.../pwm/pwmchip0 EXPORT=pwm0 SEQNUM=2045 SUBSYSTEM=pwm [1] https://lkml.org/lkml/2018/9/25/713 Signed-off-by: Fabrice Gasnier Tested-by: Gottfried Haider Tested-by: Michal Vokáč Signed-off-by: Thierry Reding --- drivers/pwm/sysfs.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/pwm/sysfs.c b/drivers/pwm/sysfs.c index 4726d43aaa0c..ceb233dd6048 100644 --- a/drivers/pwm/sysfs.c +++ b/drivers/pwm/sysfs.c @@ -249,6 +249,7 @@ static void pwm_export_release(struct device *child) static int pwm_export_child(struct device *parent, struct pwm_device *pwm) { struct pwm_export *export; + char *pwm_prop[2]; int ret; if (test_and_set_bit(PWMF_EXPORTED, &pwm->flags)) @@ -276,6 +277,10 @@ static int pwm_export_child(struct device *parent, struct pwm_device *pwm) export = NULL; return ret; } + pwm_prop[0] = kasprintf(GFP_KERNEL, "EXPORT=pwm%u", pwm->hwpwm); + pwm_prop[1] = NULL; + kobject_uevent_env(&parent->kobj, KOBJ_CHANGE, pwm_prop); + kfree(pwm_prop[0]); return 0; } @@ -288,6 +293,7 @@ static int pwm_unexport_match(struct device *child, void *data) static int pwm_unexport_child(struct device *parent, struct pwm_device *pwm) { struct device *child; + char *pwm_prop[2]; if (!test_and_clear_bit(PWMF_EXPORTED, &pwm->flags)) return -ENODEV; @@ -296,6 +302,11 @@ static int pwm_unexport_child(struct device *parent, struct pwm_device *pwm) if (!child) return -ENODEV; + pwm_prop[0] = kasprintf(GFP_KERNEL, "UNEXPORT=pwm%u", pwm->hwpwm); + pwm_prop[1] = NULL; + kobject_uevent_env(&parent->kobj, KOBJ_CHANGE, pwm_prop); + kfree(pwm_prop[0]); + /* for device_find_child() */ put_device(child); device_unregister(child); From 786e0cfa9d6fc1cc8856c1864c988d233649348c Mon Sep 17 00:00:00 2001 From: Fabrizio Castro Date: Tue, 21 Aug 2018 17:03:46 +0100 Subject: [PATCH 16/20] dt-bindings: pwm: rcar: Add r8a774a1 support Document RZ/G2M (R8A774A1) SoC bindings. Signed-off-by: Fabrizio Castro Reviewed-by: Biju Das Reviewed-by: Simon Horman Reviewed-by: Rob Herring Signed-off-by: Thierry Reding --- Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt b/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt index bdbf1e4070e2..7f31fe7e2093 100644 --- a/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt +++ b/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt @@ -5,6 +5,7 @@ Required Properties: - "renesas,pwm-r8a7743": for RZ/G1M - "renesas,pwm-r8a7744": for RZ/G1N - "renesas,pwm-r8a7745": for RZ/G1E + - "renesas,pwm-r8a774a1": for RZ/G2M - "renesas,pwm-r8a7778": for R-Car M1A - "renesas,pwm-r8a7779": for R-Car H1 - "renesas,pwm-r8a7790": for R-Car H2 From 3c413e7e39224d171ef697277cd4629b59103101 Mon Sep 17 00:00:00 2001 From: Vignesh R Date: Tue, 16 Oct 2018 11:34:01 +0530 Subject: [PATCH 17/20] dt-bindings: pwm: tiecap: Add TI AM654 SoC specific compatible Add a new compatible string "ti,am654-ecap" to support PWM ECAP IP of TI AM654 SoC. Signed-off-by: Vignesh R Reviewed-by: Rob Herring Signed-off-by: Thierry Reding --- Documentation/devicetree/bindings/pwm/pwm-tiecap.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt b/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt index 06a363d9ccef..b9a1d7402128 100644 --- a/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt +++ b/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt @@ -7,6 +7,7 @@ Required properties: for da850 - compatible = "ti,da850-ecap", "ti,am3352-ecap", "ti,am33xx-ecap"; for dra746 - compatible = "ti,dra746-ecap", "ti,am3352-ecap"; for 66ak2g - compatible = "ti,k2g-ecap", "ti,am3352-ecap"; + for am654 - compatible = "ti,am654-ecap", "ti,am3352-ecap"; - #pwm-cells: should be 3. See pwm.txt in this directory for a description of the cells format. The PWM channel index ranges from 0 to 4. The only third cell flag supported by this binding is PWM_POLARITY_INVERTED. From 6f37709fb0a61f09ca96348044c5bb13e333e518 Mon Sep 17 00:00:00 2001 From: Vignesh R Date: Tue, 16 Oct 2018 11:34:02 +0530 Subject: [PATCH 18/20] pwm: Enable TI ECAP driver for ARCH_K3 K3 devices have the same ECAP IP as OMAP SoCs. Enable driver to be built for K3 devices. Also, drop reference to AM33xx in help text, as IP is found on multiple TI SoCs. Signed-off-by: Vignesh R Signed-off-by: Thierry Reding --- drivers/pwm/Kconfig | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index 504d252716f2..27e5dd47a01f 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -447,10 +447,9 @@ config PWM_TEGRA config PWM_TIECAP tristate "ECAP PWM support" - depends on ARCH_OMAP2PLUS || ARCH_DAVINCI_DA8XX || ARCH_KEYSTONE + depends on ARCH_OMAP2PLUS || ARCH_DAVINCI_DA8XX || ARCH_KEYSTONE || ARCH_K3 help - PWM driver support for the ECAP APWM controller found on AM33XX - TI SOC + PWM driver support for the ECAP APWM controller found on TI SOCs To compile this driver as a module, choose M here: the module will be called pwm-tiecap. From 4743765babb278a7d399df5733fc8a6b6bbedf3e Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 14 Oct 2018 17:12:01 +0200 Subject: [PATCH 19/20] pwm: lpss: Force runtime-resume on suspend on Cherry Trail On Cherry Trail devices under Windows the PWM controller used for the backlight is considered part of the GPU even though it is part of the LPSS block and thus is an entirely different independent hardware unit. Because of this on Cherry Trail the GPU's (GFX0 ACPI node) _PS3 and _PS0 methods save and restore the PWM controller registers. If userspace blanks the screen before suspending, such as e.g. GNOME does, then the PWM controller will be runtime-suspended when the suspend starts. This causes the GFX0 _PS? methods to save a value of 0xffffffff for the PWM control register and to restore this value on resume. 0xffffffff is not a valid value for the register and writing this causes problems such as e.g. a flickering backlight. This commit adds a prepare method to the dev_pm_ops and makes it return 0 on Cherry Trail devices forcing a runtime-resume before other device's suspend methods run. This fixes the reading and writing back of 0xffffffff. Since we now always runtime-resume the device on suspend, it will be resumed on resume too and we no longer need to check for the GFX0 _PS0 method having resumed it underneath us, so this commit removes the now no longer necessary complete dev_pm_op. Signed-off-by: Hans de Goede Signed-off-by: Thierry Reding --- drivers/pwm/pwm-lpss-platform.c | 24 +++++++++++------------- drivers/pwm/pwm-lpss.h | 7 +++++-- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/drivers/pwm/pwm-lpss-platform.c b/drivers/pwm/pwm-lpss-platform.c index b6edf8af26cc..757230e1f575 100644 --- a/drivers/pwm/pwm-lpss-platform.c +++ b/drivers/pwm/pwm-lpss-platform.c @@ -30,7 +30,7 @@ static const struct pwm_lpss_boardinfo pwm_lpss_bsw_info = { .clk_rate = 19200000, .npwm = 1, .base_unit_bits = 16, - .check_power_on_resume = true, + .other_devices_aml_touches_pwm_regs = true, }; /* Broxton */ @@ -61,6 +61,7 @@ static int pwm_lpss_probe_platform(struct platform_device *pdev) platform_set_drvdata(pdev, lpwm); + dev_pm_set_driver_flags(&pdev->dev, DPM_FLAG_SMART_PREPARE); pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); @@ -75,25 +76,22 @@ static int pwm_lpss_remove_platform(struct platform_device *pdev) return pwm_lpss_remove(lpwm); } -static void pwm_lpss_complete(struct device *dev) +static int pwm_lpss_prepare(struct device *dev) { struct pwm_lpss_chip *lpwm = dev_get_drvdata(dev); - int ret, state; - /* The PWM may be turned on by AML code, update our state to match */ - if (pm_runtime_suspended(dev) && lpwm->info->check_power_on_resume) { - pm_runtime_disable(dev); + /* + * If other device's AML code touches the PWM regs on suspend/resume + * force runtime-resume the PWM controller to allow this. + */ + if (lpwm->info->other_devices_aml_touches_pwm_regs) + return 0; /* Force runtime-resume */ - ret = acpi_device_get_power(ACPI_COMPANION(dev), &state); - if (ret == 0 && state == ACPI_STATE_D0) - pm_runtime_set_active(dev); - - pm_runtime_enable(dev); - } + return 1; /* If runtime-suspended leave as is */ } static const struct dev_pm_ops pwm_lpss_platform_pm_ops = { - .complete = pwm_lpss_complete, + .prepare = pwm_lpss_prepare, SET_SYSTEM_SLEEP_PM_OPS(pwm_lpss_suspend, pwm_lpss_resume) }; diff --git a/drivers/pwm/pwm-lpss.h b/drivers/pwm/pwm-lpss.h index 1a2575d25bea..3236be835bd9 100644 --- a/drivers/pwm/pwm-lpss.h +++ b/drivers/pwm/pwm-lpss.h @@ -30,8 +30,11 @@ struct pwm_lpss_boardinfo { unsigned int npwm; unsigned long base_unit_bits; bool bypass; - /* Some devices have AML code messing with the state underneath us */ - bool check_power_on_resume; + /* + * On some devices the _PS0/_PS3 AML code of the GPU (GFX0) device + * messes with the PWM0 controllers state, + */ + bool other_devices_aml_touches_pwm_regs; }; struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev, struct resource *r, From 2153bbc12f77fb2203276befc0f0dddbfb023bb1 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 14 Oct 2018 17:12:02 +0200 Subject: [PATCH 20/20] pwm: lpss: Only set update bit if we are actually changing the settings According to the datasheet the update bit must be set if the on-time-div or the base-unit changes. Now that we properly order device resume on Cherry Trail so that the GFX0 _PS0 method no longer exits with an error, we end up with a sequence of events where we are writing the same values twice in a row. First the _PS0 method restores the duty cycle of 0% the GPU driver set on suspend and then the GPU driver first updates just the enabled bit in the pwm_state from 0 to 1, causing us to write the same values again, before restoring the pre-suspend duty-cycle in a separate pwm_apply call. When writing the update bit the second time, without changing any of the values the update bit clears immediately / instantly, instead of staying 1 for a while as usual. After this the next setting of the update bit seems to be ignored, causing the restoring of the pre-suspend duty-cycle to not get applied. This makes the backlight come up with a 0% dutycycle after suspend/resume. Any further brightness changes after this do work. This commit moves the setting of the update bit into pwm_lpss_prepare() and only sets the bit if we have actually changed any of the values. This avoids the setting of the update bit the second time we configure the PWM to 0% dutycycle, this fixes the backlight coming up with 0% duty-cycle after a suspend/resume. Signed-off-by: Hans de Goede Signed-off-by: Thierry Reding --- drivers/pwm/pwm-lpss.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/pwm/pwm-lpss.c b/drivers/pwm/pwm-lpss.c index ea93ef9f3672..2ac3a2aa9e53 100644 --- a/drivers/pwm/pwm-lpss.c +++ b/drivers/pwm/pwm-lpss.c @@ -88,7 +88,7 @@ static void pwm_lpss_prepare(struct pwm_lpss_chip *lpwm, struct pwm_device *pwm, unsigned long long on_time_div; unsigned long c = lpwm->info->clk_rate, base_unit_range; unsigned long long base_unit, freq = NSEC_PER_SEC; - u32 ctrl; + u32 orig_ctrl, ctrl; do_div(freq, period_ns); @@ -105,13 +105,17 @@ static void pwm_lpss_prepare(struct pwm_lpss_chip *lpwm, struct pwm_device *pwm, do_div(on_time_div, period_ns); on_time_div = 255ULL - on_time_div; - ctrl = pwm_lpss_read(pwm); + orig_ctrl = ctrl = pwm_lpss_read(pwm); ctrl &= ~PWM_ON_TIME_DIV_MASK; ctrl &= ~(base_unit_range << PWM_BASE_UNIT_SHIFT); base_unit &= base_unit_range; ctrl |= (u32) base_unit << PWM_BASE_UNIT_SHIFT; ctrl |= on_time_div; - pwm_lpss_write(pwm, ctrl); + + if (orig_ctrl != ctrl) { + pwm_lpss_write(pwm, ctrl); + pwm_lpss_write(pwm, ctrl | PWM_SW_UPDATE); + } } static inline void pwm_lpss_cond_enable(struct pwm_device *pwm, bool cond) @@ -135,7 +139,6 @@ static int pwm_lpss_apply(struct pwm_chip *chip, struct pwm_device *pwm, return ret; } pwm_lpss_prepare(lpwm, pwm, state->duty_cycle, state->period); - pwm_lpss_write(pwm, pwm_lpss_read(pwm) | PWM_SW_UPDATE); pwm_lpss_cond_enable(pwm, lpwm->info->bypass == false); ret = pwm_lpss_wait_for_update(pwm); if (ret) { @@ -148,7 +151,6 @@ static int pwm_lpss_apply(struct pwm_chip *chip, struct pwm_device *pwm, if (ret) return ret; pwm_lpss_prepare(lpwm, pwm, state->duty_cycle, state->period); - pwm_lpss_write(pwm, pwm_lpss_read(pwm) | PWM_SW_UPDATE); return pwm_lpss_wait_for_update(pwm); } } else if (pwm_is_enabled(pwm)) {