* [PATCH] sh: clkfwk: sh_clk_init_parent() should be called after clk_register()
From: Kuninori Morimoto @ 2011-12-12 3:02 UTC (permalink / raw)
To: linux-sh
sh_clk_init_parent() are using clk->mapped_reg
which is mapped in clk_register()
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
---
This is for latest paul/common/clkfwk
drivers/sh/clk/cpg.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c
index a0d8faa..45fee36 100644
--- a/drivers/sh/clk/cpg.c
+++ b/drivers/sh/clk/cpg.c
@@ -222,11 +222,11 @@ static int __init sh_clk_div6_register_ops(struct clk *clks, int nr,
clkp->ops = ops;
clkp->freq_table = freq_table + (k * freq_table_size);
clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END;
- ret = sh_clk_init_parent(clkp);
+ ret = clk_register(clkp);
if (ret < 0)
break;
- ret = clk_register(clkp);
+ ret = sh_clk_init_parent(clkp);
}
return ret;
--
1.7.5.4
^ permalink raw reply related
* [RFC][PATCH 4/4] PM / input / touchscreen: Make st1232 use device PM QoS constraints
From: Rafael J. Wysocki @ 2011-12-09 23:46 UTC (permalink / raw)
To: Linux-sh list; +Cc: Linux PM list, Guennadi Liakhovetski, Magnus Damm, LKML
In-Reply-To: <201112100042.45168.rjw@sisk.pl>
From: Rafael J. Wysocki <rjw@sisk.pl>
Make the st1232 driver use dev_pm_qos_add_ancestor_request() to
add a device PM QoS latency constraint for the I2C controller it
depends on, so that the controller won't go into an overly deep
low-power state when the touchscreen has to be particularly
responsive (e.g. when the user moves his or her finger on it)
and allow the A4R domain to be turned off if that doesn't violate
the PM QoS latency constraints.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
---
arch/arm/mach-shmobile/pm-sh7372.c | 28 +++++++++++++++++++++++++++-
drivers/input/touchscreen/st1232.c | 14 +++++++++++++-
2 files changed, 40 insertions(+), 2 deletions(-)
Index: linux/arch/arm/mach-shmobile/pm-sh7372.c
=================================--- linux.orig/arch/arm/mach-shmobile/pm-sh7372.c
+++ linux/arch/arm/mach-shmobile/pm-sh7372.c
@@ -239,7 +239,6 @@ struct sh7372_pm_domain sh7372_d4 = {
struct sh7372_pm_domain sh7372_a4r = {
.genpd.name = "A4R",
.bit_shift = 5,
- .gov = &pm_domain_always_on_gov,
.suspend = sh7372_a4r_suspend,
.resume = sh7372_intcs_resume,
};
@@ -496,9 +495,36 @@ static int sh7372_enter_suspend(suspend_
return 0;
}
+/**
+ * sh7372_pm_notifier_fn - SH7372 PM notifier routine.
+ * @notifier: Unused.
+ * @pm_event: Event being handled.
+ * @unused: Unused.
+ *
+ * This is necessary, because the A4R domain has to be "on" when
+ * suspend_device_irqs() and resume_device_irqs() are executed during system
+ * suspend and resume, respectively, so that those functions don't crash
+ * while accessing the INTCS.
+ */
+static int sh7372_pm_notifier_fn(struct notifier_block *notifier,
+ unsigned long pm_event, void *unused)
+{
+ switch (pm_event) {
+ case PM_SUSPEND_PREPARE:
+ pm_genpd_poweron(&sh7372_a4r.genpd);
+ break;
+ case PM_POST_SUSPEND:
+ pm_genpd_poweroff_unused();
+ break;
+ }
+
+ return NOTIFY_DONE;
+}
+
static void sh7372_suspend_init(void)
{
shmobile_suspend_ops.enter = sh7372_enter_suspend;
+ pm_notifier(sh7372_pm_notifier_fn, 0);
}
#else
static void sh7372_suspend_init(void) {}
Index: linux/drivers/input/touchscreen/st1232.c
=================================--- linux.orig/drivers/input/touchscreen/st1232.c
+++ linux/drivers/input/touchscreen/st1232.c
@@ -25,6 +25,7 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/types.h>
+#include <linux/pm_qos.h>
#define ST1232_TS_NAME "st1232-ts"
@@ -46,6 +47,8 @@ struct st1232_ts_data {
struct i2c_client *client;
struct input_dev *input_dev;
struct st1232_ts_finger finger[MAX_FINGERS];
+ struct dev_pm_qos_request low_latency_req;
+ bool pen_down;
};
static int st1232_ts_read_data(struct st1232_ts_data *ts)
@@ -118,8 +121,17 @@ static irqreturn_t st1232_ts_irq_handler
}
/* SYN_MT_REPORT only if no contact */
- if (!count)
+ if (!count) {
input_mt_sync(input_dev);
+ if (ts->pen_down) {
+ dev_pm_qos_remove_request(&ts->low_latency_req);
+ ts->pen_down = false;
+ }
+ } else if (!ts->pen_down) {
+ /* First contact, request 100 mcs latency. */
+ dev_pm_qos_add_ancestor_request(&ts->client->dev,
+ &ts->low_latency_req, 100);
+ }
/* SYN_REPORT */
input_sync(input_dev);
^ permalink raw reply
* [RFC][PATCH 3/4] PM / QoS: Introduce dev_pm_qos_add_ancestor_request()
From: Rafael J. Wysocki @ 2011-12-09 23:45 UTC (permalink / raw)
To: Linux-sh list; +Cc: Linux PM list, Guennadi Liakhovetski, Magnus Damm, LKML
In-Reply-To: <201112100042.45168.rjw@sisk.pl>
From: Rafael J. Wysocki <rjw@sisk.pl>
Some devices, like the I2C controller on SH7372, are not
necessary for providing power to their children or forwarding
wakeup signals (and generally interrupts) from them. They are
only needed by their children when there's some data to transfer,
so they may be suspended for the majority of time and resumed
on demand, when the children have data to send or receive. For this
purpose, however, their power.ignore_children flags have to be set,
or the PM core wouldn't allow them to be suspended while their
children were active.
Unfortunately, in some situations it may take too much time to
resume such devices so that they can assist their children in
transferring data. For example, if such a device belongs to a PM
domain which goes to the "power off" state when that device is
suspended, it may take too much time to restore power to the
domain in response to the request from one of the device's
children. In that case, if the parent's resume time is critical,
the domain should stay in the "power on" state, although it still may
be desirable to power manage the parent itself (e.g. by manipulating
its clock).
In general, device PM QoS may be used to address this problem.
Namely, if the device's children added PM QoS latency constraints
for it, they would be able to prevent it from being put into an
overly deep low-power state. However, in some cases the devices
needing to be serviced are not the immediate children of a
"children-ignoring" device, but its grandchildren or even less
direct descendants. In those cases, the entity wanting to add a
PM QoS request for a given device's ancestor that ignores its
children will have to find it in the first place, so introduce a new
helper function that may be used to achieve that. This function,
dev_pm_qos_add_ancestor_request(), will search for the first
ancestor of the given device whose power.ignore_children flag is
set and will add a device PM QoS latency request for that ancestor
on behalf of the caller. The request added this way may be removed
with the help of dev_pm_qos_remove_request() in the future, like
any other device PM QoS latency request.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
---
drivers/base/power/qos.c | 25 +++++++++++++++++++++++++
include/linux/pm_qos.h | 5 +++++
2 files changed, 30 insertions(+)
Index: linux/drivers/base/power/qos.c
=================================--- linux.orig/drivers/base/power/qos.c
+++ linux/drivers/base/power/qos.c
@@ -420,3 +420,28 @@ int dev_pm_qos_remove_global_notifier(st
return blocking_notifier_chain_unregister(&dev_pm_notifiers, notifier);
}
EXPORT_SYMBOL_GPL(dev_pm_qos_remove_global_notifier);
+
+/**
+ * dev_pm_qos_add_ancestor_request - Add PM QoS request for device's ancestor.
+ * @dev: Device whose ancestor to add the request for.
+ * @req: Pointer to the preallocated handle.
+ * @value: Constraint latency value.
+ */
+int dev_pm_qos_add_ancestor_request(struct device *dev,
+ struct dev_pm_qos_request *req, s32 value)
+{
+ struct device *ancestor = dev->parent;
+ int error = -ENODEV;
+
+ while (ancestor && !ancestor->power.ignore_children)
+ ancestor = ancestor->parent;
+
+ if (ancestor)
+ error = dev_pm_qos_add_request(ancestor, req, value);
+
+ if (error)
+ req->dev = NULL;
+
+ return error;
+}
+EXPORT_SYMBOL_GPL(dev_pm_qos_add_ancestor_request);
Index: linux/include/linux/pm_qos.h
=================================--- linux.orig/include/linux/pm_qos.h
+++ linux/include/linux/pm_qos.h
@@ -92,6 +92,8 @@ int dev_pm_qos_add_global_notifier(struc
int dev_pm_qos_remove_global_notifier(struct notifier_block *notifier);
void dev_pm_qos_constraints_init(struct device *dev);
void dev_pm_qos_constraints_destroy(struct device *dev);
+int dev_pm_qos_add_ancestor_request(struct device *dev,
+ struct dev_pm_qos_request *req, s32 value);
#else
static inline int pm_qos_update_target(struct pm_qos_constraints *c,
struct plist_node *node,
@@ -153,6 +155,9 @@ static inline void dev_pm_qos_constraint
{
dev->power.power_state = PMSG_INVALID;
}
+int dev_pm_qos_add_ancestor_request(struct device *dev,
+ struct dev_pm_qos_request *req, s32 value)
+ { return 0; }
#endif
#endif
^ permalink raw reply
* [RFC][PATCH 2/4] PM / shmobile: Remove the stay_on flag from SH7372's PM domains
From: Rafael J. Wysocki @ 2011-12-09 23:44 UTC (permalink / raw)
To: Linux-sh list; +Cc: Linux PM list, Guennadi Liakhovetski, Magnus Damm, LKML
In-Reply-To: <201112100042.45168.rjw@sisk.pl>
From: Rafael J. Wysocki <rjw@sisk.pl>
SH7372 uses two independent mechanisms for ensuring that power
domains will never be turned off: the stay_on flag and the "always
on" domain governor. Moreover, the "always on" governor is only taken
into accout by runtime PM code paths, while the stay_on flag affects
all attempts to turn the given domain off. Thus setting the stay_on
flag causes the "always on" governor to be unnecessary, which is
quite confusing.
However, the stay_on flag is currently only set for the A3SP PM
domain and only if console_suspend_enabled, so it may be replaced
by checking console_suspend_enabled directly in the A3SP's
.suspend() routine. [This requires domain .suspend() to return
a result, but that is a minor modification.]
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
---
arch/arm/mach-shmobile/include/mach/sh7372.h | 3 --
arch/arm/mach-shmobile/pm-sh7372.c | 36 ++++++++++++---------------
2 files changed, 18 insertions(+), 21 deletions(-)
Index: linux/arch/arm/mach-shmobile/include/mach/sh7372.h
=================================--- linux.orig/arch/arm/mach-shmobile/include/mach/sh7372.h
+++ linux/arch/arm/mach-shmobile/include/mach/sh7372.h
@@ -480,11 +480,10 @@ struct platform_device;
struct sh7372_pm_domain {
struct generic_pm_domain genpd;
struct dev_power_governor *gov;
- void (*suspend)(void);
+ int (*suspend)(void);
void (*resume)(void);
unsigned int bit_shift;
bool no_debug;
- bool stay_on;
};
static inline struct sh7372_pm_domain *to_sh7372_pd(struct generic_pm_domain *d)
Index: linux/arch/arm/mach-shmobile/pm-sh7372.c
=================================--- linux.orig/arch/arm/mach-shmobile/pm-sh7372.c
+++ linux/arch/arm/mach-shmobile/pm-sh7372.c
@@ -82,11 +82,12 @@ static int pd_power_down(struct generic_
struct sh7372_pm_domain *sh7372_pd = to_sh7372_pd(genpd);
unsigned int mask = 1 << sh7372_pd->bit_shift;
- if (sh7372_pd->suspend)
- sh7372_pd->suspend();
+ if (sh7372_pd->suspend) {
+ int ret = sh7372_pd->suspend();
- if (sh7372_pd->stay_on)
- return 0;
+ if (ret)
+ return ret;
+ }
if (__raw_readl(PSTR) & mask) {
unsigned int retry_count;
@@ -113,9 +114,6 @@ static int __pd_power_up(struct sh7372_p
unsigned int retry_count;
int ret = 0;
- if (sh7372_pd->stay_on)
- goto out;
-
if (__raw_readl(PSTR) & mask)
goto out;
@@ -148,10 +146,11 @@ static int pd_power_up(struct generic_pm
return __pd_power_up(to_sh7372_pd(genpd), true);
}
-static void sh7372_a4r_suspend(void)
+static int sh7372_a4r_suspend(void)
{
sh7372_intcs_suspend();
__raw_writel(0x300fffff, WUPRMSK); /* avoid wakeup */
+ return 0;
}
static bool pd_active_wakeup(struct device *dev)
@@ -243,7 +242,6 @@ struct sh7372_pm_domain sh7372_a4r = {
.gov = &pm_domain_always_on_gov,
.suspend = sh7372_a4r_suspend,
.resume = sh7372_intcs_resume,
- .stay_on = true,
};
struct sh7372_pm_domain sh7372_a3rv = {
@@ -256,21 +254,23 @@ struct sh7372_pm_domain sh7372_a3ri = {
.bit_shift = 8,
};
+static int sh7372_a3sp_suspend(void)
+{
+ /*
+ * Serial consoles make use of SCIF hardware located in A3SP,
+ * keep such power domain on if "no_console_suspend" is set.
+ */
+ return console_suspend_enabled ? -EBUSY : 0;
+}
+
struct sh7372_pm_domain sh7372_a3sp = {
.genpd.name = "A3SP",
.bit_shift = 11,
.gov = &pm_domain_always_on_gov,
.no_debug = true,
+ .suspend = sh7372_a3sp_suspend,
};
-static void sh7372_a3sp_init(void)
-{
- /* serial consoles make use of SCIF hardware located in A3SP,
- * keep such power domain on if "no_console_suspend" is set.
- */
- sh7372_a3sp.stay_on = !console_suspend_enabled;
-}
-
struct sh7372_pm_domain sh7372_a3sg = {
.genpd.name = "A3SG",
.bit_shift = 13,
@@ -514,8 +514,6 @@ void __init sh7372_pm_init(void)
/* do not convert A3SM, A3SP, A3SG, A4R power down into A4S */
__raw_writel(0, PDNSEL);
- sh7372_a3sp_init();
-
sh7372_suspend_init();
sh7372_cpuidle_init();
}
^ permalink raw reply
* [RFC][PATCH 1/4] PM / shmobile: Don't include SH7372's INTCS in syscore suspend/resume
From: Rafael J. Wysocki @ 2011-12-09 23:43 UTC (permalink / raw)
To: Linux-sh list; +Cc: Linux PM list, Guennadi Liakhovetski, Magnus Damm, LKML
In-Reply-To: <201112100042.45168.rjw@sisk.pl>
From: Rafael J. Wysocki <rjw@sisk.pl>
Since the SH7372's INTCS in included into syscore suspend/resume,
which causes the chip to be accessed when PM domains have been
turned off during system suspend, the A4R domain containing the
INTCS has to stay on during system sleep, which is suboptimal
from the power consumption point of view.
For this reason, add a new INTC flag, skip_syscore_suspend, to mark
the INTCS for intc_suspend() and intc_resume(), so that they don't
touch it. This allows the A4R domain to be turned off during
system suspend and the INTCS state is resrored during system
resume by the A4R's "power on" code.
Suggested-by: Magnus Damm <damm@opensource.se>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
---
arch/arm/mach-shmobile/intc-sh7372.c | 1 +
drivers/sh/intc/core.c | 8 ++++++++
drivers/sh/intc/internals.h | 1 +
include/linux/sh_intc.h | 1 +
4 files changed, 11 insertions(+)
Index: linux/include/linux/sh_intc.h
=================================--- linux.orig/include/linux/sh_intc.h
+++ linux/include/linux/sh_intc.h
@@ -95,6 +95,7 @@ struct intc_desc {
unsigned int num_resources;
intc_enum force_enable;
intc_enum force_disable;
+ bool skip_syscore_suspend;
struct intc_hw_desc hw;
};
Index: linux/arch/arm/mach-shmobile/intc-sh7372.c
=================================--- linux.orig/arch/arm/mach-shmobile/intc-sh7372.c
+++ linux/arch/arm/mach-shmobile/intc-sh7372.c
@@ -535,6 +535,7 @@ static struct resource intcs_resources[]
static struct intc_desc intcs_desc __initdata = {
.name = "sh7372-intcs",
.force_enable = ENABLED_INTCS,
+ .skip_syscore_suspend = true,
.resource = intcs_resources,
.num_resources = ARRAY_SIZE(intcs_resources),
.hw = INTC_HW_DESC(intcs_vectors, intcs_groups, intcs_mask_registers,
Index: linux/drivers/sh/intc/core.c
=================================--- linux.orig/drivers/sh/intc/core.c
+++ linux/drivers/sh/intc/core.c
@@ -354,6 +354,8 @@ int __init register_intc_controller(stru
if (desc->force_enable)
intc_enable_disable_enum(desc, d, desc->force_enable, 1);
+ d->skip_suspend = desc->skip_syscore_suspend;
+
nr_intc_controllers++;
return 0;
@@ -386,6 +388,9 @@ static int intc_suspend(void)
list_for_each_entry(d, &intc_list, list) {
int irq;
+ if (d->skip_suspend)
+ continue;
+
/* enable wakeup irqs belonging to this intc controller */
for_each_active_irq(irq) {
struct irq_data *data;
@@ -409,6 +414,9 @@ static void intc_resume(void)
list_for_each_entry(d, &intc_list, list) {
int irq;
+ if (d->skip_suspend)
+ continue;
+
for_each_active_irq(irq) {
struct irq_data *data;
struct irq_chip *chip;
Index: linux/drivers/sh/intc/internals.h
=================================--- linux.orig/drivers/sh/intc/internals.h
+++ linux/drivers/sh/intc/internals.h
@@ -67,6 +67,7 @@ struct intc_desc_int {
struct intc_window *window;
unsigned int nr_windows;
struct irq_chip chip;
+ bool skip_suspend;
};
^ permalink raw reply
* [RFC][PATCH 0/4] PM / shmobile: Use PM QoS latency constraints in touchscreen driver
From: Rafael J. Wysocki @ 2011-12-09 23:42 UTC (permalink / raw)
To: Linux-sh list; +Cc: Linux PM list, Guennadi Liakhovetski, Magnus Damm, LKML
Hi,
The following series of patches updates the SH7372 PM domain's so that
A4R doesn't need to be turned on during system sleep, drops the SH7372's
PM domains stay_on flag and makes the touchscreen add a PM QoS constraint
on its I2C controller to prevent the A4R domain containing it from being
turned off (due to power management) when the touchscreen is active.
Comments welcome!
Thanks,
Rafael
^ permalink raw reply
* Product Order
From: "SIMKINS LTD" @ 2011-12-09 13:04 UTC (permalink / raw)
To: simkinsltd
Hello,
I am Manager of SIMKINS LTD. USA, My company is interested in the
purchase of your products.
Kindly send me an email with details of:
*Minimum Order Quantity
*Your delivery time
*Payment terms
*And your products warranty
I await to hear from you urgently
Mr Stefan Al Simkins.
Purchasing Manager.
SIMKINS LTD
___________________________________
NOCC, http://nocc.sourceforge.net
^ permalink raw reply
* Re: [PATCH] sh: fix cpuidle on sh7724, possibly others
From: Guennadi Liakhovetski @ 2011-12-09 9:27 UTC (permalink / raw)
To: linux-sh
In-Reply-To: <Pine.LNX.4.64.1112061704300.10715@axis700.grange>
Hi Paul
On Fri, 9 Dec 2011, Paul Mundt wrote:
> On Wed, Dec 07, 2011 at 09:38:13AM +0100, Guennadi Liakhovetski wrote:
> > cpuidle has been broken on sh7724 and, possibly, other SuperH SoCs since
> >
> > commit f533c3d340536198a4889a42a68d6c0d79a504e7
> > Author: Paul Mundt <lethal@linux-sh.org>
> > Date: Fri Oct 16 17:20:58 2009 +0900
> >
> > sh: Idle loop chainsawing for SMP-based light sleep.
> >
> > i.e., since 2.6.33-rc1. The reason is a missing local_irq_enable() on the
> > path, actually entering a sleep mode. This patch adds the missing call.
> >
> > Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
> > ---
> >
> > This fixes one of the problem with cpuidle on sh. When applied (suitably
> > adjusted) directly after f533c3d340536198a4889a42a68d6c0d79a504e7, it does
> > fix the problem. However, since that commit cpuidle has been broken (at
> > least for my configuration) at least once more. This time bisection points
> > out at
> >
> > commit 03625e7107cde46e2851557ec06426799e6ae7f2
> > Author: Magnus Damm <damm@opensource.se>
> > Date: Fri Oct 30 04:24:32 2009 +0000
> >
> > sh: Use RSMEM for sleep code on sh7724
> >
> > Still investigating.
> >
> > diff --git a/arch/sh/kernel/cpu/shmobile/cpuidle.c b/arch/sh/kernel/cpu/shmobile/cpuidle.c
> > index 1cc257c..e58640a 100644
> > --- a/arch/sh/kernel/cpu/shmobile/cpuidle.c
> > +++ b/arch/sh/kernel/cpu/shmobile/cpuidle.c
> > @@ -48,6 +48,7 @@ static int cpuidle_sleep_enter(struct cpuidle_device *dev,
> > */
> > k = min_t(int, allowed_state, requested_state);
> >
> > + local_irq_enable();
> > before = ktime_get();
> > sh_mobile_call_standby(cpuidle_mode[k]);
> > after = ktime_get();
>
> Thanks for debugging this. This looks like a simple imbalance to me, but
> the changeset you cite doesn't do any SR toggling that would account for
> it, so that makes me suspect something else.
The commit, that I quoted, does add a local_irq_disable() in cpu_idle()
and a WARN_ON(irqs_disabled()) after the call to pm_idle(), so, it
expects, that inside pm_idle() interrupts are re-enabled. This is also
done in the two local implementations poll_idle() and default_idle(), but
not on the path, activated, once the cpuidle driver had been brought up.
After it has, it is only the cpuidle_idle_call() that gets executed, not
pm_idle(). And cpuidle_idle_call() ends up calling target_state->enter(),
which points at cpuidle_sleep_enter(), which locks up, if ktime_get() is
called with interrupts disabled. And it anyway has to return with
interrupts enebled. As for
> Looking at the code in question, perhaps this is the culprit?
>
> ---
>
> diff --git a/arch/sh/kernel/cpu/shmobile/pm.c b/arch/sh/kernel/cpu/shmobile/pm.c
> index a6f95ae..55b9024 100644
> --- a/arch/sh/kernel/cpu/shmobile/pm.c
> +++ b/arch/sh/kernel/cpu/shmobile/pm.c
> @@ -136,7 +136,7 @@ static int sh_pm_enter(suspend_state_t state)
> local_irq_disable();
> set_bl_bit();
> sh_mobile_call_standby(SUSP_MODE_STANDBY_SF);
> - local_irq_disable();
> + local_irq_enable();
> clear_bl_bit();
> return 0;
> }
I also was starring at this, failing to understand, but, I think, this is
a different bug altogether. I think, this .enter() method is for
suspending, not for cpuidle, or am I missing something?
Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/
^ permalink raw reply
* Re: [PATCH 04/04] sh: use ioread32/iowrite32 and mapped_reg for div6
From: Paul Mundt @ 2011-12-09 8:56 UTC (permalink / raw)
To: linux-sh
In-Reply-To: <20111208135922.18394.95163.sendpatchset@w520>
On Thu, Dec 08, 2011 at 09:49:46PM -0800, Kuninori Morimoto wrote:
> I tested these patch set on mackerel board with linus/master.
> it works well.
>
> But I'm afraid that this div6 patch didn't care
> paul/common/clkfwk which has below commit.
> it is still using clk->enable_reg.
>
> Of course I can modify it after merge ;)
>
That's ok, it's trivial to fix, I'll just tidy it up by hand when
merging. I'll add your Tested-by.
^ permalink raw reply
* Re: [PATCH] sh: fix cpuidle on sh7724, possibly others
From: Paul Mundt @ 2011-12-09 8:54 UTC (permalink / raw)
To: linux-sh
In-Reply-To: <Pine.LNX.4.64.1112061704300.10715@axis700.grange>
On Wed, Dec 07, 2011 at 09:38:13AM +0100, Guennadi Liakhovetski wrote:
> cpuidle has been broken on sh7724 and, possibly, other SuperH SoCs since
>
> commit f533c3d340536198a4889a42a68d6c0d79a504e7
> Author: Paul Mundt <lethal@linux-sh.org>
> Date: Fri Oct 16 17:20:58 2009 +0900
>
> sh: Idle loop chainsawing for SMP-based light sleep.
>
> i.e., since 2.6.33-rc1. The reason is a missing local_irq_enable() on the
> path, actually entering a sleep mode. This patch adds the missing call.
>
> Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
> ---
>
> This fixes one of the problem with cpuidle on sh. When applied (suitably
> adjusted) directly after f533c3d340536198a4889a42a68d6c0d79a504e7, it does
> fix the problem. However, since that commit cpuidle has been broken (at
> least for my configuration) at least once more. This time bisection points
> out at
>
> commit 03625e7107cde46e2851557ec06426799e6ae7f2
> Author: Magnus Damm <damm@opensource.se>
> Date: Fri Oct 30 04:24:32 2009 +0000
>
> sh: Use RSMEM for sleep code on sh7724
>
> Still investigating.
>
> diff --git a/arch/sh/kernel/cpu/shmobile/cpuidle.c b/arch/sh/kernel/cpu/shmobile/cpuidle.c
> index 1cc257c..e58640a 100644
> --- a/arch/sh/kernel/cpu/shmobile/cpuidle.c
> +++ b/arch/sh/kernel/cpu/shmobile/cpuidle.c
> @@ -48,6 +48,7 @@ static int cpuidle_sleep_enter(struct cpuidle_device *dev,
> */
> k = min_t(int, allowed_state, requested_state);
>
> + local_irq_enable();
> before = ktime_get();
> sh_mobile_call_standby(cpuidle_mode[k]);
> after = ktime_get();
Thanks for debugging this. This looks like a simple imbalance to me, but
the changeset you cite doesn't do any SR toggling that would account for
it, so that makes me suspect something else.
Looking at the code in question, perhaps this is the culprit?
---
diff --git a/arch/sh/kernel/cpu/shmobile/pm.c b/arch/sh/kernel/cpu/shmobile/pm.c
index a6f95ae..55b9024 100644
--- a/arch/sh/kernel/cpu/shmobile/pm.c
+++ b/arch/sh/kernel/cpu/shmobile/pm.c
@@ -136,7 +136,7 @@ static int sh_pm_enter(suspend_state_t state)
local_irq_disable();
set_bl_bit();
sh_mobile_call_standby(SUSP_MODE_STANDBY_SF);
- local_irq_disable();
+ local_irq_enable();
clear_bl_bit();
return 0;
}
^ permalink raw reply related
* Re: [PATCH 04/04] sh: use ioread32/iowrite32 and mapped_reg for div6
From: Kuninori Morimoto @ 2011-12-09 5:49 UTC (permalink / raw)
To: linux-sh
In-Reply-To: <20111208135922.18394.95163.sendpatchset@w520>
Hi Magnus, Paul
I tested these patch set on mackerel board with linus/master.
it works well.
But I'm afraid that this div6 patch didn't care
paul/common/clkfwk which has below commit.
it is still using clk->enable_reg.
Of course I can modify it after merge ;)
------------------------------------------------------
commit 56242a1fc595d158eddefbb4d6d76e82c2535f55
Author: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date: Mon Nov 21 21:33:18 2011 -0800
sh: clkfwk: setup clock parent from current register value
------------------------------------------------------
Tested-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
> From: Magnus Damm <damm@opensource.se>
>
> Convert the CPG DIV6 helper code to use the new mapped_reg
> together with ioread32() and iowrite32().
>
> Signed-off-by: Magnus Damm <damm@opensource.se>
> ---
>
> drivers/sh/clk/cpg.c | 18 +++++++++---------
> 1 file changed, 9 insertions(+), 9 deletions(-)
>
> --- 0011/drivers/sh/clk/cpg.c
> +++ work/drivers/sh/clk/cpg.c 2011-12-08 22:19:00.000000000 +0900
> @@ -72,7 +72,7 @@ static unsigned long sh_clk_div6_recalc(
> clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
> table, NULL);
>
> - idx = __raw_readl(clk->enable_reg) & 0x003f;
> + idx = ioread32(clk->mapped_reg) & 0x003f;
>
> return clk->freq_table[idx].frequency;
> }
> @@ -98,10 +98,10 @@ static int sh_clk_div6_set_parent(struct
> if (ret < 0)
> return ret;
>
> - value = __raw_readl(clk->enable_reg) &
> + value = ioread32(clk->mapped_reg) &
> ~(((1 << clk->src_width) - 1) << clk->src_shift);
>
> - __raw_writel(value | (i << clk->src_shift), clk->enable_reg);
> + iowrite32(value | (i << clk->src_shift), clk->mapped_reg);
>
> /* Rebuild the frequency table */
> clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
> @@ -119,10 +119,10 @@ static int sh_clk_div6_set_rate(struct c
> if (idx < 0)
> return idx;
>
> - value = __raw_readl(clk->enable_reg);
> + value = ioread32(clk->mapped_reg);
> value &= ~0x3f;
> value |= idx;
> - __raw_writel(value, clk->enable_reg);
> + iowrite32(value, clk->mapped_reg);
> return 0;
> }
>
> @@ -133,9 +133,9 @@ static int sh_clk_div6_enable(struct clk
>
> ret = sh_clk_div6_set_rate(clk, clk->rate);
> if (ret = 0) {
> - value = __raw_readl(clk->enable_reg);
> + value = ioread32(clk->mapped_reg);
> value &= ~0x100; /* clear stop bit to enable clock */
> - __raw_writel(value, clk->enable_reg);
> + iowrite32(value, clk->mapped_reg);
> }
> return ret;
> }
> @@ -144,10 +144,10 @@ static void sh_clk_div6_disable(struct c
> {
> unsigned long value;
>
> - value = __raw_readl(clk->enable_reg);
> + value = ioread32(clk->mapped_reg);
> value |= 0x100; /* stop clock */
> value |= 0x3f; /* VDIV bits must be non-zero, overwrite divider */
> - __raw_writel(value, clk->enable_reg);
> + iowrite32(value, clk->mapped_reg);
> }
>
> static struct clk_ops sh_clk_div6_clk_ops = {
Best regards
---
Kuninori Morimoto
^ permalink raw reply
* [PATCH] sh: pfc: ioremap() support
From: Magnus Damm @ 2011-12-09 3:14 UTC (permalink / raw)
To: linux-sh
From: Magnus Damm <damm@opensource.se>
Add support for non-entity mapped PFC registers through
the use of struct resource and ioremap()/iounmap().
The PFC main data structure gets updated with a pointer
to a struct resources array that point out all register
windows used by the PFC instance. The register definitions
are kept as physical addresses but the PFC code will do
transparent conversion into virtual addresses whenever
register windows are specified using with struct resource.
To introduce as little performance penalty as possible the
virtual address of each data register is cached in memory.
The virtual address of each configuration register is however
calculated during run time. This because the configuration
is considered slow path so focus is instead put on keeping
memory foot print as small as possible.
The PFC register access code is in this patch updated from
__raw_readN() / __raw_writeN() into ioreadN() / iowriteN().
This patch is needed to support the PFC block in r8a7779.
Signed-off-by: Magnus Damm <damm@opensource.se>
---
drivers/sh/pfc.c | 137 +++++++++++++++++++++++++++++++++++++++---------
include/linux/sh_pfc.h | 11 +++
2 files changed, 124 insertions(+), 24 deletions(-)
--- 0001/drivers/sh/pfc.c
+++ work/drivers/sh/pfc.c 2011-12-09 12:04:01.000000000 +0900
@@ -19,6 +19,75 @@
#include <linux/irq.h>
#include <linux/bitops.h>
#include <linux/gpio.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+
+static void pfc_iounmap(struct pinmux_info *pip)
+{
+ int k;
+
+ for (k = 0; k < pip->num_resources; k++)
+ if (pip->window[k].virt)
+ iounmap(pip->window[k].virt);
+
+ kfree(pip->window);
+ pip->window = NULL;
+}
+
+static int pfc_ioremap(struct pinmux_info *pip)
+{
+ struct resource *res;
+ int k;
+
+ if (!pip->num_resources)
+ return 0;
+
+ pip->window = kzalloc(pip->num_resources * sizeof(*pip->window),
+ GFP_NOWAIT);
+ if (!pip->window)
+ goto err1;
+
+ for (k = 0; k < pip->num_resources; k++) {
+ res = pip->resource + k;
+ WARN_ON(resource_type(res) != IORESOURCE_MEM);
+ pip->window[k].phys = res->start;
+ pip->window[k].size = resource_size(res);
+ pip->window[k].virt = ioremap_nocache(res->start,
+ resource_size(res));
+ if (!pip->window[k].virt)
+ goto err2;
+ }
+
+ return 0;
+
+err2:
+ pfc_iounmap(pip);
+err1:
+ return -1;
+}
+
+static void __iomem *pfc_phys_to_virt(struct pinmux_info *pip,
+ unsigned long address)
+{
+ struct pfc_window *window;
+ int k;
+
+ /* scan through physical windows and convert address */
+ for (k = 0; k < pip->num_resources; k++) {
+ window = pip->window + k;
+
+ if (address < window->phys)
+ continue;
+
+ if (address >= (window->phys + window->size))
+ continue;
+
+ return window->virt + (address - window->phys);
+ }
+
+ /* no windows defined, register must be 1:1 mapped virt:phys */
+ return (void __iomem *)address;
+}
static int enum_in_range(pinmux_enum_t enum_id, struct pinmux_range *r)
{
@@ -31,35 +100,35 @@ static int enum_in_range(pinmux_enum_t e
return 1;
}
-static unsigned long gpio_read_raw_reg(unsigned long reg,
+static unsigned long gpio_read_raw_reg(void __iomem *mapped_reg,
unsigned long reg_width)
{
switch (reg_width) {
case 8:
- return __raw_readb(reg);
+ return ioread8(mapped_reg);
case 16:
- return __raw_readw(reg);
+ return ioread16(mapped_reg);
case 32:
- return __raw_readl(reg);
+ return ioread32(mapped_reg);
}
BUG();
return 0;
}
-static void gpio_write_raw_reg(unsigned long reg,
+static void gpio_write_raw_reg(void __iomem *mapped_reg,
unsigned long reg_width,
unsigned long data)
{
switch (reg_width) {
case 8:
- __raw_writeb(data, reg);
+ iowrite8(data, mapped_reg);
return;
case 16:
- __raw_writew(data, reg);
+ iowrite16(data, mapped_reg);
return;
case 32:
- __raw_writel(data, reg);
+ iowrite32(data, mapped_reg);
return;
}
@@ -82,11 +151,12 @@ static void gpio_write_bit(struct pinmux
else
clear_bit(pos, &dr->reg_shadow);
- gpio_write_raw_reg(dr->reg, dr->reg_width, dr->reg_shadow);
+ gpio_write_raw_reg(dr->mapped_reg, dr->reg_width, dr->reg_shadow);
}
-static int gpio_read_reg(unsigned long reg, unsigned long reg_width,
- unsigned long field_width, unsigned long in_pos)
+static int gpio_read_reg(void __iomem *mapped_reg, unsigned long reg_width,
+ unsigned long field_width, unsigned long in_pos,
+ unsigned long reg)
{
unsigned long data, mask, pos;
@@ -98,13 +168,13 @@ static int gpio_read_reg(unsigned long r
"r_width = %ld, f_width = %ld\n",
reg, pos, reg_width, field_width);
- data = gpio_read_raw_reg(reg, reg_width);
+ data = gpio_read_raw_reg(mapped_reg, reg_width);
return (data >> pos) & mask;
}
-static void gpio_write_reg(unsigned long reg, unsigned long reg_width,
+static void gpio_write_reg(void __iomem *mapped_reg, unsigned long reg_width,
unsigned long field_width, unsigned long in_pos,
- unsigned long value)
+ unsigned long value, unsigned long reg)
{
unsigned long mask, pos;
@@ -120,13 +190,13 @@ static void gpio_write_reg(unsigned long
switch (reg_width) {
case 8:
- __raw_writeb((__raw_readb(reg) & mask) | value, reg);
+ iowrite8((ioread8(mapped_reg) & mask) | value, mapped_reg);
break;
case 16:
- __raw_writew((__raw_readw(reg) & mask) | value, reg);
+ iowrite16((ioread16(mapped_reg) & mask) | value, mapped_reg);
break;
case 32:
- __raw_writel((__raw_readl(reg) & mask) | value, reg);
+ iowrite32((ioread32(mapped_reg) & mask) | value, mapped_reg);
break;
}
}
@@ -147,6 +217,8 @@ static int setup_data_reg(struct pinmux_
if (!data_reg->reg_width)
break;
+ data_reg->mapped_reg = pfc_phys_to_virt(gpioc, data_reg->reg);
+
for (n = 0; n < data_reg->reg_width; n++) {
if (data_reg->enum_ids[n] = gpiop->enum_id) {
gpiop->flags &= ~PINMUX_FLAG_DREG;
@@ -179,7 +251,8 @@ static void setup_data_regs(struct pinmu
if (!drp->reg_width)
break;
- drp->reg_shadow = gpio_read_raw_reg(drp->reg, drp->reg_width);
+ drp->reg_shadow = gpio_read_raw_reg(drp->mapped_reg,
+ drp->reg_width);
k++;
}
}
@@ -266,12 +339,16 @@ static void write_config_reg(struct pinm
int index)
{
unsigned long ncomb, pos, value;
+ void __iomem *mapped_reg;
ncomb = 1 << crp->field_width;
pos = index / ncomb;
value = index % ncomb;
- gpio_write_reg(crp->reg, crp->reg_width, crp->field_width, pos, value);
+ mapped_reg = pfc_phys_to_virt(gpioc, crp->reg);
+
+ gpio_write_reg(mapped_reg, crp->reg_width, crp->field_width,
+ pos, value, crp->reg);
}
static int check_config_reg(struct pinmux_info *gpioc,
@@ -279,13 +356,16 @@ static int check_config_reg(struct pinmu
int index)
{
unsigned long ncomb, pos, value;
+ void __iomem *mapped_reg;
ncomb = 1 << crp->field_width;
pos = index / ncomb;
value = index % ncomb;
- if (gpio_read_reg(crp->reg, crp->reg_width,
- crp->field_width, pos) = value)
+ mapped_reg = pfc_phys_to_virt(gpioc, crp->reg);
+
+ if (gpio_read_reg(mapped_reg, crp->reg_width,
+ crp->field_width, pos, crp->reg) = value)
return 0;
return -1;
@@ -564,7 +644,7 @@ static int sh_gpio_get_value(struct pinm
if (!gpioc || get_data_reg(gpioc, gpio, &dr, &bit) != 0)
return -EINVAL;
- return gpio_read_reg(dr->reg, dr->reg_width, 1, bit);
+ return gpio_read_reg(dr->mapped_reg, dr->reg_width, 1, bit, dr->reg);
}
static int sh_gpio_get(struct gpio_chip *chip, unsigned offset)
@@ -606,10 +686,15 @@ static int sh_gpio_to_irq(struct gpio_ch
int register_pinmux(struct pinmux_info *pip)
{
struct gpio_chip *chip = &pip->chip;
+ int ret;
pr_info("%s handling gpio %d -> %d\n",
pip->name, pip->first_gpio, pip->last_gpio);
+ ret = pfc_ioremap(pip);
+ if (ret < 0)
+ return ret;
+
setup_data_regs(pip);
chip->request = sh_gpio_request;
@@ -627,12 +712,16 @@ int register_pinmux(struct pinmux_info *
chip->base = pip->first_gpio;
chip->ngpio = (pip->last_gpio - pip->first_gpio) + 1;
- return gpiochip_add(chip);
+ ret = gpiochip_add(chip);
+ if (ret < 0)
+ pfc_iounmap(pip);
+
+ return ret;
}
int unregister_pinmux(struct pinmux_info *pip)
{
pr_info("%s deregistering\n", pip->name);
-
+ pfc_iounmap(pip);
return gpiochip_remove(&pip->chip);
}
--- 0001/include/linux/sh_pfc.h
+++ work/include/linux/sh_pfc.h 2011-12-09 12:02:56.000000000 +0900
@@ -55,6 +55,7 @@ struct pinmux_cfg_reg {
struct pinmux_data_reg {
unsigned long reg, reg_width, reg_shadow;
pinmux_enum_t *enum_ids;
+ void __iomem *mapped_reg;
};
#define PINMUX_DATA_REG(name, r, r_width) \
@@ -75,6 +76,12 @@ struct pinmux_range {
pinmux_enum_t force;
};
+struct pfc_window {
+ phys_addr_t phys;
+ void __iomem *virt;
+ unsigned long size;
+};
+
struct pinmux_info {
char *name;
pinmux_enum_t reserved_id;
@@ -98,6 +105,10 @@ struct pinmux_info {
struct pinmux_irq *gpio_irq;
unsigned int gpio_irq_size;
+ struct resource *resource;
+ unsigned int num_resources;
+ struct pfc_window *window;
+
struct gpio_chip chip;
};
^ permalink raw reply
* [PATCH 04/04] sh: use ioread32/iowrite32 and mapped_reg for div6
From: Magnus Damm @ 2011-12-08 13:59 UTC (permalink / raw)
To: linux-sh
From: Magnus Damm <damm@opensource.se>
Convert the CPG DIV6 helper code to use the new mapped_reg
together with ioread32() and iowrite32().
Signed-off-by: Magnus Damm <damm@opensource.se>
---
drivers/sh/clk/cpg.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
--- 0011/drivers/sh/clk/cpg.c
+++ work/drivers/sh/clk/cpg.c 2011-12-08 22:19:00.000000000 +0900
@@ -72,7 +72,7 @@ static unsigned long sh_clk_div6_recalc(
clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
table, NULL);
- idx = __raw_readl(clk->enable_reg) & 0x003f;
+ idx = ioread32(clk->mapped_reg) & 0x003f;
return clk->freq_table[idx].frequency;
}
@@ -98,10 +98,10 @@ static int sh_clk_div6_set_parent(struct
if (ret < 0)
return ret;
- value = __raw_readl(clk->enable_reg) &
+ value = ioread32(clk->mapped_reg) &
~(((1 << clk->src_width) - 1) << clk->src_shift);
- __raw_writel(value | (i << clk->src_shift), clk->enable_reg);
+ iowrite32(value | (i << clk->src_shift), clk->mapped_reg);
/* Rebuild the frequency table */
clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
@@ -119,10 +119,10 @@ static int sh_clk_div6_set_rate(struct c
if (idx < 0)
return idx;
- value = __raw_readl(clk->enable_reg);
+ value = ioread32(clk->mapped_reg);
value &= ~0x3f;
value |= idx;
- __raw_writel(value, clk->enable_reg);
+ iowrite32(value, clk->mapped_reg);
return 0;
}
@@ -133,9 +133,9 @@ static int sh_clk_div6_enable(struct clk
ret = sh_clk_div6_set_rate(clk, clk->rate);
if (ret = 0) {
- value = __raw_readl(clk->enable_reg);
+ value = ioread32(clk->mapped_reg);
value &= ~0x100; /* clear stop bit to enable clock */
- __raw_writel(value, clk->enable_reg);
+ iowrite32(value, clk->mapped_reg);
}
return ret;
}
@@ -144,10 +144,10 @@ static void sh_clk_div6_disable(struct c
{
unsigned long value;
- value = __raw_readl(clk->enable_reg);
+ value = ioread32(clk->mapped_reg);
value |= 0x100; /* stop clock */
value |= 0x3f; /* VDIV bits must be non-zero, overwrite divider */
- __raw_writel(value, clk->enable_reg);
+ iowrite32(value, clk->mapped_reg);
}
static struct clk_ops sh_clk_div6_clk_ops = {
^ permalink raw reply
* [PATCH 03/04] sh: use ioread32/iowrite32 and mapped_reg for div4
From: Magnus Damm @ 2011-12-08 13:59 UTC (permalink / raw)
To: linux-sh
From: Magnus Damm <damm@opensource.se>
Convert the CPG DIV4 helper code to use the new mapped_reg
together with ioread32() and iowrite32().
Signed-off-by: Magnus Damm <damm@opensource.se>
---
drivers/sh/clk/cpg.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
--- 0010/drivers/sh/clk/cpg.c
+++ work/drivers/sh/clk/cpg.c 2011-12-08 22:20:29.000000000 +0900
@@ -217,7 +217,7 @@ static unsigned long sh_clk_div4_recalc(
clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
table, &clk->arch_flags);
- idx = (__raw_readl(clk->enable_reg) >> clk->enable_bit) & 0x000f;
+ idx = (ioread32(clk->mapped_reg) >> clk->enable_bit) & 0x000f;
return clk->freq_table[idx].frequency;
}
@@ -235,15 +235,15 @@ static int sh_clk_div4_set_parent(struct
*/
if (parent->flags & CLK_ENABLE_ON_INIT)
- value = __raw_readl(clk->enable_reg) & ~(1 << 7);
+ value = ioread32(clk->mapped_reg) & ~(1 << 7);
else
- value = __raw_readl(clk->enable_reg) | (1 << 7);
+ value = ioread32(clk->mapped_reg) | (1 << 7);
ret = clk_reparent(clk, parent);
if (ret < 0)
return ret;
- __raw_writel(value, clk->enable_reg);
+ iowrite32(value, clk->mapped_reg);
/* Rebiuld the frequency table */
clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
@@ -260,10 +260,10 @@ static int sh_clk_div4_set_rate(struct c
if (idx < 0)
return idx;
- value = __raw_readl(clk->enable_reg);
+ value = ioread32(clk->mapped_reg);
value &= ~(0xf << clk->enable_bit);
value |= (idx << clk->enable_bit);
- __raw_writel(value, clk->enable_reg);
+ iowrite32(value, clk->mapped_reg);
if (d4t->kick)
d4t->kick(clk);
@@ -273,13 +273,13 @@ static int sh_clk_div4_set_rate(struct c
static int sh_clk_div4_enable(struct clk *clk)
{
- __raw_writel(__raw_readl(clk->enable_reg) & ~(1 << 8), clk->enable_reg);
+ iowrite32(ioread32(clk->mapped_reg) & ~(1 << 8), clk->mapped_reg);
return 0;
}
static void sh_clk_div4_disable(struct clk *clk)
{
- __raw_writel(__raw_readl(clk->enable_reg) | (1 << 8), clk->enable_reg);
+ iowrite32(ioread32(clk->mapped_reg) | (1 << 8), clk->mapped_reg);
}
static struct clk_ops sh_clk_div4_clk_ops = {
^ permalink raw reply
* [PATCH 02/04] sh: use ioread32/iowrite32 and mapped_reg for mstp32
From: Magnus Damm @ 2011-12-08 13:59 UTC (permalink / raw)
To: linux-sh
From: Magnus Damm <damm@opensource.se>
Convert the CPG MSTP32 helper code to use the new mapped_reg
together with ioread32() and iowrite32().
Signed-off-by: Magnus Damm <damm@opensource.se>
---
drivers/sh/clk/cpg.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
--- 0001/drivers/sh/clk/cpg.c
+++ work/drivers/sh/clk/cpg.c 2011-12-08 13:31:24.000000000 +0900
@@ -15,15 +15,15 @@
static int sh_clk_mstp32_enable(struct clk *clk)
{
- __raw_writel(__raw_readl(clk->enable_reg) & ~(1 << clk->enable_bit),
- clk->enable_reg);
+ iowrite32(ioread32(clk->mapped_reg) & ~(1 << clk->enable_bit),
+ clk->mapped_reg);
return 0;
}
static void sh_clk_mstp32_disable(struct clk *clk)
{
- __raw_writel(__raw_readl(clk->enable_reg) | (1 << clk->enable_bit),
- clk->enable_reg);
+ iowrite32(ioread32(clk->mapped_reg) | (1 << clk->enable_bit),
+ clk->mapped_reg);
}
static struct clk_ops sh_clk_mstp32_clk_ops = {
^ permalink raw reply
* [PATCH 01/04] sh: extend clock struct with mapped_reg member
From: Magnus Damm @ 2011-12-08 13:58 UTC (permalink / raw)
To: linux-sh
From: Magnus Damm <damm@opensource.se>
Add a "mapped_reg" member to struct clk and use that
to keep the ioremapped register based on enable_reg.
Signed-off-by: Magnus Damm <damm@opensource.se>
---
drivers/sh/clk/core.c | 9 +++++++--
include/linux/sh_clk.h | 1 +
2 files changed, 8 insertions(+), 2 deletions(-)
--- 0001/drivers/sh/clk/core.c
+++ work/drivers/sh/clk/core.c 2011-12-08 22:26:25.000000000 +0900
@@ -355,7 +355,7 @@ static int clk_establish_mapping(struct
*/
if (!clk->parent) {
clk->mapping = &dummy_mapping;
- return 0;
+ goto out;
}
/*
@@ -384,6 +384,9 @@ static int clk_establish_mapping(struct
}
clk->mapping = mapping;
+ out:
+ clk->mapped_reg = clk->mapping->base;
+ clk->mapped_reg += (phys_addr_t)clk->enable_reg - clk->mapping->phys;
return 0;
}
@@ -402,10 +405,12 @@ static void clk_teardown_mapping(struct
/* Nothing to do */
if (mapping = &dummy_mapping)
- return;
+ goto out;
kref_put(&mapping->ref, clk_destroy_mapping);
clk->mapping = NULL;
+ out:
+ clk->mapped_reg = NULL;
}
int clk_register(struct clk *clk)
--- 0001/include/linux/sh_clk.h
+++ work/include/linux/sh_clk.h 2011-12-08 13:30:41.000000000 +0900
@@ -49,6 +49,7 @@ struct clk {
void __iomem *enable_reg;
unsigned int enable_bit;
+ void __iomem *mapped_reg;
unsigned long arch_flags;
void *priv;
^ permalink raw reply
* [PATCH 00/04] sh: clock / CPG ioremap() update
From: Magnus Damm @ 2011-12-08 13:58 UTC (permalink / raw)
To: linux-sh
sh: clock / CPG ioremap() update
[PATCH 01/04] sh: extend clock struct with mapped_reg member
[PATCH 02/04] sh: use ioread32/iowrite32 and mapped_reg for mstp32
[PATCH 03/04] sh: use ioread32/iowrite32 and mapped_reg for div4
[PATCH 04/04] sh: use ioread32/iowrite32 and mapped_reg for div6
These patches extend the drivers/sh/clk/ code to use ioremap().
Needed for the soc / board support code for r8a7779. Other SoCs
should just keep on working as before.
Signed-off-by: Magnus Damm <damm@opensource.se>
---
drivers/sh/clk/core.c | 9 +++++++--
drivers/sh/clk/cpg.c | 42 +++++++++++++++++++++---------------------
include/linux/sh_clk.h | 1 +
3 files changed, 29 insertions(+), 23 deletions(-)
^ permalink raw reply
* Re: [PATCH] sh: fix cpuidle on sh7724, possibly others
From: Guennadi Liakhovetski @ 2011-12-07 11:12 UTC (permalink / raw)
To: linux-sh
In-Reply-To: <Pine.LNX.4.64.1112061704300.10715@axis700.grange>
On Wed, 7 Dec 2011, Guennadi Liakhovetski wrote:
> cpuidle has been broken on sh7724 and, possibly, other SuperH SoCs since
>
> commit f533c3d340536198a4889a42a68d6c0d79a504e7
> Author: Paul Mundt <lethal@linux-sh.org>
> Date: Fri Oct 16 17:20:58 2009 +0900
>
> sh: Idle loop chainsawing for SMP-based light sleep.
>
> i.e., since 2.6.33-rc1. The reason is a missing local_irq_enable() on the
> path, actually entering a sleep mode. This patch adds the missing call.
>
> Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
> ---
>
> This fixes one of the problem with cpuidle on sh. When applied (suitably
> adjusted) directly after f533c3d340536198a4889a42a68d6c0d79a504e7, it does
> fix the problem. However, since that commit cpuidle has been broken (at
> least for my configuration) at least once more. This time bisection points
> out at
Apparently, a hick up during bisect: this
> commit 03625e7107cde46e2851557ec06426799e6ae7f2
> Author: Magnus Damm <damm@opensource.se>
> Date: Fri Oct 30 04:24:32 2009 +0000
>
> sh: Use RSMEM for sleep code on sh7724
>
> Still investigating.
is not the offending commit, this is the one:
commit 323ef8dba67fb7b9c709457bd0374d88cfb8f25f
Author: Magnus Damm <damm@opensource.se>
Date: Fri Oct 30 04:24:07 2009 +0000
sh: Rework SuperH Mobile sleep mode code
Thanks
Guennadi
>
> diff --git a/arch/sh/kernel/cpu/shmobile/cpuidle.c b/arch/sh/kernel/cpu/shmobile/cpuidle.c
> index 1cc257c..e58640a 100644
> --- a/arch/sh/kernel/cpu/shmobile/cpuidle.c
> +++ b/arch/sh/kernel/cpu/shmobile/cpuidle.c
> @@ -48,6 +48,7 @@ static int cpuidle_sleep_enter(struct cpuidle_device *dev,
> */
> k = min_t(int, allowed_state, requested_state);
>
> + local_irq_enable();
> before = ktime_get();
> sh_mobile_call_standby(cpuidle_mode[k]);
> after = ktime_get();
>
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/
^ permalink raw reply
* [PATCH] sh: fix cpuidle on sh7724, possibly others
From: Guennadi Liakhovetski @ 2011-12-07 8:38 UTC (permalink / raw)
To: linux-sh
cpuidle has been broken on sh7724 and, possibly, other SuperH SoCs since
commit f533c3d340536198a4889a42a68d6c0d79a504e7
Author: Paul Mundt <lethal@linux-sh.org>
Date: Fri Oct 16 17:20:58 2009 +0900
sh: Idle loop chainsawing for SMP-based light sleep.
i.e., since 2.6.33-rc1. The reason is a missing local_irq_enable() on the
path, actually entering a sleep mode. This patch adds the missing call.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
This fixes one of the problem with cpuidle on sh. When applied (suitably
adjusted) directly after f533c3d340536198a4889a42a68d6c0d79a504e7, it does
fix the problem. However, since that commit cpuidle has been broken (at
least for my configuration) at least once more. This time bisection points
out at
commit 03625e7107cde46e2851557ec06426799e6ae7f2
Author: Magnus Damm <damm@opensource.se>
Date: Fri Oct 30 04:24:32 2009 +0000
sh: Use RSMEM for sleep code on sh7724
Still investigating.
diff --git a/arch/sh/kernel/cpu/shmobile/cpuidle.c b/arch/sh/kernel/cpu/shmobile/cpuidle.c
index 1cc257c..e58640a 100644
--- a/arch/sh/kernel/cpu/shmobile/cpuidle.c
+++ b/arch/sh/kernel/cpu/shmobile/cpuidle.c
@@ -48,6 +48,7 @@ static int cpuidle_sleep_enter(struct cpuidle_device *dev,
*/
k = min_t(int, allowed_state, requested_state);
+ local_irq_enable();
before = ktime_get();
sh_mobile_call_standby(cpuidle_mode[k]);
after = ktime_get();
^ permalink raw reply related
* [PATCH 07/07] ARM: mach-shmobile: Marzen GPIO LED test code
From: Magnus Damm @ 2011-12-06 16:52 UTC (permalink / raw)
To: linux-sh
From: Magnus Damm <damm@opensource.se>
Add prototype code for LED2, LED3 and LED4 on the Marzen board.
Should most likely use the LED framework, but is OK as-is for
now when testing the r8a7779 GPIO/PFC code.
Not-yet-signed-off-by: Magnus Damm <damm@opensource.se>
---
arch/arm/mach-shmobile/board-marzen.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
--- 0010/arch/arm/mach-shmobile/board-marzen.c
+++ work/arch/arm/mach-shmobile/board-marzen.c 2011-12-07 00:25:39.000000000 +0900
@@ -25,6 +25,7 @@
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/io.h>
+#include <linux/gpio.h>
#include <linux/dma-mapping.h>
#include <mach/hardware.h>
#include <mach/r8a7779.h>
@@ -94,6 +95,18 @@ static void __init marzen_init(void)
{
r8a7779_pinmux_init();
+ gpio_request(GPIO_GP_4_29, NULL); /* LED2 */
+ gpio_direction_output(GPIO_GP_4_29, 0);
+ gpio_export(GPIO_GP_4_29, false);
+
+ gpio_request(GPIO_GP_4_30, NULL); /* LED3 */
+ gpio_direction_output(GPIO_GP_4_30, 0);
+ gpio_export(GPIO_GP_4_30, false);
+
+ gpio_request(GPIO_GP_4_31, NULL); /* LED4 */
+ gpio_direction_output(GPIO_GP_4_31, 0);
+ gpio_export(GPIO_GP_4_31, false);
+
r8a7779_add_standard_devices();
platform_add_devices(marzen_devices, ARRAY_SIZE(marzen_devices));
}
^ permalink raw reply
* [PATCH 06/07] ARM: mach-shmobile: r8a7779 PFC ioremap() workaround
From: Magnus Damm @ 2011-12-06 16:52 UTC (permalink / raw)
To: linux-sh
From: Magnus Damm <damm@opensource.se>
Since the common pfc code does not support ioremap(),
hack the code to make use of the serial debug console
mapping. Magically makes the r8a7779 PFC code work.
Will be dropped when the pfc code knows how to ioremap().
Never-signed-off-by: Magnus Damm <damm@opensource.se>
---
arch/arm/mach-shmobile/pfc-r8a7779.c | 42 +++++++++++++++++-----------------
1 file changed, 21 insertions(+), 21 deletions(-)
--- 0010/arch/arm/mach-shmobile/pfc-r8a7779.c
+++ work/arch/arm/mach-shmobile/pfc-r8a7779.c 2011-12-07 00:21:46.000000000 +0900
@@ -163,7 +163,7 @@ static struct pinmux_gpio pinmux_gpios[]
};
static struct pinmux_cfg_reg pinmux_config_regs[] = {
- { PINMUX_CFG_REG("GPSR0", 0xffc00004, 32, 1) {
+ { PINMUX_CFG_REG("GPSR0", 0xfdc00004, 32, 1) {
GP_0_31_FN, FN_IP3_31_29,
GP_0_30_FN, FN_IP3_26_24,
GP_0_29_FN, FN_IP3_22_21,
@@ -197,7 +197,7 @@ static struct pinmux_cfg_reg pinmux_conf
GP_0_1_FN, FN_AVS2,
GP_0_0_FN, FN_AVS1 }
},
- { PINMUX_CFG_REG("GPSR1", 0xffc00008, 32, 1) {
+ { PINMUX_CFG_REG("GPSR1", 0xfdc00008, 32, 1) {
GP_1_31_FN, FN_IP5_23_21,
GP_1_30_FN, FN_IP5_20_17,
GP_1_29_FN, FN_IP5_16_15,
@@ -231,7 +231,7 @@ static struct pinmux_cfg_reg pinmux_conf
GP_1_1_FN, FN_IP4_4_2,
GP_1_0_FN, FN_IP4_1_0 }
},
- { PINMUX_CFG_REG("GPSR2", 0xffc0000c, 32, 1) {
+ { PINMUX_CFG_REG("GPSR2", 0xfdc0000c, 32, 1) {
GP_2_31_FN, FN_IP10_28_26,
GP_2_30_FN, FN_IP10_25_24,
GP_2_29_FN, FN_IP10_23_21,
@@ -265,7 +265,7 @@ static struct pinmux_cfg_reg pinmux_conf
GP_2_1_FN, FN_IP8_20,
GP_2_0_FN, FN_IP5_27_24 }
},
- { PINMUX_CFG_REG("GPSR3", 0xffc00010, 32, 1) {
+ { PINMUX_CFG_REG("GPSR3", 0xfdc00010, 32, 1) {
GP_3_31_FN, FN_IP6_3_2,
GP_3_30_FN, FN_IP6_1_0,
GP_3_29_FN, FN_IP5_30_29,
@@ -299,7 +299,7 @@ static struct pinmux_cfg_reg pinmux_conf
GP_3_1_FN, FN_IP11_2_0,
GP_3_0_FN, FN_IP10_31_29 }
},
- { PINMUX_CFG_REG("GPSR4", 0xffc00014, 32, 1) {
+ { PINMUX_CFG_REG("GPSR4", 0xfdc00014, 32, 1) {
GP_4_31_FN, FN_IP8_19,
GP_4_30_FN, FN_IP8_18,
GP_4_29_FN, FN_IP8_17_16,
@@ -333,7 +333,7 @@ static struct pinmux_cfg_reg pinmux_conf
GP_4_1_FN, FN_IP6_7_6,
GP_4_0_FN, FN_IP6_5_4 }
},
- { PINMUX_CFG_REG("GPSR5", 0xffc00018, 32, 1) {
+ { PINMUX_CFG_REG("GPSR5", 0xfdc00018, 32, 1) {
GP_5_31_FN, FN_IP3_5,
GP_5_30_FN, FN_IP3_4,
GP_5_29_FN, FN_IP3_3,
@@ -367,7 +367,7 @@ static struct pinmux_cfg_reg pinmux_conf
GP_5_1_FN, FN_A2,
GP_5_0_FN, FN_A1 }
},
- { PINMUX_CFG_REG("GPSR6", 0xffc0001c, 32, 1) {
+ { PINMUX_CFG_REG("GPSR6", 0xfdc0001c, 32, 1) {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
@@ -384,13 +384,13 @@ static struct pinmux_cfg_reg pinmux_conf
GP_6_1_FN, FN_IP3_7,
GP_6_0_FN, FN_IP3_6 }
},
- { PINMUX_CFG_REG("INOUTSEL0", 0xffc40004, 32, 1) { GP_INOUTSEL(0) } },
- { PINMUX_CFG_REG("INOUTSEL1", 0xffc41004, 32, 1) { GP_INOUTSEL(1) } },
- { PINMUX_CFG_REG("INOUTSEL2", 0xffc42004, 32, 1) { GP_INOUTSEL(2) } },
- { PINMUX_CFG_REG("INOUTSEL3", 0xffc43004, 32, 1) { GP_INOUTSEL(3) } },
- { PINMUX_CFG_REG("INOUTSEL4", 0xffc44004, 32, 1) { GP_INOUTSEL(4) } },
- { PINMUX_CFG_REG("INOUTSEL5", 0xffc45004, 32, 1) { GP_INOUTSEL(5) } },
- { PINMUX_CFG_REG("INOUTSEL6", 0xffc46004, 32, 1) {
+ { PINMUX_CFG_REG("INOUTSEL0", 0xfdc40004, 32, 1) { GP_INOUTSEL(0) } },
+ { PINMUX_CFG_REG("INOUTSEL1", 0xfdc41004, 32, 1) { GP_INOUTSEL(1) } },
+ { PINMUX_CFG_REG("INOUTSEL2", 0xfdc42004, 32, 1) { GP_INOUTSEL(2) } },
+ { PINMUX_CFG_REG("INOUTSEL3", 0xfdc43004, 32, 1) { GP_INOUTSEL(3) } },
+ { PINMUX_CFG_REG("INOUTSEL4", 0xfdc44004, 32, 1) { GP_INOUTSEL(4) } },
+ { PINMUX_CFG_REG("INOUTSEL5", 0xfdc45004, 32, 1) { GP_INOUTSEL(5) } },
+ { PINMUX_CFG_REG("INOUTSEL6", 0xfdc46004, 32, 1) {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
@@ -411,13 +411,13 @@ static struct pinmux_cfg_reg pinmux_conf
};
static struct pinmux_data_reg pinmux_data_regs[] = {
- { PINMUX_DATA_REG("INDT0", 0xffc40008, 32) { GP_INDT(0) } },
- { PINMUX_DATA_REG("INDT1", 0xffc41008, 32) { GP_INDT(1) } },
- { PINMUX_DATA_REG("INDT2", 0xffc42008, 32) { GP_INDT(2) } },
- { PINMUX_DATA_REG("INDT3", 0xffc43008, 32) { GP_INDT(3) } },
- { PINMUX_DATA_REG("INDT4", 0xffc44008, 32) { GP_INDT(4) } },
- { PINMUX_DATA_REG("INDT5", 0xffc45008, 32) { GP_INDT(5) } },
- { PINMUX_DATA_REG("INDT6", 0xffc46008, 32) {
+ { PINMUX_DATA_REG("INDT0", 0xfdc40008, 32) { GP_INDT(0) } },
+ { PINMUX_DATA_REG("INDT1", 0xfdc41008, 32) { GP_INDT(1) } },
+ { PINMUX_DATA_REG("INDT2", 0xfdc42008, 32) { GP_INDT(2) } },
+ { PINMUX_DATA_REG("INDT3", 0xfdc43008, 32) { GP_INDT(3) } },
+ { PINMUX_DATA_REG("INDT4", 0xfdc44008, 32) { GP_INDT(4) } },
+ { PINMUX_DATA_REG("INDT5", 0xfdc45008, 32) { GP_INDT(5) } },
+ { PINMUX_DATA_REG("INDT6", 0xfdc46008, 32) {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, GP_6_8_DATA,
GP_6_7_DATA, GP_6_6_DATA, GP_6_5_DATA, GP_6_4_DATA,
^ permalink raw reply
* [PATCH 05/07] ARM: mach-shmobile: r8a7779 PFC GPIO-only prototype
From: Magnus Damm @ 2011-12-06 16:52 UTC (permalink / raw)
To: linux-sh
From: Magnus Damm <damm@opensource.se>
Initial r8a7779 PFC prototype support.
Only regular GPIOs are supported at this time. GPIO_FN are not
supported because they require variable bit width support in be
the shared pfc code.
This prototype requires a filthy mapping hack for the PFC/GPIO
base addresses applied on top of this patch to workt. The pfc code
needs to be extended to make use of ioremap() to support this SoC.
Not-yet-signed-off-by: Magnus Damm <damm@opensource.se>
---
arch/arm/mach-shmobile/Kconfig | 2
arch/arm/mach-shmobile/Makefile | 1
arch/arm/mach-shmobile/board-marzen.c | 2
arch/arm/mach-shmobile/include/mach/common.h | 1
arch/arm/mach-shmobile/include/mach/r8a7779.h | 63 +++
arch/arm/mach-shmobile/pfc-r8a7779.c | 452 +++++++++++++++++++++++++
6 files changed, 520 insertions(+), 1 deletion(-)
--- 0010/arch/arm/mach-shmobile/Kconfig
+++ work/arch/arm/mach-shmobile/Kconfig 2011-12-07 00:38:57.000000000 +0900
@@ -33,6 +33,7 @@ config ARCH_R8A7779
select CPU_V7
select SH_CLK_CPG
select ARM_GIC
+ select ARCH_WANT_OPTIONAL_GPIOLIB
comment "SH-Mobile Board Type"
@@ -84,6 +85,7 @@ config MACH_KOTA2
config MACH_MARZEN
bool "MARZEN board"
depends on ARCH_R8A7779
+ select ARCH_REQUIRE_GPIOLIB
comment "SH-Mobile System Configuration"
--- 0010/arch/arm/mach-shmobile/Makefile
+++ work/arch/arm/mach-shmobile/Makefile 2011-12-07 00:38:57.000000000 +0900
@@ -24,6 +24,7 @@ pfc-$(CONFIG_ARCH_SH7367) += pfc-sh7367.
pfc-$(CONFIG_ARCH_SH7377) += pfc-sh7377.o
pfc-$(CONFIG_ARCH_SH7372) += pfc-sh7372.o
pfc-$(CONFIG_ARCH_SH73A0) += pfc-sh73a0.o
+pfc-$(CONFIG_ARCH_R8A7779) += pfc-r8a7779.o
# IRQ objects
obj-$(CONFIG_ARCH_SH7367) += entry-intc.o
--- 0011/arch/arm/mach-shmobile/board-marzen.c
+++ work/arch/arm/mach-shmobile/board-marzen.c 2011-12-07 00:38:57.000000000 +0900
@@ -92,6 +92,8 @@ static void __init marzen_init_early(voi
static void __init marzen_init(void)
{
+ r8a7779_pinmux_init();
+
r8a7779_add_standard_devices();
platform_add_devices(marzen_devices, ARRAY_SIZE(marzen_devices));
}
--- 0010/arch/arm/mach-shmobile/include/mach/common.h
+++ work/arch/arm/mach-shmobile/include/mach/common.h 2011-12-07 00:38:57.000000000 +0900
@@ -57,5 +57,6 @@ extern void r8a7779_init_irq(void);
extern void r8a7779_add_early_devices(void);
extern void r8a7779_add_standard_devices(void);
extern void r8a7779_clock_init(void);
+extern void r8a7779_pinmux_init(void);
#endif /* __ARCH_MACH_COMMON_H */
--- 0010/arch/arm/mach-shmobile/include/mach/r8a7779.h
+++ work/arch/arm/mach-shmobile/include/mach/r8a7779.h 2011-12-07 00:38:57.000000000 +0900
@@ -1,6 +1,67 @@
#ifndef __ASM_R8A7779_H__
#define __ASM_R8A7779_H__
-/* Nothing at this point */
+/* Pin Function Controller:
+ * GPIO_GP_x_x - GPIO mapped to real I/O pin on CPU
+ */
+enum {
+ GPIO_GP_0_0, GPIO_GP_0_1, GPIO_GP_0_2, GPIO_GP_0_3,
+ GPIO_GP_0_4, GPIO_GP_0_5, GPIO_GP_0_6, GPIO_GP_0_7,
+ GPIO_GP_0_8, GPIO_GP_0_9, GPIO_GP_0_10, GPIO_GP_0_11,
+ GPIO_GP_0_12, GPIO_GP_0_13, GPIO_GP_0_14, GPIO_GP_0_15,
+ GPIO_GP_0_16, GPIO_GP_0_17, GPIO_GP_0_18, GPIO_GP_0_19,
+ GPIO_GP_0_20, GPIO_GP_0_21, GPIO_GP_0_22, GPIO_GP_0_23,
+ GPIO_GP_0_24, GPIO_GP_0_25, GPIO_GP_0_26, GPIO_GP_0_27,
+ GPIO_GP_0_28, GPIO_GP_0_29, GPIO_GP_0_30, GPIO_GP_0_31,
+
+ GPIO_GP_1_0, GPIO_GP_1_1, GPIO_GP_1_2, GPIO_GP_1_3,
+ GPIO_GP_1_4, GPIO_GP_1_5, GPIO_GP_1_6, GPIO_GP_1_7,
+ GPIO_GP_1_8, GPIO_GP_1_9, GPIO_GP_1_10, GPIO_GP_1_11,
+ GPIO_GP_1_12, GPIO_GP_1_13, GPIO_GP_1_14, GPIO_GP_1_15,
+ GPIO_GP_1_16, GPIO_GP_1_17, GPIO_GP_1_18, GPIO_GP_1_19,
+ GPIO_GP_1_20, GPIO_GP_1_21, GPIO_GP_1_22, GPIO_GP_1_23,
+ GPIO_GP_1_24, GPIO_GP_1_25, GPIO_GP_1_26, GPIO_GP_1_27,
+ GPIO_GP_1_28, GPIO_GP_1_29, GPIO_GP_1_30, GPIO_GP_1_31,
+
+ GPIO_GP_2_0, GPIO_GP_2_1, GPIO_GP_2_2, GPIO_GP_2_3,
+ GPIO_GP_2_4, GPIO_GP_2_5, GPIO_GP_2_6, GPIO_GP_2_7,
+ GPIO_GP_2_8, GPIO_GP_2_9, GPIO_GP_2_10, GPIO_GP_2_11,
+ GPIO_GP_2_12, GPIO_GP_2_13, GPIO_GP_2_14, GPIO_GP_2_15,
+ GPIO_GP_2_16, GPIO_GP_2_17, GPIO_GP_2_18, GPIO_GP_2_19,
+ GPIO_GP_2_20, GPIO_GP_2_21, GPIO_GP_2_22, GPIO_GP_2_23,
+ GPIO_GP_2_24, GPIO_GP_2_25, GPIO_GP_2_26, GPIO_GP_2_27,
+ GPIO_GP_2_28, GPIO_GP_2_29, GPIO_GP_2_30, GPIO_GP_2_31,
+
+ GPIO_GP_3_0, GPIO_GP_3_1, GPIO_GP_3_2, GPIO_GP_3_3,
+ GPIO_GP_3_4, GPIO_GP_3_5, GPIO_GP_3_6, GPIO_GP_3_7,
+ GPIO_GP_3_8, GPIO_GP_3_9, GPIO_GP_3_10, GPIO_GP_3_11,
+ GPIO_GP_3_12, GPIO_GP_3_13, GPIO_GP_3_14, GPIO_GP_3_15,
+ GPIO_GP_3_16, GPIO_GP_3_17, GPIO_GP_3_18, GPIO_GP_3_19,
+ GPIO_GP_3_20, GPIO_GP_3_21, GPIO_GP_3_22, GPIO_GP_3_23,
+ GPIO_GP_3_24, GPIO_GP_3_25, GPIO_GP_3_26, GPIO_GP_3_27,
+ GPIO_GP_3_28, GPIO_GP_3_29, GPIO_GP_3_30, GPIO_GP_3_31,
+
+ GPIO_GP_4_0, GPIO_GP_4_1, GPIO_GP_4_2, GPIO_GP_4_3,
+ GPIO_GP_4_4, GPIO_GP_4_5, GPIO_GP_4_6, GPIO_GP_4_7,
+ GPIO_GP_4_8, GPIO_GP_4_9, GPIO_GP_4_10, GPIO_GP_4_11,
+ GPIO_GP_4_12, GPIO_GP_4_13, GPIO_GP_4_14, GPIO_GP_4_15,
+ GPIO_GP_4_16, GPIO_GP_4_17, GPIO_GP_4_18, GPIO_GP_4_19,
+ GPIO_GP_4_20, GPIO_GP_4_21, GPIO_GP_4_22, GPIO_GP_4_23,
+ GPIO_GP_4_24, GPIO_GP_4_25, GPIO_GP_4_26, GPIO_GP_4_27,
+ GPIO_GP_4_28, GPIO_GP_4_29, GPIO_GP_4_30, GPIO_GP_4_31,
+
+ GPIO_GP_5_0, GPIO_GP_5_1, GPIO_GP_5_2, GPIO_GP_5_3,
+ GPIO_GP_5_4, GPIO_GP_5_5, GPIO_GP_5_6, GPIO_GP_5_7,
+ GPIO_GP_5_8, GPIO_GP_5_9, GPIO_GP_5_10, GPIO_GP_5_11,
+ GPIO_GP_5_12, GPIO_GP_5_13, GPIO_GP_5_14, GPIO_GP_5_15,
+ GPIO_GP_5_16, GPIO_GP_5_17, GPIO_GP_5_18, GPIO_GP_5_19,
+ GPIO_GP_5_20, GPIO_GP_5_21, GPIO_GP_5_22, GPIO_GP_5_23,
+ GPIO_GP_5_24, GPIO_GP_5_25, GPIO_GP_5_26, GPIO_GP_5_27,
+ GPIO_GP_5_28, GPIO_GP_5_29, GPIO_GP_5_30, GPIO_GP_5_31,
+
+ GPIO_GP_6_0, GPIO_GP_6_1, GPIO_GP_6_2, GPIO_GP_6_3,
+ GPIO_GP_6_4, GPIO_GP_6_5, GPIO_GP_6_6, GPIO_GP_6_7,
+ GPIO_GP_6_8,
+};
#endif /* __ASM_R8A7779_H__ */
--- /dev/null
+++ work/arch/arm/mach-shmobile/pfc-r8a7779.c 2011-12-07 00:42:35.000000000 +0900
@@ -0,0 +1,452 @@
+/*
+ * r8a7779 processor support - PFC hardware block
+ *
+ * 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/init.h>
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <mach/r8a7779.h>
+
+#define CPU_32_PORT(fn, pfx, sfx) \
+ PORT_10(fn, pfx, sfx), PORT_10(fn, pfx##1, sfx), \
+ PORT_10(fn, pfx##2, sfx), PORT_1(fn, pfx##30, sfx), \
+ PORT_1(fn, pfx##31, sfx)
+
+#define CPU_32_PORT6(fn, pfx, sfx) \
+ PORT_1(fn, pfx##0, sfx), PORT_1(fn, pfx##1, sfx), \
+ PORT_1(fn, pfx##2, sfx), PORT_1(fn, pfx##3, sfx), \
+ PORT_1(fn, pfx##4, sfx), PORT_1(fn, pfx##5, sfx), \
+ PORT_1(fn, pfx##6, sfx), PORT_1(fn, pfx##7, sfx), \
+ PORT_1(fn, pfx##8, sfx)
+
+#define CPU_ALL_PORT(fn, pfx, sfx) \
+ CPU_32_PORT(fn, pfx##_0_, sfx), \
+ CPU_32_PORT(fn, pfx##_1_, sfx), \
+ CPU_32_PORT(fn, pfx##_2_, sfx), \
+ CPU_32_PORT(fn, pfx##_3_, sfx), \
+ CPU_32_PORT(fn, pfx##_4_, sfx), \
+ CPU_32_PORT(fn, pfx##_5_, sfx), \
+ CPU_32_PORT6(fn, pfx##_6_, sfx)
+
+#define _GP_GPIO(pfx, sfx) PINMUX_GPIO(GPIO_GP##pfx, GP##pfx##_DATA)
+#define _GP_DATA(pfx, sfx) PINMUX_DATA(GP##pfx##_DATA, GP##pfx##_FN, \
+ GP##pfx##_IN, GP##pfx##_OUT)
+
+#define _GP_INOUTSEL(pfx, sfx) GP##pfx##_IN, GP##pfx##_OUT
+#define _GP_INDT(pfx, sfx) GP##pfx##_DATA
+
+#define GP_ALL(str) CPU_ALL_PORT(_PORT_ALL, GP, str)
+#define PINMUX_GPIO_GP_ALL() CPU_ALL_PORT(_GP_GPIO, , unused)
+#define PINMUX_DATA_GP_ALL() CPU_ALL_PORT(_GP_DATA, , unused)
+
+
+#define PORT_10_REV(fn, pfx, sfx) \
+ PORT_1(fn, pfx##9, sfx), PORT_1(fn, pfx##8, sfx), \
+ PORT_1(fn, pfx##7, sfx), PORT_1(fn, pfx##6, sfx), \
+ PORT_1(fn, pfx##5, sfx), PORT_1(fn, pfx##4, sfx), \
+ PORT_1(fn, pfx##3, sfx), PORT_1(fn, pfx##2, sfx), \
+ PORT_1(fn, pfx##1, sfx), PORT_1(fn, pfx##0, sfx)
+
+#define CPU_32_PORT_REV(fn, pfx, sfx) \
+ PORT_1(fn, pfx##31, sfx), PORT_1(fn, pfx##30, sfx), \
+ PORT_10_REV(fn, pfx##2, sfx), PORT_10_REV(fn, pfx##1, sfx), \
+ PORT_10_REV(fn, pfx, sfx)
+
+#define GP_INOUTSEL(bank) CPU_32_PORT_REV(_GP_INOUTSEL, _##bank##_, unused)
+#define GP_INDT(bank) CPU_32_PORT_REV(_GP_INDT, _##bank##_, unused)
+
+enum {
+ PINMUX_RESERVED = 0,
+
+ PINMUX_DATA_BEGIN,
+ GP_ALL(DATA), /* GP_0_0_DATA -> GP_6_8_DATA */
+ PINMUX_DATA_END,
+
+ PINMUX_INPUT_BEGIN,
+ GP_ALL(IN), /* GP_0_0_IN -> GP_6_8_IN */
+ PINMUX_INPUT_END,
+
+ PINMUX_OUTPUT_BEGIN,
+ GP_ALL(OUT), /* GP_0_0_OUT -> GP_6_8_OUT */
+ PINMUX_OUTPUT_END,
+
+ PINMUX_FUNCTION_BEGIN,
+ GP_ALL(FN), /* GP_0_0_FN -> GP_6_8_FN */
+
+ /* GPSR0 */
+ FN_AVS1, FN_AVS2, FN_IP0_7_6, FN_A17,
+ FN_A18, FN_A19, FN_IP0_9_8, FN_IP0_11_10,
+ FN_IP0_13_12, FN_IP0_15_14, FN_IP0_18_16, FN_IP0_22_19,
+ FN_IP0_24_23, FN_IP0_25, FN_IP0_27_26, FN_IP1_1_0,
+ FN_IP1_3_2, FN_IP1_6_4, FN_IP1_10_7, FN_IP1_14_11,
+ FN_IP1_18_15, FN_IP0_5_3, FN_IP0_30_28, FN_IP2_18_16,
+ FN_IP2_21_19, FN_IP2_30_28, FN_IP2_2_0, FN_IP3_11_9,
+ FN_IP3_14_12, FN_IP3_22_21, FN_IP3_26_24, FN_IP3_31_29,
+
+ /* GPSR1 */
+ FN_IP4_1_0, FN_IP4_4_2, FN_IP4_7_5, FN_IP4_10_8,
+ FN_IP4_11, FN_IP4_12, FN_IP4_13, FN_IP4_14,
+ FN_IP4_15, FN_IP4_16, FN_IP4_19_17, FN_IP4_22_20,
+ FN_IP4_23, FN_IP4_24, FN_IP4_25, FN_IP4_26,
+ FN_IP4_27, FN_IP4_28, FN_IP4_31_29, FN_IP5_2_0,
+ FN_IP5_3, FN_IP5_4, FN_IP5_5, FN_IP5_6,
+ FN_IP5_7, FN_IP5_8, FN_IP5_10_9, FN_IP5_12_11,
+ FN_IP5_14_13, FN_IP5_16_15, FN_IP5_20_17, FN_IP5_23_21,
+
+ /* GPSR2 */
+ FN_IP5_27_24, FN_IP8_20, FN_IP8_22_21, FN_IP8_24_23,
+ FN_IP8_27_25, FN_IP8_30_28, FN_IP9_1_0, FN_IP9_3_2,
+ FN_IP9_4, FN_IP9_5, FN_IP9_6, FN_IP9_7,
+ FN_IP9_9_8, FN_IP9_11_10, FN_IP9_13_12, FN_IP9_15_14,
+ FN_IP9_18_16, FN_IP9_21_19, FN_IP9_23_22, FN_IP9_25_24,
+ FN_IP9_27_26, FN_IP9_29_28, FN_IP10_2_0, FN_IP10_5_3,
+ FN_IP10_8_6, FN_IP10_11_9, FN_IP10_14_12, FN_IP10_17_15,
+ FN_IP10_20_18, FN_IP10_23_21, FN_IP10_25_24, FN_IP10_28_26,
+
+ /* GPSR3 */
+ FN_IP10_31_29, FN_IP11_2_0, FN_IP11_5_3, FN_IP11_8_6,
+ FN_IP11_11_9, FN_IP11_14_12, FN_IP11_17_15, FN_IP11_20_18,
+ FN_IP11_23_21, FN_IP11_26_24, FN_IP11_29_27, FN_IP12_2_0,
+ FN_IP12_5_3, FN_IP12_8_6, FN_IP12_11_9, FN_IP12_14_12,
+ FN_IP12_17_15, FN_IP7_16_15, FN_IP7_18_17, FN_IP7_28_27,
+ FN_IP7_30_29, FN_IP7_20_19, FN_IP7_22_21, FN_IP7_24_23,
+ FN_IP7_26_25, FN_IP1_20_19, FN_IP1_22_21, FN_IP1_24_23,
+ FN_IP5_28, FN_IP5_30_29, FN_IP6_1_0, FN_IP6_3_2,
+
+ /* GPSR4 */
+ FN_IP6_5_4, FN_IP6_7_6, FN_IP6_8, FN_IP6_11_9,
+ FN_IP6_14_12, FN_IP6_17_15, FN_IP6_19_18, FN_IP6_22_20,
+ FN_IP6_24_23, FN_IP6_26_25, FN_IP6_30_29, FN_IP7_1_0,
+ FN_IP7_3_2, FN_IP7_6_4, FN_IP7_9_7, FN_IP7_12_10,
+ FN_IP7_14_13, FN_IP2_7_4, FN_IP2_11_8, FN_IP2_15_12,
+ FN_IP1_28_25, FN_IP2_3_0, FN_IP8_3_0, FN_IP8_7_4,
+ FN_IP8_11_8, FN_IP8_15_12, FN_PENC0, FN_PENC1,
+ FN_IP0_2_0, FN_IP8_17_16, FN_IP8_18, FN_IP8_19,
+
+ /* GPSR5 */
+ FN_A1, FN_A2, FN_A3, FN_A4,
+ FN_A5, FN_A6, FN_A7, FN_A8,
+ FN_A9, FN_A10, FN_A11, FN_A12,
+ FN_A13, FN_A14, FN_A15, FN_A16,
+ FN_RD, FN_WE0, FN_WE1, FN_EX_WAIT0,
+ FN_IP3_23, FN_IP3_27, FN_IP3_28, FN_IP2_22,
+ FN_IP2_23, FN_IP2_24, FN_IP2_25, FN_IP2_26,
+ FN_IP2_27, FN_IP3_3, FN_IP3_4, FN_IP3_5,
+
+ /* GPSR6 */
+ FN_IP3_6, FN_IP3_7, FN_IP3_8, FN_IP3_15,
+ FN_IP3_16, FN_IP3_17, FN_IP3_18, FN_IP3_19,
+ FN_IP3_20,
+ PINMUX_FUNCTION_END,
+};
+
+static pinmux_enum_t pinmux_data[] = {
+ PINMUX_DATA_GP_ALL(), /* PINMUX_DATA(GP_M_N_DATA, GP_M_N_FN...), */
+};
+
+static struct pinmux_gpio pinmux_gpios[] = {
+ PINMUX_GPIO_GP_ALL(),
+};
+
+static struct pinmux_cfg_reg pinmux_config_regs[] = {
+ { PINMUX_CFG_REG("GPSR0", 0xffc00004, 32, 1) {
+ GP_0_31_FN, FN_IP3_31_29,
+ GP_0_30_FN, FN_IP3_26_24,
+ GP_0_29_FN, FN_IP3_22_21,
+ GP_0_28_FN, FN_IP3_14_12,
+ GP_0_27_FN, FN_IP3_11_9,
+ GP_0_26_FN, FN_IP2_2_0,
+ GP_0_25_FN, FN_IP2_30_28,
+ GP_0_24_FN, FN_IP2_21_19,
+ GP_0_23_FN, FN_IP2_18_16,
+ GP_0_22_FN, FN_IP0_30_28,
+ GP_0_21_FN, FN_IP0_5_3,
+ GP_0_20_FN, FN_IP1_18_15,
+ GP_0_19_FN, FN_IP1_14_11,
+ GP_0_18_FN, FN_IP1_10_7,
+ GP_0_17_FN, FN_IP1_6_4,
+ GP_0_16_FN, FN_IP1_3_2,
+ GP_0_15_FN, FN_IP1_1_0,
+ GP_0_14_FN, FN_IP0_27_26,
+ GP_0_13_FN, FN_IP0_25,
+ GP_0_12_FN, FN_IP0_24_23,
+ GP_0_11_FN, FN_IP0_22_19,
+ GP_0_10_FN, FN_IP0_18_16,
+ GP_0_9_FN, FN_IP0_15_14,
+ GP_0_8_FN, FN_IP0_13_12,
+ GP_0_7_FN, FN_IP0_11_10,
+ GP_0_6_FN, FN_IP0_9_8,
+ GP_0_5_FN, FN_A19,
+ GP_0_4_FN, FN_A18,
+ GP_0_3_FN, FN_A17,
+ GP_0_2_FN, FN_IP0_7_6,
+ GP_0_1_FN, FN_AVS2,
+ GP_0_0_FN, FN_AVS1 }
+ },
+ { PINMUX_CFG_REG("GPSR1", 0xffc00008, 32, 1) {
+ GP_1_31_FN, FN_IP5_23_21,
+ GP_1_30_FN, FN_IP5_20_17,
+ GP_1_29_FN, FN_IP5_16_15,
+ GP_1_28_FN, FN_IP5_14_13,
+ GP_1_27_FN, FN_IP5_12_11,
+ GP_1_26_FN, FN_IP5_10_9,
+ GP_1_25_FN, FN_IP5_8,
+ GP_1_24_FN, FN_IP5_7,
+ GP_1_23_FN, FN_IP5_6,
+ GP_1_22_FN, FN_IP5_5,
+ GP_1_21_FN, FN_IP5_4,
+ GP_1_20_FN, FN_IP5_3,
+ GP_1_19_FN, FN_IP5_2_0,
+ GP_1_18_FN, FN_IP4_31_29,
+ GP_1_17_FN, FN_IP4_28,
+ GP_1_16_FN, FN_IP4_27,
+ GP_1_15_FN, FN_IP4_26,
+ GP_1_14_FN, FN_IP4_25,
+ GP_1_13_FN, FN_IP4_24,
+ GP_1_12_FN, FN_IP4_23,
+ GP_1_11_FN, FN_IP4_22_20,
+ GP_1_10_FN, FN_IP4_19_17,
+ GP_1_9_FN, FN_IP4_16,
+ GP_1_8_FN, FN_IP4_15,
+ GP_1_7_FN, FN_IP4_14,
+ GP_1_6_FN, FN_IP4_13,
+ GP_1_5_FN, FN_IP4_12,
+ GP_1_4_FN, FN_IP4_11,
+ GP_1_3_FN, FN_IP4_10_8,
+ GP_1_2_FN, FN_IP4_7_5,
+ GP_1_1_FN, FN_IP4_4_2,
+ GP_1_0_FN, FN_IP4_1_0 }
+ },
+ { PINMUX_CFG_REG("GPSR2", 0xffc0000c, 32, 1) {
+ GP_2_31_FN, FN_IP10_28_26,
+ GP_2_30_FN, FN_IP10_25_24,
+ GP_2_29_FN, FN_IP10_23_21,
+ GP_2_28_FN, FN_IP10_20_18,
+ GP_2_27_FN, FN_IP10_17_15,
+ GP_2_26_FN, FN_IP10_14_12,
+ GP_2_25_FN, FN_IP10_11_9,
+ GP_2_24_FN, FN_IP10_8_6,
+ GP_2_23_FN, FN_IP10_5_3,
+ GP_2_22_FN, FN_IP10_2_0,
+ GP_2_21_FN, FN_IP9_29_28,
+ GP_2_20_FN, FN_IP9_27_26,
+ GP_2_19_FN, FN_IP9_25_24,
+ GP_2_18_FN, FN_IP9_23_22,
+ GP_2_17_FN, FN_IP9_21_19,
+ GP_2_16_FN, FN_IP9_18_16,
+ GP_2_15_FN, FN_IP9_15_14,
+ GP_2_14_FN, FN_IP9_13_12,
+ GP_2_13_FN, FN_IP9_11_10,
+ GP_2_12_FN, FN_IP9_9_8,
+ GP_2_11_FN, FN_IP9_7,
+ GP_2_10_FN, FN_IP9_6,
+ GP_2_9_FN, FN_IP9_5,
+ GP_2_8_FN, FN_IP9_4,
+ GP_2_7_FN, FN_IP9_3_2,
+ GP_2_6_FN, FN_IP9_1_0,
+ GP_2_5_FN, FN_IP8_30_28,
+ GP_2_4_FN, FN_IP8_27_25,
+ GP_2_3_FN, FN_IP8_24_23,
+ GP_2_2_FN, FN_IP8_22_21,
+ GP_2_1_FN, FN_IP8_20,
+ GP_2_0_FN, FN_IP5_27_24 }
+ },
+ { PINMUX_CFG_REG("GPSR3", 0xffc00010, 32, 1) {
+ GP_3_31_FN, FN_IP6_3_2,
+ GP_3_30_FN, FN_IP6_1_0,
+ GP_3_29_FN, FN_IP5_30_29,
+ GP_3_28_FN, FN_IP5_28,
+ GP_3_27_FN, FN_IP1_24_23,
+ GP_3_26_FN, FN_IP1_22_21,
+ GP_3_25_FN, FN_IP1_20_19,
+ GP_3_24_FN, FN_IP7_26_25,
+ GP_3_23_FN, FN_IP7_24_23,
+ GP_3_22_FN, FN_IP7_22_21,
+ GP_3_21_FN, FN_IP7_20_19,
+ GP_3_20_FN, FN_IP7_30_29,
+ GP_3_19_FN, FN_IP7_28_27,
+ GP_3_18_FN, FN_IP7_18_17,
+ GP_3_17_FN, FN_IP7_16_15,
+ GP_3_16_FN, FN_IP12_17_15,
+ GP_3_15_FN, FN_IP12_14_12,
+ GP_3_14_FN, FN_IP12_11_9,
+ GP_3_13_FN, FN_IP12_8_6,
+ GP_3_12_FN, FN_IP12_5_3,
+ GP_3_11_FN, FN_IP12_2_0,
+ GP_3_10_FN, FN_IP11_29_27,
+ GP_3_9_FN, FN_IP11_26_24,
+ GP_3_8_FN, FN_IP11_23_21,
+ GP_3_7_FN, FN_IP11_20_18,
+ GP_3_6_FN, FN_IP11_17_15,
+ GP_3_5_FN, FN_IP11_14_12,
+ GP_3_4_FN, FN_IP11_11_9,
+ GP_3_3_FN, FN_IP11_8_6,
+ GP_3_2_FN, FN_IP11_5_3,
+ GP_3_1_FN, FN_IP11_2_0,
+ GP_3_0_FN, FN_IP10_31_29 }
+ },
+ { PINMUX_CFG_REG("GPSR4", 0xffc00014, 32, 1) {
+ GP_4_31_FN, FN_IP8_19,
+ GP_4_30_FN, FN_IP8_18,
+ GP_4_29_FN, FN_IP8_17_16,
+ GP_4_28_FN, FN_IP0_2_0,
+ GP_4_27_FN, FN_PENC1,
+ GP_4_26_FN, FN_PENC0,
+ GP_4_25_FN, FN_IP8_15_12,
+ GP_4_24_FN, FN_IP8_11_8,
+ GP_4_23_FN, FN_IP8_7_4,
+ GP_4_22_FN, FN_IP8_3_0,
+ GP_4_21_FN, FN_IP2_3_0,
+ GP_4_20_FN, FN_IP1_28_25,
+ GP_4_19_FN, FN_IP2_15_12,
+ GP_4_18_FN, FN_IP2_11_8,
+ GP_4_17_FN, FN_IP2_7_4,
+ GP_4_16_FN, FN_IP7_14_13,
+ GP_4_15_FN, FN_IP7_12_10,
+ GP_4_14_FN, FN_IP7_9_7,
+ GP_4_13_FN, FN_IP7_6_4,
+ GP_4_12_FN, FN_IP7_3_2,
+ GP_4_11_FN, FN_IP7_1_0,
+ GP_4_10_FN, FN_IP6_30_29,
+ GP_4_9_FN, FN_IP6_26_25,
+ GP_4_8_FN, FN_IP6_24_23,
+ GP_4_7_FN, FN_IP6_22_20,
+ GP_4_6_FN, FN_IP6_19_18,
+ GP_4_5_FN, FN_IP6_17_15,
+ GP_4_4_FN, FN_IP6_14_12,
+ GP_4_3_FN, FN_IP6_11_9,
+ GP_4_2_FN, FN_IP6_8,
+ GP_4_1_FN, FN_IP6_7_6,
+ GP_4_0_FN, FN_IP6_5_4 }
+ },
+ { PINMUX_CFG_REG("GPSR5", 0xffc00018, 32, 1) {
+ GP_5_31_FN, FN_IP3_5,
+ GP_5_30_FN, FN_IP3_4,
+ GP_5_29_FN, FN_IP3_3,
+ GP_5_28_FN, FN_IP2_27,
+ GP_5_27_FN, FN_IP2_26,
+ GP_5_26_FN, FN_IP2_25,
+ GP_5_25_FN, FN_IP2_24,
+ GP_5_24_FN, FN_IP2_23,
+ GP_5_23_FN, FN_IP2_22,
+ GP_5_22_FN, FN_IP3_28,
+ GP_5_21_FN, FN_IP3_27,
+ GP_5_20_FN, FN_IP3_23,
+ GP_5_19_FN, FN_EX_WAIT0,
+ GP_5_18_FN, FN_WE1,
+ GP_5_17_FN, FN_WE0,
+ GP_5_16_FN, FN_RD,
+ GP_5_15_FN, FN_A16,
+ GP_5_14_FN, FN_A15,
+ GP_5_13_FN, FN_A14,
+ GP_5_12_FN, FN_A13,
+ GP_5_11_FN, FN_A12,
+ GP_5_10_FN, FN_A11,
+ GP_5_9_FN, FN_A10,
+ GP_5_8_FN, FN_A9,
+ GP_5_7_FN, FN_A8,
+ GP_5_6_FN, FN_A7,
+ GP_5_5_FN, FN_A6,
+ GP_5_4_FN, FN_A5,
+ GP_5_3_FN, FN_A4,
+ GP_5_2_FN, FN_A3,
+ GP_5_1_FN, FN_A2,
+ GP_5_0_FN, FN_A1 }
+ },
+ { PINMUX_CFG_REG("GPSR6", 0xffc0001c, 32, 1) {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ GP_6_8_FN, FN_IP3_20,
+ GP_6_7_FN, FN_IP3_19,
+ GP_6_6_FN, FN_IP3_18,
+ GP_6_5_FN, FN_IP3_17,
+ GP_6_4_FN, FN_IP3_16,
+ GP_6_3_FN, FN_IP3_15,
+ GP_6_2_FN, FN_IP3_8,
+ GP_6_1_FN, FN_IP3_7,
+ GP_6_0_FN, FN_IP3_6 }
+ },
+ { PINMUX_CFG_REG("INOUTSEL0", 0xffc40004, 32, 1) { GP_INOUTSEL(0) } },
+ { PINMUX_CFG_REG("INOUTSEL1", 0xffc41004, 32, 1) { GP_INOUTSEL(1) } },
+ { PINMUX_CFG_REG("INOUTSEL2", 0xffc42004, 32, 1) { GP_INOUTSEL(2) } },
+ { PINMUX_CFG_REG("INOUTSEL3", 0xffc43004, 32, 1) { GP_INOUTSEL(3) } },
+ { PINMUX_CFG_REG("INOUTSEL4", 0xffc44004, 32, 1) { GP_INOUTSEL(4) } },
+ { PINMUX_CFG_REG("INOUTSEL5", 0xffc45004, 32, 1) { GP_INOUTSEL(5) } },
+ { PINMUX_CFG_REG("INOUTSEL6", 0xffc46004, 32, 1) {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ GP_6_8_IN, GP_6_8_OUT,
+ GP_6_7_IN, GP_6_7_OUT,
+ GP_6_6_IN, GP_6_6_OUT,
+ GP_6_5_IN, GP_6_5_OUT,
+ GP_6_4_IN, GP_6_4_OUT,
+ GP_6_3_IN, GP_6_3_OUT,
+ GP_6_2_IN, GP_6_2_OUT,
+ GP_6_1_IN, GP_6_1_OUT,
+ GP_6_0_IN, GP_6_0_OUT, }
+ },
+ { },
+};
+
+static struct pinmux_data_reg pinmux_data_regs[] = {
+ { PINMUX_DATA_REG("INDT0", 0xffc40008, 32) { GP_INDT(0) } },
+ { PINMUX_DATA_REG("INDT1", 0xffc41008, 32) { GP_INDT(1) } },
+ { PINMUX_DATA_REG("INDT2", 0xffc42008, 32) { GP_INDT(2) } },
+ { PINMUX_DATA_REG("INDT3", 0xffc43008, 32) { GP_INDT(3) } },
+ { PINMUX_DATA_REG("INDT4", 0xffc44008, 32) { GP_INDT(4) } },
+ { PINMUX_DATA_REG("INDT5", 0xffc45008, 32) { GP_INDT(5) } },
+ { PINMUX_DATA_REG("INDT6", 0xffc46008, 32) {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, GP_6_8_DATA,
+ GP_6_7_DATA, GP_6_6_DATA, GP_6_5_DATA, GP_6_4_DATA,
+ GP_6_3_DATA, GP_6_2_DATA, GP_6_1_DATA, GP_6_0_DATA }
+ },
+ { },
+};
+
+static struct pinmux_info r8a7779_pinmux_info = {
+ .name = "r8a7779_pfc",
+ .reserved_id = PINMUX_RESERVED,
+ .data = { PINMUX_DATA_BEGIN, PINMUX_DATA_END },
+ .input = { PINMUX_INPUT_BEGIN, PINMUX_INPUT_END },
+ .output = { PINMUX_OUTPUT_BEGIN, PINMUX_OUTPUT_END },
+ .function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
+
+ .first_gpio = GPIO_GP_0_0,
+ .last_gpio = GPIO_GP_6_8,
+
+ .gpios = pinmux_gpios,
+ .cfg_regs = pinmux_config_regs,
+ .data_regs = pinmux_data_regs,
+
+ .gpio_data = pinmux_data,
+ .gpio_data_size = ARRAY_SIZE(pinmux_data),
+};
+
+void r8a7779_pinmux_init(void)
+{
+ register_pinmux(&r8a7779_pinmux_info);
+}
^ permalink raw reply
* [PATCH 04/07] ARM: mach-shmobile: Marzen early console hack
From: Magnus Damm @ 2011-12-06 16:52 UTC (permalink / raw)
To: linux-sh
From: Magnus Damm <damm@opensource.se>
Hack the Marzen board code to get early debug print outs.
Use with "earlyprint=sh-sci.2,11520" on the kernel command line.
Good to have when tracking down early timer or PFC issues.
Needed by the r8a7779 PFC map hack further in the series.
Never-signed-off-by: Magnus Damm <damm@opensource.se>
---
arch/arm/mach-shmobile/board-marzen.c | 8 ++++++++
arch/arm/mach-shmobile/setup-r8a7779.c | 4 ++--
2 files changed, 10 insertions(+), 2 deletions(-)
--- 0008/arch/arm/mach-shmobile/board-marzen.c
+++ work/arch/arm/mach-shmobile/board-marzen.c 2011-12-06 23:57:23.000000000 +0900
@@ -54,6 +54,13 @@ static struct map_desc marzen_io_desc[]
.length = SZ_16M,
.type = MT_DEVICE_NONSHARED
},
+ /* 16M debug map between 0xfdxxxxxx and 0xffxxxxxx */
+ {
+ .virtual = 0xfd000000,
+ .pfn = __phys_to_pfn(0xff000000),
+ .length = SZ_16M,
+ .type = MT_DEVICE_NONSHARED
+ },
};
static void __init marzen_map_io(void)
@@ -80,6 +87,7 @@ static void __init marzen_init_early(voi
* As a final step pass earlyprint=sh-sci.2,115200 on the kernel
* command line.
*/
+ shmobile_setup_console();
}
static void __init marzen_init(void)
--- 0008/arch/arm/mach-shmobile/setup-r8a7779.c
+++ work/arch/arm/mach-shmobile/setup-r8a7779.c 2011-12-06 23:56:32.000000000 +0900
@@ -70,8 +70,8 @@ static struct platform_device scif1_devi
};
static struct plat_sci_port scif2_platform_data = {
- .mapbase = 0xffe42000,
- .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP,
+ .mapbase = 0xfde42000,
+ .flags = UPF_BOOT_AUTOCONF,
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
^ permalink raw reply
* [PATCH 03/07] ARM: mach-shmobile: r8a7779 and Marzen base support
From: Magnus Damm @ 2011-12-06 16:52 UTC (permalink / raw)
To: linux-sh
From: Magnus Damm <damm@opensource.se>
Initial prototype support for the r8a7779 SoC and the Marzen board.
Only SCIF ports and the TMU are supported at this point.
To keep things simple only entity-mapped virt-to-phys mappings
are supported. This forces drivers and other SoC glue code to
make use of ioremap(). We cannot support early serial console
due to virtual address space collisions with the ARM kernel.
Not-yet-signed-off-by: Magnus Damm <damm@opensource.se>
---
arch/arm/mach-shmobile/Kconfig | 10 +
arch/arm/mach-shmobile/Makefile | 3
arch/arm/mach-shmobile/board-marzen.c | 110 +++++++++++
arch/arm/mach-shmobile/clock-r8a7779.c | 105 +++++++++++
arch/arm/mach-shmobile/include/mach/common.h | 5
arch/arm/mach-shmobile/include/mach/r8a7779.h | 6
arch/arm/mach-shmobile/intc-r8a7779.c | 58 ++++++
arch/arm/mach-shmobile/setup-r8a7779.c | 231 +++++++++++++++++++++++++
8 files changed, 528 insertions(+)
--- 0001/arch/arm/mach-shmobile/Kconfig
+++ work/arch/arm/mach-shmobile/Kconfig 2011-12-07 00:36:10.000000000 +0900
@@ -28,6 +28,12 @@ config ARCH_SH73A0
select ARM_GIC
select I2C
+config ARCH_R8A7779
+ bool "R-Car H1 (R8A77790)"
+ select CPU_V7
+ select SH_CLK_CPG
+ select ARM_GIC
+
comment "SH-Mobile Board Type"
config MACH_G3EVM
@@ -75,6 +81,10 @@ config MACH_KOTA2
select ARCH_REQUIRE_GPIOLIB
depends on ARCH_SH73A0
+config MACH_MARZEN
+ bool "MARZEN board"
+ depends on ARCH_R8A7779
+
comment "SH-Mobile System Configuration"
menu "Memory configuration"
--- 0001/arch/arm/mach-shmobile/Makefile
+++ work/arch/arm/mach-shmobile/Makefile 2011-12-07 00:37:58.000000000 +0900
@@ -10,6 +10,7 @@ obj-$(CONFIG_ARCH_SH7367) += setup-sh736
obj-$(CONFIG_ARCH_SH7377) += setup-sh7377.o clock-sh7377.o intc-sh7377.o
obj-$(CONFIG_ARCH_SH7372) += setup-sh7372.o clock-sh7372.o intc-sh7372.o
obj-$(CONFIG_ARCH_SH73A0) += setup-sh73a0.o clock-sh73a0.o intc-sh73a0.o
+obj-$(CONFIG_ARCH_R8A7779) += setup-r8a7779.o clock-r8a7779.o
# SMP objects
smp-y := platsmp.o headsmp.o
@@ -29,6 +30,7 @@ obj-$(CONFIG_ARCH_SH7367) += entry-intc.
obj-$(CONFIG_ARCH_SH7377) += entry-intc.o
obj-$(CONFIG_ARCH_SH7372) += entry-intc.o
obj-$(CONFIG_ARCH_SH73A0) += entry-gic.o
+obj-$(CONFIG_ARCH_R8A7779) += entry-gic.o intc-r8a7779.o
# PM objects
obj-$(CONFIG_SUSPEND) += suspend.o
@@ -42,6 +44,7 @@ obj-$(CONFIG_MACH_AP4EVB) += board-ap4ev
obj-$(CONFIG_MACH_AG5EVM) += board-ag5evm.o
obj-$(CONFIG_MACH_MACKEREL) += board-mackerel.o
obj-$(CONFIG_MACH_KOTA2) += board-kota2.o
+obj-$(CONFIG_MACH_MARZEN) += board-marzen.o
# Framework support
obj-$(CONFIG_SMP) += $(smp-y)
--- /dev/null
+++ work/arch/arm/mach-shmobile/board-marzen.c 2011-12-07 00:36:11.000000000 +0900
@@ -0,0 +1,110 @@
+/*
+ * marzen board support
+ *
+ * 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/interrupt.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+#include <mach/hardware.h>
+#include <mach/r8a7779.h>
+#include <mach/common.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/time.h>
+#include <asm/hardware/gic.h>
+#include <asm/traps.h>
+
+static struct platform_device *marzen_devices[] __initdata = {
+};
+
+static struct map_desc marzen_io_desc[] __initdata = {
+ /* 2M entity map for 0xf0000000 (MPCORE) */
+ {
+ .virtual = 0xf0000000,
+ .pfn = __phys_to_pfn(0xf0000000),
+ .length = SZ_2M,
+ .type = MT_DEVICE_NONSHARED
+ },
+ /* 16M entity map for 0xfexxxxxx (DMAC-S/HPBREG/INTC2/LRAM/DBSC) */
+ {
+ .virtual = 0xfe000000,
+ .pfn = __phys_to_pfn(0xfe000000),
+ .length = SZ_16M,
+ .type = MT_DEVICE_NONSHARED
+ },
+};
+
+static void __init marzen_map_io(void)
+{
+ iotable_init(marzen_io_desc, ARRAY_SIZE(marzen_io_desc));
+}
+
+static void __init marzen_init_early(void)
+{
+ r8a7779_add_early_devices();
+
+ /* Early serial console setup is not included here due to
+ * memory map collisions. The SCIF serial ports in r8a7779
+ * are difficult to entity map 1:1 due to collision with the
+ * virtual memory range used by the coherent DMA code on ARM.
+ *
+ * Anyone wanting to debug early can remove UPF_IOREMAP from
+ * the sh-sci serial console platform data, adjust mapbase
+ * to a static M:N virt:phys mapping that needs to be added to
+ * the mappings passed with iotable_init() above.
+ *
+ * Then add a call to shmobile_setup_console() from this function.
+ *
+ * As a final step pass earlyprint=sh-sci.2,115200 on the kernel
+ * command line.
+ */
+}
+
+static void __init marzen_init(void)
+{
+ r8a7779_add_standard_devices();
+ platform_add_devices(marzen_devices, ARRAY_SIZE(marzen_devices));
+}
+
+static void __init marzen_timer_init(void)
+{
+ r8a7779_clock_init();
+ shmobile_timer.init();
+ return;
+}
+
+struct sys_timer marzen_timer = {
+ .init = marzen_timer_init,
+};
+
+MACHINE_START(MARZEN, "marzen")
+ .map_io = marzen_map_io,
+ .init_early = marzen_init_early,
+ .nr_irqs = NR_IRQS_LEGACY,
+ .init_irq = r8a7779_init_irq,
+ .handle_irq = shmobile_handle_irq_gic,
+ .init_machine = marzen_init,
+ .timer = &marzen_timer,
+MACHINE_END
--- /dev/null
+++ work/arch/arm/mach-shmobile/clock-r8a7779.c 2011-12-07 00:36:11.000000000 +0900
@@ -0,0 +1,105 @@
+/*
+ * r8a7779 clock framework support
+ *
+ * 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; either 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/sh_clk.h>
+#include <linux/clkdev.h>
+#include <mach/common.h>
+
+#define FRQMR 0xffc80014
+#define MSTPCR0 0xffc80030
+#define MSTPCR1 0xffc80034
+#define MSTPCR3 0xffc8003c
+#define MSTPSR1 0xffc80044
+#define MSTPSR4 0xffc80048
+#define MSTPSR6 0xffc8004c
+#define MSTPCR4 0xffc80050
+#define MSTPCR5 0xffc80054
+#define MSTPCR6 0xffc80058
+#define MSTPCR7 0xffc80040
+
+/* ioremap() through clock mapping mandatory to avoid
+ * collision with ARM coherent DMA virtual memory range.
+ */
+
+static struct clk_mapping cpg_mapping = {
+ .phys = 0xffc80000,
+ .len = 0x80,
+};
+
+static struct clk clkp = {
+ .rate = 62500000, /* FIXME: shortcut */
+ .flags = CLK_ENABLE_ON_INIT,
+ .mapping = &cpg_mapping,
+};
+
+static struct clk *main_clks[] = {
+ &clkp,
+};
+
+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 */
+};
+
+static struct clk_lookup lookups[] = {
+ /* MSTP32 clocks */
+ CLKDEV_DEV_ID("sh_tmu.0", &mstp_clks[MSTP016]), /* TMU00 */
+ CLKDEV_DEV_ID("sh_tmu.1", &mstp_clks[MSTP016]), /* TMU01 */
+ CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP026]), /* SCIF0 */
+ CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP025]), /* SCIF1 */
+ CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP024]), /* SCIF2 */
+ CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP023]), /* SCIF3 */
+ CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP022]), /* SCIF4 */
+ CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP021]), /* SCIF6 */
+};
+
+void __init r8a7779_clock_init(void)
+{
+ int k, ret = 0;
+
+ for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
+ ret = clk_register(main_clks[k]);
+
+ if (!ret)
+ ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
+
+ clkdev_add_table(lookups, ARRAY_SIZE(lookups));
+
+ if (!ret)
+ clk_init();
+ else
+ panic("failed to setup r8a7779 clocks\n");
+}
--- 0001/arch/arm/mach-shmobile/include/mach/common.h
+++ work/arch/arm/mach-shmobile/include/mach/common.h 2011-12-07 00:36:10.000000000 +0900
@@ -53,4 +53,9 @@ extern void sh73a0_secondary_init(unsign
extern int sh73a0_boot_secondary(unsigned int cpu);
extern void sh73a0_smp_prepare_cpus(void);
+extern void r8a7779_init_irq(void);
+extern void r8a7779_add_early_devices(void);
+extern void r8a7779_add_standard_devices(void);
+extern void r8a7779_clock_init(void);
+
#endif /* __ARCH_MACH_COMMON_H */
--- /dev/null
+++ work/arch/arm/mach-shmobile/include/mach/r8a7779.h 2011-12-07 00:36:11.000000000 +0900
@@ -0,0 +1,6 @@
+#ifndef __ASM_R8A7779_H__
+#define __ASM_R8A7779_H__
+
+/* Nothing at this point */
+
+#endif /* __ASM_R8A7779_H__ */
--- /dev/null
+++ work/arch/arm/mach-shmobile/intc-r8a7779.c 2011-12-07 00:36:11.000000000 +0900
@@ -0,0 +1,58 @@
+/*
+ * r8a7779 processor support - INTC hardware block
+ *
+ * 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/interrupt.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <mach/common.h>
+#include <mach/intc.h>
+#include <mach/r8a7779.h>
+#include <asm/hardware/gic.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#define INT2SMSKCR0 0xfe7822a0
+#define INT2SMSKCR1 0xfe7822a4
+#define INT2SMSKCR2 0xfe7822a8
+#define INT2SMSKCR3 0xfe7822ac
+#define INT2SMSKCR4 0xfe7822b0
+
+static int r8a7779_set_wake(struct irq_data *data, unsigned int on)
+{
+ return 0; /* always allow wakeup */
+}
+
+void __init r8a7779_init_irq(void)
+{
+ void __iomem *gic_dist_base = __io(0xf0001000);
+ void __iomem *gic_cpu_base = __io(0xf0000100);
+
+ /* use GIC to handle interrupts */
+ gic_init(0, 29, gic_dist_base, gic_cpu_base);
+ gic_arch_extn.irq_set_wake = r8a7779_set_wake;
+
+ /* unmask all known interrupts in INTCS2 */
+ __raw_writel(0xfffffff0, INT2SMSKCR0);
+ __raw_writel(0xfff7ffff, INT2SMSKCR1);
+ __raw_writel(0xfffbffdf, INT2SMSKCR2);
+ __raw_writel(0xbffffffc, INT2SMSKCR3);
+ __raw_writel(0x003fee3f, INT2SMSKCR4);
+}
--- /dev/null
+++ work/arch/arm/mach-shmobile/setup-r8a7779.c 2011-12-07 00:36:11.000000000 +0900
@@ -0,0 +1,231 @@
+/*
+ * r8a7779 processor support
+ *
+ * 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/interrupt.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/input.h>
+#include <linux/io.h>
+#include <linux/serial_sci.h>
+#include <linux/sh_intc.h>
+#include <linux/sh_timer.h>
+#include <mach/hardware.h>
+#include <mach/r8a7779.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+static struct plat_sci_port scif0_platform_data = {
+ .mapbase = 0xffe40000,
+ .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
+ .scbrr_algo_id = SCBRR_ALGO_2,
+ .type = PORT_SCIF,
+ .irqs = { gic_spi(88), gic_spi(88),
+ gic_spi(88), gic_spi(88) },
+};
+
+static struct platform_device scif0_device = {
+ .name = "sh-sci",
+ .id = 0,
+ .dev = {
+ .platform_data = &scif0_platform_data,
+ },
+};
+
+static struct plat_sci_port scif1_platform_data = {
+ .mapbase = 0xffe41000,
+ .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
+ .scbrr_algo_id = SCBRR_ALGO_2,
+ .type = PORT_SCIF,
+ .irqs = { gic_spi(89), gic_spi(89),
+ gic_spi(89), gic_spi(89) },
+};
+
+static struct platform_device scif1_device = {
+ .name = "sh-sci",
+ .id = 1,
+ .dev = {
+ .platform_data = &scif1_platform_data,
+ },
+};
+
+static struct plat_sci_port scif2_platform_data = {
+ .mapbase = 0xffe42000,
+ .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
+ .scbrr_algo_id = SCBRR_ALGO_2,
+ .type = PORT_SCIF,
+ .irqs = { gic_spi(90), gic_spi(90),
+ gic_spi(90), gic_spi(90) },
+};
+
+static struct platform_device scif2_device = {
+ .name = "sh-sci",
+ .id = 2,
+ .dev = {
+ .platform_data = &scif2_platform_data,
+ },
+};
+
+static struct plat_sci_port scif3_platform_data = {
+ .mapbase = 0xffe43000,
+ .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
+ .scbrr_algo_id = SCBRR_ALGO_2,
+ .type = PORT_SCIF,
+ .irqs = { gic_spi(91), gic_spi(91),
+ gic_spi(91), gic_spi(91) },
+};
+
+static struct platform_device scif3_device = {
+ .name = "sh-sci",
+ .id = 3,
+ .dev = {
+ .platform_data = &scif3_platform_data,
+ },
+};
+
+static struct plat_sci_port scif4_platform_data = {
+ .mapbase = 0xffe44000,
+ .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
+ .scbrr_algo_id = SCBRR_ALGO_2,
+ .type = PORT_SCIF,
+ .irqs = { gic_spi(92), gic_spi(92),
+ gic_spi(92), gic_spi(92) },
+};
+
+static struct platform_device scif4_device = {
+ .name = "sh-sci",
+ .id = 4,
+ .dev = {
+ .platform_data = &scif4_platform_data,
+ },
+};
+
+static struct plat_sci_port scif5_platform_data = {
+ .mapbase = 0xffe45000,
+ .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
+ .scbrr_algo_id = SCBRR_ALGO_2,
+ .type = PORT_SCIF,
+ .irqs = { gic_spi(93), gic_spi(93),
+ gic_spi(93), gic_spi(93) },
+};
+
+static struct platform_device scif5_device = {
+ .name = "sh-sci",
+ .id = 5,
+ .dev = {
+ .platform_data = &scif5_platform_data,
+ },
+};
+
+/* TMU */
+static struct sh_timer_config tmu00_platform_data = {
+ .name = "TMU00",
+ .channel_offset = 0x4,
+ .timer_bit = 0,
+ .clockevent_rating = 200,
+};
+
+static struct resource tmu00_resources[] = {
+ [0] = {
+ .name = "TMU00",
+ .start = 0xffd80008,
+ .end = 0xffd80013,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = gic_spi(32),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu00_device = {
+ .name = "sh_tmu",
+ .id = 0,
+ .dev = {
+ .platform_data = &tmu00_platform_data,
+ },
+ .resource = tmu00_resources,
+ .num_resources = ARRAY_SIZE(tmu00_resources),
+};
+
+static struct sh_timer_config tmu01_platform_data = {
+ .name = "TMU01",
+ .channel_offset = 0x10,
+ .timer_bit = 1,
+ .clocksource_rating = 200,
+};
+
+static struct resource tmu01_resources[] = {
+ [0] = {
+ .name = "TMU01",
+ .start = 0xffd80014,
+ .end = 0xffd8001f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = gic_spi(33),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu01_device = {
+ .name = "sh_tmu",
+ .id = 1,
+ .dev = {
+ .platform_data = &tmu01_platform_data,
+ },
+ .resource = tmu01_resources,
+ .num_resources = ARRAY_SIZE(tmu01_resources),
+};
+
+static struct platform_device *r8a7779_early_devices[] __initdata = {
+ &scif0_device,
+ &scif1_device,
+ &scif2_device,
+ &scif3_device,
+ &scif4_device,
+ &scif5_device,
+ &tmu00_device,
+ &tmu01_device,
+};
+
+static struct platform_device *r8a7779_late_devices[] __initdata = {
+};
+
+void __init r8a7779_add_standard_devices(void)
+{
+ platform_add_devices(r8a7779_early_devices,
+ ARRAY_SIZE(r8a7779_early_devices));
+ platform_add_devices(r8a7779_late_devices,
+ ARRAY_SIZE(r8a7779_late_devices));
+}
+
+void __init r8a7779_add_early_devices(void)
+{
+ early_platform_add_devices(r8a7779_early_devices,
+ ARRAY_SIZE(r8a7779_early_devices));
+}
^ permalink raw reply
* [PATCH 02/07] sh: CPG MSTP ioremap() prototype hack
From: Magnus Damm @ 2011-12-06 16:52 UTC (permalink / raw)
To: linux-sh
From: Magnus Damm <damm@opensource.se>
Hack to use the cookie returned from ioremap(). Will be rewritten
and submitted separately in the near future. Needed by the r8a7779
clock code since entity mapping is out of the question.
Not-yet-signed-off-by: Magnus Damm <damm@opensource.se>
---
drivers/sh/clk/cpg.c | 4 ++++
1 file changed, 4 insertions(+)
--- 0001/drivers/sh/clk/cpg.c
+++ work/drivers/sh/clk/cpg.c 2011-12-07 00:32:11.000000000 +0900
@@ -42,6 +42,10 @@ int __init sh_clk_mstp32_register(struct
clkp = clks + k;
clkp->ops = &sh_clk_mstp32_clk_ops;
ret |= clk_register(clkp);
+ if (!ret && clkp->mapping->base) {
+ clkp->enable_reg -= clkp->mapping->phys;
+ clkp->enable_reg += (unsigned long)clkp->mapping->base;
+ }
}
return ret;
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox