RE: [PATCH v2 3/6] drm/edid: abstract OUI conversion to 24-bit int

2021-09-12 Thread Shankar, Uma



> -Original Message-
> From: dri-devel  On Behalf Of Jani 
> Nikula
> Sent: Tuesday, August 31, 2021 7:48 PM
> To: intel-...@lists.freedesktop.org
> Cc: dri-devel@lists.freedesktop.org; ville.syrj...@linux.intel.com; Nikula, 
> Jani
> 
> Subject: [PATCH v2 3/6] drm/edid: abstract OUI conversion to 24-bit int
> 
> Replace the open coded OUI conversion from three bytes to a 24-bit int, as 
> we'll be
> adding one more user shortly. No functional changes.
> 
> Side note: CTA-861 format has the OUI bytes in reverse order.

Looks ok to me.
Reviewed-by: Uma Shankar 

> Signed-off-by: Jani Nikula 
> ---
>  drivers/gpu/drm/drm_edid.c | 17 +++--
>  1 file changed, 7 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index
> 6325877c5fd6..92974b1478bc 100644
> --- a/drivers/gpu/drm/drm_edid.c
> +++ b/drivers/gpu/drm/drm_edid.c
> @@ -49,6 +49,11 @@
>   (((edid)->version > (maj)) || \
>((edid)->version == (maj) && (edid)->revision > (min)))
> 
> +static int oui(u8 first, u8 second, u8 third) {
> + return (first << 16) | (second << 8) | third; }
> +
>  #define EDID_EST_TIMINGS 16
>  #define EDID_STD_TIMINGS 8
>  #define EDID_DETAILED_TIMINGS 4
> @@ -4113,32 +4118,24 @@ cea_db_offsets(const u8 *cea, int *start, int *end)
> 
>  static bool cea_db_is_hdmi_vsdb(const u8 *db)  {
> - int hdmi_id;
> -
>   if (cea_db_tag(db) != VENDOR_BLOCK)
>   return false;
> 
>   if (cea_db_payload_len(db) < 5)
>   return false;
> 
> - hdmi_id = db[1] | (db[2] << 8) | (db[3] << 16);
> -
> - return hdmi_id == HDMI_IEEE_OUI;
> + return oui(db[3], db[2], db[1]) == HDMI_IEEE_OUI;
>  }
> 
>  static bool cea_db_is_hdmi_forum_vsdb(const u8 *db)  {
> - unsigned int oui;
> -
>   if (cea_db_tag(db) != VENDOR_BLOCK)
>   return false;
> 
>   if (cea_db_payload_len(db) < 7)
>   return false;
> 
> - oui = db[3] << 16 | db[2] << 8 | db[1];
> -
> - return oui == HDMI_FORUM_IEEE_OUI;
> + return oui(db[3], db[2], db[1]) == HDMI_FORUM_IEEE_OUI;
>  }
> 
>  static bool cea_db_is_vcdb(const u8 *db)
> --
> 2.30.2



RE: [Intel-gfx] [PATCH v2 2/6] drm/displayid: add DisplayID v2.0 data blocks and primary use cases

2021-09-12 Thread Shankar, Uma



> -Original Message-
> From: Intel-gfx  On Behalf Of Jani 
> Nikula
> Sent: Tuesday, August 31, 2021 7:48 PM
> To: intel-...@lists.freedesktop.org
> Cc: dri-devel@lists.freedesktop.org; ville.syrj...@linux.intel.com; Nikula, 
> Jani
> 
> Subject: [Intel-gfx] [PATCH v2 2/6] drm/displayid: add DisplayID v2.0 data 
> blocks and
> primary use cases
> 
> DisplayID v2.0 changes the data block identifiers and product types (now 
> called
> primary use cases).

Looks ok to me.
Reviewed-by: Uma Shankar 

