* Re: [PATCH v3 2/4] soc: qcom: Introduce APCS IPC driver
From: Jassi Brar @ 2017-05-04 7:54 UTC (permalink / raw)
To: Bjorn Andersson
Cc: Loic PALLARDY, Andy Gross, Rob Herring, Mark Rutland,
Ohad Ben-Cohen, linux-arm-msm@vger.kernel.org,
linux-soc@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-remoteproc@vger.kernel.org
In-Reply-To: <20170504054516.GB15143@minitux>
On Thu, May 4, 2017 at 11:15 AM, Bjorn Andersson
<bjorn.andersson@linaro.org> wrote:
> On Wed 03 May 02:55 PDT 2017, Jassi Brar wrote:
>
>> Loic, thanks for adding me.
>>
>> On Wed, May 3, 2017 at 2:58 PM, Loic PALLARDY <loic.pallardy@st.com> wrote:
>> >
>> >
>> >> -----Original Message-----
>> >> From: linux-remoteproc-owner@vger.kernel.org [mailto:linux-remoteproc-
>> >> owner@vger.kernel.org] On Behalf Of Bjorn Andersson
>> >> Sent: Wednesday, May 03, 2017 7:29 AM
>> >> To: Andy Gross <andy.gross@linaro.org>; Rob Herring
>> >> <robh+dt@kernel.org>; Mark Rutland <mark.rutland@arm.com>; Ohad Ben-
>> >> Cohen <ohad@wizery.com>
>> >> Cc: linux-arm-msm@vger.kernel.org; linux-soc@vger.kernel.org;
>> >> devicetree@vger.kernel.org; linux-kernel@vger.kernel.org; linux-
>> >> remoteproc@vger.kernel.org
>> >> Subject: [PATCH v3 2/4] soc: qcom: Introduce APCS IPC driver
>> >>
>> >> This implements a driver that exposes the IPC bits found in the APCS Global
>> >> block in various Qualcomm platforms. The bits are used to signal inter-
>> >> processor communication signals from the application CPU to other masters.
>> >>
>> >> The driver implements the "doorbell" binding and could be used as basis for a
>> >> new Linux framework, if found useful outside Qualcomm.
>> >>
>> > Hi Bjorn,
>> >
>> > Even if Qualcom APCS IPC is limited, why don't you rely on existing mailbox framework.
>> > It is there to gather all IPC management under the same interface.
>> > No need to create a new one from my pov.
>> > If you don't provide message data, mailbox framework behaves as doorbell.
>> >
>> QCOM RPM reinvented the wheel for what mailbox framework already did,
>> despite my pointing it out =>
>> http://lkml.iu.edu/hypermail//linux/kernel/1406.2/03918.html
>>
>
> The RPM interface works by writing various information in shared DRAM
> and then invoking an interrupt on the remote processor.
>
This is what _most_ platforms do, and they use mailbox framework. If
mailbox framework doesn't suit RPM, then it doesn't suit most
platforms that use it.
> My argumentation against using the mailbox framework for the RPM case
> was that the message model is a software construct and doesn't fit the
> mailbox framework.
>
Mailbox framework works beneath protocol layer (software construct).
As I said years ago, the h/w bits of the controller should be under
mailbox api, while the message structures and signals are protocol
specific and be in QCOM specific location.
> Before "inventing" the function for acquiring a handle to a doorbell I
> did look at making this a mailbox controller, but as each mailbox
> channel related to a single bit and 1 is the only value we'll ever write
> it didn't feel like it matches the mailbox expectations. But as you seem
> to object I'll attempt to rewrite it using the mailbox framework
> instead.
>
Yes, please. 1-bit messages are just a special case of N-bits messages
that mailbox framework supports.
> But which one of these would be appropriate for a "mailbox channel" that
> doesn't have any actual messages?
>
> mbox_send_message(chan, NULL)
> or
> const int one = 1;
> mbox_send_message(chan, (void*)&one);
>
It depends upon your h/w.
If each physical channel is hardwired to work on a predefined single
bit, then the driver could do without that bit being explicitly
passed.
If a physical channel can be mapped onto any bit(s), then you do need
to pass that info via mbox_send_message().
>> The driver bypassed mailbox framework and was pushed via another tree.
>> Same is being attempted now, only now it is more expensive to switch
>> to generic mailbox framework having spent so much time on QCOM
>> specific implementation of controller and protocol drivers inside
>> drivers/soc/qcom/
>
> I'm not sure I follow this, there's no extensive rework going on here -
> all I'm trying to do is abstract the "writel(BIT(x), ipc_reg)" line of
> the RPM driver, because it's being used in other clients as well.
>
No, I meant ideally RPM should have used mailbox api for the
controller programming, but moving to that now will be expensive
because you already developed huge code base around QCOM specific
mailbox implementation.
Regards.
^ permalink raw reply
* Re: [PATCHv2 1/3] dt-bindings: display: Intel FPGA VIP drm driver Devicetree bindings
From: Neil Armstrong @ 2017-05-04 7:55 UTC (permalink / raw)
To: hean.loong.ong-ral2JQCrhuEAvxtiuMwx3w,
daniel.vetter-ral2JQCrhuEAvxtiuMwx3w,
dinguyen-DgEjT+Ai2ygdnm+yROfE0A, robh+dt-DgEjT+Ai2ygdnm+yROfE0A
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
tien.hock.loh-ral2JQCrhuEAvxtiuMwx3w, Ong-CC+yJ3UmIYqDUpFQwHEjaQ,
dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
In-Reply-To: <1493086006-4392-2-git-send-email-hean.loong.ong-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
On 04/25/2017 04:06 AM, hean.loong.ong-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org wrote:
> From: "Ong, Hean Loong" <hean.loong.ong-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
>
> Device tree binding for Intel FPGA Video and Image
> Processing Suite. The binding involved would be generated
> from the Altera (Intel) Qsys system. The bindings would
> set the max width, max height, buts per pixel and memory
> port width. The device tree binding only supports the Intel
> Arria10 devkit and its variants. Vendor name retained as
> altr.
>
> Signed-off-by: Ong, Hean Loong <hean.loong.ong-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
> ---
> v2:
> * Moved Device Tree bindings to Documentation/devicetree/bindings/display/
> * Added vendor name altr, to description
> ---
> .../devicetree/bindings/display/altr,vip-fb2.txt | 30 ++++++++++++++++++++++
> 1 file changed, 30 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/display/altr,vip-fb2.txt
>
> diff --git a/Documentation/devicetree/bindings/display/altr,vip-fb2.txt b/Documentation/devicetree/bindings/display/altr,vip-fb2.txt
> new file mode 100644
> index 0000000..bdffefb
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/display/altr,vip-fb2.txt
> @@ -0,0 +1,30 @@
> +Intel Video and Image Processing(VIP) Frame Buffer II bindings
> +
> +Supported hardware: Arria 10 and above with display port IP
> +
Hi,
> +The drm driver for the Arria 10 devkit would require the display resolution
> +and pixel information to be included as these values are generated based
> +on the FPGA design that drives the video connector attached to the drm driver
> +Information the FPGA video IP component can be acquired from
> +https://www.altera.com/content/dam/altera-www/global/en_US/pdfs/literature/ug/ug_vip.pdf
The bindings should not reference the driver, but only the hardware and the way it is configured
and interconnected with the system.
Please explicit that this is an IP component that can be configured with explicit limits on
the display widths and heights and memory parameters.
But you should also indicate over what this IP is connected and add a port connected to a connector
node in case this ip is not used on a specific board like in [1] or [2] :
"""
Required nodes:
The connections to the DU output video ports are modeled using the OF graph
bindings specified in Documentation/devicetree/bindings/graph.txt.
The following table lists for each supported model the port number
corresponding to each DU output.
Port 0 Port1 Port2 Port3
-----------------------------------------------------------------------------
R8A7779 (H1) DPAD 0 DPAD 1 - -
"""
You may also need to add a "Display Port" connector binding aswell along the HDMI, VGA, ....
I know this targets an FPGA system, so you should explicit that in the description.
> +Required properties:
> +
> +- compatible: "altr,vip-frame-buffer-2.0"
You should also add model specific compatible strings for each supported FPGA devices.
> +- reg: Physical base address and length of the framebuffer controller's
> + registers.
> +- altr,max-width: The width of the framebuffer in pixels.
> +- altr,max-height: The height of the framebuffer in pixels.
> +- altr,bits-per-symbol: only "8" is currently supported
> +- altr,mem-port-width = the bus width of the avalon master port on the frame reader
What is the avalon master port ?
Can you add a schema to explicit how this IP is connected to the system ?
> +
> +Example:
> +
> + dp_0_frame_buf: vip@100000280 {
> + compatible = "altr,vip-frame-buffer-2.0";
> + reg = <0x00000001 0x00000280 0x00000040>;
> + altr,max-width = <1280>;
> + altr,max-height = <720>;
> + altr,bits-per-symbol = <8>;
> + altr,mem-port-width = <128>;
> + };
>
[1] Documentation/devicetree/bindings/display/amlogic,meson-vpu.txt
[2] Documentation/devicetree/bindings/display/renesas,du.txt
Thanks,
Neil
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v2 18/20] drm/sun4i: Add HDMI support
From: Chen-Yu Tsai @ 2017-05-04 7:55 UTC (permalink / raw)
To: Maxime Ripard
Cc: Mike Turquette, Stephen Boyd, Chen-Yu Tsai, Daniel Vetter,
David Airlie, dri-devel, Mark Rutland, Rob Herring, devicetree,
linux-arm-kernel, linux-clk, linux-kernel, linux-sunxi
In-Reply-To: <c8db196b5084b317c3a43a0caea1363951e6e5bf.1493812478.git-series.maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
On Wed, May 3, 2017 at 7:59 PM, Maxime Ripard
<maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> wrote:
> The earlier Allwinner SoCs (A10, A10s, A20, A31) have an embedded HDMI
> controller.
>
> That HDMI controller is able to do audio and CEC, but those have been left
> out for now.
>
> Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> ---
> drivers/gpu/drm/sun4i/Kconfig | 9 +-
> drivers/gpu/drm/sun4i/Makefile | 6 +-
> drivers/gpu/drm/sun4i/sun4i_hdmi.h | 157 +++++++-
> drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c | 127 +++++-
> drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c | 493 +++++++++++++++++++++-
> drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c | 225 ++++++++++-
> 6 files changed, 1017 insertions(+), 0 deletions(-)
> create mode 100644 drivers/gpu/drm/sun4i/sun4i_hdmi.h
> create mode 100644 drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c
> create mode 100644 drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
> create mode 100644 drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c
>
> diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig
> index a4b357db8856..35299c4e2594 100644
> --- a/drivers/gpu/drm/sun4i/Kconfig
> +++ b/drivers/gpu/drm/sun4i/Kconfig
> @@ -12,3 +12,12 @@ config DRM_SUN4I
> Choose this option if you have an Allwinner SoC with a
> Display Engine. If M is selected the module will be called
> sun4i-drm.
> +
> +if DRM_SUN4I
> +config DRM_SUN4I_HDMI
> + tristate "Allwinner A10 HDMI Controller Support"
> + help
> + Choose this option if you have an Allwinner SoC with an HDMI
> + controller.
> +
> +endif
> diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
> index 59b757350a1f..c09bf8093710 100644
> --- a/drivers/gpu/drm/sun4i/Makefile
> +++ b/drivers/gpu/drm/sun4i/Makefile
> @@ -11,3 +11,9 @@ obj-$(CONFIG_DRM_SUN4I) += sun4i-drm.o sun4i-tcon.o
> obj-$(CONFIG_DRM_SUN4I) += sun4i_backend.o
> obj-$(CONFIG_DRM_SUN4I) += sun6i_drc.o
> obj-$(CONFIG_DRM_SUN4I) += sun4i_tv.o
> +
> +sun4i-drm-hdmi-y += sun4i_hdmi_enc.o
> +sun4i-drm-hdmi-y += sun4i_hdmi_ddc_clk.o
> +sun4i-drm-hdmi-y += sun4i_hdmi_tmds_clk.o
> +
> +obj-$(CONFIG_DRM_SUN4I_HDMI) += sun4i-drm-hdmi.o
> diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi.h b/drivers/gpu/drm/sun4i/sun4i_hdmi.h
> new file mode 100644
> index 000000000000..40d57b195b48
> --- /dev/null
> +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi.h
> @@ -0,0 +1,157 @@
> +/*
> + * Copyright (C) 2016 Maxime Ripard
> + *
> + * Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + */
> +
> +#ifndef _SUN4I_HDMI_H_
> +#define _SUN4I_HDMI_H_
> +
> +#include <drm/drm_connector.h>
> +#include <drm/drm_encoder.h>
> +
> +#define SUN4I_HDMI_CTRL_REG 0x004
> +#define SUN4I_HDMI_CTRL_ENABLE BIT(31)
> +
> +#define SUN4I_HDMI_IRQ_REG 0x008
> +#define SUN4I_HDMI_IRQ_STA_MASK 0x73
> +#define SUN4I_HDMI_IRQ_STA_FIFO_OF BIT(1)
> +#define SUN4I_HDMI_IRQ_STA_FIFO_UF BIT(0)
> +
> +#define SUN4I_HDMI_HPD_REG 0x00c
> +#define SUN4I_HDMI_HPD_HIGH BIT(0)
> +
> +#define SUN4I_HDMI_VID_CTRL_REG 0x010
> +#define SUN4I_HDMI_VID_CTRL_ENABLE BIT(31)
> +#define SUN4I_HDMI_VID_CTRL_HDMI_MODE BIT(30)
> +
> +#define SUN4I_HDMI_VID_TIMING_ACT_REG 0x014
> +#define SUN4I_HDMI_VID_TIMING_BP_REG 0x018
> +#define SUN4I_HDMI_VID_TIMING_FP_REG 0x01c
> +#define SUN4I_HDMI_VID_TIMING_SPW_REG 0x020
> +
> +#define SUN4I_HDMI_VID_TIMING_X(x) ((((x) - 1) & GENMASK(11, 0)))
> +#define SUN4I_HDMI_VID_TIMING_Y(y) ((((y) - 1) & GENMASK(11, 0)) << 16)
> +
> +#define SUN4I_HDMI_VID_TIMING_POL_REG 0x024
> +#define SUN4I_HDMI_VID_TIMING_POL_TX_CLK (0x3e0 << 16)
> +#define SUN4I_HDMI_VID_TIMING_POL_VSYNC BIT(1)
> +#define SUN4I_HDMI_VID_TIMING_POL_HSYNC BIT(0)
> +
> +#define SUN4I_HDMI_AVI_INFOFRAME_REG(n) (0x080 + (n))
> +
> +#define SUN4I_HDMI_PAD_CTRL0_REG 0x200
> +#define SUN4I_HDMI_PAD_CTRL0_BIASEN BIT(31)
> +#define SUN4I_HDMI_PAD_CTRL0_LDOCEN BIT(30)
> +#define SUN4I_HDMI_PAD_CTRL0_LDODEN BIT(29)
> +#define SUN4I_HDMI_PAD_CTRL0_PWENC BIT(28)
> +#define SUN4I_HDMI_PAD_CTRL0_PWEND BIT(27)
> +#define SUN4I_HDMI_PAD_CTRL0_PWENG BIT(26)
> +#define SUN4I_HDMI_PAD_CTRL0_CKEN BIT(25)
> +#define SUN4I_HDMI_PAD_CTRL0_TXEN BIT(23)
> +
> +#define SUN4I_HDMI_PAD_CTRL1_REG 0x204
> +#define SUN4I_HDMI_PAD_CTRL1_AMP_OPT BIT(23)
> +#define SUN4I_HDMI_PAD_CTRL1_AMPCK_OPT BIT(22)
> +#define SUN4I_HDMI_PAD_CTRL1_EMP_OPT BIT(20)
> +#define SUN4I_HDMI_PAD_CTRL1_EMPCK_OPT BIT(19)
> +#define SUN4I_HDMI_PAD_CTRL1_REG_DEN BIT(15)
> +#define SUN4I_HDMI_PAD_CTRL1_REG_DENCK BIT(14)
> +#define SUN4I_HDMI_PAD_CTRL1_REG_EMP(n) (((n) & 7) << 10)
> +#define SUN4I_HDMI_PAD_CTRL1_HALVE_CLK BIT(6)
> +#define SUN4I_HDMI_PAD_CTRL1_REG_AMP(n) (((n) & 7) << 3)
> +
> +#define SUN4I_HDMI_PLL_CTRL_REG 0x208
> +#define SUN4I_HDMI_PLL_CTRL_PLL_EN BIT(31)
> +#define SUN4I_HDMI_PLL_CTRL_BWS BIT(30)
> +#define SUN4I_HDMI_PLL_CTRL_HV_IS_33 BIT(29)
> +#define SUN4I_HDMI_PLL_CTRL_LDO1_EN BIT(28)
> +#define SUN4I_HDMI_PLL_CTRL_LDO2_EN BIT(27)
> +#define SUN4I_HDMI_PLL_CTRL_SDIV2 BIT(25)
> +#define SUN4I_HDMI_PLL_CTRL_VCO_GAIN(n) (((n) & 7) << 20)
> +#define SUN4I_HDMI_PLL_CTRL_S(n) (((n) & 7) << 16)
> +#define SUN4I_HDMI_PLL_CTRL_CP_S(n) (((n) & 0xf) << 12)
> +#define SUN4I_HDMI_PLL_CTRL_CS(n) (((n) & 0xf) << 8)
> +#define SUN4I_HDMI_PLL_CTRL_DIV(n) (((n) & 0xf) << 4)
> +#define SUN4I_HDMI_PLL_CTRL_DIV_MASK GENMASK(7, 4)
> +#define SUN4I_HDMI_PLL_CTRL_VCO_S(n) ((n) & 0xf)
> +
> +#define SUN4I_HDMI_PLL_DBG0_REG 0x20c
> +#define SUN4I_HDMI_PLL_DBG0_TMDS_PARENT(n) (((n) & 1) << 21)
> +#define SUN4I_HDMI_PLL_DBG0_TMDS_PARENT_MASK BIT(21)
> +#define SUN4I_HDMI_PLL_DBG0_TMDS_PARENT_SHIFT 21
> +
> +#define SUN4I_HDMI_PKT_CTRL_REG(n) (0x2f0 + (4 * (n)))
> +#define SUN4I_HDMI_PKT_CTRL_TYPE(n, t) ((t) << (((n) % 4) * 4))
> +
> +#define SUN4I_HDMI_UNKNOWN_REG 0x300
> +#define SUN4I_HDMI_UNKNOWN_INPUT_SYNC BIT(27)
> +
> +#define SUN4I_HDMI_DDC_CTRL_REG 0x500
> +#define SUN4I_HDMI_DDC_CTRL_ENABLE BIT(31)
> +#define SUN4I_HDMI_DDC_CTRL_START_CMD BIT(30)
> +#define SUN4I_HDMI_DDC_CTRL_FIFO_DIR_MASK BIT(8)
> +#define SUN4I_HDMI_DDC_CTRL_FIFO_DIR_READ (0 << 8)
> +#define SUN4I_HDMI_DDC_CTRL_RESET BIT(0)
> +
> +#define SUN4I_HDMI_DDC_ADDR_REG 0x504
> +#define SUN4I_HDMI_DDC_ADDR_SEGMENT(seg) (((seg) & 0xff) << 24)
> +#define SUN4I_HDMI_DDC_ADDR_EDDC(addr) (((addr) & 0xff) << 16)
> +#define SUN4I_HDMI_DDC_ADDR_OFFSET(off) (((off) & 0xff) << 8)
> +#define SUN4I_HDMI_DDC_ADDR_SLAVE(addr) ((addr) & 0xff)
> +
> +#define SUN4I_HDMI_DDC_FIFO_CTRL_REG 0x510
> +#define SUN4I_HDMI_DDC_FIFO_CTRL_CLEAR BIT(31)
> +
> +#define SUN4I_HDMI_DDC_FIFO_DATA_REG 0x518
> +#define SUN4I_HDMI_DDC_BYTE_COUNT_REG 0x51c
> +
> +#define SUN4I_HDMI_DDC_CMD_REG 0x520
> +#define SUN4I_HDMI_DDC_CMD_EXPLICIT_EDDC_READ 6
> +
> +#define SUN4I_HDMI_DDC_CLK_REG 0x528
> +#define SUN4I_HDMI_DDC_CLK_M(m) (((m) & 0x7) << 3)
> +#define SUN4I_HDMI_DDC_CLK_N(n) ((n) & 0x7)
> +
> +#define SUN4I_HDMI_DDC_LINE_CTRL_REG 0x540
> +#define SUN4I_HDMI_DDC_LINE_CTRL_SDA_ENABLE BIT(9)
> +#define SUN4I_HDMI_DDC_LINE_CTRL_SCL_ENABLE BIT(8)
> +
> +#define SUN4I_HDMI_DDC_FIFO_SIZE 16
> +
> +enum sun4i_hdmi_pkt_type {
> + SUN4I_HDMI_PKT_AVI = 2,
> + SUN4I_HDMI_PKT_END = 15,
> +};
> +
> +struct sun4i_hdmi {
> + struct drm_connector connector;
> + struct drm_encoder encoder;
> + struct device *dev;
> +
> + void __iomem *base;
> +
> + /* Parent clocks */
> + struct clk *bus_clk;
> + struct clk *mod_clk;
> + struct clk *pll0_clk;
> + struct clk *pll1_clk;
> +
> + /* And the clocks we create */
> + struct clk *ddc_clk;
> + struct clk *tmds_clk;
> +
> + struct sun4i_drv *drv;
> +
> + bool hdmi_monitor;
> +};
> +
> +int sun4i_ddc_create(struct sun4i_hdmi *hdmi, struct clk *clk);
> +int sun4i_tmds_create(struct sun4i_hdmi *hdmi);
> +
> +#endif /* _SUN4I_HDMI_H_ */
> diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c
> new file mode 100644
> index 000000000000..4692e8c345ed
> --- /dev/null
> +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c
> @@ -0,0 +1,127 @@
> +/*
> + * Copyright (C) 2016 Free Electrons
> + * Copyright (C) 2016 NextThing Co
> + *
> + * Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + */
> +
> +#include <linux/clk-provider.h>
> +
> +#include "sun4i_tcon.h"
> +#include "sun4i_hdmi.h"
> +
> +struct sun4i_ddc {
> + struct clk_hw hw;
> + struct sun4i_hdmi *hdmi;
> +};
> +
> +static inline struct sun4i_ddc *hw_to_ddc(struct clk_hw *hw)
> +{
> + return container_of(hw, struct sun4i_ddc, hw);
> +}
> +
> +static unsigned long sun4i_ddc_calc_divider(unsigned long rate,
> + unsigned long parent_rate,
> + u8 *m, u8 *n)
> +{
> + unsigned long best_rate = 0;
> + u8 best_m = 0, best_n = 0, _m, _n;
> +
> + for (_m = 0; _m < 8; _m++) {
> + for (_n = 0; _n < 8; _n++) {
> + unsigned long tmp_rate;
> +
> + tmp_rate = (((parent_rate / 2) / 10) >> _n) / (_m + 1);
> +
> + if (tmp_rate > rate)
> + continue;
> +
> + if (abs(rate - tmp_rate) < abs(rate - best_rate)) {
> + best_rate = tmp_rate;
> + best_m = _m;
> + best_n = _n;
> + }
> + }
> + }
> +
> + if (m && n) {
> + *m = best_m;
> + *n = best_n;
> + }
> +
> + return best_rate;
> +}
> +
> +static long sun4i_ddc_round_rate(struct clk_hw *hw, unsigned long rate,
> + unsigned long *prate)
> +{
> + return sun4i_ddc_calc_divider(rate, *prate, NULL, NULL);
> +}
> +
> +static unsigned long sun4i_ddc_recalc_rate(struct clk_hw *hw,
> + unsigned long parent_rate)
> +{
> + struct sun4i_ddc *ddc = hw_to_ddc(hw);
> + u32 reg;
> + u8 m, n;
> +
> + reg = readl(ddc->hdmi->base + SUN4I_HDMI_DDC_CLK_REG);
> + m = (reg >> 3) & 0x7;
> + n = reg & 0x7;
> +
> + return (((parent_rate / 2) / 10) >> n) / (m + 1);
> +}
> +
> +static int sun4i_ddc_set_rate(struct clk_hw *hw, unsigned long rate,
> + unsigned long parent_rate)
> +{
> + struct sun4i_ddc *ddc = hw_to_ddc(hw);
> + u8 div_m, div_n;
> +
> + sun4i_ddc_calc_divider(rate, parent_rate, &div_m, &div_n);
> +
> + writel(SUN4I_HDMI_DDC_CLK_M(div_m) | SUN4I_HDMI_DDC_CLK_N(div_n),
> + ddc->hdmi->base + SUN4I_HDMI_DDC_CLK_REG);
> +
> + return 0;
> +}
> +
> +static const struct clk_ops sun4i_ddc_ops = {
> + .recalc_rate = sun4i_ddc_recalc_rate,
> + .round_rate = sun4i_ddc_round_rate,
> + .set_rate = sun4i_ddc_set_rate,
> +};
> +
> +int sun4i_ddc_create(struct sun4i_hdmi *hdmi, struct clk *parent)
> +{
> + struct clk_init_data init;
> + struct sun4i_ddc *ddc;
> + const char *parent_name;
> +
> + parent_name = __clk_get_name(parent);
> + if (!parent_name)
> + return -ENODEV;
> +
> + ddc = devm_kzalloc(hdmi->dev, sizeof(*ddc), GFP_KERNEL);
> + if (!ddc)
> + return -ENOMEM;
> +
> + init.name = "hdmi-ddc";
> + init.ops = &sun4i_ddc_ops;
> + init.parent_names = &parent_name;
> + init.num_parents = 1;
> +
> + ddc->hdmi = hdmi;
> + ddc->hw.init = &init;
> +
> + hdmi->ddc_clk = devm_clk_register(hdmi->dev, &ddc->hw);
> + if (IS_ERR(hdmi->ddc_clk))
> + return PTR_ERR(hdmi->ddc_clk);
> +
> + return 0;
> +}
> diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
> new file mode 100644
> index 000000000000..9bec23164f53
> --- /dev/null
> +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
> @@ -0,0 +1,493 @@
> +/*
> + * Copyright (C) 2016 Maxime Ripard
> + *
> + * Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + */
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_edid.h>
> +#include <drm/drm_encoder.h>
> +#include <drm/drm_of.h>
> +#include <drm/drm_panel.h>
> +
> +#include <linux/clk.h>
> +#include <linux/component.h>
> +#include <linux/iopoll.h>
> +#include <linux/platform_device.h>
> +#include <linux/pm_runtime.h>
> +
> +#include "sun4i_backend.h"
> +#include "sun4i_drv.h"
> +#include "sun4i_hdmi.h"
> +#include "sun4i_tcon.h"
> +
> +#define DDC_SEGMENT_ADDR 0x30
> +
> +static inline struct sun4i_hdmi *
> +drm_encoder_to_sun4i_hdmi(struct drm_encoder *encoder)
> +{
> + return container_of(encoder, struct sun4i_hdmi,
> + encoder);
> +}
> +
> +static inline struct sun4i_hdmi *
> +drm_connector_to_sun4i_hdmi(struct drm_connector *connector)
> +{
> + return container_of(connector, struct sun4i_hdmi,
> + connector);
> +}
> +
> +static int sun4i_hdmi_setup_avi_infoframes(struct sun4i_hdmi *hdmi,
> + struct drm_display_mode *mode)
> +{
> + struct hdmi_avi_infoframe frame;
> + u8 buffer[17];
> + int i, ret;
> +
> + ret = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
> + if (ret < 0) {
> + DRM_ERROR("Failed to get infoframes from mode\n");
> + return ret;
> + }
> +
> + ret = hdmi_avi_infoframe_pack(&frame, buffer, sizeof(buffer));
> + if (ret < 0) {
> + DRM_ERROR("Failed to pack infoframes\n");
> + return ret;
> + }
> +
> + for (i = 0; i < sizeof(buffer); i++)
> + writeb(buffer[i], hdmi->base + SUN4I_HDMI_AVI_INFOFRAME_REG(i));
> +
> + return 0;
> +}
> +
> +static int sun4i_hdmi_atomic_check(struct drm_encoder *encoder,
> + struct drm_crtc_state *crtc_state,
> + struct drm_connector_state *conn_state)
> +{
> + struct drm_display_mode *mode = &crtc_state->mode;
> +
> + if (mode->flags & DRM_MODE_FLAG_DBLCLK)
> + return -EINVAL;
> +
> + return 0;
> +}
> +
> +static void sun4i_hdmi_disable(struct drm_encoder *encoder)
> +{
> + struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
> + struct sun4i_drv *drv = hdmi->drv;
> + struct sun4i_tcon *tcon = drv->tcon;
I assume you didn't take into consideration the latest patches I sent
that remove this field.
Instead you'll want to do drm_crtc_to_sun4i_crtc(encoder->crtc)->tcon.
> + u32 val;
> +
> + DRM_DEBUG_DRIVER("Disabling the HDMI Output\n");
> +
> + val = readl(hdmi->base + SUN4I_HDMI_VID_CTRL_REG);
> + val &= ~SUN4I_HDMI_VID_CTRL_ENABLE;
> + writel(val, hdmi->base + SUN4I_HDMI_VID_CTRL_REG);
> +
> + sun4i_tcon_channel_disable(tcon, 1);
> +}
> +
> +static void sun4i_hdmi_enable(struct drm_encoder *encoder)
> +{
> + struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
> + struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
> + struct sun4i_drv *drv = hdmi->drv;
> + struct sun4i_tcon *tcon = drv->tcon;
> + u32 val = 0;
> +
> + DRM_DEBUG_DRIVER("Enabling the HDMI Output\n");
> +
> + sun4i_tcon_channel_enable(tcon, 1);
> +
> + sun4i_hdmi_setup_avi_infoframes(hdmi, mode);
> + val |= SUN4I_HDMI_PKT_CTRL_TYPE(0, SUN4I_HDMI_PKT_AVI);
> + val |= SUN4I_HDMI_PKT_CTRL_TYPE(1, SUN4I_HDMI_PKT_END);
> + writel(val, hdmi->base + SUN4I_HDMI_PKT_CTRL_REG(0));
> +
> + val = SUN4I_HDMI_VID_CTRL_ENABLE;
> + if (hdmi->hdmi_monitor)
> + val |= SUN4I_HDMI_VID_CTRL_HDMI_MODE;
> +
> + writel(val, hdmi->base + SUN4I_HDMI_VID_CTRL_REG);
> +}
> +
> +static void sun4i_hdmi_mode_set(struct drm_encoder *encoder,
> + struct drm_display_mode *mode,
> + struct drm_display_mode *adjusted_mode)
> +{
> + struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
> + struct sun4i_drv *drv = hdmi->drv;
> + struct sun4i_tcon *tcon = drv->tcon;
> + unsigned int x, y;
> + u32 val;
> +
> + sun4i_tcon1_mode_set(tcon, mode);
> + sun4i_tcon_set_mux(tcon, 1, encoder);
> +
> + clk_set_rate(tcon->sclk1, mode->crtc_clock * 1000);
> + clk_set_rate(hdmi->mod_clk, mode->crtc_clock * 1000);
> + clk_set_rate(hdmi->tmds_clk, mode->crtc_clock * 1000);
> +
> + /* Set input sync enable */
> + writel(SUN4I_HDMI_UNKNOWN_INPUT_SYNC,
> + hdmi->base + SUN4I_HDMI_UNKNOWN_REG);
> +
> + /* Setup timing registers */
> + writel(SUN4I_HDMI_VID_TIMING_X(mode->hdisplay) |
> + SUN4I_HDMI_VID_TIMING_Y(mode->vdisplay),
I can't figure out whether we should use mode->crtc_* or not...
> + hdmi->base + SUN4I_HDMI_VID_TIMING_ACT_REG);
> +
> + x = mode->htotal - mode->hsync_start;
> + y = mode->vtotal - mode->vsync_start;
> + writel(SUN4I_HDMI_VID_TIMING_X(x) | SUN4I_HDMI_VID_TIMING_Y(y),
> + hdmi->base + SUN4I_HDMI_VID_TIMING_BP_REG);
> +
> + x = mode->hsync_start - mode->hdisplay;
> + y = mode->vsync_start - mode->vdisplay;
> + writel(SUN4I_HDMI_VID_TIMING_X(x) | SUN4I_HDMI_VID_TIMING_Y(y),
> + hdmi->base + SUN4I_HDMI_VID_TIMING_FP_REG);
> +
> + x = mode->hsync_end - mode->hsync_start;
> + y = mode->vsync_end - mode->vsync_start;
> + writel(SUN4I_HDMI_VID_TIMING_X(x) | SUN4I_HDMI_VID_TIMING_Y(y),
> + hdmi->base + SUN4I_HDMI_VID_TIMING_SPW_REG);
> +
> + val = SUN4I_HDMI_VID_TIMING_POL_TX_CLK;
> + if (mode->flags & DRM_MODE_FLAG_PHSYNC)
> + val |= SUN4I_HDMI_VID_TIMING_POL_HSYNC;
> +
> + if (mode->flags & DRM_MODE_FLAG_PVSYNC)
> + val |= SUN4I_HDMI_VID_TIMING_POL_VSYNC;
> +
> + writel(val, hdmi->base + SUN4I_HDMI_VID_TIMING_POL_REG);
> +}
> +
> +static const struct drm_encoder_helper_funcs sun4i_hdmi_helper_funcs = {
> + .atomic_check = sun4i_hdmi_atomic_check,
> + .disable = sun4i_hdmi_disable,
> + .enable = sun4i_hdmi_enable,
> + .mode_set = sun4i_hdmi_mode_set,
> +};
> +
> +static const struct drm_encoder_funcs sun4i_hdmi_funcs = {
> + .destroy = drm_encoder_cleanup,
> +};
> +
> +static int sun4i_hdmi_read_sub_block(struct sun4i_hdmi *hdmi,
> + unsigned int blk, unsigned int offset,
> + u8 *buf, unsigned int count)
> +{
> + unsigned long reg;
> + int i;
> +
> + reg = readl(hdmi->base + SUN4I_HDMI_DDC_CTRL_REG);
> + reg &= ~SUN4I_HDMI_DDC_CTRL_FIFO_DIR_MASK;
> + writel(reg | SUN4I_HDMI_DDC_CTRL_FIFO_DIR_READ,
> + hdmi->base + SUN4I_HDMI_DDC_CTRL_REG);
> +
> + writel(SUN4I_HDMI_DDC_ADDR_SEGMENT(offset >> 8) |
> + SUN4I_HDMI_DDC_ADDR_EDDC(DDC_SEGMENT_ADDR << 1) |
> + SUN4I_HDMI_DDC_ADDR_OFFSET(offset) |
> + SUN4I_HDMI_DDC_ADDR_SLAVE(DDC_ADDR),
> + hdmi->base + SUN4I_HDMI_DDC_ADDR_REG);
> +
> + reg = readl(hdmi->base + SUN4I_HDMI_DDC_FIFO_CTRL_REG);
> + writel(reg | SUN4I_HDMI_DDC_FIFO_CTRL_CLEAR,
> + hdmi->base + SUN4I_HDMI_DDC_FIFO_CTRL_REG);
> +
> + writel(count, hdmi->base + SUN4I_HDMI_DDC_BYTE_COUNT_REG);
> + writel(SUN4I_HDMI_DDC_CMD_EXPLICIT_EDDC_READ,
> + hdmi->base + SUN4I_HDMI_DDC_CMD_REG);
> +
> + reg = readl(hdmi->base + SUN4I_HDMI_DDC_CTRL_REG);
> + writel(reg | SUN4I_HDMI_DDC_CTRL_START_CMD,
> + hdmi->base + SUN4I_HDMI_DDC_CTRL_REG);
> +
> + if (readl_poll_timeout(hdmi->base + SUN4I_HDMI_DDC_CTRL_REG, reg,
> + !(reg & SUN4I_HDMI_DDC_CTRL_START_CMD),
> + 100, 100000))
> + return -EIO;
> +
> + for (i = 0; i < count; i++)
> + buf[i] = readb(hdmi->base + SUN4I_HDMI_DDC_FIFO_DATA_REG);
> +
> + return 0;
> +}
> +
> +static int sun4i_hdmi_read_edid_block(void *data, u8 *buf, unsigned int blk,
> + size_t length)
> +{
> + struct sun4i_hdmi *hdmi = data;
> + int retry = 2, i;
> +
> + do {
> + for (i = 0; i < length; i += SUN4I_HDMI_DDC_FIFO_SIZE) {
> + unsigned char offset = blk * EDID_LENGTH + i;
> + unsigned int count = min((unsigned int)SUN4I_HDMI_DDC_FIFO_SIZE,
> + length - i);
> + int ret;
> +
> + ret = sun4i_hdmi_read_sub_block(hdmi, blk, offset,
> + buf + i, count);
> + if (ret)
> + return ret;
> + }
> + } while (!drm_edid_block_valid(buf, blk, true, NULL) && (retry--));
> +
> + return 0;
> +}
> +
> +static int sun4i_hdmi_get_modes(struct drm_connector *connector)
> +{
> + struct sun4i_hdmi *hdmi = drm_connector_to_sun4i_hdmi(connector);
> + unsigned long reg;
> + struct edid *edid;
> + int ret;
> +
> + /* Reset i2c controller */
> + writel(SUN4I_HDMI_DDC_CTRL_ENABLE | SUN4I_HDMI_DDC_CTRL_RESET,
> + hdmi->base + SUN4I_HDMI_DDC_CTRL_REG);
> + if (readl_poll_timeout(hdmi->base + SUN4I_HDMI_DDC_CTRL_REG, reg,
> + !(reg & SUN4I_HDMI_DDC_CTRL_RESET),
> + 100, 2000))
> + return -EIO;
> +
> + writel(SUN4I_HDMI_DDC_LINE_CTRL_SDA_ENABLE |
> + SUN4I_HDMI_DDC_LINE_CTRL_SCL_ENABLE,
> + hdmi->base + SUN4I_HDMI_DDC_LINE_CTRL_REG);
> +
> + clk_set_rate(hdmi->ddc_clk, 100000);
You might want to explicitly enable the DDC clk around the following call.
> +
> + edid = drm_do_get_edid(connector, sun4i_hdmi_read_edid_block, hdmi);
> + if (!edid)
> + return 0;
> +
> + hdmi->hdmi_monitor = drm_detect_hdmi_monitor(edid);
> + DRM_DEBUG_DRIVER("Monitor is %s monitor\n",
> + hdmi->hdmi_monitor ? "an HDMI" : "a DVI");
> +
> + drm_mode_connector_update_edid_property(connector, edid);
> + ret = drm_add_edid_modes(connector, edid);
> + kfree(edid);
> +
> + return ret;
> +}
> +
> +static const struct drm_connector_helper_funcs sun4i_hdmi_connector_helper_funcs = {
> + .get_modes = sun4i_hdmi_get_modes,
> +};
> +
> +static enum drm_connector_status
> +sun4i_hdmi_connector_detect(struct drm_connector *connector, bool force)
> +{
> + struct sun4i_hdmi *hdmi = drm_connector_to_sun4i_hdmi(connector);
> + unsigned long reg;
> +
> + if (readl_poll_timeout(hdmi->base + SUN4I_HDMI_HPD_REG, reg,
> + reg & SUN4I_HDMI_HPD_HIGH,
> + 0, 500000))
> + return connector_status_disconnected;
> +
> + return connector_status_connected;
> +}
> +
> +static const struct drm_connector_funcs sun4i_hdmi_connector_funcs = {
> + .dpms = drm_atomic_helper_connector_dpms,
> + .detect = sun4i_hdmi_connector_detect,
> + .fill_modes = drm_helper_probe_single_connector_modes,
> + .destroy = drm_connector_cleanup,
> + .reset = drm_atomic_helper_connector_reset,
> + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
> + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
> +};
> +
> +static int sun4i_hdmi_bind(struct device *dev, struct device *master,
> + void *data)
> +{
> + struct platform_device *pdev = to_platform_device(dev);
> + struct drm_device *drm = data;
> + struct sun4i_drv *drv = drm->dev_private;
> + struct sun4i_hdmi *hdmi;
> + struct resource *res;
> + u32 reg;
> + int ret;
> +
> + hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
> + if (!hdmi)
> + return -ENOMEM;
> + dev_set_drvdata(dev, hdmi);
> + hdmi->dev = dev;
> + hdmi->drv = drv;
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + hdmi->base = devm_ioremap_resource(dev, res);
> + if (IS_ERR(hdmi->base)) {
> + dev_err(dev, "Couldn't map the HDMI encoder registers\n");
> + return PTR_ERR(hdmi->base);
> + }
> +
> + hdmi->bus_clk = devm_clk_get(dev, "ahb");
> + if (IS_ERR(hdmi->bus_clk)) {
> + dev_err(dev, "Couldn't get the HDMI bus clock\n");
> + return PTR_ERR(hdmi->bus_clk);
> + }
> + clk_prepare_enable(hdmi->bus_clk);
> +
> + hdmi->mod_clk = devm_clk_get(dev, "mod");
> + if (IS_ERR(hdmi->mod_clk)) {
> + dev_err(dev, "Couldn't get the HDMI mod clock\n");
> + return PTR_ERR(hdmi->mod_clk);
> + }
> + clk_prepare_enable(hdmi->mod_clk);
> +
> + hdmi->pll0_clk = devm_clk_get(dev, "pll-0");
> + if (IS_ERR(hdmi->pll0_clk)) {
> + dev_err(dev, "Couldn't get the HDMI PLL 0 clock\n");
> + return PTR_ERR(hdmi->pll0_clk);
> + }
> +
> + hdmi->pll1_clk = devm_clk_get(dev, "pll-1");
> + if (IS_ERR(hdmi->pll1_clk)) {
> + dev_err(dev, "Couldn't get the HDMI PLL 1 clock\n");
> + return PTR_ERR(hdmi->pll1_clk);
> + }
> +
> + ret = sun4i_tmds_create(hdmi);
> + if (ret) {
> + dev_err(dev, "Couldn't create the TMDS clock\n");
> + return ret;
> + }
> +
> + writel(SUN4I_HDMI_CTRL_ENABLE, hdmi->base + SUN4I_HDMI_CTRL_REG);
> +
> + writel(SUN4I_HDMI_PAD_CTRL0_TXEN | SUN4I_HDMI_PAD_CTRL0_CKEN |
> + SUN4I_HDMI_PAD_CTRL0_PWENG | SUN4I_HDMI_PAD_CTRL0_PWEND |
> + SUN4I_HDMI_PAD_CTRL0_PWENC | SUN4I_HDMI_PAD_CTRL0_LDODEN |
> + SUN4I_HDMI_PAD_CTRL0_LDOCEN | SUN4I_HDMI_PAD_CTRL0_BIASEN,
> + hdmi->base + SUN4I_HDMI_PAD_CTRL0_REG);
> +
> + /*
> + * We can't just initialize the register there, we need to
> + * protect the clock bits that have already been read out and
> + * cached by the clock framework.
> + */
> + reg = readl(hdmi->base + SUN4I_HDMI_PAD_CTRL1_REG);
> + reg = reg & SUN4I_HDMI_PAD_CTRL1_HALVE_CLK;
Nit: just use the &= short hand.
> + reg |= SUN4I_HDMI_PAD_CTRL1_REG_AMP(6) |
> + SUN4I_HDMI_PAD_CTRL1_REG_EMP(2) |
> + SUN4I_HDMI_PAD_CTRL1_REG_DENCK |
> + SUN4I_HDMI_PAD_CTRL1_REG_DEN |
> + SUN4I_HDMI_PAD_CTRL1_EMPCK_OPT |
> + SUN4I_HDMI_PAD_CTRL1_EMP_OPT |
> + SUN4I_HDMI_PAD_CTRL1_AMPCK_OPT |
> + SUN4I_HDMI_PAD_CTRL1_AMP_OPT;
> + writel(reg, hdmi->base + SUN4I_HDMI_PAD_CTRL1_REG);
> +
> + reg = readl(hdmi->base + SUN4I_HDMI_PLL_CTRL_REG);
> + reg = reg & SUN4I_HDMI_PLL_CTRL_DIV_MASK;
Same here.
> + reg |= SUN4I_HDMI_PLL_CTRL_VCO_S(8) | SUN4I_HDMI_PLL_CTRL_CS(7) |
> + SUN4I_HDMI_PLL_CTRL_CP_S(239) | SUN4I_HDMI_PLL_CTRL_S(7) |
> + SUN4I_HDMI_PLL_CTRL_VCO_GAIN(4) | SUN4I_HDMI_PLL_CTRL_SDIV2 |
> + SUN4I_HDMI_PLL_CTRL_LDO2_EN | SUN4I_HDMI_PLL_CTRL_LDO1_EN |
> + SUN4I_HDMI_PLL_CTRL_HV_IS_33 | SUN4I_HDMI_PLL_CTRL_BWS |
> + SUN4I_HDMI_PLL_CTRL_PLL_EN;
> + writel(reg, hdmi->base + SUN4I_HDMI_PLL_CTRL_REG);
> +
> + ret = sun4i_ddc_create(hdmi, hdmi->tmds_clk);
> + if (ret) {
> + dev_err(dev, "Couldn't create the DDC clock\n");
> + return ret;
> + }
> +
> + drm_encoder_helper_add(&hdmi->encoder,
> + &sun4i_hdmi_helper_funcs);
> + ret = drm_encoder_init(drm,
> + &hdmi->encoder,
> + &sun4i_hdmi_funcs,
> + DRM_MODE_ENCODER_TMDS,
> + NULL);
> + if (ret) {
> + dev_err(dev, "Couldn't initialise the HDMI encoder\n");
> + return ret;
> + }
> +
> + hdmi->encoder.possible_crtcs = drm_of_find_possible_crtcs(drm,
> + dev->of_node);
> + if (!hdmi->encoder.possible_crtcs)
> + return ret;
You need a valid error return value here. Maybe -EPROBE_DEFER?
> +
> + drm_connector_helper_add(&hdmi->connector,
> + &sun4i_hdmi_connector_helper_funcs);
/* There is no HPD interrupt, so we need to poll the controller */
hdmi->connector.polled = DRM_CONNECTOR_POLL_CONNECT |
DRM_CONNECTOR_POLL_DISCONNECT;
> + ret = drm_connector_init(drm, &hdmi->connector,
> + &sun4i_hdmi_connector_funcs,
> + DRM_MODE_CONNECTOR_HDMIA);
> + if (ret) {
> + dev_err(dev,
> + "Couldn't initialise the HDMI connector\n");
> + goto err_cleanup_connector;
> + }
> +
> + drm_mode_connector_attach_encoder(&hdmi->connector, &hdmi->encoder);
> +
> + return 0;
> +
> +err_cleanup_connector:
> + drm_encoder_cleanup(&hdmi->encoder);
> + return ret;
> +}
> +
> +static void sun4i_hdmi_unbind(struct device *dev, struct device *master,
> + void *data)
> +{
> + struct sun4i_hdmi *hdmi = dev_get_drvdata(dev);
> +
> + drm_connector_cleanup(&hdmi->connector);
> + drm_encoder_cleanup(&hdmi->encoder);
> +}
> +
> +static const struct component_ops sun4i_hdmi_ops = {
> + .bind = sun4i_hdmi_bind,
> + .unbind = sun4i_hdmi_unbind,
> +};
> +
> +static int sun4i_hdmi_probe(struct platform_device *pdev)
> +{
> + return component_add(&pdev->dev, &sun4i_hdmi_ops);
> +}
> +
> +static int sun4i_hdmi_remove(struct platform_device *pdev)
> +{
> + component_del(&pdev->dev, &sun4i_hdmi_ops);
> +
> + return 0;
> +}
> +
> +static const struct of_device_id sun4i_hdmi_of_table[] = {
> + { .compatible = "allwinner,sun5i-a10s-hdmi" },
> + { }
> +};
> +MODULE_DEVICE_TABLE(of, sun4i_hdmi_of_table);
> +
> +static struct platform_driver sun4i_hdmi_driver = {
> + .probe = sun4i_hdmi_probe,
> + .remove = sun4i_hdmi_remove,
> + .driver = {
> + .name = "sun4i-hdmi",
> + .of_match_table = sun4i_hdmi_of_table,
> + },
> +};
> +module_platform_driver(sun4i_hdmi_driver);
> +
> +MODULE_AUTHOR("Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>");
> +MODULE_DESCRIPTION("Allwinner A10 HDMI Driver");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c
> new file mode 100644
> index 000000000000..5cf2527bffc8
> --- /dev/null
> +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c
> @@ -0,0 +1,225 @@
> +/*
> + * Copyright (C) 2016 Free Electrons
> + * Copyright (C) 2016 NextThing Co
> + *
> + * Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + */
> +
> +#include <linux/clk-provider.h>
> +
> +#include "sun4i_tcon.h"
> +#include "sun4i_hdmi.h"
> +
> +struct sun4i_tmds {
> + struct clk_hw hw;
> + struct sun4i_hdmi *hdmi;
> +};
> +
> +static inline struct sun4i_tmds *hw_to_tmds(struct clk_hw *hw)
> +{
> + return container_of(hw, struct sun4i_tmds, hw);
> +}
> +
> +
> +static unsigned long sun4i_tmds_calc_divider(unsigned long rate,
> + unsigned long parent_rate,
> + u8 *div,
> + bool *half)
> +{
> + unsigned long best_rate = 0;
> + u8 best_m = 0, m;
> + bool is_double;
> +
> + for (m = 1; m < 16; m++) {
> + u8 d;
> +
> + for (d = 1; d < 3; d++) {
> + unsigned long tmp_rate;
> +
> + tmp_rate = parent_rate / m / d;
> +
> + if (tmp_rate > rate)
> + continue;
> +
> + if (!best_rate ||
> + (rate - tmp_rate) < (rate - best_rate)) {
> + best_rate = tmp_rate;
> + best_m = m;
> + is_double = d;
> + }
> + }
> + }
> +
> + if (div && half) {
> + *div = best_m;
> + *half = is_double;
> + }
> +
> + return best_rate;
> +}
> +
> +
> +static int sun4i_tmds_determine_rate(struct clk_hw *hw,
> + struct clk_rate_request *req)
> +{
> + struct clk_hw *parent;
> + unsigned long best_parent = 0;
> + unsigned long rate = req->rate;
> + int best_div = 1, best_half = 1;
> + int i, j;
> +
> + /*
> + * We only consider PLL3, since the TCON is very likely to be
> + * clocked from it, and to have the same rate than our HDMI
> + * clock, so we should not need to do anything.
> + */
> +
> + parent = clk_hw_get_parent_by_index(hw, 0);
> + if (!parent)
> + return -EINVAL;
> +
> + for (i = 1; i < 3; i++) {
> + for (j = 1; j < 16; j++) {
> + unsigned long ideal = rate * i * j;
> + unsigned long rounded;
> +
> + rounded = clk_hw_round_rate(parent, ideal);
> +
> + if (rounded == ideal) {
> + best_parent = rounded;
> + best_half = i;
> + best_div = j;
> + goto out;
> + }
> +
> + if (abs(rate - rounded / i) <
> + abs(rate - best_parent / best_div)) {
> + best_parent = rounded;
> + best_div = i;
> + }
> + }
> + }
> +
> +out:
> + req->rate = best_parent / best_half / best_div;
> + req->best_parent_rate = best_parent;
> + req->best_parent_hw = parent;
> +
> + return 0;
> +}
> +
> +static unsigned long sun4i_tmds_recalc_rate(struct clk_hw *hw,
> + unsigned long parent_rate)
> +{
> + struct sun4i_tmds *tmds = hw_to_tmds(hw);
> + u32 reg;
> +
> + reg = readl(tmds->hdmi->base + SUN4I_HDMI_PAD_CTRL1_REG);
> + if (reg & SUN4I_HDMI_PAD_CTRL1_HALVE_CLK)
> + parent_rate /= 2;
> +
> + reg = readl(tmds->hdmi->base + SUN4I_HDMI_PLL_CTRL_REG);
> + reg = (reg >> 4) & 0xf;
> + if (!reg)
> + reg = 1;
> +
> + return parent_rate / reg;
> +}
> +
> +static int sun4i_tmds_set_rate(struct clk_hw *hw, unsigned long rate,
> + unsigned long parent_rate)
> +{
> + struct sun4i_tmds *tmds = hw_to_tmds(hw);
> + bool half;
> + u32 reg;
> + u8 div;
> +
> + sun4i_tmds_calc_divider(rate, parent_rate, &div, &half);
> +
> + reg = readl(tmds->hdmi->base + SUN4I_HDMI_PAD_CTRL1_REG);
> + reg &= ~SUN4I_HDMI_PAD_CTRL1_HALVE_CLK;
> + if (half)
> + reg |= SUN4I_HDMI_PAD_CTRL1_HALVE_CLK;
> + writel(reg, tmds->hdmi->base + SUN4I_HDMI_PAD_CTRL1_REG);
> +
> + reg = readl(tmds->hdmi->base + SUN4I_HDMI_PLL_CTRL_REG);
> + reg &= ~SUN4I_HDMI_PLL_CTRL_DIV_MASK;
> + writel(reg | SUN4I_HDMI_PLL_CTRL_DIV(div),
> + tmds->hdmi->base + SUN4I_HDMI_PLL_CTRL_REG);
> +
> + return 0;
> +}
> +
> +static u8 sun4i_tmds_get_parent(struct clk_hw *hw)
> +{
> + struct sun4i_tmds *tmds = hw_to_tmds(hw);
> + u32 reg;
> +
> + reg = readl(tmds->hdmi->base + SUN4I_HDMI_PLL_DBG0_REG);
> + return ((reg & SUN4I_HDMI_PLL_DBG0_TMDS_PARENT_MASK) >>
> + SUN4I_HDMI_PLL_DBG0_TMDS_PARENT_SHIFT);
> +}
> +
> +static int sun4i_tmds_set_parent(struct clk_hw *hw, u8 index)
> +{
> + struct sun4i_tmds *tmds = hw_to_tmds(hw);
> + u32 reg;
> +
> + if (index > 1)
> + return -EINVAL;
> +
> + reg = readl(tmds->hdmi->base + SUN4I_HDMI_PLL_DBG0_REG);
> + reg &= ~SUN4I_HDMI_PLL_DBG0_TMDS_PARENT_MASK;
> + writel(reg | SUN4I_HDMI_PLL_DBG0_TMDS_PARENT(index),
> + tmds->hdmi->base + SUN4I_HDMI_PLL_DBG0_REG);
> +
> + return 0;
> +}
> +
> +static const struct clk_ops sun4i_tmds_ops = {
> + .determine_rate = sun4i_tmds_determine_rate,
> + .recalc_rate = sun4i_tmds_recalc_rate,
> + .set_rate = sun4i_tmds_set_rate,
> +
> + .get_parent = sun4i_tmds_get_parent,
> + .set_parent = sun4i_tmds_set_parent,
> +};
> +
> +int sun4i_tmds_create(struct sun4i_hdmi *hdmi)
> +{
> + struct clk_init_data init;
> + struct sun4i_tmds *tmds;
> + const char *parents[2];
> +
> + parents[0] = __clk_get_name(hdmi->pll0_clk);
> + if (!parents[0])
> + return -ENODEV;
> +
> + parents[1] = __clk_get_name(hdmi->pll1_clk);
> + if (!parents[1])
> + return -ENODEV;
> +
> + tmds = devm_kzalloc(hdmi->dev, sizeof(*tmds), GFP_KERNEL);
> + if (!tmds)
> + return -ENOMEM;
> +
> + init.name = "hdmi-tmds";
> + init.ops = &sun4i_tmds_ops;
> + init.parent_names = parents;
> + init.num_parents = 2;
> + init.flags = CLK_SET_RATE_PARENT;
> +
> + tmds->hdmi = hdmi;
> + tmds->hw.init = &init;
> +
> + hdmi->tmds_clk = devm_clk_register(hdmi->dev, &tmds->hw);
> + if (IS_ERR(hdmi->tmds_clk))
> + return PTR_ERR(hdmi->tmds_clk);
> +
> + return 0;
> +}
> --
The rest looks good. This is coming together nicely.
Reviewed-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
^ permalink raw reply
* Re: [PATCH v2 19/20] ARM: sun5i: a10s: Add the HDMI controller node
From: Chen-Yu Tsai @ 2017-05-04 8:04 UTC (permalink / raw)
To: Maxime Ripard
Cc: Mike Turquette, Stephen Boyd, Chen-Yu Tsai, Daniel Vetter,
David Airlie, dri-devel, Mark Rutland, Rob Herring, devicetree,
linux-arm-kernel, linux-clk, linux-kernel, linux-sunxi
In-Reply-To: <1e3ddf81459adbab455b2211fe6b78bd6cf1bbec.1493812478.git-series.maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
On Wed, May 3, 2017 at 7:59 PM, Maxime Ripard
<maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> wrote:
> The A10s has an HDMI controller connected to the second TCON channel. Add
> it to our DT.
>
> Since the TV Encoder was the only channel 1 user so far, also add the
> property now that we have several users.
>
> Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> ---
> arch/arm/boot/dts/sun5i-a10s.dtsi | 50 ++++++++++++++++++++++++++++++++-
> arch/arm/boot/dts/sun5i.dtsi | 1 +-
> 2 files changed, 51 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi
> index 1e38ff80366c..c9d4ee12599d 100644
> --- a/arch/arm/boot/dts/sun5i-a10s.dtsi
> +++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
> @@ -71,7 +71,49 @@
> };
> };
>
> + display-engine {
> + compatible = "allwinner,sun5i-a10s-display-engine",
> + "allwinner,sun5i-a13-display-engine";
I assume this indicates a difference between A10s and A13, namely the former
has an HDMI controller. The compatible string should be documented.
> + allwinner,pipelines = <&fe0>;
> + };
> +
> soc@01c00000 {
> + hdmi: hdmi@01c16000 {
> + compatible = "allwinner,sun5i-a10s-hdmi";
> + reg = <0x01c16000 0x1000>;
> + interrupts = <58>;
> + clocks = <&ccu CLK_AHB_HDMI>, <&ccu CLK_HDMI>,
> + <&ccu CLK_PLL_VIDEO0_2X>,
> + <&ccu CLK_PLL_VIDEO1_2X>;
> + clock-names = "ahb", "mod", "pll-0", "pll-1";
> + dmas = <&dma SUN4I_DMA_NORMAL 16>,
> + <&dma SUN4I_DMA_NORMAL 16>,
> + <&dma SUN4I_DMA_DEDICATED 24>;
> + dma-names = "ddc-tx", "ddc-rx", "audio-tx";
> + status = "disabled";
> +
> + ports {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + hdmi_in: port@0 {
> + #address-cells = <1>;
> + #size-cells = <0>;
> + reg = <0>;
> +
> + hdmi_in_tcon0: endpoint {
Missing reg property here, since you have #address-cells = 1.
Otherwise,
Acked-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
> + remote-endpoint = <&tcon0_out_hdmi>;
> + };
> + };
> +
> + hdmi_out: port@1 {
> + #address-cells = <1>;
> + #size-cells = <0>;
> + reg = <1>;
> + };
> + };
> + };
> +
> pwm: pwm@01c20e00 {
> compatible = "allwinner,sun5i-a10s-pwm";
> reg = <0x01c20e00 0xc>;
> @@ -128,3 +170,11 @@
>
> &sram_a {
> };
> +
> +&tcon0_out {
> + tcon0_out_hdmi: endpoint@2 {
> + reg = <2>;
> + remote-endpoint = <&hdmi_in_tcon0>;
> + allwinner,tcon-channel = <1>;
> + };
> +};
> diff --git a/arch/arm/boot/dts/sun5i.dtsi b/arch/arm/boot/dts/sun5i.dtsi
> index 5175f9cc9bed..0e29f1d98a9e 100644
> --- a/arch/arm/boot/dts/sun5i.dtsi
> +++ b/arch/arm/boot/dts/sun5i.dtsi
> @@ -272,6 +272,7 @@
> tcon0_out_tve0: endpoint@1 {
> reg = <1>;
> remote-endpoint = <&tve0_in_tcon0>;
> + allwinner,tcon-channel = <1>;
> };
> };
> };
> --
> git-series 0.8.11
^ permalink raw reply
* Re: [PATCH v2 20/20] ARM: sun5i: a10s-olinuxino: Enable HDMI
From: Chen-Yu Tsai @ 2017-05-04 8:05 UTC (permalink / raw)
To: Maxime Ripard
Cc: Mike Turquette, Stephen Boyd, Chen-Yu Tsai, Daniel Vetter,
David Airlie, dri-devel, Mark Rutland, Rob Herring, devicetree,
linux-arm-kernel, linux-clk, linux-kernel, linux-sunxi
In-Reply-To: <c7ac6faa0568e6418291255af537c4b070bdea63.1493812478.git-series.maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
On Wed, May 3, 2017 at 7:59 PM, Maxime Ripard
<maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> wrote:
> The A10s Olinuxino has an HDMI connector. Make sure we can use it.
>
> Acked-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
> Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> ---
> arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts | 29 +++++++++++++++++-
> 1 file changed, 29 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts b/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts
> index 894f874a5beb..1d13b6407222 100644
> --- a/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts
> +++ b/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts
> @@ -63,6 +63,17 @@
> stdout-path = "serial0:115200n8";
> };
>
> + connector {
> + compatible = "hdmi-connector";
> + type = "a";
Just curious, should we take this into consideration when creating
drm_connector?
ChenYu
> +
> + port {
> + hdmi_con_in: endpoint {
> + remote-endpoint = <&hdmi_out_con>;
> + };
> + };
> + };
> +
> leds {
> compatible = "gpio-leds";
> pinctrl-names = "default";
> @@ -76,6 +87,10 @@
> };
> };
>
> +&be0 {
> + status = "okay";
> +};
> +
> &ehci0 {
> status = "okay";
> };
> @@ -91,6 +106,16 @@
> status = "okay";
> };
>
> +&hdmi {
> + status = "okay";
> +};
> +
> +&hdmi_out {
> + hdmi_out_con: endpoint {
> + remote-endpoint = <&hdmi_con_in>;
> + };
> +};
> +
> &i2c0 {
> pinctrl-names = "default";
> pinctrl-0 = <&i2c0_pins_a>;
> @@ -248,6 +273,10 @@
> status = "okay";
> };
>
> +&tcon0 {
> + status = "okay";
> +};
> +
> &uart0 {
> pinctrl-names = "default";
> pinctrl-0 = <&uart0_pins_a>;
> --
> git-series 0.8.11
>
> --
> You received this message because you are subscribed to the Google Groups "linux-sunxi" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
> For more options, visit https://groups.google.com/d/optout.
^ permalink raw reply
* Re: [PATCH v6 0/8] mfd: Add OF device table to I2C drivers that are missing it
From: Wolfram Sang @ 2017-05-04 8:09 UTC (permalink / raw)
To: Javier Martinez Canillas
Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Tony Lindgren,
Lee Jones, Aaro Koskinen
In-Reply-To: <20170504052107.18995-1-javier-0uQlZySMnqxg9hUCZPvPmw@public.gmane.org>
[-- Attachment #1: Type: text/plain, Size: 439 bytes --]
Javier,
thanks for the series.
> Most patches can be applied independently, with the exception of patches
> 2 to 4 that should be applied in the same tree to keep bisect-ability. I
> suggest these to go through the MFD subsystem tree.
From my POV, patches 2-5 should be applied to the same tree. Since all
I2C related patches have my tag, I assume they will be picked up by MFD.
Lee, let me know if you prefer differently.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* Re: [PATCHv2 1/3] dt-bindings: display: Intel FPGA VIP drm driver Devicetree bindings
From: Ong, Hean Loong @ 2017-05-04 8:38 UTC (permalink / raw)
To: dinguyen-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org,
narmstrong-rdvid1DuHRBWk0Htik3J/w@public.gmane.org,
Vetter, Daniel, robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org
Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org,
Loh, Tien Hock, Ong-CC+yJ3UmIYqDUpFQwHEjaQ@public.gmane.org,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <803710eb-bcce-3d89-e306-5b7433f9962d-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="utf-8", Size: 4937 bytes --]
Thanks Neil.Â
On Thu, 2017-05-04 at 09:55 +0200, Neil Armstrong wrote:
> On 04/25/2017 04:06 AM, hean.loong.ong@intel.com wrote:
> >
> > From: "Ong, Hean Loong" <hean.loong.ong@intel.com>
> >
> > Device tree binding for Intel FPGA Video and Image
> > Processing Suite. The binding involved would be generated
> > from the Altera (Intel) Qsys system. The bindings would
> > set the max width, max height, buts per pixel and memory
> > port width. The device tree binding only supports the Intel
> > Arria10 devkit and its variants. Vendor name retained as
> > altr.
> >
> > Signed-off-by: Ong, Hean Loong <hean.loong.ong@intel.com>
> > ---
> > v2:
> > * Moved Device Tree bindings to
> > Documentation/devicetree/bindings/display/
> > * Added vendor name altr, to description
> > ---
> >  .../devicetree/bindings/display/altr,vip-fb2.txt   | 30
> > ++++++++++++++++++++++
> > Â 1 file changed, 30 insertions(+)
> > Â create mode 100644
> > Documentation/devicetree/bindings/display/altr,vip-fb2.txt
> >
> > diff --git a/Documentation/devicetree/bindings/display/altr,vip-
> > fb2.txt b/Documentation/devicetree/bindings/display/altr,vip-
> > fb2.txt
> > new file mode 100644
> > index 0000000..bdffefb
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/display/altr,vip-fb2.txt
> > @@ -0,0 +1,30 @@
> > +Intel Video and Image Processing(VIP) Frame Buffer II bindings
> > +
> > +Supported hardware: Arria 10 and above with display port IP
> > +
> Hi,
>
> >
> > +The drm driver for the Arria 10 devkit would require the display
> > resolution
> > +and pixel information to be included as these values are generated
> > based
> > +on the FPGA design that drives the video connector attached to the
> > drm driver
> > +Information the FPGA video IP component can be acquired from
> > +https://www.altera.com/content/dam/altera-www/global/en_US/pdfs/li
> > terature/ug/ug_vip.pdf
> The bindings should not reference the driver, but only the hardware
> and the way it is configured
> and interconnected with the system.
> Please explicit that this is an IP component that can be configured
> with explicit limits on
> the display widths and heights and memory parameters.
>
> But you should also indicate over what this IP is connected and add a
> port connected to a connector
> node in case this ip is not used on a specific board like in [1] or
> [2] :
>
> """
> Required nodes:
>
> The connections to the DU output video ports are modeled using the OF
> graph
> bindings specified in Documentation/devicetree/bindings/graph.txt.
>
> The following table lists for each supported model the port number
> corresponding to each DU output.
>
> Port 0 Port1 Port2
> Port3
> -------------------------------------------------------------------
> ----------
> Â R8A7779 (H1) DPAD 0 DPAD 1 -
> -
> """
>
> You may also need to add a "Display Port" connector binding aswell
> along the HDMI, VGA, ....
>
> I know this targets an FPGA system, so you should explicit that in
> the description.
>
> >
> > +Required properties:
> > +
> > +- compatible: "altr,vip-frame-buffer-2.0"
> You should also add model specific compatible strings for each
> supported FPGA devices.
>
> >
> > +- reg: Physical base address and length of the framebuffer
> > controller's
> > +Â Â registers.
> > +- altr,max-width: The width of the framebuffer in pixels.
> > +- altr,max-height: The height of the framebuffer in pixels.
> > +- altr,bits-per-symbol: only "8" is currently supported
> > +- altr,mem-port-width = the bus width of the avalon master port on
> > the frame reader
> What is the avalon master port ?
A memory bus that on the FPGA that interfaces with the ARM processor
> Can you add a schema to explicit how this IP is connected to the
> system ?
>
I could like to include a more detailed schema for the next updated
patch. In the mean time the details of the IP is provided on the links
below:
https://www.altera.com/products/intellectual-property/ip/interface-prot
ocols/m-alt-displayport-megacore.html
https://www.altera.com/documentation/yru1480906794402.html
but basically the idea is:
ARM/Linux -->FPGA(Avalon-MM interface)-->DisplayPort Connector
> >
> > +
> > +Example:
> > +
> > + dp_0_frame_buf: vip@100000280 {
> > + compatible = "altr,vip-frame-buffer-2.0";
> > + reg = <0x00000001 0x00000280 0x00000040>;
> > + altr,max-width = <1280>;
> > + altr,max-height = <720>;
> > + altr,bits-per-symbol = <8>;
> > + altr,mem-port-width = <128>;
> > + };
> >
>
> [1] Documentation/devicetree/bindings/display/amlogic,meson-vpu.txt
> [2] Documentation/devicetree/bindings/display/renesas,du.txt
>
> Thanks,
>
> Neil
> N§²æìr¸yúèØb²X¬¶Ç§vØ^)Þº{.nÇ+·zøzÚÞz)í
æèw*\x1fjg¬±¨\x1e¶Ý¢j.ïÛ°\½½MúgjÌæa×\x02' ©Þ¢¸\f¢·¦j:+v¨wèjØm¶ÿ¾\a«êçzZ+ùÝ¢j"ú!¶i
^ permalink raw reply
* [PATCH] arch: arm64: Define big endian of IFC for LS1043a/LS1046a
From: Prabhakar Kushwaha @ 2017-05-04 9:10 UTC (permalink / raw)
To: devicetree-u79uwXL29TY76Z2rM5mHXA, robh-DgEjT+Ai2ygdnm+yROfE0A,
mark.rutland-5wv7dgnIgG8, shawnguo-DgEjT+Ai2ygdnm+yROfE0A
Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Prabhakar Kushwaha
Integrated flash controller present in LS1043A and LS1046A is big endian.
So add big endian property in the devive tree.
Signed-off-by: Prabhakar Kushwaha <prabhakar.kushwaha-3arQi8VN3Tc@public.gmane.org>
---
arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi | 1 +
arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi | 1 +
2 files changed, 2 insertions(+)
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
index 45cface..09f1775 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
@@ -223,6 +223,7 @@
ifc: ifc@1530000 {
compatible = "fsl,ifc", "simple-bus";
reg = <0x0 0x1530000 0x0 0x10000>;
+ big-endian;
interrupts = <0 43 0x4>;
};
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
index f4b8b7e..509e6c2 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
@@ -190,6 +190,7 @@
ifc: ifc@1530000 {
compatible = "fsl,ifc", "simple-bus";
reg = <0x0 0x1530000 0x0 0x10000>;
+ big-endian;
interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
};
--
2.7.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH] arm: arm64: Add flash node for ls1088a qds and rdb
From: Prabhakar Kushwaha @ 2017-05-04 9:10 UTC (permalink / raw)
To: devicetree, robh, mark.rutland, shawnguo
Cc: Prabhakar Kushwaha, linux-arm-kernel
In-Reply-To: <1493889032-20857-1-git-send-email-prabhakar.kushwaha@nxp.com>
LS1088AQDS consist of NOR, NAND and FPGA connected over IFC
LS1088ARDB consist of NAND and FPGA connected over IFC.
So add flash information in ifc node of device tree.
Signed-off-by: Prabhakar Kushwaha <prabhakar.kushwaha@nxp.com>
---
arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts | 27 +++++++++++++++++++++++
arch/arm64/boot/dts/freescale/fsl-ls1088a-rdb.dts | 20 +++++++++++++++++
arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi | 4 ----
3 files changed, 47 insertions(+), 4 deletions(-)
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts b/arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts
index 8c3cae5..ca7eb41 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts
@@ -53,6 +53,33 @@
compatible = "fsl,ls1088a-qds", "fsl,ls1088a";
};
+&ifc {
+ #address-cells = <2>;
+ #size-cells = <1>;
+ status = "okay";
+
+ ranges = <0 0 0x5 0x80000000 0x08000000
+ 2 0 0x5 0x30000000 0x00010000
+ 3 0 0x5 0x20000000 0x00010000>;
+
+ nor@0,0 {
+ compatible = "cfi-flash";
+ reg = <0x0 0x0 0x8000000>;
+ bank-width = <2>;
+ device-width = <1>;
+ };
+
+ nand@2,0 {
+ compatible = "fsl,ifc-nand";
+ reg = <0x2 0x0 0x10000>;
+ };
+
+ fpga: board-control@3,0 {
+ compatible = "fsl,ls1088aqds-fpga", "fsl,fpga-qixis";
+ reg = <0x3 0x0 0x0000100>;
+ };
+};
+
&i2c0 {
status = "okay";
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1088a-rdb.dts b/arch/arm64/boot/dts/freescale/fsl-ls1088a-rdb.dts
index 8a04fbb..726e167 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1088a-rdb.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1088a-rdb.dts
@@ -53,6 +53,26 @@
compatible = "fsl,ls1088a-rdb", "fsl,ls1088a";
};
+&ifc {
+ #address-cells = <2>;
+ #size-cells = <1>;
+ status = "okay";
+
+ ranges = <0 0 0x5 0x30000000 0x00010000
+ 2 0 0x5 0x20000000 0x00010000>;
+
+ nand@0,0 {
+ compatible = "fsl,ifc-nand";
+ reg = <0x0 0x0 0x10000>;
+ };
+
+ fpga: board-control@2,0 {
+ compatible = "fsl,ls1088ardb-fpga", "fsl,fpga-qixis";
+ reg = <0x2 0x0 0x0000100>;
+ };
+};
+
+
&i2c0 {
status = "okay";
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
index 2946fd7..9f6bcb4 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
@@ -217,10 +217,6 @@
#address-cells = <2>;
#size-cells = <1>;
- ranges = <0 0 0x5 0x80000000 0x08000000
- 2 0 0x5 0x30000000 0x00010000
- 3 0 0x5 0x20000000 0x00010000>;
- status = "disabled";
};
i2c0: i2c@2000000 {
--
2.7.4
^ permalink raw reply related
* Re: [PATCHv2 0/3] Intel FPGA VIP Frame Buffer II DRM Driver
From: Daniel Vetter @ 2017-05-04 9:22 UTC (permalink / raw)
To: Eric Anholt
Cc: devicetree@vger.kernel.org, Ong, Hean Loong, tien.hock.loh,
dri-devel, dinguyen, Rob Herring, Daniel Vetter
In-Reply-To: <87shklznuo.fsf@eliezer.anholt.net>
On Wed, May 3, 2017 at 10:28 PM, Eric Anholt <eric@anholt.net> wrote:
>> From: Ong Hean Loong <hean.loong.ong@intel.com>
>>
>> Hi,
>>
>> The new Intel Arria10 SOC FPGA devkit has a Display Port IP component
>> which requires a new driver. This is a virtual driver in which the
>> FGPA hardware would enable the Display Port based on the information
>> and data provided from the DRM frame buffer from the OS. Basically all
>> all information with reagrds to resolution and bits per pixel are
>> pre-configured on the FPGA design and these information are fed to
>> the driver via the device tree information as part of the hardware
>> information.
>
> I started reviewing the code, but I want to make sure I understand
> what's going on:
>
> This IP core isn't displaying contents from system memory on some sort
> of actual physical display, right? It's a core that takes some input
> video stream (not described in the DT or in this driver) and stores it
> to memory?
I assumed it's the input IP core in the linked pdf, i.e. the CVI
(clocked video input). There's also a CVO (clocked video output), and
that would indeed be a misfit for drm. Definitely need to clarify this
(in the DT description).
-Daniel
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply
* Re: [PATCH v2 2/2] [media] platform: add video-multiplexer subdevice driver
From: Philipp Zabel @ 2017-05-04 9:26 UTC (permalink / raw)
To: Sakari Ailus
Cc: linux-media-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA, Steve Longerbeam, Peter Rosin,
Pavel Machek, Rob Herring, Mark Rutland, Vladimir Zapolskiy,
kernel-bIcnvbaLZ9MEGnE8C9+IrQ, Sascha Hauer, Steve Longerbeam
In-Reply-To: <20170504071703.GS7456-S+BSfZ9RZZmRSg0ZkenSGLdO1Tsj/99ntUK59QYPAWc@public.gmane.org>
Hi Sakari,
On Thu, 2017-05-04 at 10:17 +0300, Sakari Ailus wrote:
> Hi Philipp,
>
> On Thu, May 04, 2017 at 09:07:32AM +0200, Philipp Zabel wrote:
> > On Wed, 2017-05-03 at 22:28 +0300, Sakari Ailus wrote:
> > > Hi Philipp,
> > >
> > > Thanks for continuing working on this!
> > >
> > > I have some minor comments below...
> >
> > Thank you for the comments.
> >
> > [...]
> > > Could you rebase this on the V4L2 fwnode patchset here, please?
> > >
> > > <URL:https://git.linuxtv.org/sailus/media_tree.git/log/?h=v4l2-acpi>
> > >
> > > The conversion is rather simple, as shown here:
> > >
> > > <URL:https://git.linuxtv.org/sailus/media_tree.git/commit/?h=v4l2-acpi&id=679035e11bfdbea146fed5d52fb794b34dc9cea6>
> >
> > What is the status of this patchset? Will this be merged soon?
>
> I intend to send a pull request once the next rc1 tag is pulled on
> media-tree master. It depends on patches in linux-pm tree that aren't in
> media-tree yet.
I get conflicts trying to merge v4l2-acpi into v4.11 or media-tree
master. Could you provide an updated version?
regards
Philipp
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH v1 0/2] Add PCIe phy driver for some Mediatek SoCs
From: Ryder Lee @ 2017-05-04 9:31 UTC (permalink / raw)
To: Kishon Vijay Abraham I, Rob Herring
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Ryder Lee
Hi,
This patch series add PCIe phy driver and related dt-binding file for
Mediatek mt7623 SoCs families.
Changes since v1:
- revise binding document:
drop 'status' properties.
add a description to 'phy-switch' property and add vendor prefix.
Ryder Lee (2):
phy: add PCIe PHY driver for mt7623 SoCs families
dt-bindings: phy: Add documentation for Mediatek PCIe PHY
.../devicetree/bindings/phy/phy-mt7623-pcie.txt | 63 +++++
drivers/phy/Kconfig | 9 +
drivers/phy/Makefile | 1 +
drivers/phy/phy-mt7623-pcie.c | 290 +++++++++++++++++++++
4 files changed, 363 insertions(+)
create mode 100644 Documentation/devicetree/bindings/phy/phy-mt7623-pcie.txt
create mode 100644 drivers/phy/phy-mt7623-pcie.c
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH v1 1/2] phy: add PCIe PHY driver for mt7623 SoCs families
From: Ryder Lee @ 2017-05-04 9:31 UTC (permalink / raw)
To: Kishon Vijay Abraham I, Rob Herring
Cc: devicetree, Ryder Lee, linux-mediatek, linux-kernel,
linux-arm-kernel
In-Reply-To: <1493890308-6159-1-git-send-email-ryder.lee@mediatek.com>
support PCIe PHY of MT7623 SoCs families
Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
---
drivers/phy/Kconfig | 9 ++
drivers/phy/Makefile | 1 +
drivers/phy/phy-mt7623-pcie.c | 290 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 300 insertions(+)
create mode 100644 drivers/phy/phy-mt7623-pcie.c
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index dc5277a..00ab313 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -518,4 +518,13 @@ config PHY_NSP_USB3
help
Enable this to support the Broadcom Northstar plus USB3 PHY.
If unsure, say N.
+
+config PHY_MT7623_PCIE
+ tristate "Mediatek PCIe PHY driver for MT7623 SoC families"
+ depends on ARCH_MEDIATEK && OF
+ select GENERIC_PHY
+ select MFD_SYSCON
+ help
+ Say 'Y' here to add support for Mediatek PCIe PHY driver which
+ can be found on the MT7623 SoC families.
endmenu
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index e7b0feb..95032d6 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -63,3 +63,4 @@ obj-$(CONFIG_ARCH_TEGRA) += tegra/
obj-$(CONFIG_PHY_NS2_PCIE) += phy-bcm-ns2-pcie.o
obj-$(CONFIG_PHY_MESON8B_USB2) += phy-meson8b-usb2.o
obj-$(CONFIG_PHY_NSP_USB3) += phy-bcm-nsp-usb3.o
+obj-$(CONFIG_PHY_MT7623_PCIE) += phy-mt7623-pcie.o
diff --git a/drivers/phy/phy-mt7623-pcie.c b/drivers/phy/phy-mt7623-pcie.c
new file mode 100644
index 0000000..ee575ce
--- /dev/null
+++ b/drivers/phy/phy-mt7623-pcie.c
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2017 MediaTek Inc.
+ * Author: Ryder Lee <ryder.lee@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+/* Offsets of sub-segment in each port registers */
+#define PCIE_SIFSLV_PHYD_BANK2_BASE 0xa00
+#define SSUSB_SIFSLV_PHYA_BASE 0xb00
+#define SSUSB_SIFSLV_PHYA_DA_BASE 0xc00
+
+/*
+ * RX detection stable - 1 scale represent 8 reference cycles
+ * cover reference clock from 1M~100MHz, 7us~40us
+ */
+#define B2_PHYD_RXDET1 (PCIE_SIFSLV_PHYD_BANK2_BASE + 0x28)
+#define RG_SSUSB_RXDET_STB2 GENMASK(17, 9)
+#define RG_SSUSB_RXDET_STB2_VAL(x) ((0x1ff & (x)) << 9)
+
+#define B2_PHYD_RXDET2 (PCIE_SIFSLV_PHYD_BANK2_BASE + 0x2c)
+#define RG_SSUSB_RXDET_STB2_P3 GENMASK(8, 0)
+#define RG_SSUSB_RXDET_STB2_P3_VAL(x) (0x1ff & (x))
+
+#define U3_PHYA_REG0 (SSUSB_SIFSLV_PHYA_BASE + 0x00)
+#define RG_PCIE_CLKDRV_OFFSET GENMASK(3, 1)
+#define RG_PCIE_CLKDRV_OFFSET_VAL(x) ((0x3 & (x)) << 2)
+
+#define U3_PHYA_REG1 (SSUSB_SIFSLV_PHYA_BASE + 0x04)
+#define RG_PCIE_CLKDRV_AMP GENMASK(31, 29)
+#define RG_PCIE_CLKDRV_AMP_VAL(x) ((0x7 & (x)) << 29)
+
+#define DA_SSUSB_CDR_REFCK_SEL (SSUSB_SIFSLV_PHYA_DA_BASE + 0x00)
+#define RG_SSUSB_XTAL_EXT_PE1H GENMASK(13, 12)
+#define RG_SSUSB_XTAL_EXT_PE1H_VAL(x) ((0x3 & (x)) << 12)
+#define RG_SSUSB_XTAL_EXT_PE2H GENMASK(17, 16)
+#define RG_SSUSB_XTAL_EXT_PE2H_VAL(x) ((0x3 & (x)) << 16)
+
+#define DA_SSUSB_PLL_IC (SSUSB_SIFSLV_PHYA_DA_BASE + 0x0c)
+#define RG_SSUSB_PLL_IC_PE2H GENMASK(15, 12)
+#define RG_SSUSB_PLL_IC_PE2H_VAL(x) ((0xf & (x)) << 12)
+#define RG_SSUSB_PLL_BR_PE2H GENMASK(29, 28)
+#define RG_SSUSB_PLL_BR_PE2H_VAL(x) ((0x3 & (x)) << 28)
+
+#define DA_SSUSB_PLL_BC (SSUSB_SIFSLV_PHYA_DA_BASE + 0x08)
+#define RG_SSUSB_PLL_DIVEN_PE2H GENMASK(21, 19)
+#define RG_SSUSB_PLL_BC_PE2H GENMASK(7, 6)
+#define RG_SSUSB_PLL_BC_PE2H_VAL(x) ((0x3 & (x)) << 6)
+
+#define DA_SSUSB_PLL_IR (SSUSB_SIFSLV_PHYA_DA_BASE + 0x10)
+#define RG_SSUSB_PLL_IR_PE2H GENMASK(19, 16)
+#define RG_SSUSB_PLL_IR_PE2H_VAL(x) ((0xf & (x)) << 16)
+
+#define DA_SSUSB_PLL_BP (SSUSB_SIFSLV_PHYA_DA_BASE + 0x14)
+#define RG_SSUSB_PLL_BP_PE2H GENMASK(19, 16)
+#define RG_SSUSB_PLL_BP_PE2H_VAL(x) ((0xf & (x)) << 16)
+
+#define DA_SSUSB_PLL_SSC_DELTA1_REG20 (SSUSB_SIFSLV_PHYA_DA_BASE + 0x3c)
+#define RG_SSUSB_PLL_SSC_DELTA1_PE2H GENMASK(31, 16)
+#define RG_SSUSB_PLL_SSC_DELTA1_PE2H_VAL(x) ((0xffff & (x)) << 16)
+
+#define DA_SSUSB_PLL_SSC_DELTA_REG25 (SSUSB_SIFSLV_PHYA_DA_BASE + 0x48)
+#define RG_SSUSB_PLL_SSC_DELTA_PE2H GENMASK(15, 0)
+#define RG_SSUSB_PLL_SSC_DELTA_PE2H_VAL(x) (0xffff & (x))
+
+#define HIF_SYSCFG1 0x14
+#define HIF_SYSCFG1_PHY2_MASK (0x3 << 20)
+
+struct mtk_pcie_phy {
+ struct device *dev;
+ void __iomem *base;
+ struct regmap *hif;
+ struct clk *phya_ref;
+ struct phy *phy;
+};
+
+static inline u32 phy_read(struct mtk_pcie_phy *phy, u32 reg)
+{
+ return readl(phy->base + reg);
+}
+
+static inline void phy_write(struct mtk_pcie_phy *phy, u32 val, u32 reg)
+{
+ writel(val, phy->base + reg);
+}
+
+static int mtk_pcie_phy_power_on(struct phy *phy)
+{
+ struct mtk_pcie_phy *mtk_phy = phy_get_drvdata(phy);
+ int err;
+ u32 val;
+
+ /* PCIe port2 PHY is shared with USB u3phy2 */
+ if (mtk_phy->hif)
+ regmap_update_bits(mtk_phy->hif, HIF_SYSCFG1,
+ HIF_SYSCFG1_PHY2_MASK, 0);
+
+ err = clk_prepare_enable(mtk_phy->phya_ref);
+ if (err) {
+ dev_err(mtk_phy->dev, "failed to enable PCIe phy clock\n");
+ return err;
+ }
+
+ val = phy_read(mtk_phy, DA_SSUSB_CDR_REFCK_SEL);
+ val &= ~(RG_SSUSB_XTAL_EXT_PE1H | RG_SSUSB_XTAL_EXT_PE2H);
+ val |= RG_SSUSB_XTAL_EXT_PE1H_VAL(0x2) |
+ RG_SSUSB_XTAL_EXT_PE2H_VAL(0x2);
+ phy_write(mtk_phy, val, DA_SSUSB_CDR_REFCK_SEL);
+
+ /* ref clk drive */
+ val = phy_read(mtk_phy, U3_PHYA_REG1);
+ val &= ~RG_PCIE_CLKDRV_AMP;
+ val |= RG_PCIE_CLKDRV_AMP_VAL(0x4);
+ phy_write(mtk_phy, val, U3_PHYA_REG1);
+
+ val = phy_read(mtk_phy, U3_PHYA_REG0);
+ val &= ~RG_PCIE_CLKDRV_OFFSET;
+ val |= RG_PCIE_CLKDRV_OFFSET_VAL(0x1);
+ phy_write(mtk_phy, val, U3_PHYA_REG0);
+
+ /* SSC delta -5000ppm */
+ val = phy_read(mtk_phy, DA_SSUSB_PLL_SSC_DELTA1_REG20);
+ val &= ~RG_SSUSB_PLL_SSC_DELTA1_PE2H;
+ val |= RG_SSUSB_PLL_SSC_DELTA1_PE2H_VAL(0x3c);
+ phy_write(mtk_phy, val, DA_SSUSB_PLL_SSC_DELTA1_REG20);
+
+ val = phy_read(mtk_phy, DA_SSUSB_PLL_SSC_DELTA_REG25);
+ val &= ~RG_SSUSB_PLL_SSC_DELTA_PE2H;
+ val |= RG_SSUSB_PLL_SSC_DELTA_PE2H_VAL(0x36);
+ phy_write(mtk_phy, val, DA_SSUSB_PLL_SSC_DELTA_REG25);
+
+ /* change pll BW 0.6M */
+ val = phy_read(mtk_phy, DA_SSUSB_PLL_IC);
+ val &= ~RG_SSUSB_PLL_BR_PE2H;
+ val |= RG_SSUSB_PLL_BR_PE2H_VAL(0x1);
+ phy_write(mtk_phy, val, DA_SSUSB_PLL_IC);
+
+ val = phy_read(mtk_phy, DA_SSUSB_PLL_BC);
+ val &= ~(RG_SSUSB_PLL_DIVEN_PE2H | RG_SSUSB_PLL_BC_PE2H);
+ val |= RG_SSUSB_PLL_BC_PE2H_VAL(0x3);
+ phy_write(mtk_phy, val, DA_SSUSB_PLL_BC);
+
+ val = phy_read(mtk_phy, DA_SSUSB_PLL_IR);
+ val &= ~RG_SSUSB_PLL_IR_PE2H;
+ val |= RG_SSUSB_PLL_IR_PE2H_VAL(0x2);
+ phy_write(mtk_phy, val, DA_SSUSB_PLL_IR);
+
+ val = phy_read(mtk_phy, DA_SSUSB_PLL_IC);
+ val &= ~RG_SSUSB_PLL_IC_PE2H;
+ val |= RG_SSUSB_PLL_IC_PE2H_VAL(0x1);
+ phy_write(mtk_phy, val, DA_SSUSB_PLL_IC);
+
+ val = phy_read(mtk_phy, DA_SSUSB_PLL_BP);
+ val &= ~RG_SSUSB_PLL_BP_PE2H;
+ val |= RG_SSUSB_PLL_BP_PE2H_VAL(0xa);
+ phy_write(mtk_phy, val, DA_SSUSB_PLL_BP);
+
+ /* Tx Detect Rx Timing: 10us -> 5us */
+ val = phy_read(mtk_phy, B2_PHYD_RXDET1);
+ val &= ~RG_SSUSB_RXDET_STB2;
+ val |= RG_SSUSB_RXDET_STB2_VAL(0x10);
+ phy_write(mtk_phy, val, B2_PHYD_RXDET1);
+
+ val = phy_read(mtk_phy, B2_PHYD_RXDET2);
+ val &= ~RG_SSUSB_RXDET_STB2_P3;
+ val |= RG_SSUSB_RXDET_STB2_P3_VAL(0x10);
+ phy_write(mtk_phy, val, B2_PHYD_RXDET2);
+
+ /* wait for PCIe subsys(MAC layer) register to active */
+ usleep_range(2500, 3000);
+
+ return 0;
+}
+
+static int mtk_pcie_phy_power_off(struct phy *phy)
+{
+ struct mtk_pcie_phy *mtk_phy = phy_get_drvdata(phy);
+
+ clk_disable_unprepare(mtk_phy->phya_ref);
+
+ return 0;
+}
+
+static struct phy_ops mtk_pcie_phy_ops = {
+ .power_on = mtk_pcie_phy_power_on,
+ .power_off = mtk_pcie_phy_power_off,
+ .owner = THIS_MODULE,
+};
+
+static const struct of_device_id mtk_pcie_phy_of_match[];
+
+static int mtk_pcie_phy_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ const struct of_device_id *match;
+ struct phy_provider *phy_provider;
+ struct mtk_pcie_phy *mtk_phy;
+ struct resource *res;
+ struct phy *phy;
+
+ match = of_match_device(mtk_pcie_phy_of_match, &pdev->dev);
+ if (!match)
+ return -ENODEV;
+
+ mtk_phy = devm_kzalloc(&pdev->dev, sizeof(*mtk_phy), GFP_KERNEL);
+ if (!mtk_phy)
+ return -ENOMEM;
+
+ mtk_phy->dev = &pdev->dev;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ mtk_phy->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(mtk_phy->base)) {
+ dev_err(&pdev->dev, "failed to get phy base\n");
+ return PTR_ERR(mtk_phy->base);
+ }
+
+ mtk_phy->phya_ref = devm_clk_get(&pdev->dev, "pciephya_ref");
+ if (IS_ERR(mtk_phy->phya_ref)) {
+ dev_err(&pdev->dev, "error to get pciephya_ref\n");
+ return PTR_ERR(mtk_phy->phya_ref);
+ }
+
+ if (of_find_property(np, "mediatek,phy-switch", NULL)) {
+ mtk_phy->hif = syscon_regmap_lookup_by_phandle(
+ np, "mediatek,phy-switch");
+ if (IS_ERR(mtk_phy->hif)) {
+ dev_err(&pdev->dev, "missing \"mediatek,phy-switch\" phandle\n");
+ return PTR_ERR(mtk_phy->hif);
+ }
+ }
+
+ platform_set_drvdata(pdev, mtk_phy);
+ phy = devm_phy_create(&pdev->dev, NULL, &mtk_pcie_phy_ops);
+ if (IS_ERR(phy)) {
+ dev_err(&pdev->dev, "failed to create phy device\n");
+ return PTR_ERR(phy);
+ }
+
+ mtk_phy->phy = phy;
+ phy_set_drvdata(phy, mtk_phy);
+
+ phy_provider = devm_of_phy_provider_register(&pdev->dev,
+ of_phy_simple_xlate);
+ if (IS_ERR(phy_provider)) {
+ dev_err(&pdev->dev, "failed to register phy provider\n");
+ return PTR_ERR(phy_provider);
+ }
+
+ return 0;
+}
+
+static const struct of_device_id mtk_pcie_phy_of_match[] = {
+ { .compatible = "mediatek,mt7623-pcie-phy"},
+ { .compatible = "mediatek,mt2701-pcie-phy"},
+ {},
+};
+MODULE_DEVICE_TABLE(of, mtk_pcie_phy_of_match);
+
+static struct platform_driver mtk_pcie_phy_driver = {
+ .probe = mtk_pcie_phy_probe,
+ .driver = {
+ .name = "mtk-pcie-phy",
+ .of_match_table = mtk_pcie_phy_of_match,
+ }
+};
+module_platform_driver(mtk_pcie_phy_driver);
+
+MODULE_AUTHOR("Ryder Lee <ryder.lee@mediatek.com>");
+MODULE_DESCRIPTION("Mediatek PCIe PHY driver");
+MODULE_LICENSE("GPL v2");
--
1.9.1
^ permalink raw reply related
* [PATCH v1 2/2] dt-bindings: phy: Add documentation for Mediatek PCIe PHY
From: Ryder Lee @ 2017-05-04 9:31 UTC (permalink / raw)
To: Kishon Vijay Abraham I, Rob Herring
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Ryder Lee
In-Reply-To: <1493890308-6159-1-git-send-email-ryder.lee-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
Add documentation for PCIe PHY available in MT7623 series SoCs.
Signed-off-by: Ryder Lee <ryder.lee-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
---
.../devicetree/bindings/phy/phy-mt7623-pcie.txt | 63 ++++++++++++++++++++++
1 file changed, 63 insertions(+)
create mode 100644 Documentation/devicetree/bindings/phy/phy-mt7623-pcie.txt
diff --git a/Documentation/devicetree/bindings/phy/phy-mt7623-pcie.txt b/Documentation/devicetree/bindings/phy/phy-mt7623-pcie.txt
new file mode 100644
index 0000000..1309500
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/phy-mt7623-pcie.txt
@@ -0,0 +1,63 @@
+Mediatek MT7623 PCIe PHY
+-----------------------
+
+Required properties:
+ - compatible: Should contain "mediatek,mt7623-pcie-phy".
+ - reg: Base address and length of the registers.
+ - clocks: Must contain an entry in clock-names.
+ See ../clocks/clock-bindings.txt for details.
+ - clock-names: Must be "pciephya_ref"
+ - #phy-cells: Must be 0.
+
+Optional properties:
+ - mediatek,phy-switch: A phandle to the system controller, used to
+ switch the PHY on PCIe port2 which is shared with USB u3phy2.
+
+Example:
+
+ pcie0_phy: pcie-phy@1a149000 {
+ compatible = "mediatek,mt7623-pcie-phy";
+ reg = <0 0x1a149000 0 0x1000>;
+ clocks = <&clk26m>;
+ clock-names = "pciephya_ref";
+ #phy-cells = <0>;
+ };
+
+ pcie1_phy: pcie-phy@1a14a000 {
+ compatible = "mediatek,mt7623-pcie-phy";
+ reg = <0 0x1a14a000 0 0x1000>;
+ clocks = <&clk26m>;
+ clock-names = "pciephya_ref";
+ #phy-cells = <0>;
+ };
+
+ pcie2_phy: pcie-phy@1a244000 {
+ compatible = "mediatek,mt7623-pcie-phy";
+ reg = <0 0x1a244000 0 0x1000>;
+ clocks = <&clk26m>;
+ clock-names = "pciephya_ref";
+ #phy-cells = <0>;
+
+ mediatek,phy-switch = <&hifsys>;
+ };
+
+Specifying phy control of devices
+---------------------------------
+
+Device nodes should specify the configuration required in their "phys"
+property, containing a phandle to the phy node and phy-names.
+
+Example:
+
+#include <dt-bindings/phy/phy.h>
+
+pcie: pcie@1a140000 {
+ ...
+ pcie@1,0 {
+ ...
+ phys = <&pcie0_phy>;
+ phy-names = "pcie-phy0";
+ }
+ ...
+};
+
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH v2 0/2] Add PCIe host driver support for Mediatek SoCs
From: Ryder Lee @ 2017-05-04 9:32 UTC (permalink / raw)
To: Bjorn Helgaas, Rob Herring, Arnd Bergmann
Cc: devicetree, Red Hung, linux-pci, linux-kernel, Ryder Lee,
linux-mediatek, linux-arm-kernel
Hi,
This patch series add Mediatek Gen2 PCIe host controller driver and
dt-binding document. It can be found on MT7623 series SoCs.
This driver was validated using Broadcom Tigon3 and Intel(R) 82575/82576
gigabit ethernet card.
Changes since v2:
- modify Kconfig to avoid kbuild test error on some architecture.
- change compatible string.
- revise binding document:
add missing interrupt-names.
remove the board dts example and drop 'status' properties.
remove unnecessary descriptions bout standard PCI bus binding.
Changes since v1:
- add .suppress_bind_attrs.
- remove unnecessary *_valid_device() pattern.
- remove PCI_PROBE_ONLY.
- use the regular readl() instead of readl_relaxed().
- add .map_bus() and change to use pci_generic_config_read/pci_generic_config_write.
- revise dt-binding document and move nonstandard properties to root node.
- change compatible string.
- use interrupt-map property and replace mtk_pcie_map_irq() with of_irq_parse_and_map_pci().
- use the new pci_register_host_bridge() method instead of pci_scan_root_bus().
Ryder Lee (2):
PCI: mediatek: Add Mediatek PCIe host controller support
dt-bindings: pcie: Add documentation for Mediatek PCIe
.../bindings/pci/mediatek,mt7623-pcie.txt | 149 ++++++
drivers/pci/host/Kconfig | 11 +
drivers/pci/host/Makefile | 1 +
drivers/pci/host/pcie-mediatek.c | 563 +++++++++++++++++++++
4 files changed, 724 insertions(+)
create mode 100644 Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt
create mode 100644 drivers/pci/host/pcie-mediatek.c
--
1.9.1
^ permalink raw reply
* [PATCH v2 1/2] PCI: mediatek: Add Mediatek PCIe host controller support
From: Ryder Lee @ 2017-05-04 9:32 UTC (permalink / raw)
To: Bjorn Helgaas, Rob Herring, Arnd Bergmann
Cc: linux-pci, devicetree, linux-mediatek, linux-arm-kernel,
linux-kernel, Red Hung, Ryder Lee
In-Reply-To: <1493890376-6713-1-git-send-email-ryder.lee@mediatek.com>
Add support for the Mediatek PCIe Gen2 controller which can
be found on MT7623 series SoCs.
Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
---
drivers/pci/host/Kconfig | 11 +
drivers/pci/host/Makefile | 1 +
drivers/pci/host/pcie-mediatek.c | 563 +++++++++++++++++++++++++++++++++++++++
3 files changed, 575 insertions(+)
create mode 100644 drivers/pci/host/pcie-mediatek.c
diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
index f7c1d4d..aef0de9 100644
--- a/drivers/pci/host/Kconfig
+++ b/drivers/pci/host/Kconfig
@@ -174,6 +174,17 @@ config PCIE_ROCKCHIP
There is 1 internal PCIe port available to support GEN2 with
4 slots.
+config PCIE_MEDIATEK
+ bool "Mediatek PCIe controller"
+ depends on ARM && (ARCH_MEDIATEK || COMPILE_TEST)
+ depends on OF
+ depends on PCI
+ select PCIEPORTBUS
+ help
+ Say Y here if you want to enable PCIe controller support on MT7623 series
+ SoCs. There is one single root complex with 3 root ports available.
+ Each port supports Gen2 lane x1.
+
config VMD
depends on PCI_MSI && X86_64 && SRCU
tristate "Intel Volume Management Device Driver"
diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile
index 4d36866..265adff 100644
--- a/drivers/pci/host/Makefile
+++ b/drivers/pci/host/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_PCIE_IPROC_BCMA) += pcie-iproc-bcma.o
obj-$(CONFIG_PCIE_ALTERA) += pcie-altera.o
obj-$(CONFIG_PCIE_ALTERA_MSI) += pcie-altera-msi.o
obj-$(CONFIG_PCIE_ROCKCHIP) += pcie-rockchip.o
+obj-$(CONFIG_PCIE_MEDIATEK) += pcie-mediatek.o
obj-$(CONFIG_VMD) += vmd.o
# The following drivers are for devices that use the generic ACPI
diff --git a/drivers/pci/host/pcie-mediatek.c b/drivers/pci/host/pcie-mediatek.c
new file mode 100644
index 0000000..5e8c1bf
--- /dev/null
+++ b/drivers/pci/host/pcie-mediatek.c
@@ -0,0 +1,563 @@
+/*
+ * Mediatek PCIe host controller driver.
+ *
+ * Copyright (c) 2017 MediaTek Inc.
+ * Author: Ryder Lee <ryder.lee@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_pci.h>
+#include <linux/of_platform.h>
+#include <linux/pci.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/reset.h>
+
+/* PCIe shared registers */
+#define PCIE_SYS_CFG 0x00
+#define PCIE_INT_ENABLE 0x0c
+#define PCIE_CFG_ADDR 0x20
+#define PCIE_CFG_DATA 0x24
+
+/* PCIe per port registers */
+#define PCIE_BAR0_SETUP 0x10
+#define PCIE_BAR1_SETUP 0x14
+#define PCIE_BAR0_MEM_BASE 0x18
+#define PCIE_CLASS 0x34
+#define PCIE_LINK_STATUS 0x50
+
+#define PCIE_PORT_INT_EN(x) BIT(20 + (x))
+#define PCIE_PORT_PERST(x) BIT(1 + (x))
+#define PCIE_PORT_LINKUP BIT(0)
+#define PCIE_BAR_MAP_MAX GENMASK(31, 16)
+
+#define PCIE_BAR_ENABLE BIT(0)
+#define PCIE_REVISION_ID BIT(0)
+#define PCIE_CLASS_CODE (0x60400 << 8)
+#define PCIE_CONF_REG(regn) (((regn) & GENMASK(7, 2)) | \
+ ((((regn) >> 8) & GENMASK(3, 0)) << 24))
+#define PCIE_CONF_FUN(fun) (((fun) << 8) & GENMASK(10, 8))
+#define PCIE_CONF_DEV(dev) (((dev) << 11) & GENMASK(15, 11))
+#define PCIE_CONF_BUS(bus) (((bus) << 16) & GENMASK(23, 16))
+#define PCIE_CONF_ADDR(regn, fun, dev, bus) \
+ (PCIE_CONF_REG(regn) | PCIE_CONF_FUN(fun) | \
+ PCIE_CONF_DEV(dev) | PCIE_CONF_BUS(bus))
+
+/* Mediatek specific configuration registers */
+#define PCIE_FTS_NUM 0x70c
+#define PCIE_FTS_NUM_MASK GENMASK(15, 8)
+#define PCIE_FTS_NUM_L0(x) ((x) & 0xff << 8)
+
+#define PCIE_FC_CREDIT 0x73c
+#define PCIE_FC_CREDIT_MASK (GENMASK(31, 31) | GENMASK(28, 16))
+#define PCIE_FC_CREDIT_VAL(x) ((x) << 16)
+
+/**
+ * struct mtk_pcie_port - PCIe port information
+ * @base: IO mapped register base
+ * @list: port list
+ * @pcie: pointer to PCIe host info
+ * @reset: pointer to port reset control
+ * @regs: port memory region
+ * @sys_ck: pointer to bus clock
+ * @phy: pointer to phy control block
+ * @lane: lane count
+ * @index: port index
+ */
+struct mtk_pcie_port {
+ void __iomem *base;
+ struct list_head list;
+ struct mtk_pcie *pcie;
+ struct reset_control *reset;
+ struct resource regs;
+ struct clk *sys_ck;
+ struct phy *phy;
+ u32 lane;
+ u32 index;
+};
+
+/**
+ * struct mtk_pcie - PCIe host information
+ * @dev: pointer to PCIe device
+ * @base: IO mapped register Base
+ * @free_ck: free-run reference clock
+ * @io: IO resource
+ * @pio: PIO resource
+ * @mem: non-prefetchable memory resource
+ * @busn: bus range
+ * @offset: IO / Memory offset
+ * @ports: pointer to PCIe port information
+ */
+struct mtk_pcie {
+ struct device *dev;
+ void __iomem *base;
+ struct clk *free_ck;
+
+ struct resource io;
+ struct resource pio;
+ struct resource mem;
+ struct resource busn;
+ struct {
+ resource_size_t mem;
+ resource_size_t io;
+ } offset;
+ struct list_head ports;
+};
+
+static inline bool mtk_pcie_link_is_up(struct mtk_pcie_port *port)
+{
+ return !!(readl(port->base + PCIE_LINK_STATUS) &
+ PCIE_PORT_LINKUP);
+}
+
+static void mtk_pcie_port_free(struct mtk_pcie_port *port)
+{
+ struct mtk_pcie *pcie = port->pcie;
+ struct device *dev = pcie->dev;
+
+ devm_iounmap(dev, port->base);
+ devm_release_mem_region(dev, port->regs.start,
+ resource_size(&port->regs));
+ list_del(&port->list);
+ devm_kfree(dev, port);
+}
+
+static void mtk_pcie_put_resources(struct mtk_pcie *pcie)
+{
+ struct device *dev = pcie->dev;
+ struct mtk_pcie_port *port, *tmp;
+
+ list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
+ phy_power_off(port->phy);
+ clk_disable_unprepare(port->sys_ck);
+ mtk_pcie_port_free(port);
+ }
+
+ clk_disable_unprepare(pcie->free_ck);
+ pm_runtime_put_sync(dev);
+ pm_runtime_disable(dev);
+}
+
+static void __iomem *mtk_pcie_map_bus(struct pci_bus *bus,
+ unsigned int devfn, int where)
+{
+ struct pci_host_bridge *host = pci_find_host_bridge(bus);
+ struct mtk_pcie *pcie = pci_host_bridge_priv(host);
+
+ writel(PCIE_CONF_ADDR(where, PCI_FUNC(devfn), PCI_SLOT(devfn),
+ bus->number), pcie->base + PCIE_CFG_ADDR);
+
+ return pcie->base + PCIE_CFG_DATA + (where & 3);
+}
+
+static struct pci_ops mtk_pcie_ops = {
+ .map_bus = mtk_pcie_map_bus,
+ .read = pci_generic_config_read,
+ .write = pci_generic_config_write,
+};
+
+static void mtk_pcie_configure_rc(struct mtk_pcie_port *port)
+{
+ struct mtk_pcie *pcie = port->pcie;
+ u32 func = PCI_FUNC(port->index << 3);
+ u32 slot = PCI_SLOT(port->index << 3);
+ u32 val;
+
+ /* enable interrupt */
+ val = readl(pcie->base + PCIE_INT_ENABLE);
+ val |= PCIE_PORT_INT_EN(port->index);
+ writel(val, pcie->base + PCIE_INT_ENABLE);
+
+ /* map to all DDR region. We need to set it before cfg operation. */
+ writel(PCIE_BAR_MAP_MAX | PCIE_BAR_ENABLE,
+ port->base + PCIE_BAR0_SETUP);
+
+ /* configure class Code and revision ID */
+ writel(PCIE_CLASS_CODE | PCIE_REVISION_ID,
+ port->base + PCIE_CLASS);
+
+ /* configure FC credit */
+ writel(PCIE_CONF_ADDR(PCIE_FC_CREDIT, func, slot, 0),
+ pcie->base + PCIE_CFG_ADDR);
+ val = readl(pcie->base + PCIE_CFG_DATA);
+ val &= ~PCIE_FC_CREDIT_MASK;
+ val |= PCIE_FC_CREDIT_VAL(0x806c);
+ writel(PCIE_CONF_ADDR(PCIE_FC_CREDIT, func, slot, 0),
+ pcie->base + PCIE_CFG_ADDR);
+ writel(val, pcie->base + PCIE_CFG_DATA);
+
+ /* configure RC FTS number to 250 when it leaves L0s */
+ writel(PCIE_CONF_ADDR(PCIE_FTS_NUM, func, slot, 0),
+ pcie->base + PCIE_CFG_ADDR);
+ val = readl(pcie->base + PCIE_CFG_DATA);
+ val &= ~PCIE_FTS_NUM_MASK;
+ val |= PCIE_FTS_NUM_L0(0x50);
+ writel(PCIE_CONF_ADDR(PCIE_FTS_NUM, func, slot, 0),
+ pcie->base + PCIE_CFG_ADDR);
+ writel(val, pcie->base + PCIE_CFG_DATA);
+}
+
+static void mtk_pcie_assert_ports(struct mtk_pcie_port *port)
+{
+ struct mtk_pcie *pcie = port->pcie;
+ u32 val;
+
+ /* assert port PERST_N */
+ val = readl(pcie->base + PCIE_SYS_CFG);
+ val |= PCIE_PORT_PERST(port->index);
+ writel(val, pcie->base + PCIE_SYS_CFG);
+
+ /* de-assert port PERST_N */
+ val = readl(pcie->base + PCIE_SYS_CFG);
+ val &= ~PCIE_PORT_PERST(port->index);
+ writel(val, pcie->base + PCIE_SYS_CFG);
+
+ /* PCIe v2.0 need at least 100ms delay to train from Gen1 to Gen2 */
+ msleep(100);
+}
+
+static int mtk_pcie_enable_ports(struct mtk_pcie_port *port)
+{
+ struct device *dev = port->pcie->dev;
+ int err;
+
+ err = clk_prepare_enable(port->sys_ck);
+ if (err) {
+ dev_err(dev, "failed to enable port%d clock\n", port->index);
+ goto err_sys_clk;
+ }
+
+ reset_control_assert(port->reset);
+ reset_control_deassert(port->reset);
+
+ err = phy_power_on(port->phy);
+ if (err) {
+ dev_err(dev, "failed to power on port%d phy\n", port->index);
+ goto err_phy_on;
+ }
+
+ mtk_pcie_assert_ports(port);
+
+ /* if link up, then setup root port configuration space */
+ if (mtk_pcie_link_is_up(port)) {
+ mtk_pcie_configure_rc(port);
+ return 0;
+ }
+
+ dev_info(dev, "Port%d link down\n", port->index);
+
+ phy_power_off(port->phy);
+err_phy_on:
+ clk_disable_unprepare(port->sys_ck);
+ mtk_pcie_port_free(port);
+err_sys_clk:
+ return err;
+}
+
+static int mtk_pcie_parse_ports(struct mtk_pcie *pcie,
+ struct mtk_pcie_port **p,
+ struct device_node *node,
+ int index)
+{
+ struct mtk_pcie_port *port;
+ struct device *dev = pcie->dev;
+ char name[10];
+ int err;
+
+ *p = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
+ if (!*p)
+ return -ENOMEM;
+
+ port = *p;
+
+ err = of_property_read_u32(node, "num-lanes", &port->lane);
+ if (err) {
+ dev_err(dev, "missing num-lanes property\n");
+ return err;
+ }
+
+ err = of_address_to_resource(node, 0, &port->regs);
+ if (err) {
+ dev_err(dev, "failed to parse address: %d\n", err);
+ return err;
+ }
+
+ port->base = devm_ioremap_resource(dev, &port->regs);
+ if (IS_ERR(port->base)) {
+ dev_err(dev, "failed to map port%d base\n", index);
+ return PTR_ERR(port->base);
+ }
+
+ snprintf(name, sizeof(name), "sys_ck%d", index);
+ port->sys_ck = devm_clk_get(dev, name);
+ if (IS_ERR(port->sys_ck)) {
+ dev_err(dev, "failed to get port%d clock\n", index);
+ return PTR_ERR(port->sys_ck);
+ }
+
+ snprintf(name, sizeof(name), "pcie-rst%d", index);
+ port->reset = devm_reset_control_get(dev, name);
+ if (IS_ERR(port->reset)) {
+ dev_err(dev, "failed to get port%d reset\n", index);
+ return PTR_ERR(port->reset);
+ }
+
+ snprintf(name, sizeof(name), "pcie-phy%d", index);
+ port->phy = devm_phy_get(dev, name);
+ if (IS_ERR(port->phy)) {
+ dev_err(dev, "failed to get port%d phy\n", index);
+ return PTR_ERR(port->phy);
+ }
+
+ port->index = index;
+ port->pcie = pcie;
+
+ INIT_LIST_HEAD(&port->list);
+ list_add_tail(&port->list, &pcie->ports);
+ return 0;
+}
+
+static int mtk_pcie_handle_shared_resource(struct mtk_pcie *pcie)
+{
+ struct device *dev = pcie->dev;
+ struct platform_device *pdev = to_platform_device(dev);
+ struct resource *regs;
+ int err;
+
+ /* get shared registers */
+ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ pcie->base = devm_ioremap_resource(dev, regs);
+ if (IS_ERR(pcie->base)) {
+ dev_err(dev, "failed to map shared register\n");
+ return PTR_ERR(pcie->base);
+ }
+
+ pcie->free_ck = devm_clk_get(dev, "free_ck");
+ if (IS_ERR(pcie->free_ck))
+ return PTR_ERR(pcie->free_ck);
+
+ pm_runtime_enable(dev);
+ err = pm_runtime_get_sync(dev);
+ if (err)
+ goto err_pm;
+
+ /* enable top level clock */
+ err = clk_prepare_enable(pcie->free_ck);
+ if (err) {
+ dev_err(dev, "failed to enable free_ck\n");
+ goto err_free_ck;
+ }
+
+ return 0;
+
+err_free_ck:
+ pm_runtime_put_sync(dev);
+err_pm:
+ pm_runtime_disable(dev);
+
+ return err;
+}
+
+static int mtk_pcie_parse_and_add_res(struct mtk_pcie *pcie)
+{
+ struct device *dev = pcie->dev;
+ struct device_node *node = dev->of_node, *child;
+ struct of_pci_range_parser parser;
+ struct of_pci_range range;
+ struct resource res;
+ int err, linkup = 0;
+
+ /* parse shared resources */
+ err = mtk_pcie_handle_shared_resource(pcie);
+ if (err)
+ return err;
+
+ if (of_pci_range_parser_init(&parser, node)) {
+ dev_err(dev, "missing \"ranges\" property\n");
+ return -EINVAL;
+ }
+
+ for_each_of_pci_range(&parser, &range) {
+ err = of_pci_range_to_resource(&range, node, &res);
+ if (err < 0)
+ return err;
+
+ switch (res.flags & IORESOURCE_TYPE_BITS) {
+ case IORESOURCE_IO:
+ pcie->offset.io = res.start - range.pci_addr;
+
+ memcpy(&pcie->pio, &res, sizeof(res));
+ pcie->pio.name = node->full_name;
+
+ pcie->io.start = range.cpu_addr;
+ pcie->io.end = range.cpu_addr + range.size - 1;
+ pcie->io.flags = IORESOURCE_MEM;
+ pcie->io.name = "I/O";
+
+ memcpy(&res, &pcie->io, sizeof(res));
+ break;
+
+ case IORESOURCE_MEM:
+ pcie->offset.mem = res.start - range.pci_addr;
+
+ memcpy(&pcie->mem, &res, sizeof(res));
+ pcie->mem.name = "non-prefetchable";
+ break;
+ }
+ }
+
+ err = of_pci_parse_bus_range(node, &pcie->busn);
+ if (err < 0) {
+ dev_err(dev, "failed to parse ranges property: %d\n", err);
+ pcie->busn.name = node->name;
+ pcie->busn.start = 0;
+ pcie->busn.end = 0xff;
+ pcie->busn.flags = IORESOURCE_BUS;
+ }
+
+ for_each_child_of_node(node, child) {
+ struct mtk_pcie_port *port;
+ int index;
+
+ err = of_pci_get_devfn(child);
+ if (err < 0) {
+ dev_err(dev, "failed to parse devfn: %d\n", err);
+ return err;
+ }
+
+ index = PCI_SLOT(err);
+
+ if (!of_device_is_available(child))
+ continue;
+
+ err = mtk_pcie_parse_ports(pcie, &port, child, index);
+ if (err)
+ return err;
+
+ /* enable each port, and then check link status */
+ err = mtk_pcie_enable_ports(port);
+ if (!err)
+ linkup++;
+ }
+
+ return !linkup;
+}
+
+static int mtk_pcie_request_resources(struct mtk_pcie *pcie)
+{
+ struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie);
+ struct list_head *windows = &host->windows;
+ struct device *dev = pcie->dev;
+ int err;
+
+ pci_add_resource_offset(windows, &pcie->pio, pcie->offset.io);
+ pci_add_resource_offset(windows, &pcie->mem, pcie->offset.mem);
+ pci_add_resource(windows, &pcie->busn);
+
+ err = devm_request_pci_bus_resources(dev, windows);
+ if (err < 0)
+ return err;
+
+ pci_remap_iospace(&pcie->pio, pcie->io.start);
+
+ return 0;
+}
+
+static int mtk_pcie_register_host(struct pci_host_bridge *host)
+{
+ struct mtk_pcie *pcie = pci_host_bridge_priv(host);
+ struct pci_bus *child;
+ int err;
+
+ pci_add_flags(PCI_REASSIGN_ALL_RSRC | PCI_REASSIGN_ALL_BUS);
+ host->busnr = pcie->busn.start;
+ host->dev.parent = pcie->dev;
+ host->ops = &mtk_pcie_ops;
+
+ err = pci_register_host_bridge(host);
+ if (err < 0)
+ return err;
+
+ pci_scan_child_bus(host->bus);
+
+ pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
+ pci_bus_size_bridges(host->bus);
+ pci_bus_assign_resources(host->bus);
+
+ list_for_each_entry(child, &host->bus->children, node)
+ pcie_bus_configure_settings(child);
+
+ pci_bus_add_devices(host->bus);
+
+ return 0;
+}
+
+static int mtk_pcie_probe(struct platform_device *pdev)
+{
+ struct mtk_pcie *pcie;
+ struct pci_host_bridge *host;
+ int err;
+
+ host = pci_alloc_host_bridge(sizeof(*pcie));
+ if (!host)
+ return -ENOMEM;
+
+ pcie = pci_host_bridge_priv(host);
+
+ pcie->dev = &pdev->dev;
+ platform_set_drvdata(pdev, pcie);
+ INIT_LIST_HEAD(&pcie->ports);
+
+ err = mtk_pcie_parse_and_add_res(pcie);
+ if (err)
+ return err;
+
+ err = mtk_pcie_request_resources(pcie);
+ if (err)
+ goto put_resources;
+
+ err = mtk_pcie_register_host(host);
+ if (err)
+ goto put_resources;
+
+ return 0;
+
+put_resources:
+ mtk_pcie_put_resources(pcie);
+ return err;
+}
+
+static const struct of_device_id mtk_pcie_ids[] = {
+ { .compatible = "mediatek,mt7623-pcie"},
+ { .compatible = "mediatek,mt2701-pcie"},
+ {},
+};
+MODULE_DEVICE_TABLE(of, mtk_pcie_ids);
+
+static struct platform_driver mtk_pcie_driver = {
+ .probe = mtk_pcie_probe,
+ .driver = {
+ .name = "mtk-pcie",
+ .of_match_table = mtk_pcie_ids,
+ .suppress_bind_attrs = true,
+ },
+};
+
+builtin_platform_driver(mtk_pcie_driver);
+
+MODULE_DESCRIPTION("Mediatek PCIe host controller driver.");
+MODULE_LICENSE("GPL v2");
--
1.9.1
^ permalink raw reply related
* [PATCH v2 2/2] dt-bindings: pcie: Add documentation for Mediatek PCIe
From: Ryder Lee @ 2017-05-04 9:32 UTC (permalink / raw)
To: Bjorn Helgaas, Rob Herring, Arnd Bergmann
Cc: linux-pci, devicetree, linux-mediatek, linux-arm-kernel,
linux-kernel, Red Hung, Ryder Lee
In-Reply-To: <1493890376-6713-1-git-send-email-ryder.lee@mediatek.com>
Add documentation for PCIe host driver available in MT7623
series SoCs.
Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
---
.../bindings/pci/mediatek,mt7623-pcie.txt | 149 +++++++++++++++++++++
1 file changed, 149 insertions(+)
create mode 100644 Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt
diff --git a/Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt b/Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt
new file mode 100644
index 0000000..9c5d5a7
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/mediatek,mt7623-pcie.txt
@@ -0,0 +1,149 @@
+Mediatek Gen2 PCIe controller which is available on MT7623 series SoCs
+
+PCIe subsys supports single root complex (RC) with 3 Root Ports. Each root
+ports supports a Gen2 1-lane Link and has PIPE interface to PHY.
+
+Required properties:
+- compatible: Should contain "mediatek,mt7623-pcie".
+- device_type: Must be "pci"
+- reg: Base addresses and lengths of the PCIe controller.
+- #address-cells: Address representation for root ports (must be 3)
+- #size-cells: Size representation for root ports (must be 2)
+- #interrupt-cells: Size representation for interrupts (must be 1)
+- interrupts: Three interrupt outputs of the controller. Must contain an
+ entry for each entry in the interrupt-names property.
+- interrupt-names: Must include the following names
+ - "pcie-int0"
+ - "pcie-int1"
+ - "pcie-int2"
+- interrupt-map-mask and interrupt-map: Standard PCI IRQ mapping properties
+ Please refer to the standard PCI bus binding document for a more detailed
+ explanation.
+- clocks: Must contain an entry for each entry in clock-names.
+ See ../clocks/clock-bindings.txt for details.
+- clock-names: Must include the following entries:
+ - free_ck :for reference clock of PCIe subsys
+ - sys_ck0 :for clock of Port0
+ - sys_ck1 :for clock of Port1
+ - sys_ck2 :for clock of Port2
+- resets: Must contain an entry for each entry in reset-names.
+ See ../reset/reset.txt for details.
+- reset-names: Must include the following entries:
+ - pcie-rst0 :port0 reset
+ - pcie-rst1 :port1 reset
+ - pcie-rst2 :port2 reset
+- phys: list of PHY specifiers (used by generic PHY framework).
+- phy-names : must be "pcie-phy0", "pcie-phy1", "pcie-phyN".. based on the
+ number of PHYs as specified in *phys* property.
+- power-domains: A phandle and power domain specifier pair to the power domain
+ which is responsible for collapsing and restoring power to the peripheral.
+- bus-range: Range of bus numbers associated with this controller.
+- ranges:
+ - The first three entries are expected to translate the addresses for the root
+ port registers, which are referenced by the assigned-addresses property of
+ the root port nodes (see below).
+ - The remaining entries setup the mapping for the standard I/O and memory
+ regions.
+ Please refer to the standard PCI bus binding document for a more detailed
+ explanation.
+
+In addition, the device tree node must have sub-nodes describing each
+PCIe port interface, having the following mandatory properties:
+
+Required properties:
+- device_type: Must be "pci"
+- assigned-addresses: Address and size of the port configuration registers
+- reg: Only the first four bytes are used to refer to the correct bus number
+ and device number.
+- #address-cells: Must be 3
+- #size-cells: Must be 2
+- #interrupt-cells: Must be 1
+- interrupt-map-mask and interrupt-map: Standard PCI IRQ mapping properties
+ Please refer to the standard PCI bus binding document for a more detailed
+ explanation.
+- ranges: Sub-ranges distributed from the PCIe controller node. An empty
+ property is sufficient.
+- num-lanes: Number of lanes to use for this port.
+
+Examples:
+
+ hifsys: syscon@1a000000 {
+ compatible = "mediatek,mt7623-hifsys", "syscon";
+ reg = <0 0x1a000000 0 0x1000>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+ pcie: pcie-controller@1a140000 {
+ compatible = "mediatek,mt7623-pcie";
+ device_type = "pci";
+ reg = <0 0x1a140000 0 0x1000>; /* PCIe shared registers */
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ interrupts = <GIC_SPI 193 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 194 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 195 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-names = "pcie-int0", "pcie-int1", "pcie-int2";
+ interrupt-map-mask = <0xf800 0 0 0>;
+ interrupt-map = <0x0000 0 0 0 &gic GIC_SPI 193 IRQ_TYPE_NONE>,
+ <0x0800 0 0 0 &gic GIC_SPI 194 IRQ_TYPE_NONE>,
+ <0x1000 0 0 0 &gic GIC_SPI 195 IRQ_TYPE_NONE>;
+ clocks = <&topckgen CLK_TOP_ETHIF_SEL>,
+ <&hifsys CLK_HIFSYS_PCIE0>,
+ <&hifsys CLK_HIFSYS_PCIE1>,
+ <&hifsys CLK_HIFSYS_PCIE2>;
+ clock-names = "free_ck", "sys_ck0", "sys_ck1", "sys_ck2";
+ resets = <&hifsys MT2701_HIFSYS_PCIE0_RST>,
+ <&hifsys MT2701_HIFSYS_PCIE1_RST>,
+ <&hifsys MT2701_HIFSYS_PCIE2_RST>;
+ reset-names = "pcie-rst0", "pcie-rst1", "pcie-rst2";
+ phys = <&pcie0_phy>, <&pcie1_phy>, <&pcie2_phy>;
+ phy-names = "pcie-phy0", "pcie-phy1", "pcie-phy2";
+ power-domains = <&scpsys MT2701_POWER_DOMAIN_HIF>;
+ bus-range = <0x00 0xff>;
+ ranges = <0x82000000 0 0x1a142000 0 0x1a142000 0 0x1000 /* Port0 registers */
+ 0x82000000 0 0x1a143000 0 0x1a143000 0 0x1000 /* Port1 registers */
+ 0x82000000 0 0x1a144000 0 0x1a144000 0 0x1000 /* Port2 registers */
+ 0x81000000 0 0x1a160000 0 0x1a160000 0 0x00010000 /* I/O space */
+ 0x83000000 0 0x60000000 0 0x60000000 0 0x10000000>; /* memory space */
+
+ pcie@1,0 {
+ device_type = "pci";
+ assigned-addresses = <0x82000000 0 0x1a142000 0 0x1000>;
+ reg = <0x0000 0 0 0 0>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 0>;
+ interrupt-map = <0 0 0 0 &gic GIC_SPI 193 IRQ_TYPE_NONE>;
+ ranges;
+ num-lanes = <1>;
+ };
+
+ pcie@2,0 {
+ device_type = "pci";
+ assigned-addresses = <0x82000800 0 0x1a143000 0 0x1000>;
+ reg = <0x0800 0 0 0 0>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 0>;
+ interrupt-map = <0 0 0 0 &gic GIC_SPI 194 IRQ_TYPE_NONE>;
+ ranges;
+ num-lanes = <1>;
+ };
+
+ pcie@3,0 {
+ device_type = "pci";
+ assigned-addresses = <0x82001000 0 0x1a144000 0 0x1000>;
+ reg = <0x1000 0 0 0 0>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 0>;
+ interrupt-map = <0 0 0 0 &gic GIC_SPI 195 IRQ_TYPE_NONE>;
+ ranges;
+ num-lanes = <1>;
+ };
+ };
--
1.9.1
^ permalink raw reply related
* Re: [PATCH v2 2/2] [media] platform: add video-multiplexer subdevice driver
From: Sakari Ailus @ 2017-05-04 9:48 UTC (permalink / raw)
To: Philipp Zabel
Cc: linux-media-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA, Steve Longerbeam, Peter Rosin,
Pavel Machek, Rob Herring, Mark Rutland, Vladimir Zapolskiy,
kernel-bIcnvbaLZ9MEGnE8C9+IrQ, Sascha Hauer, Steve Longerbeam
In-Reply-To: <1493889978.2381.11.camel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
Hi Philipp,
On Thu, May 04, 2017 at 11:26:18AM +0200, Philipp Zabel wrote:
> Hi Sakari,
>
> On Thu, 2017-05-04 at 10:17 +0300, Sakari Ailus wrote:
> > Hi Philipp,
> >
> > On Thu, May 04, 2017 at 09:07:32AM +0200, Philipp Zabel wrote:
> > > On Wed, 2017-05-03 at 22:28 +0300, Sakari Ailus wrote:
> > > > Hi Philipp,
> > > >
> > > > Thanks for continuing working on this!
> > > >
> > > > I have some minor comments below...
> > >
> > > Thank you for the comments.
> > >
> > > [...]
> > > > Could you rebase this on the V4L2 fwnode patchset here, please?
> > > >
> > > > <URL:https://git.linuxtv.org/sailus/media_tree.git/log/?h=v4l2-acpi>
> > > >
> > > > The conversion is rather simple, as shown here:
> > > >
> > > > <URL:https://git.linuxtv.org/sailus/media_tree.git/commit/?h=v4l2-acpi&id=679035e11bfdbea146fed5d52fb794b34dc9cea6>
> > >
> > > What is the status of this patchset? Will this be merged soon?
> >
> > I intend to send a pull request once the next rc1 tag is pulled on
> > media-tree master. It depends on patches in linux-pm tree that aren't in
> > media-tree yet.
>
> I get conflicts trying to merge v4l2-acpi into v4.11 or media-tree
> master. Could you provide an updated version?
What kind of conflicts? I wonder if something somewhere is out of sync. :-)
My v4l2-acpi branch is on top of current media-tree master and appears to
merge cleanly to v4.11 as well.
It still wouldn't compile though as it depends on the fwnode graph patches.
I've merged those here:
<URL:https://git.linuxtv.org/sailus/media_tree.git/log/?h=v4l2-acpi-merge>
--
Kind regards,
Sakari Ailus
e-mail: sakari.ailus-X3B1VOXEql0@public.gmane.org XMPP: sailus-PCDdDYkjdNMDXYZnReoRVg@public.gmane.org
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v2 2/2] [media] platform: add video-multiplexer subdevice driver
From: Philipp Zabel @ 2017-05-04 10:03 UTC (permalink / raw)
To: Sakari Ailus
Cc: linux-media, devicetree, Steve Longerbeam, Peter Rosin,
Pavel Machek, Rob Herring, Mark Rutland, Vladimir Zapolskiy,
kernel, Sascha Hauer, Steve Longerbeam
In-Reply-To: <20170504094845.GV7456@valkosipuli.retiisi.org.uk>
On Thu, 2017-05-04 at 12:48 +0300, Sakari Ailus wrote:
> Hi Philipp,
>
> On Thu, May 04, 2017 at 11:26:18AM +0200, Philipp Zabel wrote:
> > Hi Sakari,
> >
> > On Thu, 2017-05-04 at 10:17 +0300, Sakari Ailus wrote:
> > > Hi Philipp,
> > >
> > > On Thu, May 04, 2017 at 09:07:32AM +0200, Philipp Zabel wrote:
> > > > On Wed, 2017-05-03 at 22:28 +0300, Sakari Ailus wrote:
> > > > > Hi Philipp,
> > > > >
> > > > > Thanks for continuing working on this!
> > > > >
> > > > > I have some minor comments below...
> > > >
> > > > Thank you for the comments.
> > > >
> > > > [...]
> > > > > Could you rebase this on the V4L2 fwnode patchset here, please?
> > > > >
> > > > > <URL:https://git.linuxtv.org/sailus/media_tree.git/log/?h=v4l2-acpi>
> > > > >
> > > > > The conversion is rather simple, as shown here:
> > > > >
> > > > > <URL:https://git.linuxtv.org/sailus/media_tree.git/commit/?h=v4l2-acpi&id=679035e11bfdbea146fed5d52fb794b34dc9cea6>
> > > >
> > > > What is the status of this patchset? Will this be merged soon?
> > >
> > > I intend to send a pull request once the next rc1 tag is pulled on
> > > media-tree master. It depends on patches in linux-pm tree that aren't in
> > > media-tree yet.
> >
> > I get conflicts trying to merge v4l2-acpi into v4.11 or media-tree
> > master. Could you provide an updated version?
>
> What kind of conflicts? I wonder if something somewhere is out of sync. :-)
> My v4l2-acpi branch is on top of current media-tree master and appears to
> merge cleanly to v4.11 as well.
>
> It still wouldn't compile though as it depends on the fwnode graph patches.
>
> I've merged those here:
>
> <URL:https://git.linuxtv.org/sailus/media_tree.git/log/?h=v4l2-acpi-merge>
My bad, I accidentally used an old git remote that still pointed to
git://git.retiisi.org.uk/~sailus/linux.git. Fixed that now.
thanks
Philipp
^ permalink raw reply
* [v2, 0/5] Add eSDHC UHS-I/HS200 mode support for ls1012a/ls1046a/ls208xa
From: Yangbo Lu @ 2017-05-04 10:48 UTC (permalink / raw)
To: devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Shawn Guo,
ulf.hansson-QSEj5FYQhm4dnm+yROfE0A, Rob Herring, Catalin Marinas,
Harninder Rai
Cc: Xiaobo Xie, Yangbo Lu
This patchset is to add eSDHC UHS-I/HS200 mode support for ls1012a/ls1046a/ls208xa.
Also add eSDHC node for ls1088a. Because eSDHC is not a standard SD controller,
the specific speed mode support depends on board's peripheral circuit for eSDHC.
So, we have to add these speed modes support on board dts file.
In additon, these dts patches depends on esdhc driver patches which just had been merged
on mmc.git. Otherwise, the UHS-I SD card and eMMC HS200 card would fail to be initialized,
but other cards still could work fine.
https://patchwork.kernel.org/patch/9689875/
https://patchwork.kernel.org/patch/9689877/
https://patchwork.kernel.org/patch/9689879/
https://patchwork.kernel.org/patch/9689887/
https://patchwork.kernel.org/patch/9689885/
Yangbo Lu (5):
mmc: dt: add compatible into eSDHC required properties
arm64: dts: ls1046a: support SD UHS-I and eMMC HS200 on RDB
arm64: dts: ls208xa: support SD UHS-I on RDB and eMMC HS200 on QDS
arm64: dts: ls1012a: add eSDHC nodes
arm64: dts: ls1088a: add esdhc node
.../devicetree/bindings/mmc/fsl-esdhc.txt | 1 +
arch/arm64/boot/dts/freescale/fsl-ls1012a-qds.dts | 8 +++++++
arch/arm64/boot/dts/freescale/fsl-ls1012a-rdb.dts | 13 +++++++++++
arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi | 25 ++++++++++++++++++++++
arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb.dts | 8 +++++++
arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi | 4 ++--
arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts | 4 ++++
arch/arm64/boot/dts/freescale/fsl-ls1088a-rdb.dts | 4 ++++
arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi | 12 +++++++++++
arch/arm64/boot/dts/freescale/fsl-ls208xa-qds.dtsi | 1 +
arch/arm64/boot/dts/freescale/fsl-ls208xa-rdb.dtsi | 4 ++++
arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi | 2 +-
12 files changed, 83 insertions(+), 3 deletions(-)
--
2.1.0.27.g96db324
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [v2, 1/5] mmc: dt: add compatible into eSDHC required properties
From: Yangbo Lu @ 2017-05-04 10:48 UTC (permalink / raw)
To: devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Shawn Guo,
ulf.hansson-QSEj5FYQhm4dnm+yROfE0A, Rob Herring, Catalin Marinas,
Harninder Rai
Cc: Xiaobo Xie, Yangbo Lu
In-Reply-To: <1493894940-47452-1-git-send-email-yangbo.lu-3arQi8VN3Tc@public.gmane.org>
This patch is to add compatible into eSDHC required properties.
Signed-off-by: Yangbo Lu <yangbo.lu-3arQi8VN3Tc@public.gmane.org>
---
Changes for v2:
- Added this patch.
---
Documentation/devicetree/bindings/mmc/fsl-esdhc.txt | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/mmc/fsl-esdhc.txt b/Documentation/devicetree/bindings/mmc/fsl-esdhc.txt
index dedfb02..b04b248 100644
--- a/Documentation/devicetree/bindings/mmc/fsl-esdhc.txt
+++ b/Documentation/devicetree/bindings/mmc/fsl-esdhc.txt
@@ -7,6 +7,7 @@ This file documents differences between the core properties described
by mmc.txt and the properties used by the sdhci-esdhc driver.
Required properties:
+ - compatible : should be "fsl,esdhc", or "fsl,<chip>-esdhc".
- interrupt-parent : interrupt source phandle.
- clock-frequency : specifies eSDHC base clock frequency.
--
2.1.0.27.g96db324
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [v2, 2/5] arm64: dts: ls1046a: support SD UHS-I and eMMC HS200 on RDB
From: Yangbo Lu @ 2017-05-04 10:48 UTC (permalink / raw)
To: devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Shawn Guo,
ulf.hansson-QSEj5FYQhm4dnm+yROfE0A, Rob Herring, Catalin Marinas,
Harninder Rai
Cc: Xiaobo Xie, Yangbo Lu
In-Reply-To: <1493894940-47452-1-git-send-email-yangbo.lu-3arQi8VN3Tc@public.gmane.org>
This patch is to enable SD UHS-I mode and eMMC HS200 mode on
LS1046ARDB in dts. Also, the eSDHC peripheral clock must be used
instead of platform clock to support these modes.
Signed-off-by: Yangbo Lu <yangbo.lu-3arQi8VN3Tc@public.gmane.org>
---
Changes for v2:
- Sorted the node.
---
arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb.dts | 8 ++++++++
arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi | 4 ++--
2 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb.dts b/arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb.dts
index c5361e9..2d28726 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb.dts
@@ -72,6 +72,14 @@
status = "okay";
};
+&esdhc {
+ mmc-hs200-1_8v;
+ sd-uhs-sdr104;
+ sd-uhs-sdr50;
+ sd-uhs-sdr25;
+ sd-uhs-sdr12;
+};
+
&i2c0 {
status = "okay";
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
index d67557f..46b7839 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
@@ -209,10 +209,10 @@
};
esdhc: esdhc@1560000 {
- compatible = "fsl,esdhc";
+ compatible = "fsl,ls1046a-esdhc", "fsl,esdhc";
reg = <0x0 0x1560000 0x0 0x10000>;
interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
- clock-frequency = <0>;
+ clocks = <&clockgen 2 1>;
voltage-ranges = <1800 1800 3300 3300>;
sdhci,auto-cmd12;
big-endian;
--
2.1.0.27.g96db324
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [v2, 3/5] arm64: dts: ls208xa: support SD UHS-I on RDB and eMMC HS200 on QDS
From: Yangbo Lu @ 2017-05-04 10:48 UTC (permalink / raw)
To: devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Shawn Guo,
ulf.hansson-QSEj5FYQhm4dnm+yROfE0A, Rob Herring, Catalin Marinas,
Harninder Rai
Cc: Xiaobo Xie, Yangbo Lu
In-Reply-To: <1493894940-47452-1-git-send-email-yangbo.lu-3arQi8VN3Tc@public.gmane.org>
This patch is to enable SD UHS-I mode on LS208xRDB and eMMC HS200
mode on LS208xQDS in dts. Also, the eSDHC peripheral clock must be
used instead of platform clock to support these modes.
Signed-off-by: Yangbo Lu <yangbo.lu-3arQi8VN3Tc@public.gmane.org>
---
Changes for v2:
- None.
---
arch/arm64/boot/dts/freescale/fsl-ls208xa-qds.dtsi | 1 +
arch/arm64/boot/dts/freescale/fsl-ls208xa-rdb.dtsi | 4 ++++
arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi | 2 +-
3 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls208xa-qds.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls208xa-qds.dtsi
index c4282d9..b237446 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls208xa-qds.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls208xa-qds.dtsi
@@ -46,6 +46,7 @@
*/
&esdhc {
+ mmc-hs200-1_8v;
status = "okay";
};
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls208xa-rdb.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls208xa-rdb.dtsi
index 9a1d0d2..29af54b 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls208xa-rdb.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls208xa-rdb.dtsi
@@ -46,6 +46,10 @@
*/
&esdhc {
+ sd-uhs-sdr104;
+ sd-uhs-sdr50;
+ sd-uhs-sdr25;
+ sd-uhs-sdr12;
status = "okay";
};
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi
index 6e531b9..94cdd30 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi
@@ -472,7 +472,7 @@
compatible = "fsl,ls2080a-esdhc", "fsl,esdhc";
reg = <0x0 0x2140000 0x0 0x10000>;
interrupts = <0 28 0x4>; /* Level high type */
- clock-frequency = <0>; /* Updated by bootloader */
+ clocks = <&clockgen 4 1>;
voltage-ranges = <1800 1800 3300 3300>;
sdhci,auto-cmd12;
little-endian;
--
2.1.0.27.g96db324
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [v2, 4/5] arm64: dts: ls1012a: add eSDHC nodes
From: Yangbo Lu @ 2017-05-04 10:48 UTC (permalink / raw)
To: devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Shawn Guo,
ulf.hansson-QSEj5FYQhm4dnm+yROfE0A, Rob Herring, Catalin Marinas,
Harninder Rai
Cc: Xiaobo Xie, Yangbo Lu
In-Reply-To: <1493894940-47452-1-git-send-email-yangbo.lu-3arQi8VN3Tc@public.gmane.org>
There are two eSDHC controllers in LS1012A. This patch is to add
eSDHC nodes for ls1012a dts. Also enable eSDHC for RDB/QDS boards.
Signed-off-by: Yangbo Lu <yangbo.lu-3arQi8VN3Tc@public.gmane.org>
---
Changes for v2:
- Sorted the node.
---
arch/arm64/boot/dts/freescale/fsl-ls1012a-qds.dts | 8 ++++++++
arch/arm64/boot/dts/freescale/fsl-ls1012a-rdb.dts | 13 ++++++++++++
arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi | 25 +++++++++++++++++++++++
3 files changed, 46 insertions(+)
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1012a-qds.dts b/arch/arm64/boot/dts/freescale/fsl-ls1012a-qds.dts
index 40ef468..8c013b5 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1012a-qds.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a-qds.dts
@@ -97,6 +97,14 @@
status = "okay";
};
+&esdhc0 {
+ status = "okay";
+};
+
+&esdhc1 {
+ status = "okay";
+};
+
&i2c0 {
status = "okay";
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1012a-rdb.dts b/arch/arm64/boot/dts/freescale/fsl-ls1012a-rdb.dts
index 65d4313..c1a119e 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1012a-rdb.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a-rdb.dts
@@ -54,6 +54,19 @@
status = "okay";
};
+&esdhc0 {
+ sd-uhs-sdr104;
+ sd-uhs-sdr50;
+ sd-uhs-sdr25;
+ sd-uhs-sdr12;
+ status = "okay";
+};
+
+&esdhc1 {
+ mmc-hs200-1_8v;
+ status = "okay";
+};
+
&i2c0 {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
index ae47156..9a2ccd8 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
@@ -117,12 +117,37 @@
#size-cells = <2>;
ranges;
+ esdhc0: esdhc@1560000 {
+ compatible = "fsl,ls1012a-esdhc", "fsl,esdhc";
+ reg = <0x0 0x1560000 0x0 0x10000>;
+ interrupts = <0 62 0x4>;
+ clocks = <&clockgen 4 0>;
+ voltage-ranges = <1800 1800 3300 3300>;
+ sdhci,auto-cmd12;
+ big-endian;
+ bus-width = <4>;
+ status = "disabled";
+ };
+
scfg: scfg@1570000 {
compatible = "fsl,ls1012a-scfg", "syscon";
reg = <0x0 0x1570000 0x0 0x10000>;
big-endian;
};
+ esdhc1: esdhc@1580000 {
+ compatible = "fsl,ls1012a-esdhc", "fsl,esdhc";
+ reg = <0x0 0x1580000 0x0 0x10000>;
+ interrupts = <0 65 0x4>;
+ clocks = <&clockgen 4 0>;
+ voltage-ranges = <1800 1800 3300 3300>;
+ sdhci,auto-cmd12;
+ big-endian;
+ broken-cd;
+ bus-width = <4>;
+ status = "disabled";
+ };
+
crypto: crypto@1700000 {
compatible = "fsl,sec-v5.4", "fsl,sec-v5.0",
"fsl,sec-v4.0";
--
2.1.0.27.g96db324
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [v2, 5/5] arm64: dts: ls1088a: add esdhc node
From: Yangbo Lu @ 2017-05-04 10:49 UTC (permalink / raw)
To: devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Shawn Guo,
ulf.hansson-QSEj5FYQhm4dnm+yROfE0A, Rob Herring, Catalin Marinas,
Harninder Rai
Cc: Xiaobo Xie, Yangbo Lu
In-Reply-To: <1493894940-47452-1-git-send-email-yangbo.lu-3arQi8VN3Tc@public.gmane.org>
Add esdhc node for ls1088a and enable it on both RDB and QDS boards.
Signed-off-by: Yangbo Lu <yangbo.lu-3arQi8VN3Tc@public.gmane.org>
---
Changes for v2:
- Sorted the node.
---
arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts | 4 ++++
arch/arm64/boot/dts/freescale/fsl-ls1088a-rdb.dts | 4 ++++
arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi | 12 ++++++++++++
3 files changed, 20 insertions(+)
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts b/arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts
index 8c3cae5..ff21055 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts
@@ -118,6 +118,10 @@
status = "okay";
};
+&esdhc {
+ status = "okay";
+};
+
&sata {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1088a-rdb.dts b/arch/arm64/boot/dts/freescale/fsl-ls1088a-rdb.dts
index 8a04fbb..ab62ef6 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1088a-rdb.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1088a-rdb.dts
@@ -102,6 +102,10 @@
status = "okay";
};
+&esdhc {
+ status = "okay";
+};
+
&sata {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
index 2946fd7..10b5775 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
@@ -263,6 +263,18 @@
status = "disabled";
};
+ esdhc: esdhc@2140000 {
+ compatible = "fsl,ls1088a-esdhc", "fsl,esdhc";
+ reg = <0x0 0x2140000 0x0 0x10000>;
+ interrupts = <0 28 0x4>; /* Level high type */
+ clock-frequency = <0>;
+ voltage-ranges = <1800 1800 3300 3300>;
+ sdhci,auto-cmd12;
+ little-endian;
+ bus-width = <4>;
+ status = "disabled";
+ };
+
sata: sata@3200000 {
compatible = "fsl,ls1088a-ahci", "fsl,ls1043a-ahci";
reg = <0x0 0x3200000 0x0 0x10000>;
--
2.1.0.27.g96db324
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox