Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] pwm: stm32: fix build warning with CONFIG_DMA_ENGINE disabled
From: Fabrice Gasnier @ 2018-05-28  7:20 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180525210843.1821071-1-arnd@arndb.de>

On 05/25/2018 11:08 PM, Arnd Bergmann wrote:
> Without dmaengine support, we get a harmless warning about an
> unused function:
> 
> drivers/pwm/pwm-stm32.c:166:12: error: 'stm32_pwm_capture' defined but not used [-Werror=unused-function]
> 
> Changing the #ifdef to an IS_ENABLED() check shuts up that warning
> and is slightly nicer to read.
> 
> Fixes: 53e38fe73f94 ("pwm: stm32: Add capture support")
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> ---
>  drivers/pwm/pwm-stm32.c | 4 +---
>  1 file changed, 1 insertion(+), 3 deletions(-)
Hi Arnd,

Acked-by: Fabrice Gasnier <fabrice.gasnier@st.com>

Thanks,
Fabrice
> 
> diff --git a/drivers/pwm/pwm-stm32.c b/drivers/pwm/pwm-stm32.c
> index 60bfc07c4912..97bbc1f18fd6 100644
> --- a/drivers/pwm/pwm-stm32.c
> +++ b/drivers/pwm/pwm-stm32.c
> @@ -484,9 +484,7 @@ static int stm32_pwm_apply_locked(struct pwm_chip *chip, struct pwm_device *pwm,
>  static const struct pwm_ops stm32pwm_ops = {
>  	.owner = THIS_MODULE,
>  	.apply = stm32_pwm_apply_locked,
> -#if IS_ENABLED(CONFIG_DMA_ENGINE)
> -	.capture = stm32_pwm_capture,
> -#endif
> +	.capture = IS_ENABLED(CONFIG_DMA_ENGINE) ? stm32_pwm_capture : NULL,
>  };
>  
>  static int stm32_pwm_set_breakinput(struct stm32_pwm *priv,
> 

^ permalink raw reply

* [PATCHv4 1/2] ARM: imx53: add secure-reg-access support for PMU
From: Shawn Guo @ 2018-05-28  7:20 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180528064131.y5burm5kakiazaq4@earth.universe>

On Mon, May 28, 2018 at 08:41:31AM +0200, Sebastian Reichel wrote:
> > Are you saying this is a very specific setup required by i.MX53 only?
> 
> Yes, all other SoCs supported by Linux ARM PMU counters driver can
> just use the registers without having to enable platform specific
> bits first.
> 
> > In that case, I can live with it.
> 
> What about the DT node? I did not add it, since this is a i.MX53
> specific workaround anyways.

What you are adding here is secure-reg-access property, which has an
defined meaning in PMU binding doc.  I'm not really sure if it's
appropriate to use the property as a condition for DBGEN bit setup.
Or can we set up the bit regardless of the property?

Shawn

^ permalink raw reply

* [GIT PULL] Renesas ARM64 Based SoC DT Updates for v4.18
From: Simon Horman @ 2018-05-28  7:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180526211420.jmme6ikrgdiw76u7@localhost>

Hi Olof,

On Sat, May 26, 2018 at 02:14:20PM -0700, Olof Johansson wrote:
> Hi Simon,
> 
> On Fri, May 18, 2018 at 01:16:00PM +0200, Simon Horman wrote:
> > Hi Olof, Hi Kevin, Hi Arnd,
> > 
> > Please consider these Renesas ARM64 based SoC DT updates for v4.18.
> > 
> > 
> > The following changes since commit 60cc43fc888428bb2f18f08997432d426a243338:
> > 
> >   Linux 4.17-rc1 (2018-04-15 18:24:20 -0700)
> > 
> > are available in the git repository at:
> > 
> >   https://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git tags/renesas-arm64-dt-for-v4.18
> > 
> > for you to fetch changes up to 908001d778eba06ee1d832863d4e9a1e2cfd4746:
> > 
> >   arm64: dts: renesas: salvator-common: Add ADV7482 support (2018-05-18 11:52:03 +0200)
> 
> This pull request is really, really hard for us to digest. The tag
> description is very large, and it repeats several SoCs several times,
> making it hard to get an overview of what is in it. The verbosity of "<x>
> says.." makes it harder on this size of a pull request as well.

I appologise that this pull-request has turned out to be hard to digest.

I think that one reason for this is that there are an unusally large number
of commits. It seems that the team has been a little more productive than
usual and I might have been better to send a smaller pull-request earlier
in the development cycle and then follow-up with a second batch. I'll try
to pay more attention to this aspect of things going forwards.

Regarding your specific comments:

* Repetition of SoCs. I do try to group things in a logical manner,
  but clearly I failed in this case. I'll try to make that a bit clearer
  in future.

* Verbosity: There as a request a few development cycles for me
  to include more information in the commit logs. It seems that
  I may have gone a bit too far. I'll try to find a better balance next
  time around.

* Patches for the same change split up for different SoCs/boards.
  Featurs broken out into incremental patches. And so on.

  This has been a long-standing practice for Renesas SoC development.
  We find that in general it aids review. It also works well
  with the way we develop patches. But I do see your point that
  it may be a little excessive - f.e. multiple patches for the same
  whitespace fixes. Again, we'll try to find a better balance.

> 
> For example:
> 
> > * Condor board with R-Car V3H (r8a77980) SoC
> >   - Enable eMMC
> > 
> >     Sergei Shtylyov says "We're adding the R8A77980 MMC (SDHI)
> >     device nodes and then enable eMMC support on the Condor board."
> 
> The "Enable eMMC" line is just fine here.
> 
> > ----------------------------------------------------------------
> > Geert Uytterhoeven (11):
> >       arm64: dts: renesas: draak: Rename EtherAVB "mdc" pin group to "mdio"
> >       arm64: dts: renesas: salvator-common: Rename EtherAVB "mdc" pin group to "mdio"
> >       arm64: dts: renesas: ulcb: Rename EtherAVB "mdc" pin group to "mdio"
> 
> Why can't these be done in one commit?
> 
> >       arm64: dts: renesas: r8a7795: Correct whitespace
> >       arm64: dts: renesas: r8a7796: Correct whitespace
> >       arm64: dts: renesas: r8a77965: Correct whitespace
> 
> Do these really need to be three commits to fix some whitespace?
> 
> >       arm64: dts: renesas: ulcb: Add BD9571 PMIC
> >       arm64: dts: renesas: salvator-common: Add PMIC DDR Backup Power config
> >       arm64: dts: renesas: ulcb: Add PMIC DDR Backup Power config
> >       arm64: dts: renesas: r8a77970: Add secondary CA53 CPU core
> >       arm64: dts: renesas: r8a77970: Add Cortex-A53 PMU node
> 
> Why can't these be done in the same commit?
> 
> > Kieran Bingham (7):
> >       arm64: dts: renesas: r8a77965: Add FCPF and FCPV instances
> >       arm64: dts: renesas: r8a77965: Add VSP instances
> >       arm64: dts: renesas: r8a77965: Populate the DU instance placeholder
> >       arm64: dts: renesas: r8a77965: Add HDMI encoder instance
> >       arm64: dts: renesas: r8a77965-salvator-x: Enable DU external clocks and HDMI
> >       arm64: dts: renesas: r8a77965-salvator-xs: Enable DU external clocks and HDMI
> 
> These two can probably be in one commit as well.
> 
> >       arm64: dts: renesas: salvator-common: Add ADV7482 support
> > 
> > Kuninori Morimoto (8):
> >       arm64: dts: renesas: r8a7795: add HDMI sound support
> >       arm64: dts: renesas: r8a7796: add HDMI sound support
> 
> ... starting to see a trend?
> 
> >       arm64: dts: renesas: salvator-common: use audio-graph-card for Sound
> >       arm64: dts: renesas: r8a7795-es1-salvator-x: enable HDMI sound
> >       arm64: dts: renesas: r8a7795-salvator-xs: enable HDMI sound
> >       arm64: dts: renesas: r8a7796-salvator-xs: enable HDMI sound
> >       arm64: dts: renesas: r8a7795-salvator-x: enable HDMI sound
> >       arm64: dts: renesas: r8a7796-salvator-x: enable HDMI sound
> 
> ... and more.
> 
> > 
> > Magnus Damm (5):
> >       arm64: dts: renesas: r8a77970: Update IPMMU DS1 bit number
> >       arm64: dts: renesas: r8a7795: Enable IPMMU devices
> >       arm64: dts: renesas: r8a7796: Enable IPMMU devices
> >       arm64: dts: renesas: r8a77970: Enable IPMMU devices
> >       arm64: dts: renesas: r8a77995: Enable IPMMU devices
> 
> I think these 4 could be in one commit too.
> 
> > 
> > Niklas S?derlund (11):
> >       arm64: dts: renesas: r8a7795: decrease temperature hysteresis
> >       arm64: dts: renesas: r8a7796: decrease temperature hysteresis
> >       arm64: dts: renesas: r8a77965: use r8a77965-sysc binding definitions
> >       arm64: dts: renesas: r8a77965: Add R-Car Gen3 thermal support
> >       arm64: dts: renesas: r8a77965: add I2C support
> >       arm64: dts: renesas: r8a7795: add VIN and CSI-2 nodes
> >       arm64: dts: renesas: r8a7795-es1: add CSI-2 node
> >       arm64: dts: renesas: r8a7796: add VIN and CSI-2 nodes
> >       arm64: dts: renesas: r8a77965: add VIN and CSI-2 nodes
> >       arm64: dts: renesas: r8a77970: add VIN and CSI-2 nodes
> 
> 
> .... etc, etc. I'll stop here.
> 
> 
> I haven't merged this branch yet, will need to set aside more time to review
> the contents. I can't guarantee that it'll make v4.18 but I'll try.

Please let me know if there is anything I can do to help make this happen.
This work is very important to Renesas.

^ permalink raw reply

* [PATCH v4 8/9] drm/mediatek: add third ddp path
From: CK Hu @ 2018-05-28  7:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1527489507-24453-9-git-send-email-stu.hsieh@mediatek.com>

Hi, Stu:

One inline comment.

On Mon, 2018-05-28 at 14:38 +0800, Stu Hsieh wrote:
> This patch create third crtc by third ddp path
> 
> Signed-off-by: Stu Hsieh <stu.hsieh@mediatek.com>
> ---
>  drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 3 +++
>  drivers/gpu/drm/mediatek/mtk_drm_drv.c  | 5 +++++
>  drivers/gpu/drm/mediatek/mtk_drm_drv.h  | 7 +++++--
>  3 files changed, 13 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
> index 658b8dd45b83..2d6aa150a9ff 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
> @@ -539,6 +539,9 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,
>  	int ret;
>  	int i;
>  
> +	if (!path)
> +		return 0;
> +
>  	for (i = 0; i < path_len; i++) {
>  		enum mtk_ddp_comp_id comp_id = path[i];
>  		struct device_node *node;
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> index 08d5d0b47bfe..3d279a299383 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> @@ -232,6 +232,11 @@ static int mtk_drm_kms_init(struct drm_device *drm)
>  	if (ret < 0)
>  		goto err_component_unbind;
>  
> +	ret = mtk_drm_crtc_create(drm, private->data->third_path,
> +				  private->data->third_len);
> +	if (ret < 0)
> +		goto err_component_unbind;
> +
>  	/* Use OVL device for all DMA memory allocations */
>  	np = private->comp_node[private->data->main_path[0]] ?:
>  	     private->comp_node[private->data->ext_path[0]];
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
> index c3378c452c0a..d867e2683923 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
> @@ -17,8 +17,8 @@
>  #include <linux/io.h>
>  #include "mtk_drm_ddp_comp.h"
>  
> -#define MAX_CRTC	2
> -#define MAX_CONNECTOR	2
> +#define MAX_CRTC	3
> +#define MAX_CONNECTOR	3

MAX_CONNECTOR is useless, maybe we just need to remove it in a clean up
patch. Or you could keep its value.

Regards,
CK

>  
>  struct device;
>  struct device_node;
> @@ -33,6 +33,9 @@ struct mtk_mmsys_driver_data {
>  	unsigned int main_len;
>  	const enum mtk_ddp_comp_id *ext_path;
>  	unsigned int ext_len;
> +	const enum mtk_ddp_comp_id *third_path;
> +	unsigned int third_len;
> +
>  	bool shadow_register;
>  };
>  

^ permalink raw reply

* [PATCH] rtc: sun6i: Fix bit_idx value for clk_register_gate
From: Jagan Teki @ 2018-05-28  7:50 UTC (permalink / raw)
  To: linux-arm-kernel

From: Michael Trimarchi <michael@amarulasolutions.com>

clk-gate core will take bit_idx through clk_register_gate
and then do clk_gate_ops by using BIT(bit_idx), but rtc-sun6i
is passing bit_idx as BIT(bit_idx) it becomes BIT(BIT(bit_idx)
which is wrong and eventually external gate clock is not enabling.

This patch fixed by passing bit index and the original change
introduced from below commit.
"rtc: sun6i: Add support for the external oscillator gate"
(sha1: 	17ecd246414b3a0fe0cb248c86977a8bda465b7b)

Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
 drivers/rtc/rtc-sun6i.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c
index 2e6fb275acc8..a66f40c96582 100644
--- a/drivers/rtc/rtc-sun6i.c
+++ b/drivers/rtc/rtc-sun6i.c
@@ -74,7 +74,7 @@
 #define SUN6I_ALARM_CONFIG_WAKEUP		BIT(0)
 
 #define SUN6I_LOSC_OUT_GATING			0x0060
-#define SUN6I_LOSC_OUT_GATING_EN		BIT(0)
+#define SUN6I_LOSC_OUT_GATING_EN		0
 
 /*
  * Get date values
-- 
2.14.3

^ permalink raw reply related

* [PATCH v4 9/9] drm/mediatek: Add support for mediatek SOC MT2712
From: CK Hu @ 2018-05-28  7:53 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1527489507-24453-10-git-send-email-stu.hsieh@mediatek.com>

Hi, Stu:

Two inline comment.

On Mon, 2018-05-28 at 14:38 +0800, Stu Hsieh wrote:
> This patch add support for the Mediatek MT2712 DISP subsystem.
> There are two OVL engine and three disp output in MT2712.
> 
> Signed-off-by: Stu Hsieh <stu.hsieh@mediatek.com>
> ---
>  drivers/gpu/drm/mediatek/mtk_drm_ddp.c | 39 ++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/mediatek/mtk_drm_drv.c | 38 +++++++++++++++++++++++++++++++++
>  2 files changed, 77 insertions(+)
> 
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
> index 8bfc0debd2c2..3b22b48a6022 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
> @@ -61,6 +61,24 @@
>  #define MT8173_MUTEX_MOD_DISP_PWM1		24
>  #define MT8173_MUTEX_MOD_DISP_OD		25
>  
> +#define MT2712_MUTEX_MOD_DISP_PWM2		10
> +#define MT2712_MUTEX_MOD_DISP_OVL0		11
> +#define MT2712_MUTEX_MOD_DISP_OVL1		12
> +#define MT2712_MUTEX_MOD_DISP_RDMA0		13
> +#define MT2712_MUTEX_MOD_DISP_RDMA1		14
> +#define MT2712_MUTEX_MOD_DISP_RDMA2		15
> +#define MT2712_MUTEX_MOD_DISP_WDMA0		16
> +#define MT2712_MUTEX_MOD_DISP_WDMA1		17
> +#define MT2712_MUTEX_MOD_DISP_COLOR0		18
> +#define MT2712_MUTEX_MOD_DISP_COLOR1		19
> +#define MT2712_MUTEX_MOD_DISP_AAL0		20
> +#define MT2712_MUTEX_MOD_DISP_UFOE		22
> +#define MT2712_MUTEX_MOD_DISP_PWM0		23
> +#define MT2712_MUTEX_MOD_DISP_PWM1		24
> +#define MT2712_MUTEX_MOD_DISP_OD0		25
> +#define MT2712_MUTEX_MOD2_DISP_AAL1		33
> +#define MT2712_MUTEX_MOD2_DISP_OD1		34
> +
>  #define MT2701_MUTEX_MOD_DISP_OVL		3
>  #define MT2701_MUTEX_MOD_DISP_WDMA		6
>  #define MT2701_MUTEX_MOD_DISP_COLOR		7
> @@ -110,6 +128,26 @@ static const unsigned int mt2701_mutex_mod[DDP_COMPONENT_ID_MAX] = {
>  	[DDP_COMPONENT_WDMA0] = MT2701_MUTEX_MOD_DISP_WDMA,
>  };
>  
> +static const unsigned int mt2712_mutex_mod[DDP_COMPONENT_ID_MAX] = {
> +	[DDP_COMPONENT_AAL0] = MT2712_MUTEX_MOD_DISP_AAL0,
> +	[DDP_COMPONENT_AAL1] = MT2712_MUTEX_MOD2_DISP_AAL1,
> +	[DDP_COMPONENT_COLOR0] = MT2712_MUTEX_MOD_DISP_COLOR0,
> +	[DDP_COMPONENT_COLOR1] = MT2712_MUTEX_MOD_DISP_COLOR1,
> +	[DDP_COMPONENT_OD0] = MT2712_MUTEX_MOD_DISP_OD0,
> +	[DDP_COMPONENT_OD1] = MT2712_MUTEX_MOD2_DISP_OD1,
> +	[DDP_COMPONENT_OVL0] = MT2712_MUTEX_MOD_DISP_OVL0,
> +	[DDP_COMPONENT_OVL1] = MT2712_MUTEX_MOD_DISP_OVL1,
> +	[DDP_COMPONENT_PWM0] = MT2712_MUTEX_MOD_DISP_PWM0,
> +	[DDP_COMPONENT_PWM1] = MT2712_MUTEX_MOD_DISP_PWM1,
> +	[DDP_COMPONENT_PWM2] = MT2712_MUTEX_MOD_DISP_PWM2,
> +	[DDP_COMPONENT_RDMA0] = MT2712_MUTEX_MOD_DISP_RDMA0,
> +	[DDP_COMPONENT_RDMA1] = MT2712_MUTEX_MOD_DISP_RDMA1,
> +	[DDP_COMPONENT_RDMA2] = MT2712_MUTEX_MOD_DISP_RDMA2,
> +	[DDP_COMPONENT_UFOE] = MT2712_MUTEX_MOD_DISP_UFOE,
> +	[DDP_COMPONENT_WDMA0] = MT2712_MUTEX_MOD_DISP_WDMA0,
> +	[DDP_COMPONENT_WDMA1] = MT2712_MUTEX_MOD_DISP_WDMA1,
> +};
> +
>  static const unsigned int mt8173_mutex_mod[DDP_COMPONENT_ID_MAX] = {
>  	[DDP_COMPONENT_AAL0] = MT8173_MUTEX_MOD_DISP_AAL,
>  	[DDP_COMPONENT_COLOR0] = MT8173_MUTEX_MOD_DISP_COLOR0,
> @@ -430,6 +468,7 @@ static int mtk_ddp_remove(struct platform_device *pdev)
>  
>  static const struct of_device_id ddp_driver_dt_match[] = {
>  	{ .compatible = "mediatek,mt2701-disp-mutex", .data = mt2701_mutex_mod},
> +	{ .compatible = "mediatek,mt2712-disp-mutex", .data = mt2712_mutex_mod},
>  	{ .compatible = "mediatek,mt8173-disp-mutex", .data = mt8173_mutex_mod},
>  	{},
>  };
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> index 3d279a299383..3a866e1d6af4 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> @@ -146,6 +146,32 @@ static const enum mtk_ddp_comp_id mt2701_mtk_ddp_ext[] = {
>  	DDP_COMPONENT_DPI0,
>  };
>  
> +static const enum mtk_ddp_comp_id mt2712_mtk_ddp_main[] = {
> +	DDP_COMPONENT_OVL0,
> +	DDP_COMPONENT_COLOR0,
> +	DDP_COMPONENT_AAL0,
> +	DDP_COMPONENT_OD0,
> +	DDP_COMPONENT_RDMA0,
> +	DDP_COMPONENT_DPI0,
> +	DDP_COMPONENT_PWM0,
> +};
> +
> +static const enum mtk_ddp_comp_id mt2712_mtk_ddp_ext[] = {
> +	DDP_COMPONENT_OVL1,
> +	DDP_COMPONENT_COLOR1,
> +	DDP_COMPONENT_AAL1,
> +	DDP_COMPONENT_OD1,
> +	DDP_COMPONENT_RDMA1,
> +	DDP_COMPONENT_DPI1,

Where do you define DDP_COMPONENT_DPI1?

> +	DDP_COMPONENT_PWM1,
> +};
> +
> +static const enum mtk_ddp_comp_id mt2712_mtk_ddp_third[] = {
> +	DDP_COMPONENT_RDMA2,
> +	DDP_COMPONENT_DSI2,

Where do you define DDP_COMPONENT_DSI2?

Regards,
CK

> +	DDP_COMPONENT_PWM2,
> +};
> +
>  static const enum mtk_ddp_comp_id mt8173_mtk_ddp_main[] = {
>  	DDP_COMPONENT_OVL0,
>  	DDP_COMPONENT_COLOR0,
> @@ -173,6 +199,15 @@ static const struct mtk_mmsys_driver_data mt2701_mmsys_driver_data = {
>  	.shadow_register = true,
>  };
>  
> +static const struct mtk_mmsys_driver_data mt2712_mmsys_driver_data = {
> +	.main_path = mt2712_mtk_ddp_main,
> +	.main_len = ARRAY_SIZE(mt2712_mtk_ddp_main),
> +	.ext_path = mt2712_mtk_ddp_ext,
> +	.ext_len = ARRAY_SIZE(mt2712_mtk_ddp_ext),
> +	.third_path = mt2712_mtk_ddp_third,
> +	.third_len = ARRAY_SIZE(mt2712_mtk_ddp_third),
> +};
> +
>  static const struct mtk_mmsys_driver_data mt8173_mmsys_driver_data = {
>  	.main_path = mt8173_mtk_ddp_main,
>  	.main_len = ARRAY_SIZE(mt8173_mtk_ddp_main),
> @@ -379,6 +414,7 @@ static const struct of_device_id mtk_ddp_comp_dt_ids[] = {
>  	{ .compatible = "mediatek,mt8173-dsi",        .data = (void *)MTK_DSI },
>  	{ .compatible = "mediatek,mt8173-dpi",        .data = (void *)MTK_DPI },
>  	{ .compatible = "mediatek,mt2701-disp-mutex", .data = (void *)MTK_DISP_MUTEX },
> +	{ .compatible = "mediatek,mt2712-disp-mutex", .data = (void *)MTK_DISP_MUTEX },
>  	{ .compatible = "mediatek,mt8173-disp-mutex", .data = (void *)MTK_DISP_MUTEX },
>  	{ .compatible = "mediatek,mt2701-disp-pwm",   .data = (void *)MTK_DISP_BLS },
>  	{ .compatible = "mediatek,mt8173-disp-pwm",   .data = (void *)MTK_DISP_PWM },
> @@ -557,6 +593,8 @@ static SIMPLE_DEV_PM_OPS(mtk_drm_pm_ops, mtk_drm_sys_suspend,
>  static const struct of_device_id mtk_drm_of_ids[] = {
>  	{ .compatible = "mediatek,mt2701-mmsys",
>  	  .data = &mt2701_mmsys_driver_data},
> +	{ .compatible = "mediatek,mt2712-mmsys",
> +	  .data = &mt2712_mmsys_driver_data},
>  	{ .compatible = "mediatek,mt8173-mmsys",
>  	  .data = &mt8173_mmsys_driver_data},
>  	{ }

^ permalink raw reply

* [PATCH 5/5] MAINTAINERS: imx: add NXP linux team upstream maillist as reviewer
From: Shawn Guo @ 2018-05-28  8:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <AM0PR04MB4211D5AE2B22FFB8BA532ADD80690@AM0PR04MB4211.eurprd04.prod.outlook.com>

On Fri, May 25, 2018 at 02:14:07AM +0000, A.s. Dong wrote:
> Hi Shawn,
> 
> > -----Original Message-----
> > From: A.s. Dong
> > Sent: Saturday, April 28, 2018 3:06 AM
> > To: linux-arm-kernel at lists.infradead.org
> > Cc: dongas86 at gmail.com; kernel at pengutronix.de; shawnguo at kernel.org;
> > Fabio Estevam <fabio.estevam@nxp.com>; robh+dt at kernel.org;
> > catalin.marinas at arm.com; will.deacon at arm.com; dl-linux-imx <linux-
> > imx at nxp.com>; A.s. Dong <aisheng.dong@nxp.com>
> > Subject: [PATCH 5/5] MAINTAINERS: imx: add NXP linux team upstream
> > maillist as reviewer
> > 
> > Add NXP linux team upstream maillist as reviewer
> > 
> > Cc: Shawn Guo <shawnguo@kernel.org>
> > Cc: Sascha Hauer <kernel@pengutronix.de>
> > Cc: Fabio Estevam <fabio.estevam@nxp.com>
> > Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
> 
> Would you pick this one first?

Okay.  I changed patch subject a bit as below and applied the patch,
since usually we do not have subsystem prefix for MAINTAINERS change.

  MAINTAINERS: add NXP linux team maillist as i.MX reviewer

Shawn

^ permalink raw reply

* [PATCH v4 3/6] mfd: at91-usart: added mfd driver for usart
From: Andy Shevchenko @ 2018-05-28  8:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180525171941.26766-4-radu.pirea@microchip.com>

On Fri, May 25, 2018 at 8:19 PM, Radu Pirea <radu.pirea@microchip.com> wrote:
> This mfd driver is just a wrapper over atmel_serial driver and
> spi-at91-usart driver. Selection of one of the drivers is based on a
> property from device tree. If the property is not specified, the default
> driver is atmel_serial.

> +       depends on OF

What makes this driver OF specific?

> +#include <linux/of.h>
> +#include <linux/of_platform.h>

Ditto.

> +#include <linux/pinctrl/pinctrl.h>

How exactly is this used?

> +#include <linux/platform_device.h>

> +#include <linux/slab.h>

Ditto.

> +#include <linux/types.h>

> +static int at91_usart_mode_probe(struct platform_device *pdev)
> +{
> +       struct device_node *np = pdev->dev.of_node;
> +       struct mfd_cell cell;
> +       u32 opmode;
> +       int err;
> +

> +       err = of_property_read_u32(np, "atmel,usart-mode", &opmode);

Check unified device property API.

> +       return mfd_add_devices(&pdev->dev, PLATFORM_DEVID_AUTO, &cell, 1,
> +                             NULL, 0, NULL);

No devm_ and no ->remove(). Why to leak resources?

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply

* [GIT PULL] i.MX maintainers update for 4.18
From: Shawn Guo @ 2018-05-28  8:15 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Arnd, Olof,

I'm not sure which one is easier for you.  You can pull the request or
apply the patch to some arm-soc branch directly.

Shawn


The following changes since commit 60cc43fc888428bb2f18f08997432d426a243338:

  Linux 4.17-rc1 (2018-04-15 18:24:20 -0700)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git tags/imx-maintainers-4.18

for you to fetch changes up to c309f0cdc30667efd233f1220587fb0b18c8423b:

  MAINTAINERS: add NXP linux team maillist as i.MX reviewer (2018-05-28 15:55:07 +0800)

----------------------------------------------------------------
i.MX maintainers update for 4.18:
 - Add NXP linux team as a reviewer for i.MX platform support.

----------------------------------------------------------------
Dong Aisheng (1):
      MAINTAINERS: add NXP linux team maillist as i.MX reviewer

 MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)

^ permalink raw reply

* [PATCH v4 5/6] spi: at91-usart: add driver for at91-usart as spi
From: Andy Shevchenko @ 2018-05-28  8:21 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180525171941.26766-6-radu.pirea@microchip.com>

On Fri, May 25, 2018 at 8:19 PM, Radu Pirea <radu.pirea@microchip.com> wrote:
> This is the driver for at91-usart in spi mode. The USART IP can be configured
> to work in many modes and one of them is SPI.
>
> The driver was tested on sama5d3-xplained and sama5d4-xplained boards with
> enc28j60 ethernet controller as slave.

> +#include <linux/of_gpio.h>

What is the use of it?

> +#define US_INIT                        (US_MR_SPI_MASTER | US_MR_CHRL | US_MR_CLKO | \
> +                               US_MR_WRDBT)

Don't split lines like this, it's hard to read.

#define FOO \
 (BAR1 | BAR2)

I think I already told this to someone recently, maybe to you.

> +/* Register access macros */
> +#define spi_readl(port, reg) \
> +       readl_relaxed((port)->regs + US_##reg)
> +#define spi_writel(port, reg, value) \
> +       writel_relaxed((value), (port)->regs + US_##reg)
> +
> +#define spi_readb(port, reg) \
> +       readb_relaxed((port)->regs + US_##reg)
> +#define spi_writeb(port, reg, value) \
> +       writeb_relaxed((value), (port)->regs + US_##reg)

Names are too generic. You better to use the same prefix as for the
rest, i.e. at91_spi_

> +       /*used in interrupt to protect data reading*/

Comment style.

You need to read some existing code, perhaps, to see how it's done.

> +static inline void at91_usart_spi_tx(struct at91_usart_spi *aus)
> +{
> +       unsigned int len = aus->current_transfer->len;
> +       unsigned int remaining = aus->current_tx_remaining_bytes;
> +       const u8  *tx_buf = aus->current_transfer->tx_buf;
> +

> +       if (remaining)
> +               if (at91_usart_spi_tx_ready(aus)) {

if (x) {
 if (y) {
...
 }
}

is equivalent to if (x && y) {}.

Though, considering your intention here, I would rather go with better
pattern, i.e.

if (!remaining)
 return;

> +                       spi_writeb(aus, THR, tx_buf[len - remaining]);
> +                       aus->current_tx_remaining_bytes--;
> +               }
> +}
> +
> +static inline void at91_usart_spi_rx(struct at91_usart_spi *aus)
> +{

> +       if (remaining) {
> +               rx_buf[len - remaining] = spi_readb(aus, RHR);
> +               aus->current_rx_remaining_bytes--;
> +       }

Ditto.

> +}


> +static int at91_usart_gpio_setup(struct platform_device *pdev)
> +{

> +       struct device_node      *np = pdev->dev.parent->of_node;

Your driver is not OF specific as far as I can see. Drop all these
device_node stuff and change API calls respectively.

> +       int                     i;

> +       int                     ret = 0;
> +       int                     nb = 0;

What happened to indentation?

Redundnant assignment for both.

> +       if (!np)
> +               return -EINVAL;
> +
> +       nb = of_gpio_named_count(np, "cs-gpios");
> +       for (i = 0; i < nb; i++) {
> +               int cs_gpio = of_get_named_gpio(np, "cs-gpios", i);
> +
> +               if (cs_gpio < 0)
> +                       return cs_gpio;
> +
> +               if (gpio_is_valid(cs_gpio)) {
> +                       ret = devm_gpio_request_one(&pdev->dev, cs_gpio,
> +                                                   GPIOF_DIR_OUT,
> +                                                   dev_name(&pdev->dev));
> +                       if (ret)
> +                               return ret;
> +               }
> +       }
> +
> +       return 0;
> +}
> +
> +static int at91_usart_spi_probe(struct platform_device *pdev)
> +{

> +       regs = platform_get_resource(to_platform_device(pdev->dev.parent),
> +                                    IORESOURCE_MEM, 0);
> +       if (!regs)
> +               return -EINVAL;

This looks weird. Supply resource to _this_ device in your MFD code.

> +       dev_info(&pdev->dev,
> +                "Atmel USART SPI Controller version 0x%x at 0x%08lx (irq %d)\n",
> +                spi_readl(aus, VERSION),
> +                (unsigned long)regs->start, irq);

I think I already told you, don't use explicit casting when print.
If it wasn't you, do you homework then. But above is no go.

> +       return 0;

> +static struct platform_driver at91_usart_spi_driver = {
> +       .driver = {
> +               .name = "at91_usart_spi",

> +               .of_match_table = of_match_ptr(at91_usart_spi_dt_ids),

Drop of_match_ptr(). It's not needed.

> +       },
> +       .probe = at91_usart_spi_probe,

> +       .remove = at91_usart_spi_remove, };

Already told ya, split lines correctly.

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply

* [PATCH] ARM: dts: cygnus: add ethernet0 alias
From: Clément Péron @ 2018-05-28  8:22 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <74263153-2f69-71e1-513b-e034a505588b@gmail.com>

Could you review it, please.
Thanks

On Thu, 3 May 2018 at 17:13, Florian Fainelli <f.fainelli@gmail.com> wrote:

> +Ray, Scott, Eric, list

> On 05/03/2018 02:56 AM, Cl?ment P?ron wrote:
> > In order to avoid Linux generating a random mac address on every boot,
> > add an ethernet0 alias that will allow u-boot to patch the dtb with
> > the MAC address.
> >
> > Signed-off-by: Cl?ment P?ron <peron.clem@gmail.com>
> > ---
> >  arch/arm/boot/dts/bcm-cygnus.dtsi | 4 ++++
> >  1 file changed, 4 insertions(+)
> >
> > diff --git a/arch/arm/boot/dts/bcm-cygnus.dtsi
b/arch/arm/boot/dts/bcm-cygnus.dtsi
> > index 9fe4f5a6379e..1a05b8f48b54 100644
> > --- a/arch/arm/boot/dts/bcm-cygnus.dtsi
> > +++ b/arch/arm/boot/dts/bcm-cygnus.dtsi
> > @@ -41,6 +41,10 @@
> >       model = "Broadcom Cygnus SoC";
> >       interrupt-parent = <&gic>;
> >
> > +     aliases {
> > +             ethernet0 = &eth0;
> > +     };
> > +
> >       cpus {
> >               #address-cells = <1>;
> >               #size-cells = <0>;
> >

> --
> Florian

Clement

^ permalink raw reply

* [PATCH v1 1/7] drm/mediatek: move dpi private data to device
From: CK Hu @ 2018-05-28  8:25 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180514075243.5442-2-bibby.hsieh@mediatek.com>

Hi, Bibby:

Some inline comment.

On Mon, 2018-05-14 at 15:52 +0800, Bibby Hsieh wrote:
> From: chunhui dai <chunhui.dai@mediatek.com>
> 
> move clock factor and edge enable setting to private data.
> 

I think this modification is to separate different part of dpi driver
for different chip.
Describe more for this.


> Signed-off-by: chunhui dai <chunhui.dai@mediatek.com>
> ---
>  drivers/gpu/drm/mediatek/mtk_dpi.c      | 82 ++++++++++++++++++++++++++-------
>  drivers/gpu/drm/mediatek/mtk_dpi_regs.h |  2 +-
>  2 files changed, 66 insertions(+), 18 deletions(-)
> 
> diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
> index e80a603e5fb0..993dc44368bd 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dpi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
> @@ -71,11 +71,13 @@ struct mtk_dpi {
>  	struct clk *tvd_clk;
>  	int irq;
>  	struct drm_display_mode mode;
> +	const struct mtk_dpi_conf *conf;
>  	enum mtk_dpi_out_color_format color_format;
>  	enum mtk_dpi_out_yc_map yc_map;
>  	enum mtk_dpi_out_bit_num bit_num;
>  	enum mtk_dpi_out_channel_swap channel_swap;
>  	bool power_sta;
> +	int refcount;
>  	u8 power_ctl;
>  };
>  
> @@ -115,6 +117,12 @@ struct mtk_dpi_yc_limit {
>  	u16 c_bottom;
>  };
>  
> +struct mtk_dpi_conf {
> +	unsigned int (*cal_factor)(int clock);
> +	const u32 reg_h_fre_con;
> +	bool edge_sel_en;
> +};
> +
>  static void mtk_dpi_mask(struct mtk_dpi *dpi, u32 offset, u32 val, u32 mask)
>  {
>  	u32 tmp = readl(dpi->regs + offset) & ~mask;
> @@ -340,7 +348,13 @@ static void mtk_dpi_config_swap_input(struct mtk_dpi *dpi, bool enable)
>  
>  static void mtk_dpi_config_2n_h_fre(struct mtk_dpi *dpi)
>  {
> -	mtk_dpi_mask(dpi, DPI_H_FRE_CON, H_FRE_2N, H_FRE_2N);
> +	mtk_dpi_mask(dpi, dpi->conf->reg_h_fre_con, H_FRE_2N, H_FRE_2N);
> +}
> +
> +static void mtk_dpi_config_disable_edge(struct mtk_dpi *dpi)
> +{
> +	if (dpi->conf->edge_sel_en)
> +		mtk_dpi_mask(dpi, dpi->conf->reg_h_fre_con, 0, EDGE_SEL_EN);
>  }
>  
>  static void mtk_dpi_config_color_format(struct mtk_dpi *dpi,
> @@ -368,6 +382,12 @@ static void mtk_dpi_config_color_format(struct mtk_dpi *dpi,
>  
>  static void mtk_dpi_power_off(struct mtk_dpi *dpi, enum mtk_dpi_power_ctl pctl)
>  {
> +	if (WARN_ON(dpi->refcount == 0))
> +		return;
> +
> +	if (--dpi->refcount != 0)
> +		return;
> +

I think 'refcount' should be moved to an independent patch.

>  	dpi->power_ctl &= ~pctl;
>  
>  	if ((dpi->power_ctl & DPI_POWER_START) ||
> @@ -385,16 +405,19 @@ static void mtk_dpi_power_off(struct mtk_dpi *dpi, enum mtk_dpi_power_ctl pctl)
>  
>  static int mtk_dpi_power_on(struct mtk_dpi *dpi, enum mtk_dpi_power_ctl pctl)
>  {
> -	int ret;
> +	int ret = 0;
> +
> +	if (++dpi->refcount != 1)
> +		return 0;
>  
>  	dpi->power_ctl |= pctl;
>  
>  	if (!(dpi->power_ctl & DPI_POWER_START) &&
>  	    !(dpi->power_ctl & DPI_POWER_ENABLE))
> -		return 0;
> +		goto err_refcount;
>  
>  	if (dpi->power_sta)
> -		return 0;
> +		goto err_refcount;
>  
>  	ret = clk_prepare_enable(dpi->engine_clk);
>  	if (ret) {
> @@ -416,6 +439,8 @@ static int mtk_dpi_power_on(struct mtk_dpi *dpi, enum mtk_dpi_power_ctl pctl)
>  	clk_disable_unprepare(dpi->engine_clk);
>  err_eng:
>  	dpi->power_ctl &= ~pctl;
> +err_refcount:
> +	dpi->refcount--;
>  	return ret;
>  }
>  
> @@ -433,16 +458,13 @@ static int mtk_dpi_set_display_mode(struct mtk_dpi *dpi,
>  	unsigned long pll_rate;
>  	unsigned int factor;
>  
> +	if (!dpi) {
> +		dev_err(dpi->dev, "invalid argument\n");
> +		return -EINVAL;
> +	}
>  	/* let pll_rate can fix the valid range of tvdpll (1G~2GHz) */
>  	pix_rate = 1000UL * mode->clock;
> -	if (mode->clock <= 27000)
> -		factor = 16 * 3;
> -	else if (mode->clock <= 84000)
> -		factor = 8 * 3;
> -	else if (mode->clock <= 167000)
> -		factor = 4 * 3;
> -	else
> -		factor = 2 * 3;
> +	factor = dpi->conf->cal_factor(mode->clock);
>  	pll_rate = pix_rate * factor;
>  
>  	dev_dbg(dpi->dev, "Want PLL %lu Hz, pixel clock %lu Hz\n",
> @@ -518,6 +540,7 @@ static int mtk_dpi_set_display_mode(struct mtk_dpi *dpi,
>  	mtk_dpi_config_yc_map(dpi, dpi->yc_map);
>  	mtk_dpi_config_color_format(dpi, dpi->color_format);
>  	mtk_dpi_config_2n_h_fre(dpi);
> +	mtk_dpi_config_disable_edge(dpi);

What does this do? Separate this to an independent patch and describe
what does this do.

>  	mtk_dpi_sw_reset(dpi, false);
>  
>  	return 0;
> @@ -656,6 +679,31 @@ static const struct component_ops mtk_dpi_component_ops = {
>  	.unbind = mtk_dpi_unbind,
>  };
>  
> +static unsigned int mt8173_calculate_factor(int clock)
> +{
> +	if (clock <= 27000)
> +		return 16 * 3;
> +	else if (clock <= 74250)

Why do you change 84000 to 74250? If 74250 is correct for mt8173, use a
new patch for this bug fix.

Regards,
CK

> +		return 8 * 3;
> +	else if (clock <= 167000)
> +		return 4 * 3;
> +	else
> +		return 2 * 3;
> +}
> +
> +static const struct mtk_dpi_conf mt8173_conf = {
> +	.cal_factor = mt8173_calculate_factor,
> +	.reg_h_fre_con = 0xe0,
> +};
> +
> +static const struct of_device_id mtk_dpi_of_ids[] = {
> +	{ .compatible = "mediatek,mt8173-dpi",
> +	  .data = &mt8173_conf,
> +	},
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(of, mtk_dpi_of_ids);
> +
>  static int mtk_dpi_probe(struct platform_device *pdev)
>  {
>  	struct device *dev = &pdev->dev;
> @@ -663,13 +711,18 @@ static int mtk_dpi_probe(struct platform_device *pdev)
>  	struct resource *mem;
>  	struct device_node *bridge_node;
>  	int comp_id;
> +	const struct of_device_id *match;
>  	int ret;
>  
> +	match = of_match_node(mtk_dpi_of_ids, dev->of_node);
> +	if (!match)
> +		return -ENODEV;
>  	dpi = devm_kzalloc(dev, sizeof(*dpi), GFP_KERNEL);
>  	if (!dpi)
>  		return -ENOMEM;
>  
>  	dpi->dev = dev;
> +	dpi->conf = (struct mtk_dpi_conf *)match->data;
>  
>  	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>  	dpi->regs = devm_ioremap_resource(dev, mem);
> @@ -748,11 +801,6 @@ static int mtk_dpi_remove(struct platform_device *pdev)
>  	return 0;
>  }
>  
> -static const struct of_device_id mtk_dpi_of_ids[] = {
> -	{ .compatible = "mediatek,mt8173-dpi", },
> -	{}
> -};
> -
>  struct platform_driver mtk_dpi_driver = {
>  	.probe = mtk_dpi_probe,
>  	.remove = mtk_dpi_remove,
> diff --git a/drivers/gpu/drm/mediatek/mtk_dpi_regs.h b/drivers/gpu/drm/mediatek/mtk_dpi_regs.h
> index 4b6ad4751a31..d9db8c4cacd7 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dpi_regs.h
> +++ b/drivers/gpu/drm/mediatek/mtk_dpi_regs.h
> @@ -223,6 +223,6 @@
>  #define ESAV_CODE2			(0xFFF << 0)
>  #define ESAV_CODE3_MSB			BIT(16)
>  
> -#define DPI_H_FRE_CON		0xE0
> +#define EDGE_SEL_EN			BIT(5)
>  #define H_FRE_2N			BIT(25)
>  #endif /* __MTK_DPI_REGS_H */

^ permalink raw reply

* [PATCH v1 2/7] drm/mediatek: fix to get right bridge for dpi encoder
From: CK Hu @ 2018-05-28  8:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180514075243.5442-3-bibby.hsieh@mediatek.com>

Hi, Bibby:

Some inline comment.

On Mon, 2018-05-14 at 15:52 +0800, Bibby Hsieh wrote:
> From: chunhui dai <chunhui.dai@mediatek.com>
> 
> 1, dpi is an encoder, there is an bridge in the struct
> of decoder, we could use it.

The encoder.bridge is assigned in drm_bridge_attach(), so I think the
design is to assign this member in drm_bridge_attach().
Any assignment outside this function may conflict with this design.

> 2, using of_graph_get_remote_port_parent to get right
> bridge in device tree.
> 
> Signed-off-by: chunhui dai <chunhui.dai@mediatek.com>
> ---
>  drivers/gpu/drm/mediatek/mtk_dpi.c | 21 +++++++++++++--------
>  1 file changed, 13 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
> index 0a44ab175422..2b8b34c72697 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dpi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
> @@ -63,7 +63,6 @@ enum mtk_dpi_out_color_format {
>  struct mtk_dpi {
>  	struct mtk_ddp_comp ddp_comp;
>  	struct drm_encoder encoder;
> -	struct drm_bridge *bridge;
>  	void __iomem *regs;
>  	struct device *dev;
>  	struct clk *engine_clk;
> @@ -643,8 +642,8 @@ static int mtk_dpi_bind(struct device *dev, struct device *master, void *data)
>  
>  	/* Currently DPI0 is fixed to be driven by OVL1 */
>  	dpi->encoder.possible_crtcs = BIT(1);
> -
> -	ret = drm_bridge_attach(&dpi->encoder, dpi->bridge, NULL);
> +	dpi->encoder.bridge->encoder = &dpi->encoder;

This is done inside drm_bridge_attach().

> +	ret = drm_bridge_attach(&dpi->encoder, dpi->encoder.bridge, NULL);
>  	if (ret) {
>  		dev_err(dev, "Failed to attach bridge: %d\n", ret);
>  		goto err_cleanup;
> @@ -709,7 +708,7 @@ static int mtk_dpi_probe(struct platform_device *pdev)
>  	struct device *dev = &pdev->dev;
>  	struct mtk_dpi *dpi;
>  	struct resource *mem;
> -	struct device_node *bridge_node;
> +	struct device_node *ep, *bridge_node;
>  	int comp_id;
>  	const struct of_device_id *match;
>  	int ret;
> @@ -759,15 +758,21 @@ static int mtk_dpi_probe(struct platform_device *pdev)
>  		return -EINVAL;
>  	}
>  
> -	bridge_node = of_graph_get_remote_node(dev->of_node, 0, 0);
> -	if (!bridge_node)
> +	ep = of_graph_get_next_endpoint(dev->of_node, NULL);
> +	if (ep) {
> +		bridge_node = of_graph_get_remote_port_parent(ep);
> +		of_node_put(ep);
> +	}
> +	if (!bridge_node) {
> +		dev_err(dev, "Failed to find bridge node\n");
>  		return -ENODEV;
> +	}

This looks like mt8173 has the same bug, so send this patch
independently and it would be more quick to merge.
For mtk_dsi, it use drm_of_find_panel_or_bridge(), so I think you could
use the same function to get bridge.

Regards,
CK

>  
>  	dev_info(dev, "Found bridge node: %pOF\n", bridge_node);
>  
> -	dpi->bridge = of_drm_find_bridge(bridge_node);
> +	dpi->encoder.bridge = of_drm_find_bridge(bridge_node);
>  	of_node_put(bridge_node);
> -	if (!dpi->bridge)
> +	if (!dpi->encoder.bridge)
>  		return -EPROBE_DEFER;
>  
>  	comp_id = mtk_ddp_comp_get_id(dev->of_node, MTK_DPI);

^ permalink raw reply

* [PATCH v1 4/7] drm/mediatek: add hdmi driver for different hardware
From: CK Hu @ 2018-05-28  8:32 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180514075243.5442-5-bibby.hsieh@mediatek.com>

Hi, Bibby:

On Mon, 2018-05-14 at 15:52 +0800, Bibby Hsieh wrote:
> From: chunhui dai <chunhui.dai@mediatek.com>
> 
> This patch adds hdmi driver suppot for both MT2701 and MT7623.
> And also support other (existing or future) chips that use
> the same binding and driver.

I think this patch should be separated to at least two patches.
The first is to isolate the different part for mt8173. And the second is
to add mt2701 part.

Regards,
CK

> 
> Signed-off-by: Chunhui Dai <chunhui.dai@mediatek.com>
> ---
>  drivers/gpu/drm/mediatek/Makefile              |   4 +-
>  drivers/gpu/drm/mediatek/mtk_hdmi.c            |  91 +++++---
>  drivers/gpu/drm/mediatek/mtk_hdmi.h            |  28 +++
>  drivers/gpu/drm/mediatek/mtk_hdmi_phy.c        | 157 +++++++++++++
>  drivers/gpu/drm/mediatek/mtk_hdmi_regs.h       |   1 +
>  drivers/gpu/drm/mediatek/mtk_mt2701_hdmi_phy.c | 307 +++++++++++++++++++++++++
>  drivers/gpu/drm/mediatek/mtk_mt8173_hdmi_phy.c | 129 +----------
>  7 files changed, 568 insertions(+), 149 deletions(-)
>  create mode 100644 drivers/gpu/drm/mediatek/mtk_hdmi_phy.c
>  create mode 100644 drivers/gpu/drm/mediatek/mtk_mt2701_hdmi_phy.c
> 
> diff --git a/drivers/gpu/drm/mediatek/Makefile b/drivers/gpu/drm/mediatek/Makefile
> index ce83c396a742..44464893c1cb 100644
> --- a/drivers/gpu/drm/mediatek/Makefile
> +++ b/drivers/gpu/drm/mediatek/Makefile
> @@ -18,6 +18,8 @@ obj-$(CONFIG_DRM_MEDIATEK) += mediatek-drm.o
>  mediatek-drm-hdmi-objs := mtk_cec.o \
>  			  mtk_hdmi.o \
>  			  mtk_hdmi_ddc.o \
> -			  mtk_mt8173_hdmi_phy.o
> +			  mtk_mt2701_hdmi_phy.o \
> +			  mtk_mt8173_hdmi_phy.o \
> +			  mtk_hdmi_phy.o
>  
>  obj-$(CONFIG_DRM_MEDIATEK_HDMI) += mediatek-drm-hdmi.o
> diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
> index 59a11026dceb..85e280962aad 100644
> --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
> @@ -233,6 +233,7 @@ static void mtk_hdmi_hw_vid_black(struct mtk_hdmi *hdmi, bool black)
>  static void mtk_hdmi_hw_make_reg_writable(struct mtk_hdmi *hdmi, bool enable)
>  {
>  	struct arm_smccc_res res;
> +	struct mtk_hdmi_phy *hdmi_phy = phy_get_drvdata(hdmi->phy);
>  
>  	/*
>  	 * MT8173 HDMI hardware has an output control bit to enable/disable HDMI
> @@ -240,8 +241,13 @@ static void mtk_hdmi_hw_make_reg_writable(struct mtk_hdmi *hdmi, bool enable)
>  	 * The ARM trusted firmware provides an API for the HDMI driver to set
>  	 * this control bit to enable HDMI output in supervisor mode.
>  	 */
> -	arm_smccc_smc(MTK_SIP_SET_AUTHORIZED_SECURE_REG, 0x14000904, 0x80000000,
> -		      0, 0, 0, 0, 0, &res);
> +	if (hdmi_phy->conf && hdmi_phy->conf->tz_enabled)
> +		arm_smccc_smc(MTK_SIP_SET_AUTHORIZED_SECURE_REG, 0x14000904,
> +			      0x80000000, 0, 0, 0, 0, 0, &res);
> +	else
> +		regmap_update_bits(hdmi->sys_regmap,
> +				   hdmi->sys_offset + HDMI_SYS_CFG20,
> +				   HDMI_PSECUR_EN, enable ? 0 : HDMI_PSECUR_EN);
>  
>  	regmap_update_bits(hdmi->sys_regmap, hdmi->sys_offset + HDMI_SYS_CFG20,
>  			   HDMI_PCLK_FREE_RUN, enable ? HDMI_PCLK_FREE_RUN : 0);
> @@ -1437,6 +1443,7 @@ static int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi,
>  	struct platform_device *cec_pdev;
>  	struct regmap *regmap;
>  	struct resource *mem;
> +	const char *phy_name;
>  	int ret;
>  
>  	ret = mtk_hdmi_get_all_clk(hdmi, np);
> @@ -1445,9 +1452,20 @@ static int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi,
>  		return ret;
>  	}
>  
> +	ret = of_property_read_string(np, "phy-names", &phy_name);
> +	if (ret < 0) {
> +		dev_err(dev, "Failed to read phy-names: %d\n", ret);
> +		return ret;
> +	}
> +	hdmi->phy = devm_phy_get(dev, phy_name);
> +	if (IS_ERR(hdmi->phy)) {
> +		ret = PTR_ERR(hdmi->phy);
> +		dev_err(dev, "Failed to get HDMI PHY: %d\n", ret);
> +		return ret;
> +	}
> +
>  	/* The CEC module handles HDMI hotplug detection */
> -	cec_np = of_find_compatible_node(np->parent, NULL,
> -					 "mediatek,mt8173-cec");
> +	cec_np = of_parse_phandle(np, "cec", 0);
>  	if (!cec_np) {
>  		dev_err(dev, "Failed to find CEC node\n");
>  		return -EINVAL;
> @@ -1486,8 +1504,14 @@ static int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi,
>  		return PTR_ERR(hdmi->regs);
>  
>  	remote = of_graph_get_remote_node(np, 1, 0);
> -	if (!remote)
> -		return -EINVAL;
> +	if (!remote) {
> +		i2c_np = of_parse_phandle(np, "ddc-i2c-bus", 0);
> +		if (!i2c_np) {
> +			dev_err(dev, "Failed to find ddc-i2c-bus node\n");
> +			return -EINVAL;
> +		}
> +		goto find_ddc_adpt;
> +	}
>  
>  	if (!of_device_is_compatible(remote, "hdmi-connector")) {
>  		hdmi->next_bridge = of_drm_find_bridge(remote);
> @@ -1507,6 +1531,7 @@ static int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi,
>  	}
>  	of_node_put(remote);
>  
> +find_ddc_adpt:
>  	hdmi->ddc_adpt = of_find_i2c_adapter_by_node(i2c_np);
>  	if (!hdmi->ddc_adpt) {
>  		dev_err(dev, "Failed to get ddc i2c adapter by node\n");
> @@ -1575,6 +1600,11 @@ static int mtk_hdmi_audio_hw_params(struct device *dev, void *data,
>  		hdmi_params.aud_i2s_fmt = HDMI_I2S_MODE_I2S_24BIT;
>  		hdmi_params.aud_mclk = HDMI_AUD_MCLK_128FS;
>  		break;
> +	case HDMI_SPDIF:
> +		hdmi_params.aud_codec = HDMI_AUDIO_CODING_TYPE_PCM;
> +		hdmi_params.aud_sampe_size = HDMI_AUDIO_SAMPLE_SIZE_16;
> +		hdmi_params.aud_input_type = HDMI_AUD_INPUT_SPDIF;
> +		break;
>  	default:
>  		dev_err(hdmi->dev, "%s: Invalid DAI format %d\n", __func__,
>  			daifmt->fmt);
> @@ -1650,15 +1680,16 @@ static void mtk_hdmi_register_audio_driver(struct device *dev)
>  		.max_i2s_channels = 2,
>  		.i2s = 1,
>  	};
> -	struct platform_device *pdev;
> -
> -	pdev = platform_device_register_data(dev, HDMI_CODEC_DRV_NAME,
> -					     PLATFORM_DEVID_AUTO, &codec_data,
> -					     sizeof(codec_data));
> -	if (IS_ERR(pdev))
> +	static struct platform_device *pdev;
> +
> +	if (!pdev) {
> +		pdev = platform_device_register_data(dev, HDMI_CODEC_DRV_NAME,
> +						     PLATFORM_DEVID_NONE,
> +						     &codec_data,
> +						     sizeof(codec_data));
> +		DRM_INFO("%s driver bound to HDMI\n", HDMI_CODEC_DRV_NAME);
> +	}
>  		return;
> -
> -	DRM_INFO("%s driver bound to HDMI\n", HDMI_CODEC_DRV_NAME);
>  }
>  
>  static int mtk_drm_hdmi_probe(struct platform_device *pdev)
> @@ -1672,18 +1703,12 @@ static int mtk_drm_hdmi_probe(struct platform_device *pdev)
>  		return -ENOMEM;
>  
>  	hdmi->dev = dev;
> +	mtk_hdmi_register_audio_driver(dev);
>  
>  	ret = mtk_hdmi_dt_parse_pdata(hdmi, pdev);
>  	if (ret)
>  		return ret;
>  
> -	hdmi->phy = devm_phy_get(dev, "hdmi");
> -	if (IS_ERR(hdmi->phy)) {
> -		ret = PTR_ERR(hdmi->phy);
> -		dev_err(dev, "Failed to get HDMI PHY: %d\n", ret);
> -		return ret;
> -	}
> -
>  	platform_set_drvdata(pdev, hdmi);
>  
>  	ret = mtk_hdmi_output_init(hdmi);
> @@ -1692,8 +1717,6 @@ static int mtk_drm_hdmi_probe(struct platform_device *pdev)
>  		return ret;
>  	}
>  
> -	mtk_hdmi_register_audio_driver(dev);
> -
>  	hdmi->bridge.funcs = &mtk_hdmi_bridge_funcs;
>  	hdmi->bridge.of_node = pdev->dev.of_node;
>  	drm_bridge_add(&hdmi->bridge);
> @@ -1704,7 +1727,6 @@ static int mtk_drm_hdmi_probe(struct platform_device *pdev)
>  		goto err_bridge_remove;
>  	}
>  
> -	dev_dbg(dev, "mediatek hdmi probe success\n");
>  	return 0;
>  
>  err_bridge_remove:
> @@ -1773,8 +1795,25 @@ static struct platform_driver * const mtk_hdmi_drivers[] = {
>  
>  static int __init mtk_hdmitx_init(void)
>  {
> -	return platform_register_drivers(mtk_hdmi_drivers,
> -					 ARRAY_SIZE(mtk_hdmi_drivers));
> +	int ret;
> +	int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(mtk_hdmi_drivers); i++) {
> +		ret = platform_driver_register(mtk_hdmi_drivers[i]);
> +		if (ret < 0) {
> +			pr_err("Failed to register %s driver: %d\n",
> +			       mtk_hdmi_drivers[i]->driver.name, ret);
> +			goto err;
> +		}
> +	}
> +
> +	return 0;
> +
> +err:
> +	while (--i >= 0)
> +		platform_driver_unregister(mtk_hdmi_drivers[i]);
> +
> +	return ret;
>  }
>  
>  static void __exit mtk_hdmitx_exit(void)
> diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.h b/drivers/gpu/drm/mediatek/mtk_hdmi.h
> index 6371b3de1ff6..a4546b83329f 100644
> --- a/drivers/gpu/drm/mediatek/mtk_hdmi.h
> +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.h
> @@ -13,11 +13,39 @@
>   */
>  #ifndef _MTK_HDMI_CTRL_H
>  #define _MTK_HDMI_CTRL_H
> +#include <linux/clk.h>
> +#include <linux/clk-provider.h>
> +#include <linux/platform_device.h>
> +#include <linux/phy/phy.h>
> +
> +struct mtk_hdmi_phy_conf {
> +	bool tz_enabled;
> +	const struct clk_ops *hdmi_phy_clk_ops;
> +	const struct phy_ops *hdmi_phy_dev_ops;
> +};
> +
> +struct mtk_hdmi_phy {
> +	void __iomem *regs;
> +	struct device *dev;
> +	struct mtk_hdmi_phy_conf *conf;
> +	struct clk *pll;
> +	struct clk_hw pll_hw;
> +	unsigned long pll_rate;
> +	unsigned char drv_imp_clk;
> +	unsigned char drv_imp_d2;
> +	unsigned char drv_imp_d1;
> +	unsigned char drv_imp_d0;
> +	unsigned int ibias;
> +	unsigned int ibias_up;
> +};
>  
>  struct platform_driver;
>  
>  extern struct platform_driver mtk_cec_driver;
>  extern struct platform_driver mtk_hdmi_ddc_driver;
>  extern struct platform_driver mtk_hdmi_phy_driver;
> +extern struct mtk_hdmi_phy_conf mtk_hdmi_phy_8173_conf;
> +extern struct mtk_hdmi_phy_conf mtk_hdmi_phy_2701_conf;
> +
>  
>  #endif /* _MTK_HDMI_CTRL_H */
> diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi_phy.c b/drivers/gpu/drm/mediatek/mtk_hdmi_phy.c
> new file mode 100644
> index 000000000000..325790abd469
> --- /dev/null
> +++ b/drivers/gpu/drm/mediatek/mtk_hdmi_phy.c
> @@ -0,0 +1,157 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2018 MediaTek Inc.
> + * Author: Jie Qiu <jie.qiu@mediatek.com>
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/clk-provider.h>
> +#include <linux/kernel.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/of_platform.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/delay.h>
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +#include <linux/phy/phy.h>
> +#include "mtk_hdmi.h"
> +
> +static void mtk_hdmi_phy_clk_get_ops(struct mtk_hdmi_phy *hdmi_phy,
> +				     const struct clk_ops **ops)
> +{
> +	if (hdmi_phy && hdmi_phy->conf && hdmi_phy->conf->hdmi_phy_clk_ops)
> +		*ops = hdmi_phy->conf->hdmi_phy_clk_ops;
> +	else
> +		dev_err(hdmi_phy->dev, "Failed to get clk ops of phy\n");
> +}
> +
> +static const struct phy_ops *
> +mtk_hdmi_phy_dev_get_ops(const struct mtk_hdmi_phy *hdmi_phy)
> +{
> +	if (hdmi_phy && hdmi_phy->conf && hdmi_phy->conf->hdmi_phy_dev_ops)
> +		return hdmi_phy->conf->hdmi_phy_dev_ops;
> +	dev_err(hdmi_phy->dev, "Failed to get dev ops of phy\n");
> +		return NULL;
> +}
> +
> +static int mtk_hdmi_phy_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct mtk_hdmi_phy *hdmi_phy;
> +	struct resource *mem;
> +	struct clk *ref_clk;
> +	const char *ref_clk_name;
> +	struct clk_init_data clk_init = {
> +		.num_parents = 1,
> +		.parent_names = (const char * const *)&ref_clk_name,
> +		.flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE,
> +	};
> +
> +	struct phy *phy;
> +	struct phy_provider *phy_provider;
> +	int ret;
> +
> +	hdmi_phy = devm_kzalloc(dev, sizeof(*hdmi_phy), GFP_KERNEL);
> +	if (!hdmi_phy)
> +		return -ENOMEM;
> +
> +	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	hdmi_phy->regs = devm_ioremap_resource(dev, mem);
> +	if (IS_ERR(hdmi_phy->regs)) {
> +		ret = PTR_ERR(hdmi_phy->regs);
> +		dev_err(dev, "Failed to get memory resource: %d\n", ret);
> +		return ret;
> +	}
> +
> +	ref_clk = devm_clk_get(dev, "pll_ref");
> +	if (IS_ERR(ref_clk)) {
> +		ret = PTR_ERR(ref_clk);
> +		dev_err(&pdev->dev, "Failed to get PLL reference clock: %d\n",
> +			ret);
> +		return ret;
> +	}
> +	ref_clk_name = __clk_get_name(ref_clk);
> +
> +	ret = of_property_read_string(dev->of_node, "clock-output-names",
> +				      &clk_init.name);
> +	if (ret < 0) {
> +		dev_err(dev, "Failed to read clock-output-names: %d\n", ret);
> +		return ret;
> +	}
> +
> +	hdmi_phy->dev = dev;
> +	hdmi_phy->conf =
> +		(struct mtk_hdmi_phy_conf *)of_device_get_match_data(dev);
> +	mtk_hdmi_phy_clk_get_ops(hdmi_phy, &clk_init.ops);
> +	hdmi_phy->pll_hw.init = &clk_init;
> +	hdmi_phy->pll = devm_clk_register(dev, &hdmi_phy->pll_hw);
> +	if (IS_ERR(hdmi_phy->pll)) {
> +		ret = PTR_ERR(hdmi_phy->pll);
> +		dev_err(dev, "Failed to register PLL: %d\n", ret);
> +		return ret;
> +	}
> +
> +	ret = of_property_read_u32(dev->of_node, "mediatek,ibias",
> +				   &hdmi_phy->ibias);
> +	if (ret < 0) {
> +		dev_err(&pdev->dev, "Failed to get ibias: %d\n", ret);
> +		return ret;
> +	}
> +
> +	ret = of_property_read_u32(dev->of_node, "mediatek,ibias_up",
> +				   &hdmi_phy->ibias_up);
> +	if (ret < 0) {
> +		dev_err(&pdev->dev, "Failed to get ibias up: %d\n", ret);
> +		return ret;
> +	}
> +
> +	dev_info(dev, "Using default TX DRV impedance: 4.2k/36\n");
> +	hdmi_phy->drv_imp_clk = 0x30;
> +	hdmi_phy->drv_imp_d2 = 0x30;
> +	hdmi_phy->drv_imp_d1 = 0x30;
> +	hdmi_phy->drv_imp_d0 = 0x30;
> +
> +	phy = devm_phy_create(dev, NULL, mtk_hdmi_phy_dev_get_ops(hdmi_phy));
> +	if (IS_ERR(phy)) {
> +		dev_err(dev, "Failed to create HDMI PHY\n");
> +		return PTR_ERR(phy);
> +	}
> +	phy_set_drvdata(phy, hdmi_phy);
> +
> +	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
> +	if (IS_ERR(phy_provider)) {
> +		dev_err(dev, "Failed to register HDMI PHY\n");
> +		return PTR_ERR(phy_provider);
> +	}
> +
> +	return of_clk_add_provider(dev->of_node, of_clk_src_simple_get,
> +				   hdmi_phy->pll);
> +}
> +
> +static int mtk_hdmi_phy_remove(struct platform_device *pdev)
> +{
> +	return 0;
> +}
> +
> +static const struct of_device_id mtk_hdmi_phy_match[] = {
> +	{ .compatible = "mediatek,mt2701-hdmi-phy",
> +	  .data = &mtk_hdmi_phy_2701_conf,
> +	},
> +	{ .compatible = "mediatek,mt8173-hdmi-phy",
> +	  .data = &mtk_hdmi_phy_8173_conf,
> +	},
> +	{},
> +};
> +
> +struct platform_driver mtk_hdmi_phy_driver = {
> +	.probe = mtk_hdmi_phy_probe,
> +	.remove = mtk_hdmi_phy_remove,
> +	.driver = {
> +		.name = "mediatek-hdmi-phy",
> +		.of_match_table = mtk_hdmi_phy_match,
> +	},
> +};
> +
> +MODULE_DESCRIPTION("MediaTek HDMI PHY Driver");
> +MODULE_LICENSE("GPL v2");
> diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi_regs.h b/drivers/gpu/drm/mediatek/mtk_hdmi_regs.h
> index a5cb07d12c9c..e53c6646571c 100644
> --- a/drivers/gpu/drm/mediatek/mtk_hdmi_regs.h
> +++ b/drivers/gpu/drm/mediatek/mtk_hdmi_regs.h
> @@ -227,6 +227,7 @@
>  #define DEEP_COLOR_EN			BIT(0)
>  #define HDMI_AUDIO_TEST_SEL		BIT(8)
>  #define HDMI2P0_EN			BIT(11)
> +#define HDMI_PSECUR_EN			BIT(15)
>  #define HDMI_OUT_FIFO_EN		BIT(16)
>  #define HDMI_OUT_FIFO_CLK_INV		BIT(17)
>  #define MHL_MODE_ON			BIT(28)
> diff --git a/drivers/gpu/drm/mediatek/mtk_mt2701_hdmi_phy.c b/drivers/gpu/drm/mediatek/mtk_mt2701_hdmi_phy.c
> new file mode 100644
> index 000000000000..8af5e6c1aecc
> --- /dev/null
> +++ b/drivers/gpu/drm/mediatek/mtk_mt2701_hdmi_phy.c
> @@ -0,0 +1,307 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + *Copyright (c) 2018 MediaTek Inc.
> + *Author: Chunhui Dai <chunhui.dai@mediatek.com>
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/clk-provider.h>
> +#include <linux/debugfs.h>
> +#include <linux/kernel.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/of_platform.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/delay.h>
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +#include <linux/phy/phy.h>
> +#include "mtk_hdmi.h"
> +
> +#define HDMI_CON0	0x00
> +#define RG_HDMITX_DRV_IBIAS		(0)
> +#define RG_HDMITX_DRV_IBIAS_MASK	(0x3F << 0)
> +#define RG_HDMITX_EN_SER		(12)
> +#define RG_HDMITX_EN_SER_MASK		(0x0F << 12)
> +#define RG_HDMITX_EN_SLDO		(16)
> +#define RG_HDMITX_EN_SLDO_MASK		(0x0F << 16)
> +#define RG_HDMITX_EN_PRED		(20)
> +#define RG_HDMITX_EN_PRED_MASK		(0x0F << 20)
> +#define RG_HDMITX_EN_IMP		(24)
> +#define RG_HDMITX_EN_IMP_MASK		(0x0F << 24)
> +#define RG_HDMITX_EN_DRV		(28)
> +#define RG_HDMITX_EN_DRV_MASK		(0x0F << 28)
> +
> +#define HDMI_CON1	0x04
> +#define RG_HDMITX_PRED_IBIAS		(18)
> +#define RG_HDMITX_PRED_IBIAS_MASK	(0x0F << 18)
> +#define RG_HDMITX_PRED_IMP		(0x01 << 22)
> +#define RG_HDMITX_DRV_IMP		(26)
> +#define RG_HDMITX_DRV_IMP_MASK		(0x3F << 26)
> +
> +#define HDMI_CON2	0x08
> +#define RG_HDMITX_EN_TX_CKLDO		(0x01 << 0)
> +#define RG_HDMITX_EN_TX_POSDIV		(0x01 << 1)
> +#define RG_HDMITX_TX_POSDIV		(3)
> +#define RG_HDMITX_TX_POSDIV_MASK	(0x03 << 3)
> +#define RG_HDMITX_EN_MBIAS		(0x01 << 6)
> +#define RG_HDMITX_MBIAS_LPF_EN		(0x01 << 7)
> +
> +#define HDMI_CON4	0x10
> +#define RG_HDMITX_RESERVE_MASK		(0xFFFFFFFF << 0)
> +
> +#define HDMI_CON6	0x18
> +#define RG_HTPLL_BR			(0)
> +#define RG_HTPLL_BR_MASK		(0x03 << 0)
> +#define RG_HTPLL_BC			(2)
> +#define RG_HTPLL_BC_MASK		(0x03 << 2)
> +#define RG_HTPLL_BP			(4)
> +#define RG_HTPLL_BP_MASK		(0x0F << 4)
> +#define RG_HTPLL_IR			(8)
> +#define RG_HTPLL_IR_MASK		(0x0F << 8)
> +#define RG_HTPLL_IC			(12)
> +#define RG_HTPLL_IC_MASK		(0x0F << 12)
> +#define RG_HTPLL_POSDIV			(16)
> +#define RG_HTPLL_POSDIV_MASK		(0x03 << 16)
> +#define RG_HTPLL_PREDIV			(18)
> +#define RG_HTPLL_PREDIV_MASK		(0x03 << 18)
> +#define RG_HTPLL_FBKSEL			(20)
> +#define RG_HTPLL_FBKSEL_MASK		(0x03 << 20)
> +#define RG_HTPLL_RLH_EN			(0x01 << 22)
> +#define RG_HTPLL_FBKDIV			(24)
> +#define RG_HTPLL_FBKDIV_MASK		(0x7F << 24)
> +#define RG_HTPLL_EN			(0x01 << 31)
> +
> +#define HDMI_CON7	0x1c
> +#define RG_HTPLL_AUTOK_EN		(0x01 << 23)
> +#define RG_HTPLL_DIVEN			(28)
> +#define RG_HTPLL_DIVEN_MASK		(0x07 << 28)
> +
> +static inline struct mtk_hdmi_phy *to_mtk_hdmi_pll(struct clk_hw *hw)
> +{
> +	return container_of(hw, struct mtk_hdmi_phy, pll_hw);
> +}
> +
> +static inline void mtk_hdmi_pll_mask(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
> +				     u32 val, u32 mask)
> +{
> +	u32 tmp = readl(hdmi_phy->regs  + offset) & ~mask;
> +
> +	tmp |= (val & mask);
> +	writel(tmp, hdmi_phy->regs + offset);
> +}
> +
> +static int mtk_hdmi_pll_enable(struct clk_hw *hw)
> +{
> +	struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_pll(hw);
> +
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON7, RG_HTPLL_AUTOK_EN,
> +			  RG_HTPLL_AUTOK_EN);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON6, 0, RG_HTPLL_RLH_EN);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON6, (0x3 << RG_HTPLL_POSDIV),
> +			  RG_HTPLL_POSDIV_MASK);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_MBIAS,
> +			  RG_HDMITX_EN_MBIAS);
> +	usleep_range(80, 100);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON6, RG_HTPLL_EN, RG_HTPLL_EN);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_CKLDO,
> +			  RG_HDMITX_EN_TX_CKLDO);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON0, (0xf << RG_HDMITX_EN_SLDO),
> +			  RG_HDMITX_EN_SLDO_MASK);
> +	usleep_range(80, 100);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON2, RG_HDMITX_MBIAS_LPF_EN,
> +			  RG_HDMITX_MBIAS_LPF_EN);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_POSDIV,
> +			  RG_HDMITX_EN_TX_POSDIV);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON0, (0xf << RG_HDMITX_EN_SER),
> +			  RG_HDMITX_EN_SER_MASK);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON0, (0xf << RG_HDMITX_EN_PRED),
> +			  RG_HDMITX_EN_PRED_MASK);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON0, (0xf << RG_HDMITX_EN_DRV),
> +			  RG_HDMITX_EN_DRV_MASK);
> +	usleep_range(80, 100);
> +	return 0;
> +}
> +
> +static void mtk_hdmi_pll_disable(struct clk_hw *hw)
> +{
> +	struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_pll(hw);
> +
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON0, 0, RG_HDMITX_EN_DRV_MASK);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON0, 0, RG_HDMITX_EN_PRED_MASK);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON0, 0, RG_HDMITX_EN_SER_MASK);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON2, 0, RG_HDMITX_EN_TX_POSDIV);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON2, 0, RG_HDMITX_MBIAS_LPF_EN);
> +	usleep_range(80, 100);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON0, 0, RG_HDMITX_EN_SLDO_MASK);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON2, 0, RG_HDMITX_EN_TX_CKLDO);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON6, 0, RG_HTPLL_EN);
> +	usleep_range(80, 100);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON2, 0, RG_HDMITX_EN_MBIAS);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON6, 0, RG_HTPLL_POSDIV_MASK);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON6, 0, RG_HTPLL_RLH_EN);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON7, 0, RG_HTPLL_AUTOK_EN);
> +	usleep_range(80, 100);
> +}
> +
> +static int mtk_hdmi_pll_set_rate(struct clk_hw *hw, unsigned long rate,
> +				 unsigned long parent_rate)
> +{
> +	struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_pll(hw);
> +	u32 pos_div;
> +
> +	if (rate <= 64000000)
> +		pos_div = 3;
> +	else if (rate <= 12800000)
> +		pos_div = 1;
> +	else
> +		pos_div = 1;
> +
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON6, (0x3 << RG_HTPLL_PREDIV),
> +			  RG_HTPLL_PREDIV_MASK);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON6, (0x3 << RG_HTPLL_POSDIV),
> +			  RG_HTPLL_POSDIV_MASK);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON6, (0x1 << RG_HTPLL_IC),
> +			  RG_HTPLL_IC_MASK);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON6, (0x1 << RG_HTPLL_IR),
> +			  RG_HTPLL_IR_MASK);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON2, (pos_div << RG_HDMITX_TX_POSDIV),
> +			  RG_HDMITX_TX_POSDIV_MASK);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON6, (1 << RG_HTPLL_FBKSEL),
> +			  RG_HTPLL_FBKSEL_MASK);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON6, (19 << RG_HTPLL_FBKDIV),
> +			  RG_HTPLL_FBKDIV_MASK);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON7, (0x2 << RG_HTPLL_DIVEN),
> +			  RG_HTPLL_DIVEN_MASK);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON6, (0xc << RG_HTPLL_BP),
> +			  RG_HTPLL_BP_MASK);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON6, (0x2 << RG_HTPLL_BC),
> +			  RG_HTPLL_BC_MASK);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON6, (0x1 << RG_HTPLL_BR),
> +			  RG_HTPLL_BR_MASK);
> +
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON1, 0, RG_HDMITX_PRED_IMP);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON1, (0x3 << RG_HDMITX_PRED_IBIAS),
> +			  RG_HDMITX_PRED_IBIAS_MASK);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON0, (0x0 << RG_HDMITX_EN_IMP),
> +			  RG_HDMITX_EN_IMP_MASK);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON1, (0x28 << RG_HDMITX_DRV_IMP),
> +			  RG_HDMITX_DRV_IMP_MASK);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON4, 0x28, RG_HDMITX_RESERVE_MASK);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON0, (0xa << RG_HDMITX_DRV_IBIAS),
> +			  RG_HDMITX_DRV_IBIAS_MASK);
> +	return 0;
> +}
> +
> +static long mtk_hdmi_pll_round_rate(struct clk_hw *hw, unsigned long rate,
> +				    unsigned long *parent_rate)
> +{
> +	struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_pll(hw);
> +
> +	hdmi_phy->pll_rate = rate;
> +	return rate;
> +}
> +
> +static unsigned long mtk_hdmi_pll_recalc_rate(struct clk_hw *hw,
> +					      unsigned long parent_rate)
> +{
> +	struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_pll(hw);
> +
> +	return hdmi_phy->pll_rate;
> +}
> +
> +static const struct clk_ops mtk_hdmi_phy_pll_ops = {
> +	.enable = mtk_hdmi_pll_enable,
> +	.disable = mtk_hdmi_pll_disable,
> +	.set_rate = mtk_hdmi_pll_set_rate,
> +	.round_rate = mtk_hdmi_pll_round_rate,
> +	.recalc_rate = mtk_hdmi_pll_recalc_rate,
> +};
> +
> +static void mtk_hdmi_phy_enable_tmds(struct mtk_hdmi_phy *hdmi_phy)
> +{
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON7, RG_HTPLL_AUTOK_EN,
> +			  RG_HTPLL_AUTOK_EN);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON6, 0, RG_HTPLL_RLH_EN);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON6, (0x3 << RG_HTPLL_POSDIV),
> +			  RG_HTPLL_POSDIV_MASK);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_MBIAS,
> +			  RG_HDMITX_EN_MBIAS);
> +	usleep_range(80, 100);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON6, RG_HTPLL_EN, RG_HTPLL_EN);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_CKLDO,
> +			  RG_HDMITX_EN_TX_CKLDO);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON0, (0xf << RG_HDMITX_EN_SLDO),
> +			  RG_HDMITX_EN_SLDO_MASK);
> +	usleep_range(80, 100);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON2, RG_HDMITX_MBIAS_LPF_EN,
> +			  RG_HDMITX_MBIAS_LPF_EN);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_POSDIV,
> +			  RG_HDMITX_EN_TX_POSDIV);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON0, (0xf << RG_HDMITX_EN_SER),
> +			  RG_HDMITX_EN_SER_MASK);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON0, (0xf << RG_HDMITX_EN_PRED),
> +			  RG_HDMITX_EN_PRED_MASK);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON0, (0xf << RG_HDMITX_EN_DRV),
> +			  RG_HDMITX_EN_DRV_MASK);
> +	usleep_range(80, 100);
> +}
> +
> +static void mtk_hdmi_phy_disable_tmds(struct mtk_hdmi_phy *hdmi_phy)
> +{
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON0, 0, RG_HDMITX_EN_DRV_MASK);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON0, 0, RG_HDMITX_EN_PRED_MASK);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON0, 0, RG_HDMITX_EN_SER_MASK);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON2, 0, RG_HDMITX_EN_TX_POSDIV);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON2, 0, RG_HDMITX_MBIAS_LPF_EN);
> +	usleep_range(80, 100);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON0, 0, RG_HDMITX_EN_SLDO_MASK);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON2, 0, RG_HDMITX_EN_TX_CKLDO);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON6, 0, RG_HTPLL_EN);
> +	usleep_range(80, 100);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON2, 0, RG_HDMITX_EN_MBIAS);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON6, 0, RG_HTPLL_POSDIV_MASK);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON6, 0, RG_HTPLL_RLH_EN);
> +	mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON7, 0, RG_HTPLL_AUTOK_EN);
> +	usleep_range(80, 100);
> +}
> +
> +static int mtk_hdmi_phy_power_on(struct phy *phy)
> +{
> +	struct mtk_hdmi_phy *hdmi_phy = phy_get_drvdata(phy);
> +	int ret;
> +
> +	ret = clk_prepare_enable(hdmi_phy->pll);
> +	if (ret < 0)
> +		return ret;
> +
> +	mtk_hdmi_phy_enable_tmds(hdmi_phy);
> +
> +	return 0;
> +}
> +
> +static int mtk_hdmi_phy_power_off(struct phy *phy)
> +{
> +	struct mtk_hdmi_phy *hdmi_phy = phy_get_drvdata(phy);
> +
> +	mtk_hdmi_phy_disable_tmds(hdmi_phy);
> +	clk_disable_unprepare(hdmi_phy->pll);
> +
> +	return 0;
> +}
> +
> +static const struct phy_ops mtk_hdmi_phy_dev_ops = {
> +	.power_on = mtk_hdmi_phy_power_on,
> +	.power_off = mtk_hdmi_phy_power_off,
> +	.owner = THIS_MODULE,
> +};
> +
> +struct mtk_hdmi_phy_conf mtk_hdmi_phy_2701_conf = {
> +	.tz_enabled = false,
> +	.hdmi_phy_clk_ops = &mtk_hdmi_phy_pll_ops,
> +	.hdmi_phy_dev_ops = &mtk_hdmi_phy_dev_ops,
> +};
> +
> +MODULE_AUTHOR("Chunhui Dai <chunhui.dai@mediatek.com>");
> +MODULE_DESCRIPTION("MediaTek HDMI PHY Driver");
> +MODULE_LICENSE("GPL v2");
> diff --git a/drivers/gpu/drm/mediatek/mtk_mt8173_hdmi_phy.c b/drivers/gpu/drm/mediatek/mtk_mt8173_hdmi_phy.c
> index 51cb9cfb6646..1a35fdd405d8 100644
> --- a/drivers/gpu/drm/mediatek/mtk_mt8173_hdmi_phy.c
> +++ b/drivers/gpu/drm/mediatek/mtk_mt8173_hdmi_phy.c
> @@ -21,6 +21,7 @@
>  #include <linux/phy/phy.h>
>  #include <linux/platform_device.h>
>  #include <linux/types.h>
> +#include "mtk_hdmi.h"
>  
>  #define HDMI_CON0		0x00
>  #define RG_HDMITX_PLL_EN		BIT(31)
> @@ -123,20 +124,6 @@
>  #define RGS_HDMITX_5T1_EDG		(0xf << 4)
>  #define RGS_HDMITX_PLUG_TST		BIT(0)
>  
> -struct mtk_hdmi_phy {
> -	void __iomem *regs;
> -	struct device *dev;
> -	struct clk *pll;
> -	struct clk_hw pll_hw;
> -	unsigned long pll_rate;
> -	u8 drv_imp_clk;
> -	u8 drv_imp_d2;
> -	u8 drv_imp_d1;
> -	u8 drv_imp_d0;
> -	u32 ibias;
> -	u32 ibias_up;
> -};
> -
>  static const u8 PREDIV[3][4] = {
>  	{0x0, 0x0, 0x0, 0x0},	/* 27Mhz */
>  	{0x1, 0x1, 0x1, 0x1},	/* 74Mhz */
> @@ -367,7 +354,7 @@ static unsigned long mtk_hdmi_pll_recalc_rate(struct clk_hw *hw,
>  	return hdmi_phy->pll_rate;
>  }
>  
> -static const struct clk_ops mtk_hdmi_pll_ops = {
> +static const struct clk_ops mtk_hdmi_phy_pll_ops = {
>  	.prepare = mtk_hdmi_pll_prepare,
>  	.unprepare = mtk_hdmi_pll_unprepare,
>  	.set_rate = mtk_hdmi_pll_set_rate,
> @@ -414,118 +401,16 @@ static int mtk_hdmi_phy_power_off(struct phy *phy)
>  	return 0;
>  }
>  
> -static const struct phy_ops mtk_hdmi_phy_ops = {
> +static const struct phy_ops mtk_hdmi_phy_dev_ops = {
>  	.power_on = mtk_hdmi_phy_power_on,
>  	.power_off = mtk_hdmi_phy_power_off,
>  	.owner = THIS_MODULE,
>  };
>  
> -static int mtk_hdmi_phy_probe(struct platform_device *pdev)
> -{
> -	struct device *dev = &pdev->dev;
> -	struct mtk_hdmi_phy *hdmi_phy;
> -	struct resource *mem;
> -	struct clk *ref_clk;
> -	const char *ref_clk_name;
> -	struct clk_init_data clk_init = {
> -		.ops = &mtk_hdmi_pll_ops,
> -		.num_parents = 1,
> -		.parent_names = (const char * const *)&ref_clk_name,
> -		.flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE,
> -	};
> -	struct phy *phy;
> -	struct phy_provider *phy_provider;
> -	int ret;
> -
> -	hdmi_phy = devm_kzalloc(dev, sizeof(*hdmi_phy), GFP_KERNEL);
> -	if (!hdmi_phy)
> -		return -ENOMEM;
> -
> -	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> -	hdmi_phy->regs = devm_ioremap_resource(dev, mem);
> -	if (IS_ERR(hdmi_phy->regs)) {
> -		ret = PTR_ERR(hdmi_phy->regs);
> -		dev_err(dev, "Failed to get memory resource: %d\n", ret);
> -		return ret;
> -	}
> -
> -	ref_clk = devm_clk_get(dev, "pll_ref");
> -	if (IS_ERR(ref_clk)) {
> -		ret = PTR_ERR(ref_clk);
> -		dev_err(&pdev->dev, "Failed to get PLL reference clock: %d\n",
> -			ret);
> -		return ret;
> -	}
> -	ref_clk_name = __clk_get_name(ref_clk);
> -
> -	ret = of_property_read_string(dev->of_node, "clock-output-names",
> -				      &clk_init.name);
> -	if (ret < 0) {
> -		dev_err(dev, "Failed to read clock-output-names: %d\n", ret);
> -		return ret;
> -	}
> -
> -	hdmi_phy->pll_hw.init = &clk_init;
> -	hdmi_phy->pll = devm_clk_register(dev, &hdmi_phy->pll_hw);
> -	if (IS_ERR(hdmi_phy->pll)) {
> -		ret = PTR_ERR(hdmi_phy->pll);
> -		dev_err(dev, "Failed to register PLL: %d\n", ret);
> -		return ret;
> -	}
> -
> -	ret = of_property_read_u32(dev->of_node, "mediatek,ibias",
> -				   &hdmi_phy->ibias);
> -	if (ret < 0) {
> -		dev_err(&pdev->dev, "Failed to get ibias: %d\n", ret);
> -		return ret;
> -	}
> -
> -	ret = of_property_read_u32(dev->of_node, "mediatek,ibias_up",
> -				   &hdmi_phy->ibias_up);
> -	if (ret < 0) {
> -		dev_err(&pdev->dev, "Failed to get ibias up: %d\n", ret);
> -		return ret;
> -	}
> -
> -	dev_info(dev, "Using default TX DRV impedance: 4.2k/36\n");
> -	hdmi_phy->drv_imp_clk = 0x30;
> -	hdmi_phy->drv_imp_d2 = 0x30;
> -	hdmi_phy->drv_imp_d1 = 0x30;
> -	hdmi_phy->drv_imp_d0 = 0x30;
> -
> -	phy = devm_phy_create(dev, NULL, &mtk_hdmi_phy_ops);
> -	if (IS_ERR(phy)) {
> -		dev_err(dev, "Failed to create HDMI PHY\n");
> -		return PTR_ERR(phy);
> -	}
> -	phy_set_drvdata(phy, hdmi_phy);
> -
> -	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
> -	if (IS_ERR(phy_provider))
> -		return PTR_ERR(phy_provider);
> -
> -	hdmi_phy->dev = dev;
> -	return of_clk_add_provider(dev->of_node, of_clk_src_simple_get,
> -				   hdmi_phy->pll);
> -}
> -
> -static int mtk_hdmi_phy_remove(struct platform_device *pdev)
> -{
> -	return 0;
> -}
> -
> -static const struct of_device_id mtk_hdmi_phy_match[] = {
> -	{ .compatible = "mediatek,mt8173-hdmi-phy", },
> -	{},
> -};
> -
> -struct platform_driver mtk_hdmi_phy_driver = {
> -	.probe = mtk_hdmi_phy_probe,
> -	.remove = mtk_hdmi_phy_remove,
> -	.driver = {
> -		.name = "mediatek-hdmi-phy",
> -		.of_match_table = mtk_hdmi_phy_match,
> -	},
> +struct mtk_hdmi_phy_conf mtk_hdmi_phy_8173_conf = {
> +	.tz_enabled = true,
> +	.hdmi_phy_clk_ops = &mtk_hdmi_phy_pll_ops,
> +	.hdmi_phy_dev_ops = &mtk_hdmi_phy_dev_ops,
>  };
>  
>  MODULE_AUTHOR("Jie Qiu <jie.qiu@mediatek.com>");

^ permalink raw reply

* [PATCH v1 7/7] drm/mediatek: config component output by device node port
From: CK Hu @ 2018-05-28  8:38 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180514075243.5442-8-bibby.hsieh@mediatek.com>

Hi, Bibby:

On Mon, 2018-05-14 at 15:52 +0800, Bibby Hsieh wrote:
> We can select output component by device node port.
> Main path default output component is DSI.
> External path default output component is DPI.

Config the HW routine by device tree is a good idea. But I would like
this to be more general. My idea is:
1. Each component has one or two endpoint in device tree. The first and
the last has one, and the others has two.
2. Remove mtxxxx_mtk_ddp_main[] and mtxxxx_mtk_ddp_ext[], use multiple
link list (One display path has one link list, two display path has two
link list) to generate it by parsing device tree in mtk_drm_probe().

Stu has planed to do this in future. You could wait him or you could do
this first.

Regards,
CK

> 
> Signed-off-by: Bibby Hsieh <bibby.hsieh@mediatek.com>
> ---
>  drivers/gpu/drm/mediatek/mtk_drm_drv.c | 37 ++++++++++++++++++++++++++++++----
>  drivers/gpu/drm/mediatek/mtk_drm_drv.h |  4 ++--
>  2 files changed, 35 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> index f4fb86ab7b8d..05333769d862 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> @@ -24,6 +24,8 @@
>  #include <linux/of_address.h>
>  #include <linux/of_platform.h>
>  #include <linux/pm_runtime.h>
> +#include <linux/of.h>
> +#include <linux/of_graph.h>
>  
>  #include "mtk_drm_crtc.h"
>  #include "mtk_drm_ddp.h"
> @@ -133,7 +135,7 @@ static const struct drm_mode_config_funcs mtk_drm_mode_config_funcs = {
>  	.atomic_commit = mtk_atomic_commit,
>  };
>  
> -static const enum mtk_ddp_comp_id mt2701_mtk_ddp_main[] = {
> +static enum mtk_ddp_comp_id mt2701_mtk_ddp_main[] = {
>  	DDP_COMPONENT_OVL0,
>  	DDP_COMPONENT_RDMA0,
>  	DDP_COMPONENT_COLOR0,
> @@ -141,12 +143,12 @@ static const enum mtk_ddp_comp_id mt2701_mtk_ddp_main[] = {
>  	DDP_COMPONENT_DSI0,
>  };
>  
> -static const enum mtk_ddp_comp_id mt2701_mtk_ddp_ext[] = {
> +static enum mtk_ddp_comp_id mt2701_mtk_ddp_ext[] = {
>  	DDP_COMPONENT_RDMA1,
>  	DDP_COMPONENT_DPI0,
>  };
>  
> -static const enum mtk_ddp_comp_id mt8173_mtk_ddp_main[] = {
> +static enum mtk_ddp_comp_id mt8173_mtk_ddp_main[] = {
>  	DDP_COMPONENT_OVL0,
>  	DDP_COMPONENT_COLOR0,
>  	DDP_COMPONENT_AAL,
> @@ -157,7 +159,7 @@ static const enum mtk_ddp_comp_id mt8173_mtk_ddp_main[] = {
>  	DDP_COMPONENT_PWM0,
>  };
>  
> -static const enum mtk_ddp_comp_id mt8173_mtk_ddp_ext[] = {
> +static enum mtk_ddp_comp_id mt8173_mtk_ddp_ext[] = {
>  	DDP_COMPONENT_OVL1,
>  	DDP_COMPONENT_COLOR1,
>  	DDP_COMPONENT_GAMMA,
> @@ -411,6 +413,7 @@ static int mtk_drm_probe(struct platform_device *pdev)
>  
>  	/* Iterate over sibling DISP function blocks */
>  	for_each_child_of_node(dev->of_node->parent, node) {
> +		struct device_node *port, *ep, *remote;
>  		const struct of_device_id *of_id;
>  		enum mtk_ddp_comp_type comp_type;
>  		int comp_id;
> @@ -470,6 +473,32 @@ static int mtk_drm_probe(struct platform_device *pdev)
>  
>  			private->ddp_comp[comp_id] = comp;
>  		}
> +
> +		if (comp_type != MTK_DSI && comp_type != MTK_DPI) {
> +			port = of_graph_get_port_by_id(node, 0);
> +			if (!port)
> +				continue;
> +			ep = of_get_child_by_name(port, "endpoint");
> +			of_node_put(port);
> +			if (!ep)
> +				continue;
> +			remote = of_graph_get_remote_port_parent(ep);
> +			of_node_put(ep);
> +			if (!remote)
> +				continue;
> +			of_id = of_match_node(mtk_ddp_comp_dt_ids, remote);
> +			if (!of_id)
> +				continue;
> +			comp_type = (enum mtk_ddp_comp_type)of_id->data;
> +			for (i = 0; i < private->data->main_len - 1; i++)
> +				if (private->data->main_path[i] == comp_id)
> +					private->data->main_path[i + 1] =
> +					mtk_ddp_comp_get_id(node, comp_type);
> +			for (i = 0; i < private->data->ext_len - 1; i++)
> +				if (private->data->ext_path[i] == comp_id)
> +					private->data->ext_path[i + 1] =
> +					mtk_ddp_comp_get_id(node, comp_type);
> +		}
>  	}
>  
>  	if (!private->mutex_node) {
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
> index c3378c452c0a..2bcba8eb06f4 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
> @@ -29,9 +29,9 @@ struct drm_property;
>  struct regmap;
>  
>  struct mtk_mmsys_driver_data {
> -	const enum mtk_ddp_comp_id *main_path;
> +	enum mtk_ddp_comp_id *main_path;
>  	unsigned int main_len;
> -	const enum mtk_ddp_comp_id *ext_path;
> +	enum mtk_ddp_comp_id *ext_path;
>  	unsigned int ext_len;
>  	bool shadow_register;
>  };

^ permalink raw reply

* [PATCH] arm: cntvoff: Add a function definition when !SMP
From: Maxime Ripard @ 2018-05-28  8:40 UTC (permalink / raw)
  To: linux-arm-kernel

The secure_cntvoff_init function is only compiled if CONFIG_SMP is set to
true. However, that will lead to linking errors if one uses this function
without an ifdef CONFIG_SMP guard, which isn't ideal.

Provide a dumb implementation when CONFIG_SMP is false so that we don't end
up with a compilation error on our hands.

Cc: Olof Johansson <olof@lixom.net>
Cc: Myl?ne Josserand <mylene.josserand@bootlin.com>
Cc: Simon Horman <horms@verge.net.au>
Cc: Magnus Damm <magnus.damm@gmail.com>
Fixes: cad160ed0a94 ("ARM: shmobile: Convert file to use cntvoff")
Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
---
 arch/arm/include/asm/secure_cntvoff.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm/include/asm/secure_cntvoff.h b/arch/arm/include/asm/secure_cntvoff.h
index 1f93aee1f630..ce96cd781838 100644
--- a/arch/arm/include/asm/secure_cntvoff.h
+++ b/arch/arm/include/asm/secure_cntvoff.h
@@ -3,6 +3,10 @@
 #ifndef __ASMARM_ARCH_CNTVOFF_H
 #define __ASMARM_ARCH_CNTVOFF_H
 
+#ifdef CONFIG_SMP
 extern void secure_cntvoff_init(void);
+#else
+static inline void secure_cntvoff_init(void) {};
+#endif
 
 #endif
-- 
2.17.0

^ permalink raw reply related

* [PATCH 1/9] ARM: shmobile: defconfig: Enable MTD command line partition parsing
From: Simon Horman @ 2018-05-28  8:40 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180522120257.13232-1-marek.vasut+renesas@gmail.com>

On Tue, May 22, 2018 at 02:02:49PM +0200, Marek Vasut wrote:
> In preparation for removing MTD partitioning from the DTs and moving
> it over to kernel command line partition parsing, enable the support
> for kernel command line MTD partition parsing.
> 
> The argument for not having MTD partitions in the DT is the same as
> for not having hard drive partitions in DT, neither describes the
> hardware itself, so it shouldn't be in the DT. Furthermore, kernel
> command line MTD partition passing allows greater flexibility in
> case someone decided to repartition the flash, which is well in the
> realm of possibility with these systems.
> 
> Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>

Thanks, applied.

^ permalink raw reply

* [PATCH 6/9] ARM: dts: wheat: Drop MTD partitioning from DT
From: Simon Horman @ 2018-05-28  8:41 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <7e1563c3-3e13-235b-3071-c3936502530f@gmail.com>

On Thu, May 24, 2018 at 04:52:59PM +0200, Marek Vasut wrote:
> On 05/23/2018 08:25 AM, Geert Uytterhoeven wrote:
> > Hi Marek,
> > 
> > On Wed, May 23, 2018 at 12:01 AM, Marek Vasut <marek.vasut@gmail.com> wrote:
> >> On 05/22/2018 04:43 PM, Geert Uytterhoeven wrote:
> >>> On Tue, May 22, 2018 at 2:02 PM, Marek Vasut <marek.vasut@gmail.com> wrote:
> >>>> Drop the MTD partitioning from DT, since it does not describe HW
> >>>> and to give way to a more flexible kernel command line partition
> >>>> passing.
> >>>>
> >>>> To retain the original partitioning, assure you have enabled
> >>>> CONFIG_MTD_CMDLINE_PARTS in your kernel config and add the
> >>>> following to your kernel command line:
> >>>>
> >>>>   mtdparts=spi0.0:256k at 0(loader),4096k(user),-(flash)
> >>>
> >>> I think the "@0" can be dropped, as it's optional?
> >>> 4m?
> >>
> >> My take on this is that the loader is actually at offset 0x0 of the MTD
> >> device and we explicitly state that in the mtdparts to anchor the first
> >> partition within the MTD device and all the other partitions are at
> >> offset +(sum of the sizes of all partitions listed before the current
> >> one) relative to that first partition.
> > 
> > Where is this explicitly states for the first partition?
> > 
> >> Removing the @0 feels fragile at best and it seems to depend on the
> >> current behavior of the code.
> > 
> > Better, it also depends on the documented behavior:
> > 
> > Documentation/admin-guide/kernel-parameters.txt refers to
> > drivers/mtd/cmdlinepart.c, which states:
> > 
> >  * <offset>  := standard linux memsize
> >  *              if omitted the part will immediately follow the previous part
> >  *              or 0 if the first part
> > 
> > None of the examples listed there or under the MTD_CMDLINE_PARTS Kconfig
> > help text, or in a defconfig bundled with the kernel, use @0 for the first
> > partition.
> 
> I think this is exceptionally fragile and dangerous to depend on this,
> but so be it.

Could you respin with this change?

I would also like to ask for another change, in light of recent
feedback from Olof Johansson ("Re: [GIT PULL] Renesas ARM64 Based SoC DT
Updates for v4.18").

Please consolidate the dts patches into a single patch?

I have applied the defconfig patch, so there is no need to repost that one.

^ permalink raw reply

* About the DRM Mediatek patches
From: Bibby Hsieh @ 2018-05-28  8:43 UTC (permalink / raw)
  To: linux-arm-kernel

Hi, Ulrich,

I found two DRM-Mediatek related patches as below from you.
https://patchwork.kernel.org/patch/10009039/
https://patchwork.kernel.org/patch/10009049/

Did you have any plans to send the new version (There are some comments
from Philipp)? If not, may I send the new version?

Thanks.

-- 
Bibby

^ permalink raw reply

* [PATCH 06/15] arm: dts: sun: Add missing cooling device properties for CPUs
From: Maxime Ripard @ 2018-05-28  8:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <eded393f4b508a1f377f9af6859a3b82a6787e1c.1527244201.git.viresh.kumar@linaro.org>

Hi,

On Fri, May 25, 2018 at 04:01:52PM +0530, Viresh Kumar wrote:
> The cooling device properties, like "#cooling-cells" and
> "dynamic-power-coefficient", should either be present for all the CPUs
> of a cluster or none. If these are present only for a subset of CPUs of
> a cluster then things will start falling apart as soon as the CPUs are
> brought online in a different order. For example, this will happen
> because the operating system looks for such properties in the CPU node
> it is trying to bring up, so that it can register a cooling device.
> 
> Add such missing properties.
> 
> Fix other missing properties (clocks, OPP, clock latency) as well to
> make it all work.
> 
> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>

The prefix should be sunxi and not sun, but it looks good to me
otherwise.

Let me know what your preferred merge method is.

Maxime

-- 
Maxime Ripard, Bootlin (formerly Free Electrons)
Embedded Linux and Kernel engineering
https://bootlin.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180528/a2bdcdbe/attachment.sig>

^ permalink raw reply

* [RFT v3 0/4] Perf script: Add python script for CoreSight trace disassembler
From: Leo Yan @ 2018-05-28  8:44 UTC (permalink / raw)
  To: linux-arm-kernel

This patch series is to support for using 'perf script' for CoreSight
trace disassembler, for this purpose this patch series adds a new
python script to parse CoreSight tracing event and use command 'objdump'
for disassembled lines, finally this can generate readable program
execution flow for reviewing tracing data.

Patch 0001 is one fixing patch to generate samples for the start packet
and exception packets.

Patch 0002 is the prerequisite to add addr into sample dict, so this
value can be used by python script to analyze instruction range.

Patch 0003 is to add python script for trace disassembler.

Patch 0004 is to add doc to explain python script usage and give
example for it.

This patch series has been rebased on acme git tree [1] with the commit
19422a9f2a3b ("perf tools: Fix kernel_start for PTI on x86") and tested
on Hikey (ARM64 octa CA53 cores).

In this version the script has no dependency on ARM64 platform and is
expected to support ARM32 platform, but I am lacking ARM32 platform for
testing on it, so firstly upstream to support ARM64 platform.

This patch series is firstly to support 'per-thread' recording tracing
data, but we also need to verify the script can dump trace disassembler
CPU wide tracing and kernel panic kdump tracing data.  I also verified
this patch series which can work with kernel panic kdump tracing data,
because Mathieu is working on CPU wide tracing related work, so after
this we need to retest for CPU wide tracing and kdump tracing to ensure
the python script can handle well for all cases.

You are very welcome to test the script in this patch series, your
testing result and suggestion are very valuable to perfect this script
to cover more cases.

Changes from v2:
* Synced with Rob for handling CS_ETM_TRACE_ON packet, so refined 0001
  patch according to dicussion;
* Minor cleanup and fixes in 0003 patch for python script: remove 'svc'
  checking.

Changes from v1:
* According to Mike and Rob suggestion, add the fixing to generate samples
  for the start packet and exception packets.
* Simplify the python script to remove the exception prediction algorithm,
  we can rely on the sane exception packets for disassembler.


Leo Yan (4):
  perf cs-etm: Generate branch sample for missed packets
  perf script python: Add addr into perf sample dict
  perf script python: Add script for CoreSight trace disassembler
  coresight: Document for CoreSight trace disassembler

 Documentation/trace/coresight.txt                  |  52 +++++
 tools/perf/scripts/python/arm-cs-trace-disasm.py   | 235 +++++++++++++++++++++
 tools/perf/util/cs-etm.c                           |  93 ++++++--
 .../util/scripting-engines/trace-event-python.c    |   2 +
 4 files changed, 362 insertions(+), 20 deletions(-)
 create mode 100644 tools/perf/scripts/python/arm-cs-trace-disasm.py

-- 
2.7.4

^ permalink raw reply

* [RFT v3 1/4] perf cs-etm: Generate branch sample for missed packets
From: Leo Yan @ 2018-05-28  8:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1527497103-3593-1-git-send-email-leo.yan@linaro.org>

Commit e573e978fb12 ("perf cs-etm: Inject capabilitity for CoreSight
traces") reworks the samples generation flow from CoreSight trace to
match the correct format so Perf report tool can display the samples
properly.

But the change has side effect for branch packet handling, it only
generate branch samples by checking previous packet flag
'last_instr_taken_branch' is true, this results in below three kinds
packets are missed to generate branch samples:

- The start tracing packet at the beginning of tracing data;
- The exception handling packet;
- If one CS_ETM_TRACE_ON packet is inserted, we also miss to handle it
  for branch samples.  CS_ETM_TRACE_ON packet itself can give the info
  that there have a discontinuity in the trace, on the other hand we
  also miss to generate proper branch sample for packets before and
  after CS_ETM_TRACE_ON packet.

This patch is to add branch sample handling for up three kinds packets:

- In function cs_etm__sample(), check if 'prev_packet->sample_type' is
  zero and in this case it generates branch sample for the start tracing
  packet; furthermore, we also need to handle the condition for
  prev_packet::end_addr is zero in the cs_etm__last_executed_instr();

- In function cs_etm__sample(), check if 'prev_packet->exc' is true and
  generate branch sample for exception handling packet;

- If there has one CS_ETM_TRACE_ON packet is coming, we firstly generate
  branch sample in the function cs_etm__flush(), this can save complete
  info for the previous CS_ETM_RANGE packet just before CS_ETM_TRACE_ON
  packet.  We also generate branch sample for the new CS_ETM_RANGE
  packet after CS_ETM_TRACE_ON packet, this have two purposes, the
  first one purpose is to save the info for the new CS_ETM_RANGE packet,
  the second purpose is to save CS_ETM_TRACE_ON packet info so we can
  have hint for a discontinuity in the trace.

  For CS_ETM_TRACE_ON packet, its fields 'packet->start_addr' and
  'packet->end_addr' equal to 0xdeadbeefdeadbeefUL which are emitted in
  the decoder layer as dummy value.  This patch is to convert these
  values to zeros for more readable; this is accomplished by functions
  cs_etm__last_executed_instr() and cs_etm__first_executed_instr().  The
  later one is a new function introduced by this patch.

Reviewed-by: Robert Walker <robert.walker@arm.com>
Fixes: e573e978fb12 ("perf cs-etm: Inject capabilitity for CoreSight traces")
Signed-off-by: Leo Yan <leo.yan@linaro.org>
---
 tools/perf/util/cs-etm.c | 93 +++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 73 insertions(+), 20 deletions(-)

diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c
index 822ba91..8418173 100644
--- a/tools/perf/util/cs-etm.c
+++ b/tools/perf/util/cs-etm.c
@@ -495,6 +495,20 @@ static inline void cs_etm__reset_last_branch_rb(struct cs_etm_queue *etmq)
 static inline u64 cs_etm__last_executed_instr(struct cs_etm_packet *packet)
 {
 	/*
+	 * The packet is the start tracing packet if the end_addr is zero,
+	 * returns 0 for this case.
+	 */
+	if (!packet->end_addr)
+		return 0;
+
+	/*
+	 * The packet is the CS_ETM_TRACE_ON packet if the end_addr is
+	 * magic number 0xdeadbeefdeadbeefUL, returns 0 for this case.
+	 */
+	if (packet->end_addr == 0xdeadbeefdeadbeefUL)
+		return 0;
+
+	/*
 	 * The packet records the execution range with an exclusive end address
 	 *
 	 * A64 instructions are constant size, so the last executed
@@ -505,6 +519,18 @@ static inline u64 cs_etm__last_executed_instr(struct cs_etm_packet *packet)
 	return packet->end_addr - A64_INSTR_SIZE;
 }
 
+static inline u64 cs_etm__first_executed_instr(struct cs_etm_packet *packet)
+{
+	/*
+	 * The packet is the CS_ETM_TRACE_ON packet if the start_addr is
+	 * magic number 0xdeadbeefdeadbeefUL, returns 0 for this case.
+	 */
+	if (packet->start_addr == 0xdeadbeefdeadbeefUL)
+		return 0;
+
+	return packet->start_addr;
+}
+
 static inline u64 cs_etm__instr_count(const struct cs_etm_packet *packet)
 {
 	/*
@@ -546,7 +572,7 @@ static void cs_etm__update_last_branch_rb(struct cs_etm_queue *etmq)
 
 	be       = &bs->entries[etmq->last_branch_pos];
 	be->from = cs_etm__last_executed_instr(etmq->prev_packet);
-	be->to	 = etmq->packet->start_addr;
+	be->to	 = cs_etm__first_executed_instr(etmq->packet);
 	/* No support for mispredict */
 	be->flags.mispred = 0;
 	be->flags.predicted = 1;
@@ -701,7 +727,7 @@ static int cs_etm__synth_branch_sample(struct cs_etm_queue *etmq)
 	sample.ip = cs_etm__last_executed_instr(etmq->prev_packet);
 	sample.pid = etmq->pid;
 	sample.tid = etmq->tid;
-	sample.addr = etmq->packet->start_addr;
+	sample.addr = cs_etm__first_executed_instr(etmq->packet);
 	sample.id = etmq->etm->branches_id;
 	sample.stream_id = etmq->etm->branches_id;
 	sample.period = 1;
@@ -897,13 +923,28 @@ static int cs_etm__sample(struct cs_etm_queue *etmq)
 		etmq->period_instructions = instrs_over;
 	}
 
-	if (etm->sample_branches &&
-	    etmq->prev_packet &&
-	    etmq->prev_packet->sample_type == CS_ETM_RANGE &&
-	    etmq->prev_packet->last_instr_taken_branch) {
-		ret = cs_etm__synth_branch_sample(etmq);
-		if (ret)
-			return ret;
+	if (etm->sample_branches && etmq->prev_packet) {
+		bool generate_sample = false;
+
+		/* Generate sample for start tracing packet */
+		if (etmq->prev_packet->sample_type == 0 ||
+		    etmq->prev_packet->sample_type == CS_ETM_TRACE_ON)
+			generate_sample = true;
+
+		/* Generate sample for exception packet */
+		if (etmq->prev_packet->exc == true)
+			generate_sample = true;
+
+		/* Generate sample for normal branch packet */
+		if (etmq->prev_packet->sample_type == CS_ETM_RANGE &&
+		    etmq->prev_packet->last_instr_taken_branch)
+			generate_sample = true;
+
+		if (generate_sample) {
+			ret = cs_etm__synth_branch_sample(etmq);
+			if (ret)
+				return ret;
+		}
 	}
 
 	if (etm->sample_branches || etm->synth_opts.last_branch) {
@@ -922,11 +963,16 @@ static int cs_etm__sample(struct cs_etm_queue *etmq)
 static int cs_etm__flush(struct cs_etm_queue *etmq)
 {
 	int err = 0;
+	struct cs_etm_auxtrace *etm = etmq->etm;
 	struct cs_etm_packet *tmp;
 
-	if (etmq->etm->synth_opts.last_branch &&
-	    etmq->prev_packet &&
-	    etmq->prev_packet->sample_type == CS_ETM_RANGE) {
+	if (!etmq->prev_packet)
+		return 0;
+
+	if (etmq->prev_packet->sample_type != CS_ETM_RANGE)
+		return 0;
+
+	if (etmq->etm->synth_opts.last_branch) {
 		/*
 		 * Generate a last branch event for the branches left in the
 		 * circular buffer at the end of the trace.
@@ -939,18 +985,25 @@ static int cs_etm__flush(struct cs_etm_queue *etmq)
 		err = cs_etm__synth_instruction_sample(
 			etmq, addr,
 			etmq->period_instructions);
+		if (err)
+			return err;
 		etmq->period_instructions = 0;
+	}
 
-		/*
-		 * Swap PACKET with PREV_PACKET: PACKET becomes PREV_PACKET for
-		 * the next incoming packet.
-		 */
-		tmp = etmq->packet;
-		etmq->packet = etmq->prev_packet;
-		etmq->prev_packet = tmp;
+	if (etm->sample_branches) {
+		err = cs_etm__synth_branch_sample(etmq);
+		if (err)
+			return err;
 	}
 
-	return err;
+	/*
+	 * Swap PACKET with PREV_PACKET: PACKET becomes PREV_PACKET for
+	 * the next incoming packet.
+	 */
+	tmp = etmq->packet;
+	etmq->packet = etmq->prev_packet;
+	etmq->prev_packet = tmp;
+	return 0;
 }
 
 static int cs_etm__run_decoder(struct cs_etm_queue *etmq)
-- 
2.7.4

^ permalink raw reply related

* [RFT v3 2/4] perf script python: Add addr into perf sample dict
From: Leo Yan @ 2018-05-28  8:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1527497103-3593-1-git-send-email-leo.yan@linaro.org>

ARM CoreSight auxtrace uses 'sample->addr' to record the target address
for branch instructions, so the data of 'sample->addr' is required for
tracing data analysis.

This commit collects data of 'sample->addr' into perf sample dict,
finally can be used for python script for parsing event.

Signed-off-by: Leo Yan <leo.yan@linaro.org>
---
 tools/perf/util/scripting-engines/trace-event-python.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index 10dd5fc..7f8afac 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -531,6 +531,8 @@ static PyObject *get_perf_sample_dict(struct perf_sample *sample,
 			PyLong_FromUnsignedLongLong(sample->period));
 	pydict_set_item_string_decref(dict_sample, "phys_addr",
 			PyLong_FromUnsignedLongLong(sample->phys_addr));
+	pydict_set_item_string_decref(dict_sample, "addr",
+			PyLong_FromUnsignedLongLong(sample->addr));
 	set_sample_read_in_dict(dict_sample, sample, evsel);
 	pydict_set_item_string_decref(dict, "sample", dict_sample);
 
-- 
2.7.4

^ permalink raw reply related

* [RFT v3 3/4] perf script python: Add script for CoreSight trace disassembler
From: Leo Yan @ 2018-05-28  8:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1527497103-3593-1-git-send-email-leo.yan@linaro.org>

This commit adds python script to parse CoreSight tracing event and
use command 'objdump' for disassembled lines, finally we can generate
readable program execution flow for reviewing tracing data.

The script receives CoreSight tracing packet with below format:

                +------------+------------+------------+
  packet(n):    |    addr    |    ip      |    cpu     |
                +------------+------------+------------+
  packet(n+1):  |    addr    |    ip      |    cpu     |
                +------------+------------+------------+

packet::ip is the last address of current branch instruction and
packet::addr presents the start address of the next coming branch
instruction.  So for one branch instruction which starts in packet(n),
its execution flow starts from packet(n)::addr and it stops at
packet(n+1)::ip.  As results we need to combine the two continuous
packets to generate the instruction range, this is the rationale for the
script implementation:

  [ sample(n)::addr .. sample(n+1)::ip ]

Credits to Tor Jeremiassen who have written the script skeleton and
provides the ideas for reading symbol file according to build-id,
creating memory map for dso and basic packet handling.  Mathieu Poirier
contributed fixes for build-id and memory map bugs.  The detailed
development history for this script you can find from [1].  Based on Tor
and Mathieu work, the script is updated samples handling for the
corrected sample format.  Another minor enhancement is to support for
without build-id case, the script can parse kernel symbols with option
'-k' for vmlinux file path.

[1] https://github.com/Linaro/perf-opencsd/commits/perf-opencsd-v4.15/tools/perf/scripts/python/cs-trace-disasm.py

Co-authored-by: Tor Jeremiassen <tor@ti.com>
Co-authored-by: Mathieu Poirier <mathieu.poirier@linaro.org>
Signed-off-by: Leo Yan <leo.yan@linaro.org>
---
 tools/perf/scripts/python/arm-cs-trace-disasm.py | 235 +++++++++++++++++++++++
 1 file changed, 235 insertions(+)
 create mode 100644 tools/perf/scripts/python/arm-cs-trace-disasm.py

diff --git a/tools/perf/scripts/python/arm-cs-trace-disasm.py b/tools/perf/scripts/python/arm-cs-trace-disasm.py
new file mode 100644
index 0000000..1239ab4
--- /dev/null
+++ b/tools/perf/scripts/python/arm-cs-trace-disasm.py
@@ -0,0 +1,235 @@
+# arm-cs-trace-disasm.py: ARM CoreSight Trace Dump With Disassember
+# SPDX-License-Identifier: GPL-2.0
+#
+# Tor Jeremiassen <tor@ti.com> is original author who wrote script
+# skeleton, Mathieu Poirier <mathieu.poirier@linaro.org> contributed
+# fixes for build-id and memory map; Leo Yan <leo.yan@linaro.org>
+# updated the packet parsing with new samples format.
+
+import os
+import sys
+import re
+from subprocess import *
+from optparse import OptionParser, make_option
+
+# Command line parsing
+
+option_list = [
+	# formatting options for the bottom entry of the stack
+	make_option("-k", "--vmlinux", dest="vmlinux_name",
+		    help="Set path to vmlinux file"),
+	make_option("-d", "--objdump", dest="objdump_name",
+		    help="Set path to objdump executable file"),
+	make_option("-v", "--verbose", dest="verbose",
+		    action="store_true", default=False,
+		    help="Enable debugging log")
+]
+
+parser = OptionParser(option_list=option_list)
+(options, args) = parser.parse_args()
+
+if (options.objdump_name == None):
+	sys.exit("No objdump executable file specified - use -d or --objdump option")
+
+# Initialize global dicts and regular expression
+
+build_ids = dict()
+mmaps = dict()
+disasm_cache = dict()
+cpu_data = dict()
+disasm_re = re.compile("^\s*([0-9a-fA-F]+):")
+disasm_func_re = re.compile("^\s*([0-9a-fA-F]+)\s\<.*\>:")
+cache_size = 32*1024
+prev_cpu = -1
+
+def parse_buildid():
+	global build_ids
+
+	buildid_regex = "([a-fA-f0-9]+)[ \t]([^ \n]+)"
+	buildid_re = re.compile(buildid_regex)
+
+	results = check_output(["perf", "buildid-list"]).split('\n');
+	for line in results:
+		m = buildid_re.search(line)
+		if (m == None):
+			continue;
+
+		id_name = m.group(2)
+		id_num  = m.group(1)
+
+		if (id_name == "[kernel.kallsyms]") :
+			append = "/kallsyms"
+		elif (id_name == "[vdso]") :
+			append = "/vdso"
+		else:
+			append = "/elf"
+
+		build_ids[id_name] = os.environ['PERF_BUILDID_DIR'] + \
+					"/" + id_name + "/" + id_num + append;
+		# Replace duplicate slash chars to single slash char
+		build_ids[id_name] = build_ids[id_name].replace('//', '/', 1)
+
+	if ((options.vmlinux_name == None) and ("[kernel.kallsyms]" in build_ids)):
+		print "kallsyms cannot be used to dump assembler"
+
+	# Set vmlinux path to replace kallsyms file, if without buildid we still
+	# can use vmlinux to prase kernel symbols
+	if ((options.vmlinux_name != None)):
+		build_ids['[kernel.kallsyms]'] = options.vmlinux_name;
+
+def parse_mmap():
+	global mmaps
+
+	# Check mmap for PERF_RECORD_MMAP and PERF_RECORD_MMAP2
+	mmap_regex = "PERF_RECORD_MMAP.* -?[0-9]+/[0-9]+: \[(0x[0-9a-fA-F]+)\((0x[0-9a-fA-F]+)\).*:\s.*\s(\S*)"
+	mmap_re = re.compile(mmap_regex)
+
+	results = check_output("perf script --show-mmap-events | fgrep PERF_RECORD_MMAP", shell=True).split('\n')
+	for line in results:
+		m = mmap_re.search(line)
+		if (m != None):
+			if (m.group(3) == '[kernel.kallsyms]_text'):
+				dso = '[kernel.kallsyms]'
+			else:
+				dso = m.group(3)
+
+			start = int(m.group(1),0)
+			end   = int(m.group(1),0) + int(m.group(2),0)
+			mmaps[dso] = [start, end]
+
+def find_dso_mmap(addr):
+	global mmaps
+
+	for key, value in mmaps.items():
+		if (addr >= value[0] and addr < value[1]):
+			return key
+
+	return None
+
+def read_disam(dso, start_addr, stop_addr):
+	global mmaps
+	global build_ids
+
+	addr_range = start_addr  + ":" + stop_addr;
+
+	# Don't let the cache get too big, clear it when it hits max size
+	if (len(disasm_cache) > cache_size):
+		disasm_cache.clear();
+
+	try:
+		disasm_output = disasm_cache[addr_range];
+	except:
+		try:
+			fname = build_ids[dso];
+		except KeyError:
+			sys.exit("cannot find symbol file for " + dso)
+
+		disasm = [ options.objdump_name, "-d", "-z",
+			   "--start-address="+start_addr,
+			   "--stop-address="+stop_addr, fname ]
+
+		disasm_output = check_output(disasm).split('\n')
+		disasm_cache[addr_range] = disasm_output;
+
+	return disasm_output
+
+def dump_disam(dso, start_addr, stop_addr):
+	for line in read_disam(dso, start_addr, stop_addr):
+		m = disasm_func_re.search(line)
+		if (m != None):
+			print "\t",line
+			continue
+
+		m = disasm_re.search(line)
+		if (m == None):
+			continue;
+
+		print "\t",line
+
+def dump_packet(sample):
+	print "Packet = { cpu: 0x%d addr: 0x%x phys_addr: 0x%x ip: 0x%x " \
+	      "pid: %d tid: %d period: %d time: %d }" % \
+	      (sample['cpu'], sample['addr'], sample['phys_addr'], \
+	       sample['ip'], sample['pid'], sample['tid'], \
+	       sample['period'], sample['time'])
+
+def trace_begin():
+	print 'ARM CoreSight Trace Data Assembler Dump'
+	parse_buildid()
+	parse_mmap()
+
+def trace_end():
+	print 'End'
+
+def trace_unhandled(event_name, context, event_fields_dict):
+	print ' '.join(['%s=%s'%(k,str(v))for k,v in sorted(event_fields_dict.items())])
+
+def process_event(param_dict):
+	global cache_size
+	global options
+	global prev_cpu
+
+	sample = param_dict["sample"]
+
+	if (options.verbose == True):
+		dump_packet(sample)
+
+	# If period doesn't equal to 1, this packet is for instruction sample
+	# packet, we need drop this synthetic packet.
+	if (sample['period'] != 1):
+		print "Skip synthetic instruction sample"
+		return
+
+	cpu = format(sample['cpu'], "d");
+
+	# Initialize CPU data if it's empty, and directly return back
+	# if this is the first tracing event for this CPU.
+	if (cpu_data.get(str(cpu) + 'addr') == None):
+		cpu_data[str(cpu) + 'addr'] = format(sample['addr'], "#x")
+		prev_cpu = cpu
+		return
+
+	# The format for packet is:
+	#
+	#                 +------------+------------+------------+
+	#  sample_prev:   |    addr    |    ip      |    cpu     |
+	#                 +------------+------------+------------+
+	#  sample_next:   |    addr    |    ip      |    cpu     |
+	#                 +------------+------------+------------+
+	#
+	# We need to combine the two continuous packets to get the instruction
+	# range for sample_prev::cpu:
+	#
+	#     [ sample_prev::addr .. sample_next::ip ]
+	#
+	# For this purose, sample_prev::addr is stored into cpu_data structure
+	# and read back for 'start_addr' when the new packet comes, and we need
+	# to use sample_next::ip to calculate 'stop_addr', plusing extra 4 for
+	# 'stop_addr' is for the sake of objdump so the final assembler dump can
+	# include last instruction for sample_next::ip.
+
+	start_addr = cpu_data[str(prev_cpu) + 'addr']
+	stop_addr  = format(sample['ip'] + 4, "#x")
+
+	# Record for previous sample packet
+	cpu_data[str(cpu) + 'addr'] = format(sample['addr'], "#x")
+	prev_cpu = cpu
+
+	# Handle CS_ETM_TRACE_ON packet if start_addr=0 and stop_addr=4
+	if (int(start_addr, 0) == 0 and int(stop_addr, 0) == 4):
+		print "CPU%s: CS_ETM_TRACE_ON packet is inserted" % cpu
+		return
+
+	# Sanity checking dso for start_addr and stop_addr
+	prev_dso = find_dso_mmap(int(start_addr, 0))
+	next_dso = find_dso_mmap(int(stop_addr, 0))
+
+	# If cannot find dso so cannot dump assembler, bail out
+	if (prev_dso == None or next_dso == None):
+		print "Address range [ %s .. %s ]: failed to find dso" % (start_addr, stop_addr)
+		return
+	elif (prev_dso != next_dso):
+		print "Address range [ %s .. %s ]: isn't in same dso" % (start_addr, stop_addr)
+		return
+
+	dump_disam(prev_dso, start_addr, stop_addr)
-- 
2.7.4

^ permalink raw reply related

* [RFT v3 4/4] coresight: Document for CoreSight trace disassembler
From: Leo Yan @ 2018-05-28  8:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1527497103-3593-1-git-send-email-leo.yan@linaro.org>

This commit documents CoreSight trace disassembler usage and gives
example for it.

Signed-off-by: Leo Yan <leo.yan@linaro.org>
---
 Documentation/trace/coresight.txt | 52 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)

diff --git a/Documentation/trace/coresight.txt b/Documentation/trace/coresight.txt
index 6f0120c..b8f2359 100644
--- a/Documentation/trace/coresight.txt
+++ b/Documentation/trace/coresight.txt
@@ -381,3 +381,55 @@ sort example is from the AutoFDO tutorial (https://gcc.gnu.org/wiki/AutoFDO/Tuto
 	$ taskset -c 2 ./sort_autofdo
 	Bubble sorting array of 30000 elements
 	5806 ms
+
+
+Tracing data disassembler
+-------------------------
+
+'perf script' supports to use script to parse tracing packet and rely on
+'objdump' for disassembled lines, this can convert tracing data to readable
+program execution flow for easily reviewing tracing data.
+
+The CoreSight trace disassembler is located in the folder:
+tools/perf/scripts/python/arm-cs-trace-disasm.py.  This script support below
+options:
+
+	-d, --objdump: Set path to objdump executable, this option is
+		       mandatory.
+	-k, --vmlinux: Set path to vmlinux file.
+	-v, --verbose: Enable debugging log, after enable this option the
+		       script dumps every event data.
+
+Below is one example for using python script to dump CoreSight trace
+disassembler:
+
+	$ perf script -s arm-cs-trace-disasm.py -i perf.data \
+	    -F cpu,event,ip,addr,sym -- -d objdump -k ./vmlinux > cs-disasm.log
+
+Below is one example for the disassembler log:
+
+ARM CoreSight Trace Data Assembler Dump
+	ffff000008a5f2dc <etm4_enable_hw+0x344>:
+	ffff000008a5f2dc:	340000a0 	cbz	w0, ffff000008a5f2f0 <etm4_enable_hw+0x358>
+	ffff000008a5f2f0 <etm4_enable_hw+0x358>:
+	ffff000008a5f2f0:	f9400260 	ldr	x0, [x19]
+	ffff000008a5f2f4:	d5033f9f 	dsb	sy
+	ffff000008a5f2f8:	913ec000 	add	x0, x0, #0xfb0
+	ffff000008a5f2fc:	b900001f 	str	wzr, [x0]
+	ffff000008a5f300:	f9400bf3 	ldr	x19, [sp, #16]
+	ffff000008a5f304:	a8c27bfd 	ldp	x29, x30, [sp], #32
+	ffff000008a5f308:	d65f03c0 	ret
+	ffff000008a5fa18 <etm4_enable+0x1b0>:
+	ffff000008a5fa18:	14000025 	b	ffff000008a5faac <etm4_enable+0x244>
+	ffff000008a5faac <etm4_enable+0x244>:
+	ffff000008a5faac:	b9406261 	ldr	w1, [x19, #96]
+	ffff000008a5fab0:	52800015 	mov	w21, #0x0                   	// #0
+	ffff000008a5fab4:	f901ca61 	str	x1, [x19, #912]
+	ffff000008a5fab8:	2a1503e0 	mov	w0, w21
+	ffff000008a5fabc:	3940e261 	ldrb	w1, [x19, #56]
+	ffff000008a5fac0:	f901ce61 	str	x1, [x19, #920]
+	ffff000008a5fac4:	a94153f3 	ldp	x19, x20, [sp, #16]
+	ffff000008a5fac8:	a9425bf5 	ldp	x21, x22, [sp, #32]
+	ffff000008a5facc:	a94363f7 	ldp	x23, x24, [sp, #48]
+	ffff000008a5fad0:	a8c47bfd 	ldp	x29, x30, [sp], #64
+	ffff000008a5fad4:	d65f03c0 	ret
-- 
2.7.4

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox