SUPERH platform development
 help / color / mirror / Atom feed
* Re: [PATCH v5 5/5] imx6q: Remove unconditional dependency on l2x0 L2
From: Shawn Guo @ 2011-12-16  9:56 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1323964434-6764-6-git-send-email-dave.martin@linaro.org>

On Thu, Dec 15, 2011 at 03:53:54PM +0000, Dave Martin wrote:
> The i.MX6 Quad SoC will work without the l2x0 L2 cache controller
> support built into the kernel, so this patch removes the dependency
> on CACHE_L2X0.
> 
> This makes the l2x0 support optional, so that it can be turned off
> when desired for debugging purposes etc.
> 
> Since SOC_IMX6Q already depends on ARCH_IMX_V6_V7 and
> ARCH_IMX_V6_V7 selects MIGHT_HAVE_CACHE_L2X0, there is no need to
> select that option explicitly from SOC_IMX6Q.
> 
> Thanks to Shawn Guo for this suggestion.  [1]
> 
> [1] http://lists.infradead.org/pipermail/linux-arm-kernel/2011-November/074602.html
> 
> Signed-off-by: Dave Martin <dave.martin@linaro.org>

Acked-and-Tested-by: Shawn Guo <shawn.guo@linaro.org>

Regards,
Shawn

> ---
> Changes:
> 
> v5: Don't select MIGHT_HAVE_CACHE_L2X0 directly from SOC_IMX6Q, but
>     instead select implicitly via ARCH_IMX_V6_V7 (which we expect
>     to be selected by other relevant SoCs).  Thanks to Shawn for
>     this suggestion.
> 
> 
>  arch/arm/mach-imx/Kconfig |    1 -
>  1 files changed, 0 insertions(+), 1 deletions(-)
> 
> diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
> index 29a3d61..1530678 100644
> --- a/arch/arm/mach-imx/Kconfig
> +++ b/arch/arm/mach-imx/Kconfig
> @@ -609,7 +609,6 @@ comment "i.MX6 family:"
>  config SOC_IMX6Q
>  	bool "i.MX6 Quad support"
>  	select ARM_GIC
> -	select CACHE_L2X0
>  	select CPU_V7
>  	select HAVE_ARM_SCU
>  	select HAVE_IMX_GPC
> -- 
> 1.7.4.1
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 


^ permalink raw reply

* Re: [PATCH 12/57] arm: mach-shmobile: Add LCDC tx_dev field to platform data
From: Laurent Pinchart @ 2011-12-16 10:04 UTC (permalink / raw)
  To: linux-fbdev
In-Reply-To: <1323784972-24205-13-git-send-email-laurent.pinchart@ideasonboard.com>

Hi Guennadi,

On Thursday 15 December 2011 15:01:27 Guennadi Liakhovetski wrote:
> On Tue, 13 Dec 2011, Laurent Pinchart wrote:
> > Make sure the transmitter devices get registered before the associated
> > LCDC devices.
> > 
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

[snip]

> > diff --git a/arch/arm/mach-shmobile/board-ap4evb.c
> > b/arch/arm/mach-shmobile/board-ap4evb.c index dca4860..e0a6b3d 100644
> > --- a/arch/arm/mach-shmobile/board-ap4evb.c
> > +++ b/arch/arm/mach-shmobile/board-ap4evb.c

[snip]

> > @@ -627,6 +553,86 @@ static struct platform_device *qhd_devices[]
> > __initdata = {
> > 
> >  };
> >  #endif /* CONFIG_AP4EVB_QHD */
> > 
> > +/* LCDC0 */
> > +static const struct fb_videomode ap4evb_lcdc_modes[] = {
> 
> Hm, I must be missing something. I thought you were moving all the structs
> around to make them available for reference _without_ forward
> declarations. But you _do_ end up using a forward declaration anyway. Here
> and for HDMI below too. So, what's the point? Why not just forward declare
> that one struct, that's needed and leave the rest where it currently is
> in the file?

As we have circular dependencies forward declaration can't be avoided. I found 
it cleaner to have devices data in registration order in the board file, but I 
can remove this if you prefer.

> > +	{
> > +#ifdef CONFIG_AP4EVB_QHD
> > +		.name		= "R63302(QHD)",
> > +		.xres		= 544,
> > +		.yres		= 961,
> > +		.left_margin	= 72,
> > +		.right_margin	= 600,
> > +		.hsync_len	= 16,
> > +		.upper_margin	= 8,
> > +		.lower_margin	= 8,
> > +		.vsync_len	= 2,
> > +		.sync		= FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT,
> > +#else
> > +		.name		= "WVGA Panel",
> > +		.xres		= 800,
> > +		.yres		= 480,
> > +		.left_margin	= 220,
> > +		.right_margin	= 110,
> > +		.hsync_len	= 70,
> > +		.upper_margin	= 20,
> > +		.lower_margin	= 5,
> > +		.vsync_len	= 5,
> > +		.sync		= 0,
> > +#endif
> > +	},
> > +};

[snip]

> > diff --git a/arch/arm/mach-shmobile/board-mackerel.c
> > b/arch/arm/mach-shmobile/board-mackerel.c index 4ed0138..ccdd9fc 100644
> > --- a/arch/arm/mach-shmobile/board-mackerel.c
> > +++ b/arch/arm/mach-shmobile/board-mackerel.c

[snip]

> > @@ -1313,8 +1317,8 @@ static struct platform_device *mackerel_devices[]
> > __initdata = {
> >  	&sh_mmcif_device,
> >  	&ceu_device,
> >  	&mackerel_camera,
> > -	&hdmi_lcdc_device,
> >  	&hdmi_device,
> > +	&hdmi_lcdc_device,
> >  	&meram_device,
> >  };
> 
> Sorry, could you elaborate, why this is needed? If this is really
> important, then I'd prefer to test this before committing. If OTOH this is
> unimportant, and my assumption, that normally it's the platform driver
> registration order, that's important, not device registration order, is
> correct, then you don't have to swap the order?

If both the transmitter and LCDC drivers are built-in, the device probe order 
is the device registration order. As we need the transmitter to be probed 
first, it needs to be registered first.

-- 
Regards,

Laurent Pinchart

^ permalink raw reply

* Re: [PATCH 27/57] fbdev: sh_mobile_lcdc: Pass a video mode to the notify callback
From: Laurent Pinchart @ 2011-12-16 10:10 UTC (permalink / raw)
  To: linux-fbdev
In-Reply-To: <1323784972-24205-28-git-send-email-laurent.pinchart@ideasonboard.com>

Hi Guennadi,

On Thursday 15 December 2011 20:01:54 Guennadi Liakhovetski wrote:
> On Tue, 13 Dec 2011, Laurent Pinchart wrote:
> > Pass pointers to struct fb_videomode and struct fb_monspecs instead of
> > struct fb_var_screeninfo to the notify callback.
> > 
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> > 
> >  drivers/video/sh_mobile_hdmi.c   |   59
> >  +++++++++++++++++-------------------- drivers/video/sh_mobile_lcdcfb.c
> >  |   40 ++++++++++++++----------- drivers/video/sh_mobile_lcdcfb.h |   
> >  3 +-
> >  3 files changed, 51 insertions(+), 51 deletions(-)
> 
> [snip]
> 
> > diff --git a/drivers/video/sh_mobile_lcdcfb.c
> > b/drivers/video/sh_mobile_lcdcfb.c index 21e5f10..4ec216e 100644
> > --- a/drivers/video/sh_mobile_lcdcfb.c
> > +++ b/drivers/video/sh_mobile_lcdcfb.c
> 
> [ditto]
> 
> > @@ -433,12 +432,17 @@ static int sh_mobile_lcdc_display_notify(struct
> > sh_mobile_lcdc_chan *ch,
> > 
> >  		}
> >  		break;
> > 
> > -	case SH_MOBILE_LCDC_EVENT_DISPLAY_MODE:
> > +	case SH_MOBILE_LCDC_EVENT_DISPLAY_MODE: {
> > +		struct fb_var_screeninfo var;
> > +
> > 
> >  		/* Validate a proposed new mode */
> > 
> > -		var->bits_per_pixel = info->var.bits_per_pixel;
> > -		ret = info->fbops->fb_check_var(var, info);
> > +		fb_videomode_to_var(&var, mode);
> > +		var.bits_per_pixel = info->var.bits_per_pixel;
> > +		var.grayscale = info->var.grayscale;
> > +		ret = info->fbops->fb_check_var(&var, info);
> > 
> >  		break;
> >  	
> >  	}
> > 
> > +	}
> 
> nitpick - please, realign:-)

It's common in driver code not to increase the identation level twice in a 
case statement if braces are needed. However, those "braced" statements are 
usually not the last ones in the switch. In this particular case this creates 
an alignment issue at the end, as your correctly pointed out. However, I'd 
like to avoid increasing the indentation of the whole block. Increasing the 
indentation of the closing brace only also causes an alignment issue. I can 
add a default case that returns an error to fix this, but that's adding code 
to fix a cosmetic problem :-) What's your preference.

-- 
Regards,

Laurent Pinchart

^ permalink raw reply

* Re: [PATCH 34/57] fbdev: sh_mobile_lcdc: Store the format in struct sh_mobile_lcdc_chan
From: Laurent Pinchart @ 2011-12-16 10:17 UTC (permalink / raw)
  To: linux-fbdev
In-Reply-To: <1323784972-24205-35-git-send-email-laurent.pinchart@ideasonboard.com>

Hi Guennadi,

On Thursday 15 December 2011 23:29:29 Guennadi Liakhovetski wrote:
> On Tue, 13 Dec 2011, Laurent Pinchart wrote:
> > Store the active format in the channel structure, and use it instead of
> > parsing info->var all over the place when the format is needed.
> 
> Right, this is what I was wondering about, while looking at the previous
> patch:-)

So I'll consider your comment to patch 33/57 to be addressed :-)

> But:
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> > 
> >  drivers/video/sh_mobile_lcdcfb.c |   21 ++++++++++-----------
> >  drivers/video/sh_mobile_lcdcfb.h |    4 +++-
> >  2 files changed, 13 insertions(+), 12 deletions(-)
> > 
> > diff --git a/drivers/video/sh_mobile_lcdcfb.c
> > b/drivers/video/sh_mobile_lcdcfb.c index c6b6b9d..9829e01 100644
> > --- a/drivers/video/sh_mobile_lcdcfb.c
> > +++ b/drivers/video/sh_mobile_lcdcfb.c
> 
> [snip]
> 
> > @@ -1350,6 +1345,8 @@ static int sh_mobile_set_par(struct fb_info *info)
> > 
> >  		info->fix.line_length = info->var.xres
> >  		
> >  				      * info->var.bits_per_pixel / 8;
> > 
> > +	ch->format > > sh_mobile_format_info(sh_mobile_format_fourcc(&info->var));
> 
> Cannot this be NULL? As far as I could trace it back, I'm not sure with
> hotplug bits_per_pixel would be initialised correctly along the lines of
> sh_mobile_fb_reconfig().

You're right, sh_mobile_fb_reconfig() doesn't set the bits_per_pixel (and 
other format-related) field. I'll fix this by initializing those fields from 
the current var in sh_mobile_fb_reconfig() in patch 30/57, as that's the one 
that introduces the problem.

-- 
Regards,

Laurent Pinchart

^ permalink raw reply

* Re: [PATCH 25/57] sh_mobile_lcdc: Add display notify callback to sh_mobile_lcdc_chan
From: Laurent Pinchart @ 2011-12-16 10:22 UTC (permalink / raw)
  To: linux-fbdev
In-Reply-To: <1323784972-24205-26-git-send-email-laurent.pinchart@ideasonboard.com>

Hi Guennadi,

