Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/3] Add USB HCD support for STi SoCs
From: Peter Griffin @ 2014-07-24 11:00 UTC (permalink / raw)
  To: linux-arm-kernel

This driver adds support for the USB HCD controller present in STi
SoC's from STMicroelectronics. It has been tested on the stih416-b2020
board.

The original author is no longer with the company and therefore emails
to his address bounce, thus I have not added him to CC.

Changes since v1:
 - Correct s/OCHI/OHCI/ spelling
 - Improve kconfig help message
 - Various formating / spelling nits identified by Lee Jones
 - Make driver depend on OF & remove node checks in code
 - Use devm_ioremap_resource
 - Remove unnecessary header files

Peter Griffin (3):
  usb: host: st-hcd: Add USB HCD support for STi SoCs
  usb: host: st-hcd: Add st-hcd devicetree bindings documentation.
  MAINTAINERS: Add st-hcd to ARCH/STI architecture

 Documentation/devicetree/bindings/usb/st-hcd.txt |  51 +++
 MAINTAINERS                                      |   1 +
 drivers/usb/host/Kconfig                         |  13 +
 drivers/usb/host/Makefile                        |   1 +
 drivers/usb/host/st-hcd.c                        | 471 +++++++++++++++++++++++
 5 files changed, 537 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/usb/st-hcd.txt
 create mode 100644 drivers/usb/host/st-hcd.c

-- 
1.9.1

^ permalink raw reply

* next build: 629 warnings 1 failures (next/next-20140723)
From: Catalin Marinas @ 2014-07-24 10:43 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140724085037.GB1994@arm.com>

On Thu, Jul 24, 2014 at 09:50:37AM +0100, Will Deacon wrote:
> On Thu, Jul 24, 2014 at 12:27:30AM +0100, Olof Johansson wrote:
> > On Wed, Jul 23, 2014 at 2:40 AM, Olof's autobuilder <build@lixom.net> wrote:
> > >         arm64.defconfig:
> > > arch/arm64/kernel/head.S:298: Error: unknown or missing system register name at operand 2 -- `mrs x0,S3_4_C12_C9_5'
> > > arch/arm64/kernel/head.S:301: Error: unknown or missing system register name at operand 1 -- `msr S3_4_C12_C9_5,x0'
> > > arch/arm64/kernel/head.S:303: Error: unknown or missing system register name at operand 1 -- `msr S3_4_C12_C11_0,xzr'
> > > arch/arm64/kernel/ptrace.c:1119:3: error: too many arguments to function 'audit_syscall_entry'
> > > /tmp/ccq7ZztI.s:21: Error: unknown or missing system register name at operand 1 -- `msr S3_0_C12_C12_1,x0'
> > > /tmp/ccq7ZztI.s:162: Error: unknown or missing system register name at operand 2 -- `mrs x19,S3_0_C12_C12_0'
> > > /tmp/ccq7ZztI.s:186: Error: unknown or missing system register name at operand 1 -- `msr S3_0_C12_C12_1,x19'
> > > /tmp/ccq7ZztI.s:220: Error: unknown or missing system register name at operand 1 -- `msr S3_0_C12_C12_1,x19'
> > > /tmp/ccq7ZztI.s:1110: Error: unknown or missing system register name at operand 1 -- `msr S3_0_C12_C11_5,x27'
> > > /tmp/ccq7ZztI.s:1530: Error: unknown or missing system register name at operand 2 -- `mrs x0,S3_0_C12_C12_5'
> > > /tmp/ccq7ZztI.s:1540: Error: unknown or missing system register name at operand 1 -- `msr S3_0_C12_C12_5,x0'
> > > /tmp/ccq7ZztI.s:1548: Error: unknown or missing system register name at operand 2 -- `mrs x0,S3_0_C12_C12_5'
> > > /tmp/ccq7ZztI.s:1564: Error: unknown or missing system register name at operand 1 -- `msr S3_0_C4_C6_0,x0'
> > > /tmp/ccq7ZztI.s:1576: Error: unknown or missing system register name at operand 1 -- `msr S3_0_C12_C12_4,x0'
> > > /tmp/ccq7ZztI.s:1592: Error: unknown or missing system register name at operand 1 -- `msr S3_0_C12_C12_7,x0'
> > 
> > 
> > I'm building with a vanilla gcc 4.8.2 / binutils 2.23.2. That
> > shouldn't be broken like this, so those changes should be fixed (or
> > minimal toolchain expecations need to be documented -- but there
> > really is no good reason to require 4.9.0/2.24).
> 
> These all come from the GICv3 driver, so it's not going to be a lot of fun
> fixing them. You'd have to introduce a macro for generating the system-reg
> accesses (for both C and asm), then switch the GIC driver and the arch code
> over to using that.

We may need to document that enabling GICv3 requires a newer toolchain.

Otherwise, my years old macros ;) (adapted here and untested):

In asm/sysreg.h:

#define	sys_reg(op0, op1, crn, crm, op2)	\
	((((op0)-2)<<19)|((op1)<<16)|((crn)<<12)|((crm)<<8)|((op2)<<5))

#ifdef __ASSEMBLY__

	.macro	mrs_s, rt, sreg
	.inst	0xd5300000|(\sreg)|(\rt)
	.endm

	.macro	msr_s, sreg, rt
	.inst	0xd5100000|(\sreg)|(\rt)
	.endm

#else

__asm__(
"	.macro	mrs_s, rt, sreg\n"
"	.inst	0xd5300000|(\\sreg)|(\\rt)\n"
"	.endm\n"
"\n"
"	.macro	msr_s, sreg, rt\n"
"	.inst	0xd5100000|(\\sreg)|(\\rt)\n"
"	.endm\n"
);

#endif


In the arm-gic-v3.h file, we change the definitions to:

#define ICC_SRE_EL2			sys_reg(3, 4, 12, 9, 5)


And in head.S:

	mrs_s	x0, ICC_SRE_EL2

Similarly in C files (the only change is s/mrs/mrs_s/):

	asm volatile("mrs_s %0, " __stringify(ICC_IAR1_EL1) : "=r" (irqstat));


But I'll let Marc comment when he gets back from holiday (I'm pretty
sure he will enjoy it ;))

-- 
Catalin

^ permalink raw reply

* [RFC] cpufreq: Add bindings for CPU clock sharing topology
From: Viresh Kumar @ 2014-07-24 10:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CABGGisxHxdTyh500ey+KVLV3EnfYZvtsCV=Nt4Nqu7p6KJOwdA@mail.gmail.com>

On 24 July 2014 07:54, Rob Herring <rob.herring@linaro.org> wrote:

>> A previous approach tried to compare struct clk pointers, which is a bad
>> idea since those are just cookies and should not be deref'd by drivers.
>> However a similar approach would be to compare the phandle, right?

Yeah. So what's the right way then?

> I think there needs to be a way to query whether a rate change for a
> clock affects other children. As pointed out previously, the clock to
> a core may not be shared, but it's parent that can change rates could
> be shared. This could be done with functions
> clk_get_parent_rate_change to return the clock in heirarchy which can
> change rates, and clk_is_parent_clk which tells if one clock is a
> child of another clock. It's been a while since I've looked at the
> clock api. It could also be done by experiment. Change the rate for
> core 0 and see if core 1's rate is changed and still equal. There's
> probably some ordering issue with doing that though.

But Mike sort of Nak'd that as well earlier :)

^ permalink raw reply

* [PATCH] imx-drm: imx-drm-core: add suspend/resume support
From: Daniel Vetter @ 2014-07-24 10:38 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140724095430.GM21766@n2100.arm.linux.org.uk>