> Signed-off-by: Jani Nikula 
> ---
>  include/drm/drm_displayid.h | 29 +
>  1 file changed, 29 insertions(+)
> 
> diff --git a/include/drm/drm_displayid.h b/include/drm/drm_displayid.h index
> 0ed9445b5482..79771091771a 100644
> --- a/include/drm/drm_displayid.h
> +++ b/include/drm/drm_displayid.h
> @@ -26,6 +26,10 @@
> 
>  struct edid;
> 
> +/* DisplayID Structure versions */
> +#define DISPLAY_ID_STRUCTURE_VER_12  0x12
> +#define DISPLAY_ID_STRUCTURE_VER_20  0x20
> +
>  /* DisplayID Structure v1r2 Data Blocks */
>  #define DATA_BLOCK_PRODUCT_ID0x00
>  #define DATA_BLOCK_DISPLAY_PARAMETERS0x01
> @@ -48,6 +52,20 @@ struct edid;
>  #define DATA_BLOCK_VENDOR_SPECIFIC   0x7f
>  #define DATA_BLOCK_CTA   0x81
> 
> +/* DisplayID Structure v2r0 Data Blocks */
> +#define DATA_BLOCK_2_PRODUCT_ID  0x20
> +#define DATA_BLOCK_2_DISPLAY_PARAMETERS  0x21
> +#define DATA_BLOCK_2_TYPE_7_DETAILED_TIMING  0x22
> +#define DATA_BLOCK_2_TYPE_8_ENUMERATED_TIMING0x23
> +#define DATA_BLOCK_2_TYPE_9_FORMULA_TIMING   0x24
> +#define DATA_BLOCK_2_DYNAMIC_VIDEO_TIMING0x25
> +#define DATA_BLOCK_2_DISPLAY_INTERFACE_FEATURES  0x26
> +#define DATA_BLOCK_2_STEREO_DISPLAY_INTERFACE0x27
> +#define DATA_BLOCK_2_TILED_DISPLAY_TOPOLOGY  0x28
> +#define DATA_BLOCK_2_CONTAINER_ID0x29
> +#define DATA_BLOCK_2_VENDOR_SPECIFIC 0x7e
> +#define DATA_BLOCK_2_CTA_DISPLAY_ID  0x81
> +
>  /* DisplayID Structure v1r2 Product Type */
>  #define PRODUCT_TYPE_EXTENSION   0
>  #define PRODUCT_TYPE_TEST1
> @@ -57,6 +75,17 @@ struct edid;
>  #define PRODUCT_TYPE_REPEATER5
>  #define PRODUCT_TYPE_DIRECT_DRIVE6
> 
> +/* DisplayID Structure v2r0 Display Product Primary Use Case (~Product Type) 
> */
> +#define PRIMARY_USE_EXTENSION0
> +#define PRIMARY_USE_TEST 1
> +#define PRIMARY_USE_GENERIC  2
> +#define PRIMARY_USE_TV   3
> +#define PRIMARY_USE_DESKTOP_PRODUCTIVITY 4
> +#define PRIMARY_USE_DESKTOP_GAMING   5
> +#define PRIMARY_USE_PRESENTATION 6
> +#define PRIMARY_USE_HEAD_MOUNTED_VR  7
> +#define PRIMARY_USE_HEAD_MOUNTED_AR  8
> +
>  struct displayid_header {
>   u8 rev;
>   u8 bytes;
> --
> 2.30.2



RE: [PATCH v2 1/6] drm/displayid: re-align data block macros

2021-09-12 Thread Shankar, Uma



> -Original Message-
> From: dri-devel  On Behalf Of Jani 
> Nikula
> Sent: Tuesday, August 31, 2021 7:48 PM
> To: intel-...@lists.freedesktop.org
> Cc: dri-devel@lists.freedesktop.org; ville.syrj...@linux.intel.com; Nikula, 
> Jani
> 
> Subject: [PATCH v2 1/6] drm/displayid: re-align data block macros
> 
> Make the values easier to read. Also add DisplayID Structure version and 
> revision
> information (this is different from the spec version).

Looks ok to me.
Reviewed-by: Uma Shankar 

> Signed-off-by: Jani Nikula 
> ---
>  include/drm/drm_displayid.h | 57 +++--
>  1 file changed, 29 insertions(+), 28 deletions(-)
> 
> diff --git a/include/drm/drm_displayid.h b/include/drm/drm_displayid.h index
> ec64d141f578..0ed9445b5482 100644
> --- a/include/drm/drm_displayid.h
> +++ b/include/drm/drm_displayid.h
> @@ -26,35 +26,36 @@
> 
>  struct edid;
> 
> -#define DATA_BLOCK_PRODUCT_ID 0x00
> -#define DATA_BLOCK_DISPLAY_PARAMETERS 0x01 -#define
> DATA_BLOCK_COLOR_CHARACTERISTICS 0x02 -#define
> DATA_BLOCK_TYPE_1_DETAILED_TIMING 0x03 -#define
> DATA_BLOCK_TYPE_2_DETAILED_TIMING 0x04 -#define
> DATA_BLOCK_TYPE_3_SHORT_TIMING 0x05 -#define
> DATA_BLOCK_TYPE_4_DMT_TIMING 0x06 -#define DATA_BLOCK_VESA_TIMING
> 0x07 -#define DATA_BLOCK_CEA_TIMING 0x08 -#define
> DATA_BLOCK_VIDEO_TIMING_RANGE 0x09 -#define
> DATA_BLOCK_PRODUCT_SERIAL_NUMBER 0x0a -#define
> DATA_BLOCK_GP_ASCII_STRING 0x0b -#define
> DATA_BLOCK_DISPLAY_DEVICE_DATA 0x0c -#define
> DATA_BLOCK_INTERFACE_POWER_SEQUENCING 0x0d -#define
> DATA_BLOCK_TRANSFER_CHARACTERISTICS 0x0e -#define
> DATA_BLOCK_DISPLAY_INTERFACE 0x0f -#define
> DATA_BLOCK_STEREO_DISPLAY_INTERFACE 0x10 -#define
> DATA_BLOCK_TILED_DISPLAY 0x12 -#define DATA_BLOCK_CTA 0x81
> +/* DisplayID Structure v1r2 Data Blocks */
> +#define DATA_BLOCK_PRODUCT_ID0x00
> +#define DATA_BLOCK_DISPLAY_PARAMETERS0x01
> +#define DATA_BLOCK_COLOR_CHARACTERISTICS 0x02
> +#define DATA_BLOCK_TYPE_1_DETAILED_TIMING0x03
> +#define DATA_BLOCK_TYPE_2_DETAILED_TIMING0x04
> +#define DATA_BLOCK_TYPE_3_SHORT_TIMING   0x05
> +#define DATA_BLOCK_TYPE_4_DMT_TIMING 0x06
> +#define DATA_BLOCK_VESA_TIMING   0x07
> +#define DATA_BLOCK_CEA_TIMING0x08
> +#define DATA_BLOCK_VIDEO_TIMING_RANGE0x09
> +#define DATA_BLOCK_PRODUCT_SERIAL_NUMBER 0x0a
> +#define DATA_BLOCK_GP_ASCII_STRING   0x0b
> +#define DATA_BLOCK_DISPLAY_DEVICE_DATA   0x0c
> +#define DATA_BLOCK_INTERFACE_POWER_SEQUENCING0x0d
> +#define DATA_BLOCK_TRANSFER_CHARACTERISTICS  0x0e
> +#define DATA_BLOCK_DISPLAY_INTERFACE 0x0f
> +#define DATA_BLOCK_STEREO_DISPLAY_INTERFACE  0x10
> +#define DATA_BLOCK_TILED_DISPLAY 0x12
> +#define DATA_BLOCK_VENDOR_SPECIFIC   0x7f
> +#define DATA_BLOCK_CTA   0x81
> 
> -#define DATA_BLOCK_VENDOR_SPECIFIC 0x7f
> -
> -#define PRODUCT_TYPE_EXTENSION 0
> -#define PRODUCT_TYPE_TEST 1
> -#define PRODUCT_TYPE_PANEL 2
> -#define PRODUCT_TYPE_MONITOR 3
> -#define PRODUCT_TYPE_TV 4
> -#define PRODUCT_TYPE_REPEATER 5
> -#define PRODUCT_TYPE_DIRECT_DRIVE 6
> +/* DisplayID Structure v1r2 Product Type */
> +#define PRODUCT_TYPE_EXTENSION   0
> +#define PRODUCT_TYPE_TEST1
> +#define PRODUCT_TYPE_PANEL   2
> +#define PRODUCT_TYPE_MONITOR 3
> +#define PRODUCT_TYPE_TV  4
> +#define PRODUCT_TYPE_REPEATER5
> +#define PRODUCT_TYPE_DIRECT_DRIVE6
> 
>  struct displayid_header {
>   u8 rev;
> --
> 2.30.2



[RFC PATCH] drm/ttm: Try to check if new ttm man out of bounds during compile

2021-09-12 Thread xinhui pan
Allow TTM know if vendor set new ttm mananger out of bounds by adding
build_bug_on.

Signed-off-by: xinhui pan 
---
 drivers/gpu/drm/ttm/ttm_range_manager.c |  2 ++
 include/drm/ttm/ttm_device.h|  3 +++
 include/drm/ttm/ttm_range_manager.h | 10 ++
 3 files changed, 15 insertions(+)

diff --git a/drivers/gpu/drm/ttm/ttm_range_manager.c 
b/drivers/gpu/drm/ttm/ttm_range_manager.c
index 03395386e8a7..47e304719b88 100644
--- a/drivers/gpu/drm/ttm/ttm_range_manager.c
+++ b/drivers/gpu/drm/ttm/ttm_range_manager.c
@@ -127,6 +127,8 @@ static const struct ttm_resource_manager_func 
ttm_range_manager_func = {
.debug = ttm_range_man_debug
 };
 
+#undef ttm_range_man_init
+#undef ttm_range_man_fini
 /**
  * ttm_range_man_init
  *
diff --git a/include/drm/ttm/ttm_device.h b/include/drm/ttm/ttm_device.h
index 07d722950d5b..6f23724f5a06 100644
--- a/include/drm/ttm/ttm_device.h
+++ b/include/drm/ttm/ttm_device.h
@@ -285,12 +285,15 @@ int ttm_device_swapout(struct ttm_device *bdev, struct 
ttm_operation_ctx *ctx,
 static inline struct ttm_resource_manager *
 ttm_manager_type(struct ttm_device *bdev, int mem_type)
 {
+   BUILD_BUG_ON(__builtin_constant_p(mem_type)
+&& mem_type >= TTM_NUM_MEM_TYPES);
return bdev->man_drv[mem_type];
 }
 
 static inline void ttm_set_driver_manager(struct ttm_device *bdev, int type,
  struct ttm_resource_manager *manager)
 {
+   BUILD_BUG_ON(__builtin_constant_p(type) && type >= TTM_NUM_MEM_TYPES);
bdev->man_drv[type] = manager;
 }
 
diff --git a/include/drm/ttm/ttm_range_manager.h 
b/include/drm/ttm/ttm_range_manager.h
index 22b6fa42ac20..9250ade54e2c 100644
--- a/include/drm/ttm/ttm_range_manager.h
+++ b/include/drm/ttm/ttm_range_manager.h
@@ -38,5 +38,15 @@ int ttm_range_man_init(struct ttm_device *bdev,
   unsigned long p_size);
 int ttm_range_man_fini(struct ttm_device *bdev,
   unsigned type);
+#define ttm_range_man_init(bdev, type, use_tt, size) ({\
+   BUILD_BUG_ON(__builtin_constant_p(type) \
+   && type >= TTM_NUM_MEM_TYPES);  \
+   ttm_range_man_init(bdev, type, use_tt, size);   \
+})
+#define ttm_range_man_fini(bdev, type) ({  \
+   BUILD_BUG_ON(__builtin_constant_p(type) \
+   && type >= TTM_NUM_MEM_TYPES);  \
+   ttm_range_man_fini(bdev, type); \
+})
 
 #endif
-- 
2.25.1



RE: [PATCH] drm/ttm: add a WARN_ON in ttm_set_driver_manager when array bounds (v2)

2021-09-12 Thread Chen, Guchun
[Public]

Thanks for your suggestion, Robin. Do you agree with this as well, Christian 
and Xinhui?

Regards,
Guchun

-Original Message-
From: Robin Murphy  
Sent: Saturday, September 11, 2021 2:25 AM
To: Chen, Guchun ; amd-...@lists.freedesktop.org; 
dri-devel@lists.freedesktop.org; Koenig, Christian ; 
Pan, Xinhui ; Deucher, Alexander 
Cc: Shi, Leslie 
Subject: Re: [PATCH] drm/ttm: add a WARN_ON in ttm_set_driver_manager when 
array bounds (v2)

On 2021-09-10 11:09, Guchun Chen wrote:
> Vendor will define their own memory types on top of TTM_PL_PRIV, but 
> call ttm_set_driver_manager directly without checking mem_type value 
> when setting up memory manager. So add such check to aware the case 
> when array bounds.
> 
> v2: lower check level to WARN_ON
> 
> Signed-off-by: Leslie Shi 
> Signed-off-by: Guchun Chen 
> ---
>   include/drm/ttm/ttm_device.h | 1 +
>   1 file changed, 1 insertion(+)
> 
> diff --git a/include/drm/ttm/ttm_device.h 
> b/include/drm/ttm/ttm_device.h index 07d722950d5b..aa79953c807c 100644
> --- a/include/drm/ttm/ttm_device.h
> +++ b/include/drm/ttm/ttm_device.h
> @@ -291,6 +291,7 @@ ttm_manager_type(struct ttm_device *bdev, int mem_type)
>   static inline void ttm_set_driver_manager(struct ttm_device *bdev, int type,
> struct ttm_resource_manager *manager)
>   {
> + WARN_ON(type >= TTM_NUM_MEM_TYPES);

Nit: I know nothing about this code, but from the context alone it would seem 
sensible to do

if (WARN_ON(type >= TTM_NUM_MEM_TYPES))
return;

to avoid making the subsequent assignment when we *know* it's invalid and 
likely to corrupt memory.

Robin.

>   bdev->man_drv[type] = manager;
>   }
>   
> 


[PATCH] drm/rockchip: fix a -Werror fail on !CONFIG_PM_SLEEP

2021-09-12 Thread Adam Borowski
Signed-off-by: Adam Borowski 
---
 With Linus suddenly loving -Werror, let's get clean.

 drivers/gpu/drm/rockchip/cdn-dp-core.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c 
b/drivers/gpu/drm/rockchip/cdn-dp-core.c
index 8ab3247dbc4a..bee0f2d2a9be 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
@@ -1123,6 +1123,7 @@ static int cdn_dp_suspend(struct device *dev)
return ret;
 }
 
+#ifdef CONFIG_PM_SLEEP
 static int cdn_dp_resume(struct device *dev)
 {
struct cdn_dp_device *dp = dev_get_drvdata(dev);
@@ -1135,6 +1136,7 @@ static int cdn_dp_resume(struct device *dev)
 
return 0;
 }
+#endif
 
 static int cdn_dp_probe(struct platform_device *pdev)
 {
-- 
2.33.0



[PATCH] drm/fb-helper: disallow if DRM=y and FB=m

2021-09-12 Thread Adam Borowski
A subfeature of a built-in can't depend on a module.

Signed-off-by: Adam Borowski 
---
 drivers/gpu/drm/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index cea777ae7fb9..75a5a9359d4b 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -103,7 +103,7 @@ config DRM_DEBUG_DP_MST_TOPOLOGY_REFS
 config DRM_FBDEV_EMULATION
bool "Enable legacy fbdev support for your modesetting driver"
depends on DRM
-   depends on FB
+   depends on FB >= DRM
select DRM_KMS_HELPER
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
-- 
2.33.0



[PATCH v11 34/34] ARM: tegra20/30: Disable unused host1x hardware

2021-09-12 Thread Dmitry Osipenko
MPE, VI, EPP and ISP were never used and we don't have drivers for them.
Since these modules are enabled by default in a device-tree, a device is
created for them, blocking voltage scaling because there is no driver to
bind, and thus, state of PMC driver is never synced. Disable them.

Signed-off-by: Dmitry Osipenko 
---
 arch/arm/boot/dts/tegra20.dtsi | 4 
 arch/arm/boot/dts/tegra30.dtsi | 8 
 2 files changed, 12 insertions(+)

diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi
index 8ab77583846b..6eb13da7f91f 100644
--- a/arch/arm/boot/dts/tegra20.dtsi
+++ b/arch/arm/boot/dts/tegra20.dtsi
@@ -59,6 +59,7 @@ mpe@5404 {
reset-names = "mpe";
operating-points-v2 = <_dvfs_opp_table>;
power-domains = <_mpe>;
+   status = "disabled";
};
 
vi@5408 {
@@ -70,6 +71,7 @@ vi@5408 {
reset-names = "vi";
operating-points-v2 = <_dvfs_opp_table>;
power-domains = <_venc>;
+   status = "disabled";
};
 
epp@540c {
@@ -81,6 +83,7 @@ epp@540c {
reset-names = "epp";
operating-points-v2 = <_dvfs_opp_table>;
power-domains = <_core>;
+   status = "disabled";
};
 
isp@5410 {
@@ -91,6 +94,7 @@ isp@5410 {
resets = <_car 23>;
reset-names = "isp";
power-domains = <_venc>;
+   status = "disabled";
};
 
gr2d@5414 {
diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi
index 58ef4983e511..61f74b7879bb 100644
--- a/arch/arm/boot/dts/tegra30.dtsi
+++ b/arch/arm/boot/dts/tegra30.dtsi
@@ -145,6 +145,8 @@ mpe@5404 {
power-domains = <_mpe>;
 
iommus = < TEGRA_SWGROUP_MPE>;
+
+   status = "disabled";
};
 
vi@5408 {
@@ -158,6 +160,8 @@ vi@5408 {
power-domains = <_venc>;
 
iommus = < TEGRA_SWGROUP_VI>;
+
+   status = "disabled";
};
 
epp@540c {
@@ -171,6 +175,8 @@ epp@540c {
power-domains = <_heg>;
 
iommus = < TEGRA_SWGROUP_EPP>;
+
+   status = "disabled";
};
 
isp@5410 {
@@ -183,6 +189,8 @@ isp@5410 {
power-domains = <_venc>;
 
iommus = < TEGRA_SWGROUP_ISP>;
+
+   status = "disabled";
};
 
gr2d@5414 {
-- 
2.32.0



[PATCH v11 32/34] ARM: tegra: Add Memory Client resets to Tegra20 GR2D, GR3D and Host1x

2021-09-12 Thread Dmitry Osipenko
Memory access must be blocked before hardware reset is asserted and before
power is gated, otherwise a serious hardware fault is inevitable. Add
reset for memory clients to the GR2D, GR3D and Host1x nodes.

Tested-by: Paul Fertser  # PAZ00 T20
Tested-by: Nicolas Chauvet  # PAZ00 T20
Signed-off-by: Dmitry Osipenko 
---
 arch/arm/boot/dts/tegra20.dtsi | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi
index 4abb6634e8ae..8ab77583846b 100644
--- a/arch/arm/boot/dts/tegra20.dtsi
+++ b/arch/arm/boot/dts/tegra20.dtsi
@@ -40,8 +40,8 @@ host1x@5000 {
interrupt-names = "syncpt", "host1x";
clocks = <_car TEGRA20_CLK_HOST1X>;
clock-names = "host1x";
-   resets = <_car 28>;
-   reset-names = "host1x";
+   resets = <_car 28>, < TEGRA20_MC_RESET_HC>;
+   reset-names = "host1x", "mc";
operating-points-v2 = <_dvfs_opp_table>;
power-domains = <_core>;
 
@@ -98,8 +98,8 @@ gr2d@5414 {
reg = <0x5414 0x0004>;
interrupts = ;
clocks = <_car TEGRA20_CLK_GR2D>;
-   resets = <_car 21>;
-   reset-names = "2d";
+   resets = <_car 21>, < TEGRA20_MC_RESET_2D>;
+   reset-names = "2d", "mc";
operating-points-v2 = <_dvfs_opp_table>;
power-domains = <_core>;
};
@@ -108,8 +108,8 @@ gr3d@5418 {
compatible = "nvidia,tegra20-gr3d";
reg = <0x5418 0x0004>;
clocks = <_car TEGRA20_CLK_GR3D>;
-   resets = <_car 24>;
-   reset-names = "3d";
+   resets = <_car 24>, < TEGRA20_MC_RESET_3D>;
+   reset-names = "3d", "mc";
operating-points-v2 = <_dvfs_opp_table>;
power-domains = <_3d>;
};
-- 
2.32.0



[PATCH v11 33/34] ARM: tegra: Add Memory Client resets to Tegra30 GR2D, GR3D and Host1x

2021-09-12 Thread Dmitry Osipenko
Memory access must be blocked before hardware reset is asserted and before
power is gated, otherwise a serious hardware fault is inevitable. Add
reset for memory clients to the GR2D, GR3D and Host1x nodes.

Tested-by: Peter Geis  # Ouya T30
Tested-by: Matt Merhar  # Ouya T30
Signed-off-by: Dmitry Osipenko 
---
 arch/arm/boot/dts/tegra30.dtsi | 14 --
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi
index 9c7616abaa2e..58ef4983e511 100644
--- a/arch/arm/boot/dts/tegra30.dtsi
+++ b/arch/arm/boot/dts/tegra30.dtsi
@@ -123,8 +123,8 @@ host1x@5000 {
interrupt-names = "syncpt", "host1x";
clocks = <_car TEGRA30_CLK_HOST1X>;
clock-names = "host1x";
-   resets = <_car 28>;
-   reset-names = "host1x";
+   resets = <_car 28>, < TEGRA30_MC_RESET_HC>;
+   reset-names = "host1x", "mc";
iommus = < TEGRA_SWGROUP_HC>;
operating-points-v2 = <_dvfs_opp_table>;
power-domains = <_heg>;
@@ -190,8 +190,8 @@ gr2d@5414 {
reg = <0x5414 0x0004>;
interrupts = ;
clocks = <_car TEGRA30_CLK_GR2D>;
-   resets = <_car 21>;
-   reset-names = "2d";
+   resets = <_car 21>, < TEGRA30_MC_RESET_2D>;
+   reset-names = "2d", "mc";
operating-points-v2 = <_dvfs_opp_table>;
power-domains = <_heg>;
 
@@ -205,8 +205,10 @@ gr3d@5418 {
 <_car TEGRA30_CLK_GR3D2>;
clock-names = "3d", "3d2";
resets = <_car 24>,
-<_car 98>;
-   reset-names = "3d", "3d2";
+<_car 98>,
+< TEGRA30_MC_RESET_3D>,
+< TEGRA30_MC_RESET_3D2>;
+   reset-names = "3d", "3d2", "mc", "mc2";
operating-points-v2 = <_dvfs_opp_table>;
power-domains = <_3d0>, <_3d1>;
power-domain-names = "3d0", "3d1";
-- 
2.32.0



[PATCH v11 30/34] ARM: tegra: Add OPP tables and power domains to Tegra20 device-trees

2021-09-12 Thread Dmitry Osipenko
Add OPP tables and power domains to all peripheral devices which
support power management on Tegra20 SoC.

Tested-by: Paul Fertser  # PAZ00 T20
Tested-by: Nicolas Chauvet  # PAZ00 T20
Signed-off-by: Dmitry Osipenko 
---
 .../boot/dts/tegra20-acer-a500-picasso.dts|   1 +
 arch/arm/boot/dts/tegra20-colibri.dtsi|   3 +-
 arch/arm/boot/dts/tegra20-harmony.dts |   3 +-
 arch/arm/boot/dts/tegra20-paz00.dts   |   1 +
 .../arm/boot/dts/tegra20-peripherals-opp.dtsi | 941 ++
 arch/arm/boot/dts/tegra20-seaboard.dts|   3 +-
 arch/arm/boot/dts/tegra20-tamonten.dtsi   |   3 +-
 arch/arm/boot/dts/tegra20-trimslice.dts   |   9 +
 arch/arm/boot/dts/tegra20-ventana.dts |   1 +
 arch/arm/boot/dts/tegra20.dtsi| 100 ++
 10 files changed, 1061 insertions(+), 4 deletions(-)

diff --git a/arch/arm/boot/dts/tegra20-acer-a500-picasso.dts 
b/arch/arm/boot/dts/tegra20-acer-a500-picasso.dts
index 2280d75b66ab..1dbeabcb8b74 100644
--- a/arch/arm/boot/dts/tegra20-acer-a500-picasso.dts
+++ b/arch/arm/boot/dts/tegra20-acer-a500-picasso.dts
@@ -713,6 +713,7 @@ pmc@7000e400 {
nvidia,core-pwr-good-time = <3845 3845>;
nvidia,core-pwr-off-time = <458>;
nvidia,sys-clock-req-active-high;
+   core-supply = <_core>;
};
 
usb@c500 {
diff --git a/arch/arm/boot/dts/tegra20-colibri.dtsi 
b/arch/arm/boot/dts/tegra20-colibri.dtsi
index 585a5b441cf6..4ec403aa5f2e 100644
--- a/arch/arm/boot/dts/tegra20-colibri.dtsi
+++ b/arch/arm/boot/dts/tegra20-colibri.dtsi
@@ -495,7 +495,7 @@ reg_3v3_vsys: sys {
regulator-always-on;
};
 
-   sm0 {
+   vdd_core: sm0 {
regulator-name = "VDD_CORE_1.2V";
regulator-min-microvolt = <120>;
regulator-max-microvolt = <120>;
@@ -601,6 +601,7 @@ pmc@7000e400 {
nvidia,core-pwr-good-time = <3845 3845>;
nvidia,core-pwr-off-time = <3875>;
nvidia,sys-clock-req-active-high;
+   core-supply = <_core>;
 
/* Set SLEEP MODE bit in SUPPLYENE register of TPS658643 PMIC */
i2c-thermtrip {
diff --git a/arch/arm/boot/dts/tegra20-harmony.dts 
b/arch/arm/boot/dts/tegra20-harmony.dts
index ae4312eedcbd..b21bab437ebd 100644
--- a/arch/arm/boot/dts/tegra20-harmony.dts
+++ b/arch/arm/boot/dts/tegra20-harmony.dts
@@ -339,7 +339,7 @@ sys_reg: sys {
regulator-always-on;
};
 
-   sm0 {
+   vdd_core: sm0 {
regulator-name = "vdd_sm0,vdd_core";
regulator-min-microvolt = <120>;
regulator-max-microvolt = <120>;
@@ -565,6 +565,7 @@ pmc@7000e400 {
nvidia,core-pwr-good-time = <3845 3845>;
nvidia,core-pwr-off-time = <3875>;
nvidia,sys-clock-req-active-high;
+   core-supply = <_core>;
};
 
pcie@80003000 {
diff --git a/arch/arm/boot/dts/tegra20-paz00.dts 
b/arch/arm/boot/dts/tegra20-paz00.dts
index acc816bfd233..c8e4439d3dfb 100644
--- a/arch/arm/boot/dts/tegra20-paz00.dts
+++ b/arch/arm/boot/dts/tegra20-paz00.dts
@@ -519,6 +519,7 @@ pmc@7000e400 {
nvidia,core-pwr-good-time = <3845 3845>;
nvidia,core-pwr-off-time = <0>;
nvidia,sys-clock-req-active-high;
+   core-supply = <_vdd_reg>;
};
 
usb@c500 {
diff --git a/arch/arm/boot/dts/tegra20-peripherals-opp.dtsi 
b/arch/arm/boot/dts/tegra20-peripherals-opp.dtsi
index ef3ad2e5f270..ff8c3dcba8e9 100644
--- a/arch/arm/boot/dts/tegra20-peripherals-opp.dtsi
+++ b/arch/arm/boot/dts/tegra20-peripherals-opp.dtsi
@@ -1,6 +1,46 @@
 // SPDX-License-Identifier: GPL-2.0
 
 / {
+   core_opp_table: core-power-domain-opp-table {
+   compatible = "operating-points-v2";
+   opp-shared;
+
+   core_opp_950: opp@95 {
+   opp-microvolt = <95 95 130>;
+   opp-level = <95>;
+   };
+
+   core_opp_1000: opp@100 {
+   opp-microvolt = <100 100 130>;
+   opp-level = <100>;
+   };
+
+   core_opp_1100: opp@110 {
+   opp-microvolt = <110 110 130>;
+   opp-level = <110>;
+   };
+
+   core_opp_1200: opp@120 {
+   opp-microvolt = <120 120 130>;
+   opp-level = <120>;
+   };
+
+  

[PATCH v11 31/34] ARM: tegra: Add OPP tables and power domains to Tegra30 device-trees

2021-09-12 Thread Dmitry Osipenko
Add OPP tables and power domains to all peripheral devices which
support power management on Tegra30 SoC.

Tested-by: Peter Geis  # Ouya T30
Tested-by: Matt Merhar  # Ouya T30
Signed-off-by: Dmitry Osipenko 
---
 .../tegra30-asus-nexus7-grouper-common.dtsi   |1 +
 arch/arm/boot/dts/tegra30-beaver.dts  |1 +
 arch/arm/boot/dts/tegra30-cardhu.dtsi |1 +
 arch/arm/boot/dts/tegra30-colibri.dtsi|   17 +-
 arch/arm/boot/dts/tegra30-ouya.dts|1 +
 .../arm/boot/dts/tegra30-peripherals-opp.dtsi | 1412 +
 arch/arm/boot/dts/tegra30.dtsi|  153 ++
 7 files changed, 1583 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/tegra30-asus-nexus7-grouper-common.dtsi 
b/arch/arm/boot/dts/tegra30-asus-nexus7-grouper-common.dtsi
index 9732cd6f20b7..4f116c26f6ce 100644
--- a/arch/arm/boot/dts/tegra30-asus-nexus7-grouper-common.dtsi
+++ b/arch/arm/boot/dts/tegra30-asus-nexus7-grouper-common.dtsi
@@ -957,6 +957,7 @@ pmc@7000e400 {
nvidia,core-pwr-off-time = <0>;
nvidia,core-power-req-active-high;
nvidia,sys-clock-req-active-high;
+   core-supply = <_core>;
};
 
ahub@7008 {
diff --git a/arch/arm/boot/dts/tegra30-beaver.dts 
b/arch/arm/boot/dts/tegra30-beaver.dts
index e159feeedef7..b54cbb24c4d3 100644
--- a/arch/arm/boot/dts/tegra30-beaver.dts
+++ b/arch/arm/boot/dts/tegra30-beaver.dts
@@ -1915,6 +1915,7 @@ pmc@7000e400 {
nvidia,core-pwr-off-time = <0>;
nvidia,core-power-req-active-high;
nvidia,sys-clock-req-active-high;
+   core-supply = <_vdd_reg>;
};
 
ahub@7008 {
diff --git a/arch/arm/boot/dts/tegra30-cardhu.dtsi 
b/arch/arm/boot/dts/tegra30-cardhu.dtsi
index 448f1397e64a..b2bba923eb93 100644
--- a/arch/arm/boot/dts/tegra30-cardhu.dtsi
+++ b/arch/arm/boot/dts/tegra30-cardhu.dtsi
@@ -391,6 +391,7 @@ pmc@7000e400 {
nvidia,core-pwr-off-time = <0>;
nvidia,core-power-req-active-high;
nvidia,sys-clock-req-active-high;
+   core-supply = <_core>;
};
 
ahub@7008 {
diff --git a/arch/arm/boot/dts/tegra30-colibri.dtsi 
b/arch/arm/boot/dts/tegra30-colibri.dtsi
index 413e35215804..0627b64f044d 100644
--- a/arch/arm/boot/dts/tegra30-colibri.dtsi
+++ b/arch/arm/boot/dts/tegra30-colibri.dtsi
@@ -765,9 +765,14 @@ vdd1_reg: vdd1 {
 
vddctrl_reg: vddctrl {
regulator-name = "+V1.0_VDD_CPU";
-   regulator-min-microvolt = <115>;
-   regulator-max-microvolt = <115>;
+   regulator-min-microvolt = <80>;
+   regulator-max-microvolt = <125>;
+   regulator-coupled-with = <_core>;
+   regulator-coupled-max-spread = <30>;
+   regulator-max-step-microvolt = <10>;
regulator-always-on;
+
+   nvidia,tegra-cpu-regulator;
};
 
reg_1v8_vio: vio {
@@ -890,18 +895,23 @@ temp-sensor@4c {
};
 
/* SW: +V1.2_VDD_CORE */
-   regulator@60 {
+   vdd_core: regulator@60 {
compatible = "ti,tps62362";
reg = <0x60>;
 
regulator-name = "tps62362-vout";
regulator-min-microvolt = <90>;
regulator-max-microvolt = <140>;
+   regulator-coupled-with = <_reg>;
+   regulator-coupled-max-spread = <30>;
+   regulator-max-step-microvolt = <10>;
regulator-boot-on;
regulator-always-on;
ti,vsel0-state-low;
/* VSEL1: EN_CORE_DVFS_N low for DVFS */
ti,vsel1-state-low;
+
+   nvidia,tegra-core-regulator;
};
};
 
@@ -914,6 +924,7 @@ pmc@7000e400 {
nvidia,core-pwr-off-time = <0>;
nvidia,core-power-req-active-high;
nvidia,sys-clock-req-active-high;
+   core-supply = <_core>;
 
/* Set DEV_OFF bit in DCDC control register of TPS65911 PMIC */
i2c-thermtrip {
diff --git a/arch/arm/boot/dts/tegra30-ouya.dts 
b/arch/arm/boot/dts/tegra30-ouya.dts
index 90db5ff72537..2a79cd4662b1 100644
--- a/arch/arm/boot/dts/tegra30-ouya.dts
+++ b/arch/arm/boot/dts/tegra30-ouya.dts
@@ -274,6 +274,7 @@ pmc@7000e400 {
nvidia,core-pwr-off-time = <458>;
nvidia,core-power-req-active-high;
   

[PATCH v11 29/34] soc/tegra: pmc: Enable core domain support for Tegra20 and Tegra30

2021-09-12 Thread Dmitry Osipenko
All device drivers got runtime PM and OPP support. Flip the core domain
support status for Tegra20 and Tegra30 SoCs.

Signed-off-by: Dmitry Osipenko 
---
 drivers/soc/tegra/pmc.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index 5e1fc873bf8f..74de84a014e9 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -3042,7 +3042,7 @@ static void tegra20_pmc_setup_irq_polarity(struct 
tegra_pmc *pmc,
 }
 
 static const struct tegra_pmc_soc tegra20_pmc_soc = {
-   .supports_core_domain = false,
+   .supports_core_domain = true,
.num_powergates = ARRAY_SIZE(tegra20_powergates),
.powergates = tegra20_powergates,
.num_cpu_powergates = 0,
@@ -3103,7 +3103,7 @@ static const char * const tegra30_reset_sources[] = {
 };
 
 static const struct tegra_pmc_soc tegra30_pmc_soc = {
-   .supports_core_domain = false,
+   .supports_core_domain = true,
.num_powergates = ARRAY_SIZE(tegra30_powergates),
.powergates = tegra30_powergates,
.num_cpu_powergates = ARRAY_SIZE(tegra30_cpu_powergates),
-- 
2.32.0



[PATCH v11 28/34] soc/tegra: pmc: Change name of core power domain

2021-09-12 Thread Dmitry Osipenko
CORE power domain uses name of device-tree node, which is inconsistent with
the names of PMC domains. Set the name to "core" to make it consistent.

Signed-off-by: Dmitry Osipenko 
---
 drivers/soc/tegra/pmc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index fb8faf7b226a..5e1fc873bf8f 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -1353,7 +1353,7 @@ static int tegra_pmc_core_pd_add(struct tegra_pmc *pmc, 
struct device_node *np)
if (!genpd)
return -ENOMEM;
 
-   genpd->name = np->name;
+   genpd->name = "core";
genpd->set_performance_state = tegra_pmc_core_pd_set_performance_state;
genpd->opp_to_performance_state = 
tegra_pmc_core_pd_opp_to_performance_state;
 
-- 
2.32.0



[PATCH v11 27/34] soc/tegra: regulators: Prepare for suspend

2021-09-12 Thread Dmitry Osipenko
Depending on hardware version, Tegra SoC may require a higher voltages
during resume from system suspend, otherwise hardware will crash. Set
SoC voltages to a nominal levels during suspend.

Signed-off-by: Dmitry Osipenko 
---
 drivers/soc/tegra/regulators-tegra20.c |  99 
 drivers/soc/tegra/regulators-tegra30.c | 122 +
 2 files changed, 221 insertions(+)

diff --git a/drivers/soc/tegra/regulators-tegra20.c 
b/drivers/soc/tegra/regulators-tegra20.c
index b8ce9fd0650d..6a2f90ab9d3e 100644
--- a/drivers/soc/tegra/regulators-tegra20.c
+++ b/drivers/soc/tegra/regulators-tegra20.c
@@ -16,7 +16,9 @@
 #include 
 #include 
 #include 
+#include 
 
+#include 
 #include 
 
 struct tegra_regulator_coupler {
@@ -25,9 +27,12 @@ struct tegra_regulator_coupler {
struct regulator_dev *cpu_rdev;
struct regulator_dev *rtc_rdev;
struct notifier_block reboot_notifier;
+   struct notifier_block suspend_notifier;
int core_min_uV, cpu_min_uV;
bool sys_reboot_mode_req;
bool sys_reboot_mode;
+   bool sys_suspend_mode_req;
+   bool sys_suspend_mode;
 };
 
 static inline struct tegra_regulator_coupler *
@@ -105,6 +110,28 @@ static int tegra20_core_rtc_max_spread(struct 
regulator_dev *core_rdev,
return 15;
 }
 
+static int tegra20_cpu_nominal_uV(void)
+{
+   switch (tegra_sku_info.soc_speedo_id) {
+   case 0:
+   return 110;
+   case 1:
+   return 1025000;
+   default:
+   return 1125000;
+   }
+}
+
+static int tegra20_core_nominal_uV(void)
+{
+   switch (tegra_sku_info.soc_speedo_id) {
+   default:
+   return 1225000;
+   case 2:
+   return 130;
+   }
+}
+
 static int tegra20_core_rtc_update(struct tegra_regulator_coupler *tegra,
   struct regulator_dev *core_rdev,
   struct regulator_dev *rtc_rdev,
@@ -144,6 +171,11 @@ static int tegra20_core_rtc_update(struct 
tegra_regulator_coupler *tegra,
if (err)
return err;
 
+   /* prepare voltage level for suspend */
+   if (tegra->sys_suspend_mode)
+   core_min_uV = clamp(tegra20_core_nominal_uV(),
+   core_min_uV, core_max_uV);
+
core_uV = regulator_get_voltage_rdev(core_rdev);
if (core_uV < 0)
return core_uV;
@@ -279,6 +311,11 @@ static int tegra20_cpu_voltage_update(struct 
tegra_regulator_coupler *tegra,
if (tegra->sys_reboot_mode)
cpu_min_uV = max(cpu_min_uV, tegra->cpu_min_uV);
 
+   /* prepare voltage level for suspend */
+   if (tegra->sys_suspend_mode)
+   cpu_min_uV = clamp(tegra20_cpu_nominal_uV(),
+  cpu_min_uV, cpu_max_uV);
+
if (cpu_min_uV > cpu_uV) {
err = tegra20_core_rtc_update(tegra, core_rdev, rtc_rdev,
  cpu_uV, cpu_min_uV);
@@ -320,6 +357,7 @@ static int tegra20_regulator_balance_voltage(struct 
regulator_coupler *coupler,
}
 
tegra->sys_reboot_mode = READ_ONCE(tegra->sys_reboot_mode_req);
+   tegra->sys_suspend_mode = READ_ONCE(tegra->sys_suspend_mode_req);
 
if (rdev == cpu_rdev)
return tegra20_cpu_voltage_update(tegra, cpu_rdev,
@@ -334,6 +372,63 @@ static int tegra20_regulator_balance_voltage(struct 
regulator_coupler *coupler,
return -EPERM;
 }
 
+static int tegra20_regulator_prepare_suspend(struct tegra_regulator_coupler 
*tegra,
+bool sys_suspend_mode)
+{
+   int err;
+
+   if (!tegra->core_rdev || !tegra->rtc_rdev || !tegra->cpu_rdev)
+   return 0;
+
+   /*
+* All power domains are enabled early during resume from suspend
+* by GENPD core.  Domains like VENC may require a higher voltage
+* when enabled during resume from suspend.  This also prepares
+* hardware for resuming from LP0.
+*/
+
+   WRITE_ONCE(tegra->sys_suspend_mode_req, sys_suspend_mode);
+
+   err = regulator_sync_voltage_rdev(tegra->cpu_rdev);
+   if (err)
+   return err;
+
+   err = regulator_sync_voltage_rdev(tegra->core_rdev);
+   if (err)
+   return err;
+
+   return 0;
+}
+
+static int tegra20_regulator_suspend(struct notifier_block *notifier,
+unsigned long mode, void *arg)
+{
+   struct tegra_regulator_coupler *tegra;
+   int ret = 0;
+
+   tegra = container_of(notifier, struct tegra_regulator_coupler,
+suspend_notifier);
+
+   switch (mode) {
+   case PM_HIBERNATION_PREPARE:
+   case PM_RESTORE_PREPARE:
+   case PM_SUSPEND_PREPARE:
+   ret = tegra20_regulator_prepare_suspend(tegra, true);
+   break;
+
+   case PM_POST_HIBERNATION:
+   

[PATCH v11 26/34] soc/tegra: fuse: Use resource-managed helpers

2021-09-12 Thread Dmitry Osipenko
Use resource-managed helpers to make code cleaner and more correct,
properly releasing all resources in case of driver probe error.

Signed-off-by: Dmitry Osipenko 
---
 drivers/soc/tegra/fuse/fuse-tegra.c   | 32 ++
 drivers/soc/tegra/fuse/fuse-tegra20.c | 33 ---
 2 files changed, 48 insertions(+), 17 deletions(-)

diff --git a/drivers/soc/tegra/fuse/fuse-tegra.c 
b/drivers/soc/tegra/fuse/fuse-tegra.c
index cc032729a143..fe4f935ce73a 100644
--- a/drivers/soc/tegra/fuse/fuse-tegra.c
+++ b/drivers/soc/tegra/fuse/fuse-tegra.c
@@ -182,6 +182,12 @@ static const struct nvmem_cell_info tegra_fuse_cells[] = {
},
 };
 
+static void tegra_fuse_restore(void *base)
+{
+   fuse->clk = NULL;
+   fuse->base = base;
+}
+
 static int tegra_fuse_probe(struct platform_device *pdev)
 {
void __iomem *base = fuse->base;
@@ -189,13 +195,16 @@ static int tegra_fuse_probe(struct platform_device *pdev)
struct resource *res;
int err;
 
+   err = devm_add_action(>dev, tegra_fuse_restore, base);
+   if (err)
+   return err;
+
/* take over the memory region from the early initialization */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
fuse->phys = res->start;
fuse->base = devm_ioremap_resource(>dev, res);
if (IS_ERR(fuse->base)) {
err = PTR_ERR(fuse->base);
-   fuse->base = base;
return err;
}
 
@@ -205,19 +214,20 @@ static int tegra_fuse_probe(struct platform_device *pdev)
dev_err(>dev, "failed to get FUSE clock: %ld",
PTR_ERR(fuse->clk));
 
-   fuse->base = base;
return PTR_ERR(fuse->clk);
}
 
platform_set_drvdata(pdev, fuse);
fuse->dev = >dev;
 
-   pm_runtime_enable(>dev);
+   err = devm_pm_runtime_enable(>dev);
+   if (err)
+   return err;
 
if (fuse->soc->probe) {
err = fuse->soc->probe(fuse);
if (err < 0)
-   goto restore;
+   return err;
}
 
memset(, 0, sizeof(nvmem));
@@ -241,7 +251,7 @@ static int tegra_fuse_probe(struct platform_device *pdev)
err = PTR_ERR(fuse->nvmem);
dev_err(>dev, "failed to register NVMEM device: %d\n",
err);
-   goto restore;
+   return err;
}
 
fuse->rst = devm_reset_control_get_optional(>dev, "fuse");
@@ -249,7 +259,7 @@ static int tegra_fuse_probe(struct platform_device *pdev)
err = PTR_ERR(fuse->rst);
dev_err(>dev, "failed to get FUSE reset: %pe\n",
fuse->rst);
-   goto restore;
+   return err;
}
 
/*
@@ -258,26 +268,20 @@ static int tegra_fuse_probe(struct platform_device *pdev)
 */
err = pm_runtime_resume_and_get(>dev);
if (err)
-   goto restore;
+   return err;
 
err = reset_control_reset(fuse->rst);
pm_runtime_put(>dev);
 
if (err < 0) {
dev_err(>dev, "failed to reset FUSE: %d\n", err);
-   goto restore;
+   return err;
}
 
/* release the early I/O memory mapping */
iounmap(base);
 
return 0;
-
-restore:
-   fuse->clk = NULL;
-   fuse->base = base;
-   pm_runtime_disable(>dev);
-   return err;
 }
 
 static int __maybe_unused tegra_fuse_runtime_resume(struct device *dev)
diff --git a/drivers/soc/tegra/fuse/fuse-tegra20.c 
b/drivers/soc/tegra/fuse/fuse-tegra20.c
index 8ec9fc5e5e4b..12503f563e36 100644
--- a/drivers/soc/tegra/fuse/fuse-tegra20.c
+++ b/drivers/soc/tegra/fuse/fuse-tegra20.c
@@ -94,9 +94,28 @@ static bool dma_filter(struct dma_chan *chan, void 
*filter_param)
return of_device_is_compatible(np, "nvidia,tegra20-apbdma");
 }
 
+static void tegra20_fuse_release_channel(void *data)
+{
+   struct tegra_fuse *fuse = data;
+
+   dma_release_channel(fuse->apbdma.chan);
+   fuse->apbdma.chan = NULL;
+}
+
+static void tegra20_fuse_free_coherent(void *data)
+{
+   struct tegra_fuse *fuse = data;
+
+   dma_free_coherent(fuse->dev, sizeof(u32), fuse->apbdma.virt,
+ fuse->apbdma.phys);
+   fuse->apbdma.virt = NULL;
+   fuse->apbdma.phys = 0x0;
+}
+
 static int tegra20_fuse_probe(struct tegra_fuse *fuse)
 {
dma_cap_mask_t mask;
+   int err;
 
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
@@ -105,13 +124,21 @@ static int tegra20_fuse_probe(struct tegra_fuse *fuse)
if (!fuse->apbdma.chan)
return -EPROBE_DEFER;
 
+   err = devm_add_action_or_reset(fuse->dev, tegra20_fuse_release_channel,
+  fuse);
+   if (err)
+   return err;
+
fuse->apbdma.virt = 

[PATCH v11 24/34] media: staging: tegra-vde: Support generic power domain

2021-09-12 Thread Dmitry Osipenko
Currently driver supports legacy power domain API, this patch adds generic
power domain support. This allows us to utilize a modern GENPD API for
newer device-trees.

Tested-by: Peter Geis  # Ouya T30
Tested-by: Paul Fertser  # PAZ00 T20
Tested-by: Nicolas Chauvet  # PAZ00 T20 and TK1 T124
Tested-by: Matt Merhar  # Ouya T30
Signed-off-by: Dmitry Osipenko 
---
 drivers/staging/media/tegra-vde/vde.c | 57 +--
 1 file changed, 46 insertions(+), 11 deletions(-)

diff --git a/drivers/staging/media/tegra-vde/vde.c 
b/drivers/staging/media/tegra-vde/vde.c
index ed4c1250b303..bb3079a2c0b5 100644
--- a/drivers/staging/media/tegra-vde/vde.c
+++ b/drivers/staging/media/tegra-vde/vde.c
@@ -20,6 +20,7 @@
 #include 
 #include 
 
+#include 
 #include 
 
 #include "uapi.h"
@@ -920,13 +921,17 @@ static __maybe_unused int 
tegra_vde_runtime_suspend(struct device *dev)
struct tegra_vde *vde = dev_get_drvdata(dev);
int err;
 
-   err = tegra_powergate_power_off(TEGRA_POWERGATE_VDEC);
-   if (err) {
-   dev_err(dev, "Failed to power down HW: %d\n", err);
-   return err;
+   if (!dev->pm_domain) {
+   err = tegra_powergate_power_off(TEGRA_POWERGATE_VDEC);
+   if (err) {
+   dev_err(dev, "Failed to power down HW: %d\n", err);
+   return err;
+   }
}
 
clk_disable_unprepare(vde->clk);
+   reset_control_release(vde->rst);
+   reset_control_release(vde->rst_mc);
 
return 0;
 }
@@ -936,14 +941,41 @@ static __maybe_unused int tegra_vde_runtime_resume(struct 
device *dev)
struct tegra_vde *vde = dev_get_drvdata(dev);
int err;
 
-   err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_VDEC,
-   vde->clk, vde->rst);
+   err = reset_control_acquire(vde->rst_mc);
if (err) {
-   dev_err(dev, "Failed to power up HW : %d\n", err);
+   dev_err(dev, "Failed to acquire mc reset: %d\n", err);
return err;
}
 
+   err = reset_control_acquire(vde->rst);
+   if (err) {
+   dev_err(dev, "Failed to acquire reset: %d\n", err);
+   goto release_mc_reset;
+   }
+
+   if (!dev->pm_domain) {
+   err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_VDEC,
+   vde->clk, vde->rst);
+   if (err) {
+   dev_err(dev, "Failed to power up HW : %d\n", err);
+   goto release_reset;
+   }
+   }
+
+   err = clk_prepare_enable(vde->clk);
+   if (err) {
+   dev_err(dev, "Failed to enable clock: %d\n", err);
+   goto release_reset;
+   }
+
return 0;
+
+release_reset:
+   reset_control_release(vde->rst);
+release_mc_reset:
+   reset_control_release(vde->rst_mc);
+
+   return err;
 }
 
 static int tegra_vde_probe(struct platform_device *pdev)
@@ -1001,14 +1033,14 @@ static int tegra_vde_probe(struct platform_device *pdev)
return err;
}
 
-   vde->rst = devm_reset_control_get(dev, NULL);
+   vde->rst = devm_reset_control_get_exclusive_released(dev, NULL);
if (IS_ERR(vde->rst)) {
err = PTR_ERR(vde->rst);
dev_err(dev, "Could not get VDE reset %d\n", err);
return err;
}
 
-   vde->rst_mc = devm_reset_control_get_optional(dev, "mc");
+   vde->rst_mc = devm_reset_control_get_optional_exclusive_released(dev, 
"mc");
if (IS_ERR(vde->rst_mc)) {
err = PTR_ERR(vde->rst_mc);
dev_err(dev, "Could not get MC reset %d\n", err);
@@ -1066,6 +1098,10 @@ static int tegra_vde_probe(struct platform_device *pdev)
pm_runtime_use_autosuspend(dev);
pm_runtime_set_autosuspend_delay(dev, 300);
 
+   err = devm_tegra_core_dev_init_opp_table_common(dev);
+   if (err)
+   goto err_pm_runtime;
+
/*
 * VDE partition may be left ON after bootloader, hence let's
 * power-cycle it in order to put hardware into a predictable lower
@@ -1133,8 +1169,7 @@ static void tegra_vde_shutdown(struct platform_device 
*pdev)
 * On some devices bootloader isn't ready to a power-gated VDE on
 * a warm-reboot, machine will hang in that case.
 */
-   if (pm_runtime_status_suspended(>dev))
-   tegra_vde_runtime_resume(>dev);
+   pm_runtime_get_sync(>dev);
 }
 
 static __maybe_unused int tegra_vde_pm_suspend(struct device *dev)
-- 
2.32.0



[PATCH v11 25/34] soc/tegra: fuse: Reset hardware

2021-09-12 Thread Dmitry Osipenko
The FUSE controller is enabled at a boot time. Reset it in order to put
hardware and clock into clean and disabled state.

Signed-off-by: Dmitry Osipenko 
---
 drivers/soc/tegra/fuse/fuse-tegra.c | 25 +
 drivers/soc/tegra/fuse/fuse.h   |  1 +
 2 files changed, 26 insertions(+)

diff --git a/drivers/soc/tegra/fuse/fuse-tegra.c 
b/drivers/soc/tegra/fuse/fuse-tegra.c
index f2151815db58..cc032729a143 100644
--- a/drivers/soc/tegra/fuse/fuse-tegra.c
+++ b/drivers/soc/tegra/fuse/fuse-tegra.c
@@ -14,6 +14,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -243,6 +244,30 @@ static int tegra_fuse_probe(struct platform_device *pdev)
goto restore;
}
 
+   fuse->rst = devm_reset_control_get_optional(>dev, "fuse");
+   if (IS_ERR(fuse->rst)) {
+   err = PTR_ERR(fuse->rst);
+   dev_err(>dev, "failed to get FUSE reset: %pe\n",
+   fuse->rst);
+   goto restore;
+   }
+
+   /*
+* FUSE clock is enabled at a boot time, hence this resume/suspend
+* disables the clock besides the h/w resetting.
+*/
+   err = pm_runtime_resume_and_get(>dev);
+   if (err)
+   goto restore;
+
+   err = reset_control_reset(fuse->rst);
+   pm_runtime_put(>dev);
+
+   if (err < 0) {
+   dev_err(>dev, "failed to reset FUSE: %d\n", err);
+   goto restore;
+   }
+
/* release the early I/O memory mapping */
iounmap(base);
 
diff --git a/drivers/soc/tegra/fuse/fuse.h b/drivers/soc/tegra/fuse/fuse.h
index de58feba0435..1b719d85bd04 100644
--- a/drivers/soc/tegra/fuse/fuse.h
+++ b/drivers/soc/tegra/fuse/fuse.h
@@ -43,6 +43,7 @@ struct tegra_fuse {
void __iomem *base;
phys_addr_t phys;
struct clk *clk;
+   struct reset_control *rst;
 
u32 (*read_early)(struct tegra_fuse *fuse, unsigned int offset);
u32 (*read)(struct tegra_fuse *fuse, unsigned int offset);
-- 
2.32.0



[PATCH v11 23/34] media: dt: bindings: tegra-vde: Document OPP and power domain

2021-09-12 Thread Dmitry Osipenko
Document new OPP table and power domain properties of the video decoder
hardware.

Reviewed-by: Rob Herring 
Signed-off-by: Dmitry Osipenko 
---
 .../devicetree/bindings/media/nvidia,tegra-vde.yaml  | 12 
 1 file changed, 12 insertions(+)

diff --git a/Documentation/devicetree/bindings/media/nvidia,tegra-vde.yaml 
b/Documentation/devicetree/bindings/media/nvidia,tegra-vde.yaml
index 3b6c1f031e04..0b7d4d815707 100644
--- a/Documentation/devicetree/bindings/media/nvidia,tegra-vde.yaml
+++ b/Documentation/devicetree/bindings/media/nvidia,tegra-vde.yaml
@@ -68,6 +68,16 @@ properties:
 description:
   Phandle of the SRAM MMIO node.
 
+  operating-points-v2:
+description:
+  Should contain freqs and voltages and opp-supported-hw property,
+  which is a bitfield indicating SoC speedo or process ID mask.
+
+  power-domains:
+maxItems: 1
+description:
+  Phandle to the SoC core power domain.
+
 required:
   - compatible
   - reg
@@ -104,4 +114,6 @@ examples:
   reset-names = "vde", "mc";
   resets = < 61>, < 13>;
   iommus = < 15>;
+  operating-points-v2 = <_opp_table>;
+  power-domains = <>;
 };
-- 
2.32.0



[PATCH v11 18/34] pwm: tegra: Add runtime PM and OPP support

2021-09-12 Thread Dmitry Osipenko
The PWM on Tegra belongs to the core power domain and we're going to
enable GENPD support for the core domain. Now PWM must be resumed using
runtime PM API in order to initialize the PWM power state. The PWM clock
rate must be changed using OPP API that will reconfigure the power domain
performance state in accordance to the rate. Add runtime PM and OPP
support to the PWM driver.

Signed-off-by: Dmitry Osipenko 
---
 drivers/pwm/pwm-tegra.c | 88 -
 1 file changed, 70 insertions(+), 18 deletions(-)

diff --git a/drivers/pwm/pwm-tegra.c b/drivers/pwm/pwm-tegra.c
index 11a10b575ace..afb5ecde007e 100644
--- a/drivers/pwm/pwm-tegra.c
+++ b/drivers/pwm/pwm-tegra.c
@@ -42,12 +42,16 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
+#include 
+
 #define PWM_ENABLE (1 << 31)
 #define PWM_DUTY_WIDTH 8
 #define PWM_DUTY_SHIFT 16
@@ -145,7 +149,7 @@ static int tegra_pwm_config(struct pwm_chip *chip, struct 
pwm_device *pwm,
required_clk_rate =
(NSEC_PER_SEC / period_ns) << PWM_DUTY_WIDTH;
 
-   err = clk_set_rate(pc->clk, required_clk_rate);
+   err = dev_pm_opp_set_rate(pc->dev, required_clk_rate);
if (err < 0)
return -EINVAL;
 
@@ -181,8 +185,8 @@ static int tegra_pwm_config(struct pwm_chip *chip, struct 
pwm_device *pwm,
 * before writing the register. Otherwise, keep it enabled.
 */
if (!pwm_is_enabled(pwm)) {
-   err = clk_prepare_enable(pc->clk);
-   if (err < 0)
+   err = pm_runtime_resume_and_get(pc->dev);
+   if (err)
return err;
} else
val |= PWM_ENABLE;
@@ -193,7 +197,7 @@ static int tegra_pwm_config(struct pwm_chip *chip, struct 
pwm_device *pwm,
 * If the PWM is not enabled, turn the clock off again to save power.
 */
if (!pwm_is_enabled(pwm))
-   clk_disable_unprepare(pc->clk);
+   pm_runtime_put(pc->dev);
 
return 0;
 }
@@ -204,8 +208,8 @@ static int tegra_pwm_enable(struct pwm_chip *chip, struct 
pwm_device *pwm)
int rc = 0;
u32 val;
 
-   rc = clk_prepare_enable(pc->clk);
-   if (rc < 0)
+   rc = pm_runtime_resume_and_get(pc->dev);
+   if (rc)
return rc;
 
val = pwm_readl(pc, pwm->hwpwm);
@@ -224,7 +228,7 @@ static void tegra_pwm_disable(struct pwm_chip *chip, struct 
pwm_device *pwm)
val &= ~PWM_ENABLE;
pwm_writel(pc, pwm->hwpwm, val);
 
-   clk_disable_unprepare(pc->clk);
+   pm_runtime_put_sync(pc->dev);
 }
 
 static const struct pwm_ops tegra_pwm_ops = {
@@ -256,11 +260,23 @@ static int tegra_pwm_probe(struct platform_device *pdev)
if (IS_ERR(pwm->clk))
return PTR_ERR(pwm->clk);
 
+   ret = devm_pm_runtime_enable(>dev);
+   if (ret)
+   return ret;
+
+   ret = devm_tegra_core_dev_init_opp_table_common(>dev);
+   if (ret)
+   return ret;
+
+   ret = pm_runtime_resume_and_get(>dev);
+   if (ret)
+   return ret;
+
/* Set maximum frequency of the IP */
-   ret = clk_set_rate(pwm->clk, pwm->soc->max_frequency);
+   ret = dev_pm_opp_set_rate(pwm->dev, pwm->soc->max_frequency);
if (ret < 0) {
dev_err(>dev, "Failed to set max frequency: %d\n", ret);
-   return ret;
+   goto put_pm;
}
 
/*
@@ -278,7 +294,7 @@ static int tegra_pwm_probe(struct platform_device *pdev)
if (IS_ERR(pwm->rst)) {
ret = PTR_ERR(pwm->rst);
dev_err(>dev, "Reset control is not found: %d\n", ret);
-   return ret;
+   goto put_pm;
}
 
reset_control_deassert(pwm->rst);
@@ -291,34 +307,67 @@ static int tegra_pwm_probe(struct platform_device *pdev)
if (ret < 0) {
dev_err(>dev, "pwmchip_add() failed: %d\n", ret);
reset_control_assert(pwm->rst);
-   return ret;
+   goto put_pm;
}
 
+   pm_runtime_put(>dev);
+
return 0;
+put_pm:
+   pm_runtime_put(>dev);
+   return ret;
 }
 
 static int tegra_pwm_remove(struct platform_device *pdev)
 {
struct tegra_pwm_chip *pc = platform_get_drvdata(pdev);
+   int err;
 
pwmchip_remove(>chip);
 
+   err = pm_runtime_resume_and_get(pc->dev);
+   if (err)
+   return err;
+
reset_control_assert(pc->rst);
+   pm_runtime_put(pc->dev);
 
return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int tegra_pwm_suspend(struct device *dev)
+static int __maybe_unused tegra_pwm_runtime_suspend(struct device *dev)
 {
-   return pinctrl_pm_select_sleep_state(dev);
+   struct tegra_pwm_chip *pc = dev_get_drvdata(dev);
+   int err;
+
+   clk_disable_unprepare(pc->clk);

[PATCH v11 20/34] mtd: rawnand: tegra: Add runtime PM and OPP support

2021-09-12 Thread Dmitry Osipenko
The NAND on Tegra belongs to the core power domain and we're going to
enable GENPD support for the core domain. Now NAND must be resumed using
runtime PM API in order to initialize the NAND power state. Add runtime PM
and OPP support to the NAND driver.

Acked-by: Miquel Raynal 
Signed-off-by: Dmitry Osipenko 
---
 drivers/mtd/nand/raw/tegra_nand.c | 55 ++-
 1 file changed, 47 insertions(+), 8 deletions(-)

diff --git a/drivers/mtd/nand/raw/tegra_nand.c 
b/drivers/mtd/nand/raw/tegra_nand.c
index fbf67722a049..2cce38c58a26 100644
--- a/drivers/mtd/nand/raw/tegra_nand.c
+++ b/drivers/mtd/nand/raw/tegra_nand.c
@@ -17,8 +17,11 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
+#include 
+
 #define COMMAND0x00
 #define   COMMAND_GO   BIT(31)
 #define   COMMAND_CLE  BIT(30)
@@ -1152,6 +1155,7 @@ static int tegra_nand_probe(struct platform_device *pdev)
return -ENOMEM;
 
ctrl->dev = >dev;
+   platform_set_drvdata(pdev, ctrl);
nand_controller_init(>controller);
ctrl->controller.ops = _nand_controller_ops;
 
@@ -1168,14 +1172,22 @@ static int tegra_nand_probe(struct platform_device 
*pdev)
if (IS_ERR(ctrl->clk))
return PTR_ERR(ctrl->clk);
 
-   err = clk_prepare_enable(ctrl->clk);
+   err = devm_pm_runtime_enable(>dev);
+   if (err)
+   return err;
+
+   err = devm_tegra_core_dev_init_opp_table_common(>dev);
+   if (err)
+   return err;
+
+   err = pm_runtime_resume_and_get(>dev);
if (err)
return err;
 
err = reset_control_reset(rst);
if (err) {
dev_err(ctrl->dev, "Failed to reset HW: %d\n", err);
-   goto err_disable_clk;
+   goto err_put_pm;
}
 
writel_relaxed(HWSTATUS_CMD_DEFAULT, ctrl->regs + HWSTATUS_CMD);
@@ -1190,21 +1202,19 @@ static int tegra_nand_probe(struct platform_device 
*pdev)
   dev_name(>dev), ctrl);
if (err) {
dev_err(ctrl->dev, "Failed to get IRQ: %d\n", err);
-   goto err_disable_clk;
+   goto err_put_pm;
}
 
writel_relaxed(DMA_MST_CTRL_IS_DONE, ctrl->regs + DMA_MST_CTRL);
 
err = tegra_nand_chips_init(ctrl->dev, ctrl);
if (err)
-   goto err_disable_clk;
-
-   platform_set_drvdata(pdev, ctrl);
+   goto err_put_pm;
 
return 0;
 
-err_disable_clk:
-   clk_disable_unprepare(ctrl->clk);
+err_put_pm:
+   pm_runtime_put(ctrl->dev);
return err;
 }
 
@@ -1221,11 +1231,39 @@ static int tegra_nand_remove(struct platform_device 
*pdev)
 
nand_cleanup(chip);
 
+   pm_runtime_put(ctrl->dev);
+
+   return 0;
+}
+
+static int __maybe_unused tegra_nand_runtime_resume(struct device *dev)
+{
+   struct tegra_nand_controller *ctrl = dev_get_drvdata(dev);
+   int err;
+
+   err = clk_prepare_enable(ctrl->clk);
+   if (err) {
+   dev_err(dev, "Failed to enable clock: %d\n", err);
+   return err;
+   }
+
+   return 0;
+}
+
+static int __maybe_unused tegra_nand_runtime_suspend(struct device *dev)
+{
+   struct tegra_nand_controller *ctrl = dev_get_drvdata(dev);
+
clk_disable_unprepare(ctrl->clk);
 
return 0;
 }
 
+static const struct dev_pm_ops tegra_nand_pm = {
+   SET_RUNTIME_PM_OPS(tegra_nand_runtime_suspend, 
tegra_nand_runtime_resume,
+  NULL)
+};
+
 static const struct of_device_id tegra_nand_of_match[] = {
{ .compatible = "nvidia,tegra20-nand" },
{ /* sentinel */ }
@@ -1236,6 +1274,7 @@ static struct platform_driver tegra_nand_driver = {
.driver = {
.name = "tegra-nand",
.of_match_table = tegra_nand_of_match,
+   .pm = _nand_pm,
},
.probe = tegra_nand_probe,
.remove = tegra_nand_remove,
-- 
2.32.0



[PATCH v11 22/34] media: dt: bindings: tegra-vde: Convert to schema

2021-09-12 Thread Dmitry Osipenko
Convert NVIDIA Tegra video decoder binding to schema.

Reviewed-by: Rob Herring 
Signed-off-by: Dmitry Osipenko 
---
 .../bindings/media/nvidia,tegra-vde.txt   |  64 ---
 .../bindings/media/nvidia,tegra-vde.yaml  | 107 ++
 2 files changed, 107 insertions(+), 64 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/media/nvidia,tegra-vde.txt
 create mode 100644 
Documentation/devicetree/bindings/media/nvidia,tegra-vde.yaml

diff --git a/Documentation/devicetree/bindings/media/nvidia,tegra-vde.txt 
b/Documentation/devicetree/bindings/media/nvidia,tegra-vde.txt
deleted file mode 100644
index 602169b8aa19..
--- a/Documentation/devicetree/bindings/media/nvidia,tegra-vde.txt
+++ /dev/null
@@ -1,64 +0,0 @@
-NVIDIA Tegra Video Decoder Engine
-
-Required properties:
-- compatible : Must contain one of the following values:
-   - "nvidia,tegra20-vde"
-   - "nvidia,tegra30-vde"
-   - "nvidia,tegra114-vde"
-   - "nvidia,tegra124-vde"
-   - "nvidia,tegra132-vde"
-- reg : Must contain an entry for each entry in reg-names.
-- reg-names : Must include the following entries:
-  - sxe
-  - bsev
-  - mbe
-  - ppe
-  - mce
-  - tfe
-  - ppb
-  - vdma
-  - frameid
-- iram : Must contain phandle to the mmio-sram device node that represents
- IRAM region used by VDE.
-- interrupts : Must contain an entry for each entry in interrupt-names.
-- interrupt-names : Must include the following entries:
-  - sync-token
-  - bsev
-  - sxe
-- clocks : Must include the following entries:
-  - vde
-- resets : Must contain an entry for each entry in reset-names.
-- reset-names : Should include the following entries:
-  - vde
-
-Optional properties:
-- resets : Must contain an entry for each entry in reset-names.
-- reset-names : Must include the following entries:
-  - mc
-- iommus: Must contain phandle to the IOMMU device node.
-
-Example:
-
-video-codec@6001a000 {
-   compatible = "nvidia,tegra20-vde";
-   reg = <0x6001a000 0x1000 /* Syntax Engine */
-  0x6001b000 0x1000 /* Video Bitstream Engine */
-  0x6001c000  0x100 /* Macroblock Engine */
-  0x6001c200  0x100 /* Post-processing Engine */
-  0x6001c400  0x100 /* Motion Compensation Engine */
-  0x6001c600  0x100 /* Transform Engine */
-  0x6001c800  0x100 /* Pixel prediction block */
-  0x6001ca00  0x100 /* Video DMA */
-  0x6001d800  0x300 /* Video frame controls */>;
-   reg-names = "sxe", "bsev", "mbe", "ppe", "mce",
-   "tfe", "ppb", "vdma", "frameid";
-   iram = <_pool>; /* IRAM region */
-   interrupts = , /* Sync token interrupt 
*/
-, /* BSE-V interrupt */
-; /* SXE interrupt */
-   interrupt-names = "sync-token", "bsev", "sxe";
-   clocks = <_car TEGRA20_CLK_VDE>;
-   reset-names = "vde", "mc";
-   resets = <_car 61>, < TEGRA20_MC_RESET_VDE>;
-   iommus = < TEGRA_SWGROUP_VDE>;
-};
diff --git a/Documentation/devicetree/bindings/media/nvidia,tegra-vde.yaml 
b/Documentation/devicetree/bindings/media/nvidia,tegra-vde.yaml
new file mode 100644
index ..3b6c1f031e04
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/nvidia,tegra-vde.yaml
@@ -0,0 +1,107 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/nvidia,tegra-vde.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NVIDIA Tegra Video Decoder Engine
+
+maintainers:
+  - Dmitry Osipenko 
+  - Jon Hunter 
+  - Thierry Reding 
+
+properties:
+  compatible:
+oneOf:
+  - items:
+  - enum:
+  - nvidia,tegra132-vde
+  - nvidia,tegra124-vde
+  - nvidia,tegra114-vde
+  - nvidia,tegra30-vde
+  - enum:
+  - nvidia,tegra20-vde
+  - items:
+  - const: nvidia,tegra20-vde
+
+  reg:
+maxItems: 9
+
+  reg-names:
+items:
+  - const: sxe
+  - const: bsev
+  - const: mbe
+  - const: ppe
+  - const: mce
+  - const: tfe
+  - const: ppb
+  - const: vdma
+  - const: frameid
+
+  clocks:
+maxItems: 1
+
+  resets:
+maxItems: 2
+
+  reset-names:
+items:
+  - const: vde
+  - const: mc
+
+  interrupts:
+maxItems: 3
+
+  interrupt-names:
+items:
+  - const: sync-token
+  - const: bsev
+  - const: sxe
+
+  iommus:
+maxItems: 1
+
+  iram:
+$ref: /schemas/types.yaml#/definitions/phandle
+description:
+  Phandle of the SRAM MMIO node.
+
+required:
+  - compatible
+  - reg
+  - reg-names
+  - clocks
+  - resets
+  - reset-names
+  - interrupts
+  - interrupt-names
+
+additionalProperties: false
+
+examples:
+  - |
+video-codec@6001a000 {
+  compatible = "nvidia,tegra20-vde";
+  reg = <0x6001a000 0x1000>, /* Syntax Engine */
+<0x6001b000 0x1000>, /* Video Bitstream Engine */
+

[PATCH v11 19/34] mmc: sdhci-tegra: Add runtime PM and OPP support

2021-09-12 Thread Dmitry Osipenko
The SDHCI on Tegra belongs to the core power domain and we're going to
enable GENPD support for the core domain. Now SDHCI must be resumed using
runtime PM API in order to initialize the SDHCI power state. The SDHCI
clock rate must be changed using OPP API that will reconfigure the power
domain performance state in accordance to the rate. Add runtime PM and OPP
support to the SDHCI driver.

Signed-off-by: Dmitry Osipenko 
---
 drivers/mmc/host/sdhci-tegra.c | 82 +++---
 1 file changed, 66 insertions(+), 16 deletions(-)

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index a5001875876b..6cf3712bf0a6 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -15,6 +15,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -24,6 +26,8 @@
 #include 
 #include 
 
+#include 
+
 #include "sdhci-pltfm.h"
 #include "cqhci.h"
 
@@ -760,7 +764,9 @@ static void tegra_sdhci_set_clock(struct sdhci_host *host, 
unsigned int clock)
 {
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
+   struct device *dev = mmc_dev(host->mmc);
unsigned long host_clk;
+   int err;
 
if (!clock)
return sdhci_set_clock(host, clock);
@@ -778,7 +784,12 @@ static void tegra_sdhci_set_clock(struct sdhci_host *host, 
unsigned int clock)
 * from clk_get_rate() is used.
 */
host_clk = tegra_host->ddr_signaling ? clock * 2 : clock;
-   clk_set_rate(pltfm_host->clk, host_clk);
+
+   err = dev_pm_opp_set_rate(dev, host_clk);
+   if (err)
+   dev_err(dev, "failed to set clk rate to %luHz: %d\n",
+   host_clk, err);
+
tegra_host->curr_clk_rate = host_clk;
if (tegra_host->ddr_signaling)
host->max_clk = host_clk;
@@ -1705,7 +1716,6 @@ static int sdhci_tegra_probe(struct platform_device *pdev)
   "failed to get clock\n");
goto err_clk_get;
}
-   clk_prepare_enable(clk);
pltfm_host->clk = clk;
 
tegra_host->rst = devm_reset_control_get_exclusive(>dev,
@@ -1716,15 +1726,25 @@ static int sdhci_tegra_probe(struct platform_device 
*pdev)
goto err_rst_get;
}
 
+   pm_runtime_enable(>dev);
+
+   rc = devm_tegra_core_dev_init_opp_table_common(>dev);
+   if (rc)
+   goto err_pm_get;
+
+   rc = pm_runtime_resume_and_get(>dev);
+   if (rc)
+   goto err_pm_get;
+
rc = reset_control_assert(tegra_host->rst);
if (rc)
-   goto err_rst_get;
+   goto err_rst_assert;
 
usleep_range(2000, 4000);
 
rc = reset_control_deassert(tegra_host->rst);
if (rc)
-   goto err_rst_get;
+   goto err_rst_assert;
 
usleep_range(2000, 4000);
 
@@ -1736,8 +1756,11 @@ static int sdhci_tegra_probe(struct platform_device 
*pdev)
 
 err_add_host:
reset_control_assert(tegra_host->rst);
+err_rst_assert:
+   pm_runtime_put(>dev);
+err_pm_get:
+   pm_runtime_disable(>dev);
 err_rst_get:
-   clk_disable_unprepare(pltfm_host->clk);
 err_clk_get:
clk_disable_unprepare(tegra_host->tmclk);
 err_power_req:
@@ -1756,19 +1779,38 @@ static int sdhci_tegra_remove(struct platform_device 
*pdev)
 
reset_control_assert(tegra_host->rst);
usleep_range(2000, 4000);
-   clk_disable_unprepare(pltfm_host->clk);
-   clk_disable_unprepare(tegra_host->tmclk);
 
+   pm_runtime_put(>dev);
+   pm_runtime_disable(>dev);
+
+   clk_disable_unprepare(tegra_host->tmclk);
sdhci_pltfm_free(pdev);
 
return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int __maybe_unused sdhci_tegra_suspend(struct device *dev)
+static int __maybe_unused sdhci_tegra_runtime_suspend(struct device *dev)
 {
struct sdhci_host *host = dev_get_drvdata(dev);
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+
+   clk_disable_unprepare(pltfm_host->clk);
+
+   return 0;
+}
+
+static int __maybe_unused sdhci_tegra_runtime_resume(struct device *dev)
+{
+   struct sdhci_host *host = dev_get_drvdata(dev);
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+
+   return clk_prepare_enable(pltfm_host->clk);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int sdhci_tegra_suspend(struct device *dev)
+{
+   struct sdhci_host *host = dev_get_drvdata(dev);
int ret;
 
if (host->mmc->caps2 & MMC_CAP2_CQE) {
@@ -1783,17 +1825,22 @@ static int __maybe_unused sdhci_tegra_suspend(struct 
device *dev)
return ret;
}
 
-   clk_disable_unprepare(pltfm_host->clk);
+   ret = pm_runtime_force_suspend(dev);
+   if (ret) {
+   sdhci_resume_host(host);
+   cqhci_resume(host->mmc);
+   return ret;
+   }
+

[PATCH v11 21/34] spi: tegra20-slink: Add OPP support

2021-09-12 Thread Dmitry Osipenko
The SPI on Tegra belongs to the core power domain and we're going to
enable GENPD support for the core domain. Now SPI driver must use OPP
API for driving the controller's clock rate because OPP API takes care
of reconfiguring the domain's performance state in accordance to the
rate. Add OPP support to the driver.

Acked-by: Mark Brown 
Signed-off-by: Dmitry Osipenko 
---
 drivers/spi/spi-tegra20-slink.c | 10 +-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c
index 8ce840c7ecc8..1a92978d2120 100644
--- a/drivers/spi/spi-tegra20-slink.c
+++ b/drivers/spi/spi-tegra20-slink.c
@@ -18,12 +18,15 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
 
+#include 
+
 #define SLINK_COMMAND  0x000
 #define SLINK_BIT_LENGTH(x)(((x) & 0x1f) << 0)
 #define SLINK_WORD_SIZE(x) (((x) & 0x1f) << 5)
@@ -680,7 +683,7 @@ static int tegra_slink_start_transfer_one(struct spi_device 
*spi,
bits_per_word = t->bits_per_word;
speed = t->speed_hz;
if (speed != tspi->cur_speed) {
-   clk_set_rate(tspi->clk, speed * 4);
+   dev_pm_opp_set_rate(tspi->dev, speed * 4);
tspi->cur_speed = speed;
}
 
@@ -1082,6 +1085,11 @@ static int tegra_slink_probe(struct platform_device 
*pdev)
init_completion(>xfer_completion);
 
pm_runtime_enable(>dev);
+
+   ret = devm_tegra_core_dev_init_opp_table_common(>dev);
+   if (ret)
+   goto exit_pm_disable;
+
ret = pm_runtime_resume_and_get(>dev);
if (ret) {
dev_err(>dev, "pm runtime get failed, e = %d\n", ret);
-- 
2.32.0



[PATCH v11 17/34] bus: tegra-gmi: Add runtime PM and OPP support

2021-09-12 Thread Dmitry Osipenko
The GMI bus on Tegra belongs to the core power domain and we're going to
enable GENPD support for the core domain. Now GMI must be resumed using
runtime PM API in order to initialize the GMI power state. Add runtime PM
and OPP support to the GMI driver.

Signed-off-by: Dmitry Osipenko 
---
 drivers/bus/tegra-gmi.c | 52 -
 1 file changed, 46 insertions(+), 6 deletions(-)

diff --git a/drivers/bus/tegra-gmi.c b/drivers/bus/tegra-gmi.c
index a6570789f7af..72ef8a8c236b 100644
--- a/drivers/bus/tegra-gmi.c
+++ b/drivers/bus/tegra-gmi.c
@@ -13,8 +13,11 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
+#include 
+
 #define TEGRA_GMI_CONFIG   0x00
 #define TEGRA_GMI_CONFIG_GOBIT(31)
 #define TEGRA_GMI_BUS_WIDTH_32BIT  BIT(30)
@@ -54,9 +57,9 @@ static int tegra_gmi_enable(struct tegra_gmi *gmi)
 {
int err;
 
-   err = clk_prepare_enable(gmi->clk);
-   if (err < 0) {
-   dev_err(gmi->dev, "failed to enable clock: %d\n", err);
+   err = pm_runtime_resume_and_get(gmi->dev);
+   if (err) {
+   pm_runtime_disable(gmi->dev);
return err;
}
 
@@ -83,7 +86,8 @@ static void tegra_gmi_disable(struct tegra_gmi *gmi)
writel(config, gmi->base + TEGRA_GMI_CONFIG);
 
reset_control_assert(gmi->rst);
-   clk_disable_unprepare(gmi->clk);
+
+   pm_runtime_put(gmi->dev);
 }
 
 static int tegra_gmi_parse_dt(struct tegra_gmi *gmi)
@@ -213,6 +217,7 @@ static int tegra_gmi_probe(struct platform_device *pdev)
if (!gmi)
return -ENOMEM;
 
+   platform_set_drvdata(pdev, gmi);
gmi->dev = dev;
 
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -232,6 +237,14 @@ static int tegra_gmi_probe(struct platform_device *pdev)
return PTR_ERR(gmi->rst);
}
 
+   err = devm_pm_runtime_enable(gmi->dev);
+   if (err)
+   return err;
+
+   err = devm_tegra_core_dev_init_opp_table_common(>dev);
+   if (err)
+   return err;
+
err = tegra_gmi_parse_dt(gmi);
if (err)
return err;
@@ -247,8 +260,6 @@ static int tegra_gmi_probe(struct platform_device *pdev)
return err;
}
 
-   platform_set_drvdata(pdev, gmi);
-
return 0;
 }
 
@@ -262,6 +273,34 @@ static int tegra_gmi_remove(struct platform_device *pdev)
return 0;
 }
 
+static int __maybe_unused tegra_gmi_runtime_resume(struct device *dev)
+{
+   struct tegra_gmi *gmi = dev_get_drvdata(dev);
+   int err;
+
+   err = clk_prepare_enable(gmi->clk);
+   if (err < 0) {
+   dev_err(gmi->dev, "failed to enable clock: %d\n", err);
+   return err;
+   }
+
+   return 0;
+}
+
+static int __maybe_unused tegra_gmi_runtime_suspend(struct device *dev)
+{
+   struct tegra_gmi *gmi = dev_get_drvdata(dev);
+
+   clk_disable_unprepare(gmi->clk);
+
+   return 0;
+}
+
+static const struct dev_pm_ops tegra_gmi_pm = {
+   SET_RUNTIME_PM_OPS(tegra_gmi_runtime_suspend, tegra_gmi_runtime_resume,
+  NULL)
+};
+
 static const struct of_device_id tegra_gmi_id_table[] = {
{ .compatible = "nvidia,tegra20-gmi", },
{ .compatible = "nvidia,tegra30-gmi", },
@@ -275,6 +314,7 @@ static struct platform_driver tegra_gmi_driver = {
.driver = {
.name   = "tegra-gmi",
.of_match_table = tegra_gmi_id_table,
+   .pm = _gmi_pm,
},
 };
 module_platform_driver(tegra_gmi_driver);
-- 
2.32.0



[PATCH v11 16/34] usb: chipidea: tegra: Add runtime PM and OPP support

2021-09-12 Thread Dmitry Osipenko
The Tegra USB controller belongs to the core power domain and we're going
to enable GENPD support for the core domain. Now USB controller must be
resumed using runtime PM API in order to initialize the USB power state.
We already support runtime PM for the CI device, but CI's PM is separated
from the RPM managed by tegra-usb driver. Add runtime PM and OPP support
to the driver.

Signed-off-by: Dmitry Osipenko 
---
 drivers/usb/chipidea/ci_hdrc_tegra.c | 53 
 1 file changed, 46 insertions(+), 7 deletions(-)

diff --git a/drivers/usb/chipidea/ci_hdrc_tegra.c 
b/drivers/usb/chipidea/ci_hdrc_tegra.c
index 60361141ac04..3142ef7ebe42 100644
--- a/drivers/usb/chipidea/ci_hdrc_tegra.c
+++ b/drivers/usb/chipidea/ci_hdrc_tegra.c
@@ -7,6 +7,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include 
@@ -15,6 +16,8 @@
 #include 
 #include 
 
+#include 
+
 #include "../host/ehci.h"
 
 #include "ci.h"
@@ -278,6 +281,8 @@ static int tegra_usb_probe(struct platform_device *pdev)
if (!usb)
return -ENOMEM;
 
+   platform_set_drvdata(pdev, usb);
+
soc = of_device_get_match_data(>dev);
if (!soc) {
dev_err(>dev, "failed to match OF data\n");
@@ -296,11 +301,17 @@ static int tegra_usb_probe(struct platform_device *pdev)
return err;
}
 
-   err = clk_prepare_enable(usb->clk);
-   if (err < 0) {
-   dev_err(>dev, "failed to enable clock: %d\n", err);
+   err = devm_pm_runtime_enable(>dev);
+   if (err)
+   return err;
+
+   err = devm_tegra_core_dev_init_opp_table_common(>dev);
+   if (err)
+   return err;
+
+   err = pm_runtime_resume_and_get(>dev);
+   if (err)
return err;
-   }
 
if (device_property_present(>dev, "nvidia,needs-double-reset"))
usb->needs_double_reset = true;
@@ -320,8 +331,6 @@ static int tegra_usb_probe(struct platform_device *pdev)
if (err)
goto fail_power_off;
 
-   platform_set_drvdata(pdev, usb);
-
/* setup and register ChipIdea HDRC device */
usb->soc = soc;
usb->data.name = "tegra-usb";
@@ -350,7 +359,8 @@ static int tegra_usb_probe(struct platform_device *pdev)
 phy_shutdown:
usb_phy_shutdown(usb->phy);
 fail_power_off:
-   clk_disable_unprepare(usb->clk);
+   pm_runtime_put(>dev);
+
return err;
 }
 
@@ -360,15 +370,44 @@ static int tegra_usb_remove(struct platform_device *pdev)
 
ci_hdrc_remove_device(usb->dev);
usb_phy_shutdown(usb->phy);
+   pm_runtime_put(>dev);
+
+   return 0;
+}
+
+static int __maybe_unused tegra_usb_runtime_resume(struct device *dev)
+{
+   struct tegra_usb *usb = dev_get_drvdata(dev);
+   int err;
+
+   err = clk_prepare_enable(usb->clk);
+   if (err < 0) {
+   dev_err(dev, "failed to enable clock: %d\n", err);
+   return err;
+   }
+
+   return 0;
+}
+
+static int __maybe_unused tegra_usb_runtime_suspend(struct device *dev)
+{
+   struct tegra_usb *usb = dev_get_drvdata(dev);
+
clk_disable_unprepare(usb->clk);
 
return 0;
 }
 
+static const struct dev_pm_ops tegra_usb_pm = {
+   SET_RUNTIME_PM_OPS(tegra_usb_runtime_suspend, tegra_usb_runtime_resume,
+  NULL)
+};
+
 static struct platform_driver tegra_usb_driver = {
.driver = {
.name = "tegra-usb",
.of_match_table = tegra_usb_of_match,
+   .pm = _usb_pm,
},
.probe = tegra_usb_probe,
.remove = tegra_usb_remove,
-- 
2.32.0



[PATCH v11 14/34] drm/tegra: gr3d: Support generic power domain and runtime PM

2021-09-12 Thread Dmitry Osipenko
Add runtime power management and support generic power domains.

Tested-by: Peter Geis  # Ouya T30
Tested-by: Paul Fertser  # PAZ00 T20
Tested-by: Nicolas Chauvet  # PAZ00 T20 and TK1 T124
Tested-by: Matt Merhar  # Ouya T30
Signed-off-by: Dmitry Osipenko 
---
 drivers/gpu/drm/tegra/gr3d.c | 388 ++-
 1 file changed, 332 insertions(+), 56 deletions(-)

diff --git a/drivers/gpu/drm/tegra/gr3d.c b/drivers/gpu/drm/tegra/gr3d.c
index 24442ade0da3..5879402ae55e 100644
--- a/drivers/gpu/drm/tegra/gr3d.c
+++ b/drivers/gpu/drm/tegra/gr3d.c
@@ -5,32 +5,47 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
+#include 
+#include 
+#include 
 #include 
 
+#include 
 #include 
 
 #include "drm.h"
 #include "gem.h"
 #include "gr3d.h"
 
+enum {
+   RST_MC,
+   RST_GR3D,
+   RST_MC2,
+   RST_GR3D2,
+   RST_GR3D_MAX,
+};
+
 struct gr3d_soc {
unsigned int version;
+   unsigned int num_clocks;
+   unsigned int num_resets;
 };
 
 struct gr3d {
struct tegra_drm_client client;
struct host1x_channel *channel;
-   struct clk *clk_secondary;
-   struct clk *clk;
-   struct reset_control *rst_secondary;
-   struct reset_control *rst;
 
const struct gr3d_soc *soc;
+   struct clk_bulk_data *clocks;
+   unsigned int nclocks;
+   struct reset_control_bulk_data resets[RST_GR3D_MAX];
+   unsigned int nresets;
 
DECLARE_BITMAP(addr_regs, GR3D_NUM_REGS);
 };
@@ -109,16 +124,24 @@ static int gr3d_open_channel(struct tegra_drm_client 
*client,
 struct tegra_drm_context *context)
 {
struct gr3d *gr3d = to_gr3d(client);
+   int err;
 
context->channel = host1x_channel_get(gr3d->channel);
if (!context->channel)
return -ENOMEM;
 
+   err = pm_runtime_resume_and_get(client->base.dev);
+   if (err) {
+   host1x_channel_put(context->channel);
+   return err;
+   }
+
return 0;
 }
 
 static void gr3d_close_channel(struct tegra_drm_context *context)
 {
+   pm_runtime_put_sync(context->client->base.dev);
host1x_channel_put(context->channel);
 }
 
@@ -155,14 +178,20 @@ static const struct tegra_drm_client_ops gr3d_ops = {
 
 static const struct gr3d_soc tegra20_gr3d_soc = {
.version = 0x20,
+   .num_clocks = 1,
+   .num_resets = 2,
 };
 
 static const struct gr3d_soc tegra30_gr3d_soc = {
.version = 0x30,
+   .num_clocks = 2,
+   .num_resets = 4,
 };
 
 static const struct gr3d_soc tegra114_gr3d_soc = {
.version = 0x35,
+   .num_clocks = 1,
+   .num_resets = 2,
 };
 
 static const struct of_device_id tegra_gr3d_match[] = {
@@ -278,69 +307,240 @@ static const u32 gr3d_addr_regs[] = {
GR3D_GLOBAL_SAMP23SURFADDR(15),
 };
 
-static int gr3d_probe(struct platform_device *pdev)
+static int gr3d_power_up_legacy_domain(struct device *dev, const char *name,
+  unsigned int id)
 {
-   struct device_node *np = pdev->dev.of_node;
-   struct host1x_syncpt **syncpts;
-   struct gr3d *gr3d;
+   struct gr3d *gr3d = dev_get_drvdata(dev);
+   struct reset_control *reset;
+   struct clk *clk;
unsigned int i;
int err;
 
-   gr3d = devm_kzalloc(>dev, sizeof(*gr3d), GFP_KERNEL);
-   if (!gr3d)
-   return -ENOMEM;
-
-   gr3d->soc = of_device_get_match_data(>dev);
+   /*
+* Tegra20 device-tree doesn't specify 3d clock name and there is only
+* one clock for Tegra20. Tegra30+ device-trees always specified names
+* for the clocks.
+*/
+   if (gr3d->nclocks == 1) {
+   if (id == TEGRA_POWERGATE_3D1)
+   return 0;
+
+   clk = gr3d->clocks[0].clk;
+   } else {
+   for (i = 0; i < gr3d->nclocks; i++) {
+   if (WARN_ON(!gr3d->clocks[i].id))
+   continue;
+
+   if (!strcmp(gr3d->clocks[i].id, name)) {
+   clk = gr3d->clocks[i].clk;
+   break;
+   }
+   }
 
-   syncpts = devm_kzalloc(>dev, sizeof(*syncpts), GFP_KERNEL);
-   if (!syncpts)
-   return -ENOMEM;
+   if (WARN_ON(i == gr3d->nclocks))
+   return -EINVAL;
+   }
 
-   gr3d->clk = devm_clk_get(>dev, NULL);
-   if (IS_ERR(gr3d->clk)) {
-   dev_err(>dev, "cannot get clock\n");
-   return PTR_ERR(gr3d->clk);
+   /*
+* We use array of resets, which includes MC resets, and MC
+* reset shouldn't be asserted while hardware is gated because
+* MC flushing will fail for gated hardware. Hence for legacy
+* PD we request the individual reset separately.
+*/
+   reset = reset_control_get_exclusive_released(dev, 

[PATCH v11 15/34] drm/tegra: vic: Support system suspend

2021-09-12 Thread Dmitry Osipenko
Hardware must be stopped before system is suspended. Add suspend-resume
callbacks.

Signed-off-by: Dmitry Osipenko 
---
 drivers/gpu/drm/tegra/vic.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/tegra/vic.c b/drivers/gpu/drm/tegra/vic.c
index c02010ff2b7f..359dd77f8b85 100644
--- a/drivers/gpu/drm/tegra/vic.c
+++ b/drivers/gpu/drm/tegra/vic.c
@@ -315,6 +315,8 @@ static int vic_runtime_suspend(struct device *dev)
struct vic *vic = dev_get_drvdata(dev);
int err;
 
+   host1x_channel_stop(vic->channel);
+
err = reset_control_assert(vic->rst);
if (err < 0)
return err;
@@ -517,6 +519,8 @@ static int vic_remove(struct platform_device *pdev)
 
 static const struct dev_pm_ops vic_pm_ops = {
SET_RUNTIME_PM_OPS(vic_runtime_suspend, vic_runtime_resume, NULL)
+   SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+   pm_runtime_force_resume)
 };
 
 struct platform_driver tegra_vic_driver = {
-- 
2.32.0



[PATCH v11 12/34] drm/tegra: hdmi: Add OPP support

2021-09-12 Thread Dmitry Osipenko
The HDMI on Tegra belongs to the core power domain and we're going to
enable GENPD support for the core domain. Now HDMI driver must use
OPP API for driving the controller's clock rate because OPP API takes
care of reconfiguring the domain's performance state based on HDMI clock
rate. Add OPP support to the HDMI driver.

Signed-off-by: Dmitry Osipenko 
---
 drivers/gpu/drm/tegra/hdmi.c | 16 
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c
index e5d2a4026028..9a87d351a828 100644
--- a/drivers/gpu/drm/tegra/hdmi.c
+++ b/drivers/gpu/drm/tegra/hdmi.c
@@ -11,10 +11,13 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 
+#include 
+
 #include 
 #include 
 #include 
@@ -1195,7 +1198,7 @@ static void tegra_hdmi_encoder_enable(struct drm_encoder 
*encoder)
h_back_porch = mode->htotal - mode->hsync_end;
h_front_porch = mode->hsync_start - mode->hdisplay;
 
-   err = clk_set_rate(hdmi->clk, hdmi->pixel_clock);
+   err = dev_pm_opp_set_rate(hdmi->dev, hdmi->pixel_clock);
if (err < 0) {
dev_err(hdmi->dev, "failed to set HDMI clock frequency: %d\n",
err);
@@ -1732,7 +1735,14 @@ static int tegra_hdmi_probe(struct platform_device *pdev)
}
 
platform_set_drvdata(pdev, hdmi);
-   pm_runtime_enable(>dev);
+
+   err = devm_pm_runtime_enable(>dev);
+   if (err)
+   return err;
+
+   err = devm_tegra_core_dev_init_opp_table_common(>dev);
+   if (err)
+   return err;
 
INIT_LIST_HEAD(>client.list);
hdmi->client.ops = _client_ops;
@@ -1753,8 +1763,6 @@ static int tegra_hdmi_remove(struct platform_device *pdev)
struct tegra_hdmi *hdmi = platform_get_drvdata(pdev);
int err;
 
-   pm_runtime_disable(>dev);
-
err = host1x_client_unregister(>client);
if (err < 0) {
dev_err(>dev, "failed to unregister host1x client: %d\n",
-- 
2.32.0



[PATCH v11 13/34] drm/tegra: gr2d: Support generic power domain and runtime PM

2021-09-12 Thread Dmitry Osipenko
Add runtime power management and support generic power domains.

Tested-by: Peter Geis  # Ouya T30
Tested-by: Paul Fertser  # PAZ00 T20
Tested-by: Nicolas Chauvet  # PAZ00 T20 and TK1 T124
Tested-by: Matt Merhar  # Ouya T30
Signed-off-by: Dmitry Osipenko 
---
 drivers/gpu/drm/tegra/gr2d.c | 155 +--
 1 file changed, 147 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/tegra/gr2d.c b/drivers/gpu/drm/tegra/gr2d.c
index de288cba3905..13df8f118f75 100644
--- a/drivers/gpu/drm/tegra/gr2d.c
+++ b/drivers/gpu/drm/tegra/gr2d.c
@@ -7,11 +7,21 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+
+#include 
 
 #include "drm.h"
 #include "gem.h"
 #include "gr2d.h"
 
+enum {
+   RST_MC,
+   RST_GR2D,
+   RST_GR2D_MAX,
+};
+
 struct gr2d_soc {
unsigned int version;
 };
@@ -21,6 +31,9 @@ struct gr2d {
struct host1x_channel *channel;
struct clk *clk;
 
+   struct reset_control_bulk_data resets[RST_GR2D_MAX];
+   unsigned int nresets;
+
const struct gr2d_soc *soc;
 
DECLARE_BITMAP(addr_regs, GR2D_NUM_REGS);
@@ -101,16 +114,24 @@ static int gr2d_open_channel(struct tegra_drm_client 
*client,
 struct tegra_drm_context *context)
 {
struct gr2d *gr2d = to_gr2d(client);
+   int err;
 
context->channel = host1x_channel_get(gr2d->channel);
if (!context->channel)
return -ENOMEM;
 
+   err = pm_runtime_resume_and_get(client->base.dev);
+   if (err) {
+   host1x_channel_put(context->channel);
+   return err;
+   }
+
return 0;
 }
 
 static void gr2d_close_channel(struct tegra_drm_context *context)
 {
+   pm_runtime_put_sync(context->client->base.dev);
host1x_channel_put(context->channel);
 }
 
@@ -190,6 +211,27 @@ static const u32 gr2d_addr_regs[] = {
GR2D_VA_BASE_ADDR_SB,
 };
 
+static int gr2d_get_resets(struct device *dev, struct gr2d *gr2d)
+{
+   int err;
+
+   gr2d->resets[RST_MC].id = "mc";
+   gr2d->resets[RST_GR2D].id = "2d";
+   gr2d->nresets = RST_GR2D_MAX;
+
+   err = devm_reset_control_bulk_get_optional_exclusive_released(
+   dev, gr2d->nresets, gr2d->resets);
+   if (err) {
+   dev_err(dev, "failed to get reset: %d\n", err);
+   return err;
+   }
+
+   if (WARN_ON(!gr2d->resets[RST_GR2D].rstc))
+   return -ENOENT;
+
+   return 0;
+}
+
 static int gr2d_probe(struct platform_device *pdev)
 {
struct device *dev = >dev;
@@ -202,6 +244,8 @@ static int gr2d_probe(struct platform_device *pdev)
if (!gr2d)
return -ENOMEM;
 
+   platform_set_drvdata(pdev, gr2d);
+
gr2d->soc = of_device_get_match_data(dev);
 
syncpts = devm_kzalloc(dev, sizeof(*syncpts), GFP_KERNEL);
@@ -214,11 +258,9 @@ static int gr2d_probe(struct platform_device *pdev)
return PTR_ERR(gr2d->clk);
}
 
-   err = clk_prepare_enable(gr2d->clk);
-   if (err) {
-   dev_err(dev, "cannot turn on clock\n");
+   err = gr2d_get_resets(dev, gr2d);
+   if (err)
return err;
-   }
 
INIT_LIST_HEAD(>client.base.list);
gr2d->client.base.ops = _client_ops;
@@ -231,20 +273,31 @@ static int gr2d_probe(struct platform_device *pdev)
gr2d->client.version = gr2d->soc->version;
gr2d->client.ops = _ops;
 
+   pm_runtime_enable(dev);
+   pm_runtime_use_autosuspend(dev);
+   pm_runtime_set_autosuspend_delay(dev, 200);
+
+   err = devm_tegra_core_dev_init_opp_table_common(dev);
+   if (err)
+   goto disable_rpm;
+
err = host1x_client_register(>client.base);
if (err < 0) {
dev_err(dev, "failed to register host1x client: %d\n", err);
-   clk_disable_unprepare(gr2d->clk);
-   return err;
+   goto disable_rpm;
}
 
/* initialize address register map */
for (i = 0; i < ARRAY_SIZE(gr2d_addr_regs); i++)
set_bit(gr2d_addr_regs[i], gr2d->addr_regs);
 
-   platform_set_drvdata(pdev, gr2d);
-
return 0;
+
+disable_rpm:
+   pm_runtime_dont_use_autosuspend(dev);
+   pm_runtime_disable(dev);
+
+   return err;
 }
 
 static int gr2d_remove(struct platform_device *pdev)
@@ -259,15 +312,101 @@ static int gr2d_remove(struct platform_device *pdev)
return err;
}
 
+   pm_runtime_dont_use_autosuspend(>dev);
+   pm_runtime_disable(>dev);
+
+   return 0;
+}
+
+static int __maybe_unused gr2d_runtime_suspend(struct device *dev)
+{
+   struct gr2d *gr2d = dev_get_drvdata(dev);
+   int err;
+
+   host1x_channel_stop(gr2d->channel);
+   reset_control_bulk_release(gr2d->nresets, gr2d->resets);
+
+   /*
+* GR2D module shouldn't be reset while hardware is idling, otherwise
+* host1x's cmdproc will 

[PATCH v11 11/34] drm/tegra: dc: Support OPP and SoC core voltage scaling

2021-09-12 Thread Dmitry Osipenko
Add OPP and SoC core voltage scaling support to the display controller
driver. This is required for enabling system-wide DVFS on pre-Tegra186
SoCs.

Tested-by: Peter Geis  # Ouya T30
Tested-by: Paul Fertser  # PAZ00 T20
Tested-by: Nicolas Chauvet  # PAZ00 T20 and TK1 T124
Tested-by: Matt Merhar  # Ouya T30
Signed-off-by: Dmitry Osipenko 
---
 drivers/gpu/drm/tegra/dc.c | 74 ++
 drivers/gpu/drm/tegra/dc.h |  2 ++
 2 files changed, 76 insertions(+)

diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index a29d64f87563..d4047a14e2b6 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -11,9 +11,12 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
 
+#include 
 #include 
 
 #include 
@@ -1762,6 +1765,47 @@ int tegra_dc_state_setup_clock(struct tegra_dc *dc,
return 0;
 }
 
+static void tegra_dc_update_voltage_state(struct tegra_dc *dc,
+ struct tegra_dc_state *state)
+{
+   unsigned long rate, pstate;
+   struct dev_pm_opp *opp;
+   int err;
+
+   if (!dc->has_opp_table)
+   return;
+
+   /* calculate actual pixel clock rate which depends on internal divider 
*/
+   rate = DIV_ROUND_UP(clk_get_rate(dc->clk) * 2, state->div + 2);
+
+   /* find suitable OPP for the rate */
+   opp = dev_pm_opp_find_freq_ceil(dc->dev, );
+
+   if (opp == ERR_PTR(-ERANGE))
+   opp = dev_pm_opp_find_freq_floor(dc->dev, );
+
+   if (IS_ERR(opp)) {
+   dev_err(dc->dev, "failed to find OPP for %luHz: %pe\n",
+   rate, opp);
+   return;
+   }
+
+   pstate = dev_pm_opp_get_required_pstate(opp, 0);
+   dev_pm_opp_put(opp);
+
+   /*
+* The minimum core voltage depends on the pixel clock rate (which
+* depends on internal clock divider of the CRTC) and not on the
+* rate of the display controller clock. This is why we're not using
+* dev_pm_opp_set_rate() API and instead controlling the power domain
+* directly.
+*/
+   err = dev_pm_genpd_set_performance_state(dc->dev, pstate);
+   if (err)
+   dev_err(dc->dev, "failed to set power domain state to %lu: 
%d\n",
+   pstate, err);
+}
+
 static void tegra_dc_commit_state(struct tegra_dc *dc,
  struct tegra_dc_state *state)
 {
@@ -1801,6 +1845,8 @@ static void tegra_dc_commit_state(struct tegra_dc *dc,
value = SHIFT_CLK_DIVIDER(state->div) | PIXEL_CLK_DIVIDER_PCD1;
tegra_dc_writel(dc, value, DC_DISP_DISP_CLOCK_CONTROL);
}
+
+   tegra_dc_update_voltage_state(dc, state);
 }
 
 static void tegra_dc_stop(struct tegra_dc *dc)
@@ -1991,6 +2037,13 @@ static void tegra_crtc_atomic_disable(struct drm_crtc 
*crtc,
err = host1x_client_suspend(>client);
if (err < 0)
dev_err(dc->dev, "failed to suspend: %d\n", err);
+
+   if (dc->has_opp_table) {
+   err = dev_pm_genpd_set_performance_state(dc->dev, 0);
+   if (err)
+   dev_err(dc->dev,
+   "failed to clear power domain state: %d\n", 
err);
+   }
 }
 
 static void tegra_crtc_atomic_enable(struct drm_crtc *crtc,
@@ -2973,6 +3026,23 @@ static int tegra_dc_couple(struct tegra_dc *dc)
return 0;
 }
 
+static int tegra_dc_init_opp_table(struct tegra_dc *dc)
+{
+   struct tegra_core_opp_params opp_params = {};
+   int err;
+
+   err = devm_tegra_core_dev_init_opp_table(dc->dev, _params);
+   if (err && err != -ENODEV)
+   return err;
+
+   if (err)
+   dc->has_opp_table = false;
+   else
+   dc->has_opp_table = true;
+
+   return 0;
+}
+
 static int tegra_dc_probe(struct platform_device *pdev)
 {
u64 dma_mask = dma_get_mask(pdev->dev.parent);
@@ -3038,6 +3108,10 @@ static int tegra_dc_probe(struct platform_device *pdev)
tegra_powergate_power_off(dc->powergate);
}
 
+   err = tegra_dc_init_opp_table(dc);
+   if (err < 0)
+   return err;
+
dc->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(dc->regs))
return PTR_ERR(dc->regs);
diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h
index 40378308d527..871cfb0cd31c 100644
--- a/drivers/gpu/drm/tegra/dc.h
+++ b/drivers/gpu/drm/tegra/dc.h
@@ -100,6 +100,8 @@ struct tegra_dc {
struct drm_info_list *debugfs_files;
 
const struct tegra_dc_soc_info *soc;
+
+   bool has_opp_table;
 };
 
 static inline struct tegra_dc *
-- 
2.32.0



[PATCH v11 10/34] gpu: host1x: Add host1x_channel_stop()

2021-09-12 Thread Dmitry Osipenko
Add host1x_channel_stop() which waits till channel becomes idle and then
stops the channel hardware. This is needed for supporting suspend/resume
by host1x drivers since the hardware state is lost after power-gating,
thus the channel needs to be stopped before client enters into suspend.

Tested-by: Peter Geis  # Ouya T30
Tested-by: Paul Fertser  # PAZ00 T20
Tested-by: Nicolas Chauvet  # PAZ00 T20 and TK1 T124
Tested-by: Matt Merhar  # Ouya T30
Signed-off-by: Dmitry Osipenko 
---
 drivers/gpu/host1x/channel.c | 8 
 include/linux/host1x.h   | 1 +
 2 files changed, 9 insertions(+)

diff --git a/drivers/gpu/host1x/channel.c b/drivers/gpu/host1x/channel.c
index 4cd212bb570d..2a9a3a8d5931 100644
--- a/drivers/gpu/host1x/channel.c
+++ b/drivers/gpu/host1x/channel.c
@@ -75,6 +75,14 @@ struct host1x_channel *host1x_channel_get_index(struct 
host1x *host,
return ch;
 }
 
+void host1x_channel_stop(struct host1x_channel *channel)
+{
+   struct host1x *host = dev_get_drvdata(channel->dev->parent);
+
+   host1x_hw_cdma_stop(host, >cdma);
+}
+EXPORT_SYMBOL(host1x_channel_stop);
+
 static void release_channel(struct kref *kref)
 {
struct host1x_channel *channel =
diff --git a/include/linux/host1x.h b/include/linux/host1x.h
index 7bccf589aba7..66473b5be0af 100644
--- a/include/linux/host1x.h
+++ b/include/linux/host1x.h
@@ -181,6 +181,7 @@ struct host1x_job;
 
 struct host1x_channel *host1x_channel_request(struct host1x_client *client);
 struct host1x_channel *host1x_channel_get(struct host1x_channel *channel);
+void host1x_channel_stop(struct host1x_channel *channel);
 void host1x_channel_put(struct host1x_channel *channel);
 int host1x_job_submit(struct host1x_job *job);
 
-- 
2.32.0



[PATCH v11 09/34] gpu: host1x: Add runtime PM and OPP support

2021-09-12 Thread Dmitry Osipenko
Add runtime PM and OPP support to the Host1x driver. For the starter we
will keep host1x always-on because dynamic power management require a major
refactoring of the driver code since lot's of code paths are missing the
RPM handling and we're going to remove some of these paths in the future.

Tested-by: Peter Geis  # Ouya T30
Tested-by: Paul Fertser  # PAZ00 T20
Tested-by: Nicolas Chauvet  # PAZ00 T20 and TK1 T124
Tested-by: Matt Merhar  # Ouya T30
Signed-off-by: Dmitry Osipenko 
---
 drivers/gpu/host1x/debug.c |  15 +++
 drivers/gpu/host1x/dev.c   | 151 +++--
 drivers/gpu/host1x/dev.h   |   3 +-
 drivers/gpu/host1x/hw/channel_hw.c |  44 -
 drivers/gpu/host1x/intr.c  |   3 -
 drivers/gpu/host1x/syncpt.c|   5 +-
 6 files changed, 165 insertions(+), 56 deletions(-)

diff --git a/drivers/gpu/host1x/debug.c b/drivers/gpu/host1x/debug.c
index 8a14880c61bb..18d9c8d206e3 100644
--- a/drivers/gpu/host1x/debug.c
+++ b/drivers/gpu/host1x/debug.c
@@ -7,6 +7,7 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 
@@ -52,6 +53,11 @@ static int show_channel(struct host1x_channel *ch, void 
*data, bool show_fifo)
 {
struct host1x *m = dev_get_drvdata(ch->dev->parent);
struct output *o = data;
+   int err;
+
+   err = pm_runtime_resume_and_get(m->dev);
+   if (err < 0)
+   return err;
 
mutex_lock(>cdma.lock);
mutex_lock(_lock);
@@ -64,6 +70,8 @@ static int show_channel(struct host1x_channel *ch, void 
*data, bool show_fifo)
mutex_unlock(_lock);
mutex_unlock(>cdma.lock);
 
+   pm_runtime_put(m->dev);
+
return 0;
 }
 
@@ -71,9 +79,14 @@ static void show_syncpts(struct host1x *m, struct output *o)
 {
struct list_head *pos;
unsigned int i;
+   int err;
 
host1x_debug_output(o, " syncpts \n");
 
+   err = pm_runtime_resume_and_get(m->dev);
+   if (err < 0)
+   return;
+
for (i = 0; i < host1x_syncpt_nb_pts(m); i++) {
u32 max = host1x_syncpt_read_max(m->syncpt + i);
u32 min = host1x_syncpt_load(m->syncpt + i);
@@ -101,6 +114,8 @@ static void show_syncpts(struct host1x *m, struct output *o)
base_val);
}
 
+   pm_runtime_put(m->dev);
+
host1x_debug_output(o, "\n");
 }
 
diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c
index fbb6447b8659..595b91099e3e 100644
--- a/drivers/gpu/host1x/dev.c
+++ b/drivers/gpu/host1x/dev.c
@@ -6,14 +6,18 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
 #include 
+#include 
 #include 
 
+#include 
+
 #define CREATE_TRACE_POINTS
 #include 
 #undef CREATE_TRACE_POINTS
@@ -190,6 +194,9 @@ static void host1x_setup_sid_table(struct host1x *host)
const struct host1x_info *info = host->info;
unsigned int i;
 
+   if (!info->has_hypervisor)
+   return;
+
for (i = 0; i < info->num_sid_entries; i++) {
const struct host1x_sid_entry *entry = >sid_table[i];
 
@@ -347,6 +354,27 @@ static void host1x_iommu_exit(struct host1x *host)
}
 }
 
+static int host1x_get_resets(struct host1x *host)
+{
+   int err;
+
+   host->resets[0].id = "mc";
+   host->resets[1].id = "host1x";
+   host->nresets = ARRAY_SIZE(host->resets);
+
+   err = devm_reset_control_bulk_get_optional_exclusive_released(
+   host->dev, host->nresets, host->resets);
+   if (err) {
+   dev_err(host->dev, "failed to get reset: %d\n", err);
+   return err;
+   }
+
+   if (WARN_ON(!host->resets[1].rstc))
+   return -ENOENT;
+
+   return 0;
+}
+
 static int host1x_probe(struct platform_device *pdev)
 {
struct host1x *host;
@@ -423,12 +451,9 @@ static int host1x_probe(struct platform_device *pdev)
return err;
}
 
-   host->rst = devm_reset_control_get(>dev, "host1x");
-   if (IS_ERR(host->rst)) {
-   err = PTR_ERR(host->rst);
-   dev_err(>dev, "failed to get reset: %d\n", err);
+   err = host1x_get_resets(host);
+   if (err)
return err;
-   }
 
err = host1x_iommu_init(host);
if (err < 0) {
@@ -443,22 +468,10 @@ static int host1x_probe(struct platform_device *pdev)
goto iommu_exit;
}
 
-   err = clk_prepare_enable(host->clk);
-   if (err < 0) {
-   dev_err(>dev, "failed to enable clock\n");
-   goto free_channels;
-   }
-
-   err = reset_control_deassert(host->rst);
-   if (err < 0) {
-   dev_err(>dev, "failed to deassert reset: %d\n", err);
-   goto unprepare_disable;
-   }
-
err = host1x_syncpt_init(host);
if (err) {
dev_err(>dev, "failed to initialize syncpts\n");
-   goto 

[PATCH v11 08/34] dt-bindings: host1x: Document Memory Client resets of Host1x, GR2D and GR3D

2021-09-12 Thread Dmitry Osipenko
Memory Client should be blocked before hardware reset is asserted in order
to prevent memory corruption and hanging of memory controller.

Document Memory Client resets of Host1x, GR2D and GR3D hardware units.

Signed-off-by: Dmitry Osipenko 
---
 .../bindings/display/tegra/nvidia,tegra20-host1x.txt  | 4 
 1 file changed, 4 insertions(+)

diff --git 
a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-host1x.txt 
b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-host1x.txt
index 62861a8fb5c6..e61999ce54e9 100644
--- a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-host1x.txt
+++ b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-host1x.txt
@@ -19,6 +19,7 @@ Required properties:
   See ../reset/reset.txt for details.
 - reset-names: Must include the following entries:
   - host1x
+  - mc
 
 Optional properties:
 - operating-points-v2: See ../bindings/opp/opp.txt for details.
@@ -198,6 +199,7 @@ of the following host1x client modules:
 See ../reset/reset.txt for details.
   - reset-names: Must include the following entries:
 - 2d
+- mc
 
   Optional properties:
   - interconnects: Must contain entry for the GR2D memory clients.
@@ -224,6 +226,8 @@ of the following host1x client modules:
   - reset-names: Must include the following entries:
 - 3d
 - 3d2 (Only required on SoCs with two 3D clocks)
+- mc
+- mc2 (Only required on SoCs with two 3D clocks)
 
   Optional properties:
   - interconnects: Must contain entry for the GR3D memory clients.
-- 
2.32.0



[PATCH v11 07/34] dt-bindings: host1x: Document OPP and power domain properties

2021-09-12 Thread Dmitry Osipenko
Document new DVFS OPP table and power domain properties of the Host1x bus
and devices sitting on the bus.

Reviewed-by: Rob Herring 
Signed-off-by: Dmitry Osipenko 
---
 .../display/tegra/nvidia,tegra20-host1x.txt   | 49 +++
 1 file changed, 49 insertions(+)

diff --git 
a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-host1x.txt 
b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-host1x.txt
index 8a6d3e1ee306..62861a8fb5c6 100644
--- a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-host1x.txt
+++ b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-host1x.txt
@@ -20,6 +20,18 @@ Required properties:
 - reset-names: Must include the following entries:
   - host1x
 
+Optional properties:
+- operating-points-v2: See ../bindings/opp/opp.txt for details.
+  - power-domains: Phandle to HEG or core power domain.
+
+For each opp entry in 'operating-points-v2' table of host1x and its modules:
+- opp-supported-hw: One bitfield indicating:
+   On Tegra20: SoC process ID mask
+   On Tegra30+: SoC speedo ID mask
+
+   A bitwise AND is performed against the value and if any bit
+   matches, the OPP gets enabled.
+
 Each host1x client module having to perform DMA through the Memory Controller
 should have the interconnect endpoints set to the Memory Client and External
 Memory respectively.
@@ -45,6 +57,8 @@ of the following host1x client modules:
   - interconnect-names: Must include name of the interconnect path for each
 interconnect entry. Consult TRM documentation for information about
 available memory clients, see MEMORY CONTROLLER section.
+  - operating-points-v2: See ../bindings/opp/opp.txt for details.
+  - power-domains: Phandle to MPE power domain.
 
 - vi: video input
 
@@ -128,6 +142,8 @@ of the following host1x client modules:
   - interconnect-names: Must include name of the interconnect path for each
 interconnect entry. Consult TRM documentation for information about
 available memory clients, see MEMORY CONTROLLER section.
+  - operating-points-v2: See ../bindings/opp/opp.txt for details.
+  - power-domains: Phandle to VENC power domain.
 
 - epp: encoder pre-processor
 
@@ -147,6 +163,8 @@ of the following host1x client modules:
   - interconnect-names: Must include name of the interconnect path for each
 interconnect entry. Consult TRM documentation for information about
 available memory clients, see MEMORY CONTROLLER section.
+  - operating-points-v2: See ../bindings/opp/opp.txt for details.
+  - power-domains: Phandle to HEG or core power domain.
 
 - isp: image signal processor
 
@@ -166,6 +184,7 @@ of the following host1x client modules:
   - interconnect-names: Must include name of the interconnect path for each
 interconnect entry. Consult TRM documentation for information about
 available memory clients, see MEMORY CONTROLLER section.
+  - power-domains: Phandle to VENC or core power domain.
 
 - gr2d: 2D graphics engine
 
@@ -185,6 +204,8 @@ of the following host1x client modules:
   - interconnect-names: Must include name of the interconnect path for each
 interconnect entry. Consult TRM documentation for information about
 available memory clients, see MEMORY CONTROLLER section.
+  - operating-points-v2: See ../bindings/opp/opp.txt for details.
+  - power-domains: Phandle to HEG or core power domain.
 
 - gr3d: 3D graphics engine
 
@@ -209,6 +230,8 @@ of the following host1x client modules:
   - interconnect-names: Must include name of the interconnect path for each
 interconnect entry. Consult TRM documentation for information about
 available memory clients, see MEMORY CONTROLLER section.
+  - operating-points-v2: See ../bindings/opp/opp.txt for details.
+  - power-domains: Phandles to 3D or core power domain.
 
 - dc: display controller
 
@@ -241,6 +264,8 @@ of the following host1x client modules:
   - interconnect-names: Must include name of the interconnect path for each
 interconnect entry. Consult TRM documentation for information about
 available memory clients, see MEMORY CONTROLLER section.
+  - operating-points-v2: See ../bindings/opp/opp.txt for details.
+  - power-domains: Phandle to core power domain.
 
 - hdmi: High Definition Multimedia Interface
 
@@ -267,6 +292,7 @@ of the following host1x client modules:
   - nvidia,hpd-gpio: specifies a GPIO used for hotplug detection
   - nvidia,edid: supplies a binary EDID blob
   - nvidia,panel: phandle of a display panel
+  - operating-points-v2: See ../bindings/opp/opp.txt for details.
 
 - tvo: TV encoder output
 
@@ -277,6 +303,10 @@ of the following host1x client modules:
   - clocks: Must contain one entry, for the module clock.
 See ../clocks/clock-bindings.txt for details.
 
+  Optional properties:
+  - operating-points-v2: See ../bindings/opp/opp.txt for details.
+  - power-domains: Phandle to core power domain.
+
 - dsi: display serial interface
 
   Required properties:
@@ 

[PATCH v11 06/34] clk: tegra: Support runtime PM and power domain

2021-09-12 Thread Dmitry Osipenko
The Clock-and-Reset controller resides in a core power domain on NVIDIA
Tegra SoCs.  In order to support voltage scaling of the core power domain,
we hook up DVFS-capable clocks to the core GENPD for managing of the
GENPD's performance state based on the clock changes.

Some clocks don't have any specific physical hardware unit that backs
them, like root PLLs and system clock and they have theirs own voltage
requirements.  This patch adds new clk-device driver that backs the clocks
and provides runtime PM functionality for them.  A virtual clk-device is
created for each such DVFS-capable clock at the clock's registration time
by the new tegra_clk_register() helper.  Driver changes clock's device
GENPD performance state based on clk-rate notifications.

In result we have this sequence of events:

  1. Clock driver creates virtual device for selective clocks, enables
 runtime PM for the created device and registers the clock.
  2. Clk-device driver starts to listen to clock rate changes.
  3. Something changes clk rate or enables/disables clk.
  4. CCF core propagates the change through the clk tree.
  5. Clk-device driver gets clock rate-change notification or GENPD core
 handles prepare/unprepare of the clock.
  6. Clk-device driver changes GENPD performance state on clock rate
 change.
  7. GENPD driver changes voltage regulator state change.
  8. The regulator state is committed to hardware via I2C.

We rely on fact that DVFS is not needed for Tegra I2C and that Tegra I2C
driver already keeps clock always-prepared.  Hence I2C subsystem stays
independent from the clk power management and there are no deadlock spots
in the sequence.

Currently all clocks are registered very early during kernel boot when the
device driver core isn't available yet.  The clk-device can't be created
at that time.  This patch splits the registration of the clocks in two
phases:

  1. Register all essential clocks which don't use RPM and are needed
 during early boot.

  2. Register at a later boot time the rest of clocks.

This patch adds power management support for Tegra20 and Tegra30 clocks.

Tested-by: Peter Geis  # Ouya T30
Tested-by: Paul Fertser  # PAZ00 T20
Tested-by: Nicolas Chauvet  # PAZ00 T20 and TK1 T124
Tested-by: Matt Merhar  # Ouya T30
Signed-off-by: Dmitry Osipenko 
---
 drivers/clk/tegra/Makefile  |   1 +
 drivers/clk/tegra/clk-device.c  | 222 
 drivers/clk/tegra/clk-pll.c |   2 +-
 drivers/clk/tegra/clk-super.c   |   2 +-
 drivers/clk/tegra/clk-tegra20.c |  77 ---
 drivers/clk/tegra/clk-tegra30.c | 116 -
 drivers/clk/tegra/clk.c |  75 ++-
 drivers/clk/tegra/clk.h |   2 +
 8 files changed, 443 insertions(+), 54 deletions(-)
 create mode 100644 drivers/clk/tegra/clk-device.c

diff --git a/drivers/clk/tegra/Makefile b/drivers/clk/tegra/Makefile
index 7b1816856eb5..a0715cdfc1a4 100644
--- a/drivers/clk/tegra/Makefile
+++ b/drivers/clk/tegra/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-y  += clk.o
 obj-y  += clk-audio-sync.o
+obj-y  += clk-device.o
 obj-y  += clk-dfll.o
 obj-y  += clk-divider.o
 obj-y  += clk-periph.o
diff --git a/drivers/clk/tegra/clk-device.c b/drivers/clk/tegra/clk-device.c
new file mode 100644
index ..9463c285b2a5
--- /dev/null
+++ b/drivers/clk/tegra/clk-device.c
@@ -0,0 +1,222 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#include "clk.h"
+
+/*
+ * This driver manages performance state of the core power domain for the
+ * independent PLLs and system clocks.  We created a virtual clock device
+ * for such clocks, see tegra_clk_dev_register().
+ */
+
+struct tegra_clk_device {
+   struct notifier_block clk_nb;
+   struct device *dev;
+   struct clk_hw *hw;
+   struct mutex lock;
+};
+
+static int tegra_clock_set_pd_state(struct tegra_clk_device *clk_dev,
+   unsigned long rate)
+{
+   struct device *dev = clk_dev->dev;
+   struct dev_pm_opp *opp;
+   unsigned int pstate;
+
+   opp = dev_pm_opp_find_freq_ceil(dev, );
+   if (opp == ERR_PTR(-ERANGE)) {
+   dev_dbg(dev, "failed to find ceil OPP for %luHz\n", rate);
+   opp = dev_pm_opp_find_freq_floor(dev, );
+   }
+
+   if (IS_ERR(opp)) {
+   dev_err(dev, "failed to find OPP for %luHz: %pe\n", rate, opp);
+   return PTR_ERR(opp);
+   }
+
+   pstate = dev_pm_opp_get_required_pstate(opp, 0);
+   dev_pm_opp_put(opp);
+
+   return dev_pm_genpd_set_performance_state(dev, pstate);
+}
+
+static int tegra_clock_change_notify(struct notifier_block *nb,
+   

[PATCH v11 04/34] soc/tegra: Don't print error message when OPPs not available

2021-09-12 Thread Dmitry Osipenko
Previously we assumed that devm_tegra_core_dev_init_opp_table() will
be used only by drivers that will always have device with OPP table,
but this is not true anymore. For example now Tegra30 will have OPP table
for PWM, but Tegra20 not and both use the same driver. Hence let's not
print the error message about missing OPP table in the common helper,
we can print it elsewhere.

Signed-off-by: Dmitry Osipenko 
---
 drivers/soc/tegra/common.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/soc/tegra/common.c b/drivers/soc/tegra/common.c
index cd33e99249c3..a42d4f98c078 100644
--- a/drivers/soc/tegra/common.c
+++ b/drivers/soc/tegra/common.c
@@ -111,9 +111,7 @@ int devm_tegra_core_dev_init_opp_table(struct device *dev,
 */
err = devm_pm_opp_of_add_table(dev);
if (err) {
-   if (err == -ENODEV)
-   dev_err_once(dev, "OPP table not found, please update 
device-tree\n");
-   else
+   if (err != -ENODEV)
dev_err(dev, "failed to add OPP table: %d\n", err);
 
return err;
-- 
2.32.0



[PATCH v11 05/34] dt-bindings: clock: tegra-car: Document new clock sub-nodes

2021-09-12 Thread Dmitry Osipenko
Document sub-nodes which describe Tegra SoC clocks that require a higher
voltage of the core power domain in order to operate properly on a higher
clock rates.  Each node contains a phandle to OPP table and power domain.

The root PLLs and system clocks don't have any specific device dedicated
to them, clock controller is in charge of managing power for them.

Signed-off-by: Dmitry Osipenko 
---
 .../bindings/clock/nvidia,tegra20-car.yaml| 37 +++
 1 file changed, 37 insertions(+)

diff --git a/Documentation/devicetree/bindings/clock/nvidia,tegra20-car.yaml 
b/Documentation/devicetree/bindings/clock/nvidia,tegra20-car.yaml
index 459d2a525393..f832abb7f11a 100644
--- a/Documentation/devicetree/bindings/clock/nvidia,tegra20-car.yaml
+++ b/Documentation/devicetree/bindings/clock/nvidia,tegra20-car.yaml
@@ -42,6 +42,36 @@ properties:
   "#reset-cells":
 const: 1
 
+patternProperties:
+  "^(sclk)|(pll-[cem])$":
+type: object
+properties:
+  compatible:
+enum:
+  - nvidia,tegra20-sclk
+  - nvidia,tegra30-sclk
+  - nvidia,tegra30-pllc
+  - nvidia,tegra30-plle
+  - nvidia,tegra30-pllm
+
+  operating-points-v2: true
+
+  clocks:
+items:
+  - description: node's clock
+
+  power-domains:
+maxItems: 1
+description: phandle to the core SoC power domain
+
+required:
+  - compatible
+  - operating-points-v2
+  - clocks
+  - power-domains
+
+additionalProperties: false
+
 required:
   - compatible
   - reg
@@ -59,6 +89,13 @@ examples:
 reg = <0x60006000 0x1000>;
 #clock-cells = <1>;
 #reset-cells = <1>;
+
+sclk {
+compatible = "nvidia,tegra20-sclk";
+operating-points-v2 = <_table>;
+clocks = <_car TEGRA20_CLK_SCLK>;
+power-domains = <>;
+};
 };
 
 usb-controller@c5004000 {
-- 
2.32.0



[PATCH v11 03/34] soc/tegra: pmc: Disable PMC state syncing

2021-09-12 Thread Dmitry Osipenko
Disable PMC state syncing in order to ensure that we won't break older
kernels once device-trees will be updated with the addition of the power
domains. This also allows to apply device-tree PM patches independently
from the driver patches.

Signed-off-by: Dmitry Osipenko 
---
 drivers/soc/tegra/pmc.c | 17 +
 1 file changed, 17 insertions(+)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index 50091c4ec948..fb8faf7b226a 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -360,6 +360,7 @@ struct tegra_pmc_soc {
unsigned int num_pmc_clks;
bool has_blink_output;
bool has_usb_sleepwalk;
+   bool supports_core_domain;
 };
 
 /**
@@ -3041,6 +3042,7 @@ static void tegra20_pmc_setup_irq_polarity(struct 
tegra_pmc *pmc,
 }
 
 static const struct tegra_pmc_soc tegra20_pmc_soc = {
+   .supports_core_domain = false,
.num_powergates = ARRAY_SIZE(tegra20_powergates),
.powergates = tegra20_powergates,
.num_cpu_powergates = 0,
@@ -3101,6 +3103,7 @@ static const char * const tegra30_reset_sources[] = {
 };
 
 static const struct tegra_pmc_soc tegra30_pmc_soc = {
+   .supports_core_domain = false,
.num_powergates = ARRAY_SIZE(tegra30_powergates),
.powergates = tegra30_powergates,
.num_cpu_powergates = ARRAY_SIZE(tegra30_cpu_powergates),
@@ -3157,6 +3160,7 @@ static const u8 tegra114_cpu_powergates[] = {
 };
 
 static const struct tegra_pmc_soc tegra114_pmc_soc = {
+   .supports_core_domain = false,
.num_powergates = ARRAY_SIZE(tegra114_powergates),
.powergates = tegra114_powergates,
.num_cpu_powergates = ARRAY_SIZE(tegra114_cpu_powergates),
@@ -3273,6 +3277,7 @@ static const struct pinctrl_pin_desc tegra124_pin_descs[] 
= {
 };
 
 static const struct tegra_pmc_soc tegra124_pmc_soc = {
+   .supports_core_domain = false,
.num_powergates = ARRAY_SIZE(tegra124_powergates),
.powergates = tegra124_powergates,
.num_cpu_powergates = ARRAY_SIZE(tegra124_cpu_powergates),
@@ -3398,6 +3403,7 @@ static const struct tegra_wake_event 
tegra210_wake_events[] = {
 };
 
 static const struct tegra_pmc_soc tegra210_pmc_soc = {
+   .supports_core_domain = false,
.num_powergates = ARRAY_SIZE(tegra210_powergates),
.powergates = tegra210_powergates,
.num_cpu_powergates = ARRAY_SIZE(tegra210_cpu_powergates),
@@ -3555,6 +3561,7 @@ static const struct tegra_wake_event 
tegra186_wake_events[] = {
 };
 
 static const struct tegra_pmc_soc tegra186_pmc_soc = {
+   .supports_core_domain = false,
.num_powergates = 0,
.powergates = NULL,
.num_cpu_powergates = 0,
@@ -3689,6 +3696,7 @@ static const struct tegra_wake_event 
tegra194_wake_events[] = {
 };
 
 static const struct tegra_pmc_soc tegra194_pmc_soc = {
+   .supports_core_domain = false,
.num_powergates = 0,
.powergates = NULL,
.num_cpu_powergates = 0,
@@ -3757,6 +3765,7 @@ static const char * const tegra234_reset_sources[] = {
 };
 
 static const struct tegra_pmc_soc tegra234_pmc_soc = {
+   .supports_core_domain = false,
.num_powergates = 0,
.powergates = NULL,
.num_cpu_powergates = 0,
@@ -3803,6 +3812,14 @@ static void tegra_pmc_sync_state(struct device *dev)
 {
int err;
 
+   /*
+* Newer device-trees have power domains, but we need to prepare all
+* device drivers with runtime PM and OPP support first, otherwise
+* state syncing is unsafe.
+*/
+   if (!pmc->soc->supports_core_domain)
+   return;
+
/*
 * Older device-trees don't have core PD, and thus, there are
 * no dependencies that will block the state syncing. We shouldn't
-- 
2.32.0



[PATCH v11 02/34] soc/tegra: Add devm_tegra_core_dev_init_opp_table_common()

2021-09-12 Thread Dmitry Osipenko
Only couple drivers need to get the -ENODEV error code and majority of
drivers need to explicitly initialize the performance state. Add new
common helper which sets up OPP table for these drivers.

Signed-off-by: Dmitry Osipenko 
---
 include/soc/tegra/common.h | 24 
 1 file changed, 24 insertions(+)

diff --git a/include/soc/tegra/common.h b/include/soc/tegra/common.h
index af41ad80ec21..5b4a042f60fb 100644
--- a/include/soc/tegra/common.h
+++ b/include/soc/tegra/common.h
@@ -39,4 +39,28 @@ devm_tegra_core_dev_init_opp_table(struct device *dev,
 }
 #endif
 
+/*
+ * This function should be invoked with the enabled runtime PM of the device
+ * in order to initialize performance state properly. Most of Tegra devices
+ * are assumed to be suspended at a probe time and GENPD require RPM to be
+ * enabled to set up the rpm-resume state, otherwise device is active and
+ * performance state is applied immediately. Note that it will initialize
+ * OPP bandwidth if it's wired in a device-tree for this device, which is
+ * undesirable for a suspended device.
+ */
+static inline int
+devm_tegra_core_dev_init_opp_table_common(struct device *dev)
+{
+   struct tegra_core_opp_params opp_params = {};
+   int err;
+
+   opp_params.init_state = true;
+
+   err = devm_tegra_core_dev_init_opp_table(dev, _params);
+   if (err != -ENODEV)
+   return err;
+
+   return 0;
+}
+
 #endif /* __SOC_TEGRA_COMMON_H__ */
-- 
2.32.0



[PATCH v11 01/34] opp: Change type of dev_pm_opp_attach_genpd(names) argument

2021-09-12 Thread Dmitry Osipenko
Elements of the 'names' array are not changed by the code, constify them
for consistency.

Signed-off-by: Dmitry Osipenko 
---
 drivers/opp/core.c | 6 +++---
 include/linux/pm_opp.h | 8 
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/opp/core.c b/drivers/opp/core.c
index 04b4691a8aac..3057beabd370 100644
--- a/drivers/opp/core.c
+++ b/drivers/opp/core.c
@@ -2348,12 +2348,12 @@ static void _opp_detach_genpd(struct opp_table 
*opp_table)
  * "required-opps" are added in DT.
  */
 struct opp_table *dev_pm_opp_attach_genpd(struct device *dev,
-   const char **names, struct device ***virt_devs)
+   const char * const *names, struct device ***virt_devs)
 {
struct opp_table *opp_table;
struct device *virt_dev;
int index = 0, ret = -EINVAL;
-   const char **name = names;
+   const char * const *name = names;
 
opp_table = _add_opp_table(dev, false);
if (IS_ERR(opp_table))
@@ -2457,7 +2457,7 @@ static void devm_pm_opp_detach_genpd(void *data)
  *
  * Return: 0 on success and errorno otherwise.
  */
-int devm_pm_opp_attach_genpd(struct device *dev, const char **names,
+int devm_pm_opp_attach_genpd(struct device *dev, const char * const *names,
 struct device ***virt_devs)
 {
struct opp_table *opp_table;
diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h
index a95d6fdd20b6..879c138c7b8e 100644
--- a/include/linux/pm_opp.h
+++ b/include/linux/pm_opp.h
@@ -156,9 +156,9 @@ int devm_pm_opp_set_clkname(struct device *dev, const char 
*name);
 struct opp_table *dev_pm_opp_register_set_opp_helper(struct device *dev, int 
(*set_opp)(struct dev_pm_set_opp_data *data));
 void dev_pm_opp_unregister_set_opp_helper(struct opp_table *opp_table);
 int devm_pm_opp_register_set_opp_helper(struct device *dev, int 
(*set_opp)(struct dev_pm_set_opp_data *data));
-struct opp_table *dev_pm_opp_attach_genpd(struct device *dev, const char 
**names, struct device ***virt_devs);
+struct opp_table *dev_pm_opp_attach_genpd(struct device *dev, const char * 
const *names, struct device ***virt_devs);
 void dev_pm_opp_detach_genpd(struct opp_table *opp_table);
-int devm_pm_opp_attach_genpd(struct device *dev, const char **names, struct 
device ***virt_devs);
+int devm_pm_opp_attach_genpd(struct device *dev, const char * const *names, 
struct device ***virt_devs);
 struct dev_pm_opp *dev_pm_opp_xlate_required_opp(struct opp_table *src_table, 
struct opp_table *dst_table, struct dev_pm_opp *src_opp);
 int dev_pm_opp_xlate_performance_state(struct opp_table *src_table, struct 
opp_table *dst_table, unsigned int pstate);
 int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq);
@@ -376,7 +376,7 @@ static inline int devm_pm_opp_set_clkname(struct device 
*dev, const char *name)
return -EOPNOTSUPP;
 }
 
-static inline struct opp_table *dev_pm_opp_attach_genpd(struct device *dev, 
const char **names, struct device ***virt_devs)
+static inline struct opp_table *dev_pm_opp_attach_genpd(struct device *dev, 
const char * const *names, struct device ***virt_devs)
 {
return ERR_PTR(-EOPNOTSUPP);
 }
@@ -384,7 +384,7 @@ static inline struct opp_table 
*dev_pm_opp_attach_genpd(struct device *dev, cons
 static inline void dev_pm_opp_detach_genpd(struct opp_table *opp_table) {}
 
 static inline int devm_pm_opp_attach_genpd(struct device *dev,
-  const char **names,
+  const char * const *names,
   struct device ***virt_devs)
 {
return -EOPNOTSUPP;
-- 
2.32.0



[PATCH v11 00/34] NVIDIA Tegra power management patches for 5.16

2021-09-12 Thread Dmitry Osipenko
This series adds runtime PM support to Tegra drivers and enables core
voltage scaling for Tegra20/30 SoCs, resolving overheating troubles.

All patches in this series are interdependent and should go via Tegra tree.

Changelog:

v11: - Added acks and r-b from Rob Herring, Mark Brown and Miquel Raynal
   that were given to v8.

 - Corrected order of the new memory controller reset entry in
   device-trees and host1x DT binding patch, which was requested by
   Rob Herring.

 - Switched consumer drivers to use power domain state syncing done
   by new Tegra's common OPP-initialization helper.

 - Made use of new devm_pm_runtime_enable() helper that was added to
   v5.15 kernel, where appropriate.

 - Added "fuse: Use resource-managed helpers" patch.

 - Converted Tegra20/30 clk drivers to a proper platform drivers,
   which was requested by Thierry Reding.

 - Removed clk-bulk API usage from the MMC patch, which was requested
   by Thierry Reding.

 - Changed CORE power domain name to "core" in a new patch
   "Change name of core power domain".

 - Misc small fixes for problems that I found since v8, like couple
   typos in error code paths and restored working RPM for Tegra DRM
   UAPI v1 that was removed in v8 by accident.

v9-v10: Figured out remaining GENPD API changes with Ulf Hansson and
Viresh Kumar. The OPP-sync helper that was used in v8 isn't needed
anymore because GENPD API now allows consumer drivers to
init rpm_pstate of power domains.

v8: - Added new generic dev_pm_opp_sync() helper that syncs OPP state with
  hardware. All drivers changed to use it. This replaces GENPD attach_dev
  callback hacks that were used in v7.

- Added new patch patch "soc/tegra: regulators: Prepare for suspend"
  that fixes dying Tegra20 SoC after enabling VENC power domain during
  resume from suspend. It matches to what downstream kernel does on
  suspend/resume.

- After a second thought, I dropped patches which added RPM to memory
  drivers since hardware is always-on and RPM not needed.

- Replaced the "dummy host1x driver" patch with new "Disable unused
  host1x hardware" patch, since it's a cleaner solution.

Dmitry Osipenko (34):
  opp: Change type of dev_pm_opp_attach_genpd(names) argument
  soc/tegra: Add devm_tegra_core_dev_init_opp_table_common()
  soc/tegra: pmc: Disable PMC state syncing
  soc/tegra: Don't print error message when OPPs not available
  dt-bindings: clock: tegra-car: Document new clock sub-nodes
  clk: tegra: Support runtime PM and power domain
  dt-bindings: host1x: Document OPP and power domain properties
  dt-bindings: host1x: Document Memory Client resets of Host1x, GR2D and
GR3D
  gpu: host1x: Add runtime PM and OPP support
  gpu: host1x: Add host1x_channel_stop()
  drm/tegra: dc: Support OPP and SoC core voltage scaling
  drm/tegra: hdmi: Add OPP support
  drm/tegra: gr2d: Support generic power domain and runtime PM
  drm/tegra: gr3d: Support generic power domain and runtime PM
  drm/tegra: vic: Support system suspend
  usb: chipidea: tegra: Add runtime PM and OPP support
  bus: tegra-gmi: Add runtime PM and OPP support
  pwm: tegra: Add runtime PM and OPP support
  mmc: sdhci-tegra: Add runtime PM and OPP support
  mtd: rawnand: tegra: Add runtime PM and OPP support
  spi: tegra20-slink: Add OPP support
  media: dt: bindings: tegra-vde: Convert to schema
  media: dt: bindings: tegra-vde: Document OPP and power domain
  media: staging: tegra-vde: Support generic power domain
  soc/tegra: fuse: Reset hardware
  soc/tegra: fuse: Use resource-managed helpers
  soc/tegra: regulators: Prepare for suspend
  soc/tegra: pmc: Change name of core power domain
  soc/tegra: pmc: Enable core domain support for Tegra20 and Tegra30
  ARM: tegra: Add OPP tables and power domains to Tegra20 device-trees
  ARM: tegra: Add OPP tables and power domains to Tegra30 device-trees
  ARM: tegra: Add Memory Client resets to Tegra20 GR2D, GR3D and Host1x
  ARM: tegra: Add Memory Client resets to Tegra30 GR2D, GR3D and Host1x
  ARM: tegra20/30: Disable unused host1x hardware

 .../bindings/clock/nvidia,tegra20-car.yaml|   37 +
 .../display/tegra/nvidia,tegra20-host1x.txt   |   53 +
 .../bindings/media/nvidia,tegra-vde.txt   |   64 -
 .../bindings/media/nvidia,tegra-vde.yaml  |  119 ++
 .../boot/dts/tegra20-acer-a500-picasso.dts|1 +
 arch/arm/boot/dts/tegra20-colibri.dtsi|3 +-
 arch/arm/boot/dts/tegra20-harmony.dts |3 +-
 arch/arm/boot/dts/tegra20-paz00.dts   |1 +
 .../arm/boot/dts/tegra20-peripherals-opp.dtsi |  941 +++
 arch/arm/boot/dts/tegra20-seaboard.dts|3 +-
 arch/arm/boot/dts/tegra20-tamonten.dtsi   |3 +-
 arch/arm/boot/dts/tegra20-trimslice.dts   |9 +
 arch/arm/boot/dts/tegra20-ventana.dts |1 +
 arch/arm/boot/dts/tegra20.dtsi|  116 +-
 

Re: [PATCH 1/3] drm/bridge: Add a function to abstract away panels

2021-09-12 Thread Sam Ravnborg
On Fri, Sep 10, 2021 at 03:09:39PM +0200, Maxime Ripard wrote:
> Display drivers so far need to have a lot of boilerplate to first
> retrieve either the panel or bridge that they are connected to using
> drm_of_find_panel_or_bridge(), and then either deal with each with ad-hoc
> functions or create a drm panel bridge through drm_panel_bridge_add.
> 
> In order to reduce the boilerplate and hopefully create a path of least
> resistance towards using the DRM panel bridge layer, let's create the
> function devm_drm_of_get_next to reduce that boilerplate.
> 
> Signed-off-by: Maxime Ripard 
> ---
>  drivers/gpu/drm/drm_bridge.c | 42 
>  drivers/gpu/drm/drm_of.c |  3 +++
>  include/drm/drm_bridge.h |  2 ++
>  3 files changed, 43 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
> index a8ed66751c2d..10ddca4638b0 100644
> --- a/drivers/gpu/drm/drm_bridge.c
> +++ b/drivers/gpu/drm/drm_bridge.c
> @@ -28,6 +28,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  
>  #include "drm_crtc_internal.h"
> @@ -51,10 +52,8 @@
>   *
>   * Display drivers are responsible for linking encoders with the first bridge
>   * in the chains. This is done by acquiring the appropriate bridge with
> - * of_drm_find_bridge() or drm_of_find_panel_or_bridge(), or creating it for 
> a
> - * panel with drm_panel_bridge_add_typed() (or the managed version
> - * devm_drm_panel_bridge_add_typed()). Once acquired, the bridge shall be
> - * attached to the encoder with a call to drm_bridge_attach().
> + * devm_drm_of_get_bridge(). Once acquired, the bridge shall be attached to 
> the
> + * encoder with a call to drm_bridge_attach().
>   *
>   * Bridges are responsible for linking themselves with the next bridge in the
>   * chain, if any. This is done the same way as for encoders, with the call to
> @@ -1233,6 +1232,41 @@ struct drm_bridge *of_drm_find_bridge(struct 
> device_node *np)
>   return NULL;
>  }
>  EXPORT_SYMBOL(of_drm_find_bridge);
> +
> +/**
> + * devm_drm_of_get_bridge - Return next bridge in the chain
> + * @dev: device to tie the bridge lifetime to
> + * @np: device tree node containing encoder output ports
> + * @port: port in the device tree node
> + * @endpoint: endpoint in the device tree node
> + *
> + * Given a DT node's port and endpoint number, finds the connected node
> + * and returns the associated bridge if any, or creates and returns a
> + * drm panel bridge instance if a panel is connected.
> + *
> + * Returns a pointer to the bridge if successful, or an error pointer
> + * otherwise.
> + */
> +struct drm_bridge *devm_drm_of_get_bridge(struct device *dev,
> +   struct device_node *np,
> +   unsigned int port,
> +   unsigned int endpoint)
One extra comment.
In of_graph_get_remote_node() port is u32
In drm_of_find_panel_or_bridge() port is int
Here port is unsigned int

My OCD would benefit if we used u32 here - as this is consistent with
the base function of_graph_get_remote_node().

Sam


> +{
> + struct drm_bridge *bridge;
> + struct drm_panel *panel;
> + int ret;
> +
> + ret = drm_of_find_panel_or_bridge(np, port, endpoint,
> +   , );
> + if (ret)
> + return ERR_PTR(ret);
> +
> + if (panel)
> + bridge = devm_drm_panel_bridge_add(dev, panel);
> +
> + return bridge;
> +}
> +EXPORT_SYMBOL(devm_drm_of_get_bridge);
>  #endif
>  
>  MODULE_AUTHOR("Ajay Kumar ");
> diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c
> index 997b8827fed2..37c34146eea8 100644
> --- a/drivers/gpu/drm/drm_of.c
> +++ b/drivers/gpu/drm/drm_of.c
> @@ -231,6 +231,9 @@ EXPORT_SYMBOL_GPL(drm_of_encoder_active_endpoint);
>   * return either the associated struct drm_panel or drm_bridge device. Either
>   * @panel or @bridge must not be NULL.
>   *
> + * This function is deprecated and should not be used in new drivers. Use
> + * devm_drm_of_get_bridge() instead.
> + *
>   * Returns zero if successful, or one of the standard error codes if it 
> fails.
>   */
>  int drm_of_find_panel_or_bridge(const struct device_node *np,
> diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
> index 46bdfa48c413..f70c88ca96ef 100644
> --- a/include/drm/drm_bridge.h
> +++ b/include/drm/drm_bridge.h
> @@ -911,6 +911,8 @@ struct drm_bridge *devm_drm_panel_bridge_add(struct 
> device *dev,
>  struct drm_bridge *devm_drm_panel_bridge_add_typed(struct device *dev,
>  struct drm_panel *panel,
>  u32 connector_type);
> +struct drm_bridge *devm_drm_of_get_bridge(struct device *dev, struct 
> device_node *node,
> + unsigned int port, unsigned int 
> endpoint);
>  struct drm_connector 

Re: [PATCH 3/3] drm/vc4: dsi: Switch to devm_drm_of_get_bridge

2021-09-12 Thread Sam Ravnborg
On Fri, Sep 10, 2021 at 03:09:41PM +0200, Maxime Ripard wrote:
> The new devm_drm_of_get_bridge removes most of the boilerplate we
> have to deal with. Let's switch to it.
> 
> Signed-off-by: Maxime Ripard 

With the includes updated:

Acked-by: Sam Ravnborg 

Sam

> ---
>  drivers/gpu/drm/vc4/vc4_drv.c |  2 ++
>  drivers/gpu/drm/vc4/vc4_dsi.c | 28 
>  2 files changed, 6 insertions(+), 24 deletions(-)
> 
> diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c
> index 16abc3a3d601..96c526f1022e 100644
> --- a/drivers/gpu/drm/vc4/vc4_drv.c
> +++ b/drivers/gpu/drm/vc4/vc4_drv.c
> @@ -25,7 +25,9 @@
>  #include 
>  #include 
>  #include 
> +#include 
I fail to see why this include is needed?

>  #include 
> +#include 
I think this should be drm_bridge.h.
And drm_bridge.h hopefully pulls in what is needed.

>  #include 
>  #include 
>  #include 
> diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c
> index a185027911ce..a229da58962a 100644
> --- a/drivers/gpu/drm/vc4/vc4_dsi.c
> +++ b/drivers/gpu/drm/vc4/vc4_dsi.c
> @@ -1497,7 +1497,6 @@ static int vc4_dsi_bind(struct device *dev, struct 
> device *master, void *data)
>   struct drm_device *drm = dev_get_drvdata(master);
>   struct vc4_dsi *dsi = dev_get_drvdata(dev);
>   struct vc4_dsi_encoder *vc4_dsi_encoder;
> - struct drm_panel *panel;
>   const struct of_device_id *match;
>   dma_cap_mask_t dma_mask;
>   int ret;
> @@ -1609,27 +1608,9 @@ static int vc4_dsi_bind(struct device *dev, struct 
> device *master, void *data)
>   return ret;
>   }
>  
> - ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0,
> -   , >bridge);
> - if (ret) {
> - /* If the bridge or panel pointed by dev->of_node is not
> -  * enabled, just return 0 here so that we don't prevent the DRM
> -  * dev from being registered. Of course that means the DSI
> -  * encoder won't be exposed, but that's not a problem since
> -  * nothing is connected to it.
> -  */
> - if (ret == -ENODEV)
> - return 0;
> -
> - return ret;
> - }
> -
> - if (panel) {
> - dsi->bridge = devm_drm_panel_bridge_add_typed(dev, panel,
> -   
> DRM_MODE_CONNECTOR_DSI);
> - if (IS_ERR(dsi->bridge))
> - return PTR_ERR(dsi->bridge);
> - }
> + dsi->bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, 0);
> + if (IS_ERR(dsi->bridge))
> + return PTR_ERR(dsi->bridge);
>  
>   /* The esc clock rate is supposed to always be 100Mhz. */
>   ret = clk_set_rate(dsi->escape_clock, 100 * 100);
> @@ -1667,8 +1648,7 @@ static void vc4_dsi_unbind(struct device *dev, struct 
> device *master,
>  {
>   struct vc4_dsi *dsi = dev_get_drvdata(dev);
>  
> - if (dsi->bridge)
> - pm_runtime_disable(dev);
> + pm_runtime_disable(dev);
>  
>   /*
>* Restore the bridge_chain so the bridge detach procedure can happen
> -- 
> 2.31.1


Re: [PATCH 2/3] drm/vc4: dpi: Switch to devm_drm_of_get_bridge

2021-09-12 Thread Sam Ravnborg
On Fri, Sep 10, 2021 at 03:09:40PM +0200, Maxime Ripard wrote:
> The new devm_drm_of_get_bridge removes most of the boilerplate we
> have to deal with. Let's switch to it.
> 
> Signed-off-by: Maxime Ripard 
Acked-by: Sam Ravnborg 
> ---
>  drivers/gpu/drm/vc4/vc4_dpi.c | 15 ---
>  1 file changed, 4 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/gpu/drm/vc4/vc4_dpi.c b/drivers/gpu/drm/vc4/vc4_dpi.c
> index a90f2545baee..c180eb60bee8 100644
> --- a/drivers/gpu/drm/vc4/vc4_dpi.c
> +++ b/drivers/gpu/drm/vc4/vc4_dpi.c
> @@ -229,26 +229,19 @@ static const struct of_device_id vc4_dpi_dt_match[] = {
>  static int vc4_dpi_init_bridge(struct vc4_dpi *dpi)
>  {
>   struct device *dev = >pdev->dev;
> - struct drm_panel *panel;
>   struct drm_bridge *bridge;
> - int ret;
>  
> - ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0,
> -   , );
> - if (ret) {
> + bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, 0);
> + if (IS_ERR(bridge)) {
>   /* If nothing was connected in the DT, that's not an
>* error.
>*/
> - if (ret == -ENODEV)
> + if (PTR_ERR(bridge) == -ENODEV)
>   return 0;
>   else
> - return ret;
> + return PTR_ERR(bridge);
>   }
>  
> - if (panel)
> - bridge = drm_panel_bridge_add_typed(panel,
> - DRM_MODE_CONNECTOR_DPI);
> -
>   return drm_bridge_attach(dpi->encoder, bridge, NULL, 0);
>  }
>  
> -- 
> 2.31.1


Re: [PATCH 1/3] drm/bridge: Add a function to abstract away panels

2021-09-12 Thread Sam Ravnborg
Hi Maxime,
On Fri, Sep 10, 2021 at 03:09:39PM +0200, Maxime Ripard wrote:
> Display drivers so far need to have a lot of boilerplate to first
> retrieve either the panel or bridge that they are connected to using
> drm_of_find_panel_or_bridge(), and then either deal with each with ad-hoc
> functions or create a drm panel bridge through drm_panel_bridge_add.
> 
> In order to reduce the boilerplate and hopefully create a path of least
> resistance towards using the DRM panel bridge layer, let's create the
> function devm_drm_of_get_next to reduce that boilerplate.
s/devm_drm_of_get_next/devm_drm_of_get_bridge/

> 
> Signed-off-by: Maxime Ripard 

I like how this makes panels and bridges much more alike for the display
drivers.

With the changelog fixed:
Reviewed-by: Sam Ravnborg 

(I assume you will apply yourself - otherwise tell me to do it).
> ---
>  drivers/gpu/drm/drm_bridge.c | 42 
>  drivers/gpu/drm/drm_of.c |  3 +++
>  include/drm/drm_bridge.h |  2 ++
>  3 files changed, 43 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
> index a8ed66751c2d..10ddca4638b0 100644
> --- a/drivers/gpu/drm/drm_bridge.c
> +++ b/drivers/gpu/drm/drm_bridge.c
> @@ -28,6 +28,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  
>  #include "drm_crtc_internal.h"
> @@ -51,10 +52,8 @@
>   *
>   * Display drivers are responsible for linking encoders with the first bridge
>   * in the chains. This is done by acquiring the appropriate bridge with
> - * of_drm_find_bridge() or drm_of_find_panel_or_bridge(), or creating it for 
> a
> - * panel with drm_panel_bridge_add_typed() (or the managed version
> - * devm_drm_panel_bridge_add_typed()). Once acquired, the bridge shall be
> - * attached to the encoder with a call to drm_bridge_attach().
> + * devm_drm_of_get_bridge(). Once acquired, the bridge shall be attached to 
> the
> + * encoder with a call to drm_bridge_attach().
>   *
>   * Bridges are responsible for linking themselves with the next bridge in the
>   * chain, if any. This is done the same way as for encoders, with the call to
> @@ -1233,6 +1232,41 @@ struct drm_bridge *of_drm_find_bridge(struct 
> device_node *np)
>   return NULL;
>  }
>  EXPORT_SYMBOL(of_drm_find_bridge);
> +
> +/**
> + * devm_drm_of_get_bridge - Return next bridge in the chain
> + * @dev: device to tie the bridge lifetime to
> + * @np: device tree node containing encoder output ports
> + * @port: port in the device tree node
> + * @endpoint: endpoint in the device tree node
> + *
> + * Given a DT node's port and endpoint number, finds the connected node
> + * and returns the associated bridge if any, or creates and returns a
> + * drm panel bridge instance if a panel is connected.
> + *
> + * Returns a pointer to the bridge if successful, or an error pointer
> + * otherwise.
> + */
> +struct drm_bridge *devm_drm_of_get_bridge(struct device *dev,
> +   struct device_node *np,
> +   unsigned int port,
> +   unsigned int endpoint)
> +{
> + struct drm_bridge *bridge;
> + struct drm_panel *panel;
> + int ret;
> +
> + ret = drm_of_find_panel_or_bridge(np, port, endpoint,
> +   , );
> + if (ret)
> + return ERR_PTR(ret);
> +
> + if (panel)
> + bridge = devm_drm_panel_bridge_add(dev, panel);
> +
> + return bridge;
> +}
> +EXPORT_SYMBOL(devm_drm_of_get_bridge);
>  #endif
>  
>  MODULE_AUTHOR("Ajay Kumar ");
> diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c
> index 997b8827fed2..37c34146eea8 100644
> --- a/drivers/gpu/drm/drm_of.c
> +++ b/drivers/gpu/drm/drm_of.c
> @@ -231,6 +231,9 @@ EXPORT_SYMBOL_GPL(drm_of_encoder_active_endpoint);
>   * return either the associated struct drm_panel or drm_bridge device. Either
>   * @panel or @bridge must not be NULL.
>   *
> + * This function is deprecated and should not be used in new drivers. Use
> + * devm_drm_of_get_bridge() instead.
> + *
>   * Returns zero if successful, or one of the standard error codes if it 
> fails.
>   */
>  int drm_of_find_panel_or_bridge(const struct device_node *np,
> diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
> index 46bdfa48c413..f70c88ca96ef 100644
> --- a/include/drm/drm_bridge.h
> +++ b/include/drm/drm_bridge.h
> @@ -911,6 +911,8 @@ struct drm_bridge *devm_drm_panel_bridge_add(struct 
> device *dev,
>  struct drm_bridge *devm_drm_panel_bridge_add_typed(struct device *dev,
>  struct drm_panel *panel,
>  u32 connector_type);
> +struct drm_bridge *devm_drm_of_get_bridge(struct device *dev, struct 
> device_node *node,
> + unsigned int port, unsigned int 
> endpoint);
>  struct drm_connector 

Re: Accelerator drivers going forward (was Re: Habanalabs Open-Source TPC LLVM compiler and SynapseAI Core library)

2021-09-12 Thread Dave Airlie
On Sun, 12 Sept 2021 at 23:55, Greg Kroah-Hartman
 wrote:
>
> On Fri, Sep 10, 2021 at 06:10:27PM +0200, Daniel Vetter wrote:
> > Forgot to add dri-devel.
> >
> > On Fri, Sep 10, 2021 at 6:09 PM Daniel Vetter  
> > wrote:
> > >
> > > On Fri, Sep 10, 2021 at 9:58 AM Greg Kroah-Hartman
> > >  wrote:
> > > > On Fri, Sep 10, 2021 at 10:26:56AM +0300, Oded Gabbay wrote:
> > > > > Hi Greg,
> > > > >
> > > > > Following our conversations a couple of months ago, I'm happy to tell 
> > > > > you that
> > > > > Habanalabs has open-sourced its TPC (Tensor Processing Core) LLVM 
> > > > > compiler,
> > > > > which is a fork of the LLVM open-source project.
> > > > >
> > > > > The project can be found on Habanalabs GitHub website at:
> > > > > https://github.com/HabanaAI/tpc_llvm
> > > > >
> > > > > There is a companion guide on how to write TPC kernels at:
> > > > > https://docs.habana.ai/en/latest/TPC_User_Guide/TPC_User_Guide.html
> > > >
> > > > That's great news, thanks for pushing for this and releasing it all!
> > >
> > > Yeah this is neat.
> > >
> > > There's still the problem that we spent the past 2.5 years pissing off
> > > a lot of people for an imo questionable political project, bypassing
> > > all the technical review and expertise. Now that the political
> > > nonsense is resolved I think we need to look at at least the technical
> > > cleanup. The angered people are much harder to fix, so let's maybe
> > > ignore that (or perhaps a ks topic, no idea, I'm honestly not super
> > > motivated to rehash this entire story again). Here's what I think we
> > > should do:
> > >
> > > - move drivers/misc/habanalabs under drivers/gpu/habanalabs and
> > > review/discussions on dri-devel
>
> Wait, why move into gpu?  Are we going to do that for all hardware
> accelerators that we currently have in the kernel tree?
>

We could just mv drivers/gpu drivers/accel if that helps your mental model here.

> These things are not GPUs in the sense of them being "do some work and
> write out to a screen", which is what I would associate with a GPU (G
> does stand for "Graphical", right?)

Neither are a lot of the gpu drivers, it's almost like we evolved the
subsystem in 20 years,
and the name got away from us.

As an example:
etnaviv, panfrost, lima and vgem drivers have no display interfaces at
all. Nada, they do nothing except accelerate and use dma-buf to talk
to other drivers.


> Yes, GPUs can do things that some accelerators can do, but they can do
> things that accelerators can not do, and the other way around as well.
> I doubt you want all of the existing gpu drivers to be only treated as
> an "accelerator driver" now, as where would the logic that has to happen
> to get the bits out to a screen live?

Don't care, totally doesn't matter if a driver is accelerator +
display, you could write in-driver buses if you wanted to abstract
this more, since internally most GPUs are just SoCs, the display and
accelerator pieces talk to power management, irqs and dma-buf like
functionality internally in the driver, the thing is for most GPUs
there is a single PCI device to bind to, so historically nobody has
seen the value in splitting them more or adding an in-driver bus for
one set of devices.

> And since we have a long history of accepting accelerator drivers (I see
> some in our tree since 2018 at the least), and there is no common
> userspace collation trying to make a common userspace api, why do they
> have to live in the same place?  What makes them common except for the
> fact that they use the kernel as a semi-dumb pipe to send work to and
> from a different processor?
>
> Look at drivers/misc/cxl/ and drivers/misc/ocxl and drivers/misc/uacce/
> and drivers/misc/sgi-gru and drivers/misc/bcm-vk/ even drivers/misc/mei/
> as that is an off-load engine we talk to, right?
>
> What about the drivers/fpga/ api we have, it handles accelerators as
> well.  I'm sure we have many other examples in the kernel tree as well,
> I just did a quick look and found these.
>
> All the above accelerators do things in different ways because their
> hardware is different, so they need different user/kernel apis, right?
> How are we going to unify them?  Who is going to unify them?
>
> So drivers/accel/ perhaps?  I would be able to get rid of loads of
> drivers/misc/ code that way :)
>
> Who is going to be the new maintainer of this subsystem?

We already said if we could get agreement on having things follow the
rules, then they can be merged under drm trees or we'd start a new
accel tree.

The problem is the free-for-all merge with no barriers approach that
you and I believe Olof are campaigning for, doesn't seem to create
communities, it may create consulting or training opportunities for
the Linux Foundation, but thus far I don't see any communities.

Graphics accelerator community exists because of and has itself
refined the rules over time. I don't think our rules will necessarily
work for other groups immediately but I think other 

[Bug 214375] New: 5.14 Regression: Null pointer dereference in radeon_agp_head_init

2021-09-12 Thread bugzilla-daemon
https://bugzilla.kernel.org/show_bug.cgi?id=214375

Bug ID: 214375
   Summary: 5.14 Regression: Null pointer dereference in
radeon_agp_head_init
   Product: Drivers
   Version: 2.5
Kernel Version: 5.14.2
  Hardware: All
OS: Linux
  Tree: Mainline
Status: NEW
  Severity: normal
  Priority: P1
 Component: Video(DRI - non Intel)
  Assignee: drivers_video-...@kernel-bugs.osdl.org
  Reporter: calvin.wal...@kepstin.ca
Regression: No

Created attachment 298753
  --> https://bugzilla.kernel.org/attachment.cgi?id=298753=edit
Complete kernel dmesg

I have an i586 system (ALi chipset, AMD CPU) running with a Radeon 9200 SE in
an AGP slot. This system was working correctly with the 5.13 kernel series, but
after switching to 5.14 I no longer have kms graphics output.

The radeon module fails to initialize with the following backtrace:

Sep 12 13:15:53 mai kernel: [drm] radeon kernel modesetting enabled.
Sep 12 13:15:53 mai kernel: radeon :01:00.0: vgaarb: deactivate vga console
Sep 12 13:15:53 mai kernel: Console: switching to colour dummy device 80x25
Sep 12 13:15:53 mai kernel: BUG: kernel NULL pointer dereference, address:
0008
Sep 12 13:15:53 mai kernel: #PF: supervisor read access in kernel mode
Sep 12 13:15:53 mai kernel: #PF: error_code(0x) - not-present page
Sep 12 13:15:53 mai kernel: *pde =  
Sep 12 13:15:53 mai kernel: Oops:  [#1]
Sep 12 13:15:53 mai kernel: CPU: 0 PID: 288 Comm: systemd-udevd Tainted: G 
  W 5.14.2 #2
Sep 12 13:15:53 mai kernel: Hardware name: American Megatrends Inc.
Uknown  /PT-2200 , BIOS 062710  
Sep 12 13:15:53 mai kernel: EIP: radeon_agp_head_init+0xa/0xa0 [radeon]
Sep 12 13:15:53 mai kernel: Code: 85 fb fe ff 74 d6 84 c9 74 d6 84 c9 ff ff e9
f7 ff ff e9 f7 90 66 90 66 90 66 90 66 55 ba c0 0d 55 ba c0 0d 56 53 8b 70 56
53 <8b> 70 6>
Sep 12 13:15:53 mai kernel: EAX:  EBX: b3978c00 ECX: b3a21ce8 EDX:
0dc0
Sep 12 13:15:53 mai kernel: ESI: b493e000 EDI: b1cad000 EBP: b3a21cf8 ESP:
b3a21cf0
Sep 12 13:15:53 mai kernel: DS: 007b ES: 007b FS:  GS: 0033 SS: 0068
EFLAGS: 00210202
Sep 12 13:15:53 mai kernel: CR0: 80050033 CR2: 0008 CR3: 03f86000 CR4:
0090
Sep 12 13:15:53 mai kernel: Call Trace:
Sep 12 13:15:53 mai kernel:  radeon_driver_load_kms+0x168/0x1a0 [radeon]
Sep 12 13:15:53 mai kernel:  drm_dev_register+0xb5/0x1a0 [drm]
Sep 12 13:15:53 mai kernel:  radeon_pci_probe+0xa1/0xe0 [radeon]
Sep 12 13:15:53 mai kernel:  pci_device_probe+0x88/0x100
Sep 12 13:15:53 mai kernel:  really_probe.part.0+0x78/0x220
Sep 12 13:15:53 mai kernel:  __driver_probe_device+0x7e/0x100
Sep 12 13:15:53 mai kernel:  driver_probe_device+0x19/0xe0
Sep 12 13:15:53 mai kernel:  __driver_attach+0x81/0x140
Sep 12 13:15:53 mai kernel:  ? __device_attach_driver+0xe0/0xe0
Sep 12 13:15:53 mai kernel:  bus_for_each_dev+0x47/0x80
Sep 12 13:15:53 mai kernel:  driver_attach+0x17/0x20
Sep 12 13:15:53 mai kernel:  ? __device_attach_driver+0xe0/0xe0
Sep 12 13:15:53 mai kernel:  bus_add_driver+0xec/0x1a0
Sep 12 13:15:53 mai kernel:  driver_register+0x74/0xc0
Sep 12 13:15:53 mai kernel:  ? 0xf0e5f000
Sep 12 13:15:53 mai kernel:  __pci_register_driver+0x37/0x40
Sep 12 13:15:53 mai kernel:  radeon_module_init+0x65/0x1000 [radeon]
Sep 12 13:15:53 mai kernel:  do_one_initcall+0x33/0x120
Sep 12 13:15:53 mai kernel:  ? kfree+0x151/0x160
Sep 12 13:15:53 mai kernel:  ? __vunmap+0x1d5/0x260
Sep 12 13:15:53 mai kernel:  ? kmem_cache_alloc+0x10a/0x160
Sep 12 13:15:53 mai kernel:  do_init_module+0x45/0x240
Sep 12 13:15:53 mai kernel:  load_module+0x1cc3/0x2020
Sep 12 13:15:53 mai kernel:  ? 0xf0e5f000
Sep 12 13:15:53 mai kernel:  __ia32_sys_finit_module+0x89/0xc0
Sep 12 13:15:53 mai kernel:  do_int80_syscall_32+0x2e/0x80
Sep 12 13:15:53 mai kernel:  entry_INT80_32+0x109/0x109
Sep 12 13:15:53 mai kernel: EIP: 0xa7b66332
Sep 12 13:15:53 mai kernel: Code: 90 66 90 66 90 66 90 90 55 57 56 53 8b 6c 24
2c 8b 7c 24 28 8b 74 24 24 8b 54 24 20 8b 4c 24 1c 8b 5c 24 18 8b 44 24 14 cd
80 <5b> 5e 5>
Sep 12 13:15:53 mai kernel: EAX: ffda EBX: 0016 ECX: a7cbfb05 EDX:

Sep 12 13:15:53 mai kernel: ESI: 02068a50 EDI: 020677c0 EBP:  ESP:
affc0fcc
Sep 12 13:15:53 mai kernel: DS: 007b ES: 007b FS:  GS: 0033 SS: 007b
EFLAGS: 00200292
Sep 12 13:15:53 mai kernel: Modules linked in: r8169 radeon(+) realtek
mdio_devres libphy snd_emu10k1 snd_ac97_codec ac97_bus snd_util_mem
i2c_algo_bit snd_hwdep drm_ttm>
Sep 12 13:15:53 mai kernel: CR2: 0008
Sep 12 13:15:53 mai kernel: ---[ end trace d1e7fe80690cc5a8 ]---
Sep 12 13:15:53 mai kernel: EIP: radeon_agp_head_init+0xa/0xa0 [radeon]
Sep 12 13:15:53 mai kernel: Code: 85 fb fe ff 74 d6 84 c9 74 d6 84 c9 ff ff e9
f7 ff ff e9 f7 90 66 90 66 90 66 90 66 55 ba c0 0d 55 ba c0 0d 56 53 8b 70 56
53 <8b> 70 6>
Sep 12 13:15:53 mai 

[PATCH v6 2/2] habanalabs: add support for dma-buf exporter

2021-09-12 Thread Oded Gabbay
From: Tomer Tayar 

Implement the calls to the dma-buf kernel api to create a dma-buf
object backed by FD.

We block the option to mmap the DMA-BUF object because we don't support
DIRECT_IO and implicit P2P. We only implement support for explicit P2P
through importing the FD of the DMA-BUF.

In the export phase, we provide to the DMA-BUF object an array of pages
that represent the device's memory area. During the map callback,
we convert the array of pages into an SGT. We split/merge the pages
according to the dma max segment size of the importer.

To get the DMA address of the PCI bar, we use the dma_map_resources()
kernel API, because our device memory is not backed by page struct
and this API doesn't need page struct to map the physical address to
a DMA address.

We set the orig_nents member of the SGT to be 0, to indicate to other
drivers that we don't support CPU mappings.

Note that in Habanalabs's ASICs, the device memory is pinned and
immutable. Therefore, there is no need for dynamic mappings and pinning
callbacks.

Also note that in GAUDI we don't have an MMU towards the device memory
and the user works on physical addresses. Therefore, the user doesn't
pass through the kernel driver to allocate memory there. As a result,
only for GAUDI we receive from the user a device memory physical address
(instead of a handle) and a size.

We check the p2p distance using pci_p2pdma_distance_many() and refusing
to map dmabuf in case the distance doesn't allow p2p.

Signed-off-by: Tomer Tayar 
Reviewed-by: Oded Gabbay 
Reviewed-by: Gal Pressman 
Reviewed-by: Greg Kroah-Hartman 
Signed-off-by: Oded Gabbay 
---
 drivers/misc/habanalabs/Kconfig |   1 +
 drivers/misc/habanalabs/common/habanalabs.h |  22 +
 drivers/misc/habanalabs/common/memory.c | 522 +++-
 drivers/misc/habanalabs/gaudi/gaudi.c   |   1 +
 drivers/misc/habanalabs/goya/goya.c |   1 +
 5 files changed, 543 insertions(+), 4 deletions(-)

diff --git a/drivers/misc/habanalabs/Kconfig b/drivers/misc/habanalabs/Kconfig
index 293d79811372..c82d2e7b2035 100644
--- a/drivers/misc/habanalabs/Kconfig
+++ b/drivers/misc/habanalabs/Kconfig
@@ -8,6 +8,7 @@ config HABANA_AI
depends on PCI && HAS_IOMEM
select GENERIC_ALLOCATOR
select HWMON
+   select DMA_SHARED_BUFFER
help
  Enables PCIe card driver for Habana's AI Processors (AIP) that are
  designed to accelerate Deep Learning inference and training workloads.
diff --git a/drivers/misc/habanalabs/common/habanalabs.h 
b/drivers/misc/habanalabs/common/habanalabs.h
index bebebcb163ee..df49376a0880 100644
--- a/drivers/misc/habanalabs/common/habanalabs.h
+++ b/drivers/misc/habanalabs/common/habanalabs.h
@@ -26,6 +26,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #define HL_NAME"habanalabs"
 
@@ -1352,6 +1353,23 @@ struct hl_cs_counters_atomic {
atomic64_t validation_drop_cnt;
 };
 
+/**
+ * struct hl_dmabuf_wrapper - a dma-buf wrapper object.
+ * @dmabuf: pointer to dma-buf object.
+ * @ctx: pointer to the dma-buf owner's context.
+ * @phys_pg_pack: pointer to physical page pack if the dma-buf was exported for
+ *memory allocation handle.
+ * @device_address: physical address of the device's memory. Relevant only
+ *  if phys_pg_pack is NULL (dma-buf was exported from 
address).
+ *  The total size can be taken from the dmabuf object.
+ */
+struct hl_dmabuf_wrapper {
+   struct dma_buf  *dmabuf;
+   struct hl_ctx   *ctx;
+   struct hl_vm_phys_pg_pack   *phys_pg_pack;
+   uint64_tdevice_address;
+};
+
 /**
  * struct hl_ctx - user/kernel context.
  * @mem_hash: holds mapping from virtual address to virtual memory area
@@ -1662,6 +1680,7 @@ struct hl_vm_hw_block_list_node {
  * @npages: num physical pages in the pack.
  * @total_size: total size of all the pages in this list.
  * @mapping_cnt: number of shared mappings.
+ * @exporting_cnt: number of dma-buf exporting.
  * @asid: the context related to this list.
  * @page_size: size of each page in the pack.
  * @flags: HL_MEM_* flags related to this list.
@@ -1676,6 +1695,7 @@ struct hl_vm_phys_pg_pack {
u64 npages;
u64 total_size;
atomic_tmapping_cnt;
+   u32 exporting_cnt;
u32 asid;
u32 page_size;
u32 flags;
@@ -2396,6 +2416,7 @@ struct multi_cs_data {
  *  the error will be ignored by the driver during
  *  device initialization. Mainly used to debug and
  *  workaround firmware bugs
+ * @dram_pci_bar_start: start bus address of PCIe bar towards DRAM.
  * @last_successful_open_jif: timestamp (jiffies) of the last successful
  *   

[PATCH v6 1/2] habanalabs: define uAPI to export FD for DMA-BUF

2021-09-12 Thread Oded Gabbay
User process might want to share the device memory with another
driver/device, and to allow it to access it over PCIe (P2P).

To enable this, we utilize the dma-buf mechanism and add a dma-buf
exporter support, so the other driver can import the device memory and
access it.

The device memory is allocated using our existing allocation uAPI,
where the user will get a handle that represents the allocation.

The user will then need to call the new
uAPI (HL_MEM_OP_EXPORT_DMABUF_FD) and give the handle as a parameter.

The driver will return a FD that represents the DMA-BUF object that
was created to match that allocation.

Signed-off-by: Oded Gabbay 
Reviewed-by: Tomer Tayar 
Reviewed-by: Greg Kroah-Hartman 
---
 include/uapi/misc/habanalabs.h | 28 +++-
 1 file changed, 27 insertions(+), 1 deletion(-)

diff --git a/include/uapi/misc/habanalabs.h b/include/uapi/misc/habanalabs.h
index 042e96f99d85..b1def68bf5d3 100644
--- a/include/uapi/misc/habanalabs.h
+++ b/include/uapi/misc/habanalabs.h
@@ -960,6 +960,10 @@ union hl_wait_cs_args {
 #define HL_MEM_OP_UNMAP3
 /* Opcode to map a hw block */
 #define HL_MEM_OP_MAP_BLOCK4
+/* Opcode to create DMA-BUF object for an existing device memory allocation
+ * and to export an FD of that DMA-BUF back to the caller
+ */
+#define HL_MEM_OP_EXPORT_DMABUF_FD 5
 
 /* Memory flags */
 #define HL_MEM_CONTIGUOUS  0x1
@@ -1031,11 +1035,26 @@ struct hl_mem_in {
/* Virtual address returned from HL_MEM_OP_MAP */
__u64 device_virt_addr;
} unmap;
+
+   /* HL_MEM_OP_EXPORT_DMABUF_FD */
+   struct {
+   /* Handle returned from HL_MEM_OP_ALLOC. In Gaudi,
+* where we don't have MMU for the device memory, the
+* driver expects a physical address (instead of
+* a handle) in the device memory space.
+*/
+   __u64 handle;
+   /* Size of memory allocation. Relevant only for GAUDI */
+   __u64 mem_size;
+   } export_dmabuf_fd;
};
 
/* HL_MEM_OP_* */
__u32 op;
-   /* HL_MEM_* flags */
+   /* HL_MEM_* flags.
+* For the HL_MEM_OP_EXPORT_DMABUF_FD opcode, this field holds the
+* DMA-BUF file/FD flags.
+*/
__u32 flags;
/* Context ID - Currently not in use */
__u32 ctx_id;
@@ -1072,6 +1091,13 @@ struct hl_mem_out {
 
__u32 pad;
};
+
+   /* Returned in HL_MEM_OP_EXPORT_DMABUF_FD. Represents the
+* DMA-BUF object that was created to describe a memory
+* allocation on the device's memory space. The FD should be
+* passed to the importer driver
+*/
+   __u64 fd;
};
 };
 
-- 
2.17.1



[PATCH v6 0/2] Add p2p via dmabuf to habanalabs

2021-09-12 Thread Oded Gabbay
Hi,
Re-sending this patch-set following the release of our user-space TPC
compiler and runtime library.

I would appreciate a review on this.

Thanks,
Oded

Oded Gabbay (1):
  habanalabs: define uAPI to export FD for DMA-BUF

Tomer Tayar (1):
  habanalabs: add support for dma-buf exporter

 drivers/misc/habanalabs/Kconfig |   1 +
 drivers/misc/habanalabs/common/habanalabs.h |  22 +
 drivers/misc/habanalabs/common/memory.c | 522 +++-
 drivers/misc/habanalabs/gaudi/gaudi.c   |   1 +
 drivers/misc/habanalabs/goya/goya.c |   1 +
 include/uapi/misc/habanalabs.h  |  28 +-
 6 files changed, 570 insertions(+), 5 deletions(-)

-- 
2.17.1



Re: [PATCH] drm/panel-orientation-quirks: add Valve Steam Deck

2021-09-12 Thread Simon Ser
Thanks for the fixup and the quick review!


Re: Accelerator drivers going forward (was Re: Habanalabs Open-Source TPC LLVM compiler and SynapseAI Core library)

2021-09-12 Thread Simon Ser
> > > - move drivers/misc/habanalabs under drivers/gpu/habanalabs and
> > > review/discussions on dri-devel
>
> Wait, why move into gpu?  Are we going to do that for all hardware
> accelerators that we currently have in the kernel tree?
>
> These things are not GPUs in the sense of them being "do some work and
> write out to a screen", which is what I would associate with a GPU (G
> does stand for "Graphical", right?)
>
> Yes, GPUs can do things that some accelerators can do, but they can do
> things that accelerators can not do, and the other way around as well.
> I doubt you want all of the existing gpu drivers to be only treated as
> an "accelerator driver" now, as where would the logic that has to happen
> to get the bits out to a screen live?

This seems like a description of the "display" part of the drivers, driven
by KMS. There are many chips which can't do the "display" part, only the
"render" part. Their drivers are living in drivers/gpu/ as well.


Accelerator drivers going forward (was Re: Habanalabs Open-Source TPC LLVM compiler and SynapseAI Core library)

2021-09-12 Thread Greg Kroah-Hartman
On Fri, Sep 10, 2021 at 06:10:27PM +0200, Daniel Vetter wrote:
> Forgot to add dri-devel.
> 
> On Fri, Sep 10, 2021 at 6:09 PM Daniel Vetter  wrote:
> >
> > On Fri, Sep 10, 2021 at 9:58 AM Greg Kroah-Hartman
> >  wrote:
> > > On Fri, Sep 10, 2021 at 10:26:56AM +0300, Oded Gabbay wrote:
> > > > Hi Greg,
> > > >
> > > > Following our conversations a couple of months ago, I'm happy to tell 
> > > > you that
> > > > Habanalabs has open-sourced its TPC (Tensor Processing Core) LLVM 
> > > > compiler,
> > > > which is a fork of the LLVM open-source project.
> > > >
> > > > The project can be found on Habanalabs GitHub website at:
> > > > https://github.com/HabanaAI/tpc_llvm
> > > >
> > > > There is a companion guide on how to write TPC kernels at:
> > > > https://docs.habana.ai/en/latest/TPC_User_Guide/TPC_User_Guide.html
> > >
> > > That's great news, thanks for pushing for this and releasing it all!
> >
> > Yeah this is neat.
> >
> > There's still the problem that we spent the past 2.5 years pissing off
> > a lot of people for an imo questionable political project, bypassing
> > all the technical review and expertise. Now that the political
> > nonsense is resolved I think we need to look at at least the technical
> > cleanup. The angered people are much harder to fix, so let's maybe
> > ignore that (or perhaps a ks topic, no idea, I'm honestly not super
> > motivated to rehash this entire story again). Here's what I think we
> > should do:
> >
> > - move drivers/misc/habanalabs under drivers/gpu/habanalabs and
> > review/discussions on dri-devel

Wait, why move into gpu?  Are we going to do that for all hardware
accelerators that we currently have in the kernel tree?

These things are not GPUs in the sense of them being "do some work and
write out to a screen", which is what I would associate with a GPU (G
does stand for "Graphical", right?)

Yes, GPUs can do things that some accelerators can do, but they can do
things that accelerators can not do, and the other way around as well.
I doubt you want all of the existing gpu drivers to be only treated as
an "accelerator driver" now, as where would the logic that has to happen
to get the bits out to a screen live?

And since we have a long history of accepting accelerator drivers (I see
some in our tree since 2018 at the least), and there is no common
userspace collation trying to make a common userspace api, why do they
have to live in the same place?  What makes them common except for the
fact that they use the kernel as a semi-dumb pipe to send work to and
from a different processor?

Look at drivers/misc/cxl/ and drivers/misc/ocxl and drivers/misc/uacce/
and drivers/misc/sgi-gru and drivers/misc/bcm-vk/ even drivers/misc/mei/
as that is an off-load engine we talk to, right?

What about the drivers/fpga/ api we have, it handles accelerators as
well.  I'm sure we have many other examples in the kernel tree as well,
I just did a quick look and found these.

All the above accelerators do things in different ways because their
hardware is different, so they need different user/kernel apis, right?
How are we going to unify them?  Who is going to unify them?

So drivers/accel/ perhaps?  I would be able to get rid of loads of
drivers/misc/ code that way :)

Who is going to be the new maintainer of this subsystem?

So far they have all been going into drivers/misc/ because no one else
stepped up to do the review of them except me.  I would _LOVE_ the help
here as I end up reviewing a new one every kernel release at the least,
but companies do not seem to be willing to fund developers to be
maintainers these days :(

And yes, I have been reviewing the fpga code as well, even though they
do have a good maintainer, as those patches flow through my tree due to
historical reasons.  I know the fpga developers would have loved some
help with review of those patches.

> > - grandfather the entire current situation in as-is, it's not the only
> > driver we have with a funny uapi of its own (but the other driver did
> > manage to get their compiler into upstream llvm even, and not like 2
> > years late)

We have many many accelerator drivers with odd uapis as they all work
differently.  Are we going to have to have any new company that comes
along use one of the existing apis we have (and if so, which one?) or do
we allow them to create their own as everyone does do things
differently, which really is fine as far as a kernel is concerned
(again, semi-dumb pipe.)

> > - review the dma-buf stuff on dri-devel and then land it through
> > standard flows, not the gregk-misc bypass

Are dma-bufs somehow required to be reviewed on dri-devel?  As others
have asked in the past, they are already being used in other subsystems
(like IB) today, did those authors also get review there?

If so, great, if not, that feels odd to me, as I am seeing lots of
out-of-tree drivers start to use these structures, which is why the api
was created (to stop the roll-your-own-implementations.)  Does 

Re: [PATCH] drm: panel-orientation-quirks: Add quirk for the Chuwi HiBook

2021-09-12 Thread Hans de Goede
Hi,

On 9/9/21 5:50 PM, Thierry Reding wrote:
> On Sun, Sep 05, 2021 at 03:05:01PM +0200, Hans de Goede wrote:
>> The Chuwi HiBook uses a panel which has been mounted
>> 90 degrees rotated. Add a quirk for this.
>>
>> Signed-off-by: Hans de Goede 
>> ---
>>  drivers/gpu/drm/drm_panel_orientation_quirks.c | 8 
>>  1 file changed, 8 insertions(+)
> 
> I'm not very familiar with these quirks, but this looks correct and
> inline with other entries in this table.
> 
>> diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c 
>> b/drivers/gpu/drm/drm_panel_orientation_quirks.c
>> index 4e965b0f5502..7e0f581a360e 100644
>> --- a/drivers/gpu/drm/drm_panel_orientation_quirks.c
>> +++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c
>> @@ -140,6 +140,14 @@ static const struct dmi_system_id orientation_data[] = {
>>DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T103HAF"),
>>  },
>>  .driver_data = (void *)_rightside_up,
>> +}, {/* Chuwi HiBook (CWI514) */
>> +.matches = {
>> +DMI_MATCH(DMI_BOARD_VENDOR, "Hampoo"),
>> +DMI_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"),
>> +/* Above matches are too generic, add bios-date match */
>> +DMI_MATCH(DMI_BIOS_DATE, "05/07/2016"),
>> +},
>> +.driver_data = (void *)_rightside_up,
>>  }, {/* Chuwi Hi10 Pro (CWI529) */
>>  .matches = {
>>DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Hampoo"),
> 
> One thing I noticed is that there doesn't seem to be an entry for Chuwi
> Hi10 anywhere in linux-next. Perhaps that's from a different patch in
> your local tree, or it's based on some other tree that already has that.
> In any case, I trust that this can be resolved when applying, so this
> seems okay:
> 
> Reviewed-by: Thierry Reding 

Thank you, I've pushed this to drm-misc-next now.

Regards,

Hans



Re: [PATCH] drm/panel-orientation-quirks: add Valve Steam Deck

2021-09-12 Thread Hans de Goede
Hi,

On 9/11/21 8:54 PM, Sam Ravnborg wrote:
> Hi Simon,
> On Sat, Sep 11, 2021 at 10:24:40AM +, Simon Ser wrote:
>> Valve's Steam Deck has a 800x1280 LCD screen.
>>
>> Signed-off-by: Simon Ser 
>> Cc: Jared Baldridge 
>> Cc: Emil Velikov 
>> Cc: Daniel Vetter 
>> Cc: Hans de Goede 
> 
> 
> The sorting is off - "Valve Steam Deck" comes before "VIOS LTH17"
> 
> With the sorting fixed:
> 
> Acked-by: Sam Ravnborg 
> 
> (Not that I know this code, but I wanted to avoid this patch meeting the
> same fate as the patch from Hans that was left with no feedback for a
> long time).

Sam thank you for Ack-ing this, I also notices the ordering
issue and I've fixed this up while applying this.

I'm doing a test-build now and then I will push out the fixed-up
version to drm-misc-next.

Regards,

Hans



 
>> ---
>>  drivers/gpu/drm/drm_panel_orientation_quirks.c | 7 +++
>>  1 file changed, 7 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c 
>> b/drivers/gpu/drm/drm_panel_orientation_quirks.c
>> index f6bdec7fa925..3018d1dcd271 100644
>> --- a/drivers/gpu/drm/drm_panel_orientation_quirks.c
>> +++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c
>> @@ -231,6 +231,13 @@ static const struct dmi_system_id orientation_data[] = {
>>DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "LTH17"),
>>  },
>>  .driver_data = (void *)_rightside_up,
>> +}, {/* Valve Steam Deck */
>> +.matches = {
>> +  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Valve"),
>> +  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Jupiter"),
>> +  DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "1"),
>> +},
>> +.driver_data = (void *)_rightside_up,
>>  },
>>  {}
>>  };
>> -- 
>> 2.33.0
>>
>