On Friday 16 December 2011 10:40:48 Guennadi Liakhovetski wrote:
> On Tue, 13 Dec 2011, Laurent Pinchart wrote:
> > The callback implements 3 notification events:
> > 
> > - SH_MOBILE_LCDC_EVENT_DISPLAY_CONNECT notifies the LCDC that the
> >   display has been connected
> > 
> > - SH_MOBILE_LCDC_EVENT_DISPLAY_DISCONNECT notifies the LCDC that the
> >   display has been disconnected
> > 
> > - SH_MOBILE_LCDC_EVENT_DISPLAY_MODE notifies that LCDC that a display
> >   mode has been detected
> > 
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> >
> > diff --git a/drivers/video/sh_mobile_lcdcfb.c
> > b/drivers/video/sh_mobile_lcdcfb.c index 4b03aa5..21e5f10 100644
> > --- a/drivers/video/sh_mobile_lcdcfb.c
> > +++ b/drivers/video/sh_mobile_lcdcfb.c
> > @@ -363,6 +363,86 @@ static void sh_mobile_lcdc_display_off(struct

[snip]

> > +static int sh_mobile_lcdc_display_notify(struct sh_mobile_lcdc_chan *ch,
> > +					 enum sh_mobile_lcdc_entity_event event,
> > +					 struct fb_var_screeninfo *var)
> > +{
> > +	struct fb_info *info = ch->info;
> > +	int ret = 0;
> > +
> > +	switch (event) {
> > +	case SH_MOBILE_LCDC_EVENT_DISPLAY_CONNECT:
> > +		/* HDMI plug in */
> > +		if (lock_fb_info(info)) {
> > +			console_lock();
> > +
> > +			if (!sh_mobile_lcdc_must_reconfigure(ch, var) &&
> > +			    info->state = FBINFO_STATE_RUNNING) {
> > +				/* First activation with the default monitor.
> > +				 * Just turn on, if we run a resume here, the
> > +				 * logo disappears.
> > +				 */
> > +				info->var.width = var->width;
> > +				info->var.height = var->height;
> > +				sh_mobile_lcdc_display_on(ch);
> > +			} else {
> > +				/* New monitor or have to wake up */
> > +				fb_set_suspend(info, 0);
> > +			}
> > +
> > +			console_unlock();
> > +			unlock_fb_info(info);
> > +		}
> > +		break;
> > +
> > +	case SH_MOBILE_LCDC_EVENT_DISPLAY_DISCONNECT:
> > +		/* HDMI disconnect */
> > +		if (lock_fb_info(info)) {
> > +			console_lock();
> > +			fb_set_suspend(info, 1);
> > +			console_unlock();
> > +			unlock_fb_info(info);
> > +		}
> > +		break;
> > +
> > +	case SH_MOBILE_LCDC_EVENT_DISPLAY_MODE:
> > +		/* Validate a proposed new mode */
> > +		var->bits_per_pixel = info->var.bits_per_pixel;
> > +		ret = info->fbops->fb_check_var(var, info);
> 
> You can call sh_mobile_lcdc_check_var() directly here too, right?

This was a way to avoid a forward declaration. You would prefer a forward 
declaration, right ? :-) I think you would be right.

> > +		break;
> > +	}
> > +
> > +	return ret;
> > +}
> > +

-- 
Regards,

Laurent Pinchart

^ permalink raw reply

* Re: [PATCH 27/57] fbdev: sh_mobile_lcdc: Pass a video mode to the
From: Guennadi Liakhovetski @ 2011-12-16 10:33 UTC (permalink / raw)
  To: linux-fbdev
In-Reply-To: <1323784972-24205-28-git-send-email-laurent.pinchart@ideasonboard.com>

On Fri, 16 Dec 2011, Laurent Pinchart wrote:

> Hi Guennadi,
> 
> On Thursday 15 December 2011 20:01:54 Guennadi Liakhovetski wrote:
> > On Tue, 13 Dec 2011, Laurent Pinchart wrote:
> > > Pass pointers to struct fb_videomode and struct fb_monspecs instead of
> > > struct fb_var_screeninfo to the notify callback.
> > > 
> > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > > ---
> > > 
> > >  drivers/video/sh_mobile_hdmi.c   |   59
> > >  +++++++++++++++++-------------------- drivers/video/sh_mobile_lcdcfb.c
> > >  |   40 ++++++++++++++----------- drivers/video/sh_mobile_lcdcfb.h |   
> > >  3 +-
> > >  3 files changed, 51 insertions(+), 51 deletions(-)
> > 
> > [snip]
> > 
> > > diff --git a/drivers/video/sh_mobile_lcdcfb.c
> > > b/drivers/video/sh_mobile_lcdcfb.c index 21e5f10..4ec216e 100644
> > > --- a/drivers/video/sh_mobile_lcdcfb.c
> > > +++ b/drivers/video/sh_mobile_lcdcfb.c
> > 
> > [ditto]
> > 
> > > @@ -433,12 +432,17 @@ static int sh_mobile_lcdc_display_notify(struct
> > > sh_mobile_lcdc_chan *ch,
> > > 
> > >  		}
> > >  		break;
> > > 
> > > -	case SH_MOBILE_LCDC_EVENT_DISPLAY_MODE:
> > > +	case SH_MOBILE_LCDC_EVENT_DISPLAY_MODE: {
> > > +		struct fb_var_screeninfo var;
> > > +
> > > 
> > >  		/* Validate a proposed new mode */
> > > 
> > > -		var->bits_per_pixel = info->var.bits_per_pixel;
> > > -		ret = info->fbops->fb_check_var(var, info);
> > > +		fb_videomode_to_var(&var, mode);
> > > +		var.bits_per_pixel = info->var.bits_per_pixel;
> > > +		var.grayscale = info->var.grayscale;
> > > +		ret = info->fbops->fb_check_var(&var, info);
> > > 
> > >  		break;
> > >  	
> > >  	}
> > > 
> > > +	}
> > 
> > nitpick - please, realign:-)
> 
> It's common in driver code not to increase the identation level twice in a 
> case statement if braces are needed. However, those "braced" statements are 
> usually not the last ones in the switch. In this particular case this creates 
> an alignment issue at the end, as your correctly pointed out. However, I'd 
> like to avoid increasing the indentation of the whole block. Increasing the 
> indentation of the closing brace only also causes an alignment issue. I can 
> add a default case that returns an error to fix this, but that's adding code 
> to fix a cosmetic problem :-) What's your preference.

Personally, I don't like just using braces without a related statement 
like "if," "do," etc. In such "case" cases I usually avoid adding own 
braces and just put any declarations, that are needed there in the 
enclosing block, e.g., the function. If you really don't want either, I 
would probably prefer a style like

	switch (x) {
	case X:
		{
			int y;
			my_statement(y);
			break;
		}
	}

You could also do

	switch (x) {
	case X:
		do {
			int y;
			my_statement(y);
			break;
		} while (0);
	}

So, choose your poison:-)

Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/

^ permalink raw reply

* [PATCH 3/6] sh/PCI: use list_for_each_entry() for bus->devices
From: Bjorn Helgaas @ 2011-12-16 22:31 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: linux-pci, Paul Mundt, linux-sh
In-Reply-To: <20111216223043.5963.87534.stgit@bhelgaas.mtv.corp.google.com>

Replace open-coded list traversal with list_for_each_entry().

CC: Paul Mundt <lethal@linux-sh.org>
CC: linux-sh@vger.kernel.org
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
---
 arch/sh/drivers/pci/pci.c |    5 +----
 1 files changed, 1 insertions(+), 4 deletions(-)

diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c
index af9246d..e425b08 100644
--- a/arch/sh/drivers/pci/pci.c
+++ b/arch/sh/drivers/pci/pci.c
@@ -171,11 +171,8 @@ static void pcibios_fixup_device_resources(struct pci_dev *dev,
 void __devinit pcibios_fixup_bus(struct pci_bus *bus)
 {
 	struct pci_dev *dev;
-	struct list_head *ln;
-
-	for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) {
-		dev = pci_dev_b(ln);
 
+	list_for_each_entry(dev, &bus->devices, bus_list) {
 		if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI)
 			pcibios_fixup_device_resources(dev, bus);
 	}


^ permalink raw reply related

* Re: Dreamcast build broken
From: Adrian McMenamin @ 2011-12-17 10:24 UTC (permalink / raw)
  To: linux-sh
In-Reply-To: <4EC81660.3010109@gmail.com>

On 25 November 2011 16:24, Paul Cercueil <pcercuei@gmail.com> wrote:
> Le 24/11/2011 08:29, Paul Mundt a écrit :
>>

> However, starting from commit 37b7a97884ba64bf7d403351ac2a9476ab4f1bba and
> up to the latest vanilla Linux 3.1,
> the vmlinux binary won't start on my dreamcast or on the lxdream emulator.
>
No output at all?

^ permalink raw reply

* Re: [PATCH v5 1/5] ARM: l2x0/pl310: Refactor Kconfig to be more maintainable
From: Olof Johansson @ 2011-12-18  4:23 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1323964434-6764-2-git-send-email-dave.martin@linaro.org>

On Thu, Dec 15, 2011 at 7:53 AM, Dave Martin <dave.martin@linaro.org> wrote:
> Making CACHE_L2X0 depend on (huge list of MACH_ and ARCH_ configs)
> is bothersome to maintain and likely to lead to merge conflicts.
>
> This patch moves the knowledge of which platforms have a L2x0 or
> PL310 cache controller to the individual machines.  To enable this,
> a new MIGHT_HAVE_CACHE_L2X0 config option is introduced to allow
> machines to indicate that they may have such a cache controller
> independently of each other.
>
> Boards/SoCs which cannot reliably operate without the L2 cache
> controller support will need to select CACHE_L2X0 directly from
> their own Kconfigs instead.  This applies to some TrustZone-enabled
> boards where Linux runs in the Normal World, for example.
>
> Signed-off-by: Dave Martin <dave.martin@linaro.org>
> Acked-by: Anton Vorontsov <cbouatmailru@gmail.com>
>        (for cns3xxx)
> Acked-by: Tony Lindgren <tony@atomide.com>
>        (for omap)

Acked-by: Olof Johansson <olof@lixom.net> (for tegra)


-Olof

^ permalink raw reply

* [PATCH] ARM: mach-shmobile: sh7372 A4S support
From: Magnus Damm @ 2011-12-18 16:59 UTC (permalink / raw)
  To: linux-sh

From: Magnus Damm <damm@opensource.se>

Add support for the sh7372 A4S power domain / sleep mode.

The sh7372 contains a power domain named A4S which in turn
contains power domains for both I/O Devices and CPU cores.

At this point only System wide Suspend-to-RAM is supported,
but the the hardware can also support CPUIdle. With more
efforts in the future CPUIdle can work with bot A4S and A3SM.

Tested on the sh7372 Mackerel board.

Signed-off-by: Magnus Damm <damm@opensource.se>
---

 arch/arm/mach-shmobile/include/mach/common.h |    4 -
 arch/arm/mach-shmobile/include/mach/sh7372.h |    3 +
 arch/arm/mach-shmobile/intc-sh7372.c         |   49 ++++++++++++++++++++
 arch/arm/mach-shmobile/pm-sh7372.c           |   63 ++++++++++++++++++--------
 arch/arm/mach-shmobile/setup-sh7372.c        |    6 ++
 arch/arm/mach-shmobile/sleep-sh7372.S        |   21 ++++----
 6 files changed, 116 insertions(+), 30 deletions(-)

--- 0001/arch/arm/mach-shmobile/include/mach/common.h
+++ work/arch/arm/mach-shmobile/include/mach/common.h	2011-12-19 01:35:31.000000000 +0900
@@ -35,8 +35,8 @@ extern void sh7372_add_standard_devices(
 extern void sh7372_clock_init(void);
 extern void sh7372_pinmux_init(void);
 extern void sh7372_pm_init(void);
-extern void sh7372_resume_core_standby_a3sm(void);
-extern int sh7372_do_idle_a3sm(unsigned long unused);
+extern void sh7372_resume_core_standby_sysc(void);
+extern int sh7372_do_idle_sysc(unsigned long sleep_mode);
 extern struct clk sh7372_extal1_clk;
 extern struct clk sh7372_extal2_clk;
 
--- 0001/arch/arm/mach-shmobile/include/mach/sh7372.h
+++ work/arch/arm/mach-shmobile/include/mach/sh7372.h	2011-12-19 01:35:31.000000000 +0900
@@ -499,6 +499,7 @@ extern struct sh7372_pm_domain sh7372_d4
 extern struct sh7372_pm_domain sh7372_a4r;
 extern struct sh7372_pm_domain sh7372_a3rv;
 extern struct sh7372_pm_domain sh7372_a3ri;
+extern struct sh7372_pm_domain sh7372_a4s;
 extern struct sh7372_pm_domain sh7372_a3sp;
 extern struct sh7372_pm_domain sh7372_a3sg;
 
@@ -515,5 +516,7 @@ extern void sh7372_pm_add_subdomain(stru
 
 extern void sh7372_intcs_suspend(void);
 extern void sh7372_intcs_resume(void);
+extern void sh7372_intca_suspend(void);
+extern void sh7372_intca_resume(void);
 
 #endif /* __ASM_SH7372_H__ */
--- 0001/arch/arm/mach-shmobile/intc-sh7372.c
+++ work/arch/arm/mach-shmobile/intc-sh7372.c	2011-12-19 01:35:31.000000000 +0900
@@ -611,3 +611,52 @@ void sh7372_intcs_resume(void)
 	for (k = 0x80; k <= 0x9c; k += 4)
 		__raw_writeb(ffd5[k], intcs_ffd5 + k);
 }
+
+static unsigned short e694[0x200];
+static unsigned short e695[0x200];
+
+void sh7372_intca_suspend(void)
+{
+	int k;
+
+	for (k = 0x00; k <= 0x38; k += 4)
+		e694[k] = __raw_readw(0xe6940000 + k);
+
+	for (k = 0x80; k <= 0xb4; k += 4)
+		e694[k] = __raw_readb(0xe6940000 + k);
+
+	for (k = 0x180; k <= 0x1b4; k += 4)
+		e694[k] = __raw_readb(0xe6940000 + k);
+
+	for (k = 0x00; k <= 0x50; k += 4)
+		e695[k] = __raw_readw(0xe6950000 + k);
+
+	for (k = 0x80; k <= 0xa8; k += 4)
+		e695[k] = __raw_readb(0xe6950000 + k);
+
+	for (k = 0x180; k <= 0x1a8; k += 4)
+		e695[k] = __raw_readb(0xe6950000 + k);
+}
+
+void sh7372_intca_resume(void)
+{
+	int k;
+
+	for (k = 0x00; k <= 0x38; k += 4)
+		__raw_writew(e694[k], 0xe6940000 + k);
+
+	for (k = 0x80; k <= 0xb4; k += 4)
+		__raw_writeb(e694[k], 0xe6940000 + k);
+
+	for (k = 0x180; k <= 0x1b4; k += 4)
+		__raw_writeb(e694[k], 0xe6940000 + k);
+
+	for (k = 0x00; k <= 0x50; k += 4)
+		__raw_writew(e695[k], 0xe6950000 + k);
+
+	for (k = 0x80; k <= 0xa8; k += 4)
+		__raw_writeb(e695[k], 0xe6950000 + k);
+
+	for (k = 0x180; k <= 0x1a8; k += 4)
+		__raw_writeb(e695[k], 0xe6950000 + k);
+}
--- 0001/arch/arm/mach-shmobile/pm-sh7372.c
+++ work/arch/arm/mach-shmobile/pm-sh7372.c	2011-12-19 01:48:09.000000000 +0900
@@ -226,6 +226,13 @@ struct sh7372_pm_domain sh7372_a3ri = {
 	.bit_shift = 8,
 };
 
+struct sh7372_pm_domain sh7372_a4s = {
+	.bit_shift = 10,
+	.gov = &sh7372_always_on_gov,
+	.no_debug = true,
+	.stay_on = true,
+};
+
 struct sh7372_pm_domain sh7372_a3sp = {
 	.bit_shift = 11,
 	.gov = &sh7372_always_on_gov,
@@ -257,11 +264,16 @@ static int sh7372_do_idle_core_standby(u
 	return 0;
 }
 
-static void sh7372_enter_core_standby(void)
+static void sh7372_set_reset_vector(unsigned long address)
 {
 	/* set reset vector, translate 4k */
-	__raw_writel(__pa(sh7372_resume_core_standby_a3sm), SBAR);
+	__raw_writel(address, SBAR);
 	__raw_writel(0, APARMBAREA);
+}
+
+static void sh7372_enter_core_standby(void)
+{
+	sh7372_set_reset_vector(__pa(sh7372_resume_core_standby_sysc));
 
 	/* enter sleep mode with SYSTBCR to 0x10 */
 	__raw_writel(0x10, SYSTBCR);
@@ -274,27 +286,22 @@ static void sh7372_enter_core_standby(vo
 #endif
 
 #ifdef CONFIG_SUSPEND
-static void sh7372_enter_a3sm_common(int pllc0_on)
+static void sh7372_enter_sysc(int pllc0_on, unsigned long sleep_mode)
 {
-	/* set reset vector, translate 4k */
-	__raw_writel(__pa(sh7372_resume_core_standby_a3sm), SBAR);
-	__raw_writel(0, APARMBAREA);
-
 	if (pllc0_on)
 		__raw_writel(0, PLLC01STPCR);
 	else
 		__raw_writel(1 << 28, PLLC01STPCR);
 
-	__raw_writel(0, PDNSEL); /* power-down A3SM only, not A4S */
 	__raw_readl(WUPSFAC); /* read wakeup int. factor before sleep */
-	cpu_suspend(0, sh7372_do_idle_a3sm);
+	cpu_suspend(sleep_mode, sh7372_do_idle_sysc);
 	__raw_readl(WUPSFAC); /* read wakeup int. factor after wakeup */
 
 	 /* disable reset vector translation */
 	__raw_writel(0, SBAR);
 }
 
-static int sh7372_a3sm_valid(unsigned long *mskp, unsigned long *msk2p)
+static int sh7372_sysc_valid(unsigned long *mskp, unsigned long *msk2p)
 {
 	unsigned long mstpsr0, mstpsr1, mstpsr2, mstpsr3, mstpsr4;
 	unsigned long msk, msk2;
@@ -382,7 +389,7 @@ static void sh7372_icr_to_irqcr(unsigned
 	*irqcr2p = irqcr2;
 }
 
-static void sh7372_setup_a3sm(unsigned long msk, unsigned long msk2)
+static void sh7372_setup_sysc(unsigned long msk, unsigned long msk2)
 {
 	u16 irqcrx_low, irqcrx_high, irqcry_low, irqcry_high;
 	unsigned long tmp;
@@ -415,6 +422,22 @@ static void sh7372_setup_a3sm(unsigned l
 	__raw_writel((irqcrx_high << 16) | irqcrx_low, IRQCR3);
 	__raw_writel((irqcry_high << 16) | irqcry_low, IRQCR4);
 }
+
+static void sh7372_enter_a3sm_common(int pllc0_on)
+{
+	sh7372_set_reset_vector(__pa(sh7372_resume_core_standby_sysc));
+	sh7372_enter_sysc(pllc0_on, 1 << 12);
+}
+
+static void sh7372_enter_a4s_common(int pllc0_on)
+{
+	sh7372_intca_suspend();
+	memcpy((void *)SMFRAM, sh7372_resume_core_standby_sysc, 0x100);
+	sh7372_set_reset_vector(SMFRAM);
+	sh7372_enter_sysc(pllc0_on, 1 << 10);
+	sh7372_intca_resume();
+}
+
 #endif
 
 #ifdef CONFIG_CPU_IDLE
@@ -448,14 +471,20 @@ static int sh7372_enter_suspend(suspend_
 	unsigned long msk, msk2;
 
 	/* check active clocks to determine potential wakeup sources */
-	if (sh7372_a3sm_valid(&msk, &msk2)) {
-
+	if (sh7372_sysc_valid(&msk, &msk2)) {
 		/* convert INTC mask and sense to SYSC mask and sense */
-		sh7372_setup_a3sm(msk, msk2);
+		sh7372_setup_sysc(msk, msk2);
 
-		/* enter A3SM sleep with PLLC0 off */
-		pr_debug("entering A3SM\n");
-		sh7372_enter_a3sm_common(0);
+		if (!sh7372_a3sp.stay_on &&
+		    sh7372_a4s.genpd.status = GPD_STATE_POWER_OFF) {
+			/* enter A4S sleep with PLLC0 off */
+			pr_debug("entering A4S\n");
+			sh7372_enter_a4s_common(0);
+		} else {
+			/* enter A3SM sleep with PLLC0 off */
+			pr_debug("entering A3SM\n");
+			sh7372_enter_a3sm_common(0);
+		}
 	} else {
 		/* default to Core Standby that supports all wakeup sources */
 		pr_debug("entering Core Standby\n");
--- 0001/arch/arm/mach-shmobile/setup-sh7372.c
+++ work/arch/arm/mach-shmobile/setup-sh7372.c	2011-12-19 01:35:31.000000000 +0900
@@ -994,12 +994,16 @@ void __init sh7372_add_standard_devices(
 	sh7372_init_pm_domain(&sh7372_a4r);
 	sh7372_init_pm_domain(&sh7372_a3rv);
 	sh7372_init_pm_domain(&sh7372_a3ri);
-	sh7372_init_pm_domain(&sh7372_a3sg);
+	sh7372_init_pm_domain(&sh7372_a4s);
 	sh7372_init_pm_domain(&sh7372_a3sp);
+	sh7372_init_pm_domain(&sh7372_a3sg);
 
 	sh7372_pm_add_subdomain(&sh7372_a4lc, &sh7372_a3rv);
 	sh7372_pm_add_subdomain(&sh7372_a4r, &sh7372_a4lc);
 
+	sh7372_pm_add_subdomain(&sh7372_a4s, &sh7372_a3sg);
+	sh7372_pm_add_subdomain(&sh7372_a4s, &sh7372_a3sp);
+
 	platform_add_devices(sh7372_early_devices,
 			    ARRAY_SIZE(sh7372_early_devices));
 
--- 0001/arch/arm/mach-shmobile/sleep-sh7372.S
+++ work/arch/arm/mach-shmobile/sleep-sh7372.S	2011-12-19 01:47:37.000000000 +0900
@@ -37,13 +37,18 @@
 #if defined(CONFIG_SUSPEND) || defined(CONFIG_CPU_IDLE)
 	.align	12
 	.text
-	.global sh7372_resume_core_standby_a3sm
-sh7372_resume_core_standby_a3sm:
+	.global sh7372_resume_core_standby_sysc
+sh7372_resume_core_standby_sysc:
 	ldr     pc, 1f
 1:	.long   cpu_resume - PAGE_OFFSET + PLAT_PHYS_OFFSET
 
-	.global	sh7372_do_idle_a3sm
-sh7372_do_idle_a3sm:
+#define SPDCR 0xe6180008
+
+	/* A3SM & A4S power down */
+	.global	sh7372_do_idle_sysc
+sh7372_do_idle_sysc:
+	mov	r8, r0 /* sleep mode passed in r0 */
+
 	/*
 	 * Clear the SCTLR.C bit to prevent further data cache
 	 * allocation. Clearing SCTLR.C would make all the data accesses
@@ -80,13 +85,9 @@ sh7372_do_idle_a3sm:
 	dsb
 	dmb
 
-#define SPDCR 0xe6180008
-#define A3SM (1 << 12)
-
-	/* A3SM power down */
+	/* SYSC power down */
 	ldr     r0, =SPDCR
-	ldr     r1, £SM
-	str     r1, [r0]
+	str     r8, [r0]
 1:
 	b      1b
 

^ permalink raw reply

* [PATCH] ARM: mach-shmobile: sh7372 A4S Mackerel debug hack
From: Magnus Damm @ 2011-12-18 17:03 UTC (permalink / raw)
  To: linux-sh

From: Magnus Damm <damm@opensource.se>

Add some quick debugging code on top of the A4S power domain
patch to allow serial printouts before and soon after the power
has been cut/restored. Duplicates the context restore code
located in the SCIF driver in a board specific fashion. Will
only work on Mackerel. Not for upstream inclusion.

Not-signed-off-by: Magnus Damm <damm@opensource.se>
---

 arch/arm/mach-shmobile/pm-sh7372.c |   17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

--- 0004/arch/arm/mach-shmobile/pm-sh7372.c
+++ work/arch/arm/mach-shmobile/pm-sh7372.c	2011-12-19 01:50:11.000000000 +0900
@@ -7,7 +7,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  */
-
+#define DEBUG
 #include <linux/pm.h>
 #include <linux/suspend.h>
 #include <linux/cpuidle.h>
@@ -323,7 +323,9 @@ static int sh7372_sysc_valid(unsigned lo
 	mstpsr2 = __raw_readl(MSTPSR2);
 	if ((mstpsr2 & 0x000741ff) != 0x000741ff) {
 		pr_debug("sh7372 mstpsr2 0x%08lx\n", mstpsr2);
+#if 0 /* SCIF console clock will be on, ignore to debug low level A4S code */
 		return 0;
+#endif
 	}
 
 	mstpsr3 = __raw_readl(MSTPSR3);
@@ -475,11 +477,22 @@ static int sh7372_enter_suspend(suspend_
 		/* convert INTC mask and sense to SYSC mask and sense */
 		sh7372_setup_sysc(msk, msk2);
 
-		if (!sh7372_a3sp.stay_on &&
+		if (/*!sh7372_a3sp.stay_on && */
 		    sh7372_a4s.genpd.status = GPD_STATE_POWER_OFF) {
 			/* enter A4S sleep with PLLC0 off */
 			pr_debug("entering A4S\n");
 			sh7372_enter_a4s_common(0);
+
+			/* power up A3SP and setup SCIF console */
+			if (sh7372_a3sp.stay_on) {
+				sh7372_a3sp.stay_on = 0;
+				pd_power_up(&sh7372_a3sp.genpd);
+				sh7372_a3sp.stay_on = 1;
+				__raw_writew(0, 0xE6C40000); /* setup SCIF */
+				__raw_writeb(0x19, 0xE6C40004);
+				__raw_writew(0x0030, 0xE6C40008);
+				pr_debug("SCIF alive and kicking!\n");
+			}
 		} else {
 			/* enter A3SM sleep with PLLC0 off */
 			pr_debug("entering A3SM\n");

^ permalink raw reply

* Re: [PATCH 24/57] fbdev: sh_mobile_lcdc: Return display connection state in display_on
From: Laurent Pinchart @ 2011-12-19  0:21 UTC (permalink / raw)
  To: linux-fbdev
In-Reply-To: <1323784972-24205-25-git-send-email-laurent.pinchart@ideasonboard.com>

Hi Guennadi,

On Thursday 15 December 2011 18:11:03 Guennadi Liakhovetski wrote:
> On Tue, 13 Dec 2011, Laurent Pinchart wrote:
> > Return true if the display is connected and false otherwise. Set the fb
> > info state to FBINFO_STATE_SUSPENDED in the sh_mobile_lcdc driver when
> > the display is not connected.
> 
> Hmm... I'm not sure I like functions, that return either a negative error,
> or _several_ non-negative success values. How about returning -ENODEV?

That would be returning a negative error on success. Is that better ? :-)


-- 
Regards,

Laurent Pinchart

^ permalink raw reply

* Re: [PATCH 12/57] arm: mach-shmobile: Add LCDC tx_dev field to
From: Guennadi Liakhovetski @ 2011-12-19  0:27 UTC (permalink / raw)
  To: linux-fbdev
In-Reply-To: <1323784972-24205-13-git-send-email-laurent.pinchart@ideasonboard.com>

On Fri, 16 Dec 2011, Laurent Pinchart wrote:

> Hi Guennadi,
> 
> On Thursday 15 December 2011 15:01:27 Guennadi Liakhovetski wrote:
> > On Tue, 13 Dec 2011, Laurent Pinchart wrote:
> > > Make sure the transmitter devices get registered before the associated
> > > LCDC devices.
> > > 
> > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> 
> [snip]
> 
> > > diff --git a/arch/arm/mach-shmobile/board-ap4evb.c
> > > b/arch/arm/mach-shmobile/board-ap4evb.c index dca4860..e0a6b3d 100644
> > > --- a/arch/arm/mach-shmobile/board-ap4evb.c
> > > +++ b/arch/arm/mach-shmobile/board-ap4evb.c
> 
> [snip]
> 
> > > @@ -627,6 +553,86 @@ static struct platform_device *qhd_devices[]
> > > __initdata = {
> > > 
> > >  };
> > >  #endif /* CONFIG_AP4EVB_QHD */
> > > 
> > > +/* LCDC0 */
> > > +static const struct fb_videomode ap4evb_lcdc_modes[] = {
> > 
> > Hm, I must be missing something. I thought you were moving all the structs
> > around to make them available for reference _without_ forward
> > declarations. But you _do_ end up using a forward declaration anyway. Here
> > and for HDMI below too. So, what's the point? Why not just forward declare
> > that one struct, that's needed and leave the rest where it currently is
> > in the file?
> 
> As we have circular dependencies forward declaration can't be avoided. I found 
> it cleaner to have devices data in registration order in the board file, but I 
> can remove this if you prefer.

As a _general_ guidline I find smaller patches more pleasant than 
bigger;-) but if you really see an important advantage in moving these 
structs around - I can live with that too:-)

> > > +	{
> > > +#ifdef CONFIG_AP4EVB_QHD
> > > +		.name		= "R63302(QHD)",
> > > +		.xres		= 544,
> > > +		.yres		= 961,
> > > +		.left_margin	= 72,
> > > +		.right_margin	= 600,
> > > +		.hsync_len	= 16,
> > > +		.upper_margin	= 8,
> > > +		.lower_margin	= 8,
> > > +		.vsync_len	= 2,
> > > +		.sync		= FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT,
> > > +#else
> > > +		.name		= "WVGA Panel",
> > > +		.xres		= 800,
> > > +		.yres		= 480,
> > > +		.left_margin	= 220,
> > > +		.right_margin	= 110,
> > > +		.hsync_len	= 70,
> > > +		.upper_margin	= 20,
> > > +		.lower_margin	= 5,
> > > +		.vsync_len	= 5,
> > > +		.sync		= 0,
> > > +#endif
> > > +	},
> > > +};
> 
> [snip]
> 
> > > diff --git a/arch/arm/mach-shmobile/board-mackerel.c
> > > b/arch/arm/mach-shmobile/board-mackerel.c index 4ed0138..ccdd9fc 100644
> > > --- a/arch/arm/mach-shmobile/board-mackerel.c
> > > +++ b/arch/arm/mach-shmobile/board-mackerel.c
> 
> [snip]
> 
> > > @@ -1313,8 +1317,8 @@ static struct platform_device *mackerel_devices[]
> > > __initdata = {
> > >  	&sh_mmcif_device,
> > >  	&ceu_device,
> > >  	&mackerel_camera,
> > > -	&hdmi_lcdc_device,
> > >  	&hdmi_device,
> > > +	&hdmi_lcdc_device,
> > >  	&meram_device,
> > >  };
> > 
> > Sorry, could you elaborate, why this is needed? If this is really
> > important, then I'd prefer to test this before committing. If OTOH this is
> > unimportant, and my assumption, that normally it's the platform driver
> > registration order, that's important, not device registration order, is
> > correct, then you don't have to swap the order?
> 
> If both the transmitter and LCDC drivers are built-in, the device probe order 
> is the device registration order. As we need the transmitter to be probed 
> first, it needs to be registered first.

Even there I'm not quite sure about - I do remember having to fiddle with 
the Makefiles to change the probe order, which followed the linkage order. 
Could be, that this has changed since I last checked, but I'd really 
double-check this.

Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/

^ permalink raw reply

* Re: [PATCH 27/57] fbdev: sh_mobile_lcdc: Pass a video mode to the notify callback
From: Laurent Pinchart @ 2011-12-19  1:29 UTC (permalink / raw)
  To: linux-fbdev
In-Reply-To: <1323784972-24205-28-git-send-email-laurent.pinchart@ideasonboard.com>

Hi Guennadi,

On Friday 16 December 2011 11:33:55 Guennadi Liakhovetski wrote:
> On Fri, 16 Dec 2011, Laurent Pinchart wrote:
> > On Thursday 15 December 2011 20:01:54 Guennadi Liakhovetski wrote:
> > > On Tue, 13 Dec 2011, Laurent Pinchart wrote:
> > > > Pass pointers to struct fb_videomode and struct fb_monspecs instead
> > > > of struct fb_var_screeninfo to the notify callback.
> > > > 
> > > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > > > ---
> > > > 
> > > >  drivers/video/sh_mobile_hdmi.c   |   59
> > > >  +++++++++++++++++--------------------
> > > >  drivers/video/sh_mobile_lcdcfb.c
> > > >  
> > > >  |   40 ++++++++++++++----------- drivers/video/sh_mobile_lcdcfb.h |
> > > >  
> > > >  3 +-
> > > >  3 files changed, 51 insertions(+), 51 deletions(-)
> > > 
> > > [snip]
> > > 
> > > > diff --git a/drivers/video/sh_mobile_lcdcfb.c
> > > > b/drivers/video/sh_mobile_lcdcfb.c index 21e5f10..4ec216e 100644
> > > > --- a/drivers/video/sh_mobile_lcdcfb.c
> > > > +++ b/drivers/video/sh_mobile_lcdcfb.c
> > > 
> > > [ditto]
> > > 
> > > > @@ -433,12 +432,17 @@ static int sh_mobile_lcdc_display_notify(struct
> > > > sh_mobile_lcdc_chan *ch,
> > > > 
> > > >  		}
> > > >  		break;
> > > > 
> > > > -	case SH_MOBILE_LCDC_EVENT_DISPLAY_MODE:
> > > > +	case SH_MOBILE_LCDC_EVENT_DISPLAY_MODE: {
> > > > +		struct fb_var_screeninfo var;
> > > > +
> > > > 
> > > >  		/* Validate a proposed new mode */
> > > > 
> > > > -		var->bits_per_pixel = info->var.bits_per_pixel;
> > > > -		ret = info->fbops->fb_check_var(var, info);
> > > > +		fb_videomode_to_var(&var, mode);
> > > > +		var.bits_per_pixel = info->var.bits_per_pixel;
> > > > +		var.grayscale = info->var.grayscale;
> > > > +		ret = info->fbops->fb_check_var(&var, info);
> > > > 
> > > >  		break;
> > > >  	
> > > >  	}
> > > > 
> > > > +	}
> > > 
> > > nitpick - please, realign:-)
> > 
> > It's common in driver code not to increase the identation level twice in
> > a case statement if braces are needed. However, those "braced"
> > statements are usually not the last ones in the switch. In this
> > particular case this creates an alignment issue at the end, as your
> > correctly pointed out. However, I'd like to avoid increasing the
> > indentation of the whole block. Increasing the indentation of the
> > closing brace only also causes an alignment issue. I can add a default
> > case that returns an error to fix this, but that's adding code to fix a
> > cosmetic problem :-) What's your preference.
> 
> Personally, I don't like just using braces without a related statement
> like "if," "do," etc. In such "case" cases I usually avoid adding own
> braces and just put any declarations, that are needed there in the
> enclosing block, e.g., the function.

Using braces with case statements is a common practice in the kernel, without 
adding an extra indentation level.

In this particular case I can move the variable declaration at the top of the 
function, as the generated code on ARM (at least with gcc ('cs2009q3-67-hard-
sb4') 4.4.1) doesn't differ.

> If you really don't want either, I would probably prefer a style like
> 
> 	switch (x) {
> 	case X:
> 		{
> 			int y;
> 			my_statement(y);
> 			break;
> 		}
> 	}
> 
> You could also do
> 
> 	switch (x) {
> 	case X:
> 		do {
> 			int y;
> 			my_statement(y);
> 			break;
> 		} while (0);
> 	}
> 
> So, choose your poison:-)


-- 
Regards,

Laurent Pinchart

^ permalink raw reply

* Re: [PATCH/RFC] mmc: add a device PM QoS constraint when a host is
From: Ulf Hansson @ 2011-12-19 12:17 UTC (permalink / raw)
  To: Guennadi Liakhovetski
  Cc: Rafael J. Wysocki, linux-mmc@vger.kernel.org,
	linux-pm@vger.kernel.org, Chris Ball, linux-sh@vger.kernel.org
In-Reply-To: <Pine.LNX.4.64.1112160954030.6572@axis700.grange>

Guennadi Liakhovetski wrote:
> On Wed, 14 Dec 2011, Rafael J. Wysocki wrote:
> 
>> On Wednesday, December 14, 2011, Ulf Hansson wrote:
> 
> [snip]
> 
>>> 2.
>>> When executing mmc/sd commands/requests the host must always be claimed 
>>> (and thus the host is always enabled).
> 
> Why? Why cannot we save some power between IO operations - if we can do 
> this quickly and safely without affecting functionality and throughput?
> 
>>> But more important some mmc/sd 
>>> commands must be executed as a sequence, without the host being disabled 
>>> in between the commands (since a disable might mean that the clock to 
>>> card gets disabled).
> 
> Ok, there might well be such command sequences, but my question is: who 
> knows about them? Is this mandated by the MMC(/SD/SDIO/...) standard or is 
> it host-specific? Also "might mean" is actually interesting here. I think 
> we eventually need a combination of timing-oriented PM constraints and 
> "stateful" ones. During such a command sequence you would require the card 
> clock to stay on.

MMC/SD/SDIO standard sets the requirement and must somehow "notify" the 
host about how to act in certain scenarios.

Just for information, I think one interesting host driver to look at is 
omap_hsmmc. For it's enable function is does pm_runtime_get_sync and for 
it's disable function it does pm_runtime_put_autosuspend, this to make 
sure the clock is enabled when it is needed.


> 
>>> To solve this, the mmc_claim_host is used, to make 
>>> sure the host is enabled during the complete command sequence.
>>>
>>> I happily continue this discussion, to see if someone more can break the 
>>> idea about having get_sync in mmc_host_enable. :-)
>> I'll leave this one to Guennadi, if you don't mind. :-)
> 
> As I said above, I think, we need both - to be able to require a certain 
> responsiveness / throughput and specific interface parameters like 
> supplying clock, power, etc.
> 
> Also notice, that setting a constraint doesn't affect in principle, when 
> the device is allowed to suspend. This is done as usual per 
> pm_runtime_get*() and _put*(). I think, a reasonable solution to use PM 
> QoS to impose timing constraints but at the same time to not disable the 
> hardware, when this is disallowed, is to tie pm_runtime_get() and _put() 
> calls to driver's .set_ios() method, like tmio_mmc and sh_mmcif drivers 
> currently do. Those drivers only call pm_runtime_put() when the interface 
> clock is gated. So, as long as the core is aware, that that IO sequence 
> has to run uninterrupted without stopping the clock between single 
> transfers, it just has to avoid gating the clock for that period and the 
> interface will not enter any power-saving mode.
> 
> So, I don't think we need to enforce pm_runtime_get_sync() in 
> mmc_claim_host().

You might be right; but still we need a way for the mmc framework to 
prevent the host driver from disabling clock etc to the card for some 
command sequences. As the omap driver solves it is to implement the 
enable/disable function and then call for get_sync and put in these 
functions, maybe that is the way how to solve this!?

Br
Ulf Hansson


^ permalink raw reply

* Dear Sir/Madam,
From:  I am Dr. Joe working in a pharmaceutical company based in London @ 2011-12-19 14:57 UTC (permalink / raw)


I am Dr. Joe working in a pharmaceutical company based in London,
United Kingdom.based on our company's urgent need to
establish a mutual business relationship with a company or an individual in
India; contact me through my private email
address mentioned below: {joe_moore@w.cn} for more detail


^ permalink raw reply

* [GIT PULL] sh fixes for 3.2-rc7
From: Paul Mundt @ 2011-12-20  8:24 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-sh, linux-kernel

Please pull from:

        git://github.com/pmundt/linux-sh.git sh-fixes-for-linus

Which contains:

Yoshihiro Shimoda (1):
      sh: fix build warning in board-sh7757lcr

 arch/sh/boards/board-sh7757lcr.c |   16 ++++++++++------
 1 files changed, 10 insertions(+), 6 deletions(-)

^ permalink raw reply

* [GIT PULL] rmobile fixes for 3.2-rc7
From: Paul Mundt @ 2011-12-20  8:24 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-sh, linux-kernel

Please pull from:

        git://github.com/pmundt/linux-sh.git rmobile-fixes-for-linus

Which contains:

Magnus Damm (5):
      ARM: mach-shmobile: Kota2 PINT fix
      ARM: mach-shmobile: Kota2 GIC Sparse IRQ fix
      ARM: mach-shmobile: Kota2 TPU LED platform data
      ARM: mach-shmobile: AG5EVM GIC Sparse IRQ fix
      ARM: mach-shmobile: SH73A0 external Ethernet fix

 arch/arm/mach-shmobile/board-ag5evm.c |    1 +
 arch/arm/mach-shmobile/board-kota2.c  |  139 ++++++++++++++++++++++++++++----
 arch/arm/mach-shmobile/clock-sh73a0.c |   18 ++++-
 3 files changed, 139 insertions(+), 19 deletions(-)

^ permalink raw reply

* [PATCH v2] sh: sh2a: Optimise cache functions.
From: Phil Edworthy @ 2011-12-20  8:40 UTC (permalink / raw)
  To: linux-sh

When invalidating a large address range, it's better to invalidate
the entire cache rather than individual addresses.

Also, when the operand cache is set to write-though mode, there is
no need to flush data.

Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com>
---
 arch/sh/mm/cache-sh2a.c |   74 +++++++++++++++++++++++++++++------------------
 1 files changed, 46 insertions(+), 28 deletions(-)

diff --git a/arch/sh/mm/cache-sh2a.c b/arch/sh/mm/cache-sh2a.c
index 1f51225..b1bdef1 100644
--- a/arch/sh/mm/cache-sh2a.c
+++ b/arch/sh/mm/cache-sh2a.c
@@ -15,8 +15,20 @@
 #include <asm/cacheflush.h>
 #include <asm/io.h>
 
+/*
+ * The maximum number of pages we support up to when doing ranged cache
+ * flushing. Anything exceeding this will simply flush the cache in its
+ * entirety.
+ */
+#define MAX_OCACHE_PAGES	32
+#define MAX_ICACHE_PAGES	32
+
+/*
+ * Write back the dirty D-caches, but not invalidate them.
+ */
 static void sh2a__flush_wback_region(void *start, int size)
 {
+#ifdef CONFIG_CACHE_WRITEBACK
 	unsigned long v;
 	unsigned long begin, end;
 	unsigned long flags;
@@ -42,8 +54,12 @@ static void sh2a__flush_wback_region(void *start, int size)
 
 	back_to_cached();
 	local_irq_restore(flags);
+#endif
 }
 
+/*
+ * Write back the dirty D-caches and invalidate them.
+ */
 static void sh2a__flush_purge_region(void *start, int size)
 {
 	unsigned long v;
@@ -61,10 +77,14 @@ static void sh2a__flush_purge_region(void *start, int size)
 		__raw_writel((v & CACHE_PHYSADDR_MASK),
 			  CACHE_OC_ADDRESS_ARRAY | (v & 0x000007f0) | 0x00000008);
 	}
+
 	back_to_cached();
 	local_irq_restore(flags);
 }
 
+/*
+ * Invalidate the D-caches, but no write back please
+ */
 static void sh2a__flush_invalidate_region(void *start, int size)
 {
 	unsigned long v;
@@ -74,29 +94,27 @@ static void sh2a__flush_invalidate_region(void *start, int size)
 	begin = (unsigned long)start & ~(L1_CACHE_BYTES-1);
 	end = ((unsigned long)start + size + L1_CACHE_BYTES-1)
 		& ~(L1_CACHE_BYTES-1);
+
 	local_irq_save(flags);
 	jump_to_uncached();
 
-#ifdef CONFIG_CACHE_WRITEBACK
-	__raw_writel(__raw_readl(CCR) | CCR_OCACHE_INVALIDATE, CCR);
-	/* I-cache invalidate */
-	for (v = begin; v < end; v+=L1_CACHE_BYTES) {
-		__raw_writel((v & CACHE_PHYSADDR_MASK),
-			  CACHE_IC_ADDRESS_ARRAY | (v & 0x000007f0) | 0x00000008);
-	}
-#else
-	for (v = begin; v < end; v+=L1_CACHE_BYTES) {
-		__raw_writel((v & CACHE_PHYSADDR_MASK),
-			  CACHE_IC_ADDRESS_ARRAY | (v & 0x000007f0) | 0x00000008);
-		__raw_writel((v & CACHE_PHYSADDR_MASK),
-			  CACHE_OC_ADDRESS_ARRAY | (v & 0x000007f0) | 0x00000008);
+	/* If there are too many pages then just blow the cache */
+	if (((end - begin) >> PAGE_SHIFT) >= MAX_OCACHE_PAGES) {
+		__raw_writel(__raw_readl(CCR) | CCR_OCACHE_INVALIDATE, CCR);
+	} else {
+		for (v = begin; v < end; v+=L1_CACHE_BYTES) {
+			__raw_writel((v & CACHE_PHYSADDR_MASK),
+				  CACHE_OC_ADDRESS_ARRAY | (v & 0x000007f0) | 0x00000008);
+		}
 	}
-#endif
+
 	back_to_cached();
 	local_irq_restore(flags);
 }
 
-/* WBack O-Cache and flush I-Cache */
+/*
+ * Write back the range of D-cache, and purge the I-cache.
+ */
 static void sh2a_flush_icache_range(void *args)
 {
 	struct flusher_data *data = args;
@@ -107,23 +125,23 @@ static void sh2a_flush_icache_range(void *args)
 	start = data->addr1 & ~(L1_CACHE_BYTES-1);
 	end = (data->addr2 + L1_CACHE_BYTES-1) & ~(L1_CACHE_BYTES-1);
 
+#ifdef CONFIG_CACHE_WRITEBACK
+	sh2a__flush_wback_region((void *)start, end-start);
+#endif
+
 	local_irq_save(flags);
 	jump_to_uncached();
 
-	for (v = start; v < end; v+=L1_CACHE_BYTES) {
-		unsigned long addr = (v & 0x000007f0);
-		int way;
-		/* O-Cache writeback */
-		for (way = 0; way < 4; way++) {
-			unsigned long data =  __raw_readl(CACHE_OC_ADDRESS_ARRAY | addr | (way << 11));
-			if ((data & CACHE_PHYSADDR_MASK) = (v & CACHE_PHYSADDR_MASK)) {
-				data &= ~SH_CACHE_UPDATED;
-				__raw_writel(data, CACHE_OC_ADDRESS_ARRAY | addr | (way << 11));
-			}
+	/* I-Cache invalidate */
+	/* If there are too many pages then just blow the cache */
+	if (((end - start) >> PAGE_SHIFT) >= MAX_ICACHE_PAGES) {
+		__raw_writel(__raw_readl(CCR) | CCR_ICACHE_INVALIDATE, CCR);
+	} else {
+		for (v = start; v < end; v+=L1_CACHE_BYTES) {
+			unsigned long addr = (v & 0x000007f0);
+			__raw_writel(addr,
+				  CACHE_IC_ADDRESS_ARRAY | addr | 0x00000008);
 		}
-		/* I-Cache invalidate */
-		__raw_writel(addr,
-			  CACHE_IC_ADDRESS_ARRAY | addr | 0x00000008);
 	}
 
 	back_to_cached();
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 0/2] ARM: mach-shmobile: clock-r8a7779: patches
From: Kuninori Morimoto @ 2011-12-20  8:46 UTC (permalink / raw)
  To: linux-sh


Hi Paul, Magnus

These are r8a7779 clock update patches which depends on Magnus's
[ARM: mach-shmobile: r8a7779 and Marzen V2] patches

Kuninori Morimoto (2):
      ARM: mach-shmobile: clock-r8a7779: add DIV4 clock support
      ARM: mach-shmobile: clock-r8a7779: clkz/clkzs support

Best regards
---
Kuninori Morimoto

^ permalink raw reply

* [PATCH 1/2] ARM: mach-shmobile: clock-r8a7779: add DIV4 clock support
From: Kuninori Morimoto @ 2011-12-20  8:52 UTC (permalink / raw)
  To: linux-sh

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
---
 arch/arm/mach-shmobile/clock-r8a7779.c |   76 ++++++++++++++++++++++++-------
 1 files changed, 59 insertions(+), 17 deletions(-)

diff --git a/arch/arm/mach-shmobile/clock-r8a7779.c b/arch/arm/mach-shmobile/clock-r8a7779.c
index 8a90106..29c3306 100644
--- a/arch/arm/mach-shmobile/clock-r8a7779.c
+++ b/arch/arm/mach-shmobile/clock-r8a7779.c
@@ -45,36 +45,75 @@ static struct clk_mapping cpg_mapping = {
 	.len	= 0x80,
 };
 
-static struct clk clkp = {
-	.rate	= 62500000, /* FIXME: shortcut */
-	.flags	= CLK_ENABLE_ON_INIT,
-	.mapping = &cpg_mapping,
+/*
+ * Default rate for the root input clock, reset this with clk_set_rate()
+ * from the platform code.
+ */
+static struct clk plla_clk = {
+	.rate		= 1500000000,
+	.mapping	= &cpg_mapping,
 };
 
 static struct clk *main_clks[] = {
-	&clkp,
+	&plla_clk,
+};
+
+static int divisors[] = { 0, 0, 0, 6, 8, 12, 16, 0, 24, 32, 36, 0, 0, 0, 0, 0 };
+
+static struct clk_div_mult_table div4_div_mult_table = {
+	.divisors = divisors,
+	.nr_divisors = ARRAY_SIZE(divisors),
+};
+
+static struct clk_div4_table div4_table = {
+	.div_mult_table = &div4_div_mult_table,
+};
+
+enum { DIV4_S, DIV4_OUT, DIV4_S4, DIV4_S3, DIV4_S1, DIV4_P, DIV4_NR };
+
+static struct clk div4_clks[DIV4_NR] = {
+	[DIV4_S]	= SH_CLK_DIV4(&plla_clk, FRQMR, 20,
+				      0x0018, CLK_ENABLE_ON_INIT),
+	[DIV4_OUT]	= SH_CLK_DIV4(&plla_clk, FRQMR, 16,
+				      0x0700, CLK_ENABLE_ON_INIT),
+	[DIV4_S4]	= SH_CLK_DIV4(&plla_clk, FRQMR, 12,
+				      0x0040, CLK_ENABLE_ON_INIT),
+	[DIV4_S3]	= SH_CLK_DIV4(&plla_clk, FRQMR, 8,
+				      0x0010, CLK_ENABLE_ON_INIT),
+	[DIV4_S1]	= SH_CLK_DIV4(&plla_clk, FRQMR, 4,
+				      0x0060, CLK_ENABLE_ON_INIT),
+	[DIV4_P]	= SH_CLK_DIV4(&plla_clk, FRQMR, 0,
+				      0x0300, CLK_ENABLE_ON_INIT),
 };
 
 enum { MSTP026, MSTP025, MSTP024, MSTP023, MSTP022, MSTP021,
 	MSTP016, MSTP015, MSTP014,
 	MSTP_NR };
 
-#define MSTP(_parent, _reg, _bit, _flags) \
-	SH_CLK_MSTP32(_parent, _reg, _bit, _flags)
-
 static struct clk mstp_clks[MSTP_NR] = {
-	[MSTP026] = MSTP(&clkp, MSTPCR0, 26, 0), /* SCIF0 */
-	[MSTP025] = MSTP(&clkp, MSTPCR0, 25, 0), /* SCIF1 */
-	[MSTP024] = MSTP(&clkp, MSTPCR0, 24, 0), /* SCIF2 */
-	[MSTP023] = MSTP(&clkp, MSTPCR0, 23, 0), /* SCIF3 */
-	[MSTP022] = MSTP(&clkp, MSTPCR0, 22, 0), /* SCIF4 */
-	[MSTP021] = MSTP(&clkp, MSTPCR0, 21, 0), /* SCIF5 */
-	[MSTP016] = MSTP(&clkp, MSTPCR0, 16, 0), /* TMU0 */
-	[MSTP015] = MSTP(&clkp, MSTPCR0, 15, 0), /* TMU1 */
-	[MSTP014] = MSTP(&clkp, MSTPCR0, 14, 0), /* TMU2 */
+	[MSTP026] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 26, 0), /* SCIF0 */
+	[MSTP025] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 25, 0), /* SCIF1 */
+	[MSTP024] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 24, 0), /* SCIF2 */
+	[MSTP023] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 23, 0), /* SCIF3 */
+	[MSTP022] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 22, 0), /* SCIF4 */
+	[MSTP021] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 21, 0), /* SCIF5 */
+	[MSTP016] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 16, 0), /* TMU0 */
+	[MSTP015] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 15, 0), /* TMU1 */
+	[MSTP014] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 14, 0), /* TMU2 */
 };
 
 static struct clk_lookup lookups[] = {
+	/* main clocks */
+	CLKDEV_CON_ID("plla_clk", &plla_clk),
+
+	/* DIV4 clocks */
+	CLKDEV_CON_ID("shyway_clk",	&div4_clks[DIV4_S]),
+	CLKDEV_CON_ID("bus_clk",	&div4_clks[DIV4_OUT]),
+	CLKDEV_CON_ID("shyway4_clk",	&div4_clks[DIV4_S4]),
+	CLKDEV_CON_ID("shyway3_clk",	&div4_clks[DIV4_S3]),
+	CLKDEV_CON_ID("shyway1_clk",	&div4_clks[DIV4_S1]),
+	CLKDEV_CON_ID("peripheral_clk",	&div4_clks[DIV4_P]),
+
 	/* MSTP32 clocks */
 	CLKDEV_DEV_ID("sh_tmu.0", &mstp_clks[MSTP016]), /* TMU00 */
 	CLKDEV_DEV_ID("sh_tmu.1", &mstp_clks[MSTP016]), /* TMU01 */
@@ -94,6 +133,9 @@ void __init r8a7779_clock_init(void)
 		ret = clk_register(main_clks[k]);
 
 	if (!ret)
+		ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
+
+	if (!ret)
 		ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
 
 	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
-- 
1.7.5.4


^ permalink raw reply related

* [PATCH 2/2] ARM: mach-shmobile: clock-r8a7779: clkz/clkzs support
From: Kuninori Morimoto @ 2011-12-20  8:53 UTC (permalink / raw)
  To: linux-sh

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
---
 arch/arm/mach-shmobile/clock-r8a7779.c |   29 +++++++++++++++++++++++++++++
 1 files changed, 29 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-shmobile/clock-r8a7779.c b/arch/arm/mach-shmobile/clock-r8a7779.c
index 29c3306..b4b0e8c 100644
--- a/arch/arm/mach-shmobile/clock-r8a7779.c
+++ b/arch/arm/mach-shmobile/clock-r8a7779.c
@@ -102,9 +102,35 @@ static struct clk mstp_clks[MSTP_NR] = {
 	[MSTP014] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 14, 0), /* TMU2 */
 };
 
+static unsigned long mul4_recalc(struct clk *clk)
+{
+	return clk->parent->rate * 4;
+}
+
+static struct clk_ops mul4_clk_ops = {
+	.recalc		= mul4_recalc,
+};
+
+struct clk clkz_clk = {
+	.ops		= &mul4_clk_ops,
+	.parent		= &div4_clks[DIV4_S],
+};
+
+struct clk clkzs_clk = {
+	/* clks x 4 / 4 = clks */
+	.parent		= &div4_clks[DIV4_S],
+};
+
+static struct clk *late_main_clks[] = {
+	&clkz_clk,
+	&clkzs_clk,
+};
+
 static struct clk_lookup lookups[] = {
 	/* main clocks */
 	CLKDEV_CON_ID("plla_clk", &plla_clk),
+	CLKDEV_CON_ID("clkz_clk", &clkz_clk),
+	CLKDEV_CON_ID("clkzs_clk", &clkzs_clk),
 
 	/* DIV4 clocks */
 	CLKDEV_CON_ID("shyway_clk",	&div4_clks[DIV4_S]),
@@ -138,6 +164,9 @@ void __init r8a7779_clock_init(void)
 	if (!ret)
 		ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
 
+	for (k = 0; !ret && (k < ARRAY_SIZE(late_main_clks)); k++)
+		ret = clk_register(late_main_clks[k]);
+
 	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
 
 	if (!ret)
-- 
1.7.5.4


^ permalink raw reply related

* Re: [GIT PULL] rmobile fixes for 3.2-rc7
From: Linus Torvalds @ 2011-12-20 19:39 UTC (permalink / raw)
  To: Paul Mundt; +Cc: linux-sh, linux-kernel
In-Reply-To: <20111220082416.GA21727@linux-sh.org>

On Tue, Dec 20, 2011 at 12:24 AM, Paul Mundt <lethal@linux-sh.org> wrote:
> Please pull from:
>
>        git://github.com/pmundt/linux-sh.git rmobile-fixes-for-linus

Ugh. Since git does it so well these days, I'd really like to pull
signed tags only from places like github.

I pulled this, but it would really be quite easy to just have the pull
request be for a signed tag you upload instead of a branch, and then I
wouldn't have to worry about it.

                   Linus

^ permalink raw reply

* [PATCH] ARM: mach-shmobile: r8a7779 power domain support
From: Magnus Damm @ 2011-12-22  8:12 UTC (permalink / raw)
  To: linux-sh

From: Magnus Damm <damm@opensource.se>

Add power domain control support for the r8a7779 SoC.

This adds support for 4 power domains for I/O Devices
together with code that can be used for CPU cores as well.

The only out of the ordinary experience is the need for
ioremap() of SYSC registers. Because of that we need to
execute some init function before setting up the domains.

Signed-off-by: Magnus Damm <damm@opensource.se>
---

 Built on top of linux-3.2-rc + r8a7779 patches for now.
 Needs to be reworked to fit on top of the linux-pm tree.

 arch/arm/mach-shmobile/Makefile               |    1 
 arch/arm/mach-shmobile/include/mach/common.h  |    1 
 arch/arm/mach-shmobile/include/mach/r8a7779.h |   35 +++
 arch/arm/mach-shmobile/pm-r8a7779.c           |  235 +++++++++++++++++++++++++
 arch/arm/mach-shmobile/setup-r8a7779.c        |    8 
 5 files changed, 280 insertions(+)

--- 0015/arch/arm/mach-shmobile/Makefile
+++ work/arch/arm/mach-shmobile/Makefile	2011-12-22 16:21:03.000000000 +0900
@@ -37,6 +37,7 @@ obj-$(CONFIG_ARCH_R8A7779)	+= entry-gic.
 obj-$(CONFIG_SUSPEND)		+= suspend.o
 obj-$(CONFIG_CPU_IDLE)		+= cpuidle.o
 obj-$(CONFIG_ARCH_SH7372)	+= pm-sh7372.o sleep-sh7372.o
+obj-$(CONFIG_ARCH_R8A7779)	+= pm-r8a7779.o
 
 # Board objects
 obj-$(CONFIG_MACH_G3EVM)	+= board-g3evm.o
--- 0015/arch/arm/mach-shmobile/include/mach/common.h
+++ work/arch/arm/mach-shmobile/include/mach/common.h	2011-12-22 16:21:03.000000000 +0900
@@ -58,5 +58,6 @@ extern void r8a7779_add_early_devices(vo
 extern void r8a7779_add_standard_devices(void);
 extern void r8a7779_clock_init(void);
 extern void r8a7779_pinmux_init(void);
+extern void r8a7779_pm_init(void);
 
 #endif /* __ARCH_MACH_COMMON_H */
--- 0016/arch/arm/mach-shmobile/include/mach/r8a7779.h
+++ work/arch/arm/mach-shmobile/include/mach/r8a7779.h	2011-12-22 16:22:01.000000000 +0900
@@ -1,6 +1,9 @@
 #ifndef __ASM_R8A7779_H__
 #define __ASM_R8A7779_H__
 
+#include <linux/sh_clk.h>
+#include <linux/pm_domain.h>
+
 /* Pin Function Controller:
  * GPIO_FN_xx - GPIO used to select pin function
  * GPIO_GP_x_x - GPIO mapped to real I/O pin on CPU
@@ -322,4 +325,36 @@ enum {
 	GPIO_FN_GPS_MAG, GPIO_FN_FCE, GPIO_FN_SCK4_B,
 };
 
+struct platform_device;
+
+struct r8a7779_pm_ch {
+	unsigned long chan_offs;
+	unsigned int chan_bit;
+	unsigned int isr_bit;
+};
+
+struct r8a7779_pm_domain {
+	struct generic_pm_domain genpd;
+	struct r8a7779_pm_ch ch;
+};
+
+static inline struct r8a7779_pm_ch *to_r8a7779_ch(struct generic_pm_domain *d)
+{
+	return &container_of(d, struct r8a7779_pm_domain, genpd)->ch;
+}
+
+#ifdef CONFIG_PM
+extern struct r8a7779_pm_domain r8a7779_sh4a;
+extern struct r8a7779_pm_domain r8a7779_sgx;
+extern struct r8a7779_pm_domain r8a7779_vdp1;
+extern struct r8a7779_pm_domain r8a7779_impx3;
+
+extern void r8a7779_init_pm_domain(struct r8a7779_pm_domain *r8a7779_pd);
+extern void r8a7779_add_device_to_domain(struct r8a7779_pm_domain *r8a7779_pd,
+					struct platform_device *pdev);
+#else
+#define r8a7779_init_pm_domain(pd) do { } while (0)
+#define r8a7779_add_device_to_domain(pd, pdev) do { } while (0)
+#endif /* CONFIG_PM */
+
 #endif /* __ASM_R8A7779_H__ */
--- /dev/null
+++ work/arch/arm/mach-shmobile/pm-r8a7779.c	2011-12-22 16:21:44.000000000 +0900
@@ -0,0 +1,235 @@
+/*
+ * r8a7779 Power management support
+ *
+ * Copyright (C) 2011  Renesas Solutions Corp.
+ * Copyright (C) 2011  Magnus Damm
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/pm.h>
+#include <linux/suspend.h>
+#include <linux/err.h>
+#include <linux/pm_clock.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/console.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <mach/common.h>
+#include <mach/r8a7779.h>
+
+static void __iomem *r8a7779_sysc_base;
+
+/* SYSC */
+#define SYSCSR 0x00
+#define SYSCISR 0x04
+#define SYSCISCR 0x08
+#define SYSCIER 0x0c
+#define SYSCIMR 0x10
+#define PWRSR0 0x40
+#define PWRSR1 0x80
+#define PWRSR2 0xc0
+#define PWRSR3 0x100
+#define PWRSR4 0x140
+
+#define PWRSR_OFFS 0x00
+#define PWROFFCR_OFFS 0x04
+#define PWRONCR_OFFS 0x0c
+#define PWRER_OFFS 0x14
+
+#define SYSCSR_RETRIES 100
+#define SYSCSR_DELAY_US 1
+
+#define SYSCISR_RETRIES 1000
+#define SYSCISR_DELAY_US 1
+
+#ifdef CONFIG_PM
+
+static int r8a7779_sysc_pwr_on_off(struct r8a7779_pm_ch *r8a7779_ch,
+				   int sr_bit, int reg_offs)
+{
+	int k;
+
+	for (k = 0; k < SYSCSR_RETRIES; k++) {
+		if (ioread32(r8a7779_sysc_base + SYSCSR) & (1 << sr_bit))
+			break;
+		udelay(SYSCSR_DELAY_US);
+	}
+
+	if (k = SYSCSR_RETRIES)
+		return -EAGAIN;
+
+	iowrite32(1 << r8a7779_ch->chan_bit,
+		  r8a7779_sysc_base + r8a7779_ch->chan_offs + reg_offs);
+
+	return 0;
+}
+
+static int r8a7779_sysc_pwr_off(struct r8a7779_pm_ch *r8a7779_ch)
+{
+	return r8a7779_sysc_pwr_on_off(r8a7779_ch, 0, PWROFFCR_OFFS);
+}
+
+static int r8a7779_sysc_pwr_on(struct r8a7779_pm_ch *r8a7779_ch)
+{
+	return r8a7779_sysc_pwr_on_off(r8a7779_ch, 1, PWRONCR_OFFS);
+}
+
+static int r8a7779_sysc_update(struct r8a7779_pm_ch *r8a7779_ch,
+			       int (*on_off_fn)(struct r8a7779_pm_ch *))
+{
+	unsigned int isr_mask = 1 << r8a7779_ch->isr_bit;
+	unsigned int chan_mask = 1 << r8a7779_ch->chan_bit;
+	unsigned int status;
+	int ret = 0;
+	int k;
+
+	iowrite32(isr_mask, r8a7779_sysc_base + SYSCISCR);
+
+	do {
+		ret = on_off_fn(r8a7779_ch);
+		if (ret)
+			goto out;
+
+		status = ioread32(r8a7779_sysc_base +
+				  r8a7779_ch->chan_offs + PWRER_OFFS);
+	} while (status & chan_mask);
+
+	for (k = 0; k < SYSCISR_RETRIES; k++) {
+		if (ioread32(r8a7779_sysc_base + SYSCISR) & isr_mask)
+			break;
+		udelay(SYSCISR_DELAY_US);
+	}
+
+	if (k = SYSCISR_RETRIES)
+		ret = -EIO;
+
+	iowrite32(isr_mask, r8a7779_sysc_base + SYSCISCR);
+
+ out:
+	pr_debug("r8a7779 power domain %d: %02x %02x %02x %02x %02x -> %d\n",
+		 r8a7779_ch->isr_bit, ioread32(r8a7779_sysc_base + PWRSR0),
+		 ioread32(r8a7779_sysc_base + PWRSR1),
+		 ioread32(r8a7779_sysc_base + PWRSR2),
+		 ioread32(r8a7779_sysc_base + PWRSR3),
+		 ioread32(r8a7779_sysc_base + PWRSR4), ret);
+	return ret;
+}
+
+static int r8a7779_sysc_power_down(struct r8a7779_pm_ch *r8a7779_ch)
+{
+	return r8a7779_sysc_update(r8a7779_ch, r8a7779_sysc_pwr_off);
+}
+
+static int r8a7779_sysc_power_up(struct r8a7779_pm_ch *r8a7779_ch)
+{
+	return r8a7779_sysc_update(r8a7779_ch, r8a7779_sysc_pwr_on);
+}
+
+static void __init r8a7779_sysc_init(void)
+{
+	r8a7779_sysc_base = ioremap_nocache(0xffd85000, PAGE_SIZE);
+	if (!r8a7779_sysc_base)
+		panic("unable to ioremap r8a7779 SYSC hardware block\n");
+
+	/* enable all interrupt sources, but do not use interrupt handler */
+	iowrite32(0x0131000e, r8a7779_sysc_base + SYSCIER);
+	iowrite32(0, r8a7779_sysc_base + SYSCIMR);
+}
+
+static int pd_power_down(struct generic_pm_domain *genpd)
+{
+	return r8a7779_sysc_power_down(to_r8a7779_ch(genpd));
+}
+
+static int pd_power_up(struct generic_pm_domain *genpd)
+{
+	return r8a7779_sysc_power_up(to_r8a7779_ch(genpd));
+}
+
+static bool pd_is_off(struct generic_pm_domain *genpd)
+{
+	struct r8a7779_pm_ch *r8a7779_ch = to_r8a7779_ch(genpd);
+	unsigned int st;
+
+	st = ioread32(r8a7779_sysc_base + r8a7779_ch->chan_offs + PWRSR_OFFS);
+	if (st & (1 << r8a7779_ch->chan_bit))
+		return true;
+
+	return false;
+}
+
+static bool pd_active_wakeup(struct device *dev)
+{
+	return true;
+}
+
+void r8a7779_init_pm_domain(struct r8a7779_pm_domain *r8a7779_pd)
+{
+	struct generic_pm_domain *genpd = &r8a7779_pd->genpd;
+
+	pm_genpd_init(genpd, NULL, false);
+	genpd->stop_device = pm_clk_suspend;
+	genpd->start_device = pm_clk_resume;
+	genpd->dev_irq_safe = true;
+	genpd->active_wakeup = pd_active_wakeup;
+	genpd->power_off = pd_power_down;
+	genpd->power_on = pd_power_up;
+
+	if (pd_is_off(&r8a7779_pd->genpd))
+		pd_power_up(&r8a7779_pd->genpd);
+}
+
+void r8a7779_add_device_to_domain(struct r8a7779_pm_domain *r8a7779_pd,
+				 struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+
+	pm_genpd_add_device(&r8a7779_pd->genpd, dev);
+	if (pm_clk_no_clocks(dev))
+		pm_clk_add(dev, NULL);
+}
+
+struct r8a7779_pm_domain r8a7779_sh4a = {
+	.ch = {
+		.chan_offs = 0x80, /* PWRSR1 .. PWRER1 */
+		.isr_bit = 16, /* SH4A */
+	}
+};
+
+struct r8a7779_pm_domain r8a7779_sgx = {
+	.ch = {
+		.chan_offs = 0xc0, /* PWRSR2 .. PWRER2 */
+		.isr_bit = 20, /* SGX */
+	}
+};
+
+struct r8a7779_pm_domain r8a7779_vdp1 = {
+	.ch = {
+		.chan_offs = 0x100, /* PWRSR3 .. PWRER3 */
+		.isr_bit = 21, /* VDP */
+	}
+};
+
+struct r8a7779_pm_domain r8a7779_impx3 = {
+	.ch = {
+		.chan_offs = 0x140, /* PWRSR4 .. PWRER4 */
+		.isr_bit = 24, /* IMP */
+	}
+};
+
+#else /* CONFIG_PM */
+
+static inline void r8a7779_sysc_init(void) {}
+
+#endif /* CONFIG_PM */
+
+void __init r8a7779_pm_init(void)
+{
+	r8a7779_sysc_init();
+}
--- 0021/arch/arm/mach-shmobile/setup-r8a7779.c
+++ work/arch/arm/mach-shmobile/setup-r8a7779.c	2011-12-22 16:21:03.000000000 +0900
@@ -30,6 +30,7 @@
 #include <linux/sh_timer.h>
 #include <mach/hardware.h>
 #include <mach/r8a7779.h>
+#include <mach/common.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
@@ -218,6 +219,13 @@ static struct platform_device *r8a7779_l
 
 void __init r8a7779_add_standard_devices(void)
 {
+	r8a7779_pm_init();
+
+	r8a7779_init_pm_domain(&r8a7779_sh4a);
+	r8a7779_init_pm_domain(&r8a7779_sgx);
+	r8a7779_init_pm_domain(&r8a7779_vdp1);
+	r8a7779_init_pm_domain(&r8a7779_impx3);
+
 	platform_add_devices(r8a7779_early_devices,
 			    ARRAY_SIZE(r8a7779_early_devices));
 	platform_add_devices(r8a7779_late_devices,

^ permalink raw reply

* [PATCH] ARM: mach-shmobile: r8a7779 SMP support
From: Magnus Damm @ 2011-12-22  8:17 UTC (permalink / raw)
  To: linux-sh

From: Magnus Damm <damm@opensource.se>

This patch ties in the r8a7779 power domain code together with
SMP glue code to add SMP support. The SMP code allows us to
control the power domains via CPU hotplug, but this feature
is not fully implemented yet. At this point the kernel boots
with the 4 Cortex-A9 cores in SMP mode.

Signed-off-by: Magnus Damm <damm@opensource.se>
---

 Depends on the r8a7779 base plus the power domain code:
 [PATCH] ARM: mach-shmobile: r8a7779 power domain support

 arch/arm/mach-shmobile/Makefile               |    1 
 arch/arm/mach-shmobile/include/mach/common.h  |    5 
 arch/arm/mach-shmobile/include/mach/r8a7779.h |    3 
 arch/arm/mach-shmobile/platsmp.c              |   13 ++
 arch/arm/mach-shmobile/pm-r8a7779.c           |   30 ++++-
 arch/arm/mach-shmobile/smp-r8a7779.c          |  131 +++++++++++++++++++++++++
 6 files changed, 175 insertions(+), 8 deletions(-)

--- 0022/arch/arm/mach-shmobile/Makefile
+++ work/arch/arm/mach-shmobile/Makefile	2011-12-22 16:49:45.000000000 +0900
@@ -17,6 +17,7 @@ smp-y				:= platsmp.o headsmp.o
 smp-$(CONFIG_HOTPLUG_CPU)	+= hotplug.o
 smp-$(CONFIG_LOCAL_TIMERS)	+= localtimer.o
 smp-$(CONFIG_ARCH_SH73A0)	+= smp-sh73a0.o
+smp-$(CONFIG_ARCH_R8A7779)	+= smp-r8a7779.o
 
 # Pinmux setup
 pfc-y				:--- 0022/arch/arm/mach-shmobile/include/mach/common.h
+++ work/arch/arm/mach-shmobile/include/mach/common.h	2011-12-22 16:49:45.000000000 +0900
@@ -60,4 +60,9 @@ extern void r8a7779_clock_init(void);
 extern void r8a7779_pinmux_init(void);
 extern void r8a7779_pm_init(void);
 
+extern unsigned int r8a7779_get_core_count(void);
+extern void r8a7779_secondary_init(unsigned int cpu);
+extern int r8a7779_boot_secondary(unsigned int cpu);
+extern void r8a7779_smp_prepare_cpus(void);
+
 #endif /* __ARCH_MACH_COMMON_H */
--- 0022/arch/arm/mach-shmobile/include/mach/r8a7779.h
+++ work/arch/arm/mach-shmobile/include/mach/r8a7779.h	2011-12-22 16:49:45.000000000 +0900
@@ -343,6 +343,9 @@ static inline struct r8a7779_pm_ch *to_r
 	return &container_of(d, struct r8a7779_pm_domain, genpd)->ch;
 }
 
+extern int r8a7779_sysc_power_down(struct r8a7779_pm_ch *r8a7779_ch);
+extern int r8a7779_sysc_power_up(struct r8a7779_pm_ch *r8a7779_ch);
+
 #ifdef CONFIG_PM
 extern struct r8a7779_pm_domain r8a7779_sh4a;
 extern struct r8a7779_pm_domain r8a7779_sgx;
--- 0001/arch/arm/mach-shmobile/platsmp.c
+++ work/arch/arm/mach-shmobile/platsmp.c	2011-12-22 16:49:45.000000000 +0900
@@ -22,12 +22,16 @@
 #include <mach/common.h>
 
 #define is_sh73a0() (machine_is_ag5evm() || machine_is_kota2())
+#define is_r8a7779() machine_is_marzen()
 
 static unsigned int __init shmobile_smp_get_core_count(void)
 {
 	if (is_sh73a0())
 		return sh73a0_get_core_count();
 
+	if (is_r8a7779())
+		return r8a7779_get_core_count();
+
 	return 1;
 }
 
@@ -35,6 +39,9 @@ static void __init shmobile_smp_prepare_
 {
 	if (is_sh73a0())
 		sh73a0_smp_prepare_cpus();
+
+	if (is_r8a7779())
+		r8a7779_smp_prepare_cpus();
 }
 
 void __cpuinit platform_secondary_init(unsigned int cpu)
@@ -43,6 +50,9 @@ void __cpuinit platform_secondary_init(u
 
 	if (is_sh73a0())
 		sh73a0_secondary_init(cpu);
+
+	if (is_r8a7779())
+		r8a7779_secondary_init(cpu);
 }
 
 int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
@@ -50,6 +60,9 @@ int __cpuinit boot_secondary(unsigned in
 	if (is_sh73a0())
 		return sh73a0_boot_secondary(cpu);
 
+	if (is_r8a7779())
+		return r8a7779_boot_secondary(cpu);
+
 	return -ENOSYS;
 }
 
--- 0022/arch/arm/mach-shmobile/pm-r8a7779.c
+++ work/arch/arm/mach-shmobile/pm-r8a7779.c	2011-12-22 16:55:47.000000000 +0900
@@ -48,7 +48,9 @@ static void __iomem *r8a7779_sysc_base;
 #define SYSCISR_RETRIES 1000
 #define SYSCISR_DELAY_US 1
 
-#ifdef CONFIG_PM
+#if defined(CONFIG_PM) || defined(CONFIG_SMP)
+
+static DEFINE_SPINLOCK(r8a7779_sysc_lock); /* SMP CPUs + I/O devices */
 
 static int r8a7779_sysc_pwr_on_off(struct r8a7779_pm_ch *r8a7779_ch,
 				   int sr_bit, int reg_offs)
@@ -86,9 +88,12 @@ static int r8a7779_sysc_update(struct r8
 	unsigned int isr_mask = 1 << r8a7779_ch->isr_bit;
 	unsigned int chan_mask = 1 << r8a7779_ch->chan_bit;
 	unsigned int status;
+	unsigned long flags;
 	int ret = 0;
 	int k;
 
+	spin_lock_irqsave(&r8a7779_sysc_lock, flags);
+
 	iowrite32(isr_mask, r8a7779_sysc_base + SYSCISCR);
 
 	do {
@@ -112,6 +117,8 @@ static int r8a7779_sysc_update(struct r8
 	iowrite32(isr_mask, r8a7779_sysc_base + SYSCISCR);
 
  out:
+	spin_unlock_irqrestore(&r8a7779_sysc_lock, flags);
+
 	pr_debug("r8a7779 power domain %d: %02x %02x %02x %02x %02x -> %d\n",
 		 r8a7779_ch->isr_bit, ioread32(r8a7779_sysc_base + PWRSR0),
 		 ioread32(r8a7779_sysc_base + PWRSR1),
@@ -121,12 +128,12 @@ static int r8a7779_sysc_update(struct r8
 	return ret;
 }
 
-static int r8a7779_sysc_power_down(struct r8a7779_pm_ch *r8a7779_ch)
+int r8a7779_sysc_power_down(struct r8a7779_pm_ch *r8a7779_ch)
 {
 	return r8a7779_sysc_update(r8a7779_ch, r8a7779_sysc_pwr_off);
 }
 
-static int r8a7779_sysc_power_up(struct r8a7779_pm_ch *r8a7779_ch)
+int r8a7779_sysc_power_up(struct r8a7779_pm_ch *r8a7779_ch)
 {
 	return r8a7779_sysc_update(r8a7779_ch, r8a7779_sysc_pwr_on);
 }
@@ -142,6 +149,14 @@ static void __init r8a7779_sysc_init(voi
 	iowrite32(0, r8a7779_sysc_base + SYSCIMR);
 }
 
+#else /* CONFIG_PM || CONFIG_SMP */
+
+static inline void r8a7779_sysc_init(void) {}
+
+#endif /* CONFIG_PM || CONFIG_SMP */
+
+#ifdef CONFIG_PM
+
 static int pd_power_down(struct generic_pm_domain *genpd)
 {
 	return r8a7779_sysc_power_down(to_r8a7779_ch(genpd));
@@ -223,13 +238,12 @@ struct r8a7779_pm_domain r8a7779_impx3  	}
 };
 
-#else /* CONFIG_PM */
-
-static inline void r8a7779_sysc_init(void) {}
-
 #endif /* CONFIG_PM */
 
 void __init r8a7779_pm_init(void)
 {
-	r8a7779_sysc_init();
+	static int once;
+
+	if (!once++)
+		r8a7779_sysc_init();
 }
--- /dev/null
+++ work/arch/arm/mach-shmobile/smp-r8a7779.c	2011-12-22 16:49:46.000000000 +0900
@@ -0,0 +1,131 @@
+/*
+ * SMP support for R-Mobile / SH-Mobile - r8a7779 portion
+ *
+ * Copyright (C) 2011  Renesas Solutions Corp.
+ * Copyright (C) 2011  Magnus Damm
+ *
+ * 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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <mach/common.h>
+#include <mach/r8a7779.h>
+#include <asm/smp_scu.h>
+#include <asm/smp_twd.h>
+#include <asm/hardware/gic.h>
+
+#define AVECR 0xfe700040
+
+static struct r8a7779_pm_ch r8a7779_ch_cpu1 = {
+	.chan_offs = 0x40, /* PWRSR0 .. PWRER0 */
+	.chan_bit = 1, /* ARM1 */
+	.isr_bit = 1, /* ARM1 */
+};
+
+static struct r8a7779_pm_ch r8a7779_ch_cpu2 = {
+	.chan_offs = 0x40, /* PWRSR0 .. PWRER0 */
+	.chan_bit = 2, /* ARM2 */
+	.isr_bit = 2, /* ARM2 */
+};
+
+static struct r8a7779_pm_ch r8a7779_ch_cpu3 = {
+	.chan_offs = 0x40, /* PWRSR0 .. PWRER0 */
+	.chan_bit = 3, /* ARM3 */
+	.isr_bit = 3, /* ARM3 */
+};
+
+static struct r8a7779_pm_ch *r8a7779_ch_cpu[4] = {
+	[1] = &r8a7779_ch_cpu1,
+	[2] = &r8a7779_ch_cpu2,
+	[3] = &r8a7779_ch_cpu3,
+};
+
+static void __iomem *scu_base_addr(void)
+{
+	return (void __iomem *)0xf0000000;
+}
+
+static DEFINE_SPINLOCK(scu_lock);
+static unsigned long tmp;
+
+static void modify_scu_cpu_psr(unsigned long set, unsigned long clr)
+{
+	void __iomem *scu_base = scu_base_addr();
+
+	spin_lock(&scu_lock);
+	tmp = __raw_readl(scu_base + 8);
+	tmp &= ~clr;
+	tmp |= set;
+	spin_unlock(&scu_lock);
+
+	/* disable cache coherency after releasing the lock */
+	__raw_writel(tmp, scu_base + 8);
+}
+
+unsigned int __init r8a7779_get_core_count(void)
+{
+	void __iomem *scu_base = scu_base_addr();
+
+#ifdef CONFIG_HAVE_ARM_TWD
+	/* twd_base needs to be initialized before percpu_timer_setup() */
+	twd_base = (void __iomem *)0xf0000600;
+#endif
+
+	return scu_get_core_count(scu_base);
+}
+
+void __cpuinit r8a7779_secondary_init(unsigned int cpu)
+{
+	gic_secondary_init(0);
+}
+
+int __cpuinit r8a7779_boot_secondary(unsigned int cpu)
+{
+	struct r8a7779_pm_ch *ch = NULL;
+	int ret = -EIO;
+
+	cpu = cpu_logical_map(cpu);
+
+	/* enable cache coherency */
+	modify_scu_cpu_psr(0, 3 << (cpu * 8));
+
+	if (cpu < ARRAY_SIZE(r8a7779_ch_cpu))
+		ch = r8a7779_ch_cpu[cpu];
+
+	if (ch) {
+		r8a7779_sysc_power_down(ch);
+		ret = r8a7779_sysc_power_up(ch);
+	}
+
+	return ret;
+}
+
+void __init r8a7779_smp_prepare_cpus(void)
+{
+	int cpu = cpu_logical_map(0);
+
+	scu_enable(scu_base_addr());
+
+	/* Map the reset vector (in headsmp.S) */
+	__raw_writel(__pa(shmobile_secondary_vector), __io(AVECR));
+
+	/* enable cache coherency on CPU0 */
+	modify_scu_cpu_psr(0, 3 << (cpu * 8));
+
+	r8a7779_pm_init();
+}

^ 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