On Thu, Jul 24, 2014 at 10:54:30AM +0100, Russell King - ARM Linux wrote:
> On Thu, Jul 24, 2014 at 11:47:55AM +0200, Lucas Stach wrote:
> > Am Donnerstag, den 24.07.2014, 17:17 +0800 schrieb Shawn Guo:
> > > HDMI currently stops working after a system suspend/resume cycle.  It
> > > turns out that the cause is the imx-hdmi encoder .dpms hook doesn't get
> > > called from anywhere across suspend/resume cycle.
> > > 
> > > The patch follows what exynos drm driver does to walk the list of
> > > connectors and call their .dpms function from suspend/resume hook.  And
> > > the connectors' .dpms function will in turn filter down to the .dpms
> > > hooks of encoders and CRTCs.
> > > 
> > > With this change, HDMI can continue working after a suspend/resume
> > > cycle.
> > > 
> > > Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
> > > ---
> > > Tested with HDMI and LVDS.  It'd be great if someone can help test TVE
> > > to ensure the patch doesn't break anything.
> > > 
> > >  drivers/staging/imx-drm/imx-drm-core.c | 39 ++++++++++++++++++++++++++++++++++
> > >  1 file changed, 39 insertions(+)
> > > 
> > > diff --git a/drivers/staging/imx-drm/imx-drm-core.c b/drivers/staging/imx-drm/imx-drm-core.c
> > > index def8280d7ee6..b0ea1f0ed32f 100644
> > > --- a/drivers/staging/imx-drm/imx-drm-core.c
> > > +++ b/drivers/staging/imx-drm/imx-drm-core.c
> > > @@ -696,6 +696,44 @@ static int imx_drm_platform_remove(struct platform_device *pdev)
> > >  	return 0;
> > >  }
> > >  
> > > +#if CONFIG_PM_SLEEP
> > 
> > use #ifdef
> > 
> > > +static int imx_drm_suspend(struct device *dev)
> > > +{
> > > +	struct drm_device *drm_dev = dev_get_drvdata(dev);
> > > +	struct drm_connector *connector;
> > > +
> > > +	drm_kms_helper_poll_disable(drm_dev);
> > > +
> > 
> > That's ok.
> > 
> > > +	drm_modeset_lock_all(drm_dev);
> > > +	list_for_each_entry(connector, &drm_dev->mode_config.connector_list, head) {
> > > +		if (connector->funcs->dpms)
> > > +			connector->funcs->dpms(connector, DRM_MODE_DPMS_OFF);
> > > +	}
> > 
> > Don't touch DPMS state here. See below.
> 
> In which case, how else does the hardware get placed into a low power
> mode on suspend?
> 
> DRM has nothing provided, and this is left up to each DRM driver to
> implement (probably because it tends to be very driver specific.)
> i915 for example calls the CRTC DPMS function with DRM_MODE_DPMS_OFF.
> 
> This provides a similar mechanism, but also informs the connector, any
> bridge, and encoder associated with the connector as well as the CRTC
> to place themselves into a low power mode (which is what
> DRM_MODE_DPMS_OFF should be doing anyway.)

Well you need to call internal functions to make sure you can restore the
state again. Not sure any more how that all works with the crtc helpers
and whether they restore dpms state properly at all. i915 uses something
completely different nowadays.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply

* [PATCH v4 2/2] pwm: rockchip: Added to support for RK3288 SoC
From: Caesar Wang @ 2014-07-24 10:21 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1406197295-10604-1-git-send-email-caesar.wang@rock-chips.com>

This patch added to support the PWM controller found on
RK3288 SoC.

Signed-off-by: Caesar Wang <caesar.wang@rock-chips.com>
---
 drivers/pwm/pwm-rockchip.c | 124 ++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 105 insertions(+), 19 deletions(-)

diff --git a/drivers/pwm/pwm-rockchip.c b/drivers/pwm/pwm-rockchip.c
index eec2145..59c2513 100644
--- a/drivers/pwm/pwm-rockchip.c
+++ b/drivers/pwm/pwm-rockchip.c
@@ -2,6 +2,7 @@
  * PWM driver for Rockchip SoCs
  *
  * Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com>
+ * Copyright (C) 2014 ROCKCHIP, Inc.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -12,6 +13,7 @@
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/pwm.h>
 #include <linux/time.h>
@@ -25,17 +27,72 @@
 
 #define PRESCALER		2
 
+#define PWM_ENABLE		(1 << 0)
+#define PWM_CONTINUOUS		(1 << 1)
+#define PWM_DUTY_POSITIVE	(1 << 3)
+#define PWM_INACTIVE_NEGATIVE	(0 << 4)
+#define PWM_OUTPUT_LEFT		(0 << 5)
+#define PWM_LP_DISABLE		(0 << 8)
+
 struct rockchip_pwm_chip {
 	struct pwm_chip chip;
 	struct clk *clk;
+	const struct rockchip_pwm_data *data;
 	void __iomem *base;
 };
 
+struct rockchip_pwm_regs {
+	unsigned long duty;
+	unsigned long period;
+	unsigned long cntr;
+	unsigned long ctrl;
+};
+
+struct rockchip_pwm_data {
+	struct rockchip_pwm_regs regs;
+	unsigned int prescaler;
+
+	void (*set_enable)(struct pwm_chip *chip, bool enable);
+};
+
 static inline struct rockchip_pwm_chip *to_rockchip_pwm_chip(struct pwm_chip *c)
 {
 	return container_of(c, struct rockchip_pwm_chip, chip);
 }
 
+static void rockchip_pwm_set_enable_v1(struct pwm_chip *chip, bool enable)
+{
+	struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
+	u32 val = 0;
+	u32 enable_conf = PWM_CTRL_OUTPUT_EN | PWM_CTRL_TIMER_EN;
+
+	val = readl_relaxed(pc->base + pc->data->regs.ctrl);
+
+	if (enable)
+		val |= enable_conf;
+	else
+		val &= ~enable_conf;
+
+	writel_relaxed(val, pc->base + pc->data->regs.ctrl);
+}
+
+static void rockchip_pwm_set_enable_v2(struct pwm_chip *chip, bool enable)
+{
+	struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
+	u32 val = 0;
+	u32 enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE |
+		PWM_CONTINUOUS | PWM_DUTY_POSITIVE | PWM_INACTIVE_NEGATIVE;
+
+	val = readl_relaxed(pc->base + pc->data->regs.ctrl);
+
+	if (enable)
+		val |= enable_conf;
+	else
+		val &= ~enable_conf;
+
+	writel_relaxed(val, pc->base + pc->data->regs.ctrl);
+}
+
 static int rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
 			       int duty_ns, int period_ns)
 {
@@ -52,20 +109,20 @@ static int rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
 	 * default prescaler value for all practical clock rate values.
 	 */
 	div = clk_rate * period_ns;
-	do_div(div, PRESCALER * NSEC_PER_SEC);
+	do_div(div, pc->data->prescaler * NSEC_PER_SEC);
 	period = div;
 
 	div = clk_rate * duty_ns;
-	do_div(div, PRESCALER * NSEC_PER_SEC);
+	do_div(div, pc->data->prescaler * NSEC_PER_SEC);
 	duty = div;
 
 	ret = clk_enable(pc->clk);
 	if (ret)
 		return ret;
 
-	writel(period, pc->base + PWM_LRC);
-	writel(duty, pc->base + PWM_HRC);
-	writel(0, pc->base + PWM_CNTR);
+	writel(period, pc->base + pc->data->regs.period);
+	writel(duty, pc->base + pc->data->regs.duty);
+	writel(0, pc->base + pc->data->regs.cntr);
 
 	clk_disable(pc->clk);
 
@@ -76,15 +133,12 @@ static int rockchip_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
 {
 	struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
 	int ret;
-	u32 val;
 
 	ret = clk_enable(pc->clk);
 	if (ret)
 		return ret;
 
-	val = readl_relaxed(pc->base + PWM_CTRL);
-	val |= PWM_CTRL_OUTPUT_EN | PWM_CTRL_TIMER_EN;
-	writel_relaxed(val, pc->base + PWM_CTRL);
+	pc->data->set_enable(chip, true);
 
 	return 0;
 }
@@ -92,11 +146,8 @@ static int rockchip_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
 static void rockchip_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
 {
 	struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
-	u32 val;
 
-	val = readl_relaxed(pc->base + PWM_CTRL);
-	val &= ~(PWM_CTRL_OUTPUT_EN | PWM_CTRL_TIMER_EN);
-	writel_relaxed(val, pc->base + PWM_CTRL);
+	pc->data->set_enable(chip, false);
 
 	clk_disable(pc->clk);
 }
@@ -108,12 +159,52 @@ static const struct pwm_ops rockchip_pwm_ops = {
 	.owner = THIS_MODULE,
 };
 
+static const struct rockchip_pwm_data pwm_data_v1 = {
+	.regs.duty = PWM_HRC,
+	.regs.period = PWM_LRC,
+	.regs.cntr = PWM_CNTR,
+	.regs.ctrl = PWM_CTRL,
+	.prescaler = PRESCALER,
+	.set_enable = rockchip_pwm_set_enable_v1,
+};
+
+static const struct rockchip_pwm_data pwm_data_v2 = {
+	.regs.duty = PWM_LRC,
+	.regs.period = PWM_HRC,
+	.regs.cntr = PWM_CNTR,
+	.regs.ctrl = PWM_CTRL,
+	.prescaler = PRESCALER-1,
+	.set_enable = rockchip_pwm_set_enable_v2,
+};
+
+static const struct rockchip_pwm_data pwm_data_vop = {
+	.regs.duty = PWM_LRC,
+	.regs.period = PWM_HRC,
+	.regs.cntr = PWM_CTRL,
+	.regs.ctrl = PWM_CNTR,
+	.prescaler = PRESCALER-1,
+	.set_enable = rockchip_pwm_set_enable_v2,
+};
+
+static const struct of_device_id rockchip_pwm_dt_ids[] = {
+	{ .compatible = "rockchip,rk2928-pwm", .data = &pwm_data_v1},
+	{ .compatible = "rockchip,rk3288-pwm", .data = &pwm_data_v2},
+	{ .compatible = "rockchip,vop-pwm", .data = &pwm_data_vop},
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, rockchip_pwm_dt_ids);
+
 static int rockchip_pwm_probe(struct platform_device *pdev)
 {
+	const struct of_device_id *id;
 	struct rockchip_pwm_chip *pc;
 	struct resource *r;
 	int ret;
 
+	id = of_match_device(rockchip_pwm_dt_ids, &pdev->dev);
+	if (!id)
+		return -EINVAL;
+
 	pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL);
 	if (!pc)
 		return -ENOMEM;
@@ -133,6 +224,7 @@ static int rockchip_pwm_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, pc);
 
+	pc->data = id->data;
 	pc->chip.dev = &pdev->dev;
 	pc->chip.ops = &rockchip_pwm_ops;
 	pc->chip.base = -1;
@@ -156,12 +248,6 @@ static int rockchip_pwm_remove(struct platform_device *pdev)
 	return pwmchip_remove(&pc->chip);
 }
 
-static const struct of_device_id rockchip_pwm_dt_ids[] = {
-	{ .compatible = "rockchip,rk2928-pwm" },
-	{ /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, rockchip_pwm_dt_ids);
-
 static struct platform_driver rockchip_pwm_driver = {
 	.driver = {
 		.name = "rockchip-pwm",
-- 
1.9.1

^ permalink raw reply related

* [PATCH v4 1/2] pwm: rockchip: document RK3288 SoC compatible
From: Caesar Wang @ 2014-07-24 10:21 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1406197295-10604-1-git-send-email-caesar.wang@rock-chips.com>

Document new compatible for PWM founding on RK3288 SoC

Signed-off-by: Caesar Wang <caesar.wang@rock-chips.com>
---
 Documentation/devicetree/bindings/pwm/pwm-rockchip.txt | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/pwm/pwm-rockchip.txt b/Documentation/devicetree/bindings/pwm/pwm-rockchip.txt
index 3182126..d47d15a 100644
--- a/Documentation/devicetree/bindings/pwm/pwm-rockchip.txt
+++ b/Documentation/devicetree/bindings/pwm/pwm-rockchip.txt
@@ -1,7 +1,10 @@
 Rockchip PWM controller
 
 Required properties:
- - compatible: should be "rockchip,rk2928-pwm"
+ - compatible: should be "rockchip,<name>-pwm"
+   "rockchip,rk2928-pwm": found on RK29XX,RK3066 and RK3188 SoCs
+   "rockchip,rk3288-pwm": found on RK3288 SoC
+   "rockchip,vop-pwm": found integrated in VOP on RK3288 SoC
  - reg: physical base address and length of the controller's registers
  - clocks: phandle and clock specifier of the PWM reference clock
  - #pwm-cells: should be 2. See pwm.txt in this directory for a
-- 
1.9.1

^ permalink raw reply related

* [PATCH v4 0/2] This series adds support for RK3288 SoC integrated PWM
From: Caesar Wang @ 2014-07-24 10:21 UTC (permalink / raw)
  To: linux-arm-kernel

This patch will make applying on the top of Beniamino's submission,
the Beniamino's submission come from [1].

[1]:
    https://git.kernel.org/cgit/linux/kernel/git/thierry.reding/linux-pwm.git/log/?h=for-next

    Beniamino's submission won't be used from genenation Rockchip SoCs.
    So I have to add the new pwm for next genenation Rockchip SoCs.

    Tested on RK3288 SDK board.

Changes in v4:
    * address comments from Heiko St?bner:
    - fix the copyright for ROCKCHIP, Inc. 
    - remove rockchip_pwm_set_enable_vop,then it instead of rockchip_pwm_set_enable_v2.
   
Changes in v3:
    * address comments from Thierry Reding:
    - fix PWM document deccribes. 
    - add a description for [PATCH v3 2/2].
    - renamed the PWM registers
    - Changed in rockchip_pwm_data struct
    - remove the devm_ioremap(),fixed in lcdc driver.

Changes in v2:
    * address comments from Beniamino Galvani:
    - remove #include <linux/of_address.h>. 
    - of_iomap be removed,and devm_ioremap replace it.
    - remove a line no be used.

Caesar Wang (2):
  pwm: rockchip: document RK3288 SoC compatible
  pwm: rockchip: Added to support for RK3288 SoC

 .../devicetree/bindings/pwm/pwm-rockchip.txt       |   5 +-
 drivers/pwm/pwm-rockchip.c                         | 124 +++++++++++++++++----
 2 files changed, 109 insertions(+), 20 deletions(-)

-- 
1.9.1

^ permalink raw reply

* [PATCH v5 2/4] pwm: sirf: add dt-binding document
From: Barry Song @ 2014-07-24 10:08 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1405476113-10127-1-git-send-email-huayi.li@csr.com>

2014-07-16 10:01 GMT+08:00 Huayi Li <huayi.li@csr.com>:
> This patch adds dt-binding document for pwm-sirf. here the controller clock
> can't generate PWM signals, so we need seperate clock as signal source.
>
> Signed-off-by: Huayi Li <huayi.li@csr.com>

Reviewed-by: Barry Song <Baohua.Song@csr.com>

except that the commit log has not explained enough clearly that every
pwm channel can choice one from five clock sources to generate PWM
wave.

> ---
>  Documentation/devicetree/bindings/pwm/pwm-sirf.txt | 29 ++++++++++++++++++++++
>  1 file changed, 29 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/pwm/pwm-sirf.txt
>
> diff --git a/Documentation/devicetree/bindings/pwm/pwm-sirf.txt b/Documentation/devicetree/bindings/pwm/pwm-sirf.txt
> new file mode 100644
> index 0000000..221e5d9
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/pwm/pwm-sirf.txt
> @@ -0,0 +1,29 @@
> +SiRF prima2 & atlas6 PWM drivers
> +
> +Required properties:
> +- compatible: "sirf,prima2-pwm"
> +- reg: physical base address and length of the controller's registers
> +- #pwm-cells: should be 2. See pwm.txt in this directory for a description of
> +  the cells format.
> +- clocks: Must contain an entry for each entry in clock-names.
> +  See ../clock/prima2-clock.txt for details.
> +- clock-names: Must include the following entries:
> +  of clock sources to generate PWM signal,
> +  - pwmc: PWM controller clock
> +  - sigsrc0: source clock 0 for PWM
> +  - sigsrc1: source clock 1 for PWM
> +  - sigsrc2: source clock 2 for PWM
> +  - sigsrc3: source clock 3 for PWM
> +  - sigsrc4: source clock 4 for PWM
> +
> +Example:
> +
> +pwm: pwm at b0130000 {
> +       compatible = "sirf,prima2-pwm";
> +       #pwm-cells = <2>;
> +       reg = <0xb0130000 0x10000>;
> +       clocks = <&clks 21>, <&clks 1>, <&clks 2>,
> +              <&clks 3>, <&clks 0>, <&clks 4>;
> +       clock-names = "pwmc", "sigsrc0", "sigsrc1",
> +               "sigsrc2", "sigsrc3", "sigsrc4";
> +};
> --
> 1.9.3
>

-barry

^ permalink raw reply

* [PATCH v2] cpufreq: tests: Providing cpufreq regression test
From: Javi Merino @ 2014-07-24 10:05 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140723121042.5b6f49e3@amdc2363>

On Wed, Jul 23, 2014 at 11:10:42AM +0100, Lukasz Majewski wrote:
> Hi Viresh,
> 
> > On 23 July 2014 13:08, Lukasz Majewski <l.majewski@samsung.com> wrote:
> > > Do you want to say that we have enough tests and we don't need
> > > more ?
> > 
> > No. We don't have any tests at all :)
> 
> Then we should encourage as many developers as possible to share their
> private tests with us.

Linaro publishes their regression tests here:

https://git.linaro.org/tools/pm-qa.git

Description:

https://wiki.linaro.org/WorkingGroups/PowerManagement/Resources/TestSuite/PmQaSpecification#Cpufreq

I have only used the thermal ones, I can't comment on the cpufreq
tests.

Cheers,
Javi

^ permalink raw reply

* [RFC] PCI: pcie-designware: allow drivers as loadable modules
From: Lucas Stach @ 2014-07-24 10:02 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <5303286.K45Li7B92z@wuerfel>

Am Donnerstag, den 24.07.2014, 11:17 +0200 schrieb Arnd Bergmann:
> From 0ee79c7451851a34e5a7c33eb6020befcdcb2b24 Mon Sep 17 00:00:00 2001
> From: Arnd Bergmann <arnd@arndb.de>
> Date: Thu, 24 Jul 2014 11:12:48 +0200
> Subject: [PATCH] PCI: pcie-designware: allow drivers as loadable modules
> 
> The new pcie-spear13xx driver uses the pcie-designware library
> and in the current form it can be built as a loadable module.
> However, the functions it uses from the base driver are not exported,
> so this results in a build failure and a module that can never
> be loaded:
> 
> ERROR: "dw_pcie_host_init" [drivers/pci/host/pcie-spear13xx.ko] undefined!
> ERROR: "dw_handle_msi_irq" [drivers/pci/host/pcie-spear13xx.ko] undefined!
> ERROR: "dw_pcie_msi_init" [drivers/pci/host/pcie-spear13xx.ko] undefined!
> ERROR: "dw_pcie_cfg_write" [drivers/pci/host/pcie-spear13xx.ko] undefined!
> ERROR: "dw_pcie_cfg_read" [drivers/pci/host/pcie-spear13xx.ko] undefined!
> ERROR: "dw_pcie_setup_rc" [drivers/pci/host/pcie-spear13xx.ko] undefined!
> ERROR: "dw_pcie_link_up" [drivers/pci/host/pcie-spear13xx.ko] undefined!
> 
> If we want to allow loadable pcie-designware drivers, we have to
> export all those symbols and ensure none of them are marked as __init.
> This also requires making pci_assign_unassigned_resources available
> after boot.

My series "PCI: designware: init order/resource alloc fixes" removes
this function call from pcie-designware, so if it get's accepted this
should not be necessary.

Regards,
Lucas
-- 
Pengutronix e.K.             | Lucas Stach                 |
Industrial Linux Solutions   | http://www.pengutronix.de/  |

^ permalink raw reply

* [PATCH] spi/pxa2xx-pci: Enable DMA binding through device name
From: Kweh Hock Leong @ 2014-07-24 10:01 UTC (permalink / raw)
  To: linux-arm-kernel

From: "Chew, Chiau Ee" <chiau.ee.chew@intel.com>

Intel LPSS Baytrail supports two DMA controllers and SPI is only
using one of the DMA controller. During DMA channel request,
we need to ensure the requested Tx and Rx channels are from the correct
DMA controller. Thus, we add extra checking in filter callback funtion
by matching against the DMA controller device name.

Signed-off-by: Chew, Chiau Ee <chiau.ee.chew@intel.com>
Signed-off-by: Kweh, Hock Leong <hock.leong.kweh@intel.com>
---
 drivers/spi/spi-pxa2xx-dma.c   | 5 +++++
 drivers/spi/spi-pxa2xx-pci.c   | 3 +++
 include/linux/spi/pxa2xx_spi.h | 1 +
 3 files changed, 9 insertions(+)

diff --git a/drivers/spi/spi-pxa2xx-dma.c b/drivers/spi/spi-pxa2xx-dma.c
index c41ff14..4c4e918 100644
--- a/drivers/spi/spi-pxa2xx-dma.c
+++ b/drivers/spi/spi-pxa2xx-dma.c
@@ -214,6 +214,11 @@ static bool pxa2xx_spi_dma_filter(struct dma_chan *chan, void *param)
 {
 	const struct pxa2xx_spi_master *pdata = param;
 
+	if (pdata->dma_devname) {
+		if (strcmp(dev_name(chan->device->dev), pdata->dma_devname))
+			return false;
+	}
+
 	return chan->chan_id == pdata->tx_chan_id ||
 	       chan->chan_id == pdata->rx_chan_id;
 }
diff --git a/drivers/spi/spi-pxa2xx-pci.c b/drivers/spi/spi-pxa2xx-pci.c
index c1865c9..7a21bce 100644
--- a/drivers/spi/spi-pxa2xx-pci.c
+++ b/drivers/spi/spi-pxa2xx-pci.c
@@ -21,6 +21,7 @@ struct pxa_spi_info {
 	int tx_chan_id;
 	int rx_slave_id;
 	int rx_chan_id;
+	char *dma_devname;
 };
 
 static struct pxa_spi_info spi_info_configs[] = {
@@ -41,6 +42,7 @@ static struct pxa_spi_info spi_info_configs[] = {
 		.tx_chan_id = 0,
 		.rx_slave_id = 1,
 		.rx_chan_id = 1,
+		.dma_devname = "0000:00:1e.0"
 	},
 };
 
@@ -72,6 +74,7 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev,
 	spi_pdata.rx_slave_id = c->rx_slave_id;
 	spi_pdata.rx_chan_id = c->rx_chan_id;
 	spi_pdata.enable_dma = c->rx_slave_id >= 0 && c->tx_slave_id >= 0;
+	spi_pdata.dma_devname = c->dma_devname;
 
 	ssp = &spi_pdata.ssp;
 	ssp->phys_base = pci_resource_start(dev, 0);
diff --git a/include/linux/spi/pxa2xx_spi.h b/include/linux/spi/pxa2xx_spi.h
index 82d5111..264c3cb 100644
--- a/include/linux/spi/pxa2xx_spi.h
+++ b/include/linux/spi/pxa2xx_spi.h
@@ -34,6 +34,7 @@ struct pxa2xx_spi_master {
 	int tx_chan_id;
 	int rx_slave_id;
 	int tx_slave_id;
+	char *dma_devname;
 
 	/* For non-PXA arches */
 	struct ssp_device ssp;
-- 
1.9.1

^ permalink raw reply related

* [PATCH] imx-drm: imx-drm-core: add suspend/resume support
From: Marc Kleine-Budde @ 2014-07-24  9:56 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1406195275.4590.18.camel@weser.hi.pengutronix.de>

On 07/24/2014 11:47 AM, Lucas Stach wrote:
> Am Donnerstag, den 24.07.2014, 17:17 +0800 schrieb Shawn Guo:
>> HDMI currently stops working after a system suspend/resume cycle.  It
>> turns out that the cause is the imx-hdmi encoder .dpms hook doesn't get
>> called from anywhere across suspend/resume cycle.
>>
>> The patch follows what exynos drm driver does to walk the list of
>> connectors and call their .dpms function from suspend/resume hook.  And
>> the connectors' .dpms function will in turn filter down to the .dpms
>> hooks of encoders and CRTCs.
>>
>> With this change, HDMI can continue working after a suspend/resume
>> cycle.
>>
>> Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
>> ---
>> Tested with HDMI and LVDS.  It'd be great if someone can help test TVE
>> to ensure the patch doesn't break anything.
>>
>>  drivers/staging/imx-drm/imx-drm-core.c | 39 ++++++++++++++++++++++++++++++++++
>>  1 file changed, 39 insertions(+)
>>
>> diff --git a/drivers/staging/imx-drm/imx-drm-core.c b/drivers/staging/imx-drm/imx-drm-core.c
>> index def8280d7ee6..b0ea1f0ed32f 100644
>> --- a/drivers/staging/imx-drm/imx-drm-core.c
>> +++ b/drivers/staging/imx-drm/imx-drm-core.c
>> @@ -696,6 +696,44 @@ static int imx_drm_platform_remove(struct platform_device *pdev)
>>  	return 0;
>>  }
>>  
>> +#if CONFIG_PM_SLEEP
> 
> use #ifdef

...or remove #if/#ifdef and mark as __maybe_unused

Marc

-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 242 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140724/453066e7/attachment.sig>

^ permalink raw reply

* [PATCH] imx-drm: imx-drm-core: add suspend/resume support
From: Russell King - ARM Linux @ 2014-07-24  9:54 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1406195275.4590.18.camel@weser.hi.pengutronix.de>

On Thu, Jul 24, 2014 at 11:47:55AM +0200, Lucas Stach wrote:
> Am Donnerstag, den 24.07.2014, 17:17 +0800 schrieb Shawn Guo:
> > HDMI currently stops working after a system suspend/resume cycle.  It
> > turns out that the cause is the imx-hdmi encoder .dpms hook doesn't get
> > called from anywhere across suspend/resume cycle.
> > 
> > The patch follows what exynos drm driver does to walk the list of
> > connectors and call their .dpms function from suspend/resume hook.  And
> > the connectors' .dpms function will in turn filter down to the .dpms
> > hooks of encoders and CRTCs.
> > 
> > With this change, HDMI can continue working after a suspend/resume
> > cycle.
> > 
> > Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
> > ---
> > Tested with HDMI and LVDS.  It'd be great if someone can help test TVE
> > to ensure the patch doesn't break anything.
> > 
> >  drivers/staging/imx-drm/imx-drm-core.c | 39 ++++++++++++++++++++++++++++++++++
> >  1 file changed, 39 insertions(+)
> > 
> > diff --git a/drivers/staging/imx-drm/imx-drm-core.c b/drivers/staging/imx-drm/imx-drm-core.c
> > index def8280d7ee6..b0ea1f0ed32f 100644
> > --- a/drivers/staging/imx-drm/imx-drm-core.c
> > +++ b/drivers/staging/imx-drm/imx-drm-core.c
> > @@ -696,6 +696,44 @@ static int imx_drm_platform_remove(struct platform_device *pdev)
> >  	return 0;
> >  }
> >  
> > +#if CONFIG_PM_SLEEP
> 
> use #ifdef
> 
> > +static int imx_drm_suspend(struct device *dev)
> > +{
> > +	struct drm_device *drm_dev = dev_get_drvdata(dev);
> > +	struct drm_connector *connector;
> > +
> > +	drm_kms_helper_poll_disable(drm_dev);
> > +
> 
> That's ok.
> 
> > +	drm_modeset_lock_all(drm_dev);
> > +	list_for_each_entry(connector, &drm_dev->mode_config.connector_list, head) {
> > +		if (connector->funcs->dpms)
> > +			connector->funcs->dpms(connector, DRM_MODE_DPMS_OFF);
> > +	}
> 
> Don't touch DPMS state here. See below.

In which case, how else does the hardware get placed into a low power
mode on suspend?

DRM has nothing provided, and this is left up to each DRM driver to
implement (probably because it tends to be very driver specific.)
i915 for example calls the CRTC DPMS function with DRM_MODE_DPMS_OFF.

This provides a similar mechanism, but also informs the connector, any
bridge, and encoder associated with the connector as well as the CRTC
to place themselves into a low power mode (which is what
DRM_MODE_DPMS_OFF should be doing anyway.)

> > +static int imx_drm_resume(struct device *dev)
> > +{
> > +	struct drm_device *drm_dev = dev_get_drvdata(dev);
> > +	struct drm_connector *connector;
> > +
> > +	drm_modeset_lock_all(drm_dev);
> > +	list_for_each_entry(connector, &drm_dev->mode_config.connector_list, head) {
> > +		if (connector->funcs->dpms)
> > +			connector->funcs->dpms(connector, DRM_MODE_DPMS_ON);
> > +	}
> > +	drm_modeset_unlock_all(drm_dev);
> > +
> This forcefully enables all connectors, which might not have been the
> state before suspend. Have a look at simply using
> drm_helper_resume_force_mode(), which should do the right thing.

Yes, we agree there.

-- 
FTTC broadband for 0.8mile line: currently at 9.5Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply

* [PATCH 1/3] usb: host: st-hcd: Add USB HCD support for STi SoCs
From: Peter Griffin @ 2014-07-24  9:54 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140711082013.GH11948@lee--X1>

Hi Lee,

Thanks for reviewing. All your review comments have been fixed in v2.

regards,

Peter.

^ permalink raw reply

* [PATCH v5 3/4] ARM: dts: sirf: fix the pwm-cells and clocks
From: Barry Song @ 2014-07-24  9:53 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1405475714-10006-4-git-send-email-huayi.li@csr.com>

2014-07-16 9:55 GMT+08:00 Huayi Li <huayi.li@csr.com>:
> This patch adds missed pwm-cells, clock-names and signal source
> clock for PWM module.
>
> Signed-off-by: Huayi Li <huayi.li@csr.com>

Reviewed-by: Barry Song <Baohua.Song@csr.com>

> ---
>  arch/arm/boot/dts/atlas6.dtsi | 8 ++++++--
>  arch/arm/boot/dts/prima2.dtsi | 8 ++++++--
>  2 files changed, 12 insertions(+), 4 deletions(-)
>
> diff --git a/arch/arm/boot/dts/atlas6.dtsi b/arch/arm/boot/dts/atlas6.dtsi
> index bb22842..d424a69 100644
> --- a/arch/arm/boot/dts/atlas6.dtsi
> +++ b/arch/arm/boot/dts/atlas6.dtsi
> @@ -638,10 +638,14 @@
>                                  };
>                         };
>
> -                       pwm at b0130000 {
> +                       pwm: pwm at b0130000 {
>                                 compatible = "sirf,prima2-pwm";
> +                               #pwm-cells = <2>;
>                                 reg = <0xb0130000 0x10000>;
> -                               clocks = <&clks 21>;
> +                               clocks = <&clks 21>, <&clks 1>, <&clks 2>,
> +                                       <&clks 3>, <&clks 0>, <&clks 4>;
> +                               clock-names = "pwmc", "sigsrc0", "sigsrc1",
> +                                       "sigsrc2", "sigsrc3", "sigsrc4";
>                         };
>
>                         efusesys at b0140000 {
> diff --git a/arch/arm/boot/dts/prima2.dtsi b/arch/arm/boot/dts/prima2.dtsi
> index 963b7e5..68bb0c4 100644
> --- a/arch/arm/boot/dts/prima2.dtsi
> +++ b/arch/arm/boot/dts/prima2.dtsi
> @@ -646,10 +646,14 @@
>                                  };
>                         };
>
> -                       pwm at b0130000 {
> +                       pwm: pwm at b0130000 {
>                                 compatible = "sirf,prima2-pwm";
> +                               #pwm-cells = <2>;
>                                 reg = <0xb0130000 0x10000>;
> -                               clocks = <&clks 21>;
> +                               clocks = <&clks 21>, <&clks 1>, <&clks 2>,
> +                                       <&clks 3>, <&clks 0>, <&clks 4>;
> +                               clock-names = "pwmc", "sigsrc0", "sigsrc1",
> +                                       "sigsrc2", "sigsrc3", "sigsrc4";
>                         };
>
>                         efusesys at b0140000 {
> --
> 1.9.3
>

-barry

^ permalink raw reply

* [PATCH v5 1/4] pwm: add CSR SiRFSoc PWM driver
From: Barry Song @ 2014-07-24  9:48 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1405475714-10006-2-git-send-email-huayi.li@csr.com>

2014-07-16 9:55 GMT+08:00 Huayi Li <huayi.li@csr.com>:
> PWM controller of CSR SiRFSoC can generate 7 independent outputs. Each output
> duty cycle can be adjusted by setting the corresponding wait & hold registers.
> There are 6 external channels (0 to 5) and 1 internal channel (6).
> Supports a wide frequency range: the source clock divider can be from 2
> up to 65536*2.
>
> Signed-off-by: Huayi Li <huayi.li@csr.com>
> ---
>  drivers/pwm/Kconfig    |  10 ++
>  drivers/pwm/Makefile   |   1 +
>  drivers/pwm/pwm-sirf.c | 450 +++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 461 insertions(+)
>  create mode 100644 drivers/pwm/pwm-sirf.c
>
> diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
> index 4ad7b89..77d65a6 100644
> --- a/drivers/pwm/Kconfig
> +++ b/drivers/pwm/Kconfig
> @@ -215,6 +215,16 @@ config PWM_SAMSUNG
>           To compile this driver as a module, choose M here: the module
>           will be called pwm-samsung.
>
> +config PWM_SIRF
> +       tristate "SiRF PWM support"
> +       depends on ARCH_SIRF
> +       help
> +         Generic PWM framework driver for the PWM controller on SiRF
> +         SoCs.
> +
> +         To compile this driver as a module, choose M here: the module
> +         will be called pwm-sirf.
> +
>  config PWM_SPEAR
>         tristate "STMicroelectronics SPEAr PWM support"
>         depends on PLAT_SPEAR
> diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
> index 5c86a19..7fa4f14 100644
> --- a/drivers/pwm/Makefile
> +++ b/drivers/pwm/Makefile
> @@ -19,6 +19,7 @@ obj-$(CONFIG_PWM_PUV3)                += pwm-puv3.o
>  obj-$(CONFIG_PWM_PXA)          += pwm-pxa.o
>  obj-$(CONFIG_PWM_RENESAS_TPU)  += pwm-renesas-tpu.o
>  obj-$(CONFIG_PWM_SAMSUNG)      += pwm-samsung.o
> +obj-$(CONFIG_PWM_SIRF)         += pwm-sirf.o
>  obj-$(CONFIG_PWM_SPEAR)                += pwm-spear.o
>  obj-$(CONFIG_PWM_TEGRA)                += pwm-tegra.o
>  obj-$(CONFIG_PWM_TIECAP)       += pwm-tiecap.o
> diff --git a/drivers/pwm/pwm-sirf.c b/drivers/pwm/pwm-sirf.c
> new file mode 100644
> index 0000000..a5a9e2f
> --- /dev/null
> +++ b/drivers/pwm/pwm-sirf.c
> @@ -0,0 +1,450 @@
> +/*
> + * SIRF serial SoC PWM device core driver
> + *
> + * Copyright (c) 2014 Cambridge Silicon Radio Limited, a CSR plc group company.
> + *
> + * Licensed under GPLv2.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/delay.h>
> +#include <linux/device.h>
> +#include <linux/init.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/pwm.h>
> +
> +#define SIRF_PWM_SELECT_PRECLK                 0x0
> +#define SIRF_PWM_OE                            0x4
> +#define SIRF_PWM_ENABLE_PRECLOCK               0x8
> +#define SIRF_PWM_ENABLE_POSTCLOCK              0xC
> +#define SIRF_PWM_GET_WAIT_OFFSET(n)            (0x10 + 0x8*n)
> +#define SIRF_PWM_GET_HOLD_OFFSET(n)            (0x14 + 0x8*n)
> +
> +#define SIRF_PWM_TR_STEP(n)                    (0x48 + 0x8*n)
> +#define SIRF_PWM_STEP_HOLD(n)                  (0x4c + 0x8*n)
> +
> +#define SRC_FIELD_SIZE                         3
> +#define BYPASS_MODE_BIT                                21
> +#define TRANS_MODE_SELECT_BIT                  7
> +
> +#define SIRF_MAX_SRC_CLK                       5
> +
> +struct sirf_pwm_chip {
> +       struct pwm_chip chip;
> +       struct mutex mutex;
> +       void __iomem *base;
> +       struct clk *pwmc_clk;
> +};
> +
> +struct sirf_pwm {
> +       u32 sigsrc_clk_idx;
> +       struct clk *sigsrc_clk;
> +       u32 bypass_mode;
> +       u32 duty_ns;
> +};
> +
> +static inline struct sirf_pwm_chip *to_sirf_pwm_chip(struct pwm_chip *chip)
> +{
> +       return container_of(chip, struct sirf_pwm_chip, chip);
> +}
> +
> +static int sirf_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
> +{
> +       struct sirf_pwm *spwm;
> +
> +       spwm = devm_kzalloc(chip->dev, sizeof(*spwm), GFP_KERNEL);
> +       if (!spwm)
> +               return -ENOMEM;
> +
> +       pwm_set_chip_data(pwm, spwm);
> +
> +       return 0;
> +}
> +
> +static void sirf_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
> +{
> +       struct sirf_pwm *spwm = pwm_get_chip_data(pwm);
> +
> +       if (!spwm)
> +               devm_kfree(chip->dev, spwm);
> +}
> +
> +static u32 sirf_pwm_ns_to_cycles(struct pwm_device *pwm, u32 time_ns)
> +{
> +       struct sirf_pwm *spwm = pwm_get_chip_data(pwm);
> +       u32 src_clk_rate = clk_get_rate(spwm->sigsrc_clk);
> +       u64 cycle;
> +
> +       cycle = div_u64((u64)src_clk_rate * time_ns, NSEC_PER_SEC);
> +
> +       return (u32)(cycle > 1 ? cycle : 1);
> +}
> +
> +static void _sirf_pwm_hwconfig(struct pwm_chip *chip, struct pwm_device *pwm)
> +{
> +       u32 period_cycles, high_cycles, low_cycles;
> +       struct sirf_pwm_chip *spwmc = to_sirf_pwm_chip(chip);
> +       struct sirf_pwm *spwm = pwm_get_chip_data(pwm);
> +
> +       period_cycles = sirf_pwm_ns_to_cycles(pwm, pwm_get_period(pwm));
> +
> +       /*
> +        * enter bypass mode, high_cycles and low_cycle
> +        * do not need to config if period_cycles == 1
> +        */
> +       if (period_cycles == 1) {
> +               spwm->bypass_mode = 1;

the bypass mode need some comments here.  or we need to add a "TODO:
move to clk subsystem" here, it is actually not PWM, but a clock
output now.


> +       } else {
> +               spwm->bypass_mode = 0;
> +
> +               high_cycles = sirf_pwm_ns_to_cycles(pwm, spwm->duty_ns);
> +               low_cycles = period_cycles - high_cycles;
> +
> +               /*
> +                * high_cycles will equal to period_cycles when duty_ns
> +                * is big enough, so low_cycles will be 0,
> +                * a wrong value will be written to register after
> +                * low_cycles minus 1 later.
> +                */
> +               if (high_cycles == period_cycles) {
> +                       high_cycles--;
> +                       low_cycles = 1;
> +               }
> +
> +               mutex_lock(&spwmc->mutex);
> +
> +               writel(high_cycles - 1,
> +                       spwmc->base + SIRF_PWM_GET_WAIT_OFFSET(pwm->hwpwm));
> +               writel(low_cycles - 1,
> +                       spwmc->base + SIRF_PWM_GET_HOLD_OFFSET(pwm->hwpwm));
> +
> +               mutex_unlock(&spwmc->mutex);
> +       }
> +}
> +
> +static int sirf_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
> +                       int duty_ns, int period_ns)
> +{
> +       struct sirf_pwm_chip *spwmc = to_sirf_pwm_chip(chip);
> +       struct sirf_pwm *spwm = pwm_get_chip_data(pwm);
> +
> +       if (!test_bit(PWMF_ENABLED, &pwm->flags)) {
> +               u32 src_clk_rate, src_clk_rate_min = ~0;
> +               u32 i;
> +               u64 cycle;
> +               u32 cycle_diff;
> +               u32 ns_diff, ns_diff_min = ~0;
> +               int ret;
> +               char src_clk_name[10];
> +               struct clk *sigsrc_clk;
> +
> +               /*
> +                * select a best source clock for the specific PWM clock
> +                * 1. select the clock with minimal error
> +                * 2. select the slower clock if some of them have
> +                *    the same error
> +                */
> +               for (i = 0; i < SIRF_MAX_SRC_CLK; i++) {
> +                       sprintf(src_clk_name, "sigsrc%d", i);
> +                       sigsrc_clk = devm_clk_get(chip->dev, src_clk_name);
> +                       if (IS_ERR(sigsrc_clk))
> +                               continue;
> +
> +                       src_clk_rate = clk_get_rate(sigsrc_clk);
> +
> +                       cycle = (u64)src_clk_rate * period_ns;
> +                       div_u64_rem(cycle, NSEC_PER_SEC, &cycle_diff);
> +
> +                       ns_diff = (u32)cycle_diff / src_clk_rate;
> +
> +                       if (ns_diff <= ns_diff_min &&
> +                                       src_clk_rate < src_clk_rate_min) {
> +                               ns_diff_min = ns_diff;
> +                               src_clk_rate_min = src_clk_rate;
> +                               spwm->sigsrc_clk_idx = i;
> +                               spwm->sigsrc_clk = sigsrc_clk;
> +                       } else {
> +                               devm_clk_put(chip->dev, sigsrc_clk);
> +                       }
> +               }
> +
> +               /*
> +                * enable PWM before writing the register
> +                */
> +               ret = clk_prepare_enable(spwmc->pwmc_clk);
> +               if (ret)
> +                       return ret;
> +       }
> +
> +       spwm->duty_ns = duty_ns;
> +
> +       _sirf_pwm_hwconfig(chip, pwm);

it looks weird if we config pwm if it has been enabled. the whole
produre to select suitable clock source is not executed?
and only duty_ns can be configed?

> +
> +       /*
> +        * if the PWM is not enabled, turn off the clock again
> +        */
> +       if (!test_bit(PWMF_ENABLED, &pwm->flags))
> +               clk_disable_unprepare(spwmc->pwmc_clk);
> +
> +       return 0;
> +}
> +
> +static void _sirf_pwm_hwenable(struct pwm_chip *chip, struct pwm_device *pwm)
> +{
> +       struct sirf_pwm_chip *spwmc = to_sirf_pwm_chip(chip);
> +       struct sirf_pwm *spwm = pwm_get_chip_data(pwm);
> +       u32 val;
> +
> +       mutex_lock(&spwmc->mutex);
> +
> +       /* disable preclock */
> +       val = readl(spwmc->base + SIRF_PWM_ENABLE_PRECLOCK);
> +       val &= ~(1 << pwm->hwpwm);
> +       writel(val, spwmc->base + SIRF_PWM_ENABLE_PRECLOCK);
> +
> +       /* select preclock source must after disable preclk */
> +       val = readl(spwmc->base + SIRF_PWM_SELECT_PRECLK);
> +       val &= ~(0x7 << (SRC_FIELD_SIZE * pwm->hwpwm));
> +       val |= (spwm->sigsrc_clk_idx << (SRC_FIELD_SIZE * pwm->hwpwm));
> +
> +       if (spwm->bypass_mode == 1)
> +               val |= (0x1 << (BYPASS_MODE_BIT + pwm->hwpwm));
> +       else
> +               val &= ~(0x1 << (BYPASS_MODE_BIT + pwm->hwpwm));
> +
> +       writel(val, spwmc->base + SIRF_PWM_SELECT_PRECLK);
> +
> +       /* wait for some time */
> +       usleep_range(100, 200);
> +
> +       /* enable preclock */
> +       val = readl(spwmc->base + SIRF_PWM_ENABLE_PRECLOCK);
> +       val |= (1 << pwm->hwpwm);
> +       writel(val, spwmc->base + SIRF_PWM_ENABLE_PRECLOCK);
> +
> +       /* enable post clock*/
> +       val = readl(spwmc->base + SIRF_PWM_ENABLE_POSTCLOCK);
> +       val |= (1 << pwm->hwpwm);
> +       writel(val, spwmc->base + SIRF_PWM_ENABLE_POSTCLOCK);
> +
> +       /* enable output */
> +       val = readl(spwmc->base + SIRF_PWM_OE);
> +       val |= 1 << pwm->hwpwm;
> +       val |= 1 << (pwm->hwpwm + TRANS_MODE_SELECT_BIT);
> +
> +       writel(val, spwmc->base + SIRF_PWM_OE);
> +
> +       mutex_unlock(&spwmc->mutex);
> +}
> +
> +static int sirf_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
> +{
> +       struct sirf_pwm_chip *spwmc = to_sirf_pwm_chip(chip);
> +       struct sirf_pwm *spwm = pwm_get_chip_data(pwm);
> +       u32 ret;
> +
> +       ret = clk_prepare_enable(spwm->sigsrc_clk);
> +       if (ret)
> +               return ret;
> +
> +       ret = clk_prepare_enable(spwmc->pwmc_clk);
> +       if (ret)
> +               return ret;
> +
> +       _sirf_pwm_hwenable(chip, pwm);
> +
> +       return 0;
> +}
> +
> +static void sirf_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
> +{
> +       u32 val;
> +       struct sirf_pwm_chip *spwmc = to_sirf_pwm_chip(chip);
> +       struct sirf_pwm *spwm = pwm_get_chip_data(pwm);
> +
> +       mutex_lock(&spwmc->mutex);
> +
> +       /* disable output */
> +       val = readl(spwmc->base + SIRF_PWM_OE);
> +       val &= ~(1 << pwm->hwpwm);
> +       writel(val, spwmc->base + SIRF_PWM_OE);
> +
> +       /* disable postclock */
> +       val = readl(spwmc->base + SIRF_PWM_ENABLE_POSTCLOCK);
> +       val &= ~(1 << pwm->hwpwm);
> +       writel(val, spwmc->base + SIRF_PWM_ENABLE_POSTCLOCK);
> +
> +       /* disable preclock */
> +       val = readl(spwmc->base + SIRF_PWM_ENABLE_PRECLOCK);
> +       val &= ~(1 << pwm->hwpwm);
> +       writel(val, spwmc->base + SIRF_PWM_ENABLE_PRECLOCK);
> +
> +       mutex_unlock(&spwmc->mutex);
> +
> +       clk_disable_unprepare(spwm->sigsrc_clk);
> +
> +       clk_disable_unprepare(spwmc->pwmc_clk);
> +}
> +
> +static const struct pwm_ops sirf_pwm_ops = {
> +       .request = sirf_pwm_request,
> +       .free = sirf_pwm_free,
> +       .enable = sirf_pwm_enable,
> +       .disable = sirf_pwm_disable,
> +       .config = sirf_pwm_config,
> +       .owner = THIS_MODULE,
> +};
> +
> +static int sirf_pwm_probe(struct platform_device *pdev)
> +{
> +       struct sirf_pwm_chip *spwmc;
> +       struct resource *mem_res;
> +       int ret;
> +
> +       spwmc = devm_kzalloc(&pdev->dev, sizeof(*spwmc),
> +                       GFP_KERNEL);
> +       if (!spwmc)
> +               return -ENOMEM;
> +
> +       platform_set_drvdata(pdev, spwmc);
> +
> +       mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +       spwmc->base = devm_ioremap_resource(&pdev->dev, mem_res);
> +       if (IS_ERR(spwmc->base))
> +               return PTR_ERR(spwmc->base);
> +
> +       /*
> +        * get clock for PWM controller
> +        */
> +       spwmc->pwmc_clk = devm_clk_get(&pdev->dev, "pwmc");
> +       if (IS_ERR(spwmc->pwmc_clk)) {
> +               dev_err(&pdev->dev, "failed to get PWM controller clock\n");
> +               return PTR_ERR(spwmc->pwmc_clk);
> +       }
> +
> +       spwmc->chip.dev = &pdev->dev;
> +       spwmc->chip.ops = &sirf_pwm_ops;
> +       spwmc->chip.base = -1;
> +       spwmc->chip.npwm = 7;
> +
> +       mutex_init(&spwmc->mutex);
> +
> +       ret = pwmchip_add(&spwmc->chip);
> +       if (ret < 0) {
> +               dev_err(&pdev->dev, "failed to register PWM chip\n");
> +               return ret;
> +       }
> +
> +       return 0;
> +}
> +
> +static int sirf_pwm_remove(struct platform_device *pdev)
> +{
> +       struct sirf_pwm_chip *spwmc = platform_get_drvdata(pdev);
> +
> +       return pwmchip_remove(&spwmc->chip);
> +}
> +
> +#ifdef CONFIG_PM_SLEEP
> +static int sirf_pwm_suspend(struct device *dev)
> +{
> +       struct sirf_pwm_chip *spwmc = dev_get_drvdata(dev);
> +       struct pwm_device *pwm;
> +       int i;
> +
> +       for (i = 0; i < spwmc->chip.npwm; i++) {
> +               pwm = &spwmc->chip.pwms[i];
> +               /*
> +                * disable PWM which is not disabled when user suspend
> +                */
> +               if (test_bit(PWMF_REQUESTED, &pwm->flags) &&
> +                               test_bit(PWMF_ENABLED, &pwm->flags))
> +                       sirf_pwm_disable(pwm->chip, pwm);
> +       }
> +
> +       return 0;
> +}
> +
> +static int sirf_pwm_resume(struct device *dev)
> +{
> +       struct sirf_pwm_chip *spwmc = dev_get_drvdata(dev);
> +       struct pwm_device *pwm;
> +       struct sirf_pwm *spwm;
> +       int i;
> +
> +       for (i = 0; i < spwmc->chip.npwm; i++) {
> +               pwm = &spwmc->chip.pwms[i];
> +               spwm = pwm_get_chip_data(pwm);
> +
> +               if (test_bit(PWMF_REQUESTED, &pwm->flags) &&
> +                               test_bit(PWMF_ENABLED, &pwm->flags)) {
> +                       sirf_pwm_config(&spwmc->chip, pwm, spwm->duty_ns,
> +                                       pwm_get_period(pwm));
> +                       sirf_pwm_enable(&spwmc->chip, pwm);
> +               }
> +       }
> +
> +       return 0;
> +}
> +
> +static int sirf_pwm_restore(struct device *dev)
> +{
> +       struct sirf_pwm_chip *spwmc = dev_get_drvdata(dev);
> +       struct pwm_device *pwm;
> +       struct sirf_pwm *spwm;
> +       int i;
> +
> +       for (i = 0; i < spwmc->chip.npwm; i++) {
> +               pwm = &spwmc->chip.pwms[i];
> +               spwm = pwm_get_chip_data(pwm);
> +               /*
> +                * while restoring from hibernation, state of PWM is enabled,
> +                * but PWM hardware is not re-enabled, register about config
> +                * and enable should be restored here
> +                */
> +               if (test_bit(PWMF_REQUESTED, &pwm->flags) &&
> +                               test_bit(PWMF_ENABLED, &pwm->flags)) {
> +                       _sirf_pwm_hwconfig(&spwmc->chip, pwm);
> +                       _sirf_pwm_hwenable(&spwmc->chip, pwm);
> +               }
> +       }
> +
> +       return 0;
> +}
> +#else
> +#define sirf_pwm_resume NULL
> +#define sirf_pwm_suspend NULL
> +#define sirf_pwm_restore NULL
> +#endif
> +
> +static const struct dev_pm_ops sirf_pwm_pm_ops = {
> +       .suspend = sirf_pwm_suspend,
> +       .resume = sirf_pwm_resume,
> +       .restore = sirf_pwm_restore,
> +};
> +
> +static const struct of_device_id sirf_pwm_of_match[] = {
> +       { .compatible = "sirf,prima2-pwm", },
> +       {}
> +};
> +MODULE_DEVICE_TABLE(of, sirf_pwm_of_match);
> +
> +static struct platform_driver sirf_pwm_driver = {
> +       .driver = {
> +               .name = "sirf-pwm",
> +               .pm = &sirf_pwm_pm_ops,
> +               .of_match_table = sirf_pwm_of_match,
> +       },
> +       .probe = sirf_pwm_probe,
> +       .remove = sirf_pwm_remove,
> +};
> +module_platform_driver(sirf_pwm_driver);
> +
> +MODULE_DESCRIPTION("SIRF serial SoC PWM device core driver");
> +MODULE_AUTHOR("RongJun Ying <Rongjun.Ying@csr.com>");
> +MODULE_AUTHOR("Huayi Li <huayi.li@csr.com>");
> +MODULE_LICENSE("GPL v2");
> --
> 1.9.3

-barry

^ permalink raw reply

* [PATCH] imx-drm: imx-drm-core: add suspend/resume support
From: Lucas Stach @ 2014-07-24  9:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1406193474-13695-1-git-send-email-shawn.guo@freescale.com>

Am Donnerstag, den 24.07.2014, 17:17 +0800 schrieb Shawn Guo:
> HDMI currently stops working after a system suspend/resume cycle.  It
> turns out that the cause is the imx-hdmi encoder .dpms hook doesn't get
> called from anywhere across suspend/resume cycle.
> 
> The patch follows what exynos drm driver does to walk the list of
> connectors and call their .dpms function from suspend/resume hook.  And
> the connectors' .dpms function will in turn filter down to the .dpms
> hooks of encoders and CRTCs.
> 
> With this change, HDMI can continue working after a suspend/resume
> cycle.
> 
> Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
> ---
> Tested with HDMI and LVDS.  It'd be great if someone can help test TVE
> to ensure the patch doesn't break anything.
> 
>  drivers/staging/imx-drm/imx-drm-core.c | 39 ++++++++++++++++++++++++++++++++++
>  1 file changed, 39 insertions(+)
> 
> diff --git a/drivers/staging/imx-drm/imx-drm-core.c b/drivers/staging/imx-drm/imx-drm-core.c
> index def8280d7ee6..b0ea1f0ed32f 100644
> --- a/drivers/staging/imx-drm/imx-drm-core.c
> +++ b/drivers/staging/imx-drm/imx-drm-core.c
> @@ -696,6 +696,44 @@ static int imx_drm_platform_remove(struct platform_device *pdev)
>  	return 0;
>  }
>  
> +#if CONFIG_PM_SLEEP

use #ifdef

> +static int imx_drm_suspend(struct device *dev)
> +{
> +	struct drm_device *drm_dev = dev_get_drvdata(dev);
> +	struct drm_connector *connector;
> +
> +	drm_kms_helper_poll_disable(drm_dev);
> +

That's ok.

> +	drm_modeset_lock_all(drm_dev);
> +	list_for_each_entry(connector, &drm_dev->mode_config.connector_list, head) {
> +		if (connector->funcs->dpms)
> +			connector->funcs->dpms(connector, DRM_MODE_DPMS_OFF);
> +	}

Don't touch DPMS state here. See below.

> +	drm_modeset_unlock_all(drm_dev);
> +
> +	return 0;
> +}
> +
> +static int imx_drm_resume(struct device *dev)
> +{
> +	struct drm_device *drm_dev = dev_get_drvdata(dev);
> +	struct drm_connector *connector;
> +
> +	drm_modeset_lock_all(drm_dev);
> +	list_for_each_entry(connector, &drm_dev->mode_config.connector_list, head) {
> +		if (connector->funcs->dpms)
> +			connector->funcs->dpms(connector, DRM_MODE_DPMS_ON);
> +	}
> +	drm_modeset_unlock_all(drm_dev);
> +
This forcefully enables all connectors, which might not have been the
state before suspend. Have a look at simply using
drm_helper_resume_force_mode(), which should do the right thing.

> +	drm_kms_helper_poll_enable(drm_dev);
> +
> +	return 0;
> +}
> +#endif
> +
> +static SIMPLE_DEV_PM_OPS(imx_drm_pm_ops, imx_drm_suspend, imx_drm_resume);
> +
>  static const struct of_device_id imx_drm_dt_ids[] = {
>  	{ .compatible = "fsl,imx-display-subsystem", },
>  	{ /* sentinel */ },
> @@ -708,6 +746,7 @@ static struct platform_driver imx_drm_pdrv = {
>  	.driver		= {
>  		.owner	= THIS_MODULE,
>  		.name	= "imx-drm",
> +		.pm	= &imx_drm_pm_ops,
>  		.of_match_table = imx_drm_dt_ids,
>  	},
>  };

Regards,
Lucas
-- 
Pengutronix e.K.             | Lucas Stach                 |
Industrial Linux Solutions   | http://www.pengutronix.de/  |

^ permalink raw reply

* [PATCH v2 1/2] clk: samsung: exynos4: Enable ARMCLK down feature
From: Krzysztof Kozlowski @ 2014-07-24  9:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1406184144.8807.4.camel@AMDC1943>

On czw, 2014-07-24 at 08:42 +0200, Krzysztof Kozlowski wrote:
> On ?ro, 2014-07-23 at 17:18 -0700, Mike Turquette wrote:
> > Quoting Krzysztof Kozlowski (2014-07-18 07:36:32)
> > > Enable ARMCLK down feature on all Exynos4 SoCs. The frequency of
> > > ARMCLK will be reduced upon entering idle mode (WFI or WFE).
> > > 
> > > The feature behaves like very fast cpufreq ondemand governor. In idle
> > > mode this reduces energy consumption on full frequency chosen by
> > > cpufreq governor by approximately:
> > >  - Trats2:  6.5% (153 mA -> 143 mA)
> > >  - Trats:  33.0% (180 mA -> 120 mA)
> > >  - Gear1:  27.0% (180 mA -> 130 mA)
> > 
> > Nice power savings! Just a quick question on this feature: the clock
> > frequency is changed in hardware as a result of WFI/WFE?
> 
> Yes. This feature makes changes in DIVCORE and DIVCORE2 clock dividers
> when given core enters WFI/WFE.
> 
> > And this only
> > happens when all CPUs in a cluster (e.g. all 4 CPUs in Exynos 4412) are
> > in WFI/WFE state?
> 
> No, this is per-core. However measured energy savings above were in case
> where all cores entered idle (WFI).

Aaargh, that is obviously incorrect, my mistake. You're right that this
is for whole cluster as all cores share ARMCLK (and clock dividers).
However you can enable WFI/WFE detection per core. 

The datasheet does not describe what will happen exactly when you enable
the WFI/WFE detection for core0 and leave it disabled for other cores. I
assume that upon entering WFI on core0 everything will be slowed down
regardless of pending work on other cores but I didn't test it.

Best regards,
Krzysztof

> 
> Best regards,
> Krzysztof
> 
> 
> > 
> > Thanks,
> > Mike
> > 
> > > 
> > > The patch uses simillar settings as Exynos5250 (clk-exynos5250.c),
> > > except it disables clock up feature and on Exynos4412 ARMCLK down is
> > > enabled for all 4 cores.
> > > 
> > > Tested on Trats board (Exynos4210), Trats2 board (Exynos4412) and
> > > Samsung Gear 1 (Exynos4212).
> > > 
> > > Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
> > > 
> > > ---
> > > 
> > > Changes since v1:
> > > 1. Add PWR_CTRL registers to the list of saved clk registers on
> > >    Exynos4x12. Suggested by Tomasz Figa.
> > > 2. Disable the clock up feature. (sug. Tomasz Figa)
> > > 3. Use macros for setting clock down ratio. (sug. Tomasz Figa)
> > > 4. Use num_possible_cpus() for exception on Exynos4x12. (sug. Tomasz
> > >    Figa)
> > > 5. Enable the clock down feature also on Exynos4210 Trats board.
> > > ---
> > >  drivers/clk/samsung/clk-exynos4.c | 46 +++++++++++++++++++++++++++++++++++++++
> > >  1 file changed, 46 insertions(+)
> > > 
> > > diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
> > > index 7f4a473a7ad7..86c7709dc6d6 100644
> > > --- a/drivers/clk/samsung/clk-exynos4.c
> > > +++ b/drivers/clk/samsung/clk-exynos4.c
> > > @@ -114,11 +114,27 @@
> > >  #define DIV_CPU1               0x14504
> > >  #define GATE_SCLK_CPU          0x14800
> > >  #define GATE_IP_CPU            0x14900
> > > +#define PWR_CTRL1              0x15020
> > > +#define E4X12_PWR_CTRL2                0x15024
> > >  #define E4X12_DIV_ISP0         0x18300
> > >  #define E4X12_DIV_ISP1         0x18304
> > >  #define E4X12_GATE_ISP0                0x18800
> > >  #define E4X12_GATE_ISP1                0x18804
> > >  
> > > +/* Below definitions are used for PWR_CTRL settings */
> > > +#define PWR_CTRL1_CORE2_DOWN_RATIO(x)          (((x) & 0x7) << 28)
> > > +#define PWR_CTRL1_CORE1_DOWN_RATIO(x)          (((x) & 0x7) << 16)
> > > +#define PWR_CTRL1_DIV2_DOWN_EN                 (1 << 9)
> > > +#define PWR_CTRL1_DIV1_DOWN_EN                 (1 << 8)
> > > +#define PWR_CTRL1_USE_CORE3_WFE                        (1 << 7)
> > > +#define PWR_CTRL1_USE_CORE2_WFE                        (1 << 6)
> > > +#define PWR_CTRL1_USE_CORE1_WFE                        (1 << 5)
> > > +#define PWR_CTRL1_USE_CORE0_WFE                        (1 << 4)
> > > +#define PWR_CTRL1_USE_CORE3_WFI                        (1 << 3)
> > > +#define PWR_CTRL1_USE_CORE2_WFI                        (1 << 2)
> > > +#define PWR_CTRL1_USE_CORE1_WFI                        (1 << 1)
> > > +#define PWR_CTRL1_USE_CORE0_WFI                        (1 << 0)
> > > +
> > >  /* the exynos4 soc type */
> > >  enum exynos4_soc {
> > >         EXYNOS4210,
> > > @@ -155,6 +171,7 @@ static unsigned long exynos4210_clk_save[] __initdata = {
> > >         E4210_GATE_IP_LCD1,
> > >         E4210_GATE_IP_PERIR,
> > >         E4210_MPLL_CON0,
> > > +       PWR_CTRL1,
> > >  };
> > >  
> > >  static unsigned long exynos4x12_clk_save[] __initdata = {
> > > @@ -164,6 +181,8 @@ static unsigned long exynos4x12_clk_save[] __initdata = {
> > >         E4X12_DIV_ISP,
> > >         E4X12_DIV_CAM1,
> > >         E4X12_MPLL_CON0,
> > > +       PWR_CTRL1,
> > > +       E4X12_PWR_CTRL2,
> > >  };
> > >  
> > >  static unsigned long exynos4_clk_pll_regs[] __initdata = {
> > > @@ -1164,6 +1183,32 @@ static struct samsung_pll_clock exynos4x12_plls[nr_plls] __initdata = {
> > >                         VPLL_LOCK, VPLL_CON0, NULL),
> > >  };
> > >  
> > > +static void __init exynos4_core_down_clock(enum exynos4_soc soc)
> > > +{
> > > +       unsigned int tmp;
> > > +
> > > +       /*
> > > +        * Enable arm clock down (in idle) and set arm divider
> > > +        * ratios in WFI/WFE state.
> > > +        */
> > > +       tmp = (PWR_CTRL1_CORE2_DOWN_RATIO(7) | PWR_CTRL1_CORE1_DOWN_RATIO(7) |
> > > +               PWR_CTRL1_DIV2_DOWN_EN | PWR_CTRL1_DIV1_DOWN_EN |
> > > +               PWR_CTRL1_USE_CORE1_WFE | PWR_CTRL1_USE_CORE0_WFE |
> > > +               PWR_CTRL1_USE_CORE1_WFI | PWR_CTRL1_USE_CORE0_WFI);
> > > +       /* On Exynos4412 enable it also on core 2 and 3 */
> > > +       if (num_possible_cpus() == 4)
> > > +               tmp |= PWR_CTRL1_USE_CORE3_WFE | PWR_CTRL1_USE_CORE2_WFE |
> > > +                      PWR_CTRL1_USE_CORE3_WFI | PWR_CTRL1_USE_CORE2_WFI;
> > > +       __raw_writel(tmp, reg_base + PWR_CTRL1);
> > > +
> > > +       /*
> > > +        * Disable the clock up feature on Exynos4x12, in case it was
> > > +        * enabled by bootloader.
> > > +        */
> > > +       if (exynos4_soc == EXYNOS4X12)
> > > +               __raw_writel(0x0, reg_base + E4X12_PWR_CTRL2);
> > > +}
> > > +
> > >  /* register exynos4 clocks */
> > >  static void __init exynos4_clk_init(struct device_node *np,
> > >                                     enum exynos4_soc soc)
> > > @@ -1250,6 +1295,7 @@ static void __init exynos4_clk_init(struct device_node *np,
> > >         samsung_clk_register_alias(ctx, exynos4_aliases,
> > >                         ARRAY_SIZE(exynos4_aliases));
> > >  
> > > +       exynos4_core_down_clock(soc);
> > >         exynos4_clk_sleep_init();
> > >  
> > >         pr_info("%s clocks: sclk_apll = %ld, sclk_mpll = %ld\n"
> > > -- 
> > > 1.9.1
> > > 

^ permalink raw reply

* [PATCH] imx-drm: imx-drm-core: add suspend/resume support
From: Philipp Zabel @ 2014-07-24  9:38 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1406193474-13695-1-git-send-email-shawn.guo@freescale.com>

Hi Shawn,

Am Donnerstag, den 24.07.2014, 17:17 +0800 schrieb Shawn Guo:
> HDMI currently stops working after a system suspend/resume cycle.  It
> turns out that the cause is the imx-hdmi encoder .dpms hook doesn't get
> called from anywhere across suspend/resume cycle.
> 
> The patch follows what exynos drm driver does to walk the list of
> connectors and call their .dpms function from suspend/resume hook.  And
> the connectors' .dpms function will in turn filter down to the .dpms
> hooks of encoders and CRTCs.
> 
> With this change, HDMI can continue working after a suspend/resume
> cycle.
> 
> Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
> ---
> Tested with HDMI and LVDS.  It'd be great if someone can help test TVE
> to ensure the patch doesn't break anything.

Tested-by: Philipp Zabel <p.zabel@pengutronix.de>

on i.MX53-QSB with VGA via TVE.

regards
Philipp

^ permalink raw reply

* Kexec on arm64
From: Mark Rutland @ 2014-07-24  9:36 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1406162287.4062.39.camel@smoke>

On Thu, Jul 24, 2014 at 01:38:07AM +0100, Geoff Levand wrote:
> Hi Arun,
> 
> On Tue, 2014-07-22 at 18:55 +0530, Arun Chandran wrote:
> 
> > I tried the same dtb with UP configuration. For UP kernel to compile
> > did the below modifications
> 
> I'll test and fixup the kexec UP build in the next few days.
> 
> ...
> 
> > With the default target configuration "kexec -e" failed to execute
> > in UP scenario also.

It would be helpful to know _how_ it failed. Do you have any log output?

> > 
> > But I had some luck when I did the same steps with L3 cache
> > disabled. According to http://www.spinics.net/lists/arm-kernel/msg329541.html
> > it has an L3 cache. Luckily I was able to disable it in u-boot.
> > 
> > With the L3 cache disabled configuration I am able to
> > do "kexec -e". Please see the log attached.

Hmm. We don't expect the kernel to do any L3 management. It seems that
memory subsystems with L3 caches respecting cache maintenance by VA are
going to become relatively common, and we expect to handle them all by
performing maintenance by VA. See commit c218bca74eea (arm64: Relax the
kernel cache requirements for boot) for what we do at boot time.

> 
> All memory management for the main cpu is done by the arch code.  Kexec
> and cpu hot plug only work with the secondary cpus, so the problem would
> be in the arch memory code, either in setup_restart() for shutdown, or
> in the startup code.

It's possible that soft_restart and setup_restart are a little dodgy, as
they also rely on the compiler being smart and not touching the stack
after setup_restart().

However, they provide absolutely no guarantee that any data has been
flushed out to the PoC [1]. If you require any data to be flushed out to the
PoC so as to be visible to noncacheable accesses, you will need to
ensure that this is flushed by VA before soft_restart is called. Data
may have migrated to another cache (e.g. another CPU, or the L3) where
it is not visible.

> 
> I guess setup_restart() is not doing something it needs to do for your
> platform.

Unless you can see soft_restart/setup_restart making stack accesses
after the first flush_cache_all call, I suspect your code is not
flushing some data it requires.

I'd been meaning to clean up soft_restart and setup_restart for a while.
I'll have a go at cleaning them up along with any remaining
flush_cache_all abuse in arm64.

Thanks,
Mark.

^ permalink raw reply

* [PATCH v5 4/4] ARM: prima2_defconfig: enable PWM and sirf PWM driver
From: Barry Song @ 2014-07-24  9:31 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1405475714-10006-5-git-send-email-huayi.li@csr.com>

2014-07-16 9:55 GMT+08:00 Huayi Li <huayi.li@csr.com>:
> Signed-off-by: Huayi Li <huayi.li@csr.com>

Acked-by: Barry Song <Baohua.Song@csr.com>

> ---
>  arch/arm/configs/prima2_defconfig | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/arch/arm/configs/prima2_defconfig b/arch/arm/configs/prima2_defconfig
> index 23591db..303204a 100644
> --- a/arch/arm/configs/prima2_defconfig
> +++ b/arch/arm/configs/prima2_defconfig
> @@ -50,6 +50,8 @@ CONFIG_DMADEVICES_DEBUG=y
>  CONFIG_DMADEVICES_VDEBUG=y
>  CONFIG_SIRF_DMA=y
>  # CONFIG_IOMMU_SUPPORT is not set
> +CONFIG_PWM=y
> +CONFIG_PWM_SIRF=y
>  CONFIG_EXT2_FS=y
>  CONFIG_MSDOS_FS=y
>  CONFIG_VFAT_FS=y
> --
> 1.9.3
>

^ permalink raw reply

* [PATCH v3 2/2] pwm: rockchip: Added to support for RK3288 SoC
From: caesar @ 2014-07-24  9:29 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1949437.1N5XrQ9a4Y@diego>

Hi Heiko,

? 2014?07?24? 16:05, Heiko St?bner ??:
> Hi caesar.
>
> Am Donnerstag, 24. Juli 2014, 10:13:55 schrieb caesar:
>>>> +static void rockchip_pwm_set_enable_v1(struct pwm_chip *chip, bool
>>>> enable)
>>>> +{
>>>> +	struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
>>>> +	u32 val = 0;
>>>> +	u32 enable_conf = PWM_CTRL_OUTPUT_EN | PWM_CTRL_TIMER_EN;
>>>> +
>>>> +	val = readl_relaxed(pc->base + pc->data->regs.ctrl);
>>>> +
>>>> +	if (enable)
>>>> +		val |= enable_conf;
>>>> +	else
>>>> +		val &= ~enable_conf;
>>>> +
>>>> +	writel_relaxed(val, pc->base + pc->data->regs.ctrl);
>>>> +}
>>>> +
>>>> +static void rockchip_pwm_set_enable_v2(struct pwm_chip *chip, bool
>>>> enable)
>>>> +{
>>>> +	struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
>>>> +	u32 val = 0;
>>>> +	u32 enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE |
>>>> +		PWM_CONTINUOUS | PWM_DUTY_POSITIVE | PWM_INACTIVE_NEGATIVE;
>>>> +
>>>> +	val = readl_relaxed(pc->base + pc->data->regs.ctrl);
>>>> +
>>>> +	if (enable)
>>>> +		val |= enable_conf;
>>>> +	else
>>>> +		val &= ~enable_conf;
>>>> +
>>>> +	writel_relaxed(val, pc->base + pc->data->regs.ctrl);
>>>> +}
>>>> +
>>>> +static void rockchip_pwm_set_enable_vop(struct pwm_chip *chip, bool
>>>> enable) +{
>>>> +	struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
>>>> +	u32 val = 0;
>>>> +	u32 enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE |
>>>> +		PWM_CONTINUOUS | PWM_DUTY_POSITIVE | PWM_INACTIVE_NEGATIVE;
>>>> +
>>>> +	val = readl_relaxed(pc->base + pc->data->regs.ctrl);
>>>> +
>>>> +	if (enable)
>>>> +		val |= enable_conf;
>>>> +	else
>>>> +		val &= ~enable_conf;
>>>> +
>>>> +	writel_relaxed(val, pc->base + pc->data->regs.ctrl);
>>>> +}
>>> not sure if I'm just blind ... do rockchip_pwm_set_enable_v2 and
>>> rockchip_pwm_set_enable_vop differ at all?
>>>
>>> If they don't differ, I guess pwm_data_vop should just use
>>> rockchip_pwm_set_enable_v2 instead of duplicating it.
>>>
>> Yes, the rockchip_pwm_set_enable_v1 & v2 & vop is similar.
>>
>> So my v2 patch use "u32 enable_conf" instead of it .
>> +struct rockchip_pwm_data {
>>
>>   > + .........
>>   > + u32 enable_conf;
>>   > +};
>>
>> The thierry has suggested it [1] in my v2 patch:
>>
>> For this I think it would be more readable to provide function pointers
>> rather than a variable. That is:
>>
>> 	struct rockchip_pwm_data {
>> 		...
>> 		int (*enable)(struct pwm_chip *chip, struct pwm_device *pwm);
>> 		int (*disable)(struct pwm_chip *chip, struct pwm_device *pwm);
>> 	};
>> Then you can implement these for each variant of the chip and call them
>> from the common rockchip_pwm_enable(), somewhat like this.
>>
>>
>> Perhaps,thierry's suggestion I got it wrong.
> Using the function pointers like Thierry suggested looks nice, so no I don't
> think you got it wrong :-)
>
> What I meant was to simply reuse the existing function
> rockchip_pwm_set_enable_v2 when there is _no_ difference at all to
> rockchip_pwm_set_enable_vop, like
>
> static const struct rockchip_pwm_data pwm_data_v2 = {
> 	.regs.duty = PWM_LRC,
> 	.regs.period = PWM_HRC,
> 	.regs.cntr = PWM_CNTR,
> 	.regs.ctrl = PWM_CTRL,
> 	.prescaler = PRESCALER-1,
> 	.set_enable = rockchip_pwm_set_enable_v2,
> };
>
> static const struct rockchip_pwm_data pwm_data_vop = {
> 	.regs.duty = PWM_LRC,
> 	.regs.period = PWM_HRC,
> 	.regs.cntr = PWM_CTRL,
> 	.regs.ctrl = PWM_CNTR,
> 	.prescaler = PRESCALER-1,
> 	.set_enable = rockchip_pwm_set_enable_v2,
> };
>
>
> Heiko
:-( ok, I will fix this and the other issuses in v4, thanks.
>> Hi thierry& Heiko :-)
>> Maybe,could you suggest solve it reasonable? thanks.
>>
>> [1]: https://lkml.org/lkml/2014/7/21/113
>>
>>>> +
>>>>
>>>>    static int rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device
>>>>
>>>> *pwm, int duty_ns, int period_ns)
>>>>
>>>>    {
>>>>
>>>> @@ -52,20 +126,20 @@ static int rockchip_pwm_config(struct pwm_chip
>>>> *chip,
>>>> struct pwm_device *pwm, * default prescaler value for all practical clock
>>>> rate values.
>>>>
>>>>    	 */
>>>>    	
>>>>    	div = clk_rate * period_ns;
>>>>
>>>> -	do_div(div, PRESCALER * NSEC_PER_SEC);
>>>> +	do_div(div, pc->data->prescaler * NSEC_PER_SEC);
>>>>
>>>>    	period = div;
>>>>    	
>>>>    	div = clk_rate * duty_ns;
>>>>
>>>> -	do_div(div, PRESCALER * NSEC_PER_SEC);
>>>> +	do_div(div, pc->data->prescaler * NSEC_PER_SEC);
>>>>
>>>>    	duty = div;
>>>>    	
>>>>    	ret = clk_enable(pc->clk);
>>>>    	if (ret)
>>>>    	
>>>>    		return ret;
>>>>
>>>> -	writel(period, pc->base + PWM_LRC);
>>>> -	writel(duty, pc->base + PWM_HRC);
>>>> -	writel(0, pc->base + PWM_CNTR);
>>>> +	writel(period, pc->base + pc->data->regs.period);
>>>> +	writel(duty, pc->base + pc->data->regs.duty);
>>>> +	writel(0, pc->base + pc->data->regs.cntr);
>>>>
>>>>    	clk_disable(pc->clk);
>>>>
>>>> @@ -76,15 +150,12 @@ static int rockchip_pwm_enable(struct pwm_chip
>>>> *chip,
>>>> struct pwm_device *pwm) {
>>>>
>>>>    	struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
>>>>    	int ret;
>>>>
>>>> -	u32 val;
>>>>
>>>>    	ret = clk_enable(pc->clk);
>>>>    	if (ret)
>>>>    	
>>>>    		return ret;
>>>>
>>>> -	val = readl_relaxed(pc->base + PWM_CTRL);
>>>> -	val |= PWM_CTRL_OUTPUT_EN | PWM_CTRL_TIMER_EN;
>>>> -	writel_relaxed(val, pc->base + PWM_CTRL);
>>>> +	pc->data->set_enable(chip, true);
>>>>
>>>>    	return 0;
>>>>    
>>>>    }
>>>>
>>>> @@ -92,11 +163,8 @@ static int rockchip_pwm_enable(struct pwm_chip *chip,
>>>> struct pwm_device *pwm) static void rockchip_pwm_disable(struct pwm_chip
>>>> *chip, struct pwm_device *pwm) {
>>>>
>>>>    	struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
>>>>
>>>> -	u32 val;
>>>>
>>>> -	val = readl_relaxed(pc->base + PWM_CTRL);
>>>> -	val &= ~(PWM_CTRL_OUTPUT_EN | PWM_CTRL_TIMER_EN);
>>>> -	writel_relaxed(val, pc->base + PWM_CTRL);
>>>> +	pc->data->set_enable(chip, false);
>>>>
>>>>    	clk_disable(pc->clk);
>>>>    
>>>>    }
>>>>
>>>> @@ -108,12 +176,52 @@ static const struct pwm_ops rockchip_pwm_ops = {
>>>>
>>>>    	.owner = THIS_MODULE,
>>>>    
>>>>    };
>>>>
>>>> +static const struct rockchip_pwm_data pwm_data_v1 = {
>>>> +	.regs.duty = PWM_HRC,
>>>> +	.regs.period = PWM_LRC,
>>>> +	.regs.cntr = PWM_CNTR,
>>>> +	.regs.ctrl = PWM_CTRL,
>>>> +	.prescaler = PRESCALER,
>>>> +	.set_enable = rockchip_pwm_set_enable_v1,
>>>> +};
>>>> +
>>>> +static const struct rockchip_pwm_data pwm_data_v2 = {
>>>> +	.regs.duty = PWM_LRC,
>>>> +	.regs.period = PWM_HRC,
>>>> +	.regs.cntr = PWM_CNTR,
>>>> +	.regs.ctrl = PWM_CTRL,
>>>> +	.prescaler = PRESCALER-1,
>>>> +	.set_enable = rockchip_pwm_set_enable_v2,
>>>> +};
>>>> +
>>>> +static const struct rockchip_pwm_data pwm_data_vop = {
>>>> +	.regs.duty = PWM_LRC,
>>>> +	.regs.period = PWM_HRC,
>>>> +	.regs.cntr = PWM_CTRL,
>>>> +	.regs.ctrl = PWM_CNTR,
>>>> +	.prescaler = PRESCALER-1,
>>>> +	.set_enable = rockchip_pwm_set_enable_vop,
>>>> +};
>>>> +
>>>> +static const struct of_device_id rockchip_pwm_dt_ids[] = {
>>>> +	{ .compatible = "rockchip,rk2928-pwm", .data = &pwm_data_v1},
>>>> +	{ .compatible = "rockchip,rk3288-pwm", .data = &pwm_data_v2},
>>>> +	{ .compatible = "rockchip,vop-pwm", .data = &pwm_data_vop},
>>>> +	{ /* sentinel */ }
>>>> +};
>>>> +MODULE_DEVICE_TABLE(of, rockchip_pwm_dt_ids);
>>>> +
>>>>
>>>>    static int rockchip_pwm_probe(struct platform_device *pdev)
>>>>    {
>>>>
>>>> +	const struct of_device_id *id;
>>>>
>>>>    	struct rockchip_pwm_chip *pc;
>>>>    	struct resource *r;
>>>>    	int ret;
>>>>
>>>> +	id = of_match_device(rockchip_pwm_dt_ids, &pdev->dev);
>>>> +	if (!id)
>>>> +		return -EINVAL;
>>>> +
>>>>
>>>>    	pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL);
>>>>    	if (!pc)
>>>>    	
>>>>    		return -ENOMEM;
>>>>
>>>> @@ -133,6 +241,7 @@ static int rockchip_pwm_probe(struct platform_device
>>>> *pdev)
>>>>
>>>>    	platform_set_drvdata(pdev, pc);
>>>>
>>>> +	pc->data = id->data;
>>>>
>>>>    	pc->chip.dev = &pdev->dev;
>>>>    	pc->chip.ops = &rockchip_pwm_ops;
>>>>    	pc->chip.base = -1;
>>>>
>>>> @@ -156,12 +265,6 @@ static int rockchip_pwm_remove(struct
>>>> platform_device
>>>> *pdev) return pwmchip_remove(&pc->chip);
>>>>
>>>>    }
>>>>
>>>> -static const struct of_device_id rockchip_pwm_dt_ids[] = {
>>>> -	{ .compatible = "rockchip,rk2928-pwm" },
>>>> -	{ /* sentinel */ }
>>>> -};
>>>> -MODULE_DEVICE_TABLE(of, rockchip_pwm_dt_ids);
>>>> -
>>>>
>>>>    static struct platform_driver rockchip_pwm_driver = {
>>>>    
>>>>    	.driver = {
>>>>    	
>>>>    		.name = "rockchip-pwm",
>
>
>

^ permalink raw reply

* [PATCH] imx-drm: imx-drm-core: add suspend/resume support
From: Shawn Guo @ 2014-07-24  9:17 UTC (permalink / raw)
  To: linux-arm-kernel

HDMI currently stops working after a system suspend/resume cycle.  It
turns out that the cause is the imx-hdmi encoder .dpms hook doesn't get
called from anywhere across suspend/resume cycle.

The patch follows what exynos drm driver does to walk the list of
connectors and call their .dpms function from suspend/resume hook.  And
the connectors' .dpms function will in turn filter down to the .dpms
hooks of encoders and CRTCs.

With this change, HDMI can continue working after a suspend/resume
cycle.

Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
---
Tested with HDMI and LVDS.  It'd be great if someone can help test TVE
to ensure the patch doesn't break anything.

 drivers/staging/imx-drm/imx-drm-core.c | 39 ++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/drivers/staging/imx-drm/imx-drm-core.c b/drivers/staging/imx-drm/imx-drm-core.c
index def8280d7ee6..b0ea1f0ed32f 100644
--- a/drivers/staging/imx-drm/imx-drm-core.c
+++ b/drivers/staging/imx-drm/imx-drm-core.c
@@ -696,6 +696,44 @@ static int imx_drm_platform_remove(struct platform_device *pdev)
 	return 0;
 }
 
+#if CONFIG_PM_SLEEP
+static int imx_drm_suspend(struct device *dev)
+{
+	struct drm_device *drm_dev = dev_get_drvdata(dev);
+	struct drm_connector *connector;
+
+	drm_kms_helper_poll_disable(drm_dev);
+
+	drm_modeset_lock_all(drm_dev);
+	list_for_each_entry(connector, &drm_dev->mode_config.connector_list, head) {
+		if (connector->funcs->dpms)
+			connector->funcs->dpms(connector, DRM_MODE_DPMS_OFF);
+	}
+	drm_modeset_unlock_all(drm_dev);
+
+	return 0;
+}
+
+static int imx_drm_resume(struct device *dev)
+{
+	struct drm_device *drm_dev = dev_get_drvdata(dev);
+	struct drm_connector *connector;
+
+	drm_modeset_lock_all(drm_dev);
+	list_for_each_entry(connector, &drm_dev->mode_config.connector_list, head) {
+		if (connector->funcs->dpms)
+			connector->funcs->dpms(connector, DRM_MODE_DPMS_ON);
+	}
+	drm_modeset_unlock_all(drm_dev);
+
+	drm_kms_helper_poll_enable(drm_dev);
+
+	return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(imx_drm_pm_ops, imx_drm_suspend, imx_drm_resume);
+
 static const struct of_device_id imx_drm_dt_ids[] = {
 	{ .compatible = "fsl,imx-display-subsystem", },
 	{ /* sentinel */ },
@@ -708,6 +746,7 @@ static struct platform_driver imx_drm_pdrv = {
 	.driver		= {
 		.owner	= THIS_MODULE,
 		.name	= "imx-drm",
+		.pm	= &imx_drm_pm_ops,
 		.of_match_table = imx_drm_dt_ids,
 	},
 };
-- 
1.9.1

^ permalink raw reply related

* [RFC] PCI: pcie-designware: allow drivers as loadable modules
From: Arnd Bergmann @ 2014-07-24  9:17 UTC (permalink / raw)
  To: linux-arm-kernel

>From 0ee79c7451851a34e5a7c33eb6020befcdcb2b24 Mon Sep 17 00:00:00 2001
From: Arnd Bergmann <arnd@arndb.de>
Date: Thu, 24 Jul 2014 11:12:48 +0200
Subject: [PATCH] PCI: pcie-designware: allow drivers as loadable modules

The new pcie-spear13xx driver uses the pcie-designware library
and in the current form it can be built as a loadable module.
However, the functions it uses from the base driver are not exported,
so this results in a build failure and a module that can never
be loaded:

ERROR: "dw_pcie_host_init" [drivers/pci/host/pcie-spear13xx.ko] undefined!
ERROR: "dw_handle_msi_irq" [drivers/pci/host/pcie-spear13xx.ko] undefined!
ERROR: "dw_pcie_msi_init" [drivers/pci/host/pcie-spear13xx.ko] undefined!
ERROR: "dw_pcie_cfg_write" [drivers/pci/host/pcie-spear13xx.ko] undefined!
ERROR: "dw_pcie_cfg_read" [drivers/pci/host/pcie-spear13xx.ko] undefined!
ERROR: "dw_pcie_setup_rc" [drivers/pci/host/pcie-spear13xx.ko] undefined!
ERROR: "dw_pcie_link_up" [drivers/pci/host/pcie-spear13xx.ko] undefined!

If we want to allow loadable pcie-designware drivers, we have to
export all those symbols and ensure none of them are marked as __init.
This also requires making pci_assign_unassigned_resources available
after boot.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
If we don't want this patch for some reason, we should instead mark
this driver 'bool' in Kconfig, so it becomes impossible to encounter
this build error.

diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
index 1eaf4df3618a..0348408ebc68 100644
--- a/drivers/pci/host/pcie-designware.c
+++ b/drivers/pci/host/pcie-designware.c
@@ -88,6 +88,7 @@ int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32 *val)
 
 	return PCIBIOS_SUCCESSFUL;
 }
+EXPORT_SYMBOL_GPL(dw_pcie_cfg_read);
 
 int dw_pcie_cfg_write(void __iomem *addr, int where, int size, u32 val)
 {
@@ -102,6 +103,7 @@ int dw_pcie_cfg_write(void __iomem *addr, int where, int size, u32 val)
 
 	return PCIBIOS_SUCCESSFUL;
 }
+EXPORT_SYMBOL_GPL(dw_pcie_cfg_write);
 
 static inline void dw_pcie_readl_rc(struct pcie_port *pp, u32 reg, u32 *val)
 {
@@ -182,6 +184,7 @@ irqreturn_t dw_handle_msi_irq(struct pcie_port *pp)
 
 	return ret;
 }
+EXPORT_SYMBOL_GPL(dw_handle_msi_irq);
 
 void dw_pcie_msi_init(struct pcie_port *pp)
 {
@@ -192,6 +195,7 @@ void dw_pcie_msi_init(struct pcie_port *pp)
 			virt_to_phys((void *)pp->msi_data));
 	dw_pcie_wr_own_conf(pp, PCIE_MSI_ADDR_HI, 4, 0);
 }
+EXPORT_SYMBOL_GPL(dw_pcie_msi_init);
 
 static int find_valid_pos0(struct pcie_port *pp, int msgvec, int pos, int *pos0)
 {
@@ -378,6 +382,7 @@ int dw_pcie_link_up(struct pcie_port *pp)
 	else
 		return 0;
 }
+EXPORT_SYMBOL_GPL(dw_pcie_link_up);
 
 static int dw_pcie_msi_map(struct irq_domain *domain, unsigned int irq,
 			irq_hw_number_t hwirq)
@@ -393,7 +398,7 @@ static const struct irq_domain_ops msi_domain_ops = {
 	.map = dw_pcie_msi_map,
 };
 
-int __init dw_pcie_host_init(struct pcie_port *pp)
+int dw_pcie_host_init(struct pcie_port *pp)
 {
 	struct device_node *np = pp->dev->of_node;
 	struct of_pci_range range;
@@ -503,6 +508,7 @@ int __init dw_pcie_host_init(struct pcie_port *pp)
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(dw_pcie_host_init);
 
 static void dw_pcie_prog_viewport_cfg0(struct pcie_port *pp, u32 busdev)
 {
@@ -829,6 +835,7 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
 		PCI_COMMAND_MASTER | PCI_COMMAND_SERR;
 	dw_pcie_writel_rc(pp, val, PCI_COMMAND);
 }
+EXPORT_SYMBOL_GPL(dw_pcie_setup_rc);
 
 MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>");
 MODULE_DESCRIPTION("Designware PCIe host controller driver");
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 6373985ad3f7..eeef7a1f4d0d 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -1634,7 +1634,7 @@ dump:
 	pci_bus_dump_resources(bus);
 }
 
-void __init pci_assign_unassigned_resources(void)
+void pci_assign_unassigned_resources(void)
 {
 	struct pci_bus *root_bus;
 

^ permalink raw reply related

* [PATCHv3 13/16] cpuidle: mvebu: add Armada 38x support
From: Daniel Lezcano @ 2014-07-24  9:17 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1406120453-29291-14-git-send-email-thomas.petazzoni@free-electrons.com>

On 07/23/2014 03:00 PM, Thomas Petazzoni wrote:
> This commit adds the list of cpuidle states supported by the Armada
> 38x SoC in the cpuidle-mvebu-v7 driver, as well as the necessary logic
> around it to support this SoC.
>
> Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>

Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org>

> ---
>   drivers/cpuidle/cpuidle-mvebu-v7.c | 29 ++++++++++++++++++++++++++++-
>   1 file changed, 28 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/cpuidle/cpuidle-mvebu-v7.c b/drivers/cpuidle/cpuidle-mvebu-v7.c
> index d23597f..45371bb 100644
> --- a/drivers/cpuidle/cpuidle-mvebu-v7.c
> +++ b/drivers/cpuidle/cpuidle-mvebu-v7.c
> @@ -1,5 +1,5 @@
>   /*
> - * Marvell Armada 370 and Armada XP SoC cpuidle driver
> + * Marvell Armada 370, 38x and XP SoC cpuidle driver
>    *
>    * Copyright (C) 2014 Marvell
>    *
> @@ -86,6 +86,21 @@ static struct cpuidle_driver armada370_idle_driver = {
>   	.state_count = 2,
>   };
>
> +static struct cpuidle_driver armada38x_idle_driver = {
> +	.name			= "armada_38x_idle",
> +	.states[0]		= ARM_CPUIDLE_WFI_STATE,
> +	.states[1]		= {
> +		.enter			= mvebu_v7_enter_idle,
> +		.exit_latency		= 10,
> +		.power_usage		= 5,
> +		.target_residency	= 100,
> +		.flags			= CPUIDLE_FLAG_TIME_VALID,
> +		.name			= "Idle",
> +		.desc			= "CPU and SCU power down",
> +	},
> +	.state_count = 2,
> +};
> +
>   static int mvebu_v7_cpuidle_probe(struct platform_device *pdev)
>   {
>   	mvebu_v7_cpu_suspend = pdev->dev.platform_data;
> @@ -94,6 +109,8 @@ static int mvebu_v7_cpuidle_probe(struct platform_device *pdev)
>   		return cpuidle_register(&armadaxp_idle_driver, NULL);
>   	else if (!strcmp(pdev->dev.driver->name, "cpuidle-armada-370"))
>   		return cpuidle_register(&armada370_idle_driver, NULL);
> +	else if (!strcmp(pdev->dev.driver->name, "cpuidle-armada-38x"))
> +		return cpuidle_register(&armada38x_idle_driver, NULL);
>   	else
>   		return -EINVAL;
>   }
> @@ -118,6 +135,16 @@ static struct platform_driver armada370_cpuidle_plat_driver = {
>
>   module_platform_driver(armada370_cpuidle_plat_driver);
>
> +static struct platform_driver armada38x_cpuidle_plat_driver = {
> +	.driver = {
> +		.name = "cpuidle-armada-38x",
> +		.owner = THIS_MODULE,
> +	},
> +	.probe = mvebu_v7_cpuidle_probe,
> +};
> +
> +module_platform_driver(armada38x_cpuidle_plat_driver);
> +
>   MODULE_AUTHOR("Gregory CLEMENT <gregory.clement@free-electrons.com>");
>   MODULE_DESCRIPTION("Marvell EBU v7 cpuidle driver");
>   MODULE_LICENSE("GPL");
>


-- 
  <http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog

^ permalink raw reply